From c38dead3ea7e177728d90cd815cf4eead0c9f534 Mon Sep 17 00:00:00 2001 From: marha Date: Sat, 15 May 2010 16:28:11 +0000 Subject: xserver git update 15/5/2010 --- xorg-server/hw/xfree86/common/xf86.h | 708 +-- xorg-server/hw/xfree86/common/xf86AutoConfig.c | 1276 ++-- xorg-server/hw/xfree86/common/xf86Bus.c | 1366 ++--- xorg-server/hw/xfree86/common/xf86Config.c | 5172 ++++++++-------- xorg-server/hw/xfree86/common/xf86Configure.c | 1784 +++--- xorg-server/hw/xfree86/common/xf86Cursor.c | 1724 +++--- xorg-server/hw/xfree86/common/xf86DGA.c | 2454 ++++---- xorg-server/hw/xfree86/common/xf86DPMS.c | 400 +- xorg-server/hw/xfree86/common/xf86Events.c | 4 +- xorg-server/hw/xfree86/common/xf86Helper.c | 5176 ++++++++-------- xorg-server/hw/xfree86/common/xf86Init.c | 3644 +++++------ xorg-server/hw/xfree86/common/xf86Mode.c | 4134 ++++++------- xorg-server/hw/xfree86/common/xf86Option.c | 1724 +++--- xorg-server/hw/xfree86/common/xf86Privstr.h | 343 +- xorg-server/hw/xfree86/common/xf86RandR.c | 918 +-- xorg-server/hw/xfree86/common/xf86ShowOpts.c | 256 +- xorg-server/hw/xfree86/common/xf86VGAarbiter.c | 2202 +++---- xorg-server/hw/xfree86/common/xf86VidMode.c | 1334 ++-- xorg-server/hw/xfree86/common/xf86Xinput.c | 2568 ++++---- xorg-server/hw/xfree86/common/xf86cmap.c | 2332 +++---- xorg-server/hw/xfree86/common/xf86fbman.c | 2876 ++++----- xorg-server/hw/xfree86/common/xf86pciBus.c | 846 +-- xorg-server/hw/xfree86/common/xf86sbusBus.c | 1376 ++--- xorg-server/hw/xfree86/common/xf86xv.c | 4203 ++++++------- xorg-server/hw/xfree86/common/xf86xvmc.c | 458 +- xorg-server/hw/xfree86/common/xisb.c | 348 +- xorg-server/hw/xfree86/ddc/ddc.c | 1014 ++-- xorg-server/hw/xfree86/ddc/ddcProperty.c | 250 +- xorg-server/hw/xfree86/ddc/interpret_edid.c | 1370 ++--- xorg-server/hw/xfree86/dixmods/extmod/modinit.c | 374 +- xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c | 2120 ++++--- xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c | 4340 ++++++------- xorg-server/hw/xfree86/dri/dri.c | 5008 +++++++-------- xorg-server/hw/xfree86/dri/xf86dri.c | 1358 ++--- xorg-server/hw/xfree86/dri2/dri2.c | 165 +- xorg-server/hw/xfree86/dri2/dri2.h | 9 +- xorg-server/hw/xfree86/dri2/dri2ext.c | 64 +- xorg-server/hw/xfree86/exa/examodule.c | 396 +- xorg-server/hw/xfree86/fbdevhw/fbdevhw.c | 2018 +++--- xorg-server/hw/xfree86/i2c/bt829.c | 1490 ++--- xorg-server/hw/xfree86/i2c/fi1236.c | 1210 ++-- xorg-server/hw/xfree86/i2c/msp3430.c | 1452 ++--- xorg-server/hw/xfree86/i2c/tda8425.c | 156 +- xorg-server/hw/xfree86/i2c/tda9850.c | 224 +- xorg-server/hw/xfree86/i2c/tda9885.c | 208 +- xorg-server/hw/xfree86/i2c/uda1380.c | 366 +- xorg-server/hw/xfree86/i2c/xf86i2c.c | 1732 +++--- xorg-server/hw/xfree86/int10/generic.c | 988 +-- xorg-server/hw/xfree86/int10/helper_exec.c | 1454 ++--- xorg-server/hw/xfree86/int10/helper_mem.c | 660 +- xorg-server/hw/xfree86/loader/loadext.c | 884 +-- xorg-server/hw/xfree86/loader/loadmod.c | 2536 ++++---- xorg-server/hw/xfree86/modes/xf86Crtc.c | 6402 ++++++++++---------- xorg-server/hw/xfree86/modes/xf86Cursors.c | 4 +- xorg-server/hw/xfree86/modes/xf86DiDGA.c | 436 +- xorg-server/hw/xfree86/modes/xf86DisplayIDModes.c | 874 +-- xorg-server/hw/xfree86/modes/xf86EdidModes.c | 2430 ++++---- xorg-server/hw/xfree86/modes/xf86Modes.c | 1454 ++--- xorg-server/hw/xfree86/modes/xf86RandR12.c | 3620 +++++------ xorg-server/hw/xfree86/modes/xf86Rotate.c | 1054 ++-- xorg-server/hw/xfree86/os-support/bsd/i386_video.c | 1816 +++--- xorg-server/hw/xfree86/os-support/bus/Sbus.c | 1380 ++--- .../hw/xfree86/os-support/linux/int10/linux.c | 1088 ++-- xorg-server/hw/xfree86/os-support/linux/lnx_agp.c | 748 +-- .../hw/xfree86/os-support/linux/lnx_video.c | 1756 +++--- .../hw/xfree86/os-support/shared/posix_tty.c | 1310 ++-- xorg-server/hw/xfree86/os-support/shared/vidmem.c | 592 +- .../hw/xfree86/os-support/solaris/sun_agp.c | 654 +- xorg-server/hw/xfree86/ramdac/xf86Cursor.c | 958 +-- xorg-server/hw/xfree86/ramdac/xf86HWCurs.c | 1054 ++-- xorg-server/hw/xfree86/ramdac/xf86RamDac.c | 308 +- xorg-server/hw/xfree86/shadowfb/shadow.c | 3458 +++++------ xorg-server/hw/xfree86/vbe/vbe.c | 2290 +++---- xorg-server/hw/xfree86/vbe/vbe.h | 682 +-- xorg-server/hw/xfree86/vbe/vbeModes.c | 902 +-- xorg-server/hw/xfree86/vgahw/vgaCmap.c | 602 +- xorg-server/hw/xfree86/vgahw/vgaHW.c | 3990 ++++++------ xorg-server/hw/xfree86/xaa/xaaBitBlt.c | 442 +- xorg-server/hw/xfree86/xaa/xaaCpyArea.c | 774 +-- xorg-server/hw/xfree86/xaa/xaaCpyPlane.c | 416 +- xorg-server/hw/xfree86/xaa/xaaCpyWin.c | 164 +- xorg-server/hw/xfree86/xaa/xaaGC.c | 1312 ++-- xorg-server/hw/xfree86/xaa/xaaImage.c | 1042 ++-- xorg-server/hw/xfree86/xaa/xaaInit.c | 1248 ++-- xorg-server/hw/xfree86/xaa/xaaInitAccel.c | 2996 ++++----- xorg-server/hw/xfree86/xaa/xaaLineMisc.c | 302 +- xorg-server/hw/xfree86/xaa/xaaNonTEText.c | 1182 ++-- xorg-server/hw/xfree86/xaa/xaaOffscreen.c | 324 +- xorg-server/hw/xfree86/xaa/xaaOverlay.c | 258 +- xorg-server/hw/xfree86/xaa/xaaOverlayDF.c | 2100 +++---- xorg-server/hw/xfree86/xaa/xaaPCache.c | 4760 +++++++-------- xorg-server/hw/xfree86/xaa/xaaPict.c | 1310 ++-- xorg-server/hw/xfree86/xaa/xaaStateChange.c | 3252 +++++----- xorg-server/hw/xfree86/xaa/xaaTEGlyph.c | 2154 +++---- xorg-server/hw/xfree86/xaa/xaaTEText.c | 624 +- xorg-server/hw/xfree86/xaa/xaaWrapper.c | 948 +-- xorg-server/hw/xfree86/xaa/xaalocal.h | 3510 +++++------ 97 files changed, 75282 insertions(+), 75170 deletions(-) (limited to 'xorg-server/hw/xfree86') diff --git a/xorg-server/hw/xfree86/common/xf86.h b/xorg-server/hw/xfree86/common/xf86.h index e9266abd4..cddca37a3 100644 --- a/xorg-server/hw/xfree86/common/xf86.h +++ b/xorg-server/hw/xfree86/common/xf86.h @@ -1,354 +1,354 @@ -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * This file contains declarations for public XFree86 functions and variables, - * and definitions of public macros. - * - * "public" means available to video drivers. - */ - -#ifndef _XF86_H -#define _XF86_H - -#if HAVE_XORG_CONFIG_H -#include -#elif HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include "xf86str.h" -#include "xf86Opt.h" -#include -#include -#ifdef RANDR -#include -#endif - -#include "propertyst.h" - -/* General parameters */ -extern _X_EXPORT int xf86DoConfigure; -extern _X_EXPORT int xf86DoShowOptions; -extern _X_EXPORT Bool xf86DoConfigurePass1; -extern _X_EXPORT DevPrivateKey xf86ScreenKey; -extern _X_EXPORT DevPrivateKey xf86CreateRootWindowKey; -extern _X_EXPORT DevPrivateKey xf86PixmapKey; -extern _X_EXPORT ScrnInfoPtr *xf86Screens; /* List of pointers to ScrnInfoRecs */ -extern _X_EXPORT const unsigned char byte_reversed[256]; -extern _X_EXPORT Bool pciSlotClaimed; -extern _X_EXPORT Bool fbSlotClaimed; -#if defined(__sparc__) || defined(__sparc) -extern _X_EXPORT Bool sbusSlotClaimed; -#endif -extern _X_EXPORT confDRIRec xf86ConfigDRI; -extern _X_EXPORT Bool xf86inSuspend; -extern _X_EXPORT Bool xf86DRI2Enabled(void); - -extern _X_EXPORT Bool VTSwitchEnabled; /* kbd driver */ - -#define XF86SCRNINFO(p) ((ScrnInfoPtr)dixLookupPrivate(&(p)->devPrivates, \ - xf86ScreenKey)) -#define XF86FLIP_PIXELS() \ - do { \ - if (xf86GetFlipPixels()) { \ - pScreen->whitePixel = (pScreen->whitePixel) ? 0 : 1; \ - pScreen->blackPixel = (pScreen->blackPixel) ? 0 : 1; \ - } \ - while (0) - -#define BOOLTOSTRING(b) ((b) ? "TRUE" : "FALSE") - -#define PIX24TOBPP(p) (((p) == Pix24Use24) ? 24 : \ - (((p) == Pix24Use32) ? 32 : 0)) - -/* Function Prototypes */ -#ifndef _NO_XF86_PROTOTYPES - -/* xf86Bus.c */ - -extern _X_EXPORT Bool xf86CheckPciSlot( const struct pci_device * ); -extern _X_EXPORT int xf86ClaimPciSlot( struct pci_device *, DriverPtr drvp, - int chipset, GDevPtr dev, Bool active); -extern _X_EXPORT void xf86UnclaimPciSlot(struct pci_device *); -extern _X_EXPORT Bool xf86ParsePciBusString(const char *busID, int *bus, int *device, - int *func); -extern _X_EXPORT Bool xf86ComparePciBusString(const char *busID, int bus, int device, int func); -extern _X_EXPORT void xf86FormatPciBusNumber(int busnum, char *buffer); -extern _X_EXPORT int xf86GetFbInfoForScreen(int scrnIndex); -extern _X_EXPORT int xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active); -extern _X_EXPORT int xf86ClaimNoSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active); -extern _X_EXPORT void xf86EnableAccess(ScrnInfoPtr pScrn); -extern _X_EXPORT Bool xf86IsPrimaryPci(struct pci_device * pPci); -/* new RAC */ -extern _X_EXPORT Bool xf86DriverHasEntities(DriverPtr drvp); -extern _X_EXPORT void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex); -extern _X_EXPORT void xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, - int instance); -extern _X_EXPORT int xf86GetNumEntityInstances(int entityIndex); -extern _X_EXPORT GDevPtr xf86GetDevFromEntity(int entityIndex, int instance); -extern _X_EXPORT void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex); -extern _X_EXPORT EntityInfoPtr xf86GetEntityInfo(int entityIndex); -extern _X_EXPORT struct pci_device * xf86GetPciInfoForEntity(int entityIndex); -extern _X_EXPORT Bool xf86SetEntityFuncs(int entityIndex, EntityProc init, - EntityProc enter, EntityProc leave, pointer); -extern _X_EXPORT Bool xf86CheckPciMemBase(struct pci_device * pPci, memType base); -extern _X_EXPORT Bool xf86IsEntityPrimary(int entityIndex); -extern _X_EXPORT void xf86EnterServerState(xf86State state); -extern _X_EXPORT ScrnInfoPtr xf86FindScreenForEntity(int entityIndex); - -extern _X_EXPORT int xf86GetLastScrnFlag(int entityIndex); -extern _X_EXPORT void xf86SetLastScrnFlag(int entityIndex, int scrnIndex); -extern _X_EXPORT Bool xf86IsEntityShared(int entityIndex); -extern _X_EXPORT void xf86SetEntityShared(int entityIndex); -extern _X_EXPORT Bool xf86IsEntitySharable(int entityIndex); -extern _X_EXPORT void xf86SetEntitySharable(int entityIndex); -extern _X_EXPORT Bool xf86IsPrimInitDone(int entityIndex); -extern _X_EXPORT void xf86SetPrimInitDone(int entityIndex); -extern _X_EXPORT void xf86ClearPrimInitDone(int entityIndex); -extern _X_EXPORT int xf86AllocateEntityPrivateIndex(void); -extern _X_EXPORT DevUnion *xf86GetEntityPrivate(int entityIndex, int privIndex); - -/* xf86Configure.c */ -extern _X_EXPORT GDevPtr xf86AddBusDeviceToConfigure(const char *driver, BusType bus, - void *busData, int chipset); - -/* xf86Cursor.c */ - -extern _X_EXPORT void xf86LockZoom(ScreenPtr pScreen, int lock); -extern _X_EXPORT void xf86InitViewport(ScrnInfoPtr pScr); -extern _X_EXPORT void xf86SetViewport(ScreenPtr pScreen, int x, int y); -extern _X_EXPORT void xf86ZoomViewport(ScreenPtr pScreen, int zoom); -extern _X_EXPORT Bool xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode); -extern _X_EXPORT void *xf86GetPointerScreenFuncs(void); -extern _X_EXPORT void xf86InitOrigins(void); -extern _X_EXPORT void xf86ReconfigureLayout(void); - -/* xf86cvt.c */ -extern _X_EXPORT DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, - Bool Reduced, Bool Interlaced); - -/* xf86DPMS.c */ - -extern _X_EXPORT Bool xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags); - -#ifdef DPMSExtension -extern _X_EXPORT int DPMSSet(ClientPtr client, int level); -extern _X_EXPORT Bool DPMSSupported(void); -#endif - - -/* xf86DGA.c */ - -#ifdef XFreeXDGA -extern _X_EXPORT Bool DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs, DGAModePtr modes, - int num); -extern _X_EXPORT Bool DGAReInitModes(ScreenPtr pScreen, DGAModePtr modes, int num); -extern _X_EXPORT xf86SetDGAModeProc xf86SetDGAMode; -#endif - -/* xf86Events.c */ - -extern _X_EXPORT void SetTimeSinceLastInputEvent(void); -extern _X_EXPORT pointer xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data); -extern _X_EXPORT int xf86RemoveInputHandler(pointer handler); -extern _X_EXPORT void xf86DisableInputHandler(pointer handler); -extern _X_EXPORT void xf86EnableInputHandler(pointer handler); -extern _X_EXPORT pointer xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data); -extern _X_EXPORT int xf86RemoveGeneralHandler(pointer handler); -extern _X_EXPORT void xf86DisableGeneralHandler(pointer handler); -extern _X_EXPORT void xf86EnableGeneralHandler(pointer handler); -extern _X_EXPORT void xf86InterceptSignals(int *signo); -extern _X_EXPORT void xf86InterceptSigIll(void (*sigillhandler)(void)); -extern _X_EXPORT Bool xf86EnableVTSwitch(Bool new); -extern _X_EXPORT void xf86ProcessActionEvent(ActionEvent action, void *arg); -extern _X_EXPORT void xf86PrintBacktrace(void); - -/* xf86Helper.c */ - -extern _X_EXPORT void xf86AddDriver(DriverPtr driver, pointer module, int flags); -extern _X_EXPORT void xf86DeleteDriver(int drvIndex); -extern _X_EXPORT ScrnInfoPtr xf86AllocateScreen(DriverPtr drv, int flags); -extern _X_EXPORT void xf86DeleteScreen(int scrnIndex, int flags); -extern _X_EXPORT int xf86AllocateScrnInfoPrivateIndex(void); -extern _X_EXPORT Bool xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad); -extern _X_EXPORT Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp, int fbbpp, - int depth24flags); -extern _X_EXPORT void xf86PrintDepthBpp(ScrnInfoPtr scrp); -extern _X_EXPORT Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask); -extern _X_EXPORT Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual); -extern _X_EXPORT Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma newGamma); -extern _X_EXPORT void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y); -extern _X_EXPORT void xf86SetBlackWhitePixels(ScreenPtr pScreen); -extern _X_EXPORT void xf86EnableDisableFBAccess(int scrnIndex, Bool enable); -extern _X_EXPORT void xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, - const char *format, va_list args); -extern _X_EXPORT void xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, - const char *format, ...) _printf_attribute(4,5); -extern _X_EXPORT void xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...) - _printf_attribute(3,4); -extern _X_EXPORT void xf86MsgVerb(MessageType type, int verb, const char *format, ...) - _printf_attribute(3,4); -extern _X_EXPORT void xf86Msg(MessageType type, const char *format, ...) _printf_attribute(2,3); -extern _X_EXPORT void xf86ErrorFVerb(int verb, const char *format, ...) _printf_attribute(2,3); -extern _X_EXPORT void xf86ErrorF(const char *format, ...) _printf_attribute(1,2); -extern _X_EXPORT const char *xf86TokenToString(SymTabPtr table, int token); -extern _X_EXPORT int xf86StringToToken(SymTabPtr table, const char *string); -extern _X_EXPORT void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from); -extern _X_EXPORT void xf86PrintChipsets(const char *drvname, const char *drvmsg, - SymTabPtr chips); -extern _X_EXPORT int xf86MatchDevice(const char *drivername, GDevPtr **driversectlist); -extern _X_EXPORT int xf86MatchPciInstances(const char *driverName, int vendorID, - SymTabPtr chipsets, PciChipsets *PCIchipsets, - GDevPtr *devList, int numDevs, DriverPtr drvp, - int **foundEntities); -extern _X_EXPORT void xf86GetClocks(ScrnInfoPtr pScrn, int num, - Bool (*ClockFunc)(ScrnInfoPtr, int), - void (*ProtectRegs)(ScrnInfoPtr, Bool), - void (*BlankScreen)(ScrnInfoPtr, Bool), - IOADDRESS vertsyncreg, int maskval, - int knownclkindex, int knownclkvalue); -extern _X_EXPORT const char *xf86GetVisualName(int visual); -extern _X_EXPORT int xf86GetVerbosity(void); -extern _X_EXPORT Pix24Flags xf86GetPix24(void); -extern _X_EXPORT int xf86GetDepth(void); -extern _X_EXPORT rgb xf86GetWeight(void); -extern _X_EXPORT Gamma xf86GetGamma(void); -extern _X_EXPORT Bool xf86GetFlipPixels(void); -extern _X_EXPORT const char *xf86GetServerName(void); -extern _X_EXPORT Bool xf86ServerIsExiting(void); -extern _X_EXPORT Bool xf86ServerIsResetting(void); -extern _X_EXPORT Bool xf86ServerIsInitialising(void); -extern _X_EXPORT Bool xf86ServerIsOnlyDetecting(void); -extern _X_EXPORT Bool xf86CaughtSignal(void); -extern _X_EXPORT Bool xf86GetVidModeAllowNonLocal(void); -extern _X_EXPORT Bool xf86GetVidModeEnabled(void); -extern _X_EXPORT Bool xf86GetModInDevAllowNonLocal(void); -extern _X_EXPORT Bool xf86GetModInDevEnabled(void); -extern _X_EXPORT Bool xf86GetAllowMouseOpenFail(void); -extern _X_EXPORT Bool xf86IsPc98(void); -extern _X_EXPORT void xf86DisableRandR(void); -extern _X_EXPORT CARD32 xorgGetVersion(void); -extern _X_EXPORT CARD32 xf86GetModuleVersion(pointer module); -extern _X_EXPORT pointer xf86LoadDrvSubModule(DriverPtr drv, const char *name); -extern _X_EXPORT pointer xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name); -extern _X_EXPORT pointer xf86LoadOneModule(char *name, pointer optlist); -extern _X_EXPORT void xf86UnloadSubModule(pointer mod); -extern _X_EXPORT Bool xf86LoaderCheckSymbol(const char *name); -extern _X_EXPORT void xf86SetBackingStore(ScreenPtr pScreen); -extern _X_EXPORT void xf86SetSilkenMouse(ScreenPtr pScreen); -extern _X_EXPORT pointer xf86FindXvOptions(int scrnIndex, int adapt_index, char *port_name, - char **adaptor_name, pointer *adaptor_options); -extern _X_EXPORT void xf86GetOS(const char **name, int *major, int *minor, int *teeny); -extern _X_EXPORT ScrnInfoPtr xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, - int entityIndex,PciChipsets *p_chip, - void *dummy, EntityProc init, - EntityProc enter, EntityProc leave, - pointer private); -extern _X_EXPORT ScrnInfoPtr xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, - int entityIndex, EntityProc init, - EntityProc enter, EntityProc leave, - pointer private); - -/* Obsolete! don't use */ -extern _X_EXPORT Bool xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, - int entityIndex,PciChipsets *p_chip, - void *dummy, EntityProc init, - EntityProc enter, EntityProc leave, - pointer private); - -extern _X_EXPORT Bool xf86IsScreenPrimary(int scrnIndex); -extern _X_EXPORT int xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type, - int format, unsigned long len, - pointer value); -extern _X_EXPORT Bool xf86IsUnblank(int mode); - -/* xf86Init.c */ - -extern _X_EXPORT PixmapFormatPtr xf86GetPixFormat(ScrnInfoPtr pScrn, int depth); -extern _X_EXPORT int xf86GetBppFromDepth(ScrnInfoPtr pScrn, int depth); - -/* xf86Mode.c */ - -extern _X_EXPORT int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, - int DivFactor, int MulFactor, int *divider); -extern _X_EXPORT const char *xf86ModeStatusToString(ModeStatus status); -extern _X_EXPORT ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, - ClockRangePtr clockRanges, LookupModeFlags strategy); -extern _X_EXPORT ModeStatus xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor); -extern _X_EXPORT ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, - ClockRangePtr clockRanges, - LookupModeFlags strategy, - int maxPitch, int virtualX, - int virtualY); -extern _X_EXPORT ModeStatus xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, - int flags); -extern _X_EXPORT int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, - char **modeNames, ClockRangePtr clockRanges, - int *linePitches, int minPitch, int maxPitch, - int minHeight, int maxHeight, int pitchInc, - int virtualX, int virtualY, int apertureSize, - LookupModeFlags strategy); -extern _X_EXPORT void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode); -extern _X_EXPORT void xf86PruneDriverModes(ScrnInfoPtr scrp); -extern _X_EXPORT void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags); -extern _X_EXPORT void xf86PrintModes(ScrnInfoPtr scrp); -extern _X_EXPORT void xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges); -extern _X_EXPORT double xf86ModeHSync(const DisplayModeRec *mode); -extern _X_EXPORT double xf86ModeVRefresh(const DisplayModeRec *mode); -extern _X_EXPORT void xf86SetModeDefaultName(DisplayModePtr mode); -extern _X_EXPORT void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); -extern _X_EXPORT DisplayModePtr xf86DuplicateMode(const DisplayModeRec *pMode); -extern _X_EXPORT DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList); -extern _X_EXPORT Bool xf86ModesEqual(const DisplayModeRec *pMode1, - const DisplayModeRec *pMode2); -extern _X_EXPORT void xf86PrintModeline(int scrnIndex,DisplayModePtr mode); -extern _X_EXPORT DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); - -/* xf86Option.c */ - -extern _X_EXPORT void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts); - - -/* xf86RandR.c */ -#ifdef RANDR -extern _X_EXPORT Bool xf86RandRInit (ScreenPtr pScreen); -extern _X_EXPORT Rotation xf86GetRotation(ScreenPtr pScreen); -extern _X_EXPORT Bool xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen, - int newvirtX, int newvirtY, - int newmmWidth, int newmmHeight, Bool resetMode); -#endif - -/* xf86VidModeExtentionInit.c */ - -extern _X_EXPORT Bool VidModeExtensionInit(ScreenPtr pScreen); - -#endif /* _NO_XF86_PROTOTYPES */ - -#endif /* _XF86_H */ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * This file contains declarations for public XFree86 functions and variables, + * and definitions of public macros. + * + * "public" means available to video drivers. + */ + +#ifndef _XF86_H +#define _XF86_H + +#if HAVE_XORG_CONFIG_H +#include +#elif HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "xf86str.h" +#include "xf86Opt.h" +#include +#include +#ifdef RANDR +#include +#endif + +#include "propertyst.h" + +/* General parameters */ +extern _X_EXPORT int xf86DoConfigure; +extern _X_EXPORT int xf86DoShowOptions; +extern _X_EXPORT Bool xf86DoConfigurePass1; +extern _X_EXPORT DevPrivateKey xf86ScreenKey; +extern _X_EXPORT DevPrivateKey xf86CreateRootWindowKey; +extern _X_EXPORT DevPrivateKey xf86PixmapKey; +extern _X_EXPORT ScrnInfoPtr *xf86Screens; /* List of pointers to ScrnInfoRecs */ +extern _X_EXPORT const unsigned char byte_reversed[256]; +extern _X_EXPORT Bool pciSlotClaimed; +extern _X_EXPORT Bool fbSlotClaimed; +#if defined(__sparc__) || defined(__sparc) +extern _X_EXPORT Bool sbusSlotClaimed; +#endif +extern _X_EXPORT confDRIRec xf86ConfigDRI; +extern _X_EXPORT Bool xf86inSuspend; +extern _X_EXPORT Bool xf86DRI2Enabled(void); + +extern _X_EXPORT Bool VTSwitchEnabled; /* kbd driver */ + +#define XF86SCRNINFO(p) ((ScrnInfoPtr)dixLookupPrivate(&(p)->devPrivates, \ + xf86ScreenKey)) +#define XF86FLIP_PIXELS() \ + do { \ + if (xf86GetFlipPixels()) { \ + pScreen->whitePixel = (pScreen->whitePixel) ? 0 : 1; \ + pScreen->blackPixel = (pScreen->blackPixel) ? 0 : 1; \ + } \ + while (0) + +#define BOOLTOSTRING(b) ((b) ? "TRUE" : "FALSE") + +#define PIX24TOBPP(p) (((p) == Pix24Use24) ? 24 : \ + (((p) == Pix24Use32) ? 32 : 0)) + +/* Function Prototypes */ +#ifndef _NO_XF86_PROTOTYPES + +/* xf86Bus.c */ + +extern _X_EXPORT Bool xf86CheckPciSlot( const struct pci_device * ); +extern _X_EXPORT int xf86ClaimPciSlot( struct pci_device *, DriverPtr drvp, + int chipset, GDevPtr dev, Bool active); +extern _X_EXPORT void xf86UnclaimPciSlot(struct pci_device *); +extern _X_EXPORT Bool xf86ParsePciBusString(const char *busID, int *bus, int *device, + int *func); +extern _X_EXPORT Bool xf86ComparePciBusString(const char *busID, int bus, int device, int func); +extern _X_EXPORT void xf86FormatPciBusNumber(int busnum, char *buffer); +extern _X_EXPORT int xf86GetFbInfoForScreen(int scrnIndex); +extern _X_EXPORT int xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active); +extern _X_EXPORT int xf86ClaimNoSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool active); +extern _X_EXPORT void xf86EnableAccess(ScrnInfoPtr pScrn); +extern _X_EXPORT Bool xf86IsPrimaryPci(struct pci_device * pPci); +/* new RAC */ +extern _X_EXPORT Bool xf86DriverHasEntities(DriverPtr drvp); +extern _X_EXPORT void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex); +extern _X_EXPORT void xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, + int instance); +extern _X_EXPORT int xf86GetNumEntityInstances(int entityIndex); +extern _X_EXPORT GDevPtr xf86GetDevFromEntity(int entityIndex, int instance); +extern _X_EXPORT void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex); +extern _X_EXPORT EntityInfoPtr xf86GetEntityInfo(int entityIndex); +extern _X_EXPORT struct pci_device * xf86GetPciInfoForEntity(int entityIndex); +extern _X_EXPORT Bool xf86SetEntityFuncs(int entityIndex, EntityProc init, + EntityProc enter, EntityProc leave, pointer); +extern _X_EXPORT Bool xf86CheckPciMemBase(struct pci_device * pPci, memType base); +extern _X_EXPORT Bool xf86IsEntityPrimary(int entityIndex); +extern _X_EXPORT void xf86EnterServerState(xf86State state); +extern _X_EXPORT ScrnInfoPtr xf86FindScreenForEntity(int entityIndex); + +extern _X_EXPORT int xf86GetLastScrnFlag(int entityIndex); +extern _X_EXPORT void xf86SetLastScrnFlag(int entityIndex, int scrnIndex); +extern _X_EXPORT Bool xf86IsEntityShared(int entityIndex); +extern _X_EXPORT void xf86SetEntityShared(int entityIndex); +extern _X_EXPORT Bool xf86IsEntitySharable(int entityIndex); +extern _X_EXPORT void xf86SetEntitySharable(int entityIndex); +extern _X_EXPORT Bool xf86IsPrimInitDone(int entityIndex); +extern _X_EXPORT void xf86SetPrimInitDone(int entityIndex); +extern _X_EXPORT void xf86ClearPrimInitDone(int entityIndex); +extern _X_EXPORT int xf86AllocateEntityPrivateIndex(void); +extern _X_EXPORT DevUnion *xf86GetEntityPrivate(int entityIndex, int privIndex); + +/* xf86Configure.c */ +extern _X_EXPORT GDevPtr xf86AddBusDeviceToConfigure(const char *driver, BusType bus, + void *busData, int chipset); + +/* xf86Cursor.c */ + +extern _X_EXPORT void xf86LockZoom(ScreenPtr pScreen, int lock); +extern _X_EXPORT void xf86InitViewport(ScrnInfoPtr pScr); +extern _X_EXPORT void xf86SetViewport(ScreenPtr pScreen, int x, int y); +extern _X_EXPORT void xf86ZoomViewport(ScreenPtr pScreen, int zoom); +extern _X_EXPORT Bool xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode); +extern _X_EXPORT void *xf86GetPointerScreenFuncs(void); +extern _X_EXPORT void xf86InitOrigins(void); +extern _X_EXPORT void xf86ReconfigureLayout(void); + +/* xf86cvt.c */ +extern _X_EXPORT DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, + Bool Reduced, Bool Interlaced); + +/* xf86DPMS.c */ + +extern _X_EXPORT Bool xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags); + +#ifdef DPMSExtension +extern _X_EXPORT int DPMSSet(ClientPtr client, int level); +extern _X_EXPORT Bool DPMSSupported(void); +#endif + + +/* xf86DGA.c */ + +#ifdef XFreeXDGA +extern _X_EXPORT Bool DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs, DGAModePtr modes, + int num); +extern _X_EXPORT Bool DGAReInitModes(ScreenPtr pScreen, DGAModePtr modes, int num); +extern _X_EXPORT xf86SetDGAModeProc xf86SetDGAMode; +#endif + +/* xf86Events.c */ + +extern _X_EXPORT void SetTimeSinceLastInputEvent(void); +extern _X_EXPORT pointer xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data); +extern _X_EXPORT int xf86RemoveInputHandler(pointer handler); +extern _X_EXPORT void xf86DisableInputHandler(pointer handler); +extern _X_EXPORT void xf86EnableInputHandler(pointer handler); +extern _X_EXPORT pointer xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data); +extern _X_EXPORT int xf86RemoveGeneralHandler(pointer handler); +extern _X_EXPORT void xf86DisableGeneralHandler(pointer handler); +extern _X_EXPORT void xf86EnableGeneralHandler(pointer handler); +extern _X_EXPORT void xf86InterceptSignals(int *signo); +extern _X_EXPORT void xf86InterceptSigIll(void (*sigillhandler)(void)); +extern _X_EXPORT Bool xf86EnableVTSwitch(Bool new); +extern _X_EXPORT void xf86ProcessActionEvent(ActionEvent action, void *arg); +extern _X_EXPORT void xf86PrintBacktrace(void); + +/* xf86Helper.c */ + +extern _X_EXPORT void xf86AddDriver(DriverPtr driver, pointer module, int flags); +extern _X_EXPORT void xf86DeleteDriver(int drvIndex); +extern _X_EXPORT ScrnInfoPtr xf86AllocateScreen(DriverPtr drv, int flags); +extern _X_EXPORT void xf86DeleteScreen(int scrnIndex, int flags); +extern _X_EXPORT int xf86AllocateScrnInfoPrivateIndex(void); +extern _X_EXPORT Bool xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad); +extern _X_EXPORT Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp, int fbbpp, + int depth24flags); +extern _X_EXPORT void xf86PrintDepthBpp(ScrnInfoPtr scrp); +extern _X_EXPORT Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask); +extern _X_EXPORT Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual); +extern _X_EXPORT Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma newGamma); +extern _X_EXPORT void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y); +extern _X_EXPORT void xf86SetBlackWhitePixels(ScreenPtr pScreen); +extern _X_EXPORT void xf86EnableDisableFBAccess(int scrnIndex, Bool enable); +extern _X_EXPORT void xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, + const char *format, va_list args); +extern _X_EXPORT void xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, + const char *format, ...) _X_ATTRIBUTE_PRINTF(4,5); +extern _X_EXPORT void xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...) + _X_ATTRIBUTE_PRINTF(3,4); +extern _X_EXPORT void xf86MsgVerb(MessageType type, int verb, const char *format, ...) + _X_ATTRIBUTE_PRINTF(3,4); +extern _X_EXPORT void xf86Msg(MessageType type, const char *format, ...) _X_ATTRIBUTE_PRINTF(2,3); +extern _X_EXPORT void xf86ErrorFVerb(int verb, const char *format, ...) _X_ATTRIBUTE_PRINTF(2,3); +extern _X_EXPORT void xf86ErrorF(const char *format, ...) _X_ATTRIBUTE_PRINTF(1,2); +extern _X_EXPORT const char *xf86TokenToString(SymTabPtr table, int token); +extern _X_EXPORT int xf86StringToToken(SymTabPtr table, const char *string); +extern _X_EXPORT void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from); +extern _X_EXPORT void xf86PrintChipsets(const char *drvname, const char *drvmsg, + SymTabPtr chips); +extern _X_EXPORT int xf86MatchDevice(const char *drivername, GDevPtr **driversectlist); +extern _X_EXPORT int xf86MatchPciInstances(const char *driverName, int vendorID, + SymTabPtr chipsets, PciChipsets *PCIchipsets, + GDevPtr *devList, int numDevs, DriverPtr drvp, + int **foundEntities); +extern _X_EXPORT void xf86GetClocks(ScrnInfoPtr pScrn, int num, + Bool (*ClockFunc)(ScrnInfoPtr, int), + void (*ProtectRegs)(ScrnInfoPtr, Bool), + void (*BlankScreen)(ScrnInfoPtr, Bool), + IOADDRESS vertsyncreg, int maskval, + int knownclkindex, int knownclkvalue); +extern _X_EXPORT const char *xf86GetVisualName(int visual); +extern _X_EXPORT int xf86GetVerbosity(void); +extern _X_EXPORT Pix24Flags xf86GetPix24(void); +extern _X_EXPORT int xf86GetDepth(void); +extern _X_EXPORT rgb xf86GetWeight(void); +extern _X_EXPORT Gamma xf86GetGamma(void); +extern _X_EXPORT Bool xf86GetFlipPixels(void); +extern _X_EXPORT const char *xf86GetServerName(void); +extern _X_EXPORT Bool xf86ServerIsExiting(void); +extern _X_EXPORT Bool xf86ServerIsResetting(void); +extern _X_EXPORT Bool xf86ServerIsInitialising(void); +extern _X_EXPORT Bool xf86ServerIsOnlyDetecting(void); +extern _X_EXPORT Bool xf86CaughtSignal(void); +extern _X_EXPORT Bool xf86GetVidModeAllowNonLocal(void); +extern _X_EXPORT Bool xf86GetVidModeEnabled(void); +extern _X_EXPORT Bool xf86GetModInDevAllowNonLocal(void); +extern _X_EXPORT Bool xf86GetModInDevEnabled(void); +extern _X_EXPORT Bool xf86GetAllowMouseOpenFail(void); +extern _X_EXPORT Bool xf86IsPc98(void); +extern _X_EXPORT void xf86DisableRandR(void); +extern _X_EXPORT CARD32 xorgGetVersion(void); +extern _X_EXPORT CARD32 xf86GetModuleVersion(pointer module); +extern _X_EXPORT pointer xf86LoadDrvSubModule(DriverPtr drv, const char *name); +extern _X_EXPORT pointer xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name); +extern _X_EXPORT pointer xf86LoadOneModule(char *name, pointer optlist); +extern _X_EXPORT void xf86UnloadSubModule(pointer mod); +extern _X_EXPORT Bool xf86LoaderCheckSymbol(const char *name); +extern _X_EXPORT void xf86SetBackingStore(ScreenPtr pScreen); +extern _X_EXPORT void xf86SetSilkenMouse(ScreenPtr pScreen); +extern _X_EXPORT pointer xf86FindXvOptions(int scrnIndex, int adapt_index, char *port_name, + char **adaptor_name, pointer *adaptor_options); +extern _X_EXPORT void xf86GetOS(const char **name, int *major, int *minor, int *teeny); +extern _X_EXPORT ScrnInfoPtr xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, + int entityIndex,PciChipsets *p_chip, + void *dummy, EntityProc init, + EntityProc enter, EntityProc leave, + pointer private); +extern _X_EXPORT ScrnInfoPtr xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, + int entityIndex, EntityProc init, + EntityProc enter, EntityProc leave, + pointer private); + +/* Obsolete! don't use */ +extern _X_EXPORT Bool xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, + int entityIndex,PciChipsets *p_chip, + void *dummy, EntityProc init, + EntityProc enter, EntityProc leave, + pointer private); + +extern _X_EXPORT Bool xf86IsScreenPrimary(int scrnIndex); +extern _X_EXPORT int xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type, + int format, unsigned long len, + pointer value); +extern _X_EXPORT Bool xf86IsUnblank(int mode); + +/* xf86Init.c */ + +extern _X_EXPORT PixmapFormatPtr xf86GetPixFormat(ScrnInfoPtr pScrn, int depth); +extern _X_EXPORT int xf86GetBppFromDepth(ScrnInfoPtr pScrn, int depth); + +/* xf86Mode.c */ + +extern _X_EXPORT int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, + int DivFactor, int MulFactor, int *divider); +extern _X_EXPORT const char *xf86ModeStatusToString(ModeStatus status); +extern _X_EXPORT ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, + ClockRangePtr clockRanges, LookupModeFlags strategy); +extern _X_EXPORT ModeStatus xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor); +extern _X_EXPORT ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, + ClockRangePtr clockRanges, + LookupModeFlags strategy, + int maxPitch, int virtualX, + int virtualY); +extern _X_EXPORT ModeStatus xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, + int flags); +extern _X_EXPORT int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, + char **modeNames, ClockRangePtr clockRanges, + int *linePitches, int minPitch, int maxPitch, + int minHeight, int maxHeight, int pitchInc, + int virtualX, int virtualY, int apertureSize, + LookupModeFlags strategy); +extern _X_EXPORT void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode); +extern _X_EXPORT void xf86PruneDriverModes(ScrnInfoPtr scrp); +extern _X_EXPORT void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags); +extern _X_EXPORT void xf86PrintModes(ScrnInfoPtr scrp); +extern _X_EXPORT void xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges); +extern _X_EXPORT double xf86ModeHSync(const DisplayModeRec *mode); +extern _X_EXPORT double xf86ModeVRefresh(const DisplayModeRec *mode); +extern _X_EXPORT void xf86SetModeDefaultName(DisplayModePtr mode); +extern _X_EXPORT void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); +extern _X_EXPORT DisplayModePtr xf86DuplicateMode(const DisplayModeRec *pMode); +extern _X_EXPORT DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList); +extern _X_EXPORT Bool xf86ModesEqual(const DisplayModeRec *pMode1, + const DisplayModeRec *pMode2); +extern _X_EXPORT void xf86PrintModeline(int scrnIndex,DisplayModePtr mode); +extern _X_EXPORT DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); + +/* xf86Option.c */ + +extern _X_EXPORT void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts); + + +/* xf86RandR.c */ +#ifdef RANDR +extern _X_EXPORT Bool xf86RandRInit (ScreenPtr pScreen); +extern _X_EXPORT Rotation xf86GetRotation(ScreenPtr pScreen); +extern _X_EXPORT Bool xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen, + int newvirtX, int newvirtY, + int newmmWidth, int newmmHeight, Bool resetMode); +#endif + +/* xf86VidModeExtentionInit.c */ + +extern _X_EXPORT Bool VidModeExtensionInit(ScreenPtr pScreen); + +#endif /* _NO_XF86_PROTOTYPES */ + +#endif /* _XF86_H */ diff --git a/xorg-server/hw/xfree86/common/xf86AutoConfig.c b/xorg-server/hw/xfree86/common/xf86AutoConfig.c index 7b836b00d..88891e5a7 100644 --- a/xorg-server/hw/xfree86/common/xf86AutoConfig.c +++ b/xorg-server/hw/xfree86/common/xf86AutoConfig.c @@ -1,638 +1,638 @@ -/* - * Copyright 2003 by David H. Dawes. - * Copyright 2003 by X-Oz Technologies. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - * - * Author: David Dawes . - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86Parser.h" -#include "xf86tokens.h" -#include "xf86Config.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#ifdef __sparc__ -# include "xf86sbusBus.h" -#endif -#include "dirent.h" - -#ifdef sun -# include -# include -#endif - -/* Sections for the default built-in configuration. */ - -#define BUILTIN_DEVICE_NAME \ - "\"Builtin Default %s Device %d\"" - -#define BUILTIN_DEVICE_SECTION_PRE \ - "Section \"Device\"\n" \ - "\tIdentifier\t" BUILTIN_DEVICE_NAME "\n" \ - "\tDriver\t\"%s\"\n" - -#define BUILTIN_DEVICE_SECTION_POST \ - "EndSection\n\n" - -#define BUILTIN_DEVICE_SECTION \ - BUILTIN_DEVICE_SECTION_PRE \ - BUILTIN_DEVICE_SECTION_POST - -#define BUILTIN_SCREEN_NAME \ - "\"Builtin Default %s Screen %d\"" - -#define BUILTIN_SCREEN_SECTION \ - "Section \"Screen\"\n" \ - "\tIdentifier\t" BUILTIN_SCREEN_NAME "\n" \ - "\tDevice\t" BUILTIN_DEVICE_NAME "\n" \ - "EndSection\n\n" - -#define BUILTIN_LAYOUT_SECTION_PRE \ - "Section \"ServerLayout\"\n" \ - "\tIdentifier\t\"Builtin Default Layout\"\n" - -#define BUILTIN_LAYOUT_SCREEN_LINE \ - "\tScreen\t" BUILTIN_SCREEN_NAME "\n" - -#define BUILTIN_LAYOUT_SECTION_POST \ - "EndSection\n\n" - -static const char **builtinConfig = NULL; -static int builtinLines = 0; - -static void listPossibleVideoDrivers(char *matches[], int nmatches); - -/* - * A built-in config file is stored as an array of strings, with each string - * representing a single line. AppendToConfig() breaks up the string "s" - * into lines, and appends those lines it to builtinConfig. - */ - -static void -AppendToList(const char *s, const char ***list, int *lines) -{ - char *str, *newstr, *p; - - str = xnfstrdup(s); - for (p = strtok(str, "\n"); p; p = strtok(NULL, "\n")) { - (*lines)++; - *list = xnfrealloc(*list, (*lines + 1) * sizeof(**list)); - newstr = xnfalloc(strlen(p) + 2); - strcpy(newstr, p); - strcat(newstr, "\n"); - (*list)[*lines - 1] = newstr; - (*list)[*lines] = NULL; - } - xfree(str); -} - -static void -FreeList(const char ***list, int *lines) -{ - int i; - - for (i = 0; i < *lines; i++) { - if ((*list)[i]) - xfree((*list)[i]); - } - xfree(*list); - *list = NULL; - *lines = 0; -} - -static void -FreeConfig(void) -{ - FreeList(&builtinConfig, &builtinLines); -} - -static void -AppendToConfig(const char *s) -{ - AppendToList(s, &builtinConfig, &builtinLines); -} - -static int -videoPtrToDriverList(struct pci_device *dev, - char *returnList[], int returnListMax) -{ - int i; - /* Add more entries here if we ever return more than 4 drivers for - any device */ - char *driverList[5] = { NULL, NULL, NULL, NULL, NULL }; - - switch (dev->vendor_id) - { - /* AMD Geode LX */ - case 0x1022: - if (dev->device_id == 0x2081) - driverList[0] = "geode"; - break; - /* older Geode products acquired by AMD still carry an NSC vendor_id */ - case 0x100b: - if (dev->device_id == 0x0030) { - /* NSC Geode GX2 specifically */ - driverList[0] = "geode"; - /* GX2 support started its life in the NSC tree and was later - forked by AMD for GEODE so we keep it as a backup */ - driverList[1] = "nsc"; - } else - /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */ - driverList[0] = "nsc"; - break; - /* Cyrix Geode GX1 */ - case 0x1078: - if (dev->device_id == 0x0104) - driverList[0] = "cyrix"; - break; - case 0x1142: driverList[0] = "apm"; break; - case 0xedd8: driverList[0] = "ark"; break; - case 0x1a03: driverList[0] = "ast"; break; - case 0x1002: driverList[0] = "ati"; break; - case 0x102c: driverList[0] = "chips"; break; - case 0x1013: driverList[0] = "cirrus"; break; - case 0x3d3d: driverList[0] = "glint"; break; - case 0x105d: driverList[0] = "i128"; break; - case 0x8086: - if ((dev->device_id == 0x00d1) || (dev->device_id == 0x7800)) { - driverList[0] = "i740"; - } else if (dev->device_id == 0x8108) { - break; /* "hooray" for poulsbo */ - } else { - driverList[0] = "intel"; - } - break; - case 0x102b: driverList[0] = "mga"; break; - case 0x10c8: driverList[0] = "neomagic"; break; - case 0x10de: case 0x12d2: driverList[0] = "nv"; break; - case 0x1106: driverList[0] = "openchrome"; break; - case 0x1b36: driverList[0] = "qxl"; break; - case 0x1163: driverList[0] = "rendition"; break; - case 0x5333: - switch (dev->device_id) - { - case 0x88d0: case 0x88d1: case 0x88f0: case 0x8811: - case 0x8812: case 0x8814: case 0x8901: - driverList[0] = "s3"; break; - case 0x5631: case 0x883d: case 0x8a01: case 0x8a10: - case 0x8c01: case 0x8c03: case 0x8904: case 0x8a13: - driverList[0] = "s3virge"; break; - default: - driverList[0] = "savage"; break; - } - break; - case 0x1039: driverList[0] = "sis"; break; - case 0x126f: driverList[0] = "siliconmotion"; break; - case 0x121a: - if (dev->device_id < 0x0003) - driverList[0] = "voodoo"; - else - driverList[0] = "tdfx"; - break; - case 0x1011: driverList[0] = "tga"; break; - case 0x1023: driverList[0] = "trident"; break; - case 0x100c: driverList[0] = "tseng"; break; - case 0x80ee: driverList[0] = "vboxvideo"; break; - case 0x15ad: driverList[0] = "vmware"; break; - case 0x18ca: - if (dev->device_id == 0x47) - driverList[0] = "xgixp"; - else - driverList[0] = "xgi"; - break; - default: break; - } - for (i = 0; (i < returnListMax) && (driverList[i] != NULL); i++) { - returnList[i] = xnfstrdup(driverList[i]); - } - return i; /* Number of entries added */ -} - -Bool -xf86AutoConfig(void) -{ - char *deviceList[20]; - char **p; - const char **cp; - char buf[1024]; - ConfigStatus ret; - - listPossibleVideoDrivers(deviceList, 20); - - for (p = deviceList; *p; p++) { - snprintf(buf, sizeof(buf), BUILTIN_DEVICE_SECTION, *p, 0, *p); - AppendToConfig(buf); - snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION, *p, 0, *p, 0); - AppendToConfig(buf); - } - - AppendToConfig(BUILTIN_LAYOUT_SECTION_PRE); - for (p = deviceList; *p; p++) { - snprintf(buf, sizeof(buf), BUILTIN_LAYOUT_SCREEN_LINE, *p, 0); - AppendToConfig(buf); - } - AppendToConfig(BUILTIN_LAYOUT_SECTION_POST); - - for (p = deviceList; *p; p++) { - xfree(*p); - } - - xf86MsgVerb(X_DEFAULT, 0, - "Using default built-in configuration (%d lines)\n", - builtinLines); - - xf86MsgVerb(X_DEFAULT, 3, "--- Start of built-in configuration ---\n"); - for (cp = builtinConfig; *cp; cp++) - xf86ErrorFVerb(3, "\t%s", *cp); - xf86MsgVerb(X_DEFAULT, 3, "--- End of built-in configuration ---\n"); - - xf86initConfigFiles(); - xf86setBuiltinConfig(builtinConfig); - ret = xf86HandleConfigFile(TRUE); - FreeConfig(); - - if (ret != CONFIG_OK) - xf86Msg(X_ERROR, "Error parsing the built-in default configuration.\n"); - - return (ret == CONFIG_OK); -} - -static int -xchomp(char *line) -{ - size_t len = 0; - - if (!line) { - return 1; - } - - len = strlen(line); - if (line[len - 1] == '\n' && len > 0) { - line[len - 1] = '\0'; - } - return 0; -} - -#ifdef __linux__ -/* This function is used to provide a workaround for binary drivers that - * don't export their PCI ID's properly. If distros don't end up using this - * feature it can and should be removed because the symbol-based resolution - * scheme should be the primary one */ -static void -matchDriverFromFiles (char** matches, uint16_t match_vendor, uint16_t match_chip) -{ - DIR *idsdir; - FILE *fp; - struct dirent *direntry; - char *line = NULL; - size_t len; - ssize_t read; - char path_name[256], vendor_str[5], chip_str[5]; - uint16_t vendor, chip; - int i, j; - - idsdir = opendir(PCI_TXT_IDS_PATH); - if (!idsdir) - return; - - xf86Msg(X_INFO, "Scanning %s directory for additional PCI ID's supported by the drivers\n", PCI_TXT_IDS_PATH); - direntry = readdir(idsdir); - /* Read the directory */ - while (direntry) { - if (direntry->d_name[0] == '.') { - direntry = readdir(idsdir); - continue; - } - len = strlen(direntry->d_name); - /* A tiny bit of sanity checking. We should probably do better */ - if (strncmp(&(direntry->d_name[len-4]), ".ids", 4) == 0) { - /* We need the full path name to open the file */ - strncpy(path_name, PCI_TXT_IDS_PATH, 256); - strncat(path_name, "/", 1); - strncat(path_name, direntry->d_name, (256 - strlen(path_name) - 1)); - fp = fopen(path_name, "r"); - if (fp == NULL) { - xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n", path_name); - goto end; - } - /* Read the file */ -#ifdef __GLIBC__ - while ((read = getline(&line, &len, fp)) != -1) { -#else - while ((line = fgetln(fp, &len)) != (char *)NULL) { -#endif /* __GLIBC __ */ - xchomp(line); - if (isdigit(line[0])) { - strncpy(vendor_str, line, 4); - vendor_str[4] = '\0'; - vendor = (int)strtol(vendor_str, NULL, 16); - if ((strlen(&line[4])) == 0) { - chip_str[0] = '\0'; - chip = -1; - } else { - /* Handle trailing whitespace */ - if (isspace(line[4])) { - chip_str[0] = '\0'; - chip = -1; - } else { - /* Ok, it's a real ID */ - strncpy(chip_str, &line[4], 4); - chip_str[4] = '\0'; - chip = (int)strtol(chip_str, NULL, 16); - } - } - if (vendor == match_vendor && chip == match_chip ) { - i = 0; - while (matches[i]) { - i++; - } - matches[i] = (char*)xalloc(sizeof(char) * strlen(direntry->d_name) - 3); - if (!matches[i]) { - xf86Msg(X_ERROR, "Could not allocate space for the module name. Exiting.\n"); - goto end; - } - /* hack off the .ids suffix. This should guard - * against other problems, but it will end up - * taking off anything after the first '.' */ - for (j = 0; j < (strlen(direntry->d_name) - 3) ; j++) { - if (direntry->d_name[j] == '.') { - matches[i][j] = '\0'; - break; - } else { - matches[i][j] = direntry->d_name[j]; - } - } - xf86Msg(X_INFO, "Matched %s from file name %s\n", matches[i], direntry->d_name); - } - } else { - /* TODO Handle driver overrides here */ - } - } - fclose(fp); - } - direntry = readdir(idsdir); - } - end: - xfree(line); - closedir(idsdir); -} -#endif /* __linux__ */ - -static void -listPossibleVideoDrivers(char *matches[], int nmatches) -{ - struct pci_device * info = NULL; - struct pci_device_iterator *iter; - int i; - - for (i = 0 ; i < nmatches ; i++) { - matches[i] = NULL; - } - i = 0; - -#ifdef sun - /* Check for driver type based on /dev/fb type and if valid, use - it instead of PCI bus probe results */ - if (xf86Info.consoleFd >= 0) { - struct vis_identifier visid; - const char *cp; - extern char xf86SolarisFbDev[PATH_MAX]; - int iret; - - SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid)); - if (iret < 0) { - int fbfd; - - fbfd = open(xf86SolarisFbDev, O_RDONLY); - if (fbfd >= 0) { - SYSCALL(iret = ioctl(fbfd, VIS_GETIDENTIFIER, &visid)); - close(fbfd); - } - } - - if (iret < 0) { - xf86Msg(X_WARNING, - "could not get frame buffer identifier from %s\n", - xf86SolarisFbDev); - } else { - xf86Msg(X_PROBED, "console driver: %s\n", visid.name); - - /* Special case from before the general case was set */ - if (strcmp(visid.name, "NVDAnvda") == 0) { - matches[i++] = xnfstrdup("nvidia"); - } - - /* General case - split into vendor name (initial all-caps - prefix) & driver name (rest of the string). */ - if (strcmp(visid.name, "SUNWtext") != 0) { - for (cp = visid.name; (*cp != '\0') && isupper(*cp); cp++) { - /* find end of all uppercase vendor section */ - } - if ((cp != visid.name) && (*cp != '\0')) { - char *driverName = xnfstrdup(cp); - char *vendorName = xnfstrdup(visid.name); - vendorName[cp - visid.name] = '\0'; - - matches[i++] = vendorName; - matches[i++] = driverName; - } - } - } - } -#endif -#ifdef __sparc__ - { - char *sbusDriver = sparcDriverName(); - if (sbusDriver) - matches[i++] = xnfstrdup(sbusDriver); - } -#endif - - /* Find the primary device, and get some information about it. */ - iter = pci_slot_match_iterator_create(NULL); - while ((info = pci_device_next(iter)) != NULL) { - if (xf86IsPrimaryPci(info)) { - break; - } - } - - pci_iterator_destroy(iter); - - if (!info) { - ErrorF("Primary device is not PCI\n"); - } -#ifdef __linux__ - else { - matchDriverFromFiles(matches, info->vendor_id, info->device_id); - } -#endif /* __linux__ */ - - for (i = 0; (i < nmatches) && (matches[i]); i++) { - /* find end of matches list */ - } - - if ((info != NULL) && (i < nmatches)) { - i += videoPtrToDriverList(info, &(matches[i]), nmatches - i); - } - - /* Fallback to platform default hardware */ - if (i < (nmatches - 1)) { -#if defined(__i386__) || defined(__amd64__) || defined(__hurd__) - matches[i++] = xnfstrdup("vesa"); -#elif defined(__sparc__) && !defined(sun) - matches[i++] = xnfstrdup("sunffb"); -#endif - } - - /* Fallback to platform default frame buffer driver */ - if (i < (nmatches - 1)) { -#if !defined(__linux__) && defined(__sparc__) - matches[i++] = xnfstrdup("wsfb"); -#else - matches[i++] = xnfstrdup("fbdev"); -#endif - } -} - -/* copy a screen section and enter the desired driver - * and insert it at i in the list of screens */ -static Bool -copyScreen(confScreenPtr oscreen, GDevPtr odev, int i, char *driver) -{ - GDevPtr cptr = NULL; - - xf86ConfigLayout.screens[i].screen = xnfcalloc(1, sizeof(confScreenRec)); - if(!xf86ConfigLayout.screens[i].screen) - return FALSE; - memcpy(xf86ConfigLayout.screens[i].screen, oscreen, sizeof(confScreenRec)); - - cptr = xcalloc(1, sizeof(GDevRec)); - if (!cptr) - return FALSE; - memcpy(cptr, odev, sizeof(GDevRec)); - - cptr->identifier = Xprintf("Autoconfigured Video Device %s", driver); - cptr->driver = driver; - - /* now associate the new driver entry with the new screen entry */ - xf86ConfigLayout.screens[i].screen->device = cptr; - cptr->myScreenSection = xf86ConfigLayout.screens[i].screen; - - return TRUE; -} - -GDevPtr -autoConfigDevice(GDevPtr preconf_device) -{ - GDevPtr ptr = NULL; - char *matches[20]; /* If we have more than 20 drivers we're in trouble */ - int num_matches = 0, num_screens = 0, i; - screenLayoutPtr slp; - - if (!xf86configptr) { - return NULL; - } - - /* If there's a configured section with no driver chosen, use it */ - if (preconf_device) { - ptr = preconf_device; - } else { - ptr = xcalloc(1, sizeof(GDevRec)); - if (!ptr) { - return NULL; - } - ptr->chipID = -1; - ptr->chipRev = -1; - ptr->irq = -1; - - ptr->active = TRUE; - ptr->claimed = FALSE; - ptr->identifier = "Autoconfigured Video Device"; - ptr->driver = NULL; - } - if (!ptr->driver) { - /* get all possible video drivers and count them */ - listPossibleVideoDrivers(matches, 20); - for (; matches[num_matches]; num_matches++) { - xf86Msg(X_DEFAULT, "Matched %s as autoconfigured driver %d\n", - matches[num_matches], num_matches); - } - - slp = xf86ConfigLayout.screens; - if (slp) { - /* count the number of screens and make space for - * a new screen for each additional possible driver - * minus one for the already existing first one - * plus one for the terminating NULL */ - for (; slp[num_screens].screen; num_screens++); - xf86ConfigLayout.screens = xnfcalloc(num_screens + num_matches, - sizeof(screenLayoutRec)); - xf86ConfigLayout.screens[0] = slp[0]; - - /* do the first match and set that for the original first screen */ - ptr->driver = matches[0]; - if (!xf86ConfigLayout.screens[0].screen->device) { - xf86ConfigLayout.screens[0].screen->device = ptr; - ptr->myScreenSection = xf86ConfigLayout.screens[0].screen; - } - - /* for each other driver found, copy the first screen, insert it - * into the list of screens and set the driver */ - i = 0; - while (i++ < num_matches) { - if (!copyScreen(slp[0].screen, ptr, i, matches[i])) - return NULL; - } - - /* shift the rest of the original screen list - * to the end of the current screen list - * - * TODO Handle rest of multiple screen sections */ - for (i = 1; i < num_screens; i++) { - xf86ConfigLayout.screens[i+num_matches] = slp[i]; - } - xf86ConfigLayout.screens[num_screens+num_matches-1].screen = NULL; - xfree(slp); - } else { - /* layout does not have any screens, not much to do */ - ptr->driver = matches[0]; - for (i = 1; matches[i] ; i++) { - if (matches[i] != matches[0]) { - xfree(matches[i]); - } - } - } - } - - xf86Msg(X_DEFAULT, "Assigned the driver to the xf86ConfigLayout\n"); - - return ptr; -} +/* + * Copyright 2003 by David H. Dawes. + * Copyright 2003 by X-Oz Technologies. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + * + * Author: David Dawes . + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "xf86Config.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#ifdef __sparc__ +# include "xf86sbusBus.h" +#endif +#include "dirent.h" + +#ifdef sun +# include +# include +#endif + +/* Sections for the default built-in configuration. */ + +#define BUILTIN_DEVICE_NAME \ + "\"Builtin Default %s Device %d\"" + +#define BUILTIN_DEVICE_SECTION_PRE \ + "Section \"Device\"\n" \ + "\tIdentifier\t" BUILTIN_DEVICE_NAME "\n" \ + "\tDriver\t\"%s\"\n" + +#define BUILTIN_DEVICE_SECTION_POST \ + "EndSection\n\n" + +#define BUILTIN_DEVICE_SECTION \ + BUILTIN_DEVICE_SECTION_PRE \ + BUILTIN_DEVICE_SECTION_POST + +#define BUILTIN_SCREEN_NAME \ + "\"Builtin Default %s Screen %d\"" + +#define BUILTIN_SCREEN_SECTION \ + "Section \"Screen\"\n" \ + "\tIdentifier\t" BUILTIN_SCREEN_NAME "\n" \ + "\tDevice\t" BUILTIN_DEVICE_NAME "\n" \ + "EndSection\n\n" + +#define BUILTIN_LAYOUT_SECTION_PRE \ + "Section \"ServerLayout\"\n" \ + "\tIdentifier\t\"Builtin Default Layout\"\n" + +#define BUILTIN_LAYOUT_SCREEN_LINE \ + "\tScreen\t" BUILTIN_SCREEN_NAME "\n" + +#define BUILTIN_LAYOUT_SECTION_POST \ + "EndSection\n\n" + +static const char **builtinConfig = NULL; +static int builtinLines = 0; + +static void listPossibleVideoDrivers(char *matches[], int nmatches); + +/* + * A built-in config file is stored as an array of strings, with each string + * representing a single line. AppendToConfig() breaks up the string "s" + * into lines, and appends those lines it to builtinConfig. + */ + +static void +AppendToList(const char *s, const char ***list, int *lines) +{ + char *str, *newstr, *p; + + str = xnfstrdup(s); + for (p = strtok(str, "\n"); p; p = strtok(NULL, "\n")) { + (*lines)++; + *list = xnfrealloc(*list, (*lines + 1) * sizeof(**list)); + newstr = xnfalloc(strlen(p) + 2); + strcpy(newstr, p); + strcat(newstr, "\n"); + (*list)[*lines - 1] = newstr; + (*list)[*lines] = NULL; + } + free(str); +} + +static void +FreeList(const char ***list, int *lines) +{ + int i; + + for (i = 0; i < *lines; i++) { + if ((*list)[i]) + free((*list)[i]); + } + free(*list); + *list = NULL; + *lines = 0; +} + +static void +FreeConfig(void) +{ + FreeList(&builtinConfig, &builtinLines); +} + +static void +AppendToConfig(const char *s) +{ + AppendToList(s, &builtinConfig, &builtinLines); +} + +static int +videoPtrToDriverList(struct pci_device *dev, + char *returnList[], int returnListMax) +{ + int i; + /* Add more entries here if we ever return more than 4 drivers for + any device */ + char *driverList[5] = { NULL, NULL, NULL, NULL, NULL }; + + switch (dev->vendor_id) + { + /* AMD Geode LX */ + case 0x1022: + if (dev->device_id == 0x2081) + driverList[0] = "geode"; + break; + /* older Geode products acquired by AMD still carry an NSC vendor_id */ + case 0x100b: + if (dev->device_id == 0x0030) { + /* NSC Geode GX2 specifically */ + driverList[0] = "geode"; + /* GX2 support started its life in the NSC tree and was later + forked by AMD for GEODE so we keep it as a backup */ + driverList[1] = "nsc"; + } else + /* other NSC variant e.g. 0x0104 (SC1400), 0x0504 (SCx200) */ + driverList[0] = "nsc"; + break; + /* Cyrix Geode GX1 */ + case 0x1078: + if (dev->device_id == 0x0104) + driverList[0] = "cyrix"; + break; + case 0x1142: driverList[0] = "apm"; break; + case 0xedd8: driverList[0] = "ark"; break; + case 0x1a03: driverList[0] = "ast"; break; + case 0x1002: driverList[0] = "ati"; break; + case 0x102c: driverList[0] = "chips"; break; + case 0x1013: driverList[0] = "cirrus"; break; + case 0x3d3d: driverList[0] = "glint"; break; + case 0x105d: driverList[0] = "i128"; break; + case 0x8086: + if ((dev->device_id == 0x00d1) || (dev->device_id == 0x7800)) { + driverList[0] = "i740"; + } else if (dev->device_id == 0x8108) { + break; /* "hooray" for poulsbo */ + } else { + driverList[0] = "intel"; + } + break; + case 0x102b: driverList[0] = "mga"; break; + case 0x10c8: driverList[0] = "neomagic"; break; + case 0x10de: case 0x12d2: driverList[0] = "nv"; break; + case 0x1106: driverList[0] = "openchrome"; break; + case 0x1b36: driverList[0] = "qxl"; break; + case 0x1163: driverList[0] = "rendition"; break; + case 0x5333: + switch (dev->device_id) + { + case 0x88d0: case 0x88d1: case 0x88f0: case 0x8811: + case 0x8812: case 0x8814: case 0x8901: + driverList[0] = "s3"; break; + case 0x5631: case 0x883d: case 0x8a01: case 0x8a10: + case 0x8c01: case 0x8c03: case 0x8904: case 0x8a13: + driverList[0] = "s3virge"; break; + default: + driverList[0] = "savage"; break; + } + break; + case 0x1039: driverList[0] = "sis"; break; + case 0x126f: driverList[0] = "siliconmotion"; break; + case 0x121a: + if (dev->device_id < 0x0003) + driverList[0] = "voodoo"; + else + driverList[0] = "tdfx"; + break; + case 0x1011: driverList[0] = "tga"; break; + case 0x1023: driverList[0] = "trident"; break; + case 0x100c: driverList[0] = "tseng"; break; + case 0x80ee: driverList[0] = "vboxvideo"; break; + case 0x15ad: driverList[0] = "vmware"; break; + case 0x18ca: + if (dev->device_id == 0x47) + driverList[0] = "xgixp"; + else + driverList[0] = "xgi"; + break; + default: break; + } + for (i = 0; (i < returnListMax) && (driverList[i] != NULL); i++) { + returnList[i] = xnfstrdup(driverList[i]); + } + return i; /* Number of entries added */ +} + +Bool +xf86AutoConfig(void) +{ + char *deviceList[20]; + char **p; + const char **cp; + char buf[1024]; + ConfigStatus ret; + + listPossibleVideoDrivers(deviceList, 20); + + for (p = deviceList; *p; p++) { + snprintf(buf, sizeof(buf), BUILTIN_DEVICE_SECTION, *p, 0, *p); + AppendToConfig(buf); + snprintf(buf, sizeof(buf), BUILTIN_SCREEN_SECTION, *p, 0, *p, 0); + AppendToConfig(buf); + } + + AppendToConfig(BUILTIN_LAYOUT_SECTION_PRE); + for (p = deviceList; *p; p++) { + snprintf(buf, sizeof(buf), BUILTIN_LAYOUT_SCREEN_LINE, *p, 0); + AppendToConfig(buf); + } + AppendToConfig(BUILTIN_LAYOUT_SECTION_POST); + + for (p = deviceList; *p; p++) { + free(*p); + } + + xf86MsgVerb(X_DEFAULT, 0, + "Using default built-in configuration (%d lines)\n", + builtinLines); + + xf86MsgVerb(X_DEFAULT, 3, "--- Start of built-in configuration ---\n"); + for (cp = builtinConfig; *cp; cp++) + xf86ErrorFVerb(3, "\t%s", *cp); + xf86MsgVerb(X_DEFAULT, 3, "--- End of built-in configuration ---\n"); + + xf86initConfigFiles(); + xf86setBuiltinConfig(builtinConfig); + ret = xf86HandleConfigFile(TRUE); + FreeConfig(); + + if (ret != CONFIG_OK) + xf86Msg(X_ERROR, "Error parsing the built-in default configuration.\n"); + + return (ret == CONFIG_OK); +} + +static int +xchomp(char *line) +{ + size_t len = 0; + + if (!line) { + return 1; + } + + len = strlen(line); + if (line[len - 1] == '\n' && len > 0) { + line[len - 1] = '\0'; + } + return 0; +} + +#ifdef __linux__ +/* This function is used to provide a workaround for binary drivers that + * don't export their PCI ID's properly. If distros don't end up using this + * feature it can and should be removed because the symbol-based resolution + * scheme should be the primary one */ +static void +matchDriverFromFiles (char** matches, uint16_t match_vendor, uint16_t match_chip) +{ + DIR *idsdir; + FILE *fp; + struct dirent *direntry; + char *line = NULL; + size_t len; + ssize_t read; + char path_name[256], vendor_str[5], chip_str[5]; + uint16_t vendor, chip; + int i, j; + + idsdir = opendir(PCI_TXT_IDS_PATH); + if (!idsdir) + return; + + xf86Msg(X_INFO, "Scanning %s directory for additional PCI ID's supported by the drivers\n", PCI_TXT_IDS_PATH); + direntry = readdir(idsdir); + /* Read the directory */ + while (direntry) { + if (direntry->d_name[0] == '.') { + direntry = readdir(idsdir); + continue; + } + len = strlen(direntry->d_name); + /* A tiny bit of sanity checking. We should probably do better */ + if (strncmp(&(direntry->d_name[len-4]), ".ids", 4) == 0) { + /* We need the full path name to open the file */ + strncpy(path_name, PCI_TXT_IDS_PATH, 256); + strncat(path_name, "/", 1); + strncat(path_name, direntry->d_name, (256 - strlen(path_name) - 1)); + fp = fopen(path_name, "r"); + if (fp == NULL) { + xf86Msg(X_ERROR, "Could not open %s for reading. Exiting.\n", path_name); + goto end; + } + /* Read the file */ +#ifdef __GLIBC__ + while ((read = getline(&line, &len, fp)) != -1) { +#else + while ((line = fgetln(fp, &len)) != (char *)NULL) { +#endif /* __GLIBC __ */ + xchomp(line); + if (isdigit(line[0])) { + strncpy(vendor_str, line, 4); + vendor_str[4] = '\0'; + vendor = (int)strtol(vendor_str, NULL, 16); + if ((strlen(&line[4])) == 0) { + chip_str[0] = '\0'; + chip = -1; + } else { + /* Handle trailing whitespace */ + if (isspace(line[4])) { + chip_str[0] = '\0'; + chip = -1; + } else { + /* Ok, it's a real ID */ + strncpy(chip_str, &line[4], 4); + chip_str[4] = '\0'; + chip = (int)strtol(chip_str, NULL, 16); + } + } + if (vendor == match_vendor && chip == match_chip ) { + i = 0; + while (matches[i]) { + i++; + } + matches[i] = (char*)malloc(sizeof(char) * strlen(direntry->d_name) - 3); + if (!matches[i]) { + xf86Msg(X_ERROR, "Could not allocate space for the module name. Exiting.\n"); + goto end; + } + /* hack off the .ids suffix. This should guard + * against other problems, but it will end up + * taking off anything after the first '.' */ + for (j = 0; j < (strlen(direntry->d_name) - 3) ; j++) { + if (direntry->d_name[j] == '.') { + matches[i][j] = '\0'; + break; + } else { + matches[i][j] = direntry->d_name[j]; + } + } + xf86Msg(X_INFO, "Matched %s from file name %s\n", matches[i], direntry->d_name); + } + } else { + /* TODO Handle driver overrides here */ + } + } + fclose(fp); + } + direntry = readdir(idsdir); + } + end: + free(line); + closedir(idsdir); +} +#endif /* __linux__ */ + +static void +listPossibleVideoDrivers(char *matches[], int nmatches) +{ + struct pci_device * info = NULL; + struct pci_device_iterator *iter; + int i; + + for (i = 0 ; i < nmatches ; i++) { + matches[i] = NULL; + } + i = 0; + +#ifdef sun + /* Check for driver type based on /dev/fb type and if valid, use + it instead of PCI bus probe results */ + if (xf86Info.consoleFd >= 0) { + struct vis_identifier visid; + const char *cp; + extern char xf86SolarisFbDev[PATH_MAX]; + int iret; + + SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid)); + if (iret < 0) { + int fbfd; + + fbfd = open(xf86SolarisFbDev, O_RDONLY); + if (fbfd >= 0) { + SYSCALL(iret = ioctl(fbfd, VIS_GETIDENTIFIER, &visid)); + close(fbfd); + } + } + + if (iret < 0) { + xf86Msg(X_WARNING, + "could not get frame buffer identifier from %s\n", + xf86SolarisFbDev); + } else { + xf86Msg(X_PROBED, "console driver: %s\n", visid.name); + + /* Special case from before the general case was set */ + if (strcmp(visid.name, "NVDAnvda") == 0) { + matches[i++] = xnfstrdup("nvidia"); + } + + /* General case - split into vendor name (initial all-caps + prefix) & driver name (rest of the string). */ + if (strcmp(visid.name, "SUNWtext") != 0) { + for (cp = visid.name; (*cp != '\0') && isupper(*cp); cp++) { + /* find end of all uppercase vendor section */ + } + if ((cp != visid.name) && (*cp != '\0')) { + char *driverName = xnfstrdup(cp); + char *vendorName = xnfstrdup(visid.name); + vendorName[cp - visid.name] = '\0'; + + matches[i++] = vendorName; + matches[i++] = driverName; + } + } + } + } +#endif +#ifdef __sparc__ + { + char *sbusDriver = sparcDriverName(); + if (sbusDriver) + matches[i++] = xnfstrdup(sbusDriver); + } +#endif + + /* Find the primary device, and get some information about it. */ + iter = pci_slot_match_iterator_create(NULL); + while ((info = pci_device_next(iter)) != NULL) { + if (xf86IsPrimaryPci(info)) { + break; + } + } + + pci_iterator_destroy(iter); + + if (!info) { + ErrorF("Primary device is not PCI\n"); + } +#ifdef __linux__ + else { + matchDriverFromFiles(matches, info->vendor_id, info->device_id); + } +#endif /* __linux__ */ + + for (i = 0; (i < nmatches) && (matches[i]); i++) { + /* find end of matches list */ + } + + if ((info != NULL) && (i < nmatches)) { + i += videoPtrToDriverList(info, &(matches[i]), nmatches - i); + } + + /* Fallback to platform default hardware */ + if (i < (nmatches - 1)) { +#if defined(__i386__) || defined(__amd64__) || defined(__hurd__) + matches[i++] = xnfstrdup("vesa"); +#elif defined(__sparc__) && !defined(sun) + matches[i++] = xnfstrdup("sunffb"); +#endif + } + + /* Fallback to platform default frame buffer driver */ + if (i < (nmatches - 1)) { +#if !defined(__linux__) && defined(__sparc__) + matches[i++] = xnfstrdup("wsfb"); +#else + matches[i++] = xnfstrdup("fbdev"); +#endif + } +} + +/* copy a screen section and enter the desired driver + * and insert it at i in the list of screens */ +static Bool +copyScreen(confScreenPtr oscreen, GDevPtr odev, int i, char *driver) +{ + GDevPtr cptr = NULL; + + xf86ConfigLayout.screens[i].screen = xnfcalloc(1, sizeof(confScreenRec)); + if(!xf86ConfigLayout.screens[i].screen) + return FALSE; + memcpy(xf86ConfigLayout.screens[i].screen, oscreen, sizeof(confScreenRec)); + + cptr = calloc(1, sizeof(GDevRec)); + if (!cptr) + return FALSE; + memcpy(cptr, odev, sizeof(GDevRec)); + + cptr->identifier = Xprintf("Autoconfigured Video Device %s", driver); + cptr->driver = driver; + + /* now associate the new driver entry with the new screen entry */ + xf86ConfigLayout.screens[i].screen->device = cptr; + cptr->myScreenSection = xf86ConfigLayout.screens[i].screen; + + return TRUE; +} + +GDevPtr +autoConfigDevice(GDevPtr preconf_device) +{ + GDevPtr ptr = NULL; + char *matches[20]; /* If we have more than 20 drivers we're in trouble */ + int num_matches = 0, num_screens = 0, i; + screenLayoutPtr slp; + + if (!xf86configptr) { + return NULL; + } + + /* If there's a configured section with no driver chosen, use it */ + if (preconf_device) { + ptr = preconf_device; + } else { + ptr = calloc(1, sizeof(GDevRec)); + if (!ptr) { + return NULL; + } + ptr->chipID = -1; + ptr->chipRev = -1; + ptr->irq = -1; + + ptr->active = TRUE; + ptr->claimed = FALSE; + ptr->identifier = "Autoconfigured Video Device"; + ptr->driver = NULL; + } + if (!ptr->driver) { + /* get all possible video drivers and count them */ + listPossibleVideoDrivers(matches, 20); + for (; matches[num_matches]; num_matches++) { + xf86Msg(X_DEFAULT, "Matched %s as autoconfigured driver %d\n", + matches[num_matches], num_matches); + } + + slp = xf86ConfigLayout.screens; + if (slp) { + /* count the number of screens and make space for + * a new screen for each additional possible driver + * minus one for the already existing first one + * plus one for the terminating NULL */ + for (; slp[num_screens].screen; num_screens++); + xf86ConfigLayout.screens = xnfcalloc(num_screens + num_matches, + sizeof(screenLayoutRec)); + xf86ConfigLayout.screens[0] = slp[0]; + + /* do the first match and set that for the original first screen */ + ptr->driver = matches[0]; + if (!xf86ConfigLayout.screens[0].screen->device) { + xf86ConfigLayout.screens[0].screen->device = ptr; + ptr->myScreenSection = xf86ConfigLayout.screens[0].screen; + } + + /* for each other driver found, copy the first screen, insert it + * into the list of screens and set the driver */ + i = 0; + while (i++ < num_matches) { + if (!copyScreen(slp[0].screen, ptr, i, matches[i])) + return NULL; + } + + /* shift the rest of the original screen list + * to the end of the current screen list + * + * TODO Handle rest of multiple screen sections */ + for (i = 1; i < num_screens; i++) { + xf86ConfigLayout.screens[i+num_matches] = slp[i]; + } + xf86ConfigLayout.screens[num_screens+num_matches-1].screen = NULL; + free(slp); + } else { + /* layout does not have any screens, not much to do */ + ptr->driver = matches[0]; + for (i = 1; matches[i] ; i++) { + if (matches[i] != matches[0]) { + free(matches[i]); + } + } + } + } + + xf86Msg(X_DEFAULT, "Assigned the driver to the xf86ConfigLayout\n"); + + return ptr; +} diff --git a/xorg-server/hw/xfree86/common/xf86Bus.c b/xorg-server/hw/xfree86/common/xf86Bus.c index 9d243c172..5c1668644 100644 --- a/xorg-server/hw/xfree86/common/xf86Bus.c +++ b/xorg-server/hw/xfree86/common/xf86Bus.c @@ -1,683 +1,683 @@ -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * This file contains the interfaces to the bus-specific code - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include "os.h" -#include "xf86.h" -#include "xf86Priv.h" - -/* Bus-specific headers */ - -#include "xf86Bus.h" - -#define XF86_OS_PRIVS -#include "xf86_OSproc.h" -#include "xf86VGAarbiter.h" - -#include "Pci.h" - -/* Entity data */ -EntityPtr *xf86Entities = NULL; /* Bus slots claimed by drivers */ -int xf86NumEntities = 0; -static int xf86EntityPrivateCount = 0; - -BusRec primaryBus = { BUS_NONE, { 0 } }; - -static Bool xf86ResAccessEnter = FALSE; - -static Bool doFramebufferMode = FALSE; - -/* - * Call the bus probes relevant to the architecture. - * - * The only one available so far is for PCI and SBUS. - */ - -void -xf86BusProbe(void) -{ - xf86PciProbe(); -#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) - xf86SbusProbe(); -#endif -} - -/* - * Determine what bus type the busID string represents. The start of the - * bus-dependent part of the string is returned as retID. - */ - -BusType -StringToBusType(const char* busID, const char **retID) -{ - char *p, *s; - BusType ret = BUS_NONE; - - /* If no type field, Default to PCI */ - if (isdigit(busID[0])) { - if (retID) - *retID = busID; - return BUS_PCI; - } - - s = xstrdup(busID); - p = strtok(s, ":"); - if (p == NULL || *p == 0) { - xfree(s); - return BUS_NONE; - } - if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp")) - ret = BUS_PCI; - if (!xf86NameCmp(p, "sbus")) - ret = BUS_SBUS; - if (ret != BUS_NONE) - if (retID) - *retID = busID + strlen(p) + 1; - xfree(s); - return ret; -} - -/* - * Entity related code. - */ - -void -xf86EntityInit(void) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) - if (xf86Entities[i]->entityInit) { - xf86Entities[i]->entityInit(i,xf86Entities[i]->private); - } -} - -int -xf86AllocateEntity(void) -{ - xf86NumEntities++; - xf86Entities = xnfrealloc(xf86Entities, - sizeof(EntityPtr) * xf86NumEntities); - xf86Entities[xf86NumEntities - 1] = xnfcalloc(1,sizeof(EntityRec)); - xf86Entities[xf86NumEntities - 1]->entityPrivates = - xnfcalloc(sizeof(DevUnion) * xf86EntityPrivateCount, 1); - return (xf86NumEntities - 1); -} - -static void -EntityEnter(void) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) - if (xf86Entities[i]->entityEnter) { - xf86Entities[i]->entityEnter(i,xf86Entities[i]->private); - } -} - -static void -EntityLeave(void) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) - if (xf86Entities[i]->entityLeave) { - xf86Entities[i]->entityLeave(i,xf86Entities[i]->private); - } -} - -Bool -xf86IsEntityPrimary(int entityIndex) -{ - EntityPtr pEnt = xf86Entities[entityIndex]; - - if (primaryBus.type != pEnt->bus.type) return FALSE; - - switch (pEnt->bus.type) { - case BUS_PCI: - return (pEnt->bus.id.pci == primaryBus.id.pci); - case BUS_SBUS: - return (pEnt->bus.id.sbus.fbNum == primaryBus.id.sbus.fbNum); - default: - return FALSE; - } -} - -Bool -xf86SetEntityFuncs(int entityIndex, EntityProc init, EntityProc enter, - EntityProc leave, pointer private) -{ - if (entityIndex >= xf86NumEntities) - return FALSE; - xf86Entities[entityIndex]->entityInit = init; - xf86Entities[entityIndex]->entityEnter = enter; - xf86Entities[entityIndex]->entityLeave = leave; - xf86Entities[entityIndex]->private = private; - return TRUE; -} - -Bool -xf86DriverHasEntities(DriverPtr drvp) -{ - int i; - for (i = 0; i < xf86NumEntities; i++) { - if (xf86Entities[i]->driver == drvp) - return TRUE; - } - return FALSE; -} - -void -xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex) -{ - if (entityIndex == -1) - return; - if (xf86Entities[entityIndex]->inUse && - !(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL)) { - ErrorF("Requested Entity already in use!\n"); - return; - } - - pScrn->numEntities++; - pScrn->entityList = xnfrealloc(pScrn->entityList, - pScrn->numEntities * sizeof(int)); - pScrn->entityList[pScrn->numEntities - 1] = entityIndex; - xf86Entities[entityIndex]->inUse = TRUE; - pScrn->entityInstanceList = xnfrealloc(pScrn->entityInstanceList, - pScrn->numEntities * sizeof(int)); - pScrn->entityInstanceList[pScrn->numEntities - 1] = 0; - pScrn->domainIOBase = xf86Entities[entityIndex]->domainIO; -} - -void -xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, int instance) -{ - int i; - - if (entityIndex == -1 || entityIndex >= xf86NumEntities) - return; - - for (i = 0; i < pScrn->numEntities; i++) { - if (pScrn->entityList[i] == entityIndex) { - pScrn->entityInstanceList[i] = instance; - break; - } - } -} - -/* - * XXX This needs to be updated for the case where a single entity may have - * instances associated with more than one screen. - */ -ScrnInfoPtr -xf86FindScreenForEntity(int entityIndex) -{ - int i,j; - - if (entityIndex == -1) return NULL; - - if (xf86Screens) { - for (i = 0; i < xf86NumScreens; i++) { - for (j = 0; j < xf86Screens[i]->numEntities; j++) { - if ( xf86Screens[i]->entityList[j] == entityIndex ) - return (xf86Screens[i]); - } - } - } - return NULL; -} - -void -xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex) -{ - int i; - - for (i = 0; i < pScrn->numEntities; i++) { - if (pScrn->entityList[i] == entityIndex) { - for (i++; i < pScrn->numEntities; i++) - pScrn->entityList[i-1] = pScrn->entityList[i]; - pScrn->numEntities--; - xf86Entities[entityIndex]->inUse = FALSE; - break; - } - } -} - -/* - * xf86ClearEntitiesForScreen() - called when a screen is deleted - * to mark it's entities unused. Called by xf86DeleteScreen(). - */ -void -xf86ClearEntityListForScreen(int scrnIndex) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - int i, entityIndex; - - if (pScrn->entityList == NULL || pScrn->numEntities == 0) return; - - for (i = 0; i < pScrn->numEntities; i++) { - entityIndex = pScrn->entityList[i]; - xf86Entities[entityIndex]->inUse = FALSE; - /* disable resource: call the disable function */ - } - xfree(pScrn->entityList); - xfree(pScrn->entityInstanceList); - pScrn->entityList = NULL; - pScrn->entityInstanceList = NULL; -} - -/* - * Add an extra device section (GDevPtr) to an entity. - */ - -void -xf86AddDevToEntity(int entityIndex, GDevPtr dev) -{ - EntityPtr pEnt; - - if (entityIndex >= xf86NumEntities) - return; - - pEnt = xf86Entities[entityIndex]; - pEnt->numInstances++; - pEnt->devices = xnfrealloc(pEnt->devices, - pEnt->numInstances * sizeof(GDevPtr)); - pEnt->devices[pEnt->numInstances - 1] = dev; - dev->claimed = TRUE; -} - -/* - * xf86GetEntityInfo() -- This function hands information from the - * EntityRec struct to the drivers. The EntityRec structure itself - * remains invisible to the driver. - */ -EntityInfoPtr -xf86GetEntityInfo(int entityIndex) -{ - EntityInfoPtr pEnt; - int i; - - if (entityIndex == -1) - return NULL; - - if (entityIndex >= xf86NumEntities) - return NULL; - - pEnt = xnfcalloc(1,sizeof(EntityInfoRec)); - pEnt->index = entityIndex; - pEnt->location = xf86Entities[entityIndex]->bus; - pEnt->active = xf86Entities[entityIndex]->active; - pEnt->chipset = xf86Entities[entityIndex]->chipset; - pEnt->driver = xf86Entities[entityIndex]->driver; - if ( (xf86Entities[entityIndex]->devices) && - (xf86Entities[entityIndex]->devices[0]) ) { - for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++) - if (xf86Entities[entityIndex]->devices[i]->screen == 0) - break; - pEnt->device = xf86Entities[entityIndex]->devices[i]; - } else - pEnt->device = NULL; - - return pEnt; -} - -int -xf86GetNumEntityInstances(int entityIndex) -{ - if (entityIndex >= xf86NumEntities) - return -1; - - return xf86Entities[entityIndex]->numInstances; -} - -GDevPtr -xf86GetDevFromEntity(int entityIndex, int instance) -{ - int i; - - /* We might not use AddDevtoEntity */ - if ( (!xf86Entities[entityIndex]->devices) || - (!xf86Entities[entityIndex]->devices[0]) ) - return NULL; - - if (entityIndex >= xf86NumEntities || - instance >= xf86Entities[entityIndex]->numInstances) - return NULL; - - for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++) - if (xf86Entities[entityIndex]->devices[i]->screen == instance) - break; - return xf86Entities[entityIndex]->devices[i]; -} - -/* - * xf86AccessInit() - set up everything needed for access control - * called only once on first server generation. - */ -void -xf86AccessInit(void) -{ - xf86ResAccessEnter = TRUE; -} - -/* - * xf86AccessEnter() -- gets called to save the text mode VGA IO - * resources when reentering the server after a VT switch. - */ -void -xf86AccessEnter(void) -{ - if (xf86ResAccessEnter) - return; - - /* - * on enter we simply disable routing of special resources - * to any bus and let the RAC code to "open" the right bridges. - */ - EntityEnter(); - xf86EnterServerState(SETUP); - xf86ResAccessEnter = TRUE; -} - -/* - * xf86AccessLeave() -- prepares access for and calls the - * entityLeave() functions. - * xf86AccessLeaveState() --- gets called to restore the - * access to the VGA IO resources when switching VT or on - * server exit. - * This was split to call xf86AccessLeaveState() from - * ddxGiveUp(). - */ -void -xf86AccessLeave(void) -{ - if (!xf86ResAccessEnter) - return; - EntityLeave(); -} - -/* - * xf86EnableAccess() -- enable access to controlled resources. - * To reduce latency when switching access the ScrnInfoRec has - * a linked list of the EntityAccPtr of all screen entities. - */ -/* - * switching access needs to be done in te following oder: - * disable - * 1. disable old entity - * 2. reroute bus - * 3. enable new entity - * Otherwise resources needed for access control might be shadowed - * by other resources! - */ - -void -xf86EnableAccess(ScrnInfoPtr pScrn) -{ - DebugF("Enable access %i\n",pScrn->scrnIndex); - - return; -} - -/* - * xf86EnterServerState() -- set state the server is in. - */ - -typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState; - -static void -SetSIGIOForState(xf86State state) -{ - static int sigio_state; - static TriState sigio_blocked = TRI_UNSET; - - if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) { - sigio_state = xf86BlockSIGIO(); - sigio_blocked = TRI_TRUE; - } else if ((state == OPERATING) && (sigio_blocked != TRI_UNSET)) { - xf86UnblockSIGIO(sigio_state); - sigio_blocked = TRI_FALSE; - } -} - -void -xf86EnterServerState(xf86State state) -{ - /* - * This is a good place to block SIGIO during SETUP state. - * SIGIO should be blocked in SETUP state otherwise (u)sleep() - * might get interrupted early. - * We take care not to call xf86BlockSIGIO() twice. - */ - SetSIGIOForState(state); - if (state == SETUP) - DebugF("Entering SETUP state\n"); - else - DebugF("Entering OPERATING state\n"); - - return; -} - -/* - * xf86PostProbe() -- Allocate all non conflicting resources - * This function gets called by xf86Init(). - */ -void -xf86PostProbe(void) -{ - if (fbSlotClaimed) { - if (pciSlotClaimed -#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) - || sbusSlotClaimed -#endif - ) { - FatalError("Cannot run in framebuffer mode. Please specify busIDs " - " for all framebuffer devices\n"); - return; - } else { - xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n"); - doFramebufferMode = TRUE; - - return; - } - } -} - -void -xf86PostScreenInit(void) -{ - if (doFramebufferMode) { - SetSIGIOForState(OPERATING); - return; - } - - xf86VGAarbiterWrapFunctions(); - - DebugF("PostScreenInit generation: %i\n",serverGeneration); - xf86EnterServerState(OPERATING); -} - -/* - * xf86FindPrimaryDevice() - Find the display device which - * was active when the server was started. - */ -void -xf86FindPrimaryDevice(void) -{ - if (primaryBus.type != BUS_NONE) { - char *bus; - char loc[16]; - - switch (primaryBus.type) { - case BUS_PCI: - bus = "PCI"; - snprintf(loc, sizeof(loc), " %2.2x@%2.2x:%2.2x:%1.1x", - primaryBus.id.pci->bus, - primaryBus.id.pci->domain, - primaryBus.id.pci->dev, - primaryBus.id.pci->func); - break; - case BUS_SBUS: - bus = "SBUS"; - snprintf(loc, sizeof(loc), " %2.2x", primaryBus.id.sbus.fbNum); - break; - default: - bus = ""; - loc[0] = '\0'; - } - - xf86MsgVerb(X_INFO, 2, "Primary Device is: %s%s\n",bus,loc); - } -} - -int -xf86GetLastScrnFlag(int entityIndex) -{ - if(entityIndex < xf86NumEntities) { - return(xf86Entities[entityIndex]->lastScrnFlag); - } else { - return -1; - } -} - -void -xf86SetLastScrnFlag(int entityIndex, int scrnIndex) -{ - if(entityIndex < xf86NumEntities) { - xf86Entities[entityIndex]->lastScrnFlag = scrnIndex; - } -} - -Bool -xf86IsEntityShared(int entityIndex) -{ - if(entityIndex < xf86NumEntities) { - if(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) { - return TRUE; - } - } - return FALSE; -} - -void -xf86SetEntityShared(int entityIndex) -{ - if(entityIndex < xf86NumEntities) { - xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL; - } -} - -Bool -xf86IsEntitySharable(int entityIndex) -{ - if(entityIndex < xf86NumEntities) { - if(xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) { - return TRUE; - } - } - return FALSE; -} - -void -xf86SetEntitySharable(int entityIndex) -{ - if(entityIndex < xf86NumEntities) { - xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE; - } -} - -Bool -xf86IsPrimInitDone(int entityIndex) -{ - if(entityIndex < xf86NumEntities) { - if(xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) { - return TRUE; - } - } - return FALSE; -} - -void -xf86SetPrimInitDone(int entityIndex) -{ - if(entityIndex < xf86NumEntities) { - xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE; - } -} - -void -xf86ClearPrimInitDone(int entityIndex) -{ - if(entityIndex < xf86NumEntities) { - xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE; - } -} - - -/* - * Allocate a private in the entities. - */ - -int -xf86AllocateEntityPrivateIndex(void) -{ - int idx, i; - EntityPtr pEnt; - DevUnion *nprivs; - - idx = xf86EntityPrivateCount++; - for (i = 0; i < xf86NumEntities; i++) { - pEnt = xf86Entities[i]; - nprivs = xnfrealloc(pEnt->entityPrivates, - xf86EntityPrivateCount * sizeof(DevUnion)); - /* Zero the new private */ - bzero(&nprivs[idx], sizeof(DevUnion)); - pEnt->entityPrivates = nprivs; - } - return idx; -} - -DevUnion * -xf86GetEntityPrivate(int entityIndex, int privIndex) -{ - if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount) - return NULL; - - return &(xf86Entities[entityIndex]->entityPrivates[privIndex]); -} - +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * This file contains the interfaces to the bus-specific code + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "os.h" +#include "xf86.h" +#include "xf86Priv.h" + +/* Bus-specific headers */ + +#include "xf86Bus.h" + +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" +#include "xf86VGAarbiter.h" + +#include "Pci.h" + +/* Entity data */ +EntityPtr *xf86Entities = NULL; /* Bus slots claimed by drivers */ +int xf86NumEntities = 0; +static int xf86EntityPrivateCount = 0; + +BusRec primaryBus = { BUS_NONE, { 0 } }; + +static Bool xf86ResAccessEnter = FALSE; + +static Bool doFramebufferMode = FALSE; + +/* + * Call the bus probes relevant to the architecture. + * + * The only one available so far is for PCI and SBUS. + */ + +void +xf86BusProbe(void) +{ + xf86PciProbe(); +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + xf86SbusProbe(); +#endif +} + +/* + * Determine what bus type the busID string represents. The start of the + * bus-dependent part of the string is returned as retID. + */ + +BusType +StringToBusType(const char* busID, const char **retID) +{ + char *p, *s; + BusType ret = BUS_NONE; + + /* If no type field, Default to PCI */ + if (isdigit(busID[0])) { + if (retID) + *retID = busID; + return BUS_PCI; + } + + s = xstrdup(busID); + p = strtok(s, ":"); + if (p == NULL || *p == 0) { + free(s); + return BUS_NONE; + } + if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp")) + ret = BUS_PCI; + if (!xf86NameCmp(p, "sbus")) + ret = BUS_SBUS; + if (ret != BUS_NONE) + if (retID) + *retID = busID + strlen(p) + 1; + free(s); + return ret; +} + +/* + * Entity related code. + */ + +void +xf86EntityInit(void) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityInit) { + xf86Entities[i]->entityInit(i,xf86Entities[i]->private); + } +} + +int +xf86AllocateEntity(void) +{ + xf86NumEntities++; + xf86Entities = xnfrealloc(xf86Entities, + sizeof(EntityPtr) * xf86NumEntities); + xf86Entities[xf86NumEntities - 1] = xnfcalloc(1,sizeof(EntityRec)); + xf86Entities[xf86NumEntities - 1]->entityPrivates = + xnfcalloc(sizeof(DevUnion) * xf86EntityPrivateCount, 1); + return (xf86NumEntities - 1); +} + +static void +EntityEnter(void) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityEnter) { + xf86Entities[i]->entityEnter(i,xf86Entities[i]->private); + } +} + +static void +EntityLeave(void) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) + if (xf86Entities[i]->entityLeave) { + xf86Entities[i]->entityLeave(i,xf86Entities[i]->private); + } +} + +Bool +xf86IsEntityPrimary(int entityIndex) +{ + EntityPtr pEnt = xf86Entities[entityIndex]; + + if (primaryBus.type != pEnt->bus.type) return FALSE; + + switch (pEnt->bus.type) { + case BUS_PCI: + return (pEnt->bus.id.pci == primaryBus.id.pci); + case BUS_SBUS: + return (pEnt->bus.id.sbus.fbNum == primaryBus.id.sbus.fbNum); + default: + return FALSE; + } +} + +Bool +xf86SetEntityFuncs(int entityIndex, EntityProc init, EntityProc enter, + EntityProc leave, pointer private) +{ + if (entityIndex >= xf86NumEntities) + return FALSE; + xf86Entities[entityIndex]->entityInit = init; + xf86Entities[entityIndex]->entityEnter = enter; + xf86Entities[entityIndex]->entityLeave = leave; + xf86Entities[entityIndex]->private = private; + return TRUE; +} + +Bool +xf86DriverHasEntities(DriverPtr drvp) +{ + int i; + for (i = 0; i < xf86NumEntities; i++) { + if (xf86Entities[i]->driver == drvp) + return TRUE; + } + return FALSE; +} + +void +xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex) +{ + if (entityIndex == -1) + return; + if (xf86Entities[entityIndex]->inUse && + !(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL)) { + ErrorF("Requested Entity already in use!\n"); + return; + } + + pScrn->numEntities++; + pScrn->entityList = xnfrealloc(pScrn->entityList, + pScrn->numEntities * sizeof(int)); + pScrn->entityList[pScrn->numEntities - 1] = entityIndex; + xf86Entities[entityIndex]->inUse = TRUE; + pScrn->entityInstanceList = xnfrealloc(pScrn->entityInstanceList, + pScrn->numEntities * sizeof(int)); + pScrn->entityInstanceList[pScrn->numEntities - 1] = 0; + pScrn->domainIOBase = xf86Entities[entityIndex]->domainIO; +} + +void +xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, int instance) +{ + int i; + + if (entityIndex == -1 || entityIndex >= xf86NumEntities) + return; + + for (i = 0; i < pScrn->numEntities; i++) { + if (pScrn->entityList[i] == entityIndex) { + pScrn->entityInstanceList[i] = instance; + break; + } + } +} + +/* + * XXX This needs to be updated for the case where a single entity may have + * instances associated with more than one screen. + */ +ScrnInfoPtr +xf86FindScreenForEntity(int entityIndex) +{ + int i,j; + + if (entityIndex == -1) return NULL; + + if (xf86Screens) { + for (i = 0; i < xf86NumScreens; i++) { + for (j = 0; j < xf86Screens[i]->numEntities; j++) { + if ( xf86Screens[i]->entityList[j] == entityIndex ) + return (xf86Screens[i]); + } + } + } + return NULL; +} + +void +xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex) +{ + int i; + + for (i = 0; i < pScrn->numEntities; i++) { + if (pScrn->entityList[i] == entityIndex) { + for (i++; i < pScrn->numEntities; i++) + pScrn->entityList[i-1] = pScrn->entityList[i]; + pScrn->numEntities--; + xf86Entities[entityIndex]->inUse = FALSE; + break; + } + } +} + +/* + * xf86ClearEntitiesForScreen() - called when a screen is deleted + * to mark it's entities unused. Called by xf86DeleteScreen(). + */ +void +xf86ClearEntityListForScreen(int scrnIndex) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + int i, entityIndex; + + if (pScrn->entityList == NULL || pScrn->numEntities == 0) return; + + for (i = 0; i < pScrn->numEntities; i++) { + entityIndex = pScrn->entityList[i]; + xf86Entities[entityIndex]->inUse = FALSE; + /* disable resource: call the disable function */ + } + free(pScrn->entityList); + free(pScrn->entityInstanceList); + pScrn->entityList = NULL; + pScrn->entityInstanceList = NULL; +} + +/* + * Add an extra device section (GDevPtr) to an entity. + */ + +void +xf86AddDevToEntity(int entityIndex, GDevPtr dev) +{ + EntityPtr pEnt; + + if (entityIndex >= xf86NumEntities) + return; + + pEnt = xf86Entities[entityIndex]; + pEnt->numInstances++; + pEnt->devices = xnfrealloc(pEnt->devices, + pEnt->numInstances * sizeof(GDevPtr)); + pEnt->devices[pEnt->numInstances - 1] = dev; + dev->claimed = TRUE; +} + +/* + * xf86GetEntityInfo() -- This function hands information from the + * EntityRec struct to the drivers. The EntityRec structure itself + * remains invisible to the driver. + */ +EntityInfoPtr +xf86GetEntityInfo(int entityIndex) +{ + EntityInfoPtr pEnt; + int i; + + if (entityIndex == -1) + return NULL; + + if (entityIndex >= xf86NumEntities) + return NULL; + + pEnt = xnfcalloc(1,sizeof(EntityInfoRec)); + pEnt->index = entityIndex; + pEnt->location = xf86Entities[entityIndex]->bus; + pEnt->active = xf86Entities[entityIndex]->active; + pEnt->chipset = xf86Entities[entityIndex]->chipset; + pEnt->driver = xf86Entities[entityIndex]->driver; + if ( (xf86Entities[entityIndex]->devices) && + (xf86Entities[entityIndex]->devices[0]) ) { + for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++) + if (xf86Entities[entityIndex]->devices[i]->screen == 0) + break; + pEnt->device = xf86Entities[entityIndex]->devices[i]; + } else + pEnt->device = NULL; + + return pEnt; +} + +int +xf86GetNumEntityInstances(int entityIndex) +{ + if (entityIndex >= xf86NumEntities) + return -1; + + return xf86Entities[entityIndex]->numInstances; +} + +GDevPtr +xf86GetDevFromEntity(int entityIndex, int instance) +{ + int i; + + /* We might not use AddDevtoEntity */ + if ( (!xf86Entities[entityIndex]->devices) || + (!xf86Entities[entityIndex]->devices[0]) ) + return NULL; + + if (entityIndex >= xf86NumEntities || + instance >= xf86Entities[entityIndex]->numInstances) + return NULL; + + for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++) + if (xf86Entities[entityIndex]->devices[i]->screen == instance) + break; + return xf86Entities[entityIndex]->devices[i]; +} + +/* + * xf86AccessInit() - set up everything needed for access control + * called only once on first server generation. + */ +void +xf86AccessInit(void) +{ + xf86ResAccessEnter = TRUE; +} + +/* + * xf86AccessEnter() -- gets called to save the text mode VGA IO + * resources when reentering the server after a VT switch. + */ +void +xf86AccessEnter(void) +{ + if (xf86ResAccessEnter) + return; + + /* + * on enter we simply disable routing of special resources + * to any bus and let the RAC code to "open" the right bridges. + */ + EntityEnter(); + xf86EnterServerState(SETUP); + xf86ResAccessEnter = TRUE; +} + +/* + * xf86AccessLeave() -- prepares access for and calls the + * entityLeave() functions. + * xf86AccessLeaveState() --- gets called to restore the + * access to the VGA IO resources when switching VT or on + * server exit. + * This was split to call xf86AccessLeaveState() from + * ddxGiveUp(). + */ +void +xf86AccessLeave(void) +{ + if (!xf86ResAccessEnter) + return; + EntityLeave(); +} + +/* + * xf86EnableAccess() -- enable access to controlled resources. + * To reduce latency when switching access the ScrnInfoRec has + * a linked list of the EntityAccPtr of all screen entities. + */ +/* + * switching access needs to be done in te following oder: + * disable + * 1. disable old entity + * 2. reroute bus + * 3. enable new entity + * Otherwise resources needed for access control might be shadowed + * by other resources! + */ + +void +xf86EnableAccess(ScrnInfoPtr pScrn) +{ + DebugF("Enable access %i\n",pScrn->scrnIndex); + + return; +} + +/* + * xf86EnterServerState() -- set state the server is in. + */ + +typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState; + +static void +SetSIGIOForState(xf86State state) +{ + static int sigio_state; + static TriState sigio_blocked = TRI_UNSET; + + if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) { + sigio_state = xf86BlockSIGIO(); + sigio_blocked = TRI_TRUE; + } else if ((state == OPERATING) && (sigio_blocked != TRI_UNSET)) { + xf86UnblockSIGIO(sigio_state); + sigio_blocked = TRI_FALSE; + } +} + +void +xf86EnterServerState(xf86State state) +{ + /* + * This is a good place to block SIGIO during SETUP state. + * SIGIO should be blocked in SETUP state otherwise (u)sleep() + * might get interrupted early. + * We take care not to call xf86BlockSIGIO() twice. + */ + SetSIGIOForState(state); + if (state == SETUP) + DebugF("Entering SETUP state\n"); + else + DebugF("Entering OPERATING state\n"); + + return; +} + +/* + * xf86PostProbe() -- Allocate all non conflicting resources + * This function gets called by xf86Init(). + */ +void +xf86PostProbe(void) +{ + if (fbSlotClaimed) { + if (pciSlotClaimed +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + || sbusSlotClaimed +#endif + ) { + FatalError("Cannot run in framebuffer mode. Please specify busIDs " + " for all framebuffer devices\n"); + return; + } else { + xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n"); + doFramebufferMode = TRUE; + + return; + } + } +} + +void +xf86PostScreenInit(void) +{ + if (doFramebufferMode) { + SetSIGIOForState(OPERATING); + return; + } + + xf86VGAarbiterWrapFunctions(); + + DebugF("PostScreenInit generation: %i\n",serverGeneration); + xf86EnterServerState(OPERATING); +} + +/* + * xf86FindPrimaryDevice() - Find the display device which + * was active when the server was started. + */ +void +xf86FindPrimaryDevice(void) +{ + if (primaryBus.type != BUS_NONE) { + char *bus; + char loc[16]; + + switch (primaryBus.type) { + case BUS_PCI: + bus = "PCI"; + snprintf(loc, sizeof(loc), " %2.2x@%2.2x:%2.2x:%1.1x", + primaryBus.id.pci->bus, + primaryBus.id.pci->domain, + primaryBus.id.pci->dev, + primaryBus.id.pci->func); + break; + case BUS_SBUS: + bus = "SBUS"; + snprintf(loc, sizeof(loc), " %2.2x", primaryBus.id.sbus.fbNum); + break; + default: + bus = ""; + loc[0] = '\0'; + } + + xf86MsgVerb(X_INFO, 2, "Primary Device is: %s%s\n",bus,loc); + } +} + +int +xf86GetLastScrnFlag(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + return(xf86Entities[entityIndex]->lastScrnFlag); + } else { + return -1; + } +} + +void +xf86SetLastScrnFlag(int entityIndex, int scrnIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->lastScrnFlag = scrnIndex; + } +} + +Bool +xf86IsEntityShared(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + if(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) { + return TRUE; + } + } + return FALSE; +} + +void +xf86SetEntityShared(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL; + } +} + +Bool +xf86IsEntitySharable(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + if(xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) { + return TRUE; + } + } + return FALSE; +} + +void +xf86SetEntitySharable(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE; + } +} + +Bool +xf86IsPrimInitDone(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + if(xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) { + return TRUE; + } + } + return FALSE; +} + +void +xf86SetPrimInitDone(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE; + } +} + +void +xf86ClearPrimInitDone(int entityIndex) +{ + if(entityIndex < xf86NumEntities) { + xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE; + } +} + + +/* + * Allocate a private in the entities. + */ + +int +xf86AllocateEntityPrivateIndex(void) +{ + int idx, i; + EntityPtr pEnt; + DevUnion *nprivs; + + idx = xf86EntityPrivateCount++; + for (i = 0; i < xf86NumEntities; i++) { + pEnt = xf86Entities[i]; + nprivs = xnfrealloc(pEnt->entityPrivates, + xf86EntityPrivateCount * sizeof(DevUnion)); + /* Zero the new private */ + bzero(&nprivs[idx], sizeof(DevUnion)); + pEnt->entityPrivates = nprivs; + } + return idx; +} + +DevUnion * +xf86GetEntityPrivate(int entityIndex, int privIndex) +{ + if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount) + return NULL; + + return &(xf86Entities[entityIndex]->entityPrivates[privIndex]); +} + diff --git a/xorg-server/hw/xfree86/common/xf86Config.c b/xorg-server/hw/xfree86/common/xf86Config.c index 9a2837e7b..33b38930f 100644 --- a/xorg-server/hw/xfree86/common/xf86Config.c +++ b/xorg-server/hw/xfree86/common/xf86Config.c @@ -1,2586 +1,2586 @@ -/* - * Loosely based on code bearing the following copyright: - * - * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. - */ - -/* - * Copyright 1992-2003 by The XFree86 Project, Inc. - * Copyright 1997 by Metro Link, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * - * Authors: - * Dirk Hohndel - * David Dawes - * Marc La France - * Egbert Eich - * ... and others - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#ifdef XF86DRI -#include -#include -#endif - -#include "xf86.h" -#include "xf86Parser.h" -#include "xf86tokens.h" -#include "xf86Config.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "configProcs.h" -#include "globals.h" -#include "extension.h" -#include "Pci.h" - -#include "xf86Xinput.h" -extern DeviceAssocRec mouse_assoc; - -#include "xkbsrv.h" - -#include "picture.h" - -/* - * These paths define the way the config file search is done. The escape - * sequences are documented in parser/scan.c. - */ -#ifndef ROOT_CONFIGPATH -#define ROOT_CONFIGPATH "%A," "%R," \ - "/etc/X11/%R," "%P/etc/X11/%R," \ - "%E," "%F," \ - "/etc/X11/%F," "%P/etc/X11/%F," \ - "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \ - "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \ - "%P/etc/X11/%X," \ - "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ - "%P/lib/X11/%X" -#endif -#ifndef USER_CONFIGPATH -#define USER_CONFIGPATH "/etc/X11/%S," "%P/etc/X11/%S," \ - "/etc/X11/%G," "%P/etc/X11/%G," \ - "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \ - "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \ - "%P/etc/X11/%X," \ - "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ - "%P/lib/X11/%X" -#endif -#ifndef ROOT_CONFIGDIRPATH -#define ROOT_CONFIGDIRPATH "%A," "%R," \ - "/etc/X11/%R," "%C/X11/%R," \ - "/etc/X11/%X," "%C/X11/%X" -#endif -#ifndef USER_CONFIGDIRPATH -#define USER_CONFIGDIRPATH "/etc/X11/%R," "%C/X11/%R," \ - "/etc/X11/%X," "%C/X11/%X" -#endif -#ifndef SYS_CONFIGDIRPATH -#define SYS_CONFIGDIRPATH "/usr/share/X11/%X," "%D/X11/%X" -#endif -#ifndef PROJECTROOT -#define PROJECTROOT "/usr/X11R6" -#endif - -static ModuleDefault ModuleDefaults[] = { - {.name = "extmod", .toLoad = TRUE, .load_opt=NULL}, -#ifdef DBE - {.name = "dbe", .toLoad = TRUE, .load_opt=NULL}, -#endif -#ifdef GLXEXT - {.name = "glx", .toLoad = TRUE, .load_opt=NULL}, -#endif -#ifdef XRECORD - {.name = "record", .toLoad = TRUE, .load_opt=NULL}, -#endif -#ifdef XF86DRI - {.name = "dri", .toLoad = TRUE, .load_opt=NULL}, -#endif -#ifdef DRI2 - {.name = "dri2", .toLoad = TRUE, .load_opt=NULL}, -#endif - {.name = NULL, .toLoad = FALSE, .load_opt=NULL} -}; - - -/* Forward declarations */ -static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, - int scrnum, MessageType from); -static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor); -static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, - Bool active); -static Bool configInput(IDevPtr inputp, XF86ConfInputPtr conf_input, - MessageType from); -static Bool configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display); -static Bool addDefaultModes(MonPtr monitorp); -#ifdef XF86DRI -static void configDRI(XF86ConfDRIPtr drip); -#endif -static void configExtensions(XF86ConfExtensionsPtr conf_ext); - -/* - * xf86GetPathElem -- - * Extract a single element from the font path string starting at - * pnt. The font path element will be returned, and pnt will be - * updated to point to the start of the next element, or set to - * NULL if there are no more. - */ -static char * -xf86GetPathElem(char **pnt) -{ - char *p1; - - p1 = *pnt; - *pnt = index(*pnt, ','); - if (*pnt != NULL) { - **pnt = '\0'; - *pnt += 1; - } - return(p1); -} - -/* - * xf86ValidateFontPath -- - * Validates the user-specified font path. Each element that - * begins with a '/' is checked to make sure the directory exists. - * If the directory exists, the existence of a file named 'fonts.dir' - * is checked. If either check fails, an error is printed and the - * element is removed from the font path. - */ - -#define DIR_FILE "/fonts.dir" -static char * -xf86ValidateFontPath(char *path) -{ - char *tmp_path, *out_pnt, *path_elem, *next, *p1, *dir_elem; - struct stat stat_buf; - int flag; - int dirlen; - - tmp_path = xcalloc(1,strlen(path)+1); - out_pnt = tmp_path; - path_elem = NULL; - next = path; - while (next != NULL) { - path_elem = xf86GetPathElem(&next); - if (*path_elem == '/') { - dir_elem = xnfcalloc(1, strlen(path_elem) + 1); - if ((p1 = strchr(path_elem, ':')) != 0) - dirlen = p1 - path_elem; - else - dirlen = strlen(path_elem); - strncpy(dir_elem, path_elem, dirlen); - dir_elem[dirlen] = '\0'; - flag = stat(dir_elem, &stat_buf); - if (flag == 0) - if (!S_ISDIR(stat_buf.st_mode)) - flag = -1; - if (flag != 0) { - xf86Msg(X_WARNING, "The directory \"%s\" does not exist.\n", dir_elem); - xf86ErrorF("\tEntry deleted from font path.\n"); - xfree(dir_elem); - continue; - } - else { - p1 = xnfalloc(strlen(dir_elem)+strlen(DIR_FILE)+1); - strcpy(p1, dir_elem); - strcat(p1, DIR_FILE); - flag = stat(p1, &stat_buf); - if (flag == 0) - if (!S_ISREG(stat_buf.st_mode)) - flag = -1; - xfree(p1); - if (flag != 0) { - xf86Msg(X_WARNING, - "`fonts.dir' not found (or not valid) in \"%s\".\n", - dir_elem); - xf86ErrorF("\tEntry deleted from font path.\n"); - xf86ErrorF("\t(Run 'mkfontdir' on \"%s\").\n", dir_elem); - xfree(dir_elem); - continue; - } - } - xfree(dir_elem); - } - - /* - * Either an OK directory, or a font server name. So add it to - * the path. - */ - if (out_pnt != tmp_path) - *out_pnt++ = ','; - strcat(out_pnt, path_elem); - out_pnt += strlen(path_elem); - } - return(tmp_path); -} - - -/* - * use the datastructure that the parser provides and pick out the parts - * that we need at this point - */ -char ** -xf86ModulelistFromConfig(pointer **optlist) -{ - int count = 0, i = 0; - char **modulearray; - char *ignore[] = { "GLcore", "speedo", "bitmap", "drm", - "freetype", "type1", - NULL }; - pointer *optarray; - XF86LoadPtr modp; - Bool found; - - /* - * make sure the config file has been parsed and that we have a - * ModulePath set; if no ModulePath was given, use the default - * ModulePath - */ - if (xf86configptr == NULL) { - xf86Msg(X_ERROR, "Cannot access global config data structure\n"); - return NULL; - } - - if (xf86configptr->conf_modules) { - /* Walk the disable list and let people know what we've parsed to - * not be loaded - */ - modp = xf86configptr->conf_modules->mod_disable_lst; - while (modp) { - xf86Msg(X_WARNING, "\"%s\" will not be loaded unless you've specified it to be loaded elsewhere.\n", modp->load_name); - modp = (XF86LoadPtr) modp->list.next; - } - /* - * Walk the default settings table. For each module listed to be - * loaded, make sure it's in the mod_load_lst. If it's not, make - * sure it's not in the mod_no_load_lst. If it's not disabled, - * append it to mod_load_lst - */ - for (i=0 ; ModuleDefaults[i].name != NULL ; i++) { - if (ModuleDefaults[i].toLoad == FALSE) { - xf86Msg(X_WARNING, "\"%s\" is not to be loaded by default. Skipping.\n", ModuleDefaults[i].name); - continue; - } - found = FALSE; - modp = xf86configptr->conf_modules->mod_load_lst; - while (modp) { - if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) { - xf86Msg(X_INFO, "\"%s\" will be loaded. This was enabled by default and also specified in the config file.\n", ModuleDefaults[i].name); - found = TRUE; - break; - } - modp = (XF86LoadPtr) modp->list.next; - } - if (found == FALSE) { - modp = xf86configptr->conf_modules->mod_disable_lst; - while (modp) { - if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) { - xf86Msg(X_INFO, "\"%s\" will be loaded even though the default is to disable it.\n", ModuleDefaults[i].name); - found = TRUE; - break; - } - modp = (XF86LoadPtr) modp->list.next; - } - } - if (found == FALSE) { - XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules; - ptr = xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt); - xf86Msg(X_INFO, "\"%s\" will be loaded by default.\n", ModuleDefaults[i].name); - } - } - } else { - xf86configptr->conf_modules = xnfcalloc(1, sizeof(XF86ConfModuleRec)); - for (i=0 ; ModuleDefaults[i].name != NULL ; i++) { - if (ModuleDefaults[i].toLoad == TRUE) { - XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules; - ptr = xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt); - } - } - } - - /* - * Walk the list of modules in the "Module" section to determine how - * many we have. - */ - modp = xf86configptr->conf_modules->mod_load_lst; - while (modp) { - for (i = 0; ignore[i]; i++) { - if (strcmp(modp->load_name, ignore[i]) == 0) - modp->ignore = 1; - } - if (!modp->ignore) - count++; - modp = (XF86LoadPtr) modp->list.next; - } - - /* - * allocate the memory and walk the list again to fill in the pointers - */ - modulearray = xnfalloc((count + 1) * sizeof(char*)); - optarray = xnfalloc((count + 1) * sizeof(pointer)); - count = 0; - if (xf86configptr->conf_modules) { - modp = xf86configptr->conf_modules->mod_load_lst; - while (modp) { - if (!modp->ignore) { - modulearray[count] = modp->load_name; - optarray[count] = modp->load_opt; - count++; - } - modp = (XF86LoadPtr) modp->list.next; - } - } - modulearray[count] = NULL; - optarray[count] = NULL; - if (optlist) - *optlist = optarray; - else - xfree(optarray); - return modulearray; -} - - -char ** -xf86DriverlistFromConfig(void) -{ - int count = 0; - int j; - char **modulearray; - screenLayoutPtr slp; - - /* - * make sure the config file has been parsed and that we have a - * ModulePath set; if no ModulePath was given, use the default - * ModulePath - */ - if (xf86configptr == NULL) { - xf86Msg(X_ERROR, "Cannot access global config data structure\n"); - return NULL; - } - - /* - * Walk the list of driver lines in active "Device" sections to - * determine now many implicitly loaded modules there are. - * - */ - if (xf86ConfigLayout.screens) { - slp = xf86ConfigLayout.screens; - while ((slp++)->screen) { - count++; - } - } - - /* - * Handle the set of inactive "Device" sections. - */ - j = 0; - while (xf86ConfigLayout.inactives[j++].identifier) - count++; - - if (count == 0) - return NULL; - - /* - * allocate the memory and walk the list again to fill in the pointers - */ - modulearray = xnfalloc((count + 1) * sizeof(char*)); - count = 0; - slp = xf86ConfigLayout.screens; - while (slp->screen) { - modulearray[count] = slp->screen->device->driver; - count++; - slp++; - } - - j = 0; - - while (xf86ConfigLayout.inactives[j].identifier) - modulearray[count++] = xf86ConfigLayout.inactives[j++].driver; - - modulearray[count] = NULL; - - /* Remove duplicates */ - for (count = 0; modulearray[count] != NULL; count++) { - int i; - - for (i = 0; i < count; i++) - if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { - modulearray[count] = ""; - break; - } - } - return modulearray; -} - -char ** -xf86InputDriverlistFromConfig(void) -{ - int count = 0; - char **modulearray; - IDevPtr* idp; - - /* - * make sure the config file has been parsed and that we have a - * ModulePath set; if no ModulePath was given, use the default - * ModulePath - */ - if (xf86configptr == NULL) { - xf86Msg(X_ERROR, "Cannot access global config data structure\n"); - return NULL; - } - - /* - * Walk the list of driver lines in active "InputDevice" sections to - * determine now many implicitly loaded modules there are. - */ - if (xf86ConfigLayout.inputs) { - idp = xf86ConfigLayout.inputs; - while (*idp) { - count++; - idp++; - } - } - - if (count == 0) - return NULL; - - /* - * allocate the memory and walk the list again to fill in the pointers - */ - modulearray = xnfalloc((count + 1) * sizeof(char*)); - count = 0; - idp = xf86ConfigLayout.inputs; - while (idp && *idp) { - modulearray[count] = (*idp)->driver; - count++; - idp++; - } - modulearray[count] = NULL; - - /* Remove duplicates */ - for (count = 0; modulearray[count] != NULL; count++) { - int i; - - for (i = 0; i < count; i++) - if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { - modulearray[count] = ""; - break; - } - } - return modulearray; -} - -static void -fixup_video_driver_list(char **drivers) -{ - static const char *fallback[4] = { "vesa", "fbdev", "wsfb", NULL }; - char **end, **drv; - char *x; - char **ati, **atimisc; - int i; - - /* walk to the end of the list */ - for (end = drivers; *end && **end; end++) ; - end--; - - /* - * for each of the fallback drivers, if we find it in the list, - * swap it with the last available non-fallback driver. - */ - for (i = 0; fallback[i]; i++) { - for (drv = drivers; drv != end; drv++) { - if (strstr(*drv, fallback[i])) { - x = *drv; *drv = *end; *end = x; - end--; - break; - } - } - } - /* - * since the ati wrapper driver is gross and awful, sort ati before - * atimisc, which makes sure all the ati symbols are visible in xorgcfg. - */ - for (drv = drivers; drv != end; drv++) { - if (!strcmp(*drv, "atimisc")) { - atimisc = drv; - for (drv = atimisc; drv != end; drv++) { - if (!strcmp(*drv, "ati")) { - ati = drv; - x = *ati; *ati = *atimisc; *atimisc = x; - return; - } - } - /* if we get here, ati was already ahead of atimisc */ - return; - } - } -} - -static char ** -GenerateDriverlist(char * dirname) -{ - char **ret; - const char *subdirs[] = { dirname, NULL }; - static const char *patlist[] = {"(.*)_drv\\.so", "(.*)_drv\\.o", NULL}; - ret = LoaderListDirs(subdirs, patlist); - - /* fix up the probe order for video drivers */ - if (strstr(dirname, "drivers") && ret != NULL) - fixup_video_driver_list(ret); - - return ret; -} - -char ** -xf86DriverlistFromCompile(void) -{ - static char **driverlist = NULL; - - if (!driverlist) - driverlist = GenerateDriverlist("drivers"); - - return driverlist; -} - -/* - * xf86ConfigError -- - * Print a READABLE ErrorMessage!!! All information that is - * available is printed. - */ -static void -xf86ConfigError(char *msg, ...) -{ - va_list ap; - - ErrorF("\nConfig Error:\n"); - va_start(ap, msg); - VErrorF(msg, ap); - va_end(ap); - ErrorF("\n"); - return; -} - -static void -configFiles(XF86ConfFilesPtr fileconf) -{ - MessageType pathFrom; - Bool must_copy; - int size, countDirs; - char *temp_path, *log_buf, *start, *end; - - /* FontPath */ - must_copy = TRUE; - - temp_path = defaultFontPath ? defaultFontPath : ""; - if (xf86fpFlag) - pathFrom = X_CMDLINE; - else if (fileconf && fileconf->file_fontpath) { - pathFrom = X_CONFIG; - if (xf86Info.useDefaultFontPath) { - defaultFontPath = Xprintf("%s%s%s", - fileconf->file_fontpath, - *temp_path ? "," : "", temp_path); - if (defaultFontPath != NULL) { - must_copy = FALSE; - } - } - else - defaultFontPath = fileconf->file_fontpath; - } - else - pathFrom = X_DEFAULT; - temp_path = defaultFontPath ? defaultFontPath : ""; - - /* xf86ValidateFontPath modifies its argument, but returns a copy of it. */ - temp_path = must_copy ? xnfstrdup(defaultFontPath) : defaultFontPath; - defaultFontPath = xf86ValidateFontPath(temp_path); - xfree(temp_path); - - /* make fontpath more readable in the logfiles */ - countDirs = 1; - temp_path = defaultFontPath; - while ((temp_path = index(temp_path, ',')) != NULL) { - countDirs++; - temp_path++; - } - - log_buf = xnfalloc(strlen(defaultFontPath) + (2 * countDirs) + 1); - temp_path = log_buf; - start = defaultFontPath; - while((end = index(start, ',')) != NULL) { - size = (end - start) + 1; - *(temp_path++) = '\t'; - strncpy(temp_path, start, size); - temp_path += size; - *(temp_path++) = '\n'; - start += size; - } - /* copy last entry */ - *(temp_path++) = '\t'; - strcpy(temp_path, start); - xf86Msg(pathFrom, "FontPath set to:\n%s\n", log_buf); - xfree(log_buf); - - /* ModulePath */ - - if (fileconf) { - if (xf86ModPathFrom != X_CMDLINE && fileconf->file_modulepath) { - xf86ModulePath = fileconf->file_modulepath; - xf86ModPathFrom = X_CONFIG; - } - } - - xf86Msg(xf86ModPathFrom, "ModulePath set to \"%s\"\n", xf86ModulePath); - - if (!xf86xkbdirFlag && fileconf && fileconf->file_xkbdir) { - XkbBaseDirectory = fileconf->file_xkbdir; - xf86Msg(X_CONFIG, "XKB base directory set to \"%s\"\n", - XkbBaseDirectory); - } -#if 0 - /* LogFile */ - /* - * XXX The problem with this is that the log file is already open. - * One option might be to copy the exiting contents to the new location. - * and re-open it. The down side is that the default location would - * already have been overwritten. Another option would be to start with - * unique temporary location, then copy it once the correct name is known. - * A problem with this is what happens if the server exits before that - * happens. - */ - if (xf86LogFileFrom == X_DEFAULT && fileconf->file_logfile) { - xf86LogFile = fileconf->file_logfile; - xf86LogFileFrom = X_CONFIG; - } -#endif - - return; -} - -typedef enum { - FLAG_NOTRAPSIGNALS, - FLAG_DONTVTSWITCH, - FLAG_DONTZAP, - FLAG_DONTZOOM, - FLAG_DISABLEVIDMODE, - FLAG_ALLOWNONLOCAL, - FLAG_ALLOWMOUSEOPENFAIL, - FLAG_VTSYSREQ, - FLAG_SAVER_BLANKTIME, - FLAG_DPMS_STANDBYTIME, - FLAG_DPMS_SUSPENDTIME, - FLAG_DPMS_OFFTIME, - FLAG_PIXMAP, - FLAG_PC98, - FLAG_NOPM, - FLAG_XINERAMA, - FLAG_LOG, - FLAG_RENDER_COLORMAP_MODE, - FLAG_RANDR, - FLAG_AIGLX, - FLAG_IGNORE_ABI, - FLAG_ALLOW_EMPTY_INPUT, - FLAG_USE_DEFAULT_FONT_PATH, - FLAG_AUTO_ADD_DEVICES, - FLAG_AUTO_ENABLE_DEVICES, - FLAG_GLX_VISUALS, - FLAG_DRI2, - FLAG_USE_SIGIO -} FlagValues; - -/** - * NOTE: the last value for each entry is NOT the default. It is set to TRUE - * if the parser found the option in the config file. - */ -static OptionInfoRec FlagOptions[] = { - { FLAG_NOTRAPSIGNALS, "NoTrapSignals", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_DONTVTSWITCH, "DontVTSwitch", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_DONTZAP, "DontZap", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_DONTZOOM, "DontZoom", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_DISABLEVIDMODE, "DisableVidModeExtension", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_ALLOWNONLOCAL, "AllowNonLocalXvidtune", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_ALLOWMOUSEOPENFAIL, "AllowMouseOpenFail", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_VTSYSREQ, "VTSysReq", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_SAVER_BLANKTIME, "BlankTime" , OPTV_INTEGER, - {0}, FALSE }, - { FLAG_DPMS_STANDBYTIME, "StandbyTime", OPTV_INTEGER, - {0}, FALSE }, - { FLAG_DPMS_SUSPENDTIME, "SuspendTime", OPTV_INTEGER, - {0}, FALSE }, - { FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER, - {0}, FALSE }, - { FLAG_PIXMAP, "Pixmap", OPTV_INTEGER, - {0}, FALSE }, - { FLAG_PC98, "PC98", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_NOPM, "NoPM", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_LOG, "Log", OPTV_STRING, - {0}, FALSE }, - { FLAG_RENDER_COLORMAP_MODE, "RenderColormapMode", OPTV_STRING, - {0}, FALSE }, - { FLAG_RANDR, "RandR", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_AIGLX, "AIGLX", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_ALLOW_EMPTY_INPUT, "AllowEmptyInput", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_IGNORE_ABI, "IgnoreABI", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_USE_DEFAULT_FONT_PATH, "UseDefaultFontPath", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_AUTO_ADD_DEVICES, "AutoAddDevices", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_AUTO_ENABLE_DEVICES, "AutoEnableDevices", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_GLX_VISUALS, "GlxVisuals", OPTV_STRING, - {0}, FALSE }, - { FLAG_DRI2, "DRI2", OPTV_BOOLEAN, - {0}, FALSE }, - { FLAG_USE_SIGIO, "UseSIGIO", OPTV_BOOLEAN, - {0}, FALSE }, - { -1, NULL, OPTV_NONE, - {0}, FALSE }, -}; - -#ifdef SUPPORT_PC98 -static Bool -detectPC98(void) -{ - unsigned char buf[2]; - - if (xf86ReadBIOS(0xf8000, 0xe80, buf, 2) != 2) - return FALSE; - if ((buf[0] == 0x98) && (buf[1] == 0x21)) - return TRUE; - else - return FALSE; -} -#endif - -static Bool -configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) -{ - XF86OptionPtr optp, tmp; - int i; - Pix24Flags pix24 = Pix24DontCare; - Bool value; - MessageType from; - const char *s; - XkbRMLVOSet set; - /* Default options. */ - set.rules = "base"; - set.model = "pc105"; - set.layout = "us"; - set.variant = NULL; - set.options = NULL; - - /* - * Merge the ServerLayout and ServerFlags options. The former have - * precedence over the latter. - */ - optp = NULL; - if (flagsconf && flagsconf->flg_option_lst) - optp = xf86optionListDup(flagsconf->flg_option_lst); - if (layoutopts) { - tmp = xf86optionListDup(layoutopts); - if (optp) - optp = xf86optionListMerge(optp, tmp); - else - optp = tmp; - } - - xf86ProcessOptions(-1, optp, FlagOptions); - - xf86GetOptValBool(FlagOptions, FLAG_NOTRAPSIGNALS, &xf86Info.notrapSignals); - xf86GetOptValBool(FlagOptions, FLAG_DONTVTSWITCH, &xf86Info.dontVTSwitch); - xf86GetOptValBool(FlagOptions, FLAG_DONTZAP, &xf86Info.dontZap); - xf86GetOptValBool(FlagOptions, FLAG_DONTZOOM, &xf86Info.dontZoom); - - xf86GetOptValBool(FlagOptions, FLAG_IGNORE_ABI, &xf86Info.ignoreABI); - if (xf86Info.ignoreABI) { - xf86Msg(X_CONFIG, "Ignoring ABI Version\n"); - } - - if (xf86SIGIOSupported()) { - xf86Info.useSIGIO = xf86ReturnOptValBool(FlagOptions, FLAG_USE_SIGIO, USE_SIGIO_BY_DEFAULT); - if (xf86IsOptionSet(FlagOptions, FLAG_USE_SIGIO)) { - from = X_CONFIG; - } else { - from = X_DEFAULT; - } - if (!xf86Info.useSIGIO) { - xf86Msg(from, "Disabling SIGIO handlers for input devices\n"); - } else if (from == X_CONFIG) { - xf86Msg(from, "Enabling SIGIO handlers for input devices\n"); - } - } else { - xf86Info.useSIGIO = FALSE; - } - - if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_DEVICES)) { - xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_DEVICES, - &xf86Info.autoAddDevices); - from = X_CONFIG; - } - else { - from = X_DEFAULT; - } - xf86Msg(from, "%sutomatically adding devices\n", - xf86Info.autoAddDevices ? "A" : "Not a"); - - if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ENABLE_DEVICES)) { - xf86GetOptValBool(FlagOptions, FLAG_AUTO_ENABLE_DEVICES, - &xf86Info.autoEnableDevices); - from = X_CONFIG; - } - else { - from = X_DEFAULT; - } - xf86Msg(from, "%sutomatically enabling devices\n", - xf86Info.autoEnableDevices ? "A" : "Not a"); - - /* - * Set things up based on the config file information. Some of these - * settings may be overridden later when the command line options are - * checked. - */ -#ifdef XF86VIDMODE - if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEVIDMODE, &value)) - xf86Info.vidModeEnabled = !value; - if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWNONLOCAL, &value)) - xf86Info.vidModeAllowNonLocal = value; -#endif - - if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWMOUSEOPENFAIL, &value)) - xf86Info.allowMouseOpenFail = value; - - if (xf86GetOptValBool(FlagOptions, FLAG_VTSYSREQ, &value)) { -#ifdef USE_VT_SYSREQ - xf86Info.vtSysreq = value; - xf86Msg(X_CONFIG, "VTSysReq %s\n", value ? "enabled" : "disabled"); -#else - if (value) - xf86Msg(X_WARNING, "VTSysReq is not supported on this OS\n"); -#endif - } - - xf86Info.pmFlag = TRUE; - if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value)) - xf86Info.pmFlag = !value; - { - if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) { - if (!xf86NameCmp(s,"flush")) { - xf86Msg(X_CONFIG, "Flushing logfile enabled\n"); - xf86Info.log = LogFlush; - LogSetParameter(XLOG_FLUSH, TRUE); - } else if (!xf86NameCmp(s,"sync")) { - xf86Msg(X_CONFIG, "Syncing logfile enabled\n"); - xf86Info.log = LogSync; - LogSetParameter(XLOG_FLUSH, TRUE); - LogSetParameter(XLOG_SYNC, TRUE); - } else { - xf86Msg(X_WARNING,"Unknown Log option\n"); - } - } - } - - { - if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))){ - int policy = PictureParseCmapPolicy (s); - if (policy == PictureCmapPolicyInvalid) - xf86Msg(X_WARNING, "Unknown colormap policy \"%s\"\n", s); - else - { - xf86Msg(X_CONFIG, "Render colormap policy set to %s\n", s); - PictureCmapPolicy = policy; - } - } - } - -#ifdef RANDR - xf86Info.disableRandR = FALSE; - xf86Info.randRFrom = X_DEFAULT; - if (xf86GetOptValBool(FlagOptions, FLAG_RANDR, &value)) { - xf86Info.disableRandR = !value; - xf86Info.randRFrom = X_CONFIG; - } -#endif - - xf86Info.aiglx = TRUE; - xf86Info.aiglxFrom = X_DEFAULT; - if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { - xf86Info.aiglx = value; - xf86Info.aiglxFrom = X_CONFIG; - } - -#ifdef GLXEXT - xf86Info.glxVisuals = XF86_GlxVisualsTypical; - xf86Info.glxVisualsFrom = X_DEFAULT; - if ((s = xf86GetOptValString(FlagOptions, FLAG_GLX_VISUALS))) { - if (!xf86NameCmp(s, "minimal")) { - xf86Info.glxVisuals = XF86_GlxVisualsMinimal; - } else if (!xf86NameCmp(s, "typical")) { - xf86Info.glxVisuals = XF86_GlxVisualsTypical; - } else if (!xf86NameCmp(s, "all")) { - xf86Info.glxVisuals = XF86_GlxVisualsAll; - } else { - xf86Msg(X_WARNING,"Unknown GlxVisuals option\n"); - } - } - - if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { - xf86Info.aiglx = value; - xf86Info.aiglxFrom = X_CONFIG; - } -#endif - - /* AllowEmptyInput is automatically true if we're hotplugging */ - xf86Info.allowEmptyInput = (xf86Info.autoAddDevices && xf86Info.autoEnableDevices); - xf86GetOptValBool(FlagOptions, FLAG_ALLOW_EMPTY_INPUT, &xf86Info.allowEmptyInput); - - /* AEI on? Then we're not using kbd, so use the evdev rules set. */ -#if defined(linux) - if (xf86Info.allowEmptyInput) - set.rules = "evdev"; -#endif - XkbSetRulesDflts(&set); - - xf86Info.useDefaultFontPath = TRUE; - xf86Info.useDefaultFontPathFrom = X_DEFAULT; - if (xf86GetOptValBool(FlagOptions, FLAG_USE_DEFAULT_FONT_PATH, &value)) { - xf86Info.useDefaultFontPath = value; - xf86Info.useDefaultFontPathFrom = X_CONFIG; - } - -/* Make sure that timers don't overflow CARD32's after multiplying */ -#define MAX_TIME_IN_MIN (0x7fffffff / MILLI_PER_MIN) - - i = -1; - xf86GetOptValInteger(FlagOptions, FLAG_SAVER_BLANKTIME, &i); - if ((i >= 0) && (i < MAX_TIME_IN_MIN)) - ScreenSaverTime = defaultScreenSaverTime = i * MILLI_PER_MIN; - else if (i != -1) - xf86ConfigError("BlankTime value %d outside legal range of 0 - %d minutes", - i, MAX_TIME_IN_MIN); - -#ifdef DPMSExtension - i = -1; - xf86GetOptValInteger(FlagOptions, FLAG_DPMS_STANDBYTIME, &i); - if ((i >= 0) && (i < MAX_TIME_IN_MIN)) - DPMSStandbyTime = i * MILLI_PER_MIN; - else if (i != -1) - xf86ConfigError("StandbyTime value %d outside legal range of 0 - %d minutes", - i, MAX_TIME_IN_MIN); - i = -1; - xf86GetOptValInteger(FlagOptions, FLAG_DPMS_SUSPENDTIME, &i); - if ((i >= 0) && (i < MAX_TIME_IN_MIN)) - DPMSSuspendTime = i * MILLI_PER_MIN; - else if (i != -1) - xf86ConfigError("SuspendTime value %d outside legal range of 0 - %d minutes", - i, MAX_TIME_IN_MIN); - i = -1; - xf86GetOptValInteger(FlagOptions, FLAG_DPMS_OFFTIME, &i); - if ((i >= 0) && (i < MAX_TIME_IN_MIN)) - DPMSOffTime = i * MILLI_PER_MIN; - else if (i != -1) - xf86ConfigError("OffTime value %d outside legal range of 0 - %d minutes", - i, MAX_TIME_IN_MIN); -#endif - - i = -1; - xf86GetOptValInteger(FlagOptions, FLAG_PIXMAP, &i); - switch (i) { - case 24: - pix24 = Pix24Use24; - break; - case 32: - pix24 = Pix24Use32; - break; - case -1: - break; - default: - xf86ConfigError("Pixmap option's value (%d) must be 24 or 32\n", i); - return FALSE; - } - if (xf86Pix24 != Pix24DontCare) { - xf86Info.pixmap24 = xf86Pix24; - xf86Info.pix24From = X_CMDLINE; - } else if (pix24 != Pix24DontCare) { - xf86Info.pixmap24 = pix24; - xf86Info.pix24From = X_CONFIG; - } else { - xf86Info.pixmap24 = Pix24DontCare; - xf86Info.pix24From = X_DEFAULT; - } -#ifdef SUPPORT_PC98 - if (xf86GetOptValBool(FlagOptions, FLAG_PC98, &value)) { - xf86Info.pc98 = value; - if (value) { - xf86Msg(X_CONFIG, "Japanese PC98 architecture\n"); - } - } else - if (detectPC98()) { - xf86Info.pc98 = TRUE; - xf86Msg(X_PROBED, "Japanese PC98 architecture\n"); - } -#endif - -#ifdef PANORAMIX - from = X_DEFAULT; - if (!noPanoramiXExtension) - from = X_CMDLINE; - else if (xf86GetOptValBool(FlagOptions, FLAG_XINERAMA, &value)) { - noPanoramiXExtension = !value; - from = X_CONFIG; - } - if (!noPanoramiXExtension) - xf86Msg(from, "Xinerama: enabled\n"); -#endif - -#ifdef DRI2 - xf86Info.dri2 = FALSE; - xf86Info.dri2From = X_DEFAULT; - if (xf86GetOptValBool(FlagOptions, FLAG_DRI2, &value)) { - xf86Info.dri2 = value; - xf86Info.dri2From = X_CONFIG; - } -#endif - - return TRUE; -} - -Bool xf86DRI2Enabled(void) -{ - return xf86Info.dri2; -} - -/* - * Locate the core input devices. These can be specified/located in - * the following ways, in order of priority: - * - * 1. The InputDevices named by the -pointer and -keyboard command line - * options. - * 2. The "CorePointer" and "CoreKeyboard" InputDevices referred to by - * the active ServerLayout. - * 3. The first InputDevices marked as "CorePointer" and "CoreKeyboard". - * 4. The first InputDevices that use 'keyboard' or 'kbd' and a valid mouse - * driver (mouse, synaptics, evdev, vmmouse, void) - * 5. Default devices with an empty (default) configuration. These defaults - * will reference the 'mouse' and 'keyboard' drivers. - */ - -static Bool -checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) -{ - IDevPtr corePointer = NULL, coreKeyboard = NULL; - Bool foundPointer = FALSE, foundKeyboard = FALSE; - const char *pointerMsg = NULL, *keyboardMsg = NULL; - IDevPtr *devs, /* iterator */ - indp; - IDevRec Pointer, Keyboard; - XF86ConfInputPtr confInput; - XF86ConfInputRec defPtr, defKbd; - int count = 0; - MessageType from = X_DEFAULT; - int found = 0; - const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse", - "void", NULL }; - - /* - * First check if a core pointer or core keyboard have been specified - * in the active ServerLayout. If more than one is specified for either, - * remove the core attribute from the later ones. - */ - for (devs = servlayoutp->inputs; devs && *devs; devs++) { - pointer opt1 = NULL, opt2 = NULL; - indp = *devs; - if (indp->commonOptions && - xf86CheckBoolOption(indp->commonOptions, "CorePointer", FALSE)) { - opt1 = indp->commonOptions; - } - if (indp->extraOptions && - xf86CheckBoolOption(indp->extraOptions, "CorePointer", FALSE)) { - opt2 = indp->extraOptions; - } - if (opt1 || opt2) { - if (!corePointer) { - corePointer = indp; - } else { - if (opt1) - xf86ReplaceBoolOption(opt1, "CorePointer", FALSE); - if (opt2) - xf86ReplaceBoolOption(opt2, "CorePointer", FALSE); - xf86Msg(X_WARNING, "Duplicate core pointer devices. " - "Removing core pointer attribute from \"%s\"\n", - indp->identifier); - } - } - opt1 = opt2 = NULL; - if (indp->commonOptions && - xf86CheckBoolOption(indp->commonOptions, "CoreKeyboard", FALSE)) { - opt1 = indp->commonOptions; - } - if (indp->extraOptions && - xf86CheckBoolOption(indp->extraOptions, "CoreKeyboard", FALSE)) { - opt2 = indp->extraOptions; - } - if (opt1 || opt2) { - if (!coreKeyboard) { - coreKeyboard = indp; - } else { - if (opt1) - xf86ReplaceBoolOption(opt1, "CoreKeyboard", FALSE); - if (opt2) - xf86ReplaceBoolOption(opt2, "CoreKeyboard", FALSE); - xf86Msg(X_WARNING, "Duplicate core keyboard devices. " - "Removing core keyboard attribute from \"%s\"\n", - indp->identifier); - } - } - count++; - } - - confInput = NULL; - - /* 1. Check for the -pointer command line option. */ - if (xf86PointerName) { - confInput = xf86findInput(xf86PointerName, - xf86configptr->conf_input_lst); - if (!confInput) { - xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n", - xf86PointerName); - return FALSE; - } - from = X_CMDLINE; - /* - * If one was already specified in the ServerLayout, it needs to be - * removed. - */ - if (corePointer) { - for (devs = servlayoutp->inputs; devs && *devs; devs++) - if (*devs == corePointer) - { - xfree(*devs); - *devs = (IDevPtr)0x1; /* ensure we dont skip next loop*/ - break; - } - for (; devs && *devs; devs++) - devs[0] = devs[1]; - count--; - } - corePointer = NULL; - foundPointer = TRUE; - } - - /* 2. ServerLayout-specified core pointer. */ - if (corePointer) { - foundPointer = TRUE; - from = X_CONFIG; - } - - /* 3. First core pointer device. */ - if (!foundPointer && (!xf86Info.allowEmptyInput || implicitLayout)) { - XF86ConfInputPtr p; - - for (p = xf86configptr->conf_input_lst; p; p = p->list.next) { - if (p->inp_option_lst && - xf86CheckBoolOption(p->inp_option_lst, "CorePointer", FALSE)) { - confInput = p; - foundPointer = TRUE; - from = X_DEFAULT; - pointerMsg = "first core pointer device"; - break; - } - } - } - - /* 4. First pointer with an allowed mouse driver. */ - if (!foundPointer && !xf86Info.allowEmptyInput) { - const char **driver = mousedrivers; - confInput = xf86findInput(CONF_IMPLICIT_POINTER, - xf86configptr->conf_input_lst); - while (*driver && !confInput) { - confInput = xf86findInputByDriver(*driver, - xf86configptr->conf_input_lst); - driver++; - } - if (confInput) { - foundPointer = TRUE; - from = X_DEFAULT; - pointerMsg = "first mouse device"; - } - } - - /* 5. Built-in default. */ - if (!foundPointer && !xf86Info.allowEmptyInput) { - bzero(&defPtr, sizeof(defPtr)); - defPtr.inp_identifier = strdup(""); - defPtr.inp_driver = strdup("mouse"); - confInput = &defPtr; - foundPointer = TRUE; - from = X_DEFAULT; - pointerMsg = "default mouse configuration"; - } - - /* Add the core pointer device to the layout, and set it to Core. */ - if (foundPointer && confInput) { - foundPointer = configInput(&Pointer, confInput, from); - if (foundPointer) { - count++; - devs = xnfrealloc(servlayoutp->inputs, - (count + 1) * sizeof(IDevPtr)); - devs[count - 1] = xnfalloc(sizeof(IDevRec)); - *devs[count - 1] = Pointer; - devs[count - 1]->extraOptions = - xf86addNewOption(NULL, xnfstrdup("CorePointer"), NULL); - devs[count] = NULL; - servlayoutp->inputs = devs; - } - } - - if (!foundPointer && !xf86Info.allowEmptyInput) { - /* This shouldn't happen. */ - xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n"); - return FALSE; - } - - /* - * always synthesize a 'mouse' section configured to send core - * events, unless a 'void' section is found, in which case the user - * probably wants to run footless. - * - * If you're using an evdev keyboard and expect a default mouse - * section ... deal. - */ - for (devs = servlayoutp->inputs; devs && *devs; devs++) { - const char **driver = mousedrivers; - while(*driver) { - if (!strcmp((*devs)->driver, *driver)) { - found = 1; - break; - } - driver++; - } - } - if (!found && !xf86Info.allowEmptyInput) { - xf86Msg(X_INFO, "No default mouse found, adding one\n"); - bzero(&defPtr, sizeof(defPtr)); - defPtr.inp_identifier = strdup(""); - defPtr.inp_driver = strdup("mouse"); - confInput = &defPtr; - foundPointer = configInput(&Pointer, confInput, from); - if (foundPointer) { - count++; - devs = xnfrealloc(servlayoutp->inputs, - (count + 1) * sizeof(IDevPtr)); - devs[count - 1] = xnfalloc(sizeof(IDevRec)); - *devs[count - 1] = Pointer; - devs[count - 1]->extraOptions = - xf86addNewOption(NULL, xnfstrdup("AlwaysCore"), NULL); - devs[count] = NULL; - servlayoutp->inputs = devs; - } - } - - confInput = NULL; - - /* 1. Check for the -keyboard command line option. */ - if (xf86KeyboardName) { - confInput = xf86findInput(xf86KeyboardName, - xf86configptr->conf_input_lst); - if (!confInput) { - xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n", - xf86KeyboardName); - return FALSE; - } - from = X_CMDLINE; - /* - * If one was already specified in the ServerLayout, it needs to be - * removed. - */ - if (coreKeyboard) { - for (devs = servlayoutp->inputs; devs && *devs; devs++) - if (*devs == coreKeyboard) - { - xfree(*devs); - *devs = (IDevPtr)0x1; /* ensure we dont skip next loop */ - break; - } - for (; devs && *devs; devs++) - devs[0] = devs[1]; - count--; - } - coreKeyboard = NULL; - foundKeyboard = TRUE; - } - - /* 2. ServerLayout-specified core keyboard. */ - if (coreKeyboard) { - foundKeyboard = TRUE; - from = X_CONFIG; - } - - /* 3. First core keyboard device. */ - if (!foundKeyboard && (!xf86Info.allowEmptyInput || implicitLayout)) { - XF86ConfInputPtr p; - - for (p = xf86configptr->conf_input_lst; p; p = p->list.next) { - if (p->inp_option_lst && - xf86CheckBoolOption(p->inp_option_lst, "CoreKeyboard", FALSE)) { - confInput = p; - foundKeyboard = TRUE; - from = X_DEFAULT; - keyboardMsg = "first core keyboard device"; - break; - } - } - } - - /* 4. First keyboard with 'keyboard' or 'kbd' as the driver. */ - if (!foundKeyboard && !xf86Info.allowEmptyInput) { - confInput = xf86findInput(CONF_IMPLICIT_KEYBOARD, - xf86configptr->conf_input_lst); - if (!confInput) { - confInput = xf86findInputByDriver("kbd", - xf86configptr->conf_input_lst); - } - if (confInput) { - foundKeyboard = TRUE; - from = X_DEFAULT; - keyboardMsg = "first keyboard device"; - } - } - - /* 5. Built-in default. */ - if (!foundKeyboard && !xf86Info.allowEmptyInput) { - bzero(&defKbd, sizeof(defKbd)); - defKbd.inp_identifier = strdup(""); - defKbd.inp_driver = strdup("kbd"); - confInput = &defKbd; - foundKeyboard = TRUE; - keyboardMsg = "default keyboard configuration"; - from = X_DEFAULT; - } - - /* Add the core keyboard device to the layout, and set it to Core. */ - if (foundKeyboard && confInput) { - foundKeyboard = configInput(&Keyboard, confInput, from); - if (foundKeyboard) { - count++; - devs = xnfrealloc(servlayoutp->inputs, - (count + 1) * sizeof(IDevPtr)); - devs[count - 1] = xnfalloc(sizeof(IDevRec)); - *devs[count - 1] = Keyboard; - devs[count - 1]->extraOptions = - xf86addNewOption(NULL, xnfstrdup("CoreKeyboard"), NULL); - devs[count] = NULL; - servlayoutp->inputs = devs; - } - } - - if (!foundKeyboard && !xf86Info.allowEmptyInput) { - /* This shouldn't happen. */ - xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n"); - return FALSE; - } - - if (pointerMsg) { - if (implicitLayout) - xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n", - pointerMsg); - else - xf86Msg(X_DEFAULT, "The core pointer device wasn't specified " - "explicitly in the layout.\n" - "\tUsing the %s.\n", pointerMsg); - } - - if (keyboardMsg) { - if (implicitLayout) - xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n", - keyboardMsg); - else - xf86Msg(X_DEFAULT, "The core keyboard device wasn't specified " - "explicitly in the layout.\n" - "\tUsing the %s.\n", keyboardMsg); - } - - if (xf86Info.allowEmptyInput && !(foundPointer && foundKeyboard)) { -#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) - const char *config_backend; -#if defined(CONFIG_HAL) - config_backend = "HAL"; -#else - config_backend = "udev"; -#endif - xf86Msg(X_INFO, "The server relies on %s to provide the list of " - "input devices.\n\tIf no devices become available, " - "reconfigure %s or disable AutoAddDevices.\n", - config_backend, config_backend); -#else - xf86Msg(X_INFO, "Hotplugging is disabled and no input devices were configured.\n" - "\tTry disabling AllowEmptyInput.\n"); -#endif - } - - return TRUE; -} - -typedef enum { - LAYOUT_ISOLATEDEVICE, - LAYOUT_SINGLECARD -} LayoutValues; - -static OptionInfoRec LayoutOptions[] = { - { LAYOUT_ISOLATEDEVICE, "IsolateDevice", OPTV_STRING, - {0}, FALSE }, - { LAYOUT_SINGLECARD, "SingleCard", OPTV_BOOLEAN, - {0}, FALSE }, - { -1, NULL, OPTV_NONE, - {0}, FALSE }, -}; - -static Bool -configInputDevices(XF86ConfLayoutPtr layout, serverLayoutPtr servlayoutp) -{ - XF86ConfInputrefPtr irp; - IDevPtr *indp; - int count = 0; - - /* - * Count the number of input devices. - */ - irp = layout->lay_input_lst; - while (irp) { - count++; - irp = (XF86ConfInputrefPtr)irp->list.next; - } - DebugF("Found %d input devices in the layout section %s\n", - count, layout->lay_identifier); - indp = xnfcalloc((count + 1), sizeof(IDevPtr)); - indp[count] = NULL; - irp = layout->lay_input_lst; - count = 0; - while (irp) { - indp[count] = xnfalloc(sizeof(IDevRec)); - if (!configInput(indp[count], irp->iref_inputdev, X_CONFIG)) { - while(count--) - xfree(indp[count]); - xfree(indp); - return FALSE; - } - indp[count]->extraOptions = irp->iref_option_lst; - count++; - irp = (XF86ConfInputrefPtr)irp->list.next; - } - servlayoutp->inputs = indp; - - return TRUE; -} - - -/* - * figure out which layout is active, which screens are used in that layout, - * which drivers and monitors are used in these screens - */ -static Bool -configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, - char *default_layout) -{ - XF86ConfAdjacencyPtr adjp; - XF86ConfInactivePtr idp; - int count = 0; - int scrnum; - XF86ConfLayoutPtr l; - MessageType from; - screenLayoutPtr slp; - GDevPtr gdp; - int i = 0, j; - - if (!servlayoutp) - return FALSE; - - /* - * which layout section is the active one? - * - * If there is a -layout command line option, use that one, otherwise - * pick the first one. - */ - from = X_DEFAULT; - if (xf86LayoutName != NULL) - from = X_CMDLINE; - else if (default_layout) { - xf86LayoutName = default_layout; - from = X_CONFIG; - } - if (xf86LayoutName != NULL) { - if ((l = xf86findLayout(xf86LayoutName, conf_layout)) == NULL) { - xf86Msg(X_ERROR, "No ServerLayout section called \"%s\"\n", - xf86LayoutName); - return FALSE; - } - conf_layout = l; - } - xf86Msg(from, "ServerLayout \"%s\"\n", conf_layout->lay_identifier); - adjp = conf_layout->lay_adjacency_lst; - - /* - * we know that each screen is referenced exactly once on the left side - * of a layout statement in the Layout section. So to allocate the right - * size for the array we do a quick walk of the list to figure out how - * many sections we have - */ - while (adjp) { - count++; - adjp = (XF86ConfAdjacencyPtr)adjp->list.next; - } - - DebugF("Found %d screens in the layout section %s", - count, conf_layout->lay_identifier); - if (!count) /* alloc enough storage even if no screen is specified */ - count = 1; - - slp = xnfcalloc(1, (count + 1) * sizeof(screenLayoutRec)); - slp[count].screen = NULL; - /* - * now that we have storage, loop over the list again and fill in our - * data structure; at this point we do not fill in the adjacency - * information as it is not clear if we need it at all - */ - adjp = conf_layout->lay_adjacency_lst; - count = 0; - while (adjp) { - slp[count].screen = xnfcalloc(1, sizeof(confScreenRec)); - if (adjp->adj_scrnum < 0) - scrnum = count; - else - scrnum = adjp->adj_scrnum; - if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum, - X_CONFIG)) { - xfree(slp); - return FALSE; - } - slp[count].x = adjp->adj_x; - slp[count].y = adjp->adj_y; - slp[count].refname = adjp->adj_refscreen; - switch (adjp->adj_where) { - case CONF_ADJ_OBSOLETE: - slp[count].where = PosObsolete; - slp[count].topname = adjp->adj_top_str; - slp[count].bottomname = adjp->adj_bottom_str; - slp[count].leftname = adjp->adj_left_str; - slp[count].rightname = adjp->adj_right_str; - break; - case CONF_ADJ_ABSOLUTE: - slp[count].where = PosAbsolute; - break; - case CONF_ADJ_RIGHTOF: - slp[count].where = PosRightOf; - break; - case CONF_ADJ_LEFTOF: - slp[count].where = PosLeftOf; - break; - case CONF_ADJ_ABOVE: - slp[count].where = PosAbove; - break; - case CONF_ADJ_BELOW: - slp[count].where = PosBelow; - break; - case CONF_ADJ_RELATIVE: - slp[count].where = PosRelative; - break; - } - count++; - adjp = (XF86ConfAdjacencyPtr)adjp->list.next; - } - - /* No screen was specified in the layout. take the first one from the - * config file, or - if it is NULL - configScreen autogenerates one for - * us */ - if (!count) - { - slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); - if (!configScreen(slp[0].screen, xf86configptr->conf_screen_lst, - 0, X_CONFIG)) { - xfree(slp[0].screen); - xfree(slp); - return FALSE; - } - } - - /* XXX Need to tie down the upper left screen. */ - - /* Fill in the refscreen and top/bottom/left/right values */ - for (i = 0; i < count; i++) { - for (j = 0; j < count; j++) { - if (slp[i].refname && - strcmp(slp[i].refname, slp[j].screen->id) == 0) { - slp[i].refscreen = slp[j].screen; - } - if (slp[i].topname && - strcmp(slp[i].topname, slp[j].screen->id) == 0) { - slp[i].top = slp[j].screen; - } - if (slp[i].bottomname && - strcmp(slp[i].bottomname, slp[j].screen->id) == 0) { - slp[i].bottom = slp[j].screen; - } - if (slp[i].leftname && - strcmp(slp[i].leftname, slp[j].screen->id) == 0) { - slp[i].left = slp[j].screen; - } - if (slp[i].rightname && - strcmp(slp[i].rightname, slp[j].screen->id) == 0) { - slp[i].right = slp[j].screen; - } - } - if (slp[i].where != PosObsolete - && slp[i].where != PosAbsolute - && !slp[i].refscreen) { - xf86Msg(X_ERROR,"Screen %s doesn't exist: deleting placement\n", - slp[i].refname); - slp[i].where = PosAbsolute; - slp[i].x = 0; - slp[i].y = 0; - } - } - - /* - * Count the number of inactive devices. - */ - count = 0; - idp = conf_layout->lay_inactive_lst; - while (idp) { - count++; - idp = (XF86ConfInactivePtr)idp->list.next; - } - DebugF("Found %d inactive devices in the layout section %s\n", - count, conf_layout->lay_identifier); - gdp = xnfalloc((count + 1) * sizeof(GDevRec)); - gdp[count].identifier = NULL; - idp = conf_layout->lay_inactive_lst; - count = 0; - while (idp) { - if (!configDevice(&gdp[count], idp->inactive_device, FALSE)) { - xfree(gdp); - return FALSE; - } - count++; - idp = (XF86ConfInactivePtr)idp->list.next; - } - - if (!configInputDevices(conf_layout, servlayoutp)) - return FALSE; - - servlayoutp->id = conf_layout->lay_identifier; - servlayoutp->screens = slp; - servlayoutp->inactives = gdp; - servlayoutp->options = conf_layout->lay_option_lst; - from = X_DEFAULT; - - return TRUE; -} - -/* - * No layout section, so find the first Screen section and set that up as - * the only active screen. - */ -static Bool -configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen, - XF86ConfigPtr xf86configptr) -{ - MessageType from; - XF86ConfScreenPtr s; - screenLayoutPtr slp; - IDevPtr *indp; - XF86ConfLayoutRec layout; - - if (!servlayoutp) - return FALSE; - - /* - * which screen section is the active one? - * - * If there is a -screen option, use that one, otherwise use the first - * one. - */ - - from = X_CONFIG; - if (xf86ScreenName != NULL) { - if ((s = xf86findScreen(xf86ScreenName, conf_screen)) == NULL) { - xf86Msg(X_ERROR, "No Screen section called \"%s\"\n", - xf86ScreenName); - return FALSE; - } - conf_screen = s; - from = X_CMDLINE; - } - - /* We have exactly one screen */ - - slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec)); - slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); - slp[1].screen = NULL; - if (!configScreen(slp[0].screen, conf_screen, 0, from)) { - xfree(slp); - return FALSE; - } - servlayoutp->id = "(implicit)"; - servlayoutp->screens = slp; - servlayoutp->inactives = xnfcalloc(1, sizeof(GDevRec)); - servlayoutp->options = NULL; - - memset(&layout, 0, sizeof(layout)); - layout.lay_identifier = servlayoutp->id; - if (xf86layoutAddInputDevices(xf86configptr, &layout) > 0) { - if (!configInputDevices(&layout, servlayoutp)) - return FALSE; - from = X_DEFAULT; - } else { - /* Set up an empty input device list, then look for some core devices. */ - indp = xnfalloc(sizeof(IDevPtr)); - *indp = NULL; - servlayoutp->inputs = indp; - } - - return TRUE; -} - -static Bool -configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor) -{ - int count = 0; - XF86ConfVideoPortPtr conf_port; - - xf86Msg(X_CONFIG, "| |-->VideoAdaptor \"%s\"\n", - conf_adaptor->va_identifier); - adaptor->identifier = conf_adaptor->va_identifier; - adaptor->options = conf_adaptor->va_option_lst; - if (conf_adaptor->va_busid || conf_adaptor->va_driver) { - xf86Msg(X_CONFIG, "| | Unsupported device type, skipping entry\n"); - return FALSE; - } - - /* - * figure out how many videoport subsections there are and fill them in - */ - conf_port = conf_adaptor->va_port_lst; - while(conf_port) { - count++; - conf_port = (XF86ConfVideoPortPtr)conf_port->list.next; - } - adaptor->ports = xnfalloc((count) * sizeof(confXvPortRec)); - adaptor->numports = count; - count = 0; - conf_port = conf_adaptor->va_port_lst; - while(conf_port) { - adaptor->ports[count].identifier = conf_port->vp_identifier; - adaptor->ports[count].options = conf_port->vp_option_lst; - count++; - conf_port = (XF86ConfVideoPortPtr)conf_port->list.next; - } - - return TRUE; -} - -static Bool -configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, - MessageType from) -{ - int count = 0; - XF86ConfDisplayPtr dispptr; - XF86ConfAdaptorLinkPtr conf_adaptor; - Bool defaultMonitor = FALSE; - - if (!conf_screen) { - conf_screen = xnfcalloc(1, sizeof(XF86ConfScreenRec)); - conf_screen->scrn_identifier = "Default Screen Section"; - xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n"); - } - - xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier, - scrnum); - /* - * now we fill in the elements of the screen - */ - screenp->id = conf_screen->scrn_identifier; - screenp->screennum = scrnum; - screenp->defaultdepth = conf_screen->scrn_defaultdepth; - screenp->defaultbpp = conf_screen->scrn_defaultbpp; - screenp->defaultfbbpp = conf_screen->scrn_defaultfbbpp; - screenp->monitor = xnfcalloc(1, sizeof(MonRec)); - /* If no monitor is specified, create a default one. */ - if (!conf_screen->scrn_monitor) { - XF86ConfMonitorRec defMon; - - bzero(&defMon, sizeof(defMon)); - defMon.mon_identifier = ""; - if (!configMonitor(screenp->monitor, &defMon)) - return FALSE; - defaultMonitor = TRUE; - } else { - if (!configMonitor(screenp->monitor,conf_screen->scrn_monitor)) - return FALSE; - } - /* Configure the device. If there isn't one configured, attach to the - * first inactive one that we can configure. If there's none that work, - * set it to NULL so that the section can be autoconfigured later */ - screenp->device = xnfcalloc(1, sizeof(GDevRec)); - if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) { - conf_screen->scrn_device = xf86configptr->conf_device_lst; - xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n" - "\tUsing the first device section listed.\n", screenp->id); - } - if (configDevice(screenp->device,conf_screen->scrn_device, TRUE)) { - screenp->device->myScreenSection = screenp; - } else { - screenp->device = NULL; - } - screenp->options = conf_screen->scrn_option_lst; - - /* - * figure out how many display subsections there are and fill them in - */ - dispptr = conf_screen->scrn_display_lst; - while(dispptr) { - count++; - dispptr = (XF86ConfDisplayPtr)dispptr->list.next; - } - screenp->displays = xnfalloc((count) * sizeof(DispRec)); - screenp->numdisplays = count; - - /* Fill in the default Virtual size, if any */ - if (conf_screen->scrn_virtualX && conf_screen->scrn_virtualY) { - for (count = 0, dispptr = conf_screen->scrn_display_lst; - dispptr; - dispptr = (XF86ConfDisplayPtr)dispptr->list.next, count++) { - screenp->displays[count].virtualX = conf_screen->scrn_virtualX; - screenp->displays[count].virtualY = conf_screen->scrn_virtualY; - } - } - - /* Now do the per-Display Virtual sizes */ - count = 0; - dispptr = conf_screen->scrn_display_lst; - while(dispptr) { - configDisplay(&(screenp->displays[count]),dispptr); - count++; - dispptr = (XF86ConfDisplayPtr)dispptr->list.next; - } - - /* - * figure out how many videoadaptor references there are and fill them in - */ - conf_adaptor = conf_screen->scrn_adaptor_lst; - while(conf_adaptor) { - count++; - conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next; - } - screenp->xvadaptors = xnfalloc((count) * sizeof(confXvAdaptorRec)); - screenp->numxvadaptors = 0; - conf_adaptor = conf_screen->scrn_adaptor_lst; - while(conf_adaptor) { - if (configXvAdaptor(&(screenp->xvadaptors[screenp->numxvadaptors]), - conf_adaptor->al_adaptor)) - screenp->numxvadaptors++; - conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next; - } - - if (defaultMonitor) { - xf86Msg(X_DEFAULT, "No monitor specified for screen \"%s\".\n" - "\tUsing a default monitor configuration.\n", screenp->id); - } - return TRUE; -} - -typedef enum { - MON_REDUCEDBLANKING, - MON_MAX_PIX_CLOCK, -} MonitorValues; - -static OptionInfoRec MonitorOptions[] = { - { MON_REDUCEDBLANKING, "ReducedBlanking", OPTV_BOOLEAN, - {0}, FALSE }, - { MON_MAX_PIX_CLOCK, "MaxPixClock", OPTV_FREQ, - {0}, FALSE }, - { -1, NULL, OPTV_NONE, - {0}, FALSE }, -}; - -static Bool -configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor) -{ - int count; - DisplayModePtr mode,last = NULL; - XF86ConfModeLinePtr cmodep; - XF86ConfModesPtr modes; - XF86ConfModesLinkPtr modeslnk = conf_monitor->mon_modes_sect_lst; - Gamma zeros = {0.0, 0.0, 0.0}; - float badgamma = 0.0; - double maxPixClock; - - xf86Msg(X_CONFIG, "| |-->Monitor \"%s\"\n", - conf_monitor->mon_identifier); - monitorp->id = conf_monitor->mon_identifier; - monitorp->vendor = conf_monitor->mon_vendor; - monitorp->model = conf_monitor->mon_modelname; - monitorp->Modes = NULL; - monitorp->Last = NULL; - monitorp->gamma = zeros; - monitorp->widthmm = conf_monitor->mon_width; - monitorp->heightmm = conf_monitor->mon_height; - monitorp->reducedblanking = FALSE; - monitorp->maxPixClock = 0; - monitorp->options = conf_monitor->mon_option_lst; - - /* - * fill in the monitor structure - */ - for( count = 0 ; - count < conf_monitor->mon_n_hsync && count < MAX_HSYNC; - count++) { - monitorp->hsync[count].hi = conf_monitor->mon_hsync[count].hi; - monitorp->hsync[count].lo = conf_monitor->mon_hsync[count].lo; - } - monitorp->nHsync = count; - for( count = 0 ; - count < conf_monitor->mon_n_vrefresh && count < MAX_VREFRESH; - count++) { - monitorp->vrefresh[count].hi = conf_monitor->mon_vrefresh[count].hi; - monitorp->vrefresh[count].lo = conf_monitor->mon_vrefresh[count].lo; - } - monitorp->nVrefresh = count; - - /* - * first we collect the mode lines from the UseModes directive - */ - while(modeslnk) - { - modes = xf86findModes (modeslnk->ml_modes_str, - xf86configptr->conf_modes_lst); - modeslnk->ml_modes = modes; - - - /* now add the modes found in the modes - section to the list of modes for this - monitor unless it has been added before - because we are reusing the same section - for another screen */ - if (xf86itemNotSublist( - (GenericListPtr)conf_monitor->mon_modeline_lst, - (GenericListPtr)modes->mon_modeline_lst)) { - conf_monitor->mon_modeline_lst = (XF86ConfModeLinePtr) - xf86addListItem( - (GenericListPtr)conf_monitor->mon_modeline_lst, - (GenericListPtr)modes->mon_modeline_lst); - } - modeslnk = modeslnk->list.next; - } - - /* - * we need to hook in the mode lines now - * here both data structures use lists, only our internal one - * is double linked - */ - cmodep = conf_monitor->mon_modeline_lst; - while( cmodep ) { - mode = xnfcalloc(1, sizeof(DisplayModeRec)); - mode->type = 0; - mode->Clock = cmodep->ml_clock; - mode->HDisplay = cmodep->ml_hdisplay; - mode->HSyncStart = cmodep->ml_hsyncstart; - mode->HSyncEnd = cmodep->ml_hsyncend; - mode->HTotal = cmodep->ml_htotal; - mode->VDisplay = cmodep->ml_vdisplay; - mode->VSyncStart = cmodep->ml_vsyncstart; - mode->VSyncEnd = cmodep->ml_vsyncend; - mode->VTotal = cmodep->ml_vtotal; - mode->Flags = cmodep->ml_flags; - mode->HSkew = cmodep->ml_hskew; - mode->VScan = cmodep->ml_vscan; - mode->name = xnfstrdup(cmodep->ml_identifier); - if( last ) { - mode->prev = last; - last->next = mode; - } - else { - /* - * this is the first mode - */ - monitorp->Modes = mode; - mode->prev = NULL; - } - last = mode; - cmodep = (XF86ConfModeLinePtr)cmodep->list.next; - } - if(last){ - last->next = NULL; - } - monitorp->Last = last; - - /* add the (VESA) default modes */ - if (! addDefaultModes(monitorp) ) - return FALSE; - - if (conf_monitor->mon_gamma_red > GAMMA_ZERO) - monitorp->gamma.red = conf_monitor->mon_gamma_red; - if (conf_monitor->mon_gamma_green > GAMMA_ZERO) - monitorp->gamma.green = conf_monitor->mon_gamma_green; - if (conf_monitor->mon_gamma_blue > GAMMA_ZERO) - monitorp->gamma.blue = conf_monitor->mon_gamma_blue; - - /* Check that the gamma values are within range */ - if (monitorp->gamma.red > GAMMA_ZERO && - (monitorp->gamma.red < GAMMA_MIN || - monitorp->gamma.red > GAMMA_MAX)) { - badgamma = monitorp->gamma.red; - } else if (monitorp->gamma.green > GAMMA_ZERO && - (monitorp->gamma.green < GAMMA_MIN || - monitorp->gamma.green > GAMMA_MAX)) { - badgamma = monitorp->gamma.green; - } else if (monitorp->gamma.blue > GAMMA_ZERO && - (monitorp->gamma.blue < GAMMA_MIN || - monitorp->gamma.blue > GAMMA_MAX)) { - badgamma = monitorp->gamma.blue; - } - if (badgamma > GAMMA_ZERO) { - xf86ConfigError("Gamma value %.f is out of range (%.2f - %.1f)\n", - badgamma, GAMMA_MIN, GAMMA_MAX); - return FALSE; - } - - xf86ProcessOptions(-1, monitorp->options, MonitorOptions); - xf86GetOptValBool(MonitorOptions, MON_REDUCEDBLANKING, - &monitorp->reducedblanking); - if (xf86GetOptValFreq(MonitorOptions, MON_MAX_PIX_CLOCK, OPTUNITS_KHZ, - &maxPixClock) == TRUE) { - monitorp->maxPixClock = (int) maxPixClock; - } - - return TRUE; -} - -static int -lookupVisual(const char *visname) -{ - int i; - - if (!visname || !*visname) - return -1; - - for (i = 0; i <= DirectColor; i++) { - if (!xf86nameCompare(visname, xf86VisualNames[i])) - break; - } - - if (i <= DirectColor) - return i; - - return -1; -} - - -static Bool -configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display) -{ - int count = 0; - XF86ModePtr modep; - - displayp->frameX0 = conf_display->disp_frameX0; - displayp->frameY0 = conf_display->disp_frameY0; - displayp->virtualX = conf_display->disp_virtualX; - displayp->virtualY = conf_display->disp_virtualY; - displayp->depth = conf_display->disp_depth; - displayp->fbbpp = conf_display->disp_bpp; - displayp->weight.red = conf_display->disp_weight.red; - displayp->weight.green = conf_display->disp_weight.green; - displayp->weight.blue = conf_display->disp_weight.blue; - displayp->blackColour.red = conf_display->disp_black.red; - displayp->blackColour.green = conf_display->disp_black.green; - displayp->blackColour.blue = conf_display->disp_black.blue; - displayp->whiteColour.red = conf_display->disp_white.red; - displayp->whiteColour.green = conf_display->disp_white.green; - displayp->whiteColour.blue = conf_display->disp_white.blue; - displayp->options = conf_display->disp_option_lst; - if (conf_display->disp_visual) { - displayp->defaultVisual = lookupVisual(conf_display->disp_visual); - if (displayp->defaultVisual == -1) { - xf86ConfigError("Invalid visual name: \"%s\"", - conf_display->disp_visual); - return FALSE; - } - } else { - displayp->defaultVisual = -1; - } - - /* - * now hook in the modes - */ - modep = conf_display->disp_mode_lst; - while(modep) { - count++; - modep = (XF86ModePtr)modep->list.next; - } - displayp->modes = xnfalloc((count+1) * sizeof(char*)); - modep = conf_display->disp_mode_lst; - count = 0; - while(modep) { - displayp->modes[count] = modep->mode_name; - count++; - modep = (XF86ModePtr)modep->list.next; - } - displayp->modes[count] = NULL; - - return TRUE; -} - -static Bool -configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active) -{ - int i; - - if (!conf_device) { - return FALSE; - } - - if (active) - xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n", - conf_device->dev_identifier); - else - xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n", - conf_device->dev_identifier); - - devicep->identifier = conf_device->dev_identifier; - devicep->vendor = conf_device->dev_vendor; - devicep->board = conf_device->dev_board; - devicep->chipset = conf_device->dev_chipset; - devicep->ramdac = conf_device->dev_ramdac; - devicep->driver = conf_device->dev_driver; - devicep->active = active; - devicep->videoRam = conf_device->dev_videoram; - devicep->BiosBase = conf_device->dev_bios_base; - devicep->MemBase = conf_device->dev_mem_base; - devicep->IOBase = conf_device->dev_io_base; - devicep->clockchip = conf_device->dev_clockchip; - devicep->busID = conf_device->dev_busid; - devicep->textClockFreq = conf_device->dev_textclockfreq; - devicep->chipID = conf_device->dev_chipid; - devicep->chipRev = conf_device->dev_chiprev; - devicep->options = conf_device->dev_option_lst; - devicep->irq = conf_device->dev_irq; - devicep->screen = conf_device->dev_screen; - - for (i = 0; i < MAXDACSPEEDS; i++) { - if (i < CONF_MAXDACSPEEDS) - devicep->dacSpeeds[i] = conf_device->dev_dacSpeeds[i]; - else - devicep->dacSpeeds[i] = 0; - } - devicep->numclocks = conf_device->dev_clocks; - if (devicep->numclocks > MAXCLOCKS) - devicep->numclocks = MAXCLOCKS; - for (i = 0; i < devicep->numclocks; i++) { - devicep->clock[i] = conf_device->dev_clock[i]; - } - devicep->claimed = FALSE; - - return TRUE; -} - -#ifdef XF86DRI -static void -configDRI(XF86ConfDRIPtr drip) -{ - int count = 0; - XF86ConfBuffersPtr bufs; - int i; - struct group *grp; - - xf86ConfigDRI.group = -1; - xf86ConfigDRI.mode = 0; - xf86ConfigDRI.bufs_count = 0; - xf86ConfigDRI.bufs = NULL; - - if (drip) { - if (drip->dri_group_name) { - if ((grp = getgrnam(drip->dri_group_name))) - xf86ConfigDRI.group = grp->gr_gid; - } else { - if (drip->dri_group >= 0) - xf86ConfigDRI.group = drip->dri_group; - } - xf86ConfigDRI.mode = drip->dri_mode; - for (bufs = drip->dri_buffers_lst; bufs; bufs = bufs->list.next) - ++count; - - xf86ConfigDRI.bufs_count = count; - xf86ConfigDRI.bufs = xnfalloc(count * sizeof(*xf86ConfigDRI.bufs)); - - for (i = 0, bufs = drip->dri_buffers_lst; - i < count; - i++, bufs = bufs->list.next) { - - xf86ConfigDRI.bufs[i].count = bufs->buf_count; - xf86ConfigDRI.bufs[i].size = bufs->buf_size; - /* FIXME: Flags not implemented. These - could be used, for example, to specify a - contiguous block and/or write-combining - cache policy. */ - xf86ConfigDRI.bufs[i].flags = 0; - } - } -} -#endif - -static void -configExtensions(XF86ConfExtensionsPtr conf_ext) -{ - XF86OptionPtr o; - - if (conf_ext && conf_ext->ext_option_lst) { - for (o = conf_ext->ext_option_lst; o; o = xf86NextOption(o)) { - char *name = xf86OptionName(o); - char *val = xf86OptionValue(o); - char *n; - Bool enable = TRUE; - - /* Handle "No" */ - n = xf86NormalizeName(name); - if (strncmp(n, "no", 2) == 0) { - name += 2; - enable = FALSE; - } - - if (!val || - xf86NameCmp(val, "enable") == 0 || - xf86NameCmp(val, "enabled") == 0 || - xf86NameCmp(val, "on") == 0 || - xf86NameCmp(val, "1") == 0 || - xf86NameCmp(val, "yes") == 0 || - xf86NameCmp(val, "true") == 0) { - /* NOTHING NEEDED -- enabling is handled below */ - } else if (xf86NameCmp(val, "disable") == 0 || - xf86NameCmp(val, "disabled") == 0 || - xf86NameCmp(val, "off") == 0 || - xf86NameCmp(val, "0") == 0 || - xf86NameCmp(val, "no") == 0 || - xf86NameCmp(val, "false") == 0) { - enable = !enable; - } else { - xf86Msg(X_WARNING, "Ignoring unrecognized value \"%s\"\n", val); - xfree(n); - continue; - } - - if (EnableDisableExtension(name, enable)) { - xf86Msg(X_CONFIG, "Extension \"%s\" is %s\n", - name, enable ? "enabled" : "disabled"); - } else { - xf86Msg(X_WARNING, "Ignoring unrecognized extension \"%s\"\n", - name); - } - xfree(n); - } - } -} - -static Bool -configInput(IDevPtr inputp, XF86ConfInputPtr conf_input, MessageType from) -{ - xf86Msg(from, "|-->Input Device \"%s\"\n", conf_input->inp_identifier); - inputp->identifier = conf_input->inp_identifier; - inputp->driver = conf_input->inp_driver; - inputp->commonOptions = conf_input->inp_option_lst; - inputp->extraOptions = NULL; - - return TRUE; -} - -static Bool -modeIsPresent(DisplayModePtr mode, MonPtr monitorp) -{ - DisplayModePtr knownmodes = monitorp->Modes; - - /* all I can think of is a linear search... */ - while(knownmodes != NULL) - { - if(!strcmp(mode->name, knownmodes->name) && - !(knownmodes->type & M_T_DEFAULT)) - return TRUE; - knownmodes = knownmodes->next; - } - return FALSE; -} - -static Bool -addDefaultModes(MonPtr monitorp) -{ - DisplayModePtr mode; - DisplayModePtr last = monitorp->Last; - int i = 0; - - for (i = 0; i < xf86NumDefaultModes; i++) - { - mode = xf86DuplicateMode(&xf86DefaultModes[i]); - if (!modeIsPresent(mode, monitorp)) - { - monitorp->Modes = xf86ModesAdd(monitorp->Modes, mode); - last = mode; - } else { - xfree(mode); - } - } - monitorp->Last = last; - - return TRUE; -} - -static void -checkInput(serverLayoutPtr layout, Bool implicit_layout) { - checkCoreInputDevices(layout, implicit_layout); - - /* AllowEmptyInput and the "kbd" and "mouse" drivers are mutually - * exclusive. Trawl the list for mouse/kbd devices and disable them. - */ - if (xf86Info.allowEmptyInput && layout->inputs) - { - IDevPtr *dev = layout->inputs; - BOOL warned = FALSE; - - while(*dev) - { - if (strcmp((*dev)->driver, "kbd") == 0 || - strcmp((*dev)->driver, "mouse") == 0 || - strcmp((*dev)->driver, "vmmouse") == 0) - { - IDevPtr *current; - if (!warned) - { - xf86Msg(X_WARNING, "AllowEmptyInput is on, devices using " - "drivers 'kbd', 'mouse' or 'vmmouse' will be disabled.\n"); - warned = TRUE; - } - - xf86Msg(X_WARNING, "Disabling %s\n", (*dev)->identifier); - - current = dev; - xfree(*dev); - - do { - *current = *(current + 1); - current++; - } while(*current); - } else - dev++; - } - } -} - -/* - * load the config file and fill the global data structure - */ -ConfigStatus -xf86HandleConfigFile(Bool autoconfig) -{ - const char *filename, *dirname, *sysdirname; - char *filesearch, *dirsearch; - MessageType filefrom = X_DEFAULT; - MessageType dirfrom = X_DEFAULT; - char *scanptr; - Bool singlecard = 0; - Bool implicit_layout = FALSE; - - if (!autoconfig) { - if (getuid() == 0) { - filesearch = ROOT_CONFIGPATH; - dirsearch = ROOT_CONFIGDIRPATH; - } else { - filesearch = USER_CONFIGPATH; - dirsearch = USER_CONFIGDIRPATH; - } - - if (xf86ConfigFile) - filefrom = X_CMDLINE; - if (xf86ConfigDir) - dirfrom = X_CMDLINE; - - xf86initConfigFiles(); - sysdirname = xf86openConfigDirFiles(SYS_CONFIGDIRPATH, NULL, - PROJECTROOT); - dirname = xf86openConfigDirFiles(dirsearch, xf86ConfigDir, PROJECTROOT); - filename = xf86openConfigFile(filesearch, xf86ConfigFile, PROJECTROOT); - if (filename) { - xf86MsgVerb(filefrom, 0, "Using config file: \"%s\"\n", filename); - xf86ConfigFile = xnfstrdup(filename); - } else { - if (xf86ConfigFile) - xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n", - xf86ConfigFile); - } - if (dirname) { - xf86MsgVerb(dirfrom, 0, "Using config directory: \"%s\"\n", - dirname); - xf86ConfigDir = xnfstrdup(dirname); - } else { - if (xf86ConfigDir) - xf86Msg(X_ERROR, - "Unable to locate/open config directory: \"%s\"\n", - xf86ConfigDir); - } - if (sysdirname) - xf86MsgVerb(X_DEFAULT, 0, "Using system config directory \"%s\"\n", - sysdirname); - if (!filename && !dirname && !sysdirname) - return CONFIG_NOFILE; - } - - if ((xf86configptr = xf86readConfigFile ()) == NULL) { - xf86Msg(X_ERROR, "Problem parsing the config file\n"); - return CONFIG_PARSE_ERROR; - } - xf86closeConfigFile (); - - /* Initialise a few things. */ - - /* - * now we convert part of the information contained in the parser - * structures into our own structures. - * The important part here is to figure out which Screen Sections - * in the XF86Config file are active so that we can piece together - * the modes that we need later down the road. - * And while we are at it, we'll decode the rest of the stuff as well - */ - - /* First check if a layout section is present, and if it is valid. */ - - if (xf86configptr->conf_layout_lst == NULL || xf86ScreenName != NULL) { - if (xf86ScreenName == NULL) { - xf86Msg(X_DEFAULT, - "No Layout section. Using the first Screen section.\n"); - } - if (!configImpliedLayout(&xf86ConfigLayout, - xf86configptr->conf_screen_lst, - xf86configptr)) { - xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); - return CONFIG_PARSE_ERROR; - } - implicit_layout = TRUE; - } else { - if (xf86configptr->conf_flags != NULL) { - char *dfltlayout = NULL; - pointer optlist = xf86configptr->conf_flags->flg_option_lst; - - if (optlist && xf86FindOption(optlist, "defaultserverlayout")) - dfltlayout = xf86SetStrOption(optlist, "defaultserverlayout", NULL); - if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, - dfltlayout)) { - xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); - return CONFIG_PARSE_ERROR; - } - } else { - if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, - NULL)) { - xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); - return CONFIG_PARSE_ERROR; - } - } - } - - xf86ProcessOptions(-1, xf86ConfigLayout.options, LayoutOptions); - - if ((scanptr = xf86GetOptValString(LayoutOptions, LAYOUT_ISOLATEDEVICE))) { - ; /* IsolateDevice specified; overrides SingleCard */ - } else { - xf86GetOptValBool(LayoutOptions, LAYOUT_SINGLECARD, &singlecard); - if (singlecard) - scanptr = xf86ConfigLayout.screens->screen->device->busID; - } - if (scanptr) { - int bus, device, func; - if (strncmp(scanptr, "PCI:", 4) != 0) { - xf86Msg(X_WARNING, "Bus types other than PCI not yet isolable.\n" - "\tIgnoring IsolateDevice option.\n"); - } else if (sscanf(scanptr, "PCI:%d:%d:%d", &bus, &device, &func) == 3) { - xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); - xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); - xf86IsolateDevice.dev = device; - xf86IsolateDevice.func = func; - xf86Msg(X_INFO, - "Isolating PCI bus \"%d:%d:%d\"\n", bus, device, func); - } - } - - /* Now process everything else */ - if (!configServerFlags(xf86configptr->conf_flags,xf86ConfigLayout.options)){ - ErrorF ("Problem when converting the config data structures\n"); - return CONFIG_PARSE_ERROR; - } - - configFiles(xf86configptr->conf_files); - configExtensions(xf86configptr->conf_extensions); -#ifdef XF86DRI - configDRI(xf86configptr->conf_dri); -#endif - - checkInput(&xf86ConfigLayout, implicit_layout); - - /* - * Handle some command line options that can override some of the - * ServerFlags settings. - */ -#ifdef XF86VIDMODE - if (xf86VidModeDisabled) - xf86Info.vidModeEnabled = FALSE; - if (xf86VidModeAllowNonLocal) - xf86Info.vidModeAllowNonLocal = TRUE; -#endif - - if (xf86AllowMouseOpenFail) - xf86Info.allowMouseOpenFail = TRUE; - - return CONFIG_OK; -} - -Bool -xf86PathIsSafe(const char *path) -{ - return (xf86pathIsSafe(path) != 0); -} +/* + * Loosely based on code bearing the following copyright: + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + */ + +/* + * Copyright 1992-2003 by The XFree86 Project, Inc. + * Copyright 1997 by Metro Link, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * + * Authors: + * Dirk Hohndel + * David Dawes + * Marc La France + * Egbert Eich + * ... and others + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#ifdef XF86DRI +#include +#include +#endif + +#include "xf86.h" +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "xf86Config.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "configProcs.h" +#include "globals.h" +#include "extension.h" +#include "Pci.h" + +#include "xf86Xinput.h" +extern DeviceAssocRec mouse_assoc; + +#include "xkbsrv.h" + +#include "picture.h" + +/* + * These paths define the way the config file search is done. The escape + * sequences are documented in parser/scan.c. + */ +#ifndef ROOT_CONFIGPATH +#define ROOT_CONFIGPATH "%A," "%R," \ + "/etc/X11/%R," "%P/etc/X11/%R," \ + "%E," "%F," \ + "/etc/X11/%F," "%P/etc/X11/%F," \ + "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \ + "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \ + "%P/etc/X11/%X," \ + "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ + "%P/lib/X11/%X" +#endif +#ifndef USER_CONFIGPATH +#define USER_CONFIGPATH "/etc/X11/%S," "%P/etc/X11/%S," \ + "/etc/X11/%G," "%P/etc/X11/%G," \ + "/etc/X11/%X-%M," "/etc/X11/%X," "/etc/%X," \ + "%P/etc/X11/%X.%H," "%P/etc/X11/%X-%M," \ + "%P/etc/X11/%X," \ + "%P/lib/X11/%X.%H," "%P/lib/X11/%X-%M," \ + "%P/lib/X11/%X" +#endif +#ifndef ROOT_CONFIGDIRPATH +#define ROOT_CONFIGDIRPATH "%A," "%R," \ + "/etc/X11/%R," "%C/X11/%R," \ + "/etc/X11/%X," "%C/X11/%X" +#endif +#ifndef USER_CONFIGDIRPATH +#define USER_CONFIGDIRPATH "/etc/X11/%R," "%C/X11/%R," \ + "/etc/X11/%X," "%C/X11/%X" +#endif +#ifndef SYS_CONFIGDIRPATH +#define SYS_CONFIGDIRPATH "/usr/share/X11/%X," "%D/X11/%X" +#endif +#ifndef PROJECTROOT +#define PROJECTROOT "/usr/X11R6" +#endif + +static ModuleDefault ModuleDefaults[] = { + {.name = "extmod", .toLoad = TRUE, .load_opt=NULL}, +#ifdef DBE + {.name = "dbe", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef GLXEXT + {.name = "glx", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef XRECORD + {.name = "record", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef XF86DRI + {.name = "dri", .toLoad = TRUE, .load_opt=NULL}, +#endif +#ifdef DRI2 + {.name = "dri2", .toLoad = TRUE, .load_opt=NULL}, +#endif + {.name = NULL, .toLoad = FALSE, .load_opt=NULL} +}; + + +/* Forward declarations */ +static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, + int scrnum, MessageType from); +static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor); +static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, + Bool active); +static Bool configInput(IDevPtr inputp, XF86ConfInputPtr conf_input, + MessageType from); +static Bool configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display); +static Bool addDefaultModes(MonPtr monitorp); +#ifdef XF86DRI +static void configDRI(XF86ConfDRIPtr drip); +#endif +static void configExtensions(XF86ConfExtensionsPtr conf_ext); + +/* + * xf86GetPathElem -- + * Extract a single element from the font path string starting at + * pnt. The font path element will be returned, and pnt will be + * updated to point to the start of the next element, or set to + * NULL if there are no more. + */ +static char * +xf86GetPathElem(char **pnt) +{ + char *p1; + + p1 = *pnt; + *pnt = index(*pnt, ','); + if (*pnt != NULL) { + **pnt = '\0'; + *pnt += 1; + } + return(p1); +} + +/* + * xf86ValidateFontPath -- + * Validates the user-specified font path. Each element that + * begins with a '/' is checked to make sure the directory exists. + * If the directory exists, the existence of a file named 'fonts.dir' + * is checked. If either check fails, an error is printed and the + * element is removed from the font path. + */ + +#define DIR_FILE "/fonts.dir" +static char * +xf86ValidateFontPath(char *path) +{ + char *tmp_path, *out_pnt, *path_elem, *next, *p1, *dir_elem; + struct stat stat_buf; + int flag; + int dirlen; + + tmp_path = calloc(1,strlen(path)+1); + out_pnt = tmp_path; + path_elem = NULL; + next = path; + while (next != NULL) { + path_elem = xf86GetPathElem(&next); + if (*path_elem == '/') { + dir_elem = xnfcalloc(1, strlen(path_elem) + 1); + if ((p1 = strchr(path_elem, ':')) != 0) + dirlen = p1 - path_elem; + else + dirlen = strlen(path_elem); + strncpy(dir_elem, path_elem, dirlen); + dir_elem[dirlen] = '\0'; + flag = stat(dir_elem, &stat_buf); + if (flag == 0) + if (!S_ISDIR(stat_buf.st_mode)) + flag = -1; + if (flag != 0) { + xf86Msg(X_WARNING, "The directory \"%s\" does not exist.\n", dir_elem); + xf86ErrorF("\tEntry deleted from font path.\n"); + free(dir_elem); + continue; + } + else { + p1 = xnfalloc(strlen(dir_elem)+strlen(DIR_FILE)+1); + strcpy(p1, dir_elem); + strcat(p1, DIR_FILE); + flag = stat(p1, &stat_buf); + if (flag == 0) + if (!S_ISREG(stat_buf.st_mode)) + flag = -1; + free(p1); + if (flag != 0) { + xf86Msg(X_WARNING, + "`fonts.dir' not found (or not valid) in \"%s\".\n", + dir_elem); + xf86ErrorF("\tEntry deleted from font path.\n"); + xf86ErrorF("\t(Run 'mkfontdir' on \"%s\").\n", dir_elem); + free(dir_elem); + continue; + } + } + free(dir_elem); + } + + /* + * Either an OK directory, or a font server name. So add it to + * the path. + */ + if (out_pnt != tmp_path) + *out_pnt++ = ','; + strcat(out_pnt, path_elem); + out_pnt += strlen(path_elem); + } + return(tmp_path); +} + + +/* + * use the datastructure that the parser provides and pick out the parts + * that we need at this point + */ +char ** +xf86ModulelistFromConfig(pointer **optlist) +{ + int count = 0, i = 0; + char **modulearray; + char *ignore[] = { "GLcore", "speedo", "bitmap", "drm", + "freetype", "type1", + NULL }; + pointer *optarray; + XF86LoadPtr modp; + Bool found; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + if (xf86configptr->conf_modules) { + /* Walk the disable list and let people know what we've parsed to + * not be loaded + */ + modp = xf86configptr->conf_modules->mod_disable_lst; + while (modp) { + xf86Msg(X_WARNING, "\"%s\" will not be loaded unless you've specified it to be loaded elsewhere.\n", modp->load_name); + modp = (XF86LoadPtr) modp->list.next; + } + /* + * Walk the default settings table. For each module listed to be + * loaded, make sure it's in the mod_load_lst. If it's not, make + * sure it's not in the mod_no_load_lst. If it's not disabled, + * append it to mod_load_lst + */ + for (i=0 ; ModuleDefaults[i].name != NULL ; i++) { + if (ModuleDefaults[i].toLoad == FALSE) { + xf86Msg(X_WARNING, "\"%s\" is not to be loaded by default. Skipping.\n", ModuleDefaults[i].name); + continue; + } + found = FALSE; + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) { + xf86Msg(X_INFO, "\"%s\" will be loaded. This was enabled by default and also specified in the config file.\n", ModuleDefaults[i].name); + found = TRUE; + break; + } + modp = (XF86LoadPtr) modp->list.next; + } + if (found == FALSE) { + modp = xf86configptr->conf_modules->mod_disable_lst; + while (modp) { + if (strcmp(modp->load_name, ModuleDefaults[i].name) == 0) { + xf86Msg(X_INFO, "\"%s\" will be loaded even though the default is to disable it.\n", ModuleDefaults[i].name); + found = TRUE; + break; + } + modp = (XF86LoadPtr) modp->list.next; + } + } + if (found == FALSE) { + XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules; + ptr = xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt); + xf86Msg(X_INFO, "\"%s\" will be loaded by default.\n", ModuleDefaults[i].name); + } + } + } else { + xf86configptr->conf_modules = xnfcalloc(1, sizeof(XF86ConfModuleRec)); + for (i=0 ; ModuleDefaults[i].name != NULL ; i++) { + if (ModuleDefaults[i].toLoad == TRUE) { + XF86LoadPtr ptr = (XF86LoadPtr)xf86configptr->conf_modules; + ptr = xf86addNewLoadDirective(ptr, ModuleDefaults[i].name, XF86_LOAD_MODULE, ModuleDefaults[i].load_opt); + } + } + } + + /* + * Walk the list of modules in the "Module" section to determine how + * many we have. + */ + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + for (i = 0; ignore[i]; i++) { + if (strcmp(modp->load_name, ignore[i]) == 0) + modp->ignore = 1; + } + if (!modp->ignore) + count++; + modp = (XF86LoadPtr) modp->list.next; + } + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + optarray = xnfalloc((count + 1) * sizeof(pointer)); + count = 0; + if (xf86configptr->conf_modules) { + modp = xf86configptr->conf_modules->mod_load_lst; + while (modp) { + if (!modp->ignore) { + modulearray[count] = modp->load_name; + optarray[count] = modp->load_opt; + count++; + } + modp = (XF86LoadPtr) modp->list.next; + } + } + modulearray[count] = NULL; + optarray[count] = NULL; + if (optlist) + *optlist = optarray; + else + free(optarray); + return modulearray; +} + + +char ** +xf86DriverlistFromConfig(void) +{ + int count = 0; + int j; + char **modulearray; + screenLayoutPtr slp; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + /* + * Walk the list of driver lines in active "Device" sections to + * determine now many implicitly loaded modules there are. + * + */ + if (xf86ConfigLayout.screens) { + slp = xf86ConfigLayout.screens; + while ((slp++)->screen) { + count++; + } + } + + /* + * Handle the set of inactive "Device" sections. + */ + j = 0; + while (xf86ConfigLayout.inactives[j++].identifier) + count++; + + if (count == 0) + return NULL; + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + count = 0; + slp = xf86ConfigLayout.screens; + while (slp->screen) { + modulearray[count] = slp->screen->device->driver; + count++; + slp++; + } + + j = 0; + + while (xf86ConfigLayout.inactives[j].identifier) + modulearray[count++] = xf86ConfigLayout.inactives[j++].driver; + + modulearray[count] = NULL; + + /* Remove duplicates */ + for (count = 0; modulearray[count] != NULL; count++) { + int i; + + for (i = 0; i < count; i++) + if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { + modulearray[count] = ""; + break; + } + } + return modulearray; +} + +char ** +xf86InputDriverlistFromConfig(void) +{ + int count = 0; + char **modulearray; + IDevPtr* idp; + + /* + * make sure the config file has been parsed and that we have a + * ModulePath set; if no ModulePath was given, use the default + * ModulePath + */ + if (xf86configptr == NULL) { + xf86Msg(X_ERROR, "Cannot access global config data structure\n"); + return NULL; + } + + /* + * Walk the list of driver lines in active "InputDevice" sections to + * determine now many implicitly loaded modules there are. + */ + if (xf86ConfigLayout.inputs) { + idp = xf86ConfigLayout.inputs; + while (*idp) { + count++; + idp++; + } + } + + if (count == 0) + return NULL; + + /* + * allocate the memory and walk the list again to fill in the pointers + */ + modulearray = xnfalloc((count + 1) * sizeof(char*)); + count = 0; + idp = xf86ConfigLayout.inputs; + while (idp && *idp) { + modulearray[count] = (*idp)->driver; + count++; + idp++; + } + modulearray[count] = NULL; + + /* Remove duplicates */ + for (count = 0; modulearray[count] != NULL; count++) { + int i; + + for (i = 0; i < count; i++) + if (xf86NameCmp(modulearray[i], modulearray[count]) == 0) { + modulearray[count] = ""; + break; + } + } + return modulearray; +} + +static void +fixup_video_driver_list(char **drivers) +{ + static const char *fallback[4] = { "vesa", "fbdev", "wsfb", NULL }; + char **end, **drv; + char *x; + char **ati, **atimisc; + int i; + + /* walk to the end of the list */ + for (end = drivers; *end && **end; end++) ; + end--; + + /* + * for each of the fallback drivers, if we find it in the list, + * swap it with the last available non-fallback driver. + */ + for (i = 0; fallback[i]; i++) { + for (drv = drivers; drv != end; drv++) { + if (strstr(*drv, fallback[i])) { + x = *drv; *drv = *end; *end = x; + end--; + break; + } + } + } + /* + * since the ati wrapper driver is gross and awful, sort ati before + * atimisc, which makes sure all the ati symbols are visible in xorgcfg. + */ + for (drv = drivers; drv != end; drv++) { + if (!strcmp(*drv, "atimisc")) { + atimisc = drv; + for (drv = atimisc; drv != end; drv++) { + if (!strcmp(*drv, "ati")) { + ati = drv; + x = *ati; *ati = *atimisc; *atimisc = x; + return; + } + } + /* if we get here, ati was already ahead of atimisc */ + return; + } + } +} + +static char ** +GenerateDriverlist(char * dirname) +{ + char **ret; + const char *subdirs[] = { dirname, NULL }; + static const char *patlist[] = {"(.*)_drv\\.so", "(.*)_drv\\.o", NULL}; + ret = LoaderListDirs(subdirs, patlist); + + /* fix up the probe order for video drivers */ + if (strstr(dirname, "drivers") && ret != NULL) + fixup_video_driver_list(ret); + + return ret; +} + +char ** +xf86DriverlistFromCompile(void) +{ + static char **driverlist = NULL; + + if (!driverlist) + driverlist = GenerateDriverlist("drivers"); + + return driverlist; +} + +/* + * xf86ConfigError -- + * Print a READABLE ErrorMessage!!! All information that is + * available is printed. + */ +static void +xf86ConfigError(char *msg, ...) +{ + va_list ap; + + ErrorF("\nConfig Error:\n"); + va_start(ap, msg); + VErrorF(msg, ap); + va_end(ap); + ErrorF("\n"); + return; +} + +static void +configFiles(XF86ConfFilesPtr fileconf) +{ + MessageType pathFrom; + Bool must_copy; + int size, countDirs; + char *temp_path, *log_buf, *start, *end; + + /* FontPath */ + must_copy = TRUE; + + temp_path = defaultFontPath ? defaultFontPath : ""; + if (xf86fpFlag) + pathFrom = X_CMDLINE; + else if (fileconf && fileconf->file_fontpath) { + pathFrom = X_CONFIG; + if (xf86Info.useDefaultFontPath) { + defaultFontPath = Xprintf("%s%s%s", + fileconf->file_fontpath, + *temp_path ? "," : "", temp_path); + if (defaultFontPath != NULL) { + must_copy = FALSE; + } + } + else + defaultFontPath = fileconf->file_fontpath; + } + else + pathFrom = X_DEFAULT; + temp_path = defaultFontPath ? defaultFontPath : ""; + + /* xf86ValidateFontPath modifies its argument, but returns a copy of it. */ + temp_path = must_copy ? xnfstrdup(defaultFontPath) : defaultFontPath; + defaultFontPath = xf86ValidateFontPath(temp_path); + free(temp_path); + + /* make fontpath more readable in the logfiles */ + countDirs = 1; + temp_path = defaultFontPath; + while ((temp_path = index(temp_path, ',')) != NULL) { + countDirs++; + temp_path++; + } + + log_buf = xnfalloc(strlen(defaultFontPath) + (2 * countDirs) + 1); + temp_path = log_buf; + start = defaultFontPath; + while((end = index(start, ',')) != NULL) { + size = (end - start) + 1; + *(temp_path++) = '\t'; + strncpy(temp_path, start, size); + temp_path += size; + *(temp_path++) = '\n'; + start += size; + } + /* copy last entry */ + *(temp_path++) = '\t'; + strcpy(temp_path, start); + xf86Msg(pathFrom, "FontPath set to:\n%s\n", log_buf); + free(log_buf); + + /* ModulePath */ + + if (fileconf) { + if (xf86ModPathFrom != X_CMDLINE && fileconf->file_modulepath) { + xf86ModulePath = fileconf->file_modulepath; + xf86ModPathFrom = X_CONFIG; + } + } + + xf86Msg(xf86ModPathFrom, "ModulePath set to \"%s\"\n", xf86ModulePath); + + if (!xf86xkbdirFlag && fileconf && fileconf->file_xkbdir) { + XkbBaseDirectory = fileconf->file_xkbdir; + xf86Msg(X_CONFIG, "XKB base directory set to \"%s\"\n", + XkbBaseDirectory); + } +#if 0 + /* LogFile */ + /* + * XXX The problem with this is that the log file is already open. + * One option might be to copy the exiting contents to the new location. + * and re-open it. The down side is that the default location would + * already have been overwritten. Another option would be to start with + * unique temporary location, then copy it once the correct name is known. + * A problem with this is what happens if the server exits before that + * happens. + */ + if (xf86LogFileFrom == X_DEFAULT && fileconf->file_logfile) { + xf86LogFile = fileconf->file_logfile; + xf86LogFileFrom = X_CONFIG; + } +#endif + + return; +} + +typedef enum { + FLAG_NOTRAPSIGNALS, + FLAG_DONTVTSWITCH, + FLAG_DONTZAP, + FLAG_DONTZOOM, + FLAG_DISABLEVIDMODE, + FLAG_ALLOWNONLOCAL, + FLAG_ALLOWMOUSEOPENFAIL, + FLAG_VTSYSREQ, + FLAG_SAVER_BLANKTIME, + FLAG_DPMS_STANDBYTIME, + FLAG_DPMS_SUSPENDTIME, + FLAG_DPMS_OFFTIME, + FLAG_PIXMAP, + FLAG_PC98, + FLAG_NOPM, + FLAG_XINERAMA, + FLAG_LOG, + FLAG_RENDER_COLORMAP_MODE, + FLAG_RANDR, + FLAG_AIGLX, + FLAG_IGNORE_ABI, + FLAG_ALLOW_EMPTY_INPUT, + FLAG_USE_DEFAULT_FONT_PATH, + FLAG_AUTO_ADD_DEVICES, + FLAG_AUTO_ENABLE_DEVICES, + FLAG_GLX_VISUALS, + FLAG_DRI2, + FLAG_USE_SIGIO +} FlagValues; + +/** + * NOTE: the last value for each entry is NOT the default. It is set to TRUE + * if the parser found the option in the config file. + */ +static OptionInfoRec FlagOptions[] = { + { FLAG_NOTRAPSIGNALS, "NoTrapSignals", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTVTSWITCH, "DontVTSwitch", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTZAP, "DontZap", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DONTZOOM, "DontZoom", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_DISABLEVIDMODE, "DisableVidModeExtension", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_ALLOWNONLOCAL, "AllowNonLocalXvidtune", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_ALLOWMOUSEOPENFAIL, "AllowMouseOpenFail", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_VTSYSREQ, "VTSysReq", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_SAVER_BLANKTIME, "BlankTime" , OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_STANDBYTIME, "StandbyTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_SUSPENDTIME, "SuspendTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_DPMS_OFFTIME, "OffTime", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_PIXMAP, "Pixmap", OPTV_INTEGER, + {0}, FALSE }, + { FLAG_PC98, "PC98", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_NOPM, "NoPM", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_XINERAMA, "Xinerama", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_LOG, "Log", OPTV_STRING, + {0}, FALSE }, + { FLAG_RENDER_COLORMAP_MODE, "RenderColormapMode", OPTV_STRING, + {0}, FALSE }, + { FLAG_RANDR, "RandR", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AIGLX, "AIGLX", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_ALLOW_EMPTY_INPUT, "AllowEmptyInput", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_IGNORE_ABI, "IgnoreABI", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_USE_DEFAULT_FONT_PATH, "UseDefaultFontPath", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AUTO_ADD_DEVICES, "AutoAddDevices", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_AUTO_ENABLE_DEVICES, "AutoEnableDevices", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_GLX_VISUALS, "GlxVisuals", OPTV_STRING, + {0}, FALSE }, + { FLAG_DRI2, "DRI2", OPTV_BOOLEAN, + {0}, FALSE }, + { FLAG_USE_SIGIO, "UseSIGIO", OPTV_BOOLEAN, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +#ifdef SUPPORT_PC98 +static Bool +detectPC98(void) +{ + unsigned char buf[2]; + + if (xf86ReadBIOS(0xf8000, 0xe80, buf, 2) != 2) + return FALSE; + if ((buf[0] == 0x98) && (buf[1] == 0x21)) + return TRUE; + else + return FALSE; +} +#endif + +static Bool +configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) +{ + XF86OptionPtr optp, tmp; + int i; + Pix24Flags pix24 = Pix24DontCare; + Bool value; + MessageType from; + const char *s; + XkbRMLVOSet set; + /* Default options. */ + set.rules = "base"; + set.model = "pc105"; + set.layout = "us"; + set.variant = NULL; + set.options = NULL; + + /* + * Merge the ServerLayout and ServerFlags options. The former have + * precedence over the latter. + */ + optp = NULL; + if (flagsconf && flagsconf->flg_option_lst) + optp = xf86optionListDup(flagsconf->flg_option_lst); + if (layoutopts) { + tmp = xf86optionListDup(layoutopts); + if (optp) + optp = xf86optionListMerge(optp, tmp); + else + optp = tmp; + } + + xf86ProcessOptions(-1, optp, FlagOptions); + + xf86GetOptValBool(FlagOptions, FLAG_NOTRAPSIGNALS, &xf86Info.notrapSignals); + xf86GetOptValBool(FlagOptions, FLAG_DONTVTSWITCH, &xf86Info.dontVTSwitch); + xf86GetOptValBool(FlagOptions, FLAG_DONTZAP, &xf86Info.dontZap); + xf86GetOptValBool(FlagOptions, FLAG_DONTZOOM, &xf86Info.dontZoom); + + xf86GetOptValBool(FlagOptions, FLAG_IGNORE_ABI, &xf86Info.ignoreABI); + if (xf86Info.ignoreABI) { + xf86Msg(X_CONFIG, "Ignoring ABI Version\n"); + } + + if (xf86SIGIOSupported()) { + xf86Info.useSIGIO = xf86ReturnOptValBool(FlagOptions, FLAG_USE_SIGIO, USE_SIGIO_BY_DEFAULT); + if (xf86IsOptionSet(FlagOptions, FLAG_USE_SIGIO)) { + from = X_CONFIG; + } else { + from = X_DEFAULT; + } + if (!xf86Info.useSIGIO) { + xf86Msg(from, "Disabling SIGIO handlers for input devices\n"); + } else if (from == X_CONFIG) { + xf86Msg(from, "Enabling SIGIO handlers for input devices\n"); + } + } else { + xf86Info.useSIGIO = FALSE; + } + + if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ADD_DEVICES)) { + xf86GetOptValBool(FlagOptions, FLAG_AUTO_ADD_DEVICES, + &xf86Info.autoAddDevices); + from = X_CONFIG; + } + else { + from = X_DEFAULT; + } + xf86Msg(from, "%sutomatically adding devices\n", + xf86Info.autoAddDevices ? "A" : "Not a"); + + if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_ENABLE_DEVICES)) { + xf86GetOptValBool(FlagOptions, FLAG_AUTO_ENABLE_DEVICES, + &xf86Info.autoEnableDevices); + from = X_CONFIG; + } + else { + from = X_DEFAULT; + } + xf86Msg(from, "%sutomatically enabling devices\n", + xf86Info.autoEnableDevices ? "A" : "Not a"); + + /* + * Set things up based on the config file information. Some of these + * settings may be overridden later when the command line options are + * checked. + */ +#ifdef XF86VIDMODE + if (xf86GetOptValBool(FlagOptions, FLAG_DISABLEVIDMODE, &value)) + xf86Info.vidModeEnabled = !value; + if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWNONLOCAL, &value)) + xf86Info.vidModeAllowNonLocal = value; +#endif + + if (xf86GetOptValBool(FlagOptions, FLAG_ALLOWMOUSEOPENFAIL, &value)) + xf86Info.allowMouseOpenFail = value; + + if (xf86GetOptValBool(FlagOptions, FLAG_VTSYSREQ, &value)) { +#ifdef USE_VT_SYSREQ + xf86Info.vtSysreq = value; + xf86Msg(X_CONFIG, "VTSysReq %s\n", value ? "enabled" : "disabled"); +#else + if (value) + xf86Msg(X_WARNING, "VTSysReq is not supported on this OS\n"); +#endif + } + + xf86Info.pmFlag = TRUE; + if (xf86GetOptValBool(FlagOptions, FLAG_NOPM, &value)) + xf86Info.pmFlag = !value; + { + if ((s = xf86GetOptValString(FlagOptions, FLAG_LOG))) { + if (!xf86NameCmp(s,"flush")) { + xf86Msg(X_CONFIG, "Flushing logfile enabled\n"); + xf86Info.log = LogFlush; + LogSetParameter(XLOG_FLUSH, TRUE); + } else if (!xf86NameCmp(s,"sync")) { + xf86Msg(X_CONFIG, "Syncing logfile enabled\n"); + xf86Info.log = LogSync; + LogSetParameter(XLOG_FLUSH, TRUE); + LogSetParameter(XLOG_SYNC, TRUE); + } else { + xf86Msg(X_WARNING,"Unknown Log option\n"); + } + } + } + + { + if ((s = xf86GetOptValString(FlagOptions, FLAG_RENDER_COLORMAP_MODE))){ + int policy = PictureParseCmapPolicy (s); + if (policy == PictureCmapPolicyInvalid) + xf86Msg(X_WARNING, "Unknown colormap policy \"%s\"\n", s); + else + { + xf86Msg(X_CONFIG, "Render colormap policy set to %s\n", s); + PictureCmapPolicy = policy; + } + } + } + +#ifdef RANDR + xf86Info.disableRandR = FALSE; + xf86Info.randRFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_RANDR, &value)) { + xf86Info.disableRandR = !value; + xf86Info.randRFrom = X_CONFIG; + } +#endif + + xf86Info.aiglx = TRUE; + xf86Info.aiglxFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { + xf86Info.aiglx = value; + xf86Info.aiglxFrom = X_CONFIG; + } + +#ifdef GLXEXT + xf86Info.glxVisuals = XF86_GlxVisualsTypical; + xf86Info.glxVisualsFrom = X_DEFAULT; + if ((s = xf86GetOptValString(FlagOptions, FLAG_GLX_VISUALS))) { + if (!xf86NameCmp(s, "minimal")) { + xf86Info.glxVisuals = XF86_GlxVisualsMinimal; + } else if (!xf86NameCmp(s, "typical")) { + xf86Info.glxVisuals = XF86_GlxVisualsTypical; + } else if (!xf86NameCmp(s, "all")) { + xf86Info.glxVisuals = XF86_GlxVisualsAll; + } else { + xf86Msg(X_WARNING,"Unknown GlxVisuals option\n"); + } + } + + if (xf86GetOptValBool(FlagOptions, FLAG_AIGLX, &value)) { + xf86Info.aiglx = value; + xf86Info.aiglxFrom = X_CONFIG; + } +#endif + + /* AllowEmptyInput is automatically true if we're hotplugging */ + xf86Info.allowEmptyInput = (xf86Info.autoAddDevices && xf86Info.autoEnableDevices); + xf86GetOptValBool(FlagOptions, FLAG_ALLOW_EMPTY_INPUT, &xf86Info.allowEmptyInput); + + /* AEI on? Then we're not using kbd, so use the evdev rules set. */ +#if defined(linux) + if (xf86Info.allowEmptyInput) + set.rules = "evdev"; +#endif + XkbSetRulesDflts(&set); + + xf86Info.useDefaultFontPath = TRUE; + xf86Info.useDefaultFontPathFrom = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_USE_DEFAULT_FONT_PATH, &value)) { + xf86Info.useDefaultFontPath = value; + xf86Info.useDefaultFontPathFrom = X_CONFIG; + } + +/* Make sure that timers don't overflow CARD32's after multiplying */ +#define MAX_TIME_IN_MIN (0x7fffffff / MILLI_PER_MIN) + + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_SAVER_BLANKTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + ScreenSaverTime = defaultScreenSaverTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("BlankTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + +#ifdef DPMSExtension + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_STANDBYTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSStandbyTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("StandbyTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_SUSPENDTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSSuspendTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("SuspendTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_DPMS_OFFTIME, &i); + if ((i >= 0) && (i < MAX_TIME_IN_MIN)) + DPMSOffTime = i * MILLI_PER_MIN; + else if (i != -1) + xf86ConfigError("OffTime value %d outside legal range of 0 - %d minutes", + i, MAX_TIME_IN_MIN); +#endif + + i = -1; + xf86GetOptValInteger(FlagOptions, FLAG_PIXMAP, &i); + switch (i) { + case 24: + pix24 = Pix24Use24; + break; + case 32: + pix24 = Pix24Use32; + break; + case -1: + break; + default: + xf86ConfigError("Pixmap option's value (%d) must be 24 or 32\n", i); + return FALSE; + } + if (xf86Pix24 != Pix24DontCare) { + xf86Info.pixmap24 = xf86Pix24; + xf86Info.pix24From = X_CMDLINE; + } else if (pix24 != Pix24DontCare) { + xf86Info.pixmap24 = pix24; + xf86Info.pix24From = X_CONFIG; + } else { + xf86Info.pixmap24 = Pix24DontCare; + xf86Info.pix24From = X_DEFAULT; + } +#ifdef SUPPORT_PC98 + if (xf86GetOptValBool(FlagOptions, FLAG_PC98, &value)) { + xf86Info.pc98 = value; + if (value) { + xf86Msg(X_CONFIG, "Japanese PC98 architecture\n"); + } + } else + if (detectPC98()) { + xf86Info.pc98 = TRUE; + xf86Msg(X_PROBED, "Japanese PC98 architecture\n"); + } +#endif + +#ifdef PANORAMIX + from = X_DEFAULT; + if (!noPanoramiXExtension) + from = X_CMDLINE; + else if (xf86GetOptValBool(FlagOptions, FLAG_XINERAMA, &value)) { + noPanoramiXExtension = !value; + from = X_CONFIG; + } + if (!noPanoramiXExtension) + xf86Msg(from, "Xinerama: enabled\n"); +#endif + +#ifdef DRI2 + xf86Info.dri2 = FALSE; + xf86Info.dri2From = X_DEFAULT; + if (xf86GetOptValBool(FlagOptions, FLAG_DRI2, &value)) { + xf86Info.dri2 = value; + xf86Info.dri2From = X_CONFIG; + } +#endif + + return TRUE; +} + +Bool xf86DRI2Enabled(void) +{ + return xf86Info.dri2; +} + +/* + * Locate the core input devices. These can be specified/located in + * the following ways, in order of priority: + * + * 1. The InputDevices named by the -pointer and -keyboard command line + * options. + * 2. The "CorePointer" and "CoreKeyboard" InputDevices referred to by + * the active ServerLayout. + * 3. The first InputDevices marked as "CorePointer" and "CoreKeyboard". + * 4. The first InputDevices that use 'keyboard' or 'kbd' and a valid mouse + * driver (mouse, synaptics, evdev, vmmouse, void) + * 5. Default devices with an empty (default) configuration. These defaults + * will reference the 'mouse' and 'keyboard' drivers. + */ + +static Bool +checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) +{ + IDevPtr corePointer = NULL, coreKeyboard = NULL; + Bool foundPointer = FALSE, foundKeyboard = FALSE; + const char *pointerMsg = NULL, *keyboardMsg = NULL; + IDevPtr *devs, /* iterator */ + indp; + IDevRec Pointer, Keyboard; + XF86ConfInputPtr confInput; + XF86ConfInputRec defPtr, defKbd; + int count = 0; + MessageType from = X_DEFAULT; + int found = 0; + const char *mousedrivers[] = { "mouse", "synaptics", "evdev", "vmmouse", + "void", NULL }; + + /* + * First check if a core pointer or core keyboard have been specified + * in the active ServerLayout. If more than one is specified for either, + * remove the core attribute from the later ones. + */ + for (devs = servlayoutp->inputs; devs && *devs; devs++) { + pointer opt1 = NULL, opt2 = NULL; + indp = *devs; + if (indp->commonOptions && + xf86CheckBoolOption(indp->commonOptions, "CorePointer", FALSE)) { + opt1 = indp->commonOptions; + } + if (indp->extraOptions && + xf86CheckBoolOption(indp->extraOptions, "CorePointer", FALSE)) { + opt2 = indp->extraOptions; + } + if (opt1 || opt2) { + if (!corePointer) { + corePointer = indp; + } else { + if (opt1) + xf86ReplaceBoolOption(opt1, "CorePointer", FALSE); + if (opt2) + xf86ReplaceBoolOption(opt2, "CorePointer", FALSE); + xf86Msg(X_WARNING, "Duplicate core pointer devices. " + "Removing core pointer attribute from \"%s\"\n", + indp->identifier); + } + } + opt1 = opt2 = NULL; + if (indp->commonOptions && + xf86CheckBoolOption(indp->commonOptions, "CoreKeyboard", FALSE)) { + opt1 = indp->commonOptions; + } + if (indp->extraOptions && + xf86CheckBoolOption(indp->extraOptions, "CoreKeyboard", FALSE)) { + opt2 = indp->extraOptions; + } + if (opt1 || opt2) { + if (!coreKeyboard) { + coreKeyboard = indp; + } else { + if (opt1) + xf86ReplaceBoolOption(opt1, "CoreKeyboard", FALSE); + if (opt2) + xf86ReplaceBoolOption(opt2, "CoreKeyboard", FALSE); + xf86Msg(X_WARNING, "Duplicate core keyboard devices. " + "Removing core keyboard attribute from \"%s\"\n", + indp->identifier); + } + } + count++; + } + + confInput = NULL; + + /* 1. Check for the -pointer command line option. */ + if (xf86PointerName) { + confInput = xf86findInput(xf86PointerName, + xf86configptr->conf_input_lst); + if (!confInput) { + xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n", + xf86PointerName); + return FALSE; + } + from = X_CMDLINE; + /* + * If one was already specified in the ServerLayout, it needs to be + * removed. + */ + if (corePointer) { + for (devs = servlayoutp->inputs; devs && *devs; devs++) + if (*devs == corePointer) + { + free(*devs); + *devs = (IDevPtr)0x1; /* ensure we dont skip next loop*/ + break; + } + for (; devs && *devs; devs++) + devs[0] = devs[1]; + count--; + } + corePointer = NULL; + foundPointer = TRUE; + } + + /* 2. ServerLayout-specified core pointer. */ + if (corePointer) { + foundPointer = TRUE; + from = X_CONFIG; + } + + /* 3. First core pointer device. */ + if (!foundPointer && (!xf86Info.allowEmptyInput || implicitLayout)) { + XF86ConfInputPtr p; + + for (p = xf86configptr->conf_input_lst; p; p = p->list.next) { + if (p->inp_option_lst && + xf86CheckBoolOption(p->inp_option_lst, "CorePointer", FALSE)) { + confInput = p; + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "first core pointer device"; + break; + } + } + } + + /* 4. First pointer with an allowed mouse driver. */ + if (!foundPointer && !xf86Info.allowEmptyInput) { + const char **driver = mousedrivers; + confInput = xf86findInput(CONF_IMPLICIT_POINTER, + xf86configptr->conf_input_lst); + while (*driver && !confInput) { + confInput = xf86findInputByDriver(*driver, + xf86configptr->conf_input_lst); + driver++; + } + if (confInput) { + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "first mouse device"; + } + } + + /* 5. Built-in default. */ + if (!foundPointer && !xf86Info.allowEmptyInput) { + bzero(&defPtr, sizeof(defPtr)); + defPtr.inp_identifier = strdup(""); + defPtr.inp_driver = strdup("mouse"); + confInput = &defPtr; + foundPointer = TRUE; + from = X_DEFAULT; + pointerMsg = "default mouse configuration"; + } + + /* Add the core pointer device to the layout, and set it to Core. */ + if (foundPointer && confInput) { + foundPointer = configInput(&Pointer, confInput, from); + if (foundPointer) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(IDevPtr)); + devs[count - 1] = xnfalloc(sizeof(IDevRec)); + *devs[count - 1] = Pointer; + devs[count - 1]->extraOptions = + xf86addNewOption(NULL, xnfstrdup("CorePointer"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + if (!foundPointer && !xf86Info.allowEmptyInput) { + /* This shouldn't happen. */ + xf86Msg(X_ERROR, "Cannot locate a core pointer device.\n"); + return FALSE; + } + + /* + * always synthesize a 'mouse' section configured to send core + * events, unless a 'void' section is found, in which case the user + * probably wants to run footless. + * + * If you're using an evdev keyboard and expect a default mouse + * section ... deal. + */ + for (devs = servlayoutp->inputs; devs && *devs; devs++) { + const char **driver = mousedrivers; + while(*driver) { + if (!strcmp((*devs)->driver, *driver)) { + found = 1; + break; + } + driver++; + } + } + if (!found && !xf86Info.allowEmptyInput) { + xf86Msg(X_INFO, "No default mouse found, adding one\n"); + bzero(&defPtr, sizeof(defPtr)); + defPtr.inp_identifier = strdup(""); + defPtr.inp_driver = strdup("mouse"); + confInput = &defPtr; + foundPointer = configInput(&Pointer, confInput, from); + if (foundPointer) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(IDevPtr)); + devs[count - 1] = xnfalloc(sizeof(IDevRec)); + *devs[count - 1] = Pointer; + devs[count - 1]->extraOptions = + xf86addNewOption(NULL, xnfstrdup("AlwaysCore"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + confInput = NULL; + + /* 1. Check for the -keyboard command line option. */ + if (xf86KeyboardName) { + confInput = xf86findInput(xf86KeyboardName, + xf86configptr->conf_input_lst); + if (!confInput) { + xf86Msg(X_ERROR, "No InputDevice section called \"%s\"\n", + xf86KeyboardName); + return FALSE; + } + from = X_CMDLINE; + /* + * If one was already specified in the ServerLayout, it needs to be + * removed. + */ + if (coreKeyboard) { + for (devs = servlayoutp->inputs; devs && *devs; devs++) + if (*devs == coreKeyboard) + { + free(*devs); + *devs = (IDevPtr)0x1; /* ensure we dont skip next loop */ + break; + } + for (; devs && *devs; devs++) + devs[0] = devs[1]; + count--; + } + coreKeyboard = NULL; + foundKeyboard = TRUE; + } + + /* 2. ServerLayout-specified core keyboard. */ + if (coreKeyboard) { + foundKeyboard = TRUE; + from = X_CONFIG; + } + + /* 3. First core keyboard device. */ + if (!foundKeyboard && (!xf86Info.allowEmptyInput || implicitLayout)) { + XF86ConfInputPtr p; + + for (p = xf86configptr->conf_input_lst; p; p = p->list.next) { + if (p->inp_option_lst && + xf86CheckBoolOption(p->inp_option_lst, "CoreKeyboard", FALSE)) { + confInput = p; + foundKeyboard = TRUE; + from = X_DEFAULT; + keyboardMsg = "first core keyboard device"; + break; + } + } + } + + /* 4. First keyboard with 'keyboard' or 'kbd' as the driver. */ + if (!foundKeyboard && !xf86Info.allowEmptyInput) { + confInput = xf86findInput(CONF_IMPLICIT_KEYBOARD, + xf86configptr->conf_input_lst); + if (!confInput) { + confInput = xf86findInputByDriver("kbd", + xf86configptr->conf_input_lst); + } + if (confInput) { + foundKeyboard = TRUE; + from = X_DEFAULT; + keyboardMsg = "first keyboard device"; + } + } + + /* 5. Built-in default. */ + if (!foundKeyboard && !xf86Info.allowEmptyInput) { + bzero(&defKbd, sizeof(defKbd)); + defKbd.inp_identifier = strdup(""); + defKbd.inp_driver = strdup("kbd"); + confInput = &defKbd; + foundKeyboard = TRUE; + keyboardMsg = "default keyboard configuration"; + from = X_DEFAULT; + } + + /* Add the core keyboard device to the layout, and set it to Core. */ + if (foundKeyboard && confInput) { + foundKeyboard = configInput(&Keyboard, confInput, from); + if (foundKeyboard) { + count++; + devs = xnfrealloc(servlayoutp->inputs, + (count + 1) * sizeof(IDevPtr)); + devs[count - 1] = xnfalloc(sizeof(IDevRec)); + *devs[count - 1] = Keyboard; + devs[count - 1]->extraOptions = + xf86addNewOption(NULL, xnfstrdup("CoreKeyboard"), NULL); + devs[count] = NULL; + servlayoutp->inputs = devs; + } + } + + if (!foundKeyboard && !xf86Info.allowEmptyInput) { + /* This shouldn't happen. */ + xf86Msg(X_ERROR, "Cannot locate a core keyboard device.\n"); + return FALSE; + } + + if (pointerMsg) { + if (implicitLayout) + xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n", + pointerMsg); + else + xf86Msg(X_DEFAULT, "The core pointer device wasn't specified " + "explicitly in the layout.\n" + "\tUsing the %s.\n", pointerMsg); + } + + if (keyboardMsg) { + if (implicitLayout) + xf86Msg(X_DEFAULT, "No Layout section. Using the %s.\n", + keyboardMsg); + else + xf86Msg(X_DEFAULT, "The core keyboard device wasn't specified " + "explicitly in the layout.\n" + "\tUsing the %s.\n", keyboardMsg); + } + + if (xf86Info.allowEmptyInput && !(foundPointer && foundKeyboard)) { +#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) + const char *config_backend; +#if defined(CONFIG_HAL) + config_backend = "HAL"; +#else + config_backend = "udev"; +#endif + xf86Msg(X_INFO, "The server relies on %s to provide the list of " + "input devices.\n\tIf no devices become available, " + "reconfigure %s or disable AutoAddDevices.\n", + config_backend, config_backend); +#else + xf86Msg(X_INFO, "Hotplugging is disabled and no input devices were configured.\n" + "\tTry disabling AllowEmptyInput.\n"); +#endif + } + + return TRUE; +} + +typedef enum { + LAYOUT_ISOLATEDEVICE, + LAYOUT_SINGLECARD +} LayoutValues; + +static OptionInfoRec LayoutOptions[] = { + { LAYOUT_ISOLATEDEVICE, "IsolateDevice", OPTV_STRING, + {0}, FALSE }, + { LAYOUT_SINGLECARD, "SingleCard", OPTV_BOOLEAN, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +static Bool +configInputDevices(XF86ConfLayoutPtr layout, serverLayoutPtr servlayoutp) +{ + XF86ConfInputrefPtr irp; + IDevPtr *indp; + int count = 0; + + /* + * Count the number of input devices. + */ + irp = layout->lay_input_lst; + while (irp) { + count++; + irp = (XF86ConfInputrefPtr)irp->list.next; + } + DebugF("Found %d input devices in the layout section %s\n", + count, layout->lay_identifier); + indp = xnfcalloc((count + 1), sizeof(IDevPtr)); + indp[count] = NULL; + irp = layout->lay_input_lst; + count = 0; + while (irp) { + indp[count] = xnfalloc(sizeof(IDevRec)); + if (!configInput(indp[count], irp->iref_inputdev, X_CONFIG)) { + while(count--) + free(indp[count]); + free(indp); + return FALSE; + } + indp[count]->extraOptions = irp->iref_option_lst; + count++; + irp = (XF86ConfInputrefPtr)irp->list.next; + } + servlayoutp->inputs = indp; + + return TRUE; +} + + +/* + * figure out which layout is active, which screens are used in that layout, + * which drivers and monitors are used in these screens + */ +static Bool +configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, + char *default_layout) +{ + XF86ConfAdjacencyPtr adjp; + XF86ConfInactivePtr idp; + int count = 0; + int scrnum; + XF86ConfLayoutPtr l; + MessageType from; + screenLayoutPtr slp; + GDevPtr gdp; + int i = 0, j; + + if (!servlayoutp) + return FALSE; + + /* + * which layout section is the active one? + * + * If there is a -layout command line option, use that one, otherwise + * pick the first one. + */ + from = X_DEFAULT; + if (xf86LayoutName != NULL) + from = X_CMDLINE; + else if (default_layout) { + xf86LayoutName = default_layout; + from = X_CONFIG; + } + if (xf86LayoutName != NULL) { + if ((l = xf86findLayout(xf86LayoutName, conf_layout)) == NULL) { + xf86Msg(X_ERROR, "No ServerLayout section called \"%s\"\n", + xf86LayoutName); + return FALSE; + } + conf_layout = l; + } + xf86Msg(from, "ServerLayout \"%s\"\n", conf_layout->lay_identifier); + adjp = conf_layout->lay_adjacency_lst; + + /* + * we know that each screen is referenced exactly once on the left side + * of a layout statement in the Layout section. So to allocate the right + * size for the array we do a quick walk of the list to figure out how + * many sections we have + */ + while (adjp) { + count++; + adjp = (XF86ConfAdjacencyPtr)adjp->list.next; + } + + DebugF("Found %d screens in the layout section %s", + count, conf_layout->lay_identifier); + if (!count) /* alloc enough storage even if no screen is specified */ + count = 1; + + slp = xnfcalloc(1, (count + 1) * sizeof(screenLayoutRec)); + slp[count].screen = NULL; + /* + * now that we have storage, loop over the list again and fill in our + * data structure; at this point we do not fill in the adjacency + * information as it is not clear if we need it at all + */ + adjp = conf_layout->lay_adjacency_lst; + count = 0; + while (adjp) { + slp[count].screen = xnfcalloc(1, sizeof(confScreenRec)); + if (adjp->adj_scrnum < 0) + scrnum = count; + else + scrnum = adjp->adj_scrnum; + if (!configScreen(slp[count].screen, adjp->adj_screen, scrnum, + X_CONFIG)) { + free(slp); + return FALSE; + } + slp[count].x = adjp->adj_x; + slp[count].y = adjp->adj_y; + slp[count].refname = adjp->adj_refscreen; + switch (adjp->adj_where) { + case CONF_ADJ_OBSOLETE: + slp[count].where = PosObsolete; + slp[count].topname = adjp->adj_top_str; + slp[count].bottomname = adjp->adj_bottom_str; + slp[count].leftname = adjp->adj_left_str; + slp[count].rightname = adjp->adj_right_str; + break; + case CONF_ADJ_ABSOLUTE: + slp[count].where = PosAbsolute; + break; + case CONF_ADJ_RIGHTOF: + slp[count].where = PosRightOf; + break; + case CONF_ADJ_LEFTOF: + slp[count].where = PosLeftOf; + break; + case CONF_ADJ_ABOVE: + slp[count].where = PosAbove; + break; + case CONF_ADJ_BELOW: + slp[count].where = PosBelow; + break; + case CONF_ADJ_RELATIVE: + slp[count].where = PosRelative; + break; + } + count++; + adjp = (XF86ConfAdjacencyPtr)adjp->list.next; + } + + /* No screen was specified in the layout. take the first one from the + * config file, or - if it is NULL - configScreen autogenerates one for + * us */ + if (!count) + { + slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); + if (!configScreen(slp[0].screen, xf86configptr->conf_screen_lst, + 0, X_CONFIG)) { + free(slp[0].screen); + free(slp); + return FALSE; + } + } + + /* XXX Need to tie down the upper left screen. */ + + /* Fill in the refscreen and top/bottom/left/right values */ + for (i = 0; i < count; i++) { + for (j = 0; j < count; j++) { + if (slp[i].refname && + strcmp(slp[i].refname, slp[j].screen->id) == 0) { + slp[i].refscreen = slp[j].screen; + } + if (slp[i].topname && + strcmp(slp[i].topname, slp[j].screen->id) == 0) { + slp[i].top = slp[j].screen; + } + if (slp[i].bottomname && + strcmp(slp[i].bottomname, slp[j].screen->id) == 0) { + slp[i].bottom = slp[j].screen; + } + if (slp[i].leftname && + strcmp(slp[i].leftname, slp[j].screen->id) == 0) { + slp[i].left = slp[j].screen; + } + if (slp[i].rightname && + strcmp(slp[i].rightname, slp[j].screen->id) == 0) { + slp[i].right = slp[j].screen; + } + } + if (slp[i].where != PosObsolete + && slp[i].where != PosAbsolute + && !slp[i].refscreen) { + xf86Msg(X_ERROR,"Screen %s doesn't exist: deleting placement\n", + slp[i].refname); + slp[i].where = PosAbsolute; + slp[i].x = 0; + slp[i].y = 0; + } + } + + /* + * Count the number of inactive devices. + */ + count = 0; + idp = conf_layout->lay_inactive_lst; + while (idp) { + count++; + idp = (XF86ConfInactivePtr)idp->list.next; + } + DebugF("Found %d inactive devices in the layout section %s\n", + count, conf_layout->lay_identifier); + gdp = xnfalloc((count + 1) * sizeof(GDevRec)); + gdp[count].identifier = NULL; + idp = conf_layout->lay_inactive_lst; + count = 0; + while (idp) { + if (!configDevice(&gdp[count], idp->inactive_device, FALSE)) { + free(gdp); + return FALSE; + } + count++; + idp = (XF86ConfInactivePtr)idp->list.next; + } + + if (!configInputDevices(conf_layout, servlayoutp)) + return FALSE; + + servlayoutp->id = conf_layout->lay_identifier; + servlayoutp->screens = slp; + servlayoutp->inactives = gdp; + servlayoutp->options = conf_layout->lay_option_lst; + from = X_DEFAULT; + + return TRUE; +} + +/* + * No layout section, so find the first Screen section and set that up as + * the only active screen. + */ +static Bool +configImpliedLayout(serverLayoutPtr servlayoutp, XF86ConfScreenPtr conf_screen, + XF86ConfigPtr xf86configptr) +{ + MessageType from; + XF86ConfScreenPtr s; + screenLayoutPtr slp; + IDevPtr *indp; + XF86ConfLayoutRec layout; + + if (!servlayoutp) + return FALSE; + + /* + * which screen section is the active one? + * + * If there is a -screen option, use that one, otherwise use the first + * one. + */ + + from = X_CONFIG; + if (xf86ScreenName != NULL) { + if ((s = xf86findScreen(xf86ScreenName, conf_screen)) == NULL) { + xf86Msg(X_ERROR, "No Screen section called \"%s\"\n", + xf86ScreenName); + return FALSE; + } + conf_screen = s; + from = X_CMDLINE; + } + + /* We have exactly one screen */ + + slp = xnfcalloc(1, 2 * sizeof(screenLayoutRec)); + slp[0].screen = xnfcalloc(1, sizeof(confScreenRec)); + slp[1].screen = NULL; + if (!configScreen(slp[0].screen, conf_screen, 0, from)) { + free(slp); + return FALSE; + } + servlayoutp->id = "(implicit)"; + servlayoutp->screens = slp; + servlayoutp->inactives = xnfcalloc(1, sizeof(GDevRec)); + servlayoutp->options = NULL; + + memset(&layout, 0, sizeof(layout)); + layout.lay_identifier = servlayoutp->id; + if (xf86layoutAddInputDevices(xf86configptr, &layout) > 0) { + if (!configInputDevices(&layout, servlayoutp)) + return FALSE; + from = X_DEFAULT; + } else { + /* Set up an empty input device list, then look for some core devices. */ + indp = xnfalloc(sizeof(IDevPtr)); + *indp = NULL; + servlayoutp->inputs = indp; + } + + return TRUE; +} + +static Bool +configXvAdaptor(confXvAdaptorPtr adaptor, XF86ConfVideoAdaptorPtr conf_adaptor) +{ + int count = 0; + XF86ConfVideoPortPtr conf_port; + + xf86Msg(X_CONFIG, "| |-->VideoAdaptor \"%s\"\n", + conf_adaptor->va_identifier); + adaptor->identifier = conf_adaptor->va_identifier; + adaptor->options = conf_adaptor->va_option_lst; + if (conf_adaptor->va_busid || conf_adaptor->va_driver) { + xf86Msg(X_CONFIG, "| | Unsupported device type, skipping entry\n"); + return FALSE; + } + + /* + * figure out how many videoport subsections there are and fill them in + */ + conf_port = conf_adaptor->va_port_lst; + while(conf_port) { + count++; + conf_port = (XF86ConfVideoPortPtr)conf_port->list.next; + } + adaptor->ports = xnfalloc((count) * sizeof(confXvPortRec)); + adaptor->numports = count; + count = 0; + conf_port = conf_adaptor->va_port_lst; + while(conf_port) { + adaptor->ports[count].identifier = conf_port->vp_identifier; + adaptor->ports[count].options = conf_port->vp_option_lst; + count++; + conf_port = (XF86ConfVideoPortPtr)conf_port->list.next; + } + + return TRUE; +} + +static Bool +configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, + MessageType from) +{ + int count = 0; + XF86ConfDisplayPtr dispptr; + XF86ConfAdaptorLinkPtr conf_adaptor; + Bool defaultMonitor = FALSE; + + if (!conf_screen) { + conf_screen = xnfcalloc(1, sizeof(XF86ConfScreenRec)); + conf_screen->scrn_identifier = "Default Screen Section"; + xf86Msg(X_DEFAULT, "No screen section available. Using defaults.\n"); + } + + xf86Msg(from, "|-->Screen \"%s\" (%d)\n", conf_screen->scrn_identifier, + scrnum); + /* + * now we fill in the elements of the screen + */ + screenp->id = conf_screen->scrn_identifier; + screenp->screennum = scrnum; + screenp->defaultdepth = conf_screen->scrn_defaultdepth; + screenp->defaultbpp = conf_screen->scrn_defaultbpp; + screenp->defaultfbbpp = conf_screen->scrn_defaultfbbpp; + screenp->monitor = xnfcalloc(1, sizeof(MonRec)); + /* If no monitor is specified, create a default one. */ + if (!conf_screen->scrn_monitor) { + XF86ConfMonitorRec defMon; + + bzero(&defMon, sizeof(defMon)); + defMon.mon_identifier = ""; + if (!configMonitor(screenp->monitor, &defMon)) + return FALSE; + defaultMonitor = TRUE; + } else { + if (!configMonitor(screenp->monitor,conf_screen->scrn_monitor)) + return FALSE; + } + /* Configure the device. If there isn't one configured, attach to the + * first inactive one that we can configure. If there's none that work, + * set it to NULL so that the section can be autoconfigured later */ + screenp->device = xnfcalloc(1, sizeof(GDevRec)); + if ((!conf_screen->scrn_device) && (xf86configptr->conf_device_lst)) { + conf_screen->scrn_device = xf86configptr->conf_device_lst; + xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n" + "\tUsing the first device section listed.\n", screenp->id); + } + if (configDevice(screenp->device,conf_screen->scrn_device, TRUE)) { + screenp->device->myScreenSection = screenp; + } else { + screenp->device = NULL; + } + screenp->options = conf_screen->scrn_option_lst; + + /* + * figure out how many display subsections there are and fill them in + */ + dispptr = conf_screen->scrn_display_lst; + while(dispptr) { + count++; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next; + } + screenp->displays = xnfalloc((count) * sizeof(DispRec)); + screenp->numdisplays = count; + + /* Fill in the default Virtual size, if any */ + if (conf_screen->scrn_virtualX && conf_screen->scrn_virtualY) { + for (count = 0, dispptr = conf_screen->scrn_display_lst; + dispptr; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next, count++) { + screenp->displays[count].virtualX = conf_screen->scrn_virtualX; + screenp->displays[count].virtualY = conf_screen->scrn_virtualY; + } + } + + /* Now do the per-Display Virtual sizes */ + count = 0; + dispptr = conf_screen->scrn_display_lst; + while(dispptr) { + configDisplay(&(screenp->displays[count]),dispptr); + count++; + dispptr = (XF86ConfDisplayPtr)dispptr->list.next; + } + + /* + * figure out how many videoadaptor references there are and fill them in + */ + conf_adaptor = conf_screen->scrn_adaptor_lst; + while(conf_adaptor) { + count++; + conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next; + } + screenp->xvadaptors = xnfalloc((count) * sizeof(confXvAdaptorRec)); + screenp->numxvadaptors = 0; + conf_adaptor = conf_screen->scrn_adaptor_lst; + while(conf_adaptor) { + if (configXvAdaptor(&(screenp->xvadaptors[screenp->numxvadaptors]), + conf_adaptor->al_adaptor)) + screenp->numxvadaptors++; + conf_adaptor = (XF86ConfAdaptorLinkPtr)conf_adaptor->list.next; + } + + if (defaultMonitor) { + xf86Msg(X_DEFAULT, "No monitor specified for screen \"%s\".\n" + "\tUsing a default monitor configuration.\n", screenp->id); + } + return TRUE; +} + +typedef enum { + MON_REDUCEDBLANKING, + MON_MAX_PIX_CLOCK, +} MonitorValues; + +static OptionInfoRec MonitorOptions[] = { + { MON_REDUCEDBLANKING, "ReducedBlanking", OPTV_BOOLEAN, + {0}, FALSE }, + { MON_MAX_PIX_CLOCK, "MaxPixClock", OPTV_FREQ, + {0}, FALSE }, + { -1, NULL, OPTV_NONE, + {0}, FALSE }, +}; + +static Bool +configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor) +{ + int count; + DisplayModePtr mode,last = NULL; + XF86ConfModeLinePtr cmodep; + XF86ConfModesPtr modes; + XF86ConfModesLinkPtr modeslnk = conf_monitor->mon_modes_sect_lst; + Gamma zeros = {0.0, 0.0, 0.0}; + float badgamma = 0.0; + double maxPixClock; + + xf86Msg(X_CONFIG, "| |-->Monitor \"%s\"\n", + conf_monitor->mon_identifier); + monitorp->id = conf_monitor->mon_identifier; + monitorp->vendor = conf_monitor->mon_vendor; + monitorp->model = conf_monitor->mon_modelname; + monitorp->Modes = NULL; + monitorp->Last = NULL; + monitorp->gamma = zeros; + monitorp->widthmm = conf_monitor->mon_width; + monitorp->heightmm = conf_monitor->mon_height; + monitorp->reducedblanking = FALSE; + monitorp->maxPixClock = 0; + monitorp->options = conf_monitor->mon_option_lst; + + /* + * fill in the monitor structure + */ + for( count = 0 ; + count < conf_monitor->mon_n_hsync && count < MAX_HSYNC; + count++) { + monitorp->hsync[count].hi = conf_monitor->mon_hsync[count].hi; + monitorp->hsync[count].lo = conf_monitor->mon_hsync[count].lo; + } + monitorp->nHsync = count; + for( count = 0 ; + count < conf_monitor->mon_n_vrefresh && count < MAX_VREFRESH; + count++) { + monitorp->vrefresh[count].hi = conf_monitor->mon_vrefresh[count].hi; + monitorp->vrefresh[count].lo = conf_monitor->mon_vrefresh[count].lo; + } + monitorp->nVrefresh = count; + + /* + * first we collect the mode lines from the UseModes directive + */ + while(modeslnk) + { + modes = xf86findModes (modeslnk->ml_modes_str, + xf86configptr->conf_modes_lst); + modeslnk->ml_modes = modes; + + + /* now add the modes found in the modes + section to the list of modes for this + monitor unless it has been added before + because we are reusing the same section + for another screen */ + if (xf86itemNotSublist( + (GenericListPtr)conf_monitor->mon_modeline_lst, + (GenericListPtr)modes->mon_modeline_lst)) { + conf_monitor->mon_modeline_lst = (XF86ConfModeLinePtr) + xf86addListItem( + (GenericListPtr)conf_monitor->mon_modeline_lst, + (GenericListPtr)modes->mon_modeline_lst); + } + modeslnk = modeslnk->list.next; + } + + /* + * we need to hook in the mode lines now + * here both data structures use lists, only our internal one + * is double linked + */ + cmodep = conf_monitor->mon_modeline_lst; + while( cmodep ) { + mode = xnfcalloc(1, sizeof(DisplayModeRec)); + mode->type = 0; + mode->Clock = cmodep->ml_clock; + mode->HDisplay = cmodep->ml_hdisplay; + mode->HSyncStart = cmodep->ml_hsyncstart; + mode->HSyncEnd = cmodep->ml_hsyncend; + mode->HTotal = cmodep->ml_htotal; + mode->VDisplay = cmodep->ml_vdisplay; + mode->VSyncStart = cmodep->ml_vsyncstart; + mode->VSyncEnd = cmodep->ml_vsyncend; + mode->VTotal = cmodep->ml_vtotal; + mode->Flags = cmodep->ml_flags; + mode->HSkew = cmodep->ml_hskew; + mode->VScan = cmodep->ml_vscan; + mode->name = xnfstrdup(cmodep->ml_identifier); + if( last ) { + mode->prev = last; + last->next = mode; + } + else { + /* + * this is the first mode + */ + monitorp->Modes = mode; + mode->prev = NULL; + } + last = mode; + cmodep = (XF86ConfModeLinePtr)cmodep->list.next; + } + if(last){ + last->next = NULL; + } + monitorp->Last = last; + + /* add the (VESA) default modes */ + if (! addDefaultModes(monitorp) ) + return FALSE; + + if (conf_monitor->mon_gamma_red > GAMMA_ZERO) + monitorp->gamma.red = conf_monitor->mon_gamma_red; + if (conf_monitor->mon_gamma_green > GAMMA_ZERO) + monitorp->gamma.green = conf_monitor->mon_gamma_green; + if (conf_monitor->mon_gamma_blue > GAMMA_ZERO) + monitorp->gamma.blue = conf_monitor->mon_gamma_blue; + + /* Check that the gamma values are within range */ + if (monitorp->gamma.red > GAMMA_ZERO && + (monitorp->gamma.red < GAMMA_MIN || + monitorp->gamma.red > GAMMA_MAX)) { + badgamma = monitorp->gamma.red; + } else if (monitorp->gamma.green > GAMMA_ZERO && + (monitorp->gamma.green < GAMMA_MIN || + monitorp->gamma.green > GAMMA_MAX)) { + badgamma = monitorp->gamma.green; + } else if (monitorp->gamma.blue > GAMMA_ZERO && + (monitorp->gamma.blue < GAMMA_MIN || + monitorp->gamma.blue > GAMMA_MAX)) { + badgamma = monitorp->gamma.blue; + } + if (badgamma > GAMMA_ZERO) { + xf86ConfigError("Gamma value %.f is out of range (%.2f - %.1f)\n", + badgamma, GAMMA_MIN, GAMMA_MAX); + return FALSE; + } + + xf86ProcessOptions(-1, monitorp->options, MonitorOptions); + xf86GetOptValBool(MonitorOptions, MON_REDUCEDBLANKING, + &monitorp->reducedblanking); + if (xf86GetOptValFreq(MonitorOptions, MON_MAX_PIX_CLOCK, OPTUNITS_KHZ, + &maxPixClock) == TRUE) { + monitorp->maxPixClock = (int) maxPixClock; + } + + return TRUE; +} + +static int +lookupVisual(const char *visname) +{ + int i; + + if (!visname || !*visname) + return -1; + + for (i = 0; i <= DirectColor; i++) { + if (!xf86nameCompare(visname, xf86VisualNames[i])) + break; + } + + if (i <= DirectColor) + return i; + + return -1; +} + + +static Bool +configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display) +{ + int count = 0; + XF86ModePtr modep; + + displayp->frameX0 = conf_display->disp_frameX0; + displayp->frameY0 = conf_display->disp_frameY0; + displayp->virtualX = conf_display->disp_virtualX; + displayp->virtualY = conf_display->disp_virtualY; + displayp->depth = conf_display->disp_depth; + displayp->fbbpp = conf_display->disp_bpp; + displayp->weight.red = conf_display->disp_weight.red; + displayp->weight.green = conf_display->disp_weight.green; + displayp->weight.blue = conf_display->disp_weight.blue; + displayp->blackColour.red = conf_display->disp_black.red; + displayp->blackColour.green = conf_display->disp_black.green; + displayp->blackColour.blue = conf_display->disp_black.blue; + displayp->whiteColour.red = conf_display->disp_white.red; + displayp->whiteColour.green = conf_display->disp_white.green; + displayp->whiteColour.blue = conf_display->disp_white.blue; + displayp->options = conf_display->disp_option_lst; + if (conf_display->disp_visual) { + displayp->defaultVisual = lookupVisual(conf_display->disp_visual); + if (displayp->defaultVisual == -1) { + xf86ConfigError("Invalid visual name: \"%s\"", + conf_display->disp_visual); + return FALSE; + } + } else { + displayp->defaultVisual = -1; + } + + /* + * now hook in the modes + */ + modep = conf_display->disp_mode_lst; + while(modep) { + count++; + modep = (XF86ModePtr)modep->list.next; + } + displayp->modes = xnfalloc((count+1) * sizeof(char*)); + modep = conf_display->disp_mode_lst; + count = 0; + while(modep) { + displayp->modes[count] = modep->mode_name; + count++; + modep = (XF86ModePtr)modep->list.next; + } + displayp->modes[count] = NULL; + + return TRUE; +} + +static Bool +configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active) +{ + int i; + + if (!conf_device) { + return FALSE; + } + + if (active) + xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n", + conf_device->dev_identifier); + else + xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n", + conf_device->dev_identifier); + + devicep->identifier = conf_device->dev_identifier; + devicep->vendor = conf_device->dev_vendor; + devicep->board = conf_device->dev_board; + devicep->chipset = conf_device->dev_chipset; + devicep->ramdac = conf_device->dev_ramdac; + devicep->driver = conf_device->dev_driver; + devicep->active = active; + devicep->videoRam = conf_device->dev_videoram; + devicep->BiosBase = conf_device->dev_bios_base; + devicep->MemBase = conf_device->dev_mem_base; + devicep->IOBase = conf_device->dev_io_base; + devicep->clockchip = conf_device->dev_clockchip; + devicep->busID = conf_device->dev_busid; + devicep->textClockFreq = conf_device->dev_textclockfreq; + devicep->chipID = conf_device->dev_chipid; + devicep->chipRev = conf_device->dev_chiprev; + devicep->options = conf_device->dev_option_lst; + devicep->irq = conf_device->dev_irq; + devicep->screen = conf_device->dev_screen; + + for (i = 0; i < MAXDACSPEEDS; i++) { + if (i < CONF_MAXDACSPEEDS) + devicep->dacSpeeds[i] = conf_device->dev_dacSpeeds[i]; + else + devicep->dacSpeeds[i] = 0; + } + devicep->numclocks = conf_device->dev_clocks; + if (devicep->numclocks > MAXCLOCKS) + devicep->numclocks = MAXCLOCKS; + for (i = 0; i < devicep->numclocks; i++) { + devicep->clock[i] = conf_device->dev_clock[i]; + } + devicep->claimed = FALSE; + + return TRUE; +} + +#ifdef XF86DRI +static void +configDRI(XF86ConfDRIPtr drip) +{ + int count = 0; + XF86ConfBuffersPtr bufs; + int i; + struct group *grp; + + xf86ConfigDRI.group = -1; + xf86ConfigDRI.mode = 0; + xf86ConfigDRI.bufs_count = 0; + xf86ConfigDRI.bufs = NULL; + + if (drip) { + if (drip->dri_group_name) { + if ((grp = getgrnam(drip->dri_group_name))) + xf86ConfigDRI.group = grp->gr_gid; + } else { + if (drip->dri_group >= 0) + xf86ConfigDRI.group = drip->dri_group; + } + xf86ConfigDRI.mode = drip->dri_mode; + for (bufs = drip->dri_buffers_lst; bufs; bufs = bufs->list.next) + ++count; + + xf86ConfigDRI.bufs_count = count; + xf86ConfigDRI.bufs = xnfalloc(count * sizeof(*xf86ConfigDRI.bufs)); + + for (i = 0, bufs = drip->dri_buffers_lst; + i < count; + i++, bufs = bufs->list.next) { + + xf86ConfigDRI.bufs[i].count = bufs->buf_count; + xf86ConfigDRI.bufs[i].size = bufs->buf_size; + /* FIXME: Flags not implemented. These + could be used, for example, to specify a + contiguous block and/or write-combining + cache policy. */ + xf86ConfigDRI.bufs[i].flags = 0; + } + } +} +#endif + +static void +configExtensions(XF86ConfExtensionsPtr conf_ext) +{ + XF86OptionPtr o; + + if (conf_ext && conf_ext->ext_option_lst) { + for (o = conf_ext->ext_option_lst; o; o = xf86NextOption(o)) { + char *name = xf86OptionName(o); + char *val = xf86OptionValue(o); + char *n; + Bool enable = TRUE; + + /* Handle "No" */ + n = xf86NormalizeName(name); + if (strncmp(n, "no", 2) == 0) { + name += 2; + enable = FALSE; + } + + if (!val || + xf86NameCmp(val, "enable") == 0 || + xf86NameCmp(val, "enabled") == 0 || + xf86NameCmp(val, "on") == 0 || + xf86NameCmp(val, "1") == 0 || + xf86NameCmp(val, "yes") == 0 || + xf86NameCmp(val, "true") == 0) { + /* NOTHING NEEDED -- enabling is handled below */ + } else if (xf86NameCmp(val, "disable") == 0 || + xf86NameCmp(val, "disabled") == 0 || + xf86NameCmp(val, "off") == 0 || + xf86NameCmp(val, "0") == 0 || + xf86NameCmp(val, "no") == 0 || + xf86NameCmp(val, "false") == 0) { + enable = !enable; + } else { + xf86Msg(X_WARNING, "Ignoring unrecognized value \"%s\"\n", val); + free(n); + continue; + } + + if (EnableDisableExtension(name, enable)) { + xf86Msg(X_CONFIG, "Extension \"%s\" is %s\n", + name, enable ? "enabled" : "disabled"); + } else { + xf86Msg(X_WARNING, "Ignoring unrecognized extension \"%s\"\n", + name); + } + free(n); + } + } +} + +static Bool +configInput(IDevPtr inputp, XF86ConfInputPtr conf_input, MessageType from) +{ + xf86Msg(from, "|-->Input Device \"%s\"\n", conf_input->inp_identifier); + inputp->identifier = conf_input->inp_identifier; + inputp->driver = conf_input->inp_driver; + inputp->commonOptions = conf_input->inp_option_lst; + inputp->extraOptions = NULL; + + return TRUE; +} + +static Bool +modeIsPresent(DisplayModePtr mode, MonPtr monitorp) +{ + DisplayModePtr knownmodes = monitorp->Modes; + + /* all I can think of is a linear search... */ + while(knownmodes != NULL) + { + if(!strcmp(mode->name, knownmodes->name) && + !(knownmodes->type & M_T_DEFAULT)) + return TRUE; + knownmodes = knownmodes->next; + } + return FALSE; +} + +static Bool +addDefaultModes(MonPtr monitorp) +{ + DisplayModePtr mode; + DisplayModePtr last = monitorp->Last; + int i = 0; + + for (i = 0; i < xf86NumDefaultModes; i++) + { + mode = xf86DuplicateMode(&xf86DefaultModes[i]); + if (!modeIsPresent(mode, monitorp)) + { + monitorp->Modes = xf86ModesAdd(monitorp->Modes, mode); + last = mode; + } else { + free(mode); + } + } + monitorp->Last = last; + + return TRUE; +} + +static void +checkInput(serverLayoutPtr layout, Bool implicit_layout) { + checkCoreInputDevices(layout, implicit_layout); + + /* AllowEmptyInput and the "kbd" and "mouse" drivers are mutually + * exclusive. Trawl the list for mouse/kbd devices and disable them. + */ + if (xf86Info.allowEmptyInput && layout->inputs) + { + IDevPtr *dev = layout->inputs; + BOOL warned = FALSE; + + while(*dev) + { + if (strcmp((*dev)->driver, "kbd") == 0 || + strcmp((*dev)->driver, "mouse") == 0 || + strcmp((*dev)->driver, "vmmouse") == 0) + { + IDevPtr *current; + if (!warned) + { + xf86Msg(X_WARNING, "AllowEmptyInput is on, devices using " + "drivers 'kbd', 'mouse' or 'vmmouse' will be disabled.\n"); + warned = TRUE; + } + + xf86Msg(X_WARNING, "Disabling %s\n", (*dev)->identifier); + + current = dev; + free(*dev); + + do { + *current = *(current + 1); + current++; + } while(*current); + } else + dev++; + } + } +} + +/* + * load the config file and fill the global data structure + */ +ConfigStatus +xf86HandleConfigFile(Bool autoconfig) +{ + const char *filename, *dirname, *sysdirname; + char *filesearch, *dirsearch; + MessageType filefrom = X_DEFAULT; + MessageType dirfrom = X_DEFAULT; + char *scanptr; + Bool singlecard = 0; + Bool implicit_layout = FALSE; + + if (!autoconfig) { + if (getuid() == 0) { + filesearch = ROOT_CONFIGPATH; + dirsearch = ROOT_CONFIGDIRPATH; + } else { + filesearch = USER_CONFIGPATH; + dirsearch = USER_CONFIGDIRPATH; + } + + if (xf86ConfigFile) + filefrom = X_CMDLINE; + if (xf86ConfigDir) + dirfrom = X_CMDLINE; + + xf86initConfigFiles(); + sysdirname = xf86openConfigDirFiles(SYS_CONFIGDIRPATH, NULL, + PROJECTROOT); + dirname = xf86openConfigDirFiles(dirsearch, xf86ConfigDir, PROJECTROOT); + filename = xf86openConfigFile(filesearch, xf86ConfigFile, PROJECTROOT); + if (filename) { + xf86MsgVerb(filefrom, 0, "Using config file: \"%s\"\n", filename); + xf86ConfigFile = xnfstrdup(filename); + } else { + if (xf86ConfigFile) + xf86Msg(X_ERROR, "Unable to locate/open config file: \"%s\"\n", + xf86ConfigFile); + } + if (dirname) { + xf86MsgVerb(dirfrom, 0, "Using config directory: \"%s\"\n", + dirname); + xf86ConfigDir = xnfstrdup(dirname); + } else { + if (xf86ConfigDir) + xf86Msg(X_ERROR, + "Unable to locate/open config directory: \"%s\"\n", + xf86ConfigDir); + } + if (sysdirname) + xf86MsgVerb(X_DEFAULT, 0, "Using system config directory \"%s\"\n", + sysdirname); + if (!filename && !dirname && !sysdirname) + return CONFIG_NOFILE; + } + + if ((xf86configptr = xf86readConfigFile ()) == NULL) { + xf86Msg(X_ERROR, "Problem parsing the config file\n"); + return CONFIG_PARSE_ERROR; + } + xf86closeConfigFile (); + + /* Initialise a few things. */ + + /* + * now we convert part of the information contained in the parser + * structures into our own structures. + * The important part here is to figure out which Screen Sections + * in the XF86Config file are active so that we can piece together + * the modes that we need later down the road. + * And while we are at it, we'll decode the rest of the stuff as well + */ + + /* First check if a layout section is present, and if it is valid. */ + + if (xf86configptr->conf_layout_lst == NULL || xf86ScreenName != NULL) { + if (xf86ScreenName == NULL) { + xf86Msg(X_DEFAULT, + "No Layout section. Using the first Screen section.\n"); + } + if (!configImpliedLayout(&xf86ConfigLayout, + xf86configptr->conf_screen_lst, + xf86configptr)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + implicit_layout = TRUE; + } else { + if (xf86configptr->conf_flags != NULL) { + char *dfltlayout = NULL; + pointer optlist = xf86configptr->conf_flags->flg_option_lst; + + if (optlist && xf86FindOption(optlist, "defaultserverlayout")) + dfltlayout = xf86SetStrOption(optlist, "defaultserverlayout", NULL); + if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, + dfltlayout)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + } else { + if (!configLayout(&xf86ConfigLayout, xf86configptr->conf_layout_lst, + NULL)) { + xf86Msg(X_ERROR, "Unable to determine the screen layout\n"); + return CONFIG_PARSE_ERROR; + } + } + } + + xf86ProcessOptions(-1, xf86ConfigLayout.options, LayoutOptions); + + if ((scanptr = xf86GetOptValString(LayoutOptions, LAYOUT_ISOLATEDEVICE))) { + ; /* IsolateDevice specified; overrides SingleCard */ + } else { + xf86GetOptValBool(LayoutOptions, LAYOUT_SINGLECARD, &singlecard); + if (singlecard) + scanptr = xf86ConfigLayout.screens->screen->device->busID; + } + if (scanptr) { + int bus, device, func; + if (strncmp(scanptr, "PCI:", 4) != 0) { + xf86Msg(X_WARNING, "Bus types other than PCI not yet isolable.\n" + "\tIgnoring IsolateDevice option.\n"); + } else if (sscanf(scanptr, "PCI:%d:%d:%d", &bus, &device, &func) == 3) { + xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); + xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); + xf86IsolateDevice.dev = device; + xf86IsolateDevice.func = func; + xf86Msg(X_INFO, + "Isolating PCI bus \"%d:%d:%d\"\n", bus, device, func); + } + } + + /* Now process everything else */ + if (!configServerFlags(xf86configptr->conf_flags,xf86ConfigLayout.options)){ + ErrorF ("Problem when converting the config data structures\n"); + return CONFIG_PARSE_ERROR; + } + + configFiles(xf86configptr->conf_files); + configExtensions(xf86configptr->conf_extensions); +#ifdef XF86DRI + configDRI(xf86configptr->conf_dri); +#endif + + checkInput(&xf86ConfigLayout, implicit_layout); + + /* + * Handle some command line options that can override some of the + * ServerFlags settings. + */ +#ifdef XF86VIDMODE + if (xf86VidModeDisabled) + xf86Info.vidModeEnabled = FALSE; + if (xf86VidModeAllowNonLocal) + xf86Info.vidModeAllowNonLocal = TRUE; +#endif + + if (xf86AllowMouseOpenFail) + xf86Info.allowMouseOpenFail = TRUE; + + return CONFIG_OK; +} + +Bool +xf86PathIsSafe(const char *path) +{ + return (xf86pathIsSafe(path) != 0); +} diff --git a/xorg-server/hw/xfree86/common/xf86Configure.c b/xorg-server/hw/xfree86/common/xf86Configure.c index 67bf08bbf..883c666a6 100644 --- a/xorg-server/hw/xfree86/common/xf86Configure.c +++ b/xorg-server/hw/xfree86/common/xf86Configure.c @@ -1,892 +1,892 @@ -/* - * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales. - * - * 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 Alan Hourihane not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Alan Hourihane makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. - * - * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL ALAN HOURIHANE 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. - * - * Author: Alan Hourihane, alanh@fairlite.demon.co.uk - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86Config.h" -#include "xf86_OSlib.h" -#include "xf86Priv.h" -#define IN_XSERVER -#include "Configint.h" -#include "xf86DDC.h" -#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) -#include "xf86Bus.h" -#include "xf86Sbus.h" -#endif - -typedef struct _DevToConfig { - GDevRec GDev; - struct pci_device * pVideo; -#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) - sbusDevicePtr sVideo; -#endif - int iDriver; -} DevToConfigRec, *DevToConfigPtr; - -static DevToConfigPtr DevToConfig = NULL; -static int nDevToConfig = 0, CurrentDriver; - -xf86MonPtr ConfiguredMonitor; -Bool xf86DoConfigurePass1 = TRUE; -static Bool foundMouse = FALSE; - -#if defined(__SCO__) -static char *DFLT_MOUSE_PROTO = "OSMouse"; -#elif defined(__UNIXWARE__) -static char *DFLT_MOUSE_PROTO = "OSMouse"; -static char *DFLT_MOUSE_DEV = "/dev/mouse"; -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) -static char *DFLT_MOUSE_DEV = "/dev/sysmouse"; -static char *DFLT_MOUSE_PROTO = "auto"; -#elif defined(linux) -static char DFLT_MOUSE_DEV[] = "/dev/input/mice"; -static char DFLT_MOUSE_PROTO[] = "auto"; -#else -static char *DFLT_MOUSE_DEV = "/dev/mouse"; -static char *DFLT_MOUSE_PROTO = "auto"; -#endif - -static Bool -bus_pci_configure(void *busData) -{ - int i; - struct pci_device * pVideo = NULL; - - pVideo = (struct pci_device *) busData; - for (i = 0; i < nDevToConfig; i++) - if (DevToConfig[i].pVideo && - (DevToConfig[i].pVideo->domain == pVideo->domain) && - (DevToConfig[i].pVideo->bus == pVideo->bus) && - (DevToConfig[i].pVideo->dev == pVideo->dev) && - (DevToConfig[i].pVideo->func == pVideo->func)) - return 0; - - return 1; -} - -static Bool -bus_sbus_configure(void *busData) -{ -#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) - int i; - - for (i = 0; i < nDevToConfig; i++) - if (DevToConfig[i].sVideo && - DevToConfig[i].sVideo->fbNum == ((sbusDevicePtr) busData)->fbNum) - return 0; - -#endif - return 1; -} - -static void -bus_pci_newdev_configure(void *busData, int i, int *chipset) -{ - const char *VendorName; - const char *CardName; - char busnum[8]; - struct pci_device * pVideo = NULL; - - pVideo = (struct pci_device *) busData; - - DevToConfig[i].pVideo = pVideo; - - VendorName = pci_device_get_vendor_name( pVideo ); - CardName = pci_device_get_device_name( pVideo ); - - if (!VendorName) { - VendorName = xnfalloc(15); - sprintf((char*)VendorName, "Unknown Vendor"); - } - - if (!CardName) { - CardName = xnfalloc(14); - sprintf((char*)CardName, "Unknown Board"); - } - - DevToConfig[i].GDev.identifier = - xnfalloc(strlen(VendorName) + strlen(CardName) + 2); - sprintf(DevToConfig[i].GDev.identifier, "%s %s", VendorName, CardName); - - DevToConfig[i].GDev.vendor = (char *)VendorName; - DevToConfig[i].GDev.board = (char *)CardName; - - DevToConfig[i].GDev.busID = xnfalloc(16); - xf86FormatPciBusNumber(pVideo->bus, busnum); - sprintf(DevToConfig[i].GDev.busID, "PCI:%s:%d:%d", - busnum, pVideo->dev, pVideo->func); - - DevToConfig[i].GDev.chipID = pVideo->device_id; - DevToConfig[i].GDev.chipRev = pVideo->revision; - - if (*chipset < 0) { - *chipset = (pVideo->vendor_id << 16) | pVideo->device_id; - } -} - -static void -bus_sbus_newdev_configure(void *busData, int i) -{ -#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) - char *promPath = NULL; - DevToConfig[i].sVideo = (sbusDevicePtr) busData; - DevToConfig[i].GDev.identifier = DevToConfig[i].sVideo->descr; - if (sparcPromInit() >= 0) { - promPath = sparcPromNode2Pathname(&DevToConfig[i].sVideo->node); - sparcPromClose(); - } - if (promPath) { - DevToConfig[i].GDev.busID = xnfalloc(strlen(promPath) + 6); - sprintf(DevToConfig[i].GDev.busID, "SBUS:%s", promPath); - xfree(promPath); - } else { - DevToConfig[i].GDev.busID = xnfalloc(12); - sprintf(DevToConfig[i].GDev.busID, "SBUS:fb%d", - DevToConfig[i].sVideo->fbNum); - } -#endif -} - -/* - * This is called by the driver, either through xf86Match???Instances() or - * directly. We allocate a GDevRec and fill it in as much as we can, letting - * the caller fill in the rest and/or change it as it sees fit. - */ -GDevPtr -xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, int chipset) -{ - int ret, i, j; - - if (!xf86DoConfigure || !xf86DoConfigurePass1) - return NULL; - - /* Check for duplicates */ - switch (bus) { - case BUS_PCI: - ret = bus_pci_configure(busData); - break; - case BUS_SBUS: - ret = bus_sbus_configure(busData); - break; - default: - return NULL; - } - - if (ret == 0) - goto out; - - /* Allocate new structure occurrence */ - i = nDevToConfig++; - DevToConfig = - xnfrealloc(DevToConfig, nDevToConfig * sizeof(DevToConfigRec)); - memset(DevToConfig + i, 0, sizeof(DevToConfigRec)); - - DevToConfig[i].GDev.chipID = - DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1; - - DevToConfig[i].iDriver = CurrentDriver; - - /* Fill in what we know, converting the driver name to lower case */ - DevToConfig[i].GDev.driver = xnfalloc(strlen(driver) + 1); - for (j = 0; (DevToConfig[i].GDev.driver[j] = tolower(driver[j])); j++); - - switch (bus) { - case BUS_PCI: - bus_pci_newdev_configure(busData, i, &chipset); - break; - case BUS_SBUS: - bus_sbus_newdev_configure(busData, i); - break; - default: - break; - } - - /* Get driver's available options */ - if (xf86DriverList[CurrentDriver]->AvailableOptions) - DevToConfig[i].GDev.options = (OptionInfoPtr) - (*xf86DriverList[CurrentDriver]->AvailableOptions)(chipset, - bus); - - return &DevToConfig[i].GDev; - -out: - return NULL; -} - -static XF86ConfInputPtr -configureInputSection (void) -{ - XF86ConfInputPtr mouse = NULL; - parsePrologue (XF86ConfInputPtr, XF86ConfInputRec) - - ptr->inp_identifier = "Keyboard0"; - ptr->inp_driver = "kbd"; - ptr->list.next = NULL; - - /* Crude mechanism to auto-detect mouse (os dependent) */ - { - int fd; -#ifdef WSCONS_SUPPORT - fd = open("/dev/wsmouse", 0); - if (fd >= 0) { - DFLT_MOUSE_DEV = "/dev/wsmouse"; - DFLT_MOUSE_PROTO = "wsmouse"; - close(fd); - } else { - ErrorF("cannot open /dev/wsmouse\n"); - } -#endif - -#ifndef __SCO__ - fd = open(DFLT_MOUSE_DEV, 0); - if (fd != -1) { - foundMouse = TRUE; - close(fd); - } -#else - foundMouse = TRUE; -#endif - } - - mouse = calloc(1, sizeof(XF86ConfInputRec)); - mouse->inp_identifier = "Mouse0"; - mouse->inp_driver = "mouse"; - mouse->inp_option_lst = - xf86addNewOption(mouse->inp_option_lst, xstrdup("Protocol"), - xstrdup(DFLT_MOUSE_PROTO)); -#ifndef __SCO__ - mouse->inp_option_lst = - xf86addNewOption(mouse->inp_option_lst, xstrdup("Device"), - xstrdup(DFLT_MOUSE_DEV)); -#endif - mouse->inp_option_lst = - xf86addNewOption(mouse->inp_option_lst, xstrdup("ZAxisMapping"), - xstrdup("4 5 6 7")); - ptr = (XF86ConfInputPtr)xf86addListItem((glp)ptr, (glp)mouse); - return ptr; -} - -static XF86ConfScreenPtr -configureScreenSection (int screennum) -{ - int i; - int depths[] = { 1, 4, 8, 15, 16, 24/*, 32*/ }; - parsePrologue (XF86ConfScreenPtr, XF86ConfScreenRec) - - ptr->scrn_identifier = malloc(18); - sprintf(ptr->scrn_identifier, "Screen%d", screennum); - ptr->scrn_monitor_str = malloc(19); - sprintf(ptr->scrn_monitor_str, "Monitor%d", screennum); - ptr->scrn_device_str = malloc(16); - sprintf(ptr->scrn_device_str, "Card%d", screennum); - - for (i=0; idisp_depth = depths[i]; - display->disp_black.red = display->disp_white.red = -1; - display->disp_black.green = display->disp_white.green = -1; - display->disp_black.blue = display->disp_white.blue = -1; - ptr->scrn_display_lst = (XF86ConfDisplayPtr)xf86addListItem( - (glp)ptr->scrn_display_lst, (glp)display); - } - - return ptr; -} - -static const char* -optionTypeToSting(OptionValueType type) -{ - switch (type) { - case OPTV_NONE: - return ""; - case OPTV_INTEGER: - return ""; - case OPTV_STRING: - return ""; - case OPTV_ANYSTR: - return "[]"; - case OPTV_REAL: - return ""; - case OPTV_BOOLEAN: - return "[]"; - case OPTV_FREQ: - return ""; - default: - return ""; - } -} - -static XF86ConfDevicePtr -configureDeviceSection (int screennum) -{ - char identifier[16]; - OptionInfoPtr p; - int i = 0; - parsePrologue (XF86ConfDevicePtr, XF86ConfDeviceRec) - - /* Move device info to parser structure */ - sprintf(identifier, "Card%d", screennum); - ptr->dev_identifier = strdup(identifier); -/* ptr->dev_identifier = DevToConfig[screennum].GDev.identifier;*/ - ptr->dev_vendor = DevToConfig[screennum].GDev.vendor; - ptr->dev_board = DevToConfig[screennum].GDev.board; - ptr->dev_chipset = DevToConfig[screennum].GDev.chipset; - ptr->dev_busid = DevToConfig[screennum].GDev.busID; - ptr->dev_driver = DevToConfig[screennum].GDev.driver; - ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac; - for (i = 0; (i < MAXDACSPEEDS) && (i < CONF_MAXDACSPEEDS); i++) - ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i]; - ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam; - ptr->dev_textclockfreq = DevToConfig[screennum].GDev.textClockFreq; - ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase; - ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase; - ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase; - ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip; - for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks); i++) - ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i]; - ptr->dev_clocks = i; - ptr->dev_chipid = DevToConfig[screennum].GDev.chipID; - ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev; - ptr->dev_irq = DevToConfig[screennum].GDev.irq; - - /* Make sure older drivers don't segv */ - if (DevToConfig[screennum].GDev.options) { - /* Fill in the available driver options for people to use */ - const char *descrip = - " ### Available Driver options are:-\n" - " ### Values: : integer, : float, " - ": \"True\"/\"False\",\n" - " ### : \"String\", : \" Hz/kHz/MHz\"\n" - " ### [arg]: arg optional\n"; - ptr->dev_comment = xstrdup(descrip); - if (ptr->dev_comment) { - for (p = DevToConfig[screennum].GDev.options; - p->name != NULL; p++) { - char *p_e; - const char *prefix = " #Option "; - const char *middle = " \t# "; - const char *suffix = "\n"; - const char *opttype = optionTypeToSting(p->type); - char *optname; - int len = strlen(ptr->dev_comment) + strlen(prefix) + - strlen(middle) + strlen(suffix) + 1; - - optname = xalloc(strlen(p->name) + 2 + 1); - if (!optname) - break; - sprintf(optname, "\"%s\"", p->name); - - len += max(20, strlen(optname)); - len += strlen(opttype); - - ptr->dev_comment = xrealloc(ptr->dev_comment, len); - if (!ptr->dev_comment) - break; - p_e = ptr->dev_comment + strlen(ptr->dev_comment); - sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle, - opttype, suffix); - xfree(optname); - } - } - } - - return ptr; -} - -static XF86ConfLayoutPtr -configureLayoutSection (void) -{ - int scrnum = 0; - parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec) - - ptr->lay_identifier = "X.org Configured"; - - { - XF86ConfInputrefPtr iptr; - - iptr = malloc (sizeof (XF86ConfInputrefRec)); - iptr->list.next = NULL; - iptr->iref_option_lst = NULL; - iptr->iref_inputdev_str = "Mouse0"; - iptr->iref_option_lst = - xf86addNewOption (iptr->iref_option_lst, xstrdup("CorePointer"), NULL); - ptr->lay_input_lst = (XF86ConfInputrefPtr) - xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr); - } - - { - XF86ConfInputrefPtr iptr; - - iptr = malloc (sizeof (XF86ConfInputrefRec)); - iptr->list.next = NULL; - iptr->iref_option_lst = NULL; - iptr->iref_inputdev_str = "Keyboard0"; - iptr->iref_option_lst = - xf86addNewOption (iptr->iref_option_lst, xstrdup("CoreKeyboard"), NULL); - ptr->lay_input_lst = (XF86ConfInputrefPtr) - xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr); - } - - for (scrnum = 0; scrnum < nDevToConfig; scrnum++) { - XF86ConfAdjacencyPtr aptr; - - aptr = malloc (sizeof (XF86ConfAdjacencyRec)); - aptr->list.next = NULL; - aptr->adj_x = 0; - aptr->adj_y = 0; - aptr->adj_scrnum = scrnum; - aptr->adj_screen_str = xnfalloc(18); - sprintf(aptr->adj_screen_str, "Screen%d", scrnum); - if (scrnum == 0) { - aptr->adj_where = CONF_ADJ_ABSOLUTE; - aptr->adj_refscreen = NULL; - } - else { - aptr->adj_where = CONF_ADJ_RIGHTOF; - aptr->adj_refscreen = xnfalloc(18); - sprintf(aptr->adj_refscreen, "Screen%d", scrnum - 1); - } - ptr->lay_adjacency_lst = - (XF86ConfAdjacencyPtr)xf86addListItem((glp)ptr->lay_adjacency_lst, - (glp)aptr); - } - - return ptr; -} - -static XF86ConfFlagsPtr -configureFlagsSection (void) -{ - parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec) - - return ptr; -} - -static XF86ConfModulePtr -configureModuleSection (void) -{ - char **elist, **el; - /* Find the list of extension & font modules. */ - const char *esubdirs[] = { - "extensions", - "fonts", - NULL - }; - parsePrologue (XF86ConfModulePtr, XF86ConfModuleRec) - - elist = LoaderListDirs(esubdirs, NULL); - if (elist) { - for (el = elist; *el; el++) { - XF86LoadPtr module; - - module = calloc(1, sizeof(XF86LoadRec)); - module->load_name = *el; - ptr->mod_load_lst = (XF86LoadPtr)xf86addListItem( - (glp)ptr->mod_load_lst, (glp)module); - } - xfree(elist); - } - - return ptr; -} - -static XF86ConfFilesPtr -configureFilesSection (void) -{ - parsePrologue (XF86ConfFilesPtr, XF86ConfFilesRec) - - if (xf86ModulePath) - ptr->file_modulepath = strdup(xf86ModulePath); - if (defaultFontPath) - ptr->file_fontpath = strdup(defaultFontPath); - - return ptr; -} - -static XF86ConfMonitorPtr -configureMonitorSection (int screennum) -{ - parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec) - - ptr->mon_identifier = malloc(19); - sprintf(ptr->mon_identifier, "Monitor%d", screennum); - ptr->mon_vendor = strdup("Monitor Vendor"); - ptr->mon_modelname = strdup("Monitor Model"); - - return ptr; -} - -/* Initialize Configure Monitor from Detailed Timing Block */ -static void handle_detailed_input(struct detailed_monitor_section *det_mon, - void *data) -{ - XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data; - - switch (det_mon->type) { - case DS_NAME: - ptr->mon_modelname = realloc(ptr->mon_modelname, - strlen((char*)(det_mon->section.name)) + - 1); - strcpy(ptr->mon_modelname, - (char*)(det_mon->section.name)); - break; - case DS_RANGES: - ptr->mon_hsync[ptr->mon_n_hsync].lo = - det_mon->section.ranges.min_h; - ptr->mon_hsync[ptr->mon_n_hsync].hi = - det_mon->section.ranges.max_h; - ptr->mon_n_vrefresh = 1; - ptr->mon_vrefresh[ptr->mon_n_hsync].lo = - det_mon->section.ranges.min_v; - ptr->mon_vrefresh[ptr->mon_n_hsync].hi = - det_mon->section.ranges.max_v; - ptr->mon_n_hsync++; - default: - break; - } -} - -static XF86ConfMonitorPtr -configureDDCMonitorSection (int screennum) -{ - int len, mon_width, mon_height; -#define displaySizeMaxLen 80 - char displaySize_string[displaySizeMaxLen]; - int displaySizeLen; - - parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec) - - ptr->mon_identifier = malloc(19); - sprintf(ptr->mon_identifier, "Monitor%d", screennum); - ptr->mon_vendor = strdup(ConfiguredMonitor->vendor.name); - ptr->mon_modelname = malloc(12); - sprintf(ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id); - - /* features in centimetres, we want millimetres */ - mon_width = 10 * ConfiguredMonitor->features.hsize ; - mon_height = 10 * ConfiguredMonitor->features.vsize ; - -#ifdef CONFIGURE_DISPLAYSIZE - ptr->mon_width = mon_width; - ptr->mon_height = mon_height; -#else - if (mon_width && mon_height) { - /* when values available add DisplaySize option AS A COMMENT */ - - displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen, - "\t#DisplaySize\t%5d %5d\t# mm\n", - mon_width, mon_height); - - if (displaySizeLen>0 && displaySizeLenmon_comment) { - len = strlen(ptr->mon_comment); - } else { - len = 0; - } - if ((ptr->mon_comment = - realloc(ptr->mon_comment, len + strlen(displaySize_string) + 1))) { - strcpy(ptr->mon_comment + len, displaySize_string); - } - } - } -#endif /* def CONFIGURE_DISPLAYSIZE */ - - xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input, - ptr); - - if (ConfiguredMonitor->features.dpms) { - ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, xstrdup("DPMS"), NULL); - } - - return ptr; -} - -#if !defined(PATH_MAX) -# define PATH_MAX 1024 -#endif - -void -DoConfigure(void) -{ - int i,j, screennum = -1; - char *home = NULL; - char filename[PATH_MAX]; - char *addslash = ""; - XF86ConfigPtr xf86config = NULL; - char **vlist, **vl; - int *dev2screen; - - vlist = xf86DriverlistFromCompile(); - - if (!vlist) { - ErrorF("Missing output drivers. Configuration failed.\n"); - goto bail; - } - - ErrorF("List of video drivers:\n"); - for (vl = vlist; *vl; vl++) - ErrorF("\t%s\n", *vl); - - /* Load all the drivers that were found. */ - xf86LoadModules(vlist, NULL); - - xfree(vlist); - - for (i = 0; i < xf86NumDrivers; i++) { - xorgHWFlags flags; - if (!xf86DriverList[i]->driverFunc - || !xf86DriverList[i]->driverFunc(NULL, - GET_REQUIRED_HW_INTERFACES, - &flags) - || NEED_IO_ENABLED(flags)) { - xorgHWAccess = TRUE; - break; - } - } - /* Enable full I/O access */ - if (xorgHWAccess) { - if(!xf86EnableIO()) - /* oops, we have failed */ - xorgHWAccess = FALSE; - } - - xf86FindPrimaryDevice(); - - /* Create XF86Config file structure */ - xf86config = calloc(1, sizeof(XF86ConfigRec)); - - /* Call all of the probe functions, reporting the results. */ - for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) { - xorgHWFlags flags; - Bool found_screen; - DriverRec * const drv = xf86DriverList[CurrentDriver]; - - if (!xorgHWAccess) { - if (!drv->driverFunc - || !drv->driverFunc( NULL, GET_REQUIRED_HW_INTERFACES, &flags ) - || NEED_IO_ENABLED(flags)) - continue; - } - - found_screen = xf86CallDriverProbe( drv, TRUE ); - if ( found_screen && drv->Identify ) { - (*drv->Identify)(0); - } - } - - if (nDevToConfig <= 0) { - ErrorF("No devices to configure. Configuration failed.\n"); - goto bail; - } - - /* Add device, monitor and screen sections for detected devices */ - for (screennum = 0; screennum < nDevToConfig; screennum++) { - XF86ConfDevicePtr DevicePtr; - XF86ConfMonitorPtr MonitorPtr; - XF86ConfScreenPtr ScreenPtr; - - DevicePtr = configureDeviceSection(screennum); - xf86config->conf_device_lst = (XF86ConfDevicePtr)xf86addListItem( - (glp)xf86config->conf_device_lst, (glp)DevicePtr); - MonitorPtr = configureMonitorSection(screennum); - xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem( - (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr); - ScreenPtr = configureScreenSection(screennum); - xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem( - (glp)xf86config->conf_screen_lst, (glp)ScreenPtr); - } - - xf86config->conf_files = configureFilesSection(); - xf86config->conf_modules = configureModuleSection(); - xf86config->conf_flags = configureFlagsSection(); - xf86config->conf_videoadaptor_lst = NULL; - xf86config->conf_modes_lst = NULL; - xf86config->conf_vendor_lst = NULL; - xf86config->conf_dri = NULL; - xf86config->conf_input_lst = configureInputSection(); - xf86config->conf_layout_lst = configureLayoutSection(); - - home = getenv("HOME"); - if ((home == NULL) || (home[0] == '\0')) { - home = "/"; - } else { - /* Determine if trailing slash is present or needed */ - int l = strlen(home); - - if (home[l-1] != '/') { - addslash = "/"; - } - } - - snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new", - home, addslash); - - if (xf86writeConfigFile(filename, xf86config) == 0) { - xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n", - filename, strerror(errno)); - goto bail; - } - - xf86DoConfigurePass1 = FALSE; - /* Try to get DDC information filled in */ - xf86ConfigFile = filename; - if (xf86HandleConfigFile(FALSE) != CONFIG_OK) { - goto bail; - } - - xf86DoConfigurePass1 = FALSE; - - dev2screen = xnfcalloc(1,xf86NumDrivers*sizeof(int)); - - { - Bool *driverProbed = xnfcalloc(1,xf86NumDrivers*sizeof(Bool)); - for (screennum = 0; screennum < nDevToConfig; screennum++) { - int k,l,n,oldNumScreens; - - i = DevToConfig[screennum].iDriver; - - if (driverProbed[i]) continue; - driverProbed[i] = TRUE; - - oldNumScreens = xf86NumScreens; - - xf86CallDriverProbe( xf86DriverList[i], FALSE ); - - /* reorder */ - k = screennum > 0 ? screennum : 1; - for (l = oldNumScreens; l < xf86NumScreens; l++) { - /* is screen primary? */ - Bool primary = FALSE; - for (n = 0; nnumEntities; n++) { - if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) { - dev2screen[0] = l; - primary = TRUE; - break; - } - } - if (primary) continue; - /* not primary: assign it to next device of same driver */ - /* - * NOTE: we assume that devices in DevToConfig - * and xf86Screens[] have the same order except - * for the primary device which always comes first. - */ - for (; k < nDevToConfig; k++) { - if (DevToConfig[k].iDriver == i) { - dev2screen[k++] = l; - break; - } - } - } - } - xfree(driverProbed); - } - - - if (nDevToConfig != xf86NumScreens) { - ErrorF("Number of created screens does not match number of detected" - " devices.\n Configuration failed.\n"); - goto bail; - } - - xf86PostProbe(); - xf86EntityInit(); - - for (j = 0; j < xf86NumScreens; j++) { - xf86Screens[j]->scrnIndex = j; - } - - xf86freeMonitorList(xf86config->conf_monitor_lst); - xf86config->conf_monitor_lst = NULL; - xf86freeScreenList(xf86config->conf_screen_lst); - xf86config->conf_screen_lst = NULL; - for (j = 0; j < xf86NumScreens; j++) { - XF86ConfMonitorPtr MonitorPtr; - XF86ConfScreenPtr ScreenPtr; - - ConfiguredMonitor = NULL; - - xf86EnableAccess(xf86Screens[dev2screen[j]]); - if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]], - PROBE_DETECT) && - ConfiguredMonitor) { - MonitorPtr = configureDDCMonitorSection(j); - } else { - MonitorPtr = configureMonitorSection(j); - } - ScreenPtr = configureScreenSection(j); - xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem( - (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr); - xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem( - (glp)xf86config->conf_screen_lst, (glp)ScreenPtr); - } - - if (xf86writeConfigFile(filename, xf86config) == 0) { - xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n", - filename, strerror(errno)); - goto bail; - } - - ErrorF("\n"); - -#ifdef __SCO__ - ErrorF("\n"__XSERVERNAME__ - " is using the kernel event driver to access the mouse.\n" - "If you wish to use the internal "__XSERVERNAME__ - " mouse drivers, please\n" - "edit the file and correct the Device.\n"); -#else /* !__SCO__ */ - if (!foundMouse) { - ErrorF("\n"__XSERVERNAME__" is not able to detect your mouse.\n" - "Edit the file and correct the Device.\n"); - } else { - ErrorF("\n"__XSERVERNAME__" detected your mouse at device %s.\n" - "Please check your config if the mouse is still not\n" - "operational, as by default "__XSERVERNAME__ - " tries to autodetect\n" - "the protocol.\n",DFLT_MOUSE_DEV); - } -#endif /* !__SCO__ */ - - if (xf86NumScreens > 1) { - ErrorF("\n"__XSERVERNAME__ - " has configured a multihead system, please check your config.\n"); - } - - ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE ,filename); - ErrorF("To test the server, run 'X -config %s'\n\n", filename); - -bail: - OsCleanup(TRUE); - AbortDDX(); - fflush(stderr); - exit(0); -} +/* + * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Author: Alan Hourihane, alanh@fairlite.demon.co.uk + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86Config.h" +#include "xf86_OSlib.h" +#include "xf86Priv.h" +#define IN_XSERVER +#include "Configint.h" +#include "xf86DDC.h" +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) +#include "xf86Bus.h" +#include "xf86Sbus.h" +#endif + +typedef struct _DevToConfig { + GDevRec GDev; + struct pci_device * pVideo; +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + sbusDevicePtr sVideo; +#endif + int iDriver; +} DevToConfigRec, *DevToConfigPtr; + +static DevToConfigPtr DevToConfig = NULL; +static int nDevToConfig = 0, CurrentDriver; + +xf86MonPtr ConfiguredMonitor; +Bool xf86DoConfigurePass1 = TRUE; +static Bool foundMouse = FALSE; + +#if defined(__SCO__) +static char *DFLT_MOUSE_PROTO = "OSMouse"; +#elif defined(__UNIXWARE__) +static char *DFLT_MOUSE_PROTO = "OSMouse"; +static char *DFLT_MOUSE_DEV = "/dev/mouse"; +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) +static char *DFLT_MOUSE_DEV = "/dev/sysmouse"; +static char *DFLT_MOUSE_PROTO = "auto"; +#elif defined(linux) +static char DFLT_MOUSE_DEV[] = "/dev/input/mice"; +static char DFLT_MOUSE_PROTO[] = "auto"; +#else +static char *DFLT_MOUSE_DEV = "/dev/mouse"; +static char *DFLT_MOUSE_PROTO = "auto"; +#endif + +static Bool +bus_pci_configure(void *busData) +{ + int i; + struct pci_device * pVideo = NULL; + + pVideo = (struct pci_device *) busData; + for (i = 0; i < nDevToConfig; i++) + if (DevToConfig[i].pVideo && + (DevToConfig[i].pVideo->domain == pVideo->domain) && + (DevToConfig[i].pVideo->bus == pVideo->bus) && + (DevToConfig[i].pVideo->dev == pVideo->dev) && + (DevToConfig[i].pVideo->func == pVideo->func)) + return 0; + + return 1; +} + +static Bool +bus_sbus_configure(void *busData) +{ +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + int i; + + for (i = 0; i < nDevToConfig; i++) + if (DevToConfig[i].sVideo && + DevToConfig[i].sVideo->fbNum == ((sbusDevicePtr) busData)->fbNum) + return 0; + +#endif + return 1; +} + +static void +bus_pci_newdev_configure(void *busData, int i, int *chipset) +{ + const char *VendorName; + const char *CardName; + char busnum[8]; + struct pci_device * pVideo = NULL; + + pVideo = (struct pci_device *) busData; + + DevToConfig[i].pVideo = pVideo; + + VendorName = pci_device_get_vendor_name( pVideo ); + CardName = pci_device_get_device_name( pVideo ); + + if (!VendorName) { + VendorName = xnfalloc(15); + sprintf((char*)VendorName, "Unknown Vendor"); + } + + if (!CardName) { + CardName = xnfalloc(14); + sprintf((char*)CardName, "Unknown Board"); + } + + DevToConfig[i].GDev.identifier = + xnfalloc(strlen(VendorName) + strlen(CardName) + 2); + sprintf(DevToConfig[i].GDev.identifier, "%s %s", VendorName, CardName); + + DevToConfig[i].GDev.vendor = (char *)VendorName; + DevToConfig[i].GDev.board = (char *)CardName; + + DevToConfig[i].GDev.busID = xnfalloc(16); + xf86FormatPciBusNumber(pVideo->bus, busnum); + sprintf(DevToConfig[i].GDev.busID, "PCI:%s:%d:%d", + busnum, pVideo->dev, pVideo->func); + + DevToConfig[i].GDev.chipID = pVideo->device_id; + DevToConfig[i].GDev.chipRev = pVideo->revision; + + if (*chipset < 0) { + *chipset = (pVideo->vendor_id << 16) | pVideo->device_id; + } +} + +static void +bus_sbus_newdev_configure(void *busData, int i) +{ +#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) + char *promPath = NULL; + DevToConfig[i].sVideo = (sbusDevicePtr) busData; + DevToConfig[i].GDev.identifier = DevToConfig[i].sVideo->descr; + if (sparcPromInit() >= 0) { + promPath = sparcPromNode2Pathname(&DevToConfig[i].sVideo->node); + sparcPromClose(); + } + if (promPath) { + DevToConfig[i].GDev.busID = xnfalloc(strlen(promPath) + 6); + sprintf(DevToConfig[i].GDev.busID, "SBUS:%s", promPath); + free(promPath); + } else { + DevToConfig[i].GDev.busID = xnfalloc(12); + sprintf(DevToConfig[i].GDev.busID, "SBUS:fb%d", + DevToConfig[i].sVideo->fbNum); + } +#endif +} + +/* + * This is called by the driver, either through xf86Match???Instances() or + * directly. We allocate a GDevRec and fill it in as much as we can, letting + * the caller fill in the rest and/or change it as it sees fit. + */ +GDevPtr +xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, int chipset) +{ + int ret, i, j; + + if (!xf86DoConfigure || !xf86DoConfigurePass1) + return NULL; + + /* Check for duplicates */ + switch (bus) { + case BUS_PCI: + ret = bus_pci_configure(busData); + break; + case BUS_SBUS: + ret = bus_sbus_configure(busData); + break; + default: + return NULL; + } + + if (ret == 0) + goto out; + + /* Allocate new structure occurrence */ + i = nDevToConfig++; + DevToConfig = + xnfrealloc(DevToConfig, nDevToConfig * sizeof(DevToConfigRec)); + memset(DevToConfig + i, 0, sizeof(DevToConfigRec)); + + DevToConfig[i].GDev.chipID = + DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1; + + DevToConfig[i].iDriver = CurrentDriver; + + /* Fill in what we know, converting the driver name to lower case */ + DevToConfig[i].GDev.driver = xnfalloc(strlen(driver) + 1); + for (j = 0; (DevToConfig[i].GDev.driver[j] = tolower(driver[j])); j++); + + switch (bus) { + case BUS_PCI: + bus_pci_newdev_configure(busData, i, &chipset); + break; + case BUS_SBUS: + bus_sbus_newdev_configure(busData, i); + break; + default: + break; + } + + /* Get driver's available options */ + if (xf86DriverList[CurrentDriver]->AvailableOptions) + DevToConfig[i].GDev.options = (OptionInfoPtr) + (*xf86DriverList[CurrentDriver]->AvailableOptions)(chipset, + bus); + + return &DevToConfig[i].GDev; + +out: + return NULL; +} + +static XF86ConfInputPtr +configureInputSection (void) +{ + XF86ConfInputPtr mouse = NULL; + parsePrologue (XF86ConfInputPtr, XF86ConfInputRec) + + ptr->inp_identifier = "Keyboard0"; + ptr->inp_driver = "kbd"; + ptr->list.next = NULL; + + /* Crude mechanism to auto-detect mouse (os dependent) */ + { + int fd; +#ifdef WSCONS_SUPPORT + fd = open("/dev/wsmouse", 0); + if (fd >= 0) { + DFLT_MOUSE_DEV = "/dev/wsmouse"; + DFLT_MOUSE_PROTO = "wsmouse"; + close(fd); + } else { + ErrorF("cannot open /dev/wsmouse\n"); + } +#endif + +#ifndef __SCO__ + fd = open(DFLT_MOUSE_DEV, 0); + if (fd != -1) { + foundMouse = TRUE; + close(fd); + } +#else + foundMouse = TRUE; +#endif + } + + mouse = calloc(1, sizeof(XF86ConfInputRec)); + mouse->inp_identifier = "Mouse0"; + mouse->inp_driver = "mouse"; + mouse->inp_option_lst = + xf86addNewOption(mouse->inp_option_lst, xstrdup("Protocol"), + xstrdup(DFLT_MOUSE_PROTO)); +#ifndef __SCO__ + mouse->inp_option_lst = + xf86addNewOption(mouse->inp_option_lst, xstrdup("Device"), + xstrdup(DFLT_MOUSE_DEV)); +#endif + mouse->inp_option_lst = + xf86addNewOption(mouse->inp_option_lst, xstrdup("ZAxisMapping"), + xstrdup("4 5 6 7")); + ptr = (XF86ConfInputPtr)xf86addListItem((glp)ptr, (glp)mouse); + return ptr; +} + +static XF86ConfScreenPtr +configureScreenSection (int screennum) +{ + int i; + int depths[] = { 1, 4, 8, 15, 16, 24/*, 32*/ }; + parsePrologue (XF86ConfScreenPtr, XF86ConfScreenRec) + + ptr->scrn_identifier = malloc(18); + sprintf(ptr->scrn_identifier, "Screen%d", screennum); + ptr->scrn_monitor_str = malloc(19); + sprintf(ptr->scrn_monitor_str, "Monitor%d", screennum); + ptr->scrn_device_str = malloc(16); + sprintf(ptr->scrn_device_str, "Card%d", screennum); + + for (i=0; idisp_depth = depths[i]; + display->disp_black.red = display->disp_white.red = -1; + display->disp_black.green = display->disp_white.green = -1; + display->disp_black.blue = display->disp_white.blue = -1; + ptr->scrn_display_lst = (XF86ConfDisplayPtr)xf86addListItem( + (glp)ptr->scrn_display_lst, (glp)display); + } + + return ptr; +} + +static const char* +optionTypeToSting(OptionValueType type) +{ + switch (type) { + case OPTV_NONE: + return ""; + case OPTV_INTEGER: + return ""; + case OPTV_STRING: + return ""; + case OPTV_ANYSTR: + return "[]"; + case OPTV_REAL: + return ""; + case OPTV_BOOLEAN: + return "[]"; + case OPTV_FREQ: + return ""; + default: + return ""; + } +} + +static XF86ConfDevicePtr +configureDeviceSection (int screennum) +{ + char identifier[16]; + OptionInfoPtr p; + int i = 0; + parsePrologue (XF86ConfDevicePtr, XF86ConfDeviceRec) + + /* Move device info to parser structure */ + sprintf(identifier, "Card%d", screennum); + ptr->dev_identifier = strdup(identifier); +/* ptr->dev_identifier = DevToConfig[screennum].GDev.identifier;*/ + ptr->dev_vendor = DevToConfig[screennum].GDev.vendor; + ptr->dev_board = DevToConfig[screennum].GDev.board; + ptr->dev_chipset = DevToConfig[screennum].GDev.chipset; + ptr->dev_busid = DevToConfig[screennum].GDev.busID; + ptr->dev_driver = DevToConfig[screennum].GDev.driver; + ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac; + for (i = 0; (i < MAXDACSPEEDS) && (i < CONF_MAXDACSPEEDS); i++) + ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i]; + ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam; + ptr->dev_textclockfreq = DevToConfig[screennum].GDev.textClockFreq; + ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase; + ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase; + ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase; + ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip; + for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks); i++) + ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i]; + ptr->dev_clocks = i; + ptr->dev_chipid = DevToConfig[screennum].GDev.chipID; + ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev; + ptr->dev_irq = DevToConfig[screennum].GDev.irq; + + /* Make sure older drivers don't segv */ + if (DevToConfig[screennum].GDev.options) { + /* Fill in the available driver options for people to use */ + const char *descrip = + " ### Available Driver options are:-\n" + " ### Values: : integer, : float, " + ": \"True\"/\"False\",\n" + " ### : \"String\", : \" Hz/kHz/MHz\"\n" + " ### [arg]: arg optional\n"; + ptr->dev_comment = xstrdup(descrip); + if (ptr->dev_comment) { + for (p = DevToConfig[screennum].GDev.options; + p->name != NULL; p++) { + char *p_e; + const char *prefix = " #Option "; + const char *middle = " \t# "; + const char *suffix = "\n"; + const char *opttype = optionTypeToSting(p->type); + char *optname; + int len = strlen(ptr->dev_comment) + strlen(prefix) + + strlen(middle) + strlen(suffix) + 1; + + optname = malloc(strlen(p->name) + 2 + 1); + if (!optname) + break; + sprintf(optname, "\"%s\"", p->name); + + len += max(20, strlen(optname)); + len += strlen(opttype); + + ptr->dev_comment = realloc(ptr->dev_comment, len); + if (!ptr->dev_comment) + break; + p_e = ptr->dev_comment + strlen(ptr->dev_comment); + sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle, + opttype, suffix); + free(optname); + } + } + } + + return ptr; +} + +static XF86ConfLayoutPtr +configureLayoutSection (void) +{ + int scrnum = 0; + parsePrologue (XF86ConfLayoutPtr, XF86ConfLayoutRec) + + ptr->lay_identifier = "X.org Configured"; + + { + XF86ConfInputrefPtr iptr; + + iptr = malloc (sizeof (XF86ConfInputrefRec)); + iptr->list.next = NULL; + iptr->iref_option_lst = NULL; + iptr->iref_inputdev_str = "Mouse0"; + iptr->iref_option_lst = + xf86addNewOption (iptr->iref_option_lst, xstrdup("CorePointer"), NULL); + ptr->lay_input_lst = (XF86ConfInputrefPtr) + xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr); + } + + { + XF86ConfInputrefPtr iptr; + + iptr = malloc (sizeof (XF86ConfInputrefRec)); + iptr->list.next = NULL; + iptr->iref_option_lst = NULL; + iptr->iref_inputdev_str = "Keyboard0"; + iptr->iref_option_lst = + xf86addNewOption (iptr->iref_option_lst, xstrdup("CoreKeyboard"), NULL); + ptr->lay_input_lst = (XF86ConfInputrefPtr) + xf86addListItem ((glp) ptr->lay_input_lst, (glp) iptr); + } + + for (scrnum = 0; scrnum < nDevToConfig; scrnum++) { + XF86ConfAdjacencyPtr aptr; + + aptr = malloc (sizeof (XF86ConfAdjacencyRec)); + aptr->list.next = NULL; + aptr->adj_x = 0; + aptr->adj_y = 0; + aptr->adj_scrnum = scrnum; + aptr->adj_screen_str = xnfalloc(18); + sprintf(aptr->adj_screen_str, "Screen%d", scrnum); + if (scrnum == 0) { + aptr->adj_where = CONF_ADJ_ABSOLUTE; + aptr->adj_refscreen = NULL; + } + else { + aptr->adj_where = CONF_ADJ_RIGHTOF; + aptr->adj_refscreen = xnfalloc(18); + sprintf(aptr->adj_refscreen, "Screen%d", scrnum - 1); + } + ptr->lay_adjacency_lst = + (XF86ConfAdjacencyPtr)xf86addListItem((glp)ptr->lay_adjacency_lst, + (glp)aptr); + } + + return ptr; +} + +static XF86ConfFlagsPtr +configureFlagsSection (void) +{ + parsePrologue (XF86ConfFlagsPtr, XF86ConfFlagsRec) + + return ptr; +} + +static XF86ConfModulePtr +configureModuleSection (void) +{ + char **elist, **el; + /* Find the list of extension & font modules. */ + const char *esubdirs[] = { + "extensions", + "fonts", + NULL + }; + parsePrologue (XF86ConfModulePtr, XF86ConfModuleRec) + + elist = LoaderListDirs(esubdirs, NULL); + if (elist) { + for (el = elist; *el; el++) { + XF86LoadPtr module; + + module = calloc(1, sizeof(XF86LoadRec)); + module->load_name = *el; + ptr->mod_load_lst = (XF86LoadPtr)xf86addListItem( + (glp)ptr->mod_load_lst, (glp)module); + } + free(elist); + } + + return ptr; +} + +static XF86ConfFilesPtr +configureFilesSection (void) +{ + parsePrologue (XF86ConfFilesPtr, XF86ConfFilesRec) + + if (xf86ModulePath) + ptr->file_modulepath = strdup(xf86ModulePath); + if (defaultFontPath) + ptr->file_fontpath = strdup(defaultFontPath); + + return ptr; +} + +static XF86ConfMonitorPtr +configureMonitorSection (int screennum) +{ + parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec) + + ptr->mon_identifier = malloc(19); + sprintf(ptr->mon_identifier, "Monitor%d", screennum); + ptr->mon_vendor = strdup("Monitor Vendor"); + ptr->mon_modelname = strdup("Monitor Model"); + + return ptr; +} + +/* Initialize Configure Monitor from Detailed Timing Block */ +static void handle_detailed_input(struct detailed_monitor_section *det_mon, + void *data) +{ + XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data; + + switch (det_mon->type) { + case DS_NAME: + ptr->mon_modelname = realloc(ptr->mon_modelname, + strlen((char*)(det_mon->section.name)) + + 1); + strcpy(ptr->mon_modelname, + (char*)(det_mon->section.name)); + break; + case DS_RANGES: + ptr->mon_hsync[ptr->mon_n_hsync].lo = + det_mon->section.ranges.min_h; + ptr->mon_hsync[ptr->mon_n_hsync].hi = + det_mon->section.ranges.max_h; + ptr->mon_n_vrefresh = 1; + ptr->mon_vrefresh[ptr->mon_n_hsync].lo = + det_mon->section.ranges.min_v; + ptr->mon_vrefresh[ptr->mon_n_hsync].hi = + det_mon->section.ranges.max_v; + ptr->mon_n_hsync++; + default: + break; + } +} + +static XF86ConfMonitorPtr +configureDDCMonitorSection (int screennum) +{ + int len, mon_width, mon_height; +#define displaySizeMaxLen 80 + char displaySize_string[displaySizeMaxLen]; + int displaySizeLen; + + parsePrologue (XF86ConfMonitorPtr, XF86ConfMonitorRec) + + ptr->mon_identifier = malloc(19); + sprintf(ptr->mon_identifier, "Monitor%d", screennum); + ptr->mon_vendor = strdup(ConfiguredMonitor->vendor.name); + ptr->mon_modelname = malloc(12); + sprintf(ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id); + + /* features in centimetres, we want millimetres */ + mon_width = 10 * ConfiguredMonitor->features.hsize ; + mon_height = 10 * ConfiguredMonitor->features.vsize ; + +#ifdef CONFIGURE_DISPLAYSIZE + ptr->mon_width = mon_width; + ptr->mon_height = mon_height; +#else + if (mon_width && mon_height) { + /* when values available add DisplaySize option AS A COMMENT */ + + displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen, + "\t#DisplaySize\t%5d %5d\t# mm\n", + mon_width, mon_height); + + if (displaySizeLen>0 && displaySizeLenmon_comment) { + len = strlen(ptr->mon_comment); + } else { + len = 0; + } + if ((ptr->mon_comment = + realloc(ptr->mon_comment, len + strlen(displaySize_string) + 1))) { + strcpy(ptr->mon_comment + len, displaySize_string); + } + } + } +#endif /* def CONFIGURE_DISPLAYSIZE */ + + xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input, + ptr); + + if (ConfiguredMonitor->features.dpms) { + ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, xstrdup("DPMS"), NULL); + } + + return ptr; +} + +#if !defined(PATH_MAX) +# define PATH_MAX 1024 +#endif + +void +DoConfigure(void) +{ + int i,j, screennum = -1; + char *home = NULL; + char filename[PATH_MAX]; + char *addslash = ""; + XF86ConfigPtr xf86config = NULL; + char **vlist, **vl; + int *dev2screen; + + vlist = xf86DriverlistFromCompile(); + + if (!vlist) { + ErrorF("Missing output drivers. Configuration failed.\n"); + goto bail; + } + + ErrorF("List of video drivers:\n"); + for (vl = vlist; *vl; vl++) + ErrorF("\t%s\n", *vl); + + /* Load all the drivers that were found. */ + xf86LoadModules(vlist, NULL); + + free(vlist); + + for (i = 0; i < xf86NumDrivers; i++) { + xorgHWFlags flags; + if (!xf86DriverList[i]->driverFunc + || !xf86DriverList[i]->driverFunc(NULL, + GET_REQUIRED_HW_INTERFACES, + &flags) + || NEED_IO_ENABLED(flags)) { + xorgHWAccess = TRUE; + break; + } + } + /* Enable full I/O access */ + if (xorgHWAccess) { + if(!xf86EnableIO()) + /* oops, we have failed */ + xorgHWAccess = FALSE; + } + + xf86FindPrimaryDevice(); + + /* Create XF86Config file structure */ + xf86config = calloc(1, sizeof(XF86ConfigRec)); + + /* Call all of the probe functions, reporting the results. */ + for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) { + xorgHWFlags flags; + Bool found_screen; + DriverRec * const drv = xf86DriverList[CurrentDriver]; + + if (!xorgHWAccess) { + if (!drv->driverFunc + || !drv->driverFunc( NULL, GET_REQUIRED_HW_INTERFACES, &flags ) + || NEED_IO_ENABLED(flags)) + continue; + } + + found_screen = xf86CallDriverProbe( drv, TRUE ); + if ( found_screen && drv->Identify ) { + (*drv->Identify)(0); + } + } + + if (nDevToConfig <= 0) { + ErrorF("No devices to configure. Configuration failed.\n"); + goto bail; + } + + /* Add device, monitor and screen sections for detected devices */ + for (screennum = 0; screennum < nDevToConfig; screennum++) { + XF86ConfDevicePtr DevicePtr; + XF86ConfMonitorPtr MonitorPtr; + XF86ConfScreenPtr ScreenPtr; + + DevicePtr = configureDeviceSection(screennum); + xf86config->conf_device_lst = (XF86ConfDevicePtr)xf86addListItem( + (glp)xf86config->conf_device_lst, (glp)DevicePtr); + MonitorPtr = configureMonitorSection(screennum); + xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem( + (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr); + ScreenPtr = configureScreenSection(screennum); + xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem( + (glp)xf86config->conf_screen_lst, (glp)ScreenPtr); + } + + xf86config->conf_files = configureFilesSection(); + xf86config->conf_modules = configureModuleSection(); + xf86config->conf_flags = configureFlagsSection(); + xf86config->conf_videoadaptor_lst = NULL; + xf86config->conf_modes_lst = NULL; + xf86config->conf_vendor_lst = NULL; + xf86config->conf_dri = NULL; + xf86config->conf_input_lst = configureInputSection(); + xf86config->conf_layout_lst = configureLayoutSection(); + + home = getenv("HOME"); + if ((home == NULL) || (home[0] == '\0')) { + home = "/"; + } else { + /* Determine if trailing slash is present or needed */ + int l = strlen(home); + + if (home[l-1] != '/') { + addslash = "/"; + } + } + + snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new", + home, addslash); + + if (xf86writeConfigFile(filename, xf86config) == 0) { + xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n", + filename, strerror(errno)); + goto bail; + } + + xf86DoConfigurePass1 = FALSE; + /* Try to get DDC information filled in */ + xf86ConfigFile = filename; + if (xf86HandleConfigFile(FALSE) != CONFIG_OK) { + goto bail; + } + + xf86DoConfigurePass1 = FALSE; + + dev2screen = xnfcalloc(1,xf86NumDrivers*sizeof(int)); + + { + Bool *driverProbed = xnfcalloc(1,xf86NumDrivers*sizeof(Bool)); + for (screennum = 0; screennum < nDevToConfig; screennum++) { + int k,l,n,oldNumScreens; + + i = DevToConfig[screennum].iDriver; + + if (driverProbed[i]) continue; + driverProbed[i] = TRUE; + + oldNumScreens = xf86NumScreens; + + xf86CallDriverProbe( xf86DriverList[i], FALSE ); + + /* reorder */ + k = screennum > 0 ? screennum : 1; + for (l = oldNumScreens; l < xf86NumScreens; l++) { + /* is screen primary? */ + Bool primary = FALSE; + for (n = 0; nnumEntities; n++) { + if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) { + dev2screen[0] = l; + primary = TRUE; + break; + } + } + if (primary) continue; + /* not primary: assign it to next device of same driver */ + /* + * NOTE: we assume that devices in DevToConfig + * and xf86Screens[] have the same order except + * for the primary device which always comes first. + */ + for (; k < nDevToConfig; k++) { + if (DevToConfig[k].iDriver == i) { + dev2screen[k++] = l; + break; + } + } + } + } + free(driverProbed); + } + + + if (nDevToConfig != xf86NumScreens) { + ErrorF("Number of created screens does not match number of detected" + " devices.\n Configuration failed.\n"); + goto bail; + } + + xf86PostProbe(); + xf86EntityInit(); + + for (j = 0; j < xf86NumScreens; j++) { + xf86Screens[j]->scrnIndex = j; + } + + xf86freeMonitorList(xf86config->conf_monitor_lst); + xf86config->conf_monitor_lst = NULL; + xf86freeScreenList(xf86config->conf_screen_lst); + xf86config->conf_screen_lst = NULL; + for (j = 0; j < xf86NumScreens; j++) { + XF86ConfMonitorPtr MonitorPtr; + XF86ConfScreenPtr ScreenPtr; + + ConfiguredMonitor = NULL; + + xf86EnableAccess(xf86Screens[dev2screen[j]]); + if ((*xf86Screens[dev2screen[j]]->PreInit)(xf86Screens[dev2screen[j]], + PROBE_DETECT) && + ConfiguredMonitor) { + MonitorPtr = configureDDCMonitorSection(j); + } else { + MonitorPtr = configureMonitorSection(j); + } + ScreenPtr = configureScreenSection(j); + xf86config->conf_monitor_lst = (XF86ConfMonitorPtr)xf86addListItem( + (glp)xf86config->conf_monitor_lst, (glp)MonitorPtr); + xf86config->conf_screen_lst = (XF86ConfScreenPtr)xf86addListItem( + (glp)xf86config->conf_screen_lst, (glp)ScreenPtr); + } + + if (xf86writeConfigFile(filename, xf86config) == 0) { + xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n", + filename, strerror(errno)); + goto bail; + } + + ErrorF("\n"); + +#ifdef __SCO__ + ErrorF("\n"__XSERVERNAME__ + " is using the kernel event driver to access the mouse.\n" + "If you wish to use the internal "__XSERVERNAME__ + " mouse drivers, please\n" + "edit the file and correct the Device.\n"); +#else /* !__SCO__ */ + if (!foundMouse) { + ErrorF("\n"__XSERVERNAME__" is not able to detect your mouse.\n" + "Edit the file and correct the Device.\n"); + } else { + ErrorF("\n"__XSERVERNAME__" detected your mouse at device %s.\n" + "Please check your config if the mouse is still not\n" + "operational, as by default "__XSERVERNAME__ + " tries to autodetect\n" + "the protocol.\n",DFLT_MOUSE_DEV); + } +#endif /* !__SCO__ */ + + if (xf86NumScreens > 1) { + ErrorF("\n"__XSERVERNAME__ + " has configured a multihead system, please check your config.\n"); + } + + ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE ,filename); + ErrorF("To test the server, run 'X -config %s'\n\n", filename); + +bail: + OsCleanup(TRUE); + AbortDDX(); + fflush(stderr); + exit(0); +} diff --git a/xorg-server/hw/xfree86/common/xf86Cursor.c b/xorg-server/hw/xfree86/common/xf86Cursor.c index 6740faf65..76490e52d 100644 --- a/xorg-server/hw/xfree86/common/xf86Cursor.c +++ b/xorg-server/hw/xfree86/common/xf86Cursor.c @@ -1,862 +1,862 @@ -/* - * Copyright (c) 1994-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include "input.h" -#include "cursor.h" -#include "mipointer.h" -#include "scrnintstr.h" -#include "globals.h" - -#include "compiler.h" - -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSproc.h" - -#include -#include "xf86Xinput.h" - -#ifdef XFreeXDGA -#include "dgaproc.h" -#endif - -typedef struct _xf86EdgeRec { - short screen; - short start; - short end; - DDXPointRec offset; - struct _xf86EdgeRec *next; -} xf86EdgeRec, *xf86EdgePtr; - -typedef struct { - xf86EdgePtr left, right, up, down; -} xf86ScreenLayoutRec, *xf86ScreenLayoutPtr; - -static Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y); -static void xf86CrossScreen(ScreenPtr pScreen, Bool entering); -static void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); - -static void xf86PointerMoved(int scrnIndex, int x, int y); - -static miPointerScreenFuncRec xf86PointerScreenFuncs = { - xf86CursorOffScreen, - xf86CrossScreen, - xf86WarpCursor, - /* let miPointerInitialize take care of these */ - NULL, - NULL -}; - -static xf86ScreenLayoutRec xf86ScreenLayout[MAXSCREENS]; - -static Bool HardEdges; - -/* - * xf86InitViewport -- - * Initialize paning & zooming parameters, so that a driver must only - * check what resolutions are possible and whether the virtual area - * is valid if specified. - */ - -void -xf86InitViewport(ScrnInfoPtr pScr) -{ - - pScr->PointerMoved = xf86PointerMoved; - - /* - * Compute the initial Viewport if necessary - */ - if (pScr->display) { - if (pScr->display->frameX0 < 0) { - pScr->frameX0 = (pScr->virtualX - pScr->modes->HDisplay) / 2; - pScr->frameY0 = (pScr->virtualY - pScr->modes->VDisplay) / 2; - } else { - pScr->frameX0 = pScr->display->frameX0; - pScr->frameY0 = pScr->display->frameY0; - } - } - - pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; - pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; - - /* - * Now adjust the initial Viewport, so it lies within the virtual area - */ - if (pScr->frameX1 >= pScr->virtualX) - { - pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay; - pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; - } - - if (pScr->frameY1 >= pScr->virtualY) - { - pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay; - pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; - } -} - - -/* - * xf86SetViewport -- - * Scroll the visual part of the screen so the pointer is visible. - */ - -void -xf86SetViewport(ScreenPtr pScreen, int x, int y) -{ - ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); - - (*pScr->PointerMoved)(pScreen->myNum, x, y); -} - - -static void -xf86PointerMoved(int scrnIndex, int x, int y) -{ - Bool frameChanged = FALSE; - ScrnInfoPtr pScr = xf86Screens[scrnIndex]; - - /* - * check wether (x,y) belongs to the visual part of the screen - * if not, change the base of the displayed frame accoring - */ - if ( pScr->frameX0 > x) { - pScr->frameX0 = x; - pScr->frameX1 = x + pScr->currentMode->HDisplay - 1; - frameChanged = TRUE ; - } - - if ( pScr->frameX1 < x) { - pScr->frameX1 = x + 1; - pScr->frameX0 = x - pScr->currentMode->HDisplay + 1; - frameChanged = TRUE ; - } - - if ( pScr->frameY0 > y) { - pScr->frameY0 = y; - pScr->frameY1 = y + pScr->currentMode->VDisplay - 1; - frameChanged = TRUE; - } - - if ( pScr->frameY1 < y) { - pScr->frameY1 = y; - pScr->frameY0 = y - pScr->currentMode->VDisplay + 1; - frameChanged = TRUE; - } - - if (frameChanged && pScr->AdjustFrame != NULL) - pScr->AdjustFrame(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); -} - -/* - * xf86LockZoom -- - * Enable/disable ZoomViewport - */ - -void -xf86LockZoom(ScreenPtr pScreen, Bool lock) -{ - XF86SCRNINFO(pScreen)->zoomLocked = lock; -} - -/* - * xf86SwitchMode -- - * This is called by both keyboard processing and the VidMode extension to - * set a new mode. - */ - -Bool -xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) -{ - ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); - ScreenPtr pCursorScreen; - Bool Switched; - int px, py; - DeviceIntPtr dev, it; - - if (!pScr->vtSema || !mode || !pScr->SwitchMode) - return FALSE; - -#ifdef XFreeXDGA - if (DGAActive(pScr->scrnIndex)) - return FALSE; -#endif - - if (mode == pScr->currentMode) - return TRUE; - - if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY) - return FALSE; - - /* Let's take an educated guess for which pointer to take here. And about as - educated as it gets is to take the first pointer we find. - */ - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner) - break; - } - - pCursorScreen = miPointerGetScreen(dev); - if (pScreen == pCursorScreen) - miPointerGetPosition(dev, &px, &py); - - xf86EnterServerState(SETUP); - Switched = (*pScr->SwitchMode)(pScr->scrnIndex, mode, 0); - if (Switched) { - pScr->currentMode = mode; - - /* - * Adjust frame for new display size. - * Frame is centered around cursor position if cursor is on same screen. - */ - if (pScreen == pCursorScreen) - pScr->frameX0 = px - (mode->HDisplay / 2) + 1; - else - pScr->frameX0 = (pScr->frameX0 + pScr->frameX1 + 1 - mode->HDisplay) / 2; - - if (pScr->frameX0 < 0) - pScr->frameX0 = 0; - - pScr->frameX1 = pScr->frameX0 + mode->HDisplay - 1; - if (pScr->frameX1 >= pScr->virtualX) { - pScr->frameX0 = pScr->virtualX - mode->HDisplay; - pScr->frameX1 = pScr->virtualX - 1; - } - - if (pScreen == pCursorScreen) - pScr->frameY0 = py - (mode->VDisplay / 2) + 1; - else - pScr->frameY0 = (pScr->frameY0 + pScr->frameY1 + 1 - mode->VDisplay) / 2; - - if (pScr->frameY0 < 0) - pScr->frameY0 = 0; - - pScr->frameY1 = pScr->frameY0 + mode->VDisplay - 1; - if (pScr->frameY1 >= pScr->virtualY) { - pScr->frameY0 = pScr->virtualY - mode->VDisplay; - pScr->frameY1 = pScr->virtualY - 1; - } - } - xf86EnterServerState(OPERATING); - - if (pScr->AdjustFrame) - (*pScr->AdjustFrame)(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); - - /* The original code centered the frame around the cursor if possible. - * Since this is hard to achieve with multiple cursors, we do the following: - * - center around the first pointer - * - move all other pointers to the nearest edge on the screen (or leave - * them unmodified if they are within the boundaries). - */ - if (pScreen == pCursorScreen) - { - xf86WarpCursor(dev, pScreen, px, py); - } - - for (it = inputInfo.devices; it; it = it->next) - { - if (it == dev) - continue; - - if (IsPointerDevice(it) && it->spriteInfo->spriteOwner) - { - pCursorScreen = miPointerGetScreen(it); - if (pScreen == pCursorScreen) - { - miPointerGetPosition(it, &px, &py); - if (px < pScr->frameX0) - px = pScr->frameX0; - else if (px > pScr->frameX1) - px = pScr->frameX1; - - if(py < pScr->frameY0) - py = pScr->frameY0; - else if(py > pScr->frameY1) - py = pScr->frameY1; - - xf86WarpCursor(it, pScreen, px, py); - } - } - } - - return Switched; -} - -/* - * xf86ZoomViewport -- - * Reinitialize the visual part of the screen for another mode. - */ - -void -xf86ZoomViewport(ScreenPtr pScreen, int zoom) -{ - ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); - DisplayModePtr mode; - - if (pScr->zoomLocked || !(mode = pScr->currentMode)) - return; - - do { - if (zoom > 0) - mode = mode->next; - else - mode = mode->prev; - } while (mode != pScr->currentMode && !(mode->type & M_T_USERDEF)); - - (void)xf86SwitchMode(pScreen, mode); -} - - -static xf86EdgePtr -FindEdge(xf86EdgePtr edge, int val) -{ - while(edge && (edge->end <= val)) - edge = edge->next; - - if(edge && (edge->start <= val)) - return edge; - - return NULL; -} - -/* - * xf86CursorOffScreen -- - * Check whether it is necessary to switch to another screen - */ - -static Bool -xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y) -{ - xf86EdgePtr edge; - int tmp; - - if(screenInfo.numScreens == 1) - return FALSE; - - if(*x < 0) { - tmp = *y; - if(tmp < 0) tmp = 0; - if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; - - if((edge = xf86ScreenLayout[(*pScreen)->myNum].left)) - edge = FindEdge(edge, tmp); - - if(!edge) *x = 0; - else { - *x += edge->offset.x; - *y += edge->offset.y; - *pScreen = xf86Screens[edge->screen]->pScreen; - } - } - - if(*x >= (*pScreen)->width) { - tmp = *y; - if(tmp < 0) tmp = 0; - if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; - - if((edge = xf86ScreenLayout[(*pScreen)->myNum].right)) - edge = FindEdge(edge, tmp); - - if(!edge) *x = (*pScreen)->width - 1; - else { - *x += edge->offset.x; - *y += edge->offset.y; - *pScreen = xf86Screens[edge->screen]->pScreen; - } - } - - if(*y < 0) { - tmp = *x; - if(tmp < 0) tmp = 0; - if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; - - if((edge = xf86ScreenLayout[(*pScreen)->myNum].up)) - edge = FindEdge(edge, tmp); - - if(!edge) *y = 0; - else { - *x += edge->offset.x; - *y += edge->offset.y; - *pScreen = xf86Screens[edge->screen]->pScreen; - } - } - - if(*y >= (*pScreen)->height) { - tmp = *x; - if(tmp < 0) tmp = 0; - if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; - - if((edge = xf86ScreenLayout[(*pScreen)->myNum].down)) - edge = FindEdge(edge, tmp); - - if(!edge) *y = (*pScreen)->height - 1; - else { - *x += edge->offset.x; - *y += edge->offset.y; - (*pScreen) = xf86Screens[edge->screen]->pScreen; - } - } - - -#if 0 - /* This presents problems for overlapping screens when - HardEdges is used. Have to think about the logic more */ - if((*x < 0) || (*x >= (*pScreen)->width) || - (*y < 0) || (*y >= (*pScreen)->height)) { - /* We may have crossed more than one screen */ - xf86CursorOffScreen(pScreen, x, y); - } -#endif - - return TRUE; -} - - - -/* - * xf86CrossScreen -- - * Switch to another screen - * - * Currently nothing special happens, but mi assumes the CrossScreen - * method exists. - */ - -static void -xf86CrossScreen (ScreenPtr pScreen, Bool entering) -{ -} - - -/* - * xf86WarpCursor -- - * Warp possible to another screen - */ - -/* ARGSUSED */ -static void -xf86WarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - int sigstate; - sigstate = xf86BlockSIGIO (); - miPointerWarpCursor(pDev, pScreen, x, y); - - xf86Info.currentScreen = pScreen; - xf86UnblockSIGIO (sigstate); -} - - -void * -xf86GetPointerScreenFuncs(void) -{ - return (void *)&xf86PointerScreenFuncs; -} - - -static xf86EdgePtr -AddEdge( - xf86EdgePtr edge, - short min, - short max, - short dx, - short dy, - short screen -){ - xf86EdgePtr pEdge = edge, pPrev = NULL, pNew; - - while(1) { - while(pEdge && (min >= pEdge->end)) { - pPrev = pEdge; - pEdge = pEdge->next; - } - - if(!pEdge) { - if(!(pNew = xalloc(sizeof(xf86EdgeRec)))) - break; - - pNew->screen = screen; - pNew->start = min; - pNew->end = max; - pNew->offset.x = dx; - pNew->offset.y = dy; - pNew->next = NULL; - - if(pPrev) - pPrev->next = pNew; - else - edge = pNew; - - break; - } else if (min < pEdge->start) { - if(!(pNew = xalloc(sizeof(xf86EdgeRec)))) - break; - - pNew->screen = screen; - pNew->start = min; - pNew->offset.x = dx; - pNew->offset.y = dy; - pNew->next = pEdge; - - if(pPrev) pPrev->next = pNew; - else edge = pNew; - - if(max <= pEdge->start) { - pNew->end = max; - break; - } else { - pNew->end = pEdge->start; - min = pEdge->end; - } - } else - min = pEdge->end; - - pPrev = pEdge; - pEdge = pEdge->next; - - if(max <= min) break; - } - - return edge; -} - -static void -FillOutEdge(xf86EdgePtr pEdge, int limit) -{ - xf86EdgePtr pNext; - int diff; - - if(pEdge->start > 0) pEdge->start = 0; - - while((pNext = pEdge->next)) { - diff = pNext->start - pEdge->end; - if(diff > 0) { - pEdge->end += diff >> 1; - pNext->start -= diff - (diff >> 1); - } - pEdge = pNext; - } - - if(pEdge->end < limit) - pEdge->end = limit; -} - -/* - * xf86InitOrigins() can deal with a maximum of 32 screens - * on 32 bit architectures, 64 on 64 bit architectures. - */ - -void -xf86InitOrigins(void) -{ - unsigned long screensLeft, prevScreensLeft, mask; - screenLayoutPtr screen; - ScreenPtr pScreen; - int x1, x2, y1, y2, left, right, top, bottom; - int i, j, ref, minX, minY, min, max; - xf86ScreenLayoutPtr pLayout; - Bool OldStyleConfig = FALSE; - - /* need to have this set up with a config file option */ - HardEdges = FALSE; - - bzero(xf86ScreenLayout, MAXSCREENS * sizeof(xf86ScreenLayoutRec)); - - screensLeft = prevScreensLeft = (1 << xf86NumScreens) - 1; - - while(1) { - for(mask = screensLeft, i = 0; mask; mask >>= 1, i++) { - if(!(mask & 1L)) continue; - - screen = &xf86ConfigLayout.screens[i]; - - if (screen->refscreen != NULL && - screen->refscreen->screennum >= xf86NumScreens) { - screensLeft &= ~(1 << i); - xf86Msg(X_WARNING, "Not including screen \"%s\" in origins calculation.\n", - screen->screen->id); - continue; - } - - switch(screen->where) { - case PosObsolete: - OldStyleConfig = TRUE; - pLayout = &xf86ScreenLayout[i]; - /* force edge lists */ - if(screen->left) { - ref = screen->left->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - pLayout->left = AddEdge(pLayout->left, - 0, xf86Screens[i]->pScreen->height, - xf86Screens[ref]->pScreen->width, 0, ref); - } - if(screen->right) { - ref = screen->right->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - pScreen = xf86Screens[i]->pScreen; - pLayout->right = AddEdge(pLayout->right, - 0, pScreen->height, -pScreen->width, 0, ref); - } - if(screen->top) { - ref = screen->top->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - pLayout->up = AddEdge(pLayout->up, - 0, xf86Screens[i]->pScreen->width, - 0, xf86Screens[ref]->pScreen->height, ref); - } - if(screen->bottom) { - ref = screen->bottom->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - pScreen = xf86Screens[i]->pScreen; - pLayout->down = AddEdge(pLayout->down, - 0, pScreen->width, 0, -pScreen->height, ref); - } - /* we could also try to place it based on those - relative locations if we wanted to */ - screen->x = screen->y = 0; - /* FALLTHROUGH */ - case PosAbsolute: - dixScreenOrigins[i].x = screen->x; - dixScreenOrigins[i].y = screen->y; - screensLeft &= ~(1 << i); - break; - case PosRelative: - ref = screen->refscreen->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - if(screensLeft & (1 << ref)) break; - dixScreenOrigins[i].x = dixScreenOrigins[ref].x + screen->x; - dixScreenOrigins[i].y = dixScreenOrigins[ref].y + screen->y; - screensLeft &= ~(1 << i); - break; - case PosRightOf: - ref = screen->refscreen->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - if(screensLeft & (1 << ref)) break; - pScreen = xf86Screens[ref]->pScreen; - dixScreenOrigins[i].x = - dixScreenOrigins[ref].x + pScreen->width; - dixScreenOrigins[i].y = dixScreenOrigins[ref].y; - screensLeft &= ~(1 << i); - break; - case PosLeftOf: - ref = screen->refscreen->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - if(screensLeft & (1 << ref)) break; - pScreen = xf86Screens[i]->pScreen; - dixScreenOrigins[i].x = - dixScreenOrigins[ref].x - pScreen->width; - dixScreenOrigins[i].y = dixScreenOrigins[ref].y; - screensLeft &= ~(1 << i); - break; - case PosBelow: - ref = screen->refscreen->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - if(screensLeft & (1 << ref)) break; - pScreen = xf86Screens[ref]->pScreen; - dixScreenOrigins[i].x = dixScreenOrigins[ref].x; - dixScreenOrigins[i].y = - dixScreenOrigins[ref].y + pScreen->height; - screensLeft &= ~(1 << i); - break; - case PosAbove: - ref = screen->refscreen->screennum; - if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { - ErrorF("Referenced uninitialized screen in Layout!\n"); - break; - } - if(screensLeft & (1 << ref)) break; - pScreen = xf86Screens[i]->pScreen; - dixScreenOrigins[i].x = dixScreenOrigins[ref].x; - dixScreenOrigins[i].y = - dixScreenOrigins[ref].y - pScreen->height; - screensLeft &= ~(1 << i); - break; - default: - ErrorF("Illegal placement keyword in Layout!\n"); - break; - } - - } - - if(!screensLeft) break; - - if(screensLeft == prevScreensLeft) { - /* All the remaining screens are referencing each other. - Assign a value to one of them and go through again */ - i = 0; - while(!((1 << i) & screensLeft)){ i++; } - - ref = xf86ConfigLayout.screens[i].refscreen->screennum; - dixScreenOrigins[ref].x = dixScreenOrigins[ref].y = 0; - screensLeft &= ~(1 << ref); - } - - prevScreensLeft = screensLeft; - } - - /* justify the topmost and leftmost to (0,0) */ - minX = dixScreenOrigins[0].x; - minY = dixScreenOrigins[0].y; - - for(i = 1; i < xf86NumScreens; i++) { - if(dixScreenOrigins[i].x < minX) - minX = dixScreenOrigins[i].x; - if(dixScreenOrigins[i].y < minY) - minY = dixScreenOrigins[i].y; - } - - if (minX || minY) { - for(i = 0; i < xf86NumScreens; i++) { - dixScreenOrigins[i].x -= minX; - dixScreenOrigins[i].y -= minY; - } - } - - - /* Create the edge lists */ - - if(!OldStyleConfig) { - for(i = 0; i < xf86NumScreens; i++) { - pLayout = &xf86ScreenLayout[i]; - - pScreen = xf86Screens[i]->pScreen; - - left = dixScreenOrigins[i].x; - right = left + pScreen->width; - top = dixScreenOrigins[i].y; - bottom = top + pScreen->height; - - for(j = 0; j < xf86NumScreens; j++) { - if(i == j) continue; - - x1 = dixScreenOrigins[j].x; - x2 = x1 + xf86Screens[j]->pScreen->width; - y1 = dixScreenOrigins[j].y; - y2 = y1 + xf86Screens[j]->pScreen->height; - - if((bottom > y1) && (top < y2)) { - min = y1 - top; - if(min < 0) min = 0; - max = pScreen->height - (bottom - y2); - if(max > pScreen->height) max = pScreen->height; - - if(((left - 1) >= x1) && ((left - 1) < x2)) - pLayout->left = AddEdge(pLayout->left, min, max, - dixScreenOrigins[i].x - dixScreenOrigins[j].x, - dixScreenOrigins[i].y - dixScreenOrigins[j].y, j); - - if((right >= x1) && (right < x2)) - pLayout->right = AddEdge(pLayout->right, min, max, - dixScreenOrigins[i].x - dixScreenOrigins[j].x, - dixScreenOrigins[i].y - dixScreenOrigins[j].y, j); - } - - - if((left < x2) && (right > x1)) { - min = x1 - left; - if(min < 0) min = 0; - max = pScreen->width - (right - x2); - if(max > pScreen->width) max = pScreen->width; - - if(((top - 1) >= y1) && ((top - 1) < y2)) - pLayout->up = AddEdge(pLayout->up, min, max, - dixScreenOrigins[i].x - dixScreenOrigins[j].x, - dixScreenOrigins[i].y - dixScreenOrigins[j].y, j); - - if((bottom >= y1) && (bottom < y2)) - pLayout->down = AddEdge(pLayout->down, min, max, - dixScreenOrigins[i].x - dixScreenOrigins[j].x, - dixScreenOrigins[i].y - dixScreenOrigins[j].y, j); - } - } - } - } - - if(!HardEdges && !OldStyleConfig) { - for(i = 0; i < xf86NumScreens; i++) { - pLayout = &xf86ScreenLayout[i]; - pScreen = xf86Screens[i]->pScreen; - if(pLayout->left) - FillOutEdge(pLayout->left, pScreen->height); - if(pLayout->right) - FillOutEdge(pLayout->right, pScreen->height); - if(pLayout->up) - FillOutEdge(pLayout->up, pScreen->width); - if(pLayout->down) - FillOutEdge(pLayout->down, pScreen->width); - } - } -} - -void -xf86ReconfigureLayout(void) -{ - int i; - - for (i = 0; i < MAXSCREENS; i++) { - xf86ScreenLayoutPtr sl = &xf86ScreenLayout[i]; - /* we don't have to zero these, xf86InitOrigins() takes care of that */ - if (sl->left) xfree(sl->left); - if (sl->right) xfree(sl->right); - if (sl->up) xfree(sl->up); - if (sl->down) xfree(sl->down); - } - - xf86InitOrigins(); -} - - +/* + * Copyright (c) 1994-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include "input.h" +#include "cursor.h" +#include "mipointer.h" +#include "scrnintstr.h" +#include "globals.h" + +#include "compiler.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSproc.h" + +#include +#include "xf86Xinput.h" + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +typedef struct _xf86EdgeRec { + short screen; + short start; + short end; + DDXPointRec offset; + struct _xf86EdgeRec *next; +} xf86EdgeRec, *xf86EdgePtr; + +typedef struct { + xf86EdgePtr left, right, up, down; +} xf86ScreenLayoutRec, *xf86ScreenLayoutPtr; + +static Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y); +static void xf86CrossScreen(ScreenPtr pScreen, Bool entering); +static void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); + +static void xf86PointerMoved(int scrnIndex, int x, int y); + +static miPointerScreenFuncRec xf86PointerScreenFuncs = { + xf86CursorOffScreen, + xf86CrossScreen, + xf86WarpCursor, + /* let miPointerInitialize take care of these */ + NULL, + NULL +}; + +static xf86ScreenLayoutRec xf86ScreenLayout[MAXSCREENS]; + +static Bool HardEdges; + +/* + * xf86InitViewport -- + * Initialize paning & zooming parameters, so that a driver must only + * check what resolutions are possible and whether the virtual area + * is valid if specified. + */ + +void +xf86InitViewport(ScrnInfoPtr pScr) +{ + + pScr->PointerMoved = xf86PointerMoved; + + /* + * Compute the initial Viewport if necessary + */ + if (pScr->display) { + if (pScr->display->frameX0 < 0) { + pScr->frameX0 = (pScr->virtualX - pScr->modes->HDisplay) / 2; + pScr->frameY0 = (pScr->virtualY - pScr->modes->VDisplay) / 2; + } else { + pScr->frameX0 = pScr->display->frameX0; + pScr->frameY0 = pScr->display->frameY0; + } + } + + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + + /* + * Now adjust the initial Viewport, so it lies within the virtual area + */ + if (pScr->frameX1 >= pScr->virtualX) + { + pScr->frameX0 = pScr->virtualX - pScr->modes->HDisplay; + pScr->frameX1 = pScr->frameX0 + pScr->modes->HDisplay - 1; + } + + if (pScr->frameY1 >= pScr->virtualY) + { + pScr->frameY0 = pScr->virtualY - pScr->modes->VDisplay; + pScr->frameY1 = pScr->frameY0 + pScr->modes->VDisplay - 1; + } +} + + +/* + * xf86SetViewport -- + * Scroll the visual part of the screen so the pointer is visible. + */ + +void +xf86SetViewport(ScreenPtr pScreen, int x, int y) +{ + ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); + + (*pScr->PointerMoved)(pScreen->myNum, x, y); +} + + +static void +xf86PointerMoved(int scrnIndex, int x, int y) +{ + Bool frameChanged = FALSE; + ScrnInfoPtr pScr = xf86Screens[scrnIndex]; + + /* + * check wether (x,y) belongs to the visual part of the screen + * if not, change the base of the displayed frame accoring + */ + if ( pScr->frameX0 > x) { + pScr->frameX0 = x; + pScr->frameX1 = x + pScr->currentMode->HDisplay - 1; + frameChanged = TRUE ; + } + + if ( pScr->frameX1 < x) { + pScr->frameX1 = x + 1; + pScr->frameX0 = x - pScr->currentMode->HDisplay + 1; + frameChanged = TRUE ; + } + + if ( pScr->frameY0 > y) { + pScr->frameY0 = y; + pScr->frameY1 = y + pScr->currentMode->VDisplay - 1; + frameChanged = TRUE; + } + + if ( pScr->frameY1 < y) { + pScr->frameY1 = y; + pScr->frameY0 = y - pScr->currentMode->VDisplay + 1; + frameChanged = TRUE; + } + + if (frameChanged && pScr->AdjustFrame != NULL) + pScr->AdjustFrame(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); +} + +/* + * xf86LockZoom -- + * Enable/disable ZoomViewport + */ + +void +xf86LockZoom(ScreenPtr pScreen, Bool lock) +{ + XF86SCRNINFO(pScreen)->zoomLocked = lock; +} + +/* + * xf86SwitchMode -- + * This is called by both keyboard processing and the VidMode extension to + * set a new mode. + */ + +Bool +xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) +{ + ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); + ScreenPtr pCursorScreen; + Bool Switched; + int px, py; + DeviceIntPtr dev, it; + + if (!pScr->vtSema || !mode || !pScr->SwitchMode) + return FALSE; + +#ifdef XFreeXDGA + if (DGAActive(pScr->scrnIndex)) + return FALSE; +#endif + + if (mode == pScr->currentMode) + return TRUE; + + if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY) + return FALSE; + + /* Let's take an educated guess for which pointer to take here. And about as + educated as it gets is to take the first pointer we find. + */ + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner) + break; + } + + pCursorScreen = miPointerGetScreen(dev); + if (pScreen == pCursorScreen) + miPointerGetPosition(dev, &px, &py); + + xf86EnterServerState(SETUP); + Switched = (*pScr->SwitchMode)(pScr->scrnIndex, mode, 0); + if (Switched) { + pScr->currentMode = mode; + + /* + * Adjust frame for new display size. + * Frame is centered around cursor position if cursor is on same screen. + */ + if (pScreen == pCursorScreen) + pScr->frameX0 = px - (mode->HDisplay / 2) + 1; + else + pScr->frameX0 = (pScr->frameX0 + pScr->frameX1 + 1 - mode->HDisplay) / 2; + + if (pScr->frameX0 < 0) + pScr->frameX0 = 0; + + pScr->frameX1 = pScr->frameX0 + mode->HDisplay - 1; + if (pScr->frameX1 >= pScr->virtualX) { + pScr->frameX0 = pScr->virtualX - mode->HDisplay; + pScr->frameX1 = pScr->virtualX - 1; + } + + if (pScreen == pCursorScreen) + pScr->frameY0 = py - (mode->VDisplay / 2) + 1; + else + pScr->frameY0 = (pScr->frameY0 + pScr->frameY1 + 1 - mode->VDisplay) / 2; + + if (pScr->frameY0 < 0) + pScr->frameY0 = 0; + + pScr->frameY1 = pScr->frameY0 + mode->VDisplay - 1; + if (pScr->frameY1 >= pScr->virtualY) { + pScr->frameY0 = pScr->virtualY - mode->VDisplay; + pScr->frameY1 = pScr->virtualY - 1; + } + } + xf86EnterServerState(OPERATING); + + if (pScr->AdjustFrame) + (*pScr->AdjustFrame)(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); + + /* The original code centered the frame around the cursor if possible. + * Since this is hard to achieve with multiple cursors, we do the following: + * - center around the first pointer + * - move all other pointers to the nearest edge on the screen (or leave + * them unmodified if they are within the boundaries). + */ + if (pScreen == pCursorScreen) + { + xf86WarpCursor(dev, pScreen, px, py); + } + + for (it = inputInfo.devices; it; it = it->next) + { + if (it == dev) + continue; + + if (IsPointerDevice(it) && it->spriteInfo->spriteOwner) + { + pCursorScreen = miPointerGetScreen(it); + if (pScreen == pCursorScreen) + { + miPointerGetPosition(it, &px, &py); + if (px < pScr->frameX0) + px = pScr->frameX0; + else if (px > pScr->frameX1) + px = pScr->frameX1; + + if(py < pScr->frameY0) + py = pScr->frameY0; + else if(py > pScr->frameY1) + py = pScr->frameY1; + + xf86WarpCursor(it, pScreen, px, py); + } + } + } + + return Switched; +} + +/* + * xf86ZoomViewport -- + * Reinitialize the visual part of the screen for another mode. + */ + +void +xf86ZoomViewport(ScreenPtr pScreen, int zoom) +{ + ScrnInfoPtr pScr = XF86SCRNINFO(pScreen); + DisplayModePtr mode; + + if (pScr->zoomLocked || !(mode = pScr->currentMode)) + return; + + do { + if (zoom > 0) + mode = mode->next; + else + mode = mode->prev; + } while (mode != pScr->currentMode && !(mode->type & M_T_USERDEF)); + + (void)xf86SwitchMode(pScreen, mode); +} + + +static xf86EdgePtr +FindEdge(xf86EdgePtr edge, int val) +{ + while(edge && (edge->end <= val)) + edge = edge->next; + + if(edge && (edge->start <= val)) + return edge; + + return NULL; +} + +/* + * xf86CursorOffScreen -- + * Check whether it is necessary to switch to another screen + */ + +static Bool +xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y) +{ + xf86EdgePtr edge; + int tmp; + + if(screenInfo.numScreens == 1) + return FALSE; + + if(*x < 0) { + tmp = *y; + if(tmp < 0) tmp = 0; + if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; + + if((edge = xf86ScreenLayout[(*pScreen)->myNum].left)) + edge = FindEdge(edge, tmp); + + if(!edge) *x = 0; + else { + *x += edge->offset.x; + *y += edge->offset.y; + *pScreen = xf86Screens[edge->screen]->pScreen; + } + } + + if(*x >= (*pScreen)->width) { + tmp = *y; + if(tmp < 0) tmp = 0; + if(tmp >= (*pScreen)->height) tmp = (*pScreen)->height - 1; + + if((edge = xf86ScreenLayout[(*pScreen)->myNum].right)) + edge = FindEdge(edge, tmp); + + if(!edge) *x = (*pScreen)->width - 1; + else { + *x += edge->offset.x; + *y += edge->offset.y; + *pScreen = xf86Screens[edge->screen]->pScreen; + } + } + + if(*y < 0) { + tmp = *x; + if(tmp < 0) tmp = 0; + if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; + + if((edge = xf86ScreenLayout[(*pScreen)->myNum].up)) + edge = FindEdge(edge, tmp); + + if(!edge) *y = 0; + else { + *x += edge->offset.x; + *y += edge->offset.y; + *pScreen = xf86Screens[edge->screen]->pScreen; + } + } + + if(*y >= (*pScreen)->height) { + tmp = *x; + if(tmp < 0) tmp = 0; + if(tmp >= (*pScreen)->width) tmp = (*pScreen)->width - 1; + + if((edge = xf86ScreenLayout[(*pScreen)->myNum].down)) + edge = FindEdge(edge, tmp); + + if(!edge) *y = (*pScreen)->height - 1; + else { + *x += edge->offset.x; + *y += edge->offset.y; + (*pScreen) = xf86Screens[edge->screen]->pScreen; + } + } + + +#if 0 + /* This presents problems for overlapping screens when + HardEdges is used. Have to think about the logic more */ + if((*x < 0) || (*x >= (*pScreen)->width) || + (*y < 0) || (*y >= (*pScreen)->height)) { + /* We may have crossed more than one screen */ + xf86CursorOffScreen(pScreen, x, y); + } +#endif + + return TRUE; +} + + + +/* + * xf86CrossScreen -- + * Switch to another screen + * + * Currently nothing special happens, but mi assumes the CrossScreen + * method exists. + */ + +static void +xf86CrossScreen (ScreenPtr pScreen, Bool entering) +{ +} + + +/* + * xf86WarpCursor -- + * Warp possible to another screen + */ + +/* ARGSUSED */ +static void +xf86WarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + int sigstate; + sigstate = xf86BlockSIGIO (); + miPointerWarpCursor(pDev, pScreen, x, y); + + xf86Info.currentScreen = pScreen; + xf86UnblockSIGIO (sigstate); +} + + +void * +xf86GetPointerScreenFuncs(void) +{ + return (void *)&xf86PointerScreenFuncs; +} + + +static xf86EdgePtr +AddEdge( + xf86EdgePtr edge, + short min, + short max, + short dx, + short dy, + short screen +){ + xf86EdgePtr pEdge = edge, pPrev = NULL, pNew; + + while(1) { + while(pEdge && (min >= pEdge->end)) { + pPrev = pEdge; + pEdge = pEdge->next; + } + + if(!pEdge) { + if(!(pNew = malloc(sizeof(xf86EdgeRec)))) + break; + + pNew->screen = screen; + pNew->start = min; + pNew->end = max; + pNew->offset.x = dx; + pNew->offset.y = dy; + pNew->next = NULL; + + if(pPrev) + pPrev->next = pNew; + else + edge = pNew; + + break; + } else if (min < pEdge->start) { + if(!(pNew = malloc(sizeof(xf86EdgeRec)))) + break; + + pNew->screen = screen; + pNew->start = min; + pNew->offset.x = dx; + pNew->offset.y = dy; + pNew->next = pEdge; + + if(pPrev) pPrev->next = pNew; + else edge = pNew; + + if(max <= pEdge->start) { + pNew->end = max; + break; + } else { + pNew->end = pEdge->start; + min = pEdge->end; + } + } else + min = pEdge->end; + + pPrev = pEdge; + pEdge = pEdge->next; + + if(max <= min) break; + } + + return edge; +} + +static void +FillOutEdge(xf86EdgePtr pEdge, int limit) +{ + xf86EdgePtr pNext; + int diff; + + if(pEdge->start > 0) pEdge->start = 0; + + while((pNext = pEdge->next)) { + diff = pNext->start - pEdge->end; + if(diff > 0) { + pEdge->end += diff >> 1; + pNext->start -= diff - (diff >> 1); + } + pEdge = pNext; + } + + if(pEdge->end < limit) + pEdge->end = limit; +} + +/* + * xf86InitOrigins() can deal with a maximum of 32 screens + * on 32 bit architectures, 64 on 64 bit architectures. + */ + +void +xf86InitOrigins(void) +{ + unsigned long screensLeft, prevScreensLeft, mask; + screenLayoutPtr screen; + ScreenPtr pScreen; + int x1, x2, y1, y2, left, right, top, bottom; + int i, j, ref, minX, minY, min, max; + xf86ScreenLayoutPtr pLayout; + Bool OldStyleConfig = FALSE; + + /* need to have this set up with a config file option */ + HardEdges = FALSE; + + bzero(xf86ScreenLayout, MAXSCREENS * sizeof(xf86ScreenLayoutRec)); + + screensLeft = prevScreensLeft = (1 << xf86NumScreens) - 1; + + while(1) { + for(mask = screensLeft, i = 0; mask; mask >>= 1, i++) { + if(!(mask & 1L)) continue; + + screen = &xf86ConfigLayout.screens[i]; + + if (screen->refscreen != NULL && + screen->refscreen->screennum >= xf86NumScreens) { + screensLeft &= ~(1 << i); + xf86Msg(X_WARNING, "Not including screen \"%s\" in origins calculation.\n", + screen->screen->id); + continue; + } + + switch(screen->where) { + case PosObsolete: + OldStyleConfig = TRUE; + pLayout = &xf86ScreenLayout[i]; + /* force edge lists */ + if(screen->left) { + ref = screen->left->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + pLayout->left = AddEdge(pLayout->left, + 0, xf86Screens[i]->pScreen->height, + xf86Screens[ref]->pScreen->width, 0, ref); + } + if(screen->right) { + ref = screen->right->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + pScreen = xf86Screens[i]->pScreen; + pLayout->right = AddEdge(pLayout->right, + 0, pScreen->height, -pScreen->width, 0, ref); + } + if(screen->top) { + ref = screen->top->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + pLayout->up = AddEdge(pLayout->up, + 0, xf86Screens[i]->pScreen->width, + 0, xf86Screens[ref]->pScreen->height, ref); + } + if(screen->bottom) { + ref = screen->bottom->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + pScreen = xf86Screens[i]->pScreen; + pLayout->down = AddEdge(pLayout->down, + 0, pScreen->width, 0, -pScreen->height, ref); + } + /* we could also try to place it based on those + relative locations if we wanted to */ + screen->x = screen->y = 0; + /* FALLTHROUGH */ + case PosAbsolute: + dixScreenOrigins[i].x = screen->x; + dixScreenOrigins[i].y = screen->y; + screensLeft &= ~(1 << i); + break; + case PosRelative: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + dixScreenOrigins[i].x = dixScreenOrigins[ref].x + screen->x; + dixScreenOrigins[i].y = dixScreenOrigins[ref].y + screen->y; + screensLeft &= ~(1 << i); + break; + case PosRightOf: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + pScreen = xf86Screens[ref]->pScreen; + dixScreenOrigins[i].x = + dixScreenOrigins[ref].x + pScreen->width; + dixScreenOrigins[i].y = dixScreenOrigins[ref].y; + screensLeft &= ~(1 << i); + break; + case PosLeftOf: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + pScreen = xf86Screens[i]->pScreen; + dixScreenOrigins[i].x = + dixScreenOrigins[ref].x - pScreen->width; + dixScreenOrigins[i].y = dixScreenOrigins[ref].y; + screensLeft &= ~(1 << i); + break; + case PosBelow: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + pScreen = xf86Screens[ref]->pScreen; + dixScreenOrigins[i].x = dixScreenOrigins[ref].x; + dixScreenOrigins[i].y = + dixScreenOrigins[ref].y + pScreen->height; + screensLeft &= ~(1 << i); + break; + case PosAbove: + ref = screen->refscreen->screennum; + if (! xf86Screens[ref] || ! xf86Screens[ref]->pScreen) { + ErrorF("Referenced uninitialized screen in Layout!\n"); + break; + } + if(screensLeft & (1 << ref)) break; + pScreen = xf86Screens[i]->pScreen; + dixScreenOrigins[i].x = dixScreenOrigins[ref].x; + dixScreenOrigins[i].y = + dixScreenOrigins[ref].y - pScreen->height; + screensLeft &= ~(1 << i); + break; + default: + ErrorF("Illegal placement keyword in Layout!\n"); + break; + } + + } + + if(!screensLeft) break; + + if(screensLeft == prevScreensLeft) { + /* All the remaining screens are referencing each other. + Assign a value to one of them and go through again */ + i = 0; + while(!((1 << i) & screensLeft)){ i++; } + + ref = xf86ConfigLayout.screens[i].refscreen->screennum; + dixScreenOrigins[ref].x = dixScreenOrigins[ref].y = 0; + screensLeft &= ~(1 << ref); + } + + prevScreensLeft = screensLeft; + } + + /* justify the topmost and leftmost to (0,0) */ + minX = dixScreenOrigins[0].x; + minY = dixScreenOrigins[0].y; + + for(i = 1; i < xf86NumScreens; i++) { + if(dixScreenOrigins[i].x < minX) + minX = dixScreenOrigins[i].x; + if(dixScreenOrigins[i].y < minY) + minY = dixScreenOrigins[i].y; + } + + if (minX || minY) { + for(i = 0; i < xf86NumScreens; i++) { + dixScreenOrigins[i].x -= minX; + dixScreenOrigins[i].y -= minY; + } + } + + + /* Create the edge lists */ + + if(!OldStyleConfig) { + for(i = 0; i < xf86NumScreens; i++) { + pLayout = &xf86ScreenLayout[i]; + + pScreen = xf86Screens[i]->pScreen; + + left = dixScreenOrigins[i].x; + right = left + pScreen->width; + top = dixScreenOrigins[i].y; + bottom = top + pScreen->height; + + for(j = 0; j < xf86NumScreens; j++) { + if(i == j) continue; + + x1 = dixScreenOrigins[j].x; + x2 = x1 + xf86Screens[j]->pScreen->width; + y1 = dixScreenOrigins[j].y; + y2 = y1 + xf86Screens[j]->pScreen->height; + + if((bottom > y1) && (top < y2)) { + min = y1 - top; + if(min < 0) min = 0; + max = pScreen->height - (bottom - y2); + if(max > pScreen->height) max = pScreen->height; + + if(((left - 1) >= x1) && ((left - 1) < x2)) + pLayout->left = AddEdge(pLayout->left, min, max, + dixScreenOrigins[i].x - dixScreenOrigins[j].x, + dixScreenOrigins[i].y - dixScreenOrigins[j].y, j); + + if((right >= x1) && (right < x2)) + pLayout->right = AddEdge(pLayout->right, min, max, + dixScreenOrigins[i].x - dixScreenOrigins[j].x, + dixScreenOrigins[i].y - dixScreenOrigins[j].y, j); + } + + + if((left < x2) && (right > x1)) { + min = x1 - left; + if(min < 0) min = 0; + max = pScreen->width - (right - x2); + if(max > pScreen->width) max = pScreen->width; + + if(((top - 1) >= y1) && ((top - 1) < y2)) + pLayout->up = AddEdge(pLayout->up, min, max, + dixScreenOrigins[i].x - dixScreenOrigins[j].x, + dixScreenOrigins[i].y - dixScreenOrigins[j].y, j); + + if((bottom >= y1) && (bottom < y2)) + pLayout->down = AddEdge(pLayout->down, min, max, + dixScreenOrigins[i].x - dixScreenOrigins[j].x, + dixScreenOrigins[i].y - dixScreenOrigins[j].y, j); + } + } + } + } + + if(!HardEdges && !OldStyleConfig) { + for(i = 0; i < xf86NumScreens; i++) { + pLayout = &xf86ScreenLayout[i]; + pScreen = xf86Screens[i]->pScreen; + if(pLayout->left) + FillOutEdge(pLayout->left, pScreen->height); + if(pLayout->right) + FillOutEdge(pLayout->right, pScreen->height); + if(pLayout->up) + FillOutEdge(pLayout->up, pScreen->width); + if(pLayout->down) + FillOutEdge(pLayout->down, pScreen->width); + } + } +} + +void +xf86ReconfigureLayout(void) +{ + int i; + + for (i = 0; i < MAXSCREENS; i++) { + xf86ScreenLayoutPtr sl = &xf86ScreenLayout[i]; + /* we don't have to zero these, xf86InitOrigins() takes care of that */ + if (sl->left) free(sl->left); + if (sl->right) free(sl->right); + if (sl->up) free(sl->up); + if (sl->down) free(sl->down); + } + + xf86InitOrigins(); +} + + diff --git a/xorg-server/hw/xfree86/common/xf86DGA.c b/xorg-server/hw/xfree86/common/xf86DGA.c index 794a13171..ac8302169 100644 --- a/xorg-server/hw/xfree86/common/xf86DGA.c +++ b/xorg-server/hw/xfree86/common/xf86DGA.c @@ -1,1227 +1,1227 @@ -/* - * Copyright (c) 1998-2002 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - * - * Written by Mark Vojkovich - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86str.h" -#include "xf86Priv.h" -#include "dgaproc.h" -#include -#include "colormapst.h" -#include "pixmapstr.h" -#include "inputstr.h" -#include "globals.h" -#include "servermd.h" -#include "micmap.h" -#include "xkbsrv.h" -#include "xf86Xinput.h" -#include "exglobals.h" -#include "exevents.h" -#include "eventstr.h" -#include "eventconvert.h" - -#include "mi.h" - -static int DGAScreenKeyIndex; -static DevPrivateKey DGAScreenKey; -static int mieq_installed = 0; - -static Bool DGACloseScreen(int i, ScreenPtr pScreen); -static void DGADestroyColormap(ColormapPtr pmap); -static void DGAInstallColormap(ColormapPtr pmap); -static void DGAUninstallColormap(ColormapPtr pmap); -static void DGAHandleEvent(int screen_num, InternalEvent *event, - DeviceIntPtr device); - -static void -DGACopyModeInfo( - DGAModePtr mode, - XDGAModePtr xmode -); - -int *XDGAEventBase = NULL; - -#define DGA_GET_SCREEN_PRIV(pScreen) ((DGAScreenPtr) \ - dixLookupPrivate(&(pScreen)->devPrivates, DGAScreenKey)) - - -typedef struct _FakedVisualList{ - Bool free; - VisualPtr pVisual; - struct _FakedVisualList *next; -} FakedVisualList; - - -typedef struct { - ScrnInfoPtr pScrn; - int numModes; - DGAModePtr modes; - CloseScreenProcPtr CloseScreen; - DestroyColormapProcPtr DestroyColormap; - InstallColormapProcPtr InstallColormap; - UninstallColormapProcPtr UninstallColormap; - DGADevicePtr current; - DGAFunctionPtr funcs; - int input; - ClientPtr client; - int pixmapMode; - FakedVisualList *fakedVisuals; - ColormapPtr dgaColormap; - ColormapPtr savedColormap; - Bool grabMouse; - Bool grabKeyboard; -} DGAScreenRec, *DGAScreenPtr; - -Bool -DGAInit( - ScreenPtr pScreen, - DGAFunctionPtr funcs, - DGAModePtr modes, - int num -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - DGAScreenPtr pScreenPriv; - int i; - - if(!funcs || !funcs->SetMode || !funcs->OpenFramebuffer) - return FALSE; - - if(!modes || num <= 0) - return FALSE; - - DGAScreenKey = &DGAScreenKeyIndex; - - pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - if (!pScreenPriv) - { - if(!(pScreenPriv = (DGAScreenPtr)xalloc(sizeof(DGAScreenRec)))) - return FALSE; - dixSetPrivate(&pScreen->devPrivates, DGAScreenKey, pScreenPriv); - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = DGACloseScreen; - pScreenPriv->DestroyColormap = pScreen->DestroyColormap; - pScreen->DestroyColormap = DGADestroyColormap; - pScreenPriv->InstallColormap = pScreen->InstallColormap; - pScreen->InstallColormap = DGAInstallColormap; - pScreenPriv->UninstallColormap = pScreen->UninstallColormap; - pScreen->UninstallColormap = DGAUninstallColormap; - } - - pScreenPriv->pScrn = pScrn; - pScreenPriv->numModes = num; - pScreenPriv->modes = modes; - pScreenPriv->current = NULL; - - pScreenPriv->funcs = funcs; - pScreenPriv->input = 0; - pScreenPriv->client = NULL; - pScreenPriv->fakedVisuals = NULL; - pScreenPriv->dgaColormap = NULL; - pScreenPriv->savedColormap = NULL; - pScreenPriv->grabMouse = FALSE; - pScreenPriv->grabKeyboard = FALSE; - - for(i = 0; i < num; i++) - modes[i].num = i + 1; - -#ifdef PANORAMIX - if(!noPanoramiXExtension) - for(i = 0; i < num; i++) - modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; -#endif - - return TRUE; -} - -/* DGAReInitModes allows the driver to re-initialize - * the DGA mode list. - */ - -Bool -DGAReInitModes( - ScreenPtr pScreen, - DGAModePtr modes, - int num -){ - DGAScreenPtr pScreenPriv; - int i; - - /* No DGA? Ignore call (but don't make it look like it failed) */ - if(DGAScreenKey == NULL) - return TRUE; - - pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - /* Same as above */ - if(!pScreenPriv) - return TRUE; - - /* Can't do this while DGA is active */ - if(pScreenPriv->current) - return FALSE; - - /* Quick sanity check */ - if(!num) - modes = NULL; - else if(!modes) - num = 0; - - pScreenPriv->numModes = num; - pScreenPriv->modes = modes; - - /* This practically disables DGA. So be it. */ - if(!num) - return TRUE; - - for(i = 0; i < num; i++) - modes[i].num = i + 1; - -#ifdef PANORAMIX - if(!noPanoramiXExtension) - for(i = 0; i < num; i++) - modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; -#endif - - return TRUE; -} - -static void -FreeMarkedVisuals(ScreenPtr pScreen) -{ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - FakedVisualList *prev, *curr, *tmp; - - if(!pScreenPriv->fakedVisuals) - return; - - prev = NULL; - curr = pScreenPriv->fakedVisuals; - - while(curr) { - if(curr->free) { - tmp = curr; - curr = curr->next; - if(prev) - prev->next = curr; - else - pScreenPriv->fakedVisuals = curr; - xfree(tmp->pVisual); - xfree(tmp); - } else { - prev = curr; - curr = curr->next; - } - } -} - -static Bool -DGACloseScreen(int i, ScreenPtr pScreen) -{ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - if (XDGAEventBase) { - mieqSetHandler(ET_DGAEvent, NULL); - } - - FreeMarkedVisuals(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->DestroyColormap = pScreenPriv->DestroyColormap; - pScreen->InstallColormap = pScreenPriv->InstallColormap; - pScreen->UninstallColormap = pScreenPriv->UninstallColormap; - - /* DGAShutdown() should have ensured that no DGA - screen were active by here */ - - xfree(pScreenPriv); - - return((*pScreen->CloseScreen)(i, pScreen)); -} - - -static void -DGADestroyColormap(ColormapPtr pmap) -{ - ScreenPtr pScreen = pmap->pScreen; - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - VisualPtr pVisual = pmap->pVisual; - - if(pScreenPriv->fakedVisuals) { - FakedVisualList *curr = pScreenPriv->fakedVisuals; - - while(curr) { - if(curr->pVisual == pVisual) { - /* We can't get rid of them yet since FreeColormap - still needs the pVisual during the cleanup */ - curr->free = TRUE; - break; - } - curr = curr->next; - } - } - - if(pScreenPriv->DestroyColormap) { - pScreen->DestroyColormap = pScreenPriv->DestroyColormap; - (*pScreen->DestroyColormap)(pmap); - pScreen->DestroyColormap = DGADestroyColormap; - } -} - - -static void -DGAInstallColormap(ColormapPtr pmap) -{ - ScreenPtr pScreen = pmap->pScreen; - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - if(pScreenPriv->current && pScreenPriv->dgaColormap) { - if (pmap != pScreenPriv->dgaColormap) { - pScreenPriv->savedColormap = pmap; - pmap = pScreenPriv->dgaColormap; - } - } - - pScreen->InstallColormap = pScreenPriv->InstallColormap; - (*pScreen->InstallColormap)(pmap); - pScreen->InstallColormap = DGAInstallColormap; -} - -static void -DGAUninstallColormap(ColormapPtr pmap) -{ - ScreenPtr pScreen = pmap->pScreen; - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - if(pScreenPriv->current && pScreenPriv->dgaColormap) { - if (pmap == pScreenPriv->dgaColormap) { - pScreenPriv->dgaColormap = NULL; - } - } - - pScreen->UninstallColormap = pScreenPriv->UninstallColormap; - (*pScreen->UninstallColormap)(pmap); - pScreen->UninstallColormap = DGAUninstallColormap; -} - -int -xf86SetDGAMode( - int index, - int num, - DGADevicePtr devRet -){ - ScreenPtr pScreen = screenInfo.screens[index]; - DGAScreenPtr pScreenPriv; - ScrnInfoPtr pScrn; - DGADevicePtr device; - PixmapPtr pPix = NULL; - DGAModePtr pMode = NULL; - - /* First check if DGAInit was successful on this screen */ - if (DGAScreenKey == NULL) - return BadValue; - pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - if (!pScreenPriv) - return BadValue; - pScrn = pScreenPriv->pScrn; - - if(!num) { - if(pScreenPriv->current) { - PixmapPtr oldPix = pScreenPriv->current->pPix; - if(oldPix) { - if(oldPix->drawable.id) - FreeResource(oldPix->drawable.id, RT_NONE); - else - (*pScreen->DestroyPixmap)(oldPix); - } - xfree(pScreenPriv->current); - pScreenPriv->current = NULL; - pScrn->vtSema = TRUE; - (*pScreenPriv->funcs->SetMode)(pScrn, NULL); - if(pScreenPriv->savedColormap) { - (*pScreen->InstallColormap)(pScreenPriv->savedColormap); - pScreenPriv->savedColormap = NULL; - } - pScreenPriv->dgaColormap = NULL; - (*pScrn->EnableDisableFBAccess)(index, TRUE); - - FreeMarkedVisuals(pScreen); - } - - pScreenPriv->grabMouse = FALSE; - pScreenPriv->grabKeyboard = FALSE; - - return Success; - } - - if(!pScrn->vtSema && !pScreenPriv->current) /* Really switched away */ - return BadAlloc; - - if((num > 0) && (num <= pScreenPriv->numModes)) - pMode = &(pScreenPriv->modes[num - 1]); - else - return BadValue; - - if(!(device = (DGADevicePtr)xalloc(sizeof(DGADeviceRec)))) - return BadAlloc; - - if(!pScreenPriv->current) { - Bool oldVTSema = pScrn->vtSema; - - pScrn->vtSema = FALSE; /* kludge until we rewrite VT switching */ - (*pScrn->EnableDisableFBAccess)(index, FALSE); - pScrn->vtSema = oldVTSema; - } - - if(!(*pScreenPriv->funcs->SetMode)(pScrn, pMode)) { - xfree(device); - return BadAlloc; - } - - pScrn->currentMode = pMode->mode; - - if(!pScreenPriv->current && !pScreenPriv->input) { - /* if it's multihead we need to warp the cursor off of - our screen so it doesn't get trapped */ - } - - pScrn->vtSema = FALSE; - - if(pScreenPriv->current) { - PixmapPtr oldPix = pScreenPriv->current->pPix; - if(oldPix) { - if(oldPix->drawable.id) - FreeResource(oldPix->drawable.id, RT_NONE); - else - (*pScreen->DestroyPixmap)(oldPix); - } - xfree(pScreenPriv->current); - pScreenPriv->current = NULL; - } - - if(pMode->flags & DGA_PIXMAP_AVAILABLE) { - if((pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pMode->depth, 0))) { - (*pScreen->ModifyPixmapHeader)(pPix, - pMode->pixmapWidth, pMode->pixmapHeight, - pMode->depth, pMode->bitsPerPixel, - pMode->bytesPerScanline, - (pointer)(pMode->address)); - } - } - - devRet->mode = device->mode = pMode; - devRet->pPix = device->pPix = pPix; - pScreenPriv->current = device; - pScreenPriv->pixmapMode = FALSE; - pScreenPriv->grabMouse = TRUE; - pScreenPriv->grabKeyboard = TRUE; - - return Success; -} - - - -/*********** exported ones ***************/ - -void -DGASetInputMode(int index, Bool keyboard, Bool mouse) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - if (pScreenPriv) - { - pScreenPriv->grabMouse = mouse; - pScreenPriv->grabKeyboard = keyboard; - - if (!mieq_installed) { - mieqSetHandler(ET_DGAEvent, DGAHandleEvent); - mieq_installed = 1; - } - } -} - -Bool -DGAChangePixmapMode(int index, int *x, int *y, int mode) -{ - DGAScreenPtr pScreenPriv; - DGADevicePtr pDev; - DGAModePtr pMode; - PixmapPtr pPix; - - if(DGAScreenKey == NULL) - return FALSE; - - pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - if(!pScreenPriv || !pScreenPriv->current || !pScreenPriv->current->pPix) - return FALSE; - - pDev = pScreenPriv->current; - pPix = pDev->pPix; - pMode = pDev->mode; - - if(mode) { - int shift = 2; - - if(*x > (pMode->pixmapWidth - pMode->viewportWidth)) - *x = pMode->pixmapWidth - pMode->viewportWidth; - if(*y > (pMode->pixmapHeight - pMode->viewportHeight)) - *y = pMode->pixmapHeight - pMode->viewportHeight; - - switch(xf86Screens[index]->bitsPerPixel) { - case 16: shift = 1; break; - case 32: shift = 0; break; - default: break; - } - - if(BITMAP_SCANLINE_PAD == 64) - shift++; - - *x = (*x >> shift) << shift; - - pPix->drawable.x = *x; - pPix->drawable.y = *y; - pPix->drawable.width = pMode->viewportWidth; - pPix->drawable.height = pMode->viewportHeight; - } else { - pPix->drawable.x = 0; - pPix->drawable.y = 0; - pPix->drawable.width = pMode->pixmapWidth; - pPix->drawable.height = pMode->pixmapHeight; - } - pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; - pScreenPriv->pixmapMode = mode; - - return TRUE; -} - -Bool -DGAAvailable(int index) -{ - if(DGAScreenKey == NULL) - return FALSE; - - if(DGA_GET_SCREEN_PRIV(screenInfo.screens[index])) - return TRUE; - - return FALSE; -} - -Bool -DGAActive(int index) -{ - DGAScreenPtr pScreenPriv; - - if(DGAScreenKey == NULL) - return FALSE; - - pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - if(pScreenPriv && pScreenPriv->current) - return TRUE; - - return FALSE; -} - - - -/* Called by the event code in case the server is abruptly terminated */ - -void -DGAShutdown(void) -{ - ScrnInfoPtr pScrn; - int i; - - if(DGAScreenKey == NULL) - return; - - for(i = 0; i < screenInfo.numScreens; i++) { - pScrn = xf86Screens[i]; - - (void)(*pScrn->SetDGAMode)(pScrn->scrnIndex, 0, NULL); - } -} - -/* Called by the extension to initialize a mode */ - -int -DGASetMode( - int index, - int num, - XDGAModePtr mode, - PixmapPtr *pPix -){ - ScrnInfoPtr pScrn = xf86Screens[index]; - DGADeviceRec device; - int ret; - - /* We rely on the extension to check that DGA is available */ - - ret = (*pScrn->SetDGAMode)(index, num, &device); - if((ret == Success) && num) { - DGACopyModeInfo(device.mode, mode); - *pPix = device.pPix; - } - - return ret; -} - -/* Called from the extension to let the DDX know which events are requested */ - -void -DGASelectInput( - int index, - ClientPtr client, - long mask -){ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - /* We rely on the extension to check that DGA is available */ - pScreenPriv->client = client; - pScreenPriv->input = mask; -} - -int -DGAGetViewportStatus(int index) -{ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - /* We rely on the extension to check that DGA is active */ - - if (!pScreenPriv->funcs->GetViewport) - return 0; - - return (*pScreenPriv->funcs->GetViewport)(pScreenPriv->pScrn); -} - -int -DGASetViewport( - int index, - int x, int y, - int mode -){ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - if (pScreenPriv->funcs->SetViewport) - (*pScreenPriv->funcs->SetViewport)(pScreenPriv->pScrn, x, y, mode); - return Success; -} - - -static int -BitsClear(CARD32 data) -{ - int bits = 0; - CARD32 mask; - - for(mask = 1; mask; mask <<= 1) { - if(!(data & mask)) bits++; - else break; - } - - return bits; -} - -int -DGACreateColormap(int index, ClientPtr client, int id, int mode, int alloc) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - FakedVisualList *fvlp; - VisualPtr pVisual; - DGAModePtr pMode; - ColormapPtr pmap; - - if(!mode || (mode > pScreenPriv->numModes)) - return BadValue; - - if((alloc != AllocNone) && (alloc != AllocAll)) - return BadValue; - - pMode = &(pScreenPriv->modes[mode - 1]); - - if(!(pVisual = xalloc(sizeof(VisualRec)))) - return BadAlloc; - - pVisual->vid = FakeClientID(0); - pVisual->class = pMode->visualClass; - pVisual->nplanes = pMode->depth; - pVisual->ColormapEntries = 1 << pMode->depth; - pVisual->bitsPerRGBValue = (pMode->depth + 2) / 3; - - switch (pVisual->class) { - case PseudoColor: - case GrayScale: - case StaticGray: - pVisual->bitsPerRGBValue = 8; /* not quite */ - pVisual->redMask = 0; - pVisual->greenMask = 0; - pVisual->blueMask = 0; - pVisual->offsetRed = 0; - pVisual->offsetGreen = 0; - pVisual->offsetBlue = 0; - break; - case DirectColor: - case TrueColor: - pVisual->ColormapEntries = 1 << pVisual->bitsPerRGBValue; - /* fall through */ - case StaticColor: - pVisual->redMask = pMode->red_mask; - pVisual->greenMask = pMode->green_mask; - pVisual->blueMask = pMode->blue_mask; - pVisual->offsetRed = BitsClear(pVisual->redMask); - pVisual->offsetGreen = BitsClear(pVisual->greenMask); - pVisual->offsetBlue = BitsClear(pVisual->blueMask); - } - - if(!(fvlp = xalloc(sizeof(FakedVisualList)))) { - xfree(pVisual); - return BadAlloc; - } - - fvlp->free = FALSE; - fvlp->pVisual = pVisual; - fvlp->next = pScreenPriv->fakedVisuals; - pScreenPriv->fakedVisuals = fvlp; - - LEGAL_NEW_RESOURCE(id, client); - - return CreateColormap(id, pScreen, pVisual, &pmap, alloc, client->index); -} - -/* Called by the extension to install a colormap on DGA active screens */ - -void -DGAInstallCmap(ColormapPtr cmap) -{ - ScreenPtr pScreen = cmap->pScreen; - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - /* We rely on the extension to check that DGA is active */ - - if(!pScreenPriv->dgaColormap) - pScreenPriv->savedColormap = GetInstalledmiColormap(pScreen); - - pScreenPriv->dgaColormap = cmap; - - (*pScreen->InstallColormap)(cmap); -} - -int -DGASync(int index) -{ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - /* We rely on the extension to check that DGA is active */ - - if (pScreenPriv->funcs->Sync) - (*pScreenPriv->funcs->Sync)(pScreenPriv->pScrn); - - return Success; -} - -int -DGAFillRect( - int index, - int x, int y, int w, int h, - unsigned long color -){ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - /* We rely on the extension to check that DGA is active */ - - if(pScreenPriv->funcs->FillRect && - (pScreenPriv->current->mode->flags & DGA_FILL_RECT)) { - - (*pScreenPriv->funcs->FillRect)(pScreenPriv->pScrn, x, y, w, h, color); - return Success; - } - return BadMatch; -} - -int -DGABlitRect( - int index, - int srcx, int srcy, - int w, int h, - int dstx, int dsty -){ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - /* We rely on the extension to check that DGA is active */ - - if(pScreenPriv->funcs->BlitRect && - (pScreenPriv->current->mode->flags & DGA_BLIT_RECT)) { - - (*pScreenPriv->funcs->BlitRect)(pScreenPriv->pScrn, - srcx, srcy, w, h, dstx, dsty); - return Success; - } - return BadMatch; -} - -int -DGABlitTransRect( - int index, - int srcx, int srcy, - int w, int h, - int dstx, int dsty, - unsigned long color -){ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - /* We rely on the extension to check that DGA is active */ - - if(pScreenPriv->funcs->BlitTransRect && - (pScreenPriv->current->mode->flags & DGA_BLIT_RECT_TRANS)) { - - (*pScreenPriv->funcs->BlitTransRect)(pScreenPriv->pScrn, - srcx, srcy, w, h, dstx, dsty, color); - return Success; - } - return BadMatch; -} - - -int -DGAGetModes(int index) -{ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - /* We rely on the extension to check that DGA is available */ - - return pScreenPriv->numModes; -} - - -int -DGAGetModeInfo( - int index, - XDGAModePtr mode, - int num -){ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - /* We rely on the extension to check that DGA is available */ - - if((num <= 0) || (num > pScreenPriv->numModes)) - return BadValue; - - DGACopyModeInfo(&(pScreenPriv->modes[num - 1]), mode); - - return Success; -} - - -static void -DGACopyModeInfo( - DGAModePtr mode, - XDGAModePtr xmode -){ - DisplayModePtr dmode = mode->mode; - - xmode->num = mode->num; - xmode->name = dmode->name; - xmode->VSync_num = (int)(dmode->VRefresh * 1000.0); - xmode->VSync_den = 1000; - xmode->flags = mode->flags; - xmode->imageWidth = mode->imageWidth; - xmode->imageHeight = mode->imageHeight; - xmode->pixmapWidth = mode->pixmapWidth; - xmode->pixmapHeight = mode->pixmapHeight; - xmode->bytesPerScanline = mode->bytesPerScanline; - xmode->byteOrder = mode->byteOrder; - xmode->depth = mode->depth; - xmode->bitsPerPixel = mode->bitsPerPixel; - xmode->red_mask = mode->red_mask; - xmode->green_mask = mode->green_mask; - xmode->blue_mask = mode->blue_mask; - xmode->visualClass = mode->visualClass; - xmode->viewportWidth = mode->viewportWidth; - xmode->viewportHeight = mode->viewportHeight; - xmode->xViewportStep = mode->xViewportStep; - xmode->yViewportStep = mode->yViewportStep; - xmode->maxViewportX = mode->maxViewportX; - xmode->maxViewportY = mode->maxViewportY; - xmode->viewportFlags = mode->viewportFlags; - xmode->reserved1 = mode->reserved1; - xmode->reserved2 = mode->reserved2; - xmode->offset = mode->offset; - - if(dmode->Flags & V_INTERLACE) xmode->flags |= DGA_INTERLACED; - if(dmode->Flags & V_DBLSCAN) xmode->flags |= DGA_DOUBLESCAN; -} - - -Bool -DGAVTSwitch(void) -{ - ScreenPtr pScreen; - int i; - - for(i = 0; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - - /* Alternatively, this could send events to DGA clients */ - - if(DGAScreenKey) { - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - if(pScreenPriv && pScreenPriv->current) - return FALSE; - } - } - - return TRUE; -} - -Bool -DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down) -{ - DGAScreenPtr pScreenPriv; - DGAEvent event; - - if(DGAScreenKey == NULL) /* no DGA */ - return FALSE; - - if (key_code < 8 || key_code > 255) - return FALSE; - - pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - if(!pScreenPriv || !pScreenPriv->grabKeyboard) /* no direct mode */ - return FALSE; - - memset(&event, 0, sizeof(event)); - event.header = ET_Internal; - event.type = ET_DGAEvent; - event.length = sizeof(event); - event.time = GetTimeInMillis(); - event.subtype = (is_down ? ET_KeyPress : ET_KeyRelease); - event.detail = key_code; - event.dx = 0; - event.dy = 0; - mieqEnqueue (dev, (InternalEvent*)&event); - - return TRUE; -} - -static int DGAMouseX, DGAMouseY; - -Bool -DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy) -{ - DGAScreenPtr pScreenPriv; - DGAEvent event; - - if(DGAScreenKey == NULL) /* no DGA */ - return FALSE; - - pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - if(!pScreenPriv || !pScreenPriv->grabMouse) /* no direct mode */ - return FALSE; - - DGAMouseX += dx; - if (DGAMouseX < 0) - DGAMouseX = 0; - else if (DGAMouseX > screenInfo.screens[index]->width) - DGAMouseX = screenInfo.screens[index]->width; - DGAMouseY += dy; - if (DGAMouseY < 0) - DGAMouseY = 0; - else if (DGAMouseY > screenInfo.screens[index]->height) - DGAMouseY = screenInfo.screens[index]->height; - - memset(&event, 0, sizeof(event)); - event.header = ET_Internal; - event.type = ET_DGAEvent; - event.length = sizeof(event); - event.time = GetTimeInMillis(); - event.subtype = ET_Motion; - event.detail = 0; - event.dx = dx; - event.dy = dy; - mieqEnqueue (dev, (InternalEvent*)&event); - return TRUE; -} - -Bool -DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down) -{ - DGAScreenPtr pScreenPriv; - DGAEvent event; - - if (DGAScreenKey == NULL) - return FALSE; - - pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - if (!pScreenPriv || !pScreenPriv->grabMouse) - return FALSE; - - memset(&event, 0, sizeof(event)); - event.header = ET_Internal; - event.type = ET_DGAEvent; - event.length = sizeof(event); - event.time = GetTimeInMillis(); - event.subtype = (is_down ? ET_ButtonPress : ET_ButtonRelease); - event.detail = button; - event.dx = 0; - event.dy = 0; - mieqEnqueue (dev, (InternalEvent*)&event); - - return TRUE; -} - -/* We have the power to steal or modify events that are about to get queued */ - -Bool -DGAIsDgaEvent (xEvent *e) -{ - int coreEquiv; - if (DGAScreenKey == NULL || XDGAEventBase == 0) - return FALSE; - coreEquiv = e->u.u.type - *XDGAEventBase; - if (KeyPress <= coreEquiv && coreEquiv <= MotionNotify) - return TRUE; - return FALSE; -} - -#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ -static Mask filters[] = -{ - NoSuchEvent, /* 0 */ - NoSuchEvent, /* 1 */ - KeyPressMask, /* KeyPress */ - KeyReleaseMask, /* KeyRelease */ - ButtonPressMask, /* ButtonPress */ - ButtonReleaseMask, /* ButtonRelease */ - PointerMotionMask, /* MotionNotify (initial state) */ -}; - -static void -DGAProcessKeyboardEvent (ScreenPtr pScreen, DGAEvent *event, DeviceIntPtr keybd) -{ - KeyClassPtr keyc = keybd->key; - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - DeviceIntPtr pointer = GetPairedDevice(keybd); - DeviceEvent ev; - - memset(&ev, 0, sizeof(ev)); - ev.length = sizeof(ev); - ev.detail.key = event->detail; - ev.type = event->subtype; - ev.root_x = 0; - ev.root_y = 0; - ev.corestate = XkbStateFieldFromRec(&keyc->xkbInfo->state); - ev.corestate |= pointer->button->state; - - UpdateDeviceState(keybd, &ev); - - /* - * Deliver the DGA event - */ - if (pScreenPriv->client) - { - dgaEvent de; - de.u.u.type = *XDGAEventBase + GetCoreType((InternalEvent*)&ev); - de.u.u.detail = event->detail; - de.u.event.time = event->time; - de.u.event.dx = 0; - de.u.event.dy = 0; - de.u.event.screen = pScreen->myNum; - de.u.event.state = ev.corestate; - - /* If the DGA client has selected input, then deliver based on the usual filter */ - TryClientEvents (pScreenPriv->client, keybd, (xEvent *)&de, 1, - filters[ev.type], pScreenPriv->input, 0); - } - else - { - /* If the keyboard is actively grabbed, deliver a grabbed core event */ - if (keybd->deviceGrab.grab && !keybd->deviceGrab.fromPassiveGrab) - { - ev.detail.key = event->detail; - ev.time = event->time; - ev.root_x = event->dx; - ev.root_y = event->dy; - ev.corestate = event->state; - ev.deviceid = keybd->id; - DeliverGrabbedEvent ((InternalEvent*)&ev, keybd, FALSE); - } - } -} - -static void -DGAProcessPointerEvent (ScreenPtr pScreen, DGAEvent *event, DeviceIntPtr mouse) -{ - ButtonClassPtr butc = mouse->button; - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - DeviceEvent ev; - DeviceIntPtr master = GetMaster(mouse, MASTER_KEYBOARD); - - memset(&ev, 0, sizeof(ev)); - ev.header = ET_Internal; - ev.length = sizeof(ev); - ev.type = event->subtype; - ev.corestate = butc->state; - if (master && master->key) - ev.corestate |= XkbStateFieldFromRec(&master->key->xkbInfo->state); - - UpdateDeviceState(mouse, &ev); - - /* - * Deliver the DGA event - */ - if (pScreenPriv->client) - { - dgaEvent de; - int coreEquiv; - - coreEquiv = GetCoreType((InternalEvent*)&ev); - - de.u.u.type = *XDGAEventBase + coreEquiv; - de.u.u.detail = event->detail; - de.u.event.time = event->time; - de.u.event.dx = 0; - de.u.event.dy = 0; - de.u.event.screen = pScreen->myNum; - de.u.event.state = ev.corestate; - - /* If the DGA client has selected input, then deliver based on the usual filter */ - TryClientEvents (pScreenPriv->client, mouse, (xEvent *)&de, 1, - filters[coreEquiv], pScreenPriv->input, 0); - } - else - { - /* If the pointer is actively grabbed, deliver a grabbed core event */ - if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab) - { - ev.detail.button = event->detail; - ev.time = event->time; - ev.root_x = event->dx; - ev.root_y = event->dy; - ev.corestate = event->state; - DeliverGrabbedEvent ((InternalEvent*)&ev, mouse, FALSE); - } - } -} - -Bool -DGAOpenFramebuffer( - int index, - char **name, - unsigned char **mem, - int *size, - int *offset, - int *flags -){ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - /* We rely on the extension to check that DGA is available */ - - return (*pScreenPriv->funcs->OpenFramebuffer)(pScreenPriv->pScrn, - name, mem, size, offset, flags); -} - -void -DGACloseFramebuffer(int index) -{ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - - /* We rely on the extension to check that DGA is available */ - if(pScreenPriv->funcs->CloseFramebuffer) - (*pScreenPriv->funcs->CloseFramebuffer)(pScreenPriv->pScrn); -} - -/* For DGA 1.0 backwards compatibility only */ - -int -DGAGetOldDGAMode(int index) -{ - DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); - ScrnInfoPtr pScrn = pScreenPriv->pScrn; - DGAModePtr mode; - int i, w, h, p; - - /* We rely on the extension to check that DGA is available */ - - w = pScrn->currentMode->HDisplay; - h = pScrn->currentMode->VDisplay; - p = pad_to_int32(pScrn->displayWidth * bits_to_bytes(pScrn->bitsPerPixel)); - - for(i = 0; i < pScreenPriv->numModes; i++) { - mode = &(pScreenPriv->modes[i]); - - if((mode->viewportWidth == w) && (mode->viewportHeight == h) && - (mode->bytesPerScanline == p) && - (mode->bitsPerPixel == pScrn->bitsPerPixel) && - (mode->depth == pScrn->depth)) { - - return mode->num; - } - } - - return 0; -} - -static void -DGAHandleEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) -{ - DGAEvent *event= &ev->dga_event; - ScreenPtr pScreen = screenInfo.screens[screen_num]; - DGAScreenPtr pScreenPriv; - - /* no DGA */ - if (DGAScreenKey == NULL || XDGAEventBase == 0) - return; - pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); - - /* DGA not initialized on this screen */ - if (!pScreenPriv) - return; - - switch (event->subtype) { - case KeyPress: - case KeyRelease: - DGAProcessKeyboardEvent (pScreen, event, device); - break; - case MotionNotify: - case ButtonPress: - case ButtonRelease: - DGAProcessPointerEvent (pScreen, event, device); - break; - default: - break; - } -} +/* + * Copyright (c) 1998-2002 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + * + * Written by Mark Vojkovich + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86str.h" +#include "xf86Priv.h" +#include "dgaproc.h" +#include +#include "colormapst.h" +#include "pixmapstr.h" +#include "inputstr.h" +#include "globals.h" +#include "servermd.h" +#include "micmap.h" +#include "xkbsrv.h" +#include "xf86Xinput.h" +#include "exglobals.h" +#include "exevents.h" +#include "eventstr.h" +#include "eventconvert.h" + +#include "mi.h" + +static int DGAScreenKeyIndex; +static DevPrivateKey DGAScreenKey; +static int mieq_installed = 0; + +static Bool DGACloseScreen(int i, ScreenPtr pScreen); +static void DGADestroyColormap(ColormapPtr pmap); +static void DGAInstallColormap(ColormapPtr pmap); +static void DGAUninstallColormap(ColormapPtr pmap); +static void DGAHandleEvent(int screen_num, InternalEvent *event, + DeviceIntPtr device); + +static void +DGACopyModeInfo( + DGAModePtr mode, + XDGAModePtr xmode +); + +int *XDGAEventBase = NULL; + +#define DGA_GET_SCREEN_PRIV(pScreen) ((DGAScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, DGAScreenKey)) + + +typedef struct _FakedVisualList{ + Bool free; + VisualPtr pVisual; + struct _FakedVisualList *next; +} FakedVisualList; + + +typedef struct { + ScrnInfoPtr pScrn; + int numModes; + DGAModePtr modes; + CloseScreenProcPtr CloseScreen; + DestroyColormapProcPtr DestroyColormap; + InstallColormapProcPtr InstallColormap; + UninstallColormapProcPtr UninstallColormap; + DGADevicePtr current; + DGAFunctionPtr funcs; + int input; + ClientPtr client; + int pixmapMode; + FakedVisualList *fakedVisuals; + ColormapPtr dgaColormap; + ColormapPtr savedColormap; + Bool grabMouse; + Bool grabKeyboard; +} DGAScreenRec, *DGAScreenPtr; + +Bool +DGAInit( + ScreenPtr pScreen, + DGAFunctionPtr funcs, + DGAModePtr modes, + int num +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DGAScreenPtr pScreenPriv; + int i; + + if(!funcs || !funcs->SetMode || !funcs->OpenFramebuffer) + return FALSE; + + if(!modes || num <= 0) + return FALSE; + + DGAScreenKey = &DGAScreenKeyIndex; + + pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if (!pScreenPriv) + { + if(!(pScreenPriv = (DGAScreenPtr)malloc(sizeof(DGAScreenRec)))) + return FALSE; + dixSetPrivate(&pScreen->devPrivates, DGAScreenKey, pScreenPriv); + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = DGACloseScreen; + pScreenPriv->DestroyColormap = pScreen->DestroyColormap; + pScreen->DestroyColormap = DGADestroyColormap; + pScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreen->InstallColormap = DGAInstallColormap; + pScreenPriv->UninstallColormap = pScreen->UninstallColormap; + pScreen->UninstallColormap = DGAUninstallColormap; + } + + pScreenPriv->pScrn = pScrn; + pScreenPriv->numModes = num; + pScreenPriv->modes = modes; + pScreenPriv->current = NULL; + + pScreenPriv->funcs = funcs; + pScreenPriv->input = 0; + pScreenPriv->client = NULL; + pScreenPriv->fakedVisuals = NULL; + pScreenPriv->dgaColormap = NULL; + pScreenPriv->savedColormap = NULL; + pScreenPriv->grabMouse = FALSE; + pScreenPriv->grabKeyboard = FALSE; + + for(i = 0; i < num; i++) + modes[i].num = i + 1; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + for(i = 0; i < num; i++) + modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; +#endif + + return TRUE; +} + +/* DGAReInitModes allows the driver to re-initialize + * the DGA mode list. + */ + +Bool +DGAReInitModes( + ScreenPtr pScreen, + DGAModePtr modes, + int num +){ + DGAScreenPtr pScreenPriv; + int i; + + /* No DGA? Ignore call (but don't make it look like it failed) */ + if(DGAScreenKey == NULL) + return TRUE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + /* Same as above */ + if(!pScreenPriv) + return TRUE; + + /* Can't do this while DGA is active */ + if(pScreenPriv->current) + return FALSE; + + /* Quick sanity check */ + if(!num) + modes = NULL; + else if(!modes) + num = 0; + + pScreenPriv->numModes = num; + pScreenPriv->modes = modes; + + /* This practically disables DGA. So be it. */ + if(!num) + return TRUE; + + for(i = 0; i < num; i++) + modes[i].num = i + 1; + +#ifdef PANORAMIX + if(!noPanoramiXExtension) + for(i = 0; i < num; i++) + modes[i].flags &= ~DGA_PIXMAP_AVAILABLE; +#endif + + return TRUE; +} + +static void +FreeMarkedVisuals(ScreenPtr pScreen) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + FakedVisualList *prev, *curr, *tmp; + + if(!pScreenPriv->fakedVisuals) + return; + + prev = NULL; + curr = pScreenPriv->fakedVisuals; + + while(curr) { + if(curr->free) { + tmp = curr; + curr = curr->next; + if(prev) + prev->next = curr; + else + pScreenPriv->fakedVisuals = curr; + free(tmp->pVisual); + free(tmp); + } else { + prev = curr; + curr = curr->next; + } + } +} + +static Bool +DGACloseScreen(int i, ScreenPtr pScreen) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if (XDGAEventBase) { + mieqSetHandler(ET_DGAEvent, NULL); + } + + FreeMarkedVisuals(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->DestroyColormap = pScreenPriv->DestroyColormap; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->UninstallColormap = pScreenPriv->UninstallColormap; + + /* DGAShutdown() should have ensured that no DGA + screen were active by here */ + + free(pScreenPriv); + + return((*pScreen->CloseScreen)(i, pScreen)); +} + + +static void +DGADestroyColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + VisualPtr pVisual = pmap->pVisual; + + if(pScreenPriv->fakedVisuals) { + FakedVisualList *curr = pScreenPriv->fakedVisuals; + + while(curr) { + if(curr->pVisual == pVisual) { + /* We can't get rid of them yet since FreeColormap + still needs the pVisual during the cleanup */ + curr->free = TRUE; + break; + } + curr = curr->next; + } + } + + if(pScreenPriv->DestroyColormap) { + pScreen->DestroyColormap = pScreenPriv->DestroyColormap; + (*pScreen->DestroyColormap)(pmap); + pScreen->DestroyColormap = DGADestroyColormap; + } +} + + +static void +DGAInstallColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if(pScreenPriv->current && pScreenPriv->dgaColormap) { + if (pmap != pScreenPriv->dgaColormap) { + pScreenPriv->savedColormap = pmap; + pmap = pScreenPriv->dgaColormap; + } + } + + pScreen->InstallColormap = pScreenPriv->InstallColormap; + (*pScreen->InstallColormap)(pmap); + pScreen->InstallColormap = DGAInstallColormap; +} + +static void +DGAUninstallColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if(pScreenPriv->current && pScreenPriv->dgaColormap) { + if (pmap == pScreenPriv->dgaColormap) { + pScreenPriv->dgaColormap = NULL; + } + } + + pScreen->UninstallColormap = pScreenPriv->UninstallColormap; + (*pScreen->UninstallColormap)(pmap); + pScreen->UninstallColormap = DGAUninstallColormap; +} + +int +xf86SetDGAMode( + int index, + int num, + DGADevicePtr devRet +){ + ScreenPtr pScreen = screenInfo.screens[index]; + DGAScreenPtr pScreenPriv; + ScrnInfoPtr pScrn; + DGADevicePtr device; + PixmapPtr pPix = NULL; + DGAModePtr pMode = NULL; + + /* First check if DGAInit was successful on this screen */ + if (DGAScreenKey == NULL) + return BadValue; + pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + if (!pScreenPriv) + return BadValue; + pScrn = pScreenPriv->pScrn; + + if(!num) { + if(pScreenPriv->current) { + PixmapPtr oldPix = pScreenPriv->current->pPix; + if(oldPix) { + if(oldPix->drawable.id) + FreeResource(oldPix->drawable.id, RT_NONE); + else + (*pScreen->DestroyPixmap)(oldPix); + } + free(pScreenPriv->current); + pScreenPriv->current = NULL; + pScrn->vtSema = TRUE; + (*pScreenPriv->funcs->SetMode)(pScrn, NULL); + if(pScreenPriv->savedColormap) { + (*pScreen->InstallColormap)(pScreenPriv->savedColormap); + pScreenPriv->savedColormap = NULL; + } + pScreenPriv->dgaColormap = NULL; + (*pScrn->EnableDisableFBAccess)(index, TRUE); + + FreeMarkedVisuals(pScreen); + } + + pScreenPriv->grabMouse = FALSE; + pScreenPriv->grabKeyboard = FALSE; + + return Success; + } + + if(!pScrn->vtSema && !pScreenPriv->current) /* Really switched away */ + return BadAlloc; + + if((num > 0) && (num <= pScreenPriv->numModes)) + pMode = &(pScreenPriv->modes[num - 1]); + else + return BadValue; + + if(!(device = (DGADevicePtr)malloc(sizeof(DGADeviceRec)))) + return BadAlloc; + + if(!pScreenPriv->current) { + Bool oldVTSema = pScrn->vtSema; + + pScrn->vtSema = FALSE; /* kludge until we rewrite VT switching */ + (*pScrn->EnableDisableFBAccess)(index, FALSE); + pScrn->vtSema = oldVTSema; + } + + if(!(*pScreenPriv->funcs->SetMode)(pScrn, pMode)) { + free(device); + return BadAlloc; + } + + pScrn->currentMode = pMode->mode; + + if(!pScreenPriv->current && !pScreenPriv->input) { + /* if it's multihead we need to warp the cursor off of + our screen so it doesn't get trapped */ + } + + pScrn->vtSema = FALSE; + + if(pScreenPriv->current) { + PixmapPtr oldPix = pScreenPriv->current->pPix; + if(oldPix) { + if(oldPix->drawable.id) + FreeResource(oldPix->drawable.id, RT_NONE); + else + (*pScreen->DestroyPixmap)(oldPix); + } + free(pScreenPriv->current); + pScreenPriv->current = NULL; + } + + if(pMode->flags & DGA_PIXMAP_AVAILABLE) { + if((pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pMode->depth, 0))) { + (*pScreen->ModifyPixmapHeader)(pPix, + pMode->pixmapWidth, pMode->pixmapHeight, + pMode->depth, pMode->bitsPerPixel, + pMode->bytesPerScanline, + (pointer)(pMode->address)); + } + } + + devRet->mode = device->mode = pMode; + devRet->pPix = device->pPix = pPix; + pScreenPriv->current = device; + pScreenPriv->pixmapMode = FALSE; + pScreenPriv->grabMouse = TRUE; + pScreenPriv->grabKeyboard = TRUE; + + return Success; +} + + + +/*********** exported ones ***************/ + +void +DGASetInputMode(int index, Bool keyboard, Bool mouse) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if (pScreenPriv) + { + pScreenPriv->grabMouse = mouse; + pScreenPriv->grabKeyboard = keyboard; + + if (!mieq_installed) { + mieqSetHandler(ET_DGAEvent, DGAHandleEvent); + mieq_installed = 1; + } + } +} + +Bool +DGAChangePixmapMode(int index, int *x, int *y, int mode) +{ + DGAScreenPtr pScreenPriv; + DGADevicePtr pDev; + DGAModePtr pMode; + PixmapPtr pPix; + + if(DGAScreenKey == NULL) + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if(!pScreenPriv || !pScreenPriv->current || !pScreenPriv->current->pPix) + return FALSE; + + pDev = pScreenPriv->current; + pPix = pDev->pPix; + pMode = pDev->mode; + + if(mode) { + int shift = 2; + + if(*x > (pMode->pixmapWidth - pMode->viewportWidth)) + *x = pMode->pixmapWidth - pMode->viewportWidth; + if(*y > (pMode->pixmapHeight - pMode->viewportHeight)) + *y = pMode->pixmapHeight - pMode->viewportHeight; + + switch(xf86Screens[index]->bitsPerPixel) { + case 16: shift = 1; break; + case 32: shift = 0; break; + default: break; + } + + if(BITMAP_SCANLINE_PAD == 64) + shift++; + + *x = (*x >> shift) << shift; + + pPix->drawable.x = *x; + pPix->drawable.y = *y; + pPix->drawable.width = pMode->viewportWidth; + pPix->drawable.height = pMode->viewportHeight; + } else { + pPix->drawable.x = 0; + pPix->drawable.y = 0; + pPix->drawable.width = pMode->pixmapWidth; + pPix->drawable.height = pMode->pixmapHeight; + } + pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pScreenPriv->pixmapMode = mode; + + return TRUE; +} + +Bool +DGAAvailable(int index) +{ + if(DGAScreenKey == NULL) + return FALSE; + + if(DGA_GET_SCREEN_PRIV(screenInfo.screens[index])) + return TRUE; + + return FALSE; +} + +Bool +DGAActive(int index) +{ + DGAScreenPtr pScreenPriv; + + if(DGAScreenKey == NULL) + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if(pScreenPriv && pScreenPriv->current) + return TRUE; + + return FALSE; +} + + + +/* Called by the event code in case the server is abruptly terminated */ + +void +DGAShutdown(void) +{ + ScrnInfoPtr pScrn; + int i; + + if(DGAScreenKey == NULL) + return; + + for(i = 0; i < screenInfo.numScreens; i++) { + pScrn = xf86Screens[i]; + + (void)(*pScrn->SetDGAMode)(pScrn->scrnIndex, 0, NULL); + } +} + +/* Called by the extension to initialize a mode */ + +int +DGASetMode( + int index, + int num, + XDGAModePtr mode, + PixmapPtr *pPix +){ + ScrnInfoPtr pScrn = xf86Screens[index]; + DGADeviceRec device; + int ret; + + /* We rely on the extension to check that DGA is available */ + + ret = (*pScrn->SetDGAMode)(index, num, &device); + if((ret == Success) && num) { + DGACopyModeInfo(device.mode, mode); + *pPix = device.pPix; + } + + return ret; +} + +/* Called from the extension to let the DDX know which events are requested */ + +void +DGASelectInput( + int index, + ClientPtr client, + long mask +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is available */ + pScreenPriv->client = client; + pScreenPriv->input = mask; +} + +int +DGAGetViewportStatus(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if (!pScreenPriv->funcs->GetViewport) + return 0; + + return (*pScreenPriv->funcs->GetViewport)(pScreenPriv->pScrn); +} + +int +DGASetViewport( + int index, + int x, int y, + int mode +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if (pScreenPriv->funcs->SetViewport) + (*pScreenPriv->funcs->SetViewport)(pScreenPriv->pScrn, x, y, mode); + return Success; +} + + +static int +BitsClear(CARD32 data) +{ + int bits = 0; + CARD32 mask; + + for(mask = 1; mask; mask <<= 1) { + if(!(data & mask)) bits++; + else break; + } + + return bits; +} + +int +DGACreateColormap(int index, ClientPtr client, int id, int mode, int alloc) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + FakedVisualList *fvlp; + VisualPtr pVisual; + DGAModePtr pMode; + ColormapPtr pmap; + + if(!mode || (mode > pScreenPriv->numModes)) + return BadValue; + + if((alloc != AllocNone) && (alloc != AllocAll)) + return BadValue; + + pMode = &(pScreenPriv->modes[mode - 1]); + + if(!(pVisual = malloc(sizeof(VisualRec)))) + return BadAlloc; + + pVisual->vid = FakeClientID(0); + pVisual->class = pMode->visualClass; + pVisual->nplanes = pMode->depth; + pVisual->ColormapEntries = 1 << pMode->depth; + pVisual->bitsPerRGBValue = (pMode->depth + 2) / 3; + + switch (pVisual->class) { + case PseudoColor: + case GrayScale: + case StaticGray: + pVisual->bitsPerRGBValue = 8; /* not quite */ + pVisual->redMask = 0; + pVisual->greenMask = 0; + pVisual->blueMask = 0; + pVisual->offsetRed = 0; + pVisual->offsetGreen = 0; + pVisual->offsetBlue = 0; + break; + case DirectColor: + case TrueColor: + pVisual->ColormapEntries = 1 << pVisual->bitsPerRGBValue; + /* fall through */ + case StaticColor: + pVisual->redMask = pMode->red_mask; + pVisual->greenMask = pMode->green_mask; + pVisual->blueMask = pMode->blue_mask; + pVisual->offsetRed = BitsClear(pVisual->redMask); + pVisual->offsetGreen = BitsClear(pVisual->greenMask); + pVisual->offsetBlue = BitsClear(pVisual->blueMask); + } + + if(!(fvlp = malloc(sizeof(FakedVisualList)))) { + free(pVisual); + return BadAlloc; + } + + fvlp->free = FALSE; + fvlp->pVisual = pVisual; + fvlp->next = pScreenPriv->fakedVisuals; + pScreenPriv->fakedVisuals = fvlp; + + LEGAL_NEW_RESOURCE(id, client); + + return CreateColormap(id, pScreen, pVisual, &pmap, alloc, client->index); +} + +/* Called by the extension to install a colormap on DGA active screens */ + +void +DGAInstallCmap(ColormapPtr cmap) +{ + ScreenPtr pScreen = cmap->pScreen; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + /* We rely on the extension to check that DGA is active */ + + if(!pScreenPriv->dgaColormap) + pScreenPriv->savedColormap = GetInstalledmiColormap(pScreen); + + pScreenPriv->dgaColormap = cmap; + + (*pScreen->InstallColormap)(cmap); +} + +int +DGASync(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if (pScreenPriv->funcs->Sync) + (*pScreenPriv->funcs->Sync)(pScreenPriv->pScrn); + + return Success; +} + +int +DGAFillRect( + int index, + int x, int y, int w, int h, + unsigned long color +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if(pScreenPriv->funcs->FillRect && + (pScreenPriv->current->mode->flags & DGA_FILL_RECT)) { + + (*pScreenPriv->funcs->FillRect)(pScreenPriv->pScrn, x, y, w, h, color); + return Success; + } + return BadMatch; +} + +int +DGABlitRect( + int index, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if(pScreenPriv->funcs->BlitRect && + (pScreenPriv->current->mode->flags & DGA_BLIT_RECT)) { + + (*pScreenPriv->funcs->BlitRect)(pScreenPriv->pScrn, + srcx, srcy, w, h, dstx, dsty); + return Success; + } + return BadMatch; +} + +int +DGABlitTransRect( + int index, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is active */ + + if(pScreenPriv->funcs->BlitTransRect && + (pScreenPriv->current->mode->flags & DGA_BLIT_RECT_TRANS)) { + + (*pScreenPriv->funcs->BlitTransRect)(pScreenPriv->pScrn, + srcx, srcy, w, h, dstx, dsty, color); + return Success; + } + return BadMatch; +} + + +int +DGAGetModes(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + /* We rely on the extension to check that DGA is available */ + + return pScreenPriv->numModes; +} + + +int +DGAGetModeInfo( + int index, + XDGAModePtr mode, + int num +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + /* We rely on the extension to check that DGA is available */ + + if((num <= 0) || (num > pScreenPriv->numModes)) + return BadValue; + + DGACopyModeInfo(&(pScreenPriv->modes[num - 1]), mode); + + return Success; +} + + +static void +DGACopyModeInfo( + DGAModePtr mode, + XDGAModePtr xmode +){ + DisplayModePtr dmode = mode->mode; + + xmode->num = mode->num; + xmode->name = dmode->name; + xmode->VSync_num = (int)(dmode->VRefresh * 1000.0); + xmode->VSync_den = 1000; + xmode->flags = mode->flags; + xmode->imageWidth = mode->imageWidth; + xmode->imageHeight = mode->imageHeight; + xmode->pixmapWidth = mode->pixmapWidth; + xmode->pixmapHeight = mode->pixmapHeight; + xmode->bytesPerScanline = mode->bytesPerScanline; + xmode->byteOrder = mode->byteOrder; + xmode->depth = mode->depth; + xmode->bitsPerPixel = mode->bitsPerPixel; + xmode->red_mask = mode->red_mask; + xmode->green_mask = mode->green_mask; + xmode->blue_mask = mode->blue_mask; + xmode->visualClass = mode->visualClass; + xmode->viewportWidth = mode->viewportWidth; + xmode->viewportHeight = mode->viewportHeight; + xmode->xViewportStep = mode->xViewportStep; + xmode->yViewportStep = mode->yViewportStep; + xmode->maxViewportX = mode->maxViewportX; + xmode->maxViewportY = mode->maxViewportY; + xmode->viewportFlags = mode->viewportFlags; + xmode->reserved1 = mode->reserved1; + xmode->reserved2 = mode->reserved2; + xmode->offset = mode->offset; + + if(dmode->Flags & V_INTERLACE) xmode->flags |= DGA_INTERLACED; + if(dmode->Flags & V_DBLSCAN) xmode->flags |= DGA_DOUBLESCAN; +} + + +Bool +DGAVTSwitch(void) +{ + ScreenPtr pScreen; + int i; + + for(i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + + /* Alternatively, this could send events to DGA clients */ + + if(DGAScreenKey) { + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + if(pScreenPriv && pScreenPriv->current) + return FALSE; + } + } + + return TRUE; +} + +Bool +DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down) +{ + DGAScreenPtr pScreenPriv; + DGAEvent event; + + if(DGAScreenKey == NULL) /* no DGA */ + return FALSE; + + if (key_code < 8 || key_code > 255) + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if(!pScreenPriv || !pScreenPriv->grabKeyboard) /* no direct mode */ + return FALSE; + + memset(&event, 0, sizeof(event)); + event.header = ET_Internal; + event.type = ET_DGAEvent; + event.length = sizeof(event); + event.time = GetTimeInMillis(); + event.subtype = (is_down ? ET_KeyPress : ET_KeyRelease); + event.detail = key_code; + event.dx = 0; + event.dy = 0; + mieqEnqueue (dev, (InternalEvent*)&event); + + return TRUE; +} + +static int DGAMouseX, DGAMouseY; + +Bool +DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy) +{ + DGAScreenPtr pScreenPriv; + DGAEvent event; + + if(DGAScreenKey == NULL) /* no DGA */ + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if(!pScreenPriv || !pScreenPriv->grabMouse) /* no direct mode */ + return FALSE; + + DGAMouseX += dx; + if (DGAMouseX < 0) + DGAMouseX = 0; + else if (DGAMouseX > screenInfo.screens[index]->width) + DGAMouseX = screenInfo.screens[index]->width; + DGAMouseY += dy; + if (DGAMouseY < 0) + DGAMouseY = 0; + else if (DGAMouseY > screenInfo.screens[index]->height) + DGAMouseY = screenInfo.screens[index]->height; + + memset(&event, 0, sizeof(event)); + event.header = ET_Internal; + event.type = ET_DGAEvent; + event.length = sizeof(event); + event.time = GetTimeInMillis(); + event.subtype = ET_Motion; + event.detail = 0; + event.dx = dx; + event.dy = dy; + mieqEnqueue (dev, (InternalEvent*)&event); + return TRUE; +} + +Bool +DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down) +{ + DGAScreenPtr pScreenPriv; + DGAEvent event; + + if (DGAScreenKey == NULL) + return FALSE; + + pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + if (!pScreenPriv || !pScreenPriv->grabMouse) + return FALSE; + + memset(&event, 0, sizeof(event)); + event.header = ET_Internal; + event.type = ET_DGAEvent; + event.length = sizeof(event); + event.time = GetTimeInMillis(); + event.subtype = (is_down ? ET_ButtonPress : ET_ButtonRelease); + event.detail = button; + event.dx = 0; + event.dy = 0; + mieqEnqueue (dev, (InternalEvent*)&event); + + return TRUE; +} + +/* We have the power to steal or modify events that are about to get queued */ + +Bool +DGAIsDgaEvent (xEvent *e) +{ + int coreEquiv; + if (DGAScreenKey == NULL || XDGAEventBase == 0) + return FALSE; + coreEquiv = e->u.u.type - *XDGAEventBase; + if (KeyPress <= coreEquiv && coreEquiv <= MotionNotify) + return TRUE; + return FALSE; +} + +#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ +static Mask filters[] = +{ + NoSuchEvent, /* 0 */ + NoSuchEvent, /* 1 */ + KeyPressMask, /* KeyPress */ + KeyReleaseMask, /* KeyRelease */ + ButtonPressMask, /* ButtonPress */ + ButtonReleaseMask, /* ButtonRelease */ + PointerMotionMask, /* MotionNotify (initial state) */ +}; + +static void +DGAProcessKeyboardEvent (ScreenPtr pScreen, DGAEvent *event, DeviceIntPtr keybd) +{ + KeyClassPtr keyc = keybd->key; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + DeviceIntPtr pointer = GetPairedDevice(keybd); + DeviceEvent ev; + + memset(&ev, 0, sizeof(ev)); + ev.length = sizeof(ev); + ev.detail.key = event->detail; + ev.type = event->subtype; + ev.root_x = 0; + ev.root_y = 0; + ev.corestate = XkbStateFieldFromRec(&keyc->xkbInfo->state); + ev.corestate |= pointer->button->state; + + UpdateDeviceState(keybd, &ev); + + /* + * Deliver the DGA event + */ + if (pScreenPriv->client) + { + dgaEvent de; + de.u.u.type = *XDGAEventBase + GetCoreType((InternalEvent*)&ev); + de.u.u.detail = event->detail; + de.u.event.time = event->time; + de.u.event.dx = 0; + de.u.event.dy = 0; + de.u.event.screen = pScreen->myNum; + de.u.event.state = ev.corestate; + + /* If the DGA client has selected input, then deliver based on the usual filter */ + TryClientEvents (pScreenPriv->client, keybd, (xEvent *)&de, 1, + filters[ev.type], pScreenPriv->input, 0); + } + else + { + /* If the keyboard is actively grabbed, deliver a grabbed core event */ + if (keybd->deviceGrab.grab && !keybd->deviceGrab.fromPassiveGrab) + { + ev.detail.key = event->detail; + ev.time = event->time; + ev.root_x = event->dx; + ev.root_y = event->dy; + ev.corestate = event->state; + ev.deviceid = keybd->id; + DeliverGrabbedEvent ((InternalEvent*)&ev, keybd, FALSE); + } + } +} + +static void +DGAProcessPointerEvent (ScreenPtr pScreen, DGAEvent *event, DeviceIntPtr mouse) +{ + ButtonClassPtr butc = mouse->button; + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + DeviceEvent ev; + DeviceIntPtr master = GetMaster(mouse, MASTER_KEYBOARD); + + memset(&ev, 0, sizeof(ev)); + ev.header = ET_Internal; + ev.length = sizeof(ev); + ev.type = event->subtype; + ev.corestate = butc->state; + if (master && master->key) + ev.corestate |= XkbStateFieldFromRec(&master->key->xkbInfo->state); + + UpdateDeviceState(mouse, &ev); + + /* + * Deliver the DGA event + */ + if (pScreenPriv->client) + { + dgaEvent de; + int coreEquiv; + + coreEquiv = GetCoreType((InternalEvent*)&ev); + + de.u.u.type = *XDGAEventBase + coreEquiv; + de.u.u.detail = event->detail; + de.u.event.time = event->time; + de.u.event.dx = 0; + de.u.event.dy = 0; + de.u.event.screen = pScreen->myNum; + de.u.event.state = ev.corestate; + + /* If the DGA client has selected input, then deliver based on the usual filter */ + TryClientEvents (pScreenPriv->client, mouse, (xEvent *)&de, 1, + filters[coreEquiv], pScreenPriv->input, 0); + } + else + { + /* If the pointer is actively grabbed, deliver a grabbed core event */ + if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab) + { + ev.detail.button = event->detail; + ev.time = event->time; + ev.root_x = event->dx; + ev.root_y = event->dy; + ev.corestate = event->state; + DeliverGrabbedEvent ((InternalEvent*)&ev, mouse, FALSE); + } + } +} + +Bool +DGAOpenFramebuffer( + int index, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *flags +){ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is available */ + + return (*pScreenPriv->funcs->OpenFramebuffer)(pScreenPriv->pScrn, + name, mem, size, offset, flags); +} + +void +DGACloseFramebuffer(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + + /* We rely on the extension to check that DGA is available */ + if(pScreenPriv->funcs->CloseFramebuffer) + (*pScreenPriv->funcs->CloseFramebuffer)(pScreenPriv->pScrn); +} + +/* For DGA 1.0 backwards compatibility only */ + +int +DGAGetOldDGAMode(int index) +{ + DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]); + ScrnInfoPtr pScrn = pScreenPriv->pScrn; + DGAModePtr mode; + int i, w, h, p; + + /* We rely on the extension to check that DGA is available */ + + w = pScrn->currentMode->HDisplay; + h = pScrn->currentMode->VDisplay; + p = pad_to_int32(pScrn->displayWidth * bits_to_bytes(pScrn->bitsPerPixel)); + + for(i = 0; i < pScreenPriv->numModes; i++) { + mode = &(pScreenPriv->modes[i]); + + if((mode->viewportWidth == w) && (mode->viewportHeight == h) && + (mode->bytesPerScanline == p) && + (mode->bitsPerPixel == pScrn->bitsPerPixel) && + (mode->depth == pScrn->depth)) { + + return mode->num; + } + } + + return 0; +} + +static void +DGAHandleEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ + DGAEvent *event= &ev->dga_event; + ScreenPtr pScreen = screenInfo.screens[screen_num]; + DGAScreenPtr pScreenPriv; + + /* no DGA */ + if (DGAScreenKey == NULL || XDGAEventBase == 0) + return; + pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + + /* DGA not initialized on this screen */ + if (!pScreenPriv) + return; + + switch (event->subtype) { + case KeyPress: + case KeyRelease: + DGAProcessKeyboardEvent (pScreen, event, device); + break; + case MotionNotify: + case ButtonPress: + case ButtonRelease: + DGAProcessPointerEvent (pScreen, event, device); + break; + default: + break; + } +} diff --git a/xorg-server/hw/xfree86/common/xf86DPMS.c b/xorg-server/hw/xfree86/common/xf86DPMS.c index 22174c74e..3040cb294 100644 --- a/xorg-server/hw/xfree86/common/xf86DPMS.c +++ b/xorg-server/hw/xfree86/common/xf86DPMS.c @@ -1,200 +1,200 @@ -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * This file contains the DPMS functions required by the extension. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "os.h" -#include "globals.h" -#include "xf86.h" -#include "xf86Priv.h" -#ifdef DPMSExtension -#include -#include "dpmsproc.h" -#endif -#include "xf86VGAarbiter.h" - - -#ifdef DPMSExtension -static int DPMSKeyIndex; -static DevPrivateKey DPMSKey; -static Bool DPMSClose(int i, ScreenPtr pScreen); -static int DPMSCount = 0; -#endif - - -Bool -xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags) -{ -#ifdef DPMSExtension - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - DPMSPtr pDPMS; - pointer DPMSOpt; - MessageType enabled_from; - - DPMSKey = &DPMSKeyIndex; - - if (!dixSetPrivate(&pScreen->devPrivates, DPMSKey, - xcalloc(sizeof(DPMSRec), 1))) - return FALSE; - - pDPMS = dixLookupPrivate(&pScreen->devPrivates, DPMSKey); - pScrn->DPMSSet = set; - pDPMS->Flags = flags; - DPMSOpt = xf86FindOption(pScrn->options, "dpms"); - if (DPMSDisabledSwitch) { - enabled_from = X_CMDLINE; - DPMSEnabled = FALSE; - } - else if (DPMSOpt) { - enabled_from = X_CONFIG; - DPMSEnabled = xf86CheckBoolOption(pScrn->options, "dpms", FALSE); - xf86MarkOptionUsed(DPMSOpt); - } - else { - enabled_from = X_DEFAULT; - DPMSEnabled = TRUE; - } - if (DPMSEnabled) - xf86DrvMsg(pScreen->myNum, enabled_from, "DPMS enabled\n"); - pDPMS->Enabled = DPMSEnabled; - pDPMS->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = DPMSClose; - DPMSCount++; - return TRUE; -#else - return FALSE; -#endif -} - - -#ifdef DPMSExtension - -static Bool -DPMSClose(int i, ScreenPtr pScreen) -{ - DPMSPtr pDPMS; - - /* This shouldn't happen */ - if (DPMSKey == NULL) - return FALSE; - - pDPMS = dixLookupPrivate(&pScreen->devPrivates, DPMSKey); - - /* This shouldn't happen */ - if (!pDPMS) - return FALSE; - - pScreen->CloseScreen = pDPMS->CloseScreen; - - /* - * Turn on DPMS when shutting down. If this function can be used - * depends on the order the driver wraps things. If this is called - * after the driver has shut down everything the driver will have - * to deal with this internally. - */ - if (xf86Screens[i]->vtSema && xf86Screens[i]->DPMSSet) { - xf86Screens[i]->DPMSSet(xf86Screens[i],DPMSModeOn,0); - } - - xfree(pDPMS); - dixSetPrivate(&pScreen->devPrivates, DPMSKey, NULL); - if (--DPMSCount == 0) - DPMSKey = NULL; - return pScreen->CloseScreen(i, pScreen); -} - - -/* - * DPMSSet -- - * Device dependent DPMS mode setting hook. This is called whenever - * the DPMS mode is to be changed. - */ -int -DPMSSet(ClientPtr client, int level) -{ - int rc, i; - DPMSPtr pDPMS; - ScrnInfoPtr pScrn; - - DPMSPowerLevel = level; - - if (DPMSKey == NULL) - return Success; - - if (level != DPMSModeOn) { - rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive); - if (rc != Success) - return rc; - } - - /* For each screen, set the DPMS level */ - for (i = 0; i < xf86NumScreens; i++) { - pScrn = xf86Screens[i]; - pDPMS = dixLookupPrivate(&screenInfo.screens[i]->devPrivates, DPMSKey); - if (pDPMS && pScrn->DPMSSet && pDPMS->Enabled && pScrn->vtSema) { - xf86VGAarbiterLock(pScrn); - pScrn->DPMSSet(pScrn, level, 0); - xf86VGAarbiterUnlock(pScrn); - } - } - return Success; -} - - -/* - * DPMSSupported -- - * Return TRUE if any screen supports DPMS. - */ -Bool -DPMSSupported(void) -{ - int i; - DPMSPtr pDPMS; - ScrnInfoPtr pScrn; - - if (DPMSKey == NULL) { - return FALSE; - } - - /* For each screen, check if DPMS is supported */ - for (i = 0; i < xf86NumScreens; i++) { - pScrn = xf86Screens[i]; - pDPMS = dixLookupPrivate(&screenInfo.screens[i]->devPrivates, DPMSKey); - if (pDPMS && pScrn->DPMSSet) - return TRUE; - } - return FALSE; -} - -#endif /* DPMSExtension */ +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * This file contains the DPMS functions required by the extension. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "os.h" +#include "globals.h" +#include "xf86.h" +#include "xf86Priv.h" +#ifdef DPMSExtension +#include +#include "dpmsproc.h" +#endif +#include "xf86VGAarbiter.h" + + +#ifdef DPMSExtension +static int DPMSKeyIndex; +static DevPrivateKey DPMSKey; +static Bool DPMSClose(int i, ScreenPtr pScreen); +static int DPMSCount = 0; +#endif + + +Bool +xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags) +{ +#ifdef DPMSExtension + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DPMSPtr pDPMS; + pointer DPMSOpt; + MessageType enabled_from; + + DPMSKey = &DPMSKeyIndex; + + if (!dixSetPrivate(&pScreen->devPrivates, DPMSKey, + calloc(sizeof(DPMSRec), 1))) + return FALSE; + + pDPMS = dixLookupPrivate(&pScreen->devPrivates, DPMSKey); + pScrn->DPMSSet = set; + pDPMS->Flags = flags; + DPMSOpt = xf86FindOption(pScrn->options, "dpms"); + if (DPMSDisabledSwitch) { + enabled_from = X_CMDLINE; + DPMSEnabled = FALSE; + } + else if (DPMSOpt) { + enabled_from = X_CONFIG; + DPMSEnabled = xf86CheckBoolOption(pScrn->options, "dpms", FALSE); + xf86MarkOptionUsed(DPMSOpt); + } + else { + enabled_from = X_DEFAULT; + DPMSEnabled = TRUE; + } + if (DPMSEnabled) + xf86DrvMsg(pScreen->myNum, enabled_from, "DPMS enabled\n"); + pDPMS->Enabled = DPMSEnabled; + pDPMS->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = DPMSClose; + DPMSCount++; + return TRUE; +#else + return FALSE; +#endif +} + + +#ifdef DPMSExtension + +static Bool +DPMSClose(int i, ScreenPtr pScreen) +{ + DPMSPtr pDPMS; + + /* This shouldn't happen */ + if (DPMSKey == NULL) + return FALSE; + + pDPMS = dixLookupPrivate(&pScreen->devPrivates, DPMSKey); + + /* This shouldn't happen */ + if (!pDPMS) + return FALSE; + + pScreen->CloseScreen = pDPMS->CloseScreen; + + /* + * Turn on DPMS when shutting down. If this function can be used + * depends on the order the driver wraps things. If this is called + * after the driver has shut down everything the driver will have + * to deal with this internally. + */ + if (xf86Screens[i]->vtSema && xf86Screens[i]->DPMSSet) { + xf86Screens[i]->DPMSSet(xf86Screens[i],DPMSModeOn,0); + } + + free(pDPMS); + dixSetPrivate(&pScreen->devPrivates, DPMSKey, NULL); + if (--DPMSCount == 0) + DPMSKey = NULL; + return pScreen->CloseScreen(i, pScreen); +} + + +/* + * DPMSSet -- + * Device dependent DPMS mode setting hook. This is called whenever + * the DPMS mode is to be changed. + */ +int +DPMSSet(ClientPtr client, int level) +{ + int rc, i; + DPMSPtr pDPMS; + ScrnInfoPtr pScrn; + + DPMSPowerLevel = level; + + if (DPMSKey == NULL) + return Success; + + if (level != DPMSModeOn) { + rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive); + if (rc != Success) + return rc; + } + + /* For each screen, set the DPMS level */ + for (i = 0; i < xf86NumScreens; i++) { + pScrn = xf86Screens[i]; + pDPMS = dixLookupPrivate(&screenInfo.screens[i]->devPrivates, DPMSKey); + if (pDPMS && pScrn->DPMSSet && pDPMS->Enabled && pScrn->vtSema) { + xf86VGAarbiterLock(pScrn); + pScrn->DPMSSet(pScrn, level, 0); + xf86VGAarbiterUnlock(pScrn); + } + } + return Success; +} + + +/* + * DPMSSupported -- + * Return TRUE if any screen supports DPMS. + */ +Bool +DPMSSupported(void) +{ + int i; + DPMSPtr pDPMS; + ScrnInfoPtr pScrn; + + if (DPMSKey == NULL) { + return FALSE; + } + + /* For each screen, check if DPMS is supported */ + for (i = 0; i < xf86NumScreens; i++) { + pScrn = xf86Screens[i]; + pDPMS = dixLookupPrivate(&screenInfo.screens[i]->devPrivates, DPMSKey); + if (pDPMS && pScrn->DPMSSet) + return TRUE; + } + return FALSE; +} + +#endif /* DPMSExtension */ diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c index ee4835233..9d3a58f91 100644 --- a/xorg-server/hw/xfree86/common/xf86Events.c +++ b/xorg-server/hw/xfree86/common/xf86Events.c @@ -567,7 +567,7 @@ addInputHandler(int fd, InputHandlerProc proc, pointer data) if (fd < 0 || !proc) return NULL; - ih = xcalloc(sizeof(*ih), 1); + ih = calloc(sizeof(*ih), 1); if (!ih) return NULL; @@ -616,7 +616,7 @@ removeInputHandler(IHPtr ih) if (ih) p->next = ih->next; } - xfree(ih); + free(ih); } int diff --git a/xorg-server/hw/xfree86/common/xf86Helper.c b/xorg-server/hw/xfree86/common/xf86Helper.c index 1cc1526c9..4cc543fc4 100644 --- a/xorg-server/hw/xfree86/common/xf86Helper.c +++ b/xorg-server/hw/xfree86/common/xf86Helper.c @@ -1,2588 +1,2588 @@ -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * Authors: Dirk Hohndel - * David Dawes - * ... and others - * - * This file includes the helper functions that the server provides for - * different drivers. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "Pci.h" - -#include -#include "os.h" -#include "servermd.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "propertyst.h" -#include "gcstruct.h" -#include "loaderProcs.h" -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "micmap.h" -#include "xf86DDC.h" -#include "xf86Xinput.h" -#include "xf86InPriv.h" -#include "mivalidate.h" -#include "xf86Bus.h" -#include "xf86Crtc.h" - -/* For xf86GetClocks */ -#if defined(CSRG_BASED) || defined(__GNU__) -#define HAS_SETPRIORITY -#include -#endif - -static int xf86ScrnInfoPrivateCount = 0; - - -/* Add a pointer to a new DriverRec to xf86DriverList */ - -void -xf86AddDriver(DriverPtr driver, pointer module, int flags) -{ - /* Don't add null entries */ - if (!driver) - return; - - if (xf86DriverList == NULL) - xf86NumDrivers = 0; - - xf86NumDrivers++; - xf86DriverList = xnfrealloc(xf86DriverList, - xf86NumDrivers * sizeof(DriverPtr)); - xf86DriverList[xf86NumDrivers - 1] = xnfalloc(sizeof(DriverRec)); - if (flags & HaveDriverFuncs) - *xf86DriverList[xf86NumDrivers - 1] = *driver; - else { - (void) memset( xf86DriverList[xf86NumDrivers - 1], 0, - sizeof( DriverRec ) ); - (void) memcpy( xf86DriverList[xf86NumDrivers - 1], driver, - sizeof(DriverRec1)); - - } - xf86DriverList[xf86NumDrivers - 1]->module = module; - xf86DriverList[xf86NumDrivers - 1]->refCount = 0; -} - -void -xf86DeleteDriver(int drvIndex) -{ - if (xf86DriverList[drvIndex] - && (!xf86DriverHasEntities(xf86DriverList[drvIndex]))) { - if (xf86DriverList[drvIndex]->module) - UnloadModule(xf86DriverList[drvIndex]->module); - xfree(xf86DriverList[drvIndex]); - xf86DriverList[drvIndex] = NULL; - } -} - -/* Add a pointer to a new InputDriverRec to xf86InputDriverList */ - -void -xf86AddInputDriver(InputDriverPtr driver, pointer module, int flags) -{ - /* Don't add null entries */ - if (!driver) - return; - - if (xf86InputDriverList == NULL) - xf86NumInputDrivers = 0; - - xf86NumInputDrivers++; - xf86InputDriverList = xnfrealloc(xf86InputDriverList, - xf86NumInputDrivers * sizeof(InputDriverPtr)); - xf86InputDriverList[xf86NumInputDrivers - 1] = - xnfalloc(sizeof(InputDriverRec)); - *xf86InputDriverList[xf86NumInputDrivers - 1] = *driver; - xf86InputDriverList[xf86NumInputDrivers - 1]->module = module; - xf86InputDriverList[xf86NumInputDrivers - 1]->refCount = 0; -} - -void -xf86DeleteInputDriver(int drvIndex) -{ - if (xf86InputDriverList[drvIndex] && xf86InputDriverList[drvIndex]->module) - UnloadModule(xf86InputDriverList[drvIndex]->module); - xfree(xf86InputDriverList[drvIndex]); - xf86InputDriverList[drvIndex] = NULL; -} - -InputDriverPtr -xf86LookupInputDriver(const char *name) -{ - int i; - - for (i = 0; i < xf86NumInputDrivers; i++) { - if (xf86InputDriverList[i] && xf86InputDriverList[i]->driverName && - xf86NameCmp(name, xf86InputDriverList[i]->driverName) == 0) - return xf86InputDriverList[i]; - } - return NULL; -} - -InputInfoPtr -xf86LookupInput(const char *name) -{ - InputInfoPtr p; - - for (p = xf86InputDevs; p != NULL; p = p->next) { - if (strcmp(name, p->name) == 0) - return p; - } - - return NULL; -} - -/* Allocate a new ScrnInfoRec in xf86Screens */ - -ScrnInfoPtr -xf86AllocateScreen(DriverPtr drv, int flags) -{ - int i; - - if (xf86Screens == NULL) - xf86NumScreens = 0; - - i = xf86NumScreens++; - xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr)); - xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1); - xf86Screens[i]->scrnIndex = i; /* Changes when a screen is removed */ - xf86Screens[i]->origIndex = i; /* This never changes */ - xf86Screens[i]->privates = xnfcalloc(sizeof(DevUnion), - xf86ScrnInfoPrivateCount); - /* - * EnableDisableFBAccess now gets initialized in InitOutput() - * xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess; - */ - - xf86Screens[i]->drv = drv; - drv->refCount++; - xf86Screens[i]->module = DuplicateModule(drv->module, NULL); - - xf86Screens[i]->DriverFunc = drv->driverFunc; - - return xf86Screens[i]; -} - - -/* - * Remove an entry from xf86Screens. Ideally it should free all allocated - * data. To do this properly may require a driver hook. - */ - -void -xf86DeleteScreen(int scrnIndex, int flags) -{ - ScrnInfoPtr pScrn; - int i; - - /* First check if the screen is valid */ - if (xf86NumScreens == 0 || xf86Screens == NULL) - return; - - if (scrnIndex > xf86NumScreens - 1) - return; - - if (!(pScrn = xf86Screens[scrnIndex])) - return; - - /* If a FreeScreen function is defined, call it here */ - if (pScrn->FreeScreen != NULL) - pScrn->FreeScreen(scrnIndex, 0); - - while (pScrn->modes) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - - while (pScrn->modePool) - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - - xf86OptionListFree(pScrn->options); - - if (pScrn->module) - UnloadModule(pScrn->module); - - if (pScrn->drv) - pScrn->drv->refCount--; - - if (pScrn->privates) - xfree(pScrn->privates); - - xf86ClearEntityListForScreen(scrnIndex); - - xfree(pScrn); - - /* Move the other entries down, updating their scrnIndex fields */ - - xf86NumScreens--; - - for (i = scrnIndex; i < xf86NumScreens; i++) { - xf86Screens[i] = xf86Screens[i + 1]; - xf86Screens[i]->scrnIndex = i; - /* Also need to take care of the screen layout settings */ - } -} - -/* - * Allocate a private in ScrnInfoRec. - */ - -int -xf86AllocateScrnInfoPrivateIndex(void) -{ - int idx, i; - ScrnInfoPtr pScr; - DevUnion *nprivs; - - idx = xf86ScrnInfoPrivateCount++; - for (i = 0; i < xf86NumScreens; i++) { - pScr = xf86Screens[i]; - nprivs = xnfrealloc(pScr->privates, - xf86ScrnInfoPrivateCount * sizeof(DevUnion)); - /* Zero the new private */ - bzero(&nprivs[idx], sizeof(DevUnion)); - pScr->privates = nprivs; - } - return idx; -} - -/* Allocate a new InputInfoRec and append it to the tail of xf86InputDevs. */ -InputInfoPtr -xf86AllocateInput(InputDriverPtr drv, int flags) -{ - InputInfoPtr new, *prev = NULL; - - if (!(new = xcalloc(sizeof(InputInfoRec), 1))) - return NULL; - - new->drv = drv; - drv->refCount++; - new->module = DuplicateModule(drv->module, NULL); - - for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) - ; - - *prev = new; - new->next = NULL; - - return new; -} - - -/* - * Remove an entry from xf86InputDevs. Ideally it should free all allocated - * data. To do this properly may require a driver hook. - */ - -void -xf86DeleteInput(InputInfoPtr pInp, int flags) -{ - InputInfoPtr p; - - /* First check if the inputdev is valid. */ - if (pInp == NULL) - return; - -#if 0 - /* If a free function is defined, call it here. */ - if (pInp->free) - pInp->free(pInp, 0); -#endif - - if (pInp->module) - UnloadModule(pInp->module); - - if (pInp->drv) - pInp->drv->refCount--; - - /* This should *really* be handled in drv->UnInit(dev) call instead, but - * if the driver forgets about it make sure we free it or at least crash - * with flying colors */ - if (pInp->private) - xfree(pInp->private); - - /* Remove the entry from the list. */ - if (pInp == xf86InputDevs) - xf86InputDevs = pInp->next; - else { - p = xf86InputDevs; - while (p && p->next != pInp) - p = p->next; - if (p) - p->next = pInp->next; - /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ - } - xfree(pInp); -} - -Bool -xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad) -{ - int i; - - if (pScrn->numFormats >= MAXFORMATS) - return FALSE; - - if (bpp <= 0) { - if (depth == 1) - bpp = 1; - else if (depth <= 8) - bpp = 8; - else if (depth <= 16) - bpp = 16; - else if (depth <= 32) - bpp = 32; - else - return FALSE; - } - if (pad <= 0) - pad = BITMAP_SCANLINE_PAD; - - i = pScrn->numFormats++; - pScrn->formats[i].depth = depth; - pScrn->formats[i].bitsPerPixel = bpp; - pScrn->formats[i].scanlinePad = pad; - return TRUE; -} - -/* - * Set the depth we are using based on (in the following order of preference): - * - values given on the command line - * - values given in the config file - * - values provided by the driver - * - an overall default when nothing else is given - * - * Also find a Display subsection matching the depth/bpp found. - * - * Sets the following ScrnInfoRec fields: - * bitsPerPixel, pixmap24, depth, display, imageByteOrder, - * bitmapScanlinePad, bitmapScanlineUnit, bitmapBitOrder, numFormats, - * formats, fbFormat. - */ - -/* Can the screen handle 24 bpp pixmaps */ -#define DO_PIX24(f) ((f & Support24bppFb) || \ - ((f & Support32bppFb) && (f & SupportConvert24to32))) - -/* Can the screen handle 32 bpp pixmaps */ -#define DO_PIX32(f) ((f & Support32bppFb) || \ - ((f & Support24bppFb) && (f & SupportConvert32to24))) - -/* Does the screen prefer 32bpp fb for 24bpp pixmaps */ -#define CHOOSE32FOR24(f) ((f & Support32bppFb) && (f & SupportConvert24to32) \ - && (f & PreferConvert24to32)) - -/* Does the screen prefer 24bpp fb for 32bpp pixmaps */ -#define CHOOSE24FOR32(f) ((f & Support24bppFb) && (f & SupportConvert32to24) \ - && (f & PreferConvert32to24)) - -/* Can the screen handle 32bpp pixmaps for 24bpp fb */ -#define DO_PIX32FOR24(f) ((f & Support24bppFb) && (f & SupportConvert32to24)) - -/* Can the screen handle 24bpp pixmaps for 32bpp fb */ -#define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32)) - -#ifndef GLOBAL_DEFAULT_DEPTH -#define GLOBAL_DEFAULT_DEPTH 24 -#endif - -Bool -xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp, - int depth24flags) -{ - int i; - DispPtr disp; - Pix24Flags pix24 = xf86Info.pixmap24; - Bool nomatch = FALSE; - - scrp->bitsPerPixel = -1; - scrp->depth = -1; - scrp->pixmap24 = Pix24DontCare; - scrp->bitsPerPixelFrom = X_DEFAULT; - scrp->depthFrom = X_DEFAULT; - - if (xf86FbBpp > 0) { - scrp->bitsPerPixel = xf86FbBpp; - scrp->bitsPerPixelFrom = X_CMDLINE; - } - - if (xf86Depth > 0) { - scrp->depth = xf86Depth; - scrp->depthFrom = X_CMDLINE; - } - - if (xf86FbBpp < 0 && xf86Depth < 0) { - if (scrp->confScreen->defaultfbbpp > 0) { - scrp->bitsPerPixel = scrp->confScreen->defaultfbbpp; - scrp->bitsPerPixelFrom = X_CONFIG; - } - if (scrp->confScreen->defaultdepth > 0) { - scrp->depth = scrp->confScreen->defaultdepth; - scrp->depthFrom = X_CONFIG; - } - - if (scrp->confScreen->defaultfbbpp <= 0 && - scrp->confScreen->defaultdepth <= 0) { - /* - * Check for DefaultDepth and DefaultFbBpp options in the - * Device sections. - */ - int i; - GDevPtr device; - Bool found = FALSE; - - for (i = 0; i < scrp->numEntities; i++) { - device = xf86GetDevFromEntity(scrp->entityList[i], - scrp->entityInstanceList[i]); - if (device && device->options) { - if (xf86FindOption(device->options, "DefaultDepth")) { - scrp->depth = xf86SetIntOption(device->options, - "DefaultDepth", -1); - scrp->depthFrom = X_CONFIG; - found = TRUE; - } - if (xf86FindOption(device->options, "DefaultFbBpp")) { - scrp->bitsPerPixel = xf86SetIntOption(device->options, - "DefaultFbBpp", - -1); - scrp->bitsPerPixelFrom = X_CONFIG; - found = TRUE; - } - } - if (found) - break; - } - } - } - - /* If none of these is set, pick a default */ - if (scrp->bitsPerPixel < 0 && scrp->depth < 0) { - if (fbbpp > 0 || depth > 0) { - if (fbbpp > 0) - scrp->bitsPerPixel = fbbpp; - if (depth > 0) - scrp->depth = depth; - } else { - scrp->depth = GLOBAL_DEFAULT_DEPTH; - } - } - - /* If any are not given, determine a default for the others */ - - if (scrp->bitsPerPixel < 0) { - /* The depth must be set */ - if (scrp->depth > -1) { - if (scrp->depth == 1) - scrp->bitsPerPixel = 1; - else if (scrp->depth <= 4) - scrp->bitsPerPixel = 4; - else if (scrp->depth <= 8) - scrp->bitsPerPixel = 8; - else if (scrp->depth <= 16) - scrp->bitsPerPixel = 16; - else if (scrp->depth <= 24) { - /* - * Figure out if a choice is possible based on the depth24 - * and pix24 flags. - */ - /* Check pix24 first */ - if (pix24 != Pix24DontCare) { - if (pix24 == Pix24Use32) { - if (DO_PIX32(depth24flags)) { - if (CHOOSE24FOR32(depth24flags)) - scrp->bitsPerPixel = 24; - else - scrp->bitsPerPixel = 32; - } else { - nomatch = TRUE; - } - } else if (pix24 == Pix24Use24) { - if (DO_PIX24(depth24flags)) { - if (CHOOSE32FOR24(depth24flags)) - scrp->bitsPerPixel = 32; - else - scrp->bitsPerPixel = 24; - } else { - nomatch = TRUE; - } - } - } else { - if (DO_PIX32(depth24flags)) { - if (CHOOSE24FOR32(depth24flags)) - scrp->bitsPerPixel = 24; - else - scrp->bitsPerPixel = 32; - } else if (DO_PIX24(depth24flags)) { - if (CHOOSE32FOR24(depth24flags)) - scrp->bitsPerPixel = 32; - else - scrp->bitsPerPixel = 24; - } - } - } else if (scrp->depth <= 32) - scrp->bitsPerPixel = 32; - else { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Specified depth (%d) is greater than 32\n", - scrp->depth); - return FALSE; - } - } else { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "xf86SetDepthBpp: internal error: depth and fbbpp" - " are both not set\n"); - return FALSE; - } - if (scrp->bitsPerPixel < 0) { - if (nomatch) - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Driver can't support depth 24 pixmap format (%d)\n", - PIX24TOBPP(pix24)); - else if ((depth24flags & (Support24bppFb | Support32bppFb)) == - NoDepth24Support) - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Driver can't support depth 24\n"); - else - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Can't find fbbpp for depth 24\n"); - return FALSE; - } - scrp->bitsPerPixelFrom = X_PROBED; - } - - if (scrp->depth <= 0) { - /* bitsPerPixel is already set */ - switch (scrp->bitsPerPixel) { - case 32: - scrp->depth = 24; - break; - default: - /* 1, 4, 8, 16 and 24 */ - scrp->depth = scrp->bitsPerPixel; - break; - } - scrp->depthFrom = X_PROBED; - } - - /* Sanity checks */ - if (scrp->depth < 1 || scrp->depth > 32) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Specified depth (%d) is not in the range 1-32\n", - scrp->depth); - return FALSE; - } - switch (scrp->bitsPerPixel) { - case 1: - case 4: - case 8: - case 16: - case 24: - case 32: - break; - default: - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Specified fbbpp (%d) is not a permitted value\n", - scrp->bitsPerPixel); - return FALSE; - } - if (scrp->depth > scrp->bitsPerPixel) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Specified depth (%d) is greater than the fbbpp (%d)\n", - scrp->depth, scrp->bitsPerPixel); - return FALSE; - } - - /* set scrp->pixmap24 if the driver isn't flexible */ - if (scrp->bitsPerPixel == 24 && !DO_PIX32FOR24(depth24flags)) { - scrp->pixmap24 = Pix24Use24; - } - if (scrp->bitsPerPixel == 32 && !DO_PIX24FOR32(depth24flags)) { - scrp->pixmap24 = Pix24Use32; - } - - /* - * Find the Display subsection matching the depth/fbbpp and initialise - * scrp->display with it. - */ - for (i = 0, disp = scrp->confScreen->displays; - i < scrp->confScreen->numdisplays; i++, disp++) { - if ((disp->depth == scrp->depth && disp->fbbpp == scrp->bitsPerPixel) - || (disp->depth == scrp->depth && disp->fbbpp <= 0) - || (disp->fbbpp == scrp->bitsPerPixel && disp->depth <= 0)) { - scrp->display = disp; - break; - } - } - - /* - * If an exact match can't be found, see if there is one with no - * depth or fbbpp specified. - */ - if (i == scrp->confScreen->numdisplays) { - for (i = 0, disp = scrp->confScreen->displays; - i < scrp->confScreen->numdisplays; i++, disp++) { - if (disp->depth <= 0 && disp->fbbpp <= 0) { - scrp->display = disp; - break; - } - } - } - - /* - * If all else fails, create a default one. - */ - if (i == scrp->confScreen->numdisplays) { - scrp->confScreen->numdisplays++; - scrp->confScreen->displays = - xnfrealloc(scrp->confScreen->displays, - scrp->confScreen->numdisplays * sizeof(DispRec)); - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "Creating default Display subsection in Screen section\n" - "\t\"%s\" for depth/fbbpp %d/%d\n", - scrp->confScreen->id, scrp->depth, scrp->bitsPerPixel); - memset(&scrp->confScreen->displays[i], 0, sizeof(DispRec)); - scrp->confScreen->displays[i].blackColour.red = -1; - scrp->confScreen->displays[i].blackColour.green = -1; - scrp->confScreen->displays[i].blackColour.blue = -1; - scrp->confScreen->displays[i].whiteColour.red = -1; - scrp->confScreen->displays[i].whiteColour.green = -1; - scrp->confScreen->displays[i].whiteColour.blue = -1; - scrp->confScreen->displays[i].defaultVisual = -1; - scrp->confScreen->displays[i].modes = xnfalloc(sizeof(char *)); - scrp->confScreen->displays[i].modes[0] = NULL; - scrp->confScreen->displays[i].depth = depth; - scrp->confScreen->displays[i].fbbpp = fbbpp; - scrp->display = &scrp->confScreen->displays[i]; - } - - /* - * Setup defaults for the display-wide attributes the framebuffer will - * need. These defaults should eventually be set globally, and not - * dependent on the screens. - */ - scrp->imageByteOrder = IMAGE_BYTE_ORDER; - scrp->bitmapScanlinePad = BITMAP_SCANLINE_PAD; - if (scrp->depth < 8) { - /* Planar modes need these settings */ - scrp->bitmapScanlineUnit = 8; - scrp->bitmapBitOrder = MSBFirst; - } else { - scrp->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; - scrp->bitmapBitOrder = BITMAP_BIT_ORDER; - } - - /* - * If an unusual depth is required, add it to scrp->formats. The formats - * for the common depths are handled globally in InitOutput - */ - switch (scrp->depth) { - case 1: - case 4: - case 8: - case 15: - case 16: - case 24: - /* Common depths. Nothing to do for them */ - break; - default: - if (!xf86AddPixFormat(scrp, scrp->depth, 0, 0)) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Can't add pixmap format for depth %d\n", scrp->depth); - return FALSE; - } - } - - /* Initialise the framebuffer format for this screen */ - scrp->fbFormat.depth = scrp->depth; - scrp->fbFormat.bitsPerPixel = scrp->bitsPerPixel; - scrp->fbFormat.scanlinePad = BITMAP_SCANLINE_PAD; - - return TRUE; -} - -/* - * Print out the selected depth and bpp. - */ -void -xf86PrintDepthBpp(ScrnInfoPtr scrp) -{ - xf86DrvMsg(scrp->scrnIndex, scrp->depthFrom, "Depth %d, ", scrp->depth); - xf86Msg(scrp->bitsPerPixelFrom, "framebuffer bpp %d\n", scrp->bitsPerPixel); -} - -/* - * xf86SetWeight sets scrp->weight, scrp->mask, scrp->offset, and for depths - * greater than MAX_PSEUDO_DEPTH also scrp->rgbBits. - */ -Bool -xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask) -{ - MessageType weightFrom = X_DEFAULT; - - scrp->weight.red = 0; - scrp->weight.green = 0; - scrp->weight.blue = 0; - - if (xf86Weight.red > 0 && xf86Weight.green > 0 && xf86Weight.blue > 0) { - scrp->weight = xf86Weight; - weightFrom = X_CMDLINE; - } else if (scrp->display->weight.red > 0 && scrp->display->weight.green > 0 - && scrp->display->weight.blue > 0) { - scrp->weight = scrp->display->weight; - weightFrom = X_CONFIG; - } else if (weight.red > 0 && weight.green > 0 && weight.blue > 0) { - scrp->weight = weight; - } else { - switch (scrp->depth) { - case 1: - case 4: - case 8: - scrp->weight.red = scrp->weight.green = - scrp->weight.blue = scrp->rgbBits; - break; - case 15: - scrp->weight.red = scrp->weight.green = scrp->weight.blue = 5; - break; - case 16: - scrp->weight.red = scrp->weight.blue = 5; - scrp->weight.green = 6; - break; - case 24: - scrp->weight.red = scrp->weight.green = scrp->weight.blue = 8; - break; - case 30: - scrp->weight.red = scrp->weight.green = scrp->weight.blue = 10; - break; - } - } - - if (scrp->weight.red) - xf86DrvMsg(scrp->scrnIndex, weightFrom, "RGB weight %d%d%d\n", - (int)scrp->weight.red, (int)scrp->weight.green, - (int)scrp->weight.blue); - - if (scrp->depth > MAX_PSEUDO_DEPTH && - (scrp->depth != scrp->weight.red + scrp->weight.green + - scrp->weight.blue)) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Weight given (%d%d%d) is inconsistent with the " - "depth (%d)\n", - (int)scrp->weight.red, (int)scrp->weight.green, - (int)scrp->weight.blue, scrp->depth); - return FALSE; - } - if (scrp->depth > MAX_PSEUDO_DEPTH && scrp->weight.red) { - /* - * XXX Does this even mean anything for TrueColor visuals? - * If not, we shouldn't even be setting it here. However, this - * matches the behaviour of 3.x versions of XFree86. - */ - scrp->rgbBits = scrp->weight.red; - if (scrp->weight.green > scrp->rgbBits) - scrp->rgbBits = scrp->weight.green; - if (scrp->weight.blue > scrp->rgbBits) - scrp->rgbBits = scrp->weight.blue; - } - - /* Set the mask and offsets */ - if (mask.red == 0 || mask.green == 0 || mask.blue == 0) { - /* Default to a setting common to PC hardware */ - scrp->offset.red = scrp->weight.green + scrp->weight.blue; - scrp->offset.green = scrp->weight.blue; - scrp->offset.blue = 0; - scrp->mask.red = ((1 << scrp->weight.red) - 1) << scrp->offset.red; - scrp->mask.green = ((1 << scrp->weight.green) - 1) - << scrp->offset.green; - scrp->mask.blue = (1 << scrp->weight.blue) - 1; - } else { - /* Initialise to the values passed */ - scrp->mask.red = mask.red; - scrp->mask.green = mask.green; - scrp->mask.blue = mask.blue; - scrp->offset.red = ffs(mask.red); - scrp->offset.green = ffs(mask.green); - scrp->offset.blue = ffs(mask.blue); - } - return TRUE; -} - -Bool -xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual) -{ - MessageType visualFrom = X_DEFAULT; - - if (defaultColorVisualClass >= 0) { - scrp->defaultVisual = defaultColorVisualClass; - visualFrom = X_CMDLINE; - } else if (scrp->display->defaultVisual >= 0) { - scrp->defaultVisual = scrp->display->defaultVisual; - visualFrom = X_CONFIG; - } else if (visual >= 0) { - scrp->defaultVisual = visual; - } else { - if (scrp->depth == 1) - scrp->defaultVisual = StaticGray; - else if (scrp->depth == 4) - scrp->defaultVisual = StaticColor; - else if (scrp->depth <= MAX_PSEUDO_DEPTH) - scrp->defaultVisual = PseudoColor; - else - scrp->defaultVisual = TrueColor; - } - switch (scrp->defaultVisual) { - case StaticGray: - case GrayScale: - case StaticColor: - case PseudoColor: - case TrueColor: - case DirectColor: - xf86DrvMsg(scrp->scrnIndex, visualFrom, "Default visual is %s\n", - xf86VisualNames[scrp->defaultVisual]); - return TRUE; - default: - - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Invalid default visual class (%d)\n", scrp->defaultVisual); - return FALSE; - } -} - -#define TEST_GAMMA(g) \ - (g).red > GAMMA_ZERO || (g).green > GAMMA_ZERO || (g).blue > GAMMA_ZERO - -#define SET_GAMMA(g) \ - (g) > GAMMA_ZERO ? (g) : 1.0 - -Bool -xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma) -{ - MessageType from = X_DEFAULT; -#if 0 - xf86MonPtr DDC = (xf86MonPtr)(scrp->monitor->DDC); -#endif - if (TEST_GAMMA(xf86Gamma)) { - from = X_CMDLINE; - scrp->gamma.red = SET_GAMMA(xf86Gamma.red); - scrp->gamma.green = SET_GAMMA(xf86Gamma.green); - scrp->gamma.blue = SET_GAMMA(xf86Gamma.blue); - } else if (TEST_GAMMA(scrp->monitor->gamma)) { - from = X_CONFIG; - scrp->gamma.red = SET_GAMMA(scrp->monitor->gamma.red); - scrp->gamma.green = SET_GAMMA(scrp->monitor->gamma.green); - scrp->gamma.blue = SET_GAMMA(scrp->monitor->gamma.blue); -#if 0 - } else if ( DDC && DDC->features.gamma > GAMMA_ZERO ) { - from = X_PROBED; - scrp->gamma.red = SET_GAMMA(DDC->features.gamma); - scrp->gamma.green = SET_GAMMA(DDC->features.gamma); - scrp->gamma.blue = SET_GAMMA(DDC->features.gamma); - /* EDID structure version 2 gives optional seperate red, green & blue gamma values - * in bytes 0x57-0x59 */ -#endif - } else if (TEST_GAMMA(gamma)) { - scrp->gamma.red = SET_GAMMA(gamma.red); - scrp->gamma.green = SET_GAMMA(gamma.green); - scrp->gamma.blue = SET_GAMMA(gamma.blue); - } else { - scrp->gamma.red = 1.0; - scrp->gamma.green = 1.0; - scrp->gamma.blue = 1.0; - } - /* Pretend we succeeded if we support better a gamma system. - * This avoids a confusing message. - */ - if (xf86_crtc_supports_gamma(scrp)) - return TRUE; - xf86DrvMsg(scrp->scrnIndex, from, - "Using gamma correction (%.1f, %.1f, %.1f)\n", - scrp->gamma.red, scrp->gamma.green, scrp->gamma.blue); - - return TRUE; -} - -#undef TEST_GAMMA -#undef SET_GAMMA - - -/* - * Set the DPI from the command line option. XXX should allow it to be - * calculated from the widthmm/heightmm values. - */ - -#undef MMPERINCH -#define MMPERINCH 25.4 - -void -xf86SetDpi(ScrnInfoPtr pScrn, int x, int y) -{ - MessageType from = X_DEFAULT; - xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC); - int ddcWidthmm, ddcHeightmm; - int widthErr, heightErr; - - /* XXX Maybe there is no need for widthmm/heightmm in ScrnInfoRec */ - pScrn->widthmm = pScrn->monitor->widthmm; - pScrn->heightmm = pScrn->monitor->heightmm; - - if (DDC && (DDC->features.hsize > 0 && DDC->features.vsize > 0) ) { - /* DDC gives display size in mm for individual modes, - * but cm for monitor - */ - ddcWidthmm = DDC->features.hsize * 10; /* 10mm in 1cm */ - ddcHeightmm = DDC->features.vsize * 10; /* 10mm in 1cm */ - } else { - ddcWidthmm = ddcHeightmm = 0; - } - - if (monitorResolution > 0) { - pScrn->xDpi = monitorResolution; - pScrn->yDpi = monitorResolution; - from = X_CMDLINE; - } else if (pScrn->widthmm > 0 || pScrn->heightmm > 0) { - from = X_CONFIG; - if (pScrn->widthmm > 0) { - pScrn->xDpi = - (int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm); - } - if (pScrn->heightmm > 0) { - pScrn->yDpi = - (int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm); - } - if (pScrn->xDpi > 0 && pScrn->yDpi <= 0) - pScrn->yDpi = pScrn->xDpi; - if (pScrn->yDpi > 0 && pScrn->xDpi <= 0) - pScrn->xDpi = pScrn->yDpi; - xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n", - pScrn->widthmm, pScrn->heightmm); - - /* Warn if config and probe disagree about display size */ - if ( ddcWidthmm && ddcHeightmm ) { - if (pScrn->widthmm > 0) { - widthErr = abs(ddcWidthmm - pScrn->widthmm); - } else { - widthErr = 0; - } - if (pScrn->heightmm > 0) { - heightErr = abs(ddcHeightmm - pScrn->heightmm); - } else { - heightErr = 0; - } - if (widthErr>10 || heightErr>10) { - /* Should include config file name for monitor here */ - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Probed monitor is %dx%d mm, using Displaysize %dx%d mm\n", - ddcWidthmm,ddcHeightmm, pScrn->widthmm,pScrn->heightmm); - } - } - } else if ( ddcWidthmm && ddcHeightmm ) { - from = X_PROBED; - xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n", - ddcWidthmm, ddcHeightmm ); - pScrn->widthmm = ddcWidthmm; - pScrn->heightmm = ddcHeightmm; - if (pScrn->widthmm > 0) { - pScrn->xDpi = - (int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm); - } - if (pScrn->heightmm > 0) { - pScrn->yDpi = - (int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm); - } - if (pScrn->xDpi > 0 && pScrn->yDpi <= 0) - pScrn->yDpi = pScrn->xDpi; - if (pScrn->yDpi > 0 && pScrn->xDpi <= 0) - pScrn->xDpi = pScrn->yDpi; - } else { - if (x > 0) - pScrn->xDpi = x; - else - pScrn->xDpi = DEFAULT_DPI; - if (y > 0) - pScrn->yDpi = y; - else - pScrn->yDpi = DEFAULT_DPI; - } - xf86DrvMsg(pScrn->scrnIndex, from, "DPI set to (%d, %d)\n", - pScrn->xDpi, pScrn->yDpi); -} - -#undef MMPERINCH - - -void -xf86SetBlackWhitePixels(ScreenPtr pScreen) -{ - if (xf86FlipPixels) { - pScreen->whitePixel = 0; - pScreen->blackPixel = 1; - } else { - pScreen->whitePixel = 1; - pScreen->blackPixel = 0; - } -} - -/* - * xf86SetRootClip -- - * Enable or disable rendering to the screen by - * setting the root clip list and revalidating - * all of the windows - */ - -static void -xf86SetRootClip (ScreenPtr pScreen, Bool enable) -{ - WindowPtr pWin = WindowTable[pScreen->myNum]; - WindowPtr pChild; - Bool WasViewable = (Bool)(pWin->viewable); - Bool anyMarked = FALSE; - 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; - } - } - - /* - * Use REGION_BREAK to avoid optimizations in ValidateTree - * that assume the root borderClip can't change well, normally - * it doesn't...) - */ - if (enable) - { - box.x1 = 0; - box.y1 = 0; - box.x2 = pScreen->width; - box.y2 = pScreen->height; - REGION_INIT (pScreen, &pWin->winSize, &box, 1); - REGION_INIT (pScreen, &pWin->borderSize, &box, 1); - if (WasViewable) - REGION_RESET(pScreen, &pWin->borderClip, &box); - pWin->drawable.width = pScreen->width; - pWin->drawable.height = pScreen->height; - 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->firstChild) - { - anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, - pWin->firstChild, - (WindowPtr *)NULL); - } - else - { - (*pScreen->MarkWindow) (pWin); - anyMarked = TRUE; - } - - - if (anyMarked) - (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); - } - - if (WasViewable) - { - if (anyMarked) - (*pScreen->HandleExposures)(pWin); - if (anyMarked && pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); - } - if (pWin->realized) - WindowsRestructured (); - FlushAllOutput (); -} - -/* - * Function to enable/disable access to the frame buffer - * - * This is used when VT switching and when entering/leaving DGA direct mode. - * - * This has been rewritten again to eliminate the saved pixmap. The - * devPrivate field in the screen pixmap is set to NULL to catch code - * accidentally referencing the frame buffer while the X server is not - * supposed to touch it. - * - * Here, we exchange the pixmap private data, rather than the pixmaps - * themselves to avoid having to find and change any references to the screen - * pixmap such as GC's, window privates etc. This also means that this code - * does not need to know exactly how the pixmap pixels are accessed. Further, - * this exchange is >not< done through the screen's ModifyPixmapHeader() - * vector. This means the called frame buffer code layers can determine - * whether they are switched in or out by keeping track of the root pixmap's - * private data, and therefore don't need to access pScrnInfo->vtSema. - */ -void -xf86EnableDisableFBAccess(int scrnIndex, Bool enable) -{ - ScrnInfoPtr pScrnInfo = xf86Screens[scrnIndex]; - ScreenPtr pScreen = pScrnInfo->pScreen; - PixmapPtr pspix; - - pspix = (*pScreen->GetScreenPixmap) (pScreen); - if (enable) - { - /* - * Restore the screen pixmap devPrivate field - */ - pspix->devPrivate = pScrnInfo->pixmapPrivate; - /* - * Restore all of the clip lists on the screen - */ - if (!xf86Resetting) - xf86SetRootClip (pScreen, TRUE); - - } - else - { - /* - * Empty all of the clip lists on the screen - */ - xf86SetRootClip (pScreen, FALSE); - /* - * save the screen pixmap devPrivate field and - * replace it with NULL so accidental references - * to the frame buffer are caught - */ - pScrnInfo->pixmapPrivate = pspix->devPrivate; - pspix->devPrivate.ptr = NULL; - } -} - -/* Print driver messages in the standard format */ - -#undef PREFIX_SIZE -#define PREFIX_SIZE 14 - -void -xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, - va_list args) -{ - char *tmpFormat; - - /* Prefix the scrnIndex name to the format string. */ - if (scrnIndex >= 0 && scrnIndex < xf86NumScreens && - xf86Screens[scrnIndex]->name) { - tmpFormat = xalloc(strlen(format) + - strlen(xf86Screens[scrnIndex]->name) + - PREFIX_SIZE + 1); - if (!tmpFormat) - return; - - snprintf(tmpFormat, PREFIX_SIZE + 1, "%s(%d): ", - xf86Screens[scrnIndex]->name, scrnIndex); - - strcat(tmpFormat, format); - LogVMessageVerb(type, verb, tmpFormat, args); - xfree(tmpFormat); - } else - LogVMessageVerb(type, verb, format, args); -} -#undef PREFIX_SIZE - -/* Print driver messages, with verbose level specified directly */ -void -xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, - ...) -{ - va_list ap; - - va_start(ap, format); - xf86VDrvMsgVerb(scrnIndex, type, verb, format, ap); - va_end(ap); -} - -/* Print driver messages, with verbose level of 1 (default) */ -void -xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - xf86VDrvMsgVerb(scrnIndex, type, 1, format, ap); - va_end(ap); -} - -/* Print non-driver messages with verbose level specified directly */ -void -xf86MsgVerb(MessageType type, int verb, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - xf86VDrvMsgVerb(-1, type, verb, format, ap); - va_end(ap); -} - -/* Print non-driver messages with verbose level of 1 (default) */ -void -xf86Msg(MessageType type, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - xf86VDrvMsgVerb(-1, type, 1, format, ap); - va_end(ap); -} - -/* Just like ErrorF, but with the verbose level checked */ -void -xf86ErrorFVerb(int verb, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - if (xf86Verbose >= verb || xf86LogVerbose >= verb) - LogVWrite(verb, format, ap); - va_end(ap); -} - -/* Like xf86ErrorFVerb, but with an implied verbose level of 1 */ -void -xf86ErrorF(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - if (xf86Verbose >= 1 || xf86LogVerbose >= 1) - LogVWrite(1, format, ap); - va_end(ap); -} - - -void -xf86LogInit(void) -{ - char *lf = NULL; - -#define LOGSUFFIX ".log" -#define LOGOLDSUFFIX ".old" - - /* Get the log file name */ - if (xf86LogFileFrom == X_DEFAULT) { - /* Append the display number and ".log" */ - lf = malloc(strlen(xf86LogFile) + strlen("%s") + - strlen(LOGSUFFIX) + 1); - if (!lf) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(lf, "%s%%s" LOGSUFFIX, xf86LogFile); - xf86LogFile = lf; - } - - xf86LogFile = LogInit(xf86LogFile, LOGOLDSUFFIX); - xf86LogFileWasOpened = TRUE; - - xf86SetVerbosity(xf86Verbose); - xf86SetLogVerbosity(xf86LogVerbose); - -#undef LOGSUFFIX -#undef LOGOLDSUFFIX - - free(lf); -} - -void -xf86CloseLog(void) -{ - LogClose(); -} - - -/* - * Drivers can use these for using their own SymTabRecs. - */ - -const char * -xf86TokenToString(SymTabPtr table, int token) -{ - int i; - - for (i = 0; table[i].token >= 0 && table[i].token != token; i++) - ; - - if (table[i].token < 0) - return NULL; - else - return(table[i].name); -} - -int -xf86StringToToken(SymTabPtr table, const char *string) -{ - int i; - - if (string == NULL) - return -1; - - for (i = 0; table[i].token >= 0 && xf86NameCmp(string, table[i].name); i++) - ; - - return(table[i].token); -} - -/* - * helper to display the clocks found on a card - */ -void -xf86ShowClocks(ScrnInfoPtr scrp, MessageType from) -{ - int j; - - xf86DrvMsg(scrp->scrnIndex, from, "Pixel clocks available:"); - for (j=0; j < scrp->numClocks; j++) { - if ((j % 4) == 0) { - xf86ErrorF("\n"); - xf86DrvMsg(scrp->scrnIndex, from, "pixel clocks:"); - } - xf86ErrorF(" %7.3f", (double)scrp->clock[j] / 1000.0); - } - xf86ErrorF("\n"); -} - - -/* - * This prints out the driver identify message, including the names of - * the supported chipsets. - * - * XXX This makes assumptions about the line width, etc. Maybe we could - * use a more general "pretty print" function for messages. - */ -void -xf86PrintChipsets(const char *drvname, const char *drvmsg, SymTabPtr chips) -{ - int len, i; - - len = 6 + strlen(drvname) + 2 + strlen(drvmsg) + 2; - xf86Msg(X_INFO, "%s: %s:", drvname, drvmsg); - for (i = 0; chips[i].name != NULL; i++) { - if (i != 0) { - xf86ErrorF(","); - len++; - } - if (len + 2 + strlen(chips[i].name) < 78) { - xf86ErrorF(" "); - len++; - } else { - xf86ErrorF("\n\t"); - len = 8; - } - xf86ErrorF("%s", chips[i].name); - len += strlen(chips[i].name); - } - xf86ErrorF("\n"); -} - - -int -xf86MatchDevice(const char *drivername, GDevPtr **sectlist) -{ - GDevPtr gdp, *pgdp = NULL; - confScreenPtr screensecptr; - int i,j; - - if (sectlist) - *sectlist = NULL; - - if (xf86DoConfigure && xf86DoConfigurePass1) return 1; - - /* - * This is a very important function that matches the device sections - * as they show up in the config file with the drivers that the server - * loads at run time. - * - * ChipProbe can call - * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist) - * with its driver name. The function allocates an array of GDevPtr and - * returns this via sectlist and returns the number of elements in - * this list as return value. 0 means none found, -1 means fatal error. - * - * It can figure out which of the Device sections to use for which card - * (using things like the Card statement, etc). For single headed servers - * there will of course be just one such Device section. - */ - i = 0; - - /* - * first we need to loop over all the Screens sections to get to all - * 'active' device sections - */ - for (j=0; xf86ConfigLayout.screens[j].screen != NULL; j++) { - screensecptr = xf86ConfigLayout.screens[j].screen; - if ((screensecptr->device->driver != NULL) - && (xf86NameCmp( screensecptr->device->driver,drivername) == 0) - && (! screensecptr->device->claimed)) { - /* - * we have a matching driver that wasn't claimed, yet - */ - pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr)); - pgdp[i++] = screensecptr->device; - } - } - - /* Then handle the inactive devices */ - j = 0; - while (xf86ConfigLayout.inactives[j].identifier) { - gdp = &xf86ConfigLayout.inactives[j]; - if (gdp->driver && !gdp->claimed && - !xf86NameCmp(gdp->driver,drivername)) { - /* we have a matching driver that wasn't claimed yet */ - pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr)); - pgdp[i++] = gdp; - } - j++; - } - - /* - * make the array NULL terminated and return its address - */ - if (i) - pgdp[i] = NULL; - - if (sectlist) - *sectlist = pgdp; - else - xfree(pgdp); - return i; -} - -static Bool -pciDeviceHasBars(struct pci_device *pci) -{ - int i; - - for (i = 0; i < 6; i++) - if (pci->regions[i].size) - return TRUE; - - if (pci->rom_size) - return TRUE; - - return FALSE; -} - -struct Inst { - struct pci_device * pci; - GDevPtr dev; - Bool foundHW; /* PCIid in list of supported chipsets */ - Bool claimed; /* BusID matches with a device section */ - int chip; - int screen; -}; - - -/** - * Find set of unclaimed devices matching a given vendor ID. - * - * Used by drivers to find as yet unclaimed devices matching the specified - * vendor ID. - * - * \param driverName Name of the driver. This is used to find Device - * sections in the config file. - * \param vendorID PCI vendor ID of associated devices. If zero, then - * the true vendor ID must be encoded in the \c PCIid - * fields of the \c PCIchipsets entries. - * \param chipsets Symbol table used to associate chipset names with - * PCI IDs. - * \param devList List of Device sections parsed from the config file. - * \param numDevs Number of entries in \c devList. - * \param drvp Pointer the driver's control structure. - * \param foundEntities Returned list of entity indicies associated with the - * driver. - * - * \returns - * The number of elements in returned in \c foundEntities on success or zero - * on failure. - * - * \todo - * This function does a bit more than short description says. Fill in some - * more of the details of its operation. - * - * \todo - * The \c driverName parameter is redundant. It is the same as - * \c DriverRec::driverName. In a future version of this function, remove - * that parameter. - */ -int -xf86MatchPciInstances(const char *driverName, int vendorID, - SymTabPtr chipsets, PciChipsets *PCIchipsets, - GDevPtr *devList, int numDevs, DriverPtr drvp, - int **foundEntities) -{ - int i,j; - struct pci_device * pPci; - struct pci_device_iterator *iter; - struct Inst *instances = NULL; - int numClaimedInstances = 0; - int allocatedInstances = 0; - int numFound = 0; - SymTabRec *c; - PciChipsets *id; - int *retEntities = NULL; - - *foundEntities = NULL; - - - /* Each PCI device will contribute at least one entry. Each device - * section can contribute at most one entry. The sum of the two is - * guaranteed to be larger than the maximum possible number of entries. - * Do this calculation and memory allocation once now to eliminate the - * need for realloc calls inside the loop. - */ - if (!(xf86DoConfigure && xf86DoConfigurePass1)) { - unsigned max_entries = numDevs; - - iter = pci_slot_match_iterator_create(NULL); - while ((pPci = pci_device_next(iter)) != NULL) { - max_entries++; - } - - pci_iterator_destroy(iter); - instances = xnfalloc(max_entries * sizeof(struct Inst)); - } - - iter = pci_slot_match_iterator_create(NULL); - while ((pPci = pci_device_next(iter)) != NULL) { - unsigned device_class = pPci->device_class; - Bool foundVendor = FALSE; - - - /* Convert the pre-PCI 2.0 device class for a VGA adapter to the - * 2.0 version of the same class. - */ - if ( device_class == 0x00000101 ) { - device_class = 0x00030000; - } - - - /* Find PCI devices that match the given vendor ID. The vendor ID is - * either specified explicitly as a parameter to the function or - * implicitly encoded in the high bits of id->PCIid. - * - * The first device with a matching vendor is recorded, even if the - * device ID doesn't match. This is done because the Device section - * in the xorg.conf file can over-ride the device ID. A matching PCI - * ID might not be found now, but after the device ID over-ride is - * applied there /might/ be a match. - */ - for (id = PCIchipsets; id->PCIid != -1; id++) { - const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16) - | vendorID; - const unsigned device_id = (id->PCIid & 0x0000FFFF); - const unsigned match_class = 0x00030000 | id->PCIid; - - if ((vendor_id == pPci->vendor_id) - || ((vendorID == PCI_VENDOR_GENERIC) && (match_class == device_class))) { - if (!foundVendor && (instances != NULL)) { - ++allocatedInstances; - instances[allocatedInstances - 1].pci = pPci; - instances[allocatedInstances - 1].dev = NULL; - instances[allocatedInstances - 1].claimed = FALSE; - instances[allocatedInstances - 1].foundHW = FALSE; - instances[allocatedInstances - 1].screen = 0; - } - - foundVendor = TRUE; - - if ( (device_id == pPci->device_id) - || ((vendorID == PCI_VENDOR_GENERIC) - && (match_class == device_class)) ) { - if ( instances != NULL ) { - instances[allocatedInstances - 1].foundHW = TRUE; - instances[allocatedInstances - 1].chip = id->numChipset; - } - - - if ( xf86DoConfigure && xf86DoConfigurePass1 ) { - if (xf86CheckPciSlot(pPci)) { - GDevPtr pGDev = - xf86AddBusDeviceToConfigure(drvp->driverName, - BUS_PCI, pPci, -1); - if (pGDev) { - /* After configure pass 1, chipID and chipRev - * are treated as over-rides, so clobber them - * here. - */ - pGDev->chipID = -1; - pGDev->chipRev = -1; - } - - numFound++; - } - } - else { - numFound++; - } - - break; - } - } - } - } - - pci_iterator_destroy(iter); - - - /* In "probe only" or "configure" mode (signaled by instances being NULL), - * our work is done. Return the number of detected devices. - */ - if ( instances == NULL ) { - return numFound; - } - - - /* - * This may be debatable, but if no PCI devices with a matching vendor - * type is found, return zero now. It is probably not desirable to - * allow the config file to override this. - */ - if (allocatedInstances <= 0) { - xfree(instances); - return 0; - } - - - DebugF("%s instances found: %d\n", driverName, allocatedInstances); - - /* - * Check for devices that need duplicated instances. This is required - * when there is more than one screen per entity. - * - * XXX This currently doesn't work for cases where the BusID isn't - * specified explicitly in the config file. - */ - - for (j = 0; j < numDevs; j++) { - if (devList[j]->screen > 0 && devList[j]->busID - && *devList[j]->busID) { - for (i = 0; i < allocatedInstances; i++) { - pPci = instances[i].pci; - if (xf86ComparePciBusString(devList[j]->busID, - PCI_MAKE_BUS( pPci->domain, pPci->bus ), - pPci->dev, - pPci->func)) { - allocatedInstances++; - instances[allocatedInstances - 1] = instances[i]; - instances[allocatedInstances - 1].screen = - devList[j]->screen; - numFound++; - break; - } - } - } - } - - for (i = 0; i < allocatedInstances; i++) { - GDevPtr dev = NULL; - GDevPtr devBus = NULL; - - pPci = instances[i].pci; - for (j = 0; j < numDevs; j++) { - if (devList[j]->busID && *devList[j]->busID) { - if (xf86ComparePciBusString(devList[j]->busID, - PCI_MAKE_BUS( pPci->domain, pPci->bus ), - pPci->dev, - pPci->func) && - devList[j]->screen == instances[i].screen) { - - if (devBus) - xf86MsgVerb(X_WARNING,0, - "%s: More than one matching Device section for " - "instances\n\t(BusID: %s) found: %s\n", - driverName, devList[j]->busID, - devList[j]->identifier); - else - devBus = devList[j]; - } - } else { - /* - * if device section without BusID is found - * only assign to it to the primary device. - */ - if (xf86IsPrimaryPci(pPci)) { - xf86Msg(X_PROBED, "Assigning device section with no busID" - " to primary device\n"); - if (dev || devBus) - xf86MsgVerb(X_WARNING, 0, - "%s: More than one matching Device section " - "found: %s\n", driverName, devList[j]->identifier); - else - dev = devList[j]; - } - } - } - if (devBus) dev = devBus; /* busID preferred */ - if (!dev) { - if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) { - xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " - "for instance (BusID PCI:%u@%u:%u:%u) found\n", - driverName, pPci->domain, pPci->bus, pPci->dev, - pPci->func); - } - } else { - numClaimedInstances++; - instances[i].claimed = TRUE; - instances[i].dev = dev; - } - } - DebugF("%s instances found: %d\n", driverName, numClaimedInstances); - /* - * Now check that a chipset or chipID override in the device section - * is valid. Chipset has precedence over chipID. - * If chipset is not valid ignore BusSlot completely. - */ - for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { - MessageType from = X_PROBED; - - if (!instances[i].claimed) { - continue; - } - if (instances[i].dev->chipset) { - for (c = chipsets; c->token >= 0; c++) { - if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0) - break; - } - if (c->token == -1) { - instances[i].claimed = FALSE; - numClaimedInstances--; - xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " - "section \"%s\" isn't valid for this driver\n", - driverName, instances[i].dev->chipset, - instances[i].dev->identifier); - } else { - instances[i].chip = c->token; - - for (id = PCIchipsets; id->numChipset >= 0; id++) { - if (id->numChipset == instances[i].chip) - break; - } - if(id->numChipset >=0){ - xf86Msg(X_CONFIG,"Chipset override: %s\n", - instances[i].dev->chipset); - from = X_CONFIG; - } else { - instances[i].claimed = FALSE; - numClaimedInstances--; - xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " - "section \"%s\" isn't a valid PCI chipset\n", - driverName, instances[i].dev->chipset, - instances[i].dev->identifier); - } - } - } else if (instances[i].dev->chipID > 0) { - for (id = PCIchipsets; id->numChipset >= 0; id++) { - if (id->PCIid == instances[i].dev->chipID) - break; - } - if (id->numChipset == -1) { - instances[i].claimed = FALSE; - numClaimedInstances--; - xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device " - "section \"%s\" isn't valid for this driver\n", - driverName, instances[i].dev->chipID, - instances[i].dev->identifier); - } else { - instances[i].chip = id->numChipset; - - xf86Msg( X_CONFIG,"ChipID override: 0x%04X\n", - instances[i].dev->chipID); - from = X_CONFIG; - } - } else if (!instances[i].foundHW) { - /* - * This means that there was no override and the PCI chipType - * doesn't match one that is supported - */ - instances[i].claimed = FALSE; - numClaimedInstances--; - } - if (instances[i].claimed == TRUE){ - for (c = chipsets; c->token >= 0; c++) { - if (c->token == instances[i].chip) - break; - } - xf86Msg(from,"Chipset %s found\n", - c->name); - } - } - - /* - * Of the claimed instances, check that another driver hasn't already - * claimed its slot. - */ - numFound = 0; - for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { - - if (!instances[i].claimed) - continue; - pPci = instances[i].pci; - - - /* - * Allow the same entity to be used more than once for devices with - * multiple screens per entity. This assumes implicitly that there - * will be a screen == 0 instance. - * - * XXX Need to make sure that two different drivers don't claim - * the same screen > 0 instance. - */ - if (instances[i].screen == 0 && !xf86CheckPciSlot( pPci )) - continue; - - DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", - driverName, pPci->bus, pPci->dev, pPci->func); - - /* Allocate an entry in the lists to be returned */ - numFound++; - retEntities = xnfrealloc(retEntities, numFound * sizeof(int)); - retEntities[numFound - 1] = xf86ClaimPciSlot( pPci, drvp, - instances[i].chip, - instances[i].dev, - instances[i].dev->active); - if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) { - for (j = 0; j < xf86NumEntities; j++) { - EntityPtr pEnt = xf86Entities[j]; - if (pEnt->bus.type != BUS_PCI) - continue; - if (pEnt->bus.id.pci == pPci) { - retEntities[numFound - 1] = j; - xf86AddDevToEntity(j, instances[i].dev); - break; - } - } - } - } - xfree(instances); - if (numFound > 0) { - *foundEntities = retEntities; - } - - return numFound; -} - -/* - * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ... - */ -void -xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc)(ScrnInfoPtr, int), - void (*ProtectRegs)(ScrnInfoPtr, Bool), - void (*BlankScreen)(ScrnInfoPtr, Bool), IOADDRESS vertsyncreg, - int maskval, int knownclkindex, int knownclkvalue) -{ - register int status = vertsyncreg; - unsigned long i, cnt, rcnt, sync; - - /* First save registers that get written on */ - (*ClockFunc)(pScrn, CLK_REG_SAVE); - - if (num > MAXCLOCKS) - num = MAXCLOCKS; - - for (i = 0; i < num; i++) - { - if (ProtectRegs) - (*ProtectRegs)(pScrn, TRUE); - if (!(*ClockFunc)(pScrn, i)) - { - pScrn->clock[i] = -1; - continue; - } - if (ProtectRegs) - (*ProtectRegs)(pScrn, FALSE); - if (BlankScreen) - (*BlankScreen)(pScrn, FALSE); - - usleep(50000); /* let VCO stabilise */ - - cnt = 0; - sync = 200000; - - while ((inb(status) & maskval) == 0x00) - if (sync-- == 0) goto finish; - /* Something appears to be happening, so reset sync count */ - sync = 200000; - while ((inb(status) & maskval) == maskval) - if (sync-- == 0) goto finish; - /* Something appears to be happening, so reset sync count */ - sync = 200000; - while ((inb(status) & maskval) == 0x00) - if (sync-- == 0) goto finish; - - for (rcnt = 0; rcnt < 5; rcnt++) - { - while (!(inb(status) & maskval)) - cnt++; - while ((inb(status) & maskval)) - cnt++; - } - -finish: - pScrn->clock[i] = cnt ? cnt : -1; - if (BlankScreen) - (*BlankScreen)(pScrn, TRUE); - } - - for (i = 0; i < num; i++) - { - if (i != knownclkindex) - { - if (pScrn->clock[i] == -1) - { - pScrn->clock[i] = 0; - } - else - { - pScrn->clock[i] = (int)(0.5 + - (((float)knownclkvalue) * pScrn->clock[knownclkindex]) / - (pScrn->clock[i])); - /* Round to nearest 10KHz */ - pScrn->clock[i] += 5; - pScrn->clock[i] /= 10; - pScrn->clock[i] *= 10; - } - } - } - - pScrn->clock[knownclkindex] = knownclkvalue; - pScrn->numClocks = num; - - /* Restore registers that were written on */ - (*ClockFunc)(pScrn, CLK_REG_RESTORE); -} - -const char * -xf86GetVisualName(int visual) -{ - if (visual < 0 || visual > DirectColor) - return NULL; - - return xf86VisualNames[visual]; -} - - -int -xf86GetVerbosity(void) -{ - return max(xf86Verbose, xf86LogVerbose); -} - -Pix24Flags -xf86GetPix24(void) -{ - return xf86Info.pixmap24; -} - - -int -xf86GetDepth(void) -{ - return xf86Depth; -} - - -rgb -xf86GetWeight(void) -{ - return xf86Weight; -} - - -Gamma -xf86GetGamma(void) -{ - return xf86Gamma; -} - - -Bool -xf86GetFlipPixels(void) -{ - return xf86FlipPixels; -} - - -const char * -xf86GetServerName(void) -{ - return xf86ServerName; -} - - -Bool -xf86ServerIsExiting(void) -{ - return (dispatchException & DE_TERMINATE) == DE_TERMINATE; -} - - -Bool -xf86ServerIsResetting(void) -{ - return xf86Resetting; -} - - -Bool -xf86ServerIsInitialising(void) -{ - return xf86Initialising; -} - - -Bool -xf86ServerIsOnlyDetecting(void) -{ - return xf86DoConfigure; -} - - -Bool -xf86CaughtSignal(void) -{ - return xf86Info.caughtSignal; -} - - -Bool -xf86GetVidModeAllowNonLocal(void) -{ - return xf86Info.vidModeAllowNonLocal; -} - - -Bool -xf86GetVidModeEnabled(void) -{ - return xf86Info.vidModeEnabled; -} - -Bool -xf86GetModInDevAllowNonLocal(void) -{ - return xf86Info.miscModInDevAllowNonLocal; -} - - -Bool -xf86GetModInDevEnabled(void) -{ - return xf86Info.miscModInDevEnabled; -} - - -Bool -xf86GetAllowMouseOpenFail(void) -{ - return xf86Info.allowMouseOpenFail; -} - - -Bool -xf86IsPc98(void) -{ -#if SUPPORT_PC98 - return xf86Info.pc98; -#else - return FALSE; -#endif -} - -void -xf86DisableRandR(void) -{ - xf86Info.disableRandR = TRUE; - xf86Info.randRFrom = X_PROBED; -} - -CARD32 -xf86GetModuleVersion(pointer module) -{ - return (CARD32)LoaderGetModuleVersion(module); -} - -pointer -xf86LoadDrvSubModule(DriverPtr drv, const char *name) -{ - pointer ret; - int errmaj = 0, errmin = 0; - - ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL, - &errmaj, &errmin); - if (!ret) - LoaderErrorMsg(NULL, name, errmaj, errmin); - return ret; -} - -pointer -xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name) -{ - pointer ret; - int errmaj = 0, errmin = 0; - - ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL, - &errmaj, &errmin); - if (!ret) - LoaderErrorMsg(pScrn->name, name, errmaj, errmin); - return ret; -} - -/* - * xf86LoadOneModule loads a single module. - */ -pointer -xf86LoadOneModule(char *name, pointer opt) -{ - int errmaj, errmin; - char *Name; - pointer mod; - - if (!name) - return NULL; - - /* Normalise the module name */ - Name = xf86NormalizeName(name); - - /* Skip empty names */ - if (Name == NULL) - return NULL; - if (*Name == '\0') { - xfree(Name); - return NULL; - } - - mod = LoadModule(Name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin); - if (!mod) - LoaderErrorMsg(NULL, Name, errmaj, errmin); - xfree(Name); - return mod; -} - -void -xf86UnloadSubModule(pointer mod) -{ - /* - * This is disabled for now. The loader isn't smart enough yet to undo - * relocations. - */ -#if 0 - UnloadSubModule(mod); -#endif -} - -Bool -xf86LoaderCheckSymbol(const char *name) -{ - return LoaderSymbol(name) != NULL; -} - -typedef enum { - OPTION_BACKING_STORE -} BSOpts; - -static const OptionInfoRec BSOptions[] = { - { OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE } -}; - -void -xf86SetBackingStore(ScreenPtr pScreen) -{ - Bool useBS = FALSE; - MessageType from = X_DEFAULT; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - OptionInfoPtr options; - - options = xnfalloc(sizeof(BSOptions)); - (void)memcpy(options, BSOptions, sizeof(BSOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); - - /* check for commandline option here */ - if (xf86bsEnableFlag) { - from = X_CMDLINE; - useBS = TRUE; - } else if (xf86bsDisableFlag) { - from = X_CMDLINE; - useBS = FALSE; - } else { - if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS)) - from = X_CONFIG; - } - xfree(options); - pScreen->backingStoreSupport = useBS ? Always : NotUseful; - if (serverGeneration == 1) - xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n", - useBS ? "enabled" : "disabled"); -} - - -typedef enum { - OPTION_SILKEN_MOUSE -} SMOpts; - -static const OptionInfoRec SMOptions[] = { - { OPTION_SILKEN_MOUSE, "SilkenMouse", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE } -}; - -void -xf86SetSilkenMouse (ScreenPtr pScreen) -{ - Bool useSM = TRUE; - MessageType from = X_DEFAULT; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - OptionInfoPtr options; - - options = xnfalloc(sizeof(SMOptions)); - (void)memcpy(options, SMOptions, sizeof(SMOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); - - /* check for commandline option here */ - /* disable if screen shares resources */ - /* TODO VGA arb disable silken mouse */ - if (xf86silkenMouseDisableFlag) { - from = X_CMDLINE; - useSM = FALSE; - } else { - if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM)) - from = X_CONFIG; - } - xfree(options); - /* - * XXX quick hack to report correctly for OSs that can't do SilkenMouse - * yet. Should handle this differently so that alternate async methods - * work correctly with this too. - */ - pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported(); - if (serverGeneration == 1) - xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n", - pScrn->silkenMouse ? "enabled" : "disabled"); -} - -/* Wrote this function for the PM2 Xv driver, preliminary. */ - -pointer -xf86FindXvOptions(int scrnIndex, int adaptor_index, char *port_name, - char **adaptor_name, pointer *adaptor_options) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - confXvAdaptorPtr adaptor; - int i; - - if (adaptor_index >= pScrn->confScreen->numxvadaptors) { - if (adaptor_name) *adaptor_name = NULL; - if (adaptor_options) *adaptor_options = NULL; - return NULL; - } - - adaptor = &pScrn->confScreen->xvadaptors[adaptor_index]; - if (adaptor_name) *adaptor_name = adaptor->identifier; - if (adaptor_options) *adaptor_options = adaptor->options; - - for (i = 0; i < adaptor->numports; i++) - if (!xf86NameCmp(adaptor->ports[i].identifier, port_name)) - return adaptor->ports[i].options; - - return NULL; -} - -/* Rather than duplicate loader's get OS function, just include it directly */ -#define LoaderGetOS xf86GetOS -#include "loader/os.c" - -/* new RAC */ -/* - * xf86ConfigPciEntityInactive() -- This function can be used - * to configure an inactive entity as well as to reconfigure an - * previously active entity inactive. If the entity has been - * assigned to a screen before it will be removed. If p_chip is - * non-NULL all static resources listed there will be registered. - */ -static void -xf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets *p_chip, - EntityProc init, EntityProc enter, - EntityProc leave, pointer private) -{ - ScrnInfoPtr pScrn; - - if ((pScrn = xf86FindScreenForEntity(pEnt->index))) - xf86RemoveEntityFromScreen(pScrn,pEnt->index); - - /* shared resources are only needed when entity is active: remove */ - xf86SetEntityFuncs(pEnt->index,init,enter,leave,private); -} - -static void -xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init, - EntityProc enter, EntityProc leave, pointer private) -{ - ScrnInfoPtr pScrn; - - if ((pScrn = xf86FindScreenForEntity(pEnt->index))) - xf86RemoveEntityFromScreen(pScrn,pEnt->index); - xf86SetEntityFuncs(pEnt->index,init,enter,leave,private); -} - -ScrnInfoPtr -xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, - PciChipsets *p_chip, void *dummy, EntityProc init, - EntityProc enter, EntityProc leave, pointer private) -{ - EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); - if (!pEnt) return pScrn; - - if (!(pEnt->location.type == BUS_PCI) - || !xf86GetPciInfoForEntity(entityIndex)) { - xfree(pEnt); - return pScrn; - } - if (!pEnt->active) { - xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, - leave, private); - xfree(pEnt); - return pScrn; - } - - if (!pScrn) - pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag); - if (xf86IsEntitySharable(entityIndex)) { - xf86SetEntityShared(entityIndex); - } - xf86AddEntityToScreen(pScrn,entityIndex); - if (xf86IsEntityShared(entityIndex)) { - return pScrn; - } - xfree(pEnt); - - xf86SetEntityFuncs(entityIndex,init,enter,leave,private); - - return pScrn; -} - -ScrnInfoPtr -xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, - EntityProc init, EntityProc enter, EntityProc leave, - pointer private) -{ - EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); - if (!pEnt) return pScrn; - - if (!(pEnt->location.type == BUS_NONE)) { - xfree(pEnt); - return pScrn; - } - - if (!pEnt->active) { - xf86ConfigFbEntityInactive(pEnt, init, enter, leave, private); - xfree(pEnt); - return pScrn; - } - - if (!pScrn) - pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag); - xf86AddEntityToScreen(pScrn,entityIndex); - - xf86SetEntityFuncs(entityIndex,init,enter,leave,private); - - return pScrn; -} - -/* - * - * OBSOLETE ! xf86ConfigActivePciEntity() is an obsolete function. - * It is likely to be removed. Don't use! - */ - -Bool -xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex, - PciChipsets *p_chip, void *dummy, EntityProc init, - EntityProc enter, EntityProc leave, pointer private) -{ - EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); - if (!pEnt) return FALSE; - - if (!pEnt->active || !(pEnt->location.type == BUS_PCI)) { - xfree(pEnt); - return FALSE; - } - xf86AddEntityToScreen(pScrn,entityIndex); - - xfree(pEnt); - if (!xf86SetEntityFuncs(entityIndex,init,enter,leave,private)) - return FALSE; - - return TRUE; -} - -Bool -xf86IsScreenPrimary(int scrnIndex) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - int i; - - for (i=0 ; i < pScrn->numEntities; i++) { - if (xf86IsEntityPrimary(i)) - return TRUE; - } - return FALSE; -} - -int -xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type, - int format, unsigned long len, pointer value ) -{ - RootWinPropPtr pNewProp = NULL, pRegProp; - int i; - Bool existing = FALSE; - - DebugF("xf86RegisterRootWindowProperty(%d, %ld, %ld, %d, %ld, %p)\n", - ScrnIndex, property, type, format, len, value); - - if (ScrnIndex<0 || ScrnIndex>=xf86NumScreens) { - return(BadMatch); - } - - if (xf86RegisteredPropertiesTable && - xf86RegisteredPropertiesTable[ScrnIndex]) { - for (pNewProp = xf86RegisteredPropertiesTable[ScrnIndex]; - pNewProp; pNewProp = pNewProp->next) { - if (strcmp(pNewProp->name, NameForAtom(property)) == 0) - break; - } - } - - if (!pNewProp) { - if ((pNewProp = (RootWinPropPtr)xalloc(sizeof(RootWinProp))) == NULL) { - return(BadAlloc); - } - /* - * We will put this property at the end of the list so that - * the changes are made in the order they were requested. - */ - pNewProp->next = NULL; - } else { - if (pNewProp->name) - xfree(pNewProp->name); - existing = TRUE; - } - - pNewProp->name = xnfstrdup(NameForAtom(property)); - pNewProp->type = type; - pNewProp->format = format; - pNewProp->size = len; - pNewProp->data = value; - - DebugF("new property filled\n"); - - if (NULL==xf86RegisteredPropertiesTable) { - DebugF("creating xf86RegisteredPropertiesTable[] size %d\n", - xf86NumScreens); - if ( NULL==(xf86RegisteredPropertiesTable=(RootWinPropPtr*)xnfcalloc(sizeof(RootWinProp),xf86NumScreens) )) { - return(BadAlloc); - } - for (i=0; inext != NULL) { - DebugF("- next %p\n", (void *)pRegProp); - pRegProp = pRegProp->next; - } - pRegProp->next = pNewProp; - } - } - DebugF("xf86RegisterRootWindowProperty succeeded\n"); - return(Success); -} - -Bool -xf86IsUnblank(int mode) -{ - switch(mode) { - case SCREEN_SAVER_OFF: - case SCREEN_SAVER_FORCER: - return TRUE; - case SCREEN_SAVER_ON: - case SCREEN_SAVER_CYCLE: - return FALSE; - default: - xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode); - return TRUE; - } -} - -void -xf86MotionHistoryAllocate(LocalDevicePtr local) -{ - AllocateMotionHistory(local->dev); -} +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * Authors: Dirk Hohndel + * David Dawes + * ... and others + * + * This file includes the helper functions that the server provides for + * different drivers. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "Pci.h" + +#include +#include "os.h" +#include "servermd.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "gcstruct.h" +#include "loaderProcs.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "micmap.h" +#include "xf86DDC.h" +#include "xf86Xinput.h" +#include "xf86InPriv.h" +#include "mivalidate.h" +#include "xf86Bus.h" +#include "xf86Crtc.h" + +/* For xf86GetClocks */ +#if defined(CSRG_BASED) || defined(__GNU__) +#define HAS_SETPRIORITY +#include +#endif + +static int xf86ScrnInfoPrivateCount = 0; + + +/* Add a pointer to a new DriverRec to xf86DriverList */ + +void +xf86AddDriver(DriverPtr driver, pointer module, int flags) +{ + /* Don't add null entries */ + if (!driver) + return; + + if (xf86DriverList == NULL) + xf86NumDrivers = 0; + + xf86NumDrivers++; + xf86DriverList = xnfrealloc(xf86DriverList, + xf86NumDrivers * sizeof(DriverPtr)); + xf86DriverList[xf86NumDrivers - 1] = xnfalloc(sizeof(DriverRec)); + if (flags & HaveDriverFuncs) + *xf86DriverList[xf86NumDrivers - 1] = *driver; + else { + (void) memset( xf86DriverList[xf86NumDrivers - 1], 0, + sizeof( DriverRec ) ); + (void) memcpy( xf86DriverList[xf86NumDrivers - 1], driver, + sizeof(DriverRec1)); + + } + xf86DriverList[xf86NumDrivers - 1]->module = module; + xf86DriverList[xf86NumDrivers - 1]->refCount = 0; +} + +void +xf86DeleteDriver(int drvIndex) +{ + if (xf86DriverList[drvIndex] + && (!xf86DriverHasEntities(xf86DriverList[drvIndex]))) { + if (xf86DriverList[drvIndex]->module) + UnloadModule(xf86DriverList[drvIndex]->module); + free(xf86DriverList[drvIndex]); + xf86DriverList[drvIndex] = NULL; + } +} + +/* Add a pointer to a new InputDriverRec to xf86InputDriverList */ + +void +xf86AddInputDriver(InputDriverPtr driver, pointer module, int flags) +{ + /* Don't add null entries */ + if (!driver) + return; + + if (xf86InputDriverList == NULL) + xf86NumInputDrivers = 0; + + xf86NumInputDrivers++; + xf86InputDriverList = xnfrealloc(xf86InputDriverList, + xf86NumInputDrivers * sizeof(InputDriverPtr)); + xf86InputDriverList[xf86NumInputDrivers - 1] = + xnfalloc(sizeof(InputDriverRec)); + *xf86InputDriverList[xf86NumInputDrivers - 1] = *driver; + xf86InputDriverList[xf86NumInputDrivers - 1]->module = module; + xf86InputDriverList[xf86NumInputDrivers - 1]->refCount = 0; +} + +void +xf86DeleteInputDriver(int drvIndex) +{ + if (xf86InputDriverList[drvIndex] && xf86InputDriverList[drvIndex]->module) + UnloadModule(xf86InputDriverList[drvIndex]->module); + free(xf86InputDriverList[drvIndex]); + xf86InputDriverList[drvIndex] = NULL; +} + +InputDriverPtr +xf86LookupInputDriver(const char *name) +{ + int i; + + for (i = 0; i < xf86NumInputDrivers; i++) { + if (xf86InputDriverList[i] && xf86InputDriverList[i]->driverName && + xf86NameCmp(name, xf86InputDriverList[i]->driverName) == 0) + return xf86InputDriverList[i]; + } + return NULL; +} + +InputInfoPtr +xf86LookupInput(const char *name) +{ + InputInfoPtr p; + + for (p = xf86InputDevs; p != NULL; p = p->next) { + if (strcmp(name, p->name) == 0) + return p; + } + + return NULL; +} + +/* Allocate a new ScrnInfoRec in xf86Screens */ + +ScrnInfoPtr +xf86AllocateScreen(DriverPtr drv, int flags) +{ + int i; + + if (xf86Screens == NULL) + xf86NumScreens = 0; + + i = xf86NumScreens++; + xf86Screens = xnfrealloc(xf86Screens, xf86NumScreens * sizeof(ScrnInfoPtr)); + xf86Screens[i] = xnfcalloc(sizeof(ScrnInfoRec), 1); + xf86Screens[i]->scrnIndex = i; /* Changes when a screen is removed */ + xf86Screens[i]->origIndex = i; /* This never changes */ + xf86Screens[i]->privates = xnfcalloc(sizeof(DevUnion), + xf86ScrnInfoPrivateCount); + /* + * EnableDisableFBAccess now gets initialized in InitOutput() + * xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess; + */ + + xf86Screens[i]->drv = drv; + drv->refCount++; + xf86Screens[i]->module = DuplicateModule(drv->module, NULL); + + xf86Screens[i]->DriverFunc = drv->driverFunc; + + return xf86Screens[i]; +} + + +/* + * Remove an entry from xf86Screens. Ideally it should free all allocated + * data. To do this properly may require a driver hook. + */ + +void +xf86DeleteScreen(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn; + int i; + + /* First check if the screen is valid */ + if (xf86NumScreens == 0 || xf86Screens == NULL) + return; + + if (scrnIndex > xf86NumScreens - 1) + return; + + if (!(pScrn = xf86Screens[scrnIndex])) + return; + + /* If a FreeScreen function is defined, call it here */ + if (pScrn->FreeScreen != NULL) + pScrn->FreeScreen(scrnIndex, 0); + + while (pScrn->modes) + xf86DeleteMode(&pScrn->modes, pScrn->modes); + + while (pScrn->modePool) + xf86DeleteMode(&pScrn->modePool, pScrn->modePool); + + xf86OptionListFree(pScrn->options); + + if (pScrn->module) + UnloadModule(pScrn->module); + + if (pScrn->drv) + pScrn->drv->refCount--; + + if (pScrn->privates) + free(pScrn->privates); + + xf86ClearEntityListForScreen(scrnIndex); + + free(pScrn); + + /* Move the other entries down, updating their scrnIndex fields */ + + xf86NumScreens--; + + for (i = scrnIndex; i < xf86NumScreens; i++) { + xf86Screens[i] = xf86Screens[i + 1]; + xf86Screens[i]->scrnIndex = i; + /* Also need to take care of the screen layout settings */ + } +} + +/* + * Allocate a private in ScrnInfoRec. + */ + +int +xf86AllocateScrnInfoPrivateIndex(void) +{ + int idx, i; + ScrnInfoPtr pScr; + DevUnion *nprivs; + + idx = xf86ScrnInfoPrivateCount++; + for (i = 0; i < xf86NumScreens; i++) { + pScr = xf86Screens[i]; + nprivs = xnfrealloc(pScr->privates, + xf86ScrnInfoPrivateCount * sizeof(DevUnion)); + /* Zero the new private */ + bzero(&nprivs[idx], sizeof(DevUnion)); + pScr->privates = nprivs; + } + return idx; +} + +/* Allocate a new InputInfoRec and append it to the tail of xf86InputDevs. */ +InputInfoPtr +xf86AllocateInput(InputDriverPtr drv, int flags) +{ + InputInfoPtr new, *prev = NULL; + + if (!(new = calloc(sizeof(InputInfoRec), 1))) + return NULL; + + new->drv = drv; + drv->refCount++; + new->module = DuplicateModule(drv->module, NULL); + + for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next) + ; + + *prev = new; + new->next = NULL; + + return new; +} + + +/* + * Remove an entry from xf86InputDevs. Ideally it should free all allocated + * data. To do this properly may require a driver hook. + */ + +void +xf86DeleteInput(InputInfoPtr pInp, int flags) +{ + InputInfoPtr p; + + /* First check if the inputdev is valid. */ + if (pInp == NULL) + return; + +#if 0 + /* If a free function is defined, call it here. */ + if (pInp->free) + pInp->free(pInp, 0); +#endif + + if (pInp->module) + UnloadModule(pInp->module); + + if (pInp->drv) + pInp->drv->refCount--; + + /* This should *really* be handled in drv->UnInit(dev) call instead, but + * if the driver forgets about it make sure we free it or at least crash + * with flying colors */ + if (pInp->private) + free(pInp->private); + + /* Remove the entry from the list. */ + if (pInp == xf86InputDevs) + xf86InputDevs = pInp->next; + else { + p = xf86InputDevs; + while (p && p->next != pInp) + p = p->next; + if (p) + p->next = pInp->next; + /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ + } + free(pInp); +} + +Bool +xf86AddPixFormat(ScrnInfoPtr pScrn, int depth, int bpp, int pad) +{ + int i; + + if (pScrn->numFormats >= MAXFORMATS) + return FALSE; + + if (bpp <= 0) { + if (depth == 1) + bpp = 1; + else if (depth <= 8) + bpp = 8; + else if (depth <= 16) + bpp = 16; + else if (depth <= 32) + bpp = 32; + else + return FALSE; + } + if (pad <= 0) + pad = BITMAP_SCANLINE_PAD; + + i = pScrn->numFormats++; + pScrn->formats[i].depth = depth; + pScrn->formats[i].bitsPerPixel = bpp; + pScrn->formats[i].scanlinePad = pad; + return TRUE; +} + +/* + * Set the depth we are using based on (in the following order of preference): + * - values given on the command line + * - values given in the config file + * - values provided by the driver + * - an overall default when nothing else is given + * + * Also find a Display subsection matching the depth/bpp found. + * + * Sets the following ScrnInfoRec fields: + * bitsPerPixel, pixmap24, depth, display, imageByteOrder, + * bitmapScanlinePad, bitmapScanlineUnit, bitmapBitOrder, numFormats, + * formats, fbFormat. + */ + +/* Can the screen handle 24 bpp pixmaps */ +#define DO_PIX24(f) ((f & Support24bppFb) || \ + ((f & Support32bppFb) && (f & SupportConvert24to32))) + +/* Can the screen handle 32 bpp pixmaps */ +#define DO_PIX32(f) ((f & Support32bppFb) || \ + ((f & Support24bppFb) && (f & SupportConvert32to24))) + +/* Does the screen prefer 32bpp fb for 24bpp pixmaps */ +#define CHOOSE32FOR24(f) ((f & Support32bppFb) && (f & SupportConvert24to32) \ + && (f & PreferConvert24to32)) + +/* Does the screen prefer 24bpp fb for 32bpp pixmaps */ +#define CHOOSE24FOR32(f) ((f & Support24bppFb) && (f & SupportConvert32to24) \ + && (f & PreferConvert32to24)) + +/* Can the screen handle 32bpp pixmaps for 24bpp fb */ +#define DO_PIX32FOR24(f) ((f & Support24bppFb) && (f & SupportConvert32to24)) + +/* Can the screen handle 24bpp pixmaps for 32bpp fb */ +#define DO_PIX24FOR32(f) ((f & Support32bppFb) && (f & SupportConvert24to32)) + +#ifndef GLOBAL_DEFAULT_DEPTH +#define GLOBAL_DEFAULT_DEPTH 24 +#endif + +Bool +xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int dummy, int fbbpp, + int depth24flags) +{ + int i; + DispPtr disp; + Pix24Flags pix24 = xf86Info.pixmap24; + Bool nomatch = FALSE; + + scrp->bitsPerPixel = -1; + scrp->depth = -1; + scrp->pixmap24 = Pix24DontCare; + scrp->bitsPerPixelFrom = X_DEFAULT; + scrp->depthFrom = X_DEFAULT; + + if (xf86FbBpp > 0) { + scrp->bitsPerPixel = xf86FbBpp; + scrp->bitsPerPixelFrom = X_CMDLINE; + } + + if (xf86Depth > 0) { + scrp->depth = xf86Depth; + scrp->depthFrom = X_CMDLINE; + } + + if (xf86FbBpp < 0 && xf86Depth < 0) { + if (scrp->confScreen->defaultfbbpp > 0) { + scrp->bitsPerPixel = scrp->confScreen->defaultfbbpp; + scrp->bitsPerPixelFrom = X_CONFIG; + } + if (scrp->confScreen->defaultdepth > 0) { + scrp->depth = scrp->confScreen->defaultdepth; + scrp->depthFrom = X_CONFIG; + } + + if (scrp->confScreen->defaultfbbpp <= 0 && + scrp->confScreen->defaultdepth <= 0) { + /* + * Check for DefaultDepth and DefaultFbBpp options in the + * Device sections. + */ + int i; + GDevPtr device; + Bool found = FALSE; + + for (i = 0; i < scrp->numEntities; i++) { + device = xf86GetDevFromEntity(scrp->entityList[i], + scrp->entityInstanceList[i]); + if (device && device->options) { + if (xf86FindOption(device->options, "DefaultDepth")) { + scrp->depth = xf86SetIntOption(device->options, + "DefaultDepth", -1); + scrp->depthFrom = X_CONFIG; + found = TRUE; + } + if (xf86FindOption(device->options, "DefaultFbBpp")) { + scrp->bitsPerPixel = xf86SetIntOption(device->options, + "DefaultFbBpp", + -1); + scrp->bitsPerPixelFrom = X_CONFIG; + found = TRUE; + } + } + if (found) + break; + } + } + } + + /* If none of these is set, pick a default */ + if (scrp->bitsPerPixel < 0 && scrp->depth < 0) { + if (fbbpp > 0 || depth > 0) { + if (fbbpp > 0) + scrp->bitsPerPixel = fbbpp; + if (depth > 0) + scrp->depth = depth; + } else { + scrp->depth = GLOBAL_DEFAULT_DEPTH; + } + } + + /* If any are not given, determine a default for the others */ + + if (scrp->bitsPerPixel < 0) { + /* The depth must be set */ + if (scrp->depth > -1) { + if (scrp->depth == 1) + scrp->bitsPerPixel = 1; + else if (scrp->depth <= 4) + scrp->bitsPerPixel = 4; + else if (scrp->depth <= 8) + scrp->bitsPerPixel = 8; + else if (scrp->depth <= 16) + scrp->bitsPerPixel = 16; + else if (scrp->depth <= 24) { + /* + * Figure out if a choice is possible based on the depth24 + * and pix24 flags. + */ + /* Check pix24 first */ + if (pix24 != Pix24DontCare) { + if (pix24 == Pix24Use32) { + if (DO_PIX32(depth24flags)) { + if (CHOOSE24FOR32(depth24flags)) + scrp->bitsPerPixel = 24; + else + scrp->bitsPerPixel = 32; + } else { + nomatch = TRUE; + } + } else if (pix24 == Pix24Use24) { + if (DO_PIX24(depth24flags)) { + if (CHOOSE32FOR24(depth24flags)) + scrp->bitsPerPixel = 32; + else + scrp->bitsPerPixel = 24; + } else { + nomatch = TRUE; + } + } + } else { + if (DO_PIX32(depth24flags)) { + if (CHOOSE24FOR32(depth24flags)) + scrp->bitsPerPixel = 24; + else + scrp->bitsPerPixel = 32; + } else if (DO_PIX24(depth24flags)) { + if (CHOOSE32FOR24(depth24flags)) + scrp->bitsPerPixel = 32; + else + scrp->bitsPerPixel = 24; + } + } + } else if (scrp->depth <= 32) + scrp->bitsPerPixel = 32; + else { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Specified depth (%d) is greater than 32\n", + scrp->depth); + return FALSE; + } + } else { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "xf86SetDepthBpp: internal error: depth and fbbpp" + " are both not set\n"); + return FALSE; + } + if (scrp->bitsPerPixel < 0) { + if (nomatch) + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Driver can't support depth 24 pixmap format (%d)\n", + PIX24TOBPP(pix24)); + else if ((depth24flags & (Support24bppFb | Support32bppFb)) == + NoDepth24Support) + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Driver can't support depth 24\n"); + else + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Can't find fbbpp for depth 24\n"); + return FALSE; + } + scrp->bitsPerPixelFrom = X_PROBED; + } + + if (scrp->depth <= 0) { + /* bitsPerPixel is already set */ + switch (scrp->bitsPerPixel) { + case 32: + scrp->depth = 24; + break; + default: + /* 1, 4, 8, 16 and 24 */ + scrp->depth = scrp->bitsPerPixel; + break; + } + scrp->depthFrom = X_PROBED; + } + + /* Sanity checks */ + if (scrp->depth < 1 || scrp->depth > 32) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Specified depth (%d) is not in the range 1-32\n", + scrp->depth); + return FALSE; + } + switch (scrp->bitsPerPixel) { + case 1: + case 4: + case 8: + case 16: + case 24: + case 32: + break; + default: + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Specified fbbpp (%d) is not a permitted value\n", + scrp->bitsPerPixel); + return FALSE; + } + if (scrp->depth > scrp->bitsPerPixel) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Specified depth (%d) is greater than the fbbpp (%d)\n", + scrp->depth, scrp->bitsPerPixel); + return FALSE; + } + + /* set scrp->pixmap24 if the driver isn't flexible */ + if (scrp->bitsPerPixel == 24 && !DO_PIX32FOR24(depth24flags)) { + scrp->pixmap24 = Pix24Use24; + } + if (scrp->bitsPerPixel == 32 && !DO_PIX24FOR32(depth24flags)) { + scrp->pixmap24 = Pix24Use32; + } + + /* + * Find the Display subsection matching the depth/fbbpp and initialise + * scrp->display with it. + */ + for (i = 0, disp = scrp->confScreen->displays; + i < scrp->confScreen->numdisplays; i++, disp++) { + if ((disp->depth == scrp->depth && disp->fbbpp == scrp->bitsPerPixel) + || (disp->depth == scrp->depth && disp->fbbpp <= 0) + || (disp->fbbpp == scrp->bitsPerPixel && disp->depth <= 0)) { + scrp->display = disp; + break; + } + } + + /* + * If an exact match can't be found, see if there is one with no + * depth or fbbpp specified. + */ + if (i == scrp->confScreen->numdisplays) { + for (i = 0, disp = scrp->confScreen->displays; + i < scrp->confScreen->numdisplays; i++, disp++) { + if (disp->depth <= 0 && disp->fbbpp <= 0) { + scrp->display = disp; + break; + } + } + } + + /* + * If all else fails, create a default one. + */ + if (i == scrp->confScreen->numdisplays) { + scrp->confScreen->numdisplays++; + scrp->confScreen->displays = + xnfrealloc(scrp->confScreen->displays, + scrp->confScreen->numdisplays * sizeof(DispRec)); + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Creating default Display subsection in Screen section\n" + "\t\"%s\" for depth/fbbpp %d/%d\n", + scrp->confScreen->id, scrp->depth, scrp->bitsPerPixel); + memset(&scrp->confScreen->displays[i], 0, sizeof(DispRec)); + scrp->confScreen->displays[i].blackColour.red = -1; + scrp->confScreen->displays[i].blackColour.green = -1; + scrp->confScreen->displays[i].blackColour.blue = -1; + scrp->confScreen->displays[i].whiteColour.red = -1; + scrp->confScreen->displays[i].whiteColour.green = -1; + scrp->confScreen->displays[i].whiteColour.blue = -1; + scrp->confScreen->displays[i].defaultVisual = -1; + scrp->confScreen->displays[i].modes = xnfalloc(sizeof(char *)); + scrp->confScreen->displays[i].modes[0] = NULL; + scrp->confScreen->displays[i].depth = depth; + scrp->confScreen->displays[i].fbbpp = fbbpp; + scrp->display = &scrp->confScreen->displays[i]; + } + + /* + * Setup defaults for the display-wide attributes the framebuffer will + * need. These defaults should eventually be set globally, and not + * dependent on the screens. + */ + scrp->imageByteOrder = IMAGE_BYTE_ORDER; + scrp->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + if (scrp->depth < 8) { + /* Planar modes need these settings */ + scrp->bitmapScanlineUnit = 8; + scrp->bitmapBitOrder = MSBFirst; + } else { + scrp->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + scrp->bitmapBitOrder = BITMAP_BIT_ORDER; + } + + /* + * If an unusual depth is required, add it to scrp->formats. The formats + * for the common depths are handled globally in InitOutput + */ + switch (scrp->depth) { + case 1: + case 4: + case 8: + case 15: + case 16: + case 24: + /* Common depths. Nothing to do for them */ + break; + default: + if (!xf86AddPixFormat(scrp, scrp->depth, 0, 0)) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Can't add pixmap format for depth %d\n", scrp->depth); + return FALSE; + } + } + + /* Initialise the framebuffer format for this screen */ + scrp->fbFormat.depth = scrp->depth; + scrp->fbFormat.bitsPerPixel = scrp->bitsPerPixel; + scrp->fbFormat.scanlinePad = BITMAP_SCANLINE_PAD; + + return TRUE; +} + +/* + * Print out the selected depth and bpp. + */ +void +xf86PrintDepthBpp(ScrnInfoPtr scrp) +{ + xf86DrvMsg(scrp->scrnIndex, scrp->depthFrom, "Depth %d, ", scrp->depth); + xf86Msg(scrp->bitsPerPixelFrom, "framebuffer bpp %d\n", scrp->bitsPerPixel); +} + +/* + * xf86SetWeight sets scrp->weight, scrp->mask, scrp->offset, and for depths + * greater than MAX_PSEUDO_DEPTH also scrp->rgbBits. + */ +Bool +xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask) +{ + MessageType weightFrom = X_DEFAULT; + + scrp->weight.red = 0; + scrp->weight.green = 0; + scrp->weight.blue = 0; + + if (xf86Weight.red > 0 && xf86Weight.green > 0 && xf86Weight.blue > 0) { + scrp->weight = xf86Weight; + weightFrom = X_CMDLINE; + } else if (scrp->display->weight.red > 0 && scrp->display->weight.green > 0 + && scrp->display->weight.blue > 0) { + scrp->weight = scrp->display->weight; + weightFrom = X_CONFIG; + } else if (weight.red > 0 && weight.green > 0 && weight.blue > 0) { + scrp->weight = weight; + } else { + switch (scrp->depth) { + case 1: + case 4: + case 8: + scrp->weight.red = scrp->weight.green = + scrp->weight.blue = scrp->rgbBits; + break; + case 15: + scrp->weight.red = scrp->weight.green = scrp->weight.blue = 5; + break; + case 16: + scrp->weight.red = scrp->weight.blue = 5; + scrp->weight.green = 6; + break; + case 24: + scrp->weight.red = scrp->weight.green = scrp->weight.blue = 8; + break; + case 30: + scrp->weight.red = scrp->weight.green = scrp->weight.blue = 10; + break; + } + } + + if (scrp->weight.red) + xf86DrvMsg(scrp->scrnIndex, weightFrom, "RGB weight %d%d%d\n", + (int)scrp->weight.red, (int)scrp->weight.green, + (int)scrp->weight.blue); + + if (scrp->depth > MAX_PSEUDO_DEPTH && + (scrp->depth != scrp->weight.red + scrp->weight.green + + scrp->weight.blue)) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Weight given (%d%d%d) is inconsistent with the " + "depth (%d)\n", + (int)scrp->weight.red, (int)scrp->weight.green, + (int)scrp->weight.blue, scrp->depth); + return FALSE; + } + if (scrp->depth > MAX_PSEUDO_DEPTH && scrp->weight.red) { + /* + * XXX Does this even mean anything for TrueColor visuals? + * If not, we shouldn't even be setting it here. However, this + * matches the behaviour of 3.x versions of XFree86. + */ + scrp->rgbBits = scrp->weight.red; + if (scrp->weight.green > scrp->rgbBits) + scrp->rgbBits = scrp->weight.green; + if (scrp->weight.blue > scrp->rgbBits) + scrp->rgbBits = scrp->weight.blue; + } + + /* Set the mask and offsets */ + if (mask.red == 0 || mask.green == 0 || mask.blue == 0) { + /* Default to a setting common to PC hardware */ + scrp->offset.red = scrp->weight.green + scrp->weight.blue; + scrp->offset.green = scrp->weight.blue; + scrp->offset.blue = 0; + scrp->mask.red = ((1 << scrp->weight.red) - 1) << scrp->offset.red; + scrp->mask.green = ((1 << scrp->weight.green) - 1) + << scrp->offset.green; + scrp->mask.blue = (1 << scrp->weight.blue) - 1; + } else { + /* Initialise to the values passed */ + scrp->mask.red = mask.red; + scrp->mask.green = mask.green; + scrp->mask.blue = mask.blue; + scrp->offset.red = ffs(mask.red); + scrp->offset.green = ffs(mask.green); + scrp->offset.blue = ffs(mask.blue); + } + return TRUE; +} + +Bool +xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual) +{ + MessageType visualFrom = X_DEFAULT; + + if (defaultColorVisualClass >= 0) { + scrp->defaultVisual = defaultColorVisualClass; + visualFrom = X_CMDLINE; + } else if (scrp->display->defaultVisual >= 0) { + scrp->defaultVisual = scrp->display->defaultVisual; + visualFrom = X_CONFIG; + } else if (visual >= 0) { + scrp->defaultVisual = visual; + } else { + if (scrp->depth == 1) + scrp->defaultVisual = StaticGray; + else if (scrp->depth == 4) + scrp->defaultVisual = StaticColor; + else if (scrp->depth <= MAX_PSEUDO_DEPTH) + scrp->defaultVisual = PseudoColor; + else + scrp->defaultVisual = TrueColor; + } + switch (scrp->defaultVisual) { + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + case TrueColor: + case DirectColor: + xf86DrvMsg(scrp->scrnIndex, visualFrom, "Default visual is %s\n", + xf86VisualNames[scrp->defaultVisual]); + return TRUE; + default: + + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Invalid default visual class (%d)\n", scrp->defaultVisual); + return FALSE; + } +} + +#define TEST_GAMMA(g) \ + (g).red > GAMMA_ZERO || (g).green > GAMMA_ZERO || (g).blue > GAMMA_ZERO + +#define SET_GAMMA(g) \ + (g) > GAMMA_ZERO ? (g) : 1.0 + +Bool +xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma) +{ + MessageType from = X_DEFAULT; +#if 0 + xf86MonPtr DDC = (xf86MonPtr)(scrp->monitor->DDC); +#endif + if (TEST_GAMMA(xf86Gamma)) { + from = X_CMDLINE; + scrp->gamma.red = SET_GAMMA(xf86Gamma.red); + scrp->gamma.green = SET_GAMMA(xf86Gamma.green); + scrp->gamma.blue = SET_GAMMA(xf86Gamma.blue); + } else if (TEST_GAMMA(scrp->monitor->gamma)) { + from = X_CONFIG; + scrp->gamma.red = SET_GAMMA(scrp->monitor->gamma.red); + scrp->gamma.green = SET_GAMMA(scrp->monitor->gamma.green); + scrp->gamma.blue = SET_GAMMA(scrp->monitor->gamma.blue); +#if 0 + } else if ( DDC && DDC->features.gamma > GAMMA_ZERO ) { + from = X_PROBED; + scrp->gamma.red = SET_GAMMA(DDC->features.gamma); + scrp->gamma.green = SET_GAMMA(DDC->features.gamma); + scrp->gamma.blue = SET_GAMMA(DDC->features.gamma); + /* EDID structure version 2 gives optional seperate red, green & blue gamma values + * in bytes 0x57-0x59 */ +#endif + } else if (TEST_GAMMA(gamma)) { + scrp->gamma.red = SET_GAMMA(gamma.red); + scrp->gamma.green = SET_GAMMA(gamma.green); + scrp->gamma.blue = SET_GAMMA(gamma.blue); + } else { + scrp->gamma.red = 1.0; + scrp->gamma.green = 1.0; + scrp->gamma.blue = 1.0; + } + /* Pretend we succeeded if we support better a gamma system. + * This avoids a confusing message. + */ + if (xf86_crtc_supports_gamma(scrp)) + return TRUE; + xf86DrvMsg(scrp->scrnIndex, from, + "Using gamma correction (%.1f, %.1f, %.1f)\n", + scrp->gamma.red, scrp->gamma.green, scrp->gamma.blue); + + return TRUE; +} + +#undef TEST_GAMMA +#undef SET_GAMMA + + +/* + * Set the DPI from the command line option. XXX should allow it to be + * calculated from the widthmm/heightmm values. + */ + +#undef MMPERINCH +#define MMPERINCH 25.4 + +void +xf86SetDpi(ScrnInfoPtr pScrn, int x, int y) +{ + MessageType from = X_DEFAULT; + xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC); + int ddcWidthmm, ddcHeightmm; + int widthErr, heightErr; + + /* XXX Maybe there is no need for widthmm/heightmm in ScrnInfoRec */ + pScrn->widthmm = pScrn->monitor->widthmm; + pScrn->heightmm = pScrn->monitor->heightmm; + + if (DDC && (DDC->features.hsize > 0 && DDC->features.vsize > 0) ) { + /* DDC gives display size in mm for individual modes, + * but cm for monitor + */ + ddcWidthmm = DDC->features.hsize * 10; /* 10mm in 1cm */ + ddcHeightmm = DDC->features.vsize * 10; /* 10mm in 1cm */ + } else { + ddcWidthmm = ddcHeightmm = 0; + } + + if (monitorResolution > 0) { + pScrn->xDpi = monitorResolution; + pScrn->yDpi = monitorResolution; + from = X_CMDLINE; + } else if (pScrn->widthmm > 0 || pScrn->heightmm > 0) { + from = X_CONFIG; + if (pScrn->widthmm > 0) { + pScrn->xDpi = + (int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm); + } + if (pScrn->heightmm > 0) { + pScrn->yDpi = + (int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm); + } + if (pScrn->xDpi > 0 && pScrn->yDpi <= 0) + pScrn->yDpi = pScrn->xDpi; + if (pScrn->yDpi > 0 && pScrn->xDpi <= 0) + pScrn->xDpi = pScrn->yDpi; + xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n", + pScrn->widthmm, pScrn->heightmm); + + /* Warn if config and probe disagree about display size */ + if ( ddcWidthmm && ddcHeightmm ) { + if (pScrn->widthmm > 0) { + widthErr = abs(ddcWidthmm - pScrn->widthmm); + } else { + widthErr = 0; + } + if (pScrn->heightmm > 0) { + heightErr = abs(ddcHeightmm - pScrn->heightmm); + } else { + heightErr = 0; + } + if (widthErr>10 || heightErr>10) { + /* Should include config file name for monitor here */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Probed monitor is %dx%d mm, using Displaysize %dx%d mm\n", + ddcWidthmm,ddcHeightmm, pScrn->widthmm,pScrn->heightmm); + } + } + } else if ( ddcWidthmm && ddcHeightmm ) { + from = X_PROBED; + xf86DrvMsg(pScrn->scrnIndex, from, "Display dimensions: (%d, %d) mm\n", + ddcWidthmm, ddcHeightmm ); + pScrn->widthmm = ddcWidthmm; + pScrn->heightmm = ddcHeightmm; + if (pScrn->widthmm > 0) { + pScrn->xDpi = + (int)((double)pScrn->virtualX * MMPERINCH / pScrn->widthmm); + } + if (pScrn->heightmm > 0) { + pScrn->yDpi = + (int)((double)pScrn->virtualY * MMPERINCH / pScrn->heightmm); + } + if (pScrn->xDpi > 0 && pScrn->yDpi <= 0) + pScrn->yDpi = pScrn->xDpi; + if (pScrn->yDpi > 0 && pScrn->xDpi <= 0) + pScrn->xDpi = pScrn->yDpi; + } else { + if (x > 0) + pScrn->xDpi = x; + else + pScrn->xDpi = DEFAULT_DPI; + if (y > 0) + pScrn->yDpi = y; + else + pScrn->yDpi = DEFAULT_DPI; + } + xf86DrvMsg(pScrn->scrnIndex, from, "DPI set to (%d, %d)\n", + pScrn->xDpi, pScrn->yDpi); +} + +#undef MMPERINCH + + +void +xf86SetBlackWhitePixels(ScreenPtr pScreen) +{ + if (xf86FlipPixels) { + pScreen->whitePixel = 0; + pScreen->blackPixel = 1; + } else { + pScreen->whitePixel = 1; + pScreen->blackPixel = 0; + } +} + +/* + * xf86SetRootClip -- + * Enable or disable rendering to the screen by + * setting the root clip list and revalidating + * all of the windows + */ + +static void +xf86SetRootClip (ScreenPtr pScreen, Bool enable) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + WindowPtr pChild; + Bool WasViewable = (Bool)(pWin->viewable); + Bool anyMarked = FALSE; + 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; + } + } + + /* + * Use REGION_BREAK to avoid optimizations in ValidateTree + * that assume the root borderClip can't change well, normally + * it doesn't...) + */ + if (enable) + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT (pScreen, &pWin->winSize, &box, 1); + REGION_INIT (pScreen, &pWin->borderSize, &box, 1); + if (WasViewable) + REGION_RESET(pScreen, &pWin->borderClip, &box); + pWin->drawable.width = pScreen->width; + pWin->drawable.height = pScreen->height; + 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->firstChild) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, + pWin->firstChild, + (WindowPtr *)NULL); + } + else + { + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + } + + + if (anyMarked) + (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); + } + + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pWin); + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + FlushAllOutput (); +} + +/* + * Function to enable/disable access to the frame buffer + * + * This is used when VT switching and when entering/leaving DGA direct mode. + * + * This has been rewritten again to eliminate the saved pixmap. The + * devPrivate field in the screen pixmap is set to NULL to catch code + * accidentally referencing the frame buffer while the X server is not + * supposed to touch it. + * + * Here, we exchange the pixmap private data, rather than the pixmaps + * themselves to avoid having to find and change any references to the screen + * pixmap such as GC's, window privates etc. This also means that this code + * does not need to know exactly how the pixmap pixels are accessed. Further, + * this exchange is >not< done through the screen's ModifyPixmapHeader() + * vector. This means the called frame buffer code layers can determine + * whether they are switched in or out by keeping track of the root pixmap's + * private data, and therefore don't need to access pScrnInfo->vtSema. + */ +void +xf86EnableDisableFBAccess(int scrnIndex, Bool enable) +{ + ScrnInfoPtr pScrnInfo = xf86Screens[scrnIndex]; + ScreenPtr pScreen = pScrnInfo->pScreen; + PixmapPtr pspix; + + pspix = (*pScreen->GetScreenPixmap) (pScreen); + if (enable) + { + /* + * Restore the screen pixmap devPrivate field + */ + pspix->devPrivate = pScrnInfo->pixmapPrivate; + /* + * Restore all of the clip lists on the screen + */ + if (!xf86Resetting) + xf86SetRootClip (pScreen, TRUE); + + } + else + { + /* + * Empty all of the clip lists on the screen + */ + xf86SetRootClip (pScreen, FALSE); + /* + * save the screen pixmap devPrivate field and + * replace it with NULL so accidental references + * to the frame buffer are caught + */ + pScrnInfo->pixmapPrivate = pspix->devPrivate; + pspix->devPrivate.ptr = NULL; + } +} + +/* Print driver messages in the standard format */ + +#undef PREFIX_SIZE +#define PREFIX_SIZE 14 + +void +xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, + va_list args) +{ + char *tmpFormat; + + /* Prefix the scrnIndex name to the format string. */ + if (scrnIndex >= 0 && scrnIndex < xf86NumScreens && + xf86Screens[scrnIndex]->name) { + tmpFormat = malloc(strlen(format) + + strlen(xf86Screens[scrnIndex]->name) + + PREFIX_SIZE + 1); + if (!tmpFormat) + return; + + snprintf(tmpFormat, PREFIX_SIZE + 1, "%s(%d): ", + xf86Screens[scrnIndex]->name, scrnIndex); + + strcat(tmpFormat, format); + LogVMessageVerb(type, verb, tmpFormat, args); + free(tmpFormat); + } else + LogVMessageVerb(type, verb, format, args); +} +#undef PREFIX_SIZE + +/* Print driver messages, with verbose level specified directly */ +void +xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format, + ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(scrnIndex, type, verb, format, ap); + va_end(ap); +} + +/* Print driver messages, with verbose level of 1 (default) */ +void +xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(scrnIndex, type, 1, format, ap); + va_end(ap); +} + +/* Print non-driver messages with verbose level specified directly */ +void +xf86MsgVerb(MessageType type, int verb, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(-1, type, verb, format, ap); + va_end(ap); +} + +/* Print non-driver messages with verbose level of 1 (default) */ +void +xf86Msg(MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(-1, type, 1, format, ap); + va_end(ap); +} + +/* Just like ErrorF, but with the verbose level checked */ +void +xf86ErrorFVerb(int verb, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + if (xf86Verbose >= verb || xf86LogVerbose >= verb) + LogVWrite(verb, format, ap); + va_end(ap); +} + +/* Like xf86ErrorFVerb, but with an implied verbose level of 1 */ +void +xf86ErrorF(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + if (xf86Verbose >= 1 || xf86LogVerbose >= 1) + LogVWrite(1, format, ap); + va_end(ap); +} + + +void +xf86LogInit(void) +{ + char *lf = NULL; + +#define LOGSUFFIX ".log" +#define LOGOLDSUFFIX ".old" + + /* Get the log file name */ + if (xf86LogFileFrom == X_DEFAULT) { + /* Append the display number and ".log" */ + lf = malloc(strlen(xf86LogFile) + strlen("%s") + + strlen(LOGSUFFIX) + 1); + if (!lf) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(lf, "%s%%s" LOGSUFFIX, xf86LogFile); + xf86LogFile = lf; + } + + xf86LogFile = LogInit(xf86LogFile, LOGOLDSUFFIX); + xf86LogFileWasOpened = TRUE; + + xf86SetVerbosity(xf86Verbose); + xf86SetLogVerbosity(xf86LogVerbose); + +#undef LOGSUFFIX +#undef LOGOLDSUFFIX + + free(lf); +} + +void +xf86CloseLog(void) +{ + LogClose(); +} + + +/* + * Drivers can use these for using their own SymTabRecs. + */ + +const char * +xf86TokenToString(SymTabPtr table, int token) +{ + int i; + + for (i = 0; table[i].token >= 0 && table[i].token != token; i++) + ; + + if (table[i].token < 0) + return NULL; + else + return(table[i].name); +} + +int +xf86StringToToken(SymTabPtr table, const char *string) +{ + int i; + + if (string == NULL) + return -1; + + for (i = 0; table[i].token >= 0 && xf86NameCmp(string, table[i].name); i++) + ; + + return(table[i].token); +} + +/* + * helper to display the clocks found on a card + */ +void +xf86ShowClocks(ScrnInfoPtr scrp, MessageType from) +{ + int j; + + xf86DrvMsg(scrp->scrnIndex, from, "Pixel clocks available:"); + for (j=0; j < scrp->numClocks; j++) { + if ((j % 4) == 0) { + xf86ErrorF("\n"); + xf86DrvMsg(scrp->scrnIndex, from, "pixel clocks:"); + } + xf86ErrorF(" %7.3f", (double)scrp->clock[j] / 1000.0); + } + xf86ErrorF("\n"); +} + + +/* + * This prints out the driver identify message, including the names of + * the supported chipsets. + * + * XXX This makes assumptions about the line width, etc. Maybe we could + * use a more general "pretty print" function for messages. + */ +void +xf86PrintChipsets(const char *drvname, const char *drvmsg, SymTabPtr chips) +{ + int len, i; + + len = 6 + strlen(drvname) + 2 + strlen(drvmsg) + 2; + xf86Msg(X_INFO, "%s: %s:", drvname, drvmsg); + for (i = 0; chips[i].name != NULL; i++) { + if (i != 0) { + xf86ErrorF(","); + len++; + } + if (len + 2 + strlen(chips[i].name) < 78) { + xf86ErrorF(" "); + len++; + } else { + xf86ErrorF("\n\t"); + len = 8; + } + xf86ErrorF("%s", chips[i].name); + len += strlen(chips[i].name); + } + xf86ErrorF("\n"); +} + + +int +xf86MatchDevice(const char *drivername, GDevPtr **sectlist) +{ + GDevPtr gdp, *pgdp = NULL; + confScreenPtr screensecptr; + int i,j; + + if (sectlist) + *sectlist = NULL; + + if (xf86DoConfigure && xf86DoConfigurePass1) return 1; + + /* + * This is a very important function that matches the device sections + * as they show up in the config file with the drivers that the server + * loads at run time. + * + * ChipProbe can call + * int xf86MatchDevice(char * drivername, GDevPtr ** sectlist) + * with its driver name. The function allocates an array of GDevPtr and + * returns this via sectlist and returns the number of elements in + * this list as return value. 0 means none found, -1 means fatal error. + * + * It can figure out which of the Device sections to use for which card + * (using things like the Card statement, etc). For single headed servers + * there will of course be just one such Device section. + */ + i = 0; + + /* + * first we need to loop over all the Screens sections to get to all + * 'active' device sections + */ + for (j=0; xf86ConfigLayout.screens[j].screen != NULL; j++) { + screensecptr = xf86ConfigLayout.screens[j].screen; + if ((screensecptr->device->driver != NULL) + && (xf86NameCmp( screensecptr->device->driver,drivername) == 0) + && (! screensecptr->device->claimed)) { + /* + * we have a matching driver that wasn't claimed, yet + */ + pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr)); + pgdp[i++] = screensecptr->device; + } + } + + /* Then handle the inactive devices */ + j = 0; + while (xf86ConfigLayout.inactives[j].identifier) { + gdp = &xf86ConfigLayout.inactives[j]; + if (gdp->driver && !gdp->claimed && + !xf86NameCmp(gdp->driver,drivername)) { + /* we have a matching driver that wasn't claimed yet */ + pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr)); + pgdp[i++] = gdp; + } + j++; + } + + /* + * make the array NULL terminated and return its address + */ + if (i) + pgdp[i] = NULL; + + if (sectlist) + *sectlist = pgdp; + else + free(pgdp); + return i; +} + +static Bool +pciDeviceHasBars(struct pci_device *pci) +{ + int i; + + for (i = 0; i < 6; i++) + if (pci->regions[i].size) + return TRUE; + + if (pci->rom_size) + return TRUE; + + return FALSE; +} + +struct Inst { + struct pci_device * pci; + GDevPtr dev; + Bool foundHW; /* PCIid in list of supported chipsets */ + Bool claimed; /* BusID matches with a device section */ + int chip; + int screen; +}; + + +/** + * Find set of unclaimed devices matching a given vendor ID. + * + * Used by drivers to find as yet unclaimed devices matching the specified + * vendor ID. + * + * \param driverName Name of the driver. This is used to find Device + * sections in the config file. + * \param vendorID PCI vendor ID of associated devices. If zero, then + * the true vendor ID must be encoded in the \c PCIid + * fields of the \c PCIchipsets entries. + * \param chipsets Symbol table used to associate chipset names with + * PCI IDs. + * \param devList List of Device sections parsed from the config file. + * \param numDevs Number of entries in \c devList. + * \param drvp Pointer the driver's control structure. + * \param foundEntities Returned list of entity indicies associated with the + * driver. + * + * \returns + * The number of elements in returned in \c foundEntities on success or zero + * on failure. + * + * \todo + * This function does a bit more than short description says. Fill in some + * more of the details of its operation. + * + * \todo + * The \c driverName parameter is redundant. It is the same as + * \c DriverRec::driverName. In a future version of this function, remove + * that parameter. + */ +int +xf86MatchPciInstances(const char *driverName, int vendorID, + SymTabPtr chipsets, PciChipsets *PCIchipsets, + GDevPtr *devList, int numDevs, DriverPtr drvp, + int **foundEntities) +{ + int i,j; + struct pci_device * pPci; + struct pci_device_iterator *iter; + struct Inst *instances = NULL; + int numClaimedInstances = 0; + int allocatedInstances = 0; + int numFound = 0; + SymTabRec *c; + PciChipsets *id; + int *retEntities = NULL; + + *foundEntities = NULL; + + + /* Each PCI device will contribute at least one entry. Each device + * section can contribute at most one entry. The sum of the two is + * guaranteed to be larger than the maximum possible number of entries. + * Do this calculation and memory allocation once now to eliminate the + * need for realloc calls inside the loop. + */ + if (!(xf86DoConfigure && xf86DoConfigurePass1)) { + unsigned max_entries = numDevs; + + iter = pci_slot_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + max_entries++; + } + + pci_iterator_destroy(iter); + instances = xnfalloc(max_entries * sizeof(struct Inst)); + } + + iter = pci_slot_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + unsigned device_class = pPci->device_class; + Bool foundVendor = FALSE; + + + /* Convert the pre-PCI 2.0 device class for a VGA adapter to the + * 2.0 version of the same class. + */ + if ( device_class == 0x00000101 ) { + device_class = 0x00030000; + } + + + /* Find PCI devices that match the given vendor ID. The vendor ID is + * either specified explicitly as a parameter to the function or + * implicitly encoded in the high bits of id->PCIid. + * + * The first device with a matching vendor is recorded, even if the + * device ID doesn't match. This is done because the Device section + * in the xorg.conf file can over-ride the device ID. A matching PCI + * ID might not be found now, but after the device ID over-ride is + * applied there /might/ be a match. + */ + for (id = PCIchipsets; id->PCIid != -1; id++) { + const unsigned vendor_id = ((id->PCIid & 0xFFFF0000) >> 16) + | vendorID; + const unsigned device_id = (id->PCIid & 0x0000FFFF); + const unsigned match_class = 0x00030000 | id->PCIid; + + if ((vendor_id == pPci->vendor_id) + || ((vendorID == PCI_VENDOR_GENERIC) && (match_class == device_class))) { + if (!foundVendor && (instances != NULL)) { + ++allocatedInstances; + instances[allocatedInstances - 1].pci = pPci; + instances[allocatedInstances - 1].dev = NULL; + instances[allocatedInstances - 1].claimed = FALSE; + instances[allocatedInstances - 1].foundHW = FALSE; + instances[allocatedInstances - 1].screen = 0; + } + + foundVendor = TRUE; + + if ( (device_id == pPci->device_id) + || ((vendorID == PCI_VENDOR_GENERIC) + && (match_class == device_class)) ) { + if ( instances != NULL ) { + instances[allocatedInstances - 1].foundHW = TRUE; + instances[allocatedInstances - 1].chip = id->numChipset; + } + + + if ( xf86DoConfigure && xf86DoConfigurePass1 ) { + if (xf86CheckPciSlot(pPci)) { + GDevPtr pGDev = + xf86AddBusDeviceToConfigure(drvp->driverName, + BUS_PCI, pPci, -1); + if (pGDev) { + /* After configure pass 1, chipID and chipRev + * are treated as over-rides, so clobber them + * here. + */ + pGDev->chipID = -1; + pGDev->chipRev = -1; + } + + numFound++; + } + } + else { + numFound++; + } + + break; + } + } + } + } + + pci_iterator_destroy(iter); + + + /* In "probe only" or "configure" mode (signaled by instances being NULL), + * our work is done. Return the number of detected devices. + */ + if ( instances == NULL ) { + return numFound; + } + + + /* + * This may be debatable, but if no PCI devices with a matching vendor + * type is found, return zero now. It is probably not desirable to + * allow the config file to override this. + */ + if (allocatedInstances <= 0) { + free(instances); + return 0; + } + + + DebugF("%s instances found: %d\n", driverName, allocatedInstances); + + /* + * Check for devices that need duplicated instances. This is required + * when there is more than one screen per entity. + * + * XXX This currently doesn't work for cases where the BusID isn't + * specified explicitly in the config file. + */ + + for (j = 0; j < numDevs; j++) { + if (devList[j]->screen > 0 && devList[j]->busID + && *devList[j]->busID) { + for (i = 0; i < allocatedInstances; i++) { + pPci = instances[i].pci; + if (xf86ComparePciBusString(devList[j]->busID, + PCI_MAKE_BUS( pPci->domain, pPci->bus ), + pPci->dev, + pPci->func)) { + allocatedInstances++; + instances[allocatedInstances - 1] = instances[i]; + instances[allocatedInstances - 1].screen = + devList[j]->screen; + numFound++; + break; + } + } + } + } + + for (i = 0; i < allocatedInstances; i++) { + GDevPtr dev = NULL; + GDevPtr devBus = NULL; + + pPci = instances[i].pci; + for (j = 0; j < numDevs; j++) { + if (devList[j]->busID && *devList[j]->busID) { + if (xf86ComparePciBusString(devList[j]->busID, + PCI_MAKE_BUS( pPci->domain, pPci->bus ), + pPci->dev, + pPci->func) && + devList[j]->screen == instances[i].screen) { + + if (devBus) + xf86MsgVerb(X_WARNING,0, + "%s: More than one matching Device section for " + "instances\n\t(BusID: %s) found: %s\n", + driverName, devList[j]->busID, + devList[j]->identifier); + else + devBus = devList[j]; + } + } else { + /* + * if device section without BusID is found + * only assign to it to the primary device. + */ + if (xf86IsPrimaryPci(pPci)) { + xf86Msg(X_PROBED, "Assigning device section with no busID" + " to primary device\n"); + if (dev || devBus) + xf86MsgVerb(X_WARNING, 0, + "%s: More than one matching Device section " + "found: %s\n", driverName, devList[j]->identifier); + else + dev = devList[j]; + } + } + } + if (devBus) dev = devBus; /* busID preferred */ + if (!dev) { + if (xf86CheckPciSlot(pPci) && pciDeviceHasBars(pPci)) { + xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " + "for instance (BusID PCI:%u@%u:%u:%u) found\n", + driverName, pPci->domain, pPci->bus, pPci->dev, + pPci->func); + } + } else { + numClaimedInstances++; + instances[i].claimed = TRUE; + instances[i].dev = dev; + } + } + DebugF("%s instances found: %d\n", driverName, numClaimedInstances); + /* + * Now check that a chipset or chipID override in the device section + * is valid. Chipset has precedence over chipID. + * If chipset is not valid ignore BusSlot completely. + */ + for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { + MessageType from = X_PROBED; + + if (!instances[i].claimed) { + continue; + } + if (instances[i].dev->chipset) { + for (c = chipsets; c->token >= 0; c++) { + if (xf86NameCmp(c->name, instances[i].dev->chipset) == 0) + break; + } + if (c->token == -1) { + instances[i].claimed = FALSE; + numClaimedInstances--; + xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " + "section \"%s\" isn't valid for this driver\n", + driverName, instances[i].dev->chipset, + instances[i].dev->identifier); + } else { + instances[i].chip = c->token; + + for (id = PCIchipsets; id->numChipset >= 0; id++) { + if (id->numChipset == instances[i].chip) + break; + } + if(id->numChipset >=0){ + xf86Msg(X_CONFIG,"Chipset override: %s\n", + instances[i].dev->chipset); + from = X_CONFIG; + } else { + instances[i].claimed = FALSE; + numClaimedInstances--; + xf86MsgVerb(X_WARNING, 0, "%s: Chipset \"%s\" in Device " + "section \"%s\" isn't a valid PCI chipset\n", + driverName, instances[i].dev->chipset, + instances[i].dev->identifier); + } + } + } else if (instances[i].dev->chipID > 0) { + for (id = PCIchipsets; id->numChipset >= 0; id++) { + if (id->PCIid == instances[i].dev->chipID) + break; + } + if (id->numChipset == -1) { + instances[i].claimed = FALSE; + numClaimedInstances--; + xf86MsgVerb(X_WARNING, 0, "%s: ChipID 0x%04X in Device " + "section \"%s\" isn't valid for this driver\n", + driverName, instances[i].dev->chipID, + instances[i].dev->identifier); + } else { + instances[i].chip = id->numChipset; + + xf86Msg( X_CONFIG,"ChipID override: 0x%04X\n", + instances[i].dev->chipID); + from = X_CONFIG; + } + } else if (!instances[i].foundHW) { + /* + * This means that there was no override and the PCI chipType + * doesn't match one that is supported + */ + instances[i].claimed = FALSE; + numClaimedInstances--; + } + if (instances[i].claimed == TRUE){ + for (c = chipsets; c->token >= 0; c++) { + if (c->token == instances[i].chip) + break; + } + xf86Msg(from,"Chipset %s found\n", + c->name); + } + } + + /* + * Of the claimed instances, check that another driver hasn't already + * claimed its slot. + */ + numFound = 0; + for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { + + if (!instances[i].claimed) + continue; + pPci = instances[i].pci; + + + /* + * Allow the same entity to be used more than once for devices with + * multiple screens per entity. This assumes implicitly that there + * will be a screen == 0 instance. + * + * XXX Need to make sure that two different drivers don't claim + * the same screen > 0 instance. + */ + if (instances[i].screen == 0 && !xf86CheckPciSlot( pPci )) + continue; + + DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", + driverName, pPci->bus, pPci->dev, pPci->func); + + /* Allocate an entry in the lists to be returned */ + numFound++; + retEntities = xnfrealloc(retEntities, numFound * sizeof(int)); + retEntities[numFound - 1] = xf86ClaimPciSlot( pPci, drvp, + instances[i].chip, + instances[i].dev, + instances[i].dev->active); + if (retEntities[numFound - 1] == -1 && instances[i].screen > 0) { + for (j = 0; j < xf86NumEntities; j++) { + EntityPtr pEnt = xf86Entities[j]; + if (pEnt->bus.type != BUS_PCI) + continue; + if (pEnt->bus.id.pci == pPci) { + retEntities[numFound - 1] = j; + xf86AddDevToEntity(j, instances[i].dev); + break; + } + } + } + } + free(instances); + if (numFound > 0) { + *foundEntities = retEntities; + } + + return numFound; +} + +/* + * xf86GetClocks -- get the dot-clocks via a BIG BAD hack ... + */ +void +xf86GetClocks(ScrnInfoPtr pScrn, int num, Bool (*ClockFunc)(ScrnInfoPtr, int), + void (*ProtectRegs)(ScrnInfoPtr, Bool), + void (*BlankScreen)(ScrnInfoPtr, Bool), IOADDRESS vertsyncreg, + int maskval, int knownclkindex, int knownclkvalue) +{ + register int status = vertsyncreg; + unsigned long i, cnt, rcnt, sync; + + /* First save registers that get written on */ + (*ClockFunc)(pScrn, CLK_REG_SAVE); + + if (num > MAXCLOCKS) + num = MAXCLOCKS; + + for (i = 0; i < num; i++) + { + if (ProtectRegs) + (*ProtectRegs)(pScrn, TRUE); + if (!(*ClockFunc)(pScrn, i)) + { + pScrn->clock[i] = -1; + continue; + } + if (ProtectRegs) + (*ProtectRegs)(pScrn, FALSE); + if (BlankScreen) + (*BlankScreen)(pScrn, FALSE); + + usleep(50000); /* let VCO stabilise */ + + cnt = 0; + sync = 200000; + + while ((inb(status) & maskval) == 0x00) + if (sync-- == 0) goto finish; + /* Something appears to be happening, so reset sync count */ + sync = 200000; + while ((inb(status) & maskval) == maskval) + if (sync-- == 0) goto finish; + /* Something appears to be happening, so reset sync count */ + sync = 200000; + while ((inb(status) & maskval) == 0x00) + if (sync-- == 0) goto finish; + + for (rcnt = 0; rcnt < 5; rcnt++) + { + while (!(inb(status) & maskval)) + cnt++; + while ((inb(status) & maskval)) + cnt++; + } + +finish: + pScrn->clock[i] = cnt ? cnt : -1; + if (BlankScreen) + (*BlankScreen)(pScrn, TRUE); + } + + for (i = 0; i < num; i++) + { + if (i != knownclkindex) + { + if (pScrn->clock[i] == -1) + { + pScrn->clock[i] = 0; + } + else + { + pScrn->clock[i] = (int)(0.5 + + (((float)knownclkvalue) * pScrn->clock[knownclkindex]) / + (pScrn->clock[i])); + /* Round to nearest 10KHz */ + pScrn->clock[i] += 5; + pScrn->clock[i] /= 10; + pScrn->clock[i] *= 10; + } + } + } + + pScrn->clock[knownclkindex] = knownclkvalue; + pScrn->numClocks = num; + + /* Restore registers that were written on */ + (*ClockFunc)(pScrn, CLK_REG_RESTORE); +} + +const char * +xf86GetVisualName(int visual) +{ + if (visual < 0 || visual > DirectColor) + return NULL; + + return xf86VisualNames[visual]; +} + + +int +xf86GetVerbosity(void) +{ + return max(xf86Verbose, xf86LogVerbose); +} + +Pix24Flags +xf86GetPix24(void) +{ + return xf86Info.pixmap24; +} + + +int +xf86GetDepth(void) +{ + return xf86Depth; +} + + +rgb +xf86GetWeight(void) +{ + return xf86Weight; +} + + +Gamma +xf86GetGamma(void) +{ + return xf86Gamma; +} + + +Bool +xf86GetFlipPixels(void) +{ + return xf86FlipPixels; +} + + +const char * +xf86GetServerName(void) +{ + return xf86ServerName; +} + + +Bool +xf86ServerIsExiting(void) +{ + return (dispatchException & DE_TERMINATE) == DE_TERMINATE; +} + + +Bool +xf86ServerIsResetting(void) +{ + return xf86Resetting; +} + + +Bool +xf86ServerIsInitialising(void) +{ + return xf86Initialising; +} + + +Bool +xf86ServerIsOnlyDetecting(void) +{ + return xf86DoConfigure; +} + + +Bool +xf86CaughtSignal(void) +{ + return xf86Info.caughtSignal; +} + + +Bool +xf86GetVidModeAllowNonLocal(void) +{ + return xf86Info.vidModeAllowNonLocal; +} + + +Bool +xf86GetVidModeEnabled(void) +{ + return xf86Info.vidModeEnabled; +} + +Bool +xf86GetModInDevAllowNonLocal(void) +{ + return xf86Info.miscModInDevAllowNonLocal; +} + + +Bool +xf86GetModInDevEnabled(void) +{ + return xf86Info.miscModInDevEnabled; +} + + +Bool +xf86GetAllowMouseOpenFail(void) +{ + return xf86Info.allowMouseOpenFail; +} + + +Bool +xf86IsPc98(void) +{ +#if SUPPORT_PC98 + return xf86Info.pc98; +#else + return FALSE; +#endif +} + +void +xf86DisableRandR(void) +{ + xf86Info.disableRandR = TRUE; + xf86Info.randRFrom = X_PROBED; +} + +CARD32 +xf86GetModuleVersion(pointer module) +{ + return (CARD32)LoaderGetModuleVersion(module); +} + +pointer +xf86LoadDrvSubModule(DriverPtr drv, const char *name) +{ + pointer ret; + int errmaj = 0, errmin = 0; + + ret = LoadSubModule(drv->module, name, NULL, NULL, NULL, NULL, + &errmaj, &errmin); + if (!ret) + LoaderErrorMsg(NULL, name, errmaj, errmin); + return ret; +} + +pointer +xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name) +{ + pointer ret; + int errmaj = 0, errmin = 0; + + ret = LoadSubModule(pScrn->module, name, NULL, NULL, NULL, NULL, + &errmaj, &errmin); + if (!ret) + LoaderErrorMsg(pScrn->name, name, errmaj, errmin); + return ret; +} + +/* + * xf86LoadOneModule loads a single module. + */ +pointer +xf86LoadOneModule(char *name, pointer opt) +{ + int errmaj, errmin; + char *Name; + pointer mod; + + if (!name) + return NULL; + + /* Normalise the module name */ + Name = xf86NormalizeName(name); + + /* Skip empty names */ + if (Name == NULL) + return NULL; + if (*Name == '\0') { + free(Name); + return NULL; + } + + mod = LoadModule(Name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin); + if (!mod) + LoaderErrorMsg(NULL, Name, errmaj, errmin); + free(Name); + return mod; +} + +void +xf86UnloadSubModule(pointer mod) +{ + /* + * This is disabled for now. The loader isn't smart enough yet to undo + * relocations. + */ +#if 0 + UnloadSubModule(mod); +#endif +} + +Bool +xf86LoaderCheckSymbol(const char *name) +{ + return LoaderSymbol(name) != NULL; +} + +typedef enum { + OPTION_BACKING_STORE +} BSOpts; + +static const OptionInfoRec BSOptions[] = { + { OPTION_BACKING_STORE, "BackingStore", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +void +xf86SetBackingStore(ScreenPtr pScreen) +{ + Bool useBS = FALSE; + MessageType from = X_DEFAULT; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + OptionInfoPtr options; + + options = xnfalloc(sizeof(BSOptions)); + (void)memcpy(options, BSOptions, sizeof(BSOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + /* check for commandline option here */ + if (xf86bsEnableFlag) { + from = X_CMDLINE; + useBS = TRUE; + } else if (xf86bsDisableFlag) { + from = X_CMDLINE; + useBS = FALSE; + } else { + if (xf86GetOptValBool(options, OPTION_BACKING_STORE, &useBS)) + from = X_CONFIG; + } + free(options); + pScreen->backingStoreSupport = useBS ? Always : NotUseful; + if (serverGeneration == 1) + xf86DrvMsg(pScreen->myNum, from, "Backing store %s\n", + useBS ? "enabled" : "disabled"); +} + + +typedef enum { + OPTION_SILKEN_MOUSE +} SMOpts; + +static const OptionInfoRec SMOptions[] = { + { OPTION_SILKEN_MOUSE, "SilkenMouse", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +void +xf86SetSilkenMouse (ScreenPtr pScreen) +{ + Bool useSM = TRUE; + MessageType from = X_DEFAULT; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + OptionInfoPtr options; + + options = xnfalloc(sizeof(SMOptions)); + (void)memcpy(options, SMOptions, sizeof(SMOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + /* check for commandline option here */ + /* disable if screen shares resources */ + /* TODO VGA arb disable silken mouse */ + if (xf86silkenMouseDisableFlag) { + from = X_CMDLINE; + useSM = FALSE; + } else { + if (xf86GetOptValBool(options, OPTION_SILKEN_MOUSE, &useSM)) + from = X_CONFIG; + } + free(options); + /* + * XXX quick hack to report correctly for OSs that can't do SilkenMouse + * yet. Should handle this differently so that alternate async methods + * work correctly with this too. + */ + pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported(); + if (serverGeneration == 1) + xf86DrvMsg(pScreen->myNum, from, "Silken mouse %s\n", + pScrn->silkenMouse ? "enabled" : "disabled"); +} + +/* Wrote this function for the PM2 Xv driver, preliminary. */ + +pointer +xf86FindXvOptions(int scrnIndex, int adaptor_index, char *port_name, + char **adaptor_name, pointer *adaptor_options) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + confXvAdaptorPtr adaptor; + int i; + + if (adaptor_index >= pScrn->confScreen->numxvadaptors) { + if (adaptor_name) *adaptor_name = NULL; + if (adaptor_options) *adaptor_options = NULL; + return NULL; + } + + adaptor = &pScrn->confScreen->xvadaptors[adaptor_index]; + if (adaptor_name) *adaptor_name = adaptor->identifier; + if (adaptor_options) *adaptor_options = adaptor->options; + + for (i = 0; i < adaptor->numports; i++) + if (!xf86NameCmp(adaptor->ports[i].identifier, port_name)) + return adaptor->ports[i].options; + + return NULL; +} + +/* Rather than duplicate loader's get OS function, just include it directly */ +#define LoaderGetOS xf86GetOS +#include "loader/os.c" + +/* new RAC */ +/* + * xf86ConfigPciEntityInactive() -- This function can be used + * to configure an inactive entity as well as to reconfigure an + * previously active entity inactive. If the entity has been + * assigned to a screen before it will be removed. If p_chip is + * non-NULL all static resources listed there will be registered. + */ +static void +xf86ConfigPciEntityInactive(EntityInfoPtr pEnt, PciChipsets *p_chip, + EntityProc init, EntityProc enter, + EntityProc leave, pointer private) +{ + ScrnInfoPtr pScrn; + + if ((pScrn = xf86FindScreenForEntity(pEnt->index))) + xf86RemoveEntityFromScreen(pScrn,pEnt->index); + + /* shared resources are only needed when entity is active: remove */ + xf86SetEntityFuncs(pEnt->index,init,enter,leave,private); +} + +static void +xf86ConfigFbEntityInactive(EntityInfoPtr pEnt, EntityProc init, + EntityProc enter, EntityProc leave, pointer private) +{ + ScrnInfoPtr pScrn; + + if ((pScrn = xf86FindScreenForEntity(pEnt->index))) + xf86RemoveEntityFromScreen(pScrn,pEnt->index); + xf86SetEntityFuncs(pEnt->index,init,enter,leave,private); +} + +ScrnInfoPtr +xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, + PciChipsets *p_chip, void *dummy, EntityProc init, + EntityProc enter, EntityProc leave, pointer private) +{ + EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); + if (!pEnt) return pScrn; + + if (!(pEnt->location.type == BUS_PCI) + || !xf86GetPciInfoForEntity(entityIndex)) { + free(pEnt); + return pScrn; + } + if (!pEnt->active) { + xf86ConfigPciEntityInactive(pEnt, p_chip, init, enter, + leave, private); + free(pEnt); + return pScrn; + } + + if (!pScrn) + pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag); + if (xf86IsEntitySharable(entityIndex)) { + xf86SetEntityShared(entityIndex); + } + xf86AddEntityToScreen(pScrn,entityIndex); + if (xf86IsEntityShared(entityIndex)) { + return pScrn; + } + free(pEnt); + + xf86SetEntityFuncs(entityIndex,init,enter,leave,private); + + return pScrn; +} + +ScrnInfoPtr +xf86ConfigFbEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex, + EntityProc init, EntityProc enter, EntityProc leave, + pointer private) +{ + EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); + if (!pEnt) return pScrn; + + if (!(pEnt->location.type == BUS_NONE)) { + free(pEnt); + return pScrn; + } + + if (!pEnt->active) { + xf86ConfigFbEntityInactive(pEnt, init, enter, leave, private); + free(pEnt); + return pScrn; + } + + if (!pScrn) + pScrn = xf86AllocateScreen(pEnt->driver,scrnFlag); + xf86AddEntityToScreen(pScrn,entityIndex); + + xf86SetEntityFuncs(entityIndex,init,enter,leave,private); + + return pScrn; +} + +/* + * + * OBSOLETE ! xf86ConfigActivePciEntity() is an obsolete function. + * It is likely to be removed. Don't use! + */ + +Bool +xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex, + PciChipsets *p_chip, void *dummy, EntityProc init, + EntityProc enter, EntityProc leave, pointer private) +{ + EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); + if (!pEnt) return FALSE; + + if (!pEnt->active || !(pEnt->location.type == BUS_PCI)) { + free(pEnt); + return FALSE; + } + xf86AddEntityToScreen(pScrn,entityIndex); + + free(pEnt); + if (!xf86SetEntityFuncs(entityIndex,init,enter,leave,private)) + return FALSE; + + return TRUE; +} + +Bool +xf86IsScreenPrimary(int scrnIndex) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + int i; + + for (i=0 ; i < pScrn->numEntities; i++) { + if (xf86IsEntityPrimary(i)) + return TRUE; + } + return FALSE; +} + +int +xf86RegisterRootWindowProperty(int ScrnIndex, Atom property, Atom type, + int format, unsigned long len, pointer value ) +{ + RootWinPropPtr pNewProp = NULL, pRegProp; + int i; + Bool existing = FALSE; + + DebugF("xf86RegisterRootWindowProperty(%d, %ld, %ld, %d, %ld, %p)\n", + ScrnIndex, property, type, format, len, value); + + if (ScrnIndex<0 || ScrnIndex>=xf86NumScreens) { + return(BadMatch); + } + + if (xf86RegisteredPropertiesTable && + xf86RegisteredPropertiesTable[ScrnIndex]) { + for (pNewProp = xf86RegisteredPropertiesTable[ScrnIndex]; + pNewProp; pNewProp = pNewProp->next) { + if (strcmp(pNewProp->name, NameForAtom(property)) == 0) + break; + } + } + + if (!pNewProp) { + if ((pNewProp = (RootWinPropPtr)malloc(sizeof(RootWinProp))) == NULL) { + return(BadAlloc); + } + /* + * We will put this property at the end of the list so that + * the changes are made in the order they were requested. + */ + pNewProp->next = NULL; + } else { + if (pNewProp->name) + free(pNewProp->name); + existing = TRUE; + } + + pNewProp->name = xnfstrdup(NameForAtom(property)); + pNewProp->type = type; + pNewProp->format = format; + pNewProp->size = len; + pNewProp->data = value; + + DebugF("new property filled\n"); + + if (NULL==xf86RegisteredPropertiesTable) { + DebugF("creating xf86RegisteredPropertiesTable[] size %d\n", + xf86NumScreens); + if ( NULL==(xf86RegisteredPropertiesTable=(RootWinPropPtr*)xnfcalloc(sizeof(RootWinProp),xf86NumScreens) )) { + return(BadAlloc); + } + for (i=0; inext != NULL) { + DebugF("- next %p\n", (void *)pRegProp); + pRegProp = pRegProp->next; + } + pRegProp->next = pNewProp; + } + } + DebugF("xf86RegisterRootWindowProperty succeeded\n"); + return(Success); +} + +Bool +xf86IsUnblank(int mode) +{ + switch(mode) { + case SCREEN_SAVER_OFF: + case SCREEN_SAVER_FORCER: + return TRUE; + case SCREEN_SAVER_ON: + case SCREEN_SAVER_CYCLE: + return FALSE; + default: + xf86MsgVerb(X_WARNING, 0, "Unexpected save screen mode: %d\n", mode); + return TRUE; + } +} + +void +xf86MotionHistoryAllocate(LocalDevicePtr local) +{ + AllocateMotionHistory(local->dev); +} diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index 55d7a6209..d78d3d1db 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -1,1822 +1,1822 @@ -/* - * Loosely based on code bearing the following copyright: - * - * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. - */ -/* - * Copyright (c) 1992-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include - -#undef HAS_UTSNAME -#if !defined(WIN32) -#define HAS_UTSNAME 1 -#include -#endif - -#include -#include -#include -#include -#include "input.h" -#include "servermd.h" -#include "windowstr.h" -#include "scrnintstr.h" -#include "site.h" -#include "mi.h" - -#include "compiler.h" - -#include "loaderProcs.h" -#ifdef XFreeXDGA -#include "dgaproc.h" -#endif - -#define XF86_OS_PRIVS -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86Config.h" -#include "xf86_OSlib.h" -#include "xorgVersion.h" -#include "xf86Build.h" -#include "mipointer.h" -#include -#include -#include "xf86DDC.h" -#include "xf86Xinput.h" -#include "xf86InPriv.h" -#include "picturestr.h" - -#include "xf86VGAarbiter.h" -#include "globals.h" - -#ifdef DPMSExtension -#include -#include "dpmsproc.h" -#endif - -#include -#include "Pci.h" -#include "xf86Bus.h" - -#include - -/* forward declarations */ -static Bool probe_devices_from_device_sections(DriverPtr drvp); -static Bool add_matching_devices_to_configure_list(DriverPtr drvp); - -#ifdef XF86PM -void (*xf86OSPMClose)(void) = NULL; -#endif -static Bool xorgHWOpenConsole = FALSE; - -/* Common pixmap formats */ - -static PixmapFormatRec formats[MAXFORMATS] = { - { 1, 1, BITMAP_SCANLINE_PAD }, - { 4, 8, BITMAP_SCANLINE_PAD }, - { 8, 8, BITMAP_SCANLINE_PAD }, - { 15, 16, BITMAP_SCANLINE_PAD }, - { 16, 16, BITMAP_SCANLINE_PAD }, - { 24, 32, BITMAP_SCANLINE_PAD }, - { 32, 32, BITMAP_SCANLINE_PAD }, -}; -static int numFormats = 7; -static Bool formatsDone = FALSE; - -#ifndef OSNAME -#define OSNAME " unknown" -#endif -#ifndef OSVENDOR -#define OSVENDOR "" -#endif -#ifndef PRE_RELEASE -#define PRE_RELEASE XORG_VERSION_SNAP -#endif - -static void -xf86PrintBanner(void) -{ -#if PRE_RELEASE - xf86ErrorFVerb(0, "\n" - "This is a pre-release version of the X server from " XVENDORNAME ".\n" - "It is not supported in any way.\n" - "Bugs may be filed in the bugzilla at http://bugs.freedesktop.org/.\n" - "Select the \"xorg\" product for bugs you find in this release.\n" - "Before reporting bugs in pre-release versions please check the\n" - "latest version in the X.Org Foundation git repository.\n" - "See http://wiki.x.org/wiki/GitPage for git access instructions.\n"); -#endif - xf86ErrorFVerb(0, "\nX.Org X Server %d.%d.%d", - XORG_VERSION_MAJOR, - XORG_VERSION_MINOR, - XORG_VERSION_PATCH); -#if XORG_VERSION_SNAP > 0 - xf86ErrorFVerb(0, ".%d", XORG_VERSION_SNAP); -#endif - -#if XORG_VERSION_SNAP >= 900 - /* When the minor number is 99, that signifies that the we are making - * a release candidate for a major version. (X.0.0) - * When the patch number is 99, that signifies that the we are making - * a release candidate for a minor version. (X.Y.0) - * When the patch number is < 99, then we are making a release - * candidate for the next point release. (X.Y.Z) - */ -#if XORG_VERSION_MINOR >= 99 - xf86ErrorFVerb(0, " (%d.0.0 RC %d)", XORG_VERSION_MAJOR+1, - XORG_VERSION_SNAP - 900); -#elif XORG_VERSION_PATCH == 99 - xf86ErrorFVerb(0, " (%d.%d.0 RC %d)", XORG_VERSION_MAJOR, - XORG_VERSION_MINOR + 1, XORG_VERSION_SNAP - 900); -#else - xf86ErrorFVerb(0, " (%d.%d.%d RC %d)", XORG_VERSION_MAJOR, - XORG_VERSION_MINOR, XORG_VERSION_PATCH + 1, - XORG_VERSION_SNAP - 900); -#endif -#endif - -#ifdef XORG_CUSTOM_VERSION - xf86ErrorFVerb(0, " (%s)", XORG_CUSTOM_VERSION); -#endif -#ifndef XORG_DATE -# define XORG_DATE "Unknown" -#endif - xf86ErrorFVerb(0, "\nRelease Date: %s\n", XORG_DATE); - xf86ErrorFVerb(0, "X Protocol Version %d, Revision %d\n", - X_PROTOCOL, X_PROTOCOL_REVISION); - xf86ErrorFVerb(0, "Build Operating System: %s %s\n", OSNAME, OSVENDOR); -#ifdef HAS_UTSNAME - { - struct utsname name; - - /* Linux & BSD state that 0 is success, SysV (including Solaris, HP-UX, - and Irix) and Single Unix Spec 3 just say that non-negative is success. - All agree that failure is represented by a negative number. - */ - if (uname(&name) >= 0) { - xf86ErrorFVerb(0, "Current Operating System: %s %s %s %s %s\n", - name.sysname, name.nodename, name.release, name.version, name.machine); -#ifdef linux - do { - char buf[80]; - int fd = open("/proc/cmdline", O_RDONLY); - if (fd != -1) { - xf86ErrorFVerb(0, "Kernel command line: "); - memset(buf, 0, 80); - while (read(fd, buf, 80) > 0) { - xf86ErrorFVerb(0, "%.80s", buf); - memset(buf, 0, 80); - } - close(fd); - } - } while (0); -#endif - } - } -#endif -#if defined(BUILD_DATE) && (BUILD_DATE > 19000000) - { - struct tm t; - char buf[100]; - - bzero(&t, sizeof(t)); - bzero(buf, sizeof(buf)); - t.tm_mday = BUILD_DATE % 100; - t.tm_mon = (BUILD_DATE / 100) % 100 - 1; - t.tm_year = BUILD_DATE / 10000 - 1900; -#if defined(BUILD_TIME) - t.tm_sec = BUILD_TIME % 100; - t.tm_min = (BUILD_TIME / 100) % 100; - t.tm_hour = (BUILD_TIME / 10000) % 100; - if (strftime(buf, sizeof(buf), "%d %B %Y %I:%M:%S%p", &t)) - xf86ErrorFVerb(0, "Build Date: %s\n", buf); -#else - if (strftime(buf, sizeof(buf), "%d %B %Y", &t)) - xf86ErrorFVerb(0, "Build Date: %s\n", buf); -#endif - } -#endif -#if defined(BUILDERSTRING) - xf86ErrorFVerb(0, "%s \n", BUILDERSTRING); -#endif - xf86ErrorFVerb(0, "Current version of pixman: %s\n", - pixman_version_string()); - xf86ErrorFVerb(0, "\tBefore reporting problems, check " - ""__VENDORDWEBSUPPORT__"\n" - "\tto make sure that you have the latest version.\n"); -} - -static void -xf86PrintMarkers(void) -{ - LogPrintMarkers(); -} - -static Bool -xf86CreateRootWindow(WindowPtr pWin) -{ - int ret = TRUE; - int err = Success; - ScreenPtr pScreen = pWin->drawable.pScreen; - RootWinPropPtr pProp; - CreateWindowProcPtr CreateWindow = (CreateWindowProcPtr) - dixLookupPrivate(&pScreen->devPrivates, xf86CreateRootWindowKey); - - DebugF("xf86CreateRootWindow(%p)\n", pWin); - - if ( pScreen->CreateWindow != xf86CreateRootWindow ) { - /* Can't find hook we are hung on */ - xf86DrvMsg(pScreen->myNum, X_WARNING /* X_ERROR */, - "xf86CreateRootWindow %p called when not in pScreen->CreateWindow %p n", - (void *)xf86CreateRootWindow, - (void *)pScreen->CreateWindow ); - } - - /* Unhook this function ... */ - pScreen->CreateWindow = CreateWindow; - dixSetPrivate(&pScreen->devPrivates, xf86CreateRootWindowKey, NULL); - - /* ... and call the previous CreateWindow fuction, if any */ - if (NULL!=pScreen->CreateWindow) { - ret = (*pScreen->CreateWindow)(pWin); - } - - /* Now do our stuff */ - if (xf86RegisteredPropertiesTable != NULL) { - if (pWin->parent == NULL && xf86RegisteredPropertiesTable != NULL) { - for (pProp = xf86RegisteredPropertiesTable[pScreen->myNum]; - pProp != NULL && err==Success; - pProp = pProp->next ) - { - Atom prop; - - prop = MakeAtom(pProp->name, strlen(pProp->name), TRUE); - err = dixChangeWindowProperty(serverClient, pWin, - prop, pProp->type, - pProp->format, PropModeReplace, - pProp->size, pProp->data, - FALSE); - } - - /* Look at err */ - ret &= (err==Success); - - } else { - xf86Msg(X_ERROR, "xf86CreateRootWindow unexpectedly called with " - "non-root window %p (parent %p)\n", - (void *)pWin, (void *)pWin->parent); - ret = FALSE; - } - } - - DebugF("xf86CreateRootWindow() returns %d\n", ret); - return (ret); -} - - -static void -InstallSignalHandlers(void) -{ - /* - * Install signal handler for unexpected signals - */ - xf86Info.caughtSignal=FALSE; - if (!xf86Info.notrapSignals) { - OsRegisterSigWrapper(xf86SigWrapper); - } else { - signal(SIGSEGV, SIG_DFL); - signal(SIGILL, SIG_DFL); -#ifdef SIGEMT - signal(SIGEMT, SIG_DFL); -#endif - signal(SIGFPE, SIG_DFL); -#ifdef SIGBUS - signal(SIGBUS, SIG_DFL); -#endif -#ifdef SIGSYS - signal(SIGSYS, SIG_DFL); -#endif -#ifdef SIGXCPU - signal(SIGXCPU, SIG_DFL); -#endif -#ifdef SIGXFSZ - signal(SIGXFSZ, SIG_DFL); -#endif - } -} - - -#define END_OF_MATCHES(m) \ - (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) - -Bool -probe_devices_from_device_sections(DriverPtr drvp) -{ - int i, j; - struct pci_device * pPci; - Bool foundScreen = FALSE; - const struct pci_id_match * const devices = drvp->supported_devices; - GDevPtr *devList; - const unsigned numDevs = xf86MatchDevice(drvp->driverName, & devList); - - - for ( i = 0 ; i < numDevs ; i++ ) { - struct pci_device_iterator *iter; - unsigned device_id; - - - /* Find the pciVideoRec associated with this device section. - */ - iter = pci_id_match_iterator_create(NULL); - while ((pPci = pci_device_next(iter)) != NULL) { - if (devList[i]->busID && *devList[i]->busID) { - if (xf86ComparePciBusString(devList[i]->busID, - ((pPci->domain << 8) - | pPci->bus), - pPci->dev, - pPci->func)) { - break; - } - } - else if (xf86IsPrimaryPci(pPci)) { - break; - } - } - - pci_iterator_destroy(iter); - - if (pPci == NULL) { - continue; - } - - device_id = (devList[i]->chipID > 0) - ? devList[i]->chipID : pPci->device_id; - - - /* Once the pciVideoRec is found, determine if the device is supported - * by the driver. If it is, probe it! - */ - for ( j = 0 ; ! END_OF_MATCHES( devices[j] ) ; j++ ) { - if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) - && PCI_ID_COMPARE( devices[j].device_id, device_id ) - && ((devices[j].device_class_mask & pPci->device_class) - == devices[j].device_class) ) { - int entry; - - /* Allow the same entity to be used more than once for - * devices with multiple screens per entity. This assumes - * implicitly that there will be a screen == 0 instance. - * - * FIXME Need to make sure that two different drivers don't - * FIXME claim the same screen > 0 instance. - */ - if ( (devList[i]->screen == 0) && !xf86CheckPciSlot( pPci ) ) - continue; - - DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", - drvp->driverName, pPci->bus, pPci->dev, pPci->func); - - /* Allocate an entry in the lists to be returned */ - entry = xf86ClaimPciSlot(pPci, drvp, device_id, - devList[i], devList[i]->active); - - if ((entry == -1) && (devList[i]->screen > 0)) { - unsigned k; - - for ( k = 0; k < xf86NumEntities; k++ ) { - EntityPtr pEnt = xf86Entities[k]; - if (pEnt->bus.type != BUS_PCI) - continue; - - if (pEnt->bus.id.pci == pPci) { - entry = k; - xf86AddDevToEntity(k, devList[i]); - break; - } - } - } - - if (entry != -1) { - if ((*drvp->PciProbe)(drvp, entry, pPci, - devices[j].match_data)) { - foundScreen = TRUE; - } else - xf86UnclaimPciSlot(pPci); - } - - break; - } - } - } - xfree(devList); - - return foundScreen; -} - - -Bool -add_matching_devices_to_configure_list(DriverPtr drvp) -{ - const struct pci_id_match * const devices = drvp->supported_devices; - int j; - struct pci_device *pPci; - struct pci_device_iterator *iter; - int numFound = 0; - - - iter = pci_id_match_iterator_create(NULL); - while ((pPci = pci_device_next(iter)) != NULL) { - /* Determine if this device is supported by the driver. If it is, - * add it to the list of devices to configure. - */ - for (j = 0 ; ! END_OF_MATCHES(devices[j]) ; j++) { - if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) - && PCI_ID_COMPARE( devices[j].device_id, pPci->device_id ) - && ((devices[j].device_class_mask & pPci->device_class) - == devices[j].device_class) ) { - if (xf86CheckPciSlot(pPci)) { - GDevPtr pGDev = xf86AddBusDeviceToConfigure( - drvp->driverName, BUS_PCI, pPci, -1); - if (pGDev != NULL) { - /* After configure pass 1, chipID and chipRev are - * treated as over-rides, so clobber them here. - */ - pGDev->chipID = -1; - pGDev->chipRev = -1; - } - - numFound++; - } - - break; - } - } - } - - pci_iterator_destroy(iter); - - - return (numFound != 0); -} - -/** - * Call the driver's correct probe function. - * - * If the driver implements the \c DriverRec::PciProbe entry-point and an - * appropriate PCI device (with matching Device section in the xorg.conf file) - * is found, it is called. If \c DriverRec::PciProbe or no devices can be - * successfully probed with it (e.g., only non-PCI devices are available), - * the driver's \c DriverRec::Probe function is called. - * - * \param drv Driver to probe - * - * \return - * If a device can be successfully probed by the driver, \c TRUE is - * returned. Otherwise, \c FALSE is returned. - */ -Bool -xf86CallDriverProbe( DriverPtr drv, Bool detect_only ) -{ - Bool foundScreen = FALSE; - - if ( drv->PciProbe != NULL ) { - if ( xf86DoConfigure && xf86DoConfigurePass1 ) { - assert( detect_only ); - foundScreen = add_matching_devices_to_configure_list( drv ); - } - else { - assert( ! detect_only ); - foundScreen = probe_devices_from_device_sections( drv ); - } - } - - if ( ! foundScreen && (drv->Probe != NULL) ) { - xf86Msg( X_WARNING, "Falling back to old probe method for %s\n", - drv->driverName ); - foundScreen = (*drv->Probe)( drv, (detect_only) ? PROBE_DETECT - : PROBE_DEFAULT ); - } - - return foundScreen; -} - -/* - * InitOutput -- - * Initialize screenInfo for all actually accessible framebuffers. - * That includes vt-manager setup, querying all possible devices and - * collecting the pixmap formats. - */ -void -InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) -{ - int i, j, k, scr_index; - char **modulelist; - pointer *optionlist; - screenLayoutPtr layout; - Pix24Flags screenpix24, pix24; - MessageType pix24From = X_DEFAULT; - Bool pix24Fail = FALSE; - Bool autoconfig = FALSE; - GDevPtr configured_device; - - xf86Initialising = TRUE; - - if (serverGeneration == 1) { - if ((xf86ServerName = strrchr(argv[0], '/')) != 0) - xf86ServerName++; - else - xf86ServerName = argv[0]; - - xf86PrintBanner(); - xf86PrintMarkers(); - if (xf86LogFile) { - time_t t; - const char *ct; - t = time(NULL); - ct = ctime(&t); - xf86MsgVerb(xf86LogFileFrom, 0, "Log file: \"%s\", Time: %s", - xf86LogFile, ct); - } - - /* Read and parse the config file */ - if (!xf86DoConfigure && !xf86DoShowOptions) { - switch (xf86HandleConfigFile(FALSE)) { - case CONFIG_OK: - break; - case CONFIG_PARSE_ERROR: - xf86Msg(X_ERROR, "Error parsing the config file\n"); - return; - case CONFIG_NOFILE: - autoconfig = TRUE; - break; - } - } - - InstallSignalHandlers(); - - /* Initialise the loader */ - LoaderInit(); - - /* Tell the loader the default module search path */ - LoaderSetPath(xf86ModulePath); - - if (xf86Info.ignoreABI) { - LoaderSetOptions(LDR_OPT_ABI_MISMATCH_NONFATAL); - } - - if (xf86DoShowOptions) - DoShowOptions(); - - /* Do a general bus probe. This will be a PCI probe for x86 platforms */ - xf86BusProbe(); - - if (xf86DoConfigure) - DoConfigure(); - - if (autoconfig) { - if (!xf86AutoConfig()) { - xf86Msg(X_ERROR, "Auto configuration failed\n"); - return; - } - } - -#ifdef XF86PM - xf86OSPMClose = xf86OSPMOpen(); -#endif - - /* Load all modules specified explicitly in the config file */ - if ((modulelist = xf86ModulelistFromConfig(&optionlist))) { - xf86LoadModules(modulelist, optionlist); - xfree(modulelist); - xfree(optionlist); - } - - /* Load all driver modules specified in the config file */ - /* If there aren't any specified in the config file, autoconfig them */ - /* FIXME: Does not handle multiple active screen sections, but I'm not - * sure if we really want to handle that case*/ - configured_device = xf86ConfigLayout.screens->screen->device; - if ((!configured_device) || (!configured_device->driver)) { - if (!autoConfigDevice(configured_device)) { - xf86Msg(X_ERROR, "Automatic driver configuration failed\n"); - return ; - } - } - if ((modulelist = xf86DriverlistFromConfig())) { - xf86LoadModules(modulelist, NULL); - xfree(modulelist); - } - - /* Load all input driver modules specified in the config file. */ - if ((modulelist = xf86InputDriverlistFromConfig())) { - xf86LoadModules(modulelist, NULL); - xfree(modulelist); - } - - /* - * It is expected that xf86AddDriver()/xf86AddInputDriver will be - * called for each driver as it is loaded. Those functions save the - * module pointers for drivers. - * XXX Nothing keeps track of them for other modules. - */ - /* XXX What do we do if not all of these could be loaded? */ - - /* - * At this point, xf86DriverList[] is all filled in with entries for - * each of the drivers to try and xf86NumDrivers has the number of - * drivers. If there are none, return now. - */ - - if (xf86NumDrivers == 0) { - xf86Msg(X_ERROR, "No drivers available.\n"); - return; - } - - /* - * Call each of the Identify functions and call the driverFunc to check - * if HW access is required. The Identify functions print out some - * identifying information, and anything else that might be - * needed at this early stage. - */ - - for (i = 0; i < xf86NumDrivers; i++) { - if (xf86DriverList[i]->Identify != NULL) - xf86DriverList[i]->Identify(0); - - if (!xorgHWAccess || !xorgHWOpenConsole) { - xorgHWFlags flags; - if(!xf86DriverList[i]->driverFunc - || !xf86DriverList[i]->driverFunc(NULL, - GET_REQUIRED_HW_INTERFACES, - &flags)) - flags = HW_IO; - - if(NEED_IO_ENABLED(flags)) - xorgHWAccess = TRUE; - if(!(flags & HW_SKIP_CONSOLE)) - xorgHWOpenConsole = TRUE; - } - } - - if (xorgHWOpenConsole) - xf86OpenConsole(); - else - xf86Info.dontVTSwitch = TRUE; - - /* Enable full I/O access */ - if (xorgHWAccess) - xorgHWAccess = xf86EnableIO(); - - /* - * Locate bus slot that had register IO enabled at server startup - */ - if (xorgHWAccess) { - xf86AccessInit(); - xf86FindPrimaryDevice(); - } - /* - * Now call each of the Probe functions. Each successful probe will - * result in an extra entry added to the xf86Screens[] list for each - * instance of the hardware found. - */ - - for (i = 0; i < xf86NumDrivers; i++) { - xorgHWFlags flags; - if (!xorgHWAccess) { - if (!xf86DriverList[i]->driverFunc - || !xf86DriverList[i]->driverFunc(NULL, - GET_REQUIRED_HW_INTERFACES, - &flags) - || NEED_IO_ENABLED(flags)) - continue; - } - - xf86CallDriverProbe( xf86DriverList[i], FALSE ); - } - - /* - * If nothing was detected, return now. - */ - - if (xf86NumScreens == 0) { - xf86Msg(X_ERROR, "No devices detected.\n"); - return; - } - - xf86VGAarbiterInit(); - - /* - * Match up the screens found by the probes against those specified - * in the config file. Remove the ones that won't be used. Sort - * them in the order specified. - */ - - /* - * What is the best way to do this? - * - * For now, go through the screens allocated by the probes, and - * look for screen config entry which refers to the same device - * section as picked out by the probe. - * - */ - - for (i = 0; i < xf86NumScreens; i++) { - for (layout = xf86ConfigLayout.screens; layout->screen != NULL; - layout++) { - Bool found = FALSE; - for (j = 0; j < xf86Screens[i]->numEntities; j++) { - - GDevPtr dev = - xf86GetDevFromEntity(xf86Screens[i]->entityList[j], - xf86Screens[i]->entityInstanceList[j]); - - if (dev == layout->screen->device) { - /* A match has been found */ - xf86Screens[i]->confScreen = layout->screen; - found = TRUE; - break; - } - } - if (found) break; - } - if (layout->screen == NULL) { - /* No match found */ - xf86Msg(X_ERROR, - "Screen %d deleted because of no matching config section.\n", i); - xf86DeleteScreen(i--, 0); - } - } - - /* - * If no screens left, return now. - */ - - if (xf86NumScreens == 0) { - xf86Msg(X_ERROR, - "Device(s) detected, but none match those in the config file.\n"); - return; - } - - xf86PostProbe(); - xf86EntityInit(); - - /* - * Sort the drivers to match the requested ording. Using a slow - * bubble sort. - */ - for (j = 0; j < xf86NumScreens - 1; j++) { - for (i = 0; i < xf86NumScreens - j - 1; i++) { - if (xf86Screens[i + 1]->confScreen->screennum < - xf86Screens[i]->confScreen->screennum) { - ScrnInfoPtr tmpScrn = xf86Screens[i + 1]; - xf86Screens[i + 1] = xf86Screens[i]; - xf86Screens[i] = tmpScrn; - } - } - } - /* Fix up the indexes */ - for (i = 0; i < xf86NumScreens; i++) { - xf86Screens[i]->scrnIndex = i; - } - - /* - * Call the driver's PreInit()'s to complete initialisation for the first - * generation. - */ - - for (i = 0; i < xf86NumScreens; i++) { - xf86VGAarbiterScrnInit(xf86Screens[i]); - xf86VGAarbiterLock(xf86Screens[i]); - if (xf86Screens[i]->PreInit && - xf86Screens[i]->PreInit(xf86Screens[i], 0)) - xf86Screens[i]->configured = TRUE; - xf86VGAarbiterUnlock(xf86Screens[i]); - } - for (i = 0; i < xf86NumScreens; i++) - if (!xf86Screens[i]->configured) - xf86DeleteScreen(i--, 0); - - /* - * If no screens left, return now. - */ - - if (xf86NumScreens == 0) { - xf86Msg(X_ERROR, - "Screen(s) found, but none have a usable configuration.\n"); - return; - } - - for (i = 0; i < xf86NumScreens; i++) { - if (xf86Screens[i]->name == NULL) { - xf86Screens[i]->name = xnfalloc(strlen("screen") + 10 + 1); - sprintf(xf86Screens[i]->name, "screen%d", i); - xf86MsgVerb(X_WARNING, 0, - "Screen driver %d has no name set, using `%s'.\n", - i, xf86Screens[i]->name); - } - } - - /* Remove (unload) drivers that are not required */ - for (i = 0; i < xf86NumDrivers; i++) - if (xf86DriverList[i] && xf86DriverList[i]->refCount <= 0) - xf86DeleteDriver(i); - - /* - * At this stage we know how many screens there are. - */ - - for (i = 0; i < xf86NumScreens; i++) - xf86InitViewport(xf86Screens[i]); - - /* - * Collect all pixmap formats and check for conflicts at the display - * level. Should we die here? Or just delete the offending screens? - */ - screenpix24 = Pix24DontCare; - for (i = 0; i < xf86NumScreens; i++) { - if (xf86Screens[i]->imageByteOrder != - xf86Screens[0]->imageByteOrder) - FatalError("Inconsistent display bitmapBitOrder. Exiting\n"); - if (xf86Screens[i]->bitmapScanlinePad != - xf86Screens[0]->bitmapScanlinePad) - FatalError("Inconsistent display bitmapScanlinePad. Exiting\n"); - if (xf86Screens[i]->bitmapScanlineUnit != - xf86Screens[0]->bitmapScanlineUnit) - FatalError("Inconsistent display bitmapScanlineUnit. Exiting\n"); - if (xf86Screens[i]->bitmapBitOrder != - xf86Screens[0]->bitmapBitOrder) - FatalError("Inconsistent display bitmapBitOrder. Exiting\n"); - - /* Determine the depth 24 pixmap format the screens would like */ - if (xf86Screens[i]->pixmap24 != Pix24DontCare) { - if (screenpix24 == Pix24DontCare) - screenpix24 = xf86Screens[i]->pixmap24; - else if (screenpix24 != xf86Screens[i]->pixmap24) - FatalError("Inconsistent depth 24 pixmap format. Exiting\n"); - } - } - /* check if screenpix24 is consistent with the config/cmdline */ - if (xf86Info.pixmap24 != Pix24DontCare) { - pix24 = xf86Info.pixmap24; - pix24From = xf86Info.pix24From; - if (screenpix24 != Pix24DontCare && screenpix24 != xf86Info.pixmap24) - pix24Fail = TRUE; - } else if (screenpix24 != Pix24DontCare) { - pix24 = screenpix24; - pix24From = X_PROBED; - } else - pix24 = Pix24Use32; - - if (pix24Fail) - FatalError("Screen(s) can't use the required depth 24 pixmap format" - " (%d). Exiting\n", PIX24TOBPP(pix24)); - - /* Initialise the depth 24 format */ - for (j = 0; j < numFormats && formats[j].depth != 24; j++) - ; - formats[j].bitsPerPixel = PIX24TOBPP(pix24); - - /* Collect additional formats */ - for (i = 0; i < xf86NumScreens; i++) { - for (j = 0; j < xf86Screens[i]->numFormats; j++) { - for (k = 0; ; k++) { - if (k >= numFormats) { - if (k >= MAXFORMATS) - FatalError("Too many pixmap formats! Exiting\n"); - formats[k] = xf86Screens[i]->formats[j]; - numFormats++; - break; - } - if (formats[k].depth == xf86Screens[i]->formats[j].depth) { - if ((formats[k].bitsPerPixel == - xf86Screens[i]->formats[j].bitsPerPixel) && - (formats[k].scanlinePad == - xf86Screens[i]->formats[j].scanlinePad)) - break; - FatalError("Inconsistent pixmap format for depth %d." - " Exiting\n", formats[k].depth); - } - } - } - } - formatsDone = TRUE; - - if (xf86Info.vtno >= 0 ) { -#define VT_ATOM_NAME "XFree86_VT" - Atom VTAtom=-1; - CARD32 *VT = NULL; - int ret; - - /* This memory needs to stay available until the screen has been - initialized, and we can create the property for real. - */ - if ( (VT = xalloc(sizeof(CARD32)))==NULL ) { - FatalError("Unable to make VT property - out of memory. Exiting...\n"); - } - *VT = xf86Info.vtno; - - VTAtom = MakeAtom(VT_ATOM_NAME, sizeof(VT_ATOM_NAME) - 1, TRUE); - - for (i = 0, ret = Success; i < xf86NumScreens && ret == Success; i++) { - ret = xf86RegisterRootWindowProperty(xf86Screens[i]->scrnIndex, - VTAtom, XA_INTEGER, 32, - 1, VT ); - if (ret != Success) - xf86DrvMsg(xf86Screens[i]->scrnIndex, X_WARNING, - "Failed to register VT property\n"); - } - } - - /* If a screen uses depth 24, show what the pixmap format is */ - for (i = 0; i < xf86NumScreens; i++) { - if (xf86Screens[i]->depth == 24) { - xf86Msg(pix24From, "Depth 24 pixmap format is %d bpp\n", - PIX24TOBPP(pix24)); - break; - } - } - } else { - /* - * serverGeneration != 1; some OSs have to do things here, too. - */ - if (xorgHWOpenConsole) - xf86OpenConsole(); - -#ifdef XF86PM - /* - should we reopen it here? We need to deal with an already opened - device. We could leave this to the OS layer. For now we simply - close it here - */ - if (xf86OSPMClose) - xf86OSPMClose(); - if ((xf86OSPMClose = xf86OSPMOpen()) != NULL) - xf86MsgVerb(X_INFO, 3, "APM registered successfully\n"); -#endif - - /* Make sure full I/O access is enabled */ - if (xorgHWAccess) - xf86EnableIO(); - } - - /* - * Use the previously collected parts to setup pScreenInfo - */ - - pScreenInfo->imageByteOrder = xf86Screens[0]->imageByteOrder; - pScreenInfo->bitmapScanlinePad = xf86Screens[0]->bitmapScanlinePad; - pScreenInfo->bitmapScanlineUnit = xf86Screens[0]->bitmapScanlineUnit; - pScreenInfo->bitmapBitOrder = xf86Screens[0]->bitmapBitOrder; - pScreenInfo->numPixmapFormats = numFormats; - for (i = 0; i < numFormats; i++) - pScreenInfo->formats[i] = formats[i]; - - /* Make sure the server's VT is active */ - - if (serverGeneration != 1) { - xf86Resetting = TRUE; - /* All screens are in the same state, so just check the first */ - if (!xf86Screens[0]->vtSema) { -#ifdef HAS_USL_VTS - ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ); -#endif - xf86AccessEnter(); - xf86EnterServerState(SETUP); - } - } -#ifdef SCO325 - else { - /* - * Under SCO we must ack that we got the console at startup, - * I think this is the safest way to assure it. - */ - static int once = 1; - if (once) { - once = 0; - if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0) - xf86Msg(X_WARNING, "VT_ACKACQ failed"); - } - } -#endif /* SCO325 */ - - for (i = 0; i < xf86NumScreens; i++) { - xf86VGAarbiterLock(xf86Screens[i]); - /* - * Almost everything uses these defaults, and many of those that - * don't, will wrap them. - */ - xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess; -#ifdef XFreeXDGA - xf86Screens[i]->SetDGAMode = xf86SetDGAMode; -#endif - xf86Screens[i]->DPMSSet = NULL; - xf86Screens[i]->LoadPalette = NULL; - xf86Screens[i]->SetOverscan = NULL; - xf86Screens[i]->DriverFunc = NULL; - xf86Screens[i]->pScreen = NULL; - scr_index = AddScreen(xf86Screens[i]->ScreenInit, argc, argv); - xf86VGAarbiterUnlock(xf86Screens[i]); - if (scr_index == i) { - /* - * Hook in our ScrnInfoRec, and initialise some other pScreen - * fields. - */ - dixSetPrivate(&screenInfo.screens[scr_index]->devPrivates, - xf86ScreenKey, xf86Screens[i]); - xf86Screens[i]->pScreen = screenInfo.screens[scr_index]; - /* The driver should set this, but make sure it is set anyway */ - xf86Screens[i]->vtSema = TRUE; - } else { - /* This shouldn't normally happen */ - FatalError("AddScreen/ScreenInit failed for driver %d\n", i); - } - - DebugF("InitOutput - xf86Screens[%d]->pScreen = %p\n", - i, xf86Screens[i]->pScreen ); - DebugF("xf86Screens[%d]->pScreen->CreateWindow = %p\n", - i, xf86Screens[i]->pScreen->CreateWindow ); - - dixSetPrivate(&screenInfo.screens[scr_index]->devPrivates, - xf86CreateRootWindowKey, - xf86Screens[i]->pScreen->CreateWindow); - xf86Screens[i]->pScreen->CreateWindow = xf86CreateRootWindow; - - if (PictureGetSubpixelOrder (xf86Screens[i]->pScreen) == SubPixelUnknown) - { - xf86MonPtr DDC = (xf86MonPtr)(xf86Screens[i]->monitor->DDC); - PictureSetSubpixelOrder (xf86Screens[i]->pScreen, - DDC ? - (DDC->features.input_type ? - SubPixelHorizontalRGB : SubPixelNone) : - SubPixelUnknown); - } -#ifdef RANDR - if (!xf86Info.disableRandR) - xf86RandRInit (screenInfo.screens[scr_index]); - xf86Msg(xf86Info.randRFrom, "RandR %s\n", - xf86Info.disableRandR ? "disabled" : "enabled"); -#endif - } - - xf86PostScreenInit(); - - xf86InitOrigins(); - - xf86Resetting = FALSE; - xf86Initialising = FALSE; - - RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, xf86Wakeup, - NULL); -} - -/* - * InitInput -- - * Initialize all supported input devices. - */ - -void -InitInput(int argc, char **argv) -{ - IDevPtr* pDev; - DeviceIntPtr dev; - - xf86Info.vtRequestsPending = FALSE; - - mieqInit(); - - GetEventList(&xf86Events); - - /* Call the PreInit function for each input device instance. */ - for (pDev = xf86ConfigLayout.inputs; pDev && *pDev; pDev++) { - /* Replace obsolete keyboard driver with kbd */ - if (!xf86NameCmp((*pDev)->driver, "keyboard")) { - strcpy((*pDev)->driver, "kbd"); - } - - /* If one fails, the others will too */ - if (xf86NewInputDevice(*pDev, &dev, TRUE) == BadAlloc) - break; - } - - config_init(); -} - -void -CloseInput (void) -{ - config_fini(); -} - -/* - * OsVendorInit -- - * OS/Vendor-specific initialisations. Called from OsInit(), which - * is called by dix before establishing the well known sockets. - */ - -void -OsVendorInit(void) -{ - static Bool beenHere = FALSE; - -#ifdef SIGCHLD - signal(SIGCHLD, SIG_DFL); /* Need to wait for child processes */ -#endif - - if (!beenHere) { - umask(022); - xf86LogInit(); - } - - /* Set stderr to non-blocking. */ -#ifndef O_NONBLOCK -#if defined(FNDELAY) -#define O_NONBLOCK FNDELAY -#elif defined(O_NDELAY) -#define O_NONBLOCK O_NDELAY -#endif - -#ifdef O_NONBLOCK - if (!beenHere) { - if (geteuid() == 0 && getuid() != geteuid()) - { - int status; - - status = fcntl(fileno(stderr), F_GETFL, 0); - if (status != -1) { - fcntl(fileno(stderr), F_SETFL, status | O_NONBLOCK); - } - } - } -#endif -#endif - - beenHere = TRUE; -} - -/* - * ddxGiveUp -- - * Device dependent cleanup. Called by by dix before normal server death. - * For SYSV386 we must switch the terminal back to normal mode. No error- - * checking here, since there should be restored as much as possible. - */ - -void -ddxGiveUp(void) -{ - int i; - - xf86VGAarbiterFini(); - -#ifdef XF86PM - if (xf86OSPMClose) - xf86OSPMClose(); - xf86OSPMClose = NULL; -#endif - - for (i = 0; i < xf86NumScreens; i++) { - /* - * zero all access functions to - * trap calls when switched away. - */ - xf86Screens[i]->vtSema = FALSE; - } - -#ifdef XFreeXDGA - DGAShutdown(); -#endif - - if (xorgHWOpenConsole) - xf86CloseConsole(); - - xf86CloseLog(); - - /* If an unexpected signal was caught, dump a core for debugging */ - if (xf86Info.caughtSignal) - OsAbort(); -} - - - -/* - * AbortDDX -- - * DDX - specific abort routine. Called by AbortServer(). The attempt is - * made to restore all original setting of the displays. Also all devices - * are closed. - */ - -void -AbortDDX(void) -{ - int i; - - /* - * try to restore the original video state - */ -#ifdef DPMSExtension /* Turn screens back on */ - if (DPMSPowerLevel != DPMSModeOn) - DPMSSet(serverClient, DPMSModeOn); -#endif - if (xf86Screens) { - if (xf86Screens[0]->vtSema) - xf86EnterServerState(SETUP); - for (i = 0; i < xf86NumScreens; i++) - if (xf86Screens[i]->vtSema) { - /* - * if we are aborting before ScreenInit() has finished - * we might not have been wrapped yet. Therefore enable - * screen explicitely. - */ - xf86VGAarbiterLock(xf86Screens[i]); - (xf86Screens[i]->LeaveVT)(i, 0); - xf86VGAarbiterUnlock(xf86Screens[i]); - } - } - - xf86AccessLeave(); - - /* - * This is needed for an abnormal server exit, since the normal exit stuff - * MUST also be performed (i.e. the vt must be left in a defined state) - */ - ddxGiveUp(); -} - -void -OsVendorFatalError(void) -{ -#ifdef VENDORSUPPORT - ErrorF("\nPlease refer to your Operating System Vendor support pages\n" - "at %s for support on this crash.\n",VENDORSUPPORT); -#else - ErrorF("\nPlease consult the "XVENDORNAME" support \n" - "\t at "__VENDORDWEBSUPPORT__"\n for help. \n"); -#endif - if (xf86LogFile && xf86LogFileWasOpened) - ErrorF("Please also check the log file at \"%s\" for additional " - "information.\n", xf86LogFile); - ErrorF("\n"); -} - -int -xf86SetVerbosity(int verb) -{ - int save = xf86Verbose; - - xf86Verbose = verb; - LogSetParameter(XLOG_VERBOSITY, verb); - return save; -} - -int -xf86SetLogVerbosity(int verb) -{ - int save = xf86LogVerbose; - - xf86LogVerbose = verb; - LogSetParameter(XLOG_FILE_VERBOSITY, verb); - return save; -} - -static void -xf86PrintDefaultModulePath(void) -{ - ErrorF("%s\n", DEFAULT_MODULE_PATH); -} - -static void -xf86PrintDefaultLibraryPath(void) -{ - ErrorF("%s\n", DEFAULT_LIBRARY_PATH); -} - -/* - * ddxProcessArgument -- - * Process device-dependent command line args. Returns 0 if argument is - * not device dependent, otherwise Count of number of elements of argv - * that are part of a device dependent commandline option. - * - */ - -/* ARGSUSED */ -int -ddxProcessArgument(int argc, char **argv, int i) -{ - /* - * Note: can't use xalloc/xfree here because OsInit() hasn't been called - * yet. Use malloc/free instead. - */ - -#define CHECK_FOR_REQUIRED_ARGUMENT() \ - if (((i + 1) >= argc) || (!argv[i + 1])) { \ - ErrorF("Required argument to %s not specified\n", argv[i]); \ - UseMsg(); \ - FatalError("Required argument to %s not specified\n", argv[i]); \ - } - - /* First the options that are only allowed for root */ - if (!strcmp(argv[i], "-modulepath") || !strcmp(argv[i], "-logfile")) { - if ( (geteuid() == 0) && (getuid() != 0) ) { - FatalError("The '%s' option can only be used by root.\n", argv[i]); - } - else if (!strcmp(argv[i], "-modulepath")) - { - char *mp; - CHECK_FOR_REQUIRED_ARGUMENT(); - mp = malloc(strlen(argv[i + 1]) + 1); - if (!mp) - FatalError("Can't allocate memory for ModulePath\n"); - strcpy(mp, argv[i + 1]); - xf86ModulePath = mp; - xf86ModPathFrom = X_CMDLINE; - return 2; - } - else if (!strcmp(argv[i], "-logfile")) - { - char *lf; - CHECK_FOR_REQUIRED_ARGUMENT(); - lf = malloc(strlen(argv[i + 1]) + 1); - if (!lf) - FatalError("Can't allocate memory for LogFile\n"); - strcpy(lf, argv[i + 1]); - xf86LogFile = lf; - xf86LogFileFrom = X_CMDLINE; - return 2; - } - } - if (!strcmp(argv[i], "-config") || !strcmp(argv[i], "-xf86config")) - { - CHECK_FOR_REQUIRED_ARGUMENT(); - if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) { - FatalError("\nInvalid argument for %s\n" - "\tFor non-root users, the file specified with %s must be\n" - "\ta relative path and must not contain any \"..\" elements.\n" - "\tUsing default "__XCONFIGFILE__" search path.\n\n", - argv[i], argv[i]); - } - xf86ConfigFile = argv[i + 1]; - return 2; - } - if (!strcmp(argv[i], "-configdir")) - { - CHECK_FOR_REQUIRED_ARGUMENT(); - if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) { - FatalError("\nInvalid argument for %s\n" - "\tFor non-root users, the file specified with %s must be\n" - "\ta relative path and must not contain any \"..\" elements.\n" - "\tUsing default "__XCONFIGDIR__" search path.\n\n", - argv[i], argv[i]); - } - xf86ConfigDir = argv[i + 1]; - return 2; - } - if (!strcmp(argv[i],"-flipPixels")) - { - xf86FlipPixels = TRUE; - return 1; - } -#ifdef XF86VIDMODE - if (!strcmp(argv[i],"-disableVidMode")) - { - xf86VidModeDisabled = TRUE; - return 1; - } - if (!strcmp(argv[i],"-allowNonLocalXvidtune")) - { - xf86VidModeAllowNonLocal = TRUE; - return 1; - } -#endif - if (!strcmp(argv[i],"-allowMouseOpenFail")) - { - xf86AllowMouseOpenFail = TRUE; - return 1; - } - if (!strcmp(argv[i],"-ignoreABI")) - { - LoaderSetOptions(LDR_OPT_ABI_MISMATCH_NONFATAL); - return 1; - } - if (!strcmp(argv[i],"-verbose")) - { - if (++i < argc && argv[i]) - { - char *end; - long val; - val = strtol(argv[i], &end, 0); - if (*end == '\0') - { - xf86SetVerbosity(val); - return 2; - } - } - xf86SetVerbosity(++xf86Verbose); - return 1; - } - if (!strcmp(argv[i],"-logverbose")) - { - if (++i < argc && argv[i]) - { - char *end; - long val; - val = strtol(argv[i], &end, 0); - if (*end == '\0') - { - xf86SetLogVerbosity(val); - return 2; - } - } - xf86SetLogVerbosity(++xf86LogVerbose); - return 1; - } - if (!strcmp(argv[i],"-quiet")) - { - xf86SetVerbosity(-1); - return 1; - } - if (!strcmp(argv[i],"-showconfig") || !strcmp(argv[i],"-version")) - { - xf86PrintBanner(); - exit(0); - } - if (!strcmp(argv[i],"-showDefaultModulePath")) - { - xf86PrintDefaultModulePath(); - exit(0); - } - if (!strcmp(argv[i],"-showDefaultLibPath")) - { - xf86PrintDefaultLibraryPath(); - exit(0); - } - /* Notice the -fp flag, but allow it to pass to the dix layer */ - if (!strcmp(argv[i], "-fp")) - { - xf86fpFlag = TRUE; - return 0; - } - /* Notice the -bs flag, but allow it to pass to the dix layer */ - if (!strcmp(argv[i], "-bs")) - { - xf86bsDisableFlag = TRUE; - return 0; - } - /* Notice the +bs flag, but allow it to pass to the dix layer */ - if (!strcmp(argv[i], "+bs")) - { - xf86bsEnableFlag = TRUE; - return 0; - } - /* Notice the -s flag, but allow it to pass to the dix layer */ - if (!strcmp(argv[i], "-s")) - { - xf86sFlag = TRUE; - return 0; - } - if (!strcmp(argv[i], "-pixmap24")) - { - xf86Pix24 = Pix24Use24; - return 1; - } - if (!strcmp(argv[i], "-pixmap32")) - { - xf86Pix24 = Pix24Use32; - return 1; - } - if (!strcmp(argv[i], "-fbbpp")) - { - int bpp; - CHECK_FOR_REQUIRED_ARGUMENT(); - if (sscanf(argv[++i], "%d", &bpp) == 1) - { - xf86FbBpp = bpp; - return 2; - } - else - { - ErrorF("Invalid fbbpp\n"); - return 0; - } - } - if (!strcmp(argv[i], "-depth")) - { - int depth; - CHECK_FOR_REQUIRED_ARGUMENT(); - if (sscanf(argv[++i], "%d", &depth) == 1) - { - xf86Depth = depth; - return 2; - } - else - { - ErrorF("Invalid depth\n"); - return 0; - } - } - if (!strcmp(argv[i], "-weight")) - { - int red, green, blue; - CHECK_FOR_REQUIRED_ARGUMENT(); - if (sscanf(argv[++i], "%1d%1d%1d", &red, &green, &blue) == 3) - { - xf86Weight.red = red; - xf86Weight.green = green; - xf86Weight.blue = blue; - return 2; - } - else - { - ErrorF("Invalid weighting\n"); - return 0; - } - } - if (!strcmp(argv[i], "-gamma") || !strcmp(argv[i], "-rgamma") || - !strcmp(argv[i], "-ggamma") || !strcmp(argv[i], "-bgamma")) - { - double gamma; - CHECK_FOR_REQUIRED_ARGUMENT(); - if (sscanf(argv[++i], "%lf", &gamma) == 1) { - if (gamma < GAMMA_MIN || gamma > GAMMA_MAX) { - ErrorF("gamma out of range, only %.2f <= gamma_value <= %.1f" - " is valid\n", GAMMA_MIN, GAMMA_MAX); - return 0; - } - if (!strcmp(argv[i-1], "-gamma")) - xf86Gamma.red = xf86Gamma.green = xf86Gamma.blue = gamma; - else if (!strcmp(argv[i-1], "-rgamma")) xf86Gamma.red = gamma; - else if (!strcmp(argv[i-1], "-ggamma")) xf86Gamma.green = gamma; - else if (!strcmp(argv[i-1], "-bgamma")) xf86Gamma.blue = gamma; - return 2; - } - } - if (!strcmp(argv[i], "-layout")) - { - CHECK_FOR_REQUIRED_ARGUMENT(); - xf86LayoutName = argv[++i]; - return 2; - } - if (!strcmp(argv[i], "-screen")) - { - CHECK_FOR_REQUIRED_ARGUMENT(); - xf86ScreenName = argv[++i]; - return 2; - } - if (!strcmp(argv[i], "-pointer")) - { - CHECK_FOR_REQUIRED_ARGUMENT(); - xf86PointerName = argv[++i]; - return 2; - } - if (!strcmp(argv[i], "-keyboard")) - { - CHECK_FOR_REQUIRED_ARGUMENT(); - xf86KeyboardName = argv[++i]; - return 2; - } - if (!strcmp(argv[i], "-nosilk")) - { - xf86silkenMouseDisableFlag = TRUE; - return 1; - } -#ifdef HAVE_ACPI - if (!strcmp(argv[i], "-noacpi")) - { - xf86acpiDisableFlag = TRUE; - return 1; - } -#endif - if (!strcmp(argv[i], "-configure")) - { - if (getuid() != 0 && geteuid() == 0) { - ErrorF("The '-configure' option can only be used by root.\n"); - exit(1); - } - xf86DoConfigure = TRUE; - xf86AllowMouseOpenFail = TRUE; - return 1; - } - if (!strcmp(argv[i], "-showopts")) - { - if (getuid() != 0 && geteuid() == 0) { - ErrorF("The '-showopts' option can only be used by root.\n"); - exit(1); - } - xf86DoShowOptions = TRUE; - return 1; - } - if (!strcmp(argv[i], "-isolateDevice")) - { - int bus, device, func; - CHECK_FOR_REQUIRED_ARGUMENT(); - if (strncmp(argv[++i], "PCI:", 4)) { - FatalError("Bus types other than PCI not yet isolable\n"); - } - if (sscanf(argv[i], "PCI:%d:%d:%d", &bus, &device, &func) == 3) { - xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); - xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); - xf86IsolateDevice.dev = device; - xf86IsolateDevice.func = func; - return 2; - } else { - FatalError("Invalid isolated device specification\n"); - } - } - /* Notice cmdline xkbdir, but pass to dix as well */ - if (!strcmp(argv[i], "-xkbdir")) - { - xf86xkbdirFlag = TRUE; - return 0; - } - - /* OS-specific processing */ - return xf86ProcessArgument(argc, argv, i); -} - -/* - * ddxUseMsg -- - * Print out correct use of device dependent commandline options. - * Maybe the user now knows what really to do ... - */ - -void -ddxUseMsg(void) -{ - ErrorF("\n"); - ErrorF("\n"); - ErrorF("Device Dependent Usage\n"); - if (getuid() == 0 || geteuid() != 0) - { - ErrorF("-modulepath paths specify the module search path\n"); - ErrorF("-logfile file specify a log file name\n"); - ErrorF("-configure probe for devices and write an "__XCONFIGFILE__"\n"); - ErrorF("-showopts print available options for all installed drivers\n"); - } - ErrorF("-config file specify a configuration file, relative to the\n"); - ErrorF(" "__XCONFIGFILE__" search path, only root can use absolute\n"); - ErrorF("-configdir dir specify a configuration directory, relative to the\n"); - ErrorF(" "__XCONFIGDIR__" search path, only root can use absolute\n"); - ErrorF("-verbose [n] verbose startup messages\n"); - ErrorF("-logverbose [n] verbose log messages\n"); - ErrorF("-quiet minimal startup messages\n"); - ErrorF("-pixmap24 use 24bpp pixmaps for depth 24\n"); - ErrorF("-pixmap32 use 32bpp pixmaps for depth 24\n"); - ErrorF("-fbbpp n set bpp for the framebuffer. Default: 8\n"); - ErrorF("-depth n set colour depth. Default: 8\n"); - ErrorF("-gamma f set gamma value (0.1 < f < 10.0) Default: 1.0\n"); - ErrorF("-rgamma f set gamma value for red phase\n"); - ErrorF("-ggamma f set gamma value for green phase\n"); - ErrorF("-bgamma f set gamma value for blue phase\n"); - ErrorF("-weight nnn set RGB weighting at 16 bpp. Default: 565\n"); - ErrorF("-layout name specify the ServerLayout section name\n"); - ErrorF("-screen name specify the Screen section name\n"); - ErrorF("-keyboard name specify the core keyboard InputDevice name\n"); - ErrorF("-pointer name specify the core pointer InputDevice name\n"); - ErrorF("-nosilk disable Silken Mouse\n"); - ErrorF("-flipPixels swap default black/white Pixel values\n"); -#ifdef XF86VIDMODE - ErrorF("-disableVidMode disable mode adjustments with xvidtune\n"); - ErrorF("-allowNonLocalXvidtune allow xvidtune to be run as a non-local client\n"); -#endif - ErrorF("-allowMouseOpenFail start server even if the mouse can't be initialized\n"); - ErrorF("-ignoreABI make module ABI mismatches non-fatal\n"); - ErrorF("-isolateDevice bus_id restrict device resets to bus_id (PCI only)\n"); - ErrorF("-version show the server version\n"); - ErrorF("-showDefaultModulePath show the server default module path\n"); - ErrorF("-showDefaultLibPath show the server default library path\n"); - /* OS-specific usage */ - xf86UseMsg(); - ErrorF("\n"); -} - - -/* - * xf86LoadModules iterates over a list that is being passed in. - */ -Bool -xf86LoadModules(char **list, pointer *optlist) -{ - int errmaj, errmin; - pointer opt; - int i; - char *name; - Bool failed = FALSE; - - if (!list) - return TRUE; - - for (i = 0; list[i] != NULL; i++) { - - /* Normalise the module name */ - name = xf86NormalizeName(list[i]); - - /* Skip empty names */ - if (name == NULL || *name == '\0') - continue; - - /* Replace obsolete keyboard driver with kbd */ - if (!xf86NameCmp(name, "keyboard")) { - strcpy(name, "kbd"); - } - - if (optlist) - opt = optlist[i]; - else - opt = NULL; - - if (!LoadModule(name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin)) { - LoaderErrorMsg(NULL, name, errmaj, errmin); - failed = TRUE; - } - xfree(name); - } - return !failed; -} - -/* Pixmap format stuff */ - -PixmapFormatPtr -xf86GetPixFormat(ScrnInfoPtr pScrn, int depth) -{ - int i; - static PixmapFormatRec format; /* XXX not reentrant */ - - /* - * When the formats[] list initialisation isn't complete, check the - * depth 24 pixmap config/cmdline options and screen-specified formats. - */ - - if (!formatsDone) { - if (depth == 24) { - Pix24Flags pix24 = Pix24DontCare; - - format.depth = 24; - format.scanlinePad = BITMAP_SCANLINE_PAD; - if (xf86Info.pixmap24 != Pix24DontCare) - pix24 = xf86Info.pixmap24; - else if (pScrn->pixmap24 != Pix24DontCare) - pix24 = pScrn->pixmap24; - if (pix24 == Pix24Use24) - format.bitsPerPixel = 24; - else - format.bitsPerPixel = 32; - return &format; - } - } - - for (i = 0; i < numFormats; i++) - if (formats[i].depth == depth) - break; - if (i != numFormats) - return &formats[i]; - else if (!formatsDone) { - /* Check for screen-specified formats */ - for (i = 0; i < pScrn->numFormats; i++) - if (pScrn->formats[i].depth == depth) - break; - if (i != pScrn->numFormats) - return &pScrn->formats[i]; - } - return NULL; -} - -int -xf86GetBppFromDepth(ScrnInfoPtr pScrn, int depth) -{ - PixmapFormatPtr format; - - - format = xf86GetPixFormat(pScrn, depth); - if (format) - return format->bitsPerPixel; - else - return 0; -} +/* + * Loosely based on code bearing the following copyright: + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + */ +/* + * Copyright (c) 1992-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +#undef HAS_UTSNAME +#if !defined(WIN32) +#define HAS_UTSNAME 1 +#include +#endif + +#include +#include +#include +#include +#include "input.h" +#include "servermd.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "site.h" +#include "mi.h" + +#include "compiler.h" + +#include "loaderProcs.h" +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#define XF86_OS_PRIVS +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Config.h" +#include "xf86_OSlib.h" +#include "xorgVersion.h" +#include "xf86Build.h" +#include "mipointer.h" +#include +#include +#include "xf86DDC.h" +#include "xf86Xinput.h" +#include "xf86InPriv.h" +#include "picturestr.h" + +#include "xf86VGAarbiter.h" +#include "globals.h" + +#ifdef DPMSExtension +#include +#include "dpmsproc.h" +#endif + +#include +#include "Pci.h" +#include "xf86Bus.h" + +#include + +/* forward declarations */ +static Bool probe_devices_from_device_sections(DriverPtr drvp); +static Bool add_matching_devices_to_configure_list(DriverPtr drvp); + +#ifdef XF86PM +void (*xf86OSPMClose)(void) = NULL; +#endif +static Bool xorgHWOpenConsole = FALSE; + +/* Common pixmap formats */ + +static PixmapFormatRec formats[MAXFORMATS] = { + { 1, 1, BITMAP_SCANLINE_PAD }, + { 4, 8, BITMAP_SCANLINE_PAD }, + { 8, 8, BITMAP_SCANLINE_PAD }, + { 15, 16, BITMAP_SCANLINE_PAD }, + { 16, 16, BITMAP_SCANLINE_PAD }, + { 24, 32, BITMAP_SCANLINE_PAD }, + { 32, 32, BITMAP_SCANLINE_PAD }, +}; +static int numFormats = 7; +static Bool formatsDone = FALSE; + +#ifndef OSNAME +#define OSNAME " unknown" +#endif +#ifndef OSVENDOR +#define OSVENDOR "" +#endif +#ifndef PRE_RELEASE +#define PRE_RELEASE XORG_VERSION_SNAP +#endif + +static void +xf86PrintBanner(void) +{ +#if PRE_RELEASE + xf86ErrorFVerb(0, "\n" + "This is a pre-release version of the X server from " XVENDORNAME ".\n" + "It is not supported in any way.\n" + "Bugs may be filed in the bugzilla at http://bugs.freedesktop.org/.\n" + "Select the \"xorg\" product for bugs you find in this release.\n" + "Before reporting bugs in pre-release versions please check the\n" + "latest version in the X.Org Foundation git repository.\n" + "See http://wiki.x.org/wiki/GitPage for git access instructions.\n"); +#endif + xf86ErrorFVerb(0, "\nX.Org X Server %d.%d.%d", + XORG_VERSION_MAJOR, + XORG_VERSION_MINOR, + XORG_VERSION_PATCH); +#if XORG_VERSION_SNAP > 0 + xf86ErrorFVerb(0, ".%d", XORG_VERSION_SNAP); +#endif + +#if XORG_VERSION_SNAP >= 900 + /* When the minor number is 99, that signifies that the we are making + * a release candidate for a major version. (X.0.0) + * When the patch number is 99, that signifies that the we are making + * a release candidate for a minor version. (X.Y.0) + * When the patch number is < 99, then we are making a release + * candidate for the next point release. (X.Y.Z) + */ +#if XORG_VERSION_MINOR >= 99 + xf86ErrorFVerb(0, " (%d.0.0 RC %d)", XORG_VERSION_MAJOR+1, + XORG_VERSION_SNAP - 900); +#elif XORG_VERSION_PATCH == 99 + xf86ErrorFVerb(0, " (%d.%d.0 RC %d)", XORG_VERSION_MAJOR, + XORG_VERSION_MINOR + 1, XORG_VERSION_SNAP - 900); +#else + xf86ErrorFVerb(0, " (%d.%d.%d RC %d)", XORG_VERSION_MAJOR, + XORG_VERSION_MINOR, XORG_VERSION_PATCH + 1, + XORG_VERSION_SNAP - 900); +#endif +#endif + +#ifdef XORG_CUSTOM_VERSION + xf86ErrorFVerb(0, " (%s)", XORG_CUSTOM_VERSION); +#endif +#ifndef XORG_DATE +# define XORG_DATE "Unknown" +#endif + xf86ErrorFVerb(0, "\nRelease Date: %s\n", XORG_DATE); + xf86ErrorFVerb(0, "X Protocol Version %d, Revision %d\n", + X_PROTOCOL, X_PROTOCOL_REVISION); + xf86ErrorFVerb(0, "Build Operating System: %s %s\n", OSNAME, OSVENDOR); +#ifdef HAS_UTSNAME + { + struct utsname name; + + /* Linux & BSD state that 0 is success, SysV (including Solaris, HP-UX, + and Irix) and Single Unix Spec 3 just say that non-negative is success. + All agree that failure is represented by a negative number. + */ + if (uname(&name) >= 0) { + xf86ErrorFVerb(0, "Current Operating System: %s %s %s %s %s\n", + name.sysname, name.nodename, name.release, name.version, name.machine); +#ifdef linux + do { + char buf[80]; + int fd = open("/proc/cmdline", O_RDONLY); + if (fd != -1) { + xf86ErrorFVerb(0, "Kernel command line: "); + memset(buf, 0, 80); + while (read(fd, buf, 80) > 0) { + xf86ErrorFVerb(0, "%.80s", buf); + memset(buf, 0, 80); + } + close(fd); + } + } while (0); +#endif + } + } +#endif +#if defined(BUILD_DATE) && (BUILD_DATE > 19000000) + { + struct tm t; + char buf[100]; + + bzero(&t, sizeof(t)); + bzero(buf, sizeof(buf)); + t.tm_mday = BUILD_DATE % 100; + t.tm_mon = (BUILD_DATE / 100) % 100 - 1; + t.tm_year = BUILD_DATE / 10000 - 1900; +#if defined(BUILD_TIME) + t.tm_sec = BUILD_TIME % 100; + t.tm_min = (BUILD_TIME / 100) % 100; + t.tm_hour = (BUILD_TIME / 10000) % 100; + if (strftime(buf, sizeof(buf), "%d %B %Y %I:%M:%S%p", &t)) + xf86ErrorFVerb(0, "Build Date: %s\n", buf); +#else + if (strftime(buf, sizeof(buf), "%d %B %Y", &t)) + xf86ErrorFVerb(0, "Build Date: %s\n", buf); +#endif + } +#endif +#if defined(BUILDERSTRING) + xf86ErrorFVerb(0, "%s \n", BUILDERSTRING); +#endif + xf86ErrorFVerb(0, "Current version of pixman: %s\n", + pixman_version_string()); + xf86ErrorFVerb(0, "\tBefore reporting problems, check " + ""__VENDORDWEBSUPPORT__"\n" + "\tto make sure that you have the latest version.\n"); +} + +static void +xf86PrintMarkers(void) +{ + LogPrintMarkers(); +} + +static Bool +xf86CreateRootWindow(WindowPtr pWin) +{ + int ret = TRUE; + int err = Success; + ScreenPtr pScreen = pWin->drawable.pScreen; + RootWinPropPtr pProp; + CreateWindowProcPtr CreateWindow = (CreateWindowProcPtr) + dixLookupPrivate(&pScreen->devPrivates, xf86CreateRootWindowKey); + + DebugF("xf86CreateRootWindow(%p)\n", pWin); + + if ( pScreen->CreateWindow != xf86CreateRootWindow ) { + /* Can't find hook we are hung on */ + xf86DrvMsg(pScreen->myNum, X_WARNING /* X_ERROR */, + "xf86CreateRootWindow %p called when not in pScreen->CreateWindow %p n", + (void *)xf86CreateRootWindow, + (void *)pScreen->CreateWindow ); + } + + /* Unhook this function ... */ + pScreen->CreateWindow = CreateWindow; + dixSetPrivate(&pScreen->devPrivates, xf86CreateRootWindowKey, NULL); + + /* ... and call the previous CreateWindow fuction, if any */ + if (NULL!=pScreen->CreateWindow) { + ret = (*pScreen->CreateWindow)(pWin); + } + + /* Now do our stuff */ + if (xf86RegisteredPropertiesTable != NULL) { + if (pWin->parent == NULL && xf86RegisteredPropertiesTable != NULL) { + for (pProp = xf86RegisteredPropertiesTable[pScreen->myNum]; + pProp != NULL && err==Success; + pProp = pProp->next ) + { + Atom prop; + + prop = MakeAtom(pProp->name, strlen(pProp->name), TRUE); + err = dixChangeWindowProperty(serverClient, pWin, + prop, pProp->type, + pProp->format, PropModeReplace, + pProp->size, pProp->data, + FALSE); + } + + /* Look at err */ + ret &= (err==Success); + + } else { + xf86Msg(X_ERROR, "xf86CreateRootWindow unexpectedly called with " + "non-root window %p (parent %p)\n", + (void *)pWin, (void *)pWin->parent); + ret = FALSE; + } + } + + DebugF("xf86CreateRootWindow() returns %d\n", ret); + return (ret); +} + + +static void +InstallSignalHandlers(void) +{ + /* + * Install signal handler for unexpected signals + */ + xf86Info.caughtSignal=FALSE; + if (!xf86Info.notrapSignals) { + OsRegisterSigWrapper(xf86SigWrapper); + } else { + signal(SIGSEGV, SIG_DFL); + signal(SIGILL, SIG_DFL); +#ifdef SIGEMT + signal(SIGEMT, SIG_DFL); +#endif + signal(SIGFPE, SIG_DFL); +#ifdef SIGBUS + signal(SIGBUS, SIG_DFL); +#endif +#ifdef SIGSYS + signal(SIGSYS, SIG_DFL); +#endif +#ifdef SIGXCPU + signal(SIGXCPU, SIG_DFL); +#endif +#ifdef SIGXFSZ + signal(SIGXFSZ, SIG_DFL); +#endif + } +} + + +#define END_OF_MATCHES(m) \ + (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) + +Bool +probe_devices_from_device_sections(DriverPtr drvp) +{ + int i, j; + struct pci_device * pPci; + Bool foundScreen = FALSE; + const struct pci_id_match * const devices = drvp->supported_devices; + GDevPtr *devList; + const unsigned numDevs = xf86MatchDevice(drvp->driverName, & devList); + + + for ( i = 0 ; i < numDevs ; i++ ) { + struct pci_device_iterator *iter; + unsigned device_id; + + + /* Find the pciVideoRec associated with this device section. + */ + iter = pci_id_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + if (devList[i]->busID && *devList[i]->busID) { + if (xf86ComparePciBusString(devList[i]->busID, + ((pPci->domain << 8) + | pPci->bus), + pPci->dev, + pPci->func)) { + break; + } + } + else if (xf86IsPrimaryPci(pPci)) { + break; + } + } + + pci_iterator_destroy(iter); + + if (pPci == NULL) { + continue; + } + + device_id = (devList[i]->chipID > 0) + ? devList[i]->chipID : pPci->device_id; + + + /* Once the pciVideoRec is found, determine if the device is supported + * by the driver. If it is, probe it! + */ + for ( j = 0 ; ! END_OF_MATCHES( devices[j] ) ; j++ ) { + if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) + && PCI_ID_COMPARE( devices[j].device_id, device_id ) + && ((devices[j].device_class_mask & pPci->device_class) + == devices[j].device_class) ) { + int entry; + + /* Allow the same entity to be used more than once for + * devices with multiple screens per entity. This assumes + * implicitly that there will be a screen == 0 instance. + * + * FIXME Need to make sure that two different drivers don't + * FIXME claim the same screen > 0 instance. + */ + if ( (devList[i]->screen == 0) && !xf86CheckPciSlot( pPci ) ) + continue; + + DebugF("%s: card at %d:%d:%d is claimed by a Device section\n", + drvp->driverName, pPci->bus, pPci->dev, pPci->func); + + /* Allocate an entry in the lists to be returned */ + entry = xf86ClaimPciSlot(pPci, drvp, device_id, + devList[i], devList[i]->active); + + if ((entry == -1) && (devList[i]->screen > 0)) { + unsigned k; + + for ( k = 0; k < xf86NumEntities; k++ ) { + EntityPtr pEnt = xf86Entities[k]; + if (pEnt->bus.type != BUS_PCI) + continue; + + if (pEnt->bus.id.pci == pPci) { + entry = k; + xf86AddDevToEntity(k, devList[i]); + break; + } + } + } + + if (entry != -1) { + if ((*drvp->PciProbe)(drvp, entry, pPci, + devices[j].match_data)) { + foundScreen = TRUE; + } else + xf86UnclaimPciSlot(pPci); + } + + break; + } + } + } + free(devList); + + return foundScreen; +} + + +Bool +add_matching_devices_to_configure_list(DriverPtr drvp) +{ + const struct pci_id_match * const devices = drvp->supported_devices; + int j; + struct pci_device *pPci; + struct pci_device_iterator *iter; + int numFound = 0; + + + iter = pci_id_match_iterator_create(NULL); + while ((pPci = pci_device_next(iter)) != NULL) { + /* Determine if this device is supported by the driver. If it is, + * add it to the list of devices to configure. + */ + for (j = 0 ; ! END_OF_MATCHES(devices[j]) ; j++) { + if ( PCI_ID_COMPARE( devices[j].vendor_id, pPci->vendor_id ) + && PCI_ID_COMPARE( devices[j].device_id, pPci->device_id ) + && ((devices[j].device_class_mask & pPci->device_class) + == devices[j].device_class) ) { + if (xf86CheckPciSlot(pPci)) { + GDevPtr pGDev = xf86AddBusDeviceToConfigure( + drvp->driverName, BUS_PCI, pPci, -1); + if (pGDev != NULL) { + /* After configure pass 1, chipID and chipRev are + * treated as over-rides, so clobber them here. + */ + pGDev->chipID = -1; + pGDev->chipRev = -1; + } + + numFound++; + } + + break; + } + } + } + + pci_iterator_destroy(iter); + + + return (numFound != 0); +} + +/** + * Call the driver's correct probe function. + * + * If the driver implements the \c DriverRec::PciProbe entry-point and an + * appropriate PCI device (with matching Device section in the xorg.conf file) + * is found, it is called. If \c DriverRec::PciProbe or no devices can be + * successfully probed with it (e.g., only non-PCI devices are available), + * the driver's \c DriverRec::Probe function is called. + * + * \param drv Driver to probe + * + * \return + * If a device can be successfully probed by the driver, \c TRUE is + * returned. Otherwise, \c FALSE is returned. + */ +Bool +xf86CallDriverProbe( DriverPtr drv, Bool detect_only ) +{ + Bool foundScreen = FALSE; + + if ( drv->PciProbe != NULL ) { + if ( xf86DoConfigure && xf86DoConfigurePass1 ) { + assert( detect_only ); + foundScreen = add_matching_devices_to_configure_list( drv ); + } + else { + assert( ! detect_only ); + foundScreen = probe_devices_from_device_sections( drv ); + } + } + + if ( ! foundScreen && (drv->Probe != NULL) ) { + xf86Msg( X_WARNING, "Falling back to old probe method for %s\n", + drv->driverName ); + foundScreen = (*drv->Probe)( drv, (detect_only) ? PROBE_DETECT + : PROBE_DEFAULT ); + } + + return foundScreen; +} + +/* + * InitOutput -- + * Initialize screenInfo for all actually accessible framebuffers. + * That includes vt-manager setup, querying all possible devices and + * collecting the pixmap formats. + */ +void +InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) +{ + int i, j, k, scr_index; + char **modulelist; + pointer *optionlist; + screenLayoutPtr layout; + Pix24Flags screenpix24, pix24; + MessageType pix24From = X_DEFAULT; + Bool pix24Fail = FALSE; + Bool autoconfig = FALSE; + GDevPtr configured_device; + + xf86Initialising = TRUE; + + if (serverGeneration == 1) { + if ((xf86ServerName = strrchr(argv[0], '/')) != 0) + xf86ServerName++; + else + xf86ServerName = argv[0]; + + xf86PrintBanner(); + xf86PrintMarkers(); + if (xf86LogFile) { + time_t t; + const char *ct; + t = time(NULL); + ct = ctime(&t); + xf86MsgVerb(xf86LogFileFrom, 0, "Log file: \"%s\", Time: %s", + xf86LogFile, ct); + } + + /* Read and parse the config file */ + if (!xf86DoConfigure && !xf86DoShowOptions) { + switch (xf86HandleConfigFile(FALSE)) { + case CONFIG_OK: + break; + case CONFIG_PARSE_ERROR: + xf86Msg(X_ERROR, "Error parsing the config file\n"); + return; + case CONFIG_NOFILE: + autoconfig = TRUE; + break; + } + } + + InstallSignalHandlers(); + + /* Initialise the loader */ + LoaderInit(); + + /* Tell the loader the default module search path */ + LoaderSetPath(xf86ModulePath); + + if (xf86Info.ignoreABI) { + LoaderSetOptions(LDR_OPT_ABI_MISMATCH_NONFATAL); + } + + if (xf86DoShowOptions) + DoShowOptions(); + + /* Do a general bus probe. This will be a PCI probe for x86 platforms */ + xf86BusProbe(); + + if (xf86DoConfigure) + DoConfigure(); + + if (autoconfig) { + if (!xf86AutoConfig()) { + xf86Msg(X_ERROR, "Auto configuration failed\n"); + return; + } + } + +#ifdef XF86PM + xf86OSPMClose = xf86OSPMOpen(); +#endif + + /* Load all modules specified explicitly in the config file */ + if ((modulelist = xf86ModulelistFromConfig(&optionlist))) { + xf86LoadModules(modulelist, optionlist); + free(modulelist); + free(optionlist); + } + + /* Load all driver modules specified in the config file */ + /* If there aren't any specified in the config file, autoconfig them */ + /* FIXME: Does not handle multiple active screen sections, but I'm not + * sure if we really want to handle that case*/ + configured_device = xf86ConfigLayout.screens->screen->device; + if ((!configured_device) || (!configured_device->driver)) { + if (!autoConfigDevice(configured_device)) { + xf86Msg(X_ERROR, "Automatic driver configuration failed\n"); + return ; + } + } + if ((modulelist = xf86DriverlistFromConfig())) { + xf86LoadModules(modulelist, NULL); + free(modulelist); + } + + /* Load all input driver modules specified in the config file. */ + if ((modulelist = xf86InputDriverlistFromConfig())) { + xf86LoadModules(modulelist, NULL); + free(modulelist); + } + + /* + * It is expected that xf86AddDriver()/xf86AddInputDriver will be + * called for each driver as it is loaded. Those functions save the + * module pointers for drivers. + * XXX Nothing keeps track of them for other modules. + */ + /* XXX What do we do if not all of these could be loaded? */ + + /* + * At this point, xf86DriverList[] is all filled in with entries for + * each of the drivers to try and xf86NumDrivers has the number of + * drivers. If there are none, return now. + */ + + if (xf86NumDrivers == 0) { + xf86Msg(X_ERROR, "No drivers available.\n"); + return; + } + + /* + * Call each of the Identify functions and call the driverFunc to check + * if HW access is required. The Identify functions print out some + * identifying information, and anything else that might be + * needed at this early stage. + */ + + for (i = 0; i < xf86NumDrivers; i++) { + if (xf86DriverList[i]->Identify != NULL) + xf86DriverList[i]->Identify(0); + + if (!xorgHWAccess || !xorgHWOpenConsole) { + xorgHWFlags flags; + if(!xf86DriverList[i]->driverFunc + || !xf86DriverList[i]->driverFunc(NULL, + GET_REQUIRED_HW_INTERFACES, + &flags)) + flags = HW_IO; + + if(NEED_IO_ENABLED(flags)) + xorgHWAccess = TRUE; + if(!(flags & HW_SKIP_CONSOLE)) + xorgHWOpenConsole = TRUE; + } + } + + if (xorgHWOpenConsole) + xf86OpenConsole(); + else + xf86Info.dontVTSwitch = TRUE; + + /* Enable full I/O access */ + if (xorgHWAccess) + xorgHWAccess = xf86EnableIO(); + + /* + * Locate bus slot that had register IO enabled at server startup + */ + if (xorgHWAccess) { + xf86AccessInit(); + xf86FindPrimaryDevice(); + } + /* + * Now call each of the Probe functions. Each successful probe will + * result in an extra entry added to the xf86Screens[] list for each + * instance of the hardware found. + */ + + for (i = 0; i < xf86NumDrivers; i++) { + xorgHWFlags flags; + if (!xorgHWAccess) { + if (!xf86DriverList[i]->driverFunc + || !xf86DriverList[i]->driverFunc(NULL, + GET_REQUIRED_HW_INTERFACES, + &flags) + || NEED_IO_ENABLED(flags)) + continue; + } + + xf86CallDriverProbe( xf86DriverList[i], FALSE ); + } + + /* + * If nothing was detected, return now. + */ + + if (xf86NumScreens == 0) { + xf86Msg(X_ERROR, "No devices detected.\n"); + return; + } + + xf86VGAarbiterInit(); + + /* + * Match up the screens found by the probes against those specified + * in the config file. Remove the ones that won't be used. Sort + * them in the order specified. + */ + + /* + * What is the best way to do this? + * + * For now, go through the screens allocated by the probes, and + * look for screen config entry which refers to the same device + * section as picked out by the probe. + * + */ + + for (i = 0; i < xf86NumScreens; i++) { + for (layout = xf86ConfigLayout.screens; layout->screen != NULL; + layout++) { + Bool found = FALSE; + for (j = 0; j < xf86Screens[i]->numEntities; j++) { + + GDevPtr dev = + xf86GetDevFromEntity(xf86Screens[i]->entityList[j], + xf86Screens[i]->entityInstanceList[j]); + + if (dev == layout->screen->device) { + /* A match has been found */ + xf86Screens[i]->confScreen = layout->screen; + found = TRUE; + break; + } + } + if (found) break; + } + if (layout->screen == NULL) { + /* No match found */ + xf86Msg(X_ERROR, + "Screen %d deleted because of no matching config section.\n", i); + xf86DeleteScreen(i--, 0); + } + } + + /* + * If no screens left, return now. + */ + + if (xf86NumScreens == 0) { + xf86Msg(X_ERROR, + "Device(s) detected, but none match those in the config file.\n"); + return; + } + + xf86PostProbe(); + xf86EntityInit(); + + /* + * Sort the drivers to match the requested ording. Using a slow + * bubble sort. + */ + for (j = 0; j < xf86NumScreens - 1; j++) { + for (i = 0; i < xf86NumScreens - j - 1; i++) { + if (xf86Screens[i + 1]->confScreen->screennum < + xf86Screens[i]->confScreen->screennum) { + ScrnInfoPtr tmpScrn = xf86Screens[i + 1]; + xf86Screens[i + 1] = xf86Screens[i]; + xf86Screens[i] = tmpScrn; + } + } + } + /* Fix up the indexes */ + for (i = 0; i < xf86NumScreens; i++) { + xf86Screens[i]->scrnIndex = i; + } + + /* + * Call the driver's PreInit()'s to complete initialisation for the first + * generation. + */ + + for (i = 0; i < xf86NumScreens; i++) { + xf86VGAarbiterScrnInit(xf86Screens[i]); + xf86VGAarbiterLock(xf86Screens[i]); + if (xf86Screens[i]->PreInit && + xf86Screens[i]->PreInit(xf86Screens[i], 0)) + xf86Screens[i]->configured = TRUE; + xf86VGAarbiterUnlock(xf86Screens[i]); + } + for (i = 0; i < xf86NumScreens; i++) + if (!xf86Screens[i]->configured) + xf86DeleteScreen(i--, 0); + + /* + * If no screens left, return now. + */ + + if (xf86NumScreens == 0) { + xf86Msg(X_ERROR, + "Screen(s) found, but none have a usable configuration.\n"); + return; + } + + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->name == NULL) { + xf86Screens[i]->name = xnfalloc(strlen("screen") + 10 + 1); + sprintf(xf86Screens[i]->name, "screen%d", i); + xf86MsgVerb(X_WARNING, 0, + "Screen driver %d has no name set, using `%s'.\n", + i, xf86Screens[i]->name); + } + } + + /* Remove (unload) drivers that are not required */ + for (i = 0; i < xf86NumDrivers; i++) + if (xf86DriverList[i] && xf86DriverList[i]->refCount <= 0) + xf86DeleteDriver(i); + + /* + * At this stage we know how many screens there are. + */ + + for (i = 0; i < xf86NumScreens; i++) + xf86InitViewport(xf86Screens[i]); + + /* + * Collect all pixmap formats and check for conflicts at the display + * level. Should we die here? Or just delete the offending screens? + */ + screenpix24 = Pix24DontCare; + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->imageByteOrder != + xf86Screens[0]->imageByteOrder) + FatalError("Inconsistent display bitmapBitOrder. Exiting\n"); + if (xf86Screens[i]->bitmapScanlinePad != + xf86Screens[0]->bitmapScanlinePad) + FatalError("Inconsistent display bitmapScanlinePad. Exiting\n"); + if (xf86Screens[i]->bitmapScanlineUnit != + xf86Screens[0]->bitmapScanlineUnit) + FatalError("Inconsistent display bitmapScanlineUnit. Exiting\n"); + if (xf86Screens[i]->bitmapBitOrder != + xf86Screens[0]->bitmapBitOrder) + FatalError("Inconsistent display bitmapBitOrder. Exiting\n"); + + /* Determine the depth 24 pixmap format the screens would like */ + if (xf86Screens[i]->pixmap24 != Pix24DontCare) { + if (screenpix24 == Pix24DontCare) + screenpix24 = xf86Screens[i]->pixmap24; + else if (screenpix24 != xf86Screens[i]->pixmap24) + FatalError("Inconsistent depth 24 pixmap format. Exiting\n"); + } + } + /* check if screenpix24 is consistent with the config/cmdline */ + if (xf86Info.pixmap24 != Pix24DontCare) { + pix24 = xf86Info.pixmap24; + pix24From = xf86Info.pix24From; + if (screenpix24 != Pix24DontCare && screenpix24 != xf86Info.pixmap24) + pix24Fail = TRUE; + } else if (screenpix24 != Pix24DontCare) { + pix24 = screenpix24; + pix24From = X_PROBED; + } else + pix24 = Pix24Use32; + + if (pix24Fail) + FatalError("Screen(s) can't use the required depth 24 pixmap format" + " (%d). Exiting\n", PIX24TOBPP(pix24)); + + /* Initialise the depth 24 format */ + for (j = 0; j < numFormats && formats[j].depth != 24; j++) + ; + formats[j].bitsPerPixel = PIX24TOBPP(pix24); + + /* Collect additional formats */ + for (i = 0; i < xf86NumScreens; i++) { + for (j = 0; j < xf86Screens[i]->numFormats; j++) { + for (k = 0; ; k++) { + if (k >= numFormats) { + if (k >= MAXFORMATS) + FatalError("Too many pixmap formats! Exiting\n"); + formats[k] = xf86Screens[i]->formats[j]; + numFormats++; + break; + } + if (formats[k].depth == xf86Screens[i]->formats[j].depth) { + if ((formats[k].bitsPerPixel == + xf86Screens[i]->formats[j].bitsPerPixel) && + (formats[k].scanlinePad == + xf86Screens[i]->formats[j].scanlinePad)) + break; + FatalError("Inconsistent pixmap format for depth %d." + " Exiting\n", formats[k].depth); + } + } + } + } + formatsDone = TRUE; + + if (xf86Info.vtno >= 0 ) { +#define VT_ATOM_NAME "XFree86_VT" + Atom VTAtom=-1; + CARD32 *VT = NULL; + int ret; + + /* This memory needs to stay available until the screen has been + initialized, and we can create the property for real. + */ + if ( (VT = malloc(sizeof(CARD32)))==NULL ) { + FatalError("Unable to make VT property - out of memory. Exiting...\n"); + } + *VT = xf86Info.vtno; + + VTAtom = MakeAtom(VT_ATOM_NAME, sizeof(VT_ATOM_NAME) - 1, TRUE); + + for (i = 0, ret = Success; i < xf86NumScreens && ret == Success; i++) { + ret = xf86RegisterRootWindowProperty(xf86Screens[i]->scrnIndex, + VTAtom, XA_INTEGER, 32, + 1, VT ); + if (ret != Success) + xf86DrvMsg(xf86Screens[i]->scrnIndex, X_WARNING, + "Failed to register VT property\n"); + } + } + + /* If a screen uses depth 24, show what the pixmap format is */ + for (i = 0; i < xf86NumScreens; i++) { + if (xf86Screens[i]->depth == 24) { + xf86Msg(pix24From, "Depth 24 pixmap format is %d bpp\n", + PIX24TOBPP(pix24)); + break; + } + } + } else { + /* + * serverGeneration != 1; some OSs have to do things here, too. + */ + if (xorgHWOpenConsole) + xf86OpenConsole(); + +#ifdef XF86PM + /* + should we reopen it here? We need to deal with an already opened + device. We could leave this to the OS layer. For now we simply + close it here + */ + if (xf86OSPMClose) + xf86OSPMClose(); + if ((xf86OSPMClose = xf86OSPMOpen()) != NULL) + xf86MsgVerb(X_INFO, 3, "APM registered successfully\n"); +#endif + + /* Make sure full I/O access is enabled */ + if (xorgHWAccess) + xf86EnableIO(); + } + + /* + * Use the previously collected parts to setup pScreenInfo + */ + + pScreenInfo->imageByteOrder = xf86Screens[0]->imageByteOrder; + pScreenInfo->bitmapScanlinePad = xf86Screens[0]->bitmapScanlinePad; + pScreenInfo->bitmapScanlineUnit = xf86Screens[0]->bitmapScanlineUnit; + pScreenInfo->bitmapBitOrder = xf86Screens[0]->bitmapBitOrder; + pScreenInfo->numPixmapFormats = numFormats; + for (i = 0; i < numFormats; i++) + pScreenInfo->formats[i] = formats[i]; + + /* Make sure the server's VT is active */ + + if (serverGeneration != 1) { + xf86Resetting = TRUE; + /* All screens are in the same state, so just check the first */ + if (!xf86Screens[0]->vtSema) { +#ifdef HAS_USL_VTS + ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ); +#endif + xf86AccessEnter(); + xf86EnterServerState(SETUP); + } + } +#ifdef SCO325 + else { + /* + * Under SCO we must ack that we got the console at startup, + * I think this is the safest way to assure it. + */ + static int once = 1; + if (once) { + once = 0; + if (ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ) < 0) + xf86Msg(X_WARNING, "VT_ACKACQ failed"); + } + } +#endif /* SCO325 */ + + for (i = 0; i < xf86NumScreens; i++) { + xf86VGAarbiterLock(xf86Screens[i]); + /* + * Almost everything uses these defaults, and many of those that + * don't, will wrap them. + */ + xf86Screens[i]->EnableDisableFBAccess = xf86EnableDisableFBAccess; +#ifdef XFreeXDGA + xf86Screens[i]->SetDGAMode = xf86SetDGAMode; +#endif + xf86Screens[i]->DPMSSet = NULL; + xf86Screens[i]->LoadPalette = NULL; + xf86Screens[i]->SetOverscan = NULL; + xf86Screens[i]->DriverFunc = NULL; + xf86Screens[i]->pScreen = NULL; + scr_index = AddScreen(xf86Screens[i]->ScreenInit, argc, argv); + xf86VGAarbiterUnlock(xf86Screens[i]); + if (scr_index == i) { + /* + * Hook in our ScrnInfoRec, and initialise some other pScreen + * fields. + */ + dixSetPrivate(&screenInfo.screens[scr_index]->devPrivates, + xf86ScreenKey, xf86Screens[i]); + xf86Screens[i]->pScreen = screenInfo.screens[scr_index]; + /* The driver should set this, but make sure it is set anyway */ + xf86Screens[i]->vtSema = TRUE; + } else { + /* This shouldn't normally happen */ + FatalError("AddScreen/ScreenInit failed for driver %d\n", i); + } + + DebugF("InitOutput - xf86Screens[%d]->pScreen = %p\n", + i, xf86Screens[i]->pScreen ); + DebugF("xf86Screens[%d]->pScreen->CreateWindow = %p\n", + i, xf86Screens[i]->pScreen->CreateWindow ); + + dixSetPrivate(&screenInfo.screens[scr_index]->devPrivates, + xf86CreateRootWindowKey, + xf86Screens[i]->pScreen->CreateWindow); + xf86Screens[i]->pScreen->CreateWindow = xf86CreateRootWindow; + + if (PictureGetSubpixelOrder (xf86Screens[i]->pScreen) == SubPixelUnknown) + { + xf86MonPtr DDC = (xf86MonPtr)(xf86Screens[i]->monitor->DDC); + PictureSetSubpixelOrder (xf86Screens[i]->pScreen, + DDC ? + (DDC->features.input_type ? + SubPixelHorizontalRGB : SubPixelNone) : + SubPixelUnknown); + } +#ifdef RANDR + if (!xf86Info.disableRandR) + xf86RandRInit (screenInfo.screens[scr_index]); + xf86Msg(xf86Info.randRFrom, "RandR %s\n", + xf86Info.disableRandR ? "disabled" : "enabled"); +#endif + } + + xf86PostScreenInit(); + + xf86InitOrigins(); + + xf86Resetting = FALSE; + xf86Initialising = FALSE; + + RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, xf86Wakeup, + NULL); +} + +/* + * InitInput -- + * Initialize all supported input devices. + */ + +void +InitInput(int argc, char **argv) +{ + IDevPtr* pDev; + DeviceIntPtr dev; + + xf86Info.vtRequestsPending = FALSE; + + mieqInit(); + + GetEventList(&xf86Events); + + /* Call the PreInit function for each input device instance. */ + for (pDev = xf86ConfigLayout.inputs; pDev && *pDev; pDev++) { + /* Replace obsolete keyboard driver with kbd */ + if (!xf86NameCmp((*pDev)->driver, "keyboard")) { + strcpy((*pDev)->driver, "kbd"); + } + + /* If one fails, the others will too */ + if (xf86NewInputDevice(*pDev, &dev, TRUE) == BadAlloc) + break; + } + + config_init(); +} + +void +CloseInput (void) +{ + config_fini(); +} + +/* + * OsVendorInit -- + * OS/Vendor-specific initialisations. Called from OsInit(), which + * is called by dix before establishing the well known sockets. + */ + +void +OsVendorInit(void) +{ + static Bool beenHere = FALSE; + +#ifdef SIGCHLD + signal(SIGCHLD, SIG_DFL); /* Need to wait for child processes */ +#endif + + if (!beenHere) { + umask(022); + xf86LogInit(); + } + + /* Set stderr to non-blocking. */ +#ifndef O_NONBLOCK +#if defined(FNDELAY) +#define O_NONBLOCK FNDELAY +#elif defined(O_NDELAY) +#define O_NONBLOCK O_NDELAY +#endif + +#ifdef O_NONBLOCK + if (!beenHere) { + if (geteuid() == 0 && getuid() != geteuid()) + { + int status; + + status = fcntl(fileno(stderr), F_GETFL, 0); + if (status != -1) { + fcntl(fileno(stderr), F_SETFL, status | O_NONBLOCK); + } + } + } +#endif +#endif + + beenHere = TRUE; +} + +/* + * ddxGiveUp -- + * Device dependent cleanup. Called by by dix before normal server death. + * For SYSV386 we must switch the terminal back to normal mode. No error- + * checking here, since there should be restored as much as possible. + */ + +void +ddxGiveUp(void) +{ + int i; + + xf86VGAarbiterFini(); + +#ifdef XF86PM + if (xf86OSPMClose) + xf86OSPMClose(); + xf86OSPMClose = NULL; +#endif + + for (i = 0; i < xf86NumScreens; i++) { + /* + * zero all access functions to + * trap calls when switched away. + */ + xf86Screens[i]->vtSema = FALSE; + } + +#ifdef XFreeXDGA + DGAShutdown(); +#endif + + if (xorgHWOpenConsole) + xf86CloseConsole(); + + xf86CloseLog(); + + /* If an unexpected signal was caught, dump a core for debugging */ + if (xf86Info.caughtSignal) + OsAbort(); +} + + + +/* + * AbortDDX -- + * DDX - specific abort routine. Called by AbortServer(). The attempt is + * made to restore all original setting of the displays. Also all devices + * are closed. + */ + +void +AbortDDX(void) +{ + int i; + + /* + * try to restore the original video state + */ +#ifdef DPMSExtension /* Turn screens back on */ + if (DPMSPowerLevel != DPMSModeOn) + DPMSSet(serverClient, DPMSModeOn); +#endif + if (xf86Screens) { + if (xf86Screens[0]->vtSema) + xf86EnterServerState(SETUP); + for (i = 0; i < xf86NumScreens; i++) + if (xf86Screens[i]->vtSema) { + /* + * if we are aborting before ScreenInit() has finished + * we might not have been wrapped yet. Therefore enable + * screen explicitely. + */ + xf86VGAarbiterLock(xf86Screens[i]); + (xf86Screens[i]->LeaveVT)(i, 0); + xf86VGAarbiterUnlock(xf86Screens[i]); + } + } + + xf86AccessLeave(); + + /* + * This is needed for an abnormal server exit, since the normal exit stuff + * MUST also be performed (i.e. the vt must be left in a defined state) + */ + ddxGiveUp(); +} + +void +OsVendorFatalError(void) +{ +#ifdef VENDORSUPPORT + ErrorF("\nPlease refer to your Operating System Vendor support pages\n" + "at %s for support on this crash.\n",VENDORSUPPORT); +#else + ErrorF("\nPlease consult the "XVENDORNAME" support \n" + "\t at "__VENDORDWEBSUPPORT__"\n for help. \n"); +#endif + if (xf86LogFile && xf86LogFileWasOpened) + ErrorF("Please also check the log file at \"%s\" for additional " + "information.\n", xf86LogFile); + ErrorF("\n"); +} + +int +xf86SetVerbosity(int verb) +{ + int save = xf86Verbose; + + xf86Verbose = verb; + LogSetParameter(XLOG_VERBOSITY, verb); + return save; +} + +int +xf86SetLogVerbosity(int verb) +{ + int save = xf86LogVerbose; + + xf86LogVerbose = verb; + LogSetParameter(XLOG_FILE_VERBOSITY, verb); + return save; +} + +static void +xf86PrintDefaultModulePath(void) +{ + ErrorF("%s\n", DEFAULT_MODULE_PATH); +} + +static void +xf86PrintDefaultLibraryPath(void) +{ + ErrorF("%s\n", DEFAULT_LIBRARY_PATH); +} + +/* + * ddxProcessArgument -- + * Process device-dependent command line args. Returns 0 if argument is + * not device dependent, otherwise Count of number of elements of argv + * that are part of a device dependent commandline option. + * + */ + +/* ARGSUSED */ +int +ddxProcessArgument(int argc, char **argv, int i) +{ + /* + * Note: can't use xalloc/xfree here because OsInit() hasn't been called + * yet. Use malloc/free instead. + */ + +#define CHECK_FOR_REQUIRED_ARGUMENT() \ + if (((i + 1) >= argc) || (!argv[i + 1])) { \ + ErrorF("Required argument to %s not specified\n", argv[i]); \ + UseMsg(); \ + FatalError("Required argument to %s not specified\n", argv[i]); \ + } + + /* First the options that are only allowed for root */ + if (!strcmp(argv[i], "-modulepath") || !strcmp(argv[i], "-logfile")) { + if ( (geteuid() == 0) && (getuid() != 0) ) { + FatalError("The '%s' option can only be used by root.\n", argv[i]); + } + else if (!strcmp(argv[i], "-modulepath")) + { + char *mp; + CHECK_FOR_REQUIRED_ARGUMENT(); + mp = malloc(strlen(argv[i + 1]) + 1); + if (!mp) + FatalError("Can't allocate memory for ModulePath\n"); + strcpy(mp, argv[i + 1]); + xf86ModulePath = mp; + xf86ModPathFrom = X_CMDLINE; + return 2; + } + else if (!strcmp(argv[i], "-logfile")) + { + char *lf; + CHECK_FOR_REQUIRED_ARGUMENT(); + lf = malloc(strlen(argv[i + 1]) + 1); + if (!lf) + FatalError("Can't allocate memory for LogFile\n"); + strcpy(lf, argv[i + 1]); + xf86LogFile = lf; + xf86LogFileFrom = X_CMDLINE; + return 2; + } + } + if (!strcmp(argv[i], "-config") || !strcmp(argv[i], "-xf86config")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) { + FatalError("\nInvalid argument for %s\n" + "\tFor non-root users, the file specified with %s must be\n" + "\ta relative path and must not contain any \"..\" elements.\n" + "\tUsing default "__XCONFIGFILE__" search path.\n\n", + argv[i], argv[i]); + } + xf86ConfigFile = argv[i + 1]; + return 2; + } + if (!strcmp(argv[i], "-configdir")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + if (getuid() != 0 && !xf86PathIsSafe(argv[i + 1])) { + FatalError("\nInvalid argument for %s\n" + "\tFor non-root users, the file specified with %s must be\n" + "\ta relative path and must not contain any \"..\" elements.\n" + "\tUsing default "__XCONFIGDIR__" search path.\n\n", + argv[i], argv[i]); + } + xf86ConfigDir = argv[i + 1]; + return 2; + } + if (!strcmp(argv[i],"-flipPixels")) + { + xf86FlipPixels = TRUE; + return 1; + } +#ifdef XF86VIDMODE + if (!strcmp(argv[i],"-disableVidMode")) + { + xf86VidModeDisabled = TRUE; + return 1; + } + if (!strcmp(argv[i],"-allowNonLocalXvidtune")) + { + xf86VidModeAllowNonLocal = TRUE; + return 1; + } +#endif + if (!strcmp(argv[i],"-allowMouseOpenFail")) + { + xf86AllowMouseOpenFail = TRUE; + return 1; + } + if (!strcmp(argv[i],"-ignoreABI")) + { + LoaderSetOptions(LDR_OPT_ABI_MISMATCH_NONFATAL); + return 1; + } + if (!strcmp(argv[i],"-verbose")) + { + if (++i < argc && argv[i]) + { + char *end; + long val; + val = strtol(argv[i], &end, 0); + if (*end == '\0') + { + xf86SetVerbosity(val); + return 2; + } + } + xf86SetVerbosity(++xf86Verbose); + return 1; + } + if (!strcmp(argv[i],"-logverbose")) + { + if (++i < argc && argv[i]) + { + char *end; + long val; + val = strtol(argv[i], &end, 0); + if (*end == '\0') + { + xf86SetLogVerbosity(val); + return 2; + } + } + xf86SetLogVerbosity(++xf86LogVerbose); + return 1; + } + if (!strcmp(argv[i],"-quiet")) + { + xf86SetVerbosity(-1); + return 1; + } + if (!strcmp(argv[i],"-showconfig") || !strcmp(argv[i],"-version")) + { + xf86PrintBanner(); + exit(0); + } + if (!strcmp(argv[i],"-showDefaultModulePath")) + { + xf86PrintDefaultModulePath(); + exit(0); + } + if (!strcmp(argv[i],"-showDefaultLibPath")) + { + xf86PrintDefaultLibraryPath(); + exit(0); + } + /* Notice the -fp flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-fp")) + { + xf86fpFlag = TRUE; + return 0; + } + /* Notice the -bs flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-bs")) + { + xf86bsDisableFlag = TRUE; + return 0; + } + /* Notice the +bs flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "+bs")) + { + xf86bsEnableFlag = TRUE; + return 0; + } + /* Notice the -s flag, but allow it to pass to the dix layer */ + if (!strcmp(argv[i], "-s")) + { + xf86sFlag = TRUE; + return 0; + } + if (!strcmp(argv[i], "-pixmap24")) + { + xf86Pix24 = Pix24Use24; + return 1; + } + if (!strcmp(argv[i], "-pixmap32")) + { + xf86Pix24 = Pix24Use32; + return 1; + } + if (!strcmp(argv[i], "-fbbpp")) + { + int bpp; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (sscanf(argv[++i], "%d", &bpp) == 1) + { + xf86FbBpp = bpp; + return 2; + } + else + { + ErrorF("Invalid fbbpp\n"); + return 0; + } + } + if (!strcmp(argv[i], "-depth")) + { + int depth; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (sscanf(argv[++i], "%d", &depth) == 1) + { + xf86Depth = depth; + return 2; + } + else + { + ErrorF("Invalid depth\n"); + return 0; + } + } + if (!strcmp(argv[i], "-weight")) + { + int red, green, blue; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (sscanf(argv[++i], "%1d%1d%1d", &red, &green, &blue) == 3) + { + xf86Weight.red = red; + xf86Weight.green = green; + xf86Weight.blue = blue; + return 2; + } + else + { + ErrorF("Invalid weighting\n"); + return 0; + } + } + if (!strcmp(argv[i], "-gamma") || !strcmp(argv[i], "-rgamma") || + !strcmp(argv[i], "-ggamma") || !strcmp(argv[i], "-bgamma")) + { + double gamma; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (sscanf(argv[++i], "%lf", &gamma) == 1) { + if (gamma < GAMMA_MIN || gamma > GAMMA_MAX) { + ErrorF("gamma out of range, only %.2f <= gamma_value <= %.1f" + " is valid\n", GAMMA_MIN, GAMMA_MAX); + return 0; + } + if (!strcmp(argv[i-1], "-gamma")) + xf86Gamma.red = xf86Gamma.green = xf86Gamma.blue = gamma; + else if (!strcmp(argv[i-1], "-rgamma")) xf86Gamma.red = gamma; + else if (!strcmp(argv[i-1], "-ggamma")) xf86Gamma.green = gamma; + else if (!strcmp(argv[i-1], "-bgamma")) xf86Gamma.blue = gamma; + return 2; + } + } + if (!strcmp(argv[i], "-layout")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + xf86LayoutName = argv[++i]; + return 2; + } + if (!strcmp(argv[i], "-screen")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + xf86ScreenName = argv[++i]; + return 2; + } + if (!strcmp(argv[i], "-pointer")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + xf86PointerName = argv[++i]; + return 2; + } + if (!strcmp(argv[i], "-keyboard")) + { + CHECK_FOR_REQUIRED_ARGUMENT(); + xf86KeyboardName = argv[++i]; + return 2; + } + if (!strcmp(argv[i], "-nosilk")) + { + xf86silkenMouseDisableFlag = TRUE; + return 1; + } +#ifdef HAVE_ACPI + if (!strcmp(argv[i], "-noacpi")) + { + xf86acpiDisableFlag = TRUE; + return 1; + } +#endif + if (!strcmp(argv[i], "-configure")) + { + if (getuid() != 0 && geteuid() == 0) { + ErrorF("The '-configure' option can only be used by root.\n"); + exit(1); + } + xf86DoConfigure = TRUE; + xf86AllowMouseOpenFail = TRUE; + return 1; + } + if (!strcmp(argv[i], "-showopts")) + { + if (getuid() != 0 && geteuid() == 0) { + ErrorF("The '-showopts' option can only be used by root.\n"); + exit(1); + } + xf86DoShowOptions = TRUE; + return 1; + } + if (!strcmp(argv[i], "-isolateDevice")) + { + int bus, device, func; + CHECK_FOR_REQUIRED_ARGUMENT(); + if (strncmp(argv[++i], "PCI:", 4)) { + FatalError("Bus types other than PCI not yet isolable\n"); + } + if (sscanf(argv[i], "PCI:%d:%d:%d", &bus, &device, &func) == 3) { + xf86IsolateDevice.domain = PCI_DOM_FROM_BUS(bus); + xf86IsolateDevice.bus = PCI_BUS_NO_DOMAIN(bus); + xf86IsolateDevice.dev = device; + xf86IsolateDevice.func = func; + return 2; + } else { + FatalError("Invalid isolated device specification\n"); + } + } + /* Notice cmdline xkbdir, but pass to dix as well */ + if (!strcmp(argv[i], "-xkbdir")) + { + xf86xkbdirFlag = TRUE; + return 0; + } + + /* OS-specific processing */ + return xf86ProcessArgument(argc, argv, i); +} + +/* + * ddxUseMsg -- + * Print out correct use of device dependent commandline options. + * Maybe the user now knows what really to do ... + */ + +void +ddxUseMsg(void) +{ + ErrorF("\n"); + ErrorF("\n"); + ErrorF("Device Dependent Usage\n"); + if (getuid() == 0 || geteuid() != 0) + { + ErrorF("-modulepath paths specify the module search path\n"); + ErrorF("-logfile file specify a log file name\n"); + ErrorF("-configure probe for devices and write an "__XCONFIGFILE__"\n"); + ErrorF("-showopts print available options for all installed drivers\n"); + } + ErrorF("-config file specify a configuration file, relative to the\n"); + ErrorF(" "__XCONFIGFILE__" search path, only root can use absolute\n"); + ErrorF("-configdir dir specify a configuration directory, relative to the\n"); + ErrorF(" "__XCONFIGDIR__" search path, only root can use absolute\n"); + ErrorF("-verbose [n] verbose startup messages\n"); + ErrorF("-logverbose [n] verbose log messages\n"); + ErrorF("-quiet minimal startup messages\n"); + ErrorF("-pixmap24 use 24bpp pixmaps for depth 24\n"); + ErrorF("-pixmap32 use 32bpp pixmaps for depth 24\n"); + ErrorF("-fbbpp n set bpp for the framebuffer. Default: 8\n"); + ErrorF("-depth n set colour depth. Default: 8\n"); + ErrorF("-gamma f set gamma value (0.1 < f < 10.0) Default: 1.0\n"); + ErrorF("-rgamma f set gamma value for red phase\n"); + ErrorF("-ggamma f set gamma value for green phase\n"); + ErrorF("-bgamma f set gamma value for blue phase\n"); + ErrorF("-weight nnn set RGB weighting at 16 bpp. Default: 565\n"); + ErrorF("-layout name specify the ServerLayout section name\n"); + ErrorF("-screen name specify the Screen section name\n"); + ErrorF("-keyboard name specify the core keyboard InputDevice name\n"); + ErrorF("-pointer name specify the core pointer InputDevice name\n"); + ErrorF("-nosilk disable Silken Mouse\n"); + ErrorF("-flipPixels swap default black/white Pixel values\n"); +#ifdef XF86VIDMODE + ErrorF("-disableVidMode disable mode adjustments with xvidtune\n"); + ErrorF("-allowNonLocalXvidtune allow xvidtune to be run as a non-local client\n"); +#endif + ErrorF("-allowMouseOpenFail start server even if the mouse can't be initialized\n"); + ErrorF("-ignoreABI make module ABI mismatches non-fatal\n"); + ErrorF("-isolateDevice bus_id restrict device resets to bus_id (PCI only)\n"); + ErrorF("-version show the server version\n"); + ErrorF("-showDefaultModulePath show the server default module path\n"); + ErrorF("-showDefaultLibPath show the server default library path\n"); + /* OS-specific usage */ + xf86UseMsg(); + ErrorF("\n"); +} + + +/* + * xf86LoadModules iterates over a list that is being passed in. + */ +Bool +xf86LoadModules(char **list, pointer *optlist) +{ + int errmaj, errmin; + pointer opt; + int i; + char *name; + Bool failed = FALSE; + + if (!list) + return TRUE; + + for (i = 0; list[i] != NULL; i++) { + + /* Normalise the module name */ + name = xf86NormalizeName(list[i]); + + /* Skip empty names */ + if (name == NULL || *name == '\0') + continue; + + /* Replace obsolete keyboard driver with kbd */ + if (!xf86NameCmp(name, "keyboard")) { + strcpy(name, "kbd"); + } + + if (optlist) + opt = optlist[i]; + else + opt = NULL; + + if (!LoadModule(name, NULL, NULL, NULL, opt, NULL, &errmaj, &errmin)) { + LoaderErrorMsg(NULL, name, errmaj, errmin); + failed = TRUE; + } + free(name); + } + return !failed; +} + +/* Pixmap format stuff */ + +PixmapFormatPtr +xf86GetPixFormat(ScrnInfoPtr pScrn, int depth) +{ + int i; + static PixmapFormatRec format; /* XXX not reentrant */ + + /* + * When the formats[] list initialisation isn't complete, check the + * depth 24 pixmap config/cmdline options and screen-specified formats. + */ + + if (!formatsDone) { + if (depth == 24) { + Pix24Flags pix24 = Pix24DontCare; + + format.depth = 24; + format.scanlinePad = BITMAP_SCANLINE_PAD; + if (xf86Info.pixmap24 != Pix24DontCare) + pix24 = xf86Info.pixmap24; + else if (pScrn->pixmap24 != Pix24DontCare) + pix24 = pScrn->pixmap24; + if (pix24 == Pix24Use24) + format.bitsPerPixel = 24; + else + format.bitsPerPixel = 32; + return &format; + } + } + + for (i = 0; i < numFormats; i++) + if (formats[i].depth == depth) + break; + if (i != numFormats) + return &formats[i]; + else if (!formatsDone) { + /* Check for screen-specified formats */ + for (i = 0; i < pScrn->numFormats; i++) + if (pScrn->formats[i].depth == depth) + break; + if (i != pScrn->numFormats) + return &pScrn->formats[i]; + } + return NULL; +} + +int +xf86GetBppFromDepth(ScrnInfoPtr pScrn, int depth) +{ + PixmapFormatPtr format; + + + format = xf86GetPixFormat(pScrn, depth); + if (format) + return format->bitsPerPixel; + else + return 0; +} diff --git a/xorg-server/hw/xfree86/common/xf86Mode.c b/xorg-server/hw/xfree86/common/xf86Mode.c index 5d30a782c..af738e703 100644 --- a/xorg-server/hw/xfree86/common/xf86Mode.c +++ b/xorg-server/hw/xfree86/common/xf86Mode.c @@ -1,2067 +1,2067 @@ -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * LCM() and scanLineWidth() are: - * - * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org - * - * 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 Marc Aurele La France not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Marc Aurele La France makes no representations - * about the suitability of this software for any purpose. It is provided - * "as-is" without express or implied warranty. - * - * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO - * EVENT SHALL MARC AURELE LA FRANCE 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. - * - * Copyright 1990,91,92,93 by Thomas Roell, Germany. - * Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA. - * - * 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 Thomas Roell nor - * SGCS be used in advertising or publicity pertaining to distribution - * of the software without specific, written prior permission. - * Thomas Roell nor SGCS makes no representations about the suitability - * of this software for any purpose. It is provided "as is" without - * express or implied warranty. - * - * THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS 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. - */ - -/* - * Authors: Dirk Hohndel - * David Dawes - * Marc La France - * ... and others - * - * This file includes helper functions for mode related things. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "xf86Modes.h" -#include "os.h" -#include "servermd.h" -#include "globals.h" -#include "xf86.h" -#include "xf86Priv.h" -#include "edid.h" - -static void -printModeRejectMessage(int index, DisplayModePtr p, int status) -{ - char *type; - - if (p->type & M_T_BUILTIN) - type = "built-in "; - else if (p->type & M_T_DEFAULT) - type = "default "; - else if (p->type & M_T_DRIVER) - type = "driver "; - else - type = ""; - - xf86DrvMsg(index, X_INFO, "Not using %smode \"%s\" (%s)\n", type, p->name, - xf86ModeStatusToString(status)); -} - -/* - * xf86GetNearestClock -- - * Find closest clock to given frequency (in kHz). This assumes the - * number of clocks is greater than zero. - */ -int -xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, - int DivFactor, int MulFactor, int *divider) -{ - int nearestClock = 0, nearestDiv = 1; - int minimumGap = abs(freq - scrp->clock[0]); - int i, j, k, gap; - - if (allowDiv2) - k = 2; - else - k = 1; - - /* Must set this here in case the best match is scrp->clock[0] */ - if (divider != NULL) - *divider = 0; - - for (i = 0; i < scrp->numClocks; i++) { - for (j = 1; j <= k; j++) { - gap = abs((freq * j) - ((scrp->clock[i] * DivFactor) / MulFactor)); - if ((gap < minimumGap) || - ((gap == minimumGap) && (j < nearestDiv))) { - minimumGap = gap; - nearestClock = i; - nearestDiv = j; - if (divider != NULL) - *divider = (j - 1) * V_CLKDIV2; - } - } - } - return nearestClock; -} - -/* - * xf86ModeStatusToString - * - * Convert a ModeStatus value to a printable message - */ - -const char * -xf86ModeStatusToString(ModeStatus status) -{ - switch (status) { - case MODE_OK: - return "Mode OK"; - case MODE_HSYNC: - return "hsync out of range"; - case MODE_VSYNC: - return "vrefresh out of range"; - case MODE_H_ILLEGAL: - return "illegal horizontal timings"; - case MODE_V_ILLEGAL: - return "illegal vertical timings"; - case MODE_BAD_WIDTH: - return "width requires unsupported line pitch"; - case MODE_NOMODE: - return "no mode of this name"; - case MODE_NO_INTERLACE: - return "interlace mode not supported"; - case MODE_NO_DBLESCAN: - return "doublescan mode not supported"; - case MODE_NO_VSCAN: - return "multiscan mode not supported"; - case MODE_MEM: - return "insufficient memory for mode"; - case MODE_VIRTUAL_X: - return "width too large for virtual size"; - case MODE_VIRTUAL_Y: - return "height too large for virtual size"; - case MODE_MEM_VIRT: - return "insufficient memory given virtual size"; - case MODE_NOCLOCK: - return "no clock available for mode"; - case MODE_CLOCK_HIGH: - return "mode clock too high"; - case MODE_CLOCK_LOW: - return "mode clock too low"; - case MODE_CLOCK_RANGE: - return "bad mode clock/interlace/doublescan"; - case MODE_BAD_HVALUE: - return "horizontal timing out of range"; - case MODE_BAD_VVALUE: - return "vertical timing out of range"; - case MODE_BAD_VSCAN: - return "VScan value out of range"; - case MODE_HSYNC_NARROW: - return "horizontal sync too narrow"; - case MODE_HSYNC_WIDE: - return "horizontal sync too wide"; - case MODE_HBLANK_NARROW: - return "horizontal blanking too narrow"; - case MODE_HBLANK_WIDE: - return "horizontal blanking too wide"; - case MODE_VSYNC_NARROW: - return "vertical sync too narrow"; - case MODE_VSYNC_WIDE: - return "vertical sync too wide"; - case MODE_VBLANK_NARROW: - return "vertical blanking too narrow"; - case MODE_VBLANK_WIDE: - return "vertical blanking too wide"; - case MODE_PANEL: - return "exceeds panel dimensions"; - case MODE_INTERLACE_WIDTH: - return "width too large for interlaced mode"; - case MODE_ONE_WIDTH: - return "all modes must have the same width"; - case MODE_ONE_HEIGHT: - return "all modes must have the same height"; - case MODE_ONE_SIZE: - return "all modes must have the same resolution"; - case MODE_NO_REDUCED: - return "monitor doesn't support reduced blanking"; - case MODE_BANDWIDTH: - return "mode requires too much memory bandwidth"; - case MODE_BAD: - return "unknown reason"; - case MODE_ERROR: - return "internal error"; - default: - return "unknown"; - } -} - -/* - * xf86ShowClockRanges() -- Print the clock ranges allowed - * and the clock values scaled by ClockMulFactor and ClockDivFactor - */ -void -xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges) -{ - ClockRangePtr cp; - int MulFactor = 1; - int DivFactor = 1; - int i, j; - int scaledClock; - - for (cp = clockRanges; cp != NULL; cp = cp->next) { - DivFactor = max(1, cp->ClockDivFactor); - MulFactor = max(1, cp->ClockMulFactor); - if (scrp->progClock) { - if (cp->minClock) { - if (cp->maxClock) { - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "Clock range: %6.2f to %6.2f MHz\n", - (double)cp->minClock / 1000.0, - (double)cp->maxClock / 1000.0); - } else { - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "Minimum clock: %6.2f MHz\n", - (double)cp->minClock / 1000.0); - } - } else { - if (cp->maxClock) { - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "Maximum clock: %6.2f MHz\n", - (double)cp->maxClock / 1000.0); - } - } - } else if (DivFactor > 1 || MulFactor > 1) { - j = 0; - for (i = 0; i < scrp->numClocks; i++) { - scaledClock = (scrp->clock[i] * DivFactor) / MulFactor; - if (scaledClock >= cp->minClock && scaledClock <= cp->maxClock) { - if ((j % 8) == 0) { - if (j > 0) - xf86ErrorF("\n"); - xf86DrvMsg(scrp->scrnIndex, X_INFO, "scaled clocks:"); - } - xf86ErrorF(" %6.2f", (double)scaledClock / 1000.0); - j++; - } - } - xf86ErrorF("\n"); - } - } -} - -static Bool -modeInClockRange(ClockRangePtr cp, DisplayModePtr p) -{ - return ((p->Clock >= cp->minClock) && - (p->Clock <= cp->maxClock) && - (cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) && - (cp->doubleScanAllowed || - ((p->VScan <= 1) && !(p->Flags & V_DBLSCAN)))); -} - -/* - * xf86FindClockRangeForMode() [... like the name says ...] - */ -static ClockRangePtr -xf86FindClockRangeForMode(ClockRangePtr clockRanges, DisplayModePtr p) -{ - ClockRangePtr cp; - - for (cp = clockRanges; ; cp = cp->next) - if (!cp || modeInClockRange(cp, p)) - return cp; -} - - -/* - * xf86HandleBuiltinMode() - handles built-in modes - */ -static ModeStatus -xf86HandleBuiltinMode(ScrnInfoPtr scrp, - DisplayModePtr p, - DisplayModePtr modep, - ClockRangePtr clockRanges, - Bool allowDiv2) -{ - ClockRangePtr cp; - int extraFlags = 0; - int MulFactor = 1; - int DivFactor = 1; - int clockIndex; - - /* Reject previously rejected modes */ - if (p->status != MODE_OK) - return p->status; - - /* Reject previously considered modes */ - if (p->prev) - return MODE_NOMODE; - - if ((p->type & M_T_CLOCK_C) == M_T_CLOCK_C) { - /* Check clock is in range */ - cp = xf86FindClockRangeForMode(clockRanges, p); - if (cp == NULL){ - modep->type = p->type; - p->status = MODE_CLOCK_RANGE; - return MODE_CLOCK_RANGE; - } - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - if (!scrp->progClock) { - clockIndex = xf86GetNearestClock(scrp, p->Clock, allowDiv2, - cp->ClockDivFactor, - cp->ClockMulFactor, &extraFlags); - modep->Clock = (scrp->clock[clockIndex] * DivFactor) - / MulFactor; - modep->ClockIndex = clockIndex; - modep->SynthClock = scrp->clock[clockIndex]; - if (extraFlags & V_CLKDIV2) { - modep->Clock /= 2; - modep->SynthClock /= 2; - } - } else { - modep->Clock = p->Clock; - modep->ClockIndex = -1; - modep->SynthClock = (modep->Clock * MulFactor) - / DivFactor; - } - modep->PrivFlags = cp->PrivFlags; - } else { - if(!scrp->progClock) { - modep->Clock = p->Clock; - modep->ClockIndex = p->ClockIndex; - modep->SynthClock = p->SynthClock; - } else { - modep->Clock = p->Clock; - modep->ClockIndex = -1; - modep->SynthClock = p->SynthClock; - } - modep->PrivFlags = p->PrivFlags; - } - modep->type = p->type; - modep->HDisplay = p->HDisplay; - modep->HSyncStart = p->HSyncStart; - modep->HSyncEnd = p->HSyncEnd; - modep->HTotal = p->HTotal; - modep->HSkew = p->HSkew; - modep->VDisplay = p->VDisplay; - modep->VSyncStart = p->VSyncStart; - modep->VSyncEnd = p->VSyncEnd; - modep->VTotal = p->VTotal; - modep->VScan = p->VScan; - modep->Flags = p->Flags | extraFlags; - modep->CrtcHDisplay = p->CrtcHDisplay; - modep->CrtcHBlankStart = p->CrtcHBlankStart; - modep->CrtcHSyncStart = p->CrtcHSyncStart; - modep->CrtcHSyncEnd = p->CrtcHSyncEnd; - modep->CrtcHBlankEnd = p->CrtcHBlankEnd; - modep->CrtcHTotal = p->CrtcHTotal; - modep->CrtcHSkew = p->CrtcHSkew; - modep->CrtcVDisplay = p->CrtcVDisplay; - modep->CrtcVBlankStart = p->CrtcVBlankStart; - modep->CrtcVSyncStart = p->CrtcVSyncStart; - modep->CrtcVSyncEnd = p->CrtcVSyncEnd; - modep->CrtcVBlankEnd = p->CrtcVBlankEnd; - modep->CrtcVTotal = p->CrtcVTotal; - modep->CrtcHAdjusted = p->CrtcHAdjusted; - modep->CrtcVAdjusted = p->CrtcVAdjusted; - modep->HSync = p->HSync; - modep->VRefresh = p->VRefresh; - modep->Private = p->Private; - modep->PrivSize = p->PrivSize; - - p->prev = modep; - - return MODE_OK; -} - -/* - * xf86LookupMode - * - * This function returns a mode from the given list which matches the - * given name. When multiple modes with the same name are available, - * the method of picking the matching mode is determined by the - * strategy selected. - * - * This function takes the following parameters: - * scrp ScrnInfoPtr - * modep pointer to the returned mode, which must have the name - * field filled in. - * clockRanges a list of clock ranges. This is optional when all the - * modes are built-in modes. - * strategy how to decide which mode to use from multiple modes with - * the same name - * - * In addition, the following fields from the ScrnInfoRec are used: - * modePool the list of monitor modes compatible with the driver - * clocks a list of discrete clocks - * numClocks number of discrete clocks - * progClock clock is programmable - * - * If a mode was found, its values are filled in to the area pointed to - * by modep, If a mode was not found the return value indicates the - * reason. - */ - -ModeStatus -xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, - ClockRangePtr clockRanges, LookupModeFlags strategy) -{ - DisplayModePtr p, bestMode = NULL; - ClockRangePtr cp; - int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1; - double refresh, bestRefresh = 0.0; - Bool found = FALSE; - int extraFlags = 0; - int clockIndex = -1; - int MulFactor = 1; - int DivFactor = 1; - int ModePrivFlags = 0; - ModeStatus status = MODE_NOMODE; - Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0; - int n; - const int types[] = { - M_T_BUILTIN | M_T_PREFERRED, - M_T_BUILTIN, - M_T_USERDEF | M_T_PREFERRED, - M_T_USERDEF, - M_T_DRIVER | M_T_PREFERRED, - M_T_DRIVER, - 0 - }; - const int ntypes = sizeof(types) / sizeof(int); - - strategy &= ~(LOOKUP_CLKDIV2 | LOOKUP_OPTIONAL_TOLERANCES); - - /* Some sanity checking */ - if (scrp == NULL || scrp->modePool == NULL || - (!scrp->progClock && scrp->numClocks == 0)) { - ErrorF("xf86LookupMode: called with invalid scrnInfoRec\n"); - return MODE_ERROR; - } - if (modep == NULL || modep->name == NULL) { - ErrorF("xf86LookupMode: called with invalid modep\n"); - return MODE_ERROR; - } - for (cp = clockRanges; cp != NULL; cp = cp->next) { - /* DivFactor and MulFactor must be > 0 */ - cp->ClockDivFactor = max(1, cp->ClockDivFactor); - cp->ClockMulFactor = max(1, cp->ClockMulFactor); - } - - /* Scan the mode pool for matching names */ - for (n = 0; n < ntypes; n++) { - int type = types[n]; - for (p = scrp->modePool; p != NULL; p = p->next) { - - /* scan through the modes in the sort order above */ - if ((p->type & type) != type) - continue; - - if (strcmp(p->name, modep->name) == 0) { - - /* Skip over previously rejected modes */ - if (p->status != MODE_OK) { - if (!found) - status = p->status; - continue; - } - - /* Skip over previously considered modes */ - if (p->prev) - continue; - - if (p->type & M_T_BUILTIN) { - return xf86HandleBuiltinMode(scrp, p,modep, clockRanges, - allowDiv2); - } - - /* Check clock is in range */ - cp = xf86FindClockRangeForMode(clockRanges, p); - if (cp == NULL) { - /* - * XXX Could do more here to provide a more detailed - * reason for not finding a mode. - */ - p->status = MODE_CLOCK_RANGE; - if (!found) - status = MODE_CLOCK_RANGE; - continue; - } - - /* - * If programmable clock and strategy is not - * LOOKUP_BEST_REFRESH, the required mode has been found, - * otherwise record the refresh and continue looking. - */ - if (scrp->progClock) { - found = TRUE; - if (strategy != LOOKUP_BEST_REFRESH) { - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - break; - } - refresh = xf86ModeVRefresh(p); - if (p->Flags & V_INTERLACE) - refresh /= INTERLACE_REFRESH_WEIGHT; - if (refresh > bestRefresh) { - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - bestRefresh = refresh; - } - continue; - } - - /* - * Clock is in range, so if it is not a programmable clock, find - * a matching clock. - */ - - i = xf86GetNearestClock(scrp, p->Clock, allowDiv2, - cp->ClockDivFactor, cp->ClockMulFactor, &k); - /* - * If the clock is too far from the requested clock, this - * mode is no good. - */ - if (k & V_CLKDIV2) - gap = abs((p->Clock * 2) - - ((scrp->clock[i] * cp->ClockDivFactor) / - cp->ClockMulFactor)); - else - gap = abs(p->Clock - - ((scrp->clock[i] * cp->ClockDivFactor) / - cp->ClockMulFactor)); - if (gap > minimumGap) { - p->status = MODE_NOCLOCK; - if (!found) - status = MODE_NOCLOCK; - continue; - } - found = TRUE; - - if (strategy == LOOKUP_BEST_REFRESH) { - refresh = xf86ModeVRefresh(p); - if (p->Flags & V_INTERLACE) - refresh /= INTERLACE_REFRESH_WEIGHT; - if (refresh > bestRefresh) { - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - extraFlags = k; - clockIndex = i; - bestRefresh = refresh; - } - continue; - } - if (strategy == LOOKUP_CLOSEST_CLOCK) { - if (gap < minimumGap) { - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - extraFlags = k; - clockIndex = i; - minimumGap = gap; - } - continue; - } - /* - * If strategy is neither LOOKUP_BEST_REFRESH or - * LOOKUP_CLOSEST_CLOCK the required mode has been found. - */ - bestMode = p; - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - extraFlags = k; - clockIndex = i; - break; - } - } - if (found) break; - } - if (!found || bestMode == NULL) - return status; - - /* Fill in the mode parameters */ - if (scrp->progClock) { - modep->Clock = bestMode->Clock; - modep->ClockIndex = -1; - modep->SynthClock = (modep->Clock * MulFactor) / DivFactor; - } else { - modep->Clock = (scrp->clock[clockIndex] * DivFactor) / - MulFactor; - modep->ClockIndex = clockIndex; - modep->SynthClock = scrp->clock[clockIndex]; - if (extraFlags & V_CLKDIV2) { - modep->Clock /= 2; - modep->SynthClock /= 2; - } - } - modep->type = bestMode->type; - modep->PrivFlags = ModePrivFlags; - modep->HDisplay = bestMode->HDisplay; - modep->HSyncStart = bestMode->HSyncStart; - modep->HSyncEnd = bestMode->HSyncEnd; - modep->HTotal = bestMode->HTotal; - modep->HSkew = bestMode->HSkew; - modep->VDisplay = bestMode->VDisplay; - modep->VSyncStart = bestMode->VSyncStart; - modep->VSyncEnd = bestMode->VSyncEnd; - modep->VTotal = bestMode->VTotal; - modep->VScan = bestMode->VScan; - modep->Flags = bestMode->Flags | extraFlags; - modep->CrtcHDisplay = bestMode->CrtcHDisplay; - modep->CrtcHBlankStart = bestMode->CrtcHBlankStart; - modep->CrtcHSyncStart = bestMode->CrtcHSyncStart; - modep->CrtcHSyncEnd = bestMode->CrtcHSyncEnd; - modep->CrtcHBlankEnd = bestMode->CrtcHBlankEnd; - modep->CrtcHTotal = bestMode->CrtcHTotal; - modep->CrtcHSkew = bestMode->CrtcHSkew; - modep->CrtcVDisplay = bestMode->CrtcVDisplay; - modep->CrtcVBlankStart = bestMode->CrtcVBlankStart; - modep->CrtcVSyncStart = bestMode->CrtcVSyncStart; - modep->CrtcVSyncEnd = bestMode->CrtcVSyncEnd; - modep->CrtcVBlankEnd = bestMode->CrtcVBlankEnd; - modep->CrtcVTotal = bestMode->CrtcVTotal; - modep->CrtcHAdjusted = bestMode->CrtcHAdjusted; - modep->CrtcVAdjusted = bestMode->CrtcVAdjusted; - modep->HSync = bestMode->HSync; - modep->VRefresh = bestMode->VRefresh; - modep->Private = bestMode->Private; - modep->PrivSize = bestMode->PrivSize; - - bestMode->prev = modep; - - return MODE_OK; -} - -/* - * xf86CheckModeForMonitor - * - * This function takes a mode and monitor description, and determines - * if the mode is valid for the monitor. - */ -ModeStatus -xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor) -{ - int i; - - /* Sanity checks */ - if (mode == NULL || monitor == NULL) { - ErrorF("xf86CheckModeForMonitor: called with invalid parameters\n"); - return MODE_ERROR; - } - - DebugF("xf86CheckModeForMonitor(%p %s, %p %s)\n", - mode, mode->name, monitor, monitor->id); - - /* Some basic mode validity checks */ - if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart || - mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal) - return MODE_H_ILLEGAL; - - if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart || - mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal) - return MODE_V_ILLEGAL; - - if (monitor->nHsync > 0) { - /* Check hsync against the allowed ranges */ - float hsync = xf86ModeHSync(mode); - for (i = 0; i < monitor->nHsync; i++) - if ((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && - (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) - break; - - /* Now see whether we ran out of sync ranges without finding a match */ - if (i == monitor->nHsync) - return MODE_HSYNC; - } - - if (monitor->nVrefresh > 0) { - /* Check vrefresh against the allowed ranges */ - float vrefrsh = xf86ModeVRefresh(mode); - for (i = 0; i < monitor->nVrefresh; i++) - if ((vrefrsh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && - (vrefrsh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) - break; - - /* Now see whether we ran out of refresh ranges without finding a match */ - if (i == monitor->nVrefresh) - return MODE_VSYNC; - } - - /* Force interlaced modes to have an odd VTotal */ - if (mode->Flags & V_INTERLACE) - mode->CrtcVTotal = mode->VTotal |= 1; - - /* - * This code stops cvt -r modes, and only cvt -r modes, from hitting 15y+ - * old CRTs which might, when there is a lot of solar flare activity and - * when the celestial bodies are unfavourably aligned, implode trying to - * sync to it. It's called "Protecting the user from doing anything stupid". - * -- libv - */ - - if (xf86ModeIsReduced(mode)) { - if (!monitor->reducedblanking && !(mode->type & M_T_DRIVER)) - return MODE_NO_REDUCED; - } - - if ((monitor->maxPixClock) && (mode->Clock > monitor->maxPixClock)) - return MODE_CLOCK_HIGH; - - return MODE_OK; -} - -/* - * xf86CheckModeSize - * - * An internal routine to check if a mode fits in video memory. This tries to - * avoid overflows that would otherwise occur when video memory size is greater - * than 256MB. - */ -static Bool -xf86CheckModeSize(ScrnInfoPtr scrp, int w, int x, int y) -{ - int bpp = scrp->fbFormat.bitsPerPixel, - pad = scrp->fbFormat.scanlinePad; - int lineWidth, lastWidth; - - if (scrp->depth == 4) - pad *= 4; /* 4 planes */ - - /* Sanity check */ - if ((w < 0) || (x < 0) || (y <= 0)) - return FALSE; - - lineWidth = (((w * bpp) + pad - 1) / pad) * pad; - lastWidth = x * bpp; - - /* - * At this point, we need to compare - * - * (lineWidth * (y - 1)) + lastWidth - * - * against - * - * scrp->videoRam * (1024 * 8) - * - * These are bit quantities. To avoid overflows, do the comparison in - * terms of BITMAP_SCANLINE_PAD units. This assumes BITMAP_SCANLINE_PAD - * is a power of 2. We currently use 32, which limits us to a video - * memory size of 8GB. - */ - - lineWidth = (lineWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD; - lastWidth = (lastWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD; - - if ((lineWidth * (y - 1) + lastWidth) > - (scrp->videoRam * ((1024 * 8) / BITMAP_SCANLINE_PAD))) - return FALSE; - - return TRUE; -} - -/* - * xf86InitialCheckModeForDriver - * - * This function checks if a mode satisfies a driver's initial requirements: - * - mode size fits within the available pixel area (memory) - * - width lies within the range of supported line pitches - * - mode size fits within virtual size (if fixed) - * - horizontal timings are in range - * - * This function takes the following parameters: - * scrp ScrnInfoPtr - * mode mode to check - * maxPitch (optional) maximum line pitch - * virtualX (optional) virtual width requested - * virtualY (optional) virtual height requested - * - * In addition, the following fields from the ScrnInfoRec are used: - * monitor pointer to structure for monitor section - * fbFormat pixel format for the framebuffer - * videoRam video memory size (in kB) - * maxHValue maximum horizontal timing value - * maxVValue maximum vertical timing value - */ - -ModeStatus -xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, - ClockRangePtr clockRanges, - LookupModeFlags strategy, - int maxPitch, int virtualX, int virtualY) -{ - ClockRangePtr cp; - ModeStatus status; - Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0; - int i, needDiv2; - - /* Sanity checks */ - if (!scrp || !mode || !clockRanges) { - ErrorF("xf86InitialCheckModeForDriver: " - "called with invalid parameters\n"); - return MODE_ERROR; - } - - DebugF("xf86InitialCheckModeForDriver(%p, %p %s, %p, 0x%x, %d, %d, %d)\n", - scrp, mode, mode->name , clockRanges, strategy, maxPitch, virtualX, virtualY); - - /* Some basic mode validity checks */ - if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart || - mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal) - return MODE_H_ILLEGAL; - - if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart || - mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal) - return MODE_V_ILLEGAL; - - if (!xf86CheckModeSize(scrp, mode->HDisplay, mode->HDisplay, - mode->VDisplay)) - return MODE_MEM; - - if (maxPitch > 0 && mode->HDisplay > maxPitch) - return MODE_BAD_WIDTH; - - if (virtualX > 0 && mode->HDisplay > virtualX) - return MODE_VIRTUAL_X; - - if (virtualY > 0 && mode->VDisplay > virtualY) - return MODE_VIRTUAL_Y; - - if (scrp->maxHValue > 0 && mode->HTotal > scrp->maxHValue) - return MODE_BAD_HVALUE; - - if (scrp->maxVValue > 0 && mode->VTotal > scrp->maxVValue) - return MODE_BAD_VVALUE; - - /* - * The use of the DisplayModeRec's Crtc* and SynthClock elements below is - * provisional, in that they are later reused by the driver at mode-set - * time. Here, they are temporarily enlisted to contain the mode timings - * as seen by the CRT or panel (rather than the CRTC). The driver's - * ValidMode() is allowed to modify these so it can deal with such things - * as mode stretching and/or centering. The driver should >NOT< modify the - * user-supplied values as these are reported back when mode validation is - * said and done. - */ - /* - * NOTE: We (ab)use the mode->Crtc* values here to store timing - * information for the calculation of Hsync and Vrefresh. Before - * these values are calculated the driver is given the opportunity - * to either set these HSync and VRefresh itself or modify the timing - * values. - * The difference to the final calculation is small but imortand: - * here we pass the flag INTERLACE_HALVE_V regardless if the driver - * sets it or not. This way our calculation of VRefresh has the same - * effect as if we do if (flags & V_INTERLACE) refresh *= 2.0 - * This dual use of the mode->Crtc* values will certainly create - * confusion and is bad software design. However since it's part of - * the driver API it's hard to change. - */ - - if (scrp->ValidMode) { - - xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - - cp = xf86FindClockRangeForMode(clockRanges, mode); - if (!cp) - return MODE_CLOCK_RANGE; - - if (cp->ClockMulFactor < 1) - cp->ClockMulFactor = 1; - if (cp->ClockDivFactor < 1) - cp->ClockDivFactor = 1; - - /* - * XXX The effect of clock dividers and multipliers on the monitor's - * pixel clock needs to be verified. - */ - if (scrp->progClock) { - mode->SynthClock = mode->Clock; - } else { - i = xf86GetNearestClock(scrp, mode->Clock, allowDiv2, - cp->ClockDivFactor, cp->ClockMulFactor, - &needDiv2); - mode->SynthClock = (scrp->clock[i] * cp->ClockDivFactor) / - cp->ClockMulFactor; - if (needDiv2 & V_CLKDIV2) - mode->SynthClock /= 2; - } - - status = (*scrp->ValidMode)(scrp->scrnIndex, mode, FALSE, - MODECHECK_INITIAL); - if (status != MODE_OK) - return status; - - if (mode->HSync <= 0.0) - mode->HSync = (float)mode->SynthClock / (float)mode->CrtcHTotal; - if (mode->VRefresh <= 0.0) - mode->VRefresh = (mode->SynthClock * 1000.0) - / (mode->CrtcHTotal * mode->CrtcVTotal); - } - - mode->HSync = xf86ModeHSync(mode); - mode->VRefresh = xf86ModeVRefresh(mode); - - /* Assume it is OK */ - return MODE_OK; -} - -/* - * xf86CheckModeForDriver - * - * This function is for checking modes while the server is running (for - * use mainly by the VidMode extension). - * - * This function checks if a mode satisfies a driver's requirements: - * - width lies within the line pitch - * - mode size fits within virtual size - * - horizontal/vertical timings are in range - * - * This function takes the following parameters: - * scrp ScrnInfoPtr - * mode mode to check - * flags not (currently) used - * - * In addition, the following fields from the ScrnInfoRec are used: - * maxHValue maximum horizontal timing value - * maxVValue maximum vertical timing value - * virtualX virtual width - * virtualY virtual height - * clockRanges allowable clock ranges - */ - -ModeStatus -xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags) -{ - ClockRangePtr cp; - int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1; - int extraFlags = 0; - int clockIndex = -1; - int MulFactor = 1; - int DivFactor = 1; - int ModePrivFlags = 0; - ModeStatus status = MODE_NOMODE; - - /* Some sanity checking */ - if (scrp == NULL || (!scrp->progClock && scrp->numClocks == 0)) { - ErrorF("xf86CheckModeForDriver: called with invalid scrnInfoRec\n"); - return MODE_ERROR; - } - if (mode == NULL) { - ErrorF("xf86CheckModeForDriver: called with invalid modep\n"); - return MODE_ERROR; - } - - /* Check the mode size */ - if (mode->HDisplay > scrp->virtualX) - return MODE_VIRTUAL_X; - - if (mode->VDisplay > scrp->virtualY) - return MODE_VIRTUAL_Y; - - if (scrp->maxHValue > 0 && mode->HTotal > scrp->maxHValue) - return MODE_BAD_HVALUE; - - if (scrp->maxVValue > 0 && mode->VTotal > scrp->maxVValue) - return MODE_BAD_VVALUE; - - for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { - /* DivFactor and MulFactor must be > 0 */ - cp->ClockDivFactor = max(1, cp->ClockDivFactor); - cp->ClockMulFactor = max(1, cp->ClockMulFactor); - } - - if (scrp->progClock) { - /* Check clock is in range */ - for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { - if (modeInClockRange(cp, mode)) - break; - } - if (cp == NULL) { - return MODE_CLOCK_RANGE; - } - /* - * If programmable clock the required mode has been found - */ - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - } else { - status = MODE_CLOCK_RANGE; - /* Check clock is in range */ - for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { - if (modeInClockRange(cp, mode)) { - /* - * Clock is in range, so if it is not a programmable clock, - * find a matching clock. - */ - - i = xf86GetNearestClock(scrp, mode->Clock, 0, - cp->ClockDivFactor, cp->ClockMulFactor, &k); - /* - * If the clock is too far from the requested clock, this - * mode is no good. - */ - if (k & V_CLKDIV2) - gap = abs((mode->Clock * 2) - - ((scrp->clock[i] * cp->ClockDivFactor) / - cp->ClockMulFactor)); - else - gap = abs(mode->Clock - - ((scrp->clock[i] * cp->ClockDivFactor) / - cp->ClockMulFactor)); - if (gap > minimumGap) { - status = MODE_NOCLOCK; - continue; - } - - DivFactor = cp->ClockDivFactor; - MulFactor = cp->ClockMulFactor; - ModePrivFlags = cp->PrivFlags; - extraFlags = k; - clockIndex = i; - break; - } - } - if (cp == NULL) - return status; - } - - /* Fill in the mode parameters */ - if (scrp->progClock) { - mode->ClockIndex = -1; - mode->SynthClock = (mode->Clock * MulFactor) / DivFactor; - } else { - mode->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor; - mode->ClockIndex = clockIndex; - mode->SynthClock = scrp->clock[clockIndex]; - if (extraFlags & V_CLKDIV2) { - mode->Clock /= 2; - mode->SynthClock /= 2; - } - } - mode->PrivFlags = ModePrivFlags; - - return MODE_OK; -} - -static int -inferVirtualSize(ScrnInfoPtr scrp, DisplayModePtr modes, int *vx, int *vy) -{ - float aspect = 0.0; - MonPtr mon = scrp->monitor; - xf86MonPtr DDC; - int x = 0, y = 0; - DisplayModePtr mode; - - if (!mon) return 0; - DDC = mon->DDC; - - if (DDC && DDC->ver.revision >= 4) { - /* For 1.4, we might actually get native pixel format. How novel. */ - if (PREFERRED_TIMING_MODE(DDC->features.msc)) { - for (mode = modes; mode; mode = mode->next) { - if (mode->type & (M_T_DRIVER | M_T_PREFERRED)) { - x = mode->HDisplay; - y = mode->VDisplay; - goto found; - } - } - } - /* - * Even if we don't, we might get aspect ratio from extra CVT info - * or from the monitor size fields. TODO. - */ - } - - /* - * Technically this triggers if either is zero. That wasn't legal - * before EDID 1.4, but right now we'll get that wrong. TODO. - */ - if (!aspect) { - if (!mon->widthmm || !mon->heightmm) - aspect = 4.0/3.0; - else - aspect = (float)mon->widthmm / (float)mon->heightmm; - } - - /* find the largest M_T_DRIVER mode with that aspect ratio */ - for (mode = modes; mode; mode = mode->next) { - float mode_aspect, metaspect; - if (!(mode->type & (M_T_DRIVER|M_T_USERDEF))) - continue; - mode_aspect = (float)mode->HDisplay / (float)mode->VDisplay; - metaspect = aspect / mode_aspect; - /* 5% slop or so, since we only get size in centimeters */ - if (fabs(1.0 - metaspect) < 0.05) { - if ((mode->HDisplay > x) && (mode->VDisplay > y)) { - x = mode->HDisplay; - y = mode->VDisplay; - } - } - } - - if (!x || !y) { - xf86DrvMsg(scrp->scrnIndex, X_WARNING, - "Unable to estimate virtual size\n"); - return 0; - } - -found: - *vx = x; - *vy = y; - - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "Estimated virtual size for aspect ratio %.4f is %dx%d\n", - aspect, *vx, *vy); - - return 1; -} - -/* Least common multiple */ -static unsigned int -LCM(unsigned int x, unsigned int y) -{ - unsigned int m = x, n = y, o; - - while ((o = m % n)) - { - m = n; - n = o; - } - - return (x / n) * y; -} - -/* - * Given various screen attributes, determine the minimum scanline width such - * that each scanline is server and DDX padded and any pixels with imbedded - * bank boundaries are off-screen. This function returns -1 if such a width - * cannot exist. - */ -static int -scanLineWidth( - unsigned int xsize, /* pixels */ - unsigned int ysize, /* pixels */ - unsigned int width, /* pixels */ - unsigned long BankSize, /* char's */ - PixmapFormatRec *pBankFormat, - unsigned int nWidthUnit /* bits */ -) -{ - unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit; - unsigned long minBitsPerScanline, maxBitsPerScanline; - - /* Sanity checks */ - - if (!nWidthUnit || !pBankFormat) - return -1; - - nBitsPerBank = BankSize * 8; - if (nBitsPerBank % pBankFormat->scanlinePad) - return -1; - - if (xsize > width) - width = xsize; - nBitsPerScanlinePadUnit = LCM(pBankFormat->scanlinePad, nWidthUnit); - nBitsPerScanline = - (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) / - nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit; - width = nBitsPerScanline / pBankFormat->bitsPerPixel; - - if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel)) - return (int)width; - - /* - * Scanlines will be server-pad aligned at this point. They will also be - * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded - * bank boundaries are off-screen. - * - * It seems reasonable to limit total frame buffer size to 1/16 of the - * theoretical maximum address space size. On a machine with 32-bit - * addresses (to 8-bit quantities) this turns out to be 256MB. Not only - * does this provide a simple limiting condition for the loops below, but - * it also prevents unsigned long wraparounds. - */ - if (!ysize) - return -1; - - minBitsPerScanline = xsize * pBankFormat->bitsPerPixel; - if (minBitsPerScanline > nBitsPerBank) - return -1; - - if (ysize == 1) - return (int)width; - - maxBitsPerScanline = - (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1); - while (nBitsPerScanline <= maxBitsPerScanline) - { - unsigned long BankBase, BankUnit; - - BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) * - nBitsPerBank; - if (!(BankUnit % nBitsPerScanline)) - return (int)width; - - for (BankBase = BankUnit; ; BankBase += nBitsPerBank) - { - unsigned long x, y; - - y = BankBase / nBitsPerScanline; - if (y >= ysize) - return (int)width; - - x = BankBase % nBitsPerScanline; - if (!(x % pBankFormat->bitsPerPixel)) - continue; - - if (x < minBitsPerScanline) - { - /* - * Skip ahead certain widths by dividing the excess scanline - * amongst the y's. - */ - y *= nBitsPerScanlinePadUnit; - nBitsPerScanline += - ((x + y - 1) / y) * nBitsPerScanlinePadUnit; - width = nBitsPerScanline / pBankFormat->bitsPerPixel; - break; - } - - if (BankBase != BankUnit) - continue; - - if (!(nBitsPerScanline % x)) - return (int)width; - - BankBase = ((nBitsPerScanline - minBitsPerScanline) / - (nBitsPerScanline - x)) * BankUnit; - } - } - - return -1; -} - -/* - * xf86ValidateModes - * - * This function takes a set of mode names, modes and limiting conditions, - * and selects a set of modes and parameters based on those conditions. - * - * This function takes the following parameters: - * scrp ScrnInfoPtr - * availModes the list of modes available for the monitor - * modeNames (optional) list of mode names that the screen is requesting - * clockRanges a list of clock ranges - * linePitches (optional) a list of line pitches - * minPitch (optional) minimum line pitch (in pixels) - * maxPitch (optional) maximum line pitch (in pixels) - * pitchInc (mandatory) pitch increment (in bits) - * minHeight (optional) minimum virtual height (in pixels) - * maxHeight (optional) maximum virtual height (in pixels) - * virtualX (optional) virtual width requested (in pixels) - * virtualY (optional) virtual height requested (in pixels) - * apertureSize size of video aperture (in bytes) - * strategy how to decide which mode to use from multiple modes with - * the same name - * - * In addition, the following fields from the ScrnInfoRec are used: - * clocks a list of discrete clocks - * numClocks number of discrete clocks - * progClock clock is programmable - * monitor pointer to structure for monitor section - * fbFormat format of the framebuffer - * videoRam video memory size - * maxHValue maximum horizontal timing value - * maxVValue maximum vertical timing value - * xInc horizontal timing increment (defaults to 8 pixels) - * - * The function fills in the following ScrnInfoRec fields: - * modePool A subset of the modes available to the monitor which - * are compatible with the driver. - * modes one mode entry for each of the requested modes, with the - * status field filled in to indicate if the mode has been - * accepted or not. - * virtualX the resulting virtual width - * virtualY the resulting virtual height - * displayWidth the resulting line pitch - * - * The function's return value is the number of matching modes found, or -1 - * if an unrecoverable error was encountered. - */ - -int -xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, - char **modeNames, ClockRangePtr clockRanges, - int *linePitches, int minPitch, int maxPitch, int pitchInc, - int minHeight, int maxHeight, int virtualX, int virtualY, - int apertureSize, LookupModeFlags strategy) -{ - DisplayModePtr p, q, r, new, last, *endp; - int i, numModes = 0; - ModeStatus status; - int linePitch = -1, virtX = 0, virtY = 0; - int newLinePitch, newVirtX, newVirtY; - int modeSize; /* in pixels */ - Bool validateAllDefaultModes = FALSE; - Bool userModes = FALSE; - int saveType; - PixmapFormatRec *BankFormat; - ClockRangePtr cp; - ClockRangePtr storeClockRanges; - int numTimings = 0; - range hsync[MAX_HSYNC]; - range vrefresh[MAX_VREFRESH]; - Bool inferred_virtual = FALSE; - - DebugF("xf86ValidateModes(%p, %p, %p, %p,\n\t\t %p, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x)\n", - scrp, availModes, modeNames, clockRanges, - linePitches, minPitch, maxPitch, pitchInc, - minHeight, maxHeight, virtualX, virtualY, - apertureSize, strategy - ); - - /* Some sanity checking */ - if (scrp == NULL || scrp->name == NULL || !scrp->monitor || - (!scrp->progClock && scrp->numClocks == 0)) { - ErrorF("xf86ValidateModes: called with invalid scrnInfoRec\n"); - return -1; - } - if (linePitches != NULL && linePitches[0] <= 0) { - ErrorF("xf86ValidateModes: called with invalid linePitches\n"); - return -1; - } - if (pitchInc <= 0) { - ErrorF("xf86ValidateModes: called with invalid pitchInc\n"); - return -1; - } - if ((virtualX > 0) != (virtualY > 0)) { - ErrorF("xf86ValidateModes: called with invalid virtual resolution\n"); - return -1; - } - - /* - * If requested by the driver, allow missing hsync and/or vrefresh ranges - * in the monitor section. - */ - if (strategy & LOOKUP_OPTIONAL_TOLERANCES) { - strategy &= ~LOOKUP_OPTIONAL_TOLERANCES; - } else { - const char *type = ""; - - if (scrp->monitor->nHsync <= 0) { - if (numTimings > 0) { - scrp->monitor->nHsync = numTimings; - for (i = 0; i < numTimings; i++) { - scrp->monitor->hsync[i].lo = hsync[i].lo; - scrp->monitor->hsync[i].hi = hsync[i].hi; - } - } else { - scrp->monitor->hsync[0].lo = 31.5; - scrp->monitor->hsync[0].hi = 37.9; - scrp->monitor->nHsync = 1; - } - type = "default "; - } - for (i = 0; i < scrp->monitor->nHsync; i++) { - if (scrp->monitor->hsync[i].lo == scrp->monitor->hsync[i].hi) - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "%s: Using %shsync value of %.2f kHz\n", - scrp->monitor->id, type, - scrp->monitor->hsync[i].lo); - else - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "%s: Using %shsync range of %.2f-%.2f kHz\n", - scrp->monitor->id, type, - scrp->monitor->hsync[i].lo, - scrp->monitor->hsync[i].hi); - } - - type = ""; - if (scrp->monitor->nVrefresh <= 0) { - if (numTimings > 0) { - scrp->monitor->nVrefresh = numTimings; - for (i = 0; i < numTimings; i++) { - scrp->monitor->vrefresh[i].lo = vrefresh[i].lo; - scrp->monitor->vrefresh[i].hi = vrefresh[i].hi; - } - } else { - scrp->monitor->vrefresh[0].lo = 50; - scrp->monitor->vrefresh[0].hi = 70; - scrp->monitor->nVrefresh = 1; - } - type = "default "; - } - for (i = 0; i < scrp->monitor->nVrefresh; i++) { - if (scrp->monitor->vrefresh[i].lo == scrp->monitor->vrefresh[i].hi) - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "%s: Using %svrefresh value of %.2f Hz\n", - scrp->monitor->id, type, - scrp->monitor->vrefresh[i].lo); - else - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "%s: Using %svrefresh range of %.2f-%.2f Hz\n", - scrp->monitor->id, type, - scrp->monitor->vrefresh[i].lo, - scrp->monitor->vrefresh[i].hi); - } - if (scrp->monitor->maxPixClock) { - xf86DrvMsg(scrp->scrnIndex, X_INFO, - "%s: Using maximum pixel clock of %.2f MHz\n", - scrp->monitor->id, - (float)scrp->monitor->maxPixClock / 1000.0); - } - } - - /* - * Store the clockRanges for later use by the VidMode extension. - */ - storeClockRanges = scrp->clockRanges; - while (storeClockRanges != NULL) { - storeClockRanges = storeClockRanges->next; - } - for (cp = clockRanges; cp != NULL; cp = cp->next, - storeClockRanges = storeClockRanges->next) { - storeClockRanges = xnfalloc(sizeof(ClockRange)); - if (scrp->clockRanges == NULL) - scrp->clockRanges = storeClockRanges; - memcpy(storeClockRanges, cp, sizeof(ClockRange)); - } - - /* Determine which pixmap format to pass to scanLineWidth() */ - if (scrp->depth > 4) - BankFormat = &scrp->fbFormat; - else - BankFormat = xf86GetPixFormat(scrp, 1); /* >not< scrp->depth! */ - - if (scrp->xInc <= 0) - scrp->xInc = 8; /* Suitable for VGA and others */ - -#define _VIRTUALX(x) ((((x) + scrp->xInc - 1) / scrp->xInc) * scrp->xInc) - - /* - * Determine maxPitch if it wasn't given explicitly. Note linePitches - * always takes precedence if is non-NULL. In that case the minPitch and - * maxPitch values passed are ignored. - */ - if (linePitches) { - minPitch = maxPitch = linePitches[0]; - for (i = 1; linePitches[i] > 0; i++) { - if (linePitches[i] > maxPitch) - maxPitch = linePitches[i]; - if (linePitches[i] < minPitch) - minPitch = linePitches[i]; - } - } - - /* Initial check of virtual size against other constraints */ - scrp->virtualFrom = X_PROBED; - /* - * Initialise virtX and virtY if the values are fixed. - */ - if (virtualY > 0) { - if (maxHeight > 0 && virtualY > maxHeight) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Virtual height (%d) is too large for the hardware " - "(max %d)\n", virtualY, maxHeight); - return -1; - } - - if (minHeight > 0 && virtualY < minHeight) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Virtual height (%d) is too small for the hardware " - "(min %d)\n", virtualY, minHeight); - return -1; - } - - virtualX = _VIRTUALX(virtualX); - if (linePitches != NULL) { - for (i = 0; linePitches[i] != 0; i++) { - if ((linePitches[i] >= virtualX) && - (linePitches[i] == - scanLineWidth(virtualX, virtualY, linePitches[i], - apertureSize, BankFormat, pitchInc))) { - linePitch = linePitches[i]; - break; - } - } - } else { - linePitch = scanLineWidth(virtualX, virtualY, minPitch, - apertureSize, BankFormat, pitchInc); - } - - if ((linePitch < minPitch) || (linePitch > maxPitch)) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Virtual width (%d) is too large for the hardware " - "(max %d)\n", virtualX, maxPitch); - return -1; - } - - if (!xf86CheckModeSize(scrp, linePitch, virtualX, virtualY)) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Virtual size (%dx%d) (pitch %d) exceeds video memory\n", - virtualX, virtualY, linePitch); - return -1; - } - - virtX = virtualX; - virtY = virtualY; - scrp->virtualFrom = X_CONFIG; - } else if (!modeNames || !*modeNames) { - /* No virtual size given in the config, try to infer */ - /* XXX this doesn't take m{in,ax}Pitch into account; oh well */ - inferred_virtual = inferVirtualSize(scrp, availModes, &virtX, &virtY); - if (inferred_virtual) - linePitch = scanLineWidth(virtX, virtY, minPitch, apertureSize, - BankFormat, pitchInc); - } - - /* Print clock ranges and scaled clocks */ - xf86ShowClockRanges(scrp, clockRanges); - - /* - * If scrp->modePool hasn't been setup yet, set it up now. This allows the - * modes that the driver definitely can't use to be weeded out early. Note - * that a modePool mode's prev field is used to hold a pointer to the - * member of the scrp->modes list for which a match was considered. - */ - if (scrp->modePool == NULL) { - q = NULL; - for (p = availModes; p != NULL; p = p->next) { - status = xf86InitialCheckModeForDriver(scrp, p, clockRanges, - strategy, maxPitch, - virtX, virtY); - - if (status == MODE_OK) { - status = xf86CheckModeForMonitor(p, scrp->monitor); - } - - if (status == MODE_OK) { - new = xnfalloc(sizeof(DisplayModeRec)); - *new = *p; - new->next = NULL; - if (!q) { - scrp->modePool = new; - } else { - q->next = new; - } - new->prev = NULL; - q = new; - q->name = xnfstrdup(p->name); - q->status = MODE_OK; - } else { - printModeRejectMessage(scrp->scrnIndex, p, status); - } - } - - if (scrp->modePool == NULL) { - xf86DrvMsg(scrp->scrnIndex, X_WARNING, "Mode pool is empty\n"); - return 0; - } - } else { - for (p = scrp->modePool; p != NULL; p = p->next) { - p->prev = NULL; - p->status = MODE_OK; - } - } - - /* - * Allocate one entry in scrp->modes for each named mode. - */ - while (scrp->modes) - xf86DeleteMode(&scrp->modes, scrp->modes); - endp = &scrp->modes; - last = NULL; - if (modeNames != NULL) { - for (i = 0; modeNames[i] != NULL; i++) { - userModes = TRUE; - new = xnfcalloc(1, sizeof(DisplayModeRec)); - new->prev = last; - new->type = M_T_USERDEF; - new->name = xnfalloc(strlen(modeNames[i]) + 1); - strcpy(new->name, modeNames[i]); - if (new->prev) - new->prev->next = new; - *endp = last = new; - endp = &new->next; - } - } - - /* Lookup each mode */ -#ifdef RANDR - if (!xf86Info.disableRandR -#ifdef PANORAMIX - && noPanoramiXExtension -#endif - ) - validateAllDefaultModes = TRUE; -#endif - - for (p = scrp->modes; ; p = p->next) { - Bool repeat; - - /* - * If the supplied mode names don't produce a valid mode, scan through - * unconsidered modePool members until one survives validation. This - * is done in decreasing order by mode pixel area. - */ - - if (p == NULL) { - if ((numModes > 0) && !validateAllDefaultModes) - break; - - validateAllDefaultModes = TRUE; - r = NULL; - modeSize = 0; - for (q = scrp->modePool; q != NULL; q = q->next) { - if ((q->prev == NULL) && (q->status == MODE_OK)) { - /* - * Deal with the case where this mode wasn't considered - * because of a builtin mode of the same name. - */ - for (p = scrp->modes; p != NULL; p = p->next) { - if ((p->status != MODE_OK) && - !strcmp(p->name, q->name)) - break; - } - - if (p != NULL) - q->prev = p; - else { - /* - * A quick check to not allow default modes with - * horizontal timing parameters that CRTs may have - * problems with. - */ - if (!scrp->monitor->reducedblanking && - (q->type & M_T_DEFAULT) && - ((double)q->HTotal / (double)q->HDisplay) < 1.15) - continue; - - if (modeSize < (q->HDisplay * q->VDisplay)) { - r = q; - modeSize = q->HDisplay * q->VDisplay; - } - } - } - } - - if (r == NULL) - break; - - p = xnfcalloc(1, sizeof(DisplayModeRec)); - p->prev = last; - p->name = xnfalloc(strlen(r->name) + 1); - if (!userModes) - p->type = M_T_USERDEF; - strcpy(p->name, r->name); - if (p->prev) - p->prev->next = p; - *endp = last = p; - endp = &p->next; - } - - repeat = FALSE; - lookupNext: - if (repeat && ((status = p->status) != MODE_OK)) - printModeRejectMessage(scrp->scrnIndex, p, status); - saveType = p->type; - status = xf86LookupMode(scrp, p, clockRanges, strategy); - if (repeat && status == MODE_NOMODE) - continue; - if (status != MODE_OK) - printModeRejectMessage(scrp->scrnIndex, p, status); - if (status == MODE_ERROR) { - ErrorF("xf86ValidateModes: " - "unexpected result from xf86LookupMode()\n"); - return -1; - } - if (status != MODE_OK) { - if (p->status == MODE_OK) - p->status = status; - continue; - } - p->type |= saveType; - repeat = TRUE; - - newLinePitch = linePitch; - newVirtX = virtX; - newVirtY = virtY; - - /* - * Don't let non-user defined modes increase the virtual size - */ - if (!(p->type & M_T_USERDEF) && (numModes > 0)) { - if (p->HDisplay > virtX) { - p->status = MODE_VIRTUAL_X; - goto lookupNext; - } - if (p->VDisplay > virtY) { - p->status = MODE_VIRTUAL_Y; - goto lookupNext; - } - } - /* - * Adjust virtual width and height if the mode is too large for the - * current values and if they are not fixed. - */ - if (virtualX <= 0 && p->HDisplay > newVirtX) - newVirtX = _VIRTUALX(p->HDisplay); - if (virtualY <= 0 && p->VDisplay > newVirtY) { - if (maxHeight > 0 && p->VDisplay > maxHeight) { - p->status = MODE_VIRTUAL_Y; /* ? */ - goto lookupNext; - } - newVirtY = p->VDisplay; - } - - /* - * If virtual resolution is to be increased, revalidate it. - */ - if ((virtX != newVirtX) || (virtY != newVirtY)) { - if (linePitches != NULL) { - newLinePitch = -1; - for (i = 0; linePitches[i] != 0; i++) { - if ((linePitches[i] >= newVirtX) && - (linePitches[i] >= linePitch) && - (linePitches[i] == - scanLineWidth(newVirtX, newVirtY, linePitches[i], - apertureSize, BankFormat, pitchInc))) { - newLinePitch = linePitches[i]; - break; - } - } - } else { - if (linePitch < minPitch) - linePitch = minPitch; - newLinePitch = scanLineWidth(newVirtX, newVirtY, linePitch, - apertureSize, BankFormat, - pitchInc); - } - if ((newLinePitch < minPitch) || (newLinePitch > maxPitch)) { - p->status = MODE_BAD_WIDTH; - goto lookupNext; - } - - /* - * Check that the pixel area required by the new virtual height - * and line pitch isn't too large. - */ - if (!xf86CheckModeSize(scrp, newLinePitch, newVirtX, newVirtY)) { - p->status = MODE_MEM_VIRT; - goto lookupNext; - } - } - - if (scrp->ValidMode) { - /* - * Give the driver a final say, passing it the proposed virtual - * geometry. - */ - scrp->virtualX = newVirtX; - scrp->virtualY = newVirtY; - scrp->displayWidth = newLinePitch; - p->status = (scrp->ValidMode)(scrp->scrnIndex, p, FALSE, - MODECHECK_FINAL); - - if (p->status != MODE_OK) { - goto lookupNext; - } - } - - /* Mode has passed all the tests */ - virtX = newVirtX; - virtY = newVirtY; - linePitch = newLinePitch; - p->status = MODE_OK; - numModes++; - } - -#undef _VIRTUALX - - /* - * If we estimated the virtual size above, we may have filtered away all - * the modes that maximally match that size; scan again to find out and - * fix up if so. - */ - if (inferred_virtual) { - int vx = 0, vy = 0; - for (p = scrp->modes; p; p = p->next) { - if (p->HDisplay > vx && p->VDisplay > vy) { - vx = p->HDisplay; - vy = p->VDisplay; - } - } - if (vx < virtX || vy < virtY) { - xf86DrvMsg(scrp->scrnIndex, X_WARNING, - "Shrinking virtual size estimate from %dx%d to %dx%d\n", - virtX, virtY, vx, vy); - virtX = vx; - virtY = vy; - linePitch = scanLineWidth(vx, vy, minPitch, apertureSize, - BankFormat, pitchInc); - } - } - - /* Update the ScrnInfoRec parameters */ - - scrp->virtualX = virtX; - scrp->virtualY = virtY; - scrp->displayWidth = linePitch; - - if (numModes <= 0) - return 0; - - /* Make the mode list into a circular list by joining up the ends */ - p = scrp->modes; - while (p->next != NULL) - p = p->next; - /* p is now the last mode on the list */ - p->next = scrp->modes; - scrp->modes->prev = p; - - if (minHeight > 0 && virtY < minHeight) { - xf86DrvMsg(scrp->scrnIndex, X_ERROR, - "Virtual height (%d) is too small for the hardware " - "(min %d)\n", virtY, minHeight); - return -1; - } - - return numModes; -} - -/* - * xf86DeleteMode - * - * This function removes a mode from a list of modes. - * - * There are different types of mode lists: - * - * - singly linked linear lists, ending in NULL - * - doubly linked linear lists, starting and ending in NULL - * - doubly linked circular lists - * - */ - -void -xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode) -{ - /* Catch the easy/insane cases */ - if (modeList == NULL || *modeList == NULL || mode == NULL) - return; - - /* If the mode is at the start of the list, move the start of the list */ - if (*modeList == mode) - *modeList = mode->next; - - /* If mode is the only one on the list, set the list to NULL */ - if ((mode == mode->prev) && (mode == mode->next)) { - *modeList = NULL; - } else { - if ((mode->prev != NULL) && (mode->prev->next == mode)) - mode->prev->next = mode->next; - if ((mode->next != NULL) && (mode->next->prev == mode)) - mode->next->prev = mode->prev; - } - - xfree(mode->name); - xfree(mode); -} - -/* - * xf86PruneDriverModes - * - * Remove modes from the driver's mode list which have been marked as - * invalid. - */ - -void -xf86PruneDriverModes(ScrnInfoPtr scrp) -{ - DisplayModePtr first, p, n; - - p = scrp->modes; - if (p == NULL) - return; - - do { - if (!(first = scrp->modes)) - return; - n = p->next; - if (p->status != MODE_OK) { - xf86DeleteMode(&(scrp->modes), p); - } - p = n; - } while (p != NULL && p != first); - - /* modePool is no longer needed, turf it */ - while (scrp->modePool) { - /* - * A modePool mode's prev field is used to hold a pointer to the - * member of the scrp->modes list for which a match was considered. - * Clear that pointer first, otherwise xf86DeleteMode might get - * confused - */ - scrp->modePool->prev = NULL; - xf86DeleteMode(&scrp->modePool, scrp->modePool); - } -} - - -/* - * xf86SetCrtcForModes - * - * Goes through the screen's mode list, and initialises the Crtc - * parameters for each mode. The initialisation includes adjustments - * for interlaced and double scan modes. - */ -void -xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags) -{ - DisplayModePtr p; - - /* - * Store adjustFlags for use with the VidMode extension. There is an - * implicit assumption here that SetCrtcForModes is called once. - */ - scrp->adjustFlags = adjustFlags; - - p = scrp->modes; - if (p == NULL) - return; - - do { - xf86SetModeCrtc(p, adjustFlags); - DebugF("%sMode %s: %d (%d) %d %d (%d) %d %d (%d) %d %d (%d) %d\n", - (p->type & M_T_DEFAULT) ? "Default " : "", - p->name, p->CrtcHDisplay, p->CrtcHBlankStart, - p->CrtcHSyncStart, p->CrtcHSyncEnd, p->CrtcHBlankEnd, - p->CrtcHTotal, p->CrtcVDisplay, p->CrtcVBlankStart, - p->CrtcVSyncStart, p->CrtcVSyncEnd, p->CrtcVBlankEnd, - p->CrtcVTotal); - p = p->next; - } while (p != NULL && p != scrp->modes); -} - -void -xf86PrintModes(ScrnInfoPtr scrp) -{ - DisplayModePtr p; - float hsync, refresh = 0; - char *desc, *desc2, *prefix, *uprefix; - - if (scrp == NULL) - return; - - xf86DrvMsg(scrp->scrnIndex, scrp->virtualFrom, "Virtual size is %dx%d " - "(pitch %d)\n", scrp->virtualX, scrp->virtualY, - scrp->displayWidth); - - p = scrp->modes; - if (p == NULL) - return; - - do { - desc = desc2 = ""; - hsync = xf86ModeHSync(p); - refresh = xf86ModeVRefresh(p); - if (p->Flags & V_INTERLACE) { - desc = " (I)"; - } - if (p->Flags & V_DBLSCAN) { - desc = " (D)"; - } - if (p->VScan > 1) { - desc2 = " (VScan)"; - } - if (p->type & M_T_BUILTIN) - prefix = "Built-in mode"; - else if (p->type & M_T_DEFAULT) - prefix = "Default mode"; - else if (p->type & M_T_DRIVER) - prefix = "Driver mode"; - else - prefix = "Mode"; - if (p->type & M_T_USERDEF) - uprefix = "*"; - else - uprefix = " "; - if (hsync == 0 || refresh == 0) { - if (p->name) - xf86DrvMsg(scrp->scrnIndex, X_CONFIG, - "%s%s \"%s\"\n", uprefix, prefix, p->name); - else - xf86DrvMsg(scrp->scrnIndex, X_PROBED, - "%s%s %dx%d (unnamed)\n", - uprefix, prefix, p->HDisplay, p->VDisplay); - } else if (p->Clock == p->SynthClock) { - xf86DrvMsg(scrp->scrnIndex, X_CONFIG, - "%s%s \"%s\": %.1f MHz, %.1f kHz, %.1f Hz%s%s\n", - uprefix, prefix, p->name, p->Clock / 1000.0, - hsync, refresh, desc, desc2); - } else { - xf86DrvMsg(scrp->scrnIndex, X_CONFIG, - "%s%s \"%s\": %.1f MHz (scaled from %.1f MHz), " - "%.1f kHz, %.1f Hz%s%s\n", - uprefix, prefix, p->name, p->Clock / 1000.0, - p->SynthClock / 1000.0, hsync, refresh, desc, desc2); - } - if (hsync != 0 && refresh != 0) - xf86PrintModeline(scrp->scrnIndex,p); - p = p->next; - } while (p != NULL && p != scrp->modes); -} +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * LCM() and scanLineWidth() are: + * + * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org + * + * 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 Marc Aurele La France not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Marc Aurele La France makes no representations + * about the suitability of this software for any purpose. It is provided + * "as-is" without express or implied warranty. + * + * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO + * EVENT SHALL MARC AURELE LA FRANCE 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. + * + * Copyright 1990,91,92,93 by Thomas Roell, Germany. + * Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA. + * + * 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 Thomas Roell nor + * SGCS be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Thomas Roell nor SGCS makes no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS 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. + */ + +/* + * Authors: Dirk Hohndel + * David Dawes + * Marc La France + * ... and others + * + * This file includes helper functions for mode related things. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "xf86Modes.h" +#include "os.h" +#include "servermd.h" +#include "globals.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "edid.h" + +static void +printModeRejectMessage(int index, DisplayModePtr p, int status) +{ + char *type; + + if (p->type & M_T_BUILTIN) + type = "built-in "; + else if (p->type & M_T_DEFAULT) + type = "default "; + else if (p->type & M_T_DRIVER) + type = "driver "; + else + type = ""; + + xf86DrvMsg(index, X_INFO, "Not using %smode \"%s\" (%s)\n", type, p->name, + xf86ModeStatusToString(status)); +} + +/* + * xf86GetNearestClock -- + * Find closest clock to given frequency (in kHz). This assumes the + * number of clocks is greater than zero. + */ +int +xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, + int DivFactor, int MulFactor, int *divider) +{ + int nearestClock = 0, nearestDiv = 1; + int minimumGap = abs(freq - scrp->clock[0]); + int i, j, k, gap; + + if (allowDiv2) + k = 2; + else + k = 1; + + /* Must set this here in case the best match is scrp->clock[0] */ + if (divider != NULL) + *divider = 0; + + for (i = 0; i < scrp->numClocks; i++) { + for (j = 1; j <= k; j++) { + gap = abs((freq * j) - ((scrp->clock[i] * DivFactor) / MulFactor)); + if ((gap < minimumGap) || + ((gap == minimumGap) && (j < nearestDiv))) { + minimumGap = gap; + nearestClock = i; + nearestDiv = j; + if (divider != NULL) + *divider = (j - 1) * V_CLKDIV2; + } + } + } + return nearestClock; +} + +/* + * xf86ModeStatusToString + * + * Convert a ModeStatus value to a printable message + */ + +const char * +xf86ModeStatusToString(ModeStatus status) +{ + switch (status) { + case MODE_OK: + return "Mode OK"; + case MODE_HSYNC: + return "hsync out of range"; + case MODE_VSYNC: + return "vrefresh out of range"; + case MODE_H_ILLEGAL: + return "illegal horizontal timings"; + case MODE_V_ILLEGAL: + return "illegal vertical timings"; + case MODE_BAD_WIDTH: + return "width requires unsupported line pitch"; + case MODE_NOMODE: + return "no mode of this name"; + case MODE_NO_INTERLACE: + return "interlace mode not supported"; + case MODE_NO_DBLESCAN: + return "doublescan mode not supported"; + case MODE_NO_VSCAN: + return "multiscan mode not supported"; + case MODE_MEM: + return "insufficient memory for mode"; + case MODE_VIRTUAL_X: + return "width too large for virtual size"; + case MODE_VIRTUAL_Y: + return "height too large for virtual size"; + case MODE_MEM_VIRT: + return "insufficient memory given virtual size"; + case MODE_NOCLOCK: + return "no clock available for mode"; + case MODE_CLOCK_HIGH: + return "mode clock too high"; + case MODE_CLOCK_LOW: + return "mode clock too low"; + case MODE_CLOCK_RANGE: + return "bad mode clock/interlace/doublescan"; + case MODE_BAD_HVALUE: + return "horizontal timing out of range"; + case MODE_BAD_VVALUE: + return "vertical timing out of range"; + case MODE_BAD_VSCAN: + return "VScan value out of range"; + case MODE_HSYNC_NARROW: + return "horizontal sync too narrow"; + case MODE_HSYNC_WIDE: + return "horizontal sync too wide"; + case MODE_HBLANK_NARROW: + return "horizontal blanking too narrow"; + case MODE_HBLANK_WIDE: + return "horizontal blanking too wide"; + case MODE_VSYNC_NARROW: + return "vertical sync too narrow"; + case MODE_VSYNC_WIDE: + return "vertical sync too wide"; + case MODE_VBLANK_NARROW: + return "vertical blanking too narrow"; + case MODE_VBLANK_WIDE: + return "vertical blanking too wide"; + case MODE_PANEL: + return "exceeds panel dimensions"; + case MODE_INTERLACE_WIDTH: + return "width too large for interlaced mode"; + case MODE_ONE_WIDTH: + return "all modes must have the same width"; + case MODE_ONE_HEIGHT: + return "all modes must have the same height"; + case MODE_ONE_SIZE: + return "all modes must have the same resolution"; + case MODE_NO_REDUCED: + return "monitor doesn't support reduced blanking"; + case MODE_BANDWIDTH: + return "mode requires too much memory bandwidth"; + case MODE_BAD: + return "unknown reason"; + case MODE_ERROR: + return "internal error"; + default: + return "unknown"; + } +} + +/* + * xf86ShowClockRanges() -- Print the clock ranges allowed + * and the clock values scaled by ClockMulFactor and ClockDivFactor + */ +void +xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges) +{ + ClockRangePtr cp; + int MulFactor = 1; + int DivFactor = 1; + int i, j; + int scaledClock; + + for (cp = clockRanges; cp != NULL; cp = cp->next) { + DivFactor = max(1, cp->ClockDivFactor); + MulFactor = max(1, cp->ClockMulFactor); + if (scrp->progClock) { + if (cp->minClock) { + if (cp->maxClock) { + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Clock range: %6.2f to %6.2f MHz\n", + (double)cp->minClock / 1000.0, + (double)cp->maxClock / 1000.0); + } else { + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Minimum clock: %6.2f MHz\n", + (double)cp->minClock / 1000.0); + } + } else { + if (cp->maxClock) { + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Maximum clock: %6.2f MHz\n", + (double)cp->maxClock / 1000.0); + } + } + } else if (DivFactor > 1 || MulFactor > 1) { + j = 0; + for (i = 0; i < scrp->numClocks; i++) { + scaledClock = (scrp->clock[i] * DivFactor) / MulFactor; + if (scaledClock >= cp->minClock && scaledClock <= cp->maxClock) { + if ((j % 8) == 0) { + if (j > 0) + xf86ErrorF("\n"); + xf86DrvMsg(scrp->scrnIndex, X_INFO, "scaled clocks:"); + } + xf86ErrorF(" %6.2f", (double)scaledClock / 1000.0); + j++; + } + } + xf86ErrorF("\n"); + } + } +} + +static Bool +modeInClockRange(ClockRangePtr cp, DisplayModePtr p) +{ + return ((p->Clock >= cp->minClock) && + (p->Clock <= cp->maxClock) && + (cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) && + (cp->doubleScanAllowed || + ((p->VScan <= 1) && !(p->Flags & V_DBLSCAN)))); +} + +/* + * xf86FindClockRangeForMode() [... like the name says ...] + */ +static ClockRangePtr +xf86FindClockRangeForMode(ClockRangePtr clockRanges, DisplayModePtr p) +{ + ClockRangePtr cp; + + for (cp = clockRanges; ; cp = cp->next) + if (!cp || modeInClockRange(cp, p)) + return cp; +} + + +/* + * xf86HandleBuiltinMode() - handles built-in modes + */ +static ModeStatus +xf86HandleBuiltinMode(ScrnInfoPtr scrp, + DisplayModePtr p, + DisplayModePtr modep, + ClockRangePtr clockRanges, + Bool allowDiv2) +{ + ClockRangePtr cp; + int extraFlags = 0; + int MulFactor = 1; + int DivFactor = 1; + int clockIndex; + + /* Reject previously rejected modes */ + if (p->status != MODE_OK) + return p->status; + + /* Reject previously considered modes */ + if (p->prev) + return MODE_NOMODE; + + if ((p->type & M_T_CLOCK_C) == M_T_CLOCK_C) { + /* Check clock is in range */ + cp = xf86FindClockRangeForMode(clockRanges, p); + if (cp == NULL){ + modep->type = p->type; + p->status = MODE_CLOCK_RANGE; + return MODE_CLOCK_RANGE; + } + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + if (!scrp->progClock) { + clockIndex = xf86GetNearestClock(scrp, p->Clock, allowDiv2, + cp->ClockDivFactor, + cp->ClockMulFactor, &extraFlags); + modep->Clock = (scrp->clock[clockIndex] * DivFactor) + / MulFactor; + modep->ClockIndex = clockIndex; + modep->SynthClock = scrp->clock[clockIndex]; + if (extraFlags & V_CLKDIV2) { + modep->Clock /= 2; + modep->SynthClock /= 2; + } + } else { + modep->Clock = p->Clock; + modep->ClockIndex = -1; + modep->SynthClock = (modep->Clock * MulFactor) + / DivFactor; + } + modep->PrivFlags = cp->PrivFlags; + } else { + if(!scrp->progClock) { + modep->Clock = p->Clock; + modep->ClockIndex = p->ClockIndex; + modep->SynthClock = p->SynthClock; + } else { + modep->Clock = p->Clock; + modep->ClockIndex = -1; + modep->SynthClock = p->SynthClock; + } + modep->PrivFlags = p->PrivFlags; + } + modep->type = p->type; + modep->HDisplay = p->HDisplay; + modep->HSyncStart = p->HSyncStart; + modep->HSyncEnd = p->HSyncEnd; + modep->HTotal = p->HTotal; + modep->HSkew = p->HSkew; + modep->VDisplay = p->VDisplay; + modep->VSyncStart = p->VSyncStart; + modep->VSyncEnd = p->VSyncEnd; + modep->VTotal = p->VTotal; + modep->VScan = p->VScan; + modep->Flags = p->Flags | extraFlags; + modep->CrtcHDisplay = p->CrtcHDisplay; + modep->CrtcHBlankStart = p->CrtcHBlankStart; + modep->CrtcHSyncStart = p->CrtcHSyncStart; + modep->CrtcHSyncEnd = p->CrtcHSyncEnd; + modep->CrtcHBlankEnd = p->CrtcHBlankEnd; + modep->CrtcHTotal = p->CrtcHTotal; + modep->CrtcHSkew = p->CrtcHSkew; + modep->CrtcVDisplay = p->CrtcVDisplay; + modep->CrtcVBlankStart = p->CrtcVBlankStart; + modep->CrtcVSyncStart = p->CrtcVSyncStart; + modep->CrtcVSyncEnd = p->CrtcVSyncEnd; + modep->CrtcVBlankEnd = p->CrtcVBlankEnd; + modep->CrtcVTotal = p->CrtcVTotal; + modep->CrtcHAdjusted = p->CrtcHAdjusted; + modep->CrtcVAdjusted = p->CrtcVAdjusted; + modep->HSync = p->HSync; + modep->VRefresh = p->VRefresh; + modep->Private = p->Private; + modep->PrivSize = p->PrivSize; + + p->prev = modep; + + return MODE_OK; +} + +/* + * xf86LookupMode + * + * This function returns a mode from the given list which matches the + * given name. When multiple modes with the same name are available, + * the method of picking the matching mode is determined by the + * strategy selected. + * + * This function takes the following parameters: + * scrp ScrnInfoPtr + * modep pointer to the returned mode, which must have the name + * field filled in. + * clockRanges a list of clock ranges. This is optional when all the + * modes are built-in modes. + * strategy how to decide which mode to use from multiple modes with + * the same name + * + * In addition, the following fields from the ScrnInfoRec are used: + * modePool the list of monitor modes compatible with the driver + * clocks a list of discrete clocks + * numClocks number of discrete clocks + * progClock clock is programmable + * + * If a mode was found, its values are filled in to the area pointed to + * by modep, If a mode was not found the return value indicates the + * reason. + */ + +ModeStatus +xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, + ClockRangePtr clockRanges, LookupModeFlags strategy) +{ + DisplayModePtr p, bestMode = NULL; + ClockRangePtr cp; + int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1; + double refresh, bestRefresh = 0.0; + Bool found = FALSE; + int extraFlags = 0; + int clockIndex = -1; + int MulFactor = 1; + int DivFactor = 1; + int ModePrivFlags = 0; + ModeStatus status = MODE_NOMODE; + Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0; + int n; + const int types[] = { + M_T_BUILTIN | M_T_PREFERRED, + M_T_BUILTIN, + M_T_USERDEF | M_T_PREFERRED, + M_T_USERDEF, + M_T_DRIVER | M_T_PREFERRED, + M_T_DRIVER, + 0 + }; + const int ntypes = sizeof(types) / sizeof(int); + + strategy &= ~(LOOKUP_CLKDIV2 | LOOKUP_OPTIONAL_TOLERANCES); + + /* Some sanity checking */ + if (scrp == NULL || scrp->modePool == NULL || + (!scrp->progClock && scrp->numClocks == 0)) { + ErrorF("xf86LookupMode: called with invalid scrnInfoRec\n"); + return MODE_ERROR; + } + if (modep == NULL || modep->name == NULL) { + ErrorF("xf86LookupMode: called with invalid modep\n"); + return MODE_ERROR; + } + for (cp = clockRanges; cp != NULL; cp = cp->next) { + /* DivFactor and MulFactor must be > 0 */ + cp->ClockDivFactor = max(1, cp->ClockDivFactor); + cp->ClockMulFactor = max(1, cp->ClockMulFactor); + } + + /* Scan the mode pool for matching names */ + for (n = 0; n < ntypes; n++) { + int type = types[n]; + for (p = scrp->modePool; p != NULL; p = p->next) { + + /* scan through the modes in the sort order above */ + if ((p->type & type) != type) + continue; + + if (strcmp(p->name, modep->name) == 0) { + + /* Skip over previously rejected modes */ + if (p->status != MODE_OK) { + if (!found) + status = p->status; + continue; + } + + /* Skip over previously considered modes */ + if (p->prev) + continue; + + if (p->type & M_T_BUILTIN) { + return xf86HandleBuiltinMode(scrp, p,modep, clockRanges, + allowDiv2); + } + + /* Check clock is in range */ + cp = xf86FindClockRangeForMode(clockRanges, p); + if (cp == NULL) { + /* + * XXX Could do more here to provide a more detailed + * reason for not finding a mode. + */ + p->status = MODE_CLOCK_RANGE; + if (!found) + status = MODE_CLOCK_RANGE; + continue; + } + + /* + * If programmable clock and strategy is not + * LOOKUP_BEST_REFRESH, the required mode has been found, + * otherwise record the refresh and continue looking. + */ + if (scrp->progClock) { + found = TRUE; + if (strategy != LOOKUP_BEST_REFRESH) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + break; + } + refresh = xf86ModeVRefresh(p); + if (p->Flags & V_INTERLACE) + refresh /= INTERLACE_REFRESH_WEIGHT; + if (refresh > bestRefresh) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + bestRefresh = refresh; + } + continue; + } + + /* + * Clock is in range, so if it is not a programmable clock, find + * a matching clock. + */ + + i = xf86GetNearestClock(scrp, p->Clock, allowDiv2, + cp->ClockDivFactor, cp->ClockMulFactor, &k); + /* + * If the clock is too far from the requested clock, this + * mode is no good. + */ + if (k & V_CLKDIV2) + gap = abs((p->Clock * 2) - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + else + gap = abs(p->Clock - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + if (gap > minimumGap) { + p->status = MODE_NOCLOCK; + if (!found) + status = MODE_NOCLOCK; + continue; + } + found = TRUE; + + if (strategy == LOOKUP_BEST_REFRESH) { + refresh = xf86ModeVRefresh(p); + if (p->Flags & V_INTERLACE) + refresh /= INTERLACE_REFRESH_WEIGHT; + if (refresh > bestRefresh) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + bestRefresh = refresh; + } + continue; + } + if (strategy == LOOKUP_CLOSEST_CLOCK) { + if (gap < minimumGap) { + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + minimumGap = gap; + } + continue; + } + /* + * If strategy is neither LOOKUP_BEST_REFRESH or + * LOOKUP_CLOSEST_CLOCK the required mode has been found. + */ + bestMode = p; + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + break; + } + } + if (found) break; + } + if (!found || bestMode == NULL) + return status; + + /* Fill in the mode parameters */ + if (scrp->progClock) { + modep->Clock = bestMode->Clock; + modep->ClockIndex = -1; + modep->SynthClock = (modep->Clock * MulFactor) / DivFactor; + } else { + modep->Clock = (scrp->clock[clockIndex] * DivFactor) / + MulFactor; + modep->ClockIndex = clockIndex; + modep->SynthClock = scrp->clock[clockIndex]; + if (extraFlags & V_CLKDIV2) { + modep->Clock /= 2; + modep->SynthClock /= 2; + } + } + modep->type = bestMode->type; + modep->PrivFlags = ModePrivFlags; + modep->HDisplay = bestMode->HDisplay; + modep->HSyncStart = bestMode->HSyncStart; + modep->HSyncEnd = bestMode->HSyncEnd; + modep->HTotal = bestMode->HTotal; + modep->HSkew = bestMode->HSkew; + modep->VDisplay = bestMode->VDisplay; + modep->VSyncStart = bestMode->VSyncStart; + modep->VSyncEnd = bestMode->VSyncEnd; + modep->VTotal = bestMode->VTotal; + modep->VScan = bestMode->VScan; + modep->Flags = bestMode->Flags | extraFlags; + modep->CrtcHDisplay = bestMode->CrtcHDisplay; + modep->CrtcHBlankStart = bestMode->CrtcHBlankStart; + modep->CrtcHSyncStart = bestMode->CrtcHSyncStart; + modep->CrtcHSyncEnd = bestMode->CrtcHSyncEnd; + modep->CrtcHBlankEnd = bestMode->CrtcHBlankEnd; + modep->CrtcHTotal = bestMode->CrtcHTotal; + modep->CrtcHSkew = bestMode->CrtcHSkew; + modep->CrtcVDisplay = bestMode->CrtcVDisplay; + modep->CrtcVBlankStart = bestMode->CrtcVBlankStart; + modep->CrtcVSyncStart = bestMode->CrtcVSyncStart; + modep->CrtcVSyncEnd = bestMode->CrtcVSyncEnd; + modep->CrtcVBlankEnd = bestMode->CrtcVBlankEnd; + modep->CrtcVTotal = bestMode->CrtcVTotal; + modep->CrtcHAdjusted = bestMode->CrtcHAdjusted; + modep->CrtcVAdjusted = bestMode->CrtcVAdjusted; + modep->HSync = bestMode->HSync; + modep->VRefresh = bestMode->VRefresh; + modep->Private = bestMode->Private; + modep->PrivSize = bestMode->PrivSize; + + bestMode->prev = modep; + + return MODE_OK; +} + +/* + * xf86CheckModeForMonitor + * + * This function takes a mode and monitor description, and determines + * if the mode is valid for the monitor. + */ +ModeStatus +xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor) +{ + int i; + + /* Sanity checks */ + if (mode == NULL || monitor == NULL) { + ErrorF("xf86CheckModeForMonitor: called with invalid parameters\n"); + return MODE_ERROR; + } + + DebugF("xf86CheckModeForMonitor(%p %s, %p %s)\n", + mode, mode->name, monitor, monitor->id); + + /* Some basic mode validity checks */ + if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart || + mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal) + return MODE_H_ILLEGAL; + + if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart || + mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal) + return MODE_V_ILLEGAL; + + if (monitor->nHsync > 0) { + /* Check hsync against the allowed ranges */ + float hsync = xf86ModeHSync(mode); + for (i = 0; i < monitor->nHsync; i++) + if ((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) && + (hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE))) + break; + + /* Now see whether we ran out of sync ranges without finding a match */ + if (i == monitor->nHsync) + return MODE_HSYNC; + } + + if (monitor->nVrefresh > 0) { + /* Check vrefresh against the allowed ranges */ + float vrefrsh = xf86ModeVRefresh(mode); + for (i = 0; i < monitor->nVrefresh; i++) + if ((vrefrsh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) && + (vrefrsh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE))) + break; + + /* Now see whether we ran out of refresh ranges without finding a match */ + if (i == monitor->nVrefresh) + return MODE_VSYNC; + } + + /* Force interlaced modes to have an odd VTotal */ + if (mode->Flags & V_INTERLACE) + mode->CrtcVTotal = mode->VTotal |= 1; + + /* + * This code stops cvt -r modes, and only cvt -r modes, from hitting 15y+ + * old CRTs which might, when there is a lot of solar flare activity and + * when the celestial bodies are unfavourably aligned, implode trying to + * sync to it. It's called "Protecting the user from doing anything stupid". + * -- libv + */ + + if (xf86ModeIsReduced(mode)) { + if (!monitor->reducedblanking && !(mode->type & M_T_DRIVER)) + return MODE_NO_REDUCED; + } + + if ((monitor->maxPixClock) && (mode->Clock > monitor->maxPixClock)) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +/* + * xf86CheckModeSize + * + * An internal routine to check if a mode fits in video memory. This tries to + * avoid overflows that would otherwise occur when video memory size is greater + * than 256MB. + */ +static Bool +xf86CheckModeSize(ScrnInfoPtr scrp, int w, int x, int y) +{ + int bpp = scrp->fbFormat.bitsPerPixel, + pad = scrp->fbFormat.scanlinePad; + int lineWidth, lastWidth; + + if (scrp->depth == 4) + pad *= 4; /* 4 planes */ + + /* Sanity check */ + if ((w < 0) || (x < 0) || (y <= 0)) + return FALSE; + + lineWidth = (((w * bpp) + pad - 1) / pad) * pad; + lastWidth = x * bpp; + + /* + * At this point, we need to compare + * + * (lineWidth * (y - 1)) + lastWidth + * + * against + * + * scrp->videoRam * (1024 * 8) + * + * These are bit quantities. To avoid overflows, do the comparison in + * terms of BITMAP_SCANLINE_PAD units. This assumes BITMAP_SCANLINE_PAD + * is a power of 2. We currently use 32, which limits us to a video + * memory size of 8GB. + */ + + lineWidth = (lineWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD; + lastWidth = (lastWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD; + + if ((lineWidth * (y - 1) + lastWidth) > + (scrp->videoRam * ((1024 * 8) / BITMAP_SCANLINE_PAD))) + return FALSE; + + return TRUE; +} + +/* + * xf86InitialCheckModeForDriver + * + * This function checks if a mode satisfies a driver's initial requirements: + * - mode size fits within the available pixel area (memory) + * - width lies within the range of supported line pitches + * - mode size fits within virtual size (if fixed) + * - horizontal timings are in range + * + * This function takes the following parameters: + * scrp ScrnInfoPtr + * mode mode to check + * maxPitch (optional) maximum line pitch + * virtualX (optional) virtual width requested + * virtualY (optional) virtual height requested + * + * In addition, the following fields from the ScrnInfoRec are used: + * monitor pointer to structure for monitor section + * fbFormat pixel format for the framebuffer + * videoRam video memory size (in kB) + * maxHValue maximum horizontal timing value + * maxVValue maximum vertical timing value + */ + +ModeStatus +xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, + ClockRangePtr clockRanges, + LookupModeFlags strategy, + int maxPitch, int virtualX, int virtualY) +{ + ClockRangePtr cp; + ModeStatus status; + Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0; + int i, needDiv2; + + /* Sanity checks */ + if (!scrp || !mode || !clockRanges) { + ErrorF("xf86InitialCheckModeForDriver: " + "called with invalid parameters\n"); + return MODE_ERROR; + } + + DebugF("xf86InitialCheckModeForDriver(%p, %p %s, %p, 0x%x, %d, %d, %d)\n", + scrp, mode, mode->name , clockRanges, strategy, maxPitch, virtualX, virtualY); + + /* Some basic mode validity checks */ + if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart || + mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal) + return MODE_H_ILLEGAL; + + if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart || + mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal) + return MODE_V_ILLEGAL; + + if (!xf86CheckModeSize(scrp, mode->HDisplay, mode->HDisplay, + mode->VDisplay)) + return MODE_MEM; + + if (maxPitch > 0 && mode->HDisplay > maxPitch) + return MODE_BAD_WIDTH; + + if (virtualX > 0 && mode->HDisplay > virtualX) + return MODE_VIRTUAL_X; + + if (virtualY > 0 && mode->VDisplay > virtualY) + return MODE_VIRTUAL_Y; + + if (scrp->maxHValue > 0 && mode->HTotal > scrp->maxHValue) + return MODE_BAD_HVALUE; + + if (scrp->maxVValue > 0 && mode->VTotal > scrp->maxVValue) + return MODE_BAD_VVALUE; + + /* + * The use of the DisplayModeRec's Crtc* and SynthClock elements below is + * provisional, in that they are later reused by the driver at mode-set + * time. Here, they are temporarily enlisted to contain the mode timings + * as seen by the CRT or panel (rather than the CRTC). The driver's + * ValidMode() is allowed to modify these so it can deal with such things + * as mode stretching and/or centering. The driver should >NOT< modify the + * user-supplied values as these are reported back when mode validation is + * said and done. + */ + /* + * NOTE: We (ab)use the mode->Crtc* values here to store timing + * information for the calculation of Hsync and Vrefresh. Before + * these values are calculated the driver is given the opportunity + * to either set these HSync and VRefresh itself or modify the timing + * values. + * The difference to the final calculation is small but imortand: + * here we pass the flag INTERLACE_HALVE_V regardless if the driver + * sets it or not. This way our calculation of VRefresh has the same + * effect as if we do if (flags & V_INTERLACE) refresh *= 2.0 + * This dual use of the mode->Crtc* values will certainly create + * confusion and is bad software design. However since it's part of + * the driver API it's hard to change. + */ + + if (scrp->ValidMode) { + + xf86SetModeCrtc(mode, INTERLACE_HALVE_V); + + cp = xf86FindClockRangeForMode(clockRanges, mode); + if (!cp) + return MODE_CLOCK_RANGE; + + if (cp->ClockMulFactor < 1) + cp->ClockMulFactor = 1; + if (cp->ClockDivFactor < 1) + cp->ClockDivFactor = 1; + + /* + * XXX The effect of clock dividers and multipliers on the monitor's + * pixel clock needs to be verified. + */ + if (scrp->progClock) { + mode->SynthClock = mode->Clock; + } else { + i = xf86GetNearestClock(scrp, mode->Clock, allowDiv2, + cp->ClockDivFactor, cp->ClockMulFactor, + &needDiv2); + mode->SynthClock = (scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor; + if (needDiv2 & V_CLKDIV2) + mode->SynthClock /= 2; + } + + status = (*scrp->ValidMode)(scrp->scrnIndex, mode, FALSE, + MODECHECK_INITIAL); + if (status != MODE_OK) + return status; + + if (mode->HSync <= 0.0) + mode->HSync = (float)mode->SynthClock / (float)mode->CrtcHTotal; + if (mode->VRefresh <= 0.0) + mode->VRefresh = (mode->SynthClock * 1000.0) + / (mode->CrtcHTotal * mode->CrtcVTotal); + } + + mode->HSync = xf86ModeHSync(mode); + mode->VRefresh = xf86ModeVRefresh(mode); + + /* Assume it is OK */ + return MODE_OK; +} + +/* + * xf86CheckModeForDriver + * + * This function is for checking modes while the server is running (for + * use mainly by the VidMode extension). + * + * This function checks if a mode satisfies a driver's requirements: + * - width lies within the line pitch + * - mode size fits within virtual size + * - horizontal/vertical timings are in range + * + * This function takes the following parameters: + * scrp ScrnInfoPtr + * mode mode to check + * flags not (currently) used + * + * In addition, the following fields from the ScrnInfoRec are used: + * maxHValue maximum horizontal timing value + * maxVValue maximum vertical timing value + * virtualX virtual width + * virtualY virtual height + * clockRanges allowable clock ranges + */ + +ModeStatus +xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags) +{ + ClockRangePtr cp; + int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1; + int extraFlags = 0; + int clockIndex = -1; + int MulFactor = 1; + int DivFactor = 1; + int ModePrivFlags = 0; + ModeStatus status = MODE_NOMODE; + + /* Some sanity checking */ + if (scrp == NULL || (!scrp->progClock && scrp->numClocks == 0)) { + ErrorF("xf86CheckModeForDriver: called with invalid scrnInfoRec\n"); + return MODE_ERROR; + } + if (mode == NULL) { + ErrorF("xf86CheckModeForDriver: called with invalid modep\n"); + return MODE_ERROR; + } + + /* Check the mode size */ + if (mode->HDisplay > scrp->virtualX) + return MODE_VIRTUAL_X; + + if (mode->VDisplay > scrp->virtualY) + return MODE_VIRTUAL_Y; + + if (scrp->maxHValue > 0 && mode->HTotal > scrp->maxHValue) + return MODE_BAD_HVALUE; + + if (scrp->maxVValue > 0 && mode->VTotal > scrp->maxVValue) + return MODE_BAD_VVALUE; + + for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { + /* DivFactor and MulFactor must be > 0 */ + cp->ClockDivFactor = max(1, cp->ClockDivFactor); + cp->ClockMulFactor = max(1, cp->ClockMulFactor); + } + + if (scrp->progClock) { + /* Check clock is in range */ + for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { + if (modeInClockRange(cp, mode)) + break; + } + if (cp == NULL) { + return MODE_CLOCK_RANGE; + } + /* + * If programmable clock the required mode has been found + */ + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + } else { + status = MODE_CLOCK_RANGE; + /* Check clock is in range */ + for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { + if (modeInClockRange(cp, mode)) { + /* + * Clock is in range, so if it is not a programmable clock, + * find a matching clock. + */ + + i = xf86GetNearestClock(scrp, mode->Clock, 0, + cp->ClockDivFactor, cp->ClockMulFactor, &k); + /* + * If the clock is too far from the requested clock, this + * mode is no good. + */ + if (k & V_CLKDIV2) + gap = abs((mode->Clock * 2) - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + else + gap = abs(mode->Clock - + ((scrp->clock[i] * cp->ClockDivFactor) / + cp->ClockMulFactor)); + if (gap > minimumGap) { + status = MODE_NOCLOCK; + continue; + } + + DivFactor = cp->ClockDivFactor; + MulFactor = cp->ClockMulFactor; + ModePrivFlags = cp->PrivFlags; + extraFlags = k; + clockIndex = i; + break; + } + } + if (cp == NULL) + return status; + } + + /* Fill in the mode parameters */ + if (scrp->progClock) { + mode->ClockIndex = -1; + mode->SynthClock = (mode->Clock * MulFactor) / DivFactor; + } else { + mode->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor; + mode->ClockIndex = clockIndex; + mode->SynthClock = scrp->clock[clockIndex]; + if (extraFlags & V_CLKDIV2) { + mode->Clock /= 2; + mode->SynthClock /= 2; + } + } + mode->PrivFlags = ModePrivFlags; + + return MODE_OK; +} + +static int +inferVirtualSize(ScrnInfoPtr scrp, DisplayModePtr modes, int *vx, int *vy) +{ + float aspect = 0.0; + MonPtr mon = scrp->monitor; + xf86MonPtr DDC; + int x = 0, y = 0; + DisplayModePtr mode; + + if (!mon) return 0; + DDC = mon->DDC; + + if (DDC && DDC->ver.revision >= 4) { + /* For 1.4, we might actually get native pixel format. How novel. */ + if (PREFERRED_TIMING_MODE(DDC->features.msc)) { + for (mode = modes; mode; mode = mode->next) { + if (mode->type & (M_T_DRIVER | M_T_PREFERRED)) { + x = mode->HDisplay; + y = mode->VDisplay; + goto found; + } + } + } + /* + * Even if we don't, we might get aspect ratio from extra CVT info + * or from the monitor size fields. TODO. + */ + } + + /* + * Technically this triggers if either is zero. That wasn't legal + * before EDID 1.4, but right now we'll get that wrong. TODO. + */ + if (!aspect) { + if (!mon->widthmm || !mon->heightmm) + aspect = 4.0/3.0; + else + aspect = (float)mon->widthmm / (float)mon->heightmm; + } + + /* find the largest M_T_DRIVER mode with that aspect ratio */ + for (mode = modes; mode; mode = mode->next) { + float mode_aspect, metaspect; + if (!(mode->type & (M_T_DRIVER|M_T_USERDEF))) + continue; + mode_aspect = (float)mode->HDisplay / (float)mode->VDisplay; + metaspect = aspect / mode_aspect; + /* 5% slop or so, since we only get size in centimeters */ + if (fabs(1.0 - metaspect) < 0.05) { + if ((mode->HDisplay > x) && (mode->VDisplay > y)) { + x = mode->HDisplay; + y = mode->VDisplay; + } + } + } + + if (!x || !y) { + xf86DrvMsg(scrp->scrnIndex, X_WARNING, + "Unable to estimate virtual size\n"); + return 0; + } + +found: + *vx = x; + *vy = y; + + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "Estimated virtual size for aspect ratio %.4f is %dx%d\n", + aspect, *vx, *vy); + + return 1; +} + +/* Least common multiple */ +static unsigned int +LCM(unsigned int x, unsigned int y) +{ + unsigned int m = x, n = y, o; + + while ((o = m % n)) + { + m = n; + n = o; + } + + return (x / n) * y; +} + +/* + * Given various screen attributes, determine the minimum scanline width such + * that each scanline is server and DDX padded and any pixels with imbedded + * bank boundaries are off-screen. This function returns -1 if such a width + * cannot exist. + */ +static int +scanLineWidth( + unsigned int xsize, /* pixels */ + unsigned int ysize, /* pixels */ + unsigned int width, /* pixels */ + unsigned long BankSize, /* char's */ + PixmapFormatRec *pBankFormat, + unsigned int nWidthUnit /* bits */ +) +{ + unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit; + unsigned long minBitsPerScanline, maxBitsPerScanline; + + /* Sanity checks */ + + if (!nWidthUnit || !pBankFormat) + return -1; + + nBitsPerBank = BankSize * 8; + if (nBitsPerBank % pBankFormat->scanlinePad) + return -1; + + if (xsize > width) + width = xsize; + nBitsPerScanlinePadUnit = LCM(pBankFormat->scanlinePad, nWidthUnit); + nBitsPerScanline = + (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) / + nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit; + width = nBitsPerScanline / pBankFormat->bitsPerPixel; + + if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel)) + return (int)width; + + /* + * Scanlines will be server-pad aligned at this point. They will also be + * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded + * bank boundaries are off-screen. + * + * It seems reasonable to limit total frame buffer size to 1/16 of the + * theoretical maximum address space size. On a machine with 32-bit + * addresses (to 8-bit quantities) this turns out to be 256MB. Not only + * does this provide a simple limiting condition for the loops below, but + * it also prevents unsigned long wraparounds. + */ + if (!ysize) + return -1; + + minBitsPerScanline = xsize * pBankFormat->bitsPerPixel; + if (minBitsPerScanline > nBitsPerBank) + return -1; + + if (ysize == 1) + return (int)width; + + maxBitsPerScanline = + (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1); + while (nBitsPerScanline <= maxBitsPerScanline) + { + unsigned long BankBase, BankUnit; + + BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) * + nBitsPerBank; + if (!(BankUnit % nBitsPerScanline)) + return (int)width; + + for (BankBase = BankUnit; ; BankBase += nBitsPerBank) + { + unsigned long x, y; + + y = BankBase / nBitsPerScanline; + if (y >= ysize) + return (int)width; + + x = BankBase % nBitsPerScanline; + if (!(x % pBankFormat->bitsPerPixel)) + continue; + + if (x < minBitsPerScanline) + { + /* + * Skip ahead certain widths by dividing the excess scanline + * amongst the y's. + */ + y *= nBitsPerScanlinePadUnit; + nBitsPerScanline += + ((x + y - 1) / y) * nBitsPerScanlinePadUnit; + width = nBitsPerScanline / pBankFormat->bitsPerPixel; + break; + } + + if (BankBase != BankUnit) + continue; + + if (!(nBitsPerScanline % x)) + return (int)width; + + BankBase = ((nBitsPerScanline - minBitsPerScanline) / + (nBitsPerScanline - x)) * BankUnit; + } + } + + return -1; +} + +/* + * xf86ValidateModes + * + * This function takes a set of mode names, modes and limiting conditions, + * and selects a set of modes and parameters based on those conditions. + * + * This function takes the following parameters: + * scrp ScrnInfoPtr + * availModes the list of modes available for the monitor + * modeNames (optional) list of mode names that the screen is requesting + * clockRanges a list of clock ranges + * linePitches (optional) a list of line pitches + * minPitch (optional) minimum line pitch (in pixels) + * maxPitch (optional) maximum line pitch (in pixels) + * pitchInc (mandatory) pitch increment (in bits) + * minHeight (optional) minimum virtual height (in pixels) + * maxHeight (optional) maximum virtual height (in pixels) + * virtualX (optional) virtual width requested (in pixels) + * virtualY (optional) virtual height requested (in pixels) + * apertureSize size of video aperture (in bytes) + * strategy how to decide which mode to use from multiple modes with + * the same name + * + * In addition, the following fields from the ScrnInfoRec are used: + * clocks a list of discrete clocks + * numClocks number of discrete clocks + * progClock clock is programmable + * monitor pointer to structure for monitor section + * fbFormat format of the framebuffer + * videoRam video memory size + * maxHValue maximum horizontal timing value + * maxVValue maximum vertical timing value + * xInc horizontal timing increment (defaults to 8 pixels) + * + * The function fills in the following ScrnInfoRec fields: + * modePool A subset of the modes available to the monitor which + * are compatible with the driver. + * modes one mode entry for each of the requested modes, with the + * status field filled in to indicate if the mode has been + * accepted or not. + * virtualX the resulting virtual width + * virtualY the resulting virtual height + * displayWidth the resulting line pitch + * + * The function's return value is the number of matching modes found, or -1 + * if an unrecoverable error was encountered. + */ + +int +xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, + char **modeNames, ClockRangePtr clockRanges, + int *linePitches, int minPitch, int maxPitch, int pitchInc, + int minHeight, int maxHeight, int virtualX, int virtualY, + int apertureSize, LookupModeFlags strategy) +{ + DisplayModePtr p, q, r, new, last, *endp; + int i, numModes = 0; + ModeStatus status; + int linePitch = -1, virtX = 0, virtY = 0; + int newLinePitch, newVirtX, newVirtY; + int modeSize; /* in pixels */ + Bool validateAllDefaultModes = FALSE; + Bool userModes = FALSE; + int saveType; + PixmapFormatRec *BankFormat; + ClockRangePtr cp; + ClockRangePtr storeClockRanges; + int numTimings = 0; + range hsync[MAX_HSYNC]; + range vrefresh[MAX_VREFRESH]; + Bool inferred_virtual = FALSE; + + DebugF("xf86ValidateModes(%p, %p, %p, %p,\n\t\t %p, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x)\n", + scrp, availModes, modeNames, clockRanges, + linePitches, minPitch, maxPitch, pitchInc, + minHeight, maxHeight, virtualX, virtualY, + apertureSize, strategy + ); + + /* Some sanity checking */ + if (scrp == NULL || scrp->name == NULL || !scrp->monitor || + (!scrp->progClock && scrp->numClocks == 0)) { + ErrorF("xf86ValidateModes: called with invalid scrnInfoRec\n"); + return -1; + } + if (linePitches != NULL && linePitches[0] <= 0) { + ErrorF("xf86ValidateModes: called with invalid linePitches\n"); + return -1; + } + if (pitchInc <= 0) { + ErrorF("xf86ValidateModes: called with invalid pitchInc\n"); + return -1; + } + if ((virtualX > 0) != (virtualY > 0)) { + ErrorF("xf86ValidateModes: called with invalid virtual resolution\n"); + return -1; + } + + /* + * If requested by the driver, allow missing hsync and/or vrefresh ranges + * in the monitor section. + */ + if (strategy & LOOKUP_OPTIONAL_TOLERANCES) { + strategy &= ~LOOKUP_OPTIONAL_TOLERANCES; + } else { + const char *type = ""; + + if (scrp->monitor->nHsync <= 0) { + if (numTimings > 0) { + scrp->monitor->nHsync = numTimings; + for (i = 0; i < numTimings; i++) { + scrp->monitor->hsync[i].lo = hsync[i].lo; + scrp->monitor->hsync[i].hi = hsync[i].hi; + } + } else { + scrp->monitor->hsync[0].lo = 31.5; + scrp->monitor->hsync[0].hi = 37.9; + scrp->monitor->nHsync = 1; + } + type = "default "; + } + for (i = 0; i < scrp->monitor->nHsync; i++) { + if (scrp->monitor->hsync[i].lo == scrp->monitor->hsync[i].hi) + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %shsync value of %.2f kHz\n", + scrp->monitor->id, type, + scrp->monitor->hsync[i].lo); + else + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %shsync range of %.2f-%.2f kHz\n", + scrp->monitor->id, type, + scrp->monitor->hsync[i].lo, + scrp->monitor->hsync[i].hi); + } + + type = ""; + if (scrp->monitor->nVrefresh <= 0) { + if (numTimings > 0) { + scrp->monitor->nVrefresh = numTimings; + for (i = 0; i < numTimings; i++) { + scrp->monitor->vrefresh[i].lo = vrefresh[i].lo; + scrp->monitor->vrefresh[i].hi = vrefresh[i].hi; + } + } else { + scrp->monitor->vrefresh[0].lo = 50; + scrp->monitor->vrefresh[0].hi = 70; + scrp->monitor->nVrefresh = 1; + } + type = "default "; + } + for (i = 0; i < scrp->monitor->nVrefresh; i++) { + if (scrp->monitor->vrefresh[i].lo == scrp->monitor->vrefresh[i].hi) + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %svrefresh value of %.2f Hz\n", + scrp->monitor->id, type, + scrp->monitor->vrefresh[i].lo); + else + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using %svrefresh range of %.2f-%.2f Hz\n", + scrp->monitor->id, type, + scrp->monitor->vrefresh[i].lo, + scrp->monitor->vrefresh[i].hi); + } + if (scrp->monitor->maxPixClock) { + xf86DrvMsg(scrp->scrnIndex, X_INFO, + "%s: Using maximum pixel clock of %.2f MHz\n", + scrp->monitor->id, + (float)scrp->monitor->maxPixClock / 1000.0); + } + } + + /* + * Store the clockRanges for later use by the VidMode extension. + */ + storeClockRanges = scrp->clockRanges; + while (storeClockRanges != NULL) { + storeClockRanges = storeClockRanges->next; + } + for (cp = clockRanges; cp != NULL; cp = cp->next, + storeClockRanges = storeClockRanges->next) { + storeClockRanges = xnfalloc(sizeof(ClockRange)); + if (scrp->clockRanges == NULL) + scrp->clockRanges = storeClockRanges; + memcpy(storeClockRanges, cp, sizeof(ClockRange)); + } + + /* Determine which pixmap format to pass to scanLineWidth() */ + if (scrp->depth > 4) + BankFormat = &scrp->fbFormat; + else + BankFormat = xf86GetPixFormat(scrp, 1); /* >not< scrp->depth! */ + + if (scrp->xInc <= 0) + scrp->xInc = 8; /* Suitable for VGA and others */ + +#define _VIRTUALX(x) ((((x) + scrp->xInc - 1) / scrp->xInc) * scrp->xInc) + + /* + * Determine maxPitch if it wasn't given explicitly. Note linePitches + * always takes precedence if is non-NULL. In that case the minPitch and + * maxPitch values passed are ignored. + */ + if (linePitches) { + minPitch = maxPitch = linePitches[0]; + for (i = 1; linePitches[i] > 0; i++) { + if (linePitches[i] > maxPitch) + maxPitch = linePitches[i]; + if (linePitches[i] < minPitch) + minPitch = linePitches[i]; + } + } + + /* Initial check of virtual size against other constraints */ + scrp->virtualFrom = X_PROBED; + /* + * Initialise virtX and virtY if the values are fixed. + */ + if (virtualY > 0) { + if (maxHeight > 0 && virtualY > maxHeight) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual height (%d) is too large for the hardware " + "(max %d)\n", virtualY, maxHeight); + return -1; + } + + if (minHeight > 0 && virtualY < minHeight) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual height (%d) is too small for the hardware " + "(min %d)\n", virtualY, minHeight); + return -1; + } + + virtualX = _VIRTUALX(virtualX); + if (linePitches != NULL) { + for (i = 0; linePitches[i] != 0; i++) { + if ((linePitches[i] >= virtualX) && + (linePitches[i] == + scanLineWidth(virtualX, virtualY, linePitches[i], + apertureSize, BankFormat, pitchInc))) { + linePitch = linePitches[i]; + break; + } + } + } else { + linePitch = scanLineWidth(virtualX, virtualY, minPitch, + apertureSize, BankFormat, pitchInc); + } + + if ((linePitch < minPitch) || (linePitch > maxPitch)) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual width (%d) is too large for the hardware " + "(max %d)\n", virtualX, maxPitch); + return -1; + } + + if (!xf86CheckModeSize(scrp, linePitch, virtualX, virtualY)) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual size (%dx%d) (pitch %d) exceeds video memory\n", + virtualX, virtualY, linePitch); + return -1; + } + + virtX = virtualX; + virtY = virtualY; + scrp->virtualFrom = X_CONFIG; + } else if (!modeNames || !*modeNames) { + /* No virtual size given in the config, try to infer */ + /* XXX this doesn't take m{in,ax}Pitch into account; oh well */ + inferred_virtual = inferVirtualSize(scrp, availModes, &virtX, &virtY); + if (inferred_virtual) + linePitch = scanLineWidth(virtX, virtY, minPitch, apertureSize, + BankFormat, pitchInc); + } + + /* Print clock ranges and scaled clocks */ + xf86ShowClockRanges(scrp, clockRanges); + + /* + * If scrp->modePool hasn't been setup yet, set it up now. This allows the + * modes that the driver definitely can't use to be weeded out early. Note + * that a modePool mode's prev field is used to hold a pointer to the + * member of the scrp->modes list for which a match was considered. + */ + if (scrp->modePool == NULL) { + q = NULL; + for (p = availModes; p != NULL; p = p->next) { + status = xf86InitialCheckModeForDriver(scrp, p, clockRanges, + strategy, maxPitch, + virtX, virtY); + + if (status == MODE_OK) { + status = xf86CheckModeForMonitor(p, scrp->monitor); + } + + if (status == MODE_OK) { + new = xnfalloc(sizeof(DisplayModeRec)); + *new = *p; + new->next = NULL; + if (!q) { + scrp->modePool = new; + } else { + q->next = new; + } + new->prev = NULL; + q = new; + q->name = xnfstrdup(p->name); + q->status = MODE_OK; + } else { + printModeRejectMessage(scrp->scrnIndex, p, status); + } + } + + if (scrp->modePool == NULL) { + xf86DrvMsg(scrp->scrnIndex, X_WARNING, "Mode pool is empty\n"); + return 0; + } + } else { + for (p = scrp->modePool; p != NULL; p = p->next) { + p->prev = NULL; + p->status = MODE_OK; + } + } + + /* + * Allocate one entry in scrp->modes for each named mode. + */ + while (scrp->modes) + xf86DeleteMode(&scrp->modes, scrp->modes); + endp = &scrp->modes; + last = NULL; + if (modeNames != NULL) { + for (i = 0; modeNames[i] != NULL; i++) { + userModes = TRUE; + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->prev = last; + new->type = M_T_USERDEF; + new->name = xnfalloc(strlen(modeNames[i]) + 1); + strcpy(new->name, modeNames[i]); + if (new->prev) + new->prev->next = new; + *endp = last = new; + endp = &new->next; + } + } + + /* Lookup each mode */ +#ifdef RANDR + if (!xf86Info.disableRandR +#ifdef PANORAMIX + && noPanoramiXExtension +#endif + ) + validateAllDefaultModes = TRUE; +#endif + + for (p = scrp->modes; ; p = p->next) { + Bool repeat; + + /* + * If the supplied mode names don't produce a valid mode, scan through + * unconsidered modePool members until one survives validation. This + * is done in decreasing order by mode pixel area. + */ + + if (p == NULL) { + if ((numModes > 0) && !validateAllDefaultModes) + break; + + validateAllDefaultModes = TRUE; + r = NULL; + modeSize = 0; + for (q = scrp->modePool; q != NULL; q = q->next) { + if ((q->prev == NULL) && (q->status == MODE_OK)) { + /* + * Deal with the case where this mode wasn't considered + * because of a builtin mode of the same name. + */ + for (p = scrp->modes; p != NULL; p = p->next) { + if ((p->status != MODE_OK) && + !strcmp(p->name, q->name)) + break; + } + + if (p != NULL) + q->prev = p; + else { + /* + * A quick check to not allow default modes with + * horizontal timing parameters that CRTs may have + * problems with. + */ + if (!scrp->monitor->reducedblanking && + (q->type & M_T_DEFAULT) && + ((double)q->HTotal / (double)q->HDisplay) < 1.15) + continue; + + if (modeSize < (q->HDisplay * q->VDisplay)) { + r = q; + modeSize = q->HDisplay * q->VDisplay; + } + } + } + } + + if (r == NULL) + break; + + p = xnfcalloc(1, sizeof(DisplayModeRec)); + p->prev = last; + p->name = xnfalloc(strlen(r->name) + 1); + if (!userModes) + p->type = M_T_USERDEF; + strcpy(p->name, r->name); + if (p->prev) + p->prev->next = p; + *endp = last = p; + endp = &p->next; + } + + repeat = FALSE; + lookupNext: + if (repeat && ((status = p->status) != MODE_OK)) + printModeRejectMessage(scrp->scrnIndex, p, status); + saveType = p->type; + status = xf86LookupMode(scrp, p, clockRanges, strategy); + if (repeat && status == MODE_NOMODE) + continue; + if (status != MODE_OK) + printModeRejectMessage(scrp->scrnIndex, p, status); + if (status == MODE_ERROR) { + ErrorF("xf86ValidateModes: " + "unexpected result from xf86LookupMode()\n"); + return -1; + } + if (status != MODE_OK) { + if (p->status == MODE_OK) + p->status = status; + continue; + } + p->type |= saveType; + repeat = TRUE; + + newLinePitch = linePitch; + newVirtX = virtX; + newVirtY = virtY; + + /* + * Don't let non-user defined modes increase the virtual size + */ + if (!(p->type & M_T_USERDEF) && (numModes > 0)) { + if (p->HDisplay > virtX) { + p->status = MODE_VIRTUAL_X; + goto lookupNext; + } + if (p->VDisplay > virtY) { + p->status = MODE_VIRTUAL_Y; + goto lookupNext; + } + } + /* + * Adjust virtual width and height if the mode is too large for the + * current values and if they are not fixed. + */ + if (virtualX <= 0 && p->HDisplay > newVirtX) + newVirtX = _VIRTUALX(p->HDisplay); + if (virtualY <= 0 && p->VDisplay > newVirtY) { + if (maxHeight > 0 && p->VDisplay > maxHeight) { + p->status = MODE_VIRTUAL_Y; /* ? */ + goto lookupNext; + } + newVirtY = p->VDisplay; + } + + /* + * If virtual resolution is to be increased, revalidate it. + */ + if ((virtX != newVirtX) || (virtY != newVirtY)) { + if (linePitches != NULL) { + newLinePitch = -1; + for (i = 0; linePitches[i] != 0; i++) { + if ((linePitches[i] >= newVirtX) && + (linePitches[i] >= linePitch) && + (linePitches[i] == + scanLineWidth(newVirtX, newVirtY, linePitches[i], + apertureSize, BankFormat, pitchInc))) { + newLinePitch = linePitches[i]; + break; + } + } + } else { + if (linePitch < minPitch) + linePitch = minPitch; + newLinePitch = scanLineWidth(newVirtX, newVirtY, linePitch, + apertureSize, BankFormat, + pitchInc); + } + if ((newLinePitch < minPitch) || (newLinePitch > maxPitch)) { + p->status = MODE_BAD_WIDTH; + goto lookupNext; + } + + /* + * Check that the pixel area required by the new virtual height + * and line pitch isn't too large. + */ + if (!xf86CheckModeSize(scrp, newLinePitch, newVirtX, newVirtY)) { + p->status = MODE_MEM_VIRT; + goto lookupNext; + } + } + + if (scrp->ValidMode) { + /* + * Give the driver a final say, passing it the proposed virtual + * geometry. + */ + scrp->virtualX = newVirtX; + scrp->virtualY = newVirtY; + scrp->displayWidth = newLinePitch; + p->status = (scrp->ValidMode)(scrp->scrnIndex, p, FALSE, + MODECHECK_FINAL); + + if (p->status != MODE_OK) { + goto lookupNext; + } + } + + /* Mode has passed all the tests */ + virtX = newVirtX; + virtY = newVirtY; + linePitch = newLinePitch; + p->status = MODE_OK; + numModes++; + } + +#undef _VIRTUALX + + /* + * If we estimated the virtual size above, we may have filtered away all + * the modes that maximally match that size; scan again to find out and + * fix up if so. + */ + if (inferred_virtual) { + int vx = 0, vy = 0; + for (p = scrp->modes; p; p = p->next) { + if (p->HDisplay > vx && p->VDisplay > vy) { + vx = p->HDisplay; + vy = p->VDisplay; + } + } + if (vx < virtX || vy < virtY) { + xf86DrvMsg(scrp->scrnIndex, X_WARNING, + "Shrinking virtual size estimate from %dx%d to %dx%d\n", + virtX, virtY, vx, vy); + virtX = vx; + virtY = vy; + linePitch = scanLineWidth(vx, vy, minPitch, apertureSize, + BankFormat, pitchInc); + } + } + + /* Update the ScrnInfoRec parameters */ + + scrp->virtualX = virtX; + scrp->virtualY = virtY; + scrp->displayWidth = linePitch; + + if (numModes <= 0) + return 0; + + /* Make the mode list into a circular list by joining up the ends */ + p = scrp->modes; + while (p->next != NULL) + p = p->next; + /* p is now the last mode on the list */ + p->next = scrp->modes; + scrp->modes->prev = p; + + if (minHeight > 0 && virtY < minHeight) { + xf86DrvMsg(scrp->scrnIndex, X_ERROR, + "Virtual height (%d) is too small for the hardware " + "(min %d)\n", virtY, minHeight); + return -1; + } + + return numModes; +} + +/* + * xf86DeleteMode + * + * This function removes a mode from a list of modes. + * + * There are different types of mode lists: + * + * - singly linked linear lists, ending in NULL + * - doubly linked linear lists, starting and ending in NULL + * - doubly linked circular lists + * + */ + +void +xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode) +{ + /* Catch the easy/insane cases */ + if (modeList == NULL || *modeList == NULL || mode == NULL) + return; + + /* If the mode is at the start of the list, move the start of the list */ + if (*modeList == mode) + *modeList = mode->next; + + /* If mode is the only one on the list, set the list to NULL */ + if ((mode == mode->prev) && (mode == mode->next)) { + *modeList = NULL; + } else { + if ((mode->prev != NULL) && (mode->prev->next == mode)) + mode->prev->next = mode->next; + if ((mode->next != NULL) && (mode->next->prev == mode)) + mode->next->prev = mode->prev; + } + + free(mode->name); + free(mode); +} + +/* + * xf86PruneDriverModes + * + * Remove modes from the driver's mode list which have been marked as + * invalid. + */ + +void +xf86PruneDriverModes(ScrnInfoPtr scrp) +{ + DisplayModePtr first, p, n; + + p = scrp->modes; + if (p == NULL) + return; + + do { + if (!(first = scrp->modes)) + return; + n = p->next; + if (p->status != MODE_OK) { + xf86DeleteMode(&(scrp->modes), p); + } + p = n; + } while (p != NULL && p != first); + + /* modePool is no longer needed, turf it */ + while (scrp->modePool) { + /* + * A modePool mode's prev field is used to hold a pointer to the + * member of the scrp->modes list for which a match was considered. + * Clear that pointer first, otherwise xf86DeleteMode might get + * confused + */ + scrp->modePool->prev = NULL; + xf86DeleteMode(&scrp->modePool, scrp->modePool); + } +} + + +/* + * xf86SetCrtcForModes + * + * Goes through the screen's mode list, and initialises the Crtc + * parameters for each mode. The initialisation includes adjustments + * for interlaced and double scan modes. + */ +void +xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags) +{ + DisplayModePtr p; + + /* + * Store adjustFlags for use with the VidMode extension. There is an + * implicit assumption here that SetCrtcForModes is called once. + */ + scrp->adjustFlags = adjustFlags; + + p = scrp->modes; + if (p == NULL) + return; + + do { + xf86SetModeCrtc(p, adjustFlags); + DebugF("%sMode %s: %d (%d) %d %d (%d) %d %d (%d) %d %d (%d) %d\n", + (p->type & M_T_DEFAULT) ? "Default " : "", + p->name, p->CrtcHDisplay, p->CrtcHBlankStart, + p->CrtcHSyncStart, p->CrtcHSyncEnd, p->CrtcHBlankEnd, + p->CrtcHTotal, p->CrtcVDisplay, p->CrtcVBlankStart, + p->CrtcVSyncStart, p->CrtcVSyncEnd, p->CrtcVBlankEnd, + p->CrtcVTotal); + p = p->next; + } while (p != NULL && p != scrp->modes); +} + +void +xf86PrintModes(ScrnInfoPtr scrp) +{ + DisplayModePtr p; + float hsync, refresh = 0; + char *desc, *desc2, *prefix, *uprefix; + + if (scrp == NULL) + return; + + xf86DrvMsg(scrp->scrnIndex, scrp->virtualFrom, "Virtual size is %dx%d " + "(pitch %d)\n", scrp->virtualX, scrp->virtualY, + scrp->displayWidth); + + p = scrp->modes; + if (p == NULL) + return; + + do { + desc = desc2 = ""; + hsync = xf86ModeHSync(p); + refresh = xf86ModeVRefresh(p); + if (p->Flags & V_INTERLACE) { + desc = " (I)"; + } + if (p->Flags & V_DBLSCAN) { + desc = " (D)"; + } + if (p->VScan > 1) { + desc2 = " (VScan)"; + } + if (p->type & M_T_BUILTIN) + prefix = "Built-in mode"; + else if (p->type & M_T_DEFAULT) + prefix = "Default mode"; + else if (p->type & M_T_DRIVER) + prefix = "Driver mode"; + else + prefix = "Mode"; + if (p->type & M_T_USERDEF) + uprefix = "*"; + else + uprefix = " "; + if (hsync == 0 || refresh == 0) { + if (p->name) + xf86DrvMsg(scrp->scrnIndex, X_CONFIG, + "%s%s \"%s\"\n", uprefix, prefix, p->name); + else + xf86DrvMsg(scrp->scrnIndex, X_PROBED, + "%s%s %dx%d (unnamed)\n", + uprefix, prefix, p->HDisplay, p->VDisplay); + } else if (p->Clock == p->SynthClock) { + xf86DrvMsg(scrp->scrnIndex, X_CONFIG, + "%s%s \"%s\": %.1f MHz, %.1f kHz, %.1f Hz%s%s\n", + uprefix, prefix, p->name, p->Clock / 1000.0, + hsync, refresh, desc, desc2); + } else { + xf86DrvMsg(scrp->scrnIndex, X_CONFIG, + "%s%s \"%s\": %.1f MHz (scaled from %.1f MHz), " + "%.1f kHz, %.1f Hz%s%s\n", + uprefix, prefix, p->name, p->Clock / 1000.0, + p->SynthClock / 1000.0, hsync, refresh, desc, desc2); + } + if (hsync != 0 && refresh != 0) + xf86PrintModeline(scrp->scrnIndex,p); + p = p->next; + } while (p != NULL && p != scrp->modes); +} diff --git a/xorg-server/hw/xfree86/common/xf86Option.c b/xorg-server/hw/xfree86/common/xf86Option.c index a2868bf21..965ce4c7d 100644 --- a/xorg-server/hw/xfree86/common/xf86Option.c +++ b/xorg-server/hw/xfree86/common/xf86Option.c @@ -1,862 +1,862 @@ -/* - * Copyright (c) 1998-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * Author: David Dawes - * - * This file includes public option handling functions. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include "os.h" -#include "xf86.h" -#include "xf86Xinput.h" -#include "xf86Optrec.h" -#include "xf86Parser.h" - -static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, - Bool markUsed); - -/* - * xf86CollectOptions collects the options from each of the config file - * sections used by the screen and puts the combined list in pScrn->options. - * This function requires that the following have been initialised: - * - * pScrn->confScreen - * pScrn->Entities[i]->device - * pScrn->display - * pScrn->monitor - * - * The extraOpts parameter may optionally contain a list of additional options - * to include. - * - * The order of precedence for options is: - * - * extraOpts, display, confScreen, monitor, device - */ - -void -xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts) -{ - XF86OptionPtr tmp; - XF86OptionPtr extras = (XF86OptionPtr)extraOpts; - GDevPtr device; - - int i; - - pScrn->options = NULL; - - for (i=pScrn->numEntities - 1; i >= 0; i--) { - device = xf86GetDevFromEntity(pScrn->entityList[i], - pScrn->entityInstanceList[i]); - if (device && device->options) { - tmp = xf86optionListDup(device->options); - if (pScrn->options) - xf86optionListMerge(pScrn->options,tmp); - else - pScrn->options = tmp; - } - } - if (pScrn->monitor->options) { - tmp = xf86optionListDup(pScrn->monitor->options); - if (pScrn->options) - pScrn->options = xf86optionListMerge(pScrn->options, tmp); - else - pScrn->options = tmp; - } - if (pScrn->confScreen->options) { - tmp = xf86optionListDup(pScrn->confScreen->options); - if (pScrn->options) - pScrn->options = xf86optionListMerge(pScrn->options, tmp); - else - pScrn->options = tmp; - } - if (pScrn->display->options) { - tmp = xf86optionListDup(pScrn->display->options); - if (pScrn->options) - pScrn->options = xf86optionListMerge(pScrn->options, tmp); - else - pScrn->options = tmp; - } - if (extras) { - tmp = xf86optionListDup(extras); - if (pScrn->options) - pScrn->options = xf86optionListMerge(pScrn->options, tmp); - else - pScrn->options = tmp; - } -} - -/* - * xf86CollectInputOptions collects the options for an InputDevice. - * This function requires that the following has been initialised: - * - * pInfo->conf_idev - * - * The extraOpts parameter may optionally contain a list of additional options - * to include. - * - * The order of precedence for options is: - * - * extraOpts, pInfo->conf_idev->extraOptions, - * pInfo->conf_idev->commonOptions, defaultOpts - */ - -void -xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts, - pointer extraOpts) -{ - XF86OptionPtr tmp; - XF86OptionPtr extras = (XF86OptionPtr)extraOpts; - - pInfo->options = NULL; - if (defaultOpts) { - pInfo->options = xf86OptionListCreate(defaultOpts, -1, 0); - } - if (pInfo->conf_idev && pInfo->conf_idev->commonOptions) { - tmp = xf86optionListDup(pInfo->conf_idev->commonOptions); - if (pInfo->options) - pInfo->options = xf86optionListMerge(pInfo->options, tmp); - else - pInfo->options = tmp; - } - if (pInfo->conf_idev && pInfo->conf_idev->extraOptions) { - tmp = xf86optionListDup(pInfo->conf_idev->extraOptions); - if (pInfo->options) - pInfo->options = xf86optionListMerge(pInfo->options, tmp); - else - pInfo->options = tmp; - } - if (extras) { - tmp = xf86optionListDup(extras); - if (pInfo->options) - pInfo->options = xf86optionListMerge(pInfo->options, tmp); - else - pInfo->options = tmp; - } -} - -/* Created for new XInput stuff -- essentially extensions to the parser */ - -static int -LookupIntOption(pointer optlist, const char *name, int deflt, Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_INTEGER; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.num; - return deflt; -} - - -static double -LookupRealOption(pointer optlist, const char *name, double deflt, - Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_REAL; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.realnum; - return deflt; -} - - -static char * -LookupStrOption(pointer optlist, const char *name, char *deflt, Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_STRING; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.str; - if (deflt) - return xstrdup(deflt); - else - return NULL; -} - - -static int -LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed) -{ - OptionInfoRec o; - - o.name = name; - o.type = OPTV_BOOLEAN; - if (ParseOptionValue(-1, optlist, &o, markUsed)) - deflt = o.value.bool; - return deflt; -} - -/* These xf86Set* functions are intended for use by non-screen specific code */ - -int -xf86SetIntOption(pointer optlist, const char *name, int deflt) -{ - return LookupIntOption(optlist, name, deflt, TRUE); -} - - -double -xf86SetRealOption(pointer optlist, const char *name, double deflt) -{ - return LookupRealOption(optlist, name, deflt, TRUE); -} - - -char * -xf86SetStrOption(pointer optlist, const char *name, char *deflt) -{ - return LookupStrOption(optlist, name, deflt, TRUE); -} - - -int -xf86SetBoolOption(pointer optlist, const char *name, int deflt) -{ - return LookupBoolOption(optlist, name, deflt, TRUE); -} - -/* - * These are like the Set*Option functions, but they don't mark the options - * as used. - */ -int -xf86CheckIntOption(pointer optlist, const char *name, int deflt) -{ - return LookupIntOption(optlist, name, deflt, FALSE); -} - - -double -xf86CheckRealOption(pointer optlist, const char *name, double deflt) -{ - return LookupRealOption(optlist, name, deflt, FALSE); -} - - -char * -xf86CheckStrOption(pointer optlist, const char *name, char *deflt) -{ - return LookupStrOption(optlist, name, deflt, FALSE); -} - - -int -xf86CheckBoolOption(pointer optlist, const char *name, int deflt) -{ - return LookupBoolOption(optlist, name, deflt, FALSE); -} - -/* - * addNewOption() has the required property of replacing the option value - * if the option is already present. - */ -pointer -xf86ReplaceIntOption(pointer optlist, const char *name, const int val) -{ - char tmp[16]; - sprintf(tmp,"%i",val); - return xf86AddNewOption(optlist,name,tmp); -} - -pointer -xf86ReplaceRealOption(pointer optlist, const char *name, const double val) -{ - char tmp[32]; - snprintf(tmp,32,"%f",val); - return xf86AddNewOption(optlist,name,tmp); -} - -pointer -xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val) -{ - return xf86AddNewOption(optlist,name,val?"True":"False"); -} - -pointer -xf86ReplaceStrOption(pointer optlist, const char *name, const char* val) -{ - return xf86AddNewOption(optlist,name,val); -} - -pointer -xf86AddNewOption(pointer head, const char *name, const char *val) -{ - /* XXX These should actually be allocated in the parser library. */ - char *tmp = strdup(val); - char *tmp_name = strdup(name); - - return xf86addNewOption(head, tmp_name, tmp); -} - - -pointer -xf86NewOption(char *name, char *value) -{ - return xf86newOption(name, value); -} - - -pointer -xf86NextOption(pointer list) -{ - return xf86nextOption(list); -} - -pointer -xf86OptionListCreate(const char **options, int count, int used) -{ - return xf86optionListCreate(options, count, used); -} - -pointer -xf86OptionListMerge(pointer head, pointer tail) -{ - return xf86optionListMerge(head, tail); -} - -void -xf86OptionListFree(pointer opt) -{ - xf86optionListFree(opt); -} - -char * -xf86OptionName(pointer opt) -{ - return xf86optionName(opt); -} - -char * -xf86OptionValue(pointer opt) -{ - return xf86optionValue(opt); -} - -void -xf86OptionListReport(pointer parm) -{ - XF86OptionPtr opts = parm; - - while(opts) { - if (xf86optionValue(opts)) - xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n", - xf86optionName(opts), xf86optionValue(opts)); - else - xf86ErrorFVerb( 5, "\tOption \"%s\"\n", xf86optionName(opts)); - opts = xf86nextOption(opts); - } -} - -/* End of XInput-caused section */ - -pointer -xf86FindOption(pointer options, const char *name) -{ - return xf86findOption(options, name); -} - - -char * -xf86FindOptionValue(pointer options, const char *name) -{ - return xf86findOptionValue(options, name); -} - - -void -xf86MarkOptionUsed(pointer option) -{ - if (option != NULL) - ((XF86OptionPtr)option)->opt_used = TRUE; -} - - -void -xf86MarkOptionUsedByName(pointer options, const char *name) -{ - XF86OptionPtr opt; - - opt = xf86findOption(options, name); - if (opt != NULL) - opt->opt_used = TRUE; -} - -Bool -xf86CheckIfOptionUsed(pointer option) -{ - if (option != NULL) - return ((XF86OptionPtr)option)->opt_used; - else - return FALSE; -} - -Bool -xf86CheckIfOptionUsedByName(pointer options, const char *name) -{ - XF86OptionPtr opt; - - opt = xf86findOption(options, name); - if (opt != NULL) - return opt->opt_used; - else - return FALSE; -} - -void -xf86ShowUnusedOptions(int scrnIndex, pointer options) -{ - XF86OptionPtr opt = options; - - while (opt) { - if (opt->opt_name && !opt->opt_used) { - xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n", - opt->opt_name); - } - opt = opt->list.next; - } -} - - -static Bool -GetBoolValue(OptionInfoPtr p, const char *s) -{ - return xf86getBoolValue(&p->value.bool, s); -} - -static Bool -ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, - Bool markUsed) -{ - char *s, *end; - Bool wasUsed = FALSE; - - if ((s = xf86findOptionValue(options, p->name)) != NULL) { - if (markUsed) { - wasUsed = xf86CheckIfOptionUsedByName(options, p->name); - xf86MarkOptionUsedByName(options, p->name); - } - switch (p->type) { - case OPTV_INTEGER: - if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an integer value\n", - p->name); - p->found = FALSE; - } else { - p->value.num = strtoul(s, &end, 0); - if (*end == '\0') { - p->found = TRUE; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an integer value\n", - p->name); - p->found = FALSE; - } - } - break; - case OPTV_STRING: - if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires an string value\n", - p->name); - p->found = FALSE; - } else { - p->value.str = s; - p->found = TRUE; - } - break; - case OPTV_ANYSTR: - p->value.str = s; - p->found = TRUE; - break; - case OPTV_REAL: - if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a floating point value\n", - p->name); - p->found = FALSE; - } else { - p->value.realnum = strtod(s, &end); - if (*end == '\0') { - p->found = TRUE; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a floating point value\n", - p->name); - p->found = FALSE; - } - } - break; - case OPTV_BOOLEAN: - if (GetBoolValue(p, s)) { - p->found = TRUE; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a boolean value\n", p->name); - p->found = FALSE; - } - break; - case OPTV_FREQ: - if (*s == '\0') { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); - p->found = FALSE; - } else { - double freq = strtod(s, &end); - int units = 0; - - if (end != s) { - p->found = TRUE; - if (!xf86NameCmp(end, "Hz")) - units = 1; - else if (!xf86NameCmp(end, "kHz") || - !xf86NameCmp(end, "k")) - units = 1000; - else if (!xf86NameCmp(end, "MHz") || - !xf86NameCmp(end, "M")) - units = 1000000; - else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); - p->found = FALSE; - } - if (p->found) - freq *= (double)units; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a frequency value\n", - p->name); - p->found = FALSE; - } - if (p->found) { - p->value.freq.freq = freq; - p->value.freq.units = units; - } - } - break; - case OPTV_NONE: - /* Should never get here */ - p->found = FALSE; - break; - } - if (p->found && markUsed) { - int verb = 2; - if (wasUsed) - verb = 4; - xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name); - if (!(p->type == OPTV_BOOLEAN && *s == 0)) { - xf86ErrorFVerb(verb, " \"%s\"", s); - } - xf86ErrorFVerb(verb, "\n"); - } - } else if (p->type == OPTV_BOOLEAN) { - /* Look for matches with options with or without a "No" prefix. */ - char *n, *newn; - OptionInfoRec opt; - - n = xf86NormalizeName(p->name); - if (!n) { - p->found = FALSE; - return FALSE; - } - if (strncmp(n, "no", 2) == 0) { - newn = n + 2; - } else { - xfree(n); - n = xalloc(strlen(p->name) + 2 + 1); - if (!n) { - p->found = FALSE; - return FALSE; - } - strcpy(n, "No"); - strcat(n, p->name); - newn = n; - } - if ((s = xf86findOptionValue(options, newn)) != NULL) { - if (markUsed) - xf86MarkOptionUsedByName(options, newn); - if (GetBoolValue(&opt, s)) { - p->value.bool = !opt.value.bool; - p->found = TRUE; - } else { - xf86DrvMsg(scrnIndex, X_WARNING, - "Option \"%s\" requires a boolean value\n", newn); - p->found = FALSE; - } - } else { - p->found = FALSE; - } - if (p->found && markUsed) { - xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn); - if (*s != 0) { - xf86ErrorFVerb(2, " \"%s\"", s); - } - xf86ErrorFVerb(2, "\n"); - } - xfree(n); - } else { - p->found = FALSE; - } - return p->found; -} - - -void -xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo) -{ - OptionInfoPtr p; - - for (p = optinfo; p->name != NULL; p++) { - ParseOptionValue(scrnIndex, options, p, TRUE); - } -} - - -OptionInfoPtr -xf86TokenToOptinfo(const OptionInfoRec *table, int token) -{ - const OptionInfoRec *p, *match = NULL, *set = NULL; - - if (!table) { - ErrorF("xf86TokenToOptinfo: table is NULL\n"); - return NULL; - } - - for (p = table; p->token >= 0; p++) { - if (p->token == token) { - match = p; - if (p->found) - set = p; - } - } - - if (set) - return (OptionInfoPtr)set; - else if (match) - return (OptionInfoPtr)match; - else - return NULL; -} - - -const char * -xf86TokenToOptName(const OptionInfoRec *table, int token) -{ - const OptionInfoRec *p; - - p = xf86TokenToOptinfo(table, token); - return p->name; -} - - -Bool -xf86IsOptionSet(const OptionInfoRec *table, int token) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - return (p && p->found); -} - - -char * -xf86GetOptValString(const OptionInfoRec *table, int token) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) - return p->value.str; - else - return NULL; -} - - -Bool -xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - *value = p->value.num; - return TRUE; - } else - return FALSE; -} - - -Bool -xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - *value = p->value.num; - return TRUE; - } else - return FALSE; -} - - -Bool -xf86GetOptValReal(const OptionInfoRec *table, int token, double *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - *value = p->value.realnum; - return TRUE; - } else - return FALSE; -} - - -Bool -xf86GetOptValFreq(const OptionInfoRec *table, int token, - OptFreqUnits expectedUnits, double *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - if (p->value.freq.units > 0) { - /* Units give, so the scaling is known. */ - switch (expectedUnits) { - case OPTUNITS_HZ: - *value = p->value.freq.freq; - break; - case OPTUNITS_KHZ: - *value = p->value.freq.freq / 1000.0; - break; - case OPTUNITS_MHZ: - *value = p->value.freq.freq / 1000000.0; - break; - } - } else { - /* No units given, so try to guess the scaling. */ - switch (expectedUnits) { - case OPTUNITS_HZ: - *value = p->value.freq.freq; - break; - case OPTUNITS_KHZ: - if (p->value.freq.freq > 1000.0) - *value = p->value.freq.freq / 1000.0; - else - *value = p->value.freq.freq; - break; - case OPTUNITS_MHZ: - if (p->value.freq.freq > 1000000.0) - *value = p->value.freq.freq / 1000000.0; - else if (p->value.freq.freq > 1000.0) - *value = p->value.freq.freq / 1000.0; - else - *value = p->value.freq.freq; - } - } - return TRUE; - } else - return FALSE; -} - - -Bool -xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - *value = p->value.bool; - return TRUE; - } else - return FALSE; -} - - -Bool -xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def) -{ - OptionInfoPtr p; - - p = xf86TokenToOptinfo(table, token); - if (p && p->found) { - return p->value.bool; - } else - return def; -} - - -int -xf86NameCmp(const char *s1, const char *s2) -{ - return xf86nameCompare(s1, s2); -} - -char * -xf86NormalizeName(const char *s) -{ - char *ret, *q; - const char *p; - - if (s == NULL) - return NULL; - - ret = xalloc(strlen(s) + 1); - for (p = s, q = ret; *p != 0; p++) { - switch (*p) { - case '_': - case ' ': - case '\t': - continue; - default: - if (isupper(*p)) - *q++ = tolower(*p); - else - *q++ = *p; - } - } - *q = '\0'; - return ret; -} +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * Author: David Dawes + * + * This file includes public option handling functions. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include "os.h" +#include "xf86.h" +#include "xf86Xinput.h" +#include "xf86Optrec.h" +#include "xf86Parser.h" + +static Bool ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, + Bool markUsed); + +/* + * xf86CollectOptions collects the options from each of the config file + * sections used by the screen and puts the combined list in pScrn->options. + * This function requires that the following have been initialised: + * + * pScrn->confScreen + * pScrn->Entities[i]->device + * pScrn->display + * pScrn->monitor + * + * The extraOpts parameter may optionally contain a list of additional options + * to include. + * + * The order of precedence for options is: + * + * extraOpts, display, confScreen, monitor, device + */ + +void +xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts) +{ + XF86OptionPtr tmp; + XF86OptionPtr extras = (XF86OptionPtr)extraOpts; + GDevPtr device; + + int i; + + pScrn->options = NULL; + + for (i=pScrn->numEntities - 1; i >= 0; i--) { + device = xf86GetDevFromEntity(pScrn->entityList[i], + pScrn->entityInstanceList[i]); + if (device && device->options) { + tmp = xf86optionListDup(device->options); + if (pScrn->options) + xf86optionListMerge(pScrn->options,tmp); + else + pScrn->options = tmp; + } + } + if (pScrn->monitor->options) { + tmp = xf86optionListDup(pScrn->monitor->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (pScrn->confScreen->options) { + tmp = xf86optionListDup(pScrn->confScreen->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (pScrn->display->options) { + tmp = xf86optionListDup(pScrn->display->options); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } + if (extras) { + tmp = xf86optionListDup(extras); + if (pScrn->options) + pScrn->options = xf86optionListMerge(pScrn->options, tmp); + else + pScrn->options = tmp; + } +} + +/* + * xf86CollectInputOptions collects the options for an InputDevice. + * This function requires that the following has been initialised: + * + * pInfo->conf_idev + * + * The extraOpts parameter may optionally contain a list of additional options + * to include. + * + * The order of precedence for options is: + * + * extraOpts, pInfo->conf_idev->extraOptions, + * pInfo->conf_idev->commonOptions, defaultOpts + */ + +void +xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts, + pointer extraOpts) +{ + XF86OptionPtr tmp; + XF86OptionPtr extras = (XF86OptionPtr)extraOpts; + + pInfo->options = NULL; + if (defaultOpts) { + pInfo->options = xf86OptionListCreate(defaultOpts, -1, 0); + } + if (pInfo->conf_idev && pInfo->conf_idev->commonOptions) { + tmp = xf86optionListDup(pInfo->conf_idev->commonOptions); + if (pInfo->options) + pInfo->options = xf86optionListMerge(pInfo->options, tmp); + else + pInfo->options = tmp; + } + if (pInfo->conf_idev && pInfo->conf_idev->extraOptions) { + tmp = xf86optionListDup(pInfo->conf_idev->extraOptions); + if (pInfo->options) + pInfo->options = xf86optionListMerge(pInfo->options, tmp); + else + pInfo->options = tmp; + } + if (extras) { + tmp = xf86optionListDup(extras); + if (pInfo->options) + pInfo->options = xf86optionListMerge(pInfo->options, tmp); + else + pInfo->options = tmp; + } +} + +/* Created for new XInput stuff -- essentially extensions to the parser */ + +static int +LookupIntOption(pointer optlist, const char *name, int deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_INTEGER; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.num; + return deflt; +} + + +static double +LookupRealOption(pointer optlist, const char *name, double deflt, + Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_REAL; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.realnum; + return deflt; +} + + +static char * +LookupStrOption(pointer optlist, const char *name, char *deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_STRING; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.str; + if (deflt) + return xstrdup(deflt); + else + return NULL; +} + + +static int +LookupBoolOption(pointer optlist, const char *name, int deflt, Bool markUsed) +{ + OptionInfoRec o; + + o.name = name; + o.type = OPTV_BOOLEAN; + if (ParseOptionValue(-1, optlist, &o, markUsed)) + deflt = o.value.bool; + return deflt; +} + +/* These xf86Set* functions are intended for use by non-screen specific code */ + +int +xf86SetIntOption(pointer optlist, const char *name, int deflt) +{ + return LookupIntOption(optlist, name, deflt, TRUE); +} + + +double +xf86SetRealOption(pointer optlist, const char *name, double deflt) +{ + return LookupRealOption(optlist, name, deflt, TRUE); +} + + +char * +xf86SetStrOption(pointer optlist, const char *name, char *deflt) +{ + return LookupStrOption(optlist, name, deflt, TRUE); +} + + +int +xf86SetBoolOption(pointer optlist, const char *name, int deflt) +{ + return LookupBoolOption(optlist, name, deflt, TRUE); +} + +/* + * These are like the Set*Option functions, but they don't mark the options + * as used. + */ +int +xf86CheckIntOption(pointer optlist, const char *name, int deflt) +{ + return LookupIntOption(optlist, name, deflt, FALSE); +} + + +double +xf86CheckRealOption(pointer optlist, const char *name, double deflt) +{ + return LookupRealOption(optlist, name, deflt, FALSE); +} + + +char * +xf86CheckStrOption(pointer optlist, const char *name, char *deflt) +{ + return LookupStrOption(optlist, name, deflt, FALSE); +} + + +int +xf86CheckBoolOption(pointer optlist, const char *name, int deflt) +{ + return LookupBoolOption(optlist, name, deflt, FALSE); +} + +/* + * addNewOption() has the required property of replacing the option value + * if the option is already present. + */ +pointer +xf86ReplaceIntOption(pointer optlist, const char *name, const int val) +{ + char tmp[16]; + sprintf(tmp,"%i",val); + return xf86AddNewOption(optlist,name,tmp); +} + +pointer +xf86ReplaceRealOption(pointer optlist, const char *name, const double val) +{ + char tmp[32]; + snprintf(tmp,32,"%f",val); + return xf86AddNewOption(optlist,name,tmp); +} + +pointer +xf86ReplaceBoolOption(pointer optlist, const char *name, const Bool val) +{ + return xf86AddNewOption(optlist,name,val?"True":"False"); +} + +pointer +xf86ReplaceStrOption(pointer optlist, const char *name, const char* val) +{ + return xf86AddNewOption(optlist,name,val); +} + +pointer +xf86AddNewOption(pointer head, const char *name, const char *val) +{ + /* XXX These should actually be allocated in the parser library. */ + char *tmp = strdup(val); + char *tmp_name = strdup(name); + + return xf86addNewOption(head, tmp_name, tmp); +} + + +pointer +xf86NewOption(char *name, char *value) +{ + return xf86newOption(name, value); +} + + +pointer +xf86NextOption(pointer list) +{ + return xf86nextOption(list); +} + +pointer +xf86OptionListCreate(const char **options, int count, int used) +{ + return xf86optionListCreate(options, count, used); +} + +pointer +xf86OptionListMerge(pointer head, pointer tail) +{ + return xf86optionListMerge(head, tail); +} + +void +xf86OptionListFree(pointer opt) +{ + xf86optionListFree(opt); +} + +char * +xf86OptionName(pointer opt) +{ + return xf86optionName(opt); +} + +char * +xf86OptionValue(pointer opt) +{ + return xf86optionValue(opt); +} + +void +xf86OptionListReport(pointer parm) +{ + XF86OptionPtr opts = parm; + + while(opts) { + if (xf86optionValue(opts)) + xf86ErrorFVerb(5, "\tOption \"%s\" \"%s\"\n", + xf86optionName(opts), xf86optionValue(opts)); + else + xf86ErrorFVerb( 5, "\tOption \"%s\"\n", xf86optionName(opts)); + opts = xf86nextOption(opts); + } +} + +/* End of XInput-caused section */ + +pointer +xf86FindOption(pointer options, const char *name) +{ + return xf86findOption(options, name); +} + + +char * +xf86FindOptionValue(pointer options, const char *name) +{ + return xf86findOptionValue(options, name); +} + + +void +xf86MarkOptionUsed(pointer option) +{ + if (option != NULL) + ((XF86OptionPtr)option)->opt_used = TRUE; +} + + +void +xf86MarkOptionUsedByName(pointer options, const char *name) +{ + XF86OptionPtr opt; + + opt = xf86findOption(options, name); + if (opt != NULL) + opt->opt_used = TRUE; +} + +Bool +xf86CheckIfOptionUsed(pointer option) +{ + if (option != NULL) + return ((XF86OptionPtr)option)->opt_used; + else + return FALSE; +} + +Bool +xf86CheckIfOptionUsedByName(pointer options, const char *name) +{ + XF86OptionPtr opt; + + opt = xf86findOption(options, name); + if (opt != NULL) + return opt->opt_used; + else + return FALSE; +} + +void +xf86ShowUnusedOptions(int scrnIndex, pointer options) +{ + XF86OptionPtr opt = options; + + while (opt) { + if (opt->opt_name && !opt->opt_used) { + xf86DrvMsg(scrnIndex, X_WARNING, "Option \"%s\" is not used\n", + opt->opt_name); + } + opt = opt->list.next; + } +} + + +static Bool +GetBoolValue(OptionInfoPtr p, const char *s) +{ + return xf86getBoolValue(&p->value.bool, s); +} + +static Bool +ParseOptionValue(int scrnIndex, pointer options, OptionInfoPtr p, + Bool markUsed) +{ + char *s, *end; + Bool wasUsed = FALSE; + + if ((s = xf86findOptionValue(options, p->name)) != NULL) { + if (markUsed) { + wasUsed = xf86CheckIfOptionUsedByName(options, p->name); + xf86MarkOptionUsedByName(options, p->name); + } + switch (p->type) { + case OPTV_INTEGER: + if (*s == '\0') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an integer value\n", + p->name); + p->found = FALSE; + } else { + p->value.num = strtoul(s, &end, 0); + if (*end == '\0') { + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an integer value\n", + p->name); + p->found = FALSE; + } + } + break; + case OPTV_STRING: + if (*s == '\0') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires an string value\n", + p->name); + p->found = FALSE; + } else { + p->value.str = s; + p->found = TRUE; + } + break; + case OPTV_ANYSTR: + p->value.str = s; + p->found = TRUE; + break; + case OPTV_REAL: + if (*s == '\0') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a floating point value\n", + p->name); + p->found = FALSE; + } else { + p->value.realnum = strtod(s, &end); + if (*end == '\0') { + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a floating point value\n", + p->name); + p->found = FALSE; + } + } + break; + case OPTV_BOOLEAN: + if (GetBoolValue(p, s)) { + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a boolean value\n", p->name); + p->found = FALSE; + } + break; + case OPTV_FREQ: + if (*s == '\0') { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + p->found = FALSE; + } else { + double freq = strtod(s, &end); + int units = 0; + + if (end != s) { + p->found = TRUE; + if (!xf86NameCmp(end, "Hz")) + units = 1; + else if (!xf86NameCmp(end, "kHz") || + !xf86NameCmp(end, "k")) + units = 1000; + else if (!xf86NameCmp(end, "MHz") || + !xf86NameCmp(end, "M")) + units = 1000000; + else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + p->found = FALSE; + } + if (p->found) + freq *= (double)units; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a frequency value\n", + p->name); + p->found = FALSE; + } + if (p->found) { + p->value.freq.freq = freq; + p->value.freq.units = units; + } + } + break; + case OPTV_NONE: + /* Should never get here */ + p->found = FALSE; + break; + } + if (p->found && markUsed) { + int verb = 2; + if (wasUsed) + verb = 4; + xf86DrvMsgVerb(scrnIndex, X_CONFIG, verb, "Option \"%s\"", p->name); + if (!(p->type == OPTV_BOOLEAN && *s == 0)) { + xf86ErrorFVerb(verb, " \"%s\"", s); + } + xf86ErrorFVerb(verb, "\n"); + } + } else if (p->type == OPTV_BOOLEAN) { + /* Look for matches with options with or without a "No" prefix. */ + char *n, *newn; + OptionInfoRec opt; + + n = xf86NormalizeName(p->name); + if (!n) { + p->found = FALSE; + return FALSE; + } + if (strncmp(n, "no", 2) == 0) { + newn = n + 2; + } else { + free(n); + n = malloc(strlen(p->name) + 2 + 1); + if (!n) { + p->found = FALSE; + return FALSE; + } + strcpy(n, "No"); + strcat(n, p->name); + newn = n; + } + if ((s = xf86findOptionValue(options, newn)) != NULL) { + if (markUsed) + xf86MarkOptionUsedByName(options, newn); + if (GetBoolValue(&opt, s)) { + p->value.bool = !opt.value.bool; + p->found = TRUE; + } else { + xf86DrvMsg(scrnIndex, X_WARNING, + "Option \"%s\" requires a boolean value\n", newn); + p->found = FALSE; + } + } else { + p->found = FALSE; + } + if (p->found && markUsed) { + xf86DrvMsgVerb(scrnIndex, X_CONFIG, 2, "Option \"%s\"", newn); + if (*s != 0) { + xf86ErrorFVerb(2, " \"%s\"", s); + } + xf86ErrorFVerb(2, "\n"); + } + free(n); + } else { + p->found = FALSE; + } + return p->found; +} + + +void +xf86ProcessOptions(int scrnIndex, pointer options, OptionInfoPtr optinfo) +{ + OptionInfoPtr p; + + for (p = optinfo; p->name != NULL; p++) { + ParseOptionValue(scrnIndex, options, p, TRUE); + } +} + + +OptionInfoPtr +xf86TokenToOptinfo(const OptionInfoRec *table, int token) +{ + const OptionInfoRec *p, *match = NULL, *set = NULL; + + if (!table) { + ErrorF("xf86TokenToOptinfo: table is NULL\n"); + return NULL; + } + + for (p = table; p->token >= 0; p++) { + if (p->token == token) { + match = p; + if (p->found) + set = p; + } + } + + if (set) + return (OptionInfoPtr)set; + else if (match) + return (OptionInfoPtr)match; + else + return NULL; +} + + +const char * +xf86TokenToOptName(const OptionInfoRec *table, int token) +{ + const OptionInfoRec *p; + + p = xf86TokenToOptinfo(table, token); + return p->name; +} + + +Bool +xf86IsOptionSet(const OptionInfoRec *table, int token) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + return (p && p->found); +} + + +char * +xf86GetOptValString(const OptionInfoRec *table, int token) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) + return p->value.str; + else + return NULL; +} + + +Bool +xf86GetOptValInteger(const OptionInfoRec *table, int token, int *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.num; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValULong(const OptionInfoRec *table, int token, unsigned long *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.num; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValReal(const OptionInfoRec *table, int token, double *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.realnum; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValFreq(const OptionInfoRec *table, int token, + OptFreqUnits expectedUnits, double *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + if (p->value.freq.units > 0) { + /* Units give, so the scaling is known. */ + switch (expectedUnits) { + case OPTUNITS_HZ: + *value = p->value.freq.freq; + break; + case OPTUNITS_KHZ: + *value = p->value.freq.freq / 1000.0; + break; + case OPTUNITS_MHZ: + *value = p->value.freq.freq / 1000000.0; + break; + } + } else { + /* No units given, so try to guess the scaling. */ + switch (expectedUnits) { + case OPTUNITS_HZ: + *value = p->value.freq.freq; + break; + case OPTUNITS_KHZ: + if (p->value.freq.freq > 1000.0) + *value = p->value.freq.freq / 1000.0; + else + *value = p->value.freq.freq; + break; + case OPTUNITS_MHZ: + if (p->value.freq.freq > 1000000.0) + *value = p->value.freq.freq / 1000000.0; + else if (p->value.freq.freq > 1000.0) + *value = p->value.freq.freq / 1000.0; + else + *value = p->value.freq.freq; + } + } + return TRUE; + } else + return FALSE; +} + + +Bool +xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + *value = p->value.bool; + return TRUE; + } else + return FALSE; +} + + +Bool +xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def) +{ + OptionInfoPtr p; + + p = xf86TokenToOptinfo(table, token); + if (p && p->found) { + return p->value.bool; + } else + return def; +} + + +int +xf86NameCmp(const char *s1, const char *s2) +{ + return xf86nameCompare(s1, s2); +} + +char * +xf86NormalizeName(const char *s) +{ + char *ret, *q; + const char *p; + + if (s == NULL) + return NULL; + + ret = malloc(strlen(s) + 1); + for (p = s, q = ret; *p != 0; p++) { + switch (*p) { + case '_': + case ' ': + case '\t': + continue; + default: + if (isupper(*p)) + *q++ = tolower(*p); + else + *q++ = *p; + } + } + *q = '\0'; + return ret; +} diff --git a/xorg-server/hw/xfree86/common/xf86Privstr.h b/xorg-server/hw/xfree86/common/xf86Privstr.h index b2095aab1..6138b6bec 100644 --- a/xorg-server/hw/xfree86/common/xf86Privstr.h +++ b/xorg-server/hw/xfree86/common/xf86Privstr.h @@ -1,173 +1,170 @@ - -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * This file contains definitions of the private XFree86 data structures/types. - * None of the data structures here should be used by video drivers. - */ - -#ifndef _XF86PRIVSTR_H -#define _XF86PRIVSTR_H - -#include "xf86str.h" - -typedef enum { - LogNone, - LogFlush, - LogSync -} Log; - -typedef enum { - XF86_GlxVisualsMinimal, - XF86_GlxVisualsTypical, - XF86_GlxVisualsAll, -} XF86_GlxVisuals; - -/* - * xf86InfoRec contains global parameters which the video drivers never - * need to access. Global parameters which the video drivers do need - * should be individual globals. - */ - -typedef struct { - int consoleFd; - int vtno; - Bool vtSysreq; - - /* event handler part */ - int lastEventTime; - Bool vtRequestsPending; -#ifdef sun - int vtPendingNum; -#endif - Bool dontVTSwitch; - Bool dontZap; - Bool dontZoom; - Bool notrapSignals; /* don't exit cleanly - die at fault */ - Bool caughtSignal; - - /* graphics part */ - ScreenPtr currentScreen; -#if defined(CSRG_BASED) || defined(__FreeBSD_kernel__) - int screenFd; /* fd for memory mapped access to - * vga card */ - int consType; /* Which console driver? */ -#endif - - /* Other things */ - Bool allowMouseOpenFail; - Bool vidModeEnabled; /* VidMode extension enabled */ - Bool vidModeAllowNonLocal; /* allow non-local VidMode - * connections */ - Bool miscModInDevEnabled; /* Allow input devices to be - * changed */ - Bool miscModInDevAllowNonLocal; - Bool useSIGIO; /* Use SIGIO for handling - input device events */ - Pix24Flags pixmap24; - MessageType pix24From; -#ifdef SUPPORT_PC98 - Bool pc98; -#endif - Bool pmFlag; - Log log; - Bool kbdCustomKeycodes; - Bool disableRandR; - MessageType randRFrom; - Bool aiglx; - MessageType aiglxFrom; - XF86_GlxVisuals glxVisuals; - MessageType glxVisualsFrom; - - Bool useDefaultFontPath; - MessageType useDefaultFontPathFrom; - Bool ignoreABI; - - Bool allowEmptyInput; /* Allow the server to start with no input - * devices. */ - Bool autoAddDevices; /* Whether to succeed NIDR, or ignore. */ - Bool autoEnableDevices; /* Whether to enable, or let the client - * control. */ - - Bool dri2; - MessageType dri2From; -} xf86InfoRec, *xf86InfoPtr; - -#ifdef DPMSExtension -/* Private info for DPMS */ -typedef struct { - CloseScreenProcPtr CloseScreen; - Bool Enabled; - int Flags; -} DPMSRec, *DPMSPtr; -#endif - -#ifdef XF86VIDMODE -/* Private info for Video Mode Extentsion */ -typedef struct { - DisplayModePtr First; - DisplayModePtr Next; - int Flags; - CloseScreenProcPtr CloseScreen; -} VidModeRec, *VidModePtr; -#endif - -/* Information for root window properties. */ -typedef struct _RootWinProp { - struct _RootWinProp * next; - char * name; - Atom type; - short format; - long size; - pointer data; -} RootWinProp, *RootWinPropPtr; - -/* private resource types */ -#define ResNoAvoid ResBios - -/* ISC's cc can't handle ~ of UL constants, so explicitly type cast them. */ -#define XLED1 ((unsigned long) 0x00000001) -#define XLED2 ((unsigned long) 0x00000002) -#define XLED3 ((unsigned long) 0x00000004) -#define XLED4 ((unsigned long) 0x00000008) -#define XCAPS ((unsigned long) 0x20000000) -#define XNUM ((unsigned long) 0x40000000) -#define XSCR ((unsigned long) 0x80000000) -#define XCOMP ((unsigned long) 0x00008000) - -/* BSD console driver types (consType) */ -#if defined(CSRG_BASED) || defined(__FreeBSD_kernel__) -#define PCCONS 0 -#define CODRV011 1 -#define CODRV01X 2 -#define SYSCONS 8 -#define PCVT 16 -#define WSCONS 32 -#endif - -#endif /* _XF86PRIVSTR_H */ + +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * This file contains definitions of the private XFree86 data structures/types. + * None of the data structures here should be used by video drivers. + */ + +#ifndef _XF86PRIVSTR_H +#define _XF86PRIVSTR_H + +#include "xf86str.h" + +typedef enum { + LogNone, + LogFlush, + LogSync +} Log; + +typedef enum { + XF86_GlxVisualsMinimal, + XF86_GlxVisualsTypical, + XF86_GlxVisualsAll, +} XF86_GlxVisuals; + +/* + * xf86InfoRec contains global parameters which the video drivers never + * need to access. Global parameters which the video drivers do need + * should be individual globals. + */ + +typedef struct { + int consoleFd; + int vtno; + Bool vtSysreq; + + /* event handler part */ + int lastEventTime; + Bool vtRequestsPending; +#ifdef sun + int vtPendingNum; +#endif + Bool dontVTSwitch; + Bool dontZap; + Bool dontZoom; + Bool notrapSignals; /* don't exit cleanly - die at fault */ + Bool caughtSignal; + + /* graphics part */ + ScreenPtr currentScreen; +#if defined(CSRG_BASED) || defined(__FreeBSD_kernel__) + int screenFd; /* fd for memory mapped access to + * vga card */ + int consType; /* Which console driver? */ +#endif + + /* Other things */ + Bool allowMouseOpenFail; + Bool vidModeEnabled; /* VidMode extension enabled */ + Bool vidModeAllowNonLocal; /* allow non-local VidMode + * connections */ + Bool miscModInDevEnabled; /* Allow input devices to be + * changed */ + Bool miscModInDevAllowNonLocal; + Bool useSIGIO; /* Use SIGIO for handling + input device events */ + Pix24Flags pixmap24; + MessageType pix24From; +#ifdef SUPPORT_PC98 + Bool pc98; +#endif + Bool pmFlag; + Log log; + Bool kbdCustomKeycodes; + Bool disableRandR; + MessageType randRFrom; + Bool aiglx; + MessageType aiglxFrom; + XF86_GlxVisuals glxVisuals; + MessageType glxVisualsFrom; + + Bool useDefaultFontPath; + MessageType useDefaultFontPathFrom; + Bool ignoreABI; + + Bool allowEmptyInput; /* Allow the server to start with no input + * devices. */ + Bool autoAddDevices; /* Whether to succeed NIDR, or ignore. */ + Bool autoEnableDevices; /* Whether to enable, or let the client + * control. */ + + Bool dri2; + MessageType dri2From; +} xf86InfoRec, *xf86InfoPtr; + +#ifdef DPMSExtension +/* Private info for DPMS */ +typedef struct { + CloseScreenProcPtr CloseScreen; + Bool Enabled; + int Flags; +} DPMSRec, *DPMSPtr; +#endif + +#ifdef XF86VIDMODE +/* Private info for Video Mode Extentsion */ +typedef struct { + DisplayModePtr First; + DisplayModePtr Next; + int Flags; + CloseScreenProcPtr CloseScreen; +} VidModeRec, *VidModePtr; +#endif + +/* Information for root window properties. */ +typedef struct _RootWinProp { + struct _RootWinProp * next; + char * name; + Atom type; + short format; + long size; + pointer data; +} RootWinProp, *RootWinPropPtr; + +/* ISC's cc can't handle ~ of UL constants, so explicitly type cast them. */ +#define XLED1 ((unsigned long) 0x00000001) +#define XLED2 ((unsigned long) 0x00000002) +#define XLED3 ((unsigned long) 0x00000004) +#define XLED4 ((unsigned long) 0x00000008) +#define XCAPS ((unsigned long) 0x20000000) +#define XNUM ((unsigned long) 0x40000000) +#define XSCR ((unsigned long) 0x80000000) +#define XCOMP ((unsigned long) 0x00008000) + +/* BSD console driver types (consType) */ +#if defined(CSRG_BASED) || defined(__FreeBSD_kernel__) +#define PCCONS 0 +#define CODRV011 1 +#define CODRV01X 2 +#define SYSCONS 8 +#define PCVT 16 +#define WSCONS 32 +#endif + +#endif /* _XF86PRIVSTR_H */ diff --git a/xorg-server/hw/xfree86/common/xf86RandR.c b/xorg-server/hw/xfree86/common/xf86RandR.c index 86c7bde79..1893974e2 100644 --- a/xorg-server/hw/xfree86/common/xf86RandR.c +++ b/xorg-server/hw/xfree86/common/xf86RandR.c @@ -1,459 +1,459 @@ -/* - * - * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. - * - * 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. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "os.h" -#include "globals.h" -#include "xf86.h" -#include "xf86str.h" -#include "xf86Priv.h" -#include "xf86DDC.h" -#include "mipointer.h" -#include -#include "inputstr.h" - -typedef struct _xf86RandRInfo { - CreateScreenResourcesProcPtr CreateScreenResources; - CloseScreenProcPtr CloseScreen; - int virtualX; - int virtualY; - int mmWidth; - int mmHeight; - Rotation rotation; -} XF86RandRInfoRec, *XF86RandRInfoPtr; - -static int xf86RandRKeyIndex; -static DevPrivateKey xf86RandRKey; - -#define XF86RANDRINFO(p) ((XF86RandRInfoPtr)dixLookupPrivate(&(p)->devPrivates, xf86RandRKey)) - -static int -xf86RandRModeRefresh (DisplayModePtr mode) -{ - if (mode->VRefresh) - return (int) (mode->VRefresh + 0.5); - else if (mode->Clock == 0) - return 0; - else - return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); -} - -static Bool -xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) -{ - RRScreenSizePtr pSize; - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - DisplayModePtr mode; - int refresh0 = 60; - xorgRRModeMM RRModeMM; - - *rotations = RR_Rotate_0; - - for (mode = scrp->modes; mode != NULL ; mode = mode->next) - { - int refresh = xf86RandRModeRefresh (mode); - - if (mode == scrp->modes) - refresh0 = refresh; - - RRModeMM.mode = mode; - RRModeMM.virtX = randrp->virtualX; - RRModeMM.virtY = randrp->virtualY; - RRModeMM.mmWidth = randrp->mmWidth; - RRModeMM.mmHeight = randrp->mmHeight; - - if(scrp->DriverFunc) { - (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); - } - - pSize = RRRegisterSize (pScreen, - mode->HDisplay, mode->VDisplay, - RRModeMM.mmWidth, RRModeMM.mmHeight); - if (!pSize) - return FALSE; - RRRegisterRate (pScreen, pSize, refresh); - if (mode == scrp->currentMode && - mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY) - RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); - if (mode->next == scrp->modes) - break; - } - if (scrp->currentMode->HDisplay != randrp->virtualX || - scrp->currentMode->VDisplay != randrp->virtualY) - { - mode = scrp->modes; - - RRModeMM.mode = NULL; - RRModeMM.virtX = randrp->virtualX; - RRModeMM.virtY = randrp->virtualY; - RRModeMM.mmWidth = randrp->mmWidth; - RRModeMM.mmHeight = randrp->mmHeight; - - if(scrp->DriverFunc) { - (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); - } - - pSize = RRRegisterSize (pScreen, - randrp->virtualX, randrp->virtualY, - RRModeMM.mmWidth, RRModeMM.mmHeight); - if (!pSize) - return FALSE; - RRRegisterRate (pScreen, pSize, refresh0); - if (scrp->virtualX == randrp->virtualX && - scrp->virtualY == randrp->virtualY) - { - RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize); - } - } - - /* If there is driver support for randr, let it set our supported rotations */ - if(scrp->DriverFunc) { - xorgRRRotation RRRotation; - - RRRotation.RRRotations = *rotations; - if (!(*scrp->DriverFunc)(scrp, RR_GET_INFO, &RRRotation)) - return TRUE; - *rotations = RRRotation.RRRotations; - } - - return TRUE; -} - -static Bool -xf86RandRSetMode (ScreenPtr pScreen, - DisplayModePtr mode, - Bool useVirtual, - int mmWidth, - int mmHeight) -{ - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - int oldWidth = pScreen->width; - int oldHeight = pScreen->height; - int oldmmWidth = pScreen->mmWidth; - int oldmmHeight = pScreen->mmHeight; - int oldVirtualX = scrp->virtualX; - int oldVirtualY = scrp->virtualY; - WindowPtr pRoot = WindowTable[pScreen->myNum]; - Bool ret = TRUE; - - if (pRoot && scrp->vtSema) - (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); - if (useVirtual) - { - scrp->virtualX = randrp->virtualX; - scrp->virtualY = randrp->virtualY; - } - else - { - scrp->virtualX = mode->HDisplay; - scrp->virtualY = mode->VDisplay; - } - - /* - * The DIX forgets the physical dimensions we passed into RRRegisterSize, so - * reconstruct them if possible. - */ - if(scrp->DriverFunc) { - xorgRRModeMM RRModeMM; - - RRModeMM.mode = mode; - RRModeMM.virtX = scrp->virtualX; - RRModeMM.virtY = scrp->virtualY; - RRModeMM.mmWidth = mmWidth; - RRModeMM.mmHeight = mmHeight; - - (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); - - mmWidth = RRModeMM.mmWidth; - mmHeight = RRModeMM.mmHeight; - } - if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) - { - /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ - pScreen->width = scrp->virtualY; - pScreen->height = scrp->virtualX; - pScreen->mmWidth = mmHeight; - pScreen->mmHeight = mmWidth; - } - else - { - pScreen->width = scrp->virtualX; - pScreen->height = scrp->virtualY; - pScreen->mmWidth = mmWidth; - pScreen->mmHeight = mmHeight; - } - if (!xf86SwitchMode (pScreen, mode)) - { - pScreen->width = oldWidth; - pScreen->height = oldHeight; - pScreen->mmWidth = oldmmWidth; - pScreen->mmHeight = oldmmHeight; - scrp->virtualX = oldVirtualX; - scrp->virtualY = oldVirtualY; - ret = FALSE; - } - /* - * Make sure the layout is correct - */ - xf86ReconfigureLayout(); - - /* - * Make sure the whole screen is visible - */ - xf86SetViewport (pScreen, pScreen->width, pScreen->height); - xf86SetViewport (pScreen, 0, 0); - if (pRoot && scrp->vtSema) - (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); - return ret; -} - -static Bool -xf86RandRSetConfig (ScreenPtr pScreen, - Rotation rotation, - int rate, - RRScreenSizePtr pSize) -{ - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - DisplayModePtr mode; - int px, py; - Bool useVirtual = FALSE; - Rotation oldRotation = randrp->rotation; - - miPointerGetPosition(inputInfo.pointer, &px, &py); - for (mode = scrp->modes; ; mode = mode->next) - { - if (mode->HDisplay == pSize->width && - mode->VDisplay == pSize->height && - (rate == 0 || xf86RandRModeRefresh (mode) == rate)) - break; - if (mode->next == scrp->modes) - { - if (pSize->width == randrp->virtualX && - pSize->height == randrp->virtualY) - { - mode = scrp->modes; - useVirtual = TRUE; - break; - } - return FALSE; - } - } - - if (randrp->rotation != rotation) { - - /* Have the driver do its thing. */ - if (scrp->DriverFunc) { - xorgRRRotation RRRotation; - RRRotation.RRConfig.rotation = rotation; - RRRotation.RRConfig.rate = rate; - RRRotation.RRConfig.width = pSize->width; - RRRotation.RRConfig.height = pSize->height; - - /* - * Currently we need to rely on HW support for rotation. - */ - if (!(*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation)) - return FALSE; - } else - return FALSE; - - randrp->rotation = rotation; - } - - if (!xf86RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) { - if(randrp->rotation != oldRotation) { - /* Have the driver undo its thing. */ - if (scrp->DriverFunc) { - xorgRRRotation RRRotation; - RRRotation.RRConfig.rotation = oldRotation; - RRRotation.RRConfig.rate = xf86RandRModeRefresh (scrp->currentMode); - RRRotation.RRConfig.width = scrp->virtualX; - RRRotation.RRConfig.height = scrp->virtualY; - (*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation); - } - - randrp->rotation = oldRotation; - } - return FALSE; - } - /* - * Move the cursor back where it belongs; SwitchMode repositions it - */ - if (pScreen == miPointerCurrentScreen ()) - { - px = (px >= pScreen->width ? (pScreen->width - 1) : px); - py = (py >= pScreen->height ? (pScreen->height - 1) : py); - - xf86SetViewport(pScreen, px, py); - - (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); - } - - return TRUE; -} - -/* - * Wait until the screen is initialized before whacking the - * sizes around; otherwise the screen pixmap will be allocated - * at the current mode size rather than the maximum size - */ -static Bool -xf86RandRCreateScreenResources (ScreenPtr pScreen) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); -#if 0 - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - DisplayModePtr mode; -#endif - - pScreen->CreateScreenResources = randrp->CreateScreenResources; - if (!(*pScreen->CreateScreenResources) (pScreen)) - return FALSE; - -#if 0 - mode = scrp->currentMode; - if (mode) - xf86RandRSetMode (pScreen, mode, TRUE); -#endif - - return TRUE; -} - -/* - * Reset size back to original - */ -static Bool -xf86RandRCloseScreen (int index, ScreenPtr pScreen) -{ - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - - scrp->virtualX = pScreen->width = randrp->virtualX; - scrp->virtualY = pScreen->height = randrp->virtualY; - scrp->currentMode = scrp->modes; - pScreen->CloseScreen = randrp->CloseScreen; - xfree (randrp); - dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, NULL); - return (*pScreen->CloseScreen) (index, pScreen); -} - -Rotation -xf86GetRotation(ScreenPtr pScreen) -{ - if (xf86RandRKey == NULL) - return RR_Rotate_0; - - return XF86RANDRINFO(pScreen)->rotation; -} - -/* Function to change RandR's idea of the virtual screen size */ -Bool -xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen, - int newvirtX, int newvirtY, int newmmWidth, int newmmHeight, - Bool resetMode) -{ - XF86RandRInfoPtr randrp; - - if (xf86RandRKey == NULL) - return FALSE; - - randrp = XF86RANDRINFO(pScreen); - if (randrp == NULL) - return FALSE; - - if (newvirtX > 0) - randrp->virtualX = newvirtX; - - if (newvirtY > 0) - randrp->virtualY = newvirtY; - - if (newmmWidth > 0) - randrp->mmWidth = newmmWidth; - - if (newmmHeight > 0) - randrp->mmHeight = newmmHeight; - - /* This is only for during server start */ - if (resetMode) { - return (xf86RandRSetMode(pScreen, - XF86SCRNINFO(pScreen)->currentMode, - TRUE, - pScreen->mmWidth, pScreen->mmHeight)); - } - - return TRUE; -} - -Bool -xf86RandRInit (ScreenPtr pScreen) -{ - rrScrPrivPtr rp; - XF86RandRInfoPtr randrp; - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - -#ifdef PANORAMIX - /* XXX disable RandR when using Xinerama */ - if (!noPanoramiXExtension) - return TRUE; -#endif - - xf86RandRKey = &xf86RandRKeyIndex; - - randrp = xalloc (sizeof (XF86RandRInfoRec)); - if (!randrp) - return FALSE; - - if (!RRScreenInit (pScreen)) - { - xfree (randrp); - return FALSE; - } - rp = rrGetScrPriv(pScreen); - rp->rrGetInfo = xf86RandRGetInfo; - rp->rrSetConfig = xf86RandRSetConfig; - - randrp->virtualX = scrp->virtualX; - randrp->virtualY = scrp->virtualY; - randrp->mmWidth = pScreen->mmWidth; - randrp->mmHeight = pScreen->mmHeight; - - randrp->CreateScreenResources = pScreen->CreateScreenResources; - pScreen->CreateScreenResources = xf86RandRCreateScreenResources; - - randrp->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = xf86RandRCloseScreen; - - randrp->rotation = RR_Rotate_0; - - dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, randrp); - return TRUE; -} - - +/* + * + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "os.h" +#include "globals.h" +#include "xf86.h" +#include "xf86str.h" +#include "xf86Priv.h" +#include "xf86DDC.h" +#include "mipointer.h" +#include +#include "inputstr.h" + +typedef struct _xf86RandRInfo { + CreateScreenResourcesProcPtr CreateScreenResources; + CloseScreenProcPtr CloseScreen; + int virtualX; + int virtualY; + int mmWidth; + int mmHeight; + Rotation rotation; +} XF86RandRInfoRec, *XF86RandRInfoPtr; + +static int xf86RandRKeyIndex; +static DevPrivateKey xf86RandRKey; + +#define XF86RANDRINFO(p) ((XF86RandRInfoPtr)dixLookupPrivate(&(p)->devPrivates, xf86RandRKey)) + +static int +xf86RandRModeRefresh (DisplayModePtr mode) +{ + if (mode->VRefresh) + return (int) (mode->VRefresh + 0.5); + else if (mode->Clock == 0) + return 0; + else + return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); +} + +static Bool +xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + RRScreenSizePtr pSize; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int refresh0 = 60; + xorgRRModeMM RRModeMM; + + *rotations = RR_Rotate_0; + + for (mode = scrp->modes; mode != NULL ; mode = mode->next) + { + int refresh = xf86RandRModeRefresh (mode); + + if (mode == scrp->modes) + refresh0 = refresh; + + RRModeMM.mode = mode; + RRModeMM.virtX = randrp->virtualX; + RRModeMM.virtY = randrp->virtualY; + RRModeMM.mmWidth = randrp->mmWidth; + RRModeMM.mmHeight = randrp->mmHeight; + + if(scrp->DriverFunc) { + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + } + + pSize = RRRegisterSize (pScreen, + mode->HDisplay, mode->VDisplay, + RRModeMM.mmWidth, RRModeMM.mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh); + if (mode == scrp->currentMode && + mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY) + RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); + if (mode->next == scrp->modes) + break; + } + if (scrp->currentMode->HDisplay != randrp->virtualX || + scrp->currentMode->VDisplay != randrp->virtualY) + { + mode = scrp->modes; + + RRModeMM.mode = NULL; + RRModeMM.virtX = randrp->virtualX; + RRModeMM.virtY = randrp->virtualY; + RRModeMM.mmWidth = randrp->mmWidth; + RRModeMM.mmHeight = randrp->mmHeight; + + if(scrp->DriverFunc) { + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + } + + pSize = RRRegisterSize (pScreen, + randrp->virtualX, randrp->virtualY, + RRModeMM.mmWidth, RRModeMM.mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh0); + if (scrp->virtualX == randrp->virtualX && + scrp->virtualY == randrp->virtualY) + { + RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize); + } + } + + /* If there is driver support for randr, let it set our supported rotations */ + if(scrp->DriverFunc) { + xorgRRRotation RRRotation; + + RRRotation.RRRotations = *rotations; + if (!(*scrp->DriverFunc)(scrp, RR_GET_INFO, &RRRotation)) + return TRUE; + *rotations = RRRotation.RRRotations; + } + + return TRUE; +} + +static Bool +xf86RandRSetMode (ScreenPtr pScreen, + DisplayModePtr mode, + Bool useVirtual, + int mmWidth, + int mmHeight) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int oldWidth = pScreen->width; + int oldHeight = pScreen->height; + int oldmmWidth = pScreen->mmWidth; + int oldmmHeight = pScreen->mmHeight; + int oldVirtualX = scrp->virtualX; + int oldVirtualY = scrp->virtualY; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + Bool ret = TRUE; + + if (pRoot && scrp->vtSema) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); + if (useVirtual) + { + scrp->virtualX = randrp->virtualX; + scrp->virtualY = randrp->virtualY; + } + else + { + scrp->virtualX = mode->HDisplay; + scrp->virtualY = mode->VDisplay; + } + + /* + * The DIX forgets the physical dimensions we passed into RRRegisterSize, so + * reconstruct them if possible. + */ + if(scrp->DriverFunc) { + xorgRRModeMM RRModeMM; + + RRModeMM.mode = mode; + RRModeMM.virtX = scrp->virtualX; + RRModeMM.virtY = scrp->virtualY; + RRModeMM.mmWidth = mmWidth; + RRModeMM.mmHeight = mmHeight; + + (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM); + + mmWidth = RRModeMM.mmWidth; + mmHeight = RRModeMM.mmHeight; + } + if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) + { + /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ + pScreen->width = scrp->virtualY; + pScreen->height = scrp->virtualX; + pScreen->mmWidth = mmHeight; + pScreen->mmHeight = mmWidth; + } + else + { + pScreen->width = scrp->virtualX; + pScreen->height = scrp->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + } + if (!xf86SwitchMode (pScreen, mode)) + { + pScreen->width = oldWidth; + pScreen->height = oldHeight; + pScreen->mmWidth = oldmmWidth; + pScreen->mmHeight = oldmmHeight; + scrp->virtualX = oldVirtualX; + scrp->virtualY = oldVirtualY; + ret = FALSE; + } + /* + * Make sure the layout is correct + */ + xf86ReconfigureLayout(); + + /* + * Make sure the whole screen is visible + */ + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot && scrp->vtSema) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); + return ret; +} + +static Bool +xf86RandRSetConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int px, py; + Bool useVirtual = FALSE; + Rotation oldRotation = randrp->rotation; + + miPointerGetPosition(inputInfo.pointer, &px, &py); + for (mode = scrp->modes; ; mode = mode->next) + { + if (mode->HDisplay == pSize->width && + mode->VDisplay == pSize->height && + (rate == 0 || xf86RandRModeRefresh (mode) == rate)) + break; + if (mode->next == scrp->modes) + { + if (pSize->width == randrp->virtualX && + pSize->height == randrp->virtualY) + { + mode = scrp->modes; + useVirtual = TRUE; + break; + } + return FALSE; + } + } + + if (randrp->rotation != rotation) { + + /* Have the driver do its thing. */ + if (scrp->DriverFunc) { + xorgRRRotation RRRotation; + RRRotation.RRConfig.rotation = rotation; + RRRotation.RRConfig.rate = rate; + RRRotation.RRConfig.width = pSize->width; + RRRotation.RRConfig.height = pSize->height; + + /* + * Currently we need to rely on HW support for rotation. + */ + if (!(*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation)) + return FALSE; + } else + return FALSE; + + randrp->rotation = rotation; + } + + if (!xf86RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) { + if(randrp->rotation != oldRotation) { + /* Have the driver undo its thing. */ + if (scrp->DriverFunc) { + xorgRRRotation RRRotation; + RRRotation.RRConfig.rotation = oldRotation; + RRRotation.RRConfig.rate = xf86RandRModeRefresh (scrp->currentMode); + RRRotation.RRConfig.width = scrp->virtualX; + RRRotation.RRConfig.height = scrp->virtualY; + (*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation); + } + + randrp->rotation = oldRotation; + } + return FALSE; + } + /* + * Move the cursor back where it belongs; SwitchMode repositions it + */ + if (pScreen == miPointerCurrentScreen ()) + { + px = (px >= pScreen->width ? (pScreen->width - 1) : px); + py = (py >= pScreen->height ? (pScreen->height - 1) : py); + + xf86SetViewport(pScreen, px, py); + + (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); + } + + return TRUE; +} + +/* + * Wait until the screen is initialized before whacking the + * sizes around; otherwise the screen pixmap will be allocated + * at the current mode size rather than the maximum size + */ +static Bool +xf86RandRCreateScreenResources (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); +#if 0 + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + DisplayModePtr mode; +#endif + + pScreen->CreateScreenResources = randrp->CreateScreenResources; + if (!(*pScreen->CreateScreenResources) (pScreen)) + return FALSE; + +#if 0 + mode = scrp->currentMode; + if (mode) + xf86RandRSetMode (pScreen, mode, TRUE); +#endif + + return TRUE; +} + +/* + * Reset size back to original + */ +static Bool +xf86RandRCloseScreen (int index, ScreenPtr pScreen) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + scrp->virtualX = pScreen->width = randrp->virtualX; + scrp->virtualY = pScreen->height = randrp->virtualY; + scrp->currentMode = scrp->modes; + pScreen->CloseScreen = randrp->CloseScreen; + free(randrp); + dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, NULL); + return (*pScreen->CloseScreen) (index, pScreen); +} + +Rotation +xf86GetRotation(ScreenPtr pScreen) +{ + if (xf86RandRKey == NULL) + return RR_Rotate_0; + + return XF86RANDRINFO(pScreen)->rotation; +} + +/* Function to change RandR's idea of the virtual screen size */ +Bool +xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen, + int newvirtX, int newvirtY, int newmmWidth, int newmmHeight, + Bool resetMode) +{ + XF86RandRInfoPtr randrp; + + if (xf86RandRKey == NULL) + return FALSE; + + randrp = XF86RANDRINFO(pScreen); + if (randrp == NULL) + return FALSE; + + if (newvirtX > 0) + randrp->virtualX = newvirtX; + + if (newvirtY > 0) + randrp->virtualY = newvirtY; + + if (newmmWidth > 0) + randrp->mmWidth = newmmWidth; + + if (newmmHeight > 0) + randrp->mmHeight = newmmHeight; + + /* This is only for during server start */ + if (resetMode) { + return (xf86RandRSetMode(pScreen, + XF86SCRNINFO(pScreen)->currentMode, + TRUE, + pScreen->mmWidth, pScreen->mmHeight)); + } + + return TRUE; +} + +Bool +xf86RandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr rp; + XF86RandRInfoPtr randrp; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif + + xf86RandRKey = &xf86RandRKeyIndex; + + randrp = malloc(sizeof (XF86RandRInfoRec)); + if (!randrp) + return FALSE; + + if (!RRScreenInit (pScreen)) + { + free(randrp); + return FALSE; + } + rp = rrGetScrPriv(pScreen); + rp->rrGetInfo = xf86RandRGetInfo; + rp->rrSetConfig = xf86RandRSetConfig; + + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + randrp->mmWidth = pScreen->mmWidth; + randrp->mmHeight = pScreen->mmHeight; + + randrp->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = xf86RandRCreateScreenResources; + + randrp->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86RandRCloseScreen; + + randrp->rotation = RR_Rotate_0; + + dixSetPrivate(&pScreen->devPrivates, xf86RandRKey, randrp); + return TRUE; +} + + diff --git a/xorg-server/hw/xfree86/common/xf86ShowOpts.c b/xorg-server/hw/xfree86/common/xf86ShowOpts.c index 04a9a8b1c..77f156486 100644 --- a/xorg-server/hw/xfree86/common/xf86ShowOpts.c +++ b/xorg-server/hw/xfree86/common/xf86ShowOpts.c @@ -1,128 +1,128 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86ShopwOpts.c,v 3.80 2003/10/08 14:58:27 dawes Exp $ */ -/* - * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales. - * - * 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 Alan Hourihane not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Alan Hourihane makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. - * - * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL ALAN HOURIHANE 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. - * - * Author: Marcus Schaefer, ms@suse.de - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "os.h" -#ifdef XFree86LOADER -#include "loaderProcs.h" -#endif -#include "xf86.h" -#include "xf86Config.h" -#include "xf86_OSlib.h" -#include "xf86Priv.h" -/* #include "xf86PciData.h" */ -#define IN_XSERVER -#include "xf86Parser.h" -#include "xf86tokens.h" -#include "Configint.h" -#include "xf86DDC.h" -#if defined(__sparc__) && !defined(__OpenBSD__) -#include "xf86Bus.h" -#include "xf86Sbus.h" -#endif -#include "globals.h" - -static const char* -optionTypeToSting(OptionValueType type) -{ - switch (type) { - case OPTV_NONE: - return ""; - case OPTV_INTEGER: - return ""; - case OPTV_STRING: - return ""; - case OPTV_ANYSTR: - return ""; - case OPTV_REAL: - return ""; - case OPTV_BOOLEAN: - return ""; - case OPTV_FREQ: - return ""; - default: - return ""; - } -} - -void DoShowOptions (void) { - int i = 0; - char **vlist = 0; - char *pSymbol = 0; - XF86ModuleData *initData = 0; - if (! (vlist = xf86DriverlistFromCompile())) { - ErrorF("Missing output drivers\n"); - goto bail; - } - xf86LoadModules (vlist,0); - xfree (vlist); - for (i = 0; i < xf86NumDrivers; i++) { - if (xf86DriverList[i]->AvailableOptions) { - OptionInfoPtr pOption = (OptionInfoPtr)(*xf86DriverList[i]->AvailableOptions)(0,0); - if (! pOption) { - ErrorF ("(EE) Couldn't read option table for %s driver\n", - xf86DriverList[i]->driverName - ); - continue; - } - pSymbol = xalloc ( - strlen(xf86DriverList[i]->driverName) + strlen("ModuleData") + 1 - ); - strcpy (pSymbol, xf86DriverList[i]->driverName); - strcat (pSymbol, "ModuleData"); - initData = LoaderSymbol (pSymbol); - if (initData) { - XF86ModuleVersionInfo *vers = initData->vers; - OptionInfoPtr p; - ErrorF ("Driver[%d]:%s[%s] {\n", - i,xf86DriverList[i]->driverName,vers->vendor - ); - for (p = pOption; p->name != NULL; p++) { - const char *opttype = optionTypeToSting(p->type); - char *optname = xalloc(strlen(p->name) + 2 + 1); - if (!optname) { - continue; - } - sprintf(optname, "%s", p->name); - ErrorF ("\t%s:%s\n", optname,opttype); - } - ErrorF ("}\n"); - } - } - } - bail: - OsCleanup (TRUE); - AbortDDX (); - fflush (stderr); - exit (0); -} +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86ShopwOpts.c,v 3.80 2003/10/08 14:58:27 dawes Exp $ */ +/* + * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Author: Marcus Schaefer, ms@suse.de + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "os.h" +#ifdef XFree86LOADER +#include "loaderProcs.h" +#endif +#include "xf86.h" +#include "xf86Config.h" +#include "xf86_OSlib.h" +#include "xf86Priv.h" +/* #include "xf86PciData.h" */ +#define IN_XSERVER +#include "xf86Parser.h" +#include "xf86tokens.h" +#include "Configint.h" +#include "xf86DDC.h" +#if defined(__sparc__) && !defined(__OpenBSD__) +#include "xf86Bus.h" +#include "xf86Sbus.h" +#endif +#include "globals.h" + +static const char* +optionTypeToSting(OptionValueType type) +{ + switch (type) { + case OPTV_NONE: + return ""; + case OPTV_INTEGER: + return ""; + case OPTV_STRING: + return ""; + case OPTV_ANYSTR: + return ""; + case OPTV_REAL: + return ""; + case OPTV_BOOLEAN: + return ""; + case OPTV_FREQ: + return ""; + default: + return ""; + } +} + +void DoShowOptions (void) { + int i = 0; + char **vlist = 0; + char *pSymbol = 0; + XF86ModuleData *initData = 0; + if (! (vlist = xf86DriverlistFromCompile())) { + ErrorF("Missing output drivers\n"); + goto bail; + } + xf86LoadModules (vlist,0); + free(vlist); + for (i = 0; i < xf86NumDrivers; i++) { + if (xf86DriverList[i]->AvailableOptions) { + OptionInfoPtr pOption = (OptionInfoPtr)(*xf86DriverList[i]->AvailableOptions)(0,0); + if (! pOption) { + ErrorF ("(EE) Couldn't read option table for %s driver\n", + xf86DriverList[i]->driverName + ); + continue; + } + pSymbol = malloc( + strlen(xf86DriverList[i]->driverName) + strlen("ModuleData") + 1 + ); + strcpy (pSymbol, xf86DriverList[i]->driverName); + strcat (pSymbol, "ModuleData"); + initData = LoaderSymbol (pSymbol); + if (initData) { + XF86ModuleVersionInfo *vers = initData->vers; + OptionInfoPtr p; + ErrorF ("Driver[%d]:%s[%s] {\n", + i,xf86DriverList[i]->driverName,vers->vendor + ); + for (p = pOption; p->name != NULL; p++) { + const char *opttype = optionTypeToSting(p->type); + char *optname = malloc(strlen(p->name) + 2 + 1); + if (!optname) { + continue; + } + sprintf(optname, "%s", p->name); + ErrorF ("\t%s:%s\n", optname,opttype); + } + ErrorF ("}\n"); + } + } + } + bail: + OsCleanup (TRUE); + AbortDDX (); + fflush (stderr); + exit (0); +} diff --git a/xorg-server/hw/xfree86/common/xf86VGAarbiter.c b/xorg-server/hw/xfree86/common/xf86VGAarbiter.c index 52a8b9a60..ac44c5e67 100644 --- a/xorg-server/hw/xfree86/common/xf86VGAarbiter.c +++ b/xorg-server/hw/xfree86/common/xf86VGAarbiter.c @@ -1,1101 +1,1101 @@ -/* - * This code was stolen from RAC and adapted to control the legacy vga - * interface. - * - * - * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "xorg-config.h" - -#include "xf86VGAarbiter.h" - -#ifdef HAVE_PCI_DEVICE_VGAARB_INIT -#include "xf86VGAarbiterPriv.h" -#include "xf86Bus.h" -#include "xf86Priv.h" -#include "pciaccess.h" - - -static GCFuncs VGAarbiterGCFuncs = { - VGAarbiterValidateGC, VGAarbiterChangeGC, VGAarbiterCopyGC, - VGAarbiterDestroyGC, VGAarbiterChangeClip, VGAarbiterDestroyClip, - VGAarbiterCopyClip -}; - -static GCOps VGAarbiterGCOps = { - VGAarbiterFillSpans, VGAarbiterSetSpans, VGAarbiterPutImage, - VGAarbiterCopyArea, VGAarbiterCopyPlane, VGAarbiterPolyPoint, - VGAarbiterPolylines, VGAarbiterPolySegment, VGAarbiterPolyRectangle, - VGAarbiterPolyArc, VGAarbiterFillPolygon, VGAarbiterPolyFillRect, - VGAarbiterPolyFillArc, VGAarbiterPolyText8, VGAarbiterPolyText16, - VGAarbiterImageText8, VGAarbiterImageText16, VGAarbiterImageGlyphBlt, - VGAarbiterPolyGlyphBlt, VGAarbiterPushPixels, - {NULL} /* devPrivate */ -}; - -static miPointerSpriteFuncRec VGAarbiterSpriteFuncs = { - VGAarbiterSpriteRealizeCursor, VGAarbiterSpriteUnrealizeCursor, - VGAarbiterSpriteSetCursor, VGAarbiterSpriteMoveCursor, - VGAarbiterDeviceCursorInitialize, VGAarbiterDeviceCursorCleanup -}; - -static int VGAarbiterKeyIndex; -static DevPrivateKey VGAarbiterScreenKey = &VGAarbiterKeyIndex; -static int VGAarbiterGCIndex; -static DevPrivateKey VGAarbiterGCKey = &VGAarbiterGCIndex; - -static int vga_no_arb = 0; -void -xf86VGAarbiterInit(void) -{ - if (pci_device_vgaarb_init() != 0) { - vga_no_arb = 1; - xf86Msg(X_WARNING, "VGA arbiter: cannot open kernel arbiter, no multi-card support\n"); - } -} - -void -xf86VGAarbiterFini(void) -{ - if (vga_no_arb) - return; - pci_device_vgaarb_fini(); -} - -void -xf86VGAarbiterLock(ScrnInfoPtr pScrn) -{ - if (vga_no_arb) - return; - pci_device_vgaarb_set_target(pScrn->vgaDev); - pci_device_vgaarb_lock(); -} - -void -xf86VGAarbiterUnlock(ScrnInfoPtr pScrn) -{ - if (vga_no_arb) - return; - pci_device_vgaarb_unlock(); -} - -Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen) -{ - int vga_count; - int rsrc_decodes; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (vga_no_arb) - return TRUE; - - pci_device_vgaarb_get_info(pScrn->vgaDev, &vga_count, &rsrc_decodes); - if (vga_count > 1) { - if (rsrc_decodes) { - return FALSE; - } - } - return TRUE; -} - -void -xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn) -{ - struct pci_device *dev; - EntityPtr pEnt; - - if (vga_no_arb) - return; - - pEnt = xf86Entities[pScrn->entityList[0]]; - if (pEnt->bus.type != BUS_PCI) - return; - - dev = pEnt->bus.id.pci; - pScrn->vgaDev = dev; -} - -void -xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn) -{ - if (vga_no_arb) - return; - pci_device_vgaarb_decodes(VGA_ARB_RSRC_LEGACY_MEM | VGA_ARB_RSRC_LEGACY_IO); -} - -Bool -xf86VGAarbiterWrapFunctions(void) -{ - ScrnInfoPtr pScrn; - VGAarbiterScreenPtr pScreenPriv; - miPointerScreenPtr PointPriv; - PictureScreenPtr ps; - ScreenPtr pScreen; - int vga_count, i; - - if (vga_no_arb) - return FALSE; - - /* - * we need to wrap the arbiter if we have more than - * one VGA card - hotplug cries. - */ - pci_device_vgaarb_get_info(NULL, &vga_count, NULL); - if (vga_count < 2 || !xf86Screens) - return FALSE; - - xf86Msg(X_INFO,"Found %d VGA devices: arbiter wrapping enabled\n", - vga_count); - - for (i = 0; i < xf86NumScreens; i++) { - pScreen = xf86Screens[i]->pScreen; - ps = GetPictureScreenIfSet(pScreen); - pScrn = xf86Screens[pScreen->myNum]; - PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); - - if (!dixRequestPrivate(VGAarbiterGCKey, sizeof(VGAarbiterGCRec))) - return FALSE; - - if (!(pScreenPriv = xalloc(sizeof(VGAarbiterScreenRec)))) - return FALSE; - - dixSetPrivate(&pScreen->devPrivates, VGAarbiterScreenKey, pScreenPriv); - - WRAP_SCREEN(CloseScreen, VGAarbiterCloseScreen); - WRAP_SCREEN(SaveScreen, VGAarbiterSaveScreen); - WRAP_SCREEN(WakeupHandler, VGAarbiterWakeupHandler); - WRAP_SCREEN(BlockHandler, VGAarbiterBlockHandler); - WRAP_SCREEN(CreateGC, VGAarbiterCreateGC); - WRAP_SCREEN(GetImage, VGAarbiterGetImage); - WRAP_SCREEN(GetSpans, VGAarbiterGetSpans); - WRAP_SCREEN(SourceValidate, VGAarbiterSourceValidate); - WRAP_SCREEN(CopyWindow, VGAarbiterCopyWindow); - WRAP_SCREEN(ClearToBackground, VGAarbiterClearToBackground); - WRAP_SCREEN(CreatePixmap, VGAarbiterCreatePixmap); - WRAP_SCREEN(StoreColors, VGAarbiterStoreColors); - WRAP_SCREEN(DisplayCursor, VGAarbiterDisplayCursor); - WRAP_SCREEN(RealizeCursor, VGAarbiterRealizeCursor); - WRAP_SCREEN(UnrealizeCursor, VGAarbiterUnrealizeCursor); - WRAP_SCREEN(RecolorCursor, VGAarbiterRecolorCursor); - WRAP_SCREEN(SetCursorPosition, VGAarbiterSetCursorPosition); - WRAP_PICT(Composite,VGAarbiterComposite); - WRAP_PICT(Glyphs,VGAarbiterGlyphs); - WRAP_PICT(CompositeRects,VGAarbiterCompositeRects); - WRAP_SCREEN_INFO(AdjustFrame, VGAarbiterAdjustFrame); - WRAP_SCREEN_INFO(SwitchMode, VGAarbiterSwitchMode); - WRAP_SCREEN_INFO(EnterVT, VGAarbiterEnterVT); - WRAP_SCREEN_INFO(LeaveVT, VGAarbiterLeaveVT); - WRAP_SCREEN_INFO(FreeScreen, VGAarbiterFreeScreen); - WRAP_SPRITE; - } - - return TRUE; -} - -/* Screen funcs */ -static Bool -VGAarbiterCloseScreen (int i, ScreenPtr pScreen) -{ - Bool val; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, VGAarbiterScreenKey); - miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, miPointerScreenKey); - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - - UNWRAP_SCREEN(CreateGC); - UNWRAP_SCREEN(CloseScreen); - UNWRAP_SCREEN(GetImage); - UNWRAP_SCREEN(GetSpans); - UNWRAP_SCREEN(SourceValidate); - UNWRAP_SCREEN(CopyWindow); - UNWRAP_SCREEN(ClearToBackground); - UNWRAP_SCREEN(SaveScreen); - UNWRAP_SCREEN(StoreColors); - UNWRAP_SCREEN(DisplayCursor); - UNWRAP_SCREEN(RealizeCursor); - UNWRAP_SCREEN(UnrealizeCursor); - UNWRAP_SCREEN(RecolorCursor); - UNWRAP_SCREEN(SetCursorPosition); - UNWRAP_PICT(Composite); - UNWRAP_PICT(Glyphs); - UNWRAP_PICT(CompositeRects); - UNWRAP_SCREEN_INFO(AdjustFrame); - UNWRAP_SCREEN_INFO(SwitchMode); - UNWRAP_SCREEN_INFO(EnterVT); - UNWRAP_SCREEN_INFO(LeaveVT); - UNWRAP_SCREEN_INFO(FreeScreen); - UNWRAP_SPRITE; - - xfree ((pointer) pScreenPriv); - xf86VGAarbiterLock(xf86Screens[i]); - val = (*pScreen->CloseScreen) (i, pScreen); - xf86VGAarbiterUnlock(xf86Screens[i]); - return val; -} - -static void -VGAarbiterBlockHandler(int i, - pointer blockData, pointer pTimeout, pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[i]; - SCREEN_PROLOG(BlockHandler); - VGAGet(); - pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); - VGAPut(); - SCREEN_EPILOG(BlockHandler, VGAarbiterBlockHandler); -} - -static void -VGAarbiterWakeupHandler(int i, pointer blockData, unsigned long result, pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[i]; - SCREEN_PROLOG(WakeupHandler); - VGAGet(); - pScreen->WakeupHandler(i, blockData, result, pReadmask); - VGAPut(); - SCREEN_EPILOG(WakeupHandler, VGAarbiterWakeupHandler); -} - -static void -VGAarbiterGetImage ( - DrawablePtr pDrawable, - int sx, int sy, int w, int h, - unsigned int format, - unsigned long planemask, - char *pdstLine - ) -{ - ScreenPtr pScreen = pDrawable->pScreen; - SCREEN_PROLOG(GetImage); -// if (xf86Screens[pScreen->myNum]->vtSema) { - VGAGet(); -// } - (*pScreen->GetImage) (pDrawable, sx, sy, w, h, - format, planemask, pdstLine); - VGAPut(); - SCREEN_EPILOG (GetImage, VGAarbiterGetImage); -} - -static void -VGAarbiterGetSpans ( - DrawablePtr pDrawable, - int wMax, - DDXPointPtr ppt, - int *pwidth, - int nspans, - char *pdstStart - ) -{ - ScreenPtr pScreen = pDrawable->pScreen; - - SCREEN_PROLOG (GetSpans); - VGAGet(); - (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); - VGAPut(); - SCREEN_EPILOG (GetSpans, VGAarbiterGetSpans); -} - -static void -VGAarbiterSourceValidate ( - DrawablePtr pDrawable, - int x, int y, int width, int height ) -{ - ScreenPtr pScreen = pDrawable->pScreen; - SCREEN_PROLOG (SourceValidate); - VGAGet(); - if (pScreen->SourceValidate) - (*pScreen->SourceValidate) (pDrawable, x, y, width, height); - VGAPut(); - SCREEN_EPILOG (SourceValidate, VGAarbiterSourceValidate); -} - -static void -VGAarbiterCopyWindow( - WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc ) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - - SCREEN_PROLOG (CopyWindow); - VGAGet(); - (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); - VGAPut(); - SCREEN_EPILOG (CopyWindow, VGAarbiterCopyWindow); -} - -static void -VGAarbiterClearToBackground ( - WindowPtr pWin, - int x, int y, - int w, int h, - Bool generateExposures ) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - - SCREEN_PROLOG ( ClearToBackground); - VGAGet(); - (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); - VGAPut(); - SCREEN_EPILOG (ClearToBackground, VGAarbiterClearToBackground); -} - -static PixmapPtr -VGAarbiterCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint) -{ - PixmapPtr pPix; - - SCREEN_PROLOG ( CreatePixmap); - VGAGet(); - pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint); - VGAPut(); - SCREEN_EPILOG (CreatePixmap, VGAarbiterCreatePixmap); - - return pPix; -} - -static Bool -VGAarbiterSaveScreen(ScreenPtr pScreen, Bool unblank) -{ - Bool val; - - SCREEN_PROLOG (SaveScreen); - VGAGet(); - val = (*pScreen->SaveScreen) (pScreen, unblank); - VGAPut(); - SCREEN_EPILOG (SaveScreen, VGAarbiterSaveScreen); - - return val; -} - -static void -VGAarbiterStoreColors ( - ColormapPtr pmap, - int ndef, - xColorItem *pdefs) -{ - ScreenPtr pScreen = pmap->pScreen; - - SCREEN_PROLOG (StoreColors); - VGAGet(); - (*pScreen->StoreColors) (pmap,ndef,pdefs); - VGAPut(); - SCREEN_EPILOG ( StoreColors, VGAarbiterStoreColors); -} - -static void -VGAarbiterRecolorCursor ( - DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCurs, - Bool displayed - ) -{ - SCREEN_PROLOG (RecolorCursor); - VGAGet(); - (*pScreen->RecolorCursor) (pDev, pScreen, pCurs, displayed); - VGAPut(); - SCREEN_EPILOG ( RecolorCursor, VGAarbiterRecolorCursor); -} - -static Bool -VGAarbiterRealizeCursor ( - DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor - ) -{ - Bool val; - - SCREEN_PROLOG (RealizeCursor); - VGAGet(); - val = (*pScreen->RealizeCursor) (pDev, pScreen,pCursor); - VGAPut(); - SCREEN_EPILOG ( RealizeCursor, VGAarbiterRealizeCursor); - return val; -} - -static Bool -VGAarbiterUnrealizeCursor ( - DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor - ) -{ - Bool val; - - SCREEN_PROLOG (UnrealizeCursor); - VGAGet(); - val = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor); - VGAPut(); - SCREEN_EPILOG ( UnrealizeCursor, VGAarbiterUnrealizeCursor); - return val; -} - -static Bool -VGAarbiterDisplayCursor ( - DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor - ) -{ - Bool val; - - SCREEN_PROLOG (DisplayCursor); - VGAGet(); - val = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); - VGAPut(); - SCREEN_EPILOG ( DisplayCursor, VGAarbiterDisplayCursor); - return val; -} - -static Bool -VGAarbiterSetCursorPosition ( - DeviceIntPtr pDev, - ScreenPtr pScreen, - int x, int y, - Bool generateEvent) -{ - Bool val; - - SCREEN_PROLOG (SetCursorPosition); - VGAGet(); - val = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); - VGAPut(); - SCREEN_EPILOG ( SetCursorPosition, VGAarbiterSetCursorPosition); - return val; -} - -static void -VGAarbiterAdjustFrame(int index, int x, int y, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, VGAarbiterScreenKey); - - VGAGet(); - (*pScreenPriv->AdjustFrame)(index, x, y, flags); - VGAPut(); -} - -static Bool -VGAarbiterSwitchMode(int index, DisplayModePtr mode, int flags) -{ - Bool val; - ScreenPtr pScreen = screenInfo.screens[index]; - VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, VGAarbiterScreenKey); - - VGAGet(); - val = (*pScreenPriv->SwitchMode)(index, mode, flags); - VGAPut(); - return val; -} - -static Bool -VGAarbiterEnterVT(int index, int flags) -{ - Bool val; - ScreenPtr pScreen = screenInfo.screens[index]; - VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, VGAarbiterScreenKey); - - VGAGet(); - val = (*pScreenPriv->EnterVT)(index, flags); - VGAPut(); - return val; -} - -static void -VGAarbiterLeaveVT(int index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, VGAarbiterScreenKey); - - VGAGet(); - (*pScreenPriv->LeaveVT)(index, flags); - VGAPut(); -} - -static void -VGAarbiterFreeScreen(int index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, VGAarbiterScreenKey); - - VGAGet(); - (*pScreenPriv->FreeScreen)(index, flags); - VGAPut(); -} - -static Bool -VGAarbiterCreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - VGAarbiterGCPtr pGCPriv = (VGAarbiterGCPtr)dixLookupPrivate(&pGC->devPrivates, VGAarbiterGCKey); - Bool ret; - - SCREEN_PROLOG(CreateGC); - VGAGet(); - ret = (*pScreen->CreateGC)(pGC); - VGAPut(); - GC_WRAP(pGC); - SCREEN_EPILOG(CreateGC,VGAarbiterCreateGC); - - return ret; -} - -/* GC funcs */ -static void -VGAarbiterValidateGC( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw ) -{ - GC_UNWRAP(pGC); - (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); - GC_WRAP(pGC); -} - - -static void -VGAarbiterDestroyGC(GCPtr pGC) -{ - GC_UNWRAP (pGC); - (*pGC->funcs->DestroyGC)(pGC); - GC_WRAP (pGC); -} - -static void -VGAarbiterChangeGC ( - GCPtr pGC, - unsigned long mask) -{ - GC_UNWRAP (pGC); - (*pGC->funcs->ChangeGC) (pGC, mask); - GC_WRAP (pGC); -} - -static void -VGAarbiterCopyGC ( - GCPtr pGCSrc, - unsigned long mask, - GCPtr pGCDst) -{ - GC_UNWRAP (pGCDst); - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - GC_WRAP (pGCDst); -} - -static void -VGAarbiterChangeClip ( - GCPtr pGC, - int type, - pointer pvalue, - int nrects ) -{ - GC_UNWRAP (pGC); - (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); - GC_WRAP (pGC); -} - -static void -VGAarbiterCopyClip(GCPtr pgcDst, GCPtr pgcSrc) -{ - GC_UNWRAP (pgcDst); - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - GC_WRAP (pgcDst); -} - -static void -VGAarbiterDestroyClip(GCPtr pGC) -{ - GC_UNWRAP (pGC); - (* pGC->funcs->DestroyClip)(pGC); - GC_WRAP (pGC); -} - -/* GC Ops */ -static void -VGAarbiterFillSpans( - DrawablePtr pDraw, - GC *pGC, - int nInit, - DDXPointPtr pptInit, - int *pwidthInit, - int fSorted ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterSetSpans( - DrawablePtr pDraw, - GCPtr pGC, - char *pcharsrc, - register DDXPointPtr ppt, - int *pwidth, - int nspans, - int fSorted ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterPutImage( - DrawablePtr pDraw, - GCPtr pGC, - int depth, - int x, int y, int w, int h, - int leftPad, - int format, - char *pImage ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, - leftPad, format, pImage); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static RegionPtr -VGAarbiterCopyArea( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty ) -{ - RegionPtr ret; - - GC_UNWRAP(pGC); - VGAGet_GC(); - ret = (*pGC->ops->CopyArea)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty); - VGAPut_GC(); - GC_WRAP(pGC); - return ret; -} - -static RegionPtr -VGAarbiterCopyPlane( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty, - unsigned long bitPlane ) -{ - RegionPtr ret; - - GC_UNWRAP(pGC); - VGAGet_GC(); - ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, srcx, srcy, - width, height, dstx, dsty, bitPlane); - VGAPut_GC(); - GC_WRAP(pGC); - return ret; -} - -static void -VGAarbiterPolyPoint( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int npt, - xPoint *pptInit ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit); - VGAPut_GC(); - GC_WRAP(pGC); -} - - -static void -VGAarbiterPolylines( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr pptInit ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterPolySegment( - DrawablePtr pDraw, - GCPtr pGC, - int nseg, - xSegment *pSeg ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterPolyRectangle( - DrawablePtr pDraw, - GCPtr pGC, - int nRectsInit, - xRectangle *pRectsInit ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterPolyArc( - DrawablePtr pDraw, - GCPtr pGC, - int narcs, - xArc *parcs ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterFillPolygon( - DrawablePtr pDraw, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterPolyFillRect( - DrawablePtr pDraw, - GCPtr pGC, - int nrectFill, - xRectangle *prectInit) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PolyFillRect)(pDraw, pGC, nrectFill, prectInit); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterPolyFillArc( - DrawablePtr pDraw, - GCPtr pGC, - int narcs, - xArc *parcs ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static int -VGAarbiterPolyText8( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - char *chars ) -{ - int ret; - - GC_UNWRAP(pGC); - VGAGet_GC(); - ret = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars); - VGAPut_GC(); - GC_WRAP(pGC); - return ret; -} - -static int -VGAarbiterPolyText16( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - unsigned short *chars ) -{ - int ret; - - GC_UNWRAP(pGC); - VGAGet_GC(); - ret = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars); - VGAPut_GC(); - GC_WRAP(pGC); - return ret; -} - -static void -VGAarbiterImageText8( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - char *chars ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterImageText16( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - unsigned short *chars ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars); - VGAPut_GC(); - GC_WRAP(pGC); -} - - -static void -VGAarbiterImageGlyphBlt( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, xInit, yInit, - nglyph, ppci, pglyphBase); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterPolyGlyphBlt( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, xInit, yInit, - nglyph, ppci, pglyphBase); - VGAPut_GC(); - GC_WRAP(pGC); -} - -static void -VGAarbiterPushPixels( - GCPtr pGC, - PixmapPtr pBitMap, - DrawablePtr pDraw, - int dx, int dy, int xOrg, int yOrg ) -{ - GC_UNWRAP(pGC); - VGAGet_GC(); - (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); - VGAPut_GC(); - GC_WRAP(pGC); -} - - -/* miSpriteFuncs */ -static Bool -VGAarbiterSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur) -{ - Bool val; - SPRITE_PROLOG; - VGAGet(); - val = PointPriv->spriteFuncs->RealizeCursor(pDev, pScreen, pCur); - VGAPut(); - SPRITE_EPILOG; - return val; -} - -static Bool -VGAarbiterSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur) -{ - Bool val; - SPRITE_PROLOG; - VGAGet(); - val = PointPriv->spriteFuncs->UnrealizeCursor(pDev, pScreen, pCur); - VGAPut(); - SPRITE_EPILOG; - return val; -} - -static void -VGAarbiterSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur, int x, int y) -{ - SPRITE_PROLOG; - VGAGet(); - PointPriv->spriteFuncs->SetCursor(pDev, pScreen, pCur, x, y); - VGAPut(); - SPRITE_EPILOG; -} - -static void -VGAarbiterSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - SPRITE_PROLOG; - VGAGet(); - PointPriv->spriteFuncs->MoveCursor(pDev, pScreen, x, y); - VGAPut(); - SPRITE_EPILOG; -} - -static Bool -VGAarbiterDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - Bool val; - SPRITE_PROLOG; - VGAGet(); - val = PointPriv->spriteFuncs->DeviceCursorInitialize(pDev, pScreen); - VGAPut(); - SPRITE_EPILOG; - return val; -} - -static void -VGAarbiterDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - SPRITE_PROLOG; - VGAGet(); - PointPriv->spriteFuncs->DeviceCursorCleanup(pDev, pScreen); - VGAPut(); - SPRITE_EPILOG; -} - -static void -VGAarbiterComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, - PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, - INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, - CARD16 height) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - - PICTURE_PROLOGUE(Composite); - - VGAGet(); - (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, - yDst, width, height); - VGAPut(); - PICTURE_EPILOGUE(Composite, VGAarbiterComposite); -} - -static void -VGAarbiterGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, - GlyphListPtr list, GlyphPtr *glyphs) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - - PICTURE_PROLOGUE(Glyphs); - - VGAGet(); - (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); - VGAPut(); - PICTURE_EPILOGUE (Glyphs, VGAarbiterGlyphs); -} - -static void -VGAarbiterCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color, int nRect, - xRectangle *rects) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - - PICTURE_PROLOGUE(CompositeRects); - - VGAGet(); - (*ps->CompositeRects)(op, pDst, color, nRect, rects); - VGAPut(); - PICTURE_EPILOGUE (CompositeRects, VGAarbiterCompositeRects); -} -#else -/* dummy functions */ -void xf86VGAarbiterInit(void) {} -void xf86VGAarbiterFini(void) {} - -void xf86VGAarbiterLock(ScrnInfoPtr pScrn) {} -void xf86VGAarbiterUnlock(ScrnInfoPtr pScrn) {} -Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen) { return TRUE; } -void xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn) {} -void xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn) {} -Bool xf86VGAarbiterWrapFunctions(void) { return FALSE; } - -#endif +/* + * This code was stolen from RAC and adapted to control the legacy vga + * interface. + * + * + * Copyright (c) 2007 Paulo R. Zanoni, Tiago Vignatti + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "xorg-config.h" + +#include "xf86VGAarbiter.h" + +#ifdef HAVE_PCI_DEVICE_VGAARB_INIT +#include "xf86VGAarbiterPriv.h" +#include "xf86Bus.h" +#include "xf86Priv.h" +#include "pciaccess.h" + + +static GCFuncs VGAarbiterGCFuncs = { + VGAarbiterValidateGC, VGAarbiterChangeGC, VGAarbiterCopyGC, + VGAarbiterDestroyGC, VGAarbiterChangeClip, VGAarbiterDestroyClip, + VGAarbiterCopyClip +}; + +static GCOps VGAarbiterGCOps = { + VGAarbiterFillSpans, VGAarbiterSetSpans, VGAarbiterPutImage, + VGAarbiterCopyArea, VGAarbiterCopyPlane, VGAarbiterPolyPoint, + VGAarbiterPolylines, VGAarbiterPolySegment, VGAarbiterPolyRectangle, + VGAarbiterPolyArc, VGAarbiterFillPolygon, VGAarbiterPolyFillRect, + VGAarbiterPolyFillArc, VGAarbiterPolyText8, VGAarbiterPolyText16, + VGAarbiterImageText8, VGAarbiterImageText16, VGAarbiterImageGlyphBlt, + VGAarbiterPolyGlyphBlt, VGAarbiterPushPixels, + {NULL} /* devPrivate */ +}; + +static miPointerSpriteFuncRec VGAarbiterSpriteFuncs = { + VGAarbiterSpriteRealizeCursor, VGAarbiterSpriteUnrealizeCursor, + VGAarbiterSpriteSetCursor, VGAarbiterSpriteMoveCursor, + VGAarbiterDeviceCursorInitialize, VGAarbiterDeviceCursorCleanup +}; + +static int VGAarbiterKeyIndex; +static DevPrivateKey VGAarbiterScreenKey = &VGAarbiterKeyIndex; +static int VGAarbiterGCIndex; +static DevPrivateKey VGAarbiterGCKey = &VGAarbiterGCIndex; + +static int vga_no_arb = 0; +void +xf86VGAarbiterInit(void) +{ + if (pci_device_vgaarb_init() != 0) { + vga_no_arb = 1; + xf86Msg(X_WARNING, "VGA arbiter: cannot open kernel arbiter, no multi-card support\n"); + } +} + +void +xf86VGAarbiterFini(void) +{ + if (vga_no_arb) + return; + pci_device_vgaarb_fini(); +} + +void +xf86VGAarbiterLock(ScrnInfoPtr pScrn) +{ + if (vga_no_arb) + return; + pci_device_vgaarb_set_target(pScrn->vgaDev); + pci_device_vgaarb_lock(); +} + +void +xf86VGAarbiterUnlock(ScrnInfoPtr pScrn) +{ + if (vga_no_arb) + return; + pci_device_vgaarb_unlock(); +} + +Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen) +{ + int vga_count; + int rsrc_decodes; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (vga_no_arb) + return TRUE; + + pci_device_vgaarb_get_info(pScrn->vgaDev, &vga_count, &rsrc_decodes); + if (vga_count > 1) { + if (rsrc_decodes) { + return FALSE; + } + } + return TRUE; +} + +void +xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn) +{ + struct pci_device *dev; + EntityPtr pEnt; + + if (vga_no_arb) + return; + + pEnt = xf86Entities[pScrn->entityList[0]]; + if (pEnt->bus.type != BUS_PCI) + return; + + dev = pEnt->bus.id.pci; + pScrn->vgaDev = dev; +} + +void +xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn) +{ + if (vga_no_arb) + return; + pci_device_vgaarb_decodes(VGA_ARB_RSRC_LEGACY_MEM | VGA_ARB_RSRC_LEGACY_IO); +} + +Bool +xf86VGAarbiterWrapFunctions(void) +{ + ScrnInfoPtr pScrn; + VGAarbiterScreenPtr pScreenPriv; + miPointerScreenPtr PointPriv; + PictureScreenPtr ps; + ScreenPtr pScreen; + int vga_count, i; + + if (vga_no_arb) + return FALSE; + + /* + * we need to wrap the arbiter if we have more than + * one VGA card - hotplug cries. + */ + pci_device_vgaarb_get_info(NULL, &vga_count, NULL); + if (vga_count < 2 || !xf86Screens) + return FALSE; + + xf86Msg(X_INFO,"Found %d VGA devices: arbiter wrapping enabled\n", + vga_count); + + for (i = 0; i < xf86NumScreens; i++) { + pScreen = xf86Screens[i]->pScreen; + ps = GetPictureScreenIfSet(pScreen); + pScrn = xf86Screens[pScreen->myNum]; + PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + + if (!dixRequestPrivate(VGAarbiterGCKey, sizeof(VGAarbiterGCRec))) + return FALSE; + + if (!(pScreenPriv = malloc(sizeof(VGAarbiterScreenRec)))) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, VGAarbiterScreenKey, pScreenPriv); + + WRAP_SCREEN(CloseScreen, VGAarbiterCloseScreen); + WRAP_SCREEN(SaveScreen, VGAarbiterSaveScreen); + WRAP_SCREEN(WakeupHandler, VGAarbiterWakeupHandler); + WRAP_SCREEN(BlockHandler, VGAarbiterBlockHandler); + WRAP_SCREEN(CreateGC, VGAarbiterCreateGC); + WRAP_SCREEN(GetImage, VGAarbiterGetImage); + WRAP_SCREEN(GetSpans, VGAarbiterGetSpans); + WRAP_SCREEN(SourceValidate, VGAarbiterSourceValidate); + WRAP_SCREEN(CopyWindow, VGAarbiterCopyWindow); + WRAP_SCREEN(ClearToBackground, VGAarbiterClearToBackground); + WRAP_SCREEN(CreatePixmap, VGAarbiterCreatePixmap); + WRAP_SCREEN(StoreColors, VGAarbiterStoreColors); + WRAP_SCREEN(DisplayCursor, VGAarbiterDisplayCursor); + WRAP_SCREEN(RealizeCursor, VGAarbiterRealizeCursor); + WRAP_SCREEN(UnrealizeCursor, VGAarbiterUnrealizeCursor); + WRAP_SCREEN(RecolorCursor, VGAarbiterRecolorCursor); + WRAP_SCREEN(SetCursorPosition, VGAarbiterSetCursorPosition); + WRAP_PICT(Composite,VGAarbiterComposite); + WRAP_PICT(Glyphs,VGAarbiterGlyphs); + WRAP_PICT(CompositeRects,VGAarbiterCompositeRects); + WRAP_SCREEN_INFO(AdjustFrame, VGAarbiterAdjustFrame); + WRAP_SCREEN_INFO(SwitchMode, VGAarbiterSwitchMode); + WRAP_SCREEN_INFO(EnterVT, VGAarbiterEnterVT); + WRAP_SCREEN_INFO(LeaveVT, VGAarbiterLeaveVT); + WRAP_SCREEN_INFO(FreeScreen, VGAarbiterFreeScreen); + WRAP_SPRITE; + } + + return TRUE; +} + +/* Screen funcs */ +static Bool +VGAarbiterCloseScreen (int i, ScreenPtr pScreen) +{ + Bool val; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, miPointerScreenKey); + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + UNWRAP_SCREEN(CreateGC); + UNWRAP_SCREEN(CloseScreen); + UNWRAP_SCREEN(GetImage); + UNWRAP_SCREEN(GetSpans); + UNWRAP_SCREEN(SourceValidate); + UNWRAP_SCREEN(CopyWindow); + UNWRAP_SCREEN(ClearToBackground); + UNWRAP_SCREEN(SaveScreen); + UNWRAP_SCREEN(StoreColors); + UNWRAP_SCREEN(DisplayCursor); + UNWRAP_SCREEN(RealizeCursor); + UNWRAP_SCREEN(UnrealizeCursor); + UNWRAP_SCREEN(RecolorCursor); + UNWRAP_SCREEN(SetCursorPosition); + UNWRAP_PICT(Composite); + UNWRAP_PICT(Glyphs); + UNWRAP_PICT(CompositeRects); + UNWRAP_SCREEN_INFO(AdjustFrame); + UNWRAP_SCREEN_INFO(SwitchMode); + UNWRAP_SCREEN_INFO(EnterVT); + UNWRAP_SCREEN_INFO(LeaveVT); + UNWRAP_SCREEN_INFO(FreeScreen); + UNWRAP_SPRITE; + + free((pointer) pScreenPriv); + xf86VGAarbiterLock(xf86Screens[i]); + val = (*pScreen->CloseScreen) (i, pScreen); + xf86VGAarbiterUnlock(xf86Screens[i]); + return val; +} + +static void +VGAarbiterBlockHandler(int i, + pointer blockData, pointer pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + SCREEN_PROLOG(BlockHandler); + VGAGet(); + pScreen->BlockHandler(i, blockData, pTimeout, pReadmask); + VGAPut(); + SCREEN_EPILOG(BlockHandler, VGAarbiterBlockHandler); +} + +static void +VGAarbiterWakeupHandler(int i, pointer blockData, unsigned long result, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + SCREEN_PROLOG(WakeupHandler); + VGAGet(); + pScreen->WakeupHandler(i, blockData, result, pReadmask); + VGAPut(); + SCREEN_EPILOG(WakeupHandler, VGAarbiterWakeupHandler); +} + +static void +VGAarbiterGetImage ( + DrawablePtr pDrawable, + int sx, int sy, int w, int h, + unsigned int format, + unsigned long planemask, + char *pdstLine + ) +{ + ScreenPtr pScreen = pDrawable->pScreen; + SCREEN_PROLOG(GetImage); +// if (xf86Screens[pScreen->myNum]->vtSema) { + VGAGet(); +// } + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, + format, planemask, pdstLine); + VGAPut(); + SCREEN_EPILOG (GetImage, VGAarbiterGetImage); +} + +static void +VGAarbiterGetSpans ( + DrawablePtr pDrawable, + int wMax, + DDXPointPtr ppt, + int *pwidth, + int nspans, + char *pdstStart + ) +{ + ScreenPtr pScreen = pDrawable->pScreen; + + SCREEN_PROLOG (GetSpans); + VGAGet(); + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + VGAPut(); + SCREEN_EPILOG (GetSpans, VGAarbiterGetSpans); +} + +static void +VGAarbiterSourceValidate ( + DrawablePtr pDrawable, + int x, int y, int width, int height ) +{ + ScreenPtr pScreen = pDrawable->pScreen; + SCREEN_PROLOG (SourceValidate); + VGAGet(); + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height); + VGAPut(); + SCREEN_EPILOG (SourceValidate, VGAarbiterSourceValidate); +} + +static void +VGAarbiterCopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc ) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOG (CopyWindow); + VGAGet(); + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + VGAPut(); + SCREEN_EPILOG (CopyWindow, VGAarbiterCopyWindow); +} + +static void +VGAarbiterClearToBackground ( + WindowPtr pWin, + int x, int y, + int w, int h, + Bool generateExposures ) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOG ( ClearToBackground); + VGAGet(); + (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); + VGAPut(); + SCREEN_EPILOG (ClearToBackground, VGAarbiterClearToBackground); +} + +static PixmapPtr +VGAarbiterCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint) +{ + PixmapPtr pPix; + + SCREEN_PROLOG ( CreatePixmap); + VGAGet(); + pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint); + VGAPut(); + SCREEN_EPILOG (CreatePixmap, VGAarbiterCreatePixmap); + + return pPix; +} + +static Bool +VGAarbiterSaveScreen(ScreenPtr pScreen, Bool unblank) +{ + Bool val; + + SCREEN_PROLOG (SaveScreen); + VGAGet(); + val = (*pScreen->SaveScreen) (pScreen, unblank); + VGAPut(); + SCREEN_EPILOG (SaveScreen, VGAarbiterSaveScreen); + + return val; +} + +static void +VGAarbiterStoreColors ( + ColormapPtr pmap, + int ndef, + xColorItem *pdefs) +{ + ScreenPtr pScreen = pmap->pScreen; + + SCREEN_PROLOG (StoreColors); + VGAGet(); + (*pScreen->StoreColors) (pmap,ndef,pdefs); + VGAPut(); + SCREEN_EPILOG ( StoreColors, VGAarbiterStoreColors); +} + +static void +VGAarbiterRecolorCursor ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCurs, + Bool displayed + ) +{ + SCREEN_PROLOG (RecolorCursor); + VGAGet(); + (*pScreen->RecolorCursor) (pDev, pScreen, pCurs, displayed); + VGAPut(); + SCREEN_EPILOG ( RecolorCursor, VGAarbiterRecolorCursor); +} + +static Bool +VGAarbiterRealizeCursor ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor + ) +{ + Bool val; + + SCREEN_PROLOG (RealizeCursor); + VGAGet(); + val = (*pScreen->RealizeCursor) (pDev, pScreen,pCursor); + VGAPut(); + SCREEN_EPILOG ( RealizeCursor, VGAarbiterRealizeCursor); + return val; +} + +static Bool +VGAarbiterUnrealizeCursor ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor + ) +{ + Bool val; + + SCREEN_PROLOG (UnrealizeCursor); + VGAGet(); + val = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor); + VGAPut(); + SCREEN_EPILOG ( UnrealizeCursor, VGAarbiterUnrealizeCursor); + return val; +} + +static Bool +VGAarbiterDisplayCursor ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor + ) +{ + Bool val; + + SCREEN_PROLOG (DisplayCursor); + VGAGet(); + val = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); + VGAPut(); + SCREEN_EPILOG ( DisplayCursor, VGAarbiterDisplayCursor); + return val; +} + +static Bool +VGAarbiterSetCursorPosition ( + DeviceIntPtr pDev, + ScreenPtr pScreen, + int x, int y, + Bool generateEvent) +{ + Bool val; + + SCREEN_PROLOG (SetCursorPosition); + VGAGet(); + val = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); + VGAPut(); + SCREEN_EPILOG ( SetCursorPosition, VGAarbiterSetCursorPosition); + return val; +} + +static void +VGAarbiterAdjustFrame(int index, int x, int y, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(); + (*pScreenPriv->AdjustFrame)(index, x, y, flags); + VGAPut(); +} + +static Bool +VGAarbiterSwitchMode(int index, DisplayModePtr mode, int flags) +{ + Bool val; + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(); + val = (*pScreenPriv->SwitchMode)(index, mode, flags); + VGAPut(); + return val; +} + +static Bool +VGAarbiterEnterVT(int index, int flags) +{ + Bool val; + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(); + val = (*pScreenPriv->EnterVT)(index, flags); + VGAPut(); + return val; +} + +static void +VGAarbiterLeaveVT(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(); + (*pScreenPriv->LeaveVT)(index, flags); + VGAPut(); +} + +static void +VGAarbiterFreeScreen(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + VGAarbiterScreenPtr pScreenPriv = (VGAarbiterScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, VGAarbiterScreenKey); + + VGAGet(); + (*pScreenPriv->FreeScreen)(index, flags); + VGAPut(); +} + +static Bool +VGAarbiterCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + VGAarbiterGCPtr pGCPriv = (VGAarbiterGCPtr)dixLookupPrivate(&pGC->devPrivates, VGAarbiterGCKey); + Bool ret; + + SCREEN_PROLOG(CreateGC); + VGAGet(); + ret = (*pScreen->CreateGC)(pGC); + VGAPut(); + GC_WRAP(pGC); + SCREEN_EPILOG(CreateGC,VGAarbiterCreateGC); + + return ret; +} + +/* GC funcs */ +static void +VGAarbiterValidateGC( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw ) +{ + GC_UNWRAP(pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); + GC_WRAP(pGC); +} + + +static void +VGAarbiterDestroyGC(GCPtr pGC) +{ + GC_UNWRAP (pGC); + (*pGC->funcs->DestroyGC)(pGC); + GC_WRAP (pGC); +} + +static void +VGAarbiterChangeGC ( + GCPtr pGC, + unsigned long mask) +{ + GC_UNWRAP (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + GC_WRAP (pGC); +} + +static void +VGAarbiterCopyGC ( + GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + GC_UNWRAP (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + GC_WRAP (pGCDst); +} + +static void +VGAarbiterChangeClip ( + GCPtr pGC, + int type, + pointer pvalue, + int nrects ) +{ + GC_UNWRAP (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + GC_WRAP (pGC); +} + +static void +VGAarbiterCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + GC_UNWRAP (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + GC_WRAP (pgcDst); +} + +static void +VGAarbiterDestroyClip(GCPtr pGC) +{ + GC_UNWRAP (pGC); + (* pGC->funcs->DestroyClip)(pGC); + GC_WRAP (pGC); +} + +/* GC Ops */ +static void +VGAarbiterFillSpans( + DrawablePtr pDraw, + GC *pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidthInit, + int fSorted ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterSetSpans( + DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + register DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, + int format, + char *pImage ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static RegionPtr +VGAarbiterCopyArea( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty ) +{ + RegionPtr ret; + + GC_UNWRAP(pGC); + VGAGet_GC(); + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + VGAPut_GC(); + GC_WRAP(pGC); + return ret; +} + +static RegionPtr +VGAarbiterCopyPlane( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane ) +{ + RegionPtr ret; + + GC_UNWRAP(pGC); + VGAGet_GC(); + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC, srcx, srcy, + width, height, dstx, dsty, bitPlane); + VGAPut_GC(); + GC_WRAP(pGC); + return ret; +} + +static void +VGAarbiterPolyPoint( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + xPoint *pptInit ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit); + VGAPut_GC(); + GC_WRAP(pGC); +} + + +static void +VGAarbiterPolylines( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pptInit ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolySegment( + DrawablePtr pDraw, + GCPtr pGC, + int nseg, + xSegment *pSeg ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyRectangle( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterFillPolygon( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyFillRect( + DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, + xRectangle *prectInit) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PolyFillRect)(pDraw, pGC, nrectFill, prectInit); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyFillArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static int +VGAarbiterPolyText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars ) +{ + int ret; + + GC_UNWRAP(pGC); + VGAGet_GC(); + ret = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars); + VGAPut_GC(); + GC_WRAP(pGC); + return ret; +} + +static int +VGAarbiterPolyText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars ) +{ + int ret; + + GC_UNWRAP(pGC); + VGAGet_GC(); + ret = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars); + VGAPut_GC(); + GC_WRAP(pGC); + return ret; +} + +static void +VGAarbiterImageText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterImageText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars); + VGAPut_GC(); + GC_WRAP(pGC); +} + + +static void +VGAarbiterImageGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, xInit, yInit, + nglyph, ppci, pglyphBase); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPolyGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, xInit, yInit, + nglyph, ppci, pglyphBase); + VGAPut_GC(); + GC_WRAP(pGC); +} + +static void +VGAarbiterPushPixels( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, int xOrg, int yOrg ) +{ + GC_UNWRAP(pGC); + VGAGet_GC(); + (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); + VGAPut_GC(); + GC_WRAP(pGC); +} + + +/* miSpriteFuncs */ +static Bool +VGAarbiterSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur) +{ + Bool val; + SPRITE_PROLOG; + VGAGet(); + val = PointPriv->spriteFuncs->RealizeCursor(pDev, pScreen, pCur); + VGAPut(); + SPRITE_EPILOG; + return val; +} + +static Bool +VGAarbiterSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur) +{ + Bool val; + SPRITE_PROLOG; + VGAGet(); + val = PointPriv->spriteFuncs->UnrealizeCursor(pDev, pScreen, pCur); + VGAPut(); + SPRITE_EPILOG; + return val; +} + +static void +VGAarbiterSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur, int x, int y) +{ + SPRITE_PROLOG; + VGAGet(); + PointPriv->spriteFuncs->SetCursor(pDev, pScreen, pCur, x, y); + VGAPut(); + SPRITE_EPILOG; +} + +static void +VGAarbiterSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + SPRITE_PROLOG; + VGAGet(); + PointPriv->spriteFuncs->MoveCursor(pDev, pScreen, x, y); + VGAPut(); + SPRITE_EPILOG; +} + +static Bool +VGAarbiterDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + Bool val; + SPRITE_PROLOG; + VGAGet(); + val = PointPriv->spriteFuncs->DeviceCursorInitialize(pDev, pScreen); + VGAPut(); + SPRITE_EPILOG; + return val; +} + +static void +VGAarbiterDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + SPRITE_PROLOG; + VGAGet(); + PointPriv->spriteFuncs->DeviceCursorCleanup(pDev, pScreen); + VGAPut(); + SPRITE_EPILOG; +} + +static void +VGAarbiterComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, + INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + PICTURE_PROLOGUE(Composite); + + VGAGet(); + (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, + yDst, width, height); + VGAPut(); + PICTURE_EPILOGUE(Composite, VGAarbiterComposite); +} + +static void +VGAarbiterGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, + GlyphListPtr list, GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + PICTURE_PROLOGUE(Glyphs); + + VGAGet(); + (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + VGAPut(); + PICTURE_EPILOGUE (Glyphs, VGAarbiterGlyphs); +} + +static void +VGAarbiterCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color, int nRect, + xRectangle *rects) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + + PICTURE_PROLOGUE(CompositeRects); + + VGAGet(); + (*ps->CompositeRects)(op, pDst, color, nRect, rects); + VGAPut(); + PICTURE_EPILOGUE (CompositeRects, VGAarbiterCompositeRects); +} +#else +/* dummy functions */ +void xf86VGAarbiterInit(void) {} +void xf86VGAarbiterFini(void) {} + +void xf86VGAarbiterLock(ScrnInfoPtr pScrn) {} +void xf86VGAarbiterUnlock(ScrnInfoPtr pScrn) {} +Bool xf86VGAarbiterAllowDRI(ScreenPtr pScreen) { return TRUE; } +void xf86VGAarbiterScrnInit(ScrnInfoPtr pScrn) {} +void xf86VGAarbiterDeviceDecodes(ScrnInfoPtr pScrn) {} +Bool xf86VGAarbiterWrapFunctions(void) { return FALSE; } + +#endif diff --git a/xorg-server/hw/xfree86/common/xf86VidMode.c b/xorg-server/hw/xfree86/common/xf86VidMode.c index 49b86e73a..08f27b8e4 100644 --- a/xorg-server/hw/xfree86/common/xf86VidMode.c +++ b/xorg-server/hw/xfree86/common/xf86VidMode.c @@ -1,667 +1,667 @@ -/* - * Copyright (c) 1999-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * This file contains the VidMode functions required by the extension. - * These have been added to avoid the need for the higher level extension - * code to access the private XFree86 data structures directly. Wherever - * possible this code uses the functions in xf86Mode.c to do the work, - * so that two version of code that do similar things don't have to be - * maintained. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "os.h" -#include "xf86.h" -#include "xf86Priv.h" - -#ifdef XF86VIDMODE -#include "vidmodeproc.h" -#include "xf86cmap.h" - -static int VidModeKeyIndex; -static DevPrivateKey VidModeKey; -static int VidModeCount = 0; -static Bool VidModeClose(int i, ScreenPtr pScreen); - -#define VMPTR(p) ((VidModePtr)dixLookupPrivate(&(p)->devPrivates, VidModeKey)) - -#endif - -Bool -VidModeExtensionInit(ScreenPtr pScreen) -{ -#ifdef XF86VIDMODE - VidModePtr pVidMode; - - if (!xf86GetVidModeEnabled()) { - DebugF("!xf86GetVidModeEnabled()\n"); - return FALSE; - } - - VidModeKey = &VidModeKeyIndex; - - if (!dixSetPrivate(&pScreen->devPrivates, VidModeKey, - xcalloc(sizeof(VidModeRec), 1))) { - DebugF("xcalloc failed\n"); - return FALSE; - } - - pVidMode = VMPTR(pScreen); - pVidMode->Flags = 0; - pVidMode->Next = NULL; - pVidMode->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = VidModeClose; - VidModeCount++; - return TRUE; -#else - DebugF("no vidmode extension\n"); - return FALSE; -#endif -} - - -#ifdef XF86VIDMODE - -static Bool -VidModeClose(int i, ScreenPtr pScreen) -{ - VidModePtr pVidMode = VMPTR(pScreen); - - /* This shouldn't happen */ - if (!pVidMode) - return FALSE; - - pScreen->CloseScreen = pVidMode->CloseScreen; - - if (--VidModeCount == 0) { - xfree(dixLookupPrivate(&pScreen->devPrivates, VidModeKey)); - dixSetPrivate(&pScreen->devPrivates, VidModeKey, NULL); - VidModeKey = NULL; - } - return pScreen->CloseScreen(i, pScreen); -} - -Bool -VidModeAvailable(int scrnIndex) -{ - ScrnInfoPtr pScrn; - VidModePtr pVidMode; - - if (VidModeKey == NULL) { - DebugF("VidModeKey == NULL\n"); - return FALSE; - } - - pScrn = xf86Screens[scrnIndex]; - if (pScrn == NULL) { - DebugF("pScrn == NULL\n"); - return FALSE; - } - - pVidMode = VMPTR(pScrn->pScreen); - if (pVidMode) - return TRUE; - else { - DebugF("pVidMode == NULL\n"); - return FALSE; - } -} - -Bool -VidModeGetCurrentModeline(int scrnIndex, pointer *mode, int *dotClock) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - - if (pScrn->currentMode) { - *mode = (pointer)(pScrn->currentMode); - *dotClock = pScrn->currentMode->Clock; - - return TRUE; - } - return FALSE; -} - -int -VidModeGetDotClock(int scrnIndex, int Clock) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return 0; - - pScrn = xf86Screens[scrnIndex]; - if ((pScrn->progClock) || (Clock >= MAXCLOCKS)) - return Clock; - else - return pScrn->clock[Clock]; -} - -int -VidModeGetNumOfClocks(int scrnIndex, Bool *progClock) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return 0; - - pScrn = xf86Screens[scrnIndex]; - if (pScrn->progClock){ - *progClock = TRUE; - return 0; - } else { - *progClock = FALSE; - return pScrn->numClocks; - } -} - -Bool -VidModeGetClocks(int scrnIndex, int *Clocks) -{ - ScrnInfoPtr pScrn; - int i; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - - if (pScrn->progClock) - return FALSE; - - for (i = 0; i < pScrn->numClocks; i++) - *Clocks++ = pScrn->clock[i]; - - return TRUE; -} - - -Bool -VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock) -{ - ScrnInfoPtr pScrn; - VidModePtr pVidMode; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - pVidMode = VMPTR(pScrn->pScreen); - pVidMode->First = pScrn->modes; - pVidMode->Next = pVidMode->First->next; - - if (pVidMode->First->status == MODE_OK) { - *mode = (pointer)(pVidMode->First); - *dotClock = VidModeGetDotClock(scrnIndex, pVidMode->First->Clock); - return TRUE; - } - - return VidModeGetNextModeline(scrnIndex, mode, dotClock); -} - -Bool -VidModeGetNextModeline(int scrnIndex, pointer *mode, int *dotClock) -{ - ScrnInfoPtr pScrn; - VidModePtr pVidMode; - DisplayModePtr p; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - pVidMode = VMPTR(pScrn->pScreen); - - for (p = pVidMode->Next; p != NULL && p != pVidMode->First; p = p->next) { - if (p->status == MODE_OK) { - pVidMode->Next = p->next; - *mode = (pointer)p; - *dotClock = VidModeGetDotClock(scrnIndex, p->Clock); - return TRUE; - } - } - - return FALSE; -} - -Bool -VidModeDeleteModeline(int scrnIndex, pointer mode) -{ - ScrnInfoPtr pScrn; - - if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - xf86DeleteMode(&(pScrn->modes), (DisplayModePtr)mode); - return TRUE; -} - -Bool -VidModeZoomViewport(int scrnIndex, int zoom) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - xf86ZoomViewport(pScrn->pScreen, zoom); - return TRUE; -} - -Bool -VidModeSetViewPort(int scrnIndex, int x, int y) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - pScrn->frameX0 = min( max(x, 0), - pScrn->virtualX - pScrn->currentMode->HDisplay ); - pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1; - pScrn->frameY0 = min( max(y, 0), - pScrn->virtualY - pScrn->currentMode->VDisplay ); - pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1; - if (pScrn->AdjustFrame != NULL) - (pScrn->AdjustFrame)(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - - return TRUE; -} - -Bool -VidModeGetViewPort(int scrnIndex, int *x, int *y) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - *x = pScrn->frameX0; - *y = pScrn->frameY0; - return TRUE; -} - -Bool -VidModeSwitchMode(int scrnIndex, pointer mode) -{ - ScrnInfoPtr pScrn; - DisplayModePtr pTmpMode; - Bool retval; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - /* save in case we fail */ - pTmpMode = pScrn->currentMode; - /* Force a mode switch */ - pScrn->currentMode = NULL; - retval = xf86SwitchMode(pScrn->pScreen, mode); - /* we failed: restore it */ - if (retval == FALSE) - pScrn->currentMode = pTmpMode; - return retval; -} - -Bool -VidModeLockZoom(int scrnIndex, Bool lock) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - - if (xf86Info.dontZoom) - return FALSE; - - xf86LockZoom(pScrn->pScreen, lock); - return TRUE; -} - -Bool -VidModeGetMonitor(int scrnIndex, pointer *monitor) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - *monitor = (pointer)(pScrn->monitor); - - return TRUE; -} - -ModeStatus -VidModeCheckModeForMonitor(int scrnIndex, pointer mode) -{ - ScrnInfoPtr pScrn; - - if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) - return MODE_ERROR; - - pScrn = xf86Screens[scrnIndex]; - - return xf86CheckModeForMonitor((DisplayModePtr)mode, pScrn->monitor); -} - -ModeStatus -VidModeCheckModeForDriver(int scrnIndex, pointer mode) -{ - ScrnInfoPtr pScrn; - - if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) - return MODE_ERROR; - - pScrn = xf86Screens[scrnIndex]; - - return xf86CheckModeForDriver(pScrn, (DisplayModePtr)mode, 0); -} - -void -VidModeSetCrtcForMode(int scrnIndex, pointer mode) -{ - ScrnInfoPtr pScrn; - DisplayModePtr ScreenModes; - - if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) - return; - - /* Ugly hack so that the xf86Mode.c function can be used without change */ - pScrn = xf86Screens[scrnIndex]; - ScreenModes = pScrn->modes; - pScrn->modes = (DisplayModePtr)mode; - - xf86SetCrtcForModes(pScrn, pScrn->adjustFlags); - pScrn->modes = ScreenModes; - return; -} - -Bool -VidModeAddModeline(int scrnIndex, pointer mode) -{ - ScrnInfoPtr pScrn; - - if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - - ((DisplayModePtr)mode)->name = strdup(""); /* freed by deletemode */ - ((DisplayModePtr)mode)->status = MODE_OK; - ((DisplayModePtr)mode)->next = pScrn->modes->next; - ((DisplayModePtr)mode)->prev = pScrn->modes; - pScrn->modes->next = (DisplayModePtr)mode; - if( ((DisplayModePtr)mode)->next != NULL ) - ((DisplayModePtr)mode)->next->prev = (DisplayModePtr)mode; - - return TRUE; -} - -int -VidModeGetNumOfModes(int scrnIndex) -{ - pointer mode = NULL; - int dotClock= 0, nummodes = 0; - - if (!VidModeGetFirstModeline(scrnIndex, &mode, &dotClock)) - return nummodes; - - do { - nummodes++; - if (!VidModeGetNextModeline(scrnIndex, &mode, &dotClock)) - return nummodes; - } while (TRUE); -} - -Bool -VidModeSetGamma(int scrnIndex, float red, float green, float blue) -{ - ScrnInfoPtr pScrn; - Gamma gamma; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - gamma.red = red; - gamma.green = green; - gamma.blue = blue; - if (xf86ChangeGamma(pScrn->pScreen, gamma) != Success) - return FALSE; - else - return TRUE; -} - -Bool -VidModeGetGamma(int scrnIndex, float *red, float *green, float *blue) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - *red = pScrn->gamma.red; - *green = pScrn->gamma.green; - *blue = pScrn->gamma.blue; - return TRUE; -} - -Bool -VidModeSetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - xf86ChangeGammaRamp(pScrn->pScreen, size, r, g, b); - return TRUE; -} - -Bool -VidModeGetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b) -{ - ScrnInfoPtr pScrn; - - if (!VidModeAvailable(scrnIndex)) - return FALSE; - - pScrn = xf86Screens[scrnIndex]; - xf86GetGammaRamp(pScrn->pScreen, size, r, g, b); - return TRUE; -} - -int -VidModeGetGammaRampSize(int scrnIndex) -{ - if (!VidModeAvailable(scrnIndex)) - return 0; - - return xf86GetGammaRampSize(xf86Screens[scrnIndex]->pScreen); -} - -pointer -VidModeCreateMode(void) -{ - DisplayModePtr mode; - - mode = xalloc(sizeof(DisplayModeRec)); - if (mode != NULL) { - mode->name = ""; - mode->VScan = 1; /* divides refresh rate. default = 1 */ - mode->Private = NULL; - mode->next = mode; - mode->prev = mode; - } - return mode; -} - -void -VidModeCopyMode(pointer modefrom, pointer modeto) -{ - memcpy(modeto, modefrom, sizeof(DisplayModeRec)); -} - - -int -VidModeGetModeValue(pointer mode, int valtyp) -{ - int ret = 0; - - switch (valtyp) { - case VIDMODE_H_DISPLAY: - ret = ((DisplayModePtr) mode)->HDisplay; - break; - case VIDMODE_H_SYNCSTART: - ret = ((DisplayModePtr)mode)->HSyncStart; - break; - case VIDMODE_H_SYNCEND: - ret = ((DisplayModePtr)mode)->HSyncEnd; - break; - case VIDMODE_H_TOTAL: - ret = ((DisplayModePtr)mode)->HTotal; - break; - case VIDMODE_H_SKEW: - ret = ((DisplayModePtr)mode)->HSkew; - break; - case VIDMODE_V_DISPLAY: - ret = ((DisplayModePtr)mode)->VDisplay; - break; - case VIDMODE_V_SYNCSTART: - ret = ((DisplayModePtr)mode)->VSyncStart; - break; - case VIDMODE_V_SYNCEND: - ret = ((DisplayModePtr)mode)->VSyncEnd; - break; - case VIDMODE_V_TOTAL: - ret = ((DisplayModePtr)mode)->VTotal; - break; - case VIDMODE_FLAGS: - ret = ((DisplayModePtr)mode)->Flags; - break; - case VIDMODE_CLOCK: - ret = ((DisplayModePtr)mode)->Clock; - break; - } - return ret; -} - -void -VidModeSetModeValue(pointer mode, int valtyp, int val) -{ - switch (valtyp) { - case VIDMODE_H_DISPLAY: - ((DisplayModePtr)mode)->HDisplay = val; - break; - case VIDMODE_H_SYNCSTART: - ((DisplayModePtr)mode)->HSyncStart = val; - break; - case VIDMODE_H_SYNCEND: - ((DisplayModePtr)mode)->HSyncEnd = val; - break; - case VIDMODE_H_TOTAL: - ((DisplayModePtr)mode)->HTotal = val; - break; - case VIDMODE_H_SKEW: - ((DisplayModePtr)mode)->HSkew = val; - break; - case VIDMODE_V_DISPLAY: - ((DisplayModePtr)mode)->VDisplay = val; - break; - case VIDMODE_V_SYNCSTART: - ((DisplayModePtr)mode)->VSyncStart = val; - break; - case VIDMODE_V_SYNCEND: - ((DisplayModePtr)mode)->VSyncEnd = val; - break; - case VIDMODE_V_TOTAL: - ((DisplayModePtr)mode)->VTotal = val; - break; - case VIDMODE_FLAGS: - ((DisplayModePtr)mode)->Flags = val; - break; - case VIDMODE_CLOCK: - ((DisplayModePtr)mode)->Clock = val; - break; - } - return; -} - -vidMonitorValue -VidModeGetMonitorValue(pointer monitor, int valtyp, int indx) -{ - vidMonitorValue ret; - - switch (valtyp) { - case VIDMODE_MON_VENDOR: - ret.ptr = (((MonPtr)monitor)->vendor); - break; - case VIDMODE_MON_MODEL: - ret.ptr = (((MonPtr)monitor)->model); - break; - case VIDMODE_MON_NHSYNC: - ret.i = ((MonPtr)monitor)->nHsync; - break; - case VIDMODE_MON_NVREFRESH: - ret.i = ((MonPtr)monitor)->nVrefresh; - break; - case VIDMODE_MON_HSYNC_LO: - ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].lo); - break; - case VIDMODE_MON_HSYNC_HI: - ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].hi); - break; - case VIDMODE_MON_VREFRESH_LO: - ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].lo); - break; - case VIDMODE_MON_VREFRESH_HI: - ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].hi); - break; - } - return ret; -} - - -#endif /* XF86VIDMODE */ +/* + * Copyright (c) 1999-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * This file contains the VidMode functions required by the extension. + * These have been added to avoid the need for the higher level extension + * code to access the private XFree86 data structures directly. Wherever + * possible this code uses the functions in xf86Mode.c to do the work, + * so that two version of code that do similar things don't have to be + * maintained. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "os.h" +#include "xf86.h" +#include "xf86Priv.h" + +#ifdef XF86VIDMODE +#include "vidmodeproc.h" +#include "xf86cmap.h" + +static int VidModeKeyIndex; +static DevPrivateKey VidModeKey; +static int VidModeCount = 0; +static Bool VidModeClose(int i, ScreenPtr pScreen); + +#define VMPTR(p) ((VidModePtr)dixLookupPrivate(&(p)->devPrivates, VidModeKey)) + +#endif + +Bool +VidModeExtensionInit(ScreenPtr pScreen) +{ +#ifdef XF86VIDMODE + VidModePtr pVidMode; + + if (!xf86GetVidModeEnabled()) { + DebugF("!xf86GetVidModeEnabled()\n"); + return FALSE; + } + + VidModeKey = &VidModeKeyIndex; + + if (!dixSetPrivate(&pScreen->devPrivates, VidModeKey, + calloc(sizeof(VidModeRec), 1))) { + DebugF("xcalloc failed\n"); + return FALSE; + } + + pVidMode = VMPTR(pScreen); + pVidMode->Flags = 0; + pVidMode->Next = NULL; + pVidMode->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = VidModeClose; + VidModeCount++; + return TRUE; +#else + DebugF("no vidmode extension\n"); + return FALSE; +#endif +} + + +#ifdef XF86VIDMODE + +static Bool +VidModeClose(int i, ScreenPtr pScreen) +{ + VidModePtr pVidMode = VMPTR(pScreen); + + /* This shouldn't happen */ + if (!pVidMode) + return FALSE; + + pScreen->CloseScreen = pVidMode->CloseScreen; + + if (--VidModeCount == 0) { + free(dixLookupPrivate(&pScreen->devPrivates, VidModeKey)); + dixSetPrivate(&pScreen->devPrivates, VidModeKey, NULL); + VidModeKey = NULL; + } + return pScreen->CloseScreen(i, pScreen); +} + +Bool +VidModeAvailable(int scrnIndex) +{ + ScrnInfoPtr pScrn; + VidModePtr pVidMode; + + if (VidModeKey == NULL) { + DebugF("VidModeKey == NULL\n"); + return FALSE; + } + + pScrn = xf86Screens[scrnIndex]; + if (pScrn == NULL) { + DebugF("pScrn == NULL\n"); + return FALSE; + } + + pVidMode = VMPTR(pScrn->pScreen); + if (pVidMode) + return TRUE; + else { + DebugF("pVidMode == NULL\n"); + return FALSE; + } +} + +Bool +VidModeGetCurrentModeline(int scrnIndex, pointer *mode, int *dotClock) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + + if (pScrn->currentMode) { + *mode = (pointer)(pScrn->currentMode); + *dotClock = pScrn->currentMode->Clock; + + return TRUE; + } + return FALSE; +} + +int +VidModeGetDotClock(int scrnIndex, int Clock) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return 0; + + pScrn = xf86Screens[scrnIndex]; + if ((pScrn->progClock) || (Clock >= MAXCLOCKS)) + return Clock; + else + return pScrn->clock[Clock]; +} + +int +VidModeGetNumOfClocks(int scrnIndex, Bool *progClock) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return 0; + + pScrn = xf86Screens[scrnIndex]; + if (pScrn->progClock){ + *progClock = TRUE; + return 0; + } else { + *progClock = FALSE; + return pScrn->numClocks; + } +} + +Bool +VidModeGetClocks(int scrnIndex, int *Clocks) +{ + ScrnInfoPtr pScrn; + int i; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + + if (pScrn->progClock) + return FALSE; + + for (i = 0; i < pScrn->numClocks; i++) + *Clocks++ = pScrn->clock[i]; + + return TRUE; +} + + +Bool +VidModeGetFirstModeline(int scrnIndex, pointer *mode, int *dotClock) +{ + ScrnInfoPtr pScrn; + VidModePtr pVidMode; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + pVidMode = VMPTR(pScrn->pScreen); + pVidMode->First = pScrn->modes; + pVidMode->Next = pVidMode->First->next; + + if (pVidMode->First->status == MODE_OK) { + *mode = (pointer)(pVidMode->First); + *dotClock = VidModeGetDotClock(scrnIndex, pVidMode->First->Clock); + return TRUE; + } + + return VidModeGetNextModeline(scrnIndex, mode, dotClock); +} + +Bool +VidModeGetNextModeline(int scrnIndex, pointer *mode, int *dotClock) +{ + ScrnInfoPtr pScrn; + VidModePtr pVidMode; + DisplayModePtr p; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + pVidMode = VMPTR(pScrn->pScreen); + + for (p = pVidMode->Next; p != NULL && p != pVidMode->First; p = p->next) { + if (p->status == MODE_OK) { + pVidMode->Next = p->next; + *mode = (pointer)p; + *dotClock = VidModeGetDotClock(scrnIndex, p->Clock); + return TRUE; + } + } + + return FALSE; +} + +Bool +VidModeDeleteModeline(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + xf86DeleteMode(&(pScrn->modes), (DisplayModePtr)mode); + return TRUE; +} + +Bool +VidModeZoomViewport(int scrnIndex, int zoom) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + xf86ZoomViewport(pScrn->pScreen, zoom); + return TRUE; +} + +Bool +VidModeSetViewPort(int scrnIndex, int x, int y) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + pScrn->frameX0 = min( max(x, 0), + pScrn->virtualX - pScrn->currentMode->HDisplay ); + pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1; + pScrn->frameY0 = min( max(y, 0), + pScrn->virtualY - pScrn->currentMode->VDisplay ); + pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1; + if (pScrn->AdjustFrame != NULL) + (pScrn->AdjustFrame)(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + return TRUE; +} + +Bool +VidModeGetViewPort(int scrnIndex, int *x, int *y) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + *x = pScrn->frameX0; + *y = pScrn->frameY0; + return TRUE; +} + +Bool +VidModeSwitchMode(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + DisplayModePtr pTmpMode; + Bool retval; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + /* save in case we fail */ + pTmpMode = pScrn->currentMode; + /* Force a mode switch */ + pScrn->currentMode = NULL; + retval = xf86SwitchMode(pScrn->pScreen, mode); + /* we failed: restore it */ + if (retval == FALSE) + pScrn->currentMode = pTmpMode; + return retval; +} + +Bool +VidModeLockZoom(int scrnIndex, Bool lock) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + + if (xf86Info.dontZoom) + return FALSE; + + xf86LockZoom(pScrn->pScreen, lock); + return TRUE; +} + +Bool +VidModeGetMonitor(int scrnIndex, pointer *monitor) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + *monitor = (pointer)(pScrn->monitor); + + return TRUE; +} + +ModeStatus +VidModeCheckModeForMonitor(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return MODE_ERROR; + + pScrn = xf86Screens[scrnIndex]; + + return xf86CheckModeForMonitor((DisplayModePtr)mode, pScrn->monitor); +} + +ModeStatus +VidModeCheckModeForDriver(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return MODE_ERROR; + + pScrn = xf86Screens[scrnIndex]; + + return xf86CheckModeForDriver(pScrn, (DisplayModePtr)mode, 0); +} + +void +VidModeSetCrtcForMode(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + DisplayModePtr ScreenModes; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return; + + /* Ugly hack so that the xf86Mode.c function can be used without change */ + pScrn = xf86Screens[scrnIndex]; + ScreenModes = pScrn->modes; + pScrn->modes = (DisplayModePtr)mode; + + xf86SetCrtcForModes(pScrn, pScrn->adjustFlags); + pScrn->modes = ScreenModes; + return; +} + +Bool +VidModeAddModeline(int scrnIndex, pointer mode) +{ + ScrnInfoPtr pScrn; + + if ((mode == NULL) || (!VidModeAvailable(scrnIndex))) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + + ((DisplayModePtr)mode)->name = strdup(""); /* freed by deletemode */ + ((DisplayModePtr)mode)->status = MODE_OK; + ((DisplayModePtr)mode)->next = pScrn->modes->next; + ((DisplayModePtr)mode)->prev = pScrn->modes; + pScrn->modes->next = (DisplayModePtr)mode; + if( ((DisplayModePtr)mode)->next != NULL ) + ((DisplayModePtr)mode)->next->prev = (DisplayModePtr)mode; + + return TRUE; +} + +int +VidModeGetNumOfModes(int scrnIndex) +{ + pointer mode = NULL; + int dotClock= 0, nummodes = 0; + + if (!VidModeGetFirstModeline(scrnIndex, &mode, &dotClock)) + return nummodes; + + do { + nummodes++; + if (!VidModeGetNextModeline(scrnIndex, &mode, &dotClock)) + return nummodes; + } while (TRUE); +} + +Bool +VidModeSetGamma(int scrnIndex, float red, float green, float blue) +{ + ScrnInfoPtr pScrn; + Gamma gamma; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + gamma.red = red; + gamma.green = green; + gamma.blue = blue; + if (xf86ChangeGamma(pScrn->pScreen, gamma) != Success) + return FALSE; + else + return TRUE; +} + +Bool +VidModeGetGamma(int scrnIndex, float *red, float *green, float *blue) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + *red = pScrn->gamma.red; + *green = pScrn->gamma.green; + *blue = pScrn->gamma.blue; + return TRUE; +} + +Bool +VidModeSetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + xf86ChangeGammaRamp(pScrn->pScreen, size, r, g, b); + return TRUE; +} + +Bool +VidModeGetGammaRamp(int scrnIndex, int size, CARD16 *r, CARD16 *g, CARD16 *b) +{ + ScrnInfoPtr pScrn; + + if (!VidModeAvailable(scrnIndex)) + return FALSE; + + pScrn = xf86Screens[scrnIndex]; + xf86GetGammaRamp(pScrn->pScreen, size, r, g, b); + return TRUE; +} + +int +VidModeGetGammaRampSize(int scrnIndex) +{ + if (!VidModeAvailable(scrnIndex)) + return 0; + + return xf86GetGammaRampSize(xf86Screens[scrnIndex]->pScreen); +} + +pointer +VidModeCreateMode(void) +{ + DisplayModePtr mode; + + mode = malloc(sizeof(DisplayModeRec)); + if (mode != NULL) { + mode->name = ""; + mode->VScan = 1; /* divides refresh rate. default = 1 */ + mode->Private = NULL; + mode->next = mode; + mode->prev = mode; + } + return mode; +} + +void +VidModeCopyMode(pointer modefrom, pointer modeto) +{ + memcpy(modeto, modefrom, sizeof(DisplayModeRec)); +} + + +int +VidModeGetModeValue(pointer mode, int valtyp) +{ + int ret = 0; + + switch (valtyp) { + case VIDMODE_H_DISPLAY: + ret = ((DisplayModePtr) mode)->HDisplay; + break; + case VIDMODE_H_SYNCSTART: + ret = ((DisplayModePtr)mode)->HSyncStart; + break; + case VIDMODE_H_SYNCEND: + ret = ((DisplayModePtr)mode)->HSyncEnd; + break; + case VIDMODE_H_TOTAL: + ret = ((DisplayModePtr)mode)->HTotal; + break; + case VIDMODE_H_SKEW: + ret = ((DisplayModePtr)mode)->HSkew; + break; + case VIDMODE_V_DISPLAY: + ret = ((DisplayModePtr)mode)->VDisplay; + break; + case VIDMODE_V_SYNCSTART: + ret = ((DisplayModePtr)mode)->VSyncStart; + break; + case VIDMODE_V_SYNCEND: + ret = ((DisplayModePtr)mode)->VSyncEnd; + break; + case VIDMODE_V_TOTAL: + ret = ((DisplayModePtr)mode)->VTotal; + break; + case VIDMODE_FLAGS: + ret = ((DisplayModePtr)mode)->Flags; + break; + case VIDMODE_CLOCK: + ret = ((DisplayModePtr)mode)->Clock; + break; + } + return ret; +} + +void +VidModeSetModeValue(pointer mode, int valtyp, int val) +{ + switch (valtyp) { + case VIDMODE_H_DISPLAY: + ((DisplayModePtr)mode)->HDisplay = val; + break; + case VIDMODE_H_SYNCSTART: + ((DisplayModePtr)mode)->HSyncStart = val; + break; + case VIDMODE_H_SYNCEND: + ((DisplayModePtr)mode)->HSyncEnd = val; + break; + case VIDMODE_H_TOTAL: + ((DisplayModePtr)mode)->HTotal = val; + break; + case VIDMODE_H_SKEW: + ((DisplayModePtr)mode)->HSkew = val; + break; + case VIDMODE_V_DISPLAY: + ((DisplayModePtr)mode)->VDisplay = val; + break; + case VIDMODE_V_SYNCSTART: + ((DisplayModePtr)mode)->VSyncStart = val; + break; + case VIDMODE_V_SYNCEND: + ((DisplayModePtr)mode)->VSyncEnd = val; + break; + case VIDMODE_V_TOTAL: + ((DisplayModePtr)mode)->VTotal = val; + break; + case VIDMODE_FLAGS: + ((DisplayModePtr)mode)->Flags = val; + break; + case VIDMODE_CLOCK: + ((DisplayModePtr)mode)->Clock = val; + break; + } + return; +} + +vidMonitorValue +VidModeGetMonitorValue(pointer monitor, int valtyp, int indx) +{ + vidMonitorValue ret; + + switch (valtyp) { + case VIDMODE_MON_VENDOR: + ret.ptr = (((MonPtr)monitor)->vendor); + break; + case VIDMODE_MON_MODEL: + ret.ptr = (((MonPtr)monitor)->model); + break; + case VIDMODE_MON_NHSYNC: + ret.i = ((MonPtr)monitor)->nHsync; + break; + case VIDMODE_MON_NVREFRESH: + ret.i = ((MonPtr)monitor)->nVrefresh; + break; + case VIDMODE_MON_HSYNC_LO: + ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].lo); + break; + case VIDMODE_MON_HSYNC_HI: + ret.f = (100.0 * ((MonPtr)monitor)->hsync[indx].hi); + break; + case VIDMODE_MON_VREFRESH_LO: + ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].lo); + break; + case VIDMODE_MON_VREFRESH_HI: + ret.f = (100.0 * ((MonPtr)monitor)->vrefresh[indx].hi); + break; + } + return ret; +} + + +#endif /* XF86VIDMODE */ diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index a1a5527f4..f1096f1a5 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -1,1284 +1,1284 @@ -/* - * Copyright 1995-1999 by Frederic Lepied, France. - * - * 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 Frederic Lepied not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Frederic Lepied makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL FREDERIC LEPIED 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. - * - */ -/* - * Copyright (c) 2000-2002 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86Config.h" -#include "xf86Xinput.h" -#include "XIstubs.h" -#include "xf86Optrec.h" -#include "xf86Parser.h" -#include "mipointer.h" -#include "xf86InPriv.h" -#include "compiler.h" -#include "extinit.h" - -#ifdef DPMSExtension -#include -#include "dpmsproc.h" -#endif - -#include "exevents.h" /* AddInputDevice */ -#include "exglobals.h" -#include "eventstr.h" - -#include /* InputClassMatches */ -#ifdef HAVE_FNMATCH_H -#include -#endif - -#include "extnsionst.h" - -#include "windowstr.h" /* screenIsSaved */ - -#include -#include /* for int64_t */ - -#include - -#include "mi.h" - -#include /* dix pointer acceleration */ -#include - -#ifdef XFreeXDGA -#include "dgaproc.h" -#endif - -#include "xkbsrv.h" - -#include "os.h" - -EventListPtr xf86Events = NULL; - -/** - * Eval config and modify DeviceVelocityRec accordingly - */ -static void -ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, - DeviceVelocityPtr s) -{ - int tempi; - float tempf; - Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); - Atom prop; - - if(!s) - return; - - /* common settings (available via device properties) */ - tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); - if (tempf > 1.0) { - xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", - devname, tempf); - prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); - if (tempf > 1.0) { - xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", - devname, tempf); - prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - /* select profile by number */ - tempi = xf86SetIntOption(list, "AccelerationProfile", - s->statistics.profile_number); - - prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); - if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, - PropModeReplace, 1, &tempi, FALSE) == Success) { - xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, - tempi); - } else { - xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", - devname, tempi); - } - - /* set scaling */ - tempf = xf86SetRealOption(list, "ExpectedRate", 0); - prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); - if (tempf > 0) { - tempf = 1000.0 / tempf; - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } else { - tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); - XIChangeDeviceProperty(pDev, prop, float_prop, 32, - PropModeReplace, 1, &tempf, FALSE); - } - - tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); - if (tempi > 1) - InitTrackers(s, tempi); - - s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", - s->initial_range); - - s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); - - tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); - if (tempf >= 0) { - xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", - devname, tempf*100.0); - s->max_rel_diff = tempf; - } - - /* Configure softening. If const deceleration is used, this is expected - * to provide better subpixel information so we enable - * softening by default only if ConstantDeceleration is not used - */ - s->use_softening = xf86SetBoolOption(list, "Softening", - s->const_acceleration == 1.0); - - s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", - s->average_accel); - - s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); -} - -static void -ApplyAccelerationSettings(DeviceIntPtr dev){ - int scheme, i; - DeviceVelocityPtr pVel; - LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; - char* schemeStr; - - if (dev->valuator && dev->ptrfeed) { - schemeStr = xf86SetStrOption(local->options, "AccelerationScheme", ""); - - scheme = dev->valuator->accelScheme.number; - - if (!xf86NameCmp(schemeStr, "predictable")) - scheme = PtrAccelPredictable; - - if (!xf86NameCmp(schemeStr, "lightweight")) - scheme = PtrAccelLightweight; - - if (!xf86NameCmp(schemeStr, "none")) - scheme = PtrAccelNoOp; - - /* reinit scheme if needed */ - if (dev->valuator->accelScheme.number != scheme) { - if (dev->valuator->accelScheme.AccelCleanupProc) { - dev->valuator->accelScheme.AccelCleanupProc(dev); - } - - if (InitPointerAccelerationScheme(dev, scheme)) { - xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", - local->name, schemeStr, scheme); - } else { - xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", - local->name, schemeStr); - scheme = dev->valuator->accelScheme.number; - } - } else { - xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", - local->name, scheme); - } - - xfree(schemeStr); - - /* process special configuration */ - switch (scheme) { - case PtrAccelPredictable: - pVel = GetDevicePredictableAccelData(dev); - ProcessVelocityConfiguration (dev, local->name, local->options, - pVel); - break; - } - - i = xf86SetIntOption(local->options, "AccelerationNumerator", - dev->ptrfeed->ctrl.num); - if (i >= 0) - dev->ptrfeed->ctrl.num = i; - - i = xf86SetIntOption(local->options, "AccelerationDenominator", - dev->ptrfeed->ctrl.den); - if (i > 0) - dev->ptrfeed->ctrl.den = i; - - i = xf86SetIntOption(local->options, "AccelerationThreshold", - dev->ptrfeed->ctrl.threshold); - if (i >= 0) - dev->ptrfeed->ctrl.threshold = i; - - /* mostly a no-op anyway */ - (*dev->ptrfeed->CtrlProc)(dev, &dev->ptrfeed->ctrl); - - xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", - local->name, ((float)dev->ptrfeed->ctrl.num)/ - ((float)dev->ptrfeed->ctrl.den)); - xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", - local->name, dev->ptrfeed->ctrl.threshold); - } -} - -static Bool -xf86SendDragEvents(DeviceIntPtr device) -{ - LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; - - if (device->button && device->button->buttonsDown > 0) - return (local->flags & XI86_SEND_DRAG_EVENTS); - else - return (TRUE); -} - -/*********************************************************************** - * - * xf86ProcessCommonOptions -- - * - * Process global options. - * - *********************************************************************** - */ -void -xf86ProcessCommonOptions(LocalDevicePtr local, - pointer list) -{ - if (!xf86SetBoolOption(list, "AlwaysCore", 1) || - !xf86SetBoolOption(list, "SendCoreEvents", 1) || - !xf86SetBoolOption(list, "CorePointer", 1) || - !xf86SetBoolOption(list, "CoreKeyboard", 1)) { - xf86Msg(X_CONFIG, "%s: doesn't report core events\n", local->name); - } else { - local->flags |= XI86_ALWAYS_CORE; - xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name); - } - - if (xf86SetBoolOption(list, "SendDragEvents", 1)) { - local->flags |= XI86_SEND_DRAG_EVENTS; - } else { - xf86Msg(X_CONFIG, "%s: doesn't report drag events\n", local->name); - } - - /* Backwards compatibility. */ - local->history_size = GetMotionHistorySize(); -} - -/*********************************************************************** - * - * xf86ActivateDevice -- - * - * Initialize an input device. - * - * Returns TRUE on success, or FALSE otherwise. - *********************************************************************** - */ -int -xf86ActivateDevice(LocalDevicePtr local) -{ - DeviceIntPtr dev; - - if (local->flags & XI86_CONFIGURED) { - dev = AddInputDevice(serverClient, local->device_control, TRUE); - - if (dev == NULL) - { - xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", - local->name); - local->dev = NULL; - return FALSE; - } - - local->atom = MakeAtom(local->type_name, - strlen(local->type_name), - TRUE); - AssignTypeAndName(dev, local->atom, local->name); - dev->public.devicePrivate = (pointer) local; - local->dev = dev; - - dev->coreEvents = local->flags & XI86_ALWAYS_CORE; - dev->type = SLAVE; - dev->spriteInfo->spriteOwner = FALSE; - - dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; - dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; - - RegisterOtherDevice(dev); - XkbSetExtension(dev, ProcessKeyboardEvent); - - if (serverGeneration == 1) - xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", - local->name, local->type_name); - } - - return TRUE; -} - - -/*********************************************************************** - * - * Caller: ProcXOpenDevice - * - * This is the implementation-dependent routine to open an input device. - * Some implementations open all input devices when the server is first - * initialized, and never close them. Other implementations open only - * the X pointer and keyboard devices during server initialization, - * and only open other input devices when some client makes an - * XOpenDevice request. This entry point is for the latter type of - * implementation. - * - * If the physical device is not already open, do it here. In this case, - * you need to keep track of the fact that one or more clients has the - * device open, and physically close it when the last client that has - * it open does an XCloseDevice. - * - * The default implementation is to do nothing (assume all input devices - * are opened during X server initialization and kept open). - * - *********************************************************************** - */ - -void -OpenInputDevice(DeviceIntPtr dev, - ClientPtr client, - int *status) -{ - if (!dev->inited) - ActivateDevice(dev, TRUE); - - *status = Success; -} - -void -CloseInputDevice(DeviceIntPtr dev, - ClientPtr client) -{ -} - -/**************************************************************************** - * - * Caller: ProcXSetDeviceMode - * - * Change the mode of an extension device. - * This function is used to change the mode of a device from reporting - * relative motion to reporting absolute positional information, and - * vice versa. - * The default implementation below is that no such devices are supported. - * - *********************************************************************** - */ - -int -SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) -{ - LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; - - if (local->switch_mode) { - return (*local->switch_mode)(client, dev, mode); - } - else - return BadMatch; -} - - -/*********************************************************************** - * - * Caller: ProcXSetDeviceValuators - * - * Set the value of valuators on an extension input device. - * This function is used to set the initial value of valuators on - * those input devices that are capable of reporting either relative - * motion or an absolute position, and allow an initial position to be set. - * The default implementation below is that no such devices are supported. - * - *********************************************************************** - */ - -int -SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, - int first_valuator, int num_valuators) -{ - LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; - - if (local->set_device_valuators) - return (*local->set_device_valuators)(local, valuators, first_valuator, - num_valuators); - - return BadMatch; -} - - -/*********************************************************************** - * - * Caller: ProcXChangeDeviceControl - * - * Change the specified device controls on an extension input device. - * - *********************************************************************** - */ - -int -ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) -{ - LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; - - if (!local->control_proc) { - switch (control->control) { - case DEVICE_CORE: - return BadMatch; - case DEVICE_RESOLUTION: - case DEVICE_ABS_CALIB: - case DEVICE_ABS_AREA: - case DEVICE_ENABLE: - return Success; - default: - return BadMatch; - } - } - else { - return (*local->control_proc)(local, control); - } -} - -void -AddOtherInputDevices(void) -{ -} - -/* - * Classes without any Match statements match all devices. Otherwise, all - * statements must match. - */ -static Bool -InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs) -{ - char **cur; - Bool match; - - if (iclass->match_product) { - if (!attrs->product) - return FALSE; - /* see if any of the values match */ - for (cur = iclass->match_product, match = FALSE; *cur; cur++) - if (strstr(attrs->product, *cur)) { - match = TRUE; - break; - } - if (!match) - return FALSE; - } - if (iclass->match_vendor) { - if (!attrs->vendor) - return FALSE; - /* see if any of the values match */ - for (cur = iclass->match_vendor, match = FALSE; *cur; cur++) - if (strstr(attrs->vendor, *cur)) { - match = TRUE; - break; - } - if (!match) - return FALSE; - } - if (iclass->match_device) { - if (!attrs->device) - return FALSE; - /* see if any of the values match */ - for (cur = iclass->match_device, match = FALSE; *cur; cur++) -#ifdef HAVE_FNMATCH_H - if (fnmatch(*cur, attrs->device, FNM_PATHNAME) == 0) { -#else - if (strstr(attrs->device, *cur)) { -#endif - match = TRUE; - break; - } - if (!match) - return FALSE; - } - if (iclass->match_tag) { - if (!attrs->tags) - return FALSE; - - for (cur = iclass->match_tag, match = FALSE; *cur && !match; cur++) { - const char *tag; - for(tag = *attrs->tags; *tag; tag++) { - if (!strcmp(tag, *cur)) { - match = TRUE; - break; - } - } - } - - if (!match) - return FALSE; - } - - if (iclass->is_keyboard.set && - iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) - return FALSE; - if (iclass->is_pointer.set && - iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) - return FALSE; - if (iclass->is_joystick.set && - iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) - return FALSE; - if (iclass->is_tablet.set && - iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) - return FALSE; - if (iclass->is_touchpad.set && - iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) - return FALSE; - if (iclass->is_touchscreen.set && - iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) - return FALSE; - return TRUE; -} - -/* - * Merge in any InputClass configurations. Options in each InputClass - * section have more priority than the original device configuration as - * well as any previous InputClass sections. - */ -static int -MergeInputClasses(IDevPtr idev, InputAttributes *attrs) -{ - XF86ConfInputClassPtr cl; - XF86OptionPtr classopts, mergedopts = NULL; - char *classdriver = NULL; - - for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { - if (!InputClassMatches(cl, attrs)) - continue; - - /* Collect class options and merge over previous classes */ - xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", - idev->identifier, cl->identifier); - if (cl->driver) - classdriver = cl->driver; - classopts = xf86optionListDup(cl->option_lst); - mergedopts = xf86optionListMerge(mergedopts, classopts); - } - - /* Apply options to device with InputClass settings preferred. */ - if (classdriver) { - xfree(idev->driver); - idev->driver = xstrdup(classdriver); - if (!idev->driver) { - xf86Msg(X_ERROR, "Failed to allocate memory while merging " - "InputClass configuration"); - return BadAlloc; - } - mergedopts = xf86ReplaceStrOption(mergedopts, "driver", idev->driver); - } - idev->commonOptions = xf86optionListMerge(idev->commonOptions, mergedopts); - - return Success; -} - -/* - * Iterate the list of classes and look for Option "Ignore". Return the - * value of the last matching class and holler when returning TRUE. - */ -static Bool -IgnoreInputClass(IDevPtr idev, InputAttributes *attrs) -{ - XF86ConfInputClassPtr cl; - Bool ignore = FALSE; - const char *ignore_class; - - for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { - if (!InputClassMatches(cl, attrs)) - continue; - if (xf86findOption(cl->option_lst, "Ignore")) { - ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); - ignore_class = cl->identifier; - } - } - - if (ignore) - xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", - idev->identifier, ignore_class); - return ignore; -} - -/** - * Create a new input device, activate and enable it. - * - * Possible return codes: - * BadName .. a bad driver name was supplied. - * BadImplementation ... The driver does not have a PreInit function. This - * is a driver bug. - * BadMatch .. device initialization failed. - * BadAlloc .. too many input devices - * - * @param idev The device, already set up with identifier, driver, and the - * options. - * @param pdev Pointer to the new device, if Success was reported. - * @param enable Enable the device after activating it. - * - * @return Success or an error code - */ -_X_INTERNAL int -xf86NewInputDevice(IDevPtr idev, DeviceIntPtr *pdev, BOOL enable) -{ - InputDriverPtr drv = NULL; - InputInfoPtr pInfo = NULL; - DeviceIntPtr dev = NULL; - int rval; - - /* Memory leak for every attached device if we don't - * test if the module is already loaded first */ - drv = xf86LookupInputDriver(idev->driver); - if (!drv) - if (xf86LoadOneModule(idev->driver, NULL)) - drv = xf86LookupInputDriver(idev->driver); - if (!drv) { - xf86Msg(X_ERROR, "No input driver matching `%s'\n", idev->driver); - rval = BadName; - goto unwind; - } - - if (!drv->PreInit) { - xf86Msg(X_ERROR, - "Input driver `%s' has no PreInit function (ignoring)\n", - drv->driverName); - rval = BadImplementation; - goto unwind; - } - - pInfo = drv->PreInit(drv, idev, 0); - - if (!pInfo) { - xf86Msg(X_ERROR, "PreInit returned NULL for \"%s\"\n", idev->identifier); - rval = BadMatch; - goto unwind; - } - else if (!(pInfo->flags & XI86_CONFIGURED)) { - xf86Msg(X_ERROR, "PreInit failed for input device \"%s\"\n", - idev->identifier); - rval = BadMatch; - goto unwind; - } - - if (!xf86ActivateDevice(pInfo)) - { - rval = BadAlloc; - goto unwind; - } - - dev = pInfo->dev; - rval = ActivateDevice(dev, TRUE); - if (rval != Success) - { - xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", idev->identifier); - RemoveDevice(dev, TRUE); - goto unwind; - } - - /* Enable it if it's properly initialised and we're currently in the VT */ - if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) - { - EnableDevice(dev, TRUE); - if (!dev->enabled) - { - xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", idev->identifier); - rval = BadMatch; - goto unwind; - } - /* send enter/leave event, update sprite window */ - CheckMotion(NULL, dev); - } - - *pdev = dev; - return Success; - -unwind: - if(pInfo) { - if(drv->UnInit) - drv->UnInit(drv, pInfo, 0); - else - xf86DeleteInput(pInfo, 0); - } - return rval; -} - -int -NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, - DeviceIntPtr *pdev) -{ - IDevRec *idev = NULL; - InputOption *option = NULL; - int rval = Success; - int is_auto = 0; - - idev = xcalloc(sizeof(*idev), 1); - if (!idev) - return BadAlloc; - - for (option = options; option; option = option->next) { - if (strcasecmp(option->key, "driver") == 0) { - if (idev->driver) { - rval = BadRequest; - goto unwind; - } - idev->driver = xstrdup(option->value); - if (!idev->driver) { - rval = BadAlloc; - goto unwind; - } - } - - if (strcasecmp(option->key, "name") == 0 || - strcasecmp(option->key, "identifier") == 0) { - if (idev->identifier) { - rval = BadRequest; - goto unwind; - } - idev->identifier = xstrdup(option->value); - if (!idev->identifier) { - rval = BadAlloc; - goto unwind; - } - } - - if (strcmp(option->key, "_source") == 0 && - (strcmp(option->value, "server/hal") == 0 || - strcmp(option->value, "server/udev") == 0)) { - is_auto = 1; - if (!xf86Info.autoAddDevices) { - rval = BadMatch; - goto unwind; - } - } - } - - for (option = options; option; option = option->next) { - /* Steal option key/value strings from the provided list. - * We need those strings, the InputOption list doesn't. */ - idev->commonOptions = xf86addNewOption(idev->commonOptions, - option->key, option->value); - option->key = NULL; - option->value = NULL; - } - - /* Apply InputClass settings */ - if (attrs) { - if (IgnoreInputClass(idev, attrs)) { - rval = BadIDChoice; - goto unwind; - } - - rval = MergeInputClasses(idev, attrs); - if (rval != Success) - goto unwind; - } - - if (!idev->driver || !idev->identifier) { - xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); - rval = BadRequest; - goto unwind; - } - - if (!idev->identifier) { - xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); - return BadMatch; - } - - rval = xf86NewInputDevice(idev, pdev, - (!is_auto || (is_auto && xf86Info.autoEnableDevices))); - if (rval == Success) - return Success; - -unwind: - if (is_auto && !xf86Info.autoAddDevices) - xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); - if(idev->driver) - xfree(idev->driver); - if(idev->identifier) - xfree(idev->identifier); - xf86optionListFree(idev->commonOptions); - xfree(idev); - return rval; -} - -void -DeleteInputDeviceRequest(DeviceIntPtr pDev) -{ - LocalDevicePtr pInfo = (LocalDevicePtr) pDev->public.devicePrivate; - InputDriverPtr drv = NULL; - IDevRec *idev = NULL; - IDevPtr *it; - Bool isMaster = IsMaster(pDev); - - if (pInfo) /* need to get these before RemoveDevice */ - { - drv = pInfo->drv; - idev = pInfo->conf_idev; - } - - OsBlockSignals(); - RemoveDevice(pDev, TRUE); - - if (!isMaster && pInfo != NULL) - { - if(drv->UnInit) - drv->UnInit(drv, pInfo, 0); - else - xf86DeleteInput(pInfo, 0); - - /* devices added through HAL aren't in the config layout */ - it = xf86ConfigLayout.inputs; - while(*it && *it != idev) - it++; - - if (!(*it)) /* end of list, not in the layout */ - { - xfree(idev->driver); - xfree(idev->identifier); - xf86optionListFree(idev->commonOptions); - xfree(idev); - } - } - OsReleaseSignals(); -} - -/* - * convenient functions to post events - */ - -void -xf86PostMotionEvent(DeviceIntPtr device, - int is_absolute, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i = 0; - static int valuators[MAX_VALUATORS]; - - XI_VERIFY_VALUATORS(num_valuators); - - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuators[i] = va_arg(var, int); - va_end(var); - - xf86PostMotionEventP(device, is_absolute, first_valuator, num_valuators, valuators); -} - -void -xf86PostMotionEventP(DeviceIntPtr device, - int is_absolute, - int first_valuator, - int num_valuators, - int *valuators) -{ - int i = 0, nevents = 0; - Bool drag = xf86SendDragEvents(device); - DeviceEvent *event; - int flags = 0; - -#if XFreeXDGA - int index; - int dx = 0, dy = 0; -#endif - - XI_VERIFY_VALUATORS(num_valuators); - - if (is_absolute) - flags = POINTER_ABSOLUTE; - else - flags = POINTER_RELATIVE | POINTER_ACCELERATE; - -#if XFreeXDGA - /* The evdev driver may not always send all axes across. */ - if (num_valuators >= 1 && first_valuator <= 1) { - if (miPointerGetScreen(device)) { - index = miPointerGetScreen(device)->myNum; - if (first_valuator == 0) - { - dx = valuators[0]; - if (is_absolute) - dx -= device->last.valuators[0]; - } - - if (first_valuator == 1 || num_valuators >= 2) - { - dy = valuators[1 - first_valuator]; - if (is_absolute) - dy -= device->last.valuators[1]; - } - - if (DGAStealMotionEvent(device, index, dx, dy)) - return; - } - } -#endif - - nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, - flags, first_valuator, num_valuators, - valuators); - - for (i = 0; i < nevents; i++) { - event = (DeviceEvent*)((xf86Events + i)->event); - /* Don't post core motion events for devices not registered to send - * drag events. */ - if (event->header == ET_Internal && - (event->type != ET_Motion || drag)) { - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); - } - } -} - -void -xf86PostProximityEvent(DeviceIntPtr device, - int is_in, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i; - int valuators[MAX_VALUATORS]; - - XI_VERIFY_VALUATORS(num_valuators); - - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuators[i] = va_arg(var, int); - va_end(var); - - xf86PostProximityEventP(device, is_in, first_valuator, num_valuators, - valuators); - -} - -void -xf86PostProximityEventP(DeviceIntPtr device, - int is_in, - int first_valuator, - int num_valuators, - int *valuators) -{ - int i, nevents; - - XI_VERIFY_VALUATORS(num_valuators); - - nevents = GetProximityEvents(xf86Events, device, - is_in ? ProximityIn : ProximityOut, - first_valuator, num_valuators, valuators); - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); - -} - -void -xf86PostButtonEvent(DeviceIntPtr device, - int is_absolute, - int button, - int is_down, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int valuators[MAX_VALUATORS]; - int i = 0; - - XI_VERIFY_VALUATORS(num_valuators); - - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuators[i] = va_arg(var, int); - va_end(var); - - xf86PostButtonEventP(device, is_absolute, button, is_down, first_valuator, - num_valuators, valuators); - -} - -void -xf86PostButtonEventP(DeviceIntPtr device, - int is_absolute, - int button, - int is_down, - int first_valuator, - int num_valuators, - int *valuators) -{ - int i = 0, nevents = 0; - int flags = 0; - -#if XFreeXDGA - int index; -#endif - - XI_VERIFY_VALUATORS(num_valuators); - - if (is_absolute) - flags = POINTER_ABSOLUTE; - else - flags = POINTER_RELATIVE | POINTER_ACCELERATE; - -#if XFreeXDGA - if (miPointerGetScreen(device)) { - index = miPointerGetScreen(device)->myNum; - if (DGAStealButtonEvent(device, index, button, is_down)) - return; - } -#endif - - nevents = GetPointerEvents(xf86Events, device, - is_down ? ButtonPress : ButtonRelease, button, - flags, first_valuator, num_valuators, valuators); - - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); - -} - -void -xf86PostKeyEvent(DeviceIntPtr device, - unsigned int key_code, - int is_down, - int is_absolute, - int first_valuator, - int num_valuators, - ...) -{ - va_list var; - int i = 0; - static int valuators[MAX_VALUATORS]; - - XI_VERIFY_VALUATORS(num_valuators); - - va_start(var, num_valuators); - for (i = 0; i < num_valuators; i++) - valuators[i] = va_arg(var, int); - va_end(var); - - xf86PostKeyEventP(device, key_code, is_down, is_absolute, first_valuator, - num_valuators, valuators); - -} - -void -xf86PostKeyEventP(DeviceIntPtr device, - unsigned int key_code, - int is_down, - int is_absolute, - int first_valuator, - int num_valuators, - int *valuators) -{ - int i = 0, nevents = 0; - - XI_VERIFY_VALUATORS(num_valuators); - - if (is_absolute) { - nevents = GetKeyboardValuatorEvents(xf86Events, device, - is_down ? KeyPress : KeyRelease, - key_code, first_valuator, - num_valuators, valuators); - } - else { - nevents = GetKeyboardEvents(xf86Events, device, - is_down ? KeyPress : KeyRelease, - key_code); - } - - for (i = 0; i < nevents; i++) - mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); -} - -void -xf86PostKeyboardEvent(DeviceIntPtr device, - unsigned int key_code, - int is_down) -{ - xf86PostKeyEventP(device, key_code, is_down, 0, 0, 0, NULL); -} - -LocalDevicePtr -xf86FirstLocalDevice(void) -{ - return xf86InputDevs; -} - -/* - * Cx - raw data from touch screen - * Sxhigh - scaled highest dimension - * (remember, this is of rows - 1 because of 0 origin) - * Sxlow - scaled lowest dimension - * Rxhigh - highest raw value from touch screen calibration - * Rxlow - lowest raw value from touch screen calibration - * - * This function is the same for X or Y coordinates. - * You may have to reverse the high and low values to compensate for - * different orgins on the touch screen vs X. - */ - -int -xf86ScaleAxis(int Cx, - int Sxhigh, - int Sxlow, - int Rxhigh, - int Rxlow ) -{ - int X; - int64_t dSx = Sxhigh - Sxlow; - int64_t dRx = Rxhigh - Rxlow; - - if (dRx) { - X = (int)(((dSx * (Cx - Rxlow)) / dRx) + Sxlow); - } - else { - X = 0; - ErrorF ("Divide by Zero in xf86ScaleAxis"); - } - - if (X > Sxhigh) - X = Sxhigh; - if (X < Sxlow) - X = Sxlow; - - return (X); -} - -/* - * This function checks the given screen against the current screen and - * makes changes if appropriate. It should be called from an XInput driver's - * ReadInput function before any events are posted, if the device is screen - * specific like a touch screen. - */ -void -xf86XInputSetScreen(LocalDevicePtr local, - int screen_number, - int x, - int y) -{ - if (miPointerGetScreen(local->dev) != - screenInfo.screens[screen_number]) { - miPointerSetScreen(local->dev, screen_number, x, y); - } -} - - -void -xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, - int resolution, int min_res, int max_res) -{ - if (!dev || !dev->valuator) - return; - - InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, - max_res); -} - -/* - * Set the valuator values to be in synch with dix/event.c - * DefineInitialRootWindow(). - */ -void -xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) -{ - if (axnum == 0) { - dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; - dev->last.valuators[0] = dev->valuator->axisVal[0]; - } - else if (axnum == 1) { - dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; - dev->last.valuators[1] = dev->valuator->axisVal[1]; - } - - if(axnum == 0) /* to prevent double invocation */ - ApplyAccelerationSettings(dev); -} - - -/** - * Deactivate a device. Call this function from the driver if you receive a - * read error or something else that spoils your day. - * Device will be moved to the off_devices list, but it will still be there - * until you really clean up after it. - * Notifies the client about an inactive device. - * - * @param panic True if device is unrecoverable and needs to be removed. - */ -void -xf86DisableDevice(DeviceIntPtr dev, Bool panic) -{ - if(!panic) - { - DisableDevice(dev, TRUE); - } else - { - SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); - DeleteInputDeviceRequest(dev); - } -} - -/** - * Reactivate a device. Call this function from the driver if you just found - * out that the read error wasn't quite that bad after all. - * Device will be re-activated, and an event sent to the client. - */ -void -xf86EnableDevice(DeviceIntPtr dev) -{ - EnableDevice(dev, TRUE); -} - -/* end of xf86Xinput.c */ +/* + * Copyright 1995-1999 by Frederic Lepied, France. + * + * 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 Frederic Lepied not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Frederic Lepied makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL FREDERIC LEPIED 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. + * + */ +/* + * Copyright (c) 2000-2002 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Config.h" +#include "xf86Xinput.h" +#include "XIstubs.h" +#include "xf86Optrec.h" +#include "xf86Parser.h" +#include "mipointer.h" +#include "xf86InPriv.h" +#include "compiler.h" +#include "extinit.h" + +#ifdef DPMSExtension +#include +#include "dpmsproc.h" +#endif + +#include "exevents.h" /* AddInputDevice */ +#include "exglobals.h" +#include "eventstr.h" + +#include /* InputClassMatches */ +#ifdef HAVE_FNMATCH_H +#include +#endif + +#include "extnsionst.h" + +#include "windowstr.h" /* screenIsSaved */ + +#include +#include /* for int64_t */ + +#include + +#include "mi.h" + +#include /* dix pointer acceleration */ +#include + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include "xkbsrv.h" + +#include "os.h" + +EventListPtr xf86Events = NULL; + +/** + * Eval config and modify DeviceVelocityRec accordingly + */ +static void +ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, + DeviceVelocityPtr s) +{ + int tempi; + float tempf; + Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); + Atom prop; + + if(!s) + return; + + /* common settings (available via device properties) */ + tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); + if (tempf > 1.0) { + xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", + devname, tempf); + prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + /* select profile by number */ + tempi = xf86SetIntOption(list, "AccelerationProfile", + s->statistics.profile_number); + + prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); + if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, + PropModeReplace, 1, &tempi, FALSE) == Success) { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, + tempi); + } else { + xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", + devname, tempi); + } + + /* set scaling */ + tempf = xf86SetRealOption(list, "ExpectedRate", 0); + prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); + if (tempf > 0) { + tempf = 1000.0 / tempf; + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } else { + tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); + XIChangeDeviceProperty(pDev, prop, float_prop, 32, + PropModeReplace, 1, &tempf, FALSE); + } + + tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); + if (tempi > 1) + InitTrackers(s, tempi); + + s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", + s->initial_range); + + s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); + + tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); + if (tempf >= 0) { + xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", + devname, tempf*100.0); + s->max_rel_diff = tempf; + } + + /* Configure softening. If const deceleration is used, this is expected + * to provide better subpixel information so we enable + * softening by default only if ConstantDeceleration is not used + */ + s->use_softening = xf86SetBoolOption(list, "Softening", + s->const_acceleration == 1.0); + + s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", + s->average_accel); + + s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); +} + +static void +ApplyAccelerationSettings(DeviceIntPtr dev){ + int scheme, i; + DeviceVelocityPtr pVel; + LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; + char* schemeStr; + + if (dev->valuator && dev->ptrfeed) { + schemeStr = xf86SetStrOption(local->options, "AccelerationScheme", ""); + + scheme = dev->valuator->accelScheme.number; + + if (!xf86NameCmp(schemeStr, "predictable")) + scheme = PtrAccelPredictable; + + if (!xf86NameCmp(schemeStr, "lightweight")) + scheme = PtrAccelLightweight; + + if (!xf86NameCmp(schemeStr, "none")) + scheme = PtrAccelNoOp; + + /* reinit scheme if needed */ + if (dev->valuator->accelScheme.number != scheme) { + if (dev->valuator->accelScheme.AccelCleanupProc) { + dev->valuator->accelScheme.AccelCleanupProc(dev); + } + + if (InitPointerAccelerationScheme(dev, scheme)) { + xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", + local->name, schemeStr, scheme); + } else { + xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", + local->name, schemeStr); + scheme = dev->valuator->accelScheme.number; + } + } else { + xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", + local->name, scheme); + } + + free(schemeStr); + + /* process special configuration */ + switch (scheme) { + case PtrAccelPredictable: + pVel = GetDevicePredictableAccelData(dev); + ProcessVelocityConfiguration (dev, local->name, local->options, + pVel); + break; + } + + i = xf86SetIntOption(local->options, "AccelerationNumerator", + dev->ptrfeed->ctrl.num); + if (i >= 0) + dev->ptrfeed->ctrl.num = i; + + i = xf86SetIntOption(local->options, "AccelerationDenominator", + dev->ptrfeed->ctrl.den); + if (i > 0) + dev->ptrfeed->ctrl.den = i; + + i = xf86SetIntOption(local->options, "AccelerationThreshold", + dev->ptrfeed->ctrl.threshold); + if (i >= 0) + dev->ptrfeed->ctrl.threshold = i; + + /* mostly a no-op anyway */ + (*dev->ptrfeed->CtrlProc)(dev, &dev->ptrfeed->ctrl); + + xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", + local->name, ((float)dev->ptrfeed->ctrl.num)/ + ((float)dev->ptrfeed->ctrl.den)); + xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", + local->name, dev->ptrfeed->ctrl.threshold); + } +} + +static Bool +xf86SendDragEvents(DeviceIntPtr device) +{ + LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate; + + if (device->button && device->button->buttonsDown > 0) + return (local->flags & XI86_SEND_DRAG_EVENTS); + else + return (TRUE); +} + +/*********************************************************************** + * + * xf86ProcessCommonOptions -- + * + * Process global options. + * + *********************************************************************** + */ +void +xf86ProcessCommonOptions(LocalDevicePtr local, + pointer list) +{ + if (!xf86SetBoolOption(list, "AlwaysCore", 1) || + !xf86SetBoolOption(list, "SendCoreEvents", 1) || + !xf86SetBoolOption(list, "CorePointer", 1) || + !xf86SetBoolOption(list, "CoreKeyboard", 1)) { + xf86Msg(X_CONFIG, "%s: doesn't report core events\n", local->name); + } else { + local->flags |= XI86_ALWAYS_CORE; + xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name); + } + + if (xf86SetBoolOption(list, "SendDragEvents", 1)) { + local->flags |= XI86_SEND_DRAG_EVENTS; + } else { + xf86Msg(X_CONFIG, "%s: doesn't report drag events\n", local->name); + } + + /* Backwards compatibility. */ + local->history_size = GetMotionHistorySize(); +} + +/*********************************************************************** + * + * xf86ActivateDevice -- + * + * Initialize an input device. + * + * Returns TRUE on success, or FALSE otherwise. + *********************************************************************** + */ +int +xf86ActivateDevice(LocalDevicePtr local) +{ + DeviceIntPtr dev; + + if (local->flags & XI86_CONFIGURED) { + dev = AddInputDevice(serverClient, local->device_control, TRUE); + + if (dev == NULL) + { + xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", + local->name); + local->dev = NULL; + return FALSE; + } + + local->atom = MakeAtom(local->type_name, + strlen(local->type_name), + TRUE); + AssignTypeAndName(dev, local->atom, local->name); + dev->public.devicePrivate = (pointer) local; + local->dev = dev; + + dev->coreEvents = local->flags & XI86_ALWAYS_CORE; + dev->type = SLAVE; + dev->spriteInfo->spriteOwner = FALSE; + + dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; + dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; + + RegisterOtherDevice(dev); + XkbSetExtension(dev, ProcessKeyboardEvent); + + if (serverGeneration == 1) + xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n", + local->name, local->type_name); + } + + return TRUE; +} + + +/*********************************************************************** + * + * Caller: ProcXOpenDevice + * + * This is the implementation-dependent routine to open an input device. + * Some implementations open all input devices when the server is first + * initialized, and never close them. Other implementations open only + * the X pointer and keyboard devices during server initialization, + * and only open other input devices when some client makes an + * XOpenDevice request. This entry point is for the latter type of + * implementation. + * + * If the physical device is not already open, do it here. In this case, + * you need to keep track of the fact that one or more clients has the + * device open, and physically close it when the last client that has + * it open does an XCloseDevice. + * + * The default implementation is to do nothing (assume all input devices + * are opened during X server initialization and kept open). + * + *********************************************************************** + */ + +void +OpenInputDevice(DeviceIntPtr dev, + ClientPtr client, + int *status) +{ + if (!dev->inited) + ActivateDevice(dev, TRUE); + + *status = Success; +} + +void +CloseInputDevice(DeviceIntPtr dev, + ClientPtr client) +{ +} + +/**************************************************************************** + * + * Caller: ProcXSetDeviceMode + * + * Change the mode of an extension device. + * This function is used to change the mode of a device from reporting + * relative motion to reporting absolute positional information, and + * vice versa. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode) +{ + LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; + + if (local->switch_mode) { + return (*local->switch_mode)(client, dev, mode); + } + else + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXSetDeviceValuators + * + * Set the value of valuators on an extension input device. + * This function is used to set the initial value of valuators on + * those input devices that are capable of reporting either relative + * motion or an absolute position, and allow an initial position to be set. + * The default implementation below is that no such devices are supported. + * + *********************************************************************** + */ + +int +SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators, + int first_valuator, int num_valuators) +{ + LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; + + if (local->set_device_valuators) + return (*local->set_device_valuators)(local, valuators, first_valuator, + num_valuators); + + return BadMatch; +} + + +/*********************************************************************** + * + * Caller: ProcXChangeDeviceControl + * + * Change the specified device controls on an extension input device. + * + *********************************************************************** + */ + +int +ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control) +{ + LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; + + if (!local->control_proc) { + switch (control->control) { + case DEVICE_CORE: + return BadMatch; + case DEVICE_RESOLUTION: + case DEVICE_ABS_CALIB: + case DEVICE_ABS_AREA: + case DEVICE_ENABLE: + return Success; + default: + return BadMatch; + } + } + else { + return (*local->control_proc)(local, control); + } +} + +void +AddOtherInputDevices(void) +{ +} + +/* + * Classes without any Match statements match all devices. Otherwise, all + * statements must match. + */ +static Bool +InputClassMatches(XF86ConfInputClassPtr iclass, InputAttributes *attrs) +{ + char **cur; + Bool match; + + if (iclass->match_product) { + if (!attrs->product) + return FALSE; + /* see if any of the values match */ + for (cur = iclass->match_product, match = FALSE; *cur; cur++) + if (strstr(attrs->product, *cur)) { + match = TRUE; + break; + } + if (!match) + return FALSE; + } + if (iclass->match_vendor) { + if (!attrs->vendor) + return FALSE; + /* see if any of the values match */ + for (cur = iclass->match_vendor, match = FALSE; *cur; cur++) + if (strstr(attrs->vendor, *cur)) { + match = TRUE; + break; + } + if (!match) + return FALSE; + } + if (iclass->match_device) { + if (!attrs->device) + return FALSE; + /* see if any of the values match */ + for (cur = iclass->match_device, match = FALSE; *cur; cur++) +#ifdef HAVE_FNMATCH_H + if (fnmatch(*cur, attrs->device, FNM_PATHNAME) == 0) { +#else + if (strstr(attrs->device, *cur)) { +#endif + match = TRUE; + break; + } + if (!match) + return FALSE; + } + if (iclass->match_tag) { + if (!attrs->tags) + return FALSE; + + for (cur = iclass->match_tag, match = FALSE; *cur && !match; cur++) { + const char *tag; + for(tag = *attrs->tags; *tag; tag++) { + if (!strcmp(tag, *cur)) { + match = TRUE; + break; + } + } + } + + if (!match) + return FALSE; + } + + if (iclass->is_keyboard.set && + iclass->is_keyboard.val != !!(attrs->flags & ATTR_KEYBOARD)) + return FALSE; + if (iclass->is_pointer.set && + iclass->is_pointer.val != !!(attrs->flags & ATTR_POINTER)) + return FALSE; + if (iclass->is_joystick.set && + iclass->is_joystick.val != !!(attrs->flags & ATTR_JOYSTICK)) + return FALSE; + if (iclass->is_tablet.set && + iclass->is_tablet.val != !!(attrs->flags & ATTR_TABLET)) + return FALSE; + if (iclass->is_touchpad.set && + iclass->is_touchpad.val != !!(attrs->flags & ATTR_TOUCHPAD)) + return FALSE; + if (iclass->is_touchscreen.set && + iclass->is_touchscreen.val != !!(attrs->flags & ATTR_TOUCHSCREEN)) + return FALSE; + return TRUE; +} + +/* + * Merge in any InputClass configurations. Options in each InputClass + * section have more priority than the original device configuration as + * well as any previous InputClass sections. + */ +static int +MergeInputClasses(IDevPtr idev, InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + XF86OptionPtr classopts, mergedopts = NULL; + char *classdriver = NULL; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, attrs)) + continue; + + /* Collect class options and merge over previous classes */ + xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", + idev->identifier, cl->identifier); + if (cl->driver) + classdriver = cl->driver; + classopts = xf86optionListDup(cl->option_lst); + mergedopts = xf86optionListMerge(mergedopts, classopts); + } + + /* Apply options to device with InputClass settings preferred. */ + if (classdriver) { + free(idev->driver); + idev->driver = xstrdup(classdriver); + if (!idev->driver) { + xf86Msg(X_ERROR, "Failed to allocate memory while merging " + "InputClass configuration"); + return BadAlloc; + } + mergedopts = xf86ReplaceStrOption(mergedopts, "driver", idev->driver); + } + idev->commonOptions = xf86optionListMerge(idev->commonOptions, mergedopts); + + return Success; +} + +/* + * Iterate the list of classes and look for Option "Ignore". Return the + * value of the last matching class and holler when returning TRUE. + */ +static Bool +IgnoreInputClass(IDevPtr idev, InputAttributes *attrs) +{ + XF86ConfInputClassPtr cl; + Bool ignore = FALSE; + const char *ignore_class; + + for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { + if (!InputClassMatches(cl, attrs)) + continue; + if (xf86findOption(cl->option_lst, "Ignore")) { + ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); + ignore_class = cl->identifier; + } + } + + if (ignore) + xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", + idev->identifier, ignore_class); + return ignore; +} + +/** + * Create a new input device, activate and enable it. + * + * Possible return codes: + * BadName .. a bad driver name was supplied. + * BadImplementation ... The driver does not have a PreInit function. This + * is a driver bug. + * BadMatch .. device initialization failed. + * BadAlloc .. too many input devices + * + * @param idev The device, already set up with identifier, driver, and the + * options. + * @param pdev Pointer to the new device, if Success was reported. + * @param enable Enable the device after activating it. + * + * @return Success or an error code + */ +_X_INTERNAL int +xf86NewInputDevice(IDevPtr idev, DeviceIntPtr *pdev, BOOL enable) +{ + InputDriverPtr drv = NULL; + InputInfoPtr pInfo = NULL; + DeviceIntPtr dev = NULL; + int rval; + + /* Memory leak for every attached device if we don't + * test if the module is already loaded first */ + drv = xf86LookupInputDriver(idev->driver); + if (!drv) + if (xf86LoadOneModule(idev->driver, NULL)) + drv = xf86LookupInputDriver(idev->driver); + if (!drv) { + xf86Msg(X_ERROR, "No input driver matching `%s'\n", idev->driver); + rval = BadName; + goto unwind; + } + + if (!drv->PreInit) { + xf86Msg(X_ERROR, + "Input driver `%s' has no PreInit function (ignoring)\n", + drv->driverName); + rval = BadImplementation; + goto unwind; + } + + pInfo = drv->PreInit(drv, idev, 0); + + if (!pInfo) { + xf86Msg(X_ERROR, "PreInit returned NULL for \"%s\"\n", idev->identifier); + rval = BadMatch; + goto unwind; + } + else if (!(pInfo->flags & XI86_CONFIGURED)) { + xf86Msg(X_ERROR, "PreInit failed for input device \"%s\"\n", + idev->identifier); + rval = BadMatch; + goto unwind; + } + + if (!xf86ActivateDevice(pInfo)) + { + rval = BadAlloc; + goto unwind; + } + + dev = pInfo->dev; + rval = ActivateDevice(dev, TRUE); + if (rval != Success) + { + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", idev->identifier); + RemoveDevice(dev, TRUE); + goto unwind; + } + + /* Enable it if it's properly initialised and we're currently in the VT */ + if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) + { + EnableDevice(dev, TRUE); + if (!dev->enabled) + { + xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", idev->identifier); + rval = BadMatch; + goto unwind; + } + /* send enter/leave event, update sprite window */ + CheckMotion(NULL, dev); + } + + *pdev = dev; + return Success; + +unwind: + if(pInfo) { + if(drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + } + return rval; +} + +int +NewInputDeviceRequest (InputOption *options, InputAttributes *attrs, + DeviceIntPtr *pdev) +{ + IDevRec *idev = NULL; + InputOption *option = NULL; + int rval = Success; + int is_auto = 0; + + idev = calloc(sizeof(*idev), 1); + if (!idev) + return BadAlloc; + + for (option = options; option; option = option->next) { + if (strcasecmp(option->key, "driver") == 0) { + if (idev->driver) { + rval = BadRequest; + goto unwind; + } + idev->driver = xstrdup(option->value); + if (!idev->driver) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcasecmp(option->key, "name") == 0 || + strcasecmp(option->key, "identifier") == 0) { + if (idev->identifier) { + rval = BadRequest; + goto unwind; + } + idev->identifier = xstrdup(option->value); + if (!idev->identifier) { + rval = BadAlloc; + goto unwind; + } + } + + if (strcmp(option->key, "_source") == 0 && + (strcmp(option->value, "server/hal") == 0 || + strcmp(option->value, "server/udev") == 0)) { + is_auto = 1; + if (!xf86Info.autoAddDevices) { + rval = BadMatch; + goto unwind; + } + } + } + + for (option = options; option; option = option->next) { + /* Steal option key/value strings from the provided list. + * We need those strings, the InputOption list doesn't. */ + idev->commonOptions = xf86addNewOption(idev->commonOptions, + option->key, option->value); + option->key = NULL; + option->value = NULL; + } + + /* Apply InputClass settings */ + if (attrs) { + if (IgnoreInputClass(idev, attrs)) { + rval = BadIDChoice; + goto unwind; + } + + rval = MergeInputClasses(idev, attrs); + if (rval != Success) + goto unwind; + } + + if (!idev->driver || !idev->identifier) { + xf86Msg(X_INFO, "No input driver/identifier specified (ignoring)\n"); + rval = BadRequest; + goto unwind; + } + + if (!idev->identifier) { + xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); + return BadMatch; + } + + rval = xf86NewInputDevice(idev, pdev, + (!is_auto || (is_auto && xf86Info.autoEnableDevices))); + if (rval == Success) + return Success; + +unwind: + if (is_auto && !xf86Info.autoAddDevices) + xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); + if(idev->driver) + free(idev->driver); + if(idev->identifier) + free(idev->identifier); + xf86optionListFree(idev->commonOptions); + free(idev); + return rval; +} + +void +DeleteInputDeviceRequest(DeviceIntPtr pDev) +{ + LocalDevicePtr pInfo = (LocalDevicePtr) pDev->public.devicePrivate; + InputDriverPtr drv = NULL; + IDevRec *idev = NULL; + IDevPtr *it; + Bool isMaster = IsMaster(pDev); + + if (pInfo) /* need to get these before RemoveDevice */ + { + drv = pInfo->drv; + idev = pInfo->conf_idev; + } + + OsBlockSignals(); + RemoveDevice(pDev, TRUE); + + if (!isMaster && pInfo != NULL) + { + if(drv->UnInit) + drv->UnInit(drv, pInfo, 0); + else + xf86DeleteInput(pInfo, 0); + + /* devices added through HAL aren't in the config layout */ + it = xf86ConfigLayout.inputs; + while(*it && *it != idev) + it++; + + if (!(*it)) /* end of list, not in the layout */ + { + free(idev->driver); + free(idev->identifier); + xf86optionListFree(idev->commonOptions); + free(idev); + } + } + OsReleaseSignals(); +} + +/* + * convenient functions to post events + */ + +void +xf86PostMotionEvent(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + static int valuators[MAX_VALUATORS]; + + XI_VERIFY_VALUATORS(num_valuators); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuators[i] = va_arg(var, int); + va_end(var); + + xf86PostMotionEventP(device, is_absolute, first_valuator, num_valuators, valuators); +} + +void +xf86PostMotionEventP(DeviceIntPtr device, + int is_absolute, + int first_valuator, + int num_valuators, + int *valuators) +{ + int i = 0, nevents = 0; + Bool drag = xf86SendDragEvents(device); + DeviceEvent *event; + int flags = 0; + +#if XFreeXDGA + int index; + int dx = 0, dy = 0; +#endif + + XI_VERIFY_VALUATORS(num_valuators); + + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + +#if XFreeXDGA + /* The evdev driver may not always send all axes across. */ + if (num_valuators >= 1 && first_valuator <= 1) { + if (miPointerGetScreen(device)) { + index = miPointerGetScreen(device)->myNum; + if (first_valuator == 0) + { + dx = valuators[0]; + if (is_absolute) + dx -= device->last.valuators[0]; + } + + if (first_valuator == 1 || num_valuators >= 2) + { + dy = valuators[1 - first_valuator]; + if (is_absolute) + dy -= device->last.valuators[1]; + } + + if (DGAStealMotionEvent(device, index, dx, dy)) + return; + } + } +#endif + + nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, + flags, first_valuator, num_valuators, + valuators); + + for (i = 0; i < nevents; i++) { + event = (DeviceEvent*)((xf86Events + i)->event); + /* Don't post core motion events for devices not registered to send + * drag events. */ + if (event->header == ET_Internal && + (event->type != ET_Motion || drag)) { + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + } + } +} + +void +xf86PostProximityEvent(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i; + int valuators[MAX_VALUATORS]; + + XI_VERIFY_VALUATORS(num_valuators); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuators[i] = va_arg(var, int); + va_end(var); + + xf86PostProximityEventP(device, is_in, first_valuator, num_valuators, + valuators); + +} + +void +xf86PostProximityEventP(DeviceIntPtr device, + int is_in, + int first_valuator, + int num_valuators, + int *valuators) +{ + int i, nevents; + + XI_VERIFY_VALUATORS(num_valuators); + + nevents = GetProximityEvents(xf86Events, device, + is_in ? ProximityIn : ProximityOut, + first_valuator, num_valuators, valuators); + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostButtonEvent(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int valuators[MAX_VALUATORS]; + int i = 0; + + XI_VERIFY_VALUATORS(num_valuators); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuators[i] = va_arg(var, int); + va_end(var); + + xf86PostButtonEventP(device, is_absolute, button, is_down, first_valuator, + num_valuators, valuators); + +} + +void +xf86PostButtonEventP(DeviceIntPtr device, + int is_absolute, + int button, + int is_down, + int first_valuator, + int num_valuators, + int *valuators) +{ + int i = 0, nevents = 0; + int flags = 0; + +#if XFreeXDGA + int index; +#endif + + XI_VERIFY_VALUATORS(num_valuators); + + if (is_absolute) + flags = POINTER_ABSOLUTE; + else + flags = POINTER_RELATIVE | POINTER_ACCELERATE; + +#if XFreeXDGA + if (miPointerGetScreen(device)) { + index = miPointerGetScreen(device)->myNum; + if (DGAStealButtonEvent(device, index, button, is_down)) + return; + } +#endif + + nevents = GetPointerEvents(xf86Events, device, + is_down ? ButtonPress : ButtonRelease, button, + flags, first_valuator, num_valuators, valuators); + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); + +} + +void +xf86PostKeyEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + ...) +{ + va_list var; + int i = 0; + static int valuators[MAX_VALUATORS]; + + XI_VERIFY_VALUATORS(num_valuators); + + va_start(var, num_valuators); + for (i = 0; i < num_valuators; i++) + valuators[i] = va_arg(var, int); + va_end(var); + + xf86PostKeyEventP(device, key_code, is_down, is_absolute, first_valuator, + num_valuators, valuators); + +} + +void +xf86PostKeyEventP(DeviceIntPtr device, + unsigned int key_code, + int is_down, + int is_absolute, + int first_valuator, + int num_valuators, + int *valuators) +{ + int i = 0, nevents = 0; + + XI_VERIFY_VALUATORS(num_valuators); + + if (is_absolute) { + nevents = GetKeyboardValuatorEvents(xf86Events, device, + is_down ? KeyPress : KeyRelease, + key_code, first_valuator, + num_valuators, valuators); + } + else { + nevents = GetKeyboardEvents(xf86Events, device, + is_down ? KeyPress : KeyRelease, + key_code); + } + + for (i = 0; i < nevents; i++) + mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event)); +} + +void +xf86PostKeyboardEvent(DeviceIntPtr device, + unsigned int key_code, + int is_down) +{ + xf86PostKeyEventP(device, key_code, is_down, 0, 0, 0, NULL); +} + +LocalDevicePtr +xf86FirstLocalDevice(void) +{ + return xf86InputDevs; +} + +/* + * Cx - raw data from touch screen + * Sxhigh - scaled highest dimension + * (remember, this is of rows - 1 because of 0 origin) + * Sxlow - scaled lowest dimension + * Rxhigh - highest raw value from touch screen calibration + * Rxlow - lowest raw value from touch screen calibration + * + * This function is the same for X or Y coordinates. + * You may have to reverse the high and low values to compensate for + * different orgins on the touch screen vs X. + */ + +int +xf86ScaleAxis(int Cx, + int Sxhigh, + int Sxlow, + int Rxhigh, + int Rxlow ) +{ + int X; + int64_t dSx = Sxhigh - Sxlow; + int64_t dRx = Rxhigh - Rxlow; + + if (dRx) { + X = (int)(((dSx * (Cx - Rxlow)) / dRx) + Sxlow); + } + else { + X = 0; + ErrorF ("Divide by Zero in xf86ScaleAxis"); + } + + if (X > Sxhigh) + X = Sxhigh; + if (X < Sxlow) + X = Sxlow; + + return (X); +} + +/* + * This function checks the given screen against the current screen and + * makes changes if appropriate. It should be called from an XInput driver's + * ReadInput function before any events are posted, if the device is screen + * specific like a touch screen. + */ +void +xf86XInputSetScreen(LocalDevicePtr local, + int screen_number, + int x, + int y) +{ + if (miPointerGetScreen(local->dev) != + screenInfo.screens[screen_number]) { + miPointerSetScreen(local->dev, screen_number, x, y); + } +} + + +void +xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, + int resolution, int min_res, int max_res) +{ + if (!dev || !dev->valuator) + return; + + InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, + max_res); +} + +/* + * Set the valuator values to be in synch with dix/event.c + * DefineInitialRootWindow(). + */ +void +xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) +{ + if (axnum == 0) { + dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; + dev->last.valuators[0] = dev->valuator->axisVal[0]; + } + else if (axnum == 1) { + dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; + dev->last.valuators[1] = dev->valuator->axisVal[1]; + } + + if(axnum == 0) /* to prevent double invocation */ + ApplyAccelerationSettings(dev); +} + + +/** + * Deactivate a device. Call this function from the driver if you receive a + * read error or something else that spoils your day. + * Device will be moved to the off_devices list, but it will still be there + * until you really clean up after it. + * Notifies the client about an inactive device. + * + * @param panic True if device is unrecoverable and needs to be removed. + */ +void +xf86DisableDevice(DeviceIntPtr dev, Bool panic) +{ + if(!panic) + { + DisableDevice(dev, TRUE); + } else + { + SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); + DeleteInputDeviceRequest(dev); + } +} + +/** + * Reactivate a device. Call this function from the driver if you just found + * out that the read error wasn't quite that bad after all. + * Device will be re-activated, and an event sent to the client. + */ +void +xf86EnableDevice(DeviceIntPtr dev) +{ + EnableDevice(dev, TRUE); +} + +/* end of xf86Xinput.c */ diff --git a/xorg-server/hw/xfree86/common/xf86cmap.c b/xorg-server/hw/xfree86/common/xf86cmap.c index e266ffb6d..fa0ebc8eb 100644 --- a/xorg-server/hw/xfree86/common/xf86cmap.c +++ b/xorg-server/hw/xfree86/common/xf86cmap.c @@ -1,1166 +1,1166 @@ -/* - * Copyright (c) 1998-2001 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) -#include -#else -#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ -#include -#undef _XOPEN_SOURCE -#endif - -#include -#include "misc.h" -#include -#include "colormapst.h" -#include "scrnintstr.h" - -#include "resource.h" - -#include "xf86.h" -#include "xf86_OSproc.h" -#include "xf86str.h" -#include "micmap.h" -#include "xf86Crtc.h" - -#ifdef XFreeXDGA -#include -#include "dgaproc.h" -#endif - -#include "xf86cmap.h" - -#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \ - ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field) -#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ - ((pScreen)->field = wrapper) - -#define LOAD_PALETTE(pmap) \ - ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \ - ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \ - xf86Screens[pmap->pScreen->myNum]->vtSema || pScreenPriv->isDGAmode)) - - -typedef struct _CMapLink { - ColormapPtr cmap; - struct _CMapLink *next; -} CMapLink, *CMapLinkPtr; - -typedef struct { - ScrnInfoPtr pScrn; - CloseScreenProcPtr CloseScreen; - CreateColormapProcPtr CreateColormap; - DestroyColormapProcPtr DestroyColormap; - InstallColormapProcPtr InstallColormap; - StoreColorsProcPtr StoreColors; - Bool (*EnterVT)(int, int); - Bool (*SwitchMode)(int, DisplayModePtr, int); - int (*SetDGAMode)(int, int, DGADevicePtr); - xf86ChangeGammaProc *ChangeGamma; - int maxColors; - int sigRGBbits; - int gammaElements; - LOCO *gamma; - int *PreAllocIndices; - CMapLinkPtr maps; - unsigned int flags; - Bool isDGAmode; -} CMapScreenRec, *CMapScreenPtr; - -typedef struct { - int numColors; - LOCO *colors; - Bool recalculate; - int overscan; -} CMapColormapRec, *CMapColormapPtr; - -static int CMapScreenKeyIndex; -static DevPrivateKey CMapScreenKey; -static int CMapColormapKeyIndex; -static DevPrivateKey CMapColormapKey = &CMapColormapKeyIndex; - -static void CMapInstallColormap(ColormapPtr); -static void CMapStoreColors(ColormapPtr, int, xColorItem *); -static Bool CMapCloseScreen (int, ScreenPtr); -static Bool CMapCreateColormap (ColormapPtr); -static void CMapDestroyColormap (ColormapPtr); - -static Bool CMapEnterVT(int, int); -static Bool CMapSwitchMode(int, DisplayModePtr, int); -#ifdef XFreeXDGA -static int CMapSetDGAMode(int, int, DGADevicePtr); -#endif -static int CMapChangeGamma(int, Gamma); - -static void ComputeGamma(CMapScreenPtr); -static Bool CMapAllocateColormapPrivate(ColormapPtr); -static void CMapRefreshColors(ColormapPtr, int, int*); -static void CMapSetOverscan(ColormapPtr, int, int *); -static void CMapReinstallMap(ColormapPtr); -static void CMapUnwrapScreen(ScreenPtr pScreen); - - - -Bool xf86HandleColormaps( - ScreenPtr pScreen, - int maxColors, - int sigRGBbits, - xf86LoadPaletteProc *loadPalette, - xf86SetOverscanProc *setOverscan, - unsigned int flags -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - ColormapPtr pDefMap = NULL; - CMapScreenPtr pScreenPriv; - LOCO *gamma; - int *indices; - int elements; - - /* If we support a better colormap system, then pretend we succeeded. */ - if (xf86_crtc_supports_gamma(pScrn)) - return TRUE; - - if(!maxColors || !sigRGBbits || !loadPalette) - return FALSE; - - CMapScreenKey = &CMapScreenKeyIndex; - - elements = 1 << sigRGBbits; - - if(!(gamma = xalloc(elements * sizeof(LOCO)))) - return FALSE; - - if(!(indices = xalloc(maxColors * sizeof(int)))) { - xfree(gamma); - return FALSE; - } - - if(!(pScreenPriv = xalloc(sizeof(CMapScreenRec)))) { - xfree(gamma); - xfree(indices); - return FALSE; - } - - dixSetPrivate(&pScreen->devPrivates, CMapScreenKey, pScreenPriv); - - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreenPriv->CreateColormap = pScreen->CreateColormap; - pScreenPriv->DestroyColormap = pScreen->DestroyColormap; - pScreenPriv->InstallColormap = pScreen->InstallColormap; - pScreenPriv->StoreColors = pScreen->StoreColors; - pScreen->CloseScreen = CMapCloseScreen; - pScreen->CreateColormap = CMapCreateColormap; - pScreen->DestroyColormap = CMapDestroyColormap; - pScreen->InstallColormap = CMapInstallColormap; - pScreen->StoreColors = CMapStoreColors; - - pScreenPriv->pScrn = pScrn; - pScrn->LoadPalette = loadPalette; - pScrn->SetOverscan = setOverscan; - pScreenPriv->maxColors = maxColors; - pScreenPriv->sigRGBbits = sigRGBbits; - pScreenPriv->gammaElements = elements; - pScreenPriv->gamma = gamma; - pScreenPriv->PreAllocIndices = indices; - pScreenPriv->maps = NULL; - pScreenPriv->flags = flags; - pScreenPriv->isDGAmode = FALSE; - - pScreenPriv->EnterVT = pScrn->EnterVT; - pScreenPriv->SwitchMode = pScrn->SwitchMode; - pScreenPriv->SetDGAMode = pScrn->SetDGAMode; - pScreenPriv->ChangeGamma = pScrn->ChangeGamma; - - if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) { - pScrn->EnterVT = CMapEnterVT; - if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode) - pScrn->SwitchMode = CMapSwitchMode; - } -#ifdef XFreeXDGA - pScrn->SetDGAMode = CMapSetDGAMode; -#endif - pScrn->ChangeGamma = CMapChangeGamma; - - ComputeGamma(pScreenPriv); - - /* get the default map */ - dixLookupResourceByType((pointer *)&pDefMap, pScreen->defColormap, - RT_COLORMAP, serverClient, DixInstallAccess); - - if(!CMapAllocateColormapPrivate(pDefMap)) { - CMapUnwrapScreen(pScreen); - return FALSE; - } - - /* Force the initial map to be loaded */ - SetInstalledmiColormap(pScreen, NULL); - CMapInstallColormap(pDefMap); - return TRUE; -} - - -/**** Screen functions ****/ - - -static Bool -CMapCloseScreen (int i, ScreenPtr pScreen) -{ - CMapUnwrapScreen(pScreen); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static Bool -CMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv) -{ - if (pVisual->nplanes > 16) - return TRUE; - return ((1 << pVisual->nplanes) > pScreenPriv->maxColors); -} - -static Bool -CMapAllocateColormapPrivate(ColormapPtr pmap) -{ - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pmap->pScreen->devPrivates, CMapScreenKey); - CMapColormapPtr pColPriv; - CMapLinkPtr pLink; - int numColors; - LOCO *colors; - - if (CMapColormapUseMax(pmap->pVisual, pScreenPriv)) - numColors = pmap->pVisual->ColormapEntries; - else - numColors = 1 << pmap->pVisual->nplanes; - - if(!(colors = xalloc(numColors * sizeof(LOCO)))) - return FALSE; - - if(!(pColPriv = xalloc(sizeof(CMapColormapRec)))) { - xfree(colors); - return FALSE; - } - - dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv); - - pColPriv->numColors = numColors; - pColPriv->colors = colors; - pColPriv->recalculate = TRUE; - pColPriv->overscan = -1; - - /* add map to list */ - pLink = xalloc(sizeof(CMapLink)); - if(pLink) { - pLink->cmap = pmap; - pLink->next = pScreenPriv->maps; - pScreenPriv->maps = pLink; - } - - return TRUE; -} - -static Bool -CMapCreateColormap (ColormapPtr pmap) -{ - ScreenPtr pScreen = pmap->pScreen; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - Bool ret = FALSE; - - pScreen->CreateColormap = pScreenPriv->CreateColormap; - if((*pScreen->CreateColormap)(pmap)) { - if(CMapAllocateColormapPrivate(pmap)) - ret = TRUE; - } - pScreen->CreateColormap = CMapCreateColormap; - - return ret; -} - -static void -CMapDestroyColormap (ColormapPtr cmap) -{ - ScreenPtr pScreen = cmap->pScreen; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( - &cmap->devPrivates, CMapColormapKey); - CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps; - - if(pColPriv) { - if(pColPriv->colors) xfree(pColPriv->colors); - xfree(pColPriv); - } - - /* remove map from list */ - while(pLink) { - if(pLink->cmap == cmap) { - if(prevLink) - prevLink->next = pLink->next; - else - pScreenPriv->maps = pLink->next; - xfree(pLink); - break; - } - prevLink = pLink; - pLink = pLink->next; - } - - if(pScreenPriv->DestroyColormap) { - pScreen->DestroyColormap = pScreenPriv->DestroyColormap; - (*pScreen->DestroyColormap)(cmap); - pScreen->DestroyColormap = CMapDestroyColormap; - } -} - - - -static void -CMapStoreColors( - ColormapPtr pmap, - int ndef, - xColorItem *pdefs -){ - ScreenPtr pScreen = pmap->pScreen; - VisualPtr pVisual = pmap->pVisual; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - int *indices = pScreenPriv->PreAllocIndices; - int num = ndef; - - /* At the moment this isn't necessary since there's nobody below us */ - pScreen->StoreColors = pScreenPriv->StoreColors; - (*pScreen->StoreColors)(pmap, ndef, pdefs); - pScreen->StoreColors = CMapStoreColors; - - /* should never get here for these */ - if( (pVisual->class == TrueColor) || - (pVisual->class == StaticColor) || - (pVisual->class == StaticGray)) - return; - - if(pVisual->class == DirectColor) { - CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( - &pmap->devPrivates, CMapColormapKey); - int i; - - if (CMapColormapUseMax(pVisual, pScreenPriv)) { - int index; - - num = 0; - while(ndef--) { - if(pdefs[ndef].flags & DoRed) { - index = (pdefs[ndef].pixel & pVisual->redMask) >> - pVisual->offsetRed; - i = num; - while(i--) - if(indices[i] == index) break; - if(i == -1) - indices[num++] = index; - } - if(pdefs[ndef].flags & DoGreen) { - index = (pdefs[ndef].pixel & pVisual->greenMask) >> - pVisual->offsetGreen; - i = num; - while(i--) - if(indices[i] == index) break; - if(i == -1) - indices[num++] = index; - } - if(pdefs[ndef].flags & DoBlue) { - index = (pdefs[ndef].pixel & pVisual->blueMask) >> - pVisual->offsetBlue; - i = num; - while(i--) - if(indices[i] == index) break; - if(i == -1) - indices[num++] = index; - } - } - - } else { - /* not really as overkill as it seems */ - num = pColPriv->numColors; - for(i = 0; i < pColPriv->numColors; i++) - indices[i] = i; - } - } else { - while(ndef--) - indices[ndef] = pdefs[ndef].pixel; - } - - CMapRefreshColors(pmap, num, indices); -} - - -static void -CMapInstallColormap(ColormapPtr pmap) -{ - ScreenPtr pScreen = pmap->pScreen; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - - if (pmap == GetInstalledmiColormap(pmap->pScreen)) - return; - - pScreen->InstallColormap = pScreenPriv->InstallColormap; - (*pScreen->InstallColormap)(pmap); - pScreen->InstallColormap = CMapInstallColormap; - - /* Important. We let the lower layers, namely DGA, - overwrite the choice of Colormap to install */ - if (GetInstalledmiColormap(pmap->pScreen)) - pmap = GetInstalledmiColormap(pmap->pScreen); - - if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && - (pmap->pVisual->class == TrueColor) && - CMapColormapUseMax(pmap->pVisual, pScreenPriv)) - return; - - if(LOAD_PALETTE(pmap)) - CMapReinstallMap(pmap); -} - - -/**** ScrnInfoRec functions ****/ - -static Bool -CMapEnterVT(int index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - - if((*pScreenPriv->EnterVT)(index, flags)) { - if(GetInstalledmiColormap(pScreen)) - CMapReinstallMap(GetInstalledmiColormap(pScreen)); - return TRUE; - } - return FALSE; -} - - -static Bool -CMapSwitchMode(int index, DisplayModePtr mode, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - - if((*pScreenPriv->SwitchMode)(index, mode, flags)) { - if(GetInstalledmiColormap(pScreen)) - CMapReinstallMap(GetInstalledmiColormap(pScreen)); - return TRUE; - } - return FALSE; -} - -#ifdef XFreeXDGA -static int -CMapSetDGAMode(int index, int num, DGADevicePtr dev) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - int ret; - - ret = (*pScreenPriv->SetDGAMode)(index, num, dev); - - pScreenPriv->isDGAmode = DGAActive(index); - - if(!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen) - && xf86Screens[pScreen->myNum]->vtSema) - CMapReinstallMap(GetInstalledmiColormap(pScreen)); - - return ret; -} -#endif - - -/**** Utilities ****/ - -static void -CMapReinstallMap(ColormapPtr pmap) -{ - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pmap->pScreen->devPrivates, CMapScreenKey); - CMapColormapPtr cmapPriv = (CMapColormapPtr)dixLookupPrivate( - &pmap->devPrivates, CMapColormapKey); - ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; - int i = cmapPriv->numColors; - int *indices = pScreenPriv->PreAllocIndices; - - while(i--) - indices[i] = i; - - if(cmapPriv->recalculate) - CMapRefreshColors(pmap, cmapPriv->numColors, indices); - else { - (*pScrn->LoadPalette)(pScrn, cmapPriv->numColors, - indices, cmapPriv->colors, pmap->pVisual); - if (pScrn->SetOverscan) { -#ifdef DEBUGOVERSCAN - ErrorF("SetOverscan() called from CMapReinstallMap\n"); -#endif - pScrn->SetOverscan(pScrn, cmapPriv->overscan); - } - } - - cmapPriv->recalculate = FALSE; -} - - -static void -CMapRefreshColors(ColormapPtr pmap, int defs, int* indices) -{ - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pmap->pScreen->devPrivates, CMapScreenKey); - CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( - &pmap->devPrivates, CMapColormapKey); - VisualPtr pVisual = pmap->pVisual; - ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; - int numColors, i; - LOCO *gamma, *colors; - EntryPtr entry; - int reds, greens, blues, maxValue, index, shift; - - numColors = pColPriv->numColors; - shift = 16 - pScreenPriv->sigRGBbits; - maxValue = (1 << pScreenPriv->sigRGBbits) - 1; - gamma = pScreenPriv->gamma; - colors = pColPriv->colors; - - reds = pVisual->redMask >> pVisual->offsetRed; - greens = pVisual->greenMask >> pVisual->offsetGreen; - blues = pVisual->blueMask >> pVisual->offsetBlue; - - switch(pVisual->class) { - case StaticGray: - for(i = 0; i < numColors; i++) { - index = (i+1) * maxValue / numColors; - colors[i].red = gamma[index].red; - colors[i].green = gamma[index].green; - colors[i].blue = gamma[index].blue; - } - break; - case TrueColor: - if (CMapColormapUseMax(pVisual, pScreenPriv)) { - for(i = 0; i <= reds; i++) - colors[i].red = gamma[i * maxValue / reds].red; - for(i = 0; i <= greens; i++) - colors[i].green = gamma[i * maxValue / greens].green; - for(i = 0; i <= blues; i++) - colors[i].blue = gamma[i * maxValue / blues].blue; - break; - } - for(i = 0; i < numColors; i++) { - colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) * - maxValue / reds].red; - colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) * - maxValue / greens].green; - colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) * - maxValue / blues].blue; - } - break; - case StaticColor: - case PseudoColor: - case GrayScale: - for(i = 0; i < defs; i++) { - index = indices[i]; - entry = (EntryPtr)&pmap->red[index]; - - if(entry->fShared) { - colors[index].red = - gamma[entry->co.shco.red->color >> shift].red; - colors[index].green = - gamma[entry->co.shco.green->color >> shift].green; - colors[index].blue = - gamma[entry->co.shco.blue->color >> shift].blue; - } else { - colors[index].red = - gamma[entry->co.local.red >> shift].red; - colors[index].green = - gamma[entry->co.local.green >> shift].green; - colors[index].blue = - gamma[entry->co.local.blue >> shift].blue; - } - } - break; - case DirectColor: - if (CMapColormapUseMax(pVisual, pScreenPriv)) { - for(i = 0; i < defs; i++) { - index = indices[i]; - if(index <= reds) - colors[index].red = - gamma[pmap->red[index].co.local.red >> shift].red; - if(index <= greens) - colors[index].green = - gamma[pmap->green[index].co.local.green >> shift].green; - if(index <= blues) - colors[index].blue = - gamma[pmap->blue[index].co.local.blue >> shift].blue; - - } - break; - } - for(i = 0; i < defs; i++) { - index = indices[i]; - - colors[index].red = gamma[pmap->red[ - (index >> pVisual->offsetRed) & reds - ].co.local.red >> shift].red; - colors[index].green = gamma[pmap->green[ - (index >> pVisual->offsetGreen) & greens - ].co.local.green >> shift].green; - colors[index].blue = gamma[pmap->blue[ - (index >> pVisual->offsetBlue) & blues - ].co.local.blue >> shift].blue; - } - break; - } - - - if(LOAD_PALETTE(pmap)) - (*pScrn->LoadPalette)(pScreenPriv->pScrn, defs, indices, - colors, pmap->pVisual); - - if (pScrn->SetOverscan) - CMapSetOverscan(pmap, defs, indices); - -} - -static Bool -CMapCompareColors(LOCO *color1, LOCO *color2) -{ - /* return TRUE if the color1 is "closer" to black than color2 */ -#ifdef DEBUGOVERSCAN - ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n", - color1->red, color1->green, color1->blue, - color2->red, color2->green, color2->blue, - color1->red + color1->green + color1->blue, - color2->red + color2->green + color2->blue); -#endif - return (color1->red + color1->green + color1->blue < - color2->red + color2->green + color2->blue); -} - -static void -CMapSetOverscan(ColormapPtr pmap, int defs, int *indices) -{ - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pmap->pScreen->devPrivates, CMapScreenKey); - CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( - &pmap->devPrivates, CMapColormapKey); - ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; - VisualPtr pVisual = pmap->pVisual; - int i; - LOCO *colors; - int index; - Bool newOverscan = FALSE; - int overscan, tmpOverscan; - - colors = pColPriv->colors; - overscan = pColPriv->overscan; - - /* - * Search for a new overscan index in the following cases: - * - * - The index hasn't yet been initialised.  In this case search - * for an index that is black or a close match to black. - * - * - The colour of the old index is changed. In this case search - * all indices for a black or close match to black. - * - * - The colour of the old index wasn't black. In this case only - * search the indices that were changed for a better match to black. - */ - - switch (pVisual->class) { - case StaticGray: - case TrueColor: - /* Should only come here once. Initialise the overscan index to 0 */ - overscan = 0; - newOverscan = TRUE; - break; - case StaticColor: - /* - * Only come here once, but search for the overscan in the same way - * as for the other cases. - */ - case DirectColor: - case PseudoColor: - case GrayScale: - if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) { - /* Uninitialised */ - newOverscan = TRUE; - } else { - /* Check if the overscan was changed */ - for (i = 0; i < defs; i++) { - index = indices[i]; - if (index == overscan) { - newOverscan = TRUE; - break; - } - } - } - if (newOverscan) { - /* The overscan is either uninitialised or it has been changed */ - - if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) - tmpOverscan = pScreenPriv->maxColors - 1; - else - tmpOverscan = overscan; - - /* search all entries for a close match to black */ - for (i = pScreenPriv->maxColors - 1; i >= 0; i--) { - if (colors[i].red == 0 && colors[i].green == 0 && - colors[i].blue == 0) { - overscan = i; -#ifdef DEBUGOVERSCAN - ErrorF("Black found at index 0x%02x\n", i); -#endif - break; - } else { -#ifdef DEBUGOVERSCAN - ErrorF("0x%02x: ", i); -#endif - if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) { - tmpOverscan = i; -#ifdef DEBUGOVERSCAN - ErrorF("possible \"Black\" at index 0x%02x\n", i); -#endif - } - } - } - if (i < 0) - overscan = tmpOverscan; - } else { - /* Check of the old overscan wasn't black */ - if (colors[overscan].red != 0 || colors[overscan].green != 0 || - colors[overscan].blue != 0) { - int oldOverscan = tmpOverscan = overscan; - /* See of there is now a better match */ - for (i = 0; i < defs; i++) { - index = indices[i]; - if (colors[index].red == 0 && colors[index].green == 0 && - colors[index].blue == 0) { - overscan = index; -#ifdef DEBUGOVERSCAN - ErrorF("Black found at index 0x%02x\n", index); -#endif - break; - } else { -#ifdef DEBUGOVERSCAN - ErrorF("0x%02x: ", index); -#endif - if (CMapCompareColors(&colors[index], - &colors[tmpOverscan])) { - tmpOverscan = index; -#ifdef DEBUGOVERSCAN - ErrorF("possible \"Black\" at index 0x%02x\n", - index); -#endif - } - } - } - if (i == defs) - overscan = tmpOverscan; - if (overscan != oldOverscan) - newOverscan = TRUE; - } - } - break; - } - if (newOverscan) { - pColPriv->overscan = overscan; - if (LOAD_PALETTE(pmap)) { -#ifdef DEBUGOVERSCAN - ErrorF("SetOverscan() called from CmapSetOverscan\n"); -#endif - pScrn->SetOverscan(pScreenPriv->pScrn, overscan); - } - } -} - -static void -CMapUnwrapScreen(ScreenPtr pScreen) -{ - CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, CMapScreenKey); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->CreateColormap = pScreenPriv->CreateColormap; - pScreen->DestroyColormap = pScreenPriv->DestroyColormap; - pScreen->InstallColormap = pScreenPriv->InstallColormap; - pScreen->StoreColors = pScreenPriv->StoreColors; - - pScrn->EnterVT = pScreenPriv->EnterVT; - pScrn->SwitchMode = pScreenPriv->SwitchMode; - pScrn->SetDGAMode = pScreenPriv->SetDGAMode; - pScrn->ChangeGamma = pScreenPriv->ChangeGamma; - - xfree(pScreenPriv->gamma); - xfree(pScreenPriv->PreAllocIndices); - xfree(pScreenPriv); -} - - -static void -ComputeGamma(CMapScreenPtr priv) -{ - int elements = priv->gammaElements - 1; - double RedGamma, GreenGamma, BlueGamma; - int i; - -#ifndef DONT_CHECK_GAMMA - /* This check is to catch drivers that are not initialising pScrn->gamma */ - if (priv->pScrn->gamma.red < GAMMA_MIN || - priv->pScrn->gamma.red > GAMMA_MAX || - priv->pScrn->gamma.green < GAMMA_MIN || - priv->pScrn->gamma.green > GAMMA_MAX || - priv->pScrn->gamma.blue < GAMMA_MIN || - priv->pScrn->gamma.blue > GAMMA_MAX) { - - xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, - "The %s driver didn't call xf86SetGamma() to initialise\n" - "\tthe gamma values.\n", priv->pScrn->driverName); - xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, - "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName); - priv->pScrn->gamma.red = 1.0; - priv->pScrn->gamma.green = 1.0; - priv->pScrn->gamma.blue = 1.0; - } -#endif - - RedGamma = 1.0 / (double)priv->pScrn->gamma.red; - GreenGamma = 1.0 / (double)priv->pScrn->gamma.green; - BlueGamma = 1.0 / (double)priv->pScrn->gamma.blue; - - for(i = 0; i <= elements; i++) { - if(RedGamma == 1.0) - priv->gamma[i].red = i; - else - priv->gamma[i].red = (CARD16)(pow((double)i/(double)elements, - RedGamma) * (double)elements + 0.5); - - if(GreenGamma == 1.0) - priv->gamma[i].green = i; - else - priv->gamma[i].green = (CARD16)(pow((double)i/(double)elements, - GreenGamma) * (double)elements + 0.5); - - if(BlueGamma == 1.0) - priv->gamma[i].blue = i; - else - priv->gamma[i].blue = (CARD16)(pow((double)i/(double)elements, - BlueGamma) * (double)elements + 0.5); - } -} - - -int -CMapChangeGamma( - int index, - Gamma gamma -){ - int ret = Success; - ScrnInfoPtr pScrn = xf86Screens[index]; - ScreenPtr pScreen = pScrn->pScreen; - CMapColormapPtr pColPriv; - CMapScreenPtr pScreenPriv; - CMapLinkPtr pLink; - - /* Is this sufficient checking ? */ - if(CMapScreenKey == NULL) - return BadImplementation; - - pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - CMapScreenKey); - if(!pScreenPriv) - return BadImplementation; - - if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX || - gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX || - gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX) - return BadValue; - - pScrn->gamma.red = gamma.red; - pScrn->gamma.green = gamma.green; - pScrn->gamma.blue = gamma.blue; - - ComputeGamma(pScreenPriv); - - /* mark all colormaps on this screen */ - pLink = pScreenPriv->maps; - while(pLink) { - pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates, - CMapColormapKey); - pColPriv->recalculate = TRUE; - pLink = pLink->next; - } - - if(GetInstalledmiColormap(pScreen) && - ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || - pScrn->vtSema || pScreenPriv->isDGAmode)) { - ColormapPtr pMap = GetInstalledmiColormap(pScreen); - - if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && - (pMap->pVisual->class == TrueColor) && - CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { - - /* if the current map doesn't have a palette look - for another map to change the gamma on. */ - - pLink = pScreenPriv->maps; - while(pLink) { - if(pLink->cmap->pVisual->class == PseudoColor) - break; - pLink = pLink->next; - } - - if(pLink) { - /* need to trick CMapRefreshColors() into thinking - this is the currently installed map */ - SetInstalledmiColormap(pScreen, pLink->cmap); - CMapReinstallMap(pLink->cmap); - SetInstalledmiColormap(pScreen, pMap); - } - } else - CMapReinstallMap(pMap); - } - - pScrn->ChangeGamma = pScreenPriv->ChangeGamma; - if (pScrn->ChangeGamma) - ret = pScrn->ChangeGamma(index, gamma); - pScrn->ChangeGamma = CMapChangeGamma; - - return ret; -} - - -static void -ComputeGammaRamp ( - CMapScreenPtr priv, - unsigned short *red, - unsigned short *green, - unsigned short *blue -){ - int elements = priv->gammaElements; - LOCO *entry = priv->gamma; - int shift = 16 - priv->sigRGBbits; - - while(elements--) { - entry->red = *(red++) >> shift; - entry->green = *(green++) >> shift; - entry->blue = *(blue++) >> shift; - entry++; - } -} - -int -xf86ChangeGammaRamp( - ScreenPtr pScreen, - int size, - unsigned short *red, - unsigned short *green, - unsigned short *blue -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - CMapColormapPtr pColPriv; - CMapScreenPtr pScreenPriv; - CMapLinkPtr pLink; - - if (xf86_crtc_supports_gamma(pScrn)) { - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); - - if (crtc) { - if (crtc->gammaSize != size) - return BadValue; - - RRCrtcGammaSet(crtc, red, green, blue); - - return Success; - } - } - - if(CMapScreenKey == NULL) - return BadImplementation; - - pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - CMapScreenKey); - if(!pScreenPriv) - return BadImplementation; - - if(pScreenPriv->gammaElements != size) - return BadValue; - - ComputeGammaRamp(pScreenPriv, red, green, blue); - - /* mark all colormaps on this screen */ - pLink = pScreenPriv->maps; - while(pLink) { - pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates, - CMapColormapKey); - pColPriv->recalculate = TRUE; - pLink = pLink->next; - } - - if(GetInstalledmiColormap(pScreen) && - ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || - pScrn->vtSema || pScreenPriv->isDGAmode)) { - ColormapPtr pMap = GetInstalledmiColormap(pScreen); - - if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && - (pMap->pVisual->class == TrueColor) && - CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { - - /* if the current map doesn't have a palette look - for another map to change the gamma on. */ - - pLink = pScreenPriv->maps; - while(pLink) { - if(pLink->cmap->pVisual->class == PseudoColor) - break; - pLink = pLink->next; - } - - if(pLink) { - /* need to trick CMapRefreshColors() into thinking - this is the currently installed map */ - SetInstalledmiColormap(pScreen, pLink->cmap); - CMapReinstallMap(pLink->cmap); - SetInstalledmiColormap(pScreen, pMap); - } - } else - CMapReinstallMap(pMap); - } - - return Success; -} - -int -xf86GetGammaRampSize(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - CMapScreenPtr pScreenPriv; - - if (xf86_crtc_supports_gamma(pScrn)) { - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); - - if (crtc) - return crtc->gammaSize; - } - - if(CMapScreenKey == NULL) return 0; - - pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - CMapScreenKey); - if(!pScreenPriv) return 0; - - return pScreenPriv->gammaElements; -} - -int -xf86GetGammaRamp( - ScreenPtr pScreen, - int size, - unsigned short *red, - unsigned short *green, - unsigned short *blue -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - CMapScreenPtr pScreenPriv; - LOCO *entry; - int shift, sigbits; - - if (xf86_crtc_supports_gamma(pScrn)) { - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); - - if (crtc) { - if (crtc->gammaSize < size) - return BadValue; - - if (!RRCrtcGammaGet(crtc)) - return BadImplementation; - - memcpy(red, crtc->gammaRed, size * sizeof(*red)); - memcpy(green, crtc->gammaGreen, size * sizeof(*green)); - memcpy(blue, crtc->gammaBlue, size * sizeof(*blue)); - - return Success; - } - } - - if(CMapScreenKey == NULL) - return BadImplementation; - - pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - CMapScreenKey); - if(!pScreenPriv) - return BadImplementation; - - if(size > pScreenPriv->gammaElements) - return BadValue; - - entry = pScreenPriv->gamma; - sigbits = pScreenPriv->sigRGBbits; - - while(size--) { - *red = entry->red << (16 - sigbits); - *green = entry->green << (16 - sigbits); - *blue = entry->blue << (16 - sigbits); - shift = sigbits; - while(shift < 16) { - *red |= *red >> shift; - *green |= *green >> shift; - *blue |= *blue >> shift; - shift += sigbits; - } - red++; green++; blue++; - entry++; - } - - return Success; -} - -int -xf86ChangeGamma( - ScreenPtr pScreen, - Gamma gamma -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if(pScrn->ChangeGamma) - return (*pScrn->ChangeGamma)(pScreen->myNum, gamma); - - return BadImplementation; -} +/* + * Copyright (c) 1998-2001 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) +#include +#else +#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ +#include +#undef _XOPEN_SOURCE +#endif + +#include +#include "misc.h" +#include +#include "colormapst.h" +#include "scrnintstr.h" + +#include "resource.h" + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86str.h" +#include "micmap.h" +#include "xf86Crtc.h" + +#ifdef XFreeXDGA +#include +#include "dgaproc.h" +#endif + +#include "xf86cmap.h" + +#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \ + ((CMapScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, CMapScreenKey))->field) +#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ + ((pScreen)->field = wrapper) + +#define LOAD_PALETTE(pmap) \ + ((pmap == GetInstalledmiColormap(pmap->pScreen)) && \ + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || \ + xf86Screens[pmap->pScreen->myNum]->vtSema || pScreenPriv->isDGAmode)) + + +typedef struct _CMapLink { + ColormapPtr cmap; + struct _CMapLink *next; +} CMapLink, *CMapLinkPtr; + +typedef struct { + ScrnInfoPtr pScrn; + CloseScreenProcPtr CloseScreen; + CreateColormapProcPtr CreateColormap; + DestroyColormapProcPtr DestroyColormap; + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + Bool (*EnterVT)(int, int); + Bool (*SwitchMode)(int, DisplayModePtr, int); + int (*SetDGAMode)(int, int, DGADevicePtr); + xf86ChangeGammaProc *ChangeGamma; + int maxColors; + int sigRGBbits; + int gammaElements; + LOCO *gamma; + int *PreAllocIndices; + CMapLinkPtr maps; + unsigned int flags; + Bool isDGAmode; +} CMapScreenRec, *CMapScreenPtr; + +typedef struct { + int numColors; + LOCO *colors; + Bool recalculate; + int overscan; +} CMapColormapRec, *CMapColormapPtr; + +static int CMapScreenKeyIndex; +static DevPrivateKey CMapScreenKey; +static int CMapColormapKeyIndex; +static DevPrivateKey CMapColormapKey = &CMapColormapKeyIndex; + +static void CMapInstallColormap(ColormapPtr); +static void CMapStoreColors(ColormapPtr, int, xColorItem *); +static Bool CMapCloseScreen (int, ScreenPtr); +static Bool CMapCreateColormap (ColormapPtr); +static void CMapDestroyColormap (ColormapPtr); + +static Bool CMapEnterVT(int, int); +static Bool CMapSwitchMode(int, DisplayModePtr, int); +#ifdef XFreeXDGA +static int CMapSetDGAMode(int, int, DGADevicePtr); +#endif +static int CMapChangeGamma(int, Gamma); + +static void ComputeGamma(CMapScreenPtr); +static Bool CMapAllocateColormapPrivate(ColormapPtr); +static void CMapRefreshColors(ColormapPtr, int, int*); +static void CMapSetOverscan(ColormapPtr, int, int *); +static void CMapReinstallMap(ColormapPtr); +static void CMapUnwrapScreen(ScreenPtr pScreen); + + + +Bool xf86HandleColormaps( + ScreenPtr pScreen, + int maxColors, + int sigRGBbits, + xf86LoadPaletteProc *loadPalette, + xf86SetOverscanProc *setOverscan, + unsigned int flags +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ColormapPtr pDefMap = NULL; + CMapScreenPtr pScreenPriv; + LOCO *gamma; + int *indices; + int elements; + + /* If we support a better colormap system, then pretend we succeeded. */ + if (xf86_crtc_supports_gamma(pScrn)) + return TRUE; + + if(!maxColors || !sigRGBbits || !loadPalette) + return FALSE; + + CMapScreenKey = &CMapScreenKeyIndex; + + elements = 1 << sigRGBbits; + + if(!(gamma = malloc(elements * sizeof(LOCO)))) + return FALSE; + + if(!(indices = malloc(maxColors * sizeof(int)))) { + free(gamma); + return FALSE; + } + + if(!(pScreenPriv = malloc(sizeof(CMapScreenRec)))) { + free(gamma); + free(indices); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, CMapScreenKey, pScreenPriv); + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreenPriv->CreateColormap = pScreen->CreateColormap; + pScreenPriv->DestroyColormap = pScreen->DestroyColormap; + pScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreenPriv->StoreColors = pScreen->StoreColors; + pScreen->CloseScreen = CMapCloseScreen; + pScreen->CreateColormap = CMapCreateColormap; + pScreen->DestroyColormap = CMapDestroyColormap; + pScreen->InstallColormap = CMapInstallColormap; + pScreen->StoreColors = CMapStoreColors; + + pScreenPriv->pScrn = pScrn; + pScrn->LoadPalette = loadPalette; + pScrn->SetOverscan = setOverscan; + pScreenPriv->maxColors = maxColors; + pScreenPriv->sigRGBbits = sigRGBbits; + pScreenPriv->gammaElements = elements; + pScreenPriv->gamma = gamma; + pScreenPriv->PreAllocIndices = indices; + pScreenPriv->maps = NULL; + pScreenPriv->flags = flags; + pScreenPriv->isDGAmode = FALSE; + + pScreenPriv->EnterVT = pScrn->EnterVT; + pScreenPriv->SwitchMode = pScrn->SwitchMode; + pScreenPriv->SetDGAMode = pScrn->SetDGAMode; + pScreenPriv->ChangeGamma = pScrn->ChangeGamma; + + if (!(flags & CMAP_LOAD_EVEN_IF_OFFSCREEN)) { + pScrn->EnterVT = CMapEnterVT; + if ((flags & CMAP_RELOAD_ON_MODE_SWITCH) && pScrn->SwitchMode) + pScrn->SwitchMode = CMapSwitchMode; + } +#ifdef XFreeXDGA + pScrn->SetDGAMode = CMapSetDGAMode; +#endif + pScrn->ChangeGamma = CMapChangeGamma; + + ComputeGamma(pScreenPriv); + + /* get the default map */ + dixLookupResourceByType((pointer *)&pDefMap, pScreen->defColormap, + RT_COLORMAP, serverClient, DixInstallAccess); + + if(!CMapAllocateColormapPrivate(pDefMap)) { + CMapUnwrapScreen(pScreen); + return FALSE; + } + + /* Force the initial map to be loaded */ + SetInstalledmiColormap(pScreen, NULL); + CMapInstallColormap(pDefMap); + return TRUE; +} + + +/**** Screen functions ****/ + + +static Bool +CMapCloseScreen (int i, ScreenPtr pScreen) +{ + CMapUnwrapScreen(pScreen); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static Bool +CMapColormapUseMax(VisualPtr pVisual, CMapScreenPtr pScreenPriv) +{ + if (pVisual->nplanes > 16) + return TRUE; + return ((1 << pVisual->nplanes) > pScreenPriv->maxColors); +} + +static Bool +CMapAllocateColormapPrivate(ColormapPtr pmap) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pmap->pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr pColPriv; + CMapLinkPtr pLink; + int numColors; + LOCO *colors; + + if (CMapColormapUseMax(pmap->pVisual, pScreenPriv)) + numColors = pmap->pVisual->ColormapEntries; + else + numColors = 1 << pmap->pVisual->nplanes; + + if(!(colors = malloc(numColors * sizeof(LOCO)))) + return FALSE; + + if(!(pColPriv = malloc(sizeof(CMapColormapRec)))) { + free(colors); + return FALSE; + } + + dixSetPrivate(&pmap->devPrivates, CMapColormapKey, pColPriv); + + pColPriv->numColors = numColors; + pColPriv->colors = colors; + pColPriv->recalculate = TRUE; + pColPriv->overscan = -1; + + /* add map to list */ + pLink = malloc(sizeof(CMapLink)); + if(pLink) { + pLink->cmap = pmap; + pLink->next = pScreenPriv->maps; + pScreenPriv->maps = pLink; + } + + return TRUE; +} + +static Bool +CMapCreateColormap (ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + Bool ret = FALSE; + + pScreen->CreateColormap = pScreenPriv->CreateColormap; + if((*pScreen->CreateColormap)(pmap)) { + if(CMapAllocateColormapPrivate(pmap)) + ret = TRUE; + } + pScreen->CreateColormap = CMapCreateColormap; + + return ret; +} + +static void +CMapDestroyColormap (ColormapPtr cmap) +{ + ScreenPtr pScreen = cmap->pScreen; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( + &cmap->devPrivates, CMapColormapKey); + CMapLinkPtr prevLink = NULL, pLink = pScreenPriv->maps; + + if(pColPriv) { + if(pColPriv->colors) free(pColPriv->colors); + free(pColPriv); + } + + /* remove map from list */ + while(pLink) { + if(pLink->cmap == cmap) { + if(prevLink) + prevLink->next = pLink->next; + else + pScreenPriv->maps = pLink->next; + free(pLink); + break; + } + prevLink = pLink; + pLink = pLink->next; + } + + if(pScreenPriv->DestroyColormap) { + pScreen->DestroyColormap = pScreenPriv->DestroyColormap; + (*pScreen->DestroyColormap)(cmap); + pScreen->DestroyColormap = CMapDestroyColormap; + } +} + + + +static void +CMapStoreColors( + ColormapPtr pmap, + int ndef, + xColorItem *pdefs +){ + ScreenPtr pScreen = pmap->pScreen; + VisualPtr pVisual = pmap->pVisual; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + int *indices = pScreenPriv->PreAllocIndices; + int num = ndef; + + /* At the moment this isn't necessary since there's nobody below us */ + pScreen->StoreColors = pScreenPriv->StoreColors; + (*pScreen->StoreColors)(pmap, ndef, pdefs); + pScreen->StoreColors = CMapStoreColors; + + /* should never get here for these */ + if( (pVisual->class == TrueColor) || + (pVisual->class == StaticColor) || + (pVisual->class == StaticGray)) + return; + + if(pVisual->class == DirectColor) { + CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( + &pmap->devPrivates, CMapColormapKey); + int i; + + if (CMapColormapUseMax(pVisual, pScreenPriv)) { + int index; + + num = 0; + while(ndef--) { + if(pdefs[ndef].flags & DoRed) { + index = (pdefs[ndef].pixel & pVisual->redMask) >> + pVisual->offsetRed; + i = num; + while(i--) + if(indices[i] == index) break; + if(i == -1) + indices[num++] = index; + } + if(pdefs[ndef].flags & DoGreen) { + index = (pdefs[ndef].pixel & pVisual->greenMask) >> + pVisual->offsetGreen; + i = num; + while(i--) + if(indices[i] == index) break; + if(i == -1) + indices[num++] = index; + } + if(pdefs[ndef].flags & DoBlue) { + index = (pdefs[ndef].pixel & pVisual->blueMask) >> + pVisual->offsetBlue; + i = num; + while(i--) + if(indices[i] == index) break; + if(i == -1) + indices[num++] = index; + } + } + + } else { + /* not really as overkill as it seems */ + num = pColPriv->numColors; + for(i = 0; i < pColPriv->numColors; i++) + indices[i] = i; + } + } else { + while(ndef--) + indices[ndef] = pdefs[ndef].pixel; + } + + CMapRefreshColors(pmap, num, indices); +} + + +static void +CMapInstallColormap(ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + if (pmap == GetInstalledmiColormap(pmap->pScreen)) + return; + + pScreen->InstallColormap = pScreenPriv->InstallColormap; + (*pScreen->InstallColormap)(pmap); + pScreen->InstallColormap = CMapInstallColormap; + + /* Important. We let the lower layers, namely DGA, + overwrite the choice of Colormap to install */ + if (GetInstalledmiColormap(pmap->pScreen)) + pmap = GetInstalledmiColormap(pmap->pScreen); + + if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && + (pmap->pVisual->class == TrueColor) && + CMapColormapUseMax(pmap->pVisual, pScreenPriv)) + return; + + if(LOAD_PALETTE(pmap)) + CMapReinstallMap(pmap); +} + + +/**** ScrnInfoRec functions ****/ + +static Bool +CMapEnterVT(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + if((*pScreenPriv->EnterVT)(index, flags)) { + if(GetInstalledmiColormap(pScreen)) + CMapReinstallMap(GetInstalledmiColormap(pScreen)); + return TRUE; + } + return FALSE; +} + + +static Bool +CMapSwitchMode(int index, DisplayModePtr mode, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + + if((*pScreenPriv->SwitchMode)(index, mode, flags)) { + if(GetInstalledmiColormap(pScreen)) + CMapReinstallMap(GetInstalledmiColormap(pScreen)); + return TRUE; + } + return FALSE; +} + +#ifdef XFreeXDGA +static int +CMapSetDGAMode(int index, int num, DGADevicePtr dev) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + int ret; + + ret = (*pScreenPriv->SetDGAMode)(index, num, dev); + + pScreenPriv->isDGAmode = DGAActive(index); + + if(!pScreenPriv->isDGAmode && GetInstalledmiColormap(pScreen) + && xf86Screens[pScreen->myNum]->vtSema) + CMapReinstallMap(GetInstalledmiColormap(pScreen)); + + return ret; +} +#endif + + +/**** Utilities ****/ + +static void +CMapReinstallMap(ColormapPtr pmap) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pmap->pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr cmapPriv = (CMapColormapPtr)dixLookupPrivate( + &pmap->devPrivates, CMapColormapKey); + ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; + int i = cmapPriv->numColors; + int *indices = pScreenPriv->PreAllocIndices; + + while(i--) + indices[i] = i; + + if(cmapPriv->recalculate) + CMapRefreshColors(pmap, cmapPriv->numColors, indices); + else { + (*pScrn->LoadPalette)(pScrn, cmapPriv->numColors, + indices, cmapPriv->colors, pmap->pVisual); + if (pScrn->SetOverscan) { +#ifdef DEBUGOVERSCAN + ErrorF("SetOverscan() called from CMapReinstallMap\n"); +#endif + pScrn->SetOverscan(pScrn, cmapPriv->overscan); + } + } + + cmapPriv->recalculate = FALSE; +} + + +static void +CMapRefreshColors(ColormapPtr pmap, int defs, int* indices) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pmap->pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( + &pmap->devPrivates, CMapColormapKey); + VisualPtr pVisual = pmap->pVisual; + ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; + int numColors, i; + LOCO *gamma, *colors; + EntryPtr entry; + int reds, greens, blues, maxValue, index, shift; + + numColors = pColPriv->numColors; + shift = 16 - pScreenPriv->sigRGBbits; + maxValue = (1 << pScreenPriv->sigRGBbits) - 1; + gamma = pScreenPriv->gamma; + colors = pColPriv->colors; + + reds = pVisual->redMask >> pVisual->offsetRed; + greens = pVisual->greenMask >> pVisual->offsetGreen; + blues = pVisual->blueMask >> pVisual->offsetBlue; + + switch(pVisual->class) { + case StaticGray: + for(i = 0; i < numColors; i++) { + index = (i+1) * maxValue / numColors; + colors[i].red = gamma[index].red; + colors[i].green = gamma[index].green; + colors[i].blue = gamma[index].blue; + } + break; + case TrueColor: + if (CMapColormapUseMax(pVisual, pScreenPriv)) { + for(i = 0; i <= reds; i++) + colors[i].red = gamma[i * maxValue / reds].red; + for(i = 0; i <= greens; i++) + colors[i].green = gamma[i * maxValue / greens].green; + for(i = 0; i <= blues; i++) + colors[i].blue = gamma[i * maxValue / blues].blue; + break; + } + for(i = 0; i < numColors; i++) { + colors[i].red = gamma[((i >> pVisual->offsetRed) & reds) * + maxValue / reds].red; + colors[i].green = gamma[((i >> pVisual->offsetGreen) & greens) * + maxValue / greens].green; + colors[i].blue = gamma[((i >> pVisual->offsetBlue) & blues) * + maxValue / blues].blue; + } + break; + case StaticColor: + case PseudoColor: + case GrayScale: + for(i = 0; i < defs; i++) { + index = indices[i]; + entry = (EntryPtr)&pmap->red[index]; + + if(entry->fShared) { + colors[index].red = + gamma[entry->co.shco.red->color >> shift].red; + colors[index].green = + gamma[entry->co.shco.green->color >> shift].green; + colors[index].blue = + gamma[entry->co.shco.blue->color >> shift].blue; + } else { + colors[index].red = + gamma[entry->co.local.red >> shift].red; + colors[index].green = + gamma[entry->co.local.green >> shift].green; + colors[index].blue = + gamma[entry->co.local.blue >> shift].blue; + } + } + break; + case DirectColor: + if (CMapColormapUseMax(pVisual, pScreenPriv)) { + for(i = 0; i < defs; i++) { + index = indices[i]; + if(index <= reds) + colors[index].red = + gamma[pmap->red[index].co.local.red >> shift].red; + if(index <= greens) + colors[index].green = + gamma[pmap->green[index].co.local.green >> shift].green; + if(index <= blues) + colors[index].blue = + gamma[pmap->blue[index].co.local.blue >> shift].blue; + + } + break; + } + for(i = 0; i < defs; i++) { + index = indices[i]; + + colors[index].red = gamma[pmap->red[ + (index >> pVisual->offsetRed) & reds + ].co.local.red >> shift].red; + colors[index].green = gamma[pmap->green[ + (index >> pVisual->offsetGreen) & greens + ].co.local.green >> shift].green; + colors[index].blue = gamma[pmap->blue[ + (index >> pVisual->offsetBlue) & blues + ].co.local.blue >> shift].blue; + } + break; + } + + + if(LOAD_PALETTE(pmap)) + (*pScrn->LoadPalette)(pScreenPriv->pScrn, defs, indices, + colors, pmap->pVisual); + + if (pScrn->SetOverscan) + CMapSetOverscan(pmap, defs, indices); + +} + +static Bool +CMapCompareColors(LOCO *color1, LOCO *color2) +{ + /* return TRUE if the color1 is "closer" to black than color2 */ +#ifdef DEBUGOVERSCAN + ErrorF("#%02x%02x%02x vs #%02x%02x%02x (%d vs %d)\n", + color1->red, color1->green, color1->blue, + color2->red, color2->green, color2->blue, + color1->red + color1->green + color1->blue, + color2->red + color2->green + color2->blue); +#endif + return (color1->red + color1->green + color1->blue < + color2->red + color2->green + color2->blue); +} + +static void +CMapSetOverscan(ColormapPtr pmap, int defs, int *indices) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pmap->pScreen->devPrivates, CMapScreenKey); + CMapColormapPtr pColPriv = (CMapColormapPtr)dixLookupPrivate( + &pmap->devPrivates, CMapColormapKey); + ScrnInfoPtr pScrn = xf86Screens[pmap->pScreen->myNum]; + VisualPtr pVisual = pmap->pVisual; + int i; + LOCO *colors; + int index; + Bool newOverscan = FALSE; + int overscan, tmpOverscan; + + colors = pColPriv->colors; + overscan = pColPriv->overscan; + + /* + * Search for a new overscan index in the following cases: + * + * - The index hasn't yet been initialised.  In this case search + * for an index that is black or a close match to black. + * + * - The colour of the old index is changed. In this case search + * all indices for a black or close match to black. + * + * - The colour of the old index wasn't black. In this case only + * search the indices that were changed for a better match to black. + */ + + switch (pVisual->class) { + case StaticGray: + case TrueColor: + /* Should only come here once. Initialise the overscan index to 0 */ + overscan = 0; + newOverscan = TRUE; + break; + case StaticColor: + /* + * Only come here once, but search for the overscan in the same way + * as for the other cases. + */ + case DirectColor: + case PseudoColor: + case GrayScale: + if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) { + /* Uninitialised */ + newOverscan = TRUE; + } else { + /* Check if the overscan was changed */ + for (i = 0; i < defs; i++) { + index = indices[i]; + if (index == overscan) { + newOverscan = TRUE; + break; + } + } + } + if (newOverscan) { + /* The overscan is either uninitialised or it has been changed */ + + if (overscan < 0 || overscan > pScreenPriv->maxColors - 1) + tmpOverscan = pScreenPriv->maxColors - 1; + else + tmpOverscan = overscan; + + /* search all entries for a close match to black */ + for (i = pScreenPriv->maxColors - 1; i >= 0; i--) { + if (colors[i].red == 0 && colors[i].green == 0 && + colors[i].blue == 0) { + overscan = i; +#ifdef DEBUGOVERSCAN + ErrorF("Black found at index 0x%02x\n", i); +#endif + break; + } else { +#ifdef DEBUGOVERSCAN + ErrorF("0x%02x: ", i); +#endif + if (CMapCompareColors(&colors[i], &colors[tmpOverscan])) { + tmpOverscan = i; +#ifdef DEBUGOVERSCAN + ErrorF("possible \"Black\" at index 0x%02x\n", i); +#endif + } + } + } + if (i < 0) + overscan = tmpOverscan; + } else { + /* Check of the old overscan wasn't black */ + if (colors[overscan].red != 0 || colors[overscan].green != 0 || + colors[overscan].blue != 0) { + int oldOverscan = tmpOverscan = overscan; + /* See of there is now a better match */ + for (i = 0; i < defs; i++) { + index = indices[i]; + if (colors[index].red == 0 && colors[index].green == 0 && + colors[index].blue == 0) { + overscan = index; +#ifdef DEBUGOVERSCAN + ErrorF("Black found at index 0x%02x\n", index); +#endif + break; + } else { +#ifdef DEBUGOVERSCAN + ErrorF("0x%02x: ", index); +#endif + if (CMapCompareColors(&colors[index], + &colors[tmpOverscan])) { + tmpOverscan = index; +#ifdef DEBUGOVERSCAN + ErrorF("possible \"Black\" at index 0x%02x\n", + index); +#endif + } + } + } + if (i == defs) + overscan = tmpOverscan; + if (overscan != oldOverscan) + newOverscan = TRUE; + } + } + break; + } + if (newOverscan) { + pColPriv->overscan = overscan; + if (LOAD_PALETTE(pmap)) { +#ifdef DEBUGOVERSCAN + ErrorF("SetOverscan() called from CmapSetOverscan\n"); +#endif + pScrn->SetOverscan(pScreenPriv->pScrn, overscan); + } + } +} + +static void +CMapUnwrapScreen(ScreenPtr pScreen) +{ + CMapScreenPtr pScreenPriv = (CMapScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, CMapScreenKey); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->CreateColormap = pScreenPriv->CreateColormap; + pScreen->DestroyColormap = pScreenPriv->DestroyColormap; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->StoreColors = pScreenPriv->StoreColors; + + pScrn->EnterVT = pScreenPriv->EnterVT; + pScrn->SwitchMode = pScreenPriv->SwitchMode; + pScrn->SetDGAMode = pScreenPriv->SetDGAMode; + pScrn->ChangeGamma = pScreenPriv->ChangeGamma; + + free(pScreenPriv->gamma); + free(pScreenPriv->PreAllocIndices); + free(pScreenPriv); +} + + +static void +ComputeGamma(CMapScreenPtr priv) +{ + int elements = priv->gammaElements - 1; + double RedGamma, GreenGamma, BlueGamma; + int i; + +#ifndef DONT_CHECK_GAMMA + /* This check is to catch drivers that are not initialising pScrn->gamma */ + if (priv->pScrn->gamma.red < GAMMA_MIN || + priv->pScrn->gamma.red > GAMMA_MAX || + priv->pScrn->gamma.green < GAMMA_MIN || + priv->pScrn->gamma.green > GAMMA_MAX || + priv->pScrn->gamma.blue < GAMMA_MIN || + priv->pScrn->gamma.blue > GAMMA_MAX) { + + xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, + "The %s driver didn't call xf86SetGamma() to initialise\n" + "\tthe gamma values.\n", priv->pScrn->driverName); + xf86DrvMsgVerb(priv->pScrn->scrnIndex, X_WARNING, 0, + "PLEASE FIX THE `%s' DRIVER!\n", priv->pScrn->driverName); + priv->pScrn->gamma.red = 1.0; + priv->pScrn->gamma.green = 1.0; + priv->pScrn->gamma.blue = 1.0; + } +#endif + + RedGamma = 1.0 / (double)priv->pScrn->gamma.red; + GreenGamma = 1.0 / (double)priv->pScrn->gamma.green; + BlueGamma = 1.0 / (double)priv->pScrn->gamma.blue; + + for(i = 0; i <= elements; i++) { + if(RedGamma == 1.0) + priv->gamma[i].red = i; + else + priv->gamma[i].red = (CARD16)(pow((double)i/(double)elements, + RedGamma) * (double)elements + 0.5); + + if(GreenGamma == 1.0) + priv->gamma[i].green = i; + else + priv->gamma[i].green = (CARD16)(pow((double)i/(double)elements, + GreenGamma) * (double)elements + 0.5); + + if(BlueGamma == 1.0) + priv->gamma[i].blue = i; + else + priv->gamma[i].blue = (CARD16)(pow((double)i/(double)elements, + BlueGamma) * (double)elements + 0.5); + } +} + + +int +CMapChangeGamma( + int index, + Gamma gamma +){ + int ret = Success; + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = pScrn->pScreen; + CMapColormapPtr pColPriv; + CMapScreenPtr pScreenPriv; + CMapLinkPtr pLink; + + /* Is this sufficient checking ? */ + if(CMapScreenKey == NULL) + return BadImplementation; + + pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + CMapScreenKey); + if(!pScreenPriv) + return BadImplementation; + + if (gamma.red < GAMMA_MIN || gamma.red > GAMMA_MAX || + gamma.green < GAMMA_MIN || gamma.green > GAMMA_MAX || + gamma.blue < GAMMA_MIN || gamma.blue > GAMMA_MAX) + return BadValue; + + pScrn->gamma.red = gamma.red; + pScrn->gamma.green = gamma.green; + pScrn->gamma.blue = gamma.blue; + + ComputeGamma(pScreenPriv); + + /* mark all colormaps on this screen */ + pLink = pScreenPriv->maps; + while(pLink) { + pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates, + CMapColormapKey); + pColPriv->recalculate = TRUE; + pLink = pLink->next; + } + + if(GetInstalledmiColormap(pScreen) && + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || + pScrn->vtSema || pScreenPriv->isDGAmode)) { + ColormapPtr pMap = GetInstalledmiColormap(pScreen); + + if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && + (pMap->pVisual->class == TrueColor) && + CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { + + /* if the current map doesn't have a palette look + for another map to change the gamma on. */ + + pLink = pScreenPriv->maps; + while(pLink) { + if(pLink->cmap->pVisual->class == PseudoColor) + break; + pLink = pLink->next; + } + + if(pLink) { + /* need to trick CMapRefreshColors() into thinking + this is the currently installed map */ + SetInstalledmiColormap(pScreen, pLink->cmap); + CMapReinstallMap(pLink->cmap); + SetInstalledmiColormap(pScreen, pMap); + } + } else + CMapReinstallMap(pMap); + } + + pScrn->ChangeGamma = pScreenPriv->ChangeGamma; + if (pScrn->ChangeGamma) + ret = pScrn->ChangeGamma(index, gamma); + pScrn->ChangeGamma = CMapChangeGamma; + + return ret; +} + + +static void +ComputeGammaRamp ( + CMapScreenPtr priv, + unsigned short *red, + unsigned short *green, + unsigned short *blue +){ + int elements = priv->gammaElements; + LOCO *entry = priv->gamma; + int shift = 16 - priv->sigRGBbits; + + while(elements--) { + entry->red = *(red++) >> shift; + entry->green = *(green++) >> shift; + entry->blue = *(blue++) >> shift; + entry++; + } +} + +int +xf86ChangeGammaRamp( + ScreenPtr pScreen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CMapColormapPtr pColPriv; + CMapScreenPtr pScreenPriv; + CMapLinkPtr pLink; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) { + if (crtc->gammaSize != size) + return BadValue; + + RRCrtcGammaSet(crtc, red, green, blue); + + return Success; + } + } + + if(CMapScreenKey == NULL) + return BadImplementation; + + pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + CMapScreenKey); + if(!pScreenPriv) + return BadImplementation; + + if(pScreenPriv->gammaElements != size) + return BadValue; + + ComputeGammaRamp(pScreenPriv, red, green, blue); + + /* mark all colormaps on this screen */ + pLink = pScreenPriv->maps; + while(pLink) { + pColPriv = (CMapColormapPtr)dixLookupPrivate(&pLink->cmap->devPrivates, + CMapColormapKey); + pColPriv->recalculate = TRUE; + pLink = pLink->next; + } + + if(GetInstalledmiColormap(pScreen) && + ((pScreenPriv->flags & CMAP_LOAD_EVEN_IF_OFFSCREEN) || + pScrn->vtSema || pScreenPriv->isDGAmode)) { + ColormapPtr pMap = GetInstalledmiColormap(pScreen); + + if (!(pScreenPriv->flags & CMAP_PALETTED_TRUECOLOR) && + (pMap->pVisual->class == TrueColor) && + CMapColormapUseMax(pMap->pVisual, pScreenPriv)) { + + /* if the current map doesn't have a palette look + for another map to change the gamma on. */ + + pLink = pScreenPriv->maps; + while(pLink) { + if(pLink->cmap->pVisual->class == PseudoColor) + break; + pLink = pLink->next; + } + + if(pLink) { + /* need to trick CMapRefreshColors() into thinking + this is the currently installed map */ + SetInstalledmiColormap(pScreen, pLink->cmap); + CMapReinstallMap(pLink->cmap); + SetInstalledmiColormap(pScreen, pMap); + } + } else + CMapReinstallMap(pMap); + } + + return Success; +} + +int +xf86GetGammaRampSize(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CMapScreenPtr pScreenPriv; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) + return crtc->gammaSize; + } + + if(CMapScreenKey == NULL) return 0; + + pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + CMapScreenKey); + if(!pScreenPriv) return 0; + + return pScreenPriv->gammaElements; +} + +int +xf86GetGammaRamp( + ScreenPtr pScreen, + int size, + unsigned short *red, + unsigned short *green, + unsigned short *blue +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CMapScreenPtr pScreenPriv; + LOCO *entry; + int shift, sigbits; + + if (xf86_crtc_supports_gamma(pScrn)) { + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + + if (crtc) { + if (crtc->gammaSize < size) + return BadValue; + + if (!RRCrtcGammaGet(crtc)) + return BadImplementation; + + memcpy(red, crtc->gammaRed, size * sizeof(*red)); + memcpy(green, crtc->gammaGreen, size * sizeof(*green)); + memcpy(blue, crtc->gammaBlue, size * sizeof(*blue)); + + return Success; + } + } + + if(CMapScreenKey == NULL) + return BadImplementation; + + pScreenPriv = (CMapScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + CMapScreenKey); + if(!pScreenPriv) + return BadImplementation; + + if(size > pScreenPriv->gammaElements) + return BadValue; + + entry = pScreenPriv->gamma; + sigbits = pScreenPriv->sigRGBbits; + + while(size--) { + *red = entry->red << (16 - sigbits); + *green = entry->green << (16 - sigbits); + *blue = entry->blue << (16 - sigbits); + shift = sigbits; + while(shift < 16) { + *red |= *red >> shift; + *green |= *green >> shift; + *blue |= *blue >> shift; + shift += sigbits; + } + red++; green++; blue++; + entry++; + } + + return Success; +} + +int +xf86ChangeGamma( + ScreenPtr pScreen, + Gamma gamma +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if(pScrn->ChangeGamma) + return (*pScrn->ChangeGamma)(pScreen->myNum, gamma); + + return BadImplementation; +} diff --git a/xorg-server/hw/xfree86/common/xf86fbman.c b/xorg-server/hw/xfree86/common/xf86fbman.c index 5b8871723..1ca27015f 100644 --- a/xorg-server/hw/xfree86/common/xf86fbman.c +++ b/xorg-server/hw/xfree86/common/xf86fbman.c @@ -1,1438 +1,1438 @@ - -/* - * Copyright (c) 1998-2001 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" - -#include -#include "scrnintstr.h" -#include "regionstr.h" -#include "xf86fbman.h" - -/* -#define DEBUG -*/ - -static int xf86FBManagerKeyIndex; -static DevPrivateKey xf86FBManagerKey; - -Bool xf86RegisterOffscreenManager( - ScreenPtr pScreen, - FBManagerFuncsPtr funcs -){ - - xf86FBManagerKey = &xf86FBManagerKeyIndex; - dixSetPrivate(&pScreen->devPrivates, xf86FBManagerKey, funcs); - - return TRUE; -} - - -Bool -xf86FBManagerRunning(ScreenPtr pScreen) -{ - if(xf86FBManagerKey == NULL) - return FALSE; - if(!dixLookupPrivate(&pScreen->devPrivates, xf86FBManagerKey)) - return FALSE; - - return TRUE; -} - -Bool -xf86RegisterFreeBoxCallback( - ScreenPtr pScreen, - FreeBoxCallbackProcPtr FreeBoxCallback, - pointer devPriv -){ - FBManagerFuncsPtr funcs; - - if(xf86FBManagerKey == NULL) - return FALSE; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBManagerKey))) - return FALSE; - - return (*funcs->RegisterFreeBoxCallback)(pScreen, FreeBoxCallback, devPriv); -} - - -FBAreaPtr -xf86AllocateOffscreenArea( - ScreenPtr pScreen, - int w, int h, - int gran, - MoveAreaCallbackProcPtr moveCB, - RemoveAreaCallbackProcPtr removeCB, - pointer privData -){ - FBManagerFuncsPtr funcs; - - if(xf86FBManagerKey == NULL) - return NULL; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBManagerKey))) - return NULL; - - return (*funcs->AllocateOffscreenArea)( - pScreen, w, h, gran, moveCB, removeCB, privData); -} - - -FBLinearPtr -xf86AllocateOffscreenLinear( - ScreenPtr pScreen, - int length, - int gran, - MoveLinearCallbackProcPtr moveCB, - RemoveLinearCallbackProcPtr removeCB, - pointer privData -){ - FBManagerFuncsPtr funcs; - - if(xf86FBManagerKey == NULL) - return NULL; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBManagerKey))) - return NULL; - - return (*funcs->AllocateOffscreenLinear)( - pScreen, length, gran, moveCB, removeCB, privData); -} - - -void -xf86FreeOffscreenArea(FBAreaPtr area) -{ - FBManagerFuncsPtr funcs; - - if(!area) return; - - if(xf86FBManagerKey == NULL) - return; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( - &area->pScreen->devPrivates, xf86FBManagerKey))) - return; - - (*funcs->FreeOffscreenArea)(area); - - return; -} - - -void -xf86FreeOffscreenLinear(FBLinearPtr linear) -{ - FBManagerFuncsPtr funcs; - - if(!linear) return; - - if(xf86FBManagerKey == NULL) - return; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( - &linear->pScreen->devPrivates, xf86FBManagerKey))) - return; - - (*funcs->FreeOffscreenLinear)(linear); - - return; -} - - -Bool -xf86ResizeOffscreenArea( - FBAreaPtr resize, - int w, int h -){ - FBManagerFuncsPtr funcs; - - if(!resize) return FALSE; - - if(xf86FBManagerKey == NULL) - return FALSE; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( - &resize->pScreen->devPrivates, xf86FBManagerKey))) - return FALSE; - - return (*funcs->ResizeOffscreenArea)(resize, w, h); -} - -Bool -xf86ResizeOffscreenLinear( - FBLinearPtr resize, - int size -){ - FBManagerFuncsPtr funcs; - - if(!resize) return FALSE; - - if(xf86FBManagerKey == NULL) - return FALSE; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( - &resize->pScreen->devPrivates, xf86FBManagerKey))) - return FALSE; - - return (*funcs->ResizeOffscreenLinear)(resize, size); -} - - -Bool -xf86QueryLargestOffscreenArea( - ScreenPtr pScreen, - int *w, int *h, - int gran, - int preferences, - int severity -){ - FBManagerFuncsPtr funcs; - - *w = 0; - *h = 0; - - if(xf86FBManagerKey == NULL) - return FALSE; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBManagerKey))) - return FALSE; - - return (*funcs->QueryLargestOffscreenArea)( - pScreen, w, h, gran, preferences, severity); -} - -Bool -xf86QueryLargestOffscreenLinear( - ScreenPtr pScreen, - int *size, - int gran, - int severity -){ - FBManagerFuncsPtr funcs; - - *size = 0; - - if(xf86FBManagerKey == NULL) - return FALSE; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBManagerKey))) - return FALSE; - - return (*funcs->QueryLargestOffscreenLinear)( - pScreen, size, gran, severity); -} - - -Bool -xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen) -{ - FBManagerFuncsPtr funcs; - - if(xf86FBManagerKey == NULL) - return FALSE; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBManagerKey))) - return FALSE; - - return (*funcs->PurgeOffscreenAreas)(pScreen); -} - -/************************************************************\ - - Below is a specific implementation of an offscreen manager. - -\************************************************************/ - -static int xf86FBScreenKeyIndex; -static DevPrivateKey xf86FBScreenKey = &xf86FBScreenKeyIndex; - -typedef struct _FBLink { - FBArea area; - struct _FBLink *next; -} FBLink, *FBLinkPtr; - -typedef struct _FBLinearLink { - FBLinear linear; - int free; /* need to add free here as FBLinear is publicly accessible */ - FBAreaPtr area; /* only used if allocation came from XY area */ - struct _FBLinearLink *next; -} FBLinearLink, *FBLinearLinkPtr; - - -typedef struct { - ScreenPtr pScreen; - RegionPtr InitialBoxes; - RegionPtr FreeBoxes; - FBLinkPtr UsedAreas; - int NumUsedAreas; - FBLinearLinkPtr LinearAreas; - CloseScreenProcPtr CloseScreen; - int NumCallbacks; - FreeBoxCallbackProcPtr *FreeBoxesUpdateCallback; - DevUnion *devPrivates; -} FBManager, *FBManagerPtr; - - -static void -SendCallFreeBoxCallbacks(FBManagerPtr offman) -{ - int i = offman->NumCallbacks; - - while(i--) { - (*offman->FreeBoxesUpdateCallback[i])( - offman->pScreen, offman->FreeBoxes, offman->devPrivates[i].ptr); - } -} - -static Bool -localRegisterFreeBoxCallback( - ScreenPtr pScreen, - FreeBoxCallbackProcPtr FreeBoxCallback, - pointer devPriv -){ - FBManagerPtr offman; - FreeBoxCallbackProcPtr *newCallbacks; - DevUnion *newPrivates; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - newCallbacks = xrealloc( offman->FreeBoxesUpdateCallback, - sizeof(FreeBoxCallbackProcPtr) * (offman->NumCallbacks + 1)); - - newPrivates = xrealloc(offman->devPrivates, - sizeof(DevUnion) * (offman->NumCallbacks + 1)); - - if(!newCallbacks || !newPrivates) - return FALSE; - - offman->FreeBoxesUpdateCallback = newCallbacks; - offman->devPrivates = newPrivates; - - offman->FreeBoxesUpdateCallback[offman->NumCallbacks] = FreeBoxCallback; - offman->devPrivates[offman->NumCallbacks].ptr = devPriv; - offman->NumCallbacks++; - - SendCallFreeBoxCallbacks(offman); - - return TRUE; -} - - -static FBAreaPtr -AllocateArea( - FBManagerPtr offman, - int w, int h, - int granularity, - MoveAreaCallbackProcPtr moveCB, - RemoveAreaCallbackProcPtr removeCB, - pointer privData -){ - ScreenPtr pScreen = offman->pScreen; - FBLinkPtr link = NULL; - FBAreaPtr area = NULL; - RegionRec NewReg; - int i, x = 0, num; - BoxPtr boxp; - - if(granularity <= 1) granularity = 0; - - boxp = REGION_RECTS(offman->FreeBoxes); - num = REGION_NUM_RECTS(offman->FreeBoxes); - - /* look through the free boxes */ - for(i = 0; i < num; i++, boxp++) { - x = boxp->x1; - if (granularity > 1) - x = ((x + granularity - 1) / granularity) * granularity; - - if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) - continue; - - link = xalloc(sizeof(FBLink)); - if(!link) return NULL; - - area = &(link->area); - link->next = offman->UsedAreas; - offman->UsedAreas = link; - offman->NumUsedAreas++; - break; - } - - /* try to boot a removeable one out if we are not expendable ourselves */ - if(!area && !removeCB) { - link = offman->UsedAreas; - - while(link) { - if(!link->area.RemoveAreaCallback) { - link = link->next; - continue; - } - - boxp = &(link->area.box); - x = boxp->x1; - if (granularity > 1) - x = ((x + granularity - 1) / granularity) * granularity; - - if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) { - link = link->next; - continue; - } - - /* bye, bye */ - (*link->area.RemoveAreaCallback)(&link->area); - REGION_INIT(pScreen, &NewReg, &(link->area.box), 1); - REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &NewReg); - REGION_UNINIT(pScreen, &NewReg); - - area = &(link->area); - break; - } - } - - if(area) { - area->pScreen = pScreen; - area->granularity = granularity; - area->box.x1 = x; - area->box.x2 = x + w; - area->box.y1 = boxp->y1; - area->box.y2 = boxp->y1 + h; - area->MoveAreaCallback = moveCB; - area->RemoveAreaCallback = removeCB; - area->devPrivate.ptr = privData; - - REGION_INIT(pScreen, &NewReg, &(area->box), 1); - REGION_SUBTRACT(pScreen, offman->FreeBoxes, offman->FreeBoxes, &NewReg); - REGION_UNINIT(pScreen, &NewReg); - } - - return area; -} - -static FBAreaPtr -localAllocateOffscreenArea( - ScreenPtr pScreen, - int w, int h, - int gran, - MoveAreaCallbackProcPtr moveCB, - RemoveAreaCallbackProcPtr removeCB, - pointer privData -){ - FBManagerPtr offman; - FBAreaPtr area = NULL; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - if((area = AllocateArea(offman, w, h, gran, moveCB, removeCB, privData))) - SendCallFreeBoxCallbacks(offman); - - return area; -} - - -static void -localFreeOffscreenArea(FBAreaPtr area) -{ - FBManagerPtr offman; - FBLinkPtr pLink, pLinkPrev = NULL; - RegionRec FreedRegion; - ScreenPtr pScreen; - - pScreen = area->pScreen; - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - pLink = offman->UsedAreas; - if(!pLink) return; - - while(&(pLink->area) != area) { - pLinkPrev = pLink; - pLink = pLink->next; - if(!pLink) return; - } - - /* put the area back into the pool */ - REGION_INIT(pScreen, &FreedRegion, &(pLink->area.box), 1); - REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedRegion); - REGION_UNINIT(pScreen, &FreedRegion); - - if(pLinkPrev) - pLinkPrev->next = pLink->next; - else offman->UsedAreas = pLink->next; - - xfree(pLink); - offman->NumUsedAreas--; - - SendCallFreeBoxCallbacks(offman); -} - - - -static Bool -localResizeOffscreenArea( - FBAreaPtr resize, - int w, int h -){ - FBManagerPtr offman; - ScreenPtr pScreen; - BoxRec OrigArea; - RegionRec FreedReg; - FBAreaPtr area = NULL; - FBLinkPtr pLink, newLink, pLinkPrev = NULL; - - pScreen = resize->pScreen; - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - /* find this link */ - if(!(pLink = offman->UsedAreas)) - return FALSE; - - while(&(pLink->area) != resize) { - pLinkPrev = pLink; - pLink = pLink->next; - if(!pLink) return FALSE; - } - - OrigArea.x1 = resize->box.x1; - OrigArea.x2 = resize->box.x2; - OrigArea.y1 = resize->box.y1; - OrigArea.y2 = resize->box.y2; - - /* if it's smaller, this is easy */ - - if((w <= (resize->box.x2 - resize->box.x1)) && - (h <= (resize->box.y2 - resize->box.y1))) { - RegionRec NewReg; - - resize->box.x2 = resize->box.x1 + w; - resize->box.y2 = resize->box.y1 + h; - - if((resize->box.y2 == OrigArea.y2) && - (resize->box.x2 == OrigArea.x2)) - return TRUE; - - REGION_INIT(pScreen, &FreedReg, &OrigArea, 1); - REGION_INIT(pScreen, &NewReg, &(resize->box), 1); - REGION_SUBTRACT(pScreen, &FreedReg, &FreedReg, &NewReg); - REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg); - REGION_UNINIT(pScreen, &FreedReg); - REGION_UNINIT(pScreen, &NewReg); - - SendCallFreeBoxCallbacks(offman); - - return TRUE; - } - - - /* otherwise we remove the old region */ - - REGION_INIT(pScreen, &FreedReg, &OrigArea, 1); - REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg); - - /* remove the old link */ - if(pLinkPrev) - pLinkPrev->next = pLink->next; - else offman->UsedAreas = pLink->next; - - /* and try to add a new one */ - - if((area = AllocateArea(offman, w, h, resize->granularity, - resize->MoveAreaCallback, resize->RemoveAreaCallback, - resize->devPrivate.ptr))) { - - /* copy data over to our link and replace the new with old */ - memcpy(resize, area, sizeof(FBArea)); - - pLinkPrev = NULL; - newLink = offman->UsedAreas; - - while(&(newLink->area) != area) { - pLinkPrev = newLink; - newLink = newLink->next; - } - - if(pLinkPrev) - pLinkPrev->next = newLink->next; - else offman->UsedAreas = newLink->next; - - pLink->next = offman->UsedAreas; - offman->UsedAreas = pLink; - - xfree(newLink); - - /* AllocateArea added one but we really only exchanged one */ - offman->NumUsedAreas--; - } else { - /* reinstate the old region */ - REGION_SUBTRACT(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg); - REGION_UNINIT(pScreen, &FreedReg); - - pLink->next = offman->UsedAreas; - offman->UsedAreas = pLink; - return FALSE; - } - - - REGION_UNINIT(pScreen, &FreedReg); - - SendCallFreeBoxCallbacks(offman); - - return TRUE; -} - -static Bool -localQueryLargestOffscreenArea( - ScreenPtr pScreen, - int *width, int *height, - int granularity, - int preferences, - int severity -){ - FBManagerPtr offman; - RegionPtr newRegion = NULL; - BoxPtr pbox; - int nbox; - int x, w, h, area, oldArea; - - *width = *height = oldArea = 0; - - if(granularity <= 1) granularity = 0; - - if((preferences < 0) || (preferences > 3)) - return FALSE; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - if(severity < 0) severity = 0; - if(severity > 2) severity = 2; - - switch(severity) { - case 2: - if(offman->NumUsedAreas) { - FBLinkPtr pLink; - RegionRec tmpRegion; - newRegion = REGION_CREATE(pScreen, NULL, 1); - REGION_COPY(pScreen, newRegion, offman->InitialBoxes); - pLink = offman->UsedAreas; - - while(pLink) { - if(!pLink->area.RemoveAreaCallback) { - REGION_INIT(pScreen, &tmpRegion, &(pLink->area.box), 1); - REGION_SUBTRACT(pScreen, newRegion, newRegion, &tmpRegion); - REGION_UNINIT(pScreen, &tmpRegion); - } - pLink = pLink->next; - } - - nbox = REGION_NUM_RECTS(newRegion); - pbox = REGION_RECTS(newRegion); - break; - } - case 1: - if(offman->NumUsedAreas) { - FBLinkPtr pLink; - RegionRec tmpRegion; - newRegion = REGION_CREATE(pScreen, NULL, 1); - REGION_COPY(pScreen, newRegion, offman->FreeBoxes); - pLink = offman->UsedAreas; - - while(pLink) { - if(pLink->area.RemoveAreaCallback) { - REGION_INIT(pScreen, &tmpRegion, &(pLink->area.box), 1); - REGION_APPEND(pScreen, newRegion, &tmpRegion); - REGION_UNINIT(pScreen, &tmpRegion); - } - pLink = pLink->next; - } - - nbox = REGION_NUM_RECTS(newRegion); - pbox = REGION_RECTS(newRegion); - break; - } - default: - nbox = REGION_NUM_RECTS(offman->FreeBoxes); - pbox = REGION_RECTS(offman->FreeBoxes); - break; - } - - while(nbox--) { - x = pbox->x1; - if (granularity > 1) - x = ((x + granularity - 1) / granularity) * granularity; - - w = pbox->x2 - x; - h = pbox->y2 - pbox->y1; - area = w * h; - - if(w > 0) { - Bool gotIt = FALSE; - switch(preferences) { - case FAVOR_AREA_THEN_WIDTH: - if((area > oldArea) || ((area == oldArea) && (w > *width))) - gotIt = TRUE; - break; - case FAVOR_AREA_THEN_HEIGHT: - if((area > oldArea) || ((area == oldArea) && (h > *height))) - gotIt = TRUE; - break; - case FAVOR_WIDTH_THEN_AREA: - if((w > *width) || ((w == *width) && (area > oldArea))) - gotIt = TRUE; - break; - case FAVOR_HEIGHT_THEN_AREA: - if((h > *height) || ((h == *height) && (area > oldArea))) - gotIt = TRUE; - break; - } - if(gotIt) { - *width = w; - *height = h; - oldArea = area; - } - } - pbox++; - } - - if(newRegion) - REGION_DESTROY(pScreen, newRegion); - - return TRUE; -} - -static Bool -localPurgeUnlockedOffscreenAreas(ScreenPtr pScreen) -{ - FBManagerPtr offman; - FBLinkPtr pLink, tmp, pPrev = NULL; - RegionRec FreedRegion; - Bool anyUsed = FALSE; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - pLink = offman->UsedAreas; - if(!pLink) return TRUE; - - while(pLink) { - if(pLink->area.RemoveAreaCallback) { - (*pLink->area.RemoveAreaCallback)(&pLink->area); - - REGION_INIT(pScreen, &FreedRegion, &(pLink->area.box), 1); - REGION_APPEND(pScreen, offman->FreeBoxes, &FreedRegion); - REGION_UNINIT(pScreen, &FreedRegion); - - if(pPrev) - pPrev->next = pLink->next; - else offman->UsedAreas = pLink->next; - - tmp = pLink; - pLink = pLink->next; - xfree(tmp); - offman->NumUsedAreas--; - anyUsed = TRUE; - } else { - pPrev = pLink; - pLink = pLink->next; - } - } - - if(anyUsed) { - REGION_VALIDATE(pScreen, offman->FreeBoxes, &anyUsed); - SendCallFreeBoxCallbacks(offman); - } - - return TRUE; -} - -static void -LinearMoveCBWrapper(FBAreaPtr from, FBAreaPtr to) -{ - /* this will never get called */ -} - -static void -LinearRemoveCBWrapper(FBAreaPtr area) -{ - FBManagerPtr offman; - FBLinearLinkPtr pLink, pLinkPrev = NULL; - ScreenPtr pScreen = area->pScreen; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - pLink = offman->LinearAreas; - if(!pLink) return; - - while(pLink->area != area) { - pLinkPrev = pLink; - pLink = pLink->next; - if(!pLink) return; - } - - /* give the user the callback it is expecting */ - (*pLink->linear.RemoveLinearCallback)(&(pLink->linear)); - - if(pLinkPrev) - pLinkPrev->next = pLink->next; - else offman->LinearAreas = pLink->next; - - xfree(pLink); -} - -static void -DumpDebug(FBLinearLinkPtr pLink) -{ -#ifdef DEBUG - if (!pLink) ErrorF("MMmm, PLINK IS NULL!\n"); - - while (pLink) { - ErrorF(" Offset:%08x, Size:%08x, %s,%s\n", - pLink->linear.offset, - pLink->linear.size, - pLink->free ? "Free" : "Used", - pLink->area ? "Area" : "Linear"); - - pLink = pLink->next; - } -#endif -} - -static FBLinearPtr -AllocateLinear( - FBManagerPtr offman, - int size, - int granularity, - pointer privData -){ - ScreenPtr pScreen = offman->pScreen; - FBLinearLinkPtr linear = NULL; - FBLinearLinkPtr newlink = NULL; - int offset, end; - - if(size <= 0) return NULL; - - if (!offman->LinearAreas) return NULL; - - linear = offman->LinearAreas; - while (linear) { - /* Make sure we get a free area that's not an XY fallback case */ - if (!linear->area && linear->free) { - offset = linear->linear.offset; - if (granularity > 1) - offset = ((offset + granularity - 1) / granularity) * granularity; - end = offset+size; - if (end <= (linear->linear.offset + linear->linear.size)) - break; - } - linear = linear->next; - } - if (!linear) - return NULL; - - /* break left */ - if (offset > linear->linear.offset) { - newlink = xalloc(sizeof(FBLinearLink)); - if (!newlink) - return NULL; - newlink->area = NULL; - newlink->linear.offset = offset; - newlink->linear.size = linear->linear.size - (offset - linear->linear.offset); - newlink->free = 1; - newlink->next = linear->next; - linear->linear.size -= newlink->linear.size; - linear->next = newlink; - linear = newlink; - } - - /* break right */ - if (size < linear->linear.size) { - newlink = xalloc(sizeof(FBLinearLink)); - if (!newlink) - return NULL; - newlink->area = NULL; - newlink->linear.offset = offset + size; - newlink->linear.size = linear->linear.size - size; - newlink->free = 1; - newlink->next = linear->next; - linear->linear.size = size; - linear->next = newlink; - } - - /* p = middle block */ - linear->linear.granularity = granularity; - linear->free = 0; - linear->linear.pScreen = pScreen; - linear->linear.MoveLinearCallback = NULL; - linear->linear.RemoveLinearCallback = NULL; - linear->linear.devPrivate.ptr = NULL; - - DumpDebug(offman->LinearAreas); - - return &(linear->linear); -} - -static FBLinearPtr -localAllocateOffscreenLinear( - ScreenPtr pScreen, - int length, - int gran, - MoveLinearCallbackProcPtr moveCB, - RemoveLinearCallbackProcPtr removeCB, - pointer privData -){ - FBManagerPtr offman; - FBLinearLinkPtr link; - FBAreaPtr area; - FBLinearPtr linear = NULL; - BoxPtr extents; - int w, h, pitch; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - - /* Try to allocate from linear memory first...... */ - DebugF("ALLOCATING LINEAR\n"); - if ((linear = AllocateLinear(offman, length, gran, privData))) - return linear; - - DebugF("NOPE, ALLOCATING AREA\n"); - - if(!(link = xalloc(sizeof(FBLinearLink)))) - return NULL; - - /* No linear available, so try and pinch some from the XY areas */ - extents = REGION_EXTENTS(pScreen, offman->InitialBoxes); - pitch = extents->x2 - extents->x1; - - if (gran > 1) { - if (gran > pitch) { - /* we can't match the specified alignment with XY allocations */ - xfree(link); - return NULL; - } - - if (pitch % gran) { - /* pitch and granularity aren't a perfect match, let's allocate - * a bit more so we can align later on - */ - length += gran - 1; - } - } - - if(length < pitch) { /* special case */ - w = length; - h = 1; - } else { - w = pitch; - h = (length + pitch - 1) / pitch; - } - - if((area = localAllocateOffscreenArea(pScreen, w, h, gran, - moveCB ? LinearMoveCBWrapper : NULL, - removeCB ? LinearRemoveCBWrapper : NULL, - privData))) - { - link->area = area; - link->free = 0; - link->next = offman->LinearAreas; - offman->LinearAreas = link; - linear = &(link->linear); - linear->pScreen = pScreen; - linear->size = h * w; - linear->offset = (pitch * area->box.y1) + area->box.x1; - if (gran > 1) - linear->offset = ((linear->offset + gran - 1) / gran) * gran; - linear->granularity = gran; - linear->MoveLinearCallback = moveCB; - linear->RemoveLinearCallback = removeCB; - linear->devPrivate.ptr = privData; - } else - xfree(link); - - DumpDebug(offman->LinearAreas); - - return linear; -} - - -static void -localFreeOffscreenLinear(FBLinearPtr linear) -{ - FBManagerPtr offman; - FBLinearLinkPtr pLink, pLinkPrev = NULL; - ScreenPtr pScreen = linear->pScreen; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - pLink = offman->LinearAreas; - if(!pLink) return; - - while(&(pLink->linear) != linear) { - pLinkPrev = pLink; - pLink = pLink->next; - if(!pLink) return; - } - - if(pLink->area) { /* really an XY area */ - DebugF("FREEING AREA\n"); - localFreeOffscreenArea(pLink->area); - if(pLinkPrev) - pLinkPrev->next = pLink->next; - else offman->LinearAreas = pLink->next; - xfree(pLink); - DumpDebug(offman->LinearAreas); - return; - } - - pLink->free = 1; - - if (pLink->next && pLink->next->free) { - FBLinearLinkPtr p = pLink->next; - pLink->linear.size += p->linear.size; - pLink->next = p->next; - free(p); - } - - if(pLinkPrev) { - if (pLinkPrev->next && pLinkPrev->next->free && !pLinkPrev->area) { - FBLinearLinkPtr p = pLinkPrev->next; - pLinkPrev->linear.size += p->linear.size; - pLinkPrev->next = p->next; - free(p); - } - } - - DebugF("FREEING LINEAR\n"); - DumpDebug(offman->LinearAreas); -} - - -static Bool -localResizeOffscreenLinear(FBLinearPtr resize, int length) -{ - FBManagerPtr offman; - FBLinearLinkPtr pLink; - ScreenPtr pScreen = resize->pScreen; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - pLink = offman->LinearAreas; - if(!pLink) return FALSE; - - while(&(pLink->linear) != resize) { - pLink = pLink->next; - if(!pLink) return FALSE; - } - - /* This could actually be alot smarter and try to move allocations - from XY to linear when available. For now if it was XY, we keep - it XY */ - - if(pLink->area) { /* really an XY area */ - BoxPtr extents; - int pitch, w, h; - - extents = REGION_EXTENTS(pScreen, offman->InitialBoxes); - pitch = extents->x2 - extents->x1; - - if(length < pitch) { /* special case */ - w = length; - h = 1; - } else { - w = pitch; - h = (length + pitch - 1) / pitch; - } - - if(localResizeOffscreenArea(pLink->area, w, h)) { - resize->size = h * w; - resize->offset = (pitch * pLink->area->box.y1) + pLink->area->box.x1; - return TRUE; - } - } else { - /* TODO!!!! resize the linear area */ - } - - return FALSE; -} - - -static Bool -localQueryLargestOffscreenLinear( - ScreenPtr pScreen, - int *size, - int gran, - int priority -) -{ - FBManagerPtr offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - FBLinearLinkPtr pLink; - FBLinearLinkPtr pLinkRet; - - *size = 0; - - pLink = offman->LinearAreas; - - if (pLink && !pLink->area) { - pLinkRet = pLink; - while (pLink) { - if (pLink->free) { - if (pLink->linear.size > pLinkRet->linear.size) - pLinkRet = pLink; - } - pLink = pLink->next; - } - - if (pLinkRet->free) { - *size = pLinkRet->linear.size; - return TRUE; - } - } else { - int w, h; - - if(localQueryLargestOffscreenArea(pScreen, &w, &h, gran, - FAVOR_WIDTH_THEN_AREA, priority)) - { - FBManagerPtr offman; - BoxPtr extents; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - extents = REGION_EXTENTS(pScreen, offman->InitialBoxes); - if((extents->x2 - extents->x1) == w) - *size = w * h; - return TRUE; - } - } - - return FALSE; -} - - - -static FBManagerFuncs xf86FBManFuncs = { - localAllocateOffscreenArea, - localFreeOffscreenArea, - localResizeOffscreenArea, - localQueryLargestOffscreenArea, - localRegisterFreeBoxCallback, - localAllocateOffscreenLinear, - localFreeOffscreenLinear, - localResizeOffscreenLinear, - localQueryLargestOffscreenLinear, - localPurgeUnlockedOffscreenAreas - }; - - -static Bool -xf86FBCloseScreen (int i, ScreenPtr pScreen) -{ - FBLinkPtr pLink, tmp; - FBLinearLinkPtr pLinearLink, tmp2; - FBManagerPtr offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - - pScreen->CloseScreen = offman->CloseScreen; - - pLink = offman->UsedAreas; - while(pLink) { - tmp = pLink; - pLink = pLink->next; - xfree(tmp); - } - - pLinearLink = offman->LinearAreas; - while(pLinearLink) { - tmp2 = pLinearLink; - pLinearLink = pLinearLink->next; - xfree(tmp2); - } - - REGION_DESTROY(pScreen, offman->InitialBoxes); - REGION_DESTROY(pScreen, offman->FreeBoxes); - - xfree(offman->FreeBoxesUpdateCallback); - xfree(offman->devPrivates); - xfree(offman); - dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, NULL); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -Bool -xf86InitFBManager( - ScreenPtr pScreen, - BoxPtr FullBox -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - RegionRec ScreenRegion; - RegionRec FullRegion; - BoxRec ScreenBox; - Bool ret; - - ScreenBox.x1 = 0; - ScreenBox.y1 = 0; - ScreenBox.x2 = pScrn->virtualX; - ScreenBox.y2 = pScrn->virtualY; - - if((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) || - (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) { - return FALSE; - } - - if (FullBox->y2 < FullBox->y1) return FALSE; - if (FullBox->x2 < FullBox->x1) return FALSE; - - REGION_INIT(pScreen, &ScreenRegion, &ScreenBox, 1); - REGION_INIT(pScreen, &FullRegion, FullBox, 1); - - REGION_SUBTRACT(pScreen, &FullRegion, &FullRegion, &ScreenRegion); - - ret = xf86InitFBManagerRegion(pScreen, &FullRegion); - - REGION_UNINIT(pScreen, &ScreenRegion); - REGION_UNINIT(pScreen, &FullRegion); - - return ret; -} - -Bool -xf86InitFBManagerArea( - ScreenPtr pScreen, - int PixelArea, - int Verbosity -) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xRectangle Rect[3]; - RegionPtr pRegion, pScreenRegion; - int nRect; - Bool ret = FALSE; - - if (PixelArea < (pScrn->displayWidth * pScrn->virtualY)) - return FALSE; - - Rect[0].x = Rect[0].y = 0; - Rect[0].width = pScrn->displayWidth; - Rect[0].height = PixelArea / pScrn->displayWidth; - nRect = 1; - - /* Add a possible partial scanline */ - if ((Rect[1].height = Rect[1].width = PixelArea % pScrn->displayWidth)) { - Rect[1].x = 0; - Rect[1].y = Rect[0].height; - Rect[1].height = 1; - nRect++; - } - - /* Factor out virtual resolution */ - pRegion = RECTS_TO_REGION(pScreen, nRect, Rect, 0); - if (pRegion) { - if (!REGION_NAR(pRegion)) { - Rect[2].x = Rect[2].y = 0; - Rect[2].width = pScrn->virtualX; - Rect[2].height = pScrn->virtualY; - - pScreenRegion = RECTS_TO_REGION(pScreen, 1, &Rect[2], 0); - if (pScreenRegion) { - if (!REGION_NAR(pScreenRegion)) { - REGION_SUBTRACT(pScreen, pRegion, pRegion, pScreenRegion); - - ret = xf86InitFBManagerRegion(pScreen, pRegion); - - if (ret && xf86GetVerbosity() >= Verbosity) { - int scrnIndex = pScrn->scrnIndex; - - xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, - "Largest offscreen areas (with overlaps):\n"); - - if (Rect[2].width < Rect[0].width) { - xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, - "\t%d x %d rectangle at %d,0\n", - Rect[0].width - Rect[2].width, - Rect[0].height, - Rect[2].width); - } - if (Rect[2].width < Rect[1].width) { - xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, - "\t%d x %d rectangle at %d,0\n", - Rect[1].width - Rect[2].width, - Rect[0].height + Rect[1].height, - Rect[2].width); - } - if (Rect[2].height < Rect[0].height) { - xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, - "\t%d x %d rectangle at 0,%d\n", - Rect[0].width, - Rect[0].height - Rect[2].height, - Rect[2].height); - } - if (Rect[1].height) { - xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, - "\t%d x %d rectangle at 0,%d\n", - Rect[1].width, - Rect[0].height - Rect[2].height + - Rect[1].height, - Rect[2].height); - } - } - } - - REGION_DESTROY(pScreen, pScreenRegion); - } - } - - REGION_DESTROY(pScreen, pRegion); - } - - return ret; -} - -Bool -xf86InitFBManagerRegion( - ScreenPtr pScreen, - RegionPtr FullRegion -){ - FBManagerPtr offman; - - if(REGION_NIL(FullRegion)) - return FALSE; - - if(!xf86RegisterOffscreenManager(pScreen, &xf86FBManFuncs)) - return FALSE; - - offman = xalloc(sizeof(FBManager)); - if(!offman) return FALSE; - - dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, offman); - - offman->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = xf86FBCloseScreen; - - offman->InitialBoxes = REGION_CREATE(pScreen, NULL, 1); - offman->FreeBoxes = REGION_CREATE(pScreen, NULL, 1); - - REGION_COPY(pScreen, offman->InitialBoxes, FullRegion); - REGION_COPY(pScreen, offman->FreeBoxes, FullRegion); - - offman->pScreen = pScreen; - offman->UsedAreas = NULL; - offman->LinearAreas = NULL; - offman->NumUsedAreas = 0; - offman->NumCallbacks = 0; - offman->FreeBoxesUpdateCallback = NULL; - offman->devPrivates = NULL; - - return TRUE; -} - -Bool -xf86InitFBManagerLinear( - ScreenPtr pScreen, - int offset, - int size -){ - FBManagerPtr offman; - FBLinearLinkPtr link; - FBLinearPtr linear; - - if (size <= 0) - return FALSE; - - /* we expect people to have called the Area setup first for pixmap cache */ - if (!dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey)) - return FALSE; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - offman->LinearAreas = xalloc(sizeof(FBLinearLink)); - if (!offman->LinearAreas) - return FALSE; - - link = offman->LinearAreas; - link->area = NULL; - link->next = NULL; - link->free = 1; - linear = &(link->linear); - linear->pScreen = pScreen; - linear->size = size; - linear->offset = offset; - linear->granularity = 0; - linear->MoveLinearCallback = NULL; - linear->RemoveLinearCallback = NULL; - linear->devPrivate.ptr = NULL; - - return TRUE; -} - - -/* This is an implementation specific function and should - disappear after the next release. People should use the - real linear functions instead */ - -FBAreaPtr -xf86AllocateLinearOffscreenArea ( - ScreenPtr pScreen, - int length, - int gran, - MoveAreaCallbackProcPtr moveCB, - RemoveAreaCallbackProcPtr removeCB, - pointer privData -){ - FBManagerFuncsPtr funcs; - FBManagerPtr offman; - BoxPtr extents; - int w, h; - - if(xf86FBManagerKey == NULL) - return NULL; - if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBManagerKey))) - return NULL; - - offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, - xf86FBScreenKey); - extents = REGION_EXTENTS(pScreen, offman->InitialBoxes); - w = extents->x2 - extents->x1; - - if (gran > 1) { - if (gran > w) - return NULL; - - if (w % gran) - length += gran - 1; - } - - if(length <= w) { /* special case */ - h = 1; - w = length; - } else { - h = (length + w - 1) / w; - } - - return (*funcs->AllocateOffscreenArea)( - pScreen, w, h, gran, moveCB, removeCB, privData); -} + +/* + * Copyright (c) 1998-2001 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" + +#include +#include "scrnintstr.h" +#include "regionstr.h" +#include "xf86fbman.h" + +/* +#define DEBUG +*/ + +static int xf86FBManagerKeyIndex; +static DevPrivateKey xf86FBManagerKey; + +Bool xf86RegisterOffscreenManager( + ScreenPtr pScreen, + FBManagerFuncsPtr funcs +){ + + xf86FBManagerKey = &xf86FBManagerKeyIndex; + dixSetPrivate(&pScreen->devPrivates, xf86FBManagerKey, funcs); + + return TRUE; +} + + +Bool +xf86FBManagerRunning(ScreenPtr pScreen) +{ + if(xf86FBManagerKey == NULL) + return FALSE; + if(!dixLookupPrivate(&pScreen->devPrivates, xf86FBManagerKey)) + return FALSE; + + return TRUE; +} + +Bool +xf86RegisterFreeBoxCallback( + ScreenPtr pScreen, + FreeBoxCallbackProcPtr FreeBoxCallback, + pointer devPriv +){ + FBManagerFuncsPtr funcs; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return FALSE; + + return (*funcs->RegisterFreeBoxCallback)(pScreen, FreeBoxCallback, devPriv); +} + + +FBAreaPtr +xf86AllocateOffscreenArea( + ScreenPtr pScreen, + int w, int h, + int gran, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +){ + FBManagerFuncsPtr funcs; + + if(xf86FBManagerKey == NULL) + return NULL; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return NULL; + + return (*funcs->AllocateOffscreenArea)( + pScreen, w, h, gran, moveCB, removeCB, privData); +} + + +FBLinearPtr +xf86AllocateOffscreenLinear( + ScreenPtr pScreen, + int length, + int gran, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData +){ + FBManagerFuncsPtr funcs; + + if(xf86FBManagerKey == NULL) + return NULL; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return NULL; + + return (*funcs->AllocateOffscreenLinear)( + pScreen, length, gran, moveCB, removeCB, privData); +} + + +void +xf86FreeOffscreenArea(FBAreaPtr area) +{ + FBManagerFuncsPtr funcs; + + if(!area) return; + + if(xf86FBManagerKey == NULL) + return; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( + &area->pScreen->devPrivates, xf86FBManagerKey))) + return; + + (*funcs->FreeOffscreenArea)(area); + + return; +} + + +void +xf86FreeOffscreenLinear(FBLinearPtr linear) +{ + FBManagerFuncsPtr funcs; + + if(!linear) return; + + if(xf86FBManagerKey == NULL) + return; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( + &linear->pScreen->devPrivates, xf86FBManagerKey))) + return; + + (*funcs->FreeOffscreenLinear)(linear); + + return; +} + + +Bool +xf86ResizeOffscreenArea( + FBAreaPtr resize, + int w, int h +){ + FBManagerFuncsPtr funcs; + + if(!resize) return FALSE; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( + &resize->pScreen->devPrivates, xf86FBManagerKey))) + return FALSE; + + return (*funcs->ResizeOffscreenArea)(resize, w, h); +} + +Bool +xf86ResizeOffscreenLinear( + FBLinearPtr resize, + int size +){ + FBManagerFuncsPtr funcs; + + if(!resize) return FALSE; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate( + &resize->pScreen->devPrivates, xf86FBManagerKey))) + return FALSE; + + return (*funcs->ResizeOffscreenLinear)(resize, size); +} + + +Bool +xf86QueryLargestOffscreenArea( + ScreenPtr pScreen, + int *w, int *h, + int gran, + int preferences, + int severity +){ + FBManagerFuncsPtr funcs; + + *w = 0; + *h = 0; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return FALSE; + + return (*funcs->QueryLargestOffscreenArea)( + pScreen, w, h, gran, preferences, severity); +} + +Bool +xf86QueryLargestOffscreenLinear( + ScreenPtr pScreen, + int *size, + int gran, + int severity +){ + FBManagerFuncsPtr funcs; + + *size = 0; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return FALSE; + + return (*funcs->QueryLargestOffscreenLinear)( + pScreen, size, gran, severity); +} + + +Bool +xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen) +{ + FBManagerFuncsPtr funcs; + + if(xf86FBManagerKey == NULL) + return FALSE; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return FALSE; + + return (*funcs->PurgeOffscreenAreas)(pScreen); +} + +/************************************************************\ + + Below is a specific implementation of an offscreen manager. + +\************************************************************/ + +static int xf86FBScreenKeyIndex; +static DevPrivateKey xf86FBScreenKey = &xf86FBScreenKeyIndex; + +typedef struct _FBLink { + FBArea area; + struct _FBLink *next; +} FBLink, *FBLinkPtr; + +typedef struct _FBLinearLink { + FBLinear linear; + int free; /* need to add free here as FBLinear is publicly accessible */ + FBAreaPtr area; /* only used if allocation came from XY area */ + struct _FBLinearLink *next; +} FBLinearLink, *FBLinearLinkPtr; + + +typedef struct { + ScreenPtr pScreen; + RegionPtr InitialBoxes; + RegionPtr FreeBoxes; + FBLinkPtr UsedAreas; + int NumUsedAreas; + FBLinearLinkPtr LinearAreas; + CloseScreenProcPtr CloseScreen; + int NumCallbacks; + FreeBoxCallbackProcPtr *FreeBoxesUpdateCallback; + DevUnion *devPrivates; +} FBManager, *FBManagerPtr; + + +static void +SendCallFreeBoxCallbacks(FBManagerPtr offman) +{ + int i = offman->NumCallbacks; + + while(i--) { + (*offman->FreeBoxesUpdateCallback[i])( + offman->pScreen, offman->FreeBoxes, offman->devPrivates[i].ptr); + } +} + +static Bool +localRegisterFreeBoxCallback( + ScreenPtr pScreen, + FreeBoxCallbackProcPtr FreeBoxCallback, + pointer devPriv +){ + FBManagerPtr offman; + FreeBoxCallbackProcPtr *newCallbacks; + DevUnion *newPrivates; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + newCallbacks = realloc( offman->FreeBoxesUpdateCallback, + sizeof(FreeBoxCallbackProcPtr) * (offman->NumCallbacks + 1)); + + newPrivates = realloc(offman->devPrivates, + sizeof(DevUnion) * (offman->NumCallbacks + 1)); + + if(!newCallbacks || !newPrivates) + return FALSE; + + offman->FreeBoxesUpdateCallback = newCallbacks; + offman->devPrivates = newPrivates; + + offman->FreeBoxesUpdateCallback[offman->NumCallbacks] = FreeBoxCallback; + offman->devPrivates[offman->NumCallbacks].ptr = devPriv; + offman->NumCallbacks++; + + SendCallFreeBoxCallbacks(offman); + + return TRUE; +} + + +static FBAreaPtr +AllocateArea( + FBManagerPtr offman, + int w, int h, + int granularity, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +){ + ScreenPtr pScreen = offman->pScreen; + FBLinkPtr link = NULL; + FBAreaPtr area = NULL; + RegionRec NewReg; + int i, x = 0, num; + BoxPtr boxp; + + if(granularity <= 1) granularity = 0; + + boxp = REGION_RECTS(offman->FreeBoxes); + num = REGION_NUM_RECTS(offman->FreeBoxes); + + /* look through the free boxes */ + for(i = 0; i < num; i++, boxp++) { + x = boxp->x1; + if (granularity > 1) + x = ((x + granularity - 1) / granularity) * granularity; + + if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) + continue; + + link = malloc(sizeof(FBLink)); + if(!link) return NULL; + + area = &(link->area); + link->next = offman->UsedAreas; + offman->UsedAreas = link; + offman->NumUsedAreas++; + break; + } + + /* try to boot a removeable one out if we are not expendable ourselves */ + if(!area && !removeCB) { + link = offman->UsedAreas; + + while(link) { + if(!link->area.RemoveAreaCallback) { + link = link->next; + continue; + } + + boxp = &(link->area.box); + x = boxp->x1; + if (granularity > 1) + x = ((x + granularity - 1) / granularity) * granularity; + + if(((boxp->y2 - boxp->y1) < h) || ((boxp->x2 - x) < w)) { + link = link->next; + continue; + } + + /* bye, bye */ + (*link->area.RemoveAreaCallback)(&link->area); + REGION_INIT(pScreen, &NewReg, &(link->area.box), 1); + REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &NewReg); + REGION_UNINIT(pScreen, &NewReg); + + area = &(link->area); + break; + } + } + + if(area) { + area->pScreen = pScreen; + area->granularity = granularity; + area->box.x1 = x; + area->box.x2 = x + w; + area->box.y1 = boxp->y1; + area->box.y2 = boxp->y1 + h; + area->MoveAreaCallback = moveCB; + area->RemoveAreaCallback = removeCB; + area->devPrivate.ptr = privData; + + REGION_INIT(pScreen, &NewReg, &(area->box), 1); + REGION_SUBTRACT(pScreen, offman->FreeBoxes, offman->FreeBoxes, &NewReg); + REGION_UNINIT(pScreen, &NewReg); + } + + return area; +} + +static FBAreaPtr +localAllocateOffscreenArea( + ScreenPtr pScreen, + int w, int h, + int gran, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +){ + FBManagerPtr offman; + FBAreaPtr area = NULL; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + if((area = AllocateArea(offman, w, h, gran, moveCB, removeCB, privData))) + SendCallFreeBoxCallbacks(offman); + + return area; +} + + +static void +localFreeOffscreenArea(FBAreaPtr area) +{ + FBManagerPtr offman; + FBLinkPtr pLink, pLinkPrev = NULL; + RegionRec FreedRegion; + ScreenPtr pScreen; + + pScreen = area->pScreen; + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->UsedAreas; + if(!pLink) return; + + while(&(pLink->area) != area) { + pLinkPrev = pLink; + pLink = pLink->next; + if(!pLink) return; + } + + /* put the area back into the pool */ + REGION_INIT(pScreen, &FreedRegion, &(pLink->area.box), 1); + REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedRegion); + REGION_UNINIT(pScreen, &FreedRegion); + + if(pLinkPrev) + pLinkPrev->next = pLink->next; + else offman->UsedAreas = pLink->next; + + free(pLink); + offman->NumUsedAreas--; + + SendCallFreeBoxCallbacks(offman); +} + + + +static Bool +localResizeOffscreenArea( + FBAreaPtr resize, + int w, int h +){ + FBManagerPtr offman; + ScreenPtr pScreen; + BoxRec OrigArea; + RegionRec FreedReg; + FBAreaPtr area = NULL; + FBLinkPtr pLink, newLink, pLinkPrev = NULL; + + pScreen = resize->pScreen; + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + /* find this link */ + if(!(pLink = offman->UsedAreas)) + return FALSE; + + while(&(pLink->area) != resize) { + pLinkPrev = pLink; + pLink = pLink->next; + if(!pLink) return FALSE; + } + + OrigArea.x1 = resize->box.x1; + OrigArea.x2 = resize->box.x2; + OrigArea.y1 = resize->box.y1; + OrigArea.y2 = resize->box.y2; + + /* if it's smaller, this is easy */ + + if((w <= (resize->box.x2 - resize->box.x1)) && + (h <= (resize->box.y2 - resize->box.y1))) { + RegionRec NewReg; + + resize->box.x2 = resize->box.x1 + w; + resize->box.y2 = resize->box.y1 + h; + + if((resize->box.y2 == OrigArea.y2) && + (resize->box.x2 == OrigArea.x2)) + return TRUE; + + REGION_INIT(pScreen, &FreedReg, &OrigArea, 1); + REGION_INIT(pScreen, &NewReg, &(resize->box), 1); + REGION_SUBTRACT(pScreen, &FreedReg, &FreedReg, &NewReg); + REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg); + REGION_UNINIT(pScreen, &FreedReg); + REGION_UNINIT(pScreen, &NewReg); + + SendCallFreeBoxCallbacks(offman); + + return TRUE; + } + + + /* otherwise we remove the old region */ + + REGION_INIT(pScreen, &FreedReg, &OrigArea, 1); + REGION_UNION(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg); + + /* remove the old link */ + if(pLinkPrev) + pLinkPrev->next = pLink->next; + else offman->UsedAreas = pLink->next; + + /* and try to add a new one */ + + if((area = AllocateArea(offman, w, h, resize->granularity, + resize->MoveAreaCallback, resize->RemoveAreaCallback, + resize->devPrivate.ptr))) { + + /* copy data over to our link and replace the new with old */ + memcpy(resize, area, sizeof(FBArea)); + + pLinkPrev = NULL; + newLink = offman->UsedAreas; + + while(&(newLink->area) != area) { + pLinkPrev = newLink; + newLink = newLink->next; + } + + if(pLinkPrev) + pLinkPrev->next = newLink->next; + else offman->UsedAreas = newLink->next; + + pLink->next = offman->UsedAreas; + offman->UsedAreas = pLink; + + free(newLink); + + /* AllocateArea added one but we really only exchanged one */ + offman->NumUsedAreas--; + } else { + /* reinstate the old region */ + REGION_SUBTRACT(pScreen, offman->FreeBoxes, offman->FreeBoxes, &FreedReg); + REGION_UNINIT(pScreen, &FreedReg); + + pLink->next = offman->UsedAreas; + offman->UsedAreas = pLink; + return FALSE; + } + + + REGION_UNINIT(pScreen, &FreedReg); + + SendCallFreeBoxCallbacks(offman); + + return TRUE; +} + +static Bool +localQueryLargestOffscreenArea( + ScreenPtr pScreen, + int *width, int *height, + int granularity, + int preferences, + int severity +){ + FBManagerPtr offman; + RegionPtr newRegion = NULL; + BoxPtr pbox; + int nbox; + int x, w, h, area, oldArea; + + *width = *height = oldArea = 0; + + if(granularity <= 1) granularity = 0; + + if((preferences < 0) || (preferences > 3)) + return FALSE; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + if(severity < 0) severity = 0; + if(severity > 2) severity = 2; + + switch(severity) { + case 2: + if(offman->NumUsedAreas) { + FBLinkPtr pLink; + RegionRec tmpRegion; + newRegion = REGION_CREATE(pScreen, NULL, 1); + REGION_COPY(pScreen, newRegion, offman->InitialBoxes); + pLink = offman->UsedAreas; + + while(pLink) { + if(!pLink->area.RemoveAreaCallback) { + REGION_INIT(pScreen, &tmpRegion, &(pLink->area.box), 1); + REGION_SUBTRACT(pScreen, newRegion, newRegion, &tmpRegion); + REGION_UNINIT(pScreen, &tmpRegion); + } + pLink = pLink->next; + } + + nbox = REGION_NUM_RECTS(newRegion); + pbox = REGION_RECTS(newRegion); + break; + } + case 1: + if(offman->NumUsedAreas) { + FBLinkPtr pLink; + RegionRec tmpRegion; + newRegion = REGION_CREATE(pScreen, NULL, 1); + REGION_COPY(pScreen, newRegion, offman->FreeBoxes); + pLink = offman->UsedAreas; + + while(pLink) { + if(pLink->area.RemoveAreaCallback) { + REGION_INIT(pScreen, &tmpRegion, &(pLink->area.box), 1); + REGION_APPEND(pScreen, newRegion, &tmpRegion); + REGION_UNINIT(pScreen, &tmpRegion); + } + pLink = pLink->next; + } + + nbox = REGION_NUM_RECTS(newRegion); + pbox = REGION_RECTS(newRegion); + break; + } + default: + nbox = REGION_NUM_RECTS(offman->FreeBoxes); + pbox = REGION_RECTS(offman->FreeBoxes); + break; + } + + while(nbox--) { + x = pbox->x1; + if (granularity > 1) + x = ((x + granularity - 1) / granularity) * granularity; + + w = pbox->x2 - x; + h = pbox->y2 - pbox->y1; + area = w * h; + + if(w > 0) { + Bool gotIt = FALSE; + switch(preferences) { + case FAVOR_AREA_THEN_WIDTH: + if((area > oldArea) || ((area == oldArea) && (w > *width))) + gotIt = TRUE; + break; + case FAVOR_AREA_THEN_HEIGHT: + if((area > oldArea) || ((area == oldArea) && (h > *height))) + gotIt = TRUE; + break; + case FAVOR_WIDTH_THEN_AREA: + if((w > *width) || ((w == *width) && (area > oldArea))) + gotIt = TRUE; + break; + case FAVOR_HEIGHT_THEN_AREA: + if((h > *height) || ((h == *height) && (area > oldArea))) + gotIt = TRUE; + break; + } + if(gotIt) { + *width = w; + *height = h; + oldArea = area; + } + } + pbox++; + } + + if(newRegion) + REGION_DESTROY(pScreen, newRegion); + + return TRUE; +} + +static Bool +localPurgeUnlockedOffscreenAreas(ScreenPtr pScreen) +{ + FBManagerPtr offman; + FBLinkPtr pLink, tmp, pPrev = NULL; + RegionRec FreedRegion; + Bool anyUsed = FALSE; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->UsedAreas; + if(!pLink) return TRUE; + + while(pLink) { + if(pLink->area.RemoveAreaCallback) { + (*pLink->area.RemoveAreaCallback)(&pLink->area); + + REGION_INIT(pScreen, &FreedRegion, &(pLink->area.box), 1); + REGION_APPEND(pScreen, offman->FreeBoxes, &FreedRegion); + REGION_UNINIT(pScreen, &FreedRegion); + + if(pPrev) + pPrev->next = pLink->next; + else offman->UsedAreas = pLink->next; + + tmp = pLink; + pLink = pLink->next; + free(tmp); + offman->NumUsedAreas--; + anyUsed = TRUE; + } else { + pPrev = pLink; + pLink = pLink->next; + } + } + + if(anyUsed) { + REGION_VALIDATE(pScreen, offman->FreeBoxes, &anyUsed); + SendCallFreeBoxCallbacks(offman); + } + + return TRUE; +} + +static void +LinearMoveCBWrapper(FBAreaPtr from, FBAreaPtr to) +{ + /* this will never get called */ +} + +static void +LinearRemoveCBWrapper(FBAreaPtr area) +{ + FBManagerPtr offman; + FBLinearLinkPtr pLink, pLinkPrev = NULL; + ScreenPtr pScreen = area->pScreen; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->LinearAreas; + if(!pLink) return; + + while(pLink->area != area) { + pLinkPrev = pLink; + pLink = pLink->next; + if(!pLink) return; + } + + /* give the user the callback it is expecting */ + (*pLink->linear.RemoveLinearCallback)(&(pLink->linear)); + + if(pLinkPrev) + pLinkPrev->next = pLink->next; + else offman->LinearAreas = pLink->next; + + free(pLink); +} + +static void +DumpDebug(FBLinearLinkPtr pLink) +{ +#ifdef DEBUG + if (!pLink) ErrorF("MMmm, PLINK IS NULL!\n"); + + while (pLink) { + ErrorF(" Offset:%08x, Size:%08x, %s,%s\n", + pLink->linear.offset, + pLink->linear.size, + pLink->free ? "Free" : "Used", + pLink->area ? "Area" : "Linear"); + + pLink = pLink->next; + } +#endif +} + +static FBLinearPtr +AllocateLinear( + FBManagerPtr offman, + int size, + int granularity, + pointer privData +){ + ScreenPtr pScreen = offman->pScreen; + FBLinearLinkPtr linear = NULL; + FBLinearLinkPtr newlink = NULL; + int offset, end; + + if(size <= 0) return NULL; + + if (!offman->LinearAreas) return NULL; + + linear = offman->LinearAreas; + while (linear) { + /* Make sure we get a free area that's not an XY fallback case */ + if (!linear->area && linear->free) { + offset = linear->linear.offset; + if (granularity > 1) + offset = ((offset + granularity - 1) / granularity) * granularity; + end = offset+size; + if (end <= (linear->linear.offset + linear->linear.size)) + break; + } + linear = linear->next; + } + if (!linear) + return NULL; + + /* break left */ + if (offset > linear->linear.offset) { + newlink = malloc(sizeof(FBLinearLink)); + if (!newlink) + return NULL; + newlink->area = NULL; + newlink->linear.offset = offset; + newlink->linear.size = linear->linear.size - (offset - linear->linear.offset); + newlink->free = 1; + newlink->next = linear->next; + linear->linear.size -= newlink->linear.size; + linear->next = newlink; + linear = newlink; + } + + /* break right */ + if (size < linear->linear.size) { + newlink = malloc(sizeof(FBLinearLink)); + if (!newlink) + return NULL; + newlink->area = NULL; + newlink->linear.offset = offset + size; + newlink->linear.size = linear->linear.size - size; + newlink->free = 1; + newlink->next = linear->next; + linear->linear.size = size; + linear->next = newlink; + } + + /* p = middle block */ + linear->linear.granularity = granularity; + linear->free = 0; + linear->linear.pScreen = pScreen; + linear->linear.MoveLinearCallback = NULL; + linear->linear.RemoveLinearCallback = NULL; + linear->linear.devPrivate.ptr = NULL; + + DumpDebug(offman->LinearAreas); + + return &(linear->linear); +} + +static FBLinearPtr +localAllocateOffscreenLinear( + ScreenPtr pScreen, + int length, + int gran, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData +){ + FBManagerPtr offman; + FBLinearLinkPtr link; + FBAreaPtr area; + FBLinearPtr linear = NULL; + BoxPtr extents; + int w, h, pitch; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + + /* Try to allocate from linear memory first...... */ + DebugF("ALLOCATING LINEAR\n"); + if ((linear = AllocateLinear(offman, length, gran, privData))) + return linear; + + DebugF("NOPE, ALLOCATING AREA\n"); + + if(!(link = malloc(sizeof(FBLinearLink)))) + return NULL; + + /* No linear available, so try and pinch some from the XY areas */ + extents = REGION_EXTENTS(pScreen, offman->InitialBoxes); + pitch = extents->x2 - extents->x1; + + if (gran > 1) { + if (gran > pitch) { + /* we can't match the specified alignment with XY allocations */ + free(link); + return NULL; + } + + if (pitch % gran) { + /* pitch and granularity aren't a perfect match, let's allocate + * a bit more so we can align later on + */ + length += gran - 1; + } + } + + if(length < pitch) { /* special case */ + w = length; + h = 1; + } else { + w = pitch; + h = (length + pitch - 1) / pitch; + } + + if((area = localAllocateOffscreenArea(pScreen, w, h, gran, + moveCB ? LinearMoveCBWrapper : NULL, + removeCB ? LinearRemoveCBWrapper : NULL, + privData))) + { + link->area = area; + link->free = 0; + link->next = offman->LinearAreas; + offman->LinearAreas = link; + linear = &(link->linear); + linear->pScreen = pScreen; + linear->size = h * w; + linear->offset = (pitch * area->box.y1) + area->box.x1; + if (gran > 1) + linear->offset = ((linear->offset + gran - 1) / gran) * gran; + linear->granularity = gran; + linear->MoveLinearCallback = moveCB; + linear->RemoveLinearCallback = removeCB; + linear->devPrivate.ptr = privData; + } else + free(link); + + DumpDebug(offman->LinearAreas); + + return linear; +} + + +static void +localFreeOffscreenLinear(FBLinearPtr linear) +{ + FBManagerPtr offman; + FBLinearLinkPtr pLink, pLinkPrev = NULL; + ScreenPtr pScreen = linear->pScreen; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->LinearAreas; + if(!pLink) return; + + while(&(pLink->linear) != linear) { + pLinkPrev = pLink; + pLink = pLink->next; + if(!pLink) return; + } + + if(pLink->area) { /* really an XY area */ + DebugF("FREEING AREA\n"); + localFreeOffscreenArea(pLink->area); + if(pLinkPrev) + pLinkPrev->next = pLink->next; + else offman->LinearAreas = pLink->next; + free(pLink); + DumpDebug(offman->LinearAreas); + return; + } + + pLink->free = 1; + + if (pLink->next && pLink->next->free) { + FBLinearLinkPtr p = pLink->next; + pLink->linear.size += p->linear.size; + pLink->next = p->next; + free(p); + } + + if(pLinkPrev) { + if (pLinkPrev->next && pLinkPrev->next->free && !pLinkPrev->area) { + FBLinearLinkPtr p = pLinkPrev->next; + pLinkPrev->linear.size += p->linear.size; + pLinkPrev->next = p->next; + free(p); + } + } + + DebugF("FREEING LINEAR\n"); + DumpDebug(offman->LinearAreas); +} + + +static Bool +localResizeOffscreenLinear(FBLinearPtr resize, int length) +{ + FBManagerPtr offman; + FBLinearLinkPtr pLink; + ScreenPtr pScreen = resize->pScreen; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + pLink = offman->LinearAreas; + if(!pLink) return FALSE; + + while(&(pLink->linear) != resize) { + pLink = pLink->next; + if(!pLink) return FALSE; + } + + /* This could actually be alot smarter and try to move allocations + from XY to linear when available. For now if it was XY, we keep + it XY */ + + if(pLink->area) { /* really an XY area */ + BoxPtr extents; + int pitch, w, h; + + extents = REGION_EXTENTS(pScreen, offman->InitialBoxes); + pitch = extents->x2 - extents->x1; + + if(length < pitch) { /* special case */ + w = length; + h = 1; + } else { + w = pitch; + h = (length + pitch - 1) / pitch; + } + + if(localResizeOffscreenArea(pLink->area, w, h)) { + resize->size = h * w; + resize->offset = (pitch * pLink->area->box.y1) + pLink->area->box.x1; + return TRUE; + } + } else { + /* TODO!!!! resize the linear area */ + } + + return FALSE; +} + + +static Bool +localQueryLargestOffscreenLinear( + ScreenPtr pScreen, + int *size, + int gran, + int priority +) +{ + FBManagerPtr offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + FBLinearLinkPtr pLink; + FBLinearLinkPtr pLinkRet; + + *size = 0; + + pLink = offman->LinearAreas; + + if (pLink && !pLink->area) { + pLinkRet = pLink; + while (pLink) { + if (pLink->free) { + if (pLink->linear.size > pLinkRet->linear.size) + pLinkRet = pLink; + } + pLink = pLink->next; + } + + if (pLinkRet->free) { + *size = pLinkRet->linear.size; + return TRUE; + } + } else { + int w, h; + + if(localQueryLargestOffscreenArea(pScreen, &w, &h, gran, + FAVOR_WIDTH_THEN_AREA, priority)) + { + FBManagerPtr offman; + BoxPtr extents; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + extents = REGION_EXTENTS(pScreen, offman->InitialBoxes); + if((extents->x2 - extents->x1) == w) + *size = w * h; + return TRUE; + } + } + + return FALSE; +} + + + +static FBManagerFuncs xf86FBManFuncs = { + localAllocateOffscreenArea, + localFreeOffscreenArea, + localResizeOffscreenArea, + localQueryLargestOffscreenArea, + localRegisterFreeBoxCallback, + localAllocateOffscreenLinear, + localFreeOffscreenLinear, + localResizeOffscreenLinear, + localQueryLargestOffscreenLinear, + localPurgeUnlockedOffscreenAreas + }; + + +static Bool +xf86FBCloseScreen (int i, ScreenPtr pScreen) +{ + FBLinkPtr pLink, tmp; + FBLinearLinkPtr pLinearLink, tmp2; + FBManagerPtr offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + + pScreen->CloseScreen = offman->CloseScreen; + + pLink = offman->UsedAreas; + while(pLink) { + tmp = pLink; + pLink = pLink->next; + free(tmp); + } + + pLinearLink = offman->LinearAreas; + while(pLinearLink) { + tmp2 = pLinearLink; + pLinearLink = pLinearLink->next; + free(tmp2); + } + + REGION_DESTROY(pScreen, offman->InitialBoxes); + REGION_DESTROY(pScreen, offman->FreeBoxes); + + free(offman->FreeBoxesUpdateCallback); + free(offman->devPrivates); + free(offman); + dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, NULL); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +Bool +xf86InitFBManager( + ScreenPtr pScreen, + BoxPtr FullBox +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RegionRec ScreenRegion; + RegionRec FullRegion; + BoxRec ScreenBox; + Bool ret; + + ScreenBox.x1 = 0; + ScreenBox.y1 = 0; + ScreenBox.x2 = pScrn->virtualX; + ScreenBox.y2 = pScrn->virtualY; + + if((FullBox->x1 > ScreenBox.x1) || (FullBox->y1 > ScreenBox.y1) || + (FullBox->x2 < ScreenBox.x2) || (FullBox->y2 < ScreenBox.y2)) { + return FALSE; + } + + if (FullBox->y2 < FullBox->y1) return FALSE; + if (FullBox->x2 < FullBox->x1) return FALSE; + + REGION_INIT(pScreen, &ScreenRegion, &ScreenBox, 1); + REGION_INIT(pScreen, &FullRegion, FullBox, 1); + + REGION_SUBTRACT(pScreen, &FullRegion, &FullRegion, &ScreenRegion); + + ret = xf86InitFBManagerRegion(pScreen, &FullRegion); + + REGION_UNINIT(pScreen, &ScreenRegion); + REGION_UNINIT(pScreen, &FullRegion); + + return ret; +} + +Bool +xf86InitFBManagerArea( + ScreenPtr pScreen, + int PixelArea, + int Verbosity +) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xRectangle Rect[3]; + RegionPtr pRegion, pScreenRegion; + int nRect; + Bool ret = FALSE; + + if (PixelArea < (pScrn->displayWidth * pScrn->virtualY)) + return FALSE; + + Rect[0].x = Rect[0].y = 0; + Rect[0].width = pScrn->displayWidth; + Rect[0].height = PixelArea / pScrn->displayWidth; + nRect = 1; + + /* Add a possible partial scanline */ + if ((Rect[1].height = Rect[1].width = PixelArea % pScrn->displayWidth)) { + Rect[1].x = 0; + Rect[1].y = Rect[0].height; + Rect[1].height = 1; + nRect++; + } + + /* Factor out virtual resolution */ + pRegion = RECTS_TO_REGION(pScreen, nRect, Rect, 0); + if (pRegion) { + if (!REGION_NAR(pRegion)) { + Rect[2].x = Rect[2].y = 0; + Rect[2].width = pScrn->virtualX; + Rect[2].height = pScrn->virtualY; + + pScreenRegion = RECTS_TO_REGION(pScreen, 1, &Rect[2], 0); + if (pScreenRegion) { + if (!REGION_NAR(pScreenRegion)) { + REGION_SUBTRACT(pScreen, pRegion, pRegion, pScreenRegion); + + ret = xf86InitFBManagerRegion(pScreen, pRegion); + + if (ret && xf86GetVerbosity() >= Verbosity) { + int scrnIndex = pScrn->scrnIndex; + + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "Largest offscreen areas (with overlaps):\n"); + + if (Rect[2].width < Rect[0].width) { + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "\t%d x %d rectangle at %d,0\n", + Rect[0].width - Rect[2].width, + Rect[0].height, + Rect[2].width); + } + if (Rect[2].width < Rect[1].width) { + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "\t%d x %d rectangle at %d,0\n", + Rect[1].width - Rect[2].width, + Rect[0].height + Rect[1].height, + Rect[2].width); + } + if (Rect[2].height < Rect[0].height) { + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "\t%d x %d rectangle at 0,%d\n", + Rect[0].width, + Rect[0].height - Rect[2].height, + Rect[2].height); + } + if (Rect[1].height) { + xf86DrvMsgVerb(scrnIndex, X_INFO, Verbosity, + "\t%d x %d rectangle at 0,%d\n", + Rect[1].width, + Rect[0].height - Rect[2].height + + Rect[1].height, + Rect[2].height); + } + } + } + + REGION_DESTROY(pScreen, pScreenRegion); + } + } + + REGION_DESTROY(pScreen, pRegion); + } + + return ret; +} + +Bool +xf86InitFBManagerRegion( + ScreenPtr pScreen, + RegionPtr FullRegion +){ + FBManagerPtr offman; + + if(REGION_NIL(FullRegion)) + return FALSE; + + if(!xf86RegisterOffscreenManager(pScreen, &xf86FBManFuncs)) + return FALSE; + + offman = malloc(sizeof(FBManager)); + if(!offman) return FALSE; + + dixSetPrivate(&pScreen->devPrivates, xf86FBScreenKey, offman); + + offman->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86FBCloseScreen; + + offman->InitialBoxes = REGION_CREATE(pScreen, NULL, 1); + offman->FreeBoxes = REGION_CREATE(pScreen, NULL, 1); + + REGION_COPY(pScreen, offman->InitialBoxes, FullRegion); + REGION_COPY(pScreen, offman->FreeBoxes, FullRegion); + + offman->pScreen = pScreen; + offman->UsedAreas = NULL; + offman->LinearAreas = NULL; + offman->NumUsedAreas = 0; + offman->NumCallbacks = 0; + offman->FreeBoxesUpdateCallback = NULL; + offman->devPrivates = NULL; + + return TRUE; +} + +Bool +xf86InitFBManagerLinear( + ScreenPtr pScreen, + int offset, + int size +){ + FBManagerPtr offman; + FBLinearLinkPtr link; + FBLinearPtr linear; + + if (size <= 0) + return FALSE; + + /* we expect people to have called the Area setup first for pixmap cache */ + if (!dixLookupPrivate(&pScreen->devPrivates, xf86FBScreenKey)) + return FALSE; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + offman->LinearAreas = malloc(sizeof(FBLinearLink)); + if (!offman->LinearAreas) + return FALSE; + + link = offman->LinearAreas; + link->area = NULL; + link->next = NULL; + link->free = 1; + linear = &(link->linear); + linear->pScreen = pScreen; + linear->size = size; + linear->offset = offset; + linear->granularity = 0; + linear->MoveLinearCallback = NULL; + linear->RemoveLinearCallback = NULL; + linear->devPrivate.ptr = NULL; + + return TRUE; +} + + +/* This is an implementation specific function and should + disappear after the next release. People should use the + real linear functions instead */ + +FBAreaPtr +xf86AllocateLinearOffscreenArea ( + ScreenPtr pScreen, + int length, + int gran, + MoveAreaCallbackProcPtr moveCB, + RemoveAreaCallbackProcPtr removeCB, + pointer privData +){ + FBManagerFuncsPtr funcs; + FBManagerPtr offman; + BoxPtr extents; + int w, h; + + if(xf86FBManagerKey == NULL) + return NULL; + if(!(funcs = (FBManagerFuncsPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBManagerKey))) + return NULL; + + offman = (FBManagerPtr)dixLookupPrivate(&pScreen->devPrivates, + xf86FBScreenKey); + extents = REGION_EXTENTS(pScreen, offman->InitialBoxes); + w = extents->x2 - extents->x1; + + if (gran > 1) { + if (gran > w) + return NULL; + + if (w % gran) + length += gran - 1; + } + + if(length <= w) { /* special case */ + h = 1; + w = length; + } else { + h = (length + w - 1) / w; + } + + return (*funcs->AllocateOffscreenArea)( + pScreen, w, h, gran, moveCB, removeCB, privData); +} diff --git a/xorg-server/hw/xfree86/common/xf86pciBus.c b/xorg-server/hw/xfree86/common/xf86pciBus.c index ac018e739..b3164730c 100644 --- a/xorg-server/hw/xfree86/common/xf86pciBus.c +++ b/xorg-server/hw/xfree86/common/xf86pciBus.c @@ -1,423 +1,423 @@ -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* - * This file contains the interfaces to the bus-specific code - */ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include "os.h" -#include "Pci.h" -#include "xf86.h" -#include "xf86Priv.h" - -/* Bus-specific headers */ -#include "xf86Bus.h" - -#define XF86_OS_PRIVS -#include "xf86_OSproc.h" - - -/* Bus-specific globals */ -Bool pciSlotClaimed = FALSE; - -#define PCIINFOCLASSES(c) \ - ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \ - || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ - || ((((c) & 0x00ffff00) \ - == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \ - || ((((c) & 0x00ffff00) \ - == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) ) - -/* - * PCI classes that have messages printed always. The others are only - * have a message printed when the vendor/dev IDs are recognised. - */ -#define PCIALWAYSPRINTCLASSES(c) \ - ( (((c) & 0x00ffff00) \ - == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \ - || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ - || ((((c) & 0x00ffff00) \ - == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) ) - -#define IS_VGA(c) \ - (((c) & 0x00ffff00) \ - == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8))) - -void -xf86FormatPciBusNumber(int busnum, char *buffer) -{ - /* 'buffer' should be at least 8 characters long */ - if (busnum < 256) - sprintf(buffer, "%d", busnum); - else - sprintf(buffer, "%d@%d", busnum & 0x00ff, busnum >> 8); -} - -/* - * xf86Bus.c interface - */ - -void -xf86PciProbe(void) -{ - int i = 0, k; - int num = 0; - struct pci_device *info; - struct pci_device_iterator *iter; - struct pci_device ** xf86PciVideoInfo = NULL; - - - if (!xf86scanpci()) { - xf86PciVideoInfo = NULL; - return; - } - - iter = pci_slot_match_iterator_create(& xf86IsolateDevice); - while ((info = pci_device_next(iter)) != NULL) { - if (PCIINFOCLASSES(info->device_class)) { - num++; - xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo, - (sizeof(struct pci_device *) - * (num + 1))); - xf86PciVideoInfo[num] = NULL; - xf86PciVideoInfo[num - 1] = info; - - pci_device_probe(info); -#ifdef HAVE_PCI_DEVICE_IS_BOOT_VGA - if (pci_device_is_boot_vga(info)) { - primaryBus.type = BUS_PCI; - primaryBus.id.pci = info; - } -#endif - info->user_data = 0; - } - } - free(iter); - - /* If we haven't found a primary device try a different heuristic */ - if (primaryBus.type == BUS_NONE && num) { - for (i = 0; i < num; i++) { - uint16_t command; - - info = xf86PciVideoInfo[i]; - pci_device_cfg_read_u16(info, & command, 4); - - if ((command & PCI_CMD_MEM_ENABLE) - && ((num == 1) || IS_VGA(info->device_class))) { - if (primaryBus.type == BUS_NONE) { - primaryBus.type = BUS_PCI; - primaryBus.id.pci = info; - } else { - xf86Msg(X_NOTICE, - "More than one possible primary device found\n"); - primaryBus.type ^= (BusType)(-1); - } - } - } - } - - /* Print a summary of the video devices found */ - for (k = 0; k < num; k++) { - const char *vendorname = NULL, *chipname = NULL; - const char *prim = " "; - Bool memdone = FALSE, iodone = FALSE; - - - info = xf86PciVideoInfo[k]; - - vendorname = pci_device_get_vendor_name( info ); - chipname = pci_device_get_device_name( info ); - - if ((!vendorname || !chipname) && - !PCIALWAYSPRINTCLASSES(info->device_class)) - continue; - - if (xf86IsPrimaryPci(info)) - prim = "*"; - - xf86Msg(X_PROBED, "PCI:%s(%u:%u:%u:%u) %04x:%04x:%04x:%04x ", prim, - info->domain, info->bus, info->dev, info->func, - info->vendor_id, info->device_id, - info->subvendor_id, info->subdevice_id); - - if (vendorname) - xf86ErrorF("%s ", vendorname); - - if (chipname) - xf86ErrorF("%s ", chipname); - - xf86ErrorF("rev %d", info->revision); - - for (i = 0; i < 6; i++) { - struct pci_mem_region * r = & info->regions[i]; - - if ( r->size && ! r->is_IO ) { - if (!memdone) { - xf86ErrorF(", Mem @ "); - memdone = TRUE; - } else - xf86ErrorF(", "); - xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); - } - } - - for (i = 0; i < 6; i++) { - struct pci_mem_region * r = & info->regions[i]; - - if ( r->size && r->is_IO ) { - if (!iodone) { - xf86ErrorF(", I/O @ "); - iodone = TRUE; - } else - xf86ErrorF(", "); - xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); - } - } - - if ( info->rom_size ) { - xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld", (long)info->rom_size); - } - - xf86ErrorF("\n"); - } - xfree(xf86PciVideoInfo); -} - -/* - * If the slot requested is already in use, return -1. - * Otherwise, claim the slot for the screen requesting it. - */ - -int -xf86ClaimPciSlot(struct pci_device * d, DriverPtr drvp, - int chipset, GDevPtr dev, Bool active) -{ - EntityPtr p = NULL; - int num; - - if (xf86CheckPciSlot(d)) { - num = xf86AllocateEntity(); - p = xf86Entities[num]; - p->driver = drvp; - p->chipset = chipset; - p->bus.type = BUS_PCI; - p->bus.id.pci = d; - p->active = active; - p->inUse = FALSE; - if (dev) - xf86AddDevToEntity(num, dev); - pciSlotClaimed = TRUE; - - if (active) { - /* Map in this domain's I/O space */ - p->domainIO = xf86MapLegacyIO(d); - } - - return num; - } else - return -1; -} - -/* - * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim. - */ -void -xf86UnclaimPciSlot(struct pci_device *d) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) { - const EntityPtr p = xf86Entities[i]; - - if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { - /* Probably the slot should be deallocated? */ - p->bus.type = BUS_NONE; - return; - } - } -} - -/* - * Parse a BUS ID string, and return the PCI bus parameters if it was - * in the correct format for a PCI bus id. - */ - -Bool -xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func) -{ - /* - * The format is assumed to be "bus[@domain]:device[:func]", where domain, - * bus, device and func are decimal integers. domain and func may be - * omitted and assumed to be zero, although doing this isn't encouraged. - */ - - char *p, *s, *d; - const char *id; - int i; - - if (StringToBusType(busID, &id) != BUS_PCI) - return FALSE; - - s = xstrdup(id); - p = strtok(s, ":"); - if (p == NULL || *p == 0) { - xfree(s); - return FALSE; - } - d = strpbrk(p, "@"); - if (d != NULL) { - *(d++) = 0; - for (i = 0; d[i] != 0; i++) { - if (!isdigit(d[i])) { - xfree(s); - return FALSE; - } - } - } - for (i = 0; p[i] != 0; i++) { - if (!isdigit(p[i])) { - xfree(s); - return FALSE; - } - } - *bus = atoi(p); - if (d != NULL && *d != 0) - *bus += atoi(d) << 8; - p = strtok(NULL, ":"); - if (p == NULL || *p == 0) { - xfree(s); - return FALSE; - } - for (i = 0; p[i] != 0; i++) { - if (!isdigit(p[i])) { - xfree(s); - return FALSE; - } - } - *device = atoi(p); - *func = 0; - p = strtok(NULL, ":"); - if (p == NULL || *p == 0) { - xfree(s); - return TRUE; - } - for (i = 0; p[i] != 0; i++) { - if (!isdigit(p[i])) { - xfree(s); - return FALSE; - } - } - *func = atoi(p); - xfree(s); - return TRUE; -} - -/* - * Compare a BUS ID string with a PCI bus id. Return TRUE if they match. - */ - -Bool -xf86ComparePciBusString(const char *busID, int bus, int device, int func) -{ - int ibus, idevice, ifunc; - - if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) { - return bus == ibus && device == idevice && func == ifunc; - } else { - return FALSE; - } -} - -/* - * xf86IsPrimaryPci() -- return TRUE if primary device - * is PCI and bus, dev and func numbers match. - */ - -Bool -xf86IsPrimaryPci(struct pci_device *pPci) -{ - return ((primaryBus.type == BUS_PCI) && (pPci == primaryBus.id.pci)); -} - -/* - * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity. - */ -struct pci_device * -xf86GetPciInfoForEntity(int entityIndex) -{ - EntityPtr p; - - if (entityIndex >= xf86NumEntities) - return NULL; - - p = xf86Entities[entityIndex]; - return (p->bus.type == BUS_PCI) ? p->bus.id.pci : NULL; -} - -/* - * xf86CheckPciMemBase() checks that the memory base value matches one of the - * PCI base address register values for the given PCI device. - */ -Bool -xf86CheckPciMemBase( struct pci_device * pPci, memType base ) -{ - int i; - - for (i = 0; i < 6; i++) - if (base == pPci->regions[i].base_addr) - return TRUE; - return FALSE; -} - -/* - * Check if the slot requested is free. If it is already in use, return FALSE. - */ - -Bool -xf86CheckPciSlot(const struct pci_device *d) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) { - const EntityPtr p = xf86Entities[i]; - - if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { - return FALSE; - } - } - return TRUE; -} - - +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* + * This file contains the interfaces to the bus-specific code + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "os.h" +#include "Pci.h" +#include "xf86.h" +#include "xf86Priv.h" + +/* Bus-specific headers */ +#include "xf86Bus.h" + +#define XF86_OS_PRIVS +#include "xf86_OSproc.h" + + +/* Bus-specific globals */ +Bool pciSlotClaimed = FALSE; + +#define PCIINFOCLASSES(c) \ + ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16)) \ + || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ + || ((((c) & 0x00ffff00) \ + == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \ + || ((((c) & 0x00ffff00) \ + == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) ) + +/* + * PCI classes that have messages printed always. The others are only + * have a message printed when the vendor/dev IDs are recognised. + */ +#define PCIALWAYSPRINTCLASSES(c) \ + ( (((c) & 0x00ffff00) \ + == ((PCI_CLASS_PREHISTORIC << 16) | (PCI_SUBCLASS_PREHISTORIC_VGA << 8))) \ + || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16)) \ + || ((((c) & 0x00ffff00) \ + == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) ) + +#define IS_VGA(c) \ + (((c) & 0x00ffff00) \ + == ((PCI_CLASS_DISPLAY << 16) | (PCI_SUBCLASS_DISPLAY_VGA << 8))) + +void +xf86FormatPciBusNumber(int busnum, char *buffer) +{ + /* 'buffer' should be at least 8 characters long */ + if (busnum < 256) + sprintf(buffer, "%d", busnum); + else + sprintf(buffer, "%d@%d", busnum & 0x00ff, busnum >> 8); +} + +/* + * xf86Bus.c interface + */ + +void +xf86PciProbe(void) +{ + int i = 0, k; + int num = 0; + struct pci_device *info; + struct pci_device_iterator *iter; + struct pci_device ** xf86PciVideoInfo = NULL; + + + if (!xf86scanpci()) { + xf86PciVideoInfo = NULL; + return; + } + + iter = pci_slot_match_iterator_create(& xf86IsolateDevice); + while ((info = pci_device_next(iter)) != NULL) { + if (PCIINFOCLASSES(info->device_class)) { + num++; + xf86PciVideoInfo = xnfrealloc(xf86PciVideoInfo, + (sizeof(struct pci_device *) + * (num + 1))); + xf86PciVideoInfo[num] = NULL; + xf86PciVideoInfo[num - 1] = info; + + pci_device_probe(info); +#ifdef HAVE_PCI_DEVICE_IS_BOOT_VGA + if (pci_device_is_boot_vga(info)) { + primaryBus.type = BUS_PCI; + primaryBus.id.pci = info; + } +#endif + info->user_data = 0; + } + } + free(iter); + + /* If we haven't found a primary device try a different heuristic */ + if (primaryBus.type == BUS_NONE && num) { + for (i = 0; i < num; i++) { + uint16_t command; + + info = xf86PciVideoInfo[i]; + pci_device_cfg_read_u16(info, & command, 4); + + if ((command & PCI_CMD_MEM_ENABLE) + && ((num == 1) || IS_VGA(info->device_class))) { + if (primaryBus.type == BUS_NONE) { + primaryBus.type = BUS_PCI; + primaryBus.id.pci = info; + } else { + xf86Msg(X_NOTICE, + "More than one possible primary device found\n"); + primaryBus.type ^= (BusType)(-1); + } + } + } + } + + /* Print a summary of the video devices found */ + for (k = 0; k < num; k++) { + const char *vendorname = NULL, *chipname = NULL; + const char *prim = " "; + Bool memdone = FALSE, iodone = FALSE; + + + info = xf86PciVideoInfo[k]; + + vendorname = pci_device_get_vendor_name( info ); + chipname = pci_device_get_device_name( info ); + + if ((!vendorname || !chipname) && + !PCIALWAYSPRINTCLASSES(info->device_class)) + continue; + + if (xf86IsPrimaryPci(info)) + prim = "*"; + + xf86Msg(X_PROBED, "PCI:%s(%u:%u:%u:%u) %04x:%04x:%04x:%04x ", prim, + info->domain, info->bus, info->dev, info->func, + info->vendor_id, info->device_id, + info->subvendor_id, info->subdevice_id); + + if (vendorname) + xf86ErrorF("%s ", vendorname); + + if (chipname) + xf86ErrorF("%s ", chipname); + + xf86ErrorF("rev %d", info->revision); + + for (i = 0; i < 6; i++) { + struct pci_mem_region * r = & info->regions[i]; + + if ( r->size && ! r->is_IO ) { + if (!memdone) { + xf86ErrorF(", Mem @ "); + memdone = TRUE; + } else + xf86ErrorF(", "); + xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); + } + } + + for (i = 0; i < 6; i++) { + struct pci_mem_region * r = & info->regions[i]; + + if ( r->size && r->is_IO ) { + if (!iodone) { + xf86ErrorF(", I/O @ "); + iodone = TRUE; + } else + xf86ErrorF(", "); + xf86ErrorF("0x%08lx/%ld", (long)r->base_addr, (long)r->size); + } + } + + if ( info->rom_size ) { + xf86ErrorF(", BIOS @ 0x\?\?\?\?\?\?\?\?/%ld", (long)info->rom_size); + } + + xf86ErrorF("\n"); + } + free(xf86PciVideoInfo); +} + +/* + * If the slot requested is already in use, return -1. + * Otherwise, claim the slot for the screen requesting it. + */ + +int +xf86ClaimPciSlot(struct pci_device * d, DriverPtr drvp, + int chipset, GDevPtr dev, Bool active) +{ + EntityPtr p = NULL; + int num; + + if (xf86CheckPciSlot(d)) { + num = xf86AllocateEntity(); + p = xf86Entities[num]; + p->driver = drvp; + p->chipset = chipset; + p->bus.type = BUS_PCI; + p->bus.id.pci = d; + p->active = active; + p->inUse = FALSE; + if (dev) + xf86AddDevToEntity(num, dev); + pciSlotClaimed = TRUE; + + if (active) { + /* Map in this domain's I/O space */ + p->domainIO = xf86MapLegacyIO(d); + } + + return num; + } else + return -1; +} + +/* + * Unclaim PCI slot, e.g. if probing failed, so that a different driver can claim. + */ +void +xf86UnclaimPciSlot(struct pci_device *d) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) { + const EntityPtr p = xf86Entities[i]; + + if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { + /* Probably the slot should be deallocated? */ + p->bus.type = BUS_NONE; + return; + } + } +} + +/* + * Parse a BUS ID string, and return the PCI bus parameters if it was + * in the correct format for a PCI bus id. + */ + +Bool +xf86ParsePciBusString(const char *busID, int *bus, int *device, int *func) +{ + /* + * The format is assumed to be "bus[@domain]:device[:func]", where domain, + * bus, device and func are decimal integers. domain and func may be + * omitted and assumed to be zero, although doing this isn't encouraged. + */ + + char *p, *s, *d; + const char *id; + int i; + + if (StringToBusType(busID, &id) != BUS_PCI) + return FALSE; + + s = xstrdup(id); + p = strtok(s, ":"); + if (p == NULL || *p == 0) { + free(s); + return FALSE; + } + d = strpbrk(p, "@"); + if (d != NULL) { + *(d++) = 0; + for (i = 0; d[i] != 0; i++) { + if (!isdigit(d[i])) { + free(s); + return FALSE; + } + } + } + for (i = 0; p[i] != 0; i++) { + if (!isdigit(p[i])) { + free(s); + return FALSE; + } + } + *bus = atoi(p); + if (d != NULL && *d != 0) + *bus += atoi(d) << 8; + p = strtok(NULL, ":"); + if (p == NULL || *p == 0) { + free(s); + return FALSE; + } + for (i = 0; p[i] != 0; i++) { + if (!isdigit(p[i])) { + free(s); + return FALSE; + } + } + *device = atoi(p); + *func = 0; + p = strtok(NULL, ":"); + if (p == NULL || *p == 0) { + free(s); + return TRUE; + } + for (i = 0; p[i] != 0; i++) { + if (!isdigit(p[i])) { + free(s); + return FALSE; + } + } + *func = atoi(p); + free(s); + return TRUE; +} + +/* + * Compare a BUS ID string with a PCI bus id. Return TRUE if they match. + */ + +Bool +xf86ComparePciBusString(const char *busID, int bus, int device, int func) +{ + int ibus, idevice, ifunc; + + if (xf86ParsePciBusString(busID, &ibus, &idevice, &ifunc)) { + return bus == ibus && device == idevice && func == ifunc; + } else { + return FALSE; + } +} + +/* + * xf86IsPrimaryPci() -- return TRUE if primary device + * is PCI and bus, dev and func numbers match. + */ + +Bool +xf86IsPrimaryPci(struct pci_device *pPci) +{ + return ((primaryBus.type == BUS_PCI) && (pPci == primaryBus.id.pci)); +} + +/* + * xf86GetPciInfoForEntity() -- Get the pciVideoRec of entity. + */ +struct pci_device * +xf86GetPciInfoForEntity(int entityIndex) +{ + EntityPtr p; + + if (entityIndex >= xf86NumEntities) + return NULL; + + p = xf86Entities[entityIndex]; + return (p->bus.type == BUS_PCI) ? p->bus.id.pci : NULL; +} + +/* + * xf86CheckPciMemBase() checks that the memory base value matches one of the + * PCI base address register values for the given PCI device. + */ +Bool +xf86CheckPciMemBase( struct pci_device * pPci, memType base ) +{ + int i; + + for (i = 0; i < 6; i++) + if (base == pPci->regions[i].base_addr) + return TRUE; + return FALSE; +} + +/* + * Check if the slot requested is free. If it is already in use, return FALSE. + */ + +Bool +xf86CheckPciSlot(const struct pci_device *d) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) { + const EntityPtr p = xf86Entities[i]; + + if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { + return FALSE; + } + } + return TRUE; +} + + diff --git a/xorg-server/hw/xfree86/common/xf86sbusBus.c b/xorg-server/hw/xfree86/common/xf86sbusBus.c index 7b23233aa..8df3a6c7a 100644 --- a/xorg-server/hw/xfree86/common/xf86sbusBus.c +++ b/xorg-server/hw/xfree86/common/xf86sbusBus.c @@ -1,688 +1,688 @@ -/* - * SBUS bus-specific code. - * - * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include "os.h" -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86cmap.h" - -#include "xf86Bus.h" - -#include "xf86sbusBus.h" -#include "xf86Sbus.h" - -Bool sbusSlotClaimed = FALSE; - -static int xf86nSbusInfo; - -static void -CheckSbusDevice(const char *device, int fbNum) -{ - int fd, i; - struct fbgattr fbattr; - sbusDevicePtr psdp; - - fd = open(device, O_RDONLY, 0); - if (fd < 0) - return; - memset(&fbattr, 0, sizeof(fbattr)); - if (ioctl(fd, FBIOGATTR, &fbattr) < 0) { - if (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0) { - close(fd); - return; - } - } - close(fd); - for (i = 0; sbusDeviceTable[i].devId; i++) - if (sbusDeviceTable[i].fbType == fbattr.fbtype.fb_type) - break; - if (! sbusDeviceTable[i].devId) - return; - xf86SbusInfo = xnfrealloc(xf86SbusInfo, sizeof(psdp) * (++xf86nSbusInfo + 1)); - xf86SbusInfo[xf86nSbusInfo] = NULL; - xf86SbusInfo[xf86nSbusInfo - 1] = psdp = xnfcalloc(sizeof (sbusDevice), 1); - psdp->devId = sbusDeviceTable[i].devId; - psdp->fbNum = fbNum; - psdp->device = xnfstrdup(device); - psdp->width = fbattr.fbtype.fb_width; - psdp->height = fbattr.fbtype.fb_height; - psdp->fd = -1; -} - -void -xf86SbusProbe(void) -{ - int i, useProm = 0; - char fbDevName[32]; - sbusDevicePtr psdp, *psdpp; - - xf86SbusInfo = xalloc(sizeof(psdp)); - *xf86SbusInfo = NULL; - for (i = 0; i < 32; i++) { - sprintf(fbDevName, "/dev/fb%d", i); - CheckSbusDevice(fbDevName, i); - } - if (sparcPromInit() >= 0) { - useProm = 1; - sparcPromAssignNodes(); - } - for (psdpp = xf86SbusInfo; (psdp = *psdpp); psdpp++) { - for (i = 0; sbusDeviceTable[i].devId; i++) - if (sbusDeviceTable[i].devId == psdp->devId) - psdp->descr = sbusDeviceTable[i].descr; - /* - * If we can use PROM information and found the PROM node for this - * device, we can tell more about the card. - */ - if (useProm && psdp->node.node) { - char *prop, *promPath; - int len, chiprev, vmsize; - - switch (psdp->devId) { - case SBUS_DEVICE_MGX: - prop = sparcPromGetProperty(&psdp->node, "fb_size", &len); - if (prop && len == 4 && *(int *)prop == 0x400000) - psdp->descr = "Quantum 3D MGXplus with 4M VRAM"; - break; - case SBUS_DEVICE_CG6: - chiprev = 0; - vmsize = 0; - prop = sparcPromGetProperty(&psdp->node, "chiprev", &len); - if (prop && len == 4) - chiprev = *(int *)prop; - prop = sparcPromGetProperty(&psdp->node, "vmsize", &len); - if (prop && len == 4) - vmsize = *(int *)prop; - switch (chiprev) { - case 1: - case 2: - case 3: - case 4: - psdp->descr = "Sun Double width GX"; break; - case 5: - case 6: - case 7: - case 8: - case 9: - psdp->descr = "Sun Single width GX"; break; - case 11: - switch (vmsize) { - case 2: - psdp->descr = "Sun Turbo GX with 1M VSIMM"; break; - case 4: - psdp->descr = "Sun Turbo GX Plus"; break; - default: - psdp->descr = "Sun Turbo GX"; break; - } - } - break; - case SBUS_DEVICE_CG14: - prop = sparcPromGetProperty(&psdp->node, "reg", &len); - vmsize = 0; - if (prop && !(len % 12) && len > 0) - vmsize = *(int *)(prop + len - 4); - switch (vmsize) { - case 0x400000: - psdp->descr = "Sun SX with 4M VSIMM"; break; - case 0x800000: - psdp->descr = "Sun SX with 8M VSIMM"; break; - } - break; - case SBUS_DEVICE_LEO: - prop = sparcPromGetProperty(&psdp->node, "model", &len); - if (prop && len > 0 && !strstr(prop, "501-2503")) - psdp->descr = "Sun Turbo ZX"; - break; - case SBUS_DEVICE_TCX: - if (sparcPromGetBool(&psdp->node, "tcx-8-bit")) - psdp->descr = "Sun TCX (8bit)"; - else - psdp->descr = "Sun TCX (S24)"; - break; - case SBUS_DEVICE_FFB: - prop = sparcPromGetProperty(&psdp->node, "name", &len); - chiprev = 0; - prop = sparcPromGetProperty(&psdp->node, "board_type", &len); - if (prop && len == 4) - chiprev = *(int *)prop; - if (strstr (prop, "afb")) { - if (chiprev == 3) - psdp->descr = "Sun|Elite3D-M6 Horizontal"; - } else { - switch (chiprev) { - case 0x08: - psdp->descr = "Sun FFB 67MHz Creator"; break; - case 0x0b: - psdp->descr = "Sun FFB 67MHz Creator 3D"; break; - case 0x1b: - psdp->descr = "Sun FFB 75MHz Creator 3D"; break; - case 0x20: - case 0x28: - psdp->descr = "Sun FFB2 Vertical Creator"; break; - case 0x23: - case 0x2b: - psdp->descr = "Sun FFB2 Vertical Creator 3D"; break; - case 0x30: - psdp->descr = "Sun FFB2+ Vertical Creator"; break; - case 0x33: - psdp->descr = "Sun FFB2+ Vertical Creator 3D"; break; - case 0x40: - case 0x48: - psdp->descr = "Sun FFB2 Horizontal Creator"; break; - case 0x43: - case 0x4b: - psdp->descr = "Sun FFB2 Horizontal Creator 3D"; break; - } - } - break; - } - - xf86Msg(X_PROBED, "SBUS:(0x%08x) %s", psdp->node.node, psdp->descr); - promPath = sparcPromNode2Pathname (&psdp->node); - if (promPath) { - xf86ErrorF(" at %s", promPath); - xfree(promPath); - } - } else - xf86Msg(X_PROBED, "SBUS: %s", psdp->descr); - xf86ErrorF("\n"); - } - if (useProm) - sparcPromClose(); -} - -/* - * Parse a BUS ID string, and return the SBUS bus parameters if it was - * in the correct format for a SBUS bus id. - */ - -Bool -xf86ParseSbusBusString(const char *busID, int *fbNum) -{ - /* - * The format is assumed to be one of: - * "fbN", e.g. "fb1", which means the device corresponding to /dev/fbN - * "nameN", e.g. "cgsix0", which means Nth instance of card NAME - * "/prompath", e.g. "/sbus@0,10001000/cgsix@3,0" which is PROM pathname - * to the device. - */ - - const char *id; - int i, len; - - if (StringToBusType(busID, &id) != BUS_SBUS) - return FALSE; - - if (*id != '/') { - if (!strncmp (id, "fb", 2)) { - if (!isdigit(id[2])) - return FALSE; - *fbNum = atoi(id + 2); - return TRUE; - } else { - sbusDevicePtr *psdpp; - int devId; - - for (i = 0, len = 0; sbusDeviceTable[i].devId; i++) { - len = strlen(sbusDeviceTable[i].promName); - if (!strncmp (sbusDeviceTable[i].promName, id, len) - && isdigit(id[len])) - break; - } - devId = sbusDeviceTable[i].devId; - if (!devId) return FALSE; - i = atoi(id + len); - for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { - if ((*psdpp)->devId != devId) - continue; - if (!i) { - *fbNum = (*psdpp)->fbNum; - return TRUE; - } - i--; - } - } - return FALSE; - } - - if (sparcPromInit() >= 0) { - i = sparcPromPathname2Node(id); - sparcPromClose(); - if (i) { - sbusDevicePtr *psdpp; - for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { - if ((*psdpp)->node.node == i) { - *fbNum = (*psdpp)->fbNum; - return TRUE; - } - } - } - } - return FALSE; -} - -/* - * Compare a BUS ID string with a SBUS bus id. Return TRUE if they match. - */ - -Bool -xf86CompareSbusBusString(const char *busID, int fbNum) -{ - int iFbNum; - - if (xf86ParseSbusBusString(busID, &iFbNum)) { - return fbNum == iFbNum; - } else { - return FALSE; - } -} - -/* - * Check if the slot requested is free. If it is already in use, return FALSE. - */ - -Bool -xf86CheckSbusSlot(int fbNum) -{ - int i; - EntityPtr p; - - for (i = 0; i < xf86NumEntities; i++) { - p = xf86Entities[i]; - /* Check if this SBUS slot is taken */ - if (p->bus.type == BUS_SBUS && p->bus.id.sbus.fbNum == fbNum) - return FALSE; - } - - return TRUE; -} - -/* - * If the slot requested is already in use, return -1. - * Otherwise, claim the slot for the screen requesting it. - */ - -int -xf86ClaimSbusSlot(sbusDevicePtr psdp, DriverPtr drvp, - GDevPtr dev, Bool active) -{ - EntityPtr p = NULL; - - int num; - - if (xf86CheckSbusSlot(psdp->fbNum)) { - num = xf86AllocateEntity(); - p = xf86Entities[num]; - p->driver = drvp; - p->chipset = -1; - p->bus.type = BUS_SBUS; - xf86AddDevToEntity(num, dev); - p->bus.id.sbus.fbNum = psdp->fbNum; - p->active = active; - p->inUse = FALSE; - sbusSlotClaimed = TRUE; - return num; - } else - return -1; -} - -int -xf86MatchSbusInstances(const char *driverName, int sbusDevId, - GDevPtr *devList, int numDevs, DriverPtr drvp, - int **foundEntities) -{ - int i,j; - sbusDevicePtr psdp, *psdpp; - int numClaimedInstances = 0; - int allocatedInstances = 0; - int numFound = 0; - GDevPtr devBus = NULL; - GDevPtr dev = NULL; - int *retEntities = NULL; - int useProm = 0; - - struct Inst { - sbusDevicePtr sbus; - GDevPtr dev; - Bool claimed; /* BusID matches with a device section */ - } *instances = NULL; - - *foundEntities = NULL; - for (psdpp = xf86SbusInfo, psdp = *psdpp; psdp; psdp = *++psdpp) { - if (psdp->devId != sbusDevId) - continue; - if (psdp->fd == -2) - continue; - ++allocatedInstances; - instances = xnfrealloc(instances, - allocatedInstances * sizeof(struct Inst)); - instances[allocatedInstances - 1].sbus = psdp; - instances[allocatedInstances - 1].dev = NULL; - instances[allocatedInstances - 1].claimed = FALSE; - numFound++; - } - - /* - * This may be debatable, but if no SBUS devices with a matching vendor - * type is found, return zero now. It is probably not desirable to - * allow the config file to override this. - */ - if (allocatedInstances <= 0) { - xfree(instances); - return 0; - } - - if (sparcPromInit() >= 0) - useProm = 1; - - if (xf86DoConfigure && xf86DoConfigurePass1) { - GDevPtr pGDev; - int actualcards = 0; - for (i = 0; i < allocatedInstances; i++) { - actualcards++; - pGDev = xf86AddBusDeviceToConfigure(drvp->driverName, BUS_SBUS, - instances[i].sbus, -1); - if (pGDev) { - /* - * XF86Match???Instances() treat chipID and chipRev as - * overrides, so clobber them here. - */ - pGDev->chipID = pGDev->chipRev = -1; - } - } - xfree(instances); - if (useProm) - sparcPromClose(); - return actualcards; - } - - DebugF("%s instances found: %d\n", driverName, allocatedInstances); - - for (i = 0; i < allocatedInstances; i++) { - char *promPath = NULL; - - psdp = instances[i].sbus; - devBus = NULL; - dev = NULL; - if (useProm && psdp->node.node) - promPath = sparcPromNode2Pathname(&psdp->node); - - for (j = 0; j < numDevs; j++) { - if (devList[j]->busID && *devList[j]->busID) { - if (xf86CompareSbusBusString(devList[j]->busID, psdp->fbNum)) { - if (devBus) - xf86MsgVerb(X_WARNING,0, - "%s: More than one matching Device section for " - "instance (BusID: %s) found: %s\n", - driverName,devList[j]->identifier, - devList[j]->busID); - else - devBus = devList[j]; - } - } else { - if (!dev && !devBus) { - if (promPath) - xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:%s\n", - promPath); - else - xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:fb%d\n", - psdp->fbNum); - dev = devList[j]; - } else - xf86MsgVerb(X_WARNING, 0, - "%s: More than one matching Device section " - "found: %s\n", driverName, devList[j]->identifier); - } - } - if (devBus) dev = devBus; /* busID preferred */ - if (!dev && psdp->fd != -2) { - if (promPath) { - xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " - "for instance (BusID SBUS:%s) found\n", - driverName, promPath); - } else - xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " - "for instance (BusID SBUS:fb%d) found\n", - driverName, psdp->fbNum); - } else if (dev) { - numClaimedInstances++; - instances[i].claimed = TRUE; - instances[i].dev = dev; - } - if (promPath) - xfree(promPath); - } - - DebugF("%s instances found: %d\n", driverName, numClaimedInstances); - - /* - * Of the claimed instances, check that another driver hasn't already - * claimed its slot. - */ - numFound = 0; - for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { - if (!instances[i].claimed) - continue; - psdp = instances[i].sbus; - if (!xf86CheckSbusSlot(psdp->fbNum)) - continue; - - DebugF("%s: card at fb%d %08x is claimed by a Device section\n", - driverName, psdp->fbNum, psdp->node.node); - - /* Allocate an entry in the lists to be returned */ - numFound++; - retEntities = xnfrealloc(retEntities, numFound * sizeof(int)); - retEntities[numFound - 1] - = xf86ClaimSbusSlot(psdp, drvp, instances[i].dev,instances[i].dev->active ? - TRUE : FALSE); - } - xfree(instances); - if (numFound > 0) { - *foundEntities = retEntities; - } - - if (useProm) - sparcPromClose(); - - return numFound; -} - -/* - * xf86GetSbusInfoForEntity() -- Get the sbusDevicePtr of entity. - */ -sbusDevicePtr -xf86GetSbusInfoForEntity(int entityIndex) -{ - sbusDevicePtr *psdpp; - EntityPtr p = xf86Entities[entityIndex]; - - if (entityIndex >= xf86NumEntities - || p->bus.type != BUS_SBUS) return NULL; - - for (psdpp = xf86SbusInfo; *psdpp != NULL; psdpp++) { - if (p->bus.id.sbus.fbNum == (*psdpp)->fbNum) - return (*psdpp); - } - return NULL; -} - -int -xf86GetEntityForSbusInfo(sbusDevicePtr psdp) -{ - int i; - - for (i = 0; i < xf86NumEntities; i++) { - EntityPtr p = xf86Entities[i]; - if (p->bus.type != BUS_SBUS) continue; - - if (p->bus.id.sbus.fbNum == psdp->fbNum) - return i; - } - return -1; -} - -void -xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn, sbusDevicePtr psdp) -{ - DisplayModePtr mode; - - mode = xnfcalloc(sizeof(DisplayModeRec), 1); - mode->name = "current"; - mode->next = mode; - mode->prev = mode; - mode->type = M_T_BUILTIN; - mode->Clock = 100000000; - mode->HDisplay = psdp->width; - mode->HSyncStart = psdp->width; - mode->HSyncEnd = psdp->width; - mode->HTotal = psdp->width; - mode->VDisplay = psdp->height; - mode->VSyncStart = psdp->height; - mode->VSyncEnd = psdp->height; - mode->VTotal = psdp->height; - mode->SynthClock = mode->Clock; - mode->CrtcHDisplay = mode->HDisplay; - mode->CrtcHSyncStart = mode->HSyncStart; - mode->CrtcHSyncEnd = mode->HSyncEnd; - mode->CrtcHTotal = mode->HTotal; - mode->CrtcVDisplay = mode->VDisplay; - mode->CrtcVSyncStart = mode->VSyncStart; - mode->CrtcVSyncEnd = mode->VSyncEnd; - mode->CrtcVTotal = mode->VTotal; - mode->CrtcHAdjusted = FALSE; - mode->CrtcVAdjusted = FALSE; - pScrn->modes = mode; - pScrn->virtualX = psdp->width; - pScrn->virtualY = psdp->height; -} - -static sbusPaletteKeyIndex; -static DevPrivateKey sbusPaletteKey = &sbusPaletteKeyIndex; -typedef struct _sbusCmap { - sbusDevicePtr psdp; - CloseScreenProcPtr CloseScreen; - Bool origCmapValid; - unsigned char origRed[16]; - unsigned char origGreen[16]; - unsigned char origBlue[16]; -} sbusCmapRec, *sbusCmapPtr; - -#define SBUSCMAPPTR(pScreen) ((sbusCmapPtr) \ - dixLookupPrivate(&(pScreen)->devPrivates, sbusPaletteKey)) - -static void -xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, - LOCO *colors, VisualPtr pVisual) -{ - int i, index; - sbusCmapPtr cmap; - struct fbcmap fbcmap; - unsigned char *data = xalloc(numColors*3); - - cmap = SBUSCMAPPTR(pScrn->pScreen); - if (!cmap) return; - fbcmap.count = 0; - fbcmap.index = indices[0]; - fbcmap.red = data; - fbcmap.green = data + numColors; - fbcmap.blue = fbcmap.green + numColors; - for (i = 0; i < numColors; i++) { - index = indices[i]; - if (fbcmap.count && index != fbcmap.index + fbcmap.count) { - ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); - fbcmap.count = 0; - fbcmap.index = index; - } - fbcmap.red[fbcmap.count] = colors[index].red; - fbcmap.green[fbcmap.count] = colors[index].green; - fbcmap.blue[fbcmap.count++] = colors[index].blue; - } - ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); - xfree(data); -} - -static Bool -xf86SbusCmapCloseScreen(int i, ScreenPtr pScreen) -{ - sbusCmapPtr cmap; - struct fbcmap fbcmap; - - cmap = SBUSCMAPPTR(pScreen); - if (cmap->origCmapValid) { - fbcmap.index = 0; - fbcmap.count = 16; - fbcmap.red = cmap->origRed; - fbcmap.green = cmap->origGreen; - fbcmap.blue = cmap->origBlue; - ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); - } - pScreen->CloseScreen = cmap->CloseScreen; - xfree (cmap); - return (*pScreen->CloseScreen) (i, pScreen); -} - -Bool -xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp) -{ - sbusCmapPtr cmap; - struct fbcmap fbcmap; - unsigned char data[2]; - - cmap = xnfcalloc(1, sizeof(sbusCmapRec)); - dixSetPrivate(&pScreen->devPrivates, sbusPaletteKey, cmap); - cmap->psdp = psdp; - fbcmap.index = 0; - fbcmap.count = 16; - fbcmap.red = cmap->origRed; - fbcmap.green = cmap->origGreen; - fbcmap.blue = cmap->origBlue; - if (ioctl (psdp->fd, FBIOGETCMAP, &fbcmap) >= 0) - cmap->origCmapValid = TRUE; - fbcmap.index = 0; - fbcmap.count = 2; - fbcmap.red = data; - fbcmap.green = data; - fbcmap.blue = data; - if (pScreen->whitePixel == 0) { - data[0] = 255; - data[1] = 0; - } else { - data[0] = 0; - data[1] = 255; - } - ioctl (psdp->fd, FBIOPUTCMAP, &fbcmap); - cmap->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = xf86SbusCmapCloseScreen; - return xf86HandleColormaps(pScreen, 256, 8, - xf86SbusCmapLoadPalette, NULL, 0); -} +/* + * SBUS bus-specific code. + * + * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "os.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86cmap.h" + +#include "xf86Bus.h" + +#include "xf86sbusBus.h" +#include "xf86Sbus.h" + +Bool sbusSlotClaimed = FALSE; + +static int xf86nSbusInfo; + +static void +CheckSbusDevice(const char *device, int fbNum) +{ + int fd, i; + struct fbgattr fbattr; + sbusDevicePtr psdp; + + fd = open(device, O_RDONLY, 0); + if (fd < 0) + return; + memset(&fbattr, 0, sizeof(fbattr)); + if (ioctl(fd, FBIOGATTR, &fbattr) < 0) { + if (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0) { + close(fd); + return; + } + } + close(fd); + for (i = 0; sbusDeviceTable[i].devId; i++) + if (sbusDeviceTable[i].fbType == fbattr.fbtype.fb_type) + break; + if (! sbusDeviceTable[i].devId) + return; + xf86SbusInfo = xnfrealloc(xf86SbusInfo, sizeof(psdp) * (++xf86nSbusInfo + 1)); + xf86SbusInfo[xf86nSbusInfo] = NULL; + xf86SbusInfo[xf86nSbusInfo - 1] = psdp = xnfcalloc(sizeof (sbusDevice), 1); + psdp->devId = sbusDeviceTable[i].devId; + psdp->fbNum = fbNum; + psdp->device = xnfstrdup(device); + psdp->width = fbattr.fbtype.fb_width; + psdp->height = fbattr.fbtype.fb_height; + psdp->fd = -1; +} + +void +xf86SbusProbe(void) +{ + int i, useProm = 0; + char fbDevName[32]; + sbusDevicePtr psdp, *psdpp; + + xf86SbusInfo = malloc(sizeof(psdp)); + *xf86SbusInfo = NULL; + for (i = 0; i < 32; i++) { + sprintf(fbDevName, "/dev/fb%d", i); + CheckSbusDevice(fbDevName, i); + } + if (sparcPromInit() >= 0) { + useProm = 1; + sparcPromAssignNodes(); + } + for (psdpp = xf86SbusInfo; (psdp = *psdpp); psdpp++) { + for (i = 0; sbusDeviceTable[i].devId; i++) + if (sbusDeviceTable[i].devId == psdp->devId) + psdp->descr = sbusDeviceTable[i].descr; + /* + * If we can use PROM information and found the PROM node for this + * device, we can tell more about the card. + */ + if (useProm && psdp->node.node) { + char *prop, *promPath; + int len, chiprev, vmsize; + + switch (psdp->devId) { + case SBUS_DEVICE_MGX: + prop = sparcPromGetProperty(&psdp->node, "fb_size", &len); + if (prop && len == 4 && *(int *)prop == 0x400000) + psdp->descr = "Quantum 3D MGXplus with 4M VRAM"; + break; + case SBUS_DEVICE_CG6: + chiprev = 0; + vmsize = 0; + prop = sparcPromGetProperty(&psdp->node, "chiprev", &len); + if (prop && len == 4) + chiprev = *(int *)prop; + prop = sparcPromGetProperty(&psdp->node, "vmsize", &len); + if (prop && len == 4) + vmsize = *(int *)prop; + switch (chiprev) { + case 1: + case 2: + case 3: + case 4: + psdp->descr = "Sun Double width GX"; break; + case 5: + case 6: + case 7: + case 8: + case 9: + psdp->descr = "Sun Single width GX"; break; + case 11: + switch (vmsize) { + case 2: + psdp->descr = "Sun Turbo GX with 1M VSIMM"; break; + case 4: + psdp->descr = "Sun Turbo GX Plus"; break; + default: + psdp->descr = "Sun Turbo GX"; break; + } + } + break; + case SBUS_DEVICE_CG14: + prop = sparcPromGetProperty(&psdp->node, "reg", &len); + vmsize = 0; + if (prop && !(len % 12) && len > 0) + vmsize = *(int *)(prop + len - 4); + switch (vmsize) { + case 0x400000: + psdp->descr = "Sun SX with 4M VSIMM"; break; + case 0x800000: + psdp->descr = "Sun SX with 8M VSIMM"; break; + } + break; + case SBUS_DEVICE_LEO: + prop = sparcPromGetProperty(&psdp->node, "model", &len); + if (prop && len > 0 && !strstr(prop, "501-2503")) + psdp->descr = "Sun Turbo ZX"; + break; + case SBUS_DEVICE_TCX: + if (sparcPromGetBool(&psdp->node, "tcx-8-bit")) + psdp->descr = "Sun TCX (8bit)"; + else + psdp->descr = "Sun TCX (S24)"; + break; + case SBUS_DEVICE_FFB: + prop = sparcPromGetProperty(&psdp->node, "name", &len); + chiprev = 0; + prop = sparcPromGetProperty(&psdp->node, "board_type", &len); + if (prop && len == 4) + chiprev = *(int *)prop; + if (strstr (prop, "afb")) { + if (chiprev == 3) + psdp->descr = "Sun|Elite3D-M6 Horizontal"; + } else { + switch (chiprev) { + case 0x08: + psdp->descr = "Sun FFB 67MHz Creator"; break; + case 0x0b: + psdp->descr = "Sun FFB 67MHz Creator 3D"; break; + case 0x1b: + psdp->descr = "Sun FFB 75MHz Creator 3D"; break; + case 0x20: + case 0x28: + psdp->descr = "Sun FFB2 Vertical Creator"; break; + case 0x23: + case 0x2b: + psdp->descr = "Sun FFB2 Vertical Creator 3D"; break; + case 0x30: + psdp->descr = "Sun FFB2+ Vertical Creator"; break; + case 0x33: + psdp->descr = "Sun FFB2+ Vertical Creator 3D"; break; + case 0x40: + case 0x48: + psdp->descr = "Sun FFB2 Horizontal Creator"; break; + case 0x43: + case 0x4b: + psdp->descr = "Sun FFB2 Horizontal Creator 3D"; break; + } + } + break; + } + + xf86Msg(X_PROBED, "SBUS:(0x%08x) %s", psdp->node.node, psdp->descr); + promPath = sparcPromNode2Pathname (&psdp->node); + if (promPath) { + xf86ErrorF(" at %s", promPath); + free(promPath); + } + } else + xf86Msg(X_PROBED, "SBUS: %s", psdp->descr); + xf86ErrorF("\n"); + } + if (useProm) + sparcPromClose(); +} + +/* + * Parse a BUS ID string, and return the SBUS bus parameters if it was + * in the correct format for a SBUS bus id. + */ + +Bool +xf86ParseSbusBusString(const char *busID, int *fbNum) +{ + /* + * The format is assumed to be one of: + * "fbN", e.g. "fb1", which means the device corresponding to /dev/fbN + * "nameN", e.g. "cgsix0", which means Nth instance of card NAME + * "/prompath", e.g. "/sbus@0,10001000/cgsix@3,0" which is PROM pathname + * to the device. + */ + + const char *id; + int i, len; + + if (StringToBusType(busID, &id) != BUS_SBUS) + return FALSE; + + if (*id != '/') { + if (!strncmp (id, "fb", 2)) { + if (!isdigit(id[2])) + return FALSE; + *fbNum = atoi(id + 2); + return TRUE; + } else { + sbusDevicePtr *psdpp; + int devId; + + for (i = 0, len = 0; sbusDeviceTable[i].devId; i++) { + len = strlen(sbusDeviceTable[i].promName); + if (!strncmp (sbusDeviceTable[i].promName, id, len) + && isdigit(id[len])) + break; + } + devId = sbusDeviceTable[i].devId; + if (!devId) return FALSE; + i = atoi(id + len); + for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { + if ((*psdpp)->devId != devId) + continue; + if (!i) { + *fbNum = (*psdpp)->fbNum; + return TRUE; + } + i--; + } + } + return FALSE; + } + + if (sparcPromInit() >= 0) { + i = sparcPromPathname2Node(id); + sparcPromClose(); + if (i) { + sbusDevicePtr *psdpp; + for (psdpp = xf86SbusInfo; *psdpp; ++psdpp) { + if ((*psdpp)->node.node == i) { + *fbNum = (*psdpp)->fbNum; + return TRUE; + } + } + } + } + return FALSE; +} + +/* + * Compare a BUS ID string with a SBUS bus id. Return TRUE if they match. + */ + +Bool +xf86CompareSbusBusString(const char *busID, int fbNum) +{ + int iFbNum; + + if (xf86ParseSbusBusString(busID, &iFbNum)) { + return fbNum == iFbNum; + } else { + return FALSE; + } +} + +/* + * Check if the slot requested is free. If it is already in use, return FALSE. + */ + +Bool +xf86CheckSbusSlot(int fbNum) +{ + int i; + EntityPtr p; + + for (i = 0; i < xf86NumEntities; i++) { + p = xf86Entities[i]; + /* Check if this SBUS slot is taken */ + if (p->bus.type == BUS_SBUS && p->bus.id.sbus.fbNum == fbNum) + return FALSE; + } + + return TRUE; +} + +/* + * If the slot requested is already in use, return -1. + * Otherwise, claim the slot for the screen requesting it. + */ + +int +xf86ClaimSbusSlot(sbusDevicePtr psdp, DriverPtr drvp, + GDevPtr dev, Bool active) +{ + EntityPtr p = NULL; + + int num; + + if (xf86CheckSbusSlot(psdp->fbNum)) { + num = xf86AllocateEntity(); + p = xf86Entities[num]; + p->driver = drvp; + p->chipset = -1; + p->bus.type = BUS_SBUS; + xf86AddDevToEntity(num, dev); + p->bus.id.sbus.fbNum = psdp->fbNum; + p->active = active; + p->inUse = FALSE; + sbusSlotClaimed = TRUE; + return num; + } else + return -1; +} + +int +xf86MatchSbusInstances(const char *driverName, int sbusDevId, + GDevPtr *devList, int numDevs, DriverPtr drvp, + int **foundEntities) +{ + int i,j; + sbusDevicePtr psdp, *psdpp; + int numClaimedInstances = 0; + int allocatedInstances = 0; + int numFound = 0; + GDevPtr devBus = NULL; + GDevPtr dev = NULL; + int *retEntities = NULL; + int useProm = 0; + + struct Inst { + sbusDevicePtr sbus; + GDevPtr dev; + Bool claimed; /* BusID matches with a device section */ + } *instances = NULL; + + *foundEntities = NULL; + for (psdpp = xf86SbusInfo, psdp = *psdpp; psdp; psdp = *++psdpp) { + if (psdp->devId != sbusDevId) + continue; + if (psdp->fd == -2) + continue; + ++allocatedInstances; + instances = xnfrealloc(instances, + allocatedInstances * sizeof(struct Inst)); + instances[allocatedInstances - 1].sbus = psdp; + instances[allocatedInstances - 1].dev = NULL; + instances[allocatedInstances - 1].claimed = FALSE; + numFound++; + } + + /* + * This may be debatable, but if no SBUS devices with a matching vendor + * type is found, return zero now. It is probably not desirable to + * allow the config file to override this. + */ + if (allocatedInstances <= 0) { + free(instances); + return 0; + } + + if (sparcPromInit() >= 0) + useProm = 1; + + if (xf86DoConfigure && xf86DoConfigurePass1) { + GDevPtr pGDev; + int actualcards = 0; + for (i = 0; i < allocatedInstances; i++) { + actualcards++; + pGDev = xf86AddBusDeviceToConfigure(drvp->driverName, BUS_SBUS, + instances[i].sbus, -1); + if (pGDev) { + /* + * XF86Match???Instances() treat chipID and chipRev as + * overrides, so clobber them here. + */ + pGDev->chipID = pGDev->chipRev = -1; + } + } + free(instances); + if (useProm) + sparcPromClose(); + return actualcards; + } + + DebugF("%s instances found: %d\n", driverName, allocatedInstances); + + for (i = 0; i < allocatedInstances; i++) { + char *promPath = NULL; + + psdp = instances[i].sbus; + devBus = NULL; + dev = NULL; + if (useProm && psdp->node.node) + promPath = sparcPromNode2Pathname(&psdp->node); + + for (j = 0; j < numDevs; j++) { + if (devList[j]->busID && *devList[j]->busID) { + if (xf86CompareSbusBusString(devList[j]->busID, psdp->fbNum)) { + if (devBus) + xf86MsgVerb(X_WARNING,0, + "%s: More than one matching Device section for " + "instance (BusID: %s) found: %s\n", + driverName,devList[j]->identifier, + devList[j]->busID); + else + devBus = devList[j]; + } + } else { + if (!dev && !devBus) { + if (promPath) + xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:%s\n", + promPath); + else + xf86Msg(X_PROBED, "Assigning device section with no busID to SBUS:fb%d\n", + psdp->fbNum); + dev = devList[j]; + } else + xf86MsgVerb(X_WARNING, 0, + "%s: More than one matching Device section " + "found: %s\n", driverName, devList[j]->identifier); + } + } + if (devBus) dev = devBus; /* busID preferred */ + if (!dev && psdp->fd != -2) { + if (promPath) { + xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " + "for instance (BusID SBUS:%s) found\n", + driverName, promPath); + } else + xf86MsgVerb(X_WARNING, 0, "%s: No matching Device section " + "for instance (BusID SBUS:fb%d) found\n", + driverName, psdp->fbNum); + } else if (dev) { + numClaimedInstances++; + instances[i].claimed = TRUE; + instances[i].dev = dev; + } + if (promPath) + free(promPath); + } + + DebugF("%s instances found: %d\n", driverName, numClaimedInstances); + + /* + * Of the claimed instances, check that another driver hasn't already + * claimed its slot. + */ + numFound = 0; + for (i = 0; i < allocatedInstances && numClaimedInstances > 0; i++) { + if (!instances[i].claimed) + continue; + psdp = instances[i].sbus; + if (!xf86CheckSbusSlot(psdp->fbNum)) + continue; + + DebugF("%s: card at fb%d %08x is claimed by a Device section\n", + driverName, psdp->fbNum, psdp->node.node); + + /* Allocate an entry in the lists to be returned */ + numFound++; + retEntities = xnfrealloc(retEntities, numFound * sizeof(int)); + retEntities[numFound - 1] + = xf86ClaimSbusSlot(psdp, drvp, instances[i].dev,instances[i].dev->active ? + TRUE : FALSE); + } + free(instances); + if (numFound > 0) { + *foundEntities = retEntities; + } + + if (useProm) + sparcPromClose(); + + return numFound; +} + +/* + * xf86GetSbusInfoForEntity() -- Get the sbusDevicePtr of entity. + */ +sbusDevicePtr +xf86GetSbusInfoForEntity(int entityIndex) +{ + sbusDevicePtr *psdpp; + EntityPtr p = xf86Entities[entityIndex]; + + if (entityIndex >= xf86NumEntities + || p->bus.type != BUS_SBUS) return NULL; + + for (psdpp = xf86SbusInfo; *psdpp != NULL; psdpp++) { + if (p->bus.id.sbus.fbNum == (*psdpp)->fbNum) + return (*psdpp); + } + return NULL; +} + +int +xf86GetEntityForSbusInfo(sbusDevicePtr psdp) +{ + int i; + + for (i = 0; i < xf86NumEntities; i++) { + EntityPtr p = xf86Entities[i]; + if (p->bus.type != BUS_SBUS) continue; + + if (p->bus.id.sbus.fbNum == psdp->fbNum) + return i; + } + return -1; +} + +void +xf86SbusUseBuiltinMode(ScrnInfoPtr pScrn, sbusDevicePtr psdp) +{ + DisplayModePtr mode; + + mode = xnfcalloc(sizeof(DisplayModeRec), 1); + mode->name = "current"; + mode->next = mode; + mode->prev = mode; + mode->type = M_T_BUILTIN; + mode->Clock = 100000000; + mode->HDisplay = psdp->width; + mode->HSyncStart = psdp->width; + mode->HSyncEnd = psdp->width; + mode->HTotal = psdp->width; + mode->VDisplay = psdp->height; + mode->VSyncStart = psdp->height; + mode->VSyncEnd = psdp->height; + mode->VTotal = psdp->height; + mode->SynthClock = mode->Clock; + mode->CrtcHDisplay = mode->HDisplay; + mode->CrtcHSyncStart = mode->HSyncStart; + mode->CrtcHSyncEnd = mode->HSyncEnd; + mode->CrtcHTotal = mode->HTotal; + mode->CrtcVDisplay = mode->VDisplay; + mode->CrtcVSyncStart = mode->VSyncStart; + mode->CrtcVSyncEnd = mode->VSyncEnd; + mode->CrtcVTotal = mode->VTotal; + mode->CrtcHAdjusted = FALSE; + mode->CrtcVAdjusted = FALSE; + pScrn->modes = mode; + pScrn->virtualX = psdp->width; + pScrn->virtualY = psdp->height; +} + +static sbusPaletteKeyIndex; +static DevPrivateKey sbusPaletteKey = &sbusPaletteKeyIndex; +typedef struct _sbusCmap { + sbusDevicePtr psdp; + CloseScreenProcPtr CloseScreen; + Bool origCmapValid; + unsigned char origRed[16]; + unsigned char origGreen[16]; + unsigned char origBlue[16]; +} sbusCmapRec, *sbusCmapPtr; + +#define SBUSCMAPPTR(pScreen) ((sbusCmapPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, sbusPaletteKey)) + +static void +xf86SbusCmapLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO *colors, VisualPtr pVisual) +{ + int i, index; + sbusCmapPtr cmap; + struct fbcmap fbcmap; + unsigned char *data = malloc(numColors*3); + + cmap = SBUSCMAPPTR(pScrn->pScreen); + if (!cmap) return; + fbcmap.count = 0; + fbcmap.index = indices[0]; + fbcmap.red = data; + fbcmap.green = data + numColors; + fbcmap.blue = fbcmap.green + numColors; + for (i = 0; i < numColors; i++) { + index = indices[i]; + if (fbcmap.count && index != fbcmap.index + fbcmap.count) { + ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); + fbcmap.count = 0; + fbcmap.index = index; + } + fbcmap.red[fbcmap.count] = colors[index].red; + fbcmap.green[fbcmap.count] = colors[index].green; + fbcmap.blue[fbcmap.count++] = colors[index].blue; + } + ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); + free(data); +} + +static Bool +xf86SbusCmapCloseScreen(int i, ScreenPtr pScreen) +{ + sbusCmapPtr cmap; + struct fbcmap fbcmap; + + cmap = SBUSCMAPPTR(pScreen); + if (cmap->origCmapValid) { + fbcmap.index = 0; + fbcmap.count = 16; + fbcmap.red = cmap->origRed; + fbcmap.green = cmap->origGreen; + fbcmap.blue = cmap->origBlue; + ioctl (cmap->psdp->fd, FBIOPUTCMAP, &fbcmap); + } + pScreen->CloseScreen = cmap->CloseScreen; + free(cmap); + return (*pScreen->CloseScreen) (i, pScreen); +} + +Bool +xf86SbusHandleColormaps(ScreenPtr pScreen, sbusDevicePtr psdp) +{ + sbusCmapPtr cmap; + struct fbcmap fbcmap; + unsigned char data[2]; + + cmap = xnfcalloc(1, sizeof(sbusCmapRec)); + dixSetPrivate(&pScreen->devPrivates, sbusPaletteKey, cmap); + cmap->psdp = psdp; + fbcmap.index = 0; + fbcmap.count = 16; + fbcmap.red = cmap->origRed; + fbcmap.green = cmap->origGreen; + fbcmap.blue = cmap->origBlue; + if (ioctl (psdp->fd, FBIOGETCMAP, &fbcmap) >= 0) + cmap->origCmapValid = TRUE; + fbcmap.index = 0; + fbcmap.count = 2; + fbcmap.red = data; + fbcmap.green = data; + fbcmap.blue = data; + if (pScreen->whitePixel == 0) { + data[0] = 255; + data[1] = 0; + } else { + data[0] = 0; + data[1] = 255; + } + ioctl (psdp->fd, FBIOPUTCMAP, &fbcmap); + cmap->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86SbusCmapCloseScreen; + return xf86HandleColormaps(pScreen, 256, 8, + xf86SbusCmapLoadPalette, NULL, 0); +} diff --git a/xorg-server/hw/xfree86/common/xf86xv.c b/xorg-server/hw/xfree86/common/xf86xv.c index 2cc2f6093..e35b8d667 100644 --- a/xorg-server/hw/xfree86/common/xf86xv.c +++ b/xorg-server/hw/xfree86/common/xf86xv.c @@ -1,2101 +1,2102 @@ -/* - * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com) - */ -/* - * Copyright (c) 1998-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include -#include "scrnintstr.h" -#include "regionstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "mivalidate.h" -#include "validate.h" -#include "resource.h" -#include "gcstruct.h" -#include "dixstruct.h" - -#include -#include -#include "xvdix.h" -#include "xvmodproc.h" - -#include "xf86xvpriv.h" - - -/* XvScreenRec fields */ - -static Bool xf86XVCloseScreen(int, ScreenPtr); -static int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *); - -/* XvAdaptorRec fields */ - -static int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*); -static int xf86XVFreePort(XvPortPtr); -static int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -static int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -static int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -static int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -static int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr); -static int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); -static int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); -static int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8, - CARD16, CARD16,CARD16, CARD16, - unsigned int*, unsigned int*); -static int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16, - XvImagePtr, unsigned char*, Bool, - CARD16, CARD16); -static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, - CARD16*, CARD16*, int*, int*); - - -/* ScreenRec fields */ - -static Bool xf86XVDestroyWindow(WindowPtr pWin); -static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2); -static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy); - -/* ScrnInfoRec functions */ - -static Bool xf86XVEnterVT(int, int); -static void xf86XVLeaveVT(int, int); -static void xf86XVAdjustFrame(int index, int x, int y, int flags); - -/* misc */ - -static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int); - - -static int XF86XVWindowKeyIndex; -static DevPrivateKey XF86XVWindowKey = &XF86XVWindowKeyIndex; -static int XF86XvScreenKeyIndex; -DevPrivateKey XF86XvScreenKey = &XF86XvScreenKeyIndex; -static unsigned long PortResource = 0; - -DevPrivateKey (*XvGetScreenKeyProc)(void) = NULL; -unsigned long (*XvGetRTPortProc)(void) = NULL; -int (*XvScreenInitProc)(ScreenPtr) = NULL; - -#define GET_XV_SCREEN(pScreen) \ - ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey)) - -#define GET_XF86XV_SCREEN(pScreen) \ - ((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr)) - -#define GET_XF86XV_WINDOW(pWin) \ - ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey)) - -static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL; -static int NumGenDrivers = 0; - -int -xf86XVRegisterGenericAdaptorDriver( - xf86XVInitGenericAdaptorPtr InitFunc -){ - xf86XVInitGenericAdaptorPtr *newdrivers; - - newdrivers = xrealloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) * - (1 + NumGenDrivers)); - if (!newdrivers) - return 0; - GenDrivers = newdrivers; - - GenDrivers[NumGenDrivers++] = InitFunc; - - return 1; -} - -int -xf86XVListGenericAdaptors( - ScrnInfoPtr pScrn, - XF86VideoAdaptorPtr **adaptors -){ - int i,j,n,num; - XF86VideoAdaptorPtr *DrivAdap,*new; - - num = 0; - *adaptors = NULL; - /* - * The v4l driver registers itself first, but can use surfaces registered - * by other drivers. So, call the v4l driver last. - */ - for (i = NumGenDrivers; --i >= 0; ) { - DrivAdap = NULL; - n = (*GenDrivers[i])(pScrn, &DrivAdap); - if (0 == n) - continue; - new = xrealloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n)); - if (NULL == new) - continue; - *adaptors = new; - for (j = 0; j < n; j++, num++) - (*adaptors)[num] = DrivAdap[j]; - } - return num; -} - - -/**************** Offscreen surface stuff *******************/ - -typedef struct { - XF86OffscreenImagePtr images; - int num; -} OffscreenImageRec; - -static int OffscreenPrivateKeyIndex; -static DevPrivateKey OffscreenPrivateKey = &OffscreenPrivateKeyIndex; -#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey)) - -Bool -xf86XVRegisterOffscreenImages( - ScreenPtr pScreen, - XF86OffscreenImagePtr images, - int num -){ - OffscreenImageRec *OffscreenImage; - /* This function may be called before xf86XVScreenInit, so there's - * no better place than this to call dixRequestPrivate to ensure we - * have space reserved. After the first call it is a no-op. */ - if(!dixRequestPrivate(OffscreenPrivateKey, sizeof(OffscreenImageRec)) || - !(OffscreenImage = GetOffscreenImage(pScreen))) - /* Every X.org driver assumes this function always succeeds, so - * just die on allocation failure. */ - FatalError("Could not allocate private storage for XV offscreen images.\n"); - - OffscreenImage->num = num; - OffscreenImage->images = images; - return TRUE; -} - -XF86OffscreenImagePtr -xf86XVQueryOffscreenImages( - ScreenPtr pScreen, - int *num -){ - OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen); - *num = OffscreenImage->num; - return OffscreenImage->images; -} - - -XF86VideoAdaptorPtr -xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn) -{ - return xcalloc(1, sizeof(XF86VideoAdaptorRec)); -} - -void -xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr) -{ - xfree(ptr); -} - - -Bool -xf86XVScreenInit( - ScreenPtr pScreen, - XF86VideoAdaptorPtr *adaptors, - int num -){ - ScrnInfoPtr pScrn; - XF86XVScreenPtr ScreenPriv; - XvScreenPtr pxvs; - - if(num <= 0 || - !XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc) - return FALSE; - - if(Success != (*XvScreenInitProc)(pScreen)) return FALSE; - - XF86XvScreenKey = (*XvGetScreenKeyProc)(); - PortResource = (*XvGetRTPortProc)(); - - pxvs = GET_XV_SCREEN(pScreen); - - /* Anyone initializing the Xv layer must provide these two. - The Xv di layer calls them without even checking if they exist! */ - - pxvs->ddCloseScreen = xf86XVCloseScreen; - pxvs->ddQueryAdaptors = xf86XVQueryAdaptors; - - /* The Xv di layer provides us with a private hook so that we don't - have to allocate our own screen private. They also provide - a CloseScreen hook so that we don't have to wrap it. I'm not - sure that I appreciate that. */ - - ScreenPriv = xalloc(sizeof(XF86XVScreenRec)); - pxvs->devPriv.ptr = (pointer)ScreenPriv; - - if(!ScreenPriv) return FALSE; - - pScrn = xf86Screens[pScreen->myNum]; - - ScreenPriv->videoGC = NULL; /* for the helper */ - - ScreenPriv->DestroyWindow = pScreen->DestroyWindow; - ScreenPriv->WindowExposures = pScreen->WindowExposures; - ScreenPriv->ClipNotify = pScreen->ClipNotify; - ScreenPriv->EnterVT = pScrn->EnterVT; - ScreenPriv->LeaveVT = pScrn->LeaveVT; - ScreenPriv->AdjustFrame = pScrn->AdjustFrame; - - pScreen->DestroyWindow = xf86XVDestroyWindow; - pScreen->WindowExposures = xf86XVWindowExposures; - pScreen->ClipNotify = xf86XVClipNotify; - pScrn->EnterVT = xf86XVEnterVT; - pScrn->LeaveVT = xf86XVLeaveVT; - if(pScrn->AdjustFrame) - pScrn->AdjustFrame = xf86XVAdjustFrame; - - if(!xf86XVInitAdaptors(pScreen, adaptors, num)) - return FALSE; - - return TRUE; -} - -static void -xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor) -{ - int i; - - xfree(pAdaptor->name); - - if(pAdaptor->pEncodings) { - XvEncodingPtr pEncode = pAdaptor->pEncodings; - - for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) - xfree(pEncode->name); - xfree(pAdaptor->pEncodings); - } - - xfree(pAdaptor->pFormats); - - if(pAdaptor->pPorts) { - XvPortPtr pPort = pAdaptor->pPorts; - XvPortRecPrivatePtr pPriv; - - for(i = 0; i < pAdaptor->nPorts; i++, pPort++) { - pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; - if(pPriv) { - if(pPriv->clientClip) - REGION_DESTROY(pAdaptor->pScreen, pPriv->clientClip); - if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) - REGION_DESTROY(pAdaptor->pScreen, pPriv->pCompositeClip); - xfree(pPriv); - } - } - xfree(pAdaptor->pPorts); - } - - if(pAdaptor->nAttributes) { - XvAttributePtr pAttribute = pAdaptor->pAttributes; - - for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) - xfree(pAttribute->name); - xfree(pAdaptor->pAttributes); - } - - xfree(pAdaptor->pImages); - xfree(pAdaptor->devPriv.ptr); -} - -static Bool -xf86XVInitAdaptors( - ScreenPtr pScreen, - XF86VideoAdaptorPtr *infoPtr, - int number -) { - XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XF86VideoAdaptorPtr adaptorPtr; - XvAdaptorPtr pAdaptor, pa; - XvAdaptorRecPrivatePtr adaptorPriv; - int na, numAdaptor; - XvPortRecPrivatePtr portPriv; - XvPortPtr pPort, pp; - int numPort; - XF86AttributePtr attributePtr; - XvAttributePtr pAttribute, pat; - XF86VideoFormatPtr formatPtr; - XvFormatPtr pFormat, pf; - int numFormat, totFormat; - XF86VideoEncodingPtr encodingPtr; - XvEncodingPtr pEncode, pe; - XF86ImagePtr imagePtr; - XvImagePtr pImage, pi; - int numVisuals; - VisualPtr pVisual; - int i; - - pxvs->nAdaptors = 0; - pxvs->pAdaptors = NULL; - - if(!(pAdaptor = xcalloc(number, sizeof(XvAdaptorRec)))) - return FALSE; - - for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) { - adaptorPtr = infoPtr[na]; - - if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute || - !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize) - continue; - - /* client libs expect at least one encoding */ - if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings) - continue; - - pa->type = adaptorPtr->type; - - if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo) - pa->type &= ~XvVideoMask; - - if(!adaptorPtr->PutStill && !adaptorPtr->GetStill) - pa->type &= ~XvStillMask; - - if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes) - pa->type &= ~XvImageMask; - - if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage && - !adaptorPtr->PutStill) - pa->type &= ~XvInputMask; - - if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill) - pa->type &= ~XvOutputMask; - - if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask))) - continue; - if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask))) - continue; - - pa->pScreen = pScreen; - pa->ddAllocatePort = xf86XVAllocatePort; - pa->ddFreePort = xf86XVFreePort; - pa->ddPutVideo = xf86XVPutVideo; - pa->ddPutStill = xf86XVPutStill; - pa->ddGetVideo = xf86XVGetVideo; - pa->ddGetStill = xf86XVGetStill; - pa->ddStopVideo = xf86XVStopVideo; - pa->ddPutImage = xf86XVPutImage; - pa->ddSetPortAttribute = xf86XVSetPortAttribute; - pa->ddGetPortAttribute = xf86XVGetPortAttribute; - pa->ddQueryBestSize = xf86XVQueryBestSize; - pa->ddQueryImageAttributes = xf86XVQueryImageAttributes; - if((pa->name = xalloc(strlen(adaptorPtr->name) + 1))) - strcpy(pa->name, adaptorPtr->name); - - if(adaptorPtr->nEncodings && - (pEncode = xcalloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) { - - for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0; - i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) - { - pe->id = encodingPtr->id; - pe->pScreen = pScreen; - if((pe->name = xalloc(strlen(encodingPtr->name) + 1))) - strcpy(pe->name, encodingPtr->name); - pe->width = encodingPtr->width; - pe->height = encodingPtr->height; - pe->rate.numerator = encodingPtr->rate.numerator; - pe->rate.denominator = encodingPtr->rate.denominator; - } - pa->nEncodings = adaptorPtr->nEncodings; - pa->pEncodings = pEncode; - } - - if(adaptorPtr->nImages && - (pImage = xcalloc(adaptorPtr->nImages, sizeof(XvImageRec)))) { - - for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages; - i < adaptorPtr->nImages; i++, pi++, imagePtr++) - { - pi->id = imagePtr->id; - pi->type = imagePtr->type; - pi->byte_order = imagePtr->byte_order; - memcpy(pi->guid, imagePtr->guid, 16); - pi->bits_per_pixel = imagePtr->bits_per_pixel; - pi->format = imagePtr->format; - pi->num_planes = imagePtr->num_planes; - pi->depth = imagePtr->depth; - pi->red_mask = imagePtr->red_mask; - pi->green_mask = imagePtr->green_mask; - pi->blue_mask = imagePtr->blue_mask; - pi->y_sample_bits = imagePtr->y_sample_bits; - pi->u_sample_bits = imagePtr->u_sample_bits; - pi->v_sample_bits = imagePtr->v_sample_bits; - pi->horz_y_period = imagePtr->horz_y_period; - pi->horz_u_period = imagePtr->horz_u_period; - pi->horz_v_period = imagePtr->horz_v_period; - pi->vert_y_period = imagePtr->vert_y_period; - pi->vert_u_period = imagePtr->vert_u_period; - pi->vert_v_period = imagePtr->vert_v_period; - memcpy(pi->component_order, imagePtr->component_order, 32); - pi->scanline_order = imagePtr->scanline_order; - } - pa->nImages = adaptorPtr->nImages; - pa->pImages = pImage; - } - - if(adaptorPtr->nAttributes && - (pAttribute = xcalloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) - { - for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0; - i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) - { - pat->flags = attributePtr->flags; - pat->min_value = attributePtr->min_value; - pat->max_value = attributePtr->max_value; - if((pat->name = xalloc(strlen(attributePtr->name) + 1))) - strcpy(pat->name, attributePtr->name); - } - pa->nAttributes = adaptorPtr->nAttributes; - pa->pAttributes = pAttribute; - } - - - totFormat = adaptorPtr->nFormats; - - if(!(pFormat = xcalloc(totFormat, sizeof(XvFormatRec)))) { - xf86XVFreeAdaptor(pa); - continue; - } - for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats; - i < adaptorPtr->nFormats; i++, formatPtr++) - { - numVisuals = pScreen->numVisuals; - pVisual = pScreen->visuals; - - while(numVisuals--) { - if((pVisual->class == formatPtr->class) && - (pVisual->nplanes == formatPtr->depth)) { - - if(numFormat >= totFormat) { - void *moreSpace; - totFormat *= 2; - moreSpace = xrealloc(pFormat, - totFormat * sizeof(XvFormatRec)); - if(!moreSpace) break; - pFormat = moreSpace; - pf = pFormat + numFormat; - } - - pf->visual = pVisual->vid; - pf->depth = formatPtr->depth; - - pf++; - numFormat++; - } - pVisual++; - } - } - pa->nFormats = numFormat; - pa->pFormats = pFormat; - if(!numFormat) { - xf86XVFreeAdaptor(pa); - continue; - } - - if(!(adaptorPriv = xcalloc(1, sizeof(XvAdaptorRecPrivate)))) { - xf86XVFreeAdaptor(pa); - continue; - } - - adaptorPriv->flags = adaptorPtr->flags; - adaptorPriv->PutVideo = adaptorPtr->PutVideo; - adaptorPriv->PutStill = adaptorPtr->PutStill; - adaptorPriv->GetVideo = adaptorPtr->GetVideo; - adaptorPriv->GetStill = adaptorPtr->GetStill; - adaptorPriv->StopVideo = adaptorPtr->StopVideo; - adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute; - adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute; - adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize; - adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes; - adaptorPriv->PutImage = adaptorPtr->PutImage; - adaptorPriv->ReputImage = adaptorPtr->ReputImage; - - pa->devPriv.ptr = (pointer)adaptorPriv; - - if(!(pPort = xcalloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) { - xf86XVFreeAdaptor(pa); - continue; - } - for(pp = pPort, i = 0, numPort = 0; - i < adaptorPtr->nPorts; i++) { - - if(!(pp->id = FakeClientID(0))) - continue; - - if(!(portPriv = xcalloc(1, sizeof(XvPortRecPrivate)))) - continue; - - if(!AddResource(pp->id, PortResource, pp)) { - xfree(portPriv); - continue; - } - - pp->pAdaptor = pa; - pp->pNotify = (XvPortNotifyPtr)NULL; - pp->pDraw = (DrawablePtr)NULL; - pp->client = (ClientPtr)NULL; - pp->grab.client = (ClientPtr)NULL; - pp->time = currentTime; - pp->devPriv.ptr = portPriv; - - portPriv->pScrn = pScrn; - portPriv->AdaptorRec = adaptorPriv; - portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; - - pp++; - numPort++; - } - pa->nPorts = numPort; - pa->pPorts = pPort; - if(!numPort) { - xf86XVFreeAdaptor(pa); - continue; - } - - pa->base_id = pPort->id; - - pa++; - numAdaptor++; - } - - if(numAdaptor) { - pxvs->nAdaptors = numAdaptor; - pxvs->pAdaptors = pAdaptor; - } else { - xfree(pAdaptor); - return FALSE; - } - - return TRUE; -} - -/* Video should be clipped to the intersection of the window cliplist - and the client cliplist specified in the GC for which the video was - initialized. When we need to reclip a window, the GC that started - the video may not even be around anymore. That's why we save the - client clip from the GC when the video is initialized. We then - use xf86XVUpdateCompositeClip to calculate the new composite clip - when we need it. This is different from what DEC did. They saved - the GC and used it's clip list when they needed to reclip the window, - even if the client clip was different from the one the video was - initialized with. If the original GC was destroyed, they had to stop - the video. I like the new method better (MArk). - - This function only works for windows. Will need to rewrite when - (if) we support pixmap rendering. -*/ - -static void -xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) -{ - RegionPtr pregWin, pCompositeClip; - WindowPtr pWin; - ScreenPtr pScreen; - Bool freeCompClip = FALSE; - - if(portPriv->pCompositeClip) - return; - - pWin = (WindowPtr)portPriv->pDraw; - pScreen = pWin->drawable.pScreen; - - /* get window clip list */ - if(portPriv->subWindowMode == IncludeInferiors) { - pregWin = NotClippedByChildren(pWin); - freeCompClip = TRUE; - } else - pregWin = &pWin->clipList; - - if(!portPriv->clientClip) { - portPriv->pCompositeClip = pregWin; - portPriv->FreeCompositeClip = freeCompClip; - return; - } - - pCompositeClip = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, pCompositeClip, portPriv->clientClip); - REGION_TRANSLATE(pScreen, pCompositeClip, - portPriv->pDraw->x + portPriv->clipOrg.x, - portPriv->pDraw->y + portPriv->clipOrg.y); - REGION_INTERSECT(pScreen, pCompositeClip, pregWin, pCompositeClip); - - portPriv->pCompositeClip = pCompositeClip; - portPriv->FreeCompositeClip = TRUE; - - if(freeCompClip) { - REGION_DESTROY(pScreen, pregWin); - } -} - -/* Save the current clientClip and update the CompositeClip whenever - we have a fresh GC */ - -static void -xf86XVCopyClip( - XvPortRecPrivatePtr portPriv, - GCPtr pGC -){ - /* copy the new clip if it exists */ - if((pGC->clientClipType == CT_REGION) && pGC->clientClip) { - if(!portPriv->clientClip) - portPriv->clientClip = REGION_CREATE(pScreen, NullBox, 1); - /* Note: this is in window coordinates */ - REGION_COPY(pScreen, portPriv->clientClip, pGC->clientClip); - } else if(portPriv->clientClip) { /* free the old clientClip */ - REGION_DESTROY(pScreen, portPriv->clientClip); - portPriv->clientClip = NULL; - } - - /* get rid of the old clip list */ - if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) { - REGION_DESTROY(pScreen, portPriv->pCompositeClip); - } - - portPriv->clipOrg = pGC->clipOrg; - portPriv->pCompositeClip = pGC->pCompositeClip; - portPriv->FreeCompositeClip = FALSE; - portPriv->subWindowMode = pGC->subWindowMode; -} - -static int -xf86XVRegetVideo(XvPortRecPrivatePtr portPriv) -{ - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - ScreenPtr pScreen; - int ret = Success; - Bool clippedAway = FALSE; - - pScreen = portPriv->pDraw->pScreen; - xf86XVUpdateCompositeClip(portPriv); - - /* translate the video region to the screen */ - WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; - WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; - WinBox.x2 = WinBox.x1 + portPriv->drw_w; - WinBox.y2 = WinBox.y1 + portPriv->drw_h; - - /* clip to the window composite clip */ - REGION_INIT(pScreen, &WinRegion, &WinBox, 1); - REGION_NULL(pScreen, &ClipRegion); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); - - /* that's all if it's totally obscured */ - if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { - clippedAway = TRUE; - goto CLIP_VIDEO_BAILOUT; - } - - if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { - REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); - } - - ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn, - portPriv->vid_x, portPriv->vid_y, - WinBox.x1, WinBox.y1, - portPriv->vid_w, portPriv->vid_h, - portPriv->drw_w, portPriv->drw_h, - &ClipRegion, portPriv->DevPriv.ptr, - portPriv->pDraw); - - if(ret == Success) - portPriv->isOn = XV_ON; - -CLIP_VIDEO_BAILOUT: - - if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - /* This clip was copied and only good for one shot */ - if(!portPriv->FreeCompositeClip) - portPriv->pCompositeClip = NULL; - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - - -static int -xf86XVReputVideo(XvPortRecPrivatePtr portPriv) -{ - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - ScreenPtr pScreen; - int ret = Success; - Bool clippedAway = FALSE; - - pScreen = portPriv->pDraw->pScreen; - - xf86XVUpdateCompositeClip(portPriv); - - /* translate the video region to the screen */ - WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; - WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; - WinBox.x2 = WinBox.x1 + portPriv->drw_w; - WinBox.y2 = WinBox.y1 + portPriv->drw_h; - - /* clip to the window composite clip */ - REGION_INIT(pScreen, &WinRegion, &WinBox, 1); - REGION_NULL(pScreen, &ClipRegion); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); - - /* clip and translate to the viewport */ - if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { - RegionRec VPReg; - BoxRec VPBox; - - VPBox.x1 = portPriv->pScrn->frameX0; - VPBox.y1 = portPriv->pScrn->frameY0; - VPBox.x2 = portPriv->pScrn->frameX1 + 1; - VPBox.y2 = portPriv->pScrn->frameY1 + 1; - - REGION_INIT(pScreen, &VPReg, &VPBox, 1); - REGION_INTERSECT(pScreen, &ClipRegion, &ClipRegion, &VPReg); - REGION_UNINIT(pScreen, &VPReg); - } - - /* that's all if it's totally obscured */ - if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { - clippedAway = TRUE; - goto CLIP_VIDEO_BAILOUT; - } - - /* bailout if we have to clip but the hardware doesn't support it */ - if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { - BoxPtr clipBox = REGION_RECTS(&ClipRegion); - if( (REGION_NUM_RECTS(&ClipRegion) != 1) || - (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || - (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) - { - clippedAway = TRUE; - goto CLIP_VIDEO_BAILOUT; - } - } - - if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { - REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); - } - - ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn, - portPriv->vid_x, portPriv->vid_y, - WinBox.x1, WinBox.y1, - portPriv->vid_w, portPriv->vid_h, - portPriv->drw_w, portPriv->drw_h, - &ClipRegion, portPriv->DevPriv.ptr, - portPriv->pDraw); - - if(ret == Success) portPriv->isOn = XV_ON; - -CLIP_VIDEO_BAILOUT: - - if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - /* This clip was copied and only good for one shot */ - if(!portPriv->FreeCompositeClip) - portPriv->pCompositeClip = NULL; - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - -static int -xf86XVReputImage(XvPortRecPrivatePtr portPriv) -{ - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - ScreenPtr pScreen; - int ret = Success; - Bool clippedAway = FALSE; - - pScreen = portPriv->pDraw->pScreen; - - xf86XVUpdateCompositeClip(portPriv); - - /* translate the video region to the screen */ - WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; - WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; - WinBox.x2 = WinBox.x1 + portPriv->drw_w; - WinBox.y2 = WinBox.y1 + portPriv->drw_h; - - /* clip to the window composite clip */ - REGION_INIT(pScreen, &WinRegion, &WinBox, 1); - REGION_NULL(pScreen, &ClipRegion); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); - - /* clip and translate to the viewport */ - if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { - RegionRec VPReg; - BoxRec VPBox; - - VPBox.x1 = portPriv->pScrn->frameX0; - VPBox.y1 = portPriv->pScrn->frameY0; - VPBox.x2 = portPriv->pScrn->frameX1 + 1; - VPBox.y2 = portPriv->pScrn->frameY1 + 1; - - REGION_INIT(pScreen, &VPReg, &VPBox, 1); - REGION_INTERSECT(pScreen, &ClipRegion, &ClipRegion, &VPReg); - REGION_UNINIT(pScreen, &VPReg); - } - - /* that's all if it's totally obscured */ - if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { - clippedAway = TRUE; - goto CLIP_VIDEO_BAILOUT; - } - - /* bailout if we have to clip but the hardware doesn't support it */ - if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { - BoxPtr clipBox = REGION_RECTS(&ClipRegion); - if( (REGION_NUM_RECTS(&ClipRegion) != 1) || - (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || - (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) - { - clippedAway = TRUE; - goto CLIP_VIDEO_BAILOUT; - } - } - - if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { - REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); - } - - ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn, - WinBox.x1, WinBox.y1, - &ClipRegion, portPriv->DevPriv.ptr, - portPriv->pDraw); - - portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; - -CLIP_VIDEO_BAILOUT: - - if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - /* This clip was copied and only good for one shot */ - if(!portPriv->FreeCompositeClip) - portPriv->pCompositeClip = NULL; - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - - -static int -xf86XVReputAllVideo(WindowPtr pWin, pointer data) -{ - XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); - - while(WinPriv) { - if(WinPriv->PortRec->type == XvInputMask) - xf86XVReputVideo(WinPriv->PortRec); - else - xf86XVRegetVideo(WinPriv->PortRec); - WinPriv = WinPriv->next; - } - - return WT_WALKCHILDREN; -} - -static int -xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) -{ - XF86XVWindowPtr winPriv, PrivRoot; - - winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin); - - /* Enlist our port in the window private */ - while(winPriv) { - if(winPriv->PortRec == portPriv) /* we're already listed */ - break; - winPriv = winPriv->next; - } - - if(!winPriv) { - winPriv = xcalloc(1, sizeof(XF86XVWindowRec)); - if(!winPriv) return BadAlloc; - winPriv->PortRec = portPriv; - winPriv->next = PrivRoot; - dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv); - } - - portPriv->pDraw = (DrawablePtr)pWin; - - return Success; -} - - -static void -xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) -{ - XF86XVWindowPtr winPriv, prevPriv = NULL; - - winPriv = GET_XF86XV_WINDOW(pWin); - - while(winPriv) { - if(winPriv->PortRec == portPriv) { - if(prevPriv) - prevPriv->next = winPriv->next; - else - dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, - winPriv->next); - xfree(winPriv); - break; - } - prevPriv = winPriv; - winPriv = winPriv->next; - } - portPriv->pDraw = NULL; -} - -/**** ScreenRec fields ****/ - -static Bool -xf86XVDestroyWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); - XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin); - int ret; - - while(WinPriv) { - XvPortRecPrivatePtr pPriv = WinPriv->PortRec; - - if(pPriv->isOn > XV_OFF) { - (*pPriv->AdaptorRec->StopVideo)( - pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); - pPriv->isOn = XV_OFF; - } - - pPriv->pDraw = NULL; - tmp = WinPriv; - if(WinPriv->pGC) { - FreeGC(WinPriv->pGC, 0); - } - WinPriv = WinPriv->next; - xfree(tmp); - } - - dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL); - - pScreen->DestroyWindow = ScreenPriv->DestroyWindow; - ret = (*pScreen->DestroyWindow)(pWin); - pScreen->DestroyWindow = xf86XVDestroyWindow; - - return ret; -} - - -static void -xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); - XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); - XF86XVWindowPtr pPrev; - XvPortRecPrivatePtr pPriv; - Bool AreasExposed; - - AreasExposed = (WinPriv && reg1 && REGION_NOTEMPTY(pScreen, reg1)); - - pScreen->WindowExposures = ScreenPriv->WindowExposures; - (*pScreen->WindowExposures)(pWin, reg1, reg2); - pScreen->WindowExposures = xf86XVWindowExposures; - - /* filter out XClearWindow/Area */ - if (!pWin->valdata) return; - - pPrev = NULL; - - while(WinPriv) { - pPriv = WinPriv->PortRec; - - /* Reput anyone with a reput function */ - - switch(pPriv->type) { - case XvInputMask: - xf86XVReputVideo(pPriv); - break; - case XvOutputMask: - xf86XVRegetVideo(pPriv); - break; - default: /* overlaid still/image*/ - if (pPriv->AdaptorRec->ReputImage) - xf86XVReputImage(pPriv); - else if(AreasExposed) { - XF86XVWindowPtr tmp; - - if (pPriv->isOn == XV_ON) { - (*pPriv->AdaptorRec->StopVideo)( - pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); - pPriv->isOn = XV_PENDING; - } - pPriv->pDraw = NULL; - - if(!pPrev) - dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, - WinPriv->next); - else - pPrev->next = WinPriv->next; - tmp = WinPriv; - WinPriv = WinPriv->next; - xfree(tmp); - continue; - } - break; - } - pPrev = WinPriv; - WinPriv = WinPriv->next; - } -} - - -static void -xf86XVClipNotify(WindowPtr pWin, int dx, int dy) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); - XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); - XF86XVWindowPtr tmp, pPrev = NULL; - XvPortRecPrivatePtr pPriv; - Bool visible = (pWin->visibility == VisibilityUnobscured) || - (pWin->visibility == VisibilityPartiallyObscured); - - while(WinPriv) { - pPriv = WinPriv->PortRec; - - if(!pPriv) goto next; - - if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) - REGION_DESTROY(pScreen, pPriv->pCompositeClip); - - pPriv->pCompositeClip = NULL; - - if (pPriv->AdaptorRec->ClipNotify) - (*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr, - pWin, dx, dy); - - /* Stop everything except images, but stop them too if the - window isn't visible. But we only remove the images. */ - - if(pPriv->type || !visible) { - if(pPriv->isOn == XV_ON) { - (*pPriv->AdaptorRec->StopVideo)( - pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); - pPriv->isOn = XV_PENDING; - } - - if(!pPriv->type) { /* overlaid still/image */ - pPriv->pDraw = NULL; - - if(!pPrev) - dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, - WinPriv->next); - else - pPrev->next = WinPriv->next; - tmp = WinPriv; - WinPriv = WinPriv->next; - xfree(tmp); - continue; - } - } - -next: - pPrev = WinPriv; - WinPriv = WinPriv->next; - } - - if(ScreenPriv->ClipNotify) { - pScreen->ClipNotify = ScreenPriv->ClipNotify; - (*pScreen->ClipNotify)(pWin, dx, dy); - pScreen->ClipNotify = xf86XVClipNotify; - } -} - - - -/**** Required XvScreenRec fields ****/ - -static Bool -xf86XVCloseScreen(int i, ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); - XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); - XvAdaptorPtr pa; - int c; - - if(!ScreenPriv) return TRUE; - - if(ScreenPriv->videoGC) { - FreeGC(ScreenPriv->videoGC, 0); - ScreenPriv->videoGC = NULL; - } - - pScreen->DestroyWindow = ScreenPriv->DestroyWindow; - pScreen->WindowExposures = ScreenPriv->WindowExposures; - pScreen->ClipNotify = ScreenPriv->ClipNotify; - - pScrn->EnterVT = ScreenPriv->EnterVT; - pScrn->LeaveVT = ScreenPriv->LeaveVT; - pScrn->AdjustFrame = ScreenPriv->AdjustFrame; - - for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { - xf86XVFreeAdaptor(pa); - } - - xfree(pxvs->pAdaptors); - xfree(ScreenPriv); - return TRUE; -} - - -static int -xf86XVQueryAdaptors( - ScreenPtr pScreen, - XvAdaptorPtr *p_pAdaptors, - int *p_nAdaptors -){ - XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); - - *p_nAdaptors = pxvs->nAdaptors; - *p_pAdaptors = pxvs->pAdaptors; - - return (Success); -} - - -/**** ScrnInfoRec fields ****/ - -static Bool -xf86XVEnterVT(int index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); - Bool ret; - - ret = (*ScreenPriv->EnterVT)(index, flags); - - if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0); - - return ret; -} - -static void -xf86XVLeaveVT(int index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); - XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); - XvAdaptorPtr pAdaptor; - XvPortPtr pPort; - XvPortRecPrivatePtr pPriv; - int i, j; - - for(i = 0; i < pxvs->nAdaptors; i++) { - pAdaptor = &pxvs->pAdaptors[i]; - for(j = 0; j < pAdaptor->nPorts; j++) { - pPort = &pAdaptor->pPorts[j]; - pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; - if(pPriv->isOn > XV_OFF) { - - (*pPriv->AdaptorRec->StopVideo)( - pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); - pPriv->isOn = XV_OFF; - - if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) - REGION_DESTROY(pScreen, pPriv->pCompositeClip); - - pPriv->pCompositeClip = NULL; - - if(!pPriv->type && pPriv->pDraw) { /* still */ - xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv); - } - } - } - } - - (*ScreenPriv->LeaveVT)(index, flags); -} - -static void -xf86XVAdjustFrame(int index, int x, int y, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[index]; - ScreenPtr pScreen = pScrn->pScreen; - XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); - XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); - WindowPtr pWin; - XvAdaptorPtr pa; - int c, i; - - if(ScreenPriv->AdjustFrame) { - pScrn->AdjustFrame = ScreenPriv->AdjustFrame; - (*pScrn->AdjustFrame)(index, x, y, flags); - pScrn->AdjustFrame = xf86XVAdjustFrame; - } - - for(c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) { - XvPortPtr pPort = pa->pPorts; - XvPortRecPrivatePtr pPriv; - - for(i = pa->nPorts; i > 0; i--, pPort++) { - pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; - - if(!pPriv->type && (pPriv->isOn != XV_OFF)) { /* overlaid still/image */ - - if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) - REGION_DESTROY(pScreen, pPriv->pCompositeClip); - - pPriv->pCompositeClip = NULL; - - pWin = (WindowPtr)pPriv->pDraw; - - if ((pPriv->AdaptorRec->ReputImage) && - ((pWin->visibility == VisibilityUnobscured) || - (pWin->visibility == VisibilityPartiallyObscured))) - { - xf86XVReputImage(pPriv); - } else if (pPriv->isOn == XV_ON) { - (*pPriv->AdaptorRec->StopVideo)( - pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); - xf86XVRemovePortFromWindow(pWin, pPriv); - pPriv->isOn = XV_PENDING; - continue; - } - } - } - } -} - - -/**** XvAdaptorRec fields ****/ - -static int -xf86XVAllocatePort( - unsigned long port, - XvPortPtr pPort, - XvPortPtr *ppPort -){ - *ppPort = pPort; - return Success; -} - - - -static int -xf86XVFreePort(XvPortPtr pPort) -{ - return Success; -} - - -static int -xf86XVPutVideo( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - int result; - - /* No dumping video to pixmaps... For now anyhow */ - if(pDraw->type != DRAWABLE_WINDOW) { - pPort->pDraw = (DrawablePtr)NULL; - return BadAlloc; - } - - /* If we are changing windows, unregister our port in the old window */ - if(portPriv->pDraw && (portPriv->pDraw != pDraw)) - xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); - - /* Register our port with the new window */ - result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); - if(result != Success) return result; - - portPriv->type = XvInputMask; - - /* save a copy of these parameters */ - portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; - portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; - portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; - portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; - - /* make sure we have the most recent copy of the clientClip */ - xf86XVCopyClip(portPriv, pGC); - - /* To indicate to the DI layer that we were successful */ - pPort->pDraw = pDraw; - - if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ - - return(xf86XVReputVideo(portPriv)); -} - -static int -xf86XVPutStill( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - ScreenPtr pScreen; - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - int ret = Success; - Bool clippedAway = FALSE; - - if (pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ - - pScreen = pDraw->pScreen; - - WinBox.x1 = pDraw->x + drw_x; - WinBox.y1 = pDraw->y + drw_y; - WinBox.x2 = WinBox.x1 + drw_w; - WinBox.y2 = WinBox.y1 + drw_h; - - REGION_INIT(pScreen, &WinRegion, &WinBox, 1); - REGION_NULL(pScreen, &ClipRegion); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); - - if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { - RegionRec VPReg; - BoxRec VPBox; - - VPBox.x1 = portPriv->pScrn->frameX0; - VPBox.y1 = portPriv->pScrn->frameY0; - VPBox.x2 = portPriv->pScrn->frameX1 + 1; - VPBox.y2 = portPriv->pScrn->frameY1 + 1; - - REGION_INIT(pScreen, &VPReg, &VPBox, 1); - REGION_INTERSECT(pScreen, &ClipRegion, &ClipRegion, &VPReg); - REGION_UNINIT(pScreen, &VPReg); - } - - if(portPriv->pDraw) { - xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); - } - - if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { - clippedAway = TRUE; - goto PUT_STILL_BAILOUT; - } - - if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { - BoxPtr clipBox = REGION_RECTS(&ClipRegion); - if( (REGION_NUM_RECTS(&ClipRegion) != 1) || - (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || - (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) - { - clippedAway = TRUE; - goto PUT_STILL_BAILOUT; - } - } - - if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { - REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); - } - - ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn, - vid_x, vid_y, WinBox.x1, WinBox.y1, - vid_w, vid_h, drw_w, drw_h, - &ClipRegion, portPriv->DevPriv.ptr, - pDraw); - - if((ret == Success) && - (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { - - xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); - portPriv->isOn = XV_ON; - portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; - portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; - portPriv->type = 0; /* no mask means it's transient and should - not be reput once it's removed */ - pPort->pDraw = pDraw; /* make sure we can get stop requests */ - } - -PUT_STILL_BAILOUT: - - if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - -static int -xf86XVGetVideo( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - int result; - - /* No pixmaps... For now anyhow */ - if(pDraw->type != DRAWABLE_WINDOW) { - pPort->pDraw = (DrawablePtr)NULL; - return BadAlloc; - } - - /* If we are changing windows, unregister our port in the old window */ - if(portPriv->pDraw && (portPriv->pDraw != pDraw)) - xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); - - /* Register our port with the new window */ - result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); - if(result != Success) return result; - - portPriv->type = XvOutputMask; - - /* save a copy of these parameters */ - portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; - portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; - portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; - portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; - - /* make sure we have the most recent copy of the clientClip */ - xf86XVCopyClip(portPriv, pGC); - - /* To indicate to the DI layer that we were successful */ - pPort->pDraw = pDraw; - - if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ - - return(xf86XVRegetVideo(portPriv)); -} - -static int -xf86XVGetStill( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - ScreenPtr pScreen; - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - int ret = Success; - Bool clippedAway = FALSE; - - if (pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ - - pScreen = pDraw->pScreen; - - WinBox.x1 = pDraw->x + drw_x; - WinBox.y1 = pDraw->y + drw_y; - WinBox.x2 = WinBox.x1 + drw_w; - WinBox.y2 = WinBox.y1 + drw_h; - - REGION_INIT(pScreen, &WinRegion, &WinBox, 1); - REGION_NULL(pScreen, &ClipRegion); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); - - if(portPriv->pDraw) { - xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); - } - - if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { - clippedAway = TRUE; - goto GET_STILL_BAILOUT; - } - - if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { - REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); - } - - ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn, - vid_x, vid_y, WinBox.x1, WinBox.y1, - vid_w, vid_h, drw_w, drw_h, - &ClipRegion, portPriv->DevPriv.ptr, - pDraw); - -GET_STILL_BAILOUT: - - if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - - - -static int -xf86XVStopVideo( - ClientPtr client, - XvPortPtr pPort, - DrawablePtr pDraw -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - - if(pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv); - - if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ - - /* Must free resources. */ - - if(portPriv->isOn > XV_OFF) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->pScrn, portPriv->DevPriv.ptr, TRUE); - portPriv->isOn = XV_OFF; - } - - return Success; -} - -static int -xf86XVSetPortAttribute( - ClientPtr client, - XvPortPtr pPort, - Atom attribute, - INT32 value -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - - return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn, - attribute, value, portPriv->DevPriv.ptr)); -} - - -static int -xf86XVGetPortAttribute( - ClientPtr client, - XvPortPtr pPort, - Atom attribute, - INT32 *p_value -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - - return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn, - attribute, p_value, portPriv->DevPriv.ptr)); -} - - - -static int -xf86XVQueryBestSize( - ClientPtr client, - XvPortPtr pPort, - CARD8 motion, - CARD16 vid_w, CARD16 vid_h, - CARD16 drw_w, CARD16 drw_h, - unsigned int *p_w, unsigned int *p_h -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - - (*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn, - (Bool)motion, vid_w, vid_h, drw_w, drw_h, - p_w, p_h, portPriv->DevPriv.ptr); - - return Success; -} - - -static int -xf86XVPutImage( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 src_x, INT16 src_y, - CARD16 src_w, CARD16 src_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h, - XvImagePtr format, - unsigned char* data, - Bool sync, - CARD16 width, CARD16 height -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - ScreenPtr pScreen; - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - int ret = Success; - Bool clippedAway = FALSE; - - if (pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ - - pScreen = pDraw->pScreen; - - WinBox.x1 = pDraw->x + drw_x; - WinBox.y1 = pDraw->y + drw_y; - WinBox.x2 = WinBox.x1 + drw_w; - WinBox.y2 = WinBox.y1 + drw_h; - - REGION_INIT(pScreen, &WinRegion, &WinBox, 1); - REGION_NULL(pScreen, &ClipRegion); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); - - if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { - RegionRec VPReg; - BoxRec VPBox; - - VPBox.x1 = portPriv->pScrn->frameX0; - VPBox.y1 = portPriv->pScrn->frameY0; - VPBox.x2 = portPriv->pScrn->frameX1 + 1; - VPBox.y2 = portPriv->pScrn->frameY1 + 1; - - REGION_INIT(pScreen, &VPReg, &VPBox, 1); - REGION_INTERSECT(pScreen, &ClipRegion, &ClipRegion, &VPReg); - REGION_UNINIT(pScreen, &VPReg); - } - - /* If we are changing windows, unregister our port in the old window */ - if(portPriv->pDraw && (portPriv->pDraw != pDraw)) - xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); - - /* Register our port with the new window */ - ret = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); - if(ret != Success) goto PUT_IMAGE_BAILOUT; - - if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { - clippedAway = TRUE; - goto PUT_IMAGE_BAILOUT; - } - - if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { - BoxPtr clipBox = REGION_RECTS(&ClipRegion); - if( (REGION_NUM_RECTS(&ClipRegion) != 1) || - (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || - (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) - { - clippedAway = TRUE; - goto PUT_IMAGE_BAILOUT; - } - } - - if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { - REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); - } - - ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn, - src_x, src_y, WinBox.x1, WinBox.y1, - src_w, src_h, drw_w, drw_h, format->id, data, width, height, - sync, &ClipRegion, portPriv->DevPriv.ptr, - pDraw); - - if((ret == Success) && - (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { - - portPriv->isOn = XV_ON; - portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; - portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; - portPriv->type = 0; /* no mask means it's transient and should - not be reput once it's removed */ - pPort->pDraw = pDraw; /* make sure we can get stop requests */ - } - -PUT_IMAGE_BAILOUT: - - if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - - -static int -xf86XVQueryImageAttributes( - ClientPtr client, - XvPortPtr pPort, - XvImagePtr format, - CARD16 *width, - CARD16 *height, - int *pitches, - int *offsets -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - - return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn, - format->id, width, height, pitches, offsets); -} - - -void -xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr clipboxes) -{ - ScreenPtr pScreen = pDraw->pScreen; - WindowPtr pWin = (WindowPtr)pDraw; - XF86XVWindowPtr pPriv = GET_XF86XV_WINDOW(pWin); - GCPtr pGC = NULL; - XID pval[2]; - BoxPtr pbox = REGION_RECTS(clipboxes); - int i, nbox = REGION_NUM_RECTS(clipboxes); - xRectangle *rects; - - if(!xf86Screens[pScreen->myNum]->vtSema) return; - - if(pPriv) - pGC = pPriv->pGC; - - if(!pGC) { - int status; - pval[0] = key; - pval[1] = IncludeInferiors; - pGC = CreateGC(pDraw, GCForeground | GCSubwindowMode, pval, &status, - (XID)0, serverClient); - if(!pGC) return; - ValidateGC(pDraw, pGC); - if (pPriv) pPriv->pGC = pGC; - } else if (key != pGC->fgPixel){ - pval[0] = key; - ChangeGC(pGC, GCForeground, pval); - ValidateGC(pDraw, pGC); - } - - REGION_TRANSLATE(pDraw->pScreen, clipboxes, -pDraw->x, -pDraw->y); - - rects = xalloc(nbox * sizeof(xRectangle)); - - for(i = 0; i < nbox; i++, pbox++) { - rects[i].x = pbox->x1; - rects[i].y = pbox->y1; - rects[i].width = pbox->x2 - pbox->x1; - rects[i].height = pbox->y2 - pbox->y1; - } - - (*pGC->ops->PolyFillRect)(pDraw, pGC, nbox, rects); - - if (!pPriv) FreeGC(pGC, 0); - - xfree(rects); -} - -void -xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes) -{ - DrawablePtr root = &WindowTable[pScreen->myNum]->drawable; - XID pval[2]; - BoxPtr pbox = REGION_RECTS(clipboxes); - int i, nbox = REGION_NUM_RECTS(clipboxes); - xRectangle *rects; - GCPtr gc; - - if(!xf86Screens[pScreen->myNum]->vtSema) return; - - gc = GetScratchGC(root->depth, pScreen); - pval[0] = key; - pval[1] = IncludeInferiors; - (void) ChangeGC(gc, GCForeground|GCSubwindowMode, pval); - ValidateGC(root, gc); - - rects = xalloc (nbox * sizeof(xRectangle)); - - for(i = 0; i < nbox; i++, pbox++) - { - rects[i].x = pbox->x1; - rects[i].y = pbox->y1; - rects[i].width = pbox->x2 - pbox->x1; - rects[i].height = pbox->y2 - pbox->y1; - } - - (*gc->ops->PolyFillRect)(root, gc, nbox, rects); - - xfree (rects); - FreeScratchGC (gc); -} - -/* xf86XVClipVideoHelper - - - Takes the dst box in standard X BoxRec form (top and left - edges inclusive, bottom and right exclusive). The new dst - box is returned. The source boundaries are given (x1, y1 - inclusive, x2, y2 exclusive) and returned are the new source - boundaries in 16.16 fixed point. -*/ - -#define DummyScreen screenInfo.screens[0] - -Bool -xf86XVClipVideoHelper( - BoxPtr dst, - INT32 *xa, - INT32 *xb, - INT32 *ya, - INT32 *yb, - RegionPtr reg, - INT32 width, - INT32 height -){ - double xsw, xdw, ysw, ydw; - INT32 delta; - BoxPtr extents = REGION_EXTENTS(DummyScreen, reg); - int diff; - - xsw = (*xb - *xa) << 16; - xdw = dst->x2 - dst->x1; - ysw = (*yb - *ya) << 16; - ydw = dst->y2 - dst->y1; - - *xa <<= 16; *xb <<= 16; - *ya <<= 16; *yb <<= 16; - - diff = extents->x1 - dst->x1; - if (diff > 0) { - dst->x1 = extents->x1; - *xa += (diff * xsw) / xdw; - } - diff = dst->x2 - extents->x2; - if (diff > 0) { - dst->x2 = extents->x2; - *xb -= (diff * xsw) / xdw; - } - diff = extents->y1 - dst->y1; - if (diff > 0) { - dst->y1 = extents->y1; - *ya += (diff * ysw) / ydw; - } - diff = dst->y2 - extents->y2; - if (diff > 0) { - dst->y2 = extents->y2; - *yb -= (diff * ysw) / ydw; - } - - if (*xa < 0) { - diff = (((-*xa) * xdw) + xsw - 1) / xsw; - dst->x1 += diff; - *xa += (diff * xsw) / xdw; - } - delta = *xb - (width << 16); - if (delta > 0) { - diff = ((delta * xdw) + xsw - 1) / xsw; - dst->x2 -= diff; - *xb -= (diff * xsw) / xdw; - } - if (*xa >= *xb) return FALSE; - - if (*ya < 0) { - diff = (((-*ya) * ydw) + ysw - 1) / ysw; - dst->y1 += diff; - *ya += (diff * ysw) / ydw; - } - delta = *yb - (height << 16); - if (delta > 0) { - diff = ((delta * ydw) + ysw - 1) / ysw; - dst->y2 -= diff; - *yb -= (diff * ysw) / ydw; - } - if (*ya >= *yb) return FALSE; - - if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) || - (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) - { - RegionRec clipReg; - REGION_INIT(DummyScreen, &clipReg, dst, 1); - REGION_INTERSECT(DummyScreen, reg, reg, &clipReg); - REGION_UNINIT(DummyScreen, &clipReg); - } - return TRUE; -} - -void -xf86XVCopyYUV12ToPacked( - const void *srcy, - const void *srcv, - const void *srcu, - void *dst, - int srcPitchy, - int srcPitchuv, - int dstPitch, - int h, - int w -){ - CARD32 *Dst; - const CARD8 *Y, *U, *V; - int i, j; - - w >>= 1; - - for (j = 0; j < h; j++) { - Dst = dst; - Y = srcy; V = srcv; U = srcu; - i = w; - while (i >= 4) { -#if X_BYTE_ORDER == X_LITTLE_ENDIAN - Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); - Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24); - Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24); - Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24); -#else - /* This assumes a little-endian framebuffer */ - Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; - Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1]; - Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2]; - Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3]; -#endif - Dst += 4; Y += 8; V += 4; U += 4; - i -= 4; - } - - while (i--) { -#if X_BYTE_ORDER == X_LITTLE_ENDIAN - Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); -#else - /* This assumes a little-endian framebuffer */ - Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; -#endif - Dst++; Y += 2; V++; U++; - } - - dst = (CARD8 *)dst + dstPitch; - srcy = (const CARD8 *)srcy + srcPitchy; - if (j & 1) { - srcu = (const CARD8 *)srcu + srcPitchuv; - srcv = (const CARD8 *)srcv + srcPitchuv; - } - } -} - -void -xf86XVCopyPacked( - const void *src, - void *dst, - int srcPitch, - int dstPitch, - int h, - int w -){ - const CARD32 *Src; - CARD32 *Dst; - int i; - - w >>= 1; - while (--h >= 0) { - do { - Dst = dst; Src = src; - i = w; - while (i >= 4) { - Dst[0] = Src[0]; - Dst[1] = Src[1]; - Dst[2] = Src[2]; - Dst[3] = Src[3]; - Dst += 4; Src += 4; i -= 4; - } - if (!i) break; - Dst[0] = Src[0]; - if (i == 1) break; - Dst[1] = Src[1]; - if (i == 2) break; - Dst[2] = Src[2]; - } while (0); - - src = (const CARD8 *)src + srcPitch; - dst = (CARD8 *)dst + dstPitch; - } -} +/* + * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com) + */ +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include +#include "scrnintstr.h" +#include "regionstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" +#include "validate.h" +#include "resource.h" +#include "gcstruct.h" +#include "dixstruct.h" + +#include +#include +#include "xvdix.h" +#include "xvmodproc.h" + +#include "xf86xvpriv.h" + + +/* XvScreenRec fields */ + +static Bool xf86XVCloseScreen(int, ScreenPtr); +static int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *); + +/* XvAdaptorRec fields */ + +static int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*); +static int xf86XVFreePort(XvPortPtr); +static int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr); +static int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); +static int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); +static int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8, + CARD16, CARD16,CARD16, CARD16, + unsigned int*, unsigned int*); +static int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char*, Bool, + CARD16, CARD16); +static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, + CARD16*, CARD16*, int*, int*); + + +/* ScreenRec fields */ + +static Bool xf86XVDestroyWindow(WindowPtr pWin); +static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2); +static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy); + +/* ScrnInfoRec functions */ + +static Bool xf86XVEnterVT(int, int); +static void xf86XVLeaveVT(int, int); +static void xf86XVAdjustFrame(int index, int x, int y, int flags); + +/* misc */ + +static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int); + + +static int XF86XVWindowKeyIndex; +static DevPrivateKey XF86XVWindowKey = &XF86XVWindowKeyIndex; +static int XF86XvScreenKeyIndex; +DevPrivateKey XF86XvScreenKey = &XF86XvScreenKeyIndex; +static unsigned long PortResource = 0; + +DevPrivateKey (*XvGetScreenKeyProc)(void) = NULL; +unsigned long (*XvGetRTPortProc)(void) = NULL; +int (*XvScreenInitProc)(ScreenPtr) = NULL; + +#define GET_XV_SCREEN(pScreen) \ + ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey)) + +#define GET_XF86XV_SCREEN(pScreen) \ + ((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr)) + +#define GET_XF86XV_WINDOW(pWin) \ + ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey)) + +static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL; +static int NumGenDrivers = 0; + +int +xf86XVRegisterGenericAdaptorDriver( + xf86XVInitGenericAdaptorPtr InitFunc +){ + xf86XVInitGenericAdaptorPtr *newdrivers; + + newdrivers = realloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) * + (1 + NumGenDrivers)); + if (!newdrivers) + return 0; + GenDrivers = newdrivers; + + GenDrivers[NumGenDrivers++] = InitFunc; + + return 1; +} + +int +xf86XVListGenericAdaptors( + ScrnInfoPtr pScrn, + XF86VideoAdaptorPtr **adaptors +){ + int i,j,n,num; + XF86VideoAdaptorPtr *DrivAdap,*new; + + num = 0; + *adaptors = NULL; + /* + * The v4l driver registers itself first, but can use surfaces registered + * by other drivers. So, call the v4l driver last. + */ + for (i = NumGenDrivers; --i >= 0; ) { + DrivAdap = NULL; + n = (*GenDrivers[i])(pScrn, &DrivAdap); + if (0 == n) + continue; + new = realloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n)); + if (NULL == new) + continue; + *adaptors = new; + for (j = 0; j < n; j++, num++) + (*adaptors)[num] = DrivAdap[j]; + } + return num; +} + + +/**************** Offscreen surface stuff *******************/ + +typedef struct { + XF86OffscreenImagePtr images; + int num; +} OffscreenImageRec; + +static int OffscreenPrivateKeyIndex; +static DevPrivateKey OffscreenPrivateKey = &OffscreenPrivateKeyIndex; +#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey)) + +Bool +xf86XVRegisterOffscreenImages( + ScreenPtr pScreen, + XF86OffscreenImagePtr images, + int num +){ + OffscreenImageRec *OffscreenImage; + /* This function may be called before xf86XVScreenInit, so there's + * no better place than this to call dixRequestPrivate to ensure we + * have space reserved. After the first call it is a no-op. */ + if(!dixRequestPrivate(OffscreenPrivateKey, sizeof(OffscreenImageRec)) || + !(OffscreenImage = GetOffscreenImage(pScreen))) + /* Every X.org driver assumes this function always succeeds, so + * just die on allocation failure. */ + FatalError("Could not allocate private storage for XV offscreen images.\n"); + + OffscreenImage->num = num; + OffscreenImage->images = images; + return TRUE; +} + +XF86OffscreenImagePtr +xf86XVQueryOffscreenImages( + ScreenPtr pScreen, + int *num +){ + OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen); + *num = OffscreenImage->num; + return OffscreenImage->images; +} + + +XF86VideoAdaptorPtr +xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn) +{ + return calloc(1, sizeof(XF86VideoAdaptorRec)); +} + +void +xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr) +{ + free(ptr); +} + + +Bool +xf86XVScreenInit( + ScreenPtr pScreen, + XF86VideoAdaptorPtr *adaptors, + int num +){ + ScrnInfoPtr pScrn; + XF86XVScreenPtr ScreenPriv; + XvScreenPtr pxvs; + + if(num <= 0 || + !XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc) + return FALSE; + + if(Success != (*XvScreenInitProc)(pScreen)) return FALSE; + + XF86XvScreenKey = (*XvGetScreenKeyProc)(); + PortResource = (*XvGetRTPortProc)(); + + pxvs = GET_XV_SCREEN(pScreen); + + /* Anyone initializing the Xv layer must provide these two. + The Xv di layer calls them without even checking if they exist! */ + + pxvs->ddCloseScreen = xf86XVCloseScreen; + pxvs->ddQueryAdaptors = xf86XVQueryAdaptors; + + /* The Xv di layer provides us with a private hook so that we don't + have to allocate our own screen private. They also provide + a CloseScreen hook so that we don't have to wrap it. I'm not + sure that I appreciate that. */ + + ScreenPriv = malloc(sizeof(XF86XVScreenRec)); + pxvs->devPriv.ptr = (pointer)ScreenPriv; + + if(!ScreenPriv) return FALSE; + + pScrn = xf86Screens[pScreen->myNum]; + + ScreenPriv->videoGC = NULL; /* for the helper */ + + ScreenPriv->DestroyWindow = pScreen->DestroyWindow; + ScreenPriv->WindowExposures = pScreen->WindowExposures; + ScreenPriv->ClipNotify = pScreen->ClipNotify; + ScreenPriv->EnterVT = pScrn->EnterVT; + ScreenPriv->LeaveVT = pScrn->LeaveVT; + ScreenPriv->AdjustFrame = pScrn->AdjustFrame; + + pScreen->DestroyWindow = xf86XVDestroyWindow; + pScreen->WindowExposures = xf86XVWindowExposures; + pScreen->ClipNotify = xf86XVClipNotify; + pScrn->EnterVT = xf86XVEnterVT; + pScrn->LeaveVT = xf86XVLeaveVT; + if(pScrn->AdjustFrame) + pScrn->AdjustFrame = xf86XVAdjustFrame; + + if(!xf86XVInitAdaptors(pScreen, adaptors, num)) + return FALSE; + + return TRUE; +} + +static void +xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor) +{ + int i; + + free(pAdaptor->name); + + if(pAdaptor->pEncodings) { + XvEncodingPtr pEncode = pAdaptor->pEncodings; + + for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) + free(pEncode->name); + free(pAdaptor->pEncodings); + } + + free(pAdaptor->pFormats); + + if(pAdaptor->pPorts) { + XvPortPtr pPort = pAdaptor->pPorts; + XvPortRecPrivatePtr pPriv; + + for(i = 0; i < pAdaptor->nPorts; i++, pPort++) { + pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + if(pPriv) { + if(pPriv->clientClip) + REGION_DESTROY(pAdaptor->pScreen, pPriv->clientClip); + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + REGION_DESTROY(pAdaptor->pScreen, pPriv->pCompositeClip); + free(pPriv); + } + } + free(pAdaptor->pPorts); + } + + if(pAdaptor->nAttributes) { + XvAttributePtr pAttribute = pAdaptor->pAttributes; + + for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) + free(pAttribute->name); + free(pAdaptor->pAttributes); + } + + free(pAdaptor->pImages); + free(pAdaptor->devPriv.ptr); +} + +static Bool +xf86XVInitAdaptors( + ScreenPtr pScreen, + XF86VideoAdaptorPtr *infoPtr, + int number +) { + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr adaptorPtr; + XvAdaptorPtr pAdaptor, pa; + XvAdaptorRecPrivatePtr adaptorPriv; + int na, numAdaptor; + XvPortRecPrivatePtr portPriv; + XvPortPtr pPort, pp; + int numPort; + XF86AttributePtr attributePtr; + XvAttributePtr pAttribute, pat; + XF86VideoFormatPtr formatPtr; + XvFormatPtr pFormat, pf; + int numFormat, totFormat; + XF86VideoEncodingPtr encodingPtr; + XvEncodingPtr pEncode, pe; + XF86ImagePtr imagePtr; + XvImagePtr pImage, pi; + int numVisuals; + VisualPtr pVisual; + int i; + + pxvs->nAdaptors = 0; + pxvs->pAdaptors = NULL; + + if(!(pAdaptor = calloc(number, sizeof(XvAdaptorRec)))) + return FALSE; + + for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) { + adaptorPtr = infoPtr[na]; + + if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute || + !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize) + continue; + + /* client libs expect at least one encoding */ + if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings) + continue; + + pa->type = adaptorPtr->type; + + if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo) + pa->type &= ~XvVideoMask; + + if(!adaptorPtr->PutStill && !adaptorPtr->GetStill) + pa->type &= ~XvStillMask; + + if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes) + pa->type &= ~XvImageMask; + + if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage && + !adaptorPtr->PutStill) + pa->type &= ~XvInputMask; + + if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill) + pa->type &= ~XvOutputMask; + + if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask))) + continue; + if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask))) + continue; + + pa->pScreen = pScreen; + pa->ddAllocatePort = xf86XVAllocatePort; + pa->ddFreePort = xf86XVFreePort; + pa->ddPutVideo = xf86XVPutVideo; + pa->ddPutStill = xf86XVPutStill; + pa->ddGetVideo = xf86XVGetVideo; + pa->ddGetStill = xf86XVGetStill; + pa->ddStopVideo = xf86XVStopVideo; + pa->ddPutImage = xf86XVPutImage; + pa->ddSetPortAttribute = xf86XVSetPortAttribute; + pa->ddGetPortAttribute = xf86XVGetPortAttribute; + pa->ddQueryBestSize = xf86XVQueryBestSize; + pa->ddQueryImageAttributes = xf86XVQueryImageAttributes; + if((pa->name = malloc(strlen(adaptorPtr->name) + 1))) + strcpy(pa->name, adaptorPtr->name); + + if(adaptorPtr->nEncodings && + (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) { + + for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0; + i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) + { + pe->id = encodingPtr->id; + pe->pScreen = pScreen; + if((pe->name = malloc(strlen(encodingPtr->name) + 1))) + strcpy(pe->name, encodingPtr->name); + pe->width = encodingPtr->width; + pe->height = encodingPtr->height; + pe->rate.numerator = encodingPtr->rate.numerator; + pe->rate.denominator = encodingPtr->rate.denominator; + } + pa->nEncodings = adaptorPtr->nEncodings; + pa->pEncodings = pEncode; + } + + if(adaptorPtr->nImages && + (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) { + + for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages; + i < adaptorPtr->nImages; i++, pi++, imagePtr++) + { + pi->id = imagePtr->id; + pi->type = imagePtr->type; + pi->byte_order = imagePtr->byte_order; + memcpy(pi->guid, imagePtr->guid, 16); + pi->bits_per_pixel = imagePtr->bits_per_pixel; + pi->format = imagePtr->format; + pi->num_planes = imagePtr->num_planes; + pi->depth = imagePtr->depth; + pi->red_mask = imagePtr->red_mask; + pi->green_mask = imagePtr->green_mask; + pi->blue_mask = imagePtr->blue_mask; + pi->y_sample_bits = imagePtr->y_sample_bits; + pi->u_sample_bits = imagePtr->u_sample_bits; + pi->v_sample_bits = imagePtr->v_sample_bits; + pi->horz_y_period = imagePtr->horz_y_period; + pi->horz_u_period = imagePtr->horz_u_period; + pi->horz_v_period = imagePtr->horz_v_period; + pi->vert_y_period = imagePtr->vert_y_period; + pi->vert_u_period = imagePtr->vert_u_period; + pi->vert_v_period = imagePtr->vert_v_period; + memcpy(pi->component_order, imagePtr->component_order, 32); + pi->scanline_order = imagePtr->scanline_order; + } + pa->nImages = adaptorPtr->nImages; + pa->pImages = pImage; + } + + if(adaptorPtr->nAttributes && + (pAttribute = calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) + { + for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0; + i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) + { + pat->flags = attributePtr->flags; + pat->min_value = attributePtr->min_value; + pat->max_value = attributePtr->max_value; + if((pat->name = malloc(strlen(attributePtr->name) + 1))) + strcpy(pat->name, attributePtr->name); + } + pa->nAttributes = adaptorPtr->nAttributes; + pa->pAttributes = pAttribute; + } + + + totFormat = adaptorPtr->nFormats; + + if(!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) { + xf86XVFreeAdaptor(pa); + continue; + } + for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats; + i < adaptorPtr->nFormats; i++, formatPtr++) + { + numVisuals = pScreen->numVisuals; + pVisual = pScreen->visuals; + + while(numVisuals--) { + if((pVisual->class == formatPtr->class) && + (pVisual->nplanes == formatPtr->depth)) { + + if(numFormat >= totFormat) { + void *moreSpace; + totFormat *= 2; + moreSpace = realloc(pFormat, + totFormat * sizeof(XvFormatRec)); + if(!moreSpace) break; + pFormat = moreSpace; + pf = pFormat + numFormat; + } + + pf->visual = pVisual->vid; + pf->depth = formatPtr->depth; + + pf++; + numFormat++; + } + pVisual++; + } + } + pa->nFormats = numFormat; + pa->pFormats = pFormat; + if(!numFormat) { + xf86XVFreeAdaptor(pa); + continue; + } + + if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) { + xf86XVFreeAdaptor(pa); + continue; + } + + adaptorPriv->flags = adaptorPtr->flags; + adaptorPriv->PutVideo = adaptorPtr->PutVideo; + adaptorPriv->PutStill = adaptorPtr->PutStill; + adaptorPriv->GetVideo = adaptorPtr->GetVideo; + adaptorPriv->GetStill = adaptorPtr->GetStill; + adaptorPriv->StopVideo = adaptorPtr->StopVideo; + adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute; + adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute; + adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize; + adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes; + adaptorPriv->PutImage = adaptorPtr->PutImage; + adaptorPriv->ReputImage = adaptorPtr->ReputImage; + + pa->devPriv.ptr = (pointer)adaptorPriv; + + if(!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) { + xf86XVFreeAdaptor(pa); + continue; + } + for(pp = pPort, i = 0, numPort = 0; + i < adaptorPtr->nPorts; i++) { + + if(!(pp->id = FakeClientID(0))) + continue; + + if(!(portPriv = calloc(1, sizeof(XvPortRecPrivate)))) + continue; + + if(!AddResource(pp->id, PortResource, pp)) { + free(portPriv); + continue; + } + + pp->pAdaptor = pa; + pp->pNotify = (XvPortNotifyPtr)NULL; + pp->pDraw = (DrawablePtr)NULL; + pp->client = (ClientPtr)NULL; + pp->grab.client = (ClientPtr)NULL; + pp->time = currentTime; + pp->devPriv.ptr = portPriv; + + portPriv->pScrn = pScrn; + portPriv->AdaptorRec = adaptorPriv; + portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; + + pp++; + numPort++; + } + pa->nPorts = numPort; + pa->pPorts = pPort; + if(!numPort) { + xf86XVFreeAdaptor(pa); + continue; + } + + pa->base_id = pPort->id; + + pa++; + numAdaptor++; + } + + if(numAdaptor) { + pxvs->nAdaptors = numAdaptor; + pxvs->pAdaptors = pAdaptor; + } else { + free(pAdaptor); + return FALSE; + } + + return TRUE; +} + +/* Video should be clipped to the intersection of the window cliplist + and the client cliplist specified in the GC for which the video was + initialized. When we need to reclip a window, the GC that started + the video may not even be around anymore. That's why we save the + client clip from the GC when the video is initialized. We then + use xf86XVUpdateCompositeClip to calculate the new composite clip + when we need it. This is different from what DEC did. They saved + the GC and used it's clip list when they needed to reclip the window, + even if the client clip was different from the one the video was + initialized with. If the original GC was destroyed, they had to stop + the video. I like the new method better (MArk). + + This function only works for windows. Will need to rewrite when + (if) we support pixmap rendering. +*/ + +static void +xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) +{ + RegionPtr pregWin, pCompositeClip; + WindowPtr pWin; + ScreenPtr pScreen; + Bool freeCompClip = FALSE; + + if(portPriv->pCompositeClip) + return; + + pWin = (WindowPtr)portPriv->pDraw; + pScreen = pWin->drawable.pScreen; + + /* get window clip list */ + if(portPriv->subWindowMode == IncludeInferiors) { + pregWin = NotClippedByChildren(pWin); + freeCompClip = TRUE; + } else + pregWin = &pWin->clipList; + + if(!portPriv->clientClip) { + portPriv->pCompositeClip = pregWin; + portPriv->FreeCompositeClip = freeCompClip; + return; + } + + pCompositeClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pCompositeClip, portPriv->clientClip); + REGION_TRANSLATE(pScreen, pCompositeClip, + portPriv->pDraw->x + portPriv->clipOrg.x, + portPriv->pDraw->y + portPriv->clipOrg.y); + REGION_INTERSECT(pScreen, pCompositeClip, pregWin, pCompositeClip); + + portPriv->pCompositeClip = pCompositeClip; + portPriv->FreeCompositeClip = TRUE; + + if(freeCompClip) { + REGION_DESTROY(pScreen, pregWin); + } +} + +/* Save the current clientClip and update the CompositeClip whenever + we have a fresh GC */ + +static void +xf86XVCopyClip( + XvPortRecPrivatePtr portPriv, + GCPtr pGC +){ + /* copy the new clip if it exists */ + if((pGC->clientClipType == CT_REGION) && pGC->clientClip) { + if(!portPriv->clientClip) + portPriv->clientClip = REGION_CREATE(pScreen, NullBox, 1); + /* Note: this is in window coordinates */ + REGION_COPY(pScreen, portPriv->clientClip, pGC->clientClip); + } else if(portPriv->clientClip) { /* free the old clientClip */ + REGION_DESTROY(pScreen, portPriv->clientClip); + portPriv->clientClip = NULL; + } + + /* get rid of the old clip list */ + if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) { + REGION_DESTROY(pScreen, portPriv->pCompositeClip); + } + + portPriv->clipOrg = pGC->clipOrg; + portPriv->pCompositeClip = pGC->pCompositeClip; + portPriv->FreeCompositeClip = FALSE; + portPriv->subWindowMode = pGC->subWindowMode; +} + +static int +xf86XVRegetVideo(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + ScreenPtr pScreen; + int ret = Success; + Bool clippedAway = FALSE; + + pScreen = portPriv->pDraw->pScreen; + xf86XVUpdateCompositeClip(portPriv); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + REGION_INIT(pScreen, &WinRegion, &WinBox, 1); + REGION_NULL(pScreen, &ClipRegion); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* that's all if it's totally obscured */ + if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn, + portPriv->vid_x, portPriv->vid_y, + WinBox.x1, WinBox.y1, + portPriv->vid_w, portPriv->vid_h, + portPriv->drw_w, portPriv->drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + if(ret == Success) + portPriv->isOn = XV_ON; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + + +static int +xf86XVReputVideo(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + ScreenPtr pScreen; + int ret = Success; + Bool clippedAway = FALSE; + + pScreen = portPriv->pDraw->pScreen; + + xf86XVUpdateCompositeClip(portPriv); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + REGION_INIT(pScreen, &WinRegion, &WinBox, 1); + REGION_NULL(pScreen, &ClipRegion); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* clip and translate to the viewport */ + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + REGION_INIT(pScreen, &VPReg, &VPBox, 1); + REGION_INTERSECT(pScreen, &ClipRegion, &ClipRegion, &VPReg); + REGION_UNINIT(pScreen, &VPReg); + } + + /* that's all if it's totally obscured */ + if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + /* bailout if we have to clip but the hardware doesn't support it */ + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = REGION_RECTS(&ClipRegion); + if( (REGION_NUM_RECTS(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn, + portPriv->vid_x, portPriv->vid_y, + WinBox.x1, WinBox.y1, + portPriv->vid_w, portPriv->vid_h, + portPriv->drw_w, portPriv->drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + if(ret == Success) portPriv->isOn = XV_ON; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + +static int +xf86XVReputImage(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + ScreenPtr pScreen; + int ret = Success; + Bool clippedAway = FALSE; + + pScreen = portPriv->pDraw->pScreen; + + xf86XVUpdateCompositeClip(portPriv); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + REGION_INIT(pScreen, &WinRegion, &WinBox, 1); + REGION_NULL(pScreen, &ClipRegion); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* clip and translate to the viewport */ + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + REGION_INIT(pScreen, &VPReg, &VPBox, 1); + REGION_INTERSECT(pScreen, &ClipRegion, &ClipRegion, &VPReg); + REGION_UNINIT(pScreen, &VPReg); + } + + /* that's all if it's totally obscured */ + if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + /* bailout if we have to clip but the hardware doesn't support it */ + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = REGION_RECTS(&ClipRegion); + if( (REGION_NUM_RECTS(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn, + WinBox.x1, WinBox.y1, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + + +static int +xf86XVReputAllVideo(WindowPtr pWin, pointer data) +{ + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + + while(WinPriv) { + if(WinPriv->PortRec->type == XvInputMask) + xf86XVReputVideo(WinPriv->PortRec); + else + xf86XVRegetVideo(WinPriv->PortRec); + WinPriv = WinPriv->next; + } + + return WT_WALKCHILDREN; +} + +static int +xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) +{ + XF86XVWindowPtr winPriv, PrivRoot; + + winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin); + + /* Enlist our port in the window private */ + while(winPriv) { + if(winPriv->PortRec == portPriv) /* we're already listed */ + break; + winPriv = winPriv->next; + } + + if(!winPriv) { + winPriv = calloc(1, sizeof(XF86XVWindowRec)); + if(!winPriv) return BadAlloc; + winPriv->PortRec = portPriv; + winPriv->next = PrivRoot; + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv); + } + + portPriv->pDraw = (DrawablePtr)pWin; + + return Success; +} + + +static void +xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) +{ + XF86XVWindowPtr winPriv, prevPriv = NULL; + + winPriv = GET_XF86XV_WINDOW(pWin); + + while(winPriv) { + if(winPriv->PortRec == portPriv) { + if(prevPriv) + prevPriv->next = winPriv->next; + else + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, + winPriv->next); + free(winPriv); + break; + } + prevPriv = winPriv; + winPriv = winPriv->next; + } + portPriv->pDraw = NULL; +} + +/**** ScreenRec fields ****/ + +static Bool +xf86XVDestroyWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin); + int ret; + + while(WinPriv) { + XvPortRecPrivatePtr pPriv = WinPriv->PortRec; + + if(pPriv->isOn > XV_OFF) { + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); + pPriv->isOn = XV_OFF; + } + + pPriv->pDraw = NULL; + tmp = WinPriv; + if(WinPriv->pGC) { + FreeGC(WinPriv->pGC, 0); + } + WinPriv = WinPriv->next; + free(tmp); + } + + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL); + + pScreen->DestroyWindow = ScreenPriv->DestroyWindow; + ret = (*pScreen->DestroyWindow)(pWin); + pScreen->DestroyWindow = xf86XVDestroyWindow; + + return ret; +} + + +static void +xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + XF86XVWindowPtr pPrev; + XvPortRecPrivatePtr pPriv; + Bool AreasExposed; + + AreasExposed = (WinPriv && reg1 && REGION_NOTEMPTY(pScreen, reg1)); + + pScreen->WindowExposures = ScreenPriv->WindowExposures; + (*pScreen->WindowExposures)(pWin, reg1, reg2); + pScreen->WindowExposures = xf86XVWindowExposures; + + /* filter out XClearWindow/Area */ + if (!pWin->valdata) return; + + pPrev = NULL; + + while(WinPriv) { + pPriv = WinPriv->PortRec; + + /* Reput anyone with a reput function */ + + switch(pPriv->type) { + case XvInputMask: + xf86XVReputVideo(pPriv); + break; + case XvOutputMask: + xf86XVRegetVideo(pPriv); + break; + default: /* overlaid still/image*/ + if (pPriv->AdaptorRec->ReputImage) + xf86XVReputImage(pPriv); + else if(AreasExposed) { + XF86XVWindowPtr tmp; + + if (pPriv->isOn == XV_ON) { + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); + pPriv->isOn = XV_PENDING; + } + pPriv->pDraw = NULL; + + if(!pPrev) + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, + WinPriv->next); + else + pPrev->next = WinPriv->next; + tmp = WinPriv; + WinPriv = WinPriv->next; + free(tmp); + continue; + } + break; + } + pPrev = WinPriv; + WinPriv = WinPriv->next; + } +} + + +static void +xf86XVClipNotify(WindowPtr pWin, int dx, int dy) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + XF86XVWindowPtr tmp, pPrev = NULL; + XvPortRecPrivatePtr pPriv; + Bool visible = (pWin->visibility == VisibilityUnobscured) || + (pWin->visibility == VisibilityPartiallyObscured); + + while(WinPriv) { + pPriv = WinPriv->PortRec; + + if(!pPriv) goto next; + + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + REGION_DESTROY(pScreen, pPriv->pCompositeClip); + + pPriv->pCompositeClip = NULL; + + if (pPriv->AdaptorRec->ClipNotify) + (*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr, + pWin, dx, dy); + + /* Stop everything except images, but stop them too if the + window isn't visible. But we only remove the images. */ + + if(pPriv->type || !visible) { + if(pPriv->isOn == XV_ON) { + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); + pPriv->isOn = XV_PENDING; + } + + if(!pPriv->type) { /* overlaid still/image */ + pPriv->pDraw = NULL; + + if(!pPrev) + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, + WinPriv->next); + else + pPrev->next = WinPriv->next; + tmp = WinPriv; + WinPriv = WinPriv->next; + free(tmp); + continue; + } + } + +next: + pPrev = WinPriv; + WinPriv = WinPriv->next; + } + + if(ScreenPriv->ClipNotify) { + pScreen->ClipNotify = ScreenPriv->ClipNotify; + (*pScreen->ClipNotify)(pWin, dx, dy); + pScreen->ClipNotify = xf86XVClipNotify; + } +} + + + +/**** Required XvScreenRec fields ****/ + +static Bool +xf86XVCloseScreen(int i, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XvAdaptorPtr pa; + int c; + + if(!ScreenPriv) return TRUE; + + if(ScreenPriv->videoGC) { + FreeGC(ScreenPriv->videoGC, 0); + ScreenPriv->videoGC = NULL; + } + + pScreen->DestroyWindow = ScreenPriv->DestroyWindow; + pScreen->WindowExposures = ScreenPriv->WindowExposures; + pScreen->ClipNotify = ScreenPriv->ClipNotify; + + pScrn->EnterVT = ScreenPriv->EnterVT; + pScrn->LeaveVT = ScreenPriv->LeaveVT; + pScrn->AdjustFrame = ScreenPriv->AdjustFrame; + + for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { + xf86XVFreeAdaptor(pa); + } + + free(pxvs->pAdaptors); + free(ScreenPriv); + return TRUE; +} + + +static int +xf86XVQueryAdaptors( + ScreenPtr pScreen, + XvAdaptorPtr *p_pAdaptors, + int *p_nAdaptors +){ + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + + *p_nAdaptors = pxvs->nAdaptors; + *p_pAdaptors = pxvs->pAdaptors; + + return (Success); +} + + +/**** ScrnInfoRec fields ****/ + +static Bool +xf86XVEnterVT(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + Bool ret; + + ret = (*ScreenPriv->EnterVT)(index, flags); + + if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0); + + return ret; +} + +static void +xf86XVLeaveVT(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XvAdaptorPtr pAdaptor; + XvPortPtr pPort; + XvPortRecPrivatePtr pPriv; + int i, j; + + for(i = 0; i < pxvs->nAdaptors; i++) { + pAdaptor = &pxvs->pAdaptors[i]; + for(j = 0; j < pAdaptor->nPorts; j++) { + pPort = &pAdaptor->pPorts[j]; + pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + if(pPriv->isOn > XV_OFF) { + + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); + pPriv->isOn = XV_OFF; + + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + REGION_DESTROY(pScreen, pPriv->pCompositeClip); + + pPriv->pCompositeClip = NULL; + + if(!pPriv->type && pPriv->pDraw) { /* still */ + xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv); + } + } + } + } + + (*ScreenPriv->LeaveVT)(index, flags); +} + +static void +xf86XVAdjustFrame(int index, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = pScrn->pScreen; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + WindowPtr pWin; + XvAdaptorPtr pa; + int c, i; + + if(ScreenPriv->AdjustFrame) { + pScrn->AdjustFrame = ScreenPriv->AdjustFrame; + (*pScrn->AdjustFrame)(index, x, y, flags); + pScrn->AdjustFrame = xf86XVAdjustFrame; + } + + for(c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) { + XvPortPtr pPort = pa->pPorts; + XvPortRecPrivatePtr pPriv; + + for(i = pa->nPorts; i > 0; i--, pPort++) { + pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + + if(!pPriv->type && (pPriv->isOn != XV_OFF)) { /* overlaid still/image */ + + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + REGION_DESTROY(pScreen, pPriv->pCompositeClip); + + pPriv->pCompositeClip = NULL; + + pWin = (WindowPtr)pPriv->pDraw; + + if ((pPriv->AdaptorRec->ReputImage) && + ((pWin->visibility == VisibilityUnobscured) || + (pWin->visibility == VisibilityPartiallyObscured))) + { + xf86XVReputImage(pPriv); + } else if (pPriv->isOn == XV_ON) { + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); + xf86XVRemovePortFromWindow(pWin, pPriv); + pPriv->isOn = XV_PENDING; + continue; + } + } + } + } +} + + +/**** XvAdaptorRec fields ****/ + +static int +xf86XVAllocatePort( + unsigned long port, + XvPortPtr pPort, + XvPortPtr *ppPort +){ + *ppPort = pPort; + return Success; +} + + + +static int +xf86XVFreePort(XvPortPtr pPort) +{ + return Success; +} + + +static int +xf86XVPutVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + int result; + + /* No dumping video to pixmaps... For now anyhow */ + if(pDraw->type != DRAWABLE_WINDOW) { + pPort->pDraw = (DrawablePtr)NULL; + return BadAlloc; + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(result != Success) return result; + + portPriv->type = XvInputMask; + + /* save a copy of these parameters */ + portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; + portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + + /* make sure we have the most recent copy of the clientClip */ + xf86XVCopyClip(portPriv, pGC); + + /* To indicate to the DI layer that we were successful */ + pPort->pDraw = pDraw; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + return(xf86XVReputVideo(portPriv)); +} + +static int +xf86XVPutStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + ScreenPtr pScreen; + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + pScreen = pDraw->pScreen; + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + REGION_INIT(pScreen, &WinRegion, &WinBox, 1); + REGION_NULL(pScreen, &ClipRegion); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + REGION_INIT(pScreen, &VPReg, &VPBox, 1); + REGION_INTERSECT(pScreen, &ClipRegion, &ClipRegion, &VPReg); + REGION_UNINIT(pScreen, &VPReg); + } + + if(portPriv->pDraw) { + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + } + + if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { + clippedAway = TRUE; + goto PUT_STILL_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = REGION_RECTS(&ClipRegion); + if( (REGION_NUM_RECTS(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto PUT_STILL_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn, + vid_x, vid_y, WinBox.x1, WinBox.y1, + vid_w, vid_h, drw_w, drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + + if((ret == Success) && + (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { + + xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + portPriv->isOn = XV_ON; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + portPriv->type = 0; /* no mask means it's transient and should + not be reput once it's removed */ + pPort->pDraw = pDraw; /* make sure we can get stop requests */ + } + +PUT_STILL_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + +static int +xf86XVGetVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + int result; + + /* No pixmaps... For now anyhow */ + if(pDraw->type != DRAWABLE_WINDOW) { + pPort->pDraw = (DrawablePtr)NULL; + return BadAlloc; + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(result != Success) return result; + + portPriv->type = XvOutputMask; + + /* save a copy of these parameters */ + portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; + portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + + /* make sure we have the most recent copy of the clientClip */ + xf86XVCopyClip(portPriv, pGC); + + /* To indicate to the DI layer that we were successful */ + pPort->pDraw = pDraw; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + return(xf86XVRegetVideo(portPriv)); +} + +static int +xf86XVGetStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + ScreenPtr pScreen; + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + pScreen = pDraw->pScreen; + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + REGION_INIT(pScreen, &WinRegion, &WinBox, 1); + REGION_NULL(pScreen, &ClipRegion); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->pDraw) { + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + } + + if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { + clippedAway = TRUE; + goto GET_STILL_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn, + vid_x, vid_y, WinBox.x1, WinBox.y1, + vid_w, vid_h, drw_w, drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + +GET_STILL_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + + + +static int +xf86XVStopVideo( + ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDraw +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + if(pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv); + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + /* Must free resources. */ + + if(portPriv->isOn > XV_OFF) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, TRUE); + portPriv->isOn = XV_OFF; + } + + return Success; +} + +static int +xf86XVSetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 value +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn, + attribute, value, portPriv->DevPriv.ptr)); +} + + +static int +xf86XVGetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 *p_value +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn, + attribute, p_value, portPriv->DevPriv.ptr)); +} + + + +static int +xf86XVQueryBestSize( + ClientPtr client, + XvPortPtr pPort, + CARD8 motion, + CARD16 vid_w, CARD16 vid_h, + CARD16 drw_w, CARD16 drw_h, + unsigned int *p_w, unsigned int *p_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + (*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn, + (Bool)motion, vid_w, vid_h, drw_w, drw_h, + p_w, p_h, portPriv->DevPriv.ptr); + + return Success; +} + + +static int +xf86XVPutImage( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 src_x, INT16 src_y, + CARD16 src_w, CARD16 src_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h, + XvImagePtr format, + unsigned char* data, + Bool sync, + CARD16 width, CARD16 height +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + ScreenPtr pScreen; + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + pScreen = pDraw->pScreen; + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + REGION_INIT(pScreen, &WinRegion, &WinBox, 1); + REGION_NULL(pScreen, &ClipRegion); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + REGION_INIT(pScreen, &VPReg, &VPBox, 1); + REGION_INTERSECT(pScreen, &ClipRegion, &ClipRegion, &VPReg); + REGION_UNINIT(pScreen, &VPReg); + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + ret = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(ret != Success) goto PUT_IMAGE_BAILOUT; + + if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) { + clippedAway = TRUE; + goto PUT_IMAGE_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = REGION_RECTS(&ClipRegion); + if( (REGION_NUM_RECTS(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto PUT_IMAGE_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + REGION_SUBTRACT(pScreen, &ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn, + src_x, src_y, WinBox.x1, WinBox.y1, + src_w, src_h, drw_w, drw_h, format->id, data, width, height, + sync, &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + + if((ret == Success) && + (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { + + portPriv->isOn = XV_ON; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + portPriv->type = 0; /* no mask means it's transient and should + not be reput once it's removed */ + pPort->pDraw = pDraw; /* make sure we can get stop requests */ + } + +PUT_IMAGE_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + + +static int +xf86XVQueryImageAttributes( + ClientPtr client, + XvPortPtr pPort, + XvImagePtr format, + CARD16 *width, + CARD16 *height, + int *pitches, + int *offsets +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn, + format->id, width, height, pitches, offsets); +} + + +void +xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr clipboxes) +{ + ScreenPtr pScreen = pDraw->pScreen; + WindowPtr pWin = (WindowPtr)pDraw; + XF86XVWindowPtr pPriv = GET_XF86XV_WINDOW(pWin); + GCPtr pGC = NULL; + BoxPtr pbox = REGION_RECTS(clipboxes); + int i, nbox = REGION_NUM_RECTS(clipboxes); + xRectangle *rects; + + if(!xf86Screens[pScreen->myNum]->vtSema) return; + + if(pPriv) + pGC = pPriv->pGC; + + if(!pGC) { + int status; + XID pval[2]; + pval[0] = key; + pval[1] = IncludeInferiors; + pGC = CreateGC(pDraw, GCForeground | GCSubwindowMode, pval, &status, + (XID)0, serverClient); + if(!pGC) return; + ValidateGC(pDraw, pGC); + if (pPriv) pPriv->pGC = pGC; + } else if (key != pGC->fgPixel){ + ChangeGCVal val; + val.val = key; + ChangeGC(NullClient, pGC, GCForeground, &val); + ValidateGC(pDraw, pGC); + } + + REGION_TRANSLATE(pDraw->pScreen, clipboxes, -pDraw->x, -pDraw->y); + + rects = malloc(nbox * sizeof(xRectangle)); + + for(i = 0; i < nbox; i++, pbox++) { + rects[i].x = pbox->x1; + rects[i].y = pbox->y1; + rects[i].width = pbox->x2 - pbox->x1; + rects[i].height = pbox->y2 - pbox->y1; + } + + (*pGC->ops->PolyFillRect)(pDraw, pGC, nbox, rects); + + if (!pPriv) FreeGC(pGC, 0); + + free(rects); +} + +void +xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes) +{ + DrawablePtr root = &WindowTable[pScreen->myNum]->drawable; + ChangeGCVal pval[2]; + BoxPtr pbox = REGION_RECTS(clipboxes); + int i, nbox = REGION_NUM_RECTS(clipboxes); + xRectangle *rects; + GCPtr gc; + + if(!xf86Screens[pScreen->myNum]->vtSema) return; + + gc = GetScratchGC(root->depth, pScreen); + pval[0].val = key; + pval[1].val = IncludeInferiors; + (void) ChangeGC(NullClient, gc, GCForeground|GCSubwindowMode, pval); + ValidateGC(root, gc); + + rects = malloc(nbox * sizeof(xRectangle)); + + for(i = 0; i < nbox; i++, pbox++) + { + rects[i].x = pbox->x1; + rects[i].y = pbox->y1; + rects[i].width = pbox->x2 - pbox->x1; + rects[i].height = pbox->y2 - pbox->y1; + } + + (*gc->ops->PolyFillRect)(root, gc, nbox, rects); + + free(rects); + FreeScratchGC (gc); +} + +/* xf86XVClipVideoHelper - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +#define DummyScreen screenInfo.screens[0] + +Bool +xf86XVClipVideoHelper( + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height +){ + double xsw, xdw, ysw, ydw; + INT32 delta; + BoxPtr extents = REGION_EXTENTS(DummyScreen, reg); + int diff; + + xsw = (*xb - *xa) << 16; + xdw = dst->x2 - dst->x1; + ysw = (*yb - *ya) << 16; + ydw = dst->y2 - dst->y1; + + *xa <<= 16; *xb <<= 16; + *ya <<= 16; *yb <<= 16; + + diff = extents->x1 - dst->x1; + if (diff > 0) { + dst->x1 = extents->x1; + *xa += (diff * xsw) / xdw; + } + diff = dst->x2 - extents->x2; + if (diff > 0) { + dst->x2 = extents->x2; + *xb -= (diff * xsw) / xdw; + } + diff = extents->y1 - dst->y1; + if (diff > 0) { + dst->y1 = extents->y1; + *ya += (diff * ysw) / ydw; + } + diff = dst->y2 - extents->y2; + if (diff > 0) { + dst->y2 = extents->y2; + *yb -= (diff * ysw) / ydw; + } + + if (*xa < 0) { + diff = (((-*xa) * xdw) + xsw - 1) / xsw; + dst->x1 += diff; + *xa += (diff * xsw) / xdw; + } + delta = *xb - (width << 16); + if (delta > 0) { + diff = ((delta * xdw) + xsw - 1) / xsw; + dst->x2 -= diff; + *xb -= (diff * xsw) / xdw; + } + if (*xa >= *xb) return FALSE; + + if (*ya < 0) { + diff = (((-*ya) * ydw) + ysw - 1) / ysw; + dst->y1 += diff; + *ya += (diff * ysw) / ydw; + } + delta = *yb - (height << 16); + if (delta > 0) { + diff = ((delta * ydw) + ysw - 1) / ysw; + dst->y2 -= diff; + *yb -= (diff * ysw) / ydw; + } + if (*ya >= *yb) return FALSE; + + if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) || + (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) + { + RegionRec clipReg; + REGION_INIT(DummyScreen, &clipReg, dst, 1); + REGION_INTERSECT(DummyScreen, reg, reg, &clipReg); + REGION_UNINIT(DummyScreen, &clipReg); + } + return TRUE; +} + +void +xf86XVCopyYUV12ToPacked( + const void *srcy, + const void *srcv, + const void *srcu, + void *dst, + int srcPitchy, + int srcPitchuv, + int dstPitch, + int h, + int w +){ + CARD32 *Dst; + const CARD8 *Y, *U, *V; + int i, j; + + w >>= 1; + + for (j = 0; j < h; j++) { + Dst = dst; + Y = srcy; V = srcv; U = srcu; + i = w; + while (i >= 4) { +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); + Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24); + Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24); + Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24); +#else + /* This assumes a little-endian framebuffer */ + Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; + Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1]; + Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2]; + Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3]; +#endif + Dst += 4; Y += 8; V += 4; U += 4; + i -= 4; + } + + while (i--) { +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); +#else + /* This assumes a little-endian framebuffer */ + Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; +#endif + Dst++; Y += 2; V++; U++; + } + + dst = (CARD8 *)dst + dstPitch; + srcy = (const CARD8 *)srcy + srcPitchy; + if (j & 1) { + srcu = (const CARD8 *)srcu + srcPitchuv; + srcv = (const CARD8 *)srcv + srcPitchuv; + } + } +} + +void +xf86XVCopyPacked( + const void *src, + void *dst, + int srcPitch, + int dstPitch, + int h, + int w +){ + const CARD32 *Src; + CARD32 *Dst; + int i; + + w >>= 1; + while (--h >= 0) { + do { + Dst = dst; Src = src; + i = w; + while (i >= 4) { + Dst[0] = Src[0]; + Dst[1] = Src[1]; + Dst[2] = Src[2]; + Dst[3] = Src[3]; + Dst += 4; Src += 4; i -= 4; + } + if (!i) break; + Dst[0] = Src[0]; + if (i == 1) break; + Dst[1] = Src[1]; + if (i == 2) break; + Dst[2] = Src[2]; + } while (0); + + src = (const CARD8 *)src + srcPitch; + dst = (CARD8 *)dst + dstPitch; + } +} diff --git a/xorg-server/hw/xfree86/common/xf86xvmc.c b/xorg-server/hw/xfree86/common/xf86xvmc.c index 39d33da08..9cf36f526 100644 --- a/xorg-server/hw/xfree86/common/xf86xvmc.c +++ b/xorg-server/hw/xfree86/common/xf86xvmc.c @@ -1,229 +1,229 @@ - -/* - * Copyright (c) 2001-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include -#include "scrnintstr.h" -#include "resource.h" -#include "dixstruct.h" - -#include "xvmodproc.h" - -#include "xf86xvpriv.h" -#include "xf86xvmc.h" - -XvMCScreenInitProcPtr XvMCScreenInitProc = NULL; - - -typedef struct { - CloseScreenProcPtr CloseScreen; - int num_adaptors; - XF86MCAdaptorPtr *adaptors; - XvMCAdaptorPtr dixinfo; -} xf86XvMCScreenRec, *xf86XvMCScreenPtr; - -static int XF86XvMCScreenKeyIndex; -static DevPrivateKey XF86XvMCScreenKey = &XF86XvMCScreenKeyIndex; - -#define XF86XVMC_GET_PRIVATE(pScreen) (xf86XvMCScreenPtr) \ - dixLookupPrivate(&(pScreen)->devPrivates, XF86XvMCScreenKey) - - -static int -xf86XvMCCreateContext ( - XvPortPtr pPort, - XvMCContextPtr pContext, - int *num_priv, - CARD32 **priv -) -{ - xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); - ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; - - pContext->port_priv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - - return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateContext)( - pScrn, pContext, num_priv, priv); -} - -static void -xf86XvMCDestroyContext ( XvMCContextPtr pContext) -{ - xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); - ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; - - (*pScreenPriv->adaptors[pContext->adapt_num]->DestroyContext)( - pScrn, pContext); -} - -static int -xf86XvMCCreateSurface ( - XvMCSurfacePtr pSurface, - int *num_priv, - CARD32 **priv -) -{ - XvMCContextPtr pContext = pSurface->context; - xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); - ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; - - return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateSurface)( - pScrn, pSurface, num_priv, priv); -} - -static void -xf86XvMCDestroySurface (XvMCSurfacePtr pSurface) -{ - XvMCContextPtr pContext = pSurface->context; - xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); - ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; - - (*pScreenPriv->adaptors[pContext->adapt_num]->DestroySurface)( - pScrn, pSurface); -} - -static int -xf86XvMCCreateSubpicture ( - XvMCSubpicturePtr pSubpicture, - int *num_priv, - CARD32 **priv -) -{ - XvMCContextPtr pContext = pSubpicture->context; - xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); - ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; - - return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateSubpicture)( - pScrn, pSubpicture, num_priv, priv); -} - -static void -xf86XvMCDestroySubpicture (XvMCSubpicturePtr pSubpicture) -{ - XvMCContextPtr pContext = pSubpicture->context; - xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); - ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; - - (*pScreenPriv->adaptors[pContext->adapt_num]->DestroySubpicture)( - pScrn, pSubpicture); -} - - -static Bool -xf86XvMCCloseScreen (int i, ScreenPtr pScreen) -{ - xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - - xfree(pScreenPriv->dixinfo); - xfree(pScreenPriv); - - return (*pScreen->CloseScreen)(i, pScreen); -} - -Bool xf86XvMCScreenInit( - ScreenPtr pScreen, - int num_adaptors, - XF86MCAdaptorPtr *adaptors -) -{ - XvMCAdaptorPtr pAdapt; - xf86XvMCScreenPtr pScreenPriv; - XvScreenPtr pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - XF86XvScreenKey); - int i, j; - - if(!XvMCScreenInitProc) return FALSE; - - if(!(pAdapt = xalloc(sizeof(XvMCAdaptorRec) * num_adaptors))) - return FALSE; - - if(!(pScreenPriv = xalloc(sizeof(xf86XvMCScreenRec)))) { - xfree(pAdapt); - return FALSE; - } - - dixSetPrivate(&pScreen->devPrivates, XF86XvMCScreenKey, pScreenPriv); - - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = xf86XvMCCloseScreen; - - pScreenPriv->num_adaptors = num_adaptors; - pScreenPriv->adaptors = adaptors; - pScreenPriv->dixinfo = pAdapt; - - for(i = 0; i < num_adaptors; i++) { - pAdapt[i].xv_adaptor = NULL; - for(j = 0; j < pxvs->nAdaptors; j++) { - if(!strcmp((*adaptors)->name, pxvs->pAdaptors[j].name)) { - pAdapt[i].xv_adaptor = &(pxvs->pAdaptors[j]); - break; - } - } - if(!pAdapt[i].xv_adaptor) { - /* no adaptor by that name */ - xfree(pAdapt); - return FALSE; - } - pAdapt[i].num_surfaces = (*adaptors)->num_surfaces; - pAdapt[i].surfaces = (XvMCSurfaceInfoPtr*)((*adaptors)->surfaces); - pAdapt[i].num_subpictures = (*adaptors)->num_subpictures; - pAdapt[i].subpictures = (XvImagePtr*)((*adaptors)->subpictures); - pAdapt[i].CreateContext = xf86XvMCCreateContext; - pAdapt[i].DestroyContext = xf86XvMCDestroyContext; - pAdapt[i].CreateSurface = xf86XvMCCreateSurface; - pAdapt[i].DestroySurface = xf86XvMCDestroySurface; - pAdapt[i].CreateSubpicture = xf86XvMCCreateSubpicture; - pAdapt[i].DestroySubpicture = xf86XvMCDestroySubpicture; - adaptors++; - } - - if(Success != (*XvMCScreenInitProc)(pScreen, num_adaptors, pAdapt)) - return FALSE; - - return TRUE; -} - -XF86MCAdaptorPtr xf86XvMCCreateAdaptorRec (void) -{ - return xcalloc(1, sizeof(XF86MCAdaptorRec)); -} - -void xf86XvMCDestroyAdaptorRec(XF86MCAdaptorPtr adaptor) -{ - xfree(adaptor); -} + +/* + * Copyright (c) 2001-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" + +#include "xvmodproc.h" + +#include "xf86xvpriv.h" +#include "xf86xvmc.h" + +XvMCScreenInitProcPtr XvMCScreenInitProc = NULL; + + +typedef struct { + CloseScreenProcPtr CloseScreen; + int num_adaptors; + XF86MCAdaptorPtr *adaptors; + XvMCAdaptorPtr dixinfo; +} xf86XvMCScreenRec, *xf86XvMCScreenPtr; + +static int XF86XvMCScreenKeyIndex; +static DevPrivateKey XF86XvMCScreenKey = &XF86XvMCScreenKeyIndex; + +#define XF86XVMC_GET_PRIVATE(pScreen) (xf86XvMCScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, XF86XvMCScreenKey) + + +static int +xf86XvMCCreateContext ( + XvPortPtr pPort, + XvMCContextPtr pContext, + int *num_priv, + CARD32 **priv +) +{ + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + pContext->port_priv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateContext)( + pScrn, pContext, num_priv, priv); +} + +static void +xf86XvMCDestroyContext ( XvMCContextPtr pContext) +{ + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + (*pScreenPriv->adaptors[pContext->adapt_num]->DestroyContext)( + pScrn, pContext); +} + +static int +xf86XvMCCreateSurface ( + XvMCSurfacePtr pSurface, + int *num_priv, + CARD32 **priv +) +{ + XvMCContextPtr pContext = pSurface->context; + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateSurface)( + pScrn, pSurface, num_priv, priv); +} + +static void +xf86XvMCDestroySurface (XvMCSurfacePtr pSurface) +{ + XvMCContextPtr pContext = pSurface->context; + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + (*pScreenPriv->adaptors[pContext->adapt_num]->DestroySurface)( + pScrn, pSurface); +} + +static int +xf86XvMCCreateSubpicture ( + XvMCSubpicturePtr pSubpicture, + int *num_priv, + CARD32 **priv +) +{ + XvMCContextPtr pContext = pSubpicture->context; + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + return (*pScreenPriv->adaptors[pContext->adapt_num]->CreateSubpicture)( + pScrn, pSubpicture, num_priv, priv); +} + +static void +xf86XvMCDestroySubpicture (XvMCSubpicturePtr pSubpicture) +{ + XvMCContextPtr pContext = pSubpicture->context; + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pContext->pScreen); + ScrnInfoPtr pScrn = xf86Screens[pContext->pScreen->myNum]; + + (*pScreenPriv->adaptors[pContext->adapt_num]->DestroySubpicture)( + pScrn, pSubpicture); +} + + +static Bool +xf86XvMCCloseScreen (int i, ScreenPtr pScreen) +{ + xf86XvMCScreenPtr pScreenPriv = XF86XVMC_GET_PRIVATE(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + + free(pScreenPriv->dixinfo); + free(pScreenPriv); + + return (*pScreen->CloseScreen)(i, pScreen); +} + +Bool xf86XvMCScreenInit( + ScreenPtr pScreen, + int num_adaptors, + XF86MCAdaptorPtr *adaptors +) +{ + XvMCAdaptorPtr pAdapt; + xf86XvMCScreenPtr pScreenPriv; + XvScreenPtr pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + XF86XvScreenKey); + int i, j; + + if(!XvMCScreenInitProc) return FALSE; + + if(!(pAdapt = malloc(sizeof(XvMCAdaptorRec) * num_adaptors))) + return FALSE; + + if(!(pScreenPriv = malloc(sizeof(xf86XvMCScreenRec)))) { + free(pAdapt); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, XF86XvMCScreenKey, pScreenPriv); + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86XvMCCloseScreen; + + pScreenPriv->num_adaptors = num_adaptors; + pScreenPriv->adaptors = adaptors; + pScreenPriv->dixinfo = pAdapt; + + for(i = 0; i < num_adaptors; i++) { + pAdapt[i].xv_adaptor = NULL; + for(j = 0; j < pxvs->nAdaptors; j++) { + if(!strcmp((*adaptors)->name, pxvs->pAdaptors[j].name)) { + pAdapt[i].xv_adaptor = &(pxvs->pAdaptors[j]); + break; + } + } + if(!pAdapt[i].xv_adaptor) { + /* no adaptor by that name */ + free(pAdapt); + return FALSE; + } + pAdapt[i].num_surfaces = (*adaptors)->num_surfaces; + pAdapt[i].surfaces = (XvMCSurfaceInfoPtr*)((*adaptors)->surfaces); + pAdapt[i].num_subpictures = (*adaptors)->num_subpictures; + pAdapt[i].subpictures = (XvImagePtr*)((*adaptors)->subpictures); + pAdapt[i].CreateContext = xf86XvMCCreateContext; + pAdapt[i].DestroyContext = xf86XvMCDestroyContext; + pAdapt[i].CreateSurface = xf86XvMCCreateSurface; + pAdapt[i].DestroySurface = xf86XvMCDestroySurface; + pAdapt[i].CreateSubpicture = xf86XvMCCreateSubpicture; + pAdapt[i].DestroySubpicture = xf86XvMCDestroySubpicture; + adaptors++; + } + + if(Success != (*XvMCScreenInitProc)(pScreen, num_adaptors, pAdapt)) + return FALSE; + + return TRUE; +} + +XF86MCAdaptorPtr xf86XvMCCreateAdaptorRec (void) +{ + return calloc(1, sizeof(XF86MCAdaptorRec)); +} + +void xf86XvMCDestroyAdaptorRec(XF86MCAdaptorPtr adaptor) +{ + free(adaptor); +} diff --git a/xorg-server/hw/xfree86/common/xisb.c b/xorg-server/hw/xfree86/common/xisb.c index 1cb9e4854..f08327fb3 100644 --- a/xorg-server/hw/xfree86/common/xisb.c +++ b/xorg-server/hw/xfree86/common/xisb.c @@ -1,174 +1,174 @@ -/* - * Copyright (c) 1997 Metro Link Incorporated - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Except as contained in this notice, the name of the Metro Link shall not be - * used in advertising or otherwise to promote the sale, use or other dealings - * in this Software without prior written authorization from Metro Link. - * - */ - -/* - X Input Serial Buffer routines for use in any XInput driver that accesses - a serial device. -*/ - - -/***************************************************************************** - * Standard Headers - ****************************************************************************/ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include "xisb.h" - -/***************************************************************************** - * Local Headers - ****************************************************************************/ - -/***************************************************************************** - * Variables without includable headers - ****************************************************************************/ - -/***************************************************************************** - * Local Variables - ****************************************************************************/ - -/***************************************************************************** - * Function Definitions - ****************************************************************************/ - -XISBuffer * -XisbNew (int fd, ssize_t size) -{ - XISBuffer *b; - - b = xalloc (sizeof (XISBuffer)); - if (!b) - return (NULL); - b->buf = xalloc ((sizeof (unsigned char) * size)); - if (!b->buf) - { - xfree (b); - return (NULL); - } - - b->fd = fd; - b->trace = 0; - b->block_duration = 0; - b->current = 1; /* force it to be past the end to trigger initial read */ - b->end = 0; - b->buffer_size = size; - return (b); -} - -void -XisbFree (XISBuffer *b) -{ - xfree (b->buf); - xfree (b); -} - -int -XisbRead (XISBuffer *b) -{ - int ret; - - if (b->current >= b->end) - { - if (b->block_duration >= 0) - { - if (xf86WaitForInput (b->fd, b->block_duration) < 1) - return (-1); - } - else - { - /* - * automatically clear it so if XisbRead is called in a loop - * the next call will make sure there is data with select and - * thus prevent a blocking read - */ - b->block_duration = 0; - } - - ret = xf86ReadSerial (b->fd, b->buf, b->buffer_size); - switch (ret) - { - case 0: - return (-1); /* timeout */ - case -1: - return (-2); /* error */ - default: - b->end = ret; - b->current = 0; - break; - } - } - if (b->trace) - ErrorF ("read 0x%02x (%c)\n", b->buf[b->current], - isprint(b->buf[b->current])?b->buf[b->current]:'.'); - - return (b->buf[b->current++]); -} - -/* the only purpose of this function is to provide output tracing */ -ssize_t -XisbWrite (XISBuffer *b, unsigned char *msg, ssize_t len) -{ - if (b->trace) - { - int i = 0; - for (i = 0; i < len; i++) - ErrorF ("\t\twrote 0x%02x (%c)\n", msg[i], msg[i]); - } - return (xf86WriteSerial (b->fd, msg, len)); -} - -/* turn tracing of this buffer on (1) or off (0) */ -void -XisbTrace (XISBuffer *b, int trace) -{ - b->trace = trace; -} - -/* - * specify a block_duration of -1 when you know the buffer's fd is ready to - * read. After a read, it is automatically set to 0 so that the next read - * will use check to select for data and prevent a block. - * It is the caller's responsibility to set the block_duration to -1 if it - * knows that there is data to read (because the main select loop triggered - * the read) and want's to avoid the unnecessary overhead of the select call - * - * a zero or positive block duration will cause the select to block for the - * give duration in usecs. - */ - -void -XisbBlockDuration (XISBuffer *b, int block_duration) -{ - b->block_duration = block_duration; -} +/* + * Copyright (c) 1997 Metro Link Incorporated + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ + +/* + X Input Serial Buffer routines for use in any XInput driver that accesses + a serial device. +*/ + + +/***************************************************************************** + * Standard Headers + ****************************************************************************/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "xisb.h" + +/***************************************************************************** + * Local Headers + ****************************************************************************/ + +/***************************************************************************** + * Variables without includable headers + ****************************************************************************/ + +/***************************************************************************** + * Local Variables + ****************************************************************************/ + +/***************************************************************************** + * Function Definitions + ****************************************************************************/ + +XISBuffer * +XisbNew (int fd, ssize_t size) +{ + XISBuffer *b; + + b = malloc(sizeof (XISBuffer)); + if (!b) + return (NULL); + b->buf = malloc((sizeof (unsigned char) * size)); + if (!b->buf) + { + free(b); + return (NULL); + } + + b->fd = fd; + b->trace = 0; + b->block_duration = 0; + b->current = 1; /* force it to be past the end to trigger initial read */ + b->end = 0; + b->buffer_size = size; + return (b); +} + +void +XisbFree (XISBuffer *b) +{ + free(b->buf); + free(b); +} + +int +XisbRead (XISBuffer *b) +{ + int ret; + + if (b->current >= b->end) + { + if (b->block_duration >= 0) + { + if (xf86WaitForInput (b->fd, b->block_duration) < 1) + return (-1); + } + else + { + /* + * automatically clear it so if XisbRead is called in a loop + * the next call will make sure there is data with select and + * thus prevent a blocking read + */ + b->block_duration = 0; + } + + ret = xf86ReadSerial (b->fd, b->buf, b->buffer_size); + switch (ret) + { + case 0: + return (-1); /* timeout */ + case -1: + return (-2); /* error */ + default: + b->end = ret; + b->current = 0; + break; + } + } + if (b->trace) + ErrorF ("read 0x%02x (%c)\n", b->buf[b->current], + isprint(b->buf[b->current])?b->buf[b->current]:'.'); + + return (b->buf[b->current++]); +} + +/* the only purpose of this function is to provide output tracing */ +ssize_t +XisbWrite (XISBuffer *b, unsigned char *msg, ssize_t len) +{ + if (b->trace) + { + int i = 0; + for (i = 0; i < len; i++) + ErrorF ("\t\twrote 0x%02x (%c)\n", msg[i], msg[i]); + } + return (xf86WriteSerial (b->fd, msg, len)); +} + +/* turn tracing of this buffer on (1) or off (0) */ +void +XisbTrace (XISBuffer *b, int trace) +{ + b->trace = trace; +} + +/* + * specify a block_duration of -1 when you know the buffer's fd is ready to + * read. After a read, it is automatically set to 0 so that the next read + * will use check to select for data and prevent a block. + * It is the caller's responsibility to set the block_duration to -1 if it + * knows that there is data to read (because the main select loop triggered + * the read) and want's to avoid the unnecessary overhead of the select call + * + * a zero or positive block duration will cause the select to block for the + * give duration in usecs. + */ + +void +XisbBlockDuration (XISBuffer *b, int block_duration) +{ + b->block_duration = block_duration; +} diff --git a/xorg-server/hw/xfree86/ddc/ddc.c b/xorg-server/hw/xfree86/ddc/ddc.c index 6fad9fbbc..ec6465818 100644 --- a/xorg-server/hw/xfree86/ddc/ddc.c +++ b/xorg-server/hw/xfree86/ddc/ddc.c @@ -1,507 +1,507 @@ -/* xf86DDC.c - * - * Copyright 1998,1999 by Egbert Eich - */ - -/* - * A note on terminology. DDC1 is the original dumb serial protocol, and - * can only do up to 128 bytes of EDID. DDC2 is I2C-encapsulated and - * introduces extension blocks. EDID is the old display identification - * block, DisplayID is the new one. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#include "xf86DDC.h" -#include - -#define RETRIES 4 - -typedef enum { - DDCOPT_NODDC1, - DDCOPT_NODDC2, - DDCOPT_NODDC -} DDCOpts; - -static const OptionInfoRec DDCOptions[] = { - { DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE }, - { DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE }, - { DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -/* DDC1 */ - -static int -find_start(unsigned int *ptr) -{ - unsigned int comp[9], test[9]; - int i,j; - - for (i=0;i<9;i++){ - comp[i] = *(ptr++); - test[i] = 1; - } - for (i=0;i<127;i++){ - for (j=0;j<9;j++){ - test[j] = test[j] & !(comp[j] ^ *(ptr++)); - } - } - for (i=0;i<9;i++) - if (test[i]) return (i+1); - return (-1); -} - -static unsigned char * -find_header(unsigned char *block) -{ - unsigned char *ptr, *head_ptr, *end; - unsigned char header[]={0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; - - ptr = block; - end = block + EDID1_LEN; - while (ptrscrnIndex, X_PROBED, - "chipset doesn't support DDC1\n"); - return NULL; - }; - - if (TestDDC1(pScrn,read_DDC)==-1) { - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); - return NULL; - }; - - if (DDCSpeed) DDCSpeed(pScrn,DDC_FAST); - do { - EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn,read_DDC)); - count --; - } while (!EDID_block && count); - if (DDCSpeed) DDCSpeed(pScrn,DDC_SLOW); - - return EDID_block; -} - -/** - * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are - * unset. EDID information blocks are interpreted and the results returned in - * an xf86MonPtr. - * - * This function does not affect the list of modes used by drivers -- it is up - * to the driver to decide policy on what to do with EDID information. - * - * @return pointer to a new xf86MonPtr containing the EDID information. - * @return NULL if no monitor attached or failure to interpret the EDID. - */ -xf86MonPtr -xf86DoEDID_DDC1( - int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed, - unsigned int (*DDC1Read)(ScrnInfoPtr) -) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - unsigned char *EDID_block = NULL; - xf86MonPtr tmp = NULL; - int sigio; - /* Default DDC and DDC1 to enabled. */ - Bool noddc = FALSE, noddc1 = FALSE; - OptionInfoPtr options; - - options = xnfalloc(sizeof(DDCOptions)); - (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); - - xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); - xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); - xfree(options); - - if (noddc || noddc1) - return NULL; - - sigio = xf86BlockSIGIO(); - EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); - xf86UnblockSIGIO(sigio); - - if (EDID_block){ - tmp = xf86InterpretEDID(scrnIndex,EDID_block); - } -#ifdef DEBUG - else ErrorF("No EDID block returned\n"); - if (!tmp) - ErrorF("Cannot interpret EDID block\n"); -#endif - return tmp; -} - -/* DDC2 */ - -static I2CDevPtr -DDC2MakeDevice(I2CBusPtr pBus, int address, char *name) -{ - I2CDevPtr dev = NULL; - - if (!(dev = xf86I2CFindDev(pBus, address))) { - dev = xf86CreateI2CDevRec(); - dev->DevName = name; - dev->SlaveAddr = address; - dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ - dev->StartTimeout = 550; - dev->BitTimeout = 40; - dev->AcknTimeout = 40; - - dev->pI2CBus = pBus; - if (!xf86I2CDevInit(dev)) { - xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); - return NULL; - } - } - - return dev; -} - -static I2CDevPtr -DDC2Init(int scrnIndex, I2CBusPtr pBus) -{ - I2CDevPtr dev = NULL; - - /* - * Slow down the bus so that older monitors don't - * miss things. - */ - pBus->RiseFallTime = 20; - - dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2"); - if (xf86I2CProbeAddress(pBus, 0x0060)) - DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); - if (xf86I2CProbeAddress(pBus, 0x0062)) - DDC2MakeDevice(pBus, 0x0062, "EDID EEPROM interface"); - if (xf86I2CProbeAddress(pBus, 0x006E)) - DDC2MakeDevice(pBus, 0x006E, "DDC control interface"); - - return dev; -} - -/* Mmmm, smell the hacks */ -static void -EEDIDStop(I2CDevPtr d) -{ -} - -/* block is the EDID block number. a segment is two blocks. */ -static Bool -DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) -{ - unsigned char W_Buffer[1]; - int i, segment; - I2CDevPtr seg; - void (*stop)(I2CDevPtr); - - for (i = 0; i < RETRIES; i++) { - /* Stop bits reset the segment pointer to 0, so be careful here. */ - segment = block >> 1; - if (segment) { - Bool b; - - if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) - return FALSE; - - W_Buffer[0] = segment; - - stop = dev->pI2CBus->I2CStop; - dev->pI2CBus->I2CStop = EEDIDStop; - - b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); - - dev->pI2CBus->I2CStop = stop; - if (!b) { - dev->pI2CBus->I2CStop(dev); - continue; - } - } - - W_Buffer[0] = (block & 0x01) * EDID1_LEN; - - if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { - if (!DDC_checksum(R_Buffer, EDID1_LEN)) - return TRUE; - } - } - - return FALSE; -} - -/** - * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are - * unset. EDID information blocks are interpreted and the results returned in - * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return - * the complete EDID data, including all extension blocks, if the 'complete' - * parameter is TRUE; - * - * This function does not affect the list of modes used by drivers -- it is up - * to the driver to decide policy on what to do with EDID information. - * - * @return pointer to a new xf86MonPtr containing the EDID information. - * @return NULL if no monitor attached or failure to interpret the EDID. - */ -xf86MonPtr -xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - unsigned char *EDID_block = NULL; - xf86MonPtr tmp = NULL; - I2CDevPtr dev = NULL; - /* Default DDC and DDC2 to enabled. */ - Bool noddc = FALSE, noddc2 = FALSE; - OptionInfoPtr options; - - options = xalloc(sizeof(DDCOptions)); - if (!options) - return NULL; - memcpy(options, DDCOptions, sizeof(DDCOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); - - xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); - xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); - xfree(options); - - if (noddc || noddc2) - return NULL; - - if (!(dev = DDC2Init(scrnIndex, pBus))) - return NULL; - - EDID_block = xcalloc(1, EDID1_LEN); - if (!EDID_block) - return NULL; - - if (DDC2Read(dev, 0, EDID_block)) { - int i, n = EDID_block[0x7e]; - - if (complete && n) { - EDID_block = xrealloc(EDID_block, EDID1_LEN * (1+n)); - - for (i = 0; i < n; i++) - DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i))); - } - - tmp = xf86InterpretEEDID(scrnIndex, EDID_block); - } - - if (tmp && complete) - tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA; - - return tmp; -} - -/** - * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are - * unset. EDID information blocks are interpreted and the results returned in - * an xf86MonPtr. - * - * This function does not affect the list of modes used by drivers -- it is up - * to the driver to decide policy on what to do with EDID information. - * - * @return pointer to a new xf86MonPtr containing the EDID information. - * @return NULL if no monitor attached or failure to interpret the EDID. - */ -xf86MonPtr -xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) -{ - return xf86DoEEDID(scrnIndex, pBus, FALSE); -} - -/* XXX write me */ -static void * -DDC2ReadDisplayID(void) -{ - return FALSE; -} - -/** - * Attempts to probe the monitor for DisplayID information, if NoDDC and - * NoDDC2 are unset. DisplayID blocks are interpreted and the results - * returned in an xf86MonPtr. - * - * This function does not affect the list of modes used by drivers -- it is up - * to the driver to decide policy on what to do with DisplayID information. - * - * @return pointer to a new xf86MonPtr containing the DisplayID information. - * @return NULL if no monitor attached or failure to interpret the DisplayID. - */ -xf86MonPtr -xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - unsigned char *did = NULL; - xf86MonPtr tmp = NULL; - I2CDevPtr dev = NULL; - /* Default DDC and DDC2 to enabled. */ - Bool noddc = FALSE, noddc2 = FALSE; - OptionInfoPtr options; - - options = xalloc(sizeof(DDCOptions)); - if (!options) - return NULL; - memcpy(options, DDCOptions, sizeof(DDCOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); - - xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); - xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); - xfree(options); - - if (noddc || noddc2) - return NULL; - - if (!(dev = DDC2Init(scrnIndex, pBus))) - return NULL; - - if ((did = DDC2ReadDisplayID())) { - tmp = xcalloc(1, sizeof(*tmp)); - if (!tmp) - return NULL; - - tmp->scrnIndex = scrnIndex; - tmp->flags |= MONITOR_DISPLAYID; - tmp->rawData = did; - } - - return tmp; -} +/* xf86DDC.c + * + * Copyright 1998,1999 by Egbert Eich + */ + +/* + * A note on terminology. DDC1 is the original dumb serial protocol, and + * can only do up to 128 bytes of EDID. DDC2 is I2C-encapsulated and + * introduces extension blocks. EDID is the old display identification + * block, DisplayID is the new one. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86DDC.h" +#include + +#define RETRIES 4 + +typedef enum { + DDCOPT_NODDC1, + DDCOPT_NODDC2, + DDCOPT_NODDC +} DDCOpts; + +static const OptionInfoRec DDCOptions[] = { + { DDCOPT_NODDC1, "NoDDC1", OPTV_BOOLEAN, {0}, FALSE }, + { DDCOPT_NODDC2, "NoDDC2", OPTV_BOOLEAN, {0}, FALSE }, + { DDCOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +/* DDC1 */ + +static int +find_start(unsigned int *ptr) +{ + unsigned int comp[9], test[9]; + int i,j; + + for (i=0;i<9;i++){ + comp[i] = *(ptr++); + test[i] = 1; + } + for (i=0;i<127;i++){ + for (j=0;j<9;j++){ + test[j] = test[j] & !(comp[j] ^ *(ptr++)); + } + } + for (i=0;i<9;i++) + if (test[i]) return (i+1); + return (-1); +} + +static unsigned char * +find_header(unsigned char *block) +{ + unsigned char *ptr, *head_ptr, *end; + unsigned char header[]={0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; + + ptr = block; + end = block + EDID1_LEN; + while (ptrscrnIndex, X_PROBED, + "chipset doesn't support DDC1\n"); + return NULL; + }; + + if (TestDDC1(pScrn,read_DDC)==-1) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No DDC signal\n"); + return NULL; + }; + + if (DDCSpeed) DDCSpeed(pScrn,DDC_FAST); + do { + EDID_block = GetEDID_DDC1(FetchEDID_DDC1(pScrn,read_DDC)); + count --; + } while (!EDID_block && count); + if (DDCSpeed) DDCSpeed(pScrn,DDC_SLOW); + + return EDID_block; +} + +/** + * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC1 are + * unset. EDID information blocks are interpreted and the results returned in + * an xf86MonPtr. + * + * This function does not affect the list of modes used by drivers -- it is up + * to the driver to decide policy on what to do with EDID information. + * + * @return pointer to a new xf86MonPtr containing the EDID information. + * @return NULL if no monitor attached or failure to interpret the EDID. + */ +xf86MonPtr +xf86DoEDID_DDC1( + int scrnIndex, DDC1SetSpeedProc DDC1SetSpeed, + unsigned int (*DDC1Read)(ScrnInfoPtr) +) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + unsigned char *EDID_block = NULL; + xf86MonPtr tmp = NULL; + int sigio; + /* Default DDC and DDC1 to enabled. */ + Bool noddc = FALSE, noddc1 = FALSE; + OptionInfoPtr options; + + options = xnfalloc(sizeof(DDCOptions)); + (void)memcpy(options, DDCOptions, sizeof(DDCOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); + xf86GetOptValBool(options, DDCOPT_NODDC1, &noddc1); + free(options); + + if (noddc || noddc1) + return NULL; + + sigio = xf86BlockSIGIO(); + EDID_block = EDIDRead_DDC1(pScrn,DDC1SetSpeed,DDC1Read); + xf86UnblockSIGIO(sigio); + + if (EDID_block){ + tmp = xf86InterpretEDID(scrnIndex,EDID_block); + } +#ifdef DEBUG + else ErrorF("No EDID block returned\n"); + if (!tmp) + ErrorF("Cannot interpret EDID block\n"); +#endif + return tmp; +} + +/* DDC2 */ + +static I2CDevPtr +DDC2MakeDevice(I2CBusPtr pBus, int address, char *name) +{ + I2CDevPtr dev = NULL; + + if (!(dev = xf86I2CFindDev(pBus, address))) { + dev = xf86CreateI2CDevRec(); + dev->DevName = name; + dev->SlaveAddr = address; + dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ + dev->StartTimeout = 550; + dev->BitTimeout = 40; + dev->AcknTimeout = 40; + + dev->pI2CBus = pBus; + if (!xf86I2CDevInit(dev)) { + xf86DrvMsg(pBus->scrnIndex, X_PROBED, "No DDC2 device\n"); + return NULL; + } + } + + return dev; +} + +static I2CDevPtr +DDC2Init(int scrnIndex, I2CBusPtr pBus) +{ + I2CDevPtr dev = NULL; + + /* + * Slow down the bus so that older monitors don't + * miss things. + */ + pBus->RiseFallTime = 20; + + dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2"); + if (xf86I2CProbeAddress(pBus, 0x0060)) + DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register"); + if (xf86I2CProbeAddress(pBus, 0x0062)) + DDC2MakeDevice(pBus, 0x0062, "EDID EEPROM interface"); + if (xf86I2CProbeAddress(pBus, 0x006E)) + DDC2MakeDevice(pBus, 0x006E, "DDC control interface"); + + return dev; +} + +/* Mmmm, smell the hacks */ +static void +EEDIDStop(I2CDevPtr d) +{ +} + +/* block is the EDID block number. a segment is two blocks. */ +static Bool +DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer) +{ + unsigned char W_Buffer[1]; + int i, segment; + I2CDevPtr seg; + void (*stop)(I2CDevPtr); + + for (i = 0; i < RETRIES; i++) { + /* Stop bits reset the segment pointer to 0, so be careful here. */ + segment = block >> 1; + if (segment) { + Bool b; + + if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060))) + return FALSE; + + W_Buffer[0] = segment; + + stop = dev->pI2CBus->I2CStop; + dev->pI2CBus->I2CStop = EEDIDStop; + + b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0); + + dev->pI2CBus->I2CStop = stop; + if (!b) { + dev->pI2CBus->I2CStop(dev); + continue; + } + } + + W_Buffer[0] = (block & 0x01) * EDID1_LEN; + + if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) { + if (!DDC_checksum(R_Buffer, EDID1_LEN)) + return TRUE; + } + } + + return FALSE; +} + +/** + * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are + * unset. EDID information blocks are interpreted and the results returned in + * an xf86MonPtr. Unlike xf86DoEDID_DDC[12](), this function will return + * the complete EDID data, including all extension blocks, if the 'complete' + * parameter is TRUE; + * + * This function does not affect the list of modes used by drivers -- it is up + * to the driver to decide policy on what to do with EDID information. + * + * @return pointer to a new xf86MonPtr containing the EDID information. + * @return NULL if no monitor attached or failure to interpret the EDID. + */ +xf86MonPtr +xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, Bool complete) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + unsigned char *EDID_block = NULL; + xf86MonPtr tmp = NULL; + I2CDevPtr dev = NULL; + /* Default DDC and DDC2 to enabled. */ + Bool noddc = FALSE, noddc2 = FALSE; + OptionInfoPtr options; + + options = malloc(sizeof(DDCOptions)); + if (!options) + return NULL; + memcpy(options, DDCOptions, sizeof(DDCOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); + xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); + free(options); + + if (noddc || noddc2) + return NULL; + + if (!(dev = DDC2Init(scrnIndex, pBus))) + return NULL; + + EDID_block = calloc(1, EDID1_LEN); + if (!EDID_block) + return NULL; + + if (DDC2Read(dev, 0, EDID_block)) { + int i, n = EDID_block[0x7e]; + + if (complete && n) { + EDID_block = realloc(EDID_block, EDID1_LEN * (1+n)); + + for (i = 0; i < n; i++) + DDC2Read(dev, i+1, EDID_block + (EDID1_LEN * (1+i))); + } + + tmp = xf86InterpretEEDID(scrnIndex, EDID_block); + } + + if (tmp && complete) + tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA; + + return tmp; +} + +/** + * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are + * unset. EDID information blocks are interpreted and the results returned in + * an xf86MonPtr. + * + * This function does not affect the list of modes used by drivers -- it is up + * to the driver to decide policy on what to do with EDID information. + * + * @return pointer to a new xf86MonPtr containing the EDID information. + * @return NULL if no monitor attached or failure to interpret the EDID. + */ +xf86MonPtr +xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus) +{ + return xf86DoEEDID(scrnIndex, pBus, FALSE); +} + +/* XXX write me */ +static void * +DDC2ReadDisplayID(void) +{ + return FALSE; +} + +/** + * Attempts to probe the monitor for DisplayID information, if NoDDC and + * NoDDC2 are unset. DisplayID blocks are interpreted and the results + * returned in an xf86MonPtr. + * + * This function does not affect the list of modes used by drivers -- it is up + * to the driver to decide policy on what to do with DisplayID information. + * + * @return pointer to a new xf86MonPtr containing the DisplayID information. + * @return NULL if no monitor attached or failure to interpret the DisplayID. + */ +xf86MonPtr +xf86DoDisplayID(int scrnIndex, I2CBusPtr pBus) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + unsigned char *did = NULL; + xf86MonPtr tmp = NULL; + I2CDevPtr dev = NULL; + /* Default DDC and DDC2 to enabled. */ + Bool noddc = FALSE, noddc2 = FALSE; + OptionInfoPtr options; + + options = malloc(sizeof(DDCOptions)); + if (!options) + return NULL; + memcpy(options, DDCOptions, sizeof(DDCOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + xf86GetOptValBool(options, DDCOPT_NODDC, &noddc); + xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2); + free(options); + + if (noddc || noddc2) + return NULL; + + if (!(dev = DDC2Init(scrnIndex, pBus))) + return NULL; + + if ((did = DDC2ReadDisplayID())) { + tmp = calloc(1, sizeof(*tmp)); + if (!tmp) + return NULL; + + tmp->scrnIndex = scrnIndex; + tmp->flags |= MONITOR_DISPLAYID; + tmp->rawData = did; + } + + return tmp; +} diff --git a/xorg-server/hw/xfree86/ddc/ddcProperty.c b/xorg-server/hw/xfree86/ddc/ddcProperty.c index 329a63964..d4ae1006d 100644 --- a/xorg-server/hw/xfree86/ddc/ddcProperty.c +++ b/xorg-server/hw/xfree86/ddc/ddcProperty.c @@ -1,125 +1,125 @@ -/* - * Copyright 2006 Luc Verhaegen. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86DDC.h" -#include -#include "property.h" -#include "propertyst.h" -#include "xf86DDC.h" -#include - -#define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA" -#define EDID2_ATOM_NAME "XFree86_DDC_EDID2_RAWDATA" - -static void -edidMakeAtom(int i, const char *name, CARD8 *data, int size) -{ - Atom atom; - unsigned char *atom_data; - - if (!(atom_data = xalloc(size*sizeof(CARD8)))) - return; - - atom = MakeAtom(name, strlen(name), TRUE); - memcpy(atom_data, data, size); - xf86RegisterRootWindowProperty(i, atom, XA_INTEGER, 8, size, atom_data); -} - -static void -addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) -{ - int i, scrnIndex = pScrn->scrnIndex; - Bool makeEDID1prop = FALSE; - Bool makeEDID2prop = FALSE; - - if (DDC->flags & MONITOR_DISPLAYID) { - /* Don't bother, use RANDR already */ - return; - } else if (DDC->ver.version == 1) { - makeEDID1prop = TRUE; - } else if (DDC->ver.version == 2) { - int checksum1; - int checksum2; - makeEDID2prop = TRUE; - - /* Some monitors (eg Panasonic PanaSync4) - * report version==2 because they used EDID v2 spec document, - * although they use EDID v1 data structure :-( - * - * Try using checksum to determine when we have such a monitor. - */ - checksum2 = 0; - for (i = 0; i < 256; i++) - checksum2 += DDC->rawData[i]; - if (checksum2 % 256) { - xf86DrvMsg(scrnIndex, X_INFO, "Monitor EDID v2 checksum failed\n"); - xf86DrvMsg(scrnIndex, X_INFO, - "XFree86_DDC_EDID2_RAWDATA property may be bad\n"); - checksum1 = 0; - for (i = 0; i < 128; i++) - checksum1 += DDC->rawData[i]; - if (!(checksum1 % 256)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Monitor EDID v1 checksum passed,\n"); - xf86DrvMsg(scrnIndex, X_INFO, - "XFree86_DDC_EDID1_RAWDATA property created\n"); - makeEDID1prop = TRUE; - } - } - } else { - xf86DrvMsg(scrnIndex, X_PROBED, "unexpected EDID version %d.%d\n", - DDC->ver.version, DDC->ver.revision); - return; - } - - if (makeEDID1prop) { - int size = 128 + - (DDC->flags & EDID_COMPLETE_RAWDATA ? DDC->no_sections * 128 : 0); - - edidMakeAtom(scrnIndex, EDID1_ATOM_NAME, DDC->rawData, size); - } - - if (makeEDID2prop) - edidMakeAtom(scrnIndex, EDID2_ATOM_NAME, DDC->rawData, 256); -} - -Bool -xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) -{ - if (!pScrn || !pScrn->monitor || !DDC) - return FALSE; - - if (DDC->flags & MONITOR_DISPLAYID) - ; - else - xf86EdidMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC); - - addRootWindowProperties(pScrn, DDC); - - return TRUE; -} +/* + * Copyright 2006 Luc Verhaegen. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86DDC.h" +#include +#include "property.h" +#include "propertyst.h" +#include "xf86DDC.h" +#include + +#define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA" +#define EDID2_ATOM_NAME "XFree86_DDC_EDID2_RAWDATA" + +static void +edidMakeAtom(int i, const char *name, CARD8 *data, int size) +{ + Atom atom; + unsigned char *atom_data; + + if (!(atom_data = malloc(size*sizeof(CARD8)))) + return; + + atom = MakeAtom(name, strlen(name), TRUE); + memcpy(atom_data, data, size); + xf86RegisterRootWindowProperty(i, atom, XA_INTEGER, 8, size, atom_data); +} + +static void +addRootWindowProperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) +{ + int i, scrnIndex = pScrn->scrnIndex; + Bool makeEDID1prop = FALSE; + Bool makeEDID2prop = FALSE; + + if (DDC->flags & MONITOR_DISPLAYID) { + /* Don't bother, use RANDR already */ + return; + } else if (DDC->ver.version == 1) { + makeEDID1prop = TRUE; + } else if (DDC->ver.version == 2) { + int checksum1; + int checksum2; + makeEDID2prop = TRUE; + + /* Some monitors (eg Panasonic PanaSync4) + * report version==2 because they used EDID v2 spec document, + * although they use EDID v1 data structure :-( + * + * Try using checksum to determine when we have such a monitor. + */ + checksum2 = 0; + for (i = 0; i < 256; i++) + checksum2 += DDC->rawData[i]; + if (checksum2 % 256) { + xf86DrvMsg(scrnIndex, X_INFO, "Monitor EDID v2 checksum failed\n"); + xf86DrvMsg(scrnIndex, X_INFO, + "XFree86_DDC_EDID2_RAWDATA property may be bad\n"); + checksum1 = 0; + for (i = 0; i < 128; i++) + checksum1 += DDC->rawData[i]; + if (!(checksum1 % 256)) { + xf86DrvMsg(scrnIndex, X_INFO, + "Monitor EDID v1 checksum passed,\n"); + xf86DrvMsg(scrnIndex, X_INFO, + "XFree86_DDC_EDID1_RAWDATA property created\n"); + makeEDID1prop = TRUE; + } + } + } else { + xf86DrvMsg(scrnIndex, X_PROBED, "unexpected EDID version %d.%d\n", + DDC->ver.version, DDC->ver.revision); + return; + } + + if (makeEDID1prop) { + int size = 128 + + (DDC->flags & EDID_COMPLETE_RAWDATA ? DDC->no_sections * 128 : 0); + + edidMakeAtom(scrnIndex, EDID1_ATOM_NAME, DDC->rawData, size); + } + + if (makeEDID2prop) + edidMakeAtom(scrnIndex, EDID2_ATOM_NAME, DDC->rawData, 256); +} + +Bool +xf86SetDDCproperties(ScrnInfoPtr pScrn, xf86MonPtr DDC) +{ + if (!pScrn || !pScrn->monitor || !DDC) + return FALSE; + + if (DDC->flags & MONITOR_DISPLAYID) + ; + else + xf86EdidMonitorSet(pScrn->scrnIndex, pScrn->monitor, DDC); + + addRootWindowProperties(pScrn, DDC); + + return TRUE; +} diff --git a/xorg-server/hw/xfree86/ddc/interpret_edid.c b/xorg-server/hw/xfree86/ddc/interpret_edid.c index f3e593aec..1a2d2f487 100644 --- a/xorg-server/hw/xfree86/ddc/interpret_edid.c +++ b/xorg-server/hw/xfree86/ddc/interpret_edid.c @@ -1,685 +1,685 @@ -/* - * Copyright 1998 by Egbert Eich - * Copyright 2007 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * interpret_edid.c: interpret a primary EDID block - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#define _PARSE_EDID_ -#include "xf86DDC.h" -#include - -static void get_vendor_section(Uchar*, struct vendor *); -static void get_version_section(Uchar*, struct edid_version *); -static void get_display_section(Uchar*, struct disp_features *, - struct edid_version *); -static void get_established_timing_section(Uchar*, struct established_timings *); -static void get_std_timing_section(Uchar*, struct std_timings *, - struct edid_version *); -static void fetch_detailed_block(Uchar *c, struct edid_version *ver, - struct detailed_monitor_section *det_mon); -static void get_dt_md_section(Uchar *, struct edid_version *, - struct detailed_monitor_section *det_mon); -static void copy_string(Uchar *, Uchar *); -static void get_dst_timing_section(Uchar *, struct std_timings *, - struct edid_version *); -static void get_monitor_ranges(Uchar *, struct monitor_ranges *); -static void get_whitepoint_section(Uchar *, struct whitePoints *); -static void get_detailed_timing_section(Uchar*, struct detailed_timings *); -static Bool validate_version(int scrnIndex, struct edid_version *); - -static void -find_ranges_section(struct detailed_monitor_section *det, void *ranges) -{ - if (det->type == DS_RANGES && det->section.ranges.max_clock) - *(struct monitor_ranges **)ranges = &det->section.ranges; -} - -static void -find_max_detailed_clock(struct detailed_monitor_section *det, void *ret) -{ - if (det->type == DT) { - *(int *)ret = max(*((int *)ret), - det->section.d_timings.clock); - } -} - -static void -handle_edid_quirks(xf86MonPtr m) -{ - struct monitor_ranges *ranges = NULL; - - /* - * max_clock is only encoded in EDID in tens of MHz, so occasionally we - * find a monitor claiming a max of 160 with a mode requiring 162, or - * similar. Strictly we should refuse to round up too far, but let's - * see how well this works. - */ - - /* Try to find Monitor Range and max clock, then re-set range value*/ - xf86ForEachDetailedBlock(m, find_ranges_section, &ranges); - if (ranges && ranges->max_clock) { - int clock = 0; - xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock); - if (clock && (ranges->max_clock * 1e6 < clock)) { - xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max " - "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock); - ranges->max_clock = (clock+999999)/1e6; - } - } -} - -struct det_hv_parameter { - int real_hsize; - int real_vsize; - float target_aspect; -}; - -static void handle_detailed_hvsize(struct detailed_monitor_section *det_mon, - void *data) -{ - struct det_hv_parameter *p = (struct det_hv_parameter *)data; - float timing_aspect; - - if (det_mon->type == DT) { - struct detailed_timings *timing; - timing = &det_mon->section.d_timings; - - if (!timing->v_size) - return; - - timing_aspect = (float)timing->h_size / timing->v_size; - if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) { - p->real_hsize = max(p->real_hsize, timing->h_size); - p->real_vsize = max(p->real_vsize, timing->v_size); - } - } -} - -static void encode_aspect_ratio(xf86MonPtr m) -{ - /* - * some monitors encode the aspect ratio instead of the physical size. - * try to find the largest detailed timing that matches that aspect - * ratio and use that to fill in the feature section. - */ - if ((m->features.hsize == 16 && m->features.vsize == 9) || - (m->features.hsize == 16 && m->features.vsize == 10) || - (m->features.hsize == 4 && m->features.vsize == 3) || - (m->features.hsize == 5 && m->features.vsize == 4)) { - - struct det_hv_parameter p; - p.real_hsize = 0; - p.real_vsize = 0; - p.target_aspect = (float)m->features.hsize /m->features.vsize; - - xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p); - - if (!p.real_hsize || !p.real_vsize) { - m->features.hsize = m->features.vsize = 0; - } else if ((m->features.hsize * 10 == p.real_hsize) && - (m->features.vsize * 10 == p.real_vsize)) { - /* exact match is just unlikely, should do a better check though */ - m->features.hsize = m->features.vsize = 0; - } else { - /* convert mm to cm */ - m->features.hsize = (p.real_hsize + 5) / 10; - m->features.vsize = (p.real_vsize + 5) / 10; - } - - xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n", - m->features.hsize, m->features.vsize); - } -} - -xf86MonPtr -xf86InterpretEDID(int scrnIndex, Uchar *block) -{ - xf86MonPtr m; - - if (!block) return NULL; - if (! (m = xnfcalloc(sizeof(xf86Monitor),1))) return NULL; - m->scrnIndex = scrnIndex; - m->rawData = block; - - get_vendor_section(SECTION(VENDOR_SECTION,block),&m->vendor); - get_version_section(SECTION(VERSION_SECTION,block),&m->ver); - if (!validate_version(scrnIndex, &m->ver)) goto error; - get_display_section(SECTION(DISPLAY_SECTION,block),&m->features, - &m->ver); - get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION,block), - &m->timings1); - get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2, - &m->ver); - get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon); - m->no_sections = (int)*(char *)SECTION(NO_EDID,block); - - handle_edid_quirks(m); - encode_aspect_ratio(m); - - return (m); - - error: - xfree(m); - return NULL; -} - -static int get_cea_detail_timing(Uchar *blk, xf86MonPtr mon, - struct detailed_monitor_section *det_mon) -{ - int dt_num; - int dt_offset = ((struct cea_ext_body *)blk)->dt_offset; - - dt_num = 0; - - if (dt_offset < CEA_EXT_MIN_DATA_OFFSET) - return dt_num; - - for (; dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) && - dt_num < CEA_EXT_DET_TIMING_NUM; - _NEXT_DT_MD_SECTION(dt_offset)) { - - fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + dt_num); - dt_num = dt_num + 1 ; - } - - return dt_num; -} - -static void handle_cea_detail_block(Uchar *ext, xf86MonPtr mon, - handle_detailed_fn fn, - void *data) -{ - int i; - struct detailed_monitor_section det_mon[CEA_EXT_DET_TIMING_NUM]; - int det_mon_num; - - det_mon_num = get_cea_detail_timing(ext, mon, det_mon); - - for (i = 0; i < det_mon_num; i++) - fn(det_mon + i, data); -} - -void xf86ForEachDetailedBlock(xf86MonPtr mon, - handle_detailed_fn fn, - void *data) -{ - int i; - Uchar *ext; - - if (mon == NULL) - return; - - for (i = 0; i < DET_TIMINGS; i++) - fn(mon->det_mon + i, data); - - for (i = 0; i < mon->no_sections; i++) { - ext = mon->rawData + EDID1_LEN * (i + 1); - switch (ext[EXT_TAG]){ - case CEA_EXT: - handle_cea_detail_block(ext, mon, fn, data); - break; - case VTB_EXT: - case DI_EXT: - case LS_EXT: - case MI_EXT: - break; - } - } -} - -static struct cea_data_block * -extract_cea_data_block(Uchar *ext, int data_type) -{ - struct cea_ext_body *cea; - struct cea_data_block *data_collection; - struct cea_data_block *data_end; - - cea = (struct cea_ext_body *)ext; - - if (cea->dt_offset <= CEA_EXT_MIN_DATA_OFFSET) - return NULL; - - data_collection = &cea->data_collection; - data_end = (struct cea_data_block *)(cea->dt_offset + ext); - - for ( ;data_collection < data_end;) { - - if (data_type == data_collection->tag) { - return data_collection; - } - data_collection = (void *)((unsigned char *)data_collection + - data_collection->len + 1); - } - - return NULL; -} - -static void handle_cea_video_block(Uchar *ext, handle_video_fn fn, void *data) -{ - struct cea_video_block *video; - struct cea_video_block *video_end; - struct cea_data_block *data_collection; - - data_collection = extract_cea_data_block(ext, CEA_VIDEO_BLK); - if (data_collection == NULL) - return; - - video = &data_collection->u.video; - video_end = (struct cea_video_block *) - ((Uchar *)video + data_collection->len); - - for (; video < video_end; video = video + 1) { - fn(video, data); - } -} - -void xf86ForEachVideoBlock(xf86MonPtr mon, - handle_video_fn fn, - void *data) -{ - int i; - Uchar *ext; - - if (mon == NULL) - return; - - for (i = 0; i < mon->no_sections; i++) { - ext = mon->rawData + EDID1_LEN * (i + 1); - switch (ext[EXT_TAG]) { - case CEA_EXT: - handle_cea_video_block(ext, fn, data); - break; - case VTB_EXT: - case DI_EXT: - case LS_EXT: - case MI_EXT: - break; - } - } -} - -xf86MonPtr -xf86InterpretEEDID(int scrnIndex, Uchar *block) -{ - xf86MonPtr m; - - m = xf86InterpretEDID(scrnIndex, block); - if (!m) - return NULL; - - /* extension parse */ - - return m; -} - -static void -get_vendor_section(Uchar *c, struct vendor *r) -{ - r->name[0] = L1; - r->name[1] = L2; - r->name[2] = L3; - r->name[3] = '\0'; - - r->prod_id = PROD_ID; - r->serial = SERIAL_NO; - r->week = WEEK; - r->year = YEAR; -} - -static void -get_version_section(Uchar *c, struct edid_version *r) -{ - r->version = VERSION; - r->revision = REVISION; -} - -static void -get_display_section(Uchar *c, struct disp_features *r, - struct edid_version *v) -{ - r->input_type = INPUT_TYPE; - if (!DIGITAL(r->input_type)) { - r->input_voltage = INPUT_VOLTAGE; - r->input_setup = SETUP; - r->input_sync = SYNC; - } else if (v->revision == 2 || v->revision == 3) { - r->input_dfp = DFP; - } else if (v->revision >= 4) { - r->input_bpc = BPC; - r->input_interface = DIGITAL_INTERFACE; - } - r->hsize = HSIZE_MAX; - r->vsize = VSIZE_MAX; - r->gamma = GAMMA; - r->dpms = DPMS; - r->display_type = DISPLAY_TYPE; - r->msc = MSC; - r->redx = REDX; - r->redy = REDY; - r->greenx = GREENX; - r->greeny = GREENY; - r->bluex = BLUEX; - r->bluey = BLUEY; - r->whitex = WHITEX; - r->whitey = WHITEY; -} - -static void -get_established_timing_section(Uchar *c, struct established_timings *r) -{ - r->t1 = T1; - r->t2 = T2; - r->t_manu = T_MANU; -} - -static void -get_cvt_timing_section(Uchar *c, struct cvt_timings *r) -{ - int i; - - for (i = 0; i < 4; i++) { - if (c[0] && c[1] && c[2]) { - r[i].height = (c[0] + ((c[1] & 0xF0) << 8) + 1) * 2; - switch (c[1] & 0xc0) { - case 0x00: r[i].width = r[i].height * 4 / 3; break; - case 0x40: r[i].width = r[i].height * 16 / 9; break; - case 0x80: r[i].width = r[i].height * 16 / 10; break; - case 0xc0: r[i].width = r[i].height * 15 / 9; break; - } - switch (c[2] & 0x60) { - case 0x00: r[i].rate = 50; break; - case 0x20: r[i].rate = 60; break; - case 0x40: r[i].rate = 75; break; - case 0x60: r[i].rate = 85; break; - } - r[i].rates = c[2] & 0x1f; - } else { - return; - } - c += 3; - } -} - -static void -get_std_timing_section(Uchar *c, struct std_timings *r, - struct edid_version *v) -{ - int i; - - for (i=0;iversion == 1 && ver->revision >= 1 && IS_MONITOR_DESC) { - switch (MONITOR_DESC_TYPE) { - case SERIAL_NUMBER: - det_mon->type = DS_SERIAL; - copy_string(c,det_mon->section.serial); - break; - case ASCII_STR: - det_mon->type = DS_ASCII_STR; - copy_string(c,det_mon->section.ascii_data); - break; - case MONITOR_RANGES: - det_mon->type = DS_RANGES; - get_monitor_ranges(c,&det_mon->section.ranges); - break; - case MONITOR_NAME: - det_mon->type = DS_NAME; - copy_string(c,det_mon->section.name); - break; - case ADD_COLOR_POINT: - det_mon->type = DS_WHITE_P; - get_whitepoint_section(c,det_mon->section.wp); - break; - case ADD_STD_TIMINGS: - det_mon->type = DS_STD_TIMINGS; - get_dst_timing_section(c,det_mon->section.std_t, ver); - break; - case COLOR_MANAGEMENT_DATA: - det_mon->type = DS_CMD; - break; - case CVT_3BYTE_DATA: - det_mon->type = DS_CVT; - get_cvt_timing_section(c, det_mon->section.cvt); - break; - case ADD_EST_TIMINGS: - det_mon->type = DS_EST_III; - memcpy(det_mon->section.est_iii, c + 6, 6); - break; - case ADD_DUMMY: - det_mon->type = DS_DUMMY; - break; - default: - det_mon->type = DS_UNKOWN; - break; - } - if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) { - det_mon->type = DS_VENDOR + c[3]; - } - } else { - det_mon->type = DT; - get_detailed_timing_section(c, &det_mon->section.d_timings); - } -} - -static void -get_dt_md_section(Uchar *c, struct edid_version *ver, - struct detailed_monitor_section *det_mon) -{ - int i; - - for (i=0; i < DET_TIMINGS; i++) { - fetch_detailed_block(c, ver, det_mon + i); - NEXT_DT_MD_SECTION; - } -} - -static void -copy_string(Uchar *c, Uchar *s) -{ - int i; - c = c + 5; - for (i = 0; (i < 13 && *c != 0x0A); i++) - *(s++) = *(c++); - *s = 0; - while (i-- && (*--s == 0x20)) *s = 0; -} - -static void -get_dst_timing_section(Uchar *c, struct std_timings *t, - struct edid_version *v) -{ - int j; - c = c + 5; - for (j = 0; j < 5; j++) { - t[j].hsize = HSIZE1; - VSIZE1(t[j].vsize); - t[j].refresh = REFRESH_R; - t[j].id = STD_TIMING_ID; - NEXT_STD_TIMING; - } -} - -static void -get_monitor_ranges(Uchar *c, struct monitor_ranges *r) -{ - r->min_v = MIN_V; - r->max_v = MAX_V; - r->min_h = MIN_H; - r->max_h = MAX_H; - r->max_clock = 0; - if(MAX_CLOCK != 0xff) /* is specified? */ - r->max_clock = MAX_CLOCK * 10; - if (HAVE_2ND_GTF) { - r->gtf_2nd_f = F_2ND_GTF; - r->gtf_2nd_c = C_2ND_GTF; - r->gtf_2nd_m = M_2ND_GTF; - r->gtf_2nd_k = K_2ND_GTF; - r->gtf_2nd_j = J_2ND_GTF; - } else { - r->gtf_2nd_f = 0; - } - if (HAVE_CVT) { - r->max_clock_khz = MAX_CLOCK_KHZ; - r->max_clock = r->max_clock_khz / 1000; - r->maxwidth = MAXWIDTH; - r->supported_aspect = SUPPORTED_ASPECT; - r->preferred_aspect = PREFERRED_ASPECT; - r->supported_blanking = SUPPORTED_BLANKING; - r->supported_scaling = SUPPORTED_SCALING; - r->preferred_refresh = PREFERRED_REFRESH; - } else { - r->max_clock_khz = 0; - } -} - -static void -get_whitepoint_section(Uchar *c, struct whitePoints *wp) -{ - wp[0].white_x = WHITEX1; - wp[0].white_y = WHITEY1; - wp[1].white_x = WHITEX2; - wp[1].white_y = WHITEY2; - wp[0].index = WHITE_INDEX1; - wp[1].index = WHITE_INDEX2; - wp[0].white_gamma = WHITE_GAMMA1; - wp[1].white_gamma = WHITE_GAMMA2; -} - -static void -get_detailed_timing_section(Uchar *c, struct detailed_timings *r) -{ - r->clock = PIXEL_CLOCK; - r->h_active = H_ACTIVE; - r->h_blanking = H_BLANK; - r->v_active = V_ACTIVE; - r->v_blanking = V_BLANK; - r->h_sync_off = H_SYNC_OFF; - r->h_sync_width = H_SYNC_WIDTH; - r->v_sync_off = V_SYNC_OFF; - r->v_sync_width = V_SYNC_WIDTH; - r->h_size = H_SIZE; - r->v_size = V_SIZE; - r->h_border = H_BORDER; - r->v_border = V_BORDER; - r->interlaced = INTERLACED; - r->stereo = STEREO; - r->stereo_1 = STEREO1; - r->sync = SYNC_T; - r->misc = MISC; -} - -#define MAX_EDID_MINOR 4 - -static Bool -validate_version(int scrnIndex, struct edid_version *r) -{ - if (r->version != 1) { - xf86DrvMsg(scrnIndex, X_ERROR, "Unknown EDID version %d\n", - r->version); - return FALSE; - } - - if (r->revision > MAX_EDID_MINOR) - xf86DrvMsg(scrnIndex, X_WARNING, - "Assuming version 1.%d is compatible with 1.%d\n", - r->revision, MAX_EDID_MINOR); - - return TRUE; -} - -/* - * Returns true if HDMI, false if definitely not or unknown. - */ -Bool -xf86MonitorIsHDMI(xf86MonPtr mon) -{ - int i = 0, version, offset; - char *edid = NULL; - - if (!mon) - return FALSE; - - if (!(mon->flags & EDID_COMPLETE_RAWDATA)) - return FALSE; - - if (!mon->no_sections) - return FALSE; - - edid = (char *)mon->rawData; - if (!edid) - return FALSE; - - /* find the CEA extension block */ - for (i = 1; i <= mon->no_sections; i++) - if (edid[i * 128] == 0x02) - break; - if (i == mon->no_sections + 1) - return FALSE; - edid += (i * 128); - - version = edid[1]; - offset = edid[2]; - if (version < 3 || offset < 4) - return FALSE; - - /* walk the cea data blocks */ - for (i = 4; i < offset; i += (edid[i] & 0x1f) + 1) { - char *x = edid + i; - - /* find a vendor specific block */ - if ((x[0] & 0xe0) >> 5 == 0x03) { - int oui = (x[3] << 16) + (x[2] << 8) + x[1]; - - /* find the HDMI vendor OUI */ - if (oui == 0x000c03) - return TRUE; - } - } - - /* guess it's not HDMI after all */ - return FALSE; -} +/* + * Copyright 1998 by Egbert Eich + * Copyright 2007 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * interpret_edid.c: interpret a primary EDID block + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#define _PARSE_EDID_ +#include "xf86DDC.h" +#include + +static void get_vendor_section(Uchar*, struct vendor *); +static void get_version_section(Uchar*, struct edid_version *); +static void get_display_section(Uchar*, struct disp_features *, + struct edid_version *); +static void get_established_timing_section(Uchar*, struct established_timings *); +static void get_std_timing_section(Uchar*, struct std_timings *, + struct edid_version *); +static void fetch_detailed_block(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon); +static void get_dt_md_section(Uchar *, struct edid_version *, + struct detailed_monitor_section *det_mon); +static void copy_string(Uchar *, Uchar *); +static void get_dst_timing_section(Uchar *, struct std_timings *, + struct edid_version *); +static void get_monitor_ranges(Uchar *, struct monitor_ranges *); +static void get_whitepoint_section(Uchar *, struct whitePoints *); +static void get_detailed_timing_section(Uchar*, struct detailed_timings *); +static Bool validate_version(int scrnIndex, struct edid_version *); + +static void +find_ranges_section(struct detailed_monitor_section *det, void *ranges) +{ + if (det->type == DS_RANGES && det->section.ranges.max_clock) + *(struct monitor_ranges **)ranges = &det->section.ranges; +} + +static void +find_max_detailed_clock(struct detailed_monitor_section *det, void *ret) +{ + if (det->type == DT) { + *(int *)ret = max(*((int *)ret), + det->section.d_timings.clock); + } +} + +static void +handle_edid_quirks(xf86MonPtr m) +{ + struct monitor_ranges *ranges = NULL; + + /* + * max_clock is only encoded in EDID in tens of MHz, so occasionally we + * find a monitor claiming a max of 160 with a mode requiring 162, or + * similar. Strictly we should refuse to round up too far, but let's + * see how well this works. + */ + + /* Try to find Monitor Range and max clock, then re-set range value*/ + xf86ForEachDetailedBlock(m, find_ranges_section, &ranges); + if (ranges && ranges->max_clock) { + int clock = 0; + xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock); + if (clock && (ranges->max_clock * 1e6 < clock)) { + xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max " + "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock); + ranges->max_clock = (clock+999999)/1e6; + } + } +} + +struct det_hv_parameter { + int real_hsize; + int real_vsize; + float target_aspect; +}; + +static void handle_detailed_hvsize(struct detailed_monitor_section *det_mon, + void *data) +{ + struct det_hv_parameter *p = (struct det_hv_parameter *)data; + float timing_aspect; + + if (det_mon->type == DT) { + struct detailed_timings *timing; + timing = &det_mon->section.d_timings; + + if (!timing->v_size) + return; + + timing_aspect = (float)timing->h_size / timing->v_size; + if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) { + p->real_hsize = max(p->real_hsize, timing->h_size); + p->real_vsize = max(p->real_vsize, timing->v_size); + } + } +} + +static void encode_aspect_ratio(xf86MonPtr m) +{ + /* + * some monitors encode the aspect ratio instead of the physical size. + * try to find the largest detailed timing that matches that aspect + * ratio and use that to fill in the feature section. + */ + if ((m->features.hsize == 16 && m->features.vsize == 9) || + (m->features.hsize == 16 && m->features.vsize == 10) || + (m->features.hsize == 4 && m->features.vsize == 3) || + (m->features.hsize == 5 && m->features.vsize == 4)) { + + struct det_hv_parameter p; + p.real_hsize = 0; + p.real_vsize = 0; + p.target_aspect = (float)m->features.hsize /m->features.vsize; + + xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p); + + if (!p.real_hsize || !p.real_vsize) { + m->features.hsize = m->features.vsize = 0; + } else if ((m->features.hsize * 10 == p.real_hsize) && + (m->features.vsize * 10 == p.real_vsize)) { + /* exact match is just unlikely, should do a better check though */ + m->features.hsize = m->features.vsize = 0; + } else { + /* convert mm to cm */ + m->features.hsize = (p.real_hsize + 5) / 10; + m->features.vsize = (p.real_vsize + 5) / 10; + } + + xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n", + m->features.hsize, m->features.vsize); + } +} + +xf86MonPtr +xf86InterpretEDID(int scrnIndex, Uchar *block) +{ + xf86MonPtr m; + + if (!block) return NULL; + if (! (m = xnfcalloc(sizeof(xf86Monitor),1))) return NULL; + m->scrnIndex = scrnIndex; + m->rawData = block; + + get_vendor_section(SECTION(VENDOR_SECTION,block),&m->vendor); + get_version_section(SECTION(VERSION_SECTION,block),&m->ver); + if (!validate_version(scrnIndex, &m->ver)) goto error; + get_display_section(SECTION(DISPLAY_SECTION,block),&m->features, + &m->ver); + get_established_timing_section(SECTION(ESTABLISHED_TIMING_SECTION,block), + &m->timings1); + get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2, + &m->ver); + get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon); + m->no_sections = (int)*(char *)SECTION(NO_EDID,block); + + handle_edid_quirks(m); + encode_aspect_ratio(m); + + return (m); + + error: + free(m); + return NULL; +} + +static int get_cea_detail_timing(Uchar *blk, xf86MonPtr mon, + struct detailed_monitor_section *det_mon) +{ + int dt_num; + int dt_offset = ((struct cea_ext_body *)blk)->dt_offset; + + dt_num = 0; + + if (dt_offset < CEA_EXT_MIN_DATA_OFFSET) + return dt_num; + + for (; dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) && + dt_num < CEA_EXT_DET_TIMING_NUM; + _NEXT_DT_MD_SECTION(dt_offset)) { + + fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + dt_num); + dt_num = dt_num + 1 ; + } + + return dt_num; +} + +static void handle_cea_detail_block(Uchar *ext, xf86MonPtr mon, + handle_detailed_fn fn, + void *data) +{ + int i; + struct detailed_monitor_section det_mon[CEA_EXT_DET_TIMING_NUM]; + int det_mon_num; + + det_mon_num = get_cea_detail_timing(ext, mon, det_mon); + + for (i = 0; i < det_mon_num; i++) + fn(det_mon + i, data); +} + +void xf86ForEachDetailedBlock(xf86MonPtr mon, + handle_detailed_fn fn, + void *data) +{ + int i; + Uchar *ext; + + if (mon == NULL) + return; + + for (i = 0; i < DET_TIMINGS; i++) + fn(mon->det_mon + i, data); + + for (i = 0; i < mon->no_sections; i++) { + ext = mon->rawData + EDID1_LEN * (i + 1); + switch (ext[EXT_TAG]){ + case CEA_EXT: + handle_cea_detail_block(ext, mon, fn, data); + break; + case VTB_EXT: + case DI_EXT: + case LS_EXT: + case MI_EXT: + break; + } + } +} + +static struct cea_data_block * +extract_cea_data_block(Uchar *ext, int data_type) +{ + struct cea_ext_body *cea; + struct cea_data_block *data_collection; + struct cea_data_block *data_end; + + cea = (struct cea_ext_body *)ext; + + if (cea->dt_offset <= CEA_EXT_MIN_DATA_OFFSET) + return NULL; + + data_collection = &cea->data_collection; + data_end = (struct cea_data_block *)(cea->dt_offset + ext); + + for ( ;data_collection < data_end;) { + + if (data_type == data_collection->tag) { + return data_collection; + } + data_collection = (void *)((unsigned char *)data_collection + + data_collection->len + 1); + } + + return NULL; +} + +static void handle_cea_video_block(Uchar *ext, handle_video_fn fn, void *data) +{ + struct cea_video_block *video; + struct cea_video_block *video_end; + struct cea_data_block *data_collection; + + data_collection = extract_cea_data_block(ext, CEA_VIDEO_BLK); + if (data_collection == NULL) + return; + + video = &data_collection->u.video; + video_end = (struct cea_video_block *) + ((Uchar *)video + data_collection->len); + + for (; video < video_end; video = video + 1) { + fn(video, data); + } +} + +void xf86ForEachVideoBlock(xf86MonPtr mon, + handle_video_fn fn, + void *data) +{ + int i; + Uchar *ext; + + if (mon == NULL) + return; + + for (i = 0; i < mon->no_sections; i++) { + ext = mon->rawData + EDID1_LEN * (i + 1); + switch (ext[EXT_TAG]) { + case CEA_EXT: + handle_cea_video_block(ext, fn, data); + break; + case VTB_EXT: + case DI_EXT: + case LS_EXT: + case MI_EXT: + break; + } + } +} + +xf86MonPtr +xf86InterpretEEDID(int scrnIndex, Uchar *block) +{ + xf86MonPtr m; + + m = xf86InterpretEDID(scrnIndex, block); + if (!m) + return NULL; + + /* extension parse */ + + return m; +} + +static void +get_vendor_section(Uchar *c, struct vendor *r) +{ + r->name[0] = L1; + r->name[1] = L2; + r->name[2] = L3; + r->name[3] = '\0'; + + r->prod_id = PROD_ID; + r->serial = SERIAL_NO; + r->week = WEEK; + r->year = YEAR; +} + +static void +get_version_section(Uchar *c, struct edid_version *r) +{ + r->version = VERSION; + r->revision = REVISION; +} + +static void +get_display_section(Uchar *c, struct disp_features *r, + struct edid_version *v) +{ + r->input_type = INPUT_TYPE; + if (!DIGITAL(r->input_type)) { + r->input_voltage = INPUT_VOLTAGE; + r->input_setup = SETUP; + r->input_sync = SYNC; + } else if (v->revision == 2 || v->revision == 3) { + r->input_dfp = DFP; + } else if (v->revision >= 4) { + r->input_bpc = BPC; + r->input_interface = DIGITAL_INTERFACE; + } + r->hsize = HSIZE_MAX; + r->vsize = VSIZE_MAX; + r->gamma = GAMMA; + r->dpms = DPMS; + r->display_type = DISPLAY_TYPE; + r->msc = MSC; + r->redx = REDX; + r->redy = REDY; + r->greenx = GREENX; + r->greeny = GREENY; + r->bluex = BLUEX; + r->bluey = BLUEY; + r->whitex = WHITEX; + r->whitey = WHITEY; +} + +static void +get_established_timing_section(Uchar *c, struct established_timings *r) +{ + r->t1 = T1; + r->t2 = T2; + r->t_manu = T_MANU; +} + +static void +get_cvt_timing_section(Uchar *c, struct cvt_timings *r) +{ + int i; + + for (i = 0; i < 4; i++) { + if (c[0] && c[1] && c[2]) { + r[i].height = (c[0] + ((c[1] & 0xF0) << 8) + 1) * 2; + switch (c[1] & 0xc0) { + case 0x00: r[i].width = r[i].height * 4 / 3; break; + case 0x40: r[i].width = r[i].height * 16 / 9; break; + case 0x80: r[i].width = r[i].height * 16 / 10; break; + case 0xc0: r[i].width = r[i].height * 15 / 9; break; + } + switch (c[2] & 0x60) { + case 0x00: r[i].rate = 50; break; + case 0x20: r[i].rate = 60; break; + case 0x40: r[i].rate = 75; break; + case 0x60: r[i].rate = 85; break; + } + r[i].rates = c[2] & 0x1f; + } else { + return; + } + c += 3; + } +} + +static void +get_std_timing_section(Uchar *c, struct std_timings *r, + struct edid_version *v) +{ + int i; + + for (i=0;iversion == 1 && ver->revision >= 1 && IS_MONITOR_DESC) { + switch (MONITOR_DESC_TYPE) { + case SERIAL_NUMBER: + det_mon->type = DS_SERIAL; + copy_string(c,det_mon->section.serial); + break; + case ASCII_STR: + det_mon->type = DS_ASCII_STR; + copy_string(c,det_mon->section.ascii_data); + break; + case MONITOR_RANGES: + det_mon->type = DS_RANGES; + get_monitor_ranges(c,&det_mon->section.ranges); + break; + case MONITOR_NAME: + det_mon->type = DS_NAME; + copy_string(c,det_mon->section.name); + break; + case ADD_COLOR_POINT: + det_mon->type = DS_WHITE_P; + get_whitepoint_section(c,det_mon->section.wp); + break; + case ADD_STD_TIMINGS: + det_mon->type = DS_STD_TIMINGS; + get_dst_timing_section(c,det_mon->section.std_t, ver); + break; + case COLOR_MANAGEMENT_DATA: + det_mon->type = DS_CMD; + break; + case CVT_3BYTE_DATA: + det_mon->type = DS_CVT; + get_cvt_timing_section(c, det_mon->section.cvt); + break; + case ADD_EST_TIMINGS: + det_mon->type = DS_EST_III; + memcpy(det_mon->section.est_iii, c + 6, 6); + break; + case ADD_DUMMY: + det_mon->type = DS_DUMMY; + break; + default: + det_mon->type = DS_UNKOWN; + break; + } + if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) { + det_mon->type = DS_VENDOR + c[3]; + } + } else { + det_mon->type = DT; + get_detailed_timing_section(c, &det_mon->section.d_timings); + } +} + +static void +get_dt_md_section(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon) +{ + int i; + + for (i=0; i < DET_TIMINGS; i++) { + fetch_detailed_block(c, ver, det_mon + i); + NEXT_DT_MD_SECTION; + } +} + +static void +copy_string(Uchar *c, Uchar *s) +{ + int i; + c = c + 5; + for (i = 0; (i < 13 && *c != 0x0A); i++) + *(s++) = *(c++); + *s = 0; + while (i-- && (*--s == 0x20)) *s = 0; +} + +static void +get_dst_timing_section(Uchar *c, struct std_timings *t, + struct edid_version *v) +{ + int j; + c = c + 5; + for (j = 0; j < 5; j++) { + t[j].hsize = HSIZE1; + VSIZE1(t[j].vsize); + t[j].refresh = REFRESH_R; + t[j].id = STD_TIMING_ID; + NEXT_STD_TIMING; + } +} + +static void +get_monitor_ranges(Uchar *c, struct monitor_ranges *r) +{ + r->min_v = MIN_V; + r->max_v = MAX_V; + r->min_h = MIN_H; + r->max_h = MAX_H; + r->max_clock = 0; + if(MAX_CLOCK != 0xff) /* is specified? */ + r->max_clock = MAX_CLOCK * 10; + if (HAVE_2ND_GTF) { + r->gtf_2nd_f = F_2ND_GTF; + r->gtf_2nd_c = C_2ND_GTF; + r->gtf_2nd_m = M_2ND_GTF; + r->gtf_2nd_k = K_2ND_GTF; + r->gtf_2nd_j = J_2ND_GTF; + } else { + r->gtf_2nd_f = 0; + } + if (HAVE_CVT) { + r->max_clock_khz = MAX_CLOCK_KHZ; + r->max_clock = r->max_clock_khz / 1000; + r->maxwidth = MAXWIDTH; + r->supported_aspect = SUPPORTED_ASPECT; + r->preferred_aspect = PREFERRED_ASPECT; + r->supported_blanking = SUPPORTED_BLANKING; + r->supported_scaling = SUPPORTED_SCALING; + r->preferred_refresh = PREFERRED_REFRESH; + } else { + r->max_clock_khz = 0; + } +} + +static void +get_whitepoint_section(Uchar *c, struct whitePoints *wp) +{ + wp[0].white_x = WHITEX1; + wp[0].white_y = WHITEY1; + wp[1].white_x = WHITEX2; + wp[1].white_y = WHITEY2; + wp[0].index = WHITE_INDEX1; + wp[1].index = WHITE_INDEX2; + wp[0].white_gamma = WHITE_GAMMA1; + wp[1].white_gamma = WHITE_GAMMA2; +} + +static void +get_detailed_timing_section(Uchar *c, struct detailed_timings *r) +{ + r->clock = PIXEL_CLOCK; + r->h_active = H_ACTIVE; + r->h_blanking = H_BLANK; + r->v_active = V_ACTIVE; + r->v_blanking = V_BLANK; + r->h_sync_off = H_SYNC_OFF; + r->h_sync_width = H_SYNC_WIDTH; + r->v_sync_off = V_SYNC_OFF; + r->v_sync_width = V_SYNC_WIDTH; + r->h_size = H_SIZE; + r->v_size = V_SIZE; + r->h_border = H_BORDER; + r->v_border = V_BORDER; + r->interlaced = INTERLACED; + r->stereo = STEREO; + r->stereo_1 = STEREO1; + r->sync = SYNC_T; + r->misc = MISC; +} + +#define MAX_EDID_MINOR 4 + +static Bool +validate_version(int scrnIndex, struct edid_version *r) +{ + if (r->version != 1) { + xf86DrvMsg(scrnIndex, X_ERROR, "Unknown EDID version %d\n", + r->version); + return FALSE; + } + + if (r->revision > MAX_EDID_MINOR) + xf86DrvMsg(scrnIndex, X_WARNING, + "Assuming version 1.%d is compatible with 1.%d\n", + r->revision, MAX_EDID_MINOR); + + return TRUE; +} + +/* + * Returns true if HDMI, false if definitely not or unknown. + */ +Bool +xf86MonitorIsHDMI(xf86MonPtr mon) +{ + int i = 0, version, offset; + char *edid = NULL; + + if (!mon) + return FALSE; + + if (!(mon->flags & EDID_COMPLETE_RAWDATA)) + return FALSE; + + if (!mon->no_sections) + return FALSE; + + edid = (char *)mon->rawData; + if (!edid) + return FALSE; + + /* find the CEA extension block */ + for (i = 1; i <= mon->no_sections; i++) + if (edid[i * 128] == 0x02) + break; + if (i == mon->no_sections + 1) + return FALSE; + edid += (i * 128); + + version = edid[1]; + offset = edid[2]; + if (version < 3 || offset < 4) + return FALSE; + + /* walk the cea data blocks */ + for (i = 4; i < offset; i += (edid[i] & 0x1f) + 1) { + char *x = edid + i; + + /* find a vendor specific block */ + if ((x[0] & 0xe0) >> 5 == 0x03) { + int oui = (x[3] << 16) + (x[2] << 8) + x[1]; + + /* find the HDMI vendor OUI */ + if (oui == 0x000c03) + return TRUE; + } + } + + /* guess it's not HDMI after all */ + return FALSE; +} diff --git a/xorg-server/hw/xfree86/dixmods/extmod/modinit.c b/xorg-server/hw/xfree86/dixmods/extmod/modinit.c index 7d2086802..c0c17d722 100644 --- a/xorg-server/hw/xfree86/dixmods/extmod/modinit.c +++ b/xorg-server/hw/xfree86/dixmods/extmod/modinit.c @@ -1,187 +1,187 @@ -/* - * Copyright (c) 1997 Matthieu Herrb - * - * 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 Matthieu Herrb not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Matthieu Herrb makes no - * representations about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * MATTHIEU HERRB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL MATTHIEU HERRB 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. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86Module.h" -#include "xf86Opt.h" - -#include - -#include "modinit.h" -#include "globals.h" - -static MODULESETUPPROTO(extmodSetup); - -/* - * Array describing extensions to be initialized - */ -static ExtensionModule extensionModules[] = { -#ifdef XSELINUX - { - SELinuxExtensionInit, - SELINUX_EXTENSION_NAME, - &noSELinuxExtension, - NULL, - NULL - }, -#endif -#ifdef SCREENSAVER - { - ScreenSaverExtensionInit, - ScreenSaverName, - &noScreenSaverExtension, - NULL, - NULL - }, -#endif -#ifdef XF86VIDMODE - { - XFree86VidModeExtensionInit, - XF86VIDMODENAME, - &noXFree86VidModeExtension, - NULL, - NULL - }, -#endif -#ifdef XFreeXDGA - { - XFree86DGAExtensionInit, - XF86DGANAME, - &noXFree86DGAExtension, - XFree86DGARegister, - NULL - }, -#endif -#ifdef DPMSExtension - { - DPMSExtensionInit, - DPMSExtensionName, - &noDPMSExtension, - NULL, - NULL - }, -#endif -#ifdef XV - { - XvExtensionInit, - XvName, - &noXvExtension, - XvRegister, - NULL - }, - { - XvMCExtensionInit, - XvMCName, - &noXvExtension, - NULL, - NULL - }, -#endif -#ifdef RES - { - ResExtensionInit, - XRES_NAME, - &noResExtension, - NULL, - NULL - }, -#endif - { /* DON'T delete this entry ! */ - NULL, - NULL, - NULL, - NULL, - NULL - } -}; - -static XF86ModuleVersionInfo VersRec = -{ - "extmod", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - 1, 0, 0, - ABI_CLASS_EXTENSION, - ABI_EXTENSION_VERSION, - MOD_CLASS_EXTENSION, - {0,0,0,0} -}; - -/* - * Data for the loader - */ -_X_EXPORT XF86ModuleData extmodModuleData = { &VersRec, extmodSetup, NULL }; - -static pointer -extmodSetup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - int i; - - /* XXX the option stuff here is largely a sample/test case */ - - for (i = 0; extensionModules[i].name != NULL; i++) { - if (opts) { - char *s; - s = (char *)xalloc(strlen(extensionModules[i].name) + 5); - if (s) { - pointer o; - strcpy(s, "omit"); - strcat(s, extensionModules[i].name); - o = xf86FindOption(opts, s); - xfree(s); - if (o) { - xf86MarkOptionUsed(o); - continue; - } - } - } - -#ifdef XSELINUX - if (! strcmp(SELINUX_EXTENSION_NAME, extensionModules[i].name)) { - pointer o; - selinuxEnforcingState = SELINUX_MODE_DEFAULT; - - if ((o = xf86FindOption(opts, "SELinux mode disabled"))) { - xf86MarkOptionUsed(o); - selinuxEnforcingState = SELINUX_MODE_DISABLED; - } - if ((o = xf86FindOption(opts, "SELinux mode permissive"))) { - xf86MarkOptionUsed(o); - selinuxEnforcingState = SELINUX_MODE_PERMISSIVE; - } - if ((o = xf86FindOption(opts, "SELinux mode enforcing"))) { - xf86MarkOptionUsed(o); - selinuxEnforcingState = SELINUX_MODE_ENFORCING; - } - } -#endif - - LoadExtension(&extensionModules[i], FALSE); - } - /* Need a non-NULL return */ - return (pointer)1; -} +/* + * Copyright (c) 1997 Matthieu Herrb + * + * 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 Matthieu Herrb not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Matthieu Herrb makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * MATTHIEU HERRB DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL MATTHIEU HERRB 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86Module.h" +#include "xf86Opt.h" + +#include + +#include "modinit.h" +#include "globals.h" + +static MODULESETUPPROTO(extmodSetup); + +/* + * Array describing extensions to be initialized + */ +static ExtensionModule extensionModules[] = { +#ifdef XSELINUX + { + SELinuxExtensionInit, + SELINUX_EXTENSION_NAME, + &noSELinuxExtension, + NULL, + NULL + }, +#endif +#ifdef SCREENSAVER + { + ScreenSaverExtensionInit, + ScreenSaverName, + &noScreenSaverExtension, + NULL, + NULL + }, +#endif +#ifdef XF86VIDMODE + { + XFree86VidModeExtensionInit, + XF86VIDMODENAME, + &noXFree86VidModeExtension, + NULL, + NULL + }, +#endif +#ifdef XFreeXDGA + { + XFree86DGAExtensionInit, + XF86DGANAME, + &noXFree86DGAExtension, + XFree86DGARegister, + NULL + }, +#endif +#ifdef DPMSExtension + { + DPMSExtensionInit, + DPMSExtensionName, + &noDPMSExtension, + NULL, + NULL + }, +#endif +#ifdef XV + { + XvExtensionInit, + XvName, + &noXvExtension, + XvRegister, + NULL + }, + { + XvMCExtensionInit, + XvMCName, + &noXvExtension, + NULL, + NULL + }, +#endif +#ifdef RES + { + ResExtensionInit, + XRES_NAME, + &noResExtension, + NULL, + NULL + }, +#endif + { /* DON'T delete this entry ! */ + NULL, + NULL, + NULL, + NULL, + NULL + } +}; + +static XF86ModuleVersionInfo VersRec = +{ + "extmod", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 0, 0, + ABI_CLASS_EXTENSION, + ABI_EXTENSION_VERSION, + MOD_CLASS_EXTENSION, + {0,0,0,0} +}; + +/* + * Data for the loader + */ +_X_EXPORT XF86ModuleData extmodModuleData = { &VersRec, extmodSetup, NULL }; + +static pointer +extmodSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + int i; + + /* XXX the option stuff here is largely a sample/test case */ + + for (i = 0; extensionModules[i].name != NULL; i++) { + if (opts) { + char *s; + s = (char *)malloc(strlen(extensionModules[i].name) + 5); + if (s) { + pointer o; + strcpy(s, "omit"); + strcat(s, extensionModules[i].name); + o = xf86FindOption(opts, s); + free(s); + if (o) { + xf86MarkOptionUsed(o); + continue; + } + } + } + +#ifdef XSELINUX + if (! strcmp(SELINUX_EXTENSION_NAME, extensionModules[i].name)) { + pointer o; + selinuxEnforcingState = SELINUX_MODE_DEFAULT; + + if ((o = xf86FindOption(opts, "SELinux mode disabled"))) { + xf86MarkOptionUsed(o); + selinuxEnforcingState = SELINUX_MODE_DISABLED; + } + if ((o = xf86FindOption(opts, "SELinux mode permissive"))) { + xf86MarkOptionUsed(o); + selinuxEnforcingState = SELINUX_MODE_PERMISSIVE; + } + if ((o = xf86FindOption(opts, "SELinux mode enforcing"))) { + xf86MarkOptionUsed(o); + selinuxEnforcingState = SELINUX_MODE_ENFORCING; + } + } +#endif + + LoadExtension(&extensionModules[i], FALSE); + } + /* Need a non-NULL return */ + return (pointer)1; +} diff --git a/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c b/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c index 038551467..fae8d8b5d 100644 --- a/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c +++ b/xorg-server/hw/xfree86/dixmods/extmod/xf86dga2.c @@ -1,1062 +1,1058 @@ -/* - * Copyright (c) 1995 Jon Tombs - * Copyright (c) 1995, 1996, 1999 XFree86 Inc - * Copyright (c) 1999 - The XFree86 Project Inc. - * - * Written by Mark Vojkovich - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "dixstruct.h" -#include "dixevents.h" -#include "pixmapstr.h" -#include "extnsionst.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "servermd.h" -#include -#include "swaprep.h" -#include "dgaproc.h" -#include "xf86dgaext.h" -#include "protocol-versions.h" - -#include - -#include "modinit.h" - -#define DGA_PROTOCOL_OLD_SUPPORT 1 - -static DISPATCH_PROC(ProcXDGADispatch); -static DISPATCH_PROC(SProcXDGADispatch); -static DISPATCH_PROC(ProcXDGAQueryVersion); -static DISPATCH_PROC(ProcXDGAQueryModes); -static DISPATCH_PROC(ProcXDGASetMode); -static DISPATCH_PROC(ProcXDGAOpenFramebuffer); -static DISPATCH_PROC(ProcXDGACloseFramebuffer); -static DISPATCH_PROC(ProcXDGASetViewport); -static DISPATCH_PROC(ProcXDGAInstallColormap); -static DISPATCH_PROC(ProcXDGASelectInput); -static DISPATCH_PROC(ProcXDGAFillRectangle); -static DISPATCH_PROC(ProcXDGACopyArea); -static DISPATCH_PROC(ProcXDGACopyTransparentArea); -static DISPATCH_PROC(ProcXDGAGetViewportStatus); -static DISPATCH_PROC(ProcXDGASync); -static DISPATCH_PROC(ProcXDGASetClientVersion); -static DISPATCH_PROC(ProcXDGAChangePixmapMode); -static DISPATCH_PROC(ProcXDGACreateColormap); - -static void XDGAResetProc(ExtensionEntry *extEntry); - -static void DGAClientStateChange (CallbackListPtr*, pointer, pointer); - -unsigned char DGAReqCode = 0; -int DGAErrorBase; -int DGAEventBase; - -static int DGAScreenPrivateKeyIndex; -static DevPrivateKey DGAScreenPrivateKey = &DGAScreenPrivateKeyIndex; -static int DGAClientPrivateKeyIndex; -static DevPrivateKey DGAClientPrivateKey = &DGAClientPrivateKeyIndex; -static int DGACallbackRefCount = 0; - -/* This holds the client's version information */ -typedef struct { - int major; - int minor; -} DGAPrivRec, *DGAPrivPtr; - -#define DGA_GETCLIENT(idx) ((ClientPtr) \ - dixLookupPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey)) -#define DGA_SETCLIENT(idx,p) \ - dixSetPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey, p) - -#define DGA_GETPRIV(c) ((DGAPrivPtr) \ - dixLookupPrivate(&(c)->devPrivates, DGAClientPrivateKey)) -#define DGA_SETPRIV(c,p) \ - dixSetPrivate(&(c)->devPrivates, DGAClientPrivateKey, p) - - -void -XFree86DGAExtensionInit(INITARGS) -{ - ExtensionEntry* extEntry; - - if ((extEntry = AddExtension(XF86DGANAME, - XF86DGANumberEvents, - XF86DGANumberErrors, - ProcXDGADispatch, - SProcXDGADispatch, - XDGAResetProc, - StandardMinorOpcode))) { - int i; - - DGAReqCode = (unsigned char)extEntry->base; - DGAErrorBase = extEntry->errorBase; - DGAEventBase = extEntry->eventBase; - for (i = KeyPress; i <= MotionNotify; i++) - SetCriticalEvent (DGAEventBase + i); - } -} - - - -static void -XDGAResetProc (ExtensionEntry *extEntry) -{ - DeleteCallback (&ClientStateCallback, DGAClientStateChange, NULL); - DGACallbackRefCount = 0; -} - - -static int -ProcXDGAQueryVersion(ClientPtr client) -{ - xXDGAQueryVersionReply rep; - - REQUEST_SIZE_MATCH(xXDGAQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_XDGA_MAJOR_VERSION; - rep.minorVersion = SERVER_XDGA_MINOR_VERSION; - - WriteToClient(client, sizeof(xXDGAQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - - -static int -ProcXDGAOpenFramebuffer(ClientPtr client) -{ - REQUEST(xXDGAOpenFramebufferReq); - xXDGAOpenFramebufferReply rep; - char *deviceName; - int nameSize; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if (!DGAAvailable(stuff->screen)) - return DGAErrorBase + XF86DGANoDirectVideoMode; - - REQUEST_SIZE_MATCH(xXDGAOpenFramebufferReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if(!DGAOpenFramebuffer(stuff->screen, &deviceName, - (unsigned char**)(&rep.mem1), - (int*)&rep.size, (int*)&rep.offset, (int*)&rep.extra)) - { - return BadAlloc; - } - - nameSize = deviceName ? (strlen(deviceName) + 1) : 0; - rep.length = bytes_to_int32(nameSize); - - WriteToClient(client, sizeof(xXDGAOpenFramebufferReply), (char *)&rep); - if(rep.length) - WriteToClient(client, nameSize, deviceName); - - return (client->noClientException); -} - - -static int -ProcXDGACloseFramebuffer(ClientPtr client) -{ - REQUEST(xXDGACloseFramebufferReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if (!DGAAvailable(stuff->screen)) - return DGAErrorBase + XF86DGANoDirectVideoMode; - - REQUEST_SIZE_MATCH(xXDGACloseFramebufferReq); - - DGACloseFramebuffer(stuff->screen); - - return (client->noClientException); -} - -static int -ProcXDGAQueryModes(ClientPtr client) -{ - int i, num, size; - REQUEST(xXDGAQueryModesReq); - xXDGAQueryModesReply rep; - xXDGAModeInfo info; - XDGAModePtr mode; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - REQUEST_SIZE_MATCH(xXDGAQueryModesReq); - rep.type = X_Reply; - rep.length = 0; - rep.number = 0; - rep.sequenceNumber = client->sequence; - - if (!DGAAvailable(stuff->screen)) { - rep.number = 0; - rep.length = 0; - WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); - return (client->noClientException); - } - - if(!(num = DGAGetModes(stuff->screen))) { - WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); - return (client->noClientException); - } - - if(!(mode = (XDGAModePtr)xalloc(num * sizeof(XDGAModeRec)))) - return BadAlloc; - - for(i = 0; i < num; i++) - DGAGetModeInfo(stuff->screen, mode + i, i + 1); - - size = num * sz_xXDGAModeInfo; - for(i = 0; i < num; i++) - size += pad_to_int32(strlen(mode[i].name) + 1); /* plus NULL */ - - rep.number = num; - rep.length = bytes_to_int32(size); - - WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); - - for(i = 0; i < num; i++) { - size = strlen(mode[i].name) + 1; - - info.byte_order = mode[i].byteOrder; - info.depth = mode[i].depth; - info.num = mode[i].num; - info.bpp = mode[i].bitsPerPixel; - info.name_size = (size + 3) & ~3L; - info.vsync_num = mode[i].VSync_num; - info.vsync_den = mode[i].VSync_den; - info.flags = mode[i].flags; - info.image_width = mode[i].imageWidth; - info.image_height = mode[i].imageHeight; - info.pixmap_width = mode[i].pixmapWidth; - info.pixmap_height = mode[i].pixmapHeight; - info.bytes_per_scanline = mode[i].bytesPerScanline; - info.red_mask = mode[i].red_mask; - info.green_mask = mode[i].green_mask; - info.blue_mask = mode[i].blue_mask; - info.visual_class = mode[i].visualClass; - info.viewport_width = mode[i].viewportWidth; - info.viewport_height = mode[i].viewportHeight; - info.viewport_xstep = mode[i].xViewportStep; - info.viewport_ystep = mode[i].yViewportStep; - info.viewport_xmax = mode[i].maxViewportX; - info.viewport_ymax = mode[i].maxViewportY; - info.viewport_flags = mode[i].viewportFlags; - info.reserved1 = mode[i].reserved1; - info.reserved2 = mode[i].reserved2; - - WriteToClient(client, sz_xXDGAModeInfo, (char*)(&info)); - WriteToClient(client, size, mode[i].name); - } - - xfree(mode); - - return (client->noClientException); -} - - -static void -DGAClientStateChange ( - CallbackListPtr* pcbl, - pointer nulldata, - pointer calldata -){ - NewClientInfoRec* pci = (NewClientInfoRec*) calldata; - ClientPtr client = NULL; - int i; - - for(i = 0; i < screenInfo.numScreens; i++) { - if(DGA_GETCLIENT(i) == pci->client) { - client = pci->client; - break; - } - } - - if(client && - ((client->clientState == ClientStateGone) || - (client->clientState == ClientStateRetained))) { - XDGAModeRec mode; - PixmapPtr pPix; - - DGA_SETCLIENT(i, NULL); - DGASelectInput(i, NULL, 0); - DGASetMode(i, 0, &mode, &pPix); - - if(--DGACallbackRefCount == 0) - DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); - } -} - -static int -ProcXDGASetMode(ClientPtr client) -{ - REQUEST(xXDGASetModeReq); - xXDGASetModeReply rep; - XDGAModeRec mode; - xXDGAModeInfo info; - PixmapPtr pPix; - ClientPtr owner; - int size; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - owner = DGA_GETCLIENT(stuff->screen); - - REQUEST_SIZE_MATCH(xXDGASetModeReq); - rep.type = X_Reply; - rep.length = 0; - rep.offset = 0; - rep.flags = 0; - rep.sequenceNumber = client->sequence; - - if (!DGAAvailable(stuff->screen)) - return DGAErrorBase + XF86DGANoDirectVideoMode; - - if(owner && owner != client) - return DGAErrorBase + XF86DGANoDirectVideoMode; - - if(!stuff->mode) { - if(owner) { - if(--DGACallbackRefCount == 0) - DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); - } - DGA_SETCLIENT(stuff->screen, NULL); - DGASelectInput(stuff->screen, NULL, 0); - DGASetMode(stuff->screen, 0, &mode, &pPix); - WriteToClient(client, sz_xXDGASetModeReply, (char*)&rep); - return (client->noClientException); - } - - if(Success != DGASetMode(stuff->screen, stuff->mode, &mode, &pPix)) - return BadValue; - - if(!owner) { - if(DGACallbackRefCount++ == 0) - AddCallback (&ClientStateCallback, DGAClientStateChange, NULL); - } - - DGA_SETCLIENT(stuff->screen, client); - - if(pPix) { - if(AddResource(stuff->pid, RT_PIXMAP, (pointer)(pPix))) { - pPix->drawable.id = (int)stuff->pid; - rep.flags = DGA_PIXMAP_AVAILABLE; - } - } - - size = strlen(mode.name) + 1; - - info.byte_order = mode.byteOrder; - info.depth = mode.depth; - info.num = mode.num; - info.bpp = mode.bitsPerPixel; - info.name_size = (size + 3) & ~3L; - info.vsync_num = mode.VSync_num; - info.vsync_den = mode.VSync_den; - info.flags = mode.flags; - info.image_width = mode.imageWidth; - info.image_height = mode.imageHeight; - info.pixmap_width = mode.pixmapWidth; - info.pixmap_height = mode.pixmapHeight; - info.bytes_per_scanline = mode.bytesPerScanline; - info.red_mask = mode.red_mask; - info.green_mask = mode.green_mask; - info.blue_mask = mode.blue_mask; - info.visual_class = mode.visualClass; - info.viewport_width = mode.viewportWidth; - info.viewport_height = mode.viewportHeight; - info.viewport_xstep = mode.xViewportStep; - info.viewport_ystep = mode.yViewportStep; - info.viewport_xmax = mode.maxViewportX; - info.viewport_ymax = mode.maxViewportY; - info.viewport_flags = mode.viewportFlags; - info.reserved1 = mode.reserved1; - info.reserved2 = mode.reserved2; - - rep.length = bytes_to_int32(sz_xXDGAModeInfo + info.name_size); - - WriteToClient(client, sz_xXDGASetModeReply, (char*)&rep); - WriteToClient(client, sz_xXDGAModeInfo, (char*)(&info)); - WriteToClient(client, size, mode.name); - - return (client->noClientException); -} - -static int -ProcXDGASetViewport(ClientPtr client) -{ - REQUEST(xXDGASetViewportReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGASetViewportReq); - - DGASetViewport(stuff->screen, stuff->x, stuff->y, stuff->flags); - - return (client->noClientException); -} - -static int -ProcXDGAInstallColormap(ClientPtr client) -{ - ColormapPtr cmap; - int rc; - REQUEST(xXDGAInstallColormapReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGAInstallColormapReq); - - rc = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, RT_COLORMAP, - client, DixInstallAccess); - if (rc == Success) { - DGAInstallCmap(cmap); - return (client->noClientException); - } else { - return (rc == BadValue) ? BadColor : rc; - } - - return (client->noClientException); -} - - -static int -ProcXDGASelectInput(ClientPtr client) -{ - REQUEST(xXDGASelectInputReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGASelectInputReq); - - if(DGA_GETCLIENT(stuff->screen) == client) - DGASelectInput(stuff->screen, client, stuff->mask); - - return (client->noClientException); -} - - -static int -ProcXDGAFillRectangle(ClientPtr client) -{ - REQUEST(xXDGAFillRectangleReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGAFillRectangleReq); - - if(Success != DGAFillRect(stuff->screen, stuff->x, stuff->y, - stuff->width, stuff->height, stuff->color)) - return BadMatch; - - return (client->noClientException); -} - -static int -ProcXDGACopyArea(ClientPtr client) -{ - REQUEST(xXDGACopyAreaReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGACopyAreaReq); - - if(Success != DGABlitRect(stuff->screen, stuff->srcx, stuff->srcy, - stuff->width, stuff->height, stuff->dstx, stuff->dsty)) - return BadMatch; - - return (client->noClientException); -} - - -static int -ProcXDGACopyTransparentArea(ClientPtr client) -{ - REQUEST(xXDGACopyTransparentAreaReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGACopyTransparentAreaReq); - - if(Success != DGABlitTransRect(stuff->screen, stuff->srcx, stuff->srcy, - stuff->width, stuff->height, stuff->dstx, stuff->dsty, stuff->key)) - return BadMatch; - - return (client->noClientException); -} - - -static int -ProcXDGAGetViewportStatus(ClientPtr client) -{ - REQUEST(xXDGAGetViewportStatusReq); - xXDGAGetViewportStatusReply rep; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGAGetViewportStatusReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rep.status = DGAGetViewportStatus(stuff->screen); - - WriteToClient(client, sizeof(xXDGAGetViewportStatusReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXDGASync(ClientPtr client) -{ - REQUEST(xXDGASyncReq); - xXDGASyncReply rep; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGASyncReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - DGASync(stuff->screen); - - WriteToClient(client, sizeof(xXDGASyncReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXDGASetClientVersion(ClientPtr client) -{ - REQUEST(xXDGASetClientVersionReq); - - DGAPrivPtr pPriv; - - REQUEST_SIZE_MATCH(xXDGASetClientVersionReq); - if ((pPriv = DGA_GETPRIV(client)) == NULL) { - pPriv = xalloc(sizeof(DGAPrivRec)); - /* XXX Need to look into freeing this */ - if (!pPriv) - return BadAlloc; - DGA_SETPRIV(client, pPriv); - } - pPriv->major = stuff->major; - pPriv->minor = stuff->minor; - - return (client->noClientException); -} - -static int -ProcXDGAChangePixmapMode(ClientPtr client) -{ - REQUEST(xXDGAChangePixmapModeReq); - xXDGAChangePixmapModeReply rep; - int x, y; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGAChangePixmapModeReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - x = stuff->x; - y = stuff->y; - - if(!DGAChangePixmapMode(stuff->screen, &x, &y, stuff->flags)) - return BadMatch; - - rep.x = x; - rep.y = y; - WriteToClient(client, sizeof(xXDGAChangePixmapModeReply), (char *)&rep); - - return (client->noClientException); -} - - -static int -ProcXDGACreateColormap(ClientPtr client) -{ - REQUEST(xXDGACreateColormapReq); - int result; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if(DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXDGACreateColormapReq); - - if(!stuff->mode) - return BadValue; - - result = DGACreateColormap(stuff->screen, client, stuff->id, - stuff->mode, stuff->alloc); - if(result != Success) - return result; - - return (client->noClientException); -} - -/* - * - * Support for the old DGA protocol, used to live in xf86dga.c - * - */ - -#ifdef DGA_PROTOCOL_OLD_SUPPORT - -static DISPATCH_PROC(ProcXF86DGADirectVideo); -static DISPATCH_PROC(ProcXF86DGAGetVidPage); -static DISPATCH_PROC(ProcXF86DGAGetVideoLL); -static DISPATCH_PROC(ProcXF86DGAGetViewPortSize); -static DISPATCH_PROC(ProcXF86DGASetVidPage); -static DISPATCH_PROC(ProcXF86DGASetViewPort); -static DISPATCH_PROC(ProcXF86DGAInstallColormap); -static DISPATCH_PROC(ProcXF86DGAQueryDirectVideo); -static DISPATCH_PROC(ProcXF86DGAViewPortChanged); - - -static int -ProcXF86DGAGetVideoLL(ClientPtr client) -{ - REQUEST(xXF86DGAGetVideoLLReq); - xXF86DGAGetVideoLLReply rep; - XDGAModeRec mode; - int num, offset, flags; - char *name; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - REQUEST_SIZE_MATCH(xXF86DGAGetVideoLLReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if(!DGAAvailable(stuff->screen)) - return (DGAErrorBase + XF86DGANoDirectVideoMode); - - if(!(num = DGAGetOldDGAMode(stuff->screen))) - return (DGAErrorBase + XF86DGANoDirectVideoMode); - - /* get the parameters for the mode that best matches */ - DGAGetModeInfo(stuff->screen, &mode, num); - - if(!DGAOpenFramebuffer(stuff->screen, &name, - (unsigned char**)(&rep.offset), - (int*)(&rep.bank_size), &offset, &flags)) - return BadAlloc; - - rep.offset += mode.offset; - rep.width = mode.bytesPerScanline / (mode.bitsPerPixel >> 3); - rep.ram_size = rep.bank_size >> 10; - - WriteToClient(client, SIZEOF(xXF86DGAGetVideoLLReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86DGADirectVideo(ClientPtr client) -{ - int num; - PixmapPtr pix; - XDGAModeRec mode; - ClientPtr owner; - REQUEST(xXF86DGADirectVideoReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - owner = DGA_GETCLIENT(stuff->screen); - - REQUEST_SIZE_MATCH(xXF86DGADirectVideoReq); - - if (!DGAAvailable(stuff->screen)) - return DGAErrorBase + XF86DGANoDirectVideoMode; - - if (owner && owner != client) - return DGAErrorBase + XF86DGANoDirectVideoMode; - - if (stuff->enable & XF86DGADirectGraphics) { - if(!(num = DGAGetOldDGAMode(stuff->screen))) - return (DGAErrorBase + XF86DGANoDirectVideoMode); - } else - num = 0; - - if(Success != DGASetMode(stuff->screen, num, &mode, &pix)) - return (DGAErrorBase + XF86DGAScreenNotActive); - - DGASetInputMode (stuff->screen, - (stuff->enable & XF86DGADirectKeyb) != 0, - (stuff->enable & XF86DGADirectMouse) != 0); - - /* We need to track the client and attach the teardown callback */ - if (stuff->enable & - (XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse)) { - if (!owner) { - if (DGACallbackRefCount++ == 0) - AddCallback (&ClientStateCallback, DGAClientStateChange, NULL); - } - - DGA_SETCLIENT(stuff->screen, client); - } else { - if (owner) { - if (--DGACallbackRefCount == 0) - DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); - } - - DGA_SETCLIENT(stuff->screen, NULL); - } - - return (client->noClientException); -} - -static int -ProcXF86DGAGetViewPortSize(ClientPtr client) -{ - int num; - XDGAModeRec mode; - REQUEST(xXF86DGAGetViewPortSizeReq); - xXF86DGAGetViewPortSizeReply rep; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - REQUEST_SIZE_MATCH(xXF86DGAGetViewPortSizeReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if (!DGAAvailable(stuff->screen)) - return (DGAErrorBase + XF86DGANoDirectVideoMode); - - if(!(num = DGAGetOldDGAMode(stuff->screen))) - return (DGAErrorBase + XF86DGANoDirectVideoMode); - - DGAGetModeInfo(stuff->screen, &mode, num); - - rep.width = mode.viewportWidth; - rep.height = mode.viewportHeight; - - WriteToClient(client, SIZEOF(xXF86DGAGetViewPortSizeReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86DGASetViewPort(ClientPtr client) -{ - REQUEST(xXF86DGASetViewPortReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if (DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXF86DGASetViewPortReq); - - if (!DGAAvailable(stuff->screen)) - return (DGAErrorBase + XF86DGANoDirectVideoMode); - - if (!DGAActive(stuff->screen)) - return DGAErrorBase + XF86DGADirectNotActivated; - - if (DGASetViewport(stuff->screen, stuff->x, stuff->y, DGA_FLIP_RETRACE) - != Success) - return DGAErrorBase + XF86DGADirectNotActivated; - - return (client->noClientException); -} - -static int -ProcXF86DGAGetVidPage(ClientPtr client) -{ - REQUEST(xXF86DGAGetVidPageReq); - xXF86DGAGetVidPageReply rep; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - REQUEST_SIZE_MATCH(xXF86DGAGetVidPageReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.vpage = 0; /* silently fail */ - - WriteToClient(client, SIZEOF(xXF86DGAGetVidPageReply), (char *)&rep); - return (client->noClientException); -} - - -static int -ProcXF86DGASetVidPage(ClientPtr client) -{ - REQUEST(xXF86DGASetVidPageReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - REQUEST_SIZE_MATCH(xXF86DGASetVidPageReq); - - /* silently fail */ - - return (client->noClientException); -} - - -static int -ProcXF86DGAInstallColormap(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - REQUEST(xXF86DGAInstallColormapReq); - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if (DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXF86DGAInstallColormapReq); - - if (!DGAActive(stuff->screen)) - return (DGAErrorBase + XF86DGADirectNotActivated); - - rc = dixLookupResourceByType((pointer *)&pcmp, stuff->id, RT_COLORMAP, - client, DixInstallAccess); - if (rc == Success) { - DGAInstallCmap(pcmp); - return (client->noClientException); - } else { - return (rc == BadValue) ? BadColor : rc; - } -} - -static int -ProcXF86DGAQueryDirectVideo(ClientPtr client) -{ - REQUEST(xXF86DGAQueryDirectVideoReq); - xXF86DGAQueryDirectVideoReply rep; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - REQUEST_SIZE_MATCH(xXF86DGAQueryDirectVideoReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.flags = 0; - - if (DGAAvailable(stuff->screen)) - rep.flags = XF86DGADirectPresent; - - WriteToClient(client, SIZEOF(xXF86DGAQueryDirectVideoReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86DGAViewPortChanged(ClientPtr client) -{ - REQUEST(xXF86DGAViewPortChangedReq); - xXF86DGAViewPortChangedReply rep; - - if (stuff->screen > screenInfo.numScreens) - return BadValue; - - if (DGA_GETCLIENT(stuff->screen) != client) - return DGAErrorBase + XF86DGADirectNotActivated; - - REQUEST_SIZE_MATCH(xXF86DGAViewPortChangedReq); - - if (!DGAActive(stuff->screen)) - return (DGAErrorBase + XF86DGADirectNotActivated); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.result = 1; - - WriteToClient(client, SIZEOF(xXF86DGAViewPortChangedReply), (char *)&rep); - return (client->noClientException); -} - -#endif /* DGA_PROTOCOL_OLD_SUPPORT */ - -static int -SProcXDGADispatch (ClientPtr client) -{ - return DGAErrorBase + XF86DGAClientNotLocal; -} - -#if 0 -#define DGA_REQ_DEBUG -#endif - -#ifdef DGA_REQ_DEBUG -static char *dgaMinor[] = { - "QueryVersion", - "GetVideoLL", - "DirectVideo", - "GetViewPortSize", - "SetViewPort", - "GetVidPage", - "SetVidPage", - "InstallColormap", - "QueryDirectVideo", - "ViewPortChanged", - "10", - "11", - "QueryModes", - "SetMode", - "SetViewport", - "InstallColormap", - "SelectInput", - "FillRectangle", - "CopyArea", - "CopyTransparentArea", - "GetViewportStatus", - "Sync", - "OpenFramebuffer", - "CloseFramebuffer", - "SetClientVersion", - "ChangePixmapMode", - "CreateColormap", -}; -#endif - -static int -ProcXDGADispatch (ClientPtr client) -{ - REQUEST(xReq); - - if (!LocalClient(client)) - return DGAErrorBase + XF86DGAClientNotLocal; - -#ifdef DGA_REQ_DEBUG - if (stuff->data <= X_XDGACreateColormap) - fprintf (stderr, " DGA %s\n", dgaMinor[stuff->data]); -#endif - - switch (stuff->data){ - /* - * DGA2 Protocol - */ - case X_XDGAQueryVersion: - return ProcXDGAQueryVersion(client); - case X_XDGAQueryModes: - return ProcXDGAQueryModes(client); - case X_XDGASetMode: - return ProcXDGASetMode(client); - case X_XDGAOpenFramebuffer: - return ProcXDGAOpenFramebuffer(client); - case X_XDGACloseFramebuffer: - return ProcXDGACloseFramebuffer(client); - case X_XDGASetViewport: - return ProcXDGASetViewport(client); - case X_XDGAInstallColormap: - return ProcXDGAInstallColormap(client); - case X_XDGASelectInput: - return ProcXDGASelectInput(client); - case X_XDGAFillRectangle: - return ProcXDGAFillRectangle(client); - case X_XDGACopyArea: - return ProcXDGACopyArea(client); - case X_XDGACopyTransparentArea: - return ProcXDGACopyTransparentArea(client); - case X_XDGAGetViewportStatus: - return ProcXDGAGetViewportStatus(client); - case X_XDGASync: - return ProcXDGASync(client); - case X_XDGASetClientVersion: - return ProcXDGASetClientVersion(client); - case X_XDGAChangePixmapMode: - return ProcXDGAChangePixmapMode(client); - case X_XDGACreateColormap: - return ProcXDGACreateColormap(client); - /* - * Old DGA Protocol - */ -#ifdef DGA_PROTOCOL_OLD_SUPPORT - case X_XF86DGAGetVideoLL: - return ProcXF86DGAGetVideoLL(client); - case X_XF86DGADirectVideo: - return ProcXF86DGADirectVideo(client); - case X_XF86DGAGetViewPortSize: - return ProcXF86DGAGetViewPortSize(client); - case X_XF86DGASetViewPort: - return ProcXF86DGASetViewPort(client); - case X_XF86DGAGetVidPage: - return ProcXF86DGAGetVidPage(client); - case X_XF86DGASetVidPage: - return ProcXF86DGASetVidPage(client); - case X_XF86DGAInstallColormap: - return ProcXF86DGAInstallColormap(client); - case X_XF86DGAQueryDirectVideo: - return ProcXF86DGAQueryDirectVideo(client); - case X_XF86DGAViewPortChanged: - return ProcXF86DGAViewPortChanged(client); -#endif /* DGA_PROTOCOL_OLD_SUPPORT */ - default: - return BadRequest; - } -} - -void -XFree86DGARegister(INITARGS) -{ - XDGAEventBase = &DGAEventBase; -} +/* + * Copyright (c) 1995 Jon Tombs + * Copyright (c) 1995, 1996, 1999 XFree86 Inc + * Copyright (c) 1999 - The XFree86 Project Inc. + * + * Written by Mark Vojkovich + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "dixstruct.h" +#include "dixevents.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#include +#include "swaprep.h" +#include "dgaproc.h" +#include "xf86dgaext.h" +#include "protocol-versions.h" + +#include + +#include "modinit.h" + +#define DGA_PROTOCOL_OLD_SUPPORT 1 + +static DISPATCH_PROC(ProcXDGADispatch); +static DISPATCH_PROC(SProcXDGADispatch); +static DISPATCH_PROC(ProcXDGAQueryVersion); +static DISPATCH_PROC(ProcXDGAQueryModes); +static DISPATCH_PROC(ProcXDGASetMode); +static DISPATCH_PROC(ProcXDGAOpenFramebuffer); +static DISPATCH_PROC(ProcXDGACloseFramebuffer); +static DISPATCH_PROC(ProcXDGASetViewport); +static DISPATCH_PROC(ProcXDGAInstallColormap); +static DISPATCH_PROC(ProcXDGASelectInput); +static DISPATCH_PROC(ProcXDGAFillRectangle); +static DISPATCH_PROC(ProcXDGACopyArea); +static DISPATCH_PROC(ProcXDGACopyTransparentArea); +static DISPATCH_PROC(ProcXDGAGetViewportStatus); +static DISPATCH_PROC(ProcXDGASync); +static DISPATCH_PROC(ProcXDGASetClientVersion); +static DISPATCH_PROC(ProcXDGAChangePixmapMode); +static DISPATCH_PROC(ProcXDGACreateColormap); + +static void XDGAResetProc(ExtensionEntry *extEntry); + +static void DGAClientStateChange (CallbackListPtr*, pointer, pointer); + +unsigned char DGAReqCode = 0; +int DGAErrorBase; +int DGAEventBase; + +static int DGAScreenPrivateKeyIndex; +static DevPrivateKey DGAScreenPrivateKey = &DGAScreenPrivateKeyIndex; +static int DGAClientPrivateKeyIndex; +static DevPrivateKey DGAClientPrivateKey = &DGAClientPrivateKeyIndex; +static int DGACallbackRefCount = 0; + +/* This holds the client's version information */ +typedef struct { + int major; + int minor; +} DGAPrivRec, *DGAPrivPtr; + +#define DGA_GETCLIENT(idx) ((ClientPtr) \ + dixLookupPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey)) +#define DGA_SETCLIENT(idx,p) \ + dixSetPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey, p) + +#define DGA_GETPRIV(c) ((DGAPrivPtr) \ + dixLookupPrivate(&(c)->devPrivates, DGAClientPrivateKey)) +#define DGA_SETPRIV(c,p) \ + dixSetPrivate(&(c)->devPrivates, DGAClientPrivateKey, p) + + +void +XFree86DGAExtensionInit(INITARGS) +{ + ExtensionEntry* extEntry; + + if ((extEntry = AddExtension(XF86DGANAME, + XF86DGANumberEvents, + XF86DGANumberErrors, + ProcXDGADispatch, + SProcXDGADispatch, + XDGAResetProc, + StandardMinorOpcode))) { + int i; + + DGAReqCode = (unsigned char)extEntry->base; + DGAErrorBase = extEntry->errorBase; + DGAEventBase = extEntry->eventBase; + for (i = KeyPress; i <= MotionNotify; i++) + SetCriticalEvent (DGAEventBase + i); + } +} + + + +static void +XDGAResetProc (ExtensionEntry *extEntry) +{ + DeleteCallback (&ClientStateCallback, DGAClientStateChange, NULL); + DGACallbackRefCount = 0; +} + + +static int +ProcXDGAQueryVersion(ClientPtr client) +{ + xXDGAQueryVersionReply rep; + + REQUEST_SIZE_MATCH(xXDGAQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_XDGA_MAJOR_VERSION; + rep.minorVersion = SERVER_XDGA_MINOR_VERSION; + + WriteToClient(client, sizeof(xXDGAQueryVersionReply), (char *)&rep); + return Success; +} + + +static int +ProcXDGAOpenFramebuffer(ClientPtr client) +{ + REQUEST(xXDGAOpenFramebufferReq); + xXDGAOpenFramebufferReply rep; + char *deviceName; + int nameSize; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + REQUEST_SIZE_MATCH(xXDGAOpenFramebufferReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if(!DGAOpenFramebuffer(stuff->screen, &deviceName, + (unsigned char**)(&rep.mem1), + (int*)&rep.size, (int*)&rep.offset, (int*)&rep.extra)) + { + return BadAlloc; + } + + nameSize = deviceName ? (strlen(deviceName) + 1) : 0; + rep.length = bytes_to_int32(nameSize); + + WriteToClient(client, sizeof(xXDGAOpenFramebufferReply), (char *)&rep); + if(rep.length) + WriteToClient(client, nameSize, deviceName); + + return Success; +} + + +static int +ProcXDGACloseFramebuffer(ClientPtr client) +{ + REQUEST(xXDGACloseFramebufferReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + REQUEST_SIZE_MATCH(xXDGACloseFramebufferReq); + + DGACloseFramebuffer(stuff->screen); + + return Success; +} + +static int +ProcXDGAQueryModes(ClientPtr client) +{ + int i, num, size; + REQUEST(xXDGAQueryModesReq); + xXDGAQueryModesReply rep; + xXDGAModeInfo info; + XDGAModePtr mode; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXDGAQueryModesReq); + rep.type = X_Reply; + rep.length = 0; + rep.number = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) { + rep.number = 0; + rep.length = 0; + WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); + return Success; + } + + if(!(num = DGAGetModes(stuff->screen))) { + WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); + return Success; + } + + if(!(mode = (XDGAModePtr)malloc(num * sizeof(XDGAModeRec)))) + return BadAlloc; + + for(i = 0; i < num; i++) + DGAGetModeInfo(stuff->screen, mode + i, i + 1); + + size = num * sz_xXDGAModeInfo; + for(i = 0; i < num; i++) + size += pad_to_int32(strlen(mode[i].name) + 1); /* plus NULL */ + + rep.number = num; + rep.length = bytes_to_int32(size); + + WriteToClient(client, sz_xXDGAQueryModesReply, (char*)&rep); + + for(i = 0; i < num; i++) { + size = strlen(mode[i].name) + 1; + + info.byte_order = mode[i].byteOrder; + info.depth = mode[i].depth; + info.num = mode[i].num; + info.bpp = mode[i].bitsPerPixel; + info.name_size = (size + 3) & ~3L; + info.vsync_num = mode[i].VSync_num; + info.vsync_den = mode[i].VSync_den; + info.flags = mode[i].flags; + info.image_width = mode[i].imageWidth; + info.image_height = mode[i].imageHeight; + info.pixmap_width = mode[i].pixmapWidth; + info.pixmap_height = mode[i].pixmapHeight; + info.bytes_per_scanline = mode[i].bytesPerScanline; + info.red_mask = mode[i].red_mask; + info.green_mask = mode[i].green_mask; + info.blue_mask = mode[i].blue_mask; + info.visual_class = mode[i].visualClass; + info.viewport_width = mode[i].viewportWidth; + info.viewport_height = mode[i].viewportHeight; + info.viewport_xstep = mode[i].xViewportStep; + info.viewport_ystep = mode[i].yViewportStep; + info.viewport_xmax = mode[i].maxViewportX; + info.viewport_ymax = mode[i].maxViewportY; + info.viewport_flags = mode[i].viewportFlags; + info.reserved1 = mode[i].reserved1; + info.reserved2 = mode[i].reserved2; + + WriteToClient(client, sz_xXDGAModeInfo, (char*)(&info)); + WriteToClient(client, size, mode[i].name); + } + + free(mode); + + return Success; +} + + +static void +DGAClientStateChange ( + CallbackListPtr* pcbl, + pointer nulldata, + pointer calldata +){ + NewClientInfoRec* pci = (NewClientInfoRec*) calldata; + ClientPtr client = NULL; + int i; + + for(i = 0; i < screenInfo.numScreens; i++) { + if(DGA_GETCLIENT(i) == pci->client) { + client = pci->client; + break; + } + } + + if(client && + ((client->clientState == ClientStateGone) || + (client->clientState == ClientStateRetained))) { + XDGAModeRec mode; + PixmapPtr pPix; + + DGA_SETCLIENT(i, NULL); + DGASelectInput(i, NULL, 0); + DGASetMode(i, 0, &mode, &pPix); + + if(--DGACallbackRefCount == 0) + DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); + } +} + +static int +ProcXDGASetMode(ClientPtr client) +{ + REQUEST(xXDGASetModeReq); + xXDGASetModeReply rep; + XDGAModeRec mode; + xXDGAModeInfo info; + PixmapPtr pPix; + ClientPtr owner; + int size; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + owner = DGA_GETCLIENT(stuff->screen); + + REQUEST_SIZE_MATCH(xXDGASetModeReq); + rep.type = X_Reply; + rep.length = 0; + rep.offset = 0; + rep.flags = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if(owner && owner != client) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if(!stuff->mode) { + if(owner) { + if(--DGACallbackRefCount == 0) + DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); + } + DGA_SETCLIENT(stuff->screen, NULL); + DGASelectInput(stuff->screen, NULL, 0); + DGASetMode(stuff->screen, 0, &mode, &pPix); + WriteToClient(client, sz_xXDGASetModeReply, (char*)&rep); + return Success; + } + + if(Success != DGASetMode(stuff->screen, stuff->mode, &mode, &pPix)) + return BadValue; + + if(!owner) { + if(DGACallbackRefCount++ == 0) + AddCallback (&ClientStateCallback, DGAClientStateChange, NULL); + } + + DGA_SETCLIENT(stuff->screen, client); + + if(pPix) { + if(AddResource(stuff->pid, RT_PIXMAP, (pointer)(pPix))) { + pPix->drawable.id = (int)stuff->pid; + rep.flags = DGA_PIXMAP_AVAILABLE; + } + } + + size = strlen(mode.name) + 1; + + info.byte_order = mode.byteOrder; + info.depth = mode.depth; + info.num = mode.num; + info.bpp = mode.bitsPerPixel; + info.name_size = (size + 3) & ~3L; + info.vsync_num = mode.VSync_num; + info.vsync_den = mode.VSync_den; + info.flags = mode.flags; + info.image_width = mode.imageWidth; + info.image_height = mode.imageHeight; + info.pixmap_width = mode.pixmapWidth; + info.pixmap_height = mode.pixmapHeight; + info.bytes_per_scanline = mode.bytesPerScanline; + info.red_mask = mode.red_mask; + info.green_mask = mode.green_mask; + info.blue_mask = mode.blue_mask; + info.visual_class = mode.visualClass; + info.viewport_width = mode.viewportWidth; + info.viewport_height = mode.viewportHeight; + info.viewport_xstep = mode.xViewportStep; + info.viewport_ystep = mode.yViewportStep; + info.viewport_xmax = mode.maxViewportX; + info.viewport_ymax = mode.maxViewportY; + info.viewport_flags = mode.viewportFlags; + info.reserved1 = mode.reserved1; + info.reserved2 = mode.reserved2; + + rep.length = bytes_to_int32(sz_xXDGAModeInfo + info.name_size); + + WriteToClient(client, sz_xXDGASetModeReply, (char*)&rep); + WriteToClient(client, sz_xXDGAModeInfo, (char*)(&info)); + WriteToClient(client, size, mode.name); + + return Success; +} + +static int +ProcXDGASetViewport(ClientPtr client) +{ + REQUEST(xXDGASetViewportReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASetViewportReq); + + DGASetViewport(stuff->screen, stuff->x, stuff->y, stuff->flags); + + return Success; +} + +static int +ProcXDGAInstallColormap(ClientPtr client) +{ + ColormapPtr cmap; + int rc; + REQUEST(xXDGAInstallColormapReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAInstallColormapReq); + + rc = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, RT_COLORMAP, + client, DixInstallAccess); + if (rc != Success) + return (rc == BadValue) ? BadColor : rc; + DGAInstallCmap(cmap); + return Success; +} + + +static int +ProcXDGASelectInput(ClientPtr client) +{ + REQUEST(xXDGASelectInputReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASelectInputReq); + + if(DGA_GETCLIENT(stuff->screen) == client) + DGASelectInput(stuff->screen, client, stuff->mask); + + return Success; +} + + +static int +ProcXDGAFillRectangle(ClientPtr client) +{ + REQUEST(xXDGAFillRectangleReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAFillRectangleReq); + + if(Success != DGAFillRect(stuff->screen, stuff->x, stuff->y, + stuff->width, stuff->height, stuff->color)) + return BadMatch; + + return Success; +} + +static int +ProcXDGACopyArea(ClientPtr client) +{ + REQUEST(xXDGACopyAreaReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACopyAreaReq); + + if(Success != DGABlitRect(stuff->screen, stuff->srcx, stuff->srcy, + stuff->width, stuff->height, stuff->dstx, stuff->dsty)) + return BadMatch; + + return Success; +} + + +static int +ProcXDGACopyTransparentArea(ClientPtr client) +{ + REQUEST(xXDGACopyTransparentAreaReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACopyTransparentAreaReq); + + if(Success != DGABlitTransRect(stuff->screen, stuff->srcx, stuff->srcy, + stuff->width, stuff->height, stuff->dstx, stuff->dsty, stuff->key)) + return BadMatch; + + return Success; +} + + +static int +ProcXDGAGetViewportStatus(ClientPtr client) +{ + REQUEST(xXDGAGetViewportStatusReq); + xXDGAGetViewportStatusReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAGetViewportStatusReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rep.status = DGAGetViewportStatus(stuff->screen); + + WriteToClient(client, sizeof(xXDGAGetViewportStatusReply), (char *)&rep); + return Success; +} + +static int +ProcXDGASync(ClientPtr client) +{ + REQUEST(xXDGASyncReq); + xXDGASyncReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGASyncReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + DGASync(stuff->screen); + + WriteToClient(client, sizeof(xXDGASyncReply), (char *)&rep); + return Success; +} + +static int +ProcXDGASetClientVersion(ClientPtr client) +{ + REQUEST(xXDGASetClientVersionReq); + + DGAPrivPtr pPriv; + + REQUEST_SIZE_MATCH(xXDGASetClientVersionReq); + if ((pPriv = DGA_GETPRIV(client)) == NULL) { + pPriv = malloc(sizeof(DGAPrivRec)); + /* XXX Need to look into freeing this */ + if (!pPriv) + return BadAlloc; + DGA_SETPRIV(client, pPriv); + } + pPriv->major = stuff->major; + pPriv->minor = stuff->minor; + + return Success; +} + +static int +ProcXDGAChangePixmapMode(ClientPtr client) +{ + REQUEST(xXDGAChangePixmapModeReq); + xXDGAChangePixmapModeReply rep; + int x, y; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGAChangePixmapModeReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + x = stuff->x; + y = stuff->y; + + if(!DGAChangePixmapMode(stuff->screen, &x, &y, stuff->flags)) + return BadMatch; + + rep.x = x; + rep.y = y; + WriteToClient(client, sizeof(xXDGAChangePixmapModeReply), (char *)&rep); + + return Success; +} + + +static int +ProcXDGACreateColormap(ClientPtr client) +{ + REQUEST(xXDGACreateColormapReq); + int result; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if(DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXDGACreateColormapReq); + + if(!stuff->mode) + return BadValue; + + result = DGACreateColormap(stuff->screen, client, stuff->id, + stuff->mode, stuff->alloc); + if(result != Success) + return result; + + return Success; +} + +/* + * + * Support for the old DGA protocol, used to live in xf86dga.c + * + */ + +#ifdef DGA_PROTOCOL_OLD_SUPPORT + +static DISPATCH_PROC(ProcXF86DGADirectVideo); +static DISPATCH_PROC(ProcXF86DGAGetVidPage); +static DISPATCH_PROC(ProcXF86DGAGetVideoLL); +static DISPATCH_PROC(ProcXF86DGAGetViewPortSize); +static DISPATCH_PROC(ProcXF86DGASetVidPage); +static DISPATCH_PROC(ProcXF86DGASetViewPort); +static DISPATCH_PROC(ProcXF86DGAInstallColormap); +static DISPATCH_PROC(ProcXF86DGAQueryDirectVideo); +static DISPATCH_PROC(ProcXF86DGAViewPortChanged); + + +static int +ProcXF86DGAGetVideoLL(ClientPtr client) +{ + REQUEST(xXF86DGAGetVideoLLReq); + xXF86DGAGetVideoLLReply rep; + XDGAModeRec mode; + int num, offset, flags; + char *name; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetVideoLLReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if(!DGAAvailable(stuff->screen)) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + if(!(num = DGAGetOldDGAMode(stuff->screen))) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + /* get the parameters for the mode that best matches */ + DGAGetModeInfo(stuff->screen, &mode, num); + + if(!DGAOpenFramebuffer(stuff->screen, &name, + (unsigned char**)(&rep.offset), + (int*)(&rep.bank_size), &offset, &flags)) + return BadAlloc; + + rep.offset += mode.offset; + rep.width = mode.bytesPerScanline / (mode.bitsPerPixel >> 3); + rep.ram_size = rep.bank_size >> 10; + + WriteToClient(client, SIZEOF(xXF86DGAGetVideoLLReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DGADirectVideo(ClientPtr client) +{ + int num; + PixmapPtr pix; + XDGAModeRec mode; + ClientPtr owner; + REQUEST(xXF86DGADirectVideoReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + owner = DGA_GETCLIENT(stuff->screen); + + REQUEST_SIZE_MATCH(xXF86DGADirectVideoReq); + + if (!DGAAvailable(stuff->screen)) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (owner && owner != client) + return DGAErrorBase + XF86DGANoDirectVideoMode; + + if (stuff->enable & XF86DGADirectGraphics) { + if(!(num = DGAGetOldDGAMode(stuff->screen))) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + } else + num = 0; + + if(Success != DGASetMode(stuff->screen, num, &mode, &pix)) + return (DGAErrorBase + XF86DGAScreenNotActive); + + DGASetInputMode (stuff->screen, + (stuff->enable & XF86DGADirectKeyb) != 0, + (stuff->enable & XF86DGADirectMouse) != 0); + + /* We need to track the client and attach the teardown callback */ + if (stuff->enable & + (XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse)) { + if (!owner) { + if (DGACallbackRefCount++ == 0) + AddCallback (&ClientStateCallback, DGAClientStateChange, NULL); + } + + DGA_SETCLIENT(stuff->screen, client); + } else { + if (owner) { + if (--DGACallbackRefCount == 0) + DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL); + } + + DGA_SETCLIENT(stuff->screen, NULL); + } + + return Success; +} + +static int +ProcXF86DGAGetViewPortSize(ClientPtr client) +{ + int num; + XDGAModeRec mode; + REQUEST(xXF86DGAGetViewPortSizeReq); + xXF86DGAGetViewPortSizeReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetViewPortSizeReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DGAAvailable(stuff->screen)) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + if(!(num = DGAGetOldDGAMode(stuff->screen))) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + DGAGetModeInfo(stuff->screen, &mode, num); + + rep.width = mode.viewportWidth; + rep.height = mode.viewportHeight; + + WriteToClient(client, SIZEOF(xXF86DGAGetViewPortSizeReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DGASetViewPort(ClientPtr client) +{ + REQUEST(xXF86DGASetViewPortReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXF86DGASetViewPortReq); + + if (!DGAAvailable(stuff->screen)) + return (DGAErrorBase + XF86DGANoDirectVideoMode); + + if (!DGAActive(stuff->screen)) + return DGAErrorBase + XF86DGADirectNotActivated; + + if (DGASetViewport(stuff->screen, stuff->x, stuff->y, DGA_FLIP_RETRACE) + != Success) + return DGAErrorBase + XF86DGADirectNotActivated; + + return Success; +} + +static int +ProcXF86DGAGetVidPage(ClientPtr client) +{ + REQUEST(xXF86DGAGetVidPageReq); + xXF86DGAGetVidPageReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAGetVidPageReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.vpage = 0; /* silently fail */ + + WriteToClient(client, SIZEOF(xXF86DGAGetVidPageReply), (char *)&rep); + return Success; +} + + +static int +ProcXF86DGASetVidPage(ClientPtr client) +{ + REQUEST(xXF86DGASetVidPageReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGASetVidPageReq); + + /* silently fail */ + + return Success; +} + + +static int +ProcXF86DGAInstallColormap(ClientPtr client) +{ + ColormapPtr pcmp; + int rc; + REQUEST(xXF86DGAInstallColormapReq); + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXF86DGAInstallColormapReq); + + if (!DGAActive(stuff->screen)) + return (DGAErrorBase + XF86DGADirectNotActivated); + + rc = dixLookupResourceByType((pointer *)&pcmp, stuff->id, RT_COLORMAP, + client, DixInstallAccess); + if (rc == Success) { + DGAInstallCmap(pcmp); + return Success; + } else { + return (rc == BadValue) ? BadColor : rc; + } +} + +static int +ProcXF86DGAQueryDirectVideo(ClientPtr client) +{ + REQUEST(xXF86DGAQueryDirectVideoReq); + xXF86DGAQueryDirectVideoReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86DGAQueryDirectVideoReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.flags = 0; + + if (DGAAvailable(stuff->screen)) + rep.flags = XF86DGADirectPresent; + + WriteToClient(client, SIZEOF(xXF86DGAQueryDirectVideoReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DGAViewPortChanged(ClientPtr client) +{ + REQUEST(xXF86DGAViewPortChangedReq); + xXF86DGAViewPortChangedReply rep; + + if (stuff->screen > screenInfo.numScreens) + return BadValue; + + if (DGA_GETCLIENT(stuff->screen) != client) + return DGAErrorBase + XF86DGADirectNotActivated; + + REQUEST_SIZE_MATCH(xXF86DGAViewPortChangedReq); + + if (!DGAActive(stuff->screen)) + return (DGAErrorBase + XF86DGADirectNotActivated); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.result = 1; + + WriteToClient(client, SIZEOF(xXF86DGAViewPortChangedReply), (char *)&rep); + return Success; +} + +#endif /* DGA_PROTOCOL_OLD_SUPPORT */ + +static int +SProcXDGADispatch (ClientPtr client) +{ + return DGAErrorBase + XF86DGAClientNotLocal; +} + +#if 0 +#define DGA_REQ_DEBUG +#endif + +#ifdef DGA_REQ_DEBUG +static char *dgaMinor[] = { + "QueryVersion", + "GetVideoLL", + "DirectVideo", + "GetViewPortSize", + "SetViewPort", + "GetVidPage", + "SetVidPage", + "InstallColormap", + "QueryDirectVideo", + "ViewPortChanged", + "10", + "11", + "QueryModes", + "SetMode", + "SetViewport", + "InstallColormap", + "SelectInput", + "FillRectangle", + "CopyArea", + "CopyTransparentArea", + "GetViewportStatus", + "Sync", + "OpenFramebuffer", + "CloseFramebuffer", + "SetClientVersion", + "ChangePixmapMode", + "CreateColormap", +}; +#endif + +static int +ProcXDGADispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (!LocalClient(client)) + return DGAErrorBase + XF86DGAClientNotLocal; + +#ifdef DGA_REQ_DEBUG + if (stuff->data <= X_XDGACreateColormap) + fprintf (stderr, " DGA %s\n", dgaMinor[stuff->data]); +#endif + + switch (stuff->data){ + /* + * DGA2 Protocol + */ + case X_XDGAQueryVersion: + return ProcXDGAQueryVersion(client); + case X_XDGAQueryModes: + return ProcXDGAQueryModes(client); + case X_XDGASetMode: + return ProcXDGASetMode(client); + case X_XDGAOpenFramebuffer: + return ProcXDGAOpenFramebuffer(client); + case X_XDGACloseFramebuffer: + return ProcXDGACloseFramebuffer(client); + case X_XDGASetViewport: + return ProcXDGASetViewport(client); + case X_XDGAInstallColormap: + return ProcXDGAInstallColormap(client); + case X_XDGASelectInput: + return ProcXDGASelectInput(client); + case X_XDGAFillRectangle: + return ProcXDGAFillRectangle(client); + case X_XDGACopyArea: + return ProcXDGACopyArea(client); + case X_XDGACopyTransparentArea: + return ProcXDGACopyTransparentArea(client); + case X_XDGAGetViewportStatus: + return ProcXDGAGetViewportStatus(client); + case X_XDGASync: + return ProcXDGASync(client); + case X_XDGASetClientVersion: + return ProcXDGASetClientVersion(client); + case X_XDGAChangePixmapMode: + return ProcXDGAChangePixmapMode(client); + case X_XDGACreateColormap: + return ProcXDGACreateColormap(client); + /* + * Old DGA Protocol + */ +#ifdef DGA_PROTOCOL_OLD_SUPPORT + case X_XF86DGAGetVideoLL: + return ProcXF86DGAGetVideoLL(client); + case X_XF86DGADirectVideo: + return ProcXF86DGADirectVideo(client); + case X_XF86DGAGetViewPortSize: + return ProcXF86DGAGetViewPortSize(client); + case X_XF86DGASetViewPort: + return ProcXF86DGASetViewPort(client); + case X_XF86DGAGetVidPage: + return ProcXF86DGAGetVidPage(client); + case X_XF86DGASetVidPage: + return ProcXF86DGASetVidPage(client); + case X_XF86DGAInstallColormap: + return ProcXF86DGAInstallColormap(client); + case X_XF86DGAQueryDirectVideo: + return ProcXF86DGAQueryDirectVideo(client); + case X_XF86DGAViewPortChanged: + return ProcXF86DGAViewPortChanged(client); +#endif /* DGA_PROTOCOL_OLD_SUPPORT */ + default: + return BadRequest; + } +} + +void +XFree86DGARegister(INITARGS) +{ + XDGAEventBase = &DGAEventBase; +} diff --git a/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c b/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c index a304a42d4..483b92ab1 100644 --- a/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c +++ b/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c @@ -1,2170 +1,2170 @@ - -/* - -Copyright 1995 Kaleb S. KEITHLEY - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES -OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of Kaleb S. KEITHLEY -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -from Kaleb S. KEITHLEY - -*/ -/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "scrnintstr.h" -#include "servermd.h" -#include -#include "swaprep.h" -#include "xf86.h" -#include "vidmodeproc.h" -#include "globals.h" -#include "protocol-versions.h" - -#define DEFAULT_XF86VIDMODE_VERBOSITY 3 - -static int VidModeErrorBase; -static int VidModeClientPrivateKeyIndex; -static DevPrivateKey VidModeClientPrivateKey = &VidModeClientPrivateKeyIndex; - -/* This holds the client's version information */ -typedef struct { - int major; - int minor; -} VidModePrivRec, *VidModePrivPtr; - -#define VM_GETPRIV(c) ((VidModePrivPtr) \ - dixLookupPrivate(&(c)->devPrivates, VidModeClientPrivateKey)) -#define VM_SETPRIV(c,p) \ - dixSetPrivate(&(c)->devPrivates, VidModeClientPrivateKey, p) - -static DISPATCH_PROC(ProcXF86VidModeDispatch); -static DISPATCH_PROC(ProcXF86VidModeGetAllModeLines); -static DISPATCH_PROC(ProcXF86VidModeGetModeLine); -static DISPATCH_PROC(ProcXF86VidModeGetMonitor); -static DISPATCH_PROC(ProcXF86VidModeLockModeSwitch); -static DISPATCH_PROC(ProcXF86VidModeAddModeLine); -static DISPATCH_PROC(ProcXF86VidModeDeleteModeLine); -static DISPATCH_PROC(ProcXF86VidModeModModeLine); -static DISPATCH_PROC(ProcXF86VidModeValidateModeLine); -static DISPATCH_PROC(ProcXF86VidModeQueryVersion); -static DISPATCH_PROC(ProcXF86VidModeSwitchMode); -static DISPATCH_PROC(ProcXF86VidModeSwitchToMode); -static DISPATCH_PROC(ProcXF86VidModeGetViewPort); -static DISPATCH_PROC(ProcXF86VidModeSetViewPort); -static DISPATCH_PROC(ProcXF86VidModeGetDotClocks); -static DISPATCH_PROC(ProcXF86VidModeSetGamma); -static DISPATCH_PROC(ProcXF86VidModeGetGamma); -static DISPATCH_PROC(ProcXF86VidModeSetClientVersion); -static DISPATCH_PROC(ProcXF86VidModeGetGammaRamp); -static DISPATCH_PROC(ProcXF86VidModeSetGammaRamp); -static DISPATCH_PROC(ProcXF86VidModeGetGammaRampSize); -static DISPATCH_PROC(SProcXF86VidModeDispatch); -static DISPATCH_PROC(SProcXF86VidModeGetAllModeLines); -static DISPATCH_PROC(SProcXF86VidModeGetModeLine); -static DISPATCH_PROC(SProcXF86VidModeGetMonitor); -static DISPATCH_PROC(SProcXF86VidModeLockModeSwitch); -static DISPATCH_PROC(SProcXF86VidModeAddModeLine); -static DISPATCH_PROC(SProcXF86VidModeDeleteModeLine); -static DISPATCH_PROC(SProcXF86VidModeModModeLine); -static DISPATCH_PROC(SProcXF86VidModeValidateModeLine); -static DISPATCH_PROC(SProcXF86VidModeQueryVersion); -static DISPATCH_PROC(SProcXF86VidModeSwitchMode); -static DISPATCH_PROC(SProcXF86VidModeSwitchToMode); -static DISPATCH_PROC(SProcXF86VidModeGetViewPort); -static DISPATCH_PROC(SProcXF86VidModeSetViewPort); -static DISPATCH_PROC(SProcXF86VidModeGetDotClocks); -static DISPATCH_PROC(SProcXF86VidModeSetGamma); -static DISPATCH_PROC(SProcXF86VidModeGetGamma); -static DISPATCH_PROC(SProcXF86VidModeSetClientVersion); -static DISPATCH_PROC(SProcXF86VidModeGetGammaRamp); -static DISPATCH_PROC(SProcXF86VidModeSetGammaRamp); -static DISPATCH_PROC(SProcXF86VidModeGetGammaRampSize); - -#if 0 -static unsigned char XF86VidModeReqCode = 0; -#endif - -/* The XF86VIDMODE_EVENTS code is far from complete */ - -#ifdef XF86VIDMODE_EVENTS -static int XF86VidModeEventBase = 0; - -static void SXF86VidModeNotifyEvent(); - xXF86VidModeNotifyEvent * /* from */, - xXF86VidModeNotifyEvent * /* to */ -); - -static RESTYPE EventType; /* resource type for event masks */ - -typedef struct _XF86VidModeEvent *XF86VidModeEventPtr; - -typedef struct _XF86VidModeEvent { - XF86VidModeEventPtr next; - ClientPtr client; - ScreenPtr screen; - XID resource; - CARD32 mask; -} XF86VidModeEventRec; - -static int XF86VidModeFreeEvents(); - -typedef struct _XF86VidModeScreenPrivate { - XF86VidModeEventPtr events; - Bool hasWindow; -} XF86VidModeScreenPrivateRec, *XF86VidModeScreenPrivatePtr; - -static int ScreenPrivateKeyIndex; -static DevPrivateKey ScreenPrivateKey = &ScreenPrivateKeyIndex; - -#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \ - dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey)) -#define SetScreenPrivate(s,v) \ - dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v) -#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = GetScreenPrivate(s) - -#define New(t) (xalloc (sizeof (t))) -#endif - -#ifdef DEBUG -# define DEBUG_P(x) ErrorF(x"\n"); -#else -# define DEBUG_P(x) /**/ -#endif - -void -XFree86VidModeExtensionInit(void) -{ - ExtensionEntry* extEntry; - ScreenPtr pScreen; - int i; - Bool enabled = FALSE; - - DEBUG_P("XFree86VidModeExtensionInit"); - -#ifdef XF86VIDMODE_EVENTS - EventType = CreateNewResourceType(XF86VidModeFreeEvents, "VidModeEvent"); -#endif - - for(i = 0; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - if (VidModeExtensionInit(pScreen)) - enabled = TRUE; -#ifdef XF86VIDMODE_EVENTS - SetScreenPrivate (pScreen, NULL); -#endif - } - /* This means that the DDX doesn't want the vidmode extension enabled */ - if (!enabled) - return; - - if ( -#ifdef XF86VIDMODE_EVENTS - EventType && -#endif - (extEntry = AddExtension(XF86VIDMODENAME, - XF86VidModeNumberEvents, - XF86VidModeNumberErrors, - ProcXF86VidModeDispatch, - SProcXF86VidModeDispatch, - NULL, - StandardMinorOpcode))) { -#if 0 - XF86VidModeReqCode = (unsigned char)extEntry->base; -#endif - VidModeErrorBase = extEntry->errorBase; -#ifdef XF86VIDMODE_EVENTS - XF86VidModeEventBase = extEntry->eventBase; - EventSwapVector[XF86VidModeEventBase] = (EventSwapPtr)SXF86VidModeNotifyEvent; -#endif - } -} - -static int -ClientMajorVersion(ClientPtr client) -{ - VidModePrivPtr pPriv; - - pPriv = VM_GETPRIV(client); - if (!pPriv) - return 0; - else - return pPriv->major; -} - -#ifdef XF86VIDMODE_EVENTS -static void -CheckScreenPrivate (pScreen) - ScreenPtr pScreen; -{ - SetupScreen (pScreen); - - if (!pPriv) - return; - if (!pPriv->events && !pPriv->hasWindow) { - xfree (pPriv); - SetScreenPrivate (pScreen, NULL); - } -} - -static XF86VidModeScreenPrivatePtr -MakeScreenPrivate (pScreen) - ScreenPtr pScreen; -{ - SetupScreen (pScreen); - - if (pPriv) - return pPriv; - pPriv = New (XF86VidModeScreenPrivateRec); - if (!pPriv) - return 0; - pPriv->events = 0; - pPriv->hasWindow = FALSE; - SetScreenPrivate (pScreen, pPriv); - return pPriv; -} - -static unsigned long -getEventMask (ScreenPtr pScreen, ClientPtr client) -{ - SetupScreen(pScreen); - XF86VidModeEventPtr pEv; - - if (!pPriv) - return 0; - for (pEv = pPriv->events; pEv; pEv = pEv->next) - if (pEv->client == client) - return pEv->mask; - return 0; -} - -static Bool -setEventMask (ScreenPtr pScreen, ClientPtr client, unsigned long mask) -{ - SetupScreen(pScreen); - XF86VidModeEventPtr pEv, *pPrev; - - if (getEventMask (pScreen, client) == mask) - return TRUE; - if (!pPriv) { - pPriv = MakeScreenPrivate (pScreen); - if (!pPriv) - return FALSE; - } - for (pPrev = &pPriv->events; pEv = *pPrev; pPrev = &pEv->next) - if (pEv->client == client) - break; - if (mask == 0) { - *pPrev = pEv->next; - xfree (pEv); - CheckScreenPrivate (pScreen); - } else { - if (!pEv) { - pEv = New (ScreenSaverEventRec); - if (!pEv) { - CheckScreenPrivate (pScreen); - return FALSE; - } - *pPrev = pEv; - pEv->next = NULL; - pEv->client = client; - pEv->screen = pScreen; - pEv->resource = FakeClientID (client->index); - } - pEv->mask = mask; - } - return TRUE; -} - -static int -XF86VidModeFreeEvents(pointer value, XID id) -{ - XF86VidModeEventPtr pOld = (XF86VidModeEventPtr)value; - ScreenPtr pScreen = pOld->screen; - SetupScreen (pScreen); - XF86VidModeEventPtr pEv, *pPrev; - - if (!pPriv) - return TRUE; - for (pPrev = &pPriv->events; pEv = *pPrev; pPrev = &pEv->next) - if (pEv == pOld) - break; - if (!pEv) - return TRUE; - *pPrev = pEv->next; - xfree (pEv); - CheckScreenPrivate (pScreen); - return TRUE; -} - -static void -SendXF86VidModeNotify(ScreenPtr pScreen, int state, Bool forced) -{ - XF86VidModeScreenPrivatePtr pPriv; - XF86VidModeEventPtr pEv; - unsigned long mask; - xXF86VidModeNotifyEvent ev; - ClientPtr client; - int kind; - - UpdateCurrentTimeIf (); - mask = XF86VidModeNotifyMask; - pScreen = screenInfo.screens[pScreen->myNum]; - pPriv = GetScreenPrivate(pScreen); - if (!pPriv) - return; - kind = XF86VidModeModeChange; - for (pEv = pPriv->events; pEv; pEv = pEv->next) - { - client = pEv->client; - if (client->clientGone) - continue; - if (!(pEv->mask & mask)) - continue; - ev.type = XF86VidModeNotify + XF86VidModeEventBase; - ev.state = state; - ev.sequenceNumber = client->sequence; - ev.timestamp = currentTime.milliseconds; - ev.root = WindowTable[pScreen->myNum]->drawable.id; - ev.kind = kind; - ev.forced = forced; - WriteEventsToClient (client, 1, (xEvent *) &ev); - } -} - -static void -SXF86VidModeNotifyEvent(xXF86VidModeNotifyEvent *from, - xXF86VidModeNotifyEvent *to) -{ - to->type = from->type; - to->state = from->state; - cpswaps (from->sequenceNumber, to->sequenceNumber); - cpswapl (from->timestamp, to->timestamp); - cpswapl (from->root, to->root); - to->kind = from->kind; - to->forced = from->forced; -} -#endif - -static int -ProcXF86VidModeQueryVersion(ClientPtr client) -{ - xXF86VidModeQueryVersionReply rep; - register int n; - - DEBUG_P("XF86VidModeQueryVersion"); - - REQUEST_SIZE_MATCH(xXF86VidModeQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_XF86VIDMODE_MAJOR_VERSION; - rep.minorVersion = SERVER_XF86VIDMODE_MINOR_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof(xXF86VidModeQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86VidModeGetModeLine(ClientPtr client) -{ - REQUEST(xXF86VidModeGetModeLineReq); - xXF86VidModeGetModeLineReply rep; - xXF86OldVidModeGetModeLineReply oldrep; - pointer mode; - register int n; - int dotClock; - int ver; - - DEBUG_P("XF86VidModeGetModeline"); - - ver = ClientMajorVersion(client); - REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq); - rep.type = X_Reply; - if (ver < 2) { - rep.length = bytes_to_int32(SIZEOF(xXF86OldVidModeGetModeLineReply) - - SIZEOF(xGenericReply)); - } else { - rep.length = bytes_to_int32(SIZEOF(xXF86VidModeGetModeLineReply) - - SIZEOF(xGenericReply)); - } - rep.sequenceNumber = client->sequence; - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) - return BadValue; - - rep.dotclock = dotClock; - rep.hdisplay = VidModeGetModeValue(mode, VIDMODE_H_DISPLAY); - rep.hsyncstart = VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART); - rep.hsyncend = VidModeGetModeValue(mode, VIDMODE_H_SYNCEND); - rep.htotal = VidModeGetModeValue(mode, VIDMODE_H_TOTAL); - rep.hskew = VidModeGetModeValue(mode, VIDMODE_H_SKEW); - rep.vdisplay = VidModeGetModeValue(mode, VIDMODE_V_DISPLAY); - rep.vsyncstart = VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART); - rep.vsyncend = VidModeGetModeValue(mode, VIDMODE_V_SYNCEND); - rep.vtotal = VidModeGetModeValue(mode, VIDMODE_V_TOTAL); - rep.flags = VidModeGetModeValue(mode, VIDMODE_FLAGS); - - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("GetModeLine - scrn: %d clock: %ld\n", - stuff->screen, (unsigned long)rep.dotclock); - ErrorF("GetModeLine - hdsp: %d hbeg: %d hend: %d httl: %d\n", - rep.hdisplay, rep.hsyncstart, - rep.hsyncend, rep.htotal); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", - rep.vdisplay, rep.vsyncstart, rep.vsyncend, - rep.vtotal, (unsigned long)rep.flags); - } - - /* - * Older servers sometimes had server privates that the VidMode - * extention made available. So to be compatiable pretend that - * there are no server privates to pass to the client - */ - rep.privsize = 0; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.dotclock, n); - swaps(&rep.hdisplay, n); - swaps(&rep.hsyncstart, n); - swaps(&rep.hsyncend, n); - swaps(&rep.htotal, n); - swaps(&rep.hskew, n); - swaps(&rep.vdisplay, n); - swaps(&rep.vsyncstart, n); - swaps(&rep.vsyncend, n); - swaps(&rep.vtotal, n); - swapl(&rep.flags, n); - swapl(&rep.privsize, n); - } - if (ver < 2) { - oldrep.type = rep.type; - oldrep.sequenceNumber = rep.sequenceNumber; - oldrep.length = rep.length; - oldrep.dotclock = rep.dotclock; - oldrep.hdisplay = rep.hdisplay; - oldrep.hsyncstart = rep.hsyncstart; - oldrep.hsyncend = rep.hsyncend; - oldrep.htotal = rep.htotal; - oldrep.vdisplay = rep.vdisplay; - oldrep.vsyncstart = rep.vsyncstart; - oldrep.vsyncend = rep.vsyncend; - oldrep.vtotal = rep.vtotal; - oldrep.flags = rep.flags; - oldrep.privsize = rep.privsize; - WriteToClient(client, sizeof(xXF86OldVidModeGetModeLineReply), - (char *)&oldrep); - } else { - WriteToClient(client, sizeof(xXF86VidModeGetModeLineReply), - (char *)&rep); - } - return (client->noClientException); -} - -static int -ProcXF86VidModeGetAllModeLines(ClientPtr client) -{ - REQUEST(xXF86VidModeGetAllModeLinesReq); - xXF86VidModeGetAllModeLinesReply rep; - xXF86VidModeModeInfo mdinf; - xXF86OldVidModeModeInfo oldmdinf; - pointer mode; - int modecount, dotClock; - register int n; - int ver; - - DEBUG_P("XF86VidModeGetAllModelines"); - - REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - ver = ClientMajorVersion(client); - - modecount = VidModeGetNumOfModes(stuff->screen); - if (modecount < 1) - return (VidModeErrorBase + XF86VidModeExtensionDisabled); - - if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) - return BadValue; - - rep.type = X_Reply; - rep.length = SIZEOF(xXF86VidModeGetAllModeLinesReply) - - SIZEOF(xGenericReply); - if (ver < 2) - rep.length += modecount * sizeof(xXF86OldVidModeModeInfo); - else - rep.length += modecount * sizeof(xXF86VidModeModeInfo); - rep.length >>= 2; - rep.sequenceNumber = client->sequence; - rep.modecount = modecount; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.modecount, n); - } - WriteToClient(client, sizeof(xXF86VidModeGetAllModeLinesReply), (char *)&rep); - - do { - mdinf.dotclock = dotClock; - mdinf.hdisplay = VidModeGetModeValue(mode, VIDMODE_H_DISPLAY); - mdinf.hsyncstart = VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART); - mdinf.hsyncend = VidModeGetModeValue(mode, VIDMODE_H_SYNCEND); - mdinf.htotal = VidModeGetModeValue(mode, VIDMODE_H_TOTAL); - mdinf.hskew = VidModeGetModeValue(mode, VIDMODE_H_SKEW); - mdinf.vdisplay = VidModeGetModeValue(mode, VIDMODE_V_DISPLAY); - mdinf.vsyncstart = VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART); - mdinf.vsyncend = VidModeGetModeValue(mode, VIDMODE_V_SYNCEND); - mdinf.vtotal = VidModeGetModeValue(mode, VIDMODE_V_TOTAL); - mdinf.flags = VidModeGetModeValue(mode, VIDMODE_FLAGS); - mdinf.privsize = 0; - if (client->swapped) { - swapl(&mdinf.dotclock, n); - swaps(&mdinf.hdisplay, n); - swaps(&mdinf.hsyncstart, n); - swaps(&mdinf.hsyncend, n); - swaps(&mdinf.htotal, n); - swaps(&mdinf.hskew, n); - swaps(&mdinf.vdisplay, n); - swaps(&mdinf.vsyncstart, n); - swaps(&mdinf.vsyncend, n); - swaps(&mdinf.vtotal, n); - swapl(&mdinf.flags, n); - swapl(&mdinf.privsize, n); - } - if (ver < 2) { - oldmdinf.dotclock = mdinf.dotclock; - oldmdinf.hdisplay = mdinf.hdisplay; - oldmdinf.hsyncstart = mdinf.hsyncstart; - oldmdinf.hsyncend = mdinf.hsyncend; - oldmdinf.htotal = mdinf.htotal; - oldmdinf.vdisplay = mdinf.vdisplay; - oldmdinf.vsyncstart = mdinf.vsyncstart; - oldmdinf.vsyncend = mdinf.vsyncend; - oldmdinf.vtotal = mdinf.vtotal; - oldmdinf.flags = mdinf.flags; - oldmdinf.privsize = mdinf.privsize; - WriteToClient(client, sizeof(xXF86OldVidModeModeInfo), - (char *)&oldmdinf); - } else { - WriteToClient(client, sizeof(xXF86VidModeModeInfo), (char *)&mdinf); - } - - } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); - - return (client->noClientException); -} - -#define MODEMATCH(mode,stuff) \ - (VidModeGetModeValue(mode, VIDMODE_H_DISPLAY) == stuff->hdisplay \ - && VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART) == stuff->hsyncstart \ - && VidModeGetModeValue(mode, VIDMODE_H_SYNCEND) == stuff->hsyncend \ - && VidModeGetModeValue(mode, VIDMODE_H_TOTAL) == stuff->htotal \ - && VidModeGetModeValue(mode, VIDMODE_V_DISPLAY) == stuff->vdisplay \ - && VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART) == stuff->vsyncstart \ - && VidModeGetModeValue(mode, VIDMODE_V_SYNCEND) == stuff->vsyncend \ - && VidModeGetModeValue(mode, VIDMODE_V_TOTAL) == stuff->vtotal \ - && VidModeGetModeValue(mode, VIDMODE_FLAGS) == stuff->flags ) - -static int -ProcXF86VidModeAddModeLine(ClientPtr client) -{ - REQUEST(xXF86VidModeAddModeLineReq); - xXF86OldVidModeAddModeLineReq *oldstuff = - (xXF86OldVidModeAddModeLineReq *)client->requestBuffer; - xXF86VidModeAddModeLineReq newstuff; - pointer mode; - int len; - int dotClock; - int ver; - - DEBUG_P("XF86VidModeAddModeline"); - - ver = ClientMajorVersion(client); - if (ver < 2) { - /* convert from old format */ - stuff = &newstuff; - stuff->length = oldstuff->length; - stuff->screen = oldstuff->screen; - stuff->dotclock = oldstuff->dotclock; - stuff->hdisplay = oldstuff->hdisplay; - stuff->hsyncstart = oldstuff->hsyncstart; - stuff->hsyncend = oldstuff->hsyncend; - stuff->htotal = oldstuff->htotal; - stuff->hskew = 0; - stuff->vdisplay = oldstuff->vdisplay; - stuff->vsyncstart = oldstuff->vsyncstart; - stuff->vsyncend = oldstuff->vsyncend; - stuff->vtotal = oldstuff->vtotal; - stuff->flags = oldstuff->flags; - stuff->privsize = oldstuff->privsize; - stuff->after_dotclock = oldstuff->after_dotclock; - stuff->after_hdisplay = oldstuff->after_hdisplay; - stuff->after_hsyncstart = oldstuff->after_hsyncstart; - stuff->after_hsyncend = oldstuff->after_hsyncend; - stuff->after_htotal = oldstuff->after_htotal; - stuff->after_hskew = 0; - stuff->after_vdisplay = oldstuff->after_vdisplay; - stuff->after_vsyncstart = oldstuff->after_vsyncstart; - stuff->after_vsyncend = oldstuff->after_vsyncend; - stuff->after_vtotal = oldstuff->after_vtotal; - stuff->after_flags = oldstuff->after_flags; - } - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("AddModeLine - scrn: %d clock: %ld\n", - (int)stuff->screen, (unsigned long)stuff->dotclock); - ErrorF("AddModeLine - hdsp: %d hbeg: %d hend: %d httl: %d\n", - stuff->hdisplay, stuff->hsyncstart, - stuff->hsyncend, stuff->htotal); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", - stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, - stuff->vtotal, (unsigned long)stuff->flags); - ErrorF(" after - scrn: %d clock: %ld\n", - (int)stuff->screen, (unsigned long)stuff->after_dotclock); - ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", - stuff->after_hdisplay, stuff->after_hsyncstart, - stuff->after_hsyncend, stuff->after_htotal); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", - stuff->after_vdisplay, stuff->after_vsyncstart, - stuff->after_vsyncend, stuff->after_vtotal, - (unsigned long)stuff->after_flags); - } - - if (ver < 2) { - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeAddModeLineReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86OldVidModeAddModeLineReq)); - } else { - REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeAddModeLineReq)); - } - if (len != stuff->privsize) - return BadLength; - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (stuff->hsyncstart < stuff->hdisplay || - stuff->hsyncend < stuff->hsyncstart || - stuff->htotal < stuff->hsyncend || - stuff->vsyncstart < stuff->vdisplay || - stuff->vsyncend < stuff->vsyncstart || - stuff->vtotal < stuff->vsyncend) - return BadValue; - - if (stuff->after_hsyncstart < stuff->after_hdisplay || - stuff->after_hsyncend < stuff->after_hsyncstart || - stuff->after_htotal < stuff->after_hsyncend || - stuff->after_vsyncstart < stuff->after_vdisplay || - stuff->after_vsyncend < stuff->after_vsyncstart || - stuff->after_vtotal < stuff->after_vsyncend) - return BadValue; - - if (stuff->after_htotal != 0 || stuff->after_vtotal != 0) { - Bool found = FALSE; - if (VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) { - do { - if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) - == dotClock) && MODEMATCH(mode, stuff)) { - found = TRUE; - break; - } - } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); - } - if (!found) - return BadValue; - } - - - mode = VidModeCreateMode(); - if (mode == NULL) - return BadValue; - - VidModeSetModeValue(mode, VIDMODE_CLOCK, stuff->dotclock); - VidModeSetModeValue(mode, VIDMODE_H_DISPLAY, stuff->hdisplay); - VidModeSetModeValue(mode, VIDMODE_H_SYNCSTART, stuff->hsyncstart); - VidModeSetModeValue(mode, VIDMODE_H_SYNCEND, stuff->hsyncend); - VidModeSetModeValue(mode, VIDMODE_H_TOTAL, stuff->htotal); - VidModeSetModeValue(mode, VIDMODE_H_SKEW, stuff->hskew); - VidModeSetModeValue(mode, VIDMODE_V_DISPLAY, stuff->vdisplay); - VidModeSetModeValue(mode, VIDMODE_V_SYNCSTART, stuff->vsyncstart); - VidModeSetModeValue(mode, VIDMODE_V_SYNCEND, stuff->vsyncend); - VidModeSetModeValue(mode, VIDMODE_V_TOTAL, stuff->vtotal); - VidModeSetModeValue(mode, VIDMODE_FLAGS, stuff->flags); - - if (stuff->privsize) - ErrorF("AddModeLine - Privates in request have been ignored\n"); - - /* Check that the mode is consistent with the monitor specs */ - switch (VidModeCheckModeForMonitor(stuff->screen, mode)) { - case MODE_OK: - break; - case MODE_HSYNC: - case MODE_H_ILLEGAL: - xfree(mode); - return VidModeErrorBase + XF86VidModeBadHTimings; - case MODE_VSYNC: - case MODE_V_ILLEGAL: - xfree(mode); - return VidModeErrorBase + XF86VidModeBadVTimings; - default: - xfree(mode); - return VidModeErrorBase + XF86VidModeModeUnsuitable; - } - - /* Check that the driver is happy with the mode */ - if (VidModeCheckModeForDriver(stuff->screen, mode) != MODE_OK) { - xfree(mode); - return VidModeErrorBase + XF86VidModeModeUnsuitable; - } - - VidModeSetCrtcForMode(stuff->screen, mode); - - VidModeAddModeline(stuff->screen, mode); - - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) - ErrorF("AddModeLine - Succeeded\n"); - return client->noClientException; -} - -static int -ProcXF86VidModeDeleteModeLine(ClientPtr client) -{ - REQUEST(xXF86VidModeDeleteModeLineReq); - xXF86OldVidModeDeleteModeLineReq *oldstuff = - (xXF86OldVidModeDeleteModeLineReq *)client->requestBuffer; - xXF86VidModeDeleteModeLineReq newstuff; - pointer mode; - int len, dotClock; - int ver; - - DEBUG_P("XF86VidModeDeleteModeline"); - - ver = ClientMajorVersion(client); - if (ver < 2) { - /* convert from old format */ - stuff = &newstuff; - stuff->length = oldstuff->length; - stuff->screen = oldstuff->screen; - stuff->dotclock = oldstuff->dotclock; - stuff->hdisplay = oldstuff->hdisplay; - stuff->hsyncstart = oldstuff->hsyncstart; - stuff->hsyncend = oldstuff->hsyncend; - stuff->htotal = oldstuff->htotal; - stuff->hskew = 0; - stuff->vdisplay = oldstuff->vdisplay; - stuff->vsyncstart = oldstuff->vsyncstart; - stuff->vsyncend = oldstuff->vsyncend; - stuff->vtotal = oldstuff->vtotal; - stuff->flags = oldstuff->flags; - stuff->privsize = oldstuff->privsize; - } - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("DeleteModeLine - scrn: %d clock: %ld\n", - (int)stuff->screen, (unsigned long)stuff->dotclock); - ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", - stuff->hdisplay, stuff->hsyncstart, - stuff->hsyncend, stuff->htotal); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", - stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, - stuff->vtotal, (unsigned long)stuff->flags); - } - - if (ver < 2) { - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeDeleteModeLineReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86OldVidModeDeleteModeLineReq)); - } else { - REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeDeleteModeLineReq)); - } - if (len != stuff->privsize) { - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("req_len = %ld, sizeof(Req) = %d, privsize = %ld, " - "len = %d, length = %d\n", - (unsigned long)client->req_len, - (int)sizeof(xXF86VidModeDeleteModeLineReq)>>2, - (unsigned long)stuff->privsize, len, stuff->length); - } - return BadLength; - } - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) - return BadValue; - - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("Checking against clock: %d (%d)\n", - VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); - ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", - VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), - VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), - VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), - VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", - VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), - VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), - VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), - VidModeGetModeValue(mode, VIDMODE_V_TOTAL), - VidModeGetModeValue(mode, VIDMODE_FLAGS)); - } - if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && - MODEMATCH(mode, stuff)) - return BadValue; - - if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) - return BadValue; - - do { - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("Checking against clock: %d (%d)\n", - VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); - ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", - VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), - VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), - VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), - VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", - VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), - VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), - VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), - VidModeGetModeValue(mode, VIDMODE_V_TOTAL), - VidModeGetModeValue(mode, VIDMODE_FLAGS)); - } - if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && - MODEMATCH(mode, stuff)) { - VidModeDeleteModeline(stuff->screen, mode); - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) - ErrorF("DeleteModeLine - Succeeded\n"); - return(client->noClientException); - } - } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); - - return BadValue; -} - -static int -ProcXF86VidModeModModeLine(ClientPtr client) -{ - REQUEST(xXF86VidModeModModeLineReq); - xXF86OldVidModeModModeLineReq *oldstuff = - (xXF86OldVidModeModModeLineReq *)client->requestBuffer; - xXF86VidModeModModeLineReq newstuff; - pointer mode, modetmp; - int len, dotClock; - int ver; - - DEBUG_P("XF86VidModeModModeline"); - - ver = ClientMajorVersion(client); - if (ver < 2 ) { - /* convert from old format */ - stuff = &newstuff; - stuff->length = oldstuff->length; - stuff->screen = oldstuff->screen; - stuff->hdisplay = oldstuff->hdisplay; - stuff->hsyncstart = oldstuff->hsyncstart; - stuff->hsyncend = oldstuff->hsyncend; - stuff->htotal = oldstuff->htotal; - stuff->hskew = 0; - stuff->vdisplay = oldstuff->vdisplay; - stuff->vsyncstart = oldstuff->vsyncstart; - stuff->vsyncend = oldstuff->vsyncend; - stuff->vtotal = oldstuff->vtotal; - stuff->flags = oldstuff->flags; - stuff->privsize = oldstuff->privsize; - } - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("ModModeLine - scrn: %d hdsp: %d hbeg: %d hend: %d httl: %d\n", - (int)stuff->screen, stuff->hdisplay, stuff->hsyncstart, - stuff->hsyncend, stuff->htotal); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", - stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, - stuff->vtotal, (unsigned long)stuff->flags); - } - - if (ver < 2) { - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeModModeLineReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86OldVidModeModModeLineReq)); - } else { - REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeModModeLineReq)); - } - if (len != stuff->privsize) - return BadLength; - - if (stuff->hsyncstart < stuff->hdisplay || - stuff->hsyncend < stuff->hsyncstart || - stuff->htotal < stuff->hsyncend || - stuff->vsyncstart < stuff->vdisplay || - stuff->vsyncend < stuff->vsyncstart || - stuff->vtotal < stuff->vsyncend) - return BadValue; - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) - return BadValue; - - modetmp = VidModeCreateMode(); - VidModeCopyMode(mode, modetmp); - - VidModeSetModeValue(modetmp, VIDMODE_H_DISPLAY, stuff->hdisplay); - VidModeSetModeValue(modetmp, VIDMODE_H_SYNCSTART, stuff->hsyncstart); - VidModeSetModeValue(modetmp, VIDMODE_H_SYNCEND, stuff->hsyncend); - VidModeSetModeValue(modetmp, VIDMODE_H_TOTAL, stuff->htotal); - VidModeSetModeValue(modetmp, VIDMODE_H_SKEW, stuff->hskew); - VidModeSetModeValue(modetmp, VIDMODE_V_DISPLAY, stuff->vdisplay); - VidModeSetModeValue(modetmp, VIDMODE_V_SYNCSTART, stuff->vsyncstart); - VidModeSetModeValue(modetmp, VIDMODE_V_SYNCEND, stuff->vsyncend); - VidModeSetModeValue(modetmp, VIDMODE_V_TOTAL, stuff->vtotal); - VidModeSetModeValue(modetmp, VIDMODE_FLAGS, stuff->flags); - - if (stuff->privsize) - ErrorF("ModModeLine - Privates in request have been ignored\n"); - - /* Check that the mode is consistent with the monitor specs */ - switch (VidModeCheckModeForMonitor(stuff->screen, modetmp)) { - case MODE_OK: - break; - case MODE_HSYNC: - case MODE_H_ILLEGAL: - xfree(modetmp); - return VidModeErrorBase + XF86VidModeBadHTimings; - case MODE_VSYNC: - case MODE_V_ILLEGAL: - xfree(modetmp); - return VidModeErrorBase + XF86VidModeBadVTimings; - default: - xfree(modetmp); - return VidModeErrorBase + XF86VidModeModeUnsuitable; - } - - /* Check that the driver is happy with the mode */ - if (VidModeCheckModeForDriver(stuff->screen, modetmp) != MODE_OK) { - xfree(modetmp); - return VidModeErrorBase + XF86VidModeModeUnsuitable; - } - xfree(modetmp); - - VidModeSetModeValue(mode, VIDMODE_H_DISPLAY, stuff->hdisplay); - VidModeSetModeValue(mode, VIDMODE_H_SYNCSTART, stuff->hsyncstart); - VidModeSetModeValue(mode, VIDMODE_H_SYNCEND, stuff->hsyncend); - VidModeSetModeValue(mode, VIDMODE_H_TOTAL, stuff->htotal); - VidModeSetModeValue(mode, VIDMODE_H_SKEW, stuff->hskew); - VidModeSetModeValue(mode, VIDMODE_V_DISPLAY, stuff->vdisplay); - VidModeSetModeValue(mode, VIDMODE_V_SYNCSTART, stuff->vsyncstart); - VidModeSetModeValue(mode, VIDMODE_V_SYNCEND, stuff->vsyncend); - VidModeSetModeValue(mode, VIDMODE_V_TOTAL, stuff->vtotal); - VidModeSetModeValue(mode, VIDMODE_FLAGS, stuff->flags); - - VidModeSetCrtcForMode(stuff->screen, mode); - VidModeSwitchMode(stuff->screen, mode); - - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) - ErrorF("ModModeLine - Succeeded\n"); - return(client->noClientException); -} - -static int -ProcXF86VidModeValidateModeLine(ClientPtr client) -{ - REQUEST(xXF86VidModeValidateModeLineReq); - xXF86OldVidModeValidateModeLineReq *oldstuff = - (xXF86OldVidModeValidateModeLineReq *)client->requestBuffer; - xXF86VidModeValidateModeLineReq newstuff; - xXF86VidModeValidateModeLineReply rep; - pointer mode, modetmp = NULL; - int len, status, dotClock; - int ver; - - DEBUG_P("XF86VidModeValidateModeline"); - - ver = ClientMajorVersion(client); - if (ver < 2) { - /* convert from old format */ - stuff = &newstuff; - stuff->length = oldstuff->length; - stuff->screen = oldstuff->screen; - stuff->dotclock = oldstuff->dotclock; - stuff->hdisplay = oldstuff->hdisplay; - stuff->hsyncstart = oldstuff->hsyncstart; - stuff->hsyncend = oldstuff->hsyncend; - stuff->htotal = oldstuff->htotal; - stuff->hskew = 0; - stuff->vdisplay = oldstuff->vdisplay; - stuff->vsyncstart = oldstuff->vsyncstart; - stuff->vsyncend = oldstuff->vsyncend; - stuff->vtotal = oldstuff->vtotal; - stuff->flags = oldstuff->flags; - stuff->privsize = oldstuff->privsize; - } - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("ValidateModeLine - scrn: %d clock: %ld\n", - (int)stuff->screen, (unsigned long)stuff->dotclock); - ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", - stuff->hdisplay, stuff->hsyncstart, - stuff->hsyncend, stuff->htotal); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", - stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, - stuff->vtotal, (unsigned long)stuff->flags); - } - - if (ver < 2) { - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeValidateModeLineReq); - len = client->req_len - - bytes_to_int32(sizeof(xXF86OldVidModeValidateModeLineReq)); - } else { - REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeValidateModeLineReq)); - } - if (len != stuff->privsize) - return BadLength; - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - status = MODE_OK; - - if (stuff->hsyncstart < stuff->hdisplay || - stuff->hsyncend < stuff->hsyncstart || - stuff->htotal < stuff->hsyncend || - stuff->vsyncstart < stuff->vdisplay || - stuff->vsyncend < stuff->vsyncstart || - stuff->vtotal < stuff->vsyncend) - { - status = MODE_BAD; - goto status_reply; - } - - if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) - return BadValue; - - modetmp = VidModeCreateMode(); - VidModeCopyMode(mode, modetmp); - - VidModeSetModeValue(modetmp, VIDMODE_H_DISPLAY, stuff->hdisplay); - VidModeSetModeValue(modetmp, VIDMODE_H_SYNCSTART, stuff->hsyncstart); - VidModeSetModeValue(modetmp, VIDMODE_H_SYNCEND, stuff->hsyncend); - VidModeSetModeValue(modetmp, VIDMODE_H_TOTAL, stuff->htotal); - VidModeSetModeValue(modetmp, VIDMODE_H_SKEW, stuff->hskew); - VidModeSetModeValue(modetmp, VIDMODE_V_DISPLAY, stuff->vdisplay); - VidModeSetModeValue(modetmp, VIDMODE_V_SYNCSTART, stuff->vsyncstart); - VidModeSetModeValue(modetmp, VIDMODE_V_SYNCEND, stuff->vsyncend); - VidModeSetModeValue(modetmp, VIDMODE_V_TOTAL, stuff->vtotal); - VidModeSetModeValue(modetmp, VIDMODE_FLAGS, stuff->flags); - if (stuff->privsize) - ErrorF("ValidateModeLine - Privates in request have been ignored\n"); - - /* Check that the mode is consistent with the monitor specs */ - if ((status = VidModeCheckModeForMonitor(stuff->screen, modetmp)) != MODE_OK) - goto status_reply; - - /* Check that the driver is happy with the mode */ - status = VidModeCheckModeForDriver(stuff->screen, modetmp); - -status_reply: - if(modetmp) - xfree(modetmp); - - rep.type = X_Reply; - rep.length = bytes_to_int32(SIZEOF(xXF86VidModeValidateModeLineReply) - - SIZEOF(xGenericReply)); - rep.sequenceNumber = client->sequence; - rep.status = status; - if (client->swapped) { - register int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - } - WriteToClient(client, sizeof(xXF86VidModeValidateModeLineReply), (char *)&rep); - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) - ErrorF("ValidateModeLine - Succeeded (status = %d)\n", status); - return(client->noClientException); -} - -static int -ProcXF86VidModeSwitchMode(ClientPtr client) -{ - REQUEST(xXF86VidModeSwitchModeReq); - - DEBUG_P("XF86VidModeSwitchMode"); - - REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - VidModeZoomViewport(stuff->screen, (short)stuff->zoom); - - return (client->noClientException); -} - -static int -ProcXF86VidModeSwitchToMode(ClientPtr client) -{ - REQUEST(xXF86VidModeSwitchToModeReq); - xXF86OldVidModeSwitchToModeReq *oldstuff = - (xXF86OldVidModeSwitchToModeReq *)client->requestBuffer; - xXF86VidModeSwitchToModeReq newstuff; - pointer mode; - int len, dotClock; - int ver; - - DEBUG_P("XF86VidModeSwitchToMode"); - - ver = ClientMajorVersion(client); - if (ver < 2) { - /* convert from old format */ - stuff = &newstuff; - stuff->length = oldstuff->length; - stuff->screen = oldstuff->screen; - stuff->dotclock = oldstuff->dotclock; - stuff->hdisplay = oldstuff->hdisplay; - stuff->hsyncstart = oldstuff->hsyncstart; - stuff->hsyncend = oldstuff->hsyncend; - stuff->htotal = oldstuff->htotal; - stuff->hskew = 0; - stuff->vdisplay = oldstuff->vdisplay; - stuff->vsyncstart = oldstuff->vsyncstart; - stuff->vsyncend = oldstuff->vsyncend; - stuff->vtotal = oldstuff->vtotal; - stuff->flags = oldstuff->flags; - stuff->privsize = oldstuff->privsize; - } - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("SwitchToMode - scrn: %d clock: %ld\n", - (int)stuff->screen, (unsigned long)stuff->dotclock); - ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", - stuff->hdisplay, stuff->hsyncstart, - stuff->hsyncend, stuff->htotal); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", - stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, - stuff->vtotal, (unsigned long)stuff->flags); - } - - if (ver < 2) { - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeSwitchToModeReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86OldVidModeSwitchToModeReq)); - } else { - REQUEST_AT_LEAST_SIZE(xXF86VidModeSwitchToModeReq); - len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeSwitchToModeReq)); - } - if (len != stuff->privsize) - return BadLength; - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) - return BadValue; - - if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) - && MODEMATCH(mode, stuff)) - return (client->noClientException); - - if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) - return BadValue; - - do { - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { - ErrorF("Checking against clock: %d (%d)\n", - VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); - ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", - VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), - VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), - VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), - VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); - ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", - VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), - VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), - VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), - VidModeGetModeValue(mode, VIDMODE_V_TOTAL), - VidModeGetModeValue(mode, VIDMODE_FLAGS)); - } - if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && - MODEMATCH(mode, stuff)) { - - if (!VidModeSwitchMode(stuff->screen, mode)) - return BadValue; - - if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) - ErrorF("SwitchToMode - Succeeded\n"); - return(client->noClientException); - } - } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); - - return BadValue; -} - -static int -ProcXF86VidModeLockModeSwitch(ClientPtr client) -{ - REQUEST(xXF86VidModeLockModeSwitchReq); - - REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq); - - DEBUG_P("XF86VidModeLockModeSwitch"); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (!VidModeLockZoom(stuff->screen, (short)stuff->lock)) - return VidModeErrorBase + XF86VidModeZoomLocked; - - return (client->noClientException); -} - -static int -ProcXF86VidModeGetMonitor(ClientPtr client) -{ - REQUEST(xXF86VidModeGetMonitorReq); - xXF86VidModeGetMonitorReply rep; - register int n; - CARD32 *hsyncdata, *vsyncdata; - int i, nHsync, nVrefresh; - pointer monitor; - - DEBUG_P("XF86VidModeGetMonitor"); - - REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (!VidModeGetMonitor(stuff->screen, &monitor)) - return BadValue; - - nHsync = VidModeGetMonitorValue(monitor, VIDMODE_MON_NHSYNC, 0).i; - nVrefresh = VidModeGetMonitorValue(monitor, VIDMODE_MON_NVREFRESH, 0).i; - - rep.type = X_Reply; - if ((char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_VENDOR, 0)).ptr) - rep.vendorLength = strlen((char *)(VidModeGetMonitorValue(monitor, - VIDMODE_MON_VENDOR, 0)).ptr); - else - rep.vendorLength = 0; - if ((char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_MODEL, 0)).ptr) - rep.modelLength = strlen((char *)(VidModeGetMonitorValue(monitor, - VIDMODE_MON_MODEL, 0)).ptr); - else - rep.modelLength = 0; - rep.length = bytes_to_int32(SIZEOF(xXF86VidModeGetMonitorReply) - SIZEOF(xGenericReply) + - (nHsync + nVrefresh) * sizeof(CARD32) + - pad_to_int32(rep.vendorLength) + - pad_to_int32(rep.modelLength)); - rep.sequenceNumber = client->sequence; - rep.nhsync = nHsync; - rep.nvsync = nVrefresh; - hsyncdata = xalloc(nHsync * sizeof(CARD32)); - if (!hsyncdata) { - return BadAlloc; - } - - vsyncdata = xalloc(nVrefresh * sizeof(CARD32)); - if (!vsyncdata) { - xfree(hsyncdata); - return BadAlloc; - } - - for (i = 0; i < nHsync; i++) { - hsyncdata[i] = (unsigned short)(VidModeGetMonitorValue(monitor, - VIDMODE_MON_HSYNC_LO, i)).f | - (unsigned short)(VidModeGetMonitorValue(monitor, - VIDMODE_MON_HSYNC_HI, i)).f << 16; - } - for (i = 0; i < nVrefresh; i++) { - vsyncdata[i] = (unsigned short)(VidModeGetMonitorValue(monitor, - VIDMODE_MON_VREFRESH_LO, i)).f | - (unsigned short)(VidModeGetMonitorValue(monitor, - VIDMODE_MON_VREFRESH_HI, i)).f << 16; - } - - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - } - WriteToClient(client, SIZEOF(xXF86VidModeGetMonitorReply), (char *)&rep); - client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; - WriteSwappedDataToClient(client, nHsync * sizeof(CARD32), - hsyncdata); - WriteSwappedDataToClient(client, nVrefresh * sizeof(CARD32), - vsyncdata); - if (rep.vendorLength) - WriteToClient(client, rep.vendorLength, (char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_VENDOR, 0)).ptr); - if (rep.modelLength) - WriteToClient(client, rep.modelLength, (char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_MODEL, 0)).ptr); - - xfree(hsyncdata); - xfree(vsyncdata); - - return (client->noClientException); -} - -static int -ProcXF86VidModeGetViewPort(ClientPtr client) -{ - REQUEST(xXF86VidModeGetViewPortReq); - xXF86VidModeGetViewPortReply rep; - int x, y, n; - - DEBUG_P("XF86VidModeGetViewPort"); - - REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - VidModeGetViewPort(stuff->screen, &x, &y); - rep.x = x; - rep.y = y; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.x, n); - swapl(&rep.y, n); - } - WriteToClient(client, SIZEOF(xXF86VidModeGetViewPortReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86VidModeSetViewPort(ClientPtr client) -{ - REQUEST(xXF86VidModeSetViewPortReq); - - DEBUG_P("XF86VidModeSetViewPort"); - - REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (!VidModeSetViewPort(stuff->screen, stuff->x, stuff->y)) - return BadValue; - - return (client->noClientException); -} - -static int -ProcXF86VidModeGetDotClocks(ClientPtr client) -{ - REQUEST(xXF86VidModeGetDotClocksReq); - xXF86VidModeGetDotClocksReply rep; - register int n; - int numClocks; - CARD32 dotclock; - int *Clocks = NULL; - Bool ClockProg; - - DEBUG_P("XF86VidModeGetDotClocks"); - - REQUEST_SIZE_MATCH(xXF86VidModeGetDotClocksReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - numClocks = VidModeGetNumOfClocks(stuff->screen, &ClockProg); - - rep.type = X_Reply; - rep.length = bytes_to_int32(SIZEOF(xXF86VidModeGetDotClocksReply) - - SIZEOF(xGenericReply) + numClocks); - rep.sequenceNumber = client->sequence; - rep.clocks = numClocks; - rep.maxclocks = MAXCLOCKS; - rep.flags = 0; - - if (!ClockProg) { - Clocks = xalloc(numClocks * sizeof(int)); - if (!Clocks) - return BadValue; - if (!VidModeGetClocks(stuff->screen, Clocks)) { - xfree(Clocks); - return BadValue; - } - } - - if (ClockProg) { - rep.flags |= CLKFLAG_PROGRAMABLE; - } - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.clocks, n); - swapl(&rep.maxclocks, n); - swapl(&rep.flags, n); - } - WriteToClient(client, sizeof(xXF86VidModeGetDotClocksReply), (char *)&rep); - if (!ClockProg) { - for (n = 0; n < numClocks; n++) { - dotclock = *Clocks++; - if (client->swapped) { - WriteSwappedDataToClient(client, 4, (char *)&dotclock); - } else { - WriteToClient(client, 4, (char *)&dotclock); - } - } - } - - xfree(Clocks); - return (client->noClientException); -} - -static int -ProcXF86VidModeSetGamma(ClientPtr client) -{ - REQUEST(xXF86VidModeSetGammaReq); - - DEBUG_P("XF86VidModeSetGamma"); - - REQUEST_SIZE_MATCH(xXF86VidModeSetGammaReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if (!VidModeSetGamma(stuff->screen, ((float)stuff->red)/10000., - ((float)stuff->green)/10000., ((float)stuff->blue)/10000.)) - return BadValue; - - return (client->noClientException); -} - -static int -ProcXF86VidModeGetGamma(ClientPtr client) -{ - REQUEST(xXF86VidModeGetGammaReq); - xXF86VidModeGetGammaReply rep; - register int n; - float red, green, blue; - - DEBUG_P("XF86VidModeGetGamma"); - - REQUEST_SIZE_MATCH(xXF86VidModeGetGammaReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - if (!VidModeGetGamma(stuff->screen, &red, &green, &blue)) - return BadValue; - rep.red = (CARD32)(red * 10000.); - rep.green = (CARD32)(green * 10000.); - rep.blue = (CARD32)(blue * 10000.); - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.red, n); - swapl(&rep.green, n); - swapl(&rep.blue, n); - } - WriteToClient(client, sizeof(xXF86VidModeGetGammaReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86VidModeSetGammaRamp(ClientPtr client) -{ - CARD16 *r, *g, *b; - int length; - REQUEST(xXF86VidModeSetGammaRampReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if(stuff->size != VidModeGetGammaRampSize(stuff->screen)) - return BadValue; - - length = (stuff->size + 1) & ~1; - - REQUEST_FIXED_SIZE(xXF86VidModeSetGammaRampReq, length * 6); - - r = (CARD16*)&stuff[1]; - g = r + length; - b = g + length; - - if (!VidModeSetGammaRamp(stuff->screen, stuff->size, r, g, b)) - return BadValue; - - return (client->noClientException); -} - -static int -ProcXF86VidModeGetGammaRamp(ClientPtr client) -{ - CARD16 *ramp = NULL; - int n, length; - size_t ramplen = 0; - xXF86VidModeGetGammaRampReply rep; - REQUEST(xXF86VidModeGetGammaRampReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - if(stuff->size != VidModeGetGammaRampSize(stuff->screen)) - return BadValue; - - REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampReq); - - length = (stuff->size + 1) & ~1; - - if(stuff->size) { - ramplen = length * 3 * sizeof(CARD16); - if (!(ramp = xalloc(ramplen))) - return BadAlloc; - - if (!VidModeGetGammaRamp(stuff->screen, stuff->size, - ramp, ramp + length, ramp + (length * 2))) { - xfree(ramp); - return BadValue; - } - } - - rep.type = X_Reply; - rep.length = (length >> 1) * 3; - rep.sequenceNumber = client->sequence; - rep.size = stuff->size; - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.size, n); - SwapShorts((short*)ramp, length * 3); - } - WriteToClient(client, sizeof(xXF86VidModeGetGammaRampReply), (char *)&rep); - - if(stuff->size) { - WriteToClient(client, ramplen, (char*)ramp); - xfree(ramp); - } - - return (client->noClientException); -} - - -static int -ProcXF86VidModeGetGammaRampSize(ClientPtr client) -{ - xXF86VidModeGetGammaRampSizeReply rep; - int n; - REQUEST(xXF86VidModeGetGammaRampSizeReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampSizeReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.size = VidModeGetGammaRampSize(stuff->screen); - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.size, n); - } - WriteToClient(client,sizeof(xXF86VidModeGetGammaRampSizeReply),(char*)&rep); - - return (client->noClientException); -} - -static int -ProcXF86VidModeGetPermissions(ClientPtr client) -{ - xXF86VidModeGetPermissionsReply rep; - int n; - REQUEST(xXF86VidModeGetPermissionsReq); - - if(stuff->screen >= screenInfo.numScreens) - return BadValue; - - REQUEST_SIZE_MATCH(xXF86VidModeGetPermissionsReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.permissions = XF86VM_READ_PERMISSION; - if (xf86GetVidModeEnabled() && - (xf86GetVidModeAllowNonLocal() || LocalClient (client))) { - rep.permissions |= XF86VM_WRITE_PERMISSION; - } - if(client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.permissions, n); - } - WriteToClient(client,sizeof(xXF86VidModeGetPermissionsReply),(char*)&rep); - - return (client->noClientException); -} - - -static int -ProcXF86VidModeSetClientVersion(ClientPtr client) -{ - REQUEST(xXF86VidModeSetClientVersionReq); - - VidModePrivPtr pPriv; - - DEBUG_P("XF86VidModeSetClientVersion"); - - REQUEST_SIZE_MATCH(xXF86VidModeSetClientVersionReq); - - if ((pPriv = VM_GETPRIV(client)) == NULL) { - pPriv = xalloc(sizeof(VidModePrivRec)); - if (!pPriv) - return BadAlloc; - VM_SETPRIV(client, pPriv); - } - pPriv->major = stuff->major; - pPriv->minor = stuff->minor; - - return (client->noClientException); -} - -static int -ProcXF86VidModeDispatch(ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_XF86VidModeQueryVersion: - return ProcXF86VidModeQueryVersion(client); - case X_XF86VidModeGetModeLine: - return ProcXF86VidModeGetModeLine(client); - case X_XF86VidModeGetMonitor: - return ProcXF86VidModeGetMonitor(client); - case X_XF86VidModeGetAllModeLines: - return ProcXF86VidModeGetAllModeLines(client); - case X_XF86VidModeValidateModeLine: - return ProcXF86VidModeValidateModeLine(client); - case X_XF86VidModeGetViewPort: - return ProcXF86VidModeGetViewPort(client); - case X_XF86VidModeGetDotClocks: - return ProcXF86VidModeGetDotClocks(client); - case X_XF86VidModeSetClientVersion: - return ProcXF86VidModeSetClientVersion(client); - case X_XF86VidModeGetGamma: - return ProcXF86VidModeGetGamma(client); - case X_XF86VidModeGetGammaRamp: - return ProcXF86VidModeGetGammaRamp(client); - case X_XF86VidModeGetGammaRampSize: - return ProcXF86VidModeGetGammaRampSize(client); - case X_XF86VidModeGetPermissions: - return ProcXF86VidModeGetPermissions(client); - default: - if (!xf86GetVidModeEnabled()) - return VidModeErrorBase + XF86VidModeExtensionDisabled; - if (xf86GetVidModeAllowNonLocal() || LocalClient (client)) { - switch (stuff->data) { - case X_XF86VidModeAddModeLine: - return ProcXF86VidModeAddModeLine(client); - case X_XF86VidModeDeleteModeLine: - return ProcXF86VidModeDeleteModeLine(client); - case X_XF86VidModeModModeLine: - return ProcXF86VidModeModModeLine(client); - case X_XF86VidModeSwitchMode: - return ProcXF86VidModeSwitchMode(client); - case X_XF86VidModeSwitchToMode: - return ProcXF86VidModeSwitchToMode(client); - case X_XF86VidModeLockModeSwitch: - return ProcXF86VidModeLockModeSwitch(client); - case X_XF86VidModeSetViewPort: - return ProcXF86VidModeSetViewPort(client); - case X_XF86VidModeSetGamma: - return ProcXF86VidModeSetGamma(client); - case X_XF86VidModeSetGammaRamp: - return ProcXF86VidModeSetGammaRamp(client); - default: - return BadRequest; - } - } else - return VidModeErrorBase + XF86VidModeClientNotLocal; - } -} - -static int -SProcXF86VidModeQueryVersion(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeQueryVersionReq); - swaps(&stuff->length, n); - return ProcXF86VidModeQueryVersion(client); -} - -static int -SProcXF86VidModeGetModeLine(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeGetModeLineReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetModeLine(client); -} - -static int -SProcXF86VidModeGetAllModeLines(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeGetAllModeLinesReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetAllModeLines(client); -} - -static int -SProcXF86VidModeAddModeLine(ClientPtr client) -{ - xXF86OldVidModeAddModeLineReq *oldstuff = - (xXF86OldVidModeAddModeLineReq *)client->requestBuffer; - int ver; - register int n; - - REQUEST(xXF86VidModeAddModeLineReq); - ver = ClientMajorVersion(client); - if (ver < 2) { - swaps(&oldstuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeAddModeLineReq); - swapl(&oldstuff->screen, n); - swaps(&oldstuff->hdisplay, n); - swaps(&oldstuff->hsyncstart, n); - swaps(&oldstuff->hsyncend, n); - swaps(&oldstuff->htotal, n); - swaps(&oldstuff->vdisplay, n); - swaps(&oldstuff->vsyncstart, n); - swaps(&oldstuff->vsyncend, n); - swaps(&oldstuff->vtotal, n); - swapl(&oldstuff->flags, n); - swapl(&oldstuff->privsize, n); - SwapRestL(oldstuff); - } else { - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq); - swapl(&stuff->screen, n); - swaps(&stuff->hdisplay, n); - swaps(&stuff->hsyncstart, n); - swaps(&stuff->hsyncend, n); - swaps(&stuff->htotal, n); - swaps(&stuff->hskew, n); - swaps(&stuff->vdisplay, n); - swaps(&stuff->vsyncstart, n); - swaps(&stuff->vsyncend, n); - swaps(&stuff->vtotal, n); - swapl(&stuff->flags, n); - swapl(&stuff->privsize, n); - SwapRestL(stuff); - } - return ProcXF86VidModeAddModeLine(client); -} - -static int -SProcXF86VidModeDeleteModeLine(ClientPtr client) -{ - xXF86OldVidModeDeleteModeLineReq *oldstuff = - (xXF86OldVidModeDeleteModeLineReq *)client->requestBuffer; - int ver; - register int n; - - REQUEST(xXF86VidModeDeleteModeLineReq); - ver = ClientMajorVersion(client); - if (ver < 2) { - swaps(&oldstuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeDeleteModeLineReq); - swapl(&oldstuff->screen, n); - swaps(&oldstuff->hdisplay, n); - swaps(&oldstuff->hsyncstart, n); - swaps(&oldstuff->hsyncend, n); - swaps(&oldstuff->htotal, n); - swaps(&oldstuff->vdisplay, n); - swaps(&oldstuff->vsyncstart, n); - swaps(&oldstuff->vsyncend, n); - swaps(&oldstuff->vtotal, n); - swapl(&oldstuff->flags, n); - swapl(&oldstuff->privsize, n); - SwapRestL(oldstuff); - } else { - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq); - swapl(&stuff->screen, n); - swaps(&stuff->hdisplay, n); - swaps(&stuff->hsyncstart, n); - swaps(&stuff->hsyncend, n); - swaps(&stuff->htotal, n); - swaps(&stuff->hskew, n); - swaps(&stuff->vdisplay, n); - swaps(&stuff->vsyncstart, n); - swaps(&stuff->vsyncend, n); - swaps(&stuff->vtotal, n); - swapl(&stuff->flags, n); - swapl(&stuff->privsize, n); - SwapRestL(stuff); - } - return ProcXF86VidModeDeleteModeLine(client); -} - -static int -SProcXF86VidModeModModeLine(ClientPtr client) -{ - xXF86OldVidModeModModeLineReq *oldstuff = - (xXF86OldVidModeModModeLineReq *)client->requestBuffer; - int ver; - register int n; - - REQUEST(xXF86VidModeModModeLineReq); - ver = ClientMajorVersion(client); - if (ver < 2) { - swaps(&oldstuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeModModeLineReq); - swapl(&oldstuff->screen, n); - swaps(&oldstuff->hdisplay, n); - swaps(&oldstuff->hsyncstart, n); - swaps(&oldstuff->hsyncend, n); - swaps(&oldstuff->htotal, n); - swaps(&oldstuff->vdisplay, n); - swaps(&oldstuff->vsyncstart, n); - swaps(&oldstuff->vsyncend, n); - swaps(&oldstuff->vtotal, n); - swapl(&oldstuff->flags, n); - swapl(&oldstuff->privsize, n); - SwapRestL(oldstuff); - } else { - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq); - swapl(&stuff->screen, n); - swaps(&stuff->hdisplay, n); - swaps(&stuff->hsyncstart, n); - swaps(&stuff->hsyncend, n); - swaps(&stuff->htotal, n); - swaps(&stuff->hskew, n); - swaps(&stuff->vdisplay, n); - swaps(&stuff->vsyncstart, n); - swaps(&stuff->vsyncend, n); - swaps(&stuff->vtotal, n); - swapl(&stuff->flags, n); - swapl(&stuff->privsize, n); - SwapRestL(stuff); - } - return ProcXF86VidModeModModeLine(client); -} - -static int -SProcXF86VidModeValidateModeLine(ClientPtr client) -{ - xXF86OldVidModeValidateModeLineReq *oldstuff = - (xXF86OldVidModeValidateModeLineReq *)client->requestBuffer; - int ver; - register int n; - - REQUEST(xXF86VidModeValidateModeLineReq); - ver = ClientMajorVersion(client); - if (ver < 2) { - swaps(&oldstuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86OldVidModeValidateModeLineReq); - swapl(&oldstuff->screen, n); - swaps(&oldstuff->hdisplay, n); - swaps(&oldstuff->hsyncstart, n); - swaps(&oldstuff->hsyncend, n); - swaps(&oldstuff->htotal, n); - swaps(&oldstuff->vdisplay, n); - swaps(&oldstuff->vsyncstart, n); - swaps(&oldstuff->vsyncend, n); - swaps(&oldstuff->vtotal, n); - swapl(&oldstuff->flags, n); - swapl(&oldstuff->privsize, n); - SwapRestL(oldstuff); - } else { - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq); - swapl(&stuff->screen, n); - swaps(&stuff->hdisplay, n); - swaps(&stuff->hsyncstart, n); - swaps(&stuff->hsyncend, n); - swaps(&stuff->htotal, n); - swaps(&stuff->hskew, n); - swaps(&stuff->vdisplay, n); - swaps(&stuff->vsyncstart, n); - swaps(&stuff->vsyncend, n); - swaps(&stuff->vtotal, n); - swapl(&stuff->flags, n); - swapl(&stuff->privsize, n); - SwapRestL(stuff); - } - return ProcXF86VidModeValidateModeLine(client); -} - -static int -SProcXF86VidModeSwitchMode(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeSwitchModeReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq); - swaps(&stuff->screen, n); - swaps(&stuff->zoom, n); - return ProcXF86VidModeSwitchMode(client); -} - -static int -SProcXF86VidModeSwitchToMode(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeSwitchToModeReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeSwitchToModeReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeSwitchToMode(client); -} - -static int -SProcXF86VidModeLockModeSwitch(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeLockModeSwitchReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq); - swaps(&stuff->screen, n); - swaps(&stuff->lock, n); - return ProcXF86VidModeLockModeSwitch(client); -} - -static int -SProcXF86VidModeGetMonitor(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeGetMonitorReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetMonitor(client); -} - -static int -SProcXF86VidModeGetViewPort(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeGetViewPortReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetViewPort(client); -} - -static int -SProcXF86VidModeSetViewPort(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeSetViewPortReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq); - swaps(&stuff->screen, n); - swapl(&stuff->x, n); - swapl(&stuff->y, n); - return ProcXF86VidModeSetViewPort(client); -} - -static int -SProcXF86VidModeGetDotClocks(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeGetDotClocksReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetDotClocksReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetDotClocks(client); -} - -static int -SProcXF86VidModeSetClientVersion(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeSetClientVersionReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeSetClientVersionReq); - swaps(&stuff->major, n); - swaps(&stuff->minor, n); - return ProcXF86VidModeSetClientVersion(client); -} - -static int -SProcXF86VidModeSetGamma(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeSetGammaReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeSetGammaReq); - swaps(&stuff->screen, n); - swapl(&stuff->red, n); - swapl(&stuff->green, n); - swapl(&stuff->blue, n); - return ProcXF86VidModeSetGamma(client); -} - -static int -SProcXF86VidModeGetGamma(ClientPtr client) -{ - register int n; - REQUEST(xXF86VidModeGetGammaReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetGammaReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetGamma(client); -} - -static int -SProcXF86VidModeSetGammaRamp(ClientPtr client) -{ - int length, n; - REQUEST(xXF86VidModeSetGammaRampReq); - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xXF86VidModeSetGammaRampReq); - swaps(&stuff->size, n); - swaps(&stuff->screen, n); - length = ((stuff->size + 1) & ~1) * 6; - REQUEST_FIXED_SIZE(xXF86VidModeSetGammaRampReq, length); - SwapRestS(stuff); - return ProcXF86VidModeSetGammaRamp(client); -} - -static int -SProcXF86VidModeGetGammaRamp(ClientPtr client) -{ - int n; - REQUEST(xXF86VidModeGetGammaRampReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampReq); - swaps(&stuff->size, n); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetGammaRamp(client); -} - -static int -SProcXF86VidModeGetGammaRampSize(ClientPtr client) -{ - int n; - REQUEST(xXF86VidModeGetGammaRampSizeReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampSizeReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetGammaRampSize(client); -} - -static int -SProcXF86VidModeGetPermissions(ClientPtr client) -{ - int n; - REQUEST(xXF86VidModeGetPermissionsReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXF86VidModeGetPermissionsReq); - swaps(&stuff->screen, n); - return ProcXF86VidModeGetPermissions(client); -} - - -static int -SProcXF86VidModeDispatch(ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_XF86VidModeQueryVersion: - return SProcXF86VidModeQueryVersion(client); - case X_XF86VidModeGetModeLine: - return SProcXF86VidModeGetModeLine(client); - case X_XF86VidModeGetMonitor: - return SProcXF86VidModeGetMonitor(client); - case X_XF86VidModeGetAllModeLines: - return SProcXF86VidModeGetAllModeLines(client); - case X_XF86VidModeGetViewPort: - return SProcXF86VidModeGetViewPort(client); - case X_XF86VidModeValidateModeLine: - return SProcXF86VidModeValidateModeLine(client); - case X_XF86VidModeGetDotClocks: - return SProcXF86VidModeGetDotClocks(client); - case X_XF86VidModeSetClientVersion: - return SProcXF86VidModeSetClientVersion(client); - case X_XF86VidModeGetGamma: - return SProcXF86VidModeGetGamma(client); - case X_XF86VidModeGetGammaRamp: - return SProcXF86VidModeGetGammaRamp(client); - case X_XF86VidModeGetGammaRampSize: - return SProcXF86VidModeGetGammaRampSize(client); - case X_XF86VidModeGetPermissions: - return SProcXF86VidModeGetPermissions(client); - default: - if (!xf86GetVidModeEnabled()) - return VidModeErrorBase + XF86VidModeExtensionDisabled; - if (xf86GetVidModeAllowNonLocal() || LocalClient(client)) { - switch (stuff->data) { - case X_XF86VidModeAddModeLine: - return SProcXF86VidModeAddModeLine(client); - case X_XF86VidModeDeleteModeLine: - return SProcXF86VidModeDeleteModeLine(client); - case X_XF86VidModeModModeLine: - return SProcXF86VidModeModModeLine(client); - case X_XF86VidModeSwitchMode: - return SProcXF86VidModeSwitchMode(client); - case X_XF86VidModeSwitchToMode: - return SProcXF86VidModeSwitchToMode(client); - case X_XF86VidModeLockModeSwitch: - return SProcXF86VidModeLockModeSwitch(client); - case X_XF86VidModeSetViewPort: - return SProcXF86VidModeSetViewPort(client); - case X_XF86VidModeSetGamma: - return SProcXF86VidModeSetGamma(client); - case X_XF86VidModeSetGammaRamp: - return SProcXF86VidModeSetGammaRamp(client); - default: - return BadRequest; - } - } else - return VidModeErrorBase + XF86VidModeClientNotLocal; - } -} + +/* + +Copyright 1995 Kaleb S. KEITHLEY + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL Kaleb S. KEITHLEY BE LIABLE FOR ANY CLAIM, DAMAGES +OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Kaleb S. KEITHLEY +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +from Kaleb S. KEITHLEY + +*/ +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "servermd.h" +#include +#include "swaprep.h" +#include "xf86.h" +#include "vidmodeproc.h" +#include "globals.h" +#include "protocol-versions.h" + +#define DEFAULT_XF86VIDMODE_VERBOSITY 3 + +static int VidModeErrorBase; +static int VidModeClientPrivateKeyIndex; +static DevPrivateKey VidModeClientPrivateKey = &VidModeClientPrivateKeyIndex; + +/* This holds the client's version information */ +typedef struct { + int major; + int minor; +} VidModePrivRec, *VidModePrivPtr; + +#define VM_GETPRIV(c) ((VidModePrivPtr) \ + dixLookupPrivate(&(c)->devPrivates, VidModeClientPrivateKey)) +#define VM_SETPRIV(c,p) \ + dixSetPrivate(&(c)->devPrivates, VidModeClientPrivateKey, p) + +static DISPATCH_PROC(ProcXF86VidModeDispatch); +static DISPATCH_PROC(ProcXF86VidModeGetAllModeLines); +static DISPATCH_PROC(ProcXF86VidModeGetModeLine); +static DISPATCH_PROC(ProcXF86VidModeGetMonitor); +static DISPATCH_PROC(ProcXF86VidModeLockModeSwitch); +static DISPATCH_PROC(ProcXF86VidModeAddModeLine); +static DISPATCH_PROC(ProcXF86VidModeDeleteModeLine); +static DISPATCH_PROC(ProcXF86VidModeModModeLine); +static DISPATCH_PROC(ProcXF86VidModeValidateModeLine); +static DISPATCH_PROC(ProcXF86VidModeQueryVersion); +static DISPATCH_PROC(ProcXF86VidModeSwitchMode); +static DISPATCH_PROC(ProcXF86VidModeSwitchToMode); +static DISPATCH_PROC(ProcXF86VidModeGetViewPort); +static DISPATCH_PROC(ProcXF86VidModeSetViewPort); +static DISPATCH_PROC(ProcXF86VidModeGetDotClocks); +static DISPATCH_PROC(ProcXF86VidModeSetGamma); +static DISPATCH_PROC(ProcXF86VidModeGetGamma); +static DISPATCH_PROC(ProcXF86VidModeSetClientVersion); +static DISPATCH_PROC(ProcXF86VidModeGetGammaRamp); +static DISPATCH_PROC(ProcXF86VidModeSetGammaRamp); +static DISPATCH_PROC(ProcXF86VidModeGetGammaRampSize); +static DISPATCH_PROC(SProcXF86VidModeDispatch); +static DISPATCH_PROC(SProcXF86VidModeGetAllModeLines); +static DISPATCH_PROC(SProcXF86VidModeGetModeLine); +static DISPATCH_PROC(SProcXF86VidModeGetMonitor); +static DISPATCH_PROC(SProcXF86VidModeLockModeSwitch); +static DISPATCH_PROC(SProcXF86VidModeAddModeLine); +static DISPATCH_PROC(SProcXF86VidModeDeleteModeLine); +static DISPATCH_PROC(SProcXF86VidModeModModeLine); +static DISPATCH_PROC(SProcXF86VidModeValidateModeLine); +static DISPATCH_PROC(SProcXF86VidModeQueryVersion); +static DISPATCH_PROC(SProcXF86VidModeSwitchMode); +static DISPATCH_PROC(SProcXF86VidModeSwitchToMode); +static DISPATCH_PROC(SProcXF86VidModeGetViewPort); +static DISPATCH_PROC(SProcXF86VidModeSetViewPort); +static DISPATCH_PROC(SProcXF86VidModeGetDotClocks); +static DISPATCH_PROC(SProcXF86VidModeSetGamma); +static DISPATCH_PROC(SProcXF86VidModeGetGamma); +static DISPATCH_PROC(SProcXF86VidModeSetClientVersion); +static DISPATCH_PROC(SProcXF86VidModeGetGammaRamp); +static DISPATCH_PROC(SProcXF86VidModeSetGammaRamp); +static DISPATCH_PROC(SProcXF86VidModeGetGammaRampSize); + +#if 0 +static unsigned char XF86VidModeReqCode = 0; +#endif + +/* The XF86VIDMODE_EVENTS code is far from complete */ + +#ifdef XF86VIDMODE_EVENTS +static int XF86VidModeEventBase = 0; + +static void SXF86VidModeNotifyEvent(); + xXF86VidModeNotifyEvent * /* from */, + xXF86VidModeNotifyEvent * /* to */ +); + +static RESTYPE EventType; /* resource type for event masks */ + +typedef struct _XF86VidModeEvent *XF86VidModeEventPtr; + +typedef struct _XF86VidModeEvent { + XF86VidModeEventPtr next; + ClientPtr client; + ScreenPtr screen; + XID resource; + CARD32 mask; +} XF86VidModeEventRec; + +static int XF86VidModeFreeEvents(); + +typedef struct _XF86VidModeScreenPrivate { + XF86VidModeEventPtr events; + Bool hasWindow; +} XF86VidModeScreenPrivateRec, *XF86VidModeScreenPrivatePtr; + +static int ScreenPrivateKeyIndex; +static DevPrivateKey ScreenPrivateKey = &ScreenPrivateKeyIndex; + +#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \ + dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey)) +#define SetScreenPrivate(s,v) \ + dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v) +#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = GetScreenPrivate(s) + +#define New(t) (malloc(sizeof (t))) +#endif + +#ifdef DEBUG +# define DEBUG_P(x) ErrorF(x"\n"); +#else +# define DEBUG_P(x) /**/ +#endif + +void +XFree86VidModeExtensionInit(void) +{ + ExtensionEntry* extEntry; + ScreenPtr pScreen; + int i; + Bool enabled = FALSE; + + DEBUG_P("XFree86VidModeExtensionInit"); + +#ifdef XF86VIDMODE_EVENTS + EventType = CreateNewResourceType(XF86VidModeFreeEvents, "VidModeEvent"); +#endif + + for(i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + if (VidModeExtensionInit(pScreen)) + enabled = TRUE; +#ifdef XF86VIDMODE_EVENTS + SetScreenPrivate (pScreen, NULL); +#endif + } + /* This means that the DDX doesn't want the vidmode extension enabled */ + if (!enabled) + return; + + if ( +#ifdef XF86VIDMODE_EVENTS + EventType && +#endif + (extEntry = AddExtension(XF86VIDMODENAME, + XF86VidModeNumberEvents, + XF86VidModeNumberErrors, + ProcXF86VidModeDispatch, + SProcXF86VidModeDispatch, + NULL, + StandardMinorOpcode))) { +#if 0 + XF86VidModeReqCode = (unsigned char)extEntry->base; +#endif + VidModeErrorBase = extEntry->errorBase; +#ifdef XF86VIDMODE_EVENTS + XF86VidModeEventBase = extEntry->eventBase; + EventSwapVector[XF86VidModeEventBase] = (EventSwapPtr)SXF86VidModeNotifyEvent; +#endif + } +} + +static int +ClientMajorVersion(ClientPtr client) +{ + VidModePrivPtr pPriv; + + pPriv = VM_GETPRIV(client); + if (!pPriv) + return 0; + else + return pPriv->major; +} + +#ifdef XF86VIDMODE_EVENTS +static void +CheckScreenPrivate (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + + if (!pPriv) + return; + if (!pPriv->events && !pPriv->hasWindow) { + free(pPriv); + SetScreenPrivate (pScreen, NULL); + } +} + +static XF86VidModeScreenPrivatePtr +MakeScreenPrivate (pScreen) + ScreenPtr pScreen; +{ + SetupScreen (pScreen); + + if (pPriv) + return pPriv; + pPriv = New (XF86VidModeScreenPrivateRec); + if (!pPriv) + return 0; + pPriv->events = 0; + pPriv->hasWindow = FALSE; + SetScreenPrivate (pScreen, pPriv); + return pPriv; +} + +static unsigned long +getEventMask (ScreenPtr pScreen, ClientPtr client) +{ + SetupScreen(pScreen); + XF86VidModeEventPtr pEv; + + if (!pPriv) + return 0; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + if (pEv->client == client) + return pEv->mask; + return 0; +} + +static Bool +setEventMask (ScreenPtr pScreen, ClientPtr client, unsigned long mask) +{ + SetupScreen(pScreen); + XF86VidModeEventPtr pEv, *pPrev; + + if (getEventMask (pScreen, client) == mask) + return TRUE; + if (!pPriv) { + pPriv = MakeScreenPrivate (pScreen); + if (!pPriv) + return FALSE; + } + for (pPrev = &pPriv->events; pEv = *pPrev; pPrev = &pEv->next) + if (pEv->client == client) + break; + if (mask == 0) { + *pPrev = pEv->next; + free(pEv); + CheckScreenPrivate (pScreen); + } else { + if (!pEv) { + pEv = New (ScreenSaverEventRec); + if (!pEv) { + CheckScreenPrivate (pScreen); + return FALSE; + } + *pPrev = pEv; + pEv->next = NULL; + pEv->client = client; + pEv->screen = pScreen; + pEv->resource = FakeClientID (client->index); + } + pEv->mask = mask; + } + return TRUE; +} + +static int +XF86VidModeFreeEvents(pointer value, XID id) +{ + XF86VidModeEventPtr pOld = (XF86VidModeEventPtr)value; + ScreenPtr pScreen = pOld->screen; + SetupScreen (pScreen); + XF86VidModeEventPtr pEv, *pPrev; + + if (!pPriv) + return TRUE; + for (pPrev = &pPriv->events; pEv = *pPrev; pPrev = &pEv->next) + if (pEv == pOld) + break; + if (!pEv) + return TRUE; + *pPrev = pEv->next; + free(pEv); + CheckScreenPrivate (pScreen); + return TRUE; +} + +static void +SendXF86VidModeNotify(ScreenPtr pScreen, int state, Bool forced) +{ + XF86VidModeScreenPrivatePtr pPriv; + XF86VidModeEventPtr pEv; + unsigned long mask; + xXF86VidModeNotifyEvent ev; + ClientPtr client; + int kind; + + UpdateCurrentTimeIf (); + mask = XF86VidModeNotifyMask; + pScreen = screenInfo.screens[pScreen->myNum]; + pPriv = GetScreenPrivate(pScreen); + if (!pPriv) + return; + kind = XF86VidModeModeChange; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + { + client = pEv->client; + if (client->clientGone) + continue; + if (!(pEv->mask & mask)) + continue; + ev.type = XF86VidModeNotify + XF86VidModeEventBase; + ev.state = state; + ev.sequenceNumber = client->sequence; + ev.timestamp = currentTime.milliseconds; + ev.root = WindowTable[pScreen->myNum]->drawable.id; + ev.kind = kind; + ev.forced = forced; + WriteEventsToClient (client, 1, (xEvent *) &ev); + } +} + +static void +SXF86VidModeNotifyEvent(xXF86VidModeNotifyEvent *from, + xXF86VidModeNotifyEvent *to) +{ + to->type = from->type; + to->state = from->state; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->timestamp, to->timestamp); + cpswapl (from->root, to->root); + to->kind = from->kind; + to->forced = from->forced; +} +#endif + +static int +ProcXF86VidModeQueryVersion(ClientPtr client) +{ + xXF86VidModeQueryVersionReply rep; + register int n; + + DEBUG_P("XF86VidModeQueryVersion"); + + REQUEST_SIZE_MATCH(xXF86VidModeQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_XF86VIDMODE_MAJOR_VERSION; + rep.minorVersion = SERVER_XF86VIDMODE_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXF86VidModeQueryVersionReply), (char *)&rep); + return Success; +} + +static int +ProcXF86VidModeGetModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeGetModeLineReq); + xXF86VidModeGetModeLineReply rep; + xXF86OldVidModeGetModeLineReply oldrep; + pointer mode; + register int n; + int dotClock; + int ver; + + DEBUG_P("XF86VidModeGetModeline"); + + ver = ClientMajorVersion(client); + REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq); + rep.type = X_Reply; + if (ver < 2) { + rep.length = bytes_to_int32(SIZEOF(xXF86OldVidModeGetModeLineReply) - + SIZEOF(xGenericReply)); + } else { + rep.length = bytes_to_int32(SIZEOF(xXF86VidModeGetModeLineReply) - + SIZEOF(xGenericReply)); + } + rep.sequenceNumber = client->sequence; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + rep.dotclock = dotClock; + rep.hdisplay = VidModeGetModeValue(mode, VIDMODE_H_DISPLAY); + rep.hsyncstart = VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART); + rep.hsyncend = VidModeGetModeValue(mode, VIDMODE_H_SYNCEND); + rep.htotal = VidModeGetModeValue(mode, VIDMODE_H_TOTAL); + rep.hskew = VidModeGetModeValue(mode, VIDMODE_H_SKEW); + rep.vdisplay = VidModeGetModeValue(mode, VIDMODE_V_DISPLAY); + rep.vsyncstart = VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART); + rep.vsyncend = VidModeGetModeValue(mode, VIDMODE_V_SYNCEND); + rep.vtotal = VidModeGetModeValue(mode, VIDMODE_V_TOTAL); + rep.flags = VidModeGetModeValue(mode, VIDMODE_FLAGS); + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("GetModeLine - scrn: %d clock: %ld\n", + stuff->screen, (unsigned long)rep.dotclock); + ErrorF("GetModeLine - hdsp: %d hbeg: %d hend: %d httl: %d\n", + rep.hdisplay, rep.hsyncstart, + rep.hsyncend, rep.htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + rep.vdisplay, rep.vsyncstart, rep.vsyncend, + rep.vtotal, (unsigned long)rep.flags); + } + + /* + * Older servers sometimes had server privates that the VidMode + * extention made available. So to be compatiable pretend that + * there are no server privates to pass to the client + */ + rep.privsize = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.dotclock, n); + swaps(&rep.hdisplay, n); + swaps(&rep.hsyncstart, n); + swaps(&rep.hsyncend, n); + swaps(&rep.htotal, n); + swaps(&rep.hskew, n); + swaps(&rep.vdisplay, n); + swaps(&rep.vsyncstart, n); + swaps(&rep.vsyncend, n); + swaps(&rep.vtotal, n); + swapl(&rep.flags, n); + swapl(&rep.privsize, n); + } + if (ver < 2) { + oldrep.type = rep.type; + oldrep.sequenceNumber = rep.sequenceNumber; + oldrep.length = rep.length; + oldrep.dotclock = rep.dotclock; + oldrep.hdisplay = rep.hdisplay; + oldrep.hsyncstart = rep.hsyncstart; + oldrep.hsyncend = rep.hsyncend; + oldrep.htotal = rep.htotal; + oldrep.vdisplay = rep.vdisplay; + oldrep.vsyncstart = rep.vsyncstart; + oldrep.vsyncend = rep.vsyncend; + oldrep.vtotal = rep.vtotal; + oldrep.flags = rep.flags; + oldrep.privsize = rep.privsize; + WriteToClient(client, sizeof(xXF86OldVidModeGetModeLineReply), + (char *)&oldrep); + } else { + WriteToClient(client, sizeof(xXF86VidModeGetModeLineReply), + (char *)&rep); + } + return Success; +} + +static int +ProcXF86VidModeGetAllModeLines(ClientPtr client) +{ + REQUEST(xXF86VidModeGetAllModeLinesReq); + xXF86VidModeGetAllModeLinesReply rep; + xXF86VidModeModeInfo mdinf; + xXF86OldVidModeModeInfo oldmdinf; + pointer mode; + int modecount, dotClock; + register int n; + int ver; + + DEBUG_P("XF86VidModeGetAllModelines"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + ver = ClientMajorVersion(client); + + modecount = VidModeGetNumOfModes(stuff->screen); + if (modecount < 1) + return (VidModeErrorBase + XF86VidModeExtensionDisabled); + + if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + rep.type = X_Reply; + rep.length = SIZEOF(xXF86VidModeGetAllModeLinesReply) - + SIZEOF(xGenericReply); + if (ver < 2) + rep.length += modecount * sizeof(xXF86OldVidModeModeInfo); + else + rep.length += modecount * sizeof(xXF86VidModeModeInfo); + rep.length >>= 2; + rep.sequenceNumber = client->sequence; + rep.modecount = modecount; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.modecount, n); + } + WriteToClient(client, sizeof(xXF86VidModeGetAllModeLinesReply), (char *)&rep); + + do { + mdinf.dotclock = dotClock; + mdinf.hdisplay = VidModeGetModeValue(mode, VIDMODE_H_DISPLAY); + mdinf.hsyncstart = VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART); + mdinf.hsyncend = VidModeGetModeValue(mode, VIDMODE_H_SYNCEND); + mdinf.htotal = VidModeGetModeValue(mode, VIDMODE_H_TOTAL); + mdinf.hskew = VidModeGetModeValue(mode, VIDMODE_H_SKEW); + mdinf.vdisplay = VidModeGetModeValue(mode, VIDMODE_V_DISPLAY); + mdinf.vsyncstart = VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART); + mdinf.vsyncend = VidModeGetModeValue(mode, VIDMODE_V_SYNCEND); + mdinf.vtotal = VidModeGetModeValue(mode, VIDMODE_V_TOTAL); + mdinf.flags = VidModeGetModeValue(mode, VIDMODE_FLAGS); + mdinf.privsize = 0; + if (client->swapped) { + swapl(&mdinf.dotclock, n); + swaps(&mdinf.hdisplay, n); + swaps(&mdinf.hsyncstart, n); + swaps(&mdinf.hsyncend, n); + swaps(&mdinf.htotal, n); + swaps(&mdinf.hskew, n); + swaps(&mdinf.vdisplay, n); + swaps(&mdinf.vsyncstart, n); + swaps(&mdinf.vsyncend, n); + swaps(&mdinf.vtotal, n); + swapl(&mdinf.flags, n); + swapl(&mdinf.privsize, n); + } + if (ver < 2) { + oldmdinf.dotclock = mdinf.dotclock; + oldmdinf.hdisplay = mdinf.hdisplay; + oldmdinf.hsyncstart = mdinf.hsyncstart; + oldmdinf.hsyncend = mdinf.hsyncend; + oldmdinf.htotal = mdinf.htotal; + oldmdinf.vdisplay = mdinf.vdisplay; + oldmdinf.vsyncstart = mdinf.vsyncstart; + oldmdinf.vsyncend = mdinf.vsyncend; + oldmdinf.vtotal = mdinf.vtotal; + oldmdinf.flags = mdinf.flags; + oldmdinf.privsize = mdinf.privsize; + WriteToClient(client, sizeof(xXF86OldVidModeModeInfo), + (char *)&oldmdinf); + } else { + WriteToClient(client, sizeof(xXF86VidModeModeInfo), (char *)&mdinf); + } + + } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); + + return Success; +} + +#define MODEMATCH(mode,stuff) \ + (VidModeGetModeValue(mode, VIDMODE_H_DISPLAY) == stuff->hdisplay \ + && VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART) == stuff->hsyncstart \ + && VidModeGetModeValue(mode, VIDMODE_H_SYNCEND) == stuff->hsyncend \ + && VidModeGetModeValue(mode, VIDMODE_H_TOTAL) == stuff->htotal \ + && VidModeGetModeValue(mode, VIDMODE_V_DISPLAY) == stuff->vdisplay \ + && VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART) == stuff->vsyncstart \ + && VidModeGetModeValue(mode, VIDMODE_V_SYNCEND) == stuff->vsyncend \ + && VidModeGetModeValue(mode, VIDMODE_V_TOTAL) == stuff->vtotal \ + && VidModeGetModeValue(mode, VIDMODE_FLAGS) == stuff->flags ) + +static int +ProcXF86VidModeAddModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeAddModeLineReq); + xXF86OldVidModeAddModeLineReq *oldstuff = + (xXF86OldVidModeAddModeLineReq *)client->requestBuffer; + xXF86VidModeAddModeLineReq newstuff; + pointer mode; + int len; + int dotClock; + int ver; + + DEBUG_P("XF86VidModeAddModeline"); + + ver = ClientMajorVersion(client); + if (ver < 2) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->dotclock = oldstuff->dotclock; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + stuff->after_dotclock = oldstuff->after_dotclock; + stuff->after_hdisplay = oldstuff->after_hdisplay; + stuff->after_hsyncstart = oldstuff->after_hsyncstart; + stuff->after_hsyncend = oldstuff->after_hsyncend; + stuff->after_htotal = oldstuff->after_htotal; + stuff->after_hskew = 0; + stuff->after_vdisplay = oldstuff->after_vdisplay; + stuff->after_vsyncstart = oldstuff->after_vsyncstart; + stuff->after_vsyncend = oldstuff->after_vsyncend; + stuff->after_vtotal = oldstuff->after_vtotal; + stuff->after_flags = oldstuff->after_flags; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("AddModeLine - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->dotclock); + ErrorF("AddModeLine - hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + ErrorF(" after - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->after_dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->after_hdisplay, stuff->after_hsyncstart, + stuff->after_hsyncend, stuff->after_htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->after_vdisplay, stuff->after_vsyncstart, + stuff->after_vsyncend, stuff->after_vtotal, + (unsigned long)stuff->after_flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeAddModeLineReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86OldVidModeAddModeLineReq)); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeAddModeLineReq)); + } + if (len != stuff->privsize) + return BadLength; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + return BadValue; + + if (stuff->after_hsyncstart < stuff->after_hdisplay || + stuff->after_hsyncend < stuff->after_hsyncstart || + stuff->after_htotal < stuff->after_hsyncend || + stuff->after_vsyncstart < stuff->after_vdisplay || + stuff->after_vsyncend < stuff->after_vsyncstart || + stuff->after_vtotal < stuff->after_vsyncend) + return BadValue; + + if (stuff->after_htotal != 0 || stuff->after_vtotal != 0) { + Bool found = FALSE; + if (VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) { + do { + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) + == dotClock) && MODEMATCH(mode, stuff)) { + found = TRUE; + break; + } + } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); + } + if (!found) + return BadValue; + } + + + mode = VidModeCreateMode(); + if (mode == NULL) + return BadValue; + + VidModeSetModeValue(mode, VIDMODE_CLOCK, stuff->dotclock); + VidModeSetModeValue(mode, VIDMODE_H_DISPLAY, stuff->hdisplay); + VidModeSetModeValue(mode, VIDMODE_H_SYNCSTART, stuff->hsyncstart); + VidModeSetModeValue(mode, VIDMODE_H_SYNCEND, stuff->hsyncend); + VidModeSetModeValue(mode, VIDMODE_H_TOTAL, stuff->htotal); + VidModeSetModeValue(mode, VIDMODE_H_SKEW, stuff->hskew); + VidModeSetModeValue(mode, VIDMODE_V_DISPLAY, stuff->vdisplay); + VidModeSetModeValue(mode, VIDMODE_V_SYNCSTART, stuff->vsyncstart); + VidModeSetModeValue(mode, VIDMODE_V_SYNCEND, stuff->vsyncend); + VidModeSetModeValue(mode, VIDMODE_V_TOTAL, stuff->vtotal); + VidModeSetModeValue(mode, VIDMODE_FLAGS, stuff->flags); + + if (stuff->privsize) + ErrorF("AddModeLine - Privates in request have been ignored\n"); + + /* Check that the mode is consistent with the monitor specs */ + switch (VidModeCheckModeForMonitor(stuff->screen, mode)) { + case MODE_OK: + break; + case MODE_HSYNC: + case MODE_H_ILLEGAL: + free(mode); + return VidModeErrorBase + XF86VidModeBadHTimings; + case MODE_VSYNC: + case MODE_V_ILLEGAL: + free(mode); + return VidModeErrorBase + XF86VidModeBadVTimings; + default: + free(mode); + return VidModeErrorBase + XF86VidModeModeUnsuitable; + } + + /* Check that the driver is happy with the mode */ + if (VidModeCheckModeForDriver(stuff->screen, mode) != MODE_OK) { + free(mode); + return VidModeErrorBase + XF86VidModeModeUnsuitable; + } + + VidModeSetCrtcForMode(stuff->screen, mode); + + VidModeAddModeline(stuff->screen, mode); + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("AddModeLine - Succeeded\n"); + return Success; +} + +static int +ProcXF86VidModeDeleteModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeDeleteModeLineReq); + xXF86OldVidModeDeleteModeLineReq *oldstuff = + (xXF86OldVidModeDeleteModeLineReq *)client->requestBuffer; + xXF86VidModeDeleteModeLineReq newstuff; + pointer mode; + int len, dotClock; + int ver; + + DEBUG_P("XF86VidModeDeleteModeline"); + + ver = ClientMajorVersion(client); + if (ver < 2) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->dotclock = oldstuff->dotclock; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("DeleteModeLine - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeDeleteModeLineReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86OldVidModeDeleteModeLineReq)); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeDeleteModeLineReq)); + } + if (len != stuff->privsize) { + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("req_len = %ld, sizeof(Req) = %d, privsize = %ld, " + "len = %d, length = %d\n", + (unsigned long)client->req_len, + (int)sizeof(xXF86VidModeDeleteModeLineReq)>>2, + (unsigned long)stuff->privsize, len, stuff->length); + } + return BadLength; + } + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("Checking against clock: %d (%d)\n", + VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_V_TOTAL), + VidModeGetModeValue(mode, VIDMODE_FLAGS)); + } + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && + MODEMATCH(mode, stuff)) + return BadValue; + + if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + do { + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("Checking against clock: %d (%d)\n", + VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_V_TOTAL), + VidModeGetModeValue(mode, VIDMODE_FLAGS)); + } + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && + MODEMATCH(mode, stuff)) { + VidModeDeleteModeline(stuff->screen, mode); + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("DeleteModeLine - Succeeded\n"); + return Success; + } + } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); + + return BadValue; +} + +static int +ProcXF86VidModeModModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeModModeLineReq); + xXF86OldVidModeModModeLineReq *oldstuff = + (xXF86OldVidModeModModeLineReq *)client->requestBuffer; + xXF86VidModeModModeLineReq newstuff; + pointer mode, modetmp; + int len, dotClock; + int ver; + + DEBUG_P("XF86VidModeModModeline"); + + ver = ClientMajorVersion(client); + if (ver < 2 ) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("ModModeLine - scrn: %d hdsp: %d hbeg: %d hend: %d httl: %d\n", + (int)stuff->screen, stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeModModeLineReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86OldVidModeModModeLineReq)); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeModModeLineReq)); + } + if (len != stuff->privsize) + return BadLength; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + return BadValue; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + modetmp = VidModeCreateMode(); + VidModeCopyMode(mode, modetmp); + + VidModeSetModeValue(modetmp, VIDMODE_H_DISPLAY, stuff->hdisplay); + VidModeSetModeValue(modetmp, VIDMODE_H_SYNCSTART, stuff->hsyncstart); + VidModeSetModeValue(modetmp, VIDMODE_H_SYNCEND, stuff->hsyncend); + VidModeSetModeValue(modetmp, VIDMODE_H_TOTAL, stuff->htotal); + VidModeSetModeValue(modetmp, VIDMODE_H_SKEW, stuff->hskew); + VidModeSetModeValue(modetmp, VIDMODE_V_DISPLAY, stuff->vdisplay); + VidModeSetModeValue(modetmp, VIDMODE_V_SYNCSTART, stuff->vsyncstart); + VidModeSetModeValue(modetmp, VIDMODE_V_SYNCEND, stuff->vsyncend); + VidModeSetModeValue(modetmp, VIDMODE_V_TOTAL, stuff->vtotal); + VidModeSetModeValue(modetmp, VIDMODE_FLAGS, stuff->flags); + + if (stuff->privsize) + ErrorF("ModModeLine - Privates in request have been ignored\n"); + + /* Check that the mode is consistent with the monitor specs */ + switch (VidModeCheckModeForMonitor(stuff->screen, modetmp)) { + case MODE_OK: + break; + case MODE_HSYNC: + case MODE_H_ILLEGAL: + free(modetmp); + return VidModeErrorBase + XF86VidModeBadHTimings; + case MODE_VSYNC: + case MODE_V_ILLEGAL: + free(modetmp); + return VidModeErrorBase + XF86VidModeBadVTimings; + default: + free(modetmp); + return VidModeErrorBase + XF86VidModeModeUnsuitable; + } + + /* Check that the driver is happy with the mode */ + if (VidModeCheckModeForDriver(stuff->screen, modetmp) != MODE_OK) { + free(modetmp); + return VidModeErrorBase + XF86VidModeModeUnsuitable; + } + free(modetmp); + + VidModeSetModeValue(mode, VIDMODE_H_DISPLAY, stuff->hdisplay); + VidModeSetModeValue(mode, VIDMODE_H_SYNCSTART, stuff->hsyncstart); + VidModeSetModeValue(mode, VIDMODE_H_SYNCEND, stuff->hsyncend); + VidModeSetModeValue(mode, VIDMODE_H_TOTAL, stuff->htotal); + VidModeSetModeValue(mode, VIDMODE_H_SKEW, stuff->hskew); + VidModeSetModeValue(mode, VIDMODE_V_DISPLAY, stuff->vdisplay); + VidModeSetModeValue(mode, VIDMODE_V_SYNCSTART, stuff->vsyncstart); + VidModeSetModeValue(mode, VIDMODE_V_SYNCEND, stuff->vsyncend); + VidModeSetModeValue(mode, VIDMODE_V_TOTAL, stuff->vtotal); + VidModeSetModeValue(mode, VIDMODE_FLAGS, stuff->flags); + + VidModeSetCrtcForMode(stuff->screen, mode); + VidModeSwitchMode(stuff->screen, mode); + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("ModModeLine - Succeeded\n"); + return Success; +} + +static int +ProcXF86VidModeValidateModeLine(ClientPtr client) +{ + REQUEST(xXF86VidModeValidateModeLineReq); + xXF86OldVidModeValidateModeLineReq *oldstuff = + (xXF86OldVidModeValidateModeLineReq *)client->requestBuffer; + xXF86VidModeValidateModeLineReq newstuff; + xXF86VidModeValidateModeLineReply rep; + pointer mode, modetmp = NULL; + int len, status, dotClock; + int ver; + + DEBUG_P("XF86VidModeValidateModeline"); + + ver = ClientMajorVersion(client); + if (ver < 2) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->dotclock = oldstuff->dotclock; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("ValidateModeLine - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeValidateModeLineReq); + len = client->req_len - + bytes_to_int32(sizeof(xXF86OldVidModeValidateModeLineReq)); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeValidateModeLineReq)); + } + if (len != stuff->privsize) + return BadLength; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + status = MODE_OK; + + if (stuff->hsyncstart < stuff->hdisplay || + stuff->hsyncend < stuff->hsyncstart || + stuff->htotal < stuff->hsyncend || + stuff->vsyncstart < stuff->vdisplay || + stuff->vsyncend < stuff->vsyncstart || + stuff->vtotal < stuff->vsyncend) + { + status = MODE_BAD; + goto status_reply; + } + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + modetmp = VidModeCreateMode(); + VidModeCopyMode(mode, modetmp); + + VidModeSetModeValue(modetmp, VIDMODE_H_DISPLAY, stuff->hdisplay); + VidModeSetModeValue(modetmp, VIDMODE_H_SYNCSTART, stuff->hsyncstart); + VidModeSetModeValue(modetmp, VIDMODE_H_SYNCEND, stuff->hsyncend); + VidModeSetModeValue(modetmp, VIDMODE_H_TOTAL, stuff->htotal); + VidModeSetModeValue(modetmp, VIDMODE_H_SKEW, stuff->hskew); + VidModeSetModeValue(modetmp, VIDMODE_V_DISPLAY, stuff->vdisplay); + VidModeSetModeValue(modetmp, VIDMODE_V_SYNCSTART, stuff->vsyncstart); + VidModeSetModeValue(modetmp, VIDMODE_V_SYNCEND, stuff->vsyncend); + VidModeSetModeValue(modetmp, VIDMODE_V_TOTAL, stuff->vtotal); + VidModeSetModeValue(modetmp, VIDMODE_FLAGS, stuff->flags); + if (stuff->privsize) + ErrorF("ValidateModeLine - Privates in request have been ignored\n"); + + /* Check that the mode is consistent with the monitor specs */ + if ((status = VidModeCheckModeForMonitor(stuff->screen, modetmp)) != MODE_OK) + goto status_reply; + + /* Check that the driver is happy with the mode */ + status = VidModeCheckModeForDriver(stuff->screen, modetmp); + +status_reply: + if(modetmp) + free(modetmp); + + rep.type = X_Reply; + rep.length = bytes_to_int32(SIZEOF(xXF86VidModeValidateModeLineReply) + - SIZEOF(xGenericReply)); + rep.sequenceNumber = client->sequence; + rep.status = status; + if (client->swapped) { + register int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xXF86VidModeValidateModeLineReply), (char *)&rep); + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("ValidateModeLine - Succeeded (status = %d)\n", status); + return Success; +} + +static int +ProcXF86VidModeSwitchMode(ClientPtr client) +{ + REQUEST(xXF86VidModeSwitchModeReq); + + DEBUG_P("XF86VidModeSwitchMode"); + + REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + VidModeZoomViewport(stuff->screen, (short)stuff->zoom); + + return Success; +} + +static int +ProcXF86VidModeSwitchToMode(ClientPtr client) +{ + REQUEST(xXF86VidModeSwitchToModeReq); + xXF86OldVidModeSwitchToModeReq *oldstuff = + (xXF86OldVidModeSwitchToModeReq *)client->requestBuffer; + xXF86VidModeSwitchToModeReq newstuff; + pointer mode; + int len, dotClock; + int ver; + + DEBUG_P("XF86VidModeSwitchToMode"); + + ver = ClientMajorVersion(client); + if (ver < 2) { + /* convert from old format */ + stuff = &newstuff; + stuff->length = oldstuff->length; + stuff->screen = oldstuff->screen; + stuff->dotclock = oldstuff->dotclock; + stuff->hdisplay = oldstuff->hdisplay; + stuff->hsyncstart = oldstuff->hsyncstart; + stuff->hsyncend = oldstuff->hsyncend; + stuff->htotal = oldstuff->htotal; + stuff->hskew = 0; + stuff->vdisplay = oldstuff->vdisplay; + stuff->vsyncstart = oldstuff->vsyncstart; + stuff->vsyncend = oldstuff->vsyncend; + stuff->vtotal = oldstuff->vtotal; + stuff->flags = oldstuff->flags; + stuff->privsize = oldstuff->privsize; + } + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("SwitchToMode - scrn: %d clock: %ld\n", + (int)stuff->screen, (unsigned long)stuff->dotclock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + stuff->hdisplay, stuff->hsyncstart, + stuff->hsyncend, stuff->htotal); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %ld\n", + stuff->vdisplay, stuff->vsyncstart, stuff->vsyncend, + stuff->vtotal, (unsigned long)stuff->flags); + } + + if (ver < 2) { + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeSwitchToModeReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86OldVidModeSwitchToModeReq)); + } else { + REQUEST_AT_LEAST_SIZE(xXF86VidModeSwitchToModeReq); + len = client->req_len - bytes_to_int32(sizeof(xXF86VidModeSwitchToModeReq)); + } + if (len != stuff->privsize) + return BadLength; + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetCurrentModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) + && MODEMATCH(mode, stuff)) + return Success; + + if (!VidModeGetFirstModeline(stuff->screen, &mode, &dotClock)) + return BadValue; + + do { + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) { + ErrorF("Checking against clock: %d (%d)\n", + VidModeGetModeValue(mode, VIDMODE_CLOCK), dotClock); + ErrorF(" hdsp: %d hbeg: %d hend: %d httl: %d\n", + VidModeGetModeValue(mode, VIDMODE_H_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_H_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_H_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_H_TOTAL)); + ErrorF(" vdsp: %d vbeg: %d vend: %d vttl: %d flags: %d\n", + VidModeGetModeValue(mode, VIDMODE_V_DISPLAY), + VidModeGetModeValue(mode, VIDMODE_V_SYNCSTART), + VidModeGetModeValue(mode, VIDMODE_V_SYNCEND), + VidModeGetModeValue(mode, VIDMODE_V_TOTAL), + VidModeGetModeValue(mode, VIDMODE_FLAGS)); + } + if ((VidModeGetDotClock(stuff->screen, stuff->dotclock) == dotClock) && + MODEMATCH(mode, stuff)) { + + if (!VidModeSwitchMode(stuff->screen, mode)) + return BadValue; + + if (xf86GetVerbosity() > DEFAULT_XF86VIDMODE_VERBOSITY) + ErrorF("SwitchToMode - Succeeded\n"); + return Success; + } + } while (VidModeGetNextModeline(stuff->screen, &mode, &dotClock)); + + return BadValue; +} + +static int +ProcXF86VidModeLockModeSwitch(ClientPtr client) +{ + REQUEST(xXF86VidModeLockModeSwitchReq); + + REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq); + + DEBUG_P("XF86VidModeLockModeSwitch"); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeLockZoom(stuff->screen, (short)stuff->lock)) + return VidModeErrorBase + XF86VidModeZoomLocked; + + return Success; +} + +static int +ProcXF86VidModeGetMonitor(ClientPtr client) +{ + REQUEST(xXF86VidModeGetMonitorReq); + xXF86VidModeGetMonitorReply rep; + register int n; + CARD32 *hsyncdata, *vsyncdata; + int i, nHsync, nVrefresh; + pointer monitor; + + DEBUG_P("XF86VidModeGetMonitor"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeGetMonitor(stuff->screen, &monitor)) + return BadValue; + + nHsync = VidModeGetMonitorValue(monitor, VIDMODE_MON_NHSYNC, 0).i; + nVrefresh = VidModeGetMonitorValue(monitor, VIDMODE_MON_NVREFRESH, 0).i; + + rep.type = X_Reply; + if ((char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_VENDOR, 0)).ptr) + rep.vendorLength = strlen((char *)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_VENDOR, 0)).ptr); + else + rep.vendorLength = 0; + if ((char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_MODEL, 0)).ptr) + rep.modelLength = strlen((char *)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_MODEL, 0)).ptr); + else + rep.modelLength = 0; + rep.length = bytes_to_int32(SIZEOF(xXF86VidModeGetMonitorReply) - SIZEOF(xGenericReply) + + (nHsync + nVrefresh) * sizeof(CARD32) + + pad_to_int32(rep.vendorLength) + + pad_to_int32(rep.modelLength)); + rep.sequenceNumber = client->sequence; + rep.nhsync = nHsync; + rep.nvsync = nVrefresh; + hsyncdata = malloc(nHsync * sizeof(CARD32)); + if (!hsyncdata) { + return BadAlloc; + } + + vsyncdata = malloc(nVrefresh * sizeof(CARD32)); + if (!vsyncdata) { + free(hsyncdata); + return BadAlloc; + } + + for (i = 0; i < nHsync; i++) { + hsyncdata[i] = (unsigned short)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_HSYNC_LO, i)).f | + (unsigned short)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_HSYNC_HI, i)).f << 16; + } + for (i = 0; i < nVrefresh; i++) { + vsyncdata[i] = (unsigned short)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_VREFRESH_LO, i)).f | + (unsigned short)(VidModeGetMonitorValue(monitor, + VIDMODE_MON_VREFRESH_HI, i)).f << 16; + } + + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, SIZEOF(xXF86VidModeGetMonitorReply), (char *)&rep); + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, nHsync * sizeof(CARD32), + hsyncdata); + WriteSwappedDataToClient(client, nVrefresh * sizeof(CARD32), + vsyncdata); + if (rep.vendorLength) + WriteToClient(client, rep.vendorLength, (char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_VENDOR, 0)).ptr); + if (rep.modelLength) + WriteToClient(client, rep.modelLength, (char *)(VidModeGetMonitorValue(monitor, VIDMODE_MON_MODEL, 0)).ptr); + + free(hsyncdata); + free(vsyncdata); + + return Success; +} + +static int +ProcXF86VidModeGetViewPort(ClientPtr client) +{ + REQUEST(xXF86VidModeGetViewPortReq); + xXF86VidModeGetViewPortReply rep; + int x, y, n; + + DEBUG_P("XF86VidModeGetViewPort"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + VidModeGetViewPort(stuff->screen, &x, &y); + rep.x = x; + rep.y = y; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.x, n); + swapl(&rep.y, n); + } + WriteToClient(client, SIZEOF(xXF86VidModeGetViewPortReply), (char *)&rep); + return Success; +} + +static int +ProcXF86VidModeSetViewPort(ClientPtr client) +{ + REQUEST(xXF86VidModeSetViewPortReq); + + DEBUG_P("XF86VidModeSetViewPort"); + + REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeSetViewPort(stuff->screen, stuff->x, stuff->y)) + return BadValue; + + return Success; +} + +static int +ProcXF86VidModeGetDotClocks(ClientPtr client) +{ + REQUEST(xXF86VidModeGetDotClocksReq); + xXF86VidModeGetDotClocksReply rep; + register int n; + int numClocks; + CARD32 dotclock; + int *Clocks = NULL; + Bool ClockProg; + + DEBUG_P("XF86VidModeGetDotClocks"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetDotClocksReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + numClocks = VidModeGetNumOfClocks(stuff->screen, &ClockProg); + + rep.type = X_Reply; + rep.length = bytes_to_int32(SIZEOF(xXF86VidModeGetDotClocksReply) + - SIZEOF(xGenericReply) + numClocks); + rep.sequenceNumber = client->sequence; + rep.clocks = numClocks; + rep.maxclocks = MAXCLOCKS; + rep.flags = 0; + + if (!ClockProg) { + Clocks = malloc(numClocks * sizeof(int)); + if (!Clocks) + return BadValue; + if (!VidModeGetClocks(stuff->screen, Clocks)) { + free(Clocks); + return BadValue; + } + } + + if (ClockProg) { + rep.flags |= CLKFLAG_PROGRAMABLE; + } + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.clocks, n); + swapl(&rep.maxclocks, n); + swapl(&rep.flags, n); + } + WriteToClient(client, sizeof(xXF86VidModeGetDotClocksReply), (char *)&rep); + if (!ClockProg) { + for (n = 0; n < numClocks; n++) { + dotclock = *Clocks++; + if (client->swapped) { + WriteSwappedDataToClient(client, 4, (char *)&dotclock); + } else { + WriteToClient(client, 4, (char *)&dotclock); + } + } + } + + free(Clocks); + return Success; +} + +static int +ProcXF86VidModeSetGamma(ClientPtr client) +{ + REQUEST(xXF86VidModeSetGammaReq); + + DEBUG_P("XF86VidModeSetGamma"); + + REQUEST_SIZE_MATCH(xXF86VidModeSetGammaReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if (!VidModeSetGamma(stuff->screen, ((float)stuff->red)/10000., + ((float)stuff->green)/10000., ((float)stuff->blue)/10000.)) + return BadValue; + + return Success; +} + +static int +ProcXF86VidModeGetGamma(ClientPtr client) +{ + REQUEST(xXF86VidModeGetGammaReq); + xXF86VidModeGetGammaReply rep; + register int n; + float red, green, blue; + + DEBUG_P("XF86VidModeGetGamma"); + + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (!VidModeGetGamma(stuff->screen, &red, &green, &blue)) + return BadValue; + rep.red = (CARD32)(red * 10000.); + rep.green = (CARD32)(green * 10000.); + rep.blue = (CARD32)(blue * 10000.); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.red, n); + swapl(&rep.green, n); + swapl(&rep.blue, n); + } + WriteToClient(client, sizeof(xXF86VidModeGetGammaReply), (char *)&rep); + return Success; +} + +static int +ProcXF86VidModeSetGammaRamp(ClientPtr client) +{ + CARD16 *r, *g, *b; + int length; + REQUEST(xXF86VidModeSetGammaRampReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if(stuff->size != VidModeGetGammaRampSize(stuff->screen)) + return BadValue; + + length = (stuff->size + 1) & ~1; + + REQUEST_FIXED_SIZE(xXF86VidModeSetGammaRampReq, length * 6); + + r = (CARD16*)&stuff[1]; + g = r + length; + b = g + length; + + if (!VidModeSetGammaRamp(stuff->screen, stuff->size, r, g, b)) + return BadValue; + + return Success; +} + +static int +ProcXF86VidModeGetGammaRamp(ClientPtr client) +{ + CARD16 *ramp = NULL; + int n, length; + size_t ramplen = 0; + xXF86VidModeGetGammaRampReply rep; + REQUEST(xXF86VidModeGetGammaRampReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + if(stuff->size != VidModeGetGammaRampSize(stuff->screen)) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampReq); + + length = (stuff->size + 1) & ~1; + + if(stuff->size) { + ramplen = length * 3 * sizeof(CARD16); + if (!(ramp = malloc(ramplen))) + return BadAlloc; + + if (!VidModeGetGammaRamp(stuff->screen, stuff->size, + ramp, ramp + length, ramp + (length * 2))) { + free(ramp); + return BadValue; + } + } + + rep.type = X_Reply; + rep.length = (length >> 1) * 3; + rep.sequenceNumber = client->sequence; + rep.size = stuff->size; + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.size, n); + SwapShorts((short*)ramp, length * 3); + } + WriteToClient(client, sizeof(xXF86VidModeGetGammaRampReply), (char *)&rep); + + if(stuff->size) { + WriteToClient(client, ramplen, (char*)ramp); + free(ramp); + } + + return Success; +} + + +static int +ProcXF86VidModeGetGammaRampSize(ClientPtr client) +{ + xXF86VidModeGetGammaRampSizeReply rep; + int n; + REQUEST(xXF86VidModeGetGammaRampSizeReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampSizeReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.size = VidModeGetGammaRampSize(stuff->screen); + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.size, n); + } + WriteToClient(client,sizeof(xXF86VidModeGetGammaRampSizeReply),(char*)&rep); + + return Success; +} + +static int +ProcXF86VidModeGetPermissions(ClientPtr client) +{ + xXF86VidModeGetPermissionsReply rep; + int n; + REQUEST(xXF86VidModeGetPermissionsReq); + + if(stuff->screen >= screenInfo.numScreens) + return BadValue; + + REQUEST_SIZE_MATCH(xXF86VidModeGetPermissionsReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.permissions = XF86VM_READ_PERMISSION; + if (xf86GetVidModeEnabled() && + (xf86GetVidModeAllowNonLocal() || LocalClient (client))) { + rep.permissions |= XF86VM_WRITE_PERMISSION; + } + if(client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.permissions, n); + } + WriteToClient(client,sizeof(xXF86VidModeGetPermissionsReply),(char*)&rep); + + return Success; +} + + +static int +ProcXF86VidModeSetClientVersion(ClientPtr client) +{ + REQUEST(xXF86VidModeSetClientVersionReq); + + VidModePrivPtr pPriv; + + DEBUG_P("XF86VidModeSetClientVersion"); + + REQUEST_SIZE_MATCH(xXF86VidModeSetClientVersionReq); + + if ((pPriv = VM_GETPRIV(client)) == NULL) { + pPriv = malloc(sizeof(VidModePrivRec)); + if (!pPriv) + return BadAlloc; + VM_SETPRIV(client, pPriv); + } + pPriv->major = stuff->major; + pPriv->minor = stuff->minor; + + return Success; +} + +static int +ProcXF86VidModeDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XF86VidModeQueryVersion: + return ProcXF86VidModeQueryVersion(client); + case X_XF86VidModeGetModeLine: + return ProcXF86VidModeGetModeLine(client); + case X_XF86VidModeGetMonitor: + return ProcXF86VidModeGetMonitor(client); + case X_XF86VidModeGetAllModeLines: + return ProcXF86VidModeGetAllModeLines(client); + case X_XF86VidModeValidateModeLine: + return ProcXF86VidModeValidateModeLine(client); + case X_XF86VidModeGetViewPort: + return ProcXF86VidModeGetViewPort(client); + case X_XF86VidModeGetDotClocks: + return ProcXF86VidModeGetDotClocks(client); + case X_XF86VidModeSetClientVersion: + return ProcXF86VidModeSetClientVersion(client); + case X_XF86VidModeGetGamma: + return ProcXF86VidModeGetGamma(client); + case X_XF86VidModeGetGammaRamp: + return ProcXF86VidModeGetGammaRamp(client); + case X_XF86VidModeGetGammaRampSize: + return ProcXF86VidModeGetGammaRampSize(client); + case X_XF86VidModeGetPermissions: + return ProcXF86VidModeGetPermissions(client); + default: + if (!xf86GetVidModeEnabled()) + return VidModeErrorBase + XF86VidModeExtensionDisabled; + if (xf86GetVidModeAllowNonLocal() || LocalClient (client)) { + switch (stuff->data) { + case X_XF86VidModeAddModeLine: + return ProcXF86VidModeAddModeLine(client); + case X_XF86VidModeDeleteModeLine: + return ProcXF86VidModeDeleteModeLine(client); + case X_XF86VidModeModModeLine: + return ProcXF86VidModeModModeLine(client); + case X_XF86VidModeSwitchMode: + return ProcXF86VidModeSwitchMode(client); + case X_XF86VidModeSwitchToMode: + return ProcXF86VidModeSwitchToMode(client); + case X_XF86VidModeLockModeSwitch: + return ProcXF86VidModeLockModeSwitch(client); + case X_XF86VidModeSetViewPort: + return ProcXF86VidModeSetViewPort(client); + case X_XF86VidModeSetGamma: + return ProcXF86VidModeSetGamma(client); + case X_XF86VidModeSetGammaRamp: + return ProcXF86VidModeSetGammaRamp(client); + default: + return BadRequest; + } + } else + return VidModeErrorBase + XF86VidModeClientNotLocal; + } +} + +static int +SProcXF86VidModeQueryVersion(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86VidModeQueryVersion(client); +} + +static int +SProcXF86VidModeGetModeLine(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetModeLineReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetModeLine(client); +} + +static int +SProcXF86VidModeGetAllModeLines(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetAllModeLinesReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetAllModeLines(client); +} + +static int +SProcXF86VidModeAddModeLine(ClientPtr client) +{ + xXF86OldVidModeAddModeLineReq *oldstuff = + (xXF86OldVidModeAddModeLineReq *)client->requestBuffer; + int ver; + register int n; + + REQUEST(xXF86VidModeAddModeLineReq); + ver = ClientMajorVersion(client); + if (ver < 2) { + swaps(&oldstuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeAddModeLineReq); + swapl(&oldstuff->screen, n); + swaps(&oldstuff->hdisplay, n); + swaps(&oldstuff->hsyncstart, n); + swaps(&oldstuff->hsyncend, n); + swaps(&oldstuff->htotal, n); + swaps(&oldstuff->vdisplay, n); + swaps(&oldstuff->vsyncstart, n); + swaps(&oldstuff->vsyncend, n); + swaps(&oldstuff->vtotal, n); + swapl(&oldstuff->flags, n); + swapl(&oldstuff->privsize, n); + SwapRestL(oldstuff); + } else { + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->hskew, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + } + return ProcXF86VidModeAddModeLine(client); +} + +static int +SProcXF86VidModeDeleteModeLine(ClientPtr client) +{ + xXF86OldVidModeDeleteModeLineReq *oldstuff = + (xXF86OldVidModeDeleteModeLineReq *)client->requestBuffer; + int ver; + register int n; + + REQUEST(xXF86VidModeDeleteModeLineReq); + ver = ClientMajorVersion(client); + if (ver < 2) { + swaps(&oldstuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeDeleteModeLineReq); + swapl(&oldstuff->screen, n); + swaps(&oldstuff->hdisplay, n); + swaps(&oldstuff->hsyncstart, n); + swaps(&oldstuff->hsyncend, n); + swaps(&oldstuff->htotal, n); + swaps(&oldstuff->vdisplay, n); + swaps(&oldstuff->vsyncstart, n); + swaps(&oldstuff->vsyncend, n); + swaps(&oldstuff->vtotal, n); + swapl(&oldstuff->flags, n); + swapl(&oldstuff->privsize, n); + SwapRestL(oldstuff); + } else { + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->hskew, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + } + return ProcXF86VidModeDeleteModeLine(client); +} + +static int +SProcXF86VidModeModModeLine(ClientPtr client) +{ + xXF86OldVidModeModModeLineReq *oldstuff = + (xXF86OldVidModeModModeLineReq *)client->requestBuffer; + int ver; + register int n; + + REQUEST(xXF86VidModeModModeLineReq); + ver = ClientMajorVersion(client); + if (ver < 2) { + swaps(&oldstuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeModModeLineReq); + swapl(&oldstuff->screen, n); + swaps(&oldstuff->hdisplay, n); + swaps(&oldstuff->hsyncstart, n); + swaps(&oldstuff->hsyncend, n); + swaps(&oldstuff->htotal, n); + swaps(&oldstuff->vdisplay, n); + swaps(&oldstuff->vsyncstart, n); + swaps(&oldstuff->vsyncend, n); + swaps(&oldstuff->vtotal, n); + swapl(&oldstuff->flags, n); + swapl(&oldstuff->privsize, n); + SwapRestL(oldstuff); + } else { + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->hskew, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + } + return ProcXF86VidModeModModeLine(client); +} + +static int +SProcXF86VidModeValidateModeLine(ClientPtr client) +{ + xXF86OldVidModeValidateModeLineReq *oldstuff = + (xXF86OldVidModeValidateModeLineReq *)client->requestBuffer; + int ver; + register int n; + + REQUEST(xXF86VidModeValidateModeLineReq); + ver = ClientMajorVersion(client); + if (ver < 2) { + swaps(&oldstuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86OldVidModeValidateModeLineReq); + swapl(&oldstuff->screen, n); + swaps(&oldstuff->hdisplay, n); + swaps(&oldstuff->hsyncstart, n); + swaps(&oldstuff->hsyncend, n); + swaps(&oldstuff->htotal, n); + swaps(&oldstuff->vdisplay, n); + swaps(&oldstuff->vsyncstart, n); + swaps(&oldstuff->vsyncend, n); + swaps(&oldstuff->vtotal, n); + swapl(&oldstuff->flags, n); + swapl(&oldstuff->privsize, n); + SwapRestL(oldstuff); + } else { + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq); + swapl(&stuff->screen, n); + swaps(&stuff->hdisplay, n); + swaps(&stuff->hsyncstart, n); + swaps(&stuff->hsyncend, n); + swaps(&stuff->htotal, n); + swaps(&stuff->hskew, n); + swaps(&stuff->vdisplay, n); + swaps(&stuff->vsyncstart, n); + swaps(&stuff->vsyncend, n); + swaps(&stuff->vtotal, n); + swapl(&stuff->flags, n); + swapl(&stuff->privsize, n); + SwapRestL(stuff); + } + return ProcXF86VidModeValidateModeLine(client); +} + +static int +SProcXF86VidModeSwitchMode(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSwitchModeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq); + swaps(&stuff->screen, n); + swaps(&stuff->zoom, n); + return ProcXF86VidModeSwitchMode(client); +} + +static int +SProcXF86VidModeSwitchToMode(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSwitchToModeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSwitchToModeReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeSwitchToMode(client); +} + +static int +SProcXF86VidModeLockModeSwitch(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeLockModeSwitchReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq); + swaps(&stuff->screen, n); + swaps(&stuff->lock, n); + return ProcXF86VidModeLockModeSwitch(client); +} + +static int +SProcXF86VidModeGetMonitor(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetMonitorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetMonitor(client); +} + +static int +SProcXF86VidModeGetViewPort(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetViewPortReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetViewPort(client); +} + +static int +SProcXF86VidModeSetViewPort(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSetViewPortReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq); + swaps(&stuff->screen, n); + swapl(&stuff->x, n); + swapl(&stuff->y, n); + return ProcXF86VidModeSetViewPort(client); +} + +static int +SProcXF86VidModeGetDotClocks(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetDotClocksReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetDotClocksReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetDotClocks(client); +} + +static int +SProcXF86VidModeSetClientVersion(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSetClientVersionReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSetClientVersionReq); + swaps(&stuff->major, n); + swaps(&stuff->minor, n); + return ProcXF86VidModeSetClientVersion(client); +} + +static int +SProcXF86VidModeSetGamma(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeSetGammaReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeSetGammaReq); + swaps(&stuff->screen, n); + swapl(&stuff->red, n); + swapl(&stuff->green, n); + swapl(&stuff->blue, n); + return ProcXF86VidModeSetGamma(client); +} + +static int +SProcXF86VidModeGetGamma(ClientPtr client) +{ + register int n; + REQUEST(xXF86VidModeGetGammaReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetGamma(client); +} + +static int +SProcXF86VidModeSetGammaRamp(ClientPtr client) +{ + int length, n; + REQUEST(xXF86VidModeSetGammaRampReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xXF86VidModeSetGammaRampReq); + swaps(&stuff->size, n); + swaps(&stuff->screen, n); + length = ((stuff->size + 1) & ~1) * 6; + REQUEST_FIXED_SIZE(xXF86VidModeSetGammaRampReq, length); + SwapRestS(stuff); + return ProcXF86VidModeSetGammaRamp(client); +} + +static int +SProcXF86VidModeGetGammaRamp(ClientPtr client) +{ + int n; + REQUEST(xXF86VidModeGetGammaRampReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampReq); + swaps(&stuff->size, n); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetGammaRamp(client); +} + +static int +SProcXF86VidModeGetGammaRampSize(ClientPtr client) +{ + int n; + REQUEST(xXF86VidModeGetGammaRampSizeReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampSizeReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetGammaRampSize(client); +} + +static int +SProcXF86VidModeGetPermissions(ClientPtr client) +{ + int n; + REQUEST(xXF86VidModeGetPermissionsReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXF86VidModeGetPermissionsReq); + swaps(&stuff->screen, n); + return ProcXF86VidModeGetPermissions(client); +} + + +static int +SProcXF86VidModeDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XF86VidModeQueryVersion: + return SProcXF86VidModeQueryVersion(client); + case X_XF86VidModeGetModeLine: + return SProcXF86VidModeGetModeLine(client); + case X_XF86VidModeGetMonitor: + return SProcXF86VidModeGetMonitor(client); + case X_XF86VidModeGetAllModeLines: + return SProcXF86VidModeGetAllModeLines(client); + case X_XF86VidModeGetViewPort: + return SProcXF86VidModeGetViewPort(client); + case X_XF86VidModeValidateModeLine: + return SProcXF86VidModeValidateModeLine(client); + case X_XF86VidModeGetDotClocks: + return SProcXF86VidModeGetDotClocks(client); + case X_XF86VidModeSetClientVersion: + return SProcXF86VidModeSetClientVersion(client); + case X_XF86VidModeGetGamma: + return SProcXF86VidModeGetGamma(client); + case X_XF86VidModeGetGammaRamp: + return SProcXF86VidModeGetGammaRamp(client); + case X_XF86VidModeGetGammaRampSize: + return SProcXF86VidModeGetGammaRampSize(client); + case X_XF86VidModeGetPermissions: + return SProcXF86VidModeGetPermissions(client); + default: + if (!xf86GetVidModeEnabled()) + return VidModeErrorBase + XF86VidModeExtensionDisabled; + if (xf86GetVidModeAllowNonLocal() || LocalClient(client)) { + switch (stuff->data) { + case X_XF86VidModeAddModeLine: + return SProcXF86VidModeAddModeLine(client); + case X_XF86VidModeDeleteModeLine: + return SProcXF86VidModeDeleteModeLine(client); + case X_XF86VidModeModModeLine: + return SProcXF86VidModeModModeLine(client); + case X_XF86VidModeSwitchMode: + return SProcXF86VidModeSwitchMode(client); + case X_XF86VidModeSwitchToMode: + return SProcXF86VidModeSwitchToMode(client); + case X_XF86VidModeLockModeSwitch: + return SProcXF86VidModeLockModeSwitch(client); + case X_XF86VidModeSetViewPort: + return SProcXF86VidModeSetViewPort(client); + case X_XF86VidModeSetGamma: + return SProcXF86VidModeSetGamma(client); + case X_XF86VidModeSetGammaRamp: + return SProcXF86VidModeSetGammaRamp(client); + default: + return BadRequest; + } + } else + return VidModeErrorBase + XF86VidModeClientNotLocal; + } +} diff --git a/xorg-server/hw/xfree86/dri/dri.c b/xorg-server/hw/xfree86/dri/dri.c index 836967c73..a8b050a94 100644 --- a/xorg-server/hw/xfree86/dri/dri.c +++ b/xorg-server/hw/xfree86/dri/dri.c @@ -1,2504 +1,2504 @@ -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -Copyright 2000 VA Linux Systems, Inc. -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -/* - * Authors: - * Jens Owen - * Rickard E. (Rik) Faith - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include -#include -#include -#include -#include -#include - -#include -#include -#include "xf86drm.h" -#include "misc.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "servermd.h" -#define _XF86DRI_SERVER_ -#include -#include "swaprep.h" -#include "xf86str.h" -#include "dri.h" -#include "sarea.h" -#include "dristruct.h" -#include "xf86.h" -#include "xf86drm.h" -#include "mi.h" -#include "mipointer.h" -#include "xf86_OSproc.h" -#include "inputstr.h" -#include "xf86VGAarbiter.h" - -#define PCI_BUS_NO_DOMAIN(bus) ((bus) & 0xffu) - -static int DRIEntPrivIndex = -1; -static int DRIScreenPrivKeyIndex; -static DevPrivateKey DRIScreenPrivKey = &DRIScreenPrivKeyIndex; -static int DRIWindowPrivKeyIndex; -static DevPrivateKey DRIWindowPrivKey = &DRIWindowPrivKeyIndex; -static unsigned long DRIGeneration = 0; -static unsigned int DRIDrawableValidationStamp = 0; - -static RESTYPE DRIDrawablePrivResType; -static RESTYPE DRIContextPrivResType; -static void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv); - -drmServerInfo DRIDRMServerInfo; - - /* Wrapper just like xf86DrvMsg, but - without the verbosity level checking. - This will make it easy to turn off some - messages later, based on verbosity - level. */ - -/* - * Since we're already referencing things from the XFree86 common layer in - * this file, we'd might as well just call xf86VDrvMsgVerb, and have - * consistent message formatting. The verbosity of these messages can be - * easily changed here. - */ -#define DRI_MSG_VERBOSITY 1 -static void -DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap); - va_end(ap); -} - - -static void -DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv) -{ - if (pDRIEntPriv->pLSAREA != NULL) { - drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize); - pDRIEntPriv->pLSAREA = NULL; - } - if (pDRIEntPriv->hLSAREA != 0) { - drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA); - } - if (pDRIEntPriv->drmFD >= 0) { - drmClose(pDRIEntPriv->drmFD); - pDRIEntPriv->drmFD = 0; - } -} - -int -DRIMasterFD(ScrnInfoPtr pScrn) -{ - return DRI_ENT_PRIV(pScrn)->drmFD; -} - -void * -DRIMasterSareaPointer(ScrnInfoPtr pScrn) -{ - return DRI_ENT_PRIV(pScrn)->pLSAREA; -} - -drm_handle_t -DRIMasterSareaHandle(ScrnInfoPtr pScrn) -{ - return DRI_ENT_PRIV(pScrn)->hLSAREA; -} - - -Bool -DRIOpenDRMMaster(ScrnInfoPtr pScrn, - unsigned long sAreaSize, - const char *busID, - const char *drmDriverName) -{ - drmSetVersion saveSv, sv; - Bool drmWasAvailable; - DRIEntPrivPtr pDRIEntPriv; - DRIEntPrivRec tmp; - drmVersionPtr drmlibv; - int drmlibmajor, drmlibminor; - const char *openBusID; - int count; - int err; - - if (DRIEntPrivIndex == -1) - DRIEntPrivIndex = xf86AllocateEntityPrivateIndex(); - - pDRIEntPriv = DRI_ENT_PRIV(pScrn); - - if (pDRIEntPriv && pDRIEntPriv->drmFD != -1) - return TRUE; - - drmWasAvailable = drmAvailable(); - - memset(&tmp, 0, sizeof(tmp)); - - /* Check the DRM lib version. - * drmGetLibVersion was not supported in version 1.0, so check for - * symbol first to avoid possible crash or hang. - */ - - drmlibmajor = 1; - drmlibminor = 0; - if (xf86LoaderCheckSymbol("drmGetLibVersion")) { - drmlibv = drmGetLibVersion(-1); - if (drmlibv != NULL) { - drmlibmajor = drmlibv->version_major; - drmlibminor = drmlibv->version_minor; - drmFreeVersion(drmlibv); - } - } - - /* Check if the libdrm can handle falling back to loading based on name - * if a busid string is passed. - */ - openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL; - - tmp.drmFD = -1; - sv.drm_di_major = 1; - sv.drm_di_minor = 1; - sv.drm_dd_major = -1; - - saveSv = sv; - count = 10; - while (count--) { - tmp.drmFD = drmOpen(drmDriverName, openBusID); - - if (tmp.drmFD < 0) { - DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n"); - goto out_err; - } - - err = drmSetInterfaceVersion(tmp.drmFD, &sv); - - if (err != -EPERM) - break; - - sv = saveSv; - drmClose(tmp.drmFD); - tmp.drmFD = -1; - usleep(100000); - } - - if (tmp.drmFD <= 0) { - DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n"); - goto out_err; - } - - if (!drmWasAvailable) { - DRIDrvMsg(-1, X_INFO, - "[drm] loaded kernel module for \"%s\" driver.\n", - drmDriverName); - } - - if (err != 0) { - sv.drm_di_major = 1; - sv.drm_di_minor = 0; - } - - DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n", - sv.drm_di_major, sv.drm_di_minor); - - if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1) - err = 0; - else - err = drmSetBusid(tmp.drmFD, busID); - - if (err) { - DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n"); - goto out_err; - } - - /* - * Create a lock-containing sarea. - */ - - if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM, - DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) { - DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n"); - tmp.hLSAREA = 0; - goto out_err; - } - - if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize, - (drmAddressPtr)(&tmp.pLSAREA)) < 0) { - DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n"); - tmp.pLSAREA = NULL; - goto out_err; - } - - memset(tmp.pLSAREA, 0, sAreaSize); - - /* - * Reserved contexts are handled by the first opened screen. - */ - - tmp.resOwner = NULL; - - if (!pDRIEntPriv) - pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1); - - if (!pDRIEntPriv) { - DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for " - "DRM device.\n"); - goto out_err; - } - *pDRIEntPriv = tmp; - xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr = - pDRIEntPriv; - - DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n"); - return TRUE; - - out_err: - - DRIOpenDRMCleanup(&tmp); - return FALSE; -} - -static void -DRIClipNotifyAllDrawables(ScreenPtr pScreen); - -static void -dri_crtc_notify(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIClipNotifyAllDrawables(pScreen); - xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); - xf86_crtc_notify(pScreen); - pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, dri_crtc_notify); -} - -Bool -DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) -{ - DRIScreenPrivPtr pDRIPriv; - drm_context_t * reserved; - int reserved_count; - int i; - DRIEntPrivPtr pDRIEntPriv; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - DRIContextFlags flags = 0; - DRIContextPrivPtr pDRIContextPriv; - - /* If the DRI extension is disabled, do not initialize the DRI */ - if (noXFree86DRIExtension) { - DRIDrvMsg(pScreen->myNum, X_WARNING, - "Direct rendering has been disabled.\n"); - return FALSE; - } - - if (!xf86VGAarbiterAllowDRI(pScreen)) { - DRIDrvMsg(pScreen->myNum, X_WARNING, - "Direct rendering is not supported when VGA arb is necessary for the device\n"); - return FALSE; - } - -#ifdef PANORAMIX - /* - * If Xinerama is on, don't allow DRI to initialise. It won't be usable - * anyway. - */ - if (!noPanoramiXExtension) { - DRIDrvMsg(pScreen->myNum, X_WARNING, - "Direct rendering is not supported when Xinerama is enabled\n"); - return FALSE; - } -#endif - - if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize, - pDRIInfo->busIdString, - pDRIInfo->drmDriverName)) - return FALSE; - - pDRIEntPriv = DRI_ENT_PRIV(pScrn); - - if (DRIGeneration != serverGeneration) - DRIGeneration = serverGeneration; - - pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec)); - if (!pDRIPriv) { - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); - return FALSE; - } - - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); - pDRIPriv->drmFD = pDRIEntPriv->drmFD; - pDRIPriv->directRenderingSupport = TRUE; - pDRIPriv->pDriverInfo = pDRIInfo; - pDRIPriv->nrWindows = 0; - pDRIPriv->nrWindowsVisible = 0; - pDRIPriv->fullscreen = NULL; - - pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx; - pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv; - - pDRIPriv->grabbedDRILock = FALSE; - pDRIPriv->drmSIGIOHandlerInstalled = FALSE; - *pDRMFD = pDRIPriv->drmFD; - - if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) { - - if (drmAddMap( pDRIPriv->drmFD, - 0, - pDRIPriv->pDriverInfo->SAREASize, - DRM_SHM, - 0, - &pDRIPriv->hSAREA) < 0) - { - pDRIPriv->directRenderingSupport = FALSE; - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); - drmClose(pDRIPriv->drmFD); - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] drmAddMap failed\n"); - return FALSE; - } - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] added %d byte SAREA at %p\n", - pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA); - - /* Backwards compat. */ - if (drmMap( pDRIPriv->drmFD, - pDRIPriv->hSAREA, - pDRIPriv->pDriverInfo->SAREASize, - (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0) - { - pDRIPriv->directRenderingSupport = FALSE; - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); - drmClose(pDRIPriv->drmFD); - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] drmMap failed\n"); - return FALSE; - } - DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n", - pDRIPriv->hSAREA, pDRIPriv->pSAREA); - memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize); - } else { - DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock " - "SAREA also for drawables.\n"); - pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA; - pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA; - pDRIEntPriv->sAreaGrabbed = TRUE; - } - - pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA; - pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA; - - if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer) - { - if (drmAddMap( pDRIPriv->drmFD, - (drm_handle_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress, - pDRIPriv->pDriverInfo->frameBufferSize, - DRM_FRAME_BUFFER, - 0, - &pDRIPriv->pDriverInfo->hFrameBuffer) < 0) - { - pDRIPriv->directRenderingSupport = FALSE; - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); - drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); - drmClose(pDRIPriv->drmFD); - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] drmAddMap failed\n"); - return FALSE; - } - DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n", - pDRIPriv->pDriverInfo->hFrameBuffer); - } else { - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] framebuffer mapped by ddx driver\n"); - } - - if (pDRIEntPriv->resOwner == NULL) { - pDRIEntPriv->resOwner = pScreen; - - /* Add tags for reserved contexts */ - if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, - &reserved_count))) { - int i; - void *tag; - - for (i = 0; i < reserved_count; i++) { - tag = DRICreateContextPrivFromHandle(pScreen, - reserved[i], - DRI_CONTEXT_RESERVED); - drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag); - } - drmFreeReservedContextList(reserved); - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] added %d reserved context%s for kernel\n", - reserved_count, reserved_count > 1 ? "s" : ""); - } - } - - /* validate max drawable table entry set by driver */ - if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) || - (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "Invalid max drawable table size set by driver: %d\n", - pDRIPriv->pDriverInfo->maxDrawableTableEntry); - } - - /* Initialize drawable tables (screen private and SAREA) */ - for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { - pDRIPriv->DRIDrawables[i] = NULL; - pDRIPriv->pSAREA->drawableTable[i].stamp = 0; - pDRIPriv->pSAREA->drawableTable[i].flags = 0; - } - - pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount; - pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext; - - if (!pDRIEntPriv->keepFDOpen) - pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen; - - pDRIEntPriv->refCount++; - - /* Set up flags for DRICreateContextPriv */ - switch (pDRIInfo->driverSwapMethod) { - case DRI_KERNEL_SWAP: - flags = DRI_CONTEXT_2DONLY; - break; - case DRI_HIDE_X_CONTEXT: - flags = DRI_CONTEXT_PRESERVED; - break; - } - - if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, - &pDRIPriv->myContext, - flags))) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "failed to create server context\n"); - return FALSE; - } - pDRIPriv->myContextPriv = pDRIContextPriv; - - DRIDrvMsg(pScreen->myNum, X_INFO, - "X context handle = %p\n", pDRIPriv->myContext); - - /* Now that we have created the X server's context, we can grab the - * hardware lock for the X server. - */ - DRILock(pScreen, 0); - pDRIPriv->grabbedDRILock = TRUE; - - /* pointers so that we can prevent memory leaks later */ - pDRIPriv->hiddenContextStore = NULL; - pDRIPriv->partial3DContextStore = NULL; - - switch(pDRIInfo->driverSwapMethod) { - case DRI_HIDE_X_CONTEXT: - /* Server will handle 3D swaps, and hide 2D swaps from kernel. - * Register server context as a preserved context. - */ - - /* allocate memory for hidden context store */ - pDRIPriv->hiddenContextStore - = (void *)xcalloc(1, pDRIInfo->contextSize); - if (!pDRIPriv->hiddenContextStore) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "failed to allocate hidden context\n"); - DRIDestroyContextPriv(pDRIContextPriv); - return FALSE; - } - - /* allocate memory for partial 3D context store */ - pDRIPriv->partial3DContextStore - = (void *)xcalloc(1, pDRIInfo->contextSize); - if (!pDRIPriv->partial3DContextStore) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[DRI] failed to allocate partial 3D context\n"); - xfree(pDRIPriv->hiddenContextStore); - DRIDestroyContextPriv(pDRIContextPriv); - return FALSE; - } - - /* save initial context store */ - if (pDRIInfo->SwapContext) { - (*pDRIInfo->SwapContext)( - pScreen, - DRI_NO_SYNC, - DRI_2D_CONTEXT, - pDRIPriv->hiddenContextStore, - DRI_NO_CONTEXT, - NULL); - } - /* fall through */ - - case DRI_SERVER_SWAP: - /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT - * setup signal handler for receiving swap requests from kernel - */ - if (!(pDRIPriv->drmSIGIOHandlerInstalled = - drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[drm] failed to setup DRM signal handler\n"); - if (pDRIPriv->hiddenContextStore) - xfree(pDRIPriv->hiddenContextStore); - if (pDRIPriv->partial3DContextStore) - xfree(pDRIPriv->partial3DContextStore); - DRIDestroyContextPriv(pDRIContextPriv); - return FALSE; - } else { - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] installed DRM signal handler\n"); - } - - default: - break; - } - - return TRUE; -} - -Bool -DRIFinishScreenInit(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; - - /* Wrap DRI support */ - if (pDRIInfo->wrap.ValidateTree) { - pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; - pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree; - } - if (pDRIInfo->wrap.PostValidateTree) { - pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; - pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree; - } - if (pDRIInfo->wrap.WindowExposures) { - pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; - pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures; - } - - pDRIPriv->DestroyWindow = pScreen->DestroyWindow; - pScreen->DestroyWindow = DRIDestroyWindow; - - pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, - dri_crtc_notify); - - if (pDRIInfo->wrap.CopyWindow) { - pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; - pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow; - } - if (pDRIInfo->wrap.ClipNotify) { - pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; - pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify; - } - if (pDRIInfo->wrap.AdjustFrame) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; - pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame; - } - pDRIPriv->wrapped = TRUE; - - DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n"); - - return TRUE; -} - -void -DRICloseScreen(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIInfoPtr pDRIInfo; - drm_context_t * reserved; - int reserved_count; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn); - Bool closeMaster; - - if (pDRIPriv) { - - pDRIInfo = pDRIPriv->pDriverInfo; - - if (pDRIPriv->wrapped) { - /* Unwrap DRI Functions */ - if (pDRIInfo->wrap.ValidateTree) { - pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; - pDRIPriv->wrap.ValidateTree = NULL; - } - if (pDRIInfo->wrap.PostValidateTree) { - pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; - pDRIPriv->wrap.PostValidateTree = NULL; - } - if (pDRIInfo->wrap.WindowExposures) { - pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; - pDRIPriv->wrap.WindowExposures = NULL; - } - if (pDRIPriv->DestroyWindow) { - pScreen->DestroyWindow = pDRIPriv->DestroyWindow; - pDRIPriv->DestroyWindow = NULL; - } - - xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); - - if (pDRIInfo->wrap.CopyWindow) { - pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; - pDRIPriv->wrap.CopyWindow = NULL; - } - if (pDRIInfo->wrap.ClipNotify) { - pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; - pDRIPriv->wrap.ClipNotify = NULL; - } - if (pDRIInfo->wrap.AdjustFrame) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; - pDRIPriv->wrap.AdjustFrame = NULL; - } - - pDRIPriv->wrapped = FALSE; - } - - if (pDRIPriv->drmSIGIOHandlerInstalled) { - if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[drm] failed to remove DRM signal handler\n"); - } - } - - if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) { - DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv); - } - - if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "failed to destroy server context\n"); - } - - /* Remove tags for reserved contexts */ - if (pDRIEntPriv->resOwner == pScreen) { - pDRIEntPriv->resOwner = NULL; - - if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, - &reserved_count))) { - int i; - - for (i = 0; i < reserved_count; i++) { - DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD, - reserved[i])); - } - drmFreeReservedContextList(reserved); - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] removed %d reserved context%s for kernel\n", - reserved_count, reserved_count > 1 ? "s" : ""); - } - } - - /* Make sure signals get unblocked etc. */ - drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext); - pDRIPriv->pLockRefCount = NULL; - closeMaster = (--pDRIEntPriv->refCount == 0) && - !pDRIEntPriv->keepFDOpen; - if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) { - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] unmapping %d bytes of SAREA %p at %p\n", - pDRIInfo->SAREASize, - pDRIPriv->hSAREA, - pDRIPriv->pSAREA); - if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[drm] unable to unmap %d bytes" - " of SAREA %p at %p\n", - pDRIInfo->SAREASize, - pDRIPriv->hSAREA, - pDRIPriv->pSAREA); - } - } else { - pDRIEntPriv->sAreaGrabbed = FALSE; - } - - if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) { - drmClose(pDRIPriv->drmFD); - if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) { - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] Closed DRM master.\n"); - pDRIEntPriv->drmFD = -1; - } - } - - xfree(pDRIPriv); - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); - } -} - -#define DRM_MSG_VERBOSITY 3 - -static int dri_drm_debug_print(const char *format, va_list ap) -{ - xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); - return 0; -} - -static void dri_drm_get_perms(gid_t *group, mode_t *mode) -{ - *group = xf86ConfigDRI.group; - *mode = xf86ConfigDRI.mode; -} - -drmServerInfo DRIDRMServerInfo = { - dri_drm_debug_print, - xf86LoadKernelModule, - dri_drm_get_perms, -}; - -Bool -DRIExtensionInit(void) -{ - if (!DRIScreenPrivKey || DRIGeneration != serverGeneration) { - return FALSE; - } - - DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, - "DRIDrawable"); - DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete, - "DRIContext"); - - if (!DRIDrawablePrivResType || !DRIContextPrivResType) - return FALSE; - - RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); - - return TRUE; -} - -void -DRIReset(void) -{ - /* - * This stub routine is called when the X Server recycles, resources - * allocated by DRIExtensionInit need to be managed here. - * - * Currently this routine is a stub because all the interesting resources - * are managed via the screen init process. - */ -} - -Bool -DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (pDRIPriv) - *isCapable = pDRIPriv->directRenderingSupport; - else - *isCapable = FALSE; - - return TRUE; -} - -Bool -DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - *hSAREA = pDRIPriv->hSAREA; - *busIdString = pDRIPriv->pDriverInfo->busIdString; - - return TRUE; -} - -Bool -DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; - return TRUE; -} - -Bool -DRICloseConnection(ScreenPtr pScreen) -{ - return TRUE; -} - -Bool -DRIGetClientDriverName(ScreenPtr pScreen, - int *ddxDriverMajorVersion, - int *ddxDriverMinorVersion, - int *ddxDriverPatchVersion, - char **clientDriverName) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion; - *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion; - *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion; - *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName; - - return TRUE; -} - -/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper - functions that layer on drmCreateContext and drmAddContextTag. - - DRICreateContextPriv always creates a kernel drm_context_t and then calls - DRICreateContextPrivFromHandle to create a DRIContextPriv structure for - DRI tracking. For the SIGIO handler, the drm_context_t is associated with - DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv - area and are passed to the kernel (if necessary). - - DRICreateContextPriv returns a pointer to newly allocated - DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */ - -DRIContextPrivPtr -DRICreateContextPriv(ScreenPtr pScreen, - drm_context_t * pHWContext, - DRIContextFlags flags) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) { - return NULL; - } - - return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags); -} - -DRIContextPrivPtr -DRICreateContextPrivFromHandle(ScreenPtr pScreen, - drm_context_t hHWContext, - DRIContextFlags flags) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIContextPrivPtr pDRIContextPriv; - int contextPrivSize; - - contextPrivSize = sizeof(DRIContextPrivRec) + - pDRIPriv->pDriverInfo->contextSize; - if (!(pDRIContextPriv = xcalloc(1, contextPrivSize))) { - return NULL; - } - pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1); - - drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv); - - pDRIContextPriv->hwContext = hHWContext; - pDRIContextPriv->pScreen = pScreen; - pDRIContextPriv->flags = flags; - pDRIContextPriv->valid3D = FALSE; - - if (flags & DRI_CONTEXT_2DONLY) { - if (drmSetContextFlags(pDRIPriv->drmFD, - hHWContext, - DRM_CONTEXT_2DONLY)) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[drm] failed to set 2D context flag\n"); - DRIDestroyContextPriv(pDRIContextPriv); - return NULL; - } - } - if (flags & DRI_CONTEXT_PRESERVED) { - if (drmSetContextFlags(pDRIPriv->drmFD, - hHWContext, - DRM_CONTEXT_PRESERVED)) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[drm] failed to set preserved flag\n"); - DRIDestroyContextPriv(pDRIContextPriv); - return NULL; - } - } - return pDRIContextPriv; -} - -Bool -DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv) -{ - DRIScreenPrivPtr pDRIPriv; - - if (!pDRIContextPriv) return TRUE; - - pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); - - if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) { - /* Don't delete reserved contexts from - kernel area -- the kernel manages its - reserved contexts itself. */ - if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext)) - return FALSE; - } - - /* Remove the tag last to prevent a race - condition where the context has pending - buffers. The context can't be re-used - while in this thread, but buffers can be - dispatched asynchronously. */ - drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext); - xfree(pDRIContextPriv); - return TRUE; -} - -static Bool -DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIContextPrivPtr pDRIContextPriv; - void *contextStore; - - if (!(pDRIContextPriv = - DRICreateContextPriv(pScreen, - &pDRIPriv->pSAREA->dummy_context, 0))) { - return FALSE; - } - - contextStore = DRIGetContextStore(pDRIContextPriv); - if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { - if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL, - pDRIPriv->pSAREA->dummy_context, - NULL, - (DRIContextType)(long)contextStore)) { - DRIDestroyContextPriv(pDRIContextPriv); - return FALSE; - } - } - - pDRIPriv->dummyCtxPriv = pDRIContextPriv; - return TRUE; -} - -static void -DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv; - void *contextStore; - - if (!pDRIContextPriv) return; - if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) { - contextStore = DRIGetContextStore(pDRIContextPriv); - pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, - pDRIContextPriv->hwContext, - (DRIContextType)(long)contextStore); - } - - DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv); - pDRIPriv->dummyCtxPriv = NULL; -} - -Bool -DRICreateContext(ScreenPtr pScreen, VisualPtr visual, - XID context, drm_context_t * pHWContext) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIContextPrivPtr pDRIContextPriv; - void *contextStore; - - if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) { - if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) { - DRIDrvMsg(pScreen->myNum, X_INFO, - "[drm] Could not create dummy context\n"); - return FALSE; - } - } - - if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { - return FALSE; - } - - contextStore = DRIGetContextStore(pDRIContextPriv); - if (pDRIPriv->pDriverInfo->CreateContext) { - if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, NULL, - *pHWContext, NULL, - (DRIContextType)(long)contextStore))) { - DRIDestroyContextPriv(pDRIContextPriv); - return FALSE; - } - } - - /* track this in case the client dies before cleanup */ - AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv); - - return TRUE; -} - -Bool -DRIDestroyContext(ScreenPtr pScreen, XID context) -{ - FreeResourceByType(context, DRIContextPrivResType, FALSE); - - return TRUE; -} - -/* DRIContextPrivDelete is called by the resource manager. */ -Bool -DRIContextPrivDelete(pointer pResource, XID id) -{ - DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource; - DRIScreenPrivPtr pDRIPriv; - void *contextStore; - - pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); - if (pDRIPriv->pDriverInfo->DestroyContext) { - contextStore = DRIGetContextStore(pDRIContextPriv); - pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, - pDRIContextPriv->hwContext, - (DRIContextType)(long)contextStore); - } - return DRIDestroyContextPriv(pDRIContextPriv); -} - - -/* This walks the drawable timestamp array and invalidates all of them - * in the case of transition from private to shared backbuffers. It's - * not necessary for correctness, because DRIClipNotify gets called in - * time to prevent any conflict, but the transition from - * shared->private is sometimes missed if we don't do this. - */ -static void -DRIClipNotifyAllDrawables(ScreenPtr pScreen) -{ - int i; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { - pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++; - } -} - - -static void -DRITransitionToSharedBuffers(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; - - DRIClipNotifyAllDrawables( pScreen ); - - if (pDRIInfo->TransitionSingleToMulti3D) - pDRIInfo->TransitionSingleToMulti3D( pScreen ); -} - - -static void -DRITransitionToPrivateBuffers(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; - - DRIClipNotifyAllDrawables( pScreen ); - - if (pDRIInfo->TransitionMultiToSingle3D) - pDRIInfo->TransitionMultiToSingle3D( pScreen ); -} - - -static void -DRITransitionTo3d(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; - - DRIClipNotifyAllDrawables( pScreen ); - - if (pDRIInfo->TransitionTo3d) - pDRIInfo->TransitionTo3d( pScreen ); -} - -static void -DRITransitionTo2d(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; - - DRIClipNotifyAllDrawables( pScreen ); - - if (pDRIInfo->TransitionTo2d) - pDRIInfo->TransitionTo2d( pScreen ); -} - - -static int -DRIDCNTreeTraversal(WindowPtr pWin, pointer data) -{ - DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - - if (pDRIDrawablePriv) { - ScreenPtr pScreen = pWin->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (REGION_NUM_RECTS(&pWin->clipList) > 0) { - WindowPtr *pDRIWindows = (WindowPtr*)data; - int i = 0; - - while (pDRIWindows[i]) - i++; - - pDRIWindows[i] = pWin; - - pDRIPriv->nrWalked++; - } - - if (pDRIPriv->nrWindows == pDRIPriv->nrWalked) - return WT_STOPWALKING; - } - - return WT_WALKCHILDREN; -} - -static void -DRIDriverClipNotify(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (pDRIPriv->pDriverInfo->ClipNotify) { - WindowPtr *pDRIWindows = xcalloc(sizeof(WindowPtr), pDRIPriv->nrWindows); - DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; - - if (pDRIPriv->nrWindows > 0) { - pDRIPriv->nrWalked = 0; - TraverseTree(WindowTable[pScreen->myNum], DRIDCNTreeTraversal, - (pointer)pDRIWindows); - } - - pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows); - - xfree(pDRIWindows); - } -} - -static void -DRIIncreaseNumberVisible(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - switch (++pDRIPriv->nrWindowsVisible) { - case 1: - DRITransitionTo3d( pScreen ); - break; - case 2: - DRITransitionToSharedBuffers( pScreen ); - break; - default: - break; - } - - DRIDriverClipNotify(pScreen); -} - -static void -DRIDecreaseNumberVisible(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - switch (--pDRIPriv->nrWindowsVisible) { - case 0: - DRITransitionTo2d( pScreen ); - break; - case 1: - DRITransitionToPrivateBuffers( pScreen ); - break; - default: - break; - } - - DRIDriverClipNotify(pScreen); -} - -Bool -DRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable, - drm_drawable_t * hHWDrawable) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIDrawablePrivPtr pDRIDrawablePriv; - WindowPtr pWin; - - if (pDrawable->type == DRAWABLE_WINDOW) { - pWin = (WindowPtr)pDrawable; - if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { - pDRIDrawablePriv->refCount++; - - if (!pDRIDrawablePriv->hwDrawable) { - drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable); - } - } - else { - /* allocate a DRI Window Private record */ - if (!(pDRIDrawablePriv = xalloc(sizeof(DRIDrawablePrivRec)))) { - return FALSE; - } - - /* Only create a drm_drawable_t once */ - if (drmCreateDrawable(pDRIPriv->drmFD, - &pDRIDrawablePriv->hwDrawable)) { - xfree(pDRIDrawablePriv); - return FALSE; - } - - /* add it to the list of DRI drawables for this screen */ - pDRIDrawablePriv->pScreen = pScreen; - pDRIDrawablePriv->refCount = 1; - pDRIDrawablePriv->drawableIndex = -1; - pDRIDrawablePriv->nrects = REGION_NUM_RECTS(&pWin->clipList); - - /* save private off of preallocated index */ - dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, - pDRIDrawablePriv); - pDRIPriv->nrWindows++; - - if (pDRIDrawablePriv->nrects) - DRIIncreaseNumberVisible(pScreen); - } - - /* track this in case the client dies */ - AddResource(FakeClientID(client->index), DRIDrawablePrivResType, - (pointer)(intptr_t)pDrawable->id); - - if (pDRIDrawablePriv->hwDrawable) { - drmUpdateDrawableInfo(pDRIPriv->drmFD, - pDRIDrawablePriv->hwDrawable, - DRM_DRAWABLE_CLIPRECTS, - REGION_NUM_RECTS(&pWin->clipList), - REGION_RECTS(&pWin->clipList)); - *hHWDrawable = pDRIDrawablePriv->hwDrawable; - } - } - else if (pDrawable->type != DRAWABLE_PIXMAP) { /* PBuffer */ - /* NOT_DONE */ - return FALSE; - } - - return TRUE; -} - -static void -DRIDrawablePrivDestroy(WindowPtr pWin) -{ - DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - ScreenPtr pScreen; - DRIScreenPrivPtr pDRIPriv; - - if (!pDRIDrawablePriv) - return; - - pScreen = pWin->drawable.pScreen; - pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (pDRIDrawablePriv->drawableIndex != -1) { - /* bump stamp to force outstanding 3D requests to resync */ - pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp - = DRIDrawableValidationStamp++; - - /* release drawable table entry */ - pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; - } - - pDRIPriv->nrWindows--; - - if (pDRIDrawablePriv->nrects) - DRIDecreaseNumberVisible(pScreen); - - drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable); - - xfree(pDRIDrawablePriv); - dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); -} - -static Bool -DRIDestroyDrawableCB(pointer value, XID id, pointer data) -{ - if (value == data) { - /* This calls back DRIDrawablePrivDelete which frees private area */ - FreeResourceByType(id, DRIDrawablePrivResType, FALSE); - - return TRUE; - } - - return FALSE; -} - -Bool -DRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable) -{ - if (pDrawable->type == DRAWABLE_WINDOW) { - LookupClientResourceComplex(client, DRIDrawablePrivResType, - DRIDestroyDrawableCB, - (pointer)(intptr_t)pDrawable->id); - } - else { /* pixmap (or for GLX 1.3, a PBuffer) */ - /* NOT_DONE */ - return FALSE; - } - - return TRUE; -} - -Bool -DRIDrawablePrivDelete(pointer pResource, XID id) -{ - WindowPtr pWin; - int rc; - - /* For DRIDrawablePrivResType, the XID is the client's fake ID. The - * important XID is the value in pResource. */ - id = (XID)(intptr_t)pResource; - rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess); - - if (rc == Success) { - DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - - if (!pDRIDrwPriv) - return FALSE; - - if (--pDRIDrwPriv->refCount == 0) - DRIDrawablePrivDestroy(pWin); - - return TRUE; - } - else { /* pixmap (or for GLX 1.3, a PBuffer) */ - /* NOT_DONE */ - return FALSE; - } -} - -Bool -DRIGetDrawableInfo(ScreenPtr pScreen, - DrawablePtr pDrawable, - unsigned int* index, - unsigned int* stamp, - int* X, - int* Y, - int* W, - int* H, - int* numClipRects, - drm_clip_rect_t ** pClipRects, - int* backX, - int* backY, - int* numBackClipRects, - drm_clip_rect_t ** pBackClipRects) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv; - WindowPtr pWin, pOldWin; - int i; - -#if 0 - printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry); -#endif - - if (pDrawable->type == DRAWABLE_WINDOW) { - pWin = (WindowPtr)pDrawable; - if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { - - /* Manage drawable table */ - if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */ - - /* Search table for empty entry */ - i = 0; - while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) { - if (!(pDRIPriv->DRIDrawables[i])) { - pDRIPriv->DRIDrawables[i] = pDrawable; - pDRIDrawablePriv->drawableIndex = i; - pDRIPriv->pSAREA->drawableTable[i].stamp = - DRIDrawableValidationStamp++; - break; - } - i++; - } - - /* Search table for oldest entry */ - if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) { - unsigned int oldestStamp = ~0; - int oldestIndex = 0; - i = pDRIPriv->pDriverInfo->maxDrawableTableEntry; - while (i--) { - if (pDRIPriv->pSAREA->drawableTable[i].stamp < - oldestStamp) { - oldestIndex = i; - oldestStamp = - pDRIPriv->pSAREA->drawableTable[i].stamp; - } - } - pDRIDrawablePriv->drawableIndex = oldestIndex; - - /* release oldest drawable table entry */ - pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex]; - pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin); - pOldDrawPriv->drawableIndex = -1; - - /* claim drawable table entry */ - pDRIPriv->DRIDrawables[oldestIndex] = pDrawable; - - /* validate SAREA entry */ - pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp = - DRIDrawableValidationStamp++; - - /* check for stamp wrap around */ - if (oldestStamp > DRIDrawableValidationStamp) { - - /* walk SAREA table and invalidate all drawables */ - for( i=0; - i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; - i++) { - pDRIPriv->pSAREA->drawableTable[i].stamp = - DRIDrawableValidationStamp++; - } - } - } - - /* If the driver wants to be notified when the index is - * set for a drawable, let it know now. - */ - if (pDRIPriv->pDriverInfo->SetDrawableIndex) - pDRIPriv->pDriverInfo->SetDrawableIndex(pWin, - pDRIDrawablePriv->drawableIndex); - - /* reinit drawable ID if window is visible */ - if ((pWin->viewable) && - (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) - { - (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, - &pWin->clipList, pDRIDrawablePriv->drawableIndex); - } - } - - *index = pDRIDrawablePriv->drawableIndex; - *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp; - *X = (int)(pWin->drawable.x); - *Y = (int)(pWin->drawable.y); -#if 0 - *W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1); - *H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1); -#endif - *W = (int)(pWin->drawable.width); - *H = (int)(pWin->drawable.height); - *numClipRects = REGION_NUM_RECTS(&pWin->clipList); - *pClipRects = (drm_clip_rect_t *)REGION_RECTS(&pWin->clipList); - - if (!*numClipRects && pDRIPriv->fullscreen) { - /* use fake full-screen clip rect */ - pDRIPriv->fullscreen_rect.x1 = *X; - pDRIPriv->fullscreen_rect.y1 = *Y; - pDRIPriv->fullscreen_rect.x2 = *X + *W; - pDRIPriv->fullscreen_rect.y2 = *Y + *H; - - *numClipRects = 1; - *pClipRects = &pDRIPriv->fullscreen_rect; - } - - *backX = *X; - *backY = *Y; - - if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) { - /* Use a single cliprect. */ - - int x0 = *X; - int y0 = *Y; - int x1 = x0 + *W; - int y1 = y0 + *H; - - if (x0 < 0) x0 = 0; - if (y0 < 0) y0 = 0; - if (x1 > pScreen->width) x1 = pScreen->width; - if (y1 > pScreen->height) y1 = pScreen->height; - - if (y0 >= y1 || x0 >= x1) { - *numBackClipRects = 0; - *pBackClipRects = NULL; - } else { - pDRIPriv->private_buffer_rect.x1 = x0; - pDRIPriv->private_buffer_rect.y1 = y0; - pDRIPriv->private_buffer_rect.x2 = x1; - pDRIPriv->private_buffer_rect.y2 = y1; - - *numBackClipRects = 1; - *pBackClipRects = &(pDRIPriv->private_buffer_rect); - } - } else { - /* Use the frontbuffer cliprects for back buffers. */ - *numBackClipRects = 0; - *pBackClipRects = 0; - } - } - else { - /* Not a DRIDrawable */ - return FALSE; - } - } - else { /* pixmap (or for GLX 1.3, a PBuffer) */ - /* NOT_DONE */ - return FALSE; - } - - return TRUE; -} - -Bool -DRIGetDeviceInfo(ScreenPtr pScreen, - drm_handle_t * hFrameBuffer, - int* fbOrigin, - int* fbSize, - int* fbStride, - int* devPrivateSize, - void** pDevPrivate) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - *hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer; - *fbOrigin = 0; - *fbSize = pDRIPriv->pDriverInfo->frameBufferSize; - *fbStride = pDRIPriv->pDriverInfo->frameBufferStride; - *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize; - *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate; - - return TRUE; -} - -DRIInfoPtr -DRICreateInfoRec(void) -{ - DRIInfoPtr inforec = (DRIInfoPtr)xcalloc(1, sizeof(DRIInfoRec)); - if (!inforec) return NULL; - - /* Initialize defaults */ - inforec->busIdString = NULL; - - /* Wrapped function defaults */ - inforec->wrap.WakeupHandler = DRIDoWakeupHandler; - inforec->wrap.BlockHandler = DRIDoBlockHandler; - inforec->wrap.WindowExposures = DRIWindowExposures; - inforec->wrap.CopyWindow = DRICopyWindow; - inforec->wrap.ValidateTree = DRIValidateTree; - inforec->wrap.PostValidateTree = DRIPostValidateTree; - inforec->wrap.ClipNotify = DRIClipNotify; - inforec->wrap.AdjustFrame = DRIAdjustFrame; - - inforec->TransitionTo2d = 0; - inforec->TransitionTo3d = 0; - inforec->SetDrawableIndex = 0; - - return inforec; -} - -void -DRIDestroyInfoRec(DRIInfoPtr DRIInfo) -{ - if (DRIInfo->busIdString) xfree(DRIInfo->busIdString); - xfree((char*)DRIInfo); -} - - -void -DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask) -{ - int i; - - for (i = 0; i < screenInfo.numScreens; i++) { - ScreenPtr pScreen = screenInfo.screens[i]; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (pDRIPriv && - pDRIPriv->pDriverInfo->wrap.WakeupHandler) - (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData, - result, pReadmask); - } -} - -void -DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) -{ - int i; - - for (i = 0; i < screenInfo.numScreens; i++) { - ScreenPtr pScreen = screenInfo.screens[i]; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (pDRIPriv && - pDRIPriv->pDriverInfo->wrap.BlockHandler) - (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData, - pTimeout, pReadmask); - } -} - -void -DRIDoWakeupHandler(int screenNum, pointer wakeupData, - unsigned long result, pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[screenNum]; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - DRILock(pScreen, 0); - if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { - /* hide X context by swapping 2D component here */ - (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, - DRI_3D_SYNC, - DRI_2D_CONTEXT, - pDRIPriv->partial3DContextStore, - DRI_2D_CONTEXT, - pDRIPriv->hiddenContextStore); - } -} - -void -DRIDoBlockHandler(int screenNum, pointer blockData, - pointer pTimeout, pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[screenNum]; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { - /* hide X context by swapping 2D component here */ - (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, - DRI_2D_SYNC, - DRI_NO_CONTEXT, - NULL, - DRI_2D_CONTEXT, - pDRIPriv->partial3DContextStore); - } - - if (pDRIPriv->windowsTouched) - DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1); - pDRIPriv->windowsTouched = FALSE; - - DRIUnlock(pScreen); -} - -void -DRISwapContext(int drmFD, void *oldctx, void *newctx) -{ - DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx; - DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx; - ScreenPtr pScreen = newContext->pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - void* oldContextStore = NULL; - DRIContextType oldContextType; - void* newContextStore = NULL; - DRIContextType newContextType; - DRISyncType syncType; -#ifdef DEBUG - static int count = 0; - - if (!newContext) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n", - oldContext, newContext); - return; - } - - /* usefull for debugging, just print out after n context switches */ - if (!count || !(count % 1)) { - DRIDrvMsg(pScreen->myNum, X_INFO, - "[DRI] Context switch %5d from %p/0x%08x (%d)\n", - count, - oldContext, - oldContext ? oldContext->flags : 0, - oldContext ? oldContext->hwContext : -1); - DRIDrvMsg(pScreen->myNum, X_INFO, - "[DRI] Context switch %5d to %p/0x%08x (%d)\n", - count, - newContext, - newContext ? newContext->flags : 0, - newContext ? newContext->hwContext : -1); - } - ++count; -#endif - - if (!pDRIPriv->pDriverInfo->SwapContext) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[DRI] DDX driver missing context swap call back\n"); - return; - } - - if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { - - /* only 3D contexts are swapped in this case */ - if (oldContext) { - oldContextStore = DRIGetContextStore(oldContext); - oldContext->valid3D = TRUE; - oldContextType = DRI_3D_CONTEXT; - } else { - oldContextType = DRI_NO_CONTEXT; - } - newContextStore = DRIGetContextStore(newContext); - if ((newContext->valid3D) && - (newContext->hwContext != pDRIPriv->myContext)) { - newContextType = DRI_3D_CONTEXT; - } - else { - newContextType = DRI_2D_CONTEXT; - } - syncType = DRI_3D_SYNC; - } - else /* default: driverSwapMethod == DRI_SERVER_SWAP */ { - - /* optimize 2D context swaps */ - - if (newContext->flags & DRI_CONTEXT_2DONLY) { - /* go from 3D context to 2D context and only save 2D - * subset of 3D state - */ - oldContextStore = DRIGetContextStore(oldContext); - oldContextType = DRI_2D_CONTEXT; - newContextStore = DRIGetContextStore(newContext); - newContextType = DRI_2D_CONTEXT; - syncType = DRI_3D_SYNC; - pDRIPriv->lastPartial3DContext = oldContext; - } - else if (oldContext->flags & DRI_CONTEXT_2DONLY) { - if (pDRIPriv->lastPartial3DContext == newContext) { - /* go from 2D context back to previous 3D context and - * only restore 2D subset of previous 3D state - */ - oldContextStore = DRIGetContextStore(oldContext); - oldContextType = DRI_2D_CONTEXT; - newContextStore = DRIGetContextStore(newContext); - newContextType = DRI_2D_CONTEXT; - syncType = DRI_2D_SYNC; - } - else { - /* go from 2D context to a different 3D context */ - - /* call DDX driver to do partial restore */ - oldContextStore = DRIGetContextStore(oldContext); - newContextStore = - DRIGetContextStore(pDRIPriv->lastPartial3DContext); - (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, - DRI_2D_SYNC, - DRI_2D_CONTEXT, - oldContextStore, - DRI_2D_CONTEXT, - newContextStore); - - /* now setup for a complete 3D swap */ - oldContextStore = newContextStore; - oldContext->valid3D = TRUE; - oldContextType = DRI_3D_CONTEXT; - newContextStore = DRIGetContextStore(newContext); - if ((newContext->valid3D) && - (newContext->hwContext != pDRIPriv->myContext)) { - newContextType = DRI_3D_CONTEXT; - } - else { - newContextType = DRI_2D_CONTEXT; - } - syncType = DRI_NO_SYNC; - } - } - else { - /* now setup for a complete 3D swap */ - oldContextStore = newContextStore; - oldContext->valid3D = TRUE; - oldContextType = DRI_3D_CONTEXT; - newContextStore = DRIGetContextStore(newContext); - if ((newContext->valid3D) && - (newContext->hwContext != pDRIPriv->myContext)) { - newContextType = DRI_3D_CONTEXT; - } - else { - newContextType = DRI_2D_CONTEXT; - } - syncType = DRI_3D_SYNC; - } - } - - /* call DDX driver to perform the swap */ - (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, - syncType, - oldContextType, - oldContextStore, - newContextType, - newContextStore); -} - -void* -DRIGetContextStore(DRIContextPrivPtr context) -{ - return((void *)context->pContextStore); -} - -void -DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - - if(pDRIDrawablePriv) { - (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn, - pDRIDrawablePriv->drawableIndex); - } - - /* call lower wrapped functions */ - if (pDRIPriv && pDRIPriv->wrap.WindowExposures) { - - /* unwrap */ - pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; - - /* call lower layers */ - (*pScreen->WindowExposures)(pWin, prgn, bsreg); - - /* rewrap */ - pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; - pScreen->WindowExposures = DRIWindowExposures; - } -} - - -static int -DRITreeTraversal(WindowPtr pWin, pointer data) -{ - DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - - if(pDRIDrawablePriv) { - ScreenPtr pScreen = pWin->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if(REGION_NUM_RECTS(&(pWin->clipList)) > 0) { - RegionPtr reg = (RegionPtr)data; - - REGION_UNION(pScreen, reg, reg, &(pWin->clipList)); - pDRIPriv->nrWalked++; - } - - if(pDRIPriv->nrWindows == pDRIPriv->nrWalked) - return WT_STOPWALKING; - } - return WT_WALKCHILDREN; -} - -Bool -DRIDestroyWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - Bool retval = TRUE; - - DRIDrawablePrivDestroy(pWin); - - /* call lower wrapped functions */ - if(pDRIPriv->DestroyWindow) { - /* unwrap */ - pScreen->DestroyWindow = pDRIPriv->DestroyWindow; - - /* call lower layers */ - retval = (*pScreen->DestroyWindow)(pWin); - - /* rewrap */ - pDRIPriv->DestroyWindow = pScreen->DestroyWindow; - pScreen->DestroyWindow = DRIDestroyWindow; - } - - return retval; -} - -void -DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if(!pDRIPriv) return; - - if(pDRIPriv->nrWindowsVisible > 0) { - RegionRec reg; - - REGION_NULL(pScreen, ®); - pDRIPriv->nrWalked = 0; - TraverseTree(pWin, DRITreeTraversal, (pointer)(®)); - - if(REGION_NOTEMPTY(pScreen, ®)) { - REGION_TRANSLATE(pScreen, ®, ptOldOrg.x - pWin->drawable.x, - ptOldOrg.y - pWin->drawable.y); - REGION_INTERSECT(pScreen, ®, ®, prgnSrc); - - /* The MoveBuffers interface is not ideal */ - (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®, - pDRIPriv->pDriverInfo->ddxDrawableTableEntry); - } - - REGION_UNINIT(pScreen, ®); - } - - /* call lower wrapped functions */ - if(pDRIPriv->wrap.CopyWindow) { - /* unwrap */ - pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; - - /* call lower layers */ - (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); - - /* rewrap */ - pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; - pScreen->CopyWindow = DRICopyWindow; - } -} - -static void -DRIGetSecs(long *secs, long *usecs) -{ - struct timeval tv; - - gettimeofday(&tv, NULL); - - *secs = tv.tv_sec; - *usecs = tv.tv_usec; -} - -static unsigned long -DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs, - unsigned long f_secs, unsigned long f_usecs) -{ - if (f_usecs < s_usecs) { - --f_secs; - f_usecs += 1000000; - } - return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000; -} - -static void -DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */) -{ - int count = 10000; -#if !defined(__alpha__) && !defined(__powerpc__) - char ret; -#else - int ret; -#endif - long s_secs, s_usecs; - long f_secs, f_usecs; - long msecs; - long prev = 0; - - DRIGetSecs(&s_secs, &s_usecs); - - do { - DRM_SPINLOCK_COUNT(lock, val, count, ret); - if (!ret) return; /* Got lock */ - DRIGetSecs(&f_secs, &f_usecs); - msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs); - if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */ - } while (msecs < timeout); - - /* Didn't get lock, so take it. The worst - that can happen is that there is some - garbage written to the wrong part of the - framebuffer that a refresh will repair. - That's undesirable, but better than - locking the server. This should be a - very rare event. */ - DRM_SPINLOCK_TAKE(lock, val); -} - -static void -DRILockTree(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if(!pDRIPriv) return; - - /* Restore the last known 3D context if the X context is hidden */ - if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { - (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, - DRI_2D_SYNC, - DRI_NO_CONTEXT, - NULL, - DRI_2D_CONTEXT, - pDRIPriv->partial3DContextStore); - } - - /* Call kernel to release lock */ - DRIUnlock(pScreen); - - /* Grab drawable spin lock: a time out between 10 and 30 seconds is - appropriate, since this should never time out except in the case of - client death while the lock is being held. The timeout must be - greater than any reasonable rendering time. */ - DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/ - - /* Call kernel flush outstanding buffers and relock */ - DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL); - - /* Switch back to our 2D context if the X context is hidden */ - if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { - /* hide X context by swapping 2D component here */ - (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, - DRI_3D_SYNC, - DRI_2D_CONTEXT, - pDRIPriv->partial3DContextStore, - DRI_2D_CONTEXT, - pDRIPriv->hiddenContextStore); - } -} - -int -DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) -{ - ScreenPtr pScreen = pParent->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - int returnValue = 1; /* always return 1, not checked by dix/window.c */ - - if(!pDRIPriv) return returnValue; - - /* call lower wrapped functions */ - if(pDRIPriv->wrap.ValidateTree) { - /* unwrap */ - pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; - - /* call lower layers */ - returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); - - /* rewrap */ - pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; - pScreen->ValidateTree = DRIValidateTree; - } - - return returnValue; -} - -void -DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) -{ - ScreenPtr pScreen; - DRIScreenPrivPtr pDRIPriv; - - if (pParent) { - pScreen = pParent->drawable.pScreen; - } else { - pScreen = pChild->drawable.pScreen; - } - if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return; - - if (pDRIPriv->wrap.PostValidateTree) { - /* unwrap */ - pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; - - /* call lower layers */ - (*pScreen->PostValidateTree)(pParent, pChild, kind); - - /* rewrap */ - pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; - pScreen->PostValidateTree = DRIPostValidateTree; - } -} - -void -DRIClipNotify(WindowPtr pWin, int dx, int dy) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIDrawablePrivPtr pDRIDrawablePriv; - - if(!pDRIPriv) return; - - if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { - int nrects = REGION_NUM_RECTS(&pWin->clipList); - - if(!pDRIPriv->windowsTouched) { - DRILockTree(pScreen); - pDRIPriv->windowsTouched = TRUE; - } - - if (nrects && !pDRIDrawablePriv->nrects) - DRIIncreaseNumberVisible(pScreen); - else if (!nrects && pDRIDrawablePriv->nrects) - DRIDecreaseNumberVisible(pScreen); - else - DRIDriverClipNotify(pScreen); - - pDRIDrawablePriv->nrects = nrects; - - pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp - = DRIDrawableValidationStamp++; - - drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable, - DRM_DRAWABLE_CLIPRECTS, - nrects, REGION_RECTS(&pWin->clipList)); - } - - /* call lower wrapped functions */ - if(pDRIPriv->wrap.ClipNotify) { - - /* unwrap */ - pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; - - /* call lower layers */ - (*pScreen->ClipNotify)(pWin, dx, dy); - - /* rewrap */ - pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; - pScreen->ClipNotify = DRIClipNotify; - } -} - -CARD32 -DRIGetDrawableIndex(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - CARD32 index; - - if (pDRIDrawablePriv) { - index = pDRIDrawablePriv->drawableIndex; - } - else { - index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry; - } - - return index; -} - -unsigned int -DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp; -} - - -void -DRIPrintDrawableLock(ScreenPtr pScreen, char *msg) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock); -} - -void -DRILock(ScreenPtr pScreen, int flags) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; - - if (!*pDRIPriv->pLockRefCount) { - DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags); - *pDRIPriv->pLockingContext = pDRIPriv->myContext; - } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[DRI] Locking deadlock.\n" - "\tAlready locked with context %d,\n" - "\ttrying to lock with context %d.\n", - pDRIPriv->pLockingContext, - pDRIPriv->myContext); - } - (*pDRIPriv->pLockRefCount)++; -} - -void -DRIUnlock(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; - - if (*pDRIPriv->pLockRefCount > 0) { - if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "[DRI] Unlocking inconsistency:\n" - "\tContext %d trying to unlock lock held by context %d\n", - pDRIPriv->pLockingContext, - pDRIPriv->myContext); - } - (*pDRIPriv->pLockRefCount)--; - } else { - DRIDrvMsg(pScreen->myNum, X_ERROR, - "DRIUnlock called when not locked.\n"); - return; - } - if (! *pDRIPriv->pLockRefCount) - DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext); -} - -void * -DRIGetSAREAPrivate(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - if (!pDRIPriv) return 0; - - return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec)); -} - -drm_context_t -DRIGetContext(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - if (!pDRIPriv) return 0; - - return pDRIPriv->myContext; -} - -void -DRIGetTexOffsetFuncs(ScreenPtr pScreen, - DRITexOffsetStartProcPtr *texOffsetStartFunc, - DRITexOffsetFinishProcPtr *texOffsetFinishFunc) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (!pDRIPriv) return; - - *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart; - *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish; -} - -/* This lets get at the unwrapped functions so that they can correctly - * call the lowerlevel functions, and choose whether they will be - * called at every level of recursion (eg in validatetree). - */ -DRIWrappedFuncsRec * -DRIGetWrappedFuncs(ScreenPtr pScreen) -{ - return &(DRI_SCREEN_PRIV(pScreen)->wrap); -} - -/* note that this returns the library version, not the protocol version */ -void -DRIQueryVersion(int *majorVersion, - int *minorVersion, - int *patchVersion) -{ - *majorVersion = DRIINFO_MAJOR_VERSION; - *minorVersion = DRIINFO_MINOR_VERSION; - *patchVersion = DRIINFO_PATCH_VERSION; -} - -static void -_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y) -{ - pDRIPriv->pSAREA->frame.x = x; - pDRIPriv->pSAREA->frame.y = y; - pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1; - pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1; -} - -void -DRIAdjustFrame(int scrnIndex, int x, int y, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[scrnIndex]; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - int px, py; - - if (!pDRIPriv || !pDRIPriv->pSAREA) { - DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n", - pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL); - return; - } - - if (pDRIPriv->fullscreen) { - /* Fix up frame */ - pScrn->frameX0 = pDRIPriv->pSAREA->frame.x; - pScrn->frameY0 = pDRIPriv->pSAREA->frame.y; - pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1; - pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1; - - /* Fix up cursor */ - miPointerGetPosition(inputInfo.pointer, &px, &py); - if (px < pScrn->frameX0) px = pScrn->frameX0; - if (px > pScrn->frameX1) px = pScrn->frameX1; - if (py < pScrn->frameY0) py = pScrn->frameY0; - if (py > pScrn->frameY1) py = pScrn->frameY1; - pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE); - return; - } - - if (pDRIPriv->wrap.AdjustFrame) { - /* unwrap */ - pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; - /* call lower layers */ - (*pScrn->AdjustFrame)(scrnIndex, x, y, flags); - /* rewrap */ - pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; - pScrn->AdjustFrame = DRIAdjustFrame; - } - - _DRIAdjustFrame(pScrn, pDRIPriv, x, y); -} - -/* - * DRIMoveBuffersHelper swaps the regions rects in place leaving you - * a region with the rects in the order that you need to blit them, - * but it is possibly (likely) an invalid region afterwards. If you - * need to use the region again for anything you have to call - * REGION_VALIDATE on it, or better yet, save a copy first. - */ - -void -DRIMoveBuffersHelper( - ScreenPtr pScreen, - int dx, - int dy, - int *xdir, - int *ydir, - RegionPtr reg -) -{ - BoxPtr extents, pbox, firstBox, lastBox; - BoxRec tmpBox; - int y, nbox; - - extents = REGION_EXTENTS(pScreen, reg); - nbox = REGION_NUM_RECTS(reg); - pbox = REGION_RECTS(reg); - - if((dy > 0) && (dy < (extents->y2 - extents->y1))) { - *ydir = -1; - if(nbox > 1) { - firstBox = pbox; - lastBox = pbox + nbox - 1; - while((unsigned long)firstBox < (unsigned long)lastBox) { - tmpBox = *firstBox; - *firstBox = *lastBox; - *lastBox = tmpBox; - firstBox++; - lastBox--; - } - } - } else *ydir = 1; - - if((dx > 0) && (dx < (extents->x2 - extents->x1))) { - *xdir = -1; - if(nbox > 1) { - firstBox = lastBox = pbox; - y = pbox->y1; - while(--nbox) { - pbox++; - if(pbox->y1 == y) lastBox++; - else { - while((unsigned long)firstBox < (unsigned long)lastBox) { - tmpBox = *firstBox; - *firstBox = *lastBox; - *lastBox = tmpBox; - firstBox++; - lastBox--; - } - - firstBox = lastBox = pbox; - y = pbox->y1; - } - } - while((unsigned long)firstBox < (unsigned long)lastBox) { - tmpBox = *firstBox; - *firstBox = *lastBox; - *lastBox = tmpBox; - firstBox++; - lastBox--; - } - } - } else *xdir = 1; - -} - -char * -DRICreatePCIBusID(const struct pci_device * dev) -{ - char *busID; - - busID = xalloc(20); - if (busID == NULL) - return NULL; - - snprintf(busID, 20, "pci:%04x:%02x:%02x.%d", dev->domain, dev->bus, - dev->dev, dev->func); - - return busID; -} - -static void drmSIGIOHandler(int interrupt, void *closure) -{ - unsigned long key; - void *value; - ssize_t count; - drm_ctx_t ctx; - typedef void (*_drmCallback)(int, void *, void *); - char buf[256]; - drm_context_t old; - drm_context_t new; - void *oldctx; - void *newctx; - char *pt; - drmHashEntry *entry; - void *hash_table; - - hash_table = drmGetHashTable(); - - if (!hash_table) return; - if (drmHashFirst(hash_table, &key, &value)) { - entry = value; - do { -#if 0 - fprintf(stderr, "Trying %d\n", entry->fd); -#endif - if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) { - buf[count] = '\0'; -#if 0 - fprintf(stderr, "Got %s\n", buf); -#endif - - for (pt = buf; *pt != ' '; ++pt); /* Find first space */ - ++pt; - old = strtol(pt, &pt, 0); - new = strtol(pt, NULL, 0); - oldctx = drmGetContextTag(entry->fd, old); - newctx = drmGetContextTag(entry->fd, new); -#if 0 - fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); -#endif - ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); - ctx.handle = new; - ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); - } - } while (drmHashNext(hash_table, &key, &value)); - } -} - - -int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) -{ - drmHashEntry *entry; - - entry = drmGetEntry(fd); - entry->f = f; - - return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); -} - -int drmRemoveSIGIOHandler(int fd) -{ - drmHashEntry *entry = drmGetEntry(fd); - - entry->f = NULL; - - return xf86RemoveSIGIOHandler(fd); -} +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Jens Owen + * Rickard E. (Rik) Faith + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include "xf86drm.h" +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#define _XF86DRI_SERVER_ +#include +#include "swaprep.h" +#include "xf86str.h" +#include "dri.h" +#include "sarea.h" +#include "dristruct.h" +#include "xf86.h" +#include "xf86drm.h" +#include "mi.h" +#include "mipointer.h" +#include "xf86_OSproc.h" +#include "inputstr.h" +#include "xf86VGAarbiter.h" + +#define PCI_BUS_NO_DOMAIN(bus) ((bus) & 0xffu) + +static int DRIEntPrivIndex = -1; +static int DRIScreenPrivKeyIndex; +static DevPrivateKey DRIScreenPrivKey = &DRIScreenPrivKeyIndex; +static int DRIWindowPrivKeyIndex; +static DevPrivateKey DRIWindowPrivKey = &DRIWindowPrivKeyIndex; +static unsigned long DRIGeneration = 0; +static unsigned int DRIDrawableValidationStamp = 0; + +static RESTYPE DRIDrawablePrivResType; +static RESTYPE DRIContextPrivResType; +static void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv); + +drmServerInfo DRIDRMServerInfo; + + /* Wrapper just like xf86DrvMsg, but + without the verbosity level checking. + This will make it easy to turn off some + messages later, based on verbosity + level. */ + +/* + * Since we're already referencing things from the XFree86 common layer in + * this file, we'd might as well just call xf86VDrvMsgVerb, and have + * consistent message formatting. The verbosity of these messages can be + * easily changed here. + */ +#define DRI_MSG_VERBOSITY 1 +static void +DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap); + va_end(ap); +} + + +static void +DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv) +{ + if (pDRIEntPriv->pLSAREA != NULL) { + drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize); + pDRIEntPriv->pLSAREA = NULL; + } + if (pDRIEntPriv->hLSAREA != 0) { + drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA); + } + if (pDRIEntPriv->drmFD >= 0) { + drmClose(pDRIEntPriv->drmFD); + pDRIEntPriv->drmFD = 0; + } +} + +int +DRIMasterFD(ScrnInfoPtr pScrn) +{ + return DRI_ENT_PRIV(pScrn)->drmFD; +} + +void * +DRIMasterSareaPointer(ScrnInfoPtr pScrn) +{ + return DRI_ENT_PRIV(pScrn)->pLSAREA; +} + +drm_handle_t +DRIMasterSareaHandle(ScrnInfoPtr pScrn) +{ + return DRI_ENT_PRIV(pScrn)->hLSAREA; +} + + +Bool +DRIOpenDRMMaster(ScrnInfoPtr pScrn, + unsigned long sAreaSize, + const char *busID, + const char *drmDriverName) +{ + drmSetVersion saveSv, sv; + Bool drmWasAvailable; + DRIEntPrivPtr pDRIEntPriv; + DRIEntPrivRec tmp; + drmVersionPtr drmlibv; + int drmlibmajor, drmlibminor; + const char *openBusID; + int count; + int err; + + if (DRIEntPrivIndex == -1) + DRIEntPrivIndex = xf86AllocateEntityPrivateIndex(); + + pDRIEntPriv = DRI_ENT_PRIV(pScrn); + + if (pDRIEntPriv && pDRIEntPriv->drmFD != -1) + return TRUE; + + drmWasAvailable = drmAvailable(); + + memset(&tmp, 0, sizeof(tmp)); + + /* Check the DRM lib version. + * drmGetLibVersion was not supported in version 1.0, so check for + * symbol first to avoid possible crash or hang. + */ + + drmlibmajor = 1; + drmlibminor = 0; + if (xf86LoaderCheckSymbol("drmGetLibVersion")) { + drmlibv = drmGetLibVersion(-1); + if (drmlibv != NULL) { + drmlibmajor = drmlibv->version_major; + drmlibminor = drmlibv->version_minor; + drmFreeVersion(drmlibv); + } + } + + /* Check if the libdrm can handle falling back to loading based on name + * if a busid string is passed. + */ + openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL; + + tmp.drmFD = -1; + sv.drm_di_major = 1; + sv.drm_di_minor = 1; + sv.drm_dd_major = -1; + + saveSv = sv; + count = 10; + while (count--) { + tmp.drmFD = drmOpen(drmDriverName, openBusID); + + if (tmp.drmFD < 0) { + DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n"); + goto out_err; + } + + err = drmSetInterfaceVersion(tmp.drmFD, &sv); + + if (err != -EPERM) + break; + + sv = saveSv; + drmClose(tmp.drmFD); + tmp.drmFD = -1; + usleep(100000); + } + + if (tmp.drmFD <= 0) { + DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n"); + goto out_err; + } + + if (!drmWasAvailable) { + DRIDrvMsg(-1, X_INFO, + "[drm] loaded kernel module for \"%s\" driver.\n", + drmDriverName); + } + + if (err != 0) { + sv.drm_di_major = 1; + sv.drm_di_minor = 0; + } + + DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n", + sv.drm_di_major, sv.drm_di_minor); + + if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1) + err = 0; + else + err = drmSetBusid(tmp.drmFD, busID); + + if (err) { + DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n"); + goto out_err; + } + + /* + * Create a lock-containing sarea. + */ + + if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM, + DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) { + DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n"); + tmp.hLSAREA = 0; + goto out_err; + } + + if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize, + (drmAddressPtr)(&tmp.pLSAREA)) < 0) { + DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n"); + tmp.pLSAREA = NULL; + goto out_err; + } + + memset(tmp.pLSAREA, 0, sAreaSize); + + /* + * Reserved contexts are handled by the first opened screen. + */ + + tmp.resOwner = NULL; + + if (!pDRIEntPriv) + pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1); + + if (!pDRIEntPriv) { + DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for " + "DRM device.\n"); + goto out_err; + } + *pDRIEntPriv = tmp; + xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr = + pDRIEntPriv; + + DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n"); + return TRUE; + + out_err: + + DRIOpenDRMCleanup(&tmp); + return FALSE; +} + +static void +DRIClipNotifyAllDrawables(ScreenPtr pScreen); + +static void +dri_crtc_notify(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIClipNotifyAllDrawables(pScreen); + xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); + xf86_crtc_notify(pScreen); + pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, dri_crtc_notify); +} + +Bool +DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD) +{ + DRIScreenPrivPtr pDRIPriv; + drm_context_t * reserved; + int reserved_count; + int i; + DRIEntPrivPtr pDRIEntPriv; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DRIContextFlags flags = 0; + DRIContextPrivPtr pDRIContextPriv; + + /* If the DRI extension is disabled, do not initialize the DRI */ + if (noXFree86DRIExtension) { + DRIDrvMsg(pScreen->myNum, X_WARNING, + "Direct rendering has been disabled.\n"); + return FALSE; + } + + if (!xf86VGAarbiterAllowDRI(pScreen)) { + DRIDrvMsg(pScreen->myNum, X_WARNING, + "Direct rendering is not supported when VGA arb is necessary for the device\n"); + return FALSE; + } + +#ifdef PANORAMIX + /* + * If Xinerama is on, don't allow DRI to initialise. It won't be usable + * anyway. + */ + if (!noPanoramiXExtension) { + DRIDrvMsg(pScreen->myNum, X_WARNING, + "Direct rendering is not supported when Xinerama is enabled\n"); + return FALSE; + } +#endif + + if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize, + pDRIInfo->busIdString, + pDRIInfo->drmDriverName)) + return FALSE; + + pDRIEntPriv = DRI_ENT_PRIV(pScrn); + + if (DRIGeneration != serverGeneration) + DRIGeneration = serverGeneration; + + pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); + if (!pDRIPriv) { + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); + pDRIPriv->drmFD = pDRIEntPriv->drmFD; + pDRIPriv->directRenderingSupport = TRUE; + pDRIPriv->pDriverInfo = pDRIInfo; + pDRIPriv->nrWindows = 0; + pDRIPriv->nrWindowsVisible = 0; + pDRIPriv->fullscreen = NULL; + + pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx; + pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv; + + pDRIPriv->grabbedDRILock = FALSE; + pDRIPriv->drmSIGIOHandlerInstalled = FALSE; + *pDRMFD = pDRIPriv->drmFD; + + if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) { + + if (drmAddMap( pDRIPriv->drmFD, + 0, + pDRIPriv->pDriverInfo->SAREASize, + DRM_SHM, + 0, + &pDRIPriv->hSAREA) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmAddMap failed\n"); + return FALSE; + } + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] added %d byte SAREA at %p\n", + pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA); + + /* Backwards compat. */ + if (drmMap( pDRIPriv->drmFD, + pDRIPriv->hSAREA, + pDRIPriv->pDriverInfo->SAREASize, + (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmMap failed\n"); + return FALSE; + } + DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n", + pDRIPriv->hSAREA, pDRIPriv->pSAREA); + memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize); + } else { + DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock " + "SAREA also for drawables.\n"); + pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA; + pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA; + pDRIEntPriv->sAreaGrabbed = TRUE; + } + + pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA; + pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA; + + if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer) + { + if (drmAddMap( pDRIPriv->drmFD, + (drm_handle_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress, + pDRIPriv->pDriverInfo->frameBufferSize, + DRM_FRAME_BUFFER, + 0, + &pDRIPriv->pDriverInfo->hFrameBuffer) < 0) + { + pDRIPriv->directRenderingSupport = FALSE; + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize); + drmClose(pDRIPriv->drmFD); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] drmAddMap failed\n"); + return FALSE; + } + DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n", + pDRIPriv->pDriverInfo->hFrameBuffer); + } else { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] framebuffer mapped by ddx driver\n"); + } + + if (pDRIEntPriv->resOwner == NULL) { + pDRIEntPriv->resOwner = pScreen; + + /* Add tags for reserved contexts */ + if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, + &reserved_count))) { + int i; + void *tag; + + for (i = 0; i < reserved_count; i++) { + tag = DRICreateContextPrivFromHandle(pScreen, + reserved[i], + DRI_CONTEXT_RESERVED); + drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag); + } + drmFreeReservedContextList(reserved); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] added %d reserved context%s for kernel\n", + reserved_count, reserved_count > 1 ? "s" : ""); + } + } + + /* validate max drawable table entry set by driver */ + if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) || + (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "Invalid max drawable table size set by driver: %d\n", + pDRIPriv->pDriverInfo->maxDrawableTableEntry); + } + + /* Initialize drawable tables (screen private and SAREA) */ + for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { + pDRIPriv->DRIDrawables[i] = NULL; + pDRIPriv->pSAREA->drawableTable[i].stamp = 0; + pDRIPriv->pSAREA->drawableTable[i].flags = 0; + } + + pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount; + pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext; + + if (!pDRIEntPriv->keepFDOpen) + pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen; + + pDRIEntPriv->refCount++; + + /* Set up flags for DRICreateContextPriv */ + switch (pDRIInfo->driverSwapMethod) { + case DRI_KERNEL_SWAP: + flags = DRI_CONTEXT_2DONLY; + break; + case DRI_HIDE_X_CONTEXT: + flags = DRI_CONTEXT_PRESERVED; + break; + } + + if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, + &pDRIPriv->myContext, + flags))) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to create server context\n"); + return FALSE; + } + pDRIPriv->myContextPriv = pDRIContextPriv; + + DRIDrvMsg(pScreen->myNum, X_INFO, + "X context handle = %p\n", pDRIPriv->myContext); + + /* Now that we have created the X server's context, we can grab the + * hardware lock for the X server. + */ + DRILock(pScreen, 0); + pDRIPriv->grabbedDRILock = TRUE; + + /* pointers so that we can prevent memory leaks later */ + pDRIPriv->hiddenContextStore = NULL; + pDRIPriv->partial3DContextStore = NULL; + + switch(pDRIInfo->driverSwapMethod) { + case DRI_HIDE_X_CONTEXT: + /* Server will handle 3D swaps, and hide 2D swaps from kernel. + * Register server context as a preserved context. + */ + + /* allocate memory for hidden context store */ + pDRIPriv->hiddenContextStore + = (void *)calloc(1, pDRIInfo->contextSize); + if (!pDRIPriv->hiddenContextStore) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to allocate hidden context\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + + /* allocate memory for partial 3D context store */ + pDRIPriv->partial3DContextStore + = (void *)calloc(1, pDRIInfo->contextSize); + if (!pDRIPriv->partial3DContextStore) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] failed to allocate partial 3D context\n"); + free(pDRIPriv->hiddenContextStore); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + + /* save initial context store */ + if (pDRIInfo->SwapContext) { + (*pDRIInfo->SwapContext)( + pScreen, + DRI_NO_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore, + DRI_NO_CONTEXT, + NULL); + } + /* fall through */ + + case DRI_SERVER_SWAP: + /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT + * setup signal handler for receiving swap requests from kernel + */ + if (!(pDRIPriv->drmSIGIOHandlerInstalled = + drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to setup DRM signal handler\n"); + if (pDRIPriv->hiddenContextStore) + free(pDRIPriv->hiddenContextStore); + if (pDRIPriv->partial3DContextStore) + free(pDRIPriv->partial3DContextStore); + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } else { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] installed DRM signal handler\n"); + } + + default: + break; + } + + return TRUE; +} + +Bool +DRIFinishScreenInit(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + /* Wrap DRI support */ + if (pDRIInfo->wrap.ValidateTree) { + pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; + pScreen->ValidateTree = pDRIInfo->wrap.ValidateTree; + } + if (pDRIInfo->wrap.PostValidateTree) { + pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = pDRIInfo->wrap.PostValidateTree; + } + if (pDRIInfo->wrap.WindowExposures) { + pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures; + } + + pDRIPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DRIDestroyWindow; + + pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, + dri_crtc_notify); + + if (pDRIInfo->wrap.CopyWindow) { + pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow; + } + if (pDRIInfo->wrap.ClipNotify) { + pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify; + } + if (pDRIInfo->wrap.AdjustFrame) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; + pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame; + } + pDRIPriv->wrapped = TRUE; + + DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n"); + + return TRUE; +} + +void +DRICloseScreen(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo; + drm_context_t * reserved; + int reserved_count; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn); + Bool closeMaster; + + if (pDRIPriv) { + + pDRIInfo = pDRIPriv->pDriverInfo; + + if (pDRIPriv->wrapped) { + /* Unwrap DRI Functions */ + if (pDRIInfo->wrap.ValidateTree) { + pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; + pDRIPriv->wrap.ValidateTree = NULL; + } + if (pDRIInfo->wrap.PostValidateTree) { + pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; + pDRIPriv->wrap.PostValidateTree = NULL; + } + if (pDRIInfo->wrap.WindowExposures) { + pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; + pDRIPriv->wrap.WindowExposures = NULL; + } + if (pDRIPriv->DestroyWindow) { + pScreen->DestroyWindow = pDRIPriv->DestroyWindow; + pDRIPriv->DestroyWindow = NULL; + } + + xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify); + + if (pDRIInfo->wrap.CopyWindow) { + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + pDRIPriv->wrap.CopyWindow = NULL; + } + if (pDRIInfo->wrap.ClipNotify) { + pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; + pDRIPriv->wrap.ClipNotify = NULL; + } + if (pDRIInfo->wrap.AdjustFrame) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; + pDRIPriv->wrap.AdjustFrame = NULL; + } + + pDRIPriv->wrapped = FALSE; + } + + if (pDRIPriv->drmSIGIOHandlerInstalled) { + if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to remove DRM signal handler\n"); + } + } + + if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) { + DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv); + } + + if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "failed to destroy server context\n"); + } + + /* Remove tags for reserved contexts */ + if (pDRIEntPriv->resOwner == pScreen) { + pDRIEntPriv->resOwner = NULL; + + if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD, + &reserved_count))) { + int i; + + for (i = 0; i < reserved_count; i++) { + DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD, + reserved[i])); + } + drmFreeReservedContextList(reserved); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] removed %d reserved context%s for kernel\n", + reserved_count, reserved_count > 1 ? "s" : ""); + } + } + + /* Make sure signals get unblocked etc. */ + drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext); + pDRIPriv->pLockRefCount = NULL; + closeMaster = (--pDRIEntPriv->refCount == 0) && + !pDRIEntPriv->keepFDOpen; + if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] unmapping %d bytes of SAREA %p at %p\n", + pDRIInfo->SAREASize, + pDRIPriv->hSAREA, + pDRIPriv->pSAREA); + if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] unable to unmap %d bytes" + " of SAREA %p at %p\n", + pDRIInfo->SAREASize, + pDRIPriv->hSAREA, + pDRIPriv->pSAREA); + } + } else { + pDRIEntPriv->sAreaGrabbed = FALSE; + } + + if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) { + drmClose(pDRIPriv->drmFD); + if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] Closed DRM master.\n"); + pDRIEntPriv->drmFD = -1; + } + } + + free(pDRIPriv); + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + } +} + +#define DRM_MSG_VERBOSITY 3 + +static int dri_drm_debug_print(const char *format, va_list ap) +{ + xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap); + return 0; +} + +static void dri_drm_get_perms(gid_t *group, mode_t *mode) +{ + *group = xf86ConfigDRI.group; + *mode = xf86ConfigDRI.mode; +} + +drmServerInfo DRIDRMServerInfo = { + dri_drm_debug_print, + xf86LoadKernelModule, + dri_drm_get_perms, +}; + +Bool +DRIExtensionInit(void) +{ + if (!DRIScreenPrivKey || DRIGeneration != serverGeneration) { + return FALSE; + } + + DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, + "DRIDrawable"); + DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete, + "DRIContext"); + + if (!DRIDrawablePrivResType || !DRIContextPrivResType) + return FALSE; + + RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL); + + return TRUE; +} + +void +DRIReset(void) +{ + /* + * This stub routine is called when the X Server recycles, resources + * allocated by DRIExtensionInit need to be managed here. + * + * Currently this routine is a stub because all the interesting resources + * are managed via the screen init process. + */ +} + +Bool +DRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool* isCapable) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv) + *isCapable = pDRIPriv->directRenderingSupport; + else + *isCapable = FALSE; + + return TRUE; +} + +Bool +DRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *hSAREA = pDRIPriv->hSAREA; + *busIdString = pDRIPriv->pDriverInfo->busIdString; + + return TRUE; +} + +Bool +DRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; + return TRUE; +} + +Bool +DRICloseConnection(ScreenPtr pScreen) +{ + return TRUE; +} + +Bool +DRIGetClientDriverName(ScreenPtr pScreen, + int *ddxDriverMajorVersion, + int *ddxDriverMinorVersion, + int *ddxDriverPatchVersion, + char **clientDriverName) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion; + *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion; + *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion; + *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName; + + return TRUE; +} + +/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper + functions that layer on drmCreateContext and drmAddContextTag. + + DRICreateContextPriv always creates a kernel drm_context_t and then calls + DRICreateContextPrivFromHandle to create a DRIContextPriv structure for + DRI tracking. For the SIGIO handler, the drm_context_t is associated with + DRIContextPrivPtr. Any special flags are stored in the DRIContextPriv + area and are passed to the kernel (if necessary). + + DRICreateContextPriv returns a pointer to newly allocated + DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */ + +DRIContextPrivPtr +DRICreateContextPriv(ScreenPtr pScreen, + drm_context_t * pHWContext, + DRIContextFlags flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) { + return NULL; + } + + return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags); +} + +DRIContextPrivPtr +DRICreateContextPrivFromHandle(ScreenPtr pScreen, + drm_context_t hHWContext, + DRIContextFlags flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv; + int contextPrivSize; + + contextPrivSize = sizeof(DRIContextPrivRec) + + pDRIPriv->pDriverInfo->contextSize; + if (!(pDRIContextPriv = calloc(1, contextPrivSize))) { + return NULL; + } + pDRIContextPriv->pContextStore = (void *)(pDRIContextPriv + 1); + + drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv); + + pDRIContextPriv->hwContext = hHWContext; + pDRIContextPriv->pScreen = pScreen; + pDRIContextPriv->flags = flags; + pDRIContextPriv->valid3D = FALSE; + + if (flags & DRI_CONTEXT_2DONLY) { + if (drmSetContextFlags(pDRIPriv->drmFD, + hHWContext, + DRM_CONTEXT_2DONLY)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to set 2D context flag\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return NULL; + } + } + if (flags & DRI_CONTEXT_PRESERVED) { + if (drmSetContextFlags(pDRIPriv->drmFD, + hHWContext, + DRM_CONTEXT_PRESERVED)) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[drm] failed to set preserved flag\n"); + DRIDestroyContextPriv(pDRIContextPriv); + return NULL; + } + } + return pDRIContextPriv; +} + +Bool +DRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv) +{ + DRIScreenPrivPtr pDRIPriv; + + if (!pDRIContextPriv) return TRUE; + + pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); + + if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) { + /* Don't delete reserved contexts from + kernel area -- the kernel manages its + reserved contexts itself. */ + if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext)) + return FALSE; + } + + /* Remove the tag last to prevent a race + condition where the context has pending + buffers. The context can't be re-used + while in this thread, but buffers can be + dispatched asynchronously. */ + drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext); + free(pDRIContextPriv); + return TRUE; +} + +static Bool +DRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv; + void *contextStore; + + if (!(pDRIContextPriv = + DRICreateContextPriv(pScreen, + &pDRIPriv->pSAREA->dummy_context, 0))) { + return FALSE; + } + + contextStore = DRIGetContextStore(pDRIContextPriv); + if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) { + if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL, + pDRIPriv->pSAREA->dummy_context, + NULL, + (DRIContextType)(long)contextStore)) { + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + } + + pDRIPriv->dummyCtxPriv = pDRIContextPriv; + return TRUE; +} + +static void +DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv; + void *contextStore; + + if (!pDRIContextPriv) return; + if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) { + contextStore = DRIGetContextStore(pDRIContextPriv); + pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, + pDRIContextPriv->hwContext, + (DRIContextType)(long)contextStore); + } + + DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv); + pDRIPriv->dummyCtxPriv = NULL; +} + +Bool +DRICreateContext(ScreenPtr pScreen, VisualPtr visual, + XID context, drm_context_t * pHWContext) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIContextPrivPtr pDRIContextPriv; + void *contextStore; + + if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) { + if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] Could not create dummy context\n"); + return FALSE; + } + } + + if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) { + return FALSE; + } + + contextStore = DRIGetContextStore(pDRIContextPriv); + if (pDRIPriv->pDriverInfo->CreateContext) { + if (!((*pDRIPriv->pDriverInfo->CreateContext)(pScreen, NULL, + *pHWContext, NULL, + (DRIContextType)(long)contextStore))) { + DRIDestroyContextPriv(pDRIContextPriv); + return FALSE; + } + } + + /* track this in case the client dies before cleanup */ + AddResource(context, DRIContextPrivResType, (pointer)pDRIContextPriv); + + return TRUE; +} + +Bool +DRIDestroyContext(ScreenPtr pScreen, XID context) +{ + FreeResourceByType(context, DRIContextPrivResType, FALSE); + + return TRUE; +} + +/* DRIContextPrivDelete is called by the resource manager. */ +Bool +DRIContextPrivDelete(pointer pResource, XID id) +{ + DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr)pResource; + DRIScreenPrivPtr pDRIPriv; + void *contextStore; + + pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen); + if (pDRIPriv->pDriverInfo->DestroyContext) { + contextStore = DRIGetContextStore(pDRIContextPriv); + pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen, + pDRIContextPriv->hwContext, + (DRIContextType)(long)contextStore); + } + return DRIDestroyContextPriv(pDRIContextPriv); +} + + +/* This walks the drawable timestamp array and invalidates all of them + * in the case of transition from private to shared backbuffers. It's + * not necessary for correctness, because DRIClipNotify gets called in + * time to prevent any conflict, but the transition from + * shared->private is sometimes missed if we don't do this. + */ +static void +DRIClipNotifyAllDrawables(ScreenPtr pScreen) +{ + int i; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + for( i=0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) { + pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++; + } +} + + +static void +DRITransitionToSharedBuffers(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionSingleToMulti3D) + pDRIInfo->TransitionSingleToMulti3D( pScreen ); +} + + +static void +DRITransitionToPrivateBuffers(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionMultiToSingle3D) + pDRIInfo->TransitionMultiToSingle3D( pScreen ); +} + + +static void +DRITransitionTo3d(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionTo3d) + pDRIInfo->TransitionTo3d( pScreen ); +} + +static void +DRITransitionTo2d(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + DRIClipNotifyAllDrawables( pScreen ); + + if (pDRIInfo->TransitionTo2d) + pDRIInfo->TransitionTo2d( pScreen ); +} + + +static int +DRIDCNTreeTraversal(WindowPtr pWin, pointer data) +{ + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if (pDRIDrawablePriv) { + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (REGION_NUM_RECTS(&pWin->clipList) > 0) { + WindowPtr *pDRIWindows = (WindowPtr*)data; + int i = 0; + + while (pDRIWindows[i]) + i++; + + pDRIWindows[i] = pWin; + + pDRIPriv->nrWalked++; + } + + if (pDRIPriv->nrWindows == pDRIPriv->nrWalked) + return WT_STOPWALKING; + } + + return WT_WALKCHILDREN; +} + +static void +DRIDriverClipNotify(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv->pDriverInfo->ClipNotify) { + WindowPtr *pDRIWindows = calloc(sizeof(WindowPtr), pDRIPriv->nrWindows); + DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo; + + if (pDRIPriv->nrWindows > 0) { + pDRIPriv->nrWalked = 0; + TraverseTree(WindowTable[pScreen->myNum], DRIDCNTreeTraversal, + (pointer)pDRIWindows); + } + + pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows); + + free(pDRIWindows); + } +} + +static void +DRIIncreaseNumberVisible(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + switch (++pDRIPriv->nrWindowsVisible) { + case 1: + DRITransitionTo3d( pScreen ); + break; + case 2: + DRITransitionToSharedBuffers( pScreen ); + break; + default: + break; + } + + DRIDriverClipNotify(pScreen); +} + +static void +DRIDecreaseNumberVisible(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + switch (--pDRIPriv->nrWindowsVisible) { + case 0: + DRITransitionTo2d( pScreen ); + break; + case 1: + DRITransitionToPrivateBuffers( pScreen ); + break; + default: + break; + } + + DRIDriverClipNotify(pScreen); +} + +Bool +DRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable, + drm_drawable_t * hHWDrawable) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv; + WindowPtr pWin; + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + pDRIDrawablePriv->refCount++; + + if (!pDRIDrawablePriv->hwDrawable) { + drmCreateDrawable(pDRIPriv->drmFD, &pDRIDrawablePriv->hwDrawable); + } + } + else { + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = malloc(sizeof(DRIDrawablePrivRec)))) { + return FALSE; + } + + /* Only create a drm_drawable_t once */ + if (drmCreateDrawable(pDRIPriv->drmFD, + &pDRIDrawablePriv->hwDrawable)) { + free(pDRIDrawablePriv); + return FALSE; + } + + /* add it to the list of DRI drawables for this screen */ + pDRIDrawablePriv->pScreen = pScreen; + pDRIDrawablePriv->refCount = 1; + pDRIDrawablePriv->drawableIndex = -1; + pDRIDrawablePriv->nrects = REGION_NUM_RECTS(&pWin->clipList); + + /* save private off of preallocated index */ + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, + pDRIDrawablePriv); + pDRIPriv->nrWindows++; + + if (pDRIDrawablePriv->nrects) + DRIIncreaseNumberVisible(pScreen); + } + + /* track this in case the client dies */ + AddResource(FakeClientID(client->index), DRIDrawablePrivResType, + (pointer)(intptr_t)pDrawable->id); + + if (pDRIDrawablePriv->hwDrawable) { + drmUpdateDrawableInfo(pDRIPriv->drmFD, + pDRIDrawablePriv->hwDrawable, + DRM_DRAWABLE_CLIPRECTS, + REGION_NUM_RECTS(&pWin->clipList), + REGION_RECTS(&pWin->clipList)); + *hHWDrawable = pDRIDrawablePriv->hwDrawable; + } + } + else if (pDrawable->type != DRAWABLE_PIXMAP) { /* PBuffer */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +static void +DRIDrawablePrivDestroy(WindowPtr pWin) +{ + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + ScreenPtr pScreen; + DRIScreenPrivPtr pDRIPriv; + + if (!pDRIDrawablePriv) + return; + + pScreen = pWin->drawable.pScreen; + pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIDrawablePriv->drawableIndex != -1) { + /* bump stamp to force outstanding 3D requests to resync */ + pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp + = DRIDrawableValidationStamp++; + + /* release drawable table entry */ + pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; + } + + pDRIPriv->nrWindows--; + + if (pDRIDrawablePriv->nrects) + DRIDecreaseNumberVisible(pScreen); + + drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable); + + free(pDRIDrawablePriv); + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); +} + +static Bool +DRIDestroyDrawableCB(pointer value, XID id, pointer data) +{ + if (value == data) { + /* This calls back DRIDrawablePrivDelete which frees private area */ + FreeResourceByType(id, DRIDrawablePrivResType, FALSE); + + return TRUE; + } + + return FALSE; +} + +Bool +DRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable) +{ + if (pDrawable->type == DRAWABLE_WINDOW) { + LookupClientResourceComplex(client, DRIDrawablePrivResType, + DRIDestroyDrawableCB, + (pointer)(intptr_t)pDrawable->id); + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +Bool +DRIDrawablePrivDelete(pointer pResource, XID id) +{ + WindowPtr pWin; + int rc; + + /* For DRIDrawablePrivResType, the XID is the client's fake ID. The + * important XID is the value in pResource. */ + id = (XID)(intptr_t)pResource; + rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess); + + if (rc == Success) { + DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if (!pDRIDrwPriv) + return FALSE; + + if (--pDRIDrwPriv->refCount == 0) + DRIDrawablePrivDestroy(pWin); + + return TRUE; + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } +} + +Bool +DRIGetDrawableInfo(ScreenPtr pScreen, + DrawablePtr pDrawable, + unsigned int* index, + unsigned int* stamp, + int* X, + int* Y, + int* W, + int* H, + int* numClipRects, + drm_clip_rect_t ** pClipRects, + int* backX, + int* backY, + int* numBackClipRects, + drm_clip_rect_t ** pBackClipRects) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv; + WindowPtr pWin, pOldWin; + int i; + +#if 0 + printf("maxDrawableTableEntry = %d\n", pDRIPriv->pDriverInfo->maxDrawableTableEntry); +#endif + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + + /* Manage drawable table */ + if (pDRIDrawablePriv->drawableIndex == -1) { /* load SAREA table */ + + /* Search table for empty entry */ + i = 0; + while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) { + if (!(pDRIPriv->DRIDrawables[i])) { + pDRIPriv->DRIDrawables[i] = pDrawable; + pDRIDrawablePriv->drawableIndex = i; + pDRIPriv->pSAREA->drawableTable[i].stamp = + DRIDrawableValidationStamp++; + break; + } + i++; + } + + /* Search table for oldest entry */ + if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) { + unsigned int oldestStamp = ~0; + int oldestIndex = 0; + i = pDRIPriv->pDriverInfo->maxDrawableTableEntry; + while (i--) { + if (pDRIPriv->pSAREA->drawableTable[i].stamp < + oldestStamp) { + oldestIndex = i; + oldestStamp = + pDRIPriv->pSAREA->drawableTable[i].stamp; + } + } + pDRIDrawablePriv->drawableIndex = oldestIndex; + + /* release oldest drawable table entry */ + pOldWin = (WindowPtr)pDRIPriv->DRIDrawables[oldestIndex]; + pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin); + pOldDrawPriv->drawableIndex = -1; + + /* claim drawable table entry */ + pDRIPriv->DRIDrawables[oldestIndex] = pDrawable; + + /* validate SAREA entry */ + pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp = + DRIDrawableValidationStamp++; + + /* check for stamp wrap around */ + if (oldestStamp > DRIDrawableValidationStamp) { + + /* walk SAREA table and invalidate all drawables */ + for( i=0; + i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; + i++) { + pDRIPriv->pSAREA->drawableTable[i].stamp = + DRIDrawableValidationStamp++; + } + } + } + + /* If the driver wants to be notified when the index is + * set for a drawable, let it know now. + */ + if (pDRIPriv->pDriverInfo->SetDrawableIndex) + pDRIPriv->pDriverInfo->SetDrawableIndex(pWin, + pDRIDrawablePriv->drawableIndex); + + /* reinit drawable ID if window is visible */ + if ((pWin->viewable) && + (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) + { + (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, + &pWin->clipList, pDRIDrawablePriv->drawableIndex); + } + } + + *index = pDRIDrawablePriv->drawableIndex; + *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp; + *X = (int)(pWin->drawable.x); + *Y = (int)(pWin->drawable.y); +#if 0 + *W = (int)(pWin->winSize.extents.x2 - pWin->winSize.extents.x1); + *H = (int)(pWin->winSize.extents.y2 - pWin->winSize.extents.y1); +#endif + *W = (int)(pWin->drawable.width); + *H = (int)(pWin->drawable.height); + *numClipRects = REGION_NUM_RECTS(&pWin->clipList); + *pClipRects = (drm_clip_rect_t *)REGION_RECTS(&pWin->clipList); + + if (!*numClipRects && pDRIPriv->fullscreen) { + /* use fake full-screen clip rect */ + pDRIPriv->fullscreen_rect.x1 = *X; + pDRIPriv->fullscreen_rect.y1 = *Y; + pDRIPriv->fullscreen_rect.x2 = *X + *W; + pDRIPriv->fullscreen_rect.y2 = *Y + *H; + + *numClipRects = 1; + *pClipRects = &pDRIPriv->fullscreen_rect; + } + + *backX = *X; + *backY = *Y; + + if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) { + /* Use a single cliprect. */ + + int x0 = *X; + int y0 = *Y; + int x1 = x0 + *W; + int y1 = y0 + *H; + + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > pScreen->width) x1 = pScreen->width; + if (y1 > pScreen->height) y1 = pScreen->height; + + if (y0 >= y1 || x0 >= x1) { + *numBackClipRects = 0; + *pBackClipRects = NULL; + } else { + pDRIPriv->private_buffer_rect.x1 = x0; + pDRIPriv->private_buffer_rect.y1 = y0; + pDRIPriv->private_buffer_rect.x2 = x1; + pDRIPriv->private_buffer_rect.y2 = y1; + + *numBackClipRects = 1; + *pBackClipRects = &(pDRIPriv->private_buffer_rect); + } + } else { + /* Use the frontbuffer cliprects for back buffers. */ + *numBackClipRects = 0; + *pBackClipRects = 0; + } + } + else { + /* Not a DRIDrawable */ + return FALSE; + } + } + else { /* pixmap (or for GLX 1.3, a PBuffer) */ + /* NOT_DONE */ + return FALSE; + } + + return TRUE; +} + +Bool +DRIGetDeviceInfo(ScreenPtr pScreen, + drm_handle_t * hFrameBuffer, + int* fbOrigin, + int* fbSize, + int* fbStride, + int* devPrivateSize, + void** pDevPrivate) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + *hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer; + *fbOrigin = 0; + *fbSize = pDRIPriv->pDriverInfo->frameBufferSize; + *fbStride = pDRIPriv->pDriverInfo->frameBufferStride; + *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize; + *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate; + + return TRUE; +} + +DRIInfoPtr +DRICreateInfoRec(void) +{ + DRIInfoPtr inforec = (DRIInfoPtr)calloc(1, sizeof(DRIInfoRec)); + if (!inforec) return NULL; + + /* Initialize defaults */ + inforec->busIdString = NULL; + + /* Wrapped function defaults */ + inforec->wrap.WakeupHandler = DRIDoWakeupHandler; + inforec->wrap.BlockHandler = DRIDoBlockHandler; + inforec->wrap.WindowExposures = DRIWindowExposures; + inforec->wrap.CopyWindow = DRICopyWindow; + inforec->wrap.ValidateTree = DRIValidateTree; + inforec->wrap.PostValidateTree = DRIPostValidateTree; + inforec->wrap.ClipNotify = DRIClipNotify; + inforec->wrap.AdjustFrame = DRIAdjustFrame; + + inforec->TransitionTo2d = 0; + inforec->TransitionTo3d = 0; + inforec->SetDrawableIndex = 0; + + return inforec; +} + +void +DRIDestroyInfoRec(DRIInfoPtr DRIInfo) +{ + if (DRIInfo->busIdString) free(DRIInfo->busIdString); + free((char*)DRIInfo); +} + + +void +DRIWakeupHandler(pointer wakeupData, int result, pointer pReadmask) +{ + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && + pDRIPriv->pDriverInfo->wrap.WakeupHandler) + (*pDRIPriv->pDriverInfo->wrap.WakeupHandler)(i, wakeupData, + result, pReadmask); + } +} + +void +DRIBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +{ + int i; + + for (i = 0; i < screenInfo.numScreens; i++) { + ScreenPtr pScreen = screenInfo.screens[i]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && + pDRIPriv->pDriverInfo->wrap.BlockHandler) + (*pDRIPriv->pDriverInfo->wrap.BlockHandler)(i, blockData, + pTimeout, pReadmask); + } +} + +void +DRIDoWakeupHandler(int screenNum, pointer wakeupData, + unsigned long result, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + DRILock(pScreen, 0); + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_3D_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore); + } +} + +void +DRIDoBlockHandler(int screenNum, pointer blockData, + pointer pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_NO_CONTEXT, + NULL, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore); + } + + if (pDRIPriv->windowsTouched) + DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1); + pDRIPriv->windowsTouched = FALSE; + + DRIUnlock(pScreen); +} + +void +DRISwapContext(int drmFD, void *oldctx, void *newctx) +{ + DRIContextPrivPtr oldContext = (DRIContextPrivPtr)oldctx; + DRIContextPrivPtr newContext = (DRIContextPrivPtr)newctx; + ScreenPtr pScreen = newContext->pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + void* oldContextStore = NULL; + DRIContextType oldContextType; + void* newContextStore = NULL; + DRIContextType newContextType; + DRISyncType syncType; +#ifdef DEBUG + static int count = 0; + + if (!newContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] Context Switch Error: oldContext=%x, newContext=%x\n", + oldContext, newContext); + return; + } + + /* usefull for debugging, just print out after n context switches */ + if (!count || !(count % 1)) { + DRIDrvMsg(pScreen->myNum, X_INFO, + "[DRI] Context switch %5d from %p/0x%08x (%d)\n", + count, + oldContext, + oldContext ? oldContext->flags : 0, + oldContext ? oldContext->hwContext : -1); + DRIDrvMsg(pScreen->myNum, X_INFO, + "[DRI] Context switch %5d to %p/0x%08x (%d)\n", + count, + newContext, + newContext ? newContext->flags : 0, + newContext ? newContext->hwContext : -1); + } + ++count; +#endif + + if (!pDRIPriv->pDriverInfo->SwapContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] DDX driver missing context swap call back\n"); + return; + } + + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + + /* only 3D contexts are swapped in this case */ + if (oldContext) { + oldContextStore = DRIGetContextStore(oldContext); + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + } else { + oldContextType = DRI_NO_CONTEXT; + } + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_3D_SYNC; + } + else /* default: driverSwapMethod == DRI_SERVER_SWAP */ { + + /* optimize 2D context swaps */ + + if (newContext->flags & DRI_CONTEXT_2DONLY) { + /* go from 3D context to 2D context and only save 2D + * subset of 3D state + */ + oldContextStore = DRIGetContextStore(oldContext); + oldContextType = DRI_2D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + newContextType = DRI_2D_CONTEXT; + syncType = DRI_3D_SYNC; + pDRIPriv->lastPartial3DContext = oldContext; + } + else if (oldContext->flags & DRI_CONTEXT_2DONLY) { + if (pDRIPriv->lastPartial3DContext == newContext) { + /* go from 2D context back to previous 3D context and + * only restore 2D subset of previous 3D state + */ + oldContextStore = DRIGetContextStore(oldContext); + oldContextType = DRI_2D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + newContextType = DRI_2D_CONTEXT; + syncType = DRI_2D_SYNC; + } + else { + /* go from 2D context to a different 3D context */ + + /* call DDX driver to do partial restore */ + oldContextStore = DRIGetContextStore(oldContext); + newContextStore = + DRIGetContextStore(pDRIPriv->lastPartial3DContext); + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_2D_CONTEXT, + oldContextStore, + DRI_2D_CONTEXT, + newContextStore); + + /* now setup for a complete 3D swap */ + oldContextStore = newContextStore; + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_NO_SYNC; + } + } + else { + /* now setup for a complete 3D swap */ + oldContextStore = newContextStore; + oldContext->valid3D = TRUE; + oldContextType = DRI_3D_CONTEXT; + newContextStore = DRIGetContextStore(newContext); + if ((newContext->valid3D) && + (newContext->hwContext != pDRIPriv->myContext)) { + newContextType = DRI_3D_CONTEXT; + } + else { + newContextType = DRI_2D_CONTEXT; + } + syncType = DRI_3D_SYNC; + } + } + + /* call DDX driver to perform the swap */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + syncType, + oldContextType, + oldContextStore, + newContextType, + newContextStore); +} + +void* +DRIGetContextStore(DRIContextPrivPtr context) +{ + return((void *)context->pContextStore); +} + +void +DRIWindowExposures(WindowPtr pWin, RegionPtr prgn, RegionPtr bsreg) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if(pDRIDrawablePriv) { + (*pDRIPriv->pDriverInfo->InitBuffers)(pWin, prgn, + pDRIDrawablePriv->drawableIndex); + } + + /* call lower wrapped functions */ + if (pDRIPriv && pDRIPriv->wrap.WindowExposures) { + + /* unwrap */ + pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; + + /* call lower layers */ + (*pScreen->WindowExposures)(pWin, prgn, bsreg); + + /* rewrap */ + pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = DRIWindowExposures; + } +} + + +static int +DRITreeTraversal(WindowPtr pWin, pointer data) +{ + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if(pDRIDrawablePriv) { + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(REGION_NUM_RECTS(&(pWin->clipList)) > 0) { + RegionPtr reg = (RegionPtr)data; + + REGION_UNION(pScreen, reg, reg, &(pWin->clipList)); + pDRIPriv->nrWalked++; + } + + if(pDRIPriv->nrWindows == pDRIPriv->nrWalked) + return WT_STOPWALKING; + } + return WT_WALKCHILDREN; +} + +Bool +DRIDestroyWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + Bool retval = TRUE; + + DRIDrawablePrivDestroy(pWin); + + /* call lower wrapped functions */ + if(pDRIPriv->DestroyWindow) { + /* unwrap */ + pScreen->DestroyWindow = pDRIPriv->DestroyWindow; + + /* call lower layers */ + retval = (*pScreen->DestroyWindow)(pWin); + + /* rewrap */ + pDRIPriv->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = DRIDestroyWindow; + } + + return retval; +} + +void +DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv) return; + + if(pDRIPriv->nrWindowsVisible > 0) { + RegionRec reg; + + REGION_NULL(pScreen, ®); + pDRIPriv->nrWalked = 0; + TraverseTree(pWin, DRITreeTraversal, (pointer)(®)); + + if(REGION_NOTEMPTY(pScreen, ®)) { + REGION_TRANSLATE(pScreen, ®, ptOldOrg.x - pWin->drawable.x, + ptOldOrg.y - pWin->drawable.y); + REGION_INTERSECT(pScreen, ®, ®, prgnSrc); + + /* The MoveBuffers interface is not ideal */ + (*pDRIPriv->pDriverInfo->MoveBuffers)(pWin, ptOldOrg, ®, + pDRIPriv->pDriverInfo->ddxDrawableTableEntry); + } + + REGION_UNINIT(pScreen, ®); + } + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.CopyWindow) { + /* unwrap */ + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + + /* call lower layers */ + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + /* rewrap */ + pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = DRICopyWindow; + } +} + +static void +DRIGetSecs(long *secs, long *usecs) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + *secs = tv.tv_sec; + *usecs = tv.tv_usec; +} + +static unsigned long +DRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs, + unsigned long f_secs, unsigned long f_usecs) +{ + if (f_usecs < s_usecs) { + --f_secs; + f_usecs += 1000000; + } + return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000; +} + +static void +DRISpinLockTimeout(drmLock *lock, int val, unsigned long timeout /* in mS */) +{ + int count = 10000; +#if !defined(__alpha__) && !defined(__powerpc__) + char ret; +#else + int ret; +#endif + long s_secs, s_usecs; + long f_secs, f_usecs; + long msecs; + long prev = 0; + + DRIGetSecs(&s_secs, &s_usecs); + + do { + DRM_SPINLOCK_COUNT(lock, val, count, ret); + if (!ret) return; /* Got lock */ + DRIGetSecs(&f_secs, &f_usecs); + msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs); + if (msecs - prev < 250) count *= 2; /* Not more than 0.5S */ + } while (msecs < timeout); + + /* Didn't get lock, so take it. The worst + that can happen is that there is some + garbage written to the wrong part of the + framebuffer that a refresh will repair. + That's undesirable, but better than + locking the server. This should be a + very rare event. */ + DRM_SPINLOCK_TAKE(lock, val); +} + +static void +DRILockTree(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv) return; + + /* Restore the last known 3D context if the X context is hidden */ + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_2D_SYNC, + DRI_NO_CONTEXT, + NULL, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore); + } + + /* Call kernel to release lock */ + DRIUnlock(pScreen); + + /* Grab drawable spin lock: a time out between 10 and 30 seconds is + appropriate, since this should never time out except in the case of + client death while the lock is being held. The timeout must be + greater than any reasonable rendering time. */ + DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000); /*10 secs*/ + + /* Call kernel flush outstanding buffers and relock */ + DRILock(pScreen, DRM_LOCK_QUIESCENT|DRM_LOCK_FLUSH_ALL); + + /* Switch back to our 2D context if the X context is hidden */ + if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) { + /* hide X context by swapping 2D component here */ + (*pDRIPriv->pDriverInfo->SwapContext)(pScreen, + DRI_3D_SYNC, + DRI_2D_CONTEXT, + pDRIPriv->partial3DContextStore, + DRI_2D_CONTEXT, + pDRIPriv->hiddenContextStore); + } +} + +int +DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + int returnValue = 1; /* always return 1, not checked by dix/window.c */ + + if(!pDRIPriv) return returnValue; + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.ValidateTree) { + /* unwrap */ + pScreen->ValidateTree = pDRIPriv->wrap.ValidateTree; + + /* call lower layers */ + returnValue = (*pScreen->ValidateTree)(pParent, pChild, kind); + + /* rewrap */ + pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; + pScreen->ValidateTree = DRIValidateTree; + } + + return returnValue; +} + +void +DRIPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + ScreenPtr pScreen; + DRIScreenPrivPtr pDRIPriv; + + if (pParent) { + pScreen = pParent->drawable.pScreen; + } else { + pScreen = pChild->drawable.pScreen; + } + if(!(pDRIPriv = DRI_SCREEN_PRIV(pScreen))) return; + + if (pDRIPriv->wrap.PostValidateTree) { + /* unwrap */ + pScreen->PostValidateTree = pDRIPriv->wrap.PostValidateTree; + + /* call lower layers */ + (*pScreen->PostValidateTree)(pParent, pChild, kind); + + /* rewrap */ + pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = DRIPostValidateTree; + } +} + +void +DRIClipNotify(WindowPtr pWin, int dx, int dy) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv; + + if(!pDRIPriv) return; + + if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + int nrects = REGION_NUM_RECTS(&pWin->clipList); + + if(!pDRIPriv->windowsTouched) { + DRILockTree(pScreen); + pDRIPriv->windowsTouched = TRUE; + } + + if (nrects && !pDRIDrawablePriv->nrects) + DRIIncreaseNumberVisible(pScreen); + else if (!nrects && pDRIDrawablePriv->nrects) + DRIDecreaseNumberVisible(pScreen); + else + DRIDriverClipNotify(pScreen); + + pDRIDrawablePriv->nrects = nrects; + + pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp + = DRIDrawableValidationStamp++; + + drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable, + DRM_DRAWABLE_CLIPRECTS, + nrects, REGION_RECTS(&pWin->clipList)); + } + + /* call lower wrapped functions */ + if(pDRIPriv->wrap.ClipNotify) { + + /* unwrap */ + pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; + + /* call lower layers */ + (*pScreen->ClipNotify)(pWin, dx, dy); + + /* rewrap */ + pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = DRIClipNotify; + } +} + +CARD32 +DRIGetDrawableIndex(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + CARD32 index; + + if (pDRIDrawablePriv) { + index = pDRIDrawablePriv->drawableIndex; + } + else { + index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry; + } + + return index; +} + +unsigned int +DRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp; +} + + +void +DRIPrintDrawableLock(ScreenPtr pScreen, char *msg) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock); +} + +void +DRILock(ScreenPtr pScreen, int flags) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; + + if (!*pDRIPriv->pLockRefCount) { + DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags); + *pDRIPriv->pLockingContext = pDRIPriv->myContext; + } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] Locking deadlock.\n" + "\tAlready locked with context %d,\n" + "\ttrying to lock with context %d.\n", + pDRIPriv->pLockingContext, + pDRIPriv->myContext); + } + (*pDRIPriv->pLockRefCount)++; +} + +void +DRIUnlock(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if(!pDRIPriv || !pDRIPriv->pLockRefCount) return; + + if (*pDRIPriv->pLockRefCount > 0) { + if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "[DRI] Unlocking inconsistency:\n" + "\tContext %d trying to unlock lock held by context %d\n", + pDRIPriv->pLockingContext, + pDRIPriv->myContext); + } + (*pDRIPriv->pLockRefCount)--; + } else { + DRIDrvMsg(pScreen->myNum, X_ERROR, + "DRIUnlock called when not locked.\n"); + return; + } + if (! *pDRIPriv->pLockRefCount) + DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext); +} + +void * +DRIGetSAREAPrivate(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + if (!pDRIPriv) return 0; + + return (void *)(((char*)pDRIPriv->pSAREA)+sizeof(XF86DRISAREARec)); +} + +drm_context_t +DRIGetContext(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + if (!pDRIPriv) return 0; + + return pDRIPriv->myContext; +} + +void +DRIGetTexOffsetFuncs(ScreenPtr pScreen, + DRITexOffsetStartProcPtr *texOffsetStartFunc, + DRITexOffsetFinishProcPtr *texOffsetFinishFunc) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (!pDRIPriv) return; + + *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart; + *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish; +} + +/* This lets get at the unwrapped functions so that they can correctly + * call the lowerlevel functions, and choose whether they will be + * called at every level of recursion (eg in validatetree). + */ +DRIWrappedFuncsRec * +DRIGetWrappedFuncs(ScreenPtr pScreen) +{ + return &(DRI_SCREEN_PRIV(pScreen)->wrap); +} + +/* note that this returns the library version, not the protocol version */ +void +DRIQueryVersion(int *majorVersion, + int *minorVersion, + int *patchVersion) +{ + *majorVersion = DRIINFO_MAJOR_VERSION; + *minorVersion = DRIINFO_MINOR_VERSION; + *patchVersion = DRIINFO_PATCH_VERSION; +} + +static void +_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y) +{ + pDRIPriv->pSAREA->frame.x = x; + pDRIPriv->pSAREA->frame.y = y; + pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1; + pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1; +} + +void +DRIAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[scrnIndex]; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int px, py; + + if (!pDRIPriv || !pDRIPriv->pSAREA) { + DRIDrvMsg(scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n", + pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL); + return; + } + + if (pDRIPriv->fullscreen) { + /* Fix up frame */ + pScrn->frameX0 = pDRIPriv->pSAREA->frame.x; + pScrn->frameY0 = pDRIPriv->pSAREA->frame.y; + pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1; + pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1; + + /* Fix up cursor */ + miPointerGetPosition(inputInfo.pointer, &px, &py); + if (px < pScrn->frameX0) px = pScrn->frameX0; + if (px > pScrn->frameX1) px = pScrn->frameX1; + if (py < pScrn->frameY0) py = pScrn->frameY0; + if (py > pScrn->frameY1) py = pScrn->frameY1; + pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE); + return; + } + + if (pDRIPriv->wrap.AdjustFrame) { + /* unwrap */ + pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame; + /* call lower layers */ + (*pScrn->AdjustFrame)(scrnIndex, x, y, flags); + /* rewrap */ + pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame; + pScrn->AdjustFrame = DRIAdjustFrame; + } + + _DRIAdjustFrame(pScrn, pDRIPriv, x, y); +} + +/* + * DRIMoveBuffersHelper swaps the regions rects in place leaving you + * a region with the rects in the order that you need to blit them, + * but it is possibly (likely) an invalid region afterwards. If you + * need to use the region again for anything you have to call + * REGION_VALIDATE on it, or better yet, save a copy first. + */ + +void +DRIMoveBuffersHelper( + ScreenPtr pScreen, + int dx, + int dy, + int *xdir, + int *ydir, + RegionPtr reg +) +{ + BoxPtr extents, pbox, firstBox, lastBox; + BoxRec tmpBox; + int y, nbox; + + extents = REGION_EXTENTS(pScreen, reg); + nbox = REGION_NUM_RECTS(reg); + pbox = REGION_RECTS(reg); + + if((dy > 0) && (dy < (extents->y2 - extents->y1))) { + *ydir = -1; + if(nbox > 1) { + firstBox = pbox; + lastBox = pbox + nbox - 1; + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + } + } else *ydir = 1; + + if((dx > 0) && (dx < (extents->x2 - extents->x1))) { + *xdir = -1; + if(nbox > 1) { + firstBox = lastBox = pbox; + y = pbox->y1; + while(--nbox) { + pbox++; + if(pbox->y1 == y) lastBox++; + else { + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + + firstBox = lastBox = pbox; + y = pbox->y1; + } + } + while((unsigned long)firstBox < (unsigned long)lastBox) { + tmpBox = *firstBox; + *firstBox = *lastBox; + *lastBox = tmpBox; + firstBox++; + lastBox--; + } + } + } else *xdir = 1; + +} + +char * +DRICreatePCIBusID(const struct pci_device * dev) +{ + char *busID; + + busID = malloc(20); + if (busID == NULL) + return NULL; + + snprintf(busID, 20, "pci:%04x:%02x:%02x.%d", dev->domain, dev->bus, + dev->dev, dev->func); + + return busID; +} + +static void drmSIGIOHandler(int interrupt, void *closure) +{ + unsigned long key; + void *value; + ssize_t count; + drm_ctx_t ctx; + typedef void (*_drmCallback)(int, void *, void *); + char buf[256]; + drm_context_t old; + drm_context_t new; + void *oldctx; + void *newctx; + char *pt; + drmHashEntry *entry; + void *hash_table; + + hash_table = drmGetHashTable(); + + if (!hash_table) return; + if (drmHashFirst(hash_table, &key, &value)) { + entry = value; + do { +#if 0 + fprintf(stderr, "Trying %d\n", entry->fd); +#endif + if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) { + buf[count] = '\0'; +#if 0 + fprintf(stderr, "Got %s\n", buf); +#endif + + for (pt = buf; *pt != ' '; ++pt); /* Find first space */ + ++pt; + old = strtol(pt, &pt, 0); + new = strtol(pt, NULL, 0); + oldctx = drmGetContextTag(entry->fd, old); + newctx = drmGetContextTag(entry->fd, new); +#if 0 + fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx); +#endif + ((_drmCallback)entry->f)(entry->fd, oldctx, newctx); + ctx.handle = new; + ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx); + } + } while (drmHashNext(hash_table, &key, &value)); + } +} + + +int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *)) +{ + drmHashEntry *entry; + + entry = drmGetEntry(fd); + entry->f = f; + + return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0); +} + +int drmRemoveSIGIOHandler(int fd) +{ + drmHashEntry *entry = drmGetEntry(fd); + + entry->f = NULL; + + return xf86RemoveSIGIOHandler(fd); +} diff --git a/xorg-server/hw/xfree86/dri/xf86dri.c b/xorg-server/hw/xfree86/dri/xf86dri.c index 78003991b..40914ed19 100644 --- a/xorg-server/hw/xfree86/dri/xf86dri.c +++ b/xorg-server/hw/xfree86/dri/xf86dri.c @@ -1,679 +1,679 @@ -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -Copyright 2000 VA Linux Systems, Inc. -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sub license, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice (including the -next paragraph) shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. -IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -**************************************************************************/ - -/* - * Authors: - * Kevin E. Martin - * Jens Owen - * Rickard E. (Rik) Faith - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "xf86.h" - -#include -#include -#include "misc.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "servermd.h" -#define _XF86DRI_SERVER_ -#include -#include "swaprep.h" -#include "xf86str.h" -#include "dri.h" -#include "sarea.h" -#include "dristruct.h" -#include "xf86.h" -#include "xf86drm.h" -#include "protocol-versions.h" - -static int DRIErrorBase; - -static DISPATCH_PROC(ProcXF86DRIQueryVersion); -static DISPATCH_PROC(ProcXF86DRIQueryDirectRenderingCapable); -static DISPATCH_PROC(ProcXF86DRIOpenConnection); -static DISPATCH_PROC(ProcXF86DRICloseConnection); -static DISPATCH_PROC(ProcXF86DRIGetClientDriverName); -static DISPATCH_PROC(ProcXF86DRICreateContext); -static DISPATCH_PROC(ProcXF86DRIDestroyContext); -static DISPATCH_PROC(ProcXF86DRICreateDrawable); -static DISPATCH_PROC(ProcXF86DRIDestroyDrawable); -static DISPATCH_PROC(ProcXF86DRIGetDrawableInfo); -static DISPATCH_PROC(ProcXF86DRIGetDeviceInfo); -static DISPATCH_PROC(ProcXF86DRIDispatch); -static DISPATCH_PROC(ProcXF86DRIAuthConnection); - -static DISPATCH_PROC(SProcXF86DRIQueryVersion); -static DISPATCH_PROC(SProcXF86DRIQueryDirectRenderingCapable); -static DISPATCH_PROC(SProcXF86DRIDispatch); - -static void XF86DRIResetProc(ExtensionEntry* extEntry); - -static unsigned char DRIReqCode = 0; - -extern void XFree86DRIExtensionInit(void); - -void -XFree86DRIExtensionInit(void) -{ - ExtensionEntry* extEntry; - -#ifdef XF86DRI_EVENTS - EventType = CreateNewResourceType(XF86DRIFreeEvents, "DRIEvent"); -#endif - - if ( - DRIExtensionInit() && -#ifdef XF86DRI_EVENTS - EventType && ScreenPrivateIndex != -1 && -#endif - (extEntry = AddExtension(XF86DRINAME, - XF86DRINumberEvents, - XF86DRINumberErrors, - ProcXF86DRIDispatch, - SProcXF86DRIDispatch, - XF86DRIResetProc, - StandardMinorOpcode))) { - DRIReqCode = (unsigned char)extEntry->base; - DRIErrorBase = extEntry->errorBase; - } -} - -/*ARGSUSED*/ -static void -XF86DRIResetProc ( - ExtensionEntry* extEntry -) -{ - DRIReset(); -} - -static int -ProcXF86DRIQueryVersion( - register ClientPtr client -) -{ - xXF86DRIQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_XF86DRI_MAJOR_VERSION; - rep.minorVersion = SERVER_XF86DRI_MINOR_VERSION; - rep.patchVersion = SERVER_XF86DRI_PATCH_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - swapl(&rep.patchVersion, n); - } - WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86DRIQueryDirectRenderingCapable( - register ClientPtr client -) -{ - xXF86DRIQueryDirectRenderingCapableReply rep; - Bool isCapable; - register int n; - - REQUEST(xXF86DRIQueryDirectRenderingCapableReq); - REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen], - &isCapable)) { - return BadValue; - } - rep.isCapable = isCapable; - - if (!LocalClient(client) || client->swapped) - rep.isCapable = 0; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - } - - WriteToClient(client, - sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86DRIOpenConnection( - register ClientPtr client -) -{ - xXF86DRIOpenConnectionReply rep; - drm_handle_t hSAREA; - char* busIdString; - - REQUEST(xXF86DRIOpenConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - if (!DRIOpenConnection( screenInfo.screens[stuff->screen], - &hSAREA, - &busIdString)) { - return BadValue; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.busIdStringLength = 0; - if (busIdString) - rep.busIdStringLength = strlen(busIdString); - rep.length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + - pad_to_int32(rep.busIdStringLength)); - - rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); -#if defined(LONG64) && !defined(__linux__) - rep.hSAREAHigh = (CARD32)(hSAREA >> 32); -#else - rep.hSAREAHigh = 0; -#endif - - WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); - if (rep.busIdStringLength) - WriteToClient(client, rep.busIdStringLength, busIdString); - return (client->noClientException); -} - -static int -ProcXF86DRIAuthConnection( - register ClientPtr client -) -{ - xXF86DRIAuthConnectionReply rep; - - REQUEST(xXF86DRIAuthConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.authenticated = 1; - - if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) { - ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); - rep.authenticated = 0; - } - WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86DRICloseConnection( - register ClientPtr client -) -{ - REQUEST(xXF86DRICloseConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - DRICloseConnection( screenInfo.screens[stuff->screen]); - - return (client->noClientException); -} - -static int -ProcXF86DRIGetClientDriverName( - register ClientPtr client -) -{ - xXF86DRIGetClientDriverNameReply rep; - char* clientDriverName; - - REQUEST(xXF86DRIGetClientDriverNameReq); - REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - DRIGetClientDriverName( screenInfo.screens[stuff->screen], - (int *)&rep.ddxDriverMajorVersion, - (int *)&rep.ddxDriverMinorVersion, - (int *)&rep.ddxDriverPatchVersion, - &clientDriverName); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.clientDriverNameLength = 0; - if (clientDriverName) - rep.clientDriverNameLength = strlen(clientDriverName); - rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) - - SIZEOF(xGenericReply) + - pad_to_int32(rep.clientDriverNameLength)); - - WriteToClient(client, - sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); - if (rep.clientDriverNameLength) - WriteToClient(client, - rep.clientDriverNameLength, - clientDriverName); - return (client->noClientException); -} - -static int -ProcXF86DRICreateContext( - register ClientPtr client -) -{ - xXF86DRICreateContextReply rep; - ScreenPtr pScreen; - - REQUEST(xXF86DRICreateContextReq); - REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - pScreen = screenInfo.screens[stuff->screen]; - - if (!DRICreateContext( pScreen, - NULL, - stuff->context, - (drm_context_t *)&rep.hHWContext)) { - return BadValue; - } - - WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86DRIDestroyContext( - register ClientPtr client -) -{ - REQUEST(xXF86DRIDestroyContextReq); - REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - if (!DRIDestroyContext( screenInfo.screens[stuff->screen], - stuff->context)) { - return BadValue; - } - - return (client->noClientException); -} - -static int -ProcXF86DRICreateDrawable( - ClientPtr client -) -{ - xXF86DRICreateDrawableReply rep; - DrawablePtr pDrawable; - int rc; - - REQUEST(xXF86DRICreateDrawableReq); - REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client, - pDrawable, (drm_drawable_t *)&rep.hHWDrawable)) { - return BadValue; - } - - WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXF86DRIDestroyDrawable( - register ClientPtr client -) -{ - REQUEST(xXF86DRIDestroyDrawableReq); - DrawablePtr pDrawable; - int rc; - REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); - - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client, - pDrawable)) { - return BadValue; - } - - return (client->noClientException); -} - -static int -ProcXF86DRIGetDrawableInfo( - register ClientPtr client -) -{ - xXF86DRIGetDrawableInfoReply rep; - DrawablePtr pDrawable; - int X, Y, W, H; - drm_clip_rect_t * pClipRects, *pClippedRects; - drm_clip_rect_t * pBackClipRects; - int backX, backY, rc; - - REQUEST(xXF86DRIGetDrawableInfoReq); - REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if (!DRIGetDrawableInfo( screenInfo.screens[stuff->screen], - pDrawable, - (unsigned int*)&rep.drawableTableIndex, - (unsigned int*)&rep.drawableTableStamp, - (int*)&X, - (int*)&Y, - (int*)&W, - (int*)&H, - (int*)&rep.numClipRects, - &pClipRects, - &backX, - &backY, - (int*)&rep.numBackClipRects, - &pBackClipRects)) { - return BadValue; - } - - rep.drawableX = X; - rep.drawableY = Y; - rep.drawableWidth = W; - rep.drawableHeight = H; - rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - - SIZEOF(xGenericReply)); - - rep.backX = backX; - rep.backY = backY; - - if (rep.numBackClipRects) - rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; - - pClippedRects = pClipRects; - - if (rep.numClipRects) { - /* Clip cliprects to screen dimensions (redirected windows) */ - pClippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t)); - - if (pClippedRects) { - ScreenPtr pScreen = screenInfo.screens[stuff->screen]; - int i, j; - - for (i = 0, j = 0; i < rep.numClipRects; i++) { - pClippedRects[j].x1 = max(pClipRects[i].x1, 0); - pClippedRects[j].y1 = max(pClipRects[i].y1, 0); - pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); - pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); - - if (pClippedRects[j].x1 < pClippedRects[j].x2 && - pClippedRects[j].y1 < pClippedRects[j].y2) { - j++; - } - } - - rep.numClipRects = j; - } else { - rep.numClipRects = 0; - } - - rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; - } - - rep.length = bytes_to_int32(rep.length); - - WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); - - if (rep.numClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numClipRects, - (char *)pClippedRects); - xfree(pClippedRects); - } - - if (rep.numBackClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numBackClipRects, - (char *)pBackClipRects); - } - - return (client->noClientException); -} - -static int -ProcXF86DRIGetDeviceInfo( - register ClientPtr client -) -{ - xXF86DRIGetDeviceInfoReply rep; - drm_handle_t hFrameBuffer; - void *pDevPrivate; - - REQUEST(xXF86DRIGetDeviceInfoReq); - REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if (!DRIGetDeviceInfo( screenInfo.screens[stuff->screen], - &hFrameBuffer, - (int*)&rep.framebufferOrigin, - (int*)&rep.framebufferSize, - (int*)&rep.framebufferStride, - (int*)&rep.devPrivateSize, - &pDevPrivate)) { - return BadValue; - } - - rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); -#if defined(LONG64) && !defined(__linux__) - rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); -#else - rep.hFrameBufferHigh = 0; -#endif - - rep.length = 0; - if (rep.devPrivateSize) { - rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) - - SIZEOF(xGenericReply) + - pad_to_int32(rep.devPrivateSize)); - } - - WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); - if (rep.length) { - WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); - } - return (client->noClientException); -} - -static int -ProcXF86DRIDispatch ( - register ClientPtr client -) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_XF86DRIQueryVersion: - return ProcXF86DRIQueryVersion(client); - case X_XF86DRIQueryDirectRenderingCapable: - return ProcXF86DRIQueryDirectRenderingCapable(client); - } - - if (!LocalClient(client)) - return DRIErrorBase + XF86DRIClientNotLocal; - - switch (stuff->data) - { - case X_XF86DRIOpenConnection: - return ProcXF86DRIOpenConnection(client); - case X_XF86DRICloseConnection: - return ProcXF86DRICloseConnection(client); - case X_XF86DRIGetClientDriverName: - return ProcXF86DRIGetClientDriverName(client); - case X_XF86DRICreateContext: - return ProcXF86DRICreateContext(client); - case X_XF86DRIDestroyContext: - return ProcXF86DRIDestroyContext(client); - case X_XF86DRICreateDrawable: - return ProcXF86DRICreateDrawable(client); - case X_XF86DRIDestroyDrawable: - return ProcXF86DRIDestroyDrawable(client); - case X_XF86DRIGetDrawableInfo: - return ProcXF86DRIGetDrawableInfo(client); - case X_XF86DRIGetDeviceInfo: - return ProcXF86DRIGetDeviceInfo(client); - case X_XF86DRIAuthConnection: - return ProcXF86DRIAuthConnection(client); - /* {Open,Close}FullScreen are deprecated now */ - default: - return BadRequest; - } -} - -static int -SProcXF86DRIQueryVersion( - register ClientPtr client -) -{ - register int n; - REQUEST(xXF86DRIQueryVersionReq); - swaps(&stuff->length, n); - return ProcXF86DRIQueryVersion(client); -} - -static int -SProcXF86DRIQueryDirectRenderingCapable( - register ClientPtr client -) -{ - register int n; - REQUEST(xXF86DRIQueryDirectRenderingCapableReq); - swaps(&stuff->length, n); - swapl(&stuff->screen, n); - return ProcXF86DRIQueryDirectRenderingCapable(client); -} - -static int -SProcXF86DRIDispatch ( - register ClientPtr client -) -{ - REQUEST(xReq); - - /* - * Only local clients are allowed DRI access, but remote clients still need - * these requests to find out cleanly. - */ - switch (stuff->data) - { - case X_XF86DRIQueryVersion: - return SProcXF86DRIQueryVersion(client); - case X_XF86DRIQueryDirectRenderingCapable: - return SProcXF86DRIQueryDirectRenderingCapable(client); - default: - return DRIErrorBase + XF86DRIClientNotLocal; - } -} +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Kevin E. Martin + * Jens Owen + * Rickard E. (Rik) Faith + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "xf86.h" + +#include +#include +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _XF86DRI_SERVER_ +#include +#include "swaprep.h" +#include "xf86str.h" +#include "dri.h" +#include "sarea.h" +#include "dristruct.h" +#include "xf86.h" +#include "xf86drm.h" +#include "protocol-versions.h" + +static int DRIErrorBase; + +static DISPATCH_PROC(ProcXF86DRIQueryVersion); +static DISPATCH_PROC(ProcXF86DRIQueryDirectRenderingCapable); +static DISPATCH_PROC(ProcXF86DRIOpenConnection); +static DISPATCH_PROC(ProcXF86DRICloseConnection); +static DISPATCH_PROC(ProcXF86DRIGetClientDriverName); +static DISPATCH_PROC(ProcXF86DRICreateContext); +static DISPATCH_PROC(ProcXF86DRIDestroyContext); +static DISPATCH_PROC(ProcXF86DRICreateDrawable); +static DISPATCH_PROC(ProcXF86DRIDestroyDrawable); +static DISPATCH_PROC(ProcXF86DRIGetDrawableInfo); +static DISPATCH_PROC(ProcXF86DRIGetDeviceInfo); +static DISPATCH_PROC(ProcXF86DRIDispatch); +static DISPATCH_PROC(ProcXF86DRIAuthConnection); + +static DISPATCH_PROC(SProcXF86DRIQueryVersion); +static DISPATCH_PROC(SProcXF86DRIQueryDirectRenderingCapable); +static DISPATCH_PROC(SProcXF86DRIDispatch); + +static void XF86DRIResetProc(ExtensionEntry* extEntry); + +static unsigned char DRIReqCode = 0; + +extern void XFree86DRIExtensionInit(void); + +void +XFree86DRIExtensionInit(void) +{ + ExtensionEntry* extEntry; + +#ifdef XF86DRI_EVENTS + EventType = CreateNewResourceType(XF86DRIFreeEvents, "DRIEvent"); +#endif + + if ( + DRIExtensionInit() && +#ifdef XF86DRI_EVENTS + EventType && ScreenPrivateIndex != -1 && +#endif + (extEntry = AddExtension(XF86DRINAME, + XF86DRINumberEvents, + XF86DRINumberErrors, + ProcXF86DRIDispatch, + SProcXF86DRIDispatch, + XF86DRIResetProc, + StandardMinorOpcode))) { + DRIReqCode = (unsigned char)extEntry->base; + DRIErrorBase = extEntry->errorBase; + } +} + +/*ARGSUSED*/ +static void +XF86DRIResetProc ( + ExtensionEntry* extEntry +) +{ + DRIReset(); +} + +static int +ProcXF86DRIQueryVersion( + register ClientPtr client +) +{ + xXF86DRIQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_XF86DRI_MAJOR_VERSION; + rep.minorVersion = SERVER_XF86DRI_MINOR_VERSION; + rep.patchVersion = SERVER_XF86DRI_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swapl(&rep.patchVersion, n); + } + WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + xXF86DRIQueryDirectRenderingCapableReply rep; + Bool isCapable; + register int n; + + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen], + &isCapable)) { + return BadValue; + } + rep.isCapable = isCapable; + + if (!LocalClient(client) || client->swapped) + rep.isCapable = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + + WriteToClient(client, + sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRIOpenConnection( + register ClientPtr client +) +{ + xXF86DRIOpenConnectionReply rep; + drm_handle_t hSAREA; + char* busIdString; + + REQUEST(xXF86DRIOpenConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!DRIOpenConnection( screenInfo.screens[stuff->screen], + &hSAREA, + &busIdString)) { + return BadValue; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.busIdStringLength = 0; + if (busIdString) + rep.busIdStringLength = strlen(busIdString); + rep.length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + + pad_to_int32(rep.busIdStringLength)); + + rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hSAREAHigh = (CARD32)(hSAREA >> 32); +#else + rep.hSAREAHigh = 0; +#endif + + WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); + if (rep.busIdStringLength) + WriteToClient(client, rep.busIdStringLength, busIdString); + return Success; +} + +static int +ProcXF86DRIAuthConnection( + register ClientPtr client +) +{ + xXF86DRIAuthConnectionReply rep; + + REQUEST(xXF86DRIAuthConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.authenticated = 1; + + if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) { + ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); + rep.authenticated = 0; + } + WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRICloseConnection( + register ClientPtr client +) +{ + REQUEST(xXF86DRICloseConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + DRICloseConnection( screenInfo.screens[stuff->screen]); + + return Success; +} + +static int +ProcXF86DRIGetClientDriverName( + register ClientPtr client +) +{ + xXF86DRIGetClientDriverNameReply rep; + char* clientDriverName; + + REQUEST(xXF86DRIGetClientDriverNameReq); + REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + DRIGetClientDriverName( screenInfo.screens[stuff->screen], + (int *)&rep.ddxDriverMajorVersion, + (int *)&rep.ddxDriverMinorVersion, + (int *)&rep.ddxDriverPatchVersion, + &clientDriverName); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.clientDriverNameLength = 0; + if (clientDriverName) + rep.clientDriverNameLength = strlen(clientDriverName); + rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) - + SIZEOF(xGenericReply) + + pad_to_int32(rep.clientDriverNameLength)); + + WriteToClient(client, + sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); + if (rep.clientDriverNameLength) + WriteToClient(client, + rep.clientDriverNameLength, + clientDriverName); + return Success; +} + +static int +ProcXF86DRICreateContext( + register ClientPtr client +) +{ + xXF86DRICreateContextReply rep; + ScreenPtr pScreen; + + REQUEST(xXF86DRICreateContextReq); + REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + pScreen = screenInfo.screens[stuff->screen]; + + if (!DRICreateContext( pScreen, + NULL, + stuff->context, + (drm_context_t *)&rep.hHWContext)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRIDestroyContext( + register ClientPtr client +) +{ + REQUEST(xXF86DRIDestroyContextReq); + REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!DRIDestroyContext( screenInfo.screens[stuff->screen], + stuff->context)) { + return BadValue; + } + + return Success; +} + +static int +ProcXF86DRICreateDrawable( + ClientPtr client +) +{ + xXF86DRICreateDrawableReply rep; + DrawablePtr pDrawable; + int rc; + + REQUEST(xXF86DRICreateDrawableReq); + REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client, + pDrawable, (drm_drawable_t *)&rep.hHWDrawable)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); + return Success; +} + +static int +ProcXF86DRIDestroyDrawable( + register ClientPtr client +) +{ + REQUEST(xXF86DRIDestroyDrawableReq); + DrawablePtr pDrawable; + int rc; + REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); + + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client, + pDrawable)) { + return BadValue; + } + + return Success; +} + +static int +ProcXF86DRIGetDrawableInfo( + register ClientPtr client +) +{ + xXF86DRIGetDrawableInfoReply rep; + DrawablePtr pDrawable; + int X, Y, W, H; + drm_clip_rect_t * pClipRects, *pClippedRects; + drm_clip_rect_t * pBackClipRects; + int backX, backY, rc; + + REQUEST(xXF86DRIGetDrawableInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!DRIGetDrawableInfo( screenInfo.screens[stuff->screen], + pDrawable, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &pClipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &pBackClipRects)) { + return BadValue; + } + + rep.drawableX = X; + rep.drawableY = Y; + rep.drawableWidth = W; + rep.drawableHeight = H; + rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - + SIZEOF(xGenericReply)); + + rep.backX = backX; + rep.backY = backY; + + if (rep.numBackClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + + pClippedRects = pClipRects; + + if (rep.numClipRects) { + /* Clip cliprects to screen dimensions (redirected windows) */ + pClippedRects = malloc(rep.numClipRects * sizeof(drm_clip_rect_t)); + + if (pClippedRects) { + ScreenPtr pScreen = screenInfo.screens[stuff->screen]; + int i, j; + + for (i = 0, j = 0; i < rep.numClipRects; i++) { + pClippedRects[j].x1 = max(pClipRects[i].x1, 0); + pClippedRects[j].y1 = max(pClipRects[i].y1, 0); + pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); + pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); + + if (pClippedRects[j].x1 < pClippedRects[j].x2 && + pClippedRects[j].y1 < pClippedRects[j].y2) { + j++; + } + } + + rep.numClipRects = j; + } else { + rep.numClipRects = 0; + } + + rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + } + + rep.length = bytes_to_int32(rep.length); + + WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); + + if (rep.numClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numClipRects, + (char *)pClippedRects); + free(pClippedRects); + } + + if (rep.numBackClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numBackClipRects, + (char *)pBackClipRects); + } + + return Success; +} + +static int +ProcXF86DRIGetDeviceInfo( + register ClientPtr client +) +{ + xXF86DRIGetDeviceInfoReply rep; + drm_handle_t hFrameBuffer; + void *pDevPrivate; + + REQUEST(xXF86DRIGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!DRIGetDeviceInfo( screenInfo.screens[stuff->screen], + &hFrameBuffer, + (int*)&rep.framebufferOrigin, + (int*)&rep.framebufferSize, + (int*)&rep.framebufferStride, + (int*)&rep.devPrivateSize, + &pDevPrivate)) { + return BadValue; + } + + rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); +#if defined(LONG64) && !defined(__linux__) + rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); +#else + rep.hFrameBufferHigh = 0; +#endif + + rep.length = 0; + if (rep.devPrivateSize) { + rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) - + SIZEOF(xGenericReply) + + pad_to_int32(rep.devPrivateSize)); + } + + WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); + if (rep.length) { + WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); + } + return Success; +} + +static int +ProcXF86DRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_XF86DRIQueryVersion: + return ProcXF86DRIQueryVersion(client); + case X_XF86DRIQueryDirectRenderingCapable: + return ProcXF86DRIQueryDirectRenderingCapable(client); + } + + if (!LocalClient(client)) + return DRIErrorBase + XF86DRIClientNotLocal; + + switch (stuff->data) + { + case X_XF86DRIOpenConnection: + return ProcXF86DRIOpenConnection(client); + case X_XF86DRICloseConnection: + return ProcXF86DRICloseConnection(client); + case X_XF86DRIGetClientDriverName: + return ProcXF86DRIGetClientDriverName(client); + case X_XF86DRICreateContext: + return ProcXF86DRICreateContext(client); + case X_XF86DRIDestroyContext: + return ProcXF86DRIDestroyContext(client); + case X_XF86DRICreateDrawable: + return ProcXF86DRICreateDrawable(client); + case X_XF86DRIDestroyDrawable: + return ProcXF86DRIDestroyDrawable(client); + case X_XF86DRIGetDrawableInfo: + return ProcXF86DRIGetDrawableInfo(client); + case X_XF86DRIGetDeviceInfo: + return ProcXF86DRIGetDeviceInfo(client); + case X_XF86DRIAuthConnection: + return ProcXF86DRIAuthConnection(client); + /* {Open,Close}FullScreen are deprecated now */ + default: + return BadRequest; + } +} + +static int +SProcXF86DRIQueryVersion( + register ClientPtr client +) +{ + register int n; + REQUEST(xXF86DRIQueryVersionReq); + swaps(&stuff->length, n); + return ProcXF86DRIQueryVersion(client); +} + +static int +SProcXF86DRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + register int n; + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + swaps(&stuff->length, n); + swapl(&stuff->screen, n); + return ProcXF86DRIQueryDirectRenderingCapable(client); +} + +static int +SProcXF86DRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + /* + * Only local clients are allowed DRI access, but remote clients still need + * these requests to find out cleanly. + */ + switch (stuff->data) + { + case X_XF86DRIQueryVersion: + return SProcXF86DRIQueryVersion(client); + case X_XF86DRIQueryDirectRenderingCapable: + return SProcXF86DRIQueryDirectRenderingCapable(client); + default: + return DRIErrorBase + XF86DRIClientNotLocal; + } +} diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c index abcb96668..64be079ca 100644 --- a/xorg-server/hw/xfree86/dri2/dri2.c +++ b/xorg-server/hw/xfree86/dri2/dri2.c @@ -96,6 +96,8 @@ typedef struct _DRI2Screen { DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC; HandleExposuresProcPtr HandleExposures; + + ConfigNotifyProcPtr ConfigNotify; } DRI2ScreenRec; static DRI2ScreenPtr @@ -128,7 +130,7 @@ DRI2AllocateDrawable(DrawablePtr pDraw) WindowPtr pWin; PixmapPtr pPixmap; - pPriv = xalloc(sizeof *pPriv); + pPriv = malloc(sizeof *pPriv); if (pPriv == NULL) return NULL; @@ -165,9 +167,11 @@ DRI2AllocateDrawable(DrawablePtr pDraw) } typedef struct DRI2DrawableRefRec { - XID id; - XID dri2_id; - struct list link; + XID id; + XID dri2_id; + DRI2InvalidateProcPtr invalidate; + void *priv; + struct list link; } DRI2DrawableRefRec, *DRI2DrawableRefPtr; static DRI2DrawableRefPtr @@ -184,7 +188,8 @@ DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id) } static int -DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id) +DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id, + DRI2InvalidateProcPtr invalidate, void *priv) { DRI2DrawableRefPtr ref; @@ -200,13 +205,16 @@ DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id) ref->id = id; ref->dri2_id = dri2_id; + ref->invalidate = invalidate; + ref->priv = priv; list_add(&ref->link, &pPriv->reference_list); return Success; } int -DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id) +DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id, + DRI2InvalidateProcPtr invalidate, void *priv) { DRI2DrawablePtr pPriv; XID dri2_id; @@ -219,7 +227,7 @@ DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id) return BadAlloc; dri2_id = FakeClientID(client->index); - rc = DRI2AddDrawableRef(pPriv, id, dri2_id); + rc = DRI2AddDrawableRef(pPriv, id, dri2_id, invalidate, priv); if (rc != Success) return rc; @@ -270,10 +278,10 @@ static int DRI2DrawableGone(pointer p, XID id) for (i = 0; i < pPriv->bufferCount; i++) (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); - xfree(pPriv->buffers); + free(pPriv->buffers); } - xfree(pPriv); + free(pPriv); return Success; } @@ -318,6 +326,31 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds, } } +static void +update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw, + DRI2BufferPtr *buffers, int *out_count, int *width, int *height) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); + int i; + + if (pPriv->buffers != NULL) { + for (i = 0; i < pPriv->bufferCount; i++) { + if (pPriv->buffers[i] != NULL) { + (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); + } + } + + free(pPriv->buffers); + } + + pPriv->buffers = buffers; + pPriv->bufferCount = *out_count; + pPriv->width = pDraw->width; + pPriv->height = pDraw->height; + *width = pPriv->width; + *height = pPriv->height; +} + static DRI2BufferPtr * do_get_buffers(DrawablePtr pDraw, int *width, int *height, unsigned int *attachments, int count, int *out_count, @@ -344,7 +377,7 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, dimensions_match = (pDraw->width == pPriv->width) && (pDraw->height == pPriv->height); - buffers = xalloc((count + 1) * sizeof(buffers[0])); + buffers = malloc((count + 1) * sizeof(buffers[0])); for (i = 0; i < count; i++) { const unsigned attachment = *(attachments++); @@ -355,6 +388,9 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, &buffers[i])) buffers_changed = 1; + if (buffers[i] == NULL) + goto err_out; + /* If the drawable is a window and the front-buffer is requested, * silently add the fake front-buffer to the list of requested * attachments. The counting logic in the loop accounts for the case @@ -387,6 +423,9 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, front_format, dimensions_match, &buffers[i++])) buffers_changed = 1; + + if (buffers[i] == NULL) + goto err_out; } if (need_fake_front > 0) { @@ -395,29 +434,15 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, &buffers[i++])) buffers_changed = 1; + if (buffers[i] == NULL) + goto err_out; + have_fake_front = 1; } *out_count = i; - - if (pPriv->buffers != NULL) { - for (i = 0; i < pPriv->bufferCount; i++) { - if (pPriv->buffers[i] != NULL) { - (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); - } - } - - xfree(pPriv->buffers); - } - - pPriv->buffers = buffers; - pPriv->bufferCount = *out_count; - pPriv->width = pDraw->width; - pPriv->height = pDraw->height; - *width = pPriv->width; - *height = pPriv->height; - + update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height); /* If the client is getting a fake front-buffer, pre-fill it with the * contents of the real front-buffer. This ensures correct operation of @@ -438,6 +463,22 @@ do_get_buffers(DrawablePtr pDraw, int *width, int *height, } return pPriv->buffers; + +err_out: + + *out_count = 0; + + for (i = 0; i < count; i++) { + if (buffers[i] != NULL) + (*ds->DestroyBuffer)(pDraw, buffers[i]); + } + + free(buffers); + buffers = NULL; + + update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height); + + return buffers; } DRI2BufferPtr * @@ -456,6 +497,19 @@ DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height, out_count, TRUE); } +static void +DRI2InvalidateDrawable(DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + DRI2DrawableRefPtr ref; + + if (!pPriv) + return; + + list_for_each_entry(ref, &pPriv->reference_list, link) + ref->invalidate(pDraw, ref->priv); +} + /* * In the direct rendered case, we throttle the clients that have more * than their share of outstanding swaps (and thus busy buffers) when a @@ -634,6 +688,8 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame, ScreenPtr pScreen = pDraw->pScreen; DRI2DrawablePtr pPriv; CARD64 ust = 0; + BoxRec box; + RegionRec region; pPriv = DRI2GetDrawable(pDraw); if (pPriv == NULL) { @@ -645,6 +701,14 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame, pPriv->swapsPending--; pPriv->swap_count++; + box.x1 = 0; + box.y1 = 0; + box.x2 = pDraw->width; + box.y2 = pDraw->height; + REGION_INIT(pScreen, ®ion, &box, 0); + DRI2CopyRegion(pDraw, ®ion, DRI2BufferFakeFrontLeft, + DRI2BufferFrontLeft); + ust = ((CARD64)tv_sec * 1000000) + tv_usec; if (swap_complete) swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count); @@ -756,6 +820,8 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, */ *swap_target = pPriv->swap_count + pPriv->swapsPending; + DRI2InvalidateDrawable(pDraw); + return Success; } @@ -906,6 +972,30 @@ DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic) return TRUE; } +static void +DRI2ConfigNotify(WindowPtr pWin, int x, int y, int w, int h, int bw, + WindowPtr pSib) +{ + DrawablePtr pDraw = (DrawablePtr)pWin; + ScreenPtr pScreen = pDraw->pScreen; + DRI2ScreenPtr ds = DRI2GetScreen(pScreen); + DRI2DrawablePtr dd = DRI2GetDrawable(pDraw); + + if (ds->ConfigNotify) { + pScreen->ConfigNotify = ds->ConfigNotify; + + (*pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib); + + ds->ConfigNotify = pScreen->ConfigNotify; + pScreen->ConfigNotify = DRI2ConfigNotify; + } + + if (!dd || (dd->width == w && dd->height == h)) + return; + + DRI2InvalidateDrawable(pDraw); +} + Bool DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) { @@ -926,7 +1016,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) return FALSE; } - ds = xcalloc(1, sizeof *ds); + ds = calloc(1, sizeof *ds); if (!ds) return FALSE; @@ -943,7 +1033,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) ds->ScheduleSwap = info->ScheduleSwap; ds->ScheduleWaitMSC = info->ScheduleWaitMSC; ds->GetMSC = info->GetMSC; - cur_minor = 2; + cur_minor = 3; } else { cur_minor = 1; } @@ -955,17 +1045,17 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) if (info->version == 3 || info->numDrivers == 0) { /* Driver too old: use the old-style driverName field */ ds->numDrivers = 1; - ds->driverNames = xalloc(sizeof(*ds->driverNames)); + ds->driverNames = malloc(sizeof(*ds->driverNames)); if (!ds->driverNames) { - xfree(ds); + free(ds); return FALSE; } ds->driverNames[0] = info->driverName; } else { ds->numDrivers = info->numDrivers; - ds->driverNames = xalloc(info->numDrivers * sizeof(*ds->driverNames)); + ds->driverNames = malloc(info->numDrivers * sizeof(*ds->driverNames)); if (!ds->driverNames) { - xfree(ds); + free(ds); return FALSE; } memcpy(ds->driverNames, info->driverNames, @@ -974,6 +1064,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds); + ds->ConfigNotify = pScreen->ConfigNotify; + pScreen->ConfigNotify = DRI2ConfigNotify; + xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n"); for (i = 0; i < sizeof(driverTypeNames) / sizeof(driverTypeNames[0]); i++) { if (i < ds->numDrivers && ds->driverNames[i]) { @@ -990,8 +1083,8 @@ DRI2CloseScreen(ScreenPtr pScreen) { DRI2ScreenPtr ds = DRI2GetScreen(pScreen); - xfree(ds->driverNames); - xfree(ds); + free(ds->driverNames); + free(ds); dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL); } diff --git a/xorg-server/hw/xfree86/dri2/dri2.h b/xorg-server/hw/xfree86/dri2/dri2.h index cc15f120d..c43aa6a04 100644 --- a/xorg-server/hw/xfree86/dri2/dri2.h +++ b/xorg-server/hw/xfree86/dri2/dri2.h @@ -152,6 +152,10 @@ typedef int (*DRI2ScheduleWaitMSCProcPtr)(ClientPtr client, CARD64 target_msc, CARD64 divisor, CARD64 remainder); + +typedef void (*DRI2InvalidateProcPtr)(DrawablePtr pDraw, + void *data); + /** * Version of the DRI2InfoRec structure defined in this header */ @@ -199,7 +203,10 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen, extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic); extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client, - DrawablePtr pDraw, XID id); + DrawablePtr pDraw, + XID id, + DRI2InvalidateProcPtr invalidate, + void *priv); extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw); diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index 8bed02055..38efc86e0 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -91,7 +91,7 @@ ProcDRI2QueryVersion(ClientPtr client) WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep); - return client->noClientException; + return Success; } static int @@ -129,7 +129,7 @@ ProcDRI2Connect(ClientPtr client) WriteToClient(client, rep.driverNameLength, driverName); WriteToClient(client, rep.deviceNameLength, deviceName); - return client->noClientException; + return Success; } static int @@ -151,7 +151,23 @@ ProcDRI2Authenticate(ClientPtr client) rep.authenticated = DRI2Authenticate(pDraw->pScreen, stuff->magic); WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep); - return client->noClientException; + return Success; +} + +static void +DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv) +{ + xDRI2InvalidateBuffers event; + ClientPtr client = priv; + + if (client->clientGone) + return; + + event.type = DRI2EventBase + DRI2_InvalidateBuffers; + event.sequenceNumber = client->sequence; + event.drawable = pDraw->id; + + WriteEventsToClient(client, 1, (xEvent *)&event); } static int @@ -167,11 +183,12 @@ ProcDRI2CreateDrawable(ClientPtr client) &pDrawable, &status)) return status; - status = DRI2CreateDrawable(client, pDrawable, stuff->drawable); + status = DRI2CreateDrawable(client, pDrawable, stuff->drawable, + DRI2InvalidateBuffersEvent, client); if (status != Success) return status; - return client->noClientException; + return Success; } static int @@ -186,11 +203,11 @@ ProcDRI2DestroyDrawable(ClientPtr client) &pDrawable, &status)) return status; - return client->noClientException; + return Success; } -static void +static int send_buffers_reply(ClientPtr client, DrawablePtr pDrawable, DRI2BufferPtr *buffers, int count, int width, int height) { @@ -198,6 +215,9 @@ send_buffers_reply(ClientPtr client, DrawablePtr pDrawable, int skip = 0; int i; + if (buffers == NULL) + return BadAlloc; + if (pDrawable->type == DRAWABLE_WINDOW) { for (i = 0; i < count; i++) { /* Do not send the real front buffer of a window to the client. @@ -234,6 +254,7 @@ send_buffers_reply(ClientPtr client, DrawablePtr pDrawable, buffer.flags = buffers[i]->flags; WriteToClient(client, sizeof(xDRI2Buffer), &buffer); } + return Success; } @@ -252,16 +273,15 @@ ProcDRI2GetBuffers(ClientPtr client) return status; if (DRI2ThrottleClient(client, pDrawable)) - return client->noClientException; + return Success; attachments = (unsigned int *) &stuff[1]; buffers = DRI2GetBuffers(pDrawable, &width, &height, attachments, stuff->count, &count); - send_buffers_reply(client, pDrawable, buffers, count, width, height); + return send_buffers_reply(client, pDrawable, buffers, count, width, height); - return client->noClientException; } static int @@ -279,15 +299,13 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client) return status; if (DRI2ThrottleClient(client, pDrawable)) - return client->noClientException; + return Success; attachments = (unsigned int *) &stuff[1]; buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height, attachments, stuff->count, &count); - send_buffers_reply(client, pDrawable, buffers, count, width, height); - - return client->noClientException; + return send_buffers_reply(client, pDrawable, buffers, count, width, height); } static int @@ -324,7 +342,7 @@ ProcDRI2CopyRegion(ClientPtr client) WriteToClient(client, sizeof(xDRI2CopyRegionReply), &rep); - return client->noClientException; + return Success; } static void @@ -381,7 +399,7 @@ ProcDRI2SwapBuffers(ClientPtr client) * also orders swaps. */ if (DRI2ThrottleClient(client, pDrawable)) - return client->noClientException; + return Success; target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi); divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi); @@ -399,7 +417,7 @@ ProcDRI2SwapBuffers(ClientPtr client) WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep); - return client->noClientException; + return Success; } static void @@ -439,7 +457,7 @@ ProcDRI2GetMSC(ClientPtr client) WriteToClient(client, sizeof(xDRI2MSCReply), &rep); - return client->noClientException; + return Success; } static int @@ -466,7 +484,7 @@ ProcDRI2WaitMSC(ClientPtr client) if (status != Success) return status; - return client->noClientException; + return Success; } int @@ -481,7 +499,7 @@ ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc) WriteToClient(client, sizeof(xDRI2MSCReply), &rep); - return client->noClientException; + return Success; } static int @@ -501,7 +519,7 @@ ProcDRI2SwapInterval(ClientPtr client) DRI2SwapInterval(pDrawable, stuff->interval); - return client->noClientException; + return Success; } static int @@ -531,7 +549,7 @@ ProcDRI2WaitSBC(ClientPtr client) WriteToClient(client, sizeof(xDRI2MSCReply), &rep); - return client->noClientException; + return Success; } static int @@ -596,7 +614,7 @@ SProcDRI2Connect(ClientPtr client) rep.driverNameLength = 0; rep.deviceNameLength = 0; - return client->noClientException; + return Success; } static int diff --git a/xorg-server/hw/xfree86/exa/examodule.c b/xorg-server/hw/xfree86/exa/examodule.c index bcb6a405c..6238582c0 100644 --- a/xorg-server/hw/xfree86/exa/examodule.c +++ b/xorg-server/hw/xfree86/exa/examodule.c @@ -1,198 +1,198 @@ -/* - * Copyright © 2006 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Eric Anholt - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "exa_priv.h" - -#include "xf86str.h" -#include "xf86.h" - -typedef struct _ExaXorgScreenPrivRec { - CloseScreenProcPtr SavedCloseScreen; - EnableDisableFBAccessProcPtr SavedEnableDisableFBAccess; - OptionInfoPtr options; -} ExaXorgScreenPrivRec, *ExaXorgScreenPrivPtr; - -static int exaXorgScreenPrivateKeyIndex; -static DevPrivateKey exaXorgScreenPrivateKey = &exaXorgScreenPrivateKeyIndex; - -typedef enum { - EXAOPT_MIGRATION_HEURISTIC, - EXAOPT_NO_COMPOSITE, - EXAOPT_NO_UTS, - EXAOPT_NO_DFS, - EXAOPT_OPTIMIZE_MIGRATION -} EXAOpts; - -static const OptionInfoRec EXAOptions[] = { - { EXAOPT_MIGRATION_HEURISTIC, "MigrationHeuristic", - OPTV_ANYSTR, {0}, FALSE }, - { EXAOPT_NO_COMPOSITE, "EXANoComposite", - OPTV_BOOLEAN, {0}, FALSE }, - { EXAOPT_NO_UTS, "EXANoUploadToScreen", - OPTV_BOOLEAN, {0}, FALSE }, - { EXAOPT_NO_DFS, "EXANoDownloadFromScreen", - OPTV_BOOLEAN, {0}, FALSE }, - { EXAOPT_OPTIMIZE_MIGRATION, "EXAOptimizeMigration", - OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, - OPTV_NONE, {0}, FALSE } -}; - -static Bool -exaXorgCloseScreen (int i, ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); - ExaXorgScreenPrivPtr pScreenPriv = (ExaXorgScreenPrivPtr) - dixLookupPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey); - - pScreen->CloseScreen = pScreenPriv->SavedCloseScreen; - - pScrn->EnableDisableFBAccess = pScreenPriv->SavedEnableDisableFBAccess; - - xfree (pScreenPriv->options); - xfree (pScreenPriv); - - return pScreen->CloseScreen (i, pScreen); -} - -static void -exaXorgEnableDisableFBAccess (int index, Bool enable) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - ExaXorgScreenPrivPtr pScreenPriv = (ExaXorgScreenPrivPtr) - dixLookupPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey); - - if (!enable) - exaEnableDisableFBAccess (index, enable); - - if (pScreenPriv->SavedEnableDisableFBAccess) - pScreenPriv->SavedEnableDisableFBAccess (index, enable); - - if (enable) - exaEnableDisableFBAccess (index, enable); -} - -/** - * This will be called during exaDriverInit, giving us the chance to set options - * and hook in our EnableDisableFBAccess. - */ -void -exaDDXDriverInit(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - /* Do NOT use XF86SCRNINFO macro here!! */ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - ExaXorgScreenPrivPtr pScreenPriv; - - pScreenPriv = xcalloc (1, sizeof(ExaXorgScreenPrivRec)); - if (pScreenPriv == NULL) - return; - - pScreenPriv->options = xnfalloc (sizeof(EXAOptions)); - memcpy(pScreenPriv->options, EXAOptions, sizeof(EXAOptions)); - xf86ProcessOptions (pScrn->scrnIndex, pScrn->options, pScreenPriv->options); - - if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) { - if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && - pExaScr->info->offScreenBase < pExaScr->info->memorySize) { - char *heuristicName; - - heuristicName = xf86GetOptValString (pScreenPriv->options, - EXAOPT_MIGRATION_HEURISTIC); - if (heuristicName != NULL) { - if (strcmp(heuristicName, "greedy") == 0) - pExaScr->migration = ExaMigrationGreedy; - else if (strcmp(heuristicName, "always") == 0) - pExaScr->migration = ExaMigrationAlways; - else if (strcmp(heuristicName, "smart") == 0) - pExaScr->migration = ExaMigrationSmart; - else { - xf86DrvMsg (pScreen->myNum, X_WARNING, - "EXA: unknown migration heuristic %s\n", - heuristicName); - } - } - } - - pExaScr->optimize_migration = - xf86ReturnOptValBool(pScreenPriv->options, - EXAOPT_OPTIMIZE_MIGRATION, - TRUE); - } - - if (xf86ReturnOptValBool(pScreenPriv->options, - EXAOPT_NO_COMPOSITE, FALSE)) { - xf86DrvMsg(pScreen->myNum, X_CONFIG, - "EXA: Disabling Composite operation " - "(RENDER acceleration)\n"); - pExaScr->info->CheckComposite = NULL; - pExaScr->info->PrepareComposite = NULL; - } - - if (xf86ReturnOptValBool(pScreenPriv->options, EXAOPT_NO_UTS, FALSE)) { - xf86DrvMsg(pScreen->myNum, X_CONFIG, - "EXA: Disabling UploadToScreen\n"); - pExaScr->info->UploadToScreen = NULL; - } - - if (xf86ReturnOptValBool(pScreenPriv->options, EXAOPT_NO_DFS, FALSE)) { - xf86DrvMsg(pScreen->myNum, X_CONFIG, - "EXA: Disabling DownloadFromScreen\n"); - pExaScr->info->DownloadFromScreen = NULL; - } - - dixSetPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey, pScreenPriv); - - pScreenPriv->SavedEnableDisableFBAccess = pScrn->EnableDisableFBAccess; - pScrn->EnableDisableFBAccess = exaXorgEnableDisableFBAccess; - - pScreenPriv->SavedCloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = exaXorgCloseScreen; - -} - -static XF86ModuleVersionInfo exaVersRec = -{ - "exa", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - EXA_VERSION_MAJOR, EXA_VERSION_MINOR, EXA_VERSION_RELEASE, - ABI_CLASS_VIDEODRV, /* requires the video driver ABI */ - ABI_VIDEODRV_VERSION, - MOD_CLASS_NONE, - {0,0,0,0} -}; - -_X_EXPORT XF86ModuleData exaModuleData = { &exaVersRec, NULL, NULL }; +/* + * Copyright © 2006 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "exa_priv.h" + +#include "xf86str.h" +#include "xf86.h" + +typedef struct _ExaXorgScreenPrivRec { + CloseScreenProcPtr SavedCloseScreen; + EnableDisableFBAccessProcPtr SavedEnableDisableFBAccess; + OptionInfoPtr options; +} ExaXorgScreenPrivRec, *ExaXorgScreenPrivPtr; + +static int exaXorgScreenPrivateKeyIndex; +static DevPrivateKey exaXorgScreenPrivateKey = &exaXorgScreenPrivateKeyIndex; + +typedef enum { + EXAOPT_MIGRATION_HEURISTIC, + EXAOPT_NO_COMPOSITE, + EXAOPT_NO_UTS, + EXAOPT_NO_DFS, + EXAOPT_OPTIMIZE_MIGRATION +} EXAOpts; + +static const OptionInfoRec EXAOptions[] = { + { EXAOPT_MIGRATION_HEURISTIC, "MigrationHeuristic", + OPTV_ANYSTR, {0}, FALSE }, + { EXAOPT_NO_COMPOSITE, "EXANoComposite", + OPTV_BOOLEAN, {0}, FALSE }, + { EXAOPT_NO_UTS, "EXANoUploadToScreen", + OPTV_BOOLEAN, {0}, FALSE }, + { EXAOPT_NO_DFS, "EXANoDownloadFromScreen", + OPTV_BOOLEAN, {0}, FALSE }, + { EXAOPT_OPTIMIZE_MIGRATION, "EXAOptimizeMigration", + OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, + OPTV_NONE, {0}, FALSE } +}; + +static Bool +exaXorgCloseScreen (int i, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + ExaXorgScreenPrivPtr pScreenPriv = (ExaXorgScreenPrivPtr) + dixLookupPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey); + + pScreen->CloseScreen = pScreenPriv->SavedCloseScreen; + + pScrn->EnableDisableFBAccess = pScreenPriv->SavedEnableDisableFBAccess; + + free(pScreenPriv->options); + free(pScreenPriv); + + return pScreen->CloseScreen (i, pScreen); +} + +static void +exaXorgEnableDisableFBAccess (int index, Bool enable) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + ExaXorgScreenPrivPtr pScreenPriv = (ExaXorgScreenPrivPtr) + dixLookupPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey); + + if (!enable) + exaEnableDisableFBAccess (index, enable); + + if (pScreenPriv->SavedEnableDisableFBAccess) + pScreenPriv->SavedEnableDisableFBAccess (index, enable); + + if (enable) + exaEnableDisableFBAccess (index, enable); +} + +/** + * This will be called during exaDriverInit, giving us the chance to set options + * and hook in our EnableDisableFBAccess. + */ +void +exaDDXDriverInit(ScreenPtr pScreen) +{ + ExaScreenPriv(pScreen); + /* Do NOT use XF86SCRNINFO macro here!! */ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ExaXorgScreenPrivPtr pScreenPriv; + + pScreenPriv = calloc(1, sizeof(ExaXorgScreenPrivRec)); + if (pScreenPriv == NULL) + return; + + pScreenPriv->options = xnfalloc (sizeof(EXAOptions)); + memcpy(pScreenPriv->options, EXAOptions, sizeof(EXAOptions)); + xf86ProcessOptions (pScrn->scrnIndex, pScrn->options, pScreenPriv->options); + + if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) { + if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && + pExaScr->info->offScreenBase < pExaScr->info->memorySize) { + char *heuristicName; + + heuristicName = xf86GetOptValString (pScreenPriv->options, + EXAOPT_MIGRATION_HEURISTIC); + if (heuristicName != NULL) { + if (strcmp(heuristicName, "greedy") == 0) + pExaScr->migration = ExaMigrationGreedy; + else if (strcmp(heuristicName, "always") == 0) + pExaScr->migration = ExaMigrationAlways; + else if (strcmp(heuristicName, "smart") == 0) + pExaScr->migration = ExaMigrationSmart; + else { + xf86DrvMsg (pScreen->myNum, X_WARNING, + "EXA: unknown migration heuristic %s\n", + heuristicName); + } + } + } + + pExaScr->optimize_migration = + xf86ReturnOptValBool(pScreenPriv->options, + EXAOPT_OPTIMIZE_MIGRATION, + TRUE); + } + + if (xf86ReturnOptValBool(pScreenPriv->options, + EXAOPT_NO_COMPOSITE, FALSE)) { + xf86DrvMsg(pScreen->myNum, X_CONFIG, + "EXA: Disabling Composite operation " + "(RENDER acceleration)\n"); + pExaScr->info->CheckComposite = NULL; + pExaScr->info->PrepareComposite = NULL; + } + + if (xf86ReturnOptValBool(pScreenPriv->options, EXAOPT_NO_UTS, FALSE)) { + xf86DrvMsg(pScreen->myNum, X_CONFIG, + "EXA: Disabling UploadToScreen\n"); + pExaScr->info->UploadToScreen = NULL; + } + + if (xf86ReturnOptValBool(pScreenPriv->options, EXAOPT_NO_DFS, FALSE)) { + xf86DrvMsg(pScreen->myNum, X_CONFIG, + "EXA: Disabling DownloadFromScreen\n"); + pExaScr->info->DownloadFromScreen = NULL; + } + + dixSetPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey, pScreenPriv); + + pScreenPriv->SavedEnableDisableFBAccess = pScrn->EnableDisableFBAccess; + pScrn->EnableDisableFBAccess = exaXorgEnableDisableFBAccess; + + pScreenPriv->SavedCloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = exaXorgCloseScreen; + +} + +static XF86ModuleVersionInfo exaVersRec = +{ + "exa", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + EXA_VERSION_MAJOR, EXA_VERSION_MINOR, EXA_VERSION_RELEASE, + ABI_CLASS_VIDEODRV, /* requires the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +_X_EXPORT XF86ModuleData exaModuleData = { &exaVersRec, NULL, NULL }; diff --git a/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c b/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c index 880f0a20e..3f7391d50 100644 --- a/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c +++ b/xorg-server/hw/xfree86/fbdevhw/fbdevhw.c @@ -1,1009 +1,1009 @@ -/* all driver need this */ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "xf86.h" -#include "xf86_OSproc.h" - -/* pci stuff */ -#include "xf86PciInfo.h" -#include "xf86Pci.h" - -#include "xf86cmap.h" - -#include "fbdevhw.h" -#include "fbpriv.h" - -#define PAGE_MASK (~(getpagesize() - 1)) - -#include "globals.h" -#include - -#define DEBUG 0 - -#define PAGE_MASK (~(getpagesize() - 1)) - -#if DEBUG -# define TRACE_ENTER(str) ErrorF("fbdevHW: " str " %d\n",pScrn->scrnIndex) -#else -# define TRACE_ENTER(str) -#endif - -/* -------------------------------------------------------------------- */ - -static MODULESETUPPROTO(fbdevhwSetup); - -static XF86ModuleVersionInfo fbdevHWVersRec = -{ - "fbdevhw", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - 0, 0, 2, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_NONE, - {0,0,0,0} -}; - -_X_EXPORT XF86ModuleData fbdevhwModuleData = { - &fbdevHWVersRec, - fbdevhwSetup, - NULL -}; - -static pointer -fbdevhwSetup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - return (pointer)1; -} - -#include -#include -#include -#include -#include -#include -#include -#include - -/* -------------------------------------------------------------------- */ -/* our private data, and two functions to allocate/free this */ - -#define FBDEVHWPTRLVAL(p) (p)->privates[fbdevHWPrivateIndex].ptr -#define FBDEVHWPTR(p) ((fbdevHWPtr)(FBDEVHWPTRLVAL(p))) - -static int fbdevHWPrivateIndex = -1; - -typedef struct { - /* framebuffer device: filename (/dev/fb*), handle, more */ - char* device; - int fd; - void* fbmem; - unsigned int fbmem_len; - unsigned int fboff; - char* mmio; - unsigned int mmio_len; - - /* current hardware state */ - struct fb_fix_screeninfo fix; - struct fb_var_screeninfo var; - - /* saved video mode */ - struct fb_var_screeninfo saved_var; - - /* FIXME: unused??? [geert] */ - struct fb_cmap saved_cmap; - unsigned short *saved_red; - unsigned short *saved_green; - unsigned short *saved_blue; - - /* buildin video mode */ - DisplayModeRec buildin; - -} fbdevHWRec, *fbdevHWPtr; - -Bool -fbdevHWGetRec(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr; - - if (fbdevHWPrivateIndex < 0) - fbdevHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - - if (FBDEVHWPTR(pScrn) != NULL) - return TRUE; - - fPtr = FBDEVHWPTRLVAL(pScrn) = xnfcalloc(sizeof(fbdevHWRec), 1); - return TRUE; -} - -void -fbdevHWFreeRec(ScrnInfoPtr pScrn) -{ - if (fbdevHWPrivateIndex < 0) - return; - if (FBDEVHWPTR(pScrn) == NULL) - return; - xfree(FBDEVHWPTR(pScrn)); - FBDEVHWPTRLVAL(pScrn) = NULL; -} - -int -fbdevHWGetFD(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr; - - fbdevHWGetRec(pScrn); - fPtr = FBDEVHWPTR(pScrn); - - return fPtr->fd; -} - -/* -------------------------------------------------------------------- */ -/* some helpers for printing debug informations */ - -#if DEBUG -static void -print_fbdev_mode(char *txt, struct fb_var_screeninfo *var) -{ - ErrorF( "fbdev %s mode:\t%d %d %d %d %d %d %d %d %d %d %d:%d:%d\n", - txt,var->pixclock, - var->xres, var->right_margin, var->hsync_len, var->left_margin, - var->yres, var->lower_margin, var->vsync_len, var->upper_margin, - var->bits_per_pixel, - var->red.length, var->green.length, var->blue.length); -} - -static void -print_xfree_mode(char *txt, DisplayModePtr mode) -{ - ErrorF( "xfree %s mode:\t%d %d %d %d %d %d %d %d %d\n", - txt,mode->Clock, - mode->HDisplay, mode->HSyncStart, mode->HSyncEnd, mode->HTotal, - mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, mode->VTotal); -} -#endif - -/* -------------------------------------------------------------------- */ -/* Convert timings between the XFree and the Frame Buffer Device */ - -static void -xfree2fbdev_fblayout(ScrnInfoPtr pScrn, struct fb_var_screeninfo *var) -{ - var->xres_virtual = pScrn->displayWidth ? pScrn->displayWidth : - pScrn->virtualX; - var->yres_virtual = pScrn->virtualY; - var->bits_per_pixel = pScrn->bitsPerPixel; - if (pScrn->defaultVisual == TrueColor || - pScrn->defaultVisual == DirectColor) { - var->red.length = pScrn->weight.red; - var->green.length = pScrn->weight.green; - var->blue.length = pScrn->weight.blue; - } else { - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - } -} - -static void -xfree2fbdev_timing(DisplayModePtr mode, struct fb_var_screeninfo *var) -{ - var->xres = mode->HDisplay; - var->yres = mode->VDisplay; - if (var->xres_virtual < var->xres) - var->xres_virtual = var->xres; - if (var->yres_virtual < var->yres) - var->yres_virtual = var->yres; - var->xoffset = var->yoffset = 0; - var->pixclock = mode->Clock ? 1000000000/mode->Clock : 0; - var->right_margin = mode->HSyncStart-mode->HDisplay; - var->hsync_len = mode->HSyncEnd-mode->HSyncStart; - var->left_margin = mode->HTotal-mode->HSyncEnd; - var->lower_margin = mode->VSyncStart-mode->VDisplay; - var->vsync_len = mode->VSyncEnd-mode->VSyncStart; - var->upper_margin = mode->VTotal-mode->VSyncEnd; - var->sync = 0; - if (mode->Flags & V_PHSYNC) - var->sync |= FB_SYNC_HOR_HIGH_ACT; - if (mode->Flags & V_PVSYNC) - var->sync |= FB_SYNC_VERT_HIGH_ACT; - if (mode->Flags & V_PCSYNC) - var->sync |= FB_SYNC_COMP_HIGH_ACT; - if (mode->Flags & V_BCAST) - var->sync |= FB_SYNC_BROADCAST; - if (mode->Flags & V_INTERLACE) - var->vmode = FB_VMODE_INTERLACED; - else if (mode->Flags & V_DBLSCAN) - var->vmode = FB_VMODE_DOUBLE; - else - var->vmode = FB_VMODE_NONINTERLACED; -} - -static Bool -fbdev_modes_equal(struct fb_var_screeninfo *set, struct fb_var_screeninfo *req) -{ - return (set->xres_virtual >= req->xres_virtual && - set->yres_virtual >= req->yres_virtual && - set->bits_per_pixel == req->bits_per_pixel && - set->red.length == req->red.length && - set->green.length == req->green.length && - set->blue.length == req->blue.length && - set->xres == req->xres && set->yres == req->yres && - set->right_margin == req->right_margin && - set->hsync_len == req->hsync_len && - set->left_margin == req->left_margin && - set->lower_margin == req->lower_margin && - set->vsync_len == req->vsync_len && - set->upper_margin == req->upper_margin && - set->sync == req->sync && set->vmode == req->vmode); -} - -static void -fbdev2xfree_timing(struct fb_var_screeninfo *var, DisplayModePtr mode) -{ - mode->Clock = var->pixclock ? 1000000000/var->pixclock : 0; - mode->HDisplay = var->xres; - mode->HSyncStart = mode->HDisplay+var->right_margin; - mode->HSyncEnd = mode->HSyncStart+var->hsync_len; - mode->HTotal = mode->HSyncEnd+var->left_margin; - mode->VDisplay = var->yres; - mode->VSyncStart = mode->VDisplay+var->lower_margin; - mode->VSyncEnd = mode->VSyncStart+var->vsync_len; - mode->VTotal = mode->VSyncEnd+var->upper_margin; - mode->Flags = 0; - mode->Flags |= var->sync & FB_SYNC_HOR_HIGH_ACT ? V_PHSYNC : V_NHSYNC; - mode->Flags |= var->sync & FB_SYNC_VERT_HIGH_ACT ? V_PVSYNC : V_NVSYNC; - mode->Flags |= var->sync & FB_SYNC_COMP_HIGH_ACT ? V_PCSYNC : V_NCSYNC; - if (var->sync & FB_SYNC_BROADCAST) - mode->Flags |= V_BCAST; - if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) - mode->Flags |= V_INTERLACE; - else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) - mode->Flags |= V_DBLSCAN; - mode->SynthClock = mode->Clock; - mode->CrtcHDisplay = mode->HDisplay; - mode->CrtcHSyncStart = mode->HSyncStart; - mode->CrtcHSyncEnd = mode->HSyncEnd; - mode->CrtcHTotal = mode->HTotal; - mode->CrtcVDisplay = mode->VDisplay; - mode->CrtcVSyncStart = mode->VSyncStart; - mode->CrtcVSyncEnd = mode->VSyncEnd; - mode->CrtcVTotal = mode->VTotal; - mode->CrtcHAdjusted = FALSE; - mode->CrtcVAdjusted = FALSE; -} - - -/* -------------------------------------------------------------------- */ -/* open correct framebuffer device */ - -/** - * Try to find the framebuffer device for a given PCI device - */ -static int -fbdev_open_pci(struct pci_device * pPci, char **namep) -{ - struct fb_fix_screeninfo fix; - char filename[256]; - int fd,i,j; - - - /* There are two ways to that we can determine which fb device is - * associated with this PCI device. The more modern way is to look in - * the sysfs directory for the PCI device for a file named - * "graphics/fb*" - */ - - for (i = 0; i < 8; i++) { - sprintf(filename, - "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics/fb%d", - pPci->domain, pPci->bus, pPci->dev, pPci->func, i); - - fd = open(filename, O_RDONLY, 0); - if (fd < 0) { - sprintf(filename, - "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics:fb%d", - pPci->domain, pPci->bus, pPci->dev, pPci->func, i); - fd = open(filename, O_RDONLY, 0); - } - if (fd >= 0) { - close(fd); - sprintf(filename, "/dev/fb%d", i); - - fd = open(filename, O_RDWR, 0); - if (fd != -1) { - if (ioctl(fd, FBIOGET_FSCREENINFO, (void*) & fix) != -1) { - if (namep) { - *namep = xnfalloc(16); - strncpy(*namep,fix.id,16); - } - - return fd; - } - close(fd); - } - } - } - - - /* The other way is to examine the resources associated with each fb - * device and see if there is a match with the PCI device. This technique - * has some problems on certain mixed 64-bit / 32-bit architectures. - * There is a flaw in the fb_fix_screeninfo structure in that it only - * returns the low 32-bits of the address of the resources associated with - * a device. However, on a mixed architecture the base addresses of PCI - * devices, even for 32-bit applications, may be higher than 0x0f0000000. - */ - - for (i = 0; i < 8; i++) { - sprintf(filename,"/dev/fb%d",i); - if (-1 == (fd = open(filename,O_RDWR,0))) { - xf86DrvMsg(-1, X_WARNING, - "open %s: %s\n", filename, strerror(errno)); - continue; - } - if (-1 == ioctl(fd,FBIOGET_FSCREENINFO,(void*)&fix)) { - close(fd); - continue; - } - for (j = 0; j < 6; j++) { - const pciaddr_t res_start = pPci->regions[j].base_addr; - const pciaddr_t res_end = res_start + pPci->regions[j].size; - - if ((0 != fix.smem_len && - (pciaddr_t) fix.smem_start >= res_start && - (pciaddr_t) fix.smem_start < res_end) || - (0 != fix.mmio_len && - (pciaddr_t) fix.mmio_start >= res_start && - (pciaddr_t) fix.mmio_start < res_end)) - break; - } - if (j == 6) { - close(fd); - continue; - } - if (namep) { - *namep = xnfalloc(16); - strncpy(*namep,fix.id,16); - } - return fd; - } - - if (namep) - *namep = NULL; - - xf86DrvMsg(-1, X_ERROR, - "Unable to find a valid framebuffer device\n"); - return -1; -} - -static int -fbdev_open(int scrnIndex, char *dev, char** namep) -{ - struct fb_fix_screeninfo fix; - int fd; - - /* try argument (from XF86Config) first */ - if (dev) { - fd = open(dev,O_RDWR,0); - } else { - /* second: environment variable */ - dev = getenv("FRAMEBUFFER"); - if ((NULL == dev) || ((fd = open(dev,O_RDWR,0)) == -1)) { - /* last try: default device */ - dev = "/dev/fb0"; - fd = open(dev,O_RDWR,0); - } - } - - if (fd == -1) { - xf86DrvMsg(scrnIndex, X_ERROR, - "open %s: %s\n", dev, strerror(errno)); - return -1; - } - - if (namep) { - if (-1 == ioctl(fd,FBIOGET_FSCREENINFO,(void*)(&fix))) { - *namep = NULL; - xf86DrvMsg(scrnIndex, X_ERROR, - "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); - return -1; - } else { - *namep = xnfalloc(16); - strncpy(*namep,fix.id,16); - } - } - return fd; -} - -/* -------------------------------------------------------------------- */ - -Bool -fbdevHWProbe(struct pci_device * pPci, char *device,char **namep) -{ - int fd; - - if (pPci) - fd = fbdev_open_pci(pPci,namep); - else - fd = fbdev_open(-1,device,namep); - - if (-1 == fd) - return FALSE; - close(fd); - return TRUE; -} - -Bool -fbdevHWInit(ScrnInfoPtr pScrn, struct pci_device * pPci, char *device) -{ - fbdevHWPtr fPtr; - - TRACE_ENTER("Init"); - - fbdevHWGetRec(pScrn); - fPtr = FBDEVHWPTR(pScrn); - - /* open device */ - if (pPci) - fPtr->fd = fbdev_open_pci(pPci,NULL); - else - fPtr->fd = fbdev_open(pScrn->scrnIndex,device,NULL); - if (-1 == fPtr->fd) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to open framebuffer device, consult warnings" - " and/or errors above for possible reasons\n" - "\t(you may have to look at the server log to see" - " warnings)\n"); - return FALSE; - } - - /* get current fb device settings */ - if (-1 == ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "ioctl FBIOGET_FSCREENINFO: %s\n", - strerror(errno)); - return FALSE; - } - if (-1 == ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "ioctl FBIOGET_VSCREENINFO: %s\n", - strerror(errno)); - return FALSE; - } - - /* we can use the current settings as "buildin mode" */ - fbdev2xfree_timing(&fPtr->var, &fPtr->buildin); - fPtr->buildin.name = "current"; - fPtr->buildin.next = &fPtr->buildin; - fPtr->buildin.prev = &fPtr->buildin; - fPtr->buildin.type |= M_T_BUILTIN; - - return TRUE; -} - -char* -fbdevHWGetName(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - return fPtr->fix.id; -} - -int -fbdevHWGetDepth(ScrnInfoPtr pScrn, int *fbbpp) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (fbbpp) - *fbbpp = fPtr->var.bits_per_pixel; - - if (fPtr->fix.visual == FB_VISUAL_TRUECOLOR || - fPtr->fix.visual == FB_VISUAL_DIRECTCOLOR) - return fPtr->var.red.length+fPtr->var.green.length+ - fPtr->var.blue.length; - else - return fPtr->var.bits_per_pixel; -} - -int -fbdevHWGetLineLength(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - if (fPtr->fix.line_length) - return fPtr->fix.line_length; - else - return fPtr->var.xres_virtual*fPtr->var.bits_per_pixel/8; -} - -int -fbdevHWGetType(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - return fPtr->fix.type; -} - -int -fbdevHWGetVidmem(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - return fPtr->fix.smem_len; -} - -static Bool -fbdevHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - struct fb_var_screeninfo req_var = fPtr->var, set_var; - - TRACE_ENTER("SetMode"); - - xfree2fbdev_fblayout(pScrn, &req_var); - xfree2fbdev_timing(mode, &req_var); - -#if DEBUG - print_xfree_mode("init", mode); - print_fbdev_mode("init", &req_var); -#endif - - set_var = req_var; - - if (check) - set_var.activate = FB_ACTIVATE_TEST; - - if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void*)(&set_var))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); - return FALSE; - } - - if (!fbdev_modes_equal(&set_var, &req_var)) { - if (!check) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUT_VSCREENINFO succeeded but modified " - "mode\n"); -#if DEBUG - print_fbdev_mode("returned", &set_var); -#endif - return FALSE; - } - - if (!check) - fPtr->var = set_var; - - return TRUE; -} - -void -fbdevHWSetVideoModes(ScrnInfoPtr pScrn) -{ - char **modename; - DisplayModePtr mode,this,last = pScrn->modes; - - TRACE_ENTER("VerifyModes"); - if (NULL == pScrn->display->modes) - return; - - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; - - for (modename = pScrn->display->modes; *modename != NULL; modename++) { - for (mode = pScrn->monitor->Modes; mode != NULL; mode = mode->next) - if (0 == strcmp(mode->name,*modename)) - break; - if (NULL == mode) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "\tmode \"%s\" not found\n", *modename); - continue; - } - - if (!fbdevHWSetMode(pScrn, mode, TRUE)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "\tmode \"%s\" test failed\n", *modename); - continue; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "\tmode \"%s\" ok\n", *modename); - - if (pScrn->virtualX < mode->HDisplay) - pScrn->virtualX = mode->HDisplay; - if (pScrn->virtualY < mode->VDisplay) - pScrn->virtualY = mode->VDisplay; - - if (NULL == pScrn->modes) { - this = pScrn->modes = xf86DuplicateMode(mode); - this->next = this; - this->prev = this; - } else { - this = xf86DuplicateMode(mode); - this->next = pScrn->modes; - this->prev = last; - last->next = this; - pScrn->modes->prev = this; - } - last = this; - } -} - -DisplayModePtr -fbdevHWGetBuildinMode(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - return &fPtr->buildin; -} - -void -fbdevHWUseBuildinMode(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("UseBuildinMode"); - pScrn->modes = &fPtr->buildin; - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; - if (pScrn->virtualX < fPtr->buildin.HDisplay) - pScrn->virtualX = fPtr->buildin.HDisplay; - if (pScrn->virtualY < fPtr->buildin.VDisplay) - pScrn->virtualY = fPtr->buildin.VDisplay; -} - -/* -------------------------------------------------------------------- */ - -static void -calculateFbmem_len(fbdevHWPtr fPtr) -{ - fPtr->fboff = (unsigned long) fPtr->fix.smem_start & ~PAGE_MASK; - fPtr->fbmem_len = (fPtr->fboff+fPtr->fix.smem_len+~PAGE_MASK) & - PAGE_MASK; -} - - -void* -fbdevHWMapVidmem(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("MapVidmem"); - if (NULL == fPtr->fbmem) { - calculateFbmem_len(fPtr); - fPtr->fbmem = mmap(NULL, fPtr->fbmem_len, PROT_READ | PROT_WRITE, - MAP_SHARED, fPtr->fd, 0); - if (-1 == (long)fPtr->fbmem) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "mmap fbmem: %s\n", strerror(errno)); - fPtr->fbmem = NULL; - } else { - /* Perhaps we'd better add fboff to fbmem and return 0 in - fbdevHWLinearOffset()? Of course we then need to mask - fPtr->fbmem with PAGE_MASK in fbdevHWUnmapVidmem() as - well. [geert] */ - } - } - pScrn->memPhysBase = (unsigned long)fPtr->fix.smem_start & (unsigned long)(PAGE_MASK); - pScrn->fbOffset = (unsigned long)fPtr->fix.smem_start & (unsigned long)(~PAGE_MASK); - return fPtr->fbmem; -} - -int -fbdevHWLinearOffset(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("LinearOffset"); - return fPtr->fboff; -} - -Bool -fbdevHWUnmapVidmem(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("UnmapVidmem"); - if (NULL != fPtr->fbmem) { - if (-1 == munmap(fPtr->fbmem, fPtr->fbmem_len)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "munmap fbmem: %s\n", strerror(errno)); - fPtr->fbmem = NULL; - } - return TRUE; -} - -void* -fbdevHWMapMMIO(ScrnInfoPtr pScrn) -{ - unsigned int mmio_off; - - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("MapMMIO"); - if (NULL == fPtr->mmio) { - /* tell the kernel not to use accels to speed up console scrolling */ - fPtr->var.accel_flags = 0; - if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->var))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); - return FALSE; - } - mmio_off = (unsigned long) fPtr->fix.mmio_start & ~PAGE_MASK; - fPtr->mmio_len = (mmio_off+fPtr->fix.mmio_len+~PAGE_MASK) & - PAGE_MASK; - if (NULL == fPtr->fbmem) - calculateFbmem_len(fPtr); - fPtr->mmio = mmap(NULL, fPtr->mmio_len, PROT_READ | PROT_WRITE, - MAP_SHARED, fPtr->fd, fPtr->fbmem_len); - if (-1 == (long)fPtr->mmio) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "mmap mmio: %s\n", strerror(errno)); - fPtr->mmio = NULL; - } else - fPtr->mmio += mmio_off; - } - return fPtr->mmio; -} - -Bool -fbdevHWUnmapMMIO(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("UnmapMMIO"); - if (NULL != fPtr->mmio) { - if (-1 == munmap((void *)((unsigned long)fPtr->mmio & PAGE_MASK), fPtr->mmio_len)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "munmap mmio: %s\n", strerror(errno)); - fPtr->mmio = NULL; - /* FIXME: restore var.accel_flags [geert] */ - } - return TRUE; -} - -/* -------------------------------------------------------------------- */ - -Bool -fbdevHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - pScrn->vtSema = TRUE; - - /* set */ - if (!fbdevHWSetMode(pScrn, mode, FALSE)) - return FALSE; - - /* read back */ - if (0 != ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); - return FALSE; - } - if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); - return FALSE; - } - - if (pScrn->defaultVisual == TrueColor || - pScrn->defaultVisual == DirectColor) { - /* XXX: This is a hack, but it should be a NOP for all the setups that - * worked before and actually seems to fix some others... - */ - pScrn->offset.red = fPtr->var.red.offset; - pScrn->offset.green = fPtr->var.green.offset; - pScrn->offset.blue = fPtr->var.blue.offset; - pScrn->mask.red = ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset; - pScrn->mask.green = ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset; - pScrn->mask.blue = ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset; - } - - return TRUE; -} - -/* -------------------------------------------------------------------- */ -/* video mode save/restore */ - -/* TODO: colormap */ -void -fbdevHWSave(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("Save"); - if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->saved_var))) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); -} - -void -fbdevHWRestore(ScrnInfoPtr pScrn) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("Restore"); - if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->saved_var))) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); -} - -/* -------------------------------------------------------------------- */ -/* callback for xf86HandleColormaps */ - -void -fbdevHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, - LOCO *colors, VisualPtr pVisual) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - struct fb_cmap cmap; - unsigned short red,green,blue; - int i; - - TRACE_ENTER("LoadPalette"); - cmap.len = 1; - cmap.red = &red; - cmap.green = &green; - cmap.blue = &blue; - cmap.transp = NULL; - for (i = 0; i < numColors; i++) { - cmap.start = indices[i]; - red = (colors[indices[i]].red << 8) | - colors[indices[i]].red; - green = (colors[indices[i]].green << 8) | - colors[indices[i]].green; - blue = (colors[indices[i]].blue << 8) | - colors[indices[i]].blue; - if (-1 == ioctl(fPtr->fd,FBIOPUTCMAP,(void*)&cmap)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOPUTCMAP: %s\n", strerror(errno)); - } -} - -/* -------------------------------------------------------------------- */ -/* these can be hooked directly into ScrnInfoRec */ - -ModeStatus -fbdevHWValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - TRACE_ENTER("ValidMode"); - - if (!fbdevHWSetMode(pScrn, mode, TRUE)) - return MODE_BAD; - - return MODE_OK; -} - -Bool -fbdevHWSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - TRACE_ENTER("SwitchMode"); - - if (!fbdevHWSetMode(pScrn, mode, FALSE)) - return FALSE; - - return TRUE; -} - -void -fbdevHWAdjustFrame(int scrnIndex, int x, int y, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - - TRACE_ENTER("AdjustFrame"); - if ( x < 0 || x + fPtr->var.xres > fPtr->var.xres_virtual || - y < 0 || y + fPtr->var.yres > fPtr->var.yres_virtual ) - return; - - fPtr->var.xoffset = x; - fPtr->var.yoffset = y; - if (-1 == ioctl(fPtr->fd,FBIOPAN_DISPLAY,(void*)&fPtr->var)) - xf86DrvMsgVerb(scrnIndex, X_WARNING, 5, - "FBIOPAN_DISPLAY: %s\n", strerror(errno)); -} - -Bool -fbdevHWEnterVT(int scrnIndex, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - TRACE_ENTER("EnterVT"); - if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) - return FALSE; - fbdevHWAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - return TRUE; -} - -void -fbdevHWLeaveVT(int scrnIndex, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - TRACE_ENTER("LeaveVT"); - fbdevHWRestore(pScrn); -} - -void -fbdevHWDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) -{ - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - unsigned long fbmode; - - TRACE_ENTER("DPMSSet"); - if (!pScrn->vtSema) - return; - - switch (mode) { - case DPMSModeOn: - fbmode = 0; - break; - case DPMSModeStandby: - fbmode = 2; - break; - case DPMSModeSuspend: - fbmode = 3; - break; - case DPMSModeOff: - fbmode = 4; - break; - default: - return; - } - - if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)fbmode)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOBLANK: %s\n", strerror(errno)); -} - -Bool -fbdevHWSaveScreen(ScreenPtr pScreen, int mode) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); - unsigned long unblank; - - TRACE_ENTER("HWSaveScreen"); - if (!pScrn->vtSema) - return TRUE; - - unblank = xf86IsUnblank(mode); - - if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)(1-unblank))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "FBIOBLANK: %s\n", strerror(errno)); - return FALSE; - } - - return TRUE; -} - -xf86SwitchModeProc * -fbdevHWSwitchModeWeak(void) { return fbdevHWSwitchMode; } - -xf86AdjustFrameProc * -fbdevHWAdjustFrameWeak(void) { return fbdevHWAdjustFrame; } - -xf86EnterVTProc * -fbdevHWEnterVTWeak(void) { return fbdevHWEnterVT; } - -xf86LeaveVTProc * -fbdevHWLeaveVTWeak(void) { return fbdevHWLeaveVT; } - -xf86ValidModeProc * -fbdevHWValidModeWeak(void) { return fbdevHWValidMode; } - -xf86DPMSSetProc * -fbdevHWDPMSSetWeak(void) { return fbdevHWDPMSSet; } - -xf86LoadPaletteProc * -fbdevHWLoadPaletteWeak(void) { return fbdevHWLoadPalette; } - -SaveScreenProcPtr -fbdevHWSaveScreenWeak(void) { return fbdevHWSaveScreen; } +/* all driver need this */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "xf86.h" +#include "xf86_OSproc.h" + +/* pci stuff */ +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "xf86cmap.h" + +#include "fbdevhw.h" +#include "fbpriv.h" + +#define PAGE_MASK (~(getpagesize() - 1)) + +#include "globals.h" +#include + +#define DEBUG 0 + +#define PAGE_MASK (~(getpagesize() - 1)) + +#if DEBUG +# define TRACE_ENTER(str) ErrorF("fbdevHW: " str " %d\n",pScrn->scrnIndex) +#else +# define TRACE_ENTER(str) +#endif + +/* -------------------------------------------------------------------- */ + +static MODULESETUPPROTO(fbdevhwSetup); + +static XF86ModuleVersionInfo fbdevHWVersRec = +{ + "fbdevhw", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 0, 0, 2, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +_X_EXPORT XF86ModuleData fbdevhwModuleData = { + &fbdevHWVersRec, + fbdevhwSetup, + NULL +}; + +static pointer +fbdevhwSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + return (pointer)1; +} + +#include +#include +#include +#include +#include +#include +#include +#include + +/* -------------------------------------------------------------------- */ +/* our private data, and two functions to allocate/free this */ + +#define FBDEVHWPTRLVAL(p) (p)->privates[fbdevHWPrivateIndex].ptr +#define FBDEVHWPTR(p) ((fbdevHWPtr)(FBDEVHWPTRLVAL(p))) + +static int fbdevHWPrivateIndex = -1; + +typedef struct { + /* framebuffer device: filename (/dev/fb*), handle, more */ + char* device; + int fd; + void* fbmem; + unsigned int fbmem_len; + unsigned int fboff; + char* mmio; + unsigned int mmio_len; + + /* current hardware state */ + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + + /* saved video mode */ + struct fb_var_screeninfo saved_var; + + /* FIXME: unused??? [geert] */ + struct fb_cmap saved_cmap; + unsigned short *saved_red; + unsigned short *saved_green; + unsigned short *saved_blue; + + /* buildin video mode */ + DisplayModeRec buildin; + +} fbdevHWRec, *fbdevHWPtr; + +Bool +fbdevHWGetRec(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr; + + if (fbdevHWPrivateIndex < 0) + fbdevHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + + if (FBDEVHWPTR(pScrn) != NULL) + return TRUE; + + fPtr = FBDEVHWPTRLVAL(pScrn) = xnfcalloc(sizeof(fbdevHWRec), 1); + return TRUE; +} + +void +fbdevHWFreeRec(ScrnInfoPtr pScrn) +{ + if (fbdevHWPrivateIndex < 0) + return; + if (FBDEVHWPTR(pScrn) == NULL) + return; + free(FBDEVHWPTR(pScrn)); + FBDEVHWPTRLVAL(pScrn) = NULL; +} + +int +fbdevHWGetFD(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr; + + fbdevHWGetRec(pScrn); + fPtr = FBDEVHWPTR(pScrn); + + return fPtr->fd; +} + +/* -------------------------------------------------------------------- */ +/* some helpers for printing debug informations */ + +#if DEBUG +static void +print_fbdev_mode(char *txt, struct fb_var_screeninfo *var) +{ + ErrorF( "fbdev %s mode:\t%d %d %d %d %d %d %d %d %d %d %d:%d:%d\n", + txt,var->pixclock, + var->xres, var->right_margin, var->hsync_len, var->left_margin, + var->yres, var->lower_margin, var->vsync_len, var->upper_margin, + var->bits_per_pixel, + var->red.length, var->green.length, var->blue.length); +} + +static void +print_xfree_mode(char *txt, DisplayModePtr mode) +{ + ErrorF( "xfree %s mode:\t%d %d %d %d %d %d %d %d %d\n", + txt,mode->Clock, + mode->HDisplay, mode->HSyncStart, mode->HSyncEnd, mode->HTotal, + mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, mode->VTotal); +} +#endif + +/* -------------------------------------------------------------------- */ +/* Convert timings between the XFree and the Frame Buffer Device */ + +static void +xfree2fbdev_fblayout(ScrnInfoPtr pScrn, struct fb_var_screeninfo *var) +{ + var->xres_virtual = pScrn->displayWidth ? pScrn->displayWidth : + pScrn->virtualX; + var->yres_virtual = pScrn->virtualY; + var->bits_per_pixel = pScrn->bitsPerPixel; + if (pScrn->defaultVisual == TrueColor || + pScrn->defaultVisual == DirectColor) { + var->red.length = pScrn->weight.red; + var->green.length = pScrn->weight.green; + var->blue.length = pScrn->weight.blue; + } else { + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + } +} + +static void +xfree2fbdev_timing(DisplayModePtr mode, struct fb_var_screeninfo *var) +{ + var->xres = mode->HDisplay; + var->yres = mode->VDisplay; + if (var->xres_virtual < var->xres) + var->xres_virtual = var->xres; + if (var->yres_virtual < var->yres) + var->yres_virtual = var->yres; + var->xoffset = var->yoffset = 0; + var->pixclock = mode->Clock ? 1000000000/mode->Clock : 0; + var->right_margin = mode->HSyncStart-mode->HDisplay; + var->hsync_len = mode->HSyncEnd-mode->HSyncStart; + var->left_margin = mode->HTotal-mode->HSyncEnd; + var->lower_margin = mode->VSyncStart-mode->VDisplay; + var->vsync_len = mode->VSyncEnd-mode->VSyncStart; + var->upper_margin = mode->VTotal-mode->VSyncEnd; + var->sync = 0; + if (mode->Flags & V_PHSYNC) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (mode->Flags & V_PVSYNC) + var->sync |= FB_SYNC_VERT_HIGH_ACT; + if (mode->Flags & V_PCSYNC) + var->sync |= FB_SYNC_COMP_HIGH_ACT; + if (mode->Flags & V_BCAST) + var->sync |= FB_SYNC_BROADCAST; + if (mode->Flags & V_INTERLACE) + var->vmode = FB_VMODE_INTERLACED; + else if (mode->Flags & V_DBLSCAN) + var->vmode = FB_VMODE_DOUBLE; + else + var->vmode = FB_VMODE_NONINTERLACED; +} + +static Bool +fbdev_modes_equal(struct fb_var_screeninfo *set, struct fb_var_screeninfo *req) +{ + return (set->xres_virtual >= req->xres_virtual && + set->yres_virtual >= req->yres_virtual && + set->bits_per_pixel == req->bits_per_pixel && + set->red.length == req->red.length && + set->green.length == req->green.length && + set->blue.length == req->blue.length && + set->xres == req->xres && set->yres == req->yres && + set->right_margin == req->right_margin && + set->hsync_len == req->hsync_len && + set->left_margin == req->left_margin && + set->lower_margin == req->lower_margin && + set->vsync_len == req->vsync_len && + set->upper_margin == req->upper_margin && + set->sync == req->sync && set->vmode == req->vmode); +} + +static void +fbdev2xfree_timing(struct fb_var_screeninfo *var, DisplayModePtr mode) +{ + mode->Clock = var->pixclock ? 1000000000/var->pixclock : 0; + mode->HDisplay = var->xres; + mode->HSyncStart = mode->HDisplay+var->right_margin; + mode->HSyncEnd = mode->HSyncStart+var->hsync_len; + mode->HTotal = mode->HSyncEnd+var->left_margin; + mode->VDisplay = var->yres; + mode->VSyncStart = mode->VDisplay+var->lower_margin; + mode->VSyncEnd = mode->VSyncStart+var->vsync_len; + mode->VTotal = mode->VSyncEnd+var->upper_margin; + mode->Flags = 0; + mode->Flags |= var->sync & FB_SYNC_HOR_HIGH_ACT ? V_PHSYNC : V_NHSYNC; + mode->Flags |= var->sync & FB_SYNC_VERT_HIGH_ACT ? V_PVSYNC : V_NVSYNC; + mode->Flags |= var->sync & FB_SYNC_COMP_HIGH_ACT ? V_PCSYNC : V_NCSYNC; + if (var->sync & FB_SYNC_BROADCAST) + mode->Flags |= V_BCAST; + if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) + mode->Flags |= V_INTERLACE; + else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) + mode->Flags |= V_DBLSCAN; + mode->SynthClock = mode->Clock; + mode->CrtcHDisplay = mode->HDisplay; + mode->CrtcHSyncStart = mode->HSyncStart; + mode->CrtcHSyncEnd = mode->HSyncEnd; + mode->CrtcHTotal = mode->HTotal; + mode->CrtcVDisplay = mode->VDisplay; + mode->CrtcVSyncStart = mode->VSyncStart; + mode->CrtcVSyncEnd = mode->VSyncEnd; + mode->CrtcVTotal = mode->VTotal; + mode->CrtcHAdjusted = FALSE; + mode->CrtcVAdjusted = FALSE; +} + + +/* -------------------------------------------------------------------- */ +/* open correct framebuffer device */ + +/** + * Try to find the framebuffer device for a given PCI device + */ +static int +fbdev_open_pci(struct pci_device * pPci, char **namep) +{ + struct fb_fix_screeninfo fix; + char filename[256]; + int fd,i,j; + + + /* There are two ways to that we can determine which fb device is + * associated with this PCI device. The more modern way is to look in + * the sysfs directory for the PCI device for a file named + * "graphics/fb*" + */ + + for (i = 0; i < 8; i++) { + sprintf(filename, + "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics/fb%d", + pPci->domain, pPci->bus, pPci->dev, pPci->func, i); + + fd = open(filename, O_RDONLY, 0); + if (fd < 0) { + sprintf(filename, + "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics:fb%d", + pPci->domain, pPci->bus, pPci->dev, pPci->func, i); + fd = open(filename, O_RDONLY, 0); + } + if (fd >= 0) { + close(fd); + sprintf(filename, "/dev/fb%d", i); + + fd = open(filename, O_RDWR, 0); + if (fd != -1) { + if (ioctl(fd, FBIOGET_FSCREENINFO, (void*) & fix) != -1) { + if (namep) { + *namep = xnfalloc(16); + strncpy(*namep,fix.id,16); + } + + return fd; + } + close(fd); + } + } + } + + + /* The other way is to examine the resources associated with each fb + * device and see if there is a match with the PCI device. This technique + * has some problems on certain mixed 64-bit / 32-bit architectures. + * There is a flaw in the fb_fix_screeninfo structure in that it only + * returns the low 32-bits of the address of the resources associated with + * a device. However, on a mixed architecture the base addresses of PCI + * devices, even for 32-bit applications, may be higher than 0x0f0000000. + */ + + for (i = 0; i < 8; i++) { + sprintf(filename,"/dev/fb%d",i); + if (-1 == (fd = open(filename,O_RDWR,0))) { + xf86DrvMsg(-1, X_WARNING, + "open %s: %s\n", filename, strerror(errno)); + continue; + } + if (-1 == ioctl(fd,FBIOGET_FSCREENINFO,(void*)&fix)) { + close(fd); + continue; + } + for (j = 0; j < 6; j++) { + const pciaddr_t res_start = pPci->regions[j].base_addr; + const pciaddr_t res_end = res_start + pPci->regions[j].size; + + if ((0 != fix.smem_len && + (pciaddr_t) fix.smem_start >= res_start && + (pciaddr_t) fix.smem_start < res_end) || + (0 != fix.mmio_len && + (pciaddr_t) fix.mmio_start >= res_start && + (pciaddr_t) fix.mmio_start < res_end)) + break; + } + if (j == 6) { + close(fd); + continue; + } + if (namep) { + *namep = xnfalloc(16); + strncpy(*namep,fix.id,16); + } + return fd; + } + + if (namep) + *namep = NULL; + + xf86DrvMsg(-1, X_ERROR, + "Unable to find a valid framebuffer device\n"); + return -1; +} + +static int +fbdev_open(int scrnIndex, char *dev, char** namep) +{ + struct fb_fix_screeninfo fix; + int fd; + + /* try argument (from XF86Config) first */ + if (dev) { + fd = open(dev,O_RDWR,0); + } else { + /* second: environment variable */ + dev = getenv("FRAMEBUFFER"); + if ((NULL == dev) || ((fd = open(dev,O_RDWR,0)) == -1)) { + /* last try: default device */ + dev = "/dev/fb0"; + fd = open(dev,O_RDWR,0); + } + } + + if (fd == -1) { + xf86DrvMsg(scrnIndex, X_ERROR, + "open %s: %s\n", dev, strerror(errno)); + return -1; + } + + if (namep) { + if (-1 == ioctl(fd,FBIOGET_FSCREENINFO,(void*)(&fix))) { + *namep = NULL; + xf86DrvMsg(scrnIndex, X_ERROR, + "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + return -1; + } else { + *namep = xnfalloc(16); + strncpy(*namep,fix.id,16); + } + } + return fd; +} + +/* -------------------------------------------------------------------- */ + +Bool +fbdevHWProbe(struct pci_device * pPci, char *device,char **namep) +{ + int fd; + + if (pPci) + fd = fbdev_open_pci(pPci,namep); + else + fd = fbdev_open(-1,device,namep); + + if (-1 == fd) + return FALSE; + close(fd); + return TRUE; +} + +Bool +fbdevHWInit(ScrnInfoPtr pScrn, struct pci_device * pPci, char *device) +{ + fbdevHWPtr fPtr; + + TRACE_ENTER("Init"); + + fbdevHWGetRec(pScrn); + fPtr = FBDEVHWPTR(pScrn); + + /* open device */ + if (pPci) + fPtr->fd = fbdev_open_pci(pPci,NULL); + else + fPtr->fd = fbdev_open(pScrn->scrnIndex,device,NULL); + if (-1 == fPtr->fd) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to open framebuffer device, consult warnings" + " and/or errors above for possible reasons\n" + "\t(you may have to look at the server log to see" + " warnings)\n"); + return FALSE; + } + + /* get current fb device settings */ + if (-1 == ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ioctl FBIOGET_FSCREENINFO: %s\n", + strerror(errno)); + return FALSE; + } + if (-1 == ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "ioctl FBIOGET_VSCREENINFO: %s\n", + strerror(errno)); + return FALSE; + } + + /* we can use the current settings as "buildin mode" */ + fbdev2xfree_timing(&fPtr->var, &fPtr->buildin); + fPtr->buildin.name = "current"; + fPtr->buildin.next = &fPtr->buildin; + fPtr->buildin.prev = &fPtr->buildin; + fPtr->buildin.type |= M_T_BUILTIN; + + return TRUE; +} + +char* +fbdevHWGetName(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + return fPtr->fix.id; +} + +int +fbdevHWGetDepth(ScrnInfoPtr pScrn, int *fbbpp) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (fbbpp) + *fbbpp = fPtr->var.bits_per_pixel; + + if (fPtr->fix.visual == FB_VISUAL_TRUECOLOR || + fPtr->fix.visual == FB_VISUAL_DIRECTCOLOR) + return fPtr->var.red.length+fPtr->var.green.length+ + fPtr->var.blue.length; + else + return fPtr->var.bits_per_pixel; +} + +int +fbdevHWGetLineLength(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + if (fPtr->fix.line_length) + return fPtr->fix.line_length; + else + return fPtr->var.xres_virtual*fPtr->var.bits_per_pixel/8; +} + +int +fbdevHWGetType(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + return fPtr->fix.type; +} + +int +fbdevHWGetVidmem(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + return fPtr->fix.smem_len; +} + +static Bool +fbdevHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + struct fb_var_screeninfo req_var = fPtr->var, set_var; + + TRACE_ENTER("SetMode"); + + xfree2fbdev_fblayout(pScrn, &req_var); + xfree2fbdev_timing(mode, &req_var); + +#if DEBUG + print_xfree_mode("init", mode); + print_fbdev_mode("init", &req_var); +#endif + + set_var = req_var; + + if (check) + set_var.activate = FB_ACTIVATE_TEST; + + if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void*)(&set_var))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + + if (!fbdev_modes_equal(&set_var, &req_var)) { + if (!check) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUT_VSCREENINFO succeeded but modified " + "mode\n"); +#if DEBUG + print_fbdev_mode("returned", &set_var); +#endif + return FALSE; + } + + if (!check) + fPtr->var = set_var; + + return TRUE; +} + +void +fbdevHWSetVideoModes(ScrnInfoPtr pScrn) +{ + char **modename; + DisplayModePtr mode,this,last = pScrn->modes; + + TRACE_ENTER("VerifyModes"); + if (NULL == pScrn->display->modes) + return; + + pScrn->virtualX = pScrn->display->virtualX; + pScrn->virtualY = pScrn->display->virtualY; + + for (modename = pScrn->display->modes; *modename != NULL; modename++) { + for (mode = pScrn->monitor->Modes; mode != NULL; mode = mode->next) + if (0 == strcmp(mode->name,*modename)) + break; + if (NULL == mode) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\tmode \"%s\" not found\n", *modename); + continue; + } + + if (!fbdevHWSetMode(pScrn, mode, TRUE)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\tmode \"%s\" test failed\n", *modename); + continue; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "\tmode \"%s\" ok\n", *modename); + + if (pScrn->virtualX < mode->HDisplay) + pScrn->virtualX = mode->HDisplay; + if (pScrn->virtualY < mode->VDisplay) + pScrn->virtualY = mode->VDisplay; + + if (NULL == pScrn->modes) { + this = pScrn->modes = xf86DuplicateMode(mode); + this->next = this; + this->prev = this; + } else { + this = xf86DuplicateMode(mode); + this->next = pScrn->modes; + this->prev = last; + last->next = this; + pScrn->modes->prev = this; + } + last = this; + } +} + +DisplayModePtr +fbdevHWGetBuildinMode(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + return &fPtr->buildin; +} + +void +fbdevHWUseBuildinMode(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("UseBuildinMode"); + pScrn->modes = &fPtr->buildin; + pScrn->virtualX = pScrn->display->virtualX; + pScrn->virtualY = pScrn->display->virtualY; + if (pScrn->virtualX < fPtr->buildin.HDisplay) + pScrn->virtualX = fPtr->buildin.HDisplay; + if (pScrn->virtualY < fPtr->buildin.VDisplay) + pScrn->virtualY = fPtr->buildin.VDisplay; +} + +/* -------------------------------------------------------------------- */ + +static void +calculateFbmem_len(fbdevHWPtr fPtr) +{ + fPtr->fboff = (unsigned long) fPtr->fix.smem_start & ~PAGE_MASK; + fPtr->fbmem_len = (fPtr->fboff+fPtr->fix.smem_len+~PAGE_MASK) & + PAGE_MASK; +} + + +void* +fbdevHWMapVidmem(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("MapVidmem"); + if (NULL == fPtr->fbmem) { + calculateFbmem_len(fPtr); + fPtr->fbmem = mmap(NULL, fPtr->fbmem_len, PROT_READ | PROT_WRITE, + MAP_SHARED, fPtr->fd, 0); + if (-1 == (long)fPtr->fbmem) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "mmap fbmem: %s\n", strerror(errno)); + fPtr->fbmem = NULL; + } else { + /* Perhaps we'd better add fboff to fbmem and return 0 in + fbdevHWLinearOffset()? Of course we then need to mask + fPtr->fbmem with PAGE_MASK in fbdevHWUnmapVidmem() as + well. [geert] */ + } + } + pScrn->memPhysBase = (unsigned long)fPtr->fix.smem_start & (unsigned long)(PAGE_MASK); + pScrn->fbOffset = (unsigned long)fPtr->fix.smem_start & (unsigned long)(~PAGE_MASK); + return fPtr->fbmem; +} + +int +fbdevHWLinearOffset(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("LinearOffset"); + return fPtr->fboff; +} + +Bool +fbdevHWUnmapVidmem(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("UnmapVidmem"); + if (NULL != fPtr->fbmem) { + if (-1 == munmap(fPtr->fbmem, fPtr->fbmem_len)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "munmap fbmem: %s\n", strerror(errno)); + fPtr->fbmem = NULL; + } + return TRUE; +} + +void* +fbdevHWMapMMIO(ScrnInfoPtr pScrn) +{ + unsigned int mmio_off; + + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("MapMMIO"); + if (NULL == fPtr->mmio) { + /* tell the kernel not to use accels to speed up console scrolling */ + fPtr->var.accel_flags = 0; + if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->var))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + mmio_off = (unsigned long) fPtr->fix.mmio_start & ~PAGE_MASK; + fPtr->mmio_len = (mmio_off+fPtr->fix.mmio_len+~PAGE_MASK) & + PAGE_MASK; + if (NULL == fPtr->fbmem) + calculateFbmem_len(fPtr); + fPtr->mmio = mmap(NULL, fPtr->mmio_len, PROT_READ | PROT_WRITE, + MAP_SHARED, fPtr->fd, fPtr->fbmem_len); + if (-1 == (long)fPtr->mmio) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "mmap mmio: %s\n", strerror(errno)); + fPtr->mmio = NULL; + } else + fPtr->mmio += mmio_off; + } + return fPtr->mmio; +} + +Bool +fbdevHWUnmapMMIO(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("UnmapMMIO"); + if (NULL != fPtr->mmio) { + if (-1 == munmap((void *)((unsigned long)fPtr->mmio & PAGE_MASK), fPtr->mmio_len)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "munmap mmio: %s\n", strerror(errno)); + fPtr->mmio = NULL; + /* FIXME: restore var.accel_flags [geert] */ + } + return TRUE; +} + +/* -------------------------------------------------------------------- */ + +Bool +fbdevHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + pScrn->vtSema = TRUE; + + /* set */ + if (!fbdevHWSetMode(pScrn, mode, FALSE)) + return FALSE; + + /* read back */ + if (0 != ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->var))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); + return FALSE; + } + + if (pScrn->defaultVisual == TrueColor || + pScrn->defaultVisual == DirectColor) { + /* XXX: This is a hack, but it should be a NOP for all the setups that + * worked before and actually seems to fix some others... + */ + pScrn->offset.red = fPtr->var.red.offset; + pScrn->offset.green = fPtr->var.green.offset; + pScrn->offset.blue = fPtr->var.blue.offset; + pScrn->mask.red = ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset; + pScrn->mask.green = ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset; + pScrn->mask.blue = ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset; + } + + return TRUE; +} + +/* -------------------------------------------------------------------- */ +/* video mode save/restore */ + +/* TODO: colormap */ +void +fbdevHWSave(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("Save"); + if (0 != ioctl(fPtr->fd,FBIOGET_VSCREENINFO,(void*)(&fPtr->saved_var))) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); +} + +void +fbdevHWRestore(ScrnInfoPtr pScrn) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("Restore"); + if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->saved_var))) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); +} + +/* -------------------------------------------------------------------- */ +/* callback for xf86HandleColormaps */ + +void +fbdevHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO *colors, VisualPtr pVisual) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + struct fb_cmap cmap; + unsigned short red,green,blue; + int i; + + TRACE_ENTER("LoadPalette"); + cmap.len = 1; + cmap.red = &red; + cmap.green = &green; + cmap.blue = &blue; + cmap.transp = NULL; + for (i = 0; i < numColors; i++) { + cmap.start = indices[i]; + red = (colors[indices[i]].red << 8) | + colors[indices[i]].red; + green = (colors[indices[i]].green << 8) | + colors[indices[i]].green; + blue = (colors[indices[i]].blue << 8) | + colors[indices[i]].blue; + if (-1 == ioctl(fPtr->fd,FBIOPUTCMAP,(void*)&cmap)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOPUTCMAP: %s\n", strerror(errno)); + } +} + +/* -------------------------------------------------------------------- */ +/* these can be hooked directly into ScrnInfoRec */ + +ModeStatus +fbdevHWValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + TRACE_ENTER("ValidMode"); + + if (!fbdevHWSetMode(pScrn, mode, TRUE)) + return MODE_BAD; + + return MODE_OK; +} + +Bool +fbdevHWSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + TRACE_ENTER("SwitchMode"); + + if (!fbdevHWSetMode(pScrn, mode, FALSE)) + return FALSE; + + return TRUE; +} + +void +fbdevHWAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + + TRACE_ENTER("AdjustFrame"); + if ( x < 0 || x + fPtr->var.xres > fPtr->var.xres_virtual || + y < 0 || y + fPtr->var.yres > fPtr->var.yres_virtual ) + return; + + fPtr->var.xoffset = x; + fPtr->var.yoffset = y; + if (-1 == ioctl(fPtr->fd,FBIOPAN_DISPLAY,(void*)&fPtr->var)) + xf86DrvMsgVerb(scrnIndex, X_WARNING, 5, + "FBIOPAN_DISPLAY: %s\n", strerror(errno)); +} + +Bool +fbdevHWEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + TRACE_ENTER("EnterVT"); + if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) + return FALSE; + fbdevHWAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + return TRUE; +} + +void +fbdevHWLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + + TRACE_ENTER("LeaveVT"); + fbdevHWRestore(pScrn); +} + +void +fbdevHWDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) +{ + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + unsigned long fbmode; + + TRACE_ENTER("DPMSSet"); + if (!pScrn->vtSema) + return; + + switch (mode) { + case DPMSModeOn: + fbmode = 0; + break; + case DPMSModeStandby: + fbmode = 2; + break; + case DPMSModeSuspend: + fbmode = 3; + break; + case DPMSModeOff: + fbmode = 4; + break; + default: + return; + } + + if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)fbmode)) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOBLANK: %s\n", strerror(errno)); +} + +Bool +fbdevHWSaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); + unsigned long unblank; + + TRACE_ENTER("HWSaveScreen"); + if (!pScrn->vtSema) + return TRUE; + + unblank = xf86IsUnblank(mode); + + if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *)(1-unblank))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "FBIOBLANK: %s\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + +xf86SwitchModeProc * +fbdevHWSwitchModeWeak(void) { return fbdevHWSwitchMode; } + +xf86AdjustFrameProc * +fbdevHWAdjustFrameWeak(void) { return fbdevHWAdjustFrame; } + +xf86EnterVTProc * +fbdevHWEnterVTWeak(void) { return fbdevHWEnterVT; } + +xf86LeaveVTProc * +fbdevHWLeaveVTWeak(void) { return fbdevHWLeaveVT; } + +xf86ValidModeProc * +fbdevHWValidModeWeak(void) { return fbdevHWValidMode; } + +xf86DPMSSetProc * +fbdevHWDPMSSetWeak(void) { return fbdevHWDPMSSet; } + +xf86LoadPaletteProc * +fbdevHWLoadPaletteWeak(void) { return fbdevHWLoadPalette; } + +SaveScreenProcPtr +fbdevHWSaveScreenWeak(void) { return fbdevHWSaveScreen; } diff --git a/xorg-server/hw/xfree86/i2c/bt829.c b/xorg-server/hw/xfree86/i2c/bt829.c index 3963ecf47..64c711681 100644 --- a/xorg-server/hw/xfree86/i2c/bt829.c +++ b/xorg-server/hw/xfree86/i2c/bt829.c @@ -1,745 +1,745 @@ -/* TODO: clean up/fix CC code */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "xf86.h" -#include "xf86i2c.h" -#include "bt829.h" -#include "i2c_def.h" - -/* Changing the following settings (especially VCROP) may */ -/* require modifying code that calls this driver. */ -#define HCROP 0 /* amount to crop from the left and right edges */ -#define VCROP 0 /* amount to crop from the top and bottom edges */ - -#define BTVERSION (bt->id>>4) - -#define H(X) ( ((X)>>8) & 0xFF ) -#define L(X) ( (X) & 0xFF ) - -#define LIMIT(X,A,B) (((X)<(A)) ? (A) : ((X)>(B)) ? (B) : (X) ) - -/* Bt829 family chip ID's */ -#define BT815 0x02 -#define BT817 0x06 -#define BT819 0x07 -#define BT827 0x0C -#define BT829 0x0E - -/* Bt829 registers */ -#define STATUS 0x00 /* Device Status */ -#define IFORM 0x01 /* Input Format */ -#define TDEC 0x02 /* Temporal Decimation */ -#define CROP 0x03 /* MSB Cropping */ -#define VDELAY_LO 0x04 /* Vertical Delay */ -#define VACTIVE_LO 0x05 /* Vertical Active */ -#define HDELAY_LO 0x06 /* Horizontal Delay */ -#define HACTIVE_LO 0x07 /* Horizontal Active */ -#define HSCALE_HI 0x08 /* Horizontal Scaling */ -#define HSCALE_LO 0x09 /* Horizontal Scaling */ -#define BRIGHT 0x0A /* Brightness Control */ -#define CONTROL 0x0B /* Miscellaneous Control */ -#define CONTRAST_LO 0x0C /* Luma Gain (Contrast) */ -#define SAT_U_LO 0x0D /* Chroma (U) Gain (Saturation) */ -#define SAT_V_LO 0x0E /* Chroma (V) Gain (Saturation) */ -#define HUE 0x0F /* Hue Control */ -#define SCLOOP 0x10 /* SC Loop Control */ -#define WC_UP 0x11 /* White Crush Up Count */ -#define OFORM 0x12 /* Output Format */ -#define VSCALE_HI 0x13 /* Vertical Scaling */ -#define VSCALE_LO 0x14 /* Vertical Scaling */ -#define TEST 0x15 /* Test Control */ -#define VPOLE 0x16 /* Video Timing Polarity */ -#define IDCODE 0x17 /* ID Code */ -#define ADELAY 0x18 /* AGC Delay */ -#define BDELAY 0x19 /* Burst Gate Delay */ -#define ADC 0x1A /* ADC Interface */ -#define VTC 0x1B /* Video Timing Control */ -#define CC_STATUS 0x1C /* Extended Data Services/Closed Capt Status */ -#define CC_DATA 0x1D /* Extended Data Services/Closed Capt Data */ -#define WC_DN 0x1E /* White Crush Down Count */ -#define SRESET 0x1F /* Software Reset */ -#define P_IO 0x3F /* Programmable I/O */ - -static CARD8 btread(BT829Ptr bt, CARD8 reg) -{ - CARD8 v; - - I2C_WriteRead(&(bt->d), ®, 1, &v, 1); - - return v; -} - -static void btwrite(BT829Ptr bt, CARD8 reg, CARD8 val) -{ - CARD8 data[2]; - - data[0] = reg; - data[1] = val; - I2C_WriteRead(&(bt->d), data, 2, NULL, 0); -} - -/* - * Register access - */ -static void btwrite_status(BT829Ptr bt) /* STATUS */ -{ - btwrite(bt, STATUS, 0x00); /* clear */ -} - -static void btwrite_iform(BT829Ptr bt) /* IFORM */ -{ - int xtsel; - - switch (bt->format) { - case BT829_NTSC: - case BT829_NTSC_JAPAN: - case BT829_PAL_M: - case BT829_PAL_N_COMB: /* gatos says xtsel = 2 */ - xtsel = 1; - break; - case BT829_PAL: - case BT829_PAL_N: - case BT829_SECAM: - xtsel = 2; - break; - default: /* shouldn't get here */ - xtsel = 3; /* hardware default */ - break; - } - - btwrite(bt, IFORM, (bt->mux<<5) | (xtsel<<3) | bt->format); -} - -static void btwrite_tdec(BT829Ptr bt) /* TDEC */ -{ - /* use default */ -} - -static void btwrite_crop(BT829Ptr bt) /* CROP */ -{ - btwrite(bt, CROP, (H(bt->vdelay)<<6) | (H(bt->vactive)<<4) | - (H(bt->hdelay)<<2) | H(bt->width)); -} - -static void btwrite_vdelay_lo(BT829Ptr bt) /* VDELAY_LO */ -{ - btwrite(bt, VDELAY_LO, L(bt->vdelay)); -} - -static void btwrite_vactive_lo(BT829Ptr bt) /* VACTIVE_LO */ -{ - btwrite(bt, VACTIVE_LO, L(bt->vactive)); -} - -static void btwrite_hdelay_lo(BT829Ptr bt) /* HDELAY_LO */ -{ - btwrite(bt, HDELAY_LO, L(bt->hdelay)); -} - -static void btwrite_hactive_lo(BT829Ptr bt) /* HACTIVE_LO */ -{ - btwrite(bt, HACTIVE_LO, L(bt->width)); -} - -static void btwrite_hscale_hi(BT829Ptr bt) /* HSCALE_HI */ -{ - btwrite(bt, HSCALE_HI, H(bt->hscale)); -} - -static void btwrite_hscale_lo(BT829Ptr bt) /* HSCALE_LO */ -{ - btwrite(bt, HSCALE_LO, L(bt->hscale)); -} - -static void btwrite_bright(BT829Ptr bt) /* BRIGHT */ -{ - btwrite(bt, BRIGHT, bt->brightness); -} - -static void btwrite_control(BT829Ptr bt) /* CONTROL */ -{ - int ldec; - - /* The data sheet says ldec should always be 0 for SECAM */ - /* but the picture quality is better with ldec = 1 */ - ldec = (bt->width > 360); /* gatos says 384 */ - - btwrite(bt, CONTROL, - ((bt->mux==bt->svideo_mux) ? 0xC0:0x00) | /* LNOTCH and COMP */ - (ldec<<5) | (H(bt->contrast)<<2) | (H(bt->sat_u)<<1) | H(bt->sat_v)); -} - -static void btwrite_contrast_lo(BT829Ptr bt) /* CONTRAST_LO */ -{ - btwrite(bt, CONTRAST_LO, L(bt->contrast)); -} - -static void btwrite_sat_u_lo(BT829Ptr bt) /* SAT_U_LO */ -{ - btwrite(bt, SAT_U_LO, L(bt->sat_u)); -} - -static void btwrite_sat_v_lo(BT829Ptr bt) /* SAT_V_LO */ -{ - btwrite(bt, SAT_V_LO, L(bt->sat_v)); -} - -static void btwrite_hue(BT829Ptr bt) /* HUE */ -{ - btwrite(bt, HUE, bt->hue); -} - -static void btwrite_scloop(BT829Ptr bt) /* SCLOOP */ -{ - if (BTVERSION >= BT827) { - btwrite(bt, SCLOOP, - (bt->format==BT829_SECAM) ? 0x10:0x00 /* QCIF or AUTO */ - ); - } -} - -static void btwrite_wc_up(BT829Ptr bt) /* WC_UP */ -{ - if (BTVERSION >= BT827) { - /* use default */ - } -} - -static void btwrite_oform(BT829Ptr bt) /* OFORM */ -{ - btwrite(bt, OFORM, (bt->code<<3) | (bt->len<<2) | - 0x02 /* RANGE = 0, CORE = 0, VBI_FRAME = 0, OES = 2 (default) */ - ); -} - -static void btwrite_vscale_hi(BT829Ptr bt) /* VSCALE_HI */ -{ - btwrite(bt, VSCALE_HI, H(bt->vscale) | - 0x60 /* YCOMB = 0, COMB = 1, INT = 1 (default) */ - ); -} - -static void btwrite_vscale_lo(BT829Ptr bt) /* VSCALE_LO */ -{ - btwrite(bt, VSCALE_LO, L(bt->vscale)); -} - -/* TEST should not be written to */ - -static void btwrite_vpole(BT829Ptr bt) /* VPOLE */ -{ - btwrite(bt, VPOLE, (bt->out_en<<7)); -} - -/* IDCODE is read only */ - -static void btwrite_adelay(BT829Ptr bt) /* ADELAY */ -{ - switch (bt->format) { - case BT829_NTSC: - case BT829_NTSC_JAPAN: - case BT829_PAL_M: - btwrite(bt, ADELAY, 104); - break; - case BT829_PAL: - case BT829_PAL_N: - case BT829_SECAM: - case BT829_PAL_N_COMB: - btwrite(bt, ADELAY, 127); - break; - default: /* shouldn't get here */ - btwrite(bt, ADELAY, 104); /* hardware default */ - break; - } -} - -static void btwrite_bdelay(BT829Ptr bt) /* BDELAY */ -{ - switch (bt->format) { - case BT829_NTSC: - case BT829_NTSC_JAPAN: - case BT829_PAL_M: - btwrite(bt, BDELAY, 93); - break; - case BT829_PAL: - case BT829_PAL_N: - case BT829_PAL_N_COMB: - btwrite(bt, BDELAY, 114); - break; - case BT829_SECAM: - btwrite(bt, BDELAY, 160); - break; - default: /* shouldn't get here */ - btwrite(bt, BDELAY, 93); /* hardware default */ - break; - } -} - -static void btwrite_adc(BT829Ptr bt) /* ADC */ -{ - btwrite(bt, ADC, bt->mux==bt->svideo_mux ? 0x80:0x82); /* CSLEEP = 0 or 1 */ -} - -static void btwrite_vtc(BT829Ptr bt) /* VTC */ -{ - int vfilt = 0; /* hardware default */ - - if (BTVERSION > BT827) { /* gatos says >= BT827 */ - switch (bt->format) { - case BT829_NTSC: - case BT829_NTSC_JAPAN: - case BT829_PAL_M: - case BT829_PAL_N_COMB: /* gatos groups with BT829_PAL */ - if (bt->width <= 360) vfilt = 1; /* gatos says <= 240 */ - if (bt->width <= 180) vfilt = 2; /* gatos says <= 120 */ - if (bt->width <= 90) vfilt = 3; /* gatos says <= 60 */ - break; - case BT829_PAL: - case BT829_PAL_N: - case BT829_SECAM: - if (bt->width <= 384) vfilt = 1; - if (bt->width <= 192) vfilt = 2; - if (bt->width<= 96) vfilt = 3; - break; - default: /* shouldn't get here */ - break; /* use hardware default */ - } - btwrite(bt, VTC, (bt->vbien<<4) | (bt->vbifmt<<3) | vfilt); - } -} - -static void btwrite_cc_status(BT829Ptr bt) /* CC_STATUS */ -{ /* FIXME: ATI specific */ - if (BTVERSION >= BT827) { - if (bt->ccmode == 0) btwrite(bt, CC_STATUS, 0x00); - /* 0x40 is activate to set the CCVALID line. Not required yet */ - else btwrite(bt, CC_STATUS, (bt->ccmode<<4) | 0x40); - } -} - -/* CC_DATA is read only */ - -static void btwrite_wc_dn(BT829Ptr bt) /* WC_DN */ -{ - if (BTVERSION >= BT827) { - /* use default */ - } -} - -static void bt_reset(BT829Ptr bt) { /* SRESET */ - btwrite(bt, SRESET, 0x0); /* Reset all registers */ -} - -static void btwrite_p_io(BT829Ptr bt) /* P_IO */ -{ - if (BTVERSION >= BT827) { - btwrite(bt, P_IO, bt->p_io); - } -} - -/* - * Deal with dependencies - */ -static void propagate_changes(BT829Ptr bt) -{ - CARD16 hdelay, unscaled_hdelay, vdelay, hscale, vscale; - int htotal, vactive; - - switch (bt->format) { - case BT829_NTSC: - case BT829_NTSC_JAPAN: - case BT829_PAL_M: - vdelay = 22; - htotal = 754; - vactive = 480; - unscaled_hdelay = 135; - break; - case BT829_PAL: - case BT829_PAL_N: - vdelay = (bt->tunertype==5) ? 34 : 22; - htotal = 922; - vactive = 576; - unscaled_hdelay = 186; - break; - case BT829_SECAM: - vdelay = 34; - htotal = 922; - vactive = 576; - unscaled_hdelay = 186; - break; - case BT829_PAL_N_COMB: - vdelay = (bt->tunertype==5) ? 34 : 22; /* windows says 22 */ - htotal = 754; /* gatos and windows say 922 */ - vactive = 576; - unscaled_hdelay = 135; /* gatos and windows say 186 */ - break; - default: /* shouldn't get here */ - vdelay = 22; /* hardware default */ - htotal = 754; - vactive = 480; /* hardware default */ - unscaled_hdelay = 135; - break; - } - - bt->htotal = htotal; /* Used for error checking in bt829_SetCaptSize */ - - hscale = 4096 * htotal / (bt->width + 2 * HCROP)-4096; - hdelay = ( - HCROP + (bt->width + 2 * HCROP) * unscaled_hdelay / htotal - ) & 0x3FE; - - vactive = vactive - 2 * VCROP; - vdelay = vdelay + VCROP; - vscale = (0x10000 - (512*vactive/bt->height-512)) & 0x1FFF; - - if ((hdelay != bt->hdelay) || (vdelay != bt->vdelay) || - (vactive != bt->vactive) || (hscale != bt->hscale) || - (vscale != bt->vscale)) { - bt->hdelay = hdelay; - bt->vdelay = vdelay; - bt->vactive = vactive; - bt->hscale = hscale; - bt->vscale = vscale; - btwrite_crop(bt); - btwrite_vdelay_lo(bt); - btwrite_vactive_lo(bt); - btwrite_hdelay_lo(bt); - btwrite_hscale_hi(bt); - btwrite_hscale_lo(bt); - btwrite_control(bt); - btwrite_vscale_hi(bt); - btwrite_vscale_lo(bt); - } -} - -static void write_all(BT829Ptr bt) -{ - bt_reset(bt); - propagate_changes(bt); /* ensure consistency */ - btwrite_iform(bt); - btwrite_tdec(bt); - btwrite_crop(bt); - btwrite_vdelay_lo(bt); - btwrite_vactive_lo(bt); - btwrite_hdelay_lo(bt); - btwrite_hactive_lo(bt); - btwrite_hscale_hi(bt); - btwrite_hscale_lo(bt); - btwrite_bright(bt); - btwrite_control(bt); - btwrite_contrast_lo(bt); - btwrite_sat_u_lo(bt); - btwrite_sat_v_lo(bt); - btwrite_hue(bt); - btwrite_scloop(bt); - btwrite_wc_up(bt); - btwrite_oform(bt); - btwrite_vscale_hi(bt); - btwrite_vscale_lo(bt); - btwrite_vpole(bt); - btwrite_adelay(bt); - btwrite_bdelay(bt); - btwrite_adc(bt); - btwrite_vtc(bt); -/* btwrite_cc_status(bt); */ /* FIXME: CC code needs cleaning */ - btwrite_wc_dn(bt); - btwrite_p_io(bt); -} - -/* - * Public functions - */ -BT829Ptr bt829_Detect(I2CBusPtr b, I2CSlaveAddr addr) -{ - BT829Ptr bt; - I2CByte a; - - bt = xcalloc(1, sizeof(BT829Rec)); - if(bt == NULL) return NULL; - bt->d.DevName = strdup("BT829 video decoder"); - bt->d.SlaveAddr = addr; - bt->d.pI2CBus = b; - bt->d.NextDev = NULL; - bt->d.StartTimeout = b->StartTimeout; - bt->d.BitTimeout = b->BitTimeout; - bt->d.AcknTimeout = b->AcknTimeout; - bt->d.ByteTimeout = b->ByteTimeout; - - - if(!I2C_WriteRead(&(bt->d), NULL, 0, &a, 1)) - { - free(bt); - return NULL; - } - - bt->id = btread(bt,IDCODE); - - free(bt->d.DevName); - bt->d.DevName = xcalloc(200, sizeof(char)); - switch(BTVERSION){ - case BT815: - sprintf(bt->d.DevName, "bt815a video decoder, revision %d",bt->id & 0xf); - break; - case BT817: - sprintf(bt->d.DevName, "bt817a video decoder, revision %d",bt->id & 0xf); - break; - case BT819: - sprintf(bt->d.DevName, "bt819a video decoder, revision %d",bt->id & 0xf); - break; - case BT827: - sprintf(bt->d.DevName, "bt827a/b video decoder, revision %d",bt->id & 0xf); - break; - case BT829: - sprintf(bt->d.DevName, "bt829a/b video decoder, revision %d",bt->id & 0xf); - break; - default: - sprintf(bt->d.DevName, "bt8xx/unknown video decoder version %d, revision %d",bt->id >> 4,bt->id & 0xf); - break; - } - - /* set default parameters */ - if(!I2CDevInit(&(bt->d))) - { - free(bt); - return NULL; - } - - bt->tunertype = 1; - - bt->brightness = 0; /* hardware default */ - bt->ccmode = 0; - bt->code = 0; /* hardware default */ - bt->contrast = 216; /* hardware default */ - bt->format = BT829_NTSC; - bt->height = 480; /* hardware default for vactive */ - bt->hue = 0; /* hardware default */ - bt->len = 1; /* hardware default */ - bt->mux = BT829_MUX0; /* hardware default */ - bt->out_en = 0; /* hardware default */ - bt->p_io = 0; /* hardware default */ - bt->sat_u = 254; /* hardware default */ - bt->sat_v = 180; /* hardware default */ - bt->vbien = 0; /* hardware default */ - bt->vbifmt = 0; /* hardware default */ - bt->width = 640; /* hardware default for hactive */ - - bt->hdelay = 120; /* hardware default */ - bt->hscale = 684; /* hardware default */ - bt->vactive = 480; /* hardware default */ - bt->vdelay = 22; /* hardware default */ - bt->vscale = 0; /* hardware default */ - - bt->htotal = 754; /* NTSC */ - bt->svideo_mux = 0; /* no s-video */ - - return bt; -} - -int bt829_ATIInit(BT829Ptr bt) -{ - bt->code = 1; - bt->len = 0; - bt->vbien = 1; - bt->vbifmt = 1; - bt->svideo_mux = BT829_MUX1; - - write_all (bt); - - return 0; -} - -int bt829_SetFormat(BT829Ptr bt, CARD8 format) -{ - if ((format < 1) || (format > 7)) return -1; - if ((BTVERSION <= BT819) && - (format != BT829_NTSC) && (format != BT829_PAL)) return -1; - if (format == bt->format) return 0; - bt->format = format; - propagate_changes(bt); - btwrite_iform(bt); - btwrite_scloop(bt); - btwrite_adelay(bt); - btwrite_bdelay(bt); - btwrite_vtc(bt); - return 0; -} - -int bt829_SetMux(BT829Ptr bt, CARD8 mux) -{ - if ((mux < 1) || (mux > 3)) return -1; - if (mux == bt->mux) return 0; - bt->mux = mux; - /* propagate_changes(bt); */ /* no dependencies */ - btwrite_iform(bt); - btwrite_control(bt); - btwrite_adc(bt); - return 0; -} - -void bt829_SetBrightness(BT829Ptr bt, int brightness) -{ - brightness = LIMIT(brightness,-1000,999); /* ensure -128 <= brightness <= 127 below */ - brightness = (128*brightness)/1000; - if (brightness == bt->brightness) return; - bt->brightness = brightness; - /* propagate_changes(bt); */ /* no dependencies */ - btwrite_bright(bt); -} - -void bt829_SetContrast(BT829Ptr bt, int contrast) -{ - contrast = LIMIT(contrast,-1000,1000); - contrast = (216*(contrast+1000))/1000; - if (contrast == bt->contrast) return; - bt->contrast = contrast; - /* propagate_changes(bt); */ /* no dependencies */ - btwrite_control(bt); - btwrite_contrast_lo(bt); -} - -void bt829_SetSaturation(BT829Ptr bt, int saturation) -{ - CARD16 sat_u, sat_v; - - saturation = LIMIT(saturation,-1000,1000); - sat_u = (254*(saturation+1000))/1000; - sat_v = (180*(saturation+1000))/1000; - if ((sat_u == bt->sat_u) && (sat_v == bt->sat_v)) return; - bt->sat_u = sat_u; - bt->sat_v = sat_v; - /* propagate_changes(bt); */ /* no dependencies */ - btwrite_control(bt); - btwrite_sat_u_lo(bt); - btwrite_sat_v_lo(bt); -} - -void bt829_SetTint(BT829Ptr bt, int hue) -{ - hue = LIMIT(hue,-1000,999); /* ensure -128 <= hue <= 127 below */ - hue = (128*hue)/1000; - if (hue == bt->hue) return; - bt->hue = hue; - /* propagate_changes(bt); */ /* no dependencies */ - btwrite_hue(bt); -} - -int bt829_SetCaptSize(BT829Ptr bt, int width, int height) -{ - if ((width > bt->htotal - 2 * HCROP) || - (16 * width < bt->htotal - 32 * HCROP)) return -1; - if ((height > bt->vactive) || (16 * height < bt->vactive)) return -1; - if ((width == bt->width) && (height == bt->height)) return 0; - bt->width = width; - bt->height = height; - propagate_changes(bt); - btwrite_crop(bt); - btwrite_hactive_lo(bt); - btwrite_control(bt); - btwrite_vtc(bt); - return 0; -} - -int bt829_SetCC(BT829Ptr bt) /* FIXME: should take ccmode as a parameter */ -{ - if (BTVERSION < BT827) return -1; /* can't do it */ - /* propagate_changes(bt); */ /* no dependencies */ - btwrite_cc_status(bt); - /* we write to STATUS to reset the CCVALID flag */ - if (bt->ccmode != 0) btwrite_status(bt); - return 0; -} - -void bt829_SetOUT_EN(BT829Ptr bt, BOOL out_en) -{ - out_en = (out_en != 0); - if (out_en == bt->out_en) return; - bt->out_en = out_en; - /* propagate_changes(bt); */ /* no dependencies */ - btwrite_vpole(bt); -} - -void bt829_SetP_IO(BT829Ptr bt, CARD8 p_io) -{ - if (p_io == bt->p_io) return; - bt->p_io = p_io; - /* propagate_changes(bt); */ /* no dependencies */ - btwrite_p_io(bt); -} - -#define BTREAD(R) btread(bt,(R)) - -#if 0 - -void bt829_getCCdata(BT829Ptr bt,struct CCdata *data) -{ - CARD8 status; - data->num_valid=0; - /* wait for buffer to be half full (means 8/16 bytes) - * either 4 (one of CC/EDS) or 2 (both CC/EDS) frames */ - if(!(BTREAD(STATUS)&0x04)) return; /* could comment this line */ - for(;data->num_validnum_valid++) { - status=BTREAD(CC_STATUS); - if(!(status&0x04)) break; - data->data[data->num_valid]= BTREAD(CC_DATA)&0x7f; - /* stripped high bit (parity) */ - data->status[data->num_valid]= (CCS_EDS*((status&0x02)>>1)) | - (CCS_HIGH*(status&0x01)) | - (CCS_OVER*((status&0x08)>>3)) | - (CCS_PAR*((status&0x80)>>7)) ; } - btwrite(bt,STATUS,0x00); /* Reset CCVALID status bit */ - return; -} - -#endif - -/* ------------------------------------------------------------------------ */ -/* Debug and report routines */ - -#define DUMPREG(REG) \ - xf86DrvMsg(bt->d.pI2CBus->scrnIndex,X_INFO," %-12s (0x%02X) = 0x%02X\n", \ - #REG,REG,BTREAD(REG)) - -/*static void bt829_dumpregs(BT829Ptr bt) -{ - DUMPREG(STATUS); - DUMPREG(IFORM); - DUMPREG(TDEC); - DUMPREG(CROP); - DUMPREG(VDELAY_LO); - DUMPREG(VACTIVE_LO); - DUMPREG(HDELAY_LO); - DUMPREG(HACTIVE_LO); - DUMPREG(HSCALE_HI); - DUMPREG(HSCALE_LO); - DUMPREG(BRIGHT); - DUMPREG(CONTROL); - DUMPREG(CONTRAST_LO); - DUMPREG(SAT_U_LO); - DUMPREG(SAT_V_LO); - DUMPREG(HUE); - if (BTVERSION >= BT827) { - DUMPREG(SCLOOP); - DUMPREG(WC_UP) ; } - DUMPREG(OFORM); - DUMPREG(VSCALE_HI); - DUMPREG(VSCALE_LO); - DUMPREG(TEST); - DUMPREG(VPOLE); - DUMPREG(IDCODE); - DUMPREG(ADELAY); - DUMPREG(BDELAY); - DUMPREG(ADC); - if (BTVERSION >= BT827) { - DUMPREG(VTC); - DUMPREG(CC_STATUS); - DUMPREG(CC_DATA); - DUMPREG(WC_DN); - DUMPREG(P_IO) ; } -}*/ +/* TODO: clean up/fix CC code */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "xf86.h" +#include "xf86i2c.h" +#include "bt829.h" +#include "i2c_def.h" + +/* Changing the following settings (especially VCROP) may */ +/* require modifying code that calls this driver. */ +#define HCROP 0 /* amount to crop from the left and right edges */ +#define VCROP 0 /* amount to crop from the top and bottom edges */ + +#define BTVERSION (bt->id>>4) + +#define H(X) ( ((X)>>8) & 0xFF ) +#define L(X) ( (X) & 0xFF ) + +#define LIMIT(X,A,B) (((X)<(A)) ? (A) : ((X)>(B)) ? (B) : (X) ) + +/* Bt829 family chip ID's */ +#define BT815 0x02 +#define BT817 0x06 +#define BT819 0x07 +#define BT827 0x0C +#define BT829 0x0E + +/* Bt829 registers */ +#define STATUS 0x00 /* Device Status */ +#define IFORM 0x01 /* Input Format */ +#define TDEC 0x02 /* Temporal Decimation */ +#define CROP 0x03 /* MSB Cropping */ +#define VDELAY_LO 0x04 /* Vertical Delay */ +#define VACTIVE_LO 0x05 /* Vertical Active */ +#define HDELAY_LO 0x06 /* Horizontal Delay */ +#define HACTIVE_LO 0x07 /* Horizontal Active */ +#define HSCALE_HI 0x08 /* Horizontal Scaling */ +#define HSCALE_LO 0x09 /* Horizontal Scaling */ +#define BRIGHT 0x0A /* Brightness Control */ +#define CONTROL 0x0B /* Miscellaneous Control */ +#define CONTRAST_LO 0x0C /* Luma Gain (Contrast) */ +#define SAT_U_LO 0x0D /* Chroma (U) Gain (Saturation) */ +#define SAT_V_LO 0x0E /* Chroma (V) Gain (Saturation) */ +#define HUE 0x0F /* Hue Control */ +#define SCLOOP 0x10 /* SC Loop Control */ +#define WC_UP 0x11 /* White Crush Up Count */ +#define OFORM 0x12 /* Output Format */ +#define VSCALE_HI 0x13 /* Vertical Scaling */ +#define VSCALE_LO 0x14 /* Vertical Scaling */ +#define TEST 0x15 /* Test Control */ +#define VPOLE 0x16 /* Video Timing Polarity */ +#define IDCODE 0x17 /* ID Code */ +#define ADELAY 0x18 /* AGC Delay */ +#define BDELAY 0x19 /* Burst Gate Delay */ +#define ADC 0x1A /* ADC Interface */ +#define VTC 0x1B /* Video Timing Control */ +#define CC_STATUS 0x1C /* Extended Data Services/Closed Capt Status */ +#define CC_DATA 0x1D /* Extended Data Services/Closed Capt Data */ +#define WC_DN 0x1E /* White Crush Down Count */ +#define SRESET 0x1F /* Software Reset */ +#define P_IO 0x3F /* Programmable I/O */ + +static CARD8 btread(BT829Ptr bt, CARD8 reg) +{ + CARD8 v; + + I2C_WriteRead(&(bt->d), ®, 1, &v, 1); + + return v; +} + +static void btwrite(BT829Ptr bt, CARD8 reg, CARD8 val) +{ + CARD8 data[2]; + + data[0] = reg; + data[1] = val; + I2C_WriteRead(&(bt->d), data, 2, NULL, 0); +} + +/* + * Register access + */ +static void btwrite_status(BT829Ptr bt) /* STATUS */ +{ + btwrite(bt, STATUS, 0x00); /* clear */ +} + +static void btwrite_iform(BT829Ptr bt) /* IFORM */ +{ + int xtsel; + + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + case BT829_PAL_N_COMB: /* gatos says xtsel = 2 */ + xtsel = 1; + break; + case BT829_PAL: + case BT829_PAL_N: + case BT829_SECAM: + xtsel = 2; + break; + default: /* shouldn't get here */ + xtsel = 3; /* hardware default */ + break; + } + + btwrite(bt, IFORM, (bt->mux<<5) | (xtsel<<3) | bt->format); +} + +static void btwrite_tdec(BT829Ptr bt) /* TDEC */ +{ + /* use default */ +} + +static void btwrite_crop(BT829Ptr bt) /* CROP */ +{ + btwrite(bt, CROP, (H(bt->vdelay)<<6) | (H(bt->vactive)<<4) | + (H(bt->hdelay)<<2) | H(bt->width)); +} + +static void btwrite_vdelay_lo(BT829Ptr bt) /* VDELAY_LO */ +{ + btwrite(bt, VDELAY_LO, L(bt->vdelay)); +} + +static void btwrite_vactive_lo(BT829Ptr bt) /* VACTIVE_LO */ +{ + btwrite(bt, VACTIVE_LO, L(bt->vactive)); +} + +static void btwrite_hdelay_lo(BT829Ptr bt) /* HDELAY_LO */ +{ + btwrite(bt, HDELAY_LO, L(bt->hdelay)); +} + +static void btwrite_hactive_lo(BT829Ptr bt) /* HACTIVE_LO */ +{ + btwrite(bt, HACTIVE_LO, L(bt->width)); +} + +static void btwrite_hscale_hi(BT829Ptr bt) /* HSCALE_HI */ +{ + btwrite(bt, HSCALE_HI, H(bt->hscale)); +} + +static void btwrite_hscale_lo(BT829Ptr bt) /* HSCALE_LO */ +{ + btwrite(bt, HSCALE_LO, L(bt->hscale)); +} + +static void btwrite_bright(BT829Ptr bt) /* BRIGHT */ +{ + btwrite(bt, BRIGHT, bt->brightness); +} + +static void btwrite_control(BT829Ptr bt) /* CONTROL */ +{ + int ldec; + + /* The data sheet says ldec should always be 0 for SECAM */ + /* but the picture quality is better with ldec = 1 */ + ldec = (bt->width > 360); /* gatos says 384 */ + + btwrite(bt, CONTROL, + ((bt->mux==bt->svideo_mux) ? 0xC0:0x00) | /* LNOTCH and COMP */ + (ldec<<5) | (H(bt->contrast)<<2) | (H(bt->sat_u)<<1) | H(bt->sat_v)); +} + +static void btwrite_contrast_lo(BT829Ptr bt) /* CONTRAST_LO */ +{ + btwrite(bt, CONTRAST_LO, L(bt->contrast)); +} + +static void btwrite_sat_u_lo(BT829Ptr bt) /* SAT_U_LO */ +{ + btwrite(bt, SAT_U_LO, L(bt->sat_u)); +} + +static void btwrite_sat_v_lo(BT829Ptr bt) /* SAT_V_LO */ +{ + btwrite(bt, SAT_V_LO, L(bt->sat_v)); +} + +static void btwrite_hue(BT829Ptr bt) /* HUE */ +{ + btwrite(bt, HUE, bt->hue); +} + +static void btwrite_scloop(BT829Ptr bt) /* SCLOOP */ +{ + if (BTVERSION >= BT827) { + btwrite(bt, SCLOOP, + (bt->format==BT829_SECAM) ? 0x10:0x00 /* QCIF or AUTO */ + ); + } +} + +static void btwrite_wc_up(BT829Ptr bt) /* WC_UP */ +{ + if (BTVERSION >= BT827) { + /* use default */ + } +} + +static void btwrite_oform(BT829Ptr bt) /* OFORM */ +{ + btwrite(bt, OFORM, (bt->code<<3) | (bt->len<<2) | + 0x02 /* RANGE = 0, CORE = 0, VBI_FRAME = 0, OES = 2 (default) */ + ); +} + +static void btwrite_vscale_hi(BT829Ptr bt) /* VSCALE_HI */ +{ + btwrite(bt, VSCALE_HI, H(bt->vscale) | + 0x60 /* YCOMB = 0, COMB = 1, INT = 1 (default) */ + ); +} + +static void btwrite_vscale_lo(BT829Ptr bt) /* VSCALE_LO */ +{ + btwrite(bt, VSCALE_LO, L(bt->vscale)); +} + +/* TEST should not be written to */ + +static void btwrite_vpole(BT829Ptr bt) /* VPOLE */ +{ + btwrite(bt, VPOLE, (bt->out_en<<7)); +} + +/* IDCODE is read only */ + +static void btwrite_adelay(BT829Ptr bt) /* ADELAY */ +{ + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + btwrite(bt, ADELAY, 104); + break; + case BT829_PAL: + case BT829_PAL_N: + case BT829_SECAM: + case BT829_PAL_N_COMB: + btwrite(bt, ADELAY, 127); + break; + default: /* shouldn't get here */ + btwrite(bt, ADELAY, 104); /* hardware default */ + break; + } +} + +static void btwrite_bdelay(BT829Ptr bt) /* BDELAY */ +{ + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + btwrite(bt, BDELAY, 93); + break; + case BT829_PAL: + case BT829_PAL_N: + case BT829_PAL_N_COMB: + btwrite(bt, BDELAY, 114); + break; + case BT829_SECAM: + btwrite(bt, BDELAY, 160); + break; + default: /* shouldn't get here */ + btwrite(bt, BDELAY, 93); /* hardware default */ + break; + } +} + +static void btwrite_adc(BT829Ptr bt) /* ADC */ +{ + btwrite(bt, ADC, bt->mux==bt->svideo_mux ? 0x80:0x82); /* CSLEEP = 0 or 1 */ +} + +static void btwrite_vtc(BT829Ptr bt) /* VTC */ +{ + int vfilt = 0; /* hardware default */ + + if (BTVERSION > BT827) { /* gatos says >= BT827 */ + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + case BT829_PAL_N_COMB: /* gatos groups with BT829_PAL */ + if (bt->width <= 360) vfilt = 1; /* gatos says <= 240 */ + if (bt->width <= 180) vfilt = 2; /* gatos says <= 120 */ + if (bt->width <= 90) vfilt = 3; /* gatos says <= 60 */ + break; + case BT829_PAL: + case BT829_PAL_N: + case BT829_SECAM: + if (bt->width <= 384) vfilt = 1; + if (bt->width <= 192) vfilt = 2; + if (bt->width<= 96) vfilt = 3; + break; + default: /* shouldn't get here */ + break; /* use hardware default */ + } + btwrite(bt, VTC, (bt->vbien<<4) | (bt->vbifmt<<3) | vfilt); + } +} + +static void btwrite_cc_status(BT829Ptr bt) /* CC_STATUS */ +{ /* FIXME: ATI specific */ + if (BTVERSION >= BT827) { + if (bt->ccmode == 0) btwrite(bt, CC_STATUS, 0x00); + /* 0x40 is activate to set the CCVALID line. Not required yet */ + else btwrite(bt, CC_STATUS, (bt->ccmode<<4) | 0x40); + } +} + +/* CC_DATA is read only */ + +static void btwrite_wc_dn(BT829Ptr bt) /* WC_DN */ +{ + if (BTVERSION >= BT827) { + /* use default */ + } +} + +static void bt_reset(BT829Ptr bt) { /* SRESET */ + btwrite(bt, SRESET, 0x0); /* Reset all registers */ +} + +static void btwrite_p_io(BT829Ptr bt) /* P_IO */ +{ + if (BTVERSION >= BT827) { + btwrite(bt, P_IO, bt->p_io); + } +} + +/* + * Deal with dependencies + */ +static void propagate_changes(BT829Ptr bt) +{ + CARD16 hdelay, unscaled_hdelay, vdelay, hscale, vscale; + int htotal, vactive; + + switch (bt->format) { + case BT829_NTSC: + case BT829_NTSC_JAPAN: + case BT829_PAL_M: + vdelay = 22; + htotal = 754; + vactive = 480; + unscaled_hdelay = 135; + break; + case BT829_PAL: + case BT829_PAL_N: + vdelay = (bt->tunertype==5) ? 34 : 22; + htotal = 922; + vactive = 576; + unscaled_hdelay = 186; + break; + case BT829_SECAM: + vdelay = 34; + htotal = 922; + vactive = 576; + unscaled_hdelay = 186; + break; + case BT829_PAL_N_COMB: + vdelay = (bt->tunertype==5) ? 34 : 22; /* windows says 22 */ + htotal = 754; /* gatos and windows say 922 */ + vactive = 576; + unscaled_hdelay = 135; /* gatos and windows say 186 */ + break; + default: /* shouldn't get here */ + vdelay = 22; /* hardware default */ + htotal = 754; + vactive = 480; /* hardware default */ + unscaled_hdelay = 135; + break; + } + + bt->htotal = htotal; /* Used for error checking in bt829_SetCaptSize */ + + hscale = 4096 * htotal / (bt->width + 2 * HCROP)-4096; + hdelay = ( + HCROP + (bt->width + 2 * HCROP) * unscaled_hdelay / htotal + ) & 0x3FE; + + vactive = vactive - 2 * VCROP; + vdelay = vdelay + VCROP; + vscale = (0x10000 - (512*vactive/bt->height-512)) & 0x1FFF; + + if ((hdelay != bt->hdelay) || (vdelay != bt->vdelay) || + (vactive != bt->vactive) || (hscale != bt->hscale) || + (vscale != bt->vscale)) { + bt->hdelay = hdelay; + bt->vdelay = vdelay; + bt->vactive = vactive; + bt->hscale = hscale; + bt->vscale = vscale; + btwrite_crop(bt); + btwrite_vdelay_lo(bt); + btwrite_vactive_lo(bt); + btwrite_hdelay_lo(bt); + btwrite_hscale_hi(bt); + btwrite_hscale_lo(bt); + btwrite_control(bt); + btwrite_vscale_hi(bt); + btwrite_vscale_lo(bt); + } +} + +static void write_all(BT829Ptr bt) +{ + bt_reset(bt); + propagate_changes(bt); /* ensure consistency */ + btwrite_iform(bt); + btwrite_tdec(bt); + btwrite_crop(bt); + btwrite_vdelay_lo(bt); + btwrite_vactive_lo(bt); + btwrite_hdelay_lo(bt); + btwrite_hactive_lo(bt); + btwrite_hscale_hi(bt); + btwrite_hscale_lo(bt); + btwrite_bright(bt); + btwrite_control(bt); + btwrite_contrast_lo(bt); + btwrite_sat_u_lo(bt); + btwrite_sat_v_lo(bt); + btwrite_hue(bt); + btwrite_scloop(bt); + btwrite_wc_up(bt); + btwrite_oform(bt); + btwrite_vscale_hi(bt); + btwrite_vscale_lo(bt); + btwrite_vpole(bt); + btwrite_adelay(bt); + btwrite_bdelay(bt); + btwrite_adc(bt); + btwrite_vtc(bt); +/* btwrite_cc_status(bt); */ /* FIXME: CC code needs cleaning */ + btwrite_wc_dn(bt); + btwrite_p_io(bt); +} + +/* + * Public functions + */ +BT829Ptr bt829_Detect(I2CBusPtr b, I2CSlaveAddr addr) +{ + BT829Ptr bt; + I2CByte a; + + bt = calloc(1, sizeof(BT829Rec)); + if(bt == NULL) return NULL; + bt->d.DevName = strdup("BT829 video decoder"); + bt->d.SlaveAddr = addr; + bt->d.pI2CBus = b; + bt->d.NextDev = NULL; + bt->d.StartTimeout = b->StartTimeout; + bt->d.BitTimeout = b->BitTimeout; + bt->d.AcknTimeout = b->AcknTimeout; + bt->d.ByteTimeout = b->ByteTimeout; + + + if(!I2C_WriteRead(&(bt->d), NULL, 0, &a, 1)) + { + free(bt); + return NULL; + } + + bt->id = btread(bt,IDCODE); + + free(bt->d.DevName); + bt->d.DevName = calloc(200, sizeof(char)); + switch(BTVERSION){ + case BT815: + sprintf(bt->d.DevName, "bt815a video decoder, revision %d",bt->id & 0xf); + break; + case BT817: + sprintf(bt->d.DevName, "bt817a video decoder, revision %d",bt->id & 0xf); + break; + case BT819: + sprintf(bt->d.DevName, "bt819a video decoder, revision %d",bt->id & 0xf); + break; + case BT827: + sprintf(bt->d.DevName, "bt827a/b video decoder, revision %d",bt->id & 0xf); + break; + case BT829: + sprintf(bt->d.DevName, "bt829a/b video decoder, revision %d",bt->id & 0xf); + break; + default: + sprintf(bt->d.DevName, "bt8xx/unknown video decoder version %d, revision %d",bt->id >> 4,bt->id & 0xf); + break; + } + + /* set default parameters */ + if(!I2CDevInit(&(bt->d))) + { + free(bt); + return NULL; + } + + bt->tunertype = 1; + + bt->brightness = 0; /* hardware default */ + bt->ccmode = 0; + bt->code = 0; /* hardware default */ + bt->contrast = 216; /* hardware default */ + bt->format = BT829_NTSC; + bt->height = 480; /* hardware default for vactive */ + bt->hue = 0; /* hardware default */ + bt->len = 1; /* hardware default */ + bt->mux = BT829_MUX0; /* hardware default */ + bt->out_en = 0; /* hardware default */ + bt->p_io = 0; /* hardware default */ + bt->sat_u = 254; /* hardware default */ + bt->sat_v = 180; /* hardware default */ + bt->vbien = 0; /* hardware default */ + bt->vbifmt = 0; /* hardware default */ + bt->width = 640; /* hardware default for hactive */ + + bt->hdelay = 120; /* hardware default */ + bt->hscale = 684; /* hardware default */ + bt->vactive = 480; /* hardware default */ + bt->vdelay = 22; /* hardware default */ + bt->vscale = 0; /* hardware default */ + + bt->htotal = 754; /* NTSC */ + bt->svideo_mux = 0; /* no s-video */ + + return bt; +} + +int bt829_ATIInit(BT829Ptr bt) +{ + bt->code = 1; + bt->len = 0; + bt->vbien = 1; + bt->vbifmt = 1; + bt->svideo_mux = BT829_MUX1; + + write_all (bt); + + return 0; +} + +int bt829_SetFormat(BT829Ptr bt, CARD8 format) +{ + if ((format < 1) || (format > 7)) return -1; + if ((BTVERSION <= BT819) && + (format != BT829_NTSC) && (format != BT829_PAL)) return -1; + if (format == bt->format) return 0; + bt->format = format; + propagate_changes(bt); + btwrite_iform(bt); + btwrite_scloop(bt); + btwrite_adelay(bt); + btwrite_bdelay(bt); + btwrite_vtc(bt); + return 0; +} + +int bt829_SetMux(BT829Ptr bt, CARD8 mux) +{ + if ((mux < 1) || (mux > 3)) return -1; + if (mux == bt->mux) return 0; + bt->mux = mux; + /* propagate_changes(bt); */ /* no dependencies */ + btwrite_iform(bt); + btwrite_control(bt); + btwrite_adc(bt); + return 0; +} + +void bt829_SetBrightness(BT829Ptr bt, int brightness) +{ + brightness = LIMIT(brightness,-1000,999); /* ensure -128 <= brightness <= 127 below */ + brightness = (128*brightness)/1000; + if (brightness == bt->brightness) return; + bt->brightness = brightness; + /* propagate_changes(bt); */ /* no dependencies */ + btwrite_bright(bt); +} + +void bt829_SetContrast(BT829Ptr bt, int contrast) +{ + contrast = LIMIT(contrast,-1000,1000); + contrast = (216*(contrast+1000))/1000; + if (contrast == bt->contrast) return; + bt->contrast = contrast; + /* propagate_changes(bt); */ /* no dependencies */ + btwrite_control(bt); + btwrite_contrast_lo(bt); +} + +void bt829_SetSaturation(BT829Ptr bt, int saturation) +{ + CARD16 sat_u, sat_v; + + saturation = LIMIT(saturation,-1000,1000); + sat_u = (254*(saturation+1000))/1000; + sat_v = (180*(saturation+1000))/1000; + if ((sat_u == bt->sat_u) && (sat_v == bt->sat_v)) return; + bt->sat_u = sat_u; + bt->sat_v = sat_v; + /* propagate_changes(bt); */ /* no dependencies */ + btwrite_control(bt); + btwrite_sat_u_lo(bt); + btwrite_sat_v_lo(bt); +} + +void bt829_SetTint(BT829Ptr bt, int hue) +{ + hue = LIMIT(hue,-1000,999); /* ensure -128 <= hue <= 127 below */ + hue = (128*hue)/1000; + if (hue == bt->hue) return; + bt->hue = hue; + /* propagate_changes(bt); */ /* no dependencies */ + btwrite_hue(bt); +} + +int bt829_SetCaptSize(BT829Ptr bt, int width, int height) +{ + if ((width > bt->htotal - 2 * HCROP) || + (16 * width < bt->htotal - 32 * HCROP)) return -1; + if ((height > bt->vactive) || (16 * height < bt->vactive)) return -1; + if ((width == bt->width) && (height == bt->height)) return 0; + bt->width = width; + bt->height = height; + propagate_changes(bt); + btwrite_crop(bt); + btwrite_hactive_lo(bt); + btwrite_control(bt); + btwrite_vtc(bt); + return 0; +} + +int bt829_SetCC(BT829Ptr bt) /* FIXME: should take ccmode as a parameter */ +{ + if (BTVERSION < BT827) return -1; /* can't do it */ + /* propagate_changes(bt); */ /* no dependencies */ + btwrite_cc_status(bt); + /* we write to STATUS to reset the CCVALID flag */ + if (bt->ccmode != 0) btwrite_status(bt); + return 0; +} + +void bt829_SetOUT_EN(BT829Ptr bt, BOOL out_en) +{ + out_en = (out_en != 0); + if (out_en == bt->out_en) return; + bt->out_en = out_en; + /* propagate_changes(bt); */ /* no dependencies */ + btwrite_vpole(bt); +} + +void bt829_SetP_IO(BT829Ptr bt, CARD8 p_io) +{ + if (p_io == bt->p_io) return; + bt->p_io = p_io; + /* propagate_changes(bt); */ /* no dependencies */ + btwrite_p_io(bt); +} + +#define BTREAD(R) btread(bt,(R)) + +#if 0 + +void bt829_getCCdata(BT829Ptr bt,struct CCdata *data) +{ + CARD8 status; + data->num_valid=0; + /* wait for buffer to be half full (means 8/16 bytes) + * either 4 (one of CC/EDS) or 2 (both CC/EDS) frames */ + if(!(BTREAD(STATUS)&0x04)) return; /* could comment this line */ + for(;data->num_validnum_valid++) { + status=BTREAD(CC_STATUS); + if(!(status&0x04)) break; + data->data[data->num_valid]= BTREAD(CC_DATA)&0x7f; + /* stripped high bit (parity) */ + data->status[data->num_valid]= (CCS_EDS*((status&0x02)>>1)) | + (CCS_HIGH*(status&0x01)) | + (CCS_OVER*((status&0x08)>>3)) | + (CCS_PAR*((status&0x80)>>7)) ; } + btwrite(bt,STATUS,0x00); /* Reset CCVALID status bit */ + return; +} + +#endif + +/* ------------------------------------------------------------------------ */ +/* Debug and report routines */ + +#define DUMPREG(REG) \ + xf86DrvMsg(bt->d.pI2CBus->scrnIndex,X_INFO," %-12s (0x%02X) = 0x%02X\n", \ + #REG,REG,BTREAD(REG)) + +/*static void bt829_dumpregs(BT829Ptr bt) +{ + DUMPREG(STATUS); + DUMPREG(IFORM); + DUMPREG(TDEC); + DUMPREG(CROP); + DUMPREG(VDELAY_LO); + DUMPREG(VACTIVE_LO); + DUMPREG(HDELAY_LO); + DUMPREG(HACTIVE_LO); + DUMPREG(HSCALE_HI); + DUMPREG(HSCALE_LO); + DUMPREG(BRIGHT); + DUMPREG(CONTROL); + DUMPREG(CONTRAST_LO); + DUMPREG(SAT_U_LO); + DUMPREG(SAT_V_LO); + DUMPREG(HUE); + if (BTVERSION >= BT827) { + DUMPREG(SCLOOP); + DUMPREG(WC_UP) ; } + DUMPREG(OFORM); + DUMPREG(VSCALE_HI); + DUMPREG(VSCALE_LO); + DUMPREG(TEST); + DUMPREG(VPOLE); + DUMPREG(IDCODE); + DUMPREG(ADELAY); + DUMPREG(BDELAY); + DUMPREG(ADC); + if (BTVERSION >= BT827) { + DUMPREG(VTC); + DUMPREG(CC_STATUS); + DUMPREG(CC_DATA); + DUMPREG(WC_DN); + DUMPREG(P_IO) ; } +}*/ diff --git a/xorg-server/hw/xfree86/i2c/fi1236.c b/xorg-server/hw/xfree86/i2c/fi1236.c index 61224eaa5..531b64aed 100644 --- a/xorg-server/hw/xfree86/i2c/fi1236.c +++ b/xorg-server/hw/xfree86/i2c/fi1236.c @@ -1,605 +1,605 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "xf86.h" -#include "xf86i2c.h" -#include "fi1236.h" -#include "tda9885.h" -#include "i2c_def.h" - -#define NUM_TUNERS 8 - -const FI1236_parameters tuner_parms[NUM_TUNERS] = -{ - /* 0 - FI1236 */ - { 733 ,884 ,12820 ,2516 ,7220 ,0xA2 ,0x94, 0x34, 0x8e }, - /* !!!based on documentation - it should be: - {733 ,16*55.25 ,16*801.25 ,16*160 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e},*/ - - /* 1 - FI1216 */ - { 623 ,16*48.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, - /* 2 - TEMIC FN5AL */ - { 623 ,16*45.75 ,16*855.25 ,16*169 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e }, - /* 3 - MT2032.. */ - { 733 ,768 ,13760 , 0 , 0 , 0 , 0, 0, 0 }, - /* 4 - FI1246 */ - { 623 ,16*45.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, - /* 5 - FI1256 */ - { 623 ,16*49.75 ,16*863.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, - /* 6 - FI1236W */ - /*{ 733 ,884 ,12820 ,2516 ,7220 ,0x1 ,0x2, 0x4, 0x8e },*/ - { 732, 16*55.25, 16*801.25, 16*160, 16*442, 0x1, 0x2, 0x4, 0x8e }, - /* 7 - FM1216ME */ - { 623 ,16*48.25 ,16*863.25 ,16*158.00 ,16*442.00 ,0x1 ,0x2, 0x4, 0x8e } -}; - - -FI1236Ptr Detect_FI1236(I2CBusPtr b, I2CSlaveAddr addr) -{ - FI1236Ptr f; - I2CByte a; - - f = xcalloc(1,sizeof(FI1236Rec)); - if(f == NULL) return NULL; - f->d.DevName = strdup("FI12xx Tuner"); - f->d.SlaveAddr = addr; - f->d.pI2CBus = b; - f->d.NextDev = NULL; - f->d.StartTimeout = b->StartTimeout; - f->d.BitTimeout = b->BitTimeout; - f->d.AcknTimeout = b->AcknTimeout; - f->d.ByteTimeout = b->ByteTimeout; - f->type=TUNER_TYPE_FI1236; - f->afc_timer_installed=FALSE; - f->last_afc_hint=TUNER_OFF; - f->video_if=45.7812; - - if(!I2C_WriteRead(&(f->d), NULL, 0, &a, 1)) - { - free(f); - return NULL; - } - FI1236_set_tuner_type(f, TUNER_TYPE_FI1236); - if(!I2CDevInit(&(f->d))) - { - free(f); - return NULL; - } - return f; -} - -static void MT2032_dump_parameters(FI1236Ptr f, MT2032_parameters *m) -{ -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: input f_rf=%g f_if1=%g f_if2=%g f_ref=%g f_ifbw=%g f_step=%g\n", - m->f_rf, m->f_if1, m->f_if2, m->f_ref, m->f_ifbw, m->f_step); - -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: computed f_lo1=%g f_lo2=%g LO1I=%d LO2I=%d SEL=%d STEP=%d NUM=%d\n", - m->f_lo1, m->f_lo2, m->LO1I, m->LO2I, m->SEL, m->STEP, m->NUM); -} - - -static void MT2032_getid(FI1236Ptr f) -{ -CARD8 out[4]; -CARD8 in; - -in=0x11; -I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 4); -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: Company code 0x%02x%02x, part code 0x%02x, revision code 0x%02x\n", - out[0], out[1], out[2], out[3]); - -} - -/* might be buggy */ -#if 0 -static void MT2032_shutdown(FI1236Ptr f) -{ -CARD8 data[10]; - -data[0]=0x00; /* start with register 0x00 */ -data[1]=0x1A; -data[2]=0x44; -data[3]=0x20; - -I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); - -data[0]=0x05; /* now start with register 0x05 */ -data[1]=0xD7; -data[2]=0x14; -data[3]=0x05; -I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); - -data[0]=0x0B; /* now start with register 0x05 */ -data[1]=0x8F; -data[2]=0x07; -data[3]=0x43; -I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); - -usleep(15000); -} -#endif - -static void MT2032_dump_status(FI1236Ptr f); - -static void MT2032_init(FI1236Ptr f) -{ -CARD8 data[10]; -CARD8 value; -CARD8 xogc = 0x00; - -MT2032_getid(f); - -data[0]=0x02; /* start with register 0x02 */ -data[1]=0xFF; -data[2]=0x0F; -data[3]=0x1F; - -I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); - -data[0]=0x06; /* now start with register 0x06 */ -data[1]=0xE4; -data[2]=0x8F; -data[3]=0xC3; -data[4]=0x4E; -data[5]=0xEC; -I2C_WriteRead(&(f->d), (I2CByte *)data, 6, NULL, 0); - -data[0]=0x0d; /* now start with register 0x0d */ -data[1]=0x32; -I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); - -while(1) { - usleep(15000); /* wait 15 milliseconds */ - - data[0]=0x0e; /* register number 7, status */ - value=0xFF; - if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOK\n"); - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: XOK=%d\n", value & 0x01); - if(value & 1) break; - - data[0]=0x07; - if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOGC\n"); - - xogc=value & 0x7; - if(xogc==4){ - break; /* XOGC has reached 4.. stop */ - } - xogc--; - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: try XOGC=%d\n", xogc); - usleep(15000); - data[0]=0x07; /* register number 7, control byte 2 */ - data[1]=0x08 | xogc; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); - } -f->xogc=xogc; -/* wait before continuing */ -usleep(15000); /* wait 50 milliseconds */ -MT2032_dump_status(f); -} - -static int MT2032_no_spur_in_band(MT2032_parameters *m) -{ -int n_max, n1, n2; -double f_test; -n_max=5; -n1=1; -while(1){ - n2=-n1; - f_test=n1*(m->f_lo1-m->f_lo2); - while(1){ - n2--; - f_test=f_test-m->f_lo2; - xf86DrvMsg(0, X_INFO, "testing f_test=%g n1=%d n2=%d f_lo1=%g f_lo2=%g f_if2=%g\n", f_test, n1, n2, m->f_lo1, m->f_lo2, m->f_if2); - xf86DrvMsg(0, X_INFO, "d_f=%g f_ifbw=%g\n",fabs(fabs(f_test)-m->f_if2), m->f_ifbw); - if((fabs(fabs(f_test)-m->f_if2)*2.0)<=m->f_ifbw)return 0; - if(n2<=-n_max)break; - /* this line in the manual is bogus. I say it is faster - and more correct to go over all harmonics.. */ - #if 0 - if(f_test<(m->f_lo2-m->f_if2-m->f_ifbw))break; - #endif - } - n1++; - if(n1>=n_max)return 1; - } - -} - -static void MT2032_calculate_register_settings(MT2032_parameters *m, double f_rf, double f_if1, double f_if2, double f_ref, double f_ifbw, double f_step) -{ -int n; -m->f_rf=f_rf; -m->f_if1=f_if1; -m->f_if2=f_if2; -m->f_ref=f_ref; -m->f_ifbw=f_ifbw; -m->f_step=f_step; - -m->f_lo1=f_rf+f_if1; -m->LO1I=lrint(m->f_lo1/f_ref); -m->f_lo1=f_ref*m->LO1I; - -m->f_lo2=m->f_lo1-f_rf-f_if2; - -/* check for spurs */ -n=1; -while(n<3){ - if(MT2032_no_spur_in_band(m))break; - if(m->f_lo1<(f_rf+f_if1)){ - m->LO1I+=n; - } else { - m->LO1I-=n; - } - m->f_lo1=m->LO1I*f_ref; - m->f_lo2=m->f_lo1-f_rf-f_if2; - n++; - } -/* xf86DrvMsg(0, X_INFO, "MT2032: n=%d\n", n); */ -/* select VCO */ - -/* m->f_lo1>1100.0 */ -if(m->f_lo1<1370.0)m->SEL=4; - else -if(m->f_lo1<1530.0)m->SEL=3; - else -if(m->f_lo1<1720.0)m->SEL=2; - else -if(m->f_lo1<1890.0)m->SEL=1; - else /* m->f_lo1 < 1958.0 */ - m->SEL=0; - -/* calculate the rest of the registers */ -m->LO2I=floor(m->f_lo2/f_ref); -m->STEP=floor(3780.0*f_step/f_ref); -m->NUM=floor(3780.0*(m->f_lo2/f_ref-m->LO2I)); -m->NUM=m->STEP*lrint((1.0*m->NUM)/(1.0*m->STEP)); -} - -static int MT2032_wait_for_lock(FI1236Ptr f) -{ -int n; -CARD8 data[10]; -CARD8 value; - -n=12; -while(1){ - data[0]=0x0e; /* register number 7, status */ - I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); -/* xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: LO1LK=%d LO2LK=%d\n", (value & 0x04)>>2, (value & 0x02)>>1); */ - if((value & 6)==6) break; - usleep(1500); - n--; - if(n<0)break; - } -if(n<0){ - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); - return 0; - } -return 1; -} - -static void MT2032_implement_settings(FI1236Ptr f, MT2032_parameters *m) -{ -CARD8 data[10]; -CARD8 value; - -data[0]=0x00; /* start with register 0x00 */ -data[1]=(m->LO1I>>3)-1; -data[2]=(m->SEL<<4)|(m->LO1I & 0x7); -data[3]=0x86; -I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); - -data[0]=0x05; /* start with register 0x05 */ -data[1]=((m->LO2I & 0x7)<<5)|((m->LO2I>>3)-1); -if(m->f_rf<400.0)data[2]=0xe4; - else data[2]=0xf4; -I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); - -data[0]=0x07; /* register number 7, control byte 2 */ -I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: using XOGC=%d\n", (value & 0x07)); -data[1]=8 | (value & 0x7); -I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); - -data[0]=0x0b; /* start with register 0x0b */ -data[1]=m->NUM & 0xff; -data[2]=(1<<7)|((m->NUM >> 8) & 0x0f); -I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); - -MT2032_wait_for_lock(f); -} - -static void MT2032_optimize_VCO(FI1236Ptr f, MT2032_parameters *m) -{ -CARD8 data[10]; -CARD8 value; -CARD8 TAD1; - -data[0]=0x0f; /* register number 7, status */ -I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); -TAD1=value & 0x07; -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: TAD1=%d SEL=%d\n", TAD1, m->SEL); -if(TAD1 < 2)return; -if(TAD1==2){ - if(m->SEL==0)return; - m->SEL--; - } else { - if(m->SEL>=4)return; - m->SEL++; - } -data[0]=0x01; /* start with register 1 */ -data[1]=(m->SEL<<4)|(m->LO1I & 0x7); -I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); - -} - -static int FI1236_get_afc_hint(FI1236Ptr f) -{ - CARD8 out; - CARD8 AFC; - - if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) - { - TDA9885Ptr t = (TDA9885Ptr)f->afc_source; - if (t == NULL) - return TUNER_OFF; - - tda9885_getstatus(t); - tda9885_dumpstatus(t); - AFC = t->afc_status & 0x0f; - - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC); - if (AFC == 0) return TUNER_TUNED; - else if (AFC <= 0x07)return TUNER_JUST_BELOW; - else if (AFC < 0x0f )return TUNER_JUST_ABOVE; - else if (AFC == 0x0f)return TUNER_TUNED; - } - else - { - I2C_WriteRead(&(f->d), NULL, 0, &out, 1); - AFC=out & 0x7; - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC); - if(AFC==2)return TUNER_TUNED; - if(AFC==3)return TUNER_JUST_BELOW; - if(AFC==1)return TUNER_JUST_ABOVE; - return TUNER_OFF; - } - return TUNER_OFF; -} - -static int MT2032_get_afc_hint(FI1236Ptr f) -{ -CARD8 in; -CARD8 out[2]; -CARD8 AFC; -in=0x0e; -I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); -AFC=(out[0]>>4) & 0x7; -#if 0 -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC=%d TAD1=%d TAD2=%d\n", AFC, out[1] & 0x7, (out[1]>>4)& 0x07); -#endif -if(AFC==2)return TUNER_TUNED; -if(AFC==3)return TUNER_JUST_BELOW; -if(AFC==1)return TUNER_JUST_ABOVE; -return TUNER_OFF; -} - -/* this function is for external use only */ -int TUNER_get_afc_hint(FI1236Ptr f) -{ -if(f->afc_timer_installed)return TUNER_STILL_TUNING; -return f->last_afc_hint; -} - -static void MT2032_dump_status(FI1236Ptr f) -{ -CARD8 in; -CARD8 out[2]; -CARD8 AFC; -CARD8 LDONrb; -CARD8 LO1LK, LO2LK, XOK; -CARD8 TAD2, TAD1; - -in=0x0e; -I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); -XOK=out[0] & 1; -LO1LK=(out[0]>>2) &1; -LO2LK=(out[0]>>1) &1; -LDONrb=(out[0]>>3) &1; - -AFC=(out[0]>>4) & 0x7; - -TAD1=(out[1] & 0x7); -TAD2=(out[1]>>4) & 0x7; - -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: XOK=%d LO1LK=%d LO2LK=%d LDONrb=%d AFC=%d TAD1=%d TAD2=%d\n", - XOK, LO1LK, LO2LK, LDONrb, AFC, TAD1, TAD2); -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: OSCILLATOR:%s PLL1:%s PLL2:%s\n", - XOK ? "ok":"off", LO1LK ? "locked" : "off" , LO2LK ? "locked" : "off"); - -} - -static void MT2032_tune(FI1236Ptr f, double freq, double step) -{ -MT2032_parameters m; -CARD8 data[10]; -int i; -/* NTSC IF is 44mhz.. but 733/16=45.8125 and all TDAXXXX docs mention - 45.75, 39, 58.75 and 30. */ -#if 0 -MT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0, step); -MT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0, step); -#endif -MT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0, step); -MT2032_dump_parameters(f, &m); -MT2032_implement_settings(f, &m); -/* MT2032_dump_parameters(f, &m); */ -for(i=0;i<3;i++){ - MT2032_optimize_VCO(f, &m); - if(MT2032_wait_for_lock(f)){ - data[0]=0x02; /* LO Gain control register 0x02 */ - data[1]=0x20; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); - return; - } - data[0]=0x07; - data[1]=0x88|f->xogc; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); - usleep(15000); - data[1]=0x08|f->xogc; - I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); - } -xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); -} - -void FI1236_set_tuner_type(FI1236Ptr f, int type) -{ -f->type=type; -if(type>=NUM_TUNERS)type = NUM_TUNERS-1; -if(type<0)type = 0; -memcpy(&(f->parm), &(tuner_parms[type]), sizeof(FI1236_parameters)); -f->original_frequency=f->parm.min_freq; -f->afc_delta=0; -if(type==TUNER_TYPE_MT2032){ - MT2032_init(f); - return; - } -} - - -static CARD32 AFC_TimerCallback(OsTimerPtr timer, CARD32 time, pointer data){ -FI1236Ptr f=(FI1236Ptr)data; -if(FI1236_AFC(f))return 150; - else { - f->afc_timer_installed=FALSE; - f->afc_count=0; - return 0; - } -} - -void FI1236_tune(FI1236Ptr f, CARD32 frequency) -{ - CARD16 divider; - CARD8 data; - - if(frequency < f->parm.min_freq) frequency = f->parm.min_freq; - if(frequency > f->parm.max_freq) frequency = f->parm.max_freq; - - divider = (f->parm.fcar+(CARD16)frequency) & 0x7fff; - f->tuner_data.div1 = (CARD8)((divider>>8)&0x7f); - f->tuner_data.div2 = (CARD8)(divider & 0xff); - f->tuner_data.control = f->parm.control; - - if(frequency < f->parm.threshold1) - { - f->tuner_data.band = f->parm.band_low; - } - else if (frequency < f->parm.threshold2) - { - f->tuner_data.band = f->parm.band_mid; - } - else - { - f->tuner_data.band = f->parm.band_high; - } - - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner band to %d\n", f->tuner_data.band); - - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner frequency to %d\n", (int)frequency); - - if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) - { - f->tuner_data.aux = 0x20; - I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 5, NULL, 0); - I2C_WriteRead(&(f->d), NULL, 0, &data, 1); - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Tuner status %x\n", data); - - } - else - I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 4, NULL, 0); -} - -void TUNER_set_frequency(FI1236Ptr f, CARD32 frequency) -{ - if(frequency < f->parm.min_freq) frequency = f->parm.min_freq; - if(frequency > f->parm.max_freq) frequency = f->parm.max_freq; - - f->afc_delta=0; - f->original_frequency=frequency; - - if(f->type==TUNER_TYPE_MT2032) - { - MT2032_tune(f, (1.0*frequency)/16.0, 0.0625); - } else - { - FI1236_tune(f, frequency); - } - - if(!f->afc_timer_installed) - { - f->afc_timer_installed=TRUE; -/* RegisterBlockAndWakeupHandlers(FI1236_BlockHandler, AFCWakeup, f); */ - TimerSet(NULL, 0, 300, AFC_TimerCallback, f); - } - -} - - -int FI1236_AFC(FI1236Ptr f) -{ - #if 0 - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: f=%p f->count=%d f->original_frequency=%d f->afc_delta=%d\n", f, f->afc_count, f->original_frequency, f->afc_delta); - #endif - f->afc_count++; - if(f->type==TUNER_TYPE_MT2032) - { - f->last_afc_hint=MT2032_get_afc_hint(f); - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: afc_hint=%d\n", f->last_afc_hint); - if(f->last_afc_hint==TUNER_TUNED)return 0; - if(f->afc_count>3)f->last_afc_hint=TUNER_OFF; - if(f->last_afc_hint==TUNER_OFF) - { - f->afc_delta=0; - } else - f->afc_delta+=f->last_afc_hint; - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: Setting tuner frequency to %g\n", (0.5*(2*f->original_frequency+f->afc_delta))/16.0); - MT2032_tune(f, (1.0*f->original_frequency+0.5*f->afc_delta)/16.0, 0.03125); - if(f->last_afc_hint==TUNER_OFF)return 0; - return 1; /* call me again */ - } else - { - f->last_afc_hint=FI1236_get_afc_hint(f); - if(f->last_afc_hint==TUNER_TUNED) - { - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: TUNER_TUNNED\n"); - return 0; - } - if(f->afc_count>3)f->last_afc_hint=TUNER_OFF; - if(f->last_afc_hint==TUNER_OFF) - { - f->afc_delta=0; - } else - f->afc_delta+=f->last_afc_hint; - xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: Setting tuner frequency to %g\n", (0.5*(2*f->original_frequency+f->afc_delta))/16.0); - FI1236_tune(f, f->original_frequency+f->afc_delta); - if(f->last_afc_hint==TUNER_OFF)return 0; - return 1; /* call me again */ - } - return 0; /* done */ -} - -void fi1236_dump_status(FI1236Ptr f) -{ -if(f->type==TUNER_TYPE_MT2032){ - MT2032_dump_status(f); - } -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "xf86.h" +#include "xf86i2c.h" +#include "fi1236.h" +#include "tda9885.h" +#include "i2c_def.h" + +#define NUM_TUNERS 8 + +const FI1236_parameters tuner_parms[NUM_TUNERS] = +{ + /* 0 - FI1236 */ + { 733 ,884 ,12820 ,2516 ,7220 ,0xA2 ,0x94, 0x34, 0x8e }, + /* !!!based on documentation - it should be: + {733 ,16*55.25 ,16*801.25 ,16*160 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e},*/ + + /* 1 - FI1216 */ + { 623 ,16*48.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, + /* 2 - TEMIC FN5AL */ + { 623 ,16*45.75 ,16*855.25 ,16*169 ,16*454 ,0xA0 ,0x90, 0x30, 0x8e }, + /* 3 - MT2032.. */ + { 733 ,768 ,13760 , 0 , 0 , 0 , 0, 0, 0 }, + /* 4 - FI1246 */ + { 623 ,16*45.75 ,16*855.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, + /* 5 - FI1256 */ + { 623 ,16*49.75 ,16*863.25 ,16*170 ,16*450 ,0xA0 ,0x90, 0x30, 0x8e }, + /* 6 - FI1236W */ + /*{ 733 ,884 ,12820 ,2516 ,7220 ,0x1 ,0x2, 0x4, 0x8e },*/ + { 732, 16*55.25, 16*801.25, 16*160, 16*442, 0x1, 0x2, 0x4, 0x8e }, + /* 7 - FM1216ME */ + { 623 ,16*48.25 ,16*863.25 ,16*158.00 ,16*442.00 ,0x1 ,0x2, 0x4, 0x8e } +}; + + +FI1236Ptr Detect_FI1236(I2CBusPtr b, I2CSlaveAddr addr) +{ + FI1236Ptr f; + I2CByte a; + + f = calloc(1,sizeof(FI1236Rec)); + if(f == NULL) return NULL; + f->d.DevName = strdup("FI12xx Tuner"); + f->d.SlaveAddr = addr; + f->d.pI2CBus = b; + f->d.NextDev = NULL; + f->d.StartTimeout = b->StartTimeout; + f->d.BitTimeout = b->BitTimeout; + f->d.AcknTimeout = b->AcknTimeout; + f->d.ByteTimeout = b->ByteTimeout; + f->type=TUNER_TYPE_FI1236; + f->afc_timer_installed=FALSE; + f->last_afc_hint=TUNER_OFF; + f->video_if=45.7812; + + if(!I2C_WriteRead(&(f->d), NULL, 0, &a, 1)) + { + free(f); + return NULL; + } + FI1236_set_tuner_type(f, TUNER_TYPE_FI1236); + if(!I2CDevInit(&(f->d))) + { + free(f); + return NULL; + } + return f; +} + +static void MT2032_dump_parameters(FI1236Ptr f, MT2032_parameters *m) +{ +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: input f_rf=%g f_if1=%g f_if2=%g f_ref=%g f_ifbw=%g f_step=%g\n", + m->f_rf, m->f_if1, m->f_if2, m->f_ref, m->f_ifbw, m->f_step); + +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: computed f_lo1=%g f_lo2=%g LO1I=%d LO2I=%d SEL=%d STEP=%d NUM=%d\n", + m->f_lo1, m->f_lo2, m->LO1I, m->LO2I, m->SEL, m->STEP, m->NUM); +} + + +static void MT2032_getid(FI1236Ptr f) +{ +CARD8 out[4]; +CARD8 in; + +in=0x11; +I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 4); +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: Company code 0x%02x%02x, part code 0x%02x, revision code 0x%02x\n", + out[0], out[1], out[2], out[3]); + +} + +/* might be buggy */ +#if 0 +static void MT2032_shutdown(FI1236Ptr f) +{ +CARD8 data[10]; + +data[0]=0x00; /* start with register 0x00 */ +data[1]=0x1A; +data[2]=0x44; +data[3]=0x20; + +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +data[0]=0x05; /* now start with register 0x05 */ +data[1]=0xD7; +data[2]=0x14; +data[3]=0x05; +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +data[0]=0x0B; /* now start with register 0x05 */ +data[1]=0x8F; +data[2]=0x07; +data[3]=0x43; +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +usleep(15000); +} +#endif + +static void MT2032_dump_status(FI1236Ptr f); + +static void MT2032_init(FI1236Ptr f) +{ +CARD8 data[10]; +CARD8 value; +CARD8 xogc = 0x00; + +MT2032_getid(f); + +data[0]=0x02; /* start with register 0x02 */ +data[1]=0xFF; +data[2]=0x0F; +data[3]=0x1F; + +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +data[0]=0x06; /* now start with register 0x06 */ +data[1]=0xE4; +data[2]=0x8F; +data[3]=0xC3; +data[4]=0x4E; +data[5]=0xEC; +I2C_WriteRead(&(f->d), (I2CByte *)data, 6, NULL, 0); + +data[0]=0x0d; /* now start with register 0x0d */ +data[1]=0x32; +I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + +while(1) { + usleep(15000); /* wait 15 milliseconds */ + + data[0]=0x0e; /* register number 7, status */ + value=0xFF; + if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOK\n"); + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: XOK=%d\n", value & 0x01); + if(value & 1) break; + + data[0]=0x07; + if(!I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1)) + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to read XOGC\n"); + + xogc=value & 0x7; + if(xogc==4){ + break; /* XOGC has reached 4.. stop */ + } + xogc--; + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: try XOGC=%d\n", xogc); + usleep(15000); + data[0]=0x07; /* register number 7, control byte 2 */ + data[1]=0x08 | xogc; + I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + } +f->xogc=xogc; +/* wait before continuing */ +usleep(15000); /* wait 50 milliseconds */ +MT2032_dump_status(f); +} + +static int MT2032_no_spur_in_band(MT2032_parameters *m) +{ +int n_max, n1, n2; +double f_test; +n_max=5; +n1=1; +while(1){ + n2=-n1; + f_test=n1*(m->f_lo1-m->f_lo2); + while(1){ + n2--; + f_test=f_test-m->f_lo2; + xf86DrvMsg(0, X_INFO, "testing f_test=%g n1=%d n2=%d f_lo1=%g f_lo2=%g f_if2=%g\n", f_test, n1, n2, m->f_lo1, m->f_lo2, m->f_if2); + xf86DrvMsg(0, X_INFO, "d_f=%g f_ifbw=%g\n",fabs(fabs(f_test)-m->f_if2), m->f_ifbw); + if((fabs(fabs(f_test)-m->f_if2)*2.0)<=m->f_ifbw)return 0; + if(n2<=-n_max)break; + /* this line in the manual is bogus. I say it is faster + and more correct to go over all harmonics.. */ + #if 0 + if(f_test<(m->f_lo2-m->f_if2-m->f_ifbw))break; + #endif + } + n1++; + if(n1>=n_max)return 1; + } + +} + +static void MT2032_calculate_register_settings(MT2032_parameters *m, double f_rf, double f_if1, double f_if2, double f_ref, double f_ifbw, double f_step) +{ +int n; +m->f_rf=f_rf; +m->f_if1=f_if1; +m->f_if2=f_if2; +m->f_ref=f_ref; +m->f_ifbw=f_ifbw; +m->f_step=f_step; + +m->f_lo1=f_rf+f_if1; +m->LO1I=lrint(m->f_lo1/f_ref); +m->f_lo1=f_ref*m->LO1I; + +m->f_lo2=m->f_lo1-f_rf-f_if2; + +/* check for spurs */ +n=1; +while(n<3){ + if(MT2032_no_spur_in_band(m))break; + if(m->f_lo1<(f_rf+f_if1)){ + m->LO1I+=n; + } else { + m->LO1I-=n; + } + m->f_lo1=m->LO1I*f_ref; + m->f_lo2=m->f_lo1-f_rf-f_if2; + n++; + } +/* xf86DrvMsg(0, X_INFO, "MT2032: n=%d\n", n); */ +/* select VCO */ + +/* m->f_lo1>1100.0 */ +if(m->f_lo1<1370.0)m->SEL=4; + else +if(m->f_lo1<1530.0)m->SEL=3; + else +if(m->f_lo1<1720.0)m->SEL=2; + else +if(m->f_lo1<1890.0)m->SEL=1; + else /* m->f_lo1 < 1958.0 */ + m->SEL=0; + +/* calculate the rest of the registers */ +m->LO2I=floor(m->f_lo2/f_ref); +m->STEP=floor(3780.0*f_step/f_ref); +m->NUM=floor(3780.0*(m->f_lo2/f_ref-m->LO2I)); +m->NUM=m->STEP*lrint((1.0*m->NUM)/(1.0*m->STEP)); +} + +static int MT2032_wait_for_lock(FI1236Ptr f) +{ +int n; +CARD8 data[10]; +CARD8 value; + +n=12; +while(1){ + data[0]=0x0e; /* register number 7, status */ + I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); +/* xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: LO1LK=%d LO2LK=%d\n", (value & 0x04)>>2, (value & 0x02)>>1); */ + if((value & 6)==6) break; + usleep(1500); + n--; + if(n<0)break; + } +if(n<0){ + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); + return 0; + } +return 1; +} + +static void MT2032_implement_settings(FI1236Ptr f, MT2032_parameters *m) +{ +CARD8 data[10]; +CARD8 value; + +data[0]=0x00; /* start with register 0x00 */ +data[1]=(m->LO1I>>3)-1; +data[2]=(m->SEL<<4)|(m->LO1I & 0x7); +data[3]=0x86; +I2C_WriteRead(&(f->d), (I2CByte *)data, 4, NULL, 0); + +data[0]=0x05; /* start with register 0x05 */ +data[1]=((m->LO2I & 0x7)<<5)|((m->LO2I>>3)-1); +if(m->f_rf<400.0)data[2]=0xe4; + else data[2]=0xf4; +I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); + +data[0]=0x07; /* register number 7, control byte 2 */ +I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: using XOGC=%d\n", (value & 0x07)); +data[1]=8 | (value & 0x7); +I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + +data[0]=0x0b; /* start with register 0x0b */ +data[1]=m->NUM & 0xff; +data[2]=(1<<7)|((m->NUM >> 8) & 0x0f); +I2C_WriteRead(&(f->d), (I2CByte *)data, 3, NULL, 0); + +MT2032_wait_for_lock(f); +} + +static void MT2032_optimize_VCO(FI1236Ptr f, MT2032_parameters *m) +{ +CARD8 data[10]; +CARD8 value; +CARD8 TAD1; + +data[0]=0x0f; /* register number 7, status */ +I2C_WriteRead(&(f->d), (I2CByte *)data, 1, &value, 1); +TAD1=value & 0x07; +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: TAD1=%d SEL=%d\n", TAD1, m->SEL); +if(TAD1 < 2)return; +if(TAD1==2){ + if(m->SEL==0)return; + m->SEL--; + } else { + if(m->SEL>=4)return; + m->SEL++; + } +data[0]=0x01; /* start with register 1 */ +data[1]=(m->SEL<<4)|(m->LO1I & 0x7); +I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + +} + +static int FI1236_get_afc_hint(FI1236Ptr f) +{ + CARD8 out; + CARD8 AFC; + + if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) + { + TDA9885Ptr t = (TDA9885Ptr)f->afc_source; + if (t == NULL) + return TUNER_OFF; + + tda9885_getstatus(t); + tda9885_dumpstatus(t); + AFC = t->afc_status & 0x0f; + + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC); + if (AFC == 0) return TUNER_TUNED; + else if (AFC <= 0x07)return TUNER_JUST_BELOW; + else if (AFC < 0x0f )return TUNER_JUST_ABOVE; + else if (AFC == 0x0f)return TUNER_TUNED; + } + else + { + I2C_WriteRead(&(f->d), NULL, 0, &out, 1); + AFC=out & 0x7; + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: FI1236_get_afc_hint: %i\n", AFC); + if(AFC==2)return TUNER_TUNED; + if(AFC==3)return TUNER_JUST_BELOW; + if(AFC==1)return TUNER_JUST_ABOVE; + return TUNER_OFF; + } + return TUNER_OFF; +} + +static int MT2032_get_afc_hint(FI1236Ptr f) +{ +CARD8 in; +CARD8 out[2]; +CARD8 AFC; +in=0x0e; +I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); +AFC=(out[0]>>4) & 0x7; +#if 0 +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC=%d TAD1=%d TAD2=%d\n", AFC, out[1] & 0x7, (out[1]>>4)& 0x07); +#endif +if(AFC==2)return TUNER_TUNED; +if(AFC==3)return TUNER_JUST_BELOW; +if(AFC==1)return TUNER_JUST_ABOVE; +return TUNER_OFF; +} + +/* this function is for external use only */ +int TUNER_get_afc_hint(FI1236Ptr f) +{ +if(f->afc_timer_installed)return TUNER_STILL_TUNING; +return f->last_afc_hint; +} + +static void MT2032_dump_status(FI1236Ptr f) +{ +CARD8 in; +CARD8 out[2]; +CARD8 AFC; +CARD8 LDONrb; +CARD8 LO1LK, LO2LK, XOK; +CARD8 TAD2, TAD1; + +in=0x0e; +I2C_WriteRead(&(f->d), (I2CByte *)&in, 1, out, 2); +XOK=out[0] & 1; +LO1LK=(out[0]>>2) &1; +LO2LK=(out[0]>>1) &1; +LDONrb=(out[0]>>3) &1; + +AFC=(out[0]>>4) & 0x7; + +TAD1=(out[1] & 0x7); +TAD2=(out[1]>>4) & 0x7; + +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: XOK=%d LO1LK=%d LO2LK=%d LDONrb=%d AFC=%d TAD1=%d TAD2=%d\n", + XOK, LO1LK, LO2LK, LDONrb, AFC, TAD1, TAD2); +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: status: OSCILLATOR:%s PLL1:%s PLL2:%s\n", + XOK ? "ok":"off", LO1LK ? "locked" : "off" , LO2LK ? "locked" : "off"); + +} + +static void MT2032_tune(FI1236Ptr f, double freq, double step) +{ +MT2032_parameters m; +CARD8 data[10]; +int i; +/* NTSC IF is 44mhz.. but 733/16=45.8125 and all TDAXXXX docs mention + 45.75, 39, 58.75 and 30. */ +#if 0 +MT2032_calculate_register_settings(&m, freq, 1090.0, 45.125, 5.25, 6.0, step); +MT2032_calculate_register_settings(&m, freq, 1090.0, 45.74, 5.25, 6.0, step); +#endif +MT2032_calculate_register_settings(&m, freq, 1090.0, f->video_if, 5.25, 3.0, step); +MT2032_dump_parameters(f, &m); +MT2032_implement_settings(f, &m); +/* MT2032_dump_parameters(f, &m); */ +for(i=0;i<3;i++){ + MT2032_optimize_VCO(f, &m); + if(MT2032_wait_for_lock(f)){ + data[0]=0x02; /* LO Gain control register 0x02 */ + data[1]=0x20; + I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + return; + } + data[0]=0x07; + data[1]=0x88|f->xogc; + I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + usleep(15000); + data[1]=0x08|f->xogc; + I2C_WriteRead(&(f->d), (I2CByte *)data, 2, NULL, 0); + } +xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "MT2032: failed to set frequency\n"); +} + +void FI1236_set_tuner_type(FI1236Ptr f, int type) +{ +f->type=type; +if(type>=NUM_TUNERS)type = NUM_TUNERS-1; +if(type<0)type = 0; +memcpy(&(f->parm), &(tuner_parms[type]), sizeof(FI1236_parameters)); +f->original_frequency=f->parm.min_freq; +f->afc_delta=0; +if(type==TUNER_TYPE_MT2032){ + MT2032_init(f); + return; + } +} + + +static CARD32 AFC_TimerCallback(OsTimerPtr timer, CARD32 time, pointer data){ +FI1236Ptr f=(FI1236Ptr)data; +if(FI1236_AFC(f))return 150; + else { + f->afc_timer_installed=FALSE; + f->afc_count=0; + return 0; + } +} + +void FI1236_tune(FI1236Ptr f, CARD32 frequency) +{ + CARD16 divider; + CARD8 data; + + if(frequency < f->parm.min_freq) frequency = f->parm.min_freq; + if(frequency > f->parm.max_freq) frequency = f->parm.max_freq; + + divider = (f->parm.fcar+(CARD16)frequency) & 0x7fff; + f->tuner_data.div1 = (CARD8)((divider>>8)&0x7f); + f->tuner_data.div2 = (CARD8)(divider & 0xff); + f->tuner_data.control = f->parm.control; + + if(frequency < f->parm.threshold1) + { + f->tuner_data.band = f->parm.band_low; + } + else if (frequency < f->parm.threshold2) + { + f->tuner_data.band = f->parm.band_mid; + } + else + { + f->tuner_data.band = f->parm.band_high; + } + + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner band to %d\n", f->tuner_data.band); + + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Setting tuner frequency to %d\n", (int)frequency); + + if ((f->type == TUNER_TYPE_FM1216ME) || (f->type == TUNER_TYPE_FI1236W)) + { + f->tuner_data.aux = 0x20; + I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 5, NULL, 0); + I2C_WriteRead(&(f->d), NULL, 0, &data, 1); + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "Tuner status %x\n", data); + + } + else + I2C_WriteRead(&(f->d), (I2CByte *)&(f->tuner_data), 4, NULL, 0); +} + +void TUNER_set_frequency(FI1236Ptr f, CARD32 frequency) +{ + if(frequency < f->parm.min_freq) frequency = f->parm.min_freq; + if(frequency > f->parm.max_freq) frequency = f->parm.max_freq; + + f->afc_delta=0; + f->original_frequency=frequency; + + if(f->type==TUNER_TYPE_MT2032) + { + MT2032_tune(f, (1.0*frequency)/16.0, 0.0625); + } else + { + FI1236_tune(f, frequency); + } + + if(!f->afc_timer_installed) + { + f->afc_timer_installed=TRUE; +/* RegisterBlockAndWakeupHandlers(FI1236_BlockHandler, AFCWakeup, f); */ + TimerSet(NULL, 0, 300, AFC_TimerCallback, f); + } + +} + + +int FI1236_AFC(FI1236Ptr f) +{ + #if 0 + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: f=%p f->count=%d f->original_frequency=%d f->afc_delta=%d\n", f, f->afc_count, f->original_frequency, f->afc_delta); + #endif + f->afc_count++; + if(f->type==TUNER_TYPE_MT2032) + { + f->last_afc_hint=MT2032_get_afc_hint(f); + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: afc_hint=%d\n", f->last_afc_hint); + if(f->last_afc_hint==TUNER_TUNED)return 0; + if(f->afc_count>3)f->last_afc_hint=TUNER_OFF; + if(f->last_afc_hint==TUNER_OFF) + { + f->afc_delta=0; + } else + f->afc_delta+=f->last_afc_hint; + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: Setting tuner frequency to %g\n", (0.5*(2*f->original_frequency+f->afc_delta))/16.0); + MT2032_tune(f, (1.0*f->original_frequency+0.5*f->afc_delta)/16.0, 0.03125); + if(f->last_afc_hint==TUNER_OFF)return 0; + return 1; /* call me again */ + } else + { + f->last_afc_hint=FI1236_get_afc_hint(f); + if(f->last_afc_hint==TUNER_TUNED) + { + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: TUNER_TUNNED\n"); + return 0; + } + if(f->afc_count>3)f->last_afc_hint=TUNER_OFF; + if(f->last_afc_hint==TUNER_OFF) + { + f->afc_delta=0; + } else + f->afc_delta+=f->last_afc_hint; + xf86DrvMsg(f->d.pI2CBus->scrnIndex, X_INFO, "AFC: Setting tuner frequency to %g\n", (0.5*(2*f->original_frequency+f->afc_delta))/16.0); + FI1236_tune(f, f->original_frequency+f->afc_delta); + if(f->last_afc_hint==TUNER_OFF)return 0; + return 1; /* call me again */ + } + return 0; /* done */ +} + +void fi1236_dump_status(FI1236Ptr f) +{ +if(f->type==TUNER_TYPE_MT2032){ + MT2032_dump_status(f); + } +} diff --git a/xorg-server/hw/xfree86/i2c/msp3430.c b/xorg-server/hw/xfree86/i2c/msp3430.c index 4bd3a7187..b58c3f09c 100644 --- a/xorg-server/hw/xfree86/i2c/msp3430.c +++ b/xorg-server/hw/xfree86/i2c/msp3430.c @@ -1,726 +1,726 @@ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include - -#include "xf86.h" -#include "xf86i2c.h" -#include "msp3430.h" -#include "i2c_def.h" - -#define CONTROL 0x00 -#define WR_DEM 0x10 -#define RD_DEM 0x11 -#define WR_DSP 0x12 -#define RD_DSP 0x13 - - -void InitMSP34xxG(MSP3430Ptr m); -void InitMSP34x5D(MSP3430Ptr m); -void CheckModeMSP34x5D(MSP3430Ptr m); -char *MSP_getProductName (CARD16 product_id); -void mpause(int milliseconds); - -#define __MSPDEBUG__ 0 - -#if __MSPDEBUG__ > 3 - -void MSPBeep(MSP3430Ptr m, CARD8 freq); -#define __MSPBEEP MSPBeep(m,0x14); - -#else - -#define __MSPBEEP -#endif - -static void SetMSP3430Control(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegValueHigh, CARD8 RegValueLow) -{ - I2CByte data[3]; - - data[0]=RegAddress; - data[1]=RegValueHigh; - data[2]=RegValueLow; - - I2C_WriteRead(&(m->d),data,3,NULL,0); -} - -static void SetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, - CARD8 RegValueHigh, CARD8 RegValueLow) -{ - I2CByte data[5]; -#ifdef MSP_DEBUG - if(!m->registers_present[RegSubAddressLow]){ - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_ERROR, "Attempt to access non-existent register in MSP34xxX: 0x%02x 0x%02x 0x%02x <- 0x%02x 0x%02x\n", - RegAddress, RegSubAddressHigh, RegSubAddressLow, RegValueHigh, RegValueLow); - } -#endif - - data[0] = RegAddress; - data[1] = RegSubAddressHigh; - data[2] = RegSubAddressLow; - data[3] = RegValueHigh; - data[4] = RegValueLow; - - I2C_WriteRead(&(m->d),data,5,NULL,0); -} - -static void GetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, - CARD8 *RegValueHigh, CARD8 *RegValueLow) -{ - I2CByte send[3]; - I2CByte receive[2]; - - send[0] = RegAddress; - send[1] = RegSubAddressHigh; - send[2] = RegSubAddressLow; - - I2C_WriteRead(&(m->d), send, 3, receive, 2); - - *RegValueHigh = receive[0]; - *RegValueLow = receive[1]; -} - -#if __MSPDEBUG__ > 2 -static void MSP3430DumpStatus(MSP3430Ptr m) -{ -CARD8 status_hi, status_lo; -CARD8 subaddr, data[2]; - -GetMSP3430Data(m, RD_DEM, 0x02, 0x00, &status_hi, &status_lo); -xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: SAP(8)=%d mono/NICAM(7)=%d stereo=%d %s O_1=%d O_0=%d 2nd car=%d 1st car=%d\n", - status_hi & 1, (status_lo>>7) & 1, (status_lo>>6)&1, - (status_lo>>5)? ( (status_hi>>1)&1? "bad NICAM reception" : "NICAM" ) : - ((status_hi>>1)&1 ? "bogus" : "ANALOG FM/AM") , - (status_lo>>4)&1, (status_lo>>3)&1,!( (status_lo>>2)&1), !((status_lo>>1)&1)); - -GetMSP3430Data(m, RD_DEM, 0x00, 0x7E, &status_hi, &status_lo); -xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: standard result=0x%02x%02x\n", - status_hi, status_lo); -subaddr=0x0; -I2C_WriteRead(&(m->d), &subaddr, 1, data, 2); -xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: control=0x%02x%02x\n", - data[1], data[0]); -} -#endif - -/* wrapper */ -void InitMSP3430(MSP3430Ptr m) -{ - #if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP3430(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", - m->connector, m->standard, m->chip_family); - #endif - switch (m->chip_family) { - case MSPFAMILY_34x0G: - InitMSP34xxG(m); - break; - case MSPFAMILY_34x5G: - InitMSP34xxG(m); - break; - case MSPFAMILY_34x5D: - InitMSP34x5D(m); - break; - } -} - -/*----------------------------------------------------------------- -| common functions for all MSP34xx chips -|----------------------------------------------------------------*/ - -MSP3430Ptr DetectMSP3430(I2CBusPtr b, I2CSlaveAddr addr) -{ - MSP3430Ptr m; - I2CByte a; - CARD8 hardware_version, major_revision, product_code, rom_version; - Bool supported; - - m = xcalloc(1,sizeof(MSP3430Rec)); - if(m == NULL)return NULL; - m->d.DevName = strdup("MSP34xx"); - m->d.SlaveAddr = addr; - m->d.pI2CBus = b; - m->d.NextDev = NULL; - m->d.StartTimeout = b->StartTimeout; - m->d.BitTimeout = b->BitTimeout; - m->d.AcknTimeout = b->AcknTimeout; - m->d.ByteTimeout = b->ByteTimeout; - - if(!I2C_WriteRead(&(m->d), NULL, 0, &a, 1)) - { - xfree(m->d.DevName); - xfree(m); - return NULL; - } - - - m->standard=MSP3430_NTSC; - m->connector=MSP3430_CONNECTOR_1; - m->mode=MSPMODE_STEREO_A; /*stereo or chanel A if avail. */ - m->c_format=MSPFORMAT_UNKNOWN; - m->c_standard=MSPSTANDARD_UNKNOWN; - m->c_matrix=m->c_fmmatrix=m->c_source=0; - m->volume=0; - m->recheck=FALSE; - - GetMSP3430Data(m, RD_DSP, 0x00, 0x1E, &hardware_version, &major_revision); - GetMSP3430Data(m, RD_DSP, 0x00, 0x1F, &product_code, &rom_version); - m->hardware_version=hardware_version; - m->major_revision=major_revision; - m->product_code=product_code; - m->rom_version=rom_version; - - m->chip_id=((major_revision << 8) | product_code); - - supported=FALSE; - switch (major_revision) { - case 4: /* 34xxD */ - switch (product_code) { - case 0x05: /* 3405D */ - case 0x0A: /* 3410D */ - case 0x0F: /* 3415D */ - m->chip_family=MSPFAMILY_34x5D; - m->recheck=TRUE; - supported=TRUE; - break; - default: - m->chip_family=MSPFAMILY_34x0D; - } - break; - case 7: /* 34xxG */ - switch(product_code){ - case 0x00: - case 0x0A: - case 0x1E: - case 0x28: - case 0x32: - m->chip_family=MSPFAMILY_34x0G; - supported=TRUE; - break; - case 0x0f: - case 0x19: - case 0x2d: - case 0x37: - case 0x41: - m->chip_family=MSPFAMILY_34x5G; - supported=TRUE; - #ifdef MSP_DEBUG - memset(m->registers_present, 0, 256); - #define A(num) m->registers_present[(num)]=1; - #define B(num1, num2) memset(&(m->registers_present[num1]), 1, num2-num1); - A(0x20) - A(0x30) - A(0x40) - A(0x00) - B(0x01, 0x08) - B(0x0B, 0x0E) - A(0x10) - B(0x12,0x14) - A(0x16) - A(0x29) - #undef B - #undef A - #endif - break; - default: - m->chip_family=MSPFAMILY_UNKNOWN; - } - break; - default: - m->chip_family=MSPFAMILY_UNKNOWN; - } - - xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Found %s%s, rom version 0x%02x, chip_id=0x%04x\n", - MSP_getProductName(m->chip_id), supported?"":" (unsupported)", rom_version, m->chip_id); - - if (!supported) { - xfree(m->d.DevName); - xfree(m); - return NULL; - } - if(!I2CDevInit(&(m->d))) - { - xfree(m->d.DevName); - xfree(m); - return NULL; - } - - return m; -} - -void ResetMSP3430(MSP3430Ptr m) -{ - /* Reset the MSP3430 */ - SetMSP3430Control(m, 0x00, 0x80, 0x00); - /* Set it back to normal operation */ - SetMSP3430Control(m, 0x00, 0x00, 0x00); - - m->c_format=MSPFORMAT_UNKNOWN; - m->c_standard=MSPSTANDARD_UNKNOWN; - m->c_matrix=m->c_fmmatrix=m->c_source=0; - m->volume=0; -} - -void MSP3430SetVolume (MSP3430Ptr m, CARD8 value) -{ - CARD8 result; -#if 0 - CARD8 old_volume; - GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); - xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 result 0x%02x\n", result); -#endif - /* save an extra Get call */ - result=0; - - SetMSP3430Data(m, WR_DSP, 0x00, 0x00, value, result); - - SetMSP3430Data(m, WR_DSP, 0x00, 0x07, value, 0); - m->volume=value; - -#if __MSPDEBUG__ > 2 - MSP3430DumpStatus(m); - __MSPBEEP - GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); - xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 volume 0x%02x\n",value); -#endif -} - - -void MSP3430SetSAP (MSP3430Ptr m, int mode) -{ - xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Put actual code to change SAP here\n"); - - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, mode & 0xff, 0x20); -} - - -#if 0 -void MSP3430SetSource(MSP3430Ptr m, CARD8 value) -{ - /* Write to DSP, register 0x0008, (loudspeaker channel source/matrix) */ - /* This sets the source to the TV tuner, for stereo operation */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, value, 0x20); -} -#endif - - -char *MSP_getProductName (CARD16 product_id) -{ - switch (product_id) { - case 0x0400: return "MSP3400D"; - case 0x040a: return "MSP3410D"; - case 0x0405: return "MSP3405D"; - case 0x040f: return "MSP3415D"; - case 0x0700: return "MSP3400G"; - case 0x070a: return "MSP3410G"; - case 0x071e: return "MSP3430G"; - case 0x0728: return "MSP3440G"; - case 0x0732: return "MSP3450G"; - case 0x070f: return "MSP3415G"; - case 0x0719: return "MSP3425G"; - case 0x072d: return "MSP3445G"; - case 0x0737: return "MSP3455G"; - case 0x0741: return "MSP3465G"; - } - return "MSP - unknown type"; -} - -#if __MSPDEBUG__ > 2 -/*puts beep in MSP output - freq = 0x01 - 16Hz ... 0x40 - 1kHz ... 0xff - 4kHz -*/ -void MSPBeep(MSP3430Ptr m, CARD8 freq) { - SetMSP3430Data (m, WR_DSP, 0x00, freq, 0x7f, 0x40); - mpause(100); - SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x00); -} -#endif - -void mpause(int milliseconds) { - int i,m; - m=milliseconds/20; - for (i=0;i 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP34xxG(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", - m->connector, m->standard, m->chip_family); - #endif - /* Reset MSP3430 */ - SetMSP3430Control(m, 0x00, 0x80, 0x00); - /* Set it back to normal operation */ - SetMSP3430Control(m, 0x00, 0x00, 0x00); - - /*set MODUS register */ - /* bits: 0 - automatic sound detection */ - /* 1 - enable STATUS change */ - /* 12 - detect 6.5 Mhz carrier as D/K1, D/K2 or D/K NICAM (does not seem to work ) */ - /* 13 - detect 4.5 Mhz carrier as BTSC */ - if ( (m->standard & 0xff) == MSP3430_PAL ) - { - SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x30, 0x03|0x08); /* make O_ pins tristate */ - /* PAL standard */ - SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x01); /* possibly wrong */ - } else { - SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x20, 0x03|0x08); - /* standard selection is M-BTSC-Stereo */ - SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x20); - } - - switch(m->connector){ - case MSP3430_CONNECTOR_1: - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x03, 0x20); - break; - case MSP3430_CONNECTOR_2: - /* this has not been checked yet.. could be bogus */ - /* SCART Input Prescale: 0 dB gain */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); - break; - case MSP3430_CONNECTOR_3: - default: - /* SCART Input Prescale: 0 dB gain */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); - - SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); - break; - } - - switch(m->standard){ - case MSP3430_PAL: - SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); - SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); - SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x03); - /* Set volume to FAST_MUTE. */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); - break; - case MSP3430_PAL_DK1: - SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); - SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); - SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x04); - /* Set volume to FAST_MUTE. */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); - break; - case MSP3430_SECAM: /* is this right ? */ - case MSP3430_NTSC: - /* Write to DSP, register 0x000E, (prescale FM/FM matrix) */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); - - /* Set volume to FAST_MUTE. */ - SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); - break; - } - -} - -/*----------------------------------------------------------------- -| specific functions for all MSP34x5D chips -|----------------------------------------------------------------*/ - -void InitMSP34x5D(MSP3430Ptr m) -{ -int count; -CARD8 high,low; -CARD16 result,standard; -CARD16 peak; - - -if (m->c_format==MSPFORMAT_UNKNOWN) ResetMSP3430(m); -else { - /*mute volume*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x00, 0x00, 0x00); -} - - - - switch(m->connector){ - case MSP3430_CONNECTOR_2: - case MSP3430_CONNECTOR_3: - if (m->c_format!=MSPFORMAT_SCART) { - /* SCART Input Prescale: 0 dB gain */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); - /* this has not been checked yet.. could be bogus */ - m->c_format=MSPFORMAT_SCART; /*stereo*/ - } - break; - case MSP3430_CONNECTOR_1: - default: - - switch ( m->standard & 0x00ff ) { - case MSP3430_PAL: - switch( m->standard ) { - case MSP3430_PAL_DK1: - standard=MSPSTANDARD_FM_DK1; - break; -/* case MSP3430_PAL_DK2: - standard=MSPSTANDARD_FM_DK2; - break; - case MSP3430_PAL_BG: - may be FM stereo (Germany) or FM NICAM (Scandinavia,spain) - standard=MSPSTANDARD_AUTO; - break; -*/ - default: - standard=MSPSTANDARD_AUTO; - } - break; - case MSP3430_SECAM: - standard=MSPSTANDARD_AUTO; - case MSP3430_NTSC: - /* Only MSP34x5 supported format - Korean NTSC-M*/ - standard=MSPSTANDARD_FM_M; - default: - standard=MSPSTANDARD_AUTO; - } - - /*no NICAM support in MSP3410D - force to autodetect*/ - if ((m->chip_id==0x405) && (standard>=MSPSTANDARD_NICAM_BG)) - standard=MSPSTANDARD_AUTO; - - if (m->c_standard != standard) { - - SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF); - if (standard==MSPSTANDARD_AUTO) { - count = 50; /* time shouldn't exceed 1s, just in case */ - do { - usleep(20000); - GetMSP3430Data (m, RD_DEM, 0x00, 0x7e, &high, &low); - result = ( high << 8 ) | low; - --count; - } while( result > 0x07ff && count > 0 ); - - if ((result > MSPSTANDARD_AUTO)) - standard=result; - else standard=MSPSTANDARD_UNKNOWN; -#if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Detected audio standard: %d\n",result); -#endif - /* result = MSPSTANDARD_NICAM_L can be one of: - SECAM_L - MSPSTANDARD_NICAM_L - D/K1 - MSPSTANDARD_FM_DK1 - D/K2 - MSPSTANDARD_FM_DK2 - D/K-NICAM - MSPSTANDARD_NICAM_DK*/ - if( standard == MSPSTANDARD_NICAM_L ) { - if ((m->standard & 0x00ff)==MSP3430_PAL) { - /* force PAL D/K */ - standard=MSPSTANDARD_FM_DK1; - SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF); -#if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO, "Detected 6.5MHz carrier - forced to D/K1 !!!\n" ); -#endif - } - } - } - m->c_standard=standard; - } /*end - standard changed*/ - else { - if (standardc_format=MSPFORMAT_1xFM; - } - else if (standardL ch1->R*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0c, 0x00, 0x20); - - mpause(250); - GetMSP3430Data (m, RD_DSP, 0x00, 0x1A, &high, &low); - peak = (high << 8) | low; -#if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Second carrier Quasi-Peak detection: %d\n",peak); -#endif - /*turn on FM DC Notch*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x00); - - if (peak<5) { - /* if second carrier not detected - only mono from first carrier*/ - m->c_format=MSPFORMAT_1xFM; - } - else { - m->c_format=MSPFORMAT_2xFM; - /*start of FM identification process - FM_WAIT - wait at least 0.5s - used 1s - gives beter resolution*/ - mpause(1000); - } - } - else { - if (standard==MSPSTANDARD_NICAM_L) { - m->c_format=MSPFORMAT_NICAM_AM; - /* set AM prescale */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x7C, 0); - } - else { - m->c_format=MSPFORMAT_NICAM_FM; - /* set FM prescale */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0); - } - /* set FM deemphasis*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, 0x00, 0); - /* set NICAM prescale to 0dB */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x10, 0x20, 0); - } - - break; - } /*end - case conector*/ - - CheckModeMSP34x5D(m); - - /* Set volume to FAST_MUTE. */ - /*SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00);*/ - /*set volume*/ - MSP3430SetVolume(m,m->volume); - - __MSPBEEP - - -} /* EnableMSP34x5D ()... */ - - - - -void CheckModeMSP34x5D(MSP3430Ptr m) { - const char stereo_on=25; - const char stereo_off=20; - const char dual_on=-stereo_on; - const char dual_off=-stereo_off; - char detect; - CARD8 matrix, fmmatrix, source, high, low; - - fmmatrix=0; /*no matrix*/ - source=0; /*FM*/ - switch (m->c_format) { - case MSPFORMAT_NICAM_FM: - case MSPFORMAT_NICAM_AM: - case MSPFORMAT_SCART: - source=( (m->c_format == MSPFORMAT_SCART)?2:1 ); - switch (m->mode) { - case MSPMODE_MONO: - matrix=0x30; /*MONO*/ - break; - case MSPMODE_A: - matrix=0x00; /*A*/ - break; - case MSPMODE_B: - matrix=0x10; /*B*/ - break; - default: - matrix=0x20; /*STEREO*/ - break; - } - break; - default: - case MSPFORMAT_1xFM: - matrix=0x00; /*A*/ - break; - case MSPFORMAT_2xFM: - switch (m->mode) { - case MSPMODE_MONO: - matrix=0x30; /*MONO*/ - break; - case MSPMODE_STEREO: - matrix=0x20; /*STEREO*/ - fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1); - break; - case MSPMODE_AB: - matrix=0x20; /*STEREO*/ - break; - case MSPMODE_A: - matrix=0x00; /*A*/ - break; - case MSPMODE_B: - matrix=0x10; /*B*/ - break; - default: - /*FM_IDENT_CHECK*/ - GetMSP3430Data (m, RD_DSP, 0x00, 0x18, &high, &low); - detect=(char)high; -#if __MSPDEBUG__ > 1 - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Stereo Detection Register: %d\n",detect); -#endif - if (detect>=((m->c_mode==MSPMODE_STEREO)?stereo_off:stereo_on)) { - m->c_mode=MSPMODE_STEREO; - matrix=0x20; /*STEREO*/ - fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1); - } - else if (detect<=((m->c_mode==MSPMODE_AB)?dual_off:dual_on)) { - m->c_mode=MSPMODE_AB; - switch (m->mode) { - case MSPMODE_STEREO_AB: matrix=0x20; break; - case MSPMODE_STEREO_B: matrix=0x10; break; - default: - case MSPMODE_A: matrix=0x00; break; - } - } - else { - m->c_mode=MSPMODE_MONO; - matrix=0x30; /*MONO*/ - } - break; - } /* end - case mode*/ - break; - } - - if (m->c_fmmatrix != fmmatrix) { - GetMSP3430Data (m, RD_DSP, 0x00, 0x0e, &high, &low); - SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, high, fmmatrix); - m->c_fmmatrix = fmmatrix; - } - - if ((m->c_matrix != matrix) || (m->c_source != source)) { - /*set chanel source and matrix for loudspeaker*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x08, source, matrix); - - m->c_matrix = matrix; - m->c_source = source; - } - - if ( ((m->c_format) & 0xF0) == MSPFORMAT_NICAM) - SetMSP3430Data (m, WR_DEM, 0x00, 0x21, 0, 1); - -#if __MSPDEBUG__ > 0 - char *msg; - switch (matrix) { - case 0x30: /*MONO*/ - msg="MONO"; - break; - case 0x00: /*LEFT*/ - msg="MONO/CHANNEL_1"; - break; - case 0x10: /*RIGHT*/ - msg="MONO/CHANNEL_2"; - break; - case 0x20: /*LEFT*/ - msg="STEREO"; - break; - default: - msg="unknown"; - break; - } - xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Audio mode set to: %s\n",msg); -#endif -} - +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +#include "xf86.h" +#include "xf86i2c.h" +#include "msp3430.h" +#include "i2c_def.h" + +#define CONTROL 0x00 +#define WR_DEM 0x10 +#define RD_DEM 0x11 +#define WR_DSP 0x12 +#define RD_DSP 0x13 + + +void InitMSP34xxG(MSP3430Ptr m); +void InitMSP34x5D(MSP3430Ptr m); +void CheckModeMSP34x5D(MSP3430Ptr m); +char *MSP_getProductName (CARD16 product_id); +void mpause(int milliseconds); + +#define __MSPDEBUG__ 0 + +#if __MSPDEBUG__ > 3 + +void MSPBeep(MSP3430Ptr m, CARD8 freq); +#define __MSPBEEP MSPBeep(m,0x14); + +#else + +#define __MSPBEEP +#endif + +static void SetMSP3430Control(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegValueHigh, CARD8 RegValueLow) +{ + I2CByte data[3]; + + data[0]=RegAddress; + data[1]=RegValueHigh; + data[2]=RegValueLow; + + I2C_WriteRead(&(m->d),data,3,NULL,0); +} + +static void SetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, + CARD8 RegValueHigh, CARD8 RegValueLow) +{ + I2CByte data[5]; +#ifdef MSP_DEBUG + if(!m->registers_present[RegSubAddressLow]){ + xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_ERROR, "Attempt to access non-existent register in MSP34xxX: 0x%02x 0x%02x 0x%02x <- 0x%02x 0x%02x\n", + RegAddress, RegSubAddressHigh, RegSubAddressLow, RegValueHigh, RegValueLow); + } +#endif + + data[0] = RegAddress; + data[1] = RegSubAddressHigh; + data[2] = RegSubAddressLow; + data[3] = RegValueHigh; + data[4] = RegValueLow; + + I2C_WriteRead(&(m->d),data,5,NULL,0); +} + +static void GetMSP3430Data(MSP3430Ptr m, CARD8 RegAddress, CARD8 RegSubAddressHigh, CARD8 RegSubAddressLow, + CARD8 *RegValueHigh, CARD8 *RegValueLow) +{ + I2CByte send[3]; + I2CByte receive[2]; + + send[0] = RegAddress; + send[1] = RegSubAddressHigh; + send[2] = RegSubAddressLow; + + I2C_WriteRead(&(m->d), send, 3, receive, 2); + + *RegValueHigh = receive[0]; + *RegValueLow = receive[1]; +} + +#if __MSPDEBUG__ > 2 +static void MSP3430DumpStatus(MSP3430Ptr m) +{ +CARD8 status_hi, status_lo; +CARD8 subaddr, data[2]; + +GetMSP3430Data(m, RD_DEM, 0x02, 0x00, &status_hi, &status_lo); +xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: SAP(8)=%d mono/NICAM(7)=%d stereo=%d %s O_1=%d O_0=%d 2nd car=%d 1st car=%d\n", + status_hi & 1, (status_lo>>7) & 1, (status_lo>>6)&1, + (status_lo>>5)? ( (status_hi>>1)&1? "bad NICAM reception" : "NICAM" ) : + ((status_hi>>1)&1 ? "bogus" : "ANALOG FM/AM") , + (status_lo>>4)&1, (status_lo>>3)&1,!( (status_lo>>2)&1), !((status_lo>>1)&1)); + +GetMSP3430Data(m, RD_DEM, 0x00, 0x7E, &status_hi, &status_lo); +xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: standard result=0x%02x%02x\n", + status_hi, status_lo); +subaddr=0x0; +I2C_WriteRead(&(m->d), &subaddr, 1, data, 2); +xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP34xx: control=0x%02x%02x\n", + data[1], data[0]); +} +#endif + +/* wrapper */ +void InitMSP3430(MSP3430Ptr m) +{ + #if __MSPDEBUG__ > 1 + xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP3430(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", + m->connector, m->standard, m->chip_family); + #endif + switch (m->chip_family) { + case MSPFAMILY_34x0G: + InitMSP34xxG(m); + break; + case MSPFAMILY_34x5G: + InitMSP34xxG(m); + break; + case MSPFAMILY_34x5D: + InitMSP34x5D(m); + break; + } +} + +/*----------------------------------------------------------------- +| common functions for all MSP34xx chips +|----------------------------------------------------------------*/ + +MSP3430Ptr DetectMSP3430(I2CBusPtr b, I2CSlaveAddr addr) +{ + MSP3430Ptr m; + I2CByte a; + CARD8 hardware_version, major_revision, product_code, rom_version; + Bool supported; + + m = calloc(1,sizeof(MSP3430Rec)); + if(m == NULL)return NULL; + m->d.DevName = strdup("MSP34xx"); + m->d.SlaveAddr = addr; + m->d.pI2CBus = b; + m->d.NextDev = NULL; + m->d.StartTimeout = b->StartTimeout; + m->d.BitTimeout = b->BitTimeout; + m->d.AcknTimeout = b->AcknTimeout; + m->d.ByteTimeout = b->ByteTimeout; + + if(!I2C_WriteRead(&(m->d), NULL, 0, &a, 1)) + { + free(m->d.DevName); + free(m); + return NULL; + } + + + m->standard=MSP3430_NTSC; + m->connector=MSP3430_CONNECTOR_1; + m->mode=MSPMODE_STEREO_A; /*stereo or chanel A if avail. */ + m->c_format=MSPFORMAT_UNKNOWN; + m->c_standard=MSPSTANDARD_UNKNOWN; + m->c_matrix=m->c_fmmatrix=m->c_source=0; + m->volume=0; + m->recheck=FALSE; + + GetMSP3430Data(m, RD_DSP, 0x00, 0x1E, &hardware_version, &major_revision); + GetMSP3430Data(m, RD_DSP, 0x00, 0x1F, &product_code, &rom_version); + m->hardware_version=hardware_version; + m->major_revision=major_revision; + m->product_code=product_code; + m->rom_version=rom_version; + + m->chip_id=((major_revision << 8) | product_code); + + supported=FALSE; + switch (major_revision) { + case 4: /* 34xxD */ + switch (product_code) { + case 0x05: /* 3405D */ + case 0x0A: /* 3410D */ + case 0x0F: /* 3415D */ + m->chip_family=MSPFAMILY_34x5D; + m->recheck=TRUE; + supported=TRUE; + break; + default: + m->chip_family=MSPFAMILY_34x0D; + } + break; + case 7: /* 34xxG */ + switch(product_code){ + case 0x00: + case 0x0A: + case 0x1E: + case 0x28: + case 0x32: + m->chip_family=MSPFAMILY_34x0G; + supported=TRUE; + break; + case 0x0f: + case 0x19: + case 0x2d: + case 0x37: + case 0x41: + m->chip_family=MSPFAMILY_34x5G; + supported=TRUE; + #ifdef MSP_DEBUG + memset(m->registers_present, 0, 256); + #define A(num) m->registers_present[(num)]=1; + #define B(num1, num2) memset(&(m->registers_present[num1]), 1, num2-num1); + A(0x20) + A(0x30) + A(0x40) + A(0x00) + B(0x01, 0x08) + B(0x0B, 0x0E) + A(0x10) + B(0x12,0x14) + A(0x16) + A(0x29) + #undef B + #undef A + #endif + break; + default: + m->chip_family=MSPFAMILY_UNKNOWN; + } + break; + default: + m->chip_family=MSPFAMILY_UNKNOWN; + } + + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Found %s%s, rom version 0x%02x, chip_id=0x%04x\n", + MSP_getProductName(m->chip_id), supported?"":" (unsupported)", rom_version, m->chip_id); + + if (!supported) { + free(m->d.DevName); + free(m); + return NULL; + } + if(!I2CDevInit(&(m->d))) + { + free(m->d.DevName); + free(m); + return NULL; + } + + return m; +} + +void ResetMSP3430(MSP3430Ptr m) +{ + /* Reset the MSP3430 */ + SetMSP3430Control(m, 0x00, 0x80, 0x00); + /* Set it back to normal operation */ + SetMSP3430Control(m, 0x00, 0x00, 0x00); + + m->c_format=MSPFORMAT_UNKNOWN; + m->c_standard=MSPSTANDARD_UNKNOWN; + m->c_matrix=m->c_fmmatrix=m->c_source=0; + m->volume=0; +} + +void MSP3430SetVolume (MSP3430Ptr m, CARD8 value) +{ + CARD8 result; +#if 0 + CARD8 old_volume; + GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 result 0x%02x\n", result); +#endif + /* save an extra Get call */ + result=0; + + SetMSP3430Data(m, WR_DSP, 0x00, 0x00, value, result); + + SetMSP3430Data(m, WR_DSP, 0x00, 0x07, value, 0); + m->volume=value; + +#if __MSPDEBUG__ > 2 + MSP3430DumpStatus(m); + __MSPBEEP + GetMSP3430Data(m, RD_DSP, 0x00, 0x00, &old_volume, &result); + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "MSP3430 volume 0x%02x\n",value); +#endif +} + + +void MSP3430SetSAP (MSP3430Ptr m, int mode) +{ + xf86DrvMsg(m->d.pI2CBus->scrnIndex, X_INFO, "Put actual code to change SAP here\n"); + + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, mode & 0xff, 0x20); +} + + +#if 0 +void MSP3430SetSource(MSP3430Ptr m, CARD8 value) +{ + /* Write to DSP, register 0x0008, (loudspeaker channel source/matrix) */ + /* This sets the source to the TV tuner, for stereo operation */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, value, 0x20); +} +#endif + + +char *MSP_getProductName (CARD16 product_id) +{ + switch (product_id) { + case 0x0400: return "MSP3400D"; + case 0x040a: return "MSP3410D"; + case 0x0405: return "MSP3405D"; + case 0x040f: return "MSP3415D"; + case 0x0700: return "MSP3400G"; + case 0x070a: return "MSP3410G"; + case 0x071e: return "MSP3430G"; + case 0x0728: return "MSP3440G"; + case 0x0732: return "MSP3450G"; + case 0x070f: return "MSP3415G"; + case 0x0719: return "MSP3425G"; + case 0x072d: return "MSP3445G"; + case 0x0737: return "MSP3455G"; + case 0x0741: return "MSP3465G"; + } + return "MSP - unknown type"; +} + +#if __MSPDEBUG__ > 2 +/*puts beep in MSP output + freq = 0x01 - 16Hz ... 0x40 - 1kHz ... 0xff - 4kHz +*/ +void MSPBeep(MSP3430Ptr m, CARD8 freq) { + SetMSP3430Data (m, WR_DSP, 0x00, freq, 0x7f, 0x40); + mpause(100); + SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x00); +} +#endif + +void mpause(int milliseconds) { + int i,m; + m=milliseconds/20; + for (i=0;i 1 + xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"InitMSP34xxG(m->connector=%d, m->standard=%d, m->chip_family=%d)\n", + m->connector, m->standard, m->chip_family); + #endif + /* Reset MSP3430 */ + SetMSP3430Control(m, 0x00, 0x80, 0x00); + /* Set it back to normal operation */ + SetMSP3430Control(m, 0x00, 0x00, 0x00); + + /*set MODUS register */ + /* bits: 0 - automatic sound detection */ + /* 1 - enable STATUS change */ + /* 12 - detect 6.5 Mhz carrier as D/K1, D/K2 or D/K NICAM (does not seem to work ) */ + /* 13 - detect 4.5 Mhz carrier as BTSC */ + if ( (m->standard & 0xff) == MSP3430_PAL ) + { + SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x30, 0x03|0x08); /* make O_ pins tristate */ + /* PAL standard */ + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x01); /* possibly wrong */ + } else { + SetMSP3430Data(m, WR_DEM, 0x00, 0x30, 0x20, 0x03|0x08); + /* standard selection is M-BTSC-Stereo */ + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x20); + } + + switch(m->connector){ + case MSP3430_CONNECTOR_1: + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x03, 0x20); + break; + case MSP3430_CONNECTOR_2: + /* this has not been checked yet.. could be bogus */ + /* SCART Input Prescale: 0 dB gain */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); + break; + case MSP3430_CONNECTOR_3: + default: + /* SCART Input Prescale: 0 dB gain */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); + + SetMSP3430Data(m, WR_DSP, 0x00, 0x08, 0x02, 0x20); + break; + } + + switch(m->standard){ + case MSP3430_PAL: + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); + SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x03); + /* Set volume to FAST_MUTE. */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); + break; + case MSP3430_PAL_DK1: + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); + SetMSP3430Data(m, WR_DSP, 0x00, 0x10, 0x00, 0x5a); + SetMSP3430Data(m, WR_DEM, 0x00, 0x20, 0x00, 0x04); + /* Set volume to FAST_MUTE. */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); + break; + case MSP3430_SECAM: /* is this right ? */ + case MSP3430_NTSC: + /* Write to DSP, register 0x000E, (prescale FM/FM matrix) */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x0e, 0x24, 0x03); + + /* Set volume to FAST_MUTE. */ + SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00); + break; + } + +} + +/*----------------------------------------------------------------- +| specific functions for all MSP34x5D chips +|----------------------------------------------------------------*/ + +void InitMSP34x5D(MSP3430Ptr m) +{ +int count; +CARD8 high,low; +CARD16 result,standard; +CARD16 peak; + + +if (m->c_format==MSPFORMAT_UNKNOWN) ResetMSP3430(m); +else { + /*mute volume*/ + SetMSP3430Data (m, WR_DSP, 0x00, 0x00, 0x00, 0x00); +} + + + + switch(m->connector){ + case MSP3430_CONNECTOR_2: + case MSP3430_CONNECTOR_3: + if (m->c_format!=MSPFORMAT_SCART) { + /* SCART Input Prescale: 0 dB gain */ + SetMSP3430Data (m, WR_DSP, 0x00, 0x0d, 0x19, 0x00); + /* this has not been checked yet.. could be bogus */ + m->c_format=MSPFORMAT_SCART; /*stereo*/ + } + break; + case MSP3430_CONNECTOR_1: + default: + + switch ( m->standard & 0x00ff ) { + case MSP3430_PAL: + switch( m->standard ) { + case MSP3430_PAL_DK1: + standard=MSPSTANDARD_FM_DK1; + break; +/* case MSP3430_PAL_DK2: + standard=MSPSTANDARD_FM_DK2; + break; + case MSP3430_PAL_BG: + may be FM stereo (Germany) or FM NICAM (Scandinavia,spain) + standard=MSPSTANDARD_AUTO; + break; +*/ + default: + standard=MSPSTANDARD_AUTO; + } + break; + case MSP3430_SECAM: + standard=MSPSTANDARD_AUTO; + case MSP3430_NTSC: + /* Only MSP34x5 supported format - Korean NTSC-M*/ + standard=MSPSTANDARD_FM_M; + default: + standard=MSPSTANDARD_AUTO; + } + + /*no NICAM support in MSP3410D - force to autodetect*/ + if ((m->chip_id==0x405) && (standard>=MSPSTANDARD_NICAM_BG)) + standard=MSPSTANDARD_AUTO; + + if (m->c_standard != standard) { + + SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF); + if (standard==MSPSTANDARD_AUTO) { + count = 50; /* time shouldn't exceed 1s, just in case */ + do { + usleep(20000); + GetMSP3430Data (m, RD_DEM, 0x00, 0x7e, &high, &low); + result = ( high << 8 ) | low; + --count; + } while( result > 0x07ff && count > 0 ); + + if ((result > MSPSTANDARD_AUTO)) + standard=result; + else standard=MSPSTANDARD_UNKNOWN; +#if __MSPDEBUG__ > 1 + xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Detected audio standard: %d\n",result); +#endif + /* result = MSPSTANDARD_NICAM_L can be one of: + SECAM_L - MSPSTANDARD_NICAM_L + D/K1 - MSPSTANDARD_FM_DK1 + D/K2 - MSPSTANDARD_FM_DK2 + D/K-NICAM - MSPSTANDARD_NICAM_DK*/ + if( standard == MSPSTANDARD_NICAM_L ) { + if ((m->standard & 0x00ff)==MSP3430_PAL) { + /* force PAL D/K */ + standard=MSPSTANDARD_FM_DK1; + SetMSP3430Data (m, WR_DEM, 0x00, 0x20, standard>>8, standard & 0xFF); +#if __MSPDEBUG__ > 1 + xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO, "Detected 6.5MHz carrier - forced to D/K1 !!!\n" ); +#endif + } + } + } + m->c_standard=standard; + } /*end - standard changed*/ + else { + if (standardc_format=MSPFORMAT_1xFM; + } + else if (standardL ch1->R*/ + SetMSP3430Data (m, WR_DSP, 0x00, 0x0c, 0x00, 0x20); + + mpause(250); + GetMSP3430Data (m, RD_DSP, 0x00, 0x1A, &high, &low); + peak = (high << 8) | low; +#if __MSPDEBUG__ > 1 + xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Second carrier Quasi-Peak detection: %d\n",peak); +#endif + /*turn on FM DC Notch*/ + SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x00); + + if (peak<5) { + /* if second carrier not detected - only mono from first carrier*/ + m->c_format=MSPFORMAT_1xFM; + } + else { + m->c_format=MSPFORMAT_2xFM; + /*start of FM identification process - FM_WAIT + wait at least 0.5s - used 1s - gives beter resolution*/ + mpause(1000); + } + } + else { + if (standard==MSPSTANDARD_NICAM_L) { + m->c_format=MSPFORMAT_NICAM_AM; + /* set AM prescale */ + SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x7C, 0); + } + else { + m->c_format=MSPFORMAT_NICAM_FM; + /* set FM prescale */ + SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0); + } + /* set FM deemphasis*/ + SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, 0x00, 0); + /* set NICAM prescale to 0dB */ + SetMSP3430Data (m, WR_DSP, 0x00, 0x10, 0x20, 0); + } + + break; + } /*end - case conector*/ + + CheckModeMSP34x5D(m); + + /* Set volume to FAST_MUTE. */ + /*SetMSP3430Data(m, WR_DSP, 0x00, 0x00, 0xFF, 0x00);*/ + /*set volume*/ + MSP3430SetVolume(m,m->volume); + + __MSPBEEP + + +} /* EnableMSP34x5D ()... */ + + + + +void CheckModeMSP34x5D(MSP3430Ptr m) { + const char stereo_on=25; + const char stereo_off=20; + const char dual_on=-stereo_on; + const char dual_off=-stereo_off; + char detect; + CARD8 matrix, fmmatrix, source, high, low; + + fmmatrix=0; /*no matrix*/ + source=0; /*FM*/ + switch (m->c_format) { + case MSPFORMAT_NICAM_FM: + case MSPFORMAT_NICAM_AM: + case MSPFORMAT_SCART: + source=( (m->c_format == MSPFORMAT_SCART)?2:1 ); + switch (m->mode) { + case MSPMODE_MONO: + matrix=0x30; /*MONO*/ + break; + case MSPMODE_A: + matrix=0x00; /*A*/ + break; + case MSPMODE_B: + matrix=0x10; /*B*/ + break; + default: + matrix=0x20; /*STEREO*/ + break; + } + break; + default: + case MSPFORMAT_1xFM: + matrix=0x00; /*A*/ + break; + case MSPFORMAT_2xFM: + switch (m->mode) { + case MSPMODE_MONO: + matrix=0x30; /*MONO*/ + break; + case MSPMODE_STEREO: + matrix=0x20; /*STEREO*/ + fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1); + break; + case MSPMODE_AB: + matrix=0x20; /*STEREO*/ + break; + case MSPMODE_A: + matrix=0x00; /*A*/ + break; + case MSPMODE_B: + matrix=0x10; /*B*/ + break; + default: + /*FM_IDENT_CHECK*/ + GetMSP3430Data (m, RD_DSP, 0x00, 0x18, &high, &low); + detect=(char)high; +#if __MSPDEBUG__ > 1 + xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Stereo Detection Register: %d\n",detect); +#endif + if (detect>=((m->c_mode==MSPMODE_STEREO)?stereo_off:stereo_on)) { + m->c_mode=MSPMODE_STEREO; + matrix=0x20; /*STEREO*/ + fmmatrix=((m->c_standard==MSPSTANDARD_FM_M)?2:1); + } + else if (detect<=((m->c_mode==MSPMODE_AB)?dual_off:dual_on)) { + m->c_mode=MSPMODE_AB; + switch (m->mode) { + case MSPMODE_STEREO_AB: matrix=0x20; break; + case MSPMODE_STEREO_B: matrix=0x10; break; + default: + case MSPMODE_A: matrix=0x00; break; + } + } + else { + m->c_mode=MSPMODE_MONO; + matrix=0x30; /*MONO*/ + } + break; + } /* end - case mode*/ + break; + } + + if (m->c_fmmatrix != fmmatrix) { + GetMSP3430Data (m, RD_DSP, 0x00, 0x0e, &high, &low); + SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, high, fmmatrix); + m->c_fmmatrix = fmmatrix; + } + + if ((m->c_matrix != matrix) || (m->c_source != source)) { + /*set chanel source and matrix for loudspeaker*/ + SetMSP3430Data (m, WR_DSP, 0x00, 0x08, source, matrix); + + m->c_matrix = matrix; + m->c_source = source; + } + + if ( ((m->c_format) & 0xF0) == MSPFORMAT_NICAM) + SetMSP3430Data (m, WR_DEM, 0x00, 0x21, 0, 1); + +#if __MSPDEBUG__ > 0 + char *msg; + switch (matrix) { + case 0x30: /*MONO*/ + msg="MONO"; + break; + case 0x00: /*LEFT*/ + msg="MONO/CHANNEL_1"; + break; + case 0x10: /*RIGHT*/ + msg="MONO/CHANNEL_2"; + break; + case 0x20: /*LEFT*/ + msg="STEREO"; + break; + default: + msg="unknown"; + break; + } + xf86DrvMsg(m->d.pI2CBus->scrnIndex,X_INFO,"Audio mode set to: %s\n",msg); +#endif +} + diff --git a/xorg-server/hw/xfree86/i2c/tda8425.c b/xorg-server/hw/xfree86/i2c/tda8425.c index 7631a0863..abbbb2a03 100644 --- a/xorg-server/hw/xfree86/i2c/tda8425.c +++ b/xorg-server/hw/xfree86/i2c/tda8425.c @@ -1,78 +1,78 @@ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86i2c.h" -#include "tda8425.h" -#include "i2c_def.h" - -#define TDA8425(a,b) { \ - data[0]=a; \ - data[1]=b; \ - I2C_WriteRead(&(t->d), data, 2, NULL, 0); \ - } - -TDA8425Ptr Detect_tda8425(I2CBusPtr b, I2CSlaveAddr addr, Bool force) -{ - TDA8425Ptr t; - - t = xcalloc(1, sizeof(TDA8425Rec)); - if(t == NULL) return NULL; - t->d.DevName = "TDA8425 BTSC Stereo Audio Processor"; - t->d.SlaveAddr = addr; - t->d.pI2CBus = b; - t->d.NextDev = NULL; - t->d.StartTimeout = b->StartTimeout; - t->d.BitTimeout = b->BitTimeout; - t->d.AcknTimeout = b->AcknTimeout; - t->d.ByteTimeout = b->ByteTimeout; - - if(!force && !I2CProbeAddress(b, addr)) - { - xfree(t); - return NULL; - } - - /* set default parameters */ - if(!I2CDevInit(&(t->d))) - { - xfree(t); - return NULL; - } - - return t; -} - -Bool tda8425_init(TDA8425Ptr t) -{ - t->stereo = 3; /* 3 = Spacial 2 = Linear 1 = Pseudo 0 = Forced mono */ - t->v_left = 0xFF; /* FF - C0 */ - t->v_right = 0xFF; /* FF - C0 */ - t->bass = 0xF6; /* 0xFF - 0xF0 */ - t->treble = 0xF6; /* 0xFF - 0xF0 */ - t->src_sel = 3; /* 3 - stereo */ - t->mute = TRUE; - t->mux = 0; /* 0 - source one, 1 -source 2 */ - - tda8425_setaudio(t); - return TRUE; -} - -void tda8425_setaudio(TDA8425Ptr t) -{ - I2CByte data[2]; - - TDA8425(0x00, t->v_left ); - TDA8425(0x01, t->v_right ); - TDA8425(0x02, t->bass ); - TDA8425(0x03, t->treble ); - TDA8425(0x08, 0xC0 | (t->mute ? 0x20 : 0x0) | (t->stereo << 3) | (t->src_sel << 1) | - t->mux); -} - -void tda8425_mute(TDA8425Ptr t, Bool mute) -{ - t->mute = mute; - tda8425_setaudio(t); -} +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86i2c.h" +#include "tda8425.h" +#include "i2c_def.h" + +#define TDA8425(a,b) { \ + data[0]=a; \ + data[1]=b; \ + I2C_WriteRead(&(t->d), data, 2, NULL, 0); \ + } + +TDA8425Ptr Detect_tda8425(I2CBusPtr b, I2CSlaveAddr addr, Bool force) +{ + TDA8425Ptr t; + + t = calloc(1, sizeof(TDA8425Rec)); + if(t == NULL) return NULL; + t->d.DevName = "TDA8425 BTSC Stereo Audio Processor"; + t->d.SlaveAddr = addr; + t->d.pI2CBus = b; + t->d.NextDev = NULL; + t->d.StartTimeout = b->StartTimeout; + t->d.BitTimeout = b->BitTimeout; + t->d.AcknTimeout = b->AcknTimeout; + t->d.ByteTimeout = b->ByteTimeout; + + if(!force && !I2CProbeAddress(b, addr)) + { + free(t); + return NULL; + } + + /* set default parameters */ + if(!I2CDevInit(&(t->d))) + { + free(t); + return NULL; + } + + return t; +} + +Bool tda8425_init(TDA8425Ptr t) +{ + t->stereo = 3; /* 3 = Spacial 2 = Linear 1 = Pseudo 0 = Forced mono */ + t->v_left = 0xFF; /* FF - C0 */ + t->v_right = 0xFF; /* FF - C0 */ + t->bass = 0xF6; /* 0xFF - 0xF0 */ + t->treble = 0xF6; /* 0xFF - 0xF0 */ + t->src_sel = 3; /* 3 - stereo */ + t->mute = TRUE; + t->mux = 0; /* 0 - source one, 1 -source 2 */ + + tda8425_setaudio(t); + return TRUE; +} + +void tda8425_setaudio(TDA8425Ptr t) +{ + I2CByte data[2]; + + TDA8425(0x00, t->v_left ); + TDA8425(0x01, t->v_right ); + TDA8425(0x02, t->bass ); + TDA8425(0x03, t->treble ); + TDA8425(0x08, 0xC0 | (t->mute ? 0x20 : 0x0) | (t->stereo << 3) | (t->src_sel << 1) | + t->mux); +} + +void tda8425_mute(TDA8425Ptr t, Bool mute) +{ + t->mute = mute; + tda8425_setaudio(t); +} diff --git a/xorg-server/hw/xfree86/i2c/tda9850.c b/xorg-server/hw/xfree86/i2c/tda9850.c index 5b0c581ed..5d794dfe5 100644 --- a/xorg-server/hw/xfree86/i2c/tda9850.c +++ b/xorg-server/hw/xfree86/i2c/tda9850.c @@ -1,112 +1,112 @@ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86i2c.h" -#include "tda9850.h" -#include "i2c_def.h" - -#define TDA9850(a,b) { \ - data[0]=a; \ - data[1]=b; \ - I2C_WriteRead(&(t->d), data, 2, NULL, 0); \ - } - -TDA9850Ptr Detect_tda9850(I2CBusPtr b, I2CSlaveAddr addr) -{ - TDA9850Ptr t; - I2CByte a; - - t = xcalloc(1, sizeof(TDA9850Rec)); - if(t == NULL) return NULL; - switch(addr) - { - case TDA9850_ADDR_1: - t->d.DevName = "TDA9850 BTSC Stereo+SAP Audio Processor"; - break; - default: - t->d.DevName = "Generic TDAxxxx"; - break; - } - t->d.SlaveAddr = addr; - t->d.pI2CBus = b; - t->d.NextDev = NULL; - t->d.StartTimeout = b->StartTimeout; - t->d.BitTimeout = b->BitTimeout; - t->d.AcknTimeout = b->AcknTimeout; - t->d.ByteTimeout = b->ByteTimeout; - - if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) - { - xfree(t); - return NULL; - } - - /* set default parameters */ - if(!I2CDevInit(&(t->d))) - { - xfree(t); - return NULL; - } - - return t; -} - -Bool tda9850_init(TDA9850Ptr t) -{ - t->stereo = 1; - t->sap = 0; - t->mute = TRUE; - t->sap_mute = TRUE; - tda9850_setaudio(t); - return TRUE; -} - -void tda9850_setaudio(TDA9850Ptr t) -{ -CARD8 data[2]; - -if(t->mux==2) -{ - TDA9850(0x04,0x0F); TDA9850(0x05,0x0F); TDA9850(0x06, 0x58); - TDA9850(0x07,0x07); TDA9850(0x08,0x00); - TDA9850(0x09,0x00); TDA9850(0x0A,0x03); -} else -{ - TDA9850(0x04,0x07); TDA9850(0x05,0x07); - TDA9850(0x06,0x58); TDA9850(0x07,0x07); - TDA9850(0x08,0x10); TDA9850(0x09,0x10); - TDA9850(0x0A,0x03); -} - -TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0)|(t->sap_mute?0x10:0x0)); -} - -void tda9850_mute(TDA9850Ptr t, Bool mute) -{ -CARD8 data[2]; - -xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "tda9850_mute %s\n", mute ? "on" : "off"); -t->mute = mute; - -TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0x0)|(t->sap_mute?0x10:0x0)); -} - -void tda9850_sap_mute(TDA9850Ptr t, Bool sap_mute) -{ -CARD8 data[2]; - -xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "tda9850_sap_mute %s\n", sap_mute ? "on" : "off"); -t->sap_mute = sap_mute; - -TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0x0)|(t->sap_mute?0x10:0x0)); -} - -CARD16 tda9850_getstatus(TDA9850Ptr t) -{ -CARD16 status; - -I2C_WriteRead(&(t->d), NULL, 0, (I2CByte *)&status, 2); -return status; -} +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86i2c.h" +#include "tda9850.h" +#include "i2c_def.h" + +#define TDA9850(a,b) { \ + data[0]=a; \ + data[1]=b; \ + I2C_WriteRead(&(t->d), data, 2, NULL, 0); \ + } + +TDA9850Ptr Detect_tda9850(I2CBusPtr b, I2CSlaveAddr addr) +{ + TDA9850Ptr t; + I2CByte a; + + t = calloc(1, sizeof(TDA9850Rec)); + if(t == NULL) return NULL; + switch(addr) + { + case TDA9850_ADDR_1: + t->d.DevName = "TDA9850 BTSC Stereo+SAP Audio Processor"; + break; + default: + t->d.DevName = "Generic TDAxxxx"; + break; + } + t->d.SlaveAddr = addr; + t->d.pI2CBus = b; + t->d.NextDev = NULL; + t->d.StartTimeout = b->StartTimeout; + t->d.BitTimeout = b->BitTimeout; + t->d.AcknTimeout = b->AcknTimeout; + t->d.ByteTimeout = b->ByteTimeout; + + if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) + { + free(t); + return NULL; + } + + /* set default parameters */ + if(!I2CDevInit(&(t->d))) + { + free(t); + return NULL; + } + + return t; +} + +Bool tda9850_init(TDA9850Ptr t) +{ + t->stereo = 1; + t->sap = 0; + t->mute = TRUE; + t->sap_mute = TRUE; + tda9850_setaudio(t); + return TRUE; +} + +void tda9850_setaudio(TDA9850Ptr t) +{ +CARD8 data[2]; + +if(t->mux==2) +{ + TDA9850(0x04,0x0F); TDA9850(0x05,0x0F); TDA9850(0x06, 0x58); + TDA9850(0x07,0x07); TDA9850(0x08,0x00); + TDA9850(0x09,0x00); TDA9850(0x0A,0x03); +} else +{ + TDA9850(0x04,0x07); TDA9850(0x05,0x07); + TDA9850(0x06,0x58); TDA9850(0x07,0x07); + TDA9850(0x08,0x10); TDA9850(0x09,0x10); + TDA9850(0x0A,0x03); +} + +TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0)|(t->sap_mute?0x10:0x0)); +} + +void tda9850_mute(TDA9850Ptr t, Bool mute) +{ +CARD8 data[2]; + +xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "tda9850_mute %s\n", mute ? "on" : "off"); +t->mute = mute; + +TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0x0)|(t->sap_mute?0x10:0x0)); +} + +void tda9850_sap_mute(TDA9850Ptr t, Bool sap_mute) +{ +CARD8 data[2]; + +xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, "tda9850_sap_mute %s\n", sap_mute ? "on" : "off"); +t->sap_mute = sap_mute; + +TDA9850(0x06,(t->stereo<<6)|(t->sap<<7)|(t->mute?0x8:0x0)|(t->sap_mute?0x10:0x0)); +} + +CARD16 tda9850_getstatus(TDA9850Ptr t) +{ +CARD16 status; + +I2C_WriteRead(&(t->d), NULL, 0, (I2CByte *)&status, 2); +return status; +} diff --git a/xorg-server/hw/xfree86/i2c/tda9885.c b/xorg-server/hw/xfree86/i2c/tda9885.c index 4147dfdd7..f22233995 100644 --- a/xorg-server/hw/xfree86/i2c/tda9885.c +++ b/xorg-server/hw/xfree86/i2c/tda9885.c @@ -1,104 +1,104 @@ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86i2c.h" -#include "tda9885.h" -#include "i2c_def.h" - - -TDA9885Ptr Detect_tda9885(I2CBusPtr b, I2CSlaveAddr addr) -{ - TDA9885Ptr t; - I2CByte a; - - t = xcalloc(1, sizeof(TDA9885Rec)); - if(t == NULL) return NULL; - switch(addr) - { - case TDA9885_ADDR_1: - case TDA9885_ADDR_2: - case TDA9885_ADDR_3: - case TDA9885_ADDR_4: - t->d.DevName = "TDA9885 Alignment-free IF-PLL"; - break; - default: - t->d.DevName = "Generic TDAxxxx"; - break; - } - t->d.SlaveAddr = addr; - t->d.pI2CBus = b; - t->d.NextDev = NULL; - t->d.StartTimeout = b->StartTimeout; - t->d.BitTimeout = b->BitTimeout; - t->d.AcknTimeout = b->AcknTimeout; - t->d.ByteTimeout = b->ByteTimeout; - - if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) - { - xfree(t); - return NULL; - } - - /* set default parameters */ - if(!I2CDevInit(&(t->d))) - { - xfree(t); - return NULL; - } - - return t; -} - -Bool tda9885_init(TDA9885Ptr t) -{ - t->forced_mute_audio=1; - return TRUE; -} - -void tda9885_getstatus(TDA9885Ptr t) -{ -CARD8 value; - -I2C_WriteRead(&(t->d), NULL, 0, &value, 1); -t->after_reset=value & 1; -t->afc_status=(value >> 1) & 0xf; -t->fm_carrier=(value>>5)& 1; -t->vif_level=(value >>6) & 1; -t->afc_win=(value >> 7)&1; -} - -void tda9885_setparameters(TDA9885Ptr t) -{ -CARD8 data[4]; - -data[0]=0; /* start with subaddress 0 */ -data[1]=(t->sound_trap & 1) | - ((t->auto_mute_fm &1)<<1) | - ((t->carrier_mode &1)<<2) | - ((t->modulation &3)<<3) | - ((t->forced_mute_audio &1)<<5) | - ((t->port1 & 1)<<6) | - ((t->port2 &1)<<7); /* B data */ -data[2]=(t->top_adjustment & 0x1f) | - ((t->deemphasis & 0x3)<<5) | - ((t->audio_gain & 1) << 7); /* C data */ -data[3]=(t->standard_sound_carrier & 0x3) | - ((t->standard_video_if & 0x07)<<2) | - ((t->minimum_gain & 0x01)<<5) | - ((t->gating & 0x01)<<6) | - ((t->vif_agc & 0x01)<<7); /* E data */ - -I2C_WriteRead(&(t->d), data, 4, NULL, 0); - -xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"TDA9885 setparam: B data: %x, C data: %x, E data: %x\n", data[1], data[2], data[3]); -} - -void tda9885_dumpstatus(TDA9885Ptr t) -{ -xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"TDA9885 status: after_reset=%d afc_status=%d (%3.1f kHz off) fm_carrier=%d vif_level=%d afc_win=%d %s\n", - t->after_reset, t->afc_status, - (t->afc_status<8)?-12.5-t->afc_status*25.0:-12.5+(16-t->afc_status)*25.0, - t->fm_carrier, t->vif_level, t->afc_win, t->afc_win?"VCO in": "VCO out"); -} +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86i2c.h" +#include "tda9885.h" +#include "i2c_def.h" + + +TDA9885Ptr Detect_tda9885(I2CBusPtr b, I2CSlaveAddr addr) +{ + TDA9885Ptr t; + I2CByte a; + + t = calloc(1, sizeof(TDA9885Rec)); + if(t == NULL) return NULL; + switch(addr) + { + case TDA9885_ADDR_1: + case TDA9885_ADDR_2: + case TDA9885_ADDR_3: + case TDA9885_ADDR_4: + t->d.DevName = "TDA9885 Alignment-free IF-PLL"; + break; + default: + t->d.DevName = "Generic TDAxxxx"; + break; + } + t->d.SlaveAddr = addr; + t->d.pI2CBus = b; + t->d.NextDev = NULL; + t->d.StartTimeout = b->StartTimeout; + t->d.BitTimeout = b->BitTimeout; + t->d.AcknTimeout = b->AcknTimeout; + t->d.ByteTimeout = b->ByteTimeout; + + if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) + { + free(t); + return NULL; + } + + /* set default parameters */ + if(!I2CDevInit(&(t->d))) + { + free(t); + return NULL; + } + + return t; +} + +Bool tda9885_init(TDA9885Ptr t) +{ + t->forced_mute_audio=1; + return TRUE; +} + +void tda9885_getstatus(TDA9885Ptr t) +{ +CARD8 value; + +I2C_WriteRead(&(t->d), NULL, 0, &value, 1); +t->after_reset=value & 1; +t->afc_status=(value >> 1) & 0xf; +t->fm_carrier=(value>>5)& 1; +t->vif_level=(value >>6) & 1; +t->afc_win=(value >> 7)&1; +} + +void tda9885_setparameters(TDA9885Ptr t) +{ +CARD8 data[4]; + +data[0]=0; /* start with subaddress 0 */ +data[1]=(t->sound_trap & 1) | + ((t->auto_mute_fm &1)<<1) | + ((t->carrier_mode &1)<<2) | + ((t->modulation &3)<<3) | + ((t->forced_mute_audio &1)<<5) | + ((t->port1 & 1)<<6) | + ((t->port2 &1)<<7); /* B data */ +data[2]=(t->top_adjustment & 0x1f) | + ((t->deemphasis & 0x3)<<5) | + ((t->audio_gain & 1) << 7); /* C data */ +data[3]=(t->standard_sound_carrier & 0x3) | + ((t->standard_video_if & 0x07)<<2) | + ((t->minimum_gain & 0x01)<<5) | + ((t->gating & 0x01)<<6) | + ((t->vif_agc & 0x01)<<7); /* E data */ + +I2C_WriteRead(&(t->d), data, 4, NULL, 0); + +xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"TDA9885 setparam: B data: %x, C data: %x, E data: %x\n", data[1], data[2], data[3]); +} + +void tda9885_dumpstatus(TDA9885Ptr t) +{ +xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"TDA9885 status: after_reset=%d afc_status=%d (%3.1f kHz off) fm_carrier=%d vif_level=%d afc_win=%d %s\n", + t->after_reset, t->afc_status, + (t->afc_status<8)?-12.5-t->afc_status*25.0:-12.5+(16-t->afc_status)*25.0, + t->fm_carrier, t->vif_level, t->afc_win, t->afc_win?"VCO in": "VCO out"); +} diff --git a/xorg-server/hw/xfree86/i2c/uda1380.c b/xorg-server/hw/xfree86/i2c/uda1380.c index defda3cdc..eebe127ed 100644 --- a/xorg-server/hw/xfree86/i2c/uda1380.c +++ b/xorg-server/hw/xfree86/i2c/uda1380.c @@ -1,183 +1,183 @@ -/************************************************************************************* - * Copyright (C) 2005 Bogdan D. bogdand@users.sourceforge.net - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this - * software and associated documentation files (the "Software"), to deal in the Software - * without restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE - * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the author 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 author. - * - ************************************************************************************/ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86i2c.h" -#include "uda1380.h" -#include "i2c_def.h" - -UDA1380Ptr Detect_uda1380(I2CBusPtr b, I2CSlaveAddr addr) -{ - UDA1380Ptr t; - I2CByte a; - - t = xcalloc(1, sizeof(UDA1380Rec)); - if(t == NULL) return NULL; - switch(addr) - { - case UDA1380_ADDR_1: - case UDA1380_ADDR_2: - t->d.DevName = "UDA1380 Stereo audion coder-decoder"; - break; - default: - t->d.DevName = "Generic UDAxxxx"; - break; - } - t->d.SlaveAddr = addr; - t->d.pI2CBus = b; - t->d.NextDev = NULL; - t->d.StartTimeout = b->StartTimeout; - t->d.BitTimeout = b->BitTimeout; - t->d.AcknTimeout = b->AcknTimeout; - t->d.ByteTimeout = b->ByteTimeout; - - if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) - { - xfree(t); - return NULL; - } - - /* set default parameters */ - if(!I2CDevInit(&(t->d))) - { - xfree(t); - return NULL; - } - - xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 stereo coder-decoder detected\n"); - - return t; -} - -Bool uda1380_init(UDA1380Ptr t) -{ - CARD8 data[3]; - CARD16 tmp; - Bool ret; - - /* Power control */ - data[0] = 0x02; - tmp = (1 << 13) | (1 << 10) | ( 1 << 8) | (1 << 7) | (1 << 6) | (1 << 3) | (1 << 1); - data[1] = (CARD8)((tmp >> 8) & 0xff); - data[2] = (CARD8)(tmp & 0xff); - ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); - if (ret == FALSE) - { - xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to initialize\n"); - return FALSE; - } - - /* Analog mixer (AVC) */ - data[0] = 0x03; - /* the analog mixer is muted initially */ - data[1] = 0x3f; - data[2] = 0x3f; - ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); - if (ret == FALSE) - { - xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to initialize\n"); - return FALSE; - } - - xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 initialized\n"); - - return TRUE; -} - -void uda1380_shutdown(UDA1380Ptr t) -{ - CARD8 data[3]; - Bool ret; - - /* Power control */ - data[0] = 0x02; - data[1] = 0; - data[2] = 0; - ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); - if (ret == FALSE) - xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to shutdown\n"); -} - -void uda1380_setvolume(UDA1380Ptr t, INT32 value) -{ - CARD8 data[3]; - /* - * We have to scale the value ranging from -1000 to 1000 to 0x2c to 0 - */ - CARD8 volume = 47 - (CARD8)((value + 1000) * 47 / 2000); - Bool ret; - - t->analog_mixer_settings = ((volume << 8) & 0x3f00) | (volume & 0x3f); - - /* Analog mixer (AVC) */ - data[0] = 0x03; - data[1] = volume & 0x3f; - data[2] = volume & 0x3f; - ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); - if (ret == FALSE) - xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to set volume\n"); -} - -void uda1380_mute(UDA1380Ptr t, Bool mute) -{ - CARD8 data[3]; - Bool ret; - - if (mute == TRUE) - { - /* Analog mixer (AVC) */ - data[0] = 0x03; - data[1] = 0xff; - data[2] = 0xff; - ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); - if (ret == FALSE) - xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to mute\n"); - } - else - { - /* Analog mixer (AVC) */ - data[0] = 0x03; - data[1] = (CARD8)((t->analog_mixer_settings >> 8) & 0x3f); - data[2] = (CARD8)(t->analog_mixer_settings & 0x3f); - ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); - if (ret == FALSE) - xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to unmute\n"); - } -} - -void uda1380_getstatus(UDA1380Ptr t) -{ -} - -void uda1380_setparameters(UDA1380Ptr t) -{ -} - -void uda1380_dumpstatus(UDA1380Ptr t) -{ -} +/************************************************************************************* + * Copyright (C) 2005 Bogdan D. bogdand@users.sourceforge.net + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this + * software and associated documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE + * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the author 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 author. + * + ************************************************************************************/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86i2c.h" +#include "uda1380.h" +#include "i2c_def.h" + +UDA1380Ptr Detect_uda1380(I2CBusPtr b, I2CSlaveAddr addr) +{ + UDA1380Ptr t; + I2CByte a; + + t = calloc(1, sizeof(UDA1380Rec)); + if(t == NULL) return NULL; + switch(addr) + { + case UDA1380_ADDR_1: + case UDA1380_ADDR_2: + t->d.DevName = "UDA1380 Stereo audion coder-decoder"; + break; + default: + t->d.DevName = "Generic UDAxxxx"; + break; + } + t->d.SlaveAddr = addr; + t->d.pI2CBus = b; + t->d.NextDev = NULL; + t->d.StartTimeout = b->StartTimeout; + t->d.BitTimeout = b->BitTimeout; + t->d.AcknTimeout = b->AcknTimeout; + t->d.ByteTimeout = b->ByteTimeout; + + if(!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) + { + free(t); + return NULL; + } + + /* set default parameters */ + if(!I2CDevInit(&(t->d))) + { + free(t); + return NULL; + } + + xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 stereo coder-decoder detected\n"); + + return t; +} + +Bool uda1380_init(UDA1380Ptr t) +{ + CARD8 data[3]; + CARD16 tmp; + Bool ret; + + /* Power control */ + data[0] = 0x02; + tmp = (1 << 13) | (1 << 10) | ( 1 << 8) | (1 << 7) | (1 << 6) | (1 << 3) | (1 << 1); + data[1] = (CARD8)((tmp >> 8) & 0xff); + data[2] = (CARD8)(tmp & 0xff); + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + { + xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to initialize\n"); + return FALSE; + } + + /* Analog mixer (AVC) */ + data[0] = 0x03; + /* the analog mixer is muted initially */ + data[1] = 0x3f; + data[2] = 0x3f; + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + { + xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to initialize\n"); + return FALSE; + } + + xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 initialized\n"); + + return TRUE; +} + +void uda1380_shutdown(UDA1380Ptr t) +{ + CARD8 data[3]; + Bool ret; + + /* Power control */ + data[0] = 0x02; + data[1] = 0; + data[2] = 0; + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to shutdown\n"); +} + +void uda1380_setvolume(UDA1380Ptr t, INT32 value) +{ + CARD8 data[3]; + /* + * We have to scale the value ranging from -1000 to 1000 to 0x2c to 0 + */ + CARD8 volume = 47 - (CARD8)((value + 1000) * 47 / 2000); + Bool ret; + + t->analog_mixer_settings = ((volume << 8) & 0x3f00) | (volume & 0x3f); + + /* Analog mixer (AVC) */ + data[0] = 0x03; + data[1] = volume & 0x3f; + data[2] = volume & 0x3f; + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to set volume\n"); +} + +void uda1380_mute(UDA1380Ptr t, Bool mute) +{ + CARD8 data[3]; + Bool ret; + + if (mute == TRUE) + { + /* Analog mixer (AVC) */ + data[0] = 0x03; + data[1] = 0xff; + data[2] = 0xff; + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to mute\n"); + } + else + { + /* Analog mixer (AVC) */ + data[0] = 0x03; + data[1] = (CARD8)((t->analog_mixer_settings >> 8) & 0x3f); + data[2] = (CARD8)(t->analog_mixer_settings & 0x3f); + ret = I2C_WriteRead(&(t->d), data, 3, NULL, 0); + if (ret == FALSE) + xf86DrvMsg(t->d.pI2CBus->scrnIndex,X_INFO,"UDA1380 failed to unmute\n"); + } +} + +void uda1380_getstatus(UDA1380Ptr t) +{ +} + +void uda1380_setparameters(UDA1380Ptr t) +{ +} + +void uda1380_dumpstatus(UDA1380Ptr t) +{ +} diff --git a/xorg-server/hw/xfree86/i2c/xf86i2c.c b/xorg-server/hw/xfree86/i2c/xf86i2c.c index 59832d6f9..488b6815f 100644 --- a/xorg-server/hw/xfree86/i2c/xf86i2c.c +++ b/xorg-server/hw/xfree86/i2c/xf86i2c.c @@ -1,866 +1,866 @@ -/* - * Copyright (C) 1998 Itai Nahshon, Michael Schimek - * - * The original code was derived from and inspired by - * the I2C driver from the Linux kernel. - * (c) 1998 Gerd Knorr - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include -#include -#include "scrnintstr.h" -#include "regionstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "validate.h" -#include "resource.h" -#include "gcstruct.h" -#include "dixstruct.h" - -#include "xf86i2c.h" - -#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */ -#define I2C_TRACE(x) /*(x)*/ /* Report progress */ - -/* This is the default I2CUDelay function if not supplied by the driver. - * High level I2C interfaces implementing the bus protocol in hardware - * should supply this function too. - * - * Delay execution at least usec microseconds. - * All values 0 to 1e6 inclusive must be expected. - */ - -static void -I2CUDelay(I2CBusPtr b, int usec) -{ - struct timeval begin, cur; - long d_secs, d_usecs; - long diff; - - if (usec > 0) { - X_GETTIMEOFDAY(&begin); - do { - /* It would be nice to use {xf86}usleep, - * but usleep (1) takes >10000 usec ! - */ - X_GETTIMEOFDAY(&cur); - d_secs = (cur.tv_sec - begin.tv_sec); - d_usecs = (cur.tv_usec - begin.tv_usec); - diff = d_secs*1000000 + d_usecs; - } while (diff>=0 && diff< (usec + 1)); - } -} - -/* Most drivers will register just with GetBits/PutBits functions. - * The following functions implement a software I2C protocol - * by using the promitive functions given by the driver. - * ================================================================ - * - * It is assumed that there is just one master on the I2C bus, therefore - * there is no explicit test for conflits. - */ - -#define RISEFALLTIME 2 /* usec, actually 300 to 1000 ns according to the i2c specs */ - -/* Some devices will hold SCL low to slow down the bus or until - * ready for transmission. - * - * This condition will be noticed when the master tries to raise - * the SCL line. You can set the timeout to zero if the slave device - * does not support this clock synchronization. - */ - -static Bool -I2CRaiseSCL(I2CBusPtr b, int sda, int timeout) -{ - int i, scl; - - b->I2CPutBits(b, 1, sda); - b->I2CUDelay(b, b->RiseFallTime); - - for (i = timeout; i > 0; i -= b->RiseFallTime) { - b->I2CGetBits(b, &scl, &sda); - if (scl) break; - b->I2CUDelay(b, b->RiseFallTime); - } - - if (i <= 0) { - I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d, %d) timeout]", b->BusName, sda, timeout)); - return FALSE; - } - - return TRUE; -} - -/* Send a start signal on the I2C bus. The start signal notifies - * devices that a new transaction is initiated by the bus master. - * - * The start signal is always followed by a slave address. - * Slave addresses are 8+ bits. The first 7 bits identify the - * device and the last bit signals if this is a read (1) or - * write (0) operation. - * - * There may be more than one start signal on one transaction. - * This happens for example on some devices that allow reading - * of registers. First send a start bit followed by the device - * address (with the last bit 0) and the register number. Then send - * a new start bit with the device address (with the last bit 1) - * and then read the value from the device. - * - * Note this is function does not implement a multiple master - * arbitration procedure. - */ - -static Bool -I2CStart(I2CBusPtr b, int timeout) -{ - if (!I2CRaiseSCL(b, 1, timeout)) - return FALSE; - - b->I2CPutBits(b, 1, 0); - b->I2CUDelay(b, b->HoldTime); - b->I2CPutBits(b, 0, 0); - b->I2CUDelay(b, b->HoldTime); - - I2C_TRACE(ErrorF("\ni2c: <")); - - return TRUE; -} - -/* This is the default I2CStop function if not supplied by the driver. - * - * Signal devices on the I2C bus that a transaction on the - * bus has finished. There may be more than one start signal - * on a transaction but only one stop signal. - */ - -static void -I2CStop(I2CDevPtr d) -{ - I2CBusPtr b = d->pI2CBus; - - b->I2CPutBits(b, 0, 0); - b->I2CUDelay(b, b->RiseFallTime); - - b->I2CPutBits(b, 1, 0); - b->I2CUDelay(b, b->HoldTime); - b->I2CPutBits(b, 1, 1); - b->I2CUDelay(b, b->HoldTime); - - I2C_TRACE(ErrorF(">\n")); -} - -/* Write/Read a single bit to/from a device. - * Return FALSE if a timeout occurs. - */ - -static Bool -I2CWriteBit(I2CBusPtr b, int sda, int timeout) -{ - Bool r; - - b->I2CPutBits(b, 0, sda); - b->I2CUDelay(b, b->RiseFallTime); - - r = I2CRaiseSCL(b, sda, timeout); - b->I2CUDelay(b, b->HoldTime); - - b->I2CPutBits(b, 0, sda); - b->I2CUDelay(b, b->HoldTime); - - return r; -} - -static Bool -I2CReadBit(I2CBusPtr b, int *psda, int timeout) -{ - Bool r; - int scl; - - r = I2CRaiseSCL(b, 1, timeout); - b->I2CUDelay(b, b->HoldTime); - - b->I2CGetBits(b, &scl, psda); - - b->I2CPutBits(b, 0, 1); - b->I2CUDelay(b, b->HoldTime); - - return r; -} - -/* This is the default I2CPutByte function if not supplied by the driver. - * - * A single byte is sent to the device. - * The function returns FALSE if a timeout occurs, you should send - * a stop condition afterwards to reset the bus. - * - * A timeout occurs, - * if the slave pulls SCL to slow down the bus more than ByteTimeout usecs, - * or slows down the bus for more than BitTimeout usecs for each bit, - * or does not send an ACK bit (0) to acknowledge the transmission within - * AcknTimeout usecs, but a NACK (1) bit. - * - * AcknTimeout must be at least b->HoldTime, the other timeouts can be - * zero according to the comment on I2CRaiseSCL. - */ - -static Bool -I2CPutByte(I2CDevPtr d, I2CByte data) -{ - Bool r; - int i, scl, sda; - I2CBusPtr b = d->pI2CBus; - - if (!I2CWriteBit(b, (data >> 7) & 1, d->ByteTimeout)) - return FALSE; - - for (i = 6; i >= 0; i--) - if (!I2CWriteBit(b, (data >> i) & 1, d->BitTimeout)) - return FALSE; - - b->I2CPutBits(b, 0, 1); - b->I2CUDelay(b, b->RiseFallTime); - - r = I2CRaiseSCL(b, 1, b->HoldTime); - - if (r) { - for (i = d->AcknTimeout; i > 0; i -= b->HoldTime) { - b->I2CUDelay(b, b->HoldTime); - b->I2CGetBits(b, &scl, &sda); - if (sda == 0) break; - } - - if (i <= 0) { - I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]", - b->BusName, data, d->BitTimeout, - d->ByteTimeout, d->AcknTimeout)); - r = FALSE; - } - - I2C_TRACE(ErrorF("W%02x%c ", (int) data, sda ? '-' : '+')); - } - - b->I2CPutBits(b, 0, 1); - b->I2CUDelay(b, b->HoldTime); - - return r; -} - -/* This is the default I2CGetByte function if not supplied by the driver. - * - * A single byte is read from the device. - * The function returns FALSE if a timeout occurs, you should send - * a stop condition afterwards to reset the bus. - * - * A timeout occurs, - * if the slave pulls SCL to slow down the bus more than ByteTimeout usecs, - * or slows down the bus for more than b->BitTimeout usecs for each bit. - * - * ByteTimeout must be at least b->HoldTime, the other timeouts can be - * zero according to the comment on I2CRaiseSCL. - * - * For the byte in a sequence the acknowledge bit NACK (1), - * otherwise ACK (0) will be sent. - */ - -static Bool -I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) -{ - int i, sda; - I2CBusPtr b = d->pI2CBus; - - b->I2CPutBits(b, 0, 1); - b->I2CUDelay(b, b->RiseFallTime); - - if (!I2CReadBit(b, &sda, d->ByteTimeout)) - return FALSE; - - *data = (sda > 0) << 7; - - for (i = 6; i >= 0; i--) - if (!I2CReadBit(b, &sda, d->BitTimeout)) - return FALSE; - else - *data |= (sda > 0) << i; - - if (!I2CWriteBit(b, last ? 1 : 0, d->BitTimeout)) - return FALSE; - - I2C_TRACE(ErrorF("R%02x%c ", (int) *data, last ? '+' : '-')); - - return TRUE; -} - -/* This is the default I2CAddress function if not supplied by the driver. - * - * It creates the start condition, followed by the d->SlaveAddr. - * Higher level functions must call this routine rather than - * I2CStart/PutByte because a hardware I2C master may not be able - * to send a slave address without a start condition. - * - * The same timeouts apply as with I2CPutByte and additional a - * StartTimeout, similar to the ByteTimeout but for the start - * condition. - * - * In case of a timeout, the bus is left in a clean idle condition. - * I. e. you *must not* send a Stop. If this function succeeds, you *must*. - * - * The slave address format is 16 bit, with the legacy _8_bit_ slave address - * in the least significant byte. This is, the slave address must include the - * R/_W flag as least significant bit. - * - * The most significant byte of the address will be sent _after_ the LSB, - * but only if the LSB indicates: - * a) an 11 bit address, this is LSB = 1111 0xxx. - * b) a 'general call address', this is LSB = 0000 000x - see the I2C specs - * for more. - */ - -static Bool -I2CAddress(I2CDevPtr d, I2CSlaveAddr addr) -{ - if (I2CStart(d->pI2CBus, d->StartTimeout)) { - if (I2CPutByte(d, addr & 0xFF)) { - if ((addr & 0xF8) != 0xF0 && - (addr & 0xFE) != 0x00) - return TRUE; - - if (I2CPutByte(d, (addr >> 8) & 0xFF)) - return TRUE; - } - - I2CStop(d); - } - - return FALSE; -} - -/* These are the hardware independent I2C helper functions. - * ======================================================== - */ - -/* Function for probing. Just send the slave address - * and return true if the device responds. The slave address - * must have the lsb set to reflect a read (1) or write (0) access. - * Don't expect a read- or write-only device will respond otherwise. - */ - -Bool -xf86I2CProbeAddress(I2CBusPtr b, I2CSlaveAddr addr) -{ - int r; - I2CDevRec d; - - d.DevName = "Probing"; - d.BitTimeout = b->BitTimeout; - d.ByteTimeout = b->ByteTimeout; - d.AcknTimeout = b->AcknTimeout; - d.StartTimeout = b->StartTimeout; - d.SlaveAddr = addr; - d.pI2CBus = b; - d.NextDev = NULL; - - r = b->I2CAddress(&d, addr); - - if (r) b->I2CStop(&d); - - return r; -} - -/* All functions below are related to devices and take the - * slave address and timeout values from an I2CDevRec. They - * return FALSE in case of an error (presumably a timeout). - */ - -/* General purpose read and write function. - * - * 1st, if nWrite > 0 - * Send a start condition - * Send the slave address (1 or 2 bytes) with write flag - * Write n bytes from WriteBuffer - * 2nd, if nRead > 0 - * Send a start condition [again] - * Send the slave address (1 or 2 bytes) with read flag - * Read n bytes to ReadBuffer - * 3rd, if a Start condition has been successfully sent, - * Send a Stop condition. - * - * The functions exits immediately when an error occures, - * not proceeding any data left. However, step 3 will - * be executed anyway to leave the bus in clean idle state. - */ - -static Bool -I2CWriteRead(I2CDevPtr d, - I2CByte *WriteBuffer, int nWrite, - I2CByte *ReadBuffer, int nRead) -{ - Bool r = TRUE; - I2CBusPtr b = d->pI2CBus; - int s = 0; - - if (r && nWrite > 0) { - r = b->I2CAddress(d, d->SlaveAddr & ~1); - if (r) { - for (; nWrite > 0; WriteBuffer++, nWrite--) - if (!(r = b->I2CPutByte(d, *WriteBuffer))) - break; - s++; - } - } - - if (r && nRead > 0) { - r = b->I2CAddress(d, d->SlaveAddr | 1); - if (r) { - for (; nRead > 0; ReadBuffer++, nRead--) - if (!(r = b->I2CGetByte(d, ReadBuffer, nRead == 1))) - break; - s++; - } - } - - if (s) b->I2CStop(d); - - return r; -} - -/* wrapper - for compatibility and convinience */ - -Bool -xf86I2CWriteRead(I2CDevPtr d, - I2CByte *WriteBuffer, int nWrite, - I2CByte *ReadBuffer, int nRead) -{ - I2CBusPtr b = d->pI2CBus; - return b->I2CWriteRead(d,WriteBuffer,nWrite,ReadBuffer,nRead); -} - -/* Read a byte, the only readable register of a device. - */ - -Bool -xf86I2CReadStatus(I2CDevPtr d, I2CByte *pbyte) -{ - return xf86I2CWriteRead(d, NULL, 0, pbyte, 1); -} - -/* Read a byte from one of the registers determined by its sub-address. - */ - -Bool -xf86I2CReadByte(I2CDevPtr d, I2CByte subaddr, I2CByte *pbyte) -{ - return xf86I2CWriteRead(d, &subaddr, 1, pbyte, 1); -} - -/* Read bytes from subsequent registers determined by the - * sub-address of the first register. - */ - -Bool -xf86I2CReadBytes(I2CDevPtr d, I2CByte subaddr, I2CByte *pbyte, int n) -{ - return xf86I2CWriteRead(d, &subaddr, 1, pbyte, n); -} - -/* Read a word (high byte, then low byte) from one of the registers - * determined by its sub-address. - */ - -Bool -xf86I2CReadWord(I2CDevPtr d, I2CByte subaddr, unsigned short *pword) -{ - I2CByte rb[2]; - - if (!xf86I2CWriteRead(d, &subaddr, 1, rb, 2)) return FALSE; - - *pword = (rb[0] << 8) | rb[1]; - - return TRUE; -} - -/* Write a byte to one of the registers determined by its sub-address. - */ - -Bool -xf86I2CWriteByte(I2CDevPtr d, I2CByte subaddr, I2CByte byte) -{ - I2CByte wb[2]; - - wb[0] = subaddr; - wb[1] = byte; - - return xf86I2CWriteRead(d, wb, 2, NULL, 0); -} - -/* Write bytes to subsequent registers determined by the - * sub-address of the first register. - */ - -Bool -xf86I2CWriteBytes(I2CDevPtr d, I2CByte subaddr, - I2CByte *WriteBuffer, int nWrite) -{ - I2CBusPtr b = d->pI2CBus; - Bool r = TRUE; - - if (nWrite > 0) { - r = b->I2CAddress(d, d->SlaveAddr & ~1); - if (r){ - if ((r = b->I2CPutByte(d, subaddr))) - for (; nWrite > 0; WriteBuffer++, nWrite--) - if (!(r = b->I2CPutByte(d, *WriteBuffer))) - break; - - b->I2CStop(d); - } - } - - return r; -} - -/* Write a word (high byte, then low byte) to one of the registers - * determined by its sub-address. - */ - -Bool -xf86I2CWriteWord(I2CDevPtr d, I2CByte subaddr, unsigned short word) -{ - I2CByte wb[3]; - - wb[0] = subaddr; - wb[1] = word >> 8; - wb[2] = word & 0xFF; - - return xf86I2CWriteRead(d, wb, 3, NULL, 0); -} - -/* Write a vector of bytes to not adjacent registers. This vector is, - * 1st byte sub-address, 2nd byte value, 3rd byte sub-address asf. - * This function is intended to initialize devices. Note this function - * exits immediately when an error occurs, some registers may - * remain uninitialized. - */ - -Bool -xf86I2CWriteVec(I2CDevPtr d, I2CByte *vec, int nValues) -{ - I2CBusPtr b = d->pI2CBus; - Bool r = TRUE; - int s = 0; - - if (nValues > 0) { - for (; nValues > 0; nValues--, vec += 2) { - if (!(r = b->I2CAddress(d, d->SlaveAddr & ~1))) - break; - - s++; - - if (!(r = b->I2CPutByte(d, vec[0]))) - break; - - if (!(r = b->I2CPutByte(d, vec[1]))) - break; - } - - if (s > 0) b->I2CStop(d); - } - - return r; -} - -/* Administrative functions. - * ========================= - */ - -/* Allocates an I2CDevRec for you and initializes with propper defaults - * you may modify before calling xf86I2CDevInit. Your I2CDevRec must - * contain at least a SlaveAddr, and a pI2CBus pointer to the bus this - * device shall be linked to. - * - * See function I2CAddress for the slave address format. Always set - * the least significant bit, indicating a read or write access, to zero. - */ - -I2CDevPtr -xf86CreateI2CDevRec(void) -{ - return xcalloc(1, sizeof(I2CDevRec)); -} - -/* Unlink an I2C device. If you got the I2CDevRec from xf86CreateI2CDevRec - * you should set to free it. - */ - -void -xf86DestroyI2CDevRec(I2CDevPtr d, Bool unalloc) -{ - if (d) { - I2CDevPtr *p; - - /* Remove this from the list of active I2C devices. */ - - for (p = &d->pI2CBus->FirstDev; *p != NULL; p = &(*p)->NextDev) - if (*p == d) { - *p = (*p)->NextDev; - break; - } - - xf86DrvMsg(d->pI2CBus->scrnIndex, X_INFO, - "I2C device \"%s:%s\" removed.\n", - d->pI2CBus->BusName, d->DevName); - - if (unalloc) xfree(d); - } -} - -/* I2C transmissions are related to an I2CDevRec you must link to a - * previously registered bus (see xf86I2CBusInit) before attempting - * to read and write data. You may call xf86I2CProbeAddress first to - * see if the device in question is present on this bus. - * - * xf86I2CDevInit will not allocate an I2CBusRec for you, instead you - * may enter a pointer to a statically allocated I2CDevRec or the (modified) - * result of xf86CreateI2CDevRec. - * - * If you don't specify timeouts for the device (n <= 0), it will inherit - * the bus-wide defaults. The function returns TRUE on success. - */ - -Bool -xf86I2CDevInit(I2CDevPtr d) -{ - I2CBusPtr b; - - if (d == NULL || - (b = d->pI2CBus) == NULL || - (d->SlaveAddr & 1) || - xf86I2CFindDev(b, d->SlaveAddr) != NULL) - return FALSE; - - if (d->BitTimeout <= 0) d->BitTimeout = b->BitTimeout; - if (d->ByteTimeout <= 0) d->ByteTimeout = b->ByteTimeout; - if (d->AcknTimeout <= 0) d->AcknTimeout = b->AcknTimeout; - if (d->StartTimeout <= 0) d->StartTimeout = b->StartTimeout; - - d->NextDev = b->FirstDev; - b->FirstDev = d; - - xf86DrvMsg(b->scrnIndex, X_INFO, - "I2C device \"%s:%s\" registered at address 0x%02X.\n", - b->BusName, d->DevName, d->SlaveAddr); - - return TRUE; -} - -I2CDevPtr -xf86I2CFindDev(I2CBusPtr b, I2CSlaveAddr addr) -{ - I2CDevPtr d; - - if (b) { - for (d = b->FirstDev; d != NULL; d = d->NextDev) - if (d->SlaveAddr == addr) - return d; - } - - return NULL; -} - -static I2CBusPtr I2CBusList; - -/* Allocates an I2CBusRec for you and initializes with propper defaults - * you may modify before calling xf86I2CBusInit. Your I2CBusRec must - * contain at least a BusName, a scrnIndex (or -1), and a complete set - * of either high or low level I2C function pointers. You may pass - * bus-wide timeouts, otherwise inplausible values will be replaced - * with safe defaults. - */ - -I2CBusPtr -xf86CreateI2CBusRec(void) -{ - I2CBusPtr b; - - b = (I2CBusPtr) xcalloc(1, sizeof(I2CBusRec)); - - if (b != NULL) { - b->scrnIndex = -1; - b->HoldTime = 5; /* 100 kHz bus */ - b->BitTimeout = 5; - b->ByteTimeout = 5; - b->AcknTimeout = 5; - b->StartTimeout = 5; - b->RiseFallTime = RISEFALLTIME; - } - - return b; -} - -/* Unregister an I2C bus. If you got the I2CBusRec from xf86CreateI2CBusRec - * you should set to free it. If you set , the function - * xf86DestroyI2CDevRec will be called for all devices linked to the bus - * first, passing down the option. - */ - -void -xf86DestroyI2CBusRec(I2CBusPtr b, Bool unalloc, Bool devs_too) -{ - if (b) { - I2CBusPtr *p; - - /* Remove this from the list of active I2C buses */ - - for (p = &I2CBusList; *p != NULL; p = &(*p)->NextBus) - if (*p == b) { - *p = (*p)->NextBus; - break; - } - - if (b->FirstDev != NULL) { - if (devs_too) { - I2CDevPtr d; - - while ((d = b->FirstDev) != NULL) { - b->FirstDev = d->NextDev; - xf86DestroyI2CDevRec(d, unalloc); - } - } else { - if (unalloc) { - xf86Msg(X_ERROR, "i2c bug: Attempt to remove I2C bus \"%s\", " - "but device list is not empty.\n", - b->BusName); - return; - } - } - } - - xf86DrvMsg(b->scrnIndex, X_INFO, "I2C bus \"%s\" removed.\n", - b->BusName); - - if (unalloc) xfree(b); - } -} - -/* I2C masters have to register themselves using this function. - * It will not allocate an I2CBusRec for you, instead you may enter - * a pointer to a statically allocated I2CBusRec or the (modified) - * result of xf86CreateI2CBusRec. Returns TRUE on success. - * - * At this point there won't be any traffic on the I2C bus. - */ - -Bool -xf86I2CBusInit(I2CBusPtr b) -{ - /* I2C buses must be identified by a unique scrnIndex - * and name. If scrnIndex is unspecified (a negative value), - * then the name must be unique throughout the server. - */ - - if (b->BusName == NULL || - xf86I2CFindBus(b->scrnIndex, b->BusName) != NULL) - return FALSE; - - /* If the high level functions are not - * supplied, use the generic functions. - * In this case we need the low-level - * function. - */ - if (b->I2CWriteRead == NULL) - { - b->I2CWriteRead=I2CWriteRead; - - if (b->I2CPutBits == NULL || - b->I2CGetBits == NULL) - { - if (b->I2CPutByte == NULL || - b->I2CGetByte == NULL || - b->I2CAddress == NULL || - b->I2CStart == NULL || - b->I2CStop == NULL) - return FALSE; - } else { - b->I2CPutByte = I2CPutByte; - b->I2CGetByte = I2CGetByte; - b->I2CAddress = I2CAddress; - b->I2CStop = I2CStop; - b->I2CStart = I2CStart; - } - } - - if (b->I2CUDelay == NULL) - b->I2CUDelay = I2CUDelay; - - if (b->HoldTime < 2) b->HoldTime = 5; - if (b->BitTimeout <= 0) b->BitTimeout = b->HoldTime; - if (b->ByteTimeout <= 0) b->ByteTimeout = b->HoldTime; - if (b->AcknTimeout <= 0) b->AcknTimeout = b->HoldTime; - if (b->StartTimeout <= 0) b->StartTimeout = b->HoldTime; - - /* Put new bus on list. */ - - b->NextBus = I2CBusList; - I2CBusList = b; - - xf86DrvMsg(b->scrnIndex, X_INFO, "I2C bus \"%s\" initialized.\n", - b->BusName); - - return TRUE; -} - -I2CBusPtr -xf86I2CFindBus(int scrnIndex, char *name) -{ - I2CBusPtr p; - - if (name != NULL) - for (p = I2CBusList; p != NULL; p = p->NextBus) - if (scrnIndex < 0 || p->scrnIndex == scrnIndex) - if (!strcmp(p->BusName, name)) - return p; - - return NULL; -} - -/* - * Return an array of I2CBusPtr's related to a screen. The caller is - * responsible for freeing the array. - */ -int -xf86I2CGetScreenBuses(int scrnIndex, I2CBusPtr **pppI2CBus) -{ - I2CBusPtr pI2CBus; - int n = 0; - - if (pppI2CBus) - *pppI2CBus = NULL; - - for (pI2CBus = I2CBusList; pI2CBus; pI2CBus = pI2CBus->NextBus) { - if ((pI2CBus->scrnIndex >= 0) && (pI2CBus->scrnIndex != scrnIndex)) - continue; - - n++; - - if (!pppI2CBus) - continue; - - *pppI2CBus = xnfrealloc(*pppI2CBus, n * sizeof(I2CBusPtr)); - (*pppI2CBus)[n - 1] = pI2CBus; - } - - return n; -} +/* + * Copyright (C) 1998 Itai Nahshon, Michael Schimek + * + * The original code was derived from and inspired by + * the I2C driver from the Linux kernel. + * (c) 1998 Gerd Knorr + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include +#include +#include "scrnintstr.h" +#include "regionstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "validate.h" +#include "resource.h" +#include "gcstruct.h" +#include "dixstruct.h" + +#include "xf86i2c.h" + +#define I2C_TIMEOUT(x) /*(x)*/ /* Report timeouts */ +#define I2C_TRACE(x) /*(x)*/ /* Report progress */ + +/* This is the default I2CUDelay function if not supplied by the driver. + * High level I2C interfaces implementing the bus protocol in hardware + * should supply this function too. + * + * Delay execution at least usec microseconds. + * All values 0 to 1e6 inclusive must be expected. + */ + +static void +I2CUDelay(I2CBusPtr b, int usec) +{ + struct timeval begin, cur; + long d_secs, d_usecs; + long diff; + + if (usec > 0) { + X_GETTIMEOFDAY(&begin); + do { + /* It would be nice to use {xf86}usleep, + * but usleep (1) takes >10000 usec ! + */ + X_GETTIMEOFDAY(&cur); + d_secs = (cur.tv_sec - begin.tv_sec); + d_usecs = (cur.tv_usec - begin.tv_usec); + diff = d_secs*1000000 + d_usecs; + } while (diff>=0 && diff< (usec + 1)); + } +} + +/* Most drivers will register just with GetBits/PutBits functions. + * The following functions implement a software I2C protocol + * by using the promitive functions given by the driver. + * ================================================================ + * + * It is assumed that there is just one master on the I2C bus, therefore + * there is no explicit test for conflits. + */ + +#define RISEFALLTIME 2 /* usec, actually 300 to 1000 ns according to the i2c specs */ + +/* Some devices will hold SCL low to slow down the bus or until + * ready for transmission. + * + * This condition will be noticed when the master tries to raise + * the SCL line. You can set the timeout to zero if the slave device + * does not support this clock synchronization. + */ + +static Bool +I2CRaiseSCL(I2CBusPtr b, int sda, int timeout) +{ + int i, scl; + + b->I2CPutBits(b, 1, sda); + b->I2CUDelay(b, b->RiseFallTime); + + for (i = timeout; i > 0; i -= b->RiseFallTime) { + b->I2CGetBits(b, &scl, &sda); + if (scl) break; + b->I2CUDelay(b, b->RiseFallTime); + } + + if (i <= 0) { + I2C_TIMEOUT(ErrorF("[I2CRaiseSCL(<%s>, %d, %d) timeout]", b->BusName, sda, timeout)); + return FALSE; + } + + return TRUE; +} + +/* Send a start signal on the I2C bus. The start signal notifies + * devices that a new transaction is initiated by the bus master. + * + * The start signal is always followed by a slave address. + * Slave addresses are 8+ bits. The first 7 bits identify the + * device and the last bit signals if this is a read (1) or + * write (0) operation. + * + * There may be more than one start signal on one transaction. + * This happens for example on some devices that allow reading + * of registers. First send a start bit followed by the device + * address (with the last bit 0) and the register number. Then send + * a new start bit with the device address (with the last bit 1) + * and then read the value from the device. + * + * Note this is function does not implement a multiple master + * arbitration procedure. + */ + +static Bool +I2CStart(I2CBusPtr b, int timeout) +{ + if (!I2CRaiseSCL(b, 1, timeout)) + return FALSE; + + b->I2CPutBits(b, 1, 0); + b->I2CUDelay(b, b->HoldTime); + b->I2CPutBits(b, 0, 0); + b->I2CUDelay(b, b->HoldTime); + + I2C_TRACE(ErrorF("\ni2c: <")); + + return TRUE; +} + +/* This is the default I2CStop function if not supplied by the driver. + * + * Signal devices on the I2C bus that a transaction on the + * bus has finished. There may be more than one start signal + * on a transaction but only one stop signal. + */ + +static void +I2CStop(I2CDevPtr d) +{ + I2CBusPtr b = d->pI2CBus; + + b->I2CPutBits(b, 0, 0); + b->I2CUDelay(b, b->RiseFallTime); + + b->I2CPutBits(b, 1, 0); + b->I2CUDelay(b, b->HoldTime); + b->I2CPutBits(b, 1, 1); + b->I2CUDelay(b, b->HoldTime); + + I2C_TRACE(ErrorF(">\n")); +} + +/* Write/Read a single bit to/from a device. + * Return FALSE if a timeout occurs. + */ + +static Bool +I2CWriteBit(I2CBusPtr b, int sda, int timeout) +{ + Bool r; + + b->I2CPutBits(b, 0, sda); + b->I2CUDelay(b, b->RiseFallTime); + + r = I2CRaiseSCL(b, sda, timeout); + b->I2CUDelay(b, b->HoldTime); + + b->I2CPutBits(b, 0, sda); + b->I2CUDelay(b, b->HoldTime); + + return r; +} + +static Bool +I2CReadBit(I2CBusPtr b, int *psda, int timeout) +{ + Bool r; + int scl; + + r = I2CRaiseSCL(b, 1, timeout); + b->I2CUDelay(b, b->HoldTime); + + b->I2CGetBits(b, &scl, psda); + + b->I2CPutBits(b, 0, 1); + b->I2CUDelay(b, b->HoldTime); + + return r; +} + +/* This is the default I2CPutByte function if not supplied by the driver. + * + * A single byte is sent to the device. + * The function returns FALSE if a timeout occurs, you should send + * a stop condition afterwards to reset the bus. + * + * A timeout occurs, + * if the slave pulls SCL to slow down the bus more than ByteTimeout usecs, + * or slows down the bus for more than BitTimeout usecs for each bit, + * or does not send an ACK bit (0) to acknowledge the transmission within + * AcknTimeout usecs, but a NACK (1) bit. + * + * AcknTimeout must be at least b->HoldTime, the other timeouts can be + * zero according to the comment on I2CRaiseSCL. + */ + +static Bool +I2CPutByte(I2CDevPtr d, I2CByte data) +{ + Bool r; + int i, scl, sda; + I2CBusPtr b = d->pI2CBus; + + if (!I2CWriteBit(b, (data >> 7) & 1, d->ByteTimeout)) + return FALSE; + + for (i = 6; i >= 0; i--) + if (!I2CWriteBit(b, (data >> i) & 1, d->BitTimeout)) + return FALSE; + + b->I2CPutBits(b, 0, 1); + b->I2CUDelay(b, b->RiseFallTime); + + r = I2CRaiseSCL(b, 1, b->HoldTime); + + if (r) { + for (i = d->AcknTimeout; i > 0; i -= b->HoldTime) { + b->I2CUDelay(b, b->HoldTime); + b->I2CGetBits(b, &scl, &sda); + if (sda == 0) break; + } + + if (i <= 0) { + I2C_TIMEOUT(ErrorF("[I2CPutByte(<%s>, 0x%02x, %d, %d, %d) timeout]", + b->BusName, data, d->BitTimeout, + d->ByteTimeout, d->AcknTimeout)); + r = FALSE; + } + + I2C_TRACE(ErrorF("W%02x%c ", (int) data, sda ? '-' : '+')); + } + + b->I2CPutBits(b, 0, 1); + b->I2CUDelay(b, b->HoldTime); + + return r; +} + +/* This is the default I2CGetByte function if not supplied by the driver. + * + * A single byte is read from the device. + * The function returns FALSE if a timeout occurs, you should send + * a stop condition afterwards to reset the bus. + * + * A timeout occurs, + * if the slave pulls SCL to slow down the bus more than ByteTimeout usecs, + * or slows down the bus for more than b->BitTimeout usecs for each bit. + * + * ByteTimeout must be at least b->HoldTime, the other timeouts can be + * zero according to the comment on I2CRaiseSCL. + * + * For the byte in a sequence the acknowledge bit NACK (1), + * otherwise ACK (0) will be sent. + */ + +static Bool +I2CGetByte(I2CDevPtr d, I2CByte *data, Bool last) +{ + int i, sda; + I2CBusPtr b = d->pI2CBus; + + b->I2CPutBits(b, 0, 1); + b->I2CUDelay(b, b->RiseFallTime); + + if (!I2CReadBit(b, &sda, d->ByteTimeout)) + return FALSE; + + *data = (sda > 0) << 7; + + for (i = 6; i >= 0; i--) + if (!I2CReadBit(b, &sda, d->BitTimeout)) + return FALSE; + else + *data |= (sda > 0) << i; + + if (!I2CWriteBit(b, last ? 1 : 0, d->BitTimeout)) + return FALSE; + + I2C_TRACE(ErrorF("R%02x%c ", (int) *data, last ? '+' : '-')); + + return TRUE; +} + +/* This is the default I2CAddress function if not supplied by the driver. + * + * It creates the start condition, followed by the d->SlaveAddr. + * Higher level functions must call this routine rather than + * I2CStart/PutByte because a hardware I2C master may not be able + * to send a slave address without a start condition. + * + * The same timeouts apply as with I2CPutByte and additional a + * StartTimeout, similar to the ByteTimeout but for the start + * condition. + * + * In case of a timeout, the bus is left in a clean idle condition. + * I. e. you *must not* send a Stop. If this function succeeds, you *must*. + * + * The slave address format is 16 bit, with the legacy _8_bit_ slave address + * in the least significant byte. This is, the slave address must include the + * R/_W flag as least significant bit. + * + * The most significant byte of the address will be sent _after_ the LSB, + * but only if the LSB indicates: + * a) an 11 bit address, this is LSB = 1111 0xxx. + * b) a 'general call address', this is LSB = 0000 000x - see the I2C specs + * for more. + */ + +static Bool +I2CAddress(I2CDevPtr d, I2CSlaveAddr addr) +{ + if (I2CStart(d->pI2CBus, d->StartTimeout)) { + if (I2CPutByte(d, addr & 0xFF)) { + if ((addr & 0xF8) != 0xF0 && + (addr & 0xFE) != 0x00) + return TRUE; + + if (I2CPutByte(d, (addr >> 8) & 0xFF)) + return TRUE; + } + + I2CStop(d); + } + + return FALSE; +} + +/* These are the hardware independent I2C helper functions. + * ======================================================== + */ + +/* Function for probing. Just send the slave address + * and return true if the device responds. The slave address + * must have the lsb set to reflect a read (1) or write (0) access. + * Don't expect a read- or write-only device will respond otherwise. + */ + +Bool +xf86I2CProbeAddress(I2CBusPtr b, I2CSlaveAddr addr) +{ + int r; + I2CDevRec d; + + d.DevName = "Probing"; + d.BitTimeout = b->BitTimeout; + d.ByteTimeout = b->ByteTimeout; + d.AcknTimeout = b->AcknTimeout; + d.StartTimeout = b->StartTimeout; + d.SlaveAddr = addr; + d.pI2CBus = b; + d.NextDev = NULL; + + r = b->I2CAddress(&d, addr); + + if (r) b->I2CStop(&d); + + return r; +} + +/* All functions below are related to devices and take the + * slave address and timeout values from an I2CDevRec. They + * return FALSE in case of an error (presumably a timeout). + */ + +/* General purpose read and write function. + * + * 1st, if nWrite > 0 + * Send a start condition + * Send the slave address (1 or 2 bytes) with write flag + * Write n bytes from WriteBuffer + * 2nd, if nRead > 0 + * Send a start condition [again] + * Send the slave address (1 or 2 bytes) with read flag + * Read n bytes to ReadBuffer + * 3rd, if a Start condition has been successfully sent, + * Send a Stop condition. + * + * The functions exits immediately when an error occures, + * not proceeding any data left. However, step 3 will + * be executed anyway to leave the bus in clean idle state. + */ + +static Bool +I2CWriteRead(I2CDevPtr d, + I2CByte *WriteBuffer, int nWrite, + I2CByte *ReadBuffer, int nRead) +{ + Bool r = TRUE; + I2CBusPtr b = d->pI2CBus; + int s = 0; + + if (r && nWrite > 0) { + r = b->I2CAddress(d, d->SlaveAddr & ~1); + if (r) { + for (; nWrite > 0; WriteBuffer++, nWrite--) + if (!(r = b->I2CPutByte(d, *WriteBuffer))) + break; + s++; + } + } + + if (r && nRead > 0) { + r = b->I2CAddress(d, d->SlaveAddr | 1); + if (r) { + for (; nRead > 0; ReadBuffer++, nRead--) + if (!(r = b->I2CGetByte(d, ReadBuffer, nRead == 1))) + break; + s++; + } + } + + if (s) b->I2CStop(d); + + return r; +} + +/* wrapper - for compatibility and convinience */ + +Bool +xf86I2CWriteRead(I2CDevPtr d, + I2CByte *WriteBuffer, int nWrite, + I2CByte *ReadBuffer, int nRead) +{ + I2CBusPtr b = d->pI2CBus; + return b->I2CWriteRead(d,WriteBuffer,nWrite,ReadBuffer,nRead); +} + +/* Read a byte, the only readable register of a device. + */ + +Bool +xf86I2CReadStatus(I2CDevPtr d, I2CByte *pbyte) +{ + return xf86I2CWriteRead(d, NULL, 0, pbyte, 1); +} + +/* Read a byte from one of the registers determined by its sub-address. + */ + +Bool +xf86I2CReadByte(I2CDevPtr d, I2CByte subaddr, I2CByte *pbyte) +{ + return xf86I2CWriteRead(d, &subaddr, 1, pbyte, 1); +} + +/* Read bytes from subsequent registers determined by the + * sub-address of the first register. + */ + +Bool +xf86I2CReadBytes(I2CDevPtr d, I2CByte subaddr, I2CByte *pbyte, int n) +{ + return xf86I2CWriteRead(d, &subaddr, 1, pbyte, n); +} + +/* Read a word (high byte, then low byte) from one of the registers + * determined by its sub-address. + */ + +Bool +xf86I2CReadWord(I2CDevPtr d, I2CByte subaddr, unsigned short *pword) +{ + I2CByte rb[2]; + + if (!xf86I2CWriteRead(d, &subaddr, 1, rb, 2)) return FALSE; + + *pword = (rb[0] << 8) | rb[1]; + + return TRUE; +} + +/* Write a byte to one of the registers determined by its sub-address. + */ + +Bool +xf86I2CWriteByte(I2CDevPtr d, I2CByte subaddr, I2CByte byte) +{ + I2CByte wb[2]; + + wb[0] = subaddr; + wb[1] = byte; + + return xf86I2CWriteRead(d, wb, 2, NULL, 0); +} + +/* Write bytes to subsequent registers determined by the + * sub-address of the first register. + */ + +Bool +xf86I2CWriteBytes(I2CDevPtr d, I2CByte subaddr, + I2CByte *WriteBuffer, int nWrite) +{ + I2CBusPtr b = d->pI2CBus; + Bool r = TRUE; + + if (nWrite > 0) { + r = b->I2CAddress(d, d->SlaveAddr & ~1); + if (r){ + if ((r = b->I2CPutByte(d, subaddr))) + for (; nWrite > 0; WriteBuffer++, nWrite--) + if (!(r = b->I2CPutByte(d, *WriteBuffer))) + break; + + b->I2CStop(d); + } + } + + return r; +} + +/* Write a word (high byte, then low byte) to one of the registers + * determined by its sub-address. + */ + +Bool +xf86I2CWriteWord(I2CDevPtr d, I2CByte subaddr, unsigned short word) +{ + I2CByte wb[3]; + + wb[0] = subaddr; + wb[1] = word >> 8; + wb[2] = word & 0xFF; + + return xf86I2CWriteRead(d, wb, 3, NULL, 0); +} + +/* Write a vector of bytes to not adjacent registers. This vector is, + * 1st byte sub-address, 2nd byte value, 3rd byte sub-address asf. + * This function is intended to initialize devices. Note this function + * exits immediately when an error occurs, some registers may + * remain uninitialized. + */ + +Bool +xf86I2CWriteVec(I2CDevPtr d, I2CByte *vec, int nValues) +{ + I2CBusPtr b = d->pI2CBus; + Bool r = TRUE; + int s = 0; + + if (nValues > 0) { + for (; nValues > 0; nValues--, vec += 2) { + if (!(r = b->I2CAddress(d, d->SlaveAddr & ~1))) + break; + + s++; + + if (!(r = b->I2CPutByte(d, vec[0]))) + break; + + if (!(r = b->I2CPutByte(d, vec[1]))) + break; + } + + if (s > 0) b->I2CStop(d); + } + + return r; +} + +/* Administrative functions. + * ========================= + */ + +/* Allocates an I2CDevRec for you and initializes with propper defaults + * you may modify before calling xf86I2CDevInit. Your I2CDevRec must + * contain at least a SlaveAddr, and a pI2CBus pointer to the bus this + * device shall be linked to. + * + * See function I2CAddress for the slave address format. Always set + * the least significant bit, indicating a read or write access, to zero. + */ + +I2CDevPtr +xf86CreateI2CDevRec(void) +{ + return calloc(1, sizeof(I2CDevRec)); +} + +/* Unlink an I2C device. If you got the I2CDevRec from xf86CreateI2CDevRec + * you should set to free it. + */ + +void +xf86DestroyI2CDevRec(I2CDevPtr d, Bool unalloc) +{ + if (d) { + I2CDevPtr *p; + + /* Remove this from the list of active I2C devices. */ + + for (p = &d->pI2CBus->FirstDev; *p != NULL; p = &(*p)->NextDev) + if (*p == d) { + *p = (*p)->NextDev; + break; + } + + xf86DrvMsg(d->pI2CBus->scrnIndex, X_INFO, + "I2C device \"%s:%s\" removed.\n", + d->pI2CBus->BusName, d->DevName); + + if (unalloc) free(d); + } +} + +/* I2C transmissions are related to an I2CDevRec you must link to a + * previously registered bus (see xf86I2CBusInit) before attempting + * to read and write data. You may call xf86I2CProbeAddress first to + * see if the device in question is present on this bus. + * + * xf86I2CDevInit will not allocate an I2CBusRec for you, instead you + * may enter a pointer to a statically allocated I2CDevRec or the (modified) + * result of xf86CreateI2CDevRec. + * + * If you don't specify timeouts for the device (n <= 0), it will inherit + * the bus-wide defaults. The function returns TRUE on success. + */ + +Bool +xf86I2CDevInit(I2CDevPtr d) +{ + I2CBusPtr b; + + if (d == NULL || + (b = d->pI2CBus) == NULL || + (d->SlaveAddr & 1) || + xf86I2CFindDev(b, d->SlaveAddr) != NULL) + return FALSE; + + if (d->BitTimeout <= 0) d->BitTimeout = b->BitTimeout; + if (d->ByteTimeout <= 0) d->ByteTimeout = b->ByteTimeout; + if (d->AcknTimeout <= 0) d->AcknTimeout = b->AcknTimeout; + if (d->StartTimeout <= 0) d->StartTimeout = b->StartTimeout; + + d->NextDev = b->FirstDev; + b->FirstDev = d; + + xf86DrvMsg(b->scrnIndex, X_INFO, + "I2C device \"%s:%s\" registered at address 0x%02X.\n", + b->BusName, d->DevName, d->SlaveAddr); + + return TRUE; +} + +I2CDevPtr +xf86I2CFindDev(I2CBusPtr b, I2CSlaveAddr addr) +{ + I2CDevPtr d; + + if (b) { + for (d = b->FirstDev; d != NULL; d = d->NextDev) + if (d->SlaveAddr == addr) + return d; + } + + return NULL; +} + +static I2CBusPtr I2CBusList; + +/* Allocates an I2CBusRec for you and initializes with propper defaults + * you may modify before calling xf86I2CBusInit. Your I2CBusRec must + * contain at least a BusName, a scrnIndex (or -1), and a complete set + * of either high or low level I2C function pointers. You may pass + * bus-wide timeouts, otherwise inplausible values will be replaced + * with safe defaults. + */ + +I2CBusPtr +xf86CreateI2CBusRec(void) +{ + I2CBusPtr b; + + b = (I2CBusPtr) calloc(1, sizeof(I2CBusRec)); + + if (b != NULL) { + b->scrnIndex = -1; + b->HoldTime = 5; /* 100 kHz bus */ + b->BitTimeout = 5; + b->ByteTimeout = 5; + b->AcknTimeout = 5; + b->StartTimeout = 5; + b->RiseFallTime = RISEFALLTIME; + } + + return b; +} + +/* Unregister an I2C bus. If you got the I2CBusRec from xf86CreateI2CBusRec + * you should set to free it. If you set , the function + * xf86DestroyI2CDevRec will be called for all devices linked to the bus + * first, passing down the option. + */ + +void +xf86DestroyI2CBusRec(I2CBusPtr b, Bool unalloc, Bool devs_too) +{ + if (b) { + I2CBusPtr *p; + + /* Remove this from the list of active I2C buses */ + + for (p = &I2CBusList; *p != NULL; p = &(*p)->NextBus) + if (*p == b) { + *p = (*p)->NextBus; + break; + } + + if (b->FirstDev != NULL) { + if (devs_too) { + I2CDevPtr d; + + while ((d = b->FirstDev) != NULL) { + b->FirstDev = d->NextDev; + xf86DestroyI2CDevRec(d, unalloc); + } + } else { + if (unalloc) { + xf86Msg(X_ERROR, "i2c bug: Attempt to remove I2C bus \"%s\", " + "but device list is not empty.\n", + b->BusName); + return; + } + } + } + + xf86DrvMsg(b->scrnIndex, X_INFO, "I2C bus \"%s\" removed.\n", + b->BusName); + + if (unalloc) free(b); + } +} + +/* I2C masters have to register themselves using this function. + * It will not allocate an I2CBusRec for you, instead you may enter + * a pointer to a statically allocated I2CBusRec or the (modified) + * result of xf86CreateI2CBusRec. Returns TRUE on success. + * + * At this point there won't be any traffic on the I2C bus. + */ + +Bool +xf86I2CBusInit(I2CBusPtr b) +{ + /* I2C buses must be identified by a unique scrnIndex + * and name. If scrnIndex is unspecified (a negative value), + * then the name must be unique throughout the server. + */ + + if (b->BusName == NULL || + xf86I2CFindBus(b->scrnIndex, b->BusName) != NULL) + return FALSE; + + /* If the high level functions are not + * supplied, use the generic functions. + * In this case we need the low-level + * function. + */ + if (b->I2CWriteRead == NULL) + { + b->I2CWriteRead=I2CWriteRead; + + if (b->I2CPutBits == NULL || + b->I2CGetBits == NULL) + { + if (b->I2CPutByte == NULL || + b->I2CGetByte == NULL || + b->I2CAddress == NULL || + b->I2CStart == NULL || + b->I2CStop == NULL) + return FALSE; + } else { + b->I2CPutByte = I2CPutByte; + b->I2CGetByte = I2CGetByte; + b->I2CAddress = I2CAddress; + b->I2CStop = I2CStop; + b->I2CStart = I2CStart; + } + } + + if (b->I2CUDelay == NULL) + b->I2CUDelay = I2CUDelay; + + if (b->HoldTime < 2) b->HoldTime = 5; + if (b->BitTimeout <= 0) b->BitTimeout = b->HoldTime; + if (b->ByteTimeout <= 0) b->ByteTimeout = b->HoldTime; + if (b->AcknTimeout <= 0) b->AcknTimeout = b->HoldTime; + if (b->StartTimeout <= 0) b->StartTimeout = b->HoldTime; + + /* Put new bus on list. */ + + b->NextBus = I2CBusList; + I2CBusList = b; + + xf86DrvMsg(b->scrnIndex, X_INFO, "I2C bus \"%s\" initialized.\n", + b->BusName); + + return TRUE; +} + +I2CBusPtr +xf86I2CFindBus(int scrnIndex, char *name) +{ + I2CBusPtr p; + + if (name != NULL) + for (p = I2CBusList; p != NULL; p = p->NextBus) + if (scrnIndex < 0 || p->scrnIndex == scrnIndex) + if (!strcmp(p->BusName, name)) + return p; + + return NULL; +} + +/* + * Return an array of I2CBusPtr's related to a screen. The caller is + * responsible for freeing the array. + */ +int +xf86I2CGetScreenBuses(int scrnIndex, I2CBusPtr **pppI2CBus) +{ + I2CBusPtr pI2CBus; + int n = 0; + + if (pppI2CBus) + *pppI2CBus = NULL; + + for (pI2CBus = I2CBusList; pI2CBus; pI2CBus = pI2CBus->NextBus) { + if ((pI2CBus->scrnIndex >= 0) && (pI2CBus->scrnIndex != scrnIndex)) + continue; + + n++; + + if (!pppI2CBus) + continue; + + *pppI2CBus = xnfrealloc(*pppI2CBus, n * sizeof(I2CBusPtr)); + (*pppI2CBus)[n - 1] = pI2CBus; + } + + return n; +} diff --git a/xorg-server/hw/xfree86/int10/generic.c b/xorg-server/hw/xfree86/int10/generic.c index 9d39e99b0..c242405cc 100644 --- a/xorg-server/hw/xfree86/int10/generic.c +++ b/xorg-server/hw/xfree86/int10/generic.c @@ -1,494 +1,494 @@ -/* - * XFree86 int10 module - * execute BIOS int 10h calls in x86 real mode environment - * Copyright 1999 Egbert Eich - */ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include - -#include "xf86.h" -#include "xf86_OSproc.h" -#include "compiler.h" -#define _INT10_PRIVATE -#include "xf86int10.h" -#include "int10Defines.h" -#include "Pci.h" - -#define ALLOC_ENTRIES(x) ((V_RAM / x) - 1) - -static CARD8 read_b(xf86Int10InfoPtr pInt,int addr); -static CARD16 read_w(xf86Int10InfoPtr pInt,int addr); -static CARD32 read_l(xf86Int10InfoPtr pInt,int addr); -static void write_b(xf86Int10InfoPtr pInt,int addr, CARD8 val); -static void write_w(xf86Int10InfoPtr pInt,int addr, CARD16 val); -static void write_l(xf86Int10InfoPtr pInt,int addr, CARD32 val); - -/* - * the emulator cannot pass a pointer to the current xf86Int10InfoRec - * to the memory access functions therefore store it here. - */ - -typedef struct { - int shift; - int entries; - void* base; - void* vRam; - int highMemory; - void* sysMem; - char* alloc; -} genericInt10Priv; - -#define INTPriv(x) ((genericInt10Priv*)x->private) - -int10MemRec genericMem = { - read_b, - read_w, - read_l, - write_b, - write_w, - write_l -}; - -static void MapVRam(xf86Int10InfoPtr pInt); -static void UnmapVRam(xf86Int10InfoPtr pInt); -#ifdef _PC -#define GET_HIGH_BASE(x) (((V_BIOS + (x) + getpagesize() - 1)/getpagesize()) \ - * getpagesize()) -#endif - -static void *sysMem = NULL; - -/** - * Read legacy VGA video BIOS associated with specified domain. - * - * Attempts to read up to 128KiB of legacy VGA video BIOS. - * - * \return - * The number of bytes read on success or -1 on failure. - * - * \bug - * PCI ROMs can contain multiple BIOS images (e.g., OpenFirmware, x86 VGA, - * etc.). How do we know that \c pci_device_read_rom will return the - * legacy VGA BIOS image? - */ -#ifndef _PC -static int -read_legacy_video_BIOS(struct pci_device *dev, unsigned char *Buf) -{ - const ADDRESS Base = 0xC0000; - const int Len = 0x10000 * 2; - const int pagemask = getpagesize() - 1; - const ADDRESS offset = Base & ~pagemask; - const unsigned long size = ((Base + Len + pagemask) & ~pagemask) - offset; - unsigned char *ptr, *src; - int len; - - - /* Try to use the civilized PCI interface first. - */ - if (pci_device_read_rom(dev, Buf) == 0) { - return dev->rom_size; - } - - ptr = xf86MapDomainMemory(-1, VIDMEM_READONLY, dev, offset, size); - - if (!ptr) - return -1; - - /* Using memcpy() here can hang the system */ - src = ptr + (Base - offset); - for (len = 0; len < (Len / 2); len++) { - Buf[len] = src[len]; - } - - if ((Buf[0] == 0x55) && (Buf[1] == 0xAA) && (Buf[2] > 0x80)) { - for ( /* empty */ ; len < Len; len++) { - Buf[len] = src[len]; - } - } - - xf86UnMapVidMem(-1, ptr, size); - - return Len; -} -#endif /* _PC */ - - -xf86Int10InfoPtr -xf86ExtendedInitInt10(int entityIndex, int Flags) -{ - xf86Int10InfoPtr pInt; - void* base = 0; - void* vbiosMem = 0; - void* options = NULL; - int screen; - legacyVGARec vga; - -#if 0 - CARD32 cs; -#endif - - screen = (xf86FindScreenForEntity(entityIndex))->scrnIndex; - - options = xf86HandleInt10Options(xf86Screens[screen],entityIndex); - - if (int10skip(options)) { - xfree(options); - return NULL; - } - - pInt = (xf86Int10InfoPtr)xnfcalloc(1, sizeof(xf86Int10InfoRec)); - pInt->entityIndex = entityIndex; - if (!xf86Int10ExecSetup(pInt)) - goto error0; - pInt->mem = &genericMem; - pInt->private = (pointer)xnfcalloc(1, sizeof(genericInt10Priv)); - INTPriv(pInt)->alloc = (pointer)xnfcalloc(1, ALLOC_ENTRIES(getpagesize())); - pInt->scrnIndex = screen; - base = INTPriv(pInt)->base = xnfalloc(SYS_BIOS); - - /* FIXME: Shouldn't this be a failure case? Leaving dev as NULL seems like - * FIXME: an error - */ - pInt->dev = xf86GetPciInfoForEntity(entityIndex); - - /* - * we need to map video RAM MMIO as some chipsets map mmio - * registers into this range. - */ - MapVRam(pInt); -#ifdef _PC - if (!sysMem) - sysMem = xf86MapVidMem(screen, VIDMEM_MMIO, V_BIOS, - BIOS_SIZE + SYS_BIOS - V_BIOS); - INTPriv(pInt)->sysMem = sysMem; - - if (xf86ReadBIOS(0, 0, base, LOW_PAGE_SIZE) < 0) { - xf86DrvMsg(screen, X_ERROR, "Cannot read int vect\n"); - goto error1; - } - - /* - * Retrieve everything between V_BIOS and SYS_BIOS as some system BIOSes - * have executable code there. Note that xf86ReadBIOS() can only read in - * 64kB at a time. - */ - memset((char *)base + V_BIOS, 0, SYS_BIOS - V_BIOS); -#if 0 - for (cs = V_BIOS; cs < SYS_BIOS; cs += V_BIOS_SIZE) - if (xf86ReadBIOS(cs, 0, (unsigned char *)base + cs, V_BIOS_SIZE) < - V_BIOS_SIZE) - xf86DrvMsg(screen, X_WARNING, - "Unable to retrieve all of segment 0x%06X.\n", cs); -#endif - INTPriv(pInt)->highMemory = V_BIOS; - - if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) { - if (!xf86int10GetBiosSegment(pInt, (unsigned char *)sysMem - V_BIOS)) - goto error1; - - set_return_trap(pInt); - - pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); - if (! (pInt->Flags & SET_BIOS_SCRATCH)) - pInt->Flags &= ~RESTORE_BIOS_SCRATCH; - xf86Int10SaveRestoreBIOSVars(pInt, TRUE); - - } else { - const BusType location_type = xf86int10GetBiosLocationType(pInt); - int bios_location = V_BIOS; - - reset_int_vect(pInt); - set_return_trap(pInt); - - switch (location_type) { - case BUS_PCI: { - int err; - struct pci_device *rom_device = - xf86GetPciInfoForEntity(pInt->entityIndex); - - vbiosMem = (unsigned char *)base + bios_location; - err = pci_device_read_rom(rom_device, vbiosMem); - if (err) { - xf86DrvMsg(screen,X_ERROR,"Cannot read V_BIOS (3) %s\n", - strerror(err)); - goto error1; - } - INTPriv(pInt)->highMemory = GET_HIGH_BASE(rom_device->rom_size); - break; - } - default: - goto error1; - } - pInt->BIOSseg = V_BIOS >> 4; - pInt->num = 0xe6; - LockLegacyVGA(pInt, &vga); - xf86ExecX86int10(pInt); - UnlockLegacyVGA(pInt, &vga); - } -#else - if (!sysMem) { - sysMem = xnfalloc(BIOS_SIZE); - setup_system_bios(sysMem); - } - INTPriv(pInt)->sysMem = sysMem; - setup_int_vect(pInt); - set_return_trap(pInt); - - /* Retrieve the entire legacy video BIOS segment. This can be upto - * 128KiB. - */ - vbiosMem = (char *)base + V_BIOS; - memset(vbiosMem, 0, 2 * V_BIOS_SIZE); - if (read_legacy_video_BIOS(pInt->dev, vbiosMem) < V_BIOS_SIZE) { - xf86DrvMsg(screen, X_WARNING, - "Unable to retrieve all of segment 0x0C0000.\n"); - } - - /* - * If this adapter is the primary, use its post-init BIOS (if we can find - * it). - */ - { - int bios_location = V_BIOS; - Bool done = FALSE; - vbiosMem = (unsigned char *)base + bios_location; - - if (xf86IsEntityPrimary(entityIndex)) { - if (int10_check_bios(screen, bios_location >> 4, vbiosMem)) - done = TRUE; - else - xf86DrvMsg(screen,X_INFO, - "No legacy BIOS found -- trying PCI\n"); - } - if (!done) { - int err; - struct pci_device *rom_device = - xf86GetPciInfoForEntity(pInt->entityIndex); - - err = pci_device_read_rom(rom_device, vbiosMem); - if (err) { - xf86DrvMsg(screen,X_ERROR,"Cannot read V_BIOS (5) %s\n", - strerror(err)); - goto error1; - } - } - } - - pInt->BIOSseg = V_BIOS >> 4; - pInt->num = 0xe6; - LockLegacyVGA(pInt, &vga); - xf86ExecX86int10(pInt); - UnlockLegacyVGA(pInt, &vga); -#endif - xfree(options); - return pInt; - - error1: - xfree(base); - UnmapVRam(pInt); - xfree(INTPriv(pInt)->alloc); - xfree(pInt->private); - error0: - xfree(pInt); - xfree(options); - - return NULL; -} - -static void -MapVRam(xf86Int10InfoPtr pInt) -{ - int pagesize = getpagesize(); - int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize; - - INTPriv(pInt)->vRam = xf86MapDomainMemory(pInt->scrnIndex, VIDMEM_MMIO, - pInt->dev, V_RAM, size); - - pInt->ioBase = xf86Screens[pInt->scrnIndex]->domainIOBase; -} - -static void -UnmapVRam(xf86Int10InfoPtr pInt) -{ - int screen = pInt->scrnIndex; - int pagesize = getpagesize(); - int size = ((VRAM_SIZE + pagesize - 1)/pagesize) * pagesize; - - xf86UnMapVidMem(screen, INTPriv(pInt)->vRam, size); -} - -Bool -MapCurrentInt10(xf86Int10InfoPtr pInt) -{ - /* nothing to do here */ - return TRUE; -} - -void -xf86FreeInt10(xf86Int10InfoPtr pInt) -{ - if (!pInt) - return; -#if defined (_PC) - xf86Int10SaveRestoreBIOSVars(pInt, FALSE); -#endif - if (Int10Current == pInt) - Int10Current = NULL; - xfree(INTPriv(pInt)->base); - UnmapVRam(pInt); - xfree(INTPriv(pInt)->alloc); - xfree(pInt->private); - xfree(pInt); -} - -void * -xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off) -{ - int pagesize = getpagesize(); - int num_pages = ALLOC_ENTRIES(pagesize); - int i,j; - - for (i = 0; i < (num_pages - num); i++) { - if (INTPriv(pInt)->alloc[i] == 0) { - for (j = i; j < (num + i); j++) - if (INTPriv(pInt)->alloc[j] != 0) - break; - if (j == (num + i)) - break; - i += num; - } - } - if (i == (num_pages - num)) - return NULL; - - for (j = i; j < (i + num); j++) - INTPriv(pInt)->alloc[j] = 1; - - *off = (i + 1) * pagesize; - - return (char *)INTPriv(pInt)->base + *off; -} - -void -xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num) -{ - int pagesize = getpagesize(); - int first = (((char *)pbase - (char *)INTPriv(pInt)->base) / pagesize) - 1; - int i; - - for (i = first; i < (first + num); i++) - INTPriv(pInt)->alloc[i] = 0; -} - -#define OFF(addr) ((addr) & 0xffff) -#if defined _PC -# define HIGH_OFFSET (INTPriv(pInt)->highMemory) -# define HIGH_BASE V_BIOS -#else -# define HIGH_OFFSET SYS_BIOS -# define HIGH_BASE SYS_BIOS -#endif -# define SYS(addr) ((addr) >= HIGH_OFFSET) -#define V_ADDR(addr) \ - (SYS(addr) ? ((char*)INTPriv(pInt)->sysMem) + (addr - HIGH_BASE) \ - : (((char*)(INTPriv(pInt)->base) + addr))) -#define VRAM_ADDR(addr) (addr - V_RAM) -#define VRAM_BASE (INTPriv(pInt)->vRam) - -#define VRAM(addr) ((addr >= V_RAM) && (addr < (V_RAM + VRAM_SIZE))) -#define V_ADDR_RB(addr) \ - (VRAM(addr)) ? MMIO_IN8((CARD8*)VRAM_BASE,VRAM_ADDR(addr)) \ - : *(CARD8*) V_ADDR(addr) -#define V_ADDR_RW(addr) \ - (VRAM(addr)) ? MMIO_IN16((CARD16*)VRAM_BASE,VRAM_ADDR(addr)) \ - : ldw_u((pointer)V_ADDR(addr)) -#define V_ADDR_RL(addr) \ - (VRAM(addr)) ? MMIO_IN32((CARD32*)VRAM_BASE,VRAM_ADDR(addr)) \ - : ldl_u((pointer)V_ADDR(addr)) - -#define V_ADDR_WB(addr,val) \ - if(VRAM(addr)) \ - MMIO_OUT8((CARD8*)VRAM_BASE,VRAM_ADDR(addr),val); \ - else \ - *(CARD8*) V_ADDR(addr) = val; -#define V_ADDR_WW(addr,val) \ - if(VRAM(addr)) \ - MMIO_OUT16((CARD16*)VRAM_BASE,VRAM_ADDR(addr),val); \ - else \ - stw_u((val),(pointer)(V_ADDR(addr))); - -#define V_ADDR_WL(addr,val) \ - if (VRAM(addr)) \ - MMIO_OUT32((CARD32*)VRAM_BASE,VRAM_ADDR(addr),val); \ - else \ - stl_u(val,(pointer)(V_ADDR(addr))); - -static CARD8 -read_b(xf86Int10InfoPtr pInt, int addr) -{ - return V_ADDR_RB(addr); -} - -static CARD16 -read_w(xf86Int10InfoPtr pInt, int addr) -{ -#if X_BYTE_ORDER == X_LITTLE_ENDIAN - if (OFF(addr + 1) > 0) - return V_ADDR_RW(addr); -#endif - return V_ADDR_RB(addr) | (V_ADDR_RB(addr + 1) << 8); -} - -static CARD32 -read_l(xf86Int10InfoPtr pInt, int addr) -{ -#if X_BYTE_ORDER == X_LITTLE_ENDIAN - if (OFF(addr + 3) > 2) - return V_ADDR_RL(addr); -#endif - return V_ADDR_RB(addr) | - (V_ADDR_RB(addr + 1) << 8) | - (V_ADDR_RB(addr + 2) << 16) | - (V_ADDR_RB(addr + 3) << 24); -} - -static void -write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val) -{ - V_ADDR_WB(addr,val); -} - -static void -write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val) -{ -#if X_BYTE_ORDER == X_LITTLE_ENDIAN - if (OFF(addr + 1) > 0) - { V_ADDR_WW(addr, val); } -#endif - V_ADDR_WB(addr, val); - V_ADDR_WB(addr + 1, val >> 8); -} - -static void -write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val) -{ -#if X_BYTE_ORDER == X_LITTLE_ENDIAN - if (OFF(addr + 3) > 2) - { V_ADDR_WL(addr, val); } -#endif - V_ADDR_WB(addr, val); - V_ADDR_WB(addr + 1, val >> 8); - V_ADDR_WB(addr + 2, val >> 16); - V_ADDR_WB(addr + 3, val >> 24); -} - -pointer -xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr) -{ - return V_ADDR(addr); -} +/* + * XFree86 int10 module + * execute BIOS int 10h calls in x86 real mode environment + * Copyright 1999 Egbert Eich + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" +#define _INT10_PRIVATE +#include "xf86int10.h" +#include "int10Defines.h" +#include "Pci.h" + +#define ALLOC_ENTRIES(x) ((V_RAM / x) - 1) + +static CARD8 read_b(xf86Int10InfoPtr pInt,int addr); +static CARD16 read_w(xf86Int10InfoPtr pInt,int addr); +static CARD32 read_l(xf86Int10InfoPtr pInt,int addr); +static void write_b(xf86Int10InfoPtr pInt,int addr, CARD8 val); +static void write_w(xf86Int10InfoPtr pInt,int addr, CARD16 val); +static void write_l(xf86Int10InfoPtr pInt,int addr, CARD32 val); + +/* + * the emulator cannot pass a pointer to the current xf86Int10InfoRec + * to the memory access functions therefore store it here. + */ + +typedef struct { + int shift; + int entries; + void* base; + void* vRam; + int highMemory; + void* sysMem; + char* alloc; +} genericInt10Priv; + +#define INTPriv(x) ((genericInt10Priv*)x->private) + +int10MemRec genericMem = { + read_b, + read_w, + read_l, + write_b, + write_w, + write_l +}; + +static void MapVRam(xf86Int10InfoPtr pInt); +static void UnmapVRam(xf86Int10InfoPtr pInt); +#ifdef _PC +#define GET_HIGH_BASE(x) (((V_BIOS + (x) + getpagesize() - 1)/getpagesize()) \ + * getpagesize()) +#endif + +static void *sysMem = NULL; + +/** + * Read legacy VGA video BIOS associated with specified domain. + * + * Attempts to read up to 128KiB of legacy VGA video BIOS. + * + * \return + * The number of bytes read on success or -1 on failure. + * + * \bug + * PCI ROMs can contain multiple BIOS images (e.g., OpenFirmware, x86 VGA, + * etc.). How do we know that \c pci_device_read_rom will return the + * legacy VGA BIOS image? + */ +#ifndef _PC +static int +read_legacy_video_BIOS(struct pci_device *dev, unsigned char *Buf) +{ + const ADDRESS Base = 0xC0000; + const int Len = 0x10000 * 2; + const int pagemask = getpagesize() - 1; + const ADDRESS offset = Base & ~pagemask; + const unsigned long size = ((Base + Len + pagemask) & ~pagemask) - offset; + unsigned char *ptr, *src; + int len; + + + /* Try to use the civilized PCI interface first. + */ + if (pci_device_read_rom(dev, Buf) == 0) { + return dev->rom_size; + } + + ptr = xf86MapDomainMemory(-1, VIDMEM_READONLY, dev, offset, size); + + if (!ptr) + return -1; + + /* Using memcpy() here can hang the system */ + src = ptr + (Base - offset); + for (len = 0; len < (Len / 2); len++) { + Buf[len] = src[len]; + } + + if ((Buf[0] == 0x55) && (Buf[1] == 0xAA) && (Buf[2] > 0x80)) { + for ( /* empty */ ; len < Len; len++) { + Buf[len] = src[len]; + } + } + + xf86UnMapVidMem(-1, ptr, size); + + return Len; +} +#endif /* _PC */ + + +xf86Int10InfoPtr +xf86ExtendedInitInt10(int entityIndex, int Flags) +{ + xf86Int10InfoPtr pInt; + void* base = 0; + void* vbiosMem = 0; + void* options = NULL; + int screen; + legacyVGARec vga; + +#if 0 + CARD32 cs; +#endif + + screen = (xf86FindScreenForEntity(entityIndex))->scrnIndex; + + options = xf86HandleInt10Options(xf86Screens[screen],entityIndex); + + if (int10skip(options)) { + free(options); + return NULL; + } + + pInt = (xf86Int10InfoPtr)xnfcalloc(1, sizeof(xf86Int10InfoRec)); + pInt->entityIndex = entityIndex; + if (!xf86Int10ExecSetup(pInt)) + goto error0; + pInt->mem = &genericMem; + pInt->private = (pointer)xnfcalloc(1, sizeof(genericInt10Priv)); + INTPriv(pInt)->alloc = (pointer)xnfcalloc(1, ALLOC_ENTRIES(getpagesize())); + pInt->scrnIndex = screen; + base = INTPriv(pInt)->base = xnfalloc(SYS_BIOS); + + /* FIXME: Shouldn't this be a failure case? Leaving dev as NULL seems like + * FIXME: an error + */ + pInt->dev = xf86GetPciInfoForEntity(entityIndex); + + /* + * we need to map video RAM MMIO as some chipsets map mmio + * registers into this range. + */ + MapVRam(pInt); +#ifdef _PC + if (!sysMem) + sysMem = xf86MapVidMem(screen, VIDMEM_MMIO, V_BIOS, + BIOS_SIZE + SYS_BIOS - V_BIOS); + INTPriv(pInt)->sysMem = sysMem; + + if (xf86ReadBIOS(0, 0, base, LOW_PAGE_SIZE) < 0) { + xf86DrvMsg(screen, X_ERROR, "Cannot read int vect\n"); + goto error1; + } + + /* + * Retrieve everything between V_BIOS and SYS_BIOS as some system BIOSes + * have executable code there. Note that xf86ReadBIOS() can only read in + * 64kB at a time. + */ + memset((char *)base + V_BIOS, 0, SYS_BIOS - V_BIOS); +#if 0 + for (cs = V_BIOS; cs < SYS_BIOS; cs += V_BIOS_SIZE) + if (xf86ReadBIOS(cs, 0, (unsigned char *)base + cs, V_BIOS_SIZE) < + V_BIOS_SIZE) + xf86DrvMsg(screen, X_WARNING, + "Unable to retrieve all of segment 0x%06X.\n", cs); +#endif + INTPriv(pInt)->highMemory = V_BIOS; + + if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) { + if (!xf86int10GetBiosSegment(pInt, (unsigned char *)sysMem - V_BIOS)) + goto error1; + + set_return_trap(pInt); + + pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); + if (! (pInt->Flags & SET_BIOS_SCRATCH)) + pInt->Flags &= ~RESTORE_BIOS_SCRATCH; + xf86Int10SaveRestoreBIOSVars(pInt, TRUE); + + } else { + const BusType location_type = xf86int10GetBiosLocationType(pInt); + int bios_location = V_BIOS; + + reset_int_vect(pInt); + set_return_trap(pInt); + + switch (location_type) { + case BUS_PCI: { + int err; + struct pci_device *rom_device = + xf86GetPciInfoForEntity(pInt->entityIndex); + + vbiosMem = (unsigned char *)base + bios_location; + err = pci_device_read_rom(rom_device, vbiosMem); + if (err) { + xf86DrvMsg(screen,X_ERROR,"Cannot read V_BIOS (3) %s\n", + strerror(err)); + goto error1; + } + INTPriv(pInt)->highMemory = GET_HIGH_BASE(rom_device->rom_size); + break; + } + default: + goto error1; + } + pInt->BIOSseg = V_BIOS >> 4; + pInt->num = 0xe6; + LockLegacyVGA(pInt, &vga); + xf86ExecX86int10(pInt); + UnlockLegacyVGA(pInt, &vga); + } +#else + if (!sysMem) { + sysMem = xnfalloc(BIOS_SIZE); + setup_system_bios(sysMem); + } + INTPriv(pInt)->sysMem = sysMem; + setup_int_vect(pInt); + set_return_trap(pInt); + + /* Retrieve the entire legacy video BIOS segment. This can be upto + * 128KiB. + */ + vbiosMem = (char *)base + V_BIOS; + memset(vbiosMem, 0, 2 * V_BIOS_SIZE); + if (read_legacy_video_BIOS(pInt->dev, vbiosMem) < V_BIOS_SIZE) { + xf86DrvMsg(screen, X_WARNING, + "Unable to retrieve all of segment 0x0C0000.\n"); + } + + /* + * If this adapter is the primary, use its post-init BIOS (if we can find + * it). + */ + { + int bios_location = V_BIOS; + Bool done = FALSE; + vbiosMem = (unsigned char *)base + bios_location; + + if (xf86IsEntityPrimary(entityIndex)) { + if (int10_check_bios(screen, bios_location >> 4, vbiosMem)) + done = TRUE; + else + xf86DrvMsg(screen,X_INFO, + "No legacy BIOS found -- trying PCI\n"); + } + if (!done) { + int err; + struct pci_device *rom_device = + xf86GetPciInfoForEntity(pInt->entityIndex); + + err = pci_device_read_rom(rom_device, vbiosMem); + if (err) { + xf86DrvMsg(screen,X_ERROR,"Cannot read V_BIOS (5) %s\n", + strerror(err)); + goto error1; + } + } + } + + pInt->BIOSseg = V_BIOS >> 4; + pInt->num = 0xe6; + LockLegacyVGA(pInt, &vga); + xf86ExecX86int10(pInt); + UnlockLegacyVGA(pInt, &vga); +#endif + free(options); + return pInt; + + error1: + free(base); + UnmapVRam(pInt); + free(INTPriv(pInt)->alloc); + free(pInt->private); + error0: + free(pInt); + free(options); + + return NULL; +} + +static void +MapVRam(xf86Int10InfoPtr pInt) +{ + int pagesize = getpagesize(); + int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize; + + INTPriv(pInt)->vRam = xf86MapDomainMemory(pInt->scrnIndex, VIDMEM_MMIO, + pInt->dev, V_RAM, size); + + pInt->ioBase = xf86Screens[pInt->scrnIndex]->domainIOBase; +} + +static void +UnmapVRam(xf86Int10InfoPtr pInt) +{ + int screen = pInt->scrnIndex; + int pagesize = getpagesize(); + int size = ((VRAM_SIZE + pagesize - 1)/pagesize) * pagesize; + + xf86UnMapVidMem(screen, INTPriv(pInt)->vRam, size); +} + +Bool +MapCurrentInt10(xf86Int10InfoPtr pInt) +{ + /* nothing to do here */ + return TRUE; +} + +void +xf86FreeInt10(xf86Int10InfoPtr pInt) +{ + if (!pInt) + return; +#if defined (_PC) + xf86Int10SaveRestoreBIOSVars(pInt, FALSE); +#endif + if (Int10Current == pInt) + Int10Current = NULL; + free(INTPriv(pInt)->base); + UnmapVRam(pInt); + free(INTPriv(pInt)->alloc); + free(pInt->private); + free(pInt); +} + +void * +xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off) +{ + int pagesize = getpagesize(); + int num_pages = ALLOC_ENTRIES(pagesize); + int i,j; + + for (i = 0; i < (num_pages - num); i++) { + if (INTPriv(pInt)->alloc[i] == 0) { + for (j = i; j < (num + i); j++) + if (INTPriv(pInt)->alloc[j] != 0) + break; + if (j == (num + i)) + break; + i += num; + } + } + if (i == (num_pages - num)) + return NULL; + + for (j = i; j < (i + num); j++) + INTPriv(pInt)->alloc[j] = 1; + + *off = (i + 1) * pagesize; + + return (char *)INTPriv(pInt)->base + *off; +} + +void +xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num) +{ + int pagesize = getpagesize(); + int first = (((char *)pbase - (char *)INTPriv(pInt)->base) / pagesize) - 1; + int i; + + for (i = first; i < (first + num); i++) + INTPriv(pInt)->alloc[i] = 0; +} + +#define OFF(addr) ((addr) & 0xffff) +#if defined _PC +# define HIGH_OFFSET (INTPriv(pInt)->highMemory) +# define HIGH_BASE V_BIOS +#else +# define HIGH_OFFSET SYS_BIOS +# define HIGH_BASE SYS_BIOS +#endif +# define SYS(addr) ((addr) >= HIGH_OFFSET) +#define V_ADDR(addr) \ + (SYS(addr) ? ((char*)INTPriv(pInt)->sysMem) + (addr - HIGH_BASE) \ + : (((char*)(INTPriv(pInt)->base) + addr))) +#define VRAM_ADDR(addr) (addr - V_RAM) +#define VRAM_BASE (INTPriv(pInt)->vRam) + +#define VRAM(addr) ((addr >= V_RAM) && (addr < (V_RAM + VRAM_SIZE))) +#define V_ADDR_RB(addr) \ + (VRAM(addr)) ? MMIO_IN8((CARD8*)VRAM_BASE,VRAM_ADDR(addr)) \ + : *(CARD8*) V_ADDR(addr) +#define V_ADDR_RW(addr) \ + (VRAM(addr)) ? MMIO_IN16((CARD16*)VRAM_BASE,VRAM_ADDR(addr)) \ + : ldw_u((pointer)V_ADDR(addr)) +#define V_ADDR_RL(addr) \ + (VRAM(addr)) ? MMIO_IN32((CARD32*)VRAM_BASE,VRAM_ADDR(addr)) \ + : ldl_u((pointer)V_ADDR(addr)) + +#define V_ADDR_WB(addr,val) \ + if(VRAM(addr)) \ + MMIO_OUT8((CARD8*)VRAM_BASE,VRAM_ADDR(addr),val); \ + else \ + *(CARD8*) V_ADDR(addr) = val; +#define V_ADDR_WW(addr,val) \ + if(VRAM(addr)) \ + MMIO_OUT16((CARD16*)VRAM_BASE,VRAM_ADDR(addr),val); \ + else \ + stw_u((val),(pointer)(V_ADDR(addr))); + +#define V_ADDR_WL(addr,val) \ + if (VRAM(addr)) \ + MMIO_OUT32((CARD32*)VRAM_BASE,VRAM_ADDR(addr),val); \ + else \ + stl_u(val,(pointer)(V_ADDR(addr))); + +static CARD8 +read_b(xf86Int10InfoPtr pInt, int addr) +{ + return V_ADDR_RB(addr); +} + +static CARD16 +read_w(xf86Int10InfoPtr pInt, int addr) +{ +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + if (OFF(addr + 1) > 0) + return V_ADDR_RW(addr); +#endif + return V_ADDR_RB(addr) | (V_ADDR_RB(addr + 1) << 8); +} + +static CARD32 +read_l(xf86Int10InfoPtr pInt, int addr) +{ +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + if (OFF(addr + 3) > 2) + return V_ADDR_RL(addr); +#endif + return V_ADDR_RB(addr) | + (V_ADDR_RB(addr + 1) << 8) | + (V_ADDR_RB(addr + 2) << 16) | + (V_ADDR_RB(addr + 3) << 24); +} + +static void +write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val) +{ + V_ADDR_WB(addr,val); +} + +static void +write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val) +{ +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + if (OFF(addr + 1) > 0) + { V_ADDR_WW(addr, val); } +#endif + V_ADDR_WB(addr, val); + V_ADDR_WB(addr + 1, val >> 8); +} + +static void +write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val) +{ +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + if (OFF(addr + 3) > 2) + { V_ADDR_WL(addr, val); } +#endif + V_ADDR_WB(addr, val); + V_ADDR_WB(addr + 1, val >> 8); + V_ADDR_WB(addr + 2, val >> 16); + V_ADDR_WB(addr + 3, val >> 24); +} + +pointer +xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr) +{ + return V_ADDR(addr); +} diff --git a/xorg-server/hw/xfree86/int10/helper_exec.c b/xorg-server/hw/xfree86/int10/helper_exec.c index 6ba647f89..5b6253646 100644 --- a/xorg-server/hw/xfree86/int10/helper_exec.c +++ b/xorg-server/hw/xfree86/int10/helper_exec.c @@ -1,727 +1,727 @@ -/* - * XFree86 int10 module - * execute BIOS int 10h calls in x86 real mode environment - * Copyright 1999 Egbert Eich - * - * Part of this code was inspired by the VBIOS POSTing code in DOSEMU - * developed by the "DOSEMU-Development-Team" - */ - -/* - * To debug port accesses define PRINT_PORT to 1. - * Note! You also have to comment out ioperm() - * in xf86EnableIO(). Otherwise we won't trap - * on PIO. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#define PRINT_PORT 0 - -#include - -#include -#include "xf86.h" -#include "xf86_OSproc.h" -#include "compiler.h" -#define _INT10_PRIVATE -#include "int10Defines.h" -#include "xf86int10.h" -#include "Pci.h" -#ifdef _X86EMU -#include "x86emu/x86emui.h" -#else -#define DEBUG_IO_TRACE() 0 -#endif -#include - -static int pciCfg1in(CARD16 addr, CARD32 *val); -static int pciCfg1out(CARD16 addr, CARD32 val); -static int pciCfg1inw(CARD16 addr, CARD16 *val); -static int pciCfg1outw(CARD16 addr, CARD16 val); -static int pciCfg1inb(CARD16 addr, CARD8 *val); -static int pciCfg1outb(CARD16 addr, CARD8 val); -#if defined (_PC) -static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set); -#endif - -#define REG pInt - -int -setup_int(xf86Int10InfoPtr pInt) -{ - if (pInt != Int10Current) { - if (!MapCurrentInt10(pInt)) - return -1; - Int10Current = pInt; - } - X86_EAX = (CARD32) pInt->ax; - X86_EBX = (CARD32) pInt->bx; - X86_ECX = (CARD32) pInt->cx; - X86_EDX = (CARD32) pInt->dx; - X86_ESI = (CARD32) pInt->si; - X86_EDI = (CARD32) pInt->di; - X86_EBP = (CARD32) pInt->bp; - X86_ESP = 0x1000; X86_SS = pInt->stackseg >> 4; - X86_EIP = 0x0600; X86_CS = 0x0; /* address of 'hlt' */ - X86_DS = 0x40; /* standard pc ds */ - X86_ES = pInt->es; - X86_FS = 0; - X86_GS = 0; - X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK; -#if defined (_PC) - if (pInt->Flags & SET_BIOS_SCRATCH) - SetResetBIOSVars(pInt, TRUE); -#endif - return xf86BlockSIGIO(); -} - -void -finish_int(xf86Int10InfoPtr pInt, int sig) -{ - xf86UnblockSIGIO(sig); - pInt->ax = (CARD32) X86_EAX; - pInt->bx = (CARD32) X86_EBX; - pInt->cx = (CARD32) X86_ECX; - pInt->dx = (CARD32) X86_EDX; - pInt->si = (CARD32) X86_ESI; - pInt->di = (CARD32) X86_EDI; - pInt->es = (CARD16) X86_ES; - pInt->bp = (CARD32) X86_EBP; - pInt->flags = (CARD32) X86_FLAGS; -#if defined (_PC) - if (pInt->Flags & RESTORE_BIOS_SCRATCH) - SetResetBIOSVars(pInt, FALSE); -#endif -} - -/* general software interrupt handler */ -CARD32 -getIntVect(xf86Int10InfoPtr pInt,int num) -{ - return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4); -} - -void -pushw(xf86Int10InfoPtr pInt, CARD16 val) -{ - X86_ESP -= 2; - MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val); -} - -int -run_bios_int(int num, xf86Int10InfoPtr pInt) -{ - CARD32 eflags; -#ifndef _PC - /* check if bios vector is initialized */ - if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ?*/ - - if (num == 21 && X86_AH == 0x4e) { - xf86DrvMsg(pInt->scrnIndex, X_NOTICE, - "Failing Find-Matching-File on non-PC" - " (int 21, func 4e)\n"); - X86_AX = 2; - SET_FLAG(F_CF); - return 1; - } else { - xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, - "Ignoring int 0x%02x call\n", num); - if (xf86GetVerbosity() > 3) { - dump_registers(pInt); - stack_trace(pInt); - } - return 1; - } - } -#endif -#ifdef PRINT_INT - ErrorF("calling card BIOS at: "); -#endif - eflags = X86_EFLAGS; -#if 0 - eflags = eflags | IF_MASK; - X86_EFLAGS = X86_EFLAGS & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK); -#endif - pushw(pInt, eflags); - pushw(pInt, X86_CS); - pushw(pInt, X86_IP); - X86_CS = MEM_RW(pInt, (num << 2) + 2); - X86_IP = MEM_RW(pInt, num << 2); -#ifdef PRINT_INT - ErrorF("0x%x:%lx\n", X86_CS, X86_EIP); -#endif - return 1; -} - -/* Debugging stuff */ -void -dump_code(xf86Int10InfoPtr pInt) -{ - int i; - unsigned long lina = SEG_ADR((CARD32), X86_CS, IP); - - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, "code at 0x%8.8lx:\n", lina); - for (i=0; i<0x10; i++) - xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); - xf86ErrorFVerb(3, "\n"); - for (; i<0x20; i++) - xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); - xf86ErrorFVerb(3, "\n"); -} - -void -dump_registers(xf86Int10InfoPtr pInt) -{ - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, - "EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n", - (unsigned long)X86_EAX, (unsigned long)X86_EBX, - (unsigned long)X86_ECX, (unsigned long)X86_EDX); - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, - "ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n", - (unsigned long)X86_ESP, (unsigned long)X86_EBP, - (unsigned long)X86_ESI, (unsigned long)X86_EDI); - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, - "CS=0x%4.4x, SS=0x%4.4x," - " DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n", - X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS); - xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, - "EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n", - (unsigned long)X86_EIP, (unsigned long)X86_EFLAGS); -} - -void -stack_trace(xf86Int10InfoPtr pInt) -{ - int i = 0; - unsigned long stack = SEG_ADR((CARD32), X86_SS, SP); - unsigned long tail = (CARD32)((X86_SS << 4) + 0x1000); - - if (stack >= tail) return; - - xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack); - for (; stack < tail; stack++) { - xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack)); - i = (i + 1) % 0x10; - if (!i) - xf86ErrorFVerb(3, "\n"); - } - if (i) - xf86ErrorFVerb(3, "\n"); -} - -int -port_rep_inb(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -1 : 1; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_insb(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - MEM_WB(pInt, dst, x_inb(port)); - dst += inc; - } - return dst - base; -} - -int -port_rep_inw(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -2 : 2; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_insw(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - MEM_WW(pInt, dst, x_inw(port)); - dst += inc; - } - return dst - base; -} - -int -port_rep_inl(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -4 : 4; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_insl(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - MEM_WL(pInt, dst, x_inl(port)); - dst += inc; - } - return dst - base; -} - -int -port_rep_outb(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -1 : 1; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_outb(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - x_outb(port, MEM_RB(pInt, dst)); - dst += inc; - } - return dst - base; -} - -int -port_rep_outw(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -2 : 2; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_outw(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - x_outw(port, MEM_RW(pInt, dst)); - dst += inc; - } - return dst - base; -} - -int -port_rep_outl(xf86Int10InfoPtr pInt, - CARD16 port, CARD32 base, int d_f, CARD32 count) -{ - register int inc = d_f ? -4 : 4; - CARD32 dst = base; - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" rep_outl(%#x) %ld bytes at %8.8lx %s\n", - port, count, base, d_f ? "up" : "down"); - while (count--) { - x_outl(port, MEM_RL(pInt, dst)); - dst += inc; - } - return dst - base; -} - -CARD8 -x_inb(CARD16 port) -{ - CARD8 val; - - if (port == 0x40) { - Int10Current->inb40time++; - val = (CARD8)(Int10Current->inb40time >> - ((Int10Current->inb40time & 1) << 3)); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" inb(%#x) = %2.2x\n", port, val); -#ifdef __NOT_YET__ - } else if (port < 0x0100) { /* Don't interfere with mainboard */ - val = 0; - xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2, - "inb 0x%4.4x\n", port); - if (xf86GetVerbosity() > 3) { - dump_registers(Int10Current); - stack_trace(Int10Current); - } -#endif /* __NOT_YET__ */ - } else if (!pciCfg1inb(port, &val)) { - val = inb(Int10Current->ioBase + port); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" inb(%#x) = %2.2x\n", port, val); - } - return val; -} - -CARD16 -x_inw(CARD16 port) -{ - CARD16 val; - - if (port == 0x5c) { - struct timeval tv; - - /* - * Emulate a PC98's timer. Typical resolution is 3.26 usec. - * Approximate this by dividing by 3. - */ - X_GETTIMEOFDAY(&tv); - val = (CARD16)(tv.tv_usec / 3); - } else if (!pciCfg1inw(port, &val)) { - val = inw(Int10Current->ioBase + port); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" inw(%#x) = %4.4x\n", port, val); - } - return val; -} - -void -x_outb(CARD16 port, CARD8 val) -{ - if ((port == 0x43) && (val == 0)) { - struct timeval tv; - /* - * Emulate a PC's timer 0. Such timers typically have a resolution of - * some .838 usec per tick, but this can only provide 1 usec per tick. - * (Not that this matters much, given inherent emulation delays.) Use - * the bottom bit as a byte select. See inb(0x40) above. - */ - X_GETTIMEOFDAY(&tv); - Int10Current->inb40time = (CARD16)(tv.tv_usec | 1); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" outb(%#x, %2.2x)\n", port, val); -#ifdef __NOT_YET__ - } else if (port < 0x0100) { /* Don't interfere with mainboard */ - xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2, - "outb 0x%4.4x,0x%2.2x\n", port, val); - if (xf86GetVerbosity() > 3) { - dump_registers(Int10Current); - stack_trace(Int10Current); - } -#endif /* __NOT_YET__ */ - } else if (!pciCfg1outb(port, val)) { - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" outb(%#x, %2.2x)\n", port, val); - outb(Int10Current->ioBase + port, val); - } -} - -void -x_outw(CARD16 port, CARD16 val) -{ - - if (!pciCfg1outw(port, val)) { - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" outw(%#x, %4.4x)\n", port, val); - outw(Int10Current->ioBase + port, val); - } -} - -CARD32 -x_inl(CARD16 port) -{ - CARD32 val; - - if (!pciCfg1in(port, &val)) { - val = inl(Int10Current->ioBase + port); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" inl(%#x) = %8.8lx\n", port, val); - } - return val; -} - -void -x_outl(CARD16 port, CARD32 val) -{ - if (!pciCfg1out(port, val)) { - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" outl(%#x, %8.8lx)\n", port, val); - outl(Int10Current->ioBase + port, val); - } -} - -CARD8 -Mem_rb(CARD32 addr) -{ - return (*Int10Current->mem->rb)(Int10Current, addr); -} - -CARD16 -Mem_rw(CARD32 addr) -{ - return (*Int10Current->mem->rw)(Int10Current, addr); -} - -CARD32 -Mem_rl(CARD32 addr) -{ - return (*Int10Current->mem->rl)(Int10Current, addr); -} - -void -Mem_wb(CARD32 addr, CARD8 val) -{ - (*Int10Current->mem->wb)(Int10Current, addr, val); -} - -void -Mem_ww(CARD32 addr, CARD16 val) -{ - (*Int10Current->mem->ww)(Int10Current, addr, val); -} - -void -Mem_wl(CARD32 addr, CARD32 val) -{ - (*Int10Current->mem->wl)(Int10Current, addr, val); -} - -static CARD32 PciCfg1Addr = 0; - -#define PCI_OFFSET(x) ((x) & 0x000000ff) -#define PCI_TAG(x) ((x) & 0x7fffff00) - -static struct pci_device* -pci_device_for_cfg_address (CARD32 addr) -{ - struct pci_device *dev = NULL; - PCITAG tag = PCI_TAG(addr); - struct pci_slot_match slot_match = { - .domain = PCI_DOM_FROM_TAG(tag), - .bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)), - .dev = PCI_DEV_FROM_TAG(tag), - .func = PCI_FUNC_FROM_TAG(tag), - .match_data = 0 - }; - - struct pci_device_iterator *iter = - pci_slot_match_iterator_create (&slot_match); - - if (iter) - dev = pci_device_next(iter); - - pci_iterator_destroy(iter); - - return dev; -} - -static int -pciCfg1in(CARD16 addr, CARD32 *val) -{ - if (addr == 0xCF8) { - *val = PciCfg1Addr; - return 1; - } - if (addr == 0xCFC) { - pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr)); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_inl(%#lx) = %8.8lx\n", PciCfg1Addr, *val); - return 1; - } - return 0; -} - -static int -pciCfg1out(CARD16 addr, CARD32 val) -{ - if (addr == 0xCF8) { - PciCfg1Addr = val; - return 1; - } - if (addr == 0xCFC) { - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_outl(%#lx, %8.8lx)\n", PciCfg1Addr, val); - pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr)); - return 1; - } - return 0; -} - -static int -pciCfg1inw(CARD16 addr, CARD16 *val) -{ - int shift; - - if ((addr >= 0xCF8) && (addr <= 0xCFB)) { - shift = (addr - 0xCF8) * 8; - *val = (PciCfg1Addr >> shift) & 0xffff; - return 1; - } - if ((addr >= 0xCFC) && (addr <= 0xCFF)) { - const unsigned offset = addr - 0xCFC; - - pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr) + offset); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_inw(%#lx) = %4.4x\n", PciCfg1Addr + offset, *val); - return 1; - } - return 0; -} - -static int -pciCfg1outw(CARD16 addr, CARD16 val) -{ - int shift; - - if ((addr >= 0xCF8) && (addr <= 0xCFB)) { - shift = (addr - 0xCF8) * 8; - PciCfg1Addr &= ~(0xffff << shift); - PciCfg1Addr |= ((CARD32) val) << shift; - return 1; - } - if ((addr >= 0xCFC) && (addr <= 0xCFF)) { - const unsigned offset = addr - 0xCFC; - - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_outw(%#lx, %4.4x)\n", PciCfg1Addr + offset, val); - pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr) + offset); - return 1; - } - return 0; -} - -static int -pciCfg1inb(CARD16 addr, CARD8 *val) -{ - int shift; - - if ((addr >= 0xCF8) && (addr <= 0xCFB)) { - shift = (addr - 0xCF8) * 8; - *val = (PciCfg1Addr >> shift) & 0xff; - return 1; - } - if ((addr >= 0xCFC) && (addr <= 0xCFF)) { - const unsigned offset = addr - 0xCFC; - - pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr) + offset); - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_inb(%#lx) = %2.2x\n", PciCfg1Addr + offset, *val); - return 1; - } - return 0; -} - -static int -pciCfg1outb(CARD16 addr, CARD8 val) -{ - int shift; - - if ((addr >= 0xCF8) && (addr <= 0xCFB)) { - shift = (addr - 0xCF8) * 8; - PciCfg1Addr &= ~(0xff << shift); - PciCfg1Addr |= ((CARD32) val) << shift; - return 1; - } - if ((addr >= 0xCFC) && (addr <= 0xCFF)) { - const unsigned offset = addr - 0xCFC; - - if (PRINT_PORT && DEBUG_IO_TRACE()) - ErrorF(" cfg_outb(%#lx, %2.2x)\n", PciCfg1Addr + offset, val); - pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr), - val, PCI_OFFSET(PciCfg1Addr) + offset); - return 1; - } - return 0; -} - -CARD8 -bios_checksum(const CARD8 *start, int size) -{ - CARD8 sum = 0; - - while (size-- > 0) - sum += *start++; - return sum; -} - -/* - * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make - * an attempt to detect a legacy ISA card. If they find one they might - * act very strange: for example they might configure the card as a - * monochrome card. This might cause some drivers to choke. - * To avoid this we attempt legacy VGA by writing to all know VGA - * disable registers before we call the BIOS initialization and - * restore the original values afterwards. In beween we hold our - * breath. To get to a (possibly exising) ISA card need to disable - * our current PCI card. - */ -/* - * This is just for booting: we just want to catch pure - * legacy vga therefore we don't worry about mmio etc. - * This stuff should really go into vgaHW.c. However then - * the driver would have to load the vga-module prior to - * doing int10. - */ -void -LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) -{ - vga->save_msr = inb(pInt->ioBase + 0x03CC); - vga->save_vse = inb(pInt->ioBase + 0x03C3); -#ifndef __ia64__ - vga->save_46e8 = inb(pInt->ioBase + 0x46E8); -#endif - vga->save_pos102 = inb(pInt->ioBase + 0x0102); - outb(pInt->ioBase + 0x03C2, ~(CARD8)0x03 & vga->save_msr); - outb(pInt->ioBase + 0x03C3, ~(CARD8)0x01 & vga->save_vse); -#ifndef __ia64__ - outb(pInt->ioBase + 0x46E8, ~(CARD8)0x08 & vga->save_46e8); -#endif - outb(pInt->ioBase + 0x0102, ~(CARD8)0x01 & vga->save_pos102); -} - -void -UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) -{ - outb(pInt->ioBase + 0x0102, vga->save_pos102); -#ifndef __ia64__ - outb(pInt->ioBase + 0x46E8, vga->save_46e8); -#endif - outb(pInt->ioBase + 0x03C3, vga->save_vse); - outb(pInt->ioBase + 0x03C2, vga->save_msr); -} - -#if defined (_PC) -static void -SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set) -{ - int pagesize = getpagesize(); - unsigned char* base = xf86MapVidMem(pInt->scrnIndex, - VIDMEM_MMIO, 0, pagesize); - int i; - - if (set) { - for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) - MEM_WW(pInt, i, *(base + i)); - } else { - for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) - *(base + i) = MEM_RW(pInt, i); - } - - xf86UnMapVidMem(pInt->scrnIndex,base,pagesize); -} - -void -xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save) -{ - int pagesize = getpagesize(); - unsigned char* base; - int i; - - if (!xf86IsEntityPrimary(pInt->entityIndex) - || (!save && !pInt->BIOSScratch)) - return; - - base = xf86MapVidMem(pInt->scrnIndex, VIDMEM_MMIO, 0, pagesize); - base += BIOS_SCRATCH_OFF; - if (save) { - if ((pInt->BIOSScratch - = xnfalloc(BIOS_SCRATCH_LEN))) - for (i = 0; i < BIOS_SCRATCH_LEN; i++) - *(((char*)pInt->BIOSScratch + i)) = *(base + i); - } else { - if (pInt->BIOSScratch) { - for (i = 0; i < BIOS_SCRATCH_LEN; i++) - *(base + i) = *(pInt->BIOSScratch + i); - xfree(pInt->BIOSScratch); - pInt->BIOSScratch = NULL; - } - } - - xf86UnMapVidMem(pInt->scrnIndex,base - BIOS_SCRATCH_OFF ,pagesize); -} -#endif - -xf86Int10InfoPtr -xf86InitInt10(int entityIndex) -{ - return xf86ExtendedInitInt10(entityIndex, 0); -} +/* + * XFree86 int10 module + * execute BIOS int 10h calls in x86 real mode environment + * Copyright 1999 Egbert Eich + * + * Part of this code was inspired by the VBIOS POSTing code in DOSEMU + * developed by the "DOSEMU-Development-Team" + */ + +/* + * To debug port accesses define PRINT_PORT to 1. + * Note! You also have to comment out ioperm() + * in xf86EnableIO(). Otherwise we won't trap + * on PIO. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#define PRINT_PORT 0 + +#include + +#include +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" +#define _INT10_PRIVATE +#include "int10Defines.h" +#include "xf86int10.h" +#include "Pci.h" +#ifdef _X86EMU +#include "x86emu/x86emui.h" +#else +#define DEBUG_IO_TRACE() 0 +#endif +#include + +static int pciCfg1in(CARD16 addr, CARD32 *val); +static int pciCfg1out(CARD16 addr, CARD32 val); +static int pciCfg1inw(CARD16 addr, CARD16 *val); +static int pciCfg1outw(CARD16 addr, CARD16 val); +static int pciCfg1inb(CARD16 addr, CARD8 *val); +static int pciCfg1outb(CARD16 addr, CARD8 val); +#if defined (_PC) +static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set); +#endif + +#define REG pInt + +int +setup_int(xf86Int10InfoPtr pInt) +{ + if (pInt != Int10Current) { + if (!MapCurrentInt10(pInt)) + return -1; + Int10Current = pInt; + } + X86_EAX = (CARD32) pInt->ax; + X86_EBX = (CARD32) pInt->bx; + X86_ECX = (CARD32) pInt->cx; + X86_EDX = (CARD32) pInt->dx; + X86_ESI = (CARD32) pInt->si; + X86_EDI = (CARD32) pInt->di; + X86_EBP = (CARD32) pInt->bp; + X86_ESP = 0x1000; X86_SS = pInt->stackseg >> 4; + X86_EIP = 0x0600; X86_CS = 0x0; /* address of 'hlt' */ + X86_DS = 0x40; /* standard pc ds */ + X86_ES = pInt->es; + X86_FS = 0; + X86_GS = 0; + X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK; +#if defined (_PC) + if (pInt->Flags & SET_BIOS_SCRATCH) + SetResetBIOSVars(pInt, TRUE); +#endif + return xf86BlockSIGIO(); +} + +void +finish_int(xf86Int10InfoPtr pInt, int sig) +{ + xf86UnblockSIGIO(sig); + pInt->ax = (CARD32) X86_EAX; + pInt->bx = (CARD32) X86_EBX; + pInt->cx = (CARD32) X86_ECX; + pInt->dx = (CARD32) X86_EDX; + pInt->si = (CARD32) X86_ESI; + pInt->di = (CARD32) X86_EDI; + pInt->es = (CARD16) X86_ES; + pInt->bp = (CARD32) X86_EBP; + pInt->flags = (CARD32) X86_FLAGS; +#if defined (_PC) + if (pInt->Flags & RESTORE_BIOS_SCRATCH) + SetResetBIOSVars(pInt, FALSE); +#endif +} + +/* general software interrupt handler */ +CARD32 +getIntVect(xf86Int10InfoPtr pInt,int num) +{ + return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4); +} + +void +pushw(xf86Int10InfoPtr pInt, CARD16 val) +{ + X86_ESP -= 2; + MEM_WW(pInt, ((CARD32) X86_SS << 4) + X86_SP, val); +} + +int +run_bios_int(int num, xf86Int10InfoPtr pInt) +{ + CARD32 eflags; +#ifndef _PC + /* check if bios vector is initialized */ + if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ?*/ + + if (num == 21 && X86_AH == 0x4e) { + xf86DrvMsg(pInt->scrnIndex, X_NOTICE, + "Failing Find-Matching-File on non-PC" + " (int 21, func 4e)\n"); + X86_AX = 2; + SET_FLAG(F_CF); + return 1; + } else { + xf86DrvMsgVerb(pInt->scrnIndex, X_NOT_IMPLEMENTED, 2, + "Ignoring int 0x%02x call\n", num); + if (xf86GetVerbosity() > 3) { + dump_registers(pInt); + stack_trace(pInt); + } + return 1; + } + } +#endif +#ifdef PRINT_INT + ErrorF("calling card BIOS at: "); +#endif + eflags = X86_EFLAGS; +#if 0 + eflags = eflags | IF_MASK; + X86_EFLAGS = X86_EFLAGS & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK); +#endif + pushw(pInt, eflags); + pushw(pInt, X86_CS); + pushw(pInt, X86_IP); + X86_CS = MEM_RW(pInt, (num << 2) + 2); + X86_IP = MEM_RW(pInt, num << 2); +#ifdef PRINT_INT + ErrorF("0x%x:%lx\n", X86_CS, X86_EIP); +#endif + return 1; +} + +/* Debugging stuff */ +void +dump_code(xf86Int10InfoPtr pInt) +{ + int i; + unsigned long lina = SEG_ADR((CARD32), X86_CS, IP); + + xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, "code at 0x%8.8lx:\n", lina); + for (i=0; i<0x10; i++) + xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); + xf86ErrorFVerb(3, "\n"); + for (; i<0x20; i++) + xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i)); + xf86ErrorFVerb(3, "\n"); +} + +void +dump_registers(xf86Int10InfoPtr pInt) +{ + xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, + "EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n", + (unsigned long)X86_EAX, (unsigned long)X86_EBX, + (unsigned long)X86_ECX, (unsigned long)X86_EDX); + xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, + "ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n", + (unsigned long)X86_ESP, (unsigned long)X86_EBP, + (unsigned long)X86_ESI, (unsigned long)X86_EDI); + xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, + "CS=0x%4.4x, SS=0x%4.4x," + " DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n", + X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS); + xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, + "EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n", + (unsigned long)X86_EIP, (unsigned long)X86_EFLAGS); +} + +void +stack_trace(xf86Int10InfoPtr pInt) +{ + int i = 0; + unsigned long stack = SEG_ADR((CARD32), X86_SS, SP); + unsigned long tail = (CARD32)((X86_SS << 4) + 0x1000); + + if (stack >= tail) return; + + xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack); + for (; stack < tail; stack++) { + xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack)); + i = (i + 1) % 0x10; + if (!i) + xf86ErrorFVerb(3, "\n"); + } + if (i) + xf86ErrorFVerb(3, "\n"); +} + +int +port_rep_inb(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count) +{ + register int inc = d_f ? -1 : 1; + CARD32 dst = base; + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" rep_insb(%#x) %ld bytes at %8.8lx %s\n", + port, count, base, d_f ? "up" : "down"); + while (count--) { + MEM_WB(pInt, dst, x_inb(port)); + dst += inc; + } + return dst - base; +} + +int +port_rep_inw(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count) +{ + register int inc = d_f ? -2 : 2; + CARD32 dst = base; + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" rep_insw(%#x) %ld bytes at %8.8lx %s\n", + port, count, base, d_f ? "up" : "down"); + while (count--) { + MEM_WW(pInt, dst, x_inw(port)); + dst += inc; + } + return dst - base; +} + +int +port_rep_inl(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count) +{ + register int inc = d_f ? -4 : 4; + CARD32 dst = base; + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" rep_insl(%#x) %ld bytes at %8.8lx %s\n", + port, count, base, d_f ? "up" : "down"); + while (count--) { + MEM_WL(pInt, dst, x_inl(port)); + dst += inc; + } + return dst - base; +} + +int +port_rep_outb(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count) +{ + register int inc = d_f ? -1 : 1; + CARD32 dst = base; + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" rep_outb(%#x) %ld bytes at %8.8lx %s\n", + port, count, base, d_f ? "up" : "down"); + while (count--) { + x_outb(port, MEM_RB(pInt, dst)); + dst += inc; + } + return dst - base; +} + +int +port_rep_outw(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count) +{ + register int inc = d_f ? -2 : 2; + CARD32 dst = base; + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" rep_outw(%#x) %ld bytes at %8.8lx %s\n", + port, count, base, d_f ? "up" : "down"); + while (count--) { + x_outw(port, MEM_RW(pInt, dst)); + dst += inc; + } + return dst - base; +} + +int +port_rep_outl(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count) +{ + register int inc = d_f ? -4 : 4; + CARD32 dst = base; + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" rep_outl(%#x) %ld bytes at %8.8lx %s\n", + port, count, base, d_f ? "up" : "down"); + while (count--) { + x_outl(port, MEM_RL(pInt, dst)); + dst += inc; + } + return dst - base; +} + +CARD8 +x_inb(CARD16 port) +{ + CARD8 val; + + if (port == 0x40) { + Int10Current->inb40time++; + val = (CARD8)(Int10Current->inb40time >> + ((Int10Current->inb40time & 1) << 3)); + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" inb(%#x) = %2.2x\n", port, val); +#ifdef __NOT_YET__ + } else if (port < 0x0100) { /* Don't interfere with mainboard */ + val = 0; + xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2, + "inb 0x%4.4x\n", port); + if (xf86GetVerbosity() > 3) { + dump_registers(Int10Current); + stack_trace(Int10Current); + } +#endif /* __NOT_YET__ */ + } else if (!pciCfg1inb(port, &val)) { + val = inb(Int10Current->ioBase + port); + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" inb(%#x) = %2.2x\n", port, val); + } + return val; +} + +CARD16 +x_inw(CARD16 port) +{ + CARD16 val; + + if (port == 0x5c) { + struct timeval tv; + + /* + * Emulate a PC98's timer. Typical resolution is 3.26 usec. + * Approximate this by dividing by 3. + */ + X_GETTIMEOFDAY(&tv); + val = (CARD16)(tv.tv_usec / 3); + } else if (!pciCfg1inw(port, &val)) { + val = inw(Int10Current->ioBase + port); + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" inw(%#x) = %4.4x\n", port, val); + } + return val; +} + +void +x_outb(CARD16 port, CARD8 val) +{ + if ((port == 0x43) && (val == 0)) { + struct timeval tv; + /* + * Emulate a PC's timer 0. Such timers typically have a resolution of + * some .838 usec per tick, but this can only provide 1 usec per tick. + * (Not that this matters much, given inherent emulation delays.) Use + * the bottom bit as a byte select. See inb(0x40) above. + */ + X_GETTIMEOFDAY(&tv); + Int10Current->inb40time = (CARD16)(tv.tv_usec | 1); + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" outb(%#x, %2.2x)\n", port, val); +#ifdef __NOT_YET__ + } else if (port < 0x0100) { /* Don't interfere with mainboard */ + xf86DrvMsgVerb(Int10Current->scrnIndex, X_NOT_IMPLEMENTED, 2, + "outb 0x%4.4x,0x%2.2x\n", port, val); + if (xf86GetVerbosity() > 3) { + dump_registers(Int10Current); + stack_trace(Int10Current); + } +#endif /* __NOT_YET__ */ + } else if (!pciCfg1outb(port, val)) { + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" outb(%#x, %2.2x)\n", port, val); + outb(Int10Current->ioBase + port, val); + } +} + +void +x_outw(CARD16 port, CARD16 val) +{ + + if (!pciCfg1outw(port, val)) { + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" outw(%#x, %4.4x)\n", port, val); + outw(Int10Current->ioBase + port, val); + } +} + +CARD32 +x_inl(CARD16 port) +{ + CARD32 val; + + if (!pciCfg1in(port, &val)) { + val = inl(Int10Current->ioBase + port); + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" inl(%#x) = %8.8lx\n", port, val); + } + return val; +} + +void +x_outl(CARD16 port, CARD32 val) +{ + if (!pciCfg1out(port, val)) { + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" outl(%#x, %8.8lx)\n", port, val); + outl(Int10Current->ioBase + port, val); + } +} + +CARD8 +Mem_rb(CARD32 addr) +{ + return (*Int10Current->mem->rb)(Int10Current, addr); +} + +CARD16 +Mem_rw(CARD32 addr) +{ + return (*Int10Current->mem->rw)(Int10Current, addr); +} + +CARD32 +Mem_rl(CARD32 addr) +{ + return (*Int10Current->mem->rl)(Int10Current, addr); +} + +void +Mem_wb(CARD32 addr, CARD8 val) +{ + (*Int10Current->mem->wb)(Int10Current, addr, val); +} + +void +Mem_ww(CARD32 addr, CARD16 val) +{ + (*Int10Current->mem->ww)(Int10Current, addr, val); +} + +void +Mem_wl(CARD32 addr, CARD32 val) +{ + (*Int10Current->mem->wl)(Int10Current, addr, val); +} + +static CARD32 PciCfg1Addr = 0; + +#define PCI_OFFSET(x) ((x) & 0x000000ff) +#define PCI_TAG(x) ((x) & 0x7fffff00) + +static struct pci_device* +pci_device_for_cfg_address (CARD32 addr) +{ + struct pci_device *dev = NULL; + PCITAG tag = PCI_TAG(addr); + struct pci_slot_match slot_match = { + .domain = PCI_DOM_FROM_TAG(tag), + .bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)), + .dev = PCI_DEV_FROM_TAG(tag), + .func = PCI_FUNC_FROM_TAG(tag), + .match_data = 0 + }; + + struct pci_device_iterator *iter = + pci_slot_match_iterator_create (&slot_match); + + if (iter) + dev = pci_device_next(iter); + + pci_iterator_destroy(iter); + + return dev; +} + +static int +pciCfg1in(CARD16 addr, CARD32 *val) +{ + if (addr == 0xCF8) { + *val = PciCfg1Addr; + return 1; + } + if (addr == 0xCFC) { + pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr), + val, PCI_OFFSET(PciCfg1Addr)); + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" cfg_inl(%#lx) = %8.8lx\n", PciCfg1Addr, *val); + return 1; + } + return 0; +} + +static int +pciCfg1out(CARD16 addr, CARD32 val) +{ + if (addr == 0xCF8) { + PciCfg1Addr = val; + return 1; + } + if (addr == 0xCFC) { + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" cfg_outl(%#lx, %8.8lx)\n", PciCfg1Addr, val); + pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr), + val, PCI_OFFSET(PciCfg1Addr)); + return 1; + } + return 0; +} + +static int +pciCfg1inw(CARD16 addr, CARD16 *val) +{ + int shift; + + if ((addr >= 0xCF8) && (addr <= 0xCFB)) { + shift = (addr - 0xCF8) * 8; + *val = (PciCfg1Addr >> shift) & 0xffff; + return 1; + } + if ((addr >= 0xCFC) && (addr <= 0xCFF)) { + const unsigned offset = addr - 0xCFC; + + pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr), + val, PCI_OFFSET(PciCfg1Addr) + offset); + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" cfg_inw(%#lx) = %4.4x\n", PciCfg1Addr + offset, *val); + return 1; + } + return 0; +} + +static int +pciCfg1outw(CARD16 addr, CARD16 val) +{ + int shift; + + if ((addr >= 0xCF8) && (addr <= 0xCFB)) { + shift = (addr - 0xCF8) * 8; + PciCfg1Addr &= ~(0xffff << shift); + PciCfg1Addr |= ((CARD32) val) << shift; + return 1; + } + if ((addr >= 0xCFC) && (addr <= 0xCFF)) { + const unsigned offset = addr - 0xCFC; + + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" cfg_outw(%#lx, %4.4x)\n", PciCfg1Addr + offset, val); + pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr), + val, PCI_OFFSET(PciCfg1Addr) + offset); + return 1; + } + return 0; +} + +static int +pciCfg1inb(CARD16 addr, CARD8 *val) +{ + int shift; + + if ((addr >= 0xCF8) && (addr <= 0xCFB)) { + shift = (addr - 0xCF8) * 8; + *val = (PciCfg1Addr >> shift) & 0xff; + return 1; + } + if ((addr >= 0xCFC) && (addr <= 0xCFF)) { + const unsigned offset = addr - 0xCFC; + + pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr), + val, PCI_OFFSET(PciCfg1Addr) + offset); + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" cfg_inb(%#lx) = %2.2x\n", PciCfg1Addr + offset, *val); + return 1; + } + return 0; +} + +static int +pciCfg1outb(CARD16 addr, CARD8 val) +{ + int shift; + + if ((addr >= 0xCF8) && (addr <= 0xCFB)) { + shift = (addr - 0xCF8) * 8; + PciCfg1Addr &= ~(0xff << shift); + PciCfg1Addr |= ((CARD32) val) << shift; + return 1; + } + if ((addr >= 0xCFC) && (addr <= 0xCFF)) { + const unsigned offset = addr - 0xCFC; + + if (PRINT_PORT && DEBUG_IO_TRACE()) + ErrorF(" cfg_outb(%#lx, %2.2x)\n", PciCfg1Addr + offset, val); + pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr), + val, PCI_OFFSET(PciCfg1Addr) + offset); + return 1; + } + return 0; +} + +CARD8 +bios_checksum(const CARD8 *start, int size) +{ + CARD8 sum = 0; + + while (size-- > 0) + sum += *start++; + return sum; +} + +/* + * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make + * an attempt to detect a legacy ISA card. If they find one they might + * act very strange: for example they might configure the card as a + * monochrome card. This might cause some drivers to choke. + * To avoid this we attempt legacy VGA by writing to all know VGA + * disable registers before we call the BIOS initialization and + * restore the original values afterwards. In beween we hold our + * breath. To get to a (possibly exising) ISA card need to disable + * our current PCI card. + */ +/* + * This is just for booting: we just want to catch pure + * legacy vga therefore we don't worry about mmio etc. + * This stuff should really go into vgaHW.c. However then + * the driver would have to load the vga-module prior to + * doing int10. + */ +void +LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) +{ + vga->save_msr = inb(pInt->ioBase + 0x03CC); + vga->save_vse = inb(pInt->ioBase + 0x03C3); +#ifndef __ia64__ + vga->save_46e8 = inb(pInt->ioBase + 0x46E8); +#endif + vga->save_pos102 = inb(pInt->ioBase + 0x0102); + outb(pInt->ioBase + 0x03C2, ~(CARD8)0x03 & vga->save_msr); + outb(pInt->ioBase + 0x03C3, ~(CARD8)0x01 & vga->save_vse); +#ifndef __ia64__ + outb(pInt->ioBase + 0x46E8, ~(CARD8)0x08 & vga->save_46e8); +#endif + outb(pInt->ioBase + 0x0102, ~(CARD8)0x01 & vga->save_pos102); +} + +void +UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga) +{ + outb(pInt->ioBase + 0x0102, vga->save_pos102); +#ifndef __ia64__ + outb(pInt->ioBase + 0x46E8, vga->save_46e8); +#endif + outb(pInt->ioBase + 0x03C3, vga->save_vse); + outb(pInt->ioBase + 0x03C2, vga->save_msr); +} + +#if defined (_PC) +static void +SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set) +{ + int pagesize = getpagesize(); + unsigned char* base = xf86MapVidMem(pInt->scrnIndex, + VIDMEM_MMIO, 0, pagesize); + int i; + + if (set) { + for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) + MEM_WW(pInt, i, *(base + i)); + } else { + for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++) + *(base + i) = MEM_RW(pInt, i); + } + + xf86UnMapVidMem(pInt->scrnIndex,base,pagesize); +} + +void +xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save) +{ + int pagesize = getpagesize(); + unsigned char* base; + int i; + + if (!xf86IsEntityPrimary(pInt->entityIndex) + || (!save && !pInt->BIOSScratch)) + return; + + base = xf86MapVidMem(pInt->scrnIndex, VIDMEM_MMIO, 0, pagesize); + base += BIOS_SCRATCH_OFF; + if (save) { + if ((pInt->BIOSScratch + = xnfalloc(BIOS_SCRATCH_LEN))) + for (i = 0; i < BIOS_SCRATCH_LEN; i++) + *(((char*)pInt->BIOSScratch + i)) = *(base + i); + } else { + if (pInt->BIOSScratch) { + for (i = 0; i < BIOS_SCRATCH_LEN; i++) + *(base + i) = *(pInt->BIOSScratch + i); + free(pInt->BIOSScratch); + pInt->BIOSScratch = NULL; + } + } + + xf86UnMapVidMem(pInt->scrnIndex,base - BIOS_SCRATCH_OFF ,pagesize); +} +#endif + +xf86Int10InfoPtr +xf86InitInt10(int entityIndex) +{ + return xf86ExtendedInitInt10(entityIndex, 0); +} diff --git a/xorg-server/hw/xfree86/int10/helper_mem.c b/xorg-server/hw/xfree86/int10/helper_mem.c index 6f6ecc2b3..b95b56a93 100644 --- a/xorg-server/hw/xfree86/int10/helper_mem.c +++ b/xorg-server/hw/xfree86/int10/helper_mem.c @@ -1,330 +1,330 @@ -/* - * XFree86 int10 module - * execute BIOS int 10h calls in x86 real mode environment - * Copyright 1999 Egbert Eich - */ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include - -#include "xf86.h" -#include "xf86_OSproc.h" -#include "compiler.h" -#include "xf86Pci.h" -#define _INT10_PRIVATE -#if 0 -#include "int10Defines.h" -#endif -#include "xf86int10.h" - -#define REG pInt - -typedef enum { - OPT_NOINT10, - OPT_INIT_PRIMARY, -} INT10Opts; - -static const OptionInfoRec INT10Options[] = { - {OPT_NOINT10, "NoINT10", OPTV_BOOLEAN, {0}, FALSE }, - {OPT_INIT_PRIMARY, "InitPrimary", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -#ifdef DEBUG -void -dprint(unsigned long start, unsigned long size) -{ - int i,j; - char *c = (char *)start; - - for (j = 0; j < (size >> 4); j++) { - char *d = c; - ErrorF("\n0x%lx: ",(unsigned long)c); - for (i = 0; i<16; i++) - ErrorF("%2.2x ",(unsigned char) (*(c++))); - c = d; - for (i = 0; i<16; i++) { - ErrorF("%c",((((CARD8)(*c)) > 32) && (((CARD8)(*c)) < 128)) ? - (unsigned char) (*(c)): '.'); - c++; - } - } - ErrorF("\n"); -} -#endif - -#ifndef _PC -/* - * here we are really paranoid about faking a "real" - * BIOS. Most of this information was pulled from - * dosemu. - */ -void -setup_int_vect(xf86Int10InfoPtr pInt) -{ - int i; - - /* let the int vects point to the SYS_BIOS seg */ - for (i = 0; i < 0x80; i++) { - MEM_WW(pInt, i << 2, 0); - MEM_WW(pInt, (i << 2) + 2, SYS_BIOS >> 4); - } - - reset_int_vect(pInt); - /* font tables default location (int 1F) */ - MEM_WW(pInt,0x1f<<2,0xfa6e); - - /* int 11 default location (Get Equipment Configuration) */ - MEM_WW(pInt, 0x11 << 2, 0xf84d); - /* int 12 default location (Get Conventional Memory Size) */ - MEM_WW(pInt, 0x12 << 2, 0xf841); - /* int 15 default location (I/O System Extensions) */ - MEM_WW(pInt, 0x15 << 2, 0xf859); - /* int 1A default location (RTC, PCI and others) */ - MEM_WW(pInt, 0x1a << 2, 0xff6e); - /* int 05 default location (Bound Exceeded) */ - MEM_WW(pInt, 0x05 << 2, 0xff54); - /* int 08 default location (Double Fault) */ - MEM_WW(pInt, 0x08 << 2, 0xfea5); - /* int 13 default location (Disk) */ - MEM_WW(pInt, 0x13 << 2, 0xec59); - /* int 0E default location (Page Fault) */ - MEM_WW(pInt, 0x0e << 2, 0xef57); - /* int 17 default location (Parallel Port) */ - MEM_WW(pInt, 0x17 << 2, 0xefd2); - /* fdd table default location (int 1e) */ - MEM_WW(pInt, 0x1e << 2, 0xefc7); - - /* Set Equipment flag to VGA */ - i = MEM_RB(pInt, 0x0410) & 0xCF; - MEM_WB(pInt, 0x0410, i); - /* XXX Perhaps setup more of the BDA here. See also int42(0x00). */ -} -#endif - -int -setup_system_bios(void *base_addr) -{ - char *base = (char *) base_addr; - - /* - * we trap the "industry standard entry points" to the BIOS - * and all other locations by filling them with "hlt" - * TODO: implement hlt-handler for these - */ - memset(base, 0xf4, 0x10000); - - /* set bios date */ - strcpy(base + 0x0FFF5, "06/11/99"); - /* set up eisa ident string */ - strcpy(base + 0x0FFD9, "PCI_ISA"); - /* write system model id for IBM-AT */ - *((unsigned char *)(base + 0x0FFFE)) = 0xfc; - - return 1; -} - -void -reset_int_vect(xf86Int10InfoPtr pInt) -{ - /* - * This table is normally located at 0xF000:0xF0A4. However, int 0x42, - * function 0 (Mode Set) expects it (or a copy) somewhere in the bottom - * 64kB. Note that because this data doesn't survive POST, int 0x42 should - * only be used during EGA/VGA BIOS initialisation. - */ - static const CARD8 VideoParms[] = { - /* Timing for modes 0x00 & 0x01 */ - 0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c, - 0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, - /* Timing for modes 0x02 & 0x03 */ - 0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c, - 0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, - /* Timing for modes 0x04, 0x05 & 0x06 */ - 0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70, - 0x02, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, - /* Timing for mode 0x07 */ - 0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19, - 0x02, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, - /* Display page lengths in little endian order */ - 0x00, 0x08, /* Modes 0x00 and 0x01 */ - 0x00, 0x10, /* Modes 0x02 and 0x03 */ - 0x00, 0x40, /* Modes 0x04 and 0x05 */ - 0x00, 0x40, /* Modes 0x06 and 0x07 */ - /* Number of columns for each mode */ - 40, 40, 80, 80, 40, 40, 80, 80, - /* CGA Mode register value for each mode */ - 0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29, - /* Padding */ - 0x00, 0x00, 0x00, 0x00 - }; - int i; - - for (i = 0; i < sizeof(VideoParms); i++) - MEM_WB(pInt, i + (0x1000 - sizeof(VideoParms)), VideoParms[i]); - MEM_WW(pInt, 0x1d << 2, 0x1000 - sizeof(VideoParms)); - MEM_WW(pInt, (0x1d << 2) + 2, 0); - - MEM_WW(pInt, 0x10 << 2, 0xf065); - MEM_WW(pInt, (0x10 << 2) + 2, SYS_BIOS >> 4); - MEM_WW(pInt, 0x42 << 2, 0xf065); - MEM_WW(pInt, (0x42 << 2) + 2, SYS_BIOS >> 4); - MEM_WW(pInt, 0x6D << 2, 0xf065); - MEM_WW(pInt, (0x6D << 2) + 2, SYS_BIOS >> 4); -} - -void -set_return_trap(xf86Int10InfoPtr pInt) -{ - /* - * Here we set the exit condition: We return when we encounter - * 'hlt' (=0xf4), which we locate at address 0x600 in x86 memory. - */ - MEM_WB(pInt, 0x0600, 0xf4); - - /* - * Allocate a segment for the stack - */ - xf86Int10AllocPages(pInt, 1, &pInt->stackseg); -} - -void * -xf86HandleInt10Options(ScrnInfoPtr pScrn, int entityIndex) -{ - EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); - OptionInfoPtr options = NULL; - - if (pEnt->device) { - pointer configOptions = NULL; - - /* Check if xf86CollectOptions() has already been called */ - if (((pEnt->index < 0) || - !pScrn || - !(configOptions = pScrn->options)) && - pEnt->device) - configOptions = pEnt->device->options; - - if (configOptions) { - if (!(options = (OptionInfoPtr) xalloc(sizeof(INT10Options)))) - return NULL; - - (void)memcpy(options, INT10Options, sizeof(INT10Options)); - xf86ProcessOptions(pScrn->scrnIndex, configOptions, options); - } - } - xfree(pEnt); - - return options; -} - -Bool -int10skip(const void* options) -{ - Bool noint10 = FALSE; - - if (!options) return FALSE; - - xf86GetOptValBool(options, OPT_NOINT10, &noint10); - return noint10; -} - -Bool -int10_check_bios(int scrnIndex, int codeSeg, const unsigned char* vbiosMem) -{ - int size; - - if ((codeSeg & 0x1f) || /* Not 512-byte aligned otherwise */ - ((codeSeg << 4) < V_BIOS) || - ((codeSeg << 4) >= SYS_SIZE)) - return FALSE; - - if (xf86IsPc98()) - return FALSE; - - if ((*vbiosMem != 0x55) || (*(vbiosMem+1) != 0xAA) || !*(vbiosMem+2)) - return FALSE; - - size = *(vbiosMem + 2) * 512; - - if ((size + (codeSeg << 4)) > SYS_SIZE) - return FALSE; - - if (bios_checksum(vbiosMem, size)) - xf86DrvMsg(scrnIndex, X_INFO, "Bad V_BIOS checksum\n"); - - return TRUE; -} - -Bool -initPrimary(const void* options) -{ - Bool initPrimary = FALSE; - - if (!options) return FALSE; - - xf86GetOptValBool(options, OPT_INIT_PRIMARY, &initPrimary); - return initPrimary; -} - -BusType -xf86int10GetBiosLocationType(const xf86Int10InfoPtr pInt) -{ - BusType location_type; - - EntityInfoPtr pEnt = xf86GetEntityInfo(pInt->entityIndex); - location_type = pEnt->location.type; - xfree(pEnt); - - return location_type; -} - - -#define CHECK_V_SEGMENT_RANGE(x) \ - if (((x) << 4) < V_BIOS) { \ - xf86DrvMsg(pInt->scrnIndex, X_ERROR, \ - "V_BIOS address 0x%lx out of range\n", \ - (unsigned long)(x) << 4); \ - return FALSE; \ - } - -Bool -xf86int10GetBiosSegment(xf86Int10InfoPtr pInt, void *base) -{ - unsigned i; - int cs = ~0; - int segments[4]; - const char * format; - - segments[0] = MEM_RW(pInt, (0x10 << 2) + 2); - segments[1] = MEM_RW(pInt, (0x42 << 2) + 2); - segments[2] = V_BIOS >> 4; - segments[3] = ~0; - - format = "No V_BIOS found\n"; - - for (i = 0; segments[i] != ~0; i++) { - unsigned char * vbiosMem; - - cs = segments[i]; - - CHECK_V_SEGMENT_RANGE(cs); - vbiosMem = (unsigned char *)base + (cs << 4); - if (int10_check_bios(pInt->scrnIndex, cs, vbiosMem)) { - break; - } - } - - if (segments[i] == ~0) { - xf86DrvMsg(pInt->scrnIndex, X_ERROR, format, (unsigned long)cs << 4); - return FALSE; - } - - xf86DrvMsg(pInt->scrnIndex, X_INFO, "Primary V_BIOS segment is: 0x%lx\n", - (unsigned long)cs); - - pInt->BIOSseg = cs; - return TRUE; -} +/* + * XFree86 int10 module + * execute BIOS int 10h calls in x86 real mode environment + * Copyright 1999 Egbert Eich + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" +#include "xf86Pci.h" +#define _INT10_PRIVATE +#if 0 +#include "int10Defines.h" +#endif +#include "xf86int10.h" + +#define REG pInt + +typedef enum { + OPT_NOINT10, + OPT_INIT_PRIMARY, +} INT10Opts; + +static const OptionInfoRec INT10Options[] = { + {OPT_NOINT10, "NoINT10", OPTV_BOOLEAN, {0}, FALSE }, + {OPT_INIT_PRIMARY, "InitPrimary", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +#ifdef DEBUG +void +dprint(unsigned long start, unsigned long size) +{ + int i,j; + char *c = (char *)start; + + for (j = 0; j < (size >> 4); j++) { + char *d = c; + ErrorF("\n0x%lx: ",(unsigned long)c); + for (i = 0; i<16; i++) + ErrorF("%2.2x ",(unsigned char) (*(c++))); + c = d; + for (i = 0; i<16; i++) { + ErrorF("%c",((((CARD8)(*c)) > 32) && (((CARD8)(*c)) < 128)) ? + (unsigned char) (*(c)): '.'); + c++; + } + } + ErrorF("\n"); +} +#endif + +#ifndef _PC +/* + * here we are really paranoid about faking a "real" + * BIOS. Most of this information was pulled from + * dosemu. + */ +void +setup_int_vect(xf86Int10InfoPtr pInt) +{ + int i; + + /* let the int vects point to the SYS_BIOS seg */ + for (i = 0; i < 0x80; i++) { + MEM_WW(pInt, i << 2, 0); + MEM_WW(pInt, (i << 2) + 2, SYS_BIOS >> 4); + } + + reset_int_vect(pInt); + /* font tables default location (int 1F) */ + MEM_WW(pInt,0x1f<<2,0xfa6e); + + /* int 11 default location (Get Equipment Configuration) */ + MEM_WW(pInt, 0x11 << 2, 0xf84d); + /* int 12 default location (Get Conventional Memory Size) */ + MEM_WW(pInt, 0x12 << 2, 0xf841); + /* int 15 default location (I/O System Extensions) */ + MEM_WW(pInt, 0x15 << 2, 0xf859); + /* int 1A default location (RTC, PCI and others) */ + MEM_WW(pInt, 0x1a << 2, 0xff6e); + /* int 05 default location (Bound Exceeded) */ + MEM_WW(pInt, 0x05 << 2, 0xff54); + /* int 08 default location (Double Fault) */ + MEM_WW(pInt, 0x08 << 2, 0xfea5); + /* int 13 default location (Disk) */ + MEM_WW(pInt, 0x13 << 2, 0xec59); + /* int 0E default location (Page Fault) */ + MEM_WW(pInt, 0x0e << 2, 0xef57); + /* int 17 default location (Parallel Port) */ + MEM_WW(pInt, 0x17 << 2, 0xefd2); + /* fdd table default location (int 1e) */ + MEM_WW(pInt, 0x1e << 2, 0xefc7); + + /* Set Equipment flag to VGA */ + i = MEM_RB(pInt, 0x0410) & 0xCF; + MEM_WB(pInt, 0x0410, i); + /* XXX Perhaps setup more of the BDA here. See also int42(0x00). */ +} +#endif + +int +setup_system_bios(void *base_addr) +{ + char *base = (char *) base_addr; + + /* + * we trap the "industry standard entry points" to the BIOS + * and all other locations by filling them with "hlt" + * TODO: implement hlt-handler for these + */ + memset(base, 0xf4, 0x10000); + + /* set bios date */ + strcpy(base + 0x0FFF5, "06/11/99"); + /* set up eisa ident string */ + strcpy(base + 0x0FFD9, "PCI_ISA"); + /* write system model id for IBM-AT */ + *((unsigned char *)(base + 0x0FFFE)) = 0xfc; + + return 1; +} + +void +reset_int_vect(xf86Int10InfoPtr pInt) +{ + /* + * This table is normally located at 0xF000:0xF0A4. However, int 0x42, + * function 0 (Mode Set) expects it (or a copy) somewhere in the bottom + * 64kB. Note that because this data doesn't survive POST, int 0x42 should + * only be used during EGA/VGA BIOS initialisation. + */ + static const CARD8 VideoParms[] = { + /* Timing for modes 0x00 & 0x01 */ + 0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c, + 0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + /* Timing for modes 0x02 & 0x03 */ + 0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c, + 0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + /* Timing for modes 0x04, 0x05 & 0x06 */ + 0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70, + 0x02, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, + /* Timing for mode 0x07 */ + 0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19, + 0x02, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, + /* Display page lengths in little endian order */ + 0x00, 0x08, /* Modes 0x00 and 0x01 */ + 0x00, 0x10, /* Modes 0x02 and 0x03 */ + 0x00, 0x40, /* Modes 0x04 and 0x05 */ + 0x00, 0x40, /* Modes 0x06 and 0x07 */ + /* Number of columns for each mode */ + 40, 40, 80, 80, 40, 40, 80, 80, + /* CGA Mode register value for each mode */ + 0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29, + /* Padding */ + 0x00, 0x00, 0x00, 0x00 + }; + int i; + + for (i = 0; i < sizeof(VideoParms); i++) + MEM_WB(pInt, i + (0x1000 - sizeof(VideoParms)), VideoParms[i]); + MEM_WW(pInt, 0x1d << 2, 0x1000 - sizeof(VideoParms)); + MEM_WW(pInt, (0x1d << 2) + 2, 0); + + MEM_WW(pInt, 0x10 << 2, 0xf065); + MEM_WW(pInt, (0x10 << 2) + 2, SYS_BIOS >> 4); + MEM_WW(pInt, 0x42 << 2, 0xf065); + MEM_WW(pInt, (0x42 << 2) + 2, SYS_BIOS >> 4); + MEM_WW(pInt, 0x6D << 2, 0xf065); + MEM_WW(pInt, (0x6D << 2) + 2, SYS_BIOS >> 4); +} + +void +set_return_trap(xf86Int10InfoPtr pInt) +{ + /* + * Here we set the exit condition: We return when we encounter + * 'hlt' (=0xf4), which we locate at address 0x600 in x86 memory. + */ + MEM_WB(pInt, 0x0600, 0xf4); + + /* + * Allocate a segment for the stack + */ + xf86Int10AllocPages(pInt, 1, &pInt->stackseg); +} + +void * +xf86HandleInt10Options(ScrnInfoPtr pScrn, int entityIndex) +{ + EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex); + OptionInfoPtr options = NULL; + + if (pEnt->device) { + pointer configOptions = NULL; + + /* Check if xf86CollectOptions() has already been called */ + if (((pEnt->index < 0) || + !pScrn || + !(configOptions = pScrn->options)) && + pEnt->device) + configOptions = pEnt->device->options; + + if (configOptions) { + if (!(options = (OptionInfoPtr) malloc(sizeof(INT10Options)))) + return NULL; + + (void)memcpy(options, INT10Options, sizeof(INT10Options)); + xf86ProcessOptions(pScrn->scrnIndex, configOptions, options); + } + } + free(pEnt); + + return options; +} + +Bool +int10skip(const void* options) +{ + Bool noint10 = FALSE; + + if (!options) return FALSE; + + xf86GetOptValBool(options, OPT_NOINT10, &noint10); + return noint10; +} + +Bool +int10_check_bios(int scrnIndex, int codeSeg, const unsigned char* vbiosMem) +{ + int size; + + if ((codeSeg & 0x1f) || /* Not 512-byte aligned otherwise */ + ((codeSeg << 4) < V_BIOS) || + ((codeSeg << 4) >= SYS_SIZE)) + return FALSE; + + if (xf86IsPc98()) + return FALSE; + + if ((*vbiosMem != 0x55) || (*(vbiosMem+1) != 0xAA) || !*(vbiosMem+2)) + return FALSE; + + size = *(vbiosMem + 2) * 512; + + if ((size + (codeSeg << 4)) > SYS_SIZE) + return FALSE; + + if (bios_checksum(vbiosMem, size)) + xf86DrvMsg(scrnIndex, X_INFO, "Bad V_BIOS checksum\n"); + + return TRUE; +} + +Bool +initPrimary(const void* options) +{ + Bool initPrimary = FALSE; + + if (!options) return FALSE; + + xf86GetOptValBool(options, OPT_INIT_PRIMARY, &initPrimary); + return initPrimary; +} + +BusType +xf86int10GetBiosLocationType(const xf86Int10InfoPtr pInt) +{ + BusType location_type; + + EntityInfoPtr pEnt = xf86GetEntityInfo(pInt->entityIndex); + location_type = pEnt->location.type; + free(pEnt); + + return location_type; +} + + +#define CHECK_V_SEGMENT_RANGE(x) \ + if (((x) << 4) < V_BIOS) { \ + xf86DrvMsg(pInt->scrnIndex, X_ERROR, \ + "V_BIOS address 0x%lx out of range\n", \ + (unsigned long)(x) << 4); \ + return FALSE; \ + } + +Bool +xf86int10GetBiosSegment(xf86Int10InfoPtr pInt, void *base) +{ + unsigned i; + int cs = ~0; + int segments[4]; + const char * format; + + segments[0] = MEM_RW(pInt, (0x10 << 2) + 2); + segments[1] = MEM_RW(pInt, (0x42 << 2) + 2); + segments[2] = V_BIOS >> 4; + segments[3] = ~0; + + format = "No V_BIOS found\n"; + + for (i = 0; segments[i] != ~0; i++) { + unsigned char * vbiosMem; + + cs = segments[i]; + + CHECK_V_SEGMENT_RANGE(cs); + vbiosMem = (unsigned char *)base + (cs << 4); + if (int10_check_bios(pInt->scrnIndex, cs, vbiosMem)) { + break; + } + } + + if (segments[i] == ~0) { + xf86DrvMsg(pInt->scrnIndex, X_ERROR, format, (unsigned long)cs << 4); + return FALSE; + } + + xf86DrvMsg(pInt->scrnIndex, X_INFO, "Primary V_BIOS segment is: 0x%lx\n", + (unsigned long)cs); + + pInt->BIOSseg = cs; + return TRUE; +} diff --git a/xorg-server/hw/xfree86/loader/loadext.c b/xorg-server/hw/xfree86/loader/loadext.c index 29cdaf1ac..26066856d 100644 --- a/xorg-server/hw/xfree86/loader/loadext.c +++ b/xorg-server/hw/xfree86/loader/loadext.c @@ -1,442 +1,442 @@ -/* - * Copyright (c) 2000 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -/* Maybe this file belongs elsewhere? */ - -#define LOADERDECLARATIONS -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "loaderProcs.h" -#include "misc.h" -#include "xf86.h" - -/* - * This should be static, but miinitext wants it. FIXME: make extension - * initialization not completely terrible. - */ -ExtensionModule *ExtensionModuleList = NULL; -static int numExtensionModules = 0; - -static ExtensionModule * -NewExtensionModule(void) -{ - ExtensionModule *save = ExtensionModuleList; - int n; - - /* Sanity check */ - if (!ExtensionModuleList) - numExtensionModules = 0; - - n = numExtensionModules + 1; - ExtensionModuleList = xrealloc(ExtensionModuleList, - (n + 1) * sizeof(ExtensionModule)); - if (ExtensionModuleList == NULL) { - ExtensionModuleList = save; - return NULL; - } else { - numExtensionModules++; - ExtensionModuleList[numExtensionModules].name = NULL; - return ExtensionModuleList + (numExtensionModules - 1); - } -} - -void -LoadExtension(ExtensionModule * e, Bool builtin) -{ - ExtensionModule *newext; - - if (e == NULL || e->name == NULL) - return; - - if (!(newext = NewExtensionModule())) - return; - - if (builtin) - xf86MsgVerb(X_INFO, 2, "Initializing built-in extension %s\n", - e->name); - else - xf86MsgVerb(X_INFO, 2, "Loading extension %s\n", e->name); - - newext->name = e->name; - newext->initFunc = e->initFunc; - newext->disablePtr = e->disablePtr; - newext->setupFunc = e->setupFunc; - newext->initDependencies = e->initDependencies; - - if (e->setupFunc != NULL) - e->setupFunc(); -} - -/* - * Sort ExtensionModuleList according to the initialisation order - * dependencies. The code for this is taken from BSD's tsort, - * and carries the following copyright/license: - * - * - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Michael Rendell of Memorial University of Newfoundland. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#define NF_MARK 0x1 /* marker for cycle detection */ -#define NF_ACYCLIC 0x2 /* this node is cycle free */ -#define NF_NODEST 0x4 /* Unreachable */ - -typedef struct node_str NODE; -struct node_str { - NODE **n_prevp; /* pointer to previous node's n_next */ - NODE *n_next; /* next node in graph */ - NODE **n_arcs; /* array of arcs to other nodes */ - int n_narcs; /* number of arcs in n_arcs[] */ - int n_arcsize; /* size of n_arcs[] array */ - int n_refcnt; /* # of arcs pointing to this node */ - int n_flags; /* NF_* */ - const char *n_name; /* name of this node */ -}; - -static NODE *graph = NULL, **cycle_buf = NULL, **longest_cycle = NULL; -static int longest = 0; -static NODE *sorted = NULL, *last = NULL; - -/* Find a node in the graph (insert if not found) and return a pointer to it. */ -static NODE * -get_node(const char *name) -{ - NODE *n; - - for (n = graph; n && n->n_name && strcmp(n->n_name, name); - n = n->n_next) ; - if (n) - return (n); - - n = xnfalloc(sizeof(NODE)); - - n->n_narcs = 0; - n->n_arcsize = 0; - n->n_arcs = NULL; - n->n_refcnt = 0; - n->n_flags = 0; - n->n_name = name; - - /* Add to linked list. */ - if ((n->n_next = graph) != NULL) - graph->n_prevp = &n->n_next; - n->n_prevp = &graph; - graph = n; - - return (n); -} - -/* - * add an arc from node s1 to node s2 in the graph. If s1 or s2 are not in - * the graph, then add them. - */ -static void -add_arc(const char *s1, const char *s2) -{ - NODE *n1; - NODE *n2; - int bsize, i; - - n1 = get_node(s1); - - if (!strcmp(s1, s2)) - return; - - n2 = get_node(s2); - - /* - * Check if this arc is already here. - */ - for (i = 0; i < n1->n_narcs; i++) - if (n1->n_arcs[i] == n2) - return; - /* - * Add it. - */ - if (n1->n_narcs == n1->n_arcsize) { - if (!n1->n_arcsize) - n1->n_arcsize = 10; - bsize = n1->n_arcsize * sizeof(*n1->n_arcs) * 2; - n1->n_arcs = xnfrealloc(n1->n_arcs, bsize); - n1->n_arcsize = bsize / sizeof(*n1->n_arcs); - } - n1->n_arcs[n1->n_narcs++] = n2; - ++n2->n_refcnt; -} - -/* - * Clear the NODEST flag from all nodes. - */ -static void -clear_cycle(void) -{ - NODE *n; - - for (n = graph; n != NULL; n = n->n_next) - n->n_flags &= ~NF_NODEST; -} - -/* print node and remove from graph (does not actually free node) */ -static void -remove_node(NODE * n) -{ - NODE **np; - NODE *newnode; - int i; - -#ifdef DEBUG - ErrorF("%s\n", n->n_name); -#endif - newnode = xnfalloc(sizeof(NODE)); - memcpy(newnode, n, sizeof(NODE)); - if (last) - last->n_next = newnode; - else - sorted = newnode; - last = newnode; - newnode->n_next = NULL; - - for (np = n->n_arcs, i = n->n_narcs; --i >= 0; np++) - --(*np)->n_refcnt; - n->n_narcs = 0; - *n->n_prevp = n->n_next; - if (n->n_next) - n->n_next->n_prevp = n->n_prevp; -} - -static void -free_nodes(NODE * nodelist) -{ - NODE *n, *nextnode; - - for (n = nodelist; n;) { - nextnode = n->n_next; - xfree(n); - n = nextnode; - } -} - -/* look for the longest? cycle from node from to node to. */ -static int -find_cycle(NODE * from, NODE * to, int longest_len, int depth) -{ - NODE **np; - int i, len; - - /* - * avoid infinite loops and ignore portions of the graph known - * to be acyclic - */ - if (from->n_flags & (NF_NODEST | NF_MARK | NF_ACYCLIC)) - return (0); - from->n_flags |= NF_MARK; - - for (np = from->n_arcs, i = from->n_narcs; --i >= 0; np++) { - cycle_buf[depth] = *np; - if (*np == to) { - if (depth + 1 > longest_len) { - longest_len = depth + 1; - memcpy((char *)longest_cycle, - (char *)cycle_buf, longest_len * sizeof(NODE *)); - } - } else { - if ((*np)->n_flags & (NF_MARK | NF_ACYCLIC | NF_NODEST)) - continue; - len = find_cycle(*np, to, longest_len, depth + 1); - -#ifdef DEBUG - ErrorF("%*s %s->%s %d\n", depth, "", - from->n_name, to->n_name, len); -#endif - - if (len == 0) - (*np)->n_flags |= NF_NODEST; - - if (len > longest_len) - longest_len = len; - - if (len > 0 && !longest) - break; - } - } - from->n_flags &= ~NF_MARK; - return (longest_len); -} - -/* do topological sort on graph */ -static void -tsort(void) -{ - NODE *n, *next; - int cnt, i; - - while (graph != NULL) { - /* - * Keep getting rid of simple cases until there are none left, - * if there are any nodes still in the graph, then there is - * a cycle in it. - */ - do { - for (cnt = 0, n = graph; n != NULL; n = next) { - next = n->n_next; - if (n->n_refcnt == 0) { - remove_node(n); - ++cnt; - } - } - } while (graph != NULL && cnt); - - if (graph == NULL) - break; - - if (!cycle_buf) { - /* - * Allocate space for two cycle logs - one to be used - * as scratch space, the other to save the longest - * cycle. - */ - for (cnt = 0, n = graph; n != NULL; n = n->n_next) - ++cnt; - cycle_buf = xnfalloc(sizeof(NODE *) * cnt); - longest_cycle = xnfalloc(sizeof(NODE *) * cnt); - if (cycle_buf == NULL || longest_cycle == NULL) - return; - } - for (n = graph; n != NULL; n = n->n_next) - if (!(n->n_flags & NF_ACYCLIC)) { - if ((cnt = find_cycle(n, n, 0, 0))) { - ErrorF("tsort: cycle in data"); - for (i = 0; i < cnt; i++) - ErrorF("%s", longest_cycle[i]->n_name); - remove_node(n); - clear_cycle(); - break; - } else { - /* to avoid further checks */ - n->n_flags |= NF_ACYCLIC; - clear_cycle(); - } - } - - if (n == NULL) - ErrorF("tsort: internal error -- could not find cycle"); - } - if (cycle_buf) - xfree(cycle_buf); - if (longest_cycle) - xfree(longest_cycle); - if (graph) - free_nodes(graph); -} - -void -LoaderSortExtensions(void) -{ - int i, j; - ExtensionModule *ext, *newList; - NODE *node; - - graph = NULL; - longest = 0; - sorted = NULL; - last = NULL; - cycle_buf = NULL; - longest_cycle = NULL; - - /* - * Parse list and build the graph. Enter them in reverse order - * because tsort() will reverse those that have no depedencies. - */ - for (i = numExtensionModules - 1; i >= 0; i--) { - ext = &ExtensionModuleList[i]; - add_arc(ext->name, ext->name); -#ifdef DEBUG - ErrorF("Extension %s:\n", ext->name); -#endif - if (ext->initDependencies) - for (j = 0; ext->initDependencies[j]; j++) { - add_arc(ext->initDependencies[j], ext->name); -#ifdef DEBUG - ErrorF("\t%s\n", ext->initDependencies[j]); -#endif - } - } - tsort(); - newList = xnfalloc((numExtensionModules + 1) * sizeof(ExtensionModule)); - i = 0; - for (node = sorted; node; node = node->n_next) { - for (j = 0; j < numExtensionModules; j++) - if (!strcmp(node->n_name, ExtensionModuleList[j].name)) - break; - if (j != numExtensionModules) - newList[i++] = ExtensionModuleList[j]; - } - if (sorted) - free_nodes(sorted); - if (graph) - free_nodes(graph); - newList[i].name = NULL; - xfree(ExtensionModuleList); - ExtensionModuleList = newList; -#ifdef DEBUG - for (i = 0; ExtensionModuleList[i].name; i++) - ErrorF("Extension %s\n", ExtensionModuleList[i].name); -#endif -} +/* + * Copyright (c) 2000 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +/* Maybe this file belongs elsewhere? */ + +#define LOADERDECLARATIONS +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "loaderProcs.h" +#include "misc.h" +#include "xf86.h" + +/* + * This should be static, but miinitext wants it. FIXME: make extension + * initialization not completely terrible. + */ +ExtensionModule *ExtensionModuleList = NULL; +static int numExtensionModules = 0; + +static ExtensionModule * +NewExtensionModule(void) +{ + ExtensionModule *save = ExtensionModuleList; + int n; + + /* Sanity check */ + if (!ExtensionModuleList) + numExtensionModules = 0; + + n = numExtensionModules + 1; + ExtensionModuleList = realloc(ExtensionModuleList, + (n + 1) * sizeof(ExtensionModule)); + if (ExtensionModuleList == NULL) { + ExtensionModuleList = save; + return NULL; + } else { + numExtensionModules++; + ExtensionModuleList[numExtensionModules].name = NULL; + return ExtensionModuleList + (numExtensionModules - 1); + } +} + +void +LoadExtension(ExtensionModule * e, Bool builtin) +{ + ExtensionModule *newext; + + if (e == NULL || e->name == NULL) + return; + + if (!(newext = NewExtensionModule())) + return; + + if (builtin) + xf86MsgVerb(X_INFO, 2, "Initializing built-in extension %s\n", + e->name); + else + xf86MsgVerb(X_INFO, 2, "Loading extension %s\n", e->name); + + newext->name = e->name; + newext->initFunc = e->initFunc; + newext->disablePtr = e->disablePtr; + newext->setupFunc = e->setupFunc; + newext->initDependencies = e->initDependencies; + + if (e->setupFunc != NULL) + e->setupFunc(); +} + +/* + * Sort ExtensionModuleList according to the initialisation order + * dependencies. The code for this is taken from BSD's tsort, + * and carries the following copyright/license: + * + * + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Rendell of Memorial University of Newfoundland. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define NF_MARK 0x1 /* marker for cycle detection */ +#define NF_ACYCLIC 0x2 /* this node is cycle free */ +#define NF_NODEST 0x4 /* Unreachable */ + +typedef struct node_str NODE; +struct node_str { + NODE **n_prevp; /* pointer to previous node's n_next */ + NODE *n_next; /* next node in graph */ + NODE **n_arcs; /* array of arcs to other nodes */ + int n_narcs; /* number of arcs in n_arcs[] */ + int n_arcsize; /* size of n_arcs[] array */ + int n_refcnt; /* # of arcs pointing to this node */ + int n_flags; /* NF_* */ + const char *n_name; /* name of this node */ +}; + +static NODE *graph = NULL, **cycle_buf = NULL, **longest_cycle = NULL; +static int longest = 0; +static NODE *sorted = NULL, *last = NULL; + +/* Find a node in the graph (insert if not found) and return a pointer to it. */ +static NODE * +get_node(const char *name) +{ + NODE *n; + + for (n = graph; n && n->n_name && strcmp(n->n_name, name); + n = n->n_next) ; + if (n) + return (n); + + n = xnfalloc(sizeof(NODE)); + + n->n_narcs = 0; + n->n_arcsize = 0; + n->n_arcs = NULL; + n->n_refcnt = 0; + n->n_flags = 0; + n->n_name = name; + + /* Add to linked list. */ + if ((n->n_next = graph) != NULL) + graph->n_prevp = &n->n_next; + n->n_prevp = &graph; + graph = n; + + return (n); +} + +/* + * add an arc from node s1 to node s2 in the graph. If s1 or s2 are not in + * the graph, then add them. + */ +static void +add_arc(const char *s1, const char *s2) +{ + NODE *n1; + NODE *n2; + int bsize, i; + + n1 = get_node(s1); + + if (!strcmp(s1, s2)) + return; + + n2 = get_node(s2); + + /* + * Check if this arc is already here. + */ + for (i = 0; i < n1->n_narcs; i++) + if (n1->n_arcs[i] == n2) + return; + /* + * Add it. + */ + if (n1->n_narcs == n1->n_arcsize) { + if (!n1->n_arcsize) + n1->n_arcsize = 10; + bsize = n1->n_arcsize * sizeof(*n1->n_arcs) * 2; + n1->n_arcs = xnfrealloc(n1->n_arcs, bsize); + n1->n_arcsize = bsize / sizeof(*n1->n_arcs); + } + n1->n_arcs[n1->n_narcs++] = n2; + ++n2->n_refcnt; +} + +/* + * Clear the NODEST flag from all nodes. + */ +static void +clear_cycle(void) +{ + NODE *n; + + for (n = graph; n != NULL; n = n->n_next) + n->n_flags &= ~NF_NODEST; +} + +/* print node and remove from graph (does not actually free node) */ +static void +remove_node(NODE * n) +{ + NODE **np; + NODE *newnode; + int i; + +#ifdef DEBUG + ErrorF("%s\n", n->n_name); +#endif + newnode = xnfalloc(sizeof(NODE)); + memcpy(newnode, n, sizeof(NODE)); + if (last) + last->n_next = newnode; + else + sorted = newnode; + last = newnode; + newnode->n_next = NULL; + + for (np = n->n_arcs, i = n->n_narcs; --i >= 0; np++) + --(*np)->n_refcnt; + n->n_narcs = 0; + *n->n_prevp = n->n_next; + if (n->n_next) + n->n_next->n_prevp = n->n_prevp; +} + +static void +free_nodes(NODE * nodelist) +{ + NODE *n, *nextnode; + + for (n = nodelist; n;) { + nextnode = n->n_next; + free(n); + n = nextnode; + } +} + +/* look for the longest? cycle from node from to node to. */ +static int +find_cycle(NODE * from, NODE * to, int longest_len, int depth) +{ + NODE **np; + int i, len; + + /* + * avoid infinite loops and ignore portions of the graph known + * to be acyclic + */ + if (from->n_flags & (NF_NODEST | NF_MARK | NF_ACYCLIC)) + return (0); + from->n_flags |= NF_MARK; + + for (np = from->n_arcs, i = from->n_narcs; --i >= 0; np++) { + cycle_buf[depth] = *np; + if (*np == to) { + if (depth + 1 > longest_len) { + longest_len = depth + 1; + memcpy((char *)longest_cycle, + (char *)cycle_buf, longest_len * sizeof(NODE *)); + } + } else { + if ((*np)->n_flags & (NF_MARK | NF_ACYCLIC | NF_NODEST)) + continue; + len = find_cycle(*np, to, longest_len, depth + 1); + +#ifdef DEBUG + ErrorF("%*s %s->%s %d\n", depth, "", + from->n_name, to->n_name, len); +#endif + + if (len == 0) + (*np)->n_flags |= NF_NODEST; + + if (len > longest_len) + longest_len = len; + + if (len > 0 && !longest) + break; + } + } + from->n_flags &= ~NF_MARK; + return (longest_len); +} + +/* do topological sort on graph */ +static void +tsort(void) +{ + NODE *n, *next; + int cnt, i; + + while (graph != NULL) { + /* + * Keep getting rid of simple cases until there are none left, + * if there are any nodes still in the graph, then there is + * a cycle in it. + */ + do { + for (cnt = 0, n = graph; n != NULL; n = next) { + next = n->n_next; + if (n->n_refcnt == 0) { + remove_node(n); + ++cnt; + } + } + } while (graph != NULL && cnt); + + if (graph == NULL) + break; + + if (!cycle_buf) { + /* + * Allocate space for two cycle logs - one to be used + * as scratch space, the other to save the longest + * cycle. + */ + for (cnt = 0, n = graph; n != NULL; n = n->n_next) + ++cnt; + cycle_buf = xnfalloc(sizeof(NODE *) * cnt); + longest_cycle = xnfalloc(sizeof(NODE *) * cnt); + if (cycle_buf == NULL || longest_cycle == NULL) + return; + } + for (n = graph; n != NULL; n = n->n_next) + if (!(n->n_flags & NF_ACYCLIC)) { + if ((cnt = find_cycle(n, n, 0, 0))) { + ErrorF("tsort: cycle in data"); + for (i = 0; i < cnt; i++) + ErrorF("%s", longest_cycle[i]->n_name); + remove_node(n); + clear_cycle(); + break; + } else { + /* to avoid further checks */ + n->n_flags |= NF_ACYCLIC; + clear_cycle(); + } + } + + if (n == NULL) + ErrorF("tsort: internal error -- could not find cycle"); + } + if (cycle_buf) + free(cycle_buf); + if (longest_cycle) + free(longest_cycle); + if (graph) + free_nodes(graph); +} + +void +LoaderSortExtensions(void) +{ + int i, j; + ExtensionModule *ext, *newList; + NODE *node; + + graph = NULL; + longest = 0; + sorted = NULL; + last = NULL; + cycle_buf = NULL; + longest_cycle = NULL; + + /* + * Parse list and build the graph. Enter them in reverse order + * because tsort() will reverse those that have no depedencies. + */ + for (i = numExtensionModules - 1; i >= 0; i--) { + ext = &ExtensionModuleList[i]; + add_arc(ext->name, ext->name); +#ifdef DEBUG + ErrorF("Extension %s:\n", ext->name); +#endif + if (ext->initDependencies) + for (j = 0; ext->initDependencies[j]; j++) { + add_arc(ext->initDependencies[j], ext->name); +#ifdef DEBUG + ErrorF("\t%s\n", ext->initDependencies[j]); +#endif + } + } + tsort(); + newList = xnfalloc((numExtensionModules + 1) * sizeof(ExtensionModule)); + i = 0; + for (node = sorted; node; node = node->n_next) { + for (j = 0; j < numExtensionModules; j++) + if (!strcmp(node->n_name, ExtensionModuleList[j].name)) + break; + if (j != numExtensionModules) + newList[i++] = ExtensionModuleList[j]; + } + if (sorted) + free_nodes(sorted); + if (graph) + free_nodes(graph); + newList[i].name = NULL; + free(ExtensionModuleList); + ExtensionModuleList = newList; +#ifdef DEBUG + for (i = 0; ExtensionModuleList[i].name; i++) + ErrorF("Extension %s\n", ExtensionModuleList[i].name); +#endif +} diff --git a/xorg-server/hw/xfree86/loader/loadmod.c b/xorg-server/hw/xfree86/loader/loadmod.c index 5b175a546..e75ec8f69 100644 --- a/xorg-server/hw/xfree86/loader/loadmod.c +++ b/xorg-server/hw/xfree86/loader/loadmod.c @@ -1,1268 +1,1268 @@ -/* - * Copyright 1995-1998 by Metro Link, Inc. - * - * 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 Metro Link, Inc. not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Metro Link, Inc. makes no - * representations about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL METRO LINK, INC. 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. - */ -/* - * Copyright (c) 1997-2002 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "os.h" -/* For stat() and related stuff */ -#define NO_OSLIB_PROTOTYPES -#include "xf86_OSlib.h" -#define LOADERDECLARATIONS -#include "loaderProcs.h" -#include "misc.h" -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86Xinput.h" -#include "loader.h" -#include "xf86Optrec.h" - -#include -#include -#include -#include - -typedef struct _pattern { - const char *pattern; - regex_t rex; -} PatternRec, *PatternPtr; - -/* Prototypes for static functions */ -static char *FindModule(const char *, const char *, const char **, - PatternPtr); -static Bool CheckVersion(const char *, XF86ModuleVersionInfo *, - const XF86ModReqInfo *); -static void UnloadModuleOrDriver(ModuleDescPtr mod); -static char *LoaderGetCanonicalName(const char *, PatternPtr); -static void RemoveChild(ModuleDescPtr); -static ModuleDescPtr doLoadModule(const char *, const char *, const char **, - const char **, pointer, - const XF86ModReqInfo *, int *, int *, - int flags); - -const ModuleVersions LoaderVersionInfo = { - XORG_VERSION_CURRENT, - ABI_ANSIC_VERSION, - ABI_VIDEODRV_VERSION, - ABI_XINPUT_VERSION, - ABI_EXTENSION_VERSION, - ABI_FONT_VERSION -}; - -static void -FreeStringList(char **paths) -{ - char **p; - - if (!paths) - return; - - for (p = paths; *p; p++) - xfree(*p); - - xfree(paths); -} - -static char **defaultPathList = NULL; - -static Bool -PathIsAbsolute(const char *path) -{ - return (*path == '/'); -} - -/* - * Convert a comma-separated path into a NULL-terminated array of path - * elements, rejecting any that are not full absolute paths, and appending - * a '/' when it isn't already present. - */ -static char ** -InitPathList(const char *path) -{ - char *fullpath = NULL; - char *elem = NULL; - char **list = NULL, **save = NULL; - int len; - int addslash; - int n = 0; - - if (!path) - return defaultPathList; - - fullpath = xstrdup(path); - if (!fullpath) - return NULL; - elem = strtok(fullpath, ","); - while (elem) { - if (PathIsAbsolute(elem)) - { - len = strlen(elem); - addslash = (elem[len - 1] != '/'); - if (addslash) - len++; - save = list; - list = xrealloc(list, (n + 2) * sizeof(char *)); - if (!list) { - if (save) { - save[n] = NULL; - FreeStringList(save); - } - xfree(fullpath); - return NULL; - } - list[n] = xalloc(len + 1); - if (!list[n]) { - FreeStringList(list); - xfree(fullpath); - return NULL; - } - strcpy(list[n], elem); - if (addslash) { - list[n][len - 1] = '/'; - list[n][len] = '\0'; - } - n++; - } - elem = strtok(NULL, ","); - } - if (list) - list[n] = NULL; - xfree(fullpath); - return list; -} - -static void -FreePathList(char **pathlist) -{ - if (pathlist && pathlist != defaultPathList) - FreeStringList(pathlist); -} - -void -LoaderSetPath(const char *path) -{ - if (!path) - return; - - defaultPathList = InitPathList(path); -} - -/* Standard set of module subdirectories to search, in order of preference */ -static const char *stdSubdirs[] = { - "", - "input/", - "drivers/", - "multimedia/", - "extensions/", - "internal/", - NULL -}; - -/* - * Standard set of module name patterns to check, in order of preference - * These are regular expressions (suitable for use with POSIX regex(3)). - * - * This list assumes that you're an ELFish platform and therefore your - * shared libraries are named something.so. If we're ever nuts enough - * to port this DDX to, say, Darwin, we'll need to fix this. - */ -static PatternRec stdPatterns[] = { - {"^lib(.*)\\.so$",}, - {"(.*)_drv\\.so$",}, - {"(.*)\\.so$",}, - {NULL,} -}; - -static PatternPtr -InitPatterns(const char **patternlist) -{ - char errmsg[80]; - int i, e; - PatternPtr patterns = NULL; - PatternPtr p = NULL; - static int firstTime = 1; - const char **s; - - if (firstTime) { - /* precompile stdPatterns */ - firstTime = 0; - for (p = stdPatterns; p->pattern; p++) - if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) { - regerror(e, &p->rex, errmsg, sizeof(errmsg)); - FatalError("InitPatterns: regcomp error for `%s': %s\n", - p->pattern, errmsg); - } - } - - if (patternlist) { - for (i = 0, s = patternlist; *s; i++, s++) - if (*s == DEFAULT_LIST) - i += sizeof(stdPatterns) / sizeof(stdPatterns[0]) - 1 - 1; - patterns = xalloc((i + 1) * sizeof(PatternRec)); - if (!patterns) { - return NULL; - } - for (i = 0, s = patternlist; *s; i++, s++) - if (*s != DEFAULT_LIST) { - p = patterns + i; - p->pattern = *s; - if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) { - regerror(e, &p->rex, errmsg, sizeof(errmsg)); - ErrorF("InitPatterns: regcomp error for `%s': %s\n", - p->pattern, errmsg); - i--; - } - } else { - for (p = stdPatterns; p->pattern; p++, i++) - patterns[i] = *p; - if (p != stdPatterns) - i--; - } - patterns[i].pattern = NULL; - } else - patterns = stdPatterns; - return patterns; -} - -static void -FreePatterns(PatternPtr patterns) -{ - if (patterns && patterns != stdPatterns) - xfree(patterns); -} - -static const char ** -InitSubdirs(const char **subdirlist) -{ - int i; - const char **tmp_subdirlist = NULL; - char **subdirs = NULL; - const char **s, **stmp = NULL; - const char *osname; - const char *slash; - int oslen = 0, len; - Bool indefault; - - if (subdirlist == NULL) { - subdirlist = tmp_subdirlist = xalloc(2 * sizeof(char *)); - if (subdirlist == NULL) - return NULL; - subdirlist[0] = DEFAULT_LIST; - subdirlist[1] = NULL; - } - - LoaderGetOS(&osname, NULL, NULL, NULL); - oslen = strlen(osname); - - { - /* Count number of entries and check for invalid paths */ - for (i = 0, s = subdirlist; *s; i++, s++) { - if (*s == DEFAULT_LIST) { - i += sizeof(stdSubdirs) / sizeof(stdSubdirs[0]) - 1 - 1; - } else { - /* - * Path validity check. Don't allow absolute paths, or - * paths containing "..". To catch absolute paths on - * platforms that use driver letters, don't allow the ':' - * character to appear at all. - */ - if (**s == '/' || **s == '\\' || strchr(*s, ':') || - strstr(*s, "..")) { - xf86Msg(X_ERROR, "InitSubdirs: Bad subdir: \"%s\"\n", *s); - if (tmp_subdirlist) - xfree(tmp_subdirlist); - return NULL; - } - } - } - subdirs = xalloc((i * 2 + 1) * sizeof(char *)); - if (!subdirs) { - if (tmp_subdirlist) - xfree(tmp_subdirlist); - return NULL; - } - i = 0; - s = subdirlist; - indefault = FALSE; - while (*s) { - if (*s == DEFAULT_LIST) { - /* Divert to the default list */ - indefault = TRUE; - stmp = ++s; - s = stdSubdirs; - } - len = strlen(*s); - if (**s && (*s)[len - 1] != '/') { - slash = "/"; - len++; - } else - slash = ""; - len += oslen + 2; - if (!(subdirs[i] = xalloc(len))) { - while (--i >= 0) - xfree(subdirs[i]); - xfree(subdirs); - if (tmp_subdirlist) - xfree(tmp_subdirlist); - return NULL; - } - /* tack on the OS name */ - sprintf(subdirs[i], "%s%s%s/", *s, slash, osname); - i++; - /* path as given */ - subdirs[i] = xstrdup(*s); - i++; - s++; - if (indefault && !s) { - /* revert back to the main list */ - indefault = FALSE; - s = stmp; - } - } - subdirs[i] = NULL; - } - if (tmp_subdirlist) - xfree(tmp_subdirlist); - return (const char **)subdirs; -} - -static void -FreeSubdirs(const char **subdirs) -{ - const char **s; - - if (subdirs) { - for (s = subdirs; *s; s++) - xfree(*s); - xfree(subdirs); - } -} - -static char * -FindModuleInSubdir(const char *dirpath, const char *module) -{ - struct dirent *direntry = NULL; - DIR *dir = NULL; - char *ret = NULL, tmpBuf[PATH_MAX]; - struct stat stat_buf; - - dir = opendir(dirpath); - if (!dir) - return NULL; - - while ((direntry = readdir(dir))) { - if (direntry->d_name[0] == '.') - continue; - snprintf(tmpBuf, PATH_MAX, "%s%s/", dirpath, direntry->d_name); - /* the stat with the appended / fails for normal files, - and works for sub dirs fine, looks a bit strange in strace - but does seem to work */ - if ((stat(tmpBuf, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) { - if ((ret = FindModuleInSubdir(tmpBuf, module))) - break; - continue; - } - - snprintf(tmpBuf, PATH_MAX, "lib%s.so", module); - if (strcmp(direntry->d_name, tmpBuf) == 0) { - ret = malloc(strlen(tmpBuf) + strlen(dirpath) + 2); - sprintf(ret, "%s%s", dirpath, tmpBuf); - break; - } - - snprintf(tmpBuf, PATH_MAX, "%s_drv.so", module); - if (strcmp(direntry->d_name, tmpBuf) == 0) { - ret = malloc(strlen(tmpBuf) + strlen(dirpath) + 2); - sprintf(ret, "%s%s", dirpath, tmpBuf); - break; - } - - snprintf(tmpBuf, PATH_MAX, "%s.so", module); - if (strcmp(direntry->d_name, tmpBuf) == 0) { - ret = malloc(strlen(tmpBuf) + strlen(dirpath) + 2); - sprintf(ret, "%s%s", dirpath, tmpBuf); - break; - } - } - - closedir(dir); - return ret; -} - -static char * -FindModule(const char *module, const char *dirname, const char **subdirlist, - PatternPtr patterns) -{ - char buf[PATH_MAX + 1]; - char *dirpath = NULL; - char *name = NULL; - int dirlen; - const char **subdirs = NULL; - const char **s; - - dirpath = (char *)dirname; - if (strlen(dirpath) > PATH_MAX) - return NULL; - - subdirs = InitSubdirs(subdirlist); - if (!subdirs) - return NULL; - - for (s = subdirs; *s; s++) { - if ((dirlen = strlen(dirpath) + strlen(*s)) > PATH_MAX) - continue; - strcpy(buf, dirpath); - strcat(buf, *s); - if ((name = FindModuleInSubdir(buf, module))) - break; - } - - FreeSubdirs(subdirs); - if (dirpath != dirname) - xfree(dirpath); - - return name; -} - -char ** -LoaderListDirs(const char **subdirlist, const char **patternlist) -{ - char buf[PATH_MAX + 1]; - char **pathlist; - char **elem; - const char **subdirs; - const char **s; - PatternPtr patterns; - PatternPtr p; - DIR *d; - struct dirent *dp; - regmatch_t match[2]; - struct stat stat_buf; - int len, dirlen; - char *fp; - char **listing = NULL; - char **save; - int n = 0; - - if (!(pathlist = InitPathList(NULL))) - return NULL; - if (!(subdirs = InitSubdirs(subdirlist))) { - FreePathList(pathlist); - return NULL; - } - if (!(patterns = InitPatterns(patternlist))) { - FreePathList(pathlist); - FreeSubdirs(subdirs); - return NULL; - } - - for (elem = pathlist; *elem; elem++) { - for (s = subdirs; *s; s++) { - if ((dirlen = strlen(*elem) + strlen(*s)) > PATH_MAX) - continue; - strcpy(buf, *elem); - strcat(buf, *s); - fp = buf + dirlen; - if (stat(buf, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode) && - (d = opendir(buf))) { - if (buf[dirlen - 1] != '/') { - buf[dirlen++] = '/'; - fp++; - } - while ((dp = readdir(d))) { - if (dirlen + strlen(dp->d_name) > PATH_MAX) - continue; - strcpy(fp, dp->d_name); - if (!(stat(buf, &stat_buf) == 0 && - S_ISREG(stat_buf.st_mode))) - continue; - for (p = patterns; p->pattern; p++) { - if (regexec(&p->rex, dp->d_name, 2, match, 0) == 0 && - match[1].rm_so != -1) { - len = match[1].rm_eo - match[1].rm_so; - save = listing; - listing = xrealloc(listing, - (n + 2) * sizeof(char *)); - if (!listing) { - if (save) { - save[n] = NULL; - FreeStringList(save); - } - FreePathList(pathlist); - FreeSubdirs(subdirs); - FreePatterns(patterns); - return NULL; - } - listing[n] = xalloc(len + 1); - if (!listing[n]) { - FreeStringList(listing); - FreePathList(pathlist); - FreeSubdirs(subdirs); - FreePatterns(patterns); - return NULL; - } - strncpy(listing[n], dp->d_name + match[1].rm_so, - len); - listing[n][len] = '\0'; - n++; - break; - } - } - } - closedir(d); - } - } - } - if (listing) - listing[n] = NULL; - return listing; -} - -void -LoaderFreeDirList(char **list) -{ - FreeStringList(list); -} - -static Bool -CheckVersion(const char *module, XF86ModuleVersionInfo * data, - const XF86ModReqInfo * req) -{ - int vercode[4]; - char verstr[4]; - long ver = data->xf86version; - MessageType errtype; - - xf86Msg(X_INFO, "Module %s: vendor=\"%s\"\n", - data->modname ? data->modname : "UNKNOWN!", - data->vendor ? data->vendor : "UNKNOWN!"); - - /* Check for the different scheme used in XFree86 4.0.x releases: - * ((((((((major << 7) | minor) << 7) | subminor) << 5) | beta) << 5) | alpha) - * Since it wasn't used in 4.1.0 or later, limit to versions in the 4.0.x - * range, which limits the overlap with the new version scheme to conflicts - * with 6.71.8.764 through 6.72.39.934. - */ - if ((ver > (4 << 24)) && (ver < ( (4 << 24) + (1 << 17)))) { - /* 4.0.x and earlier */ - verstr[1] = verstr[3] = 0; - verstr[2] = (ver & 0x1f) ? (ver & 0x1f) + 'a' - 1 : 0; - ver >>= 5; - verstr[0] = (ver & 0x1f) ? (ver & 0x1f) + 'A' - 1 : 0; - ver >>= 5; - vercode[2] = ver & 0x7f; - ver >>= 7; - vercode[1] = ver & 0x7f; - ver >>= 7; - vercode[0] = ver; - xf86ErrorF("\tcompiled for %d.%d", vercode[0], vercode[1]); - if (vercode[2] != 0) - xf86ErrorF(".%d", vercode[2]); - xf86ErrorF("%s%s, module version = %d.%d.%d\n", verstr, verstr + 2, - data->majorversion, data->minorversion, data->patchlevel); - } else { - vercode[0] = ver / 10000000; - vercode[1] = (ver / 100000) % 100; - vercode[2] = (ver / 1000) % 100; - vercode[3] = ver % 1000; - xf86ErrorF("\tcompiled for %d.%d.%d", vercode[0], vercode[1], - vercode[2]); - if (vercode[3] != 0) - xf86ErrorF(".%d", vercode[3]); - xf86ErrorF(", module version = %d.%d.%d\n", data->majorversion, - data->minorversion, data->patchlevel); - } - - if (data->moduleclass) - xf86ErrorFVerb(2, "\tModule class: %s\n", data->moduleclass); - - ver = -1; - if (data->abiclass) { - int abimaj, abimin; - int vermaj, vermin; - - if (!strcmp(data->abiclass, ABI_CLASS_ANSIC)) - ver = LoaderVersionInfo.ansicVersion; - else if (!strcmp(data->abiclass, ABI_CLASS_VIDEODRV)) - ver = LoaderVersionInfo.videodrvVersion; - else if (!strcmp(data->abiclass, ABI_CLASS_XINPUT)) - ver = LoaderVersionInfo.xinputVersion; - else if (!strcmp(data->abiclass, ABI_CLASS_EXTENSION)) - ver = LoaderVersionInfo.extensionVersion; - else if (!strcmp(data->abiclass, ABI_CLASS_FONT)) - ver = LoaderVersionInfo.fontVersion; - - abimaj = GET_ABI_MAJOR(data->abiversion); - abimin = GET_ABI_MINOR(data->abiversion); - xf86ErrorFVerb(2, "\tABI class: %s, version %d.%d\n", - data->abiclass, abimaj, abimin); - if (ver != -1) { - vermaj = GET_ABI_MAJOR(ver); - vermin = GET_ABI_MINOR(ver); - if (abimaj != vermaj) { - if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) - errtype = X_WARNING; - else - errtype = X_ERROR; - xf86MsgVerb(errtype, 0, - "module ABI major version (%d) doesn't" - " match the server's version (%d)\n", - abimaj, vermaj); - if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)) - return FALSE; - } else if (abimin > vermin) { - if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) - errtype = X_WARNING; - else - errtype = X_ERROR; - xf86MsgVerb(errtype, 0, - "module ABI minor version (%d) is " - "newer than the server's version " - "(%d)\n", abimin, vermin); - if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)) - return FALSE; - } - } - } - - /* Check against requirements that the caller has specified */ - if (req) { - if (req->majorversion != MAJOR_UNSPEC) { - if (data->majorversion != req->majorversion) { - xf86MsgVerb(X_WARNING, 2, "module major version (%d) " - "doesn't match required major version (%d)\n", - data->majorversion, req->majorversion); - return FALSE; - } else if (req->minorversion != MINOR_UNSPEC) { - if (data->minorversion < req->minorversion) { - xf86MsgVerb(X_WARNING, 2, "module minor version (%d) " - "is less than the required minor version (%d)\n", - data->minorversion, req->minorversion); - return FALSE; - } else if (data->minorversion == req->minorversion && - req->patchlevel != PATCH_UNSPEC) { - if (data->patchlevel < req->patchlevel) { - xf86MsgVerb(X_WARNING, 2, "module patch level (%d) " - "is less than the required patch level (%d)\n", - data->patchlevel, req->patchlevel); - return FALSE; - } - } - } - } - if (req->moduleclass) { - if (!data->moduleclass || - strcmp(req->moduleclass, data->moduleclass)) { - xf86MsgVerb(X_WARNING, 2, "Module class (%s) doesn't match " - "the required class (%s)\n", - data->moduleclass ? data->moduleclass : "", - req->moduleclass); - return FALSE; - } - } else if (req->abiclass != ABI_CLASS_NONE) { - if (!data->abiclass || strcmp(req->abiclass, data->abiclass)) { - xf86MsgVerb(X_WARNING, 2, "ABI class (%s) doesn't match the " - "required ABI class (%s)\n", - data->abiclass ? data->abiclass : "", - req->abiclass); - return FALSE; - } - } - if ((req->abiclass != ABI_CLASS_NONE) && - req->abiversion != ABI_VERS_UNSPEC) { - int reqmaj, reqmin, maj, min; - - reqmaj = GET_ABI_MAJOR(req->abiversion); - reqmin = GET_ABI_MINOR(req->abiversion); - maj = GET_ABI_MAJOR(data->abiversion); - min = GET_ABI_MINOR(data->abiversion); - if (maj != reqmaj) { - xf86MsgVerb(X_WARNING, 2, "ABI major version (%d) doesn't " - "match the required ABI major version (%d)\n", - maj, reqmaj); - return FALSE; - } - /* XXX Maybe this should be the other way around? */ - if (min > reqmin) { - xf86MsgVerb(X_WARNING, 2, "module ABI minor version (%d) " - "is newer than that available (%d)\n", min, reqmin); - return FALSE; - } - } - } - return TRUE; -} - -static ModuleDescPtr -AddSibling(ModuleDescPtr head, ModuleDescPtr new) -{ - new->sib = head; - return (new); -} - -pointer -LoadSubModule(pointer _parent, const char *module, - const char **subdirlist, const char **patternlist, - pointer options, const XF86ModReqInfo * modreq, - int *errmaj, int *errmin) -{ - ModuleDescPtr submod; - ModuleDescPtr parent = (ModuleDescPtr)_parent; - - xf86MsgVerb(X_INFO, 3, "Loading sub module \"%s\"\n", module); - - if (PathIsAbsolute(module)) { - xf86Msg(X_ERROR, - "LoadSubModule: Absolute module path not permitted: \"%s\"\n", - module); - if (errmaj) - *errmaj = LDR_BADUSAGE; - if (errmin) - *errmin = 0; - return NULL; - } - - submod = doLoadModule(module, NULL, subdirlist, patternlist, options, - modreq, errmaj, errmin, LD_FLAG_GLOBAL); - if (submod && submod != (ModuleDescPtr) 1) { - parent->child = AddSibling(parent->child, submod); - submod->parent = parent; - } - return submod; -} - -static ModuleDescPtr -NewModuleDesc(const char *name) -{ - ModuleDescPtr mdp = xalloc(sizeof(ModuleDesc)); - - if (mdp) { - mdp->child = NULL; - mdp->sib = NULL; - mdp->parent = NULL; - mdp->name = xstrdup(name); - mdp->handle = -1; - mdp->SetupProc = NULL; - mdp->TearDownProc = NULL; - mdp->TearDownData = NULL; - } - - return (mdp); -} - -ModuleDescPtr -DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent) -{ - ModuleDescPtr ret; - - if (!mod) - return NULL; - - ret = NewModuleDesc(mod->name); - if (ret == NULL) - return NULL; - - if (LoaderHandleOpen(mod->handle) == -1) - return NULL; - - ret->handle = mod->handle; - ret->SetupProc = mod->SetupProc; - ret->TearDownProc = mod->TearDownProc; - ret->TearDownData = NULL; - ret->child = DuplicateModule(mod->child, ret); - ret->sib = DuplicateModule(mod->sib, parent); - ret->parent = parent; - ret->VersionInfo = mod->VersionInfo; - - return ret; -} - -static const char *compiled_in_modules[] = { - "ddc", - "i2c", - "ramdac", - NULL -}; - -static ModuleDescPtr -doLoadModule(const char *module, const char *path, const char **subdirlist, - const char **patternlist, pointer options, - const XF86ModReqInfo * modreq, - int *errmaj, int *errmin, int flags) -{ - XF86ModuleData *initdata = NULL; - char **pathlist = NULL; - char *found = NULL; - char *name = NULL; - char **path_elem = NULL; - char *p = NULL; - ModuleDescPtr ret = NULL; - int wasLoaded = 0; - PatternPtr patterns = NULL; - int noncanonical = 0; - char *m = NULL; - const char **cim; - - xf86MsgVerb(X_INFO, 3, "LoadModule: \"%s\"", module); - - patterns = InitPatterns(patternlist); - name = LoaderGetCanonicalName(module, patterns); - noncanonical = (name && strcmp(module, name) != 0); - if (noncanonical) { - xf86ErrorFVerb(3, " (%s)\n", name); - xf86MsgVerb(X_WARNING, 1, - "LoadModule: given non-canonical module name \"%s\"\n", - module); - m = name; - } else { - xf86ErrorFVerb(3, "\n"); - m = (char *)module; - } - - for (cim = compiled_in_modules; *cim; cim++) - if (!strcmp (m, *cim)) - { - xf86MsgVerb(X_INFO, 3, "Module \"%s\" already built-in\n", m); - ret = (ModuleDescPtr) 1; - goto LoadModule_exit; - } - - if (!name) { - if (errmaj) - *errmaj = LDR_BADUSAGE; - if (errmin) - *errmin = 0; - goto LoadModule_fail; - } - ret = NewModuleDesc(name); - if (!ret) { - if (errmaj) - *errmaj = LDR_NOMEM; - if (errmin) - *errmin = 0; - goto LoadModule_fail; - } - - pathlist = InitPathList(path); - if (!pathlist) { - /* This could be a malloc failure too */ - if (errmaj) - *errmaj = LDR_BADUSAGE; - if (errmin) - *errmin = 1; - goto LoadModule_fail; - } - - /* - * if the module name is not a full pathname, we need to - * check the elements in the path - */ - if (PathIsAbsolute(module)) - found = xstrdup(module); - path_elem = pathlist; - while (!found && *path_elem != NULL) { - found = FindModule(m, *path_elem, subdirlist, patterns); - path_elem++; - /* - * When the module name isn't the canonical name, search for the - * former if no match was found for the latter. - */ - if (!*path_elem && m == name) { - path_elem = pathlist; - m = (char *)module; - } - } - - /* - * did we find the module? - */ - if (!found) { - xf86Msg(X_WARNING, "Warning, couldn't open module %s\n", module); - if (errmaj) - *errmaj = LDR_NOENT; - if (errmin) - *errmin = 0; - goto LoadModule_fail; - } - ret->handle = LoaderOpen(found, name, 0, - errmaj, errmin, &wasLoaded, flags); - if (ret->handle < 0) - goto LoadModule_fail; - - /* drop any explicit suffix from the module name */ - p = strchr(name, '.'); - if (p) - *p = '\0'; - - /* - * now check if the special data object ModuleData is - * present. - */ - p = xalloc(strlen(name) + strlen("ModuleData") + 1); - if (!p) { - if (errmaj) - *errmaj = LDR_NOMEM; - if (errmin) - *errmin = 0; - goto LoadModule_fail; - } - strcpy(p, name); - strcat(p, "ModuleData"); - initdata = LoaderSymbol(p); - if (initdata) { - ModuleSetupProc setup; - ModuleTearDownProc teardown; - XF86ModuleVersionInfo *vers; - - vers = initdata->vers; - setup = initdata->setup; - teardown = initdata->teardown; - - if (!wasLoaded) { - if (vers) { - if (!CheckVersion(module, vers, modreq)) { - if (errmaj) - *errmaj = LDR_MISMATCH; - if (errmin) - *errmin = 0; - goto LoadModule_fail; - } - } else { - xf86Msg(X_ERROR, - "LoadModule: Module %s does not supply" - " version information\n", module); - if (errmaj) - *errmaj = LDR_INVALID; - if (errmin) - *errmin = 0; - goto LoadModule_fail; - } - } - if (setup) - ret->SetupProc = setup; - if (teardown) - ret->TearDownProc = teardown; - ret->VersionInfo = vers; - } else { - /* No initdata is OK for external modules */ - if (options == EXTERN_MODULE) - goto LoadModule_exit; - - /* no initdata, fail the load */ - xf86Msg(X_ERROR, "LoadModule: Module %s does not have a %s " - "data object.\n", module, p); - if (errmaj) - *errmaj = LDR_INVALID; - if (errmin) - *errmin = 0; - goto LoadModule_fail; - } - if (ret->SetupProc) { - ret->TearDownData = ret->SetupProc(ret, options, errmaj, errmin); - if (!ret->TearDownData) { - goto LoadModule_fail; - } - } else if (options) { - xf86Msg(X_WARNING, "Module Options present, but no SetupProc " - "available for %s\n", module); - } - goto LoadModule_exit; - - LoadModule_fail: - UnloadModule(ret); - ret = NULL; - - LoadModule_exit: - FreePathList(pathlist); - FreePatterns(patterns); - xfree(found); - xfree(name); - xfree(p); - - return ret; -} - -/* - * LoadModule: load a module - * - * module The module name. Normally this is not a filename but the - * module's "canonical name. A full pathname is, however, - * also accepted. - * path A comma separated list of module directories. - * subdirlist A NULL terminated list of subdirectories to search. When - * NULL, the default "stdSubdirs" list is used. The default - * list is also substituted for entries with value DEFAULT_LIST. - * patternlist A NULL terminated list of regular expressions used to find - * module filenames. Each regex should contain exactly one - * subexpression that corresponds to the canonical module name. - * When NULL, the default "stdPatterns" list is used. The - * default list is also substituted for entries with value - * DEFAULT_LIST. - * options A NULL terminated list of Options that are passed to the - * module's SetupProc function. - * modreq An optional XF86ModReqInfo* containing - * version/ABI/vendor-ABI requirements to check for when - * loading the module. The following fields of the - * XF86ModReqInfo struct are checked: - * majorversion - must match the module's majorversion exactly - * minorversion - the module's minorversion must be >= this - * patchlevel - the module's minorversion.patchlevel must be - * >= this. Patchlevel is ignored when - * minorversion is not set. - * abiclass - (string) must match the module's abiclass - * abiversion - must be consistent with the module's - * abiversion (major equal, minor no older) - * moduleclass - string must match the module's moduleclass - * string - * "don't care" values are ~0 for numbers, and NULL for strings - * errmaj Major error return. - * errmin Minor error return. - * - */ -ModuleDescPtr -LoadModule(const char *module, const char *path, const char **subdirlist, - const char **patternlist, pointer options, - const XF86ModReqInfo * modreq, int *errmaj, int *errmin) -{ - return doLoadModule(module, path, subdirlist, patternlist, options, - modreq, errmaj, errmin, LD_FLAG_GLOBAL); -} - -void -UnloadModule(pointer mod) -{ - UnloadModuleOrDriver((ModuleDescPtr)mod); -} - -static void -UnloadModuleOrDriver(ModuleDescPtr mod) -{ - if (mod == (ModuleDescPtr) 1) - return; - - if (mod == NULL || mod->name == NULL) - return; - - xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name); - - if ((mod->TearDownProc) && (mod->TearDownData)) - mod->TearDownProc(mod->TearDownData); - LoaderUnload(mod->handle); - - if (mod->child) - UnloadModuleOrDriver(mod->child); - if (mod->sib) - UnloadModuleOrDriver(mod->sib); - xfree(mod->name); - xfree(mod); -} - -void -UnloadSubModule(pointer _mod) -{ - ModuleDescPtr mod = (ModuleDescPtr)_mod; - - if (mod == NULL || mod->name == NULL) - return; - - xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name); - - if ((mod->TearDownProc) && (mod->TearDownData)) - mod->TearDownProc(mod->TearDownData); - LoaderUnload(mod->handle); - - RemoveChild(mod); - - if (mod->child) - UnloadModuleOrDriver(mod->child); - - xfree(mod->name); - xfree(mod); -} - -static void -RemoveChild(ModuleDescPtr child) -{ - ModuleDescPtr mdp; - ModuleDescPtr prevsib; - ModuleDescPtr parent; - - if (!child->parent) - return; - - parent = child->parent; - if (parent->child == child) { - parent->child = child->sib; - return; - } - - prevsib = parent->child; - mdp = prevsib->sib; - while (mdp && mdp != child) { - prevsib = mdp; - mdp = mdp->sib; - } - if (mdp == child) - prevsib->sib = child->sib; - return; -} - -void -LoaderErrorMsg(const char *name, const char *modname, int errmaj, int errmin) -{ - const char *msg; - MessageType type = X_ERROR; - - switch (errmaj) { - case LDR_NOERROR: - msg = "no error"; - break; - case LDR_NOMEM: - msg = "out of memory"; - break; - case LDR_NOENT: - msg = "module does not exist"; - break; - case LDR_NOSUBENT: - msg = "a required submodule could not be loaded"; - break; - case LDR_NOSPACE: - msg = "too many modules"; - break; - case LDR_NOMODOPEN: - msg = "open failed"; - break; - case LDR_UNKTYPE: - msg = "unknown module type"; - break; - case LDR_NOLOAD: - msg = "loader failed"; - break; - case LDR_ONCEONLY: - msg = "already loaded"; - type = X_INFO; - break; - case LDR_NOPORTOPEN: - msg = "port open failed"; - break; - case LDR_NOHARDWARE: - msg = "no hardware found"; - break; - case LDR_MISMATCH: - msg = "module requirement mismatch"; - break; - case LDR_BADUSAGE: - msg = "invalid argument(s) to LoadModule()"; - break; - case LDR_INVALID: - msg = "invalid module"; - break; - case LDR_BADOS: - msg = "module doesn't support this OS"; - break; - case LDR_MODSPECIFIC: - msg = "module-specific error"; - break; - default: - msg = "unknown error"; - } - if (name) - xf86Msg(type, "%s: Failed to load module \"%s\" (%s, %d)\n", - name, modname, msg, errmin); - else - xf86Msg(type, "Failed to load module \"%s\" (%s, %d)\n", - modname, msg, errmin); -} - -/* Given a module path or file name, return the module's canonical name */ -static char * -LoaderGetCanonicalName(const char *modname, PatternPtr patterns) -{ - char *str; - const char *s; - int len; - PatternPtr p; - regmatch_t match[2]; - - /* Strip off any leading path */ - s = strrchr(modname, '/'); - if (s == NULL) - s = modname; - else - s++; - - /* Find the first regex that is matched */ - for (p = patterns; p->pattern; p++) - if (regexec(&p->rex, s, 2, match, 0) == 0 && match[1].rm_so != -1) { - len = match[1].rm_eo - match[1].rm_so; - str = xalloc(len + 1); - if (!str) - return NULL; - strncpy(str, s + match[1].rm_so, len); - str[len] = '\0'; - return str; - } - - /* If there is no match, return the whole name minus the leading path */ - return xstrdup(s); -} - -/* - * Return the module version information. - */ -unsigned long -LoaderGetModuleVersion(ModuleDescPtr mod) -{ - if (!mod || mod == (ModuleDescPtr) 1 || !mod->VersionInfo) - return 0; - - return MODULE_VERSION_NUMERIC(mod->VersionInfo->majorversion, - mod->VersionInfo->minorversion, - mod->VersionInfo->patchlevel); -} +/* + * Copyright 1995-1998 by Metro Link, Inc. + * + * 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 Metro Link, Inc. not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Metro Link, Inc. makes no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL METRO LINK, INC. 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. + */ +/* + * Copyright (c) 1997-2002 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "os.h" +/* For stat() and related stuff */ +#define NO_OSLIB_PROTOTYPES +#include "xf86_OSlib.h" +#define LOADERDECLARATIONS +#include "loaderProcs.h" +#include "misc.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86Xinput.h" +#include "loader.h" +#include "xf86Optrec.h" + +#include +#include +#include +#include + +typedef struct _pattern { + const char *pattern; + regex_t rex; +} PatternRec, *PatternPtr; + +/* Prototypes for static functions */ +static char *FindModule(const char *, const char *, const char **, + PatternPtr); +static Bool CheckVersion(const char *, XF86ModuleVersionInfo *, + const XF86ModReqInfo *); +static void UnloadModuleOrDriver(ModuleDescPtr mod); +static char *LoaderGetCanonicalName(const char *, PatternPtr); +static void RemoveChild(ModuleDescPtr); +static ModuleDescPtr doLoadModule(const char *, const char *, const char **, + const char **, pointer, + const XF86ModReqInfo *, int *, int *, + int flags); + +const ModuleVersions LoaderVersionInfo = { + XORG_VERSION_CURRENT, + ABI_ANSIC_VERSION, + ABI_VIDEODRV_VERSION, + ABI_XINPUT_VERSION, + ABI_EXTENSION_VERSION, + ABI_FONT_VERSION +}; + +static void +FreeStringList(char **paths) +{ + char **p; + + if (!paths) + return; + + for (p = paths; *p; p++) + free(*p); + + free(paths); +} + +static char **defaultPathList = NULL; + +static Bool +PathIsAbsolute(const char *path) +{ + return (*path == '/'); +} + +/* + * Convert a comma-separated path into a NULL-terminated array of path + * elements, rejecting any that are not full absolute paths, and appending + * a '/' when it isn't already present. + */ +static char ** +InitPathList(const char *path) +{ + char *fullpath = NULL; + char *elem = NULL; + char **list = NULL, **save = NULL; + int len; + int addslash; + int n = 0; + + if (!path) + return defaultPathList; + + fullpath = xstrdup(path); + if (!fullpath) + return NULL; + elem = strtok(fullpath, ","); + while (elem) { + if (PathIsAbsolute(elem)) + { + len = strlen(elem); + addslash = (elem[len - 1] != '/'); + if (addslash) + len++; + save = list; + list = realloc(list, (n + 2) * sizeof(char *)); + if (!list) { + if (save) { + save[n] = NULL; + FreeStringList(save); + } + free(fullpath); + return NULL; + } + list[n] = malloc(len + 1); + if (!list[n]) { + FreeStringList(list); + free(fullpath); + return NULL; + } + strcpy(list[n], elem); + if (addslash) { + list[n][len - 1] = '/'; + list[n][len] = '\0'; + } + n++; + } + elem = strtok(NULL, ","); + } + if (list) + list[n] = NULL; + free(fullpath); + return list; +} + +static void +FreePathList(char **pathlist) +{ + if (pathlist && pathlist != defaultPathList) + FreeStringList(pathlist); +} + +void +LoaderSetPath(const char *path) +{ + if (!path) + return; + + defaultPathList = InitPathList(path); +} + +/* Standard set of module subdirectories to search, in order of preference */ +static const char *stdSubdirs[] = { + "", + "input/", + "drivers/", + "multimedia/", + "extensions/", + "internal/", + NULL +}; + +/* + * Standard set of module name patterns to check, in order of preference + * These are regular expressions (suitable for use with POSIX regex(3)). + * + * This list assumes that you're an ELFish platform and therefore your + * shared libraries are named something.so. If we're ever nuts enough + * to port this DDX to, say, Darwin, we'll need to fix this. + */ +static PatternRec stdPatterns[] = { + {"^lib(.*)\\.so$",}, + {"(.*)_drv\\.so$",}, + {"(.*)\\.so$",}, + {NULL,} +}; + +static PatternPtr +InitPatterns(const char **patternlist) +{ + char errmsg[80]; + int i, e; + PatternPtr patterns = NULL; + PatternPtr p = NULL; + static int firstTime = 1; + const char **s; + + if (firstTime) { + /* precompile stdPatterns */ + firstTime = 0; + for (p = stdPatterns; p->pattern; p++) + if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) { + regerror(e, &p->rex, errmsg, sizeof(errmsg)); + FatalError("InitPatterns: regcomp error for `%s': %s\n", + p->pattern, errmsg); + } + } + + if (patternlist) { + for (i = 0, s = patternlist; *s; i++, s++) + if (*s == DEFAULT_LIST) + i += sizeof(stdPatterns) / sizeof(stdPatterns[0]) - 1 - 1; + patterns = malloc((i + 1) * sizeof(PatternRec)); + if (!patterns) { + return NULL; + } + for (i = 0, s = patternlist; *s; i++, s++) + if (*s != DEFAULT_LIST) { + p = patterns + i; + p->pattern = *s; + if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) { + regerror(e, &p->rex, errmsg, sizeof(errmsg)); + ErrorF("InitPatterns: regcomp error for `%s': %s\n", + p->pattern, errmsg); + i--; + } + } else { + for (p = stdPatterns; p->pattern; p++, i++) + patterns[i] = *p; + if (p != stdPatterns) + i--; + } + patterns[i].pattern = NULL; + } else + patterns = stdPatterns; + return patterns; +} + +static void +FreePatterns(PatternPtr patterns) +{ + if (patterns && patterns != stdPatterns) + free(patterns); +} + +static const char ** +InitSubdirs(const char **subdirlist) +{ + int i; + const char **tmp_subdirlist = NULL; + char **subdirs = NULL; + const char **s, **stmp = NULL; + const char *osname; + const char *slash; + int oslen = 0, len; + Bool indefault; + + if (subdirlist == NULL) { + subdirlist = tmp_subdirlist = malloc(2 * sizeof(char *)); + if (subdirlist == NULL) + return NULL; + subdirlist[0] = DEFAULT_LIST; + subdirlist[1] = NULL; + } + + LoaderGetOS(&osname, NULL, NULL, NULL); + oslen = strlen(osname); + + { + /* Count number of entries and check for invalid paths */ + for (i = 0, s = subdirlist; *s; i++, s++) { + if (*s == DEFAULT_LIST) { + i += sizeof(stdSubdirs) / sizeof(stdSubdirs[0]) - 1 - 1; + } else { + /* + * Path validity check. Don't allow absolute paths, or + * paths containing "..". To catch absolute paths on + * platforms that use driver letters, don't allow the ':' + * character to appear at all. + */ + if (**s == '/' || **s == '\\' || strchr(*s, ':') || + strstr(*s, "..")) { + xf86Msg(X_ERROR, "InitSubdirs: Bad subdir: \"%s\"\n", *s); + if (tmp_subdirlist) + free(tmp_subdirlist); + return NULL; + } + } + } + subdirs = malloc((i * 2 + 1) * sizeof(char *)); + if (!subdirs) { + if (tmp_subdirlist) + free(tmp_subdirlist); + return NULL; + } + i = 0; + s = subdirlist; + indefault = FALSE; + while (*s) { + if (*s == DEFAULT_LIST) { + /* Divert to the default list */ + indefault = TRUE; + stmp = ++s; + s = stdSubdirs; + } + len = strlen(*s); + if (**s && (*s)[len - 1] != '/') { + slash = "/"; + len++; + } else + slash = ""; + len += oslen + 2; + if (!(subdirs[i] = malloc(len))) { + while (--i >= 0) + free(subdirs[i]); + free(subdirs); + if (tmp_subdirlist) + free(tmp_subdirlist); + return NULL; + } + /* tack on the OS name */ + sprintf(subdirs[i], "%s%s%s/", *s, slash, osname); + i++; + /* path as given */ + subdirs[i] = xstrdup(*s); + i++; + s++; + if (indefault && !s) { + /* revert back to the main list */ + indefault = FALSE; + s = stmp; + } + } + subdirs[i] = NULL; + } + if (tmp_subdirlist) + free(tmp_subdirlist); + return (const char **)subdirs; +} + +static void +FreeSubdirs(const char **subdirs) +{ + const char **s; + + if (subdirs) { + for (s = subdirs; *s; s++) + free(*s); + free(subdirs); + } +} + +static char * +FindModuleInSubdir(const char *dirpath, const char *module) +{ + struct dirent *direntry = NULL; + DIR *dir = NULL; + char *ret = NULL, tmpBuf[PATH_MAX]; + struct stat stat_buf; + + dir = opendir(dirpath); + if (!dir) + return NULL; + + while ((direntry = readdir(dir))) { + if (direntry->d_name[0] == '.') + continue; + snprintf(tmpBuf, PATH_MAX, "%s%s/", dirpath, direntry->d_name); + /* the stat with the appended / fails for normal files, + and works for sub dirs fine, looks a bit strange in strace + but does seem to work */ + if ((stat(tmpBuf, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) { + if ((ret = FindModuleInSubdir(tmpBuf, module))) + break; + continue; + } + + snprintf(tmpBuf, PATH_MAX, "lib%s.so", module); + if (strcmp(direntry->d_name, tmpBuf) == 0) { + ret = malloc(strlen(tmpBuf) + strlen(dirpath) + 2); + sprintf(ret, "%s%s", dirpath, tmpBuf); + break; + } + + snprintf(tmpBuf, PATH_MAX, "%s_drv.so", module); + if (strcmp(direntry->d_name, tmpBuf) == 0) { + ret = malloc(strlen(tmpBuf) + strlen(dirpath) + 2); + sprintf(ret, "%s%s", dirpath, tmpBuf); + break; + } + + snprintf(tmpBuf, PATH_MAX, "%s.so", module); + if (strcmp(direntry->d_name, tmpBuf) == 0) { + ret = malloc(strlen(tmpBuf) + strlen(dirpath) + 2); + sprintf(ret, "%s%s", dirpath, tmpBuf); + break; + } + } + + closedir(dir); + return ret; +} + +static char * +FindModule(const char *module, const char *dirname, const char **subdirlist, + PatternPtr patterns) +{ + char buf[PATH_MAX + 1]; + char *dirpath = NULL; + char *name = NULL; + int dirlen; + const char **subdirs = NULL; + const char **s; + + dirpath = (char *)dirname; + if (strlen(dirpath) > PATH_MAX) + return NULL; + + subdirs = InitSubdirs(subdirlist); + if (!subdirs) + return NULL; + + for (s = subdirs; *s; s++) { + if ((dirlen = strlen(dirpath) + strlen(*s)) > PATH_MAX) + continue; + strcpy(buf, dirpath); + strcat(buf, *s); + if ((name = FindModuleInSubdir(buf, module))) + break; + } + + FreeSubdirs(subdirs); + if (dirpath != dirname) + free(dirpath); + + return name; +} + +char ** +LoaderListDirs(const char **subdirlist, const char **patternlist) +{ + char buf[PATH_MAX + 1]; + char **pathlist; + char **elem; + const char **subdirs; + const char **s; + PatternPtr patterns; + PatternPtr p; + DIR *d; + struct dirent *dp; + regmatch_t match[2]; + struct stat stat_buf; + int len, dirlen; + char *fp; + char **listing = NULL; + char **save; + int n = 0; + + if (!(pathlist = InitPathList(NULL))) + return NULL; + if (!(subdirs = InitSubdirs(subdirlist))) { + FreePathList(pathlist); + return NULL; + } + if (!(patterns = InitPatterns(patternlist))) { + FreePathList(pathlist); + FreeSubdirs(subdirs); + return NULL; + } + + for (elem = pathlist; *elem; elem++) { + for (s = subdirs; *s; s++) { + if ((dirlen = strlen(*elem) + strlen(*s)) > PATH_MAX) + continue; + strcpy(buf, *elem); + strcat(buf, *s); + fp = buf + dirlen; + if (stat(buf, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode) && + (d = opendir(buf))) { + if (buf[dirlen - 1] != '/') { + buf[dirlen++] = '/'; + fp++; + } + while ((dp = readdir(d))) { + if (dirlen + strlen(dp->d_name) > PATH_MAX) + continue; + strcpy(fp, dp->d_name); + if (!(stat(buf, &stat_buf) == 0 && + S_ISREG(stat_buf.st_mode))) + continue; + for (p = patterns; p->pattern; p++) { + if (regexec(&p->rex, dp->d_name, 2, match, 0) == 0 && + match[1].rm_so != -1) { + len = match[1].rm_eo - match[1].rm_so; + save = listing; + listing = realloc(listing, + (n + 2) * sizeof(char *)); + if (!listing) { + if (save) { + save[n] = NULL; + FreeStringList(save); + } + FreePathList(pathlist); + FreeSubdirs(subdirs); + FreePatterns(patterns); + return NULL; + } + listing[n] = malloc(len + 1); + if (!listing[n]) { + FreeStringList(listing); + FreePathList(pathlist); + FreeSubdirs(subdirs); + FreePatterns(patterns); + return NULL; + } + strncpy(listing[n], dp->d_name + match[1].rm_so, + len); + listing[n][len] = '\0'; + n++; + break; + } + } + } + closedir(d); + } + } + } + if (listing) + listing[n] = NULL; + return listing; +} + +void +LoaderFreeDirList(char **list) +{ + FreeStringList(list); +} + +static Bool +CheckVersion(const char *module, XF86ModuleVersionInfo * data, + const XF86ModReqInfo * req) +{ + int vercode[4]; + char verstr[4]; + long ver = data->xf86version; + MessageType errtype; + + xf86Msg(X_INFO, "Module %s: vendor=\"%s\"\n", + data->modname ? data->modname : "UNKNOWN!", + data->vendor ? data->vendor : "UNKNOWN!"); + + /* Check for the different scheme used in XFree86 4.0.x releases: + * ((((((((major << 7) | minor) << 7) | subminor) << 5) | beta) << 5) | alpha) + * Since it wasn't used in 4.1.0 or later, limit to versions in the 4.0.x + * range, which limits the overlap with the new version scheme to conflicts + * with 6.71.8.764 through 6.72.39.934. + */ + if ((ver > (4 << 24)) && (ver < ( (4 << 24) + (1 << 17)))) { + /* 4.0.x and earlier */ + verstr[1] = verstr[3] = 0; + verstr[2] = (ver & 0x1f) ? (ver & 0x1f) + 'a' - 1 : 0; + ver >>= 5; + verstr[0] = (ver & 0x1f) ? (ver & 0x1f) + 'A' - 1 : 0; + ver >>= 5; + vercode[2] = ver & 0x7f; + ver >>= 7; + vercode[1] = ver & 0x7f; + ver >>= 7; + vercode[0] = ver; + xf86ErrorF("\tcompiled for %d.%d", vercode[0], vercode[1]); + if (vercode[2] != 0) + xf86ErrorF(".%d", vercode[2]); + xf86ErrorF("%s%s, module version = %d.%d.%d\n", verstr, verstr + 2, + data->majorversion, data->minorversion, data->patchlevel); + } else { + vercode[0] = ver / 10000000; + vercode[1] = (ver / 100000) % 100; + vercode[2] = (ver / 1000) % 100; + vercode[3] = ver % 1000; + xf86ErrorF("\tcompiled for %d.%d.%d", vercode[0], vercode[1], + vercode[2]); + if (vercode[3] != 0) + xf86ErrorF(".%d", vercode[3]); + xf86ErrorF(", module version = %d.%d.%d\n", data->majorversion, + data->minorversion, data->patchlevel); + } + + if (data->moduleclass) + xf86ErrorFVerb(2, "\tModule class: %s\n", data->moduleclass); + + ver = -1; + if (data->abiclass) { + int abimaj, abimin; + int vermaj, vermin; + + if (!strcmp(data->abiclass, ABI_CLASS_ANSIC)) + ver = LoaderVersionInfo.ansicVersion; + else if (!strcmp(data->abiclass, ABI_CLASS_VIDEODRV)) + ver = LoaderVersionInfo.videodrvVersion; + else if (!strcmp(data->abiclass, ABI_CLASS_XINPUT)) + ver = LoaderVersionInfo.xinputVersion; + else if (!strcmp(data->abiclass, ABI_CLASS_EXTENSION)) + ver = LoaderVersionInfo.extensionVersion; + else if (!strcmp(data->abiclass, ABI_CLASS_FONT)) + ver = LoaderVersionInfo.fontVersion; + + abimaj = GET_ABI_MAJOR(data->abiversion); + abimin = GET_ABI_MINOR(data->abiversion); + xf86ErrorFVerb(2, "\tABI class: %s, version %d.%d\n", + data->abiclass, abimaj, abimin); + if (ver != -1) { + vermaj = GET_ABI_MAJOR(ver); + vermin = GET_ABI_MINOR(ver); + if (abimaj != vermaj) { + if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) + errtype = X_WARNING; + else + errtype = X_ERROR; + xf86MsgVerb(errtype, 0, + "module ABI major version (%d) doesn't" + " match the server's version (%d)\n", + abimaj, vermaj); + if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)) + return FALSE; + } else if (abimin > vermin) { + if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL) + errtype = X_WARNING; + else + errtype = X_ERROR; + xf86MsgVerb(errtype, 0, + "module ABI minor version (%d) is " + "newer than the server's version " + "(%d)\n", abimin, vermin); + if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)) + return FALSE; + } + } + } + + /* Check against requirements that the caller has specified */ + if (req) { + if (req->majorversion != MAJOR_UNSPEC) { + if (data->majorversion != req->majorversion) { + xf86MsgVerb(X_WARNING, 2, "module major version (%d) " + "doesn't match required major version (%d)\n", + data->majorversion, req->majorversion); + return FALSE; + } else if (req->minorversion != MINOR_UNSPEC) { + if (data->minorversion < req->minorversion) { + xf86MsgVerb(X_WARNING, 2, "module minor version (%d) " + "is less than the required minor version (%d)\n", + data->minorversion, req->minorversion); + return FALSE; + } else if (data->minorversion == req->minorversion && + req->patchlevel != PATCH_UNSPEC) { + if (data->patchlevel < req->patchlevel) { + xf86MsgVerb(X_WARNING, 2, "module patch level (%d) " + "is less than the required patch level (%d)\n", + data->patchlevel, req->patchlevel); + return FALSE; + } + } + } + } + if (req->moduleclass) { + if (!data->moduleclass || + strcmp(req->moduleclass, data->moduleclass)) { + xf86MsgVerb(X_WARNING, 2, "Module class (%s) doesn't match " + "the required class (%s)\n", + data->moduleclass ? data->moduleclass : "", + req->moduleclass); + return FALSE; + } + } else if (req->abiclass != ABI_CLASS_NONE) { + if (!data->abiclass || strcmp(req->abiclass, data->abiclass)) { + xf86MsgVerb(X_WARNING, 2, "ABI class (%s) doesn't match the " + "required ABI class (%s)\n", + data->abiclass ? data->abiclass : "", + req->abiclass); + return FALSE; + } + } + if ((req->abiclass != ABI_CLASS_NONE) && + req->abiversion != ABI_VERS_UNSPEC) { + int reqmaj, reqmin, maj, min; + + reqmaj = GET_ABI_MAJOR(req->abiversion); + reqmin = GET_ABI_MINOR(req->abiversion); + maj = GET_ABI_MAJOR(data->abiversion); + min = GET_ABI_MINOR(data->abiversion); + if (maj != reqmaj) { + xf86MsgVerb(X_WARNING, 2, "ABI major version (%d) doesn't " + "match the required ABI major version (%d)\n", + maj, reqmaj); + return FALSE; + } + /* XXX Maybe this should be the other way around? */ + if (min > reqmin) { + xf86MsgVerb(X_WARNING, 2, "module ABI minor version (%d) " + "is newer than that available (%d)\n", min, reqmin); + return FALSE; + } + } + } + return TRUE; +} + +static ModuleDescPtr +AddSibling(ModuleDescPtr head, ModuleDescPtr new) +{ + new->sib = head; + return (new); +} + +pointer +LoadSubModule(pointer _parent, const char *module, + const char **subdirlist, const char **patternlist, + pointer options, const XF86ModReqInfo * modreq, + int *errmaj, int *errmin) +{ + ModuleDescPtr submod; + ModuleDescPtr parent = (ModuleDescPtr)_parent; + + xf86MsgVerb(X_INFO, 3, "Loading sub module \"%s\"\n", module); + + if (PathIsAbsolute(module)) { + xf86Msg(X_ERROR, + "LoadSubModule: Absolute module path not permitted: \"%s\"\n", + module); + if (errmaj) + *errmaj = LDR_BADUSAGE; + if (errmin) + *errmin = 0; + return NULL; + } + + submod = doLoadModule(module, NULL, subdirlist, patternlist, options, + modreq, errmaj, errmin, LD_FLAG_GLOBAL); + if (submod && submod != (ModuleDescPtr) 1) { + parent->child = AddSibling(parent->child, submod); + submod->parent = parent; + } + return submod; +} + +static ModuleDescPtr +NewModuleDesc(const char *name) +{ + ModuleDescPtr mdp = malloc(sizeof(ModuleDesc)); + + if (mdp) { + mdp->child = NULL; + mdp->sib = NULL; + mdp->parent = NULL; + mdp->name = xstrdup(name); + mdp->handle = -1; + mdp->SetupProc = NULL; + mdp->TearDownProc = NULL; + mdp->TearDownData = NULL; + } + + return (mdp); +} + +ModuleDescPtr +DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent) +{ + ModuleDescPtr ret; + + if (!mod) + return NULL; + + ret = NewModuleDesc(mod->name); + if (ret == NULL) + return NULL; + + if (LoaderHandleOpen(mod->handle) == -1) + return NULL; + + ret->handle = mod->handle; + ret->SetupProc = mod->SetupProc; + ret->TearDownProc = mod->TearDownProc; + ret->TearDownData = NULL; + ret->child = DuplicateModule(mod->child, ret); + ret->sib = DuplicateModule(mod->sib, parent); + ret->parent = parent; + ret->VersionInfo = mod->VersionInfo; + + return ret; +} + +static const char *compiled_in_modules[] = { + "ddc", + "i2c", + "ramdac", + NULL +}; + +static ModuleDescPtr +doLoadModule(const char *module, const char *path, const char **subdirlist, + const char **patternlist, pointer options, + const XF86ModReqInfo * modreq, + int *errmaj, int *errmin, int flags) +{ + XF86ModuleData *initdata = NULL; + char **pathlist = NULL; + char *found = NULL; + char *name = NULL; + char **path_elem = NULL; + char *p = NULL; + ModuleDescPtr ret = NULL; + int wasLoaded = 0; + PatternPtr patterns = NULL; + int noncanonical = 0; + char *m = NULL; + const char **cim; + + xf86MsgVerb(X_INFO, 3, "LoadModule: \"%s\"", module); + + patterns = InitPatterns(patternlist); + name = LoaderGetCanonicalName(module, patterns); + noncanonical = (name && strcmp(module, name) != 0); + if (noncanonical) { + xf86ErrorFVerb(3, " (%s)\n", name); + xf86MsgVerb(X_WARNING, 1, + "LoadModule: given non-canonical module name \"%s\"\n", + module); + m = name; + } else { + xf86ErrorFVerb(3, "\n"); + m = (char *)module; + } + + for (cim = compiled_in_modules; *cim; cim++) + if (!strcmp (m, *cim)) + { + xf86MsgVerb(X_INFO, 3, "Module \"%s\" already built-in\n", m); + ret = (ModuleDescPtr) 1; + goto LoadModule_exit; + } + + if (!name) { + if (errmaj) + *errmaj = LDR_BADUSAGE; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + ret = NewModuleDesc(name); + if (!ret) { + if (errmaj) + *errmaj = LDR_NOMEM; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + + pathlist = InitPathList(path); + if (!pathlist) { + /* This could be a malloc failure too */ + if (errmaj) + *errmaj = LDR_BADUSAGE; + if (errmin) + *errmin = 1; + goto LoadModule_fail; + } + + /* + * if the module name is not a full pathname, we need to + * check the elements in the path + */ + if (PathIsAbsolute(module)) + found = xstrdup(module); + path_elem = pathlist; + while (!found && *path_elem != NULL) { + found = FindModule(m, *path_elem, subdirlist, patterns); + path_elem++; + /* + * When the module name isn't the canonical name, search for the + * former if no match was found for the latter. + */ + if (!*path_elem && m == name) { + path_elem = pathlist; + m = (char *)module; + } + } + + /* + * did we find the module? + */ + if (!found) { + xf86Msg(X_WARNING, "Warning, couldn't open module %s\n", module); + if (errmaj) + *errmaj = LDR_NOENT; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + ret->handle = LoaderOpen(found, name, 0, + errmaj, errmin, &wasLoaded, flags); + if (ret->handle < 0) + goto LoadModule_fail; + + /* drop any explicit suffix from the module name */ + p = strchr(name, '.'); + if (p) + *p = '\0'; + + /* + * now check if the special data object ModuleData is + * present. + */ + p = malloc(strlen(name) + strlen("ModuleData") + 1); + if (!p) { + if (errmaj) + *errmaj = LDR_NOMEM; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + strcpy(p, name); + strcat(p, "ModuleData"); + initdata = LoaderSymbol(p); + if (initdata) { + ModuleSetupProc setup; + ModuleTearDownProc teardown; + XF86ModuleVersionInfo *vers; + + vers = initdata->vers; + setup = initdata->setup; + teardown = initdata->teardown; + + if (!wasLoaded) { + if (vers) { + if (!CheckVersion(module, vers, modreq)) { + if (errmaj) + *errmaj = LDR_MISMATCH; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + } else { + xf86Msg(X_ERROR, + "LoadModule: Module %s does not supply" + " version information\n", module); + if (errmaj) + *errmaj = LDR_INVALID; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + } + if (setup) + ret->SetupProc = setup; + if (teardown) + ret->TearDownProc = teardown; + ret->VersionInfo = vers; + } else { + /* No initdata is OK for external modules */ + if (options == EXTERN_MODULE) + goto LoadModule_exit; + + /* no initdata, fail the load */ + xf86Msg(X_ERROR, "LoadModule: Module %s does not have a %s " + "data object.\n", module, p); + if (errmaj) + *errmaj = LDR_INVALID; + if (errmin) + *errmin = 0; + goto LoadModule_fail; + } + if (ret->SetupProc) { + ret->TearDownData = ret->SetupProc(ret, options, errmaj, errmin); + if (!ret->TearDownData) { + goto LoadModule_fail; + } + } else if (options) { + xf86Msg(X_WARNING, "Module Options present, but no SetupProc " + "available for %s\n", module); + } + goto LoadModule_exit; + + LoadModule_fail: + UnloadModule(ret); + ret = NULL; + + LoadModule_exit: + FreePathList(pathlist); + FreePatterns(patterns); + free(found); + free(name); + free(p); + + return ret; +} + +/* + * LoadModule: load a module + * + * module The module name. Normally this is not a filename but the + * module's "canonical name. A full pathname is, however, + * also accepted. + * path A comma separated list of module directories. + * subdirlist A NULL terminated list of subdirectories to search. When + * NULL, the default "stdSubdirs" list is used. The default + * list is also substituted for entries with value DEFAULT_LIST. + * patternlist A NULL terminated list of regular expressions used to find + * module filenames. Each regex should contain exactly one + * subexpression that corresponds to the canonical module name. + * When NULL, the default "stdPatterns" list is used. The + * default list is also substituted for entries with value + * DEFAULT_LIST. + * options A NULL terminated list of Options that are passed to the + * module's SetupProc function. + * modreq An optional XF86ModReqInfo* containing + * version/ABI/vendor-ABI requirements to check for when + * loading the module. The following fields of the + * XF86ModReqInfo struct are checked: + * majorversion - must match the module's majorversion exactly + * minorversion - the module's minorversion must be >= this + * patchlevel - the module's minorversion.patchlevel must be + * >= this. Patchlevel is ignored when + * minorversion is not set. + * abiclass - (string) must match the module's abiclass + * abiversion - must be consistent with the module's + * abiversion (major equal, minor no older) + * moduleclass - string must match the module's moduleclass + * string + * "don't care" values are ~0 for numbers, and NULL for strings + * errmaj Major error return. + * errmin Minor error return. + * + */ +ModuleDescPtr +LoadModule(const char *module, const char *path, const char **subdirlist, + const char **patternlist, pointer options, + const XF86ModReqInfo * modreq, int *errmaj, int *errmin) +{ + return doLoadModule(module, path, subdirlist, patternlist, options, + modreq, errmaj, errmin, LD_FLAG_GLOBAL); +} + +void +UnloadModule(pointer mod) +{ + UnloadModuleOrDriver((ModuleDescPtr)mod); +} + +static void +UnloadModuleOrDriver(ModuleDescPtr mod) +{ + if (mod == (ModuleDescPtr) 1) + return; + + if (mod == NULL || mod->name == NULL) + return; + + xf86MsgVerb(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name); + + if ((mod->TearDownProc) && (mod->TearDownData)) + mod->TearDownProc(mod->TearDownData); + LoaderUnload(mod->handle); + + if (mod->child) + UnloadModuleOrDriver(mod->child); + if (mod->sib) + UnloadModuleOrDriver(mod->sib); + free(mod->name); + free(mod); +} + +void +UnloadSubModule(pointer _mod) +{ + ModuleDescPtr mod = (ModuleDescPtr)_mod; + + if (mod == NULL || mod->name == NULL) + return; + + xf86MsgVerb(X_INFO, 3, "UnloadSubModule: \"%s\"\n", mod->name); + + if ((mod->TearDownProc) && (mod->TearDownData)) + mod->TearDownProc(mod->TearDownData); + LoaderUnload(mod->handle); + + RemoveChild(mod); + + if (mod->child) + UnloadModuleOrDriver(mod->child); + + free(mod->name); + free(mod); +} + +static void +RemoveChild(ModuleDescPtr child) +{ + ModuleDescPtr mdp; + ModuleDescPtr prevsib; + ModuleDescPtr parent; + + if (!child->parent) + return; + + parent = child->parent; + if (parent->child == child) { + parent->child = child->sib; + return; + } + + prevsib = parent->child; + mdp = prevsib->sib; + while (mdp && mdp != child) { + prevsib = mdp; + mdp = mdp->sib; + } + if (mdp == child) + prevsib->sib = child->sib; + return; +} + +void +LoaderErrorMsg(const char *name, const char *modname, int errmaj, int errmin) +{ + const char *msg; + MessageType type = X_ERROR; + + switch (errmaj) { + case LDR_NOERROR: + msg = "no error"; + break; + case LDR_NOMEM: + msg = "out of memory"; + break; + case LDR_NOENT: + msg = "module does not exist"; + break; + case LDR_NOSUBENT: + msg = "a required submodule could not be loaded"; + break; + case LDR_NOSPACE: + msg = "too many modules"; + break; + case LDR_NOMODOPEN: + msg = "open failed"; + break; + case LDR_UNKTYPE: + msg = "unknown module type"; + break; + case LDR_NOLOAD: + msg = "loader failed"; + break; + case LDR_ONCEONLY: + msg = "already loaded"; + type = X_INFO; + break; + case LDR_NOPORTOPEN: + msg = "port open failed"; + break; + case LDR_NOHARDWARE: + msg = "no hardware found"; + break; + case LDR_MISMATCH: + msg = "module requirement mismatch"; + break; + case LDR_BADUSAGE: + msg = "invalid argument(s) to LoadModule()"; + break; + case LDR_INVALID: + msg = "invalid module"; + break; + case LDR_BADOS: + msg = "module doesn't support this OS"; + break; + case LDR_MODSPECIFIC: + msg = "module-specific error"; + break; + default: + msg = "unknown error"; + } + if (name) + xf86Msg(type, "%s: Failed to load module \"%s\" (%s, %d)\n", + name, modname, msg, errmin); + else + xf86Msg(type, "Failed to load module \"%s\" (%s, %d)\n", + modname, msg, errmin); +} + +/* Given a module path or file name, return the module's canonical name */ +static char * +LoaderGetCanonicalName(const char *modname, PatternPtr patterns) +{ + char *str; + const char *s; + int len; + PatternPtr p; + regmatch_t match[2]; + + /* Strip off any leading path */ + s = strrchr(modname, '/'); + if (s == NULL) + s = modname; + else + s++; + + /* Find the first regex that is matched */ + for (p = patterns; p->pattern; p++) + if (regexec(&p->rex, s, 2, match, 0) == 0 && match[1].rm_so != -1) { + len = match[1].rm_eo - match[1].rm_so; + str = malloc(len + 1); + if (!str) + return NULL; + strncpy(str, s + match[1].rm_so, len); + str[len] = '\0'; + return str; + } + + /* If there is no match, return the whole name minus the leading path */ + return xstrdup(s); +} + +/* + * Return the module version information. + */ +unsigned long +LoaderGetModuleVersion(ModuleDescPtr mod) +{ + if (!mod || mod == (ModuleDescPtr) 1 || !mod->VersionInfo) + return 0; + + return MODULE_VERSION_NUMERIC(mod->VersionInfo->majorversion, + mod->VersionInfo->minorversion, + mod->VersionInfo->patchlevel); +} diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index 1ccaffc10..9dbeea8a5 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -1,3201 +1,3201 @@ -/* - * Copyright © 2006 Keith Packard - * Copyright © 2008 Red Hat, Inc. - * - * 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#else -#ifdef HAVE_CONFIG_H -#include -#endif -#endif - -#include -#include -#include - -#include "xf86.h" -#include "xf86DDC.h" -#include "xf86Crtc.h" -#include "xf86Modes.h" -#include "xf86Priv.h" -#include "xf86RandR12.h" -#include "X11/extensions/render.h" -#include "X11/extensions/dpmsconst.h" -#include "X11/Xatom.h" -#include "picturestr.h" - -#include "xf86xv.h" - -/* - * Initialize xf86CrtcConfig structure - */ - -int xf86CrtcConfigPrivateIndex = -1; - -void -xf86CrtcConfigInit (ScrnInfoPtr scrn, - const xf86CrtcConfigFuncsRec *funcs) -{ - xf86CrtcConfigPtr config; - - if (xf86CrtcConfigPrivateIndex == -1) - xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); - - config->funcs = funcs; - - scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; -} - -void -xf86CrtcSetSizeRange (ScrnInfoPtr scrn, - int minWidth, int minHeight, - int maxWidth, int maxHeight) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->minWidth = minWidth; - config->minHeight = minHeight; - config->maxWidth = maxWidth; - config->maxHeight = maxHeight; -} - -/* - * Crtc functions - */ -xf86CrtcPtr -xf86CrtcCreate (ScrnInfoPtr scrn, - const xf86CrtcFuncsRec *funcs) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc, *crtcs; - - crtc = xcalloc (sizeof (xf86CrtcRec), 1); - if (!crtc) - return NULL; - crtc->version = XF86_CRTC_VERSION; - crtc->scrn = scrn; - crtc->funcs = funcs; -#ifdef RANDR_12_INTERFACE - crtc->randr_crtc = NULL; -#endif - crtc->rotation = RR_Rotate_0; - crtc->desiredRotation = RR_Rotate_0; - pixman_transform_init_identity (&crtc->crtc_to_framebuffer); - pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); - pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); - crtc->filter = NULL; - crtc->params = NULL; - crtc->nparams = 0; - crtc->filter_width = 0; - crtc->filter_height = 0; - crtc->transform_in_use = FALSE; - crtc->transformPresent = FALSE; - crtc->desiredTransformPresent = FALSE; - memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); - - /* Preallocate gamma at a sensible size. */ - crtc->gamma_size = 256; - crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16)); - if (!crtc->gamma_red) { - xfree (crtc); - return NULL; - } - crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; - crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; - - if (xf86_config->crtc) - crtcs = xrealloc (xf86_config->crtc, - (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); - else - crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); - if (!crtcs) - { - xfree (crtc); - return NULL; - } - xf86_config->crtc = crtcs; - xf86_config->crtc[xf86_config->num_crtc++] = crtc; - return crtc; -} - -void -xf86CrtcDestroy (xf86CrtcPtr crtc) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); - int c; - - (*crtc->funcs->destroy) (crtc); - for (c = 0; c < xf86_config->num_crtc; c++) - if (xf86_config->crtc[c] == crtc) - { - memmove (&xf86_config->crtc[c], - &xf86_config->crtc[c+1], - ((xf86_config->num_crtc - (c + 1)) * sizeof(void*))); - xf86_config->num_crtc--; - break; - } - if (crtc->params) - xfree (crtc->params); - free(crtc->gamma_red); - xfree (crtc); -} - - -/** - * Return whether any outputs are connected to the specified pipe - */ - -Bool -xf86CrtcInUse (xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o; - - for (o = 0; o < xf86_config->num_output; o++) - if (xf86_config->output[o]->crtc == crtc) - return TRUE; - return FALSE; -} - -void -xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen) -{ - int subpixel_order = SubPixelUnknown; - Bool has_none = FALSE; - ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - - if (output->crtc == crtc) - { - switch (output->subpixel_order) { - case SubPixelNone: - has_none = TRUE; - break; - case SubPixelUnknown: - break; - default: - subpixel_order = output->subpixel_order; - break; - } - } - if (subpixel_order != SubPixelUnknown) - break; - } - if (subpixel_order != SubPixelUnknown) - { - static const int circle[4] = { - SubPixelHorizontalRGB, - SubPixelVerticalRGB, - SubPixelHorizontalBGR, - SubPixelVerticalBGR, - }; - int rotate; - int c; - for (rotate = 0; rotate < 4; rotate++) - if (crtc->rotation & (1 << rotate)) - break; - for (c = 0; c < 4; c++) - if (circle[c] == subpixel_order) - break; - c = (c + rotate) & 0x3; - if ((crtc->rotation & RR_Reflect_X) && !(c & 1)) - c ^= 2; - if ((crtc->rotation & RR_Reflect_Y) && (c & 1)) - c ^= 2; - subpixel_order = circle[c]; - break; - } - } - if (subpixel_order == SubPixelUnknown && has_none) - subpixel_order = SubPixelNone; - PictureSetSubpixelOrder (pScreen, subpixel_order); -} - -/** - * Sets the given video mode on the given crtc - */ -Bool -xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, - RRTransformPtr transform, int x, int y) -{ - ScrnInfoPtr scrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - Bool ret = FALSE; - Bool didLock = FALSE; - DisplayModePtr adjusted_mode; - DisplayModeRec saved_mode; - int saved_x, saved_y; - Rotation saved_rotation; - RRTransformRec saved_transform; - Bool saved_transform_present; - - crtc->enabled = xf86CrtcInUse (crtc); - - /* We only hit this if someone explicitly sends a "disabled" modeset. */ - if (!crtc->enabled) - { - /* Check everything for stuff that should be off. */ - xf86DisableUnusedFunctions(scrn); - return TRUE; - } - - adjusted_mode = xf86DuplicateMode(mode); - - - saved_mode = crtc->mode; - saved_x = crtc->x; - saved_y = crtc->y; - saved_rotation = crtc->rotation; - if (crtc->transformPresent) { - RRTransformInit (&saved_transform); - RRTransformCopy (&saved_transform, &crtc->transform); - } - saved_transform_present = crtc->transformPresent; - - /* Update crtc values up front so the driver can rely on them for mode - * setting. - */ - crtc->mode = *mode; - crtc->x = x; - crtc->y = y; - crtc->rotation = rotation; - if (transform) { - RRTransformCopy (&crtc->transform, transform); - crtc->transformPresent = TRUE; - } else - crtc->transformPresent = FALSE; - - if (crtc->funcs->set_mode_major) { - ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y); - goto done; - } - - didLock = crtc->funcs->lock (crtc); - /* Pass our mode to the outputs and the CRTC to give them a chance to - * adjust it according to limitations or output properties, and also - * a chance to reject the mode entirely. - */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { - goto done; - } - } - - if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { - goto done; - } - - if (!xf86CrtcRotate (crtc)) - goto done; - - /* Prepare the outputs and CRTCs before setting the mode. */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - /* Disable the output as the first thing we do. */ - output->funcs->prepare(output); - } - - crtc->funcs->prepare(crtc); - - /* Set up the DPLL and any output state that needs to adjust or depend - * on the DPLL. - */ - crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y); - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->mode_set(output, mode, adjusted_mode); - } - - /* Only upload when needed, to avoid unneeded delays. */ - if (!crtc->active && crtc->funcs->gamma_set) - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); - - /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ - crtc->funcs->commit(crtc); - for (i = 0; i < xf86_config->num_output; i++) - { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->commit(output); - } - - ret = TRUE; - -done: - if (ret) { - crtc->active = TRUE; - if (scrn->pScreen) - xf86CrtcSetScreenSubpixelOrder (scrn->pScreen); - } else { - crtc->x = saved_x; - crtc->y = saved_y; - crtc->rotation = saved_rotation; - crtc->mode = saved_mode; - if (saved_transform_present) - RRTransformCopy (&crtc->transform, &saved_transform); - crtc->transformPresent = saved_transform_present; - } - - if (adjusted_mode->name) - xfree(adjusted_mode->name); - xfree(adjusted_mode); - - if (didLock) - crtc->funcs->unlock (crtc); - - return ret; -} - -/** - * Sets the given video mode on the given crtc, but without providing - * a transform - */ -Bool -xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, - int x, int y) -{ - return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y); -} - -/** - * Pans the screen, does not change the mode - */ -void -xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y) -{ - crtc->x = x; - crtc->y = y; - if (crtc->funcs->set_origin) { - if (!xf86CrtcRotate (crtc)) - return; - crtc->funcs->set_origin (crtc, x, y); - } - else - xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y); -} - -/* - * Output functions - */ - -extern XF86ConfigPtr xf86configptr; - -typedef enum { - OPTION_PREFERRED_MODE, - OPTION_POSITION, - OPTION_BELOW, - OPTION_RIGHT_OF, - OPTION_ABOVE, - OPTION_LEFT_OF, - OPTION_ENABLE, - OPTION_DISABLE, - OPTION_MIN_CLOCK, - OPTION_MAX_CLOCK, - OPTION_IGNORE, - OPTION_ROTATE, - OPTION_PANNING, - OPTION_PRIMARY, -} OutputOpts; - -static OptionInfoRec xf86OutputOptions[] = { - {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, - {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, - {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, - {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, - {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, - {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, - {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, - {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, - {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, - {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, - {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE }, - {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE }, - {-1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -enum { - OPTION_MODEDEBUG, -}; - -static OptionInfoRec xf86DeviceOptions[] = { - {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE }, - {-1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -static void -xf86OutputSetMonitor (xf86OutputPtr output) -{ - char *option_name; - static const char monitor_prefix[] = "monitor-"; - char *monitor; - - if (!output->name) - return; - - if (output->options) - xfree (output->options); - - output->options = xnfalloc (sizeof (xf86OutputOptions)); - memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); - - option_name = xnfalloc (strlen (monitor_prefix) + - strlen (output->name) + 1); - strcpy (option_name, monitor_prefix); - strcat (option_name, output->name); - monitor = xf86findOptionValue (output->scrn->options, option_name); - if (!monitor) - monitor = output->name; - else - xf86MarkOptionUsedByName (output->scrn->options, option_name); - xfree (option_name); - output->conf_monitor = xf86findMonitor (monitor, - xf86configptr->conf_monitor_lst); - /* - * Find the monitor section of the screen and use that - */ - if (!output->conf_monitor && output->use_screen_monitor) - output->conf_monitor = xf86findMonitor (output->scrn->monitor->id, - xf86configptr->conf_monitor_lst); - if (output->conf_monitor) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s using monitor section %s\n", - output->name, output->conf_monitor->mon_identifier); - xf86ProcessOptions (output->scrn->scrnIndex, - output->conf_monitor->mon_option_lst, - output->options); - } - else - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s has no monitor section\n", - output->name); -} - -static Bool -xf86OutputEnabled (xf86OutputPtr output, Bool strict) -{ - Bool enable, disable; - - /* check to see if this output was enabled in the config file */ - if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s enabled by config file\n", output->name); - return TRUE; - } - /* or if this output was disabled in the config file */ - if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable) - { - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s disabled by config file\n", output->name); - return FALSE; - } - - /* If not, try to only light up the ones we know are connected */ - if (strict) { - enable = output->status == XF86OutputStatusConnected; - } - /* But if that fails, try to light up even outputs we're unsure of */ - else { - enable = output->status != XF86OutputStatusDisconnected; - } - - xf86DrvMsg (output->scrn->scrnIndex, X_INFO, - "Output %s %sconnected\n", output->name, enable ? "" : "dis"); - return enable; -} - -static Bool -xf86OutputIgnored (xf86OutputPtr output) -{ - return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE); -} - -static char *direction[4] = { - "normal", - "left", - "inverted", - "right" -}; - -static Rotation -xf86OutputInitialRotation (xf86OutputPtr output) -{ - char *rotate_name = xf86GetOptValString (output->options, - OPTION_ROTATE); - int i; - - if (!rotate_name) - return RR_Rotate_0; - - for (i = 0; i < 4; i++) - if (xf86nameCompare (direction[i], rotate_name) == 0) - return (1 << i); - return RR_Rotate_0; -} - -xf86OutputPtr -xf86OutputCreate (ScrnInfoPtr scrn, - const xf86OutputFuncsRec *funcs, - const char *name) -{ - xf86OutputPtr output, *outputs; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int len; - Bool primary; - - if (name) - len = strlen (name) + 1; - else - len = 0; - - output = xcalloc (sizeof (xf86OutputRec) + len, 1); - if (!output) - return NULL; - output->scrn = scrn; - output->funcs = funcs; - if (name) - { - output->name = (char *) (output + 1); - strcpy (output->name, name); - } - output->subpixel_order = SubPixelUnknown; - /* - * Use the old per-screen monitor section for the first output - */ - output->use_screen_monitor = (xf86_config->num_output == 0); -#ifdef RANDR_12_INTERFACE - output->randr_output = NULL; -#endif - if (name) - { - xf86OutputSetMonitor (output); - if (xf86OutputIgnored (output)) - { - xfree (output); - return FALSE; - } - } - - - if (xf86_config->output) - outputs = xrealloc (xf86_config->output, - (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); - else - outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); - if (!outputs) - { - xfree (output); - return NULL; - } - - xf86_config->output = outputs; - - if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary) - { - memmove(xf86_config->output + 1, xf86_config->output, - xf86_config->num_output * sizeof (xf86OutputPtr)); - xf86_config->output[0] = output; - } - else - { - xf86_config->output[xf86_config->num_output] = output; - } - - xf86_config->num_output++; - - return output; -} - -Bool -xf86OutputRename (xf86OutputPtr output, const char *name) -{ - int len = strlen(name) + 1; - char *newname = xalloc (len); - - if (!newname) - return FALSE; /* so sorry... */ - - strcpy (newname, name); - if (output->name && output->name != (char *) (output + 1)) - xfree (output->name); - output->name = newname; - xf86OutputSetMonitor (output); - if (xf86OutputIgnored (output)) - return FALSE; - return TRUE; -} - -void -xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor) -{ - if (use_screen_monitor != output->use_screen_monitor) - { - output->use_screen_monitor = use_screen_monitor; - xf86OutputSetMonitor (output); - } -} - -void -xf86OutputDestroy (xf86OutputPtr output) -{ - ScrnInfoPtr scrn = output->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - (*output->funcs->destroy) (output); - while (output->probed_modes) - xf86DeleteMode (&output->probed_modes, output->probed_modes); - for (o = 0; o < xf86_config->num_output; o++) - if (xf86_config->output[o] == output) - { - memmove (&xf86_config->output[o], - &xf86_config->output[o+1], - ((xf86_config->num_output - (o + 1)) * sizeof(void*))); - xf86_config->num_output--; - break; - } - if (output->name && output->name != (char *) (output + 1)) - xfree (output->name); - xfree (output); -} - -/* - * Called during CreateScreenResources to hook up RandR - */ -static Bool -xf86CrtcCreateScreenResources (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - screen->CreateScreenResources = config->CreateScreenResources; - - if (!(*screen->CreateScreenResources)(screen)) - return FALSE; - - if (!xf86RandR12CreateScreenResources (screen)) - return FALSE; - - return TRUE; -} - -/* - * Clean up config on server reset - */ -static Bool -xf86CrtcCloseScreen (int index, ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o, c; - - screen->CloseScreen = config->CloseScreen; - - xf86RotateCloseScreen (screen); - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->randr_output = NULL; - } - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->randr_crtc = NULL; - } - return screen->CloseScreen (index, screen); -} - -/* - * Called at ScreenInit time to set up - */ -#ifdef RANDR_13_INTERFACE -int -#else -Bool -#endif -xf86CrtcScreenInit (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - /* Rotation */ - xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); - xf86DisableRandR(); /* Disable old RandR extension support */ - xf86RandR12Init (screen); - - /* support all rotations if every crtc has the shadow alloc funcs */ - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) - break; - } - if (c == config->num_crtc) - { - xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | - RR_Rotate_180 | RR_Rotate_270 | - RR_Reflect_X | RR_Reflect_Y); - xf86RandR12SetTransformSupport (screen, TRUE); - } - else - { - xf86RandR12SetRotations (screen, RR_Rotate_0); - xf86RandR12SetTransformSupport (screen, FALSE); - } - - /* Wrap CreateScreenResources so we can initialize the RandR code */ - config->CreateScreenResources = screen->CreateScreenResources; - screen->CreateScreenResources = xf86CrtcCreateScreenResources; - - config->CloseScreen = screen->CloseScreen; - screen->CloseScreen = xf86CrtcCloseScreen; - -#ifdef XFreeXDGA - _xf86_di_dga_init_internal(screen); -#endif -#ifdef RANDR_13_INTERFACE - return RANDR_INTERFACE_VERSION; -#else - return TRUE; -#endif -} - -static DisplayModePtr -xf86DefaultMode (xf86OutputPtr output, int width, int height) -{ - DisplayModePtr target_mode = NULL; - DisplayModePtr mode; - int target_diff = 0; - int target_preferred = 0; - int mm_height; - - mm_height = output->mm_height; - if (!mm_height) - mm_height = (768 * 25.4) / DEFAULT_DPI; - /* - * Pick a mode closest to DEFAULT_DPI - */ - for (mode = output->probed_modes; mode; mode = mode->next) - { - int dpi; - int preferred = (((mode->type & M_T_PREFERRED) != 0) + - ((mode->type & M_T_USERPREF) != 0)); - int diff; - - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - /* yes, use VDisplay here, not xf86ModeHeight */ - dpi = (mode->VDisplay * 254) / (mm_height * 10); - diff = dpi - DEFAULT_DPI; - diff = diff < 0 ? -diff : diff; - if (target_mode == NULL || (preferred > target_preferred) || - (preferred == target_preferred && diff < target_diff)) - { - target_mode = mode; - target_diff = diff; - target_preferred = preferred; - } - } - return target_mode; -} - -static DisplayModePtr -xf86ClosestMode (xf86OutputPtr output, - DisplayModePtr match, Rotation match_rotation, - int width, int height) -{ - DisplayModePtr target_mode = NULL; - DisplayModePtr mode; - int target_diff = 0; - - /* - * Pick a mode closest to the specified mode - */ - for (mode = output->probed_modes; mode; mode = mode->next) - { - int dx, dy; - int diff; - - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - /* exact matches are preferred */ - if (output->initial_rotation == match_rotation && - xf86ModesEqual (mode, match)) - return mode; - - dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); - dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); - diff = dx * dx + dy * dy; - if (target_mode == NULL || diff < target_diff) - { - target_mode = mode; - target_diff = diff; - } - } - return target_mode; -} - -static DisplayModePtr -xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) -{ - DisplayModePtr mode; - - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (xf86ModeWidth (mode, output->initial_rotation) > width || - xf86ModeHeight (mode, output->initial_rotation) > height) - continue; - - if (mode->type & M_T_PREFERRED) - return mode; - } - return NULL; -} - -static DisplayModePtr -xf86OutputHasUserPreferredMode (xf86OutputPtr output) -{ - DisplayModePtr mode, first = output->probed_modes; - - for (mode = first; mode && mode->next != first; mode = mode->next) - if (mode->type & M_T_USERPREF) - return mode; - - return NULL; -} - -static int -xf86PickCrtcs (ScrnInfoPtr scrn, - xf86CrtcPtr *best_crtcs, - DisplayModePtr *modes, - int n, - int width, - int height) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c, o; - xf86OutputPtr output; - xf86CrtcPtr crtc; - xf86CrtcPtr *crtcs; - xf86CrtcPtr best_crtc; - int best_score; - int score; - int my_score; - - if (n == config->num_output) - return 0; - output = config->output[n]; - - /* - * Compute score with this output disabled - */ - best_crtcs[n] = NULL; - best_crtc = NULL; - best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); - if (modes[n] == NULL) - return best_score; - - crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr)); - if (!crtcs) - return best_score; - - my_score = 1; - /* Score outputs that are known to be connected higher */ - if (output->status == XF86OutputStatusConnected) - my_score++; - /* Score outputs with preferred modes higher */ - if (xf86OutputHasPreferredMode (output, width, height)) - my_score++; - /* - * Select a crtc for this output and - * then attempt to configure the remaining - * outputs - */ - for (c = 0; c < config->num_crtc; c++) - { - if ((output->possible_crtcs & (1 << c)) == 0) - continue; - - crtc = config->crtc[c]; - /* - * Check to see if some other output is - * using this crtc - */ - for (o = 0; o < n; o++) - if (best_crtcs[o] == crtc) - break; - if (o < n) - { - /* - * If the two outputs desire the same mode, - * see if they can be cloned - */ - if (xf86ModesEqual (modes[o], modes[n]) && - config->output[o]->initial_rotation == config->output[n]->initial_rotation && - config->output[o]->initial_x == config->output[n]->initial_x && - config->output[o]->initial_y == config->output[n]->initial_y) - { - if ((output->possible_clones & (1 << o)) == 0) - continue; /* nope, try next CRTC */ - } - else - continue; /* different modes, can't clone */ - } - crtcs[n] = crtc; - memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); - score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); - if (score > best_score) - { - best_crtc = crtc; - best_score = score; - memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); - } - } - xfree (crtcs); - return best_score; -} - - -/* - * Compute the virtual size necessary to place all of the available - * crtcs in the specified configuration. - * - * canGrow indicates that the driver can make the screen larger than its initial - * configuration. If FALSE, this function will enlarge the screen to include - * the largest available mode. - */ - -static void -xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp, - Bool canGrow) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int width = 0, height = 0; - int o; - int c; - int s; - - for (c = 0; c < config->num_crtc; c++) - { - int crtc_width = 0, crtc_height = 0; - xf86CrtcPtr crtc = config->crtc[c]; - - if (crtc->enabled) - { - crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation); - crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation); - } - if (!canGrow) { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - for (s = 0; s < config->num_crtc; s++) - if (output->possible_crtcs & (1 << s)) - { - DisplayModePtr mode; - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (mode->HDisplay > crtc_width) - crtc_width = mode->HDisplay; - if (mode->VDisplay > crtc_width) - crtc_width = mode->VDisplay; - if (mode->VDisplay > crtc_height) - crtc_height = mode->VDisplay; - if (mode->HDisplay > crtc_height) - crtc_height = mode->HDisplay; - } - } - } - } - if (crtc_width > width) - width = crtc_width; - if (crtc_height > height) - height = crtc_height; - } - if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; - if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; - if (config->minWidth && width < config->minWidth) width = config->minWidth; - if (config->minHeight && height < config->minHeight) height = config->minHeight; - *widthp = width; - *heightp = height; -} - -#define POSITION_UNSET -100000 - -/* - * check if the user configured any outputs at all - * with either a position or a relative setting or a mode. - */ -static Bool -xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - Bool user_conf = FALSE; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - char *position; - char *relative_name; - OutputOpts relation; - int r; - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; - - position = xf86GetOptValString (output->options, - OPTION_POSITION); - if (position) - user_conf = TRUE; - - relation = 0; - relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) - user_conf = TRUE; - - modes[o] = xf86OutputHasUserPreferredMode(output); - if (modes[o]) - user_conf = TRUE; - } - - return user_conf; -} - -static Bool -xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - int min_x, min_y; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->initial_x = output->initial_y = POSITION_UNSET; - } - - /* - * Loop until all outputs are set - */ - for (;;) - { - Bool any_set = FALSE; - Bool keep_going = FALSE; - - for (o = 0; o < config->num_output; o++) - { - static const OutputOpts relations[] = { - OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF - }; - xf86OutputPtr output = config->output[o]; - xf86OutputPtr relative; - char *relative_name; - char *position; - OutputOpts relation; - int r; - - if (output->initial_x != POSITION_UNSET) - continue; - position = xf86GetOptValString (output->options, - OPTION_POSITION); - /* - * Absolute position wins - */ - if (position) - { - int x, y; - if (sscanf (position, "%d %d", &x, &y) == 2) - { - output->initial_x = x; - output->initial_y = y; - } - else - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output %s position not of form \"x y\"\n", - output->name); - output->initial_x = output->initial_y = 0; - } - any_set = TRUE; - continue; - } - /* - * Next comes relative positions - */ - relation = 0; - relative_name = NULL; - for (r = 0; r < 4; r++) - { - relation = relations[r]; - relative_name = xf86GetOptValString (output->options, - relation); - if (relative_name) - break; - } - if (relative_name) - { - int or; - relative = NULL; - for (or = 0; or < config->num_output; or++) - { - xf86OutputPtr out_rel = config->output[or]; - XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; - - if (rel_mon) - { - if (xf86nameCompare (rel_mon->mon_identifier, - relative_name) == 0) - { - relative = config->output[or]; - break; - } - } - if (strcmp (out_rel->name, relative_name) == 0) - { - relative = config->output[or]; - break; - } - } - if (!relative) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Cannot position output %s relative to unknown output %s\n", - output->name, relative_name); - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - continue; - } - if (!modes[or]) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Cannot position output %s relative to output %s without modes\n", - output->name, relative_name); - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - continue; - } - if (relative->initial_x == POSITION_UNSET) - { - keep_going = TRUE; - continue; - } - output->initial_x = relative->initial_x; - output->initial_y = relative->initial_y; - switch (relation) { - case OPTION_BELOW: - output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation); - break; - case OPTION_RIGHT_OF: - output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); - break; - case OPTION_ABOVE: - if (modes[o]) - output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation); - break; - case OPTION_LEFT_OF: - if (modes[o]) - output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation); - break; - default: - break; - } - any_set = TRUE; - continue; - } - - /* Nothing set, just stick them at 0,0 */ - output->initial_x = 0; - output->initial_y = 0; - any_set = TRUE; - } - if (!keep_going) - break; - if (!any_set) - { - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - if (output->initial_x == POSITION_UNSET) - { - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output position loop. Moving %s to 0,0\n", - output->name); - output->initial_x = output->initial_y = 0; - break; - } - } - } - } - - /* - * normalize positions - */ - min_x = 1000000; - min_y = 1000000; - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - if (output->initial_x < min_x) - min_x = output->initial_x; - if (output->initial_y < min_y) - min_y = output->initial_y; - } - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->initial_x -= min_x; - output->initial_y -= min_y; - } - return TRUE; -} - -static void -xf86InitialPanning (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - char *panning = xf86GetOptValString (output->options, OPTION_PANNING); - int width, height, left, top; - int track_width, track_height, track_left, track_top; - int brdr[4]; - - memset (&output->initialTotalArea, 0, sizeof(BoxRec)); - memset (&output->initialTrackingArea, 0, sizeof(BoxRec)); - memset (output->initialBorder, 0, 4*sizeof(INT16)); - - if (! panning) - continue; - - switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", - &width, &height, &left, &top, - &track_width, &track_height, &track_left, &track_top, - &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { - case 12: - output->initialBorder[0] = brdr[0]; - output->initialBorder[1] = brdr[1]; - output->initialBorder[2] = brdr[2]; - output->initialBorder[3] = brdr[3]; - /* fall through */ - case 8: - output->initialTrackingArea.x1 = track_left; - output->initialTrackingArea.y1 = track_top; - output->initialTrackingArea.x2 = track_left + track_width; - output->initialTrackingArea.y2 = track_top + track_height; - /* fall through */ - case 4: - output->initialTotalArea.x1 = left; - output->initialTotalArea.y1 = top; - /* fall through */ - case 2: - output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; - output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; - break; - default: - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Broken panning specification '%s' for output %s in config file\n", - panning, output->name); - } - } -} - -/** Return - 0 + if a should be earlier, same or later than b in list - */ -static int -xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) -{ - int diff; - - diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); - if (diff) - return diff; - diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; - if (diff) - return diff; - diff = b->Clock - a->Clock; - return diff; -} - -/** - * Insertion sort input in-place and return the resulting head - */ -static DisplayModePtr -xf86SortModes (DisplayModePtr input) -{ - DisplayModePtr output = NULL, i, o, n, *op, prev; - - /* sort by preferred status and pixel area */ - while (input) - { - i = input; - input = input->next; - for (op = &output; (o = *op); op = &o->next) - if (xf86ModeCompare (o, i) > 0) - break; - i->next = *op; - *op = i; - } - /* prune identical modes */ - for (o = output; o && (n = o->next); o = n) - { - if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) - { - o->next = n->next; - xfree (n->name); - xfree (n); - n = o; - } - } - /* hook up backward links */ - prev = NULL; - for (o = output; o; o = o->next) - { - o->prev = prev; - prev = o; - } - return output; -} - -static char * -preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) -{ - char *preferred_mode = NULL; - - /* Check for a configured preference for a particular mode */ - preferred_mode = xf86GetOptValString (output->options, - OPTION_PREFERRED_MODE); - if (preferred_mode) - return preferred_mode; - - if (pScrn->display->modes && *pScrn->display->modes) - preferred_mode = *pScrn->display->modes; - - return preferred_mode; -} - -static void -GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) -{ - if (!mon || !mode) - return; - - mon->nHsync = 1; - mon->hsync[0].lo = 1024.0; - mon->hsync[0].hi = 0.0; - - mon->nVrefresh = 1; - mon->vrefresh[0].lo = 1024.0; - mon->vrefresh[0].hi = 0.0; - - while (mode) { - if (!mode->HSync) - mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal); - - if (!mode->VRefresh) - mode->VRefresh = (1000.0 * ((float) mode->Clock)) / - ((float) (mode->HTotal * mode->VTotal)); - - if (mode->HSync < mon->hsync[0].lo) - mon->hsync[0].lo = mode->HSync; - - if (mode->HSync > mon->hsync[0].hi) - mon->hsync[0].hi = mode->HSync; - - if (mode->VRefresh < mon->vrefresh[0].lo) - mon->vrefresh[0].lo = mode->VRefresh; - - if (mode->VRefresh > mon->vrefresh[0].hi) - mon->vrefresh[0].hi = mode->VRefresh; - - mode = mode->next; - } - - /* stretch out the bottom to fit 640x480@60 */ - if (mon->hsync[0].lo > 31.0) - mon->hsync[0].lo = 31.0; - if (mon->vrefresh[0].lo > 58.0) - mon->vrefresh[0].lo = 58.0; -} - -enum det_monrec_source { - sync_config, sync_edid, sync_default -}; - -struct det_monrec_parameter { - MonRec *mon_rec; - int *max_clock; - Bool set_hsync; - Bool set_vrefresh; - enum det_monrec_source *sync_source; -}; - -static void handle_detailed_monrec(struct detailed_monitor_section *det_mon, - void *data) -{ - enum { sync_config, sync_edid, sync_default }; - struct det_monrec_parameter *p; - p = (struct det_monrec_parameter *)data; - - if (det_mon->type == DS_RANGES) { - struct monitor_ranges *ranges = &det_mon->section.ranges; - if (p->set_hsync && ranges->max_h) { - p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; - p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; - p->mon_rec->nHsync++; - if (*p->sync_source == sync_default) - *p->sync_source = sync_edid; - } - if (p->set_vrefresh && ranges->max_v) { - p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; - p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; - p->mon_rec->nVrefresh++; - if (*p->sync_source == sync_default) - *p->sync_source = sync_edid; - } - if (ranges->max_clock * 1000 > *p->max_clock) - *p->max_clock = ranges->max_clock * 1000; - } -} - -void -xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - /* When canGrow was TRUE in the initial configuration we have to - * compare against the maximum values so that we don't drop modes. - * When canGrow was FALSE, the maximum values would have been clamped - * anyway. - */ - if (maxX == 0 || maxY == 0) { - maxX = config->maxWidth; - maxY = config->maxHeight; - } - - /* Probe the list of modes for each output. */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode; - DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL; - char *preferred_mode; - xf86MonPtr edid_monitor; - XF86ConfMonitorPtr conf_monitor; - MonRec mon_rec; - int min_clock = 0; - int max_clock = 0; - double clock; - Bool add_default_modes = TRUE; - Bool debug_modes = config->debug_modes || - xf86Initialising; - enum det_monrec_source sync_source = sync_default; - - while (output->probed_modes != NULL) - xf86DeleteMode(&output->probed_modes, output->probed_modes); - - /* - * Check connection status - */ - output->status = (*output->funcs->detect)(output); - - if (output->status == XF86OutputStatusDisconnected && - !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE)) - { - xf86OutputSetEDID (output, NULL); - continue; - } - - memset (&mon_rec, '\0', sizeof (mon_rec)); - - conf_monitor = output->conf_monitor; - - if (conf_monitor) - { - int i; - - for (i = 0; i < conf_monitor->mon_n_hsync; i++) - { - mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; - mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; - mon_rec.nHsync++; - sync_source = sync_config; - } - for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) - { - mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; - mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; - mon_rec.nVrefresh++; - sync_source = sync_config; - } - config_modes = xf86GetMonitorModes (scrn, conf_monitor); - } - - output_modes = (*output->funcs->get_modes) (output); - - edid_monitor = output->MonInfo; - - if (edid_monitor) - { - struct det_monrec_parameter p; - struct disp_features *features = &edid_monitor->features; - - /* if display is not continuous-frequency, don't add default modes */ - if (!GTF_SUPPORTED(features->msc)) - add_default_modes = FALSE; - - p.mon_rec = &mon_rec; - p.max_clock = &max_clock; - p.set_hsync = mon_rec.nHsync == 0; - p.set_vrefresh = mon_rec.nVrefresh == 0; - p.sync_source = &sync_source; - - xf86ForEachDetailedBlock(edid_monitor, - handle_detailed_monrec, - &p); - } - - if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, - OPTUNITS_KHZ, &clock)) - min_clock = (int) clock; - if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, - OPTUNITS_KHZ, &clock)) - max_clock = (int) clock; - - /* If we still don't have a sync range, guess wildly */ - if (!mon_rec.nHsync || !mon_rec.nVrefresh) - GuessRangeFromModes(&mon_rec, output_modes); - - /* - * These limits will end up setting a 1024x768@60Hz mode by default, - * which seems like a fairly good mode to use when nothing else is - * specified - */ - if (mon_rec.nHsync == 0) - { - mon_rec.hsync[0].lo = 31.0; - mon_rec.hsync[0].hi = 55.0; - mon_rec.nHsync = 1; - } - if (mon_rec.nVrefresh == 0) - { - mon_rec.vrefresh[0].lo = 58.0; - mon_rec.vrefresh[0].hi = 62.0; - mon_rec.nVrefresh = 1; - } - - if (add_default_modes) - default_modes = xf86GetDefaultModes (); - - /* - * If this is not an RB monitor, remove RB modes from the default - * pool. RB modes from the config or the monitor itself are fine. - */ - if (!mon_rec.reducedblanking) - xf86ValidateModesReducedBlanking (scrn, default_modes); - - if (sync_source == sync_config) - { - /* - * Check output and config modes against sync range from config file - */ - xf86ValidateModesSync (scrn, output_modes, &mon_rec); - xf86ValidateModesSync (scrn, config_modes, &mon_rec); - } - /* - * Check default modes against sync range - */ - xf86ValidateModesSync (scrn, default_modes, &mon_rec); - /* - * Check default modes against monitor max clock - */ - if (max_clock) { - xf86ValidateModesClocks(scrn, default_modes, - &min_clock, &max_clock, 1); - xf86ValidateModesClocks(scrn, output_modes, - &min_clock, &max_clock, 1); - } - - output->probed_modes = NULL; - output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); - output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); - output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); - - /* - * Check all modes against max size, interlace, and doublescan - */ - if (maxX && maxY) - xf86ValidateModesSize (scrn, output->probed_modes, - maxX, maxY, 0); - - { - int flags = (output->interlaceAllowed ? V_INTERLACE : 0) | - (output->doubleScanAllowed ? V_DBLSCAN : 0); - xf86ValidateModesFlags (scrn, output->probed_modes, flags); - } - - /* - * Check all modes against output - */ - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - if (mode->status == MODE_OK) - mode->status = (*output->funcs->mode_valid)(output, mode); - - xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); - - output->probed_modes = xf86SortModes (output->probed_modes); - - /* Check for a configured preference for a particular mode */ - preferred_mode = preferredMode(scrn, output); - - if (preferred_mode) - { - for (mode = output->probed_modes; mode; mode = mode->next) - { - if (!strcmp (preferred_mode, mode->name)) - { - if (mode != output->probed_modes) - { - if (mode->prev) - mode->prev->next = mode->next; - if (mode->next) - mode->next->prev = mode->prev; - mode->next = output->probed_modes; - output->probed_modes->prev = mode; - mode->prev = NULL; - output->probed_modes = mode; - } - mode->type |= (M_T_PREFERRED|M_T_USERPREF); - break; - } - } - } - - output->initial_rotation = xf86OutputInitialRotation (output); - - if (debug_modes) { - if (output->probed_modes != NULL) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Printing probed modes for output %s\n", - output->name); - } else { - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "No remaining probed modes for output %s\n", - output->name); - } - } - for (mode = output->probed_modes; mode != NULL; mode = mode->next) - { - /* The code to choose the best mode per pipe later on will require - * VRefresh to be set. - */ - mode->VRefresh = xf86ModeVRefresh(mode); - xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - - if (debug_modes) - xf86PrintModeline(scrn->scrnIndex, mode); - } - } -} - - -/** - * Copy one of the output mode lists to the ScrnInfo record - */ - -/* XXX where does this function belong? Here? */ -void -xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y); - -static DisplayModePtr -biggestMode(DisplayModePtr a, DisplayModePtr b) -{ - int A, B; - - if (!a) - return b; - if (!b) - return a; - - A = a->HDisplay * a->VDisplay; - B = b->HDisplay * b->VDisplay; - - if (A > B) - return a; - - return b; -} - -static xf86OutputPtr -SetCompatOutput(xf86CrtcConfigPtr config) -{ - xf86OutputPtr output = NULL, test = NULL; - DisplayModePtr maxmode = NULL, testmode, mode; - int o, compat = -1, count, mincount = 0; - - /* Look for one that's definitely connected */ - for (o = 0; o < config->num_output; o++) - { - test = config->output[o]; - if (!test->crtc) - continue; - if (test->status != XF86OutputStatusConnected) - continue; - if (!test->probed_modes) - continue; - - testmode = mode = test->probed_modes; - for (count = 0; mode; mode = mode->next, count++) - testmode = biggestMode(testmode, mode); - - if (!output) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } else if (maxmode == biggestMode(maxmode, testmode)) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } else if ((maxmode->HDisplay == testmode->HDisplay) && - (maxmode->VDisplay == testmode->VDisplay) && - count <= mincount) { - output = test; - compat = o; - maxmode = testmode; - mincount = count; - } - } - - /* If we didn't find one, take anything we can get */ - if (!output) - { - for (o = 0; o < config->num_output; o++) - { - test = config->output[o]; - if (!test->crtc) - continue; - if (!test->probed_modes) - continue; - - if (!output) { - output = test; - compat = o; - } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) { - output = test; - compat = o; - } - } - } - - if (compat >= 0) { - config->compat_output = compat; - } else { - /* Don't change the compat output when no valid outputs found */ - output = config->output[config->compat_output]; - } - - return output; -} - -void -xf86SetScrnInfoModes (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86OutputPtr output; - xf86CrtcPtr crtc; - DisplayModePtr last, mode = NULL; - - output = SetCompatOutput(config); - - if (!output) - return; /* punt */ - - crtc = output->crtc; - - /* Clear any existing modes from scrn->modes */ - while (scrn->modes != NULL) - xf86DeleteMode(&scrn->modes, scrn->modes); - - /* Set scrn->modes to the mode list for the 'compat' output */ - scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); - - if (crtc) { - for (mode = scrn->modes; mode; mode = mode->next) - if (xf86ModesEqual (mode, &crtc->desiredMode)) - break; - } - - if (scrn->modes != NULL) { - /* For some reason, scrn->modes is circular, unlike the other mode - * lists. How great is that? - */ - for (last = scrn->modes; last && last->next; last = last->next) - ; - last->next = scrn->modes; - scrn->modes->prev = last; - if (mode) { - while (scrn->modes != mode) - scrn->modes = scrn->modes->next; - } - } - scrn->currentMode = scrn->modes; -#ifdef XFreeXDGA - if (scrn->pScreen) - _xf86_di_dga_reinit_internal(scrn->pScreen); -#endif -} - -static void -xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - Bool *enabled) -{ - Bool any_enabled = FALSE; - int o; - - for (o = 0; o < config->num_output; o++) - any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE); - - if (!any_enabled) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "No outputs definitely connected, trying again...\n"); - - for (o = 0; o < config->num_output; o++) - enabled[o] = xf86OutputEnabled(config->output[o], FALSE); - } -} - -static Bool -nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) -{ - int o = *index; - - for (o++; o < config->num_output; o++) { - if (enabled[o]) { - *index = o; - return TRUE; - } - } - - return FALSE; -} - -static Bool -aspectMatch(float a, float b) -{ - return fabs(1 - (a / b)) < 0.05; -} - -static DisplayModePtr -nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) -{ - DisplayModePtr m = NULL; - - if (!o) - return NULL; - - if (!last) - m = o->probed_modes; - else - m = last->next; - - for (; m; m = m->next) - if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) - return m; - - return NULL; -} - -static DisplayModePtr -bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) -{ - int o = -1, p; - DisplayModePtr mode = NULL, test = NULL, match = NULL; - - if (!nextEnabledOutput(config, enabled, &o)) - return NULL; - while ((mode = nextAspectMode(config->output[o], mode, aspect))) { - test = mode; - for (p = o; nextEnabledOutput(config, enabled, &p); ) { - test = xf86OutputFindClosestMode(config->output[p], mode); - if (!test) - break; - if (test->HDisplay != mode->HDisplay || - test->VDisplay != mode->VDisplay) { - test = NULL; - break; - } - } - - /* if we didn't match it on all outputs, try the next one */ - if (!test) - continue; - - /* if it's bigger than the last one, save it */ - if (!match || (test->HDisplay > match->HDisplay)) - match = test; - } - - /* return the biggest one found */ - return match; -} - -static Bool -xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o, p; - int max_pref_width = 0, max_pref_height = 0; - DisplayModePtr *preferred, *preferred_match; - Bool ret = FALSE; - - preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); - preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); - - /* Check if the preferred mode is available on all outputs */ - for (p = -1; nextEnabledOutput(config, enabled, &p); ) { - Rotation r = config->output[p]->initial_rotation; - DisplayModePtr mode; - if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p], - width, height))) { - int pref_width = xf86ModeWidth(preferred[p], r); - int pref_height = xf86ModeHeight(preferred[p], r); - Bool all_match = TRUE; - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - Bool match = FALSE; - xf86OutputPtr output = config->output[o]; - if (o == p) - continue; - - for (mode = output->probed_modes; mode; mode = mode->next) { - Rotation r = output->initial_rotation; - if (xf86ModeWidth(mode, r) == pref_width && - xf86ModeHeight(mode, r) == pref_height) { - preferred[o] = mode; - match = TRUE; - } - } - - all_match &= match; - } - - if (all_match && - (pref_width*pref_height > max_pref_width*max_pref_height)) { - for (o = -1; nextEnabledOutput(config, enabled, &o); ) - preferred_match[o] = preferred[o]; - max_pref_width = pref_width; - max_pref_height = pref_height; - ret = TRUE; - } - } - } - - /* - * If there's no preferred mode, but only one monitor, pick the - * biggest mode for its aspect ratio, assuming one exists. - */ - if (!ret) do { - int i = 0; - float aspect = 0.0; - - /* count the number of enabled outputs */ - for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; - - if (i != 1) - break; - - p = -1; - nextEnabledOutput(config, enabled, &p); - if (config->output[p]->mm_height) - aspect = (float)config->output[p]->mm_width / - (float)config->output[p]->mm_height; - - if (aspect) - preferred_match[p] = bestModeForAspect(config, enabled, aspect); - - if (preferred_match[p]) - ret = TRUE; - - } while (0); - - if (ret) { - /* oh good, there is a match. stash the selected modes and return. */ - memcpy(modes, preferred_match, - config->num_output * sizeof(DisplayModePtr)); - } - - xfree(preferred); - xfree(preferred_match); - return ret; -} - -static Bool -xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o; - float aspect = 0.0, *aspects; - xf86OutputPtr output; - Bool ret = FALSE; - DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL; - - aspects = xnfcalloc(config->num_output, sizeof(float)); - - /* collect the aspect ratios */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - output = config->output[o]; - if (output->mm_height) - aspects[o] = (float)output->mm_width / (float)output->mm_height; - else - aspects[o] = 4.0 / 3.0; - } - - /* check that they're all the same */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - output = config->output[o]; - if (!aspect) { - aspect = aspects[o]; - } else if (!aspectMatch(aspect, aspects[o])) { - goto no_aspect_match; - } - } - - /* if they're all 4:3, just skip ahead and save effort */ - if (!aspectMatch(aspect, 4.0/3.0)) - aspect_guess = bestModeForAspect(config, enabled, aspect); - -no_aspect_match: - base_guess = bestModeForAspect(config, enabled, 4.0/3.0); - - guess = biggestMode(base_guess, aspect_guess); - - if (!guess) - goto out; - - /* found a mode that works everywhere, now apply it */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - modes[o] = xf86OutputFindClosestMode(config->output[o], guess); - } - ret = TRUE; - -out: - xfree(aspects); - return ret; -} - -static Bool -xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - DisplayModePtr target_mode = NULL; - Rotation target_rotation = RR_Rotate_0; - DisplayModePtr default_mode; - int default_preferred, target_preferred = 0, o; - - /* User preferred > preferred > other modes */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - default_mode = xf86DefaultMode (config->output[o], width, height); - if (!default_mode) - continue; - - default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) + - ((default_mode->type & M_T_USERPREF) != 0)); - - if (default_preferred > target_preferred || !target_mode) { - target_mode = default_mode; - target_preferred = default_preferred; - target_rotation = config->output[o]->initial_rotation; - config->compat_output = o; - } - } - - if (target_mode) - modes[config->compat_output] = target_mode; - - /* Fill in other output modes */ - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - if (!modes[o]) - modes[o] = xf86ClosestMode(config->output[o], target_mode, - target_rotation, width, height); - } - - return (target_mode != NULL); -} - -static Bool -xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, - DisplayModePtr *modes, Bool *enabled, - int width, int height) -{ - int o; - - if (xf86UserConfiguredOutputs(scrn, modes)) - return xf86TargetFallback(scrn, config, modes, enabled, width, height); - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) - if (xf86OutputHasUserPreferredMode(config->output[o])) - return - xf86TargetFallback(scrn, config, modes, enabled, width, height); - - return FALSE; -} - -static Bool -xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, - float gamma_blue) -{ - int i, size = 256; - CARD16 *red, *green, *blue; - - red = malloc(3 * size * sizeof(CARD16)); - green = red + size; - blue = green + size; - - /* Only cause warning if user wanted gamma to be set. */ - if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { - free(red); - return FALSE; - } else if (!crtc->funcs->gamma_set) { - free(red); - return TRUE; - } - - /* At this early stage none of the randr-interface stuff is up. - * So take the default gamma size for lack of something better. - */ - for (i = 0; i < size; i++) { - if (gamma_red == 1.0) - red[i] = i << 8; - else - red[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_red) * (double)(size - 1) * 256); - - if (gamma_green == 1.0) - green[i] = i << 8; - else - green[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_green) * (double)(size - 1) * 256); - - if (gamma_blue == 1.0) - blue[i] = i << 8; - else - blue[i] = (CARD16)(pow((double)i/(double)(size - 1), - 1. / (double)gamma_blue) * (double)(size - 1) * 256); - } - - /* Default size is 256, so anything else is failure. */ - if (size != crtc->gamma_size) { - free(red); - return FALSE; - } - - crtc->gamma_size = size; - memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16)); - - /* Do not set gamma now, delay until the crtc is activated. */ - - free(red); - - return TRUE; -} - -static Bool -xf86OutputSetInitialGamma(xf86OutputPtr output) -{ - XF86ConfMonitorPtr mon = output->conf_monitor; - float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; - - if (!mon) - return TRUE; - - if (!output->crtc) - return FALSE; - - /* Get configured values, where they exist. */ - if (mon->mon_gamma_red >= GAMMA_MIN && - mon->mon_gamma_red <= GAMMA_MAX) - gamma_red = mon->mon_gamma_red; - - if (mon->mon_gamma_green >= GAMMA_MIN && - mon->mon_gamma_green <= GAMMA_MAX) - gamma_green = mon->mon_gamma_green; - - if (mon->mon_gamma_blue >= GAMMA_MIN && - mon->mon_gamma_blue <= GAMMA_MAX) - gamma_blue = mon->mon_gamma_blue; - - /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ - if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue); - return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue); - }else - return TRUE; -} - -/** - * Construct default screen configuration - * - * Given auto-detected (and, eventually, configured) values, - * construct a usable configuration for the system - * - * canGrow indicates that the driver can resize the screen to larger than its - * initially configured size via the config->funcs->resize hook. If TRUE, this - * function will set virtualX and virtualY to match the initial configuration - * and leave config->max{Width,Height} alone. If FALSE, it will bloat - * virtual[XY] to include the largest modes and set config->max{Width,Height} - * accordingly. - */ - -Bool -xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o, c; - xf86CrtcPtr *crtcs; - DisplayModePtr *modes; - Bool *enabled; - int width, height; - int i = scrn->scrnIndex; - - /* Set up the device options */ - config->options = xnfalloc (sizeof (xf86DeviceOptions)); - memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions)); - xf86ProcessOptions (scrn->scrnIndex, - scrn->options, - config->options); - config->debug_modes = xf86ReturnOptValBool (config->options, - OPTION_MODEDEBUG, FALSE); - - if (scrn->display->virtualX) - width = scrn->display->virtualX; - else - width = config->maxWidth; - if (scrn->display->virtualY) - height = scrn->display->virtualY; - else - height = config->maxHeight; - - xf86ProbeOutputModes (scrn, width, height); - - crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); - modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); - enabled = xnfcalloc (config->num_output, sizeof (Bool)); - - xf86CollectEnabledOutputs(scrn, config, enabled); - - if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); - else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); - else if (xf86TargetAspect(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n"); - else if (xf86TargetFallback(scrn, config, modes, enabled, width, height)) - xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n"); - else - xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n"); - - for (o = -1; nextEnabledOutput(config, enabled, &o); ) { - if (!modes[o]) - xf86DrvMsg (scrn->scrnIndex, X_ERROR, - "Output %s enabled but has no modes\n", - config->output[o]->name); - else - xf86DrvMsg (scrn->scrnIndex, X_INFO, - "Output %s using initial mode %s\n", - config->output[o]->name, modes[o]->name); - } - - /* - * Set the position of each output - */ - if (!xf86InitialOutputPositions (scrn, modes)) - { - xfree (crtcs); - xfree (modes); - return FALSE; - } - - /* - * Set initial panning of each output - */ - xf86InitialPanning (scrn); - - /* - * Assign CRTCs to fit output configuration - */ - if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) - { - xfree (crtcs); - xfree (modes); - return FALSE; - } - - /* XXX override xf86 common frame computation code */ - - scrn->display->frameX0 = 0; - scrn->display->frameY0 = 0; - - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->enabled = FALSE; - memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); - /* Set default gamma for all crtc's. */ - /* This is done to avoid problems later on with cloned outputs. */ - xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); - } - - if (xf86_crtc_supports_gamma(scrn)) - xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n"); - - /* - * Set initial configuration - */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr mode = modes[o]; - xf86CrtcPtr crtc = crtcs[o]; - - if (mode && crtc) - { - crtc->desiredMode = *mode; - crtc->desiredRotation = output->initial_rotation; - crtc->desiredX = output->initial_x; - crtc->desiredY = output->initial_y; - crtc->desiredTransformPresent = FALSE; - crtc->enabled = TRUE; - memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec)); - memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec)); - memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16)); - output->crtc = crtc; - if (!xf86OutputSetInitialGamma(output)) - xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name); - } else { - output->crtc = NULL; - } - } - - if (scrn->display->virtualX == 0) - { - /* - * Expand virtual size to cover the current config and potential mode - * switches, if the driver can't enlarge the screen later. - */ - xf86DefaultScreenLimits (scrn, &width, &height, canGrow); - - scrn->display->virtualX = width; - scrn->display->virtualY = height; - } - - if (width > scrn->virtualX) - scrn->virtualX = width; - if (height > scrn->virtualY) - scrn->virtualY = height; - - /* - * Make sure the configuration isn't too small. - */ - if (width < config->minWidth || height < config->minHeight) - return FALSE; - - /* - * Limit the crtc config to virtual[XY] if the driver can't grow the - * desktop. - */ - if (!canGrow) - { - xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight, - width, height); - } - - /* Mirror output modes to scrn mode list */ - xf86SetScrnInfoModes (scrn); - - xfree (crtcs); - xfree (modes); - return TRUE; -} - -/* - * Check the CRTC we're going to map each output to vs. it's current - * CRTC. If they don't match, we have to disable the output and the CRTC - * since the driver will have to re-route things. - */ -static void -xf86PrepareOutputs (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int o; - - for (o = 0; o < config->num_output; o++) { - xf86OutputPtr output = config->output[o]; -#if RANDR_GET_CRTC_INTERFACE - /* Disable outputs that are unused or will be re-routed */ - if (!output->funcs->get_crtc || - output->crtc != (*output->funcs->get_crtc)(output) || - output->crtc == NULL) -#endif - (*output->funcs->dpms)(output, DPMSModeOff); - } -} - -static void -xf86PrepareCrtcs (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - for (c = 0; c < config->num_crtc; c++) { -#if RANDR_GET_CRTC_INTERFACE - xf86CrtcPtr crtc = config->crtc[c]; - xf86OutputPtr output = NULL; - uint32_t desired_outputs = 0, current_outputs = 0; - int o; - - for (o = 0; o < config->num_output; o++) { - output = config->output[o]; - if (output->crtc == crtc) - desired_outputs |= (1<funcs->get_crtc) { - desired_outputs = 0; - break; - } - if ((*output->funcs->get_crtc)(output) == crtc) - current_outputs |= (1<funcs->dpms)(crtc, DPMSModeOff); -#else - (*crtc->funcs->dpms)(crtc, DPMSModeOff); -#endif - } -} - -/* - * Using the desired mode information in each crtc, set - * modes (used in EnterVT functions, or at server startup) - */ - -Bool -xf86SetDesiredModes (ScrnInfoPtr scrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc = config->crtc[0]; - int c; - - /* A driver with this hook will take care of this */ - if (!crtc->funcs->set_mode_major) { - xf86PrepareOutputs(scrn); - xf86PrepareCrtcs(scrn); - } - - for (c = 0; c < config->num_crtc; c++) - { - xf86OutputPtr output = NULL; - int o; - RRTransformPtr transform; - - crtc = config->crtc[c]; - - /* Skip disabled CRTCs */ - if (!crtc->enabled) - continue; - - if (xf86CompatOutput(scrn) && xf86CompatCrtc(scrn) == crtc) - output = xf86CompatOutput(scrn); - else - { - for (o = 0; o < config->num_output; o++) - if (config->output[o]->crtc == crtc) - { - output = config->output[o]; - break; - } - } - /* paranoia */ - if (!output) - continue; - - /* Mark that we'll need to re-set the mode for sure */ - memset(&crtc->mode, 0, sizeof(crtc->mode)); - if (!crtc->desiredMode.CrtcHDisplay) - { - DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode); - - if (!mode) - return FALSE; - crtc->desiredMode = *mode; - crtc->desiredRotation = RR_Rotate_0; - crtc->desiredTransformPresent = FALSE; - crtc->desiredX = 0; - crtc->desiredY = 0; - } - - if (crtc->desiredTransformPresent) - transform = &crtc->desiredTransform; - else - transform = NULL; - if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation, - transform, crtc->desiredX, crtc->desiredY)) - return FALSE; - } - - xf86DisableUnusedFunctions(scrn); - return TRUE; -} - -/** - * In the current world order, there are lists of modes per output, which may - * or may not include the mode that was asked to be set by XFree86's mode - * selection. Find the closest one, in the following preference order: - * - * - Equality - * - Closer in size to the requested mode, but no larger - * - Closer in refresh rate to the requested mode. - */ - -DisplayModePtr -xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired) -{ - DisplayModePtr best = NULL, scan = NULL; - - for (scan = output->probed_modes; scan != NULL; scan = scan->next) - { - /* If there's an exact match, we're done. */ - if (xf86ModesEqual(scan, desired)) { - best = desired; - break; - } - - /* Reject if it's larger than the desired mode. */ - if (scan->HDisplay > desired->HDisplay || - scan->VDisplay > desired->VDisplay) - { - continue; - } - - /* - * If we haven't picked a best mode yet, use the first - * one in the size range - */ - if (best == NULL) - { - best = scan; - continue; - } - - /* Find if it's closer to the right size than the current best - * option. - */ - if ((scan->HDisplay > best->HDisplay && - scan->VDisplay >= best->VDisplay) || - (scan->HDisplay >= best->HDisplay && - scan->VDisplay > best->VDisplay)) - { - best = scan; - continue; - } - - /* Find if it's still closer to the right refresh than the current - * best resolution. - */ - if (scan->HDisplay == best->HDisplay && - scan->VDisplay == best->VDisplay && - (fabs(scan->VRefresh - desired->VRefresh) < - fabs(best->VRefresh - desired->VRefresh))) { - best = scan; - } - } - return best; -} - -/** - * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, - * take the specified mode and apply it to the crtc connected to the compat - * output. Then, find similar modes for the other outputs, as with the - * InitialConfiguration code above. The goal is to clone the desired - * mode across all outputs that are currently active. - */ - -Bool -xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - Bool ok = TRUE; - xf86OutputPtr compat_output; - DisplayModePtr compat_mode = NULL; - int c; - - /* - * Let the compat output drive the final mode selection - */ - compat_output = xf86CompatOutput(pScrn); - if (compat_output) - compat_mode = xf86OutputFindClosestMode (compat_output, desired); - if (compat_mode) - desired = compat_mode; - - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - DisplayModePtr crtc_mode = NULL; - int o; - - if (!crtc->enabled) - continue; - - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - DisplayModePtr output_mode; - - /* skip outputs not on this crtc */ - if (output->crtc != crtc) - continue; - - if (crtc_mode) - { - output_mode = xf86OutputFindClosestMode (output, crtc_mode); - if (output_mode != crtc_mode) - output->crtc = NULL; - } - else - crtc_mode = xf86OutputFindClosestMode (output, desired); - } - if (!crtc_mode) - { - crtc->enabled = FALSE; - continue; - } - if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0)) - ok = FALSE; - else - { - crtc->desiredMode = *crtc_mode; - crtc->desiredRotation = rotation; - crtc->desiredTransformPresent = FALSE; - crtc->desiredX = 0; - crtc->desiredY = 0; - } - } - xf86DisableUnusedFunctions(pScrn); -#ifdef RANDR_12_INTERFACE - xf86RandR12TellChanged (pScrn->pScreen); -#endif - return ok; -} - - -/** - * Set the DPMS power mode of all outputs and CRTCs. - * - * If the new mode is off, it will turn off outputs and then CRTCs. - * Otherwise, it will affect CRTCs before outputs. - */ -void -xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int i; - - if (!scrn->vtSema) - return; - - if (mode == DPMSModeOff) { - for (i = 0; i < config->num_output; i++) { - xf86OutputPtr output = config->output[i]; - if (output->crtc != NULL) - (*output->funcs->dpms) (output, mode); - } - } - - for (i = 0; i < config->num_crtc; i++) { - xf86CrtcPtr crtc = config->crtc[i]; - if (crtc->enabled) - (*crtc->funcs->dpms) (crtc, mode); - } - - if (mode != DPMSModeOff) { - for (i = 0; i < config->num_output; i++) { - xf86OutputPtr output = config->output[i]; - if (output->crtc != NULL) - (*output->funcs->dpms) (output, mode); - } - } -} - -/** - * Implement the screensaver by just calling down into the driver DPMS hooks. - * - * Even for monitors with no DPMS support, by the definition of our DPMS hooks, - * the outputs will still get disabled (blanked). - */ -Bool -xf86SaveScreen(ScreenPtr pScreen, int mode) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (xf86IsUnblank(mode)) - xf86DPMSSet(pScrn, DPMSModeOn, 0); - else - xf86DPMSSet(pScrn, DPMSModeOff, 0); - - return TRUE; -} - -/** - * Disable all inactive crtcs and outputs - */ -void -xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o, c; - - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - if (!output->crtc) - (*output->funcs->dpms)(output, DPMSModeOff); - } - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - if (!crtc->enabled) - { - crtc->funcs->dpms(crtc, DPMSModeOff); - memset(&crtc->mode, 0, sizeof(crtc->mode)); - xf86RotateDestroy(crtc); - crtc->active = FALSE; - } - } - if (pScrn->pScreen) - xf86_crtc_notify(pScrn->pScreen); -} - -#ifdef RANDR_12_INTERFACE - -#define EDID_ATOM_NAME "EDID" - -/** - * Set the RandR EDID property - */ -static void -xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) -{ - Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE); - - /* This may get called before the RandR resources have been created */ - if (output->randr_output == NULL) - return; - - if (data_len != 0) { - RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, - PropModeReplace, data_len, data, FALSE, TRUE); - } else { - RRDeleteOutputProperty(output->randr_output, edid_atom); - } -} - -#endif - -/* Pull out a phyiscal size from a detailed timing if available. */ -struct det_phySize_parameter { - xf86OutputPtr output; - ddc_quirk_t quirks; - Bool ret; -}; - -static void handle_detailed_physical_size(struct detailed_monitor_section - *det_mon, void *data) -{ - struct det_phySize_parameter *p; - p = (struct det_phySize_parameter *)data; - - if (p->ret == TRUE ) - return ; - - xf86DetTimingApplyQuirks(det_mon, p->quirks, - p->output->MonInfo->features.hsize, - p->output->MonInfo->features.vsize); - if (det_mon->type == DT && - det_mon->section.d_timings.h_size != 0 && - det_mon->section.d_timings.v_size != 0) { - - p->output->mm_width = det_mon->section.d_timings.h_size; - p->output->mm_height = det_mon->section.d_timings.v_size; - p->ret = TRUE; - } -} - -/** - * Set the EDID information for the specified output - */ -void -xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) -{ - ScrnInfoPtr scrn = output->scrn; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - Bool debug_modes = config->debug_modes || xf86Initialising; -#ifdef RANDR_12_INTERFACE - int size; -#endif - - if (output->MonInfo != NULL) - xfree(output->MonInfo); - - output->MonInfo = edid_mon; - - if (debug_modes) { - xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", - output->name); - xf86PrintEDID(edid_mon); - } - - /* Set the DDC properties for the 'compat' output */ - if (output == xf86CompatOutput(scrn)) - xf86SetDDCproperties(scrn, edid_mon); - -#ifdef RANDR_12_INTERFACE - /* Set the RandR output properties */ - size = 0; - if (edid_mon) - { - if (edid_mon->ver.version == 1) { - size = 128; - if (edid_mon->flags & EDID_COMPLETE_RAWDATA) - size += edid_mon->no_sections * 128; - } else if (edid_mon->ver.version == 2) - size = 256; - } - xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); -#endif - - if (edid_mon) { - - struct det_phySize_parameter p; - p.output = output; - p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE); - p.ret = FALSE; - xf86ForEachDetailedBlock(edid_mon, - handle_detailed_physical_size, &p); - - /* if no mm size is available from a detailed timing, check the max size field */ - if ((!output->mm_width || !output->mm_height) && - (edid_mon->features.hsize && edid_mon->features.vsize)) - { - output->mm_width = edid_mon->features.hsize * 10; - output->mm_height = edid_mon->features.vsize * 10; - } - } -} - -/** - * Return the list of modes supported by the EDID information - * stored in 'output' - */ -DisplayModePtr -xf86OutputGetEDIDModes (xf86OutputPtr output) -{ - ScrnInfoPtr scrn = output->scrn; - xf86MonPtr edid_mon = output->MonInfo; - - if (!edid_mon) - return NULL; - return xf86DDCGetModes(scrn->scrnIndex, edid_mon); -} - -/* maybe we should care about DDC1? meh. */ -xf86MonPtr -xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) -{ - ScrnInfoPtr scrn = output->scrn; - xf86MonPtr mon; - - mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE); - if (mon) - xf86DDCApplyQuirks(scrn->scrnIndex, mon); - - return mon; -} - -static char *_xf86ConnectorNames[] = { - "None", "VGA", "DVI-I", "DVI-D", - "DVI-A", "Composite", "S-Video", - "Component", "LFP", "Proprietary", - "HDMI", "DisplayPort", - }; -char * -xf86ConnectorGetName(xf86ConnectorType connector) -{ - return _xf86ConnectorNames[connector]; -} - -static void -x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) -{ - dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; - dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; - dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; - dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; - - if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) - dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; -} - -static void -x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) -{ - if (crtc->enabled) { - crtc_box->x1 = crtc->x; - crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); - crtc_box->y1 = crtc->y; - crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); - } else - crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; -} - -static int -xf86_crtc_box_area(BoxPtr box) -{ - return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); -} - -/* - * Return the crtc covering 'box'. If two crtcs cover a portion of - * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc - * with greater coverage - */ - -static xf86CrtcPtr -xf86_covering_crtc(ScrnInfoPtr pScrn, - BoxPtr box, - xf86CrtcPtr desired, - BoxPtr crtc_box_ret) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc, best_crtc; - int coverage, best_coverage; - int c; - BoxRec crtc_box, cover_box; - - best_crtc = NULL; - best_coverage = 0; - crtc_box_ret->x1 = 0; - crtc_box_ret->x2 = 0; - crtc_box_ret->y1 = 0; - crtc_box_ret->y2 = 0; - for (c = 0; c < xf86_config->num_crtc; c++) { - crtc = xf86_config->crtc[c]; - x86_crtc_box(crtc, &crtc_box); - x86_crtc_box_intersect(&cover_box, &crtc_box, box); - coverage = xf86_crtc_box_area(&cover_box); - if (coverage && crtc == desired) { - *crtc_box_ret = crtc_box; - return crtc; - } else if (coverage > best_coverage) { - *crtc_box_ret = crtc_box; - best_crtc = crtc; - best_coverage = coverage; - } - } - return best_crtc; -} - -/* - * For overlay video, compute the relevant CRTC and - * clip video to that. - * - * returning FALSE means there was a memory failure of some kind, - * not that the video shouldn't be displayed - */ - -Bool -xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, - xf86CrtcPtr *crtc_ret, - xf86CrtcPtr desired_crtc, - BoxPtr dst, - INT32 *xa, - INT32 *xb, - INT32 *ya, - INT32 *yb, - RegionPtr reg, - INT32 width, - INT32 height) -{ - Bool ret; - RegionRec crtc_region_local; - RegionPtr crtc_region = reg; - - if (crtc_ret) { - BoxRec crtc_box; - xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, - desired_crtc, - &crtc_box); - - if (crtc) { - REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); - crtc_region = &crtc_region_local; - REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); - } - *crtc_ret = crtc; - } - - ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, - crtc_region, width, height); - - if (crtc_region != reg) - REGION_UNINIT (pScreen, &crtc_region_local); - - return ret; -} - -xf86_crtc_notify_proc_ptr -xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new) -{ - if (xf86CrtcConfigPrivateIndex != -1) - { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - xf86_crtc_notify_proc_ptr old; - - old = config->xf86_crtc_notify; - config->xf86_crtc_notify = new; - return old; - } - return NULL; -} - -void -xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) -{ - if (xf86CrtcConfigPrivateIndex != -1) - { - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - config->xf86_crtc_notify = old; - } -} - -void -xf86_crtc_notify(ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - - if (config->xf86_crtc_notify) - config->xf86_crtc_notify(screen); -} - -Bool -xf86_crtc_supports_gamma(ScrnInfoPtr pScrn) -{ - if (xf86CrtcConfigPrivateIndex != -1) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc; - - /* for multiple drivers loaded we need this */ - if (!xf86_config) - return FALSE; - if (xf86_config->num_crtc == 0) - return FALSE; - crtc = xf86_config->crtc[0]; - - return (crtc->funcs->gamma_set != NULL); - } - - return FALSE; -} +/* + * Copyright © 2006 Keith Packard + * Copyright © 2008 Red Hat, Inc. + * + * 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#else +#ifdef HAVE_CONFIG_H +#include +#endif +#endif + +#include +#include +#include + +#include "xf86.h" +#include "xf86DDC.h" +#include "xf86Crtc.h" +#include "xf86Modes.h" +#include "xf86Priv.h" +#include "xf86RandR12.h" +#include "X11/extensions/render.h" +#include "X11/extensions/dpmsconst.h" +#include "X11/Xatom.h" +#include "picturestr.h" + +#include "xf86xv.h" + +/* + * Initialize xf86CrtcConfig structure + */ + +int xf86CrtcConfigPrivateIndex = -1; + +void +xf86CrtcConfigInit (ScrnInfoPtr scrn, + const xf86CrtcConfigFuncsRec *funcs) +{ + xf86CrtcConfigPtr config; + + if (xf86CrtcConfigPrivateIndex == -1) + xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); + + config->funcs = funcs; + + scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config; +} + +void +xf86CrtcSetSizeRange (ScrnInfoPtr scrn, + int minWidth, int minHeight, + int maxWidth, int maxHeight) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->minWidth = minWidth; + config->minHeight = minHeight; + config->maxWidth = maxWidth; + config->maxHeight = maxHeight; +} + +/* + * Crtc functions + */ +xf86CrtcPtr +xf86CrtcCreate (ScrnInfoPtr scrn, + const xf86CrtcFuncsRec *funcs) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc, *crtcs; + + crtc = calloc(sizeof (xf86CrtcRec), 1); + if (!crtc) + return NULL; + crtc->version = XF86_CRTC_VERSION; + crtc->scrn = scrn; + crtc->funcs = funcs; +#ifdef RANDR_12_INTERFACE + crtc->randr_crtc = NULL; +#endif + crtc->rotation = RR_Rotate_0; + crtc->desiredRotation = RR_Rotate_0; + pixman_transform_init_identity (&crtc->crtc_to_framebuffer); + pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); + pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); + crtc->filter = NULL; + crtc->params = NULL; + crtc->nparams = 0; + crtc->filter_width = 0; + crtc->filter_height = 0; + crtc->transform_in_use = FALSE; + crtc->transformPresent = FALSE; + crtc->desiredTransformPresent = FALSE; + memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); + + /* Preallocate gamma at a sensible size. */ + crtc->gamma_size = 256; + crtc->gamma_red = malloc(3 * crtc->gamma_size * sizeof (CARD16)); + if (!crtc->gamma_red) { + free(crtc); + return NULL; + } + crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; + crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; + + if (xf86_config->crtc) + crtcs = realloc(xf86_config->crtc, + (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + else + crtcs = malloc((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); + if (!crtcs) + { + free(crtc); + return NULL; + } + xf86_config->crtc = crtcs; + xf86_config->crtc[xf86_config->num_crtc++] = crtc; + return crtc; +} + +void +xf86CrtcDestroy (xf86CrtcPtr crtc) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + int c; + + (*crtc->funcs->destroy) (crtc); + for (c = 0; c < xf86_config->num_crtc; c++) + if (xf86_config->crtc[c] == crtc) + { + memmove (&xf86_config->crtc[c], + &xf86_config->crtc[c+1], + ((xf86_config->num_crtc - (c + 1)) * sizeof(void*))); + xf86_config->num_crtc--; + break; + } + if (crtc->params) + free(crtc->params); + free(crtc->gamma_red); + free(crtc); +} + + +/** + * Return whether any outputs are connected to the specified pipe + */ + +Bool +xf86CrtcInUse (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int o; + + for (o = 0; o < xf86_config->num_output; o++) + if (xf86_config->output[o]->crtc == crtc) + return TRUE; + return FALSE; +} + +void +xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen) +{ + int subpixel_order = SubPixelUnknown; + Bool has_none = FALSE; + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c, o; + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + for (o = 0; o < xf86_config->num_output; o++) + { + xf86OutputPtr output = xf86_config->output[o]; + + if (output->crtc == crtc) + { + switch (output->subpixel_order) { + case SubPixelNone: + has_none = TRUE; + break; + case SubPixelUnknown: + break; + default: + subpixel_order = output->subpixel_order; + break; + } + } + if (subpixel_order != SubPixelUnknown) + break; + } + if (subpixel_order != SubPixelUnknown) + { + static const int circle[4] = { + SubPixelHorizontalRGB, + SubPixelVerticalRGB, + SubPixelHorizontalBGR, + SubPixelVerticalBGR, + }; + int rotate; + int c; + for (rotate = 0; rotate < 4; rotate++) + if (crtc->rotation & (1 << rotate)) + break; + for (c = 0; c < 4; c++) + if (circle[c] == subpixel_order) + break; + c = (c + rotate) & 0x3; + if ((crtc->rotation & RR_Reflect_X) && !(c & 1)) + c ^= 2; + if ((crtc->rotation & RR_Reflect_Y) && (c & 1)) + c ^= 2; + subpixel_order = circle[c]; + break; + } + } + if (subpixel_order == SubPixelUnknown && has_none) + subpixel_order = SubPixelNone; + PictureSetSubpixelOrder (pScreen, subpixel_order); +} + +/** + * Sets the given video mode on the given crtc + */ +Bool +xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + RRTransformPtr transform, int x, int y) +{ + ScrnInfoPtr scrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + Bool ret = FALSE; + Bool didLock = FALSE; + DisplayModePtr adjusted_mode; + DisplayModeRec saved_mode; + int saved_x, saved_y; + Rotation saved_rotation; + RRTransformRec saved_transform; + Bool saved_transform_present; + + crtc->enabled = xf86CrtcInUse (crtc); + + /* We only hit this if someone explicitly sends a "disabled" modeset. */ + if (!crtc->enabled) + { + /* Check everything for stuff that should be off. */ + xf86DisableUnusedFunctions(scrn); + return TRUE; + } + + adjusted_mode = xf86DuplicateMode(mode); + + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + saved_rotation = crtc->rotation; + if (crtc->transformPresent) { + RRTransformInit (&saved_transform); + RRTransformCopy (&saved_transform, &crtc->transform); + } + saved_transform_present = crtc->transformPresent; + + /* Update crtc values up front so the driver can rely on them for mode + * setting. + */ + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + crtc->rotation = rotation; + if (transform) { + RRTransformCopy (&crtc->transform, transform); + crtc->transformPresent = TRUE; + } else + crtc->transformPresent = FALSE; + + if (crtc->funcs->set_mode_major) { + ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y); + goto done; + } + + didLock = crtc->funcs->lock (crtc); + /* Pass our mode to the outputs and the CRTC to give them a chance to + * adjust it according to limitations or output properties, and also + * a chance to reject the mode entirely. + */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { + goto done; + } + } + + if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { + goto done; + } + + if (!xf86CrtcRotate (crtc)) + goto done; + + /* Prepare the outputs and CRTCs before setting the mode. */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + /* Disable the output as the first thing we do. */ + output->funcs->prepare(output); + } + + crtc->funcs->prepare(crtc); + + /* Set up the DPLL and any output state that needs to adjust or depend + * on the DPLL. + */ + crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y); + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->mode_set(output, mode, adjusted_mode); + } + + /* Only upload when needed, to avoid unneeded delays. */ + if (!crtc->active && crtc->funcs->gamma_set) + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); + + /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ + crtc->funcs->commit(crtc); + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->commit(output); + } + + ret = TRUE; + +done: + if (ret) { + crtc->active = TRUE; + if (scrn->pScreen) + xf86CrtcSetScreenSubpixelOrder (scrn->pScreen); + } else { + crtc->x = saved_x; + crtc->y = saved_y; + crtc->rotation = saved_rotation; + crtc->mode = saved_mode; + if (saved_transform_present) + RRTransformCopy (&crtc->transform, &saved_transform); + crtc->transformPresent = saved_transform_present; + } + + if (adjusted_mode->name) + free(adjusted_mode->name); + free(adjusted_mode); + + if (didLock) + crtc->funcs->unlock (crtc); + + return ret; +} + +/** + * Sets the given video mode on the given crtc, but without providing + * a transform + */ +Bool +xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y) +{ + return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y); +} + +/** + * Pans the screen, does not change the mode + */ +void +xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y) +{ + crtc->x = x; + crtc->y = y; + if (crtc->funcs->set_origin) { + if (!xf86CrtcRotate (crtc)) + return; + crtc->funcs->set_origin (crtc, x, y); + } + else + xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y); +} + +/* + * Output functions + */ + +extern XF86ConfigPtr xf86configptr; + +typedef enum { + OPTION_PREFERRED_MODE, + OPTION_POSITION, + OPTION_BELOW, + OPTION_RIGHT_OF, + OPTION_ABOVE, + OPTION_LEFT_OF, + OPTION_ENABLE, + OPTION_DISABLE, + OPTION_MIN_CLOCK, + OPTION_MAX_CLOCK, + OPTION_IGNORE, + OPTION_ROTATE, + OPTION_PANNING, + OPTION_PRIMARY, +} OutputOpts; + +static OptionInfoRec xf86OutputOptions[] = { + {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, + {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, + {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, + {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, + {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, + {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, + {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, + {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, + {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, + {OPTION_PANNING, "Panning", OPTV_STRING, {0}, FALSE }, + {OPTION_PRIMARY, "Primary", OPTV_BOOLEAN, {0}, FALSE }, + {-1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +enum { + OPTION_MODEDEBUG, +}; + +static OptionInfoRec xf86DeviceOptions[] = { + {OPTION_MODEDEBUG, "ModeDebug", OPTV_BOOLEAN, {0}, FALSE }, + {-1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +static void +xf86OutputSetMonitor (xf86OutputPtr output) +{ + char *option_name; + static const char monitor_prefix[] = "monitor-"; + char *monitor; + + if (!output->name) + return; + + if (output->options) + free(output->options); + + output->options = xnfalloc (sizeof (xf86OutputOptions)); + memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); + + option_name = xnfalloc (strlen (monitor_prefix) + + strlen (output->name) + 1); + strcpy (option_name, monitor_prefix); + strcat (option_name, output->name); + monitor = xf86findOptionValue (output->scrn->options, option_name); + if (!monitor) + monitor = output->name; + else + xf86MarkOptionUsedByName (output->scrn->options, option_name); + free(option_name); + output->conf_monitor = xf86findMonitor (monitor, + xf86configptr->conf_monitor_lst); + /* + * Find the monitor section of the screen and use that + */ + if (!output->conf_monitor && output->use_screen_monitor) + output->conf_monitor = xf86findMonitor (output->scrn->monitor->id, + xf86configptr->conf_monitor_lst); + if (output->conf_monitor) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s using monitor section %s\n", + output->name, output->conf_monitor->mon_identifier); + xf86ProcessOptions (output->scrn->scrnIndex, + output->conf_monitor->mon_option_lst, + output->options); + } + else + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s has no monitor section\n", + output->name); +} + +static Bool +xf86OutputEnabled (xf86OutputPtr output, Bool strict) +{ + Bool enable, disable; + + /* check to see if this output was enabled in the config file */ + if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s enabled by config file\n", output->name); + return TRUE; + } + /* or if this output was disabled in the config file */ + if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable) + { + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s disabled by config file\n", output->name); + return FALSE; + } + + /* If not, try to only light up the ones we know are connected */ + if (strict) { + enable = output->status == XF86OutputStatusConnected; + } + /* But if that fails, try to light up even outputs we're unsure of */ + else { + enable = output->status != XF86OutputStatusDisconnected; + } + + xf86DrvMsg (output->scrn->scrnIndex, X_INFO, + "Output %s %sconnected\n", output->name, enable ? "" : "dis"); + return enable; +} + +static Bool +xf86OutputIgnored (xf86OutputPtr output) +{ + return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE); +} + +static char *direction[4] = { + "normal", + "left", + "inverted", + "right" +}; + +static Rotation +xf86OutputInitialRotation (xf86OutputPtr output) +{ + char *rotate_name = xf86GetOptValString (output->options, + OPTION_ROTATE); + int i; + + if (!rotate_name) + return RR_Rotate_0; + + for (i = 0; i < 4; i++) + if (xf86nameCompare (direction[i], rotate_name) == 0) + return (1 << i); + return RR_Rotate_0; +} + +xf86OutputPtr +xf86OutputCreate (ScrnInfoPtr scrn, + const xf86OutputFuncsRec *funcs, + const char *name) +{ + xf86OutputPtr output, *outputs; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int len; + Bool primary; + + if (name) + len = strlen (name) + 1; + else + len = 0; + + output = calloc(sizeof (xf86OutputRec) + len, 1); + if (!output) + return NULL; + output->scrn = scrn; + output->funcs = funcs; + if (name) + { + output->name = (char *) (output + 1); + strcpy (output->name, name); + } + output->subpixel_order = SubPixelUnknown; + /* + * Use the old per-screen monitor section for the first output + */ + output->use_screen_monitor = (xf86_config->num_output == 0); +#ifdef RANDR_12_INTERFACE + output->randr_output = NULL; +#endif + if (name) + { + xf86OutputSetMonitor (output); + if (xf86OutputIgnored (output)) + { + free(output); + return FALSE; + } + } + + + if (xf86_config->output) + outputs = realloc(xf86_config->output, + (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + else + outputs = malloc((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); + if (!outputs) + { + free(output); + return NULL; + } + + xf86_config->output = outputs; + + if (xf86GetOptValBool (output->options, OPTION_PRIMARY, &primary) && primary) + { + memmove(xf86_config->output + 1, xf86_config->output, + xf86_config->num_output * sizeof (xf86OutputPtr)); + xf86_config->output[0] = output; + } + else + { + xf86_config->output[xf86_config->num_output] = output; + } + + xf86_config->num_output++; + + return output; +} + +Bool +xf86OutputRename (xf86OutputPtr output, const char *name) +{ + int len = strlen(name) + 1; + char *newname = malloc(len); + + if (!newname) + return FALSE; /* so sorry... */ + + strcpy (newname, name); + if (output->name && output->name != (char *) (output + 1)) + free(output->name); + output->name = newname; + xf86OutputSetMonitor (output); + if (xf86OutputIgnored (output)) + return FALSE; + return TRUE; +} + +void +xf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor) +{ + if (use_screen_monitor != output->use_screen_monitor) + { + output->use_screen_monitor = use_screen_monitor; + xf86OutputSetMonitor (output); + } +} + +void +xf86OutputDestroy (xf86OutputPtr output) +{ + ScrnInfoPtr scrn = output->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + (*output->funcs->destroy) (output); + while (output->probed_modes) + xf86DeleteMode (&output->probed_modes, output->probed_modes); + for (o = 0; o < xf86_config->num_output; o++) + if (xf86_config->output[o] == output) + { + memmove (&xf86_config->output[o], + &xf86_config->output[o+1], + ((xf86_config->num_output - (o + 1)) * sizeof(void*))); + xf86_config->num_output--; + break; + } + if (output->name && output->name != (char *) (output + 1)) + free(output->name); + free(output); +} + +/* + * Called during CreateScreenResources to hook up RandR + */ +static Bool +xf86CrtcCreateScreenResources (ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + screen->CreateScreenResources = config->CreateScreenResources; + + if (!(*screen->CreateScreenResources)(screen)) + return FALSE; + + if (!xf86RandR12CreateScreenResources (screen)) + return FALSE; + + return TRUE; +} + +/* + * Clean up config on server reset + */ +static Bool +xf86CrtcCloseScreen (int index, ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o, c; + + screen->CloseScreen = config->CloseScreen; + + xf86RotateCloseScreen (screen); + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->randr_output = NULL; + } + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->randr_crtc = NULL; + } + return screen->CloseScreen (index, screen); +} + +/* + * Called at ScreenInit time to set up + */ +#ifdef RANDR_13_INTERFACE +int +#else +Bool +#endif +xf86CrtcScreenInit (ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + /* Rotation */ + xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); + xf86DisableRandR(); /* Disable old RandR extension support */ + xf86RandR12Init (screen); + + /* support all rotations if every crtc has the shadow alloc funcs */ + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) + break; + } + if (c == config->num_crtc) + { + xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | + RR_Rotate_180 | RR_Rotate_270 | + RR_Reflect_X | RR_Reflect_Y); + xf86RandR12SetTransformSupport (screen, TRUE); + } + else + { + xf86RandR12SetRotations (screen, RR_Rotate_0); + xf86RandR12SetTransformSupport (screen, FALSE); + } + + /* Wrap CreateScreenResources so we can initialize the RandR code */ + config->CreateScreenResources = screen->CreateScreenResources; + screen->CreateScreenResources = xf86CrtcCreateScreenResources; + + config->CloseScreen = screen->CloseScreen; + screen->CloseScreen = xf86CrtcCloseScreen; + +#ifdef XFreeXDGA + _xf86_di_dga_init_internal(screen); +#endif +#ifdef RANDR_13_INTERFACE + return RANDR_INTERFACE_VERSION; +#else + return TRUE; +#endif +} + +static DisplayModePtr +xf86DefaultMode (xf86OutputPtr output, int width, int height) +{ + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + int target_preferred = 0; + int mm_height; + + mm_height = output->mm_height; + if (!mm_height) + mm_height = (768 * 25.4) / DEFAULT_DPI; + /* + * Pick a mode closest to DEFAULT_DPI + */ + for (mode = output->probed_modes; mode; mode = mode->next) + { + int dpi; + int preferred = (((mode->type & M_T_PREFERRED) != 0) + + ((mode->type & M_T_USERPREF) != 0)); + int diff; + + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + /* yes, use VDisplay here, not xf86ModeHeight */ + dpi = (mode->VDisplay * 254) / (mm_height * 10); + diff = dpi - DEFAULT_DPI; + diff = diff < 0 ? -diff : diff; + if (target_mode == NULL || (preferred > target_preferred) || + (preferred == target_preferred && diff < target_diff)) + { + target_mode = mode; + target_diff = diff; + target_preferred = preferred; + } + } + return target_mode; +} + +static DisplayModePtr +xf86ClosestMode (xf86OutputPtr output, + DisplayModePtr match, Rotation match_rotation, + int width, int height) +{ + DisplayModePtr target_mode = NULL; + DisplayModePtr mode; + int target_diff = 0; + + /* + * Pick a mode closest to the specified mode + */ + for (mode = output->probed_modes; mode; mode = mode->next) + { + int dx, dy; + int diff; + + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + /* exact matches are preferred */ + if (output->initial_rotation == match_rotation && + xf86ModesEqual (mode, match)) + return mode; + + dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); + dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); + diff = dx * dx + dy * dy; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } + } + return target_mode; +} + +static DisplayModePtr +xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) +{ + DisplayModePtr mode; + + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (xf86ModeWidth (mode, output->initial_rotation) > width || + xf86ModeHeight (mode, output->initial_rotation) > height) + continue; + + if (mode->type & M_T_PREFERRED) + return mode; + } + return NULL; +} + +static DisplayModePtr +xf86OutputHasUserPreferredMode (xf86OutputPtr output) +{ + DisplayModePtr mode, first = output->probed_modes; + + for (mode = first; mode && mode->next != first; mode = mode->next) + if (mode->type & M_T_USERPREF) + return mode; + + return NULL; +} + +static int +xf86PickCrtcs (ScrnInfoPtr scrn, + xf86CrtcPtr *best_crtcs, + DisplayModePtr *modes, + int n, + int width, + int height) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c, o; + xf86OutputPtr output; + xf86CrtcPtr crtc; + xf86CrtcPtr *crtcs; + xf86CrtcPtr best_crtc; + int best_score; + int score; + int my_score; + + if (n == config->num_output) + return 0; + output = config->output[n]; + + /* + * Compute score with this output disabled + */ + best_crtcs[n] = NULL; + best_crtc = NULL; + best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); + if (modes[n] == NULL) + return best_score; + + crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr)); + if (!crtcs) + return best_score; + + my_score = 1; + /* Score outputs that are known to be connected higher */ + if (output->status == XF86OutputStatusConnected) + my_score++; + /* Score outputs with preferred modes higher */ + if (xf86OutputHasPreferredMode (output, width, height)) + my_score++; + /* + * Select a crtc for this output and + * then attempt to configure the remaining + * outputs + */ + for (c = 0; c < config->num_crtc; c++) + { + if ((output->possible_crtcs & (1 << c)) == 0) + continue; + + crtc = config->crtc[c]; + /* + * Check to see if some other output is + * using this crtc + */ + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + if (o < n) + { + /* + * If the two outputs desire the same mode, + * see if they can be cloned + */ + if (xf86ModesEqual (modes[o], modes[n]) && + config->output[o]->initial_rotation == config->output[n]->initial_rotation && + config->output[o]->initial_x == config->output[n]->initial_x && + config->output[o]->initial_y == config->output[n]->initial_y) + { + if ((output->possible_clones & (1 << o)) == 0) + continue; /* nope, try next CRTC */ + } + else + continue; /* different modes, can't clone */ + } + crtcs[n] = crtc; + memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); + score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); + if (score > best_score) + { + best_crtc = crtc; + best_score = score; + memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); + } + } + free(crtcs); + return best_score; +} + + +/* + * Compute the virtual size necessary to place all of the available + * crtcs in the specified configuration. + * + * canGrow indicates that the driver can make the screen larger than its initial + * configuration. If FALSE, this function will enlarge the screen to include + * the largest available mode. + */ + +static void +xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp, + Bool canGrow) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int width = 0, height = 0; + int o; + int c; + int s; + + for (c = 0; c < config->num_crtc; c++) + { + int crtc_width = 0, crtc_height = 0; + xf86CrtcPtr crtc = config->crtc[c]; + + if (crtc->enabled) + { + crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation); + crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation); + } + if (!canGrow) { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + for (s = 0; s < config->num_crtc; s++) + if (output->possible_crtcs & (1 << s)) + { + DisplayModePtr mode; + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (mode->HDisplay > crtc_width) + crtc_width = mode->HDisplay; + if (mode->VDisplay > crtc_width) + crtc_width = mode->VDisplay; + if (mode->VDisplay > crtc_height) + crtc_height = mode->VDisplay; + if (mode->HDisplay > crtc_height) + crtc_height = mode->HDisplay; + } + } + } + } + if (crtc_width > width) + width = crtc_width; + if (crtc_height > height) + height = crtc_height; + } + if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; + if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; + if (config->minWidth && width < config->minWidth) width = config->minWidth; + if (config->minHeight && height < config->minHeight) height = config->minHeight; + *widthp = width; + *heightp = height; +} + +#define POSITION_UNSET -100000 + +/* + * check if the user configured any outputs at all + * with either a position or a relative setting or a mode. + */ +static Bool +xf86UserConfiguredOutputs(ScrnInfoPtr scrn, DisplayModePtr *modes) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + Bool user_conf = FALSE; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + char *position; + char *relative_name; + OutputOpts relation; + int r; + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + + position = xf86GetOptValString (output->options, + OPTION_POSITION); + if (position) + user_conf = TRUE; + + relation = 0; + relative_name = NULL; + for (r = 0; r < 4; r++) + { + relation = relations[r]; + relative_name = xf86GetOptValString (output->options, + relation); + if (relative_name) + break; + } + if (relative_name) + user_conf = TRUE; + + modes[o] = xf86OutputHasUserPreferredMode(output); + if (modes[o]) + user_conf = TRUE; + } + + return user_conf; +} + +static Bool +xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + int min_x, min_y; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x = output->initial_y = POSITION_UNSET; + } + + /* + * Loop until all outputs are set + */ + for (;;) + { + Bool any_set = FALSE; + Bool keep_going = FALSE; + + for (o = 0; o < config->num_output; o++) + { + static const OutputOpts relations[] = { + OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF + }; + xf86OutputPtr output = config->output[o]; + xf86OutputPtr relative; + char *relative_name; + char *position; + OutputOpts relation; + int r; + + if (output->initial_x != POSITION_UNSET) + continue; + position = xf86GetOptValString (output->options, + OPTION_POSITION); + /* + * Absolute position wins + */ + if (position) + { + int x, y; + if (sscanf (position, "%d %d", &x, &y) == 2) + { + output->initial_x = x; + output->initial_y = y; + } + else + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output %s position not of form \"x y\"\n", + output->name); + output->initial_x = output->initial_y = 0; + } + any_set = TRUE; + continue; + } + /* + * Next comes relative positions + */ + relation = 0; + relative_name = NULL; + for (r = 0; r < 4; r++) + { + relation = relations[r]; + relative_name = xf86GetOptValString (output->options, + relation); + if (relative_name) + break; + } + if (relative_name) + { + int or; + relative = NULL; + for (or = 0; or < config->num_output; or++) + { + xf86OutputPtr out_rel = config->output[or]; + XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; + + if (rel_mon) + { + if (xf86nameCompare (rel_mon->mon_identifier, + relative_name) == 0) + { + relative = config->output[or]; + break; + } + } + if (strcmp (out_rel->name, relative_name) == 0) + { + relative = config->output[or]; + break; + } + } + if (!relative) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Cannot position output %s relative to unknown output %s\n", + output->name, relative_name); + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + continue; + } + if (!modes[or]) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Cannot position output %s relative to output %s without modes\n", + output->name, relative_name); + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + continue; + } + if (relative->initial_x == POSITION_UNSET) + { + keep_going = TRUE; + continue; + } + output->initial_x = relative->initial_x; + output->initial_y = relative->initial_y; + switch (relation) { + case OPTION_BELOW: + output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation); + break; + case OPTION_RIGHT_OF: + output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); + break; + case OPTION_ABOVE: + if (modes[o]) + output->initial_y -= xf86ModeHeight (modes[o], output->initial_rotation); + break; + case OPTION_LEFT_OF: + if (modes[o]) + output->initial_x -= xf86ModeWidth (modes[o], output->initial_rotation); + break; + default: + break; + } + any_set = TRUE; + continue; + } + + /* Nothing set, just stick them at 0,0 */ + output->initial_x = 0; + output->initial_y = 0; + any_set = TRUE; + } + if (!keep_going) + break; + if (!any_set) + { + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + if (output->initial_x == POSITION_UNSET) + { + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output position loop. Moving %s to 0,0\n", + output->name); + output->initial_x = output->initial_y = 0; + break; + } + } + } + } + + /* + * normalize positions + */ + min_x = 1000000; + min_y = 1000000; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->initial_x < min_x) + min_x = output->initial_x; + if (output->initial_y < min_y) + min_y = output->initial_y; + } + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->initial_x -= min_x; + output->initial_y -= min_y; + } + return TRUE; +} + +static void +xf86InitialPanning (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + char *panning = xf86GetOptValString (output->options, OPTION_PANNING); + int width, height, left, top; + int track_width, track_height, track_left, track_top; + int brdr[4]; + + memset (&output->initialTotalArea, 0, sizeof(BoxRec)); + memset (&output->initialTrackingArea, 0, sizeof(BoxRec)); + memset (output->initialBorder, 0, 4*sizeof(INT16)); + + if (! panning) + continue; + + switch (sscanf (panning, "%dx%d+%d+%d/%dx%d+%d+%d/%d/%d/%d/%d", + &width, &height, &left, &top, + &track_width, &track_height, &track_left, &track_top, + &brdr[0], &brdr[1], &brdr[2], &brdr[3])) { + case 12: + output->initialBorder[0] = brdr[0]; + output->initialBorder[1] = brdr[1]; + output->initialBorder[2] = brdr[2]; + output->initialBorder[3] = brdr[3]; + /* fall through */ + case 8: + output->initialTrackingArea.x1 = track_left; + output->initialTrackingArea.y1 = track_top; + output->initialTrackingArea.x2 = track_left + track_width; + output->initialTrackingArea.y2 = track_top + track_height; + /* fall through */ + case 4: + output->initialTotalArea.x1 = left; + output->initialTotalArea.y1 = top; + /* fall through */ + case 2: + output->initialTotalArea.x2 = output->initialTotalArea.x1 + width; + output->initialTotalArea.y2 = output->initialTotalArea.y1 + height; + break; + default: + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Broken panning specification '%s' for output %s in config file\n", + panning, output->name); + } + } +} + +/** Return - 0 + if a should be earlier, same or later than b in list + */ +static int +xf86ModeCompare (DisplayModePtr a, DisplayModePtr b) +{ + int diff; + + diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); + if (diff) + return diff; + diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; + if (diff) + return diff; + diff = b->Clock - a->Clock; + return diff; +} + +/** + * Insertion sort input in-place and return the resulting head + */ +static DisplayModePtr +xf86SortModes (DisplayModePtr input) +{ + DisplayModePtr output = NULL, i, o, n, *op, prev; + + /* sort by preferred status and pixel area */ + while (input) + { + i = input; + input = input->next; + for (op = &output; (o = *op); op = &o->next) + if (xf86ModeCompare (o, i) > 0) + break; + i->next = *op; + *op = i; + } + /* prune identical modes */ + for (o = output; o && (n = o->next); o = n) + { + if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) + { + o->next = n->next; + free(n->name); + free(n); + n = o; + } + } + /* hook up backward links */ + prev = NULL; + for (o = output; o; o = o->next) + { + o->prev = prev; + prev = o; + } + return output; +} + +static char * +preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + char *preferred_mode = NULL; + + /* Check for a configured preference for a particular mode */ + preferred_mode = xf86GetOptValString (output->options, + OPTION_PREFERRED_MODE); + if (preferred_mode) + return preferred_mode; + + if (pScrn->display->modes && *pScrn->display->modes) + preferred_mode = *pScrn->display->modes; + + return preferred_mode; +} + +static void +GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) +{ + if (!mon || !mode) + return; + + mon->nHsync = 1; + mon->hsync[0].lo = 1024.0; + mon->hsync[0].hi = 0.0; + + mon->nVrefresh = 1; + mon->vrefresh[0].lo = 1024.0; + mon->vrefresh[0].hi = 0.0; + + while (mode) { + if (!mode->HSync) + mode->HSync = ((float) mode->Clock ) / ((float) mode->HTotal); + + if (!mode->VRefresh) + mode->VRefresh = (1000.0 * ((float) mode->Clock)) / + ((float) (mode->HTotal * mode->VTotal)); + + if (mode->HSync < mon->hsync[0].lo) + mon->hsync[0].lo = mode->HSync; + + if (mode->HSync > mon->hsync[0].hi) + mon->hsync[0].hi = mode->HSync; + + if (mode->VRefresh < mon->vrefresh[0].lo) + mon->vrefresh[0].lo = mode->VRefresh; + + if (mode->VRefresh > mon->vrefresh[0].hi) + mon->vrefresh[0].hi = mode->VRefresh; + + mode = mode->next; + } + + /* stretch out the bottom to fit 640x480@60 */ + if (mon->hsync[0].lo > 31.0) + mon->hsync[0].lo = 31.0; + if (mon->vrefresh[0].lo > 58.0) + mon->vrefresh[0].lo = 58.0; +} + +enum det_monrec_source { + sync_config, sync_edid, sync_default +}; + +struct det_monrec_parameter { + MonRec *mon_rec; + int *max_clock; + Bool set_hsync; + Bool set_vrefresh; + enum det_monrec_source *sync_source; +}; + +static void handle_detailed_monrec(struct detailed_monitor_section *det_mon, + void *data) +{ + enum { sync_config, sync_edid, sync_default }; + struct det_monrec_parameter *p; + p = (struct det_monrec_parameter *)data; + + if (det_mon->type == DS_RANGES) { + struct monitor_ranges *ranges = &det_mon->section.ranges; + if (p->set_hsync && ranges->max_h) { + p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; + p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; + p->mon_rec->nHsync++; + if (*p->sync_source == sync_default) + *p->sync_source = sync_edid; + } + if (p->set_vrefresh && ranges->max_v) { + p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; + p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; + p->mon_rec->nVrefresh++; + if (*p->sync_source == sync_default) + *p->sync_source = sync_edid; + } + if (ranges->max_clock * 1000 > *p->max_clock) + *p->max_clock = ranges->max_clock * 1000; + } +} + +void +xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + /* When canGrow was TRUE in the initial configuration we have to + * compare against the maximum values so that we don't drop modes. + * When canGrow was FALSE, the maximum values would have been clamped + * anyway. + */ + if (maxX == 0 || maxY == 0) { + maxX = config->maxWidth; + maxY = config->maxHeight; + } + + /* Probe the list of modes for each output. */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode; + DisplayModePtr config_modes = NULL, output_modes, default_modes = NULL; + char *preferred_mode; + xf86MonPtr edid_monitor; + XF86ConfMonitorPtr conf_monitor; + MonRec mon_rec; + int min_clock = 0; + int max_clock = 0; + double clock; + Bool add_default_modes = TRUE; + Bool debug_modes = config->debug_modes || + xf86Initialising; + enum det_monrec_source sync_source = sync_default; + + while (output->probed_modes != NULL) + xf86DeleteMode(&output->probed_modes, output->probed_modes); + + /* + * Check connection status + */ + output->status = (*output->funcs->detect)(output); + + if (output->status == XF86OutputStatusDisconnected && + !xf86ReturnOptValBool(output->options, OPTION_ENABLE, FALSE)) + { + xf86OutputSetEDID (output, NULL); + continue; + } + + memset (&mon_rec, '\0', sizeof (mon_rec)); + + conf_monitor = output->conf_monitor; + + if (conf_monitor) + { + int i; + + for (i = 0; i < conf_monitor->mon_n_hsync; i++) + { + mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; + mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; + mon_rec.nHsync++; + sync_source = sync_config; + } + for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) + { + mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; + mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; + mon_rec.nVrefresh++; + sync_source = sync_config; + } + config_modes = xf86GetMonitorModes (scrn, conf_monitor); + } + + output_modes = (*output->funcs->get_modes) (output); + + edid_monitor = output->MonInfo; + + if (edid_monitor) + { + struct det_monrec_parameter p; + struct disp_features *features = &edid_monitor->features; + + /* if display is not continuous-frequency, don't add default modes */ + if (!GTF_SUPPORTED(features->msc)) + add_default_modes = FALSE; + + p.mon_rec = &mon_rec; + p.max_clock = &max_clock; + p.set_hsync = mon_rec.nHsync == 0; + p.set_vrefresh = mon_rec.nVrefresh == 0; + p.sync_source = &sync_source; + + xf86ForEachDetailedBlock(edid_monitor, + handle_detailed_monrec, + &p); + } + + if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, + OPTUNITS_KHZ, &clock)) + min_clock = (int) clock; + if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, + OPTUNITS_KHZ, &clock)) + max_clock = (int) clock; + + /* If we still don't have a sync range, guess wildly */ + if (!mon_rec.nHsync || !mon_rec.nVrefresh) + GuessRangeFromModes(&mon_rec, output_modes); + + /* + * These limits will end up setting a 1024x768@60Hz mode by default, + * which seems like a fairly good mode to use when nothing else is + * specified + */ + if (mon_rec.nHsync == 0) + { + mon_rec.hsync[0].lo = 31.0; + mon_rec.hsync[0].hi = 55.0; + mon_rec.nHsync = 1; + } + if (mon_rec.nVrefresh == 0) + { + mon_rec.vrefresh[0].lo = 58.0; + mon_rec.vrefresh[0].hi = 62.0; + mon_rec.nVrefresh = 1; + } + + if (add_default_modes) + default_modes = xf86GetDefaultModes (); + + /* + * If this is not an RB monitor, remove RB modes from the default + * pool. RB modes from the config or the monitor itself are fine. + */ + if (!mon_rec.reducedblanking) + xf86ValidateModesReducedBlanking (scrn, default_modes); + + if (sync_source == sync_config) + { + /* + * Check output and config modes against sync range from config file + */ + xf86ValidateModesSync (scrn, output_modes, &mon_rec); + xf86ValidateModesSync (scrn, config_modes, &mon_rec); + } + /* + * Check default modes against sync range + */ + xf86ValidateModesSync (scrn, default_modes, &mon_rec); + /* + * Check default modes against monitor max clock + */ + if (max_clock) { + xf86ValidateModesClocks(scrn, default_modes, + &min_clock, &max_clock, 1); + xf86ValidateModesClocks(scrn, output_modes, + &min_clock, &max_clock, 1); + } + + output->probed_modes = NULL; + output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); + output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); + + /* + * Check all modes against max size, interlace, and doublescan + */ + if (maxX && maxY) + xf86ValidateModesSize (scrn, output->probed_modes, + maxX, maxY, 0); + + { + int flags = (output->interlaceAllowed ? V_INTERLACE : 0) | + (output->doubleScanAllowed ? V_DBLSCAN : 0); + xf86ValidateModesFlags (scrn, output->probed_modes, flags); + } + + /* + * Check all modes against output + */ + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + if (mode->status == MODE_OK) + mode->status = (*output->funcs->mode_valid)(output, mode); + + xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); + + output->probed_modes = xf86SortModes (output->probed_modes); + + /* Check for a configured preference for a particular mode */ + preferred_mode = preferredMode(scrn, output); + + if (preferred_mode) + { + for (mode = output->probed_modes; mode; mode = mode->next) + { + if (!strcmp (preferred_mode, mode->name)) + { + if (mode != output->probed_modes) + { + if (mode->prev) + mode->prev->next = mode->next; + if (mode->next) + mode->next->prev = mode->prev; + mode->next = output->probed_modes; + output->probed_modes->prev = mode; + mode->prev = NULL; + output->probed_modes = mode; + } + mode->type |= (M_T_PREFERRED|M_T_USERPREF); + break; + } + } + } + + output->initial_rotation = xf86OutputInitialRotation (output); + + if (debug_modes) { + if (output->probed_modes != NULL) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "Printing probed modes for output %s\n", + output->name); + } else { + xf86DrvMsg(scrn->scrnIndex, X_INFO, + "No remaining probed modes for output %s\n", + output->name); + } + } + for (mode = output->probed_modes; mode != NULL; mode = mode->next) + { + /* The code to choose the best mode per pipe later on will require + * VRefresh to be set. + */ + mode->VRefresh = xf86ModeVRefresh(mode); + xf86SetModeCrtc(mode, INTERLACE_HALVE_V); + + if (debug_modes) + xf86PrintModeline(scrn->scrnIndex, mode); + } + } +} + + +/** + * Copy one of the output mode lists to the ScrnInfo record + */ + +/* XXX where does this function belong? Here? */ +void +xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y); + +static DisplayModePtr +biggestMode(DisplayModePtr a, DisplayModePtr b) +{ + int A, B; + + if (!a) + return b; + if (!b) + return a; + + A = a->HDisplay * a->VDisplay; + B = b->HDisplay * b->VDisplay; + + if (A > B) + return a; + + return b; +} + +static xf86OutputPtr +SetCompatOutput(xf86CrtcConfigPtr config) +{ + xf86OutputPtr output = NULL, test = NULL; + DisplayModePtr maxmode = NULL, testmode, mode; + int o, compat = -1, count, mincount = 0; + + /* Look for one that's definitely connected */ + for (o = 0; o < config->num_output; o++) + { + test = config->output[o]; + if (!test->crtc) + continue; + if (test->status != XF86OutputStatusConnected) + continue; + if (!test->probed_modes) + continue; + + testmode = mode = test->probed_modes; + for (count = 0; mode; mode = mode->next, count++) + testmode = biggestMode(testmode, mode); + + if (!output) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } else if (maxmode == biggestMode(maxmode, testmode)) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } else if ((maxmode->HDisplay == testmode->HDisplay) && + (maxmode->VDisplay == testmode->VDisplay) && + count <= mincount) { + output = test; + compat = o; + maxmode = testmode; + mincount = count; + } + } + + /* If we didn't find one, take anything we can get */ + if (!output) + { + for (o = 0; o < config->num_output; o++) + { + test = config->output[o]; + if (!test->crtc) + continue; + if (!test->probed_modes) + continue; + + if (!output) { + output = test; + compat = o; + } else if (test->probed_modes->HDisplay < output->probed_modes->HDisplay) { + output = test; + compat = o; + } + } + } + + if (compat >= 0) { + config->compat_output = compat; + } else { + /* Don't change the compat output when no valid outputs found */ + output = config->output[config->compat_output]; + } + + return output; +} + +void +xf86SetScrnInfoModes (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + DisplayModePtr last, mode = NULL; + + output = SetCompatOutput(config); + + if (!output) + return; /* punt */ + + crtc = output->crtc; + + /* Clear any existing modes from scrn->modes */ + while (scrn->modes != NULL) + xf86DeleteMode(&scrn->modes, scrn->modes); + + /* Set scrn->modes to the mode list for the 'compat' output */ + scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); + + if (crtc) { + for (mode = scrn->modes; mode; mode = mode->next) + if (xf86ModesEqual (mode, &crtc->desiredMode)) + break; + } + + if (scrn->modes != NULL) { + /* For some reason, scrn->modes is circular, unlike the other mode + * lists. How great is that? + */ + for (last = scrn->modes; last && last->next; last = last->next) + ; + last->next = scrn->modes; + scrn->modes->prev = last; + if (mode) { + while (scrn->modes != mode) + scrn->modes = scrn->modes->next; + } + } + scrn->currentMode = scrn->modes; +#ifdef XFreeXDGA + if (scrn->pScreen) + _xf86_di_dga_reinit_internal(scrn->pScreen); +#endif +} + +static void +xf86CollectEnabledOutputs(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + Bool *enabled) +{ + Bool any_enabled = FALSE; + int o; + + for (o = 0; o < config->num_output; o++) + any_enabled |= enabled[o] = xf86OutputEnabled(config->output[o], TRUE); + + if (!any_enabled) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "No outputs definitely connected, trying again...\n"); + + for (o = 0; o < config->num_output; o++) + enabled[o] = xf86OutputEnabled(config->output[o], FALSE); + } +} + +static Bool +nextEnabledOutput(xf86CrtcConfigPtr config, Bool *enabled, int *index) +{ + int o = *index; + + for (o++; o < config->num_output; o++) { + if (enabled[o]) { + *index = o; + return TRUE; + } + } + + return FALSE; +} + +static Bool +aspectMatch(float a, float b) +{ + return fabs(1 - (a / b)) < 0.05; +} + +static DisplayModePtr +nextAspectMode(xf86OutputPtr o, DisplayModePtr last, float aspect) +{ + DisplayModePtr m = NULL; + + if (!o) + return NULL; + + if (!last) + m = o->probed_modes; + else + m = last->next; + + for (; m; m = m->next) + if (aspectMatch(aspect, (float)m->HDisplay / (float)m->VDisplay)) + return m; + + return NULL; +} + +static DisplayModePtr +bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) +{ + int o = -1, p; + DisplayModePtr mode = NULL, test = NULL, match = NULL; + + if (!nextEnabledOutput(config, enabled, &o)) + return NULL; + while ((mode = nextAspectMode(config->output[o], mode, aspect))) { + test = mode; + for (p = o; nextEnabledOutput(config, enabled, &p); ) { + test = xf86OutputFindClosestMode(config->output[p], mode); + if (!test) + break; + if (test->HDisplay != mode->HDisplay || + test->VDisplay != mode->VDisplay) { + test = NULL; + break; + } + } + + /* if we didn't match it on all outputs, try the next one */ + if (!test) + continue; + + /* if it's bigger than the last one, save it */ + if (!match || (test->HDisplay > match->HDisplay)) + match = test; + } + + /* return the biggest one found */ + return match; +} + +static Bool +xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o, p; + int max_pref_width = 0, max_pref_height = 0; + DisplayModePtr *preferred, *preferred_match; + Bool ret = FALSE; + + preferred = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); + preferred_match = xnfcalloc(config->num_output, sizeof(DisplayModePtr)); + + /* Check if the preferred mode is available on all outputs */ + for (p = -1; nextEnabledOutput(config, enabled, &p); ) { + Rotation r = config->output[p]->initial_rotation; + DisplayModePtr mode; + if ((preferred[p] = xf86OutputHasPreferredMode(config->output[p], + width, height))) { + int pref_width = xf86ModeWidth(preferred[p], r); + int pref_height = xf86ModeHeight(preferred[p], r); + Bool all_match = TRUE; + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + Bool match = FALSE; + xf86OutputPtr output = config->output[o]; + if (o == p) + continue; + + for (mode = output->probed_modes; mode; mode = mode->next) { + Rotation r = output->initial_rotation; + if (xf86ModeWidth(mode, r) == pref_width && + xf86ModeHeight(mode, r) == pref_height) { + preferred[o] = mode; + match = TRUE; + } + } + + all_match &= match; + } + + if (all_match && + (pref_width*pref_height > max_pref_width*max_pref_height)) { + for (o = -1; nextEnabledOutput(config, enabled, &o); ) + preferred_match[o] = preferred[o]; + max_pref_width = pref_width; + max_pref_height = pref_height; + ret = TRUE; + } + } + } + + /* + * If there's no preferred mode, but only one monitor, pick the + * biggest mode for its aspect ratio, assuming one exists. + */ + if (!ret) do { + int i = 0; + float aspect = 0.0; + + /* count the number of enabled outputs */ + for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; + + if (i != 1) + break; + + p = -1; + nextEnabledOutput(config, enabled, &p); + if (config->output[p]->mm_height) + aspect = (float)config->output[p]->mm_width / + (float)config->output[p]->mm_height; + + if (aspect) + preferred_match[p] = bestModeForAspect(config, enabled, aspect); + + if (preferred_match[p]) + ret = TRUE; + + } while (0); + + if (ret) { + /* oh good, there is a match. stash the selected modes and return. */ + memcpy(modes, preferred_match, + config->num_output * sizeof(DisplayModePtr)); + } + + free(preferred); + free(preferred_match); + return ret; +} + +static Bool +xf86TargetAspect(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o; + float aspect = 0.0, *aspects; + xf86OutputPtr output; + Bool ret = FALSE; + DisplayModePtr guess = NULL, aspect_guess = NULL, base_guess = NULL; + + aspects = xnfcalloc(config->num_output, sizeof(float)); + + /* collect the aspect ratios */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + output = config->output[o]; + if (output->mm_height) + aspects[o] = (float)output->mm_width / (float)output->mm_height; + else + aspects[o] = 4.0 / 3.0; + } + + /* check that they're all the same */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + output = config->output[o]; + if (!aspect) { + aspect = aspects[o]; + } else if (!aspectMatch(aspect, aspects[o])) { + goto no_aspect_match; + } + } + + /* if they're all 4:3, just skip ahead and save effort */ + if (!aspectMatch(aspect, 4.0/3.0)) + aspect_guess = bestModeForAspect(config, enabled, aspect); + +no_aspect_match: + base_guess = bestModeForAspect(config, enabled, 4.0/3.0); + + guess = biggestMode(base_guess, aspect_guess); + + if (!guess) + goto out; + + /* found a mode that works everywhere, now apply it */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + modes[o] = xf86OutputFindClosestMode(config->output[o], guess); + } + ret = TRUE; + +out: + free(aspects); + return ret; +} + +static Bool +xf86TargetFallback(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + DisplayModePtr target_mode = NULL; + Rotation target_rotation = RR_Rotate_0; + DisplayModePtr default_mode; + int default_preferred, target_preferred = 0, o; + + /* User preferred > preferred > other modes */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + default_mode = xf86DefaultMode (config->output[o], width, height); + if (!default_mode) + continue; + + default_preferred = (((default_mode->type & M_T_PREFERRED) != 0) + + ((default_mode->type & M_T_USERPREF) != 0)); + + if (default_preferred > target_preferred || !target_mode) { + target_mode = default_mode; + target_preferred = default_preferred; + target_rotation = config->output[o]->initial_rotation; + config->compat_output = o; + } + } + + if (target_mode) + modes[config->compat_output] = target_mode; + + /* Fill in other output modes */ + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + if (!modes[o]) + modes[o] = xf86ClosestMode(config->output[o], target_mode, + target_rotation, width, height); + } + + return (target_mode != NULL); +} + +static Bool +xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o; + + if (xf86UserConfiguredOutputs(scrn, modes)) + return xf86TargetFallback(scrn, config, modes, enabled, width, height); + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) + if (xf86OutputHasUserPreferredMode(config->output[o])) + return + xf86TargetFallback(scrn, config, modes, enabled, width, height); + + return FALSE; +} + +static Bool +xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, + float gamma_blue) +{ + int i, size = 256; + CARD16 *red, *green, *blue; + + red = malloc(3 * size * sizeof(CARD16)); + green = red + size; + blue = green + size; + + /* Only cause warning if user wanted gamma to be set. */ + if (!crtc->funcs->gamma_set && (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { + free(red); + return FALSE; + } else if (!crtc->funcs->gamma_set) { + free(red); + return TRUE; + } + + /* At this early stage none of the randr-interface stuff is up. + * So take the default gamma size for lack of something better. + */ + for (i = 0; i < size; i++) { + if (gamma_red == 1.0) + red[i] = i << 8; + else + red[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_red) * (double)(size - 1) * 256); + + if (gamma_green == 1.0) + green[i] = i << 8; + else + green[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_green) * (double)(size - 1) * 256); + + if (gamma_blue == 1.0) + blue[i] = i << 8; + else + blue[i] = (CARD16)(pow((double)i/(double)(size - 1), + 1. / (double)gamma_blue) * (double)(size - 1) * 256); + } + + /* Default size is 256, so anything else is failure. */ + if (size != crtc->gamma_size) { + free(red); + return FALSE; + } + + crtc->gamma_size = size; + memcpy (crtc->gamma_red, red, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_green, green, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_blue, blue, crtc->gamma_size * sizeof (CARD16)); + + /* Do not set gamma now, delay until the crtc is activated. */ + + free(red); + + return TRUE; +} + +static Bool +xf86OutputSetInitialGamma(xf86OutputPtr output) +{ + XF86ConfMonitorPtr mon = output->conf_monitor; + float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; + + if (!mon) + return TRUE; + + if (!output->crtc) + return FALSE; + + /* Get configured values, where they exist. */ + if (mon->mon_gamma_red >= GAMMA_MIN && + mon->mon_gamma_red <= GAMMA_MAX) + gamma_red = mon->mon_gamma_red; + + if (mon->mon_gamma_green >= GAMMA_MIN && + mon->mon_gamma_green <= GAMMA_MAX) + gamma_green = mon->mon_gamma_green; + + if (mon->mon_gamma_blue >= GAMMA_MIN && + mon->mon_gamma_blue <= GAMMA_MAX) + gamma_blue = mon->mon_gamma_blue; + + /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ + if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { + xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", output->name, gamma_red, gamma_green, gamma_blue); + return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, gamma_blue); + }else + return TRUE; +} + +/** + * Construct default screen configuration + * + * Given auto-detected (and, eventually, configured) values, + * construct a usable configuration for the system + * + * canGrow indicates that the driver can resize the screen to larger than its + * initially configured size via the config->funcs->resize hook. If TRUE, this + * function will set virtualX and virtualY to match the initial configuration + * and leave config->max{Width,Height} alone. If FALSE, it will bloat + * virtual[XY] to include the largest modes and set config->max{Width,Height} + * accordingly. + */ + +Bool +xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o, c; + xf86CrtcPtr *crtcs; + DisplayModePtr *modes; + Bool *enabled; + int width, height; + int i = scrn->scrnIndex; + + /* Set up the device options */ + config->options = xnfalloc (sizeof (xf86DeviceOptions)); + memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions)); + xf86ProcessOptions (scrn->scrnIndex, + scrn->options, + config->options); + config->debug_modes = xf86ReturnOptValBool (config->options, + OPTION_MODEDEBUG, FALSE); + + if (scrn->display->virtualX) + width = scrn->display->virtualX; + else + width = config->maxWidth; + if (scrn->display->virtualY) + height = scrn->display->virtualY; + else + height = config->maxHeight; + + xf86ProbeOutputModes (scrn, width, height); + + crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); + modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); + enabled = xnfcalloc (config->num_output, sizeof (Bool)); + + xf86CollectEnabledOutputs(scrn, config, enabled); + + if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); + else if (xf86TargetPreferred(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); + else if (xf86TargetAspect(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using fuzzy aspect match for initial modes\n"); + else if (xf86TargetFallback(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using sloppy heuristic for initial modes\n"); + else + xf86DrvMsg(i, X_WARNING, "Unable to find initial modes\n"); + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + if (!modes[o]) + xf86DrvMsg (scrn->scrnIndex, X_ERROR, + "Output %s enabled but has no modes\n", + config->output[o]->name); + else + xf86DrvMsg (scrn->scrnIndex, X_INFO, + "Output %s using initial mode %s\n", + config->output[o]->name, modes[o]->name); + } + + /* + * Set the position of each output + */ + if (!xf86InitialOutputPositions (scrn, modes)) + { + free(crtcs); + free(modes); + return FALSE; + } + + /* + * Set initial panning of each output + */ + xf86InitialPanning (scrn); + + /* + * Assign CRTCs to fit output configuration + */ + if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) + { + free(crtcs); + free(modes); + return FALSE; + } + + /* XXX override xf86 common frame computation code */ + + scrn->display->frameX0 = 0; + scrn->display->frameY0 = 0; + + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->enabled = FALSE; + memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); + /* Set default gamma for all crtc's. */ + /* This is done to avoid problems later on with cloned outputs. */ + xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); + } + + if (xf86_crtc_supports_gamma(scrn)) + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Using default gamma of (1.0, 1.0, 1.0) unless otherwise stated.\n"); + + /* + * Set initial configuration + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr mode = modes[o]; + xf86CrtcPtr crtc = crtcs[o]; + + if (mode && crtc) + { + crtc->desiredMode = *mode; + crtc->desiredRotation = output->initial_rotation; + crtc->desiredX = output->initial_x; + crtc->desiredY = output->initial_y; + crtc->desiredTransformPresent = FALSE; + crtc->enabled = TRUE; + memcpy (&crtc->panningTotalArea, &output->initialTotalArea, sizeof(BoxRec)); + memcpy (&crtc->panningTrackingArea, &output->initialTrackingArea, sizeof(BoxRec)); + memcpy (crtc->panningBorder, output->initialBorder, 4*sizeof(INT16)); + output->crtc = crtc; + if (!xf86OutputSetInitialGamma(output)) + xf86DrvMsg (scrn->scrnIndex, X_WARNING, "Initial gamma correction for output %s: failed.\n", output->name); + } else { + output->crtc = NULL; + } + } + + if (scrn->display->virtualX == 0) + { + /* + * Expand virtual size to cover the current config and potential mode + * switches, if the driver can't enlarge the screen later. + */ + xf86DefaultScreenLimits (scrn, &width, &height, canGrow); + + scrn->display->virtualX = width; + scrn->display->virtualY = height; + } + + if (width > scrn->virtualX) + scrn->virtualX = width; + if (height > scrn->virtualY) + scrn->virtualY = height; + + /* + * Make sure the configuration isn't too small. + */ + if (width < config->minWidth || height < config->minHeight) + return FALSE; + + /* + * Limit the crtc config to virtual[XY] if the driver can't grow the + * desktop. + */ + if (!canGrow) + { + xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight, + width, height); + } + + /* Mirror output modes to scrn mode list */ + xf86SetScrnInfoModes (scrn); + + free(crtcs); + free(modes); + return TRUE; +} + +/* + * Check the CRTC we're going to map each output to vs. it's current + * CRTC. If they don't match, we have to disable the output and the CRTC + * since the driver will have to re-route things. + */ +static void +xf86PrepareOutputs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int o; + + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr output = config->output[o]; +#if RANDR_GET_CRTC_INTERFACE + /* Disable outputs that are unused or will be re-routed */ + if (!output->funcs->get_crtc || + output->crtc != (*output->funcs->get_crtc)(output) || + output->crtc == NULL) +#endif + (*output->funcs->dpms)(output, DPMSModeOff); + } +} + +static void +xf86PrepareCrtcs (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + for (c = 0; c < config->num_crtc; c++) { +#if RANDR_GET_CRTC_INTERFACE + xf86CrtcPtr crtc = config->crtc[c]; + xf86OutputPtr output = NULL; + uint32_t desired_outputs = 0, current_outputs = 0; + int o; + + for (o = 0; o < config->num_output; o++) { + output = config->output[o]; + if (output->crtc == crtc) + desired_outputs |= (1<funcs->get_crtc) { + desired_outputs = 0; + break; + } + if ((*output->funcs->get_crtc)(output) == crtc) + current_outputs |= (1<funcs->dpms)(crtc, DPMSModeOff); +#else + (*crtc->funcs->dpms)(crtc, DPMSModeOff); +#endif + } +} + +/* + * Using the desired mode information in each crtc, set + * modes (used in EnterVT functions, or at server startup) + */ + +Bool +xf86SetDesiredModes (ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc = config->crtc[0]; + int c; + + /* A driver with this hook will take care of this */ + if (!crtc->funcs->set_mode_major) { + xf86PrepareOutputs(scrn); + xf86PrepareCrtcs(scrn); + } + + for (c = 0; c < config->num_crtc; c++) + { + xf86OutputPtr output = NULL; + int o; + RRTransformPtr transform; + + crtc = config->crtc[c]; + + /* Skip disabled CRTCs */ + if (!crtc->enabled) + continue; + + if (xf86CompatOutput(scrn) && xf86CompatCrtc(scrn) == crtc) + output = xf86CompatOutput(scrn); + else + { + for (o = 0; o < config->num_output; o++) + if (config->output[o]->crtc == crtc) + { + output = config->output[o]; + break; + } + } + /* paranoia */ + if (!output) + continue; + + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desiredMode.CrtcHDisplay) + { + DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode); + + if (!mode) + return FALSE; + crtc->desiredMode = *mode; + crtc->desiredRotation = RR_Rotate_0; + crtc->desiredTransformPresent = FALSE; + crtc->desiredX = 0; + crtc->desiredY = 0; + } + + if (crtc->desiredTransformPresent) + transform = &crtc->desiredTransform; + else + transform = NULL; + if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation, + transform, crtc->desiredX, crtc->desiredY)) + return FALSE; + } + + xf86DisableUnusedFunctions(scrn); + return TRUE; +} + +/** + * In the current world order, there are lists of modes per output, which may + * or may not include the mode that was asked to be set by XFree86's mode + * selection. Find the closest one, in the following preference order: + * + * - Equality + * - Closer in size to the requested mode, but no larger + * - Closer in refresh rate to the requested mode. + */ + +DisplayModePtr +xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired) +{ + DisplayModePtr best = NULL, scan = NULL; + + for (scan = output->probed_modes; scan != NULL; scan = scan->next) + { + /* If there's an exact match, we're done. */ + if (xf86ModesEqual(scan, desired)) { + best = desired; + break; + } + + /* Reject if it's larger than the desired mode. */ + if (scan->HDisplay > desired->HDisplay || + scan->VDisplay > desired->VDisplay) + { + continue; + } + + /* + * If we haven't picked a best mode yet, use the first + * one in the size range + */ + if (best == NULL) + { + best = scan; + continue; + } + + /* Find if it's closer to the right size than the current best + * option. + */ + if ((scan->HDisplay > best->HDisplay && + scan->VDisplay >= best->VDisplay) || + (scan->HDisplay >= best->HDisplay && + scan->VDisplay > best->VDisplay)) + { + best = scan; + continue; + } + + /* Find if it's still closer to the right refresh than the current + * best resolution. + */ + if (scan->HDisplay == best->HDisplay && + scan->VDisplay == best->VDisplay && + (fabs(scan->VRefresh - desired->VRefresh) < + fabs(best->VRefresh - desired->VRefresh))) { + best = scan; + } + } + return best; +} + +/** + * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, + * take the specified mode and apply it to the crtc connected to the compat + * output. Then, find similar modes for the other outputs, as with the + * InitialConfiguration code above. The goal is to clone the desired + * mode across all outputs that are currently active. + */ + +Bool +xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + Bool ok = TRUE; + xf86OutputPtr compat_output; + DisplayModePtr compat_mode = NULL; + int c; + + /* + * Let the compat output drive the final mode selection + */ + compat_output = xf86CompatOutput(pScrn); + if (compat_output) + compat_mode = xf86OutputFindClosestMode (compat_output, desired); + if (compat_mode) + desired = compat_mode; + + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + DisplayModePtr crtc_mode = NULL; + int o; + + if (!crtc->enabled) + continue; + + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + DisplayModePtr output_mode; + + /* skip outputs not on this crtc */ + if (output->crtc != crtc) + continue; + + if (crtc_mode) + { + output_mode = xf86OutputFindClosestMode (output, crtc_mode); + if (output_mode != crtc_mode) + output->crtc = NULL; + } + else + crtc_mode = xf86OutputFindClosestMode (output, desired); + } + if (!crtc_mode) + { + crtc->enabled = FALSE; + continue; + } + if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0)) + ok = FALSE; + else + { + crtc->desiredMode = *crtc_mode; + crtc->desiredRotation = rotation; + crtc->desiredTransformPresent = FALSE; + crtc->desiredX = 0; + crtc->desiredY = 0; + } + } + xf86DisableUnusedFunctions(pScrn); +#ifdef RANDR_12_INTERFACE + xf86RandR12TellChanged (pScrn->pScreen); +#endif + return ok; +} + + +/** + * Set the DPMS power mode of all outputs and CRTCs. + * + * If the new mode is off, it will turn off outputs and then CRTCs. + * Otherwise, it will affect CRTCs before outputs. + */ +void +xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + + if (!scrn->vtSema) + return; + + if (mode == DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } + + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + if (crtc->enabled) + (*crtc->funcs->dpms) (crtc, mode); + } + + if (mode != DPMSModeOff) { + for (i = 0; i < config->num_output; i++) { + xf86OutputPtr output = config->output[i]; + if (output->crtc != NULL) + (*output->funcs->dpms) (output, mode); + } + } +} + +/** + * Implement the screensaver by just calling down into the driver DPMS hooks. + * + * Even for monitors with no DPMS support, by the definition of our DPMS hooks, + * the outputs will still get disabled (blanked). + */ +Bool +xf86SaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (xf86IsUnblank(mode)) + xf86DPMSSet(pScrn, DPMSModeOn, 0); + else + xf86DPMSSet(pScrn, DPMSModeOff, 0); + + return TRUE; +} + +/** + * Disable all inactive crtcs and outputs + */ +void +xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int o, c; + + for (o = 0; o < xf86_config->num_output; o++) + { + xf86OutputPtr output = xf86_config->output[o]; + if (!output->crtc) + (*output->funcs->dpms)(output, DPMSModeOff); + } + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (!crtc->enabled) + { + crtc->funcs->dpms(crtc, DPMSModeOff); + memset(&crtc->mode, 0, sizeof(crtc->mode)); + xf86RotateDestroy(crtc); + crtc->active = FALSE; + } + } + if (pScrn->pScreen) + xf86_crtc_notify(pScrn->pScreen); +} + +#ifdef RANDR_12_INTERFACE + +#define EDID_ATOM_NAME "EDID" + +/** + * Set the RandR EDID property + */ +static void +xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) +{ + Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE); + + /* This may get called before the RandR resources have been created */ + if (output->randr_output == NULL) + return; + + if (data_len != 0) { + RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, + PropModeReplace, data_len, data, FALSE, TRUE); + } else { + RRDeleteOutputProperty(output->randr_output, edid_atom); + } +} + +#endif + +/* Pull out a phyiscal size from a detailed timing if available. */ +struct det_phySize_parameter { + xf86OutputPtr output; + ddc_quirk_t quirks; + Bool ret; +}; + +static void handle_detailed_physical_size(struct detailed_monitor_section + *det_mon, void *data) +{ + struct det_phySize_parameter *p; + p = (struct det_phySize_parameter *)data; + + if (p->ret == TRUE ) + return ; + + xf86DetTimingApplyQuirks(det_mon, p->quirks, + p->output->MonInfo->features.hsize, + p->output->MonInfo->features.vsize); + if (det_mon->type == DT && + det_mon->section.d_timings.h_size != 0 && + det_mon->section.d_timings.v_size != 0) { + + p->output->mm_width = det_mon->section.d_timings.h_size; + p->output->mm_height = det_mon->section.d_timings.v_size; + p->ret = TRUE; + } +} + +/** + * Set the EDID information for the specified output + */ +void +xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) +{ + ScrnInfoPtr scrn = output->scrn; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + Bool debug_modes = config->debug_modes || xf86Initialising; +#ifdef RANDR_12_INTERFACE + int size; +#endif + + if (output->MonInfo != NULL) + free(output->MonInfo); + + output->MonInfo = edid_mon; + + if (debug_modes) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", + output->name); + xf86PrintEDID(edid_mon); + } + + /* Set the DDC properties for the 'compat' output */ + if (output == xf86CompatOutput(scrn)) + xf86SetDDCproperties(scrn, edid_mon); + +#ifdef RANDR_12_INTERFACE + /* Set the RandR output properties */ + size = 0; + if (edid_mon) + { + if (edid_mon->ver.version == 1) { + size = 128; + if (edid_mon->flags & EDID_COMPLETE_RAWDATA) + size += edid_mon->no_sections * 128; + } else if (edid_mon->ver.version == 2) + size = 256; + } + xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); +#endif + + if (edid_mon) { + + struct det_phySize_parameter p; + p.output = output; + p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE); + p.ret = FALSE; + xf86ForEachDetailedBlock(edid_mon, + handle_detailed_physical_size, &p); + + /* if no mm size is available from a detailed timing, check the max size field */ + if ((!output->mm_width || !output->mm_height) && + (edid_mon->features.hsize && edid_mon->features.vsize)) + { + output->mm_width = edid_mon->features.hsize * 10; + output->mm_height = edid_mon->features.vsize * 10; + } + } +} + +/** + * Return the list of modes supported by the EDID information + * stored in 'output' + */ +DisplayModePtr +xf86OutputGetEDIDModes (xf86OutputPtr output) +{ + ScrnInfoPtr scrn = output->scrn; + xf86MonPtr edid_mon = output->MonInfo; + + if (!edid_mon) + return NULL; + return xf86DDCGetModes(scrn->scrnIndex, edid_mon); +} + +/* maybe we should care about DDC1? meh. */ +xf86MonPtr +xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) +{ + ScrnInfoPtr scrn = output->scrn; + xf86MonPtr mon; + + mon = xf86DoEEDID(scrn->scrnIndex, pDDCBus, TRUE); + if (mon) + xf86DDCApplyQuirks(scrn->scrnIndex, mon); + + return mon; +} + +static char *_xf86ConnectorNames[] = { + "None", "VGA", "DVI-I", "DVI-D", + "DVI-A", "Composite", "S-Video", + "Component", "LFP", "Proprietary", + "HDMI", "DisplayPort", + }; +char * +xf86ConnectorGetName(xf86ConnectorType connector) +{ + return _xf86ConnectorNames[connector]; +} + +static void +x86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) +{ + dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; + dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; + dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; + + if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; +} + +static void +x86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->enabled) { + crtc_box->x1 = crtc->x; + crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); + crtc_box->y1 = crtc->y; + crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static int +xf86_crtc_box_area(BoxPtr box) +{ + return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); +} + +/* + * Return the crtc covering 'box'. If two crtcs cover a portion of + * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc + * with greater coverage + */ + +static xf86CrtcPtr +xf86_covering_crtc(ScrnInfoPtr pScrn, + BoxPtr box, + xf86CrtcPtr desired, + BoxPtr crtc_box_ret) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc, best_crtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + best_crtc = NULL; + best_coverage = 0; + crtc_box_ret->x1 = 0; + crtc_box_ret->x2 = 0; + crtc_box_ret->y1 = 0; + crtc_box_ret->y2 = 0; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + x86_crtc_box(crtc, &crtc_box); + x86_crtc_box_intersect(&cover_box, &crtc_box, box); + coverage = xf86_crtc_box_area(&cover_box); + if (coverage && crtc == desired) { + *crtc_box_ret = crtc_box; + return crtc; + } else if (coverage > best_coverage) { + *crtc_box_ret = crtc_box; + best_crtc = crtc; + best_coverage = coverage; + } + } + return best_crtc; +} + +/* + * For overlay video, compute the relevant CRTC and + * clip video to that. + * + * returning FALSE means there was a memory failure of some kind, + * not that the video shouldn't be displayed + */ + +Bool +xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, + xf86CrtcPtr *crtc_ret, + xf86CrtcPtr desired_crtc, + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height) +{ + Bool ret; + RegionRec crtc_region_local; + RegionPtr crtc_region = reg; + + if (crtc_ret) { + BoxRec crtc_box; + xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, + desired_crtc, + &crtc_box); + + if (crtc) { + REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); + crtc_region = &crtc_region_local; + REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); + } + *crtc_ret = crtc; + } + + ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, + crtc_region, width, height); + + if (crtc_region != reg) + REGION_UNINIT (pScreen, &crtc_region_local); + + return ret; +} + +xf86_crtc_notify_proc_ptr +xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new) +{ + if (xf86CrtcConfigPrivateIndex != -1) + { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + xf86_crtc_notify_proc_ptr old; + + old = config->xf86_crtc_notify; + config->xf86_crtc_notify = new; + return old; + } + return NULL; +} + +void +xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old) +{ + if (xf86CrtcConfigPrivateIndex != -1) + { + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + config->xf86_crtc_notify = old; + } +} + +void +xf86_crtc_notify(ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + + if (config->xf86_crtc_notify) + config->xf86_crtc_notify(screen); +} + +Bool +xf86_crtc_supports_gamma(ScrnInfoPtr pScrn) +{ + if (xf86CrtcConfigPrivateIndex != -1) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc; + + /* for multiple drivers loaded we need this */ + if (!xf86_config) + return FALSE; + if (xf86_config->num_crtc == 0) + return FALSE; + crtc = xf86_config->crtc[0]; + + return (crtc->funcs->gamma_set != NULL); + } + + return FALSE; +} diff --git a/xorg-server/hw/xfree86/modes/xf86Cursors.c b/xorg-server/hw/xfree86/modes/xf86Cursors.c index 3e765e6ff..e9770f8b9 100644 --- a/xorg-server/hw/xfree86/modes/xf86Cursors.c +++ b/xorg-server/hw/xfree86/modes/xf86Cursors.c @@ -551,7 +551,7 @@ xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags) if (!cursor_info) return FALSE; - xf86_config->cursor_image = xalloc (max_width * max_height * 4); + xf86_config->cursor_image = malloc(max_width * max_height * 4); if (!xf86_config->cursor_image) { @@ -661,7 +661,7 @@ xf86_cursors_fini (ScreenPtr screen) } if (xf86_config->cursor_image) { - xfree (xf86_config->cursor_image); + free(xf86_config->cursor_image); xf86_config->cursor_image = NULL; } if (xf86_config->cursor) diff --git a/xorg-server/hw/xfree86/modes/xf86DiDGA.c b/xorg-server/hw/xfree86/modes/xf86DiDGA.c index 60fbdbf05..61c779edc 100644 --- a/xorg-server/hw/xfree86/modes/xf86DiDGA.c +++ b/xorg-server/hw/xfree86/modes/xf86DiDGA.c @@ -1,218 +1,218 @@ -/* - * Copyright © 2006 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#else -#ifdef HAVE_CONFIG_H -#include -#endif -#endif - -#include "xf86.h" -#include "xf86DDC.h" -#include "xf86_OSproc.h" -#include "dgaproc.h" -#include "xf86Crtc.h" -#include "xf86Modes.h" -#include "gcstruct.h" -#include "scrnintstr.h" -#include "windowstr.h" - -static Bool -xf86_dga_get_modes (ScreenPtr pScreen) -{ - ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - DGAModePtr modes, mode; - DisplayModePtr display_mode; - int bpp = scrn->bitsPerPixel >> 3; - int num; - - num = 0; - display_mode = scrn->modes; - while (display_mode) - { - num++; - display_mode = display_mode->next; - if (display_mode == scrn->modes) - break; - } - - if (!num) - return FALSE; - - modes = xalloc(num * sizeof(DGAModeRec)); - if (!modes) - return FALSE; - - num = 0; - display_mode = scrn->modes; - while (display_mode) - { - mode = modes + num++; - - mode->mode = display_mode; - mode->flags = DGA_CONCURRENT_ACCESS; - if (display_mode->Flags & V_DBLSCAN) - mode->flags |= DGA_DOUBLESCAN; - if (display_mode->Flags & V_INTERLACE) - mode->flags |= DGA_INTERLACED; - mode->byteOrder = scrn->imageByteOrder; - mode->depth = scrn->depth; - mode->bitsPerPixel = scrn->bitsPerPixel; - mode->red_mask = scrn->mask.red; - mode->green_mask = scrn->mask.green; - mode->blue_mask = scrn->mask.blue; - mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor; - mode->viewportWidth = display_mode->HDisplay; - mode->viewportHeight = display_mode->VDisplay; - mode->xViewportStep = (bpp == 3) ? 2 : 1; - mode->yViewportStep = 1; - mode->viewportFlags = DGA_FLIP_RETRACE; - mode->offset = 0; - mode->address = 0; - mode->imageWidth = mode->viewportWidth; - mode->imageHeight = mode->viewportHeight; - mode->bytesPerScanline = (mode->imageWidth * scrn->bitsPerPixel) >> 3; - mode->pixmapWidth = mode->imageWidth; - mode->pixmapHeight = mode->imageHeight; - mode->maxViewportX = 0; - mode->maxViewportY = 0; - - display_mode = display_mode->next; - if (display_mode == scrn->modes) - break; - } - if (xf86_config->dga_modes) - xfree (xf86_config->dga_modes); - xf86_config->dga_nmode = num; - xf86_config->dga_modes = modes; - return TRUE; -} - -static Bool -xf86_dga_set_mode(ScrnInfoPtr scrn, DGAModePtr display_mode) -{ - ScreenPtr pScreen = scrn->pScreen; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - - if (!display_mode) - { - if (xf86_config->dga_save_mode) - { - xf86SwitchMode(pScreen, xf86_config->dga_save_mode); - xf86_config->dga_save_mode = NULL; - } - } - else - { - if (!xf86_config->dga_save_mode) - { - xf86_config->dga_save_mode = scrn->currentMode; - xf86SwitchMode(pScreen, display_mode->mode); - } - } - return TRUE; -} - -static int -xf86_dga_get_viewport(ScrnInfoPtr scrn) -{ - return 0; -} - -static void -xf86_dga_set_viewport(ScrnInfoPtr scrn, int x, int y, int flags) -{ - scrn->AdjustFrame(scrn->pScreen->myNum, x, y, flags); -} - -static Bool -xf86_dga_open_framebuffer(ScrnInfoPtr scrn, - char **name, - unsigned char **mem, int *size, int *offset, int *flags) -{ - return FALSE; -} - -static void -xf86_dga_close_framebuffer(ScrnInfoPtr scrn) -{ -} - -static DGAFunctionRec xf86_dga_funcs = { - xf86_dga_open_framebuffer, - xf86_dga_close_framebuffer, - xf86_dga_set_mode, - xf86_dga_set_viewport, - xf86_dga_get_viewport, - NULL, - NULL, - NULL, - NULL -}; - -Bool -xf86DiDGAReInit (ScreenPtr pScreen) -{ - return TRUE; -} - -Bool -_xf86_di_dga_reinit_internal (ScreenPtr pScreen) -{ - ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - - if (!DGAAvailable(pScreen->myNum)) - return TRUE; - - if (!xf86_dga_get_modes (pScreen)) - return FALSE; - - return DGAReInitModes (pScreen, xf86_config->dga_modes, xf86_config->dga_nmode); -} - -Bool -xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address) -{ - return TRUE; -} - -Bool -_xf86_di_dga_init_internal (ScreenPtr pScreen) -{ - ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - - xf86_config->dga_flags = 0; - xf86_config->dga_address = 0; - xf86_config->dga_width = 0; - xf86_config->dga_height = 0; - xf86_config->dga_stride = 0; - - if (!xf86_dga_get_modes (pScreen)) - return FALSE; - - return DGAInit(pScreen, &xf86_dga_funcs, xf86_config->dga_modes, xf86_config->dga_nmode); -} +/* + * Copyright © 2006 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#else +#ifdef HAVE_CONFIG_H +#include +#endif +#endif + +#include "xf86.h" +#include "xf86DDC.h" +#include "xf86_OSproc.h" +#include "dgaproc.h" +#include "xf86Crtc.h" +#include "xf86Modes.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "windowstr.h" + +static Bool +xf86_dga_get_modes (ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + DGAModePtr modes, mode; + DisplayModePtr display_mode; + int bpp = scrn->bitsPerPixel >> 3; + int num; + + num = 0; + display_mode = scrn->modes; + while (display_mode) + { + num++; + display_mode = display_mode->next; + if (display_mode == scrn->modes) + break; + } + + if (!num) + return FALSE; + + modes = malloc(num * sizeof(DGAModeRec)); + if (!modes) + return FALSE; + + num = 0; + display_mode = scrn->modes; + while (display_mode) + { + mode = modes + num++; + + mode->mode = display_mode; + mode->flags = DGA_CONCURRENT_ACCESS; + if (display_mode->Flags & V_DBLSCAN) + mode->flags |= DGA_DOUBLESCAN; + if (display_mode->Flags & V_INTERLACE) + mode->flags |= DGA_INTERLACED; + mode->byteOrder = scrn->imageByteOrder; + mode->depth = scrn->depth; + mode->bitsPerPixel = scrn->bitsPerPixel; + mode->red_mask = scrn->mask.red; + mode->green_mask = scrn->mask.green; + mode->blue_mask = scrn->mask.blue; + mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor; + mode->viewportWidth = display_mode->HDisplay; + mode->viewportHeight = display_mode->VDisplay; + mode->xViewportStep = (bpp == 3) ? 2 : 1; + mode->yViewportStep = 1; + mode->viewportFlags = DGA_FLIP_RETRACE; + mode->offset = 0; + mode->address = 0; + mode->imageWidth = mode->viewportWidth; + mode->imageHeight = mode->viewportHeight; + mode->bytesPerScanline = (mode->imageWidth * scrn->bitsPerPixel) >> 3; + mode->pixmapWidth = mode->imageWidth; + mode->pixmapHeight = mode->imageHeight; + mode->maxViewportX = 0; + mode->maxViewportY = 0; + + display_mode = display_mode->next; + if (display_mode == scrn->modes) + break; + } + if (xf86_config->dga_modes) + free(xf86_config->dga_modes); + xf86_config->dga_nmode = num; + xf86_config->dga_modes = modes; + return TRUE; +} + +static Bool +xf86_dga_set_mode(ScrnInfoPtr scrn, DGAModePtr display_mode) +{ + ScreenPtr pScreen = scrn->pScreen; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + + if (!display_mode) + { + if (xf86_config->dga_save_mode) + { + xf86SwitchMode(pScreen, xf86_config->dga_save_mode); + xf86_config->dga_save_mode = NULL; + } + } + else + { + if (!xf86_config->dga_save_mode) + { + xf86_config->dga_save_mode = scrn->currentMode; + xf86SwitchMode(pScreen, display_mode->mode); + } + } + return TRUE; +} + +static int +xf86_dga_get_viewport(ScrnInfoPtr scrn) +{ + return 0; +} + +static void +xf86_dga_set_viewport(ScrnInfoPtr scrn, int x, int y, int flags) +{ + scrn->AdjustFrame(scrn->pScreen->myNum, x, y, flags); +} + +static Bool +xf86_dga_open_framebuffer(ScrnInfoPtr scrn, + char **name, + unsigned char **mem, int *size, int *offset, int *flags) +{ + return FALSE; +} + +static void +xf86_dga_close_framebuffer(ScrnInfoPtr scrn) +{ +} + +static DGAFunctionRec xf86_dga_funcs = { + xf86_dga_open_framebuffer, + xf86_dga_close_framebuffer, + xf86_dga_set_mode, + xf86_dga_set_viewport, + xf86_dga_get_viewport, + NULL, + NULL, + NULL, + NULL +}; + +Bool +xf86DiDGAReInit (ScreenPtr pScreen) +{ + return TRUE; +} + +Bool +_xf86_di_dga_reinit_internal (ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + + if (!DGAAvailable(pScreen->myNum)) + return TRUE; + + if (!xf86_dga_get_modes (pScreen)) + return FALSE; + + return DGAReInitModes (pScreen, xf86_config->dga_modes, xf86_config->dga_nmode); +} + +Bool +xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address) +{ + return TRUE; +} + +Bool +_xf86_di_dga_init_internal (ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + + xf86_config->dga_flags = 0; + xf86_config->dga_address = 0; + xf86_config->dga_width = 0; + xf86_config->dga_height = 0; + xf86_config->dga_stride = 0; + + if (!xf86_dga_get_modes (pScreen)) + return FALSE; + + return DGAInit(pScreen, &xf86_dga_funcs, xf86_config->dga_modes, xf86_config->dga_nmode); +} diff --git a/xorg-server/hw/xfree86/modes/xf86DisplayIDModes.c b/xorg-server/hw/xfree86/modes/xf86DisplayIDModes.c index 182d43e0e..d507e3b14 100644 --- a/xorg-server/hw/xfree86/modes/xf86DisplayIDModes.c +++ b/xorg-server/hw/xfree86/modes/xf86DisplayIDModes.c @@ -1,437 +1,437 @@ -/* - * Copyright 2009 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software") - * to deal in the software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * them Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Adam Jackson - */ - -#include "xorg-config.h" -#include "xf86.h" -#include "xf86str.h" -#include "edid.h" -#include "xf86DDC.h" - -typedef void (*did_proc)(int scrnIndex, unsigned char *data, void *closure); - -#define DID_PRODUCT_ID 0x00 -#define DID_DISPLAY_PARAMETERS 0x01 -#define DID_COLOR_INFO 0x02 -#define DID_TIMING_1_DETAILED 0x03 -#define DID_TIMING_2_DETAILED 0x04 -#define DID_TIMING_3_SHORT 0x05 -#define DID_TIMING_4_DMT 0x06 -#define DID_TIMING_VESA 0x07 -#define DID_TIMING_CEA 0x08 -#define DID_TIMING_RANGE_LIMITS 0x09 -#define DID_PRODUCT_SERIAL 0x0A -#define DID_ASCII_STRING 0x0B -#define DID_DISPLAY_DEVICE 0x0C -#define DID_POWER_SEQUENCING 0x0D -#define DID_TRANSFER_INFO 0x0E -#define DID_DISPLAY_INTERFACE 0x0F -#define DID_STEREO 0x10 -#define DID_VENDOR 0x7F - -#define extract_le16(x, i) ((x[i+1] << 8) + (x[i])) -#define extract_le24(x, i) ((x[i+2] << 16) + (x[i+1] << 8) + (x[i])) - -static DisplayModePtr -modeCalloc(void) -{ - return xcalloc(1, sizeof(DisplayModeRec)); -} - -/* - * How awesome is it to have two detailed timing formats, neither of which - * are compatible with the format in EDID? So awesome. - */ - -static void -didDetailedTiming1(int i, unsigned char *x, MonPtr mon) -{ - DisplayModePtr m = modeCalloc(); - - if (!m) - return; - - m->Clock = extract_le24(x, 0); - - m->HDisplay = extract_le16(x, 4); - m->HSyncStart = m->HDisplay + (extract_le16(x, 8) & 0x7f); - m->HSyncEnd = m->HSyncStart + extract_le16(x, 10); - m->HTotal = m->HDisplay + extract_le16(x, 6); - m->Flags |= (x[9] & 0x80) ? V_PHSYNC : V_NHSYNC; - - m->VDisplay = extract_le16(x, 12); - m->VSyncStart = m->VDisplay + (extract_le16(x, 16) & 0x7f); - m->VSyncEnd = m->VSyncStart + extract_le16(x, 18); - m->VTotal = m->VDisplay + extract_le16(x, 14); - m->Flags |= (x[17] & 0x80) ? V_PVSYNC : V_NVSYNC; - - m->type = M_T_DRIVER; - if (x[3] & 0x80) - m->type |= M_T_PREFERRED; - - /* XXX double check handling of this */ - if (x[3] & 0x10) - m->Flags |= V_INTERLACE; - - mon->Modes = xf86ModesAdd(mon->Modes, m); -} - -/* XXX no sync bits. what to do? */ -static void -didDetailedTiming2(int i, unsigned char *x, MonPtr mon) -{ - DisplayModePtr mode = modeCalloc(); - - if (!mode) - return; - - mode->Clock = extract_le24(x, 0); - - /* horiz sizes are in character cells, not pixels, hence * 8 */ - mode->HDisplay = ((extract_le16(x, 4) & 0x01ff) + 1) * 8; - mode->HSyncStart = mode->HDisplay + (((x[6] & 0xf0) >> 4) + 1) * 8; - mode->HSyncEnd = mode->HSyncStart + ((x[6] & 0x0f) + 1) * 8; - mode->HTotal = mode->HDisplay + ((x[5] >> 1) + 1) * 8; - - mode->VDisplay = extract_le16(x, 7) & 0x07ff; - mode->VSyncStart = mode->VDisplay + (x[10] >> 4) + 1; - mode->VSyncEnd = mode->VSyncStart + (x[10] & 0x0f) + 1; - mode->VTotal = mode->VDisplay + x[9]; - - mode->status = M_T_DRIVER; - if (x[3] & 0x80) - mode->status |= M_T_PREFERRED; - - /* XXX double check handling of this */ - if (x[3] & 0x10) - mode->Flags |= V_INTERLACE; - - mon->Modes = xf86ModesAdd(mon->Modes, mode); -} - -static void -didShortTiming(int i, unsigned char *x, MonPtr mon) -{ - DisplayModePtr m; - int w, h, r; - - w = (x[1] + 1) * 8; - switch (x[0] & 0x0f) { - case 0: - h = w; - break; - case 1: - h = (w * 4) / 5; - break; - case 2: - h = (w * 3) / 4; - break; - case 3: - h = (w * 9) / 15; - break; - case 4: - h = (w * 9) / 16; - break; - case 5: - h = (w * 10) / 16; - break; - default: - return; - } - r = (x[2] & 0x7f) + 1; - - m = xf86CVTMode(w, h, r, !!(x[0] & 0x10), !!(x[2] & 0x80)); - - m->type = M_T_DRIVER; - if (x[0] & 0x80) - m->type |= M_T_PREFERRED; - - mon->Modes = xf86ModesAdd(mon->Modes, m); -} - -static void -didDMTTiming(int i, unsigned char *x, void *closure) -{ - MonPtr mon = closure; - - mon->Modes = xf86ModesAdd(mon->Modes, - xf86DuplicateMode(DMTModes + *x)); -} - -#define RB 1 -#define INT 2 -static const struct did_dmt { - short w, h, r, f; -} did_dmt[] = { - /* byte 3 */ - { 640, 350, 85, 0 }, - { 640, 400, 85, 0 }, - { 720, 400, 85, 0 }, - { 640, 480, 60, 0 }, - { 640, 480, 72, 0 }, - { 640, 480, 75, 0 }, - { 640, 480, 85, 0 }, - { 800, 600, 56, 0 }, - /* byte 4 */ - { 800, 600, 60, 0 }, - { 800, 600, 72, 0 }, - { 800, 600, 75, 0 }, - { 800, 600, 85, 0 }, - { 800, 600, 120, RB }, - { 848, 480, 60, 0 }, - { 1024, 768, 43, INT }, - { 1024, 768, 60, 0 }, - /* byte 5 */ - { 1024, 768, 70, 0 }, - { 1024, 768, 75, 0 }, - { 1024, 768, 85, 0 }, - { 1024, 768, 120, RB }, - { 1152, 864, 75, 0 }, - { 1280, 768, 60, RB }, - { 1280, 768, 60, 0 }, - { 1280, 768, 75, 0 }, - /* byte 6 */ - { 1280, 768, 85, 0 }, - { 1280, 768, 120, RB }, - { 1280, 800, 60, RB }, - { 1280, 800, 60, 0 }, - { 1280, 800, 75, 0 }, - { 1280, 800, 85, 0 }, - { 1280, 800, 120, RB }, - { 1280, 960, 60, 0 }, - /* byte 7 */ - { 1280, 960, 85, 0 }, - { 1280, 960, 120, RB }, - { 1280, 1024, 60, 0 }, - { 1280, 1024, 75, 0 }, - { 1280, 1024, 85, 0 }, - { 1280, 1024, 120, RB }, - { 1360, 768, 60, 0 }, - { 1360, 768, 120, RB }, - /* byte 8 */ - { 1400, 1050, 60, RB }, - { 1400, 1050, 60, 0 }, - { 1400, 1050, 75, 0 }, - { 1400, 1050, 85, 0 }, - { 1400, 1050, 120, RB }, - { 1440, 900, 60, RB }, - { 1440, 900, 60, 0 }, - { 1440, 900, 75, 0 }, - /* byte 9 */ - { 1440, 900, 85, 0 }, - { 1440, 900, 120, RB }, - { 1600, 1200, 60, 0 }, - { 1600, 1200, 65, 0 }, - { 1600, 1200, 70, 0 }, - { 1600, 1200, 75, 0 }, - { 1600, 1200, 85, 0 }, - { 1600, 1200, 120, RB }, - /* byte a */ - { 1680, 1050, 60, RB }, - { 1680, 1050, 60, 0 }, - { 1680, 1050, 75, 0 }, - { 1680, 1050, 85, 0 }, - { 1680, 1050, 120, RB }, - { 1792, 1344, 60, 0 }, - { 1792, 1344, 75, 0 }, - { 1792, 1344, 120, RB }, - /* byte b */ - { 1856, 1392, 60, 0 }, - { 1856, 1392, 75, 0 }, - { 1856, 1392, 120, RB }, - { 1920, 1200, 60, RB }, - { 1920, 1200, 60, 0 }, - { 1920, 1200, 75, 0 }, - { 1920, 1200, 85, 0 }, - { 1920, 1200, 120, RB }, - /* byte c */ - { 1920, 1440, 60, 0 }, - { 1920, 1440, 75, 0 }, - { 1920, 1440, 120, RB }, - { 2560, 1600, 60, RB }, - { 2560, 1600, 60, 0 }, - { 2560, 1600, 75, 0 }, - { 2560, 1600, 85, 0 }, - { 2560, 1600, 120, RB }, -}; - -static void -didVesaTiming(int scrn, unsigned char *x, MonPtr mon) -{ - int i, j; - - x += 3; - - for (i = 0; i < 10; i++) - for (j = 0; j < 8; j++) - if (x[i] & (1 << j)) { - const struct did_dmt *d = &(did_dmt[i * 8 + j]); - if (d->f == INT) - continue; - mon->Modes = xf86ModesAdd(mon->Modes, - FindDMTMode(d->w, d->h, d->r, - d->f == RB)); - } - -} - -static void -handleDisplayIDBlock(int scrnIndex, unsigned char *x, void *closure) -{ - MonPtr mon = closure; - - switch (x[0]) { - case DID_DISPLAY_PARAMETERS: - /* w/h are in decimillimeters */ - mon->widthmm = (extract_le16(x, 3) + 5) / 10; - mon->heightmm = (extract_le16(x, 5) + 5) / 10; - /* XXX pixel count, feature flags, gamma, aspect, color depth */ - break; - - case DID_TIMING_RANGE_LIMITS: - { - int n; - - mon->maxPixClock = max(mon->maxPixClock, extract_le24(x, 6) * 10); - - n = mon->nHsync++; - if (n < MAX_HSYNC) { - mon->hsync[n].lo = x[9]; - mon->hsync[n].hi = x[10]; - } else { - n = MAX_HSYNC; - } - n = mon->nVrefresh++; - if (n < MAX_VREFRESH) { - mon->vrefresh[n].lo = x[13]; - mon->vrefresh[n].hi = x[14]; - } else { - n = MAX_VREFRESH; - } - break; - } - - case DID_TIMING_1_DETAILED: - { - int i; - for (i = 0; i < x[2]; i += 20) - didDetailedTiming1(scrnIndex, x + i + 3, mon); - break; - } - - case DID_TIMING_2_DETAILED: - { - int i; - for (i = 0; i < x[2]; i += 11) - didDetailedTiming2(scrnIndex, x + i + 3, mon); - break; - } - - case DID_TIMING_3_SHORT: - { - int i; - for (i = 0; i < x[2]; i += 3) - didShortTiming(scrnIndex, x + i + 3, mon); - break; - } - - case DID_TIMING_4_DMT: - { - int i; - for (i = 0; i < x[2]; i++) - didDMTTiming(scrnIndex, x + i + 3, mon); - break; - } - - case DID_TIMING_VESA: - didVesaTiming(scrnIndex, x, mon); - break; - - /* XXX pixel format, ar, orientation, subpixel, dot pitch, bit depth */ - case DID_DISPLAY_DEVICE: - - /* XXX interface, links, color encoding, ss, drm */ - case DID_DISPLAY_INTERFACE: - - /* XXX stereo */ - case DID_STEREO: - - /* nothing interesting in these */ - case DID_COLOR_INFO: - case DID_PRODUCT_SERIAL: - case DID_ASCII_STRING: - case DID_POWER_SEQUENCING: - case DID_TRANSFER_INFO: - case DID_VENDOR: - break; - - /* warn about anything else */ - default: - xf86DrvMsg(scrnIndex, X_WARNING, - "Unknown DisplayID block type %hx\n", x[0]); - break; - } -} - -static void -forEachDisplayIDBlock(int scrnIndex, unsigned char *did, did_proc proc, - void *closure) -{ - int num_extensions = did[3]; - int section_size = did[1]; - unsigned char *block; - - do { - if ((did[0] & 0xf0) != 0x10) /* not 1.x, abort */ - return; - /* XXX also, checksum */ - - block = did + 4; - - while (section_size > 0) { - int block_size = (block[2] + 2); - - proc(scrnIndex, block, closure); - - section_size -= block_size; - block += block_size; - } - - did += (did[1] + 5); - } while (num_extensions--); -} - -/* - * Fill out MonPtr with xf86MonPtr information. - */ -void -xf86DisplayIDMonitorSet(int scrnIndex, MonPtr mon, xf86MonPtr DDC) -{ - if (!mon || !DDC) - return; - - mon->DDC = DDC; - - forEachDisplayIDBlock(scrnIndex, DDC->rawData, handleDisplayIDBlock, mon); -} +/* + * Copyright 2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software") + * to deal in the software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * them Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Adam Jackson + */ + +#include "xorg-config.h" +#include "xf86.h" +#include "xf86str.h" +#include "edid.h" +#include "xf86DDC.h" + +typedef void (*did_proc)(int scrnIndex, unsigned char *data, void *closure); + +#define DID_PRODUCT_ID 0x00 +#define DID_DISPLAY_PARAMETERS 0x01 +#define DID_COLOR_INFO 0x02 +#define DID_TIMING_1_DETAILED 0x03 +#define DID_TIMING_2_DETAILED 0x04 +#define DID_TIMING_3_SHORT 0x05 +#define DID_TIMING_4_DMT 0x06 +#define DID_TIMING_VESA 0x07 +#define DID_TIMING_CEA 0x08 +#define DID_TIMING_RANGE_LIMITS 0x09 +#define DID_PRODUCT_SERIAL 0x0A +#define DID_ASCII_STRING 0x0B +#define DID_DISPLAY_DEVICE 0x0C +#define DID_POWER_SEQUENCING 0x0D +#define DID_TRANSFER_INFO 0x0E +#define DID_DISPLAY_INTERFACE 0x0F +#define DID_STEREO 0x10 +#define DID_VENDOR 0x7F + +#define extract_le16(x, i) ((x[i+1] << 8) + (x[i])) +#define extract_le24(x, i) ((x[i+2] << 16) + (x[i+1] << 8) + (x[i])) + +static DisplayModePtr +modeCalloc(void) +{ + return calloc(1, sizeof(DisplayModeRec)); +} + +/* + * How awesome is it to have two detailed timing formats, neither of which + * are compatible with the format in EDID? So awesome. + */ + +static void +didDetailedTiming1(int i, unsigned char *x, MonPtr mon) +{ + DisplayModePtr m = modeCalloc(); + + if (!m) + return; + + m->Clock = extract_le24(x, 0); + + m->HDisplay = extract_le16(x, 4); + m->HSyncStart = m->HDisplay + (extract_le16(x, 8) & 0x7f); + m->HSyncEnd = m->HSyncStart + extract_le16(x, 10); + m->HTotal = m->HDisplay + extract_le16(x, 6); + m->Flags |= (x[9] & 0x80) ? V_PHSYNC : V_NHSYNC; + + m->VDisplay = extract_le16(x, 12); + m->VSyncStart = m->VDisplay + (extract_le16(x, 16) & 0x7f); + m->VSyncEnd = m->VSyncStart + extract_le16(x, 18); + m->VTotal = m->VDisplay + extract_le16(x, 14); + m->Flags |= (x[17] & 0x80) ? V_PVSYNC : V_NVSYNC; + + m->type = M_T_DRIVER; + if (x[3] & 0x80) + m->type |= M_T_PREFERRED; + + /* XXX double check handling of this */ + if (x[3] & 0x10) + m->Flags |= V_INTERLACE; + + mon->Modes = xf86ModesAdd(mon->Modes, m); +} + +/* XXX no sync bits. what to do? */ +static void +didDetailedTiming2(int i, unsigned char *x, MonPtr mon) +{ + DisplayModePtr mode = modeCalloc(); + + if (!mode) + return; + + mode->Clock = extract_le24(x, 0); + + /* horiz sizes are in character cells, not pixels, hence * 8 */ + mode->HDisplay = ((extract_le16(x, 4) & 0x01ff) + 1) * 8; + mode->HSyncStart = mode->HDisplay + (((x[6] & 0xf0) >> 4) + 1) * 8; + mode->HSyncEnd = mode->HSyncStart + ((x[6] & 0x0f) + 1) * 8; + mode->HTotal = mode->HDisplay + ((x[5] >> 1) + 1) * 8; + + mode->VDisplay = extract_le16(x, 7) & 0x07ff; + mode->VSyncStart = mode->VDisplay + (x[10] >> 4) + 1; + mode->VSyncEnd = mode->VSyncStart + (x[10] & 0x0f) + 1; + mode->VTotal = mode->VDisplay + x[9]; + + mode->status = M_T_DRIVER; + if (x[3] & 0x80) + mode->status |= M_T_PREFERRED; + + /* XXX double check handling of this */ + if (x[3] & 0x10) + mode->Flags |= V_INTERLACE; + + mon->Modes = xf86ModesAdd(mon->Modes, mode); +} + +static void +didShortTiming(int i, unsigned char *x, MonPtr mon) +{ + DisplayModePtr m; + int w, h, r; + + w = (x[1] + 1) * 8; + switch (x[0] & 0x0f) { + case 0: + h = w; + break; + case 1: + h = (w * 4) / 5; + break; + case 2: + h = (w * 3) / 4; + break; + case 3: + h = (w * 9) / 15; + break; + case 4: + h = (w * 9) / 16; + break; + case 5: + h = (w * 10) / 16; + break; + default: + return; + } + r = (x[2] & 0x7f) + 1; + + m = xf86CVTMode(w, h, r, !!(x[0] & 0x10), !!(x[2] & 0x80)); + + m->type = M_T_DRIVER; + if (x[0] & 0x80) + m->type |= M_T_PREFERRED; + + mon->Modes = xf86ModesAdd(mon->Modes, m); +} + +static void +didDMTTiming(int i, unsigned char *x, void *closure) +{ + MonPtr mon = closure; + + mon->Modes = xf86ModesAdd(mon->Modes, + xf86DuplicateMode(DMTModes + *x)); +} + +#define RB 1 +#define INT 2 +static const struct did_dmt { + short w, h, r, f; +} did_dmt[] = { + /* byte 3 */ + { 640, 350, 85, 0 }, + { 640, 400, 85, 0 }, + { 720, 400, 85, 0 }, + { 640, 480, 60, 0 }, + { 640, 480, 72, 0 }, + { 640, 480, 75, 0 }, + { 640, 480, 85, 0 }, + { 800, 600, 56, 0 }, + /* byte 4 */ + { 800, 600, 60, 0 }, + { 800, 600, 72, 0 }, + { 800, 600, 75, 0 }, + { 800, 600, 85, 0 }, + { 800, 600, 120, RB }, + { 848, 480, 60, 0 }, + { 1024, 768, 43, INT }, + { 1024, 768, 60, 0 }, + /* byte 5 */ + { 1024, 768, 70, 0 }, + { 1024, 768, 75, 0 }, + { 1024, 768, 85, 0 }, + { 1024, 768, 120, RB }, + { 1152, 864, 75, 0 }, + { 1280, 768, 60, RB }, + { 1280, 768, 60, 0 }, + { 1280, 768, 75, 0 }, + /* byte 6 */ + { 1280, 768, 85, 0 }, + { 1280, 768, 120, RB }, + { 1280, 800, 60, RB }, + { 1280, 800, 60, 0 }, + { 1280, 800, 75, 0 }, + { 1280, 800, 85, 0 }, + { 1280, 800, 120, RB }, + { 1280, 960, 60, 0 }, + /* byte 7 */ + { 1280, 960, 85, 0 }, + { 1280, 960, 120, RB }, + { 1280, 1024, 60, 0 }, + { 1280, 1024, 75, 0 }, + { 1280, 1024, 85, 0 }, + { 1280, 1024, 120, RB }, + { 1360, 768, 60, 0 }, + { 1360, 768, 120, RB }, + /* byte 8 */ + { 1400, 1050, 60, RB }, + { 1400, 1050, 60, 0 }, + { 1400, 1050, 75, 0 }, + { 1400, 1050, 85, 0 }, + { 1400, 1050, 120, RB }, + { 1440, 900, 60, RB }, + { 1440, 900, 60, 0 }, + { 1440, 900, 75, 0 }, + /* byte 9 */ + { 1440, 900, 85, 0 }, + { 1440, 900, 120, RB }, + { 1600, 1200, 60, 0 }, + { 1600, 1200, 65, 0 }, + { 1600, 1200, 70, 0 }, + { 1600, 1200, 75, 0 }, + { 1600, 1200, 85, 0 }, + { 1600, 1200, 120, RB }, + /* byte a */ + { 1680, 1050, 60, RB }, + { 1680, 1050, 60, 0 }, + { 1680, 1050, 75, 0 }, + { 1680, 1050, 85, 0 }, + { 1680, 1050, 120, RB }, + { 1792, 1344, 60, 0 }, + { 1792, 1344, 75, 0 }, + { 1792, 1344, 120, RB }, + /* byte b */ + { 1856, 1392, 60, 0 }, + { 1856, 1392, 75, 0 }, + { 1856, 1392, 120, RB }, + { 1920, 1200, 60, RB }, + { 1920, 1200, 60, 0 }, + { 1920, 1200, 75, 0 }, + { 1920, 1200, 85, 0 }, + { 1920, 1200, 120, RB }, + /* byte c */ + { 1920, 1440, 60, 0 }, + { 1920, 1440, 75, 0 }, + { 1920, 1440, 120, RB }, + { 2560, 1600, 60, RB }, + { 2560, 1600, 60, 0 }, + { 2560, 1600, 75, 0 }, + { 2560, 1600, 85, 0 }, + { 2560, 1600, 120, RB }, +}; + +static void +didVesaTiming(int scrn, unsigned char *x, MonPtr mon) +{ + int i, j; + + x += 3; + + for (i = 0; i < 10; i++) + for (j = 0; j < 8; j++) + if (x[i] & (1 << j)) { + const struct did_dmt *d = &(did_dmt[i * 8 + j]); + if (d->f == INT) + continue; + mon->Modes = xf86ModesAdd(mon->Modes, + FindDMTMode(d->w, d->h, d->r, + d->f == RB)); + } + +} + +static void +handleDisplayIDBlock(int scrnIndex, unsigned char *x, void *closure) +{ + MonPtr mon = closure; + + switch (x[0]) { + case DID_DISPLAY_PARAMETERS: + /* w/h are in decimillimeters */ + mon->widthmm = (extract_le16(x, 3) + 5) / 10; + mon->heightmm = (extract_le16(x, 5) + 5) / 10; + /* XXX pixel count, feature flags, gamma, aspect, color depth */ + break; + + case DID_TIMING_RANGE_LIMITS: + { + int n; + + mon->maxPixClock = max(mon->maxPixClock, extract_le24(x, 6) * 10); + + n = mon->nHsync++; + if (n < MAX_HSYNC) { + mon->hsync[n].lo = x[9]; + mon->hsync[n].hi = x[10]; + } else { + n = MAX_HSYNC; + } + n = mon->nVrefresh++; + if (n < MAX_VREFRESH) { + mon->vrefresh[n].lo = x[13]; + mon->vrefresh[n].hi = x[14]; + } else { + n = MAX_VREFRESH; + } + break; + } + + case DID_TIMING_1_DETAILED: + { + int i; + for (i = 0; i < x[2]; i += 20) + didDetailedTiming1(scrnIndex, x + i + 3, mon); + break; + } + + case DID_TIMING_2_DETAILED: + { + int i; + for (i = 0; i < x[2]; i += 11) + didDetailedTiming2(scrnIndex, x + i + 3, mon); + break; + } + + case DID_TIMING_3_SHORT: + { + int i; + for (i = 0; i < x[2]; i += 3) + didShortTiming(scrnIndex, x + i + 3, mon); + break; + } + + case DID_TIMING_4_DMT: + { + int i; + for (i = 0; i < x[2]; i++) + didDMTTiming(scrnIndex, x + i + 3, mon); + break; + } + + case DID_TIMING_VESA: + didVesaTiming(scrnIndex, x, mon); + break; + + /* XXX pixel format, ar, orientation, subpixel, dot pitch, bit depth */ + case DID_DISPLAY_DEVICE: + + /* XXX interface, links, color encoding, ss, drm */ + case DID_DISPLAY_INTERFACE: + + /* XXX stereo */ + case DID_STEREO: + + /* nothing interesting in these */ + case DID_COLOR_INFO: + case DID_PRODUCT_SERIAL: + case DID_ASCII_STRING: + case DID_POWER_SEQUENCING: + case DID_TRANSFER_INFO: + case DID_VENDOR: + break; + + /* warn about anything else */ + default: + xf86DrvMsg(scrnIndex, X_WARNING, + "Unknown DisplayID block type %hx\n", x[0]); + break; + } +} + +static void +forEachDisplayIDBlock(int scrnIndex, unsigned char *did, did_proc proc, + void *closure) +{ + int num_extensions = did[3]; + int section_size = did[1]; + unsigned char *block; + + do { + if ((did[0] & 0xf0) != 0x10) /* not 1.x, abort */ + return; + /* XXX also, checksum */ + + block = did + 4; + + while (section_size > 0) { + int block_size = (block[2] + 2); + + proc(scrnIndex, block, closure); + + section_size -= block_size; + block += block_size; + } + + did += (did[1] + 5); + } while (num_extensions--); +} + +/* + * Fill out MonPtr with xf86MonPtr information. + */ +void +xf86DisplayIDMonitorSet(int scrnIndex, MonPtr mon, xf86MonPtr DDC) +{ + if (!mon || !DDC) + return; + + mon->DDC = DDC; + + forEachDisplayIDBlock(scrnIndex, DDC->rawData, handleDisplayIDBlock, mon); +} diff --git a/xorg-server/hw/xfree86/modes/xf86EdidModes.c b/xorg-server/hw/xfree86/modes/xf86EdidModes.c index ec6540841..fc469c6ba 100644 --- a/xorg-server/hw/xfree86/modes/xf86EdidModes.c +++ b/xorg-server/hw/xfree86/modes/xf86EdidModes.c @@ -1,1215 +1,1215 @@ -/* - * Copyright 2006 Luc Verhaegen. - * Copyright 2008 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/** - * @file This file covers code to convert a xf86MonPtr containing EDID-probed - * information into a list of modes, including applying monitor-specific - * quirks to fix broken EDID data. - */ -#ifdef HAVE_XORG_CONFIG_H -#include -#else -#ifdef HAVE_CONFIG_H -#include -#endif -#endif - -#define _PARSE_EDID_ -#include "xf86.h" -#include "xf86DDC.h" -#include -#include "property.h" -#include "propertyst.h" -#include "xf86Crtc.h" -#include -#include - -static void handle_detailed_rblank(struct detailed_monitor_section *det_mon, - void *data) -{ - if (det_mon->type == DS_RANGES) - if (det_mon->section.ranges.supported_blanking & CVT_REDUCED) - *(Bool*)data = TRUE; -} - -static Bool -xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC) -{ - /* EDID 1.4 explicitly defines RB support */ - if (DDC->ver.revision >= 4) { - Bool ret = FALSE; - - xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret); - return ret; - } - - /* For anything older, assume digital means RB support. Boo. */ - if (DDC->features.input_type) - return TRUE; - - return FALSE; -} - -static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) -{ - /* Belinea 10 15 55 */ - if (memcmp (DDC->vendor.name, "MAX", 4) == 0 && - ((DDC->vendor.prod_id == 1516) || - (DDC->vendor.prod_id == 0x77e))) - return TRUE; - - /* Acer AL1706 */ - if (memcmp (DDC->vendor.name, "ACR", 4) == 0 && - DDC->vendor.prod_id == 44358) - return TRUE; - - /* Bug #10814: Samsung SyncMaster 225BW */ - if (memcmp (DDC->vendor.name, "SAM", 4) == 0 && - DDC->vendor.prod_id == 596) - return TRUE; - - /* Bug #10545: Samsung SyncMaster 226BW */ - if (memcmp (DDC->vendor.name, "SAM", 4) == 0 && - DDC->vendor.prod_id == 638) - return TRUE; - - /* Acer F51 */ - if (memcmp (DDC->vendor.name, "API", 4) == 0 && - DDC->vendor.prod_id == 0x7602) - return TRUE; - - - return FALSE; -} - -static Bool quirk_prefer_large_75 (int scrnIndex, xf86MonPtr DDC) -{ - /* Bug #11603: Funai Electronics PM36B */ - if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && - DDC->vendor.prod_id == 13600) - return TRUE; - - return FALSE; -} - -static Bool quirk_detailed_h_in_cm (int scrnIndex, xf86MonPtr DDC) -{ - /* Bug #11603: Funai Electronics PM36B */ - if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && - DDC->vendor.prod_id == 13600) - return TRUE; - - return FALSE; -} - -static Bool quirk_detailed_v_in_cm (int scrnIndex, xf86MonPtr DDC) -{ - /* Bug #11603: Funai Electronics PM36B */ - if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && - DDC->vendor.prod_id == 13600) - return TRUE; - - /* Bug #21000: LGPhilipsLCD LP154W01-TLAJ */ - if (memcmp (DDC->vendor.name, "LPL", 4) == 0 && - DDC->vendor.prod_id == 47360) - return TRUE; - - /* Bug #10304: LGPhilipsLCD LP154W01-A5 */ - if (memcmp(DDC->vendor.name, "LPL", 4) == 0 && - DDC->vendor.prod_id == 0) - return TRUE; - - /* Bug #24482: LGPhilipsLCD LP154W01-TLA1 */ - if (memcmp(DDC->vendor.name, "LPL", 4) == 0 && - DDC->vendor.prod_id == 0x2a00) - return TRUE; - - /* Bug #21750: Samsung Syncmaster 2333HD */ - if (memcmp (DDC->vendor.name, "SAM", 4) == 0 && - DDC->vendor.prod_id == 1157) - return TRUE; - - return FALSE; -} - -static Bool quirk_detailed_use_maximum_size (int scrnIndex, xf86MonPtr DDC) -{ - /* Bug #21324: Iiyama Vision Master 450 */ - if (memcmp (DDC->vendor.name, "IVM", 4) == 0 && - DDC->vendor.prod_id == 6400) - return TRUE; - - return FALSE; -} - -static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC) -{ - /* Envision Peripherals, Inc. EN-7100e. See bug #9550. */ - if (memcmp (DDC->vendor.name, "EPI", 4) == 0 && - DDC->vendor.prod_id == 59264) - return TRUE; - - return FALSE; -} - -static Bool quirk_first_detailed_preferred (int scrnIndex, xf86MonPtr DDC) -{ - /* Philips 107p5 CRT. Reported on xorg@ with pastebin. */ - if (memcmp (DDC->vendor.name, "PHL", 4) == 0 && - DDC->vendor.prod_id == 57364) - return TRUE; - - /* Proview AY765C 17" LCD. See bug #15160*/ - if (memcmp (DDC->vendor.name, "PTS", 4) == 0 && - DDC->vendor.prod_id == 765) - return TRUE; - - /* ACR of some sort RH #284231 */ - if (memcmp (DDC->vendor.name, "ACR", 4) == 0 && - DDC->vendor.prod_id == 2423) - return TRUE; - - /* Peacock Ergovision 19. See rh#492359 */ - if (memcmp (DDC->vendor.name, "PEA", 4) == 0 && - DDC->vendor.prod_id == 9003) - return TRUE; - - return FALSE; -} - -static Bool quirk_detailed_sync_pp(int scrnIndex, xf86MonPtr DDC) -{ - /* Bug #12439: Samsung SyncMaster 205BW */ - if (memcmp (DDC->vendor.name, "SAM", 4) == 0 && - DDC->vendor.prod_id == 541) - return TRUE; - return FALSE; -} - -/* This should probably be made more generic */ -static Bool quirk_dvi_single_link(int scrnIndex, xf86MonPtr DDC) -{ - /* Red Hat bug #453106: Apple 23" Cinema Display */ - if (memcmp (DDC->vendor.name, "APL", 4) == 0 && - DDC->vendor.prod_id == 0x921c) - return TRUE; - return FALSE; -} - -typedef struct { - Bool (*detect) (int scrnIndex, xf86MonPtr DDC); - ddc_quirk_t quirk; - char *description; -} ddc_quirk_map_t; - -static const ddc_quirk_map_t ddc_quirks[] = { - { - quirk_prefer_large_60, DDC_QUIRK_PREFER_LARGE_60, - "Detailed timing is not preferred, use largest mode at 60Hz" - }, - { - quirk_135_clock_too_high, DDC_QUIRK_135_CLOCK_TOO_HIGH, - "Recommended 135MHz pixel clock is too high" - }, - { - quirk_prefer_large_75, DDC_QUIRK_PREFER_LARGE_75, - "Detailed timing is not preferred, use largest mode at 75Hz" - }, - { - quirk_detailed_h_in_cm, DDC_QUIRK_DETAILED_H_IN_CM, - "Detailed timings give horizontal size in cm." - }, - { - quirk_detailed_v_in_cm, DDC_QUIRK_DETAILED_V_IN_CM, - "Detailed timings give vertical size in cm." - }, - { - quirk_detailed_use_maximum_size, DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE, - "Use maximum size instead of detailed timing sizes." - }, - { - quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED, - "First detailed timing was not marked as preferred." - }, - { - quirk_detailed_sync_pp, DDC_QUIRK_DETAILED_SYNC_PP, - "Use +hsync +vsync for detailed timing." - }, - { - quirk_dvi_single_link, DDC_QUIRK_DVI_SINGLE_LINK, - "Forcing maximum pixel clock to single DVI link." - }, - { - NULL, DDC_QUIRK_NONE, - "No known quirks" - }, -}; - -/* - * These more or less come from the DMT spec. The 720x400 modes are - * inferred from historical 80x25 practice. The 640x480@67 and 832x624@75 - * modes are old-school Mac modes. The EDID spec says the 1152x864@75 mode - * should be 1152x870, again for the Mac, but instead we use the x864 DMT - * mode. - * - * The DMT modes have been fact-checked; the rest are mild guesses. - */ -#define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER -#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0 - -static const DisplayModeRec DDCEstablishedModes[17] = { - { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */ - { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */ - { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */ - { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ - { MODEPREFIX, 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */ - { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ - { MODEPREFIX, 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */ - { MODEPREFIX, 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */ - { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */ - { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ - { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */ - { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */ - { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */ - { MODEPREFIX, 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */ - { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */ - { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */ - { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */ -}; - -static DisplayModePtr -DDCModesFromEstablished(int scrnIndex, struct established_timings *timing, - ddc_quirk_t quirks) -{ - DisplayModePtr Modes = NULL, Mode = NULL; - CARD32 bits = (timing->t1) | (timing->t2 << 8) | - ((timing->t_manu & 0x80) << 9); - int i; - - for (i = 0; i < 17; i++) { - if (bits & (0x01 << i)) { - Mode = xf86DuplicateMode(&DDCEstablishedModes[i]); - Modes = xf86ModesAdd(Modes, Mode); - } - } - - return Modes; -} - -/* Autogenerated from the DMT spec */ -const DisplayModeRec DMTModes[] = { - { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 350, 382, 385, 445, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x350@85Hz */ - { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 400, 401, 404, 445, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 640x400@85Hz */ - { MODEPREFIX, 35500, 720, 756, 828, 936, 0, 400, 401, 404, 446, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@85Hz */ - { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ - { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ - { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */ - { MODEPREFIX, 36000, 640, 696, 752, 832, 0, 480, 481, 484, 509, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@85Hz */ - { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */ - { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */ - { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */ - { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */ - { MODEPREFIX, 56250, 800, 832, 896, 1048, 0, 600, 601, 604, 631, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@85Hz */ - { MODEPREFIX, 73250, 800, 848, 880, 960, 0, 600, 603, 607, 636, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 800x600@120Hz RB */ - { MODEPREFIX, 33750, 848, 864, 976, 1088, 0, 480, 486, 494, 517, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 848x480@60Hz */ - { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz (interlaced) */ - { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */ - { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */ - { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ - { MODEPREFIX, 94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@85Hz */ - { MODEPREFIX, 115500, 1024, 1072, 1104, 1184, 0, 768, 771, 775, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@120Hz RB */ - { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */ - { MODEPREFIX, 68250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 790, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@60Hz RB */ - { MODEPREFIX, 79500, 1280, 1344, 1472, 1664, 0, 768, 771, 778, 798, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@60Hz */ - { MODEPREFIX, 102250, 1280, 1360, 1488, 1696, 0, 768, 771, 778, 805, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@75Hz */ - { MODEPREFIX, 117500, 1280, 1360, 1496, 1712, 0, 768, 771, 778, 809, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@85Hz */ - { MODEPREFIX, 140250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@120Hz RB */ - { MODEPREFIX, 71000, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 823, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@60Hz RB */ - { MODEPREFIX, 83500, 1280, 1352, 1480, 1680, 0, 800, 803, 809, 831, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@60Hz */ - { MODEPREFIX, 106500, 1280, 1360, 1488, 1696, 0, 800, 803, 809, 838, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@75Hz */ - { MODEPREFIX, 122500, 1280, 1360, 1496, 1712, 0, 800, 803, 809, 843, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@85Hz */ - { MODEPREFIX, 146250, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 847, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@120Hz RB */ - { MODEPREFIX, 108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@60Hz */ - { MODEPREFIX, 148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@85Hz */ - { MODEPREFIX, 175500, 1280, 1328, 1360, 1440, 0, 960, 963, 967, 1017, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x960@120Hz RB */ - { MODEPREFIX, 108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@60Hz */ - { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */ - { MODEPREFIX, 157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@85Hz */ - { MODEPREFIX, 187250, 1280, 1328, 1360, 1440, 0, 1024, 1027, 1034, 1084, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x1024@120Hz RB */ - { MODEPREFIX, 85500, 1360, 1424, 1536, 1792, 0, 768, 771, 777, 795, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1360x768@60Hz */ - { MODEPREFIX, 148250, 1360, 1408, 1440, 1520, 0, 768, 771, 776, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1360x768@120Hz RB */ - { MODEPREFIX, 101000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@60Hz RB */ - { MODEPREFIX, 121750, 1400, 1488, 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@60Hz */ - { MODEPREFIX, 156000, 1400, 1504, 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@75Hz */ - { MODEPREFIX, 179500, 1400, 1504, 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@85Hz */ - { MODEPREFIX, 208000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@120Hz RB */ - { MODEPREFIX, 88750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 926, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@60Hz RB */ - { MODEPREFIX, 106500, 1440, 1520, 1672, 1904, 0, 900, 903, 909, 934, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@60Hz */ - { MODEPREFIX, 136750, 1440, 1536, 1688, 1936, 0, 900, 903, 909, 942, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@75Hz */ - { MODEPREFIX, 157000, 1440, 1544, 1696, 1952, 0, 900, 903, 909, 948, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@85Hz */ - { MODEPREFIX, 182750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 953, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@120Hz RB */ - { MODEPREFIX, 162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@60Hz */ - { MODEPREFIX, 175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@65Hz */ - { MODEPREFIX, 189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@70Hz */ - { MODEPREFIX, 202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@75Hz */ - { MODEPREFIX, 229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@85Hz */ - { MODEPREFIX, 268250, 1600, 1648, 1680, 1760, 0, 1200, 1203, 1207, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1600x1200@120Hz RB */ - { MODEPREFIX, 119000, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@60Hz RB */ - { MODEPREFIX, 146250, 1680, 1784, 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@60Hz */ - { MODEPREFIX, 187000, 1680, 1800, 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@75Hz */ - { MODEPREFIX, 214750, 1680, 1808, 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@85Hz */ - { MODEPREFIX, 245500, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@120Hz RB */ - { MODEPREFIX, 204750, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@60Hz */ - { MODEPREFIX, 261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@75Hz */ - { MODEPREFIX, 333250, 1792, 1840, 1872, 1952, 0, 1344, 1347, 1351, 1423, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1792x1344@120Hz RB */ - { MODEPREFIX, 218250, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@60Hz */ - { MODEPREFIX, 288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@75Hz */ - { MODEPREFIX, 356500, 1856, 1904, 1936, 2016, 0, 1392, 1395, 1399, 1474, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1856x1392@120Hz RB */ - { MODEPREFIX, 154000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1235, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@60Hz RB */ - { MODEPREFIX, 193250, 1920, 2056, 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@60Hz */ - { MODEPREFIX, 245250, 1920, 2056, 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@75Hz */ - { MODEPREFIX, 281250, 1920, 2064, 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@85Hz */ - { MODEPREFIX, 317000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@120Hz RB */ - { MODEPREFIX, 234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@60Hz */ - { MODEPREFIX, 297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@75Hz */ - { MODEPREFIX, 380500, 1920, 1968, 2000, 2080, 0, 1440, 1443, 1447, 1525, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1440@120Hz RB */ - { MODEPREFIX, 268500, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1646, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@60Hz RB */ - { MODEPREFIX, 348500, 2560, 2752, 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@60Hz */ - { MODEPREFIX, 443250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@75Hz */ - { MODEPREFIX, 505250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@85Hz */ - { MODEPREFIX, 552750, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1694, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@120Hz RB */ -}; - -#define LEVEL_DMT 0 -#define LEVEL_GTF 1 -#define LEVEL_CVT 2 - -static int -MonitorStandardTimingLevel(xf86MonPtr DDC) -{ - if (DDC->ver.revision >= 2) { - if (DDC->ver.revision >= 4 && CVT_SUPPORTED(DDC->features.msc)) { - return LEVEL_CVT; - } - return LEVEL_GTF; - } - return LEVEL_DMT; -} - -static int -ModeRefresh(const DisplayModeRec *mode) -{ - return (int)(xf86ModeVRefresh(mode) + 0.5); -} - -/* - * If rb is not set, then we'll not consider reduced-blanking modes as - * part of the DMT pool. For the 'standard' EDID mode descriptor there's - * no way to specify whether the mode should be RB or not. - */ -DisplayModePtr -FindDMTMode(int hsize, int vsize, int refresh, Bool rb) -{ - int i; - const DisplayModeRec *ret; - - for (i = 0; i < sizeof(DMTModes) / sizeof(DisplayModeRec); i++) { - ret = &DMTModes[i]; - - if (!rb && xf86ModeIsReduced(ret)) - continue; - - if (ret->HDisplay == hsize && - ret->VDisplay == vsize && - refresh == ModeRefresh(ret)) - return xf86DuplicateMode(ret); - } - - return NULL; -} - -/* - * Appendix B of the EDID 1.4 spec defines the right thing to do here. - * If the timing given here matches a mode defined in the VESA DMT standard, - * we _must_ use that. If the device supports CVT modes, then we should - * generate a CVT timing. If both of the above fail, use GTF. - * - * There are some wrinkles here. EDID 1.1 and 1.0 sinks can't really - * "support" GTF, since it wasn't a standard yet; so if they ask for a - * timing in this section that isn't defined in DMT, returning a GTF mode - * may not actually be valid. EDID 1.3 sinks often report support for - * some CVT modes, but they are not required to support CVT timings for - * modes in the standard timing descriptor, so we should _not_ treat them - * as CVT-compliant (unless specified in an extension block I suppose). - * - * EDID 1.4 requires that all sink devices support both GTF and CVT timings - * for modes in this section, but does say that CVT is preferred. - */ -static DisplayModePtr -DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks, - int timing_level, Bool rb) -{ - DisplayModePtr Modes = NULL, Mode = NULL; - int i, hsize, vsize, refresh; - - for (i = 0; i < STD_TIMINGS; i++) { - hsize = timing[i].hsize; - vsize = timing[i].vsize; - refresh = timing[i].refresh; - - /* HDTV hack, because you can't say 1366 */ - if (refresh == 60 && - ((hsize == 1360 && vsize == 765) || - (hsize == 1368 && vsize == 769))) { - Mode = xf86CVTMode(1366, 768, 60, FALSE, FALSE); - Mode->HDisplay = 1366; - Mode->VSyncStart--; - Mode->VSyncEnd--; - } else if (hsize && vsize && refresh) { - Mode = FindDMTMode(hsize, vsize, refresh, rb); - - if (!Mode) { - if (timing_level == LEVEL_CVT) - /* pass rb here too? */ - Mode = xf86CVTMode(hsize, vsize, refresh, FALSE, FALSE); - else if (timing_level == LEVEL_GTF) - Mode = xf86GTFMode(hsize, vsize, refresh, FALSE, FALSE); - } - - } - - if (Mode) { - Mode->type = M_T_DRIVER; - Modes = xf86ModesAdd(Modes, Mode); - } - Mode = NULL; - } - - return Modes; -} - -static void -DDCModeDoInterlaceQuirks(DisplayModePtr mode) -{ - /* - * EDID is delightfully ambiguous about how interlaced modes are to be - * encoded. X's internal representation is of frame height, but some - * HDTV detailed timings are encoded as field height. - * - * The format list here is from CEA, in frame size. Technically we - * should be checking refresh rate too. Whatever. - */ - static const struct { - int w, h; - } cea_interlaced[] = { - { 1920, 1080 }, - { 720, 480 }, - { 1440, 480 }, - { 2880, 480 }, - { 720, 576 }, - { 1440, 576 }, - { 2880, 576 }, - }; - static const int n_modes = sizeof(cea_interlaced)/sizeof(cea_interlaced[0]); - int i; - - for (i = 0; i < n_modes; i++) { - if ((mode->HDisplay == cea_interlaced[i].w) && - (mode->VDisplay == cea_interlaced[i].h / 2)) { - mode->VDisplay *= 2; - mode->VSyncStart *= 2; - mode->VSyncEnd *= 2; - mode->VTotal *= 2; - mode->VTotal |= 1; - } - } - - mode->Flags |= V_INTERLACE; -} - -/* - * - */ -static DisplayModePtr -DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing, - Bool preferred, ddc_quirk_t quirks) -{ - DisplayModePtr Mode; - - /* - * Refuse to create modes that are insufficiently large. 64 is a random - * number, maybe the spec says something about what the minimum is. In - * particular I see this frequently with _old_ EDID, 1.0 or so, so maybe - * our parser is just being too aggresive there. - */ - if (timing->h_active < 64 || timing->v_active < 64) { - xf86DrvMsg(scrnIndex, X_INFO, - "%s: Ignoring tiny %dx%d mode\n", __func__, - timing->h_active, timing->v_active); - return NULL; - } - - /* We don't do stereo */ - if (timing->stereo) { - xf86DrvMsg(scrnIndex, X_INFO, - "%s: Ignoring: We don't handle stereo.\n", __func__); - return NULL; - } - - /* We only do seperate sync currently */ - if (timing->sync != 0x03) { - xf86DrvMsg(scrnIndex, X_INFO, - "%s: %dx%d Warning: We only handle separate" - " sync.\n", __func__, timing->h_active, timing->v_active); - } - - Mode = xnfcalloc(1, sizeof(DisplayModeRec)); - - Mode->type = M_T_DRIVER; - if (preferred) - Mode->type |= M_T_PREFERRED; - - if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) && - timing->clock == 135000000 ) - Mode->Clock = 108880; - else - Mode->Clock = timing->clock / 1000.0; - - Mode->HDisplay = timing->h_active; - Mode->HSyncStart = timing->h_active + timing->h_sync_off; - Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width; - Mode->HTotal = timing->h_active + timing->h_blanking; - - Mode->VDisplay = timing->v_active; - Mode->VSyncStart = timing->v_active + timing->v_sync_off; - Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width; - Mode->VTotal = timing->v_active + timing->v_blanking; - - /* perform basic check on the detail timing */ - if (Mode->HSyncEnd > Mode->HTotal || Mode->VSyncEnd > Mode->VTotal) { - xfree(Mode); - return NULL; - } - - /* We ignore h/v_size and h/v_border for now. */ - - if (timing->interlaced) - DDCModeDoInterlaceQuirks(Mode); - - if (quirks & DDC_QUIRK_DETAILED_SYNC_PP) - Mode->Flags |= V_PVSYNC | V_PHSYNC; - else { - if (timing->misc & 0x02) - Mode->Flags |= V_PVSYNC; - else - Mode->Flags |= V_NVSYNC; - - if (timing->misc & 0x01) - Mode->Flags |= V_PHSYNC; - else - Mode->Flags |= V_NHSYNC; - } - - xf86SetModeDefaultName(Mode); - - return Mode; -} - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) -static DisplayModePtr -DDCModesFromCVT(int scrnIndex, struct cvt_timings *t) -{ - DisplayModePtr modes = NULL; - int i; - - for (i = 0; i < 4; i++) { - if (t[i].height) { - if (t[i].rates & 0x10) - modes = xf86ModesAdd(modes, - xf86CVTMode(t[i].width, t[i].height, 50, 0, 0)); - if (t[i].rates & 0x08) - modes = xf86ModesAdd(modes, - xf86CVTMode(t[i].width, t[i].height, 60, 0, 0)); - if (t[i].rates & 0x04) - modes = xf86ModesAdd(modes, - xf86CVTMode(t[i].width, t[i].height, 75, 0, 0)); - if (t[i].rates & 0x02) - modes = xf86ModesAdd(modes, - xf86CVTMode(t[i].width, t[i].height, 85, 0, 0)); - if (t[i].rates & 0x01) - modes = xf86ModesAdd(modes, - xf86CVTMode(t[i].width, t[i].height, 60, 1, 0)); - } else break; - } - - return modes; -} -#endif - -static const struct { - short w; - short h; - short r; - short rb; -} EstIIIModes[] = { - /* byte 6 */ - { 640, 350, 85, 0 }, - { 640, 400, 85, 0 }, - { 720, 400, 85, 0 }, - { 640, 480, 85, 0 }, - { 848, 480, 60, 0 }, - { 800, 600, 85, 0 }, - { 1024, 768, 85, 0 }, - { 1152, 864, 75, 0 }, - /* byte 7 */ - { 1280, 768, 60, 1 }, - { 1280, 768, 60, 0 }, - { 1280, 768, 75, 0 }, - { 1280, 768, 85, 0 }, - { 1280, 960, 60, 0 }, - { 1280, 960, 85, 0 }, - { 1280, 1024, 60, 0 }, - { 1280, 1024, 85, 0 }, - /* byte 8 */ - { 1360, 768, 60, 0 }, - { 1440, 900, 60, 1 }, - { 1440, 900, 60, 0 }, - { 1440, 900, 75, 0 }, - { 1440, 900, 85, 0 }, - { 1400, 1050, 60, 1 }, - { 1400, 1050, 60, 0 }, - { 1400, 1050, 75, 0 }, - /* byte 9 */ - { 1400, 1050, 85, 0 }, - { 1680, 1050, 60, 1 }, - { 1680, 1050, 60, 0 }, - { 1680, 1050, 75, 0 }, - { 1680, 1050, 85, 0 }, - { 1600, 1200, 60, 0 }, - { 1600, 1200, 65, 0 }, - { 1600, 1200, 70, 0 }, - /* byte 10 */ - { 1600, 1200, 75, 0 }, - { 1600, 1200, 85, 0 }, - { 1792, 1344, 60, 0 }, - { 1792, 1344, 85, 0 }, - { 1856, 1392, 60, 0 }, - { 1856, 1392, 75, 0 }, - { 1920, 1200, 60, 1 }, - { 1920, 1200, 60, 0 }, - /* byte 11 */ - { 1920, 1200, 75, 0 }, - { 1920, 1200, 85, 0 }, - { 1920, 1440, 60, 0 }, - { 1920, 1440, 75, 0 }, -}; - -static DisplayModePtr -DDCModesFromEstIII(unsigned char *est) -{ - DisplayModePtr modes = NULL; - int i, j, m; - - for (i = 0; i < 6; i++) { - for (j = 7; j > 0; j--) { - if (est[i] & (1 << j)) { - m = (i * 8) + (7 - j); - modes = xf86ModesAdd(modes, - FindDMTMode(EstIIIModes[m].w, - EstIIIModes[m].h, - EstIIIModes[m].r, - EstIIIModes[m].rb)); - } - } - } - - return modes; -} - -/* - * This is only valid when the sink claims to be continuous-frequency - * but does not supply a detailed range descriptor. Such sinks are - * arguably broken. Currently the mode validation code isn't aware of - * this; the non-RANDR code even punts the decision of optional sync - * range checking to the driver. Loss. - */ -static void -DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes) -{ - DisplayModePtr Mode = Modes; - - if (!Monitor || !Modes) - return; - - /* set up the ranges for scanning through the modes */ - Monitor->nHsync = 1; - Monitor->hsync[0].lo = 1024.0; - Monitor->hsync[0].hi = 0.0; - - Monitor->nVrefresh = 1; - Monitor->vrefresh[0].lo = 1024.0; - Monitor->vrefresh[0].hi = 0.0; - - while (Mode) { - if (!Mode->HSync) - Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal); - - if (!Mode->VRefresh) - Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / - ((float) (Mode->HTotal * Mode->VTotal)); - - if (Mode->HSync < Monitor->hsync[0].lo) - Monitor->hsync[0].lo = Mode->HSync; - - if (Mode->HSync > Monitor->hsync[0].hi) - Monitor->hsync[0].hi = Mode->HSync; - - if (Mode->VRefresh < Monitor->vrefresh[0].lo) - Monitor->vrefresh[0].lo = Mode->VRefresh; - - if (Mode->VRefresh > Monitor->vrefresh[0].hi) - Monitor->vrefresh[0].hi = Mode->VRefresh; - - Mode = Mode->next; - } -} - -ddc_quirk_t -xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose) -{ - ddc_quirk_t quirks; - int i; - - quirks = DDC_QUIRK_NONE; - for (i = 0; ddc_quirks[i].detect; i++) { - if (ddc_quirks[i].detect (scrnIndex, DDC)) { - if (verbose) { - xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n", - ddc_quirks[i].description); - } - quirks |= ddc_quirks[i].quirk; - } - } - - return quirks; -} - -void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon, - ddc_quirk_t quirks, - int hsize, int vsize) -{ - if (det_mon->type != DT) - return; - - if (quirks & DDC_QUIRK_DETAILED_H_IN_CM) - det_mon->section.d_timings.h_size *= 10; - - if (quirks & DDC_QUIRK_DETAILED_V_IN_CM) - det_mon->section.d_timings.v_size *= 10; - - if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { - det_mon->section.d_timings.h_size = 10 * hsize; - det_mon->section.d_timings.v_size = 10 * vsize; - } -} - -/** - * Applies monitor-specific quirks to the decoded EDID information. - * - * Note that some quirks applying to the mode list are still implemented in - * xf86DDCGetModes. - */ -void -xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC) -{ - ddc_quirk_t quirks = xf86DDCDetectQuirks (scrnIndex, DDC, FALSE); - int i; - - for (i = 0; i < DET_TIMINGS; i++) { - xf86DetTimingApplyQuirks(DDC->det_mon + i, quirks, - DDC->features.hsize, - DDC->features.vsize); - } -} - -/** - * Walks the modes list, finding the mode with the largest area which is - * closest to the target refresh rate, and marks it as the only preferred mode. -*/ -static void -xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes, - float target_refresh) -{ - DisplayModePtr mode, best = modes; - - for (mode = modes; mode; mode = mode->next) - { - mode->type &= ~M_T_PREFERRED; - - if (mode == best) continue; - - if (mode->HDisplay * mode->VDisplay > - best->HDisplay * best->VDisplay) - { - best = mode; - continue; - } - if (mode->HDisplay * mode->VDisplay == - best->HDisplay * best->VDisplay) - { - double mode_refresh = xf86ModeVRefresh (mode); - double best_refresh = xf86ModeVRefresh (best); - double mode_dist = fabs(mode_refresh - target_refresh); - double best_dist = fabs(best_refresh - target_refresh); - - if (mode_dist < best_dist) - { - best = mode; - continue; - } - } - } - if (best) - best->type |= M_T_PREFERRED; -} - -#define CEA_VIDEO_MODES_NUM 64 -static const DisplayModeRec CEAVideoModes[CEA_VIDEO_MODES_NUM] = { - { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 1:640x480@60Hz */ - { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 2:720x480@60Hz */ - { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 3:720x480@60Hz */ - { MODEPREFIX, 74250, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 4: 1280x720@60Hz */ - { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 5:1920x1080i@60Hz */ - { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 6:1440x480i@60Hz */ - { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 7:1440x480i@60Hz */ - { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 8:1440x240@60Hz */ - { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 9:1440x240@60Hz */ - { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 10:2880x480i@60Hz */ - { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 11:2880x480i@60Hz */ - { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 12:2880x240@60Hz */ - { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 13:2880x240@60Hz */ - { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 14:1440x480@60Hz */ - { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 15:1440x480@60Hz */ - { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 16:1920x1080@60Hz */ - { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 17:720x576@50Hz */ - { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 18:720x576@50Hz */ - { MODEPREFIX, 74250, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 19: 1280x720@50Hz */ - { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 20:1920x1080i@50Hz */ - { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 21:1440x576i@50Hz */ - { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 22:1440x576i@50Hz */ - { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 23:1440x288@50Hz */ - { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 24:1440x288@50Hz */ - { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 25:2880x576i@50Hz */ - { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 26:2880x576i@50Hz */ - { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 27:2880x288@50Hz */ - { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 28:2880x288@50Hz */ - { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 29:1440x576@50Hz */ - { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 30:1440x576@50Hz */ - { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 31:1920x1080@50Hz */ - { MODEPREFIX, 74250, 1920, 2558, 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 32:1920x1080@24Hz */ - { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 33:1920x1080@25Hz */ - { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 34:1920x1080@30Hz */ - { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 35:2880x480@60Hz */ - { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 36:2880x480@60Hz */ - { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 37:2880x576@50Hz */ - { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 38:2880x576@50Hz */ - { MODEPREFIX, 72000, 1920, 1952, 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, V_PHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 39:1920x1080i@50Hz */ - { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 40:1920x1080i@100Hz */ - { MODEPREFIX, 148500, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 41:1280x720@100Hz */ - { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 42:720x576@100Hz */ - { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 43:720x576@100Hz */ - { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 44:1440x576i@100Hz */ - { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 45:1440x576i@100Hz */ - { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 46:1920x1080i@120Hz */ - { MODEPREFIX, 148500, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 47:1280x720@120Hz */ - { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 48:720x480@120Hz */ - { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 49:720x480@120Hz */ - { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 50:1440x480i@120Hz */ - { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 51:1440x480i@120Hz */ - { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 52:720x576@200Hz */ - { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 53:720x576@200Hz */ - { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 54:1440x576i@200Hz */ - { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 55:1440x576i@200Hz */ - { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 56:720x480@240Hz */ - { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 57:720x480@240Hz */ - { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 58:1440x480i@240 */ - { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 59:1440x480i@240 */ - { MODEPREFIX, 59400, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 60: 1280x720@24Hz */ - { MODEPREFIX, 74250, 3700, 3740, 1430, 3960, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 61: 1280x720@25Hz */ - { MODEPREFIX, 74250, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 62: 1280x720@30Hz */ - { MODEPREFIX, 297000, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 63: 1920x1080@120Hz */ - { MODEPREFIX, 297000, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 64:1920x1080@100Hz */ -}; - -/* chose mode line by cea short video descriptor*/ -static void handle_cea_svd(struct cea_video_block *video, void *data) -{ - DisplayModePtr Mode; - DisplayModePtr *Modes = (DisplayModePtr *) data; - int vid; - - vid = video ->video_code & 0x7f; - if (vid < CEA_VIDEO_MODES_NUM) { - Mode = xf86DuplicateMode(CEAVideoModes + vid); - *Modes = xf86ModesAdd(*Modes, Mode); - } -} - -static DisplayModePtr -DDCModesFromCEAExtension(int scrnIndex, xf86MonPtr MonPtr) -{ - DisplayModePtr Modes = NULL; - - xf86ForEachVideoBlock(MonPtr, - handle_cea_svd, - &Modes); - - return Modes; -} - -struct det_modes_parameter { - xf86MonPtr DDC; - ddc_quirk_t quirks; - DisplayModePtr Modes; - Bool rb; - Bool preferred; - int timing_level; -}; - -static void handle_detailed_modes(struct detailed_monitor_section *det_mon, - void *data) -{ - DisplayModePtr Mode; - struct det_modes_parameter *p = (struct det_modes_parameter *)data; - - xf86DetTimingApplyQuirks(det_mon,p->quirks, - p->DDC->features.hsize, - p->DDC->features.vsize); - - switch (det_mon->type) { - case DT: - Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex, - &det_mon->section.d_timings, - p->preferred, - p->quirks); - p->preferred = FALSE; - p->Modes = xf86ModesAdd(p->Modes, Mode); - break; - case DS_STD_TIMINGS: - Mode = DDCModesFromStandardTiming(det_mon->section.std_t, - p->quirks, p->timing_level,p->rb); - p->Modes = xf86ModesAdd(p->Modes, Mode); - break; -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - case DS_CVT: - Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt); - p->Modes = xf86ModesAdd(p->Modes, Mode); - break; -#endif - case DS_EST_III: - Mode = DDCModesFromEstIII(det_mon->section.est_iii); - p->Modes = xf86ModesAdd(p->Modes, Mode); - break; - default: - break; - } -} - -DisplayModePtr -xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) -{ - DisplayModePtr Modes = NULL, Mode; - ddc_quirk_t quirks; - Bool preferred, rb; - int timing_level; - struct det_modes_parameter p; - - xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n", - DDC->vendor.name, DDC->vendor.prod_id); - - quirks = xf86DDCDetectQuirks(scrnIndex, DDC, TRUE); - - preferred = PREFERRED_TIMING_MODE(DDC->features.msc); - if (DDC->ver.revision >= 4) - preferred = TRUE; - if (quirks & DDC_QUIRK_FIRST_DETAILED_PREFERRED) - preferred = TRUE; - if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75)) - preferred = FALSE; - - rb = xf86MonitorSupportsReducedBlanking(DDC); - - timing_level = MonitorStandardTimingLevel(DDC); - - p.quirks = quirks; - p.DDC = DDC; - p.Modes = Modes; - p.rb = rb; - p.preferred = preferred; - p.timing_level = timing_level; - xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p); - Modes = p.Modes; - - /* Add established timings */ - Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks); - Modes = xf86ModesAdd(Modes, Mode); - - /* Add standard timings */ - Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb); - Modes = xf86ModesAdd(Modes, Mode); - - /* Add cea-extension mode timings */ - Mode = DDCModesFromCEAExtension(scrnIndex,DDC); - Modes = xf86ModesAdd(Modes, Mode); - - if (quirks & DDC_QUIRK_PREFER_LARGE_60) - xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60); - - if (quirks & DDC_QUIRK_PREFER_LARGE_75) - xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75); - - Modes = xf86PruneDuplicateModes(Modes); - - return Modes; -} - -struct det_mon_parameter { - MonPtr Monitor; - ddc_quirk_t quirks; - Bool have_hsync; - Bool have_vrefresh; - Bool have_maxpixclock; -}; - -static void handle_detailed_monset(struct detailed_monitor_section *det_mon, - void *data) -{ - int clock; - struct det_mon_parameter *p = (struct det_mon_parameter *)data; - int scrnIndex = ((xf86MonPtr)(p->Monitor->DDC))->scrnIndex; - - switch (det_mon->type) { - case DS_RANGES: - if (!p->have_hsync) { - if (!p->Monitor->nHsync) - xf86DrvMsg(scrnIndex, X_INFO, - "Using EDID range info for horizontal sync\n"); - p->Monitor->hsync[p->Monitor->nHsync].lo = - det_mon->section.ranges.min_h; - p->Monitor->hsync[p->Monitor->nHsync].hi = - det_mon->section.ranges.max_h; - p->Monitor->nHsync++; - } else { - xf86DrvMsg(scrnIndex, X_INFO, - "Using hsync ranges from config file\n"); - } - - if (!p->have_vrefresh) { - if (!p->Monitor->nVrefresh) - xf86DrvMsg(scrnIndex, X_INFO, - "Using EDID range info for vertical refresh\n"); - p->Monitor->vrefresh[p->Monitor->nVrefresh].lo = - det_mon->section.ranges.min_v; - p->Monitor->vrefresh[p->Monitor->nVrefresh].hi = - det_mon->section.ranges.max_v; - p->Monitor->nVrefresh++; - } else { - xf86DrvMsg(scrnIndex, X_INFO, - "Using vrefresh ranges from config file\n"); - } - - clock = det_mon->section.ranges.max_clock * 1000; - if (p->quirks & DDC_QUIRK_DVI_SINGLE_LINK) - clock = min(clock, 165000); - if (!p->have_maxpixclock && clock > p->Monitor->maxPixClock) - p->Monitor->maxPixClock = clock; - - break; - default: - break; - } -} - -/* - * Fill out MonPtr with xf86MonPtr information. - */ -void -xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) -{ - DisplayModePtr Modes = NULL, Mode; - struct det_mon_parameter p; - - if (!Monitor || !DDC) - return; - - Monitor->DDC = DDC; - - if (Monitor->widthmm <= 0 || Monitor->heightmm <= 0) { - Monitor->widthmm = 10 * DDC->features.hsize; - Monitor->heightmm = 10 * DDC->features.vsize; - } - - Monitor->reducedblanking = xf86MonitorSupportsReducedBlanking(DDC); - - Modes = xf86DDCGetModes(scrnIndex, DDC); - - /* Go through the detailed monitor sections */ - p.Monitor = Monitor; - p.quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE); - p.have_hsync = (Monitor->nHsync != 0); - p.have_vrefresh = (Monitor->nVrefresh != 0); - p.have_maxpixclock = (Monitor->maxPixClock != 0); - xf86ForEachDetailedBlock(DDC, handle_detailed_monset, &p); - - if (Modes) { - /* Print Modes */ - xf86DrvMsg(scrnIndex, X_INFO, "Printing DDC gathered Modelines:\n"); - - Mode = Modes; - while (Mode) { - xf86PrintModeline(scrnIndex, Mode); - Mode = Mode->next; - } - - /* Do we still need ranges to be filled in? */ - if (!Monitor->nHsync || !Monitor->nVrefresh) - DDCGuessRangesFromModes(scrnIndex, Monitor, Modes); - - /* look for last Mode */ - Mode = Modes; - - while (Mode->next) - Mode = Mode->next; - - /* add to MonPtr */ - if (Monitor->Modes) { - Monitor->Last->next = Modes; - Modes->prev = Monitor->Last; - Monitor->Last = Mode; - } else { - Monitor->Modes = Modes; - Monitor->Last = Mode; - } - } -} +/* + * Copyright 2006 Luc Verhaegen. + * Copyright 2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * @file This file covers code to convert a xf86MonPtr containing EDID-probed + * information into a list of modes, including applying monitor-specific + * quirks to fix broken EDID data. + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#else +#ifdef HAVE_CONFIG_H +#include +#endif +#endif + +#define _PARSE_EDID_ +#include "xf86.h" +#include "xf86DDC.h" +#include +#include "property.h" +#include "propertyst.h" +#include "xf86Crtc.h" +#include +#include + +static void handle_detailed_rblank(struct detailed_monitor_section *det_mon, + void *data) +{ + if (det_mon->type == DS_RANGES) + if (det_mon->section.ranges.supported_blanking & CVT_REDUCED) + *(Bool*)data = TRUE; +} + +static Bool +xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC) +{ + /* EDID 1.4 explicitly defines RB support */ + if (DDC->ver.revision >= 4) { + Bool ret = FALSE; + + xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret); + return ret; + } + + /* For anything older, assume digital means RB support. Boo. */ + if (DDC->features.input_type) + return TRUE; + + return FALSE; +} + +static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) +{ + /* Belinea 10 15 55 */ + if (memcmp (DDC->vendor.name, "MAX", 4) == 0 && + ((DDC->vendor.prod_id == 1516) || + (DDC->vendor.prod_id == 0x77e))) + return TRUE; + + /* Acer AL1706 */ + if (memcmp (DDC->vendor.name, "ACR", 4) == 0 && + DDC->vendor.prod_id == 44358) + return TRUE; + + /* Bug #10814: Samsung SyncMaster 225BW */ + if (memcmp (DDC->vendor.name, "SAM", 4) == 0 && + DDC->vendor.prod_id == 596) + return TRUE; + + /* Bug #10545: Samsung SyncMaster 226BW */ + if (memcmp (DDC->vendor.name, "SAM", 4) == 0 && + DDC->vendor.prod_id == 638) + return TRUE; + + /* Acer F51 */ + if (memcmp (DDC->vendor.name, "API", 4) == 0 && + DDC->vendor.prod_id == 0x7602) + return TRUE; + + + return FALSE; +} + +static Bool quirk_prefer_large_75 (int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #11603: Funai Electronics PM36B */ + if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && + DDC->vendor.prod_id == 13600) + return TRUE; + + return FALSE; +} + +static Bool quirk_detailed_h_in_cm (int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #11603: Funai Electronics PM36B */ + if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && + DDC->vendor.prod_id == 13600) + return TRUE; + + return FALSE; +} + +static Bool quirk_detailed_v_in_cm (int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #11603: Funai Electronics PM36B */ + if (memcmp (DDC->vendor.name, "FCM", 4) == 0 && + DDC->vendor.prod_id == 13600) + return TRUE; + + /* Bug #21000: LGPhilipsLCD LP154W01-TLAJ */ + if (memcmp (DDC->vendor.name, "LPL", 4) == 0 && + DDC->vendor.prod_id == 47360) + return TRUE; + + /* Bug #10304: LGPhilipsLCD LP154W01-A5 */ + if (memcmp(DDC->vendor.name, "LPL", 4) == 0 && + DDC->vendor.prod_id == 0) + return TRUE; + + /* Bug #24482: LGPhilipsLCD LP154W01-TLA1 */ + if (memcmp(DDC->vendor.name, "LPL", 4) == 0 && + DDC->vendor.prod_id == 0x2a00) + return TRUE; + + /* Bug #21750: Samsung Syncmaster 2333HD */ + if (memcmp (DDC->vendor.name, "SAM", 4) == 0 && + DDC->vendor.prod_id == 1157) + return TRUE; + + return FALSE; +} + +static Bool quirk_detailed_use_maximum_size (int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #21324: Iiyama Vision Master 450 */ + if (memcmp (DDC->vendor.name, "IVM", 4) == 0 && + DDC->vendor.prod_id == 6400) + return TRUE; + + return FALSE; +} + +static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC) +{ + /* Envision Peripherals, Inc. EN-7100e. See bug #9550. */ + if (memcmp (DDC->vendor.name, "EPI", 4) == 0 && + DDC->vendor.prod_id == 59264) + return TRUE; + + return FALSE; +} + +static Bool quirk_first_detailed_preferred (int scrnIndex, xf86MonPtr DDC) +{ + /* Philips 107p5 CRT. Reported on xorg@ with pastebin. */ + if (memcmp (DDC->vendor.name, "PHL", 4) == 0 && + DDC->vendor.prod_id == 57364) + return TRUE; + + /* Proview AY765C 17" LCD. See bug #15160*/ + if (memcmp (DDC->vendor.name, "PTS", 4) == 0 && + DDC->vendor.prod_id == 765) + return TRUE; + + /* ACR of some sort RH #284231 */ + if (memcmp (DDC->vendor.name, "ACR", 4) == 0 && + DDC->vendor.prod_id == 2423) + return TRUE; + + /* Peacock Ergovision 19. See rh#492359 */ + if (memcmp (DDC->vendor.name, "PEA", 4) == 0 && + DDC->vendor.prod_id == 9003) + return TRUE; + + return FALSE; +} + +static Bool quirk_detailed_sync_pp(int scrnIndex, xf86MonPtr DDC) +{ + /* Bug #12439: Samsung SyncMaster 205BW */ + if (memcmp (DDC->vendor.name, "SAM", 4) == 0 && + DDC->vendor.prod_id == 541) + return TRUE; + return FALSE; +} + +/* This should probably be made more generic */ +static Bool quirk_dvi_single_link(int scrnIndex, xf86MonPtr DDC) +{ + /* Red Hat bug #453106: Apple 23" Cinema Display */ + if (memcmp (DDC->vendor.name, "APL", 4) == 0 && + DDC->vendor.prod_id == 0x921c) + return TRUE; + return FALSE; +} + +typedef struct { + Bool (*detect) (int scrnIndex, xf86MonPtr DDC); + ddc_quirk_t quirk; + char *description; +} ddc_quirk_map_t; + +static const ddc_quirk_map_t ddc_quirks[] = { + { + quirk_prefer_large_60, DDC_QUIRK_PREFER_LARGE_60, + "Detailed timing is not preferred, use largest mode at 60Hz" + }, + { + quirk_135_clock_too_high, DDC_QUIRK_135_CLOCK_TOO_HIGH, + "Recommended 135MHz pixel clock is too high" + }, + { + quirk_prefer_large_75, DDC_QUIRK_PREFER_LARGE_75, + "Detailed timing is not preferred, use largest mode at 75Hz" + }, + { + quirk_detailed_h_in_cm, DDC_QUIRK_DETAILED_H_IN_CM, + "Detailed timings give horizontal size in cm." + }, + { + quirk_detailed_v_in_cm, DDC_QUIRK_DETAILED_V_IN_CM, + "Detailed timings give vertical size in cm." + }, + { + quirk_detailed_use_maximum_size, DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE, + "Use maximum size instead of detailed timing sizes." + }, + { + quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED, + "First detailed timing was not marked as preferred." + }, + { + quirk_detailed_sync_pp, DDC_QUIRK_DETAILED_SYNC_PP, + "Use +hsync +vsync for detailed timing." + }, + { + quirk_dvi_single_link, DDC_QUIRK_DVI_SINGLE_LINK, + "Forcing maximum pixel clock to single DVI link." + }, + { + NULL, DDC_QUIRK_NONE, + "No known quirks" + }, +}; + +/* + * These more or less come from the DMT spec. The 720x400 modes are + * inferred from historical 80x25 practice. The 640x480@67 and 832x624@75 + * modes are old-school Mac modes. The EDID spec says the 1152x864@75 mode + * should be 1152x870, again for the Mac, but instead we use the x864 DMT + * mode. + * + * The DMT modes have been fact-checked; the rest are mild guesses. + */ +#define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER +#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0 + +static const DisplayModeRec DDCEstablishedModes[17] = { + { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */ + { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */ + { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */ + { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ + { MODEPREFIX, 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */ + { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ + { MODEPREFIX, 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */ + { MODEPREFIX, 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */ + { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */ + { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ + { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */ + { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */ + { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */ + { MODEPREFIX, 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */ + { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */ + { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */ + { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */ +}; + +static DisplayModePtr +DDCModesFromEstablished(int scrnIndex, struct established_timings *timing, + ddc_quirk_t quirks) +{ + DisplayModePtr Modes = NULL, Mode = NULL; + CARD32 bits = (timing->t1) | (timing->t2 << 8) | + ((timing->t_manu & 0x80) << 9); + int i; + + for (i = 0; i < 17; i++) { + if (bits & (0x01 << i)) { + Mode = xf86DuplicateMode(&DDCEstablishedModes[i]); + Modes = xf86ModesAdd(Modes, Mode); + } + } + + return Modes; +} + +/* Autogenerated from the DMT spec */ +const DisplayModeRec DMTModes[] = { + { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 350, 382, 385, 445, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x350@85Hz */ + { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 400, 401, 404, 445, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 640x400@85Hz */ + { MODEPREFIX, 35500, 720, 756, 828, 936, 0, 400, 401, 404, 446, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@85Hz */ + { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */ + { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */ + { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */ + { MODEPREFIX, 36000, 640, 696, 752, 832, 0, 480, 481, 484, 509, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@85Hz */ + { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */ + { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */ + { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */ + { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */ + { MODEPREFIX, 56250, 800, 832, 896, 1048, 0, 600, 601, 604, 631, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@85Hz */ + { MODEPREFIX, 73250, 800, 848, 880, 960, 0, 600, 603, 607, 636, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 800x600@120Hz RB */ + { MODEPREFIX, 33750, 848, 864, 976, 1088, 0, 480, 486, 494, 517, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 848x480@60Hz */ + { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz (interlaced) */ + { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */ + { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */ + { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */ + { MODEPREFIX, 94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@85Hz */ + { MODEPREFIX, 115500, 1024, 1072, 1104, 1184, 0, 768, 771, 775, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@120Hz RB */ + { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */ + { MODEPREFIX, 68250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 790, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@60Hz RB */ + { MODEPREFIX, 79500, 1280, 1344, 1472, 1664, 0, 768, 771, 778, 798, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@60Hz */ + { MODEPREFIX, 102250, 1280, 1360, 1488, 1696, 0, 768, 771, 778, 805, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@75Hz */ + { MODEPREFIX, 117500, 1280, 1360, 1496, 1712, 0, 768, 771, 778, 809, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@85Hz */ + { MODEPREFIX, 140250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@120Hz RB */ + { MODEPREFIX, 71000, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 823, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@60Hz RB */ + { MODEPREFIX, 83500, 1280, 1352, 1480, 1680, 0, 800, 803, 809, 831, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@60Hz */ + { MODEPREFIX, 106500, 1280, 1360, 1488, 1696, 0, 800, 803, 809, 838, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@75Hz */ + { MODEPREFIX, 122500, 1280, 1360, 1496, 1712, 0, 800, 803, 809, 843, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@85Hz */ + { MODEPREFIX, 146250, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 847, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@120Hz RB */ + { MODEPREFIX, 108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@60Hz */ + { MODEPREFIX, 148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@85Hz */ + { MODEPREFIX, 175500, 1280, 1328, 1360, 1440, 0, 960, 963, 967, 1017, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x960@120Hz RB */ + { MODEPREFIX, 108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@60Hz */ + { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */ + { MODEPREFIX, 157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@85Hz */ + { MODEPREFIX, 187250, 1280, 1328, 1360, 1440, 0, 1024, 1027, 1034, 1084, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x1024@120Hz RB */ + { MODEPREFIX, 85500, 1360, 1424, 1536, 1792, 0, 768, 771, 777, 795, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1360x768@60Hz */ + { MODEPREFIX, 148250, 1360, 1408, 1440, 1520, 0, 768, 771, 776, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1360x768@120Hz RB */ + { MODEPREFIX, 101000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@60Hz RB */ + { MODEPREFIX, 121750, 1400, 1488, 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@60Hz */ + { MODEPREFIX, 156000, 1400, 1504, 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@75Hz */ + { MODEPREFIX, 179500, 1400, 1504, 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@85Hz */ + { MODEPREFIX, 208000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@120Hz RB */ + { MODEPREFIX, 88750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 926, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@60Hz RB */ + { MODEPREFIX, 106500, 1440, 1520, 1672, 1904, 0, 900, 903, 909, 934, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@60Hz */ + { MODEPREFIX, 136750, 1440, 1536, 1688, 1936, 0, 900, 903, 909, 942, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@75Hz */ + { MODEPREFIX, 157000, 1440, 1544, 1696, 1952, 0, 900, 903, 909, 948, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@85Hz */ + { MODEPREFIX, 182750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 953, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@120Hz RB */ + { MODEPREFIX, 162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@60Hz */ + { MODEPREFIX, 175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@65Hz */ + { MODEPREFIX, 189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@70Hz */ + { MODEPREFIX, 202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@75Hz */ + { MODEPREFIX, 229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@85Hz */ + { MODEPREFIX, 268250, 1600, 1648, 1680, 1760, 0, 1200, 1203, 1207, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1600x1200@120Hz RB */ + { MODEPREFIX, 119000, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@60Hz RB */ + { MODEPREFIX, 146250, 1680, 1784, 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@60Hz */ + { MODEPREFIX, 187000, 1680, 1800, 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@75Hz */ + { MODEPREFIX, 214750, 1680, 1808, 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@85Hz */ + { MODEPREFIX, 245500, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@120Hz RB */ + { MODEPREFIX, 204750, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@60Hz */ + { MODEPREFIX, 261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@75Hz */ + { MODEPREFIX, 333250, 1792, 1840, 1872, 1952, 0, 1344, 1347, 1351, 1423, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1792x1344@120Hz RB */ + { MODEPREFIX, 218250, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@60Hz */ + { MODEPREFIX, 288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@75Hz */ + { MODEPREFIX, 356500, 1856, 1904, 1936, 2016, 0, 1392, 1395, 1399, 1474, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1856x1392@120Hz RB */ + { MODEPREFIX, 154000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1235, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@60Hz RB */ + { MODEPREFIX, 193250, 1920, 2056, 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@60Hz */ + { MODEPREFIX, 245250, 1920, 2056, 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@75Hz */ + { MODEPREFIX, 281250, 1920, 2064, 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@85Hz */ + { MODEPREFIX, 317000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@120Hz RB */ + { MODEPREFIX, 234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@60Hz */ + { MODEPREFIX, 297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@75Hz */ + { MODEPREFIX, 380500, 1920, 1968, 2000, 2080, 0, 1440, 1443, 1447, 1525, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1440@120Hz RB */ + { MODEPREFIX, 268500, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1646, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@60Hz RB */ + { MODEPREFIX, 348500, 2560, 2752, 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@60Hz */ + { MODEPREFIX, 443250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@75Hz */ + { MODEPREFIX, 505250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@85Hz */ + { MODEPREFIX, 552750, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1694, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@120Hz RB */ +}; + +#define LEVEL_DMT 0 +#define LEVEL_GTF 1 +#define LEVEL_CVT 2 + +static int +MonitorStandardTimingLevel(xf86MonPtr DDC) +{ + if (DDC->ver.revision >= 2) { + if (DDC->ver.revision >= 4 && CVT_SUPPORTED(DDC->features.msc)) { + return LEVEL_CVT; + } + return LEVEL_GTF; + } + return LEVEL_DMT; +} + +static int +ModeRefresh(const DisplayModeRec *mode) +{ + return (int)(xf86ModeVRefresh(mode) + 0.5); +} + +/* + * If rb is not set, then we'll not consider reduced-blanking modes as + * part of the DMT pool. For the 'standard' EDID mode descriptor there's + * no way to specify whether the mode should be RB or not. + */ +DisplayModePtr +FindDMTMode(int hsize, int vsize, int refresh, Bool rb) +{ + int i; + const DisplayModeRec *ret; + + for (i = 0; i < sizeof(DMTModes) / sizeof(DisplayModeRec); i++) { + ret = &DMTModes[i]; + + if (!rb && xf86ModeIsReduced(ret)) + continue; + + if (ret->HDisplay == hsize && + ret->VDisplay == vsize && + refresh == ModeRefresh(ret)) + return xf86DuplicateMode(ret); + } + + return NULL; +} + +/* + * Appendix B of the EDID 1.4 spec defines the right thing to do here. + * If the timing given here matches a mode defined in the VESA DMT standard, + * we _must_ use that. If the device supports CVT modes, then we should + * generate a CVT timing. If both of the above fail, use GTF. + * + * There are some wrinkles here. EDID 1.1 and 1.0 sinks can't really + * "support" GTF, since it wasn't a standard yet; so if they ask for a + * timing in this section that isn't defined in DMT, returning a GTF mode + * may not actually be valid. EDID 1.3 sinks often report support for + * some CVT modes, but they are not required to support CVT timings for + * modes in the standard timing descriptor, so we should _not_ treat them + * as CVT-compliant (unless specified in an extension block I suppose). + * + * EDID 1.4 requires that all sink devices support both GTF and CVT timings + * for modes in this section, but does say that CVT is preferred. + */ +static DisplayModePtr +DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks, + int timing_level, Bool rb) +{ + DisplayModePtr Modes = NULL, Mode = NULL; + int i, hsize, vsize, refresh; + + for (i = 0; i < STD_TIMINGS; i++) { + hsize = timing[i].hsize; + vsize = timing[i].vsize; + refresh = timing[i].refresh; + + /* HDTV hack, because you can't say 1366 */ + if (refresh == 60 && + ((hsize == 1360 && vsize == 765) || + (hsize == 1368 && vsize == 769))) { + Mode = xf86CVTMode(1366, 768, 60, FALSE, FALSE); + Mode->HDisplay = 1366; + Mode->VSyncStart--; + Mode->VSyncEnd--; + } else if (hsize && vsize && refresh) { + Mode = FindDMTMode(hsize, vsize, refresh, rb); + + if (!Mode) { + if (timing_level == LEVEL_CVT) + /* pass rb here too? */ + Mode = xf86CVTMode(hsize, vsize, refresh, FALSE, FALSE); + else if (timing_level == LEVEL_GTF) + Mode = xf86GTFMode(hsize, vsize, refresh, FALSE, FALSE); + } + + } + + if (Mode) { + Mode->type = M_T_DRIVER; + Modes = xf86ModesAdd(Modes, Mode); + } + Mode = NULL; + } + + return Modes; +} + +static void +DDCModeDoInterlaceQuirks(DisplayModePtr mode) +{ + /* + * EDID is delightfully ambiguous about how interlaced modes are to be + * encoded. X's internal representation is of frame height, but some + * HDTV detailed timings are encoded as field height. + * + * The format list here is from CEA, in frame size. Technically we + * should be checking refresh rate too. Whatever. + */ + static const struct { + int w, h; + } cea_interlaced[] = { + { 1920, 1080 }, + { 720, 480 }, + { 1440, 480 }, + { 2880, 480 }, + { 720, 576 }, + { 1440, 576 }, + { 2880, 576 }, + }; + static const int n_modes = sizeof(cea_interlaced)/sizeof(cea_interlaced[0]); + int i; + + for (i = 0; i < n_modes; i++) { + if ((mode->HDisplay == cea_interlaced[i].w) && + (mode->VDisplay == cea_interlaced[i].h / 2)) { + mode->VDisplay *= 2; + mode->VSyncStart *= 2; + mode->VSyncEnd *= 2; + mode->VTotal *= 2; + mode->VTotal |= 1; + } + } + + mode->Flags |= V_INTERLACE; +} + +/* + * + */ +static DisplayModePtr +DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing, + Bool preferred, ddc_quirk_t quirks) +{ + DisplayModePtr Mode; + + /* + * Refuse to create modes that are insufficiently large. 64 is a random + * number, maybe the spec says something about what the minimum is. In + * particular I see this frequently with _old_ EDID, 1.0 or so, so maybe + * our parser is just being too aggresive there. + */ + if (timing->h_active < 64 || timing->v_active < 64) { + xf86DrvMsg(scrnIndex, X_INFO, + "%s: Ignoring tiny %dx%d mode\n", __func__, + timing->h_active, timing->v_active); + return NULL; + } + + /* We don't do stereo */ + if (timing->stereo) { + xf86DrvMsg(scrnIndex, X_INFO, + "%s: Ignoring: We don't handle stereo.\n", __func__); + return NULL; + } + + /* We only do seperate sync currently */ + if (timing->sync != 0x03) { + xf86DrvMsg(scrnIndex, X_INFO, + "%s: %dx%d Warning: We only handle separate" + " sync.\n", __func__, timing->h_active, timing->v_active); + } + + Mode = xnfcalloc(1, sizeof(DisplayModeRec)); + + Mode->type = M_T_DRIVER; + if (preferred) + Mode->type |= M_T_PREFERRED; + + if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) && + timing->clock == 135000000 ) + Mode->Clock = 108880; + else + Mode->Clock = timing->clock / 1000.0; + + Mode->HDisplay = timing->h_active; + Mode->HSyncStart = timing->h_active + timing->h_sync_off; + Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width; + Mode->HTotal = timing->h_active + timing->h_blanking; + + Mode->VDisplay = timing->v_active; + Mode->VSyncStart = timing->v_active + timing->v_sync_off; + Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width; + Mode->VTotal = timing->v_active + timing->v_blanking; + + /* perform basic check on the detail timing */ + if (Mode->HSyncEnd > Mode->HTotal || Mode->VSyncEnd > Mode->VTotal) { + free(Mode); + return NULL; + } + + /* We ignore h/v_size and h/v_border for now. */ + + if (timing->interlaced) + DDCModeDoInterlaceQuirks(Mode); + + if (quirks & DDC_QUIRK_DETAILED_SYNC_PP) + Mode->Flags |= V_PVSYNC | V_PHSYNC; + else { + if (timing->misc & 0x02) + Mode->Flags |= V_PVSYNC; + else + Mode->Flags |= V_NVSYNC; + + if (timing->misc & 0x01) + Mode->Flags |= V_PHSYNC; + else + Mode->Flags |= V_NHSYNC; + } + + xf86SetModeDefaultName(Mode); + + return Mode; +} + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) +static DisplayModePtr +DDCModesFromCVT(int scrnIndex, struct cvt_timings *t) +{ + DisplayModePtr modes = NULL; + int i; + + for (i = 0; i < 4; i++) { + if (t[i].height) { + if (t[i].rates & 0x10) + modes = xf86ModesAdd(modes, + xf86CVTMode(t[i].width, t[i].height, 50, 0, 0)); + if (t[i].rates & 0x08) + modes = xf86ModesAdd(modes, + xf86CVTMode(t[i].width, t[i].height, 60, 0, 0)); + if (t[i].rates & 0x04) + modes = xf86ModesAdd(modes, + xf86CVTMode(t[i].width, t[i].height, 75, 0, 0)); + if (t[i].rates & 0x02) + modes = xf86ModesAdd(modes, + xf86CVTMode(t[i].width, t[i].height, 85, 0, 0)); + if (t[i].rates & 0x01) + modes = xf86ModesAdd(modes, + xf86CVTMode(t[i].width, t[i].height, 60, 1, 0)); + } else break; + } + + return modes; +} +#endif + +static const struct { + short w; + short h; + short r; + short rb; +} EstIIIModes[] = { + /* byte 6 */ + { 640, 350, 85, 0 }, + { 640, 400, 85, 0 }, + { 720, 400, 85, 0 }, + { 640, 480, 85, 0 }, + { 848, 480, 60, 0 }, + { 800, 600, 85, 0 }, + { 1024, 768, 85, 0 }, + { 1152, 864, 75, 0 }, + /* byte 7 */ + { 1280, 768, 60, 1 }, + { 1280, 768, 60, 0 }, + { 1280, 768, 75, 0 }, + { 1280, 768, 85, 0 }, + { 1280, 960, 60, 0 }, + { 1280, 960, 85, 0 }, + { 1280, 1024, 60, 0 }, + { 1280, 1024, 85, 0 }, + /* byte 8 */ + { 1360, 768, 60, 0 }, + { 1440, 900, 60, 1 }, + { 1440, 900, 60, 0 }, + { 1440, 900, 75, 0 }, + { 1440, 900, 85, 0 }, + { 1400, 1050, 60, 1 }, + { 1400, 1050, 60, 0 }, + { 1400, 1050, 75, 0 }, + /* byte 9 */ + { 1400, 1050, 85, 0 }, + { 1680, 1050, 60, 1 }, + { 1680, 1050, 60, 0 }, + { 1680, 1050, 75, 0 }, + { 1680, 1050, 85, 0 }, + { 1600, 1200, 60, 0 }, + { 1600, 1200, 65, 0 }, + { 1600, 1200, 70, 0 }, + /* byte 10 */ + { 1600, 1200, 75, 0 }, + { 1600, 1200, 85, 0 }, + { 1792, 1344, 60, 0 }, + { 1792, 1344, 85, 0 }, + { 1856, 1392, 60, 0 }, + { 1856, 1392, 75, 0 }, + { 1920, 1200, 60, 1 }, + { 1920, 1200, 60, 0 }, + /* byte 11 */ + { 1920, 1200, 75, 0 }, + { 1920, 1200, 85, 0 }, + { 1920, 1440, 60, 0 }, + { 1920, 1440, 75, 0 }, +}; + +static DisplayModePtr +DDCModesFromEstIII(unsigned char *est) +{ + DisplayModePtr modes = NULL; + int i, j, m; + + for (i = 0; i < 6; i++) { + for (j = 7; j > 0; j--) { + if (est[i] & (1 << j)) { + m = (i * 8) + (7 - j); + modes = xf86ModesAdd(modes, + FindDMTMode(EstIIIModes[m].w, + EstIIIModes[m].h, + EstIIIModes[m].r, + EstIIIModes[m].rb)); + } + } + } + + return modes; +} + +/* + * This is only valid when the sink claims to be continuous-frequency + * but does not supply a detailed range descriptor. Such sinks are + * arguably broken. Currently the mode validation code isn't aware of + * this; the non-RANDR code even punts the decision of optional sync + * range checking to the driver. Loss. + */ +static void +DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes) +{ + DisplayModePtr Mode = Modes; + + if (!Monitor || !Modes) + return; + + /* set up the ranges for scanning through the modes */ + Monitor->nHsync = 1; + Monitor->hsync[0].lo = 1024.0; + Monitor->hsync[0].hi = 0.0; + + Monitor->nVrefresh = 1; + Monitor->vrefresh[0].lo = 1024.0; + Monitor->vrefresh[0].hi = 0.0; + + while (Mode) { + if (!Mode->HSync) + Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal); + + if (!Mode->VRefresh) + Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) / + ((float) (Mode->HTotal * Mode->VTotal)); + + if (Mode->HSync < Monitor->hsync[0].lo) + Monitor->hsync[0].lo = Mode->HSync; + + if (Mode->HSync > Monitor->hsync[0].hi) + Monitor->hsync[0].hi = Mode->HSync; + + if (Mode->VRefresh < Monitor->vrefresh[0].lo) + Monitor->vrefresh[0].lo = Mode->VRefresh; + + if (Mode->VRefresh > Monitor->vrefresh[0].hi) + Monitor->vrefresh[0].hi = Mode->VRefresh; + + Mode = Mode->next; + } +} + +ddc_quirk_t +xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose) +{ + ddc_quirk_t quirks; + int i; + + quirks = DDC_QUIRK_NONE; + for (i = 0; ddc_quirks[i].detect; i++) { + if (ddc_quirks[i].detect (scrnIndex, DDC)) { + if (verbose) { + xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n", + ddc_quirks[i].description); + } + quirks |= ddc_quirks[i].quirk; + } + } + + return quirks; +} + +void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon, + ddc_quirk_t quirks, + int hsize, int vsize) +{ + if (det_mon->type != DT) + return; + + if (quirks & DDC_QUIRK_DETAILED_H_IN_CM) + det_mon->section.d_timings.h_size *= 10; + + if (quirks & DDC_QUIRK_DETAILED_V_IN_CM) + det_mon->section.d_timings.v_size *= 10; + + if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { + det_mon->section.d_timings.h_size = 10 * hsize; + det_mon->section.d_timings.v_size = 10 * vsize; + } +} + +/** + * Applies monitor-specific quirks to the decoded EDID information. + * + * Note that some quirks applying to the mode list are still implemented in + * xf86DDCGetModes. + */ +void +xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC) +{ + ddc_quirk_t quirks = xf86DDCDetectQuirks (scrnIndex, DDC, FALSE); + int i; + + for (i = 0; i < DET_TIMINGS; i++) { + xf86DetTimingApplyQuirks(DDC->det_mon + i, quirks, + DDC->features.hsize, + DDC->features.vsize); + } +} + +/** + * Walks the modes list, finding the mode with the largest area which is + * closest to the target refresh rate, and marks it as the only preferred mode. +*/ +static void +xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes, + float target_refresh) +{ + DisplayModePtr mode, best = modes; + + for (mode = modes; mode; mode = mode->next) + { + mode->type &= ~M_T_PREFERRED; + + if (mode == best) continue; + + if (mode->HDisplay * mode->VDisplay > + best->HDisplay * best->VDisplay) + { + best = mode; + continue; + } + if (mode->HDisplay * mode->VDisplay == + best->HDisplay * best->VDisplay) + { + double mode_refresh = xf86ModeVRefresh (mode); + double best_refresh = xf86ModeVRefresh (best); + double mode_dist = fabs(mode_refresh - target_refresh); + double best_dist = fabs(best_refresh - target_refresh); + + if (mode_dist < best_dist) + { + best = mode; + continue; + } + } + } + if (best) + best->type |= M_T_PREFERRED; +} + +#define CEA_VIDEO_MODES_NUM 64 +static const DisplayModeRec CEAVideoModes[CEA_VIDEO_MODES_NUM] = { + { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 1:640x480@60Hz */ + { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 2:720x480@60Hz */ + { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 3:720x480@60Hz */ + { MODEPREFIX, 74250, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 4: 1280x720@60Hz */ + { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 5:1920x1080i@60Hz */ + { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 6:1440x480i@60Hz */ + { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 7:1440x480i@60Hz */ + { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 8:1440x240@60Hz */ + { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 9:1440x240@60Hz */ + { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 10:2880x480i@60Hz */ + { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 11:2880x480i@60Hz */ + { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 12:2880x240@60Hz */ + { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 13:2880x240@60Hz */ + { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 14:1440x480@60Hz */ + { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 15:1440x480@60Hz */ + { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 16:1920x1080@60Hz */ + { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 17:720x576@50Hz */ + { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 18:720x576@50Hz */ + { MODEPREFIX, 74250, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 19: 1280x720@50Hz */ + { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 20:1920x1080i@50Hz */ + { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 21:1440x576i@50Hz */ + { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 22:1440x576i@50Hz */ + { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 23:1440x288@50Hz */ + { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 24:1440x288@50Hz */ + { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 25:2880x576i@50Hz */ + { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 26:2880x576i@50Hz */ + { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 27:2880x288@50Hz */ + { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 28:2880x288@50Hz */ + { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 29:1440x576@50Hz */ + { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 30:1440x576@50Hz */ + { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 31:1920x1080@50Hz */ + { MODEPREFIX, 74250, 1920, 2558, 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 32:1920x1080@24Hz */ + { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 33:1920x1080@25Hz */ + { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 34:1920x1080@30Hz */ + { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 35:2880x480@60Hz */ + { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 36:2880x480@60Hz */ + { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 37:2880x576@50Hz */ + { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 38:2880x576@50Hz */ + { MODEPREFIX, 72000, 1920, 1952, 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, V_PHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 39:1920x1080i@50Hz */ + { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 40:1920x1080i@100Hz */ + { MODEPREFIX, 148500, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 41:1280x720@100Hz */ + { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 42:720x576@100Hz */ + { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 43:720x576@100Hz */ + { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 44:1440x576i@100Hz */ + { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 45:1440x576i@100Hz */ + { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 46:1920x1080i@120Hz */ + { MODEPREFIX, 148500, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 47:1280x720@120Hz */ + { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 48:720x480@120Hz */ + { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 49:720x480@120Hz */ + { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 50:1440x480i@120Hz */ + { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 51:1440x480i@120Hz */ + { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 52:720x576@200Hz */ + { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 53:720x576@200Hz */ + { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 54:1440x576i@200Hz */ + { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 55:1440x576i@200Hz */ + { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 56:720x480@240Hz */ + { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 57:720x480@240Hz */ + { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 58:1440x480i@240 */ + { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 59:1440x480i@240 */ + { MODEPREFIX, 59400, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 60: 1280x720@24Hz */ + { MODEPREFIX, 74250, 3700, 3740, 1430, 3960, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 61: 1280x720@25Hz */ + { MODEPREFIX, 74250, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 62: 1280x720@30Hz */ + { MODEPREFIX, 297000, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 63: 1920x1080@120Hz */ + { MODEPREFIX, 297000, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 64:1920x1080@100Hz */ +}; + +/* chose mode line by cea short video descriptor*/ +static void handle_cea_svd(struct cea_video_block *video, void *data) +{ + DisplayModePtr Mode; + DisplayModePtr *Modes = (DisplayModePtr *) data; + int vid; + + vid = video ->video_code & 0x7f; + if (vid < CEA_VIDEO_MODES_NUM) { + Mode = xf86DuplicateMode(CEAVideoModes + vid); + *Modes = xf86ModesAdd(*Modes, Mode); + } +} + +static DisplayModePtr +DDCModesFromCEAExtension(int scrnIndex, xf86MonPtr MonPtr) +{ + DisplayModePtr Modes = NULL; + + xf86ForEachVideoBlock(MonPtr, + handle_cea_svd, + &Modes); + + return Modes; +} + +struct det_modes_parameter { + xf86MonPtr DDC; + ddc_quirk_t quirks; + DisplayModePtr Modes; + Bool rb; + Bool preferred; + int timing_level; +}; + +static void handle_detailed_modes(struct detailed_monitor_section *det_mon, + void *data) +{ + DisplayModePtr Mode; + struct det_modes_parameter *p = (struct det_modes_parameter *)data; + + xf86DetTimingApplyQuirks(det_mon,p->quirks, + p->DDC->features.hsize, + p->DDC->features.vsize); + + switch (det_mon->type) { + case DT: + Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex, + &det_mon->section.d_timings, + p->preferred, + p->quirks); + p->preferred = FALSE; + p->Modes = xf86ModesAdd(p->Modes, Mode); + break; + case DS_STD_TIMINGS: + Mode = DDCModesFromStandardTiming(det_mon->section.std_t, + p->quirks, p->timing_level,p->rb); + p->Modes = xf86ModesAdd(p->Modes, Mode); + break; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + case DS_CVT: + Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt); + p->Modes = xf86ModesAdd(p->Modes, Mode); + break; +#endif + case DS_EST_III: + Mode = DDCModesFromEstIII(det_mon->section.est_iii); + p->Modes = xf86ModesAdd(p->Modes, Mode); + break; + default: + break; + } +} + +DisplayModePtr +xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) +{ + DisplayModePtr Modes = NULL, Mode; + ddc_quirk_t quirks; + Bool preferred, rb; + int timing_level; + struct det_modes_parameter p; + + xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n", + DDC->vendor.name, DDC->vendor.prod_id); + + quirks = xf86DDCDetectQuirks(scrnIndex, DDC, TRUE); + + preferred = PREFERRED_TIMING_MODE(DDC->features.msc); + if (DDC->ver.revision >= 4) + preferred = TRUE; + if (quirks & DDC_QUIRK_FIRST_DETAILED_PREFERRED) + preferred = TRUE; + if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75)) + preferred = FALSE; + + rb = xf86MonitorSupportsReducedBlanking(DDC); + + timing_level = MonitorStandardTimingLevel(DDC); + + p.quirks = quirks; + p.DDC = DDC; + p.Modes = Modes; + p.rb = rb; + p.preferred = preferred; + p.timing_level = timing_level; + xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p); + Modes = p.Modes; + + /* Add established timings */ + Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks); + Modes = xf86ModesAdd(Modes, Mode); + + /* Add standard timings */ + Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb); + Modes = xf86ModesAdd(Modes, Mode); + + /* Add cea-extension mode timings */ + Mode = DDCModesFromCEAExtension(scrnIndex,DDC); + Modes = xf86ModesAdd(Modes, Mode); + + if (quirks & DDC_QUIRK_PREFER_LARGE_60) + xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60); + + if (quirks & DDC_QUIRK_PREFER_LARGE_75) + xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75); + + Modes = xf86PruneDuplicateModes(Modes); + + return Modes; +} + +struct det_mon_parameter { + MonPtr Monitor; + ddc_quirk_t quirks; + Bool have_hsync; + Bool have_vrefresh; + Bool have_maxpixclock; +}; + +static void handle_detailed_monset(struct detailed_monitor_section *det_mon, + void *data) +{ + int clock; + struct det_mon_parameter *p = (struct det_mon_parameter *)data; + int scrnIndex = ((xf86MonPtr)(p->Monitor->DDC))->scrnIndex; + + switch (det_mon->type) { + case DS_RANGES: + if (!p->have_hsync) { + if (!p->Monitor->nHsync) + xf86DrvMsg(scrnIndex, X_INFO, + "Using EDID range info for horizontal sync\n"); + p->Monitor->hsync[p->Monitor->nHsync].lo = + det_mon->section.ranges.min_h; + p->Monitor->hsync[p->Monitor->nHsync].hi = + det_mon->section.ranges.max_h; + p->Monitor->nHsync++; + } else { + xf86DrvMsg(scrnIndex, X_INFO, + "Using hsync ranges from config file\n"); + } + + if (!p->have_vrefresh) { + if (!p->Monitor->nVrefresh) + xf86DrvMsg(scrnIndex, X_INFO, + "Using EDID range info for vertical refresh\n"); + p->Monitor->vrefresh[p->Monitor->nVrefresh].lo = + det_mon->section.ranges.min_v; + p->Monitor->vrefresh[p->Monitor->nVrefresh].hi = + det_mon->section.ranges.max_v; + p->Monitor->nVrefresh++; + } else { + xf86DrvMsg(scrnIndex, X_INFO, + "Using vrefresh ranges from config file\n"); + } + + clock = det_mon->section.ranges.max_clock * 1000; + if (p->quirks & DDC_QUIRK_DVI_SINGLE_LINK) + clock = min(clock, 165000); + if (!p->have_maxpixclock && clock > p->Monitor->maxPixClock) + p->Monitor->maxPixClock = clock; + + break; + default: + break; + } +} + +/* + * Fill out MonPtr with xf86MonPtr information. + */ +void +xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) +{ + DisplayModePtr Modes = NULL, Mode; + struct det_mon_parameter p; + + if (!Monitor || !DDC) + return; + + Monitor->DDC = DDC; + + if (Monitor->widthmm <= 0 || Monitor->heightmm <= 0) { + Monitor->widthmm = 10 * DDC->features.hsize; + Monitor->heightmm = 10 * DDC->features.vsize; + } + + Monitor->reducedblanking = xf86MonitorSupportsReducedBlanking(DDC); + + Modes = xf86DDCGetModes(scrnIndex, DDC); + + /* Go through the detailed monitor sections */ + p.Monitor = Monitor; + p.quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE); + p.have_hsync = (Monitor->nHsync != 0); + p.have_vrefresh = (Monitor->nVrefresh != 0); + p.have_maxpixclock = (Monitor->maxPixClock != 0); + xf86ForEachDetailedBlock(DDC, handle_detailed_monset, &p); + + if (Modes) { + /* Print Modes */ + xf86DrvMsg(scrnIndex, X_INFO, "Printing DDC gathered Modelines:\n"); + + Mode = Modes; + while (Mode) { + xf86PrintModeline(scrnIndex, Mode); + Mode = Mode->next; + } + + /* Do we still need ranges to be filled in? */ + if (!Monitor->nHsync || !Monitor->nVrefresh) + DDCGuessRangesFromModes(scrnIndex, Monitor, Modes); + + /* look for last Mode */ + Mode = Modes; + + while (Mode->next) + Mode = Mode->next; + + /* add to MonPtr */ + if (Monitor->Modes) { + Monitor->Last->next = Modes; + Modes->prev = Monitor->Last; + Monitor->Last = Mode; + } else { + Monitor->Modes = Modes; + Monitor->Last = Mode; + } + } +} diff --git a/xorg-server/hw/xfree86/modes/xf86Modes.c b/xorg-server/hw/xfree86/modes/xf86Modes.c index 75aedaa99..0507e9812 100644 --- a/xorg-server/hw/xfree86/modes/xf86Modes.c +++ b/xorg-server/hw/xfree86/modes/xf86Modes.c @@ -1,727 +1,727 @@ -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#else -#ifdef HAVE_CONFIG_H -#include -#endif -#endif - -#include "xf86Modes.h" -#include "xf86Priv.h" - -extern XF86ConfigPtr xf86configptr; - -/* - * This is the version number where we epoched. These files get copied - * into drivers that want to use this setup infrastructure on pre-1.3 - * servers, so when that happens they need to define these symbols - * themselves. However, _in_ the server, we basically always define them now. - */ -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) - -/** - * Calculates the horizontal sync rate of a mode. - */ -double -xf86ModeHSync(const DisplayModeRec *mode) -{ - double hsync = 0.0; - - if (mode->HSync > 0.0) - hsync = mode->HSync; - else if (mode->HTotal > 0) - hsync = (float)mode->Clock / (float)mode->HTotal; - - return hsync; -} - -/** - * Calculates the vertical refresh rate of a mode. - */ -double -xf86ModeVRefresh(const DisplayModeRec *mode) -{ - double refresh = 0.0; - - if (mode->VRefresh > 0.0) - refresh = mode->VRefresh; - else if (mode->HTotal > 0 && mode->VTotal > 0) { - refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal; - if (mode->Flags & V_INTERLACE) - refresh *= 2.0; - if (mode->Flags & V_DBLSCAN) - refresh /= 2.0; - if (mode->VScan > 1) - refresh /= (float)(mode->VScan); - } - return refresh; -} - -int -xf86ModeWidth (const DisplayModeRec *mode, Rotation rotation) -{ - switch (rotation & 0xf) { - case RR_Rotate_0: - case RR_Rotate_180: - return mode->HDisplay; - case RR_Rotate_90: - case RR_Rotate_270: - return mode->VDisplay; - default: - return 0; - } -} - -int -xf86ModeHeight (const DisplayModeRec *mode, Rotation rotation) -{ - switch (rotation & 0xf) { - case RR_Rotate_0: - case RR_Rotate_180: - return mode->VDisplay; - case RR_Rotate_90: - case RR_Rotate_270: - return mode->HDisplay; - default: - return 0; - } -} - -/** Calculates the memory bandwidth (in MiB/sec) of a mode. */ -unsigned int -xf86ModeBandwidth(DisplayModePtr mode, int depth) -{ - float a_active, a_total, active_percent, pixels_per_second; - int bytes_per_pixel = bits_to_bytes(depth); - - if (!mode->HTotal || !mode->VTotal || !mode->Clock) - return 0; - - a_active = mode->HDisplay * mode->VDisplay; - a_total = mode->HTotal * mode->VTotal; - active_percent = a_active / a_total; - pixels_per_second = active_percent * mode->Clock * 1000.0; - - return (unsigned int)(pixels_per_second * bytes_per_pixel / (1024 * 1024)); -} - -/** Sets a default mode name of x on a mode. */ -void -xf86SetModeDefaultName(DisplayModePtr mode) -{ - Bool interlaced = !!(mode->Flags & V_INTERLACE); - - xfree(mode->name); - - mode->name = XNFprintf("%dx%d%s", mode->HDisplay, mode->VDisplay, - interlaced ? "i" : ""); -} - -/* - * xf86SetModeCrtc - * - * Initialises the Crtc parameters for a mode. The initialisation includes - * adjustments for interlaced and double scan modes. - */ -void -xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) -{ - if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)) - return; - - p->CrtcHDisplay = p->HDisplay; - p->CrtcHSyncStart = p->HSyncStart; - p->CrtcHSyncEnd = p->HSyncEnd; - p->CrtcHTotal = p->HTotal; - p->CrtcHSkew = p->HSkew; - p->CrtcVDisplay = p->VDisplay; - p->CrtcVSyncStart = p->VSyncStart; - p->CrtcVSyncEnd = p->VSyncEnd; - p->CrtcVTotal = p->VTotal; - if (p->Flags & V_INTERLACE) { - if (adjustFlags & INTERLACE_HALVE_V) { - p->CrtcVDisplay /= 2; - p->CrtcVSyncStart /= 2; - p->CrtcVSyncEnd /= 2; - p->CrtcVTotal /= 2; - } - /* Force interlaced modes to have an odd VTotal */ - /* maybe we should only do this when INTERLACE_HALVE_V is set? */ - p->CrtcVTotal |= 1; - } - - if (p->Flags & V_DBLSCAN) { - p->CrtcVDisplay *= 2; - p->CrtcVSyncStart *= 2; - p->CrtcVSyncEnd *= 2; - p->CrtcVTotal *= 2; - } - if (p->VScan > 1) { - p->CrtcVDisplay *= p->VScan; - p->CrtcVSyncStart *= p->VScan; - p->CrtcVSyncEnd *= p->VScan; - p->CrtcVTotal *= p->VScan; - } - p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay); - p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal); - p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay); - p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal); - - p->CrtcHAdjusted = FALSE; - p->CrtcVAdjusted = FALSE; -} - -/** - * Allocates and returns a copy of pMode, including pointers within pMode. - */ -DisplayModePtr -xf86DuplicateMode(const DisplayModeRec *pMode) -{ - DisplayModePtr pNew; - - pNew = xnfalloc(sizeof(DisplayModeRec)); - *pNew = *pMode; - pNew->next = NULL; - pNew->prev = NULL; - - if (pMode->name == NULL) - xf86SetModeDefaultName(pNew); - else - pNew->name = xnfstrdup(pMode->name); - - return pNew; -} - -/** - * Duplicates every mode in the given list and returns a pointer to the first - * mode. - * - * \param modeList doubly-linked mode list - */ -DisplayModePtr -xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList) -{ - DisplayModePtr first = NULL, last = NULL; - DisplayModePtr mode; - - for (mode = modeList; mode != NULL; mode = mode->next) { - DisplayModePtr new; - - new = xf86DuplicateMode(mode); - - /* Insert pNew into modeList */ - if (last) { - last->next = new; - new->prev = last; - } else { - first = new; - new->prev = NULL; - } - new->next = NULL; - last = new; - } - - return first; -} - -/** - * Returns true if the given modes should program to the same timings. - * - * This doesn't use Crtc values, as it might be used on ModeRecs without the - * Crtc values set. So, it's assumed that the other numbers are enough. - */ -Bool -xf86ModesEqual(const DisplayModeRec *pMode1, const DisplayModeRec *pMode2) -{ - if (pMode1->Clock == pMode2->Clock && - pMode1->HDisplay == pMode2->HDisplay && - pMode1->HSyncStart == pMode2->HSyncStart && - pMode1->HSyncEnd == pMode2->HSyncEnd && - pMode1->HTotal == pMode2->HTotal && - pMode1->HSkew == pMode2->HSkew && - pMode1->VDisplay == pMode2->VDisplay && - pMode1->VSyncStart == pMode2->VSyncStart && - pMode1->VSyncEnd == pMode2->VSyncEnd && - pMode1->VTotal == pMode2->VTotal && - pMode1->VScan == pMode2->VScan && - pMode1->Flags == pMode2->Flags) - { - return TRUE; - } else { - return FALSE; - } -} - -static void -add(char **p, char *new) -{ - *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2); - strcat(*p, " "); - strcat(*p, new); -} - -/** - * Print out a modeline. - */ -void -xf86PrintModeline(int scrnIndex,DisplayModePtr mode) -{ - char tmp[256]; - char *flags = xnfcalloc(1, 1); - - if (mode->HSkew) { - snprintf(tmp, 256, "hskew %i", mode->HSkew); - add(&flags, tmp); - } - if (mode->VScan) { - snprintf(tmp, 256, "vscan %i", mode->VScan); - add(&flags, tmp); - } - if (mode->Flags & V_INTERLACE) add(&flags, "interlace"); - if (mode->Flags & V_CSYNC) add(&flags, "composite"); - if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan"); - if (mode->Flags & V_BCAST) add(&flags, "bcast"); - if (mode->Flags & V_PHSYNC) add(&flags, "+hsync"); - if (mode->Flags & V_NHSYNC) add(&flags, "-hsync"); - if (mode->Flags & V_PVSYNC) add(&flags, "+vsync"); - if (mode->Flags & V_NVSYNC) add(&flags, "-vsync"); - if (mode->Flags & V_PCSYNC) add(&flags, "+csync"); - if (mode->Flags & V_NCSYNC) add(&flags, "-csync"); -#if 0 - if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2"); -#endif - xf86DrvMsg(scrnIndex, X_INFO, - "Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s " - "(%.01f kHz)\n", - mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay, - mode->HSyncStart, mode->HSyncEnd, mode->HTotal, - mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, - mode->VTotal, flags, xf86ModeHSync(mode)); - xfree(flags); -} -#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */ - -/** - * Marks as bad any modes with unsupported flags. - * - * \param modeList doubly-linked list of modes. - * \param flags flags supported by the driver. - * - * \bug only V_INTERLACE and V_DBLSCAN are supported. Is that enough? - */ -void -xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, - int flags) -{ - DisplayModePtr mode; - - if (flags == (V_INTERLACE | V_DBLSCAN)) - return; - - for (mode = modeList; mode != NULL; mode = mode->next) { - if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE)) - mode->status = MODE_NO_INTERLACE; - if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN)) - mode->status = MODE_NO_DBLESCAN; - } -} - -/** - * Marks as bad any modes extending beyond the given max X, Y, or pitch. - * - * \param modeList doubly-linked list of modes. - */ -void -xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, - int maxX, int maxY, int maxPitch) -{ - DisplayModePtr mode; - - for (mode = modeList; mode != NULL; mode = mode->next) { - if (maxPitch > 0 && mode->HDisplay > maxPitch) - mode->status = MODE_BAD_WIDTH; - - if (maxX > 0 && mode->HDisplay > maxX) - mode->status = MODE_VIRTUAL_X; - - if (maxY > 0 && mode->VDisplay > maxY) - mode->status = MODE_VIRTUAL_Y; - - if (mode->next == modeList) - break; - } -} - -/** - * Marks as bad any modes that aren't supported by the given monitor's - * hsync and vrefresh ranges. - * - * \param modeList doubly-linked list of modes. - */ -void -xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, - MonPtr mon) -{ - DisplayModePtr mode; - - for (mode = modeList; mode != NULL; mode = mode->next) { - Bool bad; - int i; - - bad = TRUE; - for (i = 0; i < mon->nHsync; i++) { - if (xf86ModeHSync(mode) >= mon->hsync[i].lo * (1-SYNC_TOLERANCE) && - xf86ModeHSync(mode) <= mon->hsync[i].hi * (1+SYNC_TOLERANCE)) - { - bad = FALSE; - } - } - if (bad) - mode->status = MODE_HSYNC; - - bad = TRUE; - for (i = 0; i < mon->nVrefresh; i++) { - if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo * (1-SYNC_TOLERANCE) && - xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi * (1+SYNC_TOLERANCE)) - { - bad = FALSE; - } - } - if (bad) - mode->status = MODE_VSYNC; - - if (mode->next == modeList) - break; - } -} - -/** - * Marks as bad any modes extending beyond outside of the given clock ranges. - * - * \param modeList doubly-linked list of modes. - * \param min pointer to minimums of clock ranges - * \param max pointer to maximums of clock ranges - * \param n_ranges number of ranges. - */ -void -xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, - int *min, int *max, int n_ranges) -{ - DisplayModePtr mode; - int i; - - for (mode = modeList; mode != NULL; mode = mode->next) { - Bool good = FALSE; - for (i = 0; i < n_ranges; i++) { - if (mode->Clock >= min[i] * (1-SYNC_TOLERANCE) && - mode->Clock <= max[i] * (1+SYNC_TOLERANCE)) { - good = TRUE; - break; - } - } - if (!good) - mode->status = MODE_CLOCK_RANGE; - } -} - -/** - * If the user has specified a set of mode names to use, mark as bad any modes - * not listed. - * - * The user mode names specified are prefixes to names of modes, so "1024x768" - * will match modes named "1024x768", "1024x768x75", "1024x768-good", but - * "1024x768x75" would only match "1024x768x75" from that list. - * - * MODE_BAD is used as the rejection flag, for lack of a better flag. - * - * \param modeList doubly-linked list of modes. - */ -void -xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList) -{ - DisplayModePtr mode; - - if (pScrn->display->modes[0] == NULL) - return; - - for (mode = modeList; mode != NULL; mode = mode->next) { - int i; - Bool good = FALSE; - - for (i = 0; pScrn->display->modes[i] != NULL; i++) { - if (strncmp(pScrn->display->modes[i], mode->name, - strlen(pScrn->display->modes[i])) == 0) { - good = TRUE; - break; - } - } - if (!good) - mode->status = MODE_BAD; - } -} - - -/** - * Marks as bad any modes exceeding the given bandwidth. - * - * \param modeList doubly-linked list of modes. - * \param bandwidth bandwidth in MHz. - * \param depth color depth. - */ -void -xf86ValidateModesBandwidth(ScrnInfoPtr pScrn, DisplayModePtr modeList, - unsigned int bandwidth, int depth) -{ - DisplayModePtr mode; - - for (mode = modeList; mode != NULL; mode = mode->next) { - if (xf86ModeBandwidth(mode, depth) > bandwidth) -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - mode->status = MODE_BANDWIDTH; -#else - /* MODE_BANDWIDTH didn't exist in xserver 1.2 */ - mode->status = MODE_BAD; -#endif - } -} - -Bool -xf86ModeIsReduced(const DisplayModeRec *mode) -{ - if ((((mode->HDisplay * 5 / 4) & ~0x07) > mode->HTotal) && - ((mode->HTotal - mode->HDisplay) == 160) && - ((mode->HSyncEnd - mode->HDisplay) == 80) && - ((mode->HSyncEnd - mode->HSyncStart) == 32) && - ((mode->VSyncStart - mode->VDisplay) == 3)) - return TRUE; - return FALSE; -} - -/** - * Marks as bad any reduced-blanking modes. - * - * \param modeList doubly-linked list of modes. - */ -void -xf86ValidateModesReducedBlanking(ScrnInfoPtr pScrn, DisplayModePtr modeList) -{ - for (; modeList != NULL; modeList = modeList->next) - if (xf86ModeIsReduced(modeList)) - modeList->status = MODE_NO_REDUCED; -} - -/** - * Frees any modes from the list with a status other than MODE_OK. - * - * \param modeList pointer to a doubly-linked or circular list of modes. - * \param verbose determines whether the reason for mode invalidation is - * printed. - */ -void -xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, - Bool verbose) -{ - DisplayModePtr mode; - - for (mode = *modeList; mode != NULL;) { - DisplayModePtr next = mode->next, first = *modeList; - - if (mode->status != MODE_OK) { - if (verbose) { - char *type = ""; - if (mode->type & M_T_BUILTIN) - type = "built-in "; - else if (mode->type & M_T_DEFAULT) - type = "default "; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Not using %smode \"%s\" (%s)\n", type, mode->name, - xf86ModeStatusToString(mode->status)); - } - xf86DeleteMode(modeList, mode); - } - - if (next == first) - break; - mode = next; - } -} - -/** - * Adds the new mode into the mode list, and returns the new list - * - * \param modes doubly-linked mode list. - */ -DisplayModePtr -xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new) -{ - if (modes == NULL) - return new; - - if (new) { - DisplayModePtr mode = modes; - - while (mode->next) - mode = mode->next; - - mode->next = new; - new->prev = mode; - } - - return modes; -} - -/** - * Build a mode list from a list of config file modes - */ -static DisplayModePtr -xf86GetConfigModes (XF86ConfModeLinePtr conf_mode) -{ - DisplayModePtr head = NULL, prev = NULL, mode; - - for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next) - { - mode = xcalloc(1, sizeof(DisplayModeRec)); - if (!mode) - continue; - mode->name = xstrdup(conf_mode->ml_identifier); - if (!mode->name) - { - xfree (mode); - continue; - } - mode->type = 0; - mode->Clock = conf_mode->ml_clock; - mode->HDisplay = conf_mode->ml_hdisplay; - mode->HSyncStart = conf_mode->ml_hsyncstart; - mode->HSyncEnd = conf_mode->ml_hsyncend; - mode->HTotal = conf_mode->ml_htotal; - mode->VDisplay = conf_mode->ml_vdisplay; - mode->VSyncStart = conf_mode->ml_vsyncstart; - mode->VSyncEnd = conf_mode->ml_vsyncend; - mode->VTotal = conf_mode->ml_vtotal; - mode->Flags = conf_mode->ml_flags; - mode->HSkew = conf_mode->ml_hskew; - mode->VScan = conf_mode->ml_vscan; - - mode->prev = prev; - mode->next = NULL; - if (prev) - prev->next = mode; - else - head = mode; - prev = mode; - } - return head; -} - -/** - * Build a mode list from a monitor configuration - */ -DisplayModePtr -xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) -{ - DisplayModePtr modes = NULL; - XF86ConfModesLinkPtr modes_link; - - if (!conf_monitor) - return NULL; - - /* - * first we collect the mode lines from the UseModes directive - */ - for (modes_link = conf_monitor->mon_modes_sect_lst; - modes_link; - modes_link = modes_link->list.next) - { - /* If this modes link hasn't been resolved, go look it up now */ - if (!modes_link->ml_modes) - modes_link->ml_modes = xf86findModes (modes_link->ml_modes_str, - xf86configptr->conf_modes_lst); - if (modes_link->ml_modes) - modes = xf86ModesAdd (modes, - xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst)); - } - - return xf86ModesAdd (modes, - xf86GetConfigModes (conf_monitor->mon_modeline_lst)); -} - -/** - * Build a mode list containing all of the default modes - */ -DisplayModePtr -xf86GetDefaultModes (void) -{ - DisplayModePtr head = NULL, mode; - int i; - - for (i = 0; i < xf86NumDefaultModes; i++) - { - const DisplayModeRec *defMode = &xf86DefaultModes[i]; - - mode = xf86DuplicateMode(defMode); - head = xf86ModesAdd(head, mode); - } - return head; -} - -/* - * Walk a mode list and prune out duplicates. Will preserve the preferred - * mode of an otherwise-duplicate pair. - * - * Probably best to call this on lists that are all of a single class - * (driver, default, user, etc.), otherwise, which mode gets deleted is - * not especially well defined. - * - * Returns the new list. - */ - -DisplayModePtr -xf86PruneDuplicateModes(DisplayModePtr modes) -{ - DisplayModePtr m, n, o; - -top: - for (m = modes; m; m = m->next) { - for (n = m->next; n; n = o) { - o = n->next; - if (xf86ModesEqual(m, n)) { - if (n->type & M_T_PREFERRED) { - xf86DeleteMode(&modes, m); - goto top; - } - else - xf86DeleteMode(&modes, n); - } - } - } - - return modes; -} +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#else +#ifdef HAVE_CONFIG_H +#include +#endif +#endif + +#include "xf86Modes.h" +#include "xf86Priv.h" + +extern XF86ConfigPtr xf86configptr; + +/* + * This is the version number where we epoched. These files get copied + * into drivers that want to use this setup infrastructure on pre-1.3 + * servers, so when that happens they need to define these symbols + * themselves. However, _in_ the server, we basically always define them now. + */ +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) + +/** + * Calculates the horizontal sync rate of a mode. + */ +double +xf86ModeHSync(const DisplayModeRec *mode) +{ + double hsync = 0.0; + + if (mode->HSync > 0.0) + hsync = mode->HSync; + else if (mode->HTotal > 0) + hsync = (float)mode->Clock / (float)mode->HTotal; + + return hsync; +} + +/** + * Calculates the vertical refresh rate of a mode. + */ +double +xf86ModeVRefresh(const DisplayModeRec *mode) +{ + double refresh = 0.0; + + if (mode->VRefresh > 0.0) + refresh = mode->VRefresh; + else if (mode->HTotal > 0 && mode->VTotal > 0) { + refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal; + if (mode->Flags & V_INTERLACE) + refresh *= 2.0; + if (mode->Flags & V_DBLSCAN) + refresh /= 2.0; + if (mode->VScan > 1) + refresh /= (float)(mode->VScan); + } + return refresh; +} + +int +xf86ModeWidth (const DisplayModeRec *mode, Rotation rotation) +{ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_180: + return mode->HDisplay; + case RR_Rotate_90: + case RR_Rotate_270: + return mode->VDisplay; + default: + return 0; + } +} + +int +xf86ModeHeight (const DisplayModeRec *mode, Rotation rotation) +{ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_180: + return mode->VDisplay; + case RR_Rotate_90: + case RR_Rotate_270: + return mode->HDisplay; + default: + return 0; + } +} + +/** Calculates the memory bandwidth (in MiB/sec) of a mode. */ +unsigned int +xf86ModeBandwidth(DisplayModePtr mode, int depth) +{ + float a_active, a_total, active_percent, pixels_per_second; + int bytes_per_pixel = bits_to_bytes(depth); + + if (!mode->HTotal || !mode->VTotal || !mode->Clock) + return 0; + + a_active = mode->HDisplay * mode->VDisplay; + a_total = mode->HTotal * mode->VTotal; + active_percent = a_active / a_total; + pixels_per_second = active_percent * mode->Clock * 1000.0; + + return (unsigned int)(pixels_per_second * bytes_per_pixel / (1024 * 1024)); +} + +/** Sets a default mode name of x on a mode. */ +void +xf86SetModeDefaultName(DisplayModePtr mode) +{ + Bool interlaced = !!(mode->Flags & V_INTERLACE); + + free(mode->name); + + mode->name = XNFprintf("%dx%d%s", mode->HDisplay, mode->VDisplay, + interlaced ? "i" : ""); +} + +/* + * xf86SetModeCrtc + * + * Initialises the Crtc parameters for a mode. The initialisation includes + * adjustments for interlaced and double scan modes. + */ +void +xf86SetModeCrtc(DisplayModePtr p, int adjustFlags) +{ + if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN)) + return; + + p->CrtcHDisplay = p->HDisplay; + p->CrtcHSyncStart = p->HSyncStart; + p->CrtcHSyncEnd = p->HSyncEnd; + p->CrtcHTotal = p->HTotal; + p->CrtcHSkew = p->HSkew; + p->CrtcVDisplay = p->VDisplay; + p->CrtcVSyncStart = p->VSyncStart; + p->CrtcVSyncEnd = p->VSyncEnd; + p->CrtcVTotal = p->VTotal; + if (p->Flags & V_INTERLACE) { + if (adjustFlags & INTERLACE_HALVE_V) { + p->CrtcVDisplay /= 2; + p->CrtcVSyncStart /= 2; + p->CrtcVSyncEnd /= 2; + p->CrtcVTotal /= 2; + } + /* Force interlaced modes to have an odd VTotal */ + /* maybe we should only do this when INTERLACE_HALVE_V is set? */ + p->CrtcVTotal |= 1; + } + + if (p->Flags & V_DBLSCAN) { + p->CrtcVDisplay *= 2; + p->CrtcVSyncStart *= 2; + p->CrtcVSyncEnd *= 2; + p->CrtcVTotal *= 2; + } + if (p->VScan > 1) { + p->CrtcVDisplay *= p->VScan; + p->CrtcVSyncStart *= p->VScan; + p->CrtcVSyncEnd *= p->VScan; + p->CrtcVTotal *= p->VScan; + } + p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay); + p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal); + p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay); + p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal); + + p->CrtcHAdjusted = FALSE; + p->CrtcVAdjusted = FALSE; +} + +/** + * Allocates and returns a copy of pMode, including pointers within pMode. + */ +DisplayModePtr +xf86DuplicateMode(const DisplayModeRec *pMode) +{ + DisplayModePtr pNew; + + pNew = xnfalloc(sizeof(DisplayModeRec)); + *pNew = *pMode; + pNew->next = NULL; + pNew->prev = NULL; + + if (pMode->name == NULL) + xf86SetModeDefaultName(pNew); + else + pNew->name = xnfstrdup(pMode->name); + + return pNew; +} + +/** + * Duplicates every mode in the given list and returns a pointer to the first + * mode. + * + * \param modeList doubly-linked mode list + */ +DisplayModePtr +xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList) +{ + DisplayModePtr first = NULL, last = NULL; + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + DisplayModePtr new; + + new = xf86DuplicateMode(mode); + + /* Insert pNew into modeList */ + if (last) { + last->next = new; + new->prev = last; + } else { + first = new; + new->prev = NULL; + } + new->next = NULL; + last = new; + } + + return first; +} + +/** + * Returns true if the given modes should program to the same timings. + * + * This doesn't use Crtc values, as it might be used on ModeRecs without the + * Crtc values set. So, it's assumed that the other numbers are enough. + */ +Bool +xf86ModesEqual(const DisplayModeRec *pMode1, const DisplayModeRec *pMode2) +{ + if (pMode1->Clock == pMode2->Clock && + pMode1->HDisplay == pMode2->HDisplay && + pMode1->HSyncStart == pMode2->HSyncStart && + pMode1->HSyncEnd == pMode2->HSyncEnd && + pMode1->HTotal == pMode2->HTotal && + pMode1->HSkew == pMode2->HSkew && + pMode1->VDisplay == pMode2->VDisplay && + pMode1->VSyncStart == pMode2->VSyncStart && + pMode1->VSyncEnd == pMode2->VSyncEnd && + pMode1->VTotal == pMode2->VTotal && + pMode1->VScan == pMode2->VScan && + pMode1->Flags == pMode2->Flags) + { + return TRUE; + } else { + return FALSE; + } +} + +static void +add(char **p, char *new) +{ + *p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2); + strcat(*p, " "); + strcat(*p, new); +} + +/** + * Print out a modeline. + */ +void +xf86PrintModeline(int scrnIndex,DisplayModePtr mode) +{ + char tmp[256]; + char *flags = xnfcalloc(1, 1); + + if (mode->HSkew) { + snprintf(tmp, 256, "hskew %i", mode->HSkew); + add(&flags, tmp); + } + if (mode->VScan) { + snprintf(tmp, 256, "vscan %i", mode->VScan); + add(&flags, tmp); + } + if (mode->Flags & V_INTERLACE) add(&flags, "interlace"); + if (mode->Flags & V_CSYNC) add(&flags, "composite"); + if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan"); + if (mode->Flags & V_BCAST) add(&flags, "bcast"); + if (mode->Flags & V_PHSYNC) add(&flags, "+hsync"); + if (mode->Flags & V_NHSYNC) add(&flags, "-hsync"); + if (mode->Flags & V_PVSYNC) add(&flags, "+vsync"); + if (mode->Flags & V_NVSYNC) add(&flags, "-vsync"); + if (mode->Flags & V_PCSYNC) add(&flags, "+csync"); + if (mode->Flags & V_NCSYNC) add(&flags, "-csync"); +#if 0 + if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2"); +#endif + xf86DrvMsg(scrnIndex, X_INFO, + "Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s " + "(%.01f kHz)\n", + mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay, + mode->HSyncStart, mode->HSyncEnd, mode->HTotal, + mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, + mode->VTotal, flags, xf86ModeHSync(mode)); + free(flags); +} +#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */ + +/** + * Marks as bad any modes with unsupported flags. + * + * \param modeList doubly-linked list of modes. + * \param flags flags supported by the driver. + * + * \bug only V_INTERLACE and V_DBLSCAN are supported. Is that enough? + */ +void +xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int flags) +{ + DisplayModePtr mode; + + if (flags == (V_INTERLACE | V_DBLSCAN)) + return; + + for (mode = modeList; mode != NULL; mode = mode->next) { + if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE)) + mode->status = MODE_NO_INTERLACE; + if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN)) + mode->status = MODE_NO_DBLESCAN; + } +} + +/** + * Marks as bad any modes extending beyond the given max X, Y, or pitch. + * + * \param modeList doubly-linked list of modes. + */ +void +xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int maxX, int maxY, int maxPitch) +{ + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + if (maxPitch > 0 && mode->HDisplay > maxPitch) + mode->status = MODE_BAD_WIDTH; + + if (maxX > 0 && mode->HDisplay > maxX) + mode->status = MODE_VIRTUAL_X; + + if (maxY > 0 && mode->VDisplay > maxY) + mode->status = MODE_VIRTUAL_Y; + + if (mode->next == modeList) + break; + } +} + +/** + * Marks as bad any modes that aren't supported by the given monitor's + * hsync and vrefresh ranges. + * + * \param modeList doubly-linked list of modes. + */ +void +xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, + MonPtr mon) +{ + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + Bool bad; + int i; + + bad = TRUE; + for (i = 0; i < mon->nHsync; i++) { + if (xf86ModeHSync(mode) >= mon->hsync[i].lo * (1-SYNC_TOLERANCE) && + xf86ModeHSync(mode) <= mon->hsync[i].hi * (1+SYNC_TOLERANCE)) + { + bad = FALSE; + } + } + if (bad) + mode->status = MODE_HSYNC; + + bad = TRUE; + for (i = 0; i < mon->nVrefresh; i++) { + if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo * (1-SYNC_TOLERANCE) && + xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi * (1+SYNC_TOLERANCE)) + { + bad = FALSE; + } + } + if (bad) + mode->status = MODE_VSYNC; + + if (mode->next == modeList) + break; + } +} + +/** + * Marks as bad any modes extending beyond outside of the given clock ranges. + * + * \param modeList doubly-linked list of modes. + * \param min pointer to minimums of clock ranges + * \param max pointer to maximums of clock ranges + * \param n_ranges number of ranges. + */ +void +xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int *min, int *max, int n_ranges) +{ + DisplayModePtr mode; + int i; + + for (mode = modeList; mode != NULL; mode = mode->next) { + Bool good = FALSE; + for (i = 0; i < n_ranges; i++) { + if (mode->Clock >= min[i] * (1-SYNC_TOLERANCE) && + mode->Clock <= max[i] * (1+SYNC_TOLERANCE)) { + good = TRUE; + break; + } + } + if (!good) + mode->status = MODE_CLOCK_RANGE; + } +} + +/** + * If the user has specified a set of mode names to use, mark as bad any modes + * not listed. + * + * The user mode names specified are prefixes to names of modes, so "1024x768" + * will match modes named "1024x768", "1024x768x75", "1024x768-good", but + * "1024x768x75" would only match "1024x768x75" from that list. + * + * MODE_BAD is used as the rejection flag, for lack of a better flag. + * + * \param modeList doubly-linked list of modes. + */ +void +xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList) +{ + DisplayModePtr mode; + + if (pScrn->display->modes[0] == NULL) + return; + + for (mode = modeList; mode != NULL; mode = mode->next) { + int i; + Bool good = FALSE; + + for (i = 0; pScrn->display->modes[i] != NULL; i++) { + if (strncmp(pScrn->display->modes[i], mode->name, + strlen(pScrn->display->modes[i])) == 0) { + good = TRUE; + break; + } + } + if (!good) + mode->status = MODE_BAD; + } +} + + +/** + * Marks as bad any modes exceeding the given bandwidth. + * + * \param modeList doubly-linked list of modes. + * \param bandwidth bandwidth in MHz. + * \param depth color depth. + */ +void +xf86ValidateModesBandwidth(ScrnInfoPtr pScrn, DisplayModePtr modeList, + unsigned int bandwidth, int depth) +{ + DisplayModePtr mode; + + for (mode = modeList; mode != NULL; mode = mode->next) { + if (xf86ModeBandwidth(mode, depth) > bandwidth) +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + mode->status = MODE_BANDWIDTH; +#else + /* MODE_BANDWIDTH didn't exist in xserver 1.2 */ + mode->status = MODE_BAD; +#endif + } +} + +Bool +xf86ModeIsReduced(const DisplayModeRec *mode) +{ + if ((((mode->HDisplay * 5 / 4) & ~0x07) > mode->HTotal) && + ((mode->HTotal - mode->HDisplay) == 160) && + ((mode->HSyncEnd - mode->HDisplay) == 80) && + ((mode->HSyncEnd - mode->HSyncStart) == 32) && + ((mode->VSyncStart - mode->VDisplay) == 3)) + return TRUE; + return FALSE; +} + +/** + * Marks as bad any reduced-blanking modes. + * + * \param modeList doubly-linked list of modes. + */ +void +xf86ValidateModesReducedBlanking(ScrnInfoPtr pScrn, DisplayModePtr modeList) +{ + for (; modeList != NULL; modeList = modeList->next) + if (xf86ModeIsReduced(modeList)) + modeList->status = MODE_NO_REDUCED; +} + +/** + * Frees any modes from the list with a status other than MODE_OK. + * + * \param modeList pointer to a doubly-linked or circular list of modes. + * \param verbose determines whether the reason for mode invalidation is + * printed. + */ +void +xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, + Bool verbose) +{ + DisplayModePtr mode; + + for (mode = *modeList; mode != NULL;) { + DisplayModePtr next = mode->next, first = *modeList; + + if (mode->status != MODE_OK) { + if (verbose) { + char *type = ""; + if (mode->type & M_T_BUILTIN) + type = "built-in "; + else if (mode->type & M_T_DEFAULT) + type = "default "; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using %smode \"%s\" (%s)\n", type, mode->name, + xf86ModeStatusToString(mode->status)); + } + xf86DeleteMode(modeList, mode); + } + + if (next == first) + break; + mode = next; + } +} + +/** + * Adds the new mode into the mode list, and returns the new list + * + * \param modes doubly-linked mode list. + */ +DisplayModePtr +xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new) +{ + if (modes == NULL) + return new; + + if (new) { + DisplayModePtr mode = modes; + + while (mode->next) + mode = mode->next; + + mode->next = new; + new->prev = mode; + } + + return modes; +} + +/** + * Build a mode list from a list of config file modes + */ +static DisplayModePtr +xf86GetConfigModes (XF86ConfModeLinePtr conf_mode) +{ + DisplayModePtr head = NULL, prev = NULL, mode; + + for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next) + { + mode = calloc(1, sizeof(DisplayModeRec)); + if (!mode) + continue; + mode->name = xstrdup(conf_mode->ml_identifier); + if (!mode->name) + { + free(mode); + continue; + } + mode->type = 0; + mode->Clock = conf_mode->ml_clock; + mode->HDisplay = conf_mode->ml_hdisplay; + mode->HSyncStart = conf_mode->ml_hsyncstart; + mode->HSyncEnd = conf_mode->ml_hsyncend; + mode->HTotal = conf_mode->ml_htotal; + mode->VDisplay = conf_mode->ml_vdisplay; + mode->VSyncStart = conf_mode->ml_vsyncstart; + mode->VSyncEnd = conf_mode->ml_vsyncend; + mode->VTotal = conf_mode->ml_vtotal; + mode->Flags = conf_mode->ml_flags; + mode->HSkew = conf_mode->ml_hskew; + mode->VScan = conf_mode->ml_vscan; + + mode->prev = prev; + mode->next = NULL; + if (prev) + prev->next = mode; + else + head = mode; + prev = mode; + } + return head; +} + +/** + * Build a mode list from a monitor configuration + */ +DisplayModePtr +xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) +{ + DisplayModePtr modes = NULL; + XF86ConfModesLinkPtr modes_link; + + if (!conf_monitor) + return NULL; + + /* + * first we collect the mode lines from the UseModes directive + */ + for (modes_link = conf_monitor->mon_modes_sect_lst; + modes_link; + modes_link = modes_link->list.next) + { + /* If this modes link hasn't been resolved, go look it up now */ + if (!modes_link->ml_modes) + modes_link->ml_modes = xf86findModes (modes_link->ml_modes_str, + xf86configptr->conf_modes_lst); + if (modes_link->ml_modes) + modes = xf86ModesAdd (modes, + xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst)); + } + + return xf86ModesAdd (modes, + xf86GetConfigModes (conf_monitor->mon_modeline_lst)); +} + +/** + * Build a mode list containing all of the default modes + */ +DisplayModePtr +xf86GetDefaultModes (void) +{ + DisplayModePtr head = NULL, mode; + int i; + + for (i = 0; i < xf86NumDefaultModes; i++) + { + const DisplayModeRec *defMode = &xf86DefaultModes[i]; + + mode = xf86DuplicateMode(defMode); + head = xf86ModesAdd(head, mode); + } + return head; +} + +/* + * Walk a mode list and prune out duplicates. Will preserve the preferred + * mode of an otherwise-duplicate pair. + * + * Probably best to call this on lists that are all of a single class + * (driver, default, user, etc.), otherwise, which mode gets deleted is + * not especially well defined. + * + * Returns the new list. + */ + +DisplayModePtr +xf86PruneDuplicateModes(DisplayModePtr modes) +{ + DisplayModePtr m, n, o; + +top: + for (m = modes; m; m = m->next) { + for (n = m->next; n; n = o) { + o = n->next; + if (xf86ModesEqual(m, n)) { + if (n->type & M_T_PREFERRED) { + xf86DeleteMode(&modes, m); + goto top; + } + else + xf86DeleteMode(&modes, n); + } + } + } + + return modes; +} diff --git a/xorg-server/hw/xfree86/modes/xf86RandR12.c b/xorg-server/hw/xfree86/modes/xf86RandR12.c index 8898f4dad..8a4d72bd6 100644 --- a/xorg-server/hw/xfree86/modes/xf86RandR12.c +++ b/xorg-server/hw/xfree86/modes/xf86RandR12.c @@ -1,1810 +1,1810 @@ -/* - * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. - * - * 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#else -#ifdef HAVE_CONFIG_H -#include -#endif -#endif - -#include "xf86.h" -#include "os.h" -#include "globals.h" -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86DDC.h" -#include "mipointer.h" -#include "windowstr.h" -#include "inputstr.h" -#include -#include - -#include "xf86Crtc.h" -#include "xf86RandR12.h" - -typedef struct _xf86RandR12Info { - int virtualX; - int virtualY; - int mmWidth; - int mmHeight; - int maxX; - int maxY; - int pointerX; - int pointerY; - Rotation rotation; /* current mode */ - Rotation supported_rotations; /* driver supported */ - - /* Used to wrap EnterVT so we can re-probe the outputs when a laptop unsuspends - * (actually, any time that we switch back into our VT). - * - * See https://bugs.freedesktop.org/show_bug.cgi?id=21554 - */ - xf86EnterVTProc *orig_EnterVT; -} XF86RandRInfoRec, *XF86RandRInfoPtr; - -#ifdef RANDR_12_INTERFACE -static Bool xf86RandR12Init12 (ScreenPtr pScreen); -static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen); -#endif - -static int xf86RandR12Generation; -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - -static int xf86RandR12KeyIndex; -static DevPrivateKey xf86RandR12Key; -#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \ - dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key)) - -#else /* XORG_VERSION_CURRENT < 7.0 */ - -static int xf86RandR12Index; -#define XF86RANDRINFO(p) \ - ((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr) - -#endif /* XORG_VERSION_CURRENT < 7.0 */ - - -static int -xf86RandR12ModeRefresh (DisplayModePtr mode) -{ - if (mode->VRefresh) - return (int) (mode->VRefresh + 0.5); - else - return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); -} - -/* Adapt panning area; return TRUE if panning area was valid without adaption */ -static int -xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight) -{ - int ret = TRUE; - - if (crtc->version < 2) - return FALSE; - - if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) { - /* Panning in X is disabled */ - if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2) - /* Illegal configuration -> fail/disable */ - ret = FALSE; - crtc->panningTotalArea.x1 = crtc->panningTotalArea.x2 = 0; - crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0; - crtc->panningBorder[0] = crtc->panningBorder[2] = 0; - } else { - /* Panning in X is enabled */ - if (crtc->panningTotalArea.x1 < 0) { - /* Panning region outside screen -> move inside */ - crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1; - crtc->panningTotalArea.x1 = 0; - ret = FALSE; - } - if (crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay) { - /* Panning region smaller than displayed area -> crop to displayed area */ - crtc->panningTotalArea.x2 = crtc->panningTotalArea.x1 + crtc->mode.HDisplay; - ret = FALSE; - } - if (crtc->panningTotalArea.x2 > screenWidth) { - /* Panning region larger than screen -> move inside, then crop to screen */ - crtc->panningTotalArea.x1 -= crtc->panningTotalArea.x2 - screenWidth; - crtc->panningTotalArea.x2 = screenWidth; - ret = FALSE; - if (crtc->panningTotalArea.x1 < 0) - crtc->panningTotalArea.x1 = 0; - } - if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay) { - /* Borders too large -> set to 0 */ - crtc->panningBorder[0] = crtc->panningBorder[2] = 0; - ret = FALSE; - } - } - - if (crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) { - /* Panning in Y is disabled */ - if (crtc->panningTotalArea.y1 || crtc->panningTotalArea.y2) - /* Illegal configuration -> fail/disable */ - ret = FALSE; - crtc->panningTotalArea.y1 = crtc->panningTotalArea.y2 = 0; - crtc->panningTrackingArea.y1 = crtc->panningTrackingArea.y2 = 0; - crtc->panningBorder[1] = crtc->panningBorder[3] = 0; - } else { - /* Panning in Y is enabled */ - if (crtc->panningTotalArea.y1 < 0) { - /* Panning region outside screen -> move inside */ - crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1; - crtc->panningTotalArea.y1 = 0; - ret = FALSE; - } - if (crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay) { - /* Panning region smaller than displayed area -> crop to displayed area */ - crtc->panningTotalArea.y2 = crtc->panningTotalArea.y1 + crtc->mode.VDisplay; - ret = FALSE; - } - if (crtc->panningTotalArea.y2 > screenHeight) { - /* Panning region larger than screen -> move inside, then crop to screen */ - crtc->panningTotalArea.y1 -= crtc->panningTotalArea.y2 - screenHeight; - crtc->panningTotalArea.y2 = screenHeight; - ret = FALSE; - if (crtc->panningTotalArea.y1 < 0) - crtc->panningTotalArea.y1 = 0; - } - if (crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) { - /* Borders too large -> set to 0 */ - crtc->panningBorder[1] = crtc->panningBorder[3] = 0; - ret = FALSE; - } - } - - return ret; -} - -/* - * The heart of the panning operation: - * - * Given a frame buffer position (fb_x, fb_y), - * and a crtc position (crtc_x, crtc_y), - * and a transform matrix which maps frame buffer to crtc, - * compute a panning position (pan_x, pan_y) that - * makes the resulting transform line those two up - */ - -static void -xf86ComputeCrtcPan (Bool transform_in_use, - struct pixman_f_transform *m, - double screen_x, double screen_y, - double crtc_x, double crtc_y, - int old_pan_x, int old_pan_y, - int *new_pan_x, int *new_pan_y) -{ - if (transform_in_use) { - /* - * Given the current transform, M, the current position - * on the Screen, S, and the desired position on the CRTC, - * C, compute a translation, T, such that: - * - * M T S = C - * - * where T is of the form - * - * | 1 0 dx | - * | 0 1 dy | - * | 0 0 1 | - * - * M T S = - * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F | - * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F | - * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F | - * - * R = M S - * - * Cx F = M00 dx + M01 dy + R0 - * Cy F = M10 dx + M11 dy + R1 - * F = M20 dx + M21 dy + R2 - * - * Zero out dx, then dy - * - * F (Cx M10 - Cy M00) = - * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1 - * F (M10 - Cy M20) = - * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1 - * - * F (Cx M11 - Cy M01) = - * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1 - * F (M11 - Cy M21) = - * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1 - * - * Make some temporaries - * - * T = | Cx M10 - Cy M00 | - * | Cx M11 - Cy M01 | - * - * U = | M10 M01 - M00 M11 | - * | M11 M00 - M01 M10 | - * - * Q = | M10 R0 - M00 R1 | - * | M11 R0 - M01 R1 | - * - * P = | M10 - Cy M20 | - * | M11 - Cy M21 | - * - * W = | M10 M21 - M20 M11 | - * | M11 M20 - M21 M10 | - * - * V = | M10 R2 - M20 R1 | - * | M11 R2 - M21 R1 | - * - * Rewrite: - * - * F T0 = U0 dy + Q0 - * F P0 = W0 dy + V0 - * F T1 = U1 dx + Q1 - * F P1 = W1 dx + V1 - * - * Solve for F (two ways) - * - * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0 - * - * W0 Q0 - U0 V0 - * F = ------------- - * W0 T0 - U0 P0 - * - * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1 - * - * W1 Q1 - U1 V1 - * F = ------------- - * W1 T1 - U1 P1 - * - * We'll use which ever solution works (denominator != 0) - * - * Finally, solve for dx and dy: - * - * dx = (F T1 - Q1) / U1 - * dx = (F P1 - V1) / W1 - * - * dy = (F T0 - Q0) / U0 - * dy = (F P0 - V0) / W0 - */ - double r[3]; - double q[2], u[2], t[2], v[2], w[2], p[2]; - double f; - struct pict_f_vector d; - int i; - - /* Get the un-normalized crtc coordinates again */ - for (i = 0; i < 3; i++) - r[i] = m->m[i][0] * screen_x + m->m[i][1] * screen_y + m->m[i][2]; - - /* Combine values into temporaries */ - for (i = 0; i < 2; i++) { - q[i] = m->m[1][i] * r[0] - m->m[0][i] * r[1]; - u[i] = m->m[1][i] * m->m[0][1-i] - m->m[0][i] * m->m[1][1-i]; - t[i] = m->m[1][i] * crtc_x - m->m[0][i] * crtc_y; - - v[i] = m->m[1][i] * r[2] - m->m[2][i] * r[1]; - w[i] = m->m[1][i] * m->m[2][1-i] - m->m[2][i] * m->m[1][1-i]; - p[i] = m->m[1][i] - m->m[2][i] * crtc_y; - } - - /* Find a way to compute f */ - f = 0; - for (i = 0; i < 2; i++) { - double a = w[i] * q[i] - u[i] * v[i]; - double b = w[i] * t[i] - u[i] * p[i]; - if (b != 0) { - f = a/b; - break; - } - } - - /* Solve for the resulting transform vector */ - for (i = 0; i < 2; i++) { - if (u[i]) - d.v[1-i] = (t[i] * f - q[i]) / u[i]; - else if (w[1]) - d.v[1-i] = (p[i] * f - v[i]) / w[i]; - else - d.v[1-i] = 0; - } - *new_pan_x = old_pan_x - floor (d.v[0] + 0.5); - *new_pan_y = old_pan_y - floor (d.v[1] + 0.5); - } else { - *new_pan_x = screen_x - crtc_x; - *new_pan_y = screen_y - crtc_y; - } -} - -static void -xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) -{ - int newX, newY; - int width, height; - Bool panned = FALSE; - - if (crtc->version < 2) - return; - - if (! crtc->enabled || - (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1 && - crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1)) - return; - - newX = crtc->x; - newY = crtc->y; - width = crtc->mode.HDisplay; - height = crtc->mode.VDisplay; - - if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 || - (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2)) && - (crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 || - (y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2))) - { - struct pict_f_vector c; - - /* - * Pre-clip the mouse position to the panning area so that we don't - * push the crtc outside. This doesn't deal with changes to the - * panning values, only mouse position changes. - */ - if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) - { - if (x < crtc->panningTotalArea.x1) - x = crtc->panningTotalArea.x1; - if (x >= crtc->panningTotalArea.x2) - x = crtc->panningTotalArea.x2 - 1; - } - if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) - { - if (y < crtc->panningTotalArea.y1) - y = crtc->panningTotalArea.y1; - if (y >= crtc->panningTotalArea.y2) - y = crtc->panningTotalArea.y2 - 1; - } - - c.v[0] = x; - c.v[1] = y; - c.v[2] = 1.0; - if (crtc->transform_in_use) { - pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c); - } else { - c.v[0] -= crtc->x; - c.v[1] -= crtc->y; - } - - if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { - if (c.v[0] < crtc->panningBorder[0]) { - c.v[0] = crtc->panningBorder[0]; - panned = TRUE; - } - if (c.v[0] >= width - crtc->panningBorder[2]) { - c.v[0] = width - crtc->panningBorder[2] - 1; - panned = TRUE; - } - } - if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { - if (c.v[1] < crtc->panningBorder[1]) { - c.v[1] = crtc->panningBorder[1]; - panned = TRUE; - } - if (c.v[1] >= height - crtc->panningBorder[3]) { - c.v[1] = height - crtc->panningBorder[3] - 1; - panned = TRUE; - } - } - if (panned) - xf86ComputeCrtcPan (crtc->transform_in_use, - &crtc->f_framebuffer_to_crtc, - x, y, c.v[0], c.v[1], - newX, newY, &newX, &newY); - } - - /* - * Ensure that the crtc is within the panning region. - * - * XXX This computation only works when we do not have a transform - * in use. - */ - if (!crtc->transform_in_use) - { - /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */ - if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { - if (newX > crtc->panningTotalArea.x2 - width) - newX = crtc->panningTotalArea.x2 - width; - if (newX < crtc->panningTotalArea.x1) - newX = crtc->panningTotalArea.x1; - } - if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { - if (newY > crtc->panningTotalArea.y2 - height) - newY = crtc->panningTotalArea.y2 - height; - if (newY < crtc->panningTotalArea.y1) - newY = crtc->panningTotalArea.y1; - } - } - if (newX != crtc->x || newY != crtc->y) - xf86CrtcSetOrigin (crtc, newX, newY); -} - -static Bool -xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) -{ - RRScreenSizePtr pSize; - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - DisplayModePtr mode; - int refresh0 = 60; - int maxX = 0, maxY = 0; - - *rotations = randrp->supported_rotations; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = scrp->virtualX; - randrp->virtualY = scrp->virtualY; - } - - /* Re-probe the outputs for new monitors or modes */ - if (scrp->vtSema) - { - xf86ProbeOutputModes (scrp, 0, 0); - xf86SetScrnInfoModes (scrp); - } - - for (mode = scrp->modes; ; mode = mode->next) - { - int refresh = xf86RandR12ModeRefresh (mode); - if (randrp->maxX == 0 || randrp->maxY == 0) - { - if (maxX < mode->HDisplay) - maxX = mode->HDisplay; - if (maxY < mode->VDisplay) - maxY = mode->VDisplay; - } - if (mode == scrp->modes) - refresh0 = refresh; - pSize = RRRegisterSize (pScreen, - mode->HDisplay, mode->VDisplay, - randrp->mmWidth, randrp->mmHeight); - if (!pSize) - return FALSE; - RRRegisterRate (pScreen, pSize, refresh); - - if (xf86ModesEqual(mode, scrp->currentMode)) - { - RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); - } - if (mode->next == scrp->modes) - break; - } - - if (randrp->maxX == 0 || randrp->maxY == 0) - { - randrp->maxX = maxX; - randrp->maxY = maxY; - } - - return TRUE; -} - -static Bool -xf86RandR12SetMode (ScreenPtr pScreen, - DisplayModePtr mode, - Bool useVirtual, - int mmWidth, - int mmHeight) -{ - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - int oldWidth = pScreen->width; - int oldHeight = pScreen->height; - int oldmmWidth = pScreen->mmWidth; - int oldmmHeight = pScreen->mmHeight; - WindowPtr pRoot = WindowTable[pScreen->myNum]; - DisplayModePtr currentMode = NULL; - Bool ret = TRUE; - PixmapPtr pspix = NULL; - - if (pRoot) - (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); - if (useVirtual) - { - scrp->virtualX = randrp->virtualX; - scrp->virtualY = randrp->virtualY; - } - else - { - scrp->virtualX = mode->HDisplay; - scrp->virtualY = mode->VDisplay; - } - - if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) - { - /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ - pScreen->width = scrp->virtualY; - pScreen->height = scrp->virtualX; - pScreen->mmWidth = mmHeight; - pScreen->mmHeight = mmWidth; - } - else - { - pScreen->width = scrp->virtualX; - pScreen->height = scrp->virtualY; - pScreen->mmWidth = mmWidth; - pScreen->mmHeight = mmHeight; - } - if (scrp->currentMode == mode) { - /* Save current mode */ - currentMode = scrp->currentMode; - /* Reset, just so we ensure the drivers SwitchMode is called */ - scrp->currentMode = NULL; - } - /* - * We know that if the driver failed to SwitchMode to the rotated - * version, then it should revert back to it's prior mode. - */ - if (!xf86SwitchMode (pScreen, mode)) - { - ret = FALSE; - scrp->virtualX = pScreen->width = oldWidth; - scrp->virtualY = pScreen->height = oldHeight; - pScreen->mmWidth = oldmmWidth; - pScreen->mmHeight = oldmmHeight; - scrp->currentMode = currentMode; - } - /* - * Get the new Screen pixmap ptr as SwitchMode might have called - * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back... - * Unfortunately. - */ - pspix = (*pScreen->GetScreenPixmap) (pScreen); - if (pspix->devPrivate.ptr) - scrp->pixmapPrivate = pspix->devPrivate; - - /* - * Make sure the layout is correct - */ - xf86ReconfigureLayout(); - - /* - * Make sure the whole screen is visible - */ - xf86SetViewport (pScreen, pScreen->width, pScreen->height); - xf86SetViewport (pScreen, 0, 0); - if (pRoot) - (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); - return ret; -} - -Bool -xf86RandR12SetConfig (ScreenPtr pScreen, - Rotation rotation, - int rate, - RRScreenSizePtr pSize) -{ - ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - DisplayModePtr mode; - int px, py; - Bool useVirtual = FALSE; - int maxX = 0, maxY = 0; - Rotation oldRotation = randrp->rotation; - - randrp->rotation = rotation; - - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = scrp->virtualX; - randrp->virtualY = scrp->virtualY; - } - - miPointerGetPosition (inputInfo.pointer, &px, &py); - for (mode = scrp->modes; ; mode = mode->next) - { - if (randrp->maxX == 0 || randrp->maxY == 0) - { - if (maxX < mode->HDisplay) - maxX = mode->HDisplay; - if (maxY < mode->VDisplay) - maxY = mode->VDisplay; - } - if (mode->HDisplay == pSize->width && - mode->VDisplay == pSize->height && - (rate == 0 || xf86RandR12ModeRefresh (mode) == rate)) - break; - if (mode->next == scrp->modes) - { - if (pSize->width == randrp->virtualX && - pSize->height == randrp->virtualY) - { - mode = scrp->modes; - useVirtual = TRUE; - break; - } - if (randrp->maxX == 0 || randrp->maxY == 0) - { - randrp->maxX = maxX; - randrp->maxY = maxY; - } - return FALSE; - } - } - - if (randrp->maxX == 0 || randrp->maxY == 0) - { - randrp->maxX = maxX; - randrp->maxY = maxY; - } - - if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth, - pSize->mmHeight)) { - randrp->rotation = oldRotation; - return FALSE; - } - - /* - * Move the cursor back where it belongs; SwitchMode repositions it - */ - if (pScreen == miPointerGetScreen(inputInfo.pointer)) - { - px = (px >= pScreen->width ? (pScreen->width - 1) : px); - py = (py >= pScreen->height ? (pScreen->height - 1) : py); - - xf86SetViewport(pScreen, px, py); - - (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); - } - - return TRUE; -} - -static Bool -xf86RandR12ScreenSetSize (ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, - CARD32 mmHeight) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - WindowPtr pRoot = WindowTable[pScreen->myNum]; - PixmapPtr pScrnPix = (*pScreen->GetScreenPixmap)(pScreen); - Bool ret = FALSE; - int c; - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - if (xf86RandR12Key) { -#endif - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - } -#endif - if (pRoot && pScrn->vtSema) - (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); - - /* Let the driver update virtualX and virtualY */ - if (!(*config->funcs->resize)(pScrn, width, height)) - goto finish; - - ret = TRUE; - /* Update panning information */ - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; - if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 || - crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { - if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1) - crtc->panningTotalArea.x2 += width - pScreen->width; - if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1) - crtc->panningTotalArea.y2 += height - pScreen->height; - if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1) - crtc->panningTrackingArea.x2 += width - pScreen->width; - if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1) - crtc->panningTrackingArea.y2 += height - pScreen->height; - xf86RandR13VerifyPanningArea (crtc, width, height); - xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); - } - } - - pScreen->width = pScrnPix->drawable.width = width; - pScreen->height = pScrnPix->drawable.height = height; - randrp->mmWidth = pScreen->mmWidth = mmWidth; - randrp->mmHeight = pScreen->mmHeight = mmHeight; - - xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1); - xf86SetViewport (pScreen, 0, 0); - -finish: - if (pRoot && pScrn->vtSema) - (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); -#if RANDR_12_INTERFACE - if (xf86RandR12Key && WindowTable[pScreen->myNum] && ret) - RRScreenSizeNotify (pScreen); -#endif - return ret; -} - -Rotation -xf86RandR12GetRotation(ScreenPtr pScreen) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - - return randrp->rotation; -} - -Bool -xf86RandR12CreateScreenResources (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config; - XF86RandRInfoPtr randrp; - int c; - int width, height; - int mmWidth, mmHeight; -#ifdef PANORAMIX - /* XXX disable RandR when using Xinerama */ - if (!noPanoramiXExtension) - return TRUE; -#endif - - config = XF86_CRTC_CONFIG_PTR(pScrn); - randrp = XF86RANDRINFO(pScreen); - /* - * Compute size of screen - */ - width = 0; height = 0; - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation); - int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation); - - if (crtc->enabled) { - if (crtc_width > width) - width = crtc_width; - if (crtc_height > height) - height = crtc_height; - if (crtc->panningTotalArea.x2 > width) - width = crtc->panningTotalArea.x2; - if (crtc->panningTotalArea.y2 > height) - height = crtc->panningTotalArea.y2; - } - } - - if (width && height) - { - /* - * Compute physical size of screen - */ - if (monitorResolution) - { - mmWidth = width * 25.4 / monitorResolution; - mmHeight = height * 25.4 / monitorResolution; - } - else - { - xf86OutputPtr output = xf86CompatOutput(pScrn); - - if (output && - output->conf_monitor && - (output->conf_monitor->mon_width > 0 && - output->conf_monitor->mon_height > 0)) - { - /* - * Prefer user configured DisplaySize - */ - mmWidth = output->conf_monitor->mon_width; - mmHeight = output->conf_monitor->mon_height; - } - else - { - /* - * Otherwise, just set the screen to DEFAULT_DPI - */ - mmWidth = width * 25.4 / DEFAULT_DPI; - mmHeight = height * 25.4 / DEFAULT_DPI; - } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Setting screen physical size to %d x %d\n", - mmWidth, mmHeight); - /* - * This is the initial setting of the screen size. - * We have to pre-set it here, otherwise panning would be adapted - * to the new screen size. - */ - pScreen->width = width; - pScreen->height = height; - xf86RandR12ScreenSetSize (pScreen, - width, - height, - mmWidth, - mmHeight); - } - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - if (xf86RandR12Key == NULL) - return TRUE; -#endif - - if (randrp->virtualX == -1 || randrp->virtualY == -1) - { - randrp->virtualX = pScrn->virtualX; - randrp->virtualY = pScrn->virtualY; - } - xf86CrtcSetScreenSubpixelOrder (pScreen); -#if RANDR_12_INTERFACE - if (xf86RandR12CreateScreenResources12 (pScreen)) - return TRUE; -#endif - return TRUE; -} - - -Bool -xf86RandR12Init (ScreenPtr pScreen) -{ - rrScrPrivPtr rp; - XF86RandRInfoPtr randrp; - -#ifdef PANORAMIX - /* XXX disable RandR when using Xinerama */ - if (!noPanoramiXExtension) - { - if (xf86NumScreens == 1) - noPanoramiXExtension = TRUE; - else - return TRUE; - } -#endif - - if (xf86RandR12Generation != serverGeneration) - xf86RandR12Generation = serverGeneration; - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - xf86RandR12Key = &xf86RandR12KeyIndex; -#else - xf86RandR12Index = AllocateScreenPrivateIndex(); -#endif - - randrp = xalloc (sizeof (XF86RandRInfoRec)); - if (!randrp) - return FALSE; - - if (!RRScreenInit(pScreen)) - { - xfree (randrp); - return FALSE; - } - rp = rrGetScrPriv(pScreen); - rp->rrGetInfo = xf86RandR12GetInfo; - rp->rrSetConfig = xf86RandR12SetConfig; - - randrp->virtualX = -1; - randrp->virtualY = -1; - randrp->mmWidth = pScreen->mmWidth; - randrp->mmHeight = pScreen->mmHeight; - - randrp->rotation = RR_Rotate_0; /* initial rotated mode */ - - randrp->supported_rotations = RR_Rotate_0; - - randrp->maxX = randrp->maxY = 0; - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp); -#else - pScreen->devPrivates[xf86RandR12Index].ptr = randrp; -#endif - -#if RANDR_12_INTERFACE - if (!xf86RandR12Init12 (pScreen)) - return FALSE; -#endif - return TRUE; -} - -void -xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations) -{ - XF86RandRInfoPtr randrp; -#if RANDR_12_INTERFACE - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - int c; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); -#endif - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - if (xf86RandR12Key == NULL) - return; -#endif - - randrp = XF86RANDRINFO(pScreen); -#if RANDR_12_INTERFACE - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; - - RRCrtcSetRotations (crtc->randr_crtc, rotations); - } -#endif - randrp->supported_rotations = rotations; -} - -void -xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms) -{ - XF86RandRInfoPtr randrp; -#if RANDR_13_INTERFACE - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - int c; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); -#endif - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - if (xf86RandR12Key == NULL) - return; -#endif - - randrp = XF86RANDRINFO(pScreen); -#if RANDR_13_INTERFACE - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; - - RRCrtcSetTransformSupport (crtc->randr_crtc, transforms); - } -#endif -} - -void -xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) -{ - ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; - - if (xf86RandR12Generation != serverGeneration || - XF86RANDRINFO(pScreen)->virtualX == -1) - { - *x = pScrn->virtualX; - *y = pScrn->virtualY; - } else { - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - - *x = randrp->virtualX; - *y = randrp->virtualY; - } -} - -#if RANDR_12_INTERFACE - -#define FLAG_BITS (RR_HSyncPositive | \ - RR_HSyncNegative | \ - RR_VSyncPositive | \ - RR_VSyncNegative | \ - RR_Interlace | \ - RR_DoubleScan | \ - RR_CSync | \ - RR_CSyncPositive | \ - RR_CSyncNegative | \ - RR_HSkewPresent | \ - RR_BCast | \ - RR_PixelMultiplex | \ - RR_DoubleClock | \ - RR_ClockDivideBy2) - -static Bool -xf86RandRModeMatches (RRModePtr randr_mode, - DisplayModePtr mode) -{ -#if 0 - if (match_name) - { - /* check for same name */ - int len = strlen (mode->name); - if (randr_mode->mode.nameLength != len) return FALSE; - if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE; - } -#endif - - /* check for same timings */ - if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE; - if (randr_mode->mode.width != mode->HDisplay) return FALSE; - if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE; - if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE; - if (randr_mode->mode.hTotal != mode->HTotal) return FALSE; - if (randr_mode->mode.hSkew != mode->HSkew) return FALSE; - if (randr_mode->mode.height != mode->VDisplay) return FALSE; - if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE; - if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE; - if (randr_mode->mode.vTotal != mode->VTotal) return FALSE; - - /* check for same flags (using only the XF86 valid flag bits) */ - if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS)) - return FALSE; - - /* everything matches */ - return TRUE; -} - -static Bool -xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) -{ - ScreenPtr pScreen = randr_crtc->pScreen; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RRModePtr randr_mode = NULL; - int x; - int y; - Rotation rotation; - int numOutputs; - RROutputPtr *randr_outputs; - RROutputPtr randr_output; - xf86CrtcPtr crtc = randr_crtc->devPrivate; - xf86OutputPtr output; - int i, j; - DisplayModePtr mode = &crtc->mode; - Bool ret; - - randr_outputs = xalloc(config->num_output * sizeof (RROutputPtr)); - if (!randr_outputs) - return FALSE; - x = crtc->x; - y = crtc->y; - rotation = crtc->rotation; - numOutputs = 0; - randr_mode = NULL; - for (i = 0; i < config->num_output; i++) - { - output = config->output[i]; - if (output->crtc == crtc) - { - randr_output = output->randr_output; - randr_outputs[numOutputs++] = randr_output; - /* - * We make copies of modes, so pointer equality - * isn't sufficient - */ - for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++) - { - RRModePtr m = (j < randr_output->numModes ? - randr_output->modes[j] : - randr_output->userModes[j-randr_output->numModes]); - - if (xf86RandRModeMatches (m, mode)) - { - randr_mode = m; - break; - } - } - } - } - ret = RRCrtcNotify (randr_crtc, randr_mode, x, y, - rotation, - crtc->transformPresent ? &crtc->transform : NULL, - numOutputs, randr_outputs); - xfree(randr_outputs); - return ret; -} - -/* - * Convert a RandR mode to a DisplayMode - */ -static void -xf86RandRModeConvert (ScrnInfoPtr scrn, - RRModePtr randr_mode, - DisplayModePtr mode) -{ - memset(mode, 0, sizeof(DisplayModeRec)); - mode->status = MODE_OK; - - mode->Clock = randr_mode->mode.dotClock / 1000; - - mode->HDisplay = randr_mode->mode.width; - mode->HSyncStart = randr_mode->mode.hSyncStart; - mode->HSyncEnd = randr_mode->mode.hSyncEnd; - mode->HTotal = randr_mode->mode.hTotal; - mode->HSkew = randr_mode->mode.hSkew; - - mode->VDisplay = randr_mode->mode.height; - mode->VSyncStart = randr_mode->mode.vSyncStart; - mode->VSyncEnd = randr_mode->mode.vSyncEnd; - mode->VTotal = randr_mode->mode.vTotal; - mode->VScan = 0; - - mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS; - - xf86SetModeCrtc (mode, scrn->adjustFlags); -} - -static Bool -xf86RandR12CrtcSet (ScreenPtr pScreen, - RRCrtcPtr randr_crtc, - RRModePtr randr_mode, - int x, - int y, - Rotation rotation, - int num_randr_outputs, - RROutputPtr *randr_outputs) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc = randr_crtc->devPrivate; - RRTransformPtr transform; - Bool changed = FALSE; - int o, ro; - xf86CrtcPtr *save_crtcs; - Bool save_enabled = crtc->enabled; - - if (!crtc->scrn->vtSema) - return FALSE; - - save_crtcs = xalloc(config->num_output * sizeof (xf86CrtcPtr)); - if ((randr_mode != NULL) != crtc->enabled) - changed = TRUE; - else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode)) - changed = TRUE; - - if (rotation != crtc->rotation) - changed = TRUE; - - transform = RRCrtcGetTransform (randr_crtc); - if ((transform != NULL) != crtc->transformPresent) - changed = TRUE; - else if (transform && memcmp (&transform->transform, &crtc->transform.transform, - sizeof (transform->transform)) != 0) - changed = TRUE; - - if (x != crtc->x || y != crtc->y) - changed = TRUE; - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - xf86CrtcPtr new_crtc; - - save_crtcs[o] = output->crtc; - - if (output->crtc == crtc) - new_crtc = NULL; - else - new_crtc = output->crtc; - for (ro = 0; ro < num_randr_outputs; ro++) - if (output->randr_output == randr_outputs[ro]) - { - new_crtc = crtc; - break; - } - if (new_crtc != output->crtc) - { - changed = TRUE; - output->crtc = new_crtc; - } - } - for (ro = 0; ro < num_randr_outputs; ro++) - if (randr_outputs[ro]->pendingProperties) - changed = TRUE; - - /* XXX need device-independent mode setting code through an API */ - if (changed) - { - crtc->enabled = randr_mode != NULL; - - if (randr_mode) - { - DisplayModeRec mode; - RRTransformPtr transform = RRCrtcGetTransform (randr_crtc); - - xf86RandRModeConvert (pScrn, randr_mode, &mode); - if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y)) - { - crtc->enabled = save_enabled; - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - output->crtc = save_crtcs[o]; - } - xfree(save_crtcs); - return FALSE; - } - xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height); - xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); - /* - * Save the last successful setting for EnterVT - */ - crtc->desiredMode = mode; - crtc->desiredRotation = rotation; - if (transform) { - crtc->desiredTransform = *transform; - crtc->desiredTransformPresent = TRUE; - } else - crtc->desiredTransformPresent = FALSE; - - crtc->desiredX = x; - crtc->desiredY = y; - } - xf86DisableUnusedFunctions (pScrn); - } - xfree(save_crtcs); - return xf86RandR12CrtcNotify (randr_crtc); -} - -static Bool -xf86RandR12CrtcSetGamma (ScreenPtr pScreen, - RRCrtcPtr randr_crtc) -{ - xf86CrtcPtr crtc = randr_crtc->devPrivate; - - if (crtc->funcs->gamma_set == NULL) - return FALSE; - - if (!crtc->scrn->vtSema) - return TRUE; - - /* Realloc local gamma if needed. */ - if (randr_crtc->gammaSize != crtc->gamma_size) { - CARD16 *tmp_ptr; - tmp_ptr = realloc(crtc->gamma_red, 3 * crtc->gamma_size * sizeof (CARD16)); - if (!tmp_ptr) - return FALSE; - crtc->gamma_red = tmp_ptr; - crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; - crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; - } - - crtc->gamma_size = randr_crtc->gammaSize; - memcpy (crtc->gamma_red, randr_crtc->gammaRed, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_green, randr_crtc->gammaGreen, crtc->gamma_size * sizeof (CARD16)); - memcpy (crtc->gamma_blue, randr_crtc->gammaBlue, crtc->gamma_size * sizeof (CARD16)); - - /* Only set it when the crtc is actually running. - * Otherwise it will be set when it's activated. - */ - if (crtc->active) - crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); - - return TRUE; -} - -static Bool -xf86RandR12CrtcGetGamma (ScreenPtr pScreen, - RRCrtcPtr randr_crtc) -{ - xf86CrtcPtr crtc = randr_crtc->devPrivate; - - if (!crtc->gamma_size) - return FALSE; - - if (!crtc->gamma_red || !crtc->gamma_green || !crtc->gamma_blue) - return FALSE; - - /* Realloc randr gamma if needed. */ - if (randr_crtc->gammaSize != crtc->gamma_size) { - CARD16 *tmp_ptr; - tmp_ptr = realloc(randr_crtc->gammaRed, 3 * crtc->gamma_size * sizeof (CARD16)); - if (!tmp_ptr) - return FALSE; - randr_crtc->gammaRed = tmp_ptr; - randr_crtc->gammaGreen = randr_crtc->gammaRed + crtc->gamma_size; - randr_crtc->gammaBlue = randr_crtc->gammaGreen + crtc->gamma_size; - } - randr_crtc->gammaSize = crtc->gamma_size; - memcpy (randr_crtc->gammaRed, crtc->gamma_red, crtc->gamma_size * sizeof (CARD16)); - memcpy (randr_crtc->gammaGreen, crtc->gamma_green, crtc->gamma_size * sizeof (CARD16)); - memcpy (randr_crtc->gammaBlue, crtc->gamma_blue, crtc->gamma_size * sizeof (CARD16)); - - return TRUE; -} - -static Bool -xf86RandR12OutputSetProperty (ScreenPtr pScreen, - RROutputPtr randr_output, - Atom property, - RRPropertyValuePtr value) -{ - xf86OutputPtr output = randr_output->devPrivate; - - /* If we don't have any property handler, then we don't care what the - * user is setting properties to. - */ - if (output->funcs->set_property == NULL) - return TRUE; - - /* - * This function gets called even when vtSema is FALSE, as - * drivers will need to remember the correct value to apply - * when the VT switch occurs - */ - return output->funcs->set_property(output, property, value); -} - -static Bool -xf86RandR13OutputGetProperty (ScreenPtr pScreen, - RROutputPtr randr_output, - Atom property) -{ - xf86OutputPtr output = randr_output->devPrivate; - - if (output->funcs->get_property == NULL) - return TRUE; - - /* Should be safe even w/o vtSema */ - return output->funcs->get_property(output, property); -} - -static Bool -xf86RandR12OutputValidateMode (ScreenPtr pScreen, - RROutputPtr randr_output, - RRModePtr randr_mode) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86OutputPtr output = randr_output->devPrivate; - DisplayModeRec mode; - - xf86RandRModeConvert (pScrn, randr_mode, &mode); - /* - * This function may be called when vtSema is FALSE, so - * the underlying function must either avoid touching the hardware - * or return FALSE when vtSema is FALSE - */ - if (output->funcs->mode_valid (output, &mode) != MODE_OK) - return FALSE; - return TRUE; -} - -static void -xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode) -{ -} - -/** - * Given a list of xf86 modes and a RandR Output object, construct - * RandR modes and assign them to the output - */ -static Bool -xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) -{ - DisplayModePtr mode; - RRModePtr *rrmodes = NULL; - int nmode = 0; - int npreferred = 0; - Bool ret = TRUE; - int pref; - - for (mode = modes; mode; mode = mode->next) - nmode++; - - if (nmode) { - rrmodes = xalloc (nmode * sizeof (RRModePtr)); - - if (!rrmodes) - return FALSE; - nmode = 0; - - for (pref = 1; pref >= 0; pref--) { - for (mode = modes; mode; mode = mode->next) { - if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) { - xRRModeInfo modeInfo; - RRModePtr rrmode; - - modeInfo.nameLength = strlen (mode->name); - modeInfo.width = mode->HDisplay; - modeInfo.dotClock = mode->Clock * 1000; - modeInfo.hSyncStart = mode->HSyncStart; - modeInfo.hSyncEnd = mode->HSyncEnd; - modeInfo.hTotal = mode->HTotal; - modeInfo.hSkew = mode->HSkew; - - modeInfo.height = mode->VDisplay; - modeInfo.vSyncStart = mode->VSyncStart; - modeInfo.vSyncEnd = mode->VSyncEnd; - modeInfo.vTotal = mode->VTotal; - modeInfo.modeFlags = mode->Flags; - - rrmode = RRModeGet (&modeInfo, mode->name); - if (rrmode) { - rrmodes[nmode++] = rrmode; - npreferred += pref; - } - } - } - } - } - - ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred); - xfree (rrmodes); - return ret; -} - -/* - * Mirror the current mode configuration to RandR - */ -static Bool -xf86RandR12SetInfo12 (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RROutputPtr *clones; - RRCrtcPtr *crtcs; - int ncrtc; - int o, c, l; - RRCrtcPtr randr_crtc; - int nclone; - - clones = xalloc(config->num_output * sizeof (RROutputPtr)); - crtcs = xalloc (config->num_crtc * sizeof (RRCrtcPtr)); - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - ncrtc = 0; - for (c = 0; c < config->num_crtc; c++) - if (output->possible_crtcs & (1 << c)) - crtcs[ncrtc++] = config->crtc[c]->randr_crtc; - - if (output->crtc) - randr_crtc = output->crtc->randr_crtc; - else - randr_crtc = NULL; - - if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) - { - xfree (crtcs); - xfree (clones); - return FALSE; - } - - RROutputSetPhysicalSize(output->randr_output, - output->mm_width, - output->mm_height); - xf86RROutputSetModes (output->randr_output, output->probed_modes); - - switch (output->status) { - case XF86OutputStatusConnected: - RROutputSetConnection (output->randr_output, RR_Connected); - break; - case XF86OutputStatusDisconnected: - RROutputSetConnection (output->randr_output, RR_Disconnected); - break; - case XF86OutputStatusUnknown: - RROutputSetConnection (output->randr_output, RR_UnknownConnection); - break; - } - - RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order); - - /* - * Valid clones - */ - nclone = 0; - for (l = 0; l < config->num_output; l++) - { - xf86OutputPtr clone = config->output[l]; - - if (l != o && (output->possible_clones & (1 << l))) - clones[nclone++] = clone->randr_output; - } - if (!RROutputSetClones (output->randr_output, clones, nclone)) - { - xfree (crtcs); - xfree (clones); - return FALSE; - } - } - xfree (crtcs); - xfree (clones); - return TRUE; -} - - - -/* - * Query the hardware for the current state, then mirror - * that to RandR - */ -static Bool -xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (!pScrn->vtSema) - return TRUE; - xf86ProbeOutputModes (pScrn, 0, 0); - xf86SetScrnInfoModes (pScrn); - return xf86RandR12SetInfo12 (pScreen); -} - -static Bool -xf86RandR12CreateObjects12 (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - int c; - int o; - - if (!RRInit ()) - return FALSE; - - /* - * Configure crtcs - */ - for (c = 0; c < config->num_crtc; c++) - { - xf86CrtcPtr crtc = config->crtc[c]; - - crtc->randr_crtc = RRCrtcCreate (pScreen, crtc); - RRCrtcGammaSetSize (crtc->randr_crtc, 256); - } - /* - * Configure outputs - */ - for (o = 0; o < config->num_output; o++) - { - xf86OutputPtr output = config->output[o]; - - output->randr_output = RROutputCreate (pScreen, output->name, - strlen (output->name), - output); - - if (output->funcs->create_resources != NULL) - output->funcs->create_resources(output); - RRPostPendingProperties (output->randr_output); - } - return TRUE; -} - -static Bool -xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) -{ - int c; - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - if (xf86RandR12Key == NULL) - return TRUE; -#endif - - for (c = 0; c < config->num_crtc; c++) - xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); - - RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight, - config->maxWidth, config->maxHeight); - return TRUE; -} - -/* - * Something happened within the screen configuration due - * to DGA, VidMode or hot key. Tell RandR - */ - -void -xf86RandR12TellChanged (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - int c; - -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - if (xf86RandR12Key == NULL) - return; -#else - if (!XF86RANDRINFO(pScreen)) - return; -#endif - - xf86RandR12SetInfo12 (pScreen); - for (c = 0; c < config->num_crtc; c++) - xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); - - RRTellChanged (pScreen); -} - -static void -xf86RandR12PointerMoved (int scrnIndex, int x, int y) -{ - ScreenPtr pScreen = screenInfo.screens[scrnIndex]; - ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - int c; - - randrp->pointerX = x; - randrp->pointerY = y; - for (c = 0; c < config->num_crtc; c++) - xf86RandR13Pan (config->crtc[c], x, y); -} - -static Bool -xf86RandR13GetPanning (ScreenPtr pScreen, - RRCrtcPtr randr_crtc, - BoxPtr totalArea, - BoxPtr trackingArea, - INT16 *border) -{ - xf86CrtcPtr crtc = randr_crtc->devPrivate; - - if (crtc->version < 2) - return FALSE; - if (totalArea) - memcpy (totalArea, &crtc->panningTotalArea, sizeof(BoxRec)); - if (trackingArea) - memcpy (trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); - if (border) - memcpy (border, crtc->panningBorder, 4*sizeof(INT16)); - - return TRUE; -} - -static Bool -xf86RandR13SetPanning (ScreenPtr pScreen, - RRCrtcPtr randr_crtc, - BoxPtr totalArea, - BoxPtr trackingArea, - INT16 *border) -{ - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - xf86CrtcPtr crtc = randr_crtc->devPrivate; - BoxRec oldTotalArea; - BoxRec oldTrackingArea; - INT16 oldBorder[4]; - - - if (crtc->version < 2) - return FALSE; - - memcpy (&oldTotalArea, &crtc->panningTotalArea, sizeof(BoxRec)); - memcpy (&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); - memcpy (oldBorder, crtc->panningBorder, 4*sizeof(INT16)); - - if (totalArea) - memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec)); - if (trackingArea) - memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec)); - if (border) - memcpy (crtc->panningBorder, border, 4*sizeof(INT16)); - - if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) { - xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); - return TRUE; - } else { - /* Restore old settings */ - memcpy (&crtc->panningTotalArea, &oldTotalArea, sizeof(BoxRec)); - memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec)); - memcpy (crtc->panningBorder, oldBorder, 4*sizeof(INT16)); - return FALSE; - } -} - -/* - * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers - * any per-crtc setup. You asked for it... - */ - -static void -gamma_to_ramp(float gamma, CARD16 *ramp, int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (gamma == 1.0) - ramp[i] = i << 8; - else - ramp[i] = (CARD16)(pow((double)i / (double)(size - 1), 1. / gamma) - * (double)(size - 1) * 256); - } -} - -static int -xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma) -{ - CARD16 *points, *red, *green, *blue; - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); - int size; - - if (!crtc) - return Success; - - size = max(0, crtc->gammaSize); - if (!size) - return Success; - - points = xcalloc(size, 3 * sizeof(CARD16)); - if (!points) - return BadAlloc; - - red = points; - green = points + size; - blue = points + 2 * size; - - gamma_to_ramp(gamma.red, red, size); - gamma_to_ramp(gamma.green, green, size); - gamma_to_ramp(gamma.blue, blue, size); - RRCrtcGammaSet(crtc, red, green, blue); - - xfree(points); - - pScrn->gamma = gamma; - - return Success; -} - -static Bool -xf86RandR12EnterVT (int screen_index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[screen_index]; - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - - if (randrp->orig_EnterVT) { - if (!randrp->orig_EnterVT (screen_index, flags)) - return FALSE; - } - - return RRGetInfo (pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */ -} - -static Bool -xf86RandR12Init12 (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - rrScrPrivPtr rp = rrGetScrPriv(pScreen); - XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); - - rp->rrGetInfo = xf86RandR12GetInfo12; - rp->rrScreenSetSize = xf86RandR12ScreenSetSize; - rp->rrCrtcSet = xf86RandR12CrtcSet; - rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; - rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma; - rp->rrOutputSetProperty = xf86RandR12OutputSetProperty; - rp->rrOutputValidateMode = xf86RandR12OutputValidateMode; -#if RANDR_13_INTERFACE - rp->rrOutputGetProperty = xf86RandR13OutputGetProperty; - rp->rrGetPanning = xf86RandR13GetPanning; - rp->rrSetPanning = xf86RandR13SetPanning; -#endif - rp->rrModeDestroy = xf86RandR12ModeDestroy; - rp->rrSetConfig = NULL; - pScrn->PointerMoved = xf86RandR12PointerMoved; - pScrn->ChangeGamma = xf86RandR12ChangeGamma; - - randrp->orig_EnterVT = pScrn->EnterVT; - pScrn->EnterVT = xf86RandR12EnterVT; - - if (!xf86RandR12CreateObjects12 (pScreen)) - return FALSE; - - /* - * Configure output modes - */ - if (!xf86RandR12SetInfo12 (pScreen)) - return FALSE; - return TRUE; -} - -#endif - -Bool -xf86RandR12PreInit (ScrnInfoPtr pScrn) -{ - return TRUE; -} +/* + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. + * + * 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#else +#ifdef HAVE_CONFIG_H +#include +#endif +#endif + +#include "xf86.h" +#include "os.h" +#include "globals.h" +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86DDC.h" +#include "mipointer.h" +#include "windowstr.h" +#include "inputstr.h" +#include +#include + +#include "xf86Crtc.h" +#include "xf86RandR12.h" + +typedef struct _xf86RandR12Info { + int virtualX; + int virtualY; + int mmWidth; + int mmHeight; + int maxX; + int maxY; + int pointerX; + int pointerY; + Rotation rotation; /* current mode */ + Rotation supported_rotations; /* driver supported */ + + /* Used to wrap EnterVT so we can re-probe the outputs when a laptop unsuspends + * (actually, any time that we switch back into our VT). + * + * See https://bugs.freedesktop.org/show_bug.cgi?id=21554 + */ + xf86EnterVTProc *orig_EnterVT; +} XF86RandRInfoRec, *XF86RandRInfoPtr; + +#ifdef RANDR_12_INTERFACE +static Bool xf86RandR12Init12 (ScreenPtr pScreen); +static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen); +#endif + +static int xf86RandR12Generation; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + +static int xf86RandR12KeyIndex; +static DevPrivateKey xf86RandR12Key; +#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \ + dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key)) + +#else /* XORG_VERSION_CURRENT < 7.0 */ + +static int xf86RandR12Index; +#define XF86RANDRINFO(p) \ + ((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr) + +#endif /* XORG_VERSION_CURRENT < 7.0 */ + + +static int +xf86RandR12ModeRefresh (DisplayModePtr mode) +{ + if (mode->VRefresh) + return (int) (mode->VRefresh + 0.5); + else + return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); +} + +/* Adapt panning area; return TRUE if panning area was valid without adaption */ +static int +xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight) +{ + int ret = TRUE; + + if (crtc->version < 2) + return FALSE; + + if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) { + /* Panning in X is disabled */ + if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2) + /* Illegal configuration -> fail/disable */ + ret = FALSE; + crtc->panningTotalArea.x1 = crtc->panningTotalArea.x2 = 0; + crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0; + crtc->panningBorder[0] = crtc->panningBorder[2] = 0; + } else { + /* Panning in X is enabled */ + if (crtc->panningTotalArea.x1 < 0) { + /* Panning region outside screen -> move inside */ + crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1; + crtc->panningTotalArea.x1 = 0; + ret = FALSE; + } + if (crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay) { + /* Panning region smaller than displayed area -> crop to displayed area */ + crtc->panningTotalArea.x2 = crtc->panningTotalArea.x1 + crtc->mode.HDisplay; + ret = FALSE; + } + if (crtc->panningTotalArea.x2 > screenWidth) { + /* Panning region larger than screen -> move inside, then crop to screen */ + crtc->panningTotalArea.x1 -= crtc->panningTotalArea.x2 - screenWidth; + crtc->panningTotalArea.x2 = screenWidth; + ret = FALSE; + if (crtc->panningTotalArea.x1 < 0) + crtc->panningTotalArea.x1 = 0; + } + if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay) { + /* Borders too large -> set to 0 */ + crtc->panningBorder[0] = crtc->panningBorder[2] = 0; + ret = FALSE; + } + } + + if (crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) { + /* Panning in Y is disabled */ + if (crtc->panningTotalArea.y1 || crtc->panningTotalArea.y2) + /* Illegal configuration -> fail/disable */ + ret = FALSE; + crtc->panningTotalArea.y1 = crtc->panningTotalArea.y2 = 0; + crtc->panningTrackingArea.y1 = crtc->panningTrackingArea.y2 = 0; + crtc->panningBorder[1] = crtc->panningBorder[3] = 0; + } else { + /* Panning in Y is enabled */ + if (crtc->panningTotalArea.y1 < 0) { + /* Panning region outside screen -> move inside */ + crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1; + crtc->panningTotalArea.y1 = 0; + ret = FALSE; + } + if (crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay) { + /* Panning region smaller than displayed area -> crop to displayed area */ + crtc->panningTotalArea.y2 = crtc->panningTotalArea.y1 + crtc->mode.VDisplay; + ret = FALSE; + } + if (crtc->panningTotalArea.y2 > screenHeight) { + /* Panning region larger than screen -> move inside, then crop to screen */ + crtc->panningTotalArea.y1 -= crtc->panningTotalArea.y2 - screenHeight; + crtc->panningTotalArea.y2 = screenHeight; + ret = FALSE; + if (crtc->panningTotalArea.y1 < 0) + crtc->panningTotalArea.y1 = 0; + } + if (crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) { + /* Borders too large -> set to 0 */ + crtc->panningBorder[1] = crtc->panningBorder[3] = 0; + ret = FALSE; + } + } + + return ret; +} + +/* + * The heart of the panning operation: + * + * Given a frame buffer position (fb_x, fb_y), + * and a crtc position (crtc_x, crtc_y), + * and a transform matrix which maps frame buffer to crtc, + * compute a panning position (pan_x, pan_y) that + * makes the resulting transform line those two up + */ + +static void +xf86ComputeCrtcPan (Bool transform_in_use, + struct pixman_f_transform *m, + double screen_x, double screen_y, + double crtc_x, double crtc_y, + int old_pan_x, int old_pan_y, + int *new_pan_x, int *new_pan_y) +{ + if (transform_in_use) { + /* + * Given the current transform, M, the current position + * on the Screen, S, and the desired position on the CRTC, + * C, compute a translation, T, such that: + * + * M T S = C + * + * where T is of the form + * + * | 1 0 dx | + * | 0 1 dy | + * | 0 0 1 | + * + * M T S = + * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F | + * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F | + * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F | + * + * R = M S + * + * Cx F = M00 dx + M01 dy + R0 + * Cy F = M10 dx + M11 dy + R1 + * F = M20 dx + M21 dy + R2 + * + * Zero out dx, then dy + * + * F (Cx M10 - Cy M00) = + * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1 + * F (M10 - Cy M20) = + * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1 + * + * F (Cx M11 - Cy M01) = + * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1 + * F (M11 - Cy M21) = + * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1 + * + * Make some temporaries + * + * T = | Cx M10 - Cy M00 | + * | Cx M11 - Cy M01 | + * + * U = | M10 M01 - M00 M11 | + * | M11 M00 - M01 M10 | + * + * Q = | M10 R0 - M00 R1 | + * | M11 R0 - M01 R1 | + * + * P = | M10 - Cy M20 | + * | M11 - Cy M21 | + * + * W = | M10 M21 - M20 M11 | + * | M11 M20 - M21 M10 | + * + * V = | M10 R2 - M20 R1 | + * | M11 R2 - M21 R1 | + * + * Rewrite: + * + * F T0 = U0 dy + Q0 + * F P0 = W0 dy + V0 + * F T1 = U1 dx + Q1 + * F P1 = W1 dx + V1 + * + * Solve for F (two ways) + * + * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0 + * + * W0 Q0 - U0 V0 + * F = ------------- + * W0 T0 - U0 P0 + * + * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1 + * + * W1 Q1 - U1 V1 + * F = ------------- + * W1 T1 - U1 P1 + * + * We'll use which ever solution works (denominator != 0) + * + * Finally, solve for dx and dy: + * + * dx = (F T1 - Q1) / U1 + * dx = (F P1 - V1) / W1 + * + * dy = (F T0 - Q0) / U0 + * dy = (F P0 - V0) / W0 + */ + double r[3]; + double q[2], u[2], t[2], v[2], w[2], p[2]; + double f; + struct pict_f_vector d; + int i; + + /* Get the un-normalized crtc coordinates again */ + for (i = 0; i < 3; i++) + r[i] = m->m[i][0] * screen_x + m->m[i][1] * screen_y + m->m[i][2]; + + /* Combine values into temporaries */ + for (i = 0; i < 2; i++) { + q[i] = m->m[1][i] * r[0] - m->m[0][i] * r[1]; + u[i] = m->m[1][i] * m->m[0][1-i] - m->m[0][i] * m->m[1][1-i]; + t[i] = m->m[1][i] * crtc_x - m->m[0][i] * crtc_y; + + v[i] = m->m[1][i] * r[2] - m->m[2][i] * r[1]; + w[i] = m->m[1][i] * m->m[2][1-i] - m->m[2][i] * m->m[1][1-i]; + p[i] = m->m[1][i] - m->m[2][i] * crtc_y; + } + + /* Find a way to compute f */ + f = 0; + for (i = 0; i < 2; i++) { + double a = w[i] * q[i] - u[i] * v[i]; + double b = w[i] * t[i] - u[i] * p[i]; + if (b != 0) { + f = a/b; + break; + } + } + + /* Solve for the resulting transform vector */ + for (i = 0; i < 2; i++) { + if (u[i]) + d.v[1-i] = (t[i] * f - q[i]) / u[i]; + else if (w[1]) + d.v[1-i] = (p[i] * f - v[i]) / w[i]; + else + d.v[1-i] = 0; + } + *new_pan_x = old_pan_x - floor (d.v[0] + 0.5); + *new_pan_y = old_pan_y - floor (d.v[1] + 0.5); + } else { + *new_pan_x = screen_x - crtc_x; + *new_pan_y = screen_y - crtc_y; + } +} + +static void +xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) +{ + int newX, newY; + int width, height; + Bool panned = FALSE; + + if (crtc->version < 2) + return; + + if (! crtc->enabled || + (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1 && + crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1)) + return; + + newX = crtc->x; + newY = crtc->y; + width = crtc->mode.HDisplay; + height = crtc->mode.VDisplay; + + if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 || + (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2)) && + (crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 || + (y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2))) + { + struct pict_f_vector c; + + /* + * Pre-clip the mouse position to the panning area so that we don't + * push the crtc outside. This doesn't deal with changes to the + * panning values, only mouse position changes. + */ + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) + { + if (x < crtc->panningTotalArea.x1) + x = crtc->panningTotalArea.x1; + if (x >= crtc->panningTotalArea.x2) + x = crtc->panningTotalArea.x2 - 1; + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) + { + if (y < crtc->panningTotalArea.y1) + y = crtc->panningTotalArea.y1; + if (y >= crtc->panningTotalArea.y2) + y = crtc->panningTotalArea.y2 - 1; + } + + c.v[0] = x; + c.v[1] = y; + c.v[2] = 1.0; + if (crtc->transform_in_use) { + pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c); + } else { + c.v[0] -= crtc->x; + c.v[1] -= crtc->y; + } + + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { + if (c.v[0] < crtc->panningBorder[0]) { + c.v[0] = crtc->panningBorder[0]; + panned = TRUE; + } + if (c.v[0] >= width - crtc->panningBorder[2]) { + c.v[0] = width - crtc->panningBorder[2] - 1; + panned = TRUE; + } + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (c.v[1] < crtc->panningBorder[1]) { + c.v[1] = crtc->panningBorder[1]; + panned = TRUE; + } + if (c.v[1] >= height - crtc->panningBorder[3]) { + c.v[1] = height - crtc->panningBorder[3] - 1; + panned = TRUE; + } + } + if (panned) + xf86ComputeCrtcPan (crtc->transform_in_use, + &crtc->f_framebuffer_to_crtc, + x, y, c.v[0], c.v[1], + newX, newY, &newX, &newY); + } + + /* + * Ensure that the crtc is within the panning region. + * + * XXX This computation only works when we do not have a transform + * in use. + */ + if (!crtc->transform_in_use) + { + /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */ + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { + if (newX > crtc->panningTotalArea.x2 - width) + newX = crtc->panningTotalArea.x2 - width; + if (newX < crtc->panningTotalArea.x1) + newX = crtc->panningTotalArea.x1; + } + if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (newY > crtc->panningTotalArea.y2 - height) + newY = crtc->panningTotalArea.y2 - height; + if (newY < crtc->panningTotalArea.y1) + newY = crtc->panningTotalArea.y1; + } + } + if (newX != crtc->x || newY != crtc->y) + xf86CrtcSetOrigin (crtc, newX, newY); +} + +static Bool +xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + RRScreenSizePtr pSize; + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int refresh0 = 60; + int maxX = 0, maxY = 0; + + *rotations = randrp->supported_rotations; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + } + + /* Re-probe the outputs for new monitors or modes */ + if (scrp->vtSema) + { + xf86ProbeOutputModes (scrp, 0, 0); + xf86SetScrnInfoModes (scrp); + } + + for (mode = scrp->modes; ; mode = mode->next) + { + int refresh = xf86RandR12ModeRefresh (mode); + if (randrp->maxX == 0 || randrp->maxY == 0) + { + if (maxX < mode->HDisplay) + maxX = mode->HDisplay; + if (maxY < mode->VDisplay) + maxY = mode->VDisplay; + } + if (mode == scrp->modes) + refresh0 = refresh; + pSize = RRRegisterSize (pScreen, + mode->HDisplay, mode->VDisplay, + randrp->mmWidth, randrp->mmHeight); + if (!pSize) + return FALSE; + RRRegisterRate (pScreen, pSize, refresh); + + if (xf86ModesEqual(mode, scrp->currentMode)) + { + RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); + } + if (mode->next == scrp->modes) + break; + } + + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + + return TRUE; +} + +static Bool +xf86RandR12SetMode (ScreenPtr pScreen, + DisplayModePtr mode, + Bool useVirtual, + int mmWidth, + int mmHeight) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int oldWidth = pScreen->width; + int oldHeight = pScreen->height; + int oldmmWidth = pScreen->mmWidth; + int oldmmHeight = pScreen->mmHeight; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + DisplayModePtr currentMode = NULL; + Bool ret = TRUE; + PixmapPtr pspix = NULL; + + if (pRoot) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); + if (useVirtual) + { + scrp->virtualX = randrp->virtualX; + scrp->virtualY = randrp->virtualY; + } + else + { + scrp->virtualX = mode->HDisplay; + scrp->virtualY = mode->VDisplay; + } + + if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) + { + /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ + pScreen->width = scrp->virtualY; + pScreen->height = scrp->virtualX; + pScreen->mmWidth = mmHeight; + pScreen->mmHeight = mmWidth; + } + else + { + pScreen->width = scrp->virtualX; + pScreen->height = scrp->virtualY; + pScreen->mmWidth = mmWidth; + pScreen->mmHeight = mmHeight; + } + if (scrp->currentMode == mode) { + /* Save current mode */ + currentMode = scrp->currentMode; + /* Reset, just so we ensure the drivers SwitchMode is called */ + scrp->currentMode = NULL; + } + /* + * We know that if the driver failed to SwitchMode to the rotated + * version, then it should revert back to it's prior mode. + */ + if (!xf86SwitchMode (pScreen, mode)) + { + ret = FALSE; + scrp->virtualX = pScreen->width = oldWidth; + scrp->virtualY = pScreen->height = oldHeight; + pScreen->mmWidth = oldmmWidth; + pScreen->mmHeight = oldmmHeight; + scrp->currentMode = currentMode; + } + /* + * Get the new Screen pixmap ptr as SwitchMode might have called + * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back... + * Unfortunately. + */ + pspix = (*pScreen->GetScreenPixmap) (pScreen); + if (pspix->devPrivate.ptr) + scrp->pixmapPrivate = pspix->devPrivate; + + /* + * Make sure the layout is correct + */ + xf86ReconfigureLayout(); + + /* + * Make sure the whole screen is visible + */ + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); + return ret; +} + +Bool +xf86RandR12SetConfig (ScreenPtr pScreen, + Rotation rotation, + int rate, + RRScreenSizePtr pSize) +{ + ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + DisplayModePtr mode; + int px, py; + Bool useVirtual = FALSE; + int maxX = 0, maxY = 0; + Rotation oldRotation = randrp->rotation; + + randrp->rotation = rotation; + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = scrp->virtualX; + randrp->virtualY = scrp->virtualY; + } + + miPointerGetPosition (inputInfo.pointer, &px, &py); + for (mode = scrp->modes; ; mode = mode->next) + { + if (randrp->maxX == 0 || randrp->maxY == 0) + { + if (maxX < mode->HDisplay) + maxX = mode->HDisplay; + if (maxY < mode->VDisplay) + maxY = mode->VDisplay; + } + if (mode->HDisplay == pSize->width && + mode->VDisplay == pSize->height && + (rate == 0 || xf86RandR12ModeRefresh (mode) == rate)) + break; + if (mode->next == scrp->modes) + { + if (pSize->width == randrp->virtualX && + pSize->height == randrp->virtualY) + { + mode = scrp->modes; + useVirtual = TRUE; + break; + } + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + return FALSE; + } + } + + if (randrp->maxX == 0 || randrp->maxY == 0) + { + randrp->maxX = maxX; + randrp->maxY = maxY; + } + + if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth, + pSize->mmHeight)) { + randrp->rotation = oldRotation; + return FALSE; + } + + /* + * Move the cursor back where it belongs; SwitchMode repositions it + */ + if (pScreen == miPointerGetScreen(inputInfo.pointer)) + { + px = (px >= pScreen->width ? (pScreen->width - 1) : px); + py = (py >= pScreen->height ? (pScreen->height - 1) : py); + + xf86SetViewport(pScreen, px, py); + + (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); + } + + return TRUE; +} + +static Bool +xf86RandR12ScreenSetSize (ScreenPtr pScreen, + CARD16 width, + CARD16 height, + CARD32 mmWidth, + CARD32 mmHeight) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + WindowPtr pRoot = WindowTable[pScreen->myNum]; + PixmapPtr pScrnPix = (*pScreen->GetScreenPixmap)(pScreen); + Bool ret = FALSE; + int c; + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + if (xf86RandR12Key) { +#endif + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + } +#endif + if (pRoot && pScrn->vtSema) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); + + /* Let the driver update virtualX and virtualY */ + if (!(*config->funcs->resize)(pScrn, width, height)) + goto finish; + + ret = TRUE; + /* Update panning information */ + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 || + crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { + if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1) + crtc->panningTotalArea.x2 += width - pScreen->width; + if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1) + crtc->panningTotalArea.y2 += height - pScreen->height; + if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1) + crtc->panningTrackingArea.x2 += width - pScreen->width; + if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1) + crtc->panningTrackingArea.y2 += height - pScreen->height; + xf86RandR13VerifyPanningArea (crtc, width, height); + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); + } + } + + pScreen->width = pScrnPix->drawable.width = width; + pScreen->height = pScrnPix->drawable.height = height; + randrp->mmWidth = pScreen->mmWidth = mmWidth; + randrp->mmHeight = pScreen->mmHeight = mmHeight; + + xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1); + xf86SetViewport (pScreen, 0, 0); + +finish: + if (pRoot && pScrn->vtSema) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); +#if RANDR_12_INTERFACE + if (xf86RandR12Key && WindowTable[pScreen->myNum] && ret) + RRScreenSizeNotify (pScreen); +#endif + return ret; +} + +Rotation +xf86RandR12GetRotation(ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + return randrp->rotation; +} + +Bool +xf86RandR12CreateScreenResources (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config; + XF86RandRInfoPtr randrp; + int c; + int width, height; + int mmWidth, mmHeight; +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif + + config = XF86_CRTC_CONFIG_PTR(pScrn); + randrp = XF86RANDRINFO(pScreen); + /* + * Compute size of screen + */ + width = 0; height = 0; + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation); + int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation); + + if (crtc->enabled) { + if (crtc_width > width) + width = crtc_width; + if (crtc_height > height) + height = crtc_height; + if (crtc->panningTotalArea.x2 > width) + width = crtc->panningTotalArea.x2; + if (crtc->panningTotalArea.y2 > height) + height = crtc->panningTotalArea.y2; + } + } + + if (width && height) + { + /* + * Compute physical size of screen + */ + if (monitorResolution) + { + mmWidth = width * 25.4 / monitorResolution; + mmHeight = height * 25.4 / monitorResolution; + } + else + { + xf86OutputPtr output = xf86CompatOutput(pScrn); + + if (output && + output->conf_monitor && + (output->conf_monitor->mon_width > 0 && + output->conf_monitor->mon_height > 0)) + { + /* + * Prefer user configured DisplaySize + */ + mmWidth = output->conf_monitor->mon_width; + mmHeight = output->conf_monitor->mon_height; + } + else + { + /* + * Otherwise, just set the screen to DEFAULT_DPI + */ + mmWidth = width * 25.4 / DEFAULT_DPI; + mmHeight = height * 25.4 / DEFAULT_DPI; + } + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Setting screen physical size to %d x %d\n", + mmWidth, mmHeight); + /* + * This is the initial setting of the screen size. + * We have to pre-set it here, otherwise panning would be adapted + * to the new screen size. + */ + pScreen->width = width; + pScreen->height = height; + xf86RandR12ScreenSetSize (pScreen, + width, + height, + mmWidth, + mmHeight); + } + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + if (xf86RandR12Key == NULL) + return TRUE; +#endif + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + xf86CrtcSetScreenSubpixelOrder (pScreen); +#if RANDR_12_INTERFACE + if (xf86RandR12CreateScreenResources12 (pScreen)) + return TRUE; +#endif + return TRUE; +} + + +Bool +xf86RandR12Init (ScreenPtr pScreen) +{ + rrScrPrivPtr rp; + XF86RandRInfoPtr randrp; + +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + { + if (xf86NumScreens == 1) + noPanoramiXExtension = TRUE; + else + return TRUE; + } +#endif + + if (xf86RandR12Generation != serverGeneration) + xf86RandR12Generation = serverGeneration; + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + xf86RandR12Key = &xf86RandR12KeyIndex; +#else + xf86RandR12Index = AllocateScreenPrivateIndex(); +#endif + + randrp = malloc(sizeof (XF86RandRInfoRec)); + if (!randrp) + return FALSE; + + if (!RRScreenInit(pScreen)) + { + free(randrp); + return FALSE; + } + rp = rrGetScrPriv(pScreen); + rp->rrGetInfo = xf86RandR12GetInfo; + rp->rrSetConfig = xf86RandR12SetConfig; + + randrp->virtualX = -1; + randrp->virtualY = -1; + randrp->mmWidth = pScreen->mmWidth; + randrp->mmHeight = pScreen->mmHeight; + + randrp->rotation = RR_Rotate_0; /* initial rotated mode */ + + randrp->supported_rotations = RR_Rotate_0; + + randrp->maxX = randrp->maxY = 0; + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp); +#else + pScreen->devPrivates[xf86RandR12Index].ptr = randrp; +#endif + +#if RANDR_12_INTERFACE + if (!xf86RandR12Init12 (pScreen)) + return FALSE; +#endif + return TRUE; +} + +void +xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations) +{ + XF86RandRInfoPtr randrp; +#if RANDR_12_INTERFACE + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int c; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); +#endif + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + if (xf86RandR12Key == NULL) + return; +#endif + + randrp = XF86RANDRINFO(pScreen); +#if RANDR_12_INTERFACE + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + RRCrtcSetRotations (crtc->randr_crtc, rotations); + } +#endif + randrp->supported_rotations = rotations; +} + +void +xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms) +{ + XF86RandRInfoPtr randrp; +#if RANDR_13_INTERFACE + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int c; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); +#endif + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + if (xf86RandR12Key == NULL) + return; +#endif + + randrp = XF86RANDRINFO(pScreen); +#if RANDR_13_INTERFACE + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + RRCrtcSetTransformSupport (crtc->randr_crtc, transforms); + } +#endif +} + +void +xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) +{ + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + + if (xf86RandR12Generation != serverGeneration || + XF86RANDRINFO(pScreen)->virtualX == -1) + { + *x = pScrn->virtualX; + *y = pScrn->virtualY; + } else { + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + *x = randrp->virtualX; + *y = randrp->virtualY; + } +} + +#if RANDR_12_INTERFACE + +#define FLAG_BITS (RR_HSyncPositive | \ + RR_HSyncNegative | \ + RR_VSyncPositive | \ + RR_VSyncNegative | \ + RR_Interlace | \ + RR_DoubleScan | \ + RR_CSync | \ + RR_CSyncPositive | \ + RR_CSyncNegative | \ + RR_HSkewPresent | \ + RR_BCast | \ + RR_PixelMultiplex | \ + RR_DoubleClock | \ + RR_ClockDivideBy2) + +static Bool +xf86RandRModeMatches (RRModePtr randr_mode, + DisplayModePtr mode) +{ +#if 0 + if (match_name) + { + /* check for same name */ + int len = strlen (mode->name); + if (randr_mode->mode.nameLength != len) return FALSE; + if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE; + } +#endif + + /* check for same timings */ + if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE; + if (randr_mode->mode.width != mode->HDisplay) return FALSE; + if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE; + if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE; + if (randr_mode->mode.hTotal != mode->HTotal) return FALSE; + if (randr_mode->mode.hSkew != mode->HSkew) return FALSE; + if (randr_mode->mode.height != mode->VDisplay) return FALSE; + if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE; + if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE; + if (randr_mode->mode.vTotal != mode->VTotal) return FALSE; + + /* check for same flags (using only the XF86 valid flag bits) */ + if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS)) + return FALSE; + + /* everything matches */ + return TRUE; +} + +static Bool +xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) +{ + ScreenPtr pScreen = randr_crtc->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + RRModePtr randr_mode = NULL; + int x; + int y; + Rotation rotation; + int numOutputs; + RROutputPtr *randr_outputs; + RROutputPtr randr_output; + xf86CrtcPtr crtc = randr_crtc->devPrivate; + xf86OutputPtr output; + int i, j; + DisplayModePtr mode = &crtc->mode; + Bool ret; + + randr_outputs = malloc(config->num_output * sizeof (RROutputPtr)); + if (!randr_outputs) + return FALSE; + x = crtc->x; + y = crtc->y; + rotation = crtc->rotation; + numOutputs = 0; + randr_mode = NULL; + for (i = 0; i < config->num_output; i++) + { + output = config->output[i]; + if (output->crtc == crtc) + { + randr_output = output->randr_output; + randr_outputs[numOutputs++] = randr_output; + /* + * We make copies of modes, so pointer equality + * isn't sufficient + */ + for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++) + { + RRModePtr m = (j < randr_output->numModes ? + randr_output->modes[j] : + randr_output->userModes[j-randr_output->numModes]); + + if (xf86RandRModeMatches (m, mode)) + { + randr_mode = m; + break; + } + } + } + } + ret = RRCrtcNotify (randr_crtc, randr_mode, x, y, + rotation, + crtc->transformPresent ? &crtc->transform : NULL, + numOutputs, randr_outputs); + free(randr_outputs); + return ret; +} + +/* + * Convert a RandR mode to a DisplayMode + */ +static void +xf86RandRModeConvert (ScrnInfoPtr scrn, + RRModePtr randr_mode, + DisplayModePtr mode) +{ + memset(mode, 0, sizeof(DisplayModeRec)); + mode->status = MODE_OK; + + mode->Clock = randr_mode->mode.dotClock / 1000; + + mode->HDisplay = randr_mode->mode.width; + mode->HSyncStart = randr_mode->mode.hSyncStart; + mode->HSyncEnd = randr_mode->mode.hSyncEnd; + mode->HTotal = randr_mode->mode.hTotal; + mode->HSkew = randr_mode->mode.hSkew; + + mode->VDisplay = randr_mode->mode.height; + mode->VSyncStart = randr_mode->mode.vSyncStart; + mode->VSyncEnd = randr_mode->mode.vSyncEnd; + mode->VTotal = randr_mode->mode.vTotal; + mode->VScan = 0; + + mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS; + + xf86SetModeCrtc (mode, scrn->adjustFlags); +} + +static Bool +xf86RandR12CrtcSet (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + RRModePtr randr_mode, + int x, + int y, + Rotation rotation, + int num_randr_outputs, + RROutputPtr *randr_outputs) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc = randr_crtc->devPrivate; + RRTransformPtr transform; + Bool changed = FALSE; + int o, ro; + xf86CrtcPtr *save_crtcs; + Bool save_enabled = crtc->enabled; + + if (!crtc->scrn->vtSema) + return FALSE; + + save_crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr)); + if ((randr_mode != NULL) != crtc->enabled) + changed = TRUE; + else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode)) + changed = TRUE; + + if (rotation != crtc->rotation) + changed = TRUE; + + transform = RRCrtcGetTransform (randr_crtc); + if ((transform != NULL) != crtc->transformPresent) + changed = TRUE; + else if (transform && memcmp (&transform->transform, &crtc->transform.transform, + sizeof (transform->transform)) != 0) + changed = TRUE; + + if (x != crtc->x || y != crtc->y) + changed = TRUE; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + xf86CrtcPtr new_crtc; + + save_crtcs[o] = output->crtc; + + if (output->crtc == crtc) + new_crtc = NULL; + else + new_crtc = output->crtc; + for (ro = 0; ro < num_randr_outputs; ro++) + if (output->randr_output == randr_outputs[ro]) + { + new_crtc = crtc; + break; + } + if (new_crtc != output->crtc) + { + changed = TRUE; + output->crtc = new_crtc; + } + } + for (ro = 0; ro < num_randr_outputs; ro++) + if (randr_outputs[ro]->pendingProperties) + changed = TRUE; + + /* XXX need device-independent mode setting code through an API */ + if (changed) + { + crtc->enabled = randr_mode != NULL; + + if (randr_mode) + { + DisplayModeRec mode; + RRTransformPtr transform = RRCrtcGetTransform (randr_crtc); + + xf86RandRModeConvert (pScrn, randr_mode, &mode); + if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y)) + { + crtc->enabled = save_enabled; + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + output->crtc = save_crtcs[o]; + } + free(save_crtcs); + return FALSE; + } + xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height); + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); + /* + * Save the last successful setting for EnterVT + */ + crtc->desiredMode = mode; + crtc->desiredRotation = rotation; + if (transform) { + crtc->desiredTransform = *transform; + crtc->desiredTransformPresent = TRUE; + } else + crtc->desiredTransformPresent = FALSE; + + crtc->desiredX = x; + crtc->desiredY = y; + } + xf86DisableUnusedFunctions (pScrn); + } + free(save_crtcs); + return xf86RandR12CrtcNotify (randr_crtc); +} + +static Bool +xf86RandR12CrtcSetGamma (ScreenPtr pScreen, + RRCrtcPtr randr_crtc) +{ + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (crtc->funcs->gamma_set == NULL) + return FALSE; + + if (!crtc->scrn->vtSema) + return TRUE; + + /* Realloc local gamma if needed. */ + if (randr_crtc->gammaSize != crtc->gamma_size) { + CARD16 *tmp_ptr; + tmp_ptr = realloc(crtc->gamma_red, 3 * crtc->gamma_size * sizeof (CARD16)); + if (!tmp_ptr) + return FALSE; + crtc->gamma_red = tmp_ptr; + crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; + crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; + } + + crtc->gamma_size = randr_crtc->gammaSize; + memcpy (crtc->gamma_red, randr_crtc->gammaRed, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_green, randr_crtc->gammaGreen, crtc->gamma_size * sizeof (CARD16)); + memcpy (crtc->gamma_blue, randr_crtc->gammaBlue, crtc->gamma_size * sizeof (CARD16)); + + /* Only set it when the crtc is actually running. + * Otherwise it will be set when it's activated. + */ + if (crtc->active) + crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, + crtc->gamma_blue, crtc->gamma_size); + + return TRUE; +} + +static Bool +xf86RandR12CrtcGetGamma (ScreenPtr pScreen, + RRCrtcPtr randr_crtc) +{ + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (!crtc->gamma_size) + return FALSE; + + if (!crtc->gamma_red || !crtc->gamma_green || !crtc->gamma_blue) + return FALSE; + + /* Realloc randr gamma if needed. */ + if (randr_crtc->gammaSize != crtc->gamma_size) { + CARD16 *tmp_ptr; + tmp_ptr = realloc(randr_crtc->gammaRed, 3 * crtc->gamma_size * sizeof (CARD16)); + if (!tmp_ptr) + return FALSE; + randr_crtc->gammaRed = tmp_ptr; + randr_crtc->gammaGreen = randr_crtc->gammaRed + crtc->gamma_size; + randr_crtc->gammaBlue = randr_crtc->gammaGreen + crtc->gamma_size; + } + randr_crtc->gammaSize = crtc->gamma_size; + memcpy (randr_crtc->gammaRed, crtc->gamma_red, crtc->gamma_size * sizeof (CARD16)); + memcpy (randr_crtc->gammaGreen, crtc->gamma_green, crtc->gamma_size * sizeof (CARD16)); + memcpy (randr_crtc->gammaBlue, crtc->gamma_blue, crtc->gamma_size * sizeof (CARD16)); + + return TRUE; +} + +static Bool +xf86RandR12OutputSetProperty (ScreenPtr pScreen, + RROutputPtr randr_output, + Atom property, + RRPropertyValuePtr value) +{ + xf86OutputPtr output = randr_output->devPrivate; + + /* If we don't have any property handler, then we don't care what the + * user is setting properties to. + */ + if (output->funcs->set_property == NULL) + return TRUE; + + /* + * This function gets called even when vtSema is FALSE, as + * drivers will need to remember the correct value to apply + * when the VT switch occurs + */ + return output->funcs->set_property(output, property, value); +} + +static Bool +xf86RandR13OutputGetProperty (ScreenPtr pScreen, + RROutputPtr randr_output, + Atom property) +{ + xf86OutputPtr output = randr_output->devPrivate; + + if (output->funcs->get_property == NULL) + return TRUE; + + /* Should be safe even w/o vtSema */ + return output->funcs->get_property(output, property); +} + +static Bool +xf86RandR12OutputValidateMode (ScreenPtr pScreen, + RROutputPtr randr_output, + RRModePtr randr_mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86OutputPtr output = randr_output->devPrivate; + DisplayModeRec mode; + + xf86RandRModeConvert (pScrn, randr_mode, &mode); + /* + * This function may be called when vtSema is FALSE, so + * the underlying function must either avoid touching the hardware + * or return FALSE when vtSema is FALSE + */ + if (output->funcs->mode_valid (output, &mode) != MODE_OK) + return FALSE; + return TRUE; +} + +static void +xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode) +{ +} + +/** + * Given a list of xf86 modes and a RandR Output object, construct + * RandR modes and assign them to the output + */ +static Bool +xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) +{ + DisplayModePtr mode; + RRModePtr *rrmodes = NULL; + int nmode = 0; + int npreferred = 0; + Bool ret = TRUE; + int pref; + + for (mode = modes; mode; mode = mode->next) + nmode++; + + if (nmode) { + rrmodes = malloc(nmode * sizeof (RRModePtr)); + + if (!rrmodes) + return FALSE; + nmode = 0; + + for (pref = 1; pref >= 0; pref--) { + for (mode = modes; mode; mode = mode->next) { + if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) { + xRRModeInfo modeInfo; + RRModePtr rrmode; + + modeInfo.nameLength = strlen (mode->name); + modeInfo.width = mode->HDisplay; + modeInfo.dotClock = mode->Clock * 1000; + modeInfo.hSyncStart = mode->HSyncStart; + modeInfo.hSyncEnd = mode->HSyncEnd; + modeInfo.hTotal = mode->HTotal; + modeInfo.hSkew = mode->HSkew; + + modeInfo.height = mode->VDisplay; + modeInfo.vSyncStart = mode->VSyncStart; + modeInfo.vSyncEnd = mode->VSyncEnd; + modeInfo.vTotal = mode->VTotal; + modeInfo.modeFlags = mode->Flags; + + rrmode = RRModeGet (&modeInfo, mode->name); + if (rrmode) { + rrmodes[nmode++] = rrmode; + npreferred += pref; + } + } + } + } + } + + ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred); + free(rrmodes); + return ret; +} + +/* + * Mirror the current mode configuration to RandR + */ +static Bool +xf86RandR12SetInfo12 (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + RROutputPtr *clones; + RRCrtcPtr *crtcs; + int ncrtc; + int o, c, l; + RRCrtcPtr randr_crtc; + int nclone; + + clones = malloc(config->num_output * sizeof (RROutputPtr)); + crtcs = malloc(config->num_crtc * sizeof (RRCrtcPtr)); + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + ncrtc = 0; + for (c = 0; c < config->num_crtc; c++) + if (output->possible_crtcs & (1 << c)) + crtcs[ncrtc++] = config->crtc[c]->randr_crtc; + + if (output->crtc) + randr_crtc = output->crtc->randr_crtc; + else + randr_crtc = NULL; + + if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) + { + free(crtcs); + free(clones); + return FALSE; + } + + RROutputSetPhysicalSize(output->randr_output, + output->mm_width, + output->mm_height); + xf86RROutputSetModes (output->randr_output, output->probed_modes); + + switch (output->status) { + case XF86OutputStatusConnected: + RROutputSetConnection (output->randr_output, RR_Connected); + break; + case XF86OutputStatusDisconnected: + RROutputSetConnection (output->randr_output, RR_Disconnected); + break; + case XF86OutputStatusUnknown: + RROutputSetConnection (output->randr_output, RR_UnknownConnection); + break; + } + + RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order); + + /* + * Valid clones + */ + nclone = 0; + for (l = 0; l < config->num_output; l++) + { + xf86OutputPtr clone = config->output[l]; + + if (l != o && (output->possible_clones & (1 << l))) + clones[nclone++] = clone->randr_output; + } + if (!RROutputSetClones (output->randr_output, clones, nclone)) + { + free(crtcs); + free(clones); + return FALSE; + } + } + free(crtcs); + free(clones); + return TRUE; +} + + + +/* + * Query the hardware for the current state, then mirror + * that to RandR + */ +static Bool +xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (!pScrn->vtSema) + return TRUE; + xf86ProbeOutputModes (pScrn, 0, 0); + xf86SetScrnInfoModes (pScrn); + return xf86RandR12SetInfo12 (pScreen); +} + +static Bool +xf86RandR12CreateObjects12 (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + int o; + + if (!RRInit ()) + return FALSE; + + /* + * Configure crtcs + */ + for (c = 0; c < config->num_crtc; c++) + { + xf86CrtcPtr crtc = config->crtc[c]; + + crtc->randr_crtc = RRCrtcCreate (pScreen, crtc); + RRCrtcGammaSetSize (crtc->randr_crtc, 256); + } + /* + * Configure outputs + */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + output->randr_output = RROutputCreate (pScreen, output->name, + strlen (output->name), + output); + + if (output->funcs->create_resources != NULL) + output->funcs->create_resources(output); + RRPostPendingProperties (output->randr_output); + } + return TRUE; +} + +static Bool +xf86RandR12CreateScreenResources12 (ScreenPtr pScreen) +{ + int c; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + if (xf86RandR12Key == NULL) + return TRUE; +#endif + + for (c = 0; c < config->num_crtc; c++) + xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); + + RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight, + config->maxWidth, config->maxHeight); + return TRUE; +} + +/* + * Something happened within the screen configuration due + * to DGA, VidMode or hot key. Tell RandR + */ + +void +xf86RandR12TellChanged (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + if (xf86RandR12Key == NULL) + return; +#else + if (!XF86RANDRINFO(pScreen)) + return; +#endif + + xf86RandR12SetInfo12 (pScreen); + for (c = 0; c < config->num_crtc; c++) + xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); + + RRTellChanged (pScreen); +} + +static void +xf86RandR12PointerMoved (int scrnIndex, int x, int y) +{ + ScreenPtr pScreen = screenInfo.screens[scrnIndex]; + ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + int c; + + randrp->pointerX = x; + randrp->pointerY = y; + for (c = 0; c < config->num_crtc; c++) + xf86RandR13Pan (config->crtc[c], x, y); +} + +static Bool +xf86RandR13GetPanning (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border) +{ + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + if (crtc->version < 2) + return FALSE; + if (totalArea) + memcpy (totalArea, &crtc->panningTotalArea, sizeof(BoxRec)); + if (trackingArea) + memcpy (trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); + if (border) + memcpy (border, crtc->panningBorder, 4*sizeof(INT16)); + + return TRUE; +} + +static Bool +xf86RandR13SetPanning (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + BoxPtr totalArea, + BoxPtr trackingArea, + INT16 *border) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + xf86CrtcPtr crtc = randr_crtc->devPrivate; + BoxRec oldTotalArea; + BoxRec oldTrackingArea; + INT16 oldBorder[4]; + + + if (crtc->version < 2) + return FALSE; + + memcpy (&oldTotalArea, &crtc->panningTotalArea, sizeof(BoxRec)); + memcpy (&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); + memcpy (oldBorder, crtc->panningBorder, 4*sizeof(INT16)); + + if (totalArea) + memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec)); + if (trackingArea) + memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec)); + if (border) + memcpy (crtc->panningBorder, border, 4*sizeof(INT16)); + + if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) { + xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); + return TRUE; + } else { + /* Restore old settings */ + memcpy (&crtc->panningTotalArea, &oldTotalArea, sizeof(BoxRec)); + memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec)); + memcpy (crtc->panningBorder, oldBorder, 4*sizeof(INT16)); + return FALSE; + } +} + +/* + * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers + * any per-crtc setup. You asked for it... + */ + +static void +gamma_to_ramp(float gamma, CARD16 *ramp, int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (gamma == 1.0) + ramp[i] = i << 8; + else + ramp[i] = (CARD16)(pow((double)i / (double)(size - 1), 1. / gamma) + * (double)(size - 1) * 256); + } +} + +static int +xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma) +{ + CARD16 *points, *red, *green, *blue; + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); + int size; + + if (!crtc) + return Success; + + size = max(0, crtc->gammaSize); + if (!size) + return Success; + + points = calloc(size, 3 * sizeof(CARD16)); + if (!points) + return BadAlloc; + + red = points; + green = points + size; + blue = points + 2 * size; + + gamma_to_ramp(gamma.red, red, size); + gamma_to_ramp(gamma.green, green, size); + gamma_to_ramp(gamma.blue, blue, size); + RRCrtcGammaSet(crtc, red, green, blue); + + free(points); + + pScrn->gamma = gamma; + + return Success; +} + +static Bool +xf86RandR12EnterVT (int screen_index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[screen_index]; + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + if (randrp->orig_EnterVT) { + if (!randrp->orig_EnterVT (screen_index, flags)) + return FALSE; + } + + return RRGetInfo (pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */ +} + +static Bool +xf86RandR12Init12 (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + rrScrPrivPtr rp = rrGetScrPriv(pScreen); + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + + rp->rrGetInfo = xf86RandR12GetInfo12; + rp->rrScreenSetSize = xf86RandR12ScreenSetSize; + rp->rrCrtcSet = xf86RandR12CrtcSet; + rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; + rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma; + rp->rrOutputSetProperty = xf86RandR12OutputSetProperty; + rp->rrOutputValidateMode = xf86RandR12OutputValidateMode; +#if RANDR_13_INTERFACE + rp->rrOutputGetProperty = xf86RandR13OutputGetProperty; + rp->rrGetPanning = xf86RandR13GetPanning; + rp->rrSetPanning = xf86RandR13SetPanning; +#endif + rp->rrModeDestroy = xf86RandR12ModeDestroy; + rp->rrSetConfig = NULL; + pScrn->PointerMoved = xf86RandR12PointerMoved; + pScrn->ChangeGamma = xf86RandR12ChangeGamma; + + randrp->orig_EnterVT = pScrn->EnterVT; + pScrn->EnterVT = xf86RandR12EnterVT; + + if (!xf86RandR12CreateObjects12 (pScreen)) + return FALSE; + + /* + * Configure output modes + */ + if (!xf86RandR12SetInfo12 (pScreen)) + return FALSE; + return TRUE; +} + +#endif + +Bool +xf86RandR12PreInit (ScrnInfoPtr pScrn) +{ + return TRUE; +} diff --git a/xorg-server/hw/xfree86/modes/xf86Rotate.c b/xorg-server/hw/xfree86/modes/xf86Rotate.c index 5de6b0c00..e15c61476 100644 --- a/xorg-server/hw/xfree86/modes/xf86Rotate.c +++ b/xorg-server/hw/xfree86/modes/xf86Rotate.c @@ -1,527 +1,527 @@ -/* - * Copyright © 2006 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 the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS 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. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#else -#ifdef HAVE_CONFIG_H -#include -#endif -#endif - -#include -#include -#include - -#include "xf86.h" -#include "xf86DDC.h" -#include "fb.h" -#include "windowstr.h" -#include "xf86Crtc.h" -#include "xf86Modes.h" -#include "xf86RandR12.h" -#include "X11/extensions/render.h" -#include "X11/extensions/dpmsconst.h" -#include "X11/Xatom.h" - -/* borrowed from composite extension, move to Render and publish? */ - -static VisualPtr -compGetWindowVisual (WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - VisualID vid = wVisual (pWin); - int i; - - for (i = 0; i < pScreen->numVisuals; i++) - if (pScreen->visuals[i].vid == vid) - return &pScreen->visuals[i]; - return 0; -} - -static PictFormatPtr -compWindowFormat (WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - - return PictureMatchVisual (pScreen, pWin->drawable.depth, - compGetWindowVisual (pWin)); -} - -#define F(x) IntToxFixed(x) - -#define toF(x) ((float) (x) / 65536.0f) - -static void -xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) -{ - ScrnInfoPtr scrn = crtc->scrn; - ScreenPtr screen = scrn->pScreen; - WindowPtr root = WindowTable[screen->myNum]; - PixmapPtr dst_pixmap = crtc->rotatedPixmap; - PictFormatPtr format = compWindowFormat (WindowTable[screen->myNum]); - int error; - PicturePtr src, dst; - int n = REGION_NUM_RECTS(region); - BoxPtr b = REGION_RECTS(region); - XID include_inferiors = IncludeInferiors; - - src = CreatePicture (None, - &root->drawable, - format, - CPSubwindowMode, - &include_inferiors, - serverClient, - &error); - if (!src) - return; - - dst = CreatePicture (None, - &dst_pixmap->drawable, - format, - 0L, - NULL, - serverClient, - &error); - if (!dst) - return; - - error = SetPictureTransform (src, &crtc->crtc_to_framebuffer); - if (error) - return; - if (crtc->transform_in_use && crtc->filter) - SetPicturePictFilter (src, crtc->filter, - crtc->params, crtc->nparams); - - if (crtc->shadowClear) - { - CompositePicture (PictOpSrc, - src, NULL, dst, - 0, 0, 0, 0, 0, 0, - crtc->mode.HDisplay, crtc->mode.VDisplay); - crtc->shadowClear = FALSE; - } - else - { - while (n--) - { - BoxRec dst_box; - - dst_box = *b; - dst_box.x1 -= crtc->filter_width >> 1; - dst_box.x2 += crtc->filter_width >> 1; - dst_box.y1 -= crtc->filter_height >> 1; - dst_box.y2 += crtc->filter_height >> 1; - pixman_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box); - CompositePicture (PictOpSrc, - src, NULL, dst, - dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1, - dst_box.x2 - dst_box.x1, - dst_box.y2 - dst_box.y1); - b++; - } - } - FreePicture (src, None); - FreePicture (dst, None); -} - -static void -xf86CrtcDamageShadow (xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - BoxRec damage_box; - RegionRec damage_region; - ScreenPtr pScreen = pScrn->pScreen; - - damage_box.x1 = 0; - damage_box.x2 = crtc->mode.HDisplay; - damage_box.y1 = 0; - damage_box.y2 = crtc->mode.VDisplay; - if (!pixman_transform_bounds (&crtc->crtc_to_framebuffer, &damage_box)) - { - damage_box.x1 = 0; - damage_box.y1 = 0; - damage_box.x2 = pScreen->width; - damage_box.y2 = pScreen->height; - } - if (damage_box.x1 < 0) damage_box.x1 = 0; - if (damage_box.y1 < 0) damage_box.y1 = 0; - if (damage_box.x2 > pScreen->width) damage_box.x2 = pScreen->width; - if (damage_box.y2 > pScreen->height) damage_box.y2 = pScreen->height; - REGION_INIT (pScreen, &damage_region, &damage_box, 1); - DamageRegionAppend (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, - &damage_region); - REGION_UNINIT (pScreen, &damage_region); - crtc->shadowClear = TRUE; -} - -static void -xf86RotatePrepare (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int c; - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - if (crtc->rotatedData && !crtc->rotatedPixmap) - { - crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc, - crtc->rotatedData, - crtc->mode.HDisplay, - crtc->mode.VDisplay); - if (!xf86_config->rotation_damage_registered) - { - /* Hook damage to screen pixmap */ - DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, - xf86_config->rotation_damage); - xf86_config->rotation_damage_registered = TRUE; - EnableLimitedSchedulingLatency(); - } - - xf86CrtcDamageShadow (crtc); - } - } -} - -static Bool -xf86RotateRedisplay(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - DamagePtr damage = xf86_config->rotation_damage; - RegionPtr region; - - if (!damage) - return FALSE; - xf86RotatePrepare (pScreen); - region = DamageRegion(damage); - if (REGION_NOTEMPTY(pScreen, region)) - { - int c; - SourceValidateProcPtr SourceValidate; - - /* - * SourceValidate is used by the software cursor code - * to pull the cursor off of the screen when reading - * bits from the frame buffer. Bypassing this function - * leaves the software cursor in place - */ - SourceValidate = pScreen->SourceValidate; - pScreen->SourceValidate = NULL; - - for (c = 0; c < xf86_config->num_crtc; c++) - { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - - if (crtc->transform_in_use && crtc->enabled) - { - RegionRec crtc_damage; - - /* compute portion of damage that overlaps crtc */ - REGION_INIT(pScreen, &crtc_damage, &crtc->bounds, 1); - REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region); - - /* update damaged region */ - if (REGION_NOTEMPTY(pScreen, &crtc_damage)) - xf86RotateCrtcRedisplay (crtc, &crtc_damage); - - REGION_UNINIT (pScreen, &crtc_damage); - } - } - pScreen->SourceValidate = SourceValidate; - DamageEmpty(damage); - } - return TRUE; -} - -static void -xf86RotateBlockHandler(int screenNum, pointer blockData, - pointer pTimeout, pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[screenNum]; - ScrnInfoPtr pScrn = xf86Screens[screenNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - Bool rotation_active; - - rotation_active = xf86RotateRedisplay(pScreen); - pScreen->BlockHandler = xf86_config->BlockHandler; - (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); - /* cannot avoid re-wrapping until all wrapping is audited */ - xf86_config->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = xf86RotateBlockHandler; -} - -void -xf86RotateDestroy (xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - ScreenPtr pScreen = pScrn->pScreen; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int c; - - /* Free memory from rotation */ - if (crtc->rotatedPixmap || crtc->rotatedData) - { - crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData); - crtc->rotatedPixmap = NULL; - crtc->rotatedData = NULL; - } - - for (c = 0; c < xf86_config->num_crtc; c++) - if (xf86_config->crtc[c]->transform_in_use) - return; - - /* - * Clean up damage structures when no crtcs are rotated - */ - if (xf86_config->rotation_damage) - { - /* Free damage structure */ - if (xf86_config->rotation_damage_registered) - { - DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, - xf86_config->rotation_damage); - xf86_config->rotation_damage_registered = FALSE; - DisableLimitedSchedulingLatency(); - } - DamageDestroy (xf86_config->rotation_damage); - xf86_config->rotation_damage = NULL; - } -} - -void -xf86RotateFreeShadow(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - int c; - - for (c = 0; c < config->num_crtc; c++) { - xf86CrtcPtr crtc = config->crtc[c]; - - if (crtc->rotatedPixmap || crtc->rotatedData) { - crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap, - crtc->rotatedData); - crtc->rotatedPixmap = NULL; - crtc->rotatedData = NULL; - } - } -} - -void -xf86RotateCloseScreen (ScreenPtr screen) -{ - ScrnInfoPtr scrn = xf86Screens[screen->myNum]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - int c; - - for (c = 0; c < xf86_config->num_crtc; c++) - xf86RotateDestroy (xf86_config->crtc[c]); -} - -static Bool -xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb) -{ - ScrnInfoPtr pScrn = crtc->scrn; - BoxRec b; - - /* When called before PreInit, the driver is - * presumably doing load detect - */ - if (pScrn->virtualX == 0 || pScrn->virtualY == 0) - return TRUE; - - b.x1 = 0; - b.y1 = 0; - b.x2 = crtc->mode.HDisplay; - b.y2 = crtc->mode.VDisplay; - if (crtc_to_fb) - pixman_f_transform_bounds (crtc_to_fb, &b); - else { - b.x1 += crtc->x; - b.y1 += crtc->y; - b.x2 += crtc->x; - b.y2 += crtc->y; - } - - return (0 <= b.x1 && b.x2 <= pScrn->virtualX && - 0 <= b.y1 && b.y2 <= pScrn->virtualY); -} - -Bool -xf86CrtcRotate (xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ - ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; - PictTransform crtc_to_fb; - struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc; - xFixed *new_params = NULL; - int new_nparams = 0; - PictFilterPtr new_filter = NULL; - int new_width = 0; - int new_height = 0; - RRTransformPtr transform = NULL; - Bool damage = FALSE; - - if (crtc->transformPresent) - transform = &crtc->transform; - - if (!RRTransformCompute (crtc->x, crtc->y, - crtc->mode.HDisplay, crtc->mode.VDisplay, - crtc->rotation, - transform, - - &crtc_to_fb, - &f_crtc_to_fb, - &f_fb_to_crtc) && - xf86CrtcFitsScreen (crtc, &f_crtc_to_fb)) - { - /* - * If the untranslated transformation is the identity, - * disable the shadow buffer - */ - xf86RotateDestroy (crtc); - crtc->transform_in_use = FALSE; - if (new_params) - xfree (new_params); - new_params = NULL; - new_nparams = 0; - new_filter = NULL; - new_width = 0; - new_height = 0; - } - else - { - /* - * these are the size of the shadow pixmap, which - * matches the mode, not the pre-rotated copy in the - * frame buffer - */ - int width = crtc->mode.HDisplay; - int height = crtc->mode.VDisplay; - void *shadowData = crtc->rotatedData; - PixmapPtr shadow = crtc->rotatedPixmap; - int old_width = shadow ? shadow->drawable.width : 0; - int old_height = shadow ? shadow->drawable.height : 0; - - /* Allocate memory for rotation */ - if (old_width != width || old_height != height) - { - if (shadow || shadowData) - { - crtc->funcs->shadow_destroy (crtc, shadow, shadowData); - crtc->rotatedPixmap = NULL; - crtc->rotatedData = NULL; - } - shadowData = crtc->funcs->shadow_allocate (crtc, width, height); - if (!shadowData) - goto bail1; - crtc->rotatedData = shadowData; - /* shadow will be damaged in xf86RotatePrepare */ - } - else - { - /* mark shadowed area as damaged so it will be repainted */ - damage = TRUE; - } - - if (!xf86_config->rotation_damage) - { - /* Create damage structure */ - xf86_config->rotation_damage = DamageCreate (NULL, NULL, - DamageReportNone, - TRUE, pScreen, pScreen); - if (!xf86_config->rotation_damage) - goto bail2; - - /* Wrap block handler */ - if (!xf86_config->BlockHandler) { - xf86_config->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = xf86RotateBlockHandler; - } - } -#ifdef RANDR_12_INTERFACE - if (transform) - { - if (transform->nparams) { - new_params = xalloc (transform->nparams * sizeof (xFixed)); - if (new_params) { - memcpy (new_params, transform->params, - transform->nparams * sizeof (xFixed)); - new_nparams = transform->nparams; - new_filter = transform->filter; - } - } else - new_filter = transform->filter; - if (new_filter) - { - new_width = new_filter->width; - new_height = new_filter->height; - } - } -#endif - - if (0) - { - bail2: - if (shadow || shadowData) - { - crtc->funcs->shadow_destroy (crtc, shadow, shadowData); - crtc->rotatedPixmap = NULL; - crtc->rotatedData = NULL; - } - bail1: - if (old_width && old_height) - crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc, - NULL, - old_width, - old_height); - return FALSE; - } - crtc->transform_in_use = TRUE; - } - crtc->crtc_to_framebuffer = crtc_to_fb; - crtc->f_crtc_to_framebuffer = f_crtc_to_fb; - crtc->f_framebuffer_to_crtc = f_fb_to_crtc; - if (crtc->params) - xfree (crtc->params); - crtc->params = new_params; - crtc->nparams = new_nparams; - crtc->filter = new_filter; - crtc->filter_width = new_width; - crtc->filter_height = new_height; - crtc->bounds.x1 = 0; - crtc->bounds.x2 = crtc->mode.HDisplay; - crtc->bounds.y1 = 0; - crtc->bounds.y2 = crtc->mode.VDisplay; - pixman_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds); - - if (damage) - xf86CrtcDamageShadow (crtc); - - /* All done */ - return TRUE; -} +/* + * Copyright © 2006 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 the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#else +#ifdef HAVE_CONFIG_H +#include +#endif +#endif + +#include +#include +#include + +#include "xf86.h" +#include "xf86DDC.h" +#include "fb.h" +#include "windowstr.h" +#include "xf86Crtc.h" +#include "xf86Modes.h" +#include "xf86RandR12.h" +#include "X11/extensions/render.h" +#include "X11/extensions/dpmsconst.h" +#include "X11/Xatom.h" + +/* borrowed from composite extension, move to Render and publish? */ + +static VisualPtr +compGetWindowVisual (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + VisualID vid = wVisual (pWin); + int i; + + for (i = 0; i < pScreen->numVisuals; i++) + if (pScreen->visuals[i].vid == vid) + return &pScreen->visuals[i]; + return 0; +} + +static PictFormatPtr +compWindowFormat (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + return PictureMatchVisual (pScreen, pWin->drawable.depth, + compGetWindowVisual (pWin)); +} + +#define F(x) IntToxFixed(x) + +#define toF(x) ((float) (x) / 65536.0f) + +static void +xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) +{ + ScrnInfoPtr scrn = crtc->scrn; + ScreenPtr screen = scrn->pScreen; + WindowPtr root = WindowTable[screen->myNum]; + PixmapPtr dst_pixmap = crtc->rotatedPixmap; + PictFormatPtr format = compWindowFormat (WindowTable[screen->myNum]); + int error; + PicturePtr src, dst; + int n = REGION_NUM_RECTS(region); + BoxPtr b = REGION_RECTS(region); + XID include_inferiors = IncludeInferiors; + + src = CreatePicture (None, + &root->drawable, + format, + CPSubwindowMode, + &include_inferiors, + serverClient, + &error); + if (!src) + return; + + dst = CreatePicture (None, + &dst_pixmap->drawable, + format, + 0L, + NULL, + serverClient, + &error); + if (!dst) + return; + + error = SetPictureTransform (src, &crtc->crtc_to_framebuffer); + if (error) + return; + if (crtc->transform_in_use && crtc->filter) + SetPicturePictFilter (src, crtc->filter, + crtc->params, crtc->nparams); + + if (crtc->shadowClear) + { + CompositePicture (PictOpSrc, + src, NULL, dst, + 0, 0, 0, 0, 0, 0, + crtc->mode.HDisplay, crtc->mode.VDisplay); + crtc->shadowClear = FALSE; + } + else + { + while (n--) + { + BoxRec dst_box; + + dst_box = *b; + dst_box.x1 -= crtc->filter_width >> 1; + dst_box.x2 += crtc->filter_width >> 1; + dst_box.y1 -= crtc->filter_height >> 1; + dst_box.y2 += crtc->filter_height >> 1; + pixman_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box); + CompositePicture (PictOpSrc, + src, NULL, dst, + dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1, + dst_box.x2 - dst_box.x1, + dst_box.y2 - dst_box.y1); + b++; + } + } + FreePicture (src, None); + FreePicture (dst, None); +} + +static void +xf86CrtcDamageShadow (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + BoxRec damage_box; + RegionRec damage_region; + ScreenPtr pScreen = pScrn->pScreen; + + damage_box.x1 = 0; + damage_box.x2 = crtc->mode.HDisplay; + damage_box.y1 = 0; + damage_box.y2 = crtc->mode.VDisplay; + if (!pixman_transform_bounds (&crtc->crtc_to_framebuffer, &damage_box)) + { + damage_box.x1 = 0; + damage_box.y1 = 0; + damage_box.x2 = pScreen->width; + damage_box.y2 = pScreen->height; + } + if (damage_box.x1 < 0) damage_box.x1 = 0; + if (damage_box.y1 < 0) damage_box.y1 = 0; + if (damage_box.x2 > pScreen->width) damage_box.x2 = pScreen->width; + if (damage_box.y2 > pScreen->height) damage_box.y2 = pScreen->height; + REGION_INIT (pScreen, &damage_region, &damage_box, 1); + DamageRegionAppend (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, + &damage_region); + REGION_UNINIT (pScreen, &damage_region); + crtc->shadowClear = TRUE; +} + +static void +xf86RotatePrepare (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (crtc->rotatedData && !crtc->rotatedPixmap) + { + crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc, + crtc->rotatedData, + crtc->mode.HDisplay, + crtc->mode.VDisplay); + if (!xf86_config->rotation_damage_registered) + { + /* Hook damage to screen pixmap */ + DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, + xf86_config->rotation_damage); + xf86_config->rotation_damage_registered = TRUE; + EnableLimitedSchedulingLatency(); + } + + xf86CrtcDamageShadow (crtc); + } + } +} + +static Bool +xf86RotateRedisplay(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + DamagePtr damage = xf86_config->rotation_damage; + RegionPtr region; + + if (!damage) + return FALSE; + xf86RotatePrepare (pScreen); + region = DamageRegion(damage); + if (REGION_NOTEMPTY(pScreen, region)) + { + int c; + SourceValidateProcPtr SourceValidate; + + /* + * SourceValidate is used by the software cursor code + * to pull the cursor off of the screen when reading + * bits from the frame buffer. Bypassing this function + * leaves the software cursor in place + */ + SourceValidate = pScreen->SourceValidate; + pScreen->SourceValidate = NULL; + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (crtc->transform_in_use && crtc->enabled) + { + RegionRec crtc_damage; + + /* compute portion of damage that overlaps crtc */ + REGION_INIT(pScreen, &crtc_damage, &crtc->bounds, 1); + REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region); + + /* update damaged region */ + if (REGION_NOTEMPTY(pScreen, &crtc_damage)) + xf86RotateCrtcRedisplay (crtc, &crtc_damage); + + REGION_UNINIT (pScreen, &crtc_damage); + } + } + pScreen->SourceValidate = SourceValidate; + DamageEmpty(damage); + } + return TRUE; +} + +static void +xf86RotateBlockHandler(int screenNum, pointer blockData, + pointer pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + ScrnInfoPtr pScrn = xf86Screens[screenNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + Bool rotation_active; + + rotation_active = xf86RotateRedisplay(pScreen); + pScreen->BlockHandler = xf86_config->BlockHandler; + (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); + /* cannot avoid re-wrapping until all wrapping is audited */ + xf86_config->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = xf86RotateBlockHandler; +} + +void +xf86RotateDestroy (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = pScrn->pScreen; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + + /* Free memory from rotation */ + if (crtc->rotatedPixmap || crtc->rotatedData) + { + crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData); + crtc->rotatedPixmap = NULL; + crtc->rotatedData = NULL; + } + + for (c = 0; c < xf86_config->num_crtc; c++) + if (xf86_config->crtc[c]->transform_in_use) + return; + + /* + * Clean up damage structures when no crtcs are rotated + */ + if (xf86_config->rotation_damage) + { + /* Free damage structure */ + if (xf86_config->rotation_damage_registered) + { + DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, + xf86_config->rotation_damage); + xf86_config->rotation_damage_registered = FALSE; + DisableLimitedSchedulingLatency(); + } + DamageDestroy (xf86_config->rotation_damage); + xf86_config->rotation_damage = NULL; + } +} + +void +xf86RotateFreeShadow(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; + + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + if (crtc->rotatedPixmap || crtc->rotatedData) { + crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap, + crtc->rotatedData); + crtc->rotatedPixmap = NULL; + crtc->rotatedData = NULL; + } + } +} + +void +xf86RotateCloseScreen (ScreenPtr screen) +{ + ScrnInfoPtr scrn = xf86Screens[screen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) + xf86RotateDestroy (xf86_config->crtc[c]); +} + +static Bool +xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb) +{ + ScrnInfoPtr pScrn = crtc->scrn; + BoxRec b; + + /* When called before PreInit, the driver is + * presumably doing load detect + */ + if (pScrn->virtualX == 0 || pScrn->virtualY == 0) + return TRUE; + + b.x1 = 0; + b.y1 = 0; + b.x2 = crtc->mode.HDisplay; + b.y2 = crtc->mode.VDisplay; + if (crtc_to_fb) + pixman_f_transform_bounds (crtc_to_fb, &b); + else { + b.x1 += crtc->x; + b.y1 += crtc->y; + b.x2 += crtc->x; + b.y2 += crtc->y; + } + + return (0 <= b.x1 && b.x2 <= pScrn->virtualX && + 0 <= b.y1 && b.y2 <= pScrn->virtualY); +} + +Bool +xf86CrtcRotate (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ + ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; + PictTransform crtc_to_fb; + struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc; + xFixed *new_params = NULL; + int new_nparams = 0; + PictFilterPtr new_filter = NULL; + int new_width = 0; + int new_height = 0; + RRTransformPtr transform = NULL; + Bool damage = FALSE; + + if (crtc->transformPresent) + transform = &crtc->transform; + + if (!RRTransformCompute (crtc->x, crtc->y, + crtc->mode.HDisplay, crtc->mode.VDisplay, + crtc->rotation, + transform, + + &crtc_to_fb, + &f_crtc_to_fb, + &f_fb_to_crtc) && + xf86CrtcFitsScreen (crtc, &f_crtc_to_fb)) + { + /* + * If the untranslated transformation is the identity, + * disable the shadow buffer + */ + xf86RotateDestroy (crtc); + crtc->transform_in_use = FALSE; + if (new_params) + free(new_params); + new_params = NULL; + new_nparams = 0; + new_filter = NULL; + new_width = 0; + new_height = 0; + } + else + { + /* + * these are the size of the shadow pixmap, which + * matches the mode, not the pre-rotated copy in the + * frame buffer + */ + int width = crtc->mode.HDisplay; + int height = crtc->mode.VDisplay; + void *shadowData = crtc->rotatedData; + PixmapPtr shadow = crtc->rotatedPixmap; + int old_width = shadow ? shadow->drawable.width : 0; + int old_height = shadow ? shadow->drawable.height : 0; + + /* Allocate memory for rotation */ + if (old_width != width || old_height != height) + { + if (shadow || shadowData) + { + crtc->funcs->shadow_destroy (crtc, shadow, shadowData); + crtc->rotatedPixmap = NULL; + crtc->rotatedData = NULL; + } + shadowData = crtc->funcs->shadow_allocate (crtc, width, height); + if (!shadowData) + goto bail1; + crtc->rotatedData = shadowData; + /* shadow will be damaged in xf86RotatePrepare */ + } + else + { + /* mark shadowed area as damaged so it will be repainted */ + damage = TRUE; + } + + if (!xf86_config->rotation_damage) + { + /* Create damage structure */ + xf86_config->rotation_damage = DamageCreate (NULL, NULL, + DamageReportNone, + TRUE, pScreen, pScreen); + if (!xf86_config->rotation_damage) + goto bail2; + + /* Wrap block handler */ + if (!xf86_config->BlockHandler) { + xf86_config->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = xf86RotateBlockHandler; + } + } +#ifdef RANDR_12_INTERFACE + if (transform) + { + if (transform->nparams) { + new_params = malloc(transform->nparams * sizeof (xFixed)); + if (new_params) { + memcpy (new_params, transform->params, + transform->nparams * sizeof (xFixed)); + new_nparams = transform->nparams; + new_filter = transform->filter; + } + } else + new_filter = transform->filter; + if (new_filter) + { + new_width = new_filter->width; + new_height = new_filter->height; + } + } +#endif + + if (0) + { + bail2: + if (shadow || shadowData) + { + crtc->funcs->shadow_destroy (crtc, shadow, shadowData); + crtc->rotatedPixmap = NULL; + crtc->rotatedData = NULL; + } + bail1: + if (old_width && old_height) + crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc, + NULL, + old_width, + old_height); + return FALSE; + } + crtc->transform_in_use = TRUE; + } + crtc->crtc_to_framebuffer = crtc_to_fb; + crtc->f_crtc_to_framebuffer = f_crtc_to_fb; + crtc->f_framebuffer_to_crtc = f_fb_to_crtc; + if (crtc->params) + free(crtc->params); + crtc->params = new_params; + crtc->nparams = new_nparams; + crtc->filter = new_filter; + crtc->filter_width = new_width; + crtc->filter_height = new_height; + crtc->bounds.x1 = 0; + crtc->bounds.x2 = crtc->mode.HDisplay; + crtc->bounds.y1 = 0; + crtc->bounds.y2 = crtc->mode.VDisplay; + pixman_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds); + + if (damage) + xf86CrtcDamageShadow (crtc); + + /* All done */ + return TRUE; +} diff --git a/xorg-server/hw/xfree86/os-support/bsd/i386_video.c b/xorg-server/hw/xfree86/os-support/bsd/i386_video.c index 10db9c7b8..0d457193a 100644 --- a/xorg-server/hw/xfree86/os-support/bsd/i386_video.c +++ b/xorg-server/hw/xfree86/os-support/bsd/i386_video.c @@ -1,908 +1,908 @@ -/* - * Copyright 1992 by Rich Murphey - * Copyright 1993 by David Wexelblat - * - * 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 names of Rich Murphey and David Wexelblat - * not be used in advertising or publicity pertaining to distribution of - * the software without specific, written prior permission. Rich Murphey and - * David Wexelblat make no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO - * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT 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. - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "xf86.h" -#include "xf86Priv.h" - -#include -#include - -#ifdef HAS_MTRR_SUPPORT -#ifndef __NetBSD__ -#include -#include -#else -#include "memrange.h" -#endif -#define X_MTRR_ID "XFree86" -#endif - -#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) -#include -#include -#include -#ifdef __x86_64__ -#define i386_set_mtrr x86_64_set_mtrr -#define i386_get_mtrr x86_64_get_mtrr -#define i386_iopl x86_64_iopl -#endif -#endif - -#include "xf86_OSlib.h" -#include "xf86OSpriv.h" - -#if defined(__NetBSD__) && !defined(MAP_FILE) -#define MAP_FLAGS MAP_SHARED -#else -#define MAP_FLAGS (MAP_FILE | MAP_SHARED) -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((caddr_t)-1) -#endif - -#ifdef __OpenBSD__ -#define SYSCTL_MSG "\tCheck that you have set 'machdep.allowaperture=1'\n"\ - "\tin /etc/sysctl.conf and reboot your machine\n" \ - "\trefer to xf86(4) for details" -#define SYSCTL_MSG2 \ - "Check that you have set 'machdep.allowaperture=2'\n" \ - "\tin /etc/sysctl.conf and reboot your machine\n" \ - "\trefer to xf86(4) for details" -#endif - -/***************************************************************************/ -/* Video Memory Mapping section */ -/***************************************************************************/ - -static Bool useDevMem = FALSE; -static int devMemFd = -1; - -#ifdef HAS_APERTURE_DRV -#define DEV_APERTURE "/dev/xf86" -#endif -#define DEV_MEM "/dev/mem" - -static pointer mapVidMem(int, unsigned long, unsigned long, int); -static void unmapVidMem(int, pointer, unsigned long); - -#ifdef HAS_MTRR_SUPPORT -static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); -static void undoWC(int, pointer); -static Bool cleanMTRR(void); -#endif -#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) -static pointer NetBSDsetWC(int, unsigned long, unsigned long, Bool, - MessageType); -static void NetBSDundoWC(int, pointer); -#endif - -/* - * Check if /dev/mem can be mmap'd. If it can't print a warning when - * "warn" is TRUE. - */ -static void -checkDevMem(Bool warn) -{ - static Bool devMemChecked = FALSE; - int fd; - pointer base; - - if (devMemChecked) - return; - devMemChecked = TRUE; - - if ((fd = open(DEV_MEM, O_RDWR)) >= 0) - { - /* Try to map a page at the VGA address */ - base = mmap((caddr_t)0, 4096, PROT_READ | PROT_WRITE, - MAP_FLAGS, fd, (off_t)0xA0000); - - if (base != MAP_FAILED) - { - munmap((caddr_t)base, 4096); - devMemFd = fd; - useDevMem = TRUE; - return; - } else { - /* This should not happen */ - if (warn) - { - xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n", - DEV_MEM, strerror(errno)); - } - useDevMem = FALSE; - return; - } - } -#ifndef HAS_APERTURE_DRV - if (warn) - { - xf86Msg(X_WARNING, "checkDevMem: failed to open %s (%s)\n", - DEV_MEM, strerror(errno)); - } - useDevMem = FALSE; - return; -#else - /* Failed to open /dev/mem, try the aperture driver */ - if ((fd = open(DEV_APERTURE, O_RDWR)) >= 0) - { - /* Try to map a page at the VGA address */ - base = mmap((caddr_t)0, 4096, PROT_READ | PROT_WRITE, - MAP_FLAGS, fd, (off_t)0xA0000); - - if (base != MAP_FAILED) - { - munmap((caddr_t)base, 4096); - devMemFd = fd; - useDevMem = TRUE; - xf86Msg(X_INFO, "checkDevMem: using aperture driver %s\n", - DEV_APERTURE); - return; - } else { - - if (warn) - { - xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n", - DEV_APERTURE, strerror(errno)); - } - } - } else { - if (warn) - { -#ifndef __OpenBSD__ - xf86Msg(X_WARNING, "checkDevMem: failed to open %s and %s\n" - "\t(%s)\n", DEV_MEM, DEV_APERTURE, strerror(errno)); -#else /* __OpenBSD__ */ - xf86Msg(X_WARNING, "checkDevMem: failed to open %s and %s\n" - "\t(%s)\n%s", DEV_MEM, DEV_APERTURE, strerror(errno), - SYSCTL_MSG); -#endif /* __OpenBSD__ */ - } - } - - useDevMem = FALSE; - return; - -#endif -} - -void -xf86OSInitVidMem(VidMemInfoPtr pVidMem) -{ - checkDevMem(TRUE); - pVidMem->linearSupported = useDevMem; - pVidMem->mapMem = mapVidMem; - pVidMem->unmapMem = unmapVidMem; - -#if HAVE_PCI_SYSTEM_INIT_DEV_MEM - if (useDevMem) - pci_system_init_dev_mem(devMemFd); -#endif - -#ifdef HAS_MTRR_SUPPORT - if (useDevMem) { - if (cleanMTRR()) { - pVidMem->setWC = setWC; - pVidMem->undoWC = undoWC; - } - } -#endif -#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) - pVidMem->setWC = NetBSDsetWC; - pVidMem->undoWC = NetBSDundoWC; -#endif - pVidMem->initialised = TRUE; -} - -static pointer -mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) -{ - pointer base; - - checkDevMem(FALSE); - - if (useDevMem) - { - if (devMemFd < 0) - { - FatalError("xf86MapVidMem: failed to open %s (%s)", - DEV_MEM, strerror(errno)); - } - base = mmap((caddr_t)0, Size, - (flags & VIDMEM_READONLY) ? - PROT_READ : (PROT_READ | PROT_WRITE), - MAP_FLAGS, devMemFd, (off_t)Base); - if (base == MAP_FAILED) - { - FatalError("%s: could not mmap %s [s=%lx,a=%lx] (%s)", - "xf86MapVidMem", DEV_MEM, Size, Base, - strerror(errno)); - } - return(base); - } - - /* else, mmap /dev/vga */ - if ((unsigned long)Base < 0xA0000 || (unsigned long)Base >= 0xC0000) - { - FatalError("%s: Address 0x%lx outside allowable range", - "xf86MapVidMem", Base); - } - base = mmap(0, Size, - (flags & VIDMEM_READONLY) ? - PROT_READ : (PROT_READ | PROT_WRITE), - MAP_FLAGS, xf86Info.screenFd, - (unsigned long)Base - 0xA0000 - ); - if (base == MAP_FAILED) - { - FatalError("xf86MapVidMem: Could not mmap /dev/vga (%s)", - strerror(errno)); - } - return(base); -} - -static void -unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) -{ - munmap((caddr_t)Base, Size); -} - -/* - * Read BIOS via mmap()ing DEV_MEM - */ - -int -xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf, - int Len) -{ - unsigned char *ptr; - int psize; - int mlen; - - checkDevMem(TRUE); - if (devMemFd == -1) { - return(-1); - } - - psize = getpagesize(); - Offset += Base & (psize - 1); - Base &= ~(psize - 1); - mlen = (Offset + Len + psize - 1) & ~(psize - 1); - ptr = (unsigned char *)mmap((caddr_t)0, mlen, PROT_READ, - MAP_SHARED, devMemFd, (off_t)Base); - if ((long)ptr == -1) - { - xf86Msg(X_WARNING, - "xf86ReadBIOS: %s mmap[s=%x,a=%lx,o=%lx] failed (%s)\n", - DEV_MEM, Len, Base, Offset, strerror(errno)); -#ifdef __OpenBSD__ - if (Base < 0xa0000) { - xf86Msg(X_WARNING, SYSCTL_MSG2); - } -#endif - return(-1); - } -#ifdef DEBUG - ErrorF("xf86ReadBIOS: BIOS at 0x%08x has signature 0x%04x\n", - Base, ptr[0] | (ptr[1] << 8)); -#endif - (void)memcpy(Buf, (void *)(ptr + Offset), Len); - (void)munmap((caddr_t)ptr, mlen); -#ifdef DEBUG - xf86MsgVerb(X_INFO, 3, "xf86ReadBIOS(%x, %x, Buf, %x)" - "-> %02x %02x %02x %02x...\n", - Base, Offset, Len, Buf[0], Buf[1], Buf[2], Buf[3]); -#endif - return(Len); -} - -#ifdef USE_I386_IOPL -/***************************************************************************/ -/* I/O Permissions section */ -/***************************************************************************/ - -static Bool ExtendedEnabled = FALSE; - -Bool -xf86EnableIO() -{ - if (ExtendedEnabled) - return TRUE; - - if (i386_iopl(TRUE) < 0) - { -#ifndef __OpenBSD__ - xf86Msg(X_WARNING,"%s: Failed to set IOPL for extended I/O", - "xf86EnableIO"); -#else - xf86Msg(X_WARNING,"%s: Failed to set IOPL for extended I/O\n%s", - "xf86EnableIO", SYSCTL_MSG); -#endif - return FALSE; - } - ExtendedEnabled = TRUE; - - return TRUE; -} - -void -xf86DisableIO() -{ - if (!ExtendedEnabled) - return; - - i386_iopl(FALSE); - ExtendedEnabled = FALSE; - - return; -} - -#endif /* USE_I386_IOPL */ - -#ifdef USE_AMD64_IOPL -/***************************************************************************/ -/* I/O Permissions section */ -/***************************************************************************/ - -static Bool ExtendedEnabled = FALSE; - -Bool -xf86EnableIO() -{ - if (ExtendedEnabled) - return TRUE; - - if (amd64_iopl(TRUE) < 0) - { -#ifndef __OpenBSD__ - xf86Msg(X_WARNING,"%s: Failed to set IOPL for extended I/O", - "xf86EnableIO"); -#else - xf86Msg(X_WARNING,"%s: Failed to set IOPL for extended I/O\n%s", - "xf86EnableIO", SYSCTL_MSG); -#endif - return FALSE; - } - ExtendedEnabled = TRUE; - - return TRUE; -} - -void -xf86DisableIO() -{ - if (!ExtendedEnabled) - return; - - if (amd64_iopl(FALSE) == 0) { - ExtendedEnabled = FALSE; - } - /* Otherwise, the X server has revoqued its root uid, - and thus cannot give up IO privileges any more */ - - return; -} - -#endif /* USE_AMD64_IOPL */ - -#ifdef USE_DEV_IO -static int IoFd = -1; - -Bool -xf86EnableIO() -{ - if (IoFd >= 0) - return TRUE; - - if ((IoFd = open("/dev/io", O_RDWR)) == -1) - { - xf86Msg(X_WARNING,"xf86EnableIO: " - "Failed to open /dev/io for extended I/O"); - return FALSE; - } - return TRUE; -} - -void -xf86DisableIO() -{ - if (IoFd < 0) - return; - - close(IoFd); - IoFd = -1; - return; -} - -#endif - -#ifdef __NetBSD__ -/***************************************************************************/ -/* Set TV output mode */ -/***************************************************************************/ -void -xf86SetTVOut(int mode) -{ - switch (xf86Info.consType) - { -#ifdef PCCONS_SUPPORT - case PCCONS:{ - - if (ioctl (xf86Info.consoleFd, CONSOLE_X_TV_ON, &mode) < 0) - { - xf86Msg(X_WARNING, - "xf86SetTVOut: Could not set console to TV output, %s\n", - strerror(errno)); - } - } - break; -#endif /* PCCONS_SUPPORT */ - - default: - FatalError("Xf86SetTVOut: Unsupported console"); - break; - } - return; -} - -void -xf86SetRGBOut() -{ - switch (xf86Info.consType) - { -#ifdef PCCONS_SUPPORT - case PCCONS:{ - - if (ioctl (xf86Info.consoleFd, CONSOLE_X_TV_OFF, 0) < 0) - { - xf86Msg(X_WARNING, - "xf86SetTVOut: Could not set console to RGB output, %s\n", - strerror(errno)); - } - } - break; -#endif /* PCCONS_SUPPORT */ - - default: - FatalError("Xf86SetTVOut: Unsupported console"); - break; - } - return; -} -#endif - -#ifdef HAS_MTRR_SUPPORT -/* memory range (MTRR) support for FreeBSD */ - -/* - * This code is experimental. Some parts may be overkill, and other parts - * may be incomplete. - */ - -/* - * getAllRanges returns the full list of memory ranges with attributes set. - */ - -static struct mem_range_desc * -getAllRanges(int *nmr) -{ - struct mem_range_desc *mrd; - struct mem_range_op mro; - - /* - * Find how many ranges there are. If this fails, then the kernel - * probably doesn't have MTRR support. - */ - mro.mo_arg[0] = 0; - if (ioctl(devMemFd, MEMRANGE_GET, &mro)) - return NULL; - *nmr = mro.mo_arg[0]; - mrd = xnfalloc(*nmr * sizeof(struct mem_range_desc)); - mro.mo_arg[0] = *nmr; - mro.mo_desc = mrd; - if (ioctl(devMemFd, MEMRANGE_GET, &mro)) { - xfree(mrd); - return NULL; - } - return mrd; -} - -/* - * cleanMTRR removes any memory attribute that may be left by a previous - * X server. Normally there won't be any, but this takes care of the - * case where a server crashed without being able finish cleaning up. - */ - -static Bool -cleanMTRR() -{ - struct mem_range_desc *mrd; - struct mem_range_op mro; - int nmr, i; - - /* This shouldn't happen */ - if (devMemFd < 0) - return FALSE; - - if (!(mrd = getAllRanges(&nmr))) - return FALSE; - - for (i = 0; i < nmr; i++) { - if (strcmp(mrd[i].mr_owner, X_MTRR_ID) == 0 && - (mrd[i].mr_flags & MDF_ACTIVE)) { -#ifdef DEBUG - ErrorF("Clean for (0x%lx,0x%lx)\n", - (unsigned long)mrd[i].mr_base, - (unsigned long)mrd[i].mr_len); -#endif - if (mrd[i].mr_flags & MDF_FIXACTIVE) { - mro.mo_arg[0] = MEMRANGE_SET_UPDATE; - mrd[i].mr_flags = MDF_UNCACHEABLE; - } else { - mro.mo_arg[0] = MEMRANGE_SET_REMOVE; - } - mro.mo_desc = mrd + i; - ioctl(devMemFd, MEMRANGE_SET, &mro); - } - } -#ifdef DEBUG - sleep(10); -#endif - xfree(mrd); - return TRUE; -} - -typedef struct x_RangeRec { - struct mem_range_desc mrd; - Bool wasWC; - struct x_RangeRec * next; -} RangeRec, *RangePtr; - -static void -freeRangeList(RangePtr range) -{ - RangePtr rp; - - while (range) { - rp = range; - range = rp->next; - xfree(rp); - } -} - -static RangePtr -dupRangeList(RangePtr list) -{ - RangePtr new = NULL, rp, p; - - rp = list; - while (rp) { - p = xnfalloc(sizeof(RangeRec)); - *p = *rp; - p->next = new; - new = p; - rp = rp->next; - } - return new; -} - -static RangePtr -sortRangeList(RangePtr list) -{ - RangePtr rp1, rp2, copy, sorted = NULL, minp, prev, minprev; - unsigned long minBase; - - /* Sort by base address */ - rp1 = copy = dupRangeList(list); - while (rp1) { - minBase = rp1->mrd.mr_base; - minp = rp1; - minprev = NULL; - prev = rp1; - rp2 = rp1->next; - while (rp2) { - if (rp2->mrd.mr_base < minBase) { - minBase = rp2->mrd.mr_base; - minp = rp2; - minprev = prev; - } - prev = rp2; - rp2 = rp2->next; - } - if (minprev) { - minprev->next = minp->next; - rp1 = copy; - } else { - rp1 = minp->next; - } - minp->next = sorted; - sorted = minp; - } - return sorted; -} - -/* - * findRanges returns a list of ranges that overlap the specified range. - */ - -static void -findRanges(unsigned long base, unsigned long size, RangePtr *ucp, RangePtr *wcp) -{ - struct mem_range_desc *mrd; - int nmr, i; - RangePtr rp, *p; - - if (!(mrd = getAllRanges(&nmr))) - return; - - for (i = 0; i < nmr; i++) { - if ((mrd[i].mr_flags & MDF_ACTIVE) && - mrd[i].mr_base < base + size && - mrd[i].mr_base + mrd[i].mr_len > base) { - if (mrd[i].mr_flags & MDF_WRITECOMBINE) - p = wcp; - else if (mrd[i].mr_flags & MDF_UNCACHEABLE) - p = ucp; - else - continue; - rp = xnfalloc(sizeof(RangeRec)); - rp->mrd = mrd[i]; - rp->next = *p; - *p = rp; - } - } - xfree(mrd); -} - -/* - * This checks if the existing overlapping ranges fully cover the requested - * range. Is this overkill? - */ - -static Bool -fullCoverage(unsigned long base, unsigned long size, RangePtr overlap) -{ - RangePtr rp1, sorted = NULL; - unsigned long end; - - sorted = sortRangeList(overlap); - /* Look for gaps */ - rp1 = sorted; - end = base + size; - while (rp1) { - if (rp1->mrd.mr_base > base) { - freeRangeList(sorted); - return FALSE; - } else { - base = rp1->mrd.mr_base + rp1->mrd.mr_len; - } - if (base >= end) { - freeRangeList(sorted); - return TRUE; - } - rp1 = rp1->next; - } - freeRangeList(sorted); - return FALSE; -} - -static pointer -addWC(int screenNum, unsigned long base, unsigned long size, MessageType from) -{ - RangePtr uc = NULL, wc = NULL, retlist = NULL; - struct mem_range_desc mrd; - struct mem_range_op mro; - - findRanges(base, size, &uc, &wc); - - /* See of the full range is already WC */ - if (!uc && fullCoverage(base, size, wc)) { - xf86DrvMsg(screenNum, from, - "Write-combining range (0x%lx,0x%lx) was already set\n", - base, size); - return NULL; - } - - /* Otherwise, try to add the new range */ - mrd.mr_base = base; - mrd.mr_len = size; - strcpy(mrd.mr_owner, X_MTRR_ID); - mrd.mr_flags = MDF_WRITECOMBINE; - mro.mo_desc = &mrd; - mro.mo_arg[0] = MEMRANGE_SET_UPDATE; - if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { - xf86DrvMsg(screenNum, X_WARNING, - "Failed to set write-combining range " - "(0x%lx,0x%lx)\n", base, size); - return NULL; - } else { - xf86DrvMsg(screenNum, from, - "Write-combining range (0x%lx,0x%lx)\n", base, size); - retlist = xnfalloc(sizeof(RangeRec)); - retlist->mrd = mrd; - retlist->wasWC = FALSE; - retlist->next = NULL; - return retlist; - } -} - -static pointer -delWC(int screenNum, unsigned long base, unsigned long size, MessageType from) -{ - RangePtr uc = NULL, wc = NULL, retlist = NULL; - struct mem_range_desc mrd; - struct mem_range_op mro; - - findRanges(base, size, &uc, &wc); - - /* - * See of the full range is already not WC, or if there is full - * coverage from UC ranges. - */ - if (!wc || fullCoverage(base, size, uc)) { - xf86DrvMsg(screenNum, from, - "Write-combining range (0x%lx,0x%lx) was already clear\n", - base, size); - return NULL; - } - - /* Otherwise, try to add the new range */ - mrd.mr_base = base; - mrd.mr_len = size; - strcpy(mrd.mr_owner, X_MTRR_ID); - mrd.mr_flags = MDF_UNCACHEABLE; - mro.mo_desc = &mrd; - mro.mo_arg[0] = MEMRANGE_SET_UPDATE; - if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { - xf86DrvMsg(screenNum, X_WARNING, - "Failed to remove write-combining range " - "(0x%lx,0x%lx)\n", base, size); - /* XXX Should then remove all of the overlapping WC ranges */ - return NULL; - } else { - xf86DrvMsg(screenNum, from, - "Removed Write-combining range (0x%lx,0x%lx)\n", - base, size); - retlist = xnfalloc(sizeof(RangeRec)); - retlist->mrd = mrd; - retlist->wasWC = TRUE; - retlist->next = NULL; - return retlist; - } -} - -static pointer -setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, - MessageType from) -{ - if (enable) - return addWC(screenNum, base, size, from); - else - return delWC(screenNum, base, size, from); -} - -static void -undoWC(int screenNum, pointer list) -{ - RangePtr rp; - struct mem_range_op mro; - Bool failed; - - rp = list; - while (rp) { -#ifdef DEBUG - ErrorF("Undo for (0x%lx,0x%lx), %d\n", - (unsigned long)rp->mrd.mr_base, - (unsigned long)rp->mrd.mr_len, rp->wasWC); -#endif - failed = FALSE; - if (rp->wasWC) { - mro.mo_arg[0] = MEMRANGE_SET_UPDATE; - rp->mrd.mr_flags = MDF_WRITECOMBINE; - strcpy(rp->mrd.mr_owner, "unknown"); - } else { - mro.mo_arg[0] = MEMRANGE_SET_REMOVE; - } - mro.mo_desc = &rp->mrd; - - if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { - if (!rp->wasWC) { - mro.mo_arg[0] = MEMRANGE_SET_UPDATE; - rp->mrd.mr_flags = MDF_UNCACHEABLE; - strcpy(rp->mrd.mr_owner, "unknown"); - if (ioctl(devMemFd, MEMRANGE_SET, &mro)) - failed = TRUE; - } else - failed = TRUE; - } - if (failed) { - xf86DrvMsg(screenNum, X_WARNING, - "Failed to restore MTRR range (0x%lx,0x%lx)\n", - (unsigned long)rp->mrd.mr_base, - (unsigned long)rp->mrd.mr_len); - } - rp = rp->next; - } -} - -#endif /* HAS_MTRR_SUPPORT */ - - -#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) -static pointer -NetBSDsetWC(int screenNum, unsigned long base, unsigned long size, Bool enable, - MessageType from) -{ - struct mtrr *mtrrp; - int n; - - xf86DrvMsg(screenNum, X_WARNING, - "%s MTRR %lx - %lx\n", enable ? "set" : "remove", - base, (base + size)); - - mtrrp = xnfalloc(sizeof (struct mtrr)); - mtrrp->base = base; - mtrrp->len = size; - mtrrp->type = MTRR_TYPE_WC; - - /* - * MTRR_PRIVATE will make this MTRR get reset automatically - * if this process exits, so we have no need for an explicit - * cleanup operation when starting a new server. - */ - - if (enable) - mtrrp->flags = MTRR_VALID | MTRR_PRIVATE; - else - mtrrp->flags = 0; - n = 1; - - if (i386_set_mtrr(mtrrp, &n) < 0) { - xfree(mtrrp); - return NULL; - } - return mtrrp; -} - -static void -NetBSDundoWC(int screenNum, pointer list) -{ - struct mtrr *mtrrp = (struct mtrr *)list; - int n; - - if (mtrrp == NULL) - return; - n = 1; - mtrrp->flags &= ~MTRR_VALID; - i386_set_mtrr(mtrrp, &n); - xfree(mtrrp); -} -#endif +/* + * Copyright 1992 by Rich Murphey + * Copyright 1993 by David Wexelblat + * + * 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 names of Rich Murphey and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Rich Murphey and + * David Wexelblat make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * RICH MURPHEY AND DAVID WEXELBLAT DISCLAIM ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL RICH MURPHEY OR DAVID WEXELBLAT 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. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "xf86.h" +#include "xf86Priv.h" + +#include +#include + +#ifdef HAS_MTRR_SUPPORT +#ifndef __NetBSD__ +#include +#include +#else +#include "memrange.h" +#endif +#define X_MTRR_ID "XFree86" +#endif + +#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) +#include +#include +#include +#ifdef __x86_64__ +#define i386_set_mtrr x86_64_set_mtrr +#define i386_get_mtrr x86_64_get_mtrr +#define i386_iopl x86_64_iopl +#endif +#endif + +#include "xf86_OSlib.h" +#include "xf86OSpriv.h" + +#if defined(__NetBSD__) && !defined(MAP_FILE) +#define MAP_FLAGS MAP_SHARED +#else +#define MAP_FLAGS (MAP_FILE | MAP_SHARED) +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((caddr_t)-1) +#endif + +#ifdef __OpenBSD__ +#define SYSCTL_MSG "\tCheck that you have set 'machdep.allowaperture=1'\n"\ + "\tin /etc/sysctl.conf and reboot your machine\n" \ + "\trefer to xf86(4) for details" +#define SYSCTL_MSG2 \ + "Check that you have set 'machdep.allowaperture=2'\n" \ + "\tin /etc/sysctl.conf and reboot your machine\n" \ + "\trefer to xf86(4) for details" +#endif + +/***************************************************************************/ +/* Video Memory Mapping section */ +/***************************************************************************/ + +static Bool useDevMem = FALSE; +static int devMemFd = -1; + +#ifdef HAS_APERTURE_DRV +#define DEV_APERTURE "/dev/xf86" +#endif +#define DEV_MEM "/dev/mem" + +static pointer mapVidMem(int, unsigned long, unsigned long, int); +static void unmapVidMem(int, pointer, unsigned long); + +#ifdef HAS_MTRR_SUPPORT +static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); +static void undoWC(int, pointer); +static Bool cleanMTRR(void); +#endif +#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) +static pointer NetBSDsetWC(int, unsigned long, unsigned long, Bool, + MessageType); +static void NetBSDundoWC(int, pointer); +#endif + +/* + * Check if /dev/mem can be mmap'd. If it can't print a warning when + * "warn" is TRUE. + */ +static void +checkDevMem(Bool warn) +{ + static Bool devMemChecked = FALSE; + int fd; + pointer base; + + if (devMemChecked) + return; + devMemChecked = TRUE; + + if ((fd = open(DEV_MEM, O_RDWR)) >= 0) + { + /* Try to map a page at the VGA address */ + base = mmap((caddr_t)0, 4096, PROT_READ | PROT_WRITE, + MAP_FLAGS, fd, (off_t)0xA0000); + + if (base != MAP_FAILED) + { + munmap((caddr_t)base, 4096); + devMemFd = fd; + useDevMem = TRUE; + return; + } else { + /* This should not happen */ + if (warn) + { + xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n", + DEV_MEM, strerror(errno)); + } + useDevMem = FALSE; + return; + } + } +#ifndef HAS_APERTURE_DRV + if (warn) + { + xf86Msg(X_WARNING, "checkDevMem: failed to open %s (%s)\n", + DEV_MEM, strerror(errno)); + } + useDevMem = FALSE; + return; +#else + /* Failed to open /dev/mem, try the aperture driver */ + if ((fd = open(DEV_APERTURE, O_RDWR)) >= 0) + { + /* Try to map a page at the VGA address */ + base = mmap((caddr_t)0, 4096, PROT_READ | PROT_WRITE, + MAP_FLAGS, fd, (off_t)0xA0000); + + if (base != MAP_FAILED) + { + munmap((caddr_t)base, 4096); + devMemFd = fd; + useDevMem = TRUE; + xf86Msg(X_INFO, "checkDevMem: using aperture driver %s\n", + DEV_APERTURE); + return; + } else { + + if (warn) + { + xf86Msg(X_WARNING, "checkDevMem: failed to mmap %s (%s)\n", + DEV_APERTURE, strerror(errno)); + } + } + } else { + if (warn) + { +#ifndef __OpenBSD__ + xf86Msg(X_WARNING, "checkDevMem: failed to open %s and %s\n" + "\t(%s)\n", DEV_MEM, DEV_APERTURE, strerror(errno)); +#else /* __OpenBSD__ */ + xf86Msg(X_WARNING, "checkDevMem: failed to open %s and %s\n" + "\t(%s)\n%s", DEV_MEM, DEV_APERTURE, strerror(errno), + SYSCTL_MSG); +#endif /* __OpenBSD__ */ + } + } + + useDevMem = FALSE; + return; + +#endif +} + +void +xf86OSInitVidMem(VidMemInfoPtr pVidMem) +{ + checkDevMem(TRUE); + pVidMem->linearSupported = useDevMem; + pVidMem->mapMem = mapVidMem; + pVidMem->unmapMem = unmapVidMem; + +#if HAVE_PCI_SYSTEM_INIT_DEV_MEM + if (useDevMem) + pci_system_init_dev_mem(devMemFd); +#endif + +#ifdef HAS_MTRR_SUPPORT + if (useDevMem) { + if (cleanMTRR()) { + pVidMem->setWC = setWC; + pVidMem->undoWC = undoWC; + } + } +#endif +#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) + pVidMem->setWC = NetBSDsetWC; + pVidMem->undoWC = NetBSDundoWC; +#endif + pVidMem->initialised = TRUE; +} + +static pointer +mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + pointer base; + + checkDevMem(FALSE); + + if (useDevMem) + { + if (devMemFd < 0) + { + FatalError("xf86MapVidMem: failed to open %s (%s)", + DEV_MEM, strerror(errno)); + } + base = mmap((caddr_t)0, Size, + (flags & VIDMEM_READONLY) ? + PROT_READ : (PROT_READ | PROT_WRITE), + MAP_FLAGS, devMemFd, (off_t)Base); + if (base == MAP_FAILED) + { + FatalError("%s: could not mmap %s [s=%lx,a=%lx] (%s)", + "xf86MapVidMem", DEV_MEM, Size, Base, + strerror(errno)); + } + return(base); + } + + /* else, mmap /dev/vga */ + if ((unsigned long)Base < 0xA0000 || (unsigned long)Base >= 0xC0000) + { + FatalError("%s: Address 0x%lx outside allowable range", + "xf86MapVidMem", Base); + } + base = mmap(0, Size, + (flags & VIDMEM_READONLY) ? + PROT_READ : (PROT_READ | PROT_WRITE), + MAP_FLAGS, xf86Info.screenFd, + (unsigned long)Base - 0xA0000 + ); + if (base == MAP_FAILED) + { + FatalError("xf86MapVidMem: Could not mmap /dev/vga (%s)", + strerror(errno)); + } + return(base); +} + +static void +unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) +{ + munmap((caddr_t)Base, Size); +} + +/* + * Read BIOS via mmap()ing DEV_MEM + */ + +int +xf86ReadBIOS(unsigned long Base, unsigned long Offset, unsigned char *Buf, + int Len) +{ + unsigned char *ptr; + int psize; + int mlen; + + checkDevMem(TRUE); + if (devMemFd == -1) { + return(-1); + } + + psize = getpagesize(); + Offset += Base & (psize - 1); + Base &= ~(psize - 1); + mlen = (Offset + Len + psize - 1) & ~(psize - 1); + ptr = (unsigned char *)mmap((caddr_t)0, mlen, PROT_READ, + MAP_SHARED, devMemFd, (off_t)Base); + if ((long)ptr == -1) + { + xf86Msg(X_WARNING, + "xf86ReadBIOS: %s mmap[s=%x,a=%lx,o=%lx] failed (%s)\n", + DEV_MEM, Len, Base, Offset, strerror(errno)); +#ifdef __OpenBSD__ + if (Base < 0xa0000) { + xf86Msg(X_WARNING, SYSCTL_MSG2); + } +#endif + return(-1); + } +#ifdef DEBUG + ErrorF("xf86ReadBIOS: BIOS at 0x%08x has signature 0x%04x\n", + Base, ptr[0] | (ptr[1] << 8)); +#endif + (void)memcpy(Buf, (void *)(ptr + Offset), Len); + (void)munmap((caddr_t)ptr, mlen); +#ifdef DEBUG + xf86MsgVerb(X_INFO, 3, "xf86ReadBIOS(%x, %x, Buf, %x)" + "-> %02x %02x %02x %02x...\n", + Base, Offset, Len, Buf[0], Buf[1], Buf[2], Buf[3]); +#endif + return(Len); +} + +#ifdef USE_I386_IOPL +/***************************************************************************/ +/* I/O Permissions section */ +/***************************************************************************/ + +static Bool ExtendedEnabled = FALSE; + +Bool +xf86EnableIO() +{ + if (ExtendedEnabled) + return TRUE; + + if (i386_iopl(TRUE) < 0) + { +#ifndef __OpenBSD__ + xf86Msg(X_WARNING,"%s: Failed to set IOPL for extended I/O", + "xf86EnableIO"); +#else + xf86Msg(X_WARNING,"%s: Failed to set IOPL for extended I/O\n%s", + "xf86EnableIO", SYSCTL_MSG); +#endif + return FALSE; + } + ExtendedEnabled = TRUE; + + return TRUE; +} + +void +xf86DisableIO() +{ + if (!ExtendedEnabled) + return; + + i386_iopl(FALSE); + ExtendedEnabled = FALSE; + + return; +} + +#endif /* USE_I386_IOPL */ + +#ifdef USE_AMD64_IOPL +/***************************************************************************/ +/* I/O Permissions section */ +/***************************************************************************/ + +static Bool ExtendedEnabled = FALSE; + +Bool +xf86EnableIO() +{ + if (ExtendedEnabled) + return TRUE; + + if (amd64_iopl(TRUE) < 0) + { +#ifndef __OpenBSD__ + xf86Msg(X_WARNING,"%s: Failed to set IOPL for extended I/O", + "xf86EnableIO"); +#else + xf86Msg(X_WARNING,"%s: Failed to set IOPL for extended I/O\n%s", + "xf86EnableIO", SYSCTL_MSG); +#endif + return FALSE; + } + ExtendedEnabled = TRUE; + + return TRUE; +} + +void +xf86DisableIO() +{ + if (!ExtendedEnabled) + return; + + if (amd64_iopl(FALSE) == 0) { + ExtendedEnabled = FALSE; + } + /* Otherwise, the X server has revoqued its root uid, + and thus cannot give up IO privileges any more */ + + return; +} + +#endif /* USE_AMD64_IOPL */ + +#ifdef USE_DEV_IO +static int IoFd = -1; + +Bool +xf86EnableIO() +{ + if (IoFd >= 0) + return TRUE; + + if ((IoFd = open("/dev/io", O_RDWR)) == -1) + { + xf86Msg(X_WARNING,"xf86EnableIO: " + "Failed to open /dev/io for extended I/O"); + return FALSE; + } + return TRUE; +} + +void +xf86DisableIO() +{ + if (IoFd < 0) + return; + + close(IoFd); + IoFd = -1; + return; +} + +#endif + +#ifdef __NetBSD__ +/***************************************************************************/ +/* Set TV output mode */ +/***************************************************************************/ +void +xf86SetTVOut(int mode) +{ + switch (xf86Info.consType) + { +#ifdef PCCONS_SUPPORT + case PCCONS:{ + + if (ioctl (xf86Info.consoleFd, CONSOLE_X_TV_ON, &mode) < 0) + { + xf86Msg(X_WARNING, + "xf86SetTVOut: Could not set console to TV output, %s\n", + strerror(errno)); + } + } + break; +#endif /* PCCONS_SUPPORT */ + + default: + FatalError("Xf86SetTVOut: Unsupported console"); + break; + } + return; +} + +void +xf86SetRGBOut() +{ + switch (xf86Info.consType) + { +#ifdef PCCONS_SUPPORT + case PCCONS:{ + + if (ioctl (xf86Info.consoleFd, CONSOLE_X_TV_OFF, 0) < 0) + { + xf86Msg(X_WARNING, + "xf86SetTVOut: Could not set console to RGB output, %s\n", + strerror(errno)); + } + } + break; +#endif /* PCCONS_SUPPORT */ + + default: + FatalError("Xf86SetTVOut: Unsupported console"); + break; + } + return; +} +#endif + +#ifdef HAS_MTRR_SUPPORT +/* memory range (MTRR) support for FreeBSD */ + +/* + * This code is experimental. Some parts may be overkill, and other parts + * may be incomplete. + */ + +/* + * getAllRanges returns the full list of memory ranges with attributes set. + */ + +static struct mem_range_desc * +getAllRanges(int *nmr) +{ + struct mem_range_desc *mrd; + struct mem_range_op mro; + + /* + * Find how many ranges there are. If this fails, then the kernel + * probably doesn't have MTRR support. + */ + mro.mo_arg[0] = 0; + if (ioctl(devMemFd, MEMRANGE_GET, &mro)) + return NULL; + *nmr = mro.mo_arg[0]; + mrd = xnfalloc(*nmr * sizeof(struct mem_range_desc)); + mro.mo_arg[0] = *nmr; + mro.mo_desc = mrd; + if (ioctl(devMemFd, MEMRANGE_GET, &mro)) { + free(mrd); + return NULL; + } + return mrd; +} + +/* + * cleanMTRR removes any memory attribute that may be left by a previous + * X server. Normally there won't be any, but this takes care of the + * case where a server crashed without being able finish cleaning up. + */ + +static Bool +cleanMTRR() +{ + struct mem_range_desc *mrd; + struct mem_range_op mro; + int nmr, i; + + /* This shouldn't happen */ + if (devMemFd < 0) + return FALSE; + + if (!(mrd = getAllRanges(&nmr))) + return FALSE; + + for (i = 0; i < nmr; i++) { + if (strcmp(mrd[i].mr_owner, X_MTRR_ID) == 0 && + (mrd[i].mr_flags & MDF_ACTIVE)) { +#ifdef DEBUG + ErrorF("Clean for (0x%lx,0x%lx)\n", + (unsigned long)mrd[i].mr_base, + (unsigned long)mrd[i].mr_len); +#endif + if (mrd[i].mr_flags & MDF_FIXACTIVE) { + mro.mo_arg[0] = MEMRANGE_SET_UPDATE; + mrd[i].mr_flags = MDF_UNCACHEABLE; + } else { + mro.mo_arg[0] = MEMRANGE_SET_REMOVE; + } + mro.mo_desc = mrd + i; + ioctl(devMemFd, MEMRANGE_SET, &mro); + } + } +#ifdef DEBUG + sleep(10); +#endif + free(mrd); + return TRUE; +} + +typedef struct x_RangeRec { + struct mem_range_desc mrd; + Bool wasWC; + struct x_RangeRec * next; +} RangeRec, *RangePtr; + +static void +freeRangeList(RangePtr range) +{ + RangePtr rp; + + while (range) { + rp = range; + range = rp->next; + free(rp); + } +} + +static RangePtr +dupRangeList(RangePtr list) +{ + RangePtr new = NULL, rp, p; + + rp = list; + while (rp) { + p = xnfalloc(sizeof(RangeRec)); + *p = *rp; + p->next = new; + new = p; + rp = rp->next; + } + return new; +} + +static RangePtr +sortRangeList(RangePtr list) +{ + RangePtr rp1, rp2, copy, sorted = NULL, minp, prev, minprev; + unsigned long minBase; + + /* Sort by base address */ + rp1 = copy = dupRangeList(list); + while (rp1) { + minBase = rp1->mrd.mr_base; + minp = rp1; + minprev = NULL; + prev = rp1; + rp2 = rp1->next; + while (rp2) { + if (rp2->mrd.mr_base < minBase) { + minBase = rp2->mrd.mr_base; + minp = rp2; + minprev = prev; + } + prev = rp2; + rp2 = rp2->next; + } + if (minprev) { + minprev->next = minp->next; + rp1 = copy; + } else { + rp1 = minp->next; + } + minp->next = sorted; + sorted = minp; + } + return sorted; +} + +/* + * findRanges returns a list of ranges that overlap the specified range. + */ + +static void +findRanges(unsigned long base, unsigned long size, RangePtr *ucp, RangePtr *wcp) +{ + struct mem_range_desc *mrd; + int nmr, i; + RangePtr rp, *p; + + if (!(mrd = getAllRanges(&nmr))) + return; + + for (i = 0; i < nmr; i++) { + if ((mrd[i].mr_flags & MDF_ACTIVE) && + mrd[i].mr_base < base + size && + mrd[i].mr_base + mrd[i].mr_len > base) { + if (mrd[i].mr_flags & MDF_WRITECOMBINE) + p = wcp; + else if (mrd[i].mr_flags & MDF_UNCACHEABLE) + p = ucp; + else + continue; + rp = xnfalloc(sizeof(RangeRec)); + rp->mrd = mrd[i]; + rp->next = *p; + *p = rp; + } + } + free(mrd); +} + +/* + * This checks if the existing overlapping ranges fully cover the requested + * range. Is this overkill? + */ + +static Bool +fullCoverage(unsigned long base, unsigned long size, RangePtr overlap) +{ + RangePtr rp1, sorted = NULL; + unsigned long end; + + sorted = sortRangeList(overlap); + /* Look for gaps */ + rp1 = sorted; + end = base + size; + while (rp1) { + if (rp1->mrd.mr_base > base) { + freeRangeList(sorted); + return FALSE; + } else { + base = rp1->mrd.mr_base + rp1->mrd.mr_len; + } + if (base >= end) { + freeRangeList(sorted); + return TRUE; + } + rp1 = rp1->next; + } + freeRangeList(sorted); + return FALSE; +} + +static pointer +addWC(int screenNum, unsigned long base, unsigned long size, MessageType from) +{ + RangePtr uc = NULL, wc = NULL, retlist = NULL; + struct mem_range_desc mrd; + struct mem_range_op mro; + + findRanges(base, size, &uc, &wc); + + /* See of the full range is already WC */ + if (!uc && fullCoverage(base, size, wc)) { + xf86DrvMsg(screenNum, from, + "Write-combining range (0x%lx,0x%lx) was already set\n", + base, size); + return NULL; + } + + /* Otherwise, try to add the new range */ + mrd.mr_base = base; + mrd.mr_len = size; + strcpy(mrd.mr_owner, X_MTRR_ID); + mrd.mr_flags = MDF_WRITECOMBINE; + mro.mo_desc = &mrd; + mro.mo_arg[0] = MEMRANGE_SET_UPDATE; + if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { + xf86DrvMsg(screenNum, X_WARNING, + "Failed to set write-combining range " + "(0x%lx,0x%lx)\n", base, size); + return NULL; + } else { + xf86DrvMsg(screenNum, from, + "Write-combining range (0x%lx,0x%lx)\n", base, size); + retlist = xnfalloc(sizeof(RangeRec)); + retlist->mrd = mrd; + retlist->wasWC = FALSE; + retlist->next = NULL; + return retlist; + } +} + +static pointer +delWC(int screenNum, unsigned long base, unsigned long size, MessageType from) +{ + RangePtr uc = NULL, wc = NULL, retlist = NULL; + struct mem_range_desc mrd; + struct mem_range_op mro; + + findRanges(base, size, &uc, &wc); + + /* + * See of the full range is already not WC, or if there is full + * coverage from UC ranges. + */ + if (!wc || fullCoverage(base, size, uc)) { + xf86DrvMsg(screenNum, from, + "Write-combining range (0x%lx,0x%lx) was already clear\n", + base, size); + return NULL; + } + + /* Otherwise, try to add the new range */ + mrd.mr_base = base; + mrd.mr_len = size; + strcpy(mrd.mr_owner, X_MTRR_ID); + mrd.mr_flags = MDF_UNCACHEABLE; + mro.mo_desc = &mrd; + mro.mo_arg[0] = MEMRANGE_SET_UPDATE; + if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { + xf86DrvMsg(screenNum, X_WARNING, + "Failed to remove write-combining range " + "(0x%lx,0x%lx)\n", base, size); + /* XXX Should then remove all of the overlapping WC ranges */ + return NULL; + } else { + xf86DrvMsg(screenNum, from, + "Removed Write-combining range (0x%lx,0x%lx)\n", + base, size); + retlist = xnfalloc(sizeof(RangeRec)); + retlist->mrd = mrd; + retlist->wasWC = TRUE; + retlist->next = NULL; + return retlist; + } +} + +static pointer +setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, + MessageType from) +{ + if (enable) + return addWC(screenNum, base, size, from); + else + return delWC(screenNum, base, size, from); +} + +static void +undoWC(int screenNum, pointer list) +{ + RangePtr rp; + struct mem_range_op mro; + Bool failed; + + rp = list; + while (rp) { +#ifdef DEBUG + ErrorF("Undo for (0x%lx,0x%lx), %d\n", + (unsigned long)rp->mrd.mr_base, + (unsigned long)rp->mrd.mr_len, rp->wasWC); +#endif + failed = FALSE; + if (rp->wasWC) { + mro.mo_arg[0] = MEMRANGE_SET_UPDATE; + rp->mrd.mr_flags = MDF_WRITECOMBINE; + strcpy(rp->mrd.mr_owner, "unknown"); + } else { + mro.mo_arg[0] = MEMRANGE_SET_REMOVE; + } + mro.mo_desc = &rp->mrd; + + if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { + if (!rp->wasWC) { + mro.mo_arg[0] = MEMRANGE_SET_UPDATE; + rp->mrd.mr_flags = MDF_UNCACHEABLE; + strcpy(rp->mrd.mr_owner, "unknown"); + if (ioctl(devMemFd, MEMRANGE_SET, &mro)) + failed = TRUE; + } else + failed = TRUE; + } + if (failed) { + xf86DrvMsg(screenNum, X_WARNING, + "Failed to restore MTRR range (0x%lx,0x%lx)\n", + (unsigned long)rp->mrd.mr_base, + (unsigned long)rp->mrd.mr_len); + } + rp = rp->next; + } +} + +#endif /* HAS_MTRR_SUPPORT */ + + +#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) +static pointer +NetBSDsetWC(int screenNum, unsigned long base, unsigned long size, Bool enable, + MessageType from) +{ + struct mtrr *mtrrp; + int n; + + xf86DrvMsg(screenNum, X_WARNING, + "%s MTRR %lx - %lx\n", enable ? "set" : "remove", + base, (base + size)); + + mtrrp = xnfalloc(sizeof (struct mtrr)); + mtrrp->base = base; + mtrrp->len = size; + mtrrp->type = MTRR_TYPE_WC; + + /* + * MTRR_PRIVATE will make this MTRR get reset automatically + * if this process exits, so we have no need for an explicit + * cleanup operation when starting a new server. + */ + + if (enable) + mtrrp->flags = MTRR_VALID | MTRR_PRIVATE; + else + mtrrp->flags = 0; + n = 1; + + if (i386_set_mtrr(mtrrp, &n) < 0) { + free(mtrrp); + return NULL; + } + return mtrrp; +} + +static void +NetBSDundoWC(int screenNum, pointer list) +{ + struct mtrr *mtrrp = (struct mtrr *)list; + int n; + + if (mtrrp == NULL) + return; + n = 1; + mtrrp->flags &= ~MTRR_VALID; + i386_set_mtrr(mtrrp, &n); + free(mtrrp); +} +#endif diff --git a/xorg-server/hw/xfree86/os-support/bus/Sbus.c b/xorg-server/hw/xfree86/os-support/bus/Sbus.c index 0b6205f0b..4560ef016 100644 --- a/xorg-server/hw/xfree86/os-support/bus/Sbus.c +++ b/xorg-server/hw/xfree86/os-support/bus/Sbus.c @@ -1,690 +1,690 @@ -/* - * SBUS and OpenPROM access functions. - * - * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#ifdef sun -#include -#endif -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" - -#include "xf86sbusBus.h" -#include "xf86Sbus.h" - -int promRootNode; - -static int promFd = -1; -static int promCurrentNode; -static int promOpenCount = 0; -static int promP1275 = -1; -#define MAX_PROP 128 -#define MAX_VAL (4096-128-4) -static struct openpromio *promOpio; - -sbusDevicePtr *xf86SbusInfo = NULL; - -struct sbus_devtable sbusDeviceTable[] = { - { SBUS_DEVICE_BW2, FBTYPE_SUN2BW, "bwtwo", "sunbw2", "Sun Monochrome (bwtwo)" }, - { SBUS_DEVICE_CG2, FBTYPE_SUN2COLOR, "cgtwo", NULL, "Sun Color2 (cgtwo)" }, - { SBUS_DEVICE_CG3, FBTYPE_SUN3COLOR, "cgthree", "suncg3", "Sun Color3 (cgthree)" }, - { SBUS_DEVICE_CG4, FBTYPE_SUN4COLOR, "cgfour", NULL, "Sun Color4 (cgfour)" }, - { SBUS_DEVICE_CG6, FBTYPE_SUNFAST_COLOR, "cgsix", "suncg6", "Sun GX" }, - { SBUS_DEVICE_CG8, FBTYPE_MEMCOLOR, "cgeight", NULL, "Sun CG8/RasterOps" }, - { SBUS_DEVICE_CG12, FBTYPE_SUNGP3, "cgtwelve", NULL, "Sun GS (cgtwelve)" }, - { SBUS_DEVICE_CG14, FBTYPE_MDICOLOR, "cgfourteen", "suncg14", "Sun SX" }, - { SBUS_DEVICE_GT, FBTYPE_SUNGT, "gt", NULL, "Sun Graphics Tower" }, - { SBUS_DEVICE_MGX, -1, "mgx", NULL, "Quantum 3D MGXplus" }, - { SBUS_DEVICE_LEO, FBTYPE_SUNLEO, "leo", "sunleo", "Sun ZX or Turbo ZX" }, - { SBUS_DEVICE_TCX, FBTYPE_TCXCOLOR, "tcx", "suntcx", "Sun TCX" }, - { SBUS_DEVICE_FFB, FBTYPE_CREATOR, "ffb", "sunffb", "Sun FFB" }, - { SBUS_DEVICE_FFB, FBTYPE_CREATOR, "afb", "sunffb", "Sun Elite3D" }, - { 0, 0, NULL } -}; - -int -promGetSibling(int node) -{ - promOpio->oprom_size = sizeof(int); - - if (node == -1) return 0; - *(int *)promOpio->oprom_array = node; - if (ioctl(promFd, OPROMNEXT, promOpio) < 0) - return 0; - promCurrentNode = *(int *)promOpio->oprom_array; - return *(int *)promOpio->oprom_array; -} - -int -promGetChild(int node) -{ - promOpio->oprom_size = sizeof(int); - - if (!node || node == -1) return 0; - *(int *)promOpio->oprom_array = node; - if (ioctl(promFd, OPROMCHILD, promOpio) < 0) - return 0; - promCurrentNode = *(int *)promOpio->oprom_array; - return *(int *)promOpio->oprom_array; -} - -char * -promGetProperty(const char *prop, int *lenp) -{ - promOpio->oprom_size = MAX_VAL; - - strcpy(promOpio->oprom_array, prop); - if (ioctl(promFd, OPROMGETPROP, promOpio) < 0) - return 0; - if (lenp) *lenp = promOpio->oprom_size; - return promOpio->oprom_array; -} - -int -promGetBool(const char *prop) -{ - promOpio->oprom_size = 0; - - *(int *)promOpio->oprom_array = 0; - for (;;) { - promOpio->oprom_size = MAX_PROP; - if (ioctl(promFd, OPROMNXTPROP, promOpio) < 0) - return 0; - if (!promOpio->oprom_size) - return 0; - if (!strcmp(promOpio->oprom_array, prop)) - return 1; - } -} - -#define PROM_NODE_SIBLING 0x01 -#define PROM_NODE_PREF 0x02 -#define PROM_NODE_SBUS 0x04 -#define PROM_NODE_EBUS 0x08 -#define PROM_NODE_PCI 0x10 - -static int -promSetNode(sbusPromNodePtr pnode) -{ - int node; - - if (!pnode->node || pnode->node == -1) - return -1; - if (pnode->cookie[0] & PROM_NODE_SIBLING) - node = promGetSibling(pnode->cookie[1]); - else - node = promGetChild(pnode->cookie[1]); - if (pnode->node != node) - return -1; - return 0; -} - -static void -promIsP1275(void) -{ -#ifdef linux - FILE *f; - char buffer[1024]; - - if (promP1275 != -1) - return; - promP1275 = 0; - f = fopen("/proc/cpuinfo","r"); - if (!f) return; - while (fgets(buffer, 1024, f) != NULL) - if (!strncmp (buffer, "type", 4) && strstr (buffer, "sun4u")) { - promP1275 = 1; - break; - } - fclose(f); -#elif defined(sun) - struct utsname buffer; - - if ((uname(&buffer) >= 0) && !strcmp(buffer.machine, "sun4u")) - promP1275 = TRUE; - else - promP1275 = FALSE; -#elif defined(__FreeBSD__) - promP1275 = TRUE; -#else -#error Missing promIsP1275() function for this OS -#endif -} - -void -sparcPromClose(void) -{ - if (promOpenCount > 1) { - promOpenCount--; - return; - } - if (promFd != -1) { - close(promFd); - promFd = -1; - } - if (promOpio) { - xfree(promOpio); - promOpio = NULL; - } - promOpenCount = 0; -} - -int -sparcPromInit(void) -{ - if (promOpenCount) { - promOpenCount++; - return 0; - } - promFd = open("/dev/openprom", O_RDONLY, 0); - if (promFd == -1) - return -1; - promOpio = (struct openpromio *)xalloc(4096); - if (!promOpio) { - sparcPromClose(); - return -1; - } - promRootNode = promGetSibling(0); - if (!promRootNode) { - sparcPromClose(); - return -1; - } - promIsP1275(); - promOpenCount++; - - return 0; -} - -char * -sparcPromGetProperty(sbusPromNodePtr pnode, const char *prop, int *lenp) -{ - if (promSetNode(pnode)) - return NULL; - return promGetProperty(prop, lenp); -} - -int -sparcPromGetBool(sbusPromNodePtr pnode, const char *prop) -{ - if (promSetNode(pnode)) - return 0; - return promGetBool(prop); -} - -static char * -promWalkGetDriverName(int node, int oldnode) -{ - int nextnode; - int len; - char *prop; - int devId, i; - - prop = promGetProperty("device_type", &len); - if (prop && (len > 0)) do { - if (!strcmp(prop, "display")) { - prop = promGetProperty("name", &len); - if (!prop || len <= 0) - break; - while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',') - prop++; - for (i = 0; sbusDeviceTable[i].devId; i++) - if (!strcmp(prop, sbusDeviceTable[i].promName)) - break; - devId = sbusDeviceTable[i].devId; - if (!devId) - break; - if (sbusDeviceTable[i].driverName) - return sbusDeviceTable[i].driverName; - } - } while (0); - - nextnode = promGetChild(node); - if (nextnode) { - char *name; - name = promWalkGetDriverName(nextnode, node); - if (name) - return name; - } - - nextnode = promGetSibling(node); - if (nextnode) - return promWalkGetDriverName(nextnode, node); - return NULL; -} - -char * -sparcDriverName(void) -{ - char *name; - - if (sparcPromInit() < 0) - return NULL; - promGetSibling(0); - name = promWalkGetDriverName(promRootNode, 0); - sparcPromClose(); - return name; -} - -static void -promWalkAssignNodes(int node, int oldnode, int flags, sbusDevicePtr *devicePtrs) -{ - int nextnode; - int len, sbus = flags & PROM_NODE_SBUS; - char *prop; - int devId, i, j; - sbusPromNode pNode, pNode2; - - prop = promGetProperty("device_type", &len); - if (prop && (len > 0)) do { - if (!strcmp(prop, "display")) { - prop = promGetProperty("name", &len); - if (!prop || len <= 0) - break; - while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',') - prop++; - for (i = 0; sbusDeviceTable[i].devId; i++) - if (!strcmp(prop, sbusDeviceTable[i].promName)) - break; - devId = sbusDeviceTable[i].devId; - if (!devId) - break; - if (!sbus) { - if (devId == SBUS_DEVICE_FFB) { - /* - * All /SUNW,ffb outside of SBUS tree come before all - * /SUNW,afb outside of SBUS tree in Linux. - */ - if (!strcmp(prop, "afb")) - flags |= PROM_NODE_PREF; - } else if (devId != SBUS_DEVICE_CG14) - break; - } - for (i = 0; i < 32; i++) { - if (!devicePtrs[i] || devicePtrs[i]->devId != devId) - continue; - if (devicePtrs[i]->node.node) { - if ((devicePtrs[i]->node.cookie[0] & ~PROM_NODE_SIBLING) <= - (flags & ~PROM_NODE_SIBLING)) - continue; - for (j = i + 1, pNode = devicePtrs[i]->node; j < 32; j++) { - if (!devicePtrs[j] || devicePtrs[j]->devId != devId) - continue; - pNode2 = devicePtrs[j]->node; - devicePtrs[j]->node = pNode; - pNode = pNode2; - } - } - devicePtrs[i]->node.node = node; - devicePtrs[i]->node.cookie[0] = flags; - devicePtrs[i]->node.cookie[1] = oldnode; - break; - } - break; - } - } while (0); - - prop = promGetProperty("name", &len); - if (prop && len > 0) { - if (!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) - sbus = PROM_NODE_SBUS; - } - - nextnode = promGetChild(node); - if (nextnode) - promWalkAssignNodes(nextnode, node, sbus, devicePtrs); - - nextnode = promGetSibling(node); - if (nextnode) - promWalkAssignNodes(nextnode, node, PROM_NODE_SIBLING | sbus, devicePtrs); -} - -void -sparcPromAssignNodes(void) -{ - sbusDevicePtr psdp, *psdpp; - int n, holes = 0, i, j; - FILE *f; - sbusDevicePtr devicePtrs[32]; - - memset(devicePtrs, 0, sizeof(devicePtrs)); - for (psdpp = xf86SbusInfo, n = 0; (psdp = *psdpp); psdpp++, n++) { - if (psdp->fbNum != n) - holes = 1; - devicePtrs[psdp->fbNum] = psdp; - } - if (holes && (f = fopen("/proc/fb", "r")) != NULL) { - /* We could not open one of fb devices, check /proc/fb to see what - * were the types of the cards missed. */ - char buffer[64]; - int fbNum, devId; - static struct { - int devId; - char *prefix; - } procFbPrefixes[] = { - { SBUS_DEVICE_BW2, "BWtwo" }, - { SBUS_DEVICE_CG14, "CGfourteen" }, - { SBUS_DEVICE_CG6, "CGsix" }, - { SBUS_DEVICE_CG3, "CGthree" }, - { SBUS_DEVICE_FFB, "Creator" }, - { SBUS_DEVICE_FFB, "Elite 3D" }, - { SBUS_DEVICE_LEO, "Leo" }, - { SBUS_DEVICE_TCX, "TCX" }, - { 0, NULL }, - }; - - while (fscanf(f, "%d %63s\n", &fbNum, buffer) == 2) { - for (i = 0; procFbPrefixes[i].devId; i++) - if (! strncmp(procFbPrefixes[i].prefix, buffer, - strlen(procFbPrefixes[i].prefix))) - break; - devId = procFbPrefixes[i].devId; - if (! devId) continue; - if (devicePtrs[fbNum]) { - if (devicePtrs[fbNum]->devId != devId) - xf86ErrorF("Inconsistent /proc/fb with FBIOGATTR\n"); - } else if (!devicePtrs[fbNum]) { - devicePtrs[fbNum] = psdp = xnfcalloc(sizeof (sbusDevice), 1); - psdp->devId = devId; - psdp->fbNum = fbNum; - psdp->fd = -2; - } - } - fclose(f); - } - promGetSibling(0); - promWalkAssignNodes(promRootNode, 0, PROM_NODE_PREF, devicePtrs); - for (i = 0, j = 0; i < 32; i++) - if (devicePtrs[i] && devicePtrs[i]->fbNum == -1) - j++; - xf86SbusInfo = xnfrealloc(xf86SbusInfo, sizeof(psdp) * (n + j + 1)); - for (i = 0, psdpp = xf86SbusInfo; i < 32; i++) - if (devicePtrs[i]) { - if (devicePtrs[i]->fbNum == -1) { - memmove(psdpp + 1, psdpp, sizeof(psdpp) * (n + 1)); - *psdpp = devicePtrs[i]; - } else - n--; - } -} - -static char * -promGetReg(int type) -{ - char *prop; - int len; - static char regstr[40]; - - regstr[0] = 0; - prop = promGetProperty("reg", &len); - if (prop && len >= 4) { - unsigned int *reg = (unsigned int *)prop; - if (!promP1275 || (type == PROM_NODE_SBUS) || (type == PROM_NODE_EBUS)) - sprintf (regstr, "@%x,%x", reg[0], reg[1]); - else if (type == PROM_NODE_PCI) { - if ((reg[0] >> 8) & 7) - sprintf (regstr, "@%x,%x", (reg[0] >> 11) & 0x1f, (reg[0] >> 8) & 7); - else - sprintf (regstr, "@%x", (reg[0] >> 11) & 0x1f); - } else if (len == 4) - sprintf (regstr, "@%x", reg[0]); - else { - unsigned int regs[2]; - - /* Things get more complicated on UPA. If upa-portid exists, - then address is @upa-portid,second-int-in-reg, otherwise - it is @first-int-in-reg/16,second-int-in-reg (well, probably - upa-portid always exists, but just to be safe). */ - memcpy (regs, reg, sizeof(regs)); - prop = promGetProperty("upa-portid", &len); - if (prop && len == 4) { - reg = (unsigned int *)prop; - sprintf (regstr, "@%x,%x", reg[0], regs[1]); - } else - sprintf (regstr, "@%x,%x", regs[0] >> 4, regs[1]); - } - } - return regstr; -} - -static int -promWalkNode2Pathname(char *path, int parent, int node, int searchNode, int type) -{ - int nextnode; - int len, ntype = type; - char *prop, *p; - - prop = promGetProperty("name", &len); - *path = '/'; - if (!prop || len <= 0) - return 0; - if ((!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) && !type) - ntype = PROM_NODE_SBUS; - else if (!strcmp(prop, "ebus") && type == PROM_NODE_PCI) - ntype = PROM_NODE_EBUS; - else if (!strcmp(prop, "pci") && !type) - ntype = PROM_NODE_PCI; - strcpy (path + 1, prop); - p = promGetReg(type); - if (*p) - strcat (path, p); - if (node == searchNode) - return 1; - nextnode = promGetChild(node); - if (nextnode && - promWalkNode2Pathname(strchr(path, 0), node, nextnode, searchNode, ntype)) - return 1; - nextnode = promGetSibling(node); - if (nextnode && - promWalkNode2Pathname(path, parent, nextnode, searchNode, type)) - return 1; - return 0; -} - -char * -sparcPromNode2Pathname(sbusPromNodePtr pnode) -{ - char *ret; - - if (!pnode->node) return NULL; - ret = xalloc(4096); - if (!ret) return NULL; - if (promWalkNode2Pathname(ret, promRootNode, promGetChild(promRootNode), pnode->node, 0)) - return ret; - xfree(ret); - return NULL; -} - -static int -promWalkPathname2Node(char *name, char *regstr, int parent, int type) -{ - int len, node, ret; - char *prop, *p; - - for (;;) { - prop = promGetProperty("name", &len); - if (!prop || len <= 0) - return 0; - if ((!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) && !type) - type = PROM_NODE_SBUS; - else if (!strcmp(prop, "ebus") && type == PROM_NODE_PCI) - type = PROM_NODE_EBUS; - else if (!strcmp(prop, "pci") && !type) - type = PROM_NODE_PCI; - for (node = promGetChild(parent); node; node = promGetSibling(node)) { - prop = promGetProperty("name", &len); - if (!prop || len <= 0) - continue; - if (*name && strcmp(name, prop)) - continue; - if (*regstr) { - p = promGetReg(type); - if (! *p || strcmp(p + 1, regstr)) - continue; - } - break; - } - if (!node) { - for (node = promGetChild(parent); node; node = promGetSibling(node)) { - ret = promWalkPathname2Node(name, regstr, node, type); - if (ret) return ret; - } - return 0; - } - name = strchr(regstr, 0) + 1; - if (! *name) - return node; - p = strchr(name, '/'); - if (p) - *p = 0; - else - p = strchr(name, 0); - regstr = strchr(name, '@'); - if (regstr) - *regstr++ = 0; - else - regstr = p; - if (name == regstr) - return 0; - parent = node; - } -} - -int -sparcPromPathname2Node(const char *pathName) -{ - int i; - char *name, *regstr, *p; - - i = strlen(pathName); - name = xalloc(i + 2); - if (! name) return 0; - strcpy (name, pathName); - name [i + 1] = 0; - if (name[0] != '/') - return 0; - p = strchr(name + 1, '/'); - if (p) - *p = 0; - else - p = strchr(name, 0); - regstr = strchr(name, '@'); - if (regstr) - *regstr++ = 0; - else - regstr = p; - if (name + 1 == regstr) - return 0; - promGetSibling(0); - i = promWalkPathname2Node(name + 1, regstr, promRootNode, 0); - xfree(name); - return i; -} - -pointer -xf86MapSbusMem(sbusDevicePtr psdp, unsigned long offset, unsigned long size) -{ - pointer ret; - unsigned long pagemask = getpagesize() - 1; - unsigned long off = offset & ~pagemask; - unsigned long len = ((offset + size + pagemask) & ~pagemask) - off; - - if (psdp->fd == -1) { - psdp->fd = open(psdp->device, O_RDWR); - if (psdp->fd == -1) - return NULL; - } else if (psdp->fd < 0) - return NULL; - - ret = (pointer) mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, - psdp->fd, off); - if (ret == (pointer) -1) { - ret = (pointer) mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, - psdp->fd, off); - } - if (ret == (pointer) -1) - return NULL; - - return (char *)ret + (offset - off); -} - -void -xf86UnmapSbusMem(sbusDevicePtr psdp, pointer addr, unsigned long size) -{ - unsigned long mask = getpagesize() - 1; - unsigned long base = (unsigned long)addr & ~mask; - unsigned long len = (((unsigned long)addr + size + mask) & ~mask) - base; - - munmap ((pointer)base, len); -} - -/* Tell OS that we are driving the HW cursor ourselves. */ -void -xf86SbusHideOsHwCursor(sbusDevicePtr psdp) -{ - struct fbcursor fbcursor; - unsigned char zeros[8]; - - memset(&fbcursor, 0, sizeof(fbcursor)); - memset(&zeros, 0, sizeof(zeros)); - fbcursor.cmap.count = 2; - fbcursor.cmap.red = zeros; - fbcursor.cmap.green = zeros; - fbcursor.cmap.blue = zeros; - fbcursor.image = (char *)zeros; - fbcursor.mask = (char *)zeros; - fbcursor.size.x = 32; - fbcursor.size.y = 1; - fbcursor.set = FB_CUR_SETALL; - ioctl(psdp->fd, FBIOSCURSOR, &fbcursor); -} - -/* Set HW cursor colormap. */ -void -xf86SbusSetOsHwCursorCmap(sbusDevicePtr psdp, int bg, int fg) -{ - struct fbcursor fbcursor; - unsigned char red[2], green[2], blue[2]; - - memset(&fbcursor, 0, sizeof(fbcursor)); - red[0] = bg >> 16; - green[0] = bg >> 8; - blue[0] = bg; - red[1] = fg >> 16; - green[1] = fg >> 8; - blue[1] = fg; - fbcursor.cmap.count = 2; - fbcursor.cmap.red = red; - fbcursor.cmap.green = green; - fbcursor.cmap.blue = blue; - fbcursor.set = FB_CUR_SETCMAP; - ioctl(psdp->fd, FBIOSCURSOR, &fbcursor); -} +/* + * SBUS and OpenPROM access functions. + * + * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#ifdef sun +#include +#endif +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +#include "xf86sbusBus.h" +#include "xf86Sbus.h" + +int promRootNode; + +static int promFd = -1; +static int promCurrentNode; +static int promOpenCount = 0; +static int promP1275 = -1; +#define MAX_PROP 128 +#define MAX_VAL (4096-128-4) +static struct openpromio *promOpio; + +sbusDevicePtr *xf86SbusInfo = NULL; + +struct sbus_devtable sbusDeviceTable[] = { + { SBUS_DEVICE_BW2, FBTYPE_SUN2BW, "bwtwo", "sunbw2", "Sun Monochrome (bwtwo)" }, + { SBUS_DEVICE_CG2, FBTYPE_SUN2COLOR, "cgtwo", NULL, "Sun Color2 (cgtwo)" }, + { SBUS_DEVICE_CG3, FBTYPE_SUN3COLOR, "cgthree", "suncg3", "Sun Color3 (cgthree)" }, + { SBUS_DEVICE_CG4, FBTYPE_SUN4COLOR, "cgfour", NULL, "Sun Color4 (cgfour)" }, + { SBUS_DEVICE_CG6, FBTYPE_SUNFAST_COLOR, "cgsix", "suncg6", "Sun GX" }, + { SBUS_DEVICE_CG8, FBTYPE_MEMCOLOR, "cgeight", NULL, "Sun CG8/RasterOps" }, + { SBUS_DEVICE_CG12, FBTYPE_SUNGP3, "cgtwelve", NULL, "Sun GS (cgtwelve)" }, + { SBUS_DEVICE_CG14, FBTYPE_MDICOLOR, "cgfourteen", "suncg14", "Sun SX" }, + { SBUS_DEVICE_GT, FBTYPE_SUNGT, "gt", NULL, "Sun Graphics Tower" }, + { SBUS_DEVICE_MGX, -1, "mgx", NULL, "Quantum 3D MGXplus" }, + { SBUS_DEVICE_LEO, FBTYPE_SUNLEO, "leo", "sunleo", "Sun ZX or Turbo ZX" }, + { SBUS_DEVICE_TCX, FBTYPE_TCXCOLOR, "tcx", "suntcx", "Sun TCX" }, + { SBUS_DEVICE_FFB, FBTYPE_CREATOR, "ffb", "sunffb", "Sun FFB" }, + { SBUS_DEVICE_FFB, FBTYPE_CREATOR, "afb", "sunffb", "Sun Elite3D" }, + { 0, 0, NULL } +}; + +int +promGetSibling(int node) +{ + promOpio->oprom_size = sizeof(int); + + if (node == -1) return 0; + *(int *)promOpio->oprom_array = node; + if (ioctl(promFd, OPROMNEXT, promOpio) < 0) + return 0; + promCurrentNode = *(int *)promOpio->oprom_array; + return *(int *)promOpio->oprom_array; +} + +int +promGetChild(int node) +{ + promOpio->oprom_size = sizeof(int); + + if (!node || node == -1) return 0; + *(int *)promOpio->oprom_array = node; + if (ioctl(promFd, OPROMCHILD, promOpio) < 0) + return 0; + promCurrentNode = *(int *)promOpio->oprom_array; + return *(int *)promOpio->oprom_array; +} + +char * +promGetProperty(const char *prop, int *lenp) +{ + promOpio->oprom_size = MAX_VAL; + + strcpy(promOpio->oprom_array, prop); + if (ioctl(promFd, OPROMGETPROP, promOpio) < 0) + return 0; + if (lenp) *lenp = promOpio->oprom_size; + return promOpio->oprom_array; +} + +int +promGetBool(const char *prop) +{ + promOpio->oprom_size = 0; + + *(int *)promOpio->oprom_array = 0; + for (;;) { + promOpio->oprom_size = MAX_PROP; + if (ioctl(promFd, OPROMNXTPROP, promOpio) < 0) + return 0; + if (!promOpio->oprom_size) + return 0; + if (!strcmp(promOpio->oprom_array, prop)) + return 1; + } +} + +#define PROM_NODE_SIBLING 0x01 +#define PROM_NODE_PREF 0x02 +#define PROM_NODE_SBUS 0x04 +#define PROM_NODE_EBUS 0x08 +#define PROM_NODE_PCI 0x10 + +static int +promSetNode(sbusPromNodePtr pnode) +{ + int node; + + if (!pnode->node || pnode->node == -1) + return -1; + if (pnode->cookie[0] & PROM_NODE_SIBLING) + node = promGetSibling(pnode->cookie[1]); + else + node = promGetChild(pnode->cookie[1]); + if (pnode->node != node) + return -1; + return 0; +} + +static void +promIsP1275(void) +{ +#ifdef linux + FILE *f; + char buffer[1024]; + + if (promP1275 != -1) + return; + promP1275 = 0; + f = fopen("/proc/cpuinfo","r"); + if (!f) return; + while (fgets(buffer, 1024, f) != NULL) + if (!strncmp (buffer, "type", 4) && strstr (buffer, "sun4u")) { + promP1275 = 1; + break; + } + fclose(f); +#elif defined(sun) + struct utsname buffer; + + if ((uname(&buffer) >= 0) && !strcmp(buffer.machine, "sun4u")) + promP1275 = TRUE; + else + promP1275 = FALSE; +#elif defined(__FreeBSD__) + promP1275 = TRUE; +#else +#error Missing promIsP1275() function for this OS +#endif +} + +void +sparcPromClose(void) +{ + if (promOpenCount > 1) { + promOpenCount--; + return; + } + if (promFd != -1) { + close(promFd); + promFd = -1; + } + if (promOpio) { + free(promOpio); + promOpio = NULL; + } + promOpenCount = 0; +} + +int +sparcPromInit(void) +{ + if (promOpenCount) { + promOpenCount++; + return 0; + } + promFd = open("/dev/openprom", O_RDONLY, 0); + if (promFd == -1) + return -1; + promOpio = (struct openpromio *)malloc(4096); + if (!promOpio) { + sparcPromClose(); + return -1; + } + promRootNode = promGetSibling(0); + if (!promRootNode) { + sparcPromClose(); + return -1; + } + promIsP1275(); + promOpenCount++; + + return 0; +} + +char * +sparcPromGetProperty(sbusPromNodePtr pnode, const char *prop, int *lenp) +{ + if (promSetNode(pnode)) + return NULL; + return promGetProperty(prop, lenp); +} + +int +sparcPromGetBool(sbusPromNodePtr pnode, const char *prop) +{ + if (promSetNode(pnode)) + return 0; + return promGetBool(prop); +} + +static char * +promWalkGetDriverName(int node, int oldnode) +{ + int nextnode; + int len; + char *prop; + int devId, i; + + prop = promGetProperty("device_type", &len); + if (prop && (len > 0)) do { + if (!strcmp(prop, "display")) { + prop = promGetProperty("name", &len); + if (!prop || len <= 0) + break; + while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',') + prop++; + for (i = 0; sbusDeviceTable[i].devId; i++) + if (!strcmp(prop, sbusDeviceTable[i].promName)) + break; + devId = sbusDeviceTable[i].devId; + if (!devId) + break; + if (sbusDeviceTable[i].driverName) + return sbusDeviceTable[i].driverName; + } + } while (0); + + nextnode = promGetChild(node); + if (nextnode) { + char *name; + name = promWalkGetDriverName(nextnode, node); + if (name) + return name; + } + + nextnode = promGetSibling(node); + if (nextnode) + return promWalkGetDriverName(nextnode, node); + return NULL; +} + +char * +sparcDriverName(void) +{ + char *name; + + if (sparcPromInit() < 0) + return NULL; + promGetSibling(0); + name = promWalkGetDriverName(promRootNode, 0); + sparcPromClose(); + return name; +} + +static void +promWalkAssignNodes(int node, int oldnode, int flags, sbusDevicePtr *devicePtrs) +{ + int nextnode; + int len, sbus = flags & PROM_NODE_SBUS; + char *prop; + int devId, i, j; + sbusPromNode pNode, pNode2; + + prop = promGetProperty("device_type", &len); + if (prop && (len > 0)) do { + if (!strcmp(prop, "display")) { + prop = promGetProperty("name", &len); + if (!prop || len <= 0) + break; + while ((*prop >= 'A' && *prop <= 'Z') || *prop == ',') + prop++; + for (i = 0; sbusDeviceTable[i].devId; i++) + if (!strcmp(prop, sbusDeviceTable[i].promName)) + break; + devId = sbusDeviceTable[i].devId; + if (!devId) + break; + if (!sbus) { + if (devId == SBUS_DEVICE_FFB) { + /* + * All /SUNW,ffb outside of SBUS tree come before all + * /SUNW,afb outside of SBUS tree in Linux. + */ + if (!strcmp(prop, "afb")) + flags |= PROM_NODE_PREF; + } else if (devId != SBUS_DEVICE_CG14) + break; + } + for (i = 0; i < 32; i++) { + if (!devicePtrs[i] || devicePtrs[i]->devId != devId) + continue; + if (devicePtrs[i]->node.node) { + if ((devicePtrs[i]->node.cookie[0] & ~PROM_NODE_SIBLING) <= + (flags & ~PROM_NODE_SIBLING)) + continue; + for (j = i + 1, pNode = devicePtrs[i]->node; j < 32; j++) { + if (!devicePtrs[j] || devicePtrs[j]->devId != devId) + continue; + pNode2 = devicePtrs[j]->node; + devicePtrs[j]->node = pNode; + pNode = pNode2; + } + } + devicePtrs[i]->node.node = node; + devicePtrs[i]->node.cookie[0] = flags; + devicePtrs[i]->node.cookie[1] = oldnode; + break; + } + break; + } + } while (0); + + prop = promGetProperty("name", &len); + if (prop && len > 0) { + if (!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) + sbus = PROM_NODE_SBUS; + } + + nextnode = promGetChild(node); + if (nextnode) + promWalkAssignNodes(nextnode, node, sbus, devicePtrs); + + nextnode = promGetSibling(node); + if (nextnode) + promWalkAssignNodes(nextnode, node, PROM_NODE_SIBLING | sbus, devicePtrs); +} + +void +sparcPromAssignNodes(void) +{ + sbusDevicePtr psdp, *psdpp; + int n, holes = 0, i, j; + FILE *f; + sbusDevicePtr devicePtrs[32]; + + memset(devicePtrs, 0, sizeof(devicePtrs)); + for (psdpp = xf86SbusInfo, n = 0; (psdp = *psdpp); psdpp++, n++) { + if (psdp->fbNum != n) + holes = 1; + devicePtrs[psdp->fbNum] = psdp; + } + if (holes && (f = fopen("/proc/fb", "r")) != NULL) { + /* We could not open one of fb devices, check /proc/fb to see what + * were the types of the cards missed. */ + char buffer[64]; + int fbNum, devId; + static struct { + int devId; + char *prefix; + } procFbPrefixes[] = { + { SBUS_DEVICE_BW2, "BWtwo" }, + { SBUS_DEVICE_CG14, "CGfourteen" }, + { SBUS_DEVICE_CG6, "CGsix" }, + { SBUS_DEVICE_CG3, "CGthree" }, + { SBUS_DEVICE_FFB, "Creator" }, + { SBUS_DEVICE_FFB, "Elite 3D" }, + { SBUS_DEVICE_LEO, "Leo" }, + { SBUS_DEVICE_TCX, "TCX" }, + { 0, NULL }, + }; + + while (fscanf(f, "%d %63s\n", &fbNum, buffer) == 2) { + for (i = 0; procFbPrefixes[i].devId; i++) + if (! strncmp(procFbPrefixes[i].prefix, buffer, + strlen(procFbPrefixes[i].prefix))) + break; + devId = procFbPrefixes[i].devId; + if (! devId) continue; + if (devicePtrs[fbNum]) { + if (devicePtrs[fbNum]->devId != devId) + xf86ErrorF("Inconsistent /proc/fb with FBIOGATTR\n"); + } else if (!devicePtrs[fbNum]) { + devicePtrs[fbNum] = psdp = xnfcalloc(sizeof (sbusDevice), 1); + psdp->devId = devId; + psdp->fbNum = fbNum; + psdp->fd = -2; + } + } + fclose(f); + } + promGetSibling(0); + promWalkAssignNodes(promRootNode, 0, PROM_NODE_PREF, devicePtrs); + for (i = 0, j = 0; i < 32; i++) + if (devicePtrs[i] && devicePtrs[i]->fbNum == -1) + j++; + xf86SbusInfo = xnfrealloc(xf86SbusInfo, sizeof(psdp) * (n + j + 1)); + for (i = 0, psdpp = xf86SbusInfo; i < 32; i++) + if (devicePtrs[i]) { + if (devicePtrs[i]->fbNum == -1) { + memmove(psdpp + 1, psdpp, sizeof(psdpp) * (n + 1)); + *psdpp = devicePtrs[i]; + } else + n--; + } +} + +static char * +promGetReg(int type) +{ + char *prop; + int len; + static char regstr[40]; + + regstr[0] = 0; + prop = promGetProperty("reg", &len); + if (prop && len >= 4) { + unsigned int *reg = (unsigned int *)prop; + if (!promP1275 || (type == PROM_NODE_SBUS) || (type == PROM_NODE_EBUS)) + sprintf (regstr, "@%x,%x", reg[0], reg[1]); + else if (type == PROM_NODE_PCI) { + if ((reg[0] >> 8) & 7) + sprintf (regstr, "@%x,%x", (reg[0] >> 11) & 0x1f, (reg[0] >> 8) & 7); + else + sprintf (regstr, "@%x", (reg[0] >> 11) & 0x1f); + } else if (len == 4) + sprintf (regstr, "@%x", reg[0]); + else { + unsigned int regs[2]; + + /* Things get more complicated on UPA. If upa-portid exists, + then address is @upa-portid,second-int-in-reg, otherwise + it is @first-int-in-reg/16,second-int-in-reg (well, probably + upa-portid always exists, but just to be safe). */ + memcpy (regs, reg, sizeof(regs)); + prop = promGetProperty("upa-portid", &len); + if (prop && len == 4) { + reg = (unsigned int *)prop; + sprintf (regstr, "@%x,%x", reg[0], regs[1]); + } else + sprintf (regstr, "@%x,%x", regs[0] >> 4, regs[1]); + } + } + return regstr; +} + +static int +promWalkNode2Pathname(char *path, int parent, int node, int searchNode, int type) +{ + int nextnode; + int len, ntype = type; + char *prop, *p; + + prop = promGetProperty("name", &len); + *path = '/'; + if (!prop || len <= 0) + return 0; + if ((!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) && !type) + ntype = PROM_NODE_SBUS; + else if (!strcmp(prop, "ebus") && type == PROM_NODE_PCI) + ntype = PROM_NODE_EBUS; + else if (!strcmp(prop, "pci") && !type) + ntype = PROM_NODE_PCI; + strcpy (path + 1, prop); + p = promGetReg(type); + if (*p) + strcat (path, p); + if (node == searchNode) + return 1; + nextnode = promGetChild(node); + if (nextnode && + promWalkNode2Pathname(strchr(path, 0), node, nextnode, searchNode, ntype)) + return 1; + nextnode = promGetSibling(node); + if (nextnode && + promWalkNode2Pathname(path, parent, nextnode, searchNode, type)) + return 1; + return 0; +} + +char * +sparcPromNode2Pathname(sbusPromNodePtr pnode) +{ + char *ret; + + if (!pnode->node) return NULL; + ret = malloc(4096); + if (!ret) return NULL; + if (promWalkNode2Pathname(ret, promRootNode, promGetChild(promRootNode), pnode->node, 0)) + return ret; + free(ret); + return NULL; +} + +static int +promWalkPathname2Node(char *name, char *regstr, int parent, int type) +{ + int len, node, ret; + char *prop, *p; + + for (;;) { + prop = promGetProperty("name", &len); + if (!prop || len <= 0) + return 0; + if ((!strcmp(prop, "sbus") || !strcmp(prop, "sbi")) && !type) + type = PROM_NODE_SBUS; + else if (!strcmp(prop, "ebus") && type == PROM_NODE_PCI) + type = PROM_NODE_EBUS; + else if (!strcmp(prop, "pci") && !type) + type = PROM_NODE_PCI; + for (node = promGetChild(parent); node; node = promGetSibling(node)) { + prop = promGetProperty("name", &len); + if (!prop || len <= 0) + continue; + if (*name && strcmp(name, prop)) + continue; + if (*regstr) { + p = promGetReg(type); + if (! *p || strcmp(p + 1, regstr)) + continue; + } + break; + } + if (!node) { + for (node = promGetChild(parent); node; node = promGetSibling(node)) { + ret = promWalkPathname2Node(name, regstr, node, type); + if (ret) return ret; + } + return 0; + } + name = strchr(regstr, 0) + 1; + if (! *name) + return node; + p = strchr(name, '/'); + if (p) + *p = 0; + else + p = strchr(name, 0); + regstr = strchr(name, '@'); + if (regstr) + *regstr++ = 0; + else + regstr = p; + if (name == regstr) + return 0; + parent = node; + } +} + +int +sparcPromPathname2Node(const char *pathName) +{ + int i; + char *name, *regstr, *p; + + i = strlen(pathName); + name = malloc(i + 2); + if (! name) return 0; + strcpy (name, pathName); + name [i + 1] = 0; + if (name[0] != '/') + return 0; + p = strchr(name + 1, '/'); + if (p) + *p = 0; + else + p = strchr(name, 0); + regstr = strchr(name, '@'); + if (regstr) + *regstr++ = 0; + else + regstr = p; + if (name + 1 == regstr) + return 0; + promGetSibling(0); + i = promWalkPathname2Node(name + 1, regstr, promRootNode, 0); + free(name); + return i; +} + +pointer +xf86MapSbusMem(sbusDevicePtr psdp, unsigned long offset, unsigned long size) +{ + pointer ret; + unsigned long pagemask = getpagesize() - 1; + unsigned long off = offset & ~pagemask; + unsigned long len = ((offset + size + pagemask) & ~pagemask) - off; + + if (psdp->fd == -1) { + psdp->fd = open(psdp->device, O_RDWR); + if (psdp->fd == -1) + return NULL; + } else if (psdp->fd < 0) + return NULL; + + ret = (pointer) mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, + psdp->fd, off); + if (ret == (pointer) -1) { + ret = (pointer) mmap (NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, + psdp->fd, off); + } + if (ret == (pointer) -1) + return NULL; + + return (char *)ret + (offset - off); +} + +void +xf86UnmapSbusMem(sbusDevicePtr psdp, pointer addr, unsigned long size) +{ + unsigned long mask = getpagesize() - 1; + unsigned long base = (unsigned long)addr & ~mask; + unsigned long len = (((unsigned long)addr + size + mask) & ~mask) - base; + + munmap ((pointer)base, len); +} + +/* Tell OS that we are driving the HW cursor ourselves. */ +void +xf86SbusHideOsHwCursor(sbusDevicePtr psdp) +{ + struct fbcursor fbcursor; + unsigned char zeros[8]; + + memset(&fbcursor, 0, sizeof(fbcursor)); + memset(&zeros, 0, sizeof(zeros)); + fbcursor.cmap.count = 2; + fbcursor.cmap.red = zeros; + fbcursor.cmap.green = zeros; + fbcursor.cmap.blue = zeros; + fbcursor.image = (char *)zeros; + fbcursor.mask = (char *)zeros; + fbcursor.size.x = 32; + fbcursor.size.y = 1; + fbcursor.set = FB_CUR_SETALL; + ioctl(psdp->fd, FBIOSCURSOR, &fbcursor); +} + +/* Set HW cursor colormap. */ +void +xf86SbusSetOsHwCursorCmap(sbusDevicePtr psdp, int bg, int fg) +{ + struct fbcursor fbcursor; + unsigned char red[2], green[2], blue[2]; + + memset(&fbcursor, 0, sizeof(fbcursor)); + red[0] = bg >> 16; + green[0] = bg >> 8; + blue[0] = bg; + red[1] = fg >> 16; + green[1] = fg >> 8; + blue[1] = fg; + fbcursor.cmap.count = 2; + fbcursor.cmap.red = red; + fbcursor.cmap.green = green; + fbcursor.cmap.blue = blue; + fbcursor.set = FB_CUR_SETCMAP; + ioctl(psdp->fd, FBIOSCURSOR, &fbcursor); +} diff --git a/xorg-server/hw/xfree86/os-support/linux/int10/linux.c b/xorg-server/hw/xfree86/os-support/linux/int10/linux.c index 0cf3507c3..e3c8a984d 100644 --- a/xorg-server/hw/xfree86/os-support/linux/int10/linux.c +++ b/xorg-server/hw/xfree86/os-support/linux/int10/linux.c @@ -1,544 +1,544 @@ -/* - * linux specific part of the int10 module - * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2008 Egbert Eich - */ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86_OSproc.h" -#include "xf86Pci.h" -#include "compiler.h" -#define _INT10_PRIVATE -#include "xf86int10.h" -#ifdef __sparc__ -#define DEV_MEM "/dev/fb" -#else -#define DEV_MEM "/dev/mem" -#endif -#define ALLOC_ENTRIES(x) ((V_RAM / x) - 1) -#define SHMERRORPTR (pointer)(-1) - -#include -#include -#include -#include -#include -#include -#include - -static int counter = 0; -static unsigned long int10Generation = 0; - -static CARD8 read_b(xf86Int10InfoPtr pInt, int addr); -static CARD16 read_w(xf86Int10InfoPtr pInt, int addr); -static CARD32 read_l(xf86Int10InfoPtr pInt, int addr); -static void write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val); -static void write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val); -static void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val); - -int10MemRec linuxMem = { - read_b, - read_w, - read_l, - write_b, - write_w, - write_l -}; - -typedef struct { - int lowMem; - int highMem; - char* base; - char* base_high; - int screen; - char* alloc; -} linuxInt10Priv; - -#if defined DoSubModules - -typedef enum { - INT10_NOT_LOADED, - INT10_LOADED_VM86, - INT10_LOADED_X86EMU, - INT10_LOAD_FAILED -} Int10LinuxSubModuleState; - -static Int10LinuxSubModuleState loadedSubModule = INT10_NOT_LOADED; - -static Int10LinuxSubModuleState int10LinuxLoadSubModule(ScrnInfoPtr pScrn); - -#endif /* DoSubModules */ - -xf86Int10InfoPtr -xf86ExtendedInitInt10(int entityIndex, int Flags) -{ - xf86Int10InfoPtr pInt = NULL; - int screen; - int fd; - static void* vidMem = NULL; - static void* sysMem = NULL; - void* vMem = NULL; - void *options = NULL; - int low_mem; - int high_mem = -1; - char *base = SHMERRORPTR; - char *base_high = SHMERRORPTR; - int pagesize; - memType cs; - legacyVGARec vga; - Bool videoBiosMapped = FALSE; - - if (int10Generation != serverGeneration) { - counter = 0; - int10Generation = serverGeneration; - } - - screen = (xf86FindScreenForEntity(entityIndex))->scrnIndex; - - options = xf86HandleInt10Options(xf86Screens[screen],entityIndex); - - if (int10skip(options)) { - xfree(options); - return NULL; - } - -#if defined DoSubModules - if (loadedSubModule == INT10_NOT_LOADED) - loadedSubModule = int10LinuxLoadSubModule(xf86Screens[screen]); - - if (loadedSubModule == INT10_LOAD_FAILED) - return NULL; -#endif - - if ((!vidMem) || (!sysMem)) { - if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) { - if (!sysMem) { - DebugF("Mapping sys bios area\n"); - if ((sysMem = mmap((void *)(SYS_BIOS), BIOS_SIZE, - PROT_READ | PROT_EXEC, - MAP_SHARED | MAP_FIXED, fd, SYS_BIOS)) - == MAP_FAILED) { - xf86DrvMsg(screen, X_ERROR, "Cannot map SYS BIOS\n"); - close(fd); - goto error0; - } - } - if (!vidMem) { - DebugF("Mapping VRAM area\n"); - if ((vidMem = mmap((void *)(V_RAM), VRAM_SIZE, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_SHARED | MAP_FIXED, fd, V_RAM)) - == MAP_FAILED) { - xf86DrvMsg(screen, X_ERROR, "Cannot map V_RAM\n"); - close(fd); - goto error0; - } - } - close(fd); - } else { - xf86DrvMsg(screen, X_ERROR, "Cannot open %s\n", DEV_MEM); - goto error0; - } - } - - pInt = (xf86Int10InfoPtr)xnfcalloc(1, sizeof(xf86Int10InfoRec)); - pInt->scrnIndex = screen; - pInt->entityIndex = entityIndex; - pInt->dev = xf86GetPciInfoForEntity(entityIndex); - - if (!xf86Int10ExecSetup(pInt)) - goto error0; - pInt->mem = &linuxMem; - pagesize = getpagesize(); - pInt->private = (pointer)xnfcalloc(1, sizeof(linuxInt10Priv)); - ((linuxInt10Priv*)pInt->private)->screen = screen; - ((linuxInt10Priv*)pInt->private)->alloc = - (pointer)xnfcalloc(1, ALLOC_ENTRIES(pagesize)); - - if (!xf86IsEntityPrimary(entityIndex)) { - DebugF("Mapping high memory area\n"); - if ((high_mem = shmget(counter++, HIGH_MEM_SIZE, - IPC_CREAT | SHM_R | SHM_W)) == -1) { - if (errno == ENOSYS) - xf86DrvMsg(screen, X_ERROR, "shmget error\n Please reconfigure" - " your kernel to include System V IPC support\n"); - else - xf86DrvMsg(screen, X_ERROR, - "shmget(highmem) error: %s\n",strerror(errno)); - goto error1; - } - } else { - DebugF("Mapping Video BIOS\n"); - videoBiosMapped = TRUE; - if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) { - if ((vMem = mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_SHARED | MAP_FIXED, fd, V_BIOS)) - == MAP_FAILED) { - xf86DrvMsg(screen, X_ERROR, "Cannot map V_BIOS\n"); - close(fd); - goto error1; - } - close (fd); - } else - goto error1; - } - ((linuxInt10Priv*)pInt->private)->highMem = high_mem; - - DebugF("Mapping 640kB area\n"); - if ((low_mem = shmget(counter++, V_RAM, - IPC_CREAT | SHM_R | SHM_W)) == -1) { - xf86DrvMsg(screen, X_ERROR, - "shmget(lowmem) error: %s\n",strerror(errno)); - goto error2; - } - - ((linuxInt10Priv*)pInt->private)->lowMem = low_mem; - base = shmat(low_mem, 0, 0); - if (base == SHMERRORPTR) { - xf86DrvMsg(screen, X_ERROR, - "shmat(low_mem) error: %s\n",strerror(errno)); - goto error3; - } - ((linuxInt10Priv *)pInt->private)->base = base; - if (high_mem > -1) { - base_high = shmat(high_mem, 0, 0); - if (base_high == SHMERRORPTR) { - xf86DrvMsg(screen, X_ERROR, - "shmat(high_mem) error: %s\n",strerror(errno)); - goto error3; - } - ((linuxInt10Priv*)pInt->private)->base_high = base_high; - } else - ((linuxInt10Priv*)pInt->private)->base_high = NULL; - - if (!MapCurrentInt10(pInt)) - goto error3; - - Int10Current = pInt; - - DebugF("Mapping int area\n"); - if (xf86ReadBIOS(0, 0, (unsigned char *)0, LOW_PAGE_SIZE) < 0) { - xf86DrvMsg(screen, X_ERROR, "Cannot read int vect\n"); - goto error3; - } - DebugF("done\n"); - /* - * Read in everything between V_BIOS and SYS_BIOS as some system BIOSes - * have executable code there. Note that xf86ReadBIOS() can only bring in - * 64K bytes at a time. - */ - if (!videoBiosMapped) { - memset((pointer)V_BIOS, 0, SYS_BIOS - V_BIOS); - DebugF("Reading BIOS\n"); - for (cs = V_BIOS; cs < SYS_BIOS; cs += V_BIOS_SIZE) - if (xf86ReadBIOS(cs, 0, (pointer)cs, V_BIOS_SIZE) < V_BIOS_SIZE) - xf86DrvMsg(screen, X_WARNING, - "Unable to retrieve all of segment 0x%06lX.\n", - (long)cs); - DebugF("done\n"); - } - - if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) { - if (!xf86int10GetBiosSegment(pInt, NULL)) - goto error3; - - set_return_trap(pInt); -#ifdef _PC - pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); - if (! (pInt->Flags & SET_BIOS_SCRATCH)) - pInt->Flags &= ~RESTORE_BIOS_SCRATCH; - xf86Int10SaveRestoreBIOSVars(pInt, TRUE); -#endif - } else { - const BusType location_type = xf86int10GetBiosLocationType(pInt); - - switch (location_type) { - case BUS_PCI: { - int err; - struct pci_device *rom_device = - xf86GetPciInfoForEntity(pInt->entityIndex); - -#if HAVE_PCI_DEVICE_ENABLE - pci_device_enable(rom_device); -#endif - - err = pci_device_read_rom(rom_device, (unsigned char *)(V_BIOS)); - if (err) { - xf86DrvMsg(screen,X_ERROR,"Cannot read V_BIOS (%s)\n", - strerror(err)); - goto error3; - } - - pInt->BIOSseg = V_BIOS >> 4; - break; - } - default: - goto error3; - } - - pInt->num = 0xe6; - reset_int_vect(pInt); - set_return_trap(pInt); - LockLegacyVGA(pInt, &vga); - xf86ExecX86int10(pInt); - UnlockLegacyVGA(pInt, &vga); - } -#ifdef DEBUG - dprint(0xc0000, 0x20); -#endif - - xfree(options); - return pInt; - -error3: - if (base_high) - shmdt(base_high); - shmdt(base); - shmdt(0); - if (base_high) - shmdt((char*)HIGH_MEM); - shmctl(low_mem, IPC_RMID, NULL); - Int10Current = NULL; -error2: - if (high_mem > -1) - shmctl(high_mem, IPC_RMID,NULL); -error1: - if (vMem) - munmap(vMem, SYS_BIOS - V_BIOS); - xfree(((linuxInt10Priv*)pInt->private)->alloc); - xfree(pInt->private); -error0: - xfree(options); - xfree(pInt); - return NULL; -} - -Bool -MapCurrentInt10(xf86Int10InfoPtr pInt) -{ - pointer addr; - int fd = -1; - - if (Int10Current) { - shmdt(0); - if (((linuxInt10Priv*)Int10Current->private)->highMem >= 0) - shmdt((char*)HIGH_MEM); - else - munmap((pointer)V_BIOS, (SYS_BIOS - V_BIOS)); - } - addr = shmat(((linuxInt10Priv*)pInt->private)->lowMem, (char*)1, SHM_RND); - if (addr == SHMERRORPTR) { - xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot shmat() low memory\n"); - xf86DrvMsg(pInt->scrnIndex, X_ERROR, - "shmat(low_mem) error: %s\n",strerror(errno)); - return FALSE; - } - if (mprotect((void*)0, V_RAM, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) - xf86DrvMsg(pInt->scrnIndex, X_ERROR, - "Cannot set EXEC bit on low memory: %s\n", strerror(errno)); - - if (((linuxInt10Priv*)pInt->private)->highMem >= 0) { - addr = shmat(((linuxInt10Priv*)pInt->private)->highMem, - (char*)HIGH_MEM, 0); - if (addr == SHMERRORPTR) { - xf86DrvMsg(pInt->scrnIndex, X_ERROR, - "Cannot shmat() high memory\n"); - xf86DrvMsg(pInt->scrnIndex, X_ERROR, - "shmget error: %s\n",strerror(errno)); - return FALSE; - } - if (mprotect((void*)HIGH_MEM, HIGH_MEM_SIZE, - PROT_READ|PROT_WRITE|PROT_EXEC) != 0) - xf86DrvMsg(pInt->scrnIndex, X_ERROR, - "Cannot set EXEC bit on high memory: %s\n", - strerror(errno)); - } else { - if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) { - if (mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_SHARED | MAP_FIXED, fd, V_BIOS) - == MAP_FAILED) { - xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot map V_BIOS\n"); - close (fd); - return FALSE; - } - } else { - xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot open %s\n",DEV_MEM); - return FALSE; - } - close (fd); - } - - return TRUE; -} - -void -xf86FreeInt10(xf86Int10InfoPtr pInt) -{ - if (!pInt) - return; - -#ifdef _PC - xf86Int10SaveRestoreBIOSVars(pInt, FALSE); -#endif - if (Int10Current == pInt) { - shmdt(0); - if (((linuxInt10Priv*)pInt->private)->highMem >= 0) - shmdt((char*)HIGH_MEM); - else - munmap((pointer)V_BIOS, (SYS_BIOS - V_BIOS)); - Int10Current = NULL; - } - - if (((linuxInt10Priv*)pInt->private)->base_high) - shmdt(((linuxInt10Priv*)pInt->private)->base_high); - shmdt(((linuxInt10Priv*)pInt->private)->base); - shmctl(((linuxInt10Priv*)pInt->private)->lowMem, IPC_RMID, NULL); - if (((linuxInt10Priv*)pInt->private)->highMem >= 0) - shmctl(((linuxInt10Priv*)pInt->private)->highMem, IPC_RMID, NULL); - xfree(((linuxInt10Priv*)pInt->private)->alloc); - xfree(pInt->private); - xfree(pInt); -} - -void * -xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off) -{ - int pagesize = getpagesize(); - int num_pages = ALLOC_ENTRIES(pagesize); - int i, j; - - for (i = 0; i < (num_pages - num); i++) { - if (((linuxInt10Priv*)pInt->private)->alloc[i] == 0) { - for (j = i; j < (num + i); j++) - if ((((linuxInt10Priv*)pInt->private)->alloc[j] != 0)) - break; - if (j == (num + i)) - break; - else - i = i + num; - } - } - if (i == (num_pages - num)) - return NULL; - - for (j = i; j < (i + num); j++) - ((linuxInt10Priv*)pInt->private)->alloc[j] = 1; - - *off = (i + 1) * pagesize; - - return ((linuxInt10Priv*)pInt->private)->base + ((i + 1) * pagesize); -} - -void -xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num) -{ - int pagesize = getpagesize(); - int first = (((unsigned long)pbase - - (unsigned long)((linuxInt10Priv*)pInt->private)->base) - / pagesize) - 1; - int i; - - for (i = first; i < (first + num); i++) - ((linuxInt10Priv*)pInt->private)->alloc[i] = 0; -} - -static CARD8 -read_b(xf86Int10InfoPtr pInt, int addr) -{ - return *((CARD8 *)(memType)addr); -} - -static CARD16 -read_w(xf86Int10InfoPtr pInt, int addr) -{ - return *((CARD16 *)(memType)addr); -} - -static CARD32 -read_l(xf86Int10InfoPtr pInt, int addr) -{ - return *((CARD32 *)(memType)addr); -} - -static void -write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val) -{ - *((CARD8 *)(memType)addr) = val; -} - -static void -write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val) -{ - *((CARD16 *)(memType)addr) = val; -} - -static -void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val) -{ - *((CARD32 *)(memType) addr) = val; -} - -pointer -xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr) -{ - if (addr < V_RAM) - return ((linuxInt10Priv*)pInt->private)->base + addr; - else if (addr < V_BIOS) - return (pointer)(memType)addr; - else if (addr < SYS_BIOS) { - if (((linuxInt10Priv*)pInt->private)->base_high) - return (pointer)(((linuxInt10Priv*)pInt->private)->base_high - - V_BIOS + addr); - else - return (pointer) (memType)addr; - } else - return (pointer) (memType)addr; -} - -#if defined DoSubModules - -static Bool -vm86_tst(void) -{ - int __res; - -#ifdef __PIC__ - /* When compiling with -fPIC, we can't use asm constraint "b" because - %ebx is already taken by gcc. */ - __asm__ __volatile__("pushl %%ebx\n\t" - "movl %2,%%ebx\n\t" - "movl %1,%%eax\n\t" - "int $0x80\n\t" - "popl %%ebx" - :"=a" (__res) - :"n" ((int)113), "r" (NULL)); -#else - __asm__ __volatile__("int $0x80\n\t" - :"=a" (__res):"a" ((int)113), - "b" ((struct vm86_struct *)NULL)); -#endif - - if (__res < 0 && __res == -ENOSYS) - return FALSE; - - return TRUE; -} - -static Int10LinuxSubModuleState -int10LinuxLoadSubModule(ScrnInfoPtr pScrn) -{ - if (vm86_tst()) { - if (xf86LoadSubModule(pScrn,"vm86")) - return INT10_LOADED_VM86; - } - if (xf86LoadSubModule(pScrn,"x86emu")) - return INT10_LOADED_X86EMU; - - return INT10_LOAD_FAILED; -} - -#endif /* DoSubModules */ +/* + * linux specific part of the int10 module + * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2008 Egbert Eich + */ +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Pci.h" +#include "compiler.h" +#define _INT10_PRIVATE +#include "xf86int10.h" +#ifdef __sparc__ +#define DEV_MEM "/dev/fb" +#else +#define DEV_MEM "/dev/mem" +#endif +#define ALLOC_ENTRIES(x) ((V_RAM / x) - 1) +#define SHMERRORPTR (pointer)(-1) + +#include +#include +#include +#include +#include +#include +#include + +static int counter = 0; +static unsigned long int10Generation = 0; + +static CARD8 read_b(xf86Int10InfoPtr pInt, int addr); +static CARD16 read_w(xf86Int10InfoPtr pInt, int addr); +static CARD32 read_l(xf86Int10InfoPtr pInt, int addr); +static void write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val); +static void write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val); +static void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val); + +int10MemRec linuxMem = { + read_b, + read_w, + read_l, + write_b, + write_w, + write_l +}; + +typedef struct { + int lowMem; + int highMem; + char* base; + char* base_high; + int screen; + char* alloc; +} linuxInt10Priv; + +#if defined DoSubModules + +typedef enum { + INT10_NOT_LOADED, + INT10_LOADED_VM86, + INT10_LOADED_X86EMU, + INT10_LOAD_FAILED +} Int10LinuxSubModuleState; + +static Int10LinuxSubModuleState loadedSubModule = INT10_NOT_LOADED; + +static Int10LinuxSubModuleState int10LinuxLoadSubModule(ScrnInfoPtr pScrn); + +#endif /* DoSubModules */ + +xf86Int10InfoPtr +xf86ExtendedInitInt10(int entityIndex, int Flags) +{ + xf86Int10InfoPtr pInt = NULL; + int screen; + int fd; + static void* vidMem = NULL; + static void* sysMem = NULL; + void* vMem = NULL; + void *options = NULL; + int low_mem; + int high_mem = -1; + char *base = SHMERRORPTR; + char *base_high = SHMERRORPTR; + int pagesize; + memType cs; + legacyVGARec vga; + Bool videoBiosMapped = FALSE; + + if (int10Generation != serverGeneration) { + counter = 0; + int10Generation = serverGeneration; + } + + screen = (xf86FindScreenForEntity(entityIndex))->scrnIndex; + + options = xf86HandleInt10Options(xf86Screens[screen],entityIndex); + + if (int10skip(options)) { + free(options); + return NULL; + } + +#if defined DoSubModules + if (loadedSubModule == INT10_NOT_LOADED) + loadedSubModule = int10LinuxLoadSubModule(xf86Screens[screen]); + + if (loadedSubModule == INT10_LOAD_FAILED) + return NULL; +#endif + + if ((!vidMem) || (!sysMem)) { + if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) { + if (!sysMem) { + DebugF("Mapping sys bios area\n"); + if ((sysMem = mmap((void *)(SYS_BIOS), BIOS_SIZE, + PROT_READ | PROT_EXEC, + MAP_SHARED | MAP_FIXED, fd, SYS_BIOS)) + == MAP_FAILED) { + xf86DrvMsg(screen, X_ERROR, "Cannot map SYS BIOS\n"); + close(fd); + goto error0; + } + } + if (!vidMem) { + DebugF("Mapping VRAM area\n"); + if ((vidMem = mmap((void *)(V_RAM), VRAM_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED | MAP_FIXED, fd, V_RAM)) + == MAP_FAILED) { + xf86DrvMsg(screen, X_ERROR, "Cannot map V_RAM\n"); + close(fd); + goto error0; + } + } + close(fd); + } else { + xf86DrvMsg(screen, X_ERROR, "Cannot open %s\n", DEV_MEM); + goto error0; + } + } + + pInt = (xf86Int10InfoPtr)xnfcalloc(1, sizeof(xf86Int10InfoRec)); + pInt->scrnIndex = screen; + pInt->entityIndex = entityIndex; + pInt->dev = xf86GetPciInfoForEntity(entityIndex); + + if (!xf86Int10ExecSetup(pInt)) + goto error0; + pInt->mem = &linuxMem; + pagesize = getpagesize(); + pInt->private = (pointer)xnfcalloc(1, sizeof(linuxInt10Priv)); + ((linuxInt10Priv*)pInt->private)->screen = screen; + ((linuxInt10Priv*)pInt->private)->alloc = + (pointer)xnfcalloc(1, ALLOC_ENTRIES(pagesize)); + + if (!xf86IsEntityPrimary(entityIndex)) { + DebugF("Mapping high memory area\n"); + if ((high_mem = shmget(counter++, HIGH_MEM_SIZE, + IPC_CREAT | SHM_R | SHM_W)) == -1) { + if (errno == ENOSYS) + xf86DrvMsg(screen, X_ERROR, "shmget error\n Please reconfigure" + " your kernel to include System V IPC support\n"); + else + xf86DrvMsg(screen, X_ERROR, + "shmget(highmem) error: %s\n",strerror(errno)); + goto error1; + } + } else { + DebugF("Mapping Video BIOS\n"); + videoBiosMapped = TRUE; + if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) { + if ((vMem = mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED | MAP_FIXED, fd, V_BIOS)) + == MAP_FAILED) { + xf86DrvMsg(screen, X_ERROR, "Cannot map V_BIOS\n"); + close(fd); + goto error1; + } + close (fd); + } else + goto error1; + } + ((linuxInt10Priv*)pInt->private)->highMem = high_mem; + + DebugF("Mapping 640kB area\n"); + if ((low_mem = shmget(counter++, V_RAM, + IPC_CREAT | SHM_R | SHM_W)) == -1) { + xf86DrvMsg(screen, X_ERROR, + "shmget(lowmem) error: %s\n",strerror(errno)); + goto error2; + } + + ((linuxInt10Priv*)pInt->private)->lowMem = low_mem; + base = shmat(low_mem, 0, 0); + if (base == SHMERRORPTR) { + xf86DrvMsg(screen, X_ERROR, + "shmat(low_mem) error: %s\n",strerror(errno)); + goto error3; + } + ((linuxInt10Priv *)pInt->private)->base = base; + if (high_mem > -1) { + base_high = shmat(high_mem, 0, 0); + if (base_high == SHMERRORPTR) { + xf86DrvMsg(screen, X_ERROR, + "shmat(high_mem) error: %s\n",strerror(errno)); + goto error3; + } + ((linuxInt10Priv*)pInt->private)->base_high = base_high; + } else + ((linuxInt10Priv*)pInt->private)->base_high = NULL; + + if (!MapCurrentInt10(pInt)) + goto error3; + + Int10Current = pInt; + + DebugF("Mapping int area\n"); + if (xf86ReadBIOS(0, 0, (unsigned char *)0, LOW_PAGE_SIZE) < 0) { + xf86DrvMsg(screen, X_ERROR, "Cannot read int vect\n"); + goto error3; + } + DebugF("done\n"); + /* + * Read in everything between V_BIOS and SYS_BIOS as some system BIOSes + * have executable code there. Note that xf86ReadBIOS() can only bring in + * 64K bytes at a time. + */ + if (!videoBiosMapped) { + memset((pointer)V_BIOS, 0, SYS_BIOS - V_BIOS); + DebugF("Reading BIOS\n"); + for (cs = V_BIOS; cs < SYS_BIOS; cs += V_BIOS_SIZE) + if (xf86ReadBIOS(cs, 0, (pointer)cs, V_BIOS_SIZE) < V_BIOS_SIZE) + xf86DrvMsg(screen, X_WARNING, + "Unable to retrieve all of segment 0x%06lX.\n", + (long)cs); + DebugF("done\n"); + } + + if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) { + if (!xf86int10GetBiosSegment(pInt, NULL)) + goto error3; + + set_return_trap(pInt); +#ifdef _PC + pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH); + if (! (pInt->Flags & SET_BIOS_SCRATCH)) + pInt->Flags &= ~RESTORE_BIOS_SCRATCH; + xf86Int10SaveRestoreBIOSVars(pInt, TRUE); +#endif + } else { + const BusType location_type = xf86int10GetBiosLocationType(pInt); + + switch (location_type) { + case BUS_PCI: { + int err; + struct pci_device *rom_device = + xf86GetPciInfoForEntity(pInt->entityIndex); + +#if HAVE_PCI_DEVICE_ENABLE + pci_device_enable(rom_device); +#endif + + err = pci_device_read_rom(rom_device, (unsigned char *)(V_BIOS)); + if (err) { + xf86DrvMsg(screen,X_ERROR,"Cannot read V_BIOS (%s)\n", + strerror(err)); + goto error3; + } + + pInt->BIOSseg = V_BIOS >> 4; + break; + } + default: + goto error3; + } + + pInt->num = 0xe6; + reset_int_vect(pInt); + set_return_trap(pInt); + LockLegacyVGA(pInt, &vga); + xf86ExecX86int10(pInt); + UnlockLegacyVGA(pInt, &vga); + } +#ifdef DEBUG + dprint(0xc0000, 0x20); +#endif + + free(options); + return pInt; + +error3: + if (base_high) + shmdt(base_high); + shmdt(base); + shmdt(0); + if (base_high) + shmdt((char*)HIGH_MEM); + shmctl(low_mem, IPC_RMID, NULL); + Int10Current = NULL; +error2: + if (high_mem > -1) + shmctl(high_mem, IPC_RMID,NULL); +error1: + if (vMem) + munmap(vMem, SYS_BIOS - V_BIOS); + free(((linuxInt10Priv*)pInt->private)->alloc); + free(pInt->private); +error0: + free(options); + free(pInt); + return NULL; +} + +Bool +MapCurrentInt10(xf86Int10InfoPtr pInt) +{ + pointer addr; + int fd = -1; + + if (Int10Current) { + shmdt(0); + if (((linuxInt10Priv*)Int10Current->private)->highMem >= 0) + shmdt((char*)HIGH_MEM); + else + munmap((pointer)V_BIOS, (SYS_BIOS - V_BIOS)); + } + addr = shmat(((linuxInt10Priv*)pInt->private)->lowMem, (char*)1, SHM_RND); + if (addr == SHMERRORPTR) { + xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot shmat() low memory\n"); + xf86DrvMsg(pInt->scrnIndex, X_ERROR, + "shmat(low_mem) error: %s\n",strerror(errno)); + return FALSE; + } + if (mprotect((void*)0, V_RAM, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) + xf86DrvMsg(pInt->scrnIndex, X_ERROR, + "Cannot set EXEC bit on low memory: %s\n", strerror(errno)); + + if (((linuxInt10Priv*)pInt->private)->highMem >= 0) { + addr = shmat(((linuxInt10Priv*)pInt->private)->highMem, + (char*)HIGH_MEM, 0); + if (addr == SHMERRORPTR) { + xf86DrvMsg(pInt->scrnIndex, X_ERROR, + "Cannot shmat() high memory\n"); + xf86DrvMsg(pInt->scrnIndex, X_ERROR, + "shmget error: %s\n",strerror(errno)); + return FALSE; + } + if (mprotect((void*)HIGH_MEM, HIGH_MEM_SIZE, + PROT_READ|PROT_WRITE|PROT_EXEC) != 0) + xf86DrvMsg(pInt->scrnIndex, X_ERROR, + "Cannot set EXEC bit on high memory: %s\n", + strerror(errno)); + } else { + if ((fd = open(DEV_MEM, O_RDWR, 0)) >= 0) { + if (mmap((void *)(V_BIOS), SYS_BIOS - V_BIOS, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED | MAP_FIXED, fd, V_BIOS) + == MAP_FAILED) { + xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot map V_BIOS\n"); + close (fd); + return FALSE; + } + } else { + xf86DrvMsg(pInt->scrnIndex, X_ERROR, "Cannot open %s\n",DEV_MEM); + return FALSE; + } + close (fd); + } + + return TRUE; +} + +void +xf86FreeInt10(xf86Int10InfoPtr pInt) +{ + if (!pInt) + return; + +#ifdef _PC + xf86Int10SaveRestoreBIOSVars(pInt, FALSE); +#endif + if (Int10Current == pInt) { + shmdt(0); + if (((linuxInt10Priv*)pInt->private)->highMem >= 0) + shmdt((char*)HIGH_MEM); + else + munmap((pointer)V_BIOS, (SYS_BIOS - V_BIOS)); + Int10Current = NULL; + } + + if (((linuxInt10Priv*)pInt->private)->base_high) + shmdt(((linuxInt10Priv*)pInt->private)->base_high); + shmdt(((linuxInt10Priv*)pInt->private)->base); + shmctl(((linuxInt10Priv*)pInt->private)->lowMem, IPC_RMID, NULL); + if (((linuxInt10Priv*)pInt->private)->highMem >= 0) + shmctl(((linuxInt10Priv*)pInt->private)->highMem, IPC_RMID, NULL); + free(((linuxInt10Priv*)pInt->private)->alloc); + free(pInt->private); + free(pInt); +} + +void * +xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off) +{ + int pagesize = getpagesize(); + int num_pages = ALLOC_ENTRIES(pagesize); + int i, j; + + for (i = 0; i < (num_pages - num); i++) { + if (((linuxInt10Priv*)pInt->private)->alloc[i] == 0) { + for (j = i; j < (num + i); j++) + if ((((linuxInt10Priv*)pInt->private)->alloc[j] != 0)) + break; + if (j == (num + i)) + break; + else + i = i + num; + } + } + if (i == (num_pages - num)) + return NULL; + + for (j = i; j < (i + num); j++) + ((linuxInt10Priv*)pInt->private)->alloc[j] = 1; + + *off = (i + 1) * pagesize; + + return ((linuxInt10Priv*)pInt->private)->base + ((i + 1) * pagesize); +} + +void +xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num) +{ + int pagesize = getpagesize(); + int first = (((unsigned long)pbase + - (unsigned long)((linuxInt10Priv*)pInt->private)->base) + / pagesize) - 1; + int i; + + for (i = first; i < (first + num); i++) + ((linuxInt10Priv*)pInt->private)->alloc[i] = 0; +} + +static CARD8 +read_b(xf86Int10InfoPtr pInt, int addr) +{ + return *((CARD8 *)(memType)addr); +} + +static CARD16 +read_w(xf86Int10InfoPtr pInt, int addr) +{ + return *((CARD16 *)(memType)addr); +} + +static CARD32 +read_l(xf86Int10InfoPtr pInt, int addr) +{ + return *((CARD32 *)(memType)addr); +} + +static void +write_b(xf86Int10InfoPtr pInt, int addr, CARD8 val) +{ + *((CARD8 *)(memType)addr) = val; +} + +static void +write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val) +{ + *((CARD16 *)(memType)addr) = val; +} + +static +void write_l(xf86Int10InfoPtr pInt, int addr, CARD32 val) +{ + *((CARD32 *)(memType) addr) = val; +} + +pointer +xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr) +{ + if (addr < V_RAM) + return ((linuxInt10Priv*)pInt->private)->base + addr; + else if (addr < V_BIOS) + return (pointer)(memType)addr; + else if (addr < SYS_BIOS) { + if (((linuxInt10Priv*)pInt->private)->base_high) + return (pointer)(((linuxInt10Priv*)pInt->private)->base_high + - V_BIOS + addr); + else + return (pointer) (memType)addr; + } else + return (pointer) (memType)addr; +} + +#if defined DoSubModules + +static Bool +vm86_tst(void) +{ + int __res; + +#ifdef __PIC__ + /* When compiling with -fPIC, we can't use asm constraint "b" because + %ebx is already taken by gcc. */ + __asm__ __volatile__("pushl %%ebx\n\t" + "movl %2,%%ebx\n\t" + "movl %1,%%eax\n\t" + "int $0x80\n\t" + "popl %%ebx" + :"=a" (__res) + :"n" ((int)113), "r" (NULL)); +#else + __asm__ __volatile__("int $0x80\n\t" + :"=a" (__res):"a" ((int)113), + "b" ((struct vm86_struct *)NULL)); +#endif + + if (__res < 0 && __res == -ENOSYS) + return FALSE; + + return TRUE; +} + +static Int10LinuxSubModuleState +int10LinuxLoadSubModule(ScrnInfoPtr pScrn) +{ + if (vm86_tst()) { + if (xf86LoadSubModule(pScrn,"vm86")) + return INT10_LOADED_VM86; + } + if (xf86LoadSubModule(pScrn,"x86emu")) + return INT10_LOADED_X86EMU; + + return INT10_LOAD_FAILED; +} + +#endif /* DoSubModules */ diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c b/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c index 61437406d..3fa897366 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c @@ -1,374 +1,374 @@ -/* - * Abstraction of the AGP GART interface. - * - * This version is for Linux and Free/Open/NetBSD. - * - * Copyright © 2000 VA Linux Systems, Inc. - * Copyright © 2001 The XFree86 Project, Inc. - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86OSpriv.h" - -#if defined(linux) -#include -#include -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) -#include -#include -#endif - -#ifndef AGP_DEVICE -#define AGP_DEVICE "/dev/agpgart" -#endif -/* AGP page size is independent of the host page size. */ -#ifndef AGP_PAGE_SIZE -#define AGP_PAGE_SIZE 4096 -#endif -#define AGPGART_MAJOR_VERSION 0 -#define AGPGART_MINOR_VERSION 99 - -static int gartFd = -1; -static int acquiredScreen = -1; -static Bool initDone = FALSE; -/* - * Close /dev/agpgart. This frees all associated memory allocated during - * this server generation. - */ -Bool -xf86GARTCloseScreen(int screenNum) -{ - if(gartFd != -1) { - close(gartFd); - acquiredScreen = -1; - gartFd = -1; - initDone = FALSE; - } - return TRUE; -} - -/* - * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called. - */ -static Bool -GARTInit(int screenNum) -{ - struct _agp_info agpinf; - - if (initDone) - return (gartFd != -1); - - initDone = TRUE; - - if (gartFd == -1) - gartFd = open(AGP_DEVICE, O_RDWR, 0); - else - return FALSE; - - if (gartFd == -1) { - xf86DrvMsg(screenNum, X_ERROR, - "GARTInit: Unable to open " AGP_DEVICE " (%s)\n", - strerror(errno)); - return FALSE; - } - - xf86AcquireGART(-1); - /* Check the kernel driver version. */ - if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { - xf86DrvMsg(screenNum, X_ERROR, - "GARTInit: AGPIOC_INFO failed (%s)\n", strerror(errno)); - close(gartFd); - gartFd = -1; - return FALSE; - } - xf86ReleaseGART(-1); - -#if defined(linux) - /* Per Dave Jones, every effort will be made to keep the - * agpgart interface backwards compatible, so allow all - * future versions. - */ - if ( -#if (AGPGART_MAJOR_VERSION > 0) /* quiet compiler */ - agpinf.version.major < AGPGART_MAJOR_VERSION || -#endif - (agpinf.version.major == AGPGART_MAJOR_VERSION && - agpinf.version.minor < AGPGART_MINOR_VERSION)) { - xf86DrvMsg(screenNum, X_ERROR, - "GARTInit: Kernel agpgart driver version is not current" - " (%d.%d vs %d.%d)\n", - agpinf.version.major, agpinf.version.minor, - AGPGART_MAJOR_VERSION, AGPGART_MINOR_VERSION); - close(gartFd); - gartFd = -1; - return FALSE; - } -#endif - - return TRUE; -} - -Bool -xf86AgpGARTSupported(void) -{ - return GARTInit(-1); -} - -AgpInfoPtr -xf86GetAGPInfo(int screenNum) -{ - struct _agp_info agpinf; - AgpInfoPtr info; - - if (!GARTInit(screenNum)) - return NULL; - - - if ((info = xcalloc(sizeof(AgpInfo), 1)) == NULL) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86GetAGPInfo: Failed to allocate AgpInfo\n"); - return NULL; - } - - memset((char*)&agpinf, 0, sizeof(agpinf)); - - if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n", - strerror(errno)); - return NULL; - } - - info->bridgeId = agpinf.bridge_id; - info->agpMode = agpinf.agp_mode; - info->base = agpinf.aper_base; - info->size = agpinf.aper_size; - info->totalPages = agpinf.pg_total; - info->systemPages = agpinf.pg_system; - info->usedPages = agpinf.pg_used; - - xf86DrvMsg(screenNum, X_INFO, "Kernel reported %zu total, %zu used\n", agpinf.pg_total, agpinf.pg_used); - - return info; -} - -/* - * XXX If multiple screens can acquire the GART, should we have a reference - * count instead of using acquiredScreen? - */ - -Bool -xf86AcquireGART(int screenNum) -{ - if (screenNum != -1 && !GARTInit(screenNum)) - return FALSE; - - if (screenNum == -1 || acquiredScreen != screenNum) { - if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) { - xf86DrvMsg(screenNum, X_WARNING, - "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n", - strerror(errno)); - return FALSE; - } - acquiredScreen = screenNum; - } - return TRUE; -} - -Bool -xf86ReleaseGART(int screenNum) -{ - if (screenNum != -1 && !GARTInit(screenNum)) - return FALSE; - - if (acquiredScreen == screenNum) { - /* - * The FreeBSD agp driver removes allocations on release. - * The Linux driver doesn't. xf86ReleaseGART() is expected - * to give up access to the GART, but not to remove any - * allocations. - */ -#if !defined(linux) - if (screenNum == -1) -#endif - { - if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) { - xf86DrvMsg(screenNum, X_WARNING, - "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n", - strerror(errno)); - return FALSE; - } - acquiredScreen = -1; - } - return TRUE; - } - return FALSE; -} - -int -xf86AllocateGARTMemory(int screenNum, unsigned long size, int type, - unsigned long *physical) -{ - struct _agp_allocate alloc; - int pages; - - /* - * Allocates "size" bytes of GART memory (rounds up to the next - * page multiple) or type "type". A handle (key) for the allocated - * memory is returned. On error, the return value is -1. - */ - - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return -1; - - pages = (size / AGP_PAGE_SIZE); - if (size % AGP_PAGE_SIZE != 0) - pages++; - - /* XXX check for pages == 0? */ - - alloc.pg_count = pages; - alloc.type = type; - - if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: " - "allocation of %d pages failed\n\t(%s)\n", pages, - strerror(errno)); - return -1; - } - - if (physical) - *physical = alloc.physical; - - return alloc.key; -} - -Bool -xf86DeallocateGARTMemory(int screenNum, int key) -{ - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return FALSE; - - if (acquiredScreen != screenNum) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86UnbindGARTMemory: AGP not acquired by this screen\n"); - return FALSE; - } - -#ifdef __linux__ - if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) { -#else - if (ioctl(gartFd, AGPIOC_DEALLOCATE, &key) != 0) { -#endif - xf86DrvMsg(screenNum, X_WARNING,"xf86DeAllocateGARTMemory: " - "deallocation gart memory with key %d failed\n\t(%s)\n", - key, strerror(errno)); - return FALSE; - } - - return TRUE; -} - -/* Bind GART memory with "key" at "offset" */ -Bool -xf86BindGARTMemory(int screenNum, int key, unsigned long offset) -{ - struct _agp_bind bind; - int pageOffset; - - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return FALSE; - - if (acquiredScreen != screenNum) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86BindGARTMemory: AGP not acquired by this screen\n"); - return FALSE; - } - - if (offset % AGP_PAGE_SIZE != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " - "offset (0x%lx) is not page-aligned (%d)\n", - offset, AGP_PAGE_SIZE); - return FALSE; - } - pageOffset = offset / AGP_PAGE_SIZE; - - xf86DrvMsgVerb(screenNum, X_INFO, 3, - "xf86BindGARTMemory: bind key %d at 0x%08lx " - "(pgoffset %d)\n", key, offset, pageOffset); - - bind.pg_start = pageOffset; - bind.key = key; - - if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " - "binding of gart memory with key %d\n" - "\tat offset 0x%lx failed (%s)\n", - key, offset, strerror(errno)); - return FALSE; - } - - return TRUE; -} - - -/* Unbind GART memory with "key" */ -Bool -xf86UnbindGARTMemory(int screenNum, int key) -{ - struct _agp_unbind unbind; - - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return FALSE; - - if (acquiredScreen != screenNum) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86UnbindGARTMemory: AGP not acquired by this screen\n"); - return FALSE; - } - - unbind.priority = 0; - unbind.key = key; - - if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: " - "unbinding of gart memory with key %d " - "failed (%s)\n", key, strerror(errno)); - return FALSE; - } - - xf86DrvMsgVerb(screenNum, X_INFO, 3, - "xf86UnbindGARTMemory: unbind key %d\n", key); - - return TRUE; -} - - -/* XXX Interface may change. */ -Bool -xf86EnableAGP(int screenNum, CARD32 mode) -{ - agp_setup setup; - - if (!GARTInit(screenNum) || acquiredScreen != screenNum) - return FALSE; - - setup.agp_mode = mode; - if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: " - "AGPIOC_SETUP with mode %ld failed (%s)\n", - (unsigned long)mode, strerror(errno)); - return FALSE; - } - - return TRUE; -} - +/* + * Abstraction of the AGP GART interface. + * + * This version is for Linux and Free/Open/NetBSD. + * + * Copyright © 2000 VA Linux Systems, Inc. + * Copyright © 2001 The XFree86 Project, Inc. + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86OSpriv.h" + +#if defined(linux) +#include +#include +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +#include +#include +#endif + +#ifndef AGP_DEVICE +#define AGP_DEVICE "/dev/agpgart" +#endif +/* AGP page size is independent of the host page size. */ +#ifndef AGP_PAGE_SIZE +#define AGP_PAGE_SIZE 4096 +#endif +#define AGPGART_MAJOR_VERSION 0 +#define AGPGART_MINOR_VERSION 99 + +static int gartFd = -1; +static int acquiredScreen = -1; +static Bool initDone = FALSE; +/* + * Close /dev/agpgart. This frees all associated memory allocated during + * this server generation. + */ +Bool +xf86GARTCloseScreen(int screenNum) +{ + if(gartFd != -1) { + close(gartFd); + acquiredScreen = -1; + gartFd = -1; + initDone = FALSE; + } + return TRUE; +} + +/* + * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called. + */ +static Bool +GARTInit(int screenNum) +{ + struct _agp_info agpinf; + + if (initDone) + return (gartFd != -1); + + initDone = TRUE; + + if (gartFd == -1) + gartFd = open(AGP_DEVICE, O_RDWR, 0); + else + return FALSE; + + if (gartFd == -1) { + xf86DrvMsg(screenNum, X_ERROR, + "GARTInit: Unable to open " AGP_DEVICE " (%s)\n", + strerror(errno)); + return FALSE; + } + + xf86AcquireGART(-1); + /* Check the kernel driver version. */ + if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { + xf86DrvMsg(screenNum, X_ERROR, + "GARTInit: AGPIOC_INFO failed (%s)\n", strerror(errno)); + close(gartFd); + gartFd = -1; + return FALSE; + } + xf86ReleaseGART(-1); + +#if defined(linux) + /* Per Dave Jones, every effort will be made to keep the + * agpgart interface backwards compatible, so allow all + * future versions. + */ + if ( +#if (AGPGART_MAJOR_VERSION > 0) /* quiet compiler */ + agpinf.version.major < AGPGART_MAJOR_VERSION || +#endif + (agpinf.version.major == AGPGART_MAJOR_VERSION && + agpinf.version.minor < AGPGART_MINOR_VERSION)) { + xf86DrvMsg(screenNum, X_ERROR, + "GARTInit: Kernel agpgart driver version is not current" + " (%d.%d vs %d.%d)\n", + agpinf.version.major, agpinf.version.minor, + AGPGART_MAJOR_VERSION, AGPGART_MINOR_VERSION); + close(gartFd); + gartFd = -1; + return FALSE; + } +#endif + + return TRUE; +} + +Bool +xf86AgpGARTSupported(void) +{ + return GARTInit(-1); +} + +AgpInfoPtr +xf86GetAGPInfo(int screenNum) +{ + struct _agp_info agpinf; + AgpInfoPtr info; + + if (!GARTInit(screenNum)) + return NULL; + + + if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86GetAGPInfo: Failed to allocate AgpInfo\n"); + return NULL; + } + + memset((char*)&agpinf, 0, sizeof(agpinf)); + + if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n", + strerror(errno)); + return NULL; + } + + info->bridgeId = agpinf.bridge_id; + info->agpMode = agpinf.agp_mode; + info->base = agpinf.aper_base; + info->size = agpinf.aper_size; + info->totalPages = agpinf.pg_total; + info->systemPages = agpinf.pg_system; + info->usedPages = agpinf.pg_used; + + xf86DrvMsg(screenNum, X_INFO, "Kernel reported %zu total, %zu used\n", agpinf.pg_total, agpinf.pg_used); + + return info; +} + +/* + * XXX If multiple screens can acquire the GART, should we have a reference + * count instead of using acquiredScreen? + */ + +Bool +xf86AcquireGART(int screenNum) +{ + if (screenNum != -1 && !GARTInit(screenNum)) + return FALSE; + + if (screenNum == -1 || acquiredScreen != screenNum) { + if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) { + xf86DrvMsg(screenNum, X_WARNING, + "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n", + strerror(errno)); + return FALSE; + } + acquiredScreen = screenNum; + } + return TRUE; +} + +Bool +xf86ReleaseGART(int screenNum) +{ + if (screenNum != -1 && !GARTInit(screenNum)) + return FALSE; + + if (acquiredScreen == screenNum) { + /* + * The FreeBSD agp driver removes allocations on release. + * The Linux driver doesn't. xf86ReleaseGART() is expected + * to give up access to the GART, but not to remove any + * allocations. + */ +#if !defined(linux) + if (screenNum == -1) +#endif + { + if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) { + xf86DrvMsg(screenNum, X_WARNING, + "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n", + strerror(errno)); + return FALSE; + } + acquiredScreen = -1; + } + return TRUE; + } + return FALSE; +} + +int +xf86AllocateGARTMemory(int screenNum, unsigned long size, int type, + unsigned long *physical) +{ + struct _agp_allocate alloc; + int pages; + + /* + * Allocates "size" bytes of GART memory (rounds up to the next + * page multiple) or type "type". A handle (key) for the allocated + * memory is returned. On error, the return value is -1. + */ + + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return -1; + + pages = (size / AGP_PAGE_SIZE); + if (size % AGP_PAGE_SIZE != 0) + pages++; + + /* XXX check for pages == 0? */ + + alloc.pg_count = pages; + alloc.type = type; + + if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: " + "allocation of %d pages failed\n\t(%s)\n", pages, + strerror(errno)); + return -1; + } + + if (physical) + *physical = alloc.physical; + + return alloc.key; +} + +Bool +xf86DeallocateGARTMemory(int screenNum, int key) +{ + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return FALSE; + + if (acquiredScreen != screenNum) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86UnbindGARTMemory: AGP not acquired by this screen\n"); + return FALSE; + } + +#ifdef __linux__ + if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) { +#else + if (ioctl(gartFd, AGPIOC_DEALLOCATE, &key) != 0) { +#endif + xf86DrvMsg(screenNum, X_WARNING,"xf86DeAllocateGARTMemory: " + "deallocation gart memory with key %d failed\n\t(%s)\n", + key, strerror(errno)); + return FALSE; + } + + return TRUE; +} + +/* Bind GART memory with "key" at "offset" */ +Bool +xf86BindGARTMemory(int screenNum, int key, unsigned long offset) +{ + struct _agp_bind bind; + int pageOffset; + + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return FALSE; + + if (acquiredScreen != screenNum) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86BindGARTMemory: AGP not acquired by this screen\n"); + return FALSE; + } + + if (offset % AGP_PAGE_SIZE != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " + "offset (0x%lx) is not page-aligned (%d)\n", + offset, AGP_PAGE_SIZE); + return FALSE; + } + pageOffset = offset / AGP_PAGE_SIZE; + + xf86DrvMsgVerb(screenNum, X_INFO, 3, + "xf86BindGARTMemory: bind key %d at 0x%08lx " + "(pgoffset %d)\n", key, offset, pageOffset); + + bind.pg_start = pageOffset; + bind.key = key; + + if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " + "binding of gart memory with key %d\n" + "\tat offset 0x%lx failed (%s)\n", + key, offset, strerror(errno)); + return FALSE; + } + + return TRUE; +} + + +/* Unbind GART memory with "key" */ +Bool +xf86UnbindGARTMemory(int screenNum, int key) +{ + struct _agp_unbind unbind; + + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return FALSE; + + if (acquiredScreen != screenNum) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86UnbindGARTMemory: AGP not acquired by this screen\n"); + return FALSE; + } + + unbind.priority = 0; + unbind.key = key; + + if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: " + "unbinding of gart memory with key %d " + "failed (%s)\n", key, strerror(errno)); + return FALSE; + } + + xf86DrvMsgVerb(screenNum, X_INFO, 3, + "xf86UnbindGARTMemory: unbind key %d\n", key); + + return TRUE; +} + + +/* XXX Interface may change. */ +Bool +xf86EnableAGP(int screenNum, CARD32 mode) +{ + agp_setup setup; + + if (!GARTInit(screenNum) || acquiredScreen != screenNum) + return FALSE; + + setup.agp_mode = mode; + if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: " + "AGPIOC_SETUP with mode %ld failed (%s)\n", + (unsigned long)mode, strerror(errno)); + return FALSE; + } + + return TRUE; +} + diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c index 26a17425a..a515b4080 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c @@ -1,878 +1,878 @@ -/* - * Copyright 1992 by Orest Zborowski - * Copyright 1993 by David Wexelblat - * - * 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 names of Orest Zborowski and David Wexelblat - * not be used in advertising or publicity pertaining to distribution of - * the software without specific, written prior permission. Orest Zborowski - * and David Wexelblat make no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT 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. - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include - -#include -#include "input.h" -#include "scrnintstr.h" - -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86OSpriv.h" -#ifdef __alpha__ -#include "shared/xf86Axp.h" -#endif - -#ifdef HAS_MTRR_SUPPORT -#include -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -static Bool ExtendedEnabled = FALSE; - -#ifdef __ia64__ - -#include "compiler.h" -#include - -#elif !defined(__powerpc__) && \ - !defined(__mc68000__) && \ - !defined(__sparc__) && \ - !defined(__mips__) && \ - !defined(__arm__) - -/* - * Due to conflicts with "compiler.h", don't rely on to declare - * these. - */ -extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on); -extern int iopl(int __level); - -#endif - -#ifdef __alpha__ -# define BUS_BASE bus_base -#else -#define BUS_BASE (0) -#endif /* __alpha__ */ - -/***************************************************************************/ -/* Video Memory Mapping section */ -/***************************************************************************/ - -static pointer mapVidMem(int, unsigned long, unsigned long, int); -static void unmapVidMem(int, pointer, unsigned long); -#if defined (__alpha__) -extern void sethae(unsigned long hae); -extern unsigned long _bus_base __P ((void)) __attribute__ ((const)); -extern unsigned long _bus_base_sparse __P ((void)) __attribute__ ((const)); - -static pointer mapVidMemSparse(int, unsigned long, unsigned long, int); -extern axpDevice lnxGetAXP(void); -static void unmapVidMemSparse(int, pointer, unsigned long); -static axpDevice axpSystem = -1; -static Bool needSparse; -static unsigned long hae_thresh; -static unsigned long hae_mask; -static unsigned long bus_base; -#endif - -#ifdef HAS_MTRR_SUPPORT - -#define SPLIT_WC_REGIONS 1 - -static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); -static void undoWC(int, pointer); - -/* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr - driver will clean up when we exit. */ -#define MTRR_FD_UNOPENED (-1) /* We have yet to open /proc/mtrr */ -#define MTRR_FD_PROBLEM (-2) /* We tried to open /proc/mtrr, but had - a problem. */ -static int mtrr_fd = MTRR_FD_UNOPENED; - -/* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0, - and will fail on Linux 2.2 with MTRR support configured out, - so verbosity should be chosen appropriately. */ -static Bool -mtrr_open(int verbosity) -{ - /* Only report absence of /proc/mtrr once. */ - static Bool warned = FALSE; - - if (mtrr_fd == MTRR_FD_UNOPENED) { - mtrr_fd = open("/proc/mtrr", O_WRONLY); - - if (mtrr_fd < 0) - mtrr_fd = MTRR_FD_PROBLEM; - } - - if (mtrr_fd == MTRR_FD_PROBLEM) { - /* To make sure we only ever warn once, need to check - verbosity outside xf86MsgVerb */ - if (!warned && verbosity <= xf86GetVerbosity()) { - xf86MsgVerb(X_WARNING, verbosity, - "System lacks support for changing MTRRs\n"); - warned = TRUE; - } - - return FALSE; - } - else - return TRUE; -} - -/* - * We maintain a list of WC regions for each physical mapping so they can - * be undone when unmapping. - */ - -struct mtrr_wc_region { - struct mtrr_sentry sentry; - Bool added; /* added WC or removed it */ - struct mtrr_wc_region * next; -}; - - -static struct mtrr_wc_region * -mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size, - MessageType from) -{ - /* Some BIOS writers thought that setting wc over the mmio - region of a graphics devices was a good idea. Try to fix - it. */ - - struct mtrr_gentry gent; - struct mtrr_wc_region *wcreturn = NULL, *wcr; - int count, ret=0; - - /* Linux 2.0 users should not get a warning without -verbose */ - if (!mtrr_open(2)) - return NULL; - - for (gent.regnum = 0; - ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; - gent.regnum++) { - if (gent.type != MTRR_TYPE_WRCOMB - || gent.base + gent.size <= base - || base + size <= gent.base) - continue; - - /* Found an overlapping region. Delete it. */ - - wcr = xalloc(sizeof(*wcr)); - if (!wcr) - return NULL; - wcr->sentry.base = gent.base; - wcr->sentry.size = gent.size; - wcr->sentry.type = MTRR_TYPE_WRCOMB; - wcr->added = FALSE; - - count = 3; - while (count-- && - (ret = ioctl(mtrr_fd, MTRRIOC_KILL_ENTRY, &(wcr->sentry))) < 0); - - if (ret >= 0) { - xf86DrvMsg(screenNum, from, - "Removed MMIO write-combining range " - "(0x%lx,0x%lx)\n", - (unsigned long) gent.base, (unsigned long) gent.size); - wcr->next = wcreturn; - wcreturn = wcr; - gent.regnum--; - } else { - xfree(wcr); - xf86DrvMsgVerb(screenNum, X_WARNING, 0, - "Failed to remove MMIO " - "write-combining range (0x%lx,0x%lx)\n", - gent.base, (unsigned long) gent.size); - } - } - return wcreturn; -} - - -static struct mtrr_wc_region * -mtrr_remove_offending(int screenNum, unsigned long base, unsigned long size, - MessageType from) -{ - struct mtrr_gentry gent; - struct mtrr_wc_region *wcreturn = NULL, **wcr; - - if (!mtrr_open(2)) - return NULL; - - wcr = &wcreturn; - for (gent.regnum = 0; - ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++ ) { - if (gent.type == MTRR_TYPE_WRCOMB - && ((gent.base >= base && gent.base + gent.size < base + size) || - (gent.base > base && gent.base + gent.size <= base + size))) { - *wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from); - if (*wcr) gent.regnum--; - while(*wcr) { - wcr = &((*wcr)->next); - } - } - } - return wcreturn; -} - - -static struct mtrr_wc_region * -mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size, - MessageType from) -{ - struct mtrr_wc_region **wcr, *wcreturn, *curwcr; - - /* - * There can be only one.... - */ - - wcreturn = mtrr_remove_offending(screenNum, base, size, from); - wcr = &wcreturn; - while (*wcr) { - wcr = &((*wcr)->next); - } - - /* Linux 2.0 should not warn, unless the user explicitly asks for - WC. */ - - if (!mtrr_open(from == X_CONFIG ? 0 : 2)) - return wcreturn; - - *wcr = curwcr = xalloc(sizeof(**wcr)); - if (!curwcr) - return wcreturn; - - curwcr->sentry.base = base; - curwcr->sentry.size = size; - curwcr->sentry.type = MTRR_TYPE_WRCOMB; - curwcr->added = TRUE; - curwcr->next = NULL; - -#if SPLIT_WC_REGIONS - /* - * Splits up the write-combining region if it is not aligned on a - * size boundary. - */ - - { - unsigned long lbase, d_size = 1; - unsigned long n_size = size; - unsigned long n_base = base; - - for (lbase = n_base, d_size = 1; !(lbase & 1); - lbase = lbase >> 1, d_size <<= 1); - while (d_size > n_size) - d_size = d_size >> 1; - DebugF("WC_BASE: 0x%lx WC_END: 0x%lx\n",base,base+d_size-1); - n_base += d_size; - n_size -= d_size; - if (n_size) { - xf86DrvMsgVerb(screenNum,X_INFO,3,"Splitting WC range: " - "base: 0x%lx, size: 0x%lx\n",base,size); - curwcr->next = mtrr_add_wc_region(screenNum, n_base, n_size,from); - } - curwcr->sentry.size = d_size; - } - - /*****************************************************************/ -#endif /* SPLIT_WC_REGIONS */ - - if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &curwcr->sentry) >= 0) { - /* Avoid printing on every VT switch */ - if (xf86ServerIsInitialising()) { - xf86DrvMsg(screenNum, from, - "Write-combining range (0x%lx,0x%lx)\n", - base, size); - } - return wcreturn; - } - else { - *wcr = curwcr->next; - xfree(curwcr); - - /* Don't complain about the VGA region: MTRR fixed - regions aren't currently supported, but might be in - the future. */ - if ((unsigned long)base >= 0x100000) { - xf86DrvMsgVerb(screenNum, X_WARNING, 0, - "Failed to set up write-combining range " - "(0x%lx,0x%lx)\n", base, size); - } - return wcreturn; - } -} - -static void -mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr) -{ - struct mtrr_wc_region *p, *prev; - - if (mtrr_fd >= 0) { - p = wcr; - while (p) { - if (p->added) - ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry); - prev = p; - p = p->next; - xfree(prev); - } - } -} - -static pointer -setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, - MessageType from) -{ - if (enable) - return mtrr_add_wc_region(screenNum, base, size, from); - else - return mtrr_cull_wc_region(screenNum, base, size, from); -} - -static void -undoWC(int screenNum, pointer regioninfo) -{ - mtrr_undo_wc_region(screenNum, regioninfo); -} - -#endif /* HAS_MTRR_SUPPORT */ - -void -xf86OSInitVidMem(VidMemInfoPtr pVidMem) -{ - pVidMem->linearSupported = TRUE; -#ifdef __alpha__ - if (axpSystem == -1) { - axpSystem = lnxGetAXP(); - if ((needSparse = (_bus_base_sparse() > 0))) { - hae_thresh = xf86AXPParams[axpSystem].hae_thresh; - hae_mask = xf86AXPParams[axpSystem].hae_mask; - } - bus_base = _bus_base(); - } - if (needSparse) { - xf86Msg(X_INFO,"Machine needs sparse mapping\n"); - pVidMem->mapMem = mapVidMemSparse; - pVidMem->unmapMem = unmapVidMemSparse; - } else { - xf86Msg(X_INFO,"Machine type has 8/16 bit access\n"); - pVidMem->mapMem = mapVidMem; - pVidMem->unmapMem = unmapVidMem; - } -#else - pVidMem->mapMem = mapVidMem; - pVidMem->unmapMem = unmapVidMem; -#endif /* __alpha__ */ - - -#ifdef HAS_MTRR_SUPPORT - pVidMem->setWC = setWC; - pVidMem->undoWC = undoWC; -#endif - pVidMem->initialised = TRUE; -} - -#ifdef __sparc__ -/* Basically, you simply cannot do this on Sparc. You have to do something portable - * like use /dev/fb* or mmap() on /proc/bus/pci/X/Y nodes. -DaveM - */ -static pointer mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) -{ - return NULL; -} -#else -static pointer -mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) -{ - pointer base; - int fd; - int mapflags = MAP_SHARED; - int prot; - memType realBase, alignOff; - - realBase = Base & ~(getpagesize() - 1); - alignOff = Base - realBase; - DebugF("base: %lx, realBase: %lx, alignOff: %lx \n", - Base,realBase,alignOff); - -#if defined(__ia64__) || defined(__arm__) || defined(__s390__) -#ifndef MAP_WRITECOMBINED -#define MAP_WRITECOMBINED 0x00010000 -#endif -#ifndef MAP_NONCACHED -#define MAP_NONCACHED 0x00020000 -#endif - if(flags & VIDMEM_FRAMEBUFFER) - mapflags |= MAP_WRITECOMBINED; - else - mapflags |= MAP_NONCACHED; -#endif - -#if 0 - /* this will disappear when people upgrade their kernels */ - fd = open(DEV_MEM, - ((flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR) | O_SYNC); -#else - fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); -#endif - if (fd < 0) - { - FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", - strerror(errno)); - } - - if (flags & VIDMEM_READONLY) - prot = PROT_READ; - else - prot = PROT_READ | PROT_WRITE; - - /* This requires linux-0.99.pl10 or above */ - base = mmap((caddr_t)0, Size + alignOff, prot, mapflags, fd, - (off_t)realBase + BUS_BASE); - close(fd); - if (base == MAP_FAILED) { - FatalError("xf86MapVidMem: Could not mmap framebuffer" - " (0x%08lx,0x%lx) (%s)\n", Base, Size, - strerror(errno)); - } - DebugF("base: %lx aligned base: %lx\n",base, base + alignOff); - return (char *)base + alignOff; -} -#endif /* !(__sparc__) */ - -static void -unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) -{ - memType alignOff = (memType)Base - - ((memType)Base & ~(getpagesize() - 1)); - - DebugF("alignment offset: %lx\n",alignOff); - munmap((caddr_t)((memType)Base - alignOff), (Size + alignOff)); -} - - -/***************************************************************************/ -/* I/O Permissions section */ -/***************************************************************************/ - -#if defined(__powerpc__) -volatile unsigned char *ioBase = NULL; - -#ifndef __NR_pciconfig_iobase -#define __NR_pciconfig_iobase 200 -#endif - -#endif - -Bool -xf86EnableIO(void) -{ -#if defined(__powerpc__) - int fd; - unsigned int ioBase_phys; -#endif - - if (ExtendedEnabled) - return TRUE; - -#if defined(__powerpc__) - ioBase_phys = syscall(__NR_pciconfig_iobase, 2, 0, 0); - - fd = open("/dev/mem", O_RDWR); - if (ioBase == NULL) { - ioBase = (volatile unsigned char *)mmap(0, 0x20000, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, - ioBase_phys); -/* Should this be fatal or just a warning? */ -#if 0 - if (ioBase == MAP_FAILED) { - xf86Msg(X_WARNING, - "xf86EnableIOPorts: Failed to map iobase (%s)\n", - strerror(errno)); - return FALSE; - } -#endif - } - close(fd); -#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__arm__) && !defined(__m32r__) - if (ioperm(0, 1024, 1) || iopl(3)) { - if (errno == ENODEV) - ErrorF("xf86EnableIOPorts: no I/O ports found\n"); - else - FatalError("xf86EnableIOPorts: failed to set IOPL" - " for I/O (%s)\n", strerror(errno)); - return FALSE; - } -# if !defined(__alpha__) - ioperm(0x40,4,0); /* trap access to the timer chip */ - ioperm(0x60,4,0); /* trap access to the keyboard controller */ -# endif -#endif - ExtendedEnabled = TRUE; - - return TRUE; -} - -void -xf86DisableIO(void) -{ - if (!ExtendedEnabled) - return; -#if defined(__powerpc__) - munmap(ioBase, 0x20000); - ioBase = NULL; -#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__arm__) && !defined(__s390__) && !defined(__m32r__) - iopl(0); - ioperm(0, 1024, 0); -#endif - ExtendedEnabled = FALSE; - - return; -} - -#if defined (__alpha__) - -#define vuip volatile unsigned int * - -extern int readDense8(pointer Base, register unsigned long Offset); -extern int readDense16(pointer Base, register unsigned long Offset); -extern int readDense32(pointer Base, register unsigned long Offset); -extern void -writeDenseNB8(int Value, pointer Base, register unsigned long Offset); -extern void -writeDenseNB16(int Value, pointer Base, register unsigned long Offset); -extern void -writeDenseNB32(int Value, pointer Base, register unsigned long Offset); -extern void -writeDense8(int Value, pointer Base, register unsigned long Offset); -extern void -writeDense16(int Value, pointer Base, register unsigned long Offset); -extern void -writeDense32(int Value, pointer Base, register unsigned long Offset); - -static int readSparse8(pointer Base, register unsigned long Offset); -static int readSparse16(pointer Base, register unsigned long Offset); -static int readSparse32(pointer Base, register unsigned long Offset); -static void -writeSparseNB8(int Value, pointer Base, register unsigned long Offset); -static void -writeSparseNB16(int Value, pointer Base, register unsigned long Offset); -static void -writeSparseNB32(int Value, pointer Base, register unsigned long Offset); -static void -writeSparse8(int Value, pointer Base, register unsigned long Offset); -static void -writeSparse16(int Value, pointer Base, register unsigned long Offset); -static void -writeSparse32(int Value, pointer Base, register unsigned long Offset); - -#define DENSE_BASE 0x2ff00000000UL -#define SPARSE_BASE 0x30000000000UL - -static unsigned long msb_set = 0; - -static pointer -mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size, int flags) -{ - int fd, prot; - unsigned long ret, rets = 0; - - static Bool was_here = FALSE; - - if (!was_here) { - was_here = TRUE; - - xf86WriteMmio8 = writeSparse8; - xf86WriteMmio16 = writeSparse16; - xf86WriteMmio32 = writeSparse32; - xf86WriteMmioNB8 = writeSparseNB8; - xf86WriteMmioNB16 = writeSparseNB16; - xf86WriteMmioNB32 = writeSparseNB32; - xf86ReadMmio8 = readSparse8; - xf86ReadMmio16 = readSparse16; - xf86ReadMmio32 = readSparse32; - } - - fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); - if (fd < 0) { - FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", - strerror(errno)); - } - -#if 0 - xf86Msg(X_INFO,"mapVidMemSparse: try Base 0x%lx size 0x%lx flags 0x%x\n", - Base, Size, flags); -#endif - - if (flags & VIDMEM_READONLY) - prot = PROT_READ; - else - prot = PROT_READ | PROT_WRITE; - - /* This requirers linux-0.99.pl10 or above */ - - /* - * Always do DENSE mmap, since read32/write32 currently require it. - */ - ret = (unsigned long)mmap((caddr_t)(DENSE_BASE + Base), Size, - prot, MAP_SHARED, fd, - (off_t) (bus_base + Base)); - - /* - * Do SPARSE mmap only when MMIO and not MMIO_32BIT, or FRAMEBUFFER - * and SPARSE (which should require the use of read/write macros). - * - * By not SPARSE mmapping an 8MB framebuffer, we can save approx. 256K - * bytes worth of pagetable (32 pages). - */ - if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || - ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) - { - rets = (unsigned long)mmap((caddr_t)(SPARSE_BASE + (Base << 5)), - Size << 5, prot, MAP_SHARED, fd, - (off_t) _bus_base_sparse() + (Base << 5)); - } - - close(fd); - - if (ret == (unsigned long)MAP_FAILED) { - FatalError("xf86MapVidMemSparse: Could not (dense) mmap fb (%s)\n", - strerror(errno)); - } - - if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || - ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) - { - if (rets == (unsigned long)MAP_FAILED || - rets != (SPARSE_BASE + (Base << 5))) - { - FatalError("mapVidMemSparse: Could not (sparse) mmap fb (%s)\n", - strerror(errno)); - } - } - -#if 1 - if (rets) - xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" - " to DENSE at 0x%lx and SPARSE at 0x%lx\n", - Base, Size, ret, rets); - else - xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" - " to DENSE only at 0x%lx\n", - Base, Size, ret); - -#endif - return (pointer) ret; -} - -static void -unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size) -{ - unsigned long Offset = (unsigned long)Base - DENSE_BASE; -#if 1 - xf86Msg(X_INFO,"unmapVidMemSparse: unmapping Base 0x%lx Size 0x%lx\n", - Base, Size); -#endif - /* Unmap DENSE always. */ - munmap((caddr_t)Base, Size); - - /* Unmap SPARSE always, and ignore error in case we did not map it. */ - munmap((caddr_t)(SPARSE_BASE + (Offset << 5)), Size << 5); -} - -static int -readSparse8(pointer Base, register unsigned long Offset) -{ - register unsigned long result, shift; - register unsigned long msb; - - mem_barrier(); - Offset += (unsigned long)Base - DENSE_BASE; - shift = (Offset & 0x3) << 3; - if (Offset >= (hae_thresh)) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - - mem_barrier(); - result = *(vuip) (SPARSE_BASE + (Offset << 5)); - result >>= shift; - return 0xffUL & result; -} - -static int -readSparse16(pointer Base, register unsigned long Offset) -{ - register unsigned long result, shift; - register unsigned long msb; - - mem_barrier(); - Offset += (unsigned long)Base - DENSE_BASE; - shift = (Offset & 0x2) << 3; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - - mem_barrier(); - result = *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))); - result >>= shift; - return 0xffffUL & result; -} - -static int -readSparse32(pointer Base, register unsigned long Offset) -{ - /* NOTE: this is really using DENSE. */ - mem_barrier(); - return *(vuip)((unsigned long)Base+(Offset)); -} - -static void -writeSparse8(int Value, pointer Base, register unsigned long Offset) -{ - register unsigned long msb; - register unsigned int b = Value & 0xffU; - - write_mem_barrier(); - Offset += (unsigned long)Base - DENSE_BASE; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - - write_mem_barrier(); - *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; -} - -static void -writeSparse16(int Value, pointer Base, register unsigned long Offset) -{ - register unsigned long msb; - register unsigned int w = Value & 0xffffU; - - write_mem_barrier(); - Offset += (unsigned long)Base - DENSE_BASE; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - - write_mem_barrier(); - *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))) = w * 0x00010001; -} - -static void -writeSparse32(int Value, pointer Base, register unsigned long Offset) -{ - /* NOTE: this is really using DENSE. */ - write_mem_barrier(); - *(vuip)((unsigned long)Base + (Offset)) = Value; - return; -} - -static void -writeSparseNB8(int Value, pointer Base, register unsigned long Offset) -{ - register unsigned long msb; - register unsigned int b = Value & 0xffU; - - Offset += (unsigned long)Base - DENSE_BASE; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; -} - -static void -writeSparseNB16(int Value, pointer Base, register unsigned long Offset) -{ - register unsigned long msb; - register unsigned int w = Value & 0xffffU; - - Offset += (unsigned long)Base - DENSE_BASE; - if (Offset >= hae_thresh) { - msb = Offset & hae_mask; - Offset -= msb; - if (msb_set != msb) { - sethae(msb); - msb_set = msb; - } - } - *(vuip)(SPARSE_BASE+(Offset<<5)+(1<<(5-2))) = w * 0x00010001; -} - -static void -writeSparseNB32(int Value, pointer Base, register unsigned long Offset) -{ - /* NOTE: this is really using DENSE. */ - *(vuip)((unsigned long)Base + (Offset)) = Value; - return; -} - -void (*xf86WriteMmio8)(int Value, pointer Base, unsigned long Offset) - = writeDense8; -void (*xf86WriteMmio16)(int Value, pointer Base, unsigned long Offset) - = writeDense16; -void (*xf86WriteMmio32)(int Value, pointer Base, unsigned long Offset) - = writeDense32; -void (*xf86WriteMmioNB8)(int Value, pointer Base, unsigned long Offset) - = writeDenseNB8; -void (*xf86WriteMmioNB16)(int Value, pointer Base, unsigned long Offset) - = writeDenseNB16; -void (*xf86WriteMmioNB32)(int Value, pointer Base, unsigned long Offset) - = writeDenseNB32; -int (*xf86ReadMmio8)(pointer Base, unsigned long Offset) - = readDense8; -int (*xf86ReadMmio16)(pointer Base, unsigned long Offset) - = readDense16; -int (*xf86ReadMmio32)(pointer Base, unsigned long Offset) - = readDense32; - -#endif /* __alpha__ */ +/* + * Copyright 1992 by Orest Zborowski + * Copyright 1993 by David Wexelblat + * + * 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 names of Orest Zborowski and David Wexelblat + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Orest Zborowski + * and David Wexelblat make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT 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. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +#include +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86OSpriv.h" +#ifdef __alpha__ +#include "shared/xf86Axp.h" +#endif + +#ifdef HAS_MTRR_SUPPORT +#include +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static Bool ExtendedEnabled = FALSE; + +#ifdef __ia64__ + +#include "compiler.h" +#include + +#elif !defined(__powerpc__) && \ + !defined(__mc68000__) && \ + !defined(__sparc__) && \ + !defined(__mips__) && \ + !defined(__arm__) + +/* + * Due to conflicts with "compiler.h", don't rely on to declare + * these. + */ +extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on); +extern int iopl(int __level); + +#endif + +#ifdef __alpha__ +# define BUS_BASE bus_base +#else +#define BUS_BASE (0) +#endif /* __alpha__ */ + +/***************************************************************************/ +/* Video Memory Mapping section */ +/***************************************************************************/ + +static pointer mapVidMem(int, unsigned long, unsigned long, int); +static void unmapVidMem(int, pointer, unsigned long); +#if defined (__alpha__) +extern void sethae(unsigned long hae); +extern unsigned long _bus_base __P ((void)) __attribute__ ((const)); +extern unsigned long _bus_base_sparse __P ((void)) __attribute__ ((const)); + +static pointer mapVidMemSparse(int, unsigned long, unsigned long, int); +extern axpDevice lnxGetAXP(void); +static void unmapVidMemSparse(int, pointer, unsigned long); +static axpDevice axpSystem = -1; +static Bool needSparse; +static unsigned long hae_thresh; +static unsigned long hae_mask; +static unsigned long bus_base; +#endif + +#ifdef HAS_MTRR_SUPPORT + +#define SPLIT_WC_REGIONS 1 + +static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType); +static void undoWC(int, pointer); + +/* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr + driver will clean up when we exit. */ +#define MTRR_FD_UNOPENED (-1) /* We have yet to open /proc/mtrr */ +#define MTRR_FD_PROBLEM (-2) /* We tried to open /proc/mtrr, but had + a problem. */ +static int mtrr_fd = MTRR_FD_UNOPENED; + +/* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0, + and will fail on Linux 2.2 with MTRR support configured out, + so verbosity should be chosen appropriately. */ +static Bool +mtrr_open(int verbosity) +{ + /* Only report absence of /proc/mtrr once. */ + static Bool warned = FALSE; + + if (mtrr_fd == MTRR_FD_UNOPENED) { + mtrr_fd = open("/proc/mtrr", O_WRONLY); + + if (mtrr_fd < 0) + mtrr_fd = MTRR_FD_PROBLEM; + } + + if (mtrr_fd == MTRR_FD_PROBLEM) { + /* To make sure we only ever warn once, need to check + verbosity outside xf86MsgVerb */ + if (!warned && verbosity <= xf86GetVerbosity()) { + xf86MsgVerb(X_WARNING, verbosity, + "System lacks support for changing MTRRs\n"); + warned = TRUE; + } + + return FALSE; + } + else + return TRUE; +} + +/* + * We maintain a list of WC regions for each physical mapping so they can + * be undone when unmapping. + */ + +struct mtrr_wc_region { + struct mtrr_sentry sentry; + Bool added; /* added WC or removed it */ + struct mtrr_wc_region * next; +}; + + +static struct mtrr_wc_region * +mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size, + MessageType from) +{ + /* Some BIOS writers thought that setting wc over the mmio + region of a graphics devices was a good idea. Try to fix + it. */ + + struct mtrr_gentry gent; + struct mtrr_wc_region *wcreturn = NULL, *wcr; + int count, ret=0; + + /* Linux 2.0 users should not get a warning without -verbose */ + if (!mtrr_open(2)) + return NULL; + + for (gent.regnum = 0; + ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; + gent.regnum++) { + if (gent.type != MTRR_TYPE_WRCOMB + || gent.base + gent.size <= base + || base + size <= gent.base) + continue; + + /* Found an overlapping region. Delete it. */ + + wcr = malloc(sizeof(*wcr)); + if (!wcr) + return NULL; + wcr->sentry.base = gent.base; + wcr->sentry.size = gent.size; + wcr->sentry.type = MTRR_TYPE_WRCOMB; + wcr->added = FALSE; + + count = 3; + while (count-- && + (ret = ioctl(mtrr_fd, MTRRIOC_KILL_ENTRY, &(wcr->sentry))) < 0); + + if (ret >= 0) { + xf86DrvMsg(screenNum, from, + "Removed MMIO write-combining range " + "(0x%lx,0x%lx)\n", + (unsigned long) gent.base, (unsigned long) gent.size); + wcr->next = wcreturn; + wcreturn = wcr; + gent.regnum--; + } else { + free(wcr); + xf86DrvMsgVerb(screenNum, X_WARNING, 0, + "Failed to remove MMIO " + "write-combining range (0x%lx,0x%lx)\n", + gent.base, (unsigned long) gent.size); + } + } + return wcreturn; +} + + +static struct mtrr_wc_region * +mtrr_remove_offending(int screenNum, unsigned long base, unsigned long size, + MessageType from) +{ + struct mtrr_gentry gent; + struct mtrr_wc_region *wcreturn = NULL, **wcr; + + if (!mtrr_open(2)) + return NULL; + + wcr = &wcreturn; + for (gent.regnum = 0; + ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++ ) { + if (gent.type == MTRR_TYPE_WRCOMB + && ((gent.base >= base && gent.base + gent.size < base + size) || + (gent.base > base && gent.base + gent.size <= base + size))) { + *wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from); + if (*wcr) gent.regnum--; + while(*wcr) { + wcr = &((*wcr)->next); + } + } + } + return wcreturn; +} + + +static struct mtrr_wc_region * +mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size, + MessageType from) +{ + struct mtrr_wc_region **wcr, *wcreturn, *curwcr; + + /* + * There can be only one.... + */ + + wcreturn = mtrr_remove_offending(screenNum, base, size, from); + wcr = &wcreturn; + while (*wcr) { + wcr = &((*wcr)->next); + } + + /* Linux 2.0 should not warn, unless the user explicitly asks for + WC. */ + + if (!mtrr_open(from == X_CONFIG ? 0 : 2)) + return wcreturn; + + *wcr = curwcr = malloc(sizeof(**wcr)); + if (!curwcr) + return wcreturn; + + curwcr->sentry.base = base; + curwcr->sentry.size = size; + curwcr->sentry.type = MTRR_TYPE_WRCOMB; + curwcr->added = TRUE; + curwcr->next = NULL; + +#if SPLIT_WC_REGIONS + /* + * Splits up the write-combining region if it is not aligned on a + * size boundary. + */ + + { + unsigned long lbase, d_size = 1; + unsigned long n_size = size; + unsigned long n_base = base; + + for (lbase = n_base, d_size = 1; !(lbase & 1); + lbase = lbase >> 1, d_size <<= 1); + while (d_size > n_size) + d_size = d_size >> 1; + DebugF("WC_BASE: 0x%lx WC_END: 0x%lx\n",base,base+d_size-1); + n_base += d_size; + n_size -= d_size; + if (n_size) { + xf86DrvMsgVerb(screenNum,X_INFO,3,"Splitting WC range: " + "base: 0x%lx, size: 0x%lx\n",base,size); + curwcr->next = mtrr_add_wc_region(screenNum, n_base, n_size,from); + } + curwcr->sentry.size = d_size; + } + + /*****************************************************************/ +#endif /* SPLIT_WC_REGIONS */ + + if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &curwcr->sentry) >= 0) { + /* Avoid printing on every VT switch */ + if (xf86ServerIsInitialising()) { + xf86DrvMsg(screenNum, from, + "Write-combining range (0x%lx,0x%lx)\n", + base, size); + } + return wcreturn; + } + else { + *wcr = curwcr->next; + free(curwcr); + + /* Don't complain about the VGA region: MTRR fixed + regions aren't currently supported, but might be in + the future. */ + if ((unsigned long)base >= 0x100000) { + xf86DrvMsgVerb(screenNum, X_WARNING, 0, + "Failed to set up write-combining range " + "(0x%lx,0x%lx)\n", base, size); + } + return wcreturn; + } +} + +static void +mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr) +{ + struct mtrr_wc_region *p, *prev; + + if (mtrr_fd >= 0) { + p = wcr; + while (p) { + if (p->added) + ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry); + prev = p; + p = p->next; + free(prev); + } + } +} + +static pointer +setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, + MessageType from) +{ + if (enable) + return mtrr_add_wc_region(screenNum, base, size, from); + else + return mtrr_cull_wc_region(screenNum, base, size, from); +} + +static void +undoWC(int screenNum, pointer regioninfo) +{ + mtrr_undo_wc_region(screenNum, regioninfo); +} + +#endif /* HAS_MTRR_SUPPORT */ + +void +xf86OSInitVidMem(VidMemInfoPtr pVidMem) +{ + pVidMem->linearSupported = TRUE; +#ifdef __alpha__ + if (axpSystem == -1) { + axpSystem = lnxGetAXP(); + if ((needSparse = (_bus_base_sparse() > 0))) { + hae_thresh = xf86AXPParams[axpSystem].hae_thresh; + hae_mask = xf86AXPParams[axpSystem].hae_mask; + } + bus_base = _bus_base(); + } + if (needSparse) { + xf86Msg(X_INFO,"Machine needs sparse mapping\n"); + pVidMem->mapMem = mapVidMemSparse; + pVidMem->unmapMem = unmapVidMemSparse; + } else { + xf86Msg(X_INFO,"Machine type has 8/16 bit access\n"); + pVidMem->mapMem = mapVidMem; + pVidMem->unmapMem = unmapVidMem; + } +#else + pVidMem->mapMem = mapVidMem; + pVidMem->unmapMem = unmapVidMem; +#endif /* __alpha__ */ + + +#ifdef HAS_MTRR_SUPPORT + pVidMem->setWC = setWC; + pVidMem->undoWC = undoWC; +#endif + pVidMem->initialised = TRUE; +} + +#ifdef __sparc__ +/* Basically, you simply cannot do this on Sparc. You have to do something portable + * like use /dev/fb* or mmap() on /proc/bus/pci/X/Y nodes. -DaveM + */ +static pointer mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + return NULL; +} +#else +static pointer +mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + pointer base; + int fd; + int mapflags = MAP_SHARED; + int prot; + memType realBase, alignOff; + + realBase = Base & ~(getpagesize() - 1); + alignOff = Base - realBase; + DebugF("base: %lx, realBase: %lx, alignOff: %lx \n", + Base,realBase,alignOff); + +#if defined(__ia64__) || defined(__arm__) || defined(__s390__) +#ifndef MAP_WRITECOMBINED +#define MAP_WRITECOMBINED 0x00010000 +#endif +#ifndef MAP_NONCACHED +#define MAP_NONCACHED 0x00020000 +#endif + if(flags & VIDMEM_FRAMEBUFFER) + mapflags |= MAP_WRITECOMBINED; + else + mapflags |= MAP_NONCACHED; +#endif + +#if 0 + /* this will disappear when people upgrade their kernels */ + fd = open(DEV_MEM, + ((flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR) | O_SYNC); +#else + fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); +#endif + if (fd < 0) + { + FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", + strerror(errno)); + } + + if (flags & VIDMEM_READONLY) + prot = PROT_READ; + else + prot = PROT_READ | PROT_WRITE; + + /* This requires linux-0.99.pl10 or above */ + base = mmap((caddr_t)0, Size + alignOff, prot, mapflags, fd, + (off_t)realBase + BUS_BASE); + close(fd); + if (base == MAP_FAILED) { + FatalError("xf86MapVidMem: Could not mmap framebuffer" + " (0x%08lx,0x%lx) (%s)\n", Base, Size, + strerror(errno)); + } + DebugF("base: %lx aligned base: %lx\n",base, base + alignOff); + return (char *)base + alignOff; +} +#endif /* !(__sparc__) */ + +static void +unmapVidMem(int ScreenNum, pointer Base, unsigned long Size) +{ + memType alignOff = (memType)Base + - ((memType)Base & ~(getpagesize() - 1)); + + DebugF("alignment offset: %lx\n",alignOff); + munmap((caddr_t)((memType)Base - alignOff), (Size + alignOff)); +} + + +/***************************************************************************/ +/* I/O Permissions section */ +/***************************************************************************/ + +#if defined(__powerpc__) +volatile unsigned char *ioBase = NULL; + +#ifndef __NR_pciconfig_iobase +#define __NR_pciconfig_iobase 200 +#endif + +#endif + +Bool +xf86EnableIO(void) +{ +#if defined(__powerpc__) + int fd; + unsigned int ioBase_phys; +#endif + + if (ExtendedEnabled) + return TRUE; + +#if defined(__powerpc__) + ioBase_phys = syscall(__NR_pciconfig_iobase, 2, 0, 0); + + fd = open("/dev/mem", O_RDWR); + if (ioBase == NULL) { + ioBase = (volatile unsigned char *)mmap(0, 0x20000, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, + ioBase_phys); +/* Should this be fatal or just a warning? */ +#if 0 + if (ioBase == MAP_FAILED) { + xf86Msg(X_WARNING, + "xf86EnableIOPorts: Failed to map iobase (%s)\n", + strerror(errno)); + return FALSE; + } +#endif + } + close(fd); +#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__arm__) && !defined(__m32r__) + if (ioperm(0, 1024, 1) || iopl(3)) { + if (errno == ENODEV) + ErrorF("xf86EnableIOPorts: no I/O ports found\n"); + else + FatalError("xf86EnableIOPorts: failed to set IOPL" + " for I/O (%s)\n", strerror(errno)); + return FALSE; + } +# if !defined(__alpha__) + ioperm(0x40,4,0); /* trap access to the timer chip */ + ioperm(0x60,4,0); /* trap access to the keyboard controller */ +# endif +#endif + ExtendedEnabled = TRUE; + + return TRUE; +} + +void +xf86DisableIO(void) +{ + if (!ExtendedEnabled) + return; +#if defined(__powerpc__) + munmap(ioBase, 0x20000); + ioBase = NULL; +#elif !defined(__mc68000__) && !defined(__sparc__) && !defined(__mips__) && !defined(__sh__) && !defined(__hppa__) && !defined(__arm__) && !defined(__s390__) && !defined(__m32r__) + iopl(0); + ioperm(0, 1024, 0); +#endif + ExtendedEnabled = FALSE; + + return; +} + +#if defined (__alpha__) + +#define vuip volatile unsigned int * + +extern int readDense8(pointer Base, register unsigned long Offset); +extern int readDense16(pointer Base, register unsigned long Offset); +extern int readDense32(pointer Base, register unsigned long Offset); +extern void +writeDenseNB8(int Value, pointer Base, register unsigned long Offset); +extern void +writeDenseNB16(int Value, pointer Base, register unsigned long Offset); +extern void +writeDenseNB32(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense8(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense16(int Value, pointer Base, register unsigned long Offset); +extern void +writeDense32(int Value, pointer Base, register unsigned long Offset); + +static int readSparse8(pointer Base, register unsigned long Offset); +static int readSparse16(pointer Base, register unsigned long Offset); +static int readSparse32(pointer Base, register unsigned long Offset); +static void +writeSparseNB8(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseNB16(int Value, pointer Base, register unsigned long Offset); +static void +writeSparseNB32(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse8(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse16(int Value, pointer Base, register unsigned long Offset); +static void +writeSparse32(int Value, pointer Base, register unsigned long Offset); + +#define DENSE_BASE 0x2ff00000000UL +#define SPARSE_BASE 0x30000000000UL + +static unsigned long msb_set = 0; + +static pointer +mapVidMemSparse(int ScreenNum, unsigned long Base, unsigned long Size, int flags) +{ + int fd, prot; + unsigned long ret, rets = 0; + + static Bool was_here = FALSE; + + if (!was_here) { + was_here = TRUE; + + xf86WriteMmio8 = writeSparse8; + xf86WriteMmio16 = writeSparse16; + xf86WriteMmio32 = writeSparse32; + xf86WriteMmioNB8 = writeSparseNB8; + xf86WriteMmioNB16 = writeSparseNB16; + xf86WriteMmioNB32 = writeSparseNB32; + xf86ReadMmio8 = readSparse8; + xf86ReadMmio16 = readSparse16; + xf86ReadMmio32 = readSparse32; + } + + fd = open(DEV_MEM, (flags & VIDMEM_READONLY) ? O_RDONLY : O_RDWR); + if (fd < 0) { + FatalError("xf86MapVidMem: failed to open " DEV_MEM " (%s)\n", + strerror(errno)); + } + +#if 0 + xf86Msg(X_INFO,"mapVidMemSparse: try Base 0x%lx size 0x%lx flags 0x%x\n", + Base, Size, flags); +#endif + + if (flags & VIDMEM_READONLY) + prot = PROT_READ; + else + prot = PROT_READ | PROT_WRITE; + + /* This requirers linux-0.99.pl10 or above */ + + /* + * Always do DENSE mmap, since read32/write32 currently require it. + */ + ret = (unsigned long)mmap((caddr_t)(DENSE_BASE + Base), Size, + prot, MAP_SHARED, fd, + (off_t) (bus_base + Base)); + + /* + * Do SPARSE mmap only when MMIO and not MMIO_32BIT, or FRAMEBUFFER + * and SPARSE (which should require the use of read/write macros). + * + * By not SPARSE mmapping an 8MB framebuffer, we can save approx. 256K + * bytes worth of pagetable (32 pages). + */ + if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || + ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) + { + rets = (unsigned long)mmap((caddr_t)(SPARSE_BASE + (Base << 5)), + Size << 5, prot, MAP_SHARED, fd, + (off_t) _bus_base_sparse() + (Base << 5)); + } + + close(fd); + + if (ret == (unsigned long)MAP_FAILED) { + FatalError("xf86MapVidMemSparse: Could not (dense) mmap fb (%s)\n", + strerror(errno)); + } + + if (((flags & VIDMEM_MMIO) && !(flags & VIDMEM_MMIO_32BIT)) || + ((flags & VIDMEM_FRAMEBUFFER) && (flags & VIDMEM_SPARSE))) + { + if (rets == (unsigned long)MAP_FAILED || + rets != (SPARSE_BASE + (Base << 5))) + { + FatalError("mapVidMemSparse: Could not (sparse) mmap fb (%s)\n", + strerror(errno)); + } + } + +#if 1 + if (rets) + xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" + " to DENSE at 0x%lx and SPARSE at 0x%lx\n", + Base, Size, ret, rets); + else + xf86Msg(X_INFO,"mapVidMemSparse: mapped Base 0x%lx size 0x%lx" + " to DENSE only at 0x%lx\n", + Base, Size, ret); + +#endif + return (pointer) ret; +} + +static void +unmapVidMemSparse(int ScreenNum, pointer Base, unsigned long Size) +{ + unsigned long Offset = (unsigned long)Base - DENSE_BASE; +#if 1 + xf86Msg(X_INFO,"unmapVidMemSparse: unmapping Base 0x%lx Size 0x%lx\n", + Base, Size); +#endif + /* Unmap DENSE always. */ + munmap((caddr_t)Base, Size); + + /* Unmap SPARSE always, and ignore error in case we did not map it. */ + munmap((caddr_t)(SPARSE_BASE + (Offset << 5)), Size << 5); +} + +static int +readSparse8(pointer Base, register unsigned long Offset) +{ + register unsigned long result, shift; + register unsigned long msb; + + mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + shift = (Offset & 0x3) << 3; + if (Offset >= (hae_thresh)) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + mem_barrier(); + result = *(vuip) (SPARSE_BASE + (Offset << 5)); + result >>= shift; + return 0xffUL & result; +} + +static int +readSparse16(pointer Base, register unsigned long Offset) +{ + register unsigned long result, shift; + register unsigned long msb; + + mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + shift = (Offset & 0x2) << 3; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + mem_barrier(); + result = *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))); + result >>= shift; + return 0xffffUL & result; +} + +static int +readSparse32(pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + mem_barrier(); + return *(vuip)((unsigned long)Base+(Offset)); +} + +static void +writeSparse8(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int b = Value & 0xffU; + + write_mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + write_mem_barrier(); + *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; +} + +static void +writeSparse16(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int w = Value & 0xffffU; + + write_mem_barrier(); + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + + write_mem_barrier(); + *(vuip)(SPARSE_BASE + (Offset<<5) + (1<<(5-2))) = w * 0x00010001; +} + +static void +writeSparse32(int Value, pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + write_mem_barrier(); + *(vuip)((unsigned long)Base + (Offset)) = Value; + return; +} + +static void +writeSparseNB8(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int b = Value & 0xffU; + + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + *(vuip) (SPARSE_BASE + (Offset << 5)) = b * 0x01010101; +} + +static void +writeSparseNB16(int Value, pointer Base, register unsigned long Offset) +{ + register unsigned long msb; + register unsigned int w = Value & 0xffffU; + + Offset += (unsigned long)Base - DENSE_BASE; + if (Offset >= hae_thresh) { + msb = Offset & hae_mask; + Offset -= msb; + if (msb_set != msb) { + sethae(msb); + msb_set = msb; + } + } + *(vuip)(SPARSE_BASE+(Offset<<5)+(1<<(5-2))) = w * 0x00010001; +} + +static void +writeSparseNB32(int Value, pointer Base, register unsigned long Offset) +{ + /* NOTE: this is really using DENSE. */ + *(vuip)((unsigned long)Base + (Offset)) = Value; + return; +} + +void (*xf86WriteMmio8)(int Value, pointer Base, unsigned long Offset) + = writeDense8; +void (*xf86WriteMmio16)(int Value, pointer Base, unsigned long Offset) + = writeDense16; +void (*xf86WriteMmio32)(int Value, pointer Base, unsigned long Offset) + = writeDense32; +void (*xf86WriteMmioNB8)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB8; +void (*xf86WriteMmioNB16)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB16; +void (*xf86WriteMmioNB32)(int Value, pointer Base, unsigned long Offset) + = writeDenseNB32; +int (*xf86ReadMmio8)(pointer Base, unsigned long Offset) + = readDense8; +int (*xf86ReadMmio16)(pointer Base, unsigned long Offset) + = readDense16; +int (*xf86ReadMmio32)(pointer Base, unsigned long Offset) + = readDense32; + +#endif /* __alpha__ */ diff --git a/xorg-server/hw/xfree86/os-support/shared/posix_tty.c b/xorg-server/hw/xfree86/os-support/shared/posix_tty.c index da57939cf..7e2c4a181 100644 --- a/xorg-server/hw/xfree86/os-support/shared/posix_tty.c +++ b/xorg-server/hw/xfree86/os-support/shared/posix_tty.c @@ -1,655 +1,655 @@ -/* - * Copyright 1993-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Except as contained in this notice, the name of the XFree86 Project 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. - */ -/* - * - * Copyright (c) 1997 Metro Link Incorporated - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Except as contained in this notice, the name of the Metro Link shall not be - * used in advertising or otherwise to promote the sale, use or other dealings - * in this Software without prior written authorization from Metro Link. - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" - -static int -GetBaud (int baudrate) -{ -#ifdef B300 - if (baudrate == 300) - return B300; -#endif -#ifdef B1200 - if (baudrate == 1200) - return B1200; -#endif -#ifdef B2400 - if (baudrate == 2400) - return B2400; -#endif -#ifdef B4800 - if (baudrate == 4800) - return B4800; -#endif -#ifdef B9600 - if (baudrate == 9600) - return B9600; -#endif -#ifdef B19200 - if (baudrate == 19200) - return B19200; -#endif -#ifdef B38400 - if (baudrate == 38400) - return B38400; -#endif -#ifdef B57600 - if (baudrate == 57600) - return B57600; -#endif -#ifdef B115200 - if (baudrate == 115200) - return B115200; -#endif -#ifdef B230400 - if (baudrate == 230400) - return B230400; -#endif -#ifdef B460800 - if (baudrate == 460800) - return B460800; -#endif - return (0); -} - -int -xf86OpenSerial (pointer options) -{ - struct termios t; - int fd, i; - char *dev; - - dev = xf86SetStrOption (options, "Device", NULL); - if (!dev) - { - xf86Msg (X_ERROR, "xf86OpenSerial: No Device specified.\n"); - return (-1); - } - - SYSCALL (fd = open (dev, O_RDWR | O_NONBLOCK)); - if (fd == -1) - { - xf86Msg (X_ERROR, - "xf86OpenSerial: Cannot open device %s\n\t%s.\n", - dev, strerror (errno)); - xfree(dev); - return (-1); - } - - if (!isatty (fd)) - { - /* Allow non-tty devices to be opened. */ - xfree(dev); - return (fd); - } - - /* set up default port parameters */ - SYSCALL (tcgetattr (fd, &t)); - t.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR\ - |IGNCR|ICRNL|IXON); - t.c_oflag &= ~OPOST; - t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); - t.c_cflag &= ~(CSIZE|PARENB); - t.c_cflag |= CS8|CLOCAL; - - cfsetispeed (&t, B9600); - cfsetospeed (&t, B9600); - t.c_cc[VMIN] = 1; - t.c_cc[VTIME] = 0; - - SYSCALL (tcsetattr (fd, TCSANOW, &t)); - - if (xf86SetSerial (fd, options) == -1) - { - SYSCALL (close (fd)); - xfree(dev); - return (-1); - } - - SYSCALL (i = fcntl (fd, F_GETFL, 0)); - if (i == -1) - { - SYSCALL (close (fd)); - xfree(dev); - return (-1); - } - i &= ~O_NONBLOCK; - SYSCALL (i = fcntl (fd, F_SETFL, i)); - if (i == -1) - { - SYSCALL (close (fd)); - xfree(dev); - return (-1); - } - xfree(dev); - return (fd); -} - -int -xf86SetSerial (int fd, pointer options) -{ - struct termios t; - int val; - const char *s; - int baud, r; - - if (fd < 0) - return -1; - - /* Don't try to set parameters for non-tty devices. */ - if (!isatty(fd)) - return 0; - - SYSCALL (tcgetattr (fd, &t)); - - if ((val = xf86SetIntOption (options, "BaudRate", 0))) - { - if ((baud = GetBaud (val))) - { - cfsetispeed (&t, baud); - cfsetospeed (&t, baud); - } - else - { - xf86Msg (X_ERROR, - "Invalid Option BaudRate value: %d\n", val); - return (-1); - } - } - - if ((val = xf86SetIntOption (options, "StopBits", 0))) - { - switch (val) - { - case 1: - t.c_cflag &= ~(CSTOPB); - break; - case 2: - t.c_cflag |= CSTOPB; - break; - default: - xf86Msg (X_ERROR, - "Invalid Option StopBits value: %d\n", val); - return (-1); - break; - } - } - - if ((val = xf86SetIntOption (options, "DataBits", 0))) - { - switch (val) - { - case 5: - t.c_cflag &= ~(CSIZE); - t.c_cflag |= CS5; - break; - case 6: - t.c_cflag &= ~(CSIZE); - t.c_cflag |= CS6; - break; - case 7: - t.c_cflag &= ~(CSIZE); - t.c_cflag |= CS7; - break; - case 8: - t.c_cflag &= ~(CSIZE); - t.c_cflag |= CS8; - break; - default: - xf86Msg (X_ERROR, - "Invalid Option DataBits value: %d\n", val); - return (-1); - break; - } - } - - if ((s = xf86SetStrOption (options, "Parity", NULL))) - { - if (xf86NameCmp (s, "Odd") == 0) - { - t.c_cflag |= PARENB | PARODD; - } - else if (xf86NameCmp (s, "Even") == 0) - { - t.c_cflag |= PARENB; - t.c_cflag &= ~(PARODD); - } - else if (xf86NameCmp (s, "None") == 0) - { - t.c_cflag &= ~(PARENB); - } - else - { - xf86Msg (X_ERROR, "Invalid Option Parity value: %s\n", - s); - return (-1); - } - } - - if ((val = xf86SetIntOption (options, "Vmin", -1)) != -1) - { - t.c_cc[VMIN] = val; - } - if ((val = xf86SetIntOption (options, "Vtime", -1)) != -1) - { - t.c_cc[VTIME] = val; - } - - if ((s = xf86SetStrOption (options, "FlowControl", NULL))) - { - xf86MarkOptionUsedByName (options, "FlowControl"); - if (xf86NameCmp (s, "Xoff") == 0) - { - t.c_iflag |= IXOFF; - } - else if (xf86NameCmp (s, "Xon") == 0) - { - t.c_iflag |= IXON; - } - else if (xf86NameCmp (s, "XonXoff") == 0) - { - t.c_iflag |= IXON|IXOFF; - } - else if (xf86NameCmp (s, "None") == 0) - { - t.c_iflag &= ~(IXON | IXOFF); - } - else - { - xf86Msg (X_ERROR, - "Invalid Option FlowControl value: %s\n", s); - return (-1); - } - } - - if ((xf86SetBoolOption (options, "ClearDTR", FALSE))) - { -#ifdef CLEARDTR_SUPPORT -# if defined(TIOCMBIC) - val = TIOCM_DTR; - SYSCALL (ioctl(fd, TIOCMBIC, &val)); -# else - SYSCALL (ioctl(fd, TIOCCDTR, NULL)); -# endif -#else - xf86Msg (X_WARNING, - "Option ClearDTR not supported on this OS\n"); - return (-1); -#endif - xf86MarkOptionUsedByName (options, "ClearDTR"); - } - - if ((xf86SetBoolOption (options, "ClearRTS", FALSE))) - { - xf86Msg (X_WARNING, - "Option ClearRTS not supported on this OS\n"); - return (-1); - xf86MarkOptionUsedByName (options, "ClearRTS"); - } - - SYSCALL (r = tcsetattr (fd, TCSANOW, &t)); - return (r); -} - -int -xf86SetSerialSpeed (int fd, int speed) -{ - struct termios t; - int baud, r; - - if (fd < 0) - return -1; - - /* Don't try to set parameters for non-tty devices. */ - if (!isatty(fd)) - return 0; - - SYSCALL (tcgetattr (fd, &t)); - - if ((baud = GetBaud (speed))) - { - cfsetispeed (&t, baud); - cfsetospeed (&t, baud); - } - else - { - xf86Msg (X_ERROR, - "Invalid Option BaudRate value: %d\n", speed); - return (-1); - } - - SYSCALL (r = tcsetattr (fd, TCSANOW, &t)); - return (r); -} - -int -xf86ReadSerial (int fd, void *buf, int count) -{ - int r; - int i; - - SYSCALL (r = read (fd, buf, count)); - DebugF("ReadingSerial: 0x%x", - (unsigned char)*(((unsigned char *)buf))); - for (i = 1; i < r; i++) - DebugF(", 0x%x",(unsigned char)*(((unsigned char *)buf) + i)); - DebugF("\n"); - return (r); -} - -int -xf86WriteSerial (int fd, const void *buf, int count) -{ - int r; - int i; - - DebugF("WritingSerial: 0x%x",(unsigned char)*(((unsigned char *)buf))); - for (i = 1; i < count; i++) - ErrorF(", 0x%x",(unsigned char)*(((unsigned char *)buf) + i)); - DebugF("\n"); - SYSCALL (r = write (fd, buf, count)); - return (r); -} - -int -xf86CloseSerial (int fd) -{ - int r; - - SYSCALL (r = close (fd)); - return (r); -} - -int -xf86WaitForInput (int fd, int timeout) -{ - fd_set readfds; - struct timeval to; - int r; - - FD_ZERO(&readfds); - - if (fd >= 0) { - FD_SET(fd, &readfds); - } - - to.tv_sec = timeout / 1000000; - to.tv_usec = timeout % 1000000; - - if (fd >= 0) { - SYSCALL (r = select (FD_SETSIZE, &readfds, NULL, NULL, &to)); - } - else { - SYSCALL (r = select (FD_SETSIZE, NULL, NULL, NULL, &to)); - } - xf86ErrorFVerb (9,"select returned %d\n", r); - return (r); -} - -int -xf86SerialSendBreak (int fd, int duration) -{ - int r; - - SYSCALL (r = tcsendbreak (fd, duration)); - return (r); - -} - -int -xf86FlushInput(int fd) -{ - fd_set fds; - struct timeval timeout; - char c[4]; - - DebugF("FlushingSerial\n"); - if (tcflush(fd, TCIFLUSH) == 0) - return 0; - - timeout.tv_sec = 0; - timeout.tv_usec = 0; - FD_ZERO(&fds); - FD_SET(fd, &fds); - while (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) > 0) { - if (read(fd, &c, sizeof(c)) < 1) - return 0; - FD_ZERO(&fds); - FD_SET(fd, &fds); - } - return 0; -} - -static struct states { - int xf; - int os; -} modemStates[] = { -#ifdef TIOCM_LE - { XF86_M_LE, TIOCM_LE }, -#endif -#ifdef TIOCM_DTR - { XF86_M_DTR, TIOCM_DTR }, -#endif -#ifdef TIOCM_RTS - { XF86_M_RTS, TIOCM_RTS }, -#endif -#ifdef TIOCM_ST - { XF86_M_ST, TIOCM_ST }, -#endif -#ifdef TIOCM_SR - { XF86_M_SR, TIOCM_SR }, -#endif -#ifdef TIOCM_CTS - { XF86_M_CTS, TIOCM_CTS }, -#endif -#ifdef TIOCM_CAR - { XF86_M_CAR, TIOCM_CAR }, -#elif defined(TIOCM_CD) - { XF86_M_CAR, TIOCM_CD }, -#endif -#ifdef TIOCM_RNG - { XF86_M_RNG, TIOCM_RNG }, -#elif defined(TIOCM_RI) - { XF86_M_CAR, TIOCM_RI }, -#endif -#ifdef TIOCM_DSR - { XF86_M_DSR, TIOCM_DSR }, -#endif -}; - -static int numStates = sizeof(modemStates) / sizeof(modemStates[0]); - -static int -xf2osState(int state) -{ - int i; - int ret = 0; - - for (i = 0; i < numStates; i++) - if (state & modemStates[i].xf) - ret |= modemStates[i].os; - return ret; -} - -static int -os2xfState(int state) -{ - int i; - int ret = 0; - - for (i = 0; i < numStates; i++) - if (state & modemStates[i].os) - ret |= modemStates[i].xf; - return ret; -} - -static int -getOsStateMask(void) -{ - int i; - int ret = 0; - for (i = 0; i < numStates; i++) - ret |= modemStates[i].os; - return ret; -} - -static int osStateMask = 0; - -int -xf86SetSerialModemState(int fd, int state) -{ - int ret; - int s; - - if (fd < 0) - return -1; - - /* Don't try to set parameters for non-tty devices. */ - if (!isatty(fd)) - return 0; - -#ifndef TIOCMGET - return -1; -#else - if (!osStateMask) - osStateMask = getOsStateMask(); - - state = xf2osState(state); - SYSCALL((ret = ioctl(fd, TIOCMGET, &s))); - if (ret < 0) - return -1; - s &= ~osStateMask; - s |= state; - SYSCALL((ret = ioctl(fd, TIOCMSET, &s))); - if (ret < 0) - return -1; - else - return 0; -#endif -} - -int -xf86GetSerialModemState(int fd) -{ - int ret; - int s; - - if (fd < 0) - return -1; - - /* Don't try to set parameters for non-tty devices. */ - if (!isatty(fd)) - return 0; - -#ifndef TIOCMGET - return -1; -#else - SYSCALL((ret = ioctl(fd, TIOCMGET, &s))); - if (ret < 0) - return -1; - return os2xfState(s); -#endif -} - -int -xf86SerialModemSetBits(int fd, int bits) -{ - int ret; - int s; - - if (fd < 0) - return -1; - - /* Don't try to set parameters for non-tty devices. */ - if (!isatty(fd)) - return 0; - -#ifndef TIOCMGET - return -1; -#else - s = xf2osState(bits); - SYSCALL((ret = ioctl(fd, TIOCMBIS, &s))); - return ret; -#endif -} - -int -xf86SerialModemClearBits(int fd, int bits) -{ - int ret; - int s; - - if (fd < 0) - return -1; - - /* Don't try to set parameters for non-tty devices. */ - if (!isatty(fd)) - return 0; - -#ifndef TIOCMGET - return -1; -#else - s = xf2osState(bits); - SYSCALL((ret = ioctl(fd, TIOCMBIC, &s))); - return ret; -#endif -} +/* + * Copyright 1993-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project 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. + */ +/* + * + * Copyright (c) 1997 Metro Link Incorporated + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Metro Link shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Metro Link. + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" + +static int +GetBaud (int baudrate) +{ +#ifdef B300 + if (baudrate == 300) + return B300; +#endif +#ifdef B1200 + if (baudrate == 1200) + return B1200; +#endif +#ifdef B2400 + if (baudrate == 2400) + return B2400; +#endif +#ifdef B4800 + if (baudrate == 4800) + return B4800; +#endif +#ifdef B9600 + if (baudrate == 9600) + return B9600; +#endif +#ifdef B19200 + if (baudrate == 19200) + return B19200; +#endif +#ifdef B38400 + if (baudrate == 38400) + return B38400; +#endif +#ifdef B57600 + if (baudrate == 57600) + return B57600; +#endif +#ifdef B115200 + if (baudrate == 115200) + return B115200; +#endif +#ifdef B230400 + if (baudrate == 230400) + return B230400; +#endif +#ifdef B460800 + if (baudrate == 460800) + return B460800; +#endif + return (0); +} + +int +xf86OpenSerial (pointer options) +{ + struct termios t; + int fd, i; + char *dev; + + dev = xf86SetStrOption (options, "Device", NULL); + if (!dev) + { + xf86Msg (X_ERROR, "xf86OpenSerial: No Device specified.\n"); + return (-1); + } + + SYSCALL (fd = open (dev, O_RDWR | O_NONBLOCK)); + if (fd == -1) + { + xf86Msg (X_ERROR, + "xf86OpenSerial: Cannot open device %s\n\t%s.\n", + dev, strerror (errno)); + free(dev); + return (-1); + } + + if (!isatty (fd)) + { + /* Allow non-tty devices to be opened. */ + free(dev); + return (fd); + } + + /* set up default port parameters */ + SYSCALL (tcgetattr (fd, &t)); + t.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR\ + |IGNCR|ICRNL|IXON); + t.c_oflag &= ~OPOST; + t.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + t.c_cflag &= ~(CSIZE|PARENB); + t.c_cflag |= CS8|CLOCAL; + + cfsetispeed (&t, B9600); + cfsetospeed (&t, B9600); + t.c_cc[VMIN] = 1; + t.c_cc[VTIME] = 0; + + SYSCALL (tcsetattr (fd, TCSANOW, &t)); + + if (xf86SetSerial (fd, options) == -1) + { + SYSCALL (close (fd)); + free(dev); + return (-1); + } + + SYSCALL (i = fcntl (fd, F_GETFL, 0)); + if (i == -1) + { + SYSCALL (close (fd)); + free(dev); + return (-1); + } + i &= ~O_NONBLOCK; + SYSCALL (i = fcntl (fd, F_SETFL, i)); + if (i == -1) + { + SYSCALL (close (fd)); + free(dev); + return (-1); + } + free(dev); + return (fd); +} + +int +xf86SetSerial (int fd, pointer options) +{ + struct termios t; + int val; + const char *s; + int baud, r; + + if (fd < 0) + return -1; + + /* Don't try to set parameters for non-tty devices. */ + if (!isatty(fd)) + return 0; + + SYSCALL (tcgetattr (fd, &t)); + + if ((val = xf86SetIntOption (options, "BaudRate", 0))) + { + if ((baud = GetBaud (val))) + { + cfsetispeed (&t, baud); + cfsetospeed (&t, baud); + } + else + { + xf86Msg (X_ERROR, + "Invalid Option BaudRate value: %d\n", val); + return (-1); + } + } + + if ((val = xf86SetIntOption (options, "StopBits", 0))) + { + switch (val) + { + case 1: + t.c_cflag &= ~(CSTOPB); + break; + case 2: + t.c_cflag |= CSTOPB; + break; + default: + xf86Msg (X_ERROR, + "Invalid Option StopBits value: %d\n", val); + return (-1); + break; + } + } + + if ((val = xf86SetIntOption (options, "DataBits", 0))) + { + switch (val) + { + case 5: + t.c_cflag &= ~(CSIZE); + t.c_cflag |= CS5; + break; + case 6: + t.c_cflag &= ~(CSIZE); + t.c_cflag |= CS6; + break; + case 7: + t.c_cflag &= ~(CSIZE); + t.c_cflag |= CS7; + break; + case 8: + t.c_cflag &= ~(CSIZE); + t.c_cflag |= CS8; + break; + default: + xf86Msg (X_ERROR, + "Invalid Option DataBits value: %d\n", val); + return (-1); + break; + } + } + + if ((s = xf86SetStrOption (options, "Parity", NULL))) + { + if (xf86NameCmp (s, "Odd") == 0) + { + t.c_cflag |= PARENB | PARODD; + } + else if (xf86NameCmp (s, "Even") == 0) + { + t.c_cflag |= PARENB; + t.c_cflag &= ~(PARODD); + } + else if (xf86NameCmp (s, "None") == 0) + { + t.c_cflag &= ~(PARENB); + } + else + { + xf86Msg (X_ERROR, "Invalid Option Parity value: %s\n", + s); + return (-1); + } + } + + if ((val = xf86SetIntOption (options, "Vmin", -1)) != -1) + { + t.c_cc[VMIN] = val; + } + if ((val = xf86SetIntOption (options, "Vtime", -1)) != -1) + { + t.c_cc[VTIME] = val; + } + + if ((s = xf86SetStrOption (options, "FlowControl", NULL))) + { + xf86MarkOptionUsedByName (options, "FlowControl"); + if (xf86NameCmp (s, "Xoff") == 0) + { + t.c_iflag |= IXOFF; + } + else if (xf86NameCmp (s, "Xon") == 0) + { + t.c_iflag |= IXON; + } + else if (xf86NameCmp (s, "XonXoff") == 0) + { + t.c_iflag |= IXON|IXOFF; + } + else if (xf86NameCmp (s, "None") == 0) + { + t.c_iflag &= ~(IXON | IXOFF); + } + else + { + xf86Msg (X_ERROR, + "Invalid Option FlowControl value: %s\n", s); + return (-1); + } + } + + if ((xf86SetBoolOption (options, "ClearDTR", FALSE))) + { +#ifdef CLEARDTR_SUPPORT +# if defined(TIOCMBIC) + val = TIOCM_DTR; + SYSCALL (ioctl(fd, TIOCMBIC, &val)); +# else + SYSCALL (ioctl(fd, TIOCCDTR, NULL)); +# endif +#else + xf86Msg (X_WARNING, + "Option ClearDTR not supported on this OS\n"); + return (-1); +#endif + xf86MarkOptionUsedByName (options, "ClearDTR"); + } + + if ((xf86SetBoolOption (options, "ClearRTS", FALSE))) + { + xf86Msg (X_WARNING, + "Option ClearRTS not supported on this OS\n"); + return (-1); + xf86MarkOptionUsedByName (options, "ClearRTS"); + } + + SYSCALL (r = tcsetattr (fd, TCSANOW, &t)); + return (r); +} + +int +xf86SetSerialSpeed (int fd, int speed) +{ + struct termios t; + int baud, r; + + if (fd < 0) + return -1; + + /* Don't try to set parameters for non-tty devices. */ + if (!isatty(fd)) + return 0; + + SYSCALL (tcgetattr (fd, &t)); + + if ((baud = GetBaud (speed))) + { + cfsetispeed (&t, baud); + cfsetospeed (&t, baud); + } + else + { + xf86Msg (X_ERROR, + "Invalid Option BaudRate value: %d\n", speed); + return (-1); + } + + SYSCALL (r = tcsetattr (fd, TCSANOW, &t)); + return (r); +} + +int +xf86ReadSerial (int fd, void *buf, int count) +{ + int r; + int i; + + SYSCALL (r = read (fd, buf, count)); + DebugF("ReadingSerial: 0x%x", + (unsigned char)*(((unsigned char *)buf))); + for (i = 1; i < r; i++) + DebugF(", 0x%x",(unsigned char)*(((unsigned char *)buf) + i)); + DebugF("\n"); + return (r); +} + +int +xf86WriteSerial (int fd, const void *buf, int count) +{ + int r; + int i; + + DebugF("WritingSerial: 0x%x",(unsigned char)*(((unsigned char *)buf))); + for (i = 1; i < count; i++) + ErrorF(", 0x%x",(unsigned char)*(((unsigned char *)buf) + i)); + DebugF("\n"); + SYSCALL (r = write (fd, buf, count)); + return (r); +} + +int +xf86CloseSerial (int fd) +{ + int r; + + SYSCALL (r = close (fd)); + return (r); +} + +int +xf86WaitForInput (int fd, int timeout) +{ + fd_set readfds; + struct timeval to; + int r; + + FD_ZERO(&readfds); + + if (fd >= 0) { + FD_SET(fd, &readfds); + } + + to.tv_sec = timeout / 1000000; + to.tv_usec = timeout % 1000000; + + if (fd >= 0) { + SYSCALL (r = select (FD_SETSIZE, &readfds, NULL, NULL, &to)); + } + else { + SYSCALL (r = select (FD_SETSIZE, NULL, NULL, NULL, &to)); + } + xf86ErrorFVerb (9,"select returned %d\n", r); + return (r); +} + +int +xf86SerialSendBreak (int fd, int duration) +{ + int r; + + SYSCALL (r = tcsendbreak (fd, duration)); + return (r); + +} + +int +xf86FlushInput(int fd) +{ + fd_set fds; + struct timeval timeout; + char c[4]; + + DebugF("FlushingSerial\n"); + if (tcflush(fd, TCIFLUSH) == 0) + return 0; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(fd, &fds); + while (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) > 0) { + if (read(fd, &c, sizeof(c)) < 1) + return 0; + FD_ZERO(&fds); + FD_SET(fd, &fds); + } + return 0; +} + +static struct states { + int xf; + int os; +} modemStates[] = { +#ifdef TIOCM_LE + { XF86_M_LE, TIOCM_LE }, +#endif +#ifdef TIOCM_DTR + { XF86_M_DTR, TIOCM_DTR }, +#endif +#ifdef TIOCM_RTS + { XF86_M_RTS, TIOCM_RTS }, +#endif +#ifdef TIOCM_ST + { XF86_M_ST, TIOCM_ST }, +#endif +#ifdef TIOCM_SR + { XF86_M_SR, TIOCM_SR }, +#endif +#ifdef TIOCM_CTS + { XF86_M_CTS, TIOCM_CTS }, +#endif +#ifdef TIOCM_CAR + { XF86_M_CAR, TIOCM_CAR }, +#elif defined(TIOCM_CD) + { XF86_M_CAR, TIOCM_CD }, +#endif +#ifdef TIOCM_RNG + { XF86_M_RNG, TIOCM_RNG }, +#elif defined(TIOCM_RI) + { XF86_M_CAR, TIOCM_RI }, +#endif +#ifdef TIOCM_DSR + { XF86_M_DSR, TIOCM_DSR }, +#endif +}; + +static int numStates = sizeof(modemStates) / sizeof(modemStates[0]); + +static int +xf2osState(int state) +{ + int i; + int ret = 0; + + for (i = 0; i < numStates; i++) + if (state & modemStates[i].xf) + ret |= modemStates[i].os; + return ret; +} + +static int +os2xfState(int state) +{ + int i; + int ret = 0; + + for (i = 0; i < numStates; i++) + if (state & modemStates[i].os) + ret |= modemStates[i].xf; + return ret; +} + +static int +getOsStateMask(void) +{ + int i; + int ret = 0; + for (i = 0; i < numStates; i++) + ret |= modemStates[i].os; + return ret; +} + +static int osStateMask = 0; + +int +xf86SetSerialModemState(int fd, int state) +{ + int ret; + int s; + + if (fd < 0) + return -1; + + /* Don't try to set parameters for non-tty devices. */ + if (!isatty(fd)) + return 0; + +#ifndef TIOCMGET + return -1; +#else + if (!osStateMask) + osStateMask = getOsStateMask(); + + state = xf2osState(state); + SYSCALL((ret = ioctl(fd, TIOCMGET, &s))); + if (ret < 0) + return -1; + s &= ~osStateMask; + s |= state; + SYSCALL((ret = ioctl(fd, TIOCMSET, &s))); + if (ret < 0) + return -1; + else + return 0; +#endif +} + +int +xf86GetSerialModemState(int fd) +{ + int ret; + int s; + + if (fd < 0) + return -1; + + /* Don't try to set parameters for non-tty devices. */ + if (!isatty(fd)) + return 0; + +#ifndef TIOCMGET + return -1; +#else + SYSCALL((ret = ioctl(fd, TIOCMGET, &s))); + if (ret < 0) + return -1; + return os2xfState(s); +#endif +} + +int +xf86SerialModemSetBits(int fd, int bits) +{ + int ret; + int s; + + if (fd < 0) + return -1; + + /* Don't try to set parameters for non-tty devices. */ + if (!isatty(fd)) + return 0; + +#ifndef TIOCMGET + return -1; +#else + s = xf2osState(bits); + SYSCALL((ret = ioctl(fd, TIOCMBIS, &s))); + return ret; +#endif +} + +int +xf86SerialModemClearBits(int fd, int bits) +{ + int ret; + int s; + + if (fd < 0) + return -1; + + /* Don't try to set parameters for non-tty devices. */ + if (!isatty(fd)) + return 0; + +#ifndef TIOCMGET + return -1; +#else + s = xf2osState(bits); + SYSCALL((ret = ioctl(fd, TIOCMBIC, &s))); + return ret; +#endif +} diff --git a/xorg-server/hw/xfree86/os-support/shared/vidmem.c b/xorg-server/hw/xfree86/os-support/shared/vidmem.c index 803ce09bd..6358138d8 100644 --- a/xorg-server/hw/xfree86/os-support/shared/vidmem.c +++ b/xorg-server/hw/xfree86/os-support/shared/vidmem.c @@ -1,296 +1,296 @@ -/* - * Copyright (c) 1993-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) 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 copyright holder(s) and author(s). - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "input.h" -#include "scrnintstr.h" - -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86OSpriv.h" - -/* - * This file contains the common part of the video memory mapping functions - */ - -/* - * Get a piece of the ScrnInfoRec. At the moment, this is only used to hold - * the MTRR option information, but it is likely to be expanded if we do - * auto unmapping of memory at VT switch. - * - */ - -typedef struct { - unsigned long physBase; - unsigned long size; - pointer virtBase; - pointer mtrrInfo; - int flags; -} MappingRec, *MappingPtr; - -typedef struct { - int numMappings; - MappingPtr * mappings; - Bool mtrrEnabled; - MessageType mtrrFrom; - Bool mtrrOptChecked; - ScrnInfoPtr pScrn; -} VidMapRec, *VidMapPtr; - -static int vidMapIndex = -1; - -#define VIDMAPPTR(p) ((VidMapPtr)((p)->privates[vidMapIndex].ptr)) - -static VidMemInfo vidMemInfo = {FALSE, }; -static VidMapRec vidMapRec = {0, NULL, TRUE, X_DEFAULT, FALSE, NULL}; - -static VidMapPtr -getVidMapRec(int scrnIndex) -{ - VidMapPtr vp; - ScrnInfoPtr pScrn; - - if ((scrnIndex < 0) || - !(pScrn = xf86Screens[scrnIndex])) - return &vidMapRec; - - if (vidMapIndex < 0) - vidMapIndex = xf86AllocateScrnInfoPrivateIndex(); - - if (VIDMAPPTR(pScrn) != NULL) - return VIDMAPPTR(pScrn); - - vp = pScrn->privates[vidMapIndex].ptr = xnfcalloc(sizeof(VidMapRec), 1); - vp->mtrrEnabled = TRUE; /* default to enabled */ - vp->mtrrFrom = X_DEFAULT; - vp->mtrrOptChecked = FALSE; - vp->pScrn = pScrn; - return vp; -} - -static MappingPtr -newMapping(VidMapPtr vp) -{ - vp->mappings = xnfrealloc(vp->mappings, sizeof(MappingPtr) * - (vp->numMappings + 1)); - vp->mappings[vp->numMappings] = xnfcalloc(sizeof(MappingRec), 1); - return vp->mappings[vp->numMappings++]; -} - -static MappingPtr -findMapping(VidMapPtr vp, pointer vbase, unsigned long size) -{ - int i; - - for (i = 0; i < vp->numMappings; i++) { - if (vp->mappings[i]->virtBase == vbase && - vp->mappings[i]->size == size) - return vp->mappings[i]; - } - return NULL; -} - -static void -removeMapping(VidMapPtr vp, MappingPtr mp) -{ - int i, found = 0; - - for (i = 0; i < vp->numMappings; i++) { - if (vp->mappings[i] == mp) { - found = 1; - xfree(vp->mappings[i]); - } else if (found) { - vp->mappings[i - 1] = vp->mappings[i]; - } - } - vp->numMappings--; - vp->mappings[vp->numMappings] = NULL; -} - -enum { OPTION_MTRR }; -static const OptionInfoRec opts[] = -{ - { OPTION_MTRR, "mtrr", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE } -}; - -static void -checkMtrrOption(VidMapPtr vp) -{ - if (!vp->mtrrOptChecked && vp->pScrn && vp->pScrn->options != NULL) { - OptionInfoPtr options; - - options = xnfalloc(sizeof(opts)); - (void)memcpy(options, opts, sizeof(opts)); - xf86ProcessOptions(vp->pScrn->scrnIndex, vp->pScrn->options, - options); - if (xf86GetOptValBool(options, OPTION_MTRR, &vp->mtrrEnabled)) - vp->mtrrFrom = X_CONFIG; - xfree(options); - vp->mtrrOptChecked = TRUE; - } -} - -void -xf86MakeNewMapping(int ScreenNum, int Flags, unsigned long Base, unsigned long Size, pointer Vbase) -{ - VidMapPtr vp; - MappingPtr mp; - - vp = getVidMapRec(ScreenNum); - mp = newMapping(vp); - mp->physBase = Base; - mp->size = Size; - mp->virtBase = Vbase; - mp->flags = Flags; -} - -void -xf86InitVidMem(void) -{ - if (!vidMemInfo.initialised) { - memset(&vidMemInfo, 0, sizeof(VidMemInfo)); - xf86OSInitVidMem(&vidMemInfo); - } -} - -pointer -xf86MapVidMem(int ScreenNum, int Flags, unsigned long Base, unsigned long Size) -{ - pointer vbase = NULL; - VidMapPtr vp; - MappingPtr mp; - - if (((Flags & VIDMEM_FRAMEBUFFER) && - (Flags & (VIDMEM_MMIO | VIDMEM_MMIO_32BIT)))) - FatalError("Mapping memory with more than one type\n"); - - xf86InitVidMem(); - if (!vidMemInfo.initialised || !vidMemInfo.mapMem) - return NULL; - - vbase = vidMemInfo.mapMem(ScreenNum, Base, Size, Flags); - - if (!vbase || vbase == (pointer)-1) - return NULL; - - vp = getVidMapRec(ScreenNum); - mp = newMapping(vp); - mp->physBase = Base; - mp->size = Size; - mp->virtBase = vbase; - mp->flags = Flags; - - /* - * Check the "mtrr" option even when MTRR isn't supported to avoid - * warnings about unrecognised options. - */ - checkMtrrOption(vp); - - if (vp->mtrrEnabled && vidMemInfo.setWC) { - if (Flags & (VIDMEM_MMIO | VIDMEM_MMIO_32BIT)) - mp->mtrrInfo = - vidMemInfo.setWC(ScreenNum, Base, Size, FALSE, - vp->mtrrFrom); - else if (Flags & VIDMEM_FRAMEBUFFER) - mp->mtrrInfo = - vidMemInfo.setWC(ScreenNum, Base, Size, TRUE, - vp->mtrrFrom); - } - return vbase; -} - -void -xf86UnMapVidMem(int ScreenNum, pointer Base, unsigned long Size) -{ - VidMapPtr vp; - MappingPtr mp; - - if (!vidMemInfo.initialised || !vidMemInfo.unmapMem) { - xf86DrvMsg(ScreenNum, X_WARNING, - "xf86UnMapVidMem() called before xf86MapVidMem()\n"); - return; - } - - vp = getVidMapRec(ScreenNum); - mp = findMapping(vp, Base, Size); - if (!mp) { - xf86DrvMsg(ScreenNum, X_WARNING, - "xf86UnMapVidMem: cannot find region for [%p,0x%lx]\n", - Base, Size); - return; - } - if (vp->mtrrEnabled && vidMemInfo.undoWC && mp) - vidMemInfo.undoWC(ScreenNum, mp->mtrrInfo); - - vidMemInfo.unmapMem(ScreenNum, Base, Size); - removeMapping(vp, mp); -} - -Bool -xf86CheckMTRR(int ScreenNum) -{ - VidMapPtr vp = getVidMapRec(ScreenNum); - - /* - * Check the "mtrr" option even when MTRR isn't supported to avoid - * warnings about unrecognised options. - */ - checkMtrrOption(vp); - - if (vp->mtrrEnabled && vidMemInfo.setWC) - return TRUE; - - return FALSE; -} - -Bool -xf86LinearVidMem(void) -{ - xf86InitVidMem(); - return vidMemInfo.linearSupported; -} - -void -xf86MapReadSideEffects(int ScreenNum, int Flags, pointer base, - unsigned long Size) -{ - if (!(Flags & VIDMEM_READSIDEEFFECT)) - return; - - if (!vidMemInfo.initialised || !vidMemInfo.readSideEffects) - return; - - vidMemInfo.readSideEffects(ScreenNum, base, Size); -} - +/* + * Copyright (c) 1993-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) 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 copyright holder(s) and author(s). + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "input.h" +#include "scrnintstr.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86OSpriv.h" + +/* + * This file contains the common part of the video memory mapping functions + */ + +/* + * Get a piece of the ScrnInfoRec. At the moment, this is only used to hold + * the MTRR option information, but it is likely to be expanded if we do + * auto unmapping of memory at VT switch. + * + */ + +typedef struct { + unsigned long physBase; + unsigned long size; + pointer virtBase; + pointer mtrrInfo; + int flags; +} MappingRec, *MappingPtr; + +typedef struct { + int numMappings; + MappingPtr * mappings; + Bool mtrrEnabled; + MessageType mtrrFrom; + Bool mtrrOptChecked; + ScrnInfoPtr pScrn; +} VidMapRec, *VidMapPtr; + +static int vidMapIndex = -1; + +#define VIDMAPPTR(p) ((VidMapPtr)((p)->privates[vidMapIndex].ptr)) + +static VidMemInfo vidMemInfo = {FALSE, }; +static VidMapRec vidMapRec = {0, NULL, TRUE, X_DEFAULT, FALSE, NULL}; + +static VidMapPtr +getVidMapRec(int scrnIndex) +{ + VidMapPtr vp; + ScrnInfoPtr pScrn; + + if ((scrnIndex < 0) || + !(pScrn = xf86Screens[scrnIndex])) + return &vidMapRec; + + if (vidMapIndex < 0) + vidMapIndex = xf86AllocateScrnInfoPrivateIndex(); + + if (VIDMAPPTR(pScrn) != NULL) + return VIDMAPPTR(pScrn); + + vp = pScrn->privates[vidMapIndex].ptr = xnfcalloc(sizeof(VidMapRec), 1); + vp->mtrrEnabled = TRUE; /* default to enabled */ + vp->mtrrFrom = X_DEFAULT; + vp->mtrrOptChecked = FALSE; + vp->pScrn = pScrn; + return vp; +} + +static MappingPtr +newMapping(VidMapPtr vp) +{ + vp->mappings = xnfrealloc(vp->mappings, sizeof(MappingPtr) * + (vp->numMappings + 1)); + vp->mappings[vp->numMappings] = xnfcalloc(sizeof(MappingRec), 1); + return vp->mappings[vp->numMappings++]; +} + +static MappingPtr +findMapping(VidMapPtr vp, pointer vbase, unsigned long size) +{ + int i; + + for (i = 0; i < vp->numMappings; i++) { + if (vp->mappings[i]->virtBase == vbase && + vp->mappings[i]->size == size) + return vp->mappings[i]; + } + return NULL; +} + +static void +removeMapping(VidMapPtr vp, MappingPtr mp) +{ + int i, found = 0; + + for (i = 0; i < vp->numMappings; i++) { + if (vp->mappings[i] == mp) { + found = 1; + free(vp->mappings[i]); + } else if (found) { + vp->mappings[i - 1] = vp->mappings[i]; + } + } + vp->numMappings--; + vp->mappings[vp->numMappings] = NULL; +} + +enum { OPTION_MTRR }; +static const OptionInfoRec opts[] = +{ + { OPTION_MTRR, "mtrr", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +static void +checkMtrrOption(VidMapPtr vp) +{ + if (!vp->mtrrOptChecked && vp->pScrn && vp->pScrn->options != NULL) { + OptionInfoPtr options; + + options = xnfalloc(sizeof(opts)); + (void)memcpy(options, opts, sizeof(opts)); + xf86ProcessOptions(vp->pScrn->scrnIndex, vp->pScrn->options, + options); + if (xf86GetOptValBool(options, OPTION_MTRR, &vp->mtrrEnabled)) + vp->mtrrFrom = X_CONFIG; + free(options); + vp->mtrrOptChecked = TRUE; + } +} + +void +xf86MakeNewMapping(int ScreenNum, int Flags, unsigned long Base, unsigned long Size, pointer Vbase) +{ + VidMapPtr vp; + MappingPtr mp; + + vp = getVidMapRec(ScreenNum); + mp = newMapping(vp); + mp->physBase = Base; + mp->size = Size; + mp->virtBase = Vbase; + mp->flags = Flags; +} + +void +xf86InitVidMem(void) +{ + if (!vidMemInfo.initialised) { + memset(&vidMemInfo, 0, sizeof(VidMemInfo)); + xf86OSInitVidMem(&vidMemInfo); + } +} + +pointer +xf86MapVidMem(int ScreenNum, int Flags, unsigned long Base, unsigned long Size) +{ + pointer vbase = NULL; + VidMapPtr vp; + MappingPtr mp; + + if (((Flags & VIDMEM_FRAMEBUFFER) && + (Flags & (VIDMEM_MMIO | VIDMEM_MMIO_32BIT)))) + FatalError("Mapping memory with more than one type\n"); + + xf86InitVidMem(); + if (!vidMemInfo.initialised || !vidMemInfo.mapMem) + return NULL; + + vbase = vidMemInfo.mapMem(ScreenNum, Base, Size, Flags); + + if (!vbase || vbase == (pointer)-1) + return NULL; + + vp = getVidMapRec(ScreenNum); + mp = newMapping(vp); + mp->physBase = Base; + mp->size = Size; + mp->virtBase = vbase; + mp->flags = Flags; + + /* + * Check the "mtrr" option even when MTRR isn't supported to avoid + * warnings about unrecognised options. + */ + checkMtrrOption(vp); + + if (vp->mtrrEnabled && vidMemInfo.setWC) { + if (Flags & (VIDMEM_MMIO | VIDMEM_MMIO_32BIT)) + mp->mtrrInfo = + vidMemInfo.setWC(ScreenNum, Base, Size, FALSE, + vp->mtrrFrom); + else if (Flags & VIDMEM_FRAMEBUFFER) + mp->mtrrInfo = + vidMemInfo.setWC(ScreenNum, Base, Size, TRUE, + vp->mtrrFrom); + } + return vbase; +} + +void +xf86UnMapVidMem(int ScreenNum, pointer Base, unsigned long Size) +{ + VidMapPtr vp; + MappingPtr mp; + + if (!vidMemInfo.initialised || !vidMemInfo.unmapMem) { + xf86DrvMsg(ScreenNum, X_WARNING, + "xf86UnMapVidMem() called before xf86MapVidMem()\n"); + return; + } + + vp = getVidMapRec(ScreenNum); + mp = findMapping(vp, Base, Size); + if (!mp) { + xf86DrvMsg(ScreenNum, X_WARNING, + "xf86UnMapVidMem: cannot find region for [%p,0x%lx]\n", + Base, Size); + return; + } + if (vp->mtrrEnabled && vidMemInfo.undoWC && mp) + vidMemInfo.undoWC(ScreenNum, mp->mtrrInfo); + + vidMemInfo.unmapMem(ScreenNum, Base, Size); + removeMapping(vp, mp); +} + +Bool +xf86CheckMTRR(int ScreenNum) +{ + VidMapPtr vp = getVidMapRec(ScreenNum); + + /* + * Check the "mtrr" option even when MTRR isn't supported to avoid + * warnings about unrecognised options. + */ + checkMtrrOption(vp); + + if (vp->mtrrEnabled && vidMemInfo.setWC) + return TRUE; + + return FALSE; +} + +Bool +xf86LinearVidMem(void) +{ + xf86InitVidMem(); + return vidMemInfo.linearSupported; +} + +void +xf86MapReadSideEffects(int ScreenNum, int Flags, pointer base, + unsigned long Size) +{ + if (!(Flags & VIDMEM_READSIDEEFFECT)) + return; + + if (!vidMemInfo.initialised || !vidMemInfo.readSideEffects) + return; + + vidMemInfo.readSideEffects(ScreenNum, base, Size); +} + diff --git a/xorg-server/hw/xfree86/os-support/solaris/sun_agp.c b/xorg-server/hw/xfree86/os-support/solaris/sun_agp.c index e6a55a48b..a5fb5c6e6 100644 --- a/xorg-server/hw/xfree86/os-support/solaris/sun_agp.c +++ b/xorg-server/hw/xfree86/os-support/solaris/sun_agp.c @@ -1,327 +1,327 @@ -/* - * Abstraction of the AGP GART interface. - * - * This version is for Solaris. - * - * Copyright © 2000 VA Linux Systems, Inc. - * Copyright © 2001 The XFree86 Project, Inc. - */ -/* Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86_OSproc.h" -#include -#include -#include -#include -#include - -/* AGP page size is independent of the host page size. */ -#ifndef AGP_PAGE_SIZE -#define AGP_PAGE_SIZE 4096 -#endif - -static int gartFd = -1; -static int acquiredScreen = -1; -static Bool initDone = FALSE; -/* - * Close /dev/agpgart. This frees all associated memory allocated during - * this server generation. - */ -Bool -xf86GARTCloseScreen(int screenNum) -{ - if (gartFd != -1) { - close(gartFd); - acquiredScreen = -1; - gartFd = -1; - initDone = FALSE; - - xf86DrvMsg(screenNum, X_INFO, - "xf86GARTCloseScreen: device closed successfully\n"); - - } - return TRUE; -} - -/* - * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called. - */ -static Bool -GARTInit(int screenNum) -{ - if (initDone) - return (gartFd != -1); - - if (gartFd == -1) - gartFd = open(AGP_DEVICE, O_RDWR); - else - return FALSE; - - if (gartFd == -1) { - xf86DrvMsg(screenNum, X_ERROR, - "GARTInit: Unable to open " AGP_DEVICE " (%s)\n", - strerror(errno)); - return FALSE; - } - - initDone = TRUE; - xf86DrvMsg(screenNum, X_INFO, - "GARTInit: " AGP_DEVICE " opened successfully\n"); - - return TRUE; -} - -Bool -xf86AgpGARTSupported(void) -{ - return (GARTInit(-1)); - -} - -AgpInfoPtr -xf86GetAGPInfo(int screenNum) -{ - agp_info_t agpinf; - AgpInfoPtr info; - - if (!GARTInit(screenNum)) - return NULL; - - if ((info = xcalloc(sizeof(AgpInfo), 1)) == NULL) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86GetAGPInfo: Failed to allocate AgpInfo\n"); - return NULL; - } - - if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { - xf86DrvMsg(screenNum, X_ERROR, - "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n", - strerror(errno)); - return NULL; - } - - info->bridgeId = agpinf.agpi_devid; - info->agpMode = agpinf.agpi_mode; - info->base = agpinf.agpi_aperbase; - info->size = agpinf.agpi_apersize; - info->totalPages = (unsigned long)agpinf.agpi_pgtotal; - info->systemPages = (unsigned long)agpinf.agpi_pgsystem; - info->usedPages = (unsigned long)agpinf.agpi_pgused; - - return info; -} - -Bool -xf86AcquireGART(int screenNum) -{ - - if (!GARTInit(screenNum)) - return FALSE; - - if (acquiredScreen != screenNum) { - if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) { - xf86DrvMsg(screenNum, X_WARNING, - "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n", - strerror(errno)); - return FALSE; - } - acquiredScreen = screenNum; - xf86DrvMsg(screenNum, X_INFO, - "xf86AcquireGART: AGPIOC_ACQUIRE succeeded\n"); - } - return TRUE; -} - -Bool -xf86ReleaseGART(int screenNum) -{ - - if (!GARTInit(screenNum)) - return FALSE; - - if (acquiredScreen == screenNum) { - /* - * The FreeBSD agp driver removes allocations on release. - * The Solaris driver doesn't. xf86ReleaseGART() is expected - * to give up access to the GART, but not to remove any - * allocations. - */ - - if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) { - xf86DrvMsg(screenNum, X_WARNING, - "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n", - strerror(errno)); - return FALSE; - } - acquiredScreen = -1; - xf86DrvMsg(screenNum, X_INFO, - "xf86ReleaseGART: AGPIOC_RELEASE succeeded\n"); - return TRUE; - } - return FALSE; -} - -int -xf86AllocateGARTMemory(int screenNum, unsigned long size, int type, - unsigned long *physical) -{ - agp_allocate_t alloc; - int pages; - - /* - * Allocates "size" bytes of GART memory (rounds up to the next - * page multiple) or type "type". A handle (key) for the allocated - * memory is returned. On error, the return value is -1. - * "size" should be larger than 0, or AGPIOC_ALLOCATE ioctl will - * return error. - */ - - if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) - return -1; - - pages = (size / AGP_PAGE_SIZE); - if (size % AGP_PAGE_SIZE != 0) - pages++; - - alloc.agpa_pgcount = pages; - alloc.agpa_type = type; - - if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: " - "allocation of %d pages failed\n\t(%s)\n", pages, - strerror(errno)); - return -1; - } - - if (physical) - *physical = (unsigned long)alloc.agpa_physical; - - return alloc.agpa_key; -} - -Bool -xf86DeallocateGARTMemory(int screenNum, int key) -{ - if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) - return FALSE; - - if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86DeAllocateGARTMemory: " - "deallocation of gart memory with key %d failed\n" - "\t(%s)\n", key, strerror(errno)); - return FALSE; - } - - return TRUE; -} - -/* Bind GART memory with "key" at "offset" */ -Bool -xf86BindGARTMemory(int screenNum, int key, unsigned long offset) -{ - agp_bind_t bind; - int pageOffset; - - if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) - return FALSE; - - if (offset % AGP_PAGE_SIZE != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " - "offset (0x%lx) is not page-aligned (%d)\n", - offset, AGP_PAGE_SIZE); - return FALSE; - } - pageOffset = offset / AGP_PAGE_SIZE; - - xf86DrvMsgVerb(screenNum, X_INFO, 3, - "xf86BindGARTMemory: bind key %d at 0x%08lx " - "(pgoffset %d)\n", key, offset, pageOffset); - - bind.agpb_pgstart = pageOffset; - bind.agpb_key = key; - - if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " - "binding of gart memory with key %d\n" - "\tat offset 0x%lx failed (%s)\n", - key, offset, strerror(errno)); - return FALSE; - } - - return TRUE; -} - -/* Unbind GART memory with "key" */ -Bool -xf86UnbindGARTMemory(int screenNum, int key) -{ - agp_unbind_t unbind; - - if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) - return FALSE; - - unbind.agpu_pri = 0; - unbind.agpu_key = key; - - if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: " - "unbinding of gart memory with key %d " - "failed (%s)\n", key, strerror(errno)); - return FALSE; - } - - xf86DrvMsgVerb(screenNum, X_INFO, 3, - "xf86UnbindGARTMemory: unbind key %d\n", key); - - return TRUE; -} - - -/* XXX Interface may change. */ -Bool -xf86EnableAGP(int screenNum, CARD32 mode) -{ - agp_setup_t setup; - - if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) - return FALSE; - - setup.agps_mode = mode; - if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) { - xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: " - "AGPIOC_SETUP with mode %x failed (%s)\n", - mode, strerror(errno)); - return FALSE; - } - - return TRUE; -} - +/* + * Abstraction of the AGP GART interface. + * + * This version is for Solaris. + * + * Copyright © 2000 VA Linux Systems, Inc. + * Copyright © 2001 The XFree86 Project, Inc. + */ +/* Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86_OSproc.h" +#include +#include +#include +#include +#include + +/* AGP page size is independent of the host page size. */ +#ifndef AGP_PAGE_SIZE +#define AGP_PAGE_SIZE 4096 +#endif + +static int gartFd = -1; +static int acquiredScreen = -1; +static Bool initDone = FALSE; +/* + * Close /dev/agpgart. This frees all associated memory allocated during + * this server generation. + */ +Bool +xf86GARTCloseScreen(int screenNum) +{ + if (gartFd != -1) { + close(gartFd); + acquiredScreen = -1; + gartFd = -1; + initDone = FALSE; + + xf86DrvMsg(screenNum, X_INFO, + "xf86GARTCloseScreen: device closed successfully\n"); + + } + return TRUE; +} + +/* + * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called. + */ +static Bool +GARTInit(int screenNum) +{ + if (initDone) + return (gartFd != -1); + + if (gartFd == -1) + gartFd = open(AGP_DEVICE, O_RDWR); + else + return FALSE; + + if (gartFd == -1) { + xf86DrvMsg(screenNum, X_ERROR, + "GARTInit: Unable to open " AGP_DEVICE " (%s)\n", + strerror(errno)); + return FALSE; + } + + initDone = TRUE; + xf86DrvMsg(screenNum, X_INFO, + "GARTInit: " AGP_DEVICE " opened successfully\n"); + + return TRUE; +} + +Bool +xf86AgpGARTSupported(void) +{ + return (GARTInit(-1)); + +} + +AgpInfoPtr +xf86GetAGPInfo(int screenNum) +{ + agp_info_t agpinf; + AgpInfoPtr info; + + if (!GARTInit(screenNum)) + return NULL; + + if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86GetAGPInfo: Failed to allocate AgpInfo\n"); + return NULL; + } + + if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { + xf86DrvMsg(screenNum, X_ERROR, + "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n", + strerror(errno)); + return NULL; + } + + info->bridgeId = agpinf.agpi_devid; + info->agpMode = agpinf.agpi_mode; + info->base = agpinf.agpi_aperbase; + info->size = agpinf.agpi_apersize; + info->totalPages = (unsigned long)agpinf.agpi_pgtotal; + info->systemPages = (unsigned long)agpinf.agpi_pgsystem; + info->usedPages = (unsigned long)agpinf.agpi_pgused; + + return info; +} + +Bool +xf86AcquireGART(int screenNum) +{ + + if (!GARTInit(screenNum)) + return FALSE; + + if (acquiredScreen != screenNum) { + if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) { + xf86DrvMsg(screenNum, X_WARNING, + "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n", + strerror(errno)); + return FALSE; + } + acquiredScreen = screenNum; + xf86DrvMsg(screenNum, X_INFO, + "xf86AcquireGART: AGPIOC_ACQUIRE succeeded\n"); + } + return TRUE; +} + +Bool +xf86ReleaseGART(int screenNum) +{ + + if (!GARTInit(screenNum)) + return FALSE; + + if (acquiredScreen == screenNum) { + /* + * The FreeBSD agp driver removes allocations on release. + * The Solaris driver doesn't. xf86ReleaseGART() is expected + * to give up access to the GART, but not to remove any + * allocations. + */ + + if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) { + xf86DrvMsg(screenNum, X_WARNING, + "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n", + strerror(errno)); + return FALSE; + } + acquiredScreen = -1; + xf86DrvMsg(screenNum, X_INFO, + "xf86ReleaseGART: AGPIOC_RELEASE succeeded\n"); + return TRUE; + } + return FALSE; +} + +int +xf86AllocateGARTMemory(int screenNum, unsigned long size, int type, + unsigned long *physical) +{ + agp_allocate_t alloc; + int pages; + + /* + * Allocates "size" bytes of GART memory (rounds up to the next + * page multiple) or type "type". A handle (key) for the allocated + * memory is returned. On error, the return value is -1. + * "size" should be larger than 0, or AGPIOC_ALLOCATE ioctl will + * return error. + */ + + if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) + return -1; + + pages = (size / AGP_PAGE_SIZE); + if (size % AGP_PAGE_SIZE != 0) + pages++; + + alloc.agpa_pgcount = pages; + alloc.agpa_type = type; + + if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: " + "allocation of %d pages failed\n\t(%s)\n", pages, + strerror(errno)); + return -1; + } + + if (physical) + *physical = (unsigned long)alloc.agpa_physical; + + return alloc.agpa_key; +} + +Bool +xf86DeallocateGARTMemory(int screenNum, int key) +{ + if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) + return FALSE; + + if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86DeAllocateGARTMemory: " + "deallocation of gart memory with key %d failed\n" + "\t(%s)\n", key, strerror(errno)); + return FALSE; + } + + return TRUE; +} + +/* Bind GART memory with "key" at "offset" */ +Bool +xf86BindGARTMemory(int screenNum, int key, unsigned long offset) +{ + agp_bind_t bind; + int pageOffset; + + if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) + return FALSE; + + if (offset % AGP_PAGE_SIZE != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " + "offset (0x%lx) is not page-aligned (%d)\n", + offset, AGP_PAGE_SIZE); + return FALSE; + } + pageOffset = offset / AGP_PAGE_SIZE; + + xf86DrvMsgVerb(screenNum, X_INFO, 3, + "xf86BindGARTMemory: bind key %d at 0x%08lx " + "(pgoffset %d)\n", key, offset, pageOffset); + + bind.agpb_pgstart = pageOffset; + bind.agpb_key = key; + + if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " + "binding of gart memory with key %d\n" + "\tat offset 0x%lx failed (%s)\n", + key, offset, strerror(errno)); + return FALSE; + } + + return TRUE; +} + +/* Unbind GART memory with "key" */ +Bool +xf86UnbindGARTMemory(int screenNum, int key) +{ + agp_unbind_t unbind; + + if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) + return FALSE; + + unbind.agpu_pri = 0; + unbind.agpu_key = key; + + if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: " + "unbinding of gart memory with key %d " + "failed (%s)\n", key, strerror(errno)); + return FALSE; + } + + xf86DrvMsgVerb(screenNum, X_INFO, 3, + "xf86UnbindGARTMemory: unbind key %d\n", key); + + return TRUE; +} + + +/* XXX Interface may change. */ +Bool +xf86EnableAGP(int screenNum, CARD32 mode) +{ + agp_setup_t setup; + + if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) + return FALSE; + + setup.agps_mode = mode; + if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) { + xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: " + "AGPIOC_SETUP with mode %x failed (%s)\n", + mode, strerror(errno)); + return FALSE; + } + + return TRUE; +} + diff --git a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c index 346e99490..91b5795c3 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c +++ b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c @@ -1,479 +1,479 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86CursorPriv.h" -#include "colormapst.h" -#include "cursorstr.h" - -/* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for - * MPX. - * inputInfo is needed to pass the core pointer as the default argument into - * the cursor functions. - * - * Externing inputInfo is not the nice way to do it but it works. - */ -#include "inputstr.h" -extern InputInfo inputInfo; - -static int xf86CursorScreenKeyIndex; -DevPrivateKey xf86CursorScreenKey = &xf86CursorScreenKeyIndex; - -/* sprite functions */ - -static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); -static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); -static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int); -static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int); -static Bool xf86DeviceCursorInitialize(DeviceIntPtr, ScreenPtr); -static void xf86DeviceCursorCleanup(DeviceIntPtr, ScreenPtr); - -static miPointerSpriteFuncRec xf86CursorSpriteFuncs = { - xf86CursorRealizeCursor, - xf86CursorUnrealizeCursor, - xf86CursorSetCursor, - xf86CursorMoveCursor, - xf86DeviceCursorInitialize, - xf86DeviceCursorCleanup -}; - -/* Screen functions */ - -static void xf86CursorInstallColormap(ColormapPtr); -static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr, Bool); -static Bool xf86CursorCloseScreen(int, ScreenPtr); -static void xf86CursorQueryBestSize(int, unsigned short*, unsigned short*, - ScreenPtr); - -/* ScrnInfoRec functions */ - -static void xf86CursorEnableDisableFBAccess(int, Bool); -static Bool xf86CursorSwitchMode(int, DisplayModePtr,int); - -Bool -xf86InitCursor( - ScreenPtr pScreen, - xf86CursorInfoPtr infoPtr -) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - xf86CursorScreenPtr ScreenPriv; - miPointerScreenPtr PointPriv; - - if (!xf86InitHardwareCursor(pScreen, infoPtr)) - return FALSE; - - ScreenPriv = xcalloc(1, sizeof(xf86CursorScreenRec)); - if (!ScreenPriv) - return FALSE; - - dixSetPrivate(&pScreen->devPrivates, xf86CursorScreenKey, ScreenPriv); - - ScreenPriv->SWCursor = TRUE; - ScreenPriv->isUp = FALSE; - ScreenPriv->CurrentCursor = NULL; - ScreenPriv->CursorInfoPtr = infoPtr; - ScreenPriv->PalettedCursor = FALSE; - ScreenPriv->pInstalledMap = NULL; - - ScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = xf86CursorCloseScreen; - ScreenPriv->QueryBestSize = pScreen->QueryBestSize; - pScreen->QueryBestSize = xf86CursorQueryBestSize; - ScreenPriv->RecolorCursor = pScreen->RecolorCursor; - pScreen->RecolorCursor = xf86CursorRecolorCursor; - - if ((infoPtr->pScrn->bitsPerPixel == 8) && - !(infoPtr->Flags & HARDWARE_CURSOR_TRUECOLOR_AT_8BPP)) { - ScreenPriv->InstallColormap = pScreen->InstallColormap; - pScreen->InstallColormap = xf86CursorInstallColormap; - ScreenPriv->PalettedCursor = TRUE; - } - - PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); - - ScreenPriv->showTransparent = PointPriv->showTransparent; - if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) - PointPriv->showTransparent = TRUE; - else - PointPriv->showTransparent = FALSE; - ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; - PointPriv->spriteFuncs = &xf86CursorSpriteFuncs; - - ScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; - ScreenPriv->SwitchMode = pScrn->SwitchMode; - - ScreenPriv->ForceHWCursorCount = 0; - ScreenPriv->HWCursorForced = FALSE; - - pScrn->EnableDisableFBAccess = xf86CursorEnableDisableFBAccess; - if (pScrn->SwitchMode) - pScrn->SwitchMode = xf86CursorSwitchMode; - - return TRUE; -} - -/***** Screen functions *****/ - -static Bool -xf86CursorCloseScreen(int i, ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, miPointerScreenKey); - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - if (ScreenPriv->isUp && pScrn->vtSema) - xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); - - if (ScreenPriv->CurrentCursor) - FreeCursor(ScreenPriv->CurrentCursor, None); - - pScreen->CloseScreen = ScreenPriv->CloseScreen; - pScreen->QueryBestSize = ScreenPriv->QueryBestSize; - pScreen->RecolorCursor = ScreenPriv->RecolorCursor; - if (ScreenPriv->InstallColormap) - pScreen->InstallColormap = ScreenPriv->InstallColormap; - - PointPriv->spriteFuncs = ScreenPriv->spriteFuncs; - PointPriv->showTransparent = ScreenPriv->showTransparent; - - pScrn->EnableDisableFBAccess = ScreenPriv->EnableDisableFBAccess; - pScrn->SwitchMode = ScreenPriv->SwitchMode; - - xfree(ScreenPriv->transparentData); - xfree(ScreenPriv); - - return (*pScreen->CloseScreen)(i, pScreen); -} - -static void -xf86CursorQueryBestSize( - int class, - unsigned short *width, - unsigned short *height, - ScreenPtr pScreen) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - if (class == CursorShape) { - if(*width > ScreenPriv->CursorInfoPtr->MaxWidth) - *width = ScreenPriv->CursorInfoPtr->MaxWidth; - if(*height > ScreenPriv->CursorInfoPtr->MaxHeight) - *height = ScreenPriv->CursorInfoPtr->MaxHeight; - } else - (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); -} - -static void -xf86CursorInstallColormap(ColormapPtr pMap) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pMap->pScreen->devPrivates, xf86CursorScreenKey); - - ScreenPriv->pInstalledMap = pMap; - - (*ScreenPriv->InstallColormap)(pMap); -} - -static void -xf86CursorRecolorCursor( - DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCurs, - Bool displayed) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - if (!displayed) - return; - - if (ScreenPriv->SWCursor) - (*ScreenPriv->RecolorCursor)(pDev, pScreen, pCurs, displayed); - else - xf86RecolorCursor(pScreen, pCurs, displayed); -} - -/***** ScrnInfoRec functions *********/ - -static void -xf86CursorEnableDisableFBAccess( - int index, - Bool enable) -{ - DeviceIntPtr pDev = inputInfo.pointer; - - ScreenPtr pScreen = screenInfo.screens[index]; - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - if (!enable && ScreenPriv->CurrentCursor != NullCursor) { - CursorPtr currentCursor = ScreenPriv->CurrentCursor; - xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x, - ScreenPriv->y); - ScreenPriv->isUp = FALSE; - ScreenPriv->SWCursor = TRUE; - ScreenPriv->SavedCursor = currentCursor; - } - - if (ScreenPriv->EnableDisableFBAccess) - (*ScreenPriv->EnableDisableFBAccess)(index, enable); - - if (enable && ScreenPriv->SavedCursor) - { - /* - * Re-set current cursor so drivers can react to FB access having been - * temporarily disabled. - */ - xf86CursorSetCursor(pDev, pScreen, ScreenPriv->SavedCursor, - ScreenPriv->x, ScreenPriv->y); - ScreenPriv->SavedCursor = NULL; - } -} - -static Bool -xf86CursorSwitchMode(int index, DisplayModePtr mode, int flags) -{ - Bool ret; - ScreenPtr pScreen = screenInfo.screens[index]; - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, miPointerScreenKey); - - if (ScreenPriv->isUp) { - xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); - ScreenPriv->isUp = FALSE; - } - - ret = (*ScreenPriv->SwitchMode)(index, mode, flags); - - /* - * Cannot restore cursor here because the new frame[XY][01] haven't been - * calculated yet. However, because the hardware cursor was removed above, - * ensure the cursor is repainted by miPointerWarpCursor(). - */ - ScreenPriv->CursorToRestore = ScreenPriv->CurrentCursor; - PointPriv->waitForUpdate = FALSE; /* Force cursor repaint */ - - return ret; -} - -/****** miPointerSpriteFunctions *******/ - -static Bool -xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - if (pCurs->refcnt <= 1) - dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL); - - return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs); -} - -static Bool -xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCurs) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - if (pCurs->refcnt <= 1) { - xfree(dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen))); - dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL); - } - - return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs); -} - -static void -xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, - int x, int y) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; - miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, miPointerScreenKey); - - - if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */ - if (ScreenPriv->SWCursor || - !(GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer)) - (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); - else if (ScreenPriv->isUp) { - xf86SetCursor(pScreen, NullCursor, x, y); - ScreenPriv->isUp = FALSE; - } - if (ScreenPriv->CurrentCursor) - FreeCursor(ScreenPriv->CurrentCursor, None); - ScreenPriv->CurrentCursor = NullCursor; - return; - } - - /* only update for VCP, otherwise we get cursor jumps when removing a - sprite. The second cursor is never HW rendered anyway. */ - if (pDev == inputInfo.pointer || - (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer)) - { - pCurs->refcnt++; - if (ScreenPriv->CurrentCursor) - FreeCursor(ScreenPriv->CurrentCursor, None); - ScreenPriv->CurrentCursor = pCurs; - ScreenPriv->x = x; - ScreenPriv->y = y; - ScreenPriv->CursorToRestore = NULL; - ScreenPriv->HotX = pCurs->bits->xhot; - ScreenPriv->HotY = pCurs->bits->yhot; - - if (!infoPtr->pScrn->vtSema) - ScreenPriv->SavedCursor = pCurs; - - if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || (( -#ifdef ARGB_CURSOR - pCurs->bits->argb && infoPtr->UseHWCursorARGB && - (*infoPtr->UseHWCursorARGB) (pScreen, pCurs) ) || ( - pCurs->bits->argb == 0 && -#endif - (pCurs->bits->height <= infoPtr->MaxHeight) && - (pCurs->bits->width <= infoPtr->MaxWidth) && - (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs)))))) - { - - if (ScreenPriv->SWCursor) /* remove the SW cursor */ - (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); - - xf86SetCursor(pScreen, pCurs, x, y); - ScreenPriv->SWCursor = FALSE; - ScreenPriv->isUp = TRUE; - PointPriv->waitForUpdate = !infoPtr->pScrn->silkenMouse; - return; - } - - PointPriv->waitForUpdate = TRUE; - - if (ScreenPriv->isUp) { - /* Remove the HW cursor, or make it transparent */ - if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) { - xf86SetTransparentCursor(pScreen); - } else { - xf86SetCursor(pScreen, NullCursor, x, y); - ScreenPriv->isUp = FALSE; - } - } - - if (!ScreenPriv->SWCursor) - ScreenPriv->SWCursor = TRUE; - - } - - if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent) - pCurs = NullCursor; - - (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, pCurs, x, y); -} - -static void -xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - /* only update coordinate state for first sprite, otherwise we get jumps - when removing a sprite. The second sprite is never HW rendered anyway */ - if (pDev == inputInfo.pointer || - (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer)) - { - ScreenPriv->x = x; - ScreenPriv->y = y; - - if (ScreenPriv->CursorToRestore) - xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x, y); - else if (ScreenPriv->SWCursor) - (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); - else if (ScreenPriv->isUp) - xf86MoveCursor(pScreen, x, y); - } else - (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); -} - -void -xf86ForceHWCursor (ScreenPtr pScreen, Bool on) -{ - DeviceIntPtr pDev = inputInfo.pointer; - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - if (on) - { - if (ScreenPriv->ForceHWCursorCount++ == 0) - { - if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor) - { - ScreenPriv->HWCursorForced = TRUE; - xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, - ScreenPriv->x, ScreenPriv->y); - } - else - ScreenPriv->HWCursorForced = FALSE; - } - } - else - { - if (--ScreenPriv->ForceHWCursorCount == 0) - { - if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor) - xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, - ScreenPriv->x, ScreenPriv->y); - } - } -} - -xf86CursorInfoPtr -xf86CreateCursorInfoRec(void) -{ - return xcalloc(1, sizeof(xf86CursorInfoRec)); -} - -void -xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr) -{ - xfree(infoPtr); -} - -/** - * New cursor has been created. Do your initalizations here. - */ -static Bool -xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - int ret; - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - /* Init SW cursor */ - ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen); - - return ret; -} - -/** - * Cursor has been removed. Clean up after yourself. - */ -static void -xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - - /* Clean up SW cursor */ - (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); -} - + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86CursorPriv.h" +#include "colormapst.h" +#include "cursorstr.h" + +/* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for + * MPX. + * inputInfo is needed to pass the core pointer as the default argument into + * the cursor functions. + * + * Externing inputInfo is not the nice way to do it but it works. + */ +#include "inputstr.h" +extern InputInfo inputInfo; + +static int xf86CursorScreenKeyIndex; +DevPrivateKey xf86CursorScreenKey = &xf86CursorScreenKeyIndex; + +/* sprite functions */ + +static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); +static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); +static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int); +static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int); +static Bool xf86DeviceCursorInitialize(DeviceIntPtr, ScreenPtr); +static void xf86DeviceCursorCleanup(DeviceIntPtr, ScreenPtr); + +static miPointerSpriteFuncRec xf86CursorSpriteFuncs = { + xf86CursorRealizeCursor, + xf86CursorUnrealizeCursor, + xf86CursorSetCursor, + xf86CursorMoveCursor, + xf86DeviceCursorInitialize, + xf86DeviceCursorCleanup +}; + +/* Screen functions */ + +static void xf86CursorInstallColormap(ColormapPtr); +static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr, Bool); +static Bool xf86CursorCloseScreen(int, ScreenPtr); +static void xf86CursorQueryBestSize(int, unsigned short*, unsigned short*, + ScreenPtr); + +/* ScrnInfoRec functions */ + +static void xf86CursorEnableDisableFBAccess(int, Bool); +static Bool xf86CursorSwitchMode(int, DisplayModePtr,int); + +Bool +xf86InitCursor( + ScreenPtr pScreen, + xf86CursorInfoPtr infoPtr +) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CursorScreenPtr ScreenPriv; + miPointerScreenPtr PointPriv; + + if (!xf86InitHardwareCursor(pScreen, infoPtr)) + return FALSE; + + ScreenPriv = calloc(1, sizeof(xf86CursorScreenRec)); + if (!ScreenPriv) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, xf86CursorScreenKey, ScreenPriv); + + ScreenPriv->SWCursor = TRUE; + ScreenPriv->isUp = FALSE; + ScreenPriv->CurrentCursor = NULL; + ScreenPriv->CursorInfoPtr = infoPtr; + ScreenPriv->PalettedCursor = FALSE; + ScreenPriv->pInstalledMap = NULL; + + ScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = xf86CursorCloseScreen; + ScreenPriv->QueryBestSize = pScreen->QueryBestSize; + pScreen->QueryBestSize = xf86CursorQueryBestSize; + ScreenPriv->RecolorCursor = pScreen->RecolorCursor; + pScreen->RecolorCursor = xf86CursorRecolorCursor; + + if ((infoPtr->pScrn->bitsPerPixel == 8) && + !(infoPtr->Flags & HARDWARE_CURSOR_TRUECOLOR_AT_8BPP)) { + ScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreen->InstallColormap = xf86CursorInstallColormap; + ScreenPriv->PalettedCursor = TRUE; + } + + PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + + ScreenPriv->showTransparent = PointPriv->showTransparent; + if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) + PointPriv->showTransparent = TRUE; + else + PointPriv->showTransparent = FALSE; + ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; + PointPriv->spriteFuncs = &xf86CursorSpriteFuncs; + + ScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; + ScreenPriv->SwitchMode = pScrn->SwitchMode; + + ScreenPriv->ForceHWCursorCount = 0; + ScreenPriv->HWCursorForced = FALSE; + + pScrn->EnableDisableFBAccess = xf86CursorEnableDisableFBAccess; + if (pScrn->SwitchMode) + pScrn->SwitchMode = xf86CursorSwitchMode; + + return TRUE; +} + +/***** Screen functions *****/ + +static Bool +xf86CursorCloseScreen(int i, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, miPointerScreenKey); + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (ScreenPriv->isUp && pScrn->vtSema) + xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); + + if (ScreenPriv->CurrentCursor) + FreeCursor(ScreenPriv->CurrentCursor, None); + + pScreen->CloseScreen = ScreenPriv->CloseScreen; + pScreen->QueryBestSize = ScreenPriv->QueryBestSize; + pScreen->RecolorCursor = ScreenPriv->RecolorCursor; + if (ScreenPriv->InstallColormap) + pScreen->InstallColormap = ScreenPriv->InstallColormap; + + PointPriv->spriteFuncs = ScreenPriv->spriteFuncs; + PointPriv->showTransparent = ScreenPriv->showTransparent; + + pScrn->EnableDisableFBAccess = ScreenPriv->EnableDisableFBAccess; + pScrn->SwitchMode = ScreenPriv->SwitchMode; + + free(ScreenPriv->transparentData); + free(ScreenPriv); + + return (*pScreen->CloseScreen)(i, pScreen); +} + +static void +xf86CursorQueryBestSize( + int class, + unsigned short *width, + unsigned short *height, + ScreenPtr pScreen) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (class == CursorShape) { + if(*width > ScreenPriv->CursorInfoPtr->MaxWidth) + *width = ScreenPriv->CursorInfoPtr->MaxWidth; + if(*height > ScreenPriv->CursorInfoPtr->MaxHeight) + *height = ScreenPriv->CursorInfoPtr->MaxHeight; + } else + (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); +} + +static void +xf86CursorInstallColormap(ColormapPtr pMap) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pMap->pScreen->devPrivates, xf86CursorScreenKey); + + ScreenPriv->pInstalledMap = pMap; + + (*ScreenPriv->InstallColormap)(pMap); +} + +static void +xf86CursorRecolorCursor( + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCurs, + Bool displayed) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (!displayed) + return; + + if (ScreenPriv->SWCursor) + (*ScreenPriv->RecolorCursor)(pDev, pScreen, pCurs, displayed); + else + xf86RecolorCursor(pScreen, pCurs, displayed); +} + +/***** ScrnInfoRec functions *********/ + +static void +xf86CursorEnableDisableFBAccess( + int index, + Bool enable) +{ + DeviceIntPtr pDev = inputInfo.pointer; + + ScreenPtr pScreen = screenInfo.screens[index]; + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (!enable && ScreenPriv->CurrentCursor != NullCursor) { + CursorPtr currentCursor = ScreenPriv->CurrentCursor; + xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x, + ScreenPriv->y); + ScreenPriv->isUp = FALSE; + ScreenPriv->SWCursor = TRUE; + ScreenPriv->SavedCursor = currentCursor; + } + + if (ScreenPriv->EnableDisableFBAccess) + (*ScreenPriv->EnableDisableFBAccess)(index, enable); + + if (enable && ScreenPriv->SavedCursor) + { + /* + * Re-set current cursor so drivers can react to FB access having been + * temporarily disabled. + */ + xf86CursorSetCursor(pDev, pScreen, ScreenPriv->SavedCursor, + ScreenPriv->x, ScreenPriv->y); + ScreenPriv->SavedCursor = NULL; + } +} + +static Bool +xf86CursorSwitchMode(int index, DisplayModePtr mode, int flags) +{ + Bool ret; + ScreenPtr pScreen = screenInfo.screens[index]; + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, miPointerScreenKey); + + if (ScreenPriv->isUp) { + xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); + ScreenPriv->isUp = FALSE; + } + + ret = (*ScreenPriv->SwitchMode)(index, mode, flags); + + /* + * Cannot restore cursor here because the new frame[XY][01] haven't been + * calculated yet. However, because the hardware cursor was removed above, + * ensure the cursor is repainted by miPointerWarpCursor(). + */ + ScreenPriv->CursorToRestore = ScreenPriv->CurrentCursor; + PointPriv->waitForUpdate = FALSE; /* Force cursor repaint */ + + return ret; +} + +/****** miPointerSpriteFunctions *******/ + +static Bool +xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (pCurs->refcnt <= 1) + dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL); + + return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs); +} + +static Bool +xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCurs) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (pCurs->refcnt <= 1) { + free(dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen))); + dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL); + } + + return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs); +} + +static void +xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, + int x, int y) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; + miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, miPointerScreenKey); + + + if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */ + if (ScreenPriv->SWCursor || + !(GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer)) + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); + else if (ScreenPriv->isUp) { + xf86SetCursor(pScreen, NullCursor, x, y); + ScreenPriv->isUp = FALSE; + } + if (ScreenPriv->CurrentCursor) + FreeCursor(ScreenPriv->CurrentCursor, None); + ScreenPriv->CurrentCursor = NullCursor; + return; + } + + /* only update for VCP, otherwise we get cursor jumps when removing a + sprite. The second cursor is never HW rendered anyway. */ + if (pDev == inputInfo.pointer || + (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer)) + { + pCurs->refcnt++; + if (ScreenPriv->CurrentCursor) + FreeCursor(ScreenPriv->CurrentCursor, None); + ScreenPriv->CurrentCursor = pCurs; + ScreenPriv->x = x; + ScreenPriv->y = y; + ScreenPriv->CursorToRestore = NULL; + ScreenPriv->HotX = pCurs->bits->xhot; + ScreenPriv->HotY = pCurs->bits->yhot; + + if (!infoPtr->pScrn->vtSema) + ScreenPriv->SavedCursor = pCurs; + + if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || (( +#ifdef ARGB_CURSOR + pCurs->bits->argb && infoPtr->UseHWCursorARGB && + (*infoPtr->UseHWCursorARGB) (pScreen, pCurs) ) || ( + pCurs->bits->argb == 0 && +#endif + (pCurs->bits->height <= infoPtr->MaxHeight) && + (pCurs->bits->width <= infoPtr->MaxWidth) && + (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs)))))) + { + + if (ScreenPriv->SWCursor) /* remove the SW cursor */ + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); + + xf86SetCursor(pScreen, pCurs, x, y); + ScreenPriv->SWCursor = FALSE; + ScreenPriv->isUp = TRUE; + PointPriv->waitForUpdate = !infoPtr->pScrn->silkenMouse; + return; + } + + PointPriv->waitForUpdate = TRUE; + + if (ScreenPriv->isUp) { + /* Remove the HW cursor, or make it transparent */ + if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) { + xf86SetTransparentCursor(pScreen); + } else { + xf86SetCursor(pScreen, NullCursor, x, y); + ScreenPriv->isUp = FALSE; + } + } + + if (!ScreenPriv->SWCursor) + ScreenPriv->SWCursor = TRUE; + + } + + if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent) + pCurs = NullCursor; + + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, pCurs, x, y); +} + +static void +xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + /* only update coordinate state for first sprite, otherwise we get jumps + when removing a sprite. The second sprite is never HW rendered anyway */ + if (pDev == inputInfo.pointer || + (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer)) + { + ScreenPriv->x = x; + ScreenPriv->y = y; + + if (ScreenPriv->CursorToRestore) + xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x, y); + else if (ScreenPriv->SWCursor) + (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); + else if (ScreenPriv->isUp) + xf86MoveCursor(pScreen, x, y); + } else + (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); +} + +void +xf86ForceHWCursor (ScreenPtr pScreen, Bool on) +{ + DeviceIntPtr pDev = inputInfo.pointer; + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + if (on) + { + if (ScreenPriv->ForceHWCursorCount++ == 0) + { + if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor) + { + ScreenPriv->HWCursorForced = TRUE; + xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, + ScreenPriv->x, ScreenPriv->y); + } + else + ScreenPriv->HWCursorForced = FALSE; + } + } + else + { + if (--ScreenPriv->ForceHWCursorCount == 0) + { + if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor) + xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, + ScreenPriv->x, ScreenPriv->y); + } + } +} + +xf86CursorInfoPtr +xf86CreateCursorInfoRec(void) +{ + return calloc(1, sizeof(xf86CursorInfoRec)); +} + +void +xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr) +{ + free(infoPtr); +} + +/** + * New cursor has been created. Do your initalizations here. + */ +static Bool +xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + int ret; + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + /* Init SW cursor */ + ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen); + + return ret; +} + +/** + * Cursor has been removed. Clean up after yourself. + */ +static void +xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + + /* Clean up SW cursor */ + (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); +} + diff --git a/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c b/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c index 4374e51d4..43f28ef8e 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c +++ b/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c @@ -1,527 +1,527 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "xf86str.h" -#include "cursorstr.h" -#include "mi.h" -#include "mipointer.h" -#include "xf86CursorPriv.h" - -#include "servermd.h" - -#if BITMAP_SCANLINE_PAD == 64 - -#if 1 -/* Cursors might be only 32 wide. Give'em a chance */ -#define SCANLINE CARD32 -#define CUR_BITMAP_SCANLINE_PAD 32 -#define CUR_LOG2_BITMAP_PAD 5 -#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w) -#else -#define SCANLINE CARD64 -#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD -#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD -#define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w) -static CARD64 xf86CARD64ReverseBits(CARD64 w); - -static CARD64 -xf86CARD64ReverseBits(CARD64 w) -{ - unsigned char *p = (unsigned char *)&w; - - p[0] = byte_reversed[p[0]]; - p[1] = byte_reversed[p[1]]; - p[2] = byte_reversed[p[2]]; - p[3] = byte_reversed[p[3]]; - p[4] = byte_reversed[p[4]]; - p[5] = byte_reversed[p[5]]; - p[6] = byte_reversed[p[6]]; - p[7] = byte_reversed[p[7]]; - - return w; -} -#endif - -#else - -#define SCANLINE CARD32 -#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD -#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD -#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w) - -#endif /* BITMAP_SCANLINE_PAD == 64 */ - -static unsigned char* RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr); -static unsigned char* RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr); -static unsigned char* RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr); -static unsigned char* RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr); -static unsigned char* RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr); -static unsigned char* RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr); - -Bool -xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr) -{ - if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0)) - return FALSE; - - /* These are required for now */ - if (!infoPtr->SetCursorPosition || - !infoPtr->LoadCursorImage || - !infoPtr->HideCursor || - !infoPtr->ShowCursor || - !infoPtr->SetCursorColors) - return FALSE; - - if (infoPtr->RealizeCursor) { - /* Don't overwrite a driver provided Realize Cursor function */ - } else - if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) { - infoPtr->RealizeCursor = RealizeCursorInterleave1; - } else - if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) { - infoPtr->RealizeCursor = RealizeCursorInterleave8; - } else - if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) { - infoPtr->RealizeCursor = RealizeCursorInterleave16; - } else - if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) { - infoPtr->RealizeCursor = RealizeCursorInterleave32; - } else - if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) { - infoPtr->RealizeCursor = RealizeCursorInterleave64; - } else { /* not interleaved */ - infoPtr->RealizeCursor = RealizeCursorInterleave0; - } - - infoPtr->pScrn = xf86Screens[pScreen->myNum]; - - return TRUE; -} - -void -xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; - unsigned char *bits; - - if (pCurs == NullCursor) { - (*infoPtr->HideCursor)(infoPtr->pScrn); - return; - } - - bits = dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen)); - - x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX; - y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY; - -#ifdef ARGB_CURSOR - if (!pCurs->bits->argb || !infoPtr->LoadCursorARGB) -#endif - if (!bits) { - bits = (*infoPtr->RealizeCursor)(infoPtr, pCurs); - dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), bits); - } - - if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) - (*infoPtr->HideCursor)(infoPtr->pScrn); - -#ifdef ARGB_CURSOR - if (pCurs->bits->argb && infoPtr->LoadCursorARGB) - (*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs); - else -#endif - if (bits) - (*infoPtr->LoadCursorImage)(infoPtr->pScrn, bits); - - xf86RecolorCursor(pScreen, pCurs, 1); - - (*infoPtr->SetCursorPosition)(infoPtr->pScrn, x, y); - - (*infoPtr->ShowCursor)(infoPtr->pScrn); -} - -void -xf86SetTransparentCursor(ScreenPtr pScreen) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; - - if (!ScreenPriv->transparentData) - ScreenPriv->transparentData = - (*infoPtr->RealizeCursor)(infoPtr, NullCursor); - - if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) - (*infoPtr->HideCursor)(infoPtr->pScrn); - - if (ScreenPriv->transparentData) - (*infoPtr->LoadCursorImage)(infoPtr->pScrn, - ScreenPriv->transparentData); - - (*infoPtr->ShowCursor)(infoPtr->pScrn); -} - -void -xf86MoveCursor(ScreenPtr pScreen, int x, int y) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; - - x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX; - y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY; - - (*infoPtr->SetCursorPosition)(infoPtr->pScrn, x, y); -} - -void -xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed) -{ - xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( - &pScreen->devPrivates, xf86CursorScreenKey); - xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; - -#ifdef ARGB_CURSOR - /* recoloring isn't applicable to ARGB cursors and drivers - shouldn't have to ignore SetCursorColors requests */ - if (pCurs->bits->argb) - return; -#endif - - if (ScreenPriv->PalettedCursor) { - xColorItem sourceColor, maskColor; - ColormapPtr pmap = ScreenPriv->pInstalledMap; - - if (!pmap) - return; - - sourceColor.red = pCurs->foreRed; - sourceColor.green = pCurs->foreGreen; - sourceColor.blue = pCurs->foreBlue; - FakeAllocColor(pmap, &sourceColor); - maskColor.red = pCurs->backRed; - maskColor.green = pCurs->backGreen; - maskColor.blue = pCurs->backBlue; - FakeAllocColor(pmap, &maskColor); - FakeFreeColor(pmap, sourceColor.pixel); - FakeFreeColor(pmap, maskColor.pixel); - (*infoPtr->SetCursorColors)(infoPtr->pScrn, - maskColor.pixel, sourceColor.pixel); - } else { /* Pass colors in 8-8-8 RGB format */ - (*infoPtr->SetCursorColors)(infoPtr->pScrn, - (pCurs->backBlue >> 8) | - ((pCurs->backGreen >> 8) << 8) | - ((pCurs->backRed >> 8) << 16), - (pCurs->foreBlue >> 8) | - ((pCurs->foreGreen >> 8) << 8) | - ((pCurs->foreRed >> 8) << 16) - ); - } -} - -/* These functions assume that MaxWidth is a multiple of 32 */ -static unsigned char* -RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) -{ - - SCANLINE *SrcS, *SrcM, *DstS, *DstM; - SCANLINE *pSrc, *pMsk; - unsigned char *mem; - int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; - int SrcPitch, DstPitch, Pitch, y, x; - /* how many words are in the source or mask */ - int words = size / (CUR_BITMAP_SCANLINE_PAD / 4); - - - if (!(mem = xcalloc(1, size))) - return NULL; - - if (pCurs == NullCursor) { - if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) { - DstM = (SCANLINE*)mem; - if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)) - DstM += words; - memset(DstM, -1, words * sizeof(SCANLINE)); - } - return mem; - } - - /* SrcPitch == the number of scanlines wide the cursor image is */ - SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >> - CUR_LOG2_BITMAP_PAD; - - /* DstPitch is the width of the hw cursor in scanlines */ - DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD; - Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch; - - SrcS = (SCANLINE*)pCurs->bits->source; - SrcM = (SCANLINE*)pCurs->bits->mask; - DstS = (SCANLINE*)mem; - DstM = DstS + words; - - if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) { - SCANLINE *tmp; - tmp = DstS; DstS = DstM; DstM = tmp; - } - - if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) { - for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; - y--; - pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) { - for(x = 0; x < Pitch; x++) { - pSrc[x] = SrcS[x] & SrcM[x]; - pMsk[x] = SrcM[x]; - } - } - } else { - for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; - y--; - pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) { - for(x = 0; x < Pitch; x++) { - pSrc[x] = SrcS[x]; - pMsk[x] = SrcM[x]; - } - } - } - - if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) { - int count = size; - unsigned char* pntr1 = (unsigned char *)DstS; - unsigned char* pntr2 = (unsigned char *)DstM; - unsigned char a, b; - while (count) { - - a = *pntr1; - b = *pntr2; - *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4); - *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4); - pntr1++; pntr2++; - count-=2; - } - } - - /* - * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping - * out entire source mask. - */ - if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) { - int count = words; - SCANLINE* pntr = DstM; - while (count--) { - *pntr = ~(*pntr); - pntr++; - } - } - - if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) { - for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; - y--; - pSrc+=DstPitch, pMsk+=DstPitch) { - for(x = 0; x < Pitch; x++) { - pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]); - pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]); - } - } - } - - return mem; -} - -static unsigned char* -RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) -{ - unsigned char *DstS, *DstM; - unsigned char *pntr; - unsigned char *mem, *mem2; - int count; - int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; - - /* Realize the cursor without interleaving */ - if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) - return NULL; - - if (!(mem = xcalloc(1, size))) { - xfree(mem2); - return NULL; - } - - /* 1 bit interleave */ - DstS = mem2; - DstM = DstS + (size >> 1); - pntr = mem; - count = size; - while (count) { - *pntr++ = ((*DstS&0x01) ) | ((*DstM&0x01) << 1) | - ((*DstS&0x02) << 1) | ((*DstM&0x02) << 2) | - ((*DstS&0x04) << 2) | ((*DstM&0x04) << 3) | - ((*DstS&0x08) << 3) | ((*DstM&0x08) << 4); - *pntr++ = ((*DstS&0x10) >> 4) | ((*DstM&0x10) >> 3) | - ((*DstS&0x20) >> 3) | ((*DstM&0x20) >> 2) | - ((*DstS&0x40) >> 2) | ((*DstM&0x40) >> 1) | - ((*DstS&0x80) >> 1) | ((*DstM&0x80) ); - DstS++; - DstM++; - count-=2; - } - - /* Free the uninterleaved cursor */ - xfree(mem2); - - return mem; -} - -static unsigned char* -RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) -{ - unsigned char *DstS, *DstM; - unsigned char *pntr; - unsigned char *mem, *mem2; - int count; - int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; - - /* Realize the cursor without interleaving */ - if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) - return NULL; - - if (!(mem = xcalloc(1, size))) { - xfree(mem2); - return NULL; - } - - /* 8 bit interleave */ - DstS = mem2; - DstM = DstS + (size >> 1); - pntr = mem; - count = size; - while (count) { - *pntr++ = *DstS++; - *pntr++ = *DstM++; - count-=2; - } - - /* Free the uninterleaved cursor */ - xfree(mem2); - - return mem; -} - -static unsigned char* -RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) -{ - unsigned short *DstS, *DstM; - unsigned short *pntr; - unsigned char *mem, *mem2; - int count; - int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; - - /* Realize the cursor without interleaving */ - if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) - return NULL; - - if (!(mem = xcalloc(1, size))) { - xfree(mem2); - return NULL; - } - - /* 16 bit interleave */ - DstS = (pointer)mem2; - DstM = DstS + (size >> 2); - pntr = (pointer)mem; - count = (size >> 1); - while (count) { - *pntr++ = *DstS++; - *pntr++ = *DstM++; - count-=2; - } - - /* Free the uninterleaved cursor */ - xfree(mem2); - - return mem; -} - -static unsigned char* -RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) -{ - CARD32 *DstS, *DstM; - CARD32 *pntr; - unsigned char *mem, *mem2; - int count; - int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; - - /* Realize the cursor without interleaving */ - if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) - return NULL; - - if (!(mem = xcalloc(1, size))) { - xfree(mem2); - return NULL; - } - - /* 32 bit interleave */ - DstS = (pointer)mem2; - DstM = DstS + (size >> 3); - pntr = (pointer)mem; - count = (size >> 2); - while (count) { - *pntr++ = *DstS++; - *pntr++ = *DstM++; - count-=2; - } - - /* Free the uninterleaved cursor */ - xfree(mem2); - - return mem; -} - -static unsigned char* -RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) -{ - CARD32 *DstS, *DstM; - CARD32 *pntr; - unsigned char *mem, *mem2; - int count; - int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; - - /* Realize the cursor without interleaving */ - if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) - return NULL; - - if (!(mem = xcalloc(1, size))) { - xfree(mem2); - return NULL; - } - - /* 64 bit interleave */ - DstS = (pointer)mem2; - DstM = DstS + (size >> 3); - pntr = (pointer)mem; - count = (size >> 2); - while (count) { - *pntr++ = *DstS++; - *pntr++ = *DstS++; - *pntr++ = *DstM++; - *pntr++ = *DstM++; - count-=4; - } - - /* Free the uninterleaved cursor */ - xfree(mem2); - - return mem; -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "cursorstr.h" +#include "mi.h" +#include "mipointer.h" +#include "xf86CursorPriv.h" + +#include "servermd.h" + +#if BITMAP_SCANLINE_PAD == 64 + +#if 1 +/* Cursors might be only 32 wide. Give'em a chance */ +#define SCANLINE CARD32 +#define CUR_BITMAP_SCANLINE_PAD 32 +#define CUR_LOG2_BITMAP_PAD 5 +#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w) +#else +#define SCANLINE CARD64 +#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD +#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD +#define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w) +static CARD64 xf86CARD64ReverseBits(CARD64 w); + +static CARD64 +xf86CARD64ReverseBits(CARD64 w) +{ + unsigned char *p = (unsigned char *)&w; + + p[0] = byte_reversed[p[0]]; + p[1] = byte_reversed[p[1]]; + p[2] = byte_reversed[p[2]]; + p[3] = byte_reversed[p[3]]; + p[4] = byte_reversed[p[4]]; + p[5] = byte_reversed[p[5]]; + p[6] = byte_reversed[p[6]]; + p[7] = byte_reversed[p[7]]; + + return w; +} +#endif + +#else + +#define SCANLINE CARD32 +#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD +#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD +#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w) + +#endif /* BITMAP_SCANLINE_PAD == 64 */ + +static unsigned char* RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr); +static unsigned char* RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr); +static unsigned char* RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr); +static unsigned char* RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr); +static unsigned char* RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr); +static unsigned char* RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr); + +Bool +xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr) +{ + if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0)) + return FALSE; + + /* These are required for now */ + if (!infoPtr->SetCursorPosition || + !infoPtr->LoadCursorImage || + !infoPtr->HideCursor || + !infoPtr->ShowCursor || + !infoPtr->SetCursorColors) + return FALSE; + + if (infoPtr->RealizeCursor) { + /* Don't overwrite a driver provided Realize Cursor function */ + } else + if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) { + infoPtr->RealizeCursor = RealizeCursorInterleave1; + } else + if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) { + infoPtr->RealizeCursor = RealizeCursorInterleave8; + } else + if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) { + infoPtr->RealizeCursor = RealizeCursorInterleave16; + } else + if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) { + infoPtr->RealizeCursor = RealizeCursorInterleave32; + } else + if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) { + infoPtr->RealizeCursor = RealizeCursorInterleave64; + } else { /* not interleaved */ + infoPtr->RealizeCursor = RealizeCursorInterleave0; + } + + infoPtr->pScrn = xf86Screens[pScreen->myNum]; + + return TRUE; +} + +void +xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; + unsigned char *bits; + + if (pCurs == NullCursor) { + (*infoPtr->HideCursor)(infoPtr->pScrn); + return; + } + + bits = dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen)); + + x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX; + y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY; + +#ifdef ARGB_CURSOR + if (!pCurs->bits->argb || !infoPtr->LoadCursorARGB) +#endif + if (!bits) { + bits = (*infoPtr->RealizeCursor)(infoPtr, pCurs); + dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), bits); + } + + if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) + (*infoPtr->HideCursor)(infoPtr->pScrn); + +#ifdef ARGB_CURSOR + if (pCurs->bits->argb && infoPtr->LoadCursorARGB) + (*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs); + else +#endif + if (bits) + (*infoPtr->LoadCursorImage)(infoPtr->pScrn, bits); + + xf86RecolorCursor(pScreen, pCurs, 1); + + (*infoPtr->SetCursorPosition)(infoPtr->pScrn, x, y); + + (*infoPtr->ShowCursor)(infoPtr->pScrn); +} + +void +xf86SetTransparentCursor(ScreenPtr pScreen) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; + + if (!ScreenPriv->transparentData) + ScreenPriv->transparentData = + (*infoPtr->RealizeCursor)(infoPtr, NullCursor); + + if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) + (*infoPtr->HideCursor)(infoPtr->pScrn); + + if (ScreenPriv->transparentData) + (*infoPtr->LoadCursorImage)(infoPtr->pScrn, + ScreenPriv->transparentData); + + (*infoPtr->ShowCursor)(infoPtr->pScrn); +} + +void +xf86MoveCursor(ScreenPtr pScreen, int x, int y) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; + + x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX; + y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY; + + (*infoPtr->SetCursorPosition)(infoPtr->pScrn, x, y); +} + +void +xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed) +{ + xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( + &pScreen->devPrivates, xf86CursorScreenKey); + xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; + +#ifdef ARGB_CURSOR + /* recoloring isn't applicable to ARGB cursors and drivers + shouldn't have to ignore SetCursorColors requests */ + if (pCurs->bits->argb) + return; +#endif + + if (ScreenPriv->PalettedCursor) { + xColorItem sourceColor, maskColor; + ColormapPtr pmap = ScreenPriv->pInstalledMap; + + if (!pmap) + return; + + sourceColor.red = pCurs->foreRed; + sourceColor.green = pCurs->foreGreen; + sourceColor.blue = pCurs->foreBlue; + FakeAllocColor(pmap, &sourceColor); + maskColor.red = pCurs->backRed; + maskColor.green = pCurs->backGreen; + maskColor.blue = pCurs->backBlue; + FakeAllocColor(pmap, &maskColor); + FakeFreeColor(pmap, sourceColor.pixel); + FakeFreeColor(pmap, maskColor.pixel); + (*infoPtr->SetCursorColors)(infoPtr->pScrn, + maskColor.pixel, sourceColor.pixel); + } else { /* Pass colors in 8-8-8 RGB format */ + (*infoPtr->SetCursorColors)(infoPtr->pScrn, + (pCurs->backBlue >> 8) | + ((pCurs->backGreen >> 8) << 8) | + ((pCurs->backRed >> 8) << 16), + (pCurs->foreBlue >> 8) | + ((pCurs->foreGreen >> 8) << 8) | + ((pCurs->foreRed >> 8) << 16) + ); + } +} + +/* These functions assume that MaxWidth is a multiple of 32 */ +static unsigned char* +RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) +{ + + SCANLINE *SrcS, *SrcM, *DstS, *DstM; + SCANLINE *pSrc, *pMsk; + unsigned char *mem; + int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; + int SrcPitch, DstPitch, Pitch, y, x; + /* how many words are in the source or mask */ + int words = size / (CUR_BITMAP_SCANLINE_PAD / 4); + + + if (!(mem = calloc(1, size))) + return NULL; + + if (pCurs == NullCursor) { + if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) { + DstM = (SCANLINE*)mem; + if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)) + DstM += words; + memset(DstM, -1, words * sizeof(SCANLINE)); + } + return mem; + } + + /* SrcPitch == the number of scanlines wide the cursor image is */ + SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >> + CUR_LOG2_BITMAP_PAD; + + /* DstPitch is the width of the hw cursor in scanlines */ + DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD; + Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch; + + SrcS = (SCANLINE*)pCurs->bits->source; + SrcM = (SCANLINE*)pCurs->bits->mask; + DstS = (SCANLINE*)mem; + DstM = DstS + words; + + if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) { + SCANLINE *tmp; + tmp = DstS; DstS = DstM; DstM = tmp; + } + + if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) { + for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; + y--; + pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) { + for(x = 0; x < Pitch; x++) { + pSrc[x] = SrcS[x] & SrcM[x]; + pMsk[x] = SrcM[x]; + } + } + } else { + for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; + y--; + pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) { + for(x = 0; x < Pitch; x++) { + pSrc[x] = SrcS[x]; + pMsk[x] = SrcM[x]; + } + } + } + + if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) { + int count = size; + unsigned char* pntr1 = (unsigned char *)DstS; + unsigned char* pntr2 = (unsigned char *)DstM; + unsigned char a, b; + while (count) { + + a = *pntr1; + b = *pntr2; + *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4); + *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4); + pntr1++; pntr2++; + count-=2; + } + } + + /* + * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping + * out entire source mask. + */ + if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) { + int count = words; + SCANLINE* pntr = DstM; + while (count--) { + *pntr = ~(*pntr); + pntr++; + } + } + + if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) { + for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; + y--; + pSrc+=DstPitch, pMsk+=DstPitch) { + for(x = 0; x < Pitch; x++) { + pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]); + pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]); + } + } + } + + return mem; +} + +static unsigned char* +RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) +{ + unsigned char *DstS, *DstM; + unsigned char *pntr; + unsigned char *mem, *mem2; + int count; + int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; + + /* Realize the cursor without interleaving */ + if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) + return NULL; + + if (!(mem = calloc(1, size))) { + free(mem2); + return NULL; + } + + /* 1 bit interleave */ + DstS = mem2; + DstM = DstS + (size >> 1); + pntr = mem; + count = size; + while (count) { + *pntr++ = ((*DstS&0x01) ) | ((*DstM&0x01) << 1) | + ((*DstS&0x02) << 1) | ((*DstM&0x02) << 2) | + ((*DstS&0x04) << 2) | ((*DstM&0x04) << 3) | + ((*DstS&0x08) << 3) | ((*DstM&0x08) << 4); + *pntr++ = ((*DstS&0x10) >> 4) | ((*DstM&0x10) >> 3) | + ((*DstS&0x20) >> 3) | ((*DstM&0x20) >> 2) | + ((*DstS&0x40) >> 2) | ((*DstM&0x40) >> 1) | + ((*DstS&0x80) >> 1) | ((*DstM&0x80) ); + DstS++; + DstM++; + count-=2; + } + + /* Free the uninterleaved cursor */ + free(mem2); + + return mem; +} + +static unsigned char* +RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) +{ + unsigned char *DstS, *DstM; + unsigned char *pntr; + unsigned char *mem, *mem2; + int count; + int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; + + /* Realize the cursor without interleaving */ + if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) + return NULL; + + if (!(mem = calloc(1, size))) { + free(mem2); + return NULL; + } + + /* 8 bit interleave */ + DstS = mem2; + DstM = DstS + (size >> 1); + pntr = mem; + count = size; + while (count) { + *pntr++ = *DstS++; + *pntr++ = *DstM++; + count-=2; + } + + /* Free the uninterleaved cursor */ + free(mem2); + + return mem; +} + +static unsigned char* +RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) +{ + unsigned short *DstS, *DstM; + unsigned short *pntr; + unsigned char *mem, *mem2; + int count; + int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; + + /* Realize the cursor without interleaving */ + if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) + return NULL; + + if (!(mem = calloc(1, size))) { + free(mem2); + return NULL; + } + + /* 16 bit interleave */ + DstS = (pointer)mem2; + DstM = DstS + (size >> 2); + pntr = (pointer)mem; + count = (size >> 1); + while (count) { + *pntr++ = *DstS++; + *pntr++ = *DstM++; + count-=2; + } + + /* Free the uninterleaved cursor */ + free(mem2); + + return mem; +} + +static unsigned char* +RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) +{ + CARD32 *DstS, *DstM; + CARD32 *pntr; + unsigned char *mem, *mem2; + int count; + int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; + + /* Realize the cursor without interleaving */ + if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) + return NULL; + + if (!(mem = calloc(1, size))) { + free(mem2); + return NULL; + } + + /* 32 bit interleave */ + DstS = (pointer)mem2; + DstM = DstS + (size >> 3); + pntr = (pointer)mem; + count = (size >> 2); + while (count) { + *pntr++ = *DstS++; + *pntr++ = *DstM++; + count-=2; + } + + /* Free the uninterleaved cursor */ + free(mem2); + + return mem; +} + +static unsigned char* +RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) +{ + CARD32 *DstS, *DstM; + CARD32 *pntr; + unsigned char *mem, *mem2; + int count; + int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; + + /* Realize the cursor without interleaving */ + if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) + return NULL; + + if (!(mem = calloc(1, size))) { + free(mem2); + return NULL; + } + + /* 64 bit interleave */ + DstS = (pointer)mem2; + DstM = DstS + (size >> 3); + pntr = (pointer)mem; + count = (size >> 2); + while (count) { + *pntr++ = *DstS++; + *pntr++ = *DstS++; + *pntr++ = *DstM++; + *pntr++ = *DstM++; + count-=4; + } + + /* Free the uninterleaved cursor */ + free(mem2); + + return mem; +} diff --git a/xorg-server/hw/xfree86/ramdac/xf86RamDac.c b/xorg-server/hw/xfree86/ramdac/xf86RamDac.c index bd4f3466a..25d450c07 100644 --- a/xorg-server/hw/xfree86/ramdac/xf86RamDac.c +++ b/xorg-server/hw/xfree86/ramdac/xf86RamDac.c @@ -1,154 +1,154 @@ -/* - * Copyright 1998 by Alan Hourihane, Wigan, England. - * - * 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 Alan Hourihane not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Alan Hourihane makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. - * - * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL ALAN HOURIHANE 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. - * - * Authors: Alan Hourihane, - * - * Generic RAMDAC access routines. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xf86.h" -#include "xf86_OSproc.h" - -#include "xf86RamDacPriv.h" - -int RamDacHWPrivateIndex = -1; -int RamDacScreenPrivateIndex = -1; - -RamDacRecPtr -RamDacCreateInfoRec(void) -{ - RamDacRecPtr infoRec; - - infoRec = xcalloc(1, sizeof(RamDacRec)); - - return infoRec; -} - -RamDacHelperRecPtr -RamDacHelperCreateInfoRec(void) -{ - RamDacHelperRecPtr infoRec; - - infoRec = xcalloc(1, sizeof(RamDacHelperRec)); - - return infoRec; -} - -void -RamDacDestroyInfoRec(RamDacRecPtr infoRec) -{ - xfree(infoRec); -} - -void -RamDacHelperDestroyInfoRec(RamDacHelperRecPtr infoRec) -{ - xfree(infoRec); -} - -Bool -RamDacInit(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPriv) -{ - RamDacScreenRecPtr ramdacScrPtr; - - /* - * make sure the RamDacRec is allocated - */ - if (!RamDacGetRec(pScrn)) - return FALSE; - ramdacScrPtr = - ((RamDacScreenRecPtr) (pScrn)->privates[RamDacGetScreenIndex()].ptr); - ramdacScrPtr->RamDacRec = ramdacPriv; - - return(TRUE); -} - -void -RamDacGetRecPrivate(void) -{ - if (RamDacHWPrivateIndex < 0) - RamDacHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - if (RamDacScreenPrivateIndex < 0) - RamDacScreenPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - return; -} - -Bool -RamDacGetRec(ScrnInfoPtr scrp) -{ - RamDacGetRecPrivate(); - /* - * New privates are always set to NULL, so we can check if the allocation - * has already been done. - */ - if (scrp->privates[RamDacHWPrivateIndex].ptr != NULL) - return TRUE; - if (scrp->privates[RamDacScreenPrivateIndex].ptr != NULL) - return TRUE; - - scrp->privates[RamDacHWPrivateIndex].ptr = - xnfcalloc(sizeof(RamDacHWRec), 1); - scrp->privates[RamDacScreenPrivateIndex].ptr = - xnfcalloc(sizeof(RamDacScreenRec), 1); - - return TRUE; -} - -void -RamDacFreeRec(ScrnInfoPtr pScrn) -{ - RamDacHWRecPtr ramdacHWPtr; - RamDacScreenRecPtr ramdacScrPtr; - - if (RamDacHWPrivateIndex < 0) - return; - - if (RamDacScreenPrivateIndex < 0) - return; - - ramdacHWPtr = RAMDACHWPTR(pScrn); - ramdacScrPtr = ((RamDacScreenRecPtr) - (pScrn)->privates[RamDacGetScreenIndex()].ptr); - - if (ramdacHWPtr) - xfree(ramdacHWPtr); - ramdacHWPtr = NULL; - - if (ramdacScrPtr) - xfree(ramdacScrPtr); - ramdacScrPtr = NULL; -} - -int -RamDacGetHWIndex(void) -{ - return RamDacHWPrivateIndex; -} - -int -RamDacGetScreenIndex(void) -{ - return RamDacScreenPrivateIndex; -} +/* + * Copyright 1998 by Alan Hourihane, Wigan, England. + * + * 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 Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE 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. + * + * Authors: Alan Hourihane, + * + * Generic RAMDAC access routines. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "xf86RamDacPriv.h" + +int RamDacHWPrivateIndex = -1; +int RamDacScreenPrivateIndex = -1; + +RamDacRecPtr +RamDacCreateInfoRec(void) +{ + RamDacRecPtr infoRec; + + infoRec = calloc(1, sizeof(RamDacRec)); + + return infoRec; +} + +RamDacHelperRecPtr +RamDacHelperCreateInfoRec(void) +{ + RamDacHelperRecPtr infoRec; + + infoRec = calloc(1, sizeof(RamDacHelperRec)); + + return infoRec; +} + +void +RamDacDestroyInfoRec(RamDacRecPtr infoRec) +{ + free(infoRec); +} + +void +RamDacHelperDestroyInfoRec(RamDacHelperRecPtr infoRec) +{ + free(infoRec); +} + +Bool +RamDacInit(ScrnInfoPtr pScrn, RamDacRecPtr ramdacPriv) +{ + RamDacScreenRecPtr ramdacScrPtr; + + /* + * make sure the RamDacRec is allocated + */ + if (!RamDacGetRec(pScrn)) + return FALSE; + ramdacScrPtr = + ((RamDacScreenRecPtr) (pScrn)->privates[RamDacGetScreenIndex()].ptr); + ramdacScrPtr->RamDacRec = ramdacPriv; + + return(TRUE); +} + +void +RamDacGetRecPrivate(void) +{ + if (RamDacHWPrivateIndex < 0) + RamDacHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + if (RamDacScreenPrivateIndex < 0) + RamDacScreenPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + return; +} + +Bool +RamDacGetRec(ScrnInfoPtr scrp) +{ + RamDacGetRecPrivate(); + /* + * New privates are always set to NULL, so we can check if the allocation + * has already been done. + */ + if (scrp->privates[RamDacHWPrivateIndex].ptr != NULL) + return TRUE; + if (scrp->privates[RamDacScreenPrivateIndex].ptr != NULL) + return TRUE; + + scrp->privates[RamDacHWPrivateIndex].ptr = + xnfcalloc(sizeof(RamDacHWRec), 1); + scrp->privates[RamDacScreenPrivateIndex].ptr = + xnfcalloc(sizeof(RamDacScreenRec), 1); + + return TRUE; +} + +void +RamDacFreeRec(ScrnInfoPtr pScrn) +{ + RamDacHWRecPtr ramdacHWPtr; + RamDacScreenRecPtr ramdacScrPtr; + + if (RamDacHWPrivateIndex < 0) + return; + + if (RamDacScreenPrivateIndex < 0) + return; + + ramdacHWPtr = RAMDACHWPTR(pScrn); + ramdacScrPtr = ((RamDacScreenRecPtr) + (pScrn)->privates[RamDacGetScreenIndex()].ptr); + + if (ramdacHWPtr) + free(ramdacHWPtr); + ramdacHWPtr = NULL; + + if (ramdacScrPtr) + free(ramdacScrPtr); + ramdacScrPtr = NULL; +} + +int +RamDacGetHWIndex(void) +{ + return RamDacHWPrivateIndex; +} + +int +RamDacGetScreenIndex(void) +{ + return RamDacScreenPrivateIndex; +} diff --git a/xorg-server/hw/xfree86/shadowfb/shadow.c b/xorg-server/hw/xfree86/shadowfb/shadow.c index 1c8170104..9e847f4d2 100644 --- a/xorg-server/hw/xfree86/shadowfb/shadow.c +++ b/xorg-server/hw/xfree86/shadowfb/shadow.c @@ -1,1729 +1,1729 @@ -/* - Copyright (C) 1999. The XFree86 Project Inc. - - Written by Mark Vojkovich (mvojkovi@ucsd.edu) - - Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com) -*/ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "pixmapstr.h" -#include "input.h" -#include -#include "mi.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "gcstruct.h" -#include "dixfontstr.h" -#include -#include "xf86.h" -#include "xf86str.h" -#include "shadowfb.h" - -# include "picturestr.h" - -static Bool ShadowCloseScreen (int i, ScreenPtr pScreen); -static void ShadowCopyWindow( - WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgn -); -static Bool ShadowCreateGC(GCPtr pGC); -static Bool ShadowModifyPixmapHeader( - PixmapPtr pPixmap, - int width, - int height, - int depth, - int bitsPerPixel, - int devKind, - pointer pPixData -); - -static Bool ShadowEnterVT(int index, int flags); -static void ShadowLeaveVT(int index, int flags); - -static void ShadowComposite( - CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height -); - - -typedef struct { - ScrnInfoPtr pScrn; - RefreshAreaFuncPtr preRefresh; - RefreshAreaFuncPtr postRefresh; - CloseScreenProcPtr CloseScreen; - CopyWindowProcPtr CopyWindow; - CreateGCProcPtr CreateGC; - ModifyPixmapHeaderProcPtr ModifyPixmapHeader; - CompositeProcPtr Composite; - Bool (*EnterVT)(int, int); - void (*LeaveVT)(int, int); - Bool vtSema; -} ShadowScreenRec, *ShadowScreenPtr; - -typedef struct { - GCOps *ops; - GCFuncs *funcs; -} ShadowGCRec, *ShadowGCPtr; - - -static int ShadowScreenKeyIndex; -static DevPrivateKey ShadowScreenKey = &ShadowScreenKeyIndex; -static int ShadowGCKeyIndex; -static DevPrivateKey ShadowGCKey = &ShadowGCKeyIndex; - -#define GET_SCREEN_PRIVATE(pScreen) \ - (ShadowScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, ShadowScreenKey) -#define GET_GC_PRIVATE(pGC) \ - (ShadowGCPtr)dixLookupPrivate(&(pGC)->devPrivates, ShadowGCKey) - -#define SHADOW_GC_FUNC_PROLOGUE(pGC)\ - ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\ - (pGC)->funcs = pGCPriv->funcs;\ - if(pGCPriv->ops)\ - (pGC)->ops = pGCPriv->ops - -#define SHADOW_GC_FUNC_EPILOGUE(pGC)\ - pGCPriv->funcs = (pGC)->funcs;\ - (pGC)->funcs = &ShadowGCFuncs;\ - if(pGCPriv->ops) {\ - pGCPriv->ops = (pGC)->ops;\ - (pGC)->ops = &ShadowGCOps;\ - } - -#define SHADOW_GC_OP_PROLOGUE(pGC)\ - ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pGC->pScreen); \ - ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\ - GCFuncs *oldFuncs = pGC->funcs;\ - pGC->funcs = pGCPriv->funcs;\ - pGC->ops = pGCPriv->ops - - -#define SHADOW_GC_OP_EPILOGUE(pGC)\ - pGCPriv->ops = pGC->ops;\ - pGC->funcs = oldFuncs;\ - pGC->ops = &ShadowGCOps - -#define IS_VISIBLE(pWin) (pPriv->vtSema && \ - (((WindowPtr)pWin)->visibility != VisibilityFullyObscured)) - -#define TRIM_BOX(box, pGC) { \ - BoxPtr extents = &pGC->pCompositeClip->extents;\ - if(box.x1 < extents->x1) box.x1 = extents->x1; \ - if(box.x2 > extents->x2) box.x2 = extents->x2; \ - if(box.y1 < extents->y1) box.y1 = extents->y1; \ - if(box.y2 > extents->y2) box.y2 = extents->y2; \ - } - -#define TRANSLATE_BOX(box, pDraw) { \ - box.x1 += pDraw->x; \ - box.x2 += pDraw->x; \ - box.y1 += pDraw->y; \ - box.y2 += pDraw->y; \ - } - -#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \ - TRANSLATE_BOX(box, pDraw); \ - TRIM_BOX(box, pGC); \ - } - -#define BOX_NOT_EMPTY(box) \ - (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) - - - -Bool -ShadowFBInit2 ( - ScreenPtr pScreen, - RefreshAreaFuncPtr preRefreshArea, - RefreshAreaFuncPtr postRefreshArea -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - ShadowScreenPtr pPriv; - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - - if(!preRefreshArea && !postRefreshArea) return FALSE; - - if(!dixRequestPrivate(ShadowGCKey, sizeof(ShadowGCRec))) - return FALSE; - - if(!(pPriv = (ShadowScreenPtr)xalloc(sizeof(ShadowScreenRec)))) - return FALSE; - - dixSetPrivate(&pScreen->devPrivates, ShadowScreenKey, pPriv); - - pPriv->pScrn = pScrn; - pPriv->preRefresh = preRefreshArea; - pPriv->postRefresh = postRefreshArea; - pPriv->vtSema = TRUE; - - pPriv->CloseScreen = pScreen->CloseScreen; - pPriv->CopyWindow = pScreen->CopyWindow; - pPriv->CreateGC = pScreen->CreateGC; - pPriv->ModifyPixmapHeader = pScreen->ModifyPixmapHeader; - - pPriv->EnterVT = pScrn->EnterVT; - pPriv->LeaveVT = pScrn->LeaveVT; - - pScreen->CloseScreen = ShadowCloseScreen; - pScreen->CopyWindow = ShadowCopyWindow; - pScreen->CreateGC = ShadowCreateGC; - pScreen->ModifyPixmapHeader = ShadowModifyPixmapHeader; - - pScrn->EnterVT = ShadowEnterVT; - pScrn->LeaveVT = ShadowLeaveVT; - - if(ps) { - pPriv->Composite = ps->Composite; - ps->Composite = ShadowComposite; - } - - return TRUE; -} - -Bool -ShadowFBInit ( - ScreenPtr pScreen, - RefreshAreaFuncPtr refreshArea -){ - return ShadowFBInit2(pScreen, NULL, refreshArea); -} - -/**********************************************************/ - -static Bool -ShadowEnterVT(int index, int flags) -{ - ScrnInfoPtr pScrn = xf86Screens[index]; - ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen); - - if((*pPriv->EnterVT)(index, flags)) { - pPriv->vtSema = TRUE; - return TRUE; - } - - return FALSE; -} - -static void -ShadowLeaveVT(int index, int flags) -{ - ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(xf86Screens[index]->pScreen); - - pPriv->vtSema = FALSE; - - (*pPriv->LeaveVT)(index, flags); -} - -/**********************************************************/ - - -static Bool -ShadowCloseScreen (int i, ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - - pScreen->CloseScreen = pPriv->CloseScreen; - pScreen->CopyWindow = pPriv->CopyWindow; - pScreen->CreateGC = pPriv->CreateGC; - pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader; - - pScrn->EnterVT = pPriv->EnterVT; - pScrn->LeaveVT = pPriv->LeaveVT; - - if(ps) { - ps->Composite = pPriv->Composite; - } - - xfree((pointer)pPriv); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static void -ShadowCopyWindow( - WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgn -){ - ScreenPtr pScreen = pWin->drawable.pScreen; - ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); - int num = 0; - RegionRec rgnDst; - - if (pPriv->vtSema) { - REGION_NULL(pWin->drawable.pScreen, &rgnDst); - REGION_COPY(pWin->drawable.pScreen, &rgnDst, prgn); - - REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst, - pWin->drawable.x - ptOldOrg.x, - pWin->drawable.y - ptOldOrg.y); - REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, &rgnDst); - if ((num = REGION_NUM_RECTS(&rgnDst))) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst)); - } else { - REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); - } - } - - pScreen->CopyWindow = pPriv->CopyWindow; - (*pScreen->CopyWindow) (pWin, ptOldOrg, prgn); - pScreen->CopyWindow = ShadowCopyWindow; - - if (num) { - if (pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst)); - REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); - } -} - -static Bool -ShadowModifyPixmapHeader( - PixmapPtr pPixmap, - int width, - int height, - int depth, - int bitsPerPixel, - int devKind, - pointer pPixData -) -{ - ScreenPtr pScreen; - ScrnInfoPtr pScrn; - ShadowScreenPtr pPriv; - Bool retval; - PixmapPtr pScreenPix; - - if (!pPixmap) - return FALSE; - - pScreen = pPixmap->drawable.pScreen; - pScrn = xf86Screens[pScreen->myNum]; - - pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); - - if (pPixmap == pScreenPix && !pScrn->vtSema) - pScreenPix->devPrivate = pScrn->pixmapPrivate; - - pPriv = GET_SCREEN_PRIVATE(pScreen); - - pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader; - retval = (*pScreen->ModifyPixmapHeader)(pPixmap, - width, height, depth, bitsPerPixel, devKind, pPixData); - pScreen->ModifyPixmapHeader = ShadowModifyPixmapHeader; - - if (pPixmap == pScreenPix && !pScrn->vtSema) - { - pScrn->pixmapPrivate = pScreenPix->devPrivate; - pScreenPix->devPrivate.ptr = 0; - } - return retval; -} - -static void -ShadowComposite( - CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height -){ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); - PictureScreenPtr ps = GetPictureScreen(pScreen); - BoxRec box; - BoxPtr extents; - Bool boxNotEmpty = FALSE; - - if (pPriv->vtSema - && pDst->pDrawable->type == DRAWABLE_WINDOW) { - - box.x1 = pDst->pDrawable->x + xDst; - box.y1 = pDst->pDrawable->y + yDst; - box.x2 = box.x1 + width; - box.y2 = box.y1 + height; - - extents = &pDst->pCompositeClip->extents; - if(box.x1 < extents->x1) box.x1 = extents->x1; - if(box.x2 > extents->x2) box.x2 = extents->x2; - if(box.y1 < extents->y1) box.y1 = extents->y1; - if(box.y2 > extents->y2) box.y2 = extents->y2; - - if (BOX_NOT_EMPTY(box)) { - if (pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - ps->Composite = pPriv->Composite; - (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, - xMask, yMask, xDst, yDst, width, height); - ps->Composite = ShadowComposite; - - if (pPriv->postRefresh && boxNotEmpty) { - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - } -} - -/**********************************************************/ - -static void ShadowValidateGC(GCPtr, unsigned long, DrawablePtr); -static void ShadowChangeGC(GCPtr, unsigned long); -static void ShadowCopyGC(GCPtr, unsigned long, GCPtr); -static void ShadowDestroyGC(GCPtr); -static void ShadowChangeClip(GCPtr, int, pointer, int); -static void ShadowDestroyClip(GCPtr); -static void ShadowCopyClip(GCPtr, GCPtr); - -GCFuncs ShadowGCFuncs = { - ShadowValidateGC, ShadowChangeGC, ShadowCopyGC, ShadowDestroyGC, - ShadowChangeClip, ShadowDestroyClip, ShadowCopyClip -}; - - -extern GCOps ShadowGCOps; - -static Bool -ShadowCreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); - ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC); - Bool ret; - - pScreen->CreateGC = pPriv->CreateGC; - if((ret = (*pScreen->CreateGC) (pGC))) { - pGCPriv->ops = NULL; - pGCPriv->funcs = pGC->funcs; - pGC->funcs = &ShadowGCFuncs; - } - pScreen->CreateGC = ShadowCreateGC; - - return ret; -} - - -static void -ShadowValidateGC( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -){ - SHADOW_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); - if(pDraw->type == DRAWABLE_WINDOW) - pGCPriv->ops = pGC->ops; /* just so it's not NULL */ - else - pGCPriv->ops = NULL; - SHADOW_GC_FUNC_EPILOGUE (pGC); -} - - -static void -ShadowDestroyGC(GCPtr pGC) -{ - SHADOW_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->DestroyGC)(pGC); - SHADOW_GC_FUNC_EPILOGUE (pGC); -} - -static void -ShadowChangeGC ( - GCPtr pGC, - unsigned long mask -){ - SHADOW_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeGC) (pGC, mask); - SHADOW_GC_FUNC_EPILOGUE (pGC); -} - -static void -ShadowCopyGC ( - GCPtr pGCSrc, - unsigned long mask, - GCPtr pGCDst -){ - SHADOW_GC_FUNC_PROLOGUE (pGCDst); - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - SHADOW_GC_FUNC_EPILOGUE (pGCDst); -} - -static void -ShadowChangeClip ( - GCPtr pGC, - int type, - pointer pvalue, - int nrects -){ - SHADOW_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); - SHADOW_GC_FUNC_EPILOGUE (pGC); -} - -static void -ShadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc) -{ - SHADOW_GC_FUNC_PROLOGUE (pgcDst); - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - SHADOW_GC_FUNC_EPILOGUE (pgcDst); -} - -static void -ShadowDestroyClip(GCPtr pGC) -{ - SHADOW_GC_FUNC_PROLOGUE (pGC); - (* pGC->funcs->DestroyClip)(pGC); - SHADOW_GC_FUNC_EPILOGUE (pGC); -} - - - - -/**********************************************************/ - - -static void -ShadowFillSpans( - DrawablePtr pDraw, - GC *pGC, - int nInit, - DDXPointPtr pptInit, - int *pwidthInit, - int fSorted -){ - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nInit) { - DDXPointPtr ppt = pptInit; - int *pwidth = pwidthInit; - int i = nInit; - BoxRec box; - Bool boxNotEmpty = FALSE; - - box.x1 = ppt->x; - box.x2 = box.x1 + *pwidth; - box.y2 = box.y1 = ppt->y; - - while(--i) { - ppt++; - pwidth++; - if(box.x1 > ppt->x) box.x1 = ppt->x; - if(box.x2 < (ppt->x + *pwidth)) - box.x2 = ppt->x + *pwidth; - if(box.y1 > ppt->y) box.y1 = ppt->y; - else if(box.y2 < ppt->y) box.y2 = ppt->y; - } - - box.y2++; - - if(!pGC->miTranslate) { - TRANSLATE_BOX(box, pDraw); - } - TRIM_BOX(box, pGC); - - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - - (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - } else - (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - -static void -ShadowSetSpans( - DrawablePtr pDraw, - GCPtr pGC, - char *pcharsrc, - DDXPointPtr pptInit, - int *pwidthInit, - int nspans, - int fSorted -){ - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nspans) { - DDXPointPtr ppt = pptInit; - int *pwidth = pwidthInit; - int i = nspans; - BoxRec box; - Bool boxNotEmpty = FALSE; - - box.x1 = ppt->x; - box.x2 = box.x1 + *pwidth; - box.y2 = box.y1 = ppt->y; - - while(--i) { - ppt++; - pwidth++; - if(box.x1 > ppt->x) box.x1 = ppt->x; - if(box.x2 < (ppt->x + *pwidth)) - box.x2 = ppt->x + *pwidth; - if(box.y1 > ppt->y) box.y1 = ppt->y; - else if(box.y2 < ppt->y) box.y2 = ppt->y; - } - - box.y2++; - - if(!pGC->miTranslate) { - TRANSLATE_BOX(box, pDraw); - } - TRIM_BOX(box, pGC); - - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - - (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, - pwidthInit, nspans, fSorted); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - } else - (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, - pwidthInit, nspans, fSorted); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - -static void -ShadowPutImage( - DrawablePtr pDraw, - GCPtr pGC, - int depth, - int x, int y, int w, int h, - int leftPad, - int format, - char *pImage -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw)) { - box.x1 = x + pDraw->x; - box.x2 = box.x1 + w; - box.y1 = y + pDraw->y; - box.y2 = box.y1 + h; - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, - leftPad, format, pImage); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); - -} - -static RegionPtr -ShadowCopyArea( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty -){ - RegionPtr ret; - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDst)) { - box.x1 = dstx + pDst->x; - box.x2 = box.x1 + width; - box.y1 = dsty + pDst->y; - box.y2 = box.y1 + height; - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - ret = (*pGC->ops->CopyArea)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); - - return ret; -} - -static RegionPtr -ShadowCopyPlane( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty, - unsigned long bitPlane -){ - RegionPtr ret; - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDst)) { - box.x1 = dstx + pDst->x; - box.x2 = box.x1 + width; - box.y1 = dsty + pDst->y; - box.y2 = box.y1 + height; - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - ret = (*pGC->ops->CopyPlane)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); - - return ret; -} - -static void -ShadowPolyPoint( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int nptInit, - xPoint *pptInit -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nptInit) { - xPoint *ppt = pptInit; - int npt = nptInit; - - box.x2 = box.x1 = pptInit->x; - box.y2 = box.y1 = pptInit->y; - - /* this could be slow if the points were spread out */ - - while(--npt) { - ppt++; - if(box.x1 > ppt->x) box.x1 = ppt->x; - else if(box.x2 < ppt->x) box.x2 = ppt->x; - if(box.y1 > ppt->y) box.y1 = ppt->y; - else if(box.y2 < ppt->y) box.y2 = ppt->y; - } - - box.x2++; - box.y2++; - - TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->PolyPoint)(pDraw, pGC, mode, nptInit, pptInit); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - -static void -ShadowPolylines( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int nptInit, - DDXPointPtr pptInit -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nptInit) { - DDXPointPtr ppt = pptInit; - int npt = nptInit; - int extra = pGC->lineWidth >> 1; - - box.x2 = box.x1 = pptInit->x; - box.y2 = box.y1 = pptInit->y; - - if(npt > 1) { - if(pGC->joinStyle == JoinMiter) - extra = 6 * pGC->lineWidth; - else if(pGC->capStyle == CapProjecting) - extra = pGC->lineWidth; - } - - if(mode == CoordModePrevious) { - int x = box.x1; - int y = box.y1; - while(--npt) { - ppt++; - x += ppt->x; - y += ppt->y; - if(box.x1 > x) box.x1 = x; - else if(box.x2 < x) box.x2 = x; - if(box.y1 > y) box.y1 = y; - else if(box.y2 < y) box.y2 = y; - } - } else { - while(--npt) { - ppt++; - if(box.x1 > ppt->x) box.x1 = ppt->x; - else if(box.x2 < ppt->x) box.x2 = ppt->x; - if(box.y1 > ppt->y) box.y1 = ppt->y; - else if(box.y2 < ppt->y) box.y2 = ppt->y; - } - } - - box.x2++; - box.y2++; - - if(extra) { - box.x1 -= extra; - box.x2 += extra; - box.y1 -= extra; - box.y2 += extra; - } - - TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->Polylines)(pDraw, pGC, mode, nptInit, pptInit); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - -static void -ShadowPolySegment( - DrawablePtr pDraw, - GCPtr pGC, - int nsegInit, - xSegment *pSegInit -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nsegInit) { - int extra = pGC->lineWidth; - xSegment *pSeg = pSegInit; - int nseg = nsegInit; - - if(pGC->capStyle != CapProjecting) - extra >>= 1; - - if(pSeg->x2 > pSeg->x1) { - box.x1 = pSeg->x1; - box.x2 = pSeg->x2; - } else { - box.x2 = pSeg->x1; - box.x1 = pSeg->x2; - } - - if(pSeg->y2 > pSeg->y1) { - box.y1 = pSeg->y1; - box.y2 = pSeg->y2; - } else { - box.y2 = pSeg->y1; - box.y1 = pSeg->y2; - } - - while(--nseg) { - pSeg++; - if(pSeg->x2 > pSeg->x1) { - if(pSeg->x1 < box.x1) box.x1 = pSeg->x1; - if(pSeg->x2 > box.x2) box.x2 = pSeg->x2; - } else { - if(pSeg->x2 < box.x1) box.x1 = pSeg->x2; - if(pSeg->x1 > box.x2) box.x2 = pSeg->x1; - } - if(pSeg->y2 > pSeg->y1) { - if(pSeg->y1 < box.y1) box.y1 = pSeg->y1; - if(pSeg->y2 > box.y2) box.y2 = pSeg->y2; - } else { - if(pSeg->y2 < box.y1) box.y1 = pSeg->y2; - if(pSeg->y1 > box.y2) box.y2 = pSeg->y1; - } - } - - box.x2++; - box.y2++; - - if(extra) { - box.x1 -= extra; - box.x2 += extra; - box.y1 -= extra; - box.y2 += extra; - } - - TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->PolySegment)(pDraw, pGC, nsegInit, pSegInit); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - -static void -ShadowPolyRectangle( - DrawablePtr pDraw, - GCPtr pGC, - int nRectsInit, - xRectangle *pRectsInit -){ - BoxRec box; - BoxPtr pBoxInit = NULL; - Bool boxNotEmpty = FALSE; - int num = 0; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nRectsInit) { - xRectangle *pRects = pRectsInit; - int nRects = nRectsInit; - - if(nRects >= 32) { - int extra = pGC->lineWidth >> 1; - - box.x1 = pRects->x; - box.x2 = box.x1 + pRects->width; - box.y1 = pRects->y; - box.y2 = box.y1 + pRects->height; - - while(--nRects) { - pRects++; - if(box.x1 > pRects->x) box.x1 = pRects->x; - if(box.x2 < (pRects->x + pRects->width)) - box.x2 = pRects->x + pRects->width; - if(box.y1 > pRects->y) box.y1 = pRects->y; - if(box.y2 < (pRects->y + pRects->height)) - box.y2 = pRects->y + pRects->height; - } - - if(extra) { - box.x1 -= extra; - box.x2 += extra; - box.y1 -= extra; - box.y2 += extra; - } - - box.x2++; - box.y2++; - - TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } else { - BoxPtr pbox; - int offset1, offset2, offset3; - - offset2 = pGC->lineWidth; - if(!offset2) offset2 = 1; - offset1 = offset2 >> 1; - offset3 = offset2 - offset1; - - pBoxInit = (BoxPtr)xalloc(nRects * 4 * sizeof(BoxRec)); - pbox = pBoxInit; - - while(nRects--) { - pbox->x1 = pRects->x - offset1; - pbox->y1 = pRects->y - offset1; - pbox->x2 = pbox->x1 + pRects->width + offset2; - pbox->y2 = pbox->y1 + offset2; - TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); - if(BOX_NOT_EMPTY((*pbox))) { - num++; - pbox++; - } - - pbox->x1 = pRects->x - offset1; - pbox->y1 = pRects->y + offset3; - pbox->x2 = pbox->x1 + offset2; - pbox->y2 = pbox->y1 + pRects->height - offset2; - TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); - if(BOX_NOT_EMPTY((*pbox))) { - num++; - pbox++; - } - - pbox->x1 = pRects->x + pRects->width - offset1; - pbox->y1 = pRects->y + offset3; - pbox->x2 = pbox->x1 + offset2; - pbox->y2 = pbox->y1 + pRects->height - offset2; - TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); - if(BOX_NOT_EMPTY((*pbox))) { - num++; - pbox++; - } - - pbox->x1 = pRects->x - offset1; - pbox->y1 = pRects->y + pRects->height - offset1; - pbox->x2 = pbox->x1 + pRects->width + offset2; - pbox->y2 = pbox->y1 + offset2; - TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); - if(BOX_NOT_EMPTY((*pbox))) { - num++; - pbox++; - } - - pRects++; - } - - if(num) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, num, pBoxInit); - } else { - xfree(pBoxInit); - } - } - } - - (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit); - - if(boxNotEmpty && pPriv->postRefresh) { - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - } else if(num) { - if(pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, num, pBoxInit); - xfree(pBoxInit); - } - - SHADOW_GC_OP_EPILOGUE(pGC); - -} - -static void -ShadowPolyArc( - DrawablePtr pDraw, - GCPtr pGC, - int narcsInit, - xArc *parcsInit -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && narcsInit) { - int narcs = narcsInit; - xArc *parcs = parcsInit; - int extra = pGC->lineWidth >> 1; - - box.x1 = parcs->x; - box.x2 = box.x1 + parcs->width; - box.y1 = parcs->y; - box.y2 = box.y1 + parcs->height; - - /* should I break these up instead ? */ - - while(--narcs) { - parcs++; - if(box.x1 > parcs->x) box.x1 = parcs->x; - if(box.x2 < (parcs->x + parcs->width)) - box.x2 = parcs->x + parcs->width; - if(box.y1 > parcs->y) box.y1 = parcs->y; - if(box.y2 < (parcs->y + parcs->height)) - box.y2 = parcs->y + parcs->height; - } - - if(extra) { - box.x1 -= extra; - box.x2 += extra; - box.y1 -= extra; - box.y2 += extra; - } - - box.x2++; - box.y2++; - - TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->PolyArc)(pDraw, pGC, narcsInit, parcsInit); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); - -} - -static void -ShadowFillPolygon( - DrawablePtr pDraw, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr pptInit -){ - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && (count > 2)) { - DDXPointPtr ppt = pptInit; - int i = count; - BoxRec box; - Bool boxNotEmpty = FALSE; - - box.x2 = box.x1 = ppt->x; - box.y2 = box.y1 = ppt->y; - - if(mode != CoordModeOrigin) { - int x = box.x1; - int y = box.y1; - while(--i) { - ppt++; - x += ppt->x; - y += ppt->y; - if(box.x1 > x) box.x1 = x; - else if(box.x2 < x) box.x2 = x; - if(box.y1 > y) box.y1 = y; - else if(box.y2 < y) box.y2 = y; - } - } else { - while(--i) { - ppt++; - if(box.x1 > ppt->x) box.x1 = ppt->x; - else if(box.x2 < ppt->x) box.x2 = ppt->x; - if(box.y1 > ppt->y) box.y1 = ppt->y; - else if(box.y2 < ppt->y) box.y2 = ppt->y; - } - } - - box.x2++; - box.y2++; - - TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - - (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - } else - (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - - -static void -ShadowPolyFillRect( - DrawablePtr pDraw, - GCPtr pGC, - int nRectsInit, - xRectangle *pRectsInit -){ - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nRectsInit) { - BoxRec box; - Bool boxNotEmpty = FALSE; - xRectangle *pRects = pRectsInit; - int nRects = nRectsInit; - - box.x1 = pRects->x; - box.x2 = box.x1 + pRects->width; - box.y1 = pRects->y; - box.y2 = box.y1 + pRects->height; - - while(--nRects) { - pRects++; - if(box.x1 > pRects->x) box.x1 = pRects->x; - if(box.x2 < (pRects->x + pRects->width)) - box.x2 = pRects->x + pRects->width; - if(box.y1 > pRects->y) box.y1 = pRects->y; - if(box.y2 < (pRects->y + pRects->height)) - box.y2 = pRects->y + pRects->height; - } - - /* cfb messes with the pRectsInit so we have to do our - calculations first */ - - TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - - (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - } else - (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - - -static void -ShadowPolyFillArc( - DrawablePtr pDraw, - GCPtr pGC, - int narcsInit, - xArc *parcsInit -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && narcsInit) { - xArc *parcs = parcsInit; - int narcs = narcsInit; - - box.x1 = parcs->x; - box.x2 = box.x1 + parcs->width; - box.y1 = parcs->y; - box.y2 = box.y1 + parcs->height; - - /* should I break these up instead ? */ - - while(--narcs) { - parcs++; - if(box.x1 > parcs->x) box.x1 = parcs->x; - if(box.x2 < (parcs->x + parcs->width)) - box.x2 = parcs->x + parcs->width; - if(box.y1 > parcs->y) box.y1 = parcs->y; - if(box.y2 < (parcs->y + parcs->height)) - box.y2 = parcs->y + parcs->height; - } - - TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->PolyFillArc)(pDraw, pGC, narcsInit, parcsInit); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - -static void -ShadowTextExtent(FontPtr pFont, int count, char* chars, - FontEncoding fontEncoding, BoxPtr box) -{ - unsigned long n, i; - int w; - CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ - - GetGlyphs(pFont, (unsigned long)count, (unsigned char *)chars, - fontEncoding, &n, charinfo); - w = 0; - for (i=0; i < n; i++) { - w += charinfo[i]->metrics.characterWidth; - } - if (i) { - w += charinfo[i - 1]->metrics.rightSideBearing; - } - - box->x1 = 0; - if (n) { - if (charinfo[0]->metrics.leftSideBearing < 0) { - box->x1 = charinfo[0]->metrics.leftSideBearing; - } - } - box->x2 = w; - box->y1 = -FONTMAXBOUNDS(pFont,ascent); - box->y2 = FONTMAXBOUNDS(pFont,descent); -} - - - -static void -ShadowFontToBox(BoxPtr BB, DrawablePtr pDrawable, GCPtr pGC, int x, int y, - int count, char *chars, int wide) -{ - FontPtr pFont; - - pFont = pGC->font; - if (pFont->info.constantWidth) { - int ascent, descent, left, right = 0; - - ascent = max(pFont->info.fontAscent, pFont->info.maxbounds.ascent); - descent = max(pFont->info.fontDescent, pFont->info.maxbounds.descent); - left = pFont->info.maxbounds.leftSideBearing; - if (count > 0) { - right = (count - 1) * pFont->info.maxbounds.characterWidth; - } - right += pFont->info.maxbounds.rightSideBearing; - BB->x1 = - max(pDrawable->x + x - left, (REGION_EXTENTS(pGC->pScreen, - &((WindowPtr) pDrawable)->winSize))->x1); - BB->y1 = - max(pDrawable->y + y - ascent, - (REGION_EXTENTS(pGC->pScreen, - &((WindowPtr) pDrawable)->winSize))->y1); - BB->x2 = - min(pDrawable->x + x + right, - (REGION_EXTENTS(pGC->pScreen, - &((WindowPtr) pDrawable)->winSize))->x2); - BB->y2 = - min(pDrawable->y + y + descent, - (REGION_EXTENTS(pGC->pScreen, - &((WindowPtr) pDrawable)->winSize))->y2); - } else { - ShadowTextExtent(pFont, count, chars, wide ? (FONTLASTROW(pFont) == 0) - ? Linear16Bit : TwoD16Bit : Linear8Bit, BB); - BB->x1 = - max(pDrawable->x + x + BB->x1, (REGION_EXTENTS(pGC->pScreen, - &((WindowPtr) pDrawable)->winSize))->x1); - BB->y1 = - max(pDrawable->y + y + BB->y1, - (REGION_EXTENTS(pGC->pScreen, - &((WindowPtr) pDrawable)->winSize))->y1); - BB->x2 = - min(pDrawable->x + x + BB->x2, - (REGION_EXTENTS(pGC->pScreen, - &((WindowPtr) pDrawable)->winSize))->x2); - BB->y2 = - min(pDrawable->y + y + BB->y2, - (REGION_EXTENTS(pGC->pScreen, - &((WindowPtr) pDrawable)->winSize))->y2); - } -} - -static int -ShadowPolyText8( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - char *chars -){ - int width; - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw)) { - ShadowFontToBox(&box, pDraw, pGC, x, y, count, chars, 0); - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); - - return width; -} - -static int -ShadowPolyText16( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - unsigned short *chars -){ - int width; - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw)) { - ShadowFontToBox(&box, pDraw, pGC, x, y, count, (char*)chars, 1); - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); - - return width; -} - -static void -ShadowImageText8( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - char *chars -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && count) { - int top, bot, Min, Max; - - top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); - bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); - - Min = count * FONTMINBOUNDS(pGC->font, characterWidth); - if(Min > 0) Min = 0; - Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); - if(Max < 0) Max = 0; - - /* ugh */ - box.x1 = pDraw->x + x + Min + - FONTMINBOUNDS(pGC->font, leftSideBearing); - box.x2 = pDraw->x + x + Max + - FONTMAXBOUNDS(pGC->font, rightSideBearing); - - box.y1 = pDraw->y + y - top; - box.y2 = pDraw->y + y + bot; - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} -static void -ShadowImageText16( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - unsigned short *chars -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && count) { - int top, bot, Min, Max; - - top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); - bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); - - Min = count * FONTMINBOUNDS(pGC->font, characterWidth); - if(Min > 0) Min = 0; - Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); - if(Max < 0) Max = 0; - - /* ugh */ - box.x1 = pDraw->x + x + Min + - FONTMINBOUNDS(pGC->font, leftSideBearing); - box.x2 = pDraw->x + x + Max + - FONTMAXBOUNDS(pGC->font, rightSideBearing); - - box.y1 = pDraw->y + y - top; - box.y2 = pDraw->y + y + bot; - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - - -static void -ShadowImageGlyphBlt( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - unsigned int nglyphInit, - CharInfoPtr *ppciInit, - pointer pglyphBase -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nglyphInit) { - CharInfoPtr *ppci = ppciInit; - unsigned int nglyph = nglyphInit; - int top, bot, width = 0; - - top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); - bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); - - box.x1 = ppci[0]->metrics.leftSideBearing; - if(box.x1 > 0) box.x1 = 0; - box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - - ppci[nglyph - 1]->metrics.characterWidth; - if(box.x2 < 0) box.x2 = 0; - - box.x2 += pDraw->x + x; - box.x1 += pDraw->x + x; - - while(nglyph--) { - width += (*ppci)->metrics.characterWidth; - ppci++; - } - - if(width > 0) - box.x2 += width; - else - box.x1 += width; - - box.y1 = pDraw->y + y - top; - box.y2 = pDraw->y + y + bot; - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyphInit, - ppciInit, pglyphBase); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - -static void -ShadowPolyGlyphBlt( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - unsigned int nglyphInit, - CharInfoPtr *ppciInit, - pointer pglyphBase -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw) && nglyphInit) { - CharInfoPtr *ppci = ppciInit; - unsigned int nglyph = nglyphInit; - - /* ugh */ - box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing; - box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing; - - if(nglyph > 1) { - int width = 0; - - while(--nglyph) { - width += (*ppci)->metrics.characterWidth; - ppci++; - } - - if(width > 0) box.x2 += width; - else box.x1 += width; - } - - box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent); - box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent); - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyphInit, - ppciInit, pglyphBase); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - -static void -ShadowPushPixels( - GCPtr pGC, - PixmapPtr pBitMap, - DrawablePtr pDraw, - int dx, int dy, int xOrg, int yOrg -){ - BoxRec box; - Bool boxNotEmpty = FALSE; - - SHADOW_GC_OP_PROLOGUE(pGC); - - if(IS_VISIBLE(pDraw)) { - box.x1 = xOrg; - box.y1 = yOrg; - - if(!pGC->miTranslate) { - box.x1 += pDraw->x; - box.y1 += pDraw->y; - } - - box.x2 = box.x1 + dx; - box.y2 = box.y1 + dy; - - TRIM_BOX(box, pGC); - if(BOX_NOT_EMPTY(box)) { - if(pPriv->preRefresh) - (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); - boxNotEmpty = TRUE; - } - } - - (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); - - if(boxNotEmpty && pPriv->postRefresh) - (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); - - SHADOW_GC_OP_EPILOGUE(pGC); -} - - -GCOps ShadowGCOps = { - ShadowFillSpans, ShadowSetSpans, - ShadowPutImage, ShadowCopyArea, - ShadowCopyPlane, ShadowPolyPoint, - ShadowPolylines, ShadowPolySegment, - ShadowPolyRectangle, ShadowPolyArc, - ShadowFillPolygon, ShadowPolyFillRect, - ShadowPolyFillArc, ShadowPolyText8, - ShadowPolyText16, ShadowImageText8, - ShadowImageText16, ShadowImageGlyphBlt, - ShadowPolyGlyphBlt, ShadowPushPixels, - {NULL} /* devPrivate */ -}; - +/* + Copyright (C) 1999. The XFree86 Project Inc. + + Written by Mark Vojkovich (mvojkovi@ucsd.edu) + + Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com) +*/ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "pixmapstr.h" +#include "input.h" +#include +#include "mi.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "dixfontstr.h" +#include +#include "xf86.h" +#include "xf86str.h" +#include "shadowfb.h" + +# include "picturestr.h" + +static Bool ShadowCloseScreen (int i, ScreenPtr pScreen); +static void ShadowCopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgn +); +static Bool ShadowCreateGC(GCPtr pGC); +static Bool ShadowModifyPixmapHeader( + PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, + int devKind, + pointer pPixData +); + +static Bool ShadowEnterVT(int index, int flags); +static void ShadowLeaveVT(int index, int flags); + +static void ShadowComposite( + CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height +); + + +typedef struct { + ScrnInfoPtr pScrn; + RefreshAreaFuncPtr preRefresh; + RefreshAreaFuncPtr postRefresh; + CloseScreenProcPtr CloseScreen; + CopyWindowProcPtr CopyWindow; + CreateGCProcPtr CreateGC; + ModifyPixmapHeaderProcPtr ModifyPixmapHeader; + CompositeProcPtr Composite; + Bool (*EnterVT)(int, int); + void (*LeaveVT)(int, int); + Bool vtSema; +} ShadowScreenRec, *ShadowScreenPtr; + +typedef struct { + GCOps *ops; + GCFuncs *funcs; +} ShadowGCRec, *ShadowGCPtr; + + +static int ShadowScreenKeyIndex; +static DevPrivateKey ShadowScreenKey = &ShadowScreenKeyIndex; +static int ShadowGCKeyIndex; +static DevPrivateKey ShadowGCKey = &ShadowGCKeyIndex; + +#define GET_SCREEN_PRIVATE(pScreen) \ + (ShadowScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, ShadowScreenKey) +#define GET_GC_PRIVATE(pGC) \ + (ShadowGCPtr)dixLookupPrivate(&(pGC)->devPrivates, ShadowGCKey) + +#define SHADOW_GC_FUNC_PROLOGUE(pGC)\ + ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\ + (pGC)->funcs = pGCPriv->funcs;\ + if(pGCPriv->ops)\ + (pGC)->ops = pGCPriv->ops + +#define SHADOW_GC_FUNC_EPILOGUE(pGC)\ + pGCPriv->funcs = (pGC)->funcs;\ + (pGC)->funcs = &ShadowGCFuncs;\ + if(pGCPriv->ops) {\ + pGCPriv->ops = (pGC)->ops;\ + (pGC)->ops = &ShadowGCOps;\ + } + +#define SHADOW_GC_OP_PROLOGUE(pGC)\ + ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pGC->pScreen); \ + ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC);\ + GCFuncs *oldFuncs = pGC->funcs;\ + pGC->funcs = pGCPriv->funcs;\ + pGC->ops = pGCPriv->ops + + +#define SHADOW_GC_OP_EPILOGUE(pGC)\ + pGCPriv->ops = pGC->ops;\ + pGC->funcs = oldFuncs;\ + pGC->ops = &ShadowGCOps + +#define IS_VISIBLE(pWin) (pPriv->vtSema && \ + (((WindowPtr)pWin)->visibility != VisibilityFullyObscured)) + +#define TRIM_BOX(box, pGC) { \ + BoxPtr extents = &pGC->pCompositeClip->extents;\ + if(box.x1 < extents->x1) box.x1 = extents->x1; \ + if(box.x2 > extents->x2) box.x2 = extents->x2; \ + if(box.y1 < extents->y1) box.y1 = extents->y1; \ + if(box.y2 > extents->y2) box.y2 = extents->y2; \ + } + +#define TRANSLATE_BOX(box, pDraw) { \ + box.x1 += pDraw->x; \ + box.x2 += pDraw->x; \ + box.y1 += pDraw->y; \ + box.y2 += pDraw->y; \ + } + +#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \ + TRANSLATE_BOX(box, pDraw); \ + TRIM_BOX(box, pGC); \ + } + +#define BOX_NOT_EMPTY(box) \ + (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) + + + +Bool +ShadowFBInit2 ( + ScreenPtr pScreen, + RefreshAreaFuncPtr preRefreshArea, + RefreshAreaFuncPtr postRefreshArea +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ShadowScreenPtr pPriv; + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if(!preRefreshArea && !postRefreshArea) return FALSE; + + if(!dixRequestPrivate(ShadowGCKey, sizeof(ShadowGCRec))) + return FALSE; + + if(!(pPriv = (ShadowScreenPtr)malloc(sizeof(ShadowScreenRec)))) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, ShadowScreenKey, pPriv); + + pPriv->pScrn = pScrn; + pPriv->preRefresh = preRefreshArea; + pPriv->postRefresh = postRefreshArea; + pPriv->vtSema = TRUE; + + pPriv->CloseScreen = pScreen->CloseScreen; + pPriv->CopyWindow = pScreen->CopyWindow; + pPriv->CreateGC = pScreen->CreateGC; + pPriv->ModifyPixmapHeader = pScreen->ModifyPixmapHeader; + + pPriv->EnterVT = pScrn->EnterVT; + pPriv->LeaveVT = pScrn->LeaveVT; + + pScreen->CloseScreen = ShadowCloseScreen; + pScreen->CopyWindow = ShadowCopyWindow; + pScreen->CreateGC = ShadowCreateGC; + pScreen->ModifyPixmapHeader = ShadowModifyPixmapHeader; + + pScrn->EnterVT = ShadowEnterVT; + pScrn->LeaveVT = ShadowLeaveVT; + + if(ps) { + pPriv->Composite = ps->Composite; + ps->Composite = ShadowComposite; + } + + return TRUE; +} + +Bool +ShadowFBInit ( + ScreenPtr pScreen, + RefreshAreaFuncPtr refreshArea +){ + return ShadowFBInit2(pScreen, NULL, refreshArea); +} + +/**********************************************************/ + +static Bool +ShadowEnterVT(int index, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScrn->pScreen); + + if((*pPriv->EnterVT)(index, flags)) { + pPriv->vtSema = TRUE; + return TRUE; + } + + return FALSE; +} + +static void +ShadowLeaveVT(int index, int flags) +{ + ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(xf86Screens[index]->pScreen); + + pPriv->vtSema = FALSE; + + (*pPriv->LeaveVT)(index, flags); +} + +/**********************************************************/ + + +static Bool +ShadowCloseScreen (int i, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + pScreen->CloseScreen = pPriv->CloseScreen; + pScreen->CopyWindow = pPriv->CopyWindow; + pScreen->CreateGC = pPriv->CreateGC; + pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader; + + pScrn->EnterVT = pPriv->EnterVT; + pScrn->LeaveVT = pPriv->LeaveVT; + + if(ps) { + ps->Composite = pPriv->Composite; + } + + free((pointer)pPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +ShadowCopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgn +){ + ScreenPtr pScreen = pWin->drawable.pScreen; + ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); + int num = 0; + RegionRec rgnDst; + + if (pPriv->vtSema) { + REGION_NULL(pWin->drawable.pScreen, &rgnDst); + REGION_COPY(pWin->drawable.pScreen, &rgnDst, prgn); + + REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst, + pWin->drawable.x - ptOldOrg.x, + pWin->drawable.y - ptOldOrg.y); + REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, &rgnDst); + if ((num = REGION_NUM_RECTS(&rgnDst))) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst)); + } else { + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); + } + } + + pScreen->CopyWindow = pPriv->CopyWindow; + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgn); + pScreen->CopyWindow = ShadowCopyWindow; + + if (num) { + if (pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, num, REGION_RECTS(&rgnDst)); + REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); + } +} + +static Bool +ShadowModifyPixmapHeader( + PixmapPtr pPixmap, + int width, + int height, + int depth, + int bitsPerPixel, + int devKind, + pointer pPixData +) +{ + ScreenPtr pScreen; + ScrnInfoPtr pScrn; + ShadowScreenPtr pPriv; + Bool retval; + PixmapPtr pScreenPix; + + if (!pPixmap) + return FALSE; + + pScreen = pPixmap->drawable.pScreen; + pScrn = xf86Screens[pScreen->myNum]; + + pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); + + if (pPixmap == pScreenPix && !pScrn->vtSema) + pScreenPix->devPrivate = pScrn->pixmapPrivate; + + pPriv = GET_SCREEN_PRIVATE(pScreen); + + pScreen->ModifyPixmapHeader = pPriv->ModifyPixmapHeader; + retval = (*pScreen->ModifyPixmapHeader)(pPixmap, + width, height, depth, bitsPerPixel, devKind, pPixData); + pScreen->ModifyPixmapHeader = ShadowModifyPixmapHeader; + + if (pPixmap == pScreenPix && !pScrn->vtSema) + { + pScrn->pixmapPrivate = pScreenPix->devPrivate; + pScreenPix->devPrivate.ptr = 0; + } + return retval; +} + +static void +ShadowComposite( + CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height +){ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); + PictureScreenPtr ps = GetPictureScreen(pScreen); + BoxRec box; + BoxPtr extents; + Bool boxNotEmpty = FALSE; + + if (pPriv->vtSema + && pDst->pDrawable->type == DRAWABLE_WINDOW) { + + box.x1 = pDst->pDrawable->x + xDst; + box.y1 = pDst->pDrawable->y + yDst; + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; + + extents = &pDst->pCompositeClip->extents; + if(box.x1 < extents->x1) box.x1 = extents->x1; + if(box.x2 > extents->x2) box.x2 = extents->x2; + if(box.y1 < extents->y1) box.y1 = extents->y1; + if(box.y2 > extents->y2) box.y2 = extents->y2; + + if (BOX_NOT_EMPTY(box)) { + if (pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + ps->Composite = pPriv->Composite; + (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc, + xMask, yMask, xDst, yDst, width, height); + ps->Composite = ShadowComposite; + + if (pPriv->postRefresh && boxNotEmpty) { + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + } +} + +/**********************************************************/ + +static void ShadowValidateGC(GCPtr, unsigned long, DrawablePtr); +static void ShadowChangeGC(GCPtr, unsigned long); +static void ShadowCopyGC(GCPtr, unsigned long, GCPtr); +static void ShadowDestroyGC(GCPtr); +static void ShadowChangeClip(GCPtr, int, pointer, int); +static void ShadowDestroyClip(GCPtr); +static void ShadowCopyClip(GCPtr, GCPtr); + +GCFuncs ShadowGCFuncs = { + ShadowValidateGC, ShadowChangeGC, ShadowCopyGC, ShadowDestroyGC, + ShadowChangeClip, ShadowDestroyClip, ShadowCopyClip +}; + + +extern GCOps ShadowGCOps; + +static Bool +ShadowCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + ShadowScreenPtr pPriv = GET_SCREEN_PRIVATE(pScreen); + ShadowGCPtr pGCPriv = GET_GC_PRIVATE(pGC); + Bool ret; + + pScreen->CreateGC = pPriv->CreateGC; + if((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->ops = NULL; + pGCPriv->funcs = pGC->funcs; + pGC->funcs = &ShadowGCFuncs; + } + pScreen->CreateGC = ShadowCreateGC; + + return ret; +} + + +static void +ShadowValidateGC( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); + if(pDraw->type == DRAWABLE_WINDOW) + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ + else + pGCPriv->ops = NULL; + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + + +static void +ShadowDestroyGC(GCPtr pGC) +{ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + +static void +ShadowChangeGC ( + GCPtr pGC, + unsigned long mask +){ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + +static void +ShadowCopyGC ( + GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst +){ + SHADOW_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + SHADOW_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +ShadowChangeClip ( + GCPtr pGC, + int type, + pointer pvalue, + int nrects +){ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + +static void +ShadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + SHADOW_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + SHADOW_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +ShadowDestroyClip(GCPtr pGC) +{ + SHADOW_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + SHADOW_GC_FUNC_EPILOGUE (pGC); +} + + + + +/**********************************************************/ + + +static void +ShadowFillSpans( + DrawablePtr pDraw, + GC *pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidthInit, + int fSorted +){ + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nInit) { + DDXPointPtr ppt = pptInit; + int *pwidth = pwidthInit; + int i = nInit; + BoxRec box; + Bool boxNotEmpty = FALSE; + + box.x1 = ppt->x; + box.x2 = box.x1 + *pwidth; + box.y2 = box.y1 = ppt->y; + + while(--i) { + ppt++; + pwidth++; + if(box.x1 > ppt->x) box.x1 = ppt->x; + if(box.x2 < (ppt->x + *pwidth)) + box.x2 = ppt->x + *pwidth; + if(box.y1 > ppt->y) box.y1 = ppt->y; + else if(box.y2 < ppt->y) box.y2 = ppt->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDraw); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + + (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + } else + (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + +static void +ShadowSetSpans( + DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + DDXPointPtr pptInit, + int *pwidthInit, + int nspans, + int fSorted +){ + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nspans) { + DDXPointPtr ppt = pptInit; + int *pwidth = pwidthInit; + int i = nspans; + BoxRec box; + Bool boxNotEmpty = FALSE; + + box.x1 = ppt->x; + box.x2 = box.x1 + *pwidth; + box.y2 = box.y1 = ppt->y; + + while(--i) { + ppt++; + pwidth++; + if(box.x1 > ppt->x) box.x1 = ppt->x; + if(box.x2 < (ppt->x + *pwidth)) + box.x2 = ppt->x + *pwidth; + if(box.y1 > ppt->y) box.y1 = ppt->y; + else if(box.y2 < ppt->y) box.y2 = ppt->y; + } + + box.y2++; + + if(!pGC->miTranslate) { + TRANSLATE_BOX(box, pDraw); + } + TRIM_BOX(box, pGC); + + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + + (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, + pwidthInit, nspans, fSorted); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + } else + (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, + pwidthInit, nspans, fSorted); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + +static void +ShadowPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, + int format, + char *pImage +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw)) { + box.x1 = x + pDraw->x; + box.x2 = box.x1 + w; + box.y1 = y + pDraw->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); + +} + +static RegionPtr +ShadowCopyArea( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty +){ + RegionPtr ret; + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDst)) { + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); + + return ret; +} + +static RegionPtr +ShadowCopyPlane( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane +){ + RegionPtr ret; + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDst)) { + box.x1 = dstx + pDst->x; + box.x2 = box.x1 + width; + box.y1 = dsty + pDst->y; + box.y2 = box.y1 + height; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); + + return ret; +} + +static void +ShadowPolyPoint( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int nptInit, + xPoint *pptInit +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nptInit) { + xPoint *ppt = pptInit; + int npt = nptInit; + + box.x2 = box.x1 = pptInit->x; + box.y2 = box.y1 = pptInit->y; + + /* this could be slow if the points were spread out */ + + while(--npt) { + ppt++; + if(box.x1 > ppt->x) box.x1 = ppt->x; + else if(box.x2 < ppt->x) box.x2 = ppt->x; + if(box.y1 > ppt->y) box.y1 = ppt->y; + else if(box.y2 < ppt->y) box.y2 = ppt->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->PolyPoint)(pDraw, pGC, mode, nptInit, pptInit); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + +static void +ShadowPolylines( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int nptInit, + DDXPointPtr pptInit +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nptInit) { + DDXPointPtr ppt = pptInit; + int npt = nptInit; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptInit->x; + box.y2 = box.y1 = pptInit->y; + + if(npt > 1) { + if(pGC->joinStyle == JoinMiter) + extra = 6 * pGC->lineWidth; + else if(pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + } + + if(mode == CoordModePrevious) { + int x = box.x1; + int y = box.y1; + while(--npt) { + ppt++; + x += ppt->x; + y += ppt->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } else { + while(--npt) { + ppt++; + if(box.x1 > ppt->x) box.x1 = ppt->x; + else if(box.x2 < ppt->x) box.x2 = ppt->x; + if(box.y1 > ppt->y) box.y1 = ppt->y; + else if(box.y2 < ppt->y) box.y2 = ppt->y; + } + } + + box.x2++; + box.y2++; + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->Polylines)(pDraw, pGC, mode, nptInit, pptInit); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + +static void +ShadowPolySegment( + DrawablePtr pDraw, + GCPtr pGC, + int nsegInit, + xSegment *pSegInit +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nsegInit) { + int extra = pGC->lineWidth; + xSegment *pSeg = pSegInit; + int nseg = nsegInit; + + if(pGC->capStyle != CapProjecting) + extra >>= 1; + + if(pSeg->x2 > pSeg->x1) { + box.x1 = pSeg->x1; + box.x2 = pSeg->x2; + } else { + box.x2 = pSeg->x1; + box.x1 = pSeg->x2; + } + + if(pSeg->y2 > pSeg->y1) { + box.y1 = pSeg->y1; + box.y2 = pSeg->y2; + } else { + box.y2 = pSeg->y1; + box.y1 = pSeg->y2; + } + + while(--nseg) { + pSeg++; + if(pSeg->x2 > pSeg->x1) { + if(pSeg->x1 < box.x1) box.x1 = pSeg->x1; + if(pSeg->x2 > box.x2) box.x2 = pSeg->x2; + } else { + if(pSeg->x2 < box.x1) box.x1 = pSeg->x2; + if(pSeg->x1 > box.x2) box.x2 = pSeg->x1; + } + if(pSeg->y2 > pSeg->y1) { + if(pSeg->y1 < box.y1) box.y1 = pSeg->y1; + if(pSeg->y2 > box.y2) box.y2 = pSeg->y2; + } else { + if(pSeg->y2 < box.y1) box.y1 = pSeg->y2; + if(pSeg->y1 > box.y2) box.y2 = pSeg->y1; + } + } + + box.x2++; + box.y2++; + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->PolySegment)(pDraw, pGC, nsegInit, pSegInit); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + +static void +ShadowPolyRectangle( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit +){ + BoxRec box; + BoxPtr pBoxInit = NULL; + Bool boxNotEmpty = FALSE; + int num = 0; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nRectsInit) { + xRectangle *pRects = pRectsInit; + int nRects = nRectsInit; + + if(nRects >= 32) { + int extra = pGC->lineWidth >> 1; + + box.x1 = pRects->x; + box.x2 = box.x1 + pRects->width; + box.y1 = pRects->y; + box.y2 = box.y1 + pRects->height; + + while(--nRects) { + pRects++; + if(box.x1 > pRects->x) box.x1 = pRects->x; + if(box.x2 < (pRects->x + pRects->width)) + box.x2 = pRects->x + pRects->width; + if(box.y1 > pRects->y) box.y1 = pRects->y; + if(box.y2 < (pRects->y + pRects->height)) + box.y2 = pRects->y + pRects->height; + } + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } else { + BoxPtr pbox; + int offset1, offset2, offset3; + + offset2 = pGC->lineWidth; + if(!offset2) offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + pBoxInit = (BoxPtr)malloc(nRects * 4 * sizeof(BoxRec)); + pbox = pBoxInit; + + while(nRects--) { + pbox->x1 = pRects->x - offset1; + pbox->y1 = pRects->y - offset1; + pbox->x2 = pbox->x1 + pRects->width + offset2; + pbox->y2 = pbox->y1 + offset2; + TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); + if(BOX_NOT_EMPTY((*pbox))) { + num++; + pbox++; + } + + pbox->x1 = pRects->x - offset1; + pbox->y1 = pRects->y + offset3; + pbox->x2 = pbox->x1 + offset2; + pbox->y2 = pbox->y1 + pRects->height - offset2; + TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); + if(BOX_NOT_EMPTY((*pbox))) { + num++; + pbox++; + } + + pbox->x1 = pRects->x + pRects->width - offset1; + pbox->y1 = pRects->y + offset3; + pbox->x2 = pbox->x1 + offset2; + pbox->y2 = pbox->y1 + pRects->height - offset2; + TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); + if(BOX_NOT_EMPTY((*pbox))) { + num++; + pbox++; + } + + pbox->x1 = pRects->x - offset1; + pbox->y1 = pRects->y + pRects->height - offset1; + pbox->x2 = pbox->x1 + pRects->width + offset2; + pbox->y2 = pbox->y1 + offset2; + TRIM_AND_TRANSLATE_BOX((*pbox), pDraw, pGC); + if(BOX_NOT_EMPTY((*pbox))) { + num++; + pbox++; + } + + pRects++; + } + + if(num) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, num, pBoxInit); + } else { + free(pBoxInit); + } + } + } + + (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit); + + if(boxNotEmpty && pPriv->postRefresh) { + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + } else if(num) { + if(pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, num, pBoxInit); + free(pBoxInit); + } + + SHADOW_GC_OP_EPILOGUE(pGC); + +} + +static void +ShadowPolyArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcsInit, + xArc *parcsInit +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && narcsInit) { + int narcs = narcsInit; + xArc *parcs = parcsInit; + int extra = pGC->lineWidth >> 1; + + box.x1 = parcs->x; + box.x2 = box.x1 + parcs->width; + box.y1 = parcs->y; + box.y2 = box.y1 + parcs->height; + + /* should I break these up instead ? */ + + while(--narcs) { + parcs++; + if(box.x1 > parcs->x) box.x1 = parcs->x; + if(box.x2 < (parcs->x + parcs->width)) + box.x2 = parcs->x + parcs->width; + if(box.y1 > parcs->y) box.y1 = parcs->y; + if(box.y2 < (parcs->y + parcs->height)) + box.y2 = parcs->y + parcs->height; + } + + if(extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->PolyArc)(pDraw, pGC, narcsInit, parcsInit); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); + +} + +static void +ShadowFillPolygon( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr pptInit +){ + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && (count > 2)) { + DDXPointPtr ppt = pptInit; + int i = count; + BoxRec box; + Bool boxNotEmpty = FALSE; + + box.x2 = box.x1 = ppt->x; + box.y2 = box.y1 = ppt->y; + + if(mode != CoordModeOrigin) { + int x = box.x1; + int y = box.y1; + while(--i) { + ppt++; + x += ppt->x; + y += ppt->y; + if(box.x1 > x) box.x1 = x; + else if(box.x2 < x) box.x2 = x; + if(box.y1 > y) box.y1 = y; + else if(box.y2 < y) box.y2 = y; + } + } else { + while(--i) { + ppt++; + if(box.x1 > ppt->x) box.x1 = ppt->x; + else if(box.x2 < ppt->x) box.x2 = ppt->x; + if(box.y1 > ppt->y) box.y1 = ppt->y; + else if(box.y2 < ppt->y) box.y2 = ppt->y; + } + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + + (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + } else + (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + + +static void +ShadowPolyFillRect( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit +){ + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nRectsInit) { + BoxRec box; + Bool boxNotEmpty = FALSE; + xRectangle *pRects = pRectsInit; + int nRects = nRectsInit; + + box.x1 = pRects->x; + box.x2 = box.x1 + pRects->width; + box.y1 = pRects->y; + box.y2 = box.y1 + pRects->height; + + while(--nRects) { + pRects++; + if(box.x1 > pRects->x) box.x1 = pRects->x; + if(box.x2 < (pRects->x + pRects->width)) + box.x2 = pRects->x + pRects->width; + if(box.y1 > pRects->y) box.y1 = pRects->y; + if(box.y2 < (pRects->y + pRects->height)) + box.y2 = pRects->y + pRects->height; + } + + /* cfb messes with the pRectsInit so we have to do our + calculations first */ + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + + (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + } else + (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + + +static void +ShadowPolyFillArc( + DrawablePtr pDraw, + GCPtr pGC, + int narcsInit, + xArc *parcsInit +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && narcsInit) { + xArc *parcs = parcsInit; + int narcs = narcsInit; + + box.x1 = parcs->x; + box.x2 = box.x1 + parcs->width; + box.y1 = parcs->y; + box.y2 = box.y1 + parcs->height; + + /* should I break these up instead ? */ + + while(--narcs) { + parcs++; + if(box.x1 > parcs->x) box.x1 = parcs->x; + if(box.x2 < (parcs->x + parcs->width)) + box.x2 = parcs->x + parcs->width; + if(box.y1 > parcs->y) box.y1 = parcs->y; + if(box.y2 < (parcs->y + parcs->height)) + box.y2 = parcs->y + parcs->height; + } + + TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->PolyFillArc)(pDraw, pGC, narcsInit, parcsInit); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + +static void +ShadowTextExtent(FontPtr pFont, int count, char* chars, + FontEncoding fontEncoding, BoxPtr box) +{ + unsigned long n, i; + int w; + CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */ + + GetGlyphs(pFont, (unsigned long)count, (unsigned char *)chars, + fontEncoding, &n, charinfo); + w = 0; + for (i=0; i < n; i++) { + w += charinfo[i]->metrics.characterWidth; + } + if (i) { + w += charinfo[i - 1]->metrics.rightSideBearing; + } + + box->x1 = 0; + if (n) { + if (charinfo[0]->metrics.leftSideBearing < 0) { + box->x1 = charinfo[0]->metrics.leftSideBearing; + } + } + box->x2 = w; + box->y1 = -FONTMAXBOUNDS(pFont,ascent); + box->y2 = FONTMAXBOUNDS(pFont,descent); +} + + + +static void +ShadowFontToBox(BoxPtr BB, DrawablePtr pDrawable, GCPtr pGC, int x, int y, + int count, char *chars, int wide) +{ + FontPtr pFont; + + pFont = pGC->font; + if (pFont->info.constantWidth) { + int ascent, descent, left, right = 0; + + ascent = max(pFont->info.fontAscent, pFont->info.maxbounds.ascent); + descent = max(pFont->info.fontDescent, pFont->info.maxbounds.descent); + left = pFont->info.maxbounds.leftSideBearing; + if (count > 0) { + right = (count - 1) * pFont->info.maxbounds.characterWidth; + } + right += pFont->info.maxbounds.rightSideBearing; + BB->x1 = + max(pDrawable->x + x - left, (REGION_EXTENTS(pGC->pScreen, + &((WindowPtr) pDrawable)->winSize))->x1); + BB->y1 = + max(pDrawable->y + y - ascent, + (REGION_EXTENTS(pGC->pScreen, + &((WindowPtr) pDrawable)->winSize))->y1); + BB->x2 = + min(pDrawable->x + x + right, + (REGION_EXTENTS(pGC->pScreen, + &((WindowPtr) pDrawable)->winSize))->x2); + BB->y2 = + min(pDrawable->y + y + descent, + (REGION_EXTENTS(pGC->pScreen, + &((WindowPtr) pDrawable)->winSize))->y2); + } else { + ShadowTextExtent(pFont, count, chars, wide ? (FONTLASTROW(pFont) == 0) + ? Linear16Bit : TwoD16Bit : Linear8Bit, BB); + BB->x1 = + max(pDrawable->x + x + BB->x1, (REGION_EXTENTS(pGC->pScreen, + &((WindowPtr) pDrawable)->winSize))->x1); + BB->y1 = + max(pDrawable->y + y + BB->y1, + (REGION_EXTENTS(pGC->pScreen, + &((WindowPtr) pDrawable)->winSize))->y1); + BB->x2 = + min(pDrawable->x + x + BB->x2, + (REGION_EXTENTS(pGC->pScreen, + &((WindowPtr) pDrawable)->winSize))->x2); + BB->y2 = + min(pDrawable->y + y + BB->y2, + (REGION_EXTENTS(pGC->pScreen, + &((WindowPtr) pDrawable)->winSize))->y2); + } +} + +static int +ShadowPolyText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +){ + int width; + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw)) { + ShadowFontToBox(&box, pDraw, pGC, x, y, count, chars, 0); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); + + return width; +} + +static int +ShadowPolyText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +){ + int width; + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw)) { + ShadowFontToBox(&box, pDraw, pGC, x, y, count, (char*)chars, 1); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); + + return width; +} + +static void +ShadowImageText8( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && count) { + int top, bot, Min, Max; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + Min = count * FONTMINBOUNDS(pGC->font, characterWidth); + if(Min > 0) Min = 0; + Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); + if(Max < 0) Max = 0; + + /* ugh */ + box.x1 = pDraw->x + x + Min + + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = pDraw->x + x + Max + + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + box.y1 = pDraw->y + y - top; + box.y2 = pDraw->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} +static void +ShadowImageText16( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && count) { + int top, bot, Min, Max; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + Min = count * FONTMINBOUNDS(pGC->font, characterWidth); + if(Min > 0) Min = 0; + Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); + if(Max < 0) Max = 0; + + /* ugh */ + box.x1 = pDraw->x + x + Min + + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = pDraw->x + x + Max + + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + box.y1 = pDraw->y + y - top; + box.y2 = pDraw->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + + +static void +ShadowImageGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + unsigned int nglyphInit, + CharInfoPtr *ppciInit, + pointer pglyphBase +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nglyphInit) { + CharInfoPtr *ppci = ppciInit; + unsigned int nglyph = nglyphInit; + int top, bot, width = 0; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + box.x1 = ppci[0]->metrics.leftSideBearing; + if(box.x1 > 0) box.x1 = 0; + box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - + ppci[nglyph - 1]->metrics.characterWidth; + if(box.x2 < 0) box.x2 = 0; + + box.x2 += pDraw->x + x; + box.x1 += pDraw->x + x; + + while(nglyph--) { + width += (*ppci)->metrics.characterWidth; + ppci++; + } + + if(width > 0) + box.x2 += width; + else + box.x1 += width; + + box.y1 = pDraw->y + y - top; + box.y2 = pDraw->y + y + bot; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyphInit, + ppciInit, pglyphBase); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + +static void +ShadowPolyGlyphBlt( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + unsigned int nglyphInit, + CharInfoPtr *ppciInit, + pointer pglyphBase +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw) && nglyphInit) { + CharInfoPtr *ppci = ppciInit; + unsigned int nglyph = nglyphInit; + + /* ugh */ + box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing; + box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing; + + if(nglyph > 1) { + int width = 0; + + while(--nglyph) { + width += (*ppci)->metrics.characterWidth; + ppci++; + } + + if(width > 0) box.x2 += width; + else box.x1 += width; + } + + box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyphInit, + ppciInit, pglyphBase); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + +static void +ShadowPushPixels( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, int xOrg, int yOrg +){ + BoxRec box; + Bool boxNotEmpty = FALSE; + + SHADOW_GC_OP_PROLOGUE(pGC); + + if(IS_VISIBLE(pDraw)) { + box.x1 = xOrg; + box.y1 = yOrg; + + if(!pGC->miTranslate) { + box.x1 += pDraw->x; + box.y1 += pDraw->y; + } + + box.x2 = box.x1 + dx; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if(BOX_NOT_EMPTY(box)) { + if(pPriv->preRefresh) + (*pPriv->preRefresh)(pPriv->pScrn, 1, &box); + boxNotEmpty = TRUE; + } + } + + (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); + + if(boxNotEmpty && pPriv->postRefresh) + (*pPriv->postRefresh)(pPriv->pScrn, 1, &box); + + SHADOW_GC_OP_EPILOGUE(pGC); +} + + +GCOps ShadowGCOps = { + ShadowFillSpans, ShadowSetSpans, + ShadowPutImage, ShadowCopyArea, + ShadowCopyPlane, ShadowPolyPoint, + ShadowPolylines, ShadowPolySegment, + ShadowPolyRectangle, ShadowPolyArc, + ShadowFillPolygon, ShadowPolyFillRect, + ShadowPolyFillArc, ShadowPolyText8, + ShadowPolyText16, ShadowImageText8, + ShadowImageText16, ShadowImageGlyphBlt, + ShadowPolyGlyphBlt, ShadowPushPixels, + {NULL} /* devPrivate */ +}; + diff --git a/xorg-server/hw/xfree86/vbe/vbe.c b/xorg-server/hw/xfree86/vbe/vbe.c index 26f5911d5..bb88b86cf 100644 --- a/xorg-server/hw/xfree86/vbe/vbe.c +++ b/xorg-server/hw/xfree86/vbe/vbe.c @@ -1,1145 +1,1145 @@ - -/* - * XFree86 vbe module - * Copyright 2000 Egbert Eich - * - * The mode query/save/set/restore functions from the vesa driver - * have been moved here. - * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) - * Authors: Paulo César Pereira de Andrade - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "xf86.h" -#include "vbe.h" -#include -#include - -#define VERSION(x) VBE_VERSION_MAJOR(x),VBE_VERSION_MINOR(x) - -#if X_BYTE_ORDER == X_LITTLE_ENDIAN -#define B_O16(x) (x) -#define B_O32(x) (x) -#else -#define B_O16(x) ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8)) -#define B_O32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \ - | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24)) -#endif -#define L_ADD(x) (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00) - -#define FARP(p) (((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff)) -#define R16(v) ((v) & 0xffff) - -static unsigned char * vbeReadEDID(vbeInfoPtr pVbe); -static Bool vbeProbeDDC(vbeInfoPtr pVbe); - -static const char vbeVersionString[] = "VBE2"; - -vbeInfoPtr -VBEInit(xf86Int10InfoPtr pInt, int entityIndex) -{ - return VBEExtendedInit(pInt, entityIndex, 0); -} - -vbeInfoPtr -VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags) -{ - int RealOff; - pointer page = NULL; - ScrnInfoPtr pScrn = xf86FindScreenForEntity(entityIndex); - vbeControllerInfoPtr vbe = NULL; - Bool init_int10 = FALSE; - vbeInfoPtr vip = NULL; - int screen; - - if (!pScrn) return NULL; - screen = pScrn->scrnIndex; - - if (!pInt) { - if (!xf86LoadSubModule(pScrn, "int10")) - goto error; - - xf86DrvMsg(screen,X_INFO,"initializing int10\n"); - pInt = xf86ExtendedInitInt10(entityIndex,Flags); - if (!pInt) - goto error; - init_int10 = TRUE; - } - - page = xf86Int10AllocPages(pInt,1,&RealOff); - if (!page) goto error; - vbe = (vbeControllerInfoPtr) page; - memcpy(vbe->VbeSignature,vbeVersionString,4); - - pInt->ax = 0x4F00; - pInt->es = SEG_ADDR(RealOff); - pInt->di = SEG_OFF(RealOff); - pInt->num = 0x10; - - xf86ExecX86int10(pInt); - - if ((pInt->ax & 0xff) != 0x4f) { - xf86DrvMsgVerb(screen,X_INFO,3,"VESA BIOS not detected\n"); - goto error; - } - - switch (pInt->ax & 0xff00) { - case 0: - xf86DrvMsg(screen,X_INFO,"VESA BIOS detected\n"); - break; - case 0x100: - xf86DrvMsg(screen,X_INFO,"VESA BIOS function failed\n"); - goto error; - case 0x200: - xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported\n"); - goto error; - case 0x300: - xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported in current mode\n"); - goto error; - default: - xf86DrvMsg(screen,X_INFO,"Invalid\n"); - goto error; - } - - xf86DrvMsgVerb(screen, X_INFO, 4, - "VbeVersion is %d, OemStringPtr is 0x%08lx,\n" - "\tOemVendorNamePtr is 0x%08lx, OemProductNamePtr is 0x%08lx,\n" - "\tOemProductRevPtr is 0x%08lx\n", - vbe->VbeVersion, (unsigned long)vbe->OemStringPtr, - (unsigned long)vbe->OemVendorNamePtr, - (unsigned long)vbe->OemProductNamePtr, - (unsigned long)vbe->OemProductRevPtr); - - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Version %i.%i\n", - VERSION(vbe->VbeVersion)); - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Total Mem: %i kB\n", - vbe->TotalMem * 64); - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM: %s\n", - (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemStringPtr))); - - if (B_O16(vbe->VbeVersion) >= 0x200) { - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Software Rev: %i.%i\n", - VERSION(vbe->OemSoftwareRev)); - if (vbe->OemVendorNamePtr) - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Vendor: %s\n", - (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemVendorNamePtr))); - if (vbe->OemProductNamePtr) - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product: %s\n", - (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductNamePtr))); - if (vbe->OemProductRevPtr) - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product Rev: %s\n", - (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductRevPtr))); - } - vip = (vbeInfoPtr)xnfalloc(sizeof(vbeInfoRec)); - vip->version = B_O16(vbe->VbeVersion); - vip->pInt10 = pInt; - vip->ddc = DDC_UNCHECKED; - vip->memory = page; - vip->real_mode_base = RealOff; - vip->num_pages = 1; - vip->init_int10 = init_int10; - - return vip; - - error: - if (page) - xf86Int10FreePages(pInt, page, 1); - if (init_int10) - xf86FreeInt10(pInt); - return NULL; -} - -void -vbeFree(vbeInfoPtr pVbe) -{ - if (!pVbe) - return; - - xf86Int10FreePages(pVbe->pInt10,pVbe->memory,pVbe->num_pages); - /* If we have initalized int10 we ought to free it, too */ - if (pVbe->init_int10) - xf86FreeInt10(pVbe->pInt10); - xfree(pVbe); - return; -} - -static Bool -vbeProbeDDC(vbeInfoPtr pVbe) -{ - char *ddc_level; - int screen = pVbe->pInt10->scrnIndex; - - if (pVbe->ddc == DDC_NONE) - return FALSE; - if (pVbe->ddc != DDC_UNCHECKED) - return TRUE; - - pVbe->pInt10->ax = 0x4F15; - pVbe->pInt10->bx = 0; - pVbe->pInt10->cx = 0; - pVbe->pInt10->es = 0; - pVbe->pInt10->di = 0; - pVbe->pInt10->num = 0x10; - - xf86ExecX86int10(pVbe->pInt10); - - if ((pVbe->pInt10->ax & 0xff) != 0x4f) { - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC not supported\n"); - pVbe->ddc = DDC_NONE; - return FALSE; - } - - switch ((pVbe->pInt10->ax >> 8) & 0xff) { - case 0: - xf86DrvMsg(screen,X_INFO,"VESA VBE DDC supported\n"); - switch (pVbe->pInt10->bx & 0x3) { - case 0: - ddc_level = " none"; - pVbe->ddc = DDC_NONE; - break; - case 1: - ddc_level = " 1"; - pVbe->ddc = DDC_1; - break; - case 2: - ddc_level = " 2"; - pVbe->ddc = DDC_2; - break; - case 3: - ddc_level = " 1 + 2"; - pVbe->ddc = DDC_1_2; - break; - default: - ddc_level = ""; - pVbe->ddc = DDC_NONE; - break; - } - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Level%s\n",ddc_level); - if (pVbe->pInt10->bx & 0x4) { - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Screen blanked" - "for data transfer\n"); - pVbe->ddc_blank = TRUE; - } else - pVbe->ddc_blank = FALSE; - - xf86DrvMsgVerb(screen,X_INFO,3, - "VESA VBE DDC transfer in appr. %x sec.\n", - (pVbe->pInt10->bx >> 8) & 0xff); - } - - return TRUE; -} - -typedef enum { - VBEOPT_NOVBE, - VBEOPT_NODDC -} VBEOpts; - -static const OptionInfoRec VBEOptions[] = { - { VBEOPT_NOVBE, "NoVBE", OPTV_BOOLEAN, {0}, FALSE }, - { VBEOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE }, -}; - -static unsigned char * -vbeReadEDID(vbeInfoPtr pVbe) -{ - int RealOff = pVbe->real_mode_base; - pointer page = pVbe->memory; - unsigned char *tmp = NULL; - Bool novbe = FALSE; - Bool noddc = FALSE; - int screen = pVbe->pInt10->scrnIndex; - OptionInfoPtr options; - - if (!page) return NULL; - - options = xnfalloc(sizeof(VBEOptions)); - (void)memcpy(options, VBEOptions, sizeof(VBEOptions)); - xf86ProcessOptions(screen, xf86Screens[screen]->options, options); - xf86GetOptValBool(options, VBEOPT_NOVBE, &novbe); - xf86GetOptValBool(options, VBEOPT_NODDC, &noddc); - xfree(options); - if (novbe || noddc) return NULL; - - if (!vbeProbeDDC(pVbe)) goto error; - - memset(page,0,sizeof(vbeInfoPtr)); - strcpy(page,vbeVersionString); - - pVbe->pInt10->ax = 0x4F15; - pVbe->pInt10->bx = 0x01; - pVbe->pInt10->cx = 0; - pVbe->pInt10->dx = 0; - pVbe->pInt10->es = SEG_ADDR(RealOff); - pVbe->pInt10->di = SEG_OFF(RealOff); - pVbe->pInt10->num = 0x10; - - xf86ExecX86int10(pVbe->pInt10); - - if ((pVbe->pInt10->ax & 0xff) != 0x4f) { - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC invalid\n"); - goto error; - } - switch (pVbe->pInt10->ax & 0xff00) { - case 0x0: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read successfully\n"); - tmp = (unsigned char *)xnfalloc(128); - memcpy(tmp,page,128); - break; - case 0x100: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read failed\n"); - break; - default: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC unkown failure %i\n", - pVbe->pInt10->ax & 0xff00); - break; - } - - error: - return tmp; -} - -xf86MonPtr -vbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule) -{ - xf86MonPtr pMonitor; - pointer pModule; - unsigned char *DDC_data = NULL; - - if (!pVbe) return NULL; - if (pVbe->version < 0x200) - return NULL; - - if (!(pModule = pDDCModule)) { - pModule = - xf86LoadSubModule(xf86Screens[pVbe->pInt10->scrnIndex], "ddc"); - if (!pModule) - return NULL; - } - - DDC_data = vbeReadEDID(pVbe); - - if (!DDC_data) - return NULL; - - pMonitor = xf86InterpretEDID(pVbe->pInt10->scrnIndex, DDC_data); - - if (!pDDCModule) - xf86UnloadSubModule(pModule); - return pMonitor; -} - -#define GET_UNALIGNED2(x) \ - ((*(CARD16*)(x)) | (*(((CARD16*)(x) + 1))) << 16) - -VbeInfoBlock * -VBEGetVBEInfo(vbeInfoPtr pVbe) -{ - VbeInfoBlock *block = NULL; - int i, pStr, pModes; - char *str; - CARD16 major, *modes; - - bzero(pVbe->memory, sizeof(VbeInfoBlock)); - - /* - Input: - AH := 4Fh Super VGA support - AL := 00h Return Super VGA information - ES:DI := Pointer to buffer - - Output: - AX := status - (All other registers are preserved) - */ - - ((char*)pVbe->memory)[0] = 'V'; - ((char*)pVbe->memory)[1] = 'B'; - ((char*)pVbe->memory)[2] = 'E'; - ((char*)pVbe->memory)[3] = '2'; - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f00; - pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); - pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (NULL); - - block = xcalloc(sizeof(VbeInfoBlock), 1); - block->VESASignature[0] = ((char*)pVbe->memory)[0]; - block->VESASignature[1] = ((char*)pVbe->memory)[1]; - block->VESASignature[2] = ((char*)pVbe->memory)[2]; - block->VESASignature[3] = ((char*)pVbe->memory)[3]; - - block->VESAVersion = *(CARD16*)(((char*)pVbe->memory) + 4); - major = (unsigned)block->VESAVersion >> 8; - - pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 6)); - str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); - block->OEMStringPtr = strdup(str); - - block->Capabilities[0] = ((char*)pVbe->memory)[10]; - block->Capabilities[1] = ((char*)pVbe->memory)[11]; - block->Capabilities[2] = ((char*)pVbe->memory)[12]; - block->Capabilities[3] = ((char*)pVbe->memory)[13]; - - pModes = GET_UNALIGNED2((((char*)pVbe->memory) + 14)); - modes = xf86int10Addr(pVbe->pInt10, FARP(pModes)); - i = 0; - while (modes[i] != 0xffff) - i++; - block->VideoModePtr = xalloc(sizeof(CARD16) * i + 1); - memcpy(block->VideoModePtr, modes, sizeof(CARD16) * i); - block->VideoModePtr[i] = 0xffff; - - block->TotalMemory = *(CARD16*)(((char*)pVbe->memory) + 18); - - if (major < 2) - memcpy(&block->OemSoftwareRev, ((char*)pVbe->memory) + 20, 236); - else { - block->OemSoftwareRev = *(CARD16*)(((char*)pVbe->memory) + 20); - pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 22)); - str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); - block->OemVendorNamePtr = strdup(str); - pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 26)); - str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); - block->OemProductNamePtr = strdup(str); - pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 30)); - str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); - block->OemProductRevPtr = strdup(str); - memcpy(&block->Reserved, ((char*)pVbe->memory) + 34, 222); - memcpy(&block->OemData, ((char*)pVbe->memory) + 256, 256); - } - - return (block); -} - -void -VBEFreeVBEInfo(VbeInfoBlock *block) -{ - xfree(block->OEMStringPtr); - xfree(block->VideoModePtr); - if (((unsigned)block->VESAVersion >> 8) >= 2) { - xfree(block->OemVendorNamePtr); - xfree(block->OemProductNamePtr); - xfree(block->OemProductRevPtr); - } - xfree(block); -} - -Bool -VBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock *block) -{ - /* - Input: - AH := 4Fh Super VGA support - AL := 02h Set Super VGA video mode - BX := Video mode - D0-D8 := Mode number - D9-D10 := Reserved (must be 0) - D11 := 0 Use current default refresh rate - := 1 Use user specified CRTC values for refresh rate - D12-13 Reserved for VBE/AF (must be 0) - D14 := 0 Use windowed frame buffer model - := 1 Use linear/flat frame buffer model - D15 := 0 Clear video memory - := 1 Don't clear video memory - ES:DI := Pointer to VbeCRTCInfoBlock structure - - Output: AX = Status - (All other registers are preserved) - */ - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f02; - pVbe->pInt10->bx = mode; - if (block) { - pVbe->pInt10->bx |= 1 << 11; - memcpy(pVbe->memory, block, sizeof(VbeCRTCInfoBlock)); - pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); - pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); - } else - pVbe->pInt10->bx &= ~(1 << 11); - - xf86ExecX86int10(pVbe->pInt10); - - return (R16(pVbe->pInt10->ax) == 0x4f); -} - -Bool -VBEGetVBEMode(vbeInfoPtr pVbe, int *mode) -{ - /* - Input: - AH := 4Fh Super VGA support - AL := 03h Return current video mode - - Output: - AX := Status - BX := Current video mode - (All other registers are preserved) - */ - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f03; - - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) == 0x4f) { - *mode = R16(pVbe->pInt10->bx); - - return (TRUE); - } - - return (FALSE); -} - -VbeModeInfoBlock * -VBEGetModeInfo(vbeInfoPtr pVbe, int mode) -{ - VbeModeInfoBlock *block = NULL; - - bzero(pVbe->memory, sizeof(VbeModeInfoBlock)); - - /* - Input: - AH := 4Fh Super VGA support - AL := 01h Return Super VGA mode information - CX := Super VGA video mode - (mode number must be one of those returned by Function 0) - ES:DI := Pointer to buffer - - Output: - AX := status - (All other registers are preserved) - */ - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f01; - pVbe->pInt10->cx = mode; - pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); - pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); - xf86ExecX86int10(pVbe->pInt10); - if (R16(pVbe->pInt10->ax) != 0x4f) - return (NULL); - - block = xcalloc(sizeof(VbeModeInfoBlock), 1); - - block->ModeAttributes = *(CARD16*)pVbe->memory; - block->WinAAttributes = ((char*)pVbe->memory)[2]; - block->WinBAttributes = ((char*)pVbe->memory)[3]; - block->WinGranularity = *(CARD16*)(((char*)pVbe->memory) + 4); - block->WinSize = *(CARD16*)(((char*)pVbe->memory) + 6); - block->WinASegment = *(CARD16*)(((char*)pVbe->memory) + 8); - block->WinBSegment = *(CARD16*)(((char*)pVbe->memory) + 10); - block->WinFuncPtr = *(CARD32*)(((char*)pVbe->memory) + 12); - block->BytesPerScanline = *(CARD16*)(((char*)pVbe->memory) + 16); - - /* mandatory information for VBE 1.2 and above */ - block->XResolution = *(CARD16*)(((char*)pVbe->memory) + 18); - block->YResolution = *(CARD16*)(((char*)pVbe->memory) + 20); - block->XCharSize = ((char*)pVbe->memory)[22]; - block->YCharSize = ((char*)pVbe->memory)[23]; - block->NumberOfPlanes = ((char*)pVbe->memory)[24]; - block->BitsPerPixel = ((char*)pVbe->memory)[25]; - block->NumberOfBanks = ((char*)pVbe->memory)[26]; - block->MemoryModel = ((char*)pVbe->memory)[27]; - block->BankSize = ((char*)pVbe->memory)[28]; - block->NumberOfImages = ((char*)pVbe->memory)[29]; - block->Reserved = ((char*)pVbe->memory)[30]; - - /* Direct color fields (required for direct/6 and YUV/7 memory models) */ - block->RedMaskSize = ((char*)pVbe->memory)[31]; - block->RedFieldPosition = ((char*)pVbe->memory)[32]; - block->GreenMaskSize = ((char*)pVbe->memory)[33]; - block->GreenFieldPosition = ((char*)pVbe->memory)[34]; - block->BlueMaskSize = ((char*)pVbe->memory)[35]; - block->BlueFieldPosition = ((char*)pVbe->memory)[36]; - block->RsvdMaskSize = ((char*)pVbe->memory)[37]; - block->RsvdFieldPosition = ((char*)pVbe->memory)[38]; - block->DirectColorModeInfo = ((char*)pVbe->memory)[39]; - - /* Mandatory information for VBE 2.0 and above */ - if (pVbe->version >= 0x200) { - block->PhysBasePtr = *(CARD32*)(((char*)pVbe->memory) + 40); - block->Reserved32 = *(CARD32*)(((char*)pVbe->memory) + 44); - block->Reserved16 = *(CARD16*)(((char*)pVbe->memory) + 48); - - /* Mandatory information for VBE 3.0 and above */ - if (pVbe->version >= 0x300) { - block->LinBytesPerScanLine = *(CARD16*)(((char*)pVbe->memory) + 50); - block->BnkNumberOfImagePages = ((char*)pVbe->memory)[52]; - block->LinNumberOfImagePages = ((char*)pVbe->memory)[53]; - block->LinRedMaskSize = ((char*)pVbe->memory)[54]; - block->LinRedFieldPosition = ((char*)pVbe->memory)[55]; - block->LinGreenMaskSize = ((char*)pVbe->memory)[56]; - block->LinGreenFieldPosition = ((char*)pVbe->memory)[57]; - block->LinBlueMaskSize = ((char*)pVbe->memory)[58]; - block->LinBlueFieldPosition = ((char*)pVbe->memory)[59]; - block->LinRsvdMaskSize = ((char*)pVbe->memory)[60]; - block->LinRsvdFieldPosition = ((char*)pVbe->memory)[61]; - block->MaxPixelClock = *(CARD32*)(((char*)pVbe->memory) + 62); - memcpy(&block->Reserved2, ((char*)pVbe->memory) + 66, 188); - } - else - memcpy(&block->LinBytesPerScanLine, ((char*)pVbe->memory) + 50, 206); - } - else - memcpy(&block->PhysBasePtr, ((char*)pVbe->memory) + 40, 216); - - return (block); -} - -void -VBEFreeModeInfo(VbeModeInfoBlock *block) -{ - xfree(block); -} - -Bool -VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function, - pointer *memory, int *size, int *real_mode_pages) -{ - /* - Input: - AH := 4Fh Super VGA support - AL := 04h Save/restore Super VGA video state - DL := 00h Return save/restore state buffer size - CX := Requested states - D0 = Save/restore video hardware state - D1 = Save/restore video BIOS data state - D2 = Save/restore video DAC state - D3 = Save/restore Super VGA state - - Output: - AX = Status - BX = Number of 64-byte blocks to hold the state buffer - (All other registers are preserved) - - - Input: - AH := 4Fh Super VGA support - AL := 04h Save/restore Super VGA video state - DL := 01h Save Super VGA video state - CX := Requested states (see above) - ES:BX := Pointer to buffer - - Output: - AX := Status - (All other registers are preserved) - - - Input: - AH := 4Fh Super VGA support - AL := 04h Save/restore Super VGA video state - DL := 02h Restore Super VGA video state - CX := Requested states (see above) - ES:BX := Pointer to buffer - - Output: - AX := Status - (All other registers are preserved) - */ - - if ((pVbe->version & 0xff00) > 0x100) { - int screen = pVbe->pInt10->scrnIndex; - if (function == MODE_QUERY || - (function == MODE_SAVE && !*memory)) { - /* Query amount of memory to save state */ - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f04; - pVbe->pInt10->dx = 0; - pVbe->pInt10->cx = 0x000f; - xf86ExecX86int10(pVbe->pInt10); - if (R16(pVbe->pInt10->ax) != 0x4f) - return (FALSE); - - if (function == MODE_SAVE) { - int npages = (R16(pVbe->pInt10->bx) * 64) / 4096 + 1; - if ((*memory = xf86Int10AllocPages(pVbe->pInt10, npages, - real_mode_pages)) == NULL) { - xf86DrvMsg(screen, X_ERROR, - "Cannot allocate memory to save SVGA state.\n"); - return (FALSE); - } - } - *size = pVbe->pInt10->bx * 64; - } - - /* Save/Restore Super VGA state */ - if (function != MODE_QUERY) { - - if (!*memory) return FALSE; - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f04; - switch (function) { - case MODE_SAVE: - pVbe->pInt10->dx = 1; - break; - case MODE_RESTORE: - pVbe->pInt10->dx = 2; - break; - case MODE_QUERY: - return FALSE; - } - pVbe->pInt10->cx = 0x000f; - - pVbe->pInt10->es = SEG_ADDR(*real_mode_pages); - pVbe->pInt10->bx = SEG_OFF(*real_mode_pages); - xf86ExecX86int10(pVbe->pInt10); - return (R16(pVbe->pInt10->ax) == 0x4f); - - } - } - return TRUE; -} - -Bool -VBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window) -{ - /* - Input: - AH := 4Fh Super VGA support - AL := 05h - - Output: - */ - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f05; - pVbe->pInt10->bx = window; - pVbe->pInt10->dx = iBank; - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (FALSE); - - return (TRUE); -} - -Bool -VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, vbeScanwidthCommand command, - int width, int *pixels, int *bytes, int *max) -{ - if (command < SCANWID_SET || command > SCANWID_GET_MAX) - return (FALSE); - - /* - Input: - AX := 4F06h VBE Set/Get Logical Scan Line Length - BL := 00h Set Scan Line Length in Pixels - := 01h Get Scan Line Length - := 02h Set Scan Line Length in Bytes - := 03h Get Maximum Scan Line Length - CX := If BL=00h Desired Width in Pixels - If BL=02h Desired Width in Bytes - (Ignored for Get Functions) - - Output: - AX := VBE Return Status - BX := Bytes Per Scan Line - CX := Actual Pixels Per Scan Line - (truncated to nearest complete pixel) - DX := Maximum Number of Scan Lines - */ - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f06; - pVbe->pInt10->bx = command; - if (command == SCANWID_SET || command == SCANWID_SET_BYTES) - pVbe->pInt10->cx = width; - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (FALSE); - - if (command == SCANWID_GET || command == SCANWID_GET_MAX) { - if (pixels) - *pixels = R16(pVbe->pInt10->cx); - if (bytes) - *bytes = R16(pVbe->pInt10->bx); - if (max) - *max = R16(pVbe->pInt10->dx); - } - - return (TRUE); -} - -Bool -VBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace) -{ - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f07; - pVbe->pInt10->bx = wait_retrace ? 0x80 : 0x00; - pVbe->pInt10->cx = x; - pVbe->pInt10->dx = y; - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (FALSE); - - return (TRUE); -} - -Bool -VBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y) -{ - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f07; - pVbe->pInt10->bx = 0x01; - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (FALSE); - - *x = pVbe->pInt10->cx; - *y = pVbe->pInt10->dx; - - return (TRUE); -} - -int -VBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits) -{ - /* - Input: - AX := 4F08h VBE Set/Get Palette Format - BL := 00h Set DAC Palette Format - := 01h Get DAC Palette Format - BH := Desired bits of color per primary - (Set DAC Palette Format only) - - Output: - AX := VBE Return Status - BH := Current number of bits of color per primary - */ - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f08; - if (!bits) - pVbe->pInt10->bx = 0x01; - else - pVbe->pInt10->bx = (bits & 0x00ff) << 8; - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (0); - - return (bits != 0 ? bits : (pVbe->pInt10->bx >> 8) & 0x00ff); -} - -CARD32 * -VBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num, - CARD32 *data, Bool secondary, Bool wait_retrace) -{ - /* - Input: - (16-bit) - AX := 4F09h VBE Load/Unload Palette Data - BL := 00h Set Palette Data - := 01h Get Palette Data - := 02h Set Secondary Palette Data - := 03h Get Secondary Palette Data - := 80h Set Palette Data during Vertical Retrace - CX := Number of palette registers to update (to a maximum of 256) - DX := First of the palette registers to update (start) - ES:DI := Table of palette values (see below for format) - - Output: - AX := VBE Return Status - - - Input: - (32-bit) - BL := 00h Set Palette Data - := 80h Set Palette Data during Vertical Retrace - CX := Number of palette registers to update (to a maximum of 256) - DX := First of the palette registers to update (start) - ES:EDI := Table of palette values (see below for format) - DS := Selector for memory mapped registers - */ - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f09; - if (!secondary) - pVbe->pInt10->bx = set && wait_retrace ? 0x80 : set ? 0 : 1; - else - pVbe->pInt10->bx = set ? 2 : 3; - pVbe->pInt10->cx = num; - pVbe->pInt10->dx = first; - pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); - pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); - if (set) - memcpy(pVbe->memory, data, num * sizeof(CARD32)); - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (NULL); - - if (set) - return (data); - - data = xalloc(num * sizeof(CARD32)); - memcpy(data, pVbe->memory, num * sizeof(CARD32)); - - return (data); -} - -VBEpmi * -VBEGetVBEpmi(vbeInfoPtr pVbe) -{ - VBEpmi *pmi; - - /* - Input: - AH := 4Fh Super VGA support - AL := 0Ah Protected Mode Interface - BL := 00h Return Protected Mode Table - - Output: - AX := Status - ES := Real Mode Segment of Table - DI := Offset of Table - CX := Lenght of Table including protected mode code in bytes (for copying purposes) - (All other registers are preserved) - */ - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f0a; - pVbe->pInt10->bx = 0; - pVbe->pInt10->di = 0; - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (NULL); - - pmi = xalloc(sizeof(VBEpmi)); - pmi->seg_tbl = R16(pVbe->pInt10->es); - pmi->tbl_off = R16(pVbe->pInt10->di); - pmi->tbl_len = R16(pVbe->pInt10->cx); - - return (pmi); -} - -#if 0 -vbeModeInfoPtr -VBEBuildVbeModeList(vbeInfoPtr pVbe, VbeInfoBlock *vbe) -{ - vbeModeInfoPtr ModeList = NULL; - - int i = 0; - while (vbe->VideoModePtr[i] != 0xffff) { - vbeModeInfoPtr m; - VbeModeInfoBlock *mode; - int id = vbe->VideoModePtr[i++]; - int bpp; - - if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) - continue; - - bpp = mode->BitsPerPixel; - - m = xnfcalloc(sizeof(vbeModeInfoRec),1); - m->width = mode->XResolution; - m->height = mode->YResolution; - m->bpp = bpp; - m->n = id; - m->next = ModeList; - - xf86DrvMsgVerb(pVbe->pInt10->scrnIndex, X_PROBED, 3, - "BIOS reported VESA mode 0x%x: x:%i y:%i bpp:%i\n", - m->n, m->width, m->height, m->bpp); - - ModeList = m; - - VBEFreeModeInfo(mode); - } - return ModeList; -} - -unsigned short -VBECalcVbeModeIndex(vbeModeInfoPtr m, DisplayModePtr mode, int bpp) -{ - while (m) { - if (bpp == m->bpp - && mode->HDisplay == m->width - && mode->VDisplay == m->height) - return m->n; - m = m->next; - } - return 0; -} -#endif - -void -VBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr, - vbeSaveRestoreFunction function) -{ - Bool SaveSucc = FALSE; - - if (VBE_VERSION_MAJOR(pVbe->version) > 1 - && (function == MODE_SAVE || vbe_sr->pstate)) { - if (function == MODE_RESTORE) - memcpy(vbe_sr->state, vbe_sr->pstate, vbe_sr->stateSize); - ErrorF("VBESaveRestore\n"); - if ((VBESaveRestore(pVbe,function, - (pointer)&vbe_sr->state, - &vbe_sr->stateSize,&vbe_sr->statePage))) { - if (function == MODE_SAVE) { - SaveSucc = TRUE; - vbe_sr->stateMode = -1; /* invalidate */ - /* don't rely on the memory not being touched */ - if (vbe_sr->pstate == NULL) - vbe_sr->pstate = xalloc(vbe_sr->stateSize); - memcpy(vbe_sr->pstate, vbe_sr->state, vbe_sr->stateSize); - } - ErrorF("VBESaveRestore done with success\n"); - return; - } - ErrorF("VBESaveRestore done\n"); - } - - if (function == MODE_SAVE && !SaveSucc) - (void)VBEGetVBEMode(pVbe, &vbe_sr->stateMode); - - if (function == MODE_RESTORE && vbe_sr->stateMode != -1) - VBESetVBEMode(pVbe, vbe_sr->stateMode, NULL); - -} - -int -VBEGetPixelClock(vbeInfoPtr pVbe, int mode, int clock) -{ - /* - Input: - AX := 4F0Bh VBE Get Pixel Clock - BL := 00h Get Pixel Clock - ECX := pixel clock in units of Hz - DX := mode number - - Output: - AX := VBE Return Status - ECX := Closest pixel clock - */ - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f0b; - pVbe->pInt10->bx = 0x00; - pVbe->pInt10->cx = clock; - pVbe->pInt10->dx = mode; - xf86ExecX86int10(pVbe->pInt10); - - if (R16(pVbe->pInt10->ax) != 0x4f) - return (0); - - return (pVbe->pInt10->cx); -} - -Bool -VBEDPMSSet(vbeInfoPtr pVbe, int mode) -{ - /* - Input: - AX := 4F10h DPMS - BL := 01h Set Display Power State - BH := requested power state - - Output: - AX := VBE Return Status - */ - - pVbe->pInt10->num = 0x10; - pVbe->pInt10->ax = 0x4f10; - pVbe->pInt10->bx = 0x01; - switch (mode) { - case DPMSModeOn: - break; - case DPMSModeStandby: - pVbe->pInt10->bx |= 0x100; - break; - case DPMSModeSuspend: - pVbe->pInt10->bx |= 0x200; - break; - case DPMSModeOff: - pVbe->pInt10->bx |= 0x400; - break; - } - xf86ExecX86int10(pVbe->pInt10); - return (R16(pVbe->pInt10->ax) == 0x4f); -} - -void -VBEInterpretPanelID(int scrnIndex, struct vbePanelID *data) -{ - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - DisplayModePtr mode; - const float PANEL_HZ = 60.0; - - if (!data) - return; - - xf86DrvMsg(scrnIndex, X_INFO, "PanelID returned panel resolution %dx%d\n", - data->hsize, data->vsize); - - if (pScrn->monitor->nHsync || pScrn->monitor->nVrefresh) - return; - - mode = xf86CVTMode(data->hsize, data->vsize, PANEL_HZ, 1, 0); - - pScrn->monitor->nHsync = 1; - pScrn->monitor->hsync[0].lo = 31.5; - pScrn->monitor->hsync[0].hi = (float)mode->Clock / (float)mode->HTotal; - pScrn->monitor->nVrefresh = 1; - pScrn->monitor->vrefresh[0].lo = 56.0; - pScrn->monitor->vrefresh[0].hi = - (float)mode->Clock*1000.0 / (float)mode->HTotal / (float)mode->VTotal; - - xfree(mode); -} - -struct vbePanelID * -VBEReadPanelID(vbeInfoPtr pVbe) -{ - int RealOff = pVbe->real_mode_base; - pointer page = pVbe->memory; - void *tmp = NULL; - int screen = pVbe->pInt10->scrnIndex; - - pVbe->pInt10->ax = 0x4F11; - pVbe->pInt10->bx = 0x01; - pVbe->pInt10->cx = 0; - pVbe->pInt10->dx = 0; - pVbe->pInt10->es = SEG_ADDR(RealOff); - pVbe->pInt10->di = SEG_OFF(RealOff); - pVbe->pInt10->num = 0x10; - - xf86ExecX86int10(pVbe->pInt10); - - if ((pVbe->pInt10->ax & 0xff) != 0x4f) { - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n"); - goto error; - } - - switch (pVbe->pInt10->ax & 0xff00) { - case 0x0: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n"); - tmp = xnfalloc(32); - memcpy(tmp, page, 32); - break; - case 0x100: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n"); - break; - default: - xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n", - pVbe->pInt10->ax & 0xff00); - break; - } - -error: - return tmp; -} + +/* + * XFree86 vbe module + * Copyright 2000 Egbert Eich + * + * The mode query/save/set/restore functions from the vesa driver + * have been moved here. + * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) + * Authors: Paulo César Pereira de Andrade + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "xf86.h" +#include "vbe.h" +#include +#include + +#define VERSION(x) VBE_VERSION_MAJOR(x),VBE_VERSION_MINOR(x) + +#if X_BYTE_ORDER == X_LITTLE_ENDIAN +#define B_O16(x) (x) +#define B_O32(x) (x) +#else +#define B_O16(x) ((((x) & 0xff) << 8) | (((x) & 0xff) >> 8)) +#define B_O32(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) \ + | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000) >> 24)) +#endif +#define L_ADD(x) (B_O32(x) & 0xffff) + ((B_O32(x) >> 12) & 0xffff00) + +#define FARP(p) (((unsigned)(p & 0xffff0000) >> 12) | (p & 0xffff)) +#define R16(v) ((v) & 0xffff) + +static unsigned char * vbeReadEDID(vbeInfoPtr pVbe); +static Bool vbeProbeDDC(vbeInfoPtr pVbe); + +static const char vbeVersionString[] = "VBE2"; + +vbeInfoPtr +VBEInit(xf86Int10InfoPtr pInt, int entityIndex) +{ + return VBEExtendedInit(pInt, entityIndex, 0); +} + +vbeInfoPtr +VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags) +{ + int RealOff; + pointer page = NULL; + ScrnInfoPtr pScrn = xf86FindScreenForEntity(entityIndex); + vbeControllerInfoPtr vbe = NULL; + Bool init_int10 = FALSE; + vbeInfoPtr vip = NULL; + int screen; + + if (!pScrn) return NULL; + screen = pScrn->scrnIndex; + + if (!pInt) { + if (!xf86LoadSubModule(pScrn, "int10")) + goto error; + + xf86DrvMsg(screen,X_INFO,"initializing int10\n"); + pInt = xf86ExtendedInitInt10(entityIndex,Flags); + if (!pInt) + goto error; + init_int10 = TRUE; + } + + page = xf86Int10AllocPages(pInt,1,&RealOff); + if (!page) goto error; + vbe = (vbeControllerInfoPtr) page; + memcpy(vbe->VbeSignature,vbeVersionString,4); + + pInt->ax = 0x4F00; + pInt->es = SEG_ADDR(RealOff); + pInt->di = SEG_OFF(RealOff); + pInt->num = 0x10; + + xf86ExecX86int10(pInt); + + if ((pInt->ax & 0xff) != 0x4f) { + xf86DrvMsgVerb(screen,X_INFO,3,"VESA BIOS not detected\n"); + goto error; + } + + switch (pInt->ax & 0xff00) { + case 0: + xf86DrvMsg(screen,X_INFO,"VESA BIOS detected\n"); + break; + case 0x100: + xf86DrvMsg(screen,X_INFO,"VESA BIOS function failed\n"); + goto error; + case 0x200: + xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported\n"); + goto error; + case 0x300: + xf86DrvMsg(screen,X_INFO,"VESA BIOS not supported in current mode\n"); + goto error; + default: + xf86DrvMsg(screen,X_INFO,"Invalid\n"); + goto error; + } + + xf86DrvMsgVerb(screen, X_INFO, 4, + "VbeVersion is %d, OemStringPtr is 0x%08lx,\n" + "\tOemVendorNamePtr is 0x%08lx, OemProductNamePtr is 0x%08lx,\n" + "\tOemProductRevPtr is 0x%08lx\n", + vbe->VbeVersion, (unsigned long)vbe->OemStringPtr, + (unsigned long)vbe->OemVendorNamePtr, + (unsigned long)vbe->OemProductNamePtr, + (unsigned long)vbe->OemProductRevPtr); + + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Version %i.%i\n", + VERSION(vbe->VbeVersion)); + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE Total Mem: %i kB\n", + vbe->TotalMem * 64); + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM: %s\n", + (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemStringPtr))); + + if (B_O16(vbe->VbeVersion) >= 0x200) { + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Software Rev: %i.%i\n", + VERSION(vbe->OemSoftwareRev)); + if (vbe->OemVendorNamePtr) + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Vendor: %s\n", + (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemVendorNamePtr))); + if (vbe->OemProductNamePtr) + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product: %s\n", + (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductNamePtr))); + if (vbe->OemProductRevPtr) + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE OEM Product Rev: %s\n", + (CARD8*)xf86int10Addr(pInt,L_ADD(vbe->OemProductRevPtr))); + } + vip = (vbeInfoPtr)xnfalloc(sizeof(vbeInfoRec)); + vip->version = B_O16(vbe->VbeVersion); + vip->pInt10 = pInt; + vip->ddc = DDC_UNCHECKED; + vip->memory = page; + vip->real_mode_base = RealOff; + vip->num_pages = 1; + vip->init_int10 = init_int10; + + return vip; + + error: + if (page) + xf86Int10FreePages(pInt, page, 1); + if (init_int10) + xf86FreeInt10(pInt); + return NULL; +} + +void +vbeFree(vbeInfoPtr pVbe) +{ + if (!pVbe) + return; + + xf86Int10FreePages(pVbe->pInt10,pVbe->memory,pVbe->num_pages); + /* If we have initalized int10 we ought to free it, too */ + if (pVbe->init_int10) + xf86FreeInt10(pVbe->pInt10); + free(pVbe); + return; +} + +static Bool +vbeProbeDDC(vbeInfoPtr pVbe) +{ + char *ddc_level; + int screen = pVbe->pInt10->scrnIndex; + + if (pVbe->ddc == DDC_NONE) + return FALSE; + if (pVbe->ddc != DDC_UNCHECKED) + return TRUE; + + pVbe->pInt10->ax = 0x4F15; + pVbe->pInt10->bx = 0; + pVbe->pInt10->cx = 0; + pVbe->pInt10->es = 0; + pVbe->pInt10->di = 0; + pVbe->pInt10->num = 0x10; + + xf86ExecX86int10(pVbe->pInt10); + + if ((pVbe->pInt10->ax & 0xff) != 0x4f) { + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC not supported\n"); + pVbe->ddc = DDC_NONE; + return FALSE; + } + + switch ((pVbe->pInt10->ax >> 8) & 0xff) { + case 0: + xf86DrvMsg(screen,X_INFO,"VESA VBE DDC supported\n"); + switch (pVbe->pInt10->bx & 0x3) { + case 0: + ddc_level = " none"; + pVbe->ddc = DDC_NONE; + break; + case 1: + ddc_level = " 1"; + pVbe->ddc = DDC_1; + break; + case 2: + ddc_level = " 2"; + pVbe->ddc = DDC_2; + break; + case 3: + ddc_level = " 1 + 2"; + pVbe->ddc = DDC_1_2; + break; + default: + ddc_level = ""; + pVbe->ddc = DDC_NONE; + break; + } + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Level%s\n",ddc_level); + if (pVbe->pInt10->bx & 0x4) { + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC Screen blanked" + "for data transfer\n"); + pVbe->ddc_blank = TRUE; + } else + pVbe->ddc_blank = FALSE; + + xf86DrvMsgVerb(screen,X_INFO,3, + "VESA VBE DDC transfer in appr. %x sec.\n", + (pVbe->pInt10->bx >> 8) & 0xff); + } + + return TRUE; +} + +typedef enum { + VBEOPT_NOVBE, + VBEOPT_NODDC +} VBEOpts; + +static const OptionInfoRec VBEOptions[] = { + { VBEOPT_NOVBE, "NoVBE", OPTV_BOOLEAN, {0}, FALSE }, + { VBEOPT_NODDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE }, +}; + +static unsigned char * +vbeReadEDID(vbeInfoPtr pVbe) +{ + int RealOff = pVbe->real_mode_base; + pointer page = pVbe->memory; + unsigned char *tmp = NULL; + Bool novbe = FALSE; + Bool noddc = FALSE; + int screen = pVbe->pInt10->scrnIndex; + OptionInfoPtr options; + + if (!page) return NULL; + + options = xnfalloc(sizeof(VBEOptions)); + (void)memcpy(options, VBEOptions, sizeof(VBEOptions)); + xf86ProcessOptions(screen, xf86Screens[screen]->options, options); + xf86GetOptValBool(options, VBEOPT_NOVBE, &novbe); + xf86GetOptValBool(options, VBEOPT_NODDC, &noddc); + free(options); + if (novbe || noddc) return NULL; + + if (!vbeProbeDDC(pVbe)) goto error; + + memset(page,0,sizeof(vbeInfoPtr)); + strcpy(page,vbeVersionString); + + pVbe->pInt10->ax = 0x4F15; + pVbe->pInt10->bx = 0x01; + pVbe->pInt10->cx = 0; + pVbe->pInt10->dx = 0; + pVbe->pInt10->es = SEG_ADDR(RealOff); + pVbe->pInt10->di = SEG_OFF(RealOff); + pVbe->pInt10->num = 0x10; + + xf86ExecX86int10(pVbe->pInt10); + + if ((pVbe->pInt10->ax & 0xff) != 0x4f) { + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC invalid\n"); + goto error; + } + switch (pVbe->pInt10->ax & 0xff00) { + case 0x0: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read successfully\n"); + tmp = (unsigned char *)xnfalloc(128); + memcpy(tmp,page,128); + break; + case 0x100: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC read failed\n"); + break; + default: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE DDC unkown failure %i\n", + pVbe->pInt10->ax & 0xff00); + break; + } + + error: + return tmp; +} + +xf86MonPtr +vbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule) +{ + xf86MonPtr pMonitor; + pointer pModule; + unsigned char *DDC_data = NULL; + + if (!pVbe) return NULL; + if (pVbe->version < 0x200) + return NULL; + + if (!(pModule = pDDCModule)) { + pModule = + xf86LoadSubModule(xf86Screens[pVbe->pInt10->scrnIndex], "ddc"); + if (!pModule) + return NULL; + } + + DDC_data = vbeReadEDID(pVbe); + + if (!DDC_data) + return NULL; + + pMonitor = xf86InterpretEDID(pVbe->pInt10->scrnIndex, DDC_data); + + if (!pDDCModule) + xf86UnloadSubModule(pModule); + return pMonitor; +} + +#define GET_UNALIGNED2(x) \ + ((*(CARD16*)(x)) | (*(((CARD16*)(x) + 1))) << 16) + +VbeInfoBlock * +VBEGetVBEInfo(vbeInfoPtr pVbe) +{ + VbeInfoBlock *block = NULL; + int i, pStr, pModes; + char *str; + CARD16 major, *modes; + + bzero(pVbe->memory, sizeof(VbeInfoBlock)); + + /* + Input: + AH := 4Fh Super VGA support + AL := 00h Return Super VGA information + ES:DI := Pointer to buffer + + Output: + AX := status + (All other registers are preserved) + */ + + ((char*)pVbe->memory)[0] = 'V'; + ((char*)pVbe->memory)[1] = 'B'; + ((char*)pVbe->memory)[2] = 'E'; + ((char*)pVbe->memory)[3] = '2'; + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f00; + pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); + pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (NULL); + + block = calloc(sizeof(VbeInfoBlock), 1); + block->VESASignature[0] = ((char*)pVbe->memory)[0]; + block->VESASignature[1] = ((char*)pVbe->memory)[1]; + block->VESASignature[2] = ((char*)pVbe->memory)[2]; + block->VESASignature[3] = ((char*)pVbe->memory)[3]; + + block->VESAVersion = *(CARD16*)(((char*)pVbe->memory) + 4); + major = (unsigned)block->VESAVersion >> 8; + + pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 6)); + str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); + block->OEMStringPtr = strdup(str); + + block->Capabilities[0] = ((char*)pVbe->memory)[10]; + block->Capabilities[1] = ((char*)pVbe->memory)[11]; + block->Capabilities[2] = ((char*)pVbe->memory)[12]; + block->Capabilities[3] = ((char*)pVbe->memory)[13]; + + pModes = GET_UNALIGNED2((((char*)pVbe->memory) + 14)); + modes = xf86int10Addr(pVbe->pInt10, FARP(pModes)); + i = 0; + while (modes[i] != 0xffff) + i++; + block->VideoModePtr = malloc(sizeof(CARD16) * i + 1); + memcpy(block->VideoModePtr, modes, sizeof(CARD16) * i); + block->VideoModePtr[i] = 0xffff; + + block->TotalMemory = *(CARD16*)(((char*)pVbe->memory) + 18); + + if (major < 2) + memcpy(&block->OemSoftwareRev, ((char*)pVbe->memory) + 20, 236); + else { + block->OemSoftwareRev = *(CARD16*)(((char*)pVbe->memory) + 20); + pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 22)); + str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); + block->OemVendorNamePtr = strdup(str); + pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 26)); + str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); + block->OemProductNamePtr = strdup(str); + pStr = GET_UNALIGNED2((((char*)pVbe->memory) + 30)); + str = xf86int10Addr(pVbe->pInt10, FARP(pStr)); + block->OemProductRevPtr = strdup(str); + memcpy(&block->Reserved, ((char*)pVbe->memory) + 34, 222); + memcpy(&block->OemData, ((char*)pVbe->memory) + 256, 256); + } + + return (block); +} + +void +VBEFreeVBEInfo(VbeInfoBlock *block) +{ + free(block->OEMStringPtr); + free(block->VideoModePtr); + if (((unsigned)block->VESAVersion >> 8) >= 2) { + free(block->OemVendorNamePtr); + free(block->OemProductNamePtr); + free(block->OemProductRevPtr); + } + free(block); +} + +Bool +VBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock *block) +{ + /* + Input: + AH := 4Fh Super VGA support + AL := 02h Set Super VGA video mode + BX := Video mode + D0-D8 := Mode number + D9-D10 := Reserved (must be 0) + D11 := 0 Use current default refresh rate + := 1 Use user specified CRTC values for refresh rate + D12-13 Reserved for VBE/AF (must be 0) + D14 := 0 Use windowed frame buffer model + := 1 Use linear/flat frame buffer model + D15 := 0 Clear video memory + := 1 Don't clear video memory + ES:DI := Pointer to VbeCRTCInfoBlock structure + + Output: AX = Status + (All other registers are preserved) + */ + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f02; + pVbe->pInt10->bx = mode; + if (block) { + pVbe->pInt10->bx |= 1 << 11; + memcpy(pVbe->memory, block, sizeof(VbeCRTCInfoBlock)); + pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); + pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); + } else + pVbe->pInt10->bx &= ~(1 << 11); + + xf86ExecX86int10(pVbe->pInt10); + + return (R16(pVbe->pInt10->ax) == 0x4f); +} + +Bool +VBEGetVBEMode(vbeInfoPtr pVbe, int *mode) +{ + /* + Input: + AH := 4Fh Super VGA support + AL := 03h Return current video mode + + Output: + AX := Status + BX := Current video mode + (All other registers are preserved) + */ + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f03; + + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) == 0x4f) { + *mode = R16(pVbe->pInt10->bx); + + return (TRUE); + } + + return (FALSE); +} + +VbeModeInfoBlock * +VBEGetModeInfo(vbeInfoPtr pVbe, int mode) +{ + VbeModeInfoBlock *block = NULL; + + bzero(pVbe->memory, sizeof(VbeModeInfoBlock)); + + /* + Input: + AH := 4Fh Super VGA support + AL := 01h Return Super VGA mode information + CX := Super VGA video mode + (mode number must be one of those returned by Function 0) + ES:DI := Pointer to buffer + + Output: + AX := status + (All other registers are preserved) + */ + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f01; + pVbe->pInt10->cx = mode; + pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); + pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); + xf86ExecX86int10(pVbe->pInt10); + if (R16(pVbe->pInt10->ax) != 0x4f) + return (NULL); + + block = calloc(sizeof(VbeModeInfoBlock), 1); + + block->ModeAttributes = *(CARD16*)pVbe->memory; + block->WinAAttributes = ((char*)pVbe->memory)[2]; + block->WinBAttributes = ((char*)pVbe->memory)[3]; + block->WinGranularity = *(CARD16*)(((char*)pVbe->memory) + 4); + block->WinSize = *(CARD16*)(((char*)pVbe->memory) + 6); + block->WinASegment = *(CARD16*)(((char*)pVbe->memory) + 8); + block->WinBSegment = *(CARD16*)(((char*)pVbe->memory) + 10); + block->WinFuncPtr = *(CARD32*)(((char*)pVbe->memory) + 12); + block->BytesPerScanline = *(CARD16*)(((char*)pVbe->memory) + 16); + + /* mandatory information for VBE 1.2 and above */ + block->XResolution = *(CARD16*)(((char*)pVbe->memory) + 18); + block->YResolution = *(CARD16*)(((char*)pVbe->memory) + 20); + block->XCharSize = ((char*)pVbe->memory)[22]; + block->YCharSize = ((char*)pVbe->memory)[23]; + block->NumberOfPlanes = ((char*)pVbe->memory)[24]; + block->BitsPerPixel = ((char*)pVbe->memory)[25]; + block->NumberOfBanks = ((char*)pVbe->memory)[26]; + block->MemoryModel = ((char*)pVbe->memory)[27]; + block->BankSize = ((char*)pVbe->memory)[28]; + block->NumberOfImages = ((char*)pVbe->memory)[29]; + block->Reserved = ((char*)pVbe->memory)[30]; + + /* Direct color fields (required for direct/6 and YUV/7 memory models) */ + block->RedMaskSize = ((char*)pVbe->memory)[31]; + block->RedFieldPosition = ((char*)pVbe->memory)[32]; + block->GreenMaskSize = ((char*)pVbe->memory)[33]; + block->GreenFieldPosition = ((char*)pVbe->memory)[34]; + block->BlueMaskSize = ((char*)pVbe->memory)[35]; + block->BlueFieldPosition = ((char*)pVbe->memory)[36]; + block->RsvdMaskSize = ((char*)pVbe->memory)[37]; + block->RsvdFieldPosition = ((char*)pVbe->memory)[38]; + block->DirectColorModeInfo = ((char*)pVbe->memory)[39]; + + /* Mandatory information for VBE 2.0 and above */ + if (pVbe->version >= 0x200) { + block->PhysBasePtr = *(CARD32*)(((char*)pVbe->memory) + 40); + block->Reserved32 = *(CARD32*)(((char*)pVbe->memory) + 44); + block->Reserved16 = *(CARD16*)(((char*)pVbe->memory) + 48); + + /* Mandatory information for VBE 3.0 and above */ + if (pVbe->version >= 0x300) { + block->LinBytesPerScanLine = *(CARD16*)(((char*)pVbe->memory) + 50); + block->BnkNumberOfImagePages = ((char*)pVbe->memory)[52]; + block->LinNumberOfImagePages = ((char*)pVbe->memory)[53]; + block->LinRedMaskSize = ((char*)pVbe->memory)[54]; + block->LinRedFieldPosition = ((char*)pVbe->memory)[55]; + block->LinGreenMaskSize = ((char*)pVbe->memory)[56]; + block->LinGreenFieldPosition = ((char*)pVbe->memory)[57]; + block->LinBlueMaskSize = ((char*)pVbe->memory)[58]; + block->LinBlueFieldPosition = ((char*)pVbe->memory)[59]; + block->LinRsvdMaskSize = ((char*)pVbe->memory)[60]; + block->LinRsvdFieldPosition = ((char*)pVbe->memory)[61]; + block->MaxPixelClock = *(CARD32*)(((char*)pVbe->memory) + 62); + memcpy(&block->Reserved2, ((char*)pVbe->memory) + 66, 188); + } + else + memcpy(&block->LinBytesPerScanLine, ((char*)pVbe->memory) + 50, 206); + } + else + memcpy(&block->PhysBasePtr, ((char*)pVbe->memory) + 40, 216); + + return (block); +} + +void +VBEFreeModeInfo(VbeModeInfoBlock *block) +{ + free(block); +} + +Bool +VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction function, + pointer *memory, int *size, int *real_mode_pages) +{ + /* + Input: + AH := 4Fh Super VGA support + AL := 04h Save/restore Super VGA video state + DL := 00h Return save/restore state buffer size + CX := Requested states + D0 = Save/restore video hardware state + D1 = Save/restore video BIOS data state + D2 = Save/restore video DAC state + D3 = Save/restore Super VGA state + + Output: + AX = Status + BX = Number of 64-byte blocks to hold the state buffer + (All other registers are preserved) + + + Input: + AH := 4Fh Super VGA support + AL := 04h Save/restore Super VGA video state + DL := 01h Save Super VGA video state + CX := Requested states (see above) + ES:BX := Pointer to buffer + + Output: + AX := Status + (All other registers are preserved) + + + Input: + AH := 4Fh Super VGA support + AL := 04h Save/restore Super VGA video state + DL := 02h Restore Super VGA video state + CX := Requested states (see above) + ES:BX := Pointer to buffer + + Output: + AX := Status + (All other registers are preserved) + */ + + if ((pVbe->version & 0xff00) > 0x100) { + int screen = pVbe->pInt10->scrnIndex; + if (function == MODE_QUERY || + (function == MODE_SAVE && !*memory)) { + /* Query amount of memory to save state */ + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f04; + pVbe->pInt10->dx = 0; + pVbe->pInt10->cx = 0x000f; + xf86ExecX86int10(pVbe->pInt10); + if (R16(pVbe->pInt10->ax) != 0x4f) + return (FALSE); + + if (function == MODE_SAVE) { + int npages = (R16(pVbe->pInt10->bx) * 64) / 4096 + 1; + if ((*memory = xf86Int10AllocPages(pVbe->pInt10, npages, + real_mode_pages)) == NULL) { + xf86DrvMsg(screen, X_ERROR, + "Cannot allocate memory to save SVGA state.\n"); + return (FALSE); + } + } + *size = pVbe->pInt10->bx * 64; + } + + /* Save/Restore Super VGA state */ + if (function != MODE_QUERY) { + + if (!*memory) return FALSE; + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f04; + switch (function) { + case MODE_SAVE: + pVbe->pInt10->dx = 1; + break; + case MODE_RESTORE: + pVbe->pInt10->dx = 2; + break; + case MODE_QUERY: + return FALSE; + } + pVbe->pInt10->cx = 0x000f; + + pVbe->pInt10->es = SEG_ADDR(*real_mode_pages); + pVbe->pInt10->bx = SEG_OFF(*real_mode_pages); + xf86ExecX86int10(pVbe->pInt10); + return (R16(pVbe->pInt10->ax) == 0x4f); + + } + } + return TRUE; +} + +Bool +VBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window) +{ + /* + Input: + AH := 4Fh Super VGA support + AL := 05h + + Output: + */ + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f05; + pVbe->pInt10->bx = window; + pVbe->pInt10->dx = iBank; + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (FALSE); + + return (TRUE); +} + +Bool +VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, vbeScanwidthCommand command, + int width, int *pixels, int *bytes, int *max) +{ + if (command < SCANWID_SET || command > SCANWID_GET_MAX) + return (FALSE); + + /* + Input: + AX := 4F06h VBE Set/Get Logical Scan Line Length + BL := 00h Set Scan Line Length in Pixels + := 01h Get Scan Line Length + := 02h Set Scan Line Length in Bytes + := 03h Get Maximum Scan Line Length + CX := If BL=00h Desired Width in Pixels + If BL=02h Desired Width in Bytes + (Ignored for Get Functions) + + Output: + AX := VBE Return Status + BX := Bytes Per Scan Line + CX := Actual Pixels Per Scan Line + (truncated to nearest complete pixel) + DX := Maximum Number of Scan Lines + */ + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f06; + pVbe->pInt10->bx = command; + if (command == SCANWID_SET || command == SCANWID_SET_BYTES) + pVbe->pInt10->cx = width; + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (FALSE); + + if (command == SCANWID_GET || command == SCANWID_GET_MAX) { + if (pixels) + *pixels = R16(pVbe->pInt10->cx); + if (bytes) + *bytes = R16(pVbe->pInt10->bx); + if (max) + *max = R16(pVbe->pInt10->dx); + } + + return (TRUE); +} + +Bool +VBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace) +{ + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f07; + pVbe->pInt10->bx = wait_retrace ? 0x80 : 0x00; + pVbe->pInt10->cx = x; + pVbe->pInt10->dx = y; + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (FALSE); + + return (TRUE); +} + +Bool +VBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y) +{ + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f07; + pVbe->pInt10->bx = 0x01; + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (FALSE); + + *x = pVbe->pInt10->cx; + *y = pVbe->pInt10->dx; + + return (TRUE); +} + +int +VBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits) +{ + /* + Input: + AX := 4F08h VBE Set/Get Palette Format + BL := 00h Set DAC Palette Format + := 01h Get DAC Palette Format + BH := Desired bits of color per primary + (Set DAC Palette Format only) + + Output: + AX := VBE Return Status + BH := Current number of bits of color per primary + */ + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f08; + if (!bits) + pVbe->pInt10->bx = 0x01; + else + pVbe->pInt10->bx = (bits & 0x00ff) << 8; + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (0); + + return (bits != 0 ? bits : (pVbe->pInt10->bx >> 8) & 0x00ff); +} + +CARD32 * +VBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num, + CARD32 *data, Bool secondary, Bool wait_retrace) +{ + /* + Input: + (16-bit) + AX := 4F09h VBE Load/Unload Palette Data + BL := 00h Set Palette Data + := 01h Get Palette Data + := 02h Set Secondary Palette Data + := 03h Get Secondary Palette Data + := 80h Set Palette Data during Vertical Retrace + CX := Number of palette registers to update (to a maximum of 256) + DX := First of the palette registers to update (start) + ES:DI := Table of palette values (see below for format) + + Output: + AX := VBE Return Status + + + Input: + (32-bit) + BL := 00h Set Palette Data + := 80h Set Palette Data during Vertical Retrace + CX := Number of palette registers to update (to a maximum of 256) + DX := First of the palette registers to update (start) + ES:EDI := Table of palette values (see below for format) + DS := Selector for memory mapped registers + */ + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f09; + if (!secondary) + pVbe->pInt10->bx = set && wait_retrace ? 0x80 : set ? 0 : 1; + else + pVbe->pInt10->bx = set ? 2 : 3; + pVbe->pInt10->cx = num; + pVbe->pInt10->dx = first; + pVbe->pInt10->es = SEG_ADDR(pVbe->real_mode_base); + pVbe->pInt10->di = SEG_OFF(pVbe->real_mode_base); + if (set) + memcpy(pVbe->memory, data, num * sizeof(CARD32)); + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (NULL); + + if (set) + return (data); + + data = malloc(num * sizeof(CARD32)); + memcpy(data, pVbe->memory, num * sizeof(CARD32)); + + return (data); +} + +VBEpmi * +VBEGetVBEpmi(vbeInfoPtr pVbe) +{ + VBEpmi *pmi; + + /* + Input: + AH := 4Fh Super VGA support + AL := 0Ah Protected Mode Interface + BL := 00h Return Protected Mode Table + + Output: + AX := Status + ES := Real Mode Segment of Table + DI := Offset of Table + CX := Lenght of Table including protected mode code in bytes (for copying purposes) + (All other registers are preserved) + */ + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f0a; + pVbe->pInt10->bx = 0; + pVbe->pInt10->di = 0; + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (NULL); + + pmi = malloc(sizeof(VBEpmi)); + pmi->seg_tbl = R16(pVbe->pInt10->es); + pmi->tbl_off = R16(pVbe->pInt10->di); + pmi->tbl_len = R16(pVbe->pInt10->cx); + + return (pmi); +} + +#if 0 +vbeModeInfoPtr +VBEBuildVbeModeList(vbeInfoPtr pVbe, VbeInfoBlock *vbe) +{ + vbeModeInfoPtr ModeList = NULL; + + int i = 0; + while (vbe->VideoModePtr[i] != 0xffff) { + vbeModeInfoPtr m; + VbeModeInfoBlock *mode; + int id = vbe->VideoModePtr[i++]; + int bpp; + + if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) + continue; + + bpp = mode->BitsPerPixel; + + m = xnfcalloc(sizeof(vbeModeInfoRec),1); + m->width = mode->XResolution; + m->height = mode->YResolution; + m->bpp = bpp; + m->n = id; + m->next = ModeList; + + xf86DrvMsgVerb(pVbe->pInt10->scrnIndex, X_PROBED, 3, + "BIOS reported VESA mode 0x%x: x:%i y:%i bpp:%i\n", + m->n, m->width, m->height, m->bpp); + + ModeList = m; + + VBEFreeModeInfo(mode); + } + return ModeList; +} + +unsigned short +VBECalcVbeModeIndex(vbeModeInfoPtr m, DisplayModePtr mode, int bpp) +{ + while (m) { + if (bpp == m->bpp + && mode->HDisplay == m->width + && mode->VDisplay == m->height) + return m->n; + m = m->next; + } + return 0; +} +#endif + +void +VBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr, + vbeSaveRestoreFunction function) +{ + Bool SaveSucc = FALSE; + + if (VBE_VERSION_MAJOR(pVbe->version) > 1 + && (function == MODE_SAVE || vbe_sr->pstate)) { + if (function == MODE_RESTORE) + memcpy(vbe_sr->state, vbe_sr->pstate, vbe_sr->stateSize); + ErrorF("VBESaveRestore\n"); + if ((VBESaveRestore(pVbe,function, + (pointer)&vbe_sr->state, + &vbe_sr->stateSize,&vbe_sr->statePage))) { + if (function == MODE_SAVE) { + SaveSucc = TRUE; + vbe_sr->stateMode = -1; /* invalidate */ + /* don't rely on the memory not being touched */ + if (vbe_sr->pstate == NULL) + vbe_sr->pstate = malloc(vbe_sr->stateSize); + memcpy(vbe_sr->pstate, vbe_sr->state, vbe_sr->stateSize); + } + ErrorF("VBESaveRestore done with success\n"); + return; + } + ErrorF("VBESaveRestore done\n"); + } + + if (function == MODE_SAVE && !SaveSucc) + (void)VBEGetVBEMode(pVbe, &vbe_sr->stateMode); + + if (function == MODE_RESTORE && vbe_sr->stateMode != -1) + VBESetVBEMode(pVbe, vbe_sr->stateMode, NULL); + +} + +int +VBEGetPixelClock(vbeInfoPtr pVbe, int mode, int clock) +{ + /* + Input: + AX := 4F0Bh VBE Get Pixel Clock + BL := 00h Get Pixel Clock + ECX := pixel clock in units of Hz + DX := mode number + + Output: + AX := VBE Return Status + ECX := Closest pixel clock + */ + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f0b; + pVbe->pInt10->bx = 0x00; + pVbe->pInt10->cx = clock; + pVbe->pInt10->dx = mode; + xf86ExecX86int10(pVbe->pInt10); + + if (R16(pVbe->pInt10->ax) != 0x4f) + return (0); + + return (pVbe->pInt10->cx); +} + +Bool +VBEDPMSSet(vbeInfoPtr pVbe, int mode) +{ + /* + Input: + AX := 4F10h DPMS + BL := 01h Set Display Power State + BH := requested power state + + Output: + AX := VBE Return Status + */ + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f10; + pVbe->pInt10->bx = 0x01; + switch (mode) { + case DPMSModeOn: + break; + case DPMSModeStandby: + pVbe->pInt10->bx |= 0x100; + break; + case DPMSModeSuspend: + pVbe->pInt10->bx |= 0x200; + break; + case DPMSModeOff: + pVbe->pInt10->bx |= 0x400; + break; + } + xf86ExecX86int10(pVbe->pInt10); + return (R16(pVbe->pInt10->ax) == 0x4f); +} + +void +VBEInterpretPanelID(int scrnIndex, struct vbePanelID *data) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + DisplayModePtr mode; + const float PANEL_HZ = 60.0; + + if (!data) + return; + + xf86DrvMsg(scrnIndex, X_INFO, "PanelID returned panel resolution %dx%d\n", + data->hsize, data->vsize); + + if (pScrn->monitor->nHsync || pScrn->monitor->nVrefresh) + return; + + mode = xf86CVTMode(data->hsize, data->vsize, PANEL_HZ, 1, 0); + + pScrn->monitor->nHsync = 1; + pScrn->monitor->hsync[0].lo = 31.5; + pScrn->monitor->hsync[0].hi = (float)mode->Clock / (float)mode->HTotal; + pScrn->monitor->nVrefresh = 1; + pScrn->monitor->vrefresh[0].lo = 56.0; + pScrn->monitor->vrefresh[0].hi = + (float)mode->Clock*1000.0 / (float)mode->HTotal / (float)mode->VTotal; + + free(mode); +} + +struct vbePanelID * +VBEReadPanelID(vbeInfoPtr pVbe) +{ + int RealOff = pVbe->real_mode_base; + pointer page = pVbe->memory; + void *tmp = NULL; + int screen = pVbe->pInt10->scrnIndex; + + pVbe->pInt10->ax = 0x4F11; + pVbe->pInt10->bx = 0x01; + pVbe->pInt10->cx = 0; + pVbe->pInt10->dx = 0; + pVbe->pInt10->es = SEG_ADDR(RealOff); + pVbe->pInt10->di = SEG_OFF(RealOff); + pVbe->pInt10->num = 0x10; + + xf86ExecX86int10(pVbe->pInt10); + + if ((pVbe->pInt10->ax & 0xff) != 0x4f) { + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n"); + goto error; + } + + switch (pVbe->pInt10->ax & 0xff00) { + case 0x0: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n"); + tmp = xnfalloc(32); + memcpy(tmp, page, 32); + break; + case 0x100: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n"); + break; + default: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n", + pVbe->pInt10->ax & 0xff00); + break; + } + +error: + return tmp; +} diff --git a/xorg-server/hw/xfree86/vbe/vbe.h b/xorg-server/hw/xfree86/vbe/vbe.h index b1ec5a9fb..4786709ea 100644 --- a/xorg-server/hw/xfree86/vbe/vbe.h +++ b/xorg-server/hw/xfree86/vbe/vbe.h @@ -1,341 +1,341 @@ - -/* - * XFree86 vbe module - * Copyright 2000 Egbert Eich - * - * The mode query/save/set/restore functions from the vesa driver - * have been moved here. - * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) - * Authors: Paulo César Pereira de Andrade - */ - -#ifndef _VBE_H -#define _VBE_H -#include "xf86int10.h" -#include "xf86DDC.h" - -typedef enum { - DDC_UNCHECKED, - DDC_NONE, - DDC_1, - DDC_2, - DDC_1_2 -} -ddc_lvl; - -typedef struct { - xf86Int10InfoPtr pInt10; - int version; - pointer memory; - int real_mode_base; - int num_pages; - Bool init_int10; - ddc_lvl ddc; - Bool ddc_blank; -} vbeInfoRec, *vbeInfoPtr; - -#define VBE_VERSION_MAJOR(x) *((CARD8*)(&x) + 1) -#define VBE_VERSION_MINOR(x) (CARD8)(x) - -extern _X_EXPORT vbeInfoPtr VBEInit(xf86Int10InfoPtr pInt, int entityIndex); -extern _X_EXPORT vbeInfoPtr VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags); -extern _X_EXPORT void vbeFree(vbeInfoPtr pVbe); -extern _X_EXPORT xf86MonPtr vbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule); - -#pragma pack(1) - -typedef struct vbeControllerInfoBlock { - CARD8 VbeSignature[4]; - CARD16 VbeVersion; - CARD32 OemStringPtr; - CARD8 Capabilities[4]; - CARD32 VideoModePtr; - CARD16 TotalMem; - CARD16 OemSoftwareRev; - CARD32 OemVendorNamePtr; - CARD32 OemProductNamePtr; - CARD32 OemProductRevPtr; - CARD8 Scratch[222]; - CARD8 OemData[256]; -} vbeControllerInfoRec, *vbeControllerInfoPtr; - -#if defined(__GNUC__) || defined(__USLC__) || defined(__SUNPRO_C) -#pragma pack() /* All GCC versions recognise this syntax */ -#else -#pragma pack(0) -#endif - -#ifndef __GNUC__ -#define __attribute__(a) -#endif - -typedef struct _VbeInfoBlock VbeInfoBlock; -typedef struct _VbeModeInfoBlock VbeModeInfoBlock; -typedef struct _VbeCRTCInfoBlock VbeCRTCInfoBlock; - -/* - * INT 0 - */ - -struct _VbeInfoBlock { - /* VESA 1.2 fields */ - CARD8 VESASignature[4]; /* VESA */ - CARD16 VESAVersion; /* Higher byte major, lower byte minor */ - /*CARD32*/char *OEMStringPtr; /* Pointer to OEM string */ - CARD8 Capabilities[4]; /* Capabilities of the video environment */ - - /*CARD32*/CARD16 *VideoModePtr; /* pointer to supported Super VGA modes */ - - CARD16 TotalMemory; /* Number of 64kb memory blocks on board */ - /* if not VESA 2, 236 scratch bytes follow (256 bytes total size) */ - - /* VESA 2 fields */ - CARD16 OemSoftwareRev; /* VBE implementation Software revision */ - /*CARD32*/char *OemVendorNamePtr; /* Pointer to Vendor Name String */ - /*CARD32*/char *OemProductNamePtr; /* Pointer to Product Name String */ - /*CARD32*/char *OemProductRevPtr; /* Pointer to Product Revision String */ - CARD8 Reserved[222]; /* Reserved for VBE implementation */ - CARD8 OemData[256]; /* Data Area for OEM Strings */ -} __attribute__((packed)); - -/* Return Super VGA Information */ -extern _X_EXPORT VbeInfoBlock *VBEGetVBEInfo(vbeInfoPtr pVbe); -extern _X_EXPORT void VBEFreeVBEInfo(VbeInfoBlock *block); - -/* - * INT 1 - */ - -struct _VbeModeInfoBlock { - CARD16 ModeAttributes; /* mode attributes */ - CARD8 WinAAttributes; /* window A attributes */ - CARD8 WinBAttributes; /* window B attributes */ - CARD16 WinGranularity; /* window granularity */ - CARD16 WinSize; /* window size */ - CARD16 WinASegment; /* window A start segment */ - CARD16 WinBSegment; /* window B start segment */ - CARD32 WinFuncPtr; /* real mode pointer to window function */ - CARD16 BytesPerScanline; /* bytes per scanline */ - - /* Mandatory information for VBE 1.2 and above */ - CARD16 XResolution; /* horizontal resolution in pixels or characters */ - CARD16 YResolution; /* vertical resolution in pixels or characters */ - CARD8 XCharSize; /* character cell width in pixels */ - CARD8 YCharSize; /* character cell height in pixels */ - CARD8 NumberOfPlanes; /* number of memory planes */ - CARD8 BitsPerPixel; /* bits per pixel */ - CARD8 NumberOfBanks; /* number of banks */ - CARD8 MemoryModel; /* memory model type */ - CARD8 BankSize; /* bank size in KB */ - CARD8 NumberOfImages; /* number of images */ - CARD8 Reserved; /* 1 */ /* reserved for page function */ - - /* Direct color fields (required for direct/6 and YUV/7 memory models) */ - CARD8 RedMaskSize; /* size of direct color red mask in bits */ - CARD8 RedFieldPosition; /* bit position of lsb of red mask */ - CARD8 GreenMaskSize; /* size of direct color green mask in bits */ - CARD8 GreenFieldPosition; /* bit position of lsb of green mask */ - CARD8 BlueMaskSize; /* size of direct color blue mask in bits */ - CARD8 BlueFieldPosition; /* bit position of lsb of blue mask */ - CARD8 RsvdMaskSize; /* size of direct color reserved mask in bits */ - CARD8 RsvdFieldPosition; /* bit position of lsb of reserved mask */ - CARD8 DirectColorModeInfo; /* direct color mode attributes */ - - /* Mandatory information for VBE 2.0 and above */ - CARD32 PhysBasePtr; /* physical address for flat memory frame buffer */ - CARD32 Reserved32; /* 0 */ /* Reserved - always set to 0 */ - CARD16 Reserved16; /* 0 */ /* Reserved - always set to 0 */ - - /* Mandatory information for VBE 3.0 and above */ - CARD16 LinBytesPerScanLine; /* bytes per scan line for linear modes */ - CARD8 BnkNumberOfImagePages; /* number of images for banked modes */ - CARD8 LinNumberOfImagePages; /* number of images for linear modes */ - CARD8 LinRedMaskSize; /* size of direct color red mask (linear modes) */ - CARD8 LinRedFieldPosition; /* bit position of lsb of red mask (linear modes) */ - CARD8 LinGreenMaskSize; /* size of direct color green mask (linear modes) */ - CARD8 LinGreenFieldPosition; /* bit position of lsb of green mask (linear modes) */ - CARD8 LinBlueMaskSize; /* size of direct color blue mask (linear modes) */ - CARD8 LinBlueFieldPosition; /* bit position of lsb of blue mask (linear modes) */ - CARD8 LinRsvdMaskSize; /* size of direct color reserved mask (linear modes) */ - CARD8 LinRsvdFieldPosition; /* bit position of lsb of reserved mask (linear modes) */ - CARD32 MaxPixelClock; /* maximum pixel clock (in Hz) for graphics mode */ - CARD8 Reserved2[189]; /* remainder of VbeModeInfoBlock */ -} __attribute__((packed)); - -/* Return VBE Mode Information */ -extern _X_EXPORT VbeModeInfoBlock *VBEGetModeInfo(vbeInfoPtr pVbe, int mode); -extern _X_EXPORT void VBEFreeModeInfo(VbeModeInfoBlock *block); - -/* - * INT2 - */ - -#define CRTC_DBLSCAN (1<<0) -#define CRTC_INTERLACE (1<<1) -#define CRTC_NHSYNC (1<<2) -#define CRTC_NVSYNC (1<<3) - -struct _VbeCRTCInfoBlock { - CARD16 HorizontalTotal; /* Horizontal total in pixels */ - CARD16 HorizontalSyncStart; /* Horizontal sync start in pixels */ - CARD16 HorizontalSyncEnd; /* Horizontal sync end in pixels */ - CARD16 VerticalTotal; /* Vertical total in lines */ - CARD16 VerticalSyncStart; /* Vertical sync start in lines */ - CARD16 VerticalSyncEnd; /* Vertical sync end in lines */ - CARD8 Flags; /* Flags (Interlaced, Double Scan etc) */ - CARD32 PixelClock; /* Pixel clock in units of Hz */ - CARD16 RefreshRate; /* Refresh rate in units of 0.01 Hz */ - CARD8 Reserved[40]; /* remainder of ModeInfoBlock */ -} __attribute__((packed)); -/* VbeCRTCInfoBlock is in the VESA 3.0 specs */ - -extern _X_EXPORT Bool VBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock *crtc); - -/* - * INT 3 - */ - -extern _X_EXPORT Bool VBEGetVBEMode(vbeInfoPtr pVbe, int *mode); - -/* - * INT 4 - */ - -/* Save/Restore Super VGA video state */ -/* function values are (values stored in VESAPtr): - * 0 := query & allocate amount of memory to save state - * 1 := save state - * 2 := restore state - * - * function 0 called automatically if function 1 called without - * a previous call to function 0. - */ - -typedef enum { - MODE_QUERY, - MODE_SAVE, - MODE_RESTORE -} vbeSaveRestoreFunction; - -extern _X_EXPORT Bool -VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction fuction, - pointer *memory, int *size, int *real_mode_pages); - -/* - * INT 5 - */ - -extern _X_EXPORT Bool -VBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window); - -/* - * INT 6 - */ - -typedef enum { - SCANWID_SET, - SCANWID_GET, - SCANWID_SET_BYTES, - SCANWID_GET_MAX -} vbeScanwidthCommand; - -#define VBESetLogicalScanline(pVbe, width) \ - VBESetGetLogicalScanlineLength(pVbe, SCANWID_SET, width, \ - NULL, NULL, NULL) -#define VBESetLogicalScanlineBytes(pVbe, width) \ - VBESetGetLogicalScanlineLength(pVbe, SCANWID_SET_BYTES, width, \ - NULL, NULL, NULL) -#define VBEGetLogicalScanline(pVbe, pixels, bytes, max) \ - VBESetGetLogicalScanlineLength(pVbe, SCANWID_GET, 0, \ - pixels, bytes, max) -#define VBEGetMaxLogicalScanline(pVbe, pixels, bytes, max) \ - VBESetGetLogicalScanlineLength(pVbe, SCANWID_GET_MAX, 0, \ - pixels, bytes, max) -extern _X_EXPORT Bool VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, - vbeScanwidthCommand command, int width, - int *pixels, int *bytes, int *max); - -/* - * INT 7 - */ - -/* 16 bit code */ -extern _X_EXPORT Bool VBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace); -extern _X_EXPORT Bool VBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y); - -/* - * INT 8 - */ - -/* if bits is 0, then it is a GET */ -extern _X_EXPORT int VBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits); - -/* - * INT 9 - */ - -/* - * If getting a palette, the data argument is not used. It will return - * the data. - * If setting a palette, it will return the pointer received on success, - * NULL on failure. - */ -extern _X_EXPORT CARD32 *VBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num, - CARD32 *data, Bool secondary, Bool wait_retrace); -#define VBEFreePaletteData(data) xfree(data) - -/* - * INT A - */ - -typedef struct _VBEpmi { - int seg_tbl; - int tbl_off; - int tbl_len; -} VBEpmi; - -extern _X_EXPORT VBEpmi *VBEGetVBEpmi(vbeInfoPtr pVbe); -#define VESAFreeVBEpmi(pmi) xfree(pmi) - -/* high level helper functions */ - -typedef struct _vbeModeInfoRec { - int width; - int height; - int bpp; - int n; - struct _vbeModeInfoRec *next; -} vbeModeInfoRec, *vbeModeInfoPtr; - -typedef struct { - CARD8 *state; - CARD8 *pstate; - int statePage; - int stateSize; - int stateMode; -} vbeSaveRestoreRec, *vbeSaveRestorePtr; - -extern _X_EXPORT void -VBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr, - vbeSaveRestoreFunction function); - -extern _X_EXPORT int VBEGetPixelClock(vbeInfoPtr pVbe, int mode, int Clock); -extern _X_EXPORT Bool VBEDPMSSet(vbeInfoPtr pVbe, int mode); - -struct vbePanelID { - short hsize; - short vsize; - short fptype; - char redbpp; - char greenbpp; - char bluebpp; - char reservedbpp; - int reserved_offscreen_mem_size; - int reserved_offscreen_mem_pointer; - char reserved[14]; -}; - -extern _X_EXPORT void VBEInterpretPanelID(int scrnIndex, struct vbePanelID *data); -extern _X_EXPORT struct vbePanelID *VBEReadPanelID(vbeInfoPtr pVbe); - -#endif + +/* + * XFree86 vbe module + * Copyright 2000 Egbert Eich + * + * The mode query/save/set/restore functions from the vesa driver + * have been moved here. + * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com) + * Authors: Paulo César Pereira de Andrade + */ + +#ifndef _VBE_H +#define _VBE_H +#include "xf86int10.h" +#include "xf86DDC.h" + +typedef enum { + DDC_UNCHECKED, + DDC_NONE, + DDC_1, + DDC_2, + DDC_1_2 +} +ddc_lvl; + +typedef struct { + xf86Int10InfoPtr pInt10; + int version; + pointer memory; + int real_mode_base; + int num_pages; + Bool init_int10; + ddc_lvl ddc; + Bool ddc_blank; +} vbeInfoRec, *vbeInfoPtr; + +#define VBE_VERSION_MAJOR(x) *((CARD8*)(&x) + 1) +#define VBE_VERSION_MINOR(x) (CARD8)(x) + +extern _X_EXPORT vbeInfoPtr VBEInit(xf86Int10InfoPtr pInt, int entityIndex); +extern _X_EXPORT vbeInfoPtr VBEExtendedInit(xf86Int10InfoPtr pInt, int entityIndex, int Flags); +extern _X_EXPORT void vbeFree(vbeInfoPtr pVbe); +extern _X_EXPORT xf86MonPtr vbeDoEDID(vbeInfoPtr pVbe, pointer pDDCModule); + +#pragma pack(1) + +typedef struct vbeControllerInfoBlock { + CARD8 VbeSignature[4]; + CARD16 VbeVersion; + CARD32 OemStringPtr; + CARD8 Capabilities[4]; + CARD32 VideoModePtr; + CARD16 TotalMem; + CARD16 OemSoftwareRev; + CARD32 OemVendorNamePtr; + CARD32 OemProductNamePtr; + CARD32 OemProductRevPtr; + CARD8 Scratch[222]; + CARD8 OemData[256]; +} vbeControllerInfoRec, *vbeControllerInfoPtr; + +#if defined(__GNUC__) || defined(__USLC__) || defined(__SUNPRO_C) +#pragma pack() /* All GCC versions recognise this syntax */ +#else +#pragma pack(0) +#endif + +#ifndef __GNUC__ +#define __attribute__(a) +#endif + +typedef struct _VbeInfoBlock VbeInfoBlock; +typedef struct _VbeModeInfoBlock VbeModeInfoBlock; +typedef struct _VbeCRTCInfoBlock VbeCRTCInfoBlock; + +/* + * INT 0 + */ + +struct _VbeInfoBlock { + /* VESA 1.2 fields */ + CARD8 VESASignature[4]; /* VESA */ + CARD16 VESAVersion; /* Higher byte major, lower byte minor */ + /*CARD32*/char *OEMStringPtr; /* Pointer to OEM string */ + CARD8 Capabilities[4]; /* Capabilities of the video environment */ + + /*CARD32*/CARD16 *VideoModePtr; /* pointer to supported Super VGA modes */ + + CARD16 TotalMemory; /* Number of 64kb memory blocks on board */ + /* if not VESA 2, 236 scratch bytes follow (256 bytes total size) */ + + /* VESA 2 fields */ + CARD16 OemSoftwareRev; /* VBE implementation Software revision */ + /*CARD32*/char *OemVendorNamePtr; /* Pointer to Vendor Name String */ + /*CARD32*/char *OemProductNamePtr; /* Pointer to Product Name String */ + /*CARD32*/char *OemProductRevPtr; /* Pointer to Product Revision String */ + CARD8 Reserved[222]; /* Reserved for VBE implementation */ + CARD8 OemData[256]; /* Data Area for OEM Strings */ +} __attribute__((packed)); + +/* Return Super VGA Information */ +extern _X_EXPORT VbeInfoBlock *VBEGetVBEInfo(vbeInfoPtr pVbe); +extern _X_EXPORT void VBEFreeVBEInfo(VbeInfoBlock *block); + +/* + * INT 1 + */ + +struct _VbeModeInfoBlock { + CARD16 ModeAttributes; /* mode attributes */ + CARD8 WinAAttributes; /* window A attributes */ + CARD8 WinBAttributes; /* window B attributes */ + CARD16 WinGranularity; /* window granularity */ + CARD16 WinSize; /* window size */ + CARD16 WinASegment; /* window A start segment */ + CARD16 WinBSegment; /* window B start segment */ + CARD32 WinFuncPtr; /* real mode pointer to window function */ + CARD16 BytesPerScanline; /* bytes per scanline */ + + /* Mandatory information for VBE 1.2 and above */ + CARD16 XResolution; /* horizontal resolution in pixels or characters */ + CARD16 YResolution; /* vertical resolution in pixels or characters */ + CARD8 XCharSize; /* character cell width in pixels */ + CARD8 YCharSize; /* character cell height in pixels */ + CARD8 NumberOfPlanes; /* number of memory planes */ + CARD8 BitsPerPixel; /* bits per pixel */ + CARD8 NumberOfBanks; /* number of banks */ + CARD8 MemoryModel; /* memory model type */ + CARD8 BankSize; /* bank size in KB */ + CARD8 NumberOfImages; /* number of images */ + CARD8 Reserved; /* 1 */ /* reserved for page function */ + + /* Direct color fields (required for direct/6 and YUV/7 memory models) */ + CARD8 RedMaskSize; /* size of direct color red mask in bits */ + CARD8 RedFieldPosition; /* bit position of lsb of red mask */ + CARD8 GreenMaskSize; /* size of direct color green mask in bits */ + CARD8 GreenFieldPosition; /* bit position of lsb of green mask */ + CARD8 BlueMaskSize; /* size of direct color blue mask in bits */ + CARD8 BlueFieldPosition; /* bit position of lsb of blue mask */ + CARD8 RsvdMaskSize; /* size of direct color reserved mask in bits */ + CARD8 RsvdFieldPosition; /* bit position of lsb of reserved mask */ + CARD8 DirectColorModeInfo; /* direct color mode attributes */ + + /* Mandatory information for VBE 2.0 and above */ + CARD32 PhysBasePtr; /* physical address for flat memory frame buffer */ + CARD32 Reserved32; /* 0 */ /* Reserved - always set to 0 */ + CARD16 Reserved16; /* 0 */ /* Reserved - always set to 0 */ + + /* Mandatory information for VBE 3.0 and above */ + CARD16 LinBytesPerScanLine; /* bytes per scan line for linear modes */ + CARD8 BnkNumberOfImagePages; /* number of images for banked modes */ + CARD8 LinNumberOfImagePages; /* number of images for linear modes */ + CARD8 LinRedMaskSize; /* size of direct color red mask (linear modes) */ + CARD8 LinRedFieldPosition; /* bit position of lsb of red mask (linear modes) */ + CARD8 LinGreenMaskSize; /* size of direct color green mask (linear modes) */ + CARD8 LinGreenFieldPosition; /* bit position of lsb of green mask (linear modes) */ + CARD8 LinBlueMaskSize; /* size of direct color blue mask (linear modes) */ + CARD8 LinBlueFieldPosition; /* bit position of lsb of blue mask (linear modes) */ + CARD8 LinRsvdMaskSize; /* size of direct color reserved mask (linear modes) */ + CARD8 LinRsvdFieldPosition; /* bit position of lsb of reserved mask (linear modes) */ + CARD32 MaxPixelClock; /* maximum pixel clock (in Hz) for graphics mode */ + CARD8 Reserved2[189]; /* remainder of VbeModeInfoBlock */ +} __attribute__((packed)); + +/* Return VBE Mode Information */ +extern _X_EXPORT VbeModeInfoBlock *VBEGetModeInfo(vbeInfoPtr pVbe, int mode); +extern _X_EXPORT void VBEFreeModeInfo(VbeModeInfoBlock *block); + +/* + * INT2 + */ + +#define CRTC_DBLSCAN (1<<0) +#define CRTC_INTERLACE (1<<1) +#define CRTC_NHSYNC (1<<2) +#define CRTC_NVSYNC (1<<3) + +struct _VbeCRTCInfoBlock { + CARD16 HorizontalTotal; /* Horizontal total in pixels */ + CARD16 HorizontalSyncStart; /* Horizontal sync start in pixels */ + CARD16 HorizontalSyncEnd; /* Horizontal sync end in pixels */ + CARD16 VerticalTotal; /* Vertical total in lines */ + CARD16 VerticalSyncStart; /* Vertical sync start in lines */ + CARD16 VerticalSyncEnd; /* Vertical sync end in lines */ + CARD8 Flags; /* Flags (Interlaced, Double Scan etc) */ + CARD32 PixelClock; /* Pixel clock in units of Hz */ + CARD16 RefreshRate; /* Refresh rate in units of 0.01 Hz */ + CARD8 Reserved[40]; /* remainder of ModeInfoBlock */ +} __attribute__((packed)); +/* VbeCRTCInfoBlock is in the VESA 3.0 specs */ + +extern _X_EXPORT Bool VBESetVBEMode(vbeInfoPtr pVbe, int mode, VbeCRTCInfoBlock *crtc); + +/* + * INT 3 + */ + +extern _X_EXPORT Bool VBEGetVBEMode(vbeInfoPtr pVbe, int *mode); + +/* + * INT 4 + */ + +/* Save/Restore Super VGA video state */ +/* function values are (values stored in VESAPtr): + * 0 := query & allocate amount of memory to save state + * 1 := save state + * 2 := restore state + * + * function 0 called automatically if function 1 called without + * a previous call to function 0. + */ + +typedef enum { + MODE_QUERY, + MODE_SAVE, + MODE_RESTORE +} vbeSaveRestoreFunction; + +extern _X_EXPORT Bool +VBESaveRestore(vbeInfoPtr pVbe, vbeSaveRestoreFunction fuction, + pointer *memory, int *size, int *real_mode_pages); + +/* + * INT 5 + */ + +extern _X_EXPORT Bool +VBEBankSwitch(vbeInfoPtr pVbe, unsigned int iBank, int window); + +/* + * INT 6 + */ + +typedef enum { + SCANWID_SET, + SCANWID_GET, + SCANWID_SET_BYTES, + SCANWID_GET_MAX +} vbeScanwidthCommand; + +#define VBESetLogicalScanline(pVbe, width) \ + VBESetGetLogicalScanlineLength(pVbe, SCANWID_SET, width, \ + NULL, NULL, NULL) +#define VBESetLogicalScanlineBytes(pVbe, width) \ + VBESetGetLogicalScanlineLength(pVbe, SCANWID_SET_BYTES, width, \ + NULL, NULL, NULL) +#define VBEGetLogicalScanline(pVbe, pixels, bytes, max) \ + VBESetGetLogicalScanlineLength(pVbe, SCANWID_GET, 0, \ + pixels, bytes, max) +#define VBEGetMaxLogicalScanline(pVbe, pixels, bytes, max) \ + VBESetGetLogicalScanlineLength(pVbe, SCANWID_GET_MAX, 0, \ + pixels, bytes, max) +extern _X_EXPORT Bool VBESetGetLogicalScanlineLength(vbeInfoPtr pVbe, + vbeScanwidthCommand command, int width, + int *pixels, int *bytes, int *max); + +/* + * INT 7 + */ + +/* 16 bit code */ +extern _X_EXPORT Bool VBESetDisplayStart(vbeInfoPtr pVbe, int x, int y, Bool wait_retrace); +extern _X_EXPORT Bool VBEGetDisplayStart(vbeInfoPtr pVbe, int *x, int *y); + +/* + * INT 8 + */ + +/* if bits is 0, then it is a GET */ +extern _X_EXPORT int VBESetGetDACPaletteFormat(vbeInfoPtr pVbe, int bits); + +/* + * INT 9 + */ + +/* + * If getting a palette, the data argument is not used. It will return + * the data. + * If setting a palette, it will return the pointer received on success, + * NULL on failure. + */ +extern _X_EXPORT CARD32 *VBESetGetPaletteData(vbeInfoPtr pVbe, Bool set, int first, int num, + CARD32 *data, Bool secondary, Bool wait_retrace); +#define VBEFreePaletteData(data) free(data) + +/* + * INT A + */ + +typedef struct _VBEpmi { + int seg_tbl; + int tbl_off; + int tbl_len; +} VBEpmi; + +extern _X_EXPORT VBEpmi *VBEGetVBEpmi(vbeInfoPtr pVbe); +#define VESAFreeVBEpmi(pmi) free(pmi) + +/* high level helper functions */ + +typedef struct _vbeModeInfoRec { + int width; + int height; + int bpp; + int n; + struct _vbeModeInfoRec *next; +} vbeModeInfoRec, *vbeModeInfoPtr; + +typedef struct { + CARD8 *state; + CARD8 *pstate; + int statePage; + int stateSize; + int stateMode; +} vbeSaveRestoreRec, *vbeSaveRestorePtr; + +extern _X_EXPORT void +VBEVesaSaveRestore(vbeInfoPtr pVbe, vbeSaveRestorePtr vbe_sr, + vbeSaveRestoreFunction function); + +extern _X_EXPORT int VBEGetPixelClock(vbeInfoPtr pVbe, int mode, int Clock); +extern _X_EXPORT Bool VBEDPMSSet(vbeInfoPtr pVbe, int mode); + +struct vbePanelID { + short hsize; + short vsize; + short fptype; + char redbpp; + char greenbpp; + char bluebpp; + char reservedbpp; + int reserved_offscreen_mem_size; + int reserved_offscreen_mem_pointer; + char reserved[14]; +}; + +extern _X_EXPORT void VBEInterpretPanelID(int scrnIndex, struct vbePanelID *data); +extern _X_EXPORT struct vbePanelID *VBEReadPanelID(vbeInfoPtr pVbe); + +#endif diff --git a/xorg-server/hw/xfree86/vbe/vbeModes.c b/xorg-server/hw/xfree86/vbe/vbeModes.c index 1a4d2407c..5b69b0096 100644 --- a/xorg-server/hw/xfree86/vbe/vbeModes.c +++ b/xorg-server/hw/xfree86/vbe/vbeModes.c @@ -1,451 +1,451 @@ -#define DEBUG_VERB 2 -/* - * Copyright © 2002 David Dawes - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Except as contained in this notice, the name of the author(s) 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 author(s). - * - * Authors: David Dawes - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include - -#include "xf86.h" -#include "vbe.h" -#include "vbeModes.h" - -static int -GetDepthFlag(vbeInfoPtr pVbe, int id) -{ - VbeModeInfoBlock *mode; - int bpp; - - if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) - return 0; - - if (VBE_MODE_USABLE(mode, 0)) { - int depth; - - if (VBE_MODE_COLOR(mode)) { - depth = mode->RedMaskSize + mode->GreenMaskSize + - mode->BlueMaskSize; - } else { - depth = 1; - } - bpp = mode->BitsPerPixel; - VBEFreeModeInfo(mode); - mode = NULL; - switch (depth) { - case 1: - return V_DEPTH_1; - case 4: - return V_DEPTH_4; - case 8: - return V_DEPTH_8; - case 15: - return V_DEPTH_15; - case 16: - return V_DEPTH_16; - case 24: - switch (bpp) { - case 24: - return V_DEPTH_24_24; - case 32: - return V_DEPTH_24_32; - } - } - } - if (mode) - VBEFreeModeInfo(mode); - return 0; -} - -/* - * Find supported mode depths. - */ -int -VBEFindSupportedDepths(vbeInfoPtr pVbe, VbeInfoBlock *vbe, int *flags24, - int modeTypes) -{ - int i = 0; - int depths = 0; - - if (modeTypes & V_MODETYPE_VBE) { - while (vbe->VideoModePtr[i] != 0xffff) { - depths |= GetDepthFlag(pVbe, vbe->VideoModePtr[i++]); - } - } - - /* - * XXX This possibly only works with VBE 3.0 and later. - */ - if (modeTypes & V_MODETYPE_VGA) { - for (i = 0; i < 0x7F; i++) { - depths |= GetDepthFlag(pVbe, i); - } - } - - if (flags24) { - if (depths & V_DEPTH_24_24) - *flags24 |= Support24bppFb; - if (depths & V_DEPTH_24_32) - *flags24 |= Support32bppFb; - } - - return depths; -} - -static DisplayModePtr -CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id, - int flags) -{ - CARD16 major; - VbeModeInfoBlock *mode; - DisplayModePtr pMode; - VbeModeInfoData *data; - Bool modeOK = FALSE; - - major = (unsigned)(vbe->VESAVersion >> 8); - - if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) - return NULL; - - /* Does the mode match the depth/bpp? */ - /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */ - if (VBE_MODE_USABLE(mode, flags) && - ((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) || - (mode->BitsPerPixel > 8 && - (mode->RedMaskSize + mode->GreenMaskSize + - mode->BlueMaskSize) == pScrn->depth && - mode->BitsPerPixel == pScrn->bitsPerPixel) || - (mode->BitsPerPixel == 15 && pScrn->depth == 15) || - (mode->BitsPerPixel <= 8 && - mode->BitsPerPixel == pScrn->bitsPerPixel))) { - modeOK = TRUE; - xf86ErrorFVerb(DEBUG_VERB, "*"); - } - - xf86ErrorFVerb(DEBUG_VERB, - "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution); - xf86ErrorFVerb(DEBUG_VERB, - " ModeAttributes: 0x%x\n", mode->ModeAttributes); - xf86ErrorFVerb(DEBUG_VERB, - " WinAAttributes: 0x%x\n", mode->WinAAttributes); - xf86ErrorFVerb(DEBUG_VERB, - " WinBAttributes: 0x%x\n", mode->WinBAttributes); - xf86ErrorFVerb(DEBUG_VERB, - " WinGranularity: %d\n", mode->WinGranularity); - xf86ErrorFVerb(DEBUG_VERB, - " WinSize: %d\n", mode->WinSize); - xf86ErrorFVerb(DEBUG_VERB, - " WinASegment: 0x%x\n", mode->WinASegment); - xf86ErrorFVerb(DEBUG_VERB, - " WinBSegment: 0x%x\n", mode->WinBSegment); - xf86ErrorFVerb(DEBUG_VERB, - " WinFuncPtr: 0x%lx\n", (unsigned long)mode->WinFuncPtr); - xf86ErrorFVerb(DEBUG_VERB, - " BytesPerScanline: %d\n", mode->BytesPerScanline); - xf86ErrorFVerb(DEBUG_VERB, - " XResolution: %d\n", mode->XResolution); - xf86ErrorFVerb(DEBUG_VERB, - " YResolution: %d\n", mode->YResolution); - xf86ErrorFVerb(DEBUG_VERB, - " XCharSize: %d\n", mode->XCharSize); - xf86ErrorFVerb(DEBUG_VERB, - " YCharSize: %d\n", mode->YCharSize); - xf86ErrorFVerb(DEBUG_VERB, - " NumberOfPlanes: %d\n", mode->NumberOfPlanes); - xf86ErrorFVerb(DEBUG_VERB, - " BitsPerPixel: %d\n", mode->BitsPerPixel); - xf86ErrorFVerb(DEBUG_VERB, - " NumberOfBanks: %d\n", mode->NumberOfBanks); - xf86ErrorFVerb(DEBUG_VERB, - " MemoryModel: %d\n", mode->MemoryModel); - xf86ErrorFVerb(DEBUG_VERB, - " BankSize: %d\n", mode->BankSize); - xf86ErrorFVerb(DEBUG_VERB, - " NumberOfImages: %d\n", mode->NumberOfImages); - xf86ErrorFVerb(DEBUG_VERB, - " RedMaskSize: %d\n", mode->RedMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " RedFieldPosition: %d\n", mode->RedFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " GreenMaskSize: %d\n", mode->GreenMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " GreenFieldPosition: %d\n", mode->GreenFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " BlueMaskSize: %d\n", mode->BlueMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " BlueFieldPosition: %d\n", mode->BlueFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " RsvdMaskSize: %d\n", mode->RsvdMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " RsvdFieldPosition: %d\n", mode->RsvdFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " DirectColorModeInfo: %d\n", mode->DirectColorModeInfo); - if (major >= 2) { - xf86ErrorFVerb(DEBUG_VERB, - " PhysBasePtr: 0x%lx\n", - (unsigned long)mode->PhysBasePtr); - if (major >= 3) { - xf86ErrorFVerb(DEBUG_VERB, - " LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine); - xf86ErrorFVerb(DEBUG_VERB, - " BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages); - xf86ErrorFVerb(DEBUG_VERB, - " LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages); - xf86ErrorFVerb(DEBUG_VERB, - " LinRedMaskSize: %d\n", mode->LinRedMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " LinRedFieldPosition: %d\n", mode->LinRedFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " LinGreenMaskSize: %d\n", mode->LinGreenMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " LinBlueMaskSize: %d\n", mode->LinBlueMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize); - xf86ErrorFVerb(DEBUG_VERB, - " LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition); - xf86ErrorFVerb(DEBUG_VERB, - " MaxPixelClock: %ld\n", (unsigned long)mode->MaxPixelClock); - } - } - - if (!modeOK) { - VBEFreeModeInfo(mode); - return NULL; - } - pMode = xnfcalloc(sizeof(DisplayModeRec), 1); - - pMode->status = MODE_OK; - pMode->type = M_T_BUILTIN; - - /* for adjust frame */ - pMode->HDisplay = mode->XResolution; - pMode->VDisplay = mode->YResolution; - - data = xnfcalloc(sizeof(VbeModeInfoData), 1); - data->mode = id; - data->data = mode; - pMode->PrivSize = sizeof(VbeModeInfoData); - pMode->Private = (INT32*)data; - pMode->next = NULL; - return pMode; -} - -/* - * Check the available BIOS modes, and extract those that match the - * requirements into the modePool. Note: modePool is a NULL-terminated - * list. - */ - -DisplayModePtr -VBEGetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, - int modeTypes) -{ - DisplayModePtr pMode, p = NULL, modePool = NULL; - int i = 0; - - if (modeTypes & V_MODETYPE_VBE) { - while (vbe->VideoModePtr[i] != 0xffff) { - int id = vbe->VideoModePtr[i++]; - - if ((pMode = CheckMode(pScrn, pVbe, vbe, id, modeTypes)) != NULL) { - ModeStatus status = MODE_OK; - - /* Check the mode against a specified virtual size (if any) */ - if (pScrn->display->virtualX > 0 && - pMode->HDisplay > pScrn->display->virtualX) { - status = MODE_VIRTUAL_X; - } - if (pScrn->display->virtualY > 0 && - pMode->VDisplay > pScrn->display->virtualY) { - status = MODE_VIRTUAL_Y; - } - if (status != MODE_OK) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Not using mode \"%dx%d\" (%s)\n", - pMode->HDisplay, pMode->VDisplay, - xf86ModeStatusToString(status)); - } else { - if (p == NULL) { - modePool = pMode; - } else { - p->next = pMode; - } - pMode->prev = NULL; - p = pMode; - } - } - } - } - if (modeTypes & V_MODETYPE_VGA) { - for (i = 0; i < 0x7F; i++) { - if ((pMode = CheckMode(pScrn, pVbe, vbe, i, modeTypes)) != NULL) { - ModeStatus status = MODE_OK; - - /* Check the mode against a specified virtual size (if any) */ - if (pScrn->display->virtualX > 0 && - pMode->HDisplay > pScrn->display->virtualX) { - status = MODE_VIRTUAL_X; - } - if (pScrn->display->virtualY > 0 && - pMode->VDisplay > pScrn->display->virtualY) { - status = MODE_VIRTUAL_Y; - } - if (status != MODE_OK) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Not using mode \"%dx%d\" (%s)\n", - pMode->HDisplay, pMode->VDisplay, - xf86ModeStatusToString(status)); - } else { - if (p == NULL) { - modePool = pMode; - } else { - p->next = pMode; - } - pMode->prev = NULL; - p = pMode; - } - } - } - } - return modePool; -} - -void -VBESetModeNames(DisplayModePtr pMode) -{ - if (!pMode) - return; - - do { - if (!pMode->name) { - /* Catch "bad" modes. */ - if (pMode->HDisplay > 10000 || pMode->HDisplay < 0 || - pMode->VDisplay > 10000 || pMode->VDisplay < 0) { - pMode->name = strdup("BADMODE"); - } else { - pMode->name = xnfalloc(4 + 1 + 4 + 1); - sprintf(pMode->name, "%dx%d", pMode->HDisplay, pMode->VDisplay); - } - } - pMode = pMode->next; - } while (pMode); -} - -/* - * Go through the monitor modes and selecting the best set of - * parameters for each BIOS mode. Note: This is only supported in - * VBE version 3.0 or later. - */ -void -VBESetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe) -{ - DisplayModePtr pMode; - VbeModeInfoData *data; - - pMode = pScrn->modes; - do { - DisplayModePtr p, best = NULL; - ModeStatus status; - - for (p = pScrn->monitor->Modes; p != NULL; p = p->next) { - if ((p->HDisplay != pMode->HDisplay) || - (p->VDisplay != pMode->VDisplay) || - (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) - continue; - /* XXX could support the various V_ flags */ - status = xf86CheckModeForMonitor(p, pScrn->monitor); - if (status != MODE_OK) - continue; - if (!best || (p->Clock > best->Clock)) - best = p; - } - - if (best) { - int clock; - - data = (VbeModeInfoData*)pMode->Private; - pMode->HSync = (float)best->Clock * 1000.0 / best->HTotal + 0.5; - pMode->VRefresh = pMode->HSync / best->VTotal + 0.5; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Attempting to use %dHz refresh for mode \"%s\" (%x)\n", - (int)pMode->VRefresh, pMode->name, data->mode); - data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1); - data->block->HorizontalTotal = best->HTotal; - data->block->HorizontalSyncStart = best->HSyncStart; - data->block->HorizontalSyncEnd = best->HSyncEnd; - data->block->VerticalTotal = best->VTotal; - data->block->VerticalSyncStart = best->VSyncStart; - data->block->VerticalSyncEnd = best->VSyncEnd; - data->block->Flags = ((best->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | - ((best->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); - data->block->PixelClock = best->Clock * 1000; - /* XXX May not have this. */ - clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); - DebugF("Setting clock %.2fMHz, closest is %.2fMHz\n", - (double)data->block->PixelClock / 1000000.0, - (double)clock / 1000000.0); - if (clock) - data->block->PixelClock = clock; - data->mode |= (1 << 11); - data->block->RefreshRate = ((double)(data->block->PixelClock) / - (double)(best->HTotal * best->VTotal)) * 100; - } - pMode = pMode->next; - } while (pMode != pScrn->modes); -} - -/* - * These wrappers are to allow (temporary) funtionality divergences. - */ -int -VBEValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, - char **modeNames, ClockRangePtr clockRanges, - int *linePitches, int minPitch, int maxPitch, int pitchInc, - int minHeight, int maxHeight, int virtualX, int virtualY, - int apertureSize, LookupModeFlags strategy) -{ - return xf86ValidateModes(scrp, availModes, modeNames, clockRanges, - linePitches, minPitch, maxPitch, pitchInc, - minHeight, maxHeight, virtualX, virtualY, - apertureSize, strategy); -} - -void -VBEPrintModes(ScrnInfoPtr scrp) -{ - xf86PrintModes(scrp); -} - +#define DEBUG_VERB 2 +/* + * Copyright © 2002 David Dawes + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the author(s) 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 author(s). + * + * Authors: David Dawes + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +#include "xf86.h" +#include "vbe.h" +#include "vbeModes.h" + +static int +GetDepthFlag(vbeInfoPtr pVbe, int id) +{ + VbeModeInfoBlock *mode; + int bpp; + + if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) + return 0; + + if (VBE_MODE_USABLE(mode, 0)) { + int depth; + + if (VBE_MODE_COLOR(mode)) { + depth = mode->RedMaskSize + mode->GreenMaskSize + + mode->BlueMaskSize; + } else { + depth = 1; + } + bpp = mode->BitsPerPixel; + VBEFreeModeInfo(mode); + mode = NULL; + switch (depth) { + case 1: + return V_DEPTH_1; + case 4: + return V_DEPTH_4; + case 8: + return V_DEPTH_8; + case 15: + return V_DEPTH_15; + case 16: + return V_DEPTH_16; + case 24: + switch (bpp) { + case 24: + return V_DEPTH_24_24; + case 32: + return V_DEPTH_24_32; + } + } + } + if (mode) + VBEFreeModeInfo(mode); + return 0; +} + +/* + * Find supported mode depths. + */ +int +VBEFindSupportedDepths(vbeInfoPtr pVbe, VbeInfoBlock *vbe, int *flags24, + int modeTypes) +{ + int i = 0; + int depths = 0; + + if (modeTypes & V_MODETYPE_VBE) { + while (vbe->VideoModePtr[i] != 0xffff) { + depths |= GetDepthFlag(pVbe, vbe->VideoModePtr[i++]); + } + } + + /* + * XXX This possibly only works with VBE 3.0 and later. + */ + if (modeTypes & V_MODETYPE_VGA) { + for (i = 0; i < 0x7F; i++) { + depths |= GetDepthFlag(pVbe, i); + } + } + + if (flags24) { + if (depths & V_DEPTH_24_24) + *flags24 |= Support24bppFb; + if (depths & V_DEPTH_24_32) + *flags24 |= Support32bppFb; + } + + return depths; +} + +static DisplayModePtr +CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id, + int flags) +{ + CARD16 major; + VbeModeInfoBlock *mode; + DisplayModePtr pMode; + VbeModeInfoData *data; + Bool modeOK = FALSE; + + major = (unsigned)(vbe->VESAVersion >> 8); + + if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) + return NULL; + + /* Does the mode match the depth/bpp? */ + /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */ + if (VBE_MODE_USABLE(mode, flags) && + ((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) || + (mode->BitsPerPixel > 8 && + (mode->RedMaskSize + mode->GreenMaskSize + + mode->BlueMaskSize) == pScrn->depth && + mode->BitsPerPixel == pScrn->bitsPerPixel) || + (mode->BitsPerPixel == 15 && pScrn->depth == 15) || + (mode->BitsPerPixel <= 8 && + mode->BitsPerPixel == pScrn->bitsPerPixel))) { + modeOK = TRUE; + xf86ErrorFVerb(DEBUG_VERB, "*"); + } + + xf86ErrorFVerb(DEBUG_VERB, + "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution); + xf86ErrorFVerb(DEBUG_VERB, + " ModeAttributes: 0x%x\n", mode->ModeAttributes); + xf86ErrorFVerb(DEBUG_VERB, + " WinAAttributes: 0x%x\n", mode->WinAAttributes); + xf86ErrorFVerb(DEBUG_VERB, + " WinBAttributes: 0x%x\n", mode->WinBAttributes); + xf86ErrorFVerb(DEBUG_VERB, + " WinGranularity: %d\n", mode->WinGranularity); + xf86ErrorFVerb(DEBUG_VERB, + " WinSize: %d\n", mode->WinSize); + xf86ErrorFVerb(DEBUG_VERB, + " WinASegment: 0x%x\n", mode->WinASegment); + xf86ErrorFVerb(DEBUG_VERB, + " WinBSegment: 0x%x\n", mode->WinBSegment); + xf86ErrorFVerb(DEBUG_VERB, + " WinFuncPtr: 0x%lx\n", (unsigned long)mode->WinFuncPtr); + xf86ErrorFVerb(DEBUG_VERB, + " BytesPerScanline: %d\n", mode->BytesPerScanline); + xf86ErrorFVerb(DEBUG_VERB, + " XResolution: %d\n", mode->XResolution); + xf86ErrorFVerb(DEBUG_VERB, + " YResolution: %d\n", mode->YResolution); + xf86ErrorFVerb(DEBUG_VERB, + " XCharSize: %d\n", mode->XCharSize); + xf86ErrorFVerb(DEBUG_VERB, + " YCharSize: %d\n", mode->YCharSize); + xf86ErrorFVerb(DEBUG_VERB, + " NumberOfPlanes: %d\n", mode->NumberOfPlanes); + xf86ErrorFVerb(DEBUG_VERB, + " BitsPerPixel: %d\n", mode->BitsPerPixel); + xf86ErrorFVerb(DEBUG_VERB, + " NumberOfBanks: %d\n", mode->NumberOfBanks); + xf86ErrorFVerb(DEBUG_VERB, + " MemoryModel: %d\n", mode->MemoryModel); + xf86ErrorFVerb(DEBUG_VERB, + " BankSize: %d\n", mode->BankSize); + xf86ErrorFVerb(DEBUG_VERB, + " NumberOfImages: %d\n", mode->NumberOfImages); + xf86ErrorFVerb(DEBUG_VERB, + " RedMaskSize: %d\n", mode->RedMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " RedFieldPosition: %d\n", mode->RedFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " GreenMaskSize: %d\n", mode->GreenMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " GreenFieldPosition: %d\n", mode->GreenFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " BlueMaskSize: %d\n", mode->BlueMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " BlueFieldPosition: %d\n", mode->BlueFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " RsvdMaskSize: %d\n", mode->RsvdMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " RsvdFieldPosition: %d\n", mode->RsvdFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " DirectColorModeInfo: %d\n", mode->DirectColorModeInfo); + if (major >= 2) { + xf86ErrorFVerb(DEBUG_VERB, + " PhysBasePtr: 0x%lx\n", + (unsigned long)mode->PhysBasePtr); + if (major >= 3) { + xf86ErrorFVerb(DEBUG_VERB, + " LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine); + xf86ErrorFVerb(DEBUG_VERB, + " BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages); + xf86ErrorFVerb(DEBUG_VERB, + " LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages); + xf86ErrorFVerb(DEBUG_VERB, + " LinRedMaskSize: %d\n", mode->LinRedMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " LinRedFieldPosition: %d\n", mode->LinRedFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " LinGreenMaskSize: %d\n", mode->LinGreenMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " LinBlueMaskSize: %d\n", mode->LinBlueMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " MaxPixelClock: %ld\n", (unsigned long)mode->MaxPixelClock); + } + } + + if (!modeOK) { + VBEFreeModeInfo(mode); + return NULL; + } + pMode = xnfcalloc(sizeof(DisplayModeRec), 1); + + pMode->status = MODE_OK; + pMode->type = M_T_BUILTIN; + + /* for adjust frame */ + pMode->HDisplay = mode->XResolution; + pMode->VDisplay = mode->YResolution; + + data = xnfcalloc(sizeof(VbeModeInfoData), 1); + data->mode = id; + data->data = mode; + pMode->PrivSize = sizeof(VbeModeInfoData); + pMode->Private = (INT32*)data; + pMode->next = NULL; + return pMode; +} + +/* + * Check the available BIOS modes, and extract those that match the + * requirements into the modePool. Note: modePool is a NULL-terminated + * list. + */ + +DisplayModePtr +VBEGetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, + int modeTypes) +{ + DisplayModePtr pMode, p = NULL, modePool = NULL; + int i = 0; + + if (modeTypes & V_MODETYPE_VBE) { + while (vbe->VideoModePtr[i] != 0xffff) { + int id = vbe->VideoModePtr[i++]; + + if ((pMode = CheckMode(pScrn, pVbe, vbe, id, modeTypes)) != NULL) { + ModeStatus status = MODE_OK; + + /* Check the mode against a specified virtual size (if any) */ + if (pScrn->display->virtualX > 0 && + pMode->HDisplay > pScrn->display->virtualX) { + status = MODE_VIRTUAL_X; + } + if (pScrn->display->virtualY > 0 && + pMode->VDisplay > pScrn->display->virtualY) { + status = MODE_VIRTUAL_Y; + } + if (status != MODE_OK) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%dx%d\" (%s)\n", + pMode->HDisplay, pMode->VDisplay, + xf86ModeStatusToString(status)); + } else { + if (p == NULL) { + modePool = pMode; + } else { + p->next = pMode; + } + pMode->prev = NULL; + p = pMode; + } + } + } + } + if (modeTypes & V_MODETYPE_VGA) { + for (i = 0; i < 0x7F; i++) { + if ((pMode = CheckMode(pScrn, pVbe, vbe, i, modeTypes)) != NULL) { + ModeStatus status = MODE_OK; + + /* Check the mode against a specified virtual size (if any) */ + if (pScrn->display->virtualX > 0 && + pMode->HDisplay > pScrn->display->virtualX) { + status = MODE_VIRTUAL_X; + } + if (pScrn->display->virtualY > 0 && + pMode->VDisplay > pScrn->display->virtualY) { + status = MODE_VIRTUAL_Y; + } + if (status != MODE_OK) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%dx%d\" (%s)\n", + pMode->HDisplay, pMode->VDisplay, + xf86ModeStatusToString(status)); + } else { + if (p == NULL) { + modePool = pMode; + } else { + p->next = pMode; + } + pMode->prev = NULL; + p = pMode; + } + } + } + } + return modePool; +} + +void +VBESetModeNames(DisplayModePtr pMode) +{ + if (!pMode) + return; + + do { + if (!pMode->name) { + /* Catch "bad" modes. */ + if (pMode->HDisplay > 10000 || pMode->HDisplay < 0 || + pMode->VDisplay > 10000 || pMode->VDisplay < 0) { + pMode->name = strdup("BADMODE"); + } else { + pMode->name = xnfalloc(4 + 1 + 4 + 1); + sprintf(pMode->name, "%dx%d", pMode->HDisplay, pMode->VDisplay); + } + } + pMode = pMode->next; + } while (pMode); +} + +/* + * Go through the monitor modes and selecting the best set of + * parameters for each BIOS mode. Note: This is only supported in + * VBE version 3.0 or later. + */ +void +VBESetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe) +{ + DisplayModePtr pMode; + VbeModeInfoData *data; + + pMode = pScrn->modes; + do { + DisplayModePtr p, best = NULL; + ModeStatus status; + + for (p = pScrn->monitor->Modes; p != NULL; p = p->next) { + if ((p->HDisplay != pMode->HDisplay) || + (p->VDisplay != pMode->VDisplay) || + (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) + continue; + /* XXX could support the various V_ flags */ + status = xf86CheckModeForMonitor(p, pScrn->monitor); + if (status != MODE_OK) + continue; + if (!best || (p->Clock > best->Clock)) + best = p; + } + + if (best) { + int clock; + + data = (VbeModeInfoData*)pMode->Private; + pMode->HSync = (float)best->Clock * 1000.0 / best->HTotal + 0.5; + pMode->VRefresh = pMode->HSync / best->VTotal + 0.5; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Attempting to use %dHz refresh for mode \"%s\" (%x)\n", + (int)pMode->VRefresh, pMode->name, data->mode); + data->block = calloc(sizeof(VbeCRTCInfoBlock), 1); + data->block->HorizontalTotal = best->HTotal; + data->block->HorizontalSyncStart = best->HSyncStart; + data->block->HorizontalSyncEnd = best->HSyncEnd; + data->block->VerticalTotal = best->VTotal; + data->block->VerticalSyncStart = best->VSyncStart; + data->block->VerticalSyncEnd = best->VSyncEnd; + data->block->Flags = ((best->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | + ((best->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); + data->block->PixelClock = best->Clock * 1000; + /* XXX May not have this. */ + clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); + DebugF("Setting clock %.2fMHz, closest is %.2fMHz\n", + (double)data->block->PixelClock / 1000000.0, + (double)clock / 1000000.0); + if (clock) + data->block->PixelClock = clock; + data->mode |= (1 << 11); + data->block->RefreshRate = ((double)(data->block->PixelClock) / + (double)(best->HTotal * best->VTotal)) * 100; + } + pMode = pMode->next; + } while (pMode != pScrn->modes); +} + +/* + * These wrappers are to allow (temporary) funtionality divergences. + */ +int +VBEValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, + char **modeNames, ClockRangePtr clockRanges, + int *linePitches, int minPitch, int maxPitch, int pitchInc, + int minHeight, int maxHeight, int virtualX, int virtualY, + int apertureSize, LookupModeFlags strategy) +{ + return xf86ValidateModes(scrp, availModes, modeNames, clockRanges, + linePitches, minPitch, maxPitch, pitchInc, + minHeight, maxHeight, virtualX, virtualY, + apertureSize, strategy); +} + +void +VBEPrintModes(ScrnInfoPtr scrp) +{ + xf86PrintModes(scrp); +} + diff --git a/xorg-server/hw/xfree86/vgahw/vgaCmap.c b/xorg-server/hw/xfree86/vgahw/vgaCmap.c index 06eeb4ce1..e337b42c0 100644 --- a/xorg-server/hw/xfree86/vgahw/vgaCmap.c +++ b/xorg-server/hw/xfree86/vgahw/vgaCmap.c @@ -1,301 +1,301 @@ -/* - * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. - * - * 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 Thomas Roell not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Thomas Roell makes no representations - * about the suitability of this software for any purpose. It is provided - * "as is" without express or implied warranty. - * - * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THOMAS ROELL 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. - * - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include "windowstr.h" -#include "compiler.h" -#include "mipointer.h" -#include "micmap.h" - -#include "xf86.h" -#include "vgaHW.h" - -#include -#include "dgaproc.h" - - -#define NOMAPYET (ColormapPtr) 0 - -int -vgaListInstalledColormaps(pScreen, pmaps) - ScreenPtr pScreen; - Colormap *pmaps; -{ - /* By the time we are processing requests, we can guarantee that there - * is always a colormap installed */ - - *pmaps = GetInstalledmiColormap(pScreen)->mid; - return(1); -} - -int -vgaGetInstalledColormaps(pScreen, pmaps) - ScreenPtr pScreen; - ColormapPtr *pmaps; -{ - /* By the time we are processing requests, we can guarantee that there - * is always a colormap installed */ - - *pmaps = GetInstalledmiColormap(pScreen); - return(1); -} - -int vgaCheckColorMap(ColormapPtr pmap) -{ - return (pmap != GetInstalledmiColormap(pmap->pScreen)); -} - - -void -vgaStoreColors(pmap, ndef, pdefs) - ColormapPtr pmap; - int ndef; - xColorItem *pdefs; -{ - int i; - unsigned char *cmap, *tmp = NULL; - xColorItem directDefs[256]; - Bool new_overscan = FALSE; - Bool writeColormap; - - /* This can get called before the ScrnInfoRec is installed so we - can't rely on getting it with XF86SCRNINFO() */ - int scrnIndex = pmap->pScreen->myNum; - ScrnInfoPtr scrninfp = xf86Screens[scrnIndex]; - vgaHWPtr hwp = VGAHWPTR(scrninfp); - - unsigned char overscan = hwp->ModeReg.Attribute[OVERSCAN]; - unsigned char tmp_overscan = 0; - - if (vgaCheckColorMap(pmap)) - return; - - if ((pmap->pVisual->class | DynamicClass) == DirectColor) - { - ndef = miExpandDirectColors (pmap, ndef, pdefs, directDefs); - pdefs = directDefs; - } - - writeColormap = scrninfp->vtSema; - if (DGAAvailable(scrnIndex)) - { - writeColormap = writeColormap || - (DGAGetDirectMode(scrnIndex) && - !(DGAGetFlags(scrnIndex) & XF86DGADirectColormap)) || - (DGAGetFlags(scrnIndex) & XF86DGAHasColormap); - } - - if (writeColormap) - hwp->enablePalette(hwp); - - for(i = 0; i < ndef; i++) - { - if (pdefs[i].pixel == overscan) - { - new_overscan = TRUE; - } - cmap = &(hwp->ModeReg.DAC[pdefs[i].pixel*3]); - if (scrninfp->rgbBits == 8) { - cmap[0] = pdefs[i].red >> 8; - cmap[1] = pdefs[i].green >> 8; - cmap[2] = pdefs[i].blue >> 8; - } - else { - cmap[0] = pdefs[i].red >> 10; - cmap[1] = pdefs[i].green >> 10; - cmap[2] = pdefs[i].blue >> 10; - } -#if 0 - if (clgd6225Lcd) - { - /* The LCD doesn't like white */ - if (cmap[0] == 63) cmap[0]= 62; - if (cmap[1] == 63) cmap[1]= 62; - if (cmap[2] == 63) cmap[2]= 62; - } -#endif - - if (writeColormap) - { - if (hwp->ShowOverscan && i == 255) - continue; - hwp->writeDacWriteAddr(hwp, pdefs[i].pixel); - DACDelay(hwp); - hwp->writeDacData(hwp, cmap[0]); - DACDelay(hwp); - hwp->writeDacData(hwp, cmap[1]); - DACDelay(hwp); - hwp->writeDacData(hwp, cmap[2]); - DACDelay(hwp); - } - } - if (new_overscan && !hwp->ShowOverscan) - { - new_overscan = FALSE; - for(i = 0; i < ndef; i++) - { - if (pdefs[i].pixel == overscan) - { - if ((pdefs[i].red != 0) || - (pdefs[i].green != 0) || - (pdefs[i].blue != 0)) - { - new_overscan = TRUE; - tmp_overscan = overscan; - tmp = &(hwp->ModeReg.DAC[pdefs[i].pixel*3]); - } - break; - } - } - if (new_overscan) - { - /* - * Find a black pixel, or the nearest match. - */ - for (i=255; i >= 0; i--) - { - cmap = &(hwp->ModeReg.DAC[i*3]); - if ((cmap[0] == 0) && (cmap[1] == 0) && (cmap[2] == 0)) - { - overscan = i; - break; - } - else - { - if ((cmap[0] < tmp[0]) && - (cmap[1] < tmp[1]) && (cmap[2] < tmp[2])) - { - tmp = cmap; - tmp_overscan = i; - } - } - } - if (i < 0) - { - overscan = tmp_overscan; - } - hwp->ModeReg.Attribute[OVERSCAN] = overscan; - if (writeColormap) - { - hwp->writeAttr(hwp, OVERSCAN, overscan); - } - } - } - - if (writeColormap) - hwp->disablePalette(hwp); -} - - -void -vgaInstallColormap(pmap) - ColormapPtr pmap; -{ - ColormapPtr oldmap = GetInstalledmiColormap(pmap->pScreen); - int entries; - Pixel * ppix; - xrgb * prgb; - xColorItem *defs; - int i; - - - if (pmap == oldmap) - return; - - if ((pmap->pVisual->class | DynamicClass) == DirectColor) - entries = (pmap->pVisual->redMask | - pmap->pVisual->greenMask | - pmap->pVisual->blueMask) + 1; - else - entries = pmap->pVisual->ColormapEntries; - - ppix = (Pixel *)xalloc( entries * sizeof(Pixel)); - prgb = (xrgb *)xalloc( entries * sizeof(xrgb)); - defs = (xColorItem *)xalloc(entries * sizeof(xColorItem)); - - if ( oldmap != NOMAPYET) - WalkTree( pmap->pScreen, TellLostMap, &oldmap->mid); - - SetInstalledmiColormap(pmap->pScreen, pmap); - - for ( i=0; ipScreen->StoreColors(pmap, entries, defs); - - WalkTree(pmap->pScreen, TellGainedMap, &pmap->mid); - - xfree(ppix); - xfree(prgb); - xfree(defs); -} - - -void -vgaUninstallColormap(pmap) - ColormapPtr pmap; -{ - - ColormapPtr defColormap; - - if ( pmap != GetInstalledmiColormap(pmap->pScreen)) - return; - - dixLookupResourceByType((pointer *)&defColormap, pmap->pScreen->defColormap, - RT_COLORMAP, serverClient, DixInstallAccess); - - if (defColormap == GetInstalledmiColormap(pmap->pScreen)) - return; - - (*pmap->pScreen->InstallColormap) (defColormap); -} - - -void -vgaHandleColormaps(ScreenPtr pScreen, ScrnInfoPtr scrnp) -{ - if (scrnp->bitsPerPixel > 1) { - if (scrnp->bitsPerPixel <= 8) { /* For 8bpp SVGA and VGA16 */ - pScreen->InstallColormap = vgaInstallColormap; - pScreen->UninstallColormap = vgaUninstallColormap; - pScreen->ListInstalledColormaps = vgaListInstalledColormaps; - pScreen->StoreColors = vgaStoreColors; - } - } -} - +/* + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * 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 Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL 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. + * + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include "windowstr.h" +#include "compiler.h" +#include "mipointer.h" +#include "micmap.h" + +#include "xf86.h" +#include "vgaHW.h" + +#include +#include "dgaproc.h" + + +#define NOMAPYET (ColormapPtr) 0 + +int +vgaListInstalledColormaps(pScreen, pmaps) + ScreenPtr pScreen; + Colormap *pmaps; +{ + /* By the time we are processing requests, we can guarantee that there + * is always a colormap installed */ + + *pmaps = GetInstalledmiColormap(pScreen)->mid; + return(1); +} + +int +vgaGetInstalledColormaps(pScreen, pmaps) + ScreenPtr pScreen; + ColormapPtr *pmaps; +{ + /* By the time we are processing requests, we can guarantee that there + * is always a colormap installed */ + + *pmaps = GetInstalledmiColormap(pScreen); + return(1); +} + +int vgaCheckColorMap(ColormapPtr pmap) +{ + return (pmap != GetInstalledmiColormap(pmap->pScreen)); +} + + +void +vgaStoreColors(pmap, ndef, pdefs) + ColormapPtr pmap; + int ndef; + xColorItem *pdefs; +{ + int i; + unsigned char *cmap, *tmp = NULL; + xColorItem directDefs[256]; + Bool new_overscan = FALSE; + Bool writeColormap; + + /* This can get called before the ScrnInfoRec is installed so we + can't rely on getting it with XF86SCRNINFO() */ + int scrnIndex = pmap->pScreen->myNum; + ScrnInfoPtr scrninfp = xf86Screens[scrnIndex]; + vgaHWPtr hwp = VGAHWPTR(scrninfp); + + unsigned char overscan = hwp->ModeReg.Attribute[OVERSCAN]; + unsigned char tmp_overscan = 0; + + if (vgaCheckColorMap(pmap)) + return; + + if ((pmap->pVisual->class | DynamicClass) == DirectColor) + { + ndef = miExpandDirectColors (pmap, ndef, pdefs, directDefs); + pdefs = directDefs; + } + + writeColormap = scrninfp->vtSema; + if (DGAAvailable(scrnIndex)) + { + writeColormap = writeColormap || + (DGAGetDirectMode(scrnIndex) && + !(DGAGetFlags(scrnIndex) & XF86DGADirectColormap)) || + (DGAGetFlags(scrnIndex) & XF86DGAHasColormap); + } + + if (writeColormap) + hwp->enablePalette(hwp); + + for(i = 0; i < ndef; i++) + { + if (pdefs[i].pixel == overscan) + { + new_overscan = TRUE; + } + cmap = &(hwp->ModeReg.DAC[pdefs[i].pixel*3]); + if (scrninfp->rgbBits == 8) { + cmap[0] = pdefs[i].red >> 8; + cmap[1] = pdefs[i].green >> 8; + cmap[2] = pdefs[i].blue >> 8; + } + else { + cmap[0] = pdefs[i].red >> 10; + cmap[1] = pdefs[i].green >> 10; + cmap[2] = pdefs[i].blue >> 10; + } +#if 0 + if (clgd6225Lcd) + { + /* The LCD doesn't like white */ + if (cmap[0] == 63) cmap[0]= 62; + if (cmap[1] == 63) cmap[1]= 62; + if (cmap[2] == 63) cmap[2]= 62; + } +#endif + + if (writeColormap) + { + if (hwp->ShowOverscan && i == 255) + continue; + hwp->writeDacWriteAddr(hwp, pdefs[i].pixel); + DACDelay(hwp); + hwp->writeDacData(hwp, cmap[0]); + DACDelay(hwp); + hwp->writeDacData(hwp, cmap[1]); + DACDelay(hwp); + hwp->writeDacData(hwp, cmap[2]); + DACDelay(hwp); + } + } + if (new_overscan && !hwp->ShowOverscan) + { + new_overscan = FALSE; + for(i = 0; i < ndef; i++) + { + if (pdefs[i].pixel == overscan) + { + if ((pdefs[i].red != 0) || + (pdefs[i].green != 0) || + (pdefs[i].blue != 0)) + { + new_overscan = TRUE; + tmp_overscan = overscan; + tmp = &(hwp->ModeReg.DAC[pdefs[i].pixel*3]); + } + break; + } + } + if (new_overscan) + { + /* + * Find a black pixel, or the nearest match. + */ + for (i=255; i >= 0; i--) + { + cmap = &(hwp->ModeReg.DAC[i*3]); + if ((cmap[0] == 0) && (cmap[1] == 0) && (cmap[2] == 0)) + { + overscan = i; + break; + } + else + { + if ((cmap[0] < tmp[0]) && + (cmap[1] < tmp[1]) && (cmap[2] < tmp[2])) + { + tmp = cmap; + tmp_overscan = i; + } + } + } + if (i < 0) + { + overscan = tmp_overscan; + } + hwp->ModeReg.Attribute[OVERSCAN] = overscan; + if (writeColormap) + { + hwp->writeAttr(hwp, OVERSCAN, overscan); + } + } + } + + if (writeColormap) + hwp->disablePalette(hwp); +} + + +void +vgaInstallColormap(pmap) + ColormapPtr pmap; +{ + ColormapPtr oldmap = GetInstalledmiColormap(pmap->pScreen); + int entries; + Pixel * ppix; + xrgb * prgb; + xColorItem *defs; + int i; + + + if (pmap == oldmap) + return; + + if ((pmap->pVisual->class | DynamicClass) == DirectColor) + entries = (pmap->pVisual->redMask | + pmap->pVisual->greenMask | + pmap->pVisual->blueMask) + 1; + else + entries = pmap->pVisual->ColormapEntries; + + ppix = (Pixel *)malloc( entries * sizeof(Pixel)); + prgb = (xrgb *)malloc( entries * sizeof(xrgb)); + defs = (xColorItem *)malloc(entries * sizeof(xColorItem)); + + if ( oldmap != NOMAPYET) + WalkTree( pmap->pScreen, TellLostMap, &oldmap->mid); + + SetInstalledmiColormap(pmap->pScreen, pmap); + + for ( i=0; ipScreen->StoreColors(pmap, entries, defs); + + WalkTree(pmap->pScreen, TellGainedMap, &pmap->mid); + + free(ppix); + free(prgb); + free(defs); +} + + +void +vgaUninstallColormap(pmap) + ColormapPtr pmap; +{ + + ColormapPtr defColormap; + + if ( pmap != GetInstalledmiColormap(pmap->pScreen)) + return; + + dixLookupResourceByType((pointer *)&defColormap, pmap->pScreen->defColormap, + RT_COLORMAP, serverClient, DixInstallAccess); + + if (defColormap == GetInstalledmiColormap(pmap->pScreen)) + return; + + (*pmap->pScreen->InstallColormap) (defColormap); +} + + +void +vgaHandleColormaps(ScreenPtr pScreen, ScrnInfoPtr scrnp) +{ + if (scrnp->bitsPerPixel > 1) { + if (scrnp->bitsPerPixel <= 8) { /* For 8bpp SVGA and VGA16 */ + pScreen->InstallColormap = vgaInstallColormap; + pScreen->UninstallColormap = vgaUninstallColormap; + pScreen->ListInstalledColormaps = vgaListInstalledColormaps; + pScreen->StoreColors = vgaStoreColors; + } + } +} + diff --git a/xorg-server/hw/xfree86/vgahw/vgaHW.c b/xorg-server/hw/xfree86/vgahw/vgaHW.c index 004376b75..396a3cc62 100644 --- a/xorg-server/hw/xfree86/vgahw/vgaHW.c +++ b/xorg-server/hw/xfree86/vgahw/vgaHW.c @@ -1,1995 +1,1995 @@ - -/* - * - * Copyright 1991-1999 by The XFree86 Project, Inc. - * - * Loosely based on code bearing the following copyright: - * - * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. - * - */ - -#define _NEED_SYSI86 - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include "misc.h" - -#include "xf86.h" -#include "xf86_OSproc.h" -#include "vgaHW.h" - -#include "compiler.h" - -#include "xf86cmap.h" - -#include "Pci.h" - -#ifndef SAVE_FONT1 -#define SAVE_FONT1 1 -#endif - -/* - * These used to be OS-specific, which made this module have an undesirable - * OS dependency. Define them by default for all platforms. - */ -#ifndef NEED_SAVED_CMAP -#define NEED_SAVED_CMAP -#endif -#ifndef SAVE_TEXT -#define SAVE_TEXT 1 -#endif -#ifndef SAVE_FONT2 -#define SAVE_FONT2 1 -#endif - -/* bytes per plane to save for text */ -#define TEXT_AMOUNT 16384 - -/* bytes per plane to save for font data */ -#define FONT_AMOUNT (8*8192) - -#if 0 -/* Override all of these for now */ -#undef SAVE_FONT1 -#define SAVE_FONT1 1 -#undef SAVE_FONT2 -#define SAVE_FONT2 1 -#undef SAVE_TEST -#define SAVE_TEST 1 -#undef FONT_AMOUNT -#define FONT_AMOUNT 65536 -#undef TEXT_AMOUNT -#define TEXT_AMOUNT 65536 -#endif - -/* DAC indices for white and black */ -#define WHITE_VALUE 0x3F -#define BLACK_VALUE 0x00 -#define OVERSCAN_VALUE 0x01 - - -/* Use a private definition of this here */ -#undef VGAHWPTR -#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr -#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p))) - -static int vgaHWPrivateIndex = -1; - -#define DAC_TEST_MASK 0x3F - -#ifdef NEED_SAVED_CMAP -/* This default colourmap is used only when it can't be read from the VGA */ - -static CARD8 defaultDAC[768] = -{ - 0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42, - 42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42, - 21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63, - 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63, - 0, 0, 0, 5, 5, 5, 8, 8, 8, 11, 11, 11, - 14, 14, 14, 17, 17, 17, 20, 20, 20, 24, 24, 24, - 28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40, - 45, 45, 45, 50, 50, 50, 56, 56, 56, 63, 63, 63, - 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 63, - 63, 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, - 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, - 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 0, - 0, 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, - 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, - 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 63, - 63, 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, - 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, - 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 31, - 31, 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, - 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, - 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 63, - 63, 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, - 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, - 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 45, - 45, 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, - 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, - 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 28, - 28, 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, - 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, - 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 0, - 0, 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, - 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, - 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 28, - 28, 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, - 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, - 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 14, - 14, 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, - 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, - 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 28, - 28, 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, - 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, - 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 20, - 20, 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, - 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, - 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 16, - 16, 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, - 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, - 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 0, - 0, 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, - 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, - 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 16, - 16, 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, - 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, - 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 8, - 8, 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, - 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, - 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 16, - 16, 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, - 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, - 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 11, - 11, 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, - 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; -#endif /* NEED_SAVED_CMAP */ - -/* - * Standard VGA versions of the register access functions. - */ -static void -stdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) -{ - outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index); - outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET, value); -} - -static CARD8 -stdReadCrtc(vgaHWPtr hwp, CARD8 index) -{ - outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index); - return inb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET); -} - -static void -stdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value) -{ - outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index); - outb(hwp->PIOOffset + VGA_GRAPH_DATA, value); -} - -static CARD8 -stdReadGr(vgaHWPtr hwp, CARD8 index) -{ - outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index); - return inb(hwp->PIOOffset + VGA_GRAPH_DATA); -} - -static void -stdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value) -{ - outb(hwp->PIOOffset + VGA_SEQ_INDEX, index); - outb(hwp->PIOOffset + VGA_SEQ_DATA, value); -} - -static CARD8 -stdReadSeq(vgaHWPtr hwp, CARD8 index) -{ - outb(hwp->PIOOffset + VGA_SEQ_INDEX, index); - return inb(hwp->PIOOffset + VGA_SEQ_DATA); -} - -static CARD8 -stdReadST00(vgaHWPtr hwp) -{ - return inb(hwp->PIOOffset + VGA_IN_STAT_0); -} - -static CARD8 -stdReadST01(vgaHWPtr hwp) -{ - return inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); -} - -static CARD8 -stdReadFCR(vgaHWPtr hwp) -{ - return inb(hwp->PIOOffset + VGA_FEATURE_R); -} - -static void -stdWriteFCR(vgaHWPtr hwp, CARD8 value) -{ - outb(hwp->IOBase + hwp->PIOOffset + VGA_FEATURE_W_OFFSET,value); -} - -static void -stdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value) -{ - if (hwp->paletteEnabled) - index &= ~0x20; - else - index |= 0x20; - - (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); - outb(hwp->PIOOffset + VGA_ATTR_INDEX, index); - outb(hwp->PIOOffset + VGA_ATTR_DATA_W, value); -} - -static CARD8 -stdReadAttr(vgaHWPtr hwp, CARD8 index) -{ - if (hwp->paletteEnabled) - index &= ~0x20; - else - index |= 0x20; - - (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); - outb(hwp->PIOOffset + VGA_ATTR_INDEX, index); - return inb(hwp->PIOOffset + VGA_ATTR_DATA_R); -} - -static void -stdWriteMiscOut(vgaHWPtr hwp, CARD8 value) -{ - outb(hwp->PIOOffset + VGA_MISC_OUT_W, value); -} - -static CARD8 -stdReadMiscOut(vgaHWPtr hwp) -{ - return inb(hwp->PIOOffset + VGA_MISC_OUT_R); -} - -static void -stdEnablePalette(vgaHWPtr hwp) -{ - (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); - outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x00); - hwp->paletteEnabled = TRUE; -} - -static void -stdDisablePalette(vgaHWPtr hwp) -{ - (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); - outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x20); - hwp->paletteEnabled = FALSE; -} - -static void -stdWriteDacMask(vgaHWPtr hwp, CARD8 value) -{ - outb(hwp->PIOOffset + VGA_DAC_MASK, value); -} - -static CARD8 -stdReadDacMask(vgaHWPtr hwp) -{ - return inb(hwp->PIOOffset + VGA_DAC_MASK); -} - -static void -stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) -{ - outb(hwp->PIOOffset + VGA_DAC_READ_ADDR, value); -} - -static void -stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) -{ - outb(hwp->PIOOffset + VGA_DAC_WRITE_ADDR, value); -} - -static void -stdWriteDacData(vgaHWPtr hwp, CARD8 value) -{ - outb(hwp->PIOOffset + VGA_DAC_DATA, value); -} - -static CARD8 -stdReadDacData(vgaHWPtr hwp) -{ - return inb(hwp->PIOOffset + VGA_DAC_DATA); -} - -static CARD8 -stdReadEnable(vgaHWPtr hwp) -{ - return inb(hwp->PIOOffset + VGA_ENABLE); -} - -static void -stdWriteEnable(vgaHWPtr hwp, CARD8 value) -{ - outb(hwp->PIOOffset + VGA_ENABLE, value); -} - -void -vgaHWSetStdFuncs(vgaHWPtr hwp) -{ - hwp->writeCrtc = stdWriteCrtc; - hwp->readCrtc = stdReadCrtc; - hwp->writeGr = stdWriteGr; - hwp->readGr = stdReadGr; - hwp->readST00 = stdReadST00; - hwp->readST01 = stdReadST01; - hwp->readFCR = stdReadFCR; - hwp->writeFCR = stdWriteFCR; - hwp->writeAttr = stdWriteAttr; - hwp->readAttr = stdReadAttr; - hwp->writeSeq = stdWriteSeq; - hwp->readSeq = stdReadSeq; - hwp->writeMiscOut = stdWriteMiscOut; - hwp->readMiscOut = stdReadMiscOut; - hwp->enablePalette = stdEnablePalette; - hwp->disablePalette = stdDisablePalette; - hwp->writeDacMask = stdWriteDacMask; - hwp->readDacMask = stdReadDacMask; - hwp->writeDacWriteAddr = stdWriteDacWriteAddr; - hwp->writeDacReadAddr = stdWriteDacReadAddr; - hwp->writeDacData = stdWriteDacData; - hwp->readDacData = stdReadDacData; - hwp->PIOOffset = 0; - hwp->readEnable = stdReadEnable; - hwp->writeEnable = stdWriteEnable; -} - -/* - * MMIO versions of the register access functions. These require - * hwp->MemBase to be set in such a way that when the standard VGA port - * adderss is added the correct memory address results. - */ - -#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p))) -#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v)) - -static void -mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) -{ - moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index); - moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value); -} - -static CARD8 -mmioReadCrtc(vgaHWPtr hwp, CARD8 index) -{ - moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index); - return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET); -} - -static void -mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value) -{ - moutb(VGA_GRAPH_INDEX, index); - moutb(VGA_GRAPH_DATA, value); -} - -static CARD8 -mmioReadGr(vgaHWPtr hwp, CARD8 index) -{ - moutb(VGA_GRAPH_INDEX, index); - return minb(VGA_GRAPH_DATA); -} - -static void -mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value) -{ - moutb(VGA_SEQ_INDEX, index); - moutb(VGA_SEQ_DATA, value); -} - -static CARD8 -mmioReadSeq(vgaHWPtr hwp, CARD8 index) -{ - moutb(VGA_SEQ_INDEX, index); - return minb(VGA_SEQ_DATA); -} - -static CARD8 -mmioReadST00(vgaHWPtr hwp) -{ - return minb(VGA_IN_STAT_0); -} - -static CARD8 -mmioReadST01(vgaHWPtr hwp) -{ - return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); -} - -static CARD8 -mmioReadFCR(vgaHWPtr hwp) -{ - return minb(VGA_FEATURE_R); -} - -static void -mmioWriteFCR(vgaHWPtr hwp, CARD8 value) -{ - moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET,value); -} - -static void -mmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value) -{ - if (hwp->paletteEnabled) - index &= ~0x20; - else - index |= 0x20; - - (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); - moutb(VGA_ATTR_INDEX, index); - moutb(VGA_ATTR_DATA_W, value); -} - -static CARD8 -mmioReadAttr(vgaHWPtr hwp, CARD8 index) -{ - if (hwp->paletteEnabled) - index &= ~0x20; - else - index |= 0x20; - - (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); - moutb(VGA_ATTR_INDEX, index); - return minb(VGA_ATTR_DATA_R); -} - -static void -mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value) -{ - moutb(VGA_MISC_OUT_W, value); -} - -static CARD8 -mmioReadMiscOut(vgaHWPtr hwp) -{ - return minb(VGA_MISC_OUT_R); -} - -static void -mmioEnablePalette(vgaHWPtr hwp) -{ - (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); - moutb(VGA_ATTR_INDEX, 0x00); - hwp->paletteEnabled = TRUE; -} - -static void -mmioDisablePalette(vgaHWPtr hwp) -{ - (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); - moutb(VGA_ATTR_INDEX, 0x20); - hwp->paletteEnabled = FALSE; -} - -static void -mmioWriteDacMask(vgaHWPtr hwp, CARD8 value) -{ - moutb(VGA_DAC_MASK, value); -} - -static CARD8 -mmioReadDacMask(vgaHWPtr hwp) -{ - return minb(VGA_DAC_MASK); -} - -static void -mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) -{ - moutb(VGA_DAC_READ_ADDR, value); -} - -static void -mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) -{ - moutb(VGA_DAC_WRITE_ADDR, value); -} - -static void -mmioWriteDacData(vgaHWPtr hwp, CARD8 value) -{ - moutb(VGA_DAC_DATA, value); -} - -static CARD8 -mmioReadDacData(vgaHWPtr hwp) -{ - return minb(VGA_DAC_DATA); -} - -static CARD8 -mmioReadEnable(vgaHWPtr hwp) -{ - return minb(VGA_ENABLE); -} - -static void -mmioWriteEnable(vgaHWPtr hwp, CARD8 value) -{ - moutb(VGA_ENABLE, value); -} - -void -vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset) -{ - hwp->writeCrtc = mmioWriteCrtc; - hwp->readCrtc = mmioReadCrtc; - hwp->writeGr = mmioWriteGr; - hwp->readGr = mmioReadGr; - hwp->readST00 = mmioReadST00; - hwp->readST01 = mmioReadST01; - hwp->readFCR = mmioReadFCR; - hwp->writeFCR = mmioWriteFCR; - hwp->writeAttr = mmioWriteAttr; - hwp->readAttr = mmioReadAttr; - hwp->writeSeq = mmioWriteSeq; - hwp->readSeq = mmioReadSeq; - hwp->writeMiscOut = mmioWriteMiscOut; - hwp->readMiscOut = mmioReadMiscOut; - hwp->enablePalette = mmioEnablePalette; - hwp->disablePalette = mmioDisablePalette; - hwp->writeDacMask = mmioWriteDacMask; - hwp->readDacMask = mmioReadDacMask; - hwp->writeDacWriteAddr = mmioWriteDacWriteAddr; - hwp->writeDacReadAddr = mmioWriteDacReadAddr; - hwp->writeDacData = mmioWriteDacData; - hwp->readDacData = mmioReadDacData; - hwp->MMIOBase = base; - hwp->MMIOOffset = offset; - hwp->readEnable = mmioReadEnable; - hwp->writeEnable = mmioWriteEnable; -} - -/* - * vgaHWProtect -- - * Protect VGA registers and memory from corruption during loads. - */ - -void -vgaHWProtect(ScrnInfoPtr pScrn, Bool on) -{ - vgaHWPtr hwp = VGAHWPTR(pScrn); - - unsigned char tmp; - - if (pScrn->vtSema) { - if (on) { - /* - * Turn off screen and disable sequencer. - */ - tmp = hwp->readSeq(hwp, 0x01); - - vgaHWSeqReset(hwp, TRUE); /* start synchronous reset */ - hwp->writeSeq(hwp, 0x01, tmp | 0x20); /* disable the display */ - - hwp->enablePalette(hwp); - } else { - /* - * Reenable sequencer, then turn on screen. - */ - - tmp = hwp->readSeq(hwp, 0x01); - - hwp->writeSeq(hwp, 0x01, tmp & ~0x20); /* reenable display */ - vgaHWSeqReset(hwp, FALSE); /* clear synchronousreset */ - - hwp->disablePalette(hwp); - } - } -} - -vgaHWProtectProc *vgaHWProtectWeak(void) { - return vgaHWProtect; -} - -/* - * vgaHWBlankScreen -- blank the screen. - */ - -void -vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on) -{ - vgaHWPtr hwp = VGAHWPTR(pScrn); - unsigned char scrn; - - scrn = hwp->readSeq(hwp, 0x01); - - if (on) { - scrn &= ~0x20; /* enable screen */ - } else { - scrn |= 0x20; /* blank screen */ - } - - vgaHWSeqReset(hwp, TRUE); - hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ - vgaHWSeqReset(hwp, FALSE); -} - -vgaHWBlankScreenProc *vgaHWBlankScreenWeak(void) { - return vgaHWBlankScreen; -} - -/* - * vgaHWSaveScreen -- blank the screen. - */ - -Bool -vgaHWSaveScreen(ScreenPtr pScreen, int mode) -{ - ScrnInfoPtr pScrn = NULL; - Bool on; - - if (pScreen != NULL) - pScrn = xf86Screens[pScreen->myNum]; - - on = xf86IsUnblank(mode); - -#if 0 - if (on) - SetTimeSinceLastInputEvent(); -#endif - - if ((pScrn != NULL) && pScrn->vtSema) { - vgaHWBlankScreen(pScrn, on); - } - return (TRUE); -} - - -/* - * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode - * - * This generic VGA function can only set the Off and On modes. If the - * Standby and Suspend modes are to be supported, a chip specific replacement - * for this function must be written. - */ - -void -vgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) -{ - unsigned char seq1 = 0, crtc17 = 0; - vgaHWPtr hwp = VGAHWPTR(pScrn); - - if (!pScrn->vtSema) return; - - switch (PowerManagementMode) { - case DPMSModeOn: - /* Screen: On; HSync: On, VSync: On */ - seq1 = 0x00; - crtc17 = 0x80; - break; - case DPMSModeStandby: - /* Screen: Off; HSync: Off, VSync: On -- Not Supported */ - seq1 = 0x20; - crtc17 = 0x80; - break; - case DPMSModeSuspend: - /* Screen: Off; HSync: On, VSync: Off -- Not Supported */ - seq1 = 0x20; - crtc17 = 0x80; - break; - case DPMSModeOff: - /* Screen: Off; HSync: Off, VSync: Off */ - seq1 = 0x20; - crtc17 = 0x00; - break; - } - hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */ - seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20; - hwp->writeSeq(hwp, 0x01, seq1); - crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80; - usleep(10000); - hwp->writeCrtc(hwp, 0x17, crtc17); - hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */ -} - - -/* - * vgaHWSeqReset - * perform a sequencer reset. - */ - -void -vgaHWSeqReset(vgaHWPtr hwp, Bool start) -{ - if (start) - hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */ - else - hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */ -} - - -void -vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore) -{ -#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 - vgaHWPtr hwp = VGAHWPTR(scrninfp); - int savedIOBase; - unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4; - Bool doMap = FALSE; - - /* If nothing to do, return now */ - if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo) - return; - - if (hwp->Base == NULL) { - doMap = TRUE; - if (!vgaHWMapMem(scrninfp)) { - xf86DrvMsg(scrninfp->scrnIndex, X_ERROR, - "vgaHWRestoreFonts: vgaHWMapMem() failed\n"); - return; - } - } - - /* save the registers that are needed here */ - miscOut = hwp->readMiscOut(hwp); - attr10 = hwp->readAttr(hwp, 0x10); - gr1 = hwp->readGr(hwp, 0x01); - gr3 = hwp->readGr(hwp, 0x03); - gr4 = hwp->readGr(hwp, 0x04); - gr5 = hwp->readGr(hwp, 0x05); - gr6 = hwp->readGr(hwp, 0x06); - gr8 = hwp->readGr(hwp, 0x08); - seq2 = hwp->readSeq(hwp, 0x02); - seq4 = hwp->readSeq(hwp, 0x04); - - /* save hwp->IOBase and temporarily set it for colour mode */ - savedIOBase = hwp->IOBase; - hwp->IOBase = VGA_IOBASE_COLOR; - - /* Force into colour mode */ - hwp->writeMiscOut(hwp, miscOut | 0x01); - - vgaHWBlankScreen(scrninfp, FALSE); - - /* - * here we temporarily switch to 16 colour planar mode, to simply - * copy the font-info and saved text. - * - * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly! - */ -#if 0 - hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */ -#endif - - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ - - if (scrninfp->depth == 4) { - /* GJA */ - hwp->writeGr(hwp, 0x03, 0x00); /* don't rotate, write unmodified */ - hwp->writeGr(hwp, 0x08, 0xFF); /* write all bits in a byte */ - hwp->writeGr(hwp, 0x01, 0x00); /* all planes come from CPU */ - } - -#if SAVE_FONT1 - if (hwp->FontInfo1) { - hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */ - hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */ - slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT); - } -#endif - -#if SAVE_FONT2 - if (hwp->FontInfo2) { - hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */ - hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */ - slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT); - } -#endif - -#if SAVE_TEXT - if (hwp->TextInfo) { - hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */ - hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */ - slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT); - hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */ - hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */ - slowbcopy_tobus((unsigned char *)hwp->TextInfo + TEXT_AMOUNT, - hwp->Base, TEXT_AMOUNT); - } -#endif - - vgaHWBlankScreen(scrninfp, TRUE); - - /* restore the registers that were changed */ - hwp->writeMiscOut(hwp, miscOut); - hwp->writeAttr(hwp, 0x10, attr10); - hwp->writeGr(hwp, 0x01, gr1); - hwp->writeGr(hwp, 0x03, gr3); - hwp->writeGr(hwp, 0x04, gr4); - hwp->writeGr(hwp, 0x05, gr5); - hwp->writeGr(hwp, 0x06, gr6); - hwp->writeGr(hwp, 0x08, gr8); - hwp->writeSeq(hwp, 0x02, seq2); - hwp->writeSeq(hwp, 0x04, seq4); - hwp->IOBase = savedIOBase; - - if (doMap) - vgaHWUnmapMem(scrninfp); - -#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */ -} - - -void -vgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore) -{ - vgaHWPtr hwp = VGAHWPTR(scrninfp); - int i; - - if (restore->MiscOutReg & 0x01) - hwp->IOBase = VGA_IOBASE_COLOR; - else - hwp->IOBase = VGA_IOBASE_MONO; - - hwp->writeMiscOut(hwp, restore->MiscOutReg); - - for (i = 1; i < restore->numSequencer; i++) - hwp->writeSeq(hwp, i, restore->Sequencer[i]); - - /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */ - hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80); - - for (i = 0; i < restore->numCRTC; i++) - hwp->writeCrtc(hwp, i, restore->CRTC[i]); - - for (i = 0; i < restore->numGraphics; i++) - hwp->writeGr(hwp, i, restore->Graphics[i]); - - hwp->enablePalette(hwp); - for (i = 0; i < restore->numAttribute; i++) - hwp->writeAttr(hwp, i, restore->Attribute[i]); - hwp->disablePalette(hwp); -} - - -void -vgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore) -{ - vgaHWPtr hwp = VGAHWPTR(scrninfp); - int i; - -#if 0 - hwp->enablePalette(hwp); -#endif - - hwp->writeDacMask(hwp, 0xFF); - hwp->writeDacWriteAddr(hwp, 0x00); - for (i = 0; i < 768; i++) { - hwp->writeDacData(hwp, restore->DAC[i]); - DACDelay(hwp); - } - - hwp->disablePalette(hwp); -} - - -/* - * vgaHWRestore -- - * restore the VGA state - */ - -void -vgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags) -{ - if (flags & VGA_SR_MODE) - vgaHWRestoreMode(scrninfp, restore); - - if (flags & VGA_SR_FONTS) - vgaHWRestoreFonts(scrninfp, restore); - - if (flags & VGA_SR_CMAP) - vgaHWRestoreColormap(scrninfp, restore); -} - -void -vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save) -{ -#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 - vgaHWPtr hwp = VGAHWPTR(scrninfp); - int savedIOBase; - unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4; - Bool doMap = FALSE; - - if (hwp->Base == NULL) { - doMap = TRUE; - if (!vgaHWMapMem(scrninfp)) { - xf86DrvMsg(scrninfp->scrnIndex, X_ERROR, - "vgaHWSaveFonts: vgaHWMapMem() failed\n"); - return; - } - } - - /* If in graphics mode, don't save anything */ - attr10 = hwp->readAttr(hwp, 0x10); - if (attr10 & 0x01) - return; - - /* save the registers that are needed here */ - miscOut = hwp->readMiscOut(hwp); - gr4 = hwp->readGr(hwp, 0x04); - gr5 = hwp->readGr(hwp, 0x05); - gr6 = hwp->readGr(hwp, 0x06); - seq2 = hwp->readSeq(hwp, 0x02); - seq4 = hwp->readSeq(hwp, 0x04); - - /* save hwp->IOBase and temporarily set it for colour mode */ - savedIOBase = hwp->IOBase; - hwp->IOBase = VGA_IOBASE_COLOR; - - /* Force into colour mode */ - hwp->writeMiscOut(hwp, miscOut | 0x01); - - vgaHWBlankScreen(scrninfp, FALSE); - - /* - * get the character sets, and text screen if required - */ - /* - * Here we temporarily switch to 16 colour planar mode, to simply - * copy the font-info - * - * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly! - */ -#if 0 - hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */ -#endif - - hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ - hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ - hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ - -#if SAVE_FONT1 - if (hwp->FontInfo1 || (hwp->FontInfo1 = xalloc(FONT_AMOUNT))) { - hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */ - hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */ - slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT); - } -#endif /* SAVE_FONT1 */ -#if SAVE_FONT2 - if (hwp->FontInfo2 || (hwp->FontInfo2 = xalloc(FONT_AMOUNT))) { - hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */ - hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */ - slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT); - } -#endif /* SAVE_FONT2 */ -#if SAVE_TEXT - if (hwp->TextInfo || (hwp->TextInfo = xalloc(2 * TEXT_AMOUNT))) { - hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */ - hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */ - slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT); - hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */ - hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */ - slowbcopy_frombus(hwp->Base, - (unsigned char *)hwp->TextInfo + TEXT_AMOUNT, TEXT_AMOUNT); - } -#endif /* SAVE_TEXT */ - - /* Restore clobbered registers */ - hwp->writeAttr(hwp, 0x10, attr10); - hwp->writeSeq(hwp, 0x02, seq2); - hwp->writeSeq(hwp, 0x04, seq4); - hwp->writeGr(hwp, 0x04, gr4); - hwp->writeGr(hwp, 0x05, gr5); - hwp->writeGr(hwp, 0x06, gr6); - hwp->writeMiscOut(hwp, miscOut); - hwp->IOBase = savedIOBase; - - vgaHWBlankScreen(scrninfp, TRUE); - - if (doMap) - vgaHWUnmapMem(scrninfp); - -#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */ -} - -void -vgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save) -{ - vgaHWPtr hwp = VGAHWPTR(scrninfp); - int i; - - save->MiscOutReg = hwp->readMiscOut(hwp); - if (save->MiscOutReg & 0x01) - hwp->IOBase = VGA_IOBASE_COLOR; - else - hwp->IOBase = VGA_IOBASE_MONO; - - for (i = 0; i < save->numCRTC; i++) { - save->CRTC[i] = hwp->readCrtc(hwp, i); - DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]); - } - - hwp->enablePalette(hwp); - for (i = 0; i < save->numAttribute; i++) { - save->Attribute[i] = hwp->readAttr(hwp, i); - DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]); - } - hwp->disablePalette(hwp); - - for (i = 0; i < save->numGraphics; i++) { - save->Graphics[i] = hwp->readGr(hwp, i); - DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]); - } - - for (i = 1; i < save->numSequencer; i++) { - save->Sequencer[i] = hwp->readSeq(hwp, i); - DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]); - } -} - - -void -vgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save) -{ - vgaHWPtr hwp = VGAHWPTR(scrninfp); - Bool readError = FALSE; - int i; - -#ifdef NEED_SAVED_CMAP - /* - * Some ET4000 chips from 1991 have a HW bug that prevents the reading - * of the color lookup table. Mask rev 9042EAI is known to have this bug. - * - * If the colourmap is not readable, we set the saved map to a default - * map (taken from Ferraro's "Programmer's Guide to the EGA and VGA - * Cards" 2nd ed). - */ - - /* Only save it once */ - if (hwp->cmapSaved) - return; - -#if 0 - hwp->enablePalette(hwp); -#endif - - hwp->writeDacMask(hwp, 0xFF); - - /* - * check if we can read the lookup table - */ - hwp->writeDacReadAddr(hwp, 0x00); - for (i = 0; i < 6; i++) { - save->DAC[i] = hwp->readDacData(hwp); - switch (i % 3) { - case 0: - DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]); - break; - case 1: - DebugF("0x%02x, ", save->DAC[i]); - break; - case 2: - DebugF("0x%02x\n", save->DAC[i]); - } - } - - /* - * Check if we can read the palette - - * use foreground color to prevent flashing. - */ - hwp->writeDacWriteAddr(hwp, 0x01); - for (i = 3; i < 6; i++) - hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK); - hwp->writeDacReadAddr(hwp, 0x01); - for (i = 3; i < 6; i++) { - if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK)) - readError = TRUE; - } - hwp->writeDacWriteAddr(hwp, 0x01); - for (i = 3; i < 6; i++) - hwp->writeDacData(hwp, save->DAC[i]); - - if (readError) { - /* - * save the default lookup table - */ - memmove(save->DAC, defaultDAC, 768); - xf86DrvMsg(scrninfp->scrnIndex, X_WARNING, - "Cannot read colourmap from VGA. Will restore with default\n"); - } else { - /* save the colourmap */ - hwp->writeDacReadAddr(hwp, 0x02); - for (i = 6; i < 768; i++) { - save->DAC[i] = hwp->readDacData(hwp); - DACDelay(hwp); - switch (i % 3) { - case 0: - DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]); - break; - case 1: - DebugF("0x%02x, ", save->DAC[i]); - break; - case 2: - DebugF("0x%02x\n", save->DAC[i]); - } - } - } - - hwp->disablePalette(hwp); - hwp->cmapSaved = TRUE; -#endif -} - -/* - * vgaHWSave -- - * save the current VGA state - */ - -void -vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags) -{ - if (save == NULL) - return; - - if (flags & VGA_SR_CMAP) - vgaHWSaveColormap(scrninfp, save); - - if (flags & VGA_SR_MODE) - vgaHWSaveMode(scrninfp, save); - - if (flags & VGA_SR_FONTS) - vgaHWSaveFonts(scrninfp, save); -} - - -/* - * vgaHWInit -- - * Handle the initialization, etc. of a screen. - * Return FALSE on failure. - */ - -Bool -vgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode) -{ - unsigned int i; - vgaHWPtr hwp; - vgaRegPtr regp; - int depth = scrninfp->depth; - - /* - * make sure the vgaHWRec is allocated - */ - if (!vgaHWGetHWRec(scrninfp)) - return FALSE; - hwp = VGAHWPTR(scrninfp); - regp = &hwp->ModeReg; - - /* - * compute correct Hsync & Vsync polarity - */ - if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) - && (mode->Flags & (V_PVSYNC | V_NVSYNC))) - { - regp->MiscOutReg = 0x23; - if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40; - if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80; - } - else - { - int VDisplay = mode->VDisplay; - if (mode->Flags & V_DBLSCAN) - VDisplay *= 2; - if (mode->VScan > 1) - VDisplay *= mode->VScan; - if (VDisplay < 400) - regp->MiscOutReg = 0xA3; /* +hsync -vsync */ - else if (VDisplay < 480) - regp->MiscOutReg = 0x63; /* -hsync +vsync */ - else if (VDisplay < 768) - regp->MiscOutReg = 0xE3; /* -hsync -vsync */ - else - regp->MiscOutReg = 0x23; /* +hsync +vsync */ - } - - regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2; - - /* - * Time Sequencer - */ - if (depth == 4) - regp->Sequencer[0] = 0x02; - else - regp->Sequencer[0] = 0x00; - if (mode->Flags & V_CLKDIV2) - regp->Sequencer[1] = 0x09; - else - regp->Sequencer[1] = 0x01; - if (depth == 1) - regp->Sequencer[2] = 1 << BIT_PLANE; - else - regp->Sequencer[2] = 0x0F; - regp->Sequencer[3] = 0x00; /* Font select */ - if (depth < 8) - regp->Sequencer[4] = 0x06; /* Misc */ - else - regp->Sequencer[4] = 0x0E; /* Misc */ - - /* - * CRTC Controller - */ - regp->CRTC[0] = (mode->CrtcHTotal >> 3) - 5; - regp->CRTC[1] = (mode->CrtcHDisplay >> 3) - 1; - regp->CRTC[2] = (mode->CrtcHBlankStart >> 3) - 1; - regp->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; - i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F); - if (i < 0x80) - regp->CRTC[3] |= i; - regp->CRTC[4] = (mode->CrtcHSyncStart >> 3); - regp->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) - | (((mode->CrtcHSyncEnd >> 3)) & 0x1F); - regp->CRTC[6] = (mode->CrtcVTotal - 2) & 0xFF; - regp->CRTC[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8) - | (((mode->CrtcVDisplay - 1) & 0x100) >> 7) - | ((mode->CrtcVSyncStart & 0x100) >> 6) - | (((mode->CrtcVBlankStart - 1) & 0x100) >> 5) - | 0x10 - | (((mode->CrtcVTotal - 2) & 0x200) >> 4) - | (((mode->CrtcVDisplay - 1) & 0x200) >> 3) - | ((mode->CrtcVSyncStart & 0x200) >> 2); - regp->CRTC[8] = 0x00; - regp->CRTC[9] = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40; - if (mode->Flags & V_DBLSCAN) - regp->CRTC[9] |= 0x80; - if (mode->VScan >= 32) - regp->CRTC[9] |= 0x1F; - else if (mode->VScan > 1) - regp->CRTC[9] |= mode->VScan - 1; - regp->CRTC[10] = 0x00; - regp->CRTC[11] = 0x00; - regp->CRTC[12] = 0x00; - regp->CRTC[13] = 0x00; - regp->CRTC[14] = 0x00; - regp->CRTC[15] = 0x00; - regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF; - regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20; - regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF; - regp->CRTC[19] = scrninfp->displayWidth >> 4; /* just a guess */ - regp->CRTC[20] = 0x00; - regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF; - regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; - if (depth < 8) - regp->CRTC[23] = 0xE3; - else - regp->CRTC[23] = 0xC3; - regp->CRTC[24] = 0xFF; - - vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO); - vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO); - - /* - * Theory resumes here.... - */ - - /* - * Graphics Display Controller - */ - regp->Graphics[0] = 0x00; - regp->Graphics[1] = 0x00; - regp->Graphics[2] = 0x00; - regp->Graphics[3] = 0x00; - if (depth == 1) { - regp->Graphics[4] = BIT_PLANE; - regp->Graphics[5] = 0x00; - } else { - regp->Graphics[4] = 0x00; - if (depth == 4) - regp->Graphics[5] = 0x02; - else - regp->Graphics[5] = 0x40; - } - regp->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */ - regp->Graphics[7] = 0x0F; - regp->Graphics[8] = 0xFF; - - if (depth == 1) { - /* Initialise the Mono map according to which bit-plane gets used */ - - Bool flipPixels = xf86GetFlipPixels(); - - for (i=0; i<16; i++) - if (((i & (1 << BIT_PLANE)) != 0) != flipPixels) - regp->Attribute[i] = WHITE_VALUE; - else - regp->Attribute[i] = BLACK_VALUE; - - regp->Attribute[16] = 0x01; /* -VGA2- */ /* wrong for the ET4000 */ - if (!hwp->ShowOverscan) - regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */ - } else { - regp->Attribute[0] = 0x00; /* standard colormap translation */ - regp->Attribute[1] = 0x01; - regp->Attribute[2] = 0x02; - regp->Attribute[3] = 0x03; - regp->Attribute[4] = 0x04; - regp->Attribute[5] = 0x05; - regp->Attribute[6] = 0x06; - regp->Attribute[7] = 0x07; - regp->Attribute[8] = 0x08; - regp->Attribute[9] = 0x09; - regp->Attribute[10] = 0x0A; - regp->Attribute[11] = 0x0B; - regp->Attribute[12] = 0x0C; - regp->Attribute[13] = 0x0D; - regp->Attribute[14] = 0x0E; - regp->Attribute[15] = 0x0F; - if (depth == 4) - regp->Attribute[16] = 0x81; /* wrong for the ET4000 */ - else - regp->Attribute[16] = 0x41; /* wrong for the ET4000 */ - /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */ - } - regp->Attribute[18] = 0x0F; - regp->Attribute[19] = 0x00; - regp->Attribute[20] = 0x00; - - return(TRUE); -} - - /* - * OK, so much for theory. Now, let's deal with the >real< world... - * - * The above CRTC settings are precise in theory, except that many, if not - * most, VGA clones fail to reset the blanking signal when the character or - * line counter reaches [HV]Total. In this case, the signal is only - * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as - * the case may be) at the start of the >next< scanline or frame, which - * means only part of the screen shows. This affects how null overscans - * are to be implemented on such adapters. - * - * Henceforth, VGA cores that implement this broken, but unfortunately - * common, behaviour are to be designated as KGA's, in honour of Koen - * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion - * a series of events that led to the discovery of this problem. - * - * Some VGA's are KGA's only in the horizontal, or only in the vertical, - * some in both, others in neither. Don't let anyone tell you there is - * such a thing as a VGA "standard"... And, thank the Creator for the fact - * that Hilbert spaces are not yet implemented in this industry. - * - * The following implements a trick suggested by David Dawes. This sets - * [HV]BlankEnd to zero if the blanking interval does not already contain a - * 0-point, and decrements it by one otherwise. In the latter case, this - * will produce a left and/or top overscan which the colourmap code will - * (still) need to ensure is as close to black as possible. This will make - * the behaviour consistent across all chipsets, while allowing all - * chipsets to display the entire screen. Non-KGA drivers can ignore the - * following in their own copy of this code. - * - * -- TSI @ UQV, 1998.08.21 - */ - -CARD32 -vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits, - unsigned int Flags) -{ - int nExtBits = (nBits < 6) ? 0 : nBits - 6; - CARD32 ExtBits; - CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6; - - regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) - | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F); - regp->CRTC[5] = (regp->CRTC[5] & ~0x80) - | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2); - ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask; - - /* First the horizontal case */ - if ((Flags & KGA_FIX_OVERSCAN) - && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) - { - int i = (regp->CRTC[3] & 0x1F) - | ((regp->CRTC[5] & 0x80) >> 2) - | ExtBits; - if (Flags & KGA_ENABLE_ON_ZERO) { - if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1) - & (0x3F | ExtBitMask))) - && (mode->CrtcHBlankEnd == mode->CrtcHTotal)) - i = 0; - } else if (Flags & KGA_BE_TOT_DEC) - i--; - regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F); - regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80); - ExtBits = i & ExtBitMask; - } - return ExtBits >> 6; -} - - /* - * The vertical case is a little trickier. Some VGA's ignore bit 0x80 of - * CRTC[22]. Also, in some cases, a zero CRTC[22] will still blank the - * very first scanline in a double- or multi-scanned mode. This last case - * needs further investigation. - */ -CARD32 -vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits, - unsigned int Flags) -{ - CARD32 ExtBits; - CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8); - CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8; - /* If width is not known nBits should be 0. In this - * case BitMask is set to 0 so we can check for it. */ - CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1); - int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF; - regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; - ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask; - - if ((Flags & KGA_FIX_OVERSCAN) - && (mode->CrtcVBlankEnd == mode->CrtcVTotal)) - /* Null top overscan */ - { - int i = regp->CRTC[22] | ExtBits; - if (Flags & KGA_ENABLE_ON_ZERO) { - if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask))) - || ((i > VBlankStart) && /* 8-bit case */ - ((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */ - !(regp->CRTC[9] & 0x9F)) /* 1 scanline/row */ - i = 0; - else - i = (i - 1); - } else if (Flags & KGA_BE_TOT_DEC) - i = (i - 1); - - regp->CRTC[22] = i & 0xFF; - ExtBits = i & 0xFF00; - } - return ExtBits >> 8; -} - -/* - * these are some more hardware specific helpers, formerly in vga.c - */ -static void -vgaHWGetHWRecPrivate(void) -{ - if (vgaHWPrivateIndex < 0) - vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); - return; -} - - -static void -vgaHWFreeRegs(vgaRegPtr regp) -{ - if (regp->CRTC) - xfree (regp->CRTC); - - regp->CRTC = - regp->Sequencer = - regp->Graphics = - regp->Attribute = NULL; - - regp->numCRTC = - regp->numSequencer = - regp->numGraphics = - regp->numAttribute = 0; -} - - - -static Bool -vgaHWAllocRegs(vgaRegPtr regp) -{ - unsigned char *buf; - - if ((regp->numCRTC + regp->numSequencer + regp->numGraphics + - regp->numAttribute) == 0) - return FALSE; - - buf = xcalloc(regp->numCRTC + - regp->numSequencer + - regp->numGraphics + - regp->numAttribute, 1); - if (!buf) - return FALSE; - - regp->CRTC = buf; - regp->Sequencer = regp->CRTC + regp->numCRTC; - regp->Graphics = regp->Sequencer + regp->numSequencer; - regp->Attribute = regp->Graphics + regp->numGraphics; - - return TRUE; -} - - -Bool -vgaHWAllocDefaultRegs(vgaRegPtr regp) -{ - regp->numCRTC = VGA_NUM_CRTC; - regp->numSequencer = VGA_NUM_SEQ; - regp->numGraphics = VGA_NUM_GFX; - regp->numAttribute = VGA_NUM_ATTR; - - return vgaHWAllocRegs(regp); -} - - -Bool -vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer, - int numGraphics, int numAttribute) -{ -#define VGAHWMINNUM(regtype) \ - ((newMode.num##regtype < regp->num##regtype) ? \ - (newMode.num##regtype) : (regp->num##regtype)) -#define VGAHWCOPYREGSET(regtype) \ - memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype)) - - vgaRegRec newMode, newSaved; - vgaRegPtr regp; - - regp = &VGAHWPTR(scrp)->ModeReg; - memcpy (&newMode, regp, sizeof(vgaRegRec)); - - /* allocate space for new registers */ - - regp = &newMode; - regp->numCRTC = numCRTC; - regp->numSequencer = numSequencer; - regp->numGraphics = numGraphics; - regp->numAttribute = numAttribute; - if (!vgaHWAllocRegs(regp)) - return FALSE; - - regp = &VGAHWPTR(scrp)->SavedReg; - memcpy (&newSaved, regp, sizeof(vgaRegRec)); - - regp = &newSaved; - regp->numCRTC = numCRTC; - regp->numSequencer = numSequencer; - regp->numGraphics = numGraphics; - regp->numAttribute = numAttribute; - if (!vgaHWAllocRegs(regp)) { - vgaHWFreeRegs(&newMode); - return FALSE; - } - - /* allocations succeeded, copy register data into new space */ - - regp = &VGAHWPTR(scrp)->ModeReg; - VGAHWCOPYREGSET(CRTC); - VGAHWCOPYREGSET(Sequencer); - VGAHWCOPYREGSET(Graphics); - VGAHWCOPYREGSET(Attribute); - - regp = &VGAHWPTR(scrp)->SavedReg; - VGAHWCOPYREGSET(CRTC); - VGAHWCOPYREGSET(Sequencer); - VGAHWCOPYREGSET(Graphics); - VGAHWCOPYREGSET(Attribute); - - /* free old register arrays */ - - regp = &VGAHWPTR(scrp)->ModeReg; - vgaHWFreeRegs(regp); - memcpy(regp, &newMode, sizeof(vgaRegRec)); - - regp = &VGAHWPTR(scrp)->SavedReg; - vgaHWFreeRegs(regp); - memcpy(regp, &newSaved, sizeof(vgaRegRec)); - - return TRUE; - -#undef VGAHWMINNUM -#undef VGAHWCOPYREGSET -} - - -Bool -vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src) -{ - vgaHWFreeRegs(dst); - - memcpy(dst, src, sizeof(vgaRegRec)); - - if (!vgaHWAllocRegs(dst)) - return FALSE; - - memcpy(dst->CRTC, src->CRTC, src->numCRTC); - memcpy(dst->Sequencer, src->Sequencer, src->numSequencer); - memcpy(dst->Graphics, src->Graphics, src->numGraphics); - memcpy(dst->Attribute, src->Attribute, src->numAttribute); - - return TRUE; -} - - -Bool -vgaHWGetHWRec(ScrnInfoPtr scrp) -{ - vgaRegPtr regp; - vgaHWPtr hwp; - int i; - - /* - * Let's make sure that the private exists and allocate one. - */ - vgaHWGetHWRecPrivate(); - /* - * New privates are always set to NULL, so we can check if the allocation - * has already been done. - */ - if (VGAHWPTR(scrp)) - return TRUE; - hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1); - regp = &VGAHWPTR(scrp)->ModeReg; - - if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) || - (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) { - xfree(hwp); - return FALSE; - } - - if (scrp->bitsPerPixel == 1) { - rgb blackColour = scrp->display->blackColour, - whiteColour = scrp->display->whiteColour; - - if (blackColour.red > 0x3F) blackColour.red = 0x3F; - if (blackColour.green > 0x3F) blackColour.green = 0x3F; - if (blackColour.blue > 0x3F) blackColour.blue = 0x3F; - - if (whiteColour.red > 0x3F) whiteColour.red = 0x3F; - if (whiteColour.green > 0x3F) whiteColour.green = 0x3F; - if (whiteColour.blue > 0x3F) whiteColour.blue = 0x3F; - - if ((blackColour.red == whiteColour.red ) && - (blackColour.green == whiteColour.green) && - (blackColour.blue == whiteColour.blue )) { - blackColour.red ^= 0x3F; - blackColour.green ^= 0x3F; - blackColour.blue ^= 0x3F; - } - - /* - * initialize default colormap for monochrome - */ - for (i=0; i<3; i++) regp->DAC[i] = 0x00; - for (i=3; i<768; i++) regp->DAC[i] = 0x3F; - i = BLACK_VALUE * 3; - regp->DAC[i++] = blackColour.red; - regp->DAC[i++] = blackColour.green; - regp->DAC[i] = blackColour.blue; - i = WHITE_VALUE * 3; - regp->DAC[i++] = whiteColour.red; - regp->DAC[i++] = whiteColour.green; - regp->DAC[i] = whiteColour.blue; - i = OVERSCAN_VALUE * 3; - regp->DAC[i++] = 0x00; - regp->DAC[i++] = 0x00; - regp->DAC[i] = 0x00; - } else { - /* Set all colours to black */ - for (i=0; i<768; i++) regp->DAC[i] = 0x00; - /* ... and the overscan */ - if (scrp->depth >= 4) - regp->Attribute[OVERSCAN] = 0xFF; - } - if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) { - xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan"); - xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n"); - regp->DAC[765] = 0x3F; - regp->DAC[766] = 0x00; - regp->DAC[767] = 0x3F; - regp->Attribute[OVERSCAN] = 0xFF; - hwp->ShowOverscan = TRUE; - } else - hwp->ShowOverscan = FALSE; - - hwp->paletteEnabled = FALSE; - hwp->cmapSaved = FALSE; - hwp->MapSize = 0; - hwp->pScrn = scrp; - - /* Initialise the function pointers with the standard VGA versions */ - vgaHWSetStdFuncs(hwp); - - hwp->PIOOffset = scrp->domainIOBase; - hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]); - - return TRUE; -} - - -void -vgaHWFreeHWRec(ScrnInfoPtr scrp) -{ - if (vgaHWPrivateIndex >= 0) { - vgaHWPtr hwp = VGAHWPTR(scrp); - - if (!hwp) - return; - - xfree(hwp->FontInfo1); - xfree(hwp->FontInfo2); - xfree(hwp->TextInfo); - - vgaHWFreeRegs (&hwp->ModeReg); - vgaHWFreeRegs (&hwp->SavedReg); - - xfree(hwp); - VGAHWPTRLVAL(scrp) = NULL; - } -} - - -Bool -vgaHWMapMem(ScrnInfoPtr scrp) -{ - vgaHWPtr hwp = VGAHWPTR(scrp); - int scr_index = scrp->scrnIndex; - - if (hwp->Base) - return TRUE; - - /* If not set, initialise with the defaults */ - if (hwp->MapSize == 0) - hwp->MapSize = VGA_DEFAULT_MEM_SIZE; - if (hwp->MapPhys == 0) - hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR; - - /* - * Map as VIDMEM_MMIO_32BIT because WC - * is bad when there is page flipping. - * XXX This is not correct but we do it - * for now. - */ - DebugF("Mapping VGAMem\n"); - hwp->Base = xf86MapDomainMemory(scr_index, VIDMEM_MMIO_32BIT, hwp->dev, - hwp->MapPhys, hwp->MapSize); - return hwp->Base != NULL; -} - - -void -vgaHWUnmapMem(ScrnInfoPtr scrp) -{ - vgaHWPtr hwp = VGAHWPTR(scrp); - int scr_index = scrp->scrnIndex; - - if (hwp->Base == NULL) - return; - - DebugF("Unmapping VGAMem\n"); - xf86UnMapVidMem(scr_index, hwp->Base, hwp->MapSize); - hwp->Base = NULL; -} - -int -vgaHWGetIndex(void) -{ - return vgaHWPrivateIndex; -} - - -void -vgaHWGetIOBase(vgaHWPtr hwp) -{ - hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ? - VGA_IOBASE_COLOR : VGA_IOBASE_MONO; - xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3, - "vgaHWGetIOBase: hwp->IOBase is 0x%04x, hwp->PIOOffset is 0x%04lx\n", - hwp->IOBase, hwp->PIOOffset); -} - - -void -vgaHWLock(vgaHWPtr hwp) -{ - /* Protect CRTC[0-7] */ - hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80); -} - -void -vgaHWUnlock(vgaHWPtr hwp) -{ - /* Unprotect CRTC[0-7] */ - hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80); -} - - -void -vgaHWEnable(vgaHWPtr hwp) -{ - hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01); -} - - -void -vgaHWDisable(vgaHWPtr hwp) -{ - hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01); -} - - -static void -vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, - VisualPtr pVisual) -{ - vgaHWPtr hwp = VGAHWPTR(pScrn); - int i, index; - - for (i = 0; i < numColors; i++) { - index = indices[i]; - hwp->writeDacWriteAddr(hwp, index); - DACDelay(hwp); - hwp->writeDacData(hwp, colors[index].red); - DACDelay(hwp); - hwp->writeDacData(hwp, colors[index].green); - DACDelay(hwp); - hwp->writeDacData(hwp, colors[index].blue); - DACDelay(hwp); - } - - /* This shouldn't be necessary, but we'll play safe. */ - hwp->disablePalette(hwp); -} - - -static void -vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan) -{ - vgaHWPtr hwp = VGAHWPTR(pScrn); - - if (overscan < 0 || overscan > 255) - return; - - hwp->enablePalette(hwp); - hwp->writeAttr(hwp, OVERSCAN, overscan); - -#ifdef DEBUGOVERSCAN - { - int ov = hwp->readAttr(hwp, OVERSCAN); - int red, green, blue; - - hwp->writeDacReadAddr(hwp, ov); - red = hwp->readDacData(hwp); - green = hwp->readDacData(hwp); - blue = hwp->readDacData(hwp); - ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n", - ov, red, green, blue); - } -#endif - - hwp->disablePalette(hwp); -} - - -Bool -vgaHWHandleColormaps(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if (pScrn->depth > 1 && pScrn->depth <= 8) { - return xf86HandleColormaps(pScreen, 1 << pScrn->depth, - pScrn->rgbBits, vgaHWLoadPalette, - pScrn->depth > 4 ? vgaHWSetOverscan : NULL, - CMAP_RELOAD_ON_MODE_SWITCH); - } - return TRUE; -} - -/* ----------------------- DDC support ------------------------*/ -/* - * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total - * to read out EDID at a faster rate. Allowed maximum is 25kHz with - * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen - * readback, enable access to cr00-cr07. - */ - -/* vertical timings */ -#define DISPLAY_END 0x04 -#define BLANK_START DISPLAY_END -#define SYNC_START BLANK_START -#define SYNC_END 0x09 -#define BLANK_END SYNC_END -#define V_TOTAL BLANK_END -/* this function doesn't have to be reentrant for our purposes */ -struct _vgaDdcSave { - unsigned char cr03; - unsigned char cr06; - unsigned char cr07; - unsigned char cr09; - unsigned char cr10; - unsigned char cr11; - unsigned char cr12; - unsigned char cr15; - unsigned char cr16; - unsigned char msr; -}; - -void -vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) -{ - vgaHWPtr hwp = VGAHWPTR(pScrn); - unsigned char tmp; - struct _vgaDdcSave* save; - switch (speed) { - case DDC_FAST: - - if (hwp->ddc != NULL) break; - hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave),1); - save = (struct _vgaDdcSave *)hwp->ddc; - /* Lightpen register disable - allow access to cr10 & 11; just in case */ - save->cr03 = hwp->readCrtc(hwp, 0x03); - hwp->writeCrtc(hwp,0x03,(save->cr03 |0x80)); - save->cr12 = hwp->readCrtc(hwp, 0x12); - hwp->writeCrtc(hwp,0x12,DISPLAY_END); - save->cr15 = hwp->readCrtc(hwp, 0x15); - hwp->writeCrtc(hwp,0x15,BLANK_START); - save->cr10 = hwp->readCrtc(hwp, 0x10); - hwp->writeCrtc(hwp,0x10,SYNC_START); - save->cr11 = hwp->readCrtc(hwp, 0x11); - /* unprotect group 1 registers; just in case ...*/ - hwp->writeCrtc(hwp,0x11,((save->cr11 & 0x70) | SYNC_END)); - save->cr16 = hwp->readCrtc(hwp, 0x16); - hwp->writeCrtc(hwp,0x16,BLANK_END); - save->cr06 = hwp->readCrtc(hwp, 0x06); - hwp->writeCrtc(hwp,0x06,V_TOTAL); - /* all values have less than 8 bit - mask out 9th and 10th bits */ - save->cr09 = hwp->readCrtc(hwp, 0x09); - hwp->writeCrtc(hwp,0x09,(save->cr09 &0xDF)); - save->cr07 = hwp->readCrtc(hwp, 0x07); - hwp->writeCrtc(hwp,0x07,(save->cr07 &0x10)); - /* vsync polarity negativ & ensure a 25MHz clock */ - save->msr = hwp->readMiscOut(hwp); - hwp->writeMiscOut(hwp,((save->msr & 0xF3) | 0x80)); - break; - case DDC_SLOW: - if (hwp->ddc == NULL) break; - save = (struct _vgaDdcSave *)hwp->ddc; - hwp->writeMiscOut(hwp,save->msr); - hwp->writeCrtc(hwp,0x07,save->cr07); - tmp = hwp->readCrtc(hwp, 0x09); - hwp->writeCrtc(hwp,0x09,((save->cr09 & 0x20) | (tmp & 0xDF))); - hwp->writeCrtc(hwp,0x06,save->cr06); - hwp->writeCrtc(hwp,0x16,save->cr16); - hwp->writeCrtc(hwp,0x11,save->cr11); - hwp->writeCrtc(hwp,0x10,save->cr10); - hwp->writeCrtc(hwp,0x15,save->cr15); - hwp->writeCrtc(hwp,0x12,save->cr12); - hwp->writeCrtc(hwp,0x03,save->cr03); - xfree(save); - hwp->ddc = NULL; - break; - default: - break; - } -} - -DDC1SetSpeedProc -vgaHWddc1SetSpeedWeak(void) -{ - return vgaHWddc1SetSpeed; -} - -SaveScreenProcPtr vgaHWSaveScreenWeak(void) -{ - return vgaHWSaveScreen; -} + +/* + * + * Copyright 1991-1999 by The XFree86 Project, Inc. + * + * Loosely based on code bearing the following copyright: + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + */ + +#define _NEED_SYSI86 + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include "misc.h" + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" + +#include "compiler.h" + +#include "xf86cmap.h" + +#include "Pci.h" + +#ifndef SAVE_FONT1 +#define SAVE_FONT1 1 +#endif + +/* + * These used to be OS-specific, which made this module have an undesirable + * OS dependency. Define them by default for all platforms. + */ +#ifndef NEED_SAVED_CMAP +#define NEED_SAVED_CMAP +#endif +#ifndef SAVE_TEXT +#define SAVE_TEXT 1 +#endif +#ifndef SAVE_FONT2 +#define SAVE_FONT2 1 +#endif + +/* bytes per plane to save for text */ +#define TEXT_AMOUNT 16384 + +/* bytes per plane to save for font data */ +#define FONT_AMOUNT (8*8192) + +#if 0 +/* Override all of these for now */ +#undef SAVE_FONT1 +#define SAVE_FONT1 1 +#undef SAVE_FONT2 +#define SAVE_FONT2 1 +#undef SAVE_TEST +#define SAVE_TEST 1 +#undef FONT_AMOUNT +#define FONT_AMOUNT 65536 +#undef TEXT_AMOUNT +#define TEXT_AMOUNT 65536 +#endif + +/* DAC indices for white and black */ +#define WHITE_VALUE 0x3F +#define BLACK_VALUE 0x00 +#define OVERSCAN_VALUE 0x01 + + +/* Use a private definition of this here */ +#undef VGAHWPTR +#define VGAHWPTRLVAL(p) (p)->privates[vgaHWPrivateIndex].ptr +#define VGAHWPTR(p) ((vgaHWPtr)(VGAHWPTRLVAL(p))) + +static int vgaHWPrivateIndex = -1; + +#define DAC_TEST_MASK 0x3F + +#ifdef NEED_SAVED_CMAP +/* This default colourmap is used only when it can't be read from the VGA */ + +static CARD8 defaultDAC[768] = +{ + 0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42, + 42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42, + 21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63, + 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63, + 0, 0, 0, 5, 5, 5, 8, 8, 8, 11, 11, 11, + 14, 14, 14, 17, 17, 17, 20, 20, 20, 24, 24, 24, + 28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40, + 45, 45, 45, 50, 50, 50, 56, 56, 56, 63, 63, 63, + 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 63, + 63, 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, + 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, + 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 0, + 0, 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, + 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, + 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 63, + 63, 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, + 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, + 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 31, + 31, 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, + 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, + 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 63, + 63, 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, + 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, + 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 45, + 45, 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, + 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, + 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 28, + 28, 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, + 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, + 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 0, + 0, 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, + 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, + 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 28, + 28, 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, + 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, + 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 14, + 14, 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, + 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, + 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 28, + 28, 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, + 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, + 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 20, + 20, 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, + 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, + 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 16, + 16, 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, + 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, + 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 0, + 0, 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, + 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, + 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 16, + 16, 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, + 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, + 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 8, + 8, 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, + 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, + 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 16, + 16, 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, + 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, + 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 11, + 11, 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, + 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; +#endif /* NEED_SAVED_CMAP */ + +/* + * Standard VGA versions of the register access functions. + */ +static void +stdWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index); + outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET, value); +} + +static CARD8 +stdReadCrtc(vgaHWPtr hwp, CARD8 index) +{ + outb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_INDEX_OFFSET, index); + return inb(hwp->IOBase + hwp->PIOOffset + VGA_CRTC_DATA_OFFSET); +} + +static void +stdWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index); + outb(hwp->PIOOffset + VGA_GRAPH_DATA, value); +} + +static CARD8 +stdReadGr(vgaHWPtr hwp, CARD8 index) +{ + outb(hwp->PIOOffset + VGA_GRAPH_INDEX, index); + return inb(hwp->PIOOffset + VGA_GRAPH_DATA); +} + +static void +stdWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + outb(hwp->PIOOffset + VGA_SEQ_INDEX, index); + outb(hwp->PIOOffset + VGA_SEQ_DATA, value); +} + +static CARD8 +stdReadSeq(vgaHWPtr hwp, CARD8 index) +{ + outb(hwp->PIOOffset + VGA_SEQ_INDEX, index); + return inb(hwp->PIOOffset + VGA_SEQ_DATA); +} + +static CARD8 +stdReadST00(vgaHWPtr hwp) +{ + return inb(hwp->PIOOffset + VGA_IN_STAT_0); +} + +static CARD8 +stdReadST01(vgaHWPtr hwp) +{ + return inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); +} + +static CARD8 +stdReadFCR(vgaHWPtr hwp) +{ + return inb(hwp->PIOOffset + VGA_FEATURE_R); +} + +static void +stdWriteFCR(vgaHWPtr hwp, CARD8 value) +{ + outb(hwp->IOBase + hwp->PIOOffset + VGA_FEATURE_W_OFFSET,value); +} + +static void +stdWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + if (hwp->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); + outb(hwp->PIOOffset + VGA_ATTR_INDEX, index); + outb(hwp->PIOOffset + VGA_ATTR_DATA_W, value); +} + +static CARD8 +stdReadAttr(vgaHWPtr hwp, CARD8 index) +{ + if (hwp->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); + outb(hwp->PIOOffset + VGA_ATTR_INDEX, index); + return inb(hwp->PIOOffset + VGA_ATTR_DATA_R); +} + +static void +stdWriteMiscOut(vgaHWPtr hwp, CARD8 value) +{ + outb(hwp->PIOOffset + VGA_MISC_OUT_W, value); +} + +static CARD8 +stdReadMiscOut(vgaHWPtr hwp) +{ + return inb(hwp->PIOOffset + VGA_MISC_OUT_R); +} + +static void +stdEnablePalette(vgaHWPtr hwp) +{ + (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); + outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x00); + hwp->paletteEnabled = TRUE; +} + +static void +stdDisablePalette(vgaHWPtr hwp) +{ + (void) inb(hwp->IOBase + hwp->PIOOffset + VGA_IN_STAT_1_OFFSET); + outb(hwp->PIOOffset + VGA_ATTR_INDEX, 0x20); + hwp->paletteEnabled = FALSE; +} + +static void +stdWriteDacMask(vgaHWPtr hwp, CARD8 value) +{ + outb(hwp->PIOOffset + VGA_DAC_MASK, value); +} + +static CARD8 +stdReadDacMask(vgaHWPtr hwp) +{ + return inb(hwp->PIOOffset + VGA_DAC_MASK); +} + +static void +stdWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) +{ + outb(hwp->PIOOffset + VGA_DAC_READ_ADDR, value); +} + +static void +stdWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) +{ + outb(hwp->PIOOffset + VGA_DAC_WRITE_ADDR, value); +} + +static void +stdWriteDacData(vgaHWPtr hwp, CARD8 value) +{ + outb(hwp->PIOOffset + VGA_DAC_DATA, value); +} + +static CARD8 +stdReadDacData(vgaHWPtr hwp) +{ + return inb(hwp->PIOOffset + VGA_DAC_DATA); +} + +static CARD8 +stdReadEnable(vgaHWPtr hwp) +{ + return inb(hwp->PIOOffset + VGA_ENABLE); +} + +static void +stdWriteEnable(vgaHWPtr hwp, CARD8 value) +{ + outb(hwp->PIOOffset + VGA_ENABLE, value); +} + +void +vgaHWSetStdFuncs(vgaHWPtr hwp) +{ + hwp->writeCrtc = stdWriteCrtc; + hwp->readCrtc = stdReadCrtc; + hwp->writeGr = stdWriteGr; + hwp->readGr = stdReadGr; + hwp->readST00 = stdReadST00; + hwp->readST01 = stdReadST01; + hwp->readFCR = stdReadFCR; + hwp->writeFCR = stdWriteFCR; + hwp->writeAttr = stdWriteAttr; + hwp->readAttr = stdReadAttr; + hwp->writeSeq = stdWriteSeq; + hwp->readSeq = stdReadSeq; + hwp->writeMiscOut = stdWriteMiscOut; + hwp->readMiscOut = stdReadMiscOut; + hwp->enablePalette = stdEnablePalette; + hwp->disablePalette = stdDisablePalette; + hwp->writeDacMask = stdWriteDacMask; + hwp->readDacMask = stdReadDacMask; + hwp->writeDacWriteAddr = stdWriteDacWriteAddr; + hwp->writeDacReadAddr = stdWriteDacReadAddr; + hwp->writeDacData = stdWriteDacData; + hwp->readDacData = stdReadDacData; + hwp->PIOOffset = 0; + hwp->readEnable = stdReadEnable; + hwp->writeEnable = stdWriteEnable; +} + +/* + * MMIO versions of the register access functions. These require + * hwp->MemBase to be set in such a way that when the standard VGA port + * adderss is added the correct memory address results. + */ + +#define minb(p) MMIO_IN8(hwp->MMIOBase, (hwp->MMIOOffset + (p))) +#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (hwp->MMIOOffset + (p)),(v)) + +static void +mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index); + moutb(hwp->IOBase + VGA_CRTC_DATA_OFFSET, value); +} + +static CARD8 +mmioReadCrtc(vgaHWPtr hwp, CARD8 index) +{ + moutb(hwp->IOBase + VGA_CRTC_INDEX_OFFSET, index); + return minb(hwp->IOBase + VGA_CRTC_DATA_OFFSET); +} + +static void +mmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + moutb(VGA_GRAPH_INDEX, index); + moutb(VGA_GRAPH_DATA, value); +} + +static CARD8 +mmioReadGr(vgaHWPtr hwp, CARD8 index) +{ + moutb(VGA_GRAPH_INDEX, index); + return minb(VGA_GRAPH_DATA); +} + +static void +mmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + moutb(VGA_SEQ_INDEX, index); + moutb(VGA_SEQ_DATA, value); +} + +static CARD8 +mmioReadSeq(vgaHWPtr hwp, CARD8 index) +{ + moutb(VGA_SEQ_INDEX, index); + return minb(VGA_SEQ_DATA); +} + +static CARD8 +mmioReadST00(vgaHWPtr hwp) +{ + return minb(VGA_IN_STAT_0); +} + +static CARD8 +mmioReadST01(vgaHWPtr hwp) +{ + return minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); +} + +static CARD8 +mmioReadFCR(vgaHWPtr hwp) +{ + return minb(VGA_FEATURE_R); +} + +static void +mmioWriteFCR(vgaHWPtr hwp, CARD8 value) +{ + moutb(hwp->IOBase + VGA_FEATURE_W_OFFSET,value); +} + +static void +mmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + if (hwp->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); + moutb(VGA_ATTR_INDEX, index); + moutb(VGA_ATTR_DATA_W, value); +} + +static CARD8 +mmioReadAttr(vgaHWPtr hwp, CARD8 index) +{ + if (hwp->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); + moutb(VGA_ATTR_INDEX, index); + return minb(VGA_ATTR_DATA_R); +} + +static void +mmioWriteMiscOut(vgaHWPtr hwp, CARD8 value) +{ + moutb(VGA_MISC_OUT_W, value); +} + +static CARD8 +mmioReadMiscOut(vgaHWPtr hwp) +{ + return minb(VGA_MISC_OUT_R); +} + +static void +mmioEnablePalette(vgaHWPtr hwp) +{ + (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); + moutb(VGA_ATTR_INDEX, 0x00); + hwp->paletteEnabled = TRUE; +} + +static void +mmioDisablePalette(vgaHWPtr hwp) +{ + (void) minb(hwp->IOBase + VGA_IN_STAT_1_OFFSET); + moutb(VGA_ATTR_INDEX, 0x20); + hwp->paletteEnabled = FALSE; +} + +static void +mmioWriteDacMask(vgaHWPtr hwp, CARD8 value) +{ + moutb(VGA_DAC_MASK, value); +} + +static CARD8 +mmioReadDacMask(vgaHWPtr hwp) +{ + return minb(VGA_DAC_MASK); +} + +static void +mmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) +{ + moutb(VGA_DAC_READ_ADDR, value); +} + +static void +mmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) +{ + moutb(VGA_DAC_WRITE_ADDR, value); +} + +static void +mmioWriteDacData(vgaHWPtr hwp, CARD8 value) +{ + moutb(VGA_DAC_DATA, value); +} + +static CARD8 +mmioReadDacData(vgaHWPtr hwp) +{ + return minb(VGA_DAC_DATA); +} + +static CARD8 +mmioReadEnable(vgaHWPtr hwp) +{ + return minb(VGA_ENABLE); +} + +static void +mmioWriteEnable(vgaHWPtr hwp, CARD8 value) +{ + moutb(VGA_ENABLE, value); +} + +void +vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset) +{ + hwp->writeCrtc = mmioWriteCrtc; + hwp->readCrtc = mmioReadCrtc; + hwp->writeGr = mmioWriteGr; + hwp->readGr = mmioReadGr; + hwp->readST00 = mmioReadST00; + hwp->readST01 = mmioReadST01; + hwp->readFCR = mmioReadFCR; + hwp->writeFCR = mmioWriteFCR; + hwp->writeAttr = mmioWriteAttr; + hwp->readAttr = mmioReadAttr; + hwp->writeSeq = mmioWriteSeq; + hwp->readSeq = mmioReadSeq; + hwp->writeMiscOut = mmioWriteMiscOut; + hwp->readMiscOut = mmioReadMiscOut; + hwp->enablePalette = mmioEnablePalette; + hwp->disablePalette = mmioDisablePalette; + hwp->writeDacMask = mmioWriteDacMask; + hwp->readDacMask = mmioReadDacMask; + hwp->writeDacWriteAddr = mmioWriteDacWriteAddr; + hwp->writeDacReadAddr = mmioWriteDacReadAddr; + hwp->writeDacData = mmioWriteDacData; + hwp->readDacData = mmioReadDacData; + hwp->MMIOBase = base; + hwp->MMIOOffset = offset; + hwp->readEnable = mmioReadEnable; + hwp->writeEnable = mmioWriteEnable; +} + +/* + * vgaHWProtect -- + * Protect VGA registers and memory from corruption during loads. + */ + +void +vgaHWProtect(ScrnInfoPtr pScrn, Bool on) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + + unsigned char tmp; + + if (pScrn->vtSema) { + if (on) { + /* + * Turn off screen and disable sequencer. + */ + tmp = hwp->readSeq(hwp, 0x01); + + vgaHWSeqReset(hwp, TRUE); /* start synchronous reset */ + hwp->writeSeq(hwp, 0x01, tmp | 0x20); /* disable the display */ + + hwp->enablePalette(hwp); + } else { + /* + * Reenable sequencer, then turn on screen. + */ + + tmp = hwp->readSeq(hwp, 0x01); + + hwp->writeSeq(hwp, 0x01, tmp & ~0x20); /* reenable display */ + vgaHWSeqReset(hwp, FALSE); /* clear synchronousreset */ + + hwp->disablePalette(hwp); + } + } +} + +vgaHWProtectProc *vgaHWProtectWeak(void) { + return vgaHWProtect; +} + +/* + * vgaHWBlankScreen -- blank the screen. + */ + +void +vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + unsigned char scrn; + + scrn = hwp->readSeq(hwp, 0x01); + + if (on) { + scrn &= ~0x20; /* enable screen */ + } else { + scrn |= 0x20; /* blank screen */ + } + + vgaHWSeqReset(hwp, TRUE); + hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ + vgaHWSeqReset(hwp, FALSE); +} + +vgaHWBlankScreenProc *vgaHWBlankScreenWeak(void) { + return vgaHWBlankScreen; +} + +/* + * vgaHWSaveScreen -- blank the screen. + */ + +Bool +vgaHWSaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = NULL; + Bool on; + + if (pScreen != NULL) + pScrn = xf86Screens[pScreen->myNum]; + + on = xf86IsUnblank(mode); + +#if 0 + if (on) + SetTimeSinceLastInputEvent(); +#endif + + if ((pScrn != NULL) && pScrn->vtSema) { + vgaHWBlankScreen(pScrn, on); + } + return (TRUE); +} + + +/* + * vgaHWDPMSSet -- Sets VESA Display Power Management Signaling (DPMS) Mode + * + * This generic VGA function can only set the Off and On modes. If the + * Standby and Suspend modes are to be supported, a chip specific replacement + * for this function must be written. + */ + +void +vgaHWDPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) +{ + unsigned char seq1 = 0, crtc17 = 0; + vgaHWPtr hwp = VGAHWPTR(pScrn); + + if (!pScrn->vtSema) return; + + switch (PowerManagementMode) { + case DPMSModeOn: + /* Screen: On; HSync: On, VSync: On */ + seq1 = 0x00; + crtc17 = 0x80; + break; + case DPMSModeStandby: + /* Screen: Off; HSync: Off, VSync: On -- Not Supported */ + seq1 = 0x20; + crtc17 = 0x80; + break; + case DPMSModeSuspend: + /* Screen: Off; HSync: On, VSync: Off -- Not Supported */ + seq1 = 0x20; + crtc17 = 0x80; + break; + case DPMSModeOff: + /* Screen: Off; HSync: Off, VSync: Off */ + seq1 = 0x20; + crtc17 = 0x00; + break; + } + hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */ + seq1 |= hwp->readSeq(hwp, 0x01) & ~0x20; + hwp->writeSeq(hwp, 0x01, seq1); + crtc17 |= hwp->readCrtc(hwp, 0x17) & ~0x80; + usleep(10000); + hwp->writeCrtc(hwp, 0x17, crtc17); + hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */ +} + + +/* + * vgaHWSeqReset + * perform a sequencer reset. + */ + +void +vgaHWSeqReset(vgaHWPtr hwp, Bool start) +{ + if (start) + hwp->writeSeq(hwp, 0x00, 0x01); /* Synchronous Reset */ + else + hwp->writeSeq(hwp, 0x00, 0x03); /* End Reset */ +} + + +void +vgaHWRestoreFonts(ScrnInfoPtr scrninfp, vgaRegPtr restore) +{ +#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 + vgaHWPtr hwp = VGAHWPTR(scrninfp); + int savedIOBase; + unsigned char miscOut, attr10, gr1, gr3, gr4, gr5, gr6, gr8, seq2, seq4; + Bool doMap = FALSE; + + /* If nothing to do, return now */ + if (!hwp->FontInfo1 && !hwp->FontInfo2 && !hwp->TextInfo) + return; + + if (hwp->Base == NULL) { + doMap = TRUE; + if (!vgaHWMapMem(scrninfp)) { + xf86DrvMsg(scrninfp->scrnIndex, X_ERROR, + "vgaHWRestoreFonts: vgaHWMapMem() failed\n"); + return; + } + } + + /* save the registers that are needed here */ + miscOut = hwp->readMiscOut(hwp); + attr10 = hwp->readAttr(hwp, 0x10); + gr1 = hwp->readGr(hwp, 0x01); + gr3 = hwp->readGr(hwp, 0x03); + gr4 = hwp->readGr(hwp, 0x04); + gr5 = hwp->readGr(hwp, 0x05); + gr6 = hwp->readGr(hwp, 0x06); + gr8 = hwp->readGr(hwp, 0x08); + seq2 = hwp->readSeq(hwp, 0x02); + seq4 = hwp->readSeq(hwp, 0x04); + + /* save hwp->IOBase and temporarily set it for colour mode */ + savedIOBase = hwp->IOBase; + hwp->IOBase = VGA_IOBASE_COLOR; + + /* Force into colour mode */ + hwp->writeMiscOut(hwp, miscOut | 0x01); + + vgaHWBlankScreen(scrninfp, FALSE); + + /* + * here we temporarily switch to 16 colour planar mode, to simply + * copy the font-info and saved text. + * + * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly! + */ +#if 0 + hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */ +#endif + + hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ + hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ + hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ + + if (scrninfp->depth == 4) { + /* GJA */ + hwp->writeGr(hwp, 0x03, 0x00); /* don't rotate, write unmodified */ + hwp->writeGr(hwp, 0x08, 0xFF); /* write all bits in a byte */ + hwp->writeGr(hwp, 0x01, 0x00); /* all planes come from CPU */ + } + +#if SAVE_FONT1 + if (hwp->FontInfo1) { + hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */ + hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */ + slowbcopy_tobus(hwp->FontInfo1, hwp->Base, FONT_AMOUNT); + } +#endif + +#if SAVE_FONT2 + if (hwp->FontInfo2) { + hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */ + hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */ + slowbcopy_tobus(hwp->FontInfo2, hwp->Base, FONT_AMOUNT); + } +#endif + +#if SAVE_TEXT + if (hwp->TextInfo) { + hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */ + hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */ + slowbcopy_tobus(hwp->TextInfo, hwp->Base, TEXT_AMOUNT); + hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */ + hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */ + slowbcopy_tobus((unsigned char *)hwp->TextInfo + TEXT_AMOUNT, + hwp->Base, TEXT_AMOUNT); + } +#endif + + vgaHWBlankScreen(scrninfp, TRUE); + + /* restore the registers that were changed */ + hwp->writeMiscOut(hwp, miscOut); + hwp->writeAttr(hwp, 0x10, attr10); + hwp->writeGr(hwp, 0x01, gr1); + hwp->writeGr(hwp, 0x03, gr3); + hwp->writeGr(hwp, 0x04, gr4); + hwp->writeGr(hwp, 0x05, gr5); + hwp->writeGr(hwp, 0x06, gr6); + hwp->writeGr(hwp, 0x08, gr8); + hwp->writeSeq(hwp, 0x02, seq2); + hwp->writeSeq(hwp, 0x04, seq4); + hwp->IOBase = savedIOBase; + + if (doMap) + vgaHWUnmapMem(scrninfp); + +#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */ +} + + +void +vgaHWRestoreMode(ScrnInfoPtr scrninfp, vgaRegPtr restore) +{ + vgaHWPtr hwp = VGAHWPTR(scrninfp); + int i; + + if (restore->MiscOutReg & 0x01) + hwp->IOBase = VGA_IOBASE_COLOR; + else + hwp->IOBase = VGA_IOBASE_MONO; + + hwp->writeMiscOut(hwp, restore->MiscOutReg); + + for (i = 1; i < restore->numSequencer; i++) + hwp->writeSeq(hwp, i, restore->Sequencer[i]); + + /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */ + hwp->writeCrtc(hwp, 17, restore->CRTC[17] & ~0x80); + + for (i = 0; i < restore->numCRTC; i++) + hwp->writeCrtc(hwp, i, restore->CRTC[i]); + + for (i = 0; i < restore->numGraphics; i++) + hwp->writeGr(hwp, i, restore->Graphics[i]); + + hwp->enablePalette(hwp); + for (i = 0; i < restore->numAttribute; i++) + hwp->writeAttr(hwp, i, restore->Attribute[i]); + hwp->disablePalette(hwp); +} + + +void +vgaHWRestoreColormap(ScrnInfoPtr scrninfp, vgaRegPtr restore) +{ + vgaHWPtr hwp = VGAHWPTR(scrninfp); + int i; + +#if 0 + hwp->enablePalette(hwp); +#endif + + hwp->writeDacMask(hwp, 0xFF); + hwp->writeDacWriteAddr(hwp, 0x00); + for (i = 0; i < 768; i++) { + hwp->writeDacData(hwp, restore->DAC[i]); + DACDelay(hwp); + } + + hwp->disablePalette(hwp); +} + + +/* + * vgaHWRestore -- + * restore the VGA state + */ + +void +vgaHWRestore(ScrnInfoPtr scrninfp, vgaRegPtr restore, int flags) +{ + if (flags & VGA_SR_MODE) + vgaHWRestoreMode(scrninfp, restore); + + if (flags & VGA_SR_FONTS) + vgaHWRestoreFonts(scrninfp, restore); + + if (flags & VGA_SR_CMAP) + vgaHWRestoreColormap(scrninfp, restore); +} + +void +vgaHWSaveFonts(ScrnInfoPtr scrninfp, vgaRegPtr save) +{ +#if SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 + vgaHWPtr hwp = VGAHWPTR(scrninfp); + int savedIOBase; + unsigned char miscOut, attr10, gr4, gr5, gr6, seq2, seq4; + Bool doMap = FALSE; + + if (hwp->Base == NULL) { + doMap = TRUE; + if (!vgaHWMapMem(scrninfp)) { + xf86DrvMsg(scrninfp->scrnIndex, X_ERROR, + "vgaHWSaveFonts: vgaHWMapMem() failed\n"); + return; + } + } + + /* If in graphics mode, don't save anything */ + attr10 = hwp->readAttr(hwp, 0x10); + if (attr10 & 0x01) + return; + + /* save the registers that are needed here */ + miscOut = hwp->readMiscOut(hwp); + gr4 = hwp->readGr(hwp, 0x04); + gr5 = hwp->readGr(hwp, 0x05); + gr6 = hwp->readGr(hwp, 0x06); + seq2 = hwp->readSeq(hwp, 0x02); + seq4 = hwp->readSeq(hwp, 0x04); + + /* save hwp->IOBase and temporarily set it for colour mode */ + savedIOBase = hwp->IOBase; + hwp->IOBase = VGA_IOBASE_COLOR; + + /* Force into colour mode */ + hwp->writeMiscOut(hwp, miscOut | 0x01); + + vgaHWBlankScreen(scrninfp, FALSE); + + /* + * get the character sets, and text screen if required + */ + /* + * Here we temporarily switch to 16 colour planar mode, to simply + * copy the font-info + * + * BUG ALERT: The (S)VGA's segment-select register MUST be set correctly! + */ +#if 0 + hwp->writeAttr(hwp, 0x10, 0x01); /* graphics mode */ +#endif + + hwp->writeSeq(hwp, 0x04, 0x06); /* enable plane graphics */ + hwp->writeGr(hwp, 0x05, 0x00); /* write mode 0, read mode 0 */ + hwp->writeGr(hwp, 0x06, 0x05); /* set graphics */ + +#if SAVE_FONT1 + if (hwp->FontInfo1 || (hwp->FontInfo1 = malloc(FONT_AMOUNT))) { + hwp->writeSeq(hwp, 0x02, 0x04); /* write to plane 2 */ + hwp->writeGr(hwp, 0x04, 0x02); /* read plane 2 */ + slowbcopy_frombus(hwp->Base, hwp->FontInfo1, FONT_AMOUNT); + } +#endif /* SAVE_FONT1 */ +#if SAVE_FONT2 + if (hwp->FontInfo2 || (hwp->FontInfo2 = malloc(FONT_AMOUNT))) { + hwp->writeSeq(hwp, 0x02, 0x08); /* write to plane 3 */ + hwp->writeGr(hwp, 0x04, 0x03); /* read plane 3 */ + slowbcopy_frombus(hwp->Base, hwp->FontInfo2, FONT_AMOUNT); + } +#endif /* SAVE_FONT2 */ +#if SAVE_TEXT + if (hwp->TextInfo || (hwp->TextInfo = malloc(2 * TEXT_AMOUNT))) { + hwp->writeSeq(hwp, 0x02, 0x01); /* write to plane 0 */ + hwp->writeGr(hwp, 0x04, 0x00); /* read plane 0 */ + slowbcopy_frombus(hwp->Base, hwp->TextInfo, TEXT_AMOUNT); + hwp->writeSeq(hwp, 0x02, 0x02); /* write to plane 1 */ + hwp->writeGr(hwp, 0x04, 0x01); /* read plane 1 */ + slowbcopy_frombus(hwp->Base, + (unsigned char *)hwp->TextInfo + TEXT_AMOUNT, TEXT_AMOUNT); + } +#endif /* SAVE_TEXT */ + + /* Restore clobbered registers */ + hwp->writeAttr(hwp, 0x10, attr10); + hwp->writeSeq(hwp, 0x02, seq2); + hwp->writeSeq(hwp, 0x04, seq4); + hwp->writeGr(hwp, 0x04, gr4); + hwp->writeGr(hwp, 0x05, gr5); + hwp->writeGr(hwp, 0x06, gr6); + hwp->writeMiscOut(hwp, miscOut); + hwp->IOBase = savedIOBase; + + vgaHWBlankScreen(scrninfp, TRUE); + + if (doMap) + vgaHWUnmapMem(scrninfp); + +#endif /* SAVE_TEXT || SAVE_FONT1 || SAVE_FONT2 */ +} + +void +vgaHWSaveMode(ScrnInfoPtr scrninfp, vgaRegPtr save) +{ + vgaHWPtr hwp = VGAHWPTR(scrninfp); + int i; + + save->MiscOutReg = hwp->readMiscOut(hwp); + if (save->MiscOutReg & 0x01) + hwp->IOBase = VGA_IOBASE_COLOR; + else + hwp->IOBase = VGA_IOBASE_MONO; + + for (i = 0; i < save->numCRTC; i++) { + save->CRTC[i] = hwp->readCrtc(hwp, i); + DebugF("CRTC[0x%02x] = 0x%02x\n", i, save->CRTC[i]); + } + + hwp->enablePalette(hwp); + for (i = 0; i < save->numAttribute; i++) { + save->Attribute[i] = hwp->readAttr(hwp, i); + DebugF("Attribute[0x%02x] = 0x%02x\n", i, save->Attribute[i]); + } + hwp->disablePalette(hwp); + + for (i = 0; i < save->numGraphics; i++) { + save->Graphics[i] = hwp->readGr(hwp, i); + DebugF("Graphics[0x%02x] = 0x%02x\n", i, save->Graphics[i]); + } + + for (i = 1; i < save->numSequencer; i++) { + save->Sequencer[i] = hwp->readSeq(hwp, i); + DebugF("Sequencer[0x%02x] = 0x%02x\n", i, save->Sequencer[i]); + } +} + + +void +vgaHWSaveColormap(ScrnInfoPtr scrninfp, vgaRegPtr save) +{ + vgaHWPtr hwp = VGAHWPTR(scrninfp); + Bool readError = FALSE; + int i; + +#ifdef NEED_SAVED_CMAP + /* + * Some ET4000 chips from 1991 have a HW bug that prevents the reading + * of the color lookup table. Mask rev 9042EAI is known to have this bug. + * + * If the colourmap is not readable, we set the saved map to a default + * map (taken from Ferraro's "Programmer's Guide to the EGA and VGA + * Cards" 2nd ed). + */ + + /* Only save it once */ + if (hwp->cmapSaved) + return; + +#if 0 + hwp->enablePalette(hwp); +#endif + + hwp->writeDacMask(hwp, 0xFF); + + /* + * check if we can read the lookup table + */ + hwp->writeDacReadAddr(hwp, 0x00); + for (i = 0; i < 6; i++) { + save->DAC[i] = hwp->readDacData(hwp); + switch (i % 3) { + case 0: + DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]); + break; + case 1: + DebugF("0x%02x, ", save->DAC[i]); + break; + case 2: + DebugF("0x%02x\n", save->DAC[i]); + } + } + + /* + * Check if we can read the palette - + * use foreground color to prevent flashing. + */ + hwp->writeDacWriteAddr(hwp, 0x01); + for (i = 3; i < 6; i++) + hwp->writeDacData(hwp, ~save->DAC[i] & DAC_TEST_MASK); + hwp->writeDacReadAddr(hwp, 0x01); + for (i = 3; i < 6; i++) { + if (hwp->readDacData(hwp) != (~save->DAC[i] & DAC_TEST_MASK)) + readError = TRUE; + } + hwp->writeDacWriteAddr(hwp, 0x01); + for (i = 3; i < 6; i++) + hwp->writeDacData(hwp, save->DAC[i]); + + if (readError) { + /* + * save the default lookup table + */ + memmove(save->DAC, defaultDAC, 768); + xf86DrvMsg(scrninfp->scrnIndex, X_WARNING, + "Cannot read colourmap from VGA. Will restore with default\n"); + } else { + /* save the colourmap */ + hwp->writeDacReadAddr(hwp, 0x02); + for (i = 6; i < 768; i++) { + save->DAC[i] = hwp->readDacData(hwp); + DACDelay(hwp); + switch (i % 3) { + case 0: + DebugF("DAC[0x%02x] = 0x%02x, ", i / 3, save->DAC[i]); + break; + case 1: + DebugF("0x%02x, ", save->DAC[i]); + break; + case 2: + DebugF("0x%02x\n", save->DAC[i]); + } + } + } + + hwp->disablePalette(hwp); + hwp->cmapSaved = TRUE; +#endif +} + +/* + * vgaHWSave -- + * save the current VGA state + */ + +void +vgaHWSave(ScrnInfoPtr scrninfp, vgaRegPtr save, int flags) +{ + if (save == NULL) + return; + + if (flags & VGA_SR_CMAP) + vgaHWSaveColormap(scrninfp, save); + + if (flags & VGA_SR_MODE) + vgaHWSaveMode(scrninfp, save); + + if (flags & VGA_SR_FONTS) + vgaHWSaveFonts(scrninfp, save); +} + + +/* + * vgaHWInit -- + * Handle the initialization, etc. of a screen. + * Return FALSE on failure. + */ + +Bool +vgaHWInit(ScrnInfoPtr scrninfp, DisplayModePtr mode) +{ + unsigned int i; + vgaHWPtr hwp; + vgaRegPtr regp; + int depth = scrninfp->depth; + + /* + * make sure the vgaHWRec is allocated + */ + if (!vgaHWGetHWRec(scrninfp)) + return FALSE; + hwp = VGAHWPTR(scrninfp); + regp = &hwp->ModeReg; + + /* + * compute correct Hsync & Vsync polarity + */ + if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) + && (mode->Flags & (V_PVSYNC | V_NVSYNC))) + { + regp->MiscOutReg = 0x23; + if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40; + if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80; + } + else + { + int VDisplay = mode->VDisplay; + if (mode->Flags & V_DBLSCAN) + VDisplay *= 2; + if (mode->VScan > 1) + VDisplay *= mode->VScan; + if (VDisplay < 400) + regp->MiscOutReg = 0xA3; /* +hsync -vsync */ + else if (VDisplay < 480) + regp->MiscOutReg = 0x63; /* -hsync +vsync */ + else if (VDisplay < 768) + regp->MiscOutReg = 0xE3; /* -hsync -vsync */ + else + regp->MiscOutReg = 0x23; /* +hsync +vsync */ + } + + regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2; + + /* + * Time Sequencer + */ + if (depth == 4) + regp->Sequencer[0] = 0x02; + else + regp->Sequencer[0] = 0x00; + if (mode->Flags & V_CLKDIV2) + regp->Sequencer[1] = 0x09; + else + regp->Sequencer[1] = 0x01; + if (depth == 1) + regp->Sequencer[2] = 1 << BIT_PLANE; + else + regp->Sequencer[2] = 0x0F; + regp->Sequencer[3] = 0x00; /* Font select */ + if (depth < 8) + regp->Sequencer[4] = 0x06; /* Misc */ + else + regp->Sequencer[4] = 0x0E; /* Misc */ + + /* + * CRTC Controller + */ + regp->CRTC[0] = (mode->CrtcHTotal >> 3) - 5; + regp->CRTC[1] = (mode->CrtcHDisplay >> 3) - 1; + regp->CRTC[2] = (mode->CrtcHBlankStart >> 3) - 1; + regp->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; + i = (((mode->CrtcHSkew << 2) + 0x10) & ~0x1F); + if (i < 0x80) + regp->CRTC[3] |= i; + regp->CRTC[4] = (mode->CrtcHSyncStart >> 3); + regp->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) + | (((mode->CrtcHSyncEnd >> 3)) & 0x1F); + regp->CRTC[6] = (mode->CrtcVTotal - 2) & 0xFF; + regp->CRTC[7] = (((mode->CrtcVTotal - 2) & 0x100) >> 8) + | (((mode->CrtcVDisplay - 1) & 0x100) >> 7) + | ((mode->CrtcVSyncStart & 0x100) >> 6) + | (((mode->CrtcVBlankStart - 1) & 0x100) >> 5) + | 0x10 + | (((mode->CrtcVTotal - 2) & 0x200) >> 4) + | (((mode->CrtcVDisplay - 1) & 0x200) >> 3) + | ((mode->CrtcVSyncStart & 0x200) >> 2); + regp->CRTC[8] = 0x00; + regp->CRTC[9] = (((mode->CrtcVBlankStart - 1) & 0x200) >> 4) | 0x40; + if (mode->Flags & V_DBLSCAN) + regp->CRTC[9] |= 0x80; + if (mode->VScan >= 32) + regp->CRTC[9] |= 0x1F; + else if (mode->VScan > 1) + regp->CRTC[9] |= mode->VScan - 1; + regp->CRTC[10] = 0x00; + regp->CRTC[11] = 0x00; + regp->CRTC[12] = 0x00; + regp->CRTC[13] = 0x00; + regp->CRTC[14] = 0x00; + regp->CRTC[15] = 0x00; + regp->CRTC[16] = mode->CrtcVSyncStart & 0xFF; + regp->CRTC[17] = (mode->CrtcVSyncEnd & 0x0F) | 0x20; + regp->CRTC[18] = (mode->CrtcVDisplay - 1) & 0xFF; + regp->CRTC[19] = scrninfp->displayWidth >> 4; /* just a guess */ + regp->CRTC[20] = 0x00; + regp->CRTC[21] = (mode->CrtcVBlankStart - 1) & 0xFF; + regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; + if (depth < 8) + regp->CRTC[23] = 0xE3; + else + regp->CRTC[23] = 0xC3; + regp->CRTC[24] = 0xFF; + + vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO); + vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO); + + /* + * Theory resumes here.... + */ + + /* + * Graphics Display Controller + */ + regp->Graphics[0] = 0x00; + regp->Graphics[1] = 0x00; + regp->Graphics[2] = 0x00; + regp->Graphics[3] = 0x00; + if (depth == 1) { + regp->Graphics[4] = BIT_PLANE; + regp->Graphics[5] = 0x00; + } else { + regp->Graphics[4] = 0x00; + if (depth == 4) + regp->Graphics[5] = 0x02; + else + regp->Graphics[5] = 0x40; + } + regp->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */ + regp->Graphics[7] = 0x0F; + regp->Graphics[8] = 0xFF; + + if (depth == 1) { + /* Initialise the Mono map according to which bit-plane gets used */ + + Bool flipPixels = xf86GetFlipPixels(); + + for (i=0; i<16; i++) + if (((i & (1 << BIT_PLANE)) != 0) != flipPixels) + regp->Attribute[i] = WHITE_VALUE; + else + regp->Attribute[i] = BLACK_VALUE; + + regp->Attribute[16] = 0x01; /* -VGA2- */ /* wrong for the ET4000 */ + if (!hwp->ShowOverscan) + regp->Attribute[OVERSCAN] = OVERSCAN_VALUE; /* -VGA2- */ + } else { + regp->Attribute[0] = 0x00; /* standard colormap translation */ + regp->Attribute[1] = 0x01; + regp->Attribute[2] = 0x02; + regp->Attribute[3] = 0x03; + regp->Attribute[4] = 0x04; + regp->Attribute[5] = 0x05; + regp->Attribute[6] = 0x06; + regp->Attribute[7] = 0x07; + regp->Attribute[8] = 0x08; + regp->Attribute[9] = 0x09; + regp->Attribute[10] = 0x0A; + regp->Attribute[11] = 0x0B; + regp->Attribute[12] = 0x0C; + regp->Attribute[13] = 0x0D; + regp->Attribute[14] = 0x0E; + regp->Attribute[15] = 0x0F; + if (depth == 4) + regp->Attribute[16] = 0x81; /* wrong for the ET4000 */ + else + regp->Attribute[16] = 0x41; /* wrong for the ET4000 */ + /* Attribute[17] (overscan) initialised in vgaHWGetHWRec() */ + } + regp->Attribute[18] = 0x0F; + regp->Attribute[19] = 0x00; + regp->Attribute[20] = 0x00; + + return(TRUE); +} + + /* + * OK, so much for theory. Now, let's deal with the >real< world... + * + * The above CRTC settings are precise in theory, except that many, if not + * most, VGA clones fail to reset the blanking signal when the character or + * line counter reaches [HV]Total. In this case, the signal is only + * unblanked when the counter reaches [HV]BlankEnd (mod 64, 128 or 256 as + * the case may be) at the start of the >next< scanline or frame, which + * means only part of the screen shows. This affects how null overscans + * are to be implemented on such adapters. + * + * Henceforth, VGA cores that implement this broken, but unfortunately + * common, behaviour are to be designated as KGA's, in honour of Koen + * Gadeyne, whose zeal to eliminate overscans (read: fury) set in motion + * a series of events that led to the discovery of this problem. + * + * Some VGA's are KGA's only in the horizontal, or only in the vertical, + * some in both, others in neither. Don't let anyone tell you there is + * such a thing as a VGA "standard"... And, thank the Creator for the fact + * that Hilbert spaces are not yet implemented in this industry. + * + * The following implements a trick suggested by David Dawes. This sets + * [HV]BlankEnd to zero if the blanking interval does not already contain a + * 0-point, and decrements it by one otherwise. In the latter case, this + * will produce a left and/or top overscan which the colourmap code will + * (still) need to ensure is as close to black as possible. This will make + * the behaviour consistent across all chipsets, while allowing all + * chipsets to display the entire screen. Non-KGA drivers can ignore the + * following in their own copy of this code. + * + * -- TSI @ UQV, 1998.08.21 + */ + +CARD32 +vgaHWHBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits, + unsigned int Flags) +{ + int nExtBits = (nBits < 6) ? 0 : nBits - 6; + CARD32 ExtBits; + CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 6; + + regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) + | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F); + regp->CRTC[5] = (regp->CRTC[5] & ~0x80) + | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2); + ExtBits = ((mode->CrtcHBlankEnd >> 3) - 1) & ExtBitMask; + + /* First the horizontal case */ + if ((Flags & KGA_FIX_OVERSCAN) + && ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3))) + { + int i = (regp->CRTC[3] & 0x1F) + | ((regp->CRTC[5] & 0x80) >> 2) + | ExtBits; + if (Flags & KGA_ENABLE_ON_ZERO) { + if ((i-- > (((mode->CrtcHBlankStart >> 3) - 1) + & (0x3F | ExtBitMask))) + && (mode->CrtcHBlankEnd == mode->CrtcHTotal)) + i = 0; + } else if (Flags & KGA_BE_TOT_DEC) + i--; + regp->CRTC[3] = (regp->CRTC[3] & ~0x1F) | (i & 0x1F); + regp->CRTC[5] = (regp->CRTC[5] & ~0x80) | ((i << 2) & 0x80); + ExtBits = i & ExtBitMask; + } + return ExtBits >> 6; +} + + /* + * The vertical case is a little trickier. Some VGA's ignore bit 0x80 of + * CRTC[22]. Also, in some cases, a zero CRTC[22] will still blank the + * very first scanline in a double- or multi-scanned mode. This last case + * needs further investigation. + */ +CARD32 +vgaHWVBlankKGA(DisplayModePtr mode, vgaRegPtr regp, int nBits, + unsigned int Flags) +{ + CARD32 ExtBits; + CARD32 nExtBits = (nBits < 8) ? 0 : (nBits - 8); + CARD32 ExtBitMask = ((1 << nExtBits) - 1) << 8; + /* If width is not known nBits should be 0. In this + * case BitMask is set to 0 so we can check for it. */ + CARD32 BitMask = (nBits < 7) ? 0 : ((1 << nExtBits) - 1); + int VBlankStart = (mode->CrtcVBlankStart - 1) & 0xFF; + regp->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; + ExtBits = (mode->CrtcVBlankEnd - 1) & ExtBitMask; + + if ((Flags & KGA_FIX_OVERSCAN) + && (mode->CrtcVBlankEnd == mode->CrtcVTotal)) + /* Null top overscan */ + { + int i = regp->CRTC[22] | ExtBits; + if (Flags & KGA_ENABLE_ON_ZERO) { + if (((BitMask && ((i & BitMask) > (VBlankStart & BitMask))) + || ((i > VBlankStart) && /* 8-bit case */ + ((i & 0x7F) > (VBlankStart & 0x7F)))) && /* 7-bit case */ + !(regp->CRTC[9] & 0x9F)) /* 1 scanline/row */ + i = 0; + else + i = (i - 1); + } else if (Flags & KGA_BE_TOT_DEC) + i = (i - 1); + + regp->CRTC[22] = i & 0xFF; + ExtBits = i & 0xFF00; + } + return ExtBits >> 8; +} + +/* + * these are some more hardware specific helpers, formerly in vga.c + */ +static void +vgaHWGetHWRecPrivate(void) +{ + if (vgaHWPrivateIndex < 0) + vgaHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); + return; +} + + +static void +vgaHWFreeRegs(vgaRegPtr regp) +{ + if (regp->CRTC) + free(regp->CRTC); + + regp->CRTC = + regp->Sequencer = + regp->Graphics = + regp->Attribute = NULL; + + regp->numCRTC = + regp->numSequencer = + regp->numGraphics = + regp->numAttribute = 0; +} + + + +static Bool +vgaHWAllocRegs(vgaRegPtr regp) +{ + unsigned char *buf; + + if ((regp->numCRTC + regp->numSequencer + regp->numGraphics + + regp->numAttribute) == 0) + return FALSE; + + buf = calloc(regp->numCRTC + + regp->numSequencer + + regp->numGraphics + + regp->numAttribute, 1); + if (!buf) + return FALSE; + + regp->CRTC = buf; + regp->Sequencer = regp->CRTC + regp->numCRTC; + regp->Graphics = regp->Sequencer + regp->numSequencer; + regp->Attribute = regp->Graphics + regp->numGraphics; + + return TRUE; +} + + +Bool +vgaHWAllocDefaultRegs(vgaRegPtr regp) +{ + regp->numCRTC = VGA_NUM_CRTC; + regp->numSequencer = VGA_NUM_SEQ; + regp->numGraphics = VGA_NUM_GFX; + regp->numAttribute = VGA_NUM_ATTR; + + return vgaHWAllocRegs(regp); +} + + +Bool +vgaHWSetRegCounts(ScrnInfoPtr scrp, int numCRTC, int numSequencer, + int numGraphics, int numAttribute) +{ +#define VGAHWMINNUM(regtype) \ + ((newMode.num##regtype < regp->num##regtype) ? \ + (newMode.num##regtype) : (regp->num##regtype)) +#define VGAHWCOPYREGSET(regtype) \ + memcpy (newMode.regtype, regp->regtype, VGAHWMINNUM(regtype)) + + vgaRegRec newMode, newSaved; + vgaRegPtr regp; + + regp = &VGAHWPTR(scrp)->ModeReg; + memcpy (&newMode, regp, sizeof(vgaRegRec)); + + /* allocate space for new registers */ + + regp = &newMode; + regp->numCRTC = numCRTC; + regp->numSequencer = numSequencer; + regp->numGraphics = numGraphics; + regp->numAttribute = numAttribute; + if (!vgaHWAllocRegs(regp)) + return FALSE; + + regp = &VGAHWPTR(scrp)->SavedReg; + memcpy (&newSaved, regp, sizeof(vgaRegRec)); + + regp = &newSaved; + regp->numCRTC = numCRTC; + regp->numSequencer = numSequencer; + regp->numGraphics = numGraphics; + regp->numAttribute = numAttribute; + if (!vgaHWAllocRegs(regp)) { + vgaHWFreeRegs(&newMode); + return FALSE; + } + + /* allocations succeeded, copy register data into new space */ + + regp = &VGAHWPTR(scrp)->ModeReg; + VGAHWCOPYREGSET(CRTC); + VGAHWCOPYREGSET(Sequencer); + VGAHWCOPYREGSET(Graphics); + VGAHWCOPYREGSET(Attribute); + + regp = &VGAHWPTR(scrp)->SavedReg; + VGAHWCOPYREGSET(CRTC); + VGAHWCOPYREGSET(Sequencer); + VGAHWCOPYREGSET(Graphics); + VGAHWCOPYREGSET(Attribute); + + /* free old register arrays */ + + regp = &VGAHWPTR(scrp)->ModeReg; + vgaHWFreeRegs(regp); + memcpy(regp, &newMode, sizeof(vgaRegRec)); + + regp = &VGAHWPTR(scrp)->SavedReg; + vgaHWFreeRegs(regp); + memcpy(regp, &newSaved, sizeof(vgaRegRec)); + + return TRUE; + +#undef VGAHWMINNUM +#undef VGAHWCOPYREGSET +} + + +Bool +vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src) +{ + vgaHWFreeRegs(dst); + + memcpy(dst, src, sizeof(vgaRegRec)); + + if (!vgaHWAllocRegs(dst)) + return FALSE; + + memcpy(dst->CRTC, src->CRTC, src->numCRTC); + memcpy(dst->Sequencer, src->Sequencer, src->numSequencer); + memcpy(dst->Graphics, src->Graphics, src->numGraphics); + memcpy(dst->Attribute, src->Attribute, src->numAttribute); + + return TRUE; +} + + +Bool +vgaHWGetHWRec(ScrnInfoPtr scrp) +{ + vgaRegPtr regp; + vgaHWPtr hwp; + int i; + + /* + * Let's make sure that the private exists and allocate one. + */ + vgaHWGetHWRecPrivate(); + /* + * New privates are always set to NULL, so we can check if the allocation + * has already been done. + */ + if (VGAHWPTR(scrp)) + return TRUE; + hwp = VGAHWPTRLVAL(scrp) = xnfcalloc(sizeof(vgaHWRec), 1); + regp = &VGAHWPTR(scrp)->ModeReg; + + if ((!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->SavedReg)) || + (!vgaHWAllocDefaultRegs(&VGAHWPTR(scrp)->ModeReg))) { + free(hwp); + return FALSE; + } + + if (scrp->bitsPerPixel == 1) { + rgb blackColour = scrp->display->blackColour, + whiteColour = scrp->display->whiteColour; + + if (blackColour.red > 0x3F) blackColour.red = 0x3F; + if (blackColour.green > 0x3F) blackColour.green = 0x3F; + if (blackColour.blue > 0x3F) blackColour.blue = 0x3F; + + if (whiteColour.red > 0x3F) whiteColour.red = 0x3F; + if (whiteColour.green > 0x3F) whiteColour.green = 0x3F; + if (whiteColour.blue > 0x3F) whiteColour.blue = 0x3F; + + if ((blackColour.red == whiteColour.red ) && + (blackColour.green == whiteColour.green) && + (blackColour.blue == whiteColour.blue )) { + blackColour.red ^= 0x3F; + blackColour.green ^= 0x3F; + blackColour.blue ^= 0x3F; + } + + /* + * initialize default colormap for monochrome + */ + for (i=0; i<3; i++) regp->DAC[i] = 0x00; + for (i=3; i<768; i++) regp->DAC[i] = 0x3F; + i = BLACK_VALUE * 3; + regp->DAC[i++] = blackColour.red; + regp->DAC[i++] = blackColour.green; + regp->DAC[i] = blackColour.blue; + i = WHITE_VALUE * 3; + regp->DAC[i++] = whiteColour.red; + regp->DAC[i++] = whiteColour.green; + regp->DAC[i] = whiteColour.blue; + i = OVERSCAN_VALUE * 3; + regp->DAC[i++] = 0x00; + regp->DAC[i++] = 0x00; + regp->DAC[i] = 0x00; + } else { + /* Set all colours to black */ + for (i=0; i<768; i++) regp->DAC[i] = 0x00; + /* ... and the overscan */ + if (scrp->depth >= 4) + regp->Attribute[OVERSCAN] = 0xFF; + } + if (xf86FindOption(scrp->confScreen->options, "ShowOverscan")) { + xf86MarkOptionUsedByName(scrp->confScreen->options, "ShowOverscan"); + xf86DrvMsg(scrp->scrnIndex, X_CONFIG, "Showing overscan area\n"); + regp->DAC[765] = 0x3F; + regp->DAC[766] = 0x00; + regp->DAC[767] = 0x3F; + regp->Attribute[OVERSCAN] = 0xFF; + hwp->ShowOverscan = TRUE; + } else + hwp->ShowOverscan = FALSE; + + hwp->paletteEnabled = FALSE; + hwp->cmapSaved = FALSE; + hwp->MapSize = 0; + hwp->pScrn = scrp; + + /* Initialise the function pointers with the standard VGA versions */ + vgaHWSetStdFuncs(hwp); + + hwp->PIOOffset = scrp->domainIOBase; + hwp->dev = xf86GetPciInfoForEntity(scrp->entityList[0]); + + return TRUE; +} + + +void +vgaHWFreeHWRec(ScrnInfoPtr scrp) +{ + if (vgaHWPrivateIndex >= 0) { + vgaHWPtr hwp = VGAHWPTR(scrp); + + if (!hwp) + return; + + free(hwp->FontInfo1); + free(hwp->FontInfo2); + free(hwp->TextInfo); + + vgaHWFreeRegs (&hwp->ModeReg); + vgaHWFreeRegs (&hwp->SavedReg); + + free(hwp); + VGAHWPTRLVAL(scrp) = NULL; + } +} + + +Bool +vgaHWMapMem(ScrnInfoPtr scrp) +{ + vgaHWPtr hwp = VGAHWPTR(scrp); + int scr_index = scrp->scrnIndex; + + if (hwp->Base) + return TRUE; + + /* If not set, initialise with the defaults */ + if (hwp->MapSize == 0) + hwp->MapSize = VGA_DEFAULT_MEM_SIZE; + if (hwp->MapPhys == 0) + hwp->MapPhys = VGA_DEFAULT_PHYS_ADDR; + + /* + * Map as VIDMEM_MMIO_32BIT because WC + * is bad when there is page flipping. + * XXX This is not correct but we do it + * for now. + */ + DebugF("Mapping VGAMem\n"); + hwp->Base = xf86MapDomainMemory(scr_index, VIDMEM_MMIO_32BIT, hwp->dev, + hwp->MapPhys, hwp->MapSize); + return hwp->Base != NULL; +} + + +void +vgaHWUnmapMem(ScrnInfoPtr scrp) +{ + vgaHWPtr hwp = VGAHWPTR(scrp); + int scr_index = scrp->scrnIndex; + + if (hwp->Base == NULL) + return; + + DebugF("Unmapping VGAMem\n"); + xf86UnMapVidMem(scr_index, hwp->Base, hwp->MapSize); + hwp->Base = NULL; +} + +int +vgaHWGetIndex(void) +{ + return vgaHWPrivateIndex; +} + + +void +vgaHWGetIOBase(vgaHWPtr hwp) +{ + hwp->IOBase = (hwp->readMiscOut(hwp) & 0x01) ? + VGA_IOBASE_COLOR : VGA_IOBASE_MONO; + xf86DrvMsgVerb(hwp->pScrn->scrnIndex, X_INFO, 3, + "vgaHWGetIOBase: hwp->IOBase is 0x%04x, hwp->PIOOffset is 0x%04lx\n", + hwp->IOBase, hwp->PIOOffset); +} + + +void +vgaHWLock(vgaHWPtr hwp) +{ + /* Protect CRTC[0-7] */ + hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x80); +} + +void +vgaHWUnlock(vgaHWPtr hwp) +{ + /* Unprotect CRTC[0-7] */ + hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) & ~0x80); +} + + +void +vgaHWEnable(vgaHWPtr hwp) +{ + hwp->writeEnable(hwp, hwp->readEnable(hwp) | 0x01); +} + + +void +vgaHWDisable(vgaHWPtr hwp) +{ + hwp->writeEnable(hwp, hwp->readEnable(hwp) & ~0x01); +} + + +static void +vgaHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, + VisualPtr pVisual) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + int i, index; + + for (i = 0; i < numColors; i++) { + index = indices[i]; + hwp->writeDacWriteAddr(hwp, index); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].red); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].green); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].blue); + DACDelay(hwp); + } + + /* This shouldn't be necessary, but we'll play safe. */ + hwp->disablePalette(hwp); +} + + +static void +vgaHWSetOverscan(ScrnInfoPtr pScrn, int overscan) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + + if (overscan < 0 || overscan > 255) + return; + + hwp->enablePalette(hwp); + hwp->writeAttr(hwp, OVERSCAN, overscan); + +#ifdef DEBUGOVERSCAN + { + int ov = hwp->readAttr(hwp, OVERSCAN); + int red, green, blue; + + hwp->writeDacReadAddr(hwp, ov); + red = hwp->readDacData(hwp); + green = hwp->readDacData(hwp); + blue = hwp->readDacData(hwp); + ErrorF("Overscan index is 0x%02x, colours are #%02x%02x%02x\n", + ov, red, green, blue); + } +#endif + + hwp->disablePalette(hwp); +} + + +Bool +vgaHWHandleColormaps(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (pScrn->depth > 1 && pScrn->depth <= 8) { + return xf86HandleColormaps(pScreen, 1 << pScrn->depth, + pScrn->rgbBits, vgaHWLoadPalette, + pScrn->depth > 4 ? vgaHWSetOverscan : NULL, + CMAP_RELOAD_ON_MODE_SWITCH); + } + return TRUE; +} + +/* ----------------------- DDC support ------------------------*/ +/* + * Adjust v_active, v_blank, v_sync, v_sync_end, v_blank_end, v_total + * to read out EDID at a faster rate. Allowed maximum is 25kHz with + * 20 usec v_sync active. Set positive v_sync polarity, turn off lightpen + * readback, enable access to cr00-cr07. + */ + +/* vertical timings */ +#define DISPLAY_END 0x04 +#define BLANK_START DISPLAY_END +#define SYNC_START BLANK_START +#define SYNC_END 0x09 +#define BLANK_END SYNC_END +#define V_TOTAL BLANK_END +/* this function doesn't have to be reentrant for our purposes */ +struct _vgaDdcSave { + unsigned char cr03; + unsigned char cr06; + unsigned char cr07; + unsigned char cr09; + unsigned char cr10; + unsigned char cr11; + unsigned char cr12; + unsigned char cr15; + unsigned char cr16; + unsigned char msr; +}; + +void +vgaHWddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + unsigned char tmp; + struct _vgaDdcSave* save; + switch (speed) { + case DDC_FAST: + + if (hwp->ddc != NULL) break; + hwp->ddc = xnfcalloc(sizeof(struct _vgaDdcSave),1); + save = (struct _vgaDdcSave *)hwp->ddc; + /* Lightpen register disable - allow access to cr10 & 11; just in case */ + save->cr03 = hwp->readCrtc(hwp, 0x03); + hwp->writeCrtc(hwp,0x03,(save->cr03 |0x80)); + save->cr12 = hwp->readCrtc(hwp, 0x12); + hwp->writeCrtc(hwp,0x12,DISPLAY_END); + save->cr15 = hwp->readCrtc(hwp, 0x15); + hwp->writeCrtc(hwp,0x15,BLANK_START); + save->cr10 = hwp->readCrtc(hwp, 0x10); + hwp->writeCrtc(hwp,0x10,SYNC_START); + save->cr11 = hwp->readCrtc(hwp, 0x11); + /* unprotect group 1 registers; just in case ...*/ + hwp->writeCrtc(hwp,0x11,((save->cr11 & 0x70) | SYNC_END)); + save->cr16 = hwp->readCrtc(hwp, 0x16); + hwp->writeCrtc(hwp,0x16,BLANK_END); + save->cr06 = hwp->readCrtc(hwp, 0x06); + hwp->writeCrtc(hwp,0x06,V_TOTAL); + /* all values have less than 8 bit - mask out 9th and 10th bits */ + save->cr09 = hwp->readCrtc(hwp, 0x09); + hwp->writeCrtc(hwp,0x09,(save->cr09 &0xDF)); + save->cr07 = hwp->readCrtc(hwp, 0x07); + hwp->writeCrtc(hwp,0x07,(save->cr07 &0x10)); + /* vsync polarity negativ & ensure a 25MHz clock */ + save->msr = hwp->readMiscOut(hwp); + hwp->writeMiscOut(hwp,((save->msr & 0xF3) | 0x80)); + break; + case DDC_SLOW: + if (hwp->ddc == NULL) break; + save = (struct _vgaDdcSave *)hwp->ddc; + hwp->writeMiscOut(hwp,save->msr); + hwp->writeCrtc(hwp,0x07,save->cr07); + tmp = hwp->readCrtc(hwp, 0x09); + hwp->writeCrtc(hwp,0x09,((save->cr09 & 0x20) | (tmp & 0xDF))); + hwp->writeCrtc(hwp,0x06,save->cr06); + hwp->writeCrtc(hwp,0x16,save->cr16); + hwp->writeCrtc(hwp,0x11,save->cr11); + hwp->writeCrtc(hwp,0x10,save->cr10); + hwp->writeCrtc(hwp,0x15,save->cr15); + hwp->writeCrtc(hwp,0x12,save->cr12); + hwp->writeCrtc(hwp,0x03,save->cr03); + free(save); + hwp->ddc = NULL; + break; + default: + break; + } +} + +DDC1SetSpeedProc +vgaHWddc1SetSpeedWeak(void) +{ + return vgaHWddc1SetSpeed; +} + +SaveScreenProcPtr vgaHWSaveScreenWeak(void) +{ + return vgaHWSaveScreen; +} diff --git a/xorg-server/hw/xfree86/xaa/xaaBitBlt.c b/xorg-server/hw/xfree86/xaa/xaaBitBlt.c index ebba74e55..b1fda1cd6 100644 --- a/xorg-server/hw/xfree86/xaa/xaaBitBlt.c +++ b/xorg-server/hw/xfree86/xaa/xaaBitBlt.c @@ -1,221 +1,221 @@ - -/* - This is a lighter version of cfbBitBlt. We calculate the boxes - when accelerating pixmap->screen and screen->screen copies. - We also pass the GC to the doBitBlt function so that it has access - to the fg and bg so CopyPlane can use this. -*/ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "mi.h" -#include "pixmapstr.h" -#include "gcstruct.h" -#include "windowstr.h" -#include "xaalocal.h" - - -RegionPtr -XAABitBlt( - DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GC *pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty, - void (*doBitBlt)(DrawablePtr, DrawablePtr, GCPtr, RegionPtr, DDXPointPtr), - unsigned long bitPlane ) -{ - - RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ - RegionPtr prgnExposed; - Bool freeSrcClip = FALSE; - RegionRec rgnDst; - DDXPointPtr pptSrc, ppt; - DDXPointRec origDest; - BoxPtr pbox; - BoxRec fastBox; - int i, dx, dy, numRects; - xRectangle origSource; - int fastClip = 0; /* for fast clipping with pixmap source */ - int fastExpose = 0; /* for fast exposures with pixmap source */ - - origSource.x = srcx; - origSource.y = srcy; - origSource.width = width; - origSource.height = height; - origDest.x = dstx; - origDest.y = dsty; - - if((pSrcDrawable != pDstDrawable) && - pSrcDrawable->pScreen->SourceValidate) { - (*pSrcDrawable->pScreen->SourceValidate) ( - pSrcDrawable, srcx, srcy, width, height); - } - - srcx += pSrcDrawable->x; - srcy += pSrcDrawable->y; - - /* clip the source */ - if (pSrcDrawable->type == DRAWABLE_PIXMAP) { - if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) - prgnSrcClip = pGC->pCompositeClip; - else - fastClip = 1; - } else { /* Window */ - if (pGC->subWindowMode == IncludeInferiors) { - if (!((WindowPtr) pSrcDrawable)->parent) { - /* - * special case bitblt from root window in - * IncludeInferiors mode; just like from a pixmap - */ - fastClip = 1; - } else if ((pSrcDrawable == pDstDrawable) && - (pGC->clientClipType == CT_NONE)) { - prgnSrcClip = pGC->pCompositeClip; - } else { - prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); - freeSrcClip = TRUE; - } - } else { - prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; - } - } - - fastBox.x1 = srcx; - fastBox.y1 = srcy; - fastBox.x2 = srcx + width; - fastBox.y2 = srcy + height; - - /* Don't create a source region if we are doing a fast clip */ - if (fastClip) { - fastExpose = 1; - /* - * clip the source; if regions extend beyond the source size, - * make sure exposure events get sent - */ - if (fastBox.x1 < pSrcDrawable->x) { - fastBox.x1 = pSrcDrawable->x; - fastExpose = 0; - } - if (fastBox.y1 < pSrcDrawable->y) { - fastBox.y1 = pSrcDrawable->y; - fastExpose = 0; - } - if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) { - fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; - fastExpose = 0; - } - if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) { - fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; - fastExpose = 0; - } - } else { - REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); - REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); - } - - dstx += pDstDrawable->x; - dsty += pDstDrawable->y; - - if (pDstDrawable->type == DRAWABLE_WINDOW) { - if (!((WindowPtr)pDstDrawable)->realized) { - if (!fastClip) - REGION_UNINIT(pGC->pScreen, &rgnDst); - if (freeSrcClip) - REGION_DESTROY(pGC->pScreen, prgnSrcClip); - return NULL; - } - } - - dx = srcx - dstx; - dy = srcy - dsty; - - /* Translate and clip the dst to the destination composite clip */ - if (fastClip) { - RegionPtr cclip; - - /* Translate the region directly */ - fastBox.x1 -= dx; - fastBox.x2 -= dx; - fastBox.y1 -= dy; - fastBox.y2 -= dy; - - /* If the destination composite clip is one rectangle we can - do the clip directly. Otherwise we have to create a full - blown region and call intersect */ - - cclip = pGC->pCompositeClip; - if (REGION_NUM_RECTS(cclip) == 1) { - BoxPtr pBox = REGION_RECTS(cclip); - - if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1; - if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2; - if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1; - if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2; - - /* Check to see if the region is empty */ - if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) { - REGION_NULL(pGC->pScreen, &rgnDst); - } else { - REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); - } - } else { - /* We must turn off fastClip now, since we must create - a full blown region. It is intersected with the - composite clip below. */ - fastClip = 0; - REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1); - } - } else { - REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); - } - - if (!fastClip) { - REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, - pGC->pCompositeClip); - } - - /* Do bit blitting */ - numRects = REGION_NUM_RECTS(&rgnDst); - if (numRects && width && height) { - if(!(pptSrc = (DDXPointPtr)xalloc(numRects * - sizeof(DDXPointRec)))) { - REGION_UNINIT(pGC->pScreen, &rgnDst); - if (freeSrcClip) - REGION_DESTROY(pGC->pScreen, prgnSrcClip); - return NULL; - } - pbox = REGION_RECTS(&rgnDst); - ppt = pptSrc; - for (i = numRects; --i >= 0; pbox++, ppt++) { - ppt->x = pbox->x1 + dx; - ppt->y = pbox->y1 + dy; - } - - (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC, &rgnDst, pptSrc); - xfree(pptSrc); - } - - prgnExposed = NULL; - if (pGC->fExpose) { - /* Pixmap sources generate a NoExposed (we return NULL to do this) */ - if (!fastExpose) - prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, - origSource.x, origSource.y, - (int)origSource.width, - (int)origSource.height, - origDest.x, origDest.y, bitPlane); - } - REGION_UNINIT(pGC->pScreen, &rgnDst); - if (freeSrcClip) - REGION_DESTROY(pGC->pScreen, prgnSrcClip); - return prgnExposed; -} + +/* + This is a lighter version of cfbBitBlt. We calculate the boxes + when accelerating pixmap->screen and screen->screen copies. + We also pass the GC to the doBitBlt function so that it has access + to the fg and bg so CopyPlane can use this. +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "mi.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "xaalocal.h" + + +RegionPtr +XAABitBlt( + DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + void (*doBitBlt)(DrawablePtr, DrawablePtr, GCPtr, RegionPtr, DDXPointPtr), + unsigned long bitPlane ) +{ + + RegionPtr prgnSrcClip = NULL; /* may be a new region, or just a copy */ + RegionPtr prgnExposed; + Bool freeSrcClip = FALSE; + RegionRec rgnDst; + DDXPointPtr pptSrc, ppt; + DDXPointRec origDest; + BoxPtr pbox; + BoxRec fastBox; + int i, dx, dy, numRects; + xRectangle origSource; + int fastClip = 0; /* for fast clipping with pixmap source */ + int fastExpose = 0; /* for fast exposures with pixmap source */ + + origSource.x = srcx; + origSource.y = srcy; + origSource.width = width; + origSource.height = height; + origDest.x = dstx; + origDest.y = dsty; + + if((pSrcDrawable != pDstDrawable) && + pSrcDrawable->pScreen->SourceValidate) { + (*pSrcDrawable->pScreen->SourceValidate) ( + pSrcDrawable, srcx, srcy, width, height); + } + + srcx += pSrcDrawable->x; + srcy += pSrcDrawable->y; + + /* clip the source */ + if (pSrcDrawable->type == DRAWABLE_PIXMAP) { + if ((pSrcDrawable == pDstDrawable) && (pGC->clientClipType == CT_NONE)) + prgnSrcClip = pGC->pCompositeClip; + else + fastClip = 1; + } else { /* Window */ + if (pGC->subWindowMode == IncludeInferiors) { + if (!((WindowPtr) pSrcDrawable)->parent) { + /* + * special case bitblt from root window in + * IncludeInferiors mode; just like from a pixmap + */ + fastClip = 1; + } else if ((pSrcDrawable == pDstDrawable) && + (pGC->clientClipType == CT_NONE)) { + prgnSrcClip = pGC->pCompositeClip; + } else { + prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable); + freeSrcClip = TRUE; + } + } else { + prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList; + } + } + + fastBox.x1 = srcx; + fastBox.y1 = srcy; + fastBox.x2 = srcx + width; + fastBox.y2 = srcy + height; + + /* Don't create a source region if we are doing a fast clip */ + if (fastClip) { + fastExpose = 1; + /* + * clip the source; if regions extend beyond the source size, + * make sure exposure events get sent + */ + if (fastBox.x1 < pSrcDrawable->x) { + fastBox.x1 = pSrcDrawable->x; + fastExpose = 0; + } + if (fastBox.y1 < pSrcDrawable->y) { + fastBox.y1 = pSrcDrawable->y; + fastExpose = 0; + } + if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width) { + fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width; + fastExpose = 0; + } + if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height) { + fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height; + fastExpose = 0; + } + } else { + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); + REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip); + } + + dstx += pDstDrawable->x; + dsty += pDstDrawable->y; + + if (pDstDrawable->type == DRAWABLE_WINDOW) { + if (!((WindowPtr)pDstDrawable)->realized) { + if (!fastClip) + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return NULL; + } + } + + dx = srcx - dstx; + dy = srcy - dsty; + + /* Translate and clip the dst to the destination composite clip */ + if (fastClip) { + RegionPtr cclip; + + /* Translate the region directly */ + fastBox.x1 -= dx; + fastBox.x2 -= dx; + fastBox.y1 -= dy; + fastBox.y2 -= dy; + + /* If the destination composite clip is one rectangle we can + do the clip directly. Otherwise we have to create a full + blown region and call intersect */ + + cclip = pGC->pCompositeClip; + if (REGION_NUM_RECTS(cclip) == 1) { + BoxPtr pBox = REGION_RECTS(cclip); + + if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1; + if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2; + if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1; + if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2; + + /* Check to see if the region is empty */ + if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2) { + REGION_NULL(pGC->pScreen, &rgnDst); + } else { + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1); + } + } else { + /* We must turn off fastClip now, since we must create + a full blown region. It is intersected with the + composite clip below. */ + fastClip = 0; + REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1); + } + } else { + REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy); + } + + if (!fastClip) { + REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, + pGC->pCompositeClip); + } + + /* Do bit blitting */ + numRects = REGION_NUM_RECTS(&rgnDst); + if (numRects && width && height) { + if(!(pptSrc = (DDXPointPtr)malloc(numRects * + sizeof(DDXPointRec)))) { + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return NULL; + } + pbox = REGION_RECTS(&rgnDst); + ppt = pptSrc; + for (i = numRects; --i >= 0; pbox++, ppt++) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC, &rgnDst, pptSrc); + free(pptSrc); + } + + prgnExposed = NULL; + if (pGC->fExpose) { + /* Pixmap sources generate a NoExposed (we return NULL to do this) */ + if (!fastExpose) + prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + origSource.x, origSource.y, + (int)origSource.width, + (int)origSource.height, + origDest.x, origDest.y, bitPlane); + } + REGION_UNINIT(pGC->pScreen, &rgnDst); + if (freeSrcClip) + REGION_DESTROY(pGC->pScreen, prgnSrcClip); + return prgnExposed; +} diff --git a/xorg-server/hw/xfree86/xaa/xaaCpyArea.c b/xorg-server/hw/xfree86/xaa/xaaCpyArea.c index 6a898cd5f..eefd8d38d 100644 --- a/xorg-server/hw/xfree86/xaa/xaaCpyArea.c +++ b/xorg-server/hw/xfree86/xaa/xaaCpyArea.c @@ -1,387 +1,387 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" -#include "migc.h" -#include "gcstruct.h" -#include "pixmapstr.h" - -/* - Written mostly by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). - */ - - -RegionPtr -XAACopyArea( - DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GC *pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - - if(pDstDrawable->type == DRAWABLE_WINDOW) { - if((pSrcDrawable->type == DRAWABLE_WINDOW) || - IS_OFFSCREEN_PIXMAP(pSrcDrawable)){ - if(infoRec->ScreenToScreenBitBlt && - CHECK_ROP(pGC,infoRec->ScreenToScreenBitBltFlags) && - CHECK_ROPSRC(pGC,infoRec->ScreenToScreenBitBltFlags) && - CHECK_PLANEMASK(pGC,infoRec->ScreenToScreenBitBltFlags)) - return (XAABitBlt( pSrcDrawable, pDstDrawable, - pGC, srcx, srcy, width, height, dstx, dsty, - XAADoBitBlt, 0L)); - } else { - if(infoRec->WritePixmap && - ((pDstDrawable->bitsPerPixel == pSrcDrawable->bitsPerPixel) || - ((pDstDrawable->bitsPerPixel == 24) && - (pSrcDrawable->bitsPerPixel == 32) && - (infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) && - CHECK_ROP(pGC,infoRec->WritePixmapFlags) && - CHECK_ROPSRC(pGC,infoRec->WritePixmapFlags) && - CHECK_PLANEMASK(pGC,infoRec->WritePixmapFlags) && - CHECK_NO_GXCOPY(pGC,infoRec->WritePixmapFlags)) - return (XAABitBlt( pSrcDrawable, pDstDrawable, - pGC, srcx, srcy, width, height, dstx, dsty, - XAADoImageWrite, 0L)); - } - } else if(IS_OFFSCREEN_PIXMAP(pDstDrawable)){ - if((pSrcDrawable->type == DRAWABLE_WINDOW) || - IS_OFFSCREEN_PIXMAP(pSrcDrawable)){ - if(infoRec->ScreenToScreenBitBlt && - CHECK_ROP(pGC,infoRec->ScreenToScreenBitBltFlags) && - CHECK_ROPSRC(pGC,infoRec->ScreenToScreenBitBltFlags) && - CHECK_PLANEMASK(pGC,infoRec->ScreenToScreenBitBltFlags)) - return (XAABitBlt( pSrcDrawable, pDstDrawable, - pGC, srcx, srcy, width, height, dstx, dsty, - XAADoBitBlt, 0L)); - } - } - - return (XAAFallbackOps.CopyArea(pSrcDrawable, pDstDrawable, pGC, - srcx, srcy, width, height, dstx, dsty)); -} - - -void -XAADoBitBlt( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - RegionPtr prgnDst, - DDXPointPtr pptSrc ) -{ - int nbox, careful; - BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; - DDXPointPtr pptTmp, pptNew1, pptNew2; - int xdir, ydir; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - - /* XXX we have to err on the side of safety when both are windows, - * because we don't know if IncludeInferiors is being used. - */ - careful = ((pSrc == pDst) || - ((pSrc->type == DRAWABLE_WINDOW) && - (pDst->type == DRAWABLE_WINDOW))); - - pbox = REGION_RECTS(prgnDst); - nbox = REGION_NUM_RECTS(prgnDst); - - pboxNew1 = NULL; - pptNew1 = NULL; - pboxNew2 = NULL; - pptNew2 = NULL; - if (careful && (pptSrc->y < pbox->y1)) { - /* walk source botttom to top */ - ydir = -1; - - if (nbox > 1) { - /* keep ordering in each band, reverse order of bands */ - pboxNew1 = (BoxPtr)xalloc(sizeof(BoxRec) * nbox); - if(!pboxNew1) - return; - pptNew1 = (DDXPointPtr)xalloc(sizeof(DDXPointRec) * nbox); - if(!pptNew1) { - xfree(pboxNew1); - return; - } - pboxBase = pboxNext = pbox+nbox-1; - while (pboxBase >= pbox) { - while ((pboxNext >= pbox) && - (pboxBase->y1 == pboxNext->y1)) - pboxNext--; - pboxTmp = pboxNext+1; - pptTmp = pptSrc + (pboxTmp - pbox); - while (pboxTmp <= pboxBase) { - *pboxNew1++ = *pboxTmp++; - *pptNew1++ = *pptTmp++; - } - pboxBase = pboxNext; - } - pboxNew1 -= nbox; - pbox = pboxNew1; - pptNew1 -= nbox; - pptSrc = pptNew1; - } - } else { - /* walk source top to bottom */ - ydir = 1; - } - - if (careful && (pptSrc->x < pbox->x1)) { - /* walk source right to left */ - xdir = -1; - - if (nbox > 1) { - /* reverse order of rects in each band */ - pboxNew2 = (BoxPtr)xalloc(sizeof(BoxRec) * nbox); - pptNew2 = (DDXPointPtr)xalloc(sizeof(DDXPointRec) * nbox); - if(!pboxNew2 || !pptNew2) { - if (pptNew2) xfree(pptNew2); - if (pboxNew2) xfree(pboxNew2); - if (pboxNew1) { - xfree(pptNew1); - xfree(pboxNew1); - } - return; - } - pboxBase = pboxNext = pbox; - while (pboxBase < pbox+nbox) { - while ((pboxNext < pbox+nbox) && - (pboxNext->y1 == pboxBase->y1)) - pboxNext++; - pboxTmp = pboxNext; - pptTmp = pptSrc + (pboxTmp - pbox); - while (pboxTmp != pboxBase) { - *pboxNew2++ = *--pboxTmp; - *pptNew2++ = *--pptTmp; - } - pboxBase = pboxNext; - } - pboxNew2 -= nbox; - pbox = pboxNew2; - pptNew2 -= nbox; - pptSrc = pptNew2; - } - } else { - /* walk source left to right */ - xdir = 1; - } - - (*infoRec->ScreenToScreenBitBlt)(infoRec->pScrn, nbox, pptSrc, pbox, - xdir, ydir, pGC->alu, pGC->planemask); - - if (pboxNew2) { - xfree(pptNew2); - xfree(pboxNew2); - } - if (pboxNew1) { - xfree(pptNew1); - xfree(pboxNew1); - } - -} - -void -XAADoImageWrite( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - RegionPtr prgnDst, - DDXPointPtr pptSrc ) -{ - int srcwidth; - unsigned char* psrcBase; /* start of image */ - unsigned char* srcPntr; /* index into the image */ - BoxPtr pbox = REGION_RECTS(prgnDst); - int nbox = REGION_NUM_RECTS(prgnDst); - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - int Bpp = pSrc->bitsPerPixel >> 3; - - psrcBase = (unsigned char *)((PixmapPtr)pSrc)->devPrivate.ptr; - srcwidth = (int)((PixmapPtr)pSrc)->devKind; - - for(; nbox; pbox++, pptSrc++, nbox--) { - srcPntr = psrcBase + (pptSrc->y * srcwidth) + (pptSrc->x * Bpp); - - (*infoRec->WritePixmap)(infoRec->pScrn, pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, srcPntr, srcwidth, - pGC->alu, pGC->planemask, -1, pSrc->bitsPerPixel, pSrc->depth); - } -} - - -void -XAADoImageRead( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - RegionPtr prgnDst, - DDXPointPtr pptSrc ) -{ - int dstwidth; - unsigned char* pdstBase; /* start of image */ - unsigned char* dstPntr; /* index into the image */ - BoxPtr pbox = REGION_RECTS(prgnDst); - int nbox = REGION_NUM_RECTS(prgnDst); - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - int Bpp = pSrc->bitsPerPixel >> 3; /* wouldn't get here unless both - src and dst have same bpp */ - - pdstBase = (unsigned char *)((PixmapPtr)pDst)->devPrivate.ptr; - dstwidth = (int)((PixmapPtr)pDst)->devKind; - - for(; nbox; pbox++, pptSrc++, nbox--) { - dstPntr = pdstBase + (pbox->y1 * dstwidth) + (pbox->x1 * Bpp); - - (*infoRec->ReadPixmap)(infoRec->pScrn, pptSrc->x, pptSrc->y, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, dstPntr, dstwidth, - pSrc->bitsPerPixel, pSrc->depth); - } -} - - -void -XAAScreenToScreenBitBlt( - ScrnInfoPtr pScrn, - int nbox, - DDXPointPtr pptSrc, - BoxPtr pbox, - int xdir, int ydir, - int alu, - unsigned int planemask ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int dirsetup; - - if ((!(infoRec->CopyAreaFlags & ONLY_TWO_BITBLT_DIRECTIONS) - || (xdir == ydir)) && - (!(infoRec->CopyAreaFlags & ONLY_LEFT_TO_RIGHT_BITBLT) - || (xdir == 1))) { - (*infoRec->SetupForScreenToScreenCopy)(pScrn, - xdir, ydir, alu, planemask, -1); - for (; nbox; pbox++, pptSrc++, nbox--) - (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, - pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - SET_SYNC_FLAG(infoRec); - return; - } - - if (infoRec->CopyAreaFlags & ONLY_LEFT_TO_RIGHT_BITBLT) { - /* - * This is the case of a chip that only supports xdir = 1, - * with ydir = 1 or ydir = -1, but we have xdir = -1. - */ - (*infoRec->SetupForScreenToScreenCopy)(pScrn, - 1, ydir, alu, planemask, -1); - for (; nbox; pbox++, pptSrc++, nbox--) - if (pptSrc->y != pbox->y1 || pptSrc->x >= pbox->x1) - /* No problem. Do a xdir = 1 blit instead. */ - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, - pptSrc->x, pptSrc->y, pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - else - { - /* - * This is the difficult case. Needs striping into - * non-overlapping horizontal chunks. - */ - int stripeWidth, w, fullStripes, extra, i; - stripeWidth = 16; - w = pbox->x2 - pbox->x1; - if (pbox->x1 - pptSrc->x < stripeWidth) - stripeWidth = pbox->x1 - pptSrc->x; - fullStripes = w / stripeWidth; - extra = w % stripeWidth; - - /* First, take care of the little bit on the far right */ - if (extra) - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, - pptSrc->x + fullStripes * stripeWidth, pptSrc->y, - pbox->x1 + fullStripes * stripeWidth, pbox->y1, - extra, pbox->y2 - pbox->y1); - - /* Now, take care of the rest of the blit */ - for (i = fullStripes - 1; i >= 0; i--) - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, - pptSrc->x + i * stripeWidth, pptSrc->y, - pbox->x1 + i * stripeWidth, pbox->y1, - stripeWidth, pbox->y2 - pbox->y1); - } - SET_SYNC_FLAG(infoRec); - return; - } - - /* - * Now the case of a chip that only supports xdir = ydir = 1 or - * xdir = ydir = -1, but we have xdir != ydir. - */ - dirsetup = 0; /* No direction set up yet. */ - for (; nbox; pbox++, pptSrc++, nbox--) { - if (xdir == 1 && pptSrc->y != pbox->y1) { - /* Do a xdir = ydir = -1 blit instead. */ - if (dirsetup != -1) { - (*infoRec->SetupForScreenToScreenCopy)(pScrn, - -1, -1, alu, planemask, -1); - dirsetup = -1; - } - (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, - pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - } - else if (xdir == -1 && pptSrc->y != pbox->y1) { - /* Do a xdir = ydir = 1 blit instead. */ - if (dirsetup != 1) { - (*infoRec->SetupForScreenToScreenCopy)(pScrn, - 1, 1, alu, planemask, -1); - dirsetup = 1; - } - (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, - pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - } - else - if (xdir == 1) { - /* - * xdir = 1, ydir = -1. - * Perform line-by-line xdir = ydir = 1 blits, going up. - */ - int i; - if (dirsetup != 1) { - (*infoRec->SetupForScreenToScreenCopy)(pScrn, - 1, 1, alu, planemask, -1); - dirsetup = 1; - } - for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, - pptSrc->x, pptSrc->y + i, pbox->x1, pbox->y1 + i, - pbox->x2 - pbox->x1, 1); - } - else { - /* - * xdir = -1, ydir = 1. - * Perform line-by-line xdir = ydir = -1 blits, going down. - */ - int i; - if (dirsetup != -1) { - (*infoRec->SetupForScreenToScreenCopy)(pScrn, - -1, -1, alu, planemask, -1); - dirsetup = -1; - } - for (i = 0; i < pbox->y2 - pbox->y1; i++) - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, - pptSrc->x, pptSrc->y + i, pbox->x1, pbox->y1 + i, - pbox->x2 - pbox->x1, 1); - } - } /* next box */ - SET_SYNC_FLAG(infoRec); -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "migc.h" +#include "gcstruct.h" +#include "pixmapstr.h" + +/* + Written mostly by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). + */ + + +RegionPtr +XAACopyArea( + DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if(pDstDrawable->type == DRAWABLE_WINDOW) { + if((pSrcDrawable->type == DRAWABLE_WINDOW) || + IS_OFFSCREEN_PIXMAP(pSrcDrawable)){ + if(infoRec->ScreenToScreenBitBlt && + CHECK_ROP(pGC,infoRec->ScreenToScreenBitBltFlags) && + CHECK_ROPSRC(pGC,infoRec->ScreenToScreenBitBltFlags) && + CHECK_PLANEMASK(pGC,infoRec->ScreenToScreenBitBltFlags)) + return (XAABitBlt( pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, + XAADoBitBlt, 0L)); + } else { + if(infoRec->WritePixmap && + ((pDstDrawable->bitsPerPixel == pSrcDrawable->bitsPerPixel) || + ((pDstDrawable->bitsPerPixel == 24) && + (pSrcDrawable->bitsPerPixel == 32) && + (infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) && + CHECK_ROP(pGC,infoRec->WritePixmapFlags) && + CHECK_ROPSRC(pGC,infoRec->WritePixmapFlags) && + CHECK_PLANEMASK(pGC,infoRec->WritePixmapFlags) && + CHECK_NO_GXCOPY(pGC,infoRec->WritePixmapFlags)) + return (XAABitBlt( pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, + XAADoImageWrite, 0L)); + } + } else if(IS_OFFSCREEN_PIXMAP(pDstDrawable)){ + if((pSrcDrawable->type == DRAWABLE_WINDOW) || + IS_OFFSCREEN_PIXMAP(pSrcDrawable)){ + if(infoRec->ScreenToScreenBitBlt && + CHECK_ROP(pGC,infoRec->ScreenToScreenBitBltFlags) && + CHECK_ROPSRC(pGC,infoRec->ScreenToScreenBitBltFlags) && + CHECK_PLANEMASK(pGC,infoRec->ScreenToScreenBitBltFlags)) + return (XAABitBlt( pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, + XAADoBitBlt, 0L)); + } + } + + return (XAAFallbackOps.CopyArea(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty)); +} + + +void +XAADoBitBlt( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + RegionPtr prgnDst, + DDXPointPtr pptSrc ) +{ + int nbox, careful; + BoxPtr pbox, pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; + DDXPointPtr pptTmp, pptNew1, pptNew2; + int xdir, ydir; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + /* XXX we have to err on the side of safety when both are windows, + * because we don't know if IncludeInferiors is being used. + */ + careful = ((pSrc == pDst) || + ((pSrc->type == DRAWABLE_WINDOW) && + (pDst->type == DRAWABLE_WINDOW))); + + pbox = REGION_RECTS(prgnDst); + nbox = REGION_NUM_RECTS(prgnDst); + + pboxNew1 = NULL; + pptNew1 = NULL; + pboxNew2 = NULL; + pptNew2 = NULL; + if (careful && (pptSrc->y < pbox->y1)) { + /* walk source botttom to top */ + ydir = -1; + + if (nbox > 1) { + /* keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr)malloc(sizeof(BoxRec) * nbox); + if(!pboxNew1) + return; + pptNew1 = (DDXPointPtr)malloc(sizeof(DDXPointRec) * nbox); + if(!pptNew1) { + free(pboxNew1); + return; + } + pboxBase = pboxNext = pbox+nbox-1; + while (pboxBase >= pbox) { + while ((pboxNext >= pbox) && + (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext+1; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp <= pboxBase) { + *pboxNew1++ = *pboxTmp++; + *pptNew1++ = *pptTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + pptNew1 -= nbox; + pptSrc = pptNew1; + } + } else { + /* walk source top to bottom */ + ydir = 1; + } + + if (careful && (pptSrc->x < pbox->x1)) { + /* walk source right to left */ + xdir = -1; + + if (nbox > 1) { + /* reverse order of rects in each band */ + pboxNew2 = (BoxPtr)malloc(sizeof(BoxRec) * nbox); + pptNew2 = (DDXPointPtr)malloc(sizeof(DDXPointRec) * nbox); + if(!pboxNew2 || !pptNew2) { + if (pptNew2) free(pptNew2); + if (pboxNew2) free(pboxNew2); + if (pboxNew1) { + free(pptNew1); + free(pboxNew1); + } + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox+nbox) { + while ((pboxNext < pbox+nbox) && + (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp != pboxBase) { + *pboxNew2++ = *--pboxTmp; + *pptNew2++ = *--pptTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + pptNew2 -= nbox; + pptSrc = pptNew2; + } + } else { + /* walk source left to right */ + xdir = 1; + } + + (*infoRec->ScreenToScreenBitBlt)(infoRec->pScrn, nbox, pptSrc, pbox, + xdir, ydir, pGC->alu, pGC->planemask); + + if (pboxNew2) { + free(pptNew2); + free(pboxNew2); + } + if (pboxNew1) { + free(pptNew1); + free(pboxNew1); + } + +} + +void +XAADoImageWrite( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + RegionPtr prgnDst, + DDXPointPtr pptSrc ) +{ + int srcwidth; + unsigned char* psrcBase; /* start of image */ + unsigned char* srcPntr; /* index into the image */ + BoxPtr pbox = REGION_RECTS(prgnDst); + int nbox = REGION_NUM_RECTS(prgnDst); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int Bpp = pSrc->bitsPerPixel >> 3; + + psrcBase = (unsigned char *)((PixmapPtr)pSrc)->devPrivate.ptr; + srcwidth = (int)((PixmapPtr)pSrc)->devKind; + + for(; nbox; pbox++, pptSrc++, nbox--) { + srcPntr = psrcBase + (pptSrc->y * srcwidth) + (pptSrc->x * Bpp); + + (*infoRec->WritePixmap)(infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, srcPntr, srcwidth, + pGC->alu, pGC->planemask, -1, pSrc->bitsPerPixel, pSrc->depth); + } +} + + +void +XAADoImageRead( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + RegionPtr prgnDst, + DDXPointPtr pptSrc ) +{ + int dstwidth; + unsigned char* pdstBase; /* start of image */ + unsigned char* dstPntr; /* index into the image */ + BoxPtr pbox = REGION_RECTS(prgnDst); + int nbox = REGION_NUM_RECTS(prgnDst); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int Bpp = pSrc->bitsPerPixel >> 3; /* wouldn't get here unless both + src and dst have same bpp */ + + pdstBase = (unsigned char *)((PixmapPtr)pDst)->devPrivate.ptr; + dstwidth = (int)((PixmapPtr)pDst)->devKind; + + for(; nbox; pbox++, pptSrc++, nbox--) { + dstPntr = pdstBase + (pbox->y1 * dstwidth) + (pbox->x1 * Bpp); + + (*infoRec->ReadPixmap)(infoRec->pScrn, pptSrc->x, pptSrc->y, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, dstPntr, dstwidth, + pSrc->bitsPerPixel, pSrc->depth); + } +} + + +void +XAAScreenToScreenBitBlt( + ScrnInfoPtr pScrn, + int nbox, + DDXPointPtr pptSrc, + BoxPtr pbox, + int xdir, int ydir, + int alu, + unsigned int planemask ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int dirsetup; + + if ((!(infoRec->CopyAreaFlags & ONLY_TWO_BITBLT_DIRECTIONS) + || (xdir == ydir)) && + (!(infoRec->CopyAreaFlags & ONLY_LEFT_TO_RIGHT_BITBLT) + || (xdir == 1))) { + (*infoRec->SetupForScreenToScreenCopy)(pScrn, + xdir, ydir, alu, planemask, -1); + for (; nbox; pbox++, pptSrc++, nbox--) + (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, + pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + SET_SYNC_FLAG(infoRec); + return; + } + + if (infoRec->CopyAreaFlags & ONLY_LEFT_TO_RIGHT_BITBLT) { + /* + * This is the case of a chip that only supports xdir = 1, + * with ydir = 1 or ydir = -1, but we have xdir = -1. + */ + (*infoRec->SetupForScreenToScreenCopy)(pScrn, + 1, ydir, alu, planemask, -1); + for (; nbox; pbox++, pptSrc++, nbox--) + if (pptSrc->y != pbox->y1 || pptSrc->x >= pbox->x1) + /* No problem. Do a xdir = 1 blit instead. */ + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pptSrc->x, pptSrc->y, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + else + { + /* + * This is the difficult case. Needs striping into + * non-overlapping horizontal chunks. + */ + int stripeWidth, w, fullStripes, extra, i; + stripeWidth = 16; + w = pbox->x2 - pbox->x1; + if (pbox->x1 - pptSrc->x < stripeWidth) + stripeWidth = pbox->x1 - pptSrc->x; + fullStripes = w / stripeWidth; + extra = w % stripeWidth; + + /* First, take care of the little bit on the far right */ + if (extra) + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pptSrc->x + fullStripes * stripeWidth, pptSrc->y, + pbox->x1 + fullStripes * stripeWidth, pbox->y1, + extra, pbox->y2 - pbox->y1); + + /* Now, take care of the rest of the blit */ + for (i = fullStripes - 1; i >= 0; i--) + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pptSrc->x + i * stripeWidth, pptSrc->y, + pbox->x1 + i * stripeWidth, pbox->y1, + stripeWidth, pbox->y2 - pbox->y1); + } + SET_SYNC_FLAG(infoRec); + return; + } + + /* + * Now the case of a chip that only supports xdir = ydir = 1 or + * xdir = ydir = -1, but we have xdir != ydir. + */ + dirsetup = 0; /* No direction set up yet. */ + for (; nbox; pbox++, pptSrc++, nbox--) { + if (xdir == 1 && pptSrc->y != pbox->y1) { + /* Do a xdir = ydir = -1 blit instead. */ + if (dirsetup != -1) { + (*infoRec->SetupForScreenToScreenCopy)(pScrn, + -1, -1, alu, planemask, -1); + dirsetup = -1; + } + (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, + pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + } + else if (xdir == -1 && pptSrc->y != pbox->y1) { + /* Do a xdir = ydir = 1 blit instead. */ + if (dirsetup != 1) { + (*infoRec->SetupForScreenToScreenCopy)(pScrn, + 1, 1, alu, planemask, -1); + dirsetup = 1; + } + (*infoRec->SubsequentScreenToScreenCopy)(pScrn,pptSrc->x, pptSrc->y, + pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + } + else + if (xdir == 1) { + /* + * xdir = 1, ydir = -1. + * Perform line-by-line xdir = ydir = 1 blits, going up. + */ + int i; + if (dirsetup != 1) { + (*infoRec->SetupForScreenToScreenCopy)(pScrn, + 1, 1, alu, planemask, -1); + dirsetup = 1; + } + for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pptSrc->x, pptSrc->y + i, pbox->x1, pbox->y1 + i, + pbox->x2 - pbox->x1, 1); + } + else { + /* + * xdir = -1, ydir = 1. + * Perform line-by-line xdir = ydir = -1 blits, going down. + */ + int i; + if (dirsetup != -1) { + (*infoRec->SetupForScreenToScreenCopy)(pScrn, + -1, -1, alu, planemask, -1); + dirsetup = -1; + } + for (i = 0; i < pbox->y2 - pbox->y1; i++) + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, + pptSrc->x, pptSrc->y + i, pbox->x1, pbox->y1 + i, + pbox->x2 - pbox->x1, 1); + } + } /* next box */ + SET_SYNC_FLAG(infoRec); +} diff --git a/xorg-server/hw/xfree86/xaa/xaaCpyPlane.c b/xorg-server/hw/xfree86/xaa/xaaCpyPlane.c index aa4c0407c..358cb6fb2 100644 --- a/xorg-server/hw/xfree86/xaa/xaaCpyPlane.c +++ b/xorg-server/hw/xfree86/xaa/xaaCpyPlane.c @@ -1,208 +1,208 @@ - -/* - A CopyPlane function that handles bitmap->screen copies and - sends anything else to the Fallback. - - Also, a PushPixels for solid fill styles. - - Written by Mark Vojkovich (markv@valinux.com) - -*/ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#include "servermd.h" - -#include -#include "scrnintstr.h" -#include "mi.h" -#include "pixmapstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xaawrap.h" - -static void XAACopyPlane1toNColorExpand(DrawablePtr pSrc, DrawablePtr pDst, - GCPtr pGC, RegionPtr rgnDst, - DDXPointPtr pptSrc); -static void XAACopyPlaneNtoNColorExpand(DrawablePtr pSrc, DrawablePtr pDst, - GCPtr pGC, RegionPtr rgnDst, - DDXPointPtr pptSrc); - - -static unsigned long TmpBitPlane; - -RegionPtr -XAACopyPlaneColorExpansion( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty, - unsigned long bitPlane -){ - if((pSrc->type == DRAWABLE_PIXMAP) && !XAA_DEPTH_BUG(pGC)) { - if(pSrc->bitsPerPixel == 1) { - return(XAABitBlt(pSrc, pDst, pGC, srcx, srcy, - width, height, dstx, dsty, - XAACopyPlane1toNColorExpand, bitPlane)); - } else if(bitPlane < (1 << pDst->depth)){ - TmpBitPlane = bitPlane; - return(XAABitBlt(pSrc, pDst, pGC, srcx, srcy, - width, height, dstx, dsty, - XAACopyPlaneNtoNColorExpand, bitPlane)); - } - } - - return (XAAFallbackOps.CopyPlane(pSrc, pDst, pGC, srcx, srcy, - width, height, dstx, dsty, bitPlane)); -} - - -static void -XAACopyPlane1toNColorExpand( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - RegionPtr rgnDst, - DDXPointPtr pptSrc ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - BoxPtr pbox = REGION_RECTS(rgnDst); - int numrects = REGION_NUM_RECTS(rgnDst); - unsigned char *src = ((PixmapPtr)pSrc)->devPrivate.ptr; - int srcwidth = ((PixmapPtr)pSrc)->devKind; - - while(numrects--) { - (*infoRec->WriteBitmap)(infoRec->pScrn, pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, - src + (srcwidth * pptSrc->y) + ((pptSrc->x >> 5) << 2), - srcwidth, pptSrc->x & 31, - pGC->fgPixel, pGC->bgPixel, pGC->alu, pGC->planemask); - pbox++; pptSrc++; - } -} - - -static void -XAACopyPlaneNtoNColorExpand( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - RegionPtr rgnDst, - DDXPointPtr pptSrc -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - BoxPtr pbox = REGION_RECTS(rgnDst); - int numrects = REGION_NUM_RECTS(rgnDst); - unsigned char *src = ((PixmapPtr)pSrc)->devPrivate.ptr; - unsigned char *data, *srcPtr, *dataPtr; - int srcwidth = ((PixmapPtr)pSrc)->devKind; - int pitch, width, height, h, i, index, offset; - int Bpp = pSrc->bitsPerPixel >> 3; - unsigned long mask = TmpBitPlane; - - if(TmpBitPlane < (1 << 8)) { - offset = 0; - } else if(TmpBitPlane < (1 << 16)) { - offset = 1; - mask >>= 8; - } else if(TmpBitPlane < (1 << 24)) { - offset = 2; - mask >>= 16; - } else { - offset = 3; - mask >>= 24; - } - - if(IS_OFFSCREEN_PIXMAP(pSrc)) - SYNC_CHECK(pSrc); - - while(numrects--) { - width = pbox->x2 - pbox->x1; - h = height = pbox->y2 - pbox->y1; - pitch = BitmapBytePad(width); - - if(!(data = xcalloc(height, pitch))) - goto ALLOC_FAILED; - - dataPtr = data; - srcPtr = ((pptSrc->y) * srcwidth) + src + - ((pptSrc->x) * Bpp) + offset; - - while(h--) { - for(i = index = 0; i < width; i++, index += Bpp) { - if(mask & srcPtr[index]) - dataPtr[i >> 3] |= (1 << (i & 7)); - } - dataPtr += pitch; - srcPtr += srcwidth; - } - - (*infoRec->WriteBitmap)(infoRec->pScrn, - pbox->x1, pbox->y1, width, height, data, pitch, 0, - pGC->fgPixel, pGC->bgPixel, pGC->alu, pGC->planemask); - - xfree(data); - -ALLOC_FAILED: - - pbox++; pptSrc++; - } -} - -void -XAAPushPixelsSolidColorExpansion( - GCPtr pGC, - PixmapPtr pBitMap, - DrawablePtr pDraw, - int dx, int dy, - int xOrg, int yOrg ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - int MaxBoxes = REGION_NUM_RECTS(pGC->pCompositeClip); - BoxPtr pbox, pClipBoxes; - int nboxes, srcx, srcy; - xRectangle TheRect; - unsigned char *src = pBitMap->devPrivate.ptr; - int srcwidth = pBitMap->devKind; - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - TheRect.x = xOrg; - TheRect.y = yOrg; - TheRect.width = dx; - TheRect.height = dy; - - if(MaxBoxes > (infoRec->PreAllocSize/sizeof(BoxRec))) { - pClipBoxes = xalloc(MaxBoxes * sizeof(BoxRec)); - if(!pClipBoxes) return; - } else pClipBoxes = (BoxPtr)infoRec->PreAllocMem; - - nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect); - pbox = pClipBoxes; - - while(nboxes--) { - srcx = pbox->x1 - xOrg; - srcy = pbox->y1 - yOrg; - (*infoRec->WriteBitmap)(infoRec->pScrn, pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, - src + (srcwidth * srcy) + ((srcx >> 5) << 2), - srcwidth, srcx & 31, - pGC->fgPixel, -1, pGC->alu, pGC->planemask); - pbox++; - } - - if(pClipBoxes != (BoxPtr)infoRec->PreAllocMem) - xfree(pClipBoxes); -} - + +/* + A CopyPlane function that handles bitmap->screen copies and + sends anything else to the Fallback. + + Also, a PushPixels for solid fill styles. + + Written by Mark Vojkovich (markv@valinux.com) + +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "servermd.h" + +#include +#include "scrnintstr.h" +#include "mi.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" + +static void XAACopyPlane1toNColorExpand(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, RegionPtr rgnDst, + DDXPointPtr pptSrc); +static void XAACopyPlaneNtoNColorExpand(DrawablePtr pSrc, DrawablePtr pDst, + GCPtr pGC, RegionPtr rgnDst, + DDXPointPtr pptSrc); + + +static unsigned long TmpBitPlane; + +RegionPtr +XAACopyPlaneColorExpansion( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane +){ + if((pSrc->type == DRAWABLE_PIXMAP) && !XAA_DEPTH_BUG(pGC)) { + if(pSrc->bitsPerPixel == 1) { + return(XAABitBlt(pSrc, pDst, pGC, srcx, srcy, + width, height, dstx, dsty, + XAACopyPlane1toNColorExpand, bitPlane)); + } else if(bitPlane < (1 << pDst->depth)){ + TmpBitPlane = bitPlane; + return(XAABitBlt(pSrc, pDst, pGC, srcx, srcy, + width, height, dstx, dsty, + XAACopyPlaneNtoNColorExpand, bitPlane)); + } + } + + return (XAAFallbackOps.CopyPlane(pSrc, pDst, pGC, srcx, srcy, + width, height, dstx, dsty, bitPlane)); +} + + +static void +XAACopyPlane1toNColorExpand( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + RegionPtr rgnDst, + DDXPointPtr pptSrc ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + BoxPtr pbox = REGION_RECTS(rgnDst); + int numrects = REGION_NUM_RECTS(rgnDst); + unsigned char *src = ((PixmapPtr)pSrc)->devPrivate.ptr; + int srcwidth = ((PixmapPtr)pSrc)->devKind; + + while(numrects--) { + (*infoRec->WriteBitmap)(infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + src + (srcwidth * pptSrc->y) + ((pptSrc->x >> 5) << 2), + srcwidth, pptSrc->x & 31, + pGC->fgPixel, pGC->bgPixel, pGC->alu, pGC->planemask); + pbox++; pptSrc++; + } +} + + +static void +XAACopyPlaneNtoNColorExpand( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + RegionPtr rgnDst, + DDXPointPtr pptSrc +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + BoxPtr pbox = REGION_RECTS(rgnDst); + int numrects = REGION_NUM_RECTS(rgnDst); + unsigned char *src = ((PixmapPtr)pSrc)->devPrivate.ptr; + unsigned char *data, *srcPtr, *dataPtr; + int srcwidth = ((PixmapPtr)pSrc)->devKind; + int pitch, width, height, h, i, index, offset; + int Bpp = pSrc->bitsPerPixel >> 3; + unsigned long mask = TmpBitPlane; + + if(TmpBitPlane < (1 << 8)) { + offset = 0; + } else if(TmpBitPlane < (1 << 16)) { + offset = 1; + mask >>= 8; + } else if(TmpBitPlane < (1 << 24)) { + offset = 2; + mask >>= 16; + } else { + offset = 3; + mask >>= 24; + } + + if(IS_OFFSCREEN_PIXMAP(pSrc)) + SYNC_CHECK(pSrc); + + while(numrects--) { + width = pbox->x2 - pbox->x1; + h = height = pbox->y2 - pbox->y1; + pitch = BitmapBytePad(width); + + if(!(data = calloc(height, pitch))) + goto ALLOC_FAILED; + + dataPtr = data; + srcPtr = ((pptSrc->y) * srcwidth) + src + + ((pptSrc->x) * Bpp) + offset; + + while(h--) { + for(i = index = 0; i < width; i++, index += Bpp) { + if(mask & srcPtr[index]) + dataPtr[i >> 3] |= (1 << (i & 7)); + } + dataPtr += pitch; + srcPtr += srcwidth; + } + + (*infoRec->WriteBitmap)(infoRec->pScrn, + pbox->x1, pbox->y1, width, height, data, pitch, 0, + pGC->fgPixel, pGC->bgPixel, pGC->alu, pGC->planemask); + + free(data); + +ALLOC_FAILED: + + pbox++; pptSrc++; + } +} + +void +XAAPushPixelsSolidColorExpansion( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, + int xOrg, int yOrg ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int MaxBoxes = REGION_NUM_RECTS(pGC->pCompositeClip); + BoxPtr pbox, pClipBoxes; + int nboxes, srcx, srcy; + xRectangle TheRect; + unsigned char *src = pBitMap->devPrivate.ptr; + int srcwidth = pBitMap->devKind; + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + TheRect.x = xOrg; + TheRect.y = yOrg; + TheRect.width = dx; + TheRect.height = dy; + + if(MaxBoxes > (infoRec->PreAllocSize/sizeof(BoxRec))) { + pClipBoxes = malloc(MaxBoxes * sizeof(BoxRec)); + if(!pClipBoxes) return; + } else pClipBoxes = (BoxPtr)infoRec->PreAllocMem; + + nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect); + pbox = pClipBoxes; + + while(nboxes--) { + srcx = pbox->x1 - xOrg; + srcy = pbox->y1 - yOrg; + (*infoRec->WriteBitmap)(infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + src + (srcwidth * srcy) + ((srcx >> 5) << 2), + srcwidth, srcx & 31, + pGC->fgPixel, -1, pGC->alu, pGC->planemask); + pbox++; + } + + if(pClipBoxes != (BoxPtr)infoRec->PreAllocMem) + free(pClipBoxes); +} + diff --git a/xorg-server/hw/xfree86/xaa/xaaCpyWin.c b/xorg-server/hw/xfree86/xaa/xaaCpyWin.c index 31c421e65..34f460f24 100644 --- a/xorg-server/hw/xfree86/xaa/xaaCpyWin.c +++ b/xorg-server/hw/xfree86/xaa/xaaCpyWin.c @@ -1,82 +1,82 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "windowstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "xaawrap.h" - -/* - Written by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). -*/ - -void -XAACopyWindow( - WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc ) -{ - DDXPointPtr pptSrc, ppt; - RegionRec rgnDst; - BoxPtr pbox; - int dx, dy, nbox; - WindowPtr pwinRoot; - ScreenPtr pScreen = pWin->drawable.pScreen; - XAAInfoRecPtr infoRec = - GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); - - if (!infoRec->pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { - XAA_SCREEN_PROLOGUE (pScreen, CopyWindow); - if(infoRec->pScrn->vtSema && infoRec->NeedToSync) { - (*infoRec->Sync)(infoRec->pScrn); - infoRec->NeedToSync = FALSE; - } - (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); - XAA_SCREEN_EPILOGUE (pScreen, CopyWindow, XAACopyWindow); - return; - } - - pwinRoot = WindowTable[pScreen->myNum]; - - REGION_NULL(pScreen, &rgnDst); - - dx = ptOldOrg.x - pWin->drawable.x; - dy = ptOldOrg.y - pWin->drawable.y; - REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); - REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); - - pbox = REGION_RECTS(&rgnDst); - nbox = REGION_NUM_RECTS(&rgnDst); - if(!nbox || - !(pptSrc = (DDXPointPtr )xalloc(nbox * sizeof(DDXPointRec)))) { - REGION_UNINIT(pScreen, &rgnDst); - return; - } - ppt = pptSrc; - - while(nbox--) { - ppt->x = pbox->x1 + dx; - ppt->y = pbox->y1 + dy; - ppt++; pbox++; - } - - infoRec->ScratchGC.planemask = ~0L; - infoRec->ScratchGC.alu = GXcopy; - - XAADoBitBlt((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, - &(infoRec->ScratchGC), &rgnDst, pptSrc); - - xfree(pptSrc); - REGION_UNINIT(pScreen, &rgnDst); -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "xaawrap.h" + +/* + Written by Harm Hanemaayer (H.Hanemaayer@inter.nl.net). +*/ + +void +XAACopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc ) +{ + DDXPointPtr pptSrc, ppt; + RegionRec rgnDst; + BoxPtr pbox; + int dx, dy, nbox; + WindowPtr pwinRoot; + ScreenPtr pScreen = pWin->drawable.pScreen; + XAAInfoRecPtr infoRec = + GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); + + if (!infoRec->pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { + XAA_SCREEN_PROLOGUE (pScreen, CopyWindow); + if(infoRec->pScrn->vtSema && infoRec->NeedToSync) { + (*infoRec->Sync)(infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + XAA_SCREEN_EPILOGUE (pScreen, CopyWindow, XAACopyWindow); + return; + } + + pwinRoot = WindowTable[pScreen->myNum]; + + REGION_NULL(pScreen, &rgnDst); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + pbox = REGION_RECTS(&rgnDst); + nbox = REGION_NUM_RECTS(&rgnDst); + if(!nbox || + !(pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec)))) { + REGION_UNINIT(pScreen, &rgnDst); + return; + } + ppt = pptSrc; + + while(nbox--) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + ppt++; pbox++; + } + + infoRec->ScratchGC.planemask = ~0L; + infoRec->ScratchGC.alu = GXcopy; + + XAADoBitBlt((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + + free(pptSrc); + REGION_UNINIT(pScreen, &rgnDst); +} diff --git a/xorg-server/hw/xfree86/xaa/xaaGC.c b/xorg-server/hw/xfree86/xaa/xaaGC.c index e6083d529..d029d982b 100644 --- a/xorg-server/hw/xfree86/xaa/xaaGC.c +++ b/xorg-server/hw/xfree86/xaa/xaaGC.c @@ -1,656 +1,656 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" -#include "migc.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "xaawrap.h" - -static void XAAValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); -static void XAAChangeGC(GCPtr pGC, unsigned long mask); -static void XAACopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); -static void XAADestroyGC(GCPtr pGC); -static void XAAChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects); -static void XAADestroyClip(GCPtr pGC); -static void XAACopyClip(GCPtr pgcDst, GCPtr pgcSrc); - -GCFuncs XAAGCFuncs = { - XAAValidateGC, XAAChangeGC, XAACopyGC, XAADestroyGC, - XAAChangeClip, XAADestroyClip, XAACopyClip -}; - -extern GCOps XAAPixmapOps; - -Bool -XAACreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&pGC->devPrivates, - XAAGetGCKey()); - Bool ret; - - XAA_SCREEN_PROLOGUE(pScreen,CreateGC); - - if((ret = (*pScreen->CreateGC)(pGC))) { - pGCPriv->wrapOps = NULL; - pGCPriv->wrapFuncs = pGC->funcs; - pGCPriv->XAAOps = &XAAFallbackOps; - pGCPriv->flags = 0; - pGCPriv->DashLength = 0; - pGCPriv->DashPattern = NULL; - pGCPriv->changes = 0; - /* initialize any other private fields here */ - pGC->funcs = &XAAGCFuncs; - } - - XAA_SCREEN_EPILOGUE(pScreen,CreateGC,XAACreateGC); - - return ret; -} - - -static void -XAAValidateGC( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - XAA_GC_FUNC_PROLOGUE(pGC); - - (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); - - if((changes & GCPlaneMask) && - ((pGC->planemask & infoRec->FullPlanemasks[pGC->depth - 1]) == - infoRec->FullPlanemasks[pGC->depth - 1])) - { - pGC->planemask = ~0; - } - - if(pGC->depth != 32) { - /* 0xffffffff is reserved for transparency */ - if(pGC->bgPixel == 0xffffffff) - pGC->bgPixel = 0x7fffffff; - if(pGC->fgPixel == 0xffffffff) - pGC->fgPixel = 0x7fffffff; - } - - if((pDraw->type == DRAWABLE_PIXMAP) && !IS_OFFSCREEN_PIXMAP(pDraw)){ - pGCPriv->flags = OPS_ARE_PIXMAP; - pGCPriv->changes |= changes; - - /* make sure we're not using videomemory pixmaps to render - onto system memory drawables */ - - if((pGC->fillStyle == FillTiled) && - IS_OFFSCREEN_PIXMAP(pGC->tile.pixmap) && - !OFFSCREEN_PIXMAP_LOCKED(pGC->tile.pixmap)) { - - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); - FBAreaPtr area = pPriv->offscreenArea; - - XAARemoveAreaCallback(area); /* clobbers pPriv->offscreenArea */ - xf86FreeOffscreenArea(area); - } - } - else if(!infoRec->pScrn->vtSema && (pDraw->type == DRAWABLE_WINDOW)) { - pGCPriv->flags = 0; - pGCPriv->changes |= changes; - } - else { - if(!(pGCPriv->flags & OPS_ARE_ACCEL)) { - changes |= pGCPriv->changes; - pGCPriv->changes = 0; - } - pGCPriv->flags = OPS_ARE_ACCEL; - -#if 1 - /* Ugh. If we can't use the blitter on offscreen pixmaps used - as tiles, then we need to move them out as cfb can't handle - tiles with non-zero origins */ - - if((pGC->fillStyle == FillTiled) && - IS_OFFSCREEN_PIXMAP(pGC->tile.pixmap) && - (DO_PIXMAP_COPY != (*infoRec->TiledFillChooser)(pGC))) { - - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); - FBAreaPtr area = pPriv->offscreenArea; - - XAARemoveAreaCallback(area); /* clobbers pPriv->offscreenArea */ - xf86FreeOffscreenArea(area); - } -#endif - } - - XAA_GC_FUNC_EPILOGUE(pGC); - - if(!(pGCPriv->flags & OPS_ARE_ACCEL)) return; - - if((changes & GCTile) && !pGC->tileIsPixel && pGC->tile.pixmap){ - XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); - - if(pixPriv->flags & DIRTY) { - pixPriv->flags &= ~(DIRTY | REDUCIBILITY_MASK); - pGC->tile.pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - } - } - if((changes & GCStipple) && pGC->stipple){ - XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); - - if(pixPriv->flags & DIRTY) { - pixPriv->flags &= ~(DIRTY | REDUCIBILITY_MASK); - pGC->stipple->drawable.serialNumber = NEXT_SERIAL_NUMBER; - } - } - - /* If our Ops are still the default ones we need to allocate new ones */ - if(pGC->ops == &XAAFallbackOps) { - if(!(pGCPriv->XAAOps = xalloc(sizeof(GCOps)))) { - pGCPriv->XAAOps = &XAAFallbackOps; - return; - } - /* make a modifiable copy of the default ops */ - memcpy(pGCPriv->XAAOps, &XAAFallbackOps, sizeof(GCOps)); - pGC->ops = pGCPriv->XAAOps; - changes = ~0; - } - - if(!changes) return; - - if((changes & GCDashList) && infoRec->ComputeDash) - infoRec->ComputeDash(pGC); - - if(changes & infoRec->FillSpansMask) - (*infoRec->ValidateFillSpans)(pGC, changes, pDraw); - - if(changes & infoRec->SetSpansMask) - (*infoRec->ValidateSetSpans)(pGC, changes, pDraw); - - if(changes & infoRec->PutImageMask) - (*infoRec->ValidatePutImage)(pGC, changes, pDraw); - - if(changes & infoRec->CopyAreaMask) - (*infoRec->ValidateCopyArea)(pGC, changes, pDraw); - - if(changes & infoRec->CopyPlaneMask) - (*infoRec->ValidateCopyPlane)(pGC, changes, pDraw); - - if(changes & infoRec->PolyPointMask) - (*infoRec->ValidatePolyPoint)(pGC, changes, pDraw); - - if(changes & infoRec->PolylinesMask) - (*infoRec->ValidatePolylines)(pGC, changes, pDraw); - - if(changes & infoRec->PolySegmentMask) - (*infoRec->ValidatePolySegment)(pGC, changes, pDraw); - - if(changes & infoRec->PolyRectangleMask) - (*infoRec->ValidatePolyRectangle)(pGC, changes, pDraw); - - if(changes & infoRec->PolyArcMask) - (*infoRec->ValidatePolyArc)(pGC, changes, pDraw); - - if(changes & infoRec->FillPolygonMask) - (*infoRec->ValidateFillPolygon)(pGC, changes, pDraw); - - if(changes & infoRec->PolyFillRectMask) - (*infoRec->ValidatePolyFillRect)(pGC, changes, pDraw); - - if(changes & infoRec->PolyFillArcMask) - (*infoRec->ValidatePolyFillArc)(pGC, changes, pDraw); - - if(changes & infoRec->PolyGlyphBltMask) - (*infoRec->ValidatePolyGlyphBlt)(pGC, changes, pDraw); - - if(changes & infoRec->ImageGlyphBltMask) - (*infoRec->ValidateImageGlyphBlt)(pGC, changes, pDraw); - - if(changes & infoRec->PolyText8Mask) - (*infoRec->ValidatePolyText8)(pGC, changes, pDraw); - - if(changes & infoRec->PolyText16Mask) - (*infoRec->ValidatePolyText16)(pGC, changes, pDraw); - - if(changes & infoRec->ImageText8Mask) - (*infoRec->ValidateImageText8)(pGC, changes, pDraw); - - if(changes & infoRec->ImageText16Mask) - (*infoRec->ValidateImageText16)(pGC, changes, pDraw); - - if(changes & infoRec->PushPixelsMask) - (*infoRec->ValidatePushPixels)(pGC, changes, pDraw); -} - - -static void -XAADestroyGC(GCPtr pGC) -{ - XAA_GC_FUNC_PROLOGUE (pGC); - - if(pGCPriv->XAAOps != &XAAFallbackOps) - xfree(pGCPriv->XAAOps); - - if(pGCPriv->DashPattern) - xfree(pGCPriv->DashPattern); - - (*pGC->funcs->DestroyGC)(pGC); - XAA_GC_FUNC_EPILOGUE (pGC); -} - -static void -XAAChangeGC ( - GCPtr pGC, - unsigned long mask -) -{ - XAA_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeGC) (pGC, mask); - XAA_GC_FUNC_EPILOGUE (pGC); - - /* we have to assume that shared memory pixmaps are dirty - because we can't wrap all operations on them */ - - if((mask & GCTile) && !pGC->tileIsPixel && - PIXMAP_IS_SHARED(pGC->tile.pixmap)) - { - XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); - pPixPriv->flags |= DIRTY; - } - - if((mask & GCStipple) && PIXMAP_IS_SHARED(pGC->stipple)){ - XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); - pPixPriv->flags |= DIRTY; - } -} - -static void -XAACopyGC ( - GCPtr pGCSrc, - unsigned long mask, - GCPtr pGCDst) -{ - XAA_GC_FUNC_PROLOGUE (pGCDst); - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - XAA_GC_FUNC_EPILOGUE (pGCDst); -} -static void -XAAChangeClip ( - GCPtr pGC, - int type, - pointer pvalue, - int nrects ) -{ - XAA_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); - XAA_GC_FUNC_EPILOGUE (pGC); -} - -static void -XAACopyClip(GCPtr pgcDst, GCPtr pgcSrc) -{ - XAA_GC_FUNC_PROLOGUE (pgcDst); - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - XAA_GC_FUNC_EPILOGUE (pgcDst); -} - -static void -XAADestroyClip(GCPtr pGC) -{ - XAA_GC_FUNC_PROLOGUE (pGC); - (* pGC->funcs->DestroyClip)(pGC); - XAA_GC_FUNC_EPILOGUE (pGC); -} - -/**** Pixmap Wrappers ****/ - - - -static void -XAAFillSpansPixmap( - DrawablePtr pDraw, - GC *pGC, - int nInit, - DDXPointPtr pptInit, - int *pwidthInit, - int fSorted -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static void -XAASetSpansPixmap( - DrawablePtr pDraw, - GCPtr pGC, - char *pcharsrc, - register DDXPointPtr ppt, - int *pwidth, - int nspans, - int fSorted -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static void -XAAPutImagePixmap( - DrawablePtr pDraw, - GCPtr pGC, - int depth, - int x, int y, int w, int h, - int leftPad, - int format, - char *pImage -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, - leftPad, format, pImage); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static RegionPtr -XAACopyAreaPixmap( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - RegionPtr ret; - - if(infoRec->pScrn->vtSema && - ((pSrc->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pSrc))) - { - if(infoRec->ReadPixmap && (pGC->alu == GXcopy) && - (pSrc->bitsPerPixel == pDst->bitsPerPixel) && - ((pGC->planemask & infoRec->FullPlanemasks[pSrc->depth - 1]) - == infoRec->FullPlanemasks[pSrc->depth - 1])) - { - XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst)); - pixPriv->flags |= DIRTY; - - return (XAABitBlt( pSrc, pDst, pGC, - srcx, srcy, width, height, dstx, dsty, - XAADoImageRead, 0L)); - } else - if(infoRec->NeedToSync) { - (*infoRec->Sync)(infoRec->pScrn); - infoRec->NeedToSync = FALSE; - } - } - - { - XAA_PIXMAP_OP_PROLOGUE(pGC, pDst); - ret = (*pGC->ops->CopyArea)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty); - XAA_PIXMAP_OP_EPILOGUE(pGC); - } - return ret; -} - -static RegionPtr -XAACopyPlanePixmap( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty, - unsigned long bitPlane -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - RegionPtr ret; - - XAA_PIXMAP_OP_PROLOGUE(pGC, pDst); - - if(infoRec->pScrn->vtSema && - ((pSrc->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pSrc))){ - if(infoRec->NeedToSync) { - (*infoRec->Sync)(infoRec->pScrn); - infoRec->NeedToSync = FALSE; - } - } - - ret = (*pGC->ops->CopyPlane)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); - XAA_PIXMAP_OP_EPILOGUE(pGC); - return ret; -} - -static void -XAAPolyPointPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int npt, - xPoint *pptInit -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - - -static void -XAAPolylinesPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr pptInit -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static void -XAAPolySegmentPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int nseg, - xSegment *pSeg -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static void -XAAPolyRectanglePixmap( - DrawablePtr pDraw, - GCPtr pGC, - int nRectsInit, - xRectangle *pRectsInit -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static void -XAAPolyArcPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int narcs, - xArc *parcs -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static void -XAAFillPolygonPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - - -static void -XAAPolyFillRectPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int nrectFill, - xRectangle *prectInit -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PolyFillRect)(pDraw, pGC, nrectFill, prectInit); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - - -static void -XAAPolyFillArcPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int narcs, - xArc *parcs -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static int -XAAPolyText8Pixmap( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - char *chars -){ - int ret; - - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - ret = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars); - XAA_PIXMAP_OP_EPILOGUE(pGC); - return ret; -} - -static int -XAAPolyText16Pixmap( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - unsigned short *chars -){ - int ret; - - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - ret = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars); - XAA_PIXMAP_OP_EPILOGUE(pGC); - return ret; -} - -static void -XAAImageText8Pixmap( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - char *chars -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} -static void -XAAImageText16Pixmap( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - unsigned short *chars -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - - -static void -XAAImageGlyphBltPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, xInit, yInit, nglyph, - ppci, pglyphBase); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static void -XAAPolyGlyphBltPixmap( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, xInit, yInit, nglyph, - ppci, pglyphBase); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -static void -XAAPushPixelsPixmap( - GCPtr pGC, - PixmapPtr pBitMap, - DrawablePtr pDraw, - int dx, int dy, int xOrg, int yOrg -){ - XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); - (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); - XAA_PIXMAP_OP_EPILOGUE(pGC); -} - -GCOps XAAPixmapOps = { - XAAFillSpansPixmap, XAASetSpansPixmap, - XAAPutImagePixmap, XAACopyAreaPixmap, - XAACopyPlanePixmap, XAAPolyPointPixmap, - XAAPolylinesPixmap, XAAPolySegmentPixmap, - XAAPolyRectanglePixmap, XAAPolyArcPixmap, - XAAFillPolygonPixmap, XAAPolyFillRectPixmap, - XAAPolyFillArcPixmap, XAAPolyText8Pixmap, - XAAPolyText16Pixmap, XAAImageText8Pixmap, - XAAImageText16Pixmap, XAAImageGlyphBltPixmap, - XAAPolyGlyphBltPixmap, XAAPushPixelsPixmap, - {NULL} /* devPrivate */ -}; + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "migc.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "xaawrap.h" + +static void XAAValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); +static void XAAChangeGC(GCPtr pGC, unsigned long mask); +static void XAACopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +static void XAADestroyGC(GCPtr pGC); +static void XAAChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects); +static void XAADestroyClip(GCPtr pGC); +static void XAACopyClip(GCPtr pgcDst, GCPtr pgcSrc); + +GCFuncs XAAGCFuncs = { + XAAValidateGC, XAAChangeGC, XAACopyGC, XAADestroyGC, + XAAChangeClip, XAADestroyClip, XAACopyClip +}; + +extern GCOps XAAPixmapOps; + +Bool +XAACreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&pGC->devPrivates, + XAAGetGCKey()); + Bool ret; + + XAA_SCREEN_PROLOGUE(pScreen,CreateGC); + + if((ret = (*pScreen->CreateGC)(pGC))) { + pGCPriv->wrapOps = NULL; + pGCPriv->wrapFuncs = pGC->funcs; + pGCPriv->XAAOps = &XAAFallbackOps; + pGCPriv->flags = 0; + pGCPriv->DashLength = 0; + pGCPriv->DashPattern = NULL; + pGCPriv->changes = 0; + /* initialize any other private fields here */ + pGC->funcs = &XAAGCFuncs; + } + + XAA_SCREEN_EPILOGUE(pScreen,CreateGC,XAACreateGC); + + return ret; +} + + +static void +XAAValidateGC( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAA_GC_FUNC_PROLOGUE(pGC); + + (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); + + if((changes & GCPlaneMask) && + ((pGC->planemask & infoRec->FullPlanemasks[pGC->depth - 1]) == + infoRec->FullPlanemasks[pGC->depth - 1])) + { + pGC->planemask = ~0; + } + + if(pGC->depth != 32) { + /* 0xffffffff is reserved for transparency */ + if(pGC->bgPixel == 0xffffffff) + pGC->bgPixel = 0x7fffffff; + if(pGC->fgPixel == 0xffffffff) + pGC->fgPixel = 0x7fffffff; + } + + if((pDraw->type == DRAWABLE_PIXMAP) && !IS_OFFSCREEN_PIXMAP(pDraw)){ + pGCPriv->flags = OPS_ARE_PIXMAP; + pGCPriv->changes |= changes; + + /* make sure we're not using videomemory pixmaps to render + onto system memory drawables */ + + if((pGC->fillStyle == FillTiled) && + IS_OFFSCREEN_PIXMAP(pGC->tile.pixmap) && + !OFFSCREEN_PIXMAP_LOCKED(pGC->tile.pixmap)) { + + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + FBAreaPtr area = pPriv->offscreenArea; + + XAARemoveAreaCallback(area); /* clobbers pPriv->offscreenArea */ + xf86FreeOffscreenArea(area); + } + } + else if(!infoRec->pScrn->vtSema && (pDraw->type == DRAWABLE_WINDOW)) { + pGCPriv->flags = 0; + pGCPriv->changes |= changes; + } + else { + if(!(pGCPriv->flags & OPS_ARE_ACCEL)) { + changes |= pGCPriv->changes; + pGCPriv->changes = 0; + } + pGCPriv->flags = OPS_ARE_ACCEL; + +#if 1 + /* Ugh. If we can't use the blitter on offscreen pixmaps used + as tiles, then we need to move them out as cfb can't handle + tiles with non-zero origins */ + + if((pGC->fillStyle == FillTiled) && + IS_OFFSCREEN_PIXMAP(pGC->tile.pixmap) && + (DO_PIXMAP_COPY != (*infoRec->TiledFillChooser)(pGC))) { + + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + FBAreaPtr area = pPriv->offscreenArea; + + XAARemoveAreaCallback(area); /* clobbers pPriv->offscreenArea */ + xf86FreeOffscreenArea(area); + } +#endif + } + + XAA_GC_FUNC_EPILOGUE(pGC); + + if(!(pGCPriv->flags & OPS_ARE_ACCEL)) return; + + if((changes & GCTile) && !pGC->tileIsPixel && pGC->tile.pixmap){ + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + + if(pixPriv->flags & DIRTY) { + pixPriv->flags &= ~(DIRTY | REDUCIBILITY_MASK); + pGC->tile.pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + } + if((changes & GCStipple) && pGC->stipple){ + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + + if(pixPriv->flags & DIRTY) { + pixPriv->flags &= ~(DIRTY | REDUCIBILITY_MASK); + pGC->stipple->drawable.serialNumber = NEXT_SERIAL_NUMBER; + } + } + + /* If our Ops are still the default ones we need to allocate new ones */ + if(pGC->ops == &XAAFallbackOps) { + if(!(pGCPriv->XAAOps = malloc(sizeof(GCOps)))) { + pGCPriv->XAAOps = &XAAFallbackOps; + return; + } + /* make a modifiable copy of the default ops */ + memcpy(pGCPriv->XAAOps, &XAAFallbackOps, sizeof(GCOps)); + pGC->ops = pGCPriv->XAAOps; + changes = ~0; + } + + if(!changes) return; + + if((changes & GCDashList) && infoRec->ComputeDash) + infoRec->ComputeDash(pGC); + + if(changes & infoRec->FillSpansMask) + (*infoRec->ValidateFillSpans)(pGC, changes, pDraw); + + if(changes & infoRec->SetSpansMask) + (*infoRec->ValidateSetSpans)(pGC, changes, pDraw); + + if(changes & infoRec->PutImageMask) + (*infoRec->ValidatePutImage)(pGC, changes, pDraw); + + if(changes & infoRec->CopyAreaMask) + (*infoRec->ValidateCopyArea)(pGC, changes, pDraw); + + if(changes & infoRec->CopyPlaneMask) + (*infoRec->ValidateCopyPlane)(pGC, changes, pDraw); + + if(changes & infoRec->PolyPointMask) + (*infoRec->ValidatePolyPoint)(pGC, changes, pDraw); + + if(changes & infoRec->PolylinesMask) + (*infoRec->ValidatePolylines)(pGC, changes, pDraw); + + if(changes & infoRec->PolySegmentMask) + (*infoRec->ValidatePolySegment)(pGC, changes, pDraw); + + if(changes & infoRec->PolyRectangleMask) + (*infoRec->ValidatePolyRectangle)(pGC, changes, pDraw); + + if(changes & infoRec->PolyArcMask) + (*infoRec->ValidatePolyArc)(pGC, changes, pDraw); + + if(changes & infoRec->FillPolygonMask) + (*infoRec->ValidateFillPolygon)(pGC, changes, pDraw); + + if(changes & infoRec->PolyFillRectMask) + (*infoRec->ValidatePolyFillRect)(pGC, changes, pDraw); + + if(changes & infoRec->PolyFillArcMask) + (*infoRec->ValidatePolyFillArc)(pGC, changes, pDraw); + + if(changes & infoRec->PolyGlyphBltMask) + (*infoRec->ValidatePolyGlyphBlt)(pGC, changes, pDraw); + + if(changes & infoRec->ImageGlyphBltMask) + (*infoRec->ValidateImageGlyphBlt)(pGC, changes, pDraw); + + if(changes & infoRec->PolyText8Mask) + (*infoRec->ValidatePolyText8)(pGC, changes, pDraw); + + if(changes & infoRec->PolyText16Mask) + (*infoRec->ValidatePolyText16)(pGC, changes, pDraw); + + if(changes & infoRec->ImageText8Mask) + (*infoRec->ValidateImageText8)(pGC, changes, pDraw); + + if(changes & infoRec->ImageText16Mask) + (*infoRec->ValidateImageText16)(pGC, changes, pDraw); + + if(changes & infoRec->PushPixelsMask) + (*infoRec->ValidatePushPixels)(pGC, changes, pDraw); +} + + +static void +XAADestroyGC(GCPtr pGC) +{ + XAA_GC_FUNC_PROLOGUE (pGC); + + if(pGCPriv->XAAOps != &XAAFallbackOps) + free(pGCPriv->XAAOps); + + if(pGCPriv->DashPattern) + free(pGCPriv->DashPattern); + + (*pGC->funcs->DestroyGC)(pGC); + XAA_GC_FUNC_EPILOGUE (pGC); +} + +static void +XAAChangeGC ( + GCPtr pGC, + unsigned long mask +) +{ + XAA_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + XAA_GC_FUNC_EPILOGUE (pGC); + + /* we have to assume that shared memory pixmaps are dirty + because we can't wrap all operations on them */ + + if((mask & GCTile) && !pGC->tileIsPixel && + PIXMAP_IS_SHARED(pGC->tile.pixmap)) + { + XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap); + pPixPriv->flags |= DIRTY; + } + + if((mask & GCStipple) && PIXMAP_IS_SHARED(pGC->stipple)){ + XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple); + pPixPriv->flags |= DIRTY; + } +} + +static void +XAACopyGC ( + GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + XAA_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + XAA_GC_FUNC_EPILOGUE (pGCDst); +} +static void +XAAChangeClip ( + GCPtr pGC, + int type, + pointer pvalue, + int nrects ) +{ + XAA_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + XAA_GC_FUNC_EPILOGUE (pGC); +} + +static void +XAACopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + XAA_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + XAA_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +XAADestroyClip(GCPtr pGC) +{ + XAA_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + XAA_GC_FUNC_EPILOGUE (pGC); +} + +/**** Pixmap Wrappers ****/ + + + +static void +XAAFillSpansPixmap( + DrawablePtr pDraw, + GC *pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidthInit, + int fSorted +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAASetSpansPixmap( + DrawablePtr pDraw, + GCPtr pGC, + char *pcharsrc, + register DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, ppt, pwidth, nspans, fSorted); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPutImagePixmap( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, int y, int w, int h, + int leftPad, + int format, + char *pImage +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static RegionPtr +XAACopyAreaPixmap( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + RegionPtr ret; + + if(infoRec->pScrn->vtSema && + ((pSrc->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pSrc))) + { + if(infoRec->ReadPixmap && (pGC->alu == GXcopy) && + (pSrc->bitsPerPixel == pDst->bitsPerPixel) && + ((pGC->planemask & infoRec->FullPlanemasks[pSrc->depth - 1]) + == infoRec->FullPlanemasks[pSrc->depth - 1])) + { + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst)); + pixPriv->flags |= DIRTY; + + return (XAABitBlt( pSrc, pDst, pGC, + srcx, srcy, width, height, dstx, dsty, + XAADoImageRead, 0L)); + } else + if(infoRec->NeedToSync) { + (*infoRec->Sync)(infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + } + + { + XAA_PIXMAP_OP_PROLOGUE(pGC, pDst); + ret = (*pGC->ops->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); + XAA_PIXMAP_OP_EPILOGUE(pGC); + } + return ret; +} + +static RegionPtr +XAACopyPlanePixmap( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + RegionPtr ret; + + XAA_PIXMAP_OP_PROLOGUE(pGC, pDst); + + if(infoRec->pScrn->vtSema && + ((pSrc->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pSrc))){ + if(infoRec->NeedToSync) { + (*infoRec->Sync)(infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + } + + ret = (*pGC->ops->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + XAA_PIXMAP_OP_EPILOGUE(pGC); + return ret; +} + +static void +XAAPolyPointPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + xPoint *pptInit +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + + +static void +XAAPolylinesPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pptInit +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolySegmentPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int nseg, + xSegment *pSeg +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolyRectanglePixmap( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyRectangle)(pDraw, pGC, nRectsInit, pRectsInit); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolyArcPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAFillPolygonPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + + +static void +XAAPolyFillRectPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, + xRectangle *prectInit +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyFillRect)(pDraw, pGC, nrectFill, prectInit); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + + +static void +XAAPolyFillArcPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static int +XAAPolyText8Pixmap( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +){ + int ret; + + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + ret = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars); + XAA_PIXMAP_OP_EPILOGUE(pGC); + return ret; +} + +static int +XAAPolyText16Pixmap( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +){ + int ret; + + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + ret = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars); + XAA_PIXMAP_OP_EPILOGUE(pGC); + return ret; +} + +static void +XAAImageText8Pixmap( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} +static void +XAAImageText16Pixmap( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + + +static void +XAAImageGlyphBltPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, xInit, yInit, nglyph, + ppci, pglyphBase); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPolyGlyphBltPixmap( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, xInit, yInit, nglyph, + ppci, pglyphBase); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +static void +XAAPushPixelsPixmap( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, int xOrg, int yOrg +){ + XAA_PIXMAP_OP_PROLOGUE(pGC, pDraw); + (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); + XAA_PIXMAP_OP_EPILOGUE(pGC); +} + +GCOps XAAPixmapOps = { + XAAFillSpansPixmap, XAASetSpansPixmap, + XAAPutImagePixmap, XAACopyAreaPixmap, + XAACopyPlanePixmap, XAAPolyPointPixmap, + XAAPolylinesPixmap, XAAPolySegmentPixmap, + XAAPolyRectanglePixmap, XAAPolyArcPixmap, + XAAFillPolygonPixmap, XAAPolyFillRectPixmap, + XAAPolyFillArcPixmap, XAAPolyText8Pixmap, + XAAPolyText16Pixmap, XAAImageText8Pixmap, + XAAImageText16Pixmap, XAAImageGlyphBltPixmap, + XAAPolyGlyphBltPixmap, XAAPushPixelsPixmap, + {NULL} /* devPrivate */ +}; diff --git a/xorg-server/hw/xfree86/xaa/xaaImage.c b/xorg-server/hw/xfree86/xaa/xaaImage.c index 4933beea3..c8d98c7d0 100644 --- a/xorg-server/hw/xfree86/xaa/xaaImage.c +++ b/xorg-server/hw/xfree86/xaa/xaaImage.c @@ -1,521 +1,521 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#include "servermd.h" - -#include -#include "scrnintstr.h" -#include "mi.h" -#include "pixmapstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" - -void XAAMoveDWORDS_FixedBase( - register CARD32* dest, - register CARD32* src, - register int dwords ) -{ - while(dwords & ~0x03) { - *dest = *src; - *dest = *(src + 1); - *dest = *(src + 2); - *dest = *(src + 3); - dwords -= 4; - src += 4; - } - - if(!dwords) return; - *dest = *src; - if(dwords == 1) return; - *dest = *(src + 1); - if(dwords == 2) return; - *dest = *(src + 2); -} - -void XAAMoveDWORDS( - register CARD32* dest, - register CARD32* src, - register int dwords ) -{ - while(dwords & ~0x03) { - *dest = *src; - *(dest + 1) = *(src + 1); - *(dest + 2) = *(src + 2); - *(dest + 3) = *(src + 3); - src += 4; - dest += 4; - dwords -= 4; - } - if(!dwords) return; - *dest = *src; - if(dwords == 1) return; - *(dest + 1) = *(src + 1); - if(dwords == 2) return; - *(dest + 2) = *(src + 2); -} - -void XAAMoveDWORDS_FixedSrc( - register CARD32* dest, - register CARD32* src, - register int dwords ) -{ - while(dwords & ~0x03) { - *dest = *src; - *(dest + 1) = *src; - *(dest + 2) = *src; - *(dest + 3) = *src; - dest += 4; - dwords -= 4; - } - if(!dwords) return; - *dest = *src; - if(dwords == 1) return; - *(dest + 1) = *src; - if(dwords == 2) return; - *(dest + 2) = *src; -} - -static void -XAAWritePixmap32To24( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *srcInit, - int srcwidth, /* bytes */ - int rop, - unsigned int planemask, - int trans -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int count, dwords = bytes_to_int32(w * 3); - CARD32 *src, *dst; - Bool PlusOne = FALSE; - - if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && - ((dwords * h) & 0x01)) { - PlusOne = TRUE; - } - - (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, trans, 24, 24); - (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, 0); - - if(dwords > infoRec->ImageWriteRange) { - dst = (CARD32*)infoRec->ImageWriteBase; - while(h--) { - src = (CARD32*)srcInit; - count = w; - - while(count >= 4) { - *dst = (src[0] & 0x00ffffff) | (src[1] << 24); - *dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); - *dst = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8); - src += 4; - count -= 4; - } - switch(count) { - case 0: break; - case 1: *dst = src[0]; - break; - case 2: *dst = (src[0] & 0x00ffffff) | (src[1] << 24); - *dst = src[1] >> 8; - break; - default: *dst = (src[0] & 0x00ffffff) | (src[1] << 24); - *dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); - *dst = src[2] >> 16; - break; - } - srcInit += srcwidth; - } - } else { - while(h--) { - dst = (CARD32*)infoRec->ImageWriteBase; - src = (CARD32*)srcInit; - count = w; - - while(count >= 4) { - dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); - dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); - dst[2] = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8); - dst += 3; - src += 4; - count -= 4; - } - switch(count) { - case 0: break; - case 1: dst[0] = src[0]; - break; - case 2: dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); - dst[1] = src[1] >> 8; - break; - default: dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); - dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); - dst[2] = src[2] >> 16; - break; - } - srcInit += srcwidth; - } - } - - if(PlusOne) { - CARD32* base = (CARD32*)infoRec->ImageWriteBase; - *base = 0x00000000; - } - - if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) - (*infoRec->Sync)(pScrn); - else SET_SYNC_FLAG(infoRec); - -} - -void -XAAWritePixmap ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, /* bytes */ - int rop, - unsigned int planemask, - int trans, - int bpp, int depth -){ - XAAInfoRecPtr infoRec; - int dwords, skipleft, Bpp; - Bool beCareful, PlusOne; - - if((bpp == 32) && (pScrn->bitsPerPixel == 24)) { - XAAWritePixmap32To24(pScrn, x, y, w, h, src, srcwidth, - rop, planemask, trans); - return; - } - - infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - beCareful = PlusOne = FALSE; - Bpp = bpp >> 3; - - if((skipleft = (long)src & 0x03L)) { - if(!(infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) { - skipleft = 0; - beCareful = TRUE; - goto BAD_ALIGNMENT; - } - - if(Bpp == 3) - skipleft = 4 - skipleft; - else - skipleft /= Bpp; - - if((x < skipleft) && !(infoRec->ImageWriteFlags & - LEFT_EDGE_CLIPPING_NEGATIVE_X)) { - skipleft = 0; - beCareful = TRUE; - goto BAD_ALIGNMENT; - } - - x -= skipleft; - w += skipleft; - - if(Bpp == 3) - src -= 3 * skipleft; - else /* is this Alpha friendly ? */ - src = (unsigned char*)((long)src & ~0x03L); - } - -BAD_ALIGNMENT: - - dwords = bytes_to_int32(w * Bpp); - - if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && - ((dwords * h) & 0x01)) { - PlusOne = TRUE; - } - - - (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, trans, bpp, depth); - (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft); - - if(beCareful) { - /* in cases with bad alignment we have to be careful not - to read beyond the end of the source */ - if(((x * Bpp) + (dwords << 2)) > srcwidth) h--; - else beCareful = FALSE; - } - - if(dwords > infoRec->ImageWriteRange) { - while(h--) { - XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase, - (CARD32*)src, dwords); - src += srcwidth; - } - if(beCareful) { - int shift = ((long)src & 0x03L) << 3; - if(--dwords) - XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase, - (CARD32*)src, dwords); - src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L); - *((CARD32*)infoRec->ImageWriteBase) = *((CARD32*)src) >> shift; - } - } else { - if(srcwidth == (dwords << 2)) { - int decrement = infoRec->ImageWriteRange/dwords; - - while(h > decrement) { - XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, - (CARD32*)src, dwords * decrement); - src += (srcwidth * decrement); - h -= decrement; - } - if(h) { - XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, - (CARD32*)src, dwords * h); - if(beCareful) src += (srcwidth * h); - } - } else { - while(h--) { - XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, - (CARD32*)src, dwords); - src += srcwidth; - } - } - - if(beCareful) { - int shift = ((long)src & 0x03L) << 3; - if(--dwords) - XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, - (CARD32*)src, dwords); - src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L); - - ((CARD32*)infoRec->ImageWriteBase)[dwords] = - *((CARD32*)src) >> shift; - } - } - - if(PlusOne) { - CARD32* base = (CARD32*)infoRec->ImageWriteBase; - *base = 0x00000000; - } - - if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) - (*infoRec->Sync)(pScrn); - else SET_SYNC_FLAG(infoRec); -} - - -void -XAAWritePixmapScanline ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, /* bytes */ - int rop, - unsigned int planemask, - int trans, - int bpp, int depth -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int dwords, skipleft, bufferNo = 0, Bpp = bpp >> 3; - Bool beCareful = FALSE; - CARD32* base; - - if((skipleft = (long)src & 0x03L)) { - if(!(infoRec->ScanlineImageWriteFlags & LEFT_EDGE_CLIPPING)) { - skipleft = 0; - beCareful = TRUE; - goto BAD_ALIGNMENT; - } - - if(Bpp == 3) - skipleft = 4 - skipleft; - else - skipleft /= Bpp; - - if((x < skipleft) && !(infoRec->ScanlineImageWriteFlags & - LEFT_EDGE_CLIPPING_NEGATIVE_X)) { - skipleft = 0; - beCareful = TRUE; - goto BAD_ALIGNMENT; - } - - x -= skipleft; - w += skipleft; - - if(Bpp == 3) - src -= 3 * skipleft; - else - src = (unsigned char*)((long)src & ~0x03L); - } - -BAD_ALIGNMENT: - - dwords = bytes_to_int32(w * Bpp); - - (*infoRec->SetupForScanlineImageWrite)( - pScrn, rop, planemask, trans, bpp, depth); - (*infoRec->SubsequentScanlineImageWriteRect)(pScrn, x, y, w, h, skipleft); - - if(beCareful) { - /* in cases with bad alignment we have to be careful not - to read beyond the end of the source */ - if(((x * Bpp) + (dwords << 2)) > srcwidth) h--; - else beCareful = FALSE; - } - - while(h--) { - base = (CARD32*)infoRec->ScanlineImageWriteBuffers[bufferNo]; - XAAMoveDWORDS(base, (CARD32*)src, dwords); - (*infoRec->SubsequentImageWriteScanline)(pScrn, bufferNo++); - src += srcwidth; - if(bufferNo >= infoRec->NumScanlineImageWriteBuffers) - bufferNo = 0; - } - - if(beCareful) { - int shift = ((long)src & 0x03L) << 3; - base = (CARD32*)infoRec->ScanlineImageWriteBuffers[bufferNo]; - if(--dwords) - XAAMoveDWORDS(base,(CARD32*)src, dwords); - src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L); - - base[dwords] = *((CARD32*)src) >> shift; - (*infoRec->SubsequentImageWriteScanline)(pScrn, bufferNo); - } - - SET_SYNC_FLAG(infoRec); -} - - -void -XAAPutImage( - DrawablePtr pDraw, - GCPtr pGC, - int depth, - int x, - int y, - int w, - int h, - int leftPad, - int format, - char *pImage -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - int bpp = BitsPerPixel(depth); - Bool depthBug = FALSE; - if(!w || !h) return; - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - depthBug = XAA_DEPTH_BUG(pGC); - - if(((format == ZPixmap) && infoRec->WritePixmap && - ((pDraw->bitsPerPixel == bpp) || - ((pDraw->bitsPerPixel == 24) && (bpp == 32) && - (infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) && - CHECK_ROP(pGC,infoRec->WritePixmapFlags) && - CHECK_ROPSRC(pGC,infoRec->WritePixmapFlags) && - CHECK_PLANEMASK(pGC,infoRec->WritePixmapFlags) && - CHECK_NO_GXCOPY(pGC,infoRec->WritePixmapFlags)) || - ((format == XYBitmap) && !depthBug && infoRec->WriteBitmap && - CHECK_ROP(pGC,infoRec->WriteBitmapFlags) && - CHECK_ROPSRC(pGC,infoRec->WriteBitmapFlags) && - CHECK_PLANEMASK(pGC,infoRec->WriteBitmapFlags) && - CHECK_COLORS(pGC,infoRec->WriteBitmapFlags) && - !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) || - ((format == XYPixmap) && !depthBug && infoRec->WriteBitmap && - CHECK_ROP(pGC,infoRec->WriteBitmapFlags) && - CHECK_ROPSRC(pGC,infoRec->WriteBitmapFlags) && - !(infoRec->WriteBitmapFlags & NO_PLANEMASK) && - !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY))){ - - int MaxBoxes = REGION_NUM_RECTS(pGC->pCompositeClip); - BoxPtr pbox, pClipBoxes; - int nboxes, srcx, srcy, srcwidth; - xRectangle TheRect; - - TheRect.x = pDraw->x + x; - TheRect.y = pDraw->y + y; - TheRect.width = w; - TheRect.height = h; - - if(MaxBoxes > (infoRec->PreAllocSize/sizeof(BoxRec))) { - pClipBoxes = xalloc(MaxBoxes * sizeof(BoxRec)); - if(!pClipBoxes) return; - } else pClipBoxes = (BoxPtr)infoRec->PreAllocMem; - - nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect); - pbox = pClipBoxes; - - if(format == XYBitmap) { - srcwidth = BitmapBytePad(leftPad + w); - while(nboxes--) { - srcx = pbox->x1 - TheRect.x + leftPad; - srcy = pbox->y1 - TheRect.y; - (*infoRec->WriteBitmap)(infoRec->pScrn, pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, - (unsigned char*)pImage + - (srcwidth * srcy) + ((srcx >> 5) << 2), - srcwidth, srcx & 31, pGC->fgPixel, pGC->bgPixel, - pGC->alu, pGC->planemask); - pbox++; - } - } else if(format == ZPixmap) { - int Bpp = bpp >> 3; - srcwidth = PixmapBytePad(leftPad + w, depth); - while(nboxes--) { - srcx = pbox->x1 - TheRect.x + leftPad; - srcy = pbox->y1 - TheRect.y; - (*infoRec->WritePixmap)(infoRec->pScrn, pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, - (unsigned char*)pImage + - (srcwidth * srcy) + (srcx * Bpp), - srcwidth, pGC->alu, pGC->planemask, -1, - Bpp << 3, depth); - pbox++; - } - } else { /* XYPixmap */ - int depth = pGC->depth; - int numBox, increment; - unsigned long i, mask; - BoxPtr pntBox; - - srcwidth = BitmapBytePad(w + leftPad); - increment = h * srcwidth; - i = 1 << (depth - 1); - mask = ~0; - - if((infoRec->pScrn->overlayFlags & OVERLAY_8_32_PLANAR) && - (pGC->depth == 8)){ - i = 0x80000000; mask = 0xff000000; - } - - for(; i & mask; i >>= 1, pImage += increment) { - if(i & pGC->planemask) { - pntBox = pbox; - numBox = nboxes; - while(numBox--) { - srcx = pntBox->x1 - TheRect.x + leftPad; - srcy = pntBox->y1 - TheRect.y; - (*infoRec->WriteBitmap)(infoRec->pScrn, - pntBox->x1, pntBox->y1, - pntBox->x2 - pntBox->x1, - pntBox->y2 - pntBox->y1, - (unsigned char*)pImage + - (srcwidth * srcy) + ((srcx >> 5) << 2), - srcwidth, srcx & 31, ~0, 0, pGC->alu, i); - pntBox++; - } - } - } - - } - - if(pClipBoxes != (BoxPtr)infoRec->PreAllocMem) - xfree(pClipBoxes); - } else - XAAFallbackOps.PutImage(pDraw, pGC, depth, x, y, w, h, leftPad, - format, pImage); -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "servermd.h" + +#include +#include "scrnintstr.h" +#include "mi.h" +#include "pixmapstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + +void XAAMoveDWORDS_FixedBase( + register CARD32* dest, + register CARD32* src, + register int dwords ) +{ + while(dwords & ~0x03) { + *dest = *src; + *dest = *(src + 1); + *dest = *(src + 2); + *dest = *(src + 3); + dwords -= 4; + src += 4; + } + + if(!dwords) return; + *dest = *src; + if(dwords == 1) return; + *dest = *(src + 1); + if(dwords == 2) return; + *dest = *(src + 2); +} + +void XAAMoveDWORDS( + register CARD32* dest, + register CARD32* src, + register int dwords ) +{ + while(dwords & ~0x03) { + *dest = *src; + *(dest + 1) = *(src + 1); + *(dest + 2) = *(src + 2); + *(dest + 3) = *(src + 3); + src += 4; + dest += 4; + dwords -= 4; + } + if(!dwords) return; + *dest = *src; + if(dwords == 1) return; + *(dest + 1) = *(src + 1); + if(dwords == 2) return; + *(dest + 2) = *(src + 2); +} + +void XAAMoveDWORDS_FixedSrc( + register CARD32* dest, + register CARD32* src, + register int dwords ) +{ + while(dwords & ~0x03) { + *dest = *src; + *(dest + 1) = *src; + *(dest + 2) = *src; + *(dest + 3) = *src; + dest += 4; + dwords -= 4; + } + if(!dwords) return; + *dest = *src; + if(dwords == 1) return; + *(dest + 1) = *src; + if(dwords == 2) return; + *(dest + 2) = *src; +} + +static void +XAAWritePixmap32To24( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *srcInit, + int srcwidth, /* bytes */ + int rop, + unsigned int planemask, + int trans +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int count, dwords = bytes_to_int32(w * 3); + CARD32 *src, *dst; + Bool PlusOne = FALSE; + + if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && + ((dwords * h) & 0x01)) { + PlusOne = TRUE; + } + + (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, trans, 24, 24); + (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, 0); + + if(dwords > infoRec->ImageWriteRange) { + dst = (CARD32*)infoRec->ImageWriteBase; + while(h--) { + src = (CARD32*)srcInit; + count = w; + + while(count >= 4) { + *dst = (src[0] & 0x00ffffff) | (src[1] << 24); + *dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); + *dst = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8); + src += 4; + count -= 4; + } + switch(count) { + case 0: break; + case 1: *dst = src[0]; + break; + case 2: *dst = (src[0] & 0x00ffffff) | (src[1] << 24); + *dst = src[1] >> 8; + break; + default: *dst = (src[0] & 0x00ffffff) | (src[1] << 24); + *dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); + *dst = src[2] >> 16; + break; + } + srcInit += srcwidth; + } + } else { + while(h--) { + dst = (CARD32*)infoRec->ImageWriteBase; + src = (CARD32*)srcInit; + count = w; + + while(count >= 4) { + dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); + dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); + dst[2] = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8); + dst += 3; + src += 4; + count -= 4; + } + switch(count) { + case 0: break; + case 1: dst[0] = src[0]; + break; + case 2: dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); + dst[1] = src[1] >> 8; + break; + default: dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); + dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); + dst[2] = src[2] >> 16; + break; + } + srcInit += srcwidth; + } + } + + if(PlusOne) { + CARD32* base = (CARD32*)infoRec->ImageWriteBase; + *base = 0x00000000; + } + + if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) + (*infoRec->Sync)(pScrn); + else SET_SYNC_FLAG(infoRec); + +} + +void +XAAWritePixmap ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, /* bytes */ + int rop, + unsigned int planemask, + int trans, + int bpp, int depth +){ + XAAInfoRecPtr infoRec; + int dwords, skipleft, Bpp; + Bool beCareful, PlusOne; + + if((bpp == 32) && (pScrn->bitsPerPixel == 24)) { + XAAWritePixmap32To24(pScrn, x, y, w, h, src, srcwidth, + rop, planemask, trans); + return; + } + + infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + beCareful = PlusOne = FALSE; + Bpp = bpp >> 3; + + if((skipleft = (long)src & 0x03L)) { + if(!(infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + if(Bpp == 3) + skipleft = 4 - skipleft; + else + skipleft /= Bpp; + + if((x < skipleft) && !(infoRec->ImageWriteFlags & + LEFT_EDGE_CLIPPING_NEGATIVE_X)) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + x -= skipleft; + w += skipleft; + + if(Bpp == 3) + src -= 3 * skipleft; + else /* is this Alpha friendly ? */ + src = (unsigned char*)((long)src & ~0x03L); + } + +BAD_ALIGNMENT: + + dwords = bytes_to_int32(w * Bpp); + + if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && + ((dwords * h) & 0x01)) { + PlusOne = TRUE; + } + + + (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, trans, bpp, depth); + (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft); + + if(beCareful) { + /* in cases with bad alignment we have to be careful not + to read beyond the end of the source */ + if(((x * Bpp) + (dwords << 2)) > srcwidth) h--; + else beCareful = FALSE; + } + + if(dwords > infoRec->ImageWriteRange) { + while(h--) { + XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase, + (CARD32*)src, dwords); + src += srcwidth; + } + if(beCareful) { + int shift = ((long)src & 0x03L) << 3; + if(--dwords) + XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase, + (CARD32*)src, dwords); + src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L); + *((CARD32*)infoRec->ImageWriteBase) = *((CARD32*)src) >> shift; + } + } else { + if(srcwidth == (dwords << 2)) { + int decrement = infoRec->ImageWriteRange/dwords; + + while(h > decrement) { + XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, + (CARD32*)src, dwords * decrement); + src += (srcwidth * decrement); + h -= decrement; + } + if(h) { + XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, + (CARD32*)src, dwords * h); + if(beCareful) src += (srcwidth * h); + } + } else { + while(h--) { + XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, + (CARD32*)src, dwords); + src += srcwidth; + } + } + + if(beCareful) { + int shift = ((long)src & 0x03L) << 3; + if(--dwords) + XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase, + (CARD32*)src, dwords); + src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L); + + ((CARD32*)infoRec->ImageWriteBase)[dwords] = + *((CARD32*)src) >> shift; + } + } + + if(PlusOne) { + CARD32* base = (CARD32*)infoRec->ImageWriteBase; + *base = 0x00000000; + } + + if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) + (*infoRec->Sync)(pScrn); + else SET_SYNC_FLAG(infoRec); +} + + +void +XAAWritePixmapScanline ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, /* bytes */ + int rop, + unsigned int planemask, + int trans, + int bpp, int depth +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int dwords, skipleft, bufferNo = 0, Bpp = bpp >> 3; + Bool beCareful = FALSE; + CARD32* base; + + if((skipleft = (long)src & 0x03L)) { + if(!(infoRec->ScanlineImageWriteFlags & LEFT_EDGE_CLIPPING)) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + if(Bpp == 3) + skipleft = 4 - skipleft; + else + skipleft /= Bpp; + + if((x < skipleft) && !(infoRec->ScanlineImageWriteFlags & + LEFT_EDGE_CLIPPING_NEGATIVE_X)) { + skipleft = 0; + beCareful = TRUE; + goto BAD_ALIGNMENT; + } + + x -= skipleft; + w += skipleft; + + if(Bpp == 3) + src -= 3 * skipleft; + else + src = (unsigned char*)((long)src & ~0x03L); + } + +BAD_ALIGNMENT: + + dwords = bytes_to_int32(w * Bpp); + + (*infoRec->SetupForScanlineImageWrite)( + pScrn, rop, planemask, trans, bpp, depth); + (*infoRec->SubsequentScanlineImageWriteRect)(pScrn, x, y, w, h, skipleft); + + if(beCareful) { + /* in cases with bad alignment we have to be careful not + to read beyond the end of the source */ + if(((x * Bpp) + (dwords << 2)) > srcwidth) h--; + else beCareful = FALSE; + } + + while(h--) { + base = (CARD32*)infoRec->ScanlineImageWriteBuffers[bufferNo]; + XAAMoveDWORDS(base, (CARD32*)src, dwords); + (*infoRec->SubsequentImageWriteScanline)(pScrn, bufferNo++); + src += srcwidth; + if(bufferNo >= infoRec->NumScanlineImageWriteBuffers) + bufferNo = 0; + } + + if(beCareful) { + int shift = ((long)src & 0x03L) << 3; + base = (CARD32*)infoRec->ScanlineImageWriteBuffers[bufferNo]; + if(--dwords) + XAAMoveDWORDS(base,(CARD32*)src, dwords); + src = (unsigned char*)((long)(src + (dwords << 2)) & ~0x03L); + + base[dwords] = *((CARD32*)src) >> shift; + (*infoRec->SubsequentImageWriteScanline)(pScrn, bufferNo); + } + + SET_SYNC_FLAG(infoRec); +} + + +void +XAAPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + int bpp = BitsPerPixel(depth); + Bool depthBug = FALSE; + if(!w || !h) return; + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + depthBug = XAA_DEPTH_BUG(pGC); + + if(((format == ZPixmap) && infoRec->WritePixmap && + ((pDraw->bitsPerPixel == bpp) || + ((pDraw->bitsPerPixel == 24) && (bpp == 32) && + (infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) && + CHECK_ROP(pGC,infoRec->WritePixmapFlags) && + CHECK_ROPSRC(pGC,infoRec->WritePixmapFlags) && + CHECK_PLANEMASK(pGC,infoRec->WritePixmapFlags) && + CHECK_NO_GXCOPY(pGC,infoRec->WritePixmapFlags)) || + ((format == XYBitmap) && !depthBug && infoRec->WriteBitmap && + CHECK_ROP(pGC,infoRec->WriteBitmapFlags) && + CHECK_ROPSRC(pGC,infoRec->WriteBitmapFlags) && + CHECK_PLANEMASK(pGC,infoRec->WriteBitmapFlags) && + CHECK_COLORS(pGC,infoRec->WriteBitmapFlags) && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) || + ((format == XYPixmap) && !depthBug && infoRec->WriteBitmap && + CHECK_ROP(pGC,infoRec->WriteBitmapFlags) && + CHECK_ROPSRC(pGC,infoRec->WriteBitmapFlags) && + !(infoRec->WriteBitmapFlags & NO_PLANEMASK) && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY))){ + + int MaxBoxes = REGION_NUM_RECTS(pGC->pCompositeClip); + BoxPtr pbox, pClipBoxes; + int nboxes, srcx, srcy, srcwidth; + xRectangle TheRect; + + TheRect.x = pDraw->x + x; + TheRect.y = pDraw->y + y; + TheRect.width = w; + TheRect.height = h; + + if(MaxBoxes > (infoRec->PreAllocSize/sizeof(BoxRec))) { + pClipBoxes = malloc(MaxBoxes * sizeof(BoxRec)); + if(!pClipBoxes) return; + } else pClipBoxes = (BoxPtr)infoRec->PreAllocMem; + + nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect); + pbox = pClipBoxes; + + if(format == XYBitmap) { + srcwidth = BitmapBytePad(leftPad + w); + while(nboxes--) { + srcx = pbox->x1 - TheRect.x + leftPad; + srcy = pbox->y1 - TheRect.y; + (*infoRec->WriteBitmap)(infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + (unsigned char*)pImage + + (srcwidth * srcy) + ((srcx >> 5) << 2), + srcwidth, srcx & 31, pGC->fgPixel, pGC->bgPixel, + pGC->alu, pGC->planemask); + pbox++; + } + } else if(format == ZPixmap) { + int Bpp = bpp >> 3; + srcwidth = PixmapBytePad(leftPad + w, depth); + while(nboxes--) { + srcx = pbox->x1 - TheRect.x + leftPad; + srcy = pbox->y1 - TheRect.y; + (*infoRec->WritePixmap)(infoRec->pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + (unsigned char*)pImage + + (srcwidth * srcy) + (srcx * Bpp), + srcwidth, pGC->alu, pGC->planemask, -1, + Bpp << 3, depth); + pbox++; + } + } else { /* XYPixmap */ + int depth = pGC->depth; + int numBox, increment; + unsigned long i, mask; + BoxPtr pntBox; + + srcwidth = BitmapBytePad(w + leftPad); + increment = h * srcwidth; + i = 1 << (depth - 1); + mask = ~0; + + if((infoRec->pScrn->overlayFlags & OVERLAY_8_32_PLANAR) && + (pGC->depth == 8)){ + i = 0x80000000; mask = 0xff000000; + } + + for(; i & mask; i >>= 1, pImage += increment) { + if(i & pGC->planemask) { + pntBox = pbox; + numBox = nboxes; + while(numBox--) { + srcx = pntBox->x1 - TheRect.x + leftPad; + srcy = pntBox->y1 - TheRect.y; + (*infoRec->WriteBitmap)(infoRec->pScrn, + pntBox->x1, pntBox->y1, + pntBox->x2 - pntBox->x1, + pntBox->y2 - pntBox->y1, + (unsigned char*)pImage + + (srcwidth * srcy) + ((srcx >> 5) << 2), + srcwidth, srcx & 31, ~0, 0, pGC->alu, i); + pntBox++; + } + } + } + + } + + if(pClipBoxes != (BoxPtr)infoRec->PreAllocMem) + free(pClipBoxes); + } else + XAAFallbackOps.PutImage(pDraw, pGC, depth, x, y, w, h, leftPad, + format, pImage); +} diff --git a/xorg-server/hw/xfree86/xaa/xaaInit.c b/xorg-server/hw/xfree86/xaa/xaaInit.c index 7d4583dc2..58efb6a82 100644 --- a/xorg-server/hw/xfree86/xaa/xaaInit.c +++ b/xorg-server/hw/xfree86/xaa/xaaInit.c @@ -1,624 +1,624 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "xf86str.h" -#include "mi.h" -#include "miline.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xaawrap.h" -#include "xf86fbman.h" -#include "servermd.h" -#ifdef COMPOSITE -#include "cw.h" -#endif - -#define MAX_PREALLOC_MEM 65536 /* MUST be >= 1024 */ - -#define MIN_OFFPIX_SIZE (320*200) - -static Bool XAACloseScreen(int i, ScreenPtr pScreen); -static void XAAGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, - unsigned int format, unsigned long planemask, - char *pdstLine); -static void XAAGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, - int *pwidth, int nspans, char *pdstStart); -static PixmapPtr XAACreatePixmap(ScreenPtr pScreen, int w, int h, int depth, - unsigned usage_hint); -static Bool XAADestroyPixmap(PixmapPtr pPixmap); -static Bool XAAEnterVT (int index, int flags); -static void XAALeaveVT (int index, int flags); -static int XAASetDGAMode(int index, int num, DGADevicePtr devRet); -static void XAAEnableDisableFBAccess (int index, Bool enable); -static Bool XAAChangeWindowAttributes (WindowPtr pWin, unsigned long mask); - -static int XAAScreenKeyIndex; -static DevPrivateKey XAAScreenKey = &XAAScreenKeyIndex; -static int XAAGCKeyIndex; -static DevPrivateKey XAAGCKey = &XAAGCKeyIndex; -static int XAAPixmapKeyIndex; -static DevPrivateKey XAAPixmapKey = &XAAPixmapKeyIndex; - -DevPrivateKey XAAGetScreenKey(void) { - return XAAScreenKey; -} - -DevPrivateKey XAAGetGCKey(void) { - return XAAGCKey; -} - -DevPrivateKey XAAGetPixmapKey(void) { - return XAAPixmapKey; -} - -/* temp kludge */ -static Bool SwitchedOut = FALSE; - -XAAInfoRecPtr -XAACreateInfoRec(void) -{ - XAAInfoRecPtr infoRec; - - infoRec = xcalloc(1, sizeof(XAAInfoRec)); - if(infoRec) - infoRec->CachePixelGranularity = -1; - - return infoRec; -} - -void -XAADestroyInfoRec(XAAInfoRecPtr infoRec) -{ - if(!infoRec) return; - - if(infoRec->ClosePixmapCache) - (*infoRec->ClosePixmapCache)(infoRec->pScrn->pScreen); - - if(infoRec->PreAllocMem) - xfree(infoRec->PreAllocMem); - - if(infoRec->PixmapCachePrivate) - xfree(infoRec->PixmapCachePrivate); - - xfree(infoRec); -} - - -Bool -XAAInit(ScreenPtr pScreen, XAAInfoRecPtr infoRec) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XAAScreenPtr pScreenPriv; - int i; - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - - /* Return successfully if no acceleration wanted */ - if (!infoRec) - return TRUE; - - if (!dixRequestPrivate(XAAGCKey, sizeof(XAAGCRec))) - return FALSE; - - if (!dixRequestPrivate(XAAPixmapKey, sizeof(XAAPixmapRec))) - return FALSE; - - if (!(pScreenPriv = xalloc(sizeof(XAAScreenRec)))) - return FALSE; - - dixSetPrivate(&pScreen->devPrivates, XAAScreenKey, pScreenPriv); - - if(!xf86FBManagerRunning(pScreen)) - infoRec->Flags &= ~(PIXMAP_CACHE | OFFSCREEN_PIXMAPS); - if(!(infoRec->Flags & LINEAR_FRAMEBUFFER)) - infoRec->Flags &= ~OFFSCREEN_PIXMAPS; - - if(!infoRec->FullPlanemask) { /* for backwards compatibility */ - infoRec->FullPlanemask = (1 << pScrn->depth) - 1; - infoRec->FullPlanemasks[pScrn->depth - 1] = infoRec->FullPlanemask; - } - - for(i = 0; i < 32; i++) { - if(!infoRec->FullPlanemasks[i]) /* keep any set by caller */ - infoRec->FullPlanemasks[i] = (1 << (i+1)) - 1; - } - - if(!XAAInitAccel(pScreen, infoRec)) return FALSE; - pScreenPriv->AccelInfoRec = infoRec; - infoRec->ScratchGC.pScreen = pScreen; - - - if(!infoRec->GetImage) - infoRec->GetImage = XAAGetImage; - if(!infoRec->GetSpans) - infoRec->GetSpans = XAAGetSpans; - if(!infoRec->CopyWindow) - infoRec->CopyWindow = XAACopyWindow; - - pScreenPriv->CreateGC = pScreen->CreateGC; - pScreen->CreateGC = XAACreateGC; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = XAACloseScreen; - pScreenPriv->GetImage = pScreen->GetImage; - pScreen->GetImage = infoRec->GetImage; - pScreenPriv->GetSpans = pScreen->GetSpans; - pScreen->GetSpans = infoRec->GetSpans; - pScreenPriv->CopyWindow = pScreen->CopyWindow; - pScreen->CopyWindow = infoRec->CopyWindow; - pScreenPriv->CreatePixmap = pScreen->CreatePixmap; - pScreen->CreatePixmap = XAACreatePixmap; - pScreenPriv->DestroyPixmap = pScreen->DestroyPixmap; - pScreen->DestroyPixmap = XAADestroyPixmap; - pScreenPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; - pScreen->ChangeWindowAttributes = XAAChangeWindowAttributes; - - pScreenPriv->EnterVT = pScrn->EnterVT; - pScrn->EnterVT = XAAEnterVT; - pScreenPriv->LeaveVT = pScrn->LeaveVT; - pScrn->LeaveVT = XAALeaveVT; - pScreenPriv->SetDGAMode = pScrn->SetDGAMode; - pScrn->SetDGAMode = XAASetDGAMode; - pScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; - pScrn->EnableDisableFBAccess = XAAEnableDisableFBAccess; - - pScreenPriv->WindowExposures = pScreen->WindowExposures; - if (ps) - { - pScreenPriv->Composite = ps->Composite; - ps->Composite = XAAComposite; - pScreenPriv->Glyphs = ps->Glyphs; - ps->Glyphs = XAAGlyphs; - } - if(pScrn->overlayFlags & OVERLAY_8_32_PLANAR) - XAASetupOverlay8_32Planar(pScreen); - - infoRec->PreAllocMem = xalloc(MAX_PREALLOC_MEM); - if(infoRec->PreAllocMem) - infoRec->PreAllocSize = MAX_PREALLOC_MEM; - - if(infoRec->Flags & PIXMAP_CACHE) - xf86RegisterFreeBoxCallback(pScreen, infoRec->InitPixmapCache, - (pointer)infoRec); - - if(infoRec->Flags & MICROSOFT_ZERO_LINE_BIAS) - miSetZeroLineBias(pScreen, OCTANT1 | OCTANT2 | OCTANT3 | OCTANT4); - -#ifdef COMPOSITE - /* Initialize the composite wrapper. This needs to happen after the - * wrapping above (so it comes before us), but before all other extensions, - * so it doesn't confuse them. (particularly damage). - */ - miInitializeCompositeWrapper(pScreen); -#endif - - return TRUE; -} - - - -static Bool -XAACloseScreen (int i, ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XAAScreenPtr pScreenPriv = - (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); - - pScrn->EnterVT = pScreenPriv->EnterVT; - pScrn->LeaveVT = pScreenPriv->LeaveVT; - pScrn->EnableDisableFBAccess = pScreenPriv->EnableDisableFBAccess; - - pScreen->CreateGC = pScreenPriv->CreateGC; - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->GetImage = pScreenPriv->GetImage; - pScreen->GetSpans = pScreenPriv->GetSpans; - pScreen->CopyWindow = pScreenPriv->CopyWindow; - pScreen->WindowExposures = pScreenPriv->WindowExposures; - pScreen->CreatePixmap = pScreenPriv->CreatePixmap; - pScreen->DestroyPixmap = pScreenPriv->DestroyPixmap; - pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes; - - /* We leave it up to the client to free the XAAInfoRec */ - - xfree ((pointer) pScreenPriv); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static void -XAAGetImage ( - DrawablePtr pDraw, - int sx, int sy, int w, int h, - unsigned int format, - unsigned long planemask, - char *pdstLine -) -{ - ScreenPtr pScreen = pDraw->pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - ScrnInfoPtr pScrn = infoRec->pScrn; - - if(pScrn->vtSema && - ((pDraw->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pDraw))) - { - if(infoRec->ReadPixmap && (format == ZPixmap) && - ((planemask & infoRec->FullPlanemasks[pDraw->depth - 1]) == - infoRec->FullPlanemasks[pDraw->depth - 1]) && - (pDraw->bitsPerPixel == BitsPerPixel(pDraw->depth))) - { - (*infoRec->ReadPixmap)(pScrn, - sx + pDraw->x, sy + pDraw->y, w, h, - (unsigned char *)pdstLine, - PixmapBytePad(w, pDraw->depth), - pDraw->bitsPerPixel, pDraw->depth); - return; - } - SYNC_CHECK(pDraw); - } - - XAA_SCREEN_PROLOGUE (pScreen, GetImage); - (*pScreen->GetImage) (pDraw, sx, sy, w, h, format, planemask, pdstLine); - XAA_SCREEN_EPILOGUE (pScreen, GetImage, XAAGetImage); -} - -static void -XAAGetSpans ( - DrawablePtr pDraw, - int wMax, - DDXPointPtr ppt, - int *pwidth, - int nspans, - char *pdstStart -) -{ - ScreenPtr pScreen = pDraw->pScreen; - XAA_SCREEN_PROLOGUE (pScreen, GetSpans); - if(xf86Screens[pScreen->myNum]->vtSema && - ((pDraw->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pDraw))) { - SYNC_CHECK(pDraw); - } - (*pScreen->GetSpans) (pDraw, wMax, ppt, pwidth, nspans, pdstStart); - XAA_SCREEN_EPILOGUE (pScreen, GetSpans, XAAGetSpans); -} - - -static int -XAAPixmapBPP (ScreenPtr pScreen, int depth) -{ - PixmapPtr pPix; - int bpp; - DestroyPixmapProcPtr destroyPixmap; - - XAA_SCREEN_PROLOGUE (pScreen, CreatePixmap); - pPix = (*pScreen->CreatePixmap) (pScreen, 1, 1, depth, - CREATE_PIXMAP_USAGE_SCRATCH); - XAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, XAACreatePixmap); - if (!pPix) - return 0; - bpp = pPix->drawable.bitsPerPixel; - destroyPixmap = pScreen->DestroyPixmap; - XAA_SCREEN_PROLOGUE (pScreen, DestroyPixmap); - (*pScreen->DestroyPixmap) (pPix); - XAA_SCREEN_EPILOGUE (pScreen, DestroyPixmap, destroyPixmap); - return bpp; -} - -static void -XAAInitializeOffscreenDepths (ScreenPtr pScreen) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - int d, dep; - - infoRec->offscreenDepthsInitialized = TRUE; - infoRec->offscreenDepths = 0; - if (infoRec->Flags & OFFSCREEN_PIXMAPS) { - for (d = 0; d < pScreen->numDepths; d++) { - dep = pScreen->allowedDepths[d].depth; - if (XAAPixmapBPP (pScreen, dep) == pScrn->bitsPerPixel) - infoRec->offscreenDepths |= (1 << (dep - 1)); - } - } -} - -static PixmapPtr -XAACreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XAAPixmapPtr pPriv; - PixmapPtr pPix = NULL; - int size = w * h; - - if (w > 32767 || h > 32767) - return NullPixmap; - - if (!infoRec->offscreenDepthsInitialized) - XAAInitializeOffscreenDepths (pScreen); - - if(pScrn->vtSema && - (usage_hint != CREATE_PIXMAP_USAGE_GLYPH_PICTURE) && - (infoRec->offscreenDepths & (1 << (depth - 1))) && - (size >= MIN_OFFPIX_SIZE) && !SwitchedOut && - (!infoRec->maxOffPixWidth || (w <= infoRec->maxOffPixWidth)) && - (!infoRec->maxOffPixHeight || (h <= infoRec->maxOffPixHeight)) ) - { - PixmapLinkPtr pLink; - PixmapPtr pScreenPix; - FBAreaPtr area; - int gran = 0; - - switch(pScrn->bitsPerPixel) { - case 24: - case 8: gran = 4; break; - case 16: gran = 2; break; - case 32: gran = 1; break; - default: break; - } - - if(BITMAP_SCANLINE_PAD == 64) - gran *= 2; - - if(!(area = xf86AllocateOffscreenArea(pScreen, w, h, gran, 0, - XAARemoveAreaCallback, NULL))) { - goto BAILOUT; - } - - if(!(pLink = xalloc(sizeof(PixmapLink)))) { - xf86FreeOffscreenArea(area); - goto BAILOUT; - } - - XAA_SCREEN_PROLOGUE (pScreen, CreatePixmap); - pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, usage_hint); - XAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, XAACreatePixmap); - - if (!pPix) { - xfree (pLink); - xf86FreeOffscreenArea(area); - goto BAILOUT; - } - - pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); - - pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - pPix->drawable.x = area->box.x1; - pPix->drawable.y = area->box.y1; - pPix->drawable.width = w; - pPix->drawable.height = h; - pPix->drawable.bitsPerPixel = pScrn->bitsPerPixel; - pPix->devKind = pScreenPix->devKind; - pPix->devPrivate.ptr = pScreenPix->devPrivate.ptr; - area->devPrivate.ptr = pPix; - - pPriv->flags = OFFSCREEN; - pPriv->offscreenArea = area; - pPriv->freeData = FALSE; - - pLink->next = infoRec->OffscreenPixmaps; - pLink->pPix = pPix; - infoRec->OffscreenPixmaps = pLink; - return pPix; - } -BAILOUT: - XAA_SCREEN_PROLOGUE (pScreen, CreatePixmap); - pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint); - XAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, XAACreatePixmap); - - if(pPix) { - pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - pPriv->flags = 0; - pPriv->offscreenArea = NULL; - pPriv->freeData = FALSE; - if(!w || !h) /* either scratch or shared memory */ - pPriv->flags |= SHARED_PIXMAP; - } - - return pPix; -} - -static Bool -XAADestroyPixmap(PixmapPtr pPix) -{ - ScreenPtr pScreen = pPix->drawable.pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - Bool ret; - - if(pPix->refcnt == 1) { - if(pPriv->flags & OFFSCREEN) { - if(pPriv->flags & DGA_PIXMAP) - xfree(pPriv->offscreenArea); - else { - FBAreaPtr area = pPriv->offscreenArea; - PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; - PixmapLinkPtr prev = NULL; - - while(pLink->pPix != pPix) { - prev = pLink; - pLink = pLink->next; - } - - if(prev) prev->next = pLink->next; - else infoRec->OffscreenPixmaps = pLink->next; - - if(!area) area = pLink->area; - - xf86FreeOffscreenArea(area); - pPriv->offscreenArea = NULL; - xfree(pLink); - } - } - - if(pPriv->freeData) { /* pixmaps that were once in video ram */ - xfree(pPix->devPrivate.ptr); - pPix->devPrivate.ptr = NULL; - } - } - - XAA_SCREEN_PROLOGUE (pScreen, DestroyPixmap); - ret = (*pScreen->DestroyPixmap) (pPix); - XAA_SCREEN_EPILOGUE (pScreen, DestroyPixmap, XAADestroyPixmap); - - return ret; -} - -static Bool -XAAChangeWindowAttributes (WindowPtr pWin, unsigned long mask) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - Bool ret; - - XAA_SCREEN_PROLOGUE (pScreen, ChangeWindowAttributes); - ret = (*pScreen->ChangeWindowAttributes) (pWin, mask); - XAA_SCREEN_EPILOGUE (pScreen, ChangeWindowAttributes, XAAChangeWindowAttributes); - - /* we have to assume that shared memory pixmaps are dirty - because we can't wrap operations on them */ - - if((mask & CWBackPixmap) && (pWin->backgroundState == BackgroundPixmap) && - PIXMAP_IS_SHARED(pWin->background.pixmap)) - { - XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pWin->background.pixmap); - pPixPriv->flags |= DIRTY; - } - if((mask & CWBorderPixmap) && !(pWin->borderIsPixel) && - PIXMAP_IS_SHARED(pWin->border.pixmap)) - { - XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pWin->border.pixmap); - pPixPriv->flags |= DIRTY; - } - - return ret; -} - - - -/* These two aren't really needed for anything */ - -static Bool -XAAEnterVT(int index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - XAAScreenPtr pScreenPriv = - (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); - - return((*pScreenPriv->EnterVT)(index, flags)); -} - -static void -XAALeaveVT(int index, int flags) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - XAAScreenPtr pScreenPriv = - (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); - XAAInfoRecPtr infoRec = pScreenPriv->AccelInfoRec; - - if(infoRec->NeedToSync) { - (*infoRec->Sync)(infoRec->pScrn); - infoRec->NeedToSync = FALSE; - } - - (*pScreenPriv->LeaveVT)(index, flags); -} - -typedef struct { - Bool UsingPixmapCache; - Bool CanDoColor8x8; - Bool CanDoMono8x8; -} SavedCacheState, *SavedCacheStatePtr; - -static int -XAASetDGAMode(int index, int num, DGADevicePtr devRet) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAAScreenPtr pScreenPriv = - (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); - int ret; - - if (!num && infoRec->dgaSaves) { /* restore old pixmap cache state */ - SavedCacheStatePtr state = (SavedCacheStatePtr)infoRec->dgaSaves; - - infoRec->UsingPixmapCache = state->UsingPixmapCache; - infoRec->CanDoColor8x8 = state->CanDoColor8x8; - infoRec->CanDoMono8x8 = state->CanDoMono8x8; - xfree(infoRec->dgaSaves); - infoRec->dgaSaves = NULL; - } - - ret = (*pScreenPriv->SetDGAMode)(index, num, devRet); - if(ret != Success) return ret; - - if(num && devRet->pPix) { /* accelerate this pixmap */ - XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(devRet->pPix); - FBAreaPtr area; - - if((area = xalloc(sizeof(FBArea)))) { - area->pScreen = pScreen; - area->box.x1 = 0; - area->box.x2 = 0; - area->box.y1 = devRet->mode->pixmapWidth; - area->box.y2 = devRet->mode->pixmapHeight; - area->granularity = 0; - area->MoveAreaCallback = 0; - area->RemoveAreaCallback = 0; - area->devPrivate.ptr = 0; - - pixPriv->flags |= OFFSCREEN | DGA_PIXMAP; - pixPriv->offscreenArea = area; - - if(!infoRec->dgaSaves) { /* save pixmap cache state */ - SavedCacheStatePtr state = xalloc(sizeof(SavedCacheState)); - - state->UsingPixmapCache = infoRec->UsingPixmapCache; - state->CanDoColor8x8 = infoRec->CanDoColor8x8; - state->CanDoMono8x8 = infoRec->CanDoMono8x8; - infoRec->dgaSaves = (char*)state; - - infoRec->UsingPixmapCache = FALSE; - if(infoRec->PixmapCacheFlags & CACHE_MONO_8x8) - infoRec->CanDoMono8x8 = FALSE; - if(infoRec->PixmapCacheFlags & CACHE_COLOR_8x8) - infoRec->CanDoColor8x8 = FALSE; - } - } - } - - return ret; -} - - - -static void -XAAEnableDisableFBAccess (int index, Bool enable) -{ - ScreenPtr pScreen = screenInfo.screens[index]; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAAScreenPtr pScreenPriv = - (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); - - if(!enable) { - if((infoRec->Flags & OFFSCREEN_PIXMAPS) && (infoRec->OffscreenPixmaps)) - XAAMoveOutOffscreenPixmaps(pScreen); - if(infoRec->Flags & PIXMAP_CACHE) - XAAInvalidatePixmapCache(pScreen); - SwitchedOut = TRUE; - } - - (*pScreenPriv->EnableDisableFBAccess)(index, enable); - - if(enable) { - if((infoRec->Flags & OFFSCREEN_PIXMAPS) && (infoRec->OffscreenPixmaps)) - XAAMoveInOffscreenPixmaps(pScreen); - SwitchedOut = FALSE; - } -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miline.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "xf86fbman.h" +#include "servermd.h" +#ifdef COMPOSITE +#include "cw.h" +#endif + +#define MAX_PREALLOC_MEM 65536 /* MUST be >= 1024 */ + +#define MIN_OFFPIX_SIZE (320*200) + +static Bool XAACloseScreen(int i, ScreenPtr pScreen); +static void XAAGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planemask, + char *pdstLine); +static void XAAGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, + int *pwidth, int nspans, char *pdstStart); +static PixmapPtr XAACreatePixmap(ScreenPtr pScreen, int w, int h, int depth, + unsigned usage_hint); +static Bool XAADestroyPixmap(PixmapPtr pPixmap); +static Bool XAAEnterVT (int index, int flags); +static void XAALeaveVT (int index, int flags); +static int XAASetDGAMode(int index, int num, DGADevicePtr devRet); +static void XAAEnableDisableFBAccess (int index, Bool enable); +static Bool XAAChangeWindowAttributes (WindowPtr pWin, unsigned long mask); + +static int XAAScreenKeyIndex; +static DevPrivateKey XAAScreenKey = &XAAScreenKeyIndex; +static int XAAGCKeyIndex; +static DevPrivateKey XAAGCKey = &XAAGCKeyIndex; +static int XAAPixmapKeyIndex; +static DevPrivateKey XAAPixmapKey = &XAAPixmapKeyIndex; + +DevPrivateKey XAAGetScreenKey(void) { + return XAAScreenKey; +} + +DevPrivateKey XAAGetGCKey(void) { + return XAAGCKey; +} + +DevPrivateKey XAAGetPixmapKey(void) { + return XAAPixmapKey; +} + +/* temp kludge */ +static Bool SwitchedOut = FALSE; + +XAAInfoRecPtr +XAACreateInfoRec(void) +{ + XAAInfoRecPtr infoRec; + + infoRec = calloc(1, sizeof(XAAInfoRec)); + if(infoRec) + infoRec->CachePixelGranularity = -1; + + return infoRec; +} + +void +XAADestroyInfoRec(XAAInfoRecPtr infoRec) +{ + if(!infoRec) return; + + if(infoRec->ClosePixmapCache) + (*infoRec->ClosePixmapCache)(infoRec->pScrn->pScreen); + + if(infoRec->PreAllocMem) + free(infoRec->PreAllocMem); + + if(infoRec->PixmapCachePrivate) + free(infoRec->PixmapCachePrivate); + + free(infoRec); +} + + +Bool +XAAInit(ScreenPtr pScreen, XAAInfoRecPtr infoRec) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XAAScreenPtr pScreenPriv; + int i; + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + /* Return successfully if no acceleration wanted */ + if (!infoRec) + return TRUE; + + if (!dixRequestPrivate(XAAGCKey, sizeof(XAAGCRec))) + return FALSE; + + if (!dixRequestPrivate(XAAPixmapKey, sizeof(XAAPixmapRec))) + return FALSE; + + if (!(pScreenPriv = malloc(sizeof(XAAScreenRec)))) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, XAAScreenKey, pScreenPriv); + + if(!xf86FBManagerRunning(pScreen)) + infoRec->Flags &= ~(PIXMAP_CACHE | OFFSCREEN_PIXMAPS); + if(!(infoRec->Flags & LINEAR_FRAMEBUFFER)) + infoRec->Flags &= ~OFFSCREEN_PIXMAPS; + + if(!infoRec->FullPlanemask) { /* for backwards compatibility */ + infoRec->FullPlanemask = (1 << pScrn->depth) - 1; + infoRec->FullPlanemasks[pScrn->depth - 1] = infoRec->FullPlanemask; + } + + for(i = 0; i < 32; i++) { + if(!infoRec->FullPlanemasks[i]) /* keep any set by caller */ + infoRec->FullPlanemasks[i] = (1 << (i+1)) - 1; + } + + if(!XAAInitAccel(pScreen, infoRec)) return FALSE; + pScreenPriv->AccelInfoRec = infoRec; + infoRec->ScratchGC.pScreen = pScreen; + + + if(!infoRec->GetImage) + infoRec->GetImage = XAAGetImage; + if(!infoRec->GetSpans) + infoRec->GetSpans = XAAGetSpans; + if(!infoRec->CopyWindow) + infoRec->CopyWindow = XAACopyWindow; + + pScreenPriv->CreateGC = pScreen->CreateGC; + pScreen->CreateGC = XAACreateGC; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = XAACloseScreen; + pScreenPriv->GetImage = pScreen->GetImage; + pScreen->GetImage = infoRec->GetImage; + pScreenPriv->GetSpans = pScreen->GetSpans; + pScreen->GetSpans = infoRec->GetSpans; + pScreenPriv->CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = infoRec->CopyWindow; + pScreenPriv->CreatePixmap = pScreen->CreatePixmap; + pScreen->CreatePixmap = XAACreatePixmap; + pScreenPriv->DestroyPixmap = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = XAADestroyPixmap; + pScreenPriv->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + pScreen->ChangeWindowAttributes = XAAChangeWindowAttributes; + + pScreenPriv->EnterVT = pScrn->EnterVT; + pScrn->EnterVT = XAAEnterVT; + pScreenPriv->LeaveVT = pScrn->LeaveVT; + pScrn->LeaveVT = XAALeaveVT; + pScreenPriv->SetDGAMode = pScrn->SetDGAMode; + pScrn->SetDGAMode = XAASetDGAMode; + pScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; + pScrn->EnableDisableFBAccess = XAAEnableDisableFBAccess; + + pScreenPriv->WindowExposures = pScreen->WindowExposures; + if (ps) + { + pScreenPriv->Composite = ps->Composite; + ps->Composite = XAAComposite; + pScreenPriv->Glyphs = ps->Glyphs; + ps->Glyphs = XAAGlyphs; + } + if(pScrn->overlayFlags & OVERLAY_8_32_PLANAR) + XAASetupOverlay8_32Planar(pScreen); + + infoRec->PreAllocMem = malloc(MAX_PREALLOC_MEM); + if(infoRec->PreAllocMem) + infoRec->PreAllocSize = MAX_PREALLOC_MEM; + + if(infoRec->Flags & PIXMAP_CACHE) + xf86RegisterFreeBoxCallback(pScreen, infoRec->InitPixmapCache, + (pointer)infoRec); + + if(infoRec->Flags & MICROSOFT_ZERO_LINE_BIAS) + miSetZeroLineBias(pScreen, OCTANT1 | OCTANT2 | OCTANT3 | OCTANT4); + +#ifdef COMPOSITE + /* Initialize the composite wrapper. This needs to happen after the + * wrapping above (so it comes before us), but before all other extensions, + * so it doesn't confuse them. (particularly damage). + */ + miInitializeCompositeWrapper(pScreen); +#endif + + return TRUE; +} + + + +static Bool +XAACloseScreen (int i, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XAAScreenPtr pScreenPriv = + (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + + pScrn->EnterVT = pScreenPriv->EnterVT; + pScrn->LeaveVT = pScreenPriv->LeaveVT; + pScrn->EnableDisableFBAccess = pScreenPriv->EnableDisableFBAccess; + + pScreen->CreateGC = pScreenPriv->CreateGC; + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->CopyWindow = pScreenPriv->CopyWindow; + pScreen->WindowExposures = pScreenPriv->WindowExposures; + pScreen->CreatePixmap = pScreenPriv->CreatePixmap; + pScreen->DestroyPixmap = pScreenPriv->DestroyPixmap; + pScreen->ChangeWindowAttributes = pScreenPriv->ChangeWindowAttributes; + + /* We leave it up to the client to free the XAAInfoRec */ + + free((pointer) pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +XAAGetImage ( + DrawablePtr pDraw, + int sx, int sy, int w, int h, + unsigned int format, + unsigned long planemask, + char *pdstLine +) +{ + ScreenPtr pScreen = pDraw->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + ScrnInfoPtr pScrn = infoRec->pScrn; + + if(pScrn->vtSema && + ((pDraw->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pDraw))) + { + if(infoRec->ReadPixmap && (format == ZPixmap) && + ((planemask & infoRec->FullPlanemasks[pDraw->depth - 1]) == + infoRec->FullPlanemasks[pDraw->depth - 1]) && + (pDraw->bitsPerPixel == BitsPerPixel(pDraw->depth))) + { + (*infoRec->ReadPixmap)(pScrn, + sx + pDraw->x, sy + pDraw->y, w, h, + (unsigned char *)pdstLine, + PixmapBytePad(w, pDraw->depth), + pDraw->bitsPerPixel, pDraw->depth); + return; + } + SYNC_CHECK(pDraw); + } + + XAA_SCREEN_PROLOGUE (pScreen, GetImage); + (*pScreen->GetImage) (pDraw, sx, sy, w, h, format, planemask, pdstLine); + XAA_SCREEN_EPILOGUE (pScreen, GetImage, XAAGetImage); +} + +static void +XAAGetSpans ( + DrawablePtr pDraw, + int wMax, + DDXPointPtr ppt, + int *pwidth, + int nspans, + char *pdstStart +) +{ + ScreenPtr pScreen = pDraw->pScreen; + XAA_SCREEN_PROLOGUE (pScreen, GetSpans); + if(xf86Screens[pScreen->myNum]->vtSema && + ((pDraw->type == DRAWABLE_WINDOW) || IS_OFFSCREEN_PIXMAP(pDraw))) { + SYNC_CHECK(pDraw); + } + (*pScreen->GetSpans) (pDraw, wMax, ppt, pwidth, nspans, pdstStart); + XAA_SCREEN_EPILOGUE (pScreen, GetSpans, XAAGetSpans); +} + + +static int +XAAPixmapBPP (ScreenPtr pScreen, int depth) +{ + PixmapPtr pPix; + int bpp; + DestroyPixmapProcPtr destroyPixmap; + + XAA_SCREEN_PROLOGUE (pScreen, CreatePixmap); + pPix = (*pScreen->CreatePixmap) (pScreen, 1, 1, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + XAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, XAACreatePixmap); + if (!pPix) + return 0; + bpp = pPix->drawable.bitsPerPixel; + destroyPixmap = pScreen->DestroyPixmap; + XAA_SCREEN_PROLOGUE (pScreen, DestroyPixmap); + (*pScreen->DestroyPixmap) (pPix); + XAA_SCREEN_EPILOGUE (pScreen, DestroyPixmap, destroyPixmap); + return bpp; +} + +static void +XAAInitializeOffscreenDepths (ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + int d, dep; + + infoRec->offscreenDepthsInitialized = TRUE; + infoRec->offscreenDepths = 0; + if (infoRec->Flags & OFFSCREEN_PIXMAPS) { + for (d = 0; d < pScreen->numDepths; d++) { + dep = pScreen->allowedDepths[d].depth; + if (XAAPixmapBPP (pScreen, dep) == pScrn->bitsPerPixel) + infoRec->offscreenDepths |= (1 << (dep - 1)); + } + } +} + +static PixmapPtr +XAACreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XAAPixmapPtr pPriv; + PixmapPtr pPix = NULL; + int size = w * h; + + if (w > 32767 || h > 32767) + return NullPixmap; + + if (!infoRec->offscreenDepthsInitialized) + XAAInitializeOffscreenDepths (pScreen); + + if(pScrn->vtSema && + (usage_hint != CREATE_PIXMAP_USAGE_GLYPH_PICTURE) && + (infoRec->offscreenDepths & (1 << (depth - 1))) && + (size >= MIN_OFFPIX_SIZE) && !SwitchedOut && + (!infoRec->maxOffPixWidth || (w <= infoRec->maxOffPixWidth)) && + (!infoRec->maxOffPixHeight || (h <= infoRec->maxOffPixHeight)) ) + { + PixmapLinkPtr pLink; + PixmapPtr pScreenPix; + FBAreaPtr area; + int gran = 0; + + switch(pScrn->bitsPerPixel) { + case 24: + case 8: gran = 4; break; + case 16: gran = 2; break; + case 32: gran = 1; break; + default: break; + } + + if(BITMAP_SCANLINE_PAD == 64) + gran *= 2; + + if(!(area = xf86AllocateOffscreenArea(pScreen, w, h, gran, 0, + XAARemoveAreaCallback, NULL))) { + goto BAILOUT; + } + + if(!(pLink = malloc(sizeof(PixmapLink)))) { + xf86FreeOffscreenArea(area); + goto BAILOUT; + } + + XAA_SCREEN_PROLOGUE (pScreen, CreatePixmap); + pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, usage_hint); + XAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, XAACreatePixmap); + + if (!pPix) { + free(pLink); + xf86FreeOffscreenArea(area); + goto BAILOUT; + } + + pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); + + pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + pPix->drawable.x = area->box.x1; + pPix->drawable.y = area->box.y1; + pPix->drawable.width = w; + pPix->drawable.height = h; + pPix->drawable.bitsPerPixel = pScrn->bitsPerPixel; + pPix->devKind = pScreenPix->devKind; + pPix->devPrivate.ptr = pScreenPix->devPrivate.ptr; + area->devPrivate.ptr = pPix; + + pPriv->flags = OFFSCREEN; + pPriv->offscreenArea = area; + pPriv->freeData = FALSE; + + pLink->next = infoRec->OffscreenPixmaps; + pLink->pPix = pPix; + infoRec->OffscreenPixmaps = pLink; + return pPix; + } +BAILOUT: + XAA_SCREEN_PROLOGUE (pScreen, CreatePixmap); + pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint); + XAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, XAACreatePixmap); + + if(pPix) { + pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + pPriv->flags = 0; + pPriv->offscreenArea = NULL; + pPriv->freeData = FALSE; + if(!w || !h) /* either scratch or shared memory */ + pPriv->flags |= SHARED_PIXMAP; + } + + return pPix; +} + +static Bool +XAADestroyPixmap(PixmapPtr pPix) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + Bool ret; + + if(pPix->refcnt == 1) { + if(pPriv->flags & OFFSCREEN) { + if(pPriv->flags & DGA_PIXMAP) + free(pPriv->offscreenArea); + else { + FBAreaPtr area = pPriv->offscreenArea; + PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; + PixmapLinkPtr prev = NULL; + + while(pLink->pPix != pPix) { + prev = pLink; + pLink = pLink->next; + } + + if(prev) prev->next = pLink->next; + else infoRec->OffscreenPixmaps = pLink->next; + + if(!area) area = pLink->area; + + xf86FreeOffscreenArea(area); + pPriv->offscreenArea = NULL; + free(pLink); + } + } + + if(pPriv->freeData) { /* pixmaps that were once in video ram */ + free(pPix->devPrivate.ptr); + pPix->devPrivate.ptr = NULL; + } + } + + XAA_SCREEN_PROLOGUE (pScreen, DestroyPixmap); + ret = (*pScreen->DestroyPixmap) (pPix); + XAA_SCREEN_EPILOGUE (pScreen, DestroyPixmap, XAADestroyPixmap); + + return ret; +} + +static Bool +XAAChangeWindowAttributes (WindowPtr pWin, unsigned long mask) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + Bool ret; + + XAA_SCREEN_PROLOGUE (pScreen, ChangeWindowAttributes); + ret = (*pScreen->ChangeWindowAttributes) (pWin, mask); + XAA_SCREEN_EPILOGUE (pScreen, ChangeWindowAttributes, XAAChangeWindowAttributes); + + /* we have to assume that shared memory pixmaps are dirty + because we can't wrap operations on them */ + + if((mask & CWBackPixmap) && (pWin->backgroundState == BackgroundPixmap) && + PIXMAP_IS_SHARED(pWin->background.pixmap)) + { + XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pWin->background.pixmap); + pPixPriv->flags |= DIRTY; + } + if((mask & CWBorderPixmap) && !(pWin->borderIsPixel) && + PIXMAP_IS_SHARED(pWin->border.pixmap)) + { + XAAPixmapPtr pPixPriv = XAA_GET_PIXMAP_PRIVATE(pWin->border.pixmap); + pPixPriv->flags |= DIRTY; + } + + return ret; +} + + + +/* These two aren't really needed for anything */ + +static Bool +XAAEnterVT(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + XAAScreenPtr pScreenPriv = + (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + + return((*pScreenPriv->EnterVT)(index, flags)); +} + +static void +XAALeaveVT(int index, int flags) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + XAAScreenPtr pScreenPriv = + (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + XAAInfoRecPtr infoRec = pScreenPriv->AccelInfoRec; + + if(infoRec->NeedToSync) { + (*infoRec->Sync)(infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + + (*pScreenPriv->LeaveVT)(index, flags); +} + +typedef struct { + Bool UsingPixmapCache; + Bool CanDoColor8x8; + Bool CanDoMono8x8; +} SavedCacheState, *SavedCacheStatePtr; + +static int +XAASetDGAMode(int index, int num, DGADevicePtr devRet) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAScreenPtr pScreenPriv = + (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + int ret; + + if (!num && infoRec->dgaSaves) { /* restore old pixmap cache state */ + SavedCacheStatePtr state = (SavedCacheStatePtr)infoRec->dgaSaves; + + infoRec->UsingPixmapCache = state->UsingPixmapCache; + infoRec->CanDoColor8x8 = state->CanDoColor8x8; + infoRec->CanDoMono8x8 = state->CanDoMono8x8; + free(infoRec->dgaSaves); + infoRec->dgaSaves = NULL; + } + + ret = (*pScreenPriv->SetDGAMode)(index, num, devRet); + if(ret != Success) return ret; + + if(num && devRet->pPix) { /* accelerate this pixmap */ + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(devRet->pPix); + FBAreaPtr area; + + if((area = malloc(sizeof(FBArea)))) { + area->pScreen = pScreen; + area->box.x1 = 0; + area->box.x2 = 0; + area->box.y1 = devRet->mode->pixmapWidth; + area->box.y2 = devRet->mode->pixmapHeight; + area->granularity = 0; + area->MoveAreaCallback = 0; + area->RemoveAreaCallback = 0; + area->devPrivate.ptr = 0; + + pixPriv->flags |= OFFSCREEN | DGA_PIXMAP; + pixPriv->offscreenArea = area; + + if(!infoRec->dgaSaves) { /* save pixmap cache state */ + SavedCacheStatePtr state = malloc(sizeof(SavedCacheState)); + + state->UsingPixmapCache = infoRec->UsingPixmapCache; + state->CanDoColor8x8 = infoRec->CanDoColor8x8; + state->CanDoMono8x8 = infoRec->CanDoMono8x8; + infoRec->dgaSaves = (char*)state; + + infoRec->UsingPixmapCache = FALSE; + if(infoRec->PixmapCacheFlags & CACHE_MONO_8x8) + infoRec->CanDoMono8x8 = FALSE; + if(infoRec->PixmapCacheFlags & CACHE_COLOR_8x8) + infoRec->CanDoColor8x8 = FALSE; + } + } + } + + return ret; +} + + + +static void +XAAEnableDisableFBAccess (int index, Bool enable) +{ + ScreenPtr pScreen = screenInfo.screens[index]; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAScreenPtr pScreenPriv = + (XAAScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XAAScreenKey); + + if(!enable) { + if((infoRec->Flags & OFFSCREEN_PIXMAPS) && (infoRec->OffscreenPixmaps)) + XAAMoveOutOffscreenPixmaps(pScreen); + if(infoRec->Flags & PIXMAP_CACHE) + XAAInvalidatePixmapCache(pScreen); + SwitchedOut = TRUE; + } + + (*pScreenPriv->EnableDisableFBAccess)(index, enable); + + if(enable) { + if((infoRec->Flags & OFFSCREEN_PIXMAPS) && (infoRec->OffscreenPixmaps)) + XAAMoveInOffscreenPixmaps(pScreen); + SwitchedOut = FALSE; + } +} diff --git a/xorg-server/hw/xfree86/xaa/xaaInitAccel.c b/xorg-server/hw/xfree86/xaa/xaaInitAccel.c index 6f3d622e1..d24599d48 100644 --- a/xorg-server/hw/xfree86/xaa/xaaInitAccel.c +++ b/xorg-server/hw/xfree86/xaa/xaaInitAccel.c @@ -1,1498 +1,1498 @@ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xf86fbman.h" -#include "servermd.h" - -/* - * XAA Config options - */ - -typedef enum { - XAAOPT_SCREEN_TO_SCREEN_COPY, - XAAOPT_SOLID_FILL_RECT, - XAAOPT_SOLID_FILL_TRAP, - XAAOPT_SOLID_TWO_POINT_LINE, - XAAOPT_SOLID_BRESENHAM_LINE, - XAAOPT_SOLID_HORVERT_LINE, - XAAOPT_DASHED_TWO_POINT_LINE, - XAAOPT_DASHED_BRESENHAM_LINE, - XAAOPT_MONO_8x8_PATTERN_FILL_RECT, - XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, - XAAOPT_COL_8x8_PATTERN_FILL_RECT, - XAAOPT_COL_8x8_PATTERN_FILL_TRAP, - XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, - XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL, - XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, - XAAOPT_IMAGE_WRITE_RECT, - XAAOPT_SCANLINE_IMAGE_WRITE_RECT, - XAAOPT_WRITE_BITMAP, - XAAOPT_WRITE_PIXMAP, - XAAOPT_PIXMAP_CACHE, - XAAOPT_OFFSCREEN_PIXMAPS, - XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE -} XAAOpts; - -static const OptionInfoRec XAAOptions[] = { - {XAAOPT_SCREEN_TO_SCREEN_COPY, "XaaNoScreenToScreenCopy", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_SOLID_FILL_RECT, "XaaNoSolidFillRect", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_SOLID_FILL_TRAP, "XaaNoSolidFillTrap", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_SOLID_TWO_POINT_LINE, "XaaNoSolidTwoPointLine", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_SOLID_BRESENHAM_LINE, "XaaNoSolidBresenhamLine", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_SOLID_HORVERT_LINE, "XaaNoSolidHorVertLine", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_DASHED_TWO_POINT_LINE, "XaaNoDashedTwoPointLine", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_DASHED_BRESENHAM_LINE, "XaaNoDashedBresenhamLine", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_MONO_8x8_PATTERN_FILL_RECT, "XaaNoMono8x8PatternFillRect", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, "XaaNoMono8x8PatternFillTrap", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_COL_8x8_PATTERN_FILL_RECT, "XaaNoColor8x8PatternFillRect", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_COL_8x8_PATTERN_FILL_TRAP, "XaaNoColor8x8PatternFillTrap", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, "XaaNoCPUToScreenColorExpandFill", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL,"XaaNoScanlineCPUToScreenColorExpandFill", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, "XaaNoScreenToScreenColorExpandFill", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_IMAGE_WRITE_RECT, "XaaNoImageWriteRect", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_SCANLINE_IMAGE_WRITE_RECT, "XaaNoScanlineImageWriteRect", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_WRITE_BITMAP, "XaaNoWriteBitmap", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_WRITE_PIXMAP, "XaaNoWritePixmap", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_PIXMAP_CACHE, "XaaNoPixmapCache", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_OFFSCREEN_PIXMAPS, "XaaNoOffscreenPixmaps", - OPTV_BOOLEAN, {0}, FALSE }, - {XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE, "XaaOffscreenPixmaps", - OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, - OPTV_NONE, {0}, FALSE } -}; - -static XF86ModuleVersionInfo xaaVersRec = -{ - "xaa", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - XAA_VERSION_MAJOR, - XAA_VERSION_MINOR, - XAA_VERSION_RELEASE, - ABI_CLASS_VIDEODRV, /* requires the video driver ABI */ - ABI_VIDEODRV_VERSION, - MOD_CLASS_NONE, - {0,0,0,0} -}; - -_X_EXPORT XF86ModuleData xaaModuleData = { &xaaVersRec, NULL, NULL }; - -Bool -XAAInitAccel(ScreenPtr pScreen, XAAInfoRecPtr infoRec) -{ - int index = pScreen->myNum; - ScrnInfoPtr pScrn = xf86Screens[index]; - Bool HaveScreenToScreenCopy = FALSE; - Bool HaveColorExpansion = FALSE; - Bool HaveScanlineColorExpansion = FALSE; - Bool HaveSolidFillRect = FALSE; - Bool HaveMono8x8PatternFillRect = FALSE; - Bool HaveColor8x8PatternFillRect = FALSE; - Bool HaveSolidFillTrap = FALSE; - Bool HaveMono8x8PatternFillTrap = FALSE; - Bool HaveColor8x8PatternFillTrap = FALSE; - Bool HaveSolidTwoPointLine = FALSE; - Bool HaveSolidBresenhamLine = FALSE; - Bool HaveSolidHorVertLine = FALSE; - Bool HaveDashedTwoPointLine = FALSE; - Bool HaveDashedBresenhamLine = FALSE; - Bool HaveImageWriteRect = FALSE; - Bool HaveScanlineImageWriteRect = FALSE; - Bool HaveScreenToScreenColorExpandFill = FALSE; - OptionInfoPtr options; - int is_shared = 0; - int i; - - options = xnfalloc(sizeof(XAAOptions)); - (void)memcpy(options, XAAOptions, sizeof(XAAOptions)); - xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); - - infoRec->pScrn = pScrn; - infoRec->NeedToSync = FALSE; - - /* must have a Sync function */ - if(!infoRec->Sync) return FALSE; - for(i = 0; i < pScrn->numEntities; i++) { - if(xf86IsEntityShared(pScrn->entityList[i])) is_shared = 1; - } - - /* If this PCI entity has IS_SHARED_ACCEL set in entityProp - * then a RestoreAccelState function is required - */ - if(!infoRec->RestoreAccelState && is_shared) return FALSE; - - if(infoRec->RestoreAccelState) { - if(!XAAInitStateWrap(pScreen, infoRec)) return FALSE; - } - - if (serverGeneration == 1) - xf86DrvMsg(index, X_INFO, - "Using XFree86 Acceleration Architecture (XAA)\n"); - - - /************** Low Level *************/ - - if(!infoRec->SetClippingRectangle || !infoRec->DisableClipping) { - infoRec->ClippingFlags = 0; - infoRec->SetClippingRectangle = NULL; - infoRec->DisableClipping = NULL; - } - - /**** CopyArea ****/ - - if(infoRec->SetupForScreenToScreenCopy && - infoRec->SubsequentScreenToScreenCopy && - !xf86ReturnOptValBool(options, XAAOPT_SCREEN_TO_SCREEN_COPY, FALSE)) { - HaveScreenToScreenCopy = TRUE; - } else { - infoRec->ScreenToScreenCopyFlags = 0; - infoRec->SetupForScreenToScreenCopy = NULL; - infoRec->SubsequentScreenToScreenCopy = NULL; - } - - /**** Solid Filled Rects ****/ - - if(infoRec->SetupForSolidFill && infoRec->SubsequentSolidFillRect && - !xf86ReturnOptValBool(options, XAAOPT_SOLID_FILL_RECT, FALSE)) { - HaveSolidFillRect = TRUE; - if(infoRec->SubsequentSolidFillTrap && - !xf86ReturnOptValBool(options, XAAOPT_SOLID_FILL_TRAP, FALSE)) - HaveSolidFillTrap = TRUE; - else - infoRec->SubsequentSolidFillTrap = NULL; - } else { - infoRec->SolidFillFlags = 0; - infoRec->SetupForSolidFill = NULL; - infoRec->SubsequentSolidFillRect = NULL; - infoRec->SubsequentSolidFillTrap = NULL; - } - - /**** Solid lines ****/ - - if(infoRec->SetupForSolidLine) { - if(infoRec->SubsequentSolidTwoPointLine && - !xf86ReturnOptValBool(options, - XAAOPT_SOLID_TWO_POINT_LINE, FALSE)) - HaveSolidTwoPointLine = TRUE; - if(infoRec->SubsequentSolidBresenhamLine && - !xf86ReturnOptValBool(options, XAAOPT_SOLID_BRESENHAM_LINE, FALSE)) { - HaveSolidBresenhamLine = TRUE; - - if(infoRec->SolidBresenhamLineErrorTermBits) - infoRec->SolidBresenhamLineErrorTermBits = - ~((1 << infoRec->SolidBresenhamLineErrorTermBits) - 1); - } - - if(infoRec->SubsequentSolidHorVertLine && - !xf86ReturnOptValBool(options, - XAAOPT_SOLID_HORVERT_LINE, FALSE)) - HaveSolidHorVertLine = TRUE; - else if(HaveSolidTwoPointLine) { - infoRec->SubsequentSolidHorVertLine = - XAASolidHorVertLineAsTwoPoint; - HaveSolidHorVertLine = TRUE; - } else if(HaveSolidBresenhamLine) { - infoRec->SubsequentSolidHorVertLine = - XAASolidHorVertLineAsBresenham; - HaveSolidHorVertLine = TRUE; - } - } - - /* XXX Should this also check for XAAOPT_SOLID_HORVERT_LINE? */ - if (!HaveSolidTwoPointLine && - !HaveSolidBresenhamLine && - !HaveSolidHorVertLine && - HaveSolidFillRect) { - infoRec->SetupForSolidLine = infoRec->SetupForSolidFill; - infoRec->SubsequentSolidHorVertLine = XAASolidHorVertLineAsRects; - infoRec->SolidLineFlags = infoRec->SolidFillFlags; - HaveSolidHorVertLine = TRUE; - } - - if (!HaveSolidTwoPointLine) - infoRec->SubsequentSolidTwoPointLine = NULL; - if (!HaveSolidBresenhamLine) - infoRec->SubsequentSolidBresenhamLine = NULL; - if (!HaveSolidHorVertLine) - infoRec->SubsequentSolidHorVertLine = NULL; - - /* Disable all if nothing left over */ - if (!HaveSolidTwoPointLine && - !HaveSolidBresenhamLine && - !HaveSolidHorVertLine) { - infoRec->SolidLineFlags = 0; - infoRec->SetupForSolidLine = NULL; - } - - /**** 8x8 Mono Pattern Filled Rects ****/ - - if(infoRec->SetupForMono8x8PatternFill && - infoRec->SubsequentMono8x8PatternFillRect && - !xf86ReturnOptValBool(options, - XAAOPT_MONO_8x8_PATTERN_FILL_RECT, - FALSE)) { - HaveMono8x8PatternFillRect = TRUE; - if(infoRec->SubsequentMono8x8PatternFillTrap && - !xf86ReturnOptValBool(options, - XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, - FALSE)) - HaveMono8x8PatternFillTrap = TRUE; - - if(infoRec->Mono8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_BITS) { - infoRec->CanDoMono8x8 = TRUE; - } else { /* others require caching */ - int min_pitch; - infoRec->PixmapCacheFlags |= CACHE_MONO_8x8; - - switch(pScrn->bitsPerPixel) { - case 32: min_pitch = 2; break; - case 24: min_pitch = 3; break; - case 16: min_pitch = 4; break; - default: min_pitch = 8; break; - } - - if(min_pitch > infoRec->MonoPatternPitch) - infoRec->MonoPatternPitch = min_pitch; - - if(infoRec->Mono8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { - if(!infoRec->CacheWidthMono8x8Pattern || - !infoRec->CacheHeightMono8x8Pattern) { - infoRec->CacheWidthMono8x8Pattern = - infoRec->MonoPatternPitch; - infoRec->CacheHeightMono8x8Pattern = 1; - } - } else { - int numPerLine = 128/infoRec->MonoPatternPitch; - - if(!infoRec->CacheWidthMono8x8Pattern || - !infoRec->CacheHeightMono8x8Pattern) { - infoRec->CacheWidthMono8x8Pattern = - numPerLine * infoRec->MonoPatternPitch; - infoRec->CacheHeightMono8x8Pattern = - (64 + numPerLine - 1)/numPerLine; - } - } - } - } else { - infoRec->Mono8x8PatternFillFlags = 0; - infoRec->SetupForMono8x8PatternFill = NULL; - infoRec->SubsequentMono8x8PatternFillRect = NULL; - } - - /**** Dashed lines ****/ - - if(infoRec->SetupForDashedLine && infoRec->DashPatternMaxLength) { - if(infoRec->SubsequentDashedTwoPointLine && - !xf86ReturnOptValBool(options, XAAOPT_DASHED_TWO_POINT_LINE, - FALSE)) - HaveDashedTwoPointLine = TRUE; - if(infoRec->SubsequentDashedBresenhamLine && - !xf86ReturnOptValBool(options, XAAOPT_DASHED_BRESENHAM_LINE, - FALSE)) { - HaveDashedBresenhamLine = TRUE; - - if(infoRec->DashedBresenhamLineErrorTermBits) - infoRec->DashedBresenhamLineErrorTermBits = - ~((1 << infoRec->DashedBresenhamLineErrorTermBits) - 1); - } - } - - if (!HaveDashedTwoPointLine) - infoRec->SubsequentDashedTwoPointLine = NULL; - if (!HaveDashedBresenhamLine) - infoRec->SubsequentDashedBresenhamLine = NULL; - - /* Disable all if nothing left over */ - if (!HaveDashedTwoPointLine && !HaveDashedBresenhamLine) { - infoRec->DashedLineFlags = 0; - infoRec->SetupForDashedLine = NULL; - } - - /**** 8x8 Color Pattern Filled Rects ****/ - - if(infoRec->SetupForColor8x8PatternFill && - infoRec->SubsequentColor8x8PatternFillRect && - !xf86ReturnOptValBool(options, XAAOPT_COL_8x8_PATTERN_FILL_RECT, FALSE)) { - HaveColor8x8PatternFillRect = TRUE; - if(infoRec->SubsequentColor8x8PatternFillTrap && - !xf86ReturnOptValBool(options, XAAOPT_COL_8x8_PATTERN_FILL_TRAP, - FALSE)) - HaveColor8x8PatternFillTrap = TRUE; - else - infoRec->SubsequentColor8x8PatternFillTrap = NULL; - - infoRec->PixmapCacheFlags |= CACHE_COLOR_8x8; - - if(infoRec->Color8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { - if(!infoRec->CacheWidthColor8x8Pattern || - !infoRec->CacheHeightColor8x8Pattern) { - infoRec->CacheWidthColor8x8Pattern = 64; - infoRec->CacheHeightColor8x8Pattern = 1; - } - } else { - if(!infoRec->CacheWidthColor8x8Pattern || - !infoRec->CacheHeightColor8x8Pattern) { - infoRec->CacheWidthColor8x8Pattern = 128; - infoRec->CacheHeightColor8x8Pattern = 8; - } - } - } else { - infoRec->Color8x8PatternFillFlags = 0; - infoRec->SetupForColor8x8PatternFill = NULL; - infoRec->SubsequentColor8x8PatternFillRect = NULL; - infoRec->SubsequentColor8x8PatternFillTrap = NULL; - } - - /**** Color Expansion ****/ - - if(infoRec->SetupForCPUToScreenColorExpandFill && - infoRec->ColorExpandBase && - infoRec->SubsequentCPUToScreenColorExpandFill && - !xf86ReturnOptValBool(options, XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, - FALSE)) { - int dwordsNeeded = pScrn->virtualX; - - infoRec->ColorExpandRange >>= 2; /* convert to DWORDS */ - HaveColorExpansion = TRUE; - - if(infoRec->CPUToScreenColorExpandFillFlags & - LEFT_EDGE_CLIPPING_NEGATIVE_X) - dwordsNeeded += 31; - dwordsNeeded = (dwordsNeeded + 31) >> 5; - if(dwordsNeeded > infoRec->ColorExpandRange) - infoRec->CPUToScreenColorExpandFillFlags |= CPU_TRANSFER_BASE_FIXED; - } else { - infoRec->CPUToScreenColorExpandFillFlags = 0; - infoRec->SetupForCPUToScreenColorExpandFill = NULL; - infoRec->SubsequentCPUToScreenColorExpandFill = NULL; - } - - /**** Scanline Color Expansion ****/ - - if(infoRec->SetupForScanlineCPUToScreenColorExpandFill && - infoRec->SubsequentScanlineCPUToScreenColorExpandFill && - infoRec->SubsequentColorExpandScanline && - infoRec->ScanlineColorExpandBuffers && - (infoRec->NumScanlineColorExpandBuffers > 0) && - !xf86ReturnOptValBool(options, - XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL, - FALSE)) { - HaveScanlineColorExpansion = TRUE; - } else { - infoRec->ScanlineCPUToScreenColorExpandFillFlags = 0; - infoRec->SetupForScanlineCPUToScreenColorExpandFill = NULL; - infoRec->SubsequentScanlineCPUToScreenColorExpandFill = NULL; - infoRec->SubsequentColorExpandScanline = NULL; - } - - /**** Screen to Screen Color Expansion ****/ - - if(infoRec->SetupForScreenToScreenColorExpandFill && - infoRec->SubsequentScreenToScreenColorExpandFill && - !xf86ReturnOptValBool(options, XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, - FALSE)) { - HaveScreenToScreenColorExpandFill = TRUE; - if (!infoRec->CacheColorExpandDensity) - infoRec->CacheColorExpandDensity = 1; - } else { - infoRec->ScreenToScreenColorExpandFillFlags = 0; - infoRec->SetupForScreenToScreenColorExpandFill = NULL; - infoRec->SubsequentScreenToScreenColorExpandFill = NULL; - } - - /**** Image Writes ****/ - - if(infoRec->SetupForImageWrite && infoRec->ImageWriteBase && - infoRec->SubsequentImageWriteRect && - !xf86ReturnOptValBool(options, XAAOPT_IMAGE_WRITE_RECT, FALSE)) { - - infoRec->ImageWriteRange >>= 2; /* convert to DWORDS */ - if(infoRec->ImageWriteFlags & CPU_TRANSFER_BASE_FIXED) - infoRec->ImageWriteRange = 0; - HaveImageWriteRect = TRUE; - } else { - infoRec->ImageWriteFlags = 0; - infoRec->SetupForImageWrite = NULL; - infoRec->SubsequentImageWriteRect = NULL; - } - - /**** Scanline Image Writes ****/ - - if(infoRec->SetupForScanlineImageWrite && - infoRec->SubsequentScanlineImageWriteRect && - infoRec->SubsequentImageWriteScanline && - infoRec->ScanlineImageWriteBuffers && - (infoRec->NumScanlineImageWriteBuffers > 0) && - !xf86ReturnOptValBool(options, XAAOPT_SCANLINE_IMAGE_WRITE_RECT, - FALSE)) { - HaveScanlineImageWriteRect = TRUE; - } else { - infoRec->ScanlineImageWriteFlags = 0; - infoRec->SetupForScanlineImageWrite = NULL; - infoRec->SubsequentScanlineImageWriteRect = NULL; - infoRec->SubsequentImageWriteScanline = NULL; - } - -#ifndef __i386__ - /* XAA makes some unaligned accesses when clipping is not available */ -# define CLIP_FLAGS (LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X) - if(HaveImageWriteRect && - ((infoRec->ImageWriteFlags & CLIP_FLAGS) != CLIP_FLAGS)) - { - HaveImageWriteRect = FALSE; - } - if(HaveScanlineImageWriteRect && - ((infoRec->ScanlineImageWriteFlags & CLIP_FLAGS) != CLIP_FLAGS)) - { - HaveScanlineImageWriteRect = FALSE; - } -#endif - - if (serverGeneration == 1) { - if(HaveScreenToScreenCopy) - xf86ErrorF("\tScreen to screen bit blits\n"); - if(HaveSolidFillRect) - xf86ErrorF("\tSolid filled rectangles\n"); - if(HaveSolidFillTrap) - xf86ErrorF("\tSolid filled trapezoids\n"); - if(HaveMono8x8PatternFillRect) - xf86ErrorF("\t8x8 mono pattern filled rectangles\n"); - if(HaveMono8x8PatternFillTrap) - xf86ErrorF("\t8x8 mono pattern filled trapezoids\n"); - if(HaveColor8x8PatternFillRect) - xf86ErrorF("\t8x8 color pattern filled rectangles\n"); - if(HaveColor8x8PatternFillTrap) - xf86ErrorF("\t8x8 color pattern filled trapezoids\n"); - - if(HaveColorExpansion) - xf86ErrorF("\tCPU to Screen color expansion\n"); - else if(HaveScanlineColorExpansion) - xf86ErrorF("\tIndirect CPU to Screen color expansion\n"); - - if(HaveScreenToScreenColorExpandFill) - xf86ErrorF("\tScreen to Screen color expansion\n"); - - if(HaveSolidTwoPointLine || HaveSolidBresenhamLine) - xf86ErrorF("\tSolid Lines\n"); - else if(HaveSolidHorVertLine) - xf86ErrorF("\tSolid Horizontal and Vertical Lines\n"); - - if(HaveDashedTwoPointLine || HaveDashedBresenhamLine) - xf86ErrorF("\tDashed Lines\n"); - - if(HaveImageWriteRect) - xf86ErrorF("\tImage Writes\n"); - else if(HaveScanlineImageWriteRect) - xf86ErrorF("\tScanline Image Writes\n"); - - } - -#define XAAMSG(s) do { if (serverGeneration == 1) xf86ErrorF(s); } while (0) - - if((infoRec->Flags & OFFSCREEN_PIXMAPS) && HaveScreenToScreenCopy && - xf86ReturnOptValBool(options, - XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE, - FALSE)) - { - XAAMSG("\tOffscreen Pixmaps\n"); - } else { - infoRec->Flags &= ~OFFSCREEN_PIXMAPS; - } - - - /************** Mid Level *************/ - - /**** ScreenToScreenBitBlt ****/ - - if(infoRec->ScreenToScreenBitBlt) { - XAAMSG("\tDriver provided ScreenToScreenBitBlt replacement\n"); - } else if(HaveScreenToScreenCopy) { - infoRec->ScreenToScreenBitBlt = XAAScreenToScreenBitBlt; - infoRec->ScreenToScreenBitBltFlags = infoRec->ScreenToScreenCopyFlags; - } - - /**** FillSolidRects ****/ - - if(infoRec->FillSolidRects) { - XAAMSG("\tDriver provided FillSolidRects replacement\n"); - } else if(HaveSolidFillRect) { - infoRec->FillSolidRects = XAAFillSolidRects; - infoRec->FillSolidRectsFlags = infoRec->SolidFillFlags; - } - - /**** FillSolidSpans ****/ - - if(infoRec->FillSolidSpans) { - XAAMSG("\tDriver provided FillSolidSpans replacement\n"); - } else if(HaveSolidFillRect) { - infoRec->FillSolidSpans = XAAFillSolidSpans; - infoRec->FillSolidSpansFlags = infoRec->SolidFillFlags; - } - - /**** FillMono8x8PatternRects ****/ - - if(infoRec->FillMono8x8PatternRects) { - XAAMSG("\tDriver provided FillMono8x8PatternRects replacement\n"); - } else if(HaveMono8x8PatternFillRect) { - infoRec->FillMono8x8PatternRects = - (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? - XAAFillMono8x8PatternRectsScreenOrigin : - XAAFillMono8x8PatternRects; - - infoRec->FillMono8x8PatternRectsFlags = - infoRec->Mono8x8PatternFillFlags; - } - - /**** FillMono8x8PatternSpans ****/ - - if(infoRec->FillMono8x8PatternSpans) { - XAAMSG("\tDriver provided FillMono8x8PatternSpans replacement\n"); - } else if(HaveMono8x8PatternFillRect) { - infoRec->FillMono8x8PatternSpans = - (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? - XAAFillMono8x8PatternSpansScreenOrigin: - XAAFillMono8x8PatternSpans; - - infoRec->FillMono8x8PatternSpansFlags = - infoRec->Mono8x8PatternFillFlags; - } - - /**** FillColor8x8Rects ****/ - - if(infoRec->FillColor8x8PatternRects) { - XAAMSG("\tDriver provided FillColor8x8PatternRects replacement\n"); - } else if(HaveColor8x8PatternFillRect) { - infoRec->FillColor8x8PatternRects = - (infoRec->Color8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? - XAAFillColor8x8PatternRectsScreenOrigin : - XAAFillColor8x8PatternRects; - - infoRec->FillColor8x8PatternRectsFlags = - infoRec->Color8x8PatternFillFlags; - } - - /**** FillColor8x8Spans ****/ - - if(infoRec->FillColor8x8PatternSpans) { - XAAMSG("\tDriver provided FillColor8x8PatternSpans replacement\n"); - } else if(HaveColor8x8PatternFillRect) { - infoRec->FillColor8x8PatternSpans = - (infoRec->Color8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? - XAAFillColor8x8PatternSpansScreenOrigin: - XAAFillColor8x8PatternSpans; - - infoRec->FillColor8x8PatternSpansFlags = - infoRec->Color8x8PatternFillFlags; - } - - /**** FillCacheBltRects ****/ - - if(infoRec->FillCacheBltRects) { - XAAMSG("\tDriver provided FillCacheBltRects replacement\n"); - } else if(HaveScreenToScreenCopy) { - infoRec->FillCacheBltRects = XAAFillCacheBltRects; - infoRec->FillCacheBltRectsFlags = infoRec->ScreenToScreenCopyFlags; - } - - /**** FillCacheBltSpans ****/ - - if(infoRec->FillCacheBltSpans) { - XAAMSG("\tDriver provided FillCacheBltSpans replacement\n"); - } else if(HaveScreenToScreenCopy) { - infoRec->FillCacheBltSpans = XAAFillCacheBltSpans; - infoRec->FillCacheBltSpansFlags = infoRec->ScreenToScreenCopyFlags; - } - - /**** FillCacheExpandRects ****/ - - if(infoRec->FillCacheExpandRects) { - XAAMSG("\tDriver provided FillCacheExpandRects replacement\n"); - } else if(HaveScreenToScreenColorExpandFill) { - infoRec->FillCacheExpandRects = XAAFillCacheExpandRects; - infoRec->FillCacheExpandRectsFlags = - infoRec->ScreenToScreenColorExpandFillFlags; - } - - /**** FillCacheExpandSpans ****/ - - if(infoRec->FillCacheExpandSpans) { - XAAMSG("\tDriver provided FillCacheExpandSpans replacement\n"); - } else if(HaveScreenToScreenColorExpandFill) { - infoRec->FillCacheExpandSpans = XAAFillCacheExpandSpans; - infoRec->FillCacheExpandSpansFlags = - infoRec->ScreenToScreenColorExpandFillFlags; - } - - /**** FillColorExpandRects ****/ - - if(infoRec->FillColorExpandRects) { - XAAMSG("\tDriver provided FillColorExpandRects replacement\n"); - } else if(HaveColorExpansion) { - if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { - if(infoRec->CPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->FillColorExpandRects = - XAAFillColorExpandRects3MSBFirstFixedBase; - else - infoRec->FillColorExpandRects = - XAAFillColorExpandRects3MSBFirst; - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->FillColorExpandRects = - XAAFillColorExpandRects3LSBFirstFixedBase; - else - infoRec->FillColorExpandRects = - XAAFillColorExpandRects3LSBFirst; - } - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->FillColorExpandRects = - XAAFillColorExpandRectsMSBFirstFixedBase; - else - infoRec->FillColorExpandRects = - XAAFillColorExpandRectsMSBFirst; - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->FillColorExpandRects = - XAAFillColorExpandRectsLSBFirstFixedBase; - else - infoRec->FillColorExpandRects = - XAAFillColorExpandRectsLSBFirst; - } - } - infoRec->FillColorExpandRectsFlags = - infoRec->CPUToScreenColorExpandFillFlags; - } else if(HaveScanlineColorExpansion) { - if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & - TRIPLE_BITS_24BPP) { - if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) - infoRec->FillColorExpandRects = - XAAFillScanlineColorExpandRects3MSBFirst; - else - infoRec->FillColorExpandRects = - XAAFillScanlineColorExpandRects3LSBFirst; - } else { - if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) - infoRec->FillColorExpandRects = - XAAFillScanlineColorExpandRectsMSBFirst; - else - infoRec->FillColorExpandRects = - XAAFillScanlineColorExpandRectsLSBFirst; - } - infoRec->FillColorExpandRectsFlags = - infoRec->ScanlineCPUToScreenColorExpandFillFlags; - } - - /**** FillColorExpandSpans ****/ - - if(infoRec->FillColorExpandSpans) { - XAAMSG("\tDriver provided FillColorExpandSpans replacement\n"); - } else if(HaveColorExpansion) { - if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { - if(infoRec->CPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->FillColorExpandSpans = - XAAFillColorExpandSpans3MSBFirstFixedBase; - else - infoRec->FillColorExpandSpans = - XAAFillColorExpandSpans3MSBFirst; - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->FillColorExpandSpans = - XAAFillColorExpandSpans3LSBFirstFixedBase; - else - infoRec->FillColorExpandSpans = - XAAFillColorExpandSpans3LSBFirst; - } - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->FillColorExpandSpans = - XAAFillColorExpandSpansMSBFirstFixedBase; - else - infoRec->FillColorExpandSpans = - XAAFillColorExpandSpansMSBFirst; - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->FillColorExpandSpans = - XAAFillColorExpandSpansLSBFirstFixedBase; - else - infoRec->FillColorExpandSpans = - XAAFillColorExpandSpansLSBFirst; - } - } - infoRec->FillColorExpandSpansFlags = - infoRec->CPUToScreenColorExpandFillFlags; - } else if(HaveScanlineColorExpansion) { - if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & - TRIPLE_BITS_24BPP) { - if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) - infoRec->FillColorExpandSpans = - XAAFillScanlineColorExpandSpans3MSBFirst; - else - infoRec->FillColorExpandSpans = - XAAFillScanlineColorExpandSpans3LSBFirst; - } else { - if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) - infoRec->FillColorExpandSpans = - XAAFillScanlineColorExpandSpansMSBFirst; - else - infoRec->FillColorExpandSpans = - XAAFillScanlineColorExpandSpansLSBFirst; - } - infoRec->FillColorExpandSpansFlags = - infoRec->ScanlineCPUToScreenColorExpandFillFlags; - } - - /**** FillImageWriteRects ****/ - - if(infoRec->FillImageWriteRects) { - XAAMSG("\tDriver provided FillImageWriteRects replacement\n"); - } else if(HaveImageWriteRect && - (infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && - (infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) { - infoRec->FillImageWriteRects = XAAFillImageWriteRects; - infoRec->FillImageWriteRectsFlags = infoRec->ImageWriteFlags; - } - - /**** WriteBitmap ****/ - - if(infoRec->WriteBitmap && - !xf86ReturnOptValBool(options, XAAOPT_WRITE_BITMAP, FALSE)) { - XAAMSG("\tDriver provided WriteBitmap replacement\n"); - } else if(HaveColorExpansion) { - if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { - if(infoRec->CPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->WriteBitmap = - XAAWriteBitmapColorExpand3MSBFirstFixedBase; - else - infoRec->WriteBitmap = XAAWriteBitmapColorExpand3MSBFirst; - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->WriteBitmap = - XAAWriteBitmapColorExpand3LSBFirstFixedBase; - else - infoRec->WriteBitmap = XAAWriteBitmapColorExpand3LSBFirst; - } - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->WriteBitmap = - XAAWriteBitmapColorExpandMSBFirstFixedBase; - else - infoRec->WriteBitmap = XAAWriteBitmapColorExpandMSBFirst; - } else { - if(infoRec->CPUToScreenColorExpandFillFlags & - CPU_TRANSFER_BASE_FIXED) - infoRec->WriteBitmap = - XAAWriteBitmapColorExpandLSBFirstFixedBase; - else - infoRec->WriteBitmap = XAAWriteBitmapColorExpandLSBFirst; - } - } - infoRec->WriteBitmapFlags = infoRec->CPUToScreenColorExpandFillFlags; - } else if(HaveScanlineColorExpansion) { - if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & - TRIPLE_BITS_24BPP) { - if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) - infoRec->WriteBitmap = - XAAWriteBitmapScanlineColorExpand3MSBFirst; - else - infoRec->WriteBitmap = - XAAWriteBitmapScanlineColorExpand3LSBFirst; - } else { - if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST) - infoRec->WriteBitmap = - XAAWriteBitmapScanlineColorExpandMSBFirst; - else - infoRec->WriteBitmap = - XAAWriteBitmapScanlineColorExpandLSBFirst; - } - infoRec->WriteBitmapFlags = - infoRec->ScanlineCPUToScreenColorExpandFillFlags; - } else - infoRec->WriteBitmap = NULL; - - /**** TE Glyphs ****/ - - if (infoRec->TEGlyphRenderer) { - XAAMSG("\tDriver provided TEGlyphRenderer replacement\n"); - } else if (HaveColorExpansion) { - infoRec->TEGlyphRendererFlags = - infoRec->CPUToScreenColorExpandFillFlags; - - if (infoRec->TEGlyphRendererFlags & TRIPLE_BITS_24BPP) { - if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { - if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) - infoRec->TEGlyphRenderer = - XAATEGlyphRenderer3MSBFirstFixedBase; - else - infoRec->TEGlyphRenderer = XAATEGlyphRenderer3MSBFirst; - } else { - if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) - infoRec->TEGlyphRenderer = - XAATEGlyphRenderer3LSBFirstFixedBase; - else - infoRec->TEGlyphRenderer = XAATEGlyphRenderer3LSBFirst; - } - - if (!HaveSolidFillRect && - (infoRec->TEGlyphRendererFlags & RGB_EQUAL)) { - infoRec->TEGlyphRendererFlags &= ~RGB_EQUAL; - XAAMSG("WARNING: TEGlyphRenderer cannot support RGB_EQUAL" - " without solid fills\n"); - } - } else { - if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { - if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) - infoRec->TEGlyphRenderer = - XAATEGlyphRendererMSBFirstFixedBase; - else - infoRec->TEGlyphRenderer = XAATEGlyphRendererMSBFirst; - } else { - if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) - infoRec->TEGlyphRenderer = - XAATEGlyphRendererLSBFirstFixedBase; - else - infoRec->TEGlyphRenderer = XAATEGlyphRendererLSBFirst; - } - } - - if (!HaveSolidFillRect && - (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { - infoRec->TEGlyphRendererFlags &= ~TRANSPARENCY_ONLY; - XAAMSG("WARNING: TEGlyphRenderer cannot support TRANPARENCY_ONLY" - " without solid fills\n"); - } - - } else if (HaveScanlineColorExpansion) { - infoRec->TEGlyphRendererFlags = - infoRec->ScanlineCPUToScreenColorExpandFillFlags; - - if (infoRec->TEGlyphRendererFlags & TRIPLE_BITS_24BPP) { - if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) - infoRec->TEGlyphRenderer = XAATEGlyphRendererScanline3MSBFirst; - else - infoRec->TEGlyphRenderer = XAATEGlyphRendererScanline3LSBFirst; - - if (!HaveSolidFillRect && - (infoRec->TEGlyphRendererFlags & RGB_EQUAL)) { - infoRec->TEGlyphRendererFlags &= ~RGB_EQUAL; - XAAMSG("WARNING: TEGlyphRenderer cannot support RGB_EQUAL" - " without solid fills\n"); - } - } else { - if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) - infoRec->TEGlyphRenderer = XAATEGlyphRendererScanlineMSBFirst; - else - infoRec->TEGlyphRenderer = XAATEGlyphRendererScanlineLSBFirst; - } - - if (!HaveSolidFillRect && - (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { - infoRec->TEGlyphRendererFlags &= ~TRANSPARENCY_ONLY; - XAAMSG("WARNING: TEGlyphRenderer cannot support TRANPARENCY_ONLY" - " without solid fills\n"); - } - } - - /**** NonTE Glyphs ****/ - - if(infoRec->NonTEGlyphRenderer) { - XAAMSG("\tDriver provided NonTEGlyphRenderer replacement\n"); - } else if(infoRec->WriteBitmap && - !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) { - infoRec->NonTEGlyphRenderer = XAANonTEGlyphRenderer; - infoRec->NonTEGlyphRendererFlags = infoRec->WriteBitmapFlags; - } - - /**** WritePixmap ****/ - - if(infoRec->WritePixmap && - !xf86ReturnOptValBool(options, XAAOPT_WRITE_PIXMAP, FALSE)) { - XAAMSG("\tDriver provided WritePixmap replacement\n"); - } else if(HaveImageWriteRect) { - infoRec->WritePixmap = XAAWritePixmap; - infoRec->WritePixmapFlags = - infoRec->ImageWriteFlags | CONVERT_32BPP_TO_24BPP; - } else if(HaveScanlineImageWriteRect) { - infoRec->WritePixmap = XAAWritePixmapScanline; - infoRec->WritePixmapFlags = infoRec->ScanlineImageWriteFlags; - } else - infoRec->WritePixmap = NULL; - - /**** ReadPixmap ****/ - - if(infoRec->ReadPixmap) { - XAAMSG("\tDriver provided ReadPixmap replacement\n"); - } - - - /************** GC Level *************/ - - /**** CopyArea ****/ - - if(infoRec->CopyArea) { - XAAMSG("\tDriver provided GC level CopyArea replacement\n"); - } else if(infoRec->ScreenToScreenBitBlt) { - infoRec->CopyArea = XAACopyArea; - infoRec->CopyAreaFlags = infoRec->ScreenToScreenBitBltFlags; - - /* most GC level primitives use one mid-level primitive so - the GC level primitive gets the mid-level primitive flag - and we use that at GC validation time. But CopyArea uses - more than one mid-level primitive so we have to essentially - do a GC validation every time that primitive is used. - The CopyAreaFlags would only be used for filtering out the - common denominators. Here we assume that if you don't do - ScreenToScreenBitBlt you aren't going to do the others. - We also assume that ScreenToScreenBitBlt has the least - restrictions. */ - } - - if(infoRec->CopyPlane) { - XAAMSG("\tDriver provided GC level CopyPlane replacement\n"); - } else if(infoRec->WriteBitmap && - !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) { - infoRec->CopyPlane = XAACopyPlaneColorExpansion; - infoRec->CopyPlaneFlags = infoRec->WriteBitmapFlags; - } - - if(infoRec->PushPixelsSolid) { - XAAMSG("\tDriver provided GC level PushPixelsSolid replacement\n"); - } else if(infoRec->WriteBitmap && - !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) { - infoRec->PushPixelsSolid = XAAPushPixelsSolidColorExpansion; - infoRec->PushPixelsFlags = infoRec->WriteBitmapFlags; - } - - if(infoRec->FillSolidRects) { - if(!infoRec->PolyFillRectSolid) { - infoRec->PolyFillRectSolid = XAAPolyFillRect; - infoRec->PolyFillRectSolidFlags = infoRec->FillSolidRectsFlags; - } - } - if(infoRec->FillSolidSpans) { - if(!infoRec->FillSpansSolid) { - infoRec->FillSpansSolid = XAAFillSpans; - infoRec->FillSpansSolidFlags = infoRec->FillSolidSpansFlags; - } - } - - if(infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || - infoRec->FillCacheBltRects || infoRec->FillColorExpandRects || - infoRec->FillCacheExpandRects) { - if(!infoRec->PolyFillRectStippled) { - - infoRec->PolyFillRectStippled = XAAPolyFillRect; - infoRec->PolyFillRectStippledFlags = 0; - } - } - - if(infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || - infoRec->FillCacheBltSpans || infoRec->FillColorExpandSpans || - infoRec->FillCacheExpandSpans) { - if(!infoRec->FillSpansStippled) { - - infoRec->FillSpansStippled = XAAFillSpans; - infoRec->FillSpansStippledFlags = 0; - } - } - - if(infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || - infoRec->FillCacheBltRects || infoRec->FillColorExpandRects || - infoRec->FillCacheExpandRects) { - if(!infoRec->PolyFillRectOpaqueStippled) { - - infoRec->PolyFillRectOpaqueStippled = XAAPolyFillRect; - infoRec->PolyFillRectOpaqueStippledFlags = 0; - } - } - - if(infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || - infoRec->FillCacheBltSpans || infoRec->FillColorExpandSpans || - infoRec->FillCacheExpandSpans) { - if(!infoRec->FillSpansOpaqueStippled) { - - infoRec->FillSpansOpaqueStippled = XAAFillSpans; - infoRec->FillSpansOpaqueStippledFlags = 0; - } - } - - if(infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || - infoRec->FillCacheBltRects || infoRec->FillImageWriteRects) { - if(!infoRec->PolyFillRectTiled) { - - infoRec->PolyFillRectTiled = XAAPolyFillRect; - infoRec->PolyFillRectTiledFlags = 0; - } - } - - if(infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || - infoRec->FillCacheBltSpans) { - if(!infoRec->FillSpansTiled) { - - infoRec->FillSpansTiled = XAAFillSpans; - infoRec->FillSpansTiledFlags = 0; - } - } - - if(infoRec->TEGlyphRenderer && - !(infoRec->TEGlyphRendererFlags & NO_TRANSPARENCY)) { - - if(!infoRec->PolyText8TE) { - infoRec->PolyText8TE = XAAPolyText8TEColorExpansion; - infoRec->PolyText8TEFlags = infoRec->TEGlyphRendererFlags; - } - - if(!infoRec->PolyText16TE) { - infoRec->PolyText16TE = XAAPolyText16TEColorExpansion; - infoRec->PolyText16TEFlags = infoRec->TEGlyphRendererFlags; - } - - if(!infoRec->PolyGlyphBltTE) { - infoRec->PolyGlyphBltTE = XAAPolyGlyphBltTEColorExpansion; - infoRec->PolyGlyphBltTEFlags = infoRec->TEGlyphRendererFlags; - } - } - - if(infoRec->TEGlyphRenderer && - !(infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { - - if(!infoRec->ImageText8TE) { - infoRec->ImageText8TE = XAAImageText8TEColorExpansion; - infoRec->ImageText8TEFlags = infoRec->TEGlyphRendererFlags; - } - - if(!infoRec->ImageText16TE) { - infoRec->ImageText16TE = XAAImageText16TEColorExpansion; - infoRec->ImageText16TEFlags = infoRec->TEGlyphRendererFlags; - } - - if(!infoRec->ImageGlyphBltTE) { - infoRec->ImageGlyphBltTE = XAAImageGlyphBltTEColorExpansion; - infoRec->ImageGlyphBltTEFlags = infoRec->TEGlyphRendererFlags; - } - } - - if(infoRec->NonTEGlyphRenderer) { - if(!infoRec->PolyText8NonTE) { - infoRec->PolyText8NonTE = XAAPolyText8NonTEColorExpansion; - infoRec->PolyText8NonTEFlags = infoRec->NonTEGlyphRendererFlags; - } - - if(!infoRec->PolyText16NonTE) { - infoRec->PolyText16NonTE = XAAPolyText16NonTEColorExpansion; - infoRec->PolyText16NonTEFlags = infoRec->NonTEGlyphRendererFlags; - } - if(!infoRec->PolyGlyphBltNonTE) { - infoRec->PolyGlyphBltNonTE = XAAPolyGlyphBltNonTEColorExpansion; - infoRec->PolyGlyphBltNonTEFlags = infoRec->NonTEGlyphRendererFlags; - } - } - - if(infoRec->NonTEGlyphRenderer && HaveSolidFillRect) { - if(!infoRec->ImageText8NonTE) { - infoRec->ImageText8NonTE = XAAImageText8NonTEColorExpansion; - infoRec->ImageText8NonTEFlags = infoRec->NonTEGlyphRendererFlags; - } - - if(!infoRec->ImageText16NonTE) { - infoRec->ImageText16NonTE = XAAImageText16NonTEColorExpansion; - infoRec->ImageText16NonTEFlags = infoRec->NonTEGlyphRendererFlags; - } - - if(!infoRec->ImageGlyphBltNonTE) { - infoRec->ImageGlyphBltNonTE = XAAImageGlyphBltNonTEColorExpansion; - infoRec->ImageGlyphBltNonTEFlags = infoRec->NonTEGlyphRendererFlags; - } - } - - if(!infoRec->PolyRectangleThinSolid && HaveSolidHorVertLine) { - infoRec->PolyRectangleThinSolid = XAAPolyRectangleThinSolid; - infoRec->PolyRectangleThinSolidFlags = infoRec->SolidLineFlags; - } - - if(!infoRec->FillPolygonSolid && HaveSolidFillRect) { - infoRec->FillPolygonSolid = XAAFillPolygonSolid; - infoRec->FillPolygonSolidFlags = infoRec->SolidFillFlags; - } - - if(!infoRec->FillPolygonStippled && (HaveMono8x8PatternFillRect || - HaveScreenToScreenColorExpandFill || HaveScreenToScreenCopy)) { - infoRec->FillPolygonStippled = XAAFillPolygonStippled; - infoRec->FillPolygonStippledFlags = infoRec->SolidFillFlags; - } - - if(!infoRec->FillPolygonOpaqueStippled && (HaveMono8x8PatternFillRect || - HaveScreenToScreenColorExpandFill || HaveScreenToScreenCopy)) { - infoRec->FillPolygonOpaqueStippled = XAAFillPolygonStippled; - infoRec->FillPolygonOpaqueStippledFlags = infoRec->SolidFillFlags; - } - - if(!infoRec->FillPolygonTiled && (HaveMono8x8PatternFillRect || - HaveScreenToScreenColorExpandFill || HaveScreenToScreenCopy)) { - infoRec->FillPolygonTiled = XAAFillPolygonTiled; - infoRec->FillPolygonTiledFlags = infoRec->SolidFillFlags; - } - - - if(!infoRec->PolyFillArcSolid && HaveSolidFillRect) { - infoRec->PolyFillArcSolid = XAAPolyFillArcSolid; - infoRec->PolyFillArcSolidFlags = infoRec->SolidFillFlags; - } - - if(!infoRec->PolylinesWideSolid && HaveSolidFillRect) { - infoRec->PolylinesWideSolid = XAAPolylinesWideSolid; - infoRec->PolylinesWideSolidFlags = - infoRec->SolidFillFlags | GXCOPY_ONLY; - } - - if(!infoRec->PutImage && (infoRec->WritePixmap || - (infoRec->WriteBitmap && - !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)))) { - infoRec->PutImage = XAAPutImage; - - /* See comment for CopyArea above. But here we make fewer - assumptions. The driver can provide the PutImageFlags if - it wants too */ - } - - if(HaveSolidHorVertLine && - (HaveSolidBresenhamLine || (HaveSolidTwoPointLine && - (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_LINE)))){ - if(!infoRec->PolylinesThinSolid) { - infoRec->PolylinesThinSolid = XAAPolyLines; - infoRec->PolylinesThinSolidFlags = infoRec->SolidLineFlags; - } - if(!infoRec->PolySegmentThinSolid) { - infoRec->PolySegmentThinSolid = XAAPolySegment; - infoRec->PolySegmentThinSolidFlags = infoRec->SolidLineFlags; - } - } - - if(HaveDashedBresenhamLine || (HaveDashedTwoPointLine && - (infoRec->ClippingFlags & HARDWARE_CLIP_DASHED_LINE))){ - if(!infoRec->PolylinesThinDashed) { - infoRec->PolylinesThinDashed = XAAPolyLinesDashed; - infoRec->PolylinesThinDashedFlags = infoRec->DashedLineFlags; - } - if(!infoRec->PolySegmentThinDashed) { - infoRec->PolySegmentThinDashed = XAAPolySegmentDashed; - infoRec->PolySegmentThinDashedFlags = infoRec->DashedLineFlags; - } - } - - if(infoRec->PolylinesThinDashed || infoRec->PolySegmentThinDashed) { - if(!infoRec->ComputeDash) - infoRec->ComputeDash = XAAComputeDash; - } - - { - Bool haveTexture = infoRec->CPUToScreenTextureFormats && - infoRec->CPUToScreenTextureDstFormats && - infoRec->SetupForCPUToScreenTexture2 && - infoRec->SubsequentCPUToScreenTexture; - Bool haveAlphaTexture = infoRec->CPUToScreenAlphaTextureFormats && - infoRec->CPUToScreenAlphaTextureDstFormats && - infoRec->SetupForCPUToScreenAlphaTexture2 && - infoRec->SubsequentCPUToScreenAlphaTexture; - - if(!infoRec->Composite && (haveTexture || haveAlphaTexture)) - infoRec->Composite = XAADoComposite; - - if(!infoRec->Glyphs && infoRec->WriteBitmap && - !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) - { - infoRec->Glyphs = XAADoGlyphs; - } - } - - /************ Validation Functions **************/ - - if(!infoRec->ValidateCopyArea && infoRec->CopyArea) { - infoRec->CopyAreaMask = GCWhenForced; - if((infoRec->CopyAreaFlags & GXCOPY_ONLY) || - (infoRec->CopyAreaFlags & ROP_NEEDS_SOURCE)) - infoRec->CopyAreaMask |= GCFunction; - if(infoRec->CopyAreaFlags & NO_PLANEMASK) - infoRec->CopyAreaMask |= GCPlaneMask; - infoRec->ValidateCopyArea = XAAValidateCopyArea; - } - - if(!infoRec->ValidateCopyPlane && infoRec->CopyPlane) { - infoRec->CopyPlaneMask = GCWhenForced; - if((infoRec->CopyPlaneFlags & GXCOPY_ONLY) || - (infoRec->CopyPlaneFlags & ROP_NEEDS_SOURCE)) - infoRec->CopyPlaneMask |= GCFunction; - if(infoRec->CopyPlaneFlags & NO_PLANEMASK) - infoRec->CopyPlaneMask |= GCPlaneMask; - if(infoRec->CopyPlaneFlags & RGB_EQUAL) - infoRec->CopyPlaneMask |= GCForeground | GCBackground; - infoRec->ValidateCopyPlane = XAAValidateCopyPlane; - } - - if(!infoRec->ValidatePutImage && infoRec->PutImage) { - infoRec->PutImageMask = GCWhenForced; - if((infoRec->PutImageFlags & GXCOPY_ONLY) || - (infoRec->PutImageFlags & ROP_NEEDS_SOURCE)) - infoRec->PutImageMask |= GCFunction; - if(infoRec->PutImageFlags & NO_PLANEMASK) - infoRec->PutImageMask |= GCPlaneMask; - if(infoRec->PutImageFlags & RGB_EQUAL) - infoRec->PutImageMask |= GCForeground | GCBackground; - infoRec->ValidatePutImage = XAAValidatePutImage; - } - - - if(!infoRec->ValidatePushPixels && infoRec->PushPixelsSolid) { - infoRec->PushPixelsMask = GCFillStyle; - if((infoRec->PushPixelsFlags & GXCOPY_ONLY) || - (infoRec->PushPixelsFlags & ROP_NEEDS_SOURCE) || - (infoRec->PushPixelsFlags & TRANSPARENCY_GXCOPY_ONLY)) - infoRec->PushPixelsMask |= GCFunction; - if(infoRec->PushPixelsFlags & NO_PLANEMASK) - infoRec->PushPixelsMask |= GCPlaneMask; - if(infoRec->PushPixelsFlags & RGB_EQUAL) - infoRec->PushPixelsMask |= GCForeground; - infoRec->ValidatePushPixels = XAAValidatePushPixels; - } - - /* By default XAA assumes the FillSpans, PolyFillRects, FillPolygon - and PolyFillArcs have the same restrictions. If you supply GC - level replacements for any of these and alter this relationship - you may need to supply replacement validation routines */ - - if(!infoRec->ValidateFillSpans && - (infoRec->FillSpansSolid || infoRec->FillSpansStippled || - infoRec->FillSpansOpaqueStippled || infoRec->FillSpansTiled)) { - - int compositeFlags = infoRec->FillSpansSolidFlags | - infoRec->FillSpansStippledFlags | - infoRec->FillSpansOpaqueStippledFlags | - infoRec->FillSpansTiledFlags; - - infoRec->FillSpansMask = GCFillStyle | GCTile | GCStipple; - - if((compositeFlags & GXCOPY_ONLY) || - (compositeFlags & ROP_NEEDS_SOURCE)) - infoRec->FillSpansMask |= GCFunction; - if(compositeFlags & NO_PLANEMASK) - infoRec->FillSpansMask |= GCPlaneMask; - if(compositeFlags & RGB_EQUAL) - infoRec->FillSpansMask |= GCForeground; - infoRec->ValidateFillSpans = XAAValidateFillSpans; - } - - /* By default XAA only provides Validations for the GlyphBlt - functions and not the text higher up. This is because the - Text8/16 and GlyphBlt are linked. If you break this linkage, - you may need to have the driver supply its own Validation - routines */ - - if(!infoRec->ValidatePolyGlyphBlt && - (infoRec->PolyGlyphBltTE || infoRec->PolyGlyphBltNonTE)) { - int compositeFlags = infoRec->PolyGlyphBltTEFlags | - infoRec->PolyGlyphBltNonTEFlags; - - infoRec->PolyGlyphBltMask = GCFillStyle | GCFont; - if((compositeFlags & GXCOPY_ONLY) || - (compositeFlags & ROP_NEEDS_SOURCE) || - (infoRec->PolyGlyphBltNonTEFlags & TRANSPARENCY_GXCOPY_ONLY)) - infoRec->PolyGlyphBltMask |= GCFunction; - if(compositeFlags & NO_PLANEMASK) - infoRec->PolyGlyphBltMask |= GCPlaneMask; - if(compositeFlags & RGB_EQUAL) - infoRec->PolyGlyphBltMask |= GCForeground; - infoRec->ValidatePolyGlyphBlt = XAAValidatePolyGlyphBlt; - } - - if(!infoRec->ValidateImageGlyphBlt && - (infoRec->ImageGlyphBltTE || infoRec->ImageGlyphBltNonTE)) { - int compositeFlags = infoRec->ImageGlyphBltTEFlags | - infoRec->ImageGlyphBltNonTEFlags; - - if(infoRec->ImageGlyphBltNonTE) - compositeFlags |= infoRec->SolidFillFlags; - - infoRec->ImageGlyphBltMask = GCFont; - if(compositeFlags & NO_PLANEMASK) - infoRec->ImageGlyphBltMask |= GCPlaneMask; - if(compositeFlags & RGB_EQUAL) - infoRec->ImageGlyphBltMask |= GCForeground | GCBackground; - infoRec->ValidateImageGlyphBlt = XAAValidateImageGlyphBlt; - } - - /* By default XAA only provides a Validation function for the - Polylines and does segments and polylines at the same time */ - - if(!infoRec->ValidatePolylines && infoRec->ValidateFillSpans) { - int compositeFlags = infoRec->PolyRectangleThinSolidFlags | - infoRec->PolylinesWideSolidFlags | - infoRec->PolylinesThinSolidFlags | - infoRec->PolySegmentThinSolidFlags | - infoRec->PolySegmentThinDashedFlags | - infoRec->PolylinesThinDashedFlags; - - infoRec->ValidatePolylines = XAAValidatePolylines; - infoRec->PolylinesMask = - infoRec->FillSpansMask | GCLineStyle | GCLineWidth; - - if(infoRec->PolySegmentThinDashed || infoRec->PolylinesThinDashed) - infoRec->PolylinesMask |= GCDashList; - if(compositeFlags & NO_PLANEMASK) - infoRec->PolylinesMask |= GCPlaneMask; - if((compositeFlags & GXCOPY_ONLY) || - (compositeFlags & ROP_NEEDS_SOURCE)) - infoRec->PolylinesMask |= GCFunction; - if(compositeFlags & RGB_EQUAL) - infoRec->PolylinesMask |= GCForeground; - } - - - /**** Fill choosers ****/ - - if(!infoRec->StippledFillChooser) - infoRec->StippledFillChooser = XAAStippledFillChooser; - - if(!infoRec->OpaqueStippledFillChooser) - infoRec->OpaqueStippledFillChooser = XAAOpaqueStippledFillChooser; - - if(!infoRec->TiledFillChooser) - infoRec->TiledFillChooser = XAATiledFillChooser; - - - /**** Setup the pixmap cache ****/ - - if(infoRec->WriteBitmapToCache) {} - else if(infoRec->WriteBitmap && - !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) - infoRec->WriteBitmapToCache = XAAWriteBitmapToCache; - else if(infoRec->Flags & LINEAR_FRAMEBUFFER) - infoRec->WriteBitmapToCache = XAAWriteBitmapToCacheLinear; - else - infoRec->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES; - - if(infoRec->WritePixmapToCache) {} - else if(infoRec->WritePixmap && !(infoRec->WritePixmapFlags & NO_GXCOPY)) - infoRec->WritePixmapToCache = XAAWritePixmapToCache; - else if(infoRec->Flags & LINEAR_FRAMEBUFFER) - infoRec->WritePixmapToCache = XAAWritePixmapToCacheLinear; - else - infoRec->Flags &= ~PIXMAP_CACHE; - - if (xf86ReturnOptValBool(options, XAAOPT_PIXMAP_CACHE, FALSE)) - infoRec->Flags &= ~PIXMAP_CACHE; - - if(infoRec->WriteMono8x8PatternToCache) {} - else if(infoRec->PixmapCacheFlags & CACHE_MONO_8x8) { - if(infoRec->WritePixmapToCache) - infoRec->WriteMono8x8PatternToCache = XAAWriteMono8x8PatternToCache; - else - infoRec->PixmapCacheFlags &= ~CACHE_MONO_8x8; - } - - if(infoRec->WriteColor8x8PatternToCache) {} - else if(infoRec->PixmapCacheFlags & CACHE_COLOR_8x8) { - if(infoRec->WritePixmapToCache && infoRec->WriteBitmapToCache) - infoRec->WriteColor8x8PatternToCache = XAAWriteColor8x8PatternToCache; - else - infoRec->PixmapCacheFlags &= ~CACHE_COLOR_8x8; - } - - if(infoRec->CachePixelGranularity < 0) { - switch(pScrn->bitsPerPixel) { - case 24: - case 8: infoRec->CachePixelGranularity = 4; break; - case 16: infoRec->CachePixelGranularity = 2; break; - case 32: infoRec->CachePixelGranularity = 1; break; - default: break; - } - - if(BITMAP_SCANLINE_PAD == 64) - infoRec->CachePixelGranularity *= 2; - } - - xfree(options); - - if(!infoRec->CacheTile && infoRec->WritePixmapToCache) - infoRec->CacheTile = XAACacheTile; - if(!infoRec->CacheMonoStipple && infoRec->WritePixmapToCache) - infoRec->CacheMonoStipple = XAACacheMonoStipple; - if(!infoRec->CacheStipple && infoRec->WriteBitmapToCache) - infoRec->CacheStipple = XAACacheStipple; - if(!infoRec->CacheMono8x8Pattern && infoRec->WriteMono8x8PatternToCache) - infoRec->CacheMono8x8Pattern = XAACacheMono8x8Pattern; - if(!infoRec->CacheColor8x8Pattern && infoRec->WriteColor8x8PatternToCache) - infoRec->CacheColor8x8Pattern = XAACacheColor8x8Pattern; - - if((infoRec->Flags & PIXMAP_CACHE) && !infoRec->InitPixmapCache) { - infoRec->InitPixmapCache = XAAInitPixmapCache; - infoRec->ClosePixmapCache = XAAClosePixmapCache; - } - - return TRUE; -} +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xf86fbman.h" +#include "servermd.h" + +/* + * XAA Config options + */ + +typedef enum { + XAAOPT_SCREEN_TO_SCREEN_COPY, + XAAOPT_SOLID_FILL_RECT, + XAAOPT_SOLID_FILL_TRAP, + XAAOPT_SOLID_TWO_POINT_LINE, + XAAOPT_SOLID_BRESENHAM_LINE, + XAAOPT_SOLID_HORVERT_LINE, + XAAOPT_DASHED_TWO_POINT_LINE, + XAAOPT_DASHED_BRESENHAM_LINE, + XAAOPT_MONO_8x8_PATTERN_FILL_RECT, + XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, + XAAOPT_COL_8x8_PATTERN_FILL_RECT, + XAAOPT_COL_8x8_PATTERN_FILL_TRAP, + XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, + XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL, + XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, + XAAOPT_IMAGE_WRITE_RECT, + XAAOPT_SCANLINE_IMAGE_WRITE_RECT, + XAAOPT_WRITE_BITMAP, + XAAOPT_WRITE_PIXMAP, + XAAOPT_PIXMAP_CACHE, + XAAOPT_OFFSCREEN_PIXMAPS, + XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE +} XAAOpts; + +static const OptionInfoRec XAAOptions[] = { + {XAAOPT_SCREEN_TO_SCREEN_COPY, "XaaNoScreenToScreenCopy", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_SOLID_FILL_RECT, "XaaNoSolidFillRect", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_SOLID_FILL_TRAP, "XaaNoSolidFillTrap", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_SOLID_TWO_POINT_LINE, "XaaNoSolidTwoPointLine", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_SOLID_BRESENHAM_LINE, "XaaNoSolidBresenhamLine", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_SOLID_HORVERT_LINE, "XaaNoSolidHorVertLine", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_DASHED_TWO_POINT_LINE, "XaaNoDashedTwoPointLine", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_DASHED_BRESENHAM_LINE, "XaaNoDashedBresenhamLine", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_MONO_8x8_PATTERN_FILL_RECT, "XaaNoMono8x8PatternFillRect", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, "XaaNoMono8x8PatternFillTrap", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_COL_8x8_PATTERN_FILL_RECT, "XaaNoColor8x8PatternFillRect", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_COL_8x8_PATTERN_FILL_TRAP, "XaaNoColor8x8PatternFillTrap", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, "XaaNoCPUToScreenColorExpandFill", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL,"XaaNoScanlineCPUToScreenColorExpandFill", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, "XaaNoScreenToScreenColorExpandFill", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_IMAGE_WRITE_RECT, "XaaNoImageWriteRect", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_SCANLINE_IMAGE_WRITE_RECT, "XaaNoScanlineImageWriteRect", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_WRITE_BITMAP, "XaaNoWriteBitmap", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_WRITE_PIXMAP, "XaaNoWritePixmap", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_PIXMAP_CACHE, "XaaNoPixmapCache", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_OFFSCREEN_PIXMAPS, "XaaNoOffscreenPixmaps", + OPTV_BOOLEAN, {0}, FALSE }, + {XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE, "XaaOffscreenPixmaps", + OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, + OPTV_NONE, {0}, FALSE } +}; + +static XF86ModuleVersionInfo xaaVersRec = +{ + "xaa", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + XAA_VERSION_MAJOR, + XAA_VERSION_MINOR, + XAA_VERSION_RELEASE, + ABI_CLASS_VIDEODRV, /* requires the video driver ABI */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_NONE, + {0,0,0,0} +}; + +_X_EXPORT XF86ModuleData xaaModuleData = { &xaaVersRec, NULL, NULL }; + +Bool +XAAInitAccel(ScreenPtr pScreen, XAAInfoRecPtr infoRec) +{ + int index = pScreen->myNum; + ScrnInfoPtr pScrn = xf86Screens[index]; + Bool HaveScreenToScreenCopy = FALSE; + Bool HaveColorExpansion = FALSE; + Bool HaveScanlineColorExpansion = FALSE; + Bool HaveSolidFillRect = FALSE; + Bool HaveMono8x8PatternFillRect = FALSE; + Bool HaveColor8x8PatternFillRect = FALSE; + Bool HaveSolidFillTrap = FALSE; + Bool HaveMono8x8PatternFillTrap = FALSE; + Bool HaveColor8x8PatternFillTrap = FALSE; + Bool HaveSolidTwoPointLine = FALSE; + Bool HaveSolidBresenhamLine = FALSE; + Bool HaveSolidHorVertLine = FALSE; + Bool HaveDashedTwoPointLine = FALSE; + Bool HaveDashedBresenhamLine = FALSE; + Bool HaveImageWriteRect = FALSE; + Bool HaveScanlineImageWriteRect = FALSE; + Bool HaveScreenToScreenColorExpandFill = FALSE; + OptionInfoPtr options; + int is_shared = 0; + int i; + + options = xnfalloc(sizeof(XAAOptions)); + (void)memcpy(options, XAAOptions, sizeof(XAAOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); + + infoRec->pScrn = pScrn; + infoRec->NeedToSync = FALSE; + + /* must have a Sync function */ + if(!infoRec->Sync) return FALSE; + for(i = 0; i < pScrn->numEntities; i++) { + if(xf86IsEntityShared(pScrn->entityList[i])) is_shared = 1; + } + + /* If this PCI entity has IS_SHARED_ACCEL set in entityProp + * then a RestoreAccelState function is required + */ + if(!infoRec->RestoreAccelState && is_shared) return FALSE; + + if(infoRec->RestoreAccelState) { + if(!XAAInitStateWrap(pScreen, infoRec)) return FALSE; + } + + if (serverGeneration == 1) + xf86DrvMsg(index, X_INFO, + "Using XFree86 Acceleration Architecture (XAA)\n"); + + + /************** Low Level *************/ + + if(!infoRec->SetClippingRectangle || !infoRec->DisableClipping) { + infoRec->ClippingFlags = 0; + infoRec->SetClippingRectangle = NULL; + infoRec->DisableClipping = NULL; + } + + /**** CopyArea ****/ + + if(infoRec->SetupForScreenToScreenCopy && + infoRec->SubsequentScreenToScreenCopy && + !xf86ReturnOptValBool(options, XAAOPT_SCREEN_TO_SCREEN_COPY, FALSE)) { + HaveScreenToScreenCopy = TRUE; + } else { + infoRec->ScreenToScreenCopyFlags = 0; + infoRec->SetupForScreenToScreenCopy = NULL; + infoRec->SubsequentScreenToScreenCopy = NULL; + } + + /**** Solid Filled Rects ****/ + + if(infoRec->SetupForSolidFill && infoRec->SubsequentSolidFillRect && + !xf86ReturnOptValBool(options, XAAOPT_SOLID_FILL_RECT, FALSE)) { + HaveSolidFillRect = TRUE; + if(infoRec->SubsequentSolidFillTrap && + !xf86ReturnOptValBool(options, XAAOPT_SOLID_FILL_TRAP, FALSE)) + HaveSolidFillTrap = TRUE; + else + infoRec->SubsequentSolidFillTrap = NULL; + } else { + infoRec->SolidFillFlags = 0; + infoRec->SetupForSolidFill = NULL; + infoRec->SubsequentSolidFillRect = NULL; + infoRec->SubsequentSolidFillTrap = NULL; + } + + /**** Solid lines ****/ + + if(infoRec->SetupForSolidLine) { + if(infoRec->SubsequentSolidTwoPointLine && + !xf86ReturnOptValBool(options, + XAAOPT_SOLID_TWO_POINT_LINE, FALSE)) + HaveSolidTwoPointLine = TRUE; + if(infoRec->SubsequentSolidBresenhamLine && + !xf86ReturnOptValBool(options, XAAOPT_SOLID_BRESENHAM_LINE, FALSE)) { + HaveSolidBresenhamLine = TRUE; + + if(infoRec->SolidBresenhamLineErrorTermBits) + infoRec->SolidBresenhamLineErrorTermBits = + ~((1 << infoRec->SolidBresenhamLineErrorTermBits) - 1); + } + + if(infoRec->SubsequentSolidHorVertLine && + !xf86ReturnOptValBool(options, + XAAOPT_SOLID_HORVERT_LINE, FALSE)) + HaveSolidHorVertLine = TRUE; + else if(HaveSolidTwoPointLine) { + infoRec->SubsequentSolidHorVertLine = + XAASolidHorVertLineAsTwoPoint; + HaveSolidHorVertLine = TRUE; + } else if(HaveSolidBresenhamLine) { + infoRec->SubsequentSolidHorVertLine = + XAASolidHorVertLineAsBresenham; + HaveSolidHorVertLine = TRUE; + } + } + + /* XXX Should this also check for XAAOPT_SOLID_HORVERT_LINE? */ + if (!HaveSolidTwoPointLine && + !HaveSolidBresenhamLine && + !HaveSolidHorVertLine && + HaveSolidFillRect) { + infoRec->SetupForSolidLine = infoRec->SetupForSolidFill; + infoRec->SubsequentSolidHorVertLine = XAASolidHorVertLineAsRects; + infoRec->SolidLineFlags = infoRec->SolidFillFlags; + HaveSolidHorVertLine = TRUE; + } + + if (!HaveSolidTwoPointLine) + infoRec->SubsequentSolidTwoPointLine = NULL; + if (!HaveSolidBresenhamLine) + infoRec->SubsequentSolidBresenhamLine = NULL; + if (!HaveSolidHorVertLine) + infoRec->SubsequentSolidHorVertLine = NULL; + + /* Disable all if nothing left over */ + if (!HaveSolidTwoPointLine && + !HaveSolidBresenhamLine && + !HaveSolidHorVertLine) { + infoRec->SolidLineFlags = 0; + infoRec->SetupForSolidLine = NULL; + } + + /**** 8x8 Mono Pattern Filled Rects ****/ + + if(infoRec->SetupForMono8x8PatternFill && + infoRec->SubsequentMono8x8PatternFillRect && + !xf86ReturnOptValBool(options, + XAAOPT_MONO_8x8_PATTERN_FILL_RECT, + FALSE)) { + HaveMono8x8PatternFillRect = TRUE; + if(infoRec->SubsequentMono8x8PatternFillTrap && + !xf86ReturnOptValBool(options, + XAAOPT_MONO_8x8_PATTERN_FILL_TRAP, + FALSE)) + HaveMono8x8PatternFillTrap = TRUE; + + if(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_BITS) { + infoRec->CanDoMono8x8 = TRUE; + } else { /* others require caching */ + int min_pitch; + infoRec->PixmapCacheFlags |= CACHE_MONO_8x8; + + switch(pScrn->bitsPerPixel) { + case 32: min_pitch = 2; break; + case 24: min_pitch = 3; break; + case 16: min_pitch = 4; break; + default: min_pitch = 8; break; + } + + if(min_pitch > infoRec->MonoPatternPitch) + infoRec->MonoPatternPitch = min_pitch; + + if(infoRec->Mono8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + if(!infoRec->CacheWidthMono8x8Pattern || + !infoRec->CacheHeightMono8x8Pattern) { + infoRec->CacheWidthMono8x8Pattern = + infoRec->MonoPatternPitch; + infoRec->CacheHeightMono8x8Pattern = 1; + } + } else { + int numPerLine = 128/infoRec->MonoPatternPitch; + + if(!infoRec->CacheWidthMono8x8Pattern || + !infoRec->CacheHeightMono8x8Pattern) { + infoRec->CacheWidthMono8x8Pattern = + numPerLine * infoRec->MonoPatternPitch; + infoRec->CacheHeightMono8x8Pattern = + (64 + numPerLine - 1)/numPerLine; + } + } + } + } else { + infoRec->Mono8x8PatternFillFlags = 0; + infoRec->SetupForMono8x8PatternFill = NULL; + infoRec->SubsequentMono8x8PatternFillRect = NULL; + } + + /**** Dashed lines ****/ + + if(infoRec->SetupForDashedLine && infoRec->DashPatternMaxLength) { + if(infoRec->SubsequentDashedTwoPointLine && + !xf86ReturnOptValBool(options, XAAOPT_DASHED_TWO_POINT_LINE, + FALSE)) + HaveDashedTwoPointLine = TRUE; + if(infoRec->SubsequentDashedBresenhamLine && + !xf86ReturnOptValBool(options, XAAOPT_DASHED_BRESENHAM_LINE, + FALSE)) { + HaveDashedBresenhamLine = TRUE; + + if(infoRec->DashedBresenhamLineErrorTermBits) + infoRec->DashedBresenhamLineErrorTermBits = + ~((1 << infoRec->DashedBresenhamLineErrorTermBits) - 1); + } + } + + if (!HaveDashedTwoPointLine) + infoRec->SubsequentDashedTwoPointLine = NULL; + if (!HaveDashedBresenhamLine) + infoRec->SubsequentDashedBresenhamLine = NULL; + + /* Disable all if nothing left over */ + if (!HaveDashedTwoPointLine && !HaveDashedBresenhamLine) { + infoRec->DashedLineFlags = 0; + infoRec->SetupForDashedLine = NULL; + } + + /**** 8x8 Color Pattern Filled Rects ****/ + + if(infoRec->SetupForColor8x8PatternFill && + infoRec->SubsequentColor8x8PatternFillRect && + !xf86ReturnOptValBool(options, XAAOPT_COL_8x8_PATTERN_FILL_RECT, FALSE)) { + HaveColor8x8PatternFillRect = TRUE; + if(infoRec->SubsequentColor8x8PatternFillTrap && + !xf86ReturnOptValBool(options, XAAOPT_COL_8x8_PATTERN_FILL_TRAP, + FALSE)) + HaveColor8x8PatternFillTrap = TRUE; + else + infoRec->SubsequentColor8x8PatternFillTrap = NULL; + + infoRec->PixmapCacheFlags |= CACHE_COLOR_8x8; + + if(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + if(!infoRec->CacheWidthColor8x8Pattern || + !infoRec->CacheHeightColor8x8Pattern) { + infoRec->CacheWidthColor8x8Pattern = 64; + infoRec->CacheHeightColor8x8Pattern = 1; + } + } else { + if(!infoRec->CacheWidthColor8x8Pattern || + !infoRec->CacheHeightColor8x8Pattern) { + infoRec->CacheWidthColor8x8Pattern = 128; + infoRec->CacheHeightColor8x8Pattern = 8; + } + } + } else { + infoRec->Color8x8PatternFillFlags = 0; + infoRec->SetupForColor8x8PatternFill = NULL; + infoRec->SubsequentColor8x8PatternFillRect = NULL; + infoRec->SubsequentColor8x8PatternFillTrap = NULL; + } + + /**** Color Expansion ****/ + + if(infoRec->SetupForCPUToScreenColorExpandFill && + infoRec->ColorExpandBase && + infoRec->SubsequentCPUToScreenColorExpandFill && + !xf86ReturnOptValBool(options, XAAOPT_CPU_TO_SCREEN_COL_EXP_FILL, + FALSE)) { + int dwordsNeeded = pScrn->virtualX; + + infoRec->ColorExpandRange >>= 2; /* convert to DWORDS */ + HaveColorExpansion = TRUE; + + if(infoRec->CPUToScreenColorExpandFillFlags & + LEFT_EDGE_CLIPPING_NEGATIVE_X) + dwordsNeeded += 31; + dwordsNeeded = (dwordsNeeded + 31) >> 5; + if(dwordsNeeded > infoRec->ColorExpandRange) + infoRec->CPUToScreenColorExpandFillFlags |= CPU_TRANSFER_BASE_FIXED; + } else { + infoRec->CPUToScreenColorExpandFillFlags = 0; + infoRec->SetupForCPUToScreenColorExpandFill = NULL; + infoRec->SubsequentCPUToScreenColorExpandFill = NULL; + } + + /**** Scanline Color Expansion ****/ + + if(infoRec->SetupForScanlineCPUToScreenColorExpandFill && + infoRec->SubsequentScanlineCPUToScreenColorExpandFill && + infoRec->SubsequentColorExpandScanline && + infoRec->ScanlineColorExpandBuffers && + (infoRec->NumScanlineColorExpandBuffers > 0) && + !xf86ReturnOptValBool(options, + XAAOPT_SCANLINE_CPU_TO_SCREEN_COL_EXP_FILL, + FALSE)) { + HaveScanlineColorExpansion = TRUE; + } else { + infoRec->ScanlineCPUToScreenColorExpandFillFlags = 0; + infoRec->SetupForScanlineCPUToScreenColorExpandFill = NULL; + infoRec->SubsequentScanlineCPUToScreenColorExpandFill = NULL; + infoRec->SubsequentColorExpandScanline = NULL; + } + + /**** Screen to Screen Color Expansion ****/ + + if(infoRec->SetupForScreenToScreenColorExpandFill && + infoRec->SubsequentScreenToScreenColorExpandFill && + !xf86ReturnOptValBool(options, XAAOPT_SCREEN_TO_SCREEN_COL_EXP_FILL, + FALSE)) { + HaveScreenToScreenColorExpandFill = TRUE; + if (!infoRec->CacheColorExpandDensity) + infoRec->CacheColorExpandDensity = 1; + } else { + infoRec->ScreenToScreenColorExpandFillFlags = 0; + infoRec->SetupForScreenToScreenColorExpandFill = NULL; + infoRec->SubsequentScreenToScreenColorExpandFill = NULL; + } + + /**** Image Writes ****/ + + if(infoRec->SetupForImageWrite && infoRec->ImageWriteBase && + infoRec->SubsequentImageWriteRect && + !xf86ReturnOptValBool(options, XAAOPT_IMAGE_WRITE_RECT, FALSE)) { + + infoRec->ImageWriteRange >>= 2; /* convert to DWORDS */ + if(infoRec->ImageWriteFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->ImageWriteRange = 0; + HaveImageWriteRect = TRUE; + } else { + infoRec->ImageWriteFlags = 0; + infoRec->SetupForImageWrite = NULL; + infoRec->SubsequentImageWriteRect = NULL; + } + + /**** Scanline Image Writes ****/ + + if(infoRec->SetupForScanlineImageWrite && + infoRec->SubsequentScanlineImageWriteRect && + infoRec->SubsequentImageWriteScanline && + infoRec->ScanlineImageWriteBuffers && + (infoRec->NumScanlineImageWriteBuffers > 0) && + !xf86ReturnOptValBool(options, XAAOPT_SCANLINE_IMAGE_WRITE_RECT, + FALSE)) { + HaveScanlineImageWriteRect = TRUE; + } else { + infoRec->ScanlineImageWriteFlags = 0; + infoRec->SetupForScanlineImageWrite = NULL; + infoRec->SubsequentScanlineImageWriteRect = NULL; + infoRec->SubsequentImageWriteScanline = NULL; + } + +#ifndef __i386__ + /* XAA makes some unaligned accesses when clipping is not available */ +# define CLIP_FLAGS (LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X) + if(HaveImageWriteRect && + ((infoRec->ImageWriteFlags & CLIP_FLAGS) != CLIP_FLAGS)) + { + HaveImageWriteRect = FALSE; + } + if(HaveScanlineImageWriteRect && + ((infoRec->ScanlineImageWriteFlags & CLIP_FLAGS) != CLIP_FLAGS)) + { + HaveScanlineImageWriteRect = FALSE; + } +#endif + + if (serverGeneration == 1) { + if(HaveScreenToScreenCopy) + xf86ErrorF("\tScreen to screen bit blits\n"); + if(HaveSolidFillRect) + xf86ErrorF("\tSolid filled rectangles\n"); + if(HaveSolidFillTrap) + xf86ErrorF("\tSolid filled trapezoids\n"); + if(HaveMono8x8PatternFillRect) + xf86ErrorF("\t8x8 mono pattern filled rectangles\n"); + if(HaveMono8x8PatternFillTrap) + xf86ErrorF("\t8x8 mono pattern filled trapezoids\n"); + if(HaveColor8x8PatternFillRect) + xf86ErrorF("\t8x8 color pattern filled rectangles\n"); + if(HaveColor8x8PatternFillTrap) + xf86ErrorF("\t8x8 color pattern filled trapezoids\n"); + + if(HaveColorExpansion) + xf86ErrorF("\tCPU to Screen color expansion\n"); + else if(HaveScanlineColorExpansion) + xf86ErrorF("\tIndirect CPU to Screen color expansion\n"); + + if(HaveScreenToScreenColorExpandFill) + xf86ErrorF("\tScreen to Screen color expansion\n"); + + if(HaveSolidTwoPointLine || HaveSolidBresenhamLine) + xf86ErrorF("\tSolid Lines\n"); + else if(HaveSolidHorVertLine) + xf86ErrorF("\tSolid Horizontal and Vertical Lines\n"); + + if(HaveDashedTwoPointLine || HaveDashedBresenhamLine) + xf86ErrorF("\tDashed Lines\n"); + + if(HaveImageWriteRect) + xf86ErrorF("\tImage Writes\n"); + else if(HaveScanlineImageWriteRect) + xf86ErrorF("\tScanline Image Writes\n"); + + } + +#define XAAMSG(s) do { if (serverGeneration == 1) xf86ErrorF(s); } while (0) + + if((infoRec->Flags & OFFSCREEN_PIXMAPS) && HaveScreenToScreenCopy && + xf86ReturnOptValBool(options, + XAAOPT_HAS_DUMB_INVERTED_OPTION_SENSE, + FALSE)) + { + XAAMSG("\tOffscreen Pixmaps\n"); + } else { + infoRec->Flags &= ~OFFSCREEN_PIXMAPS; + } + + + /************** Mid Level *************/ + + /**** ScreenToScreenBitBlt ****/ + + if(infoRec->ScreenToScreenBitBlt) { + XAAMSG("\tDriver provided ScreenToScreenBitBlt replacement\n"); + } else if(HaveScreenToScreenCopy) { + infoRec->ScreenToScreenBitBlt = XAAScreenToScreenBitBlt; + infoRec->ScreenToScreenBitBltFlags = infoRec->ScreenToScreenCopyFlags; + } + + /**** FillSolidRects ****/ + + if(infoRec->FillSolidRects) { + XAAMSG("\tDriver provided FillSolidRects replacement\n"); + } else if(HaveSolidFillRect) { + infoRec->FillSolidRects = XAAFillSolidRects; + infoRec->FillSolidRectsFlags = infoRec->SolidFillFlags; + } + + /**** FillSolidSpans ****/ + + if(infoRec->FillSolidSpans) { + XAAMSG("\tDriver provided FillSolidSpans replacement\n"); + } else if(HaveSolidFillRect) { + infoRec->FillSolidSpans = XAAFillSolidSpans; + infoRec->FillSolidSpansFlags = infoRec->SolidFillFlags; + } + + /**** FillMono8x8PatternRects ****/ + + if(infoRec->FillMono8x8PatternRects) { + XAAMSG("\tDriver provided FillMono8x8PatternRects replacement\n"); + } else if(HaveMono8x8PatternFillRect) { + infoRec->FillMono8x8PatternRects = + (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? + XAAFillMono8x8PatternRectsScreenOrigin : + XAAFillMono8x8PatternRects; + + infoRec->FillMono8x8PatternRectsFlags = + infoRec->Mono8x8PatternFillFlags; + } + + /**** FillMono8x8PatternSpans ****/ + + if(infoRec->FillMono8x8PatternSpans) { + XAAMSG("\tDriver provided FillMono8x8PatternSpans replacement\n"); + } else if(HaveMono8x8PatternFillRect) { + infoRec->FillMono8x8PatternSpans = + (infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? + XAAFillMono8x8PatternSpansScreenOrigin: + XAAFillMono8x8PatternSpans; + + infoRec->FillMono8x8PatternSpansFlags = + infoRec->Mono8x8PatternFillFlags; + } + + /**** FillColor8x8Rects ****/ + + if(infoRec->FillColor8x8PatternRects) { + XAAMSG("\tDriver provided FillColor8x8PatternRects replacement\n"); + } else if(HaveColor8x8PatternFillRect) { + infoRec->FillColor8x8PatternRects = + (infoRec->Color8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? + XAAFillColor8x8PatternRectsScreenOrigin : + XAAFillColor8x8PatternRects; + + infoRec->FillColor8x8PatternRectsFlags = + infoRec->Color8x8PatternFillFlags; + } + + /**** FillColor8x8Spans ****/ + + if(infoRec->FillColor8x8PatternSpans) { + XAAMSG("\tDriver provided FillColor8x8PatternSpans replacement\n"); + } else if(HaveColor8x8PatternFillRect) { + infoRec->FillColor8x8PatternSpans = + (infoRec->Color8x8PatternFillFlags & HARDWARE_PATTERN_SCREEN_ORIGIN) ? + XAAFillColor8x8PatternSpansScreenOrigin: + XAAFillColor8x8PatternSpans; + + infoRec->FillColor8x8PatternSpansFlags = + infoRec->Color8x8PatternFillFlags; + } + + /**** FillCacheBltRects ****/ + + if(infoRec->FillCacheBltRects) { + XAAMSG("\tDriver provided FillCacheBltRects replacement\n"); + } else if(HaveScreenToScreenCopy) { + infoRec->FillCacheBltRects = XAAFillCacheBltRects; + infoRec->FillCacheBltRectsFlags = infoRec->ScreenToScreenCopyFlags; + } + + /**** FillCacheBltSpans ****/ + + if(infoRec->FillCacheBltSpans) { + XAAMSG("\tDriver provided FillCacheBltSpans replacement\n"); + } else if(HaveScreenToScreenCopy) { + infoRec->FillCacheBltSpans = XAAFillCacheBltSpans; + infoRec->FillCacheBltSpansFlags = infoRec->ScreenToScreenCopyFlags; + } + + /**** FillCacheExpandRects ****/ + + if(infoRec->FillCacheExpandRects) { + XAAMSG("\tDriver provided FillCacheExpandRects replacement\n"); + } else if(HaveScreenToScreenColorExpandFill) { + infoRec->FillCacheExpandRects = XAAFillCacheExpandRects; + infoRec->FillCacheExpandRectsFlags = + infoRec->ScreenToScreenColorExpandFillFlags; + } + + /**** FillCacheExpandSpans ****/ + + if(infoRec->FillCacheExpandSpans) { + XAAMSG("\tDriver provided FillCacheExpandSpans replacement\n"); + } else if(HaveScreenToScreenColorExpandFill) { + infoRec->FillCacheExpandSpans = XAAFillCacheExpandSpans; + infoRec->FillCacheExpandSpansFlags = + infoRec->ScreenToScreenColorExpandFillFlags; + } + + /**** FillColorExpandRects ****/ + + if(infoRec->FillColorExpandRects) { + XAAMSG("\tDriver provided FillColorExpandRects replacement\n"); + } else if(HaveColorExpansion) { + if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { + if(infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandRects = + XAAFillColorExpandRects3MSBFirstFixedBase; + else + infoRec->FillColorExpandRects = + XAAFillColorExpandRects3MSBFirst; + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandRects = + XAAFillColorExpandRects3LSBFirstFixedBase; + else + infoRec->FillColorExpandRects = + XAAFillColorExpandRects3LSBFirst; + } + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandRects = + XAAFillColorExpandRectsMSBFirstFixedBase; + else + infoRec->FillColorExpandRects = + XAAFillColorExpandRectsMSBFirst; + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandRects = + XAAFillColorExpandRectsLSBFirstFixedBase; + else + infoRec->FillColorExpandRects = + XAAFillColorExpandRectsLSBFirst; + } + } + infoRec->FillColorExpandRectsFlags = + infoRec->CPUToScreenColorExpandFillFlags; + } else if(HaveScanlineColorExpansion) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + TRIPLE_BITS_24BPP) { + if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->FillColorExpandRects = + XAAFillScanlineColorExpandRects3MSBFirst; + else + infoRec->FillColorExpandRects = + XAAFillScanlineColorExpandRects3LSBFirst; + } else { + if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->FillColorExpandRects = + XAAFillScanlineColorExpandRectsMSBFirst; + else + infoRec->FillColorExpandRects = + XAAFillScanlineColorExpandRectsLSBFirst; + } + infoRec->FillColorExpandRectsFlags = + infoRec->ScanlineCPUToScreenColorExpandFillFlags; + } + + /**** FillColorExpandSpans ****/ + + if(infoRec->FillColorExpandSpans) { + XAAMSG("\tDriver provided FillColorExpandSpans replacement\n"); + } else if(HaveColorExpansion) { + if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { + if(infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpans3MSBFirstFixedBase; + else + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpans3MSBFirst; + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpans3LSBFirstFixedBase; + else + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpans3LSBFirst; + } + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpansMSBFirstFixedBase; + else + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpansMSBFirst; + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpansLSBFirstFixedBase; + else + infoRec->FillColorExpandSpans = + XAAFillColorExpandSpansLSBFirst; + } + } + infoRec->FillColorExpandSpansFlags = + infoRec->CPUToScreenColorExpandFillFlags; + } else if(HaveScanlineColorExpansion) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + TRIPLE_BITS_24BPP) { + if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->FillColorExpandSpans = + XAAFillScanlineColorExpandSpans3MSBFirst; + else + infoRec->FillColorExpandSpans = + XAAFillScanlineColorExpandSpans3LSBFirst; + } else { + if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->FillColorExpandSpans = + XAAFillScanlineColorExpandSpansMSBFirst; + else + infoRec->FillColorExpandSpans = + XAAFillScanlineColorExpandSpansLSBFirst; + } + infoRec->FillColorExpandSpansFlags = + infoRec->ScanlineCPUToScreenColorExpandFillFlags; + } + + /**** FillImageWriteRects ****/ + + if(infoRec->FillImageWriteRects) { + XAAMSG("\tDriver provided FillImageWriteRects replacement\n"); + } else if(HaveImageWriteRect && + (infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && + (infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) { + infoRec->FillImageWriteRects = XAAFillImageWriteRects; + infoRec->FillImageWriteRectsFlags = infoRec->ImageWriteFlags; + } + + /**** WriteBitmap ****/ + + if(infoRec->WriteBitmap && + !xf86ReturnOptValBool(options, XAAOPT_WRITE_BITMAP, FALSE)) { + XAAMSG("\tDriver provided WriteBitmap replacement\n"); + } else if(HaveColorExpansion) { + if (infoRec->CPUToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) { + if(infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->WriteBitmap = + XAAWriteBitmapColorExpand3MSBFirstFixedBase; + else + infoRec->WriteBitmap = XAAWriteBitmapColorExpand3MSBFirst; + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->WriteBitmap = + XAAWriteBitmapColorExpand3LSBFirstFixedBase; + else + infoRec->WriteBitmap = XAAWriteBitmapColorExpand3LSBFirst; + } + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->WriteBitmap = + XAAWriteBitmapColorExpandMSBFirstFixedBase; + else + infoRec->WriteBitmap = XAAWriteBitmapColorExpandMSBFirst; + } else { + if(infoRec->CPUToScreenColorExpandFillFlags & + CPU_TRANSFER_BASE_FIXED) + infoRec->WriteBitmap = + XAAWriteBitmapColorExpandLSBFirstFixedBase; + else + infoRec->WriteBitmap = XAAWriteBitmapColorExpandLSBFirst; + } + } + infoRec->WriteBitmapFlags = infoRec->CPUToScreenColorExpandFillFlags; + } else if(HaveScanlineColorExpansion) { + if (infoRec->ScanlineCPUToScreenColorExpandFillFlags & + TRIPLE_BITS_24BPP) { + if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->WriteBitmap = + XAAWriteBitmapScanlineColorExpand3MSBFirst; + else + infoRec->WriteBitmap = + XAAWriteBitmapScanlineColorExpand3LSBFirst; + } else { + if(infoRec->ScanlineCPUToScreenColorExpandFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->WriteBitmap = + XAAWriteBitmapScanlineColorExpandMSBFirst; + else + infoRec->WriteBitmap = + XAAWriteBitmapScanlineColorExpandLSBFirst; + } + infoRec->WriteBitmapFlags = + infoRec->ScanlineCPUToScreenColorExpandFillFlags; + } else + infoRec->WriteBitmap = NULL; + + /**** TE Glyphs ****/ + + if (infoRec->TEGlyphRenderer) { + XAAMSG("\tDriver provided TEGlyphRenderer replacement\n"); + } else if (HaveColorExpansion) { + infoRec->TEGlyphRendererFlags = + infoRec->CPUToScreenColorExpandFillFlags; + + if (infoRec->TEGlyphRendererFlags & TRIPLE_BITS_24BPP) { + if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->TEGlyphRenderer = + XAATEGlyphRenderer3MSBFirstFixedBase; + else + infoRec->TEGlyphRenderer = XAATEGlyphRenderer3MSBFirst; + } else { + if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->TEGlyphRenderer = + XAATEGlyphRenderer3LSBFirstFixedBase; + else + infoRec->TEGlyphRenderer = XAATEGlyphRenderer3LSBFirst; + } + + if (!HaveSolidFillRect && + (infoRec->TEGlyphRendererFlags & RGB_EQUAL)) { + infoRec->TEGlyphRendererFlags &= ~RGB_EQUAL; + XAAMSG("WARNING: TEGlyphRenderer cannot support RGB_EQUAL" + " without solid fills\n"); + } + } else { + if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->TEGlyphRenderer = + XAATEGlyphRendererMSBFirstFixedBase; + else + infoRec->TEGlyphRenderer = XAATEGlyphRendererMSBFirst; + } else { + if (infoRec->TEGlyphRendererFlags & CPU_TRANSFER_BASE_FIXED) + infoRec->TEGlyphRenderer = + XAATEGlyphRendererLSBFirstFixedBase; + else + infoRec->TEGlyphRenderer = XAATEGlyphRendererLSBFirst; + } + } + + if (!HaveSolidFillRect && + (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + infoRec->TEGlyphRendererFlags &= ~TRANSPARENCY_ONLY; + XAAMSG("WARNING: TEGlyphRenderer cannot support TRANPARENCY_ONLY" + " without solid fills\n"); + } + + } else if (HaveScanlineColorExpansion) { + infoRec->TEGlyphRendererFlags = + infoRec->ScanlineCPUToScreenColorExpandFillFlags; + + if (infoRec->TEGlyphRendererFlags & TRIPLE_BITS_24BPP) { + if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->TEGlyphRenderer = XAATEGlyphRendererScanline3MSBFirst; + else + infoRec->TEGlyphRenderer = XAATEGlyphRendererScanline3LSBFirst; + + if (!HaveSolidFillRect && + (infoRec->TEGlyphRendererFlags & RGB_EQUAL)) { + infoRec->TEGlyphRendererFlags &= ~RGB_EQUAL; + XAAMSG("WARNING: TEGlyphRenderer cannot support RGB_EQUAL" + " without solid fills\n"); + } + } else { + if (infoRec->TEGlyphRendererFlags & BIT_ORDER_IN_BYTE_MSBFIRST) + infoRec->TEGlyphRenderer = XAATEGlyphRendererScanlineMSBFirst; + else + infoRec->TEGlyphRenderer = XAATEGlyphRendererScanlineLSBFirst; + } + + if (!HaveSolidFillRect && + (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + infoRec->TEGlyphRendererFlags &= ~TRANSPARENCY_ONLY; + XAAMSG("WARNING: TEGlyphRenderer cannot support TRANPARENCY_ONLY" + " without solid fills\n"); + } + } + + /**** NonTE Glyphs ****/ + + if(infoRec->NonTEGlyphRenderer) { + XAAMSG("\tDriver provided NonTEGlyphRenderer replacement\n"); + } else if(infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) { + infoRec->NonTEGlyphRenderer = XAANonTEGlyphRenderer; + infoRec->NonTEGlyphRendererFlags = infoRec->WriteBitmapFlags; + } + + /**** WritePixmap ****/ + + if(infoRec->WritePixmap && + !xf86ReturnOptValBool(options, XAAOPT_WRITE_PIXMAP, FALSE)) { + XAAMSG("\tDriver provided WritePixmap replacement\n"); + } else if(HaveImageWriteRect) { + infoRec->WritePixmap = XAAWritePixmap; + infoRec->WritePixmapFlags = + infoRec->ImageWriteFlags | CONVERT_32BPP_TO_24BPP; + } else if(HaveScanlineImageWriteRect) { + infoRec->WritePixmap = XAAWritePixmapScanline; + infoRec->WritePixmapFlags = infoRec->ScanlineImageWriteFlags; + } else + infoRec->WritePixmap = NULL; + + /**** ReadPixmap ****/ + + if(infoRec->ReadPixmap) { + XAAMSG("\tDriver provided ReadPixmap replacement\n"); + } + + + /************** GC Level *************/ + + /**** CopyArea ****/ + + if(infoRec->CopyArea) { + XAAMSG("\tDriver provided GC level CopyArea replacement\n"); + } else if(infoRec->ScreenToScreenBitBlt) { + infoRec->CopyArea = XAACopyArea; + infoRec->CopyAreaFlags = infoRec->ScreenToScreenBitBltFlags; + + /* most GC level primitives use one mid-level primitive so + the GC level primitive gets the mid-level primitive flag + and we use that at GC validation time. But CopyArea uses + more than one mid-level primitive so we have to essentially + do a GC validation every time that primitive is used. + The CopyAreaFlags would only be used for filtering out the + common denominators. Here we assume that if you don't do + ScreenToScreenBitBlt you aren't going to do the others. + We also assume that ScreenToScreenBitBlt has the least + restrictions. */ + } + + if(infoRec->CopyPlane) { + XAAMSG("\tDriver provided GC level CopyPlane replacement\n"); + } else if(infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) { + infoRec->CopyPlane = XAACopyPlaneColorExpansion; + infoRec->CopyPlaneFlags = infoRec->WriteBitmapFlags; + } + + if(infoRec->PushPixelsSolid) { + XAAMSG("\tDriver provided GC level PushPixelsSolid replacement\n"); + } else if(infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) { + infoRec->PushPixelsSolid = XAAPushPixelsSolidColorExpansion; + infoRec->PushPixelsFlags = infoRec->WriteBitmapFlags; + } + + if(infoRec->FillSolidRects) { + if(!infoRec->PolyFillRectSolid) { + infoRec->PolyFillRectSolid = XAAPolyFillRect; + infoRec->PolyFillRectSolidFlags = infoRec->FillSolidRectsFlags; + } + } + if(infoRec->FillSolidSpans) { + if(!infoRec->FillSpansSolid) { + infoRec->FillSpansSolid = XAAFillSpans; + infoRec->FillSpansSolidFlags = infoRec->FillSolidSpansFlags; + } + } + + if(infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || + infoRec->FillCacheBltRects || infoRec->FillColorExpandRects || + infoRec->FillCacheExpandRects) { + if(!infoRec->PolyFillRectStippled) { + + infoRec->PolyFillRectStippled = XAAPolyFillRect; + infoRec->PolyFillRectStippledFlags = 0; + } + } + + if(infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || + infoRec->FillCacheBltSpans || infoRec->FillColorExpandSpans || + infoRec->FillCacheExpandSpans) { + if(!infoRec->FillSpansStippled) { + + infoRec->FillSpansStippled = XAAFillSpans; + infoRec->FillSpansStippledFlags = 0; + } + } + + if(infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || + infoRec->FillCacheBltRects || infoRec->FillColorExpandRects || + infoRec->FillCacheExpandRects) { + if(!infoRec->PolyFillRectOpaqueStippled) { + + infoRec->PolyFillRectOpaqueStippled = XAAPolyFillRect; + infoRec->PolyFillRectOpaqueStippledFlags = 0; + } + } + + if(infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || + infoRec->FillCacheBltSpans || infoRec->FillColorExpandSpans || + infoRec->FillCacheExpandSpans) { + if(!infoRec->FillSpansOpaqueStippled) { + + infoRec->FillSpansOpaqueStippled = XAAFillSpans; + infoRec->FillSpansOpaqueStippledFlags = 0; + } + } + + if(infoRec->FillMono8x8PatternRects || infoRec->FillColor8x8PatternRects || + infoRec->FillCacheBltRects || infoRec->FillImageWriteRects) { + if(!infoRec->PolyFillRectTiled) { + + infoRec->PolyFillRectTiled = XAAPolyFillRect; + infoRec->PolyFillRectTiledFlags = 0; + } + } + + if(infoRec->FillMono8x8PatternSpans || infoRec->FillColor8x8PatternSpans || + infoRec->FillCacheBltSpans) { + if(!infoRec->FillSpansTiled) { + + infoRec->FillSpansTiled = XAAFillSpans; + infoRec->FillSpansTiledFlags = 0; + } + } + + if(infoRec->TEGlyphRenderer && + !(infoRec->TEGlyphRendererFlags & NO_TRANSPARENCY)) { + + if(!infoRec->PolyText8TE) { + infoRec->PolyText8TE = XAAPolyText8TEColorExpansion; + infoRec->PolyText8TEFlags = infoRec->TEGlyphRendererFlags; + } + + if(!infoRec->PolyText16TE) { + infoRec->PolyText16TE = XAAPolyText16TEColorExpansion; + infoRec->PolyText16TEFlags = infoRec->TEGlyphRendererFlags; + } + + if(!infoRec->PolyGlyphBltTE) { + infoRec->PolyGlyphBltTE = XAAPolyGlyphBltTEColorExpansion; + infoRec->PolyGlyphBltTEFlags = infoRec->TEGlyphRendererFlags; + } + } + + if(infoRec->TEGlyphRenderer && + !(infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + + if(!infoRec->ImageText8TE) { + infoRec->ImageText8TE = XAAImageText8TEColorExpansion; + infoRec->ImageText8TEFlags = infoRec->TEGlyphRendererFlags; + } + + if(!infoRec->ImageText16TE) { + infoRec->ImageText16TE = XAAImageText16TEColorExpansion; + infoRec->ImageText16TEFlags = infoRec->TEGlyphRendererFlags; + } + + if(!infoRec->ImageGlyphBltTE) { + infoRec->ImageGlyphBltTE = XAAImageGlyphBltTEColorExpansion; + infoRec->ImageGlyphBltTEFlags = infoRec->TEGlyphRendererFlags; + } + } + + if(infoRec->NonTEGlyphRenderer) { + if(!infoRec->PolyText8NonTE) { + infoRec->PolyText8NonTE = XAAPolyText8NonTEColorExpansion; + infoRec->PolyText8NonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + + if(!infoRec->PolyText16NonTE) { + infoRec->PolyText16NonTE = XAAPolyText16NonTEColorExpansion; + infoRec->PolyText16NonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + if(!infoRec->PolyGlyphBltNonTE) { + infoRec->PolyGlyphBltNonTE = XAAPolyGlyphBltNonTEColorExpansion; + infoRec->PolyGlyphBltNonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + } + + if(infoRec->NonTEGlyphRenderer && HaveSolidFillRect) { + if(!infoRec->ImageText8NonTE) { + infoRec->ImageText8NonTE = XAAImageText8NonTEColorExpansion; + infoRec->ImageText8NonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + + if(!infoRec->ImageText16NonTE) { + infoRec->ImageText16NonTE = XAAImageText16NonTEColorExpansion; + infoRec->ImageText16NonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + + if(!infoRec->ImageGlyphBltNonTE) { + infoRec->ImageGlyphBltNonTE = XAAImageGlyphBltNonTEColorExpansion; + infoRec->ImageGlyphBltNonTEFlags = infoRec->NonTEGlyphRendererFlags; + } + } + + if(!infoRec->PolyRectangleThinSolid && HaveSolidHorVertLine) { + infoRec->PolyRectangleThinSolid = XAAPolyRectangleThinSolid; + infoRec->PolyRectangleThinSolidFlags = infoRec->SolidLineFlags; + } + + if(!infoRec->FillPolygonSolid && HaveSolidFillRect) { + infoRec->FillPolygonSolid = XAAFillPolygonSolid; + infoRec->FillPolygonSolidFlags = infoRec->SolidFillFlags; + } + + if(!infoRec->FillPolygonStippled && (HaveMono8x8PatternFillRect || + HaveScreenToScreenColorExpandFill || HaveScreenToScreenCopy)) { + infoRec->FillPolygonStippled = XAAFillPolygonStippled; + infoRec->FillPolygonStippledFlags = infoRec->SolidFillFlags; + } + + if(!infoRec->FillPolygonOpaqueStippled && (HaveMono8x8PatternFillRect || + HaveScreenToScreenColorExpandFill || HaveScreenToScreenCopy)) { + infoRec->FillPolygonOpaqueStippled = XAAFillPolygonStippled; + infoRec->FillPolygonOpaqueStippledFlags = infoRec->SolidFillFlags; + } + + if(!infoRec->FillPolygonTiled && (HaveMono8x8PatternFillRect || + HaveScreenToScreenColorExpandFill || HaveScreenToScreenCopy)) { + infoRec->FillPolygonTiled = XAAFillPolygonTiled; + infoRec->FillPolygonTiledFlags = infoRec->SolidFillFlags; + } + + + if(!infoRec->PolyFillArcSolid && HaveSolidFillRect) { + infoRec->PolyFillArcSolid = XAAPolyFillArcSolid; + infoRec->PolyFillArcSolidFlags = infoRec->SolidFillFlags; + } + + if(!infoRec->PolylinesWideSolid && HaveSolidFillRect) { + infoRec->PolylinesWideSolid = XAAPolylinesWideSolid; + infoRec->PolylinesWideSolidFlags = + infoRec->SolidFillFlags | GXCOPY_ONLY; + } + + if(!infoRec->PutImage && (infoRec->WritePixmap || + (infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)))) { + infoRec->PutImage = XAAPutImage; + + /* See comment for CopyArea above. But here we make fewer + assumptions. The driver can provide the PutImageFlags if + it wants too */ + } + + if(HaveSolidHorVertLine && + (HaveSolidBresenhamLine || (HaveSolidTwoPointLine && + (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_LINE)))){ + if(!infoRec->PolylinesThinSolid) { + infoRec->PolylinesThinSolid = XAAPolyLines; + infoRec->PolylinesThinSolidFlags = infoRec->SolidLineFlags; + } + if(!infoRec->PolySegmentThinSolid) { + infoRec->PolySegmentThinSolid = XAAPolySegment; + infoRec->PolySegmentThinSolidFlags = infoRec->SolidLineFlags; + } + } + + if(HaveDashedBresenhamLine || (HaveDashedTwoPointLine && + (infoRec->ClippingFlags & HARDWARE_CLIP_DASHED_LINE))){ + if(!infoRec->PolylinesThinDashed) { + infoRec->PolylinesThinDashed = XAAPolyLinesDashed; + infoRec->PolylinesThinDashedFlags = infoRec->DashedLineFlags; + } + if(!infoRec->PolySegmentThinDashed) { + infoRec->PolySegmentThinDashed = XAAPolySegmentDashed; + infoRec->PolySegmentThinDashedFlags = infoRec->DashedLineFlags; + } + } + + if(infoRec->PolylinesThinDashed || infoRec->PolySegmentThinDashed) { + if(!infoRec->ComputeDash) + infoRec->ComputeDash = XAAComputeDash; + } + + { + Bool haveTexture = infoRec->CPUToScreenTextureFormats && + infoRec->CPUToScreenTextureDstFormats && + infoRec->SetupForCPUToScreenTexture2 && + infoRec->SubsequentCPUToScreenTexture; + Bool haveAlphaTexture = infoRec->CPUToScreenAlphaTextureFormats && + infoRec->CPUToScreenAlphaTextureDstFormats && + infoRec->SetupForCPUToScreenAlphaTexture2 && + infoRec->SubsequentCPUToScreenAlphaTexture; + + if(!infoRec->Composite && (haveTexture || haveAlphaTexture)) + infoRec->Composite = XAADoComposite; + + if(!infoRec->Glyphs && infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY)) + { + infoRec->Glyphs = XAADoGlyphs; + } + } + + /************ Validation Functions **************/ + + if(!infoRec->ValidateCopyArea && infoRec->CopyArea) { + infoRec->CopyAreaMask = GCWhenForced; + if((infoRec->CopyAreaFlags & GXCOPY_ONLY) || + (infoRec->CopyAreaFlags & ROP_NEEDS_SOURCE)) + infoRec->CopyAreaMask |= GCFunction; + if(infoRec->CopyAreaFlags & NO_PLANEMASK) + infoRec->CopyAreaMask |= GCPlaneMask; + infoRec->ValidateCopyArea = XAAValidateCopyArea; + } + + if(!infoRec->ValidateCopyPlane && infoRec->CopyPlane) { + infoRec->CopyPlaneMask = GCWhenForced; + if((infoRec->CopyPlaneFlags & GXCOPY_ONLY) || + (infoRec->CopyPlaneFlags & ROP_NEEDS_SOURCE)) + infoRec->CopyPlaneMask |= GCFunction; + if(infoRec->CopyPlaneFlags & NO_PLANEMASK) + infoRec->CopyPlaneMask |= GCPlaneMask; + if(infoRec->CopyPlaneFlags & RGB_EQUAL) + infoRec->CopyPlaneMask |= GCForeground | GCBackground; + infoRec->ValidateCopyPlane = XAAValidateCopyPlane; + } + + if(!infoRec->ValidatePutImage && infoRec->PutImage) { + infoRec->PutImageMask = GCWhenForced; + if((infoRec->PutImageFlags & GXCOPY_ONLY) || + (infoRec->PutImageFlags & ROP_NEEDS_SOURCE)) + infoRec->PutImageMask |= GCFunction; + if(infoRec->PutImageFlags & NO_PLANEMASK) + infoRec->PutImageMask |= GCPlaneMask; + if(infoRec->PutImageFlags & RGB_EQUAL) + infoRec->PutImageMask |= GCForeground | GCBackground; + infoRec->ValidatePutImage = XAAValidatePutImage; + } + + + if(!infoRec->ValidatePushPixels && infoRec->PushPixelsSolid) { + infoRec->PushPixelsMask = GCFillStyle; + if((infoRec->PushPixelsFlags & GXCOPY_ONLY) || + (infoRec->PushPixelsFlags & ROP_NEEDS_SOURCE) || + (infoRec->PushPixelsFlags & TRANSPARENCY_GXCOPY_ONLY)) + infoRec->PushPixelsMask |= GCFunction; + if(infoRec->PushPixelsFlags & NO_PLANEMASK) + infoRec->PushPixelsMask |= GCPlaneMask; + if(infoRec->PushPixelsFlags & RGB_EQUAL) + infoRec->PushPixelsMask |= GCForeground; + infoRec->ValidatePushPixels = XAAValidatePushPixels; + } + + /* By default XAA assumes the FillSpans, PolyFillRects, FillPolygon + and PolyFillArcs have the same restrictions. If you supply GC + level replacements for any of these and alter this relationship + you may need to supply replacement validation routines */ + + if(!infoRec->ValidateFillSpans && + (infoRec->FillSpansSolid || infoRec->FillSpansStippled || + infoRec->FillSpansOpaqueStippled || infoRec->FillSpansTiled)) { + + int compositeFlags = infoRec->FillSpansSolidFlags | + infoRec->FillSpansStippledFlags | + infoRec->FillSpansOpaqueStippledFlags | + infoRec->FillSpansTiledFlags; + + infoRec->FillSpansMask = GCFillStyle | GCTile | GCStipple; + + if((compositeFlags & GXCOPY_ONLY) || + (compositeFlags & ROP_NEEDS_SOURCE)) + infoRec->FillSpansMask |= GCFunction; + if(compositeFlags & NO_PLANEMASK) + infoRec->FillSpansMask |= GCPlaneMask; + if(compositeFlags & RGB_EQUAL) + infoRec->FillSpansMask |= GCForeground; + infoRec->ValidateFillSpans = XAAValidateFillSpans; + } + + /* By default XAA only provides Validations for the GlyphBlt + functions and not the text higher up. This is because the + Text8/16 and GlyphBlt are linked. If you break this linkage, + you may need to have the driver supply its own Validation + routines */ + + if(!infoRec->ValidatePolyGlyphBlt && + (infoRec->PolyGlyphBltTE || infoRec->PolyGlyphBltNonTE)) { + int compositeFlags = infoRec->PolyGlyphBltTEFlags | + infoRec->PolyGlyphBltNonTEFlags; + + infoRec->PolyGlyphBltMask = GCFillStyle | GCFont; + if((compositeFlags & GXCOPY_ONLY) || + (compositeFlags & ROP_NEEDS_SOURCE) || + (infoRec->PolyGlyphBltNonTEFlags & TRANSPARENCY_GXCOPY_ONLY)) + infoRec->PolyGlyphBltMask |= GCFunction; + if(compositeFlags & NO_PLANEMASK) + infoRec->PolyGlyphBltMask |= GCPlaneMask; + if(compositeFlags & RGB_EQUAL) + infoRec->PolyGlyphBltMask |= GCForeground; + infoRec->ValidatePolyGlyphBlt = XAAValidatePolyGlyphBlt; + } + + if(!infoRec->ValidateImageGlyphBlt && + (infoRec->ImageGlyphBltTE || infoRec->ImageGlyphBltNonTE)) { + int compositeFlags = infoRec->ImageGlyphBltTEFlags | + infoRec->ImageGlyphBltNonTEFlags; + + if(infoRec->ImageGlyphBltNonTE) + compositeFlags |= infoRec->SolidFillFlags; + + infoRec->ImageGlyphBltMask = GCFont; + if(compositeFlags & NO_PLANEMASK) + infoRec->ImageGlyphBltMask |= GCPlaneMask; + if(compositeFlags & RGB_EQUAL) + infoRec->ImageGlyphBltMask |= GCForeground | GCBackground; + infoRec->ValidateImageGlyphBlt = XAAValidateImageGlyphBlt; + } + + /* By default XAA only provides a Validation function for the + Polylines and does segments and polylines at the same time */ + + if(!infoRec->ValidatePolylines && infoRec->ValidateFillSpans) { + int compositeFlags = infoRec->PolyRectangleThinSolidFlags | + infoRec->PolylinesWideSolidFlags | + infoRec->PolylinesThinSolidFlags | + infoRec->PolySegmentThinSolidFlags | + infoRec->PolySegmentThinDashedFlags | + infoRec->PolylinesThinDashedFlags; + + infoRec->ValidatePolylines = XAAValidatePolylines; + infoRec->PolylinesMask = + infoRec->FillSpansMask | GCLineStyle | GCLineWidth; + + if(infoRec->PolySegmentThinDashed || infoRec->PolylinesThinDashed) + infoRec->PolylinesMask |= GCDashList; + if(compositeFlags & NO_PLANEMASK) + infoRec->PolylinesMask |= GCPlaneMask; + if((compositeFlags & GXCOPY_ONLY) || + (compositeFlags & ROP_NEEDS_SOURCE)) + infoRec->PolylinesMask |= GCFunction; + if(compositeFlags & RGB_EQUAL) + infoRec->PolylinesMask |= GCForeground; + } + + + /**** Fill choosers ****/ + + if(!infoRec->StippledFillChooser) + infoRec->StippledFillChooser = XAAStippledFillChooser; + + if(!infoRec->OpaqueStippledFillChooser) + infoRec->OpaqueStippledFillChooser = XAAOpaqueStippledFillChooser; + + if(!infoRec->TiledFillChooser) + infoRec->TiledFillChooser = XAATiledFillChooser; + + + /**** Setup the pixmap cache ****/ + + if(infoRec->WriteBitmapToCache) {} + else if(infoRec->WriteBitmap && + !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) + infoRec->WriteBitmapToCache = XAAWriteBitmapToCache; + else if(infoRec->Flags & LINEAR_FRAMEBUFFER) + infoRec->WriteBitmapToCache = XAAWriteBitmapToCacheLinear; + else + infoRec->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES; + + if(infoRec->WritePixmapToCache) {} + else if(infoRec->WritePixmap && !(infoRec->WritePixmapFlags & NO_GXCOPY)) + infoRec->WritePixmapToCache = XAAWritePixmapToCache; + else if(infoRec->Flags & LINEAR_FRAMEBUFFER) + infoRec->WritePixmapToCache = XAAWritePixmapToCacheLinear; + else + infoRec->Flags &= ~PIXMAP_CACHE; + + if (xf86ReturnOptValBool(options, XAAOPT_PIXMAP_CACHE, FALSE)) + infoRec->Flags &= ~PIXMAP_CACHE; + + if(infoRec->WriteMono8x8PatternToCache) {} + else if(infoRec->PixmapCacheFlags & CACHE_MONO_8x8) { + if(infoRec->WritePixmapToCache) + infoRec->WriteMono8x8PatternToCache = XAAWriteMono8x8PatternToCache; + else + infoRec->PixmapCacheFlags &= ~CACHE_MONO_8x8; + } + + if(infoRec->WriteColor8x8PatternToCache) {} + else if(infoRec->PixmapCacheFlags & CACHE_COLOR_8x8) { + if(infoRec->WritePixmapToCache && infoRec->WriteBitmapToCache) + infoRec->WriteColor8x8PatternToCache = XAAWriteColor8x8PatternToCache; + else + infoRec->PixmapCacheFlags &= ~CACHE_COLOR_8x8; + } + + if(infoRec->CachePixelGranularity < 0) { + switch(pScrn->bitsPerPixel) { + case 24: + case 8: infoRec->CachePixelGranularity = 4; break; + case 16: infoRec->CachePixelGranularity = 2; break; + case 32: infoRec->CachePixelGranularity = 1; break; + default: break; + } + + if(BITMAP_SCANLINE_PAD == 64) + infoRec->CachePixelGranularity *= 2; + } + + free(options); + + if(!infoRec->CacheTile && infoRec->WritePixmapToCache) + infoRec->CacheTile = XAACacheTile; + if(!infoRec->CacheMonoStipple && infoRec->WritePixmapToCache) + infoRec->CacheMonoStipple = XAACacheMonoStipple; + if(!infoRec->CacheStipple && infoRec->WriteBitmapToCache) + infoRec->CacheStipple = XAACacheStipple; + if(!infoRec->CacheMono8x8Pattern && infoRec->WriteMono8x8PatternToCache) + infoRec->CacheMono8x8Pattern = XAACacheMono8x8Pattern; + if(!infoRec->CacheColor8x8Pattern && infoRec->WriteColor8x8PatternToCache) + infoRec->CacheColor8x8Pattern = XAACacheColor8x8Pattern; + + if((infoRec->Flags & PIXMAP_CACHE) && !infoRec->InitPixmapCache) { + infoRec->InitPixmapCache = XAAInitPixmapCache; + infoRec->ClosePixmapCache = XAAClosePixmapCache; + } + + return TRUE; +} diff --git a/xorg-server/hw/xfree86/xaa/xaaLineMisc.c b/xorg-server/hw/xfree86/xaa/xaaLineMisc.c index 6cef4bcd5..3e5330fd3 100644 --- a/xorg-server/hw/xfree86/xaa/xaaLineMisc.c +++ b/xorg-server/hw/xfree86/xaa/xaaLineMisc.c @@ -1,151 +1,151 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "miline.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" - - -void -XAASolidHorVertLineAsRects( - ScrnInfoPtr pScrn, - int x, int y, int len, int dir -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - if(dir == DEGREES_0) - (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, len, 1); - else - (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, len); -} - - -void -XAASolidHorVertLineAsTwoPoint( - ScrnInfoPtr pScrn, - int x, int y, int len, int dir -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - len--; - - if(dir == DEGREES_0) - (*infoRec->SubsequentSolidTwoPointLine)(pScrn, x, y, x + len, y, 0); - else - (*infoRec->SubsequentSolidTwoPointLine)(pScrn, x, y, x, y + len, 0); -} - -void -XAASolidHorVertLineAsBresenham( - ScrnInfoPtr pScrn, - int x, int y, int len, int dir -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - if(dir == DEGREES_0) - (*infoRec->SubsequentSolidBresenhamLine)( - pScrn, x, y, len << 1, 0, -len, len, 0); - else - (*infoRec->SubsequentSolidBresenhamLine)( - pScrn, x, y, len << 1, 0, -len, len, YMAJOR); -} - - -void -XAAComputeDash(GCPtr pGC) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&pGC->devPrivates, - XAAGetGCKey()); - Bool EvenDash = (pGC->numInDashList & 0x01) ? FALSE : TRUE; - int PatternLength = 0; - unsigned char* DashPtr = (unsigned char*)pGC->dash; - CARD32 *ptr; - int count = pGC->numInDashList; - int shift, value, direction; - Bool set; - - if(pGCPriv->DashPattern) - xfree(pGCPriv->DashPattern); - - pGCPriv->DashPattern = NULL; - pGCPriv->DashLength = 0; - - while(count--) - PatternLength += *(DashPtr++); - - if(!EvenDash) - PatternLength <<= 1; - - if(PatternLength > infoRec->DashPatternMaxLength) - return; - - if((infoRec->DashedLineFlags & LINE_PATTERN_POWER_OF_2_ONLY) && - (PatternLength & (PatternLength - 1))) - return; - - pGCPriv->DashPattern = xcalloc((PatternLength + 31) >> 5, 4); - if(!pGCPriv->DashPattern) return; - pGCPriv->DashLength = PatternLength; - - if(infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | - LINE_PATTERN_LSBFIRST_LSBJUSTIFIED)) { - direction = 1; - set = TRUE; - DashPtr = (unsigned char*)pGC->dash; - } else { - direction = -1; - set = FALSE; - DashPtr = (unsigned char*)pGC->dash + pGC->numInDashList - 1; - } - - if(infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | - LINE_PATTERN_MSBFIRST_MSBJUSTIFIED)) - shift = 32 - (PatternLength & 31); - else - shift = 0; - - ptr = (CARD32*)(pGCPriv->DashPattern); - -CONCATENATE: - - count = pGC->numInDashList; - - while(count--) { - value = *DashPtr; - DashPtr += direction; - while(value) { - if(value < (32 - shift)) { - if(set) *ptr |= XAAShiftMasks[value] << shift; - shift += value; - break; - } else { - if(set) *ptr |= ~0L << shift; - value -= (32 - shift); - shift = 0; - ptr++; - } - } - if(set) set = FALSE; - else set = TRUE; - } - - if(!EvenDash) { - EvenDash = TRUE; - if(infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | - LINE_PATTERN_LSBFIRST_LSBJUSTIFIED)) - DashPtr = (unsigned char*)pGC->dash; - else - DashPtr = (unsigned char*)pGC->dash + pGC->numInDashList; - goto CONCATENATE; - } -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "miline.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" + + +void +XAASolidHorVertLineAsRects( + ScrnInfoPtr pScrn, + int x, int y, int len, int dir +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + if(dir == DEGREES_0) + (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, len, 1); + else + (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, 1, len); +} + + +void +XAASolidHorVertLineAsTwoPoint( + ScrnInfoPtr pScrn, + int x, int y, int len, int dir +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + len--; + + if(dir == DEGREES_0) + (*infoRec->SubsequentSolidTwoPointLine)(pScrn, x, y, x + len, y, 0); + else + (*infoRec->SubsequentSolidTwoPointLine)(pScrn, x, y, x, y + len, 0); +} + +void +XAASolidHorVertLineAsBresenham( + ScrnInfoPtr pScrn, + int x, int y, int len, int dir +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + if(dir == DEGREES_0) + (*infoRec->SubsequentSolidBresenhamLine)( + pScrn, x, y, len << 1, 0, -len, len, 0); + else + (*infoRec->SubsequentSolidBresenhamLine)( + pScrn, x, y, len << 1, 0, -len, len, YMAJOR); +} + + +void +XAAComputeDash(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + XAAGCPtr pGCPriv = (XAAGCPtr)dixLookupPrivate(&pGC->devPrivates, + XAAGetGCKey()); + Bool EvenDash = (pGC->numInDashList & 0x01) ? FALSE : TRUE; + int PatternLength = 0; + unsigned char* DashPtr = (unsigned char*)pGC->dash; + CARD32 *ptr; + int count = pGC->numInDashList; + int shift, value, direction; + Bool set; + + if(pGCPriv->DashPattern) + free(pGCPriv->DashPattern); + + pGCPriv->DashPattern = NULL; + pGCPriv->DashLength = 0; + + while(count--) + PatternLength += *(DashPtr++); + + if(!EvenDash) + PatternLength <<= 1; + + if(PatternLength > infoRec->DashPatternMaxLength) + return; + + if((infoRec->DashedLineFlags & LINE_PATTERN_POWER_OF_2_ONLY) && + (PatternLength & (PatternLength - 1))) + return; + + pGCPriv->DashPattern = calloc((PatternLength + 31) >> 5, 4); + if(!pGCPriv->DashPattern) return; + pGCPriv->DashLength = PatternLength; + + if(infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | + LINE_PATTERN_LSBFIRST_LSBJUSTIFIED)) { + direction = 1; + set = TRUE; + DashPtr = (unsigned char*)pGC->dash; + } else { + direction = -1; + set = FALSE; + DashPtr = (unsigned char*)pGC->dash + pGC->numInDashList - 1; + } + + if(infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | + LINE_PATTERN_MSBFIRST_MSBJUSTIFIED)) + shift = 32 - (PatternLength & 31); + else + shift = 0; + + ptr = (CARD32*)(pGCPriv->DashPattern); + +CONCATENATE: + + count = pGC->numInDashList; + + while(count--) { + value = *DashPtr; + DashPtr += direction; + while(value) { + if(value < (32 - shift)) { + if(set) *ptr |= XAAShiftMasks[value] << shift; + shift += value; + break; + } else { + if(set) *ptr |= ~0L << shift; + value -= (32 - shift); + shift = 0; + ptr++; + } + } + if(set) set = FALSE; + else set = TRUE; + } + + if(!EvenDash) { + EvenDash = TRUE; + if(infoRec->DashedLineFlags & (LINE_PATTERN_LSBFIRST_MSBJUSTIFIED | + LINE_PATTERN_LSBFIRST_LSBJUSTIFIED)) + DashPtr = (unsigned char*)pGC->dash; + else + DashPtr = (unsigned char*)pGC->dash + pGC->numInDashList; + goto CONCATENATE; + } +} diff --git a/xorg-server/hw/xfree86/xaa/xaaNonTEText.c b/xorg-server/hw/xfree86/xaa/xaaNonTEText.c index d32c0bbc5..eb798a82b 100644 --- a/xorg-server/hw/xfree86/xaa/xaaNonTEText.c +++ b/xorg-server/hw/xfree86/xaa/xaaNonTEText.c @@ -1,591 +1,591 @@ - -/******************************************************************** - - In this file we have GC level replacements for PolyText8/16, - ImageText8/16, ImageGlyphBlt and PolyGlyphBlt for NonTE (proportional) - fonts. The idea is that everything in this file is device independent. - The mentioned GCOps are merely wrappers for the - PolyGlyphBltNonTEColorExpansion and ImageGlyphBltNonTEColorExpansion - functions which calculate the boxes containing arbitrarily clipped - text and passes them to the NonTEGlyphRenderer which will usually - be a lower level XAA function which renders these clipped glyphs using - the basic color expansion functions exported by the chipset driver. - The NonTEGlyphRenderer itself may optionally be driver supplied to - facilitate work-arounds/optimizations at a higher level than usual. - - Written by Mark Vojkovich (mvojkovi@ucsd.edu) - -********************************************************************/ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include -#include "scrnintstr.h" -#include "dixfontstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaacexp.h" -#include "xaalocal.h" -#include "gcstruct.h" -#include "pixmapstr.h" - - -static void ImageGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn, - int xInit, int yInit, FontPtr font, - int fg, int bg, unsigned planemask, - RegionPtr cclip, int nglyph, - unsigned char* gBase, CharInfoPtr *ppci); -static int PolyGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn, - int xInit, int yInit, FontPtr font, - int fg, int rop, unsigned planemask, - RegionPtr cclip, int nglyph, - unsigned char* gBase, CharInfoPtr *ppci); - -/******************************************************************** - - GC level replacements for PolyText8/16 and ImageText8/16 - for NonTE fonts when using color expansion. - -********************************************************************/ - - -int -XAAPolyText8NonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - char *chars ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - unsigned long n; - int width = 0; - - (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count, - (unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo); - - if(n) { - width = PolyGlyphBltNonTEColorExpansion( infoRec->pScrn, - x + pDraw->x, y + pDraw->y, pGC->font, - pGC->fgPixel, pGC->alu, pGC->planemask, - pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), - infoRec->CharInfo); - } - - return (x + width); -} - - -int -XAAPolyText16NonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - unsigned short *chars ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - unsigned long n; - int width = 0; - - (*pGC->font->get_glyphs)( - pGC->font, (unsigned long)count, (unsigned char *)chars, - (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, - &n, infoRec->CharInfo); - - if(n) { - width = PolyGlyphBltNonTEColorExpansion( infoRec->pScrn, - x + pDraw->x, y + pDraw->y, pGC->font, - pGC->fgPixel, pGC->alu, pGC->planemask, - pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), - infoRec->CharInfo); - } - - return (x + width); -} - - -void -XAAImageText8NonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - char *chars -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - unsigned long n; - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count, - (unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo); - - if(n) ImageGlyphBltNonTEColorExpansion( - infoRec->pScrn, x + pDraw->x, y + pDraw->y, - pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask, - pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); -} - - -void -XAAImageText16NonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, - int y, - int count, - unsigned short *chars -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - unsigned long n; - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - (*pGC->font->get_glyphs)( - pGC->font, (unsigned long)count, (unsigned char *)chars, - (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, - &n, infoRec->CharInfo); - - if(n) ImageGlyphBltNonTEColorExpansion( - infoRec->pScrn, x + pDraw->x, y + pDraw->y, - pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask, - pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); -} - - - -/******************************************************************** - - GC level replacements for ImageGlyphBlt and PolyGlyphBlt for - NonTE fonts when using color expansion. - -********************************************************************/ - - -void -XAAImageGlyphBltNonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, /* array of character info */ - pointer pglyphBase /* start of array of glyphs */ -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - ImageGlyphBltNonTEColorExpansion( - infoRec->pScrn, xInit + pDraw->x, yInit + pDraw->y, - pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask, - pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci); -} - -void -XAAPolyGlyphBltNonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, /* array of character info */ - pointer pglyphBase /* start of array of glyphs */ -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - PolyGlyphBltNonTEColorExpansion( - infoRec->pScrn, xInit + pDraw->x, yInit + pDraw->y, - pGC->font, pGC->fgPixel, pGC->alu, pGC->planemask, - pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci); -} - - - - -/******************************************************************** - - ImageGlyphBltNonTEColorExpansion - - PolyGlyphBltNonTEColorExpansion - - - These guys compute the clipped pieces of text and send it to - the lower-level function which will handle acceleration of - arbitrarily clipped text. - -********************************************************************/ - - - -static int -CollectCharacterInfo( - NonTEGlyphPtr glyphs, - unsigned int nglyph, - CharInfoPtr *ppci, - FontPtr pfont -){ - int i, w = 0; - - for(i = 0; i < nglyph; i++, ppci++, glyphs++) { - glyphs->bits = (unsigned char*)((*ppci)->bits); - glyphs->start = w + (*ppci)->metrics.leftSideBearing; - glyphs->end = w + (*ppci)->metrics.rightSideBearing; - glyphs->yoff = (*ppci)->metrics.ascent; - glyphs->height = glyphs->yoff + (*ppci)->metrics.descent; - glyphs->srcwidth = PADGLYPHWIDTHBYTES(glyphs->end - glyphs->start); - w += (*ppci)->metrics.characterWidth; - } - return w; -} - - -static void -PolyGlyphBltAsSingleBitmap ( - ScrnInfoPtr pScrn, - int nglyph, - FontPtr font, - int xInit, - int yInit, - int nbox, - BoxPtr pbox, - int fg, - int rop, - unsigned planemask -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - CARD32 *block, *pntr, *bits; - int pitch, topLine, botLine, top, bot, height; - int Left, Right, Top, Bottom; - int LeftEdge, RightEdge; - int bitPitch, shift, size, i, skippix; - NonTEGlyphPtr glyphs = infoRec->GlyphInfo; - Bool extra; - - Left = xInit + infoRec->GlyphInfo[0].start; - Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; - Top = yInit - FONTMAXBOUNDS(font,ascent); - Bottom = yInit + FONTMAXBOUNDS(font,descent); - - /* get into the first band that may contain part of our string */ - while(nbox && (Top >= pbox->y2)) { - pbox++; nbox--; - } - - if(!nbox) return; - - pitch = (Right - Left + 31) >> 5; - size = (pitch << 2) * (Bottom - Top); - block = xcalloc(1, size); - - topLine = 10000; botLine = -10000; - - while(nglyph--) { - top = -glyphs->yoff; - bot = top + glyphs->height; - if(top < topLine) topLine = top; - if(bot > botLine) botLine = bot; - skippix = glyphs->start - infoRec->GlyphInfo[0].start; - bits = (CARD32*)glyphs->bits; - bitPitch = glyphs->srcwidth >> 2; - pntr = block + ((FONTMAXBOUNDS(font,ascent) + top) * pitch) + - (skippix >> 5); - shift = skippix & 31; - extra = ((shift + glyphs->end - glyphs->start) > 32); - - for(i = top; i < bot; i++) { - *pntr |= SHIFT_L(*bits, shift); - if(extra) - *(pntr + 1) |= SHIFT_R(*bits,32 - shift); - pntr += pitch; - bits += bitPitch; - } - - glyphs++; - } - - pntr = block + ((FONTMAXBOUNDS(font,ascent) + topLine) * pitch); - - Top = yInit + topLine; - Bottom = yInit + botLine; - - while(nbox && (Top >= pbox->y2)) { - pbox++; nbox--; - } - - while(nbox && (Bottom > pbox->y1)) { - LeftEdge = max(Left, pbox->x1); - RightEdge = min(Right, pbox->x2); - - if(RightEdge > LeftEdge) { - skippix = LeftEdge - Left; - topLine = max(Top, pbox->y1); - botLine = min(Bottom, pbox->y2); - height = botLine - topLine; - - if(height > 0) - (*infoRec->WriteBitmap)(pScrn, LeftEdge, topLine, - RightEdge - LeftEdge, height, - (unsigned char*)(pntr + ((topLine - Top) * pitch) + - (skippix >> 5)), - pitch << 2, skippix & 31, fg, -1, rop, planemask); - } - - nbox--; pbox++; - } - - xfree(block); -} - -static void -ImageGlyphBltNonTEColorExpansion( - ScrnInfoPtr pScrn, - int xInit, int yInit, - FontPtr font, - int fg, int bg, - unsigned planemask, - RegionPtr cclip, - int nglyph, - unsigned char* gBase, - CharInfoPtr *ppci -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int skippix, skipglyph, width, n, i; - int Left, Right, Top, Bottom; - int LeftEdge, RightEdge, ytop, ybot; - int nbox = REGION_NUM_RECTS(cclip); - BoxPtr pbox = REGION_RECTS(cclip); - Bool AlreadySetup = FALSE; - - width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font); - - /* find our backing rectangle dimensions */ - Left = xInit; - Right = Left + width; - Top = yInit - FONTASCENT(font); - Bottom = yInit + FONTDESCENT(font); - - /* get into the first band that may contain part of our box */ - while(nbox && (Top >= pbox->y2)) { - pbox++; nbox--; - } - - while(nbox && (Bottom >= pbox->y1)) { - /* handle backing rect first */ - LeftEdge = max(Left, pbox->x1); - RightEdge = min(Right, pbox->x2); - if(RightEdge > LeftEdge) { - ytop = max(Top, pbox->y1); - ybot = min(Bottom, pbox->y2); - - if(ybot > ytop) { - if(!AlreadySetup) { - (*infoRec->SetupForSolidFill)(pScrn, bg, GXcopy, planemask); - AlreadySetup = TRUE; - } - (*infoRec->SubsequentSolidFillRect)(pScrn, - LeftEdge, ytop, RightEdge - LeftEdge, ybot - ytop); - } - } - nbox--; pbox++; - } - - nbox = REGION_NUM_RECTS(cclip); - pbox = REGION_RECTS(cclip); - - if(infoRec->WriteBitmap && (nglyph > 1) && - ((FONTMAXBOUNDS(font, rightSideBearing) - - FONTMINBOUNDS(font, leftSideBearing)) <= 32)) - { - PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font, - xInit, yInit, nbox, pbox, - fg, GXcopy, planemask); - - return; - } - - /* compute an approximate but covering bounding box */ - Left = xInit + infoRec->GlyphInfo[0].start; - Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; - Top = yInit - FONTMAXBOUNDS(font,ascent); - Bottom = yInit + FONTMAXBOUNDS(font,descent); - - /* get into the first band that may contain part of our box */ - while(nbox && (Top >= pbox->y2)) { - pbox++; nbox--; - } - - /* stop when the lower edge of the box is beyond our string */ - while(nbox && (Bottom >= pbox->y1)) { - LeftEdge = max(Left, pbox->x1); - RightEdge = min(Right, pbox->x2); - - if(RightEdge > LeftEdge) { /* we're possibly drawing something */ - ytop = max(Top, pbox->y1); - ybot = min(Bottom, pbox->y2); - if(ybot > ytop) { - skippix = LeftEdge - xInit; - skipglyph = 0; - while(skippix >= infoRec->GlyphInfo[skipglyph].end) - skipglyph++; - - skippix = RightEdge - xInit; - n = 0; i = skipglyph; - while((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) { - i++; n++; - } - - if(n) (*infoRec->NonTEGlyphRenderer)(pScrn, - xInit, yInit, n, infoRec->GlyphInfo + skipglyph, - pbox, fg, GXcopy, planemask); - } - } - - nbox--; pbox++; - } -} - - -static int -PolyGlyphBltNonTEColorExpansion( - ScrnInfoPtr pScrn, - int xInit, int yInit, - FontPtr font, - int fg, int rop, - unsigned planemask, - RegionPtr cclip, - int nglyph, - unsigned char* gBase, - CharInfoPtr *ppci -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int skippix, skipglyph, width, n, i; - int Left, Right, Top, Bottom; - int LeftEdge, RightEdge; - int nbox = REGION_NUM_RECTS(cclip); - BoxPtr pbox = REGION_RECTS(cclip); - - width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font); - - if(!nbox) - return width; - - if((infoRec->WriteBitmap) && (rop == GXcopy) && (nglyph > 1) && - ((FONTMAXBOUNDS(font, rightSideBearing) - - FONTMINBOUNDS(font, leftSideBearing)) <= 32)) { - - PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font, - xInit, yInit, nbox, pbox, - fg, rop, planemask); - - return width; - } - - /* compute an approximate but covering bounding box */ - Left = xInit + infoRec->GlyphInfo[0].start; - Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; - Top = yInit - FONTMAXBOUNDS(font,ascent); - Bottom = yInit + FONTMAXBOUNDS(font,descent); - - /* get into the first band that may contain part of our string */ - while(nbox && (Top >= pbox->y2)) { - pbox++; nbox--; - } - - /* stop when the lower edge of the box is beyond our string */ - while(nbox && (Bottom >= pbox->y1)) { - LeftEdge = max(Left, pbox->x1); - RightEdge = min(Right, pbox->x2); - - if(RightEdge > LeftEdge) { /* we're possibly drawing something */ - - skippix = LeftEdge - xInit; - skipglyph = 0; - while(skippix >= infoRec->GlyphInfo[skipglyph].end) - skipglyph++; - - skippix = RightEdge - xInit; - n = 0; i = skipglyph; - while((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) { - i++; n++; - } - - if(n) (*infoRec->NonTEGlyphRenderer)(pScrn, - xInit, yInit, n, infoRec->GlyphInfo + skipglyph, - pbox, fg, rop, planemask); - } - - nbox--; pbox++; - } - return width; -} - - -/* It is possible that the none of the glyphs passed to the - NonTEGlyphRenderer will be drawn. This function being called - indicates that part of the text string's bounding box is visible - but not necessarily that any of the characters are visible */ - -void XAANonTEGlyphRenderer( - ScrnInfoPtr pScrn, - int x, int y, int n, - NonTEGlyphPtr glyphs, - BoxPtr pbox, - int fg, int rop, - unsigned int planemask -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int x1, x2, y1, y2, i, w, h, skipleft, skiptop; - unsigned char *src; - - for(i = 0; i < n; i++, glyphs++) { - x1 = x + glyphs->start; - x2 = x + glyphs->end; - y1 = y - glyphs->yoff; - y2 = y1 + glyphs->height; - - if(y1 < pbox->y1) { - skiptop = pbox->y1 - y1; - y1 = pbox->y1; - } else skiptop = 0; - if(y2 > pbox->y2) y2 = pbox->y2; - h = y2 - y1; - if(h <= 0) continue; - - if(x1 < pbox->x1) { - skipleft = pbox->x1 - x1; - x1 = pbox->x1; - } else skipleft = 0; - if(x2 > pbox->x2) x2 = pbox->x2; - - w = x2 - x1; - - if(w > 0) { - src = glyphs->bits + (skiptop * glyphs->srcwidth); - - if(skipleft) { - src += (skipleft >> 5) << 2; - skipleft &= 31; - } - - (*infoRec->WriteBitmap)(pScrn, x1, y1, w, h, src, - glyphs->srcwidth, skipleft, fg, -1, rop, planemask); - } - } - -} + +/******************************************************************** + + In this file we have GC level replacements for PolyText8/16, + ImageText8/16, ImageGlyphBlt and PolyGlyphBlt for NonTE (proportional) + fonts. The idea is that everything in this file is device independent. + The mentioned GCOps are merely wrappers for the + PolyGlyphBltNonTEColorExpansion and ImageGlyphBltNonTEColorExpansion + functions which calculate the boxes containing arbitrarily clipped + text and passes them to the NonTEGlyphRenderer which will usually + be a lower level XAA function which renders these clipped glyphs using + the basic color expansion functions exported by the chipset driver. + The NonTEGlyphRenderer itself may optionally be driver supplied to + facilitate work-arounds/optimizations at a higher level than usual. + + Written by Mark Vojkovich (mvojkovi@ucsd.edu) + +********************************************************************/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include +#include "scrnintstr.h" +#include "dixfontstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaacexp.h" +#include "xaalocal.h" +#include "gcstruct.h" +#include "pixmapstr.h" + + +static void ImageGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn, + int xInit, int yInit, FontPtr font, + int fg, int bg, unsigned planemask, + RegionPtr cclip, int nglyph, + unsigned char* gBase, CharInfoPtr *ppci); +static int PolyGlyphBltNonTEColorExpansion(ScrnInfoPtr pScrn, + int xInit, int yInit, FontPtr font, + int fg, int rop, unsigned planemask, + RegionPtr cclip, int nglyph, + unsigned char* gBase, CharInfoPtr *ppci); + +/******************************************************************** + + GC level replacements for PolyText8/16 and ImageText8/16 + for NonTE fonts when using color expansion. + +********************************************************************/ + + +int +XAAPolyText8NonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + int width = 0; + + (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count, + (unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo); + + if(n) { + width = PolyGlyphBltNonTEColorExpansion( infoRec->pScrn, + x + pDraw->x, y + pDraw->y, pGC->font, + pGC->fgPixel, pGC->alu, pGC->planemask, + pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), + infoRec->CharInfo); + } + + return (x + width); +} + + +int +XAAPolyText16NonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + int width = 0; + + (*pGC->font->get_glyphs)( + pGC->font, (unsigned long)count, (unsigned char *)chars, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, infoRec->CharInfo); + + if(n) { + width = PolyGlyphBltNonTEColorExpansion( infoRec->pScrn, + x + pDraw->x, y + pDraw->y, pGC->font, + pGC->fgPixel, pGC->alu, pGC->planemask, + pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), + infoRec->CharInfo); + } + + return (x + width); +} + + +void +XAAImageText8NonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + char *chars +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count, + (unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo); + + if(n) ImageGlyphBltNonTEColorExpansion( + infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask, + pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); +} + + +void +XAAImageText16NonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, + int y, + int count, + unsigned short *chars +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + (*pGC->font->get_glyphs)( + pGC->font, (unsigned long)count, (unsigned char *)chars, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, infoRec->CharInfo); + + if(n) ImageGlyphBltNonTEColorExpansion( + infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask, + pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); +} + + + +/******************************************************************** + + GC level replacements for ImageGlyphBlt and PolyGlyphBlt for + NonTE fonts when using color expansion. + +********************************************************************/ + + +void +XAAImageGlyphBltNonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, /* array of character info */ + pointer pglyphBase /* start of array of glyphs */ +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + ImageGlyphBltNonTEColorExpansion( + infoRec->pScrn, xInit + pDraw->x, yInit + pDraw->y, + pGC->font, pGC->fgPixel, pGC->bgPixel, pGC->planemask, + pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci); +} + +void +XAAPolyGlyphBltNonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, /* array of character info */ + pointer pglyphBase /* start of array of glyphs */ +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + PolyGlyphBltNonTEColorExpansion( + infoRec->pScrn, xInit + pDraw->x, yInit + pDraw->y, + pGC->font, pGC->fgPixel, pGC->alu, pGC->planemask, + pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci); +} + + + + +/******************************************************************** + + ImageGlyphBltNonTEColorExpansion - + PolyGlyphBltNonTEColorExpansion - + + These guys compute the clipped pieces of text and send it to + the lower-level function which will handle acceleration of + arbitrarily clipped text. + +********************************************************************/ + + + +static int +CollectCharacterInfo( + NonTEGlyphPtr glyphs, + unsigned int nglyph, + CharInfoPtr *ppci, + FontPtr pfont +){ + int i, w = 0; + + for(i = 0; i < nglyph; i++, ppci++, glyphs++) { + glyphs->bits = (unsigned char*)((*ppci)->bits); + glyphs->start = w + (*ppci)->metrics.leftSideBearing; + glyphs->end = w + (*ppci)->metrics.rightSideBearing; + glyphs->yoff = (*ppci)->metrics.ascent; + glyphs->height = glyphs->yoff + (*ppci)->metrics.descent; + glyphs->srcwidth = PADGLYPHWIDTHBYTES(glyphs->end - glyphs->start); + w += (*ppci)->metrics.characterWidth; + } + return w; +} + + +static void +PolyGlyphBltAsSingleBitmap ( + ScrnInfoPtr pScrn, + int nglyph, + FontPtr font, + int xInit, + int yInit, + int nbox, + BoxPtr pbox, + int fg, + int rop, + unsigned planemask +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *block, *pntr, *bits; + int pitch, topLine, botLine, top, bot, height; + int Left, Right, Top, Bottom; + int LeftEdge, RightEdge; + int bitPitch, shift, size, i, skippix; + NonTEGlyphPtr glyphs = infoRec->GlyphInfo; + Bool extra; + + Left = xInit + infoRec->GlyphInfo[0].start; + Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; + Top = yInit - FONTMAXBOUNDS(font,ascent); + Bottom = yInit + FONTMAXBOUNDS(font,descent); + + /* get into the first band that may contain part of our string */ + while(nbox && (Top >= pbox->y2)) { + pbox++; nbox--; + } + + if(!nbox) return; + + pitch = (Right - Left + 31) >> 5; + size = (pitch << 2) * (Bottom - Top); + block = calloc(1, size); + + topLine = 10000; botLine = -10000; + + while(nglyph--) { + top = -glyphs->yoff; + bot = top + glyphs->height; + if(top < topLine) topLine = top; + if(bot > botLine) botLine = bot; + skippix = glyphs->start - infoRec->GlyphInfo[0].start; + bits = (CARD32*)glyphs->bits; + bitPitch = glyphs->srcwidth >> 2; + pntr = block + ((FONTMAXBOUNDS(font,ascent) + top) * pitch) + + (skippix >> 5); + shift = skippix & 31; + extra = ((shift + glyphs->end - glyphs->start) > 32); + + for(i = top; i < bot; i++) { + *pntr |= SHIFT_L(*bits, shift); + if(extra) + *(pntr + 1) |= SHIFT_R(*bits,32 - shift); + pntr += pitch; + bits += bitPitch; + } + + glyphs++; + } + + pntr = block + ((FONTMAXBOUNDS(font,ascent) + topLine) * pitch); + + Top = yInit + topLine; + Bottom = yInit + botLine; + + while(nbox && (Top >= pbox->y2)) { + pbox++; nbox--; + } + + while(nbox && (Bottom > pbox->y1)) { + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + + if(RightEdge > LeftEdge) { + skippix = LeftEdge - Left; + topLine = max(Top, pbox->y1); + botLine = min(Bottom, pbox->y2); + height = botLine - topLine; + + if(height > 0) + (*infoRec->WriteBitmap)(pScrn, LeftEdge, topLine, + RightEdge - LeftEdge, height, + (unsigned char*)(pntr + ((topLine - Top) * pitch) + + (skippix >> 5)), + pitch << 2, skippix & 31, fg, -1, rop, planemask); + } + + nbox--; pbox++; + } + + free(block); +} + +static void +ImageGlyphBltNonTEColorExpansion( + ScrnInfoPtr pScrn, + int xInit, int yInit, + FontPtr font, + int fg, int bg, + unsigned planemask, + RegionPtr cclip, + int nglyph, + unsigned char* gBase, + CharInfoPtr *ppci +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int skippix, skipglyph, width, n, i; + int Left, Right, Top, Bottom; + int LeftEdge, RightEdge, ytop, ybot; + int nbox = REGION_NUM_RECTS(cclip); + BoxPtr pbox = REGION_RECTS(cclip); + Bool AlreadySetup = FALSE; + + width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font); + + /* find our backing rectangle dimensions */ + Left = xInit; + Right = Left + width; + Top = yInit - FONTASCENT(font); + Bottom = yInit + FONTDESCENT(font); + + /* get into the first band that may contain part of our box */ + while(nbox && (Top >= pbox->y2)) { + pbox++; nbox--; + } + + while(nbox && (Bottom >= pbox->y1)) { + /* handle backing rect first */ + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + if(RightEdge > LeftEdge) { + ytop = max(Top, pbox->y1); + ybot = min(Bottom, pbox->y2); + + if(ybot > ytop) { + if(!AlreadySetup) { + (*infoRec->SetupForSolidFill)(pScrn, bg, GXcopy, planemask); + AlreadySetup = TRUE; + } + (*infoRec->SubsequentSolidFillRect)(pScrn, + LeftEdge, ytop, RightEdge - LeftEdge, ybot - ytop); + } + } + nbox--; pbox++; + } + + nbox = REGION_NUM_RECTS(cclip); + pbox = REGION_RECTS(cclip); + + if(infoRec->WriteBitmap && (nglyph > 1) && + ((FONTMAXBOUNDS(font, rightSideBearing) - + FONTMINBOUNDS(font, leftSideBearing)) <= 32)) + { + PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font, + xInit, yInit, nbox, pbox, + fg, GXcopy, planemask); + + return; + } + + /* compute an approximate but covering bounding box */ + Left = xInit + infoRec->GlyphInfo[0].start; + Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; + Top = yInit - FONTMAXBOUNDS(font,ascent); + Bottom = yInit + FONTMAXBOUNDS(font,descent); + + /* get into the first band that may contain part of our box */ + while(nbox && (Top >= pbox->y2)) { + pbox++; nbox--; + } + + /* stop when the lower edge of the box is beyond our string */ + while(nbox && (Bottom >= pbox->y1)) { + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + + if(RightEdge > LeftEdge) { /* we're possibly drawing something */ + ytop = max(Top, pbox->y1); + ybot = min(Bottom, pbox->y2); + if(ybot > ytop) { + skippix = LeftEdge - xInit; + skipglyph = 0; + while(skippix >= infoRec->GlyphInfo[skipglyph].end) + skipglyph++; + + skippix = RightEdge - xInit; + n = 0; i = skipglyph; + while((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) { + i++; n++; + } + + if(n) (*infoRec->NonTEGlyphRenderer)(pScrn, + xInit, yInit, n, infoRec->GlyphInfo + skipglyph, + pbox, fg, GXcopy, planemask); + } + } + + nbox--; pbox++; + } +} + + +static int +PolyGlyphBltNonTEColorExpansion( + ScrnInfoPtr pScrn, + int xInit, int yInit, + FontPtr font, + int fg, int rop, + unsigned planemask, + RegionPtr cclip, + int nglyph, + unsigned char* gBase, + CharInfoPtr *ppci +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int skippix, skipglyph, width, n, i; + int Left, Right, Top, Bottom; + int LeftEdge, RightEdge; + int nbox = REGION_NUM_RECTS(cclip); + BoxPtr pbox = REGION_RECTS(cclip); + + width = CollectCharacterInfo(infoRec->GlyphInfo, nglyph, ppci, font); + + if(!nbox) + return width; + + if((infoRec->WriteBitmap) && (rop == GXcopy) && (nglyph > 1) && + ((FONTMAXBOUNDS(font, rightSideBearing) - + FONTMINBOUNDS(font, leftSideBearing)) <= 32)) { + + PolyGlyphBltAsSingleBitmap(pScrn, nglyph, font, + xInit, yInit, nbox, pbox, + fg, rop, planemask); + + return width; + } + + /* compute an approximate but covering bounding box */ + Left = xInit + infoRec->GlyphInfo[0].start; + Right = xInit + infoRec->GlyphInfo[nglyph - 1].end; + Top = yInit - FONTMAXBOUNDS(font,ascent); + Bottom = yInit + FONTMAXBOUNDS(font,descent); + + /* get into the first band that may contain part of our string */ + while(nbox && (Top >= pbox->y2)) { + pbox++; nbox--; + } + + /* stop when the lower edge of the box is beyond our string */ + while(nbox && (Bottom >= pbox->y1)) { + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + + if(RightEdge > LeftEdge) { /* we're possibly drawing something */ + + skippix = LeftEdge - xInit; + skipglyph = 0; + while(skippix >= infoRec->GlyphInfo[skipglyph].end) + skipglyph++; + + skippix = RightEdge - xInit; + n = 0; i = skipglyph; + while((i < nglyph) && (skippix > infoRec->GlyphInfo[i].start)) { + i++; n++; + } + + if(n) (*infoRec->NonTEGlyphRenderer)(pScrn, + xInit, yInit, n, infoRec->GlyphInfo + skipglyph, + pbox, fg, rop, planemask); + } + + nbox--; pbox++; + } + return width; +} + + +/* It is possible that the none of the glyphs passed to the + NonTEGlyphRenderer will be drawn. This function being called + indicates that part of the text string's bounding box is visible + but not necessarily that any of the characters are visible */ + +void XAANonTEGlyphRenderer( + ScrnInfoPtr pScrn, + int x, int y, int n, + NonTEGlyphPtr glyphs, + BoxPtr pbox, + int fg, int rop, + unsigned int planemask +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int x1, x2, y1, y2, i, w, h, skipleft, skiptop; + unsigned char *src; + + for(i = 0; i < n; i++, glyphs++) { + x1 = x + glyphs->start; + x2 = x + glyphs->end; + y1 = y - glyphs->yoff; + y2 = y1 + glyphs->height; + + if(y1 < pbox->y1) { + skiptop = pbox->y1 - y1; + y1 = pbox->y1; + } else skiptop = 0; + if(y2 > pbox->y2) y2 = pbox->y2; + h = y2 - y1; + if(h <= 0) continue; + + if(x1 < pbox->x1) { + skipleft = pbox->x1 - x1; + x1 = pbox->x1; + } else skipleft = 0; + if(x2 > pbox->x2) x2 = pbox->x2; + + w = x2 - x1; + + if(w > 0) { + src = glyphs->bits + (skiptop * glyphs->srcwidth); + + if(skipleft) { + src += (skipleft >> 5) << 2; + skipleft &= 31; + } + + (*infoRec->WriteBitmap)(pScrn, x1, y1, w, h, src, + glyphs->srcwidth, skipleft, fg, -1, rop, planemask); + } + } + +} diff --git a/xorg-server/hw/xfree86/xaa/xaaOffscreen.c b/xorg-server/hw/xfree86/xaa/xaaOffscreen.c index 7c9d53270..41be2b491 100644 --- a/xorg-server/hw/xfree86/xaa/xaaOffscreen.c +++ b/xorg-server/hw/xfree86/xaa/xaaOffscreen.c @@ -1,162 +1,162 @@ - -/* - Copyright (c) 1999 - The XFree86 Project Inc. - - Written by Mark Vojkovich - -*/ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "xf86str.h" -#include "mi.h" -#include "miline.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xaawrap.h" -#include "xf86fbman.h" -#include "servermd.h" - -void -XAAMoveOutOffscreenPixmaps(ScreenPtr pScreen) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; - XAAPixmapPtr pPriv; - - while(pLink) { - pPriv = XAA_GET_PIXMAP_PRIVATE(pLink->pPix); - pLink->area = pPriv->offscreenArea; - XAAMoveOutOffscreenPixmap(pLink->pPix); - pLink = pLink->next; - } -} - - - -void -XAAMoveInOffscreenPixmaps(ScreenPtr pScreen) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; - PixmapPtr pPix, pScreenPix, tmpPix; - pointer data; - XAAPixmapPtr pPriv; - GCPtr pGC; - FBAreaPtr area; - - pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); - - while(pLink) { - pPix = pLink->pPix; - pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - area = pLink->area; - - data = pPix->devPrivate.ptr; - tmpPix = GetScratchPixmapHeader(pScreen, - pPix->drawable.width, pPix->drawable.height, - pPix->drawable.depth, pPix->drawable.bitsPerPixel, - pPix->devKind, data); - - pPriv->freeData = FALSE; - - pPix->drawable.x = area->box.x1; - pPix->drawable.y = area->box.y1; - pPix->devKind = pScreenPix->devKind; - pPix->devPrivate.ptr = pScreenPix->devPrivate.ptr; - pPix->drawable.bitsPerPixel = infoRec->pScrn->bitsPerPixel; - pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; - - if(!tmpPix) { - pPriv->offscreenArea = area; - xfree(data); - pLink = pLink->next; - continue; - } - - pGC = GetScratchGC(pPix->drawable.depth, pScreen); - ValidateGC((DrawablePtr)pPix, pGC); - - (*pGC->ops->CopyArea)((DrawablePtr)tmpPix, (DrawablePtr)pPix, pGC, - 0, 0, pPix->drawable.width, pPix->drawable.height, 0, 0); - - xfree(data); - tmpPix->devPrivate.ptr = NULL; - - FreeScratchGC(pGC); - FreeScratchPixmapHeader(tmpPix); - - pPriv->offscreenArea = area; - pLink->area = NULL; - pLink = pLink->next; - } -} - - -void -XAARemoveAreaCallback(FBAreaPtr area) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(area->pScreen); - PixmapPtr pPix = (PixmapPtr)area->devPrivate.ptr; - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - - XAAMoveOutOffscreenPixmap(pPix); - - pPriv->flags &= ~OFFSCREEN; - - DELIST_OFFSCREEN_PIXMAP(pPix); -} - -void -XAAMoveOutOffscreenPixmap(PixmapPtr pPix) -{ - ScreenPtr pScreen = pPix->drawable.pScreen; - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - int width, height, devKind, bitsPerPixel; - PixmapPtr tmpPix; - unsigned char *data; - GCPtr pGC; - - width = pPix->drawable.width; - height = pPix->drawable.height; - bitsPerPixel = pPix->drawable.bitsPerPixel; - - devKind = BitmapBytePad(width * bitsPerPixel); - if(!(data = xalloc(devKind * height))) - FatalError("Out of memory\n"); - - tmpPix = GetScratchPixmapHeader(pScreen, width, height, - pPix->drawable.depth, bitsPerPixel, devKind, data); - if(!tmpPix) { - xfree(data); - FatalError("Out of memory\n"); - } - - pGC = GetScratchGC(pPix->drawable.depth, pScreen); - ValidateGC((DrawablePtr)tmpPix, pGC); - - (*pGC->ops->CopyArea)((DrawablePtr)pPix, (DrawablePtr)tmpPix, - pGC, 0, 0, width, height, 0, 0); - - FreeScratchGC(pGC); - FreeScratchPixmapHeader(tmpPix); - - pPix->drawable.x = 0; - pPix->drawable.y = 0; - pPix->devKind = devKind; - pPix->devPrivate.ptr = data; - pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; - - pPriv->offscreenArea = NULL; - pPriv->freeData = TRUE; -} + +/* + Copyright (c) 1999 - The XFree86 Project Inc. + + Written by Mark Vojkovich + +*/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miline.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "xf86fbman.h" +#include "servermd.h" + +void +XAAMoveOutOffscreenPixmaps(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; + XAAPixmapPtr pPriv; + + while(pLink) { + pPriv = XAA_GET_PIXMAP_PRIVATE(pLink->pPix); + pLink->area = pPriv->offscreenArea; + XAAMoveOutOffscreenPixmap(pLink->pPix); + pLink = pLink->next; + } +} + + + +void +XAAMoveInOffscreenPixmaps(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + PixmapLinkPtr pLink = infoRec->OffscreenPixmaps; + PixmapPtr pPix, pScreenPix, tmpPix; + pointer data; + XAAPixmapPtr pPriv; + GCPtr pGC; + FBAreaPtr area; + + pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); + + while(pLink) { + pPix = pLink->pPix; + pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + area = pLink->area; + + data = pPix->devPrivate.ptr; + tmpPix = GetScratchPixmapHeader(pScreen, + pPix->drawable.width, pPix->drawable.height, + pPix->drawable.depth, pPix->drawable.bitsPerPixel, + pPix->devKind, data); + + pPriv->freeData = FALSE; + + pPix->drawable.x = area->box.x1; + pPix->drawable.y = area->box.y1; + pPix->devKind = pScreenPix->devKind; + pPix->devPrivate.ptr = pScreenPix->devPrivate.ptr; + pPix->drawable.bitsPerPixel = infoRec->pScrn->bitsPerPixel; + pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + if(!tmpPix) { + pPriv->offscreenArea = area; + free(data); + pLink = pLink->next; + continue; + } + + pGC = GetScratchGC(pPix->drawable.depth, pScreen); + ValidateGC((DrawablePtr)pPix, pGC); + + (*pGC->ops->CopyArea)((DrawablePtr)tmpPix, (DrawablePtr)pPix, pGC, + 0, 0, pPix->drawable.width, pPix->drawable.height, 0, 0); + + free(data); + tmpPix->devPrivate.ptr = NULL; + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(tmpPix); + + pPriv->offscreenArea = area; + pLink->area = NULL; + pLink = pLink->next; + } +} + + +void +XAARemoveAreaCallback(FBAreaPtr area) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(area->pScreen); + PixmapPtr pPix = (PixmapPtr)area->devPrivate.ptr; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + + XAAMoveOutOffscreenPixmap(pPix); + + pPriv->flags &= ~OFFSCREEN; + + DELIST_OFFSCREEN_PIXMAP(pPix); +} + +void +XAAMoveOutOffscreenPixmap(PixmapPtr pPix) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + int width, height, devKind, bitsPerPixel; + PixmapPtr tmpPix; + unsigned char *data; + GCPtr pGC; + + width = pPix->drawable.width; + height = pPix->drawable.height; + bitsPerPixel = pPix->drawable.bitsPerPixel; + + devKind = BitmapBytePad(width * bitsPerPixel); + if(!(data = malloc(devKind * height))) + FatalError("Out of memory\n"); + + tmpPix = GetScratchPixmapHeader(pScreen, width, height, + pPix->drawable.depth, bitsPerPixel, devKind, data); + if(!tmpPix) { + free(data); + FatalError("Out of memory\n"); + } + + pGC = GetScratchGC(pPix->drawable.depth, pScreen); + ValidateGC((DrawablePtr)tmpPix, pGC); + + (*pGC->ops->CopyArea)((DrawablePtr)pPix, (DrawablePtr)tmpPix, + pGC, 0, 0, width, height, 0, 0); + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(tmpPix); + + pPix->drawable.x = 0; + pPix->drawable.y = 0; + pPix->devKind = devKind; + pPix->devPrivate.ptr = data; + pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER; + + pPriv->offscreenArea = NULL; + pPriv->freeData = TRUE; +} diff --git a/xorg-server/hw/xfree86/xaa/xaaOverlay.c b/xorg-server/hw/xfree86/xaa/xaaOverlay.c index 2956a3dbf..b7122a58f 100644 --- a/xorg-server/hw/xfree86/xaa/xaaOverlay.c +++ b/xorg-server/hw/xfree86/xaa/xaaOverlay.c @@ -1,129 +1,129 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "windowstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xaawrap.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "mioverlay.h" - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif - -static void -XAACopyWindow8_32( - WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc -){ - DDXPointPtr pptSrc, ppt; - RegionRec rgnDst; - BoxPtr pbox; - int dx, dy, nbox; - WindowPtr pwinRoot; - ScreenPtr pScreen = pWin->drawable.pScreen; - XAAInfoRecPtr infoRec = - GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); - Bool doUnderlay = miOverlayCopyUnderlay(pScreen); - RegionPtr borderClip = &pWin->borderClip; - Bool freeReg = FALSE; - - if (!infoRec->pScrn->vtSema || !infoRec->ScreenToScreenBitBlt || - (infoRec->ScreenToScreenBitBltFlags & NO_PLANEMASK)) - { - XAA_SCREEN_PROLOGUE (pScreen, CopyWindow); - if(infoRec->pScrn->vtSema && infoRec->NeedToSync) { - (*infoRec->Sync)(infoRec->pScrn); - infoRec->NeedToSync = FALSE; - } - (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); - XAA_SCREEN_EPILOGUE (pScreen, CopyWindow, XAACopyWindow8_32); - return; - } - - pwinRoot = WindowTable[pScreen->myNum]; - - if(doUnderlay) - freeReg = miOverlayCollectUnderlayRegions(pWin, &borderClip); - - REGION_NULL(pScreen, &rgnDst); - - dx = ptOldOrg.x - pWin->drawable.x; - dy = ptOldOrg.y - pWin->drawable.y; - REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); - REGION_INTERSECT(pScreen, &rgnDst, borderClip, prgnSrc); - - pbox = REGION_RECTS(&rgnDst); - nbox = REGION_NUM_RECTS(&rgnDst); - if(!nbox || - !(pptSrc = (DDXPointPtr )xalloc(nbox * sizeof(DDXPointRec)))) { - REGION_UNINIT(pScreen, &rgnDst); - return; - } - ppt = pptSrc; - - while(nbox--) { - ppt->x = pbox->x1 + dx; - ppt->y = pbox->y1 + dy; - ppt++; pbox++; - } - - infoRec->ScratchGC.planemask = doUnderlay ? 0x00ffffff : 0xff000000; - infoRec->ScratchGC.alu = GXcopy; - - XAADoBitBlt((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, - &(infoRec->ScratchGC), &rgnDst, pptSrc); - - xfree(pptSrc); - REGION_UNINIT(pScreen, &rgnDst); - if(freeReg) - REGION_DESTROY(pScreen, borderClip); -} - -static void -XAASetColorKey8_32( - ScreenPtr pScreen, - int nbox, - BoxPtr pbox -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - ScrnInfoPtr pScrn = infoRec->pScrn; - - /* I'm counting on writes being clipped away while switched away. - If this isn't going to be true then I need to be wrapping instead. */ - if(!infoRec->pScrn->vtSema) return; - - (*infoRec->FillSolidRects)(pScrn, pScrn->colorKey << 24, GXcopy, - 0xff000000, nbox, pbox); - - SET_SYNC_FLAG(infoRec); -} - -void -XAASetupOverlay8_32Planar(ScreenPtr pScreen) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - int i; - - pScreen->CopyWindow = XAACopyWindow8_32; - - if(!(infoRec->FillSolidRectsFlags & NO_PLANEMASK)) - miOverlaySetTransFunction(pScreen, XAASetColorKey8_32); - - infoRec->FullPlanemask = ~0; - for(i = 0; i < 32; i++) /* haven't thought about this much */ - infoRec->FullPlanemasks[i] = ~0; -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "mioverlay.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +static void +XAACopyWindow8_32( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc +){ + DDXPointPtr pptSrc, ppt; + RegionRec rgnDst; + BoxPtr pbox; + int dx, dy, nbox; + WindowPtr pwinRoot; + ScreenPtr pScreen = pWin->drawable.pScreen; + XAAInfoRecPtr infoRec = + GET_XAAINFORECPTR_FROM_DRAWABLE((&pWin->drawable)); + Bool doUnderlay = miOverlayCopyUnderlay(pScreen); + RegionPtr borderClip = &pWin->borderClip; + Bool freeReg = FALSE; + + if (!infoRec->pScrn->vtSema || !infoRec->ScreenToScreenBitBlt || + (infoRec->ScreenToScreenBitBltFlags & NO_PLANEMASK)) + { + XAA_SCREEN_PROLOGUE (pScreen, CopyWindow); + if(infoRec->pScrn->vtSema && infoRec->NeedToSync) { + (*infoRec->Sync)(infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + XAA_SCREEN_EPILOGUE (pScreen, CopyWindow, XAACopyWindow8_32); + return; + } + + pwinRoot = WindowTable[pScreen->myNum]; + + if(doUnderlay) + freeReg = miOverlayCollectUnderlayRegions(pWin, &borderClip); + + REGION_NULL(pScreen, &rgnDst); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + REGION_INTERSECT(pScreen, &rgnDst, borderClip, prgnSrc); + + pbox = REGION_RECTS(&rgnDst); + nbox = REGION_NUM_RECTS(&rgnDst); + if(!nbox || + !(pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec)))) { + REGION_UNINIT(pScreen, &rgnDst); + return; + } + ppt = pptSrc; + + while(nbox--) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + ppt++; pbox++; + } + + infoRec->ScratchGC.planemask = doUnderlay ? 0x00ffffff : 0xff000000; + infoRec->ScratchGC.alu = GXcopy; + + XAADoBitBlt((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + + free(pptSrc); + REGION_UNINIT(pScreen, &rgnDst); + if(freeReg) + REGION_DESTROY(pScreen, borderClip); +} + +static void +XAASetColorKey8_32( + ScreenPtr pScreen, + int nbox, + BoxPtr pbox +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + ScrnInfoPtr pScrn = infoRec->pScrn; + + /* I'm counting on writes being clipped away while switched away. + If this isn't going to be true then I need to be wrapping instead. */ + if(!infoRec->pScrn->vtSema) return; + + (*infoRec->FillSolidRects)(pScrn, pScrn->colorKey << 24, GXcopy, + 0xff000000, nbox, pbox); + + SET_SYNC_FLAG(infoRec); +} + +void +XAASetupOverlay8_32Planar(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + int i; + + pScreen->CopyWindow = XAACopyWindow8_32; + + if(!(infoRec->FillSolidRectsFlags & NO_PLANEMASK)) + miOverlaySetTransFunction(pScreen, XAASetColorKey8_32); + + infoRec->FullPlanemask = ~0; + for(i = 0; i < 32; i++) /* haven't thought about this much */ + infoRec->FullPlanemasks[i] = ~0; +} diff --git a/xorg-server/hw/xfree86/xaa/xaaOverlayDF.c b/xorg-server/hw/xfree86/xaa/xaaOverlayDF.c index 8db816e1e..4548935fd 100644 --- a/xorg-server/hw/xfree86/xaa/xaaOverlayDF.c +++ b/xorg-server/hw/xfree86/xaa/xaaOverlayDF.c @@ -1,1050 +1,1050 @@ -/* - Copyright (c) 1999 - The XFree86 Project Inc. - - Written by Mark Vojkovich -*/ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "xf86str.h" -#include "mi.h" -#include "miline.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xaawrap.h" -#include "servermd.h" - -/* Screen funcs */ - -static void XAAOverCopyWindow(WindowPtr, DDXPointRec, RegionPtr); -static void XAAOverWindowExposures(WindowPtr, RegionPtr, RegionPtr); - -static int XAAOverStippledFillChooser(GCPtr); -static int XAAOverOpaqueStippledFillChooser(GCPtr); -static int XAAOverTiledFillChooser(GCPtr); - -/* GC funcs */ - -static RegionPtr XAAOverCopyArea(DrawablePtr, DrawablePtr, GC *, - int, int, int, int, int, int); -static RegionPtr XAAOverCopyPlane(DrawablePtr, DrawablePtr, GCPtr, - int, int, int, int, int, int, unsigned long); -static void XAAOverPushPixelsSolid(GCPtr, PixmapPtr, DrawablePtr, int, - int, int, int); -static void XAAOverPolyFillRectSolid(DrawablePtr, GCPtr, int, xRectangle*); -static void XAAOverPolyFillRectStippled(DrawablePtr, GCPtr, int, xRectangle*); -static void XAAOverPolyFillRectOpaqueStippled(DrawablePtr, GCPtr, - int, xRectangle*); -static void XAAOverPolyFillRectTiled(DrawablePtr, GCPtr, int, xRectangle*); -static void XAAOverFillSpansSolid(DrawablePtr, GCPtr, int, DDXPointPtr, - int*, int); -static void XAAOverFillSpansStippled(DrawablePtr, GCPtr, int, DDXPointPtr, - int*, int); -static void XAAOverFillSpansOpaqueStippled(DrawablePtr, GCPtr, int, - DDXPointPtr, int*, int); -static void XAAOverFillSpansTiled(DrawablePtr, GCPtr, int, DDXPointPtr, - int*, int); -static int XAAOverPolyText8TE(DrawablePtr, GCPtr, int, int, int, char *); -static int XAAOverPolyText16TE(DrawablePtr, GCPtr, int, int, int, - unsigned short*); -static void XAAOverImageText8TE(DrawablePtr, GCPtr, int, int, int, char*); -static void XAAOverImageText16TE(DrawablePtr, GCPtr, int, int, int, - unsigned short*); -static void XAAOverImageGlyphBltTE(DrawablePtr, GCPtr, int, int, - unsigned int, CharInfoPtr*, pointer); -static void XAAOverPolyGlyphBltTE(DrawablePtr, GCPtr, int, int, - unsigned int, CharInfoPtr*, pointer); -static int XAAOverPolyText8NonTE(DrawablePtr, GCPtr, int, int, int, char*); -static int XAAOverPolyText16NonTE(DrawablePtr, GCPtr, int, int, int, - unsigned short*); -static void XAAOverImageText8NonTE(DrawablePtr, GCPtr, int, int, int, char*); -static void XAAOverImageText16NonTE(DrawablePtr, GCPtr, int, int, int, - unsigned short*); -static void XAAOverImageGlyphBltNonTE(DrawablePtr, GCPtr, int, int, - unsigned int, CharInfoPtr *, pointer); -static void XAAOverPolyGlyphBltNonTE(DrawablePtr, GCPtr, int, int, - unsigned int, CharInfoPtr *, pointer); -static void XAAOverPolyRectangleThinSolid(DrawablePtr, GCPtr, int, xRectangle*); -static void XAAOverPolylinesWideSolid(DrawablePtr, GCPtr, int, int, - DDXPointPtr); -static void XAAOverPolylinesThinSolid(DrawablePtr, GCPtr, int, int, - DDXPointPtr); -static void XAAOverPolySegmentThinSolid(DrawablePtr, GCPtr, int, xSegment*); -static void XAAOverPolylinesThinDashed(DrawablePtr, GCPtr, int, int, - DDXPointPtr); -static void XAAOverPolySegmentThinDashed(DrawablePtr, GCPtr, int, xSegment*); -static void XAAOverFillPolygonSolid(DrawablePtr, GCPtr, int, int, int, - DDXPointPtr); -static void XAAOverFillPolygonStippled(DrawablePtr, GCPtr, int, int, int, - DDXPointPtr); -static void XAAOverFillPolygonOpaqueStippled(DrawablePtr, GCPtr, int, int, int, - DDXPointPtr); -static void XAAOverFillPolygonTiled(DrawablePtr, GCPtr, int, int, int, - DDXPointPtr); -static void XAAOverPolyFillArcSolid(DrawablePtr, GCPtr, int, xArc*); -static void XAAOverPutImage(DrawablePtr, GCPtr, int, int, int, int, int, - int, int, char*); - - -typedef struct { - ScrnInfoPtr pScrn; - DepthChangeFuncPtr callback; - int currentDepth; -/* GC funcs */ - RegionPtr (*CopyArea)(DrawablePtr, DrawablePtr, GC *, - int, int, int, int, int, int); - RegionPtr (*CopyPlane)(DrawablePtr, DrawablePtr, GCPtr, - int, int, int, int, int, int, unsigned long); - void (*PushPixelsSolid)(GCPtr, PixmapPtr, DrawablePtr, int, int, int, int); - void (*PolyFillRectSolid)(DrawablePtr, GCPtr, int, xRectangle*); - void (*PolyFillRectStippled)(DrawablePtr, GCPtr, int, xRectangle*); - void (*PolyFillRectOpaqueStippled)(DrawablePtr, GCPtr, int, xRectangle*); - void (*PolyFillRectTiled)(DrawablePtr, GCPtr, int, xRectangle*); - void (*FillSpansSolid)(DrawablePtr, GCPtr, int, DDXPointPtr, int*, int); - void (*FillSpansStippled)(DrawablePtr, GCPtr, int, DDXPointPtr, int*, int); - void (*FillSpansOpaqueStippled)(DrawablePtr,GCPtr,int,DDXPointPtr,int*,int); - void (*FillSpansTiled)(DrawablePtr, GCPtr, int, DDXPointPtr, int*, int); - int (*PolyText8TE)(DrawablePtr, GCPtr, int, int, int, char *); - int (*PolyText16TE)(DrawablePtr, GCPtr, int, int, int, unsigned short*); - void (*ImageText8TE)(DrawablePtr, GCPtr, int, int, int, char*); - void (*ImageText16TE)(DrawablePtr, GCPtr, int, int, int, unsigned short*); - void (*ImageGlyphBltTE)(DrawablePtr, GCPtr, int, int, unsigned int, - CharInfoPtr*, pointer); - void (*PolyGlyphBltTE)(DrawablePtr, GCPtr, int, int, unsigned int, - CharInfoPtr*, pointer); - int (*PolyText8NonTE)(DrawablePtr, GCPtr, int, int, int, char*); - int (*PolyText16NonTE)(DrawablePtr, GCPtr, int, int, int, unsigned short*); - void (*ImageText8NonTE)(DrawablePtr, GCPtr, int, int, int, char*); - void (*ImageText16NonTE)(DrawablePtr, GCPtr, int, int, int, unsigned short*); - void (*ImageGlyphBltNonTE)(DrawablePtr, GCPtr, int, int, unsigned int, - CharInfoPtr *, pointer); - void (*PolyGlyphBltNonTE)(DrawablePtr, GCPtr, int, int, unsigned int, - CharInfoPtr *, pointer); - void (*PolyRectangleThinSolid)(DrawablePtr, GCPtr, int, xRectangle*); - void (*PolylinesWideSolid)(DrawablePtr, GCPtr, int, int, DDXPointPtr); - - void (*PolylinesThinSolid)(DrawablePtr, GCPtr, int, int, DDXPointPtr); - void (*PolySegmentThinSolid)(DrawablePtr, GCPtr, int, xSegment*); - void (*PolylinesThinDashed)(DrawablePtr, GCPtr, int, int, DDXPointPtr); - void (*PolySegmentThinDashed)(DrawablePtr, GCPtr, int, xSegment*); - void (*FillPolygonSolid)(DrawablePtr, GCPtr, int, int, int, DDXPointPtr); - void (*FillPolygonStippled)(DrawablePtr, GCPtr, int, int, int, DDXPointPtr); - void (*FillPolygonOpaqueStippled)(DrawablePtr, GCPtr, int, int, int, - DDXPointPtr); - void (*FillPolygonTiled)(DrawablePtr, GCPtr, int, int, int, DDXPointPtr); - void (*PolyFillArcSolid)(DrawablePtr, GCPtr, int, xArc*); - void (*PutImage)(DrawablePtr, GCPtr, int, int, int, int, int, int, - int, char*); - int (*StippledFillChooser)(GCPtr); - int (*OpaqueStippledFillChooser)(GCPtr); - int (*TiledFillChooser)(GCPtr); -} XAAOverlayRec, *XAAOverlayPtr; - -static int XAAOverlayKeyIndex; -static DevPrivateKey XAAOverlayKey = &XAAOverlayKeyIndex; - -#define GET_OVERLAY_PRIV(pScreen) \ - (XAAOverlayPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAOverlayKey) - -#define SWITCH_DEPTH(d) \ - if(pOverPriv->currentDepth != d) { \ - (*pOverPriv->callback)(pOverPriv->pScrn, d); \ - pOverPriv->currentDepth = d; \ - } - - -Bool -XAAInitDualFramebufferOverlay( - ScreenPtr pScreen, - DepthChangeFuncPtr callback -){ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAAOverlayPtr pOverPriv; - - if(!(pOverPriv = xalloc(sizeof(XAAOverlayRec)))) - return FALSE; - - dixSetPrivate(&pScreen->devPrivates, XAAOverlayKey, pOverPriv); - - pOverPriv->pScrn = pScrn; - pOverPriv->callback = callback; - pOverPriv->currentDepth = -1; - - /* Overwrite key screen functions. The XAA core will clean up */ - - pScreen->CopyWindow = XAAOverCopyWindow; - pScreen->WindowExposures = XAAOverWindowExposures; - - pOverPriv->StippledFillChooser = infoRec->StippledFillChooser; - pOverPriv->OpaqueStippledFillChooser = infoRec->OpaqueStippledFillChooser; - pOverPriv->TiledFillChooser = infoRec->TiledFillChooser; - - infoRec->StippledFillChooser = XAAOverStippledFillChooser; - infoRec->OpaqueStippledFillChooser = XAAOverOpaqueStippledFillChooser; - infoRec->TiledFillChooser = XAAOverTiledFillChooser; - - /* wrap all XAA GC rendering */ - - pOverPriv->CopyArea = infoRec->CopyArea; - pOverPriv->CopyPlane = infoRec->CopyPlane; - pOverPriv->PushPixelsSolid = infoRec->PushPixelsSolid; - pOverPriv->PolyFillRectSolid = infoRec->PolyFillRectSolid; - pOverPriv->PolyFillRectStippled = infoRec->PolyFillRectStippled; - pOverPriv->PolyFillRectOpaqueStippled = infoRec->PolyFillRectOpaqueStippled; - pOverPriv->PolyFillRectTiled = infoRec->PolyFillRectTiled; - pOverPriv->FillSpansSolid = infoRec->FillSpansSolid; - pOverPriv->FillSpansStippled = infoRec->FillSpansStippled; - pOverPriv->FillSpansOpaqueStippled = infoRec->FillSpansOpaqueStippled; - pOverPriv->FillSpansTiled = infoRec->FillSpansTiled; - pOverPriv->PolyText8TE = infoRec->PolyText8TE; - pOverPriv->PolyText16TE = infoRec->PolyText16TE; - pOverPriv->ImageText8TE = infoRec->ImageText8TE; - pOverPriv->ImageText16TE = infoRec->ImageText16TE; - pOverPriv->ImageGlyphBltTE = infoRec->ImageGlyphBltTE; - pOverPriv->PolyGlyphBltTE = infoRec->PolyGlyphBltTE; - pOverPriv->PolyText8NonTE = infoRec->PolyText8NonTE; - pOverPriv->PolyText16NonTE = infoRec->PolyText16NonTE; - pOverPriv->ImageText8NonTE = infoRec->ImageText8NonTE; - pOverPriv->ImageText16NonTE = infoRec->ImageText16NonTE; - pOverPriv->ImageGlyphBltNonTE = infoRec->ImageGlyphBltNonTE; - pOverPriv->PolyGlyphBltNonTE = infoRec->PolyGlyphBltNonTE; - pOverPriv->PolyRectangleThinSolid = infoRec->PolyRectangleThinSolid; - pOverPriv->PolylinesWideSolid = infoRec->PolylinesWideSolid; - pOverPriv->PolylinesThinSolid = infoRec->PolylinesThinSolid; - pOverPriv->PolySegmentThinSolid = infoRec->PolySegmentThinSolid; - pOverPriv->PolylinesThinDashed = infoRec->PolylinesThinDashed; - pOverPriv->PolySegmentThinDashed = infoRec->PolySegmentThinDashed; - pOverPriv->FillPolygonSolid = infoRec->FillPolygonSolid; - pOverPriv->FillPolygonStippled = infoRec->FillPolygonStippled; - pOverPriv->FillPolygonOpaqueStippled = infoRec->FillPolygonOpaqueStippled; - pOverPriv->FillPolygonTiled = infoRec->FillPolygonTiled; - pOverPriv->PolyFillArcSolid = infoRec->PolyFillArcSolid; - pOverPriv->PutImage = infoRec->PutImage; - - - if(infoRec->CopyArea) - infoRec->CopyArea = XAAOverCopyArea; - if(infoRec->CopyPlane) - infoRec->CopyPlane = XAAOverCopyPlane; - if(infoRec->PushPixelsSolid) - infoRec->PushPixelsSolid = XAAOverPushPixelsSolid; - if(infoRec->PolyFillRectSolid) - infoRec->PolyFillRectSolid = XAAOverPolyFillRectSolid; - if(infoRec->PolyFillRectStippled) - infoRec->PolyFillRectStippled = XAAOverPolyFillRectStippled; - if(infoRec->PolyFillRectOpaqueStippled) - infoRec->PolyFillRectOpaqueStippled = XAAOverPolyFillRectOpaqueStippled; - if(infoRec->PolyFillRectTiled) - infoRec->PolyFillRectTiled = XAAOverPolyFillRectTiled; - if(infoRec->FillSpansSolid) - infoRec->FillSpansSolid = XAAOverFillSpansSolid; - if(infoRec->FillSpansStippled) - infoRec->FillSpansStippled = XAAOverFillSpansStippled; - if(infoRec->FillSpansOpaqueStippled) - infoRec->FillSpansOpaqueStippled = XAAOverFillSpansOpaqueStippled; - if(infoRec->FillSpansTiled) - infoRec->FillSpansTiled = XAAOverFillSpansTiled; - if(infoRec->PolyText8TE) - infoRec->PolyText8TE = XAAOverPolyText8TE; - if(infoRec->PolyText16TE) - infoRec->PolyText16TE = XAAOverPolyText16TE; - if(infoRec->ImageText8TE) - infoRec->ImageText8TE = XAAOverImageText8TE; - if(infoRec->ImageText16TE) - infoRec->ImageText16TE = XAAOverImageText16TE; - if(infoRec->ImageGlyphBltTE) - infoRec->ImageGlyphBltTE = XAAOverImageGlyphBltTE; - if(infoRec->PolyGlyphBltTE) - infoRec->PolyGlyphBltTE = XAAOverPolyGlyphBltTE; - if(infoRec->PolyText8NonTE) - infoRec->PolyText8NonTE = XAAOverPolyText8NonTE; - if(infoRec->PolyText16NonTE) - infoRec->PolyText16NonTE = XAAOverPolyText16NonTE; - if(infoRec->ImageText8NonTE) - infoRec->ImageText8NonTE = XAAOverImageText8NonTE; - if(infoRec->ImageText16NonTE) - infoRec->ImageText16NonTE = XAAOverImageText16NonTE; - if(infoRec->ImageGlyphBltNonTE) - infoRec->ImageGlyphBltNonTE = XAAOverImageGlyphBltNonTE; - if(infoRec->PolyGlyphBltNonTE) - infoRec->PolyGlyphBltNonTE = XAAOverPolyGlyphBltNonTE; - if(infoRec->PolyRectangleThinSolid) - infoRec->PolyRectangleThinSolid = XAAOverPolyRectangleThinSolid; - if(infoRec->PolylinesWideSolid) - infoRec->PolylinesWideSolid = XAAOverPolylinesWideSolid; - if(infoRec->PolylinesThinSolid) - infoRec->PolylinesThinSolid = XAAOverPolylinesThinSolid; - if(infoRec->PolySegmentThinSolid) - infoRec->PolySegmentThinSolid = XAAOverPolySegmentThinSolid; - if(infoRec->PolylinesThinDashed) - infoRec->PolylinesThinDashed = XAAOverPolylinesThinDashed; - if(infoRec->PolySegmentThinDashed) - infoRec->PolySegmentThinDashed = XAAOverPolySegmentThinDashed; - if(infoRec->FillPolygonSolid) - infoRec->FillPolygonSolid = XAAOverFillPolygonSolid; - if(infoRec->FillPolygonStippled) - infoRec->FillPolygonStippled = XAAOverFillPolygonStippled; - if(infoRec->FillPolygonOpaqueStippled) - infoRec->FillPolygonOpaqueStippled = XAAOverFillPolygonOpaqueStippled; - if(infoRec->FillPolygonTiled) - infoRec->FillPolygonTiled = XAAOverFillPolygonTiled; - if(infoRec->PolyFillArcSolid) - infoRec->PolyFillArcSolid = XAAOverPolyFillArcSolid; - if(infoRec->PutImage) - infoRec->PutImage = XAAOverPutImage; - - return TRUE; -} - -/*********************** Screen functions ************************/ - -void -XAAOverCopyWindow( - WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc -){ - ScreenPtr pScreen = pWin->drawable.pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen); - ScrnInfoPtr pScrn = infoRec->pScrn; - DDXPointPtr ppt, pptSrc; - RegionRec rgnDst; - BoxPtr pbox; - int i, nbox, dx, dy; - WindowPtr pRoot = WindowTable[pScreen->myNum]; - - - if (!pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { - XAA_SCREEN_PROLOGUE (pScreen, CopyWindow); - if(pScrn->vtSema && infoRec->NeedToSync) { - (*infoRec->Sync)(pScrn); - infoRec->NeedToSync = FALSE; - } - (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); - XAA_SCREEN_EPILOGUE (pScreen, CopyWindow, XAAOverCopyWindow); - return; - } - - infoRec->ScratchGC.alu = GXcopy; - infoRec->ScratchGC.planemask = ~0; - - REGION_NULL(pScreen, &rgnDst); - - dx = ptOldOrg.x - pWin->drawable.x; - dy = ptOldOrg.y - pWin->drawable.y; - REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); - REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); - - nbox = REGION_NUM_RECTS(&rgnDst); - if(nbox && - (pptSrc = (DDXPointPtr )xalloc(nbox * sizeof(DDXPointRec)))) { - - pbox = REGION_RECTS(&rgnDst); - for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { - ppt->x = pbox->x1 + dx; - ppt->y = pbox->y1 + dy; - } - - SWITCH_DEPTH(8); - XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, - &(infoRec->ScratchGC), &rgnDst, pptSrc); - - if(pWin->drawable.bitsPerPixel != 8) { - SWITCH_DEPTH(pScrn->depth); - XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, - &(infoRec->ScratchGC), &rgnDst, pptSrc); - } - - xfree(pptSrc); - } - - REGION_UNINIT(pScreen, &rgnDst); - - if(pWin->drawable.depth == 8) { - REGION_NULL(pScreen, &rgnDst); - miSegregateChildren(pWin, &rgnDst, pScrn->depth); - if(REGION_NOTEMPTY(pScreen, &rgnDst)) { - REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, prgnSrc); - nbox = REGION_NUM_RECTS(&rgnDst); - if(nbox && - (pptSrc = (DDXPointPtr )xalloc(nbox * sizeof(DDXPointRec)))){ - - pbox = REGION_RECTS(&rgnDst); - for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { - ppt->x = pbox->x1 + dx; - ppt->y = pbox->y1 + dy; - } - - SWITCH_DEPTH(pScrn->depth); - XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, - &(infoRec->ScratchGC), &rgnDst, pptSrc); - xfree(pptSrc); - } - } - REGION_UNINIT(pScreen, &rgnDst); - } -} - - -void -XAAOverWindowExposures( - WindowPtr pWin, - RegionPtr pReg, - RegionPtr pOtherReg -){ - ScreenPtr pScreen = pWin->drawable.pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - - if((pWin->drawable.bitsPerPixel != 8) && infoRec->pScrn->vtSema) { - if(REGION_NUM_RECTS(pReg) && infoRec->FillSolidRects) { - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen); - - SWITCH_DEPTH(8); - (*infoRec->FillSolidRects)(infoRec->pScrn, - infoRec->pScrn->colorKey, GXcopy, ~0, - REGION_NUM_RECTS(pReg), REGION_RECTS(pReg)); - miWindowExposures(pWin, pReg, pOtherReg); - return; - } else if(infoRec->NeedToSync) { - (*infoRec->Sync)(infoRec->pScrn); - infoRec->NeedToSync = FALSE; - } - } - - XAA_SCREEN_PROLOGUE (pScreen, WindowExposures); - (*pScreen->WindowExposures) (pWin, pReg, pOtherReg); - XAA_SCREEN_EPILOGUE(pScreen, WindowExposures, XAAOverWindowExposures); -} - -/********************* Choosers *************************/ - -static int -XAAOverStippledFillChooser(GCPtr pGC) -{ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - int ret; - - ret = (*pOverPriv->StippledFillChooser)(pGC); - - if((pGC->depth == 8) && - ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { - ret = 0; - } - - return ret; -} - -static int -XAAOverOpaqueStippledFillChooser(GCPtr pGC) -{ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - int ret; - - ret = (*pOverPriv->OpaqueStippledFillChooser)(pGC); - - if((pGC->depth == 8) && - ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { - ret = 0; - } - - return ret; -} - -static int -XAAOverTiledFillChooser(GCPtr pGC) -{ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - int ret; - - ret = (*pOverPriv->TiledFillChooser)(pGC); - - if((pGC->depth == 8) && - ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { - ret = 0; - } - - return ret; -} - - -/**************************** GC Functions **************************/ - -static RegionPtr -XAAOverCopyArea( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - return (*pOverPriv->CopyArea)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty); -} - -static RegionPtr -XAAOverCopyPlane( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, int srcy, - int width, int height, - int dstx, int dsty, - unsigned long bitPlane -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - return (*pOverPriv->CopyPlane)(pSrc, pDst, - pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); - -} - -static void -XAAOverPushPixelsSolid( - GCPtr pGC, - PixmapPtr pBitMap, - DrawablePtr pDraw, - int dx, int dy, - int xOrg, int yOrg -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PushPixelsSolid)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); -} - - - -static void -XAAOverPolyFillRectSolid( - DrawablePtr pDraw, - GCPtr pGC, - int nrectFill, - xRectangle *prectInit -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolyFillRectSolid)(pDraw, pGC, nrectFill, prectInit); -} - -static void -XAAOverPolyFillRectStippled( - DrawablePtr pDraw, - GCPtr pGC, - int nrectFill, - xRectangle *prectInit -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolyFillRectStippled)(pDraw, pGC, nrectFill, prectInit); -} - - -static void -XAAOverPolyFillRectOpaqueStippled( - DrawablePtr pDraw, - GCPtr pGC, - int nrectFill, - xRectangle *prectInit -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolyFillRectOpaqueStippled)(pDraw, pGC, nrectFill, prectInit); -} - -static void -XAAOverPolyFillRectTiled( - DrawablePtr pDraw, - GCPtr pGC, - int nrectFill, - xRectangle *prectInit -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolyFillRectTiled)(pDraw, pGC, nrectFill, prectInit); -} - - -static void -XAAOverFillSpansSolid( - DrawablePtr pDraw, - GCPtr pGC, - int nInit, - DDXPointPtr ppt, - int *pwidth, - int fSorted -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->FillSpansSolid)( - pDraw, pGC, nInit, ppt, pwidth, fSorted); -} - - -static void -XAAOverFillSpansStippled( - DrawablePtr pDraw, - GCPtr pGC, - int nInit, - DDXPointPtr ppt, - int *pwidth, - int fSorted -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->FillSpansStippled)(pDraw, pGC, nInit, ppt, pwidth, fSorted); -} - -static void -XAAOverFillSpansOpaqueStippled( - DrawablePtr pDraw, - GCPtr pGC, - int nInit, - DDXPointPtr ppt, - int *pwidth, - int fSorted -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->FillSpansOpaqueStippled)( - pDraw, pGC, nInit, ppt, pwidth, fSorted); -} - - -static void -XAAOverFillSpansTiled( - DrawablePtr pDraw, - GCPtr pGC, - int nInit, - DDXPointPtr ppt, - int *pwidth, - int fSorted -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->FillSpansTiled)(pDraw, pGC, nInit, ppt, pwidth, fSorted); -} - -static int -XAAOverPolyText8TE( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - return (*pOverPriv->PolyText8TE)(pDraw, pGC, x, y, count, chars); -} - - -static int -XAAOverPolyText16TE( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - return (*pOverPriv->PolyText16TE)(pDraw, pGC, x, y, count, chars); -} - - -static void -XAAOverImageText8TE( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->ImageText8TE)(pDraw, pGC, x, y, count, chars); -} - - -static void -XAAOverImageText16TE( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->ImageText16TE)(pDraw, pGC, x, y, count, chars); -} - -static void -XAAOverImageGlyphBltTE( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->ImageGlyphBltTE)( - pDraw, pGC, xInit, yInit, nglyph, ppci, pglyphBase); -} - -static void -XAAOverPolyGlyphBltTE( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolyGlyphBltTE)( - pDraw, pGC, xInit, yInit, nglyph, ppci, pglyphBase); -} - -static int -XAAOverPolyText8NonTE( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - return (*pOverPriv->PolyText8NonTE)(pDraw, pGC, x, y, count, chars); -} - - -static int -XAAOverPolyText16NonTE( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - return (*pOverPriv->PolyText16NonTE)(pDraw, pGC, x, y, count, chars); -} - -static void -XAAOverImageText8NonTE( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->ImageText8NonTE)(pDraw, pGC, x, y, count, chars); -} - -static void -XAAOverImageText16NonTE( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->ImageText16NonTE)(pDraw, pGC, x, y, count, chars); -} - - -static void -XAAOverImageGlyphBltNonTE( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->ImageGlyphBltNonTE)( - pDraw, pGC, xInit, yInit, nglyph, ppci, pglyphBase); -} - -static void -XAAOverPolyGlyphBltNonTE( - DrawablePtr pDraw, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolyGlyphBltNonTE)( - pDraw, pGC, xInit, yInit, nglyph, ppci, pglyphBase); -} - -static void -XAAOverPolyRectangleThinSolid( - DrawablePtr pDraw, - GCPtr pGC, - int nRectsInit, - xRectangle *pRectsInit -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolyRectangleThinSolid)(pDraw, pGC, nRectsInit, pRectsInit); -} - - - -static void -XAAOverPolylinesWideSolid( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr pPts -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolylinesWideSolid)(pDraw, pGC, mode, npt, pPts); -} - - -static void -XAAOverPolylinesThinSolid( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr pPts -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolylinesThinSolid)(pDraw, pGC, mode, npt, pPts); -} - -static void -XAAOverPolySegmentThinSolid( - DrawablePtr pDraw, - GCPtr pGC, - int nseg, - xSegment *pSeg -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolySegmentThinSolid)(pDraw, pGC, nseg, pSeg); -} - -static void -XAAOverPolylinesThinDashed( - DrawablePtr pDraw, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr pPts -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolylinesThinDashed)(pDraw, pGC, mode, npt, pPts); -} - -static void -XAAOverPolySegmentThinDashed( - DrawablePtr pDraw, - GCPtr pGC, - int nseg, - xSegment *pSeg -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolySegmentThinDashed)(pDraw, pGC, nseg, pSeg); -} - - -static void -XAAOverFillPolygonSolid( - DrawablePtr pDraw, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->FillPolygonSolid)(pDraw, pGC, shape, mode, count, ptsIn); -} - -static void -XAAOverFillPolygonStippled( - DrawablePtr pDraw, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->FillPolygonStippled)(pDraw, pGC, shape, mode, count, ptsIn); -} - - -static void -XAAOverFillPolygonOpaqueStippled( - DrawablePtr pDraw, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->FillPolygonOpaqueStippled)( - pDraw, pGC, shape, mode, count, ptsIn); -} - -static void -XAAOverFillPolygonTiled( - DrawablePtr pDraw, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->FillPolygonTiled)(pDraw, pGC, shape, mode, count, ptsIn); -} - - -static void -XAAOverPolyFillArcSolid( - DrawablePtr pDraw, - GCPtr pGC, - int narcs, - xArc *parcs -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PolyFillArcSolid)(pDraw, pGC, narcs, parcs); -} - - -static void -XAAOverPutImage( - DrawablePtr pDraw, - GCPtr pGC, - int depth, - int x, - int y, - int w, - int h, - int leftPad, - int format, - char *pImage -){ - XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); - - SWITCH_DEPTH(pGC->depth); - - (*pOverPriv->PutImage)(pDraw, pGC, depth, x, y, w, h, - leftPad, format, pImage); -} - +/* + Copyright (c) 1999 - The XFree86 Project Inc. + + Written by Mark Vojkovich +*/ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miline.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "servermd.h" + +/* Screen funcs */ + +static void XAAOverCopyWindow(WindowPtr, DDXPointRec, RegionPtr); +static void XAAOverWindowExposures(WindowPtr, RegionPtr, RegionPtr); + +static int XAAOverStippledFillChooser(GCPtr); +static int XAAOverOpaqueStippledFillChooser(GCPtr); +static int XAAOverTiledFillChooser(GCPtr); + +/* GC funcs */ + +static RegionPtr XAAOverCopyArea(DrawablePtr, DrawablePtr, GC *, + int, int, int, int, int, int); +static RegionPtr XAAOverCopyPlane(DrawablePtr, DrawablePtr, GCPtr, + int, int, int, int, int, int, unsigned long); +static void XAAOverPushPixelsSolid(GCPtr, PixmapPtr, DrawablePtr, int, + int, int, int); +static void XAAOverPolyFillRectSolid(DrawablePtr, GCPtr, int, xRectangle*); +static void XAAOverPolyFillRectStippled(DrawablePtr, GCPtr, int, xRectangle*); +static void XAAOverPolyFillRectOpaqueStippled(DrawablePtr, GCPtr, + int, xRectangle*); +static void XAAOverPolyFillRectTiled(DrawablePtr, GCPtr, int, xRectangle*); +static void XAAOverFillSpansSolid(DrawablePtr, GCPtr, int, DDXPointPtr, + int*, int); +static void XAAOverFillSpansStippled(DrawablePtr, GCPtr, int, DDXPointPtr, + int*, int); +static void XAAOverFillSpansOpaqueStippled(DrawablePtr, GCPtr, int, + DDXPointPtr, int*, int); +static void XAAOverFillSpansTiled(DrawablePtr, GCPtr, int, DDXPointPtr, + int*, int); +static int XAAOverPolyText8TE(DrawablePtr, GCPtr, int, int, int, char *); +static int XAAOverPolyText16TE(DrawablePtr, GCPtr, int, int, int, + unsigned short*); +static void XAAOverImageText8TE(DrawablePtr, GCPtr, int, int, int, char*); +static void XAAOverImageText16TE(DrawablePtr, GCPtr, int, int, int, + unsigned short*); +static void XAAOverImageGlyphBltTE(DrawablePtr, GCPtr, int, int, + unsigned int, CharInfoPtr*, pointer); +static void XAAOverPolyGlyphBltTE(DrawablePtr, GCPtr, int, int, + unsigned int, CharInfoPtr*, pointer); +static int XAAOverPolyText8NonTE(DrawablePtr, GCPtr, int, int, int, char*); +static int XAAOverPolyText16NonTE(DrawablePtr, GCPtr, int, int, int, + unsigned short*); +static void XAAOverImageText8NonTE(DrawablePtr, GCPtr, int, int, int, char*); +static void XAAOverImageText16NonTE(DrawablePtr, GCPtr, int, int, int, + unsigned short*); +static void XAAOverImageGlyphBltNonTE(DrawablePtr, GCPtr, int, int, + unsigned int, CharInfoPtr *, pointer); +static void XAAOverPolyGlyphBltNonTE(DrawablePtr, GCPtr, int, int, + unsigned int, CharInfoPtr *, pointer); +static void XAAOverPolyRectangleThinSolid(DrawablePtr, GCPtr, int, xRectangle*); +static void XAAOverPolylinesWideSolid(DrawablePtr, GCPtr, int, int, + DDXPointPtr); +static void XAAOverPolylinesThinSolid(DrawablePtr, GCPtr, int, int, + DDXPointPtr); +static void XAAOverPolySegmentThinSolid(DrawablePtr, GCPtr, int, xSegment*); +static void XAAOverPolylinesThinDashed(DrawablePtr, GCPtr, int, int, + DDXPointPtr); +static void XAAOverPolySegmentThinDashed(DrawablePtr, GCPtr, int, xSegment*); +static void XAAOverFillPolygonSolid(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); +static void XAAOverFillPolygonStippled(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); +static void XAAOverFillPolygonOpaqueStippled(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); +static void XAAOverFillPolygonTiled(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); +static void XAAOverPolyFillArcSolid(DrawablePtr, GCPtr, int, xArc*); +static void XAAOverPutImage(DrawablePtr, GCPtr, int, int, int, int, int, + int, int, char*); + + +typedef struct { + ScrnInfoPtr pScrn; + DepthChangeFuncPtr callback; + int currentDepth; +/* GC funcs */ + RegionPtr (*CopyArea)(DrawablePtr, DrawablePtr, GC *, + int, int, int, int, int, int); + RegionPtr (*CopyPlane)(DrawablePtr, DrawablePtr, GCPtr, + int, int, int, int, int, int, unsigned long); + void (*PushPixelsSolid)(GCPtr, PixmapPtr, DrawablePtr, int, int, int, int); + void (*PolyFillRectSolid)(DrawablePtr, GCPtr, int, xRectangle*); + void (*PolyFillRectStippled)(DrawablePtr, GCPtr, int, xRectangle*); + void (*PolyFillRectOpaqueStippled)(DrawablePtr, GCPtr, int, xRectangle*); + void (*PolyFillRectTiled)(DrawablePtr, GCPtr, int, xRectangle*); + void (*FillSpansSolid)(DrawablePtr, GCPtr, int, DDXPointPtr, int*, int); + void (*FillSpansStippled)(DrawablePtr, GCPtr, int, DDXPointPtr, int*, int); + void (*FillSpansOpaqueStippled)(DrawablePtr,GCPtr,int,DDXPointPtr,int*,int); + void (*FillSpansTiled)(DrawablePtr, GCPtr, int, DDXPointPtr, int*, int); + int (*PolyText8TE)(DrawablePtr, GCPtr, int, int, int, char *); + int (*PolyText16TE)(DrawablePtr, GCPtr, int, int, int, unsigned short*); + void (*ImageText8TE)(DrawablePtr, GCPtr, int, int, int, char*); + void (*ImageText16TE)(DrawablePtr, GCPtr, int, int, int, unsigned short*); + void (*ImageGlyphBltTE)(DrawablePtr, GCPtr, int, int, unsigned int, + CharInfoPtr*, pointer); + void (*PolyGlyphBltTE)(DrawablePtr, GCPtr, int, int, unsigned int, + CharInfoPtr*, pointer); + int (*PolyText8NonTE)(DrawablePtr, GCPtr, int, int, int, char*); + int (*PolyText16NonTE)(DrawablePtr, GCPtr, int, int, int, unsigned short*); + void (*ImageText8NonTE)(DrawablePtr, GCPtr, int, int, int, char*); + void (*ImageText16NonTE)(DrawablePtr, GCPtr, int, int, int, unsigned short*); + void (*ImageGlyphBltNonTE)(DrawablePtr, GCPtr, int, int, unsigned int, + CharInfoPtr *, pointer); + void (*PolyGlyphBltNonTE)(DrawablePtr, GCPtr, int, int, unsigned int, + CharInfoPtr *, pointer); + void (*PolyRectangleThinSolid)(DrawablePtr, GCPtr, int, xRectangle*); + void (*PolylinesWideSolid)(DrawablePtr, GCPtr, int, int, DDXPointPtr); + + void (*PolylinesThinSolid)(DrawablePtr, GCPtr, int, int, DDXPointPtr); + void (*PolySegmentThinSolid)(DrawablePtr, GCPtr, int, xSegment*); + void (*PolylinesThinDashed)(DrawablePtr, GCPtr, int, int, DDXPointPtr); + void (*PolySegmentThinDashed)(DrawablePtr, GCPtr, int, xSegment*); + void (*FillPolygonSolid)(DrawablePtr, GCPtr, int, int, int, DDXPointPtr); + void (*FillPolygonStippled)(DrawablePtr, GCPtr, int, int, int, DDXPointPtr); + void (*FillPolygonOpaqueStippled)(DrawablePtr, GCPtr, int, int, int, + DDXPointPtr); + void (*FillPolygonTiled)(DrawablePtr, GCPtr, int, int, int, DDXPointPtr); + void (*PolyFillArcSolid)(DrawablePtr, GCPtr, int, xArc*); + void (*PutImage)(DrawablePtr, GCPtr, int, int, int, int, int, int, + int, char*); + int (*StippledFillChooser)(GCPtr); + int (*OpaqueStippledFillChooser)(GCPtr); + int (*TiledFillChooser)(GCPtr); +} XAAOverlayRec, *XAAOverlayPtr; + +static int XAAOverlayKeyIndex; +static DevPrivateKey XAAOverlayKey = &XAAOverlayKeyIndex; + +#define GET_OVERLAY_PRIV(pScreen) \ + (XAAOverlayPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAOverlayKey) + +#define SWITCH_DEPTH(d) \ + if(pOverPriv->currentDepth != d) { \ + (*pOverPriv->callback)(pOverPriv->pScrn, d); \ + pOverPriv->currentDepth = d; \ + } + + +Bool +XAAInitDualFramebufferOverlay( + ScreenPtr pScreen, + DepthChangeFuncPtr callback +){ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAOverlayPtr pOverPriv; + + if(!(pOverPriv = malloc(sizeof(XAAOverlayRec)))) + return FALSE; + + dixSetPrivate(&pScreen->devPrivates, XAAOverlayKey, pOverPriv); + + pOverPriv->pScrn = pScrn; + pOverPriv->callback = callback; + pOverPriv->currentDepth = -1; + + /* Overwrite key screen functions. The XAA core will clean up */ + + pScreen->CopyWindow = XAAOverCopyWindow; + pScreen->WindowExposures = XAAOverWindowExposures; + + pOverPriv->StippledFillChooser = infoRec->StippledFillChooser; + pOverPriv->OpaqueStippledFillChooser = infoRec->OpaqueStippledFillChooser; + pOverPriv->TiledFillChooser = infoRec->TiledFillChooser; + + infoRec->StippledFillChooser = XAAOverStippledFillChooser; + infoRec->OpaqueStippledFillChooser = XAAOverOpaqueStippledFillChooser; + infoRec->TiledFillChooser = XAAOverTiledFillChooser; + + /* wrap all XAA GC rendering */ + + pOverPriv->CopyArea = infoRec->CopyArea; + pOverPriv->CopyPlane = infoRec->CopyPlane; + pOverPriv->PushPixelsSolid = infoRec->PushPixelsSolid; + pOverPriv->PolyFillRectSolid = infoRec->PolyFillRectSolid; + pOverPriv->PolyFillRectStippled = infoRec->PolyFillRectStippled; + pOverPriv->PolyFillRectOpaqueStippled = infoRec->PolyFillRectOpaqueStippled; + pOverPriv->PolyFillRectTiled = infoRec->PolyFillRectTiled; + pOverPriv->FillSpansSolid = infoRec->FillSpansSolid; + pOverPriv->FillSpansStippled = infoRec->FillSpansStippled; + pOverPriv->FillSpansOpaqueStippled = infoRec->FillSpansOpaqueStippled; + pOverPriv->FillSpansTiled = infoRec->FillSpansTiled; + pOverPriv->PolyText8TE = infoRec->PolyText8TE; + pOverPriv->PolyText16TE = infoRec->PolyText16TE; + pOverPriv->ImageText8TE = infoRec->ImageText8TE; + pOverPriv->ImageText16TE = infoRec->ImageText16TE; + pOverPriv->ImageGlyphBltTE = infoRec->ImageGlyphBltTE; + pOverPriv->PolyGlyphBltTE = infoRec->PolyGlyphBltTE; + pOverPriv->PolyText8NonTE = infoRec->PolyText8NonTE; + pOverPriv->PolyText16NonTE = infoRec->PolyText16NonTE; + pOverPriv->ImageText8NonTE = infoRec->ImageText8NonTE; + pOverPriv->ImageText16NonTE = infoRec->ImageText16NonTE; + pOverPriv->ImageGlyphBltNonTE = infoRec->ImageGlyphBltNonTE; + pOverPriv->PolyGlyphBltNonTE = infoRec->PolyGlyphBltNonTE; + pOverPriv->PolyRectangleThinSolid = infoRec->PolyRectangleThinSolid; + pOverPriv->PolylinesWideSolid = infoRec->PolylinesWideSolid; + pOverPriv->PolylinesThinSolid = infoRec->PolylinesThinSolid; + pOverPriv->PolySegmentThinSolid = infoRec->PolySegmentThinSolid; + pOverPriv->PolylinesThinDashed = infoRec->PolylinesThinDashed; + pOverPriv->PolySegmentThinDashed = infoRec->PolySegmentThinDashed; + pOverPriv->FillPolygonSolid = infoRec->FillPolygonSolid; + pOverPriv->FillPolygonStippled = infoRec->FillPolygonStippled; + pOverPriv->FillPolygonOpaqueStippled = infoRec->FillPolygonOpaqueStippled; + pOverPriv->FillPolygonTiled = infoRec->FillPolygonTiled; + pOverPriv->PolyFillArcSolid = infoRec->PolyFillArcSolid; + pOverPriv->PutImage = infoRec->PutImage; + + + if(infoRec->CopyArea) + infoRec->CopyArea = XAAOverCopyArea; + if(infoRec->CopyPlane) + infoRec->CopyPlane = XAAOverCopyPlane; + if(infoRec->PushPixelsSolid) + infoRec->PushPixelsSolid = XAAOverPushPixelsSolid; + if(infoRec->PolyFillRectSolid) + infoRec->PolyFillRectSolid = XAAOverPolyFillRectSolid; + if(infoRec->PolyFillRectStippled) + infoRec->PolyFillRectStippled = XAAOverPolyFillRectStippled; + if(infoRec->PolyFillRectOpaqueStippled) + infoRec->PolyFillRectOpaqueStippled = XAAOverPolyFillRectOpaqueStippled; + if(infoRec->PolyFillRectTiled) + infoRec->PolyFillRectTiled = XAAOverPolyFillRectTiled; + if(infoRec->FillSpansSolid) + infoRec->FillSpansSolid = XAAOverFillSpansSolid; + if(infoRec->FillSpansStippled) + infoRec->FillSpansStippled = XAAOverFillSpansStippled; + if(infoRec->FillSpansOpaqueStippled) + infoRec->FillSpansOpaqueStippled = XAAOverFillSpansOpaqueStippled; + if(infoRec->FillSpansTiled) + infoRec->FillSpansTiled = XAAOverFillSpansTiled; + if(infoRec->PolyText8TE) + infoRec->PolyText8TE = XAAOverPolyText8TE; + if(infoRec->PolyText16TE) + infoRec->PolyText16TE = XAAOverPolyText16TE; + if(infoRec->ImageText8TE) + infoRec->ImageText8TE = XAAOverImageText8TE; + if(infoRec->ImageText16TE) + infoRec->ImageText16TE = XAAOverImageText16TE; + if(infoRec->ImageGlyphBltTE) + infoRec->ImageGlyphBltTE = XAAOverImageGlyphBltTE; + if(infoRec->PolyGlyphBltTE) + infoRec->PolyGlyphBltTE = XAAOverPolyGlyphBltTE; + if(infoRec->PolyText8NonTE) + infoRec->PolyText8NonTE = XAAOverPolyText8NonTE; + if(infoRec->PolyText16NonTE) + infoRec->PolyText16NonTE = XAAOverPolyText16NonTE; + if(infoRec->ImageText8NonTE) + infoRec->ImageText8NonTE = XAAOverImageText8NonTE; + if(infoRec->ImageText16NonTE) + infoRec->ImageText16NonTE = XAAOverImageText16NonTE; + if(infoRec->ImageGlyphBltNonTE) + infoRec->ImageGlyphBltNonTE = XAAOverImageGlyphBltNonTE; + if(infoRec->PolyGlyphBltNonTE) + infoRec->PolyGlyphBltNonTE = XAAOverPolyGlyphBltNonTE; + if(infoRec->PolyRectangleThinSolid) + infoRec->PolyRectangleThinSolid = XAAOverPolyRectangleThinSolid; + if(infoRec->PolylinesWideSolid) + infoRec->PolylinesWideSolid = XAAOverPolylinesWideSolid; + if(infoRec->PolylinesThinSolid) + infoRec->PolylinesThinSolid = XAAOverPolylinesThinSolid; + if(infoRec->PolySegmentThinSolid) + infoRec->PolySegmentThinSolid = XAAOverPolySegmentThinSolid; + if(infoRec->PolylinesThinDashed) + infoRec->PolylinesThinDashed = XAAOverPolylinesThinDashed; + if(infoRec->PolySegmentThinDashed) + infoRec->PolySegmentThinDashed = XAAOverPolySegmentThinDashed; + if(infoRec->FillPolygonSolid) + infoRec->FillPolygonSolid = XAAOverFillPolygonSolid; + if(infoRec->FillPolygonStippled) + infoRec->FillPolygonStippled = XAAOverFillPolygonStippled; + if(infoRec->FillPolygonOpaqueStippled) + infoRec->FillPolygonOpaqueStippled = XAAOverFillPolygonOpaqueStippled; + if(infoRec->FillPolygonTiled) + infoRec->FillPolygonTiled = XAAOverFillPolygonTiled; + if(infoRec->PolyFillArcSolid) + infoRec->PolyFillArcSolid = XAAOverPolyFillArcSolid; + if(infoRec->PutImage) + infoRec->PutImage = XAAOverPutImage; + + return TRUE; +} + +/*********************** Screen functions ************************/ + +void +XAAOverCopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc +){ + ScreenPtr pScreen = pWin->drawable.pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen); + ScrnInfoPtr pScrn = infoRec->pScrn; + DDXPointPtr ppt, pptSrc; + RegionRec rgnDst; + BoxPtr pbox; + int i, nbox, dx, dy; + WindowPtr pRoot = WindowTable[pScreen->myNum]; + + + if (!pScrn->vtSema || !infoRec->ScreenToScreenBitBlt) { + XAA_SCREEN_PROLOGUE (pScreen, CopyWindow); + if(pScrn->vtSema && infoRec->NeedToSync) { + (*infoRec->Sync)(pScrn); + infoRec->NeedToSync = FALSE; + } + (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc); + XAA_SCREEN_EPILOGUE (pScreen, CopyWindow, XAAOverCopyWindow); + return; + } + + infoRec->ScratchGC.alu = GXcopy; + infoRec->ScratchGC.planemask = ~0; + + REGION_NULL(pScreen, &rgnDst); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); + REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); + + nbox = REGION_NUM_RECTS(&rgnDst); + if(nbox && + (pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec)))) { + + pbox = REGION_RECTS(&rgnDst); + for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + SWITCH_DEPTH(8); + XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + + if(pWin->drawable.bitsPerPixel != 8) { + SWITCH_DEPTH(pScrn->depth); + XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + } + + free(pptSrc); + } + + REGION_UNINIT(pScreen, &rgnDst); + + if(pWin->drawable.depth == 8) { + REGION_NULL(pScreen, &rgnDst); + miSegregateChildren(pWin, &rgnDst, pScrn->depth); + if(REGION_NOTEMPTY(pScreen, &rgnDst)) { + REGION_INTERSECT(pScreen, &rgnDst, &rgnDst, prgnSrc); + nbox = REGION_NUM_RECTS(&rgnDst); + if(nbox && + (pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec)))){ + + pbox = REGION_RECTS(&rgnDst); + for (i = nbox, ppt = pptSrc; i--; ppt++, pbox++) { + ppt->x = pbox->x1 + dx; + ppt->y = pbox->y1 + dy; + } + + SWITCH_DEPTH(pScrn->depth); + XAADoBitBlt((DrawablePtr)pRoot, (DrawablePtr)pRoot, + &(infoRec->ScratchGC), &rgnDst, pptSrc); + free(pptSrc); + } + } + REGION_UNINIT(pScreen, &rgnDst); + } +} + + +void +XAAOverWindowExposures( + WindowPtr pWin, + RegionPtr pReg, + RegionPtr pOtherReg +){ + ScreenPtr pScreen = pWin->drawable.pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + if((pWin->drawable.bitsPerPixel != 8) && infoRec->pScrn->vtSema) { + if(REGION_NUM_RECTS(pReg) && infoRec->FillSolidRects) { + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pScreen); + + SWITCH_DEPTH(8); + (*infoRec->FillSolidRects)(infoRec->pScrn, + infoRec->pScrn->colorKey, GXcopy, ~0, + REGION_NUM_RECTS(pReg), REGION_RECTS(pReg)); + miWindowExposures(pWin, pReg, pOtherReg); + return; + } else if(infoRec->NeedToSync) { + (*infoRec->Sync)(infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } + } + + XAA_SCREEN_PROLOGUE (pScreen, WindowExposures); + (*pScreen->WindowExposures) (pWin, pReg, pOtherReg); + XAA_SCREEN_EPILOGUE(pScreen, WindowExposures, XAAOverWindowExposures); +} + +/********************* Choosers *************************/ + +static int +XAAOverStippledFillChooser(GCPtr pGC) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + int ret; + + ret = (*pOverPriv->StippledFillChooser)(pGC); + + if((pGC->depth == 8) && + ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { + ret = 0; + } + + return ret; +} + +static int +XAAOverOpaqueStippledFillChooser(GCPtr pGC) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + int ret; + + ret = (*pOverPriv->OpaqueStippledFillChooser)(pGC); + + if((pGC->depth == 8) && + ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { + ret = 0; + } + + return ret; +} + +static int +XAAOverTiledFillChooser(GCPtr pGC) +{ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + int ret; + + ret = (*pOverPriv->TiledFillChooser)(pGC); + + if((pGC->depth == 8) && + ((ret == DO_COLOR_8x8) || (ret == DO_CACHE_BLT))) { + ret = 0; + } + + return ret; +} + + +/**************************** GC Functions **************************/ + +static RegionPtr +XAAOverCopyArea( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->CopyArea)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty); +} + +static RegionPtr +XAAOverCopyPlane( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, int srcy, + int width, int height, + int dstx, int dsty, + unsigned long bitPlane +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->CopyPlane)(pSrc, pDst, + pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); + +} + +static void +XAAOverPushPixelsSolid( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDraw, + int dx, int dy, + int xOrg, int yOrg +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PushPixelsSolid)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg); +} + + + +static void +XAAOverPolyFillRectSolid( + DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, + xRectangle *prectInit +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillRectSolid)(pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAOverPolyFillRectStippled( + DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, + xRectangle *prectInit +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillRectStippled)(pDraw, pGC, nrectFill, prectInit); +} + + +static void +XAAOverPolyFillRectOpaqueStippled( + DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, + xRectangle *prectInit +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillRectOpaqueStippled)(pDraw, pGC, nrectFill, prectInit); +} + +static void +XAAOverPolyFillRectTiled( + DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, + xRectangle *prectInit +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillRectTiled)(pDraw, pGC, nrectFill, prectInit); +} + + +static void +XAAOverFillSpansSolid( + DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, + int *pwidth, + int fSorted +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillSpansSolid)( + pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + + +static void +XAAOverFillSpansStippled( + DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, + int *pwidth, + int fSorted +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillSpansStippled)(pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + +static void +XAAOverFillSpansOpaqueStippled( + DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, + int *pwidth, + int fSorted +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillSpansOpaqueStippled)( + pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + + +static void +XAAOverFillSpansTiled( + DrawablePtr pDraw, + GCPtr pGC, + int nInit, + DDXPointPtr ppt, + int *pwidth, + int fSorted +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillSpansTiled)(pDraw, pGC, nInit, ppt, pwidth, fSorted); +} + +static int +XAAOverPolyText8TE( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->PolyText8TE)(pDraw, pGC, x, y, count, chars); +} + + +static int +XAAOverPolyText16TE( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->PolyText16TE)(pDraw, pGC, x, y, count, chars); +} + + +static void +XAAOverImageText8TE( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageText8TE)(pDraw, pGC, x, y, count, chars); +} + + +static void +XAAOverImageText16TE( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageText16TE)(pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageGlyphBltTE( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageGlyphBltTE)( + pDraw, pGC, xInit, yInit, nglyph, ppci, pglyphBase); +} + +static void +XAAOverPolyGlyphBltTE( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyGlyphBltTE)( + pDraw, pGC, xInit, yInit, nglyph, ppci, pglyphBase); +} + +static int +XAAOverPolyText8NonTE( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->PolyText8NonTE)(pDraw, pGC, x, y, count, chars); +} + + +static int +XAAOverPolyText16NonTE( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + return (*pOverPriv->PolyText16NonTE)(pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageText8NonTE( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageText8NonTE)(pDraw, pGC, x, y, count, chars); +} + +static void +XAAOverImageText16NonTE( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageText16NonTE)(pDraw, pGC, x, y, count, chars); +} + + +static void +XAAOverImageGlyphBltNonTE( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->ImageGlyphBltNonTE)( + pDraw, pGC, xInit, yInit, nglyph, ppci, pglyphBase); +} + +static void +XAAOverPolyGlyphBltNonTE( + DrawablePtr pDraw, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyGlyphBltNonTE)( + pDraw, pGC, xInit, yInit, nglyph, ppci, pglyphBase); +} + +static void +XAAOverPolyRectangleThinSolid( + DrawablePtr pDraw, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyRectangleThinSolid)(pDraw, pGC, nRectsInit, pRectsInit); +} + + + +static void +XAAOverPolylinesWideSolid( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pPts +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolylinesWideSolid)(pDraw, pGC, mode, npt, pPts); +} + + +static void +XAAOverPolylinesThinSolid( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pPts +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolylinesThinSolid)(pDraw, pGC, mode, npt, pPts); +} + +static void +XAAOverPolySegmentThinSolid( + DrawablePtr pDraw, + GCPtr pGC, + int nseg, + xSegment *pSeg +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolySegmentThinSolid)(pDraw, pGC, nseg, pSeg); +} + +static void +XAAOverPolylinesThinDashed( + DrawablePtr pDraw, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pPts +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolylinesThinDashed)(pDraw, pGC, mode, npt, pPts); +} + +static void +XAAOverPolySegmentThinDashed( + DrawablePtr pDraw, + GCPtr pGC, + int nseg, + xSegment *pSeg +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolySegmentThinDashed)(pDraw, pGC, nseg, pSeg); +} + + +static void +XAAOverFillPolygonSolid( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillPolygonSolid)(pDraw, pGC, shape, mode, count, ptsIn); +} + +static void +XAAOverFillPolygonStippled( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillPolygonStippled)(pDraw, pGC, shape, mode, count, ptsIn); +} + + +static void +XAAOverFillPolygonOpaqueStippled( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillPolygonOpaqueStippled)( + pDraw, pGC, shape, mode, count, ptsIn); +} + +static void +XAAOverFillPolygonTiled( + DrawablePtr pDraw, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->FillPolygonTiled)(pDraw, pGC, shape, mode, count, ptsIn); +} + + +static void +XAAOverPolyFillArcSolid( + DrawablePtr pDraw, + GCPtr pGC, + int narcs, + xArc *parcs +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PolyFillArcSolid)(pDraw, pGC, narcs, parcs); +} + + +static void +XAAOverPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage +){ + XAAOverlayPtr pOverPriv = GET_OVERLAY_PRIV(pGC->pScreen); + + SWITCH_DEPTH(pGC->depth); + + (*pOverPriv->PutImage)(pDraw, pGC, depth, x, y, w, h, + leftPad, format, pImage); +} + diff --git a/xorg-server/hw/xfree86/xaa/xaaPCache.c b/xorg-server/hw/xfree86/xaa/xaaPCache.c index 7e3011bd5..62726d539 100644 --- a/xorg-server/hw/xfree86/xaa/xaaPCache.c +++ b/xorg-server/hw/xfree86/xaa/xaaPCache.c @@ -1,2380 +1,2380 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "gc.h" -#include "mi.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "regionstr.h" -#include "servermd.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaacexp.h" -#include "xaalocal.h" -#include "xaawrap.h" - -#define MAX_COLOR 32 -#define MAX_MONO 32 -#define MAX_8 32 -#define MAX_128 32 -#define MAX_256 32 -#define MAX_512 16 - -static int CacheInitIndex = -1; -#define CACHEINIT(p) ((p)->privates[CacheInitIndex].val) - - -typedef struct _CacheLink { - int x; - int y; - int w; - int h; - struct _CacheLink *next; -} CacheLink, *CacheLinkPtr; - - -static void -TransferList(CacheLinkPtr list, XAACacheInfoPtr array, int num) -{ - while(num--) { - array->x = list->x; - array->y = list->y; - array->w = list->w; - array->h = list->h; - array->serialNumber = 0; - array->fg = array->bg = -1; - list = list->next; - array++; - } -} - - - -static CacheLinkPtr -Enlist(CacheLinkPtr link, int x, int y, int w, int h) -{ - CacheLinkPtr newLink; - - newLink = xalloc(sizeof(CacheLink)); - newLink->next = link; - newLink->x = x; newLink->y = y; - newLink->w = w; newLink->h = h; - return newLink; -} - - - -static CacheLinkPtr -Delist(CacheLinkPtr link) { - CacheLinkPtr ret = NULL; - - if(link) { - ret = link->next; - xfree(link); - } - return ret; -} - - - -static void -FreeList(CacheLinkPtr link) { - CacheLinkPtr tmp; - - while(link) { - tmp = link; - link = link->next; - xfree(tmp); - } -} - - - -static CacheLinkPtr -QuadLinks(CacheLinkPtr big, CacheLinkPtr little) -{ - /* CAUTION: This doesn't free big */ - int w1, w2, h1, h2; - - while(big) { - w1 = big->w >> 1; - w2 = big->w - w1; - h1 = big->h >> 1; - h2 = big->h - h1; - - little = Enlist(little, big->x, big->y, w1, h1); - little = Enlist(little, big->x + w1, big->y, w2, h1); - little = Enlist(little, big->x, big->y + h1, w1, h2); - little = Enlist(little, big->x + w1, big->y + h1, w2, h2); - - big = big->next; - } - return little; -} - - -static void -SubdivideList(CacheLinkPtr *large, CacheLinkPtr *small) -{ - CacheLinkPtr big = *large; - CacheLinkPtr little = *small; - int size = big->w >> 1; - - little = Enlist(little, big->x, big->y, size, size); - little = Enlist(little, big->x + size, big->y, size, size); - little = Enlist(little, big->x, big->y + size, size, size); - little = Enlist(little, big->x + size, big->y + size, size, size); - *small = little; - big = Delist(big); - *large = big; -} - -static void -FreePixmapCachePrivate(XAAPixmapCachePrivatePtr pPriv) -{ - if(!pPriv) return; - - if(pPriv->Info512) - xfree(pPriv->Info512); - if(pPriv->Info256) - xfree(pPriv->Info256); - if(pPriv->Info128) - xfree(pPriv->Info128); - if(pPriv->InfoColor) - xfree(pPriv->InfoColor); - if(pPriv->InfoMono) - xfree(pPriv->InfoMono); - if(pPriv->InfoPartial) - xfree(pPriv->InfoPartial); - - xfree(pPriv); -} - -void -XAAClosePixmapCache(ScreenPtr pScreen) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - - if(infoRec->PixmapCachePrivate) - FreePixmapCachePrivate( - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); - - infoRec->PixmapCachePrivate = NULL; -} - - - -static CacheLinkPtr -ThinOutPartials( - CacheLinkPtr ListPartial, - int *num, int *maxw, int *maxh -) { -/* This guy's job is to get at least 4 big slots out of a list of fragments */ - - CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; - int Num64, Num32, Num16, Num8, NumKeepers; - int w, h; - - List64 = List32 = List16 = List8 = ListKeepers = NULL; - Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; - w = h = 0; - - /* We sort partials by how large a square tile they can cache. - If a partial can't store a 64x64, 32x32, 16x16 or 8x8 tile, - we free it. */ - - pCur = ListPartial; - while(pCur) { - next = pCur->next; - if((pCur->w >= 64) && (pCur->h >= 64)) { - pCur->next = List64; List64 = pCur; - Num64++; - } else - if((pCur->w >= 32) && (pCur->h >= 32)) { - pCur->next = List32; List32 = pCur; - Num32++; - } else - if((pCur->w >= 16) && (pCur->h >= 16)) { - pCur->next = List16; List16 = pCur; - Num16++; - } else - if((pCur->w >= 8) && (pCur->h >= 8)) { - pCur->next = List8; List8 = pCur; - Num8++; - } else { - xfree(pCur); - } - - pCur = next; - } - - /* We save all the tiles from the largest bin that we can get - at least 4 of. If there are too few of a bigger slot, we - cut it in fourths to make smaller slots. */ - - if(Num64 >= 4) { - ListKeepers = List64; List64 = NULL; - NumKeepers = Num64; - goto GOT_EM; - } else if(Num64) { - List32 = QuadLinks(List64, List32); - Num32 += Num64 * 4; - Num64 = 0; - } - - if(Num32 >= 4) { - ListKeepers = List32; List32 = NULL; - NumKeepers = Num32; - goto GOT_EM; - } else if(Num32) { - List16 = QuadLinks(List32, List16); - Num16 += Num32 * 4; - Num32 = 0; - } - - if(Num16 >= 4) { - ListKeepers = List16; List16 = NULL; - NumKeepers = Num16; - goto GOT_EM; - } else if(Num16) { - List8 = QuadLinks(List16, List8); - Num8 += Num16 * 4; - Num16 = 0; - } - - if(Num8 >= 4) { - ListKeepers = List8; List8 = NULL; - NumKeepers = Num8; - goto GOT_EM; - } - -GOT_EM: - - /* Free the ones we aren't using */ - - if(List64) FreeList(List64); - if(List32) FreeList(List32); - if(List16) FreeList(List16); - if(List8) FreeList(List8); - - - /* Enlarge the slots if we can */ - - if(ListKeepers) { - CacheLinkPtr pLink = ListKeepers; - w = h = 128; - - while(pLink) { - if(pLink->w < w) w = pLink->w; - if(pLink->h < h) h = pLink->h; - pLink = pLink->next; - } - } - - *maxw = w; - *maxh = h; - *num = NumKeepers; - return ListKeepers; -} - -static void -ConvertColorToMono( - CacheLinkPtr *ColorList, - int ColorW, int ColorH, - CacheLinkPtr *MonoList, - int MonoW, int MonoH -){ - int x, y, w; - - x = (*ColorList)->x; y = (*ColorList)->y; - *ColorList = Delist(*ColorList); - - while(ColorH) { - ColorH -= MonoH; - for(w = 0; w <= (ColorW - MonoW); w += MonoW) - *MonoList = Enlist(*MonoList, x + w, y + ColorH, MonoW, MonoH); - } -} - -static void -ConvertAllPartialsTo8x8( - int *NumMono, int *NumColor, - CacheLinkPtr ListPartial, - CacheLinkPtr *ListMono, - CacheLinkPtr *ListColor, - XAAInfoRecPtr infoRec -){ -/* This guy extracts as many 8x8 slots as it can out of fragments */ - - int ColorH = infoRec->CacheHeightColor8x8Pattern; - int ColorW = infoRec->CacheWidthColor8x8Pattern; - int MonoH = infoRec->CacheHeightMono8x8Pattern; - int MonoW = infoRec->CacheWidthMono8x8Pattern; - int x, y, w, Height, Width; - Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); - Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); - CacheLinkPtr pLink = ListPartial; - CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; - - if(DoColor && DoMono) { - /* we assume color patterns take more space than color ones */ - if(MonoH > ColorH) ColorH = MonoH; - if(MonoW > ColorW) ColorW = MonoW; - } - - /* Break up the area into as many Color and Mono slots as we can */ - - while(pLink) { - Height = pLink->h; - Width = pLink->w; - x = pLink->x; - y = pLink->y; - - if(DoColor) { - while(Height >= ColorH) { - Height -= ColorH; - for(w = 0; w <= (Width - ColorW); w += ColorW) { - ColorList = Enlist( - ColorList, x + w, y + Height, ColorW, ColorH); - (*NumColor)++; - } - } - } - - if(DoMono && (Height >= MonoH)) { - while(Height >= MonoH) { - Height -= MonoH; - for(w = 0; w <= (Width - MonoW); w += MonoW) { - MonoList = Enlist( - MonoList, x + w, y + Height, MonoW, MonoH); - (*NumMono)++; - } - } - } - - pLink = pLink->next; - } - - - *ListMono = MonoList; - *ListColor = ColorList; - FreeList(ListPartial); -} - - -static CacheLinkPtr -ExtractOneThatFits(CacheLinkPtr *initList, int w, int h) -{ - CacheLinkPtr list = *initList; - CacheLinkPtr prev = NULL; - - while(list) { - if((list->w >= w) && (list->h >= h)) - break; - prev = list; - list = list->next; - } - - if(list) { - if(prev) - prev->next = list->next; - else - *initList = list->next; - - list->next = NULL; - } - - return list; -} - - -static CacheLinkPtr -ConvertSomePartialsTo8x8( - int *NumMono, int *NumColor, int *NumPartial, - CacheLinkPtr ListPartial, - CacheLinkPtr *ListMono, - CacheLinkPtr *ListColor, - int *maxw, int *maxh, - XAAInfoRecPtr infoRec -){ -/* This guy tries to get 4 of each type of 8x8 slot requested out of - a list of fragments all while trying to retain some big fragments - for the cache blits */ - - int ColorH = infoRec->CacheHeightColor8x8Pattern; - int ColorW = infoRec->CacheWidthColor8x8Pattern; - int MonoH = infoRec->CacheHeightMono8x8Pattern; - int MonoW = infoRec->CacheWidthMono8x8Pattern; - Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); - Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); - CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; - CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; - int Num64, Num32, Num16, Num8, NumKeepers; - int w, h, Width, Height; - int MonosPerColor = 1; - - if(DoColor && DoMono) { - /* we assume color patterns take more space than color ones */ - if(MonoH > ColorH) ColorH = MonoH; - if(MonoW > ColorW) ColorW = MonoW; - MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); - } - - List64 = List32 = List16 = List8 = ListKeepers = MonoList = ColorList = NULL; - Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; - Width = Height = 0; - - /* We sort partials by how large a square tile they can cache. - We make 8x8 patterns from the leftovers if we can. */ - - pCur = ListPartial; - while(pCur) { - next = pCur->next; - if((pCur->w >= 64) && (pCur->h >= 64)) { - pCur->next = List64; List64 = pCur; - Num64++; - } else - if((pCur->w >= 32) && (pCur->h >= 32)) { - pCur->next = List32; List32 = pCur; - Num32++; - } else - if((pCur->w >= 16) && (pCur->h >= 16)) { - pCur->next = List16; List16 = pCur; - Num16++; - } else - if((pCur->w >= 8) && (pCur->h >= 8)) { - pCur->next = List8; List8 = pCur; - Num8++; - } else { - h = pCur->h; - if(DoColor && (pCur->w >= ColorW) && (h >= ColorH)) { - while(h >= ColorH) { - h -= ColorH; - for(w = 0; w <= (pCur->w - ColorW); w += ColorW) { - ColorList = Enlist( ColorList, - pCur->x + w, pCur->y + h, ColorW, ColorH); - (*NumColor)++; - } - } - } - if(DoMono && (pCur->w >= MonoW) && (h >= MonoH)) { - while(h >= MonoH) { - h -= MonoH; - for(w = 0; w <= (pCur->w - MonoW); w += MonoW) { - MonoList = Enlist( MonoList, - pCur->x + w, pCur->y + h, MonoW, MonoH); - (*NumMono)++; - } - } - } - xfree(pCur); - } - - pCur = next; - } - - /* Try to extract at least 4 of each type of 8x8 slot that we need */ - - if(DoColor) { - CacheLinkPtr theOne; - while(*NumColor < 4) { - theOne = NULL; - if(Num8) { - if((theOne = ExtractOneThatFits(&List8, ColorW, ColorH))) - Num8--; - } - if(Num16 && !theOne) { - if((theOne = ExtractOneThatFits(&List16, ColorW, ColorH))) - Num16--; - } - if(Num32 && !theOne) { - if((theOne = ExtractOneThatFits(&List32, ColorW, ColorH))) - Num32--; - } - if(Num64 && !theOne) { - if((theOne = ExtractOneThatFits(&List64, ColorW, ColorH))) - Num64--; - } - - if(!theOne) break; - - - ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, - &MonoList, &ColorList, infoRec); - - if(DoMono) { - while(*NumColor && (*NumMono < 4)) { - ConvertColorToMono(&ColorList, ColorW, ColorH, - &MonoList, MonoW, MonoH); - (*NumColor)--; *NumMono += MonosPerColor; - } - } - } - } - - if(DoMono) { - CacheLinkPtr theOne; - while(*NumMono < 4) { - theOne = NULL; - if(Num8) { - if((theOne = ExtractOneThatFits(&List8, MonoW, MonoH))) - Num8--; - } - if(Num16 && !theOne) { - if((theOne = ExtractOneThatFits(&List16, MonoW, MonoH))) - Num16--; - } - if(Num32 && !theOne) { - if((theOne = ExtractOneThatFits(&List32, MonoW, MonoH))) - Num32--; - } - if(Num64 && !theOne) { - if((theOne = ExtractOneThatFits(&List64, MonoW, MonoH))) - Num64--; - } - - if(!theOne) break; - - ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, - &MonoList, &ColorList, infoRec); - } - } - - /* We save all the tiles from the largest bin that we can get - at least 4 of. If there are too few of a bigger slot, we - cut it in fourths to make smaller slots. */ - - if(Num64 >= 4) { - ListKeepers = List64; List64 = NULL; - NumKeepers = Num64; - goto GOT_EM; - } else if(Num64) { - List32 = QuadLinks(List64, List32); - Num32 += Num64 * 4; - Num64 = 0; - } - - if(Num32 >= 4) { - ListKeepers = List32; List32 = NULL; - NumKeepers = Num32; - goto GOT_EM; - } else if(Num32) { - List16 = QuadLinks(List32, List16); - Num16 += Num32 * 4; - Num32 = 0; - } - - if(Num16 >= 4) { - ListKeepers = List16; List16 = NULL; - NumKeepers = Num16; - goto GOT_EM; - } else if(Num16) { - List8 = QuadLinks(List16, List8); - Num8 += Num16 * 4; - Num16 = 0; - } - - if(Num8 >= 4) { - ListKeepers = List8; List8 = NULL; - NumKeepers = Num8; - goto GOT_EM; - } - -GOT_EM: - - /* Free the ones we aren't using */ - - if(List64) - ConvertAllPartialsTo8x8(NumMono, NumColor, List64, - &MonoList, &ColorList, infoRec); - if(List32) - ConvertAllPartialsTo8x8(NumMono, NumColor, List32, - &MonoList, &ColorList, infoRec); - if(List16) - ConvertAllPartialsTo8x8(NumMono, NumColor, List16, - &MonoList, &ColorList, infoRec); - if(List8) - ConvertAllPartialsTo8x8(NumMono, NumColor, List8, - &MonoList, &ColorList, infoRec); - - - /* Enlarge the slots if we can */ - - if(ListKeepers) { - CacheLinkPtr pLink = ListKeepers; - Width = Height = 128; - - while(pLink) { - if(pLink->w < Width) Width = pLink->w; - if(pLink->h < Height) Height = pLink->h; - pLink = pLink->next; - } - } - - *ListMono = MonoList; - *ListColor = ColorList; - *maxw = Width; - *maxh = Height; - *NumPartial = NumKeepers; - return ListKeepers; -} - - -void -XAAInitPixmapCache( - ScreenPtr pScreen, - RegionPtr areas, - pointer data -) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XAAInfoRecPtr infoRec = (XAAInfoRecPtr)data; - XAAPixmapCachePrivatePtr pCachePriv; - BoxPtr pBox = REGION_RECTS(areas); - int nBox = REGION_NUM_RECTS(areas); - int Num512, Num256, Num128, NumPartial, NumColor, NumMono; - int Target512, Target256; - CacheLinkPtr List512, List256, List128, ListPartial, ListColor, ListMono; - int x, y, w, h, ntotal, granularity, width, height, i; - int MaxPartialWidth, MaxPartialHeight; - - infoRec->MaxCacheableTileWidth = 0; - infoRec->MaxCacheableTileHeight = 0; - infoRec->MaxCacheableStippleHeight = 0; - infoRec->MaxCacheableStippleWidth = 0; - infoRec->UsingPixmapCache = FALSE; - - - if(!nBox || !pBox || !(infoRec->Flags & PIXMAP_CACHE)) - return; - - /* Allocate a persistent per-screen init flag to control messages */ - if (CacheInitIndex < 0) - CacheInitIndex = xf86AllocateScrnInfoPrivateIndex(); - - /* free the old private data if it exists */ - if(infoRec->PixmapCachePrivate) { - FreePixmapCachePrivate( - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); - infoRec->PixmapCachePrivate = NULL; - } - - Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0; - List512 = List256 = List128 = ListPartial = ListMono = ListColor = NULL; - granularity = infoRec->CachePixelGranularity; - if(granularity <= 1) granularity = 0; - - /* go through the boxes and break it into as many pieces as we can fit */ - - while(nBox--) { - x = pBox->x1; - if(granularity) { - int tmp = x % granularity; - if(tmp) x += (granularity - tmp); - } - width = pBox->x2 - x; - if(width <= 0) {pBox++; continue;} - - y = pBox->y1; - height = pBox->y2 - y; - - for(h = 0; h <= (height - 512); h += 512) { - for(w = 0; w <= (width - 512); w += 512) { - List512 = Enlist(List512, x + w, y + h, 512, 512); - Num512++; - } - for(; w <= (width - 256); w += 256) { - List256 = Enlist(List256, x + w, y + h, 256, 256); - List256 = Enlist(List256, x + w, y + h + 256, 256, 256); - Num256 += 2; - } - for(; w <= (width - 128); w += 128) { - List128 = Enlist(List128, x + w, y + h, 128, 128); - List128 = Enlist(List128, x + w, y + h + 128, 128, 128); - List128 = Enlist(List128, x + w, y + h + 256, 128, 128); - List128 = Enlist(List128, x + w, y + h + 384, 128, 128); - Num128 += 4; - } - if(w < width) { - int d = width - w; - ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); - ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); - ListPartial = Enlist(ListPartial, x + w, y + h + 256, d, 128); - ListPartial = Enlist(ListPartial, x + w, y + h + 384, d, 128); - NumPartial += 4; - } - } - for(; h <= (height - 256); h += 256) { - for(w = 0; w <= (width - 256); w += 256) { - List256 = Enlist(List256, x + w, y + h, 256, 256); - Num256++; - } - for(; w <= (width - 128); w += 128) { - List128 = Enlist(List128, x + w, y + h, 128, 128); - List128 = Enlist(List128, x + w, y + h + 128, 128, 128); - Num128 += 2; - } - if(w < width) { - int d = width - w; - ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); - ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); - NumPartial += 2; - } - } - for(; h <= (height - 128); h += 128) { - for(w = 0; w <= (width - 128); w += 128) { - List128 = Enlist(List128, x + w, y + h, 128, 128); - Num128++; - } - if(w < width) { - ListPartial = Enlist( - ListPartial, x + w, y + h, width - w, 128); - NumPartial++; - } - } - if(h < height) { - int d = height - h; - for(w = 0; w <= (width - 128); w += 128) { - ListPartial = Enlist(ListPartial, x + w, y + h, 128, d); - NumPartial++; - } - if(w < width) { - ListPartial = Enlist(ListPartial, x + w, y + h, width - w, d); - NumPartial++; - } - } - pBox++; - } - - -/* - by this point we've carved the space into as many 512x512, 256x256 - and 128x128 blocks as we could fit. We will then break larger - blocks into smaller ones if we need to. The rules are as follows: - - 512x512 - - 1) Don't take up more than half the memory. - 2) Don't bother if you can't get at least four. - 3) Don't make more than MAX_512. - 4) Don't have any of there are no 256x256s. - - 256x256 - - 1) Don't take up more than a quarter of the memory enless there - aren't any 512x512s. Then we can take up to half. - 2) Don't bother if you can't get at least four. - 3) Don't make more than MAX_256. - - 128x128 - - 1) Don't make more than MAX_128. - - We don't bother with the partial blocks unless we can use them - for 8x8 pattern fills or we are short on larger blocks. - -*/ - - ntotal = Num128 + (Num256<<2) + (Num512<<4); - - Target512 = ntotal >> 5; - if(Target512 < 4) Target512 = 0; - if(!Target512) Target256 = ntotal >> 3; - else Target256 = ntotal >> 4; - if(Target256 < 4) Target256 = 0; - - if(Num512 && Num256 < 4) { - while(Num512 && Num256 < Target256) { - SubdivideList(&List512, &List256); - Num256 += 4; Num512--; - } - } - - if(!Num512) { /* no room */ - } else if((Num512 < 4) || (!Target512)) { - while(Num512) { - SubdivideList(&List512, &List256); - Num256 += 4; Num512--; - } - } else if((Num512 > MAX_512) || (Num512 > Target512)){ - while(Num512 > MAX_512) { - SubdivideList(&List512, &List256); - Num256 += 4; Num512--; - } - while(Num512 > Target512) { - if(Num256 < MAX_256) { - SubdivideList(&List512, &List256); - Num256 += 4; Num512--; - } else break; - } - } - - if(!Num256) { /* no room */ - } else if((Num256 < 4) || (!Target256)) { - while(Num256) { - SubdivideList(&List256, &List128); - Num128 += 4; Num256--; - } - } else if((Num256 > MAX_256) || (Num256 > Target256)) { - while(Num256 > MAX_256) { - SubdivideList(&List256, &List128); - Num128 += 4; Num256--; - } - while(Num256 > Target256) { - if(Num128 < MAX_128) { - SubdivideList(&List256, &List128); - Num128 += 4; Num256--; - } else break; - } - } - - if(Num128 && ((Num128 < 4) || (Num128 > MAX_128))) { - CacheLinkPtr next; - int max = (Num128 > MAX_128) ? MAX_128 : 0; - - /* - * Note: next is set in this way to work around a code generation - * bug in gcc 2.7.2.3. - */ - next = List128->next; - while(Num128 > max) { - List128->next = ListPartial; - ListPartial = List128; - if((List128 = next)) - next = List128->next; - NumPartial++; Num128--; - } - } - - MaxPartialHeight = MaxPartialWidth = 0; - - /* at this point we have as many 512x512 and 256x256 slots as we - want but may have an excess of 128x128 slots. We still need - to find out if we need 8x8 slots. We take these from the - partials if we have them. Otherwise, we break some 128x128's */ - - if(!(infoRec->PixmapCacheFlags & (CACHE_MONO_8x8 | CACHE_COLOR_8x8))) { - if(NumPartial) { - if(Num128) { /* don't bother with partials */ - FreeList(ListPartial); - NumPartial = 0; ListPartial = NULL; - } else { - /* We have no big slots. Weed out the unusable partials */ - ListPartial = ThinOutPartials(ListPartial, &NumPartial, - &MaxPartialWidth, &MaxPartialHeight); - } - } - } else { - int MonosPerColor = 1; - int ColorH = infoRec->CacheHeightColor8x8Pattern; - int ColorW = infoRec->CacheWidthColor8x8Pattern; - int MonoH = infoRec->CacheHeightMono8x8Pattern; - int MonoW = infoRec->CacheWidthMono8x8Pattern; - Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); - Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); - - if(DoColor) infoRec->CanDoColor8x8 = FALSE; - if(DoMono) infoRec->CanDoMono8x8 = FALSE; - - if(DoColor && DoMono) { - /* we assume color patterns take more space than color ones */ - if(MonoH > ColorH) ColorH = MonoH; - if(MonoW > ColorW) ColorW = MonoW; - MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); - } - - if(Num128) { - if(NumPartial) { /* use all for 8x8 slots */ - ConvertAllPartialsTo8x8(&NumMono, &NumColor, - ListPartial, &ListMono, &ListColor, infoRec); - NumPartial = 0; ListPartial = NULL; - } - - /* Get some 8x8 slots from the 128 slots */ - while((Num128 > 4) && - ((NumMono < MAX_MONO) && (NumColor < MAX_COLOR))) { - CacheLinkPtr tmp = NULL; - - tmp = Enlist(tmp, List128->x, List128->y, - List128->w, List128->h); - List128 = Delist(List128); - Num128--; - - ConvertAllPartialsTo8x8(&NumMono, &NumColor, - tmp, &ListMono, &ListColor, infoRec); - } - } else if(NumPartial) { - /* We have share partials between 8x8 slots and tiles. */ - ListPartial = ConvertSomePartialsTo8x8(&NumMono, &NumColor, - &NumPartial, ListPartial, &ListMono, &ListColor, - &MaxPartialWidth, &MaxPartialHeight, infoRec); - } - - - if(DoMono && DoColor) { - if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { - int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; - - while(NumColor > max) { - ConvertColorToMono(&ListColor, ColorW, ColorH, - &ListMono, MonoW, MonoH); - NumColor--; NumMono += MonosPerColor; - } - } - - /* favor Mono slots over Color ones */ - while((NumColor > 4) && (NumMono < MAX_MONO)) { - ConvertColorToMono(&ListColor, ColorW, ColorH, - &ListMono, MonoW, MonoH); - NumColor--; NumMono += MonosPerColor; - } - } - - if(NumMono && ((NumMono > MAX_MONO) || (NumMono < 4))) { - int max = (NumMono > MAX_MONO) ? MAX_MONO : 0; - - while(NumMono > max) { - ListMono = Delist(ListMono); - NumMono--; - } - } - if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { - int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; - - while(NumColor > max) { - ListColor = Delist(ListColor); - NumColor--; - } - } - } - - - pCachePriv = xcalloc(1,sizeof(XAAPixmapCachePrivate)); - if(!pCachePriv) { - if(Num512) FreeList(List512); - if(Num256) FreeList(List256); - if(Num128) FreeList(List128); - if(NumPartial) FreeList(ListPartial); - if(NumColor) FreeList(ListColor); - if(NumMono) FreeList(ListMono); - return; - } - - infoRec->PixmapCachePrivate = (char*)pCachePriv; - - if(Num512) { - pCachePriv->Info512 = xcalloc(Num512,sizeof(XAACacheInfoRec)); - if(!pCachePriv->Info512) Num512 = 0; - if(Num512) TransferList(List512, pCachePriv->Info512, Num512); - FreeList(List512); - pCachePriv->Num512x512 = Num512; - } - if(Num256) { - pCachePriv->Info256 = xcalloc(Num256, sizeof(XAACacheInfoRec)); - if(!pCachePriv->Info256) Num256 = 0; - if(Num256) TransferList(List256, pCachePriv->Info256, Num256); - FreeList(List256); - pCachePriv->Num256x256 = Num256; - } - if(Num128) { - pCachePriv->Info128 = xcalloc(Num128, sizeof(XAACacheInfoRec)); - if(!pCachePriv->Info128) Num128 = 0; - if(Num128) TransferList(List128, pCachePriv->Info128, Num128); - FreeList(List128); - pCachePriv->Num128x128 = Num128; - } - - if(NumPartial) { - pCachePriv->InfoPartial = xcalloc(NumPartial, sizeof(XAACacheInfoRec)); - if(!pCachePriv->InfoPartial) NumPartial = 0; - if(NumPartial) - TransferList(ListPartial, pCachePriv->InfoPartial, NumPartial); - FreeList(ListPartial); - pCachePriv->NumPartial = NumPartial; - } - - if(NumColor) { - pCachePriv->InfoColor = xcalloc(NumColor, sizeof(XAACacheInfoRec)); - if(!pCachePriv->InfoColor) NumColor = 0; - if(NumColor) TransferList(ListColor, pCachePriv->InfoColor, NumColor); - FreeList(ListColor); - pCachePriv->NumColor = NumColor; - } - - if(NumMono) { - pCachePriv->InfoMono = xcalloc(NumMono, sizeof(XAACacheInfoRec)); - if(!pCachePriv->InfoMono) NumMono = 0; - if(NumMono) TransferList(ListMono, pCachePriv->InfoMono, NumMono); - FreeList(ListMono); - pCachePriv->NumMono = NumMono; - } - - - if(NumPartial) { - infoRec->MaxCacheableTileWidth = MaxPartialWidth; - infoRec->MaxCacheableTileHeight = MaxPartialHeight; - } - if(Num128) - infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 128; - if(Num256) - infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 256; - if(Num512) - infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 512; - - - infoRec->MaxCacheableStippleHeight = infoRec->MaxCacheableTileHeight; - infoRec->MaxCacheableStippleWidth = - infoRec->MaxCacheableTileWidth * pScrn->bitsPerPixel; - if(infoRec->ScreenToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) - infoRec->MaxCacheableStippleWidth /= 3; - - if(NumMono) { - if(!(infoRec->Mono8x8PatternFillFlags & - (HARDWARE_PATTERN_PROGRAMMED_ORIGIN | - HARDWARE_PATTERN_PROGRAMMED_BITS))) { - int numPerLine = - infoRec->CacheWidthMono8x8Pattern/infoRec->MonoPatternPitch; - - for(i = 0; i < 64; i++) { - pCachePriv->MonoOffsets[i].y = i/numPerLine; - pCachePriv->MonoOffsets[i].x = (i % numPerLine) * - infoRec->MonoPatternPitch; - } - } - infoRec->CanDoMono8x8 = TRUE; - } - if(NumColor) { - if(!(infoRec->Color8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { - - for(i = 0; i < 64; i++) { - pCachePriv->ColorOffsets[i].y = i & 0x07; - pCachePriv->ColorOffsets[i].x = i & ~0x07; - } - } - infoRec->CanDoColor8x8 = TRUE; - } - - if(!CACHEINIT(pScrn)) { - xf86ErrorF("\tSetting up tile and stipple cache:\n"); - if(NumPartial) - xf86ErrorF("\t\t%i %ix%i slots\n", - NumPartial, MaxPartialWidth, MaxPartialHeight); - if(Num128) xf86ErrorF("\t\t%i 128x128 slots\n", Num128); - if(Num256) xf86ErrorF("\t\t%i 256x256 slots\n", Num256); - if(Num512) xf86ErrorF("\t\t%i 512x512 slots\n", Num512); - if(NumColor) xf86ErrorF("\t\t%i 8x8 color pattern slots\n", NumColor); - if(NumMono) xf86ErrorF("\t\t%i 8x8 color expansion slots\n", NumMono); - } - - if(!(NumPartial | Num128 | Num256 | Num512 | NumColor | NumMono)) { - if(!CACHEINIT(pScrn)) - xf86ErrorF("\t\tNot enough video memory for pixmap cache\n"); - } else infoRec->UsingPixmapCache = TRUE; - - CACHEINIT(pScrn) = 1; -} - -#if X_BYTE_ORDER == X_BIG_ENDIAN -static CARD32 StippleMasks[4] = { - 0x80808080, - 0xC0C0C0C0, - 0x00000000, - 0xF0F0F0F0 -}; -#else -static CARD32 StippleMasks[4] = { - 0x01010101, - 0x03030303, - 0x00000000, - 0x0F0F0F0F -}; -#endif - -Bool -XAACheckStippleReducibility(PixmapPtr pPixmap) -{ - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); - CARD32 *IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - int w = pPixmap->drawable.width; - int h = pPixmap->drawable.height; - int i; - CARD32 bits[8]; - CARD32 mask = SHIFT_R(0xFFFFFFFF,24); - - pPriv->flags |= REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR; - pPriv->flags &= ~REDUCIBLE_TO_8x8; - - if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) - return FALSE; - - i = (h > 8) ? 8 : h; - - switch(w) { - case 32: - while(i--) { - bits[i] = IntPtr[i] & mask; - if( (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 8)), 8)) || - (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,16)),16)) || - (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,24)),24))) - return FALSE; - } - break; - case 16: - while(i--) { - bits[i] = IntPtr[i] & mask; - if(bits[i] != ((IntPtr[i] & SHIFT_R(SHIFT_L(mask,8),8)))) - return FALSE; - } - break; - default: - while(i--) - bits[i] = IntPtr[i] & mask; - break; - } - - switch(h) { - case 32: - if( (IntPtr[8] != IntPtr[16]) || (IntPtr[9] != IntPtr[17]) || - (IntPtr[10] != IntPtr[18]) || (IntPtr[11] != IntPtr[19]) || - (IntPtr[12] != IntPtr[20]) || (IntPtr[13] != IntPtr[21]) || - (IntPtr[14] != IntPtr[22]) || (IntPtr[15] != IntPtr[23]) || - (IntPtr[16] != IntPtr[24]) || (IntPtr[17] != IntPtr[25]) || - (IntPtr[18] != IntPtr[26]) || (IntPtr[19] != IntPtr[27]) || - (IntPtr[20] != IntPtr[28]) || (IntPtr[21] != IntPtr[29]) || - (IntPtr[22] != IntPtr[30]) || (IntPtr[23] != IntPtr[31])) - return FALSE; - /* fall through */ - case 16: - if( (IntPtr[0] != IntPtr[8]) || (IntPtr[1] != IntPtr[9]) || - (IntPtr[2] != IntPtr[10]) || (IntPtr[3] != IntPtr[11]) || - (IntPtr[4] != IntPtr[12]) || (IntPtr[5] != IntPtr[13]) || - (IntPtr[6] != IntPtr[14]) || (IntPtr[7] != IntPtr[15])) - return FALSE; - case 8: break; - case 1: bits[1] = bits[0]; - case 2: bits[2] = bits[0]; bits[3] = bits[1]; - case 4: bits[4] = bits[0]; bits[5] = bits[1]; - bits[6] = bits[2]; bits[7] = bits[3]; - break; - } - - pPriv->flags |= REDUCIBLE_TO_8x8; - - pPriv->pattern0 = bits[0] | SHIFT_L(bits[1],8) | SHIFT_L(bits[2],16) | SHIFT_L(bits[3],24); - pPriv->pattern1 = bits[4] | SHIFT_L(bits[5],8) | SHIFT_L(bits[6],16) | SHIFT_L(bits[7],24); - - if(w < 8) { - pPriv->pattern0 &= StippleMasks[w - 1]; - pPriv->pattern1 &= StippleMasks[w - 1]; - - switch(w) { - case 1: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,1); - pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,1); - case 2: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,2); - pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,2); - case 4: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,4); - pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,4); - } - } - - if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { - pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); - pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); - } - - - return TRUE; -} - - -Bool -XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono) -{ - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - CARD32 *IntPtr; - int w = pPixmap->drawable.width; - int h = pPixmap->drawable.height; - int pitch = pPixmap->devKind >> 2; - int dwords, i, j; - - pPriv->flags |= REDUCIBILITY_CHECKED; - pPriv->flags &= ~(REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR); - - if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) - return FALSE; - - dwords = ((w * pPixmap->drawable.bitsPerPixel) + 31) >> 5; - i = (h > 8) ? 8 : h; - - - if(w > 8) { - IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - switch(pPixmap->drawable.bitsPerPixel) { - case 8: - while(i--) { - for(j = 2; j < dwords; j++) - if(IntPtr[j] != IntPtr[j & 0x01]) - return FALSE; - IntPtr += pitch; - } - break; - case 16: - while(i--) { - for(j = 4; j < dwords; j++) - if(IntPtr[j] != IntPtr[j & 0x03]) - return FALSE; - IntPtr += pitch; - } - break; - case 24: - while(i--) { - for(j = 6; j < dwords; j++) - if(IntPtr[j] != IntPtr[j % 6]) - return FALSE; - IntPtr += pitch; - } - break; - case 32: - while(i--) { - for(j = 8; j < dwords; j++) - if(IntPtr[j] != IntPtr[j & 0x07]) - return FALSE; - IntPtr += pitch; - } - break; - default: return FALSE; - } - - } - - - if(h == 32) { - CARD32 *IntPtr2, *IntPtr3, *IntPtr4; - i = 8; - IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - IntPtr2 = IntPtr + (pitch << 3); - IntPtr3 = IntPtr2 + (pitch << 3); - IntPtr4 = IntPtr3 + (pitch << 3); - while(i--) { - for(j = 0; j < dwords; j++) - if((IntPtr[j] != IntPtr2[j]) || (IntPtr[j] != IntPtr3[j]) || - (IntPtr[j] != IntPtr4[j])) - return FALSE; - IntPtr += pitch; - IntPtr2 += pitch; - IntPtr3 += pitch; - IntPtr4 += pitch; - } - } else if (h == 16) { - CARD32 *IntPtr2; - i = 8; - IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - IntPtr2 = IntPtr + (pitch << 3); - while(i--) { - for(j = 0; j < dwords; j++) - if(IntPtr[j] != IntPtr2[j]) - return FALSE; - IntPtr += pitch; - IntPtr2 += pitch; - } - } - - pPriv->flags |= REDUCIBLE_TO_8x8; - - if(checkMono) { - XAAInfoRecPtr infoRec = - GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); - unsigned char bits[8]; - int fg, bg = -1, x, y; - - i = (h > 8) ? 8 : h; - j = (w > 8) ? 8 : w; - - if(pPixmap->drawable.bitsPerPixel == 8) { - unsigned char *srcp = pPixmap->devPrivate.ptr; - fg = srcp[0]; - pitch = pPixmap->devKind; - for(y = 0; y < i; y++) { - bits[y] = 0; - for(x = 0; x < j; x++) { - if(srcp[x] != fg) { - if(bg == -1) bg = srcp[x]; - else if(bg != srcp[x]) return TRUE; - } else bits[y] |= 1 << x; - } - srcp += pitch; - } - } else if(pPixmap->drawable.bitsPerPixel == 16) { - unsigned short *srcp = (unsigned short*)pPixmap->devPrivate.ptr; - fg = srcp[0]; - pitch = pPixmap->devKind >> 1; - for(y = 0; y < i; y++) { - bits[y] = 0; - for(x = 0; x < j; x++) { - if(srcp[x] != fg) { - if(bg == -1) bg = srcp[x]; - else if(bg != srcp[x]) return TRUE; - } else bits[y] |= 1 << x; - } - srcp += pitch; - } - } else if(pPixmap->drawable.bitsPerPixel == 24) { - CARD32 val; - unsigned char *srcp = pPixmap->devPrivate.ptr; - fg = *((CARD32*)srcp) & 0x00FFFFFF; - pitch = pPixmap->devKind; - j *= 3; - for(y = 0; y < i; y++) { - bits[y] = 0; - for(x = 0; x < j; x+=3) { - val = *((CARD32*)(srcp+x)) & 0x00FFFFFF; - if(val != fg) { - if(bg == -1) bg = val; - else if(bg != val) - return TRUE; - } else bits[y] |= 1 << (x/3); - } - srcp += pitch; - } - } else if(pPixmap->drawable.bitsPerPixel == 32) { - IntPtr = (CARD32*)pPixmap->devPrivate.ptr; - fg = IntPtr[0]; - for(y = 0; y < i; y++) { - bits[y] = 0; - for(x = 0; x < j; x++) { - if(IntPtr[x] != fg) { - if(bg == -1) bg = IntPtr[x]; - else if(bg != IntPtr[x]) return TRUE; - } else bits[y] |= 1 << x; - } - IntPtr += pitch; - } - } else return TRUE; - - pPriv->fg = fg; - if(bg == -1) pPriv->bg = fg; - else pPriv->bg = bg; - - if(h < 8) { - switch(h) { - case 1: bits[1] = bits[0]; - case 2: bits[2] = bits[0]; bits[3] = bits[1]; - case 4: bits[4] = bits[0]; bits[5] = bits[1]; - bits[6] = bits[2]; bits[7] = bits[3]; - break; - } - } - - pPriv->pattern0 = - bits[0] | (bits[1]<<8) | (bits[2]<<16) | (bits[3]<<24); - pPriv->pattern1 = - bits[4] | (bits[5]<<8) | (bits[6]<<16) | (bits[7]<<24); - - if(w < 8) { - switch(w) { - case 1: pPriv->pattern0 |= (pPriv->pattern0 << 1); - pPriv->pattern1 |= (pPriv->pattern1 << 1); - case 2: pPriv->pattern0 |= (pPriv->pattern0 << 2); - pPriv->pattern1 |= (pPriv->pattern1 << 2); - case 4: pPriv->pattern0 |= (pPriv->pattern0 << 4); - pPriv->pattern1 |= (pPriv->pattern1 << 4); - } - } - pPriv->flags |= REDUCIBLE_TO_2_COLOR; - - if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { - pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); - pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); - } - - } - - return TRUE; -} - - -void XAATileCache( - ScrnInfoPtr pScrn, - XAACacheInfoPtr pCache, - int w, int h -) { - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, ~0, -1); - - while((w << 1) <= pCache->w) { - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, - pCache->x + w, pCache->y, w, h); - w <<= 1; - } - if(w != pCache->w) { - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, - pCache->x + w, pCache->y, pCache->w - w, h); - w = pCache->w; - } - - while((h << 1) <= pCache->h) { - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, - pCache->x, pCache->y + h, w, h); - h <<= 1; - } - if(h != pCache->h) { - (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, - pCache->x, pCache->y + h, w, pCache->h - h); - } - SET_SYNC_FLAG(infoRec); -} - -XAACacheInfoPtr -XAACacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) -{ - int w = pPix->drawable.width; - int h = pPix->drawable.height; - int size = max(w, h); - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache, cacheRoot = NULL; - int i, max = 0; - int *current; - - if(size <= 128) { - if(pCachePriv->Info128) { - cacheRoot = pCachePriv->Info128; - max = pCachePriv->Num128x128; - current = &pCachePriv->Current128; - } else { - cacheRoot = pCachePriv->InfoPartial; - max = pCachePriv->NumPartial; - current = &pCachePriv->CurrentPartial; - } - } else if(size <= 256) { - cacheRoot = pCachePriv->Info256; - max = pCachePriv->Num256x256; - current = &pCachePriv->Current256; - } else if(size <= 512) { - cacheRoot = pCachePriv->Info512; - max = pCachePriv->Num512x512; - current = &pCachePriv->Current512; - } else { /* something's wrong */ - ErrorF("Something's wrong in XAACacheTile()\n"); - return pCachePriv->Info128; - } - - pCache = cacheRoot; - - /* lets look for it */ - for(i = 0; i < max; i++, pCache++) { - if(pCache->serialNumber == pPix->drawable.serialNumber) { - pCache->trans_color = -1; - return pCache; - } - } - - pCache = &cacheRoot[(*current)++]; - if(*current >= max) *current = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->trans_color = pCache->bg = pCache->fg = -1; - pCache->orig_w = w; pCache->orig_h = h; - (*infoRec->WritePixmapToCache)( - pScrn, pCache->x, pCache->y, w, h, pPix->devPrivate.ptr, - pPix->devKind, pPix->drawable.bitsPerPixel, pPix->drawable.depth); - if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && - ((w != pCache->w) || (h != pCache->h))) - XAATileCache(pScrn, pCache, w, h); - - return pCache; -} - -XAACacheInfoPtr -XAACacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) -{ - int w = pPix->drawable.width; - int h = pPix->drawable.height; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache, cacheRoot = NULL; - int i, max = 0, funcNo, pad, dwords, bpp = pScrn->bitsPerPixel; - int *current; - StippleScanlineProcPtr StippleFunc; - unsigned char *data, *srcPtr, *dstPtr; - - if((h <= 128) && (w <= 128 * bpp)) { - if(pCachePriv->Info128) { - cacheRoot = pCachePriv->Info128; - max = pCachePriv->Num128x128; - current = &pCachePriv->Current128; - } else { - cacheRoot = pCachePriv->InfoPartial; - max = pCachePriv->NumPartial; - current = &pCachePriv->CurrentPartial; - } - } else if((h <= 256) && (w <= 256 * bpp)){ - cacheRoot = pCachePriv->Info256; - max = pCachePriv->Num256x256; - current = &pCachePriv->Current256; - } else if((h <= 512) && (w <= 526 * bpp)){ - cacheRoot = pCachePriv->Info512; - max = pCachePriv->Num512x512; - current = &pCachePriv->Current512; - } else { /* something's wrong */ - ErrorF("Something's wrong in XAACacheMonoStipple()\n"); - return pCachePriv->Info128; - } - - pCache = cacheRoot; - - /* lets look for it */ - for(i = 0; i < max; i++, pCache++) { - if((pCache->serialNumber == pPix->drawable.serialNumber) && - (pCache->fg == -1) && (pCache->bg == -1)) { - pCache->trans_color = -1; - return pCache; - } - } - - pCache = &cacheRoot[(*current)++]; - if(*current >= max) *current = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->trans_color = pCache->bg = pCache->fg = -1; - pCache->orig_w = w; pCache->orig_h = h; - - if(w <= 32) { - if(w & (w - 1)) funcNo = 1; - else funcNo = 0; - } else funcNo = 2; - - pad = BitmapBytePad(pCache->w * bpp); - dwords = bytes_to_int32(pad); - dstPtr = data = (unsigned char*)xalloc(pad * pCache->h); - srcPtr = (unsigned char*)pPix->devPrivate.ptr; - - if(infoRec->ScreenToScreenColorExpandFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) - StippleFunc = XAAStippleScanlineFuncMSBFirst[funcNo]; - else - StippleFunc = XAAStippleScanlineFuncLSBFirst[funcNo]; - - /* don't bother generating more than we'll ever use */ - max = ((pScrn->displayWidth + w - 1) + 31) >> 5; - if(dwords > max) - dwords = max; - - for(i = 0; i < h; i++) { - (*StippleFunc)((CARD32*)dstPtr, (CARD32*)srcPtr, 0, w, dwords); - srcPtr += pPix->devKind; - dstPtr += pad; - } - - while((h<<1) <= pCache->h) { - memcpy(data + (pad * h), data, pad * h); - h <<= 1; - } - - if(h < pCache->h) - memcpy(data + (pad * h), data, pad * (pCache->h - h)); - - (*infoRec->WritePixmapToCache)( - pScrn, pCache->x, pCache->y, pCache->w, pCache->h, data, - pad, bpp, pScrn->depth); - - xfree(data); - - return pCache; -} - -XAACacheInfoPtr -XAACachePlanarMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) -{ - int w = pPix->drawable.width; - int h = pPix->drawable.height; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache, cacheRoot = NULL; - int i, max = 0; - int *current; - - if((h <= 128) && (w <= 128)) { - if(pCachePriv->Info128) { - cacheRoot = pCachePriv->Info128; - max = pCachePriv->Num128x128; - current = &pCachePriv->Current128; - } else { - cacheRoot = pCachePriv->InfoPartial; - max = pCachePriv->NumPartial; - current = &pCachePriv->CurrentPartial; - } - } else if((h <= 256) && (w <= 256)){ - cacheRoot = pCachePriv->Info256; - max = pCachePriv->Num256x256; - current = &pCachePriv->Current256; - } else if((h <= 512) && (w <= 526)){ - cacheRoot = pCachePriv->Info512; - max = pCachePriv->Num512x512; - current = &pCachePriv->Current512; - } else { /* something's wrong */ - ErrorF("Something's wrong in XAACachePlanarMonoStipple()\n"); - return pCachePriv->Info128; - } - - pCache = cacheRoot; - - /* lets look for it */ - for(i = 0; i < max; i++, pCache++) { - if((pCache->serialNumber == pPix->drawable.serialNumber) && - (pCache->fg == -1) && (pCache->bg == -1)) { - pCache->trans_color = -1; - return pCache; - } - } - - pCache = &cacheRoot[(*current)++]; - if(*current >= max) *current = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->trans_color = pCache->bg = pCache->fg = -1; - pCache->orig_w = w; pCache->orig_h = h; - - /* Plane 0 holds the stipple. Plane 1 holds the inverted stipple */ - (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, - pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, - pPix->devKind, 1, 2); - if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_MONO_DATA) && - ((w != pCache->w) || (h != pCache->h))) - XAATileCache(pScrn, pCache, w, h); - - return pCache; -} - -XAACachePlanarMonoStippleProc -XAAGetCachePlanarMonoStipple(void) -{ - return XAACachePlanarMonoStipple; -} - -XAACacheInfoPtr -XAACacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) -{ - int w = pPix->drawable.width; - int h = pPix->drawable.height; - int size = max(w, h); - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache, cacheRoot = NULL; - int i, max = 0; - int *current; - - if(size <= 128) { - if(pCachePriv->Info128) { - cacheRoot = pCachePriv->Info128; - max = pCachePriv->Num128x128; - current = &pCachePriv->Current128; - } else { - cacheRoot = pCachePriv->InfoPartial; - max = pCachePriv->NumPartial; - current = &pCachePriv->CurrentPartial; - } - } else if(size <= 256) { - cacheRoot = pCachePriv->Info256; - max = pCachePriv->Num256x256; - current = &pCachePriv->Current256; - } else if(size <= 512) { - cacheRoot = pCachePriv->Info512; - max = pCachePriv->Num512x512; - current = &pCachePriv->Current512; - } else { /* something's wrong */ - ErrorF("Something's wrong in XAACacheStipple()\n"); - return pCachePriv->Info128; - } - - pCache = cacheRoot; - /* lets look for it */ - if(bg == -1) - for(i = 0; i < max; i++, pCache++) { - if((pCache->serialNumber == pPix->drawable.serialNumber) && - (fg == pCache->fg) && (pCache->fg != pCache->bg)) { - pCache->trans_color = pCache->bg; - return pCache; - } - } - else - for(i = 0; i < max; i++, pCache++) { - if((pCache->serialNumber == pPix->drawable.serialNumber) && - (fg == pCache->fg) && (bg == pCache->bg)) { - pCache->trans_color = -1; - return pCache; - } - } - - pCache = &cacheRoot[(*current)++]; - if(*current >= max) *current = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->fg = fg; - if(bg == -1) - pCache->trans_color = bg = fg ^ 1; - else - pCache->trans_color = -1; - pCache->bg = bg; - - pCache->orig_w = w; pCache->orig_h = h; - (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, - pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, - pPix->devKind, fg, bg); - if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && - ((w != pCache->w) || (h != pCache->h))) - XAATileCache(pScrn, pCache, w, h); - - return pCache; -} - - - -XAACacheInfoPtr -XAACacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, int pat1) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache = pCachePriv->InfoMono; - int i; - - for(i = 0; i < pCachePriv->NumMono; i++, pCache++) { - if(pCache->serialNumber && - (pCache->pat0 == pat0) && (pCache->pat1 == pat1)) - return pCache; - } - - /* OK, let's cache it */ - pCache = &pCachePriv->InfoMono[pCachePriv->CurrentMono++]; - if(pCachePriv->CurrentMono >= pCachePriv->NumMono) - pCachePriv->CurrentMono = 0; - - pCache->serialNumber = 1; /* we don't care since we do lookups by pattern */ - pCache->pat0 = pat0; - pCache->pat1 = pat1; - - (*infoRec->WriteMono8x8PatternToCache)(pScrn, pCache); - - return pCache; -} - - - -XAACacheInfoPtr -XAACacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - XAACacheInfoPtr pCache = pCachePriv->InfoColor; - XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - int i; - - if(!(pixPriv->flags & REDUCIBLE_TO_2_COLOR)) { - for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { - if(pCache->serialNumber == pPix->drawable.serialNumber) { - pCache->trans_color = -1; - return pCache; - } - } - pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; - if(pCachePriv->CurrentColor >= pCachePriv->NumColor) - pCachePriv->CurrentColor = 0; - - pCache->serialNumber = pPix->drawable.serialNumber; - pCache->trans_color = pCache->fg = pCache->bg = -1; - } else { - int pat0 = pixPriv->pattern0; - int pat1 = pixPriv->pattern1; - - if(fg == -1) { /* it's a tile */ - fg = pixPriv->fg; bg = pixPriv->bg; - } - - if(bg == -1) { /* stipple */ - for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { - if(pCache->serialNumber && - (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && - (pCache->fg == fg) && (pCache->bg != fg)) { - pCache->trans_color = pCache->bg; - return pCache; - } - } - } else { /* opaque stipple */ - for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { - if(pCache->serialNumber && - (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && - (pCache->fg == fg) && (pCache->bg == bg)) { - pCache->trans_color = -1; - return pCache; - } - } - } - pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; - if(pCachePriv->CurrentColor >= pCachePriv->NumColor) - pCachePriv->CurrentColor = 0; - - if(bg == -1) - pCache->trans_color = bg = fg ^ 1; - else - pCache->trans_color = -1; - - pCache->pat0 = pat0; pCache->pat1 = pat1; - pCache->fg = fg; pCache->bg = bg; - pCache->serialNumber = 1; - } - - (*infoRec->WriteColor8x8PatternToCache)(pScrn, pPix, pCache); - - return pCache; -} - - -void -XAAWriteBitmapToCache( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int fg, int bg -) { - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - (*infoRec->WriteBitmap)(pScrn, x, y, w, h, src, srcwidth, - 0, fg, bg, GXcopy, ~0); -} - -void -XAAWriteBitmapToCacheLinear( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int fg, int bg -){ - ScreenPtr pScreen = pScrn->pScreen; - PixmapPtr pScreenPix, pDstPix; - XID gcvals[2]; - GCPtr pGC; - - pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); - - pDstPix = GetScratchPixmapHeader(pScreen, pScreenPix->drawable.width, - y + h, pScreenPix->drawable.depth, - pScreenPix->drawable.bitsPerPixel, - pScreenPix->devKind, - pScreenPix->devPrivate.ptr); - - pGC = GetScratchGC(pScreenPix->drawable.depth, pScreen); - gcvals[0] = fg; - gcvals[1] = bg; - DoChangeGC(pGC, GCForeground | GCBackground, gcvals, 0); - ValidateGC((DrawablePtr)pDstPix, pGC); - - /* We've unwrapped already so these ops miss a sync */ - SYNC_CHECK(pScrn); - - (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, 1, x, y, w, h, 0, - XYBitmap, (pointer)src); - - FreeScratchGC(pGC); - FreeScratchPixmapHeader(pDstPix); -} - - -void -XAAWritePixmapToCache( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int bpp, int depth -) { - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - - (*infoRec->WritePixmap)(pScrn, x, y, w, h, src, srcwidth, - GXcopy, ~0, -1, bpp, depth); -} - - - -void -XAAWritePixmapToCacheLinear( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int bpp, int depth -){ - ScreenPtr pScreen = pScrn->pScreen; - PixmapPtr pScreenPix, pDstPix; - GCPtr pGC; - - pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); - - pDstPix = GetScratchPixmapHeader(pScreen, x + w, y + h, - depth, bpp, pScreenPix->devKind, - pScreenPix->devPrivate.ptr); - - pGC = GetScratchGC(depth, pScreen); - ValidateGC((DrawablePtr)pDstPix, pGC); - - /* We've unwrapped already so these ops miss a sync */ - SYNC_CHECK(pScrn); - - if(bpp == BitsPerPixel(depth)) - (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, depth, x, y, w, - h, 0, ZPixmap, (pointer)src); - else { - PixmapPtr pSrcPix; - - pSrcPix = GetScratchPixmapHeader(pScreen, w, h, depth, bpp, - srcwidth, (pointer)src); - - (*pGC->ops->CopyArea)((DrawablePtr)pSrcPix, (DrawablePtr)pDstPix, - pGC, 0, 0, w, h, x, y); - - FreeScratchPixmapHeader(pSrcPix); - } - - FreeScratchGC(pGC); - FreeScratchPixmapHeader(pDstPix); -} - - -void -XAAWriteMono8x8PatternToCache( - ScrnInfoPtr pScrn, - XAACacheInfoPtr pCache -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - unsigned char *data; - int pad, Bpp = (pScrn->bitsPerPixel >> 3); - - pCache->offsets = pCachePriv->MonoOffsets; - - pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); - - data = (unsigned char*)xalloc(pad * pCache->h); - if(!data) return; - - if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { - CARD32* ptr = (CARD32*)data; - ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; - } else { - CARD32 *ptr; - DDXPointPtr pPoint = pCache->offsets; - int patx, paty, i; - - for(i = 0; i < 64; i++, pPoint++) { - patx = pCache->pat0; paty = pCache->pat1; - XAARotateMonoPattern(&patx, &paty, i & 0x07, i >> 3, - (infoRec->Mono8x8PatternFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST)); - ptr = (CARD32*)(data + (pad * pPoint->y) + (Bpp * pPoint->x)); - ptr[0] = patx; ptr[1] = paty; - } - } - - (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, - pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); - - xfree(data); -} - -void -XAAWriteColor8x8PatternToCache( - ScrnInfoPtr pScrn, - PixmapPtr pPix, - XAACacheInfoPtr pCache -){ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - int pad, i, w, h, nw, nh, Bpp; - unsigned char *data, *srcPtr, *dstPtr; - - pCache->offsets = pCachePriv->ColorOffsets; - - if(pixPriv->flags & REDUCIBLE_TO_2_COLOR) { - CARD32* ptr; - pad = BitmapBytePad(pCache->w); - data = (unsigned char*)xalloc(pad * pCache->h); - if(!data) return; - - if(infoRec->Color8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { - ptr = (CARD32*)data; - ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; - } else { - int patx, paty; - - ptr = (CARD32*)data; - ptr[0] = ptr[2] = pCache->pat0; ptr[1] = ptr[3] = pCache->pat1; - for(i = 1; i < 8; i++) { - patx = pCache->pat0; paty = pCache->pat1; - XAARotateMonoPattern(&patx, &paty, i, 0, - (infoRec->Mono8x8PatternFillFlags & - BIT_ORDER_IN_BYTE_MSBFIRST)); - ptr = (CARD32*)(data + (pad * i)); - ptr[0] = ptr[2] = patx; ptr[1] = ptr[3] = paty; - } - } - - (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, - pCache->w, pCache->h, data, pad, pCache->fg, pCache->bg); - - xfree(data); - return; - } - - Bpp = pScrn->bitsPerPixel >> 3; - h = min(8,pPix->drawable.height); - w = min(8,pPix->drawable.width); - pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); - - data = (unsigned char*)xalloc(pad * pCache->h); - if(!data) return; - - /* Write and expand horizontally. */ - for (i = h, dstPtr = data, srcPtr = pPix->devPrivate.ptr; i--; - srcPtr += pPix->devKind, dstPtr += pScrn->bitsPerPixel) { - nw = w; - memcpy(dstPtr, srcPtr, w * Bpp); - while (nw != 8) { - memcpy(dstPtr + (nw * Bpp), dstPtr, nw * Bpp); - nw <<= 1; - } - } - nh = h; - /* Expand vertically. */ - while (nh != 8) { - memcpy(data + (nh*pScrn->bitsPerPixel), data, nh*pScrn->bitsPerPixel); - nh <<= 1; - } - - if(!(infoRec->Color8x8PatternFillFlags & - HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ - int j; - unsigned char *ptr = data + (128 * Bpp); - - memcpy(data + (64 * Bpp), data, 64 * Bpp); - for(i = 1; i < 8; i++, ptr += (128 * Bpp)) { - for(j = 0; j < 8; j++) { - memcpy(ptr + (j * 8) * Bpp, data + (j * 8 + i) * Bpp, - (8 - i) * Bpp); - memcpy(ptr + (j * 8 + 8 - i) * Bpp, data + j * 8 * Bpp, i*Bpp); - } - memcpy(ptr + (64 * Bpp), ptr, 64 * Bpp); - } - } - - (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, - pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); - - xfree(data); -} - - - -int -XAAStippledFillChooser(GCPtr pGC) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - PixmapPtr pPixmap = pGC->stipple; - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - - if(!(pPriv->flags & REDUCIBILITY_CHECKED) && - (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { - XAACheckStippleReducibility(pPixmap); - } - - - if(pPriv->flags & REDUCIBLE_TO_8x8) { - if(infoRec->CanDoMono8x8 && - !(infoRec->FillMono8x8PatternSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillMono8x8PatternSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_FG(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { - - return DO_MONO_8x8; - } - - if(infoRec->CanDoColor8x8 && - !(infoRec->FillColor8x8PatternSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillColor8x8PatternSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { - - return DO_COLOR_8x8; - } - } - - if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / - infoRec->CacheColorExpandDensity) && - !(infoRec->FillCacheExpandSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillCacheExpandSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_FG(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { - - return DO_CACHE_EXPAND; - } - - - if(infoRec->UsingPixmapCache && - !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && - infoRec->FillCacheBltSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && - !(infoRec->FillCacheBltSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillCacheBltSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { - - return DO_CACHE_BLT; - } - - if(infoRec->FillColorExpandSpans && - !(infoRec->FillColorExpandSpansFlags & NO_TRANSPARENCY) && - ((pGC->alu == GXcopy) || !(infoRec->FillColorExpandSpansFlags & - TRANSPARENCY_GXCOPY_ONLY)) && - CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_FG(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { - - return DO_COLOR_EXPAND; - } - - return 0; -} - - -int -XAAOpaqueStippledFillChooser(GCPtr pGC) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - PixmapPtr pPixmap = pGC->stipple; - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - - if(XAA_DEPTH_BUG(pGC)) - return 0; - - if(!(pPriv->flags & REDUCIBILITY_CHECKED) && - (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { - XAACheckStippleReducibility(pPixmap); - } - - if(pPriv->flags & REDUCIBLE_TO_8x8) { - if(infoRec->CanDoMono8x8 && - !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && - CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_COLORS(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { - - return DO_MONO_8x8; - } - - if(infoRec->CanDoColor8x8 && - CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { - - return DO_COLOR_8x8; - } - } - - if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / - infoRec->CacheColorExpandDensity) && - !(infoRec->FillCacheExpandSpansFlags & TRANSPARENCY_ONLY) && - CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_COLORS(pGC,infoRec->FillCacheExpandSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { - - return DO_CACHE_EXPAND; - } - - if(infoRec->UsingPixmapCache && - !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && - infoRec->FillCacheBltSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && - CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { - - return DO_CACHE_BLT; - } - - if(infoRec->FillColorExpandSpans && - !(infoRec->FillColorExpandSpansFlags & TRANSPARENCY_ONLY) && - CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_COLORS(pGC,infoRec->FillColorExpandSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { - - return DO_COLOR_EXPAND; - } - - return 0; -} - - - -int -XAATiledFillChooser(GCPtr pGC) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - PixmapPtr pPixmap = pGC->tile.pixmap; - XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); - - if(IS_OFFSCREEN_PIXMAP(pPixmap) && infoRec->FillCacheBltSpans && - CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { - - return DO_PIXMAP_COPY; - } - - if(!(pPriv->flags & REDUCIBILITY_CHECKED) && - (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { - XAACheckTileReducibility(pPixmap,infoRec->CanDoMono8x8); - } - - if(pPriv->flags & REDUCIBLE_TO_8x8) { - if((pPriv->flags & REDUCIBLE_TO_2_COLOR) && infoRec->CanDoMono8x8 && - !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && - CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && - (!(infoRec->FillMono8x8PatternSpansFlags & RGB_EQUAL) || - (CHECK_RGB_EQUAL(pPriv->fg) && CHECK_RGB_EQUAL(pPriv->bg))) && - CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { - - return DO_MONO_8x8; - } - - if(infoRec->CanDoColor8x8 && - CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { - - return DO_COLOR_8x8; - } - } - - if(infoRec->UsingPixmapCache && infoRec->FillCacheBltSpans && - (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && - (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && - CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { - - return DO_CACHE_BLT; - } - - if(infoRec->FillImageWriteRects && - CHECK_NO_GXCOPY(pGC,infoRec->FillImageWriteRectsFlags) && - CHECK_ROP(pGC,infoRec->FillImageWriteRectsFlags) && - CHECK_ROPSRC(pGC,infoRec->FillImageWriteRectsFlags) && - CHECK_PLANEMASK(pGC,infoRec->FillImageWriteRectsFlags)) { - - return DO_IMAGE_WRITE; - } - - return 0; -} - - -static int RotateMasksX[8] = { - 0xFFFFFFFF, 0x7F7F7F7F, 0x3F3F3F3F, 0x1F1F1F1F, - 0x0F0F0F0F, 0x07070707, 0x03030303, 0x01010101 -}; - -static int RotateMasksY[4] = { - 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF -}; - -void -XAARotateMonoPattern( - int *pat0, int *pat1, - int xorg, int yorg, - Bool msbfirst -){ - int tmp, mask; - - if(xorg) { - if(msbfirst) xorg = 8 - xorg; - mask = RotateMasksX[xorg]; - *pat0 = ((*pat0 >> xorg) & mask) | ((*pat0 << (8 - xorg)) & ~mask); - *pat1 = ((*pat1 >> xorg) & mask) | ((*pat1 << (8 - xorg)) & ~mask); - } - if(yorg >= 4) { - tmp = *pat0; *pat0 = *pat1; *pat1 = tmp; - yorg -= 4; - } - if(yorg) { - mask = RotateMasksY[yorg]; - yorg <<= 3; - tmp = *pat0; - *pat0 = ((*pat0 >> yorg) & mask) | ((*pat1 << (32 - yorg)) & ~mask); - *pat1 = ((*pat1 >> yorg) & mask) | ((tmp << (32 - yorg)) & ~mask); - } -} - - - -void -XAAInvalidatePixmapCache(ScreenPtr pScreen) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAAPixmapCachePrivatePtr pCachePriv = - (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; - int i; - - if(!pCachePriv) return; - - for(i = 0; i < pCachePriv->Num512x512; i++) - (pCachePriv->Info512)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->Num256x256; i++) - (pCachePriv->Info256)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->Num128x128; i++) - (pCachePriv->Info128)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->NumPartial; i++) - (pCachePriv->InfoPartial)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->NumMono; i++) - (pCachePriv->InfoMono)[i].serialNumber = 0; - for(i = 0; i < pCachePriv->NumColor; i++) - (pCachePriv->InfoColor)[i].serialNumber = 0; -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "gc.h" +#include "mi.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "regionstr.h" +#include "servermd.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaacexp.h" +#include "xaalocal.h" +#include "xaawrap.h" + +#define MAX_COLOR 32 +#define MAX_MONO 32 +#define MAX_8 32 +#define MAX_128 32 +#define MAX_256 32 +#define MAX_512 16 + +static int CacheInitIndex = -1; +#define CACHEINIT(p) ((p)->privates[CacheInitIndex].val) + + +typedef struct _CacheLink { + int x; + int y; + int w; + int h; + struct _CacheLink *next; +} CacheLink, *CacheLinkPtr; + + +static void +TransferList(CacheLinkPtr list, XAACacheInfoPtr array, int num) +{ + while(num--) { + array->x = list->x; + array->y = list->y; + array->w = list->w; + array->h = list->h; + array->serialNumber = 0; + array->fg = array->bg = -1; + list = list->next; + array++; + } +} + + + +static CacheLinkPtr +Enlist(CacheLinkPtr link, int x, int y, int w, int h) +{ + CacheLinkPtr newLink; + + newLink = malloc(sizeof(CacheLink)); + newLink->next = link; + newLink->x = x; newLink->y = y; + newLink->w = w; newLink->h = h; + return newLink; +} + + + +static CacheLinkPtr +Delist(CacheLinkPtr link) { + CacheLinkPtr ret = NULL; + + if(link) { + ret = link->next; + free(link); + } + return ret; +} + + + +static void +FreeList(CacheLinkPtr link) { + CacheLinkPtr tmp; + + while(link) { + tmp = link; + link = link->next; + free(tmp); + } +} + + + +static CacheLinkPtr +QuadLinks(CacheLinkPtr big, CacheLinkPtr little) +{ + /* CAUTION: This doesn't free big */ + int w1, w2, h1, h2; + + while(big) { + w1 = big->w >> 1; + w2 = big->w - w1; + h1 = big->h >> 1; + h2 = big->h - h1; + + little = Enlist(little, big->x, big->y, w1, h1); + little = Enlist(little, big->x + w1, big->y, w2, h1); + little = Enlist(little, big->x, big->y + h1, w1, h2); + little = Enlist(little, big->x + w1, big->y + h1, w2, h2); + + big = big->next; + } + return little; +} + + +static void +SubdivideList(CacheLinkPtr *large, CacheLinkPtr *small) +{ + CacheLinkPtr big = *large; + CacheLinkPtr little = *small; + int size = big->w >> 1; + + little = Enlist(little, big->x, big->y, size, size); + little = Enlist(little, big->x + size, big->y, size, size); + little = Enlist(little, big->x, big->y + size, size, size); + little = Enlist(little, big->x + size, big->y + size, size, size); + *small = little; + big = Delist(big); + *large = big; +} + +static void +FreePixmapCachePrivate(XAAPixmapCachePrivatePtr pPriv) +{ + if(!pPriv) return; + + if(pPriv->Info512) + free(pPriv->Info512); + if(pPriv->Info256) + free(pPriv->Info256); + if(pPriv->Info128) + free(pPriv->Info128); + if(pPriv->InfoColor) + free(pPriv->InfoColor); + if(pPriv->InfoMono) + free(pPriv->InfoMono); + if(pPriv->InfoPartial) + free(pPriv->InfoPartial); + + free(pPriv); +} + +void +XAAClosePixmapCache(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + if(infoRec->PixmapCachePrivate) + FreePixmapCachePrivate( + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); + + infoRec->PixmapCachePrivate = NULL; +} + + + +static CacheLinkPtr +ThinOutPartials( + CacheLinkPtr ListPartial, + int *num, int *maxw, int *maxh +) { +/* This guy's job is to get at least 4 big slots out of a list of fragments */ + + CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; + int Num64, Num32, Num16, Num8, NumKeepers; + int w, h; + + List64 = List32 = List16 = List8 = ListKeepers = NULL; + Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; + w = h = 0; + + /* We sort partials by how large a square tile they can cache. + If a partial can't store a 64x64, 32x32, 16x16 or 8x8 tile, + we free it. */ + + pCur = ListPartial; + while(pCur) { + next = pCur->next; + if((pCur->w >= 64) && (pCur->h >= 64)) { + pCur->next = List64; List64 = pCur; + Num64++; + } else + if((pCur->w >= 32) && (pCur->h >= 32)) { + pCur->next = List32; List32 = pCur; + Num32++; + } else + if((pCur->w >= 16) && (pCur->h >= 16)) { + pCur->next = List16; List16 = pCur; + Num16++; + } else + if((pCur->w >= 8) && (pCur->h >= 8)) { + pCur->next = List8; List8 = pCur; + Num8++; + } else { + free(pCur); + } + + pCur = next; + } + + /* We save all the tiles from the largest bin that we can get + at least 4 of. If there are too few of a bigger slot, we + cut it in fourths to make smaller slots. */ + + if(Num64 >= 4) { + ListKeepers = List64; List64 = NULL; + NumKeepers = Num64; + goto GOT_EM; + } else if(Num64) { + List32 = QuadLinks(List64, List32); + Num32 += Num64 * 4; + Num64 = 0; + } + + if(Num32 >= 4) { + ListKeepers = List32; List32 = NULL; + NumKeepers = Num32; + goto GOT_EM; + } else if(Num32) { + List16 = QuadLinks(List32, List16); + Num16 += Num32 * 4; + Num32 = 0; + } + + if(Num16 >= 4) { + ListKeepers = List16; List16 = NULL; + NumKeepers = Num16; + goto GOT_EM; + } else if(Num16) { + List8 = QuadLinks(List16, List8); + Num8 += Num16 * 4; + Num16 = 0; + } + + if(Num8 >= 4) { + ListKeepers = List8; List8 = NULL; + NumKeepers = Num8; + goto GOT_EM; + } + +GOT_EM: + + /* Free the ones we aren't using */ + + if(List64) FreeList(List64); + if(List32) FreeList(List32); + if(List16) FreeList(List16); + if(List8) FreeList(List8); + + + /* Enlarge the slots if we can */ + + if(ListKeepers) { + CacheLinkPtr pLink = ListKeepers; + w = h = 128; + + while(pLink) { + if(pLink->w < w) w = pLink->w; + if(pLink->h < h) h = pLink->h; + pLink = pLink->next; + } + } + + *maxw = w; + *maxh = h; + *num = NumKeepers; + return ListKeepers; +} + +static void +ConvertColorToMono( + CacheLinkPtr *ColorList, + int ColorW, int ColorH, + CacheLinkPtr *MonoList, + int MonoW, int MonoH +){ + int x, y, w; + + x = (*ColorList)->x; y = (*ColorList)->y; + *ColorList = Delist(*ColorList); + + while(ColorH) { + ColorH -= MonoH; + for(w = 0; w <= (ColorW - MonoW); w += MonoW) + *MonoList = Enlist(*MonoList, x + w, y + ColorH, MonoW, MonoH); + } +} + +static void +ConvertAllPartialsTo8x8( + int *NumMono, int *NumColor, + CacheLinkPtr ListPartial, + CacheLinkPtr *ListMono, + CacheLinkPtr *ListColor, + XAAInfoRecPtr infoRec +){ +/* This guy extracts as many 8x8 slots as it can out of fragments */ + + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + int x, y, w, Height, Width; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + CacheLinkPtr pLink = ListPartial; + CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; + + if(DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if(MonoH > ColorH) ColorH = MonoH; + if(MonoW > ColorW) ColorW = MonoW; + } + + /* Break up the area into as many Color and Mono slots as we can */ + + while(pLink) { + Height = pLink->h; + Width = pLink->w; + x = pLink->x; + y = pLink->y; + + if(DoColor) { + while(Height >= ColorH) { + Height -= ColorH; + for(w = 0; w <= (Width - ColorW); w += ColorW) { + ColorList = Enlist( + ColorList, x + w, y + Height, ColorW, ColorH); + (*NumColor)++; + } + } + } + + if(DoMono && (Height >= MonoH)) { + while(Height >= MonoH) { + Height -= MonoH; + for(w = 0; w <= (Width - MonoW); w += MonoW) { + MonoList = Enlist( + MonoList, x + w, y + Height, MonoW, MonoH); + (*NumMono)++; + } + } + } + + pLink = pLink->next; + } + + + *ListMono = MonoList; + *ListColor = ColorList; + FreeList(ListPartial); +} + + +static CacheLinkPtr +ExtractOneThatFits(CacheLinkPtr *initList, int w, int h) +{ + CacheLinkPtr list = *initList; + CacheLinkPtr prev = NULL; + + while(list) { + if((list->w >= w) && (list->h >= h)) + break; + prev = list; + list = list->next; + } + + if(list) { + if(prev) + prev->next = list->next; + else + *initList = list->next; + + list->next = NULL; + } + + return list; +} + + +static CacheLinkPtr +ConvertSomePartialsTo8x8( + int *NumMono, int *NumColor, int *NumPartial, + CacheLinkPtr ListPartial, + CacheLinkPtr *ListMono, + CacheLinkPtr *ListColor, + int *maxw, int *maxh, + XAAInfoRecPtr infoRec +){ +/* This guy tries to get 4 of each type of 8x8 slot requested out of + a list of fragments all while trying to retain some big fragments + for the cache blits */ + + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + CacheLinkPtr List64, List32, List16, List8, pCur, next, ListKeepers; + CacheLinkPtr MonoList = *ListMono, ColorList = *ListColor; + int Num64, Num32, Num16, Num8, NumKeepers; + int w, h, Width, Height; + int MonosPerColor = 1; + + if(DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if(MonoH > ColorH) ColorH = MonoH; + if(MonoW > ColorW) ColorW = MonoW; + MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); + } + + List64 = List32 = List16 = List8 = ListKeepers = MonoList = ColorList = NULL; + Num64 = Num32 = Num16 = Num8 = NumKeepers = 0; + Width = Height = 0; + + /* We sort partials by how large a square tile they can cache. + We make 8x8 patterns from the leftovers if we can. */ + + pCur = ListPartial; + while(pCur) { + next = pCur->next; + if((pCur->w >= 64) && (pCur->h >= 64)) { + pCur->next = List64; List64 = pCur; + Num64++; + } else + if((pCur->w >= 32) && (pCur->h >= 32)) { + pCur->next = List32; List32 = pCur; + Num32++; + } else + if((pCur->w >= 16) && (pCur->h >= 16)) { + pCur->next = List16; List16 = pCur; + Num16++; + } else + if((pCur->w >= 8) && (pCur->h >= 8)) { + pCur->next = List8; List8 = pCur; + Num8++; + } else { + h = pCur->h; + if(DoColor && (pCur->w >= ColorW) && (h >= ColorH)) { + while(h >= ColorH) { + h -= ColorH; + for(w = 0; w <= (pCur->w - ColorW); w += ColorW) { + ColorList = Enlist( ColorList, + pCur->x + w, pCur->y + h, ColorW, ColorH); + (*NumColor)++; + } + } + } + if(DoMono && (pCur->w >= MonoW) && (h >= MonoH)) { + while(h >= MonoH) { + h -= MonoH; + for(w = 0; w <= (pCur->w - MonoW); w += MonoW) { + MonoList = Enlist( MonoList, + pCur->x + w, pCur->y + h, MonoW, MonoH); + (*NumMono)++; + } + } + } + free(pCur); + } + + pCur = next; + } + + /* Try to extract at least 4 of each type of 8x8 slot that we need */ + + if(DoColor) { + CacheLinkPtr theOne; + while(*NumColor < 4) { + theOne = NULL; + if(Num8) { + if((theOne = ExtractOneThatFits(&List8, ColorW, ColorH))) + Num8--; + } + if(Num16 && !theOne) { + if((theOne = ExtractOneThatFits(&List16, ColorW, ColorH))) + Num16--; + } + if(Num32 && !theOne) { + if((theOne = ExtractOneThatFits(&List32, ColorW, ColorH))) + Num32--; + } + if(Num64 && !theOne) { + if((theOne = ExtractOneThatFits(&List64, ColorW, ColorH))) + Num64--; + } + + if(!theOne) break; + + + ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, + &MonoList, &ColorList, infoRec); + + if(DoMono) { + while(*NumColor && (*NumMono < 4)) { + ConvertColorToMono(&ColorList, ColorW, ColorH, + &MonoList, MonoW, MonoH); + (*NumColor)--; *NumMono += MonosPerColor; + } + } + } + } + + if(DoMono) { + CacheLinkPtr theOne; + while(*NumMono < 4) { + theOne = NULL; + if(Num8) { + if((theOne = ExtractOneThatFits(&List8, MonoW, MonoH))) + Num8--; + } + if(Num16 && !theOne) { + if((theOne = ExtractOneThatFits(&List16, MonoW, MonoH))) + Num16--; + } + if(Num32 && !theOne) { + if((theOne = ExtractOneThatFits(&List32, MonoW, MonoH))) + Num32--; + } + if(Num64 && !theOne) { + if((theOne = ExtractOneThatFits(&List64, MonoW, MonoH))) + Num64--; + } + + if(!theOne) break; + + ConvertAllPartialsTo8x8(NumMono, NumColor, theOne, + &MonoList, &ColorList, infoRec); + } + } + + /* We save all the tiles from the largest bin that we can get + at least 4 of. If there are too few of a bigger slot, we + cut it in fourths to make smaller slots. */ + + if(Num64 >= 4) { + ListKeepers = List64; List64 = NULL; + NumKeepers = Num64; + goto GOT_EM; + } else if(Num64) { + List32 = QuadLinks(List64, List32); + Num32 += Num64 * 4; + Num64 = 0; + } + + if(Num32 >= 4) { + ListKeepers = List32; List32 = NULL; + NumKeepers = Num32; + goto GOT_EM; + } else if(Num32) { + List16 = QuadLinks(List32, List16); + Num16 += Num32 * 4; + Num32 = 0; + } + + if(Num16 >= 4) { + ListKeepers = List16; List16 = NULL; + NumKeepers = Num16; + goto GOT_EM; + } else if(Num16) { + List8 = QuadLinks(List16, List8); + Num8 += Num16 * 4; + Num16 = 0; + } + + if(Num8 >= 4) { + ListKeepers = List8; List8 = NULL; + NumKeepers = Num8; + goto GOT_EM; + } + +GOT_EM: + + /* Free the ones we aren't using */ + + if(List64) + ConvertAllPartialsTo8x8(NumMono, NumColor, List64, + &MonoList, &ColorList, infoRec); + if(List32) + ConvertAllPartialsTo8x8(NumMono, NumColor, List32, + &MonoList, &ColorList, infoRec); + if(List16) + ConvertAllPartialsTo8x8(NumMono, NumColor, List16, + &MonoList, &ColorList, infoRec); + if(List8) + ConvertAllPartialsTo8x8(NumMono, NumColor, List8, + &MonoList, &ColorList, infoRec); + + + /* Enlarge the slots if we can */ + + if(ListKeepers) { + CacheLinkPtr pLink = ListKeepers; + Width = Height = 128; + + while(pLink) { + if(pLink->w < Width) Width = pLink->w; + if(pLink->h < Height) Height = pLink->h; + pLink = pLink->next; + } + } + + *ListMono = MonoList; + *ListColor = ColorList; + *maxw = Width; + *maxh = Height; + *NumPartial = NumKeepers; + return ListKeepers; +} + + +void +XAAInitPixmapCache( + ScreenPtr pScreen, + RegionPtr areas, + pointer data +) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XAAInfoRecPtr infoRec = (XAAInfoRecPtr)data; + XAAPixmapCachePrivatePtr pCachePriv; + BoxPtr pBox = REGION_RECTS(areas); + int nBox = REGION_NUM_RECTS(areas); + int Num512, Num256, Num128, NumPartial, NumColor, NumMono; + int Target512, Target256; + CacheLinkPtr List512, List256, List128, ListPartial, ListColor, ListMono; + int x, y, w, h, ntotal, granularity, width, height, i; + int MaxPartialWidth, MaxPartialHeight; + + infoRec->MaxCacheableTileWidth = 0; + infoRec->MaxCacheableTileHeight = 0; + infoRec->MaxCacheableStippleHeight = 0; + infoRec->MaxCacheableStippleWidth = 0; + infoRec->UsingPixmapCache = FALSE; + + + if(!nBox || !pBox || !(infoRec->Flags & PIXMAP_CACHE)) + return; + + /* Allocate a persistent per-screen init flag to control messages */ + if (CacheInitIndex < 0) + CacheInitIndex = xf86AllocateScrnInfoPrivateIndex(); + + /* free the old private data if it exists */ + if(infoRec->PixmapCachePrivate) { + FreePixmapCachePrivate( + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate); + infoRec->PixmapCachePrivate = NULL; + } + + Num512 = Num256 = Num128 = NumPartial = NumMono = NumColor = 0; + List512 = List256 = List128 = ListPartial = ListMono = ListColor = NULL; + granularity = infoRec->CachePixelGranularity; + if(granularity <= 1) granularity = 0; + + /* go through the boxes and break it into as many pieces as we can fit */ + + while(nBox--) { + x = pBox->x1; + if(granularity) { + int tmp = x % granularity; + if(tmp) x += (granularity - tmp); + } + width = pBox->x2 - x; + if(width <= 0) {pBox++; continue;} + + y = pBox->y1; + height = pBox->y2 - y; + + for(h = 0; h <= (height - 512); h += 512) { + for(w = 0; w <= (width - 512); w += 512) { + List512 = Enlist(List512, x + w, y + h, 512, 512); + Num512++; + } + for(; w <= (width - 256); w += 256) { + List256 = Enlist(List256, x + w, y + h, 256, 256); + List256 = Enlist(List256, x + w, y + h + 256, 256, 256); + Num256 += 2; + } + for(; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + List128 = Enlist(List128, x + w, y + h + 128, 128, 128); + List128 = Enlist(List128, x + w, y + h + 256, 128, 128); + List128 = Enlist(List128, x + w, y + h + 384, 128, 128); + Num128 += 4; + } + if(w < width) { + int d = width - w; + ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 256, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 384, d, 128); + NumPartial += 4; + } + } + for(; h <= (height - 256); h += 256) { + for(w = 0; w <= (width - 256); w += 256) { + List256 = Enlist(List256, x + w, y + h, 256, 256); + Num256++; + } + for(; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + List128 = Enlist(List128, x + w, y + h + 128, 128, 128); + Num128 += 2; + } + if(w < width) { + int d = width - w; + ListPartial = Enlist(ListPartial, x + w, y + h, d, 128); + ListPartial = Enlist(ListPartial, x + w, y + h + 128, d, 128); + NumPartial += 2; + } + } + for(; h <= (height - 128); h += 128) { + for(w = 0; w <= (width - 128); w += 128) { + List128 = Enlist(List128, x + w, y + h, 128, 128); + Num128++; + } + if(w < width) { + ListPartial = Enlist( + ListPartial, x + w, y + h, width - w, 128); + NumPartial++; + } + } + if(h < height) { + int d = height - h; + for(w = 0; w <= (width - 128); w += 128) { + ListPartial = Enlist(ListPartial, x + w, y + h, 128, d); + NumPartial++; + } + if(w < width) { + ListPartial = Enlist(ListPartial, x + w, y + h, width - w, d); + NumPartial++; + } + } + pBox++; + } + + +/* + by this point we've carved the space into as many 512x512, 256x256 + and 128x128 blocks as we could fit. We will then break larger + blocks into smaller ones if we need to. The rules are as follows: + + 512x512 - + 1) Don't take up more than half the memory. + 2) Don't bother if you can't get at least four. + 3) Don't make more than MAX_512. + 4) Don't have any of there are no 256x256s. + + 256x256 - + 1) Don't take up more than a quarter of the memory enless there + aren't any 512x512s. Then we can take up to half. + 2) Don't bother if you can't get at least four. + 3) Don't make more than MAX_256. + + 128x128 - + 1) Don't make more than MAX_128. + + We don't bother with the partial blocks unless we can use them + for 8x8 pattern fills or we are short on larger blocks. + +*/ + + ntotal = Num128 + (Num256<<2) + (Num512<<4); + + Target512 = ntotal >> 5; + if(Target512 < 4) Target512 = 0; + if(!Target512) Target256 = ntotal >> 3; + else Target256 = ntotal >> 4; + if(Target256 < 4) Target256 = 0; + + if(Num512 && Num256 < 4) { + while(Num512 && Num256 < Target256) { + SubdivideList(&List512, &List256); + Num256 += 4; Num512--; + } + } + + if(!Num512) { /* no room */ + } else if((Num512 < 4) || (!Target512)) { + while(Num512) { + SubdivideList(&List512, &List256); + Num256 += 4; Num512--; + } + } else if((Num512 > MAX_512) || (Num512 > Target512)){ + while(Num512 > MAX_512) { + SubdivideList(&List512, &List256); + Num256 += 4; Num512--; + } + while(Num512 > Target512) { + if(Num256 < MAX_256) { + SubdivideList(&List512, &List256); + Num256 += 4; Num512--; + } else break; + } + } + + if(!Num256) { /* no room */ + } else if((Num256 < 4) || (!Target256)) { + while(Num256) { + SubdivideList(&List256, &List128); + Num128 += 4; Num256--; + } + } else if((Num256 > MAX_256) || (Num256 > Target256)) { + while(Num256 > MAX_256) { + SubdivideList(&List256, &List128); + Num128 += 4; Num256--; + } + while(Num256 > Target256) { + if(Num128 < MAX_128) { + SubdivideList(&List256, &List128); + Num128 += 4; Num256--; + } else break; + } + } + + if(Num128 && ((Num128 < 4) || (Num128 > MAX_128))) { + CacheLinkPtr next; + int max = (Num128 > MAX_128) ? MAX_128 : 0; + + /* + * Note: next is set in this way to work around a code generation + * bug in gcc 2.7.2.3. + */ + next = List128->next; + while(Num128 > max) { + List128->next = ListPartial; + ListPartial = List128; + if((List128 = next)) + next = List128->next; + NumPartial++; Num128--; + } + } + + MaxPartialHeight = MaxPartialWidth = 0; + + /* at this point we have as many 512x512 and 256x256 slots as we + want but may have an excess of 128x128 slots. We still need + to find out if we need 8x8 slots. We take these from the + partials if we have them. Otherwise, we break some 128x128's */ + + if(!(infoRec->PixmapCacheFlags & (CACHE_MONO_8x8 | CACHE_COLOR_8x8))) { + if(NumPartial) { + if(Num128) { /* don't bother with partials */ + FreeList(ListPartial); + NumPartial = 0; ListPartial = NULL; + } else { + /* We have no big slots. Weed out the unusable partials */ + ListPartial = ThinOutPartials(ListPartial, &NumPartial, + &MaxPartialWidth, &MaxPartialHeight); + } + } + } else { + int MonosPerColor = 1; + int ColorH = infoRec->CacheHeightColor8x8Pattern; + int ColorW = infoRec->CacheWidthColor8x8Pattern; + int MonoH = infoRec->CacheHeightMono8x8Pattern; + int MonoW = infoRec->CacheWidthMono8x8Pattern; + Bool DoColor = (infoRec->PixmapCacheFlags & CACHE_COLOR_8x8); + Bool DoMono = (infoRec->PixmapCacheFlags & CACHE_MONO_8x8); + + if(DoColor) infoRec->CanDoColor8x8 = FALSE; + if(DoMono) infoRec->CanDoMono8x8 = FALSE; + + if(DoColor && DoMono) { + /* we assume color patterns take more space than color ones */ + if(MonoH > ColorH) ColorH = MonoH; + if(MonoW > ColorW) ColorW = MonoW; + MonosPerColor = (ColorH/MonoH) * (ColorW/MonoW); + } + + if(Num128) { + if(NumPartial) { /* use all for 8x8 slots */ + ConvertAllPartialsTo8x8(&NumMono, &NumColor, + ListPartial, &ListMono, &ListColor, infoRec); + NumPartial = 0; ListPartial = NULL; + } + + /* Get some 8x8 slots from the 128 slots */ + while((Num128 > 4) && + ((NumMono < MAX_MONO) && (NumColor < MAX_COLOR))) { + CacheLinkPtr tmp = NULL; + + tmp = Enlist(tmp, List128->x, List128->y, + List128->w, List128->h); + List128 = Delist(List128); + Num128--; + + ConvertAllPartialsTo8x8(&NumMono, &NumColor, + tmp, &ListMono, &ListColor, infoRec); + } + } else if(NumPartial) { + /* We have share partials between 8x8 slots and tiles. */ + ListPartial = ConvertSomePartialsTo8x8(&NumMono, &NumColor, + &NumPartial, ListPartial, &ListMono, &ListColor, + &MaxPartialWidth, &MaxPartialHeight, infoRec); + } + + + if(DoMono && DoColor) { + if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { + int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; + + while(NumColor > max) { + ConvertColorToMono(&ListColor, ColorW, ColorH, + &ListMono, MonoW, MonoH); + NumColor--; NumMono += MonosPerColor; + } + } + + /* favor Mono slots over Color ones */ + while((NumColor > 4) && (NumMono < MAX_MONO)) { + ConvertColorToMono(&ListColor, ColorW, ColorH, + &ListMono, MonoW, MonoH); + NumColor--; NumMono += MonosPerColor; + } + } + + if(NumMono && ((NumMono > MAX_MONO) || (NumMono < 4))) { + int max = (NumMono > MAX_MONO) ? MAX_MONO : 0; + + while(NumMono > max) { + ListMono = Delist(ListMono); + NumMono--; + } + } + if(NumColor && ((NumColor > MAX_COLOR) || (NumColor < 4))) { + int max = (NumColor > MAX_COLOR) ? MAX_COLOR : 0; + + while(NumColor > max) { + ListColor = Delist(ListColor); + NumColor--; + } + } + } + + + pCachePriv = calloc(1,sizeof(XAAPixmapCachePrivate)); + if(!pCachePriv) { + if(Num512) FreeList(List512); + if(Num256) FreeList(List256); + if(Num128) FreeList(List128); + if(NumPartial) FreeList(ListPartial); + if(NumColor) FreeList(ListColor); + if(NumMono) FreeList(ListMono); + return; + } + + infoRec->PixmapCachePrivate = (char*)pCachePriv; + + if(Num512) { + pCachePriv->Info512 = calloc(Num512,sizeof(XAACacheInfoRec)); + if(!pCachePriv->Info512) Num512 = 0; + if(Num512) TransferList(List512, pCachePriv->Info512, Num512); + FreeList(List512); + pCachePriv->Num512x512 = Num512; + } + if(Num256) { + pCachePriv->Info256 = calloc(Num256, sizeof(XAACacheInfoRec)); + if(!pCachePriv->Info256) Num256 = 0; + if(Num256) TransferList(List256, pCachePriv->Info256, Num256); + FreeList(List256); + pCachePriv->Num256x256 = Num256; + } + if(Num128) { + pCachePriv->Info128 = calloc(Num128, sizeof(XAACacheInfoRec)); + if(!pCachePriv->Info128) Num128 = 0; + if(Num128) TransferList(List128, pCachePriv->Info128, Num128); + FreeList(List128); + pCachePriv->Num128x128 = Num128; + } + + if(NumPartial) { + pCachePriv->InfoPartial = calloc(NumPartial, sizeof(XAACacheInfoRec)); + if(!pCachePriv->InfoPartial) NumPartial = 0; + if(NumPartial) + TransferList(ListPartial, pCachePriv->InfoPartial, NumPartial); + FreeList(ListPartial); + pCachePriv->NumPartial = NumPartial; + } + + if(NumColor) { + pCachePriv->InfoColor = calloc(NumColor, sizeof(XAACacheInfoRec)); + if(!pCachePriv->InfoColor) NumColor = 0; + if(NumColor) TransferList(ListColor, pCachePriv->InfoColor, NumColor); + FreeList(ListColor); + pCachePriv->NumColor = NumColor; + } + + if(NumMono) { + pCachePriv->InfoMono = calloc(NumMono, sizeof(XAACacheInfoRec)); + if(!pCachePriv->InfoMono) NumMono = 0; + if(NumMono) TransferList(ListMono, pCachePriv->InfoMono, NumMono); + FreeList(ListMono); + pCachePriv->NumMono = NumMono; + } + + + if(NumPartial) { + infoRec->MaxCacheableTileWidth = MaxPartialWidth; + infoRec->MaxCacheableTileHeight = MaxPartialHeight; + } + if(Num128) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 128; + if(Num256) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 256; + if(Num512) + infoRec->MaxCacheableTileWidth = infoRec->MaxCacheableTileHeight = 512; + + + infoRec->MaxCacheableStippleHeight = infoRec->MaxCacheableTileHeight; + infoRec->MaxCacheableStippleWidth = + infoRec->MaxCacheableTileWidth * pScrn->bitsPerPixel; + if(infoRec->ScreenToScreenColorExpandFillFlags & TRIPLE_BITS_24BPP) + infoRec->MaxCacheableStippleWidth /= 3; + + if(NumMono) { + if(!(infoRec->Mono8x8PatternFillFlags & + (HARDWARE_PATTERN_PROGRAMMED_ORIGIN | + HARDWARE_PATTERN_PROGRAMMED_BITS))) { + int numPerLine = + infoRec->CacheWidthMono8x8Pattern/infoRec->MonoPatternPitch; + + for(i = 0; i < 64; i++) { + pCachePriv->MonoOffsets[i].y = i/numPerLine; + pCachePriv->MonoOffsets[i].x = (i % numPerLine) * + infoRec->MonoPatternPitch; + } + } + infoRec->CanDoMono8x8 = TRUE; + } + if(NumColor) { + if(!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) { + + for(i = 0; i < 64; i++) { + pCachePriv->ColorOffsets[i].y = i & 0x07; + pCachePriv->ColorOffsets[i].x = i & ~0x07; + } + } + infoRec->CanDoColor8x8 = TRUE; + } + + if(!CACHEINIT(pScrn)) { + xf86ErrorF("\tSetting up tile and stipple cache:\n"); + if(NumPartial) + xf86ErrorF("\t\t%i %ix%i slots\n", + NumPartial, MaxPartialWidth, MaxPartialHeight); + if(Num128) xf86ErrorF("\t\t%i 128x128 slots\n", Num128); + if(Num256) xf86ErrorF("\t\t%i 256x256 slots\n", Num256); + if(Num512) xf86ErrorF("\t\t%i 512x512 slots\n", Num512); + if(NumColor) xf86ErrorF("\t\t%i 8x8 color pattern slots\n", NumColor); + if(NumMono) xf86ErrorF("\t\t%i 8x8 color expansion slots\n", NumMono); + } + + if(!(NumPartial | Num128 | Num256 | Num512 | NumColor | NumMono)) { + if(!CACHEINIT(pScrn)) + xf86ErrorF("\t\tNot enough video memory for pixmap cache\n"); + } else infoRec->UsingPixmapCache = TRUE; + + CACHEINIT(pScrn) = 1; +} + +#if X_BYTE_ORDER == X_BIG_ENDIAN +static CARD32 StippleMasks[4] = { + 0x80808080, + 0xC0C0C0C0, + 0x00000000, + 0xF0F0F0F0 +}; +#else +static CARD32 StippleMasks[4] = { + 0x01010101, + 0x03030303, + 0x00000000, + 0x0F0F0F0F +}; +#endif + +Bool +XAACheckStippleReducibility(PixmapPtr pPixmap) +{ + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); + CARD32 *IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + int w = pPixmap->drawable.width; + int h = pPixmap->drawable.height; + int i; + CARD32 bits[8]; + CARD32 mask = SHIFT_R(0xFFFFFFFF,24); + + pPriv->flags |= REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR; + pPriv->flags &= ~REDUCIBLE_TO_8x8; + + if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) + return FALSE; + + i = (h > 8) ? 8 : h; + + switch(w) { + case 32: + while(i--) { + bits[i] = IntPtr[i] & mask; + if( (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask, 8)), 8)) || + (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,16)),16)) || + (bits[i] != SHIFT_R((IntPtr[i] & SHIFT_L(mask,24)),24))) + return FALSE; + } + break; + case 16: + while(i--) { + bits[i] = IntPtr[i] & mask; + if(bits[i] != ((IntPtr[i] & SHIFT_R(SHIFT_L(mask,8),8)))) + return FALSE; + } + break; + default: + while(i--) + bits[i] = IntPtr[i] & mask; + break; + } + + switch(h) { + case 32: + if( (IntPtr[8] != IntPtr[16]) || (IntPtr[9] != IntPtr[17]) || + (IntPtr[10] != IntPtr[18]) || (IntPtr[11] != IntPtr[19]) || + (IntPtr[12] != IntPtr[20]) || (IntPtr[13] != IntPtr[21]) || + (IntPtr[14] != IntPtr[22]) || (IntPtr[15] != IntPtr[23]) || + (IntPtr[16] != IntPtr[24]) || (IntPtr[17] != IntPtr[25]) || + (IntPtr[18] != IntPtr[26]) || (IntPtr[19] != IntPtr[27]) || + (IntPtr[20] != IntPtr[28]) || (IntPtr[21] != IntPtr[29]) || + (IntPtr[22] != IntPtr[30]) || (IntPtr[23] != IntPtr[31])) + return FALSE; + /* fall through */ + case 16: + if( (IntPtr[0] != IntPtr[8]) || (IntPtr[1] != IntPtr[9]) || + (IntPtr[2] != IntPtr[10]) || (IntPtr[3] != IntPtr[11]) || + (IntPtr[4] != IntPtr[12]) || (IntPtr[5] != IntPtr[13]) || + (IntPtr[6] != IntPtr[14]) || (IntPtr[7] != IntPtr[15])) + return FALSE; + case 8: break; + case 1: bits[1] = bits[0]; + case 2: bits[2] = bits[0]; bits[3] = bits[1]; + case 4: bits[4] = bits[0]; bits[5] = bits[1]; + bits[6] = bits[2]; bits[7] = bits[3]; + break; + } + + pPriv->flags |= REDUCIBLE_TO_8x8; + + pPriv->pattern0 = bits[0] | SHIFT_L(bits[1],8) | SHIFT_L(bits[2],16) | SHIFT_L(bits[3],24); + pPriv->pattern1 = bits[4] | SHIFT_L(bits[5],8) | SHIFT_L(bits[6],16) | SHIFT_L(bits[7],24); + + if(w < 8) { + pPriv->pattern0 &= StippleMasks[w - 1]; + pPriv->pattern1 &= StippleMasks[w - 1]; + + switch(w) { + case 1: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,1); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,1); + case 2: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,2); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,2); + case 4: pPriv->pattern0 |= SHIFT_L(pPriv->pattern0,4); + pPriv->pattern1 |= SHIFT_L(pPriv->pattern1,4); + } + } + + if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); + pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); + } + + + return TRUE; +} + + +Bool +XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono) +{ + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + CARD32 *IntPtr; + int w = pPixmap->drawable.width; + int h = pPixmap->drawable.height; + int pitch = pPixmap->devKind >> 2; + int dwords, i, j; + + pPriv->flags |= REDUCIBILITY_CHECKED; + pPriv->flags &= ~(REDUCIBILITY_CHECKED | REDUCIBLE_TO_2_COLOR); + + if((w > 32) || (h > 32) || (w & (w - 1)) || (h & (h - 1))) + return FALSE; + + dwords = ((w * pPixmap->drawable.bitsPerPixel) + 31) >> 5; + i = (h > 8) ? 8 : h; + + + if(w > 8) { + IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + switch(pPixmap->drawable.bitsPerPixel) { + case 8: + while(i--) { + for(j = 2; j < dwords; j++) + if(IntPtr[j] != IntPtr[j & 0x01]) + return FALSE; + IntPtr += pitch; + } + break; + case 16: + while(i--) { + for(j = 4; j < dwords; j++) + if(IntPtr[j] != IntPtr[j & 0x03]) + return FALSE; + IntPtr += pitch; + } + break; + case 24: + while(i--) { + for(j = 6; j < dwords; j++) + if(IntPtr[j] != IntPtr[j % 6]) + return FALSE; + IntPtr += pitch; + } + break; + case 32: + while(i--) { + for(j = 8; j < dwords; j++) + if(IntPtr[j] != IntPtr[j & 0x07]) + return FALSE; + IntPtr += pitch; + } + break; + default: return FALSE; + } + + } + + + if(h == 32) { + CARD32 *IntPtr2, *IntPtr3, *IntPtr4; + i = 8; + IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + IntPtr2 = IntPtr + (pitch << 3); + IntPtr3 = IntPtr2 + (pitch << 3); + IntPtr4 = IntPtr3 + (pitch << 3); + while(i--) { + for(j = 0; j < dwords; j++) + if((IntPtr[j] != IntPtr2[j]) || (IntPtr[j] != IntPtr3[j]) || + (IntPtr[j] != IntPtr4[j])) + return FALSE; + IntPtr += pitch; + IntPtr2 += pitch; + IntPtr3 += pitch; + IntPtr4 += pitch; + } + } else if (h == 16) { + CARD32 *IntPtr2; + i = 8; + IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + IntPtr2 = IntPtr + (pitch << 3); + while(i--) { + for(j = 0; j < dwords; j++) + if(IntPtr[j] != IntPtr2[j]) + return FALSE; + IntPtr += pitch; + IntPtr2 += pitch; + } + } + + pPriv->flags |= REDUCIBLE_TO_8x8; + + if(checkMono) { + XAAInfoRecPtr infoRec = + GET_XAAINFORECPTR_FROM_DRAWABLE(&pPixmap->drawable); + unsigned char bits[8]; + int fg, bg = -1, x, y; + + i = (h > 8) ? 8 : h; + j = (w > 8) ? 8 : w; + + if(pPixmap->drawable.bitsPerPixel == 8) { + unsigned char *srcp = pPixmap->devPrivate.ptr; + fg = srcp[0]; + pitch = pPixmap->devKind; + for(y = 0; y < i; y++) { + bits[y] = 0; + for(x = 0; x < j; x++) { + if(srcp[x] != fg) { + if(bg == -1) bg = srcp[x]; + else if(bg != srcp[x]) return TRUE; + } else bits[y] |= 1 << x; + } + srcp += pitch; + } + } else if(pPixmap->drawable.bitsPerPixel == 16) { + unsigned short *srcp = (unsigned short*)pPixmap->devPrivate.ptr; + fg = srcp[0]; + pitch = pPixmap->devKind >> 1; + for(y = 0; y < i; y++) { + bits[y] = 0; + for(x = 0; x < j; x++) { + if(srcp[x] != fg) { + if(bg == -1) bg = srcp[x]; + else if(bg != srcp[x]) return TRUE; + } else bits[y] |= 1 << x; + } + srcp += pitch; + } + } else if(pPixmap->drawable.bitsPerPixel == 24) { + CARD32 val; + unsigned char *srcp = pPixmap->devPrivate.ptr; + fg = *((CARD32*)srcp) & 0x00FFFFFF; + pitch = pPixmap->devKind; + j *= 3; + for(y = 0; y < i; y++) { + bits[y] = 0; + for(x = 0; x < j; x+=3) { + val = *((CARD32*)(srcp+x)) & 0x00FFFFFF; + if(val != fg) { + if(bg == -1) bg = val; + else if(bg != val) + return TRUE; + } else bits[y] |= 1 << (x/3); + } + srcp += pitch; + } + } else if(pPixmap->drawable.bitsPerPixel == 32) { + IntPtr = (CARD32*)pPixmap->devPrivate.ptr; + fg = IntPtr[0]; + for(y = 0; y < i; y++) { + bits[y] = 0; + for(x = 0; x < j; x++) { + if(IntPtr[x] != fg) { + if(bg == -1) bg = IntPtr[x]; + else if(bg != IntPtr[x]) return TRUE; + } else bits[y] |= 1 << x; + } + IntPtr += pitch; + } + } else return TRUE; + + pPriv->fg = fg; + if(bg == -1) pPriv->bg = fg; + else pPriv->bg = bg; + + if(h < 8) { + switch(h) { + case 1: bits[1] = bits[0]; + case 2: bits[2] = bits[0]; bits[3] = bits[1]; + case 4: bits[4] = bits[0]; bits[5] = bits[1]; + bits[6] = bits[2]; bits[7] = bits[3]; + break; + } + } + + pPriv->pattern0 = + bits[0] | (bits[1]<<8) | (bits[2]<<16) | (bits[3]<<24); + pPriv->pattern1 = + bits[4] | (bits[5]<<8) | (bits[6]<<16) | (bits[7]<<24); + + if(w < 8) { + switch(w) { + case 1: pPriv->pattern0 |= (pPriv->pattern0 << 1); + pPriv->pattern1 |= (pPriv->pattern1 << 1); + case 2: pPriv->pattern0 |= (pPriv->pattern0 << 2); + pPriv->pattern1 |= (pPriv->pattern1 << 2); + case 4: pPriv->pattern0 |= (pPriv->pattern0 << 4); + pPriv->pattern1 |= (pPriv->pattern1 << 4); + } + } + pPriv->flags |= REDUCIBLE_TO_2_COLOR; + + if(infoRec->Mono8x8PatternFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) { + pPriv->pattern0 = SWAP_BITS_IN_BYTES(pPriv->pattern0); + pPriv->pattern1 = SWAP_BITS_IN_BYTES(pPriv->pattern1); + } + + } + + return TRUE; +} + + +void XAATileCache( + ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache, + int w, int h +) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, GXcopy, ~0, -1); + + while((w << 1) <= pCache->w) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, + pCache->x + w, pCache->y, w, h); + w <<= 1; + } + if(w != pCache->w) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, + pCache->x + w, pCache->y, pCache->w - w, h); + w = pCache->w; + } + + while((h << 1) <= pCache->h) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, + pCache->x, pCache->y + h, w, h); + h <<= 1; + } + if(h != pCache->h) { + (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pCache->x, pCache->y, + pCache->x, pCache->y + h, w, pCache->h - h); + } + SET_SYNC_FLAG(infoRec); +} + +XAACacheInfoPtr +XAACacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + int size = max(w, h); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if(size <= 128) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if(size <= 256) { + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if(size <= 512) { + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheTile()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for(i = 0; i < max; i++, pCache++) { + if(pCache->serialNumber == pPix->drawable.serialNumber) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; pCache->orig_h = h; + (*infoRec->WritePixmapToCache)( + pScrn, pCache->x, pCache->y, w, h, pPix->devPrivate.ptr, + pPix->devKind, pPix->drawable.bitsPerPixel, pPix->drawable.depth); + if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + +XAACacheInfoPtr +XAACacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0, funcNo, pad, dwords, bpp = pScrn->bitsPerPixel; + int *current; + StippleScanlineProcPtr StippleFunc; + unsigned char *data, *srcPtr, *dstPtr; + + if((h <= 128) && (w <= 128 * bpp)) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if((h <= 256) && (w <= 256 * bpp)){ + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if((h <= 512) && (w <= 526 * bpp)){ + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheMonoStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (pCache->fg == -1) && (pCache->bg == -1)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; pCache->orig_h = h; + + if(w <= 32) { + if(w & (w - 1)) funcNo = 1; + else funcNo = 0; + } else funcNo = 2; + + pad = BitmapBytePad(pCache->w * bpp); + dwords = bytes_to_int32(pad); + dstPtr = data = (unsigned char*)malloc(pad * pCache->h); + srcPtr = (unsigned char*)pPix->devPrivate.ptr; + + if(infoRec->ScreenToScreenColorExpandFillFlags & BIT_ORDER_IN_BYTE_MSBFIRST) + StippleFunc = XAAStippleScanlineFuncMSBFirst[funcNo]; + else + StippleFunc = XAAStippleScanlineFuncLSBFirst[funcNo]; + + /* don't bother generating more than we'll ever use */ + max = ((pScrn->displayWidth + w - 1) + 31) >> 5; + if(dwords > max) + dwords = max; + + for(i = 0; i < h; i++) { + (*StippleFunc)((CARD32*)dstPtr, (CARD32*)srcPtr, 0, w, dwords); + srcPtr += pPix->devKind; + dstPtr += pad; + } + + while((h<<1) <= pCache->h) { + memcpy(data + (pad * h), data, pad * h); + h <<= 1; + } + + if(h < pCache->h) + memcpy(data + (pad * h), data, pad * (pCache->h - h)); + + (*infoRec->WritePixmapToCache)( + pScrn, pCache->x, pCache->y, pCache->w, pCache->h, data, + pad, bpp, pScrn->depth); + + free(data); + + return pCache; +} + +XAACacheInfoPtr +XAACachePlanarMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if((h <= 128) && (w <= 128)) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if((h <= 256) && (w <= 256)){ + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if((h <= 512) && (w <= 526)){ + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACachePlanarMonoStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (pCache->fg == -1) && (pCache->bg == -1)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; pCache->orig_h = h; + + /* Plane 0 holds the stipple. Plane 1 holds the inverted stipple */ + (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, + pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, + pPix->devKind, 1, 2); + if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_MONO_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + +XAACachePlanarMonoStippleProc +XAAGetCachePlanarMonoStipple(void) +{ + return XAACachePlanarMonoStipple; +} + +XAACacheInfoPtr +XAACacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + int size = max(w, h); + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + int i, max = 0; + int *current; + + if(size <= 128) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if(size <= 256) { + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if(size <= 512) { + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + /* lets look for it */ + if(bg == -1) + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (fg == pCache->fg) && (pCache->fg != pCache->bg)) { + pCache->trans_color = pCache->bg; + return pCache; + } + } + else + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (fg == pCache->fg) && (bg == pCache->bg)) { + pCache->trans_color = -1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->fg = fg; + if(bg == -1) + pCache->trans_color = bg = fg ^ 1; + else + pCache->trans_color = -1; + pCache->bg = bg; + + pCache->orig_w = w; pCache->orig_h = h; + (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, + pPix->drawable.width, pPix->drawable.height, pPix->devPrivate.ptr, + pPix->devKind, fg, bg); + if(!(infoRec->PixmapCacheFlags & DO_NOT_TILE_COLOR_DATA) && + ((w != pCache->w) || (h != pCache->h))) + XAATileCache(pScrn, pCache, w, h); + + return pCache; +} + + + +XAACacheInfoPtr +XAACacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, int pat1) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache = pCachePriv->InfoMono; + int i; + + for(i = 0; i < pCachePriv->NumMono; i++, pCache++) { + if(pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1)) + return pCache; + } + + /* OK, let's cache it */ + pCache = &pCachePriv->InfoMono[pCachePriv->CurrentMono++]; + if(pCachePriv->CurrentMono >= pCachePriv->NumMono) + pCachePriv->CurrentMono = 0; + + pCache->serialNumber = 1; /* we don't care since we do lookups by pattern */ + pCache->pat0 = pat0; + pCache->pat1 = pat1; + + (*infoRec->WriteMono8x8PatternToCache)(pScrn, pCache); + + return pCache; +} + + + +XAACacheInfoPtr +XAACacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, int bg) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache = pCachePriv->InfoColor; + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + int i; + + if(!(pixPriv->flags & REDUCIBLE_TO_2_COLOR)) { + for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if(pCache->serialNumber == pPix->drawable.serialNumber) { + pCache->trans_color = -1; + return pCache; + } + } + pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; + if(pCachePriv->CurrentColor >= pCachePriv->NumColor) + pCachePriv->CurrentColor = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->fg = pCache->bg = -1; + } else { + int pat0 = pixPriv->pattern0; + int pat1 = pixPriv->pattern1; + + if(fg == -1) { /* it's a tile */ + fg = pixPriv->fg; bg = pixPriv->bg; + } + + if(bg == -1) { /* stipple */ + for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if(pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && + (pCache->fg == fg) && (pCache->bg != fg)) { + pCache->trans_color = pCache->bg; + return pCache; + } + } + } else { /* opaque stipple */ + for(i = 0; i < pCachePriv->NumColor; i++, pCache++) { + if(pCache->serialNumber && + (pCache->pat0 == pat0) && (pCache->pat1 == pat1) && + (pCache->fg == fg) && (pCache->bg == bg)) { + pCache->trans_color = -1; + return pCache; + } + } + } + pCache = &pCachePriv->InfoColor[pCachePriv->CurrentColor++]; + if(pCachePriv->CurrentColor >= pCachePriv->NumColor) + pCachePriv->CurrentColor = 0; + + if(bg == -1) + pCache->trans_color = bg = fg ^ 1; + else + pCache->trans_color = -1; + + pCache->pat0 = pat0; pCache->pat1 = pat1; + pCache->fg = fg; pCache->bg = bg; + pCache->serialNumber = 1; + } + + (*infoRec->WriteColor8x8PatternToCache)(pScrn, pPix, pCache); + + return pCache; +} + + +void +XAAWriteBitmapToCache( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int fg, int bg +) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->WriteBitmap)(pScrn, x, y, w, h, src, srcwidth, + 0, fg, bg, GXcopy, ~0); +} + +void +XAAWriteBitmapToCacheLinear( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int fg, int bg +){ + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr pScreenPix, pDstPix; + ChangeGCVal gcvals[2]; + GCPtr pGC; + + pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); + + pDstPix = GetScratchPixmapHeader(pScreen, pScreenPix->drawable.width, + y + h, pScreenPix->drawable.depth, + pScreenPix->drawable.bitsPerPixel, + pScreenPix->devKind, + pScreenPix->devPrivate.ptr); + + pGC = GetScratchGC(pScreenPix->drawable.depth, pScreen); + gcvals[0].val = fg; + gcvals[1].val = bg; + ChangeGC(NullClient, pGC, GCForeground | GCBackground, gcvals); + ValidateGC((DrawablePtr)pDstPix, pGC); + + /* We've unwrapped already so these ops miss a sync */ + SYNC_CHECK(pScrn); + + (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, 1, x, y, w, h, 0, + XYBitmap, (pointer)src); + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(pDstPix); +} + + +void +XAAWritePixmapToCache( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int bpp, int depth +) { + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + + (*infoRec->WritePixmap)(pScrn, x, y, w, h, src, srcwidth, + GXcopy, ~0, -1, bpp, depth); +} + + + +void +XAAWritePixmapToCacheLinear( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int bpp, int depth +){ + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr pScreenPix, pDstPix; + GCPtr pGC; + + pScreenPix = (*pScreen->GetScreenPixmap)(pScreen); + + pDstPix = GetScratchPixmapHeader(pScreen, x + w, y + h, + depth, bpp, pScreenPix->devKind, + pScreenPix->devPrivate.ptr); + + pGC = GetScratchGC(depth, pScreen); + ValidateGC((DrawablePtr)pDstPix, pGC); + + /* We've unwrapped already so these ops miss a sync */ + SYNC_CHECK(pScrn); + + if(bpp == BitsPerPixel(depth)) + (*pGC->ops->PutImage)((DrawablePtr)pDstPix, pGC, depth, x, y, w, + h, 0, ZPixmap, (pointer)src); + else { + PixmapPtr pSrcPix; + + pSrcPix = GetScratchPixmapHeader(pScreen, w, h, depth, bpp, + srcwidth, (pointer)src); + + (*pGC->ops->CopyArea)((DrawablePtr)pSrcPix, (DrawablePtr)pDstPix, + pGC, 0, 0, w, h, x, y); + + FreeScratchPixmapHeader(pSrcPix); + } + + FreeScratchGC(pGC); + FreeScratchPixmapHeader(pDstPix); +} + + +void +XAAWriteMono8x8PatternToCache( + ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + unsigned char *data; + int pad, Bpp = (pScrn->bitsPerPixel >> 3); + + pCache->offsets = pCachePriv->MonoOffsets; + + pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); + + data = (unsigned char*)malloc(pad * pCache->h); + if(!data) return; + + if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + CARD32* ptr = (CARD32*)data; + ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; + } else { + CARD32 *ptr; + DDXPointPtr pPoint = pCache->offsets; + int patx, paty, i; + + for(i = 0; i < 64; i++, pPoint++) { + patx = pCache->pat0; paty = pCache->pat1; + XAARotateMonoPattern(&patx, &paty, i & 0x07, i >> 3, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + ptr = (CARD32*)(data + (pad * pPoint->y) + (Bpp * pPoint->x)); + ptr[0] = patx; ptr[1] = paty; + } + } + + (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); + + free(data); +} + +void +XAAWriteColor8x8PatternToCache( + ScrnInfoPtr pScrn, + PixmapPtr pPix, + XAACacheInfoPtr pCache +){ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + XAAPixmapPtr pixPriv = XAA_GET_PIXMAP_PRIVATE(pPix); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + int pad, i, w, h, nw, nh, Bpp; + unsigned char *data, *srcPtr, *dstPtr; + + pCache->offsets = pCachePriv->ColorOffsets; + + if(pixPriv->flags & REDUCIBLE_TO_2_COLOR) { + CARD32* ptr; + pad = BitmapBytePad(pCache->w); + data = (unsigned char*)malloc(pad * pCache->h); + if(!data) return; + + if(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN) { + ptr = (CARD32*)data; + ptr[0] = pCache->pat0; ptr[1] = pCache->pat1; + } else { + int patx, paty; + + ptr = (CARD32*)data; + ptr[0] = ptr[2] = pCache->pat0; ptr[1] = ptr[3] = pCache->pat1; + for(i = 1; i < 8; i++) { + patx = pCache->pat0; paty = pCache->pat1; + XAARotateMonoPattern(&patx, &paty, i, 0, + (infoRec->Mono8x8PatternFillFlags & + BIT_ORDER_IN_BYTE_MSBFIRST)); + ptr = (CARD32*)(data + (pad * i)); + ptr[0] = ptr[2] = patx; ptr[1] = ptr[3] = paty; + } + } + + (*infoRec->WriteBitmapToCache)(pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, pCache->fg, pCache->bg); + + free(data); + return; + } + + Bpp = pScrn->bitsPerPixel >> 3; + h = min(8,pPix->drawable.height); + w = min(8,pPix->drawable.width); + pad = BitmapBytePad(pCache->w * pScrn->bitsPerPixel); + + data = (unsigned char*)malloc(pad * pCache->h); + if(!data) return; + + /* Write and expand horizontally. */ + for (i = h, dstPtr = data, srcPtr = pPix->devPrivate.ptr; i--; + srcPtr += pPix->devKind, dstPtr += pScrn->bitsPerPixel) { + nw = w; + memcpy(dstPtr, srcPtr, w * Bpp); + while (nw != 8) { + memcpy(dstPtr + (nw * Bpp), dstPtr, nw * Bpp); + nw <<= 1; + } + } + nh = h; + /* Expand vertically. */ + while (nh != 8) { + memcpy(data + (nh*pScrn->bitsPerPixel), data, nh*pScrn->bitsPerPixel); + nh <<= 1; + } + + if(!(infoRec->Color8x8PatternFillFlags & + HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){ + int j; + unsigned char *ptr = data + (128 * Bpp); + + memcpy(data + (64 * Bpp), data, 64 * Bpp); + for(i = 1; i < 8; i++, ptr += (128 * Bpp)) { + for(j = 0; j < 8; j++) { + memcpy(ptr + (j * 8) * Bpp, data + (j * 8 + i) * Bpp, + (8 - i) * Bpp); + memcpy(ptr + (j * 8 + 8 - i) * Bpp, data + j * 8 * Bpp, i*Bpp); + } + memcpy(ptr + (64 * Bpp), ptr, 64 * Bpp); + } + } + + (*infoRec->WritePixmapToCache)(pScrn, pCache->x, pCache->y, + pCache->w, pCache->h, data, pad, pScrn->bitsPerPixel, pScrn->depth); + + free(data); +} + + + +int +XAAStippledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->stipple; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if(!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckStippleReducibility(pPixmap); + } + + + if(pPriv->flags & REDUCIBLE_TO_8x8) { + if(infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillMono8x8PatternSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_FG(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if(infoRec->CanDoColor8x8 && + !(infoRec->FillColor8x8PatternSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillColor8x8PatternSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / + infoRec->CacheColorExpandDensity) && + !(infoRec->FillCacheExpandSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillCacheExpandSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_FG(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { + + return DO_CACHE_EXPAND; + } + + + if(infoRec->UsingPixmapCache && + !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && + infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + !(infoRec->FillCacheBltSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillCacheBltSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if(infoRec->FillColorExpandSpans && + !(infoRec->FillColorExpandSpansFlags & NO_TRANSPARENCY) && + ((pGC->alu == GXcopy) || !(infoRec->FillColorExpandSpansFlags & + TRANSPARENCY_GXCOPY_ONLY)) && + CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_FG(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { + + return DO_COLOR_EXPAND; + } + + return 0; +} + + +int +XAAOpaqueStippledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->stipple; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if(XAA_DEPTH_BUG(pGC)) + return 0; + + if(!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckStippleReducibility(pPixmap); + } + + if(pPriv->flags & REDUCIBLE_TO_8x8) { + if(infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_COLORS(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if(infoRec->CanDoColor8x8 && + CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if(infoRec->UsingPixmapCache && infoRec->FillCacheExpandSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableStippleHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableStippleWidth / + infoRec->CacheColorExpandDensity) && + !(infoRec->FillCacheExpandSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_COLORS(pGC,infoRec->FillCacheExpandSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheExpandSpansFlags)) { + + return DO_CACHE_EXPAND; + } + + if(infoRec->UsingPixmapCache && + !(infoRec->PixmapCacheFlags & DO_NOT_BLIT_STIPPLES) && + infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if(infoRec->FillColorExpandSpans && + !(infoRec->FillColorExpandSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_COLORS(pGC,infoRec->FillColorExpandSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColorExpandSpansFlags)) { + + return DO_COLOR_EXPAND; + } + + return 0; +} + + + +int +XAATiledFillChooser(GCPtr pGC) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + PixmapPtr pPixmap = pGC->tile.pixmap; + XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pPixmap); + + if(IS_OFFSCREEN_PIXMAP(pPixmap) && infoRec->FillCacheBltSpans && + CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { + + return DO_PIXMAP_COPY; + } + + if(!(pPriv->flags & REDUCIBILITY_CHECKED) && + (infoRec->CanDoMono8x8 || infoRec->CanDoColor8x8)) { + XAACheckTileReducibility(pPixmap,infoRec->CanDoMono8x8); + } + + if(pPriv->flags & REDUCIBLE_TO_8x8) { + if((pPriv->flags & REDUCIBLE_TO_2_COLOR) && infoRec->CanDoMono8x8 && + !(infoRec->FillMono8x8PatternSpansFlags & TRANSPARENCY_ONLY) && + CHECK_ROP(pGC,infoRec->FillMono8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillMono8x8PatternSpansFlags) && + (!(infoRec->FillMono8x8PatternSpansFlags & RGB_EQUAL) || + (CHECK_RGB_EQUAL(pPriv->fg) && CHECK_RGB_EQUAL(pPriv->bg))) && + CHECK_PLANEMASK(pGC,infoRec->FillMono8x8PatternSpansFlags)) { + + return DO_MONO_8x8; + } + + if(infoRec->CanDoColor8x8 && + CHECK_ROP(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillColor8x8PatternSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillColor8x8PatternSpansFlags)) { + + return DO_COLOR_8x8; + } + } + + if(infoRec->UsingPixmapCache && infoRec->FillCacheBltSpans && + (pPixmap->drawable.height <= infoRec->MaxCacheableTileHeight) && + (pPixmap->drawable.width <= infoRec->MaxCacheableTileWidth) && + CHECK_ROP(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_ROPSRC(pGC,infoRec->FillCacheBltSpansFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillCacheBltSpansFlags)) { + + return DO_CACHE_BLT; + } + + if(infoRec->FillImageWriteRects && + CHECK_NO_GXCOPY(pGC,infoRec->FillImageWriteRectsFlags) && + CHECK_ROP(pGC,infoRec->FillImageWriteRectsFlags) && + CHECK_ROPSRC(pGC,infoRec->FillImageWriteRectsFlags) && + CHECK_PLANEMASK(pGC,infoRec->FillImageWriteRectsFlags)) { + + return DO_IMAGE_WRITE; + } + + return 0; +} + + +static int RotateMasksX[8] = { + 0xFFFFFFFF, 0x7F7F7F7F, 0x3F3F3F3F, 0x1F1F1F1F, + 0x0F0F0F0F, 0x07070707, 0x03030303, 0x01010101 +}; + +static int RotateMasksY[4] = { + 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF, 0x000000FF +}; + +void +XAARotateMonoPattern( + int *pat0, int *pat1, + int xorg, int yorg, + Bool msbfirst +){ + int tmp, mask; + + if(xorg) { + if(msbfirst) xorg = 8 - xorg; + mask = RotateMasksX[xorg]; + *pat0 = ((*pat0 >> xorg) & mask) | ((*pat0 << (8 - xorg)) & ~mask); + *pat1 = ((*pat1 >> xorg) & mask) | ((*pat1 << (8 - xorg)) & ~mask); + } + if(yorg >= 4) { + tmp = *pat0; *pat0 = *pat1; *pat1 = tmp; + yorg -= 4; + } + if(yorg) { + mask = RotateMasksY[yorg]; + yorg <<= 3; + tmp = *pat0; + *pat0 = ((*pat0 >> yorg) & mask) | ((*pat1 << (32 - yorg)) & ~mask); + *pat1 = ((*pat1 >> yorg) & mask) | ((tmp << (32 - yorg)) & ~mask); + } +} + + + +void +XAAInvalidatePixmapCache(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + int i; + + if(!pCachePriv) return; + + for(i = 0; i < pCachePriv->Num512x512; i++) + (pCachePriv->Info512)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->Num256x256; i++) + (pCachePriv->Info256)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->Num128x128; i++) + (pCachePriv->Info128)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->NumPartial; i++) + (pCachePriv->InfoPartial)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->NumMono; i++) + (pCachePriv->InfoMono)[i].serialNumber = 0; + for(i = 0; i < pCachePriv->NumColor; i++) + (pCachePriv->InfoColor)[i].serialNumber = 0; +} diff --git a/xorg-server/hw/xfree86/xaa/xaaPict.c b/xorg-server/hw/xfree86/xaa/xaaPict.c index e059d3d65..b66291458 100644 --- a/xorg-server/hw/xfree86/xaa/xaaPict.c +++ b/xorg-server/hw/xfree86/xaa/xaaPict.c @@ -1,655 +1,655 @@ -/* - * - * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. - * - * 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. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "xf86str.h" -#include "mi.h" -#include "picturestr.h" -#include "glyphstr.h" -#include "picture.h" -#include "mipict.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xaawrap.h" -#include "xaacexp.h" -#include "xf86fbman.h" -#include "servermd.h" - -Bool -XAAGetPixelFromRGBA ( - CARD32 *pixel, - CARD16 red, - CARD16 green, - CARD16 blue, - CARD16 alpha, - CARD32 format -){ - int rbits, bbits, gbits, abits; - int rshift, bshift, gshift, ashift; - - *pixel = 0; - - if(!PICT_FORMAT_COLOR(format)) - return FALSE; - - rbits = PICT_FORMAT_R(format); - gbits = PICT_FORMAT_G(format); - bbits = PICT_FORMAT_B(format); - abits = PICT_FORMAT_A(format); - - if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { - bshift = 0; - gshift = bbits; - rshift = gshift + gbits; - ashift = rshift + rbits; - } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { - rshift = 0; - gshift = rbits; - bshift = gshift + gbits; - ashift = bshift + bbits; - } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { - bshift = PICT_FORMAT_BPP(format) - bbits; - gshift = bshift - gbits; - rshift = gshift - rbits; - ashift = 0; - } else - return FALSE; - - *pixel |= ( blue >> (16 - bbits)) << bshift; - *pixel |= ( red >> (16 - rbits)) << rshift; - *pixel |= (green >> (16 - gbits)) << gshift; - *pixel |= (alpha >> (16 - abits)) << ashift; - - return TRUE; -} - - -Bool -XAAGetRGBAFromPixel( - CARD32 pixel, - CARD16 *red, - CARD16 *green, - CARD16 *blue, - CARD16 *alpha, - CARD32 format -){ - int rbits, bbits, gbits, abits; - int rshift, bshift, gshift, ashift; - - if(!PICT_FORMAT_COLOR(format)) - return FALSE; - - rbits = PICT_FORMAT_R(format); - gbits = PICT_FORMAT_G(format); - bbits = PICT_FORMAT_B(format); - abits = PICT_FORMAT_A(format); - - if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { - bshift = 0; - gshift = bbits; - rshift = gshift + gbits; - ashift = rshift + rbits; - } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { - rshift = 0; - gshift = rbits; - bshift = gshift + gbits; - ashift = bshift + bbits; - } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { - bshift = PICT_FORMAT_BPP(format) - bbits; - gshift = bshift - gbits; - rshift = gshift - rbits; - ashift = 0; - } else - return FALSE; - - *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits); - while(rbits < 16) { - *red |= *red >> rbits; - rbits <<= 1; - } - - *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits); - while(gbits < 16) { - *green |= *green >> gbits; - gbits <<= 1; - } - - *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits); - while(bbits < 16) { - *blue |= *blue >> bbits; - bbits <<= 1; - } - - if(abits) { - *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits); - while(abits < 16) { - *alpha |= *alpha >> abits; - abits <<= 1; - } - } else *alpha = 0xffff; - - return TRUE; -} - -/* 8:8:8 + PICT_a8 -> 8:8:8:8 texture */ - -void -XAA_888_plus_PICT_a8_to_8888 ( - CARD32 color, - CARD8 *alphaPtr, /* in bytes */ - int alphaPitch, - CARD32 *dstPtr, - int dstPitch, /* in dwords */ - int width, - int height -){ - int x; - - color &= 0x00ffffff; - - while(height--) { - for(x = 0; x < width; x++) - dstPtr[x] = color | (alphaPtr[x] << 24); - dstPtr += dstPitch; - alphaPtr += alphaPitch; - } -} - -#define DRAWABLE_IS_ON_CARD(pDraw) \ - (pDraw->type == DRAWABLE_WINDOW || \ - (pDraw->type == DRAWABLE_PIXMAP && IS_OFFSCREEN_PIXMAP(pDraw))) - -Bool -XAADoComposite ( - CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height -){ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - RegionRec region; - CARD32 *formats, *dstformats; - int flags = 0; - BoxPtr pbox; - int nbox, w, h; - - if(!REGION_NUM_RECTS(pDst->pCompositeClip)) - return TRUE; - - if(!infoRec->pScrn->vtSema || !DRAWABLE_IS_ON_CARD(pDst->pDrawable)) - return FALSE; - - if(DRAWABLE_IS_ON_CARD(pSrc->pDrawable)) - return FALSE; - - if (pSrc->transform || (pMask && pMask->transform)) - return FALSE; - - if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) - return FALSE; - - if ((pSrc->repeat && pSrc->repeatType != RepeatNormal) || - (pMask && pMask->repeat && pMask->repeatType != RepeatNormal)) - { - return FALSE; - } - - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; - - if(pMask) { - if(pMask->componentAlpha) - return FALSE; - - /* for now we only do it if there is a 1x1 (solid) source */ - - if((pSrc->pDrawable->width == 1) && (pSrc->pDrawable->height == 1)) { - CARD16 red, green, blue, alpha; - CARD32 pixel = - *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr)); - - if(!XAAGetRGBAFromPixel(pixel,&red,&green,&blue,&alpha,pSrc->format)) - return FALSE; - - xMask += pMask->pDrawable->x; - yMask += pMask->pDrawable->y; - - /* pull out color expandable operations here */ - if((pMask->format == PICT_a1) && (alpha == 0xffff) && - (op == PictOpOver) && infoRec->WriteBitmap && !pMask->repeat && - !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY) && - (!(infoRec->WriteBitmapFlags & RGB_EQUAL) || - ((red == green) && (green == blue)))) - { - PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable); - int skipleft; - - if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, - width, height)) - return TRUE; - - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - - if(!nbox) - return TRUE; - - XAAGetPixelFromRGBA(&pixel, red, green, blue, 0, pDst->format); - - xMask -= xDst; - yMask -= yDst; - - while(nbox--) { - skipleft = pbox->x1 + xMask; - - (*infoRec->WriteBitmap)(infoRec->pScrn, - pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, - (unsigned char*)(pPix->devPrivate.ptr) + - (pPix->devKind * (pbox->y1 + yMask)) + - ((skipleft >> 3) & ~3), pPix->devKind, - skipleft & 31, pixel, -1, GXcopy, ~0); - pbox++; - } - - /* WriteBitmap sets the Sync flag */ - REGION_UNINIT(pScreen, ®ion); - return TRUE; - } - - formats = infoRec->CPUToScreenAlphaTextureFormats; - dstformats = infoRec->CPUToScreenAlphaTextureDstFormats; - if(!formats || !dstformats) - return FALSE; - - w = pMask->pDrawable->width; - h = pMask->pDrawable->height; - - if(pMask->repeat) { - if((infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_TILE) || - ((infoRec->CPUToScreenAlphaTextureFlags & - XAA_RENDER_POWER_OF_2_TILE_ONLY) && - ((h & (h - 1)) || (w & (w - 1))))) - { - return FALSE; - } - flags |= XAA_RENDER_REPEAT; - } - - if((alpha != 0xffff) && - (infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_SRC_ALPHA)) - return FALSE; - - while(*formats != pMask->format) { - if(!(*formats)) return FALSE; - formats++; - } - while(*dstformats != pDst->format) { - if(!(*dstformats)) - return FALSE; - dstformats++; - } - - if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, - width, height)) - return TRUE; - - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - - if(!nbox) { - REGION_UNINIT(pScreen, ®ion); - return TRUE; - } - - if(!(infoRec->SetupForCPUToScreenAlphaTexture2)(infoRec->pScrn, - op, red, green, blue, alpha, pMask->format, - pDst->format, - ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr, - ((PixmapPtr)(pMask->pDrawable))->devKind, - w, h, flags)) - { - REGION_UNINIT(pScreen, ®ion); - return FALSE; - } - - xMask -= xDst; - yMask -= yDst; - - while(nbox--) { - (*infoRec->SubsequentCPUToScreenAlphaTexture)(infoRec->pScrn, - pbox->x1, pbox->y1, - pbox->x1 + xMask, pbox->y1 + yMask, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - pbox++; - } - - SET_SYNC_FLAG(infoRec); - REGION_UNINIT(pScreen, ®ion); - return TRUE; - } - } else { - formats = infoRec->CPUToScreenTextureFormats; - dstformats = infoRec->CPUToScreenTextureDstFormats; - if(!formats || !dstformats) - return FALSE; - - w = pSrc->pDrawable->width; - h = pSrc->pDrawable->height; - - if(pSrc->repeat) { - if((infoRec->CPUToScreenTextureFlags & XAA_RENDER_NO_TILE) || - ((infoRec->CPUToScreenTextureFlags & - XAA_RENDER_POWER_OF_2_TILE_ONLY) && - ((h & (h - 1)) || (w & (w - 1))))) - { - return FALSE; - } - flags |= XAA_RENDER_REPEAT; - } - - while(*formats != pSrc->format) { - if(!(*formats)) return FALSE; - formats++; - } - while(*dstformats != pDst->format) { - if(!(*dstformats)) - return FALSE; - dstformats++; - } - - if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, - width, height)) - return TRUE; - - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - - if(!nbox) { - REGION_UNINIT(pScreen, ®ion); - return TRUE; - } - - if(!(infoRec->SetupForCPUToScreenTexture2)(infoRec->pScrn, - op, pSrc->format, pDst->format, - ((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr, - ((PixmapPtr)(pSrc->pDrawable))->devKind, - w, h, flags)) - { - REGION_UNINIT(pScreen, ®ion); - return FALSE; - } - - - xSrc -= xDst; - ySrc -= yDst; - - while(nbox--) { - (*infoRec->SubsequentCPUToScreenTexture)(infoRec->pScrn, - pbox->x1, pbox->y1, - pbox->x1 + xSrc, pbox->y1 + ySrc, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - pbox++; - } - - SET_SYNC_FLAG(infoRec); - REGION_UNINIT(pScreen, ®ion); - return TRUE; - } - - - return FALSE; -} - -static void -XAACompositeSrcCopy (PicturePtr pSrc, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - int i, nbox; - int xoff, yoff; - BoxPtr pbox; - DDXPointPtr pptSrc; - RegionRec region; - - xDst += pDst->pDrawable->x; - yDst += pDst->pDrawable->y; - xSrc += pSrc->pDrawable->x; - ySrc += pSrc->pDrawable->y; - - if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, - xSrc, ySrc, 0, 0, xDst, yDst, - width, height)) - return; - - nbox = REGION_NUM_RECTS(®ion); - pbox = REGION_RECTS(®ion); - - if(!nbox) { - REGION_UNINIT(pScreen, ®ion); - return; - } - pptSrc = xalloc(sizeof(DDXPointRec) * nbox); - if (!pptSrc) { - REGION_UNINIT(pScreen, ®ion); - return; - } - xoff = xSrc - xDst; - yoff = ySrc - yDst; - for (i = 0; i < nbox; i++) { - pptSrc[i].x = pbox[i].x1 + xoff; - pptSrc[i].y = pbox[i].y1 + yoff; - } - - infoRec->ScratchGC.planemask = ~0L; - infoRec->ScratchGC.alu = GXcopy; - - XAADoBitBlt(pSrc->pDrawable, pDst->pDrawable, &infoRec->ScratchGC, ®ion, - pptSrc); - - xfree(pptSrc); - REGION_UNINIT(pScreen, ®ion); - return; -} - -void -XAAComposite (CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAA_RENDER_PROLOGUE(pScreen, Composite); - - if(!pMask && infoRec->pScrn->vtSema && - infoRec->ScreenToScreenBitBlt && - pSrc->pDrawable && - DRAWABLE_IS_ON_CARD(pSrc->pDrawable) && - DRAWABLE_IS_ON_CARD(pDst->pDrawable) && - !pSrc->transform && - (!pSrc->repeat || (xSrc >= 0 && ySrc >= 0 && - xSrc+width<=pSrc->pDrawable->width && - ySrc+height<=pSrc->pDrawable->height)) && - ((op == PictOpSrc && - ((pSrc->format==pDst->format) || - (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) || - (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) || - (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap && - pSrc->format==pDst->format && - (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))) - { - XAACompositeSrcCopy(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height); - } else if(!pSrc->pDrawable || (pMask && !pMask->pDrawable) || - !infoRec->Composite || - !(*infoRec->Composite)(op, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, - width, height)) - { - if(infoRec->pScrn->vtSema && - ((pSrc->pDrawable && - (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) || - pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) { - SYNC_CHECK(pDst->pDrawable); - } - (*GetPictureScreen(pScreen)->Composite) (op, - pSrc, - pMask, - pDst, - xSrc, - ySrc, - xMask, - yMask, - xDst, - yDst, - width, - height); - } - - if(pDst->pDrawable->type == DRAWABLE_PIXMAP) - (XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY; - - XAA_RENDER_EPILOGUE(pScreen, Composite, XAAComposite); -} - -Bool -XAADoGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - - if(!REGION_NUM_RECTS(pDst->pCompositeClip)) - return TRUE; - - if(!infoRec->pScrn->vtSema || - ((pDst->pDrawable->type != DRAWABLE_WINDOW) && - !IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) - return FALSE; - - if((pSrc->pDrawable->type != DRAWABLE_PIXMAP) || - IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) - return FALSE; - - /* - * If it looks like we have a chance of being able to draw these - * glyphs with an accelerated Composite, do that now to avoid - * unneeded and costly syncs. - */ - if(maskFormat) { - if(!infoRec->CPUToScreenAlphaTextureFormats) - return FALSE; - } else { - if(!infoRec->CPUToScreenTextureFormats) - return FALSE; - } - - miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); - - return TRUE; -} - - -void -XAAGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); - XAA_RENDER_PROLOGUE(pScreen, Glyphs); - - if(!pSrc->pDrawable || !infoRec->Glyphs || - !(*infoRec->Glyphs)(op, pSrc, pDst, maskFormat, - xSrc, ySrc, nlist, list, glyphs)) - { - if(infoRec->pScrn->vtSema && - ((pSrc->pDrawable && - (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) || - pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) { - SYNC_CHECK(pDst->pDrawable); - } - (*GetPictureScreen(pScreen)->Glyphs) (op, pSrc, pDst, maskFormat, - xSrc, ySrc, nlist, list, glyphs); - } - - if(pDst->pDrawable->type == DRAWABLE_PIXMAP) - (XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY; - - XAA_RENDER_EPILOGUE(pScreen, Glyphs, XAAGlyphs); -} +/* + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * + * 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. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "picturestr.h" +#include "glyphstr.h" +#include "picture.h" +#include "mipict.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "xaacexp.h" +#include "xf86fbman.h" +#include "servermd.h" + +Bool +XAAGetPixelFromRGBA ( + CARD32 *pixel, + CARD16 red, + CARD16 green, + CARD16 blue, + CARD16 alpha, + CARD32 format +){ + int rbits, bbits, gbits, abits; + int rshift, bshift, gshift, ashift; + + *pixel = 0; + + if(!PICT_FORMAT_COLOR(format)) + return FALSE; + + rbits = PICT_FORMAT_R(format); + gbits = PICT_FORMAT_G(format); + bbits = PICT_FORMAT_B(format); + abits = PICT_FORMAT_A(format); + + if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { + bshift = 0; + gshift = bbits; + rshift = gshift + gbits; + ashift = rshift + rbits; + } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { + rshift = 0; + gshift = rbits; + bshift = gshift + gbits; + ashift = bshift + bbits; + } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { + bshift = PICT_FORMAT_BPP(format) - bbits; + gshift = bshift - gbits; + rshift = gshift - rbits; + ashift = 0; + } else + return FALSE; + + *pixel |= ( blue >> (16 - bbits)) << bshift; + *pixel |= ( red >> (16 - rbits)) << rshift; + *pixel |= (green >> (16 - gbits)) << gshift; + *pixel |= (alpha >> (16 - abits)) << ashift; + + return TRUE; +} + + +Bool +XAAGetRGBAFromPixel( + CARD32 pixel, + CARD16 *red, + CARD16 *green, + CARD16 *blue, + CARD16 *alpha, + CARD32 format +){ + int rbits, bbits, gbits, abits; + int rshift, bshift, gshift, ashift; + + if(!PICT_FORMAT_COLOR(format)) + return FALSE; + + rbits = PICT_FORMAT_R(format); + gbits = PICT_FORMAT_G(format); + bbits = PICT_FORMAT_B(format); + abits = PICT_FORMAT_A(format); + + if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) { + bshift = 0; + gshift = bbits; + rshift = gshift + gbits; + ashift = rshift + rbits; + } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) { + rshift = 0; + gshift = rbits; + bshift = gshift + gbits; + ashift = bshift + bbits; + } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) { + bshift = PICT_FORMAT_BPP(format) - bbits; + gshift = bshift - gbits; + rshift = gshift - rbits; + ashift = 0; + } else + return FALSE; + + *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits); + while(rbits < 16) { + *red |= *red >> rbits; + rbits <<= 1; + } + + *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits); + while(gbits < 16) { + *green |= *green >> gbits; + gbits <<= 1; + } + + *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits); + while(bbits < 16) { + *blue |= *blue >> bbits; + bbits <<= 1; + } + + if(abits) { + *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits); + while(abits < 16) { + *alpha |= *alpha >> abits; + abits <<= 1; + } + } else *alpha = 0xffff; + + return TRUE; +} + +/* 8:8:8 + PICT_a8 -> 8:8:8:8 texture */ + +void +XAA_888_plus_PICT_a8_to_8888 ( + CARD32 color, + CARD8 *alphaPtr, /* in bytes */ + int alphaPitch, + CARD32 *dstPtr, + int dstPitch, /* in dwords */ + int width, + int height +){ + int x; + + color &= 0x00ffffff; + + while(height--) { + for(x = 0; x < width; x++) + dstPtr[x] = color | (alphaPtr[x] << 24); + dstPtr += dstPitch; + alphaPtr += alphaPitch; + } +} + +#define DRAWABLE_IS_ON_CARD(pDraw) \ + (pDraw->type == DRAWABLE_WINDOW || \ + (pDraw->type == DRAWABLE_PIXMAP && IS_OFFSCREEN_PIXMAP(pDraw))) + +Bool +XAADoComposite ( + CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height +){ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + RegionRec region; + CARD32 *formats, *dstformats; + int flags = 0; + BoxPtr pbox; + int nbox, w, h; + + if(!REGION_NUM_RECTS(pDst->pCompositeClip)) + return TRUE; + + if(!infoRec->pScrn->vtSema || !DRAWABLE_IS_ON_CARD(pDst->pDrawable)) + return FALSE; + + if(DRAWABLE_IS_ON_CARD(pSrc->pDrawable)) + return FALSE; + + if (pSrc->transform || (pMask && pMask->transform)) + return FALSE; + + if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap)) + return FALSE; + + if ((pSrc->repeat && pSrc->repeatType != RepeatNormal) || + (pMask && pMask->repeat && pMask->repeatType != RepeatNormal)) + { + return FALSE; + } + + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + + if(pMask) { + if(pMask->componentAlpha) + return FALSE; + + /* for now we only do it if there is a 1x1 (solid) source */ + + if((pSrc->pDrawable->width == 1) && (pSrc->pDrawable->height == 1)) { + CARD16 red, green, blue, alpha; + CARD32 pixel = + *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr)); + + if(!XAAGetRGBAFromPixel(pixel,&red,&green,&blue,&alpha,pSrc->format)) + return FALSE; + + xMask += pMask->pDrawable->x; + yMask += pMask->pDrawable->y; + + /* pull out color expandable operations here */ + if((pMask->format == PICT_a1) && (alpha == 0xffff) && + (op == PictOpOver) && infoRec->WriteBitmap && !pMask->repeat && + !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY) && + (!(infoRec->WriteBitmapFlags & RGB_EQUAL) || + ((red == green) && (green == blue)))) + { + PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable); + int skipleft; + + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) + return TRUE; + + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + + if(!nbox) + return TRUE; + + XAAGetPixelFromRGBA(&pixel, red, green, blue, 0, pDst->format); + + xMask -= xDst; + yMask -= yDst; + + while(nbox--) { + skipleft = pbox->x1 + xMask; + + (*infoRec->WriteBitmap)(infoRec->pScrn, + pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, + (unsigned char*)(pPix->devPrivate.ptr) + + (pPix->devKind * (pbox->y1 + yMask)) + + ((skipleft >> 3) & ~3), pPix->devKind, + skipleft & 31, pixel, -1, GXcopy, ~0); + pbox++; + } + + /* WriteBitmap sets the Sync flag */ + REGION_UNINIT(pScreen, ®ion); + return TRUE; + } + + formats = infoRec->CPUToScreenAlphaTextureFormats; + dstformats = infoRec->CPUToScreenAlphaTextureDstFormats; + if(!formats || !dstformats) + return FALSE; + + w = pMask->pDrawable->width; + h = pMask->pDrawable->height; + + if(pMask->repeat) { + if((infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_TILE) || + ((infoRec->CPUToScreenAlphaTextureFlags & + XAA_RENDER_POWER_OF_2_TILE_ONLY) && + ((h & (h - 1)) || (w & (w - 1))))) + { + return FALSE; + } + flags |= XAA_RENDER_REPEAT; + } + + if((alpha != 0xffff) && + (infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_SRC_ALPHA)) + return FALSE; + + while(*formats != pMask->format) { + if(!(*formats)) return FALSE; + formats++; + } + while(*dstformats != pDst->format) { + if(!(*dstformats)) + return FALSE; + dstformats++; + } + + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) + return TRUE; + + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + + if(!nbox) { + REGION_UNINIT(pScreen, ®ion); + return TRUE; + } + + if(!(infoRec->SetupForCPUToScreenAlphaTexture2)(infoRec->pScrn, + op, red, green, blue, alpha, pMask->format, + pDst->format, + ((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr, + ((PixmapPtr)(pMask->pDrawable))->devKind, + w, h, flags)) + { + REGION_UNINIT(pScreen, ®ion); + return FALSE; + } + + xMask -= xDst; + yMask -= yDst; + + while(nbox--) { + (*infoRec->SubsequentCPUToScreenAlphaTexture)(infoRec->pScrn, + pbox->x1, pbox->y1, + pbox->x1 + xMask, pbox->y1 + yMask, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + pbox++; + } + + SET_SYNC_FLAG(infoRec); + REGION_UNINIT(pScreen, ®ion); + return TRUE; + } + } else { + formats = infoRec->CPUToScreenTextureFormats; + dstformats = infoRec->CPUToScreenTextureDstFormats; + if(!formats || !dstformats) + return FALSE; + + w = pSrc->pDrawable->width; + h = pSrc->pDrawable->height; + + if(pSrc->repeat) { + if((infoRec->CPUToScreenTextureFlags & XAA_RENDER_NO_TILE) || + ((infoRec->CPUToScreenTextureFlags & + XAA_RENDER_POWER_OF_2_TILE_ONLY) && + ((h & (h - 1)) || (w & (w - 1))))) + { + return FALSE; + } + flags |= XAA_RENDER_REPEAT; + } + + while(*formats != pSrc->format) { + if(!(*formats)) return FALSE; + formats++; + } + while(*dstformats != pDst->format) { + if(!(*dstformats)) + return FALSE; + dstformats++; + } + + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) + return TRUE; + + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + + if(!nbox) { + REGION_UNINIT(pScreen, ®ion); + return TRUE; + } + + if(!(infoRec->SetupForCPUToScreenTexture2)(infoRec->pScrn, + op, pSrc->format, pDst->format, + ((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr, + ((PixmapPtr)(pSrc->pDrawable))->devKind, + w, h, flags)) + { + REGION_UNINIT(pScreen, ®ion); + return FALSE; + } + + + xSrc -= xDst; + ySrc -= yDst; + + while(nbox--) { + (*infoRec->SubsequentCPUToScreenTexture)(infoRec->pScrn, + pbox->x1, pbox->y1, + pbox->x1 + xSrc, pbox->y1 + ySrc, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + pbox++; + } + + SET_SYNC_FLAG(infoRec); + REGION_UNINIT(pScreen, ®ion); + return TRUE; + } + + + return FALSE; +} + +static void +XAACompositeSrcCopy (PicturePtr pSrc, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + int i, nbox; + int xoff, yoff; + BoxPtr pbox; + DDXPointPtr pptSrc; + RegionRec region; + + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + + if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst, + xSrc, ySrc, 0, 0, xDst, yDst, + width, height)) + return; + + nbox = REGION_NUM_RECTS(®ion); + pbox = REGION_RECTS(®ion); + + if(!nbox) { + REGION_UNINIT(pScreen, ®ion); + return; + } + pptSrc = malloc(sizeof(DDXPointRec) * nbox); + if (!pptSrc) { + REGION_UNINIT(pScreen, ®ion); + return; + } + xoff = xSrc - xDst; + yoff = ySrc - yDst; + for (i = 0; i < nbox; i++) { + pptSrc[i].x = pbox[i].x1 + xoff; + pptSrc[i].y = pbox[i].y1 + yoff; + } + + infoRec->ScratchGC.planemask = ~0L; + infoRec->ScratchGC.alu = GXcopy; + + XAADoBitBlt(pSrc->pDrawable, pDst->pDrawable, &infoRec->ScratchGC, ®ion, + pptSrc); + + free(pptSrc); + REGION_UNINIT(pScreen, ®ion); + return; +} + +void +XAAComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAA_RENDER_PROLOGUE(pScreen, Composite); + + if(!pMask && infoRec->pScrn->vtSema && + infoRec->ScreenToScreenBitBlt && + pSrc->pDrawable && + DRAWABLE_IS_ON_CARD(pSrc->pDrawable) && + DRAWABLE_IS_ON_CARD(pDst->pDrawable) && + !pSrc->transform && + (!pSrc->repeat || (xSrc >= 0 && ySrc >= 0 && + xSrc+width<=pSrc->pDrawable->width && + ySrc+height<=pSrc->pDrawable->height)) && + ((op == PictOpSrc && + ((pSrc->format==pDst->format) || + (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) || + (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) || + (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap && + pSrc->format==pDst->format && + (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8)))) + { + XAACompositeSrcCopy(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height); + } else if(!pSrc->pDrawable || (pMask && !pMask->pDrawable) || + !infoRec->Composite || + !(*infoRec->Composite)(op, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, + width, height)) + { + if(infoRec->pScrn->vtSema && + ((pSrc->pDrawable && + (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) || + pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) { + SYNC_CHECK(pDst->pDrawable); + } + (*GetPictureScreen(pScreen)->Composite) (op, + pSrc, + pMask, + pDst, + xSrc, + ySrc, + xMask, + yMask, + xDst, + yDst, + width, + height); + } + + if(pDst->pDrawable->type == DRAWABLE_PIXMAP) + (XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY; + + XAA_RENDER_EPILOGUE(pScreen, Composite, XAAComposite); +} + +Bool +XAADoGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + + if(!REGION_NUM_RECTS(pDst->pCompositeClip)) + return TRUE; + + if(!infoRec->pScrn->vtSema || + ((pDst->pDrawable->type != DRAWABLE_WINDOW) && + !IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) + return FALSE; + + if((pSrc->pDrawable->type != DRAWABLE_PIXMAP) || + IS_OFFSCREEN_PIXMAP(pSrc->pDrawable)) + return FALSE; + + /* + * If it looks like we have a chance of being able to draw these + * glyphs with an accelerated Composite, do that now to avoid + * unneeded and costly syncs. + */ + if(maskFormat) { + if(!infoRec->CPUToScreenAlphaTextureFormats) + return FALSE; + } else { + if(!infoRec->CPUToScreenTextureFormats) + return FALSE; + } + + miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + + return TRUE; +} + + +void +XAAGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen); + XAA_RENDER_PROLOGUE(pScreen, Glyphs); + + if(!pSrc->pDrawable || !infoRec->Glyphs || + !(*infoRec->Glyphs)(op, pSrc, pDst, maskFormat, + xSrc, ySrc, nlist, list, glyphs)) + { + if(infoRec->pScrn->vtSema && + ((pSrc->pDrawable && + (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) || + pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) { + SYNC_CHECK(pDst->pDrawable); + } + (*GetPictureScreen(pScreen)->Glyphs) (op, pSrc, pDst, maskFormat, + xSrc, ySrc, nlist, list, glyphs); + } + + if(pDst->pDrawable->type == DRAWABLE_PIXMAP) + (XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY; + + XAA_RENDER_EPILOGUE(pScreen, Glyphs, XAAGlyphs); +} diff --git a/xorg-server/hw/xfree86/xaa/xaaStateChange.c b/xorg-server/hw/xfree86/xaa/xaaStateChange.c index f33261453..9c98a32f2 100644 --- a/xorg-server/hw/xfree86/xaa/xaaStateChange.c +++ b/xorg-server/hw/xfree86/xaa/xaaStateChange.c @@ -1,1626 +1,1626 @@ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "xf86str.h" -#include "mi.h" -#include "miline.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xaawrap.h" -#include "servermd.h" - -#define XAA_STATE_WRAP(func) do {\ -if(infoRec->func) { \ - pStatePriv->func = infoRec->func;\ - infoRec->func = XAAStateWrap##func;\ -}} while(0) - -/* Wrap all XAA functions and allocate our private structure. - */ - -typedef struct _XAAStateWrapRec { - ScrnInfoPtr pScrn; - void (*RestoreAccelState)(ScrnInfoPtr pScrn); - void (*Sync)(ScrnInfoPtr pScrn); - void (*SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir, - int rop, unsigned int planemask, - int trans_color); - void (*SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop, - unsigned int planemask); - void (*SetupForSolidLine)(ScrnInfoPtr pScrn,int color,int rop, - unsigned int planemask); - void (*SetupForDashedLine)(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int length, - unsigned char *pattern); - void (*SetClippingRectangle) (ScrnInfoPtr pScrn, int left, int top, - int right, int bottom); - void (*DisableClipping)(ScrnInfoPtr pScrn); - void (*SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, - int fg, int bg, int rop, - unsigned int planemask); - void (*SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, - int rop, unsigned int planemask, - int transparency_color); - void (*SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, - int bg, int rop, - unsigned int planemask); - void (*SetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask); - void (*SetupForScreenToScreenColorExpandFill) (ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask); - void (*SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int transparency_color, - int bpp, int depth); - void (*SetupForScanlineImageWrite)(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, - int transparency_color, - int bpp, int depth); - void (*SetupForImageRead) (ScrnInfoPtr pScrn, int bpp, int depth); - void (*ScreenToScreenBitBlt)(ScrnInfoPtr pScrn, int nbox, - DDXPointPtr pptSrc, BoxPtr pbox, int xdir, - int ydir, int alu, unsigned int planmask); - void (*WriteBitmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *src, int srcwidth, int skipleft, - int fg, int bg, int rop, unsigned int planemask); - void (*FillSolidRects)(ScrnInfoPtr pScrn, int fg, int rop, - unsigned int planemask, int nBox, BoxPtr pBox); - void (*FillMono8x8PatternRects)(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int nBox, - BoxPtr pBox, int pat0, int pat1, - int xorg, int yorg); - void (*FillColor8x8PatternRects)(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int nBox, - BoxPtr pBox, int xorg, int yorg, - XAACacheInfoPtr pCache); - void (*FillCacheBltRects)(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int nBox, BoxPtr pBox, - int xorg, int yorg, XAACacheInfoPtr pCache); - void (*FillColorExpandRects)(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int nBox, - BoxPtr pBox, int xorg, int yorg, - PixmapPtr pPix); - void (*FillCacheExpandRects)(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int nBox, BoxPtr pBox, - int xorg, int yorg, PixmapPtr pPix); - void (*FillImageWriteRects)(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int nBox, BoxPtr pBox, - int xorg, int yorg, PixmapPtr pPix); - void (*FillSolidSpans)(ScrnInfoPtr pScrn, int fg, int rop, - unsigned int planemask, int n, DDXPointPtr points, - int *widths, int fSorted); - void (*FillMono8x8PatternSpans)(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int n, - DDXPointPtr points, int *widths, - int fSorted, int pat0, int pat1, - int xorg, int yorg); - void (*FillColor8x8PatternSpans)(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int n, - DDXPointPtr points, int *widths, - int fSorted, XAACacheInfoPtr pCache, - int xorg, int yorg); - void (*FillCacheBltSpans)(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int n, DDXPointPtr points, - int *widths, int fSorted, XAACacheInfoPtr pCache, - int xorg, int yorg); - void (*FillColorExpandSpans)(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int n, - DDXPointPtr points, int *widths, int fSorted, - int xorg, int yorg, PixmapPtr pPix); - void (*FillCacheExpandSpans)(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int n, DDXPointPtr ppt, - int *pwidth, int fSorted, int xorg, int yorg, - PixmapPtr pPix); - void (*TEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int w, int h, - int skipleft, int startline, unsigned int **glyphs, - int glyphWidth, int fg, int bg, int rop, - unsigned planemask); - void (*NonTEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int n, - NonTEGlyphPtr glyphs, BoxPtr pbox, - int fg, int rop, unsigned int planemask); - void (*WritePixmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *src, int srcwidth, int rop, - unsigned int planemask, int transparency_color, - int bpp, int depth); - void (*ReadPixmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *dst, int dstwidth, int bpp, int depth); - RegionPtr (*CopyArea)(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, - GC *pGC, int srcx, int srcy, int width, int height, - int dstx, int dsty); - RegionPtr (*CopyPlane)(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int width, int height, int dstx, - int dsty, unsigned long bitPlane); - void (*PushPixelsSolid) (GCPtr pGC, PixmapPtr pBitMap, - DrawablePtr pDrawable, int dx, int dy, int xOrg, - int yOrg); - void (*PolyFillRectSolid)(DrawablePtr pDraw, GCPtr pGC, int nrectFill, - xRectangle *prectInit); - void (*PolyFillRectStippled)(DrawablePtr pDraw, GCPtr pGC, int nrectFill, - xRectangle *prectInit); - void (*PolyFillRectOpaqueStippled)(DrawablePtr pDraw, GCPtr pGC, - int nrectFill, xRectangle *prectInit); - void (*PolyFillRectTiled)(DrawablePtr pDraw, GCPtr pGC, int nrectFill, - xRectangle *prectInit); - void (*FillSpansSolid)(DrawablePtr pDraw, GCPtr pGC, int nInit, - DDXPointPtr ppt, int *pwidth, int fSorted); - void (*FillSpansStippled)(DrawablePtr pDraw, GCPtr pGC, int nInit, - DDXPointPtr ppt, int *pwidth, int fSorted); - void (*FillSpansOpaqueStippled)(DrawablePtr pDraw, GCPtr pGC, int nInit, - DDXPointPtr ppt, int *pwidth, int fSorted); - void (*FillSpansTiled)(DrawablePtr pDraw, GCPtr pGC, int nInit, - DDXPointPtr ppt, int *pwidth, int fSorted); - int (*PolyText8TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, - char *chars); - int (*PolyText16TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, - unsigned short *chars); - void (*ImageText8TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, - char *chars); - void (*ImageText16TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, unsigned short *chars); - void (*ImageGlyphBltTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, - int yInit, unsigned int nglyph, CharInfoPtr *ppci, - pointer pglyphBase); - void (*PolyGlyphBltTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, - int yInit, unsigned int nglyph, CharInfoPtr *ppci, - pointer pglyphBase); - int (*PolyText8NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, char *chars); - int (*PolyText16NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, unsigned short *chars); - void (*ImageText8NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, char *chars); - void (*ImageText16NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, unsigned short *chars); - void (*ImageGlyphBltNonTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, - int yInit, unsigned int nglyph, - CharInfoPtr *ppci, pointer pglyphBase); - void (*PolyGlyphBltNonTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, - int yInit, unsigned int nglyph, - CharInfoPtr *ppci, pointer pglyphBase); - void (*PolyRectangleThinSolid)(DrawablePtr pDrawable,GCPtr pGC, - int nRectsInit, xRectangle *pRectsInit); - void (*PolylinesWideSolid)(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pPts); - void (*PolylinesThinSolid)(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pPts); - void (*PolySegmentThinSolid)(DrawablePtr pDrawable, GCPtr pGC, int nseg, - xSegment *pSeg); - void (*PolylinesThinDashed)(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pPts); - void (*PolySegmentThinDashed)(DrawablePtr pDrawable, GCPtr pGC, int nseg, - xSegment *pSeg); - void (*FillPolygonSolid)(DrawablePtr pDrawable, GCPtr pGC, int shape, - int mode, int count, DDXPointPtr ptsIn); - void (*FillPolygonStippled)(DrawablePtr pDrawable, GCPtr pGC, int shape, - int mode, int count, DDXPointPtr ptsIn); - void (*FillPolygonOpaqueStippled)(DrawablePtr pDrawable, GCPtr pGC, - int shape, int mode, int count, - DDXPointPtr ptsIn); - void (*FillPolygonTiled)(DrawablePtr pDrawable, GCPtr pGC, int shape, - int mode, int count, DDXPointPtr ptsIn); - void (*PolyFillArcSolid)(DrawablePtr pDraw, GCPtr pGC, int narcs, - xArc *parcs); - void (*PutImage)(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y, - int w, int h, int leftPad, int format, char *pImage); - ValidateGCProcPtr ValidateFillSpans; - ValidateGCProcPtr ValidateSetSpans; - ValidateGCProcPtr ValidatePutImage; - ValidateGCProcPtr ValidateCopyArea; - ValidateGCProcPtr ValidateCopyPlane; - ValidateGCProcPtr ValidatePolyPoint; - ValidateGCProcPtr ValidatePolylines; - ValidateGCProcPtr ValidatePolySegment; - ValidateGCProcPtr ValidatePolyRectangle; - ValidateGCProcPtr ValidatePolyArc; - ValidateGCProcPtr ValidateFillPolygon; - ValidateGCProcPtr ValidatePolyFillRect; - ValidateGCProcPtr ValidatePolyFillArc; - ValidateGCProcPtr ValidatePolyText8; - ValidateGCProcPtr ValidatePolyText16; - ValidateGCProcPtr ValidateImageText8; - ValidateGCProcPtr ValidateImageText16; - ValidateGCProcPtr ValidatePolyGlyphBlt; - ValidateGCProcPtr ValidateImageGlyphBlt; - ValidateGCProcPtr ValidatePushPixels; - void (*ComputeDash)(GCPtr pGC); - void (*InitPixmapCache)(ScreenPtr pScreen, RegionPtr areas, pointer data); - void (*ClosePixmapCache)(ScreenPtr pScreen); - int (*StippledFillChooser)(GCPtr pGC); - int (*OpaqueStippledFillChooser)(GCPtr pGC); - int (*TiledFillChooser)(GCPtr pGC); - XAACacheInfoPtr (*CacheTile)(ScrnInfoPtr Scrn, PixmapPtr pPix); - XAACacheInfoPtr (*CacheStipple)(ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, - int bg); - XAACacheInfoPtr (*CacheMonoStipple)(ScrnInfoPtr Scrn, PixmapPtr pPix); - XAACacheInfoPtr (*CacheMono8x8Pattern)(ScrnInfoPtr Scrn, int pat0, - int pat1); - XAACacheInfoPtr (*CacheColor8x8Pattern)(ScrnInfoPtr Scrn, PixmapPtr pPix, - int fg, int bg); - void (*WriteBitmapToCache) (ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *src, int srcwidth, int fg, - int bg); - void (*WritePixmapToCache) (ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *src, int srcwidth, int bpp, - int depth); - void (*WriteMono8x8PatternToCache)(ScrnInfoPtr pScrn, - XAACacheInfoPtr pCache); - void (*WriteColor8x8PatternToCache)(ScrnInfoPtr pScrn, PixmapPtr pPix, - XAACacheInfoPtr pCache); - GetImageProcPtr GetImage; - GetSpansProcPtr GetSpans; - CopyWindowProcPtr CopyWindow; - Bool (*SetupForCPUToScreenAlphaTexture2)(ScrnInfoPtr pScrn, int op, - CARD16 red, CARD16 green, - CARD16 blue, CARD16 alpha, - CARD32 maskFormat, CARD32 dstFormat, - CARD8 *alphaPtr, int alphaPitch, - int width, int height, int flags); - Bool (*SetupForCPUToScreenTexture2)(ScrnInfoPtr pScrn, int op, - CARD32 srcFormat, CARD32 dstFormat, - CARD8 *texPtr, int texPitch, - int width, int height, int flags); -} XAAStateWrapRec, *XAAStateWrapPtr; - -static int XAAStateKeyIndex; -static DevPrivateKey XAAStateKey = &XAAStateKeyIndex; - -/* Wrap functions start here */ -#define GET_STATEPRIV_GC(pGC) XAAStateWrapPtr pStatePriv =\ -(XAAStateWrapPtr)dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAStateKey) - -#define GET_STATEPRIV_SCREEN(pScreen) XAAStateWrapPtr pStatePriv =\ -(XAAStateWrapPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAStateKey) - -#define GET_STATEPRIV_PSCRN(pScrn) XAAStateWrapPtr pStatePriv =\ -(XAAStateWrapPtr)dixLookupPrivate(&(pScrn)->pScreen->devPrivates, XAAStateKey) - -#define STATE_CHECK_SP(pStatePriv) {\ - ScrnInfoPtr pScrn = pStatePriv->pScrn;\ - int i = 0;\ - int need_change = 0;\ - while(i < pScrn->numEntities) {\ - if(xf86IsEntityShared(pScrn->entityList[i]) &&\ - xf86GetLastScrnFlag(pScrn->entityList[i]) != pScrn->scrnIndex) {\ - need_change = 1;\ - xf86SetLastScrnFlag(pScrn->entityList[i],\ - pScrn->scrnIndex);\ - }\ - i++;\ - }\ - if(need_change == 1) (*pStatePriv->RestoreAccelState)(pScrn);\ -} - -#define STATE_CHECK_PSCRN(pScrn) {\ - int i = 0;\ - int need_change = 0;\ - while(i < pScrn->numEntities) {\ - if(xf86IsEntityShared(pScrn->entityList[i]) &&\ - xf86GetLastScrnFlag(pScrn->entityList[i]) != pScrn->scrnIndex) {\ - need_change = 1;\ - xf86SetLastScrnFlag(pScrn->entityList[i],\ - pScrn->scrnIndex);\ - }\ - i++;\ - }\ - if(need_change == 1) (*pStatePriv->RestoreAccelState)(pScrn);\ -} - -static void XAAStateWrapSync(ScrnInfoPtr pScrn) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->Sync)(pScrn); -} - -static void XAAStateWrapSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, - int rop, unsigned int planemask, - int trans_color) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, rop, planemask, - trans_color); -} - -static void XAAStateWrapSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, - unsigned int planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForSolidFill)(pScrn, color, rop, planemask); -} - -static void XAAStateWrapSetupForSolidLine(ScrnInfoPtr pScrn,int color,int rop, - unsigned int planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForSolidLine)(pScrn, color, rop, planemask); -} - -static void XAAStateWrapSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int length, - unsigned char *pattern) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForDashedLine)(pScrn, fg, bg, rop, planemask, length, pattern); -} - -static void XAAStateWrapSetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, - int right, int bottom) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetClippingRectangle)(pScrn, left, top, right, bottom); -} - -static void XAAStateWrapDisableClipping(ScrnInfoPtr pScrn) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->DisableClipping)(pScrn); -} - -static void XAAStateWrapSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, - int fg, int bg, int rop, - unsigned int planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForMono8x8PatternFill)(pScrn, patx, paty, fg, bg, rop, planemask); -} - -static void XAAStateWrapSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, - int rop, unsigned int planemask, - int transparency_color) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForColor8x8PatternFill)(pScrn, patx, paty, rop, planemask, - transparency_color); -} - -static void XAAStateWrapSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, - int bg, int rop, - unsigned int planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForCPUToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask); -} - -static void XAAStateWrapSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, - int fg, int bg, - int rop, - unsigned int planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForScanlineCPUToScreenColorExpandFill)(pScrn, fg, bg, rop, - planemask); -} - -static void XAAStateWrapSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForScreenToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask); -} - -static void XAAStateWrapSetupForImageWrite(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int transparency_color, - int bpp, int depth) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForImageWrite)(pScrn, rop, planemask, transparency_color, bpp, - depth); -} - -static void XAAStateWrapSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, - int transparency_color, - int bpp, int depth) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForScanlineImageWrite)(pScrn, rop, planemask, transparency_color, - bpp, depth); -} - -static void XAAStateWrapSetupForImageRead(ScrnInfoPtr pScrn, int bpp, int depth) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->SetupForImageRead)(pScrn, bpp, depth); -} - -static void XAAStateWrapScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, - DDXPointPtr pptSrc, BoxPtr pbox, int xdir, - int ydir, int alu, unsigned int planmask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->ScreenToScreenBitBlt)(pScrn, nbox, - pptSrc, pbox, xdir, - ydir, alu, planmask); -} - -static void XAAStateWrapWriteBitmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *src, int srcwidth, int skipleft, - int fg, int bg, int rop, unsigned int planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->WriteBitmap)(pScrn, x, y, w, h, - src, srcwidth, skipleft, - fg, bg, rop, planemask); -} - -static void XAAStateWrapFillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, - unsigned int planemask, int nBox, BoxPtr pBox) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillSolidRects)(pScrn, fg, rop, - planemask, nBox, pBox); -} - -static void XAAStateWrapFillMono8x8PatternRects(ScrnInfoPtr pScrn, int fg, int bg, - int rop, unsigned int planemask, int nBox, - BoxPtr pBox, int pat0, int pat1, - int xorg, int yorg) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillMono8x8PatternRects)(pScrn, fg, bg, - rop, planemask, nBox, - pBox, pat0, pat1, - xorg, yorg); -} - -static void XAAStateWrapFillColor8x8PatternRects(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int nBox, - BoxPtr pBox, int xorg, int yorg, - XAACacheInfoPtr pCache) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillColor8x8PatternRects)(pScrn, rop, - planemask, nBox, - pBox, xorg, yorg, - pCache); -} - -static void XAAStateWrapFillCacheBltRects(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int nBox, BoxPtr pBox, - int xorg, int yorg, XAACacheInfoPtr pCache) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillCacheBltRects)(pScrn, rop, - planemask, nBox, pBox, - xorg, yorg, pCache); -} - -static void XAAStateWrapFillColorExpandRects(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int nBox, - BoxPtr pBox, int xorg, int yorg, - PixmapPtr pPix) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillColorExpandRects)(pScrn, fg, bg, rop, - planemask, nBox, - pBox, xorg, yorg, - pPix); -} - -static void XAAStateWrapFillCacheExpandRects(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int nBox, - BoxPtr pBox, int xorg, int yorg, - PixmapPtr pPix) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillCacheExpandRects)(pScrn, fg, bg, rop, - planemask, nBox, - pBox, xorg, yorg, - pPix); -} - -static void XAAStateWrapFillImageWriteRects(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int nBox, BoxPtr pBox, - int xorg, int yorg, PixmapPtr pPix) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillImageWriteRects)(pScrn, rop, - planemask, nBox, pBox, - xorg, yorg, pPix); -} - -static void XAAStateWrapFillSolidSpans(ScrnInfoPtr pScrn, int fg, int rop, - unsigned int planemask, int n, DDXPointPtr points, - int *widths, int fSorted) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillSolidSpans)(pScrn, fg, rop, - planemask, n, points, - widths, fSorted); -} - -static void XAAStateWrapFillMono8x8PatternSpans(ScrnInfoPtr pScrn, int fg, int bg, - int rop, unsigned int planemask, int n, - DDXPointPtr points, int *widths, - int fSorted, int pat0, int pat1, - int xorg, int yorg) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillMono8x8PatternSpans)(pScrn, fg, bg, - rop, planemask, n, - points, widths, - fSorted, pat0, pat1, - xorg, yorg); -} - -static void XAAStateWrapFillColor8x8PatternSpans(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int n, - DDXPointPtr points, int *widths, - int fSorted, XAACacheInfoPtr pCache, - int xorg, int yorg) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillColor8x8PatternSpans)(pScrn, rop, - planemask, n, - points, widths, - fSorted, pCache, - xorg, yorg); -} - -static void XAAStateWrapFillCacheBltSpans(ScrnInfoPtr pScrn, int rop, - unsigned int planemask, int n, - DDXPointPtr points, int *widths, - int fSorted, XAACacheInfoPtr pCache, - int xorg, int yorg) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillCacheBltSpans)(pScrn, rop, - planemask, n, - points, widths, - fSorted, pCache, - xorg, yorg); -} - -static void XAAStateWrapFillColorExpandSpans(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int n, - DDXPointPtr points, int *widths, int fSorted, - int xorg, int yorg, PixmapPtr pPix) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillColorExpandSpans)(pScrn, fg, bg, rop, - planemask, n, - points, widths, fSorted, - xorg, yorg, pPix); -} - -static void XAAStateWrapFillCacheExpandSpans(ScrnInfoPtr pScrn, int fg, int bg, int rop, - unsigned int planemask, int n, - DDXPointPtr ppt, int *pwidth, int fSorted, - int xorg, int yorg, PixmapPtr pPix) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->FillCacheExpandSpans)(pScrn, fg, bg, rop, - planemask, n, - ppt, pwidth, fSorted, - xorg, yorg, pPix); -} - -static void XAAStateWrapTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int w, int h, - int skipleft, int startline, - unsigned int **glyphs, - int glyphWidth, int fg, int bg, int rop, - unsigned planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->TEGlyphRenderer)(pScrn, x, y, w, h, - skipleft, startline, - glyphs, - glyphWidth, fg, bg, rop, - planemask); -} - -static void XAAStateWrapNonTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int n, - NonTEGlyphPtr glyphs, BoxPtr pbox, - int fg, int rop, unsigned int planemask) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->NonTEGlyphRenderer)(pScrn, x, y, n, - glyphs, pbox, - fg, rop, planemask); -} - -static void XAAStateWrapWritePixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *src, int srcwidth, int rop, - unsigned int planemask, int transparency_color, - int bpp, int depth) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->WritePixmap)(pScrn, x, y, w, h, - src, srcwidth, rop, - planemask, transparency_color, - bpp, depth); -} - -static void XAAStateWrapReadPixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *dst, int dstwidth, int bpp, int depth) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->ReadPixmap)(pScrn, x, y, w, h, - dst, dstwidth, bpp, depth); -} - -static RegionPtr XAAStateWrapCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, - GC *pGC, int srcx, int srcy, int width, int height, - int dstx, int dsty) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->CopyArea)(pSrcDrawable, pDstDrawable, - pGC, srcx, srcy, width, height, - dstx, dsty); -} - -static RegionPtr XAAStateWrapCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, - int srcx, int srcy, int width, int height, - int dstx, int dsty, unsigned long bitPlane) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->CopyPlane)(pSrc, pDst, pGC, - srcx, srcy, width, height, - dstx, dsty, bitPlane); -} - -static void XAAStateWrapPushPixelsSolid(GCPtr pGC, PixmapPtr pBitMap, - DrawablePtr pDrawable, int dx, int dy, int xOrg, - int yOrg) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PushPixelsSolid)(pGC, pBitMap, - pDrawable, dx, dy, xOrg, - yOrg); -} - -static void XAAStateWrapPolyFillRectSolid(DrawablePtr pDraw, GCPtr pGC, int nrectFill, - xRectangle *prectInit) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolyFillRectSolid)(pDraw, pGC, nrectFill, - prectInit); -} - -static void XAAStateWrapPolyFillRectStippled(DrawablePtr pDraw, GCPtr pGC, int nrectFill, - xRectangle *prectInit) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolyFillRectStippled)(pDraw, pGC, nrectFill, - prectInit); -} - -static void XAAStateWrapPolyFillRectOpaqueStippled(DrawablePtr pDraw, GCPtr pGC, - int nrectFill, xRectangle *prectInit) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolyFillRectOpaqueStippled)(pDraw, pGC, - nrectFill, prectInit); -} - -static void XAAStateWrapPolyFillRectTiled(DrawablePtr pDraw, GCPtr pGC, int nrectFill, - xRectangle *prectInit) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolyFillRectTiled)(pDraw, pGC, nrectFill, - prectInit); -} - -static void XAAStateWrapFillSpansSolid(DrawablePtr pDraw, GCPtr pGC, int nInit, - DDXPointPtr ppt, int *pwidth, int fSorted) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->FillSpansSolid)(pDraw, pGC, nInit, - ppt, pwidth, fSorted); -} - -static void XAAStateWrapFillSpansStippled(DrawablePtr pDraw, GCPtr pGC, int nInit, - DDXPointPtr ppt, int *pwidth, int fSorted) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->FillSpansStippled)(pDraw, pGC, nInit, - ppt, pwidth, fSorted); -} - -static void XAAStateWrapFillSpansOpaqueStippled(DrawablePtr pDraw, GCPtr pGC, int nInit, - DDXPointPtr ppt, int *pwidth, int fSorted) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->FillSpansOpaqueStippled)(pDraw, pGC, nInit, - ppt, pwidth, fSorted); -} - -static void XAAStateWrapFillSpansTiled(DrawablePtr pDraw, GCPtr pGC, int nInit, - DDXPointPtr ppt, int *pwidth, int fSorted) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->FillSpansTiled)(pDraw, pGC, nInit, - ppt, pwidth, fSorted); -} - -static int XAAStateWrapPolyText8TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, - char *chars) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->PolyText8TE)(pDraw, pGC, x, y, count, - chars); -} - -static int XAAStateWrapPolyText16TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, - unsigned short *chars) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->PolyText16TE)(pDraw, pGC, x, y, count, - chars); -} - -static void XAAStateWrapImageText8TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, char *chars) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ImageText8TE)(pDraw, pGC, x, y, - count, chars); -} - -static void XAAStateWrapImageText16TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, unsigned short *chars) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ImageText16TE)(pDraw, pGC, x, y, - count, chars); -} - -static void XAAStateWrapImageGlyphBltTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, - int yInit, unsigned int nglyph, CharInfoPtr *ppci, - pointer pglyphBase) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ImageGlyphBltTE)(pDrawable, pGC, xInit, - yInit, nglyph, ppci, - pglyphBase); -} - -static void XAAStateWrapPolyGlyphBltTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, - int yInit, unsigned int nglyph, CharInfoPtr *ppci, - pointer pglyphBase) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolyGlyphBltTE)(pDrawable, pGC, xInit, - yInit, nglyph, ppci, - pglyphBase); -} - -static int XAAStateWrapPolyText8NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, char *chars) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->PolyText8NonTE)(pDraw, pGC, x, y, - count, chars); -} - -static int XAAStateWrapPolyText16NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, unsigned short *chars) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->PolyText16NonTE)(pDraw, pGC, x, y, - count, chars); -} - -static void XAAStateWrapImageText8NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, char *chars) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ImageText8NonTE)(pDraw, pGC, x, y, - count, chars); -} - -static void XAAStateWrapImageText16NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, - int count, unsigned short *chars) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ImageText16NonTE)(pDraw, pGC, x, y, - count, chars); -} - -static void XAAStateWrapImageGlyphBltNonTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, - int yInit, unsigned int nglyph, - CharInfoPtr *ppci, pointer pglyphBase) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ImageGlyphBltNonTE)(pDrawable, pGC, xInit, - yInit, nglyph, - ppci, pglyphBase); -} - -static void XAAStateWrapPolyGlyphBltNonTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, - int yInit, unsigned int nglyph, - CharInfoPtr *ppci, pointer pglyphBase) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolyGlyphBltNonTE)(pDrawable, pGC, xInit, - yInit, nglyph, - ppci, pglyphBase); -} - -static void XAAStateWrapPolyRectangleThinSolid(DrawablePtr pDrawable,GCPtr pGC, - int nRectsInit, xRectangle *pRectsInit) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolyRectangleThinSolid)(pDrawable, pGC, - nRectsInit, pRectsInit); -} - -static void XAAStateWrapPolylinesWideSolid(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pPts) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolylinesWideSolid)(pDrawable, pGC, mode, - npt, pPts); -} - -static void XAAStateWrapPolylinesThinSolid(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pPts) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolylinesThinSolid)(pDrawable, pGC, mode, - npt, pPts); -} - -static void XAAStateWrapPolySegmentThinSolid(DrawablePtr pDrawable, GCPtr pGC, int nseg, - xSegment *pSeg) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolySegmentThinSolid)(pDrawable, pGC, nseg, - pSeg); -} - -static void XAAStateWrapPolylinesThinDashed(DrawablePtr pDrawable, GCPtr pGC, int mode, - int npt, DDXPointPtr pPts) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolylinesThinDashed)(pDrawable, pGC, mode, - npt, pPts); -} - -static void XAAStateWrapPolySegmentThinDashed(DrawablePtr pDrawable, GCPtr pGC, int nseg, - xSegment *pSeg) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolySegmentThinDashed)(pDrawable, pGC, nseg, - pSeg); -} - -static void XAAStateWrapFillPolygonSolid(DrawablePtr pDrawable, GCPtr pGC, int shape, - int mode, int count, DDXPointPtr ptsIn) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->FillPolygonSolid)(pDrawable, pGC, shape, - mode, count, ptsIn); -} - -static void XAAStateWrapFillPolygonStippled(DrawablePtr pDrawable, GCPtr pGC, int shape, - int mode, int count, DDXPointPtr ptsIn) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->FillPolygonStippled)(pDrawable, pGC, shape, - mode, count, ptsIn); -} - -static void XAAStateWrapFillPolygonOpaqueStippled(DrawablePtr pDrawable, GCPtr pGC, - int shape, int mode, int count, - DDXPointPtr ptsIn) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->FillPolygonOpaqueStippled)(pDrawable, pGC, - shape, mode, count, - ptsIn); -} - -static void XAAStateWrapFillPolygonTiled(DrawablePtr pDrawable, GCPtr pGC, int shape, - int mode, int count, DDXPointPtr ptsIn) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->FillPolygonTiled)(pDrawable, pGC, shape, - mode, count, ptsIn); -} - -static void XAAStateWrapPolyFillArcSolid(DrawablePtr pDraw, GCPtr pGC, int narcs, - xArc *parcs) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PolyFillArcSolid)(pDraw, pGC, narcs, - parcs); -} - -static void XAAStateWrapPutImage(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y, - int w, int h, int leftPad, int format, char *pImage) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->PutImage)(pDraw, pGC, depth, x, y, - w, h, leftPad, format, pImage); -} - -static void XAAStateWrapValidateFillSpans(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidateFillSpans)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidateSetSpans(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidateSetSpans)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePutImage(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePutImage)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidateCopyArea(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidateCopyArea)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidateCopyPlane(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidateCopyPlane)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolyPoint(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolyPoint)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolylines(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolylines)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolySegment(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolySegment)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolyRectangle(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolyRectangle)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolyArc(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolyArc)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidateFillPolygon(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidateFillPolygon)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolyFillRect(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolyFillRect)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolyFillArc(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolyFillArc)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolyText8(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolyText8)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolyText16(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolyText16)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidateImageText8(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidateImageText8)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidateImageText16(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidateImageText16)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePolyGlyphBlt(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePolyGlyphBlt)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidateImageGlyphBlt(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - (*pStatePriv->ValidateImageGlyphBlt)(pGC, changes, - pDraw); -} - -static void XAAStateWrapValidatePushPixels(GCPtr pGC, unsigned long changes, - DrawablePtr pDraw) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ValidatePushPixels)(pGC, changes, - pDraw); -} - -static void XAAStateWrapComputeDash(GCPtr pGC) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ComputeDash)(pGC); -} - -static void XAAStateWrapInitPixmapCache(ScreenPtr pScreen, RegionPtr areas, - pointer data) -{ - GET_STATEPRIV_SCREEN(pScreen); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->InitPixmapCache)(pScreen, areas, - data); -} - -static void XAAStateWrapClosePixmapCache(ScreenPtr pScreen) -{ - GET_STATEPRIV_SCREEN(pScreen); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->ClosePixmapCache)(pScreen); -} - -static int XAAStateWrapStippledFillChooser(GCPtr pGC) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->StippledFillChooser)(pGC); -} - -static int XAAStateWrapOpaqueStippledFillChooser(GCPtr pGC) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->OpaqueStippledFillChooser)(pGC); -} - -static int XAAStateWrapTiledFillChooser(GCPtr pGC) -{ - GET_STATEPRIV_GC(pGC); - STATE_CHECK_SP(pStatePriv); - - return (*pStatePriv->TiledFillChooser)(pGC); -} - -static XAACacheInfoPtr XAAStateWrapCacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - return (*pStatePriv->CacheTile)(pScrn, pPix); -} - -static XAACacheInfoPtr XAAStateWrapCacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, - int bg) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - return (*pStatePriv->CacheStipple)(pScrn, pPix, fg, - bg); -} - -static XAACacheInfoPtr XAAStateWrapCacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - return (*pStatePriv->CacheMonoStipple)(pScrn, pPix); -} - -static XAACacheInfoPtr XAAStateWrapCacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, - int pat1) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - return (*pStatePriv->CacheMono8x8Pattern)(pScrn, pat0, - pat1); -} - -static XAACacheInfoPtr XAAStateWrapCacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, - int fg, int bg) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - return (*pStatePriv->CacheColor8x8Pattern)(pScrn, pPix, - fg, bg); -} - -static void XAAStateWrapWriteBitmapToCache(ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *src, int srcwidth, int fg, - int bg) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->WriteBitmapToCache)(pScrn, x, y, w, h, - src, srcwidth, fg, - bg); -} - -static void XAAStateWrapWritePixmapToCache(ScrnInfoPtr pScrn, int x, int y, int w, int h, - unsigned char *src, int srcwidth, int bpp, - int depth) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->WritePixmapToCache)(pScrn, x, y, w, h, - src, srcwidth, bpp, - depth); -} - -static void XAAStateWrapWriteMono8x8PatternToCache(ScrnInfoPtr pScrn, - XAACacheInfoPtr pCache) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->WriteMono8x8PatternToCache)(pScrn, - pCache); -} - -static void XAAStateWrapWriteColor8x8PatternToCache(ScrnInfoPtr pScrn, PixmapPtr pPix, - XAACacheInfoPtr pCache) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - (*pStatePriv->WriteColor8x8PatternToCache)(pScrn, pPix, - pCache); -} - -static void XAAStateWrapGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, - unsigned int format,unsigned long planeMask, - char *pdstLine) -{ - GET_STATEPRIV_SCREEN(pDrawable->pScreen); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->GetImage)(pDrawable, sx, sy, w, h, - format, planeMask, - pdstLine); -} - -static void XAAStateWrapGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, - int *pwidth, int nspans, char *pdstStart) -{ - GET_STATEPRIV_SCREEN(pDrawable->pScreen); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->GetSpans)(pDrawable, wMax, ppt, - pwidth, nspans, pdstStart); -} - -static void XAAStateWrapCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, - RegionPtr prgnSrc) -{ - GET_STATEPRIV_SCREEN(pWindow->drawable.pScreen); - STATE_CHECK_SP(pStatePriv); - - (*pStatePriv->CopyWindow)(pWindow, ptOldOrg, - prgnSrc); -} - -static Bool XAAStateWrapSetupForCPUToScreenAlphaTexture2(ScrnInfoPtr pScrn, - int op, CARD16 red, - CARD16 green, - CARD16 blue, - CARD16 alpha, - CARD32 srcFormat, - CARD32 dstFormat, - CARD8 *alphaPtr, - int alphaPitch, - int width, int height, - int flags) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - return (*pStatePriv->SetupForCPUToScreenAlphaTexture2)(pScrn, op, red, green, - blue, alpha, srcFormat, - dstFormat, alphaPtr, - alphaPitch, width, - height, flags); -} - -static Bool XAAStateWrapSetupForCPUToScreenTexture2(ScrnInfoPtr pScrn, int op, - CARD32 srcFormat, - CARD32 dstFormat, - CARD8 *texPtr, int texPitch, - int width, int height, - int flags) -{ - GET_STATEPRIV_PSCRN(pScrn); - STATE_CHECK_PSCRN(pScrn); - - return (*pStatePriv->SetupForCPUToScreenTexture2)(pScrn, op, srcFormat, - dstFormat, texPtr, texPitch, - width, height, flags); -} - -/* Setup Function */ -Bool -XAAInitStateWrap(ScreenPtr pScreen, XAAInfoRecPtr infoRec) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - XAAStateWrapPtr pStatePriv; - int i = 0; - - if(!(pStatePriv = xalloc(sizeof(XAAStateWrapRec)))) return FALSE; - dixSetPrivate(&pScreen->devPrivates, XAAStateKey, pStatePriv); - pStatePriv->RestoreAccelState = infoRec->RestoreAccelState; - pStatePriv->pScrn = pScrn; - - /* Initialize the last screen to -1 so whenever an accel function - * is called the proper state is setup - */ - while(i < pScrn->numEntities) { - xf86SetLastScrnFlag(pScrn->entityList[i], -1); - i++; - } -/* Do the wrapping */ - XAA_STATE_WRAP(Sync); - XAA_STATE_WRAP(SetupForScreenToScreenCopy); - XAA_STATE_WRAP(SetupForSolidFill); - XAA_STATE_WRAP(SetupForSolidLine); - XAA_STATE_WRAP(SetupForDashedLine); - XAA_STATE_WRAP(SetClippingRectangle); - XAA_STATE_WRAP(DisableClipping); - XAA_STATE_WRAP(SetupForMono8x8PatternFill); - XAA_STATE_WRAP(SetupForColor8x8PatternFill); - XAA_STATE_WRAP(SetupForCPUToScreenColorExpandFill); - XAA_STATE_WRAP(SetupForScanlineCPUToScreenColorExpandFill); - XAA_STATE_WRAP(SetupForScreenToScreenColorExpandFill); - XAA_STATE_WRAP(SetupForImageWrite); - XAA_STATE_WRAP(SetupForScanlineImageWrite); - XAA_STATE_WRAP(SetupForImageRead); - XAA_STATE_WRAP(ScreenToScreenBitBlt); - XAA_STATE_WRAP(WriteBitmap); - XAA_STATE_WRAP(FillSolidRects); - XAA_STATE_WRAP(FillMono8x8PatternRects); - XAA_STATE_WRAP(FillColor8x8PatternRects); - XAA_STATE_WRAP(FillCacheBltRects); - XAA_STATE_WRAP(FillColorExpandRects); - XAA_STATE_WRAP(FillCacheExpandRects); - XAA_STATE_WRAP(FillImageWriteRects); - XAA_STATE_WRAP(FillSolidSpans); - XAA_STATE_WRAP(FillMono8x8PatternSpans); - XAA_STATE_WRAP(FillColor8x8PatternSpans); - XAA_STATE_WRAP(FillCacheBltSpans); - XAA_STATE_WRAP(FillColorExpandSpans); - XAA_STATE_WRAP(FillCacheExpandSpans); - XAA_STATE_WRAP(TEGlyphRenderer); - XAA_STATE_WRAP(NonTEGlyphRenderer); - XAA_STATE_WRAP(WritePixmap); - XAA_STATE_WRAP(ReadPixmap); - XAA_STATE_WRAP(CopyArea); - XAA_STATE_WRAP(CopyPlane); - XAA_STATE_WRAP(PushPixelsSolid); - XAA_STATE_WRAP(PolyFillRectSolid); - XAA_STATE_WRAP(PolyFillRectStippled); - XAA_STATE_WRAP(PolyFillRectOpaqueStippled); - XAA_STATE_WRAP(PolyFillRectTiled); - XAA_STATE_WRAP(FillSpansSolid); - XAA_STATE_WRAP(FillSpansStippled); - XAA_STATE_WRAP(FillSpansOpaqueStippled); - XAA_STATE_WRAP(FillSpansTiled); - XAA_STATE_WRAP(PolyText8TE); - XAA_STATE_WRAP(PolyText16TE); - XAA_STATE_WRAP(ImageText8TE); - XAA_STATE_WRAP(ImageText16TE); - XAA_STATE_WRAP(ImageGlyphBltTE); - XAA_STATE_WRAP(PolyGlyphBltTE); - XAA_STATE_WRAP(PolyText8NonTE); - XAA_STATE_WRAP(PolyText16NonTE); - XAA_STATE_WRAP(ImageText8NonTE); - XAA_STATE_WRAP(ImageText16NonTE); - XAA_STATE_WRAP(ImageGlyphBltNonTE); - XAA_STATE_WRAP(PolyGlyphBltNonTE); - XAA_STATE_WRAP(PolyRectangleThinSolid); - XAA_STATE_WRAP(PolylinesWideSolid); - XAA_STATE_WRAP(PolylinesThinSolid); - XAA_STATE_WRAP(PolySegmentThinSolid); - XAA_STATE_WRAP(PolylinesThinDashed); - XAA_STATE_WRAP(PolySegmentThinDashed); - XAA_STATE_WRAP(FillPolygonSolid); - XAA_STATE_WRAP(FillPolygonStippled); - XAA_STATE_WRAP(FillPolygonOpaqueStippled); - XAA_STATE_WRAP(FillPolygonTiled); - XAA_STATE_WRAP(PolyFillArcSolid); - XAA_STATE_WRAP(PutImage); - XAA_STATE_WRAP(ValidateFillSpans); - XAA_STATE_WRAP(ValidateSetSpans); - XAA_STATE_WRAP(ValidatePutImage); - XAA_STATE_WRAP(ValidateCopyArea); - XAA_STATE_WRAP(ValidateCopyPlane); - XAA_STATE_WRAP(ValidatePolyPoint); - XAA_STATE_WRAP(ValidatePolylines); - XAA_STATE_WRAP(ValidatePolySegment); - XAA_STATE_WRAP(ValidatePolyRectangle); - XAA_STATE_WRAP(ValidatePolyArc); - XAA_STATE_WRAP(ValidateFillPolygon); - XAA_STATE_WRAP(ValidatePolyFillRect); - XAA_STATE_WRAP(ValidatePolyFillArc); - XAA_STATE_WRAP(ValidatePolyText8); - XAA_STATE_WRAP(ValidatePolyText16); - XAA_STATE_WRAP(ValidateImageText8); - XAA_STATE_WRAP(ValidateImageText16); - XAA_STATE_WRAP(ValidatePolyGlyphBlt); - XAA_STATE_WRAP(ValidateImageGlyphBlt); - XAA_STATE_WRAP(ValidatePushPixels); - XAA_STATE_WRAP(ComputeDash); - XAA_STATE_WRAP(InitPixmapCache); - XAA_STATE_WRAP(ClosePixmapCache); - XAA_STATE_WRAP(StippledFillChooser); - XAA_STATE_WRAP(OpaqueStippledFillChooser); - XAA_STATE_WRAP(TiledFillChooser); - XAA_STATE_WRAP(CacheTile); - XAA_STATE_WRAP(CacheStipple); - XAA_STATE_WRAP(CacheMonoStipple); - XAA_STATE_WRAP(CacheMono8x8Pattern); - XAA_STATE_WRAP(CacheColor8x8Pattern); - XAA_STATE_WRAP(WriteBitmapToCache); - XAA_STATE_WRAP(WritePixmapToCache); - XAA_STATE_WRAP(WriteMono8x8PatternToCache); - XAA_STATE_WRAP(WriteColor8x8PatternToCache); - XAA_STATE_WRAP(GetImage); - XAA_STATE_WRAP(GetSpans); - XAA_STATE_WRAP(CopyWindow); - XAA_STATE_WRAP(SetupForCPUToScreenAlphaTexture2); - XAA_STATE_WRAP(SetupForCPUToScreenTexture2); - return TRUE; -} + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "xf86str.h" +#include "mi.h" +#include "miline.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaawrap.h" +#include "servermd.h" + +#define XAA_STATE_WRAP(func) do {\ +if(infoRec->func) { \ + pStatePriv->func = infoRec->func;\ + infoRec->func = XAAStateWrap##func;\ +}} while(0) + +/* Wrap all XAA functions and allocate our private structure. + */ + +typedef struct _XAAStateWrapRec { + ScrnInfoPtr pScrn; + void (*RestoreAccelState)(ScrnInfoPtr pScrn); + void (*Sync)(ScrnInfoPtr pScrn); + void (*SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, + int trans_color); + void (*SetupForSolidFill)(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask); + void (*SetupForSolidLine)(ScrnInfoPtr pScrn,int color,int rop, + unsigned int planemask); + void (*SetupForDashedLine)(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int length, + unsigned char *pattern); + void (*SetClippingRectangle) (ScrnInfoPtr pScrn, int left, int top, + int right, int bottom); + void (*DisableClipping)(ScrnInfoPtr pScrn); + void (*SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, + int fg, int bg, int rop, + unsigned int planemask); + void (*SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, + int rop, unsigned int planemask, + int transparency_color); + void (*SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, + int bg, int rop, + unsigned int planemask); + void (*SetupForScanlineCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); + void (*SetupForScreenToScreenColorExpandFill) (ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); + void (*SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth); + void (*SetupForScanlineImageWrite)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth); + void (*SetupForImageRead) (ScrnInfoPtr pScrn, int bpp, int depth); + void (*ScreenToScreenBitBlt)(ScrnInfoPtr pScrn, int nbox, + DDXPointPtr pptSrc, BoxPtr pbox, int xdir, + int ydir, int alu, unsigned int planmask); + void (*WriteBitmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int skipleft, + int fg, int bg, int rop, unsigned int planemask); + void (*FillSolidRects)(ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox); + void (*FillMono8x8PatternRects)(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int pat0, int pat1, + int xorg, int yorg); + void (*FillColor8x8PatternRects)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + XAACacheInfoPtr pCache); + void (*FillCacheBltRects)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, XAACacheInfoPtr pCache); + void (*FillColorExpandRects)(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + PixmapPtr pPix); + void (*FillCacheExpandRects)(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + void (*FillImageWriteRects)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix); + void (*FillSolidSpans)(ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int n, DDXPointPtr points, + int *widths, int fSorted); + void (*FillMono8x8PatternSpans)(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, int pat0, int pat1, + int xorg, int yorg); + void (*FillColor8x8PatternSpans)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, XAACacheInfoPtr pCache, + int xorg, int yorg); + void (*FillCacheBltSpans)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int n, DDXPointPtr points, + int *widths, int fSorted, XAACacheInfoPtr pCache, + int xorg, int yorg); + void (*FillColorExpandSpans)(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, int fSorted, + int xorg, int yorg, PixmapPtr pPix); + void (*FillCacheExpandSpans)(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, DDXPointPtr ppt, + int *pwidth, int fSorted, int xorg, int yorg, + PixmapPtr pPix); + void (*TEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft, int startline, unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask); + void (*NonTEGlyphRenderer)(ScrnInfoPtr pScrn, int x, int y, int n, + NonTEGlyphPtr glyphs, BoxPtr pbox, + int fg, int rop, unsigned int planemask); + void (*WritePixmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth); + void (*ReadPixmap) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *dst, int dstwidth, int bpp, int depth); + RegionPtr (*CopyArea)(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GC *pGC, int srcx, int srcy, int width, int height, + int dstx, int dsty); + RegionPtr (*CopyPlane)(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int width, int height, int dstx, + int dsty, unsigned long bitPlane); + void (*PushPixelsSolid) (GCPtr pGC, PixmapPtr pBitMap, + DrawablePtr pDrawable, int dx, int dy, int xOrg, + int yOrg); + void (*PolyFillRectSolid)(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit); + void (*PolyFillRectStippled)(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit); + void (*PolyFillRectOpaqueStippled)(DrawablePtr pDraw, GCPtr pGC, + int nrectFill, xRectangle *prectInit); + void (*PolyFillRectTiled)(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit); + void (*FillSpansSolid)(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + void (*FillSpansStippled)(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + void (*FillSpansOpaqueStippled)(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + void (*FillSpansTiled)(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted); + int (*PolyText8TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + char *chars); + int (*PolyText16TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + unsigned short *chars); + void (*ImageText8TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + char *chars); + void (*ImageText16TE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars); + void (*ImageGlyphBltTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase); + void (*PolyGlyphBltTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase); + int (*PolyText8NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars); + int (*PolyText16NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars); + void (*ImageText8NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars); + void (*ImageText16NonTE) (DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars); + void (*ImageGlyphBltNonTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase); + void (*PolyGlyphBltNonTE) (DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase); + void (*PolyRectangleThinSolid)(DrawablePtr pDrawable,GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit); + void (*PolylinesWideSolid)(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts); + void (*PolylinesThinSolid)(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts); + void (*PolySegmentThinSolid)(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg); + void (*PolylinesThinDashed)(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts); + void (*PolySegmentThinDashed)(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg); + void (*FillPolygonSolid)(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); + void (*FillPolygonStippled)(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); + void (*FillPolygonOpaqueStippled)(DrawablePtr pDrawable, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr ptsIn); + void (*FillPolygonTiled)(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn); + void (*PolyFillArcSolid)(DrawablePtr pDraw, GCPtr pGC, int narcs, + xArc *parcs); + void (*PutImage)(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char *pImage); + ValidateGCProcPtr ValidateFillSpans; + ValidateGCProcPtr ValidateSetSpans; + ValidateGCProcPtr ValidatePutImage; + ValidateGCProcPtr ValidateCopyArea; + ValidateGCProcPtr ValidateCopyPlane; + ValidateGCProcPtr ValidatePolyPoint; + ValidateGCProcPtr ValidatePolylines; + ValidateGCProcPtr ValidatePolySegment; + ValidateGCProcPtr ValidatePolyRectangle; + ValidateGCProcPtr ValidatePolyArc; + ValidateGCProcPtr ValidateFillPolygon; + ValidateGCProcPtr ValidatePolyFillRect; + ValidateGCProcPtr ValidatePolyFillArc; + ValidateGCProcPtr ValidatePolyText8; + ValidateGCProcPtr ValidatePolyText16; + ValidateGCProcPtr ValidateImageText8; + ValidateGCProcPtr ValidateImageText16; + ValidateGCProcPtr ValidatePolyGlyphBlt; + ValidateGCProcPtr ValidateImageGlyphBlt; + ValidateGCProcPtr ValidatePushPixels; + void (*ComputeDash)(GCPtr pGC); + void (*InitPixmapCache)(ScreenPtr pScreen, RegionPtr areas, pointer data); + void (*ClosePixmapCache)(ScreenPtr pScreen); + int (*StippledFillChooser)(GCPtr pGC); + int (*OpaqueStippledFillChooser)(GCPtr pGC); + int (*TiledFillChooser)(GCPtr pGC); + XAACacheInfoPtr (*CacheTile)(ScrnInfoPtr Scrn, PixmapPtr pPix); + XAACacheInfoPtr (*CacheStipple)(ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, + int bg); + XAACacheInfoPtr (*CacheMonoStipple)(ScrnInfoPtr Scrn, PixmapPtr pPix); + XAACacheInfoPtr (*CacheMono8x8Pattern)(ScrnInfoPtr Scrn, int pat0, + int pat1); + XAACacheInfoPtr (*CacheColor8x8Pattern)(ScrnInfoPtr Scrn, PixmapPtr pPix, + int fg, int bg); + void (*WriteBitmapToCache) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int fg, + int bg); + void (*WritePixmapToCache) (ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int bpp, + int depth); + void (*WriteMono8x8PatternToCache)(ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache); + void (*WriteColor8x8PatternToCache)(ScrnInfoPtr pScrn, PixmapPtr pPix, + XAACacheInfoPtr pCache); + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + CopyWindowProcPtr CopyWindow; + Bool (*SetupForCPUToScreenAlphaTexture2)(ScrnInfoPtr pScrn, int op, + CARD16 red, CARD16 green, + CARD16 blue, CARD16 alpha, + CARD32 maskFormat, CARD32 dstFormat, + CARD8 *alphaPtr, int alphaPitch, + int width, int height, int flags); + Bool (*SetupForCPUToScreenTexture2)(ScrnInfoPtr pScrn, int op, + CARD32 srcFormat, CARD32 dstFormat, + CARD8 *texPtr, int texPitch, + int width, int height, int flags); +} XAAStateWrapRec, *XAAStateWrapPtr; + +static int XAAStateKeyIndex; +static DevPrivateKey XAAStateKey = &XAAStateKeyIndex; + +/* Wrap functions start here */ +#define GET_STATEPRIV_GC(pGC) XAAStateWrapPtr pStatePriv =\ +(XAAStateWrapPtr)dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAStateKey) + +#define GET_STATEPRIV_SCREEN(pScreen) XAAStateWrapPtr pStatePriv =\ +(XAAStateWrapPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAStateKey) + +#define GET_STATEPRIV_PSCRN(pScrn) XAAStateWrapPtr pStatePriv =\ +(XAAStateWrapPtr)dixLookupPrivate(&(pScrn)->pScreen->devPrivates, XAAStateKey) + +#define STATE_CHECK_SP(pStatePriv) {\ + ScrnInfoPtr pScrn = pStatePriv->pScrn;\ + int i = 0;\ + int need_change = 0;\ + while(i < pScrn->numEntities) {\ + if(xf86IsEntityShared(pScrn->entityList[i]) &&\ + xf86GetLastScrnFlag(pScrn->entityList[i]) != pScrn->scrnIndex) {\ + need_change = 1;\ + xf86SetLastScrnFlag(pScrn->entityList[i],\ + pScrn->scrnIndex);\ + }\ + i++;\ + }\ + if(need_change == 1) (*pStatePriv->RestoreAccelState)(pScrn);\ +} + +#define STATE_CHECK_PSCRN(pScrn) {\ + int i = 0;\ + int need_change = 0;\ + while(i < pScrn->numEntities) {\ + if(xf86IsEntityShared(pScrn->entityList[i]) &&\ + xf86GetLastScrnFlag(pScrn->entityList[i]) != pScrn->scrnIndex) {\ + need_change = 1;\ + xf86SetLastScrnFlag(pScrn->entityList[i],\ + pScrn->scrnIndex);\ + }\ + i++;\ + }\ + if(need_change == 1) (*pStatePriv->RestoreAccelState)(pScrn);\ +} + +static void XAAStateWrapSync(ScrnInfoPtr pScrn) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->Sync)(pScrn); +} + +static void XAAStateWrapSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, + int trans_color) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, rop, planemask, + trans_color); +} + +static void XAAStateWrapSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForSolidFill)(pScrn, color, rop, planemask); +} + +static void XAAStateWrapSetupForSolidLine(ScrnInfoPtr pScrn,int color,int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForSolidLine)(pScrn, color, rop, planemask); +} + +static void XAAStateWrapSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int length, + unsigned char *pattern) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForDashedLine)(pScrn, fg, bg, rop, planemask, length, pattern); +} + +static void XAAStateWrapSetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, + int right, int bottom) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetClippingRectangle)(pScrn, left, top, right, bottom); +} + +static void XAAStateWrapDisableClipping(ScrnInfoPtr pScrn) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->DisableClipping)(pScrn); +} + +static void XAAStateWrapSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, + int fg, int bg, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForMono8x8PatternFill)(pScrn, patx, paty, fg, bg, rop, planemask); +} + +static void XAAStateWrapSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, + int rop, unsigned int planemask, + int transparency_color) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForColor8x8PatternFill)(pScrn, patx, paty, rop, planemask, + transparency_color); +} + +static void XAAStateWrapSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, + int bg, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForCPUToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask); +} + +static void XAAStateWrapSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForScanlineCPUToScreenColorExpandFill)(pScrn, fg, bg, rop, + planemask); +} + +static void XAAStateWrapSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForScreenToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask); +} + +static void XAAStateWrapSetupForImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForImageWrite)(pScrn, rop, planemask, transparency_color, bpp, + depth); +} + +static void XAAStateWrapSetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForScanlineImageWrite)(pScrn, rop, planemask, transparency_color, + bpp, depth); +} + +static void XAAStateWrapSetupForImageRead(ScrnInfoPtr pScrn, int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->SetupForImageRead)(pScrn, bpp, depth); +} + +static void XAAStateWrapScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, + DDXPointPtr pptSrc, BoxPtr pbox, int xdir, + int ydir, int alu, unsigned int planmask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->ScreenToScreenBitBlt)(pScrn, nbox, + pptSrc, pbox, xdir, + ydir, alu, planmask); +} + +static void XAAStateWrapWriteBitmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int skipleft, + int fg, int bg, int rop, unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WriteBitmap)(pScrn, x, y, w, h, + src, srcwidth, skipleft, + fg, bg, rop, planemask); +} + +static void XAAStateWrapFillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int nBox, BoxPtr pBox) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillSolidRects)(pScrn, fg, rop, + planemask, nBox, pBox); +} + +static void XAAStateWrapFillMono8x8PatternRects(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int nBox, + BoxPtr pBox, int pat0, int pat1, + int xorg, int yorg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillMono8x8PatternRects)(pScrn, fg, bg, + rop, planemask, nBox, + pBox, pat0, pat1, + xorg, yorg); +} + +static void XAAStateWrapFillColor8x8PatternRects(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + XAACacheInfoPtr pCache) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillColor8x8PatternRects)(pScrn, rop, + planemask, nBox, + pBox, xorg, yorg, + pCache); +} + +static void XAAStateWrapFillCacheBltRects(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, XAACacheInfoPtr pCache) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillCacheBltRects)(pScrn, rop, + planemask, nBox, pBox, + xorg, yorg, pCache); +} + +static void XAAStateWrapFillColorExpandRects(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillColorExpandRects)(pScrn, fg, bg, rop, + planemask, nBox, + pBox, xorg, yorg, + pPix); +} + +static void XAAStateWrapFillCacheExpandRects(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int nBox, + BoxPtr pBox, int xorg, int yorg, + PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillCacheExpandRects)(pScrn, fg, bg, rop, + planemask, nBox, + pBox, xorg, yorg, + pPix); +} + +static void XAAStateWrapFillImageWriteRects(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int nBox, BoxPtr pBox, + int xorg, int yorg, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillImageWriteRects)(pScrn, rop, + planemask, nBox, pBox, + xorg, yorg, pPix); +} + +static void XAAStateWrapFillSolidSpans(ScrnInfoPtr pScrn, int fg, int rop, + unsigned int planemask, int n, DDXPointPtr points, + int *widths, int fSorted) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillSolidSpans)(pScrn, fg, rop, + planemask, n, points, + widths, fSorted); +} + +static void XAAStateWrapFillMono8x8PatternSpans(ScrnInfoPtr pScrn, int fg, int bg, + int rop, unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, int pat0, int pat1, + int xorg, int yorg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillMono8x8PatternSpans)(pScrn, fg, bg, + rop, planemask, n, + points, widths, + fSorted, pat0, pat1, + xorg, yorg); +} + +static void XAAStateWrapFillColor8x8PatternSpans(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, XAACacheInfoPtr pCache, + int xorg, int yorg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillColor8x8PatternSpans)(pScrn, rop, + planemask, n, + points, widths, + fSorted, pCache, + xorg, yorg); +} + +static void XAAStateWrapFillCacheBltSpans(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, + int fSorted, XAACacheInfoPtr pCache, + int xorg, int yorg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillCacheBltSpans)(pScrn, rop, + planemask, n, + points, widths, + fSorted, pCache, + xorg, yorg); +} + +static void XAAStateWrapFillColorExpandSpans(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr points, int *widths, int fSorted, + int xorg, int yorg, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillColorExpandSpans)(pScrn, fg, bg, rop, + planemask, n, + points, widths, fSorted, + xorg, yorg, pPix); +} + +static void XAAStateWrapFillCacheExpandSpans(ScrnInfoPtr pScrn, int fg, int bg, int rop, + unsigned int planemask, int n, + DDXPointPtr ppt, int *pwidth, int fSorted, + int xorg, int yorg, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->FillCacheExpandSpans)(pScrn, fg, bg, rop, + planemask, n, + ppt, pwidth, fSorted, + xorg, yorg, pPix); +} + +static void XAAStateWrapTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft, int startline, + unsigned int **glyphs, + int glyphWidth, int fg, int bg, int rop, + unsigned planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->TEGlyphRenderer)(pScrn, x, y, w, h, + skipleft, startline, + glyphs, + glyphWidth, fg, bg, rop, + planemask); +} + +static void XAAStateWrapNonTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int n, + NonTEGlyphPtr glyphs, BoxPtr pbox, + int fg, int rop, unsigned int planemask) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->NonTEGlyphRenderer)(pScrn, x, y, n, + glyphs, pbox, + fg, rop, planemask); +} + +static void XAAStateWrapWritePixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int rop, + unsigned int planemask, int transparency_color, + int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WritePixmap)(pScrn, x, y, w, h, + src, srcwidth, rop, + planemask, transparency_color, + bpp, depth); +} + +static void XAAStateWrapReadPixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *dst, int dstwidth, int bpp, int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->ReadPixmap)(pScrn, x, y, w, h, + dst, dstwidth, bpp, depth); +} + +static RegionPtr XAAStateWrapCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GC *pGC, int srcx, int srcy, int width, int height, + int dstx, int dsty) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->CopyArea)(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, + dstx, dsty); +} + +static RegionPtr XAAStateWrapCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, + int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long bitPlane) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->CopyPlane)(pSrc, pDst, pGC, + srcx, srcy, width, height, + dstx, dsty, bitPlane); +} + +static void XAAStateWrapPushPixelsSolid(GCPtr pGC, PixmapPtr pBitMap, + DrawablePtr pDrawable, int dx, int dy, int xOrg, + int yOrg) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PushPixelsSolid)(pGC, pBitMap, + pDrawable, dx, dy, xOrg, + yOrg); +} + +static void XAAStateWrapPolyFillRectSolid(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillRectSolid)(pDraw, pGC, nrectFill, + prectInit); +} + +static void XAAStateWrapPolyFillRectStippled(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillRectStippled)(pDraw, pGC, nrectFill, + prectInit); +} + +static void XAAStateWrapPolyFillRectOpaqueStippled(DrawablePtr pDraw, GCPtr pGC, + int nrectFill, xRectangle *prectInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillRectOpaqueStippled)(pDraw, pGC, + nrectFill, prectInit); +} + +static void XAAStateWrapPolyFillRectTiled(DrawablePtr pDraw, GCPtr pGC, int nrectFill, + xRectangle *prectInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillRectTiled)(pDraw, pGC, nrectFill, + prectInit); +} + +static void XAAStateWrapFillSpansSolid(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillSpansSolid)(pDraw, pGC, nInit, + ppt, pwidth, fSorted); +} + +static void XAAStateWrapFillSpansStippled(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillSpansStippled)(pDraw, pGC, nInit, + ppt, pwidth, fSorted); +} + +static void XAAStateWrapFillSpansOpaqueStippled(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillSpansOpaqueStippled)(pDraw, pGC, nInit, + ppt, pwidth, fSorted); +} + +static void XAAStateWrapFillSpansTiled(DrawablePtr pDraw, GCPtr pGC, int nInit, + DDXPointPtr ppt, int *pwidth, int fSorted) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillSpansTiled)(pDraw, pGC, nInit, + ppt, pwidth, fSorted); +} + +static int XAAStateWrapPolyText8TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + char *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->PolyText8TE)(pDraw, pGC, x, y, count, + chars); +} + +static int XAAStateWrapPolyText16TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, int count, + unsigned short *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->PolyText16TE)(pDraw, pGC, x, y, count, + chars); +} + +static void XAAStateWrapImageText8TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageText8TE)(pDraw, pGC, x, y, + count, chars); +} + +static void XAAStateWrapImageText16TE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageText16TE)(pDraw, pGC, x, y, + count, chars); +} + +static void XAAStateWrapImageGlyphBltTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageGlyphBltTE)(pDrawable, pGC, xInit, + yInit, nglyph, ppci, + pglyphBase); +} + +static void XAAStateWrapPolyGlyphBltTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, CharInfoPtr *ppci, + pointer pglyphBase) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyGlyphBltTE)(pDrawable, pGC, xInit, + yInit, nglyph, ppci, + pglyphBase); +} + +static int XAAStateWrapPolyText8NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->PolyText8NonTE)(pDraw, pGC, x, y, + count, chars); +} + +static int XAAStateWrapPolyText16NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->PolyText16NonTE)(pDraw, pGC, x, y, + count, chars); +} + +static void XAAStateWrapImageText8NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, char *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageText8NonTE)(pDraw, pGC, x, y, + count, chars); +} + +static void XAAStateWrapImageText16NonTE(DrawablePtr pDraw, GCPtr pGC, int x, int y, + int count, unsigned short *chars) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageText16NonTE)(pDraw, pGC, x, y, + count, chars); +} + +static void XAAStateWrapImageGlyphBltNonTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ImageGlyphBltNonTE)(pDrawable, pGC, xInit, + yInit, nglyph, + ppci, pglyphBase); +} + +static void XAAStateWrapPolyGlyphBltNonTE(DrawablePtr pDrawable, GCPtr pGC, int xInit, + int yInit, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyGlyphBltNonTE)(pDrawable, pGC, xInit, + yInit, nglyph, + ppci, pglyphBase); +} + +static void XAAStateWrapPolyRectangleThinSolid(DrawablePtr pDrawable,GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyRectangleThinSolid)(pDrawable, pGC, + nRectsInit, pRectsInit); +} + +static void XAAStateWrapPolylinesWideSolid(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolylinesWideSolid)(pDrawable, pGC, mode, + npt, pPts); +} + +static void XAAStateWrapPolylinesThinSolid(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolylinesThinSolid)(pDrawable, pGC, mode, + npt, pPts); +} + +static void XAAStateWrapPolySegmentThinSolid(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolySegmentThinSolid)(pDrawable, pGC, nseg, + pSeg); +} + +static void XAAStateWrapPolylinesThinDashed(DrawablePtr pDrawable, GCPtr pGC, int mode, + int npt, DDXPointPtr pPts) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolylinesThinDashed)(pDrawable, pGC, mode, + npt, pPts); +} + +static void XAAStateWrapPolySegmentThinDashed(DrawablePtr pDrawable, GCPtr pGC, int nseg, + xSegment *pSeg) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolySegmentThinDashed)(pDrawable, pGC, nseg, + pSeg); +} + +static void XAAStateWrapFillPolygonSolid(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillPolygonSolid)(pDrawable, pGC, shape, + mode, count, ptsIn); +} + +static void XAAStateWrapFillPolygonStippled(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillPolygonStippled)(pDrawable, pGC, shape, + mode, count, ptsIn); +} + +static void XAAStateWrapFillPolygonOpaqueStippled(DrawablePtr pDrawable, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr ptsIn) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillPolygonOpaqueStippled)(pDrawable, pGC, + shape, mode, count, + ptsIn); +} + +static void XAAStateWrapFillPolygonTiled(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int count, DDXPointPtr ptsIn) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->FillPolygonTiled)(pDrawable, pGC, shape, + mode, count, ptsIn); +} + +static void XAAStateWrapPolyFillArcSolid(DrawablePtr pDraw, GCPtr pGC, int narcs, + xArc *parcs) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PolyFillArcSolid)(pDraw, pGC, narcs, + parcs); +} + +static void XAAStateWrapPutImage(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char *pImage) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->PutImage)(pDraw, pGC, depth, x, y, + w, h, leftPad, format, pImage); +} + +static void XAAStateWrapValidateFillSpans(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateFillSpans)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidateSetSpans(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateSetSpans)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePutImage(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePutImage)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidateCopyArea(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateCopyArea)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidateCopyPlane(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateCopyPlane)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolyPoint(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyPoint)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolylines(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolylines)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolySegment(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolySegment)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolyRectangle(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyRectangle)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolyArc(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyArc)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidateFillPolygon(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateFillPolygon)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolyFillRect(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyFillRect)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolyFillArc(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyFillArc)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolyText8(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyText8)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolyText16(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyText16)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidateImageText8(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateImageText8)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidateImageText16(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidateImageText16)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePolyGlyphBlt(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePolyGlyphBlt)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidateImageGlyphBlt(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + (*pStatePriv->ValidateImageGlyphBlt)(pGC, changes, + pDraw); +} + +static void XAAStateWrapValidatePushPixels(GCPtr pGC, unsigned long changes, + DrawablePtr pDraw) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ValidatePushPixels)(pGC, changes, + pDraw); +} + +static void XAAStateWrapComputeDash(GCPtr pGC) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ComputeDash)(pGC); +} + +static void XAAStateWrapInitPixmapCache(ScreenPtr pScreen, RegionPtr areas, + pointer data) +{ + GET_STATEPRIV_SCREEN(pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->InitPixmapCache)(pScreen, areas, + data); +} + +static void XAAStateWrapClosePixmapCache(ScreenPtr pScreen) +{ + GET_STATEPRIV_SCREEN(pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->ClosePixmapCache)(pScreen); +} + +static int XAAStateWrapStippledFillChooser(GCPtr pGC) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->StippledFillChooser)(pGC); +} + +static int XAAStateWrapOpaqueStippledFillChooser(GCPtr pGC) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->OpaqueStippledFillChooser)(pGC); +} + +static int XAAStateWrapTiledFillChooser(GCPtr pGC) +{ + GET_STATEPRIV_GC(pGC); + STATE_CHECK_SP(pStatePriv); + + return (*pStatePriv->TiledFillChooser)(pGC); +} + +static XAACacheInfoPtr XAAStateWrapCacheTile(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheTile)(pScrn, pPix); +} + +static XAACacheInfoPtr XAAStateWrapCacheStipple(ScrnInfoPtr pScrn, PixmapPtr pPix, int fg, + int bg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheStipple)(pScrn, pPix, fg, + bg); +} + +static XAACacheInfoPtr XAAStateWrapCacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheMonoStipple)(pScrn, pPix); +} + +static XAACacheInfoPtr XAAStateWrapCacheMono8x8Pattern(ScrnInfoPtr pScrn, int pat0, + int pat1) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheMono8x8Pattern)(pScrn, pat0, + pat1); +} + +static XAACacheInfoPtr XAAStateWrapCacheColor8x8Pattern(ScrnInfoPtr pScrn, PixmapPtr pPix, + int fg, int bg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->CacheColor8x8Pattern)(pScrn, pPix, + fg, bg); +} + +static void XAAStateWrapWriteBitmapToCache(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int fg, + int bg) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WriteBitmapToCache)(pScrn, x, y, w, h, + src, srcwidth, fg, + bg); +} + +static void XAAStateWrapWritePixmapToCache(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int bpp, + int depth) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WritePixmapToCache)(pScrn, x, y, w, h, + src, srcwidth, bpp, + depth); +} + +static void XAAStateWrapWriteMono8x8PatternToCache(ScrnInfoPtr pScrn, + XAACacheInfoPtr pCache) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WriteMono8x8PatternToCache)(pScrn, + pCache); +} + +static void XAAStateWrapWriteColor8x8PatternToCache(ScrnInfoPtr pScrn, PixmapPtr pPix, + XAACacheInfoPtr pCache) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + (*pStatePriv->WriteColor8x8PatternToCache)(pScrn, pPix, + pCache); +} + +static void XAAStateWrapGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format,unsigned long planeMask, + char *pdstLine) +{ + GET_STATEPRIV_SCREEN(pDrawable->pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->GetImage)(pDrawable, sx, sy, w, h, + format, planeMask, + pdstLine); +} + +static void XAAStateWrapGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, + int *pwidth, int nspans, char *pdstStart) +{ + GET_STATEPRIV_SCREEN(pDrawable->pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->GetSpans)(pDrawable, wMax, ppt, + pwidth, nspans, pdstStart); +} + +static void XAAStateWrapCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + GET_STATEPRIV_SCREEN(pWindow->drawable.pScreen); + STATE_CHECK_SP(pStatePriv); + + (*pStatePriv->CopyWindow)(pWindow, ptOldOrg, + prgnSrc); +} + +static Bool XAAStateWrapSetupForCPUToScreenAlphaTexture2(ScrnInfoPtr pScrn, + int op, CARD16 red, + CARD16 green, + CARD16 blue, + CARD16 alpha, + CARD32 srcFormat, + CARD32 dstFormat, + CARD8 *alphaPtr, + int alphaPitch, + int width, int height, + int flags) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->SetupForCPUToScreenAlphaTexture2)(pScrn, op, red, green, + blue, alpha, srcFormat, + dstFormat, alphaPtr, + alphaPitch, width, + height, flags); +} + +static Bool XAAStateWrapSetupForCPUToScreenTexture2(ScrnInfoPtr pScrn, int op, + CARD32 srcFormat, + CARD32 dstFormat, + CARD8 *texPtr, int texPitch, + int width, int height, + int flags) +{ + GET_STATEPRIV_PSCRN(pScrn); + STATE_CHECK_PSCRN(pScrn); + + return (*pStatePriv->SetupForCPUToScreenTexture2)(pScrn, op, srcFormat, + dstFormat, texPtr, texPitch, + width, height, flags); +} + +/* Setup Function */ +Bool +XAAInitStateWrap(ScreenPtr pScreen, XAAInfoRecPtr infoRec) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XAAStateWrapPtr pStatePriv; + int i = 0; + + if(!(pStatePriv = malloc(sizeof(XAAStateWrapRec)))) return FALSE; + dixSetPrivate(&pScreen->devPrivates, XAAStateKey, pStatePriv); + pStatePriv->RestoreAccelState = infoRec->RestoreAccelState; + pStatePriv->pScrn = pScrn; + + /* Initialize the last screen to -1 so whenever an accel function + * is called the proper state is setup + */ + while(i < pScrn->numEntities) { + xf86SetLastScrnFlag(pScrn->entityList[i], -1); + i++; + } +/* Do the wrapping */ + XAA_STATE_WRAP(Sync); + XAA_STATE_WRAP(SetupForScreenToScreenCopy); + XAA_STATE_WRAP(SetupForSolidFill); + XAA_STATE_WRAP(SetupForSolidLine); + XAA_STATE_WRAP(SetupForDashedLine); + XAA_STATE_WRAP(SetClippingRectangle); + XAA_STATE_WRAP(DisableClipping); + XAA_STATE_WRAP(SetupForMono8x8PatternFill); + XAA_STATE_WRAP(SetupForColor8x8PatternFill); + XAA_STATE_WRAP(SetupForCPUToScreenColorExpandFill); + XAA_STATE_WRAP(SetupForScanlineCPUToScreenColorExpandFill); + XAA_STATE_WRAP(SetupForScreenToScreenColorExpandFill); + XAA_STATE_WRAP(SetupForImageWrite); + XAA_STATE_WRAP(SetupForScanlineImageWrite); + XAA_STATE_WRAP(SetupForImageRead); + XAA_STATE_WRAP(ScreenToScreenBitBlt); + XAA_STATE_WRAP(WriteBitmap); + XAA_STATE_WRAP(FillSolidRects); + XAA_STATE_WRAP(FillMono8x8PatternRects); + XAA_STATE_WRAP(FillColor8x8PatternRects); + XAA_STATE_WRAP(FillCacheBltRects); + XAA_STATE_WRAP(FillColorExpandRects); + XAA_STATE_WRAP(FillCacheExpandRects); + XAA_STATE_WRAP(FillImageWriteRects); + XAA_STATE_WRAP(FillSolidSpans); + XAA_STATE_WRAP(FillMono8x8PatternSpans); + XAA_STATE_WRAP(FillColor8x8PatternSpans); + XAA_STATE_WRAP(FillCacheBltSpans); + XAA_STATE_WRAP(FillColorExpandSpans); + XAA_STATE_WRAP(FillCacheExpandSpans); + XAA_STATE_WRAP(TEGlyphRenderer); + XAA_STATE_WRAP(NonTEGlyphRenderer); + XAA_STATE_WRAP(WritePixmap); + XAA_STATE_WRAP(ReadPixmap); + XAA_STATE_WRAP(CopyArea); + XAA_STATE_WRAP(CopyPlane); + XAA_STATE_WRAP(PushPixelsSolid); + XAA_STATE_WRAP(PolyFillRectSolid); + XAA_STATE_WRAP(PolyFillRectStippled); + XAA_STATE_WRAP(PolyFillRectOpaqueStippled); + XAA_STATE_WRAP(PolyFillRectTiled); + XAA_STATE_WRAP(FillSpansSolid); + XAA_STATE_WRAP(FillSpansStippled); + XAA_STATE_WRAP(FillSpansOpaqueStippled); + XAA_STATE_WRAP(FillSpansTiled); + XAA_STATE_WRAP(PolyText8TE); + XAA_STATE_WRAP(PolyText16TE); + XAA_STATE_WRAP(ImageText8TE); + XAA_STATE_WRAP(ImageText16TE); + XAA_STATE_WRAP(ImageGlyphBltTE); + XAA_STATE_WRAP(PolyGlyphBltTE); + XAA_STATE_WRAP(PolyText8NonTE); + XAA_STATE_WRAP(PolyText16NonTE); + XAA_STATE_WRAP(ImageText8NonTE); + XAA_STATE_WRAP(ImageText16NonTE); + XAA_STATE_WRAP(ImageGlyphBltNonTE); + XAA_STATE_WRAP(PolyGlyphBltNonTE); + XAA_STATE_WRAP(PolyRectangleThinSolid); + XAA_STATE_WRAP(PolylinesWideSolid); + XAA_STATE_WRAP(PolylinesThinSolid); + XAA_STATE_WRAP(PolySegmentThinSolid); + XAA_STATE_WRAP(PolylinesThinDashed); + XAA_STATE_WRAP(PolySegmentThinDashed); + XAA_STATE_WRAP(FillPolygonSolid); + XAA_STATE_WRAP(FillPolygonStippled); + XAA_STATE_WRAP(FillPolygonOpaqueStippled); + XAA_STATE_WRAP(FillPolygonTiled); + XAA_STATE_WRAP(PolyFillArcSolid); + XAA_STATE_WRAP(PutImage); + XAA_STATE_WRAP(ValidateFillSpans); + XAA_STATE_WRAP(ValidateSetSpans); + XAA_STATE_WRAP(ValidatePutImage); + XAA_STATE_WRAP(ValidateCopyArea); + XAA_STATE_WRAP(ValidateCopyPlane); + XAA_STATE_WRAP(ValidatePolyPoint); + XAA_STATE_WRAP(ValidatePolylines); + XAA_STATE_WRAP(ValidatePolySegment); + XAA_STATE_WRAP(ValidatePolyRectangle); + XAA_STATE_WRAP(ValidatePolyArc); + XAA_STATE_WRAP(ValidateFillPolygon); + XAA_STATE_WRAP(ValidatePolyFillRect); + XAA_STATE_WRAP(ValidatePolyFillArc); + XAA_STATE_WRAP(ValidatePolyText8); + XAA_STATE_WRAP(ValidatePolyText16); + XAA_STATE_WRAP(ValidateImageText8); + XAA_STATE_WRAP(ValidateImageText16); + XAA_STATE_WRAP(ValidatePolyGlyphBlt); + XAA_STATE_WRAP(ValidateImageGlyphBlt); + XAA_STATE_WRAP(ValidatePushPixels); + XAA_STATE_WRAP(ComputeDash); + XAA_STATE_WRAP(InitPixmapCache); + XAA_STATE_WRAP(ClosePixmapCache); + XAA_STATE_WRAP(StippledFillChooser); + XAA_STATE_WRAP(OpaqueStippledFillChooser); + XAA_STATE_WRAP(TiledFillChooser); + XAA_STATE_WRAP(CacheTile); + XAA_STATE_WRAP(CacheStipple); + XAA_STATE_WRAP(CacheMonoStipple); + XAA_STATE_WRAP(CacheMono8x8Pattern); + XAA_STATE_WRAP(CacheColor8x8Pattern); + XAA_STATE_WRAP(WriteBitmapToCache); + XAA_STATE_WRAP(WritePixmapToCache); + XAA_STATE_WRAP(WriteMono8x8PatternToCache); + XAA_STATE_WRAP(WriteColor8x8PatternToCache); + XAA_STATE_WRAP(GetImage); + XAA_STATE_WRAP(GetSpans); + XAA_STATE_WRAP(CopyWindow); + XAA_STATE_WRAP(SetupForCPUToScreenAlphaTexture2); + XAA_STATE_WRAP(SetupForCPUToScreenTexture2); + return TRUE; +} diff --git a/xorg-server/hw/xfree86/xaa/xaaTEGlyph.c b/xorg-server/hw/xfree86/xaa/xaaTEGlyph.c index 41e638e5c..049bb2cb3 100644 --- a/xorg-server/hw/xfree86/xaa/xaaTEGlyph.c +++ b/xorg-server/hw/xfree86/xaa/xaaTEGlyph.c @@ -1,1077 +1,1077 @@ - - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "xaa.h" -#include "xaalocal.h" -#include "xaacexp.h" -#include "xf86.h" - -/* scanline function for TRIPLE_BITS_24BPP */ -static CARD32 *DrawTextScanline3(CARD32 *base, CARD32 *mem, int width); - -/* Loop unrolled functions for common font widths */ -static CARD32 *DrawTETextScanlineGeneric(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth7(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth10(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth12(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth14(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth16(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth18(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth24(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); - - -#ifdef USEASSEMBLER -# ifdef FIXEDBASE -# ifdef MSBFIRST -CARD32 *DrawTETextScanlineWidth6PMSBFirstFixedBase(CARD32 *base, - unsigned int **glyphp, int line, int width, int glyphwidth); -CARD32 *DrawTETextScanlineWidth8PMSBFirstFixedBase(CARD32 *base, - unsigned int **glyphp, int line, int width, int glyphwidth); -CARD32 *DrawTETextScanlineWidth9PMSBFirstFixedBase(CARD32 *base, - unsigned int **glyphp, int line, int width, int glyphwidth); -# else -CARD32 *DrawTETextScanlineWidth6PLSBFirstFixedBase(CARD32 *base, - unsigned int **glyphp, int line, int width, int glyphwidth); -CARD32 *DrawTETextScanlineWidth8PLSBFirstFixedBase(CARD32 *base, - unsigned int **glyphp, int line, int width, int glyphwidth); -CARD32 *DrawTETextScanlineWidth9PLSBFirstFixedBase(CARD32 *base, - unsigned int **glyphp, int line, int width, int glyphwidth); -# endif -# else -# ifdef MSBFIRST -CARD32 *DrawTETextScanlineWidth6PMSBFirst(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -CARD32 *DrawTETextScanlineWidth8PMSBFirst(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -CARD32 *DrawTETextScanlineWidth9PMSBFirst(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -# else -CARD32 *DrawTETextScanlineWidth6PLSBFirst(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -CARD32 *DrawTETextScanlineWidth8PLSBFirst(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -CARD32 *DrawTETextScanlineWidth9PLSBFirst(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -# endif -# endif -#else -static CARD32 *DrawTETextScanlineWidth6(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth8(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -static CARD32 *DrawTETextScanlineWidth9(CARD32 *base, unsigned int **glyphp, - int line, int width, int glyphwidth); -#endif - -#define glyph_scanline_func EXPNAME(XAAGlyphScanlineFunc) -#define glyph_get_scanline_func EXPNAME(XAAGetGlyphScanlineFunc) - - -GlyphScanlineFuncPtr glyph_scanline_func[32] = { - DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, - DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, - DrawTETextScanlineGeneric, -#ifdef USEASSEMBLER -# ifdef FIXEDBASE -# ifdef MSBFIRST - DrawTETextScanlineWidth6PMSBFirstFixedBase, - DrawTETextScanlineWidth7, - DrawTETextScanlineWidth8PMSBFirstFixedBase, - DrawTETextScanlineWidth9PMSBFirstFixedBase, -# else - DrawTETextScanlineWidth6PLSBFirstFixedBase, - DrawTETextScanlineWidth7, - DrawTETextScanlineWidth8PLSBFirstFixedBase, - DrawTETextScanlineWidth9PLSBFirstFixedBase, -# endif -# else -# ifdef MSBFIRST - DrawTETextScanlineWidth6PMSBFirst, - DrawTETextScanlineWidth7, - DrawTETextScanlineWidth8PMSBFirst, - DrawTETextScanlineWidth9PMSBFirst, -# else - DrawTETextScanlineWidth6PLSBFirst, - DrawTETextScanlineWidth7, - DrawTETextScanlineWidth8PLSBFirst, - DrawTETextScanlineWidth9PLSBFirst, -# endif -# endif -#else - DrawTETextScanlineWidth6, DrawTETextScanlineWidth7, - DrawTETextScanlineWidth8, DrawTETextScanlineWidth9, -#endif - DrawTETextScanlineWidth10, - DrawTETextScanlineGeneric, DrawTETextScanlineWidth12, - DrawTETextScanlineGeneric, DrawTETextScanlineWidth14, - DrawTETextScanlineGeneric, DrawTETextScanlineWidth16, - DrawTETextScanlineGeneric, DrawTETextScanlineWidth18, - DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, - DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, - DrawTETextScanlineGeneric, DrawTETextScanlineWidth24, - DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, - DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, - DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, - DrawTETextScanlineGeneric, DrawTETextScanlineGeneric -}; - -GlyphScanlineFuncPtr *glyph_get_scanline_func(void) { - return glyph_scanline_func; -} - - -/******************************************************************** - - Here we have TEGlyphRenders for a bunch of different color - expansion types. The driver may provide its own renderer, but - this is the default one which renders using lower-level primitives - exported by the chipset driver. - -********************************************************************/ - -/* This gets built for MSBFIRST or LSBFIRST with FIXEDBASE or not. - A total of 4 versions */ - -void -EXPNAME(XAATEGlyphRenderer)( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - CARD32* base; - GlyphScanlineFuncPtr GlyphFunc = glyph_scanline_func[glyphWidth - 1]; - int dwords = 0; - - if((bg != -1) && (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { - (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); - (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); - bg = -1; - } - - (*infoRec->SetupForCPUToScreenColorExpandFill)( - pScrn, fg, bg, rop, planemask); - - if(skipleft && - (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING) || - (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && - (skipleft > x)))) { - /* draw the first character only */ - - int count = h, line = startline; - int width = glyphWidth - skipleft; - - if(width > w) width = w; - - (*infoRec->SubsequentCPUToScreenColorExpandFill)( - pScrn, x, y, width, h, 0); - - base = (CARD32*)infoRec->ColorExpandBase; - - while(count--) { - register CARD32 tmp = SHIFT_R(glyphs[0][line++],skipleft); - WRITE_BITS(tmp); - } - - w -= width; - if((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && - ((((width + 31) >> 5) * h) & 1)) { - base = (CARD32*)infoRec->ColorExpandBase; - base[0] = 0x00000000; - } - if(!w) goto THE_END; - glyphs++; - x += width; - skipleft = 0; /* nicely aligned again */ - } - - w += skipleft; - x -= skipleft; - dwords = ((w + 31) >> 5) * h; - - (*infoRec->SubsequentCPUToScreenColorExpandFill)( - pScrn, x, y, w, h, skipleft); - - base = (CARD32*)infoRec->ColorExpandBase; - -#ifndef FIXEDBASE - if((((w + 31) >> 5) * h) <= infoRec->ColorExpandRange) - while(h--) { - base = (*GlyphFunc)(base, glyphs, startline++, w, glyphWidth); - } - else -#endif - while(h--) { - (*GlyphFunc)(base, glyphs, startline++, w, glyphWidth); - } - - if((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && - (dwords & 1)) { - base = (CARD32*)infoRec->ColorExpandBase; - base[0] = 0x00000000; - } - -THE_END: - - if(infoRec->TEGlyphRendererFlags & SYNC_AFTER_COLOR_EXPAND) - (*infoRec->Sync)(pScrn); - else SET_SYNC_FLAG(infoRec); -} - -/******************************************************************** - - This is the GlyphRenderer for TRIPLE_BITS_24BPP. It renders to a buffer - with the non FIXEDBASE LSB_FIRST code before tripling, and possibly - reversing the bits and sending them to the screen - -********************************************************************/ - -void -EXPNAME(XAATEGlyphRenderer3)( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - CARD32 *base, *mem; - GlyphScanlineFuncPtr GlyphFunc = XAAGlyphScanlineFuncLSBFirst[glyphWidth - 1]; - int dwords = 0; - - if((bg != -1) && - ((infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY) || - ((infoRec->TEGlyphRendererFlags & RGB_EQUAL) && - (!CHECK_RGB_EQUAL(bg))))) { - (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); - (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); - bg = -1; - } - - (*infoRec->SetupForCPUToScreenColorExpandFill)( - pScrn, fg, bg, rop, planemask); - - if(skipleft) { - /* draw the first character only */ - - int count = h, line = startline; - int width = glyphWidth - skipleft; - CARD32 bits; - - if(width > w) width = w; - (*infoRec->SubsequentCPUToScreenColorExpandFill)( - pScrn, x, y, width, h, 0); - - base = (CARD32*)infoRec->ColorExpandBase; - - while(count--) { - bits = SHIFT_R(glyphs[0][line++],skipleft); - if (width >= 22) { - WRITE_BITS3(bits); - } else if (width >= 11) { - WRITE_BITS2(bits); - } else { - WRITE_BITS1(bits); - } - } - - w -= width; - if((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && - ((((3 * width + 31) >> 5) * h) & 1)) { - base = (CARD32*)infoRec->ColorExpandBase; - base[0] = 0x00000000; - } - if(!w) goto THE_END; - glyphs++; - x += width; - skipleft = 0; /* nicely aligned again */ - } - - dwords = ((3 * w + 31) >> 5) * h; - mem = (CARD32*)xalloc(((w + 31) >> 3) * sizeof(char)); - if (!mem) return; - - (*infoRec->SubsequentCPUToScreenColorExpandFill)(pScrn, x, y, w, h, 0); - - base = (CARD32*)infoRec->ColorExpandBase; - -# ifndef FIXEDBASE - if((((3 * w + 31) >> 5) * h) <= infoRec->ColorExpandRange) - while(h--) { - (*GlyphFunc)(mem, glyphs, startline++, w, glyphWidth); - base = DrawTextScanline3(base, mem, w); - } - else -# endif - while(h--) { - (*GlyphFunc)(mem, glyphs, startline++, w, glyphWidth); - DrawTextScanline3(base, mem, w); - } - - xfree(mem); - - if((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && - (dwords & 1)) { - base = (CARD32*)infoRec->ColorExpandBase; - base[0] = 0x00000000; - } - -THE_END: - - if(infoRec->TEGlyphRendererFlags & SYNC_AFTER_COLOR_EXPAND) - (*infoRec->Sync)(pScrn); - else SET_SYNC_FLAG(infoRec); -} - - -#ifndef FIXEDBASE -/* Scanline version of above gets built for LSBFIRST and MSBFIRST */ - -void -EXPNAME(XAATEGlyphRendererScanline)( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int bufferNo; - CARD32* base; - GlyphScanlineFuncPtr GlyphFunc = glyph_scanline_func[glyphWidth - 1]; - - if((bg != -1) && (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { - (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); - (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); - bg = -1; - } - - (*infoRec->SetupForScanlineCPUToScreenColorExpandFill)( - pScrn, fg, bg, rop, planemask); - - if(skipleft && - (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING) || - (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && - (skipleft > x)))) { - /* draw the first character only */ - - int count = h, line = startline; - int width = glyphWidth - skipleft; - - if(width > w) width = w; - - (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( - pScrn, x, y, width, h, 0); - - bufferNo = 0; - - while(count--) { - register CARD32 tmp = SHIFT_R(glyphs[0][line++],skipleft); - base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; - WRITE_BITS(tmp); - (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); - if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) - bufferNo = 0; - } - - w -= width; - if(!w) goto THE_END; - glyphs++; - x += width; - skipleft = 0; /* nicely aligned again */ - } - - w += skipleft; - x -= skipleft; - - (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( - pScrn, x, y, w, h, skipleft); - - bufferNo = 0; - - while(h--) { - base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; - (*GlyphFunc)(base, glyphs, startline++, w, glyphWidth); - (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); - if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) - bufferNo = 0; - } - -THE_END: - - SET_SYNC_FLAG(infoRec); -} - -void -EXPNAME(XAATEGlyphRendererScanline3)( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int bufferNo; - CARD32 *base, *mem; - GlyphScanlineFuncPtr GlyphFunc = XAAGlyphScanlineFuncLSBFirst[glyphWidth - 1]; - - if((bg != -1) && - ((infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY) || - ((infoRec->TEGlyphRendererFlags & RGB_EQUAL) && - (!CHECK_RGB_EQUAL(bg))))) { - (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); - (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); - bg = -1; - } - - (*infoRec->SetupForScanlineCPUToScreenColorExpandFill)( - pScrn, fg, bg, rop, planemask); - - if(skipleft) { - /* draw the first character only */ - - int count = h, line = startline; - int width = glyphWidth - skipleft; - CARD32 bits; - - if(width > w) width = w; - - (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( - pScrn, x, y, width, h, 0); - - bufferNo = 0; - - while(count--) { - base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; - bits = SHIFT_R(glyphs[0][line++],skipleft); - if (width >= 22) { - WRITE_BITS3(bits); - } else if (width >= 11) { - WRITE_BITS2(bits); - } else { - WRITE_BITS1(bits); - } - (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); - if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) - bufferNo = 0; - } - - w -= width; - if(!w) goto THE_END; - glyphs++; - x += width; - skipleft = 0; /* nicely aligned again */ - } - - w += skipleft; - x -= skipleft; - mem = (CARD32*)xalloc(((w + 31) >> 3) * sizeof(char)); - if (!mem) return; - - (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( - pScrn, x, y, w, h, skipleft); - - bufferNo = 0; - - while(h--) { - base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; - (*GlyphFunc)(mem, glyphs, startline++, w, glyphWidth); - DrawTextScanline3(base, mem, w); - (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); - if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) - bufferNo = 0; - } - - xfree(mem); - -THE_END: - - SET_SYNC_FLAG(infoRec); -} - -#endif - - - -/******************************************************************** - - TRIPLE_BITS_24BPP scanline rendering code. - -********************************************************************/ - - - -static CARD32* -DrawTextScanline3( - CARD32 *base, - CARD32 *mem, - int width ) -{ - - while(width > 32) { - WRITE_BITS3(*mem); - mem++; - width -= 32; - } - if(width) { - if (width >= 22) { - WRITE_BITS3(*mem); - } else if (width >= 11) { - WRITE_BITS2(*mem); - } else { - WRITE_BITS1(*mem); - } - } - - return base; -} - - -/******************************************************************** - - Generic TE scanline rendering code. - -********************************************************************/ - - - -static CARD32* -DrawTETextScanlineGeneric( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - CARD32 bits = (*glyphp)[line]; - int shift = glyphwidth; - - while(width > 32) { - while(shift < 32) { - glyphp++; - bits |= SHIFT_L((*glyphp)[line], shift); - shift += glyphwidth; - } - WRITE_BITS(bits); - shift &= 31; - if(shift) - bits = SHIFT_R((*glyphp)[line],(glyphwidth - shift)); - else bits = 0; - width -= 32; - } - - if(width) { - width -= shift; - while(width > 0) { - glyphp++; - bits |= SHIFT_L((*glyphp)[line],shift); - shift += glyphwidth; - width -= glyphwidth; - } - WRITE_BITS(bits); - } - - return base; -} - - -/******************************************************************** - - Loop unrolled TE font scanline rendering code - -********************************************************************/ - - -#ifndef USEASSEMBLER -static CARD32* -DrawTETextScanlineWidth6( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],6); - bits |= SHIFT_L(glyphp[2][line],12); - bits |= SHIFT_L(glyphp[3][line],18); - bits |= SHIFT_L(glyphp[4][line],24); - bits |= SHIFT_L(glyphp[5][line],30); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = SHIFT_R(glyphp[5][line],2); - bits |= SHIFT_L(glyphp[6][line],4); - bits |= SHIFT_L(glyphp[7][line],10); - bits |= SHIFT_L(glyphp[8][line],16); - bits |= SHIFT_L(glyphp[9][line],22); - bits |= SHIFT_L(glyphp[10][line],28); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = SHIFT_R(glyphp[10][line],4); - bits |= SHIFT_L(glyphp[11][line],2); - bits |= SHIFT_L(glyphp[12][line],8); - bits |= SHIFT_L(glyphp[13][line],14); - bits |= SHIFT_L(glyphp[14][line],20); - bits |= SHIFT_L(glyphp[15][line],26); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); -#ifndef FIXEDBASE - base += 3; -#endif - width -= 96; - glyphp += 16; - } - return base; -} -#endif - -static CARD32* -DrawTETextScanlineWidth7( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],7); - bits |= SHIFT_L(glyphp[2][line],14); - bits |= SHIFT_L(glyphp[3][line],21); - bits |= SHIFT_L(glyphp[4][line],28); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = SHIFT_R(glyphp[4][line],4); - bits |= SHIFT_L(glyphp[5][line],3); - bits |= SHIFT_L(glyphp[6][line],10); - bits |= SHIFT_L(glyphp[7][line],17); - bits |= SHIFT_L(glyphp[8][line],24); - bits |= SHIFT_L(glyphp[9][line],31); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = SHIFT_R(glyphp[9][line],1); - bits |= SHIFT_L(glyphp[10][line],6); - bits |= SHIFT_L(glyphp[11][line],13); - bits |= SHIFT_L(glyphp[12][line],20); - bits |= SHIFT_L(glyphp[13][line],27); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); - bits = SHIFT_R(glyphp[13][line],5); - bits |= SHIFT_L(glyphp[14][line],2); - bits |= SHIFT_L(glyphp[15][line],9); - bits |= SHIFT_L(glyphp[16][line],16); - bits |= SHIFT_L(glyphp[17][line],23); - bits |= SHIFT_L(glyphp[18][line],30); - WRITE_IN_BITORDER(base, 3, bits); - CHECKRETURN(4); - bits = SHIFT_R(glyphp[18][line],2); - bits |= SHIFT_L(glyphp[19][line],5); - bits |= SHIFT_L(glyphp[20][line],12); - bits |= SHIFT_L(glyphp[21][line],19); - bits |= SHIFT_L(glyphp[22][line],26); - WRITE_IN_BITORDER(base, 4, bits); - CHECKRETURN(5); - bits = SHIFT_R(glyphp[22][line],6); - bits |= SHIFT_L(glyphp[23][line],1); - bits |= SHIFT_L(glyphp[24][line],8); - bits |= SHIFT_L(glyphp[25][line],15); - bits |= SHIFT_L(glyphp[26][line],22); - bits |= SHIFT_L(glyphp[27][line],29); - WRITE_IN_BITORDER(base, 5, bits); - CHECKRETURN(6); - bits = SHIFT_R(glyphp[27][line],3); - bits |= SHIFT_L(glyphp[28][line],4); - bits |= SHIFT_L(glyphp[29][line],11); - bits |= SHIFT_L(glyphp[30][line],18); - bits |= SHIFT_L(glyphp[31][line],25); - WRITE_IN_BITORDER(base, 6, bits); - CHECKRETURN(7); -#ifndef FIXEDBASE - base += 7; -#endif - width -= 224; - glyphp += 32; - } - return base; -} - - -#ifndef USEASSEMBLER -static CARD32* -DrawTETextScanlineWidth8( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],8); - bits |= SHIFT_L(glyphp[2][line],16); - bits |= SHIFT_L(glyphp[3][line],24); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = glyphp[4][line]; - bits |= SHIFT_L(glyphp[5][line],8); - bits |= SHIFT_L(glyphp[6][line],16); - bits |= SHIFT_L(glyphp[7][line],24); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); -#ifndef FIXEDBASE - base += 2; -#endif - width -= 64; - glyphp += 8; - } - return base; -} -#endif - -#ifndef USEASSEMBLER -static CARD32* -DrawTETextScanlineWidth9( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],9); - bits |= SHIFT_L(glyphp[2][line],18); - bits |= SHIFT_L(glyphp[3][line],27); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = SHIFT_R(glyphp[3][line],5); - bits |= SHIFT_L(glyphp[4][line],4); - bits |= SHIFT_L(glyphp[5][line],13); - bits |= SHIFT_L(glyphp[6][line],22); - bits |= SHIFT_L(glyphp[7][line],31); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = SHIFT_R(glyphp[7][line],1); - bits |= SHIFT_L(glyphp[8][line],8); - bits |= SHIFT_L(glyphp[9][line],17); - bits |= SHIFT_L(glyphp[10][line],26); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); - bits = SHIFT_R(glyphp[10][line],6); - bits |= SHIFT_L(glyphp[11][line],3); - bits |= SHIFT_L(glyphp[12][line],12); - bits |= SHIFT_L(glyphp[13][line],21); - bits |= SHIFT_L(glyphp[14][line],30); - WRITE_IN_BITORDER(base, 3, bits); - CHECKRETURN(4); - bits = SHIFT_R(glyphp[14][line],2); - bits |= SHIFT_L(glyphp[15][line],7); - bits |= SHIFT_L(glyphp[16][line],16); - bits |= SHIFT_L(glyphp[17][line],25); - WRITE_IN_BITORDER(base, 4, bits); - CHECKRETURN(5); - bits = SHIFT_R(glyphp[17][line],7); - bits |= SHIFT_L(glyphp[18][line],2); - bits |= SHIFT_L(glyphp[19][line],11); - bits |= SHIFT_L(glyphp[20][line],20); - bits |= SHIFT_L(glyphp[21][line],29); - WRITE_IN_BITORDER(base, 5, bits); - CHECKRETURN(6); - bits = SHIFT_R(glyphp[21][line],3); - bits |= SHIFT_L(glyphp[22][line],6); - bits |= SHIFT_L(glyphp[23][line],15); - bits |= SHIFT_L(glyphp[24][line],24); - WRITE_IN_BITORDER(base, 6, bits); - CHECKRETURN(7); - bits = SHIFT_R(glyphp[24][line],8); - bits |= SHIFT_L(glyphp[25][line],1); - bits |= SHIFT_L(glyphp[26][line],10); - bits |= SHIFT_L(glyphp[27][line],19); - bits |= SHIFT_L(glyphp[28][line],28); - WRITE_IN_BITORDER(base, 7, bits); - CHECKRETURN(8); - bits = SHIFT_R(glyphp[28][line],4); - bits |= SHIFT_L(glyphp[29][line],5); - bits |= SHIFT_L(glyphp[30][line],14); - bits |= SHIFT_L(glyphp[31][line],23); - WRITE_IN_BITORDER(base, 8, bits); - CHECKRETURN(9); -#ifndef FIXEDBASE - base += 9; -#endif - width -= 288; - glyphp += 32; - } - return base; -} -#endif - -static CARD32* -DrawTETextScanlineWidth10( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],10); - bits |= SHIFT_L(glyphp[2][line],20); - bits |= SHIFT_L(glyphp[3][line],30); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = SHIFT_R(glyphp[3][line],2); - bits |= SHIFT_L(glyphp[4][line],8); - bits |= SHIFT_L(glyphp[5][line],18); - bits |= SHIFT_L(glyphp[6][line],28); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = SHIFT_R(glyphp[6][line],4); - bits |= SHIFT_L(glyphp[7][line],6); - bits |= SHIFT_L(glyphp[8][line],16); - bits |= SHIFT_L(glyphp[9][line],26); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); - bits = SHIFT_R(glyphp[9][line],6); - bits |= SHIFT_L(glyphp[10][line],4); - bits |= SHIFT_L(glyphp[11][line],14); - bits |= SHIFT_L(glyphp[12][line],24); - WRITE_IN_BITORDER(base, 3, bits); - CHECKRETURN(4); - bits = SHIFT_R(glyphp[12][line],8); - bits |= SHIFT_L(glyphp[13][line],2); - bits |= SHIFT_L(glyphp[14][line],12); - bits |= SHIFT_L(glyphp[15][line],22); - WRITE_IN_BITORDER(base, 4, bits); - CHECKRETURN(5); -#ifndef FIXEDBASE - base += 5; -#endif - width -= 160; - glyphp += 16; - } - return base; -} - -static CARD32* -DrawTETextScanlineWidth12( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],12); - bits |= SHIFT_L(glyphp[2][line],24); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = SHIFT_R(glyphp[2][line],8); - bits |= SHIFT_L(glyphp[3][line],4); - bits |= SHIFT_L(glyphp[4][line],16); - bits |= SHIFT_L(glyphp[5][line],28); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = SHIFT_R(glyphp[5][line],4); - bits |= SHIFT_L(glyphp[6][line],8); - bits |= SHIFT_L(glyphp[7][line],20); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); -#ifndef FIXEDBASE - base += 3; -#endif - width -= 96; - glyphp += 8; - } - return base; -} - - - -static CARD32* -DrawTETextScanlineWidth14( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],14); - bits |= SHIFT_L(glyphp[2][line],28); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = SHIFT_R(glyphp[2][line],4); - bits |= SHIFT_L(glyphp[3][line],10); - bits |= SHIFT_L(glyphp[4][line],24); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = SHIFT_R(glyphp[4][line],8); - bits |= SHIFT_L(glyphp[5][line],6); - bits |= SHIFT_L(glyphp[6][line],20); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); - bits = SHIFT_R(glyphp[6][line],12); - bits |= SHIFT_L(glyphp[7][line],2); - bits |= SHIFT_L(glyphp[8][line],16); - bits |= SHIFT_L(glyphp[9][line],30); - WRITE_IN_BITORDER(base, 3, bits); - CHECKRETURN(4); - bits = SHIFT_R(glyphp[9][line],2); - bits |= SHIFT_L(glyphp[10][line],12); - bits |= SHIFT_L(glyphp[11][line],26); - WRITE_IN_BITORDER(base, 4, bits); - CHECKRETURN(5); - bits = SHIFT_R(glyphp[11][line],6); - bits |= SHIFT_L(glyphp[12][line],8); - bits |= SHIFT_L(glyphp[13][line],22); - WRITE_IN_BITORDER(base, 5, bits); - CHECKRETURN(6); - bits = SHIFT_R(glyphp[13][line],10); - bits |= SHIFT_L(glyphp[14][line],4); - bits |= SHIFT_L(glyphp[15][line],18); - WRITE_IN_BITORDER(base, 6, bits); - CHECKRETURN(7); -#ifndef FIXEDBASE - base += 7; -#endif - width -= 224; - glyphp += 16; - } - return base; -} - - -static CARD32* -DrawTETextScanlineWidth16( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],16); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = glyphp[2][line]; - bits |= SHIFT_L(glyphp[3][line],16); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = glyphp[4][line]; - bits |= SHIFT_L(glyphp[5][line],16); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); - bits = glyphp[6][line]; - bits |= SHIFT_L(glyphp[7][line],16); - WRITE_IN_BITORDER(base, 3, bits); - CHECKRETURN(4); -#ifndef FIXEDBASE - base += 4; -#endif - width -= 128; - glyphp += 8; - } - return base; -} - - - -static CARD32* -DrawTETextScanlineWidth18( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],18); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = SHIFT_R(glyphp[1][line],14); - bits |= SHIFT_L(glyphp[2][line],4); - bits |= SHIFT_L(glyphp[3][line],22); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = SHIFT_R(glyphp[3][line],10); - bits |= SHIFT_L(glyphp[4][line],8); - bits |= SHIFT_L(glyphp[5][line],26); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); - bits = SHIFT_R(glyphp[5][line],6); - bits |= SHIFT_L(glyphp[6][line],12); - bits |= SHIFT_L(glyphp[7][line],30); - WRITE_IN_BITORDER(base, 3, bits); - CHECKRETURN(4); - bits = SHIFT_R(glyphp[7][line],2); - bits |= SHIFT_L(glyphp[8][line],16); - WRITE_IN_BITORDER(base, 4, bits); - CHECKRETURN(5); - bits = SHIFT_R(glyphp[8][line],16); - bits |= SHIFT_L(glyphp[9][line],2); - bits |= SHIFT_L(glyphp[10][line],20); - WRITE_IN_BITORDER(base, 5, bits); - CHECKRETURN(6); - bits = SHIFT_R(glyphp[10][line],12); - bits |= SHIFT_L(glyphp[11][line],6); - bits |= SHIFT_L(glyphp[12][line],24); - WRITE_IN_BITORDER(base, 6, bits); - CHECKRETURN(7); - bits = SHIFT_R(glyphp[12][line],8); - bits |= SHIFT_L(glyphp[13][line],10); - bits |= SHIFT_L(glyphp[14][line],28); - WRITE_IN_BITORDER(base, 7, bits); - CHECKRETURN(8); - bits = SHIFT_R(glyphp[14][line],4); - bits |= SHIFT_L(glyphp[15][line],14); - WRITE_IN_BITORDER(base, 8, bits); - CHECKRETURN(9); -#ifndef FIXEDBASE - base += 9; -#endif - width -= 288; - glyphp += 16; - } - return base; -} - - -static CARD32* -DrawTETextScanlineWidth24( - CARD32 *base, - unsigned int **glyphp, - int line, int width, int glyphwidth ) -{ - while (1) { - unsigned int bits; - bits = glyphp[0][line]; - bits |= SHIFT_L(glyphp[1][line],24); - WRITE_IN_BITORDER(base, 0, bits); - CHECKRETURN(1); - bits = SHIFT_R(glyphp[1][line],8); - bits |= SHIFT_L(glyphp[2][line],16); - WRITE_IN_BITORDER(base, 1, bits); - CHECKRETURN(2); - bits = SHIFT_R(glyphp[2][line],16); - bits |= SHIFT_L(glyphp[3][line],8); - WRITE_IN_BITORDER(base, 2, bits); - CHECKRETURN(3); -#ifndef FIXEDBASE - base += 3; -#endif - width -= 96; - glyphp += 4; - } - return base; -} - - + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "xaa.h" +#include "xaalocal.h" +#include "xaacexp.h" +#include "xf86.h" + +/* scanline function for TRIPLE_BITS_24BPP */ +static CARD32 *DrawTextScanline3(CARD32 *base, CARD32 *mem, int width); + +/* Loop unrolled functions for common font widths */ +static CARD32 *DrawTETextScanlineGeneric(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth7(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth10(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth12(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth14(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth16(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth18(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth24(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); + + +#ifdef USEASSEMBLER +# ifdef FIXEDBASE +# ifdef MSBFIRST +CARD32 *DrawTETextScanlineWidth6PMSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth8PMSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth9PMSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, int line, int width, int glyphwidth); +# else +CARD32 *DrawTETextScanlineWidth6PLSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth8PLSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth9PLSBFirstFixedBase(CARD32 *base, + unsigned int **glyphp, int line, int width, int glyphwidth); +# endif +# else +# ifdef MSBFIRST +CARD32 *DrawTETextScanlineWidth6PMSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth8PMSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth9PMSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +# else +CARD32 *DrawTETextScanlineWidth6PLSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth8PLSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +CARD32 *DrawTETextScanlineWidth9PLSBFirst(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +# endif +# endif +#else +static CARD32 *DrawTETextScanlineWidth6(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth8(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +static CARD32 *DrawTETextScanlineWidth9(CARD32 *base, unsigned int **glyphp, + int line, int width, int glyphwidth); +#endif + +#define glyph_scanline_func EXPNAME(XAAGlyphScanlineFunc) +#define glyph_get_scanline_func EXPNAME(XAAGetGlyphScanlineFunc) + + +GlyphScanlineFuncPtr glyph_scanline_func[32] = { + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, +#ifdef USEASSEMBLER +# ifdef FIXEDBASE +# ifdef MSBFIRST + DrawTETextScanlineWidth6PMSBFirstFixedBase, + DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8PMSBFirstFixedBase, + DrawTETextScanlineWidth9PMSBFirstFixedBase, +# else + DrawTETextScanlineWidth6PLSBFirstFixedBase, + DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8PLSBFirstFixedBase, + DrawTETextScanlineWidth9PLSBFirstFixedBase, +# endif +# else +# ifdef MSBFIRST + DrawTETextScanlineWidth6PMSBFirst, + DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8PMSBFirst, + DrawTETextScanlineWidth9PMSBFirst, +# else + DrawTETextScanlineWidth6PLSBFirst, + DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8PLSBFirst, + DrawTETextScanlineWidth9PLSBFirst, +# endif +# endif +#else + DrawTETextScanlineWidth6, DrawTETextScanlineWidth7, + DrawTETextScanlineWidth8, DrawTETextScanlineWidth9, +#endif + DrawTETextScanlineWidth10, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth12, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth14, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth16, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth18, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineWidth24, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric, + DrawTETextScanlineGeneric, DrawTETextScanlineGeneric +}; + +GlyphScanlineFuncPtr *glyph_get_scanline_func(void) { + return glyph_scanline_func; +} + + +/******************************************************************** + + Here we have TEGlyphRenders for a bunch of different color + expansion types. The driver may provide its own renderer, but + this is the default one which renders using lower-level primitives + exported by the chipset driver. + +********************************************************************/ + +/* This gets built for MSBFIRST or LSBFIRST with FIXEDBASE or not. + A total of 4 versions */ + +void +EXPNAME(XAATEGlyphRenderer)( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32* base; + GlyphScanlineFuncPtr GlyphFunc = glyph_scanline_func[glyphWidth - 1]; + int dwords = 0; + + if((bg != -1) && (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + bg = -1; + } + + (*infoRec->SetupForCPUToScreenColorExpandFill)( + pScrn, fg, bg, rop, planemask); + + if(skipleft && + (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING) || + (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && + (skipleft > x)))) { + /* draw the first character only */ + + int count = h, line = startline; + int width = glyphWidth - skipleft; + + if(width > w) width = w; + + (*infoRec->SubsequentCPUToScreenColorExpandFill)( + pScrn, x, y, width, h, 0); + + base = (CARD32*)infoRec->ColorExpandBase; + + while(count--) { + register CARD32 tmp = SHIFT_R(glyphs[0][line++],skipleft); + WRITE_BITS(tmp); + } + + w -= width; + if((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && + ((((width + 31) >> 5) * h) & 1)) { + base = (CARD32*)infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + if(!w) goto THE_END; + glyphs++; + x += width; + skipleft = 0; /* nicely aligned again */ + } + + w += skipleft; + x -= skipleft; + dwords = ((w + 31) >> 5) * h; + + (*infoRec->SubsequentCPUToScreenColorExpandFill)( + pScrn, x, y, w, h, skipleft); + + base = (CARD32*)infoRec->ColorExpandBase; + +#ifndef FIXEDBASE + if((((w + 31) >> 5) * h) <= infoRec->ColorExpandRange) + while(h--) { + base = (*GlyphFunc)(base, glyphs, startline++, w, glyphWidth); + } + else +#endif + while(h--) { + (*GlyphFunc)(base, glyphs, startline++, w, glyphWidth); + } + + if((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && + (dwords & 1)) { + base = (CARD32*)infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + +THE_END: + + if(infoRec->TEGlyphRendererFlags & SYNC_AFTER_COLOR_EXPAND) + (*infoRec->Sync)(pScrn); + else SET_SYNC_FLAG(infoRec); +} + +/******************************************************************** + + This is the GlyphRenderer for TRIPLE_BITS_24BPP. It renders to a buffer + with the non FIXEDBASE LSB_FIRST code before tripling, and possibly + reversing the bits and sending them to the screen + +********************************************************************/ + +void +EXPNAME(XAATEGlyphRenderer3)( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + CARD32 *base, *mem; + GlyphScanlineFuncPtr GlyphFunc = XAAGlyphScanlineFuncLSBFirst[glyphWidth - 1]; + int dwords = 0; + + if((bg != -1) && + ((infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY) || + ((infoRec->TEGlyphRendererFlags & RGB_EQUAL) && + (!CHECK_RGB_EQUAL(bg))))) { + (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + bg = -1; + } + + (*infoRec->SetupForCPUToScreenColorExpandFill)( + pScrn, fg, bg, rop, planemask); + + if(skipleft) { + /* draw the first character only */ + + int count = h, line = startline; + int width = glyphWidth - skipleft; + CARD32 bits; + + if(width > w) width = w; + (*infoRec->SubsequentCPUToScreenColorExpandFill)( + pScrn, x, y, width, h, 0); + + base = (CARD32*)infoRec->ColorExpandBase; + + while(count--) { + bits = SHIFT_R(glyphs[0][line++],skipleft); + if (width >= 22) { + WRITE_BITS3(bits); + } else if (width >= 11) { + WRITE_BITS2(bits); + } else { + WRITE_BITS1(bits); + } + } + + w -= width; + if((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && + ((((3 * width + 31) >> 5) * h) & 1)) { + base = (CARD32*)infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + if(!w) goto THE_END; + glyphs++; + x += width; + skipleft = 0; /* nicely aligned again */ + } + + dwords = ((3 * w + 31) >> 5) * h; + mem = (CARD32*)malloc(((w + 31) >> 3) * sizeof(char)); + if (!mem) return; + + (*infoRec->SubsequentCPUToScreenColorExpandFill)(pScrn, x, y, w, h, 0); + + base = (CARD32*)infoRec->ColorExpandBase; + +# ifndef FIXEDBASE + if((((3 * w + 31) >> 5) * h) <= infoRec->ColorExpandRange) + while(h--) { + (*GlyphFunc)(mem, glyphs, startline++, w, glyphWidth); + base = DrawTextScanline3(base, mem, w); + } + else +# endif + while(h--) { + (*GlyphFunc)(mem, glyphs, startline++, w, glyphWidth); + DrawTextScanline3(base, mem, w); + } + + free(mem); + + if((infoRec->TEGlyphRendererFlags & CPU_TRANSFER_PAD_QWORD) && + (dwords & 1)) { + base = (CARD32*)infoRec->ColorExpandBase; + base[0] = 0x00000000; + } + +THE_END: + + if(infoRec->TEGlyphRendererFlags & SYNC_AFTER_COLOR_EXPAND) + (*infoRec->Sync)(pScrn); + else SET_SYNC_FLAG(infoRec); +} + + +#ifndef FIXEDBASE +/* Scanline version of above gets built for LSBFIRST and MSBFIRST */ + +void +EXPNAME(XAATEGlyphRendererScanline)( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int bufferNo; + CARD32* base; + GlyphScanlineFuncPtr GlyphFunc = glyph_scanline_func[glyphWidth - 1]; + + if((bg != -1) && (infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY)) { + (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + bg = -1; + } + + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill)( + pScrn, fg, bg, rop, planemask); + + if(skipleft && + (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING) || + (!(infoRec->TEGlyphRendererFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) && + (skipleft > x)))) { + /* draw the first character only */ + + int count = h, line = startline; + int width = glyphWidth - skipleft; + + if(width > w) width = w; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( + pScrn, x, y, width, h, 0); + + bufferNo = 0; + + while(count--) { + register CARD32 tmp = SHIFT_R(glyphs[0][line++],skipleft); + base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; + WRITE_BITS(tmp); + (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); + if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + w -= width; + if(!w) goto THE_END; + glyphs++; + x += width; + skipleft = 0; /* nicely aligned again */ + } + + w += skipleft; + x -= skipleft; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( + pScrn, x, y, w, h, skipleft); + + bufferNo = 0; + + while(h--) { + base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; + (*GlyphFunc)(base, glyphs, startline++, w, glyphWidth); + (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); + if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + +THE_END: + + SET_SYNC_FLAG(infoRec); +} + +void +EXPNAME(XAATEGlyphRendererScanline3)( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int bufferNo; + CARD32 *base, *mem; + GlyphScanlineFuncPtr GlyphFunc = XAAGlyphScanlineFuncLSBFirst[glyphWidth - 1]; + + if((bg != -1) && + ((infoRec->TEGlyphRendererFlags & TRANSPARENCY_ONLY) || + ((infoRec->TEGlyphRendererFlags & RGB_EQUAL) && + (!CHECK_RGB_EQUAL(bg))))) { + (*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask); + (*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + bg = -1; + } + + (*infoRec->SetupForScanlineCPUToScreenColorExpandFill)( + pScrn, fg, bg, rop, planemask); + + if(skipleft) { + /* draw the first character only */ + + int count = h, line = startline; + int width = glyphWidth - skipleft; + CARD32 bits; + + if(width > w) width = w; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( + pScrn, x, y, width, h, 0); + + bufferNo = 0; + + while(count--) { + base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; + bits = SHIFT_R(glyphs[0][line++],skipleft); + if (width >= 22) { + WRITE_BITS3(bits); + } else if (width >= 11) { + WRITE_BITS2(bits); + } else { + WRITE_BITS1(bits); + } + (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); + if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + w -= width; + if(!w) goto THE_END; + glyphs++; + x += width; + skipleft = 0; /* nicely aligned again */ + } + + w += skipleft; + x -= skipleft; + mem = (CARD32*)malloc(((w + 31) >> 3) * sizeof(char)); + if (!mem) return; + + (*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)( + pScrn, x, y, w, h, skipleft); + + bufferNo = 0; + + while(h--) { + base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo]; + (*GlyphFunc)(mem, glyphs, startline++, w, glyphWidth); + DrawTextScanline3(base, mem, w); + (*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++); + if(bufferNo >= infoRec->NumScanlineColorExpandBuffers) + bufferNo = 0; + } + + free(mem); + +THE_END: + + SET_SYNC_FLAG(infoRec); +} + +#endif + + + +/******************************************************************** + + TRIPLE_BITS_24BPP scanline rendering code. + +********************************************************************/ + + + +static CARD32* +DrawTextScanline3( + CARD32 *base, + CARD32 *mem, + int width ) +{ + + while(width > 32) { + WRITE_BITS3(*mem); + mem++; + width -= 32; + } + if(width) { + if (width >= 22) { + WRITE_BITS3(*mem); + } else if (width >= 11) { + WRITE_BITS2(*mem); + } else { + WRITE_BITS1(*mem); + } + } + + return base; +} + + +/******************************************************************** + + Generic TE scanline rendering code. + +********************************************************************/ + + + +static CARD32* +DrawTETextScanlineGeneric( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + CARD32 bits = (*glyphp)[line]; + int shift = glyphwidth; + + while(width > 32) { + while(shift < 32) { + glyphp++; + bits |= SHIFT_L((*glyphp)[line], shift); + shift += glyphwidth; + } + WRITE_BITS(bits); + shift &= 31; + if(shift) + bits = SHIFT_R((*glyphp)[line],(glyphwidth - shift)); + else bits = 0; + width -= 32; + } + + if(width) { + width -= shift; + while(width > 0) { + glyphp++; + bits |= SHIFT_L((*glyphp)[line],shift); + shift += glyphwidth; + width -= glyphwidth; + } + WRITE_BITS(bits); + } + + return base; +} + + +/******************************************************************** + + Loop unrolled TE font scanline rendering code + +********************************************************************/ + + +#ifndef USEASSEMBLER +static CARD32* +DrawTETextScanlineWidth6( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],6); + bits |= SHIFT_L(glyphp[2][line],12); + bits |= SHIFT_L(glyphp[3][line],18); + bits |= SHIFT_L(glyphp[4][line],24); + bits |= SHIFT_L(glyphp[5][line],30); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[5][line],2); + bits |= SHIFT_L(glyphp[6][line],4); + bits |= SHIFT_L(glyphp[7][line],10); + bits |= SHIFT_L(glyphp[8][line],16); + bits |= SHIFT_L(glyphp[9][line],22); + bits |= SHIFT_L(glyphp[10][line],28); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[10][line],4); + bits |= SHIFT_L(glyphp[11][line],2); + bits |= SHIFT_L(glyphp[12][line],8); + bits |= SHIFT_L(glyphp[13][line],14); + bits |= SHIFT_L(glyphp[14][line],20); + bits |= SHIFT_L(glyphp[15][line],26); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); +#ifndef FIXEDBASE + base += 3; +#endif + width -= 96; + glyphp += 16; + } + return base; +} +#endif + +static CARD32* +DrawTETextScanlineWidth7( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],7); + bits |= SHIFT_L(glyphp[2][line],14); + bits |= SHIFT_L(glyphp[3][line],21); + bits |= SHIFT_L(glyphp[4][line],28); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[4][line],4); + bits |= SHIFT_L(glyphp[5][line],3); + bits |= SHIFT_L(glyphp[6][line],10); + bits |= SHIFT_L(glyphp[7][line],17); + bits |= SHIFT_L(glyphp[8][line],24); + bits |= SHIFT_L(glyphp[9][line],31); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[9][line],1); + bits |= SHIFT_L(glyphp[10][line],6); + bits |= SHIFT_L(glyphp[11][line],13); + bits |= SHIFT_L(glyphp[12][line],20); + bits |= SHIFT_L(glyphp[13][line],27); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[13][line],5); + bits |= SHIFT_L(glyphp[14][line],2); + bits |= SHIFT_L(glyphp[15][line],9); + bits |= SHIFT_L(glyphp[16][line],16); + bits |= SHIFT_L(glyphp[17][line],23); + bits |= SHIFT_L(glyphp[18][line],30); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[18][line],2); + bits |= SHIFT_L(glyphp[19][line],5); + bits |= SHIFT_L(glyphp[20][line],12); + bits |= SHIFT_L(glyphp[21][line],19); + bits |= SHIFT_L(glyphp[22][line],26); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); + bits = SHIFT_R(glyphp[22][line],6); + bits |= SHIFT_L(glyphp[23][line],1); + bits |= SHIFT_L(glyphp[24][line],8); + bits |= SHIFT_L(glyphp[25][line],15); + bits |= SHIFT_L(glyphp[26][line],22); + bits |= SHIFT_L(glyphp[27][line],29); + WRITE_IN_BITORDER(base, 5, bits); + CHECKRETURN(6); + bits = SHIFT_R(glyphp[27][line],3); + bits |= SHIFT_L(glyphp[28][line],4); + bits |= SHIFT_L(glyphp[29][line],11); + bits |= SHIFT_L(glyphp[30][line],18); + bits |= SHIFT_L(glyphp[31][line],25); + WRITE_IN_BITORDER(base, 6, bits); + CHECKRETURN(7); +#ifndef FIXEDBASE + base += 7; +#endif + width -= 224; + glyphp += 32; + } + return base; +} + + +#ifndef USEASSEMBLER +static CARD32* +DrawTETextScanlineWidth8( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],8); + bits |= SHIFT_L(glyphp[2][line],16); + bits |= SHIFT_L(glyphp[3][line],24); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = glyphp[4][line]; + bits |= SHIFT_L(glyphp[5][line],8); + bits |= SHIFT_L(glyphp[6][line],16); + bits |= SHIFT_L(glyphp[7][line],24); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); +#ifndef FIXEDBASE + base += 2; +#endif + width -= 64; + glyphp += 8; + } + return base; +} +#endif + +#ifndef USEASSEMBLER +static CARD32* +DrawTETextScanlineWidth9( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],9); + bits |= SHIFT_L(glyphp[2][line],18); + bits |= SHIFT_L(glyphp[3][line],27); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[3][line],5); + bits |= SHIFT_L(glyphp[4][line],4); + bits |= SHIFT_L(glyphp[5][line],13); + bits |= SHIFT_L(glyphp[6][line],22); + bits |= SHIFT_L(glyphp[7][line],31); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[7][line],1); + bits |= SHIFT_L(glyphp[8][line],8); + bits |= SHIFT_L(glyphp[9][line],17); + bits |= SHIFT_L(glyphp[10][line],26); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[10][line],6); + bits |= SHIFT_L(glyphp[11][line],3); + bits |= SHIFT_L(glyphp[12][line],12); + bits |= SHIFT_L(glyphp[13][line],21); + bits |= SHIFT_L(glyphp[14][line],30); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[14][line],2); + bits |= SHIFT_L(glyphp[15][line],7); + bits |= SHIFT_L(glyphp[16][line],16); + bits |= SHIFT_L(glyphp[17][line],25); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); + bits = SHIFT_R(glyphp[17][line],7); + bits |= SHIFT_L(glyphp[18][line],2); + bits |= SHIFT_L(glyphp[19][line],11); + bits |= SHIFT_L(glyphp[20][line],20); + bits |= SHIFT_L(glyphp[21][line],29); + WRITE_IN_BITORDER(base, 5, bits); + CHECKRETURN(6); + bits = SHIFT_R(glyphp[21][line],3); + bits |= SHIFT_L(glyphp[22][line],6); + bits |= SHIFT_L(glyphp[23][line],15); + bits |= SHIFT_L(glyphp[24][line],24); + WRITE_IN_BITORDER(base, 6, bits); + CHECKRETURN(7); + bits = SHIFT_R(glyphp[24][line],8); + bits |= SHIFT_L(glyphp[25][line],1); + bits |= SHIFT_L(glyphp[26][line],10); + bits |= SHIFT_L(glyphp[27][line],19); + bits |= SHIFT_L(glyphp[28][line],28); + WRITE_IN_BITORDER(base, 7, bits); + CHECKRETURN(8); + bits = SHIFT_R(glyphp[28][line],4); + bits |= SHIFT_L(glyphp[29][line],5); + bits |= SHIFT_L(glyphp[30][line],14); + bits |= SHIFT_L(glyphp[31][line],23); + WRITE_IN_BITORDER(base, 8, bits); + CHECKRETURN(9); +#ifndef FIXEDBASE + base += 9; +#endif + width -= 288; + glyphp += 32; + } + return base; +} +#endif + +static CARD32* +DrawTETextScanlineWidth10( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],10); + bits |= SHIFT_L(glyphp[2][line],20); + bits |= SHIFT_L(glyphp[3][line],30); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[3][line],2); + bits |= SHIFT_L(glyphp[4][line],8); + bits |= SHIFT_L(glyphp[5][line],18); + bits |= SHIFT_L(glyphp[6][line],28); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[6][line],4); + bits |= SHIFT_L(glyphp[7][line],6); + bits |= SHIFT_L(glyphp[8][line],16); + bits |= SHIFT_L(glyphp[9][line],26); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[9][line],6); + bits |= SHIFT_L(glyphp[10][line],4); + bits |= SHIFT_L(glyphp[11][line],14); + bits |= SHIFT_L(glyphp[12][line],24); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[12][line],8); + bits |= SHIFT_L(glyphp[13][line],2); + bits |= SHIFT_L(glyphp[14][line],12); + bits |= SHIFT_L(glyphp[15][line],22); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); +#ifndef FIXEDBASE + base += 5; +#endif + width -= 160; + glyphp += 16; + } + return base; +} + +static CARD32* +DrawTETextScanlineWidth12( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],12); + bits |= SHIFT_L(glyphp[2][line],24); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[2][line],8); + bits |= SHIFT_L(glyphp[3][line],4); + bits |= SHIFT_L(glyphp[4][line],16); + bits |= SHIFT_L(glyphp[5][line],28); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[5][line],4); + bits |= SHIFT_L(glyphp[6][line],8); + bits |= SHIFT_L(glyphp[7][line],20); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); +#ifndef FIXEDBASE + base += 3; +#endif + width -= 96; + glyphp += 8; + } + return base; +} + + + +static CARD32* +DrawTETextScanlineWidth14( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],14); + bits |= SHIFT_L(glyphp[2][line],28); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[2][line],4); + bits |= SHIFT_L(glyphp[3][line],10); + bits |= SHIFT_L(glyphp[4][line],24); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[4][line],8); + bits |= SHIFT_L(glyphp[5][line],6); + bits |= SHIFT_L(glyphp[6][line],20); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[6][line],12); + bits |= SHIFT_L(glyphp[7][line],2); + bits |= SHIFT_L(glyphp[8][line],16); + bits |= SHIFT_L(glyphp[9][line],30); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[9][line],2); + bits |= SHIFT_L(glyphp[10][line],12); + bits |= SHIFT_L(glyphp[11][line],26); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); + bits = SHIFT_R(glyphp[11][line],6); + bits |= SHIFT_L(glyphp[12][line],8); + bits |= SHIFT_L(glyphp[13][line],22); + WRITE_IN_BITORDER(base, 5, bits); + CHECKRETURN(6); + bits = SHIFT_R(glyphp[13][line],10); + bits |= SHIFT_L(glyphp[14][line],4); + bits |= SHIFT_L(glyphp[15][line],18); + WRITE_IN_BITORDER(base, 6, bits); + CHECKRETURN(7); +#ifndef FIXEDBASE + base += 7; +#endif + width -= 224; + glyphp += 16; + } + return base; +} + + +static CARD32* +DrawTETextScanlineWidth16( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],16); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = glyphp[2][line]; + bits |= SHIFT_L(glyphp[3][line],16); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = glyphp[4][line]; + bits |= SHIFT_L(glyphp[5][line],16); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = glyphp[6][line]; + bits |= SHIFT_L(glyphp[7][line],16); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); +#ifndef FIXEDBASE + base += 4; +#endif + width -= 128; + glyphp += 8; + } + return base; +} + + + +static CARD32* +DrawTETextScanlineWidth18( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],18); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[1][line],14); + bits |= SHIFT_L(glyphp[2][line],4); + bits |= SHIFT_L(glyphp[3][line],22); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[3][line],10); + bits |= SHIFT_L(glyphp[4][line],8); + bits |= SHIFT_L(glyphp[5][line],26); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); + bits = SHIFT_R(glyphp[5][line],6); + bits |= SHIFT_L(glyphp[6][line],12); + bits |= SHIFT_L(glyphp[7][line],30); + WRITE_IN_BITORDER(base, 3, bits); + CHECKRETURN(4); + bits = SHIFT_R(glyphp[7][line],2); + bits |= SHIFT_L(glyphp[8][line],16); + WRITE_IN_BITORDER(base, 4, bits); + CHECKRETURN(5); + bits = SHIFT_R(glyphp[8][line],16); + bits |= SHIFT_L(glyphp[9][line],2); + bits |= SHIFT_L(glyphp[10][line],20); + WRITE_IN_BITORDER(base, 5, bits); + CHECKRETURN(6); + bits = SHIFT_R(glyphp[10][line],12); + bits |= SHIFT_L(glyphp[11][line],6); + bits |= SHIFT_L(glyphp[12][line],24); + WRITE_IN_BITORDER(base, 6, bits); + CHECKRETURN(7); + bits = SHIFT_R(glyphp[12][line],8); + bits |= SHIFT_L(glyphp[13][line],10); + bits |= SHIFT_L(glyphp[14][line],28); + WRITE_IN_BITORDER(base, 7, bits); + CHECKRETURN(8); + bits = SHIFT_R(glyphp[14][line],4); + bits |= SHIFT_L(glyphp[15][line],14); + WRITE_IN_BITORDER(base, 8, bits); + CHECKRETURN(9); +#ifndef FIXEDBASE + base += 9; +#endif + width -= 288; + glyphp += 16; + } + return base; +} + + +static CARD32* +DrawTETextScanlineWidth24( + CARD32 *base, + unsigned int **glyphp, + int line, int width, int glyphwidth ) +{ + while (1) { + unsigned int bits; + bits = glyphp[0][line]; + bits |= SHIFT_L(glyphp[1][line],24); + WRITE_IN_BITORDER(base, 0, bits); + CHECKRETURN(1); + bits = SHIFT_R(glyphp[1][line],8); + bits |= SHIFT_L(glyphp[2][line],16); + WRITE_IN_BITORDER(base, 1, bits); + CHECKRETURN(2); + bits = SHIFT_R(glyphp[2][line],16); + bits |= SHIFT_L(glyphp[3][line],8); + WRITE_IN_BITORDER(base, 2, bits); + CHECKRETURN(3); +#ifndef FIXEDBASE + base += 3; +#endif + width -= 96; + glyphp += 4; + } + return base; +} + + diff --git a/xorg-server/hw/xfree86/xaa/xaaTEText.c b/xorg-server/hw/xfree86/xaa/xaaTEText.c index fc445726f..1e28d3103 100644 --- a/xorg-server/hw/xfree86/xaa/xaaTEText.c +++ b/xorg-server/hw/xfree86/xaa/xaaTEText.c @@ -1,312 +1,312 @@ - -/******************************************************************** - - In this file we have GC level replacements for PolyText8/16, - ImageText8/16, ImageGlyphBlt and PolyGlyphBlt for TE (fixed) fonts. - The idea is that everything in this file is device independent. - The mentioned GCOps are merely wrappers for XAAGlyphBltTEColorExpansion - which calculates the boxes containing arbitrarily clipped text - and passes them to the TEGlyphRenderer which will usually be a lower - level XAA function which renders these clipped glyphs using - the basic color expansion functions exported by the chipset driver. - The TEGlyphRenderer itself may optionally be driver supplied to - facilitate work-arounds/optimizations at a higher level than usual. - - v1.0 - Mark Vojkovich (mvojkovi@ucsd.edu) - - -********************************************************************/ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include -#include -#include "scrnintstr.h" -#include "dixfontstr.h" -#include "xf86str.h" -#include "xaa.h" -#include "xaalocal.h" -#include "gcstruct.h" -#include "pixmapstr.h" - - -static void XAAGlyphBltTEColorExpansion(ScrnInfoPtr pScrn, int xInit, - int yInit, FontPtr font, int fg, int bg, int rop, - unsigned int planemask, RegionPtr cclip, int nglyph, - unsigned char* gBase, CharInfoPtr *ppci); - - -/******************************************************************** - - GC level replacements for PolyText8/16 and ImageText8/16 - for TE fonts when using color expansion. - -********************************************************************/ - - -int -XAAPolyText8TEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - unsigned long n; - - (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count, - (unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo); - - /* we have divorced XAAGlyphBltTEColorExpansion from the drawable */ - if(n) XAAGlyphBltTEColorExpansion( - infoRec->pScrn, x + pDraw->x, y + pDraw->y, - pGC->font, pGC->fgPixel, -1, pGC->alu, pGC->planemask, - pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); - - return (x + (n * FONTMAXBOUNDS(pGC->font, characterWidth))); -} - - -int -XAAPolyText16TEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - unsigned long n; - - (*pGC->font->get_glyphs)( - pGC->font, (unsigned long)count, (unsigned char *)chars, - (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, - &n, infoRec->CharInfo); - - if(n) XAAGlyphBltTEColorExpansion( - infoRec->pScrn, x + pDraw->x, y + pDraw->y, - pGC->font, pGC->fgPixel, -1, pGC->alu, pGC->planemask, - pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); - - return (x + (n * FONTMAXBOUNDS(pGC->font, characterWidth))); -} - - -void -XAAImageText8TEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - unsigned long n; - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count, - (unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo); - - if(n) XAAGlyphBltTEColorExpansion( - infoRec->pScrn, x + pDraw->x, y + pDraw->y, - pGC->font, pGC->fgPixel, pGC->bgPixel, GXcopy, pGC->planemask, - pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); -} - - -void -XAAImageText16TEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - unsigned long n; - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - (*pGC->font->get_glyphs)( - pGC->font, (unsigned long)count, (unsigned char *)chars, - (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, - &n, infoRec->CharInfo); - - if(n) XAAGlyphBltTEColorExpansion( - infoRec->pScrn, x + pDraw->x, y + pDraw->y, - pGC->font, pGC->fgPixel, pGC->bgPixel, GXcopy, pGC->planemask, - pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); -} - - - -/******************************************************************** - - GC level replacements for ImageGlyphBlt and PolyGlyphBlt for - TE fonts when using color expansion. - -********************************************************************/ - - -void -XAAImageGlyphBltTEColorExpansion( - DrawablePtr pDrawable, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - XAAGlyphBltTEColorExpansion( - infoRec->pScrn, xInit + pDrawable->x, yInit + pDrawable->y, - pGC->font, pGC->fgPixel, pGC->bgPixel, GXcopy, pGC->planemask, - pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci); -} - -void -XAAPolyGlyphBltTEColorExpansion( - DrawablePtr pDrawable, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); - - if(!REGION_NUM_RECTS(pGC->pCompositeClip)) - return; - - XAAGlyphBltTEColorExpansion( - infoRec->pScrn, xInit + pDrawable->x, yInit + pDrawable->y, - pGC->font, pGC->fgPixel, -1, pGC->alu, pGC->planemask, - pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci); -} - - - - -/******************************************************************** - - XAAGlyphBltTEColorExpansion - - - This guy computes the clipped pieces of text and sends it to - the lower-level function which will handle acceleration of - arbitrarily clipped text. - -********************************************************************/ - - -static void -XAAGlyphBltTEColorExpansion( - ScrnInfoPtr pScrn, - int xInit, int yInit, - FontPtr font, - int fg, int bg, - int rop, - unsigned int planemask, - RegionPtr cclip, - int nglyph, - unsigned char* gBase, - CharInfoPtr *ppci ) -{ - XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); - int skippix, skipglyphs; - int Left, Right, Top, Bottom; - int LeftEdge, RightEdge, ytop, ybot; - int nbox = REGION_NUM_RECTS(cclip); - BoxPtr pbox = REGION_RECTS(cclip); - unsigned int **glyphs = NULL; - int glyphWidth = FONTMAXBOUNDS(font, characterWidth); - - /* find the size of the box */ - Left = xInit; - Right = Left + (glyphWidth * nglyph); - Top = yInit - FONTASCENT(font); - Bottom = yInit + FONTDESCENT(font); - - /* get into the first band that may contain part of our string */ - while(nbox && (Top >= pbox->y2)) { - pbox++; nbox--; - } - - /* stop when the lower edge of the box is beyond our string */ - while(nbox && (Bottom > pbox->y1)) { - LeftEdge = max(Left, pbox->x1); - RightEdge = min(Right, pbox->x2); - - if(RightEdge > LeftEdge) { /* we have something to draw */ - unsigned int *fallbackBits = NULL; - ytop = max(Top, pbox->y1); - ybot = min(Bottom, pbox->y2); - - if((skippix = LeftEdge - Left)) { - skipglyphs = skippix/glyphWidth; - skippix %= glyphWidth; - } else skipglyphs = 0; - - if(!glyphs) { - int count; - glyphs = (unsigned int**)(infoRec->PreAllocMem); - - for(count = 0; count < nglyph; count++) { - glyphs[count] = (unsigned int*) - FONTGLYPHBITS(gBase,*ppci++); - if (!glyphs[count]) { - /* Glyphs with NULL bits do exist in the wild. - Replace with blank bits in that case */ - - if (!fallbackBits) { - int fontHeight = Bottom - Top + 1; - fallbackBits = xcalloc (glyphWidth * fontHeight, 1); - if (!fallbackBits) - return; - } - glyphs[count] = fallbackBits; - } - } - - /* our new unrolled TE code only writes DWORDS at a time - so it can read up to 6 characters past the last one - we're displaying */ - glyphs[count + 0] = glyphs[0]; - glyphs[count + 1] = glyphs[0]; - glyphs[count + 2] = glyphs[0]; - glyphs[count + 3] = glyphs[0]; - glyphs[count + 4] = glyphs[0]; - glyphs[count + 5] = glyphs[0]; - } - - /* x, y, w, h, skipleft, skiptop, glyphp, glyphWidth, fg, bg, rop, pm */ - - (*infoRec->TEGlyphRenderer)( pScrn, - LeftEdge, ytop, RightEdge - LeftEdge, ybot - ytop, - skippix, ytop - Top, glyphs + skipglyphs, glyphWidth, - fg, bg, rop, planemask); - - if (fallbackBits) - xfree (fallbackBits); - } - - nbox--; pbox++; - } -} - - - - + +/******************************************************************** + + In this file we have GC level replacements for PolyText8/16, + ImageText8/16, ImageGlyphBlt and PolyGlyphBlt for TE (fixed) fonts. + The idea is that everything in this file is device independent. + The mentioned GCOps are merely wrappers for XAAGlyphBltTEColorExpansion + which calculates the boxes containing arbitrarily clipped text + and passes them to the TEGlyphRenderer which will usually be a lower + level XAA function which renders these clipped glyphs using + the basic color expansion functions exported by the chipset driver. + The TEGlyphRenderer itself may optionally be driver supplied to + facilitate work-arounds/optimizations at a higher level than usual. + + v1.0 - Mark Vojkovich (mvojkovi@ucsd.edu) + + +********************************************************************/ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include +#include +#include "scrnintstr.h" +#include "dixfontstr.h" +#include "xf86str.h" +#include "xaa.h" +#include "xaalocal.h" +#include "gcstruct.h" +#include "pixmapstr.h" + + +static void XAAGlyphBltTEColorExpansion(ScrnInfoPtr pScrn, int xInit, + int yInit, FontPtr font, int fg, int bg, int rop, + unsigned int planemask, RegionPtr cclip, int nglyph, + unsigned char* gBase, CharInfoPtr *ppci); + + +/******************************************************************** + + GC level replacements for PolyText8/16 and ImageText8/16 + for TE fonts when using color expansion. + +********************************************************************/ + + +int +XAAPolyText8TEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count, + (unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo); + + /* we have divorced XAAGlyphBltTEColorExpansion from the drawable */ + if(n) XAAGlyphBltTEColorExpansion( + infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, -1, pGC->alu, pGC->planemask, + pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); + + return (x + (n * FONTMAXBOUNDS(pGC->font, characterWidth))); +} + + +int +XAAPolyText16TEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + (*pGC->font->get_glyphs)( + pGC->font, (unsigned long)count, (unsigned char *)chars, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, infoRec->CharInfo); + + if(n) XAAGlyphBltTEColorExpansion( + infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, -1, pGC->alu, pGC->planemask, + pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); + + return (x + (n * FONTMAXBOUNDS(pGC->font, characterWidth))); +} + + +void +XAAImageText8TEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + (*pGC->font->get_glyphs)(pGC->font, (unsigned long)count, + (unsigned char *)chars, Linear8Bit, &n, infoRec->CharInfo); + + if(n) XAAGlyphBltTEColorExpansion( + infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, pGC->bgPixel, GXcopy, pGC->planemask, + pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); +} + + +void +XAAImageText16TEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + unsigned long n; + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + (*pGC->font->get_glyphs)( + pGC->font, (unsigned long)count, (unsigned char *)chars, + (FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit, + &n, infoRec->CharInfo); + + if(n) XAAGlyphBltTEColorExpansion( + infoRec->pScrn, x + pDraw->x, y + pDraw->y, + pGC->font, pGC->fgPixel, pGC->bgPixel, GXcopy, pGC->planemask, + pGC->pCompositeClip, n, FONTGLYPHS(pGC->font), infoRec->CharInfo); +} + + + +/******************************************************************** + + GC level replacements for ImageGlyphBlt and PolyGlyphBlt for + TE fonts when using color expansion. + +********************************************************************/ + + +void +XAAImageGlyphBltTEColorExpansion( + DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + XAAGlyphBltTEColorExpansion( + infoRec->pScrn, xInit + pDrawable->x, yInit + pDrawable->y, + pGC->font, pGC->fgPixel, pGC->bgPixel, GXcopy, pGC->planemask, + pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci); +} + +void +XAAPolyGlyphBltTEColorExpansion( + DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); + + if(!REGION_NUM_RECTS(pGC->pCompositeClip)) + return; + + XAAGlyphBltTEColorExpansion( + infoRec->pScrn, xInit + pDrawable->x, yInit + pDrawable->y, + pGC->font, pGC->fgPixel, -1, pGC->alu, pGC->planemask, + pGC->pCompositeClip, nglyph, (unsigned char*)pglyphBase, ppci); +} + + + + +/******************************************************************** + + XAAGlyphBltTEColorExpansion - + + This guy computes the clipped pieces of text and sends it to + the lower-level function which will handle acceleration of + arbitrarily clipped text. + +********************************************************************/ + + +static void +XAAGlyphBltTEColorExpansion( + ScrnInfoPtr pScrn, + int xInit, int yInit, + FontPtr font, + int fg, int bg, + int rop, + unsigned int planemask, + RegionPtr cclip, + int nglyph, + unsigned char* gBase, + CharInfoPtr *ppci ) +{ + XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); + int skippix, skipglyphs; + int Left, Right, Top, Bottom; + int LeftEdge, RightEdge, ytop, ybot; + int nbox = REGION_NUM_RECTS(cclip); + BoxPtr pbox = REGION_RECTS(cclip); + unsigned int **glyphs = NULL; + int glyphWidth = FONTMAXBOUNDS(font, characterWidth); + + /* find the size of the box */ + Left = xInit; + Right = Left + (glyphWidth * nglyph); + Top = yInit - FONTASCENT(font); + Bottom = yInit + FONTDESCENT(font); + + /* get into the first band that may contain part of our string */ + while(nbox && (Top >= pbox->y2)) { + pbox++; nbox--; + } + + /* stop when the lower edge of the box is beyond our string */ + while(nbox && (Bottom > pbox->y1)) { + LeftEdge = max(Left, pbox->x1); + RightEdge = min(Right, pbox->x2); + + if(RightEdge > LeftEdge) { /* we have something to draw */ + unsigned int *fallbackBits = NULL; + ytop = max(Top, pbox->y1); + ybot = min(Bottom, pbox->y2); + + if((skippix = LeftEdge - Left)) { + skipglyphs = skippix/glyphWidth; + skippix %= glyphWidth; + } else skipglyphs = 0; + + if(!glyphs) { + int count; + glyphs = (unsigned int**)(infoRec->PreAllocMem); + + for(count = 0; count < nglyph; count++) { + glyphs[count] = (unsigned int*) + FONTGLYPHBITS(gBase,*ppci++); + if (!glyphs[count]) { + /* Glyphs with NULL bits do exist in the wild. + Replace with blank bits in that case */ + + if (!fallbackBits) { + int fontHeight = Bottom - Top + 1; + fallbackBits = calloc(glyphWidth * fontHeight, 1); + if (!fallbackBits) + return; + } + glyphs[count] = fallbackBits; + } + } + + /* our new unrolled TE code only writes DWORDS at a time + so it can read up to 6 characters past the last one + we're displaying */ + glyphs[count + 0] = glyphs[0]; + glyphs[count + 1] = glyphs[0]; + glyphs[count + 2] = glyphs[0]; + glyphs[count + 3] = glyphs[0]; + glyphs[count + 4] = glyphs[0]; + glyphs[count + 5] = glyphs[0]; + } + + /* x, y, w, h, skipleft, skiptop, glyphp, glyphWidth, fg, bg, rop, pm */ + + (*infoRec->TEGlyphRenderer)( pScrn, + LeftEdge, ytop, RightEdge - LeftEdge, ybot - ytop, + skippix, ytop - Top, glyphs + skipglyphs, glyphWidth, + fg, bg, rop, planemask); + + if (fallbackBits) + free(fallbackBits); + } + + nbox--; pbox++; + } +} + + + + diff --git a/xorg-server/hw/xfree86/xaa/xaaWrapper.c b/xorg-server/hw/xfree86/xaa/xaaWrapper.c index d6409887c..f709d0b35 100644 --- a/xorg-server/hw/xfree86/xaa/xaaWrapper.c +++ b/xorg-server/hw/xfree86/xaa/xaaWrapper.c @@ -1,474 +1,474 @@ -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include "scrnintstr.h" -#include "gcstruct.h" -#include "glyphstr.h" -#include "window.h" -#include "windowstr.h" -#include "picture.h" -#include "picturestr.h" -#include "colormapst.h" -#include "xaa.h" -#include "xaalocal.h" -#include "xaaWrapper.h" - -void XAASync(ScreenPtr pScreen); - -/* #include "render.h" */ - -#if 1 -#define COND(pDraw) \ - ((pDraw)->depth \ - != (xaaWrapperGetScrPriv(((DrawablePtr)(pDraw))->pScreen))->depth) -#else -#define COND(pDraw) 1 -#endif - -static Bool xaaWrapperCreateGC(GCPtr pGC); -static void xaaWrapperValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); -static void xaaWrapperDestroyGC(GCPtr pGC); -static void xaaWrapperChangeGC (GCPtr pGC, unsigned long mask); -static void xaaWrapperCopyGC (GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); -static void xaaWrapperChangeClip (GCPtr pGC, int type, pointer pvalue, int nrects); - -static void xaaWrapperCopyClip(GCPtr pgcDst, GCPtr pgcSrc); -static void xaaWrapperDestroyClip(GCPtr pGC); - - -static void -xaaWrapperComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); -static void -xaaWrapperGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, - GlyphListPtr list, GlyphPtr *glyphs); - - -typedef struct { - CloseScreenProcPtr CloseScreen; - CreateScreenResourcesProcPtr CreateScreenResources; - CreateWindowProcPtr CreateWindow; - CopyWindowProcPtr CopyWindow; - WindowExposuresProcPtr WindowExposures; - CreateGCProcPtr CreateGC; - CreateColormapProcPtr CreateColormap; - DestroyColormapProcPtr DestroyColormap; - InstallColormapProcPtr InstallColormap; - UninstallColormapProcPtr UninstallColormap; - ListInstalledColormapsProcPtr ListInstalledColormaps; - StoreColorsProcPtr StoreColors; - CompositeProcPtr Composite; - GlyphsProcPtr Glyphs; - - CloseScreenProcPtr wrapCloseScreen; - CreateScreenResourcesProcPtr wrapCreateScreenResources; - CreateWindowProcPtr wrapCreateWindow; - CopyWindowProcPtr wrapCopyWindow; - WindowExposuresProcPtr wrapWindowExposures; - CreateGCProcPtr wrapCreateGC; - CreateColormapProcPtr wrapCreateColormap; - DestroyColormapProcPtr wrapDestroyColormap; - InstallColormapProcPtr wrapInstallColormap; - UninstallColormapProcPtr wrapUninstallColormap; - ListInstalledColormapsProcPtr wrapListInstalledColormaps; - StoreColorsProcPtr wrapStoreColors; - CompositeProcPtr wrapComposite; - GlyphsProcPtr wrapGlyphs; - int depth; -} xaaWrapperScrPrivRec, *xaaWrapperScrPrivPtr; - -#define xaaWrapperGetScrPriv(s) ((xaaWrapperScrPrivPtr) \ - dixLookupPrivate(&(s)->devPrivates, xaaWrapperScrPrivateKey)) -#define xaaWrapperScrPriv(s) xaaWrapperScrPrivPtr pScrPriv = xaaWrapperGetScrPriv(s) - -#define wrap(priv,real,mem,func) {\ - priv->mem = real->mem; \ - real->mem = func; \ -} - -#define unwrap(priv,real,mem) {\ - real->mem = priv->mem; \ -} - -#define cond_wrap(priv,cond,real,mem,wrapmem,func) {\ - if (COND(cond)) \ - priv->wrapmem = real->mem; \ - else \ - priv->mem = real->mem; \ - real->mem = func; \ -} - -#define cond_unwrap(priv,cond,real,mem,wrapmem) {\ - if (COND(cond)) \ - real->mem = priv->wrapmem; \ - else \ - real->mem = priv->mem; \ -} - -#define get(priv,real,func,wrap) \ - priv->wrap = real->func; - -typedef struct _xaaWrapperGCPriv { - GCOps *ops; - Bool wrap; - GCFuncs *funcs; - GCOps *wrapops; -} xaaWrapperGCPrivRec, *xaaWrapperGCPrivPtr; - -#define xaaWrapperGetGCPriv(pGC) ((xaaWrapperGCPrivPtr) \ - dixLookupPrivate(&(pGC)->devPrivates, xaaWrapperGCPrivateKey)) -#define xaaWrapperGCPriv(pGC) xaaWrapperGCPrivPtr pGCPriv = xaaWrapperGetGCPriv(pGC) - - -static int xaaWrapperScrPrivateKeyIndex; -static DevPrivateKey xaaWrapperScrPrivateKey = &xaaWrapperScrPrivateKeyIndex; -static int xaaWrapperGCPrivateKeyIndex; -static DevPrivateKey xaaWrapperGCPrivateKey = &xaaWrapperGCPrivateKeyIndex; - -static Bool -xaaWrapperCreateScreenResources(ScreenPtr pScreen) -{ - xaaWrapperScrPriv(pScreen); - Bool ret; - - unwrap (pScrPriv,pScreen, CreateScreenResources); - ret = pScreen->CreateScreenResources(pScreen); - wrap(pScrPriv,pScreen,CreateScreenResources,xaaWrapperCreateScreenResources); - return ret; -} - -static Bool -xaaWrapperCloseScreen (int iScreen, ScreenPtr pScreen) -{ - xaaWrapperScrPriv(pScreen); - Bool ret; - - unwrap (pScrPriv,pScreen, CloseScreen); - ret = pScreen->CloseScreen(iScreen,pScreen); - return TRUE; -} - -static Bool -xaaWrapperCreateWindow(WindowPtr pWin) -{ - xaaWrapperScrPriv(pWin->drawable.pScreen); - Bool ret; - - cond_unwrap(pScrPriv, &pWin->drawable, pWin->drawable.pScreen, - CreateWindow, wrapCreateWindow); - ret = pWin->drawable.pScreen->CreateWindow(pWin); - cond_wrap(pScrPriv, &pWin->drawable, pWin->drawable.pScreen, CreateWindow, - wrapCreateWindow, xaaWrapperCreateWindow); - - return ret; -} - -static void -xaaWrapperCopyWindow(WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - xaaWrapperScrPriv(pScreen); - - unwrap (pScrPriv, pScreen, CopyWindow); -#if 0 - if (COND(&pWin->drawable)) - pWin->drawable.pScreen->CopyWindow = pScrPriv->wrapCopyWindow; -#endif - pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc); - wrap(pScrPriv, pScreen, CopyWindow, xaaWrapperCopyWindow); -} - -static void -xaaWrapperWindowExposures (WindowPtr pWin, - RegionPtr prgn, - RegionPtr other_exposed) -{ - xaaWrapperScrPriv(pWin->drawable.pScreen); - - cond_unwrap(pScrPriv, &pWin->drawable, pWin->drawable.pScreen, - WindowExposures, wrapWindowExposures); - pWin->drawable.pScreen->WindowExposures(pWin, prgn, other_exposed); - cond_wrap(pScrPriv, &pWin->drawable, pWin->drawable.pScreen, - WindowExposures, wrapWindowExposures, xaaWrapperWindowExposures); -} - -static Bool -xaaWrapperCreateColormap(ColormapPtr pmap) -{ - xaaWrapperScrPriv(pmap->pScreen); - Bool ret; - unwrap(pScrPriv,pmap->pScreen, CreateColormap); - ret = pmap->pScreen->CreateColormap(pmap); - wrap(pScrPriv,pmap->pScreen,CreateColormap,xaaWrapperCreateColormap); - - return ret; -} - -static void -xaaWrapperDestroyColormap(ColormapPtr pmap) -{ - xaaWrapperScrPriv(pmap->pScreen); - unwrap(pScrPriv,pmap->pScreen, DestroyColormap); - pmap->pScreen->DestroyColormap(pmap); - wrap(pScrPriv,pmap->pScreen,DestroyColormap,xaaWrapperDestroyColormap); -} - -static void -xaaWrapperStoreColors(ColormapPtr pmap, int nColors, xColorItem *pColors) -{ - xaaWrapperScrPriv(pmap->pScreen); - unwrap(pScrPriv,pmap->pScreen, StoreColors); - pmap->pScreen->StoreColors(pmap,nColors,pColors); - wrap(pScrPriv,pmap->pScreen,StoreColors,xaaWrapperStoreColors); -} - -static void -xaaWrapperInstallColormap(ColormapPtr pmap) -{ - xaaWrapperScrPriv(pmap->pScreen); - - unwrap(pScrPriv,pmap->pScreen, InstallColormap); - pmap->pScreen->InstallColormap(pmap); - wrap(pScrPriv,pmap->pScreen,InstallColormap,xaaWrapperInstallColormap); -} - -static void -xaaWrapperUninstallColormap(ColormapPtr pmap) -{ - xaaWrapperScrPriv(pmap->pScreen); - - unwrap(pScrPriv,pmap->pScreen, UninstallColormap); - pmap->pScreen->UninstallColormap(pmap); - wrap(pScrPriv,pmap->pScreen,UninstallColormap,xaaWrapperUninstallColormap); -} - -static int -xaaWrapperListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds) -{ - int n; - xaaWrapperScrPriv(pScreen); - - unwrap(pScrPriv,pScreen, ListInstalledColormaps); - n = pScreen->ListInstalledColormaps(pScreen, pCmapIds); - wrap (pScrPriv,pScreen,ListInstalledColormaps,xaaWrapperListInstalledColormaps); - return n; -} - -Bool -xaaSetupWrapper(ScreenPtr pScreen, XAAInfoRecPtr infoPtr, int depth, SyncFunc *func) -{ - Bool ret; - xaaWrapperScrPrivPtr pScrPriv; - PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); - - if (!dixRequestPrivate(xaaWrapperGCPrivateKey, sizeof(xaaWrapperGCPrivRec))) - return FALSE; - - pScrPriv = (xaaWrapperScrPrivPtr) xalloc (sizeof (xaaWrapperScrPrivRec)); - if (!pScrPriv) - return FALSE; - - get (pScrPriv, pScreen, CloseScreen, wrapCloseScreen); - get (pScrPriv, pScreen, CreateScreenResources, wrapCreateScreenResources); - get (pScrPriv, pScreen, CreateWindow, wrapCreateWindow); - get (pScrPriv, pScreen, CopyWindow, wrapCopyWindow); - get (pScrPriv, pScreen, WindowExposures, wrapWindowExposures); - get (pScrPriv, pScreen, CreateGC, wrapCreateGC); - get (pScrPriv, pScreen, CreateColormap, wrapCreateColormap); - get (pScrPriv, pScreen, DestroyColormap, wrapDestroyColormap); - get (pScrPriv, pScreen, InstallColormap, wrapInstallColormap); - get (pScrPriv, pScreen, UninstallColormap, wrapUninstallColormap); - get (pScrPriv, pScreen, ListInstalledColormaps, wrapListInstalledColormaps); - get (pScrPriv, pScreen, StoreColors, wrapStoreColors); - if (ps) { - get (pScrPriv, ps, Glyphs, wrapGlyphs); - get (pScrPriv, ps, Composite, wrapComposite); - } - if (!(ret = XAAInit(pScreen,infoPtr))) - return FALSE; - - wrap (pScrPriv, pScreen, CloseScreen, xaaWrapperCloseScreen); - wrap (pScrPriv, pScreen, CreateScreenResources, - xaaWrapperCreateScreenResources); - wrap (pScrPriv, pScreen, CreateWindow, xaaWrapperCreateWindow); - wrap (pScrPriv, pScreen, CopyWindow, xaaWrapperCopyWindow); - wrap (pScrPriv, pScreen, WindowExposures, xaaWrapperWindowExposures); - wrap (pScrPriv, pScreen, CreateGC, xaaWrapperCreateGC); - wrap (pScrPriv, pScreen, CreateColormap, xaaWrapperCreateColormap); - wrap (pScrPriv, pScreen, DestroyColormap, xaaWrapperDestroyColormap); - wrap (pScrPriv, pScreen, InstallColormap, xaaWrapperInstallColormap); - wrap (pScrPriv, pScreen, UninstallColormap, xaaWrapperUninstallColormap); - wrap (pScrPriv, pScreen, ListInstalledColormaps, - xaaWrapperListInstalledColormaps); - wrap (pScrPriv, pScreen, StoreColors, xaaWrapperStoreColors); - - if (ps) { - wrap (pScrPriv, ps, Glyphs, xaaWrapperGlyphs); - wrap (pScrPriv, ps, Composite, xaaWrapperComposite); - } - pScrPriv->depth = depth; - dixSetPrivate(&pScreen->devPrivates, xaaWrapperScrPrivateKey, pScrPriv); - - *func = XAASync; - - return ret; -} - -GCFuncs xaaWrapperGCFuncs = { - xaaWrapperValidateGC, xaaWrapperChangeGC, xaaWrapperCopyGC, - xaaWrapperDestroyGC, xaaWrapperChangeClip, xaaWrapperDestroyClip, - xaaWrapperCopyClip -}; - -#define XAAWRAPPER_GC_FUNC_PROLOGUE(pGC) \ - xaaWrapperGCPriv(pGC); \ - unwrap(pGCPriv, pGC, funcs); \ - if (pGCPriv->wrap) unwrap(pGCPriv, pGC, ops) - -#define XAAWRAPPER_GC_FUNC_EPILOGUE(pGC) \ - wrap(pGCPriv, pGC, funcs, &xaaWrapperGCFuncs); \ - if (pGCPriv->wrap) wrap(pGCPriv, pGC, ops, pGCPriv->wrapops) - -static Bool -xaaWrapperCreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - xaaWrapperScrPriv(pScreen); - xaaWrapperGCPriv(pGC); - Bool ret; - - unwrap (pScrPriv, pScreen, CreateGC); - if((ret = (*pScreen->CreateGC) (pGC))) { - pGCPriv->wrap = FALSE; - pGCPriv->funcs = pGC->funcs; - pGCPriv->wrapops = pGC->ops; - pGC->funcs = &xaaWrapperGCFuncs; - } - wrap (pScrPriv, pScreen, CreateGC, xaaWrapperCreateGC); - - return ret; -} - -static void -xaaWrapperValidateGC( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -){ - XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); - - if(COND(pDraw)) - pGCPriv->wrap = TRUE; - - XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); -} - -static void -xaaWrapperDestroyGC(GCPtr pGC) -{ - XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->DestroyGC)(pGC); - XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); -} - -static void -xaaWrapperChangeGC ( - GCPtr pGC, - unsigned long mask -){ - XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeGC) (pGC, mask); - XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); -} - -static void -xaaWrapperCopyGC ( - GCPtr pGCSrc, - unsigned long mask, - GCPtr pGCDst -){ - XAAWRAPPER_GC_FUNC_PROLOGUE (pGCDst); - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - XAAWRAPPER_GC_FUNC_EPILOGUE (pGCDst); -} - -static void -xaaWrapperChangeClip ( - GCPtr pGC, - int type, - pointer pvalue, - int nrects -){ - XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); - XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); -} - -static void -xaaWrapperCopyClip(GCPtr pgcDst, GCPtr pgcSrc) -{ - XAAWRAPPER_GC_FUNC_PROLOGUE (pgcDst); - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - XAAWRAPPER_GC_FUNC_EPILOGUE (pgcDst); -} - -static void -xaaWrapperDestroyClip(GCPtr pGC) -{ - XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); - (* pGC->funcs->DestroyClip)(pGC); - XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); -} - -static void -xaaWrapperComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, - INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - xaaWrapperScrPriv(pScreen); - - unwrap (pScrPriv, ps, Composite); - (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); - wrap (pScrPriv, ps, Composite, xaaWrapperComposite); -} - - -static void -xaaWrapperGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, - GlyphListPtr list, GlyphPtr *glyphs) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - PictureScreenPtr ps = GetPictureScreen(pScreen); - xaaWrapperScrPriv(pScreen); - - unwrap (pScrPriv, ps, Glyphs); - (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, - nlist, list, glyphs); - wrap (pScrPriv, ps, Glyphs, xaaWrapperGlyphs); - -} - -void -XAASync(ScreenPtr pScreen) -{ - XAAScreenPtr pScreenPriv = (XAAScreenPtr) - dixLookupPrivate(&pScreen->devPrivates, XAAGetScreenKey()); - XAAInfoRecPtr infoRec = pScreenPriv->AccelInfoRec; - - if(infoRec->NeedToSync) { - (*infoRec->Sync)(infoRec->pScrn); - infoRec->NeedToSync = FALSE; - } -} +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include "scrnintstr.h" +#include "gcstruct.h" +#include "glyphstr.h" +#include "window.h" +#include "windowstr.h" +#include "picture.h" +#include "picturestr.h" +#include "colormapst.h" +#include "xaa.h" +#include "xaalocal.h" +#include "xaaWrapper.h" + +void XAASync(ScreenPtr pScreen); + +/* #include "render.h" */ + +#if 1 +#define COND(pDraw) \ + ((pDraw)->depth \ + != (xaaWrapperGetScrPriv(((DrawablePtr)(pDraw))->pScreen))->depth) +#else +#define COND(pDraw) 1 +#endif + +static Bool xaaWrapperCreateGC(GCPtr pGC); +static void xaaWrapperValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw); +static void xaaWrapperDestroyGC(GCPtr pGC); +static void xaaWrapperChangeGC (GCPtr pGC, unsigned long mask); +static void xaaWrapperCopyGC (GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +static void xaaWrapperChangeClip (GCPtr pGC, int type, pointer pvalue, int nrects); + +static void xaaWrapperCopyClip(GCPtr pgcDst, GCPtr pgcSrc); +static void xaaWrapperDestroyClip(GCPtr pGC); + + +static void +xaaWrapperComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); +static void +xaaWrapperGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, + GlyphListPtr list, GlyphPtr *glyphs); + + +typedef struct { + CloseScreenProcPtr CloseScreen; + CreateScreenResourcesProcPtr CreateScreenResources; + CreateWindowProcPtr CreateWindow; + CopyWindowProcPtr CopyWindow; + WindowExposuresProcPtr WindowExposures; + CreateGCProcPtr CreateGC; + CreateColormapProcPtr CreateColormap; + DestroyColormapProcPtr DestroyColormap; + InstallColormapProcPtr InstallColormap; + UninstallColormapProcPtr UninstallColormap; + ListInstalledColormapsProcPtr ListInstalledColormaps; + StoreColorsProcPtr StoreColors; + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; + + CloseScreenProcPtr wrapCloseScreen; + CreateScreenResourcesProcPtr wrapCreateScreenResources; + CreateWindowProcPtr wrapCreateWindow; + CopyWindowProcPtr wrapCopyWindow; + WindowExposuresProcPtr wrapWindowExposures; + CreateGCProcPtr wrapCreateGC; + CreateColormapProcPtr wrapCreateColormap; + DestroyColormapProcPtr wrapDestroyColormap; + InstallColormapProcPtr wrapInstallColormap; + UninstallColormapProcPtr wrapUninstallColormap; + ListInstalledColormapsProcPtr wrapListInstalledColormaps; + StoreColorsProcPtr wrapStoreColors; + CompositeProcPtr wrapComposite; + GlyphsProcPtr wrapGlyphs; + int depth; +} xaaWrapperScrPrivRec, *xaaWrapperScrPrivPtr; + +#define xaaWrapperGetScrPriv(s) ((xaaWrapperScrPrivPtr) \ + dixLookupPrivate(&(s)->devPrivates, xaaWrapperScrPrivateKey)) +#define xaaWrapperScrPriv(s) xaaWrapperScrPrivPtr pScrPriv = xaaWrapperGetScrPriv(s) + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +#define cond_wrap(priv,cond,real,mem,wrapmem,func) {\ + if (COND(cond)) \ + priv->wrapmem = real->mem; \ + else \ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define cond_unwrap(priv,cond,real,mem,wrapmem) {\ + if (COND(cond)) \ + real->mem = priv->wrapmem; \ + else \ + real->mem = priv->mem; \ +} + +#define get(priv,real,func,wrap) \ + priv->wrap = real->func; + +typedef struct _xaaWrapperGCPriv { + GCOps *ops; + Bool wrap; + GCFuncs *funcs; + GCOps *wrapops; +} xaaWrapperGCPrivRec, *xaaWrapperGCPrivPtr; + +#define xaaWrapperGetGCPriv(pGC) ((xaaWrapperGCPrivPtr) \ + dixLookupPrivate(&(pGC)->devPrivates, xaaWrapperGCPrivateKey)) +#define xaaWrapperGCPriv(pGC) xaaWrapperGCPrivPtr pGCPriv = xaaWrapperGetGCPriv(pGC) + + +static int xaaWrapperScrPrivateKeyIndex; +static DevPrivateKey xaaWrapperScrPrivateKey = &xaaWrapperScrPrivateKeyIndex; +static int xaaWrapperGCPrivateKeyIndex; +static DevPrivateKey xaaWrapperGCPrivateKey = &xaaWrapperGCPrivateKeyIndex; + +static Bool +xaaWrapperCreateScreenResources(ScreenPtr pScreen) +{ + xaaWrapperScrPriv(pScreen); + Bool ret; + + unwrap (pScrPriv,pScreen, CreateScreenResources); + ret = pScreen->CreateScreenResources(pScreen); + wrap(pScrPriv,pScreen,CreateScreenResources,xaaWrapperCreateScreenResources); + return ret; +} + +static Bool +xaaWrapperCloseScreen (int iScreen, ScreenPtr pScreen) +{ + xaaWrapperScrPriv(pScreen); + Bool ret; + + unwrap (pScrPriv,pScreen, CloseScreen); + ret = pScreen->CloseScreen(iScreen,pScreen); + return TRUE; +} + +static Bool +xaaWrapperCreateWindow(WindowPtr pWin) +{ + xaaWrapperScrPriv(pWin->drawable.pScreen); + Bool ret; + + cond_unwrap(pScrPriv, &pWin->drawable, pWin->drawable.pScreen, + CreateWindow, wrapCreateWindow); + ret = pWin->drawable.pScreen->CreateWindow(pWin); + cond_wrap(pScrPriv, &pWin->drawable, pWin->drawable.pScreen, CreateWindow, + wrapCreateWindow, xaaWrapperCreateWindow); + + return ret; +} + +static void +xaaWrapperCopyWindow(WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + xaaWrapperScrPriv(pScreen); + + unwrap (pScrPriv, pScreen, CopyWindow); +#if 0 + if (COND(&pWin->drawable)) + pWin->drawable.pScreen->CopyWindow = pScrPriv->wrapCopyWindow; +#endif + pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc); + wrap(pScrPriv, pScreen, CopyWindow, xaaWrapperCopyWindow); +} + +static void +xaaWrapperWindowExposures (WindowPtr pWin, + RegionPtr prgn, + RegionPtr other_exposed) +{ + xaaWrapperScrPriv(pWin->drawable.pScreen); + + cond_unwrap(pScrPriv, &pWin->drawable, pWin->drawable.pScreen, + WindowExposures, wrapWindowExposures); + pWin->drawable.pScreen->WindowExposures(pWin, prgn, other_exposed); + cond_wrap(pScrPriv, &pWin->drawable, pWin->drawable.pScreen, + WindowExposures, wrapWindowExposures, xaaWrapperWindowExposures); +} + +static Bool +xaaWrapperCreateColormap(ColormapPtr pmap) +{ + xaaWrapperScrPriv(pmap->pScreen); + Bool ret; + unwrap(pScrPriv,pmap->pScreen, CreateColormap); + ret = pmap->pScreen->CreateColormap(pmap); + wrap(pScrPriv,pmap->pScreen,CreateColormap,xaaWrapperCreateColormap); + + return ret; +} + +static void +xaaWrapperDestroyColormap(ColormapPtr pmap) +{ + xaaWrapperScrPriv(pmap->pScreen); + unwrap(pScrPriv,pmap->pScreen, DestroyColormap); + pmap->pScreen->DestroyColormap(pmap); + wrap(pScrPriv,pmap->pScreen,DestroyColormap,xaaWrapperDestroyColormap); +} + +static void +xaaWrapperStoreColors(ColormapPtr pmap, int nColors, xColorItem *pColors) +{ + xaaWrapperScrPriv(pmap->pScreen); + unwrap(pScrPriv,pmap->pScreen, StoreColors); + pmap->pScreen->StoreColors(pmap,nColors,pColors); + wrap(pScrPriv,pmap->pScreen,StoreColors,xaaWrapperStoreColors); +} + +static void +xaaWrapperInstallColormap(ColormapPtr pmap) +{ + xaaWrapperScrPriv(pmap->pScreen); + + unwrap(pScrPriv,pmap->pScreen, InstallColormap); + pmap->pScreen->InstallColormap(pmap); + wrap(pScrPriv,pmap->pScreen,InstallColormap,xaaWrapperInstallColormap); +} + +static void +xaaWrapperUninstallColormap(ColormapPtr pmap) +{ + xaaWrapperScrPriv(pmap->pScreen); + + unwrap(pScrPriv,pmap->pScreen, UninstallColormap); + pmap->pScreen->UninstallColormap(pmap); + wrap(pScrPriv,pmap->pScreen,UninstallColormap,xaaWrapperUninstallColormap); +} + +static int +xaaWrapperListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds) +{ + int n; + xaaWrapperScrPriv(pScreen); + + unwrap(pScrPriv,pScreen, ListInstalledColormaps); + n = pScreen->ListInstalledColormaps(pScreen, pCmapIds); + wrap (pScrPriv,pScreen,ListInstalledColormaps,xaaWrapperListInstalledColormaps); + return n; +} + +Bool +xaaSetupWrapper(ScreenPtr pScreen, XAAInfoRecPtr infoPtr, int depth, SyncFunc *func) +{ + Bool ret; + xaaWrapperScrPrivPtr pScrPriv; + PictureScreenPtr ps = GetPictureScreenIfSet(pScreen); + + if (!dixRequestPrivate(xaaWrapperGCPrivateKey, sizeof(xaaWrapperGCPrivRec))) + return FALSE; + + pScrPriv = (xaaWrapperScrPrivPtr) malloc(sizeof (xaaWrapperScrPrivRec)); + if (!pScrPriv) + return FALSE; + + get (pScrPriv, pScreen, CloseScreen, wrapCloseScreen); + get (pScrPriv, pScreen, CreateScreenResources, wrapCreateScreenResources); + get (pScrPriv, pScreen, CreateWindow, wrapCreateWindow); + get (pScrPriv, pScreen, CopyWindow, wrapCopyWindow); + get (pScrPriv, pScreen, WindowExposures, wrapWindowExposures); + get (pScrPriv, pScreen, CreateGC, wrapCreateGC); + get (pScrPriv, pScreen, CreateColormap, wrapCreateColormap); + get (pScrPriv, pScreen, DestroyColormap, wrapDestroyColormap); + get (pScrPriv, pScreen, InstallColormap, wrapInstallColormap); + get (pScrPriv, pScreen, UninstallColormap, wrapUninstallColormap); + get (pScrPriv, pScreen, ListInstalledColormaps, wrapListInstalledColormaps); + get (pScrPriv, pScreen, StoreColors, wrapStoreColors); + if (ps) { + get (pScrPriv, ps, Glyphs, wrapGlyphs); + get (pScrPriv, ps, Composite, wrapComposite); + } + if (!(ret = XAAInit(pScreen,infoPtr))) + return FALSE; + + wrap (pScrPriv, pScreen, CloseScreen, xaaWrapperCloseScreen); + wrap (pScrPriv, pScreen, CreateScreenResources, + xaaWrapperCreateScreenResources); + wrap (pScrPriv, pScreen, CreateWindow, xaaWrapperCreateWindow); + wrap (pScrPriv, pScreen, CopyWindow, xaaWrapperCopyWindow); + wrap (pScrPriv, pScreen, WindowExposures, xaaWrapperWindowExposures); + wrap (pScrPriv, pScreen, CreateGC, xaaWrapperCreateGC); + wrap (pScrPriv, pScreen, CreateColormap, xaaWrapperCreateColormap); + wrap (pScrPriv, pScreen, DestroyColormap, xaaWrapperDestroyColormap); + wrap (pScrPriv, pScreen, InstallColormap, xaaWrapperInstallColormap); + wrap (pScrPriv, pScreen, UninstallColormap, xaaWrapperUninstallColormap); + wrap (pScrPriv, pScreen, ListInstalledColormaps, + xaaWrapperListInstalledColormaps); + wrap (pScrPriv, pScreen, StoreColors, xaaWrapperStoreColors); + + if (ps) { + wrap (pScrPriv, ps, Glyphs, xaaWrapperGlyphs); + wrap (pScrPriv, ps, Composite, xaaWrapperComposite); + } + pScrPriv->depth = depth; + dixSetPrivate(&pScreen->devPrivates, xaaWrapperScrPrivateKey, pScrPriv); + + *func = XAASync; + + return ret; +} + +GCFuncs xaaWrapperGCFuncs = { + xaaWrapperValidateGC, xaaWrapperChangeGC, xaaWrapperCopyGC, + xaaWrapperDestroyGC, xaaWrapperChangeClip, xaaWrapperDestroyClip, + xaaWrapperCopyClip +}; + +#define XAAWRAPPER_GC_FUNC_PROLOGUE(pGC) \ + xaaWrapperGCPriv(pGC); \ + unwrap(pGCPriv, pGC, funcs); \ + if (pGCPriv->wrap) unwrap(pGCPriv, pGC, ops) + +#define XAAWRAPPER_GC_FUNC_EPILOGUE(pGC) \ + wrap(pGCPriv, pGC, funcs, &xaaWrapperGCFuncs); \ + if (pGCPriv->wrap) wrap(pGCPriv, pGC, ops, pGCPriv->wrapops) + +static Bool +xaaWrapperCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + xaaWrapperScrPriv(pScreen); + xaaWrapperGCPriv(pGC); + Bool ret; + + unwrap (pScrPriv, pScreen, CreateGC); + if((ret = (*pScreen->CreateGC) (pGC))) { + pGCPriv->wrap = FALSE; + pGCPriv->funcs = pGC->funcs; + pGCPriv->wrapops = pGC->ops; + pGC->funcs = &xaaWrapperGCFuncs; + } + wrap (pScrPriv, pScreen, CreateGC, xaaWrapperCreateGC); + + return ret; +} + +static void +xaaWrapperValidateGC( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); + + if(COND(pDraw)) + pGCPriv->wrap = TRUE; + + XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); +} + +static void +xaaWrapperDestroyGC(GCPtr pGC) +{ + XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); +} + +static void +xaaWrapperChangeGC ( + GCPtr pGC, + unsigned long mask +){ + XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); +} + +static void +xaaWrapperCopyGC ( + GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst +){ + XAAWRAPPER_GC_FUNC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + XAAWRAPPER_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +xaaWrapperChangeClip ( + GCPtr pGC, + int type, + pointer pvalue, + int nrects +){ + XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); +} + +static void +xaaWrapperCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + XAAWRAPPER_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + XAAWRAPPER_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +xaaWrapperDestroyClip(GCPtr pGC) +{ + XAAWRAPPER_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + XAAWRAPPER_GC_FUNC_EPILOGUE (pGC); +} + +static void +xaaWrapperComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + xaaWrapperScrPriv(pScreen); + + unwrap (pScrPriv, ps, Composite); + (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height); + wrap (pScrPriv, ps, Composite, xaaWrapperComposite); +} + + +static void +xaaWrapperGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, + GlyphListPtr list, GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + xaaWrapperScrPriv(pScreen); + + unwrap (pScrPriv, ps, Glyphs); + (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, + nlist, list, glyphs); + wrap (pScrPriv, ps, Glyphs, xaaWrapperGlyphs); + +} + +void +XAASync(ScreenPtr pScreen) +{ + XAAScreenPtr pScreenPriv = (XAAScreenPtr) + dixLookupPrivate(&pScreen->devPrivates, XAAGetScreenKey()); + XAAInfoRecPtr infoRec = pScreenPriv->AccelInfoRec; + + if(infoRec->NeedToSync) { + (*infoRec->Sync)(infoRec->pScrn); + infoRec->NeedToSync = FALSE; + } +} diff --git a/xorg-server/hw/xfree86/xaa/xaalocal.h b/xorg-server/hw/xfree86/xaa/xaalocal.h index 129c1d6c4..6c492c013 100644 --- a/xorg-server/hw/xfree86/xaa/xaalocal.h +++ b/xorg-server/hw/xfree86/xaa/xaalocal.h @@ -1,1755 +1,1755 @@ - -#ifndef _XAALOCAL_H -#define _XAALOCAL_H - -/* This file is very unorganized ! */ - - -#include "gcstruct.h" -#include "regionstr.h" -#include "xf86fbman.h" -#include "xaa.h" -#include "mi.h" -#include "picturestr.h" - -#define GCWhenForced (GCArcMode << 1) - -#define DO_COLOR_8x8 0x00000001 -#define DO_MONO_8x8 0x00000002 -#define DO_CACHE_BLT 0x00000003 -#define DO_COLOR_EXPAND 0x00000004 -#define DO_CACHE_EXPAND 0x00000005 -#define DO_IMAGE_WRITE 0x00000006 -#define DO_PIXMAP_COPY 0x00000007 -#define DO_SOLID 0x00000008 - - -typedef CARD32 * (*GlyphScanlineFuncPtr)( - CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width -); - -typedef CARD32 *(*StippleScanlineProcPtr)(CARD32*, CARD32*, int, int, int); - -typedef void (*RectFuncPtr) (ScrnInfoPtr, int, int, int, int, int, int, - XAACacheInfoPtr); -typedef void (*TrapFuncPtr) (ScrnInfoPtr, int, int, int, int, int, int, - int, int, int, int, int, int, - XAACacheInfoPtr); - - - -typedef struct _XAAScreen { - CreateGCProcPtr CreateGC; - CloseScreenProcPtr CloseScreen; - GetImageProcPtr GetImage; - GetSpansProcPtr GetSpans; - CopyWindowProcPtr CopyWindow; - WindowExposuresProcPtr WindowExposures; - CreatePixmapProcPtr CreatePixmap; - DestroyPixmapProcPtr DestroyPixmap; - ChangeWindowAttributesProcPtr ChangeWindowAttributes; - XAAInfoRecPtr AccelInfoRec; - Bool (*EnterVT)(int, int); - void (*LeaveVT)(int, int); - int (*SetDGAMode)(int, int, DGADevicePtr); - void (*EnableDisableFBAccess)(int, Bool); - CompositeProcPtr Composite; - GlyphsProcPtr Glyphs; -} XAAScreenRec, *XAAScreenPtr; - -#define OPS_ARE_PIXMAP 0x00000001 -#define OPS_ARE_ACCEL 0x00000002 - -typedef struct _XAAGC { - GCOps *wrapOps; - GCFuncs *wrapFuncs; - GCOps *XAAOps; - int DashLength; - unsigned char* DashPattern; - unsigned long changes; - unsigned long flags; -} XAAGCRec, *XAAGCPtr; - -#define REDUCIBILITY_CHECKED 0x00000001 -#define REDUCIBLE_TO_8x8 0x00000002 -#define REDUCIBLE_TO_2_COLOR 0x00000004 -#define DIRTY 0x00010000 -#define OFFSCREEN 0x00020000 -#define DGA_PIXMAP 0x00040000 -#define SHARED_PIXMAP 0x00080000 -#define LOCKED_PIXMAP 0x00100000 - -#define REDUCIBILITY_MASK \ - (REDUCIBILITY_CHECKED | REDUCIBLE_TO_8x8 | REDUCIBLE_TO_2_COLOR) - -typedef struct _XAAPixmap { - unsigned long flags; - CARD32 pattern0; - CARD32 pattern1; - int fg; - int bg; - FBAreaPtr offscreenArea; - Bool freeData; -} XAAPixmapRec, *XAAPixmapPtr; - - -extern _X_EXPORT Bool -XAACreateGC( - GCPtr pGC -); - -extern _X_EXPORT Bool -XAAInitAccel( - ScreenPtr pScreen, - XAAInfoRecPtr infoRec -); - -extern _X_EXPORT RegionPtr -XAABitBlt( - DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GC *pGC, - int srcx, - int srcy, - int width, - int height, - int dstx, - int dsty, - void (*doBitBlt)(DrawablePtr, DrawablePtr, GCPtr, RegionPtr, DDXPointPtr), - unsigned long bitPlane -); - -extern _X_EXPORT void -XAAScreenToScreenBitBlt( - ScrnInfoPtr pScrn, - int nbox, - DDXPointPtr pptSrc, - BoxPtr pbox, - int xdir, - int ydir, - int alu, - unsigned int planemask -); - -extern _X_EXPORT void -XAADoBitBlt( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - RegionPtr prgnDst, - DDXPointPtr pptSrc -); - -extern _X_EXPORT void -XAADoImageWrite( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - RegionPtr prgnDst, - DDXPointPtr pptSrc -); - -extern _X_EXPORT void -XAADoImageRead( - DrawablePtr pSrc, - DrawablePtr pDst, - GC *pGC, - RegionPtr prgnDst, - DDXPointPtr pptSrc -); - -extern _X_EXPORT void -XAACopyWindow( - WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc -); - - -extern _X_EXPORT RegionPtr -XAACopyArea( - DrawablePtr pSrcDrawable, - DrawablePtr pDstDrawable, - GC *pGC, - int srcx, - int srcy, - int width, - int height, - int dstx, - int dsty -); - -extern _X_EXPORT void -XAAValidateCopyArea( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -); - -extern _X_EXPORT void -XAAValidatePutImage( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -); - -extern _X_EXPORT void -XAAValidateCopyPlane( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -); - -extern _X_EXPORT void -XAAValidatePushPixels( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -); - -extern _X_EXPORT void -XAAValidateFillSpans( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -); - -extern _X_EXPORT void -XAAValidatePolyGlyphBlt( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -); - -extern _X_EXPORT void -XAAValidateImageGlyphBlt( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -); - -extern _X_EXPORT void -XAAValidatePolylines( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -); - - -extern _X_EXPORT RegionPtr -XAACopyPlaneColorExpansion( - DrawablePtr pSrc, - DrawablePtr pDst, - GCPtr pGC, - int srcx, - int srcy, - int width, - int height, - int dstx, - int dsty, - unsigned long bitPlane -); - - -extern _X_EXPORT void -XAAPushPixelsSolidColorExpansion( - GCPtr pGC, - PixmapPtr pBitMap, - DrawablePtr pDrawable, - int dx, - int dy, - int xOrg, - int yOrg -); - -extern _X_EXPORT void -XAAWriteBitmapColorExpandMSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapColorExpand3MSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapColorExpandMSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapColorExpand3MSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapColorExpandLSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapColorExpand3LSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapColorExpandLSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapColorExpand3LSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - - -extern _X_EXPORT void -XAAWriteBitmapScanlineColorExpandMSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapScanlineColorExpand3MSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapScanlineColorExpandMSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapScanlineColorExpand3MSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapScanlineColorExpandLSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapScanlineColorExpand3LSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapScanlineColorExpandLSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWriteBitmapScanlineColorExpand3LSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int skipleft, - int fg, int bg, - int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAWritePixmap ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int rop, - unsigned int planemask, - int transparency_color, - int bpp, int depth -); - -extern _X_EXPORT void -XAAWritePixmapScanline ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int rop, - unsigned int planemask, - int transparency_color, - int bpp, int depth -); - -typedef void (*ClipAndRenderRectsFunc)(GCPtr, int, BoxPtr, int, int); - - -extern _X_EXPORT void -XAAClipAndRenderRects( - GCPtr pGC, - ClipAndRenderRectsFunc func, - int nrectFill, - xRectangle *prectInit, - int xorg, int yorg -); - - -typedef void (*ClipAndRenderSpansFunc)(GCPtr, int, DDXPointPtr, int*, - int, int, int); - -extern _X_EXPORT void -XAAClipAndRenderSpans( - GCPtr pGC, - DDXPointPtr ppt, - int *pwidth, - int nspans, - int fSorted, - ClipAndRenderSpansFunc func, - int xorg, - int yorg -); - - -extern _X_EXPORT void -XAAFillSolidRects( - ScrnInfoPtr pScrn, - int fg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox -); - -extern _X_EXPORT void -XAAFillMono8x8PatternRects( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int pat0, int pat1, - int xorg, int yorg -); - -extern _X_EXPORT void -XAAFillMono8x8PatternRectsScreenOrigin( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int pat0, int pat1, - int xorg, int yorg -); - - -extern _X_EXPORT void -XAAFillColor8x8PatternRectsScreenOrigin( - ScrnInfoPtr pScrn, - int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorigin, int yorigin, - XAACacheInfoPtr pCache -); - -extern _X_EXPORT void -XAAFillColor8x8PatternRects( - ScrnInfoPtr pScrn, - int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorigin, int yorigin, - XAACacheInfoPtr pCache -); - -extern _X_EXPORT void -XAAFillCacheBltRects( - ScrnInfoPtr pScrn, - int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - XAACacheInfoPtr pCache -); - -extern _X_EXPORT void -XAAFillCacheExpandRects( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillImageWriteRects( - ScrnInfoPtr pScrn, - int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAPolyFillRect( - DrawablePtr pDraw, - GCPtr pGC, - int nrectFill, - xRectangle *prectInit -); - - -extern _X_EXPORT void -XAATEGlyphRendererMSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRenderer3MSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRendererMSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRenderer3MSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRendererLSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - - -extern _X_EXPORT void -XAATEGlyphRenderer3LSBFirstFixedBase ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRendererLSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRenderer3LSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - - -extern _X_EXPORT void -XAATEGlyphRendererScanlineMSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRendererScanline3MSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRendererScanlineLSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - -extern _X_EXPORT void -XAATEGlyphRendererScanline3LSBFirst ( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, int skipleft, int startline, - unsigned int **glyphs, int glyphWidth, - int fg, int bg, int rop, unsigned planemask -); - - -extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncMSBFirstFixedBase[32])( - CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width -); - -extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncMSBFirst[32])( - CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width -); - -extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncLSBFirstFixedBase[32])( - CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width -); - -extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncLSBFirst[32])( - CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width -); - -extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncMSBFirstFixedBase(void); -extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncMSBFirst(void); -extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncLSBFirstFixedBase(void); -extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncLSBFirst(void); - -extern _X_EXPORT void -XAAFillColorExpandRectsLSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandRects3LSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandRectsLSBFirstFixedBase( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandRects3LSBFirstFixedBase( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandRectsMSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandRects3MSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandRectsMSBFirstFixedBase( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandRects3MSBFirstFixedBase( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillScanlineColorExpandRectsLSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillScanlineColorExpandRects3LSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillScanlineColorExpandRectsMSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillScanlineColorExpandRects3MSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int nBox, - BoxPtr pBox, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandSpansLSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandSpans3LSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandSpansLSBFirstFixedBase( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandSpans3LSBFirstFixedBase( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandSpansMSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandSpans3MSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandSpansMSBFirstFixedBase( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillColorExpandSpans3MSBFirstFixedBase( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillScanlineColorExpandSpansLSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillScanlineColorExpandSpans3LSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAPutImage( - DrawablePtr pDraw, - GCPtr pGC, - int depth, - int x, - int y, - int w, - int h, - int leftPad, - int format, - char *pImage -); - -extern _X_EXPORT void -XAAFillScanlineColorExpandSpansMSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillScanlineColorExpandSpans3MSBFirst( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - - -extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncMSBFirstFixedBase[6])( - CARD32* base, CARD32* src, int offset, int width, int dwords -); - -extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncMSBFirst[6])( - CARD32* base, CARD32* src, int offset, int width, int dwords -); - -extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncLSBFirstFixedBase[6])( - CARD32* base, CARD32* src, int offset, int width, int dwords -); - -extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncLSBFirst[6])( - CARD32* base, CARD32* src, int offset, int width, int dwords -); - -extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFuncMSBFirstFixedBase(void); -extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFuncMSBFirst(void); -extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFuncLSBFirstFixedBase(void); -extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFuncLSBFirst(void); -extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFunc3MSBFirstFixedBase(void); -extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFunc3MSBFirst(void); -extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFunc3LSBFirstFixedBase(void); -extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFunc3LSBFirst(void); - -extern _X_EXPORT int -XAAPolyText8TEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars -); - -extern _X_EXPORT int -XAAPolyText16TEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars -); - -extern _X_EXPORT void -XAAImageText8TEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars -); - -extern _X_EXPORT void -XAAImageText16TEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars -); - -extern _X_EXPORT void -XAAImageGlyphBltTEColorExpansion( - DrawablePtr pDrawable, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -); - -extern _X_EXPORT void -XAAPolyGlyphBltTEColorExpansion( - DrawablePtr pDrawable, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -); - - -extern _X_EXPORT int -XAAPolyText8NonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars -); - -extern _X_EXPORT int -XAAPolyText16NonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars -); - -extern _X_EXPORT void -XAAImageText8NonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - char *chars -); - -extern _X_EXPORT void -XAAImageText16NonTEColorExpansion( - DrawablePtr pDraw, - GCPtr pGC, - int x, int y, - int count, - unsigned short *chars -); - -extern _X_EXPORT void -XAAImageGlyphBltNonTEColorExpansion( - DrawablePtr pDrawable, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -); - -extern _X_EXPORT void -XAAPolyGlyphBltNonTEColorExpansion( - DrawablePtr pDrawable, - GCPtr pGC, - int xInit, int yInit, - unsigned int nglyph, - CharInfoPtr *ppci, - pointer pglyphBase -); - - -extern _X_EXPORT void XAANonTEGlyphRenderer( - ScrnInfoPtr pScrn, - int x, int y, int n, - NonTEGlyphPtr glyphs, - BoxPtr pbox, - int fg, int rop, - unsigned int planemask -); - -extern _X_EXPORT void -XAAFillSolidSpans( - ScrnInfoPtr pScrn, - int fg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, int fSorted -); - -extern _X_EXPORT void -XAAFillMono8x8PatternSpans( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, int fSorted, - int patx, int paty, - int xorg, int yorg -); - -extern _X_EXPORT void -XAAFillMono8x8PatternSpansScreenOrigin( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, int fSorted, - int patx, int paty, - int xorg, int yorg -); - -extern _X_EXPORT void -XAAFillColor8x8PatternSpansScreenOrigin( - ScrnInfoPtr pScrn, - int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, int fSorted, - XAACacheInfoPtr, - int xorigin, int yorigin -); - -extern _X_EXPORT void -XAAFillColor8x8PatternSpans( - ScrnInfoPtr pScrn, - int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, int fSorted, - XAACacheInfoPtr, - int xorigin, int yorigin -); - -extern _X_EXPORT void -XAAFillCacheBltSpans( - ScrnInfoPtr pScrn, - int rop, - unsigned int planemask, - int n, - DDXPointPtr points, - int *widths, - int fSorted, - XAACacheInfoPtr pCache, - int xorg, int yorg -); - -extern _X_EXPORT void -XAAFillCacheExpandSpans( - ScrnInfoPtr pScrn, - int fg, int bg, int rop, - unsigned int planemask, - int n, - DDXPointPtr ppt, - int *pwidth, - int fSorted, - int xorg, int yorg, - PixmapPtr pPix -); - -extern _X_EXPORT void -XAAFillSpans( - DrawablePtr pDrawable, - GC *pGC, - int nInit, - DDXPointPtr pptInit, - int *pwidth, - int fSorted -); - - -extern _X_EXPORT void -XAAInitPixmapCache( - ScreenPtr pScreen, - RegionPtr areas, - pointer data -); - -extern _X_EXPORT void -XAAWriteBitmapToCache( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int fg, int bg -); - -extern _X_EXPORT void -XAAWriteBitmapToCacheLinear( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int fg, int bg -); - -extern _X_EXPORT void -XAAWritePixmapToCache( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int bpp, int depth -); - -extern _X_EXPORT void -XAAWritePixmapToCacheLinear( - ScrnInfoPtr pScrn, - int x, int y, int w, int h, - unsigned char *src, - int srcwidth, - int bpp, int depth -); - -extern _X_EXPORT void -XAASolidHorVertLineAsRects( - ScrnInfoPtr pScrn, - int x, int y, int len, int dir -); - -extern _X_EXPORT void -XAASolidHorVertLineAsTwoPoint( - ScrnInfoPtr pScrn, - int x, int y, int len, int dir -); - -extern _X_EXPORT void -XAASolidHorVertLineAsBresenham( - ScrnInfoPtr pScrn, - int x, int y, int len, int dir -); - - -extern _X_EXPORT void -XAAPolyRectangleThinSolid( - DrawablePtr pDrawable, - GCPtr pGC, - int nRectsInit, - xRectangle *pRectsInit -); - - -extern _X_EXPORT void -XAAPolylinesWideSolid ( - DrawablePtr pDrawable, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr pPts -); - -extern _X_EXPORT void -XAAFillPolygonSolid( - DrawablePtr pDrawable, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn -); - -extern _X_EXPORT void -XAAFillPolygonStippled( - DrawablePtr pDrawable, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn -); - - -extern _X_EXPORT void -XAAFillPolygonTiled( - DrawablePtr pDrawable, - GCPtr pGC, - int shape, - int mode, - int count, - DDXPointPtr ptsIn -); - - -extern _X_EXPORT int -XAAIsEasyPolygon( - DDXPointPtr ptsIn, - int count, - BoxPtr extents, - int origin, - DDXPointPtr *topPoint, - int *topY, int *bottomY, - int shape -); - -extern _X_EXPORT void -XAAFillPolygonHelper( - ScrnInfoPtr pScrn, - DDXPointPtr ptsIn, - int count, - DDXPointPtr topPoint, - int y, - int maxy, - int origin, - RectFuncPtr RectFunc, - TrapFuncPtr TrapFunc, - int xorg, - int yorg, - XAACacheInfoPtr pCache -); - -extern _X_EXPORT void -XAAPolySegment( - DrawablePtr pDrawable, - GCPtr pGC, - int nseg, - xSegment *pSeg -); - -extern _X_EXPORT void -XAAPolyLines( - DrawablePtr pDrawable, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr pptInit -); - -extern _X_EXPORT void -XAAPolySegmentDashed( - DrawablePtr pDrawable, - GCPtr pGC, - int nseg, - xSegment *pSeg -); - -extern _X_EXPORT void -XAAPolyLinesDashed( - DrawablePtr pDrawable, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr pptInit -); - - -extern _X_EXPORT void -XAAWriteMono8x8PatternToCache(ScrnInfoPtr pScrn, XAACacheInfoPtr pCache); - -extern _X_EXPORT void -XAAWriteColor8x8PatternToCache( - ScrnInfoPtr pScrn, - PixmapPtr pPix, - XAACacheInfoPtr pCache -); - -extern _X_EXPORT void -XAARotateMonoPattern( - int *pat0, int *pat1, - int xoffset, int yoffset, - Bool msbfirst -); - -extern _X_EXPORT void XAAComputeDash(GCPtr pGC); - -extern _X_EXPORT void XAAMoveDWORDS_FixedBase( - register CARD32* dest, - register CARD32* src, - register int dwords -); - -extern _X_EXPORT void XAAMoveDWORDS_FixedSrc( - register CARD32* dest, - register CARD32* src, - register int dwords -); - -extern _X_EXPORT void XAAMoveDWORDS( - register CARD32* dest, - register CARD32* src, - register int dwords -); - -extern _X_EXPORT int -XAAGetRectClipBoxes( - GCPtr pGC, - BoxPtr pboxClippedBase, - int nrectFill, - xRectangle *prectInit -); - -extern _X_EXPORT void -XAASetupOverlay8_32Planar(ScreenPtr); - -extern _X_EXPORT void -XAAPolyFillArcSolid(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs); - -extern _X_EXPORT XAACacheInfoPtr -XAACacheTile(ScrnInfoPtr Scrn, PixmapPtr pPix); - -extern _X_EXPORT XAACacheInfoPtr -XAACacheMonoStipple(ScrnInfoPtr Scrn, PixmapPtr pPix); - -extern _X_EXPORT XAACacheInfoPtr -XAACachePlanarMonoStipple(ScrnInfoPtr Scrn, PixmapPtr pPix); - -typedef XAACacheInfoPtr (*XAACachePlanarMonoStippleProc)(ScrnInfoPtr, PixmapPtr); -extern _X_EXPORT XAACachePlanarMonoStippleProc XAAGetCachePlanarMonoStipple(void); - -extern _X_EXPORT XAACacheInfoPtr -XAACacheStipple(ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, int bg); - -extern _X_EXPORT XAACacheInfoPtr -XAACacheMono8x8Pattern(ScrnInfoPtr Scrn, int pat0, int pat1); - -extern _X_EXPORT XAACacheInfoPtr -XAACacheColor8x8Pattern(ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, int bg); - -extern _X_EXPORT void -XAATileCache(ScrnInfoPtr pScrn, XAACacheInfoPtr pCache, int w, int h); - -extern _X_EXPORT void XAAClosePixmapCache(ScreenPtr pScreen); -void XAAInvalidatePixmapCache(ScreenPtr pScreen); - -extern _X_EXPORT Bool XAACheckStippleReducibility(PixmapPtr pPixmap); -extern _X_EXPORT Bool XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono); - -extern _X_EXPORT int XAAStippledFillChooser(GCPtr pGC); -extern _X_EXPORT int XAAOpaqueStippledFillChooser(GCPtr pGC); -extern _X_EXPORT int XAATiledFillChooser(GCPtr pGC); - -extern _X_EXPORT void XAAMoveInOffscreenPixmaps(ScreenPtr pScreen); -extern _X_EXPORT void XAAMoveOutOffscreenPixmaps(ScreenPtr pScreen); -extern _X_EXPORT void XAARemoveAreaCallback(FBAreaPtr area); -extern _X_EXPORT void XAAMoveOutOffscreenPixmap(PixmapPtr pPix); -extern _X_EXPORT Bool XAAInitStateWrap(ScreenPtr pScreen, XAAInfoRecPtr infoRec); - -extern _X_EXPORT void -XAAComposite (CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - - -extern _X_EXPORT Bool -XAADoComposite (CARD8 op, - PicturePtr pSrc, - PicturePtr pMask, - PicturePtr pDst, - INT16 xSrc, - INT16 ySrc, - INT16 xMask, - INT16 yMask, - INT16 xDst, - INT16 yDst, - CARD16 width, - CARD16 height); - - -extern _X_EXPORT void -XAAGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs); - -extern _X_EXPORT Bool -XAADoGlyphs (CARD8 op, - PicturePtr pSrc, - PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, - INT16 ySrc, - int nlist, - GlyphListPtr list, - GlyphPtr *glyphs); - - - -/* helpers */ -extern _X_EXPORT void -XAA_888_plus_PICT_a8_to_8888 ( - CARD32 color, - CARD8 *alphaPtr, /* in bytes */ - int alphaPitch, - CARD32 *dstPtr, - int dstPitch, /* in dwords */ - int width, - int height -); - -extern _X_EXPORT Bool -XAAGetRGBAFromPixel( - CARD32 pixel, - CARD16 *red, - CARD16 *green, - CARD16 *blue, - CARD16 *alpha, - CARD32 format -); - - -extern _X_EXPORT Bool -XAAGetPixelFromRGBA ( - CARD32 *pixel, - CARD16 red, - CARD16 green, - CARD16 blue, - CARD16 alpha, - CARD32 format -); - -/* XXX should be static */ -extern _X_EXPORT GCOps XAAFallbackOps; -extern _X_EXPORT GCOps *XAAGetFallbackOps(void); -extern _X_EXPORT GCFuncs XAAGCFuncs; -extern _X_EXPORT DevPrivateKey XAAGetScreenKey(void); -extern _X_EXPORT DevPrivateKey XAAGetGCKey(void); -extern _X_EXPORT DevPrivateKey XAAGetPixmapKey(void); - -extern _X_EXPORT unsigned int XAAShiftMasks[32]; - -extern _X_EXPORT unsigned int byte_expand3[256], byte_reversed_expand3[256]; - -extern _X_EXPORT CARD32 XAAReverseBitOrder(CARD32 data); - -#define GET_XAASCREENPTR_FROM_SCREEN(pScreen)\ - dixLookupPrivate(&(pScreen)->devPrivates, XAAGetScreenKey()) - -#define GET_XAASCREENPTR_FROM_GC(pGC)\ - dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAGetScreenKey()) - -#define GET_XAASCREENPTR_FROM_DRAWABLE(pDraw)\ - dixLookupPrivate(&(pDraw)->pScreen->devPrivates, XAAGetScreenKey()) - -#define GET_XAAINFORECPTR_FROM_SCREEN(pScreen)\ -((XAAScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAGetScreenKey()))->AccelInfoRec - -#define GET_XAAINFORECPTR_FROM_GC(pGC)\ -((XAAScreenPtr)dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec - -#define GET_XAAINFORECPTR_FROM_DRAWABLE(pDraw)\ -((XAAScreenPtr)dixLookupPrivate(&(pDraw)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec - -#define GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn)\ -((XAAScreenPtr)dixLookupPrivate(&(pScrn)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec - -#define XAA_GET_PIXMAP_PRIVATE(pix)\ - (XAAPixmapPtr)dixLookupPrivate(&(pix)->devPrivates, XAAGetPixmapKey()) - -#define CHECK_RGB_EQUAL(c) (!((((c) >> 8) ^ (c)) & 0xffff)) - -#define CHECK_FG(pGC, flags) \ - (!(flags & RGB_EQUAL) || CHECK_RGB_EQUAL(pGC->fgPixel)) - -#define CHECK_BG(pGC, flags) \ - (!(flags & RGB_EQUAL) || CHECK_RGB_EQUAL(pGC->bgPixel)) - -#define CHECK_ROP(pGC, flags) \ - (!(flags & GXCOPY_ONLY) || (pGC->alu == GXcopy)) - -#define CHECK_ROPSRC(pGC, flags) \ - (!(flags & ROP_NEEDS_SOURCE) || ((pGC->alu != GXclear) && \ - (pGC->alu != GXnoop) && (pGC->alu != GXinvert) && \ - (pGC->alu != GXset))) - -#define CHECK_PLANEMASK(pGC, flags) \ - (!(flags & NO_PLANEMASK) || \ - ((pGC->planemask & infoRec->FullPlanemasks[pGC->depth - 1]) == \ - infoRec->FullPlanemasks[pGC->depth - 1])) - -#define CHECK_COLORS(pGC, flags) \ - (!(flags & RGB_EQUAL) || \ - (CHECK_RGB_EQUAL(pGC->fgPixel) && CHECK_RGB_EQUAL(pGC->bgPixel))) - -#define CHECK_NO_GXCOPY(pGC, flags) \ - ((pGC->alu != GXcopy) || !(flags & NO_GXCOPY) || \ - ((pGC->planemask & infoRec->FullPlanemask) != infoRec->FullPlanemask)) - -#define IS_OFFSCREEN_PIXMAP(pPix)\ - ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->offscreenArea) - -#define PIXMAP_IS_SHARED(pPix)\ - ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->flags & SHARED_PIXMAP) - -#define OFFSCREEN_PIXMAP_LOCKED(pPix)\ - ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->flags & LOCKED_PIXMAP) - -#define XAA_DEPTH_BUG(pGC) \ - ((pGC->depth == 32) && (pGC->bgPixel == 0xffffffff)) - -#define DELIST_OFFSCREEN_PIXMAP(pPix) { \ - PixmapLinkPtr _pLink, _prev; \ - _pLink = infoRec->OffscreenPixmaps; \ - _prev = NULL; \ - while(_pLink) { \ - if(_pLink->pPix == pPix) { \ - if(_prev) _prev->next = _pLink->next; \ - else infoRec->OffscreenPixmaps = _pLink->next; \ - xfree(_pLink); \ - break; \ - } \ - _prev = _pLink; \ - _pLink = _pLink->next; \ - }} - - -#define SWAP_BITS_IN_BYTES(v) \ - (((0x01010101 & (v)) << 7) | ((0x02020202 & (v)) << 5) | \ - ((0x04040404 & (v)) << 3) | ((0x08080808 & (v)) << 1) | \ - ((0x10101010 & (v)) >> 1) | ((0x20202020 & (v)) >> 3) | \ - ((0x40404040 & (v)) >> 5) | ((0x80808080 & (v)) >> 7)) - -/* - * Moved XAAPixmapCachePrivate here from xaaPCache.c, since driver - * replacements for CacheMonoStipple need access to it - */ - -typedef struct { - int Num512x512; - int Current512; - XAACacheInfoPtr Info512; - int Num256x256; - int Current256; - XAACacheInfoPtr Info256; - int Num128x128; - int Current128; - XAACacheInfoPtr Info128; - int NumMono; - int CurrentMono; - XAACacheInfoPtr InfoMono; - int NumColor; - int CurrentColor; - XAACacheInfoPtr InfoColor; - int NumPartial; - int CurrentPartial; - XAACacheInfoPtr InfoPartial; - DDXPointRec MonoOffsets[64]; - DDXPointRec ColorOffsets[64]; -} XAAPixmapCachePrivate, *XAAPixmapCachePrivatePtr; - - -#endif /* _XAALOCAL_H */ + +#ifndef _XAALOCAL_H +#define _XAALOCAL_H + +/* This file is very unorganized ! */ + + +#include "gcstruct.h" +#include "regionstr.h" +#include "xf86fbman.h" +#include "xaa.h" +#include "mi.h" +#include "picturestr.h" + +#define GCWhenForced (GCArcMode << 1) + +#define DO_COLOR_8x8 0x00000001 +#define DO_MONO_8x8 0x00000002 +#define DO_CACHE_BLT 0x00000003 +#define DO_COLOR_EXPAND 0x00000004 +#define DO_CACHE_EXPAND 0x00000005 +#define DO_IMAGE_WRITE 0x00000006 +#define DO_PIXMAP_COPY 0x00000007 +#define DO_SOLID 0x00000008 + + +typedef CARD32 * (*GlyphScanlineFuncPtr)( + CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width +); + +typedef CARD32 *(*StippleScanlineProcPtr)(CARD32*, CARD32*, int, int, int); + +typedef void (*RectFuncPtr) (ScrnInfoPtr, int, int, int, int, int, int, + XAACacheInfoPtr); +typedef void (*TrapFuncPtr) (ScrnInfoPtr, int, int, int, int, int, int, + int, int, int, int, int, int, + XAACacheInfoPtr); + + + +typedef struct _XAAScreen { + CreateGCProcPtr CreateGC; + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + CopyWindowProcPtr CopyWindow; + WindowExposuresProcPtr WindowExposures; + CreatePixmapProcPtr CreatePixmap; + DestroyPixmapProcPtr DestroyPixmap; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + XAAInfoRecPtr AccelInfoRec; + Bool (*EnterVT)(int, int); + void (*LeaveVT)(int, int); + int (*SetDGAMode)(int, int, DGADevicePtr); + void (*EnableDisableFBAccess)(int, Bool); + CompositeProcPtr Composite; + GlyphsProcPtr Glyphs; +} XAAScreenRec, *XAAScreenPtr; + +#define OPS_ARE_PIXMAP 0x00000001 +#define OPS_ARE_ACCEL 0x00000002 + +typedef struct _XAAGC { + GCOps *wrapOps; + GCFuncs *wrapFuncs; + GCOps *XAAOps; + int DashLength; + unsigned char* DashPattern; + unsigned long changes; + unsigned long flags; +} XAAGCRec, *XAAGCPtr; + +#define REDUCIBILITY_CHECKED 0x00000001 +#define REDUCIBLE_TO_8x8 0x00000002 +#define REDUCIBLE_TO_2_COLOR 0x00000004 +#define DIRTY 0x00010000 +#define OFFSCREEN 0x00020000 +#define DGA_PIXMAP 0x00040000 +#define SHARED_PIXMAP 0x00080000 +#define LOCKED_PIXMAP 0x00100000 + +#define REDUCIBILITY_MASK \ + (REDUCIBILITY_CHECKED | REDUCIBLE_TO_8x8 | REDUCIBLE_TO_2_COLOR) + +typedef struct _XAAPixmap { + unsigned long flags; + CARD32 pattern0; + CARD32 pattern1; + int fg; + int bg; + FBAreaPtr offscreenArea; + Bool freeData; +} XAAPixmapRec, *XAAPixmapPtr; + + +extern _X_EXPORT Bool +XAACreateGC( + GCPtr pGC +); + +extern _X_EXPORT Bool +XAAInitAccel( + ScreenPtr pScreen, + XAAInfoRecPtr infoRec +); + +extern _X_EXPORT RegionPtr +XAABitBlt( + DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC *pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + void (*doBitBlt)(DrawablePtr, DrawablePtr, GCPtr, RegionPtr, DDXPointPtr), + unsigned long bitPlane +); + +extern _X_EXPORT void +XAAScreenToScreenBitBlt( + ScrnInfoPtr pScrn, + int nbox, + DDXPointPtr pptSrc, + BoxPtr pbox, + int xdir, + int ydir, + int alu, + unsigned int planemask +); + +extern _X_EXPORT void +XAADoBitBlt( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + RegionPtr prgnDst, + DDXPointPtr pptSrc +); + +extern _X_EXPORT void +XAADoImageWrite( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + RegionPtr prgnDst, + DDXPointPtr pptSrc +); + +extern _X_EXPORT void +XAADoImageRead( + DrawablePtr pSrc, + DrawablePtr pDst, + GC *pGC, + RegionPtr prgnDst, + DDXPointPtr pptSrc +); + +extern _X_EXPORT void +XAACopyWindow( + WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc +); + + +extern _X_EXPORT RegionPtr +XAACopyArea( + DrawablePtr pSrcDrawable, + DrawablePtr pDstDrawable, + GC *pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty +); + +extern _X_EXPORT void +XAAValidateCopyArea( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +); + +extern _X_EXPORT void +XAAValidatePutImage( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +); + +extern _X_EXPORT void +XAAValidateCopyPlane( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +); + +extern _X_EXPORT void +XAAValidatePushPixels( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +); + +extern _X_EXPORT void +XAAValidateFillSpans( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +); + +extern _X_EXPORT void +XAAValidatePolyGlyphBlt( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +); + +extern _X_EXPORT void +XAAValidateImageGlyphBlt( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +); + +extern _X_EXPORT void +XAAValidatePolylines( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +); + + +extern _X_EXPORT RegionPtr +XAACopyPlaneColorExpansion( + DrawablePtr pSrc, + DrawablePtr pDst, + GCPtr pGC, + int srcx, + int srcy, + int width, + int height, + int dstx, + int dsty, + unsigned long bitPlane +); + + +extern _X_EXPORT void +XAAPushPixelsSolidColorExpansion( + GCPtr pGC, + PixmapPtr pBitMap, + DrawablePtr pDrawable, + int dx, + int dy, + int xOrg, + int yOrg +); + +extern _X_EXPORT void +XAAWriteBitmapColorExpandMSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapColorExpand3MSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapColorExpandMSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapColorExpand3MSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapColorExpandLSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapColorExpand3LSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapColorExpandLSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapColorExpand3LSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + + +extern _X_EXPORT void +XAAWriteBitmapScanlineColorExpandMSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapScanlineColorExpand3MSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapScanlineColorExpandMSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapScanlineColorExpand3MSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapScanlineColorExpandLSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapScanlineColorExpand3LSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapScanlineColorExpandLSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWriteBitmapScanlineColorExpand3LSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int skipleft, + int fg, int bg, + int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAWritePixmap ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth +); + +extern _X_EXPORT void +XAAWritePixmapScanline ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int rop, + unsigned int planemask, + int transparency_color, + int bpp, int depth +); + +typedef void (*ClipAndRenderRectsFunc)(GCPtr, int, BoxPtr, int, int); + + +extern _X_EXPORT void +XAAClipAndRenderRects( + GCPtr pGC, + ClipAndRenderRectsFunc func, + int nrectFill, + xRectangle *prectInit, + int xorg, int yorg +); + + +typedef void (*ClipAndRenderSpansFunc)(GCPtr, int, DDXPointPtr, int*, + int, int, int); + +extern _X_EXPORT void +XAAClipAndRenderSpans( + GCPtr pGC, + DDXPointPtr ppt, + int *pwidth, + int nspans, + int fSorted, + ClipAndRenderSpansFunc func, + int xorg, + int yorg +); + + +extern _X_EXPORT void +XAAFillSolidRects( + ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox +); + +extern _X_EXPORT void +XAAFillMono8x8PatternRects( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int pat0, int pat1, + int xorg, int yorg +); + +extern _X_EXPORT void +XAAFillMono8x8PatternRectsScreenOrigin( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int pat0, int pat1, + int xorg, int yorg +); + + +extern _X_EXPORT void +XAAFillColor8x8PatternRectsScreenOrigin( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorigin, int yorigin, + XAACacheInfoPtr pCache +); + +extern _X_EXPORT void +XAAFillColor8x8PatternRects( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorigin, int yorigin, + XAACacheInfoPtr pCache +); + +extern _X_EXPORT void +XAAFillCacheBltRects( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + XAACacheInfoPtr pCache +); + +extern _X_EXPORT void +XAAFillCacheExpandRects( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillImageWriteRects( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAPolyFillRect( + DrawablePtr pDraw, + GCPtr pGC, + int nrectFill, + xRectangle *prectInit +); + + +extern _X_EXPORT void +XAATEGlyphRendererMSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRenderer3MSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRendererMSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRenderer3MSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRendererLSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + + +extern _X_EXPORT void +XAATEGlyphRenderer3LSBFirstFixedBase ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRendererLSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRenderer3LSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + + +extern _X_EXPORT void +XAATEGlyphRendererScanlineMSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRendererScanline3MSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRendererScanlineLSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + +extern _X_EXPORT void +XAATEGlyphRendererScanline3LSBFirst ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft, int startline, + unsigned int **glyphs, int glyphWidth, + int fg, int bg, int rop, unsigned planemask +); + + +extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncMSBFirstFixedBase[32])( + CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width +); + +extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncMSBFirst[32])( + CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width +); + +extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncLSBFirstFixedBase[32])( + CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width +); + +extern _X_EXPORT CARD32 *(*XAAGlyphScanlineFuncLSBFirst[32])( + CARD32 *base, unsigned int **glyphp, int line, int nglyph, int width +); + +extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncMSBFirstFixedBase(void); +extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncMSBFirst(void); +extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncLSBFirstFixedBase(void); +extern _X_EXPORT GlyphScanlineFuncPtr *XAAGetGlyphScanlineFuncLSBFirst(void); + +extern _X_EXPORT void +XAAFillColorExpandRectsLSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandRects3LSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandRectsLSBFirstFixedBase( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandRects3LSBFirstFixedBase( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandRectsMSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandRects3MSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandRectsMSBFirstFixedBase( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandRects3MSBFirstFixedBase( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillScanlineColorExpandRectsLSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillScanlineColorExpandRects3LSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillScanlineColorExpandRectsMSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillScanlineColorExpandRects3MSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int nBox, + BoxPtr pBox, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandSpansLSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandSpans3LSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandSpansLSBFirstFixedBase( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandSpans3LSBFirstFixedBase( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandSpansMSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandSpans3MSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandSpansMSBFirstFixedBase( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillColorExpandSpans3MSBFirstFixedBase( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillScanlineColorExpandSpansLSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillScanlineColorExpandSpans3LSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAPutImage( + DrawablePtr pDraw, + GCPtr pGC, + int depth, + int x, + int y, + int w, + int h, + int leftPad, + int format, + char *pImage +); + +extern _X_EXPORT void +XAAFillScanlineColorExpandSpansMSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillScanlineColorExpandSpans3MSBFirst( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + + +extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncMSBFirstFixedBase[6])( + CARD32* base, CARD32* src, int offset, int width, int dwords +); + +extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncMSBFirst[6])( + CARD32* base, CARD32* src, int offset, int width, int dwords +); + +extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncLSBFirstFixedBase[6])( + CARD32* base, CARD32* src, int offset, int width, int dwords +); + +extern _X_EXPORT CARD32 *(*XAAStippleScanlineFuncLSBFirst[6])( + CARD32* base, CARD32* src, int offset, int width, int dwords +); + +extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFuncMSBFirstFixedBase(void); +extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFuncMSBFirst(void); +extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFuncLSBFirstFixedBase(void); +extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFuncLSBFirst(void); +extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFunc3MSBFirstFixedBase(void); +extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFunc3MSBFirst(void); +extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFunc3LSBFirstFixedBase(void); +extern _X_EXPORT StippleScanlineProcPtr *XAAGetStippleScanlineFunc3LSBFirst(void); + +extern _X_EXPORT int +XAAPolyText8TEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars +); + +extern _X_EXPORT int +XAAPolyText16TEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars +); + +extern _X_EXPORT void +XAAImageText8TEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars +); + +extern _X_EXPORT void +XAAImageText16TEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars +); + +extern _X_EXPORT void +XAAImageGlyphBltTEColorExpansion( + DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +); + +extern _X_EXPORT void +XAAPolyGlyphBltTEColorExpansion( + DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +); + + +extern _X_EXPORT int +XAAPolyText8NonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars +); + +extern _X_EXPORT int +XAAPolyText16NonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars +); + +extern _X_EXPORT void +XAAImageText8NonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + char *chars +); + +extern _X_EXPORT void +XAAImageText16NonTEColorExpansion( + DrawablePtr pDraw, + GCPtr pGC, + int x, int y, + int count, + unsigned short *chars +); + +extern _X_EXPORT void +XAAImageGlyphBltNonTEColorExpansion( + DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +); + +extern _X_EXPORT void +XAAPolyGlyphBltNonTEColorExpansion( + DrawablePtr pDrawable, + GCPtr pGC, + int xInit, int yInit, + unsigned int nglyph, + CharInfoPtr *ppci, + pointer pglyphBase +); + + +extern _X_EXPORT void XAANonTEGlyphRenderer( + ScrnInfoPtr pScrn, + int x, int y, int n, + NonTEGlyphPtr glyphs, + BoxPtr pbox, + int fg, int rop, + unsigned int planemask +); + +extern _X_EXPORT void +XAAFillSolidSpans( + ScrnInfoPtr pScrn, + int fg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted +); + +extern _X_EXPORT void +XAAFillMono8x8PatternSpans( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + int patx, int paty, + int xorg, int yorg +); + +extern _X_EXPORT void +XAAFillMono8x8PatternSpansScreenOrigin( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + int patx, int paty, + int xorg, int yorg +); + +extern _X_EXPORT void +XAAFillColor8x8PatternSpansScreenOrigin( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + XAACacheInfoPtr, + int xorigin, int yorigin +); + +extern _X_EXPORT void +XAAFillColor8x8PatternSpans( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, int fSorted, + XAACacheInfoPtr, + int xorigin, int yorigin +); + +extern _X_EXPORT void +XAAFillCacheBltSpans( + ScrnInfoPtr pScrn, + int rop, + unsigned int planemask, + int n, + DDXPointPtr points, + int *widths, + int fSorted, + XAACacheInfoPtr pCache, + int xorg, int yorg +); + +extern _X_EXPORT void +XAAFillCacheExpandSpans( + ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask, + int n, + DDXPointPtr ppt, + int *pwidth, + int fSorted, + int xorg, int yorg, + PixmapPtr pPix +); + +extern _X_EXPORT void +XAAFillSpans( + DrawablePtr pDrawable, + GC *pGC, + int nInit, + DDXPointPtr pptInit, + int *pwidth, + int fSorted +); + + +extern _X_EXPORT void +XAAInitPixmapCache( + ScreenPtr pScreen, + RegionPtr areas, + pointer data +); + +extern _X_EXPORT void +XAAWriteBitmapToCache( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int fg, int bg +); + +extern _X_EXPORT void +XAAWriteBitmapToCacheLinear( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int fg, int bg +); + +extern _X_EXPORT void +XAAWritePixmapToCache( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int bpp, int depth +); + +extern _X_EXPORT void +XAAWritePixmapToCacheLinear( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned char *src, + int srcwidth, + int bpp, int depth +); + +extern _X_EXPORT void +XAASolidHorVertLineAsRects( + ScrnInfoPtr pScrn, + int x, int y, int len, int dir +); + +extern _X_EXPORT void +XAASolidHorVertLineAsTwoPoint( + ScrnInfoPtr pScrn, + int x, int y, int len, int dir +); + +extern _X_EXPORT void +XAASolidHorVertLineAsBresenham( + ScrnInfoPtr pScrn, + int x, int y, int len, int dir +); + + +extern _X_EXPORT void +XAAPolyRectangleThinSolid( + DrawablePtr pDrawable, + GCPtr pGC, + int nRectsInit, + xRectangle *pRectsInit +); + + +extern _X_EXPORT void +XAAPolylinesWideSolid ( + DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pPts +); + +extern _X_EXPORT void +XAAFillPolygonSolid( + DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn +); + +extern _X_EXPORT void +XAAFillPolygonStippled( + DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn +); + + +extern _X_EXPORT void +XAAFillPolygonTiled( + DrawablePtr pDrawable, + GCPtr pGC, + int shape, + int mode, + int count, + DDXPointPtr ptsIn +); + + +extern _X_EXPORT int +XAAIsEasyPolygon( + DDXPointPtr ptsIn, + int count, + BoxPtr extents, + int origin, + DDXPointPtr *topPoint, + int *topY, int *bottomY, + int shape +); + +extern _X_EXPORT void +XAAFillPolygonHelper( + ScrnInfoPtr pScrn, + DDXPointPtr ptsIn, + int count, + DDXPointPtr topPoint, + int y, + int maxy, + int origin, + RectFuncPtr RectFunc, + TrapFuncPtr TrapFunc, + int xorg, + int yorg, + XAACacheInfoPtr pCache +); + +extern _X_EXPORT void +XAAPolySegment( + DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pSeg +); + +extern _X_EXPORT void +XAAPolyLines( + DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pptInit +); + +extern _X_EXPORT void +XAAPolySegmentDashed( + DrawablePtr pDrawable, + GCPtr pGC, + int nseg, + xSegment *pSeg +); + +extern _X_EXPORT void +XAAPolyLinesDashed( + DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr pptInit +); + + +extern _X_EXPORT void +XAAWriteMono8x8PatternToCache(ScrnInfoPtr pScrn, XAACacheInfoPtr pCache); + +extern _X_EXPORT void +XAAWriteColor8x8PatternToCache( + ScrnInfoPtr pScrn, + PixmapPtr pPix, + XAACacheInfoPtr pCache +); + +extern _X_EXPORT void +XAARotateMonoPattern( + int *pat0, int *pat1, + int xoffset, int yoffset, + Bool msbfirst +); + +extern _X_EXPORT void XAAComputeDash(GCPtr pGC); + +extern _X_EXPORT void XAAMoveDWORDS_FixedBase( + register CARD32* dest, + register CARD32* src, + register int dwords +); + +extern _X_EXPORT void XAAMoveDWORDS_FixedSrc( + register CARD32* dest, + register CARD32* src, + register int dwords +); + +extern _X_EXPORT void XAAMoveDWORDS( + register CARD32* dest, + register CARD32* src, + register int dwords +); + +extern _X_EXPORT int +XAAGetRectClipBoxes( + GCPtr pGC, + BoxPtr pboxClippedBase, + int nrectFill, + xRectangle *prectInit +); + +extern _X_EXPORT void +XAASetupOverlay8_32Planar(ScreenPtr); + +extern _X_EXPORT void +XAAPolyFillArcSolid(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheTile(ScrnInfoPtr Scrn, PixmapPtr pPix); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheMonoStipple(ScrnInfoPtr Scrn, PixmapPtr pPix); + +extern _X_EXPORT XAACacheInfoPtr +XAACachePlanarMonoStipple(ScrnInfoPtr Scrn, PixmapPtr pPix); + +typedef XAACacheInfoPtr (*XAACachePlanarMonoStippleProc)(ScrnInfoPtr, PixmapPtr); +extern _X_EXPORT XAACachePlanarMonoStippleProc XAAGetCachePlanarMonoStipple(void); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheStipple(ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, int bg); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheMono8x8Pattern(ScrnInfoPtr Scrn, int pat0, int pat1); + +extern _X_EXPORT XAACacheInfoPtr +XAACacheColor8x8Pattern(ScrnInfoPtr Scrn, PixmapPtr pPix, int fg, int bg); + +extern _X_EXPORT void +XAATileCache(ScrnInfoPtr pScrn, XAACacheInfoPtr pCache, int w, int h); + +extern _X_EXPORT void XAAClosePixmapCache(ScreenPtr pScreen); +void XAAInvalidatePixmapCache(ScreenPtr pScreen); + +extern _X_EXPORT Bool XAACheckStippleReducibility(PixmapPtr pPixmap); +extern _X_EXPORT Bool XAACheckTileReducibility(PixmapPtr pPixmap, Bool checkMono); + +extern _X_EXPORT int XAAStippledFillChooser(GCPtr pGC); +extern _X_EXPORT int XAAOpaqueStippledFillChooser(GCPtr pGC); +extern _X_EXPORT int XAATiledFillChooser(GCPtr pGC); + +extern _X_EXPORT void XAAMoveInOffscreenPixmaps(ScreenPtr pScreen); +extern _X_EXPORT void XAAMoveOutOffscreenPixmaps(ScreenPtr pScreen); +extern _X_EXPORT void XAARemoveAreaCallback(FBAreaPtr area); +extern _X_EXPORT void XAAMoveOutOffscreenPixmap(PixmapPtr pPix); +extern _X_EXPORT Bool XAAInitStateWrap(ScreenPtr pScreen, XAAInfoRecPtr infoRec); + +extern _X_EXPORT void +XAAComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + + +extern _X_EXPORT Bool +XAADoComposite (CARD8 op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); + + +extern _X_EXPORT void +XAAGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + +extern _X_EXPORT Bool +XAADoGlyphs (CARD8 op, + PicturePtr pSrc, + PicturePtr pDst, + PictFormatPtr maskFormat, + INT16 xSrc, + INT16 ySrc, + int nlist, + GlyphListPtr list, + GlyphPtr *glyphs); + + + +/* helpers */ +extern _X_EXPORT void +XAA_888_plus_PICT_a8_to_8888 ( + CARD32 color, + CARD8 *alphaPtr, /* in bytes */ + int alphaPitch, + CARD32 *dstPtr, + int dstPitch, /* in dwords */ + int width, + int height +); + +extern _X_EXPORT Bool +XAAGetRGBAFromPixel( + CARD32 pixel, + CARD16 *red, + CARD16 *green, + CARD16 *blue, + CARD16 *alpha, + CARD32 format +); + + +extern _X_EXPORT Bool +XAAGetPixelFromRGBA ( + CARD32 *pixel, + CARD16 red, + CARD16 green, + CARD16 blue, + CARD16 alpha, + CARD32 format +); + +/* XXX should be static */ +extern _X_EXPORT GCOps XAAFallbackOps; +extern _X_EXPORT GCOps *XAAGetFallbackOps(void); +extern _X_EXPORT GCFuncs XAAGCFuncs; +extern _X_EXPORT DevPrivateKey XAAGetScreenKey(void); +extern _X_EXPORT DevPrivateKey XAAGetGCKey(void); +extern _X_EXPORT DevPrivateKey XAAGetPixmapKey(void); + +extern _X_EXPORT unsigned int XAAShiftMasks[32]; + +extern _X_EXPORT unsigned int byte_expand3[256], byte_reversed_expand3[256]; + +extern _X_EXPORT CARD32 XAAReverseBitOrder(CARD32 data); + +#define GET_XAASCREENPTR_FROM_SCREEN(pScreen)\ + dixLookupPrivate(&(pScreen)->devPrivates, XAAGetScreenKey()) + +#define GET_XAASCREENPTR_FROM_GC(pGC)\ + dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAGetScreenKey()) + +#define GET_XAASCREENPTR_FROM_DRAWABLE(pDraw)\ + dixLookupPrivate(&(pDraw)->pScreen->devPrivates, XAAGetScreenKey()) + +#define GET_XAAINFORECPTR_FROM_SCREEN(pScreen)\ +((XAAScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XAAGetScreenKey()))->AccelInfoRec + +#define GET_XAAINFORECPTR_FROM_GC(pGC)\ +((XAAScreenPtr)dixLookupPrivate(&(pGC)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec + +#define GET_XAAINFORECPTR_FROM_DRAWABLE(pDraw)\ +((XAAScreenPtr)dixLookupPrivate(&(pDraw)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec + +#define GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn)\ +((XAAScreenPtr)dixLookupPrivate(&(pScrn)->pScreen->devPrivates, XAAGetScreenKey()))->AccelInfoRec + +#define XAA_GET_PIXMAP_PRIVATE(pix)\ + (XAAPixmapPtr)dixLookupPrivate(&(pix)->devPrivates, XAAGetPixmapKey()) + +#define CHECK_RGB_EQUAL(c) (!((((c) >> 8) ^ (c)) & 0xffff)) + +#define CHECK_FG(pGC, flags) \ + (!(flags & RGB_EQUAL) || CHECK_RGB_EQUAL(pGC->fgPixel)) + +#define CHECK_BG(pGC, flags) \ + (!(flags & RGB_EQUAL) || CHECK_RGB_EQUAL(pGC->bgPixel)) + +#define CHECK_ROP(pGC, flags) \ + (!(flags & GXCOPY_ONLY) || (pGC->alu == GXcopy)) + +#define CHECK_ROPSRC(pGC, flags) \ + (!(flags & ROP_NEEDS_SOURCE) || ((pGC->alu != GXclear) && \ + (pGC->alu != GXnoop) && (pGC->alu != GXinvert) && \ + (pGC->alu != GXset))) + +#define CHECK_PLANEMASK(pGC, flags) \ + (!(flags & NO_PLANEMASK) || \ + ((pGC->planemask & infoRec->FullPlanemasks[pGC->depth - 1]) == \ + infoRec->FullPlanemasks[pGC->depth - 1])) + +#define CHECK_COLORS(pGC, flags) \ + (!(flags & RGB_EQUAL) || \ + (CHECK_RGB_EQUAL(pGC->fgPixel) && CHECK_RGB_EQUAL(pGC->bgPixel))) + +#define CHECK_NO_GXCOPY(pGC, flags) \ + ((pGC->alu != GXcopy) || !(flags & NO_GXCOPY) || \ + ((pGC->planemask & infoRec->FullPlanemask) != infoRec->FullPlanemask)) + +#define IS_OFFSCREEN_PIXMAP(pPix)\ + ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->offscreenArea) + +#define PIXMAP_IS_SHARED(pPix)\ + ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->flags & SHARED_PIXMAP) + +#define OFFSCREEN_PIXMAP_LOCKED(pPix)\ + ((XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pPix)))->flags & LOCKED_PIXMAP) + +#define XAA_DEPTH_BUG(pGC) \ + ((pGC->depth == 32) && (pGC->bgPixel == 0xffffffff)) + +#define DELIST_OFFSCREEN_PIXMAP(pPix) { \ + PixmapLinkPtr _pLink, _prev; \ + _pLink = infoRec->OffscreenPixmaps; \ + _prev = NULL; \ + while(_pLink) { \ + if(_pLink->pPix == pPix) { \ + if(_prev) _prev->next = _pLink->next; \ + else infoRec->OffscreenPixmaps = _pLink->next; \ + free(_pLink); \ + break; \ + } \ + _prev = _pLink; \ + _pLink = _pLink->next; \ + }} + + +#define SWAP_BITS_IN_BYTES(v) \ + (((0x01010101 & (v)) << 7) | ((0x02020202 & (v)) << 5) | \ + ((0x04040404 & (v)) << 3) | ((0x08080808 & (v)) << 1) | \ + ((0x10101010 & (v)) >> 1) | ((0x20202020 & (v)) >> 3) | \ + ((0x40404040 & (v)) >> 5) | ((0x80808080 & (v)) >> 7)) + +/* + * Moved XAAPixmapCachePrivate here from xaaPCache.c, since driver + * replacements for CacheMonoStipple need access to it + */ + +typedef struct { + int Num512x512; + int Current512; + XAACacheInfoPtr Info512; + int Num256x256; + int Current256; + XAACacheInfoPtr Info256; + int Num128x128; + int Current128; + XAACacheInfoPtr Info128; + int NumMono; + int CurrentMono; + XAACacheInfoPtr InfoMono; + int NumColor; + int CurrentColor; + XAACacheInfoPtr InfoColor; + int NumPartial; + int CurrentPartial; + XAACacheInfoPtr InfoPartial; + DDXPointRec MonoOffsets[64]; + DDXPointRec ColorOffsets[64]; +} XAAPixmapCachePrivate, *XAAPixmapCachePrivatePtr; + + +#endif /* _XAALOCAL_H */ -- cgit v1.2.3