From 1c94119ae26b94a60bb2c2b33494ed43c3b8a52f Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 16 May 2010 20:50:58 +0000 Subject: svn merge -r588:HEAD ^/branches/released . --- xorg-server/hw/dmx/dmx.c | 2254 +++--- xorg-server/hw/dmx/dmx_glxvisuals.c | 1202 ++-- xorg-server/hw/dmx/dmxcmap.c | 424 +- xorg-server/hw/dmx/dmxcursor.c | 1970 +++--- xorg-server/hw/dmx/dmxfont.c | 1110 ++- xorg-server/hw/dmx/dmxgc.c | 842 +-- xorg-server/hw/dmx/dmxinit.c | 10 +- xorg-server/hw/dmx/dmxpict.c | 26 +- xorg-server/hw/dmx/dmxpixmap.c | 506 +- xorg-server/hw/dmx/dmxprop.c | 694 +- xorg-server/hw/dmx/dmxscrinit.c | 1048 +-- xorg-server/hw/dmx/dmxsync.c | 386 +- xorg-server/hw/dmx/dmxwindow.c | 2030 +++--- xorg-server/hw/dmx/doc/dmx.sgml | 5555 ++++++++------- xorg-server/hw/dmx/glxProxy/glxcmds.c | 7220 ++++++++++---------- xorg-server/hw/dmx/glxProxy/glxext.c | 1064 +-- xorg-server/hw/dmx/glxProxy/glxscreens.c | 754 +- xorg-server/hw/dmx/glxProxy/glxsingle.c | 2024 +++--- xorg-server/hw/dmx/glxProxy/glxswap.c | 1076 +-- xorg-server/hw/dmx/glxProxy/glxutil.c | 222 +- xorg-server/hw/dmx/glxProxy/glxvendor.c | 1164 ++-- xorg-server/hw/dmx/glxProxy/glxvisuals.c | 1078 +-- xorg-server/hw/dmx/glxProxy/unpack.h | 456 +- xorg-server/hw/dmx/input/dmxinputinit.c | 2622 +++---- xorg-server/hw/dmx/input/dmxmotion.c | 284 +- xorg-server/hw/dmx/input/lnx-keyboard.c | 1980 +++--- xorg-server/hw/dmx/input/usb-keyboard.c | 888 +-- xorg-server/hw/kdrive/ephyr/ephyr.c | 20 +- xorg-server/hw/kdrive/ephyr/ephyr_draw.c | 1047 ++- xorg-server/hw/kdrive/ephyr/ephyrdriext.c | 2858 ++++---- xorg-server/hw/kdrive/ephyr/ephyrglxext.c | 1446 ++-- xorg-server/hw/kdrive/ephyr/ephyrhostvideo.c | 2024 +++--- xorg-server/hw/kdrive/ephyr/ephyrvideo.c | 2546 +++---- xorg-server/hw/kdrive/fake/fake.c | 952 +-- xorg-server/hw/kdrive/fbdev/fbdev.c | 1652 ++--- xorg-server/hw/kdrive/linux/evdev.c | 1078 +-- xorg-server/hw/kdrive/linux/keyboard.c | 1530 ++--- xorg-server/hw/kdrive/linux/mouse.c | 2060 +++--- xorg-server/hw/kdrive/linux/tslib.c | 380 +- xorg-server/hw/kdrive/src/kcmap.c | 492 +- xorg-server/hw/kdrive/src/kdrive.c | 8 +- xorg-server/hw/kdrive/src/kinfo.c | 326 +- xorg-server/hw/kdrive/src/kinput.c | 24 +- xorg-server/hw/kdrive/src/kshadow.c | 162 +- xorg-server/hw/kdrive/src/kxv.c | 3814 +++++------ xorg-server/hw/vfb/InitOutput.c | 1946 +++--- 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 +++++----- xorg-server/hw/xnest/Color.c | 990 +-- xorg-server/hw/xnest/Cursor.c | 366 +- xorg-server/hw/xnest/Display.c | 386 +- xorg-server/hw/xnest/Font.c | 172 +- xorg-server/hw/xnest/GC.c | 678 +- xorg-server/hw/xnest/Keyboard.c | 514 +- xorg-server/hw/xnest/Pixmap.c | 282 +- xorg-server/hw/xnest/Screen.c | 841 ++- xorg-server/hw/xquartz/GL/glcontextmodes.c | 1100 +-- xorg-server/hw/xquartz/GL/indirect.c | 18 +- xorg-server/hw/xquartz/GL/visualConfigs.c | 570 +- xorg-server/hw/xquartz/applewm.c | 1492 ++-- xorg-server/hw/xquartz/darwin.c | 1816 ++--- xorg-server/hw/xquartz/pseudoramiX.c | 942 +-- xorg-server/hw/xquartz/quartz.c | 897 ++- xorg-server/hw/xquartz/xpr/appledri.c | 858 +-- xorg-server/hw/xquartz/xpr/dri.c | 1906 +++--- xorg-server/hw/xquartz/xpr/driWrap.c | 1094 +-- xorg-server/hw/xquartz/xpr/x-hook.c | 240 +- xorg-server/hw/xquartz/xpr/xprCursor.c | 836 +-- xorg-server/hw/xquartz/xpr/xprScreen.c | 4 +- xorg-server/hw/xwin/glx/indirect.c | 4928 ++++++------- xorg-server/hw/xwin/win.h | 2884 ++++---- xorg-server/hw/xwin/winauth.c | 4 +- xorg-server/hw/xwin/winconfig.c | 4 +- xorg-server/hw/xwin/windialogs.c | 2 +- xorg-server/hw/xwin/winerror.c | 340 +- xorg-server/hw/xwin/winvideo.c | 420 +- xorg-server/hw/xwin/winwindow.c | 1186 ++-- xorg-server/hw/xwin/winwindowswm.c | 26 +- 173 files changed, 119801 insertions(+), 119701 deletions(-) (limited to 'xorg-server/hw') diff --git a/xorg-server/hw/dmx/dmx.c b/xorg-server/hw/dmx/dmx.c index a1afe76cf..b201fb8a7 100644 --- a/xorg-server/hw/dmx/dmx.c +++ b/xorg-server/hw/dmx/dmx.c @@ -1,1127 +1,1127 @@ -/* - * Copyright 2002-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: - * Rickard E. (Rik) Faith - * - */ - -/** \file - * This file implements the server-side part of the DMX protocol. A - * vector of fucntions is provided at extension initialization time, so - * most all of the useful functions in this file are declared static and - * do not appear in the doxygen documentation. - * - * Much of the low-level work is done by functions in \a dmxextension.c - * - * Please see the Client-to-Server DMX Extension to the X Protocol - * document for details about the protocol. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "opaque.h" - -#include "dmxextension.h" -#include -#include -#include "protocol-versions.h" - -#ifdef PANORAMIX -#include "panoramiX.h" -extern unsigned long XRT_WINDOW; -extern int PanoramiXNumScreens; -#endif - -extern void DMXExtensionInit(void); - -static unsigned char DMXCode; - -static DISPATCH_PROC(ProcDMXDispatch); -static DISPATCH_PROC(ProcDMXQueryVersion); -static DISPATCH_PROC(ProcDMXSync); -static DISPATCH_PROC(ProcDMXForceWindowCreation); -static DISPATCH_PROC(ProcDMXGetScreenCount); -static DISPATCH_PROC(ProcDMXGetScreenAttributes); -static DISPATCH_PROC(ProcDMXChangeScreensAttributes); -static DISPATCH_PROC(ProcDMXAddScreen); -static DISPATCH_PROC(ProcDMXRemoveScreen); -static DISPATCH_PROC(ProcDMXGetWindowAttributes); -static DISPATCH_PROC(ProcDMXGetDesktopAttributes); -static DISPATCH_PROC(ProcDMXChangeDesktopAttributes); -static DISPATCH_PROC(ProcDMXGetInputCount); -static DISPATCH_PROC(ProcDMXGetInputAttributes); -static DISPATCH_PROC(ProcDMXAddInput); -static DISPATCH_PROC(ProcDMXRemoveInput); - -static DISPATCH_PROC(SProcDMXDispatch); -static DISPATCH_PROC(SProcDMXQueryVersion); -static DISPATCH_PROC(SProcDMXSync); -static DISPATCH_PROC(SProcDMXForceWindowCreation); -static DISPATCH_PROC(SProcDMXGetScreenCount); -static DISPATCH_PROC(SProcDMXGetScreenAttributes); -static DISPATCH_PROC(SProcDMXChangeScreensAttributes); -static DISPATCH_PROC(SProcDMXAddScreen); -static DISPATCH_PROC(SProcDMXRemoveScreen); -static DISPATCH_PROC(SProcDMXGetWindowAttributes); -static DISPATCH_PROC(SProcDMXGetDesktopAttributes); -static DISPATCH_PROC(SProcDMXChangeDesktopAttributes); -static DISPATCH_PROC(SProcDMXGetInputCount); -static DISPATCH_PROC(SProcDMXGetInputAttributes); -static DISPATCH_PROC(SProcDMXAddInput); -static DISPATCH_PROC(SProcDMXRemoveInput); - -static int _DMXXineramaActive(void) -{ -#ifdef PANORAMIX - return !noPanoramiXExtension; -#endif - return 0; -} - -/** Initialize the extension. */ -void DMXExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if ((extEntry = AddExtension(DMX_EXTENSION_NAME, 0, 0, - ProcDMXDispatch, SProcDMXDispatch, - NULL, StandardMinorOpcode))) - DMXCode = extEntry->base; -} - -static void dmxSetScreenAttribute(int bit, DMXScreenAttributesPtr attr, - CARD32 value) -{ - switch (1 << bit) { - case DMXScreenWindowWidth: attr->screenWindowWidth = value; break; - case DMXScreenWindowHeight: attr->screenWindowHeight = value; break; - case DMXScreenWindowXoffset: attr->screenWindowXoffset = value; break; - case DMXScreenWindowYoffset: attr->screenWindowYoffset = value; break; - case DMXRootWindowWidth: attr->rootWindowWidth = value; break; - case DMXRootWindowHeight: attr->rootWindowHeight = value; break; - case DMXRootWindowXoffset: attr->rootWindowXoffset = value; break; - case DMXRootWindowYoffset: attr->rootWindowYoffset = value; break; - case DMXRootWindowXorigin: attr->rootWindowXorigin = value; break; - case DMXRootWindowYorigin: attr->rootWindowYorigin = value; break; - } -} - -static int dmxFetchScreenAttributes(unsigned int mask, - DMXScreenAttributesPtr attr, - CARD32 *value_list) -{ - int i; - CARD32 *value = value_list; - int count = 0; - - for (i = 0; i < 32; i++) { - if (mask & (1 << i)) { - dmxSetScreenAttribute(i, attr, *value); - ++value; - ++count; - } - } - return count; -} - -static void dmxSetDesktopAttribute(int bit, DMXDesktopAttributesPtr attr, - CARD32 value) -{ - switch (1 << bit) { - case DMXDesktopWidth: attr->width = value; break; - case DMXDesktopHeight: attr->height = value; break; - case DMXDesktopShiftX: attr->shiftX = value; break; - case DMXDesktopShiftY: attr->shiftY = value; break; - } -} - -static int dmxFetchDesktopAttributes(unsigned int mask, - DMXDesktopAttributesPtr attr, - CARD32 *value_list) -{ - int i; - CARD32 *value = value_list; - int count = 0; - - for (i = 0; i < 32; i++) { - if (mask & (1 << i)) { - dmxSetDesktopAttribute(i, attr, *value); - ++value; - ++count; - } - } - return count; -} - -static void dmxSetInputAttribute(int bit, DMXInputAttributesPtr attr, - CARD32 value) -{ - switch (1 << bit) { - case DMXInputType: attr->inputType = value; break; - case DMXInputPhysicalScreen: attr->physicalScreen = value; break; - case DMXInputSendsCore: attr->sendsCore = !!value; break; - } -} - -static int dmxFetchInputAttributes(unsigned int mask, - DMXInputAttributesPtr attr, - CARD32 *value_list) -{ - int i; - CARD32 *value = value_list; - int count = 0; - - for (i = 0; i < 32; i++) { - if (mask & (1 << i)) { - dmxSetInputAttribute(i, attr, *value); - ++value; - ++count; - } - } - return count; -} - -static int ProcDMXQueryVersion(ClientPtr client) -{ - xDMXQueryVersionReply rep; - int n; - - REQUEST_SIZE_MATCH(xDMXQueryVersionReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.majorVersion = SERVER_DMX_MAJOR_VERSION; - rep.minorVersion = SERVER_DMX_MINOR_VERSION; - rep.patchVersion = SERVER_DMX_PATCH_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.majorVersion, n); - swapl(&rep.minorVersion, n); - swapl(&rep.patchVersion, n); - } - WriteToClient(client, sizeof(xDMXQueryVersionReply), (char *)&rep); - return client->noClientException; -} - -static int ProcDMXSync(ClientPtr client) -{ - xDMXSyncReply rep; - int n; - - REQUEST_SIZE_MATCH(xDMXSyncReq); - - dmxFlushPendingSyncs(); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.status = 0; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - } - WriteToClient(client, sizeof(xDMXSyncReply), (char *)&rep); - return client->noClientException; -} - -static int ProcDMXForceWindowCreation(ClientPtr client) -{ - xDMXForceWindowCreationReply rep; - REQUEST(xDMXForceWindowCreationReq); - WindowPtr pWin; - int n; - - REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq); - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - PanoramiXRes *win; - int i; - - if (!(win = SecurityLookupIDByType(client, stuff->window, XRT_WINDOW, - DixReadAccess))) - return -1; /* BadWindow */ - - FOR_NSCREENS(i) { - if (Success != dixLookupWindow(&pWin, win->info[i].id, client, - DixReadAccess)) - return -1; /* BadWindow */ - - dmxForceWindowCreation(pWin); - } - goto doreply; - } -#endif - - if (Success != dixLookupWindow(&pWin, stuff->window, client, - DixReadAccess)) - return -1; /* BadWindow */ - - dmxForceWindowCreation(pWin); - doreply: - dmxFlushPendingSyncs(); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.status = 0; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - } - WriteToClient(client, sizeof(xDMXForceWindowCreationReply), (char *)&rep); - return Success; -} - -static int ProcDMXGetScreenCount(ClientPtr client) -{ - xDMXGetScreenCountReply rep; - int n; - - REQUEST_SIZE_MATCH(xDMXGetScreenCountReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.screenCount = dmxGetNumScreens(); - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.screenCount, n); - } - WriteToClient(client, sizeof(xDMXGetScreenCountReply), (char *)&rep); - return client->noClientException; -} - -static int ProcDMXGetScreenAttributes(ClientPtr client) -{ - REQUEST(xDMXGetScreenAttributesReq); - xDMXGetScreenAttributesReply rep; - int n; - int length; - int paddedLength; - DMXScreenAttributesRec attr; - - REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq); - - if (stuff->physicalScreen < 0 - || stuff->physicalScreen >= dmxGetNumScreens()) return BadValue; - - if (!dmxGetScreenAttributes(stuff->physicalScreen, &attr)) - return BadValue; - - rep.logicalScreen = attr.logicalScreen; - rep.screenWindowWidth = attr.screenWindowWidth; - rep.screenWindowHeight = attr.screenWindowHeight; - rep.screenWindowXoffset = attr.screenWindowXoffset; - rep.screenWindowYoffset = attr.screenWindowYoffset; - rep.rootWindowWidth = attr.rootWindowWidth; - rep.rootWindowHeight = attr.rootWindowHeight; - rep.rootWindowXoffset = attr.rootWindowXoffset; - rep.rootWindowYoffset = attr.rootWindowYoffset; - rep.rootWindowXorigin = attr.rootWindowXorigin; - rep.rootWindowYorigin = attr.rootWindowYorigin; - - length = attr.displayName ? strlen(attr.displayName) : 0; - paddedLength = pad_to_int32(length); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = bytes_to_int32((sizeof(xDMXGetScreenAttributesReply) - sizeof(xGenericReply)) - + paddedLength); - rep.displayNameLength = length; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.displayNameLength, n); - swapl(&rep.logicalScreen, n); - swaps(&rep.screenWindowWidth, n); - swaps(&rep.screenWindowHeight, n); - swaps(&rep.screenWindowXoffset, n); - swaps(&rep.screenWindowYoffset, n); - swaps(&rep.rootWindowWidth, n); - swaps(&rep.rootWindowHeight, n); - swaps(&rep.rootWindowXoffset, n); - swaps(&rep.rootWindowYoffset, n); - swaps(&rep.rootWindowXorigin, n); - swaps(&rep.rootWindowYorigin, n); - } - WriteToClient(client, sizeof(xDMXGetScreenAttributesReply), (char *)&rep); - if (length) WriteToClient(client, length, (char *)attr.displayName); - return client->noClientException; -} - -static int ProcDMXChangeScreensAttributes(ClientPtr client) -{ - REQUEST(xDMXChangeScreensAttributesReq); - xDMXChangeScreensAttributesReply rep; - int n; - int status = DMX_BAD_XINERAMA; - unsigned int mask = 0; - unsigned int i; - CARD32 *screen_list; - CARD32 *mask_list; - CARD32 *value_list; - DMXScreenAttributesPtr attribs; - int errorScreen = 0; - unsigned int len; - int ones = 0; - - - REQUEST_AT_LEAST_SIZE(xDMXChangeScreensAttributesReq); - len = client->req_len - bytes_to_int32(sizeof(xDMXChangeScreensAttributesReq)); - if (len < stuff->screenCount + stuff->maskCount) - return BadLength; - - screen_list = (CARD32 *)(stuff + 1); - mask_list = &screen_list[stuff->screenCount]; - value_list = &mask_list[stuff->maskCount]; - - for (i = 0; i < stuff->maskCount; i++) ones += Ones(mask_list[i]); - if (len != stuff->screenCount + stuff->maskCount + ones) - return BadLength; - - if (!_DMXXineramaActive()) goto noxinerama; - - if (!(attribs = xalloc(stuff->screenCount * sizeof(*attribs)))) - return BadAlloc; - - for (i = 0; i < stuff->screenCount; i++) { - int count; - - if (i < stuff->maskCount) mask = mask_list[i]; - dmxGetScreenAttributes(screen_list[i], &attribs[i]); - count = dmxFetchScreenAttributes(mask, &attribs[i], value_list); - value_list += count; - } - -#if PANORAMIX - status = dmxConfigureScreenWindows(stuff->screenCount, - screen_list, - attribs, - &errorScreen); -#endif - - xfree(attribs); - - if (status == BadValue) return status; - - noxinerama: - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.status = status; - rep.errorScreen = errorScreen; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - swapl(&rep.errorScreen, n); - } - WriteToClient(client, - sizeof(xDMXChangeScreensAttributesReply), - (char *)&rep); - return client->noClientException; -} - -static int ProcDMXAddScreen(ClientPtr client) -{ - REQUEST(xDMXAddScreenReq); - xDMXAddScreenReply rep; - int n; - int status = 0; - CARD32 *value_list; - DMXScreenAttributesRec attr; - int count; - char *name; - int len; - int paddedLength; - - REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq); - paddedLength = pad_to_int32(stuff->displayNameLength); - len = client->req_len - bytes_to_int32(sizeof(xDMXAddScreenReq)); - if (len != Ones(stuff->valueMask) + paddedLength/4) - return BadLength; - - memset(&attr, 0, sizeof(attr)); - dmxGetScreenAttributes(stuff->physicalScreen, &attr); - value_list = (CARD32 *)(stuff + 1); - count = dmxFetchScreenAttributes(stuff->valueMask, &attr, value_list); - - if (!(name = xalloc(stuff->displayNameLength + 1 + 4))) - return BadAlloc; - memcpy(name, &value_list[count], stuff->displayNameLength); - name[stuff->displayNameLength] = '\0'; - attr.displayName = name; - - status = dmxAttachScreen(stuff->physicalScreen, &attr); - - xfree(name); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.status = status; - rep.physicalScreen = stuff->physicalScreen; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - swapl(&rep.physicalScreen, n); - } - WriteToClient(client, - sizeof(xDMXAddScreenReply), - (char *)&rep); - return client->noClientException; -} - -static int ProcDMXRemoveScreen(ClientPtr client) -{ - REQUEST(xDMXRemoveScreenReq); - xDMXRemoveScreenReply rep; - int n; - int status = 0; - - REQUEST_SIZE_MATCH(xDMXRemoveScreenReq); - - status = dmxDetachScreen(stuff->physicalScreen); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.status = status; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - } - WriteToClient(client, - sizeof(xDMXRemoveScreenReply), - (char *)&rep); - return client->noClientException; -} - - -#ifdef PANORAMIX -static int dmxPopulatePanoramiX(ClientPtr client, Window window, - CARD32 *screens, CARD32 *windows, - xRectangle *pos, xRectangle *vis) -{ - WindowPtr pWin; - PanoramiXRes *win; - int i; - int count = 0; - DMXWindowAttributesRec attr; - - if (!(win = SecurityLookupIDByType(client, window, XRT_WINDOW, - DixReadAccess))) - return -1; /* BadWindow */ - - FOR_NSCREENS(i) { - if (Success != dixLookupWindow(&pWin, win->info[i].id, client, - DixReadAccess)) - return -1; /* BadWindow */ - if (dmxGetWindowAttributes(pWin, &attr)) { - screens[count] = attr.screen; - windows[count] = attr.window; - pos[count] = attr.pos; - vis[count] = attr.vis; - ++count; /* Only count existing windows */ - } - } - return count; -} -#endif - -static int dmxPopulate(ClientPtr client, Window window, CARD32 *screens, - CARD32 *windows, xRectangle *pos, xRectangle *vis) -{ - WindowPtr pWin; - DMXWindowAttributesRec attr; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) - return dmxPopulatePanoramiX(client, window, screens, windows, - pos, vis); -#endif - - if (Success != dixLookupWindow(&pWin, window, client, DixReadAccess)) - return -1; /* BadWindow */ - - dmxGetWindowAttributes(pWin, &attr); - *screens = attr.screen; - *windows = attr.window; - *pos = attr.pos; - *vis = attr.vis; - return 1; -} - -static int dmxMaxNumScreens(void) -{ -#ifdef PANORAMIX - if (!noPanoramiXExtension) return PanoramiXNumScreens; -#endif - return 1; -} - -static int ProcDMXGetWindowAttributes(ClientPtr client) -{ - REQUEST(xDMXGetWindowAttributesReq); - xDMXGetWindowAttributesReply rep; - int i, n; - CARD32 *screens; - CARD32 *windows; - xRectangle *pos, *vis; - int count = dmxMaxNumScreens(); - - REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq); - - if (!(screens = xalloc(count * sizeof(*screens)))) - return BadAlloc; - if (!(windows = xalloc(count * sizeof(*windows)))) { - xfree(screens); - return BadAlloc; - } - if (!(pos = xalloc(count * sizeof(*pos)))) { - xfree(windows); - xfree(screens); - return BadAlloc; - } - if (!(vis = xalloc(count * sizeof(*vis)))) { - xfree(pos); - xfree(windows); - xfree(screens); - return BadAlloc; - } - - if ((count = dmxPopulate(client, stuff->window, screens, windows, - pos, vis)) < 0) { - xfree(vis); - xfree(pos); - xfree(windows); - xfree(screens); - return BadWindow; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = count * 6; - rep.screenCount = count; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.screenCount, n); - for (i = 0; i < count; i++) { - swapl(&screens[i], n); - swapl(&windows[i], n); - - swaps(&pos[i].x, n); - swaps(&pos[i].y, n); - swaps(&pos[i].width, n); - swaps(&pos[i].height, n); - - swaps(&vis[i].x, n); - swaps(&vis[i].y, n); - swaps(&vis[i].width, n); - swaps(&vis[i].height, n); - } - } - - dmxFlushPendingSyncs(); - - WriteToClient(client, sizeof(xDMXGetWindowAttributesReply), (char *)&rep); - if (count) { - WriteToClient(client, count * sizeof(*screens), (char *)screens); - WriteToClient(client, count * sizeof(*windows), (char *)windows); - WriteToClient(client, count * sizeof(*pos), (char *)pos); - WriteToClient(client, count * sizeof(*vis), (char *)vis); - } - - xfree(vis); - xfree(pos); - xfree(windows); - xfree(screens); - - return client->noClientException; -} - -static int ProcDMXGetDesktopAttributes(ClientPtr client) -{ - xDMXGetDesktopAttributesReply rep; - int n; - DMXDesktopAttributesRec attr; - - REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq); - - dmxGetDesktopAttributes(&attr); - - rep.width = attr.width; - rep.height = attr.height; - rep.shiftX = attr.shiftX; - rep.shiftY = attr.shiftY; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.width, n); - swapl(&rep.height, n); - swapl(&rep.shiftX, n); - swapl(&rep.shiftY, n); - } - WriteToClient(client, sizeof(xDMXGetDesktopAttributesReply), (char *)&rep); - return client->noClientException; -} - -static int ProcDMXChangeDesktopAttributes(ClientPtr client) -{ - REQUEST(xDMXChangeDesktopAttributesReq); - xDMXChangeDesktopAttributesReply rep; - int n; - int status = DMX_BAD_XINERAMA; - CARD32 *value_list; - DMXDesktopAttributesRec attr; - int len; - - REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq); - len = client->req_len - (sizeof(xDMXChangeDesktopAttributesReq) >> 2); - if (len != Ones(stuff->valueMask)) - return BadLength; - - if (!_DMXXineramaActive()) goto noxinerama; - - value_list = (CARD32 *)(stuff + 1); - - dmxGetDesktopAttributes(&attr); - dmxFetchDesktopAttributes(stuff->valueMask, &attr, value_list); - -#if PANORAMIX - status = dmxConfigureDesktop(&attr); -#endif - if (status == BadValue) return status; - - noxinerama: - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.status = status; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - } - WriteToClient(client, - sizeof(xDMXChangeDesktopAttributesReply), - (char *)&rep); - return client->noClientException; -} - -static int ProcDMXGetInputCount(ClientPtr client) -{ - xDMXGetInputCountReply rep; - int n; - - REQUEST_SIZE_MATCH(xDMXGetInputCountReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.inputCount = dmxGetInputCount(); - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.inputCount, n); - } - WriteToClient(client, sizeof(xDMXGetInputCountReply), (char *)&rep); - return client->noClientException; -} - -static int ProcDMXGetInputAttributes(ClientPtr client) -{ - REQUEST(xDMXGetInputAttributesReq); - xDMXGetInputAttributesReply rep; - int n; - int length; - int paddedLength; - DMXInputAttributesRec attr; - - REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq); - - if (dmxGetInputAttributes(stuff->deviceId, &attr)) return BadValue; - rep.inputType = attr.inputType; - rep.physicalScreen = attr.physicalScreen; - rep.physicalId = attr.physicalId; - rep.isCore = attr.isCore; - rep.sendsCore = attr.sendsCore; - rep.detached = attr.detached; - - length = attr.name ? strlen(attr.name) : 0; - paddedLength = pad_to_int32(length); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = bytes_to_int32(paddedLength); - rep.nameLength = length; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.inputType, n); - swapl(&rep.physicalScreen, n); - swapl(&rep.physicalId, n); - swapl(&rep.nameLength, n); - } - WriteToClient(client, sizeof(xDMXGetInputAttributesReply), (char *)&rep); - if (length) WriteToClient(client, length, (char *)attr.name); - return client->noClientException; -} - -static int ProcDMXAddInput(ClientPtr client) -{ - REQUEST(xDMXAddInputReq); - xDMXAddInputReply rep; - int n; - int status = 0; - CARD32 *value_list; - DMXInputAttributesRec attr; - int count; - char *name; - int len; - int paddedLength; - int id = -1; - - REQUEST_AT_LEAST_SIZE(xDMXAddInputReq); - paddedLength = pad_to_int32(stuff->displayNameLength); - len = client->req_len - (sizeof(xDMXAddInputReq) >> 2); - if (len != Ones(stuff->valueMask) + paddedLength/4) - return BadLength; - - memset(&attr, 0, sizeof(attr)); - value_list = (CARD32 *)(stuff + 1); - count = dmxFetchInputAttributes(stuff->valueMask, &attr, value_list); - - if (!(name = xalloc(stuff->displayNameLength + 1 + 4))) - return BadAlloc; - memcpy(name, &value_list[count], stuff->displayNameLength); - name[stuff->displayNameLength] = '\0'; - attr.name = name; - - status = dmxAddInput(&attr, &id); - - xfree(name); - - if (status) return status; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.status = status; - rep.physicalId = id; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - swapl(&rep.physicalId, n); - } - WriteToClient(client, sizeof(xDMXAddInputReply), (char *)&rep); - return client->noClientException; -} - -static int ProcDMXRemoveInput(ClientPtr client) -{ - REQUEST(xDMXRemoveInputReq); - xDMXRemoveInputReply rep; - int n; - int status = 0; - - REQUEST_SIZE_MATCH(xDMXRemoveInputReq); - - status = dmxRemoveInput(stuff->physicalId); - - if (status) return status; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.status = status; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.status, n); - } - WriteToClient(client, sizeof(xDMXRemoveInputReply), (char *)&rep); - return client->noClientException; -} - -static int ProcDMXDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) { - case X_DMXQueryVersion: return ProcDMXQueryVersion(client); - case X_DMXSync: return ProcDMXSync(client); - case X_DMXForceWindowCreation: return ProcDMXForceWindowCreation(client); - case X_DMXGetScreenCount: return ProcDMXGetScreenCount(client); - case X_DMXGetScreenAttributes: return ProcDMXGetScreenAttributes(client); - case X_DMXChangeScreensAttributes: - return ProcDMXChangeScreensAttributes(client); - case X_DMXAddScreen: return ProcDMXAddScreen(client); - case X_DMXRemoveScreen: return ProcDMXRemoveScreen(client); - case X_DMXGetWindowAttributes: return ProcDMXGetWindowAttributes(client); - case X_DMXGetDesktopAttributes: return ProcDMXGetDesktopAttributes(client); - case X_DMXChangeDesktopAttributes: - return ProcDMXChangeDesktopAttributes(client); - case X_DMXGetInputCount: return ProcDMXGetInputCount(client); - case X_DMXGetInputAttributes: return ProcDMXGetInputAttributes(client); - case X_DMXAddInput: return ProcDMXAddInput(client); - case X_DMXRemoveInput: return ProcDMXRemoveInput(client); - - case X_DMXGetScreenInformationDEPRECATED: - case X_DMXForceWindowCreationDEPRECATED: - case X_DMXReconfigureScreenDEPRECATED: - return BadImplementation; - - default: return BadRequest; - } -} - -static int SProcDMXQueryVersion(ClientPtr client) -{ - int n; - REQUEST(xDMXQueryVersionReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXQueryVersionReq); - return ProcDMXQueryVersion(client); -} - -static int SProcDMXSync(ClientPtr client) -{ - int n; - REQUEST(xDMXSyncReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXSyncReq); - return ProcDMXSync(client); -} - -static int SProcDMXForceWindowCreation(ClientPtr client) -{ - int n; - REQUEST(xDMXForceWindowCreationReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq); - swaps(&stuff->window, n); - return ProcDMXForceWindowCreation(client); -} - -static int SProcDMXGetScreenCount(ClientPtr client) -{ - int n; - REQUEST(xDMXGetScreenCountReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXGetScreenCountReq); - return ProcDMXGetScreenCount(client); -} - -static int SProcDMXGetScreenAttributes(ClientPtr client) -{ - int n; - REQUEST(xDMXGetScreenAttributesReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq); - swapl(&stuff->physicalScreen, n); - return ProcDMXGetScreenAttributes(client); -} - -static int SProcDMXChangeScreensAttributes(ClientPtr client) -{ - int n; - REQUEST(xDMXChangeScreensAttributesReq); - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xDMXGetScreenAttributesReq); - swapl(&stuff->screenCount, n); - swapl(&stuff->maskCount, n); - SwapRestL(stuff); - return ProcDMXGetScreenAttributes(client); -} - -static int SProcDMXAddScreen(ClientPtr client) -{ - int n; - int paddedLength; - REQUEST(xDMXAddScreenReq); - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq); - swapl(&stuff->displayNameLength, n); - swapl(&stuff->valueMask, n); - paddedLength = pad_to_int32(stuff->displayNameLength); - SwapLongs((CARD32 *)(stuff+1), LengthRestL(stuff) - paddedLength/4); - return ProcDMXAddScreen(client); -} - -static int SProcDMXRemoveScreen(ClientPtr client) -{ - int n; - REQUEST(xDMXRemoveScreenReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXRemoveScreenReq); - swapl(&stuff->physicalScreen, n); - return ProcDMXRemoveScreen(client); -} - -static int SProcDMXGetWindowAttributes(ClientPtr client) -{ - int n; - REQUEST(xDMXGetWindowAttributesReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq); - swapl(&stuff->window, n); - return ProcDMXGetWindowAttributes(client); -} - -static int SProcDMXGetDesktopAttributes(ClientPtr client) -{ - int n; - REQUEST(xDMXGetDesktopAttributesReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq); - return ProcDMXGetDesktopAttributes(client); -} - -static int SProcDMXChangeDesktopAttributes(ClientPtr client) -{ - int n; - REQUEST(xDMXChangeDesktopAttributesReq); - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq); - swapl(&stuff->valueMask, n); - SwapRestL(stuff); - return ProcDMXChangeDesktopAttributes(client); -} - -static int SProcDMXGetInputCount(ClientPtr client) -{ - int n; - REQUEST(xDMXGetInputCountReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXGetInputCountReq); - return ProcDMXGetInputCount(client); -} - -static int SProcDMXGetInputAttributes(ClientPtr client) -{ - int n; - REQUEST(xDMXGetInputAttributesReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq); - swapl(&stuff->deviceId, n); - return ProcDMXGetInputAttributes(client); -} - -static int SProcDMXAddInput(ClientPtr client) -{ - int n; - int paddedLength; - REQUEST(xDMXAddInputReq); - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xDMXAddInputReq); - swapl(&stuff->displayNameLength, n); - swapl(&stuff->valueMask, n); - paddedLength = pad_to_int32(stuff->displayNameLength); - SwapLongs((CARD32 *)(stuff+1), LengthRestL(stuff) - paddedLength/4); - return ProcDMXAddInput(client); -} - -static int SProcDMXRemoveInput(ClientPtr client) -{ - int n; - REQUEST(xDMXRemoveInputReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDMXRemoveInputReq); - swapl(&stuff->physicalId, n); - return ProcDMXRemoveInput(client); -} - -static int SProcDMXDispatch (ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) { - case X_DMXQueryVersion: return SProcDMXQueryVersion(client); - case X_DMXSync: return SProcDMXSync(client); - case X_DMXForceWindowCreation: return SProcDMXForceWindowCreation(client); - case X_DMXGetScreenCount: return SProcDMXGetScreenCount(client); - case X_DMXGetScreenAttributes: return SProcDMXGetScreenAttributes(client); - case X_DMXChangeScreensAttributes: - return SProcDMXChangeScreensAttributes(client); - case X_DMXAddScreen: return SProcDMXAddScreen(client); - case X_DMXRemoveScreen: return SProcDMXRemoveScreen(client); - case X_DMXGetWindowAttributes: return SProcDMXGetWindowAttributes(client); - case X_DMXGetDesktopAttributes: - return SProcDMXGetDesktopAttributes(client); - case X_DMXChangeDesktopAttributes: - return SProcDMXChangeDesktopAttributes(client); - case X_DMXGetInputCount: return SProcDMXGetInputCount(client); - case X_DMXGetInputAttributes: return SProcDMXGetInputAttributes(client); - case X_DMXAddInput: return SProcDMXAddInput(client); - case X_DMXRemoveInput: return SProcDMXRemoveInput(client); - - case X_DMXGetScreenInformationDEPRECATED: - case X_DMXForceWindowCreationDEPRECATED: - case X_DMXReconfigureScreenDEPRECATED: - return BadImplementation; - - default: return BadRequest; - } -} +/* + * Copyright 2002-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: + * Rickard E. (Rik) Faith + * + */ + +/** \file + * This file implements the server-side part of the DMX protocol. A + * vector of fucntions is provided at extension initialization time, so + * most all of the useful functions in this file are declared static and + * do not appear in the doxygen documentation. + * + * Much of the low-level work is done by functions in \a dmxextension.c + * + * Please see the Client-to-Server DMX Extension to the X Protocol + * document for details about the protocol. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "opaque.h" + +#include "dmxextension.h" +#include +#include +#include "protocol-versions.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +extern unsigned long XRT_WINDOW; +extern int PanoramiXNumScreens; +#endif + +extern void DMXExtensionInit(void); + +static unsigned char DMXCode; + +static DISPATCH_PROC(ProcDMXDispatch); +static DISPATCH_PROC(ProcDMXQueryVersion); +static DISPATCH_PROC(ProcDMXSync); +static DISPATCH_PROC(ProcDMXForceWindowCreation); +static DISPATCH_PROC(ProcDMXGetScreenCount); +static DISPATCH_PROC(ProcDMXGetScreenAttributes); +static DISPATCH_PROC(ProcDMXChangeScreensAttributes); +static DISPATCH_PROC(ProcDMXAddScreen); +static DISPATCH_PROC(ProcDMXRemoveScreen); +static DISPATCH_PROC(ProcDMXGetWindowAttributes); +static DISPATCH_PROC(ProcDMXGetDesktopAttributes); +static DISPATCH_PROC(ProcDMXChangeDesktopAttributes); +static DISPATCH_PROC(ProcDMXGetInputCount); +static DISPATCH_PROC(ProcDMXGetInputAttributes); +static DISPATCH_PROC(ProcDMXAddInput); +static DISPATCH_PROC(ProcDMXRemoveInput); + +static DISPATCH_PROC(SProcDMXDispatch); +static DISPATCH_PROC(SProcDMXQueryVersion); +static DISPATCH_PROC(SProcDMXSync); +static DISPATCH_PROC(SProcDMXForceWindowCreation); +static DISPATCH_PROC(SProcDMXGetScreenCount); +static DISPATCH_PROC(SProcDMXGetScreenAttributes); +static DISPATCH_PROC(SProcDMXChangeScreensAttributes); +static DISPATCH_PROC(SProcDMXAddScreen); +static DISPATCH_PROC(SProcDMXRemoveScreen); +static DISPATCH_PROC(SProcDMXGetWindowAttributes); +static DISPATCH_PROC(SProcDMXGetDesktopAttributes); +static DISPATCH_PROC(SProcDMXChangeDesktopAttributes); +static DISPATCH_PROC(SProcDMXGetInputCount); +static DISPATCH_PROC(SProcDMXGetInputAttributes); +static DISPATCH_PROC(SProcDMXAddInput); +static DISPATCH_PROC(SProcDMXRemoveInput); + +static int _DMXXineramaActive(void) +{ +#ifdef PANORAMIX + return !noPanoramiXExtension; +#endif + return 0; +} + +/** Initialize the extension. */ +void DMXExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if ((extEntry = AddExtension(DMX_EXTENSION_NAME, 0, 0, + ProcDMXDispatch, SProcDMXDispatch, + NULL, StandardMinorOpcode))) + DMXCode = extEntry->base; +} + +static void dmxSetScreenAttribute(int bit, DMXScreenAttributesPtr attr, + CARD32 value) +{ + switch (1 << bit) { + case DMXScreenWindowWidth: attr->screenWindowWidth = value; break; + case DMXScreenWindowHeight: attr->screenWindowHeight = value; break; + case DMXScreenWindowXoffset: attr->screenWindowXoffset = value; break; + case DMXScreenWindowYoffset: attr->screenWindowYoffset = value; break; + case DMXRootWindowWidth: attr->rootWindowWidth = value; break; + case DMXRootWindowHeight: attr->rootWindowHeight = value; break; + case DMXRootWindowXoffset: attr->rootWindowXoffset = value; break; + case DMXRootWindowYoffset: attr->rootWindowYoffset = value; break; + case DMXRootWindowXorigin: attr->rootWindowXorigin = value; break; + case DMXRootWindowYorigin: attr->rootWindowYorigin = value; break; + } +} + +static int dmxFetchScreenAttributes(unsigned int mask, + DMXScreenAttributesPtr attr, + CARD32 *value_list) +{ + int i; + CARD32 *value = value_list; + int count = 0; + + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) { + dmxSetScreenAttribute(i, attr, *value); + ++value; + ++count; + } + } + return count; +} + +static void dmxSetDesktopAttribute(int bit, DMXDesktopAttributesPtr attr, + CARD32 value) +{ + switch (1 << bit) { + case DMXDesktopWidth: attr->width = value; break; + case DMXDesktopHeight: attr->height = value; break; + case DMXDesktopShiftX: attr->shiftX = value; break; + case DMXDesktopShiftY: attr->shiftY = value; break; + } +} + +static int dmxFetchDesktopAttributes(unsigned int mask, + DMXDesktopAttributesPtr attr, + CARD32 *value_list) +{ + int i; + CARD32 *value = value_list; + int count = 0; + + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) { + dmxSetDesktopAttribute(i, attr, *value); + ++value; + ++count; + } + } + return count; +} + +static void dmxSetInputAttribute(int bit, DMXInputAttributesPtr attr, + CARD32 value) +{ + switch (1 << bit) { + case DMXInputType: attr->inputType = value; break; + case DMXInputPhysicalScreen: attr->physicalScreen = value; break; + case DMXInputSendsCore: attr->sendsCore = !!value; break; + } +} + +static int dmxFetchInputAttributes(unsigned int mask, + DMXInputAttributesPtr attr, + CARD32 *value_list) +{ + int i; + CARD32 *value = value_list; + int count = 0; + + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) { + dmxSetInputAttribute(i, attr, *value); + ++value; + ++count; + } + } + return count; +} + +static int ProcDMXQueryVersion(ClientPtr client) +{ + xDMXQueryVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xDMXQueryVersionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.majorVersion = SERVER_DMX_MAJOR_VERSION; + rep.minorVersion = SERVER_DMX_MINOR_VERSION; + rep.patchVersion = SERVER_DMX_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + swapl(&rep.patchVersion, n); + } + WriteToClient(client, sizeof(xDMXQueryVersionReply), (char *)&rep); + return Success; +} + +static int ProcDMXSync(ClientPtr client) +{ + xDMXSyncReply rep; + int n; + + REQUEST_SIZE_MATCH(xDMXSyncReq); + + dmxFlushPendingSyncs(); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xDMXSyncReply), (char *)&rep); + return Success; +} + +static int ProcDMXForceWindowCreation(ClientPtr client) +{ + xDMXForceWindowCreationReply rep; + REQUEST(xDMXForceWindowCreationReq); + WindowPtr pWin; + int n; + + REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq); + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + PanoramiXRes *win; + int i; + + if (!(win = SecurityLookupIDByType(client, stuff->window, XRT_WINDOW, + DixReadAccess))) + return -1; /* BadWindow */ + + FOR_NSCREENS(i) { + if (Success != dixLookupWindow(&pWin, win->info[i].id, client, + DixReadAccess)) + return -1; /* BadWindow */ + + dmxForceWindowCreation(pWin); + } + goto doreply; + } +#endif + + if (Success != dixLookupWindow(&pWin, stuff->window, client, + DixReadAccess)) + return -1; /* BadWindow */ + + dmxForceWindowCreation(pWin); + doreply: + dmxFlushPendingSyncs(); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = 0; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xDMXForceWindowCreationReply), (char *)&rep); + return Success; +} + +static int ProcDMXGetScreenCount(ClientPtr client) +{ + xDMXGetScreenCountReply rep; + int n; + + REQUEST_SIZE_MATCH(xDMXGetScreenCountReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.screenCount = dmxGetNumScreens(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.screenCount, n); + } + WriteToClient(client, sizeof(xDMXGetScreenCountReply), (char *)&rep); + return Success; +} + +static int ProcDMXGetScreenAttributes(ClientPtr client) +{ + REQUEST(xDMXGetScreenAttributesReq); + xDMXGetScreenAttributesReply rep; + int n; + int length; + int paddedLength; + DMXScreenAttributesRec attr; + + REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq); + + if (stuff->physicalScreen < 0 + || stuff->physicalScreen >= dmxGetNumScreens()) return BadValue; + + if (!dmxGetScreenAttributes(stuff->physicalScreen, &attr)) + return BadValue; + + rep.logicalScreen = attr.logicalScreen; + rep.screenWindowWidth = attr.screenWindowWidth; + rep.screenWindowHeight = attr.screenWindowHeight; + rep.screenWindowXoffset = attr.screenWindowXoffset; + rep.screenWindowYoffset = attr.screenWindowYoffset; + rep.rootWindowWidth = attr.rootWindowWidth; + rep.rootWindowHeight = attr.rootWindowHeight; + rep.rootWindowXoffset = attr.rootWindowXoffset; + rep.rootWindowYoffset = attr.rootWindowYoffset; + rep.rootWindowXorigin = attr.rootWindowXorigin; + rep.rootWindowYorigin = attr.rootWindowYorigin; + + length = attr.displayName ? strlen(attr.displayName) : 0; + paddedLength = pad_to_int32(length); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32((sizeof(xDMXGetScreenAttributesReply) - sizeof(xGenericReply)) + + paddedLength); + rep.displayNameLength = length; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.displayNameLength, n); + swapl(&rep.logicalScreen, n); + swaps(&rep.screenWindowWidth, n); + swaps(&rep.screenWindowHeight, n); + swaps(&rep.screenWindowXoffset, n); + swaps(&rep.screenWindowYoffset, n); + swaps(&rep.rootWindowWidth, n); + swaps(&rep.rootWindowHeight, n); + swaps(&rep.rootWindowXoffset, n); + swaps(&rep.rootWindowYoffset, n); + swaps(&rep.rootWindowXorigin, n); + swaps(&rep.rootWindowYorigin, n); + } + WriteToClient(client, sizeof(xDMXGetScreenAttributesReply), (char *)&rep); + if (length) WriteToClient(client, length, (char *)attr.displayName); + return Success; +} + +static int ProcDMXChangeScreensAttributes(ClientPtr client) +{ + REQUEST(xDMXChangeScreensAttributesReq); + xDMXChangeScreensAttributesReply rep; + int n; + int status = DMX_BAD_XINERAMA; + unsigned int mask = 0; + unsigned int i; + CARD32 *screen_list; + CARD32 *mask_list; + CARD32 *value_list; + DMXScreenAttributesPtr attribs; + int errorScreen = 0; + unsigned int len; + int ones = 0; + + + REQUEST_AT_LEAST_SIZE(xDMXChangeScreensAttributesReq); + len = client->req_len - bytes_to_int32(sizeof(xDMXChangeScreensAttributesReq)); + if (len < stuff->screenCount + stuff->maskCount) + return BadLength; + + screen_list = (CARD32 *)(stuff + 1); + mask_list = &screen_list[stuff->screenCount]; + value_list = &mask_list[stuff->maskCount]; + + for (i = 0; i < stuff->maskCount; i++) ones += Ones(mask_list[i]); + if (len != stuff->screenCount + stuff->maskCount + ones) + return BadLength; + + if (!_DMXXineramaActive()) goto noxinerama; + + if (!(attribs = malloc(stuff->screenCount * sizeof(*attribs)))) + return BadAlloc; + + for (i = 0; i < stuff->screenCount; i++) { + int count; + + if (i < stuff->maskCount) mask = mask_list[i]; + dmxGetScreenAttributes(screen_list[i], &attribs[i]); + count = dmxFetchScreenAttributes(mask, &attribs[i], value_list); + value_list += count; + } + +#if PANORAMIX + status = dmxConfigureScreenWindows(stuff->screenCount, + screen_list, + attribs, + &errorScreen); +#endif + + free(attribs); + + if (status == BadValue) return status; + + noxinerama: + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + rep.errorScreen = errorScreen; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + swapl(&rep.errorScreen, n); + } + WriteToClient(client, + sizeof(xDMXChangeScreensAttributesReply), + (char *)&rep); + return Success; +} + +static int ProcDMXAddScreen(ClientPtr client) +{ + REQUEST(xDMXAddScreenReq); + xDMXAddScreenReply rep; + int n; + int status = 0; + CARD32 *value_list; + DMXScreenAttributesRec attr; + int count; + char *name; + int len; + int paddedLength; + + REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq); + paddedLength = pad_to_int32(stuff->displayNameLength); + len = client->req_len - bytes_to_int32(sizeof(xDMXAddScreenReq)); + if (len != Ones(stuff->valueMask) + paddedLength/4) + return BadLength; + + memset(&attr, 0, sizeof(attr)); + dmxGetScreenAttributes(stuff->physicalScreen, &attr); + value_list = (CARD32 *)(stuff + 1); + count = dmxFetchScreenAttributes(stuff->valueMask, &attr, value_list); + + if (!(name = malloc(stuff->displayNameLength + 1 + 4))) + return BadAlloc; + memcpy(name, &value_list[count], stuff->displayNameLength); + name[stuff->displayNameLength] = '\0'; + attr.displayName = name; + + status = dmxAttachScreen(stuff->physicalScreen, &attr); + + free(name); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + rep.physicalScreen = stuff->physicalScreen; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + swapl(&rep.physicalScreen, n); + } + WriteToClient(client, + sizeof(xDMXAddScreenReply), + (char *)&rep); + return Success; +} + +static int ProcDMXRemoveScreen(ClientPtr client) +{ + REQUEST(xDMXRemoveScreenReq); + xDMXRemoveScreenReply rep; + int n; + int status = 0; + + REQUEST_SIZE_MATCH(xDMXRemoveScreenReq); + + status = dmxDetachScreen(stuff->physicalScreen); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, + sizeof(xDMXRemoveScreenReply), + (char *)&rep); + return Success; +} + + +#ifdef PANORAMIX +static int dmxPopulatePanoramiX(ClientPtr client, Window window, + CARD32 *screens, CARD32 *windows, + xRectangle *pos, xRectangle *vis) +{ + WindowPtr pWin; + PanoramiXRes *win; + int i; + int count = 0; + DMXWindowAttributesRec attr; + + if (!(win = SecurityLookupIDByType(client, window, XRT_WINDOW, + DixReadAccess))) + return -1; /* BadWindow */ + + FOR_NSCREENS(i) { + if (Success != dixLookupWindow(&pWin, win->info[i].id, client, + DixReadAccess)) + return -1; /* BadWindow */ + if (dmxGetWindowAttributes(pWin, &attr)) { + screens[count] = attr.screen; + windows[count] = attr.window; + pos[count] = attr.pos; + vis[count] = attr.vis; + ++count; /* Only count existing windows */ + } + } + return count; +} +#endif + +static int dmxPopulate(ClientPtr client, Window window, CARD32 *screens, + CARD32 *windows, xRectangle *pos, xRectangle *vis) +{ + WindowPtr pWin; + DMXWindowAttributesRec attr; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + return dmxPopulatePanoramiX(client, window, screens, windows, + pos, vis); +#endif + + if (Success != dixLookupWindow(&pWin, window, client, DixReadAccess)) + return -1; /* BadWindow */ + + dmxGetWindowAttributes(pWin, &attr); + *screens = attr.screen; + *windows = attr.window; + *pos = attr.pos; + *vis = attr.vis; + return 1; +} + +static int dmxMaxNumScreens(void) +{ +#ifdef PANORAMIX + if (!noPanoramiXExtension) return PanoramiXNumScreens; +#endif + return 1; +} + +static int ProcDMXGetWindowAttributes(ClientPtr client) +{ + REQUEST(xDMXGetWindowAttributesReq); + xDMXGetWindowAttributesReply rep; + int i, n; + CARD32 *screens; + CARD32 *windows; + xRectangle *pos, *vis; + int count = dmxMaxNumScreens(); + + REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq); + + if (!(screens = malloc(count * sizeof(*screens)))) + return BadAlloc; + if (!(windows = malloc(count * sizeof(*windows)))) { + free(screens); + return BadAlloc; + } + if (!(pos = malloc(count * sizeof(*pos)))) { + free(windows); + free(screens); + return BadAlloc; + } + if (!(vis = malloc(count * sizeof(*vis)))) { + free(pos); + free(windows); + free(screens); + return BadAlloc; + } + + if ((count = dmxPopulate(client, stuff->window, screens, windows, + pos, vis)) < 0) { + free(vis); + free(pos); + free(windows); + free(screens); + return BadWindow; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = count * 6; + rep.screenCount = count; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.screenCount, n); + for (i = 0; i < count; i++) { + swapl(&screens[i], n); + swapl(&windows[i], n); + + swaps(&pos[i].x, n); + swaps(&pos[i].y, n); + swaps(&pos[i].width, n); + swaps(&pos[i].height, n); + + swaps(&vis[i].x, n); + swaps(&vis[i].y, n); + swaps(&vis[i].width, n); + swaps(&vis[i].height, n); + } + } + + dmxFlushPendingSyncs(); + + WriteToClient(client, sizeof(xDMXGetWindowAttributesReply), (char *)&rep); + if (count) { + WriteToClient(client, count * sizeof(*screens), (char *)screens); + WriteToClient(client, count * sizeof(*windows), (char *)windows); + WriteToClient(client, count * sizeof(*pos), (char *)pos); + WriteToClient(client, count * sizeof(*vis), (char *)vis); + } + + free(vis); + free(pos); + free(windows); + free(screens); + + return Success; +} + +static int ProcDMXGetDesktopAttributes(ClientPtr client) +{ + xDMXGetDesktopAttributesReply rep; + int n; + DMXDesktopAttributesRec attr; + + REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq); + + dmxGetDesktopAttributes(&attr); + + rep.width = attr.width; + rep.height = attr.height; + rep.shiftX = attr.shiftX; + rep.shiftY = attr.shiftY; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.width, n); + swapl(&rep.height, n); + swapl(&rep.shiftX, n); + swapl(&rep.shiftY, n); + } + WriteToClient(client, sizeof(xDMXGetDesktopAttributesReply), (char *)&rep); + return Success; +} + +static int ProcDMXChangeDesktopAttributes(ClientPtr client) +{ + REQUEST(xDMXChangeDesktopAttributesReq); + xDMXChangeDesktopAttributesReply rep; + int n; + int status = DMX_BAD_XINERAMA; + CARD32 *value_list; + DMXDesktopAttributesRec attr; + int len; + + REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq); + len = client->req_len - (sizeof(xDMXChangeDesktopAttributesReq) >> 2); + if (len != Ones(stuff->valueMask)) + return BadLength; + + if (!_DMXXineramaActive()) goto noxinerama; + + value_list = (CARD32 *)(stuff + 1); + + dmxGetDesktopAttributes(&attr); + dmxFetchDesktopAttributes(stuff->valueMask, &attr, value_list); + +#if PANORAMIX + status = dmxConfigureDesktop(&attr); +#endif + if (status == BadValue) return status; + + noxinerama: + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, + sizeof(xDMXChangeDesktopAttributesReply), + (char *)&rep); + return Success; +} + +static int ProcDMXGetInputCount(ClientPtr client) +{ + xDMXGetInputCountReply rep; + int n; + + REQUEST_SIZE_MATCH(xDMXGetInputCountReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.inputCount = dmxGetInputCount(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.inputCount, n); + } + WriteToClient(client, sizeof(xDMXGetInputCountReply), (char *)&rep); + return Success; +} + +static int ProcDMXGetInputAttributes(ClientPtr client) +{ + REQUEST(xDMXGetInputAttributesReq); + xDMXGetInputAttributesReply rep; + int n; + int length; + int paddedLength; + DMXInputAttributesRec attr; + + REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq); + + if (dmxGetInputAttributes(stuff->deviceId, &attr)) return BadValue; + rep.inputType = attr.inputType; + rep.physicalScreen = attr.physicalScreen; + rep.physicalId = attr.physicalId; + rep.isCore = attr.isCore; + rep.sendsCore = attr.sendsCore; + rep.detached = attr.detached; + + length = attr.name ? strlen(attr.name) : 0; + paddedLength = pad_to_int32(length); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32(paddedLength); + rep.nameLength = length; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.inputType, n); + swapl(&rep.physicalScreen, n); + swapl(&rep.physicalId, n); + swapl(&rep.nameLength, n); + } + WriteToClient(client, sizeof(xDMXGetInputAttributesReply), (char *)&rep); + if (length) WriteToClient(client, length, (char *)attr.name); + return Success; +} + +static int ProcDMXAddInput(ClientPtr client) +{ + REQUEST(xDMXAddInputReq); + xDMXAddInputReply rep; + int n; + int status = 0; + CARD32 *value_list; + DMXInputAttributesRec attr; + int count; + char *name; + int len; + int paddedLength; + int id = -1; + + REQUEST_AT_LEAST_SIZE(xDMXAddInputReq); + paddedLength = pad_to_int32(stuff->displayNameLength); + len = client->req_len - (sizeof(xDMXAddInputReq) >> 2); + if (len != Ones(stuff->valueMask) + paddedLength/4) + return BadLength; + + memset(&attr, 0, sizeof(attr)); + value_list = (CARD32 *)(stuff + 1); + count = dmxFetchInputAttributes(stuff->valueMask, &attr, value_list); + + if (!(name = malloc(stuff->displayNameLength + 1 + 4))) + return BadAlloc; + memcpy(name, &value_list[count], stuff->displayNameLength); + name[stuff->displayNameLength] = '\0'; + attr.name = name; + + status = dmxAddInput(&attr, &id); + + free(name); + + if (status) return status; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + rep.physicalId = id; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + swapl(&rep.physicalId, n); + } + WriteToClient(client, sizeof(xDMXAddInputReply), (char *)&rep); + return Success; +} + +static int ProcDMXRemoveInput(ClientPtr client) +{ + REQUEST(xDMXRemoveInputReq); + xDMXRemoveInputReply rep; + int n; + int status = 0; + + REQUEST_SIZE_MATCH(xDMXRemoveInputReq); + + status = dmxRemoveInput(stuff->physicalId); + + if (status) return status; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.status = status; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.status, n); + } + WriteToClient(client, sizeof(xDMXRemoveInputReply), (char *)&rep); + return Success; +} + +static int ProcDMXDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_DMXQueryVersion: return ProcDMXQueryVersion(client); + case X_DMXSync: return ProcDMXSync(client); + case X_DMXForceWindowCreation: return ProcDMXForceWindowCreation(client); + case X_DMXGetScreenCount: return ProcDMXGetScreenCount(client); + case X_DMXGetScreenAttributes: return ProcDMXGetScreenAttributes(client); + case X_DMXChangeScreensAttributes: + return ProcDMXChangeScreensAttributes(client); + case X_DMXAddScreen: return ProcDMXAddScreen(client); + case X_DMXRemoveScreen: return ProcDMXRemoveScreen(client); + case X_DMXGetWindowAttributes: return ProcDMXGetWindowAttributes(client); + case X_DMXGetDesktopAttributes: return ProcDMXGetDesktopAttributes(client); + case X_DMXChangeDesktopAttributes: + return ProcDMXChangeDesktopAttributes(client); + case X_DMXGetInputCount: return ProcDMXGetInputCount(client); + case X_DMXGetInputAttributes: return ProcDMXGetInputAttributes(client); + case X_DMXAddInput: return ProcDMXAddInput(client); + case X_DMXRemoveInput: return ProcDMXRemoveInput(client); + + case X_DMXGetScreenInformationDEPRECATED: + case X_DMXForceWindowCreationDEPRECATED: + case X_DMXReconfigureScreenDEPRECATED: + return BadImplementation; + + default: return BadRequest; + } +} + +static int SProcDMXQueryVersion(ClientPtr client) +{ + int n; + REQUEST(xDMXQueryVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXQueryVersionReq); + return ProcDMXQueryVersion(client); +} + +static int SProcDMXSync(ClientPtr client) +{ + int n; + REQUEST(xDMXSyncReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXSyncReq); + return ProcDMXSync(client); +} + +static int SProcDMXForceWindowCreation(ClientPtr client) +{ + int n; + REQUEST(xDMXForceWindowCreationReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq); + swaps(&stuff->window, n); + return ProcDMXForceWindowCreation(client); +} + +static int SProcDMXGetScreenCount(ClientPtr client) +{ + int n; + REQUEST(xDMXGetScreenCountReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetScreenCountReq); + return ProcDMXGetScreenCount(client); +} + +static int SProcDMXGetScreenAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXGetScreenAttributesReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq); + swapl(&stuff->physicalScreen, n); + return ProcDMXGetScreenAttributes(client); +} + +static int SProcDMXChangeScreensAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXChangeScreensAttributesReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDMXGetScreenAttributesReq); + swapl(&stuff->screenCount, n); + swapl(&stuff->maskCount, n); + SwapRestL(stuff); + return ProcDMXGetScreenAttributes(client); +} + +static int SProcDMXAddScreen(ClientPtr client) +{ + int n; + int paddedLength; + REQUEST(xDMXAddScreenReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq); + swapl(&stuff->displayNameLength, n); + swapl(&stuff->valueMask, n); + paddedLength = pad_to_int32(stuff->displayNameLength); + SwapLongs((CARD32 *)(stuff+1), LengthRestL(stuff) - paddedLength/4); + return ProcDMXAddScreen(client); +} + +static int SProcDMXRemoveScreen(ClientPtr client) +{ + int n; + REQUEST(xDMXRemoveScreenReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXRemoveScreenReq); + swapl(&stuff->physicalScreen, n); + return ProcDMXRemoveScreen(client); +} + +static int SProcDMXGetWindowAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXGetWindowAttributesReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq); + swapl(&stuff->window, n); + return ProcDMXGetWindowAttributes(client); +} + +static int SProcDMXGetDesktopAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXGetDesktopAttributesReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq); + return ProcDMXGetDesktopAttributes(client); +} + +static int SProcDMXChangeDesktopAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXChangeDesktopAttributesReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + return ProcDMXChangeDesktopAttributes(client); +} + +static int SProcDMXGetInputCount(ClientPtr client) +{ + int n; + REQUEST(xDMXGetInputCountReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetInputCountReq); + return ProcDMXGetInputCount(client); +} + +static int SProcDMXGetInputAttributes(ClientPtr client) +{ + int n; + REQUEST(xDMXGetInputAttributesReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq); + swapl(&stuff->deviceId, n); + return ProcDMXGetInputAttributes(client); +} + +static int SProcDMXAddInput(ClientPtr client) +{ + int n; + int paddedLength; + REQUEST(xDMXAddInputReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xDMXAddInputReq); + swapl(&stuff->displayNameLength, n); + swapl(&stuff->valueMask, n); + paddedLength = pad_to_int32(stuff->displayNameLength); + SwapLongs((CARD32 *)(stuff+1), LengthRestL(stuff) - paddedLength/4); + return ProcDMXAddInput(client); +} + +static int SProcDMXRemoveInput(ClientPtr client) +{ + int n; + REQUEST(xDMXRemoveInputReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDMXRemoveInputReq); + swapl(&stuff->physicalId, n); + return ProcDMXRemoveInput(client); +} + +static int SProcDMXDispatch (ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) { + case X_DMXQueryVersion: return SProcDMXQueryVersion(client); + case X_DMXSync: return SProcDMXSync(client); + case X_DMXForceWindowCreation: return SProcDMXForceWindowCreation(client); + case X_DMXGetScreenCount: return SProcDMXGetScreenCount(client); + case X_DMXGetScreenAttributes: return SProcDMXGetScreenAttributes(client); + case X_DMXChangeScreensAttributes: + return SProcDMXChangeScreensAttributes(client); + case X_DMXAddScreen: return SProcDMXAddScreen(client); + case X_DMXRemoveScreen: return SProcDMXRemoveScreen(client); + case X_DMXGetWindowAttributes: return SProcDMXGetWindowAttributes(client); + case X_DMXGetDesktopAttributes: + return SProcDMXGetDesktopAttributes(client); + case X_DMXChangeDesktopAttributes: + return SProcDMXChangeDesktopAttributes(client); + case X_DMXGetInputCount: return SProcDMXGetInputCount(client); + case X_DMXGetInputAttributes: return SProcDMXGetInputAttributes(client); + case X_DMXAddInput: return SProcDMXAddInput(client); + case X_DMXRemoveInput: return SProcDMXRemoveInput(client); + + case X_DMXGetScreenInformationDEPRECATED: + case X_DMXForceWindowCreationDEPRECATED: + case X_DMXReconfigureScreenDEPRECATED: + return BadImplementation; + + default: return BadRequest; + } +} diff --git a/xorg-server/hw/dmx/dmx_glxvisuals.c b/xorg-server/hw/dmx/dmx_glxvisuals.c index ec33468be..50a23e30f 100644 --- a/xorg-server/hw/dmx/dmx_glxvisuals.c +++ b/xorg-server/hw/dmx/dmx_glxvisuals.c @@ -1,601 +1,601 @@ -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include "dmx.h" -#include -#include -#include -#include - -#include "dmx_glxvisuals.h" - -__GLXvisualConfig *GetGLXVisualConfigs(Display *dpy, int screen, int *nconfigs) -{ - xGLXGetVisualConfigsReq *req; - xGLXGetVisualConfigsReply reply; - __GLXvisualConfig *config, *configs; - GLint i, j, nvisuals, nprops; - INT32 *props, *p; - int majorOpcode, dummy; - int num_good_visuals; - - if (!XQueryExtension(dpy, "GLX", &majorOpcode, &dummy, &dummy)) { - return(NULL); - } - - /* Send the glXGetVisualConfigs request */ - LockDisplay(dpy); - GetReq(GLXGetVisualConfigs,req); - req->reqType = majorOpcode; - req->glxCode = X_GLXGetVisualConfigs; - req->screen = screen; - if (!_XReply(dpy, (xReply*) &reply, 0, False)) { - /* Something is busted. Punt. */ - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - nvisuals = (int)reply.numVisuals; - if (!nvisuals) { - /* This screen does not support GL rendering */ - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - /* Check number of properties per visual */ - nprops = (int)reply.numProps; - if (nprops < __GLX_MIN_CONFIG_PROPS) { - /* Huh? Not in protocol defined limits. Punt */ - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - props = (INT32*) Xmalloc(nprops * __GLX_SIZE_CARD32); - if (!props) { - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - /* Allocate memory for our config structure */ - config = (__GLXvisualConfig*) - Xmalloc(nvisuals * sizeof(__GLXvisualConfig)); - if (!config) { - Xfree(props); - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - memset(config, 0, nvisuals * sizeof(__GLXvisualConfig)); - configs = config; - num_good_visuals = 0; - - /* Convert config structure into our format */ - for (i=0; ivisualRating = GLX_NONE_EXT; - config->transparentPixel = GLX_NONE_EXT; - - /* Copy in the first set of properties */ - config->vid = props[0]; - config->class = props[1]; - - config->rgba = (Bool) props[2]; - - config->redSize = props[3]; - config->greenSize = props[4]; - config->blueSize = props[5]; - config->alphaSize = props[6]; - - config->accumRedSize = props[7]; - config->accumGreenSize = props[8]; - config->accumBlueSize = props[9]; - config->accumAlphaSize = props[10]; - - config->doubleBuffer = (Bool) props[11]; - config->stereo = (Bool) props[12]; - - config->bufferSize = props[13]; - config->depthSize = props[14]; - config->stencilSize = props[15]; - - config->auxBuffers = props[16]; - config->level = props[17]; - - /* Process remaining properties */ - p = &props[18]; - for (j=__GLX_MIN_CONFIG_PROPS; jmultiSampleSize = value; - break; - case GLX_SAMPLE_BUFFERS_SGIS: - config->nMultiSampleBuffers = value; - break; - - case GLX_TRANSPARENT_TYPE_EXT: - config->transparentPixel = value; - break; - case GLX_TRANSPARENT_INDEX_VALUE_EXT: - config->transparentIndex = value; - break; - case GLX_TRANSPARENT_RED_VALUE_EXT: - config->transparentRed = value; - break; - case GLX_TRANSPARENT_GREEN_VALUE_EXT: - config->transparentGreen = value; - break; - case GLX_TRANSPARENT_BLUE_VALUE_EXT: - config->transparentBlue = value; - break; - case GLX_TRANSPARENT_ALPHA_VALUE_EXT: - config->transparentAlpha = value; - break; - - case GLX_VISUAL_CAVEAT_EXT: - config->visualRating = value; - break; - - /* visualSelectGroup is an internal used property */ - case GLX_VISUAL_SELECT_GROUP_SGIX: - config->visualSelectGroup = value; - break; - - default : - /* Ignore properties we don't recognize */ - break; - } - } /* for j */ - - /* - // filter out overlay visuals (dmx does not support overlays) - */ - if (config->level == 0) { - config++; - num_good_visuals++; - } - - } /* for i */ - - UnlockDisplay(dpy); - - nvisuals = num_good_visuals; - - config = configs; - for (i=0; ivid; - vis = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask, - &template, &n); - - if (vis != NULL) { - config->redMask = vis->red_mask; - config->greenMask = vis->green_mask; - config->blueMask = vis->blue_mask; - config->alphaMask = 0; /* XXX */ - free(vis); - } - } - config++; - } /* for i */ - - XFree(props); - SyncHandle(); - - *nconfigs = nvisuals; - return( configs ); -} - - -__GLXFBConfig *GetGLXFBConfigs(Display *dpy, int glxMajorOpcode, int *nconfigs) -{ - xGLXGetFBConfigsReq *req; - xGLXGetFBConfigsReply reply; - __GLXFBConfig *config, *fbconfigs; - GLint i, j, numFBConfigs, numAttribs; - INT32 *attrs, *p; - int screen = DefaultScreen( dpy ); - int numValidConfigs = 0; - - /* Send the glXGetFBConfigs request */ - LockDisplay(dpy); - GetReq(GLXGetFBConfigs, req); - req->reqType = glxMajorOpcode; - req->glxCode = X_GLXGetFBConfigs; - req->screen = screen; - - *nconfigs = 0; - - if (!_XReply(dpy, (xReply*) &reply, 0, False)) { - /* Something is busted. Punt. */ - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - numFBConfigs = (int)reply.numFBConfigs; - if (!numFBConfigs) { - /* This screen does not support GL rendering */ - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - numAttribs = (int)reply.numAttribs; - if (!numAttribs) { - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - attrs = (INT32*) Xmalloc(2*numAttribs * __GLX_SIZE_CARD32); - if (!attrs) { - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - - /* Allocate memory for our config structure */ - config = (__GLXFBConfig*) - Xmalloc(numFBConfigs * sizeof(__GLXFBConfig)); - if (!config) { - Xfree(attrs); - UnlockDisplay(dpy); - SyncHandle(); - return NULL; - } - memset(config, 0, numFBConfigs * sizeof(__GLXFBConfig)); - fbconfigs = config; - - /* Convert attribute list into our format */ - for (i=0; itransparentType = GLX_NONE_EXT; - config->visualCaveat = GLX_NONE_EXT; - config->minRed = 0.; - config->maxRed = 1.; - config->minGreen = 0.; - config->maxGreen = 1.; - config->minBlue = 0.; - config->maxBlue = 1.; - config->minAlpha = 0.; - config->maxAlpha = 1.; - - /* Read attribute list */ - _XRead(dpy, (char *)attrs, (2*numAttribs * __GLX_SIZE_CARD32)); - - p = attrs; - for (j=0; jid = value; - break; - case GLX_BUFFER_SIZE: - config->indexBits = value; - break; - case GLX_LEVEL: - config->level = value; - break; - case GLX_DOUBLEBUFFER: - config->doubleBufferMode = value; - break; - case GLX_STEREO: - config->stereoMode = value; - break; - case GLX_AUX_BUFFERS: - config->maxAuxBuffers = value; - break; - case GLX_RED_SIZE: - config->redBits = value; - break; - case GLX_GREEN_SIZE: - config->greenBits = value; - break; - case GLX_BLUE_SIZE: - config->blueBits = value; - break; - case GLX_ALPHA_SIZE: - config->alphaBits = value; - break; - case GLX_DEPTH_SIZE: - config->depthBits = value; - break; - case GLX_STENCIL_SIZE: - config->stencilBits = value; - break; - case GLX_ACCUM_RED_SIZE: - config->accumRedBits = value; - break; - case GLX_ACCUM_GREEN_SIZE: - config->accumGreenBits = value; - break; - case GLX_ACCUM_BLUE_SIZE: - config->accumBlueBits = value; - break; - case GLX_ACCUM_ALPHA_SIZE: - config->accumAlphaBits = value; - break; - case GLX_RENDER_TYPE: - config->renderType = value; - break; - case GLX_DRAWABLE_TYPE: - config->drawableType = value; - break; - case GLX_X_VISUAL_TYPE: - config->visualType = value; - break; - case GLX_CONFIG_CAVEAT: - config->visualCaveat = value; - break; - case GLX_TRANSPARENT_TYPE: - config->transparentType = value; - break; - case GLX_TRANSPARENT_INDEX_VALUE: - config->transparentIndex = value; - break; - case GLX_TRANSPARENT_RED_VALUE: - config->transparentRed = value; - break; - case GLX_TRANSPARENT_GREEN_VALUE: - config->transparentGreen = value; - break; - case GLX_TRANSPARENT_BLUE_VALUE: - config->transparentBlue = value; - break; - case GLX_TRANSPARENT_ALPHA_VALUE: - config->transparentAlpha = value; - break; - case GLX_MAX_PBUFFER_WIDTH: - config->maxPbufferWidth = value; - break; - case GLX_MAX_PBUFFER_HEIGHT: - config->maxPbufferHeight = value; - break; - case GLX_MAX_PBUFFER_PIXELS: - config->maxPbufferPixels = value; - break; - case GLX_VISUAL_ID: - config->associatedVisualId = value; - break; - - /* visualSelectGroup is an internal used property */ - case GLX_VISUAL_SELECT_GROUP_SGIX: - config->visualSelectGroup = value; - break; - - /* SGIS_multisample attributes */ - case GLX_SAMPLES_SGIS: - config->multiSampleSize = value; - break; - case GLX_SAMPLE_BUFFERS_SGIS: - config->nMultiSampleBuffers = value; - break; - - /* SGIX_pbuffer specific attributes */ - case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: - config->optimalPbufferWidth = value; - break; - case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: - config->optimalPbufferHeight = value; - break; - - default: - /* Ignore attributes we don't recognize */ - break; - } - } /* for j */ - - /* Fill in derived values */ - config->screen = screen; - - config->rgbMode = config->renderType & GLX_RGBA_BIT; - config->colorIndexMode = !config->rgbMode; - - config->haveAccumBuffer = - config->accumRedBits > 0 || - config->accumGreenBits > 0 || - config->accumBlueBits > 0; - /* Can't have alpha without color */ - - config->haveDepthBuffer = config->depthBits > 0; - config->haveStencilBuffer = config->stencilBits > 0; - - /* overlay visuals are not valid for now */ - if (!config->level) { - config++; - numValidConfigs++; - } - - } /* for i */ - UnlockDisplay(dpy); - - config = fbconfigs; - for (i=0; iassociatedVisualId != 0) { - XVisualInfo *vis, template; - int n; - - template.screen = screen; - template.visualid = config->associatedVisualId; - vis = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask, - &template, &n); - - if (vis != NULL) { - config->redMask = (GLuint)vis->red_mask; - config->greenMask = (GLuint)vis->green_mask; - config->blueMask = (GLuint)vis->blue_mask; - config->alphaMask = 0; /* XXX */ - free(vis); - } - } - - config++; - } /* for i */ - - XFree(attrs); - SyncHandle(); - - *nconfigs = numValidConfigs; - return fbconfigs; -} - -__GLXvisualConfig * -GetGLXVisualConfigsFromFBConfigs(__GLXFBConfig *fbconfigs, int nfbconfigs, - XVisualInfo *visuals, int nvisuals, - __GLXvisualConfig *glxConfigs, int nGlxConfigs, - int *nconfigs) -{ - __GLXvisualConfig *configs = NULL; - int i; - - if (!fbconfigs || !nfbconfigs || !nconfigs) return(NULL); - *nconfigs = 0; - - /* Allocate memory for our config structure */ - configs = (__GLXvisualConfig*) - Xmalloc(nfbconfigs * sizeof(__GLXvisualConfig)); - if (!configs) { - return NULL; - } - memset(configs, 0, nfbconfigs * sizeof(__GLXvisualConfig)); - - for (i=0; iassociatedVisualId > 0) { - __GLXvisualConfig *cfg = configs + (*nconfigs); - int j; - XVisualInfo *vinfo = NULL; - - for (j=0; jassociatedVisualId) { - vinfo = &visuals[j]; - break; - } - } - if (!vinfo) continue; - - /* skip 16 bit colormap visuals */ - if (vinfo->depth == 16 && - vinfo->class != TrueColor && - vinfo->class != DirectColor ) { - continue; - } - - (*nconfigs)++; - - /* - * if the same visualid exists in the glx configs, - * copy the glx attributes from the glx config - */ - for (j=0; jvisualid) - break; - } - if (j < nGlxConfigs) { - memcpy(cfg, &glxConfigs[j], sizeof(__GLXvisualConfig) ); - continue; - } - - /* - * make glx attributes from the FB config attributes - */ - cfg->vid = fbcfg->associatedVisualId; - cfg->class = vinfo->class; - cfg->rgba = !(fbcfg->renderType & GLX_COLOR_INDEX_BIT_SGIX); - cfg->redSize = fbcfg->redBits; - cfg->greenSize = fbcfg->greenBits; - cfg->blueSize = fbcfg->blueBits; - cfg->alphaSize = fbcfg->alphaBits; - cfg->redMask = fbcfg->redMask; - cfg->greenMask = fbcfg->greenMask; - cfg->blueMask = fbcfg->blueMask; - cfg->alphaMask = fbcfg->alphaMask; - cfg->accumRedSize = fbcfg->accumRedBits; - cfg->accumGreenSize = fbcfg->accumGreenBits; - cfg->accumBlueSize = fbcfg->accumBlueBits; - cfg->accumAlphaSize = fbcfg->accumAlphaBits; - cfg->doubleBuffer = fbcfg->doubleBufferMode; - cfg->stereo = fbcfg->stereoMode; - if (vinfo->class == TrueColor || vinfo->class == DirectColor) { - cfg->bufferSize = (fbcfg->rgbMode ? (fbcfg->redBits + - fbcfg->greenBits + - fbcfg->blueBits + - fbcfg->alphaBits) - : fbcfg->indexBits ); - } - else { - cfg->bufferSize = vinfo->depth; - } - cfg->depthSize = fbcfg->depthBits; - cfg->stencilSize = fbcfg->stencilBits; - cfg->auxBuffers = fbcfg->maxAuxBuffers; - cfg->level = fbcfg->level; - cfg->visualRating = fbcfg->visualCaveat; - cfg->transparentPixel = fbcfg->transparentType; - cfg->transparentRed = fbcfg->transparentRed; - cfg->transparentGreen = fbcfg->transparentGreen; - cfg->transparentBlue = fbcfg->transparentBlue; - cfg->transparentAlpha = fbcfg->transparentAlpha; - cfg->transparentIndex = fbcfg->transparentIndex; - cfg->multiSampleSize = fbcfg->multiSampleSize; - cfg->nMultiSampleBuffers = fbcfg->nMultiSampleBuffers; - cfg->visualSelectGroup = fbcfg->visualSelectGroup; - } - } - - return( configs ); -} - +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include +#include +#include +#include + +#include "dmx_glxvisuals.h" + +__GLXvisualConfig *GetGLXVisualConfigs(Display *dpy, int screen, int *nconfigs) +{ + xGLXGetVisualConfigsReq *req; + xGLXGetVisualConfigsReply reply; + __GLXvisualConfig *config, *configs; + GLint i, j, nvisuals, nprops; + INT32 *props, *p; + int majorOpcode, dummy; + int num_good_visuals; + + if (!XQueryExtension(dpy, "GLX", &majorOpcode, &dummy, &dummy)) { + return(NULL); + } + + /* Send the glXGetVisualConfigs request */ + LockDisplay(dpy); + GetReq(GLXGetVisualConfigs,req); + req->reqType = majorOpcode; + req->glxCode = X_GLXGetVisualConfigs; + req->screen = screen; + if (!_XReply(dpy, (xReply*) &reply, 0, False)) { + /* Something is busted. Punt. */ + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + nvisuals = (int)reply.numVisuals; + if (!nvisuals) { + /* This screen does not support GL rendering */ + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + /* Check number of properties per visual */ + nprops = (int)reply.numProps; + if (nprops < __GLX_MIN_CONFIG_PROPS) { + /* Huh? Not in protocol defined limits. Punt */ + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + props = (INT32*) Xmalloc(nprops * __GLX_SIZE_CARD32); + if (!props) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + /* Allocate memory for our config structure */ + config = (__GLXvisualConfig*) + Xmalloc(nvisuals * sizeof(__GLXvisualConfig)); + if (!config) { + free(props); + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + memset(config, 0, nvisuals * sizeof(__GLXvisualConfig)); + configs = config; + num_good_visuals = 0; + + /* Convert config structure into our format */ + for (i=0; ivisualRating = GLX_NONE_EXT; + config->transparentPixel = GLX_NONE_EXT; + + /* Copy in the first set of properties */ + config->vid = props[0]; + config->class = props[1]; + + config->rgba = (Bool) props[2]; + + config->redSize = props[3]; + config->greenSize = props[4]; + config->blueSize = props[5]; + config->alphaSize = props[6]; + + config->accumRedSize = props[7]; + config->accumGreenSize = props[8]; + config->accumBlueSize = props[9]; + config->accumAlphaSize = props[10]; + + config->doubleBuffer = (Bool) props[11]; + config->stereo = (Bool) props[12]; + + config->bufferSize = props[13]; + config->depthSize = props[14]; + config->stencilSize = props[15]; + + config->auxBuffers = props[16]; + config->level = props[17]; + + /* Process remaining properties */ + p = &props[18]; + for (j=__GLX_MIN_CONFIG_PROPS; jmultiSampleSize = value; + break; + case GLX_SAMPLE_BUFFERS_SGIS: + config->nMultiSampleBuffers = value; + break; + + case GLX_TRANSPARENT_TYPE_EXT: + config->transparentPixel = value; + break; + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + config->transparentIndex = value; + break; + case GLX_TRANSPARENT_RED_VALUE_EXT: + config->transparentRed = value; + break; + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + config->transparentGreen = value; + break; + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + config->transparentBlue = value; + break; + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + config->transparentAlpha = value; + break; + + case GLX_VISUAL_CAVEAT_EXT: + config->visualRating = value; + break; + + /* visualSelectGroup is an internal used property */ + case GLX_VISUAL_SELECT_GROUP_SGIX: + config->visualSelectGroup = value; + break; + + default : + /* Ignore properties we don't recognize */ + break; + } + } /* for j */ + + /* + // filter out overlay visuals (dmx does not support overlays) + */ + if (config->level == 0) { + config++; + num_good_visuals++; + } + + } /* for i */ + + UnlockDisplay(dpy); + + nvisuals = num_good_visuals; + + config = configs; + for (i=0; ivid; + vis = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask, + &template, &n); + + if (vis != NULL) { + config->redMask = vis->red_mask; + config->greenMask = vis->green_mask; + config->blueMask = vis->blue_mask; + config->alphaMask = 0; /* XXX */ + free(vis); + } + } + config++; + } /* for i */ + + XFree(props); + SyncHandle(); + + *nconfigs = nvisuals; + return( configs ); +} + + +__GLXFBConfig *GetGLXFBConfigs(Display *dpy, int glxMajorOpcode, int *nconfigs) +{ + xGLXGetFBConfigsReq *req; + xGLXGetFBConfigsReply reply; + __GLXFBConfig *config, *fbconfigs; + GLint i, j, numFBConfigs, numAttribs; + INT32 *attrs, *p; + int screen = DefaultScreen( dpy ); + int numValidConfigs = 0; + + /* Send the glXGetFBConfigs request */ + LockDisplay(dpy); + GetReq(GLXGetFBConfigs, req); + req->reqType = glxMajorOpcode; + req->glxCode = X_GLXGetFBConfigs; + req->screen = screen; + + *nconfigs = 0; + + if (!_XReply(dpy, (xReply*) &reply, 0, False)) { + /* Something is busted. Punt. */ + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + numFBConfigs = (int)reply.numFBConfigs; + if (!numFBConfigs) { + /* This screen does not support GL rendering */ + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + numAttribs = (int)reply.numAttribs; + if (!numAttribs) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + attrs = (INT32*) Xmalloc(2*numAttribs * __GLX_SIZE_CARD32); + if (!attrs) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + /* Allocate memory for our config structure */ + config = (__GLXFBConfig*) + Xmalloc(numFBConfigs * sizeof(__GLXFBConfig)); + if (!config) { + free(attrs); + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + memset(config, 0, numFBConfigs * sizeof(__GLXFBConfig)); + fbconfigs = config; + + /* Convert attribute list into our format */ + for (i=0; itransparentType = GLX_NONE_EXT; + config->visualCaveat = GLX_NONE_EXT; + config->minRed = 0.; + config->maxRed = 1.; + config->minGreen = 0.; + config->maxGreen = 1.; + config->minBlue = 0.; + config->maxBlue = 1.; + config->minAlpha = 0.; + config->maxAlpha = 1.; + + /* Read attribute list */ + _XRead(dpy, (char *)attrs, (2*numAttribs * __GLX_SIZE_CARD32)); + + p = attrs; + for (j=0; jid = value; + break; + case GLX_BUFFER_SIZE: + config->indexBits = value; + break; + case GLX_LEVEL: + config->level = value; + break; + case GLX_DOUBLEBUFFER: + config->doubleBufferMode = value; + break; + case GLX_STEREO: + config->stereoMode = value; + break; + case GLX_AUX_BUFFERS: + config->maxAuxBuffers = value; + break; + case GLX_RED_SIZE: + config->redBits = value; + break; + case GLX_GREEN_SIZE: + config->greenBits = value; + break; + case GLX_BLUE_SIZE: + config->blueBits = value; + break; + case GLX_ALPHA_SIZE: + config->alphaBits = value; + break; + case GLX_DEPTH_SIZE: + config->depthBits = value; + break; + case GLX_STENCIL_SIZE: + config->stencilBits = value; + break; + case GLX_ACCUM_RED_SIZE: + config->accumRedBits = value; + break; + case GLX_ACCUM_GREEN_SIZE: + config->accumGreenBits = value; + break; + case GLX_ACCUM_BLUE_SIZE: + config->accumBlueBits = value; + break; + case GLX_ACCUM_ALPHA_SIZE: + config->accumAlphaBits = value; + break; + case GLX_RENDER_TYPE: + config->renderType = value; + break; + case GLX_DRAWABLE_TYPE: + config->drawableType = value; + break; + case GLX_X_VISUAL_TYPE: + config->visualType = value; + break; + case GLX_CONFIG_CAVEAT: + config->visualCaveat = value; + break; + case GLX_TRANSPARENT_TYPE: + config->transparentType = value; + break; + case GLX_TRANSPARENT_INDEX_VALUE: + config->transparentIndex = value; + break; + case GLX_TRANSPARENT_RED_VALUE: + config->transparentRed = value; + break; + case GLX_TRANSPARENT_GREEN_VALUE: + config->transparentGreen = value; + break; + case GLX_TRANSPARENT_BLUE_VALUE: + config->transparentBlue = value; + break; + case GLX_TRANSPARENT_ALPHA_VALUE: + config->transparentAlpha = value; + break; + case GLX_MAX_PBUFFER_WIDTH: + config->maxPbufferWidth = value; + break; + case GLX_MAX_PBUFFER_HEIGHT: + config->maxPbufferHeight = value; + break; + case GLX_MAX_PBUFFER_PIXELS: + config->maxPbufferPixels = value; + break; + case GLX_VISUAL_ID: + config->associatedVisualId = value; + break; + + /* visualSelectGroup is an internal used property */ + case GLX_VISUAL_SELECT_GROUP_SGIX: + config->visualSelectGroup = value; + break; + + /* SGIS_multisample attributes */ + case GLX_SAMPLES_SGIS: + config->multiSampleSize = value; + break; + case GLX_SAMPLE_BUFFERS_SGIS: + config->nMultiSampleBuffers = value; + break; + + /* SGIX_pbuffer specific attributes */ + case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: + config->optimalPbufferWidth = value; + break; + case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: + config->optimalPbufferHeight = value; + break; + + default: + /* Ignore attributes we don't recognize */ + break; + } + } /* for j */ + + /* Fill in derived values */ + config->screen = screen; + + config->rgbMode = config->renderType & GLX_RGBA_BIT; + config->colorIndexMode = !config->rgbMode; + + config->haveAccumBuffer = + config->accumRedBits > 0 || + config->accumGreenBits > 0 || + config->accumBlueBits > 0; + /* Can't have alpha without color */ + + config->haveDepthBuffer = config->depthBits > 0; + config->haveStencilBuffer = config->stencilBits > 0; + + /* overlay visuals are not valid for now */ + if (!config->level) { + config++; + numValidConfigs++; + } + + } /* for i */ + UnlockDisplay(dpy); + + config = fbconfigs; + for (i=0; iassociatedVisualId != 0) { + XVisualInfo *vis, template; + int n; + + template.screen = screen; + template.visualid = config->associatedVisualId; + vis = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask, + &template, &n); + + if (vis != NULL) { + config->redMask = (GLuint)vis->red_mask; + config->greenMask = (GLuint)vis->green_mask; + config->blueMask = (GLuint)vis->blue_mask; + config->alphaMask = 0; /* XXX */ + free(vis); + } + } + + config++; + } /* for i */ + + XFree(attrs); + SyncHandle(); + + *nconfigs = numValidConfigs; + return fbconfigs; +} + +__GLXvisualConfig * +GetGLXVisualConfigsFromFBConfigs(__GLXFBConfig *fbconfigs, int nfbconfigs, + XVisualInfo *visuals, int nvisuals, + __GLXvisualConfig *glxConfigs, int nGlxConfigs, + int *nconfigs) +{ + __GLXvisualConfig *configs = NULL; + int i; + + if (!fbconfigs || !nfbconfigs || !nconfigs) return(NULL); + *nconfigs = 0; + + /* Allocate memory for our config structure */ + configs = (__GLXvisualConfig*) + Xmalloc(nfbconfigs * sizeof(__GLXvisualConfig)); + if (!configs) { + return NULL; + } + memset(configs, 0, nfbconfigs * sizeof(__GLXvisualConfig)); + + for (i=0; iassociatedVisualId > 0) { + __GLXvisualConfig *cfg = configs + (*nconfigs); + int j; + XVisualInfo *vinfo = NULL; + + for (j=0; jassociatedVisualId) { + vinfo = &visuals[j]; + break; + } + } + if (!vinfo) continue; + + /* skip 16 bit colormap visuals */ + if (vinfo->depth == 16 && + vinfo->class != TrueColor && + vinfo->class != DirectColor ) { + continue; + } + + (*nconfigs)++; + + /* + * if the same visualid exists in the glx configs, + * copy the glx attributes from the glx config + */ + for (j=0; jvisualid) + break; + } + if (j < nGlxConfigs) { + memcpy(cfg, &glxConfigs[j], sizeof(__GLXvisualConfig) ); + continue; + } + + /* + * make glx attributes from the FB config attributes + */ + cfg->vid = fbcfg->associatedVisualId; + cfg->class = vinfo->class; + cfg->rgba = !(fbcfg->renderType & GLX_COLOR_INDEX_BIT_SGIX); + cfg->redSize = fbcfg->redBits; + cfg->greenSize = fbcfg->greenBits; + cfg->blueSize = fbcfg->blueBits; + cfg->alphaSize = fbcfg->alphaBits; + cfg->redMask = fbcfg->redMask; + cfg->greenMask = fbcfg->greenMask; + cfg->blueMask = fbcfg->blueMask; + cfg->alphaMask = fbcfg->alphaMask; + cfg->accumRedSize = fbcfg->accumRedBits; + cfg->accumGreenSize = fbcfg->accumGreenBits; + cfg->accumBlueSize = fbcfg->accumBlueBits; + cfg->accumAlphaSize = fbcfg->accumAlphaBits; + cfg->doubleBuffer = fbcfg->doubleBufferMode; + cfg->stereo = fbcfg->stereoMode; + if (vinfo->class == TrueColor || vinfo->class == DirectColor) { + cfg->bufferSize = (fbcfg->rgbMode ? (fbcfg->redBits + + fbcfg->greenBits + + fbcfg->blueBits + + fbcfg->alphaBits) + : fbcfg->indexBits ); + } + else { + cfg->bufferSize = vinfo->depth; + } + cfg->depthSize = fbcfg->depthBits; + cfg->stencilSize = fbcfg->stencilBits; + cfg->auxBuffers = fbcfg->maxAuxBuffers; + cfg->level = fbcfg->level; + cfg->visualRating = fbcfg->visualCaveat; + cfg->transparentPixel = fbcfg->transparentType; + cfg->transparentRed = fbcfg->transparentRed; + cfg->transparentGreen = fbcfg->transparentGreen; + cfg->transparentBlue = fbcfg->transparentBlue; + cfg->transparentAlpha = fbcfg->transparentAlpha; + cfg->transparentIndex = fbcfg->transparentIndex; + cfg->multiSampleSize = fbcfg->multiSampleSize; + cfg->nMultiSampleBuffers = fbcfg->nMultiSampleBuffers; + cfg->visualSelectGroup = fbcfg->visualSelectGroup; + } + } + + return( configs ); +} + diff --git a/xorg-server/hw/dmx/dmxcmap.c b/xorg-server/hw/dmx/dmxcmap.c index 4aa586aff..5a56afda2 100644 --- a/xorg-server/hw/dmx/dmxcmap.c +++ b/xorg-server/hw/dmx/dmxcmap.c @@ -1,212 +1,212 @@ -/* - * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 - * - */ - -/** \file - * Colormap support. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include "dmx.h" -#include "dmxlog.h" -#include "dmxsync.h" -#include "dmxcmap.h" -#include "dmxvisual.h" - -#include "micmap.h" - -static Bool dmxAllocateColormapPrivates(ColormapPtr pColormap) -{ - dmxColormapPrivPtr pCmapPriv; - - pCmapPriv = (dmxColormapPrivPtr)xalloc(sizeof(*pCmapPriv)); - if (!pCmapPriv) - return FALSE; - pCmapPriv->cmap = (Colormap)0; - - DMX_SET_COLORMAP_PRIV(pColormap, pCmapPriv); - - return TRUE; -} - -/** Create \a pColormap on the back-end server. */ -Bool dmxBECreateColormap(ColormapPtr pColormap) -{ - ScreenPtr pScreen = pColormap->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); - VisualPtr pVisual = pColormap->pVisual; - Visual *visual = dmxLookupVisual(pScreen, pVisual); - - if (visual) { - pCmapPriv->cmap = XCreateColormap(dmxScreen->beDisplay, - dmxScreen->scrnWin, - visual, - (pVisual->class & DynamicClass ? - AllocAll : AllocNone)); - return (pCmapPriv->cmap != 0); - } - else { - dmxLog(dmxWarning, "dmxBECreateColormap: No visual found\n"); - return 0; - } -} - -/** Create colormap on back-end server associated with \a pColormap's - * screen. */ -Bool dmxCreateColormap(ColormapPtr pColormap) -{ - ScreenPtr pScreen = pColormap->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - Bool ret = TRUE; - - if (!dmxAllocateColormapPrivates(pColormap)) - return FALSE; - - if (dmxScreen->beDisplay) { - if (!dmxBECreateColormap(pColormap)) - return FALSE; - } - - DMX_UNWRAP(CreateColormap, dmxScreen, pScreen); - if (pScreen->CreateColormap) - ret = pScreen->CreateColormap(pColormap); - DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen); - - return ret; -} - -/** Destroy \a pColormap on the back-end server. */ -Bool dmxBEFreeColormap(ColormapPtr pColormap) -{ - ScreenPtr pScreen = pColormap->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); - - if (pCmapPriv->cmap) { - XFreeColormap(dmxScreen->beDisplay, pCmapPriv->cmap); - pCmapPriv->cmap = (Colormap)0; - return TRUE; - } - - return FALSE; -} - -/** Destroy colormap on back-end server associated with \a pColormap's - * screen. */ -void dmxDestroyColormap(ColormapPtr pColormap) -{ - ScreenPtr pScreen = pColormap->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); - - if (dmxScreen->beDisplay) - dmxBEFreeColormap(pColormap); - xfree(pCmapPriv); - DMX_SET_COLORMAP_PRIV(pColormap, NULL); - - DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen); - if (pScreen->DestroyColormap) - pScreen->DestroyColormap(pColormap); - DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen); -} - -/** Install colormap on back-end server associated with \a pColormap's - * screen. */ -void dmxInstallColormap(ColormapPtr pColormap) -{ - ScreenPtr pScreen = pColormap->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); - - DMX_UNWRAP(InstallColormap, dmxScreen, pScreen); - if (pScreen->InstallColormap) - pScreen->InstallColormap(pColormap); - DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen); - - if (dmxScreen->beDisplay) { - XInstallColormap(dmxScreen->beDisplay, pCmapPriv->cmap); - dmxSync(dmxScreen, FALSE); - } -} - -/** Store colors in \a pColormap on back-end server associated with \a - * pColormap's screen. */ -void dmxStoreColors(ColormapPtr pColormap, int ndef, xColorItem *pdef) -{ - ScreenPtr pScreen = pColormap->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); - - if (dmxScreen->beDisplay && (pColormap->pVisual->class & DynamicClass)) { - XColor *color = xalloc(sizeof(*color) * ndef); - int i; - - if (color) { - for (i = 0; i < ndef; i++) { - color[i].pixel = pdef[i].pixel; - color[i].red = pdef[i].red; - color[i].blue = pdef[i].blue; - color[i].green = pdef[i].green; - color[i].flags = pdef[i].flags; - color[i].pad = pdef[i].pad; - } - XStoreColors(dmxScreen->beDisplay, pCmapPriv->cmap, color, ndef); - xfree(color); - } else { /* xalloc failed, so fallback */ - XColor c; - for (i = 0; i < ndef; i++) { - c.pixel = pdef[i].pixel; - c.red = pdef[i].red; - c.blue = pdef[i].blue; - c.green = pdef[i].green; - c.flags = pdef[i].flags; - c.pad = pdef[i].pad; - XStoreColor(dmxScreen->beDisplay, pCmapPriv->cmap, &c); - } - } - dmxSync(dmxScreen, FALSE); - } - - DMX_UNWRAP(StoreColors, dmxScreen, pScreen); - if (pScreen->StoreColors) - pScreen->StoreColors(pColormap, ndef, pdef); - DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen); -} - -/** Create the DMX server's default colormap. */ -Bool dmxCreateDefColormap(ScreenPtr pScreen) -{ - return miCreateDefColormap(pScreen); -} +/* + * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 + * + */ + +/** \file + * Colormap support. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include "dmxlog.h" +#include "dmxsync.h" +#include "dmxcmap.h" +#include "dmxvisual.h" + +#include "micmap.h" + +static Bool dmxAllocateColormapPrivates(ColormapPtr pColormap) +{ + dmxColormapPrivPtr pCmapPriv; + + pCmapPriv = (dmxColormapPrivPtr)malloc(sizeof(*pCmapPriv)); + if (!pCmapPriv) + return FALSE; + pCmapPriv->cmap = (Colormap)0; + + DMX_SET_COLORMAP_PRIV(pColormap, pCmapPriv); + + return TRUE; +} + +/** Create \a pColormap on the back-end server. */ +Bool dmxBECreateColormap(ColormapPtr pColormap) +{ + ScreenPtr pScreen = pColormap->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); + VisualPtr pVisual = pColormap->pVisual; + Visual *visual = dmxLookupVisual(pScreen, pVisual); + + if (visual) { + pCmapPriv->cmap = XCreateColormap(dmxScreen->beDisplay, + dmxScreen->scrnWin, + visual, + (pVisual->class & DynamicClass ? + AllocAll : AllocNone)); + return (pCmapPriv->cmap != 0); + } + else { + dmxLog(dmxWarning, "dmxBECreateColormap: No visual found\n"); + return 0; + } +} + +/** Create colormap on back-end server associated with \a pColormap's + * screen. */ +Bool dmxCreateColormap(ColormapPtr pColormap) +{ + ScreenPtr pScreen = pColormap->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Bool ret = TRUE; + + if (!dmxAllocateColormapPrivates(pColormap)) + return FALSE; + + if (dmxScreen->beDisplay) { + if (!dmxBECreateColormap(pColormap)) + return FALSE; + } + + DMX_UNWRAP(CreateColormap, dmxScreen, pScreen); + if (pScreen->CreateColormap) + ret = pScreen->CreateColormap(pColormap); + DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen); + + return ret; +} + +/** Destroy \a pColormap on the back-end server. */ +Bool dmxBEFreeColormap(ColormapPtr pColormap) +{ + ScreenPtr pScreen = pColormap->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); + + if (pCmapPriv->cmap) { + XFreeColormap(dmxScreen->beDisplay, pCmapPriv->cmap); + pCmapPriv->cmap = (Colormap)0; + return TRUE; + } + + return FALSE; +} + +/** Destroy colormap on back-end server associated with \a pColormap's + * screen. */ +void dmxDestroyColormap(ColormapPtr pColormap) +{ + ScreenPtr pScreen = pColormap->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); + + if (dmxScreen->beDisplay) + dmxBEFreeColormap(pColormap); + free(pCmapPriv); + DMX_SET_COLORMAP_PRIV(pColormap, NULL); + + DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen); + if (pScreen->DestroyColormap) + pScreen->DestroyColormap(pColormap); + DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen); +} + +/** Install colormap on back-end server associated with \a pColormap's + * screen. */ +void dmxInstallColormap(ColormapPtr pColormap) +{ + ScreenPtr pScreen = pColormap->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); + + DMX_UNWRAP(InstallColormap, dmxScreen, pScreen); + if (pScreen->InstallColormap) + pScreen->InstallColormap(pColormap); + DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen); + + if (dmxScreen->beDisplay) { + XInstallColormap(dmxScreen->beDisplay, pCmapPriv->cmap); + dmxSync(dmxScreen, FALSE); + } +} + +/** Store colors in \a pColormap on back-end server associated with \a + * pColormap's screen. */ +void dmxStoreColors(ColormapPtr pColormap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pColormap->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxColormapPrivPtr pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap); + + if (dmxScreen->beDisplay && (pColormap->pVisual->class & DynamicClass)) { + XColor *color = malloc(sizeof(*color) * ndef); + int i; + + if (color) { + for (i = 0; i < ndef; i++) { + color[i].pixel = pdef[i].pixel; + color[i].red = pdef[i].red; + color[i].blue = pdef[i].blue; + color[i].green = pdef[i].green; + color[i].flags = pdef[i].flags; + color[i].pad = pdef[i].pad; + } + XStoreColors(dmxScreen->beDisplay, pCmapPriv->cmap, color, ndef); + free(color); + } else { /* xalloc failed, so fallback */ + XColor c; + for (i = 0; i < ndef; i++) { + c.pixel = pdef[i].pixel; + c.red = pdef[i].red; + c.blue = pdef[i].blue; + c.green = pdef[i].green; + c.flags = pdef[i].flags; + c.pad = pdef[i].pad; + XStoreColor(dmxScreen->beDisplay, pCmapPriv->cmap, &c); + } + } + dmxSync(dmxScreen, FALSE); + } + + DMX_UNWRAP(StoreColors, dmxScreen, pScreen); + if (pScreen->StoreColors) + pScreen->StoreColors(pColormap, ndef, pdef); + DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen); +} + +/** Create the DMX server's default colormap. */ +Bool dmxCreateDefColormap(ScreenPtr pScreen) +{ + return miCreateDefColormap(pScreen); +} diff --git a/xorg-server/hw/dmx/dmxcursor.c b/xorg-server/hw/dmx/dmxcursor.c index 37e66d758..2d0243343 100644 --- a/xorg-server/hw/dmx/dmxcursor.c +++ b/xorg-server/hw/dmx/dmxcursor.c @@ -1,985 +1,985 @@ -/* - * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: - * David H. Dawes - * Kevin E. Martin - * Rickard E. (Rik) Faith - * - */ - -/** \file - * This file contains code than supports cursor movement, including the - * code that initializes and reinitializes the screen positions and - * computes screen overlap. - * - * "This code is based very closely on the XFree86 equivalent - * (xfree86/common/xf86Cursor.c)." --David Dawes. - * - * "This code was then extensively re-written, as explained here." - * --Rik Faith - * - * The code in xf86Cursor.c used edge lists to implement the - * CursorOffScreen function. The edge list computation was complex - * (especially in the face of arbitrarily overlapping screens) compared - * with the speed savings in the CursorOffScreen function. The new - * implementation has erred on the side of correctness, readability, and - * maintainability over efficiency. For the common (non-edge) case, the - * dmxCursorOffScreen function does avoid a loop over all the screens. - * When the cursor has left the screen, all the screens are searched, - * and the first screen (in dmxScreens order) containing the cursor will - * be returned. If run-time profiling shows that this routing is a - * performance bottle-neck, then an edge list may have to be - * reimplemented. An edge list algorithm is O(edges) whereas the new - * algorithm is O(dmxNumScreens). Since edges is usually 1-3 and - * dmxNumScreens may be 30-60 for large backend walls, this trade off - * may be compelling. - * - * The xf86InitOrigins routine uses bit masks during the computation and - * is therefore limited to the length of a word (e.g., 32 or 64 bits) - * screens. Because Xdmx is expected to be used with a large number of - * backend displays, this limitation was removed. The new - * implementation has erred on the side of readability over efficiency, - * using the dmxSL* routines to manage a screen list instead of a - * bitmap, and a function call to decrease the length of the main - * routine. Both algorithms are of the same order, and both are called - * only at server generation time, so trading clarity and long-term - * maintainability for efficiency does not seem justified in this case. - */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#define DMX_CURSOR_DEBUG 0 - -#include "dmx.h" -#include "dmxsync.h" -#include "dmxcursor.h" -#include "dmxlog.h" -#include "dmxprop.h" -#include "dmxinput.h" - -#include "mipointer.h" -#include "windowstr.h" -#include "globals.h" -#include "cursorstr.h" -#include "dixevents.h" /* For GetSpriteCursor() */ -#include "inputstr.h" /* for inputInfo.pointer */ - -#if DMX_CURSOR_DEBUG -#define DMXDBG0(f) dmxLog(dmxDebug,f) -#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a) -#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b) -#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) -#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d) -#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e) -#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g) -#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h) -#else -#define DMXDBG0(f) -#define DMXDBG1(f,a) -#define DMXDBG2(f,a,b) -#define DMXDBG3(f,a,b,c) -#define DMXDBG4(f,a,b,c,d) -#define DMXDBG5(f,a,b,c,d,e) -#define DMXDBG6(f,a,b,c,d,e,g) -#define DMXDBG7(f,a,b,c,d,e,g,h) -#endif - -static int dmxCursorDoMultiCursors = 1; - -/** Turn off support for displaying multiple cursors on overlapped - back-end displays. See #dmxCursorDoMultiCursors. */ -void dmxCursorNoMulti(void) -{ - dmxCursorDoMultiCursors = 0; -} - -static Bool dmxCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) -{ - DMXScreenInfo *dmxScreen; - int i; - int localX = *x; - int localY = *y; - int globalX; - int globalY; - - if (screenInfo.numScreens == 1) - return FALSE; - - /* On current screen? */ - dmxScreen = &dmxScreens[(*ppScreen)->myNum]; - if (localX >= 0 - && localX < dmxScreen->rootWidth - && localY >= 0 - && localY < dmxScreen->rootHeight) - return FALSE; - - /* Convert to global coordinate space */ - globalX = dmxScreen->rootXOrigin + localX; - globalY = dmxScreen->rootYOrigin + localY; - - /* Is cursor on the current screen? - * This efficiently exits this routine - * for the most common case. */ - if (ppScreen && *ppScreen) { - dmxScreen = &dmxScreens[(*ppScreen)->myNum]; - if (globalX >= dmxScreen->rootXOrigin - && globalX < dmxScreen->rootXOrigin + dmxScreen->rootWidth - && globalY >= dmxScreen->rootYOrigin - && globalY < dmxScreen->rootYOrigin + dmxScreen->rootHeight) - return FALSE; - } - - /* Find first screen cursor is on */ - for (i = 0; i < dmxNumScreens; i++) { - dmxScreen = &dmxScreens[i]; - if (globalX >= dmxScreen->rootXOrigin - && globalX < dmxScreen->rootXOrigin + dmxScreen->rootWidth - && globalY >= dmxScreen->rootYOrigin - && globalY < dmxScreen->rootYOrigin + dmxScreen->rootHeight) { - if (dmxScreen->index == (*ppScreen)->myNum) - return FALSE; - *ppScreen = screenInfo.screens[dmxScreen->index]; - *x = globalX - dmxScreen->rootXOrigin; - *y = globalY - dmxScreen->rootYOrigin; - return TRUE; - } - } - return FALSE; -} - -static void dmxCrossScreen(ScreenPtr pScreen, Bool entering) -{ -} - -static void dmxWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - DMXDBG3("dmxWarpCursor(%d,%d,%d)\n", pScreen->myNum, x, y); -#if 11 /*BP*/ - /* This call is depracated. Replace with???? */ - miPointerWarpCursor(pDev, pScreen, x, y); -#else - pScreen->SetCursorPosition(pDev, pScreen, x, y, FALSE); -#endif -} - -miPointerScreenFuncRec dmxPointerCursorFuncs = -{ - dmxCursorOffScreen, - dmxCrossScreen, - dmxWarpCursor, - NULL, - NULL, -}; - - -/** Create a list of screens that we'll manipulate. */ -static int *dmxSLCreate(void) -{ - int *list = malloc(dmxNumScreens * sizeof(*list)); - int i; - - for (i = 0; i < dmxNumScreens; i++) - list[i] = 1; - return list; -} - -/** Free list. */ -static void dmxSLFree(int *list) -{ - free(list); -} - -/** Find next uninitialized entry in list. */ -static int dmxSLFindNext(int *list) -{ - int i; - for (i = 0; i < dmxNumScreens; i++) - if (list[i]) - return i; - return -1; -} - -/** Make one pass over all the screens and return the number updated. */ -static int dmxTryComputeScreenOrigins(int *screensLeft) -{ - ScreenPtr pScreen; - DMXScreenInfo *screen; - int i, ref; - int changed = 0; - - for (i = 0; i < dmxNumScreens; i++) { - if (!screensLeft[i]) - continue; - screen = &dmxScreens[i]; - switch (screen->where) { - case PosAbsolute: - dixScreenOrigins[i].x = screen->whereX; - dixScreenOrigins[i].y = screen->whereY; - ++changed, screensLeft[i] = 0; - break; - case PosRelative: - ref = screen->whereRefScreen; - if (screensLeft[ref]) - break; - dixScreenOrigins[i].x = dixScreenOrigins[ref].x + screen->whereX; - dixScreenOrigins[i].y = dixScreenOrigins[ref].y + screen->whereY; - ++changed, screensLeft[i] = 0; - break; - case PosRightOf: - ref = screen->whereRefScreen; - if (screensLeft[ref]) - break; - pScreen = screenInfo.screens[ref]; - dixScreenOrigins[i].x = dixScreenOrigins[ref].x + pScreen->width; - dixScreenOrigins[i].y = dixScreenOrigins[ref].y; - ++changed, screensLeft[i] = 0; - break; - case PosLeftOf: - ref = screen->whereRefScreen; - if (screensLeft[ref]) - break; - pScreen = screenInfo.screens[i]; - dixScreenOrigins[i].x = dixScreenOrigins[ref].x - pScreen->width; - dixScreenOrigins[i].y = dixScreenOrigins[ref].y; - ++changed, screensLeft[i] = 0; - break; - case PosBelow: - ref = screen->whereRefScreen; - if (screensLeft[ref]) - break; - pScreen = screenInfo.screens[ref]; - dixScreenOrigins[i].x = dixScreenOrigins[ref].x; - dixScreenOrigins[i].y = dixScreenOrigins[ref].y + pScreen->height; - ++changed, screensLeft[i] = 0; - break; - case PosAbove: - ref = screen->whereRefScreen; - if (screensLeft[ref]) - break; - pScreen = screenInfo.screens[i]; - dixScreenOrigins[i].x = dixScreenOrigins[ref].x; - dixScreenOrigins[i].y = dixScreenOrigins[ref].y - pScreen->height; - ++changed, screensLeft[i] = 0; - break; - case PosNone: - dmxLog(dmxFatal, "No position information for screen %d\n", i); - } - } - return changed; -} - -static void dmxComputeScreenOrigins(void) -{ - int *screensLeft; - int i, ref; - int minX, minY; - - /* Compute origins based on - * configuration information. */ - screensLeft = dmxSLCreate(); - while ((i = dmxSLFindNext(screensLeft)) >= 0) { - while (dmxTryComputeScreenOrigins(screensLeft)); - if ((i = dmxSLFindNext(screensLeft)) >= 0) { - /* All of the remaining screens are referencing each other. - * Assign a value to one of them and go through again. This - * guarantees that we will eventually terminate. - */ - ref = dmxScreens[i].whereRefScreen; - dixScreenOrigins[ref].x = dixScreenOrigins[ref].y = 0; - screensLeft[ref] = 0; - } - } - dmxSLFree(screensLeft); - - - /* Justify the topmost and leftmost to - * (0,0). */ - minX = dixScreenOrigins[0].x; - minY = dixScreenOrigins[0].y; - for (i = 1; i < dmxNumScreens; i++) { /* Compute minX, minY */ - 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 < dmxNumScreens; i++) { - dixScreenOrigins[i].x -= minX; - dixScreenOrigins[i].y -= minY; - } - } -} - -/** Recompute origin information in the #dmxScreens list. This is - * called from #dmxInitOrigins. */ -void dmxReInitOrigins(void) -{ - int i; - - if (dmxNumScreens > MAXSCREENS) - dmxLog(dmxFatal, "dmxNumScreens = %d > MAXSCREENS = %d\n", - dmxNumScreens, MAXSCREENS); - - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - dmxLogOutput(dmxScreen, - "s=%dx%d%+d%+d r=%dx%d%+d%+d @%d,%d" - " (be=%dx%d depth=%d bpp=%d)\n", - dmxScreen->scrnWidth, dmxScreen->scrnHeight, - dmxScreen->scrnX, dmxScreen->scrnY, - - dmxScreen->rootWidth, dmxScreen->rootHeight, - dmxScreen->rootX, dmxScreen->rootY, - - dmxScreen->rootXOrigin, dmxScreen->rootYOrigin, - dmxScreen->beWidth, dmxScreen->beHeight, - dmxScreen->beDepth, dmxScreen->beBPP); - } -} - -/** Initialize screen origins (and relative position). This is called - * for each server generation. For dynamic reconfiguration, use - * #dmxReInitOrigins() instead. */ -void dmxInitOrigins(void) -{ - int i; - - if (dmxNumScreens > MAXSCREENS) - dmxLog(dmxFatal, "dmxNumScreens = %d > MAXSCREENS = %d\n", - dmxNumScreens, MAXSCREENS); - - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - dmxLogOutput(dmxScreen, - "(request) s=%dx%d%+d%+d r=%dx%d%+d%+d @%d,%d (%d)" - " (be=%dx%d depth=%d bpp=%d)\n", - dmxScreen->scrnWidth, dmxScreen->scrnHeight, - dmxScreen->scrnX, dmxScreen->scrnY, - - dmxScreen->rootWidth, dmxScreen->rootHeight, - dmxScreen->rootX, dmxScreen->rootY, - - dmxScreen->whereX, dmxScreen->whereY, - dmxScreen->where, - - dmxScreen->beWidth, dmxScreen->beHeight, - dmxScreen->beDepth, dmxScreen->beBPP); - } - - dmxComputeScreenOrigins(); - - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - dmxScreen->rootXOrigin = dixScreenOrigins[i].x; - dmxScreen->rootYOrigin = dixScreenOrigins[i].y; - } - - dmxReInitOrigins(); -} - -/** Returns non-zero if the global \a x, \a y coordinate is on the - * screen window of the \a dmxScreen. */ -int dmxOnScreen(int x, int y, DMXScreenInfo *dmxScreen) -{ -#if DMX_CURSOR_DEBUG > 1 - dmxLog(dmxDebug, - "dmxOnScreen %d %d,%d (r=%dx%d%+d%+d@%d,%d s=%dx%d%+d%+d)\n", - dmxScreen->index, x, y, - dmxScreen->rootWidth, dmxScreen->rootHeight, - dmxScreen->rootX, dmxScreen->rootY, - dmxScreen->rootXOrigin, dmxScreen->rootYOrigin, - dmxScreen->scrnWidth, dmxScreen->scrnHeight, - dmxScreen->scrnX, dmxScreen->scrnY); -#endif - if (x >= dmxScreen->rootXOrigin - && x < dmxScreen->rootXOrigin + dmxScreen->rootWidth - && y >= dmxScreen->rootYOrigin - && y < dmxScreen->rootYOrigin + dmxScreen->rootHeight) return 1; - return 0; -} - -/** Returns non-zero if \a a overlaps \a b. */ -static int dmxDoesOverlap(DMXScreenInfo *a, DMXScreenInfo *b) -{ - if (dmxOnScreen(a->rootXOrigin, - a->rootYOrigin, b)) - return 1; - - if (dmxOnScreen(a->rootXOrigin, - a->rootYOrigin + a->scrnWidth, b)) - return 1; - - if (dmxOnScreen(a->rootXOrigin + a->scrnHeight, - a->rootYOrigin, b)) - return 1; - - if (dmxOnScreen(a->rootXOrigin + a->scrnHeight, - a->rootYOrigin + a->scrnWidth, b)) - return 1; - - if (dmxOnScreen(b->rootXOrigin, - b->rootYOrigin, a)) - return 1; - - if (dmxOnScreen(b->rootXOrigin, - b->rootYOrigin + b->scrnWidth, a)) - return 1; - - if (dmxOnScreen(b->rootXOrigin + b->scrnHeight, - b->rootYOrigin, a)) - return 1; - - if (dmxOnScreen(b->rootXOrigin + b->scrnHeight, - b->rootYOrigin + b->scrnWidth, a)) - return 1; - - return 0; -} - -/** Used with \a dmxInterateOverlap to print out a list of screens which - * overlap each other. */ -static void *dmxPrintOverlap(DMXScreenInfo *dmxScreen, void *closure) -{ - DMXScreenInfo *a = closure; - if (dmxScreen != a) { - if (dmxScreen->cursorNotShared) - dmxLogOutputCont(a, " [%d/%s]", dmxScreen->index, dmxScreen->name); - else - dmxLogOutputCont(a, " %d/%s", dmxScreen->index, dmxScreen->name); - } - return NULL; -} - -/** Iterate over the screens which overlap with the \a start screen, - * calling \a f with the \a closure for each argument. Often used with - * #dmxPrintOverlap. */ -static void *dmxIterateOverlap(DMXScreenInfo *start, - void *(*f)(DMXScreenInfo *dmxScreen, void *), - void *closure) -{ - DMXScreenInfo *pt; - - if (!start->over) return f(start, closure); - - for (pt = start->over; /* condition at end of loop */; pt = pt->over) { - void *retval; - if ((retval = f(pt, closure))) return retval; - if (pt == start) break; - } - return NULL; -} - -/** Used with #dmxPropertyIterate to determine if screen \a a is the - * same as the screen \a closure. */ -static void *dmxTestSameDisplay(DMXScreenInfo *a, void *closure) -{ - DMXScreenInfo *b = closure; - - if (a == b) - return a; - return NULL; -} - -/** Detects overlapping dmxScreens and creates circular lists. This - * uses an O(dmxNumScreens^2) algorithm, but dmxNumScreens is < 100 and - * the computation only needs to be performed for every server - * generation or dynamic reconfiguration . */ -void dmxInitOverlap(void) -{ - int i, j; - DMXScreenInfo *a, *b, *pt; - - for (i = 0; i < dmxNumScreens; i++) - dmxScreens[i].over = NULL; - - for (i = 0; i < dmxNumScreens; i++) { - a = &dmxScreens[i]; - - for (j = i+1; j < dmxNumScreens; j++) { - b = &dmxScreens[j]; - if (b->over) - continue; - - if (dmxDoesOverlap(a, b)) { - DMXDBG6("%d overlaps %d: a=%p %p b=%p %p\n", - a->index, b->index, a, a->over, b, b->over); - b->over = (a->over ? a->over : a); - a->over = b; - } - } - } - - for (i = 0; i < dmxNumScreens; i++) { - a = &dmxScreens[i]; - - if (!a->over) - continue; - - /* Flag all pairs that are on same display */ - for (pt = a->over; pt != a; pt = pt->over) { - if (dmxPropertyIterate(a, dmxTestSameDisplay, pt)) { - /* The ->over sets contain the transitive set of screens - * that overlap. For screens that are on the same - * backend display, we only want to exclude pairs of - * screens that mutually overlap on the backend display, - * so we call dmxDoesOverlap, which is stricter than the - * ->over set. */ - if (!dmxDoesOverlap(a, pt)) - continue; - a->cursorNotShared = 1; - pt->cursorNotShared = 1; - dmxLog(dmxInfo, - "Screen %d and %d overlap on %s\n", - a->index, pt->index, a->name); - } - } - } - - for (i = 0; i < dmxNumScreens; i++) { - a = &dmxScreens[i]; - - if (a->over) { - dmxLogOutput(a, "Overlaps"); - dmxIterateOverlap(a, dmxPrintOverlap, a); - dmxLogOutputCont(a, "\n"); - } - } -} - -/** Create \a pCursor on the back-end associated with \a pScreen. */ -void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen); - CursorBitsPtr pBits = pCursor->bits; - Pixmap src, msk; - XColor fg, bg; - XImage *img; - XlibGC gc = NULL; - XGCValues v; - unsigned long m; - int i; - - if (!pCursorPriv) - return; - - m = GCFunction | GCPlaneMask | GCForeground | GCBackground | GCClipMask; - v.function = GXcopy; - v.plane_mask = AllPlanes; - v.foreground = 1L; - v.background = 0L; - v.clip_mask = None; - - for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { - if (dmxScreen->bePixmapFormats[i].depth == 1) { - /* Create GC in the back-end servers */ - gc = XCreateGC(dmxScreen->beDisplay, dmxScreen->scrnDefDrawables[i], - m, &v); - break; - } - } - if (!gc) - dmxLog(dmxFatal, "dmxRealizeCursor: gc not initialized\n"); - - src = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin, - pBits->width, pBits->height, 1); - msk = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin, - pBits->width, pBits->height, 1); - - img = XCreateImage(dmxScreen->beDisplay, - dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, - 1, XYBitmap, 0, (char *)pBits->source, - pBits->width, pBits->height, - BitmapPad(dmxScreen->beDisplay), 0); - - XPutImage(dmxScreen->beDisplay, src, gc, img, 0, 0, 0, 0, - pBits->width, pBits->height); - - XFree(img); - - img = XCreateImage(dmxScreen->beDisplay, - dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, - 1, XYBitmap, 0, (char *)pBits->mask, - pBits->width, pBits->height, - BitmapPad(dmxScreen->beDisplay), 0); - - XPutImage(dmxScreen->beDisplay, msk, gc, img, 0, 0, 0, 0, - pBits->width, pBits->height); - - XFree(img); - - fg.red = pCursor->foreRed; - fg.green = pCursor->foreGreen; - fg.blue = pCursor->foreBlue; - - bg.red = pCursor->backRed; - bg.green = pCursor->backGreen; - bg.blue = pCursor->backBlue; - - pCursorPriv->cursor = XCreatePixmapCursor(dmxScreen->beDisplay, - src, msk, - &fg, &bg, - pBits->xhot, pBits->yhot); - - XFreePixmap(dmxScreen->beDisplay, src); - XFreePixmap(dmxScreen->beDisplay, msk); - XFreeGC(dmxScreen->beDisplay, gc); - - dmxSync(dmxScreen, FALSE); -} - -static Bool _dmxRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxCursorPrivPtr pCursorPriv; - - DMXDBG2("_dmxRealizeCursor(%d,%p)\n", pScreen->myNum, pCursor); - - DMX_SET_CURSOR_PRIV(pCursor, pScreen, xalloc(sizeof(*pCursorPriv))); - if (!DMX_GET_CURSOR_PRIV(pCursor, pScreen)) - return FALSE; - - pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen); - pCursorPriv->cursor = (Cursor)0; - - if (!dmxScreen->beDisplay) - return TRUE; - - dmxBECreateCursor(pScreen, pCursor); - return TRUE; -} - -/** Free \a pCursor on the back-end associated with \a pScreen. */ -Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen); - - if (pCursorPriv) { - XFreeCursor(dmxScreen->beDisplay, pCursorPriv->cursor); - pCursorPriv->cursor = (Cursor)0; - return TRUE; - } - - return FALSE; -} - -static Bool _dmxUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - - DMXDBG2("_dmxUnrealizeCursor(%d,%p)\n", - pScreen->myNum, pCursor); - - if (dmxScreen->beDisplay) { - if (dmxBEFreeCursor(pScreen, pCursor)) - xfree(DMX_GET_CURSOR_PRIV(pCursor, pScreen)); - } - DMX_SET_CURSOR_PRIV(pCursor, pScreen, NULL); - - return TRUE; -} - -static void _dmxMoveCursor(ScreenPtr pScreen, int x, int y) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - int newX = x + dmxScreen->rootX; - int newY = y + dmxScreen->rootY; - - if (newX < 0) newX = 0; - if (newY < 0) newY = 0; - - DMXDBG5("_dmxMoveCursor(%d,%d,%d) -> %d,%d\n", - pScreen->myNum, x, y, newX, newY); - if (dmxScreen->beDisplay) { - XWarpPointer(dmxScreen->beDisplay, None, dmxScreen->scrnWin, - 0, 0, 0, 0, newX, newY); - dmxSync(dmxScreen, TRUE); - } -} - -static void _dmxSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - - DMXDBG4("_dmxSetCursor(%d,%p,%d,%d)\n", pScreen->myNum, pCursor, x, y); - - if (pCursor) { - dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen); - if (pCursorPriv && dmxScreen->curCursor != pCursorPriv->cursor) { - if (dmxScreen->beDisplay) - XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin, - pCursorPriv->cursor); - dmxScreen->cursor = pCursor; - dmxScreen->curCursor = pCursorPriv->cursor; - dmxScreen->cursorVisible = 1; - } - _dmxMoveCursor(pScreen, x, y); - } else { - if (dmxScreen->beDisplay) - XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin, - dmxScreen->noCursor); - dmxScreen->cursor = NULL; - dmxScreen->curCursor = (Cursor)0; - dmxScreen->cursorVisible = 0; - } - if (dmxScreen->beDisplay) dmxSync(dmxScreen, TRUE); -} - -static Bool dmxRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - DMXScreenInfo *start = &dmxScreens[pScreen->myNum]; - DMXScreenInfo *pt; - - if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) - return _dmxRealizeCursor(pScreen, pCursor); - - for (pt = start->over; /* condition at end of loop */; pt = pt->over) { - if (pt->cursorNotShared) - continue; - _dmxRealizeCursor(screenInfo.screens[pt->index], pCursor); - if (pt == start) - break; - } - return TRUE; -} - -static Bool dmxUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - DMXScreenInfo *start = &dmxScreens[pScreen->myNum]; - DMXScreenInfo *pt; - - if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) - return _dmxUnrealizeCursor(pScreen, pCursor); - - for (pt = start->over; /* condition at end of loop */; pt = pt->over) { - if (pt->cursorNotShared) - continue; - _dmxUnrealizeCursor(screenInfo.screens[pt->index], pCursor); - if (pt == start) - break; - } - return TRUE; -} - -static CursorPtr dmxFindCursor(DMXScreenInfo *start) -{ - DMXScreenInfo *pt; - - if (!start || !start->over) - return GetSpriteCursor(inputInfo.pointer); - for (pt = start->over; /* condition at end of loop */; pt = pt->over) { - if (pt->cursor) - return pt->cursor; - if (pt == start) - break; - } - return GetSpriteCursor(inputInfo.pointer); -} - -/** Move the cursor to coordinates (\a x, \a y)on \a pScreen. This - * function is usually called via #dmxPointerSpriteFuncs, except during - * reconfiguration when the cursor is repositioned to force an update on - * newley overlapping screens and on screens that no longer overlap. - * - * The coords (x,y) are in global coord space. We'll loop over the - * back-end screens and see if they contain the global coord. If so, call - * _dmxMoveCursor() (XWarpPointer) to position the pointer on that screen. - */ -void dmxMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - DMXScreenInfo *start = &dmxScreens[pScreen->myNum]; - DMXScreenInfo *pt; - - DMXDBG3("dmxMoveCursor(%d,%d,%d)\n", pScreen->myNum, x, y); - - if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) { - _dmxMoveCursor(pScreen, x, y); - return; - } - - for (pt = start->over; /* condition at end of loop */; pt = pt->over) { - if (pt->cursorNotShared) - continue; - if (dmxOnScreen(x + start->rootXOrigin, y + start->rootYOrigin, pt)) { - if (/* pt != start && */ !pt->cursorVisible) { - if (!pt->cursor) { - /* This only happens during - * reconfiguration when a new overlap - * occurs. */ - CursorPtr pCursor; - - if ((pCursor = dmxFindCursor(start))) - _dmxRealizeCursor(screenInfo.screens[pt->index], - pt->cursor = pCursor); - - } - _dmxSetCursor(screenInfo.screens[pt->index], - pt->cursor, - x + start->rootXOrigin - pt->rootXOrigin, - y + start->rootYOrigin - pt->rootYOrigin); - } - _dmxMoveCursor(screenInfo.screens[pt->index], - x + start->rootXOrigin - pt->rootXOrigin, - y + start->rootYOrigin - pt->rootYOrigin); - } else if (/* pt != start && */ pt->cursorVisible) { - _dmxSetCursor(screenInfo.screens[pt->index], - NULL, - x + start->rootXOrigin - pt->rootXOrigin, - y + start->rootYOrigin - pt->rootYOrigin); - } - if (pt == start) - break; - } -} - -static void dmxSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) -{ - DMXScreenInfo *start = &dmxScreens[pScreen->myNum]; - DMXScreenInfo *pt; - int GX, GY, gx, gy; - - DMXDBG5("dmxSetCursor(%d %p, %p,%d,%d)\n", - pScreen->myNum, start, pCursor, x, y); - - /* We do this check here because of two cases: - * - * 1) if a client calls XWarpPointer() - * and Xinerama is not running, we can - * have mi's notion of the pointer - * position out of phase with DMX's - * notion. - * - * 2) if a down button is held while the - * cursor moves outside the root window, - * mi's notion of the pointer position - * is out of phase with DMX's notion and - * the cursor can remain visible when it - * shouldn't be. */ - - dmxGetGlobalPosition(&GX, &GY); - gx = start->rootXOrigin + x; - gy = start->rootYOrigin + y; - if (x && y && (GX != gx || GY != gy)) - dmxCoreMotion(NULL, gx, gy, 0, DMX_NO_BLOCK); - - if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) { - _dmxSetCursor(pScreen, pCursor, x, y); - return; - } - - for (pt = start->over; /* condition at end of loop */; pt = pt->over) { - if (pt->cursorNotShared) - continue; - if (dmxOnScreen(x + start->rootXOrigin, y + start->rootYOrigin, pt)) { - _dmxSetCursor(screenInfo.screens[pt->index], pCursor, - x + start->rootXOrigin - pt->rootXOrigin, - y + start->rootYOrigin - pt->rootYOrigin); - } else { - _dmxSetCursor(screenInfo.screens[pt->index], NULL, - x + start->rootXOrigin - pt->rootXOrigin, - y + start->rootYOrigin - pt->rootYOrigin); - } - if (pt == start) - break; - } -} - - -/** This routine is used by the backend input routines to hide the - * cursor on a screen that is being used for relative input. \see - * dmxbackend.c */ -void dmxHideCursor(DMXScreenInfo *dmxScreen) -{ - int x, y; - ScreenPtr pScreen = screenInfo.screens[dmxScreen->index]; - - dmxGetGlobalPosition(&x, &y); - _dmxSetCursor(pScreen, NULL, x, y); -} - -/** This routine is called during reconfiguration to make sure the - * cursor is visible. */ -void dmxCheckCursor(void) -{ - int i; - int x, y; - ScreenPtr pScreen; - DMXScreenInfo *firstScreen; - - dmxGetGlobalPosition(&x, &y); - firstScreen = dmxFindFirstScreen(x, y); - - DMXDBG2("dmxCheckCursor %d %d\n", x, y); - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - pScreen = screenInfo.screens[dmxScreen->index]; - - if (!dmxOnScreen(x, y, dmxScreen)) { - if (firstScreen && i == miPointerGetScreen(inputInfo.pointer)->myNum) - miPointerSetScreen(inputInfo.pointer, firstScreen->index, x, y); - _dmxSetCursor(pScreen, NULL, - x - dmxScreen->rootXOrigin, - y - dmxScreen->rootYOrigin); - } else { - if (!dmxScreen->cursor) { - CursorPtr pCursor; - - if ((pCursor = dmxFindCursor(dmxScreen))) { - _dmxRealizeCursor(pScreen, dmxScreen->cursor = pCursor); - } - } - _dmxSetCursor(pScreen, dmxScreen->cursor, - x - dmxScreen->rootXOrigin, - y - dmxScreen->rootYOrigin); - } - } - DMXDBG2(" leave dmxCheckCursor %d %d\n", x, y); -} - -static Bool dmxDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) -{ - return TRUE; -} - -static void dmxDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) -{ -} - -miPointerSpriteFuncRec dmxPointerSpriteFuncs = -{ - dmxRealizeCursor, - dmxUnrealizeCursor, - dmxSetCursor, - dmxMoveCursor, - dmxDeviceCursorInitialize, - dmxDeviceCursorCleanup -}; +/* + * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: + * David H. Dawes + * Kevin E. Martin + * Rickard E. (Rik) Faith + * + */ + +/** \file + * This file contains code than supports cursor movement, including the + * code that initializes and reinitializes the screen positions and + * computes screen overlap. + * + * "This code is based very closely on the XFree86 equivalent + * (xfree86/common/xf86Cursor.c)." --David Dawes. + * + * "This code was then extensively re-written, as explained here." + * --Rik Faith + * + * The code in xf86Cursor.c used edge lists to implement the + * CursorOffScreen function. The edge list computation was complex + * (especially in the face of arbitrarily overlapping screens) compared + * with the speed savings in the CursorOffScreen function. The new + * implementation has erred on the side of correctness, readability, and + * maintainability over efficiency. For the common (non-edge) case, the + * dmxCursorOffScreen function does avoid a loop over all the screens. + * When the cursor has left the screen, all the screens are searched, + * and the first screen (in dmxScreens order) containing the cursor will + * be returned. If run-time profiling shows that this routing is a + * performance bottle-neck, then an edge list may have to be + * reimplemented. An edge list algorithm is O(edges) whereas the new + * algorithm is O(dmxNumScreens). Since edges is usually 1-3 and + * dmxNumScreens may be 30-60 for large backend walls, this trade off + * may be compelling. + * + * The xf86InitOrigins routine uses bit masks during the computation and + * is therefore limited to the length of a word (e.g., 32 or 64 bits) + * screens. Because Xdmx is expected to be used with a large number of + * backend displays, this limitation was removed. The new + * implementation has erred on the side of readability over efficiency, + * using the dmxSL* routines to manage a screen list instead of a + * bitmap, and a function call to decrease the length of the main + * routine. Both algorithms are of the same order, and both are called + * only at server generation time, so trading clarity and long-term + * maintainability for efficiency does not seem justified in this case. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#define DMX_CURSOR_DEBUG 0 + +#include "dmx.h" +#include "dmxsync.h" +#include "dmxcursor.h" +#include "dmxlog.h" +#include "dmxprop.h" +#include "dmxinput.h" + +#include "mipointer.h" +#include "windowstr.h" +#include "globals.h" +#include "cursorstr.h" +#include "dixevents.h" /* For GetSpriteCursor() */ +#include "inputstr.h" /* for inputInfo.pointer */ + +#if DMX_CURSOR_DEBUG +#define DMXDBG0(f) dmxLog(dmxDebug,f) +#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a) +#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b) +#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) +#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d) +#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e) +#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g) +#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h) +#else +#define DMXDBG0(f) +#define DMXDBG1(f,a) +#define DMXDBG2(f,a,b) +#define DMXDBG3(f,a,b,c) +#define DMXDBG4(f,a,b,c,d) +#define DMXDBG5(f,a,b,c,d,e) +#define DMXDBG6(f,a,b,c,d,e,g) +#define DMXDBG7(f,a,b,c,d,e,g,h) +#endif + +static int dmxCursorDoMultiCursors = 1; + +/** Turn off support for displaying multiple cursors on overlapped + back-end displays. See #dmxCursorDoMultiCursors. */ +void dmxCursorNoMulti(void) +{ + dmxCursorDoMultiCursors = 0; +} + +static Bool dmxCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) +{ + DMXScreenInfo *dmxScreen; + int i; + int localX = *x; + int localY = *y; + int globalX; + int globalY; + + if (screenInfo.numScreens == 1) + return FALSE; + + /* On current screen? */ + dmxScreen = &dmxScreens[(*ppScreen)->myNum]; + if (localX >= 0 + && localX < dmxScreen->rootWidth + && localY >= 0 + && localY < dmxScreen->rootHeight) + return FALSE; + + /* Convert to global coordinate space */ + globalX = dmxScreen->rootXOrigin + localX; + globalY = dmxScreen->rootYOrigin + localY; + + /* Is cursor on the current screen? + * This efficiently exits this routine + * for the most common case. */ + if (ppScreen && *ppScreen) { + dmxScreen = &dmxScreens[(*ppScreen)->myNum]; + if (globalX >= dmxScreen->rootXOrigin + && globalX < dmxScreen->rootXOrigin + dmxScreen->rootWidth + && globalY >= dmxScreen->rootYOrigin + && globalY < dmxScreen->rootYOrigin + dmxScreen->rootHeight) + return FALSE; + } + + /* Find first screen cursor is on */ + for (i = 0; i < dmxNumScreens; i++) { + dmxScreen = &dmxScreens[i]; + if (globalX >= dmxScreen->rootXOrigin + && globalX < dmxScreen->rootXOrigin + dmxScreen->rootWidth + && globalY >= dmxScreen->rootYOrigin + && globalY < dmxScreen->rootYOrigin + dmxScreen->rootHeight) { + if (dmxScreen->index == (*ppScreen)->myNum) + return FALSE; + *ppScreen = screenInfo.screens[dmxScreen->index]; + *x = globalX - dmxScreen->rootXOrigin; + *y = globalY - dmxScreen->rootYOrigin; + return TRUE; + } + } + return FALSE; +} + +static void dmxCrossScreen(ScreenPtr pScreen, Bool entering) +{ +} + +static void dmxWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + DMXDBG3("dmxWarpCursor(%d,%d,%d)\n", pScreen->myNum, x, y); +#if 11 /*BP*/ + /* This call is depracated. Replace with???? */ + miPointerWarpCursor(pDev, pScreen, x, y); +#else + pScreen->SetCursorPosition(pDev, pScreen, x, y, FALSE); +#endif +} + +miPointerScreenFuncRec dmxPointerCursorFuncs = +{ + dmxCursorOffScreen, + dmxCrossScreen, + dmxWarpCursor, + NULL, + NULL, +}; + + +/** Create a list of screens that we'll manipulate. */ +static int *dmxSLCreate(void) +{ + int *list = malloc(dmxNumScreens * sizeof(*list)); + int i; + + for (i = 0; i < dmxNumScreens; i++) + list[i] = 1; + return list; +} + +/** Free list. */ +static void dmxSLFree(int *list) +{ + free(list); +} + +/** Find next uninitialized entry in list. */ +static int dmxSLFindNext(int *list) +{ + int i; + for (i = 0; i < dmxNumScreens; i++) + if (list[i]) + return i; + return -1; +} + +/** Make one pass over all the screens and return the number updated. */ +static int dmxTryComputeScreenOrigins(int *screensLeft) +{ + ScreenPtr pScreen; + DMXScreenInfo *screen; + int i, ref; + int changed = 0; + + for (i = 0; i < dmxNumScreens; i++) { + if (!screensLeft[i]) + continue; + screen = &dmxScreens[i]; + switch (screen->where) { + case PosAbsolute: + dixScreenOrigins[i].x = screen->whereX; + dixScreenOrigins[i].y = screen->whereY; + ++changed, screensLeft[i] = 0; + break; + case PosRelative: + ref = screen->whereRefScreen; + if (screensLeft[ref]) + break; + dixScreenOrigins[i].x = dixScreenOrigins[ref].x + screen->whereX; + dixScreenOrigins[i].y = dixScreenOrigins[ref].y + screen->whereY; + ++changed, screensLeft[i] = 0; + break; + case PosRightOf: + ref = screen->whereRefScreen; + if (screensLeft[ref]) + break; + pScreen = screenInfo.screens[ref]; + dixScreenOrigins[i].x = dixScreenOrigins[ref].x + pScreen->width; + dixScreenOrigins[i].y = dixScreenOrigins[ref].y; + ++changed, screensLeft[i] = 0; + break; + case PosLeftOf: + ref = screen->whereRefScreen; + if (screensLeft[ref]) + break; + pScreen = screenInfo.screens[i]; + dixScreenOrigins[i].x = dixScreenOrigins[ref].x - pScreen->width; + dixScreenOrigins[i].y = dixScreenOrigins[ref].y; + ++changed, screensLeft[i] = 0; + break; + case PosBelow: + ref = screen->whereRefScreen; + if (screensLeft[ref]) + break; + pScreen = screenInfo.screens[ref]; + dixScreenOrigins[i].x = dixScreenOrigins[ref].x; + dixScreenOrigins[i].y = dixScreenOrigins[ref].y + pScreen->height; + ++changed, screensLeft[i] = 0; + break; + case PosAbove: + ref = screen->whereRefScreen; + if (screensLeft[ref]) + break; + pScreen = screenInfo.screens[i]; + dixScreenOrigins[i].x = dixScreenOrigins[ref].x; + dixScreenOrigins[i].y = dixScreenOrigins[ref].y - pScreen->height; + ++changed, screensLeft[i] = 0; + break; + case PosNone: + dmxLog(dmxFatal, "No position information for screen %d\n", i); + } + } + return changed; +} + +static void dmxComputeScreenOrigins(void) +{ + int *screensLeft; + int i, ref; + int minX, minY; + + /* Compute origins based on + * configuration information. */ + screensLeft = dmxSLCreate(); + while ((i = dmxSLFindNext(screensLeft)) >= 0) { + while (dmxTryComputeScreenOrigins(screensLeft)); + if ((i = dmxSLFindNext(screensLeft)) >= 0) { + /* All of the remaining screens are referencing each other. + * Assign a value to one of them and go through again. This + * guarantees that we will eventually terminate. + */ + ref = dmxScreens[i].whereRefScreen; + dixScreenOrigins[ref].x = dixScreenOrigins[ref].y = 0; + screensLeft[ref] = 0; + } + } + dmxSLFree(screensLeft); + + + /* Justify the topmost and leftmost to + * (0,0). */ + minX = dixScreenOrigins[0].x; + minY = dixScreenOrigins[0].y; + for (i = 1; i < dmxNumScreens; i++) { /* Compute minX, minY */ + 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 < dmxNumScreens; i++) { + dixScreenOrigins[i].x -= minX; + dixScreenOrigins[i].y -= minY; + } + } +} + +/** Recompute origin information in the #dmxScreens list. This is + * called from #dmxInitOrigins. */ +void dmxReInitOrigins(void) +{ + int i; + + if (dmxNumScreens > MAXSCREENS) + dmxLog(dmxFatal, "dmxNumScreens = %d > MAXSCREENS = %d\n", + dmxNumScreens, MAXSCREENS); + + for (i = 0; i < dmxNumScreens; i++) { + DMXScreenInfo *dmxScreen = &dmxScreens[i]; + dmxLogOutput(dmxScreen, + "s=%dx%d%+d%+d r=%dx%d%+d%+d @%d,%d" + " (be=%dx%d depth=%d bpp=%d)\n", + dmxScreen->scrnWidth, dmxScreen->scrnHeight, + dmxScreen->scrnX, dmxScreen->scrnY, + + dmxScreen->rootWidth, dmxScreen->rootHeight, + dmxScreen->rootX, dmxScreen->rootY, + + dmxScreen->rootXOrigin, dmxScreen->rootYOrigin, + dmxScreen->beWidth, dmxScreen->beHeight, + dmxScreen->beDepth, dmxScreen->beBPP); + } +} + +/** Initialize screen origins (and relative position). This is called + * for each server generation. For dynamic reconfiguration, use + * #dmxReInitOrigins() instead. */ +void dmxInitOrigins(void) +{ + int i; + + if (dmxNumScreens > MAXSCREENS) + dmxLog(dmxFatal, "dmxNumScreens = %d > MAXSCREENS = %d\n", + dmxNumScreens, MAXSCREENS); + + for (i = 0; i < dmxNumScreens; i++) { + DMXScreenInfo *dmxScreen = &dmxScreens[i]; + dmxLogOutput(dmxScreen, + "(request) s=%dx%d%+d%+d r=%dx%d%+d%+d @%d,%d (%d)" + " (be=%dx%d depth=%d bpp=%d)\n", + dmxScreen->scrnWidth, dmxScreen->scrnHeight, + dmxScreen->scrnX, dmxScreen->scrnY, + + dmxScreen->rootWidth, dmxScreen->rootHeight, + dmxScreen->rootX, dmxScreen->rootY, + + dmxScreen->whereX, dmxScreen->whereY, + dmxScreen->where, + + dmxScreen->beWidth, dmxScreen->beHeight, + dmxScreen->beDepth, dmxScreen->beBPP); + } + + dmxComputeScreenOrigins(); + + for (i = 0; i < dmxNumScreens; i++) { + DMXScreenInfo *dmxScreen = &dmxScreens[i]; + dmxScreen->rootXOrigin = dixScreenOrigins[i].x; + dmxScreen->rootYOrigin = dixScreenOrigins[i].y; + } + + dmxReInitOrigins(); +} + +/** Returns non-zero if the global \a x, \a y coordinate is on the + * screen window of the \a dmxScreen. */ +int dmxOnScreen(int x, int y, DMXScreenInfo *dmxScreen) +{ +#if DMX_CURSOR_DEBUG > 1 + dmxLog(dmxDebug, + "dmxOnScreen %d %d,%d (r=%dx%d%+d%+d@%d,%d s=%dx%d%+d%+d)\n", + dmxScreen->index, x, y, + dmxScreen->rootWidth, dmxScreen->rootHeight, + dmxScreen->rootX, dmxScreen->rootY, + dmxScreen->rootXOrigin, dmxScreen->rootYOrigin, + dmxScreen->scrnWidth, dmxScreen->scrnHeight, + dmxScreen->scrnX, dmxScreen->scrnY); +#endif + if (x >= dmxScreen->rootXOrigin + && x < dmxScreen->rootXOrigin + dmxScreen->rootWidth + && y >= dmxScreen->rootYOrigin + && y < dmxScreen->rootYOrigin + dmxScreen->rootHeight) return 1; + return 0; +} + +/** Returns non-zero if \a a overlaps \a b. */ +static int dmxDoesOverlap(DMXScreenInfo *a, DMXScreenInfo *b) +{ + if (dmxOnScreen(a->rootXOrigin, + a->rootYOrigin, b)) + return 1; + + if (dmxOnScreen(a->rootXOrigin, + a->rootYOrigin + a->scrnWidth, b)) + return 1; + + if (dmxOnScreen(a->rootXOrigin + a->scrnHeight, + a->rootYOrigin, b)) + return 1; + + if (dmxOnScreen(a->rootXOrigin + a->scrnHeight, + a->rootYOrigin + a->scrnWidth, b)) + return 1; + + if (dmxOnScreen(b->rootXOrigin, + b->rootYOrigin, a)) + return 1; + + if (dmxOnScreen(b->rootXOrigin, + b->rootYOrigin + b->scrnWidth, a)) + return 1; + + if (dmxOnScreen(b->rootXOrigin + b->scrnHeight, + b->rootYOrigin, a)) + return 1; + + if (dmxOnScreen(b->rootXOrigin + b->scrnHeight, + b->rootYOrigin + b->scrnWidth, a)) + return 1; + + return 0; +} + +/** Used with \a dmxInterateOverlap to print out a list of screens which + * overlap each other. */ +static void *dmxPrintOverlap(DMXScreenInfo *dmxScreen, void *closure) +{ + DMXScreenInfo *a = closure; + if (dmxScreen != a) { + if (dmxScreen->cursorNotShared) + dmxLogOutputCont(a, " [%d/%s]", dmxScreen->index, dmxScreen->name); + else + dmxLogOutputCont(a, " %d/%s", dmxScreen->index, dmxScreen->name); + } + return NULL; +} + +/** Iterate over the screens which overlap with the \a start screen, + * calling \a f with the \a closure for each argument. Often used with + * #dmxPrintOverlap. */ +static void *dmxIterateOverlap(DMXScreenInfo *start, + void *(*f)(DMXScreenInfo *dmxScreen, void *), + void *closure) +{ + DMXScreenInfo *pt; + + if (!start->over) return f(start, closure); + + for (pt = start->over; /* condition at end of loop */; pt = pt->over) { + void *retval; + if ((retval = f(pt, closure))) return retval; + if (pt == start) break; + } + return NULL; +} + +/** Used with #dmxPropertyIterate to determine if screen \a a is the + * same as the screen \a closure. */ +static void *dmxTestSameDisplay(DMXScreenInfo *a, void *closure) +{ + DMXScreenInfo *b = closure; + + if (a == b) + return a; + return NULL; +} + +/** Detects overlapping dmxScreens and creates circular lists. This + * uses an O(dmxNumScreens^2) algorithm, but dmxNumScreens is < 100 and + * the computation only needs to be performed for every server + * generation or dynamic reconfiguration . */ +void dmxInitOverlap(void) +{ + int i, j; + DMXScreenInfo *a, *b, *pt; + + for (i = 0; i < dmxNumScreens; i++) + dmxScreens[i].over = NULL; + + for (i = 0; i < dmxNumScreens; i++) { + a = &dmxScreens[i]; + + for (j = i+1; j < dmxNumScreens; j++) { + b = &dmxScreens[j]; + if (b->over) + continue; + + if (dmxDoesOverlap(a, b)) { + DMXDBG6("%d overlaps %d: a=%p %p b=%p %p\n", + a->index, b->index, a, a->over, b, b->over); + b->over = (a->over ? a->over : a); + a->over = b; + } + } + } + + for (i = 0; i < dmxNumScreens; i++) { + a = &dmxScreens[i]; + + if (!a->over) + continue; + + /* Flag all pairs that are on same display */ + for (pt = a->over; pt != a; pt = pt->over) { + if (dmxPropertyIterate(a, dmxTestSameDisplay, pt)) { + /* The ->over sets contain the transitive set of screens + * that overlap. For screens that are on the same + * backend display, we only want to exclude pairs of + * screens that mutually overlap on the backend display, + * so we call dmxDoesOverlap, which is stricter than the + * ->over set. */ + if (!dmxDoesOverlap(a, pt)) + continue; + a->cursorNotShared = 1; + pt->cursorNotShared = 1; + dmxLog(dmxInfo, + "Screen %d and %d overlap on %s\n", + a->index, pt->index, a->name); + } + } + } + + for (i = 0; i < dmxNumScreens; i++) { + a = &dmxScreens[i]; + + if (a->over) { + dmxLogOutput(a, "Overlaps"); + dmxIterateOverlap(a, dmxPrintOverlap, a); + dmxLogOutputCont(a, "\n"); + } + } +} + +/** Create \a pCursor on the back-end associated with \a pScreen. */ +void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen); + CursorBitsPtr pBits = pCursor->bits; + Pixmap src, msk; + XColor fg, bg; + XImage *img; + XlibGC gc = NULL; + XGCValues v; + unsigned long m; + int i; + + if (!pCursorPriv) + return; + + m = GCFunction | GCPlaneMask | GCForeground | GCBackground | GCClipMask; + v.function = GXcopy; + v.plane_mask = AllPlanes; + v.foreground = 1L; + v.background = 0L; + v.clip_mask = None; + + for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { + if (dmxScreen->bePixmapFormats[i].depth == 1) { + /* Create GC in the back-end servers */ + gc = XCreateGC(dmxScreen->beDisplay, dmxScreen->scrnDefDrawables[i], + m, &v); + break; + } + } + if (!gc) + dmxLog(dmxFatal, "dmxRealizeCursor: gc not initialized\n"); + + src = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin, + pBits->width, pBits->height, 1); + msk = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin, + pBits->width, pBits->height, 1); + + img = XCreateImage(dmxScreen->beDisplay, + dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, + 1, XYBitmap, 0, (char *)pBits->source, + pBits->width, pBits->height, + BitmapPad(dmxScreen->beDisplay), 0); + + XPutImage(dmxScreen->beDisplay, src, gc, img, 0, 0, 0, 0, + pBits->width, pBits->height); + + XFree(img); + + img = XCreateImage(dmxScreen->beDisplay, + dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, + 1, XYBitmap, 0, (char *)pBits->mask, + pBits->width, pBits->height, + BitmapPad(dmxScreen->beDisplay), 0); + + XPutImage(dmxScreen->beDisplay, msk, gc, img, 0, 0, 0, 0, + pBits->width, pBits->height); + + XFree(img); + + fg.red = pCursor->foreRed; + fg.green = pCursor->foreGreen; + fg.blue = pCursor->foreBlue; + + bg.red = pCursor->backRed; + bg.green = pCursor->backGreen; + bg.blue = pCursor->backBlue; + + pCursorPriv->cursor = XCreatePixmapCursor(dmxScreen->beDisplay, + src, msk, + &fg, &bg, + pBits->xhot, pBits->yhot); + + XFreePixmap(dmxScreen->beDisplay, src); + XFreePixmap(dmxScreen->beDisplay, msk); + XFreeGC(dmxScreen->beDisplay, gc); + + dmxSync(dmxScreen, FALSE); +} + +static Bool _dmxRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxCursorPrivPtr pCursorPriv; + + DMXDBG2("_dmxRealizeCursor(%d,%p)\n", pScreen->myNum, pCursor); + + DMX_SET_CURSOR_PRIV(pCursor, pScreen, malloc(sizeof(*pCursorPriv))); + if (!DMX_GET_CURSOR_PRIV(pCursor, pScreen)) + return FALSE; + + pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen); + pCursorPriv->cursor = (Cursor)0; + + if (!dmxScreen->beDisplay) + return TRUE; + + dmxBECreateCursor(pScreen, pCursor); + return TRUE; +} + +/** Free \a pCursor on the back-end associated with \a pScreen. */ +Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen); + + if (pCursorPriv) { + XFreeCursor(dmxScreen->beDisplay, pCursorPriv->cursor); + pCursorPriv->cursor = (Cursor)0; + return TRUE; + } + + return FALSE; +} + +static Bool _dmxUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + + DMXDBG2("_dmxUnrealizeCursor(%d,%p)\n", + pScreen->myNum, pCursor); + + if (dmxScreen->beDisplay) { + if (dmxBEFreeCursor(pScreen, pCursor)) + free(DMX_GET_CURSOR_PRIV(pCursor, pScreen)); + } + DMX_SET_CURSOR_PRIV(pCursor, pScreen, NULL); + + return TRUE; +} + +static void _dmxMoveCursor(ScreenPtr pScreen, int x, int y) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + int newX = x + dmxScreen->rootX; + int newY = y + dmxScreen->rootY; + + if (newX < 0) newX = 0; + if (newY < 0) newY = 0; + + DMXDBG5("_dmxMoveCursor(%d,%d,%d) -> %d,%d\n", + pScreen->myNum, x, y, newX, newY); + if (dmxScreen->beDisplay) { + XWarpPointer(dmxScreen->beDisplay, None, dmxScreen->scrnWin, + 0, 0, 0, 0, newX, newY); + dmxSync(dmxScreen, TRUE); + } +} + +static void _dmxSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + + DMXDBG4("_dmxSetCursor(%d,%p,%d,%d)\n", pScreen->myNum, pCursor, x, y); + + if (pCursor) { + dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen); + if (pCursorPriv && dmxScreen->curCursor != pCursorPriv->cursor) { + if (dmxScreen->beDisplay) + XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin, + pCursorPriv->cursor); + dmxScreen->cursor = pCursor; + dmxScreen->curCursor = pCursorPriv->cursor; + dmxScreen->cursorVisible = 1; + } + _dmxMoveCursor(pScreen, x, y); + } else { + if (dmxScreen->beDisplay) + XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin, + dmxScreen->noCursor); + dmxScreen->cursor = NULL; + dmxScreen->curCursor = (Cursor)0; + dmxScreen->cursorVisible = 0; + } + if (dmxScreen->beDisplay) dmxSync(dmxScreen, TRUE); +} + +static Bool dmxRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + DMXScreenInfo *start = &dmxScreens[pScreen->myNum]; + DMXScreenInfo *pt; + + if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) + return _dmxRealizeCursor(pScreen, pCursor); + + for (pt = start->over; /* condition at end of loop */; pt = pt->over) { + if (pt->cursorNotShared) + continue; + _dmxRealizeCursor(screenInfo.screens[pt->index], pCursor); + if (pt == start) + break; + } + return TRUE; +} + +static Bool dmxUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + DMXScreenInfo *start = &dmxScreens[pScreen->myNum]; + DMXScreenInfo *pt; + + if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) + return _dmxUnrealizeCursor(pScreen, pCursor); + + for (pt = start->over; /* condition at end of loop */; pt = pt->over) { + if (pt->cursorNotShared) + continue; + _dmxUnrealizeCursor(screenInfo.screens[pt->index], pCursor); + if (pt == start) + break; + } + return TRUE; +} + +static CursorPtr dmxFindCursor(DMXScreenInfo *start) +{ + DMXScreenInfo *pt; + + if (!start || !start->over) + return GetSpriteCursor(inputInfo.pointer); + for (pt = start->over; /* condition at end of loop */; pt = pt->over) { + if (pt->cursor) + return pt->cursor; + if (pt == start) + break; + } + return GetSpriteCursor(inputInfo.pointer); +} + +/** Move the cursor to coordinates (\a x, \a y)on \a pScreen. This + * function is usually called via #dmxPointerSpriteFuncs, except during + * reconfiguration when the cursor is repositioned to force an update on + * newley overlapping screens and on screens that no longer overlap. + * + * The coords (x,y) are in global coord space. We'll loop over the + * back-end screens and see if they contain the global coord. If so, call + * _dmxMoveCursor() (XWarpPointer) to position the pointer on that screen. + */ +void dmxMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + DMXScreenInfo *start = &dmxScreens[pScreen->myNum]; + DMXScreenInfo *pt; + + DMXDBG3("dmxMoveCursor(%d,%d,%d)\n", pScreen->myNum, x, y); + + if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) { + _dmxMoveCursor(pScreen, x, y); + return; + } + + for (pt = start->over; /* condition at end of loop */; pt = pt->over) { + if (pt->cursorNotShared) + continue; + if (dmxOnScreen(x + start->rootXOrigin, y + start->rootYOrigin, pt)) { + if (/* pt != start && */ !pt->cursorVisible) { + if (!pt->cursor) { + /* This only happens during + * reconfiguration when a new overlap + * occurs. */ + CursorPtr pCursor; + + if ((pCursor = dmxFindCursor(start))) + _dmxRealizeCursor(screenInfo.screens[pt->index], + pt->cursor = pCursor); + + } + _dmxSetCursor(screenInfo.screens[pt->index], + pt->cursor, + x + start->rootXOrigin - pt->rootXOrigin, + y + start->rootYOrigin - pt->rootYOrigin); + } + _dmxMoveCursor(screenInfo.screens[pt->index], + x + start->rootXOrigin - pt->rootXOrigin, + y + start->rootYOrigin - pt->rootYOrigin); + } else if (/* pt != start && */ pt->cursorVisible) { + _dmxSetCursor(screenInfo.screens[pt->index], + NULL, + x + start->rootXOrigin - pt->rootXOrigin, + y + start->rootYOrigin - pt->rootYOrigin); + } + if (pt == start) + break; + } +} + +static void dmxSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + DMXScreenInfo *start = &dmxScreens[pScreen->myNum]; + DMXScreenInfo *pt; + int GX, GY, gx, gy; + + DMXDBG5("dmxSetCursor(%d %p, %p,%d,%d)\n", + pScreen->myNum, start, pCursor, x, y); + + /* We do this check here because of two cases: + * + * 1) if a client calls XWarpPointer() + * and Xinerama is not running, we can + * have mi's notion of the pointer + * position out of phase with DMX's + * notion. + * + * 2) if a down button is held while the + * cursor moves outside the root window, + * mi's notion of the pointer position + * is out of phase with DMX's notion and + * the cursor can remain visible when it + * shouldn't be. */ + + dmxGetGlobalPosition(&GX, &GY); + gx = start->rootXOrigin + x; + gy = start->rootYOrigin + y; + if (x && y && (GX != gx || GY != gy)) + dmxCoreMotion(NULL, gx, gy, 0, DMX_NO_BLOCK); + + if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) { + _dmxSetCursor(pScreen, pCursor, x, y); + return; + } + + for (pt = start->over; /* condition at end of loop */; pt = pt->over) { + if (pt->cursorNotShared) + continue; + if (dmxOnScreen(x + start->rootXOrigin, y + start->rootYOrigin, pt)) { + _dmxSetCursor(screenInfo.screens[pt->index], pCursor, + x + start->rootXOrigin - pt->rootXOrigin, + y + start->rootYOrigin - pt->rootYOrigin); + } else { + _dmxSetCursor(screenInfo.screens[pt->index], NULL, + x + start->rootXOrigin - pt->rootXOrigin, + y + start->rootYOrigin - pt->rootYOrigin); + } + if (pt == start) + break; + } +} + + +/** This routine is used by the backend input routines to hide the + * cursor on a screen that is being used for relative input. \see + * dmxbackend.c */ +void dmxHideCursor(DMXScreenInfo *dmxScreen) +{ + int x, y; + ScreenPtr pScreen = screenInfo.screens[dmxScreen->index]; + + dmxGetGlobalPosition(&x, &y); + _dmxSetCursor(pScreen, NULL, x, y); +} + +/** This routine is called during reconfiguration to make sure the + * cursor is visible. */ +void dmxCheckCursor(void) +{ + int i; + int x, y; + ScreenPtr pScreen; + DMXScreenInfo *firstScreen; + + dmxGetGlobalPosition(&x, &y); + firstScreen = dmxFindFirstScreen(x, y); + + DMXDBG2("dmxCheckCursor %d %d\n", x, y); + for (i = 0; i < dmxNumScreens; i++) { + DMXScreenInfo *dmxScreen = &dmxScreens[i]; + pScreen = screenInfo.screens[dmxScreen->index]; + + if (!dmxOnScreen(x, y, dmxScreen)) { + if (firstScreen && i == miPointerGetScreen(inputInfo.pointer)->myNum) + miPointerSetScreen(inputInfo.pointer, firstScreen->index, x, y); + _dmxSetCursor(pScreen, NULL, + x - dmxScreen->rootXOrigin, + y - dmxScreen->rootYOrigin); + } else { + if (!dmxScreen->cursor) { + CursorPtr pCursor; + + if ((pCursor = dmxFindCursor(dmxScreen))) { + _dmxRealizeCursor(pScreen, dmxScreen->cursor = pCursor); + } + } + _dmxSetCursor(pScreen, dmxScreen->cursor, + x - dmxScreen->rootXOrigin, + y - dmxScreen->rootYOrigin); + } + } + DMXDBG2(" leave dmxCheckCursor %d %d\n", x, y); +} + +static Bool dmxDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) +{ + return TRUE; +} + +static void dmxDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) +{ +} + +miPointerSpriteFuncRec dmxPointerSpriteFuncs = +{ + dmxRealizeCursor, + dmxUnrealizeCursor, + dmxSetCursor, + dmxMoveCursor, + dmxDeviceCursorInitialize, + dmxDeviceCursorCleanup +}; diff --git a/xorg-server/hw/dmx/dmxfont.c b/xorg-server/hw/dmx/dmxfont.c index c33aee79a..3f0264edb 100644 --- a/xorg-server/hw/dmx/dmxfont.c +++ b/xorg-server/hw/dmx/dmxfont.c @@ -1,559 +1,551 @@ -/* - * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 - * - */ - -/** \file - * This file provides support for fonts. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#define DMX_FONTPATH_DEBUG 0 - -#include "dmx.h" -#include "dmxsync.h" -#include "dmxfont.h" -#include "dmxlog.h" - -#include -#include "dixfont.h" -#include "dixstruct.h" - -static int (*dmxSaveProcVector[256])(ClientPtr); -static int dmxFontLastError; - -static int dmxFontErrorHandler(Display *dpy, XErrorEvent *ev) -{ - dmxFontLastError = ev->error_code; - - return 0; -} - -static char **dmxGetFontPath(int *npaths) -{ - char **fp; - unsigned char *c, *paths; - char *newfp; - int len, l, i; - - GetFontPath(serverClient, npaths, &len, &paths); - - newfp = xalloc(*npaths + len); - c = (unsigned char *)newfp; - fp = xalloc(*npaths * sizeof(*fp)); - - memmove(newfp, paths+1, *npaths + len - 1); - l = *paths; - for (i = 0; i < *npaths; i++) { - fp[i] = (char *)c; - c += l; - l = *c; - *c++ = '\0'; - } - -#if DMX_FONTPATH_DEBUG - for (i = 0; i < *npaths; i++) - dmxLog(dmxDebug, "FontPath[%d] = %s\n", i, fp[i]); -#endif - - return fp; -} - -static void dmxFreeFontPath(char **fp) -{ - xfree(fp[0]); - xfree(fp); -} - -static Bool dmxCheckFontPathElement(DMXScreenInfo *dmxScreen, char *fp) -{ - int (*oldErrorHandler)(Display *, XErrorEvent *); - - if (!dmxScreen->beDisplay) - return TRUE; - - dmxFontLastError = 0; - oldErrorHandler = XSetErrorHandler(dmxFontErrorHandler); - XSetFontPath(dmxScreen->beDisplay, &fp, 1); - dmxSync(dmxScreen, TRUE); /* Must complete before removing handler */ - XSetErrorHandler(oldErrorHandler); - - return (dmxFontLastError == 0); -} - -static int dmxSetFontPath(DMXScreenInfo *dmxScreen) -{ - int (*oldErrorHandler)(Display *, XErrorEvent *); - char **fp; - int result = Success; - int npaths; - - if (!dmxScreen->beDisplay) - return result; - - fp = dmxGetFontPath(&npaths); - if (!fp) return BadAlloc; - - dmxFontLastError = 0; - oldErrorHandler = XSetErrorHandler(dmxFontErrorHandler); - XSetFontPath(dmxScreen->beDisplay, fp, npaths); - dmxSync(dmxScreen, TRUE); /* Must complete before removing handler */ - XSetErrorHandler(oldErrorHandler); - - if (dmxFontLastError) { - result = dmxFontLastError; - /* We could set *error here to the offending path, but it is - * ignored, so we don't bother figuring out which path is bad. - * If we do add this support in the future, we'll need to add - * error to the function's argument list. - */ - } - - dmxFreeFontPath(fp); - - return result; -} - -static int dmxCheckFontPath(DMXScreenInfo *dmxScreen, int *error) -{ - char **oldFontPath; - int nOldPaths; - int result = Success; - - if (!dmxScreen->beDisplay) - return result; - - /* Save old font path */ - oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths); - - result = dmxSetFontPath(dmxScreen); - - /* Restore old font path */ - XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths); - XFreeFontPath(oldFontPath); - dmxSync(dmxScreen, FALSE); - - return result; -} - -static int dmxProcSetFontPath(ClientPtr client) -{ - unsigned char *ptr; - unsigned long nbytes, total, n; - long nfonts; - int i, result; - int error; - unsigned char *oldFontPath, *tmpFontPath; - int nOldPaths; - int lenOldPaths; - REQUEST(xSetFontPathReq); - - REQUEST_AT_LEAST_SIZE(xSetFontPathReq); - - nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); - total = nbytes; - ptr = (unsigned char *)&stuff[1]; - nfonts = stuff->nFonts; - - while (--nfonts >= 0) { - if ((total == 0) || (total < (n = (*ptr + 1)))) - return BadLength; - total -= n; - ptr += n; - } - if (total >= 4) - return BadLength; - - GetFontPath(serverClient, &nOldPaths, &lenOldPaths, &tmpFontPath); - oldFontPath = xalloc(nOldPaths + lenOldPaths); - memmove(oldFontPath, tmpFontPath, nOldPaths + lenOldPaths); - - result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1], - &error); - if (!result) { - for (i = 0; i < dmxNumScreens; i++) - if ((result = dmxCheckFontPath(&dmxScreens[i], &error))) - break; - - if (result) { - int ignoreresult, ignoreerror; - - /* Restore old fontpath in the DMX server */ - ignoreresult = SetFontPath(client, nOldPaths, oldFontPath, - &ignoreerror); - } else { - result = client->noClientException; - client->errorValue = error; - } - } - - xfree(oldFontPath); - return result; -} - -/** Initialize font support. In addition to the screen function call - * pointers, DMX also hooks in at the ProcVector[] level. Here the old - * ProcVector function pointers are saved and the new ProcVector - * function pointers are initialized. */ -void dmxInitFonts(void) -{ - int i; - - for (i = 0; i < 256; i++) - dmxSaveProcVector[i] = ProcVector[i]; - - ProcVector[X_SetFontPath] = dmxProcSetFontPath; -} - -/** Reset font support by restoring the original ProcVector function - * pointers. */ -void dmxResetFonts(void) -{ - int i; - - for (i = 0; i < 256; i++) - ProcVector[i] = dmxSaveProcVector[i]; -} - -/** Load the font, \a pFont, on the back-end server associated with \a - * pScreen. When a font is loaded, the font path on back-end server is - * first initialized to that specified on the command line with the - * -fontpath options, and then the font is loaded. */ -Bool dmxBELoadFont(ScreenPtr pScreen, FontPtr pFont) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxFontPrivPtr pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex); - const char *name; - char **oldFontPath = NULL; - int nOldPaths; - Atom name_atom, value_atom; - int i; - - /* Make sure we have a font private struct to work with */ - if (!pFontPriv) - return FALSE; - - /* Don't load a font over top of itself */ - if (pFontPriv->font[pScreen->myNum]) { - return TRUE; /* Already loaded font */ - } - - /* Save old font path */ - oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths); - - /* Set the font path for the font about to be loaded on the back-end */ - if (dmxSetFontPath(dmxScreen)) { - char **fp; - int npaths; - Bool *goodfps; - - /* This could fail only when first starting the X server and - * loading the default font. If it fails here, then the default - * font path is invalid, no default font path will be set, the - * DMX server will fail to load the default font, and it will - * exit with an error unless we remove the offending font paths - * with the -ignorebadfontpaths command line option. - */ - - fp = dmxGetFontPath(&npaths); - if (!fp) { - dmxLog(dmxError, - "No default font path set.\n"); - dmxLog(dmxError, - "Please see the Xdmx man page for information on how to\n"); - dmxLog(dmxError, - "initialize the DMX server's default font path.\n"); - XFreeFontPath(oldFontPath); - return FALSE; - } - - if (!dmxFontPath) - dmxLog(dmxWarning, "No default font path is set.\n"); - - goodfps = xalloc(npaths * sizeof(*goodfps)); - - dmxLog(dmxError, - "The DMX server failed to set the following font paths on " - "screen #%d:\n", pScreen->myNum); - - for (i = 0; i < npaths; i++) - if (!(goodfps[i] = dmxCheckFontPathElement(dmxScreen, fp[i]))) - dmxLog(dmxError, " %s\n", fp[i]); - - if (dmxIgnoreBadFontPaths) { - char *newfp; - int newnpaths = 0; - int len = 0; - int j = 0; - int error; - - dmxLog(dmxError, - "These font paths will not be used because the " - "\"-ignorebadfontpaths\"\n"); - dmxLog(dmxError, - "option is set.\n"); - - for (i = 0; i < npaths; i++) - if (goodfps[i]) { - len += strlen(fp[i]) + 1; - newnpaths++; - } - - if (!newnpaths) { - /* No valid font paths were found */ - dmxLog(dmxError, - "After removing the font paths above, no valid font " - "paths were\n"); - dmxLog(dmxError, - "available. Please check that the font paths set on " - "the command\n"); - dmxLog(dmxError, - "line or in the configuration file via the " - "\"-fontpath\" option\n"); - dmxLog(dmxError, - "are valid on all back-end servers. See the Xdmx man " - "page for\n"); - dmxLog(dmxError, - "more information on font paths.\n"); - dmxFreeFontPath(fp); - XFreeFontPath(oldFontPath); - xfree(goodfps); - return FALSE; - } - - newfp = xalloc(len * sizeof(*newfp)); - for (i = 0; i < npaths; i++) { - if (goodfps[i]) { - int n = strlen(fp[i]); - newfp[j++] = n; - strncpy(&newfp[j], fp[i], n); - j += n; - } - } - - if (SetFontPath(serverClient, newnpaths, (unsigned char *)newfp, - &error)) { - /* Note that this should never happen since all of the - * FPEs were previously valid. */ - dmxLog(dmxError, "Cannot reset the default font path.\n"); - } - } else if (dmxFontPath) { - dmxLog(dmxError, - "Please remove these font paths from the command line " - "or\n"); - dmxLog(dmxError, - "configuration file, or set the \"-ignorebadfontpaths\" " - "option to\n"); - dmxLog(dmxError, - "ignore them. For more information on these options, see " - "the\n"); - dmxLog(dmxError, - "Xdmx man page.\n"); - } else { - dmxLog(dmxError, - "Please specify the font paths that are available on all " - "back-end\n"); - dmxLog(dmxError, - "servers with the \"-fontpath\" option, or use the " - "\"-ignorebadfontpaths\"\n"); - dmxLog(dmxError, - "to ignore bad defaults. For more information on " - "these and other\n"); - dmxLog(dmxError, - "font-path-related options, see the Xdmx man page.\n"); - } - - if (!dmxIgnoreBadFontPaths || - (dmxIgnoreBadFontPaths && dmxSetFontPath(dmxScreen))) { - /* We still have errors so return with error */ - dmxFreeFontPath(fp); - XFreeFontPath(oldFontPath); - xfree(goodfps); - return FALSE; - } - } - - /* Find requested font on back-end server */ - name_atom = MakeAtom("FONT", 4, TRUE); - value_atom = 0L; - - for (i = 0; i < pFont->info.nprops; i++) { - if ((Atom)pFont->info.props[i].name == name_atom) { - value_atom = pFont->info.props[i].value; - break; - } - } - if (!value_atom) return FALSE; - - name = NameForAtom(value_atom); - if (!name) return FALSE; - - pFontPriv->font[pScreen->myNum] = - XLoadQueryFont(dmxScreen->beDisplay, name); - - /* Restore old font path */ - XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths); - XFreeFontPath(oldFontPath); - dmxSync(dmxScreen, FALSE); - - if (!pFontPriv->font[pScreen->myNum]) return FALSE; - - return TRUE; -} - -/** Realize the font, \a pFont, on the back-end server associated with - * \a pScreen. */ -Bool dmxRealizeFont(ScreenPtr pScreen, FontPtr pFont) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxFontPrivPtr pFontPriv; - - if (!(pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) { - FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); - pFontPriv = xalloc(sizeof(dmxFontPrivRec)); - if (!pFontPriv) return FALSE; - pFontPriv->font = NULL; - MAXSCREENSALLOC(pFontPriv->font); - if (!pFontPriv->font) { - xfree(pFontPriv); - return FALSE; - } - pFontPriv->refcnt = 0; - } - - FontSetPrivate(pFont, dmxFontPrivateIndex, (pointer)pFontPriv); - - if (dmxScreen->beDisplay) { - if (!dmxBELoadFont(pScreen, pFont)) - return FALSE; - - pFontPriv->refcnt++; - } else { - pFontPriv->font[pScreen->myNum] = NULL; - } - - return TRUE; -} - -/** Free \a pFont on the back-end associated with \a pScreen. */ -Bool dmxBEFreeFont(ScreenPtr pScreen, FontPtr pFont) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxFontPrivPtr pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex); - - if (pFontPriv && pFontPriv->font[pScreen->myNum]) { - XFreeFont(dmxScreen->beDisplay, pFontPriv->font[pScreen->myNum]); - pFontPriv->font[pScreen->myNum] = NULL; - return TRUE; - } - - return FALSE; -} - -/** Unrealize the font, \a pFont, on the back-end server associated with - * \a pScreen. */ -Bool dmxUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxFontPrivPtr pFontPriv; - - if ((pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) { - /* In case the font failed to load properly */ - if (!pFontPriv->refcnt) { - MAXSCREENSFREE(pFontPriv->font); - xfree(pFontPriv); - FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); - } else if (pFontPriv->font[pScreen->myNum]) { - if (dmxScreen->beDisplay) - dmxBEFreeFont(pScreen, pFont); - - /* The code below is non-obvious, so here's an explanation... - * - * When creating the default GC, the server opens up the - * default font once for each screen, which in turn calls - * the RealizeFont function pointer once for each screen. - * During this process both dix's font refcnt and DMX's font - * refcnt are incremented once for each screen. - * - * Later, when shutting down the X server, dix shuts down - * each screen in reverse order. During this shutdown - * procedure, each screen's default GC is freed and then - * that screen is closed by calling the CloseScreen function - * pointer. screenInfo.numScreens is then decremented after - * closing each screen. This procedure means that the dix's - * font refcnt for the font used by the default GC's is - * decremented once for each screen # greater than 0. - * However, since dix's refcnt for the default font is not - * yet 0 for each screen greater than 0, no call to the - * UnrealizeFont function pointer is made for those screens. - * Then, when screen 0 is being closed, dix's font refcnt - * for the default GC's font is finally 0 and the font is - * unrealized. However, since screenInfo.numScreens has - * been decremented already down to 1, only one call to - * UnrealizeFont is made (for screen 0). Thus, even though - * RealizeFont was called once for each screen, - * UnrealizeFont is only called for screen 0. - * - * This is a bug in dix. - * - * To avoid the memory leak of pFontPriv for each server - * generation, we can also free pFontPriv if the refcnt is - * not yet 0 but the # of screens is 1 -- i.e., the case - * described in the dix bug above. This is only a temporary - * workaround until the bug in dix is solved. - * - * The other problem is that the font structure allocated by - * XLoadQueryFont() above is not freed for screens > 0. - * This problem cannot be worked around here since the back- - * end displays for screens > 0 have already been closed by - * the time this code is called from dix. - * - * When the bug in dix described above is fixed, then we can - * remove the "|| screenInfo.numScreens == 1" code below and - * the memory leaks will be eliminated. - */ - if (--pFontPriv->refcnt == 0 -#if 1 - /* Remove this code when the dix bug is fixed */ - || screenInfo.numScreens == 1 -#endif - ) { - MAXSCREENSFREE(pFontPriv->font); - xfree(pFontPriv); - FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); - } - } - } - - return TRUE; -} +/* + * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 + * + */ + +/** \file + * This file provides support for fonts. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#define DMX_FONTPATH_DEBUG 0 + +#include "dmx.h" +#include "dmxsync.h" +#include "dmxfont.h" +#include "dmxlog.h" + +#include +#include "dixfont.h" +#include "dixstruct.h" + +static int (*dmxSaveProcVector[256])(ClientPtr); +static int dmxFontLastError; + +static int dmxFontErrorHandler(Display *dpy, XErrorEvent *ev) +{ + dmxFontLastError = ev->error_code; + + return 0; +} + +static char **dmxGetFontPath(int *npaths) +{ + char **fp; + unsigned char *c, *paths; + char *newfp; + int len, l, i; + + GetFontPath(serverClient, npaths, &len, &paths); + + newfp = malloc(*npaths + len); + c = (unsigned char *)newfp; + fp = malloc(*npaths * sizeof(*fp)); + + memmove(newfp, paths+1, *npaths + len - 1); + l = *paths; + for (i = 0; i < *npaths; i++) { + fp[i] = (char *)c; + c += l; + l = *c; + *c++ = '\0'; + } + +#if DMX_FONTPATH_DEBUG + for (i = 0; i < *npaths; i++) + dmxLog(dmxDebug, "FontPath[%d] = %s\n", i, fp[i]); +#endif + + return fp; +} + +static void dmxFreeFontPath(char **fp) +{ + free(fp[0]); + free(fp); +} + +static Bool dmxCheckFontPathElement(DMXScreenInfo *dmxScreen, char *fp) +{ + int (*oldErrorHandler)(Display *, XErrorEvent *); + + if (!dmxScreen->beDisplay) + return TRUE; + + dmxFontLastError = 0; + oldErrorHandler = XSetErrorHandler(dmxFontErrorHandler); + XSetFontPath(dmxScreen->beDisplay, &fp, 1); + dmxSync(dmxScreen, TRUE); /* Must complete before removing handler */ + XSetErrorHandler(oldErrorHandler); + + return (dmxFontLastError == 0); +} + +static int dmxSetFontPath(DMXScreenInfo *dmxScreen) +{ + int (*oldErrorHandler)(Display *, XErrorEvent *); + char **fp; + int result = Success; + int npaths; + + if (!dmxScreen->beDisplay) + return result; + + fp = dmxGetFontPath(&npaths); + if (!fp) return BadAlloc; + + dmxFontLastError = 0; + oldErrorHandler = XSetErrorHandler(dmxFontErrorHandler); + XSetFontPath(dmxScreen->beDisplay, fp, npaths); + dmxSync(dmxScreen, TRUE); /* Must complete before removing handler */ + XSetErrorHandler(oldErrorHandler); + + if (dmxFontLastError) { + result = dmxFontLastError; + /* We could set *error here to the offending path, but it is + * ignored, so we don't bother figuring out which path is bad. + * If we do add this support in the future, we'll need to add + * error to the function's argument list. + */ + } + + dmxFreeFontPath(fp); + + return result; +} + +static int dmxCheckFontPath(DMXScreenInfo *dmxScreen, int *error) +{ + char **oldFontPath; + int nOldPaths; + int result = Success; + + if (!dmxScreen->beDisplay) + return result; + + /* Save old font path */ + oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths); + + result = dmxSetFontPath(dmxScreen); + + /* Restore old font path */ + XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths); + XFreeFontPath(oldFontPath); + dmxSync(dmxScreen, FALSE); + + return result; +} + +static int dmxProcSetFontPath(ClientPtr client) +{ + unsigned char *ptr; + unsigned long nbytes, total, n; + long nfonts; + int i, result; + unsigned char *oldFontPath, *tmpFontPath; + int nOldPaths; + int lenOldPaths; + REQUEST(xSetFontPathReq); + + REQUEST_AT_LEAST_SIZE(xSetFontPathReq); + + nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); + total = nbytes; + ptr = (unsigned char *)&stuff[1]; + nfonts = stuff->nFonts; + + while (--nfonts >= 0) { + if ((total == 0) || (total < (n = (*ptr + 1)))) + return BadLength; + total -= n; + ptr += n; + } + if (total >= 4) + return BadLength; + + GetFontPath(serverClient, &nOldPaths, &lenOldPaths, &tmpFontPath); + oldFontPath = malloc(nOldPaths + lenOldPaths); + memmove(oldFontPath, tmpFontPath, nOldPaths + lenOldPaths); + + result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1]); + if (!result) { + int error = 0; + for (i = 0; i < dmxNumScreens; i++) + if ((result = dmxCheckFontPath(&dmxScreens[i], &error))) + break; + + if (result) { + /* Restore old fontpath in the DMX server */ + SetFontPath(client, nOldPaths, oldFontPath); + client->errorValue = error; + } + } + + free(oldFontPath); + return result; +} + +/** Initialize font support. In addition to the screen function call + * pointers, DMX also hooks in at the ProcVector[] level. Here the old + * ProcVector function pointers are saved and the new ProcVector + * function pointers are initialized. */ +void dmxInitFonts(void) +{ + int i; + + for (i = 0; i < 256; i++) + dmxSaveProcVector[i] = ProcVector[i]; + + ProcVector[X_SetFontPath] = dmxProcSetFontPath; +} + +/** Reset font support by restoring the original ProcVector function + * pointers. */ +void dmxResetFonts(void) +{ + int i; + + for (i = 0; i < 256; i++) + ProcVector[i] = dmxSaveProcVector[i]; +} + +/** Load the font, \a pFont, on the back-end server associated with \a + * pScreen. When a font is loaded, the font path on back-end server is + * first initialized to that specified on the command line with the + * -fontpath options, and then the font is loaded. */ +Bool dmxBELoadFont(ScreenPtr pScreen, FontPtr pFont) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxFontPrivPtr pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex); + const char *name; + char **oldFontPath = NULL; + int nOldPaths; + Atom name_atom, value_atom; + int i; + + /* Make sure we have a font private struct to work with */ + if (!pFontPriv) + return FALSE; + + /* Don't load a font over top of itself */ + if (pFontPriv->font[pScreen->myNum]) { + return TRUE; /* Already loaded font */ + } + + /* Save old font path */ + oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths); + + /* Set the font path for the font about to be loaded on the back-end */ + if (dmxSetFontPath(dmxScreen)) { + char **fp; + int npaths; + Bool *goodfps; + + /* This could fail only when first starting the X server and + * loading the default font. If it fails here, then the default + * font path is invalid, no default font path will be set, the + * DMX server will fail to load the default font, and it will + * exit with an error unless we remove the offending font paths + * with the -ignorebadfontpaths command line option. + */ + + fp = dmxGetFontPath(&npaths); + if (!fp) { + dmxLog(dmxError, + "No default font path set.\n"); + dmxLog(dmxError, + "Please see the Xdmx man page for information on how to\n"); + dmxLog(dmxError, + "initialize the DMX server's default font path.\n"); + XFreeFontPath(oldFontPath); + return FALSE; + } + + if (!dmxFontPath) + dmxLog(dmxWarning, "No default font path is set.\n"); + + goodfps = malloc(npaths * sizeof(*goodfps)); + + dmxLog(dmxError, + "The DMX server failed to set the following font paths on " + "screen #%d:\n", pScreen->myNum); + + for (i = 0; i < npaths; i++) + if (!(goodfps[i] = dmxCheckFontPathElement(dmxScreen, fp[i]))) + dmxLog(dmxError, " %s\n", fp[i]); + + if (dmxIgnoreBadFontPaths) { + char *newfp; + int newnpaths = 0; + int len = 0; + int j = 0; + + dmxLog(dmxError, + "These font paths will not be used because the " + "\"-ignorebadfontpaths\"\n"); + dmxLog(dmxError, + "option is set.\n"); + + for (i = 0; i < npaths; i++) + if (goodfps[i]) { + len += strlen(fp[i]) + 1; + newnpaths++; + } + + if (!newnpaths) { + /* No valid font paths were found */ + dmxLog(dmxError, + "After removing the font paths above, no valid font " + "paths were\n"); + dmxLog(dmxError, + "available. Please check that the font paths set on " + "the command\n"); + dmxLog(dmxError, + "line or in the configuration file via the " + "\"-fontpath\" option\n"); + dmxLog(dmxError, + "are valid on all back-end servers. See the Xdmx man " + "page for\n"); + dmxLog(dmxError, + "more information on font paths.\n"); + dmxFreeFontPath(fp); + XFreeFontPath(oldFontPath); + free(goodfps); + return FALSE; + } + + newfp = malloc(len * sizeof(*newfp)); + for (i = 0; i < npaths; i++) { + if (goodfps[i]) { + int n = strlen(fp[i]); + newfp[j++] = n; + strncpy(&newfp[j], fp[i], n); + j += n; + } + } + + if (SetFontPath(serverClient, newnpaths, (unsigned char *)newfp)) { + /* Note that this should never happen since all of the + * FPEs were previously valid. */ + dmxLog(dmxError, "Cannot reset the default font path.\n"); + } + } else if (dmxFontPath) { + dmxLog(dmxError, + "Please remove these font paths from the command line " + "or\n"); + dmxLog(dmxError, + "configuration file, or set the \"-ignorebadfontpaths\" " + "option to\n"); + dmxLog(dmxError, + "ignore them. For more information on these options, see " + "the\n"); + dmxLog(dmxError, + "Xdmx man page.\n"); + } else { + dmxLog(dmxError, + "Please specify the font paths that are available on all " + "back-end\n"); + dmxLog(dmxError, + "servers with the \"-fontpath\" option, or use the " + "\"-ignorebadfontpaths\"\n"); + dmxLog(dmxError, + "to ignore bad defaults. For more information on " + "these and other\n"); + dmxLog(dmxError, + "font-path-related options, see the Xdmx man page.\n"); + } + + if (!dmxIgnoreBadFontPaths || + (dmxIgnoreBadFontPaths && dmxSetFontPath(dmxScreen))) { + /* We still have errors so return with error */ + dmxFreeFontPath(fp); + XFreeFontPath(oldFontPath); + free(goodfps); + return FALSE; + } + } + + /* Find requested font on back-end server */ + name_atom = MakeAtom("FONT", 4, TRUE); + value_atom = 0L; + + for (i = 0; i < pFont->info.nprops; i++) { + if ((Atom)pFont->info.props[i].name == name_atom) { + value_atom = pFont->info.props[i].value; + break; + } + } + if (!value_atom) return FALSE; + + name = NameForAtom(value_atom); + if (!name) return FALSE; + + pFontPriv->font[pScreen->myNum] = + XLoadQueryFont(dmxScreen->beDisplay, name); + + /* Restore old font path */ + XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths); + XFreeFontPath(oldFontPath); + dmxSync(dmxScreen, FALSE); + + if (!pFontPriv->font[pScreen->myNum]) return FALSE; + + return TRUE; +} + +/** Realize the font, \a pFont, on the back-end server associated with + * \a pScreen. */ +Bool dmxRealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxFontPrivPtr pFontPriv; + + if (!(pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) { + FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); + pFontPriv = malloc(sizeof(dmxFontPrivRec)); + if (!pFontPriv) return FALSE; + pFontPriv->font = NULL; + MAXSCREENSALLOC(pFontPriv->font); + if (!pFontPriv->font) { + free(pFontPriv); + return FALSE; + } + pFontPriv->refcnt = 0; + } + + FontSetPrivate(pFont, dmxFontPrivateIndex, (pointer)pFontPriv); + + if (dmxScreen->beDisplay) { + if (!dmxBELoadFont(pScreen, pFont)) + return FALSE; + + pFontPriv->refcnt++; + } else { + pFontPriv->font[pScreen->myNum] = NULL; + } + + return TRUE; +} + +/** Free \a pFont on the back-end associated with \a pScreen. */ +Bool dmxBEFreeFont(ScreenPtr pScreen, FontPtr pFont) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxFontPrivPtr pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex); + + if (pFontPriv && pFontPriv->font[pScreen->myNum]) { + XFreeFont(dmxScreen->beDisplay, pFontPriv->font[pScreen->myNum]); + pFontPriv->font[pScreen->myNum] = NULL; + return TRUE; + } + + return FALSE; +} + +/** Unrealize the font, \a pFont, on the back-end server associated with + * \a pScreen. */ +Bool dmxUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxFontPrivPtr pFontPriv; + + if ((pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) { + /* In case the font failed to load properly */ + if (!pFontPriv->refcnt) { + MAXSCREENSFREE(pFontPriv->font); + free(pFontPriv); + FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); + } else if (pFontPriv->font[pScreen->myNum]) { + if (dmxScreen->beDisplay) + dmxBEFreeFont(pScreen, pFont); + + /* The code below is non-obvious, so here's an explanation... + * + * When creating the default GC, the server opens up the + * default font once for each screen, which in turn calls + * the RealizeFont function pointer once for each screen. + * During this process both dix's font refcnt and DMX's font + * refcnt are incremented once for each screen. + * + * Later, when shutting down the X server, dix shuts down + * each screen in reverse order. During this shutdown + * procedure, each screen's default GC is freed and then + * that screen is closed by calling the CloseScreen function + * pointer. screenInfo.numScreens is then decremented after + * closing each screen. This procedure means that the dix's + * font refcnt for the font used by the default GC's is + * decremented once for each screen # greater than 0. + * However, since dix's refcnt for the default font is not + * yet 0 for each screen greater than 0, no call to the + * UnrealizeFont function pointer is made for those screens. + * Then, when screen 0 is being closed, dix's font refcnt + * for the default GC's font is finally 0 and the font is + * unrealized. However, since screenInfo.numScreens has + * been decremented already down to 1, only one call to + * UnrealizeFont is made (for screen 0). Thus, even though + * RealizeFont was called once for each screen, + * UnrealizeFont is only called for screen 0. + * + * This is a bug in dix. + * + * To avoid the memory leak of pFontPriv for each server + * generation, we can also free pFontPriv if the refcnt is + * not yet 0 but the # of screens is 1 -- i.e., the case + * described in the dix bug above. This is only a temporary + * workaround until the bug in dix is solved. + * + * The other problem is that the font structure allocated by + * XLoadQueryFont() above is not freed for screens > 0. + * This problem cannot be worked around here since the back- + * end displays for screens > 0 have already been closed by + * the time this code is called from dix. + * + * When the bug in dix described above is fixed, then we can + * remove the "|| screenInfo.numScreens == 1" code below and + * the memory leaks will be eliminated. + */ + if (--pFontPriv->refcnt == 0 +#if 1 + /* Remove this code when the dix bug is fixed */ + || screenInfo.numScreens == 1 +#endif + ) { + MAXSCREENSFREE(pFontPriv->font); + free(pFontPriv); + FontSetPrivate(pFont, dmxFontPrivateIndex, NULL); + } + } + } + + return TRUE; +} diff --git a/xorg-server/hw/dmx/dmxgc.c b/xorg-server/hw/dmx/dmxgc.c index eb21d3c60..82f74b6e6 100644 --- a/xorg-server/hw/dmx/dmxgc.c +++ b/xorg-server/hw/dmx/dmxgc.c @@ -1,421 +1,421 @@ -/* - * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 - * - */ - -/** \file - * This file provides support for GCs. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include "dmx.h" -#include "dmxsync.h" -#include "dmxgc.h" -#include "dmxgcops.h" -#include "dmxpixmap.h" -#include "dmxfont.h" - -#include "gcstruct.h" -#include "pixmapstr.h" -#include "migc.h" - -static GCFuncs dmxGCFuncs = { - dmxValidateGC, - dmxChangeGC, - dmxCopyGC, - dmxDestroyGC, - dmxChangeClip, - dmxDestroyClip, - dmxCopyClip, -}; - -static GCOps dmxGCOps = { - dmxFillSpans, - dmxSetSpans, - dmxPutImage, - dmxCopyArea, - dmxCopyPlane, - dmxPolyPoint, - dmxPolylines, - dmxPolySegment, - dmxPolyRectangle, - dmxPolyArc, - dmxFillPolygon, - dmxPolyFillRect, - dmxPolyFillArc, - dmxPolyText8, - dmxPolyText16, - dmxImageText8, - dmxImageText16, - dmxImageGlyphBlt, - dmxPolyGlyphBlt, - dmxPushPixels -}; - -/** Initialize the GC on \a pScreen */ -Bool dmxInitGC(ScreenPtr pScreen) -{ - if (!dixRequestPrivate(dmxGCPrivateKey, sizeof(dmxGCPrivRec))) - return FALSE; - return TRUE; -} - -/** Create the GC on the back-end server. */ -void dmxBECreateGC(ScreenPtr pScreen, GCPtr pGC) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); - int i; - - for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { - if (pGC->depth == dmxScreen->bePixmapFormats[i].depth) { - unsigned long mask; - XGCValues gcvals; - - mask = GCGraphicsExposures; - gcvals.graphics_exposures = FALSE; - - /* Create GC in the back-end servers */ - pGCPriv->gc = XCreateGC(dmxScreen->beDisplay, - dmxScreen->scrnDefDrawables[i], - mask, &gcvals); - break; - } - } -} - -/** Create a graphics context on the back-end server associated /a pGC's - * screen. */ -Bool dmxCreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); - Bool ret; - - DMX_UNWRAP(CreateGC, dmxScreen, pScreen); - if ((ret = pScreen->CreateGC(pGC))) { - /* Save the old funcs */ - pGCPriv->funcs = pGC->funcs; - pGCPriv->ops = NULL; - - pGC->funcs = &dmxGCFuncs; - - if (dmxScreen->beDisplay) { - dmxBECreateGC(pScreen, pGC); - } else { - pGCPriv->gc = NULL; - } - - /* Check for "magic special case" - * 1. see CreateGC in dix/gc.c for more info - * 2. see dmxChangeGC for more info - */ - pGCPriv->msc = (!pGC->tileIsPixel && !pGC->tile.pixmap); - } - DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen); - - return ret; -} - -/** Validate a graphics context, \a pGC, locally in the DMX server and - * recompute the composite clip, if necessary. */ -void dmxValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) -{ - dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); - - DMX_GC_FUNC_PROLOGUE(pGC); -#if 0 - pGC->funcs->ValidateGC(pGC, changes, pDrawable); -#endif - - if (pDrawable->type == DRAWABLE_WINDOW || - pDrawable->type == DRAWABLE_PIXMAP) { - /* Save the old ops, since we're about to change the ops in the - * epilogue. - */ - pGCPriv->ops = pGC->ops; - } else { - pGCPriv->ops = NULL; - } - - /* If the client clip is different or moved OR the subwindowMode has - * changed OR the window's clip has changed since the last - * validation, then we need to recompute the composite clip. - */ - if ((changes & (GCClipXOrigin | - GCClipYOrigin | - GCClipMask | - GCSubwindowMode)) || - (pDrawable->serialNumber != - (pGC->serialNumber & DRAWABLE_SERIAL_BITS))) { - miComputeCompositeClip(pGC, pDrawable); - } - - DMX_GC_FUNC_EPILOGUE(pGC); -} - -/** Set the values in the graphics context on the back-end server - * associated with \a pGC's screen. */ -void dmxChangeGC(GCPtr pGC, unsigned long mask) -{ - ScreenPtr pScreen = pGC->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); - XGCValues v; - - DMX_GC_FUNC_PROLOGUE(pGC); -#if 0 - pGC->funcs->ChangeGC(pGC, mask); -#endif - - /* Handle "magic special case" from CreateGC */ - if (pGCPriv->msc) { - /* The "magic special case" is used to handle the case where a - * foreground pixel is set when the GC is created so that a - * "pseudo default-tile" can be created and used in case the - * fillstyle was set to FillTiled. This specific case is tested - * in xtest (XCreateGC test #3). What has happened in dix by - * the time it reaches here is (1) the pGC->tile.pixel has been - * set to pGC->fgPixel and pGC->tileIsPixel is set, (2) if a - * tile has also been set, then pGC->tileIsPixel is unset and - * pGC->tile.pixmap is initialized; else, the default tile is - * created and pGC->tileIsPixel is unset and pGC->tile.pixmap is - * initialized to the "pseudo default-tile". In either case, - * pGC->tile.pixmap is set; however, in the "magic special case" - * the mask is not updated to allow us to detect that we should - * initialize the GCTile in the back-end server. Thus, we catch - * this case in dmxCreateGC and add GCTile to the mask here. - * Are there any cases that I've missed? - */ - - /* Make sure that the tile.pixmap is set, just in case the user - * set GCTile in the mask but forgot to set vals.pixmap - */ - if (pGC->tile.pixmap) mask |= GCTile; - - /* This only happens once when the GC is created */ - pGCPriv->msc = FALSE; - } - - /* Update back-end server's gc */ - if (mask & GCFunction) v.function = pGC->alu; - if (mask & GCPlaneMask) v.plane_mask = pGC->planemask; - if (mask & GCForeground) v.foreground = pGC->fgPixel; - if (mask & GCBackground) v.background = pGC->bgPixel; - if (mask & GCLineWidth) v.line_width = pGC->lineWidth; - if (mask & GCLineStyle) v.line_style = pGC->lineStyle; - if (mask & GCCapStyle) v.cap_style = pGC->capStyle; - if (mask & GCJoinStyle) v.join_style = pGC->joinStyle; - if (mask & GCFillStyle) v.fill_style = pGC->fillStyle; - if (mask & GCFillRule) v.fill_rule = pGC->fillRule; - if (mask & GCTile) { - if (pGC->tileIsPixel) { - mask &= ~GCTile; - } else { - dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->tile.pixmap); - v.tile = (Drawable)pPixPriv->pixmap; - } - } - if (mask & GCStipple) { - dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->stipple); - v.stipple = (Drawable)pPixPriv->pixmap; - } - if (mask & GCTileStipXOrigin) v.ts_x_origin = pGC->patOrg.x; - if (mask & GCTileStipYOrigin) v.ts_y_origin = pGC->patOrg.y; - if (mask & GCFont) { - if (dmxScreen->beDisplay) { - dmxFontPrivPtr pFontPriv; - pFontPriv = FontGetPrivate(pGC->font, dmxFontPrivateIndex); - v.font = pFontPriv->font[pScreen->myNum]->fid; - } else { - mask &= ~GCFont; - } - } - if (mask & GCSubwindowMode) v.subwindow_mode = pGC->subWindowMode; - - /* Graphics exposures are not needed on the back-ends since they can - be generated on the front-end thereby saving bandwidth. */ - if (mask & GCGraphicsExposures) mask &= ~GCGraphicsExposures; - - if (mask & GCClipXOrigin) v.clip_x_origin = pGC->clipOrg.x; - if (mask & GCClipYOrigin) v.clip_y_origin = pGC->clipOrg.y; - if (mask & GCClipMask) mask &= ~GCClipMask; /* See ChangeClip */ - if (mask & GCDashOffset) v.dash_offset = pGC->dashOffset; - if (mask & GCDashList) { - mask &= ~GCDashList; - if (dmxScreen->beDisplay) - XSetDashes(dmxScreen->beDisplay, pGCPriv->gc, - pGC->dashOffset, (char *)pGC->dash, - pGC->numInDashList); - } - if (mask & GCArcMode) v.arc_mode = pGC->arcMode; - - if (mask && dmxScreen->beDisplay) { - XChangeGC(dmxScreen->beDisplay, pGCPriv->gc, mask, &v); - dmxSync(dmxScreen, FALSE); - } - - DMX_GC_FUNC_EPILOGUE(pGC); -} - -/** Copy \a pGCSrc to \a pGCDst on the back-end server associated with - * \a pGCSrc's screen. */ -void dmxCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst) -{ - ScreenPtr pScreen = pGCSrc->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxGCPrivPtr pGCSrcPriv = DMX_GET_GC_PRIV(pGCSrc); - dmxGCPrivPtr pGCDstPriv = DMX_GET_GC_PRIV(pGCDst); - - DMX_GC_FUNC_PROLOGUE(pGCDst); - pGCDst->funcs->CopyGC(pGCSrc, changes, pGCDst); - - /* Copy the GC on the back-end server */ - if (dmxScreen->beDisplay) - XCopyGC(dmxScreen->beDisplay, pGCSrcPriv->gc, changes, pGCDstPriv->gc); - - DMX_GC_FUNC_EPILOGUE(pGCDst); -} - -/** Free the \a pGC on the back-end server. */ -Bool dmxBEFreeGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); - - if (pGCPriv->gc) { - XFreeGC(dmxScreen->beDisplay, pGCPriv->gc); - pGCPriv->gc = NULL; - return TRUE; - } - - return FALSE; -} - -/** Destroy the graphics context, \a pGC and free the corresponding GC - * on the back-end server. */ -void dmxDestroyGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - - DMX_GC_FUNC_PROLOGUE(pGC); - - /* Free the GC on the back-end server */ - if (dmxScreen->beDisplay) - dmxBEFreeGC(pGC); - - pGC->funcs->DestroyGC(pGC); - DMX_GC_FUNC_EPILOGUE(pGC); -} - -/** Change the clip rects for a GC. */ -void dmxChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects) -{ - ScreenPtr pScreen = pGC->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); - XRectangle *pRects; - BoxPtr pBox; - int i, nRects; - - DMX_GC_FUNC_PROLOGUE(pGC); - pGC->funcs->ChangeClip(pGC, type, pvalue, nrects); - - /* Set the client clip on the back-end server */ - switch (pGC->clientClipType) { - case CT_NONE: - if (dmxScreen->beDisplay) - XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None); - break; - - case CT_REGION: - if (dmxScreen->beDisplay) { - nRects = REGION_NUM_RECTS((RegionPtr)pGC->clientClip); - pRects = xalloc(nRects * sizeof(*pRects)); - pBox = REGION_RECTS((RegionPtr)pGC->clientClip); - - for (i = 0; i < nRects; i++) { - pRects[i].x = pBox[i].x1; - pRects[i].y = pBox[i].y1; - pRects[i].width = pBox[i].x2 - pBox[i].x1; - pRects[i].height = pBox[i].y2 - pBox[i].y1; - } - - XSetClipRectangles(dmxScreen->beDisplay, pGCPriv->gc, - pGC->clipOrg.x, pGC->clipOrg.y, - pRects, nRects, Unsorted); - - xfree(pRects); - } - break; - - case CT_PIXMAP: - case CT_UNSORTED: - case CT_YSORTED: - case CT_YXSORTED: - case CT_YXBANDED: - /* These clip types are condensed down to either NONE or REGION - in the mi code */ - break; - } - - DMX_GC_FUNC_EPILOGUE(pGC); -} - -/** Destroy a GC's clip rects. */ -void dmxDestroyClip(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); - - DMX_GC_FUNC_PROLOGUE(pGC); - pGC->funcs->DestroyClip(pGC); - - /* Set the client clip on the back-end server to None */ - if (dmxScreen->beDisplay) - XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None); - - DMX_GC_FUNC_EPILOGUE(pGC); -} - -/** Copy a GC's clip rects. */ -void dmxCopyClip(GCPtr pGCDst, GCPtr pGCSrc) -{ - DMX_GC_FUNC_PROLOGUE(pGCDst); - pGCDst->funcs->CopyClip(pGCDst, pGCSrc); - DMX_GC_FUNC_EPILOGUE(pGCDst); -} +/* + * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 + * + */ + +/** \file + * This file provides support for GCs. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include "dmxsync.h" +#include "dmxgc.h" +#include "dmxgcops.h" +#include "dmxpixmap.h" +#include "dmxfont.h" + +#include "gcstruct.h" +#include "pixmapstr.h" +#include "migc.h" + +static GCFuncs dmxGCFuncs = { + dmxValidateGC, + dmxChangeGC, + dmxCopyGC, + dmxDestroyGC, + dmxChangeClip, + dmxDestroyClip, + dmxCopyClip, +}; + +static GCOps dmxGCOps = { + dmxFillSpans, + dmxSetSpans, + dmxPutImage, + dmxCopyArea, + dmxCopyPlane, + dmxPolyPoint, + dmxPolylines, + dmxPolySegment, + dmxPolyRectangle, + dmxPolyArc, + dmxFillPolygon, + dmxPolyFillRect, + dmxPolyFillArc, + dmxPolyText8, + dmxPolyText16, + dmxImageText8, + dmxImageText16, + dmxImageGlyphBlt, + dmxPolyGlyphBlt, + dmxPushPixels +}; + +/** Initialize the GC on \a pScreen */ +Bool dmxInitGC(ScreenPtr pScreen) +{ + if (!dixRequestPrivate(dmxGCPrivateKey, sizeof(dmxGCPrivRec))) + return FALSE; + return TRUE; +} + +/** Create the GC on the back-end server. */ +void dmxBECreateGC(ScreenPtr pScreen, GCPtr pGC) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); + int i; + + for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { + if (pGC->depth == dmxScreen->bePixmapFormats[i].depth) { + unsigned long mask; + XGCValues gcvals; + + mask = GCGraphicsExposures; + gcvals.graphics_exposures = FALSE; + + /* Create GC in the back-end servers */ + pGCPriv->gc = XCreateGC(dmxScreen->beDisplay, + dmxScreen->scrnDefDrawables[i], + mask, &gcvals); + break; + } + } +} + +/** Create a graphics context on the back-end server associated /a pGC's + * screen. */ +Bool dmxCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); + Bool ret; + + DMX_UNWRAP(CreateGC, dmxScreen, pScreen); + if ((ret = pScreen->CreateGC(pGC))) { + /* Save the old funcs */ + pGCPriv->funcs = pGC->funcs; + pGCPriv->ops = NULL; + + pGC->funcs = &dmxGCFuncs; + + if (dmxScreen->beDisplay) { + dmxBECreateGC(pScreen, pGC); + } else { + pGCPriv->gc = NULL; + } + + /* Check for "magic special case" + * 1. see CreateGC in dix/gc.c for more info + * 2. see dmxChangeGC for more info + */ + pGCPriv->msc = (!pGC->tileIsPixel && !pGC->tile.pixmap); + } + DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen); + + return ret; +} + +/** Validate a graphics context, \a pGC, locally in the DMX server and + * recompute the composite clip, if necessary. */ +void dmxValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); + + DMX_GC_FUNC_PROLOGUE(pGC); +#if 0 + pGC->funcs->ValidateGC(pGC, changes, pDrawable); +#endif + + if (pDrawable->type == DRAWABLE_WINDOW || + pDrawable->type == DRAWABLE_PIXMAP) { + /* Save the old ops, since we're about to change the ops in the + * epilogue. + */ + pGCPriv->ops = pGC->ops; + } else { + pGCPriv->ops = NULL; + } + + /* If the client clip is different or moved OR the subwindowMode has + * changed OR the window's clip has changed since the last + * validation, then we need to recompute the composite clip. + */ + if ((changes & (GCClipXOrigin | + GCClipYOrigin | + GCClipMask | + GCSubwindowMode)) || + (pDrawable->serialNumber != + (pGC->serialNumber & DRAWABLE_SERIAL_BITS))) { + miComputeCompositeClip(pGC, pDrawable); + } + + DMX_GC_FUNC_EPILOGUE(pGC); +} + +/** Set the values in the graphics context on the back-end server + * associated with \a pGC's screen. */ +void dmxChangeGC(GCPtr pGC, unsigned long mask) +{ + ScreenPtr pScreen = pGC->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); + XGCValues v; + + DMX_GC_FUNC_PROLOGUE(pGC); +#if 0 + pGC->funcs->ChangeGC(pGC, mask); +#endif + + /* Handle "magic special case" from CreateGC */ + if (pGCPriv->msc) { + /* The "magic special case" is used to handle the case where a + * foreground pixel is set when the GC is created so that a + * "pseudo default-tile" can be created and used in case the + * fillstyle was set to FillTiled. This specific case is tested + * in xtest (XCreateGC test #3). What has happened in dix by + * the time it reaches here is (1) the pGC->tile.pixel has been + * set to pGC->fgPixel and pGC->tileIsPixel is set, (2) if a + * tile has also been set, then pGC->tileIsPixel is unset and + * pGC->tile.pixmap is initialized; else, the default tile is + * created and pGC->tileIsPixel is unset and pGC->tile.pixmap is + * initialized to the "pseudo default-tile". In either case, + * pGC->tile.pixmap is set; however, in the "magic special case" + * the mask is not updated to allow us to detect that we should + * initialize the GCTile in the back-end server. Thus, we catch + * this case in dmxCreateGC and add GCTile to the mask here. + * Are there any cases that I've missed? + */ + + /* Make sure that the tile.pixmap is set, just in case the user + * set GCTile in the mask but forgot to set vals.pixmap + */ + if (pGC->tile.pixmap) mask |= GCTile; + + /* This only happens once when the GC is created */ + pGCPriv->msc = FALSE; + } + + /* Update back-end server's gc */ + if (mask & GCFunction) v.function = pGC->alu; + if (mask & GCPlaneMask) v.plane_mask = pGC->planemask; + if (mask & GCForeground) v.foreground = pGC->fgPixel; + if (mask & GCBackground) v.background = pGC->bgPixel; + if (mask & GCLineWidth) v.line_width = pGC->lineWidth; + if (mask & GCLineStyle) v.line_style = pGC->lineStyle; + if (mask & GCCapStyle) v.cap_style = pGC->capStyle; + if (mask & GCJoinStyle) v.join_style = pGC->joinStyle; + if (mask & GCFillStyle) v.fill_style = pGC->fillStyle; + if (mask & GCFillRule) v.fill_rule = pGC->fillRule; + if (mask & GCTile) { + if (pGC->tileIsPixel) { + mask &= ~GCTile; + } else { + dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->tile.pixmap); + v.tile = (Drawable)pPixPriv->pixmap; + } + } + if (mask & GCStipple) { + dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pGC->stipple); + v.stipple = (Drawable)pPixPriv->pixmap; + } + if (mask & GCTileStipXOrigin) v.ts_x_origin = pGC->patOrg.x; + if (mask & GCTileStipYOrigin) v.ts_y_origin = pGC->patOrg.y; + if (mask & GCFont) { + if (dmxScreen->beDisplay) { + dmxFontPrivPtr pFontPriv; + pFontPriv = FontGetPrivate(pGC->font, dmxFontPrivateIndex); + v.font = pFontPriv->font[pScreen->myNum]->fid; + } else { + mask &= ~GCFont; + } + } + if (mask & GCSubwindowMode) v.subwindow_mode = pGC->subWindowMode; + + /* Graphics exposures are not needed on the back-ends since they can + be generated on the front-end thereby saving bandwidth. */ + if (mask & GCGraphicsExposures) mask &= ~GCGraphicsExposures; + + if (mask & GCClipXOrigin) v.clip_x_origin = pGC->clipOrg.x; + if (mask & GCClipYOrigin) v.clip_y_origin = pGC->clipOrg.y; + if (mask & GCClipMask) mask &= ~GCClipMask; /* See ChangeClip */ + if (mask & GCDashOffset) v.dash_offset = pGC->dashOffset; + if (mask & GCDashList) { + mask &= ~GCDashList; + if (dmxScreen->beDisplay) + XSetDashes(dmxScreen->beDisplay, pGCPriv->gc, + pGC->dashOffset, (char *)pGC->dash, + pGC->numInDashList); + } + if (mask & GCArcMode) v.arc_mode = pGC->arcMode; + + if (mask && dmxScreen->beDisplay) { + XChangeGC(dmxScreen->beDisplay, pGCPriv->gc, mask, &v); + dmxSync(dmxScreen, FALSE); + } + + DMX_GC_FUNC_EPILOGUE(pGC); +} + +/** Copy \a pGCSrc to \a pGCDst on the back-end server associated with + * \a pGCSrc's screen. */ +void dmxCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst) +{ + ScreenPtr pScreen = pGCSrc->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxGCPrivPtr pGCSrcPriv = DMX_GET_GC_PRIV(pGCSrc); + dmxGCPrivPtr pGCDstPriv = DMX_GET_GC_PRIV(pGCDst); + + DMX_GC_FUNC_PROLOGUE(pGCDst); + pGCDst->funcs->CopyGC(pGCSrc, changes, pGCDst); + + /* Copy the GC on the back-end server */ + if (dmxScreen->beDisplay) + XCopyGC(dmxScreen->beDisplay, pGCSrcPriv->gc, changes, pGCDstPriv->gc); + + DMX_GC_FUNC_EPILOGUE(pGCDst); +} + +/** Free the \a pGC on the back-end server. */ +Bool dmxBEFreeGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); + + if (pGCPriv->gc) { + XFreeGC(dmxScreen->beDisplay, pGCPriv->gc); + pGCPriv->gc = NULL; + return TRUE; + } + + return FALSE; +} + +/** Destroy the graphics context, \a pGC and free the corresponding GC + * on the back-end server. */ +void dmxDestroyGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + + DMX_GC_FUNC_PROLOGUE(pGC); + + /* Free the GC on the back-end server */ + if (dmxScreen->beDisplay) + dmxBEFreeGC(pGC); + + pGC->funcs->DestroyGC(pGC); + DMX_GC_FUNC_EPILOGUE(pGC); +} + +/** Change the clip rects for a GC. */ +void dmxChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects) +{ + ScreenPtr pScreen = pGC->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); + XRectangle *pRects; + BoxPtr pBox; + int i, nRects; + + DMX_GC_FUNC_PROLOGUE(pGC); + pGC->funcs->ChangeClip(pGC, type, pvalue, nrects); + + /* Set the client clip on the back-end server */ + switch (pGC->clientClipType) { + case CT_NONE: + if (dmxScreen->beDisplay) + XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None); + break; + + case CT_REGION: + if (dmxScreen->beDisplay) { + nRects = REGION_NUM_RECTS((RegionPtr)pGC->clientClip); + pRects = malloc(nRects * sizeof(*pRects)); + pBox = REGION_RECTS((RegionPtr)pGC->clientClip); + + for (i = 0; i < nRects; i++) { + pRects[i].x = pBox[i].x1; + pRects[i].y = pBox[i].y1; + pRects[i].width = pBox[i].x2 - pBox[i].x1; + pRects[i].height = pBox[i].y2 - pBox[i].y1; + } + + XSetClipRectangles(dmxScreen->beDisplay, pGCPriv->gc, + pGC->clipOrg.x, pGC->clipOrg.y, + pRects, nRects, Unsorted); + + free(pRects); + } + break; + + case CT_PIXMAP: + case CT_UNSORTED: + case CT_YSORTED: + case CT_YXSORTED: + case CT_YXBANDED: + /* These clip types are condensed down to either NONE or REGION + in the mi code */ + break; + } + + DMX_GC_FUNC_EPILOGUE(pGC); +} + +/** Destroy a GC's clip rects. */ +void dmxDestroyClip(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxGCPrivPtr pGCPriv = DMX_GET_GC_PRIV(pGC); + + DMX_GC_FUNC_PROLOGUE(pGC); + pGC->funcs->DestroyClip(pGC); + + /* Set the client clip on the back-end server to None */ + if (dmxScreen->beDisplay) + XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None); + + DMX_GC_FUNC_EPILOGUE(pGC); +} + +/** Copy a GC's clip rects. */ +void dmxCopyClip(GCPtr pGCDst, GCPtr pGCSrc) +{ + DMX_GC_FUNC_PROLOGUE(pGCDst); + pGCDst->funcs->CopyClip(pGCDst, pGCSrc); + DMX_GC_FUNC_EPILOGUE(pGCDst); +} diff --git a/xorg-server/hw/dmx/dmxinit.c b/xorg-server/hw/dmx/dmxinit.c index 617ec5e49..37b302a25 100644 --- a/xorg-server/hw/dmx/dmxinit.c +++ b/xorg-server/hw/dmx/dmxinit.c @@ -412,7 +412,7 @@ void dmxGetColormaps(DMXScreenInfo *dmxScreen) int i; dmxScreen->beNumDefColormaps = dmxScreen->beNumVisuals; - dmxScreen->beDefColormaps = xalloc(dmxScreen->beNumDefColormaps * + dmxScreen->beDefColormaps = malloc(dmxScreen->beNumDefColormaps * sizeof(*dmxScreen->beDefColormaps)); for (i = 0; i < dmxScreen->beNumDefColormaps; i++) @@ -738,7 +738,7 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[]) nconfigs = dmxScreen->numGlxVisuals; } - configprivs = xalloc(nconfigs * sizeof(dmxGlxVisualPrivate*)); + configprivs = malloc(nconfigs * sizeof(dmxGlxVisualPrivate*)); if (configs != NULL && configprivs != NULL) { @@ -748,7 +748,7 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[]) for (i = 0; i < nconfigs; i++) { configprivs[i] = (dmxGlxVisualPrivate *) - xalloc(sizeof(dmxGlxVisualPrivate)); + malloc(sizeof(dmxGlxVisualPrivate)); configprivs[i]->x_visual_depth = 0; configprivs[i]->x_visual_class = 0; @@ -816,11 +816,11 @@ static void dmxSetDefaultFontPath(char *fp) int len; len = strlen(dmxFontPath); - dmxFontPath = xrealloc(dmxFontPath, len+fplen+1); + dmxFontPath = realloc(dmxFontPath, len+fplen+1); dmxFontPath[len] = ','; strncpy(&dmxFontPath[len+1], fp, fplen); } else { - dmxFontPath = xalloc(fplen); + dmxFontPath = malloc(fplen); strncpy(dmxFontPath, fp, fplen); } diff --git a/xorg-server/hw/dmx/dmxpict.c b/xorg-server/hw/dmx/dmxpict.c index efb2e41c9..c7bcd5b91 100644 --- a/xorg-server/hw/dmx/dmxpict.c +++ b/xorg-server/hw/dmx/dmxpict.c @@ -274,7 +274,7 @@ static int dmxProcRenderCreateGlyphSet(ClientPtr client) glyphSet = SecurityLookupIDByType(client, stuff->gsid, GlyphSetType, DixDestroyAccess); - glyphPriv = xalloc(sizeof(dmxGlyphPrivRec)); + glyphPriv = malloc(sizeof(dmxGlyphPrivRec)); if (!glyphPriv) return BadAlloc; glyphPriv->glyphSets = NULL; MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc); @@ -331,7 +331,7 @@ static int dmxProcRenderFreeGlyphSet(ClientPtr client) } MAXSCREENSFREE(glyphPriv->glyphSets); - xfree(glyphPriv); + free(glyphPriv); DMX_SET_GLYPH_PRIV(glyphSet, NULL); } @@ -369,7 +369,7 @@ static int dmxProcRenderAddGlyphs(ClientPtr client) sizeof(xRenderAddGlyphsReq) - (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs); - gidsCopy = xalloc(sizeof(*gidsCopy) * nglyphs); + gidsCopy = malloc(sizeof(*gidsCopy) * nglyphs); for (i = 0; i < nglyphs; i++) gidsCopy[i] = gids[i]; /* FIXME: Will this ever fail? */ @@ -387,7 +387,7 @@ static int dmxProcRenderAddGlyphs(ClientPtr client) dmxSync(dmxScreen, FALSE); } } - xfree(gidsCopy); + free(gidsCopy); } return ret; @@ -411,7 +411,7 @@ static int dmxProcRenderFreeGlyphs(ClientPtr client) nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2; if (nglyphs) { - gids = xalloc(sizeof(*gids) * nglyphs); + gids = malloc(sizeof(*gids) * nglyphs); for (i = 0; i < nglyphs; i++) gids[i] = ((CARD32 *)(stuff + 1))[i]; @@ -424,7 +424,7 @@ static int dmxProcRenderFreeGlyphs(ClientPtr client) dmxSync(dmxScreen, FALSE); } } - xfree(gids); + free(gids); } } @@ -531,13 +531,13 @@ static int dmxProcRenderCompositeGlyphs(ClientPtr client) /* The following only works for Render version > 0.2 */ /* All of the XGlyphElt* structure sizes are identical */ - elts = xalloc(nelt * sizeof(XGlyphElt8)); + elts = malloc(nelt * sizeof(XGlyphElt8)); if (!elts) return BadAlloc; - glyphs = xalloc(nglyph * size); + glyphs = malloc(nglyph * size); if (!glyphs) { - xfree(elts); + free(elts); return BadAlloc; } @@ -605,8 +605,8 @@ static int dmxProcRenderCompositeGlyphs(ClientPtr client) dmxSync(dmxScreen, FALSE); - xfree(elts); - xfree(glyphs); + free(elts); + free(glyphs); } return ret; @@ -878,7 +878,7 @@ int dmxChangePictureClip(PicturePtr pPicture, int clipType, int nRects; nRects = nBox; - pRects = pRect = xalloc(nRects * sizeof(*pRect)); + pRects = pRect = malloc(nRects * sizeof(*pRect)); while (nBox--) { pRect->x = pBox->x1; @@ -894,7 +894,7 @@ int dmxChangePictureClip(PicturePtr pPicture, int clipType, 0, 0, pRects, nRects); - xfree(pRects); + free(pRects); } else { XRenderSetPictureClipRectangles(dmxScreen->beDisplay, pPictPriv->pict, diff --git a/xorg-server/hw/dmx/dmxpixmap.c b/xorg-server/hw/dmx/dmxpixmap.c index 66224031a..bcbcc3a88 100644 --- a/xorg-server/hw/dmx/dmxpixmap.c +++ b/xorg-server/hw/dmx/dmxpixmap.c @@ -1,253 +1,253 @@ -/* - * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 - * - */ - -/** \file - * Provides pixmap support. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include "dmx.h" -#include "dmxsync.h" -#include "dmxpixmap.h" - -#include "pixmapstr.h" -#include "servermd.h" -#include "privates.h" - -/** Initialize a private area in \a pScreen for pixmap information. */ -Bool dmxInitPixmap(ScreenPtr pScreen) -{ - if (!dixRequestPrivate(dmxPixPrivateKey, sizeof(dmxPixPrivRec))) - return FALSE; - - return TRUE; -} - -/** Create a pixmap on the back-end server. */ -void dmxBECreatePixmap(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); - - /* Make sure we haven't already created this pixmap. This can - * happen when the pixmap is used elsewhere (e.g., as a background - * or border for a window) and the refcnt > 1. - */ - if (pPixPriv->pixmap) - return; - - if (pPixmap->drawable.width && pPixmap->drawable.height) { - pPixPriv->pixmap = XCreatePixmap(dmxScreen->beDisplay, - dmxScreen->scrnWin, - pPixmap->drawable.width, - pPixmap->drawable.height, - pPixmap->drawable.depth); - dmxSync(dmxScreen, FALSE); - } -} - -/** Create a pixmap for \a pScreen with the specified \a width, \a - * height, and \a depth. */ -PixmapPtr dmxCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, - unsigned usage_hint) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PixmapPtr pPixmap; - int bpp; - dmxPixPrivPtr pPixPriv; - -#if 0 - DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen); - if (pScreen->CreatePixmap) - ret = pScreen->CreatePixmap(pPixmap); -#endif - - /* Create pixmap on back-end server */ - if (depth == 24) bpp = 32; - else bpp = depth; - - pPixmap = AllocatePixmap(pScreen, 0); - if (!pPixmap) - return NullPixmap; - - pPixmap->drawable.type = DRAWABLE_PIXMAP; - pPixmap->drawable.class = 0; - pPixmap->drawable.pScreen = pScreen; - pPixmap->drawable.depth = depth; - pPixmap->drawable.bitsPerPixel = bpp; - pPixmap->drawable.id = 0; - pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - pPixmap->drawable.x = 0; - pPixmap->drawable.y = 0; - pPixmap->drawable.width = width; - pPixmap->drawable.height = height; - pPixmap->devKind = PixmapBytePad(width, bpp); - pPixmap->refcnt = 1; - pPixmap->usage_hint = usage_hint; - - pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); - pPixPriv->pixmap = (Pixmap)0; - pPixPriv->detachedImage = NULL; - - /* Create the pixmap on the back-end server */ - if (dmxScreen->beDisplay) { - dmxBECreatePixmap(pPixmap); - } - -#if 0 - DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen); -#endif - - return pPixmap; -} - -/** Destroy the pixmap on the back-end server. */ -Bool dmxBEFreePixmap(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); - - if (pPixPriv->pixmap) { - XFreePixmap(dmxScreen->beDisplay, pPixPriv->pixmap); - pPixPriv->pixmap = (Pixmap)0; - return TRUE; - } - - return FALSE; -} - -/** Destroy the pixmap pointed to by \a pPixmap. */ -Bool dmxDestroyPixmap(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - Bool ret = TRUE; - -#if 0 - DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen); -#endif - - if (--pPixmap->refcnt) - return TRUE; - - /* Destroy pixmap on back-end server */ - if (dmxScreen->beDisplay) { - if (dmxBEFreePixmap(pPixmap)) { - /* Also make sure that we destroy any detached image */ - dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); - if (pPixPriv->detachedImage) - XDestroyImage(pPixPriv->detachedImage); - dmxSync(dmxScreen, FALSE); - } - } - dixFreePrivates(pPixmap->devPrivates); - xfree(pPixmap); - -#if 0 - if (pScreen->DestroyPixmap) - ret = pScreen->DestroyPixmap(pPixmap); - DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen); -#endif - - return ret; -} - -/** Create and return a region based on the pixmap pointed to by \a - * pPixmap. */ -RegionPtr dmxBitmapToRegion(PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); - XImage *ximage; - RegionPtr pReg, pTmpReg; - int x, y; - unsigned long previousPixel, currentPixel; - BoxRec Box; - Bool overlap; - - if (!dmxScreen->beDisplay) { - pReg = REGION_CREATE(pScreen, NullBox, 1); - return pReg; - } - - ximage = XGetImage(dmxScreen->beDisplay, pPixPriv->pixmap, 0, 0, - pPixmap->drawable.width, pPixmap->drawable.height, - 1, XYPixmap); - - pReg = REGION_CREATE(pScreen, NullBox, 1); - pTmpReg = REGION_CREATE(pScreen, NullBox, 1); - if(!pReg || !pTmpReg) { - XDestroyImage(ximage); - return NullRegion; - } - - for (y = 0; y < pPixmap->drawable.height; y++) { - Box.y1 = y; - Box.y2 = y + 1; - previousPixel = 0L; - for (x = 0; x < pPixmap->drawable.width; x++) { - currentPixel = XGetPixel(ximage, x, y); - if (previousPixel != currentPixel) { - if (previousPixel == 0L) { - /* left edge */ - Box.x1 = x; - } else if (currentPixel == 0L) { - /* right edge */ - Box.x2 = x; - REGION_RESET(pScreen, pTmpReg, &Box); - REGION_APPEND(pScreen, pReg, pTmpReg); - } - previousPixel = currentPixel; - } - } - if (previousPixel != 0L) { - /* right edge because of the end of pixmap */ - Box.x2 = pPixmap->drawable.width; - REGION_RESET(pScreen, pTmpReg, &Box); - REGION_APPEND(pScreen, pReg, pTmpReg); - } - } - - REGION_DESTROY(pScreen, pTmpReg); - XDestroyImage(ximage); - - REGION_VALIDATE(pScreen, pReg, &overlap); - - dmxSync(dmxScreen, FALSE); - return(pReg); -} +/* + * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 + * + */ + +/** \file + * Provides pixmap support. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include "dmxsync.h" +#include "dmxpixmap.h" + +#include "pixmapstr.h" +#include "servermd.h" +#include "privates.h" + +/** Initialize a private area in \a pScreen for pixmap information. */ +Bool dmxInitPixmap(ScreenPtr pScreen) +{ + if (!dixRequestPrivate(dmxPixPrivateKey, sizeof(dmxPixPrivRec))) + return FALSE; + + return TRUE; +} + +/** Create a pixmap on the back-end server. */ +void dmxBECreatePixmap(PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); + + /* Make sure we haven't already created this pixmap. This can + * happen when the pixmap is used elsewhere (e.g., as a background + * or border for a window) and the refcnt > 1. + */ + if (pPixPriv->pixmap) + return; + + if (pPixmap->drawable.width && pPixmap->drawable.height) { + pPixPriv->pixmap = XCreatePixmap(dmxScreen->beDisplay, + dmxScreen->scrnWin, + pPixmap->drawable.width, + pPixmap->drawable.height, + pPixmap->drawable.depth); + dmxSync(dmxScreen, FALSE); + } +} + +/** Create a pixmap for \a pScreen with the specified \a width, \a + * height, and \a depth. */ +PixmapPtr dmxCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + PixmapPtr pPixmap; + int bpp; + dmxPixPrivPtr pPixPriv; + +#if 0 + DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen); + if (pScreen->CreatePixmap) + ret = pScreen->CreatePixmap(pPixmap); +#endif + + /* Create pixmap on back-end server */ + if (depth == 24) bpp = 32; + else bpp = depth; + + pPixmap = AllocatePixmap(pScreen, 0); + if (!pPixmap) + return NullPixmap; + + pPixmap->drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = bpp; + pPixmap->drawable.id = 0; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->devKind = PixmapBytePad(width, bpp); + pPixmap->refcnt = 1; + pPixmap->usage_hint = usage_hint; + + pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); + pPixPriv->pixmap = (Pixmap)0; + pPixPriv->detachedImage = NULL; + + /* Create the pixmap on the back-end server */ + if (dmxScreen->beDisplay) { + dmxBECreatePixmap(pPixmap); + } + +#if 0 + DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen); +#endif + + return pPixmap; +} + +/** Destroy the pixmap on the back-end server. */ +Bool dmxBEFreePixmap(PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); + + if (pPixPriv->pixmap) { + XFreePixmap(dmxScreen->beDisplay, pPixPriv->pixmap); + pPixPriv->pixmap = (Pixmap)0; + return TRUE; + } + + return FALSE; +} + +/** Destroy the pixmap pointed to by \a pPixmap. */ +Bool dmxDestroyPixmap(PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Bool ret = TRUE; + +#if 0 + DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen); +#endif + + if (--pPixmap->refcnt) + return TRUE; + + /* Destroy pixmap on back-end server */ + if (dmxScreen->beDisplay) { + if (dmxBEFreePixmap(pPixmap)) { + /* Also make sure that we destroy any detached image */ + dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); + if (pPixPriv->detachedImage) + XDestroyImage(pPixPriv->detachedImage); + dmxSync(dmxScreen, FALSE); + } + } + dixFreePrivates(pPixmap->devPrivates); + free(pPixmap); + +#if 0 + if (pScreen->DestroyPixmap) + ret = pScreen->DestroyPixmap(pPixmap); + DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen); +#endif + + return ret; +} + +/** Create and return a region based on the pixmap pointed to by \a + * pPixmap. */ +RegionPtr dmxBitmapToRegion(PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap); + XImage *ximage; + RegionPtr pReg, pTmpReg; + int x, y; + unsigned long previousPixel, currentPixel; + BoxRec Box; + Bool overlap; + + if (!dmxScreen->beDisplay) { + pReg = REGION_CREATE(pScreen, NullBox, 1); + return pReg; + } + + ximage = XGetImage(dmxScreen->beDisplay, pPixPriv->pixmap, 0, 0, + pPixmap->drawable.width, pPixmap->drawable.height, + 1, XYPixmap); + + pReg = REGION_CREATE(pScreen, NullBox, 1); + pTmpReg = REGION_CREATE(pScreen, NullBox, 1); + if(!pReg || !pTmpReg) { + XDestroyImage(ximage); + return NullRegion; + } + + for (y = 0; y < pPixmap->drawable.height; y++) { + Box.y1 = y; + Box.y2 = y + 1; + previousPixel = 0L; + for (x = 0; x < pPixmap->drawable.width; x++) { + currentPixel = XGetPixel(ximage, x, y); + if (previousPixel != currentPixel) { + if (previousPixel == 0L) { + /* left edge */ + Box.x1 = x; + } else if (currentPixel == 0L) { + /* right edge */ + Box.x2 = x; + REGION_RESET(pScreen, pTmpReg, &Box); + REGION_APPEND(pScreen, pReg, pTmpReg); + } + previousPixel = currentPixel; + } + } + if (previousPixel != 0L) { + /* right edge because of the end of pixmap */ + Box.x2 = pPixmap->drawable.width; + REGION_RESET(pScreen, pTmpReg, &Box); + REGION_APPEND(pScreen, pReg, pTmpReg); + } + } + + REGION_DESTROY(pScreen, pTmpReg); + XDestroyImage(ximage); + + REGION_VALIDATE(pScreen, pReg, &overlap); + + dmxSync(dmxScreen, FALSE); + return(pReg); +} diff --git a/xorg-server/hw/dmx/dmxprop.c b/xorg-server/hw/dmx/dmxprop.c index 376313d8d..95efcb0e0 100644 --- a/xorg-server/hw/dmx/dmxprop.c +++ b/xorg-server/hw/dmx/dmxprop.c @@ -1,347 +1,347 @@ -/* - * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: - * Rickard E. (Rik) Faith - * - */ - -/** \file - * - * It is possible for one of the DMX "backend displays" to actually be - * smaller than the dimensions of the backend X server. Therefore, it - * is possible for more than one of the DMX "backend displays" to be - * physically located on the same backend X server. This situation must - * be detected so that cursor motion can be handled in an expected - * fashion. - * - * We could analyze the names used for the DMX "backend displays" (e.g., - * the names passed to the -display command-line parameter), but there - * are many possible names for a single X display, and failing to detect - * sameness leads to very unexpected results. Therefore, whenever the - * DMX server opens a window on a backend X server, a property value is - * queried and set on that backend to detect when another window is - * already open on that server. - * - * Further, it is possible that two different DMX server instantiations - * both have windows on the same physical backend X server. This case - * is also detected so that pointer input is not taken from that - * particular backend X server. - * - * The routines in this file handle the property management. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include "dmx.h" -#include "dmxprop.h" -#include "dmxlog.h" - -/** Holds the window id of all DMX windows on the backend X server. */ -#define DMX_ATOMNAME "DMX_NAME" - -/** The identification string of this DMX server */ -#define DMX_IDENT "Xdmx" - -extern char *display; - -static int dmxPropertyErrorHandler(Display *dpy, XErrorEvent *ev) -{ - return 0; -} - -static const unsigned char *dmxPropertyIdentifier(void) -{ - /* RATS: These buffers are only used in - * length-limited calls. */ - char hostname[256]; - static char buf[128]; - static int initialized = 0; - - if (initialized++) return (unsigned char *)buf; - - XmuGetHostname(hostname, sizeof(hostname)); - XmuSnprintf(buf, sizeof(buf), "%s:%s:%s", DMX_IDENT, hostname, display); - return (unsigned char *)buf; -} - -/** Starting with the \a start screen, iterate over all of the screens - * on the same physical X server as \a start, calling \a f with the - * screen and the \a closure. (The common case is that \a start is the - * only DMX window on the backend X server.) */ -void *dmxPropertyIterate(DMXScreenInfo *start, - void *(*f)(DMXScreenInfo *dmxScreen, void *), - void *closure) -{ - DMXScreenInfo *pt; - - if (!start->next) { - if (!start->beDisplay) return NULL; - return f(start, closure); - } - - for (pt = start->next; /* condition at end of loop */; pt = pt->next) { - void *retval; - /* beDisplay ban be NULL if a screen was detached */ - dmxLog(dmxDebug, "pt = %p\n", pt); - dmxLog(dmxDebug, "pt->beDisplay = %p\n", pt->beDisplay); - if (pt->beDisplay && (retval = f(pt, closure))) return retval; - if (pt == start) break; - } - return NULL; -} - -/** Returns 0 if this is the only Xdmx session on the display; 1 - * otherwise. */ -static int dmxPropertyCheckOtherServers(DMXScreenInfo *dmxScreen, Atom atom) -{ - Display *dpy = dmxScreen->beDisplay; - XTextProperty tp; - XTextProperty tproot; - const char *pt; - int retcode = 0; - char **list = NULL; - int count = 0; - int i; - int (*dmxOldHandler)(Display *, XErrorEvent *); - - if (!dpy) - return 0; - - if (!XGetTextProperty(dpy, RootWindow(dpy,0), &tproot, atom) - || !tproot.nitems) return 0; - - /* Ignore BadWindow errors for this - * routine because the window id stored - * in the property might be old */ - dmxOldHandler = XSetErrorHandler(dmxPropertyErrorHandler); - for (pt = (const char *)tproot.value; pt && *pt; pt = pt ? pt + 1 : NULL) { - if ((pt = strchr(pt, ','))) { - Window win = strtol(pt+1, NULL, 10); - if (XGetTextProperty(dpy, win, &tp, atom) && tp.nitems) { - if (!strncmp((char *)tp.value, DMX_IDENT, strlen(DMX_IDENT))) { - int flag = 0; - for (i = 0; i < count; i++) - if (!strcmp(list[i], (char *)tp.value)) { - ++flag; - break; - } - if (flag) continue; - ++retcode; - dmxLogOutputWarning(dmxScreen, - "%s also running on %s\n", - tp.value, dmxScreen->name); - list = xrealloc(list, ++count * sizeof(*list)); - list[count-1] = xalloc(tp.nitems + 2); - strncpy(list[count-1], (char *)tp.value, tp.nitems + 1); - } - XFree(tp.value); - } - } - } - XSetErrorHandler(dmxOldHandler); - - for (i = 0; i < count; i++) xfree(list[i]); - xfree(list); - XFree(tproot.value); - if (!retcode) - dmxLogOutput(dmxScreen, "No Xdmx server running on backend\n"); - return retcode; -} - -/** Returns NULL if this is the only Xdmx window on the display. - * Otherwise, returns a pointer to the dmxScreen of the other windows on - * the display. */ -static DMXScreenInfo *dmxPropertyCheckOtherWindows(DMXScreenInfo *dmxScreen, - Atom atom) -{ - Display *dpy = dmxScreen->beDisplay; - const unsigned char *id = dmxPropertyIdentifier(); - XTextProperty tproot; - XTextProperty tp; - const char *pt; - int (*dmxOldHandler)(Display *, XErrorEvent *); - - if (!dpy) - return NULL; - - if (!XGetTextProperty(dpy, RootWindow(dpy,0), &tproot, atom) - || !tproot.nitems) return 0; - - /* Ignore BadWindow errors for this - * routine because the window id stored - * in the property might be old */ - dmxOldHandler = XSetErrorHandler(dmxPropertyErrorHandler); - for (pt = (const char *)tproot.value; pt && *pt; pt = pt ? pt + 1 : NULL) { - if ((pt = strchr(pt, ','))) { - Window win = strtol(pt+1, NULL, 10); - if (XGetTextProperty(dpy, win, &tp, atom) && tp.nitems) { - dmxLog(dmxDebug,"On %s/%lu: %s\n", - dmxScreen->name, win, tp.value); - if (!strncmp((char *)tp.value, (char *)id, - strlen((char *)id))) { - int idx; - - if (!(pt = strchr((char *)tp.value, ','))) continue; - idx = strtol(pt+1, NULL, 10); - if (idx < 0 || idx >= dmxNumScreens) continue; - if (dmxScreens[idx].scrnWin != win) continue; - XSetErrorHandler(dmxOldHandler); - return &dmxScreens[idx]; - } - XFree(tp.value); - } - } - } - XSetErrorHandler(dmxOldHandler); - XFree(tproot.value); - return 0; -} - -/** Returns 0 if this is the only Xdmx session on the display; 1 - * otherwise. */ -int dmxPropertyDisplay(DMXScreenInfo *dmxScreen) -{ - Atom atom; - const unsigned char *id = dmxPropertyIdentifier(); - Display *dpy = dmxScreen->beDisplay; - - if (!dpy) - return 0; - - atom = XInternAtom(dpy, DMX_ATOMNAME, False); - if (dmxPropertyCheckOtherServers(dmxScreen, atom)) { - dmxScreen->shared = 1; - return 1; - } - XChangeProperty(dpy, RootWindow(dpy,0), atom, XA_STRING, 8, - PropModeReplace, id, strlen((char *)id)); - return 0; -} - -/** Returns 1 if the dmxScreen and the display in \a name are on the - * same display, or 0 otherwise. We can't just compare the display - * names because there can be multiple synonyms for the same display, - * some of which cannot be determined without accessing the display - * itself (e.g., domain aliases or machines with multiple NICs). */ -int dmxPropertySameDisplay(DMXScreenInfo *dmxScreen, const char *name) -{ - Display *dpy0 = dmxScreen->beDisplay; - Atom atom0; - XTextProperty tp0; - Display *dpy1 = NULL; - Atom atom1; - XTextProperty tp1; - int retval = 0; - - if (!dpy0) - return 0; - - tp0.nitems = 0; - tp1.nitems = 0; - - if ((atom0 = XInternAtom(dpy0, DMX_ATOMNAME, True)) == None) { - dmxLog(dmxWarning, "No atom on %s\n", dmxScreen->name); - return 0; - } - if (!XGetTextProperty(dpy0, RootWindow(dpy0,0), &tp0, atom0) - || !tp0.nitems) { - dmxLog(dmxWarning, "No text property on %s\n", dmxScreen->name); - return 0; - } - - if (!(dpy1 = XOpenDisplay(name))) { - dmxLog(dmxWarning, "Cannot open %s\n", name); - goto cleanup; - } - atom1 = XInternAtom(dpy1, DMX_ATOMNAME, True); - if (atom1 == None) { - dmxLog(dmxDebug, "No atom on %s\n", name); - goto cleanup; - } - if (!XGetTextProperty(dpy1, RootWindow(dpy1,0), &tp1, atom1) - || !tp1.nitems) { - dmxLog(dmxDebug, "No text property on %s\n", name); - goto cleanup; - } - if (!strcmp((char *)tp0.value, (char *)tp1.value)) retval = 1; - - cleanup: - if (tp0.nitems) XFree(tp0.value); - if (tp1.nitems) XFree(tp1.value); - if (dpy1) XCloseDisplay(dpy1); - return retval; -} - -/** Prints a log message if \a dmxScreen is on the same backend X server - * as some other DMX backend (output) screen. Modifies the property - * (#DMX_ATOMNAME) on the backend X server to reflect the creation of \a - * dmxScreen. - * - * The root window of the backend X server holds a list of window ids - * for all DMX windows (on this DMX server or some other DMX server). - * - * This list can then be iterated, and the property for each window can - * be examined. This property contains the following tuple (no quotes): - * - * "#DMX_IDENT::," - */ -void dmxPropertyWindow(DMXScreenInfo *dmxScreen) -{ - Atom atom; - const unsigned char *id = dmxPropertyIdentifier(); - Display *dpy = dmxScreen->beDisplay; - Window win = dmxScreen->scrnWin; - DMXScreenInfo *other; - char buf[128]; /* RATS: only used with XmuSnprintf */ - - if (!dpy) - return; /* FIXME: What should be done here if Xdmx is started - * with this screen initially detached? - */ - - atom = XInternAtom(dpy, DMX_ATOMNAME, False); - if ((other = dmxPropertyCheckOtherWindows(dmxScreen, atom))) { - DMXScreenInfo *tmp = dmxScreen->next; - dmxScreen->next = (other->next ? other->next : other); - other->next = (tmp ? tmp : dmxScreen); - dmxLog(dmxDebug, "%d/%s/%lu and %d/%s/%lu are on the same backend\n", - dmxScreen->index, dmxScreen->name, dmxScreen->scrnWin, - other->index, other->name, other->scrnWin); - } - - XmuSnprintf(buf, sizeof(buf), ".%d,%lu", dmxScreen->index, - (long unsigned)win); - XChangeProperty(dpy, RootWindow(dpy,0), atom, XA_STRING, 8, - PropModeAppend, (unsigned char *)buf, strlen(buf)); - - XmuSnprintf(buf, sizeof(buf), "%s,%d", id, dmxScreen->index); - XChangeProperty(dpy, win, atom, XA_STRING, 8, - PropModeAppend, (unsigned char *)buf, strlen(buf)); -} +/* + * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: + * Rickard E. (Rik) Faith + * + */ + +/** \file + * + * It is possible for one of the DMX "backend displays" to actually be + * smaller than the dimensions of the backend X server. Therefore, it + * is possible for more than one of the DMX "backend displays" to be + * physically located on the same backend X server. This situation must + * be detected so that cursor motion can be handled in an expected + * fashion. + * + * We could analyze the names used for the DMX "backend displays" (e.g., + * the names passed to the -display command-line parameter), but there + * are many possible names for a single X display, and failing to detect + * sameness leads to very unexpected results. Therefore, whenever the + * DMX server opens a window on a backend X server, a property value is + * queried and set on that backend to detect when another window is + * already open on that server. + * + * Further, it is possible that two different DMX server instantiations + * both have windows on the same physical backend X server. This case + * is also detected so that pointer input is not taken from that + * particular backend X server. + * + * The routines in this file handle the property management. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include "dmxprop.h" +#include "dmxlog.h" + +/** Holds the window id of all DMX windows on the backend X server. */ +#define DMX_ATOMNAME "DMX_NAME" + +/** The identification string of this DMX server */ +#define DMX_IDENT "Xdmx" + +extern char *display; + +static int dmxPropertyErrorHandler(Display *dpy, XErrorEvent *ev) +{ + return 0; +} + +static const unsigned char *dmxPropertyIdentifier(void) +{ + /* RATS: These buffers are only used in + * length-limited calls. */ + char hostname[256]; + static char buf[128]; + static int initialized = 0; + + if (initialized++) return (unsigned char *)buf; + + XmuGetHostname(hostname, sizeof(hostname)); + XmuSnprintf(buf, sizeof(buf), "%s:%s:%s", DMX_IDENT, hostname, display); + return (unsigned char *)buf; +} + +/** Starting with the \a start screen, iterate over all of the screens + * on the same physical X server as \a start, calling \a f with the + * screen and the \a closure. (The common case is that \a start is the + * only DMX window on the backend X server.) */ +void *dmxPropertyIterate(DMXScreenInfo *start, + void *(*f)(DMXScreenInfo *dmxScreen, void *), + void *closure) +{ + DMXScreenInfo *pt; + + if (!start->next) { + if (!start->beDisplay) return NULL; + return f(start, closure); + } + + for (pt = start->next; /* condition at end of loop */; pt = pt->next) { + void *retval; + /* beDisplay ban be NULL if a screen was detached */ + dmxLog(dmxDebug, "pt = %p\n", pt); + dmxLog(dmxDebug, "pt->beDisplay = %p\n", pt->beDisplay); + if (pt->beDisplay && (retval = f(pt, closure))) return retval; + if (pt == start) break; + } + return NULL; +} + +/** Returns 0 if this is the only Xdmx session on the display; 1 + * otherwise. */ +static int dmxPropertyCheckOtherServers(DMXScreenInfo *dmxScreen, Atom atom) +{ + Display *dpy = dmxScreen->beDisplay; + XTextProperty tp; + XTextProperty tproot; + const char *pt; + int retcode = 0; + char **list = NULL; + int count = 0; + int i; + int (*dmxOldHandler)(Display *, XErrorEvent *); + + if (!dpy) + return 0; + + if (!XGetTextProperty(dpy, RootWindow(dpy,0), &tproot, atom) + || !tproot.nitems) return 0; + + /* Ignore BadWindow errors for this + * routine because the window id stored + * in the property might be old */ + dmxOldHandler = XSetErrorHandler(dmxPropertyErrorHandler); + for (pt = (const char *)tproot.value; pt && *pt; pt = pt ? pt + 1 : NULL) { + if ((pt = strchr(pt, ','))) { + Window win = strtol(pt+1, NULL, 10); + if (XGetTextProperty(dpy, win, &tp, atom) && tp.nitems) { + if (!strncmp((char *)tp.value, DMX_IDENT, strlen(DMX_IDENT))) { + int flag = 0; + for (i = 0; i < count; i++) + if (!strcmp(list[i], (char *)tp.value)) { + ++flag; + break; + } + if (flag) continue; + ++retcode; + dmxLogOutputWarning(dmxScreen, + "%s also running on %s\n", + tp.value, dmxScreen->name); + list = realloc(list, ++count * sizeof(*list)); + list[count-1] = malloc(tp.nitems + 2); + strncpy(list[count-1], (char *)tp.value, tp.nitems + 1); + } + XFree(tp.value); + } + } + } + XSetErrorHandler(dmxOldHandler); + + for (i = 0; i < count; i++) free(list[i]); + free(list); + XFree(tproot.value); + if (!retcode) + dmxLogOutput(dmxScreen, "No Xdmx server running on backend\n"); + return retcode; +} + +/** Returns NULL if this is the only Xdmx window on the display. + * Otherwise, returns a pointer to the dmxScreen of the other windows on + * the display. */ +static DMXScreenInfo *dmxPropertyCheckOtherWindows(DMXScreenInfo *dmxScreen, + Atom atom) +{ + Display *dpy = dmxScreen->beDisplay; + const unsigned char *id = dmxPropertyIdentifier(); + XTextProperty tproot; + XTextProperty tp; + const char *pt; + int (*dmxOldHandler)(Display *, XErrorEvent *); + + if (!dpy) + return NULL; + + if (!XGetTextProperty(dpy, RootWindow(dpy,0), &tproot, atom) + || !tproot.nitems) return 0; + + /* Ignore BadWindow errors for this + * routine because the window id stored + * in the property might be old */ + dmxOldHandler = XSetErrorHandler(dmxPropertyErrorHandler); + for (pt = (const char *)tproot.value; pt && *pt; pt = pt ? pt + 1 : NULL) { + if ((pt = strchr(pt, ','))) { + Window win = strtol(pt+1, NULL, 10); + if (XGetTextProperty(dpy, win, &tp, atom) && tp.nitems) { + dmxLog(dmxDebug,"On %s/%lu: %s\n", + dmxScreen->name, win, tp.value); + if (!strncmp((char *)tp.value, (char *)id, + strlen((char *)id))) { + int idx; + + if (!(pt = strchr((char *)tp.value, ','))) continue; + idx = strtol(pt+1, NULL, 10); + if (idx < 0 || idx >= dmxNumScreens) continue; + if (dmxScreens[idx].scrnWin != win) continue; + XSetErrorHandler(dmxOldHandler); + return &dmxScreens[idx]; + } + XFree(tp.value); + } + } + } + XSetErrorHandler(dmxOldHandler); + XFree(tproot.value); + return 0; +} + +/** Returns 0 if this is the only Xdmx session on the display; 1 + * otherwise. */ +int dmxPropertyDisplay(DMXScreenInfo *dmxScreen) +{ + Atom atom; + const unsigned char *id = dmxPropertyIdentifier(); + Display *dpy = dmxScreen->beDisplay; + + if (!dpy) + return 0; + + atom = XInternAtom(dpy, DMX_ATOMNAME, False); + if (dmxPropertyCheckOtherServers(dmxScreen, atom)) { + dmxScreen->shared = 1; + return 1; + } + XChangeProperty(dpy, RootWindow(dpy,0), atom, XA_STRING, 8, + PropModeReplace, id, strlen((char *)id)); + return 0; +} + +/** Returns 1 if the dmxScreen and the display in \a name are on the + * same display, or 0 otherwise. We can't just compare the display + * names because there can be multiple synonyms for the same display, + * some of which cannot be determined without accessing the display + * itself (e.g., domain aliases or machines with multiple NICs). */ +int dmxPropertySameDisplay(DMXScreenInfo *dmxScreen, const char *name) +{ + Display *dpy0 = dmxScreen->beDisplay; + Atom atom0; + XTextProperty tp0; + Display *dpy1 = NULL; + Atom atom1; + XTextProperty tp1; + int retval = 0; + + if (!dpy0) + return 0; + + tp0.nitems = 0; + tp1.nitems = 0; + + if ((atom0 = XInternAtom(dpy0, DMX_ATOMNAME, True)) == None) { + dmxLog(dmxWarning, "No atom on %s\n", dmxScreen->name); + return 0; + } + if (!XGetTextProperty(dpy0, RootWindow(dpy0,0), &tp0, atom0) + || !tp0.nitems) { + dmxLog(dmxWarning, "No text property on %s\n", dmxScreen->name); + return 0; + } + + if (!(dpy1 = XOpenDisplay(name))) { + dmxLog(dmxWarning, "Cannot open %s\n", name); + goto cleanup; + } + atom1 = XInternAtom(dpy1, DMX_ATOMNAME, True); + if (atom1 == None) { + dmxLog(dmxDebug, "No atom on %s\n", name); + goto cleanup; + } + if (!XGetTextProperty(dpy1, RootWindow(dpy1,0), &tp1, atom1) + || !tp1.nitems) { + dmxLog(dmxDebug, "No text property on %s\n", name); + goto cleanup; + } + if (!strcmp((char *)tp0.value, (char *)tp1.value)) retval = 1; + + cleanup: + if (tp0.nitems) XFree(tp0.value); + if (tp1.nitems) XFree(tp1.value); + if (dpy1) XCloseDisplay(dpy1); + return retval; +} + +/** Prints a log message if \a dmxScreen is on the same backend X server + * as some other DMX backend (output) screen. Modifies the property + * (#DMX_ATOMNAME) on the backend X server to reflect the creation of \a + * dmxScreen. + * + * The root window of the backend X server holds a list of window ids + * for all DMX windows (on this DMX server or some other DMX server). + * + * This list can then be iterated, and the property for each window can + * be examined. This property contains the following tuple (no quotes): + * + * "#DMX_IDENT::," + */ +void dmxPropertyWindow(DMXScreenInfo *dmxScreen) +{ + Atom atom; + const unsigned char *id = dmxPropertyIdentifier(); + Display *dpy = dmxScreen->beDisplay; + Window win = dmxScreen->scrnWin; + DMXScreenInfo *other; + char buf[128]; /* RATS: only used with XmuSnprintf */ + + if (!dpy) + return; /* FIXME: What should be done here if Xdmx is started + * with this screen initially detached? + */ + + atom = XInternAtom(dpy, DMX_ATOMNAME, False); + if ((other = dmxPropertyCheckOtherWindows(dmxScreen, atom))) { + DMXScreenInfo *tmp = dmxScreen->next; + dmxScreen->next = (other->next ? other->next : other); + other->next = (tmp ? tmp : dmxScreen); + dmxLog(dmxDebug, "%d/%s/%lu and %d/%s/%lu are on the same backend\n", + dmxScreen->index, dmxScreen->name, dmxScreen->scrnWin, + other->index, other->name, other->scrnWin); + } + + XmuSnprintf(buf, sizeof(buf), ".%d,%lu", dmxScreen->index, + (long unsigned)win); + XChangeProperty(dpy, RootWindow(dpy,0), atom, XA_STRING, 8, + PropModeAppend, (unsigned char *)buf, strlen(buf)); + + XmuSnprintf(buf, sizeof(buf), "%s,%d", id, dmxScreen->index); + XChangeProperty(dpy, win, atom, XA_STRING, 8, + PropModeAppend, (unsigned char *)buf, strlen(buf)); +} diff --git a/xorg-server/hw/dmx/dmxscrinit.c b/xorg-server/hw/dmx/dmxscrinit.c index c1beb9ba5..edb14a23a 100644 --- a/xorg-server/hw/dmx/dmxscrinit.c +++ b/xorg-server/hw/dmx/dmxscrinit.c @@ -1,524 +1,524 @@ -/* - * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 - * David H. Dawes - * - */ - -/** \file - * This file provides support for screen initialization. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include "dmx.h" -#include "dmxsync.h" -#include "dmxshadow.h" -#include "dmxscrinit.h" -#include "dmxcursor.h" -#include "dmxgc.h" -#include "dmxgcops.h" -#include "dmxwindow.h" -#include "dmxpixmap.h" -#include "dmxfont.h" -#include "dmxcmap.h" -#include "dmxprop.h" -#include "dmxdpms.h" - -#include "dmxpict.h" - -#include "fb.h" -#include "mipointer.h" -#include "micmap.h" - -extern Bool dmxCloseScreen(int idx, ScreenPtr pScreen); -static Bool dmxSaveScreen(ScreenPtr pScreen, int what); - -static unsigned long dmxGeneration; -static unsigned long *dmxCursorGeneration; - -static int dmxGCPrivateKeyIndex; -DevPrivateKey dmxGCPrivateKey = &dmxGCPrivateKeyIndex; /**< Private index for GCs */ -static int dmxWinPrivateKeyIndex; -DevPrivateKey dmxWinPrivateKey = &dmxWinPrivateKeyIndex; /**< Private index for Windows */ -static int dmxPixPrivateKeyIndex; -DevPrivateKey dmxPixPrivateKey = &dmxPixPrivateKeyIndex; /**< Private index for Pixmaps */ -int dmxFontPrivateIndex; /**< Private index for Fonts */ -static int dmxScreenPrivateKeyIndex; -DevPrivateKey dmxScreenPrivateKey = &dmxScreenPrivateKeyIndex; /**< Private index for Screens */ -static int dmxColormapPrivateKeyIndex; -DevPrivateKey dmxColormapPrivateKey = &dmxColormapPrivateKeyIndex; /**< Private index for Colormaps */ -static int dmxPictPrivateKeyIndex; -DevPrivateKey dmxPictPrivateKey = &dmxPictPrivateKeyIndex; /**< Private index for Picts */ -static int dmxGlyphSetPrivateKeyIndex; -DevPrivateKey dmxGlyphSetPrivateKey = &dmxGlyphSetPrivateKeyIndex; /**< Private index for GlyphSets */ - -/** Initialize the parts of screen \a idx that require access to the - * back-end server. */ -void dmxBEScreenInit(int idx, ScreenPtr pScreen) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[idx]; - XSetWindowAttributes attribs; - XGCValues gcvals; - unsigned long mask; - int i, j; - - /* FIXME: The dmxScreenInit() code currently assumes that it will - * not be called if the Xdmx server is started with this screen - * detached -- i.e., it assumes that dmxScreen->beDisplay is always - * valid. This is not necessarily a valid assumption when full - * addition/removal of screens is implemented, but when this code is - * broken out for screen reattachment, then we will reevaluate this - * assumption. - */ - - pScreen->mmWidth = DisplayWidthMM(dmxScreen->beDisplay, - DefaultScreen(dmxScreen->beDisplay)); - pScreen->mmHeight = DisplayHeightMM(dmxScreen->beDisplay, - DefaultScreen(dmxScreen->beDisplay)); - - pScreen->whitePixel = dmxScreen->beWhitePixel; - pScreen->blackPixel = dmxScreen->beBlackPixel; - - /* Handle screen savers and DPMS on the backend */ - dmxDPMSInit(dmxScreen); - - /* Create root window for screen */ - mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect; - attribs.background_pixel = dmxScreen->beBlackPixel; - attribs.event_mask = (KeyPressMask - | KeyReleaseMask - | ButtonPressMask - | ButtonReleaseMask - | EnterWindowMask - | LeaveWindowMask - | PointerMotionMask - | KeymapStateMask - | FocusChangeMask); - attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex]; - attribs.override_redirect = True; - - dmxScreen->scrnWin = - XCreateWindow(dmxScreen->beDisplay, - DefaultRootWindow(dmxScreen->beDisplay), - dmxScreen->scrnX, - dmxScreen->scrnY, - dmxScreen->scrnWidth, - dmxScreen->scrnHeight, - 0, - pScreen->rootDepth, - InputOutput, - dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, - mask, - &attribs); - dmxPropertyWindow(dmxScreen); - - /* - * This turns off the cursor by defining a cursor with no visible - * components. - */ - { - char noCursorData[] = {0, 0, 0, 0, - 0, 0, 0, 0}; - Pixmap pixmap; - XColor color, tmp; - - pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin, - noCursorData, 8, 8); - XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0], - "black", &color, &tmp); - dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay, - pixmap, pixmap, - &color, &color, 0, 0); - XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin, - dmxScreen->noCursor); - - XFreePixmap(dmxScreen->beDisplay, pixmap); - } - - XMapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); - - if (dmxShadowFB) { - mask = (GCFunction - | GCPlaneMask - | GCClipMask); - gcvals.function = GXcopy; - gcvals.plane_mask = AllPlanes; - gcvals.clip_mask = None; - - dmxScreen->shadowGC = XCreateGC(dmxScreen->beDisplay, - dmxScreen->scrnWin, - mask, &gcvals); - - dmxScreen->shadowFBImage = - XCreateImage(dmxScreen->beDisplay, - dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, - dmxScreen->beDepth, - ZPixmap, - 0, - (char *)dmxScreen->shadow, - dmxScreen->scrnWidth, dmxScreen->scrnHeight, - dmxScreen->beBPP, - PixmapBytePad(dmxScreen->scrnWidth, - dmxScreen->beBPP)); - } else { - /* Create default drawables (used during GC creation) */ - for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) - for (j = 0; j < dmxScreen->beNumDepths; j++) - if ((dmxScreen->bePixmapFormats[i].depth == 1) || - (dmxScreen->bePixmapFormats[i].depth == - dmxScreen->beDepths[j])) { - dmxScreen->scrnDefDrawables[i] = (Drawable) - XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin, - 1, 1, dmxScreen->bePixmapFormats[i].depth); - break; - } - } -} - -/** Initialize screen number \a idx. */ -Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[]) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[idx]; - int i, j; - - if (dmxGeneration != serverGeneration) { - /* Allocate font private index */ - dmxFontPrivateIndex = AllocateFontPrivateIndex(); - if (dmxFontPrivateIndex == -1) - return FALSE; - - dmxGeneration = serverGeneration; - } - - if (dmxShadowFB) { - dmxScreen->shadow = shadowAlloc(dmxScreen->scrnWidth, - dmxScreen->scrnHeight, - dmxScreen->beBPP); - } else { - if (!dmxInitGC(pScreen)) return FALSE; - if (!dmxInitWindow(pScreen)) return FALSE; - if (!dmxInitPixmap(pScreen)) return FALSE; - } - - /* - * Initalise the visual types. miSetVisualTypesAndMasks() requires - * that all of the types for each depth be collected together. It's - * intended for slightly different usage to what we would like here. - * Maybe a miAddVisualTypeAndMask() function will be added to make - * things easier here. - */ - for (i = 0; i < dmxScreen->beNumDepths; i++) { - int depth; - int visuals = 0; - int bitsPerRgb = 0; - int preferredClass = -1; - Pixel redMask = 0; - Pixel greenMask = 0; - Pixel blueMask = 0; - - depth = dmxScreen->beDepths[i]; - for (j = 0; j < dmxScreen->beNumVisuals; j++) { - XVisualInfo *vi; - - vi = &dmxScreen->beVisuals[j]; - if (vi->depth == depth) { - /* Assume the masks are all the same. */ - visuals |= (1 << vi->class); - bitsPerRgb = vi->bits_per_rgb; - redMask = vi->red_mask; - greenMask = vi->green_mask; - blueMask = vi->blue_mask; - if (j == dmxScreen->beDefVisualIndex) { - preferredClass = vi->class; - } - } - } - miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb, preferredClass, - redMask, greenMask, blueMask); - } - - fbScreenInit(pScreen, - dmxShadowFB ? dmxScreen->shadow : NULL, - dmxScreen->scrnWidth, - dmxScreen->scrnHeight, - dmxScreen->beXDPI, - dmxScreen->beXDPI, - dmxScreen->scrnWidth, - dmxScreen->beBPP); - (void)dmxPictureInit(pScreen, 0, 0); - - /* Not yet... */ - pScreen->GetWindowPixmap = NULL; - pScreen->SetWindowPixmap = NULL; - - if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL)) - return FALSE; - - miInitializeBackingStore(pScreen); - - if (dmxShadowFB) { - miDCInitialize(pScreen, &dmxPointerCursorFuncs); - } else { - MAXSCREENSALLOC(dmxCursorGeneration); - if (dmxCursorGeneration[idx] != serverGeneration) { - if (!(miPointerInitialize(pScreen, - &dmxPointerSpriteFuncs, - &dmxPointerCursorFuncs, - FALSE))) - return FALSE; - - dmxCursorGeneration[idx] = serverGeneration; - } - } - - DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen); - DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen); - - dmxBEScreenInit(idx, pScreen); - - if (!dmxShadowFB) { - /* Wrap GC functions */ - DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen); - - /* Wrap Window functions */ - DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen); - DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen); - DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen); - DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen, - pScreen); - DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen); - DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen); - DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen); - DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen); - DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen); - - DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen); - DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen); - - DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen); - - /* Wrap Image functions */ - DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen); - DMX_WRAP(GetSpans, dmxGetSpans, dmxScreen, pScreen); - - /* Wrap Pixmap functions */ - DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen); - DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen); - DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen); - - /* Wrap Font functions */ - DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen); - DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen); - - /* Wrap Colormap functions */ - DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen); - DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen); - DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen); - DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen); - - /* Wrap Shape functions */ - DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen); - } - - if (!dmxCreateDefColormap(pScreen)) - return FALSE; - - return TRUE; -} - -/** Close the \a pScreen resources on the back-end server. */ -void dmxBECloseScreen(ScreenPtr pScreen) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - int i; - - /* Restore the back-end screen-saver and DPMS state. */ - dmxDPMSTerm(dmxScreen); - - /* Free the screen resources */ - - XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor); - dmxScreen->noCursor = (Cursor)0; - - XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); - XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); - dmxScreen->scrnWin = (Window)0; - - if (dmxShadowFB) { - /* Free the shadow GC and image assocated with the back-end server */ - XFreeGC(dmxScreen->beDisplay, dmxScreen->shadowGC); - dmxScreen->shadowGC = NULL; - XFree(dmxScreen->shadowFBImage); - dmxScreen->shadowFBImage = NULL; - } else { - /* Free the default drawables */ - for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { - if (dmxScreen->scrnDefDrawables[i]) { - XFreePixmap(dmxScreen->beDisplay, - dmxScreen->scrnDefDrawables[i]); - dmxScreen->scrnDefDrawables[i] = (Drawable)0; - } - } - } - - /* Free resources allocated during initialization (in dmxinit.c) */ - for (i = 0; i < dmxScreen->beNumDefColormaps; i++) - XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]); - xfree(dmxScreen->beDefColormaps); - dmxScreen->beDefColormaps = NULL; - -#if 0 - /* Do not free visuals, depths and pixmap formats here. Free them - * in dmxCloseScreen() instead -- see comment below. */ - XFree(dmxScreen->beVisuals); - dmxScreen->beVisuals = NULL; - - XFree(dmxScreen->beDepths); - dmxScreen->beDepths = NULL; - - XFree(dmxScreen->bePixmapFormats); - dmxScreen->bePixmapFormats = NULL; -#endif - -#ifdef GLXEXT - if (dmxScreen->glxVisuals) { - XFree(dmxScreen->glxVisuals); - dmxScreen->glxVisuals = NULL; - dmxScreen->numGlxVisuals = 0; - } -#endif - - /* Close display */ - XCloseDisplay(dmxScreen->beDisplay); - dmxScreen->beDisplay = NULL; -} - -/** Close screen number \a idx. */ -Bool dmxCloseScreen(int idx, ScreenPtr pScreen) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[idx]; - - /* Reset the proc vectors */ - if (idx == 0) { - dmxResetRender(); - dmxResetFonts(); - } - - if (dmxShadowFB) { - /* Free the shadow framebuffer */ - xfree(dmxScreen->shadow); - } else { - - /* Unwrap Shape functions */ - DMX_UNWRAP(SetShape, dmxScreen, pScreen); - - /* Unwrap the pScreen functions */ - DMX_UNWRAP(CreateGC, dmxScreen, pScreen); - - DMX_UNWRAP(CreateWindow, dmxScreen, pScreen); - DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen); - DMX_UNWRAP(PositionWindow, dmxScreen, pScreen); - DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen); - DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen); - DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen); - DMX_UNWRAP(RestackWindow, dmxScreen, pScreen); - DMX_UNWRAP(WindowExposures, dmxScreen, pScreen); - DMX_UNWRAP(CopyWindow, dmxScreen, pScreen); - - DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen); - DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen); - - DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen); - - DMX_UNWRAP(GetImage, dmxScreen, pScreen); - DMX_UNWRAP(GetSpans, dmxScreen, pScreen); - - DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen); - DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen); - DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen); - - DMX_UNWRAP(RealizeFont, dmxScreen, pScreen); - DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen); - - DMX_UNWRAP(CreateColormap, dmxScreen, pScreen); - DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen); - DMX_UNWRAP(InstallColormap, dmxScreen, pScreen); - DMX_UNWRAP(StoreColors, dmxScreen, pScreen); - } - - DMX_UNWRAP(SaveScreen, dmxScreen, pScreen); - - if (dmxScreen->beDisplay) { - dmxBECloseScreen(pScreen); - -#if 1 - /* Free visuals, depths and pixmap formats here so that they - * won't be freed when a screen is detached, thereby allowing - * the screen to be reattached to be compared to the one - * previously removed. - */ - XFree(dmxScreen->beVisuals); - dmxScreen->beVisuals = NULL; - - XFree(dmxScreen->beDepths); - dmxScreen->beDepths = NULL; - - XFree(dmxScreen->bePixmapFormats); - dmxScreen->bePixmapFormats = NULL; -#endif - } - - DMX_UNWRAP(CloseScreen, dmxScreen, pScreen); - return pScreen->CloseScreen(idx, pScreen); -} - -static Bool dmxSaveScreen(ScreenPtr pScreen, int what) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - - if (dmxScreen->beDisplay) { - switch (what) { - case SCREEN_SAVER_OFF: - case SCREEN_SAVER_FORCER: - XResetScreenSaver(dmxScreen->beDisplay); - dmxSync(dmxScreen, FALSE); - break; - case SCREEN_SAVER_ON: - case SCREEN_SAVER_CYCLE: - XActivateScreenSaver(dmxScreen->beDisplay); - dmxSync(dmxScreen, FALSE); - break; - } - } - - return TRUE; -} +/* + * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 + * David H. Dawes + * + */ + +/** \file + * This file provides support for screen initialization. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include "dmxsync.h" +#include "dmxshadow.h" +#include "dmxscrinit.h" +#include "dmxcursor.h" +#include "dmxgc.h" +#include "dmxgcops.h" +#include "dmxwindow.h" +#include "dmxpixmap.h" +#include "dmxfont.h" +#include "dmxcmap.h" +#include "dmxprop.h" +#include "dmxdpms.h" + +#include "dmxpict.h" + +#include "fb.h" +#include "mipointer.h" +#include "micmap.h" + +extern Bool dmxCloseScreen(int idx, ScreenPtr pScreen); +static Bool dmxSaveScreen(ScreenPtr pScreen, int what); + +static unsigned long dmxGeneration; +static unsigned long *dmxCursorGeneration; + +static int dmxGCPrivateKeyIndex; +DevPrivateKey dmxGCPrivateKey = &dmxGCPrivateKeyIndex; /**< Private index for GCs */ +static int dmxWinPrivateKeyIndex; +DevPrivateKey dmxWinPrivateKey = &dmxWinPrivateKeyIndex; /**< Private index for Windows */ +static int dmxPixPrivateKeyIndex; +DevPrivateKey dmxPixPrivateKey = &dmxPixPrivateKeyIndex; /**< Private index for Pixmaps */ +int dmxFontPrivateIndex; /**< Private index for Fonts */ +static int dmxScreenPrivateKeyIndex; +DevPrivateKey dmxScreenPrivateKey = &dmxScreenPrivateKeyIndex; /**< Private index for Screens */ +static int dmxColormapPrivateKeyIndex; +DevPrivateKey dmxColormapPrivateKey = &dmxColormapPrivateKeyIndex; /**< Private index for Colormaps */ +static int dmxPictPrivateKeyIndex; +DevPrivateKey dmxPictPrivateKey = &dmxPictPrivateKeyIndex; /**< Private index for Picts */ +static int dmxGlyphSetPrivateKeyIndex; +DevPrivateKey dmxGlyphSetPrivateKey = &dmxGlyphSetPrivateKeyIndex; /**< Private index for GlyphSets */ + +/** Initialize the parts of screen \a idx that require access to the + * back-end server. */ +void dmxBEScreenInit(int idx, ScreenPtr pScreen) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[idx]; + XSetWindowAttributes attribs; + XGCValues gcvals; + unsigned long mask; + int i, j; + + /* FIXME: The dmxScreenInit() code currently assumes that it will + * not be called if the Xdmx server is started with this screen + * detached -- i.e., it assumes that dmxScreen->beDisplay is always + * valid. This is not necessarily a valid assumption when full + * addition/removal of screens is implemented, but when this code is + * broken out for screen reattachment, then we will reevaluate this + * assumption. + */ + + pScreen->mmWidth = DisplayWidthMM(dmxScreen->beDisplay, + DefaultScreen(dmxScreen->beDisplay)); + pScreen->mmHeight = DisplayHeightMM(dmxScreen->beDisplay, + DefaultScreen(dmxScreen->beDisplay)); + + pScreen->whitePixel = dmxScreen->beWhitePixel; + pScreen->blackPixel = dmxScreen->beBlackPixel; + + /* Handle screen savers and DPMS on the backend */ + dmxDPMSInit(dmxScreen); + + /* Create root window for screen */ + mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect; + attribs.background_pixel = dmxScreen->beBlackPixel; + attribs.event_mask = (KeyPressMask + | KeyReleaseMask + | ButtonPressMask + | ButtonReleaseMask + | EnterWindowMask + | LeaveWindowMask + | PointerMotionMask + | KeymapStateMask + | FocusChangeMask); + attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex]; + attribs.override_redirect = True; + + dmxScreen->scrnWin = + XCreateWindow(dmxScreen->beDisplay, + DefaultRootWindow(dmxScreen->beDisplay), + dmxScreen->scrnX, + dmxScreen->scrnY, + dmxScreen->scrnWidth, + dmxScreen->scrnHeight, + 0, + pScreen->rootDepth, + InputOutput, + dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, + mask, + &attribs); + dmxPropertyWindow(dmxScreen); + + /* + * This turns off the cursor by defining a cursor with no visible + * components. + */ + { + char noCursorData[] = {0, 0, 0, 0, + 0, 0, 0, 0}; + Pixmap pixmap; + XColor color, tmp; + + pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin, + noCursorData, 8, 8); + XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0], + "black", &color, &tmp); + dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay, + pixmap, pixmap, + &color, &color, 0, 0); + XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin, + dmxScreen->noCursor); + + XFreePixmap(dmxScreen->beDisplay, pixmap); + } + + XMapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); + + if (dmxShadowFB) { + mask = (GCFunction + | GCPlaneMask + | GCClipMask); + gcvals.function = GXcopy; + gcvals.plane_mask = AllPlanes; + gcvals.clip_mask = None; + + dmxScreen->shadowGC = XCreateGC(dmxScreen->beDisplay, + dmxScreen->scrnWin, + mask, &gcvals); + + dmxScreen->shadowFBImage = + XCreateImage(dmxScreen->beDisplay, + dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, + dmxScreen->beDepth, + ZPixmap, + 0, + (char *)dmxScreen->shadow, + dmxScreen->scrnWidth, dmxScreen->scrnHeight, + dmxScreen->beBPP, + PixmapBytePad(dmxScreen->scrnWidth, + dmxScreen->beBPP)); + } else { + /* Create default drawables (used during GC creation) */ + for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) + for (j = 0; j < dmxScreen->beNumDepths; j++) + if ((dmxScreen->bePixmapFormats[i].depth == 1) || + (dmxScreen->bePixmapFormats[i].depth == + dmxScreen->beDepths[j])) { + dmxScreen->scrnDefDrawables[i] = (Drawable) + XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin, + 1, 1, dmxScreen->bePixmapFormats[i].depth); + break; + } + } +} + +/** Initialize screen number \a idx. */ +Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[]) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[idx]; + int i, j; + + if (dmxGeneration != serverGeneration) { + /* Allocate font private index */ + dmxFontPrivateIndex = AllocateFontPrivateIndex(); + if (dmxFontPrivateIndex == -1) + return FALSE; + + dmxGeneration = serverGeneration; + } + + if (dmxShadowFB) { + dmxScreen->shadow = shadowAlloc(dmxScreen->scrnWidth, + dmxScreen->scrnHeight, + dmxScreen->beBPP); + } else { + if (!dmxInitGC(pScreen)) return FALSE; + if (!dmxInitWindow(pScreen)) return FALSE; + if (!dmxInitPixmap(pScreen)) return FALSE; + } + + /* + * Initalise the visual types. miSetVisualTypesAndMasks() requires + * that all of the types for each depth be collected together. It's + * intended for slightly different usage to what we would like here. + * Maybe a miAddVisualTypeAndMask() function will be added to make + * things easier here. + */ + for (i = 0; i < dmxScreen->beNumDepths; i++) { + int depth; + int visuals = 0; + int bitsPerRgb = 0; + int preferredClass = -1; + Pixel redMask = 0; + Pixel greenMask = 0; + Pixel blueMask = 0; + + depth = dmxScreen->beDepths[i]; + for (j = 0; j < dmxScreen->beNumVisuals; j++) { + XVisualInfo *vi; + + vi = &dmxScreen->beVisuals[j]; + if (vi->depth == depth) { + /* Assume the masks are all the same. */ + visuals |= (1 << vi->class); + bitsPerRgb = vi->bits_per_rgb; + redMask = vi->red_mask; + greenMask = vi->green_mask; + blueMask = vi->blue_mask; + if (j == dmxScreen->beDefVisualIndex) { + preferredClass = vi->class; + } + } + } + miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb, preferredClass, + redMask, greenMask, blueMask); + } + + fbScreenInit(pScreen, + dmxShadowFB ? dmxScreen->shadow : NULL, + dmxScreen->scrnWidth, + dmxScreen->scrnHeight, + dmxScreen->beXDPI, + dmxScreen->beXDPI, + dmxScreen->scrnWidth, + dmxScreen->beBPP); + (void)dmxPictureInit(pScreen, 0, 0); + + /* Not yet... */ + pScreen->GetWindowPixmap = NULL; + pScreen->SetWindowPixmap = NULL; + + if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL)) + return FALSE; + + miInitializeBackingStore(pScreen); + + if (dmxShadowFB) { + miDCInitialize(pScreen, &dmxPointerCursorFuncs); + } else { + MAXSCREENSALLOC(dmxCursorGeneration); + if (dmxCursorGeneration[idx] != serverGeneration) { + if (!(miPointerInitialize(pScreen, + &dmxPointerSpriteFuncs, + &dmxPointerCursorFuncs, + FALSE))) + return FALSE; + + dmxCursorGeneration[idx] = serverGeneration; + } + } + + DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen); + DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen); + + dmxBEScreenInit(idx, pScreen); + + if (!dmxShadowFB) { + /* Wrap GC functions */ + DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen); + + /* Wrap Window functions */ + DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen); + DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen); + DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen); + DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen, + pScreen); + DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen); + DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen); + DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen); + DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen); + DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen); + + DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen); + DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen); + + DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen); + + /* Wrap Image functions */ + DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen); + DMX_WRAP(GetSpans, dmxGetSpans, dmxScreen, pScreen); + + /* Wrap Pixmap functions */ + DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen); + DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen); + DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen); + + /* Wrap Font functions */ + DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen); + DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen); + + /* Wrap Colormap functions */ + DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen); + DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen); + DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen); + DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen); + + /* Wrap Shape functions */ + DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen); + } + + if (!dmxCreateDefColormap(pScreen)) + return FALSE; + + return TRUE; +} + +/** Close the \a pScreen resources on the back-end server. */ +void dmxBECloseScreen(ScreenPtr pScreen) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + int i; + + /* Restore the back-end screen-saver and DPMS state. */ + dmxDPMSTerm(dmxScreen); + + /* Free the screen resources */ + + XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor); + dmxScreen->noCursor = (Cursor)0; + + XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); + XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); + dmxScreen->scrnWin = (Window)0; + + if (dmxShadowFB) { + /* Free the shadow GC and image assocated with the back-end server */ + XFreeGC(dmxScreen->beDisplay, dmxScreen->shadowGC); + dmxScreen->shadowGC = NULL; + XFree(dmxScreen->shadowFBImage); + dmxScreen->shadowFBImage = NULL; + } else { + /* Free the default drawables */ + for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { + if (dmxScreen->scrnDefDrawables[i]) { + XFreePixmap(dmxScreen->beDisplay, + dmxScreen->scrnDefDrawables[i]); + dmxScreen->scrnDefDrawables[i] = (Drawable)0; + } + } + } + + /* Free resources allocated during initialization (in dmxinit.c) */ + for (i = 0; i < dmxScreen->beNumDefColormaps; i++) + XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]); + free(dmxScreen->beDefColormaps); + dmxScreen->beDefColormaps = NULL; + +#if 0 + /* Do not free visuals, depths and pixmap formats here. Free them + * in dmxCloseScreen() instead -- see comment below. */ + XFree(dmxScreen->beVisuals); + dmxScreen->beVisuals = NULL; + + XFree(dmxScreen->beDepths); + dmxScreen->beDepths = NULL; + + XFree(dmxScreen->bePixmapFormats); + dmxScreen->bePixmapFormats = NULL; +#endif + +#ifdef GLXEXT + if (dmxScreen->glxVisuals) { + XFree(dmxScreen->glxVisuals); + dmxScreen->glxVisuals = NULL; + dmxScreen->numGlxVisuals = 0; + } +#endif + + /* Close display */ + XCloseDisplay(dmxScreen->beDisplay); + dmxScreen->beDisplay = NULL; +} + +/** Close screen number \a idx. */ +Bool dmxCloseScreen(int idx, ScreenPtr pScreen) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[idx]; + + /* Reset the proc vectors */ + if (idx == 0) { + dmxResetRender(); + dmxResetFonts(); + } + + if (dmxShadowFB) { + /* Free the shadow framebuffer */ + free(dmxScreen->shadow); + } else { + + /* Unwrap Shape functions */ + DMX_UNWRAP(SetShape, dmxScreen, pScreen); + + /* Unwrap the pScreen functions */ + DMX_UNWRAP(CreateGC, dmxScreen, pScreen); + + DMX_UNWRAP(CreateWindow, dmxScreen, pScreen); + DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen); + DMX_UNWRAP(PositionWindow, dmxScreen, pScreen); + DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen); + DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen); + DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen); + DMX_UNWRAP(RestackWindow, dmxScreen, pScreen); + DMX_UNWRAP(WindowExposures, dmxScreen, pScreen); + DMX_UNWRAP(CopyWindow, dmxScreen, pScreen); + + DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen); + DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen); + + DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen); + + DMX_UNWRAP(GetImage, dmxScreen, pScreen); + DMX_UNWRAP(GetSpans, dmxScreen, pScreen); + + DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen); + DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen); + DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen); + + DMX_UNWRAP(RealizeFont, dmxScreen, pScreen); + DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen); + + DMX_UNWRAP(CreateColormap, dmxScreen, pScreen); + DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen); + DMX_UNWRAP(InstallColormap, dmxScreen, pScreen); + DMX_UNWRAP(StoreColors, dmxScreen, pScreen); + } + + DMX_UNWRAP(SaveScreen, dmxScreen, pScreen); + + if (dmxScreen->beDisplay) { + dmxBECloseScreen(pScreen); + +#if 1 + /* Free visuals, depths and pixmap formats here so that they + * won't be freed when a screen is detached, thereby allowing + * the screen to be reattached to be compared to the one + * previously removed. + */ + XFree(dmxScreen->beVisuals); + dmxScreen->beVisuals = NULL; + + XFree(dmxScreen->beDepths); + dmxScreen->beDepths = NULL; + + XFree(dmxScreen->bePixmapFormats); + dmxScreen->bePixmapFormats = NULL; +#endif + } + + DMX_UNWRAP(CloseScreen, dmxScreen, pScreen); + return pScreen->CloseScreen(idx, pScreen); +} + +static Bool dmxSaveScreen(ScreenPtr pScreen, int what) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + + if (dmxScreen->beDisplay) { + switch (what) { + case SCREEN_SAVER_OFF: + case SCREEN_SAVER_FORCER: + XResetScreenSaver(dmxScreen->beDisplay); + dmxSync(dmxScreen, FALSE); + break; + case SCREEN_SAVER_ON: + case SCREEN_SAVER_CYCLE: + XActivateScreenSaver(dmxScreen->beDisplay); + dmxSync(dmxScreen, FALSE); + break; + } + } + + return TRUE; +} diff --git a/xorg-server/hw/dmx/dmxsync.c b/xorg-server/hw/dmx/dmxsync.c index 2cec1b97c..8ace59470 100644 --- a/xorg-server/hw/dmx/dmxsync.c +++ b/xorg-server/hw/dmx/dmxsync.c @@ -1,193 +1,193 @@ -/* - * Copyright 2002-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: - * Rickard E. (Rik) Faith - * - */ - -/** \file - * - * The DMX server code is written to call #dmxSync() whenever an XSync() - * might be necessary. However, since XSync() requires a two way - * communication with the other X server, eliminating unnecessary - * XSync() calls is a key performance optimization. Support for this - * optimization is provided here. Statistics about XSync() calls and - * latency are gathered in \a dmxstat.c. - * - * During the initial conversion from calling XSync() immediately to the - * XSync() batching method implemented in this file, it was noted that, - * out of more than 300 \a x11perf tests, 8 tests became more than 100 - * times faster, with 68 more than 50X faster, 114 more than 10X faster, - * and 181 more than 2X faster. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include "dmx.h" -#include "dmxsync.h" -#include "dmxstat.h" -#include "dmxlog.h" -#include - -static int dmxSyncInterval = 100; /* Default interval in milliseconds */ -static OsTimerPtr dmxSyncTimer; -static int dmxSyncPending; - -static void dmxDoSync(DMXScreenInfo *dmxScreen) -{ - dmxScreen->needsSync = FALSE; - - if (!dmxScreen->beDisplay) - return; /* FIXME: Is this correct behavior for sync stats? */ - - if (!dmxStatInterval) { - XSync(dmxScreen->beDisplay, False); - } else { - struct timeval start, stop; - - gettimeofday(&start, 0); - XSync(dmxScreen->beDisplay, False); - gettimeofday(&stop, 0); - dmxStatSync(dmxScreen, &stop, &start, dmxSyncPending); - } -} - -static CARD32 dmxSyncCallback(OsTimerPtr timer, CARD32 time, pointer arg) -{ - int i; - - if (dmxSyncPending) { - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - if (dmxScreen->needsSync) dmxDoSync(dmxScreen); - } - } - dmxSyncPending = 0; - return 0; /* Do not place on queue again */ -} - -static void dmxSyncBlockHandler(pointer blockData, OSTimePtr pTimeout, - pointer pReadMask) -{ - TimerForce(dmxSyncTimer); -} - -static void dmxSyncWakeupHandler(pointer blockData, int result, - pointer pReadMask) -{ -} - -/** Request the XSync() batching optimization with the specified \a - * interval (in mS). If the \a interval is 0, 100mS is used. If the \a - * interval is less than 0, then the XSync() batching optimization is - * not requested (e.g., so the -syncbatch -1 command line option can - * turn off the default 100mS XSync() batching). - * - * Note that the parameter to this routine is a string, since it will - * usually be called from #ddxProcessArgument in \a dmxinit.c */ -void dmxSyncActivate(const char *interval) -{ - dmxSyncInterval = (interval ? atoi(interval) : 100); - - if (dmxSyncInterval < 0) dmxSyncInterval = 0; -} - -/** Initialize the XSync() batching optimization, but only if - * #dmxSyncActivate was last called with a non-negative value. */ -void dmxSyncInit(void) -{ - if (dmxSyncInterval) { - RegisterBlockAndWakeupHandlers(dmxSyncBlockHandler, - dmxSyncWakeupHandler, - NULL); - dmxLog(dmxInfo, "XSync batching with %d ms interval\n", - dmxSyncInterval); - } else { - dmxLog(dmxInfo, "XSync batching disabled\n"); - } -} - -/** Request an XSync() to the display used by \a dmxScreen. If \a now - * is TRUE, call XSync() immediately instead of waiting for the next - * XSync() batching point. Note that if XSync() batching was deselected - * with #dmxSyncActivate() before #dmxSyncInit() was called, then no - * XSync() batching is performed and this function always calles XSync() - * immediately. - * - * (Note that this function uses TimerSet but works correctly in the - * face of a server generation. See the source for details.) - * - * If \a dmxScreen is \a NULL, then all pending syncs will be flushed - * immediately. - */ -void dmxSync(DMXScreenInfo *dmxScreen, Bool now) -{ - static unsigned long dmxGeneration = 0; - - if (dmxSyncInterval) { - if (dmxGeneration != serverGeneration) { - /* Server generation does a TimerInit, which frees all - * timers. So, at this point dmxSyncTimer is either: - * 1) NULL, iff dmxGeneration == 0, - * 2) freed, if it was on a queue (dmxSyncPending != 0), or - * 3) allocated, if it wasn't on a queue (dmxSyncPending == 0) - */ - if (dmxSyncTimer && !dmxSyncPending) xfree(dmxSyncTimer); - dmxSyncTimer = NULL; - now = TRUE; - dmxGeneration = serverGeneration; - } - /* Queue sync */ - if (dmxScreen) { - dmxScreen->needsSync = TRUE; - ++dmxSyncPending; - } - - /* Do sync or set time for later */ - if (now || !dmxScreen) { - if (!TimerForce(dmxSyncTimer)) dmxSyncCallback(NULL, 0, NULL); - /* At this point, dmxSyncPending == 0 because - * dmxSyncCallback must have been called. */ - if (dmxSyncPending) - dmxLog(dmxFatal, "dmxSync(%s,%d): dmxSyncPending = %d\n", - dmxScreen ? dmxScreen->name : "", now, dmxSyncPending); - } else { - dmxScreen->needsSync = TRUE; - if (dmxSyncPending == 1) - dmxSyncTimer = TimerSet(dmxSyncTimer, 0, dmxSyncInterval, - dmxSyncCallback, NULL); - } - } else { - /* If dmxSyncInterval is not being used, - * then all the backends are already - * up-to-date. */ - if (dmxScreen) dmxDoSync(dmxScreen); - } -} +/* + * Copyright 2002-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: + * Rickard E. (Rik) Faith + * + */ + +/** \file + * + * The DMX server code is written to call #dmxSync() whenever an XSync() + * might be necessary. However, since XSync() requires a two way + * communication with the other X server, eliminating unnecessary + * XSync() calls is a key performance optimization. Support for this + * optimization is provided here. Statistics about XSync() calls and + * latency are gathered in \a dmxstat.c. + * + * During the initial conversion from calling XSync() immediately to the + * XSync() batching method implemented in this file, it was noted that, + * out of more than 300 \a x11perf tests, 8 tests became more than 100 + * times faster, with 68 more than 50X faster, 114 more than 10X faster, + * and 181 more than 2X faster. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include "dmxsync.h" +#include "dmxstat.h" +#include "dmxlog.h" +#include + +static int dmxSyncInterval = 100; /* Default interval in milliseconds */ +static OsTimerPtr dmxSyncTimer; +static int dmxSyncPending; + +static void dmxDoSync(DMXScreenInfo *dmxScreen) +{ + dmxScreen->needsSync = FALSE; + + if (!dmxScreen->beDisplay) + return; /* FIXME: Is this correct behavior for sync stats? */ + + if (!dmxStatInterval) { + XSync(dmxScreen->beDisplay, False); + } else { + struct timeval start, stop; + + gettimeofday(&start, 0); + XSync(dmxScreen->beDisplay, False); + gettimeofday(&stop, 0); + dmxStatSync(dmxScreen, &stop, &start, dmxSyncPending); + } +} + +static CARD32 dmxSyncCallback(OsTimerPtr timer, CARD32 time, pointer arg) +{ + int i; + + if (dmxSyncPending) { + for (i = 0; i < dmxNumScreens; i++) { + DMXScreenInfo *dmxScreen = &dmxScreens[i]; + if (dmxScreen->needsSync) dmxDoSync(dmxScreen); + } + } + dmxSyncPending = 0; + return 0; /* Do not place on queue again */ +} + +static void dmxSyncBlockHandler(pointer blockData, OSTimePtr pTimeout, + pointer pReadMask) +{ + TimerForce(dmxSyncTimer); +} + +static void dmxSyncWakeupHandler(pointer blockData, int result, + pointer pReadMask) +{ +} + +/** Request the XSync() batching optimization with the specified \a + * interval (in mS). If the \a interval is 0, 100mS is used. If the \a + * interval is less than 0, then the XSync() batching optimization is + * not requested (e.g., so the -syncbatch -1 command line option can + * turn off the default 100mS XSync() batching). + * + * Note that the parameter to this routine is a string, since it will + * usually be called from #ddxProcessArgument in \a dmxinit.c */ +void dmxSyncActivate(const char *interval) +{ + dmxSyncInterval = (interval ? atoi(interval) : 100); + + if (dmxSyncInterval < 0) dmxSyncInterval = 0; +} + +/** Initialize the XSync() batching optimization, but only if + * #dmxSyncActivate was last called with a non-negative value. */ +void dmxSyncInit(void) +{ + if (dmxSyncInterval) { + RegisterBlockAndWakeupHandlers(dmxSyncBlockHandler, + dmxSyncWakeupHandler, + NULL); + dmxLog(dmxInfo, "XSync batching with %d ms interval\n", + dmxSyncInterval); + } else { + dmxLog(dmxInfo, "XSync batching disabled\n"); + } +} + +/** Request an XSync() to the display used by \a dmxScreen. If \a now + * is TRUE, call XSync() immediately instead of waiting for the next + * XSync() batching point. Note that if XSync() batching was deselected + * with #dmxSyncActivate() before #dmxSyncInit() was called, then no + * XSync() batching is performed and this function always calles XSync() + * immediately. + * + * (Note that this function uses TimerSet but works correctly in the + * face of a server generation. See the source for details.) + * + * If \a dmxScreen is \a NULL, then all pending syncs will be flushed + * immediately. + */ +void dmxSync(DMXScreenInfo *dmxScreen, Bool now) +{ + static unsigned long dmxGeneration = 0; + + if (dmxSyncInterval) { + if (dmxGeneration != serverGeneration) { + /* Server generation does a TimerInit, which frees all + * timers. So, at this point dmxSyncTimer is either: + * 1) NULL, iff dmxGeneration == 0, + * 2) freed, if it was on a queue (dmxSyncPending != 0), or + * 3) allocated, if it wasn't on a queue (dmxSyncPending == 0) + */ + if (dmxSyncTimer && !dmxSyncPending) free(dmxSyncTimer); + dmxSyncTimer = NULL; + now = TRUE; + dmxGeneration = serverGeneration; + } + /* Queue sync */ + if (dmxScreen) { + dmxScreen->needsSync = TRUE; + ++dmxSyncPending; + } + + /* Do sync or set time for later */ + if (now || !dmxScreen) { + if (!TimerForce(dmxSyncTimer)) dmxSyncCallback(NULL, 0, NULL); + /* At this point, dmxSyncPending == 0 because + * dmxSyncCallback must have been called. */ + if (dmxSyncPending) + dmxLog(dmxFatal, "dmxSync(%s,%d): dmxSyncPending = %d\n", + dmxScreen ? dmxScreen->name : "", now, dmxSyncPending); + } else { + dmxScreen->needsSync = TRUE; + if (dmxSyncPending == 1) + dmxSyncTimer = TimerSet(dmxSyncTimer, 0, dmxSyncInterval, + dmxSyncCallback, NULL); + } + } else { + /* If dmxSyncInterval is not being used, + * then all the backends are already + * up-to-date. */ + if (dmxScreen) dmxDoSync(dmxScreen); + } +} diff --git a/xorg-server/hw/dmx/dmxwindow.c b/xorg-server/hw/dmx/dmxwindow.c index ea2f2c579..3466f074f 100644 --- a/xorg-server/hw/dmx/dmxwindow.c +++ b/xorg-server/hw/dmx/dmxwindow.c @@ -1,1015 +1,1015 @@ -/* - * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 - * - */ - -/** \file - * This file provides support for window-related functions. */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include "dmx.h" -#include "dmxsync.h" -#include "dmxwindow.h" -#include "dmxpixmap.h" -#include "dmxcmap.h" -#include "dmxvisual.h" -#include "dmxinput.h" -#include "dmxextension.h" -#include "dmxpict.h" - -#include "windowstr.h" - -static void dmxDoRestackWindow(WindowPtr pWindow); -static void dmxDoChangeWindowAttributes(WindowPtr pWindow, - unsigned long *mask, - XSetWindowAttributes *attribs); - -static void dmxDoSetShape(WindowPtr pWindow); - -/** Initialize the private area for the window functions. */ -Bool dmxInitWindow(ScreenPtr pScreen) -{ - if (!dixRequestPrivate(dmxWinPrivateKey, sizeof(dmxWinPrivRec))) - return FALSE; - - return TRUE; -} - - -Window dmxCreateRootWindow(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - Window parent; - Visual *visual; - unsigned long mask; - XSetWindowAttributes attribs; - ColormapPtr pCmap; - dmxColormapPrivPtr pCmapPriv; - - /* Create root window */ - - parent = dmxScreen->scrnWin; /* This is our "Screen" window */ - visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual; - - pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP); - pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); - - mask = CWEventMask | CWBackingStore | CWColormap | CWBorderPixel; - attribs.event_mask = ExposureMask; - attribs.backing_store = NotUseful; - attribs.colormap = pCmapPriv->cmap; - attribs.border_pixel = 0; - - /* Incorporate new attributes, if needed */ - if (pWinPriv->attribMask) { - dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs); - mask |= pWinPriv->attribMask; - } - - return XCreateWindow(dmxScreen->beDisplay, - parent, - pWindow->origin.x - wBorderWidth(pWindow), - pWindow->origin.y - wBorderWidth(pWindow), - pWindow->drawable.width, - pWindow->drawable.height, - pWindow->borderWidth, - pWindow->drawable.depth, - pWindow->drawable.class, - visual, - mask, - &attribs); -} - -/** Change the location and size of the "screen" window. Called from - * #dmxConfigureScreenWindow(). */ -void dmxResizeScreenWindow(ScreenPtr pScreen, - int x, int y, int w, int h) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - unsigned int m; - XWindowChanges c; - - if (!dmxScreen->beDisplay) - return; - - /* Handle resizing on back-end server */ - m = CWX | CWY | CWWidth | CWHeight; - c.x = x; - c.y = y; - c.width = w; - c.height = h; - - XConfigureWindow(dmxScreen->beDisplay, dmxScreen->scrnWin, m, &c); - dmxSync(dmxScreen, False); -} - -/** Change the location and size of the "root" window. Called from - * #dmxConfigureRootWindow. */ -void dmxResizeRootWindow(WindowPtr pRoot, - int x, int y, int w, int h) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pRoot->drawable.pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot); - unsigned int m; - XWindowChanges c; - - /* Handle resizing on back-end server */ - if (dmxScreen->beDisplay) { - m = CWX | CWY | CWWidth | CWHeight; - c.x = x; - c.y = y; - c.width = (w > 0) ? w : 1; - c.height = (h > 0) ? h : 1; - - XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); - } - - if (w == 0 || h == 0) { - if (pWinPriv->mapped) { - if (dmxScreen->beDisplay) - XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window); - pWinPriv->mapped = FALSE; - } - } else if (!pWinPriv->mapped) { - if (dmxScreen->beDisplay) - XMapWindow(dmxScreen->beDisplay, pWinPriv->window); - pWinPriv->mapped = TRUE; - } - - if (dmxScreen->beDisplay) - dmxSync(dmxScreen, False); -} - -void dmxGetDefaultWindowAttributes(WindowPtr pWindow, - Colormap *cmap, - Visual **visual) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - - if (pWindow->drawable.class != InputOnly && - pWindow->optional && - pWindow->optional->visual != wVisual(pWindow->parent)) { - - /* Find the matching visual */ - *visual = dmxLookupVisualFromID(pScreen, wVisual(pWindow)); - - /* Handle optional colormaps */ - if (pWindow->optional->colormap) { - ColormapPtr pCmap; - dmxColormapPrivPtr pCmapPriv; - - pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), - RT_COLORMAP); - pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); - *cmap = pCmapPriv->cmap; - } else { - *cmap = dmxColormapFromDefaultVisual(pScreen, *visual); - } - } else { - *visual = CopyFromParent; - *cmap = (Colormap)0; - } -} - -static Window dmxCreateNonRootWindow(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - Window parent; - unsigned long mask = 0L; - XSetWindowAttributes attribs; - dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent); - - /* Create window on back-end server */ - - parent = pParentPriv->window; - - /* The parent won't exist if this call to CreateNonRootWindow came - from ReparentWindow and the grandparent window has not yet been - created */ - if (!parent) { - dmxCreateAndRealizeWindow(pWindow->parent, FALSE); - parent = pParentPriv->window; - } - - /* Incorporate new attributes, if needed */ - if (pWinPriv->attribMask) { - dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs); - mask |= pWinPriv->attribMask; - } - - /* Add in default attributes */ - if (pWindow->drawable.class != InputOnly) { - mask |= CWBackingStore; - attribs.backing_store = NotUseful; - - if (!(mask & CWColormap) && pWinPriv->cmap) { - mask |= CWColormap; - attribs.colormap = pWinPriv->cmap; - if (!(mask & CWBorderPixel)) { - mask |= CWBorderPixel; - attribs.border_pixel = 0; - } - } - } - - /* Handle case where subwindows are being mapped, but created out of - order -- if current window has a previous sibling, then it cannot - be created on top of the stack, so we must restack the windows */ - pWinPriv->restacked = (pWindow->prevSib != NullWindow); - - return XCreateWindow(dmxScreen->beDisplay, - parent, - pWindow->origin.x - wBorderWidth(pWindow), - pWindow->origin.y - wBorderWidth(pWindow), - pWindow->drawable.width, - pWindow->drawable.height, - pWindow->borderWidth, - pWindow->drawable.depth, - pWindow->drawable.class, - pWinPriv->visual, - mask, - &attribs); -} - -/** This function handles lazy window creation and realization. Window - * creation is handled by #dmxCreateNonRootWindow(). It also handles - * any stacking changes that have occured since the window was - * originally created by calling #dmxDoRestackWindow(). If the window - * is shaped, the shape is set on the back-end server by calling - * #dmxDoSetShape(), and if the window has pictures (from RENDER) - * associated with it, those pictures are created on the back-end - * server by calling #dmxCreatePictureList(). If \a doSync is TRUE, - * then #dmxSync() is called. */ -void dmxCreateAndRealizeWindow(WindowPtr pWindow, Bool doSync) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - - if (!dmxScreen->beDisplay) return; - - pWinPriv->window = dmxCreateNonRootWindow(pWindow); - if (pWinPriv->restacked) dmxDoRestackWindow(pWindow); - if (pWinPriv->isShaped) dmxDoSetShape(pWindow); - if (pWinPriv->hasPict) dmxCreatePictureList(pWindow); - if (pWinPriv->mapped) XMapWindow(dmxScreen->beDisplay, - pWinPriv->window); - if (doSync) dmxSync(dmxScreen, False); -} - -/** Create \a pWindow on the back-end server. If the lazy window - * creation optimization is enabled, then the actual creation and - * realization of the window is handled by - * #dmxCreateAndRealizeWindow(). */ -Bool dmxCreateWindow(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - Bool ret = TRUE; - - DMX_UNWRAP(CreateWindow, dmxScreen, pScreen); -#if 0 - if (pScreen->CreateWindow) - ret = pScreen->CreateWindow(pWindow); -#endif - - /* Set up the defaults */ - pWinPriv->window = (Window)0; - pWinPriv->offscreen = TRUE; - pWinPriv->mapped = FALSE; - pWinPriv->restacked = FALSE; - pWinPriv->attribMask = 0; - pWinPriv->isShaped = FALSE; - pWinPriv->hasPict = FALSE; -#ifdef GLXEXT - pWinPriv->swapGroup = NULL; - pWinPriv->barrier = 0; -#endif - - if (dmxScreen->beDisplay) { - /* Only create the root window at this stage -- non-root windows are - created when they are mapped and are on-screen */ - if (!pWindow->parent) { - dmxScreen->rootWin = pWinPriv->window - = dmxCreateRootWindow(pWindow); - if (dmxScreen->scrnX != dmxScreen->rootX - || dmxScreen->scrnY != dmxScreen->rootY - || dmxScreen->scrnWidth != dmxScreen->rootWidth - || dmxScreen->scrnHeight != dmxScreen->rootHeight) { - dmxResizeRootWindow(pWindow, - dmxScreen->rootX, - dmxScreen->rootY, - dmxScreen->rootWidth, - dmxScreen->rootHeight); - dmxUpdateScreenResources(screenInfo.screens[dmxScreen->index], - dmxScreen->rootX, - dmxScreen->rootY, - dmxScreen->rootWidth, - dmxScreen->rootHeight); - pWindow->origin.x = dmxScreen->rootX; - pWindow->origin.y = dmxScreen->rootY; - } - } else { - dmxGetDefaultWindowAttributes(pWindow, - &pWinPriv->cmap, - &pWinPriv->visual); - - if (dmxLazyWindowCreation) { - /* Save parent's visual for use later */ - if (pWinPriv->visual == CopyFromParent) - pWinPriv->visual = - dmxLookupVisualFromID(pScreen, - wVisual(pWindow->parent)); - } else { - pWinPriv->window = dmxCreateNonRootWindow(pWindow); - } - } - - dmxSync(dmxScreen, False); - } - - DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen); - - return ret; -} - -/** Destroy \a pWindow on the back-end server. */ -Bool dmxBEDestroyWindow(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - - if (pWinPriv->window) { - XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window); - pWinPriv->window = (Window)0; - return TRUE; - } - - return FALSE; -} - -/** Destroy \a pWindow on the back-end server. If any RENDER pictures - were created, destroy them as well. */ -Bool dmxDestroyWindow(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - Bool ret = TRUE; - Bool needSync = FALSE; -#ifdef GLXEXT - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); -#endif - - DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen); - - /* Destroy any picture list associated with this window */ - needSync |= dmxDestroyPictureList(pWindow); - - /* Destroy window on back-end server */ - needSync |= dmxBEDestroyWindow(pWindow); - if (needSync) dmxSync(dmxScreen, FALSE); - -#ifdef GLXEXT - if (pWinPriv->swapGroup && pWinPriv->windowDestroyed) - pWinPriv->windowDestroyed(pWindow); -#endif - - if (pScreen->DestroyWindow) - ret = pScreen->DestroyWindow(pWindow); - - DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen); - - return ret; -} - -/** Change the position of \a pWindow to be \a x, \a y. */ -Bool dmxPositionWindow(WindowPtr pWindow, int x, int y) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - Bool ret = TRUE; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - unsigned int m; - XWindowChanges c; - - DMX_UNWRAP(PositionWindow, dmxScreen, pScreen); -#if 0 - if (pScreen->PositionWindow) - ret = pScreen->PositionWindow(pWindow, x, y); -#endif - - /* Determine if the window is completely off the visible portion of - the screen */ - pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); - - /* If the window is now on-screen and it is mapped and it has not - been created yet, create it and map it */ - if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { - dmxCreateAndRealizeWindow(pWindow, TRUE); - } else if (pWinPriv->window) { - /* Position window on back-end server */ - m = CWX | CWY | CWWidth | CWHeight; - c.x = pWindow->origin.x - wBorderWidth(pWindow); - c.y = pWindow->origin.y - wBorderWidth(pWindow); - c.width = pWindow->drawable.width; - c.height = pWindow->drawable.height; - if (pWindow->drawable.class != InputOnly) { - m |= CWBorderWidth; - c.border_width = pWindow->borderWidth; - } - - XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); - dmxSync(dmxScreen, False); - } - - DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen); - - return ret; -} - -static void dmxDoChangeWindowAttributes(WindowPtr pWindow, - unsigned long *mask, - XSetWindowAttributes *attribs) -{ - dmxPixPrivPtr pPixPriv; - - if (*mask & CWBackPixmap) { - switch (pWindow->backgroundState) { - case None: - attribs->background_pixmap = None; - break; - - case ParentRelative: - attribs->background_pixmap = ParentRelative; - break; - - case BackgroundPixmap: - pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->background.pixmap); - attribs->background_pixmap = pPixPriv->pixmap; - break; - - case BackgroundPixel: - *mask &= ~CWBackPixmap; - break; - } - } - - if (*mask & CWBackPixel) { - if (pWindow->backgroundState == BackgroundPixel) - attribs->background_pixel = pWindow->background.pixel; - else - *mask &= ~CWBackPixel; - } - - if (*mask & CWBorderPixmap) { - if (pWindow->borderIsPixel) - *mask &= ~CWBorderPixmap; - else { - pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->border.pixmap); - attribs->border_pixmap = pPixPriv->pixmap; - } - } - - if (*mask & CWBorderPixel) { - if (pWindow->borderIsPixel) - attribs->border_pixel = pWindow->border.pixel; - else - *mask &= ~CWBorderPixel; - } - - if (*mask & CWBitGravity) - attribs->bit_gravity = pWindow->bitGravity; - - if (*mask & CWWinGravity) - *mask &= ~CWWinGravity; /* Handled by dix */ - - if (*mask & CWBackingStore) - *mask &= ~CWBackingStore; /* Backing store not supported */ - - if (*mask & CWBackingPlanes) - *mask &= ~CWBackingPlanes; /* Backing store not supported */ - - if (*mask & CWBackingPixel) - *mask &= ~CWBackingPixel; /* Backing store not supported */ - - if (*mask & CWOverrideRedirect) - attribs->override_redirect = pWindow->overrideRedirect; - - if (*mask & CWSaveUnder) - *mask &= ~CWSaveUnder; /* Save unders not supported */ - - if (*mask & CWEventMask) - *mask &= ~CWEventMask; /* Events are handled by dix */ - - if (*mask & CWDontPropagate) - *mask &= ~CWDontPropagate; /* Events are handled by dix */ - - if (*mask & CWColormap) { - ColormapPtr pCmap; - dmxColormapPrivPtr pCmapPriv; - - pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP); - pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); - attribs->colormap = pCmapPriv->cmap; - } - - if (*mask & CWCursor) - *mask &= ~CWCursor; /* Handled by the cursor code */ -} - -/** Change the window attributes of \a pWindow. */ -Bool dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - Bool ret = TRUE; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - XSetWindowAttributes attribs; - - DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen); -#if 0 - if (pScreen->ChangeWindowAttributes) - ret = pScreen->ChangeWindowAttributes(pWindow, mask); -#endif - - /* Change window attribs on back-end server */ - dmxDoChangeWindowAttributes(pWindow, &mask, &attribs); - - /* Save mask for lazy window creation optimization */ - pWinPriv->attribMask |= mask; - - if (mask && pWinPriv->window) { - XChangeWindowAttributes(dmxScreen->beDisplay, pWinPriv->window, - mask, &attribs); - dmxSync(dmxScreen, False); - } - - DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen, - pScreen); - - return ret; -} - -/** Realize \a pWindow on the back-end server. If the lazy window - * creation optimization is enabled, the window is only realized when - * it at least partially overlaps the screen. */ -Bool dmxRealizeWindow(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - Bool ret = TRUE; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - - DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen); -#if 0 - if (pScreen->RealizeWindow) - ret = pScreen->RealizeWindow(pWindow); -#endif - - /* Determine if the window is completely off the visible portion of - the screen */ - pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); - - /* If the window hasn't been created and it's not offscreen, then - create it */ - if (!pWinPriv->window && !pWinPriv->offscreen) { - dmxCreateAndRealizeWindow(pWindow, FALSE); - } - - if (pWinPriv->window) { - /* Realize window on back-end server */ - XMapWindow(dmxScreen->beDisplay, pWinPriv->window); - dmxSync(dmxScreen, False); - } - - /* Let the other functions know that the window is now mapped */ - pWinPriv->mapped = TRUE; - - DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen); - - dmxUpdateWindowInfo(DMX_UPDATE_REALIZE, pWindow); - return ret; -} - -/** Unrealize \a pWindow on the back-end server. */ -Bool dmxUnrealizeWindow(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - Bool ret = TRUE; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - - DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen); -#if 0 - if (pScreen->UnrealizeWindow) - ret = pScreen->UnrealizeWindow(pWindow); -#endif - - if (pWinPriv->window) { - /* Unrealize window on back-end server */ - XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window); - dmxSync(dmxScreen, False); - } - - /* When unrealized (i.e., unmapped), the window is always considered - off of the visible portion of the screen */ - pWinPriv->offscreen = TRUE; - pWinPriv->mapped = FALSE; - -#ifdef GLXEXT - if (pWinPriv->swapGroup && pWinPriv->windowUnmapped) - pWinPriv->windowUnmapped(pWindow); -#endif - - DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen); - - dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE, pWindow); - return ret; -} - -static void dmxDoRestackWindow(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - WindowPtr pNextSib = pWindow->nextSib; - unsigned int m; - XWindowChanges c; - - if (pNextSib == NullWindow) { - /* Window is at the bottom of the stack */ - m = CWStackMode; - c.sibling = (Window)0; - c.stack_mode = Below; - XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); - } else { - /* Window is not at the bottom of the stack */ - dmxWinPrivPtr pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib); - - /* Handle case where siblings have not yet been created due to - lazy window creation optimization by first finding the next - sibling in the sibling list that has been created (if any) - and then putting the current window just above that sibling, - and if no next siblings have been created yet, then put it at - the bottom of the stack (since it might have a previous - sibling that should be above it). */ - while (!pNextSibPriv->window) { - pNextSib = pNextSib->nextSib; - if (pNextSib == NullWindow) { - /* Window is at the bottom of the stack */ - m = CWStackMode; - c.sibling = (Window)0; - c.stack_mode = Below; - XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); - return; - } - pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib); - } - - m = CWStackMode | CWSibling; - c.sibling = pNextSibPriv->window; - c.stack_mode = Above; - XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); - } -} - -/** Handle window restacking. The actual restacking occurs in - * #dmxDoRestackWindow(). */ -void dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - - DMX_UNWRAP(RestackWindow, dmxScreen, pScreen); -#if 0 - if (pScreen->RestackWindow) - pScreen->RestackWindow(pWindow, pOldNextSib); -#endif - - if (pOldNextSib != pWindow->nextSib) { - /* Track restacking for lazy window creation optimization */ - pWinPriv->restacked = TRUE; - - /* Restack window on back-end server */ - if (pWinPriv->window) { - dmxDoRestackWindow(pWindow); - dmxSync(dmxScreen, False); - } - } - - DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen); - dmxUpdateWindowInfo(DMX_UPDATE_RESTACK, pWindow); -} - -static Bool dmxWindowExposurePredicate(Display *dpy, XEvent *ev, XPointer ptr) -{ - return (ev->type == Expose && ev->xexpose.window == *(Window *)ptr); -} - -/** Handle exposures on \a pWindow. Since window exposures are handled - * in DMX, the events that are generated by the back-end server are - * redundant, so we eat them here. */ -void dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn, - RegionPtr other_exposed) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - XEvent ev; - - DMX_UNWRAP(WindowExposures, dmxScreen, pScreen); - - dmxSync(dmxScreen, False); - - if (pWinPriv->window) { - while (XCheckIfEvent(dmxScreen->beDisplay, &ev, - dmxWindowExposurePredicate, - (XPointer)&pWinPriv->window)) { - /* Handle expose events -- this should not be necessary - since the base window in which the root window was - created is guaranteed to be on top (override_redirect), - so we should just swallow these events. If for some - reason the window is not on top, then we'd need to - collect these events and send them to the client later - (e.g., during the block handler as Xnest does). */ - } - } - -#if 1 - if (pScreen->WindowExposures) - pScreen->WindowExposures(pWindow, prgn, other_exposed); -#endif - DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen); -} - -/** Move \a pWindow on the back-end server. Determine whether or not it - * is on or offscreen, and realize it if it is newly on screen and the - * lazy window creation optimization is enabled. */ -void dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - unsigned int m; - XWindowChanges c; - - DMX_UNWRAP(CopyWindow, dmxScreen, pScreen); -#if 0 - if (pScreen->CopyWindow) - pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc); -#endif - - /* Determine if the window is completely off the visible portion of - the screen */ - pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); - - /* If the window is now on-screen and it is mapped and it has not - been created yet, create it and map it */ - if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { - dmxCreateAndRealizeWindow(pWindow, TRUE); - } else if (pWinPriv->window) { - /* Move window on back-end server */ - m = CWX | CWY | CWWidth | CWHeight; - c.x = pWindow->origin.x - wBorderWidth(pWindow); - c.y = pWindow->origin.y - wBorderWidth(pWindow); - c.width = pWindow->drawable.width; - c.height = pWindow->drawable.height; - - XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); - dmxSync(dmxScreen, False); - } - - DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen); - dmxUpdateWindowInfo(DMX_UPDATE_COPY, pWindow); -} - -/** Resize \a pWindow on the back-end server. Determine whether or not - * it is on or offscreen, and realize it if it is newly on screen and - * the lazy window creation optimization is enabled. */ -void dmxResizeWindow(WindowPtr pWindow, int x, int y, - unsigned int w, unsigned int h, WindowPtr pSib) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - dmxWinPrivPtr pSibPriv; - unsigned int m; - XWindowChanges c; - - if (pSib) - pSibPriv = DMX_GET_WINDOW_PRIV(pSib); - - DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen); -#if 1 - if (pScreen->ResizeWindow) - pScreen->ResizeWindow(pWindow, x, y, w, h, pSib); -#endif - - /* Determine if the window is completely off the visible portion of - the screen */ - pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); - - /* If the window is now on-screen and it is mapped and it has not - been created yet, create it and map it */ - if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { - dmxCreateAndRealizeWindow(pWindow, TRUE); - } else if (pWinPriv->window) { - /* Handle resizing on back-end server */ - m = CWX | CWY | CWWidth | CWHeight; - c.x = pWindow->origin.x - wBorderWidth(pWindow); - c.y = pWindow->origin.y - wBorderWidth(pWindow); - c.width = pWindow->drawable.width; - c.height = pWindow->drawable.height; - - XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); - dmxSync(dmxScreen, False); - } - - DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen); - dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow); -} - -/** Reparent \a pWindow on the back-end server. */ -void dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent); - - DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen); -#if 0 - if (pScreen->ReparentWindow) - pScreen->ReparentWindow(pWindow, pPriorParent); -#endif - - if (pWinPriv->window) { - if (!pParentPriv->window) { - dmxCreateAndRealizeWindow(pWindow->parent, FALSE); - } - - /* Handle reparenting on back-end server */ - XReparentWindow(dmxScreen->beDisplay, pWinPriv->window, - pParentPriv->window, - pWindow->origin.x - wBorderWidth(pWindow), - pWindow->origin.x - wBorderWidth(pWindow)); - dmxSync(dmxScreen, False); - } - - DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen); - dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow); -} - -/** Change border width for \a pWindow to \a width pixels. */ -void dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - unsigned int m; - XWindowChanges c; - - DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen); -#if 1 - if (pScreen->ChangeBorderWidth) - pScreen->ChangeBorderWidth(pWindow, width); -#endif - - /* NOTE: Do we need to check for on/off screen here? */ - - if (pWinPriv->window) { - /* Handle border width change on back-end server */ - m = CWBorderWidth; - c.border_width = width; - - XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); - dmxSync(dmxScreen, False); - } - - DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen); -} - -static void dmxDoSetShape(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - int nBox; - BoxPtr pBox; - int nRect; - XRectangle *pRect; - XRectangle *pRectFirst; - - /* First, set the bounding shape */ - if (wBoundingShape(pWindow)) { - pBox = REGION_RECTS(wBoundingShape(pWindow)); - nRect = nBox = REGION_NUM_RECTS(wBoundingShape(pWindow)); - pRectFirst = pRect = xalloc(nRect * sizeof(*pRect)); - while (nBox--) { - pRect->x = pBox->x1; - pRect->y = pBox->y1; - pRect->width = pBox->x2 - pBox->x1; - pRect->height = pBox->y2 - pBox->y1; - pBox++; - pRect++; - } - XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window, - ShapeBounding, 0, 0, - pRectFirst, nRect, - ShapeSet, YXBanded); - xfree(pRectFirst); - } else { - XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window, - ShapeBounding, 0, 0, None, ShapeSet); - } - - /* Next, set the clip shape */ - if (wClipShape(pWindow)) { - pBox = REGION_RECTS(wClipShape(pWindow)); - nRect = nBox = REGION_NUM_RECTS(wClipShape(pWindow)); - pRectFirst = pRect = xalloc(nRect * sizeof(*pRect)); - while (nBox--) { - pRect->x = pBox->x1; - pRect->y = pBox->y1; - pRect->width = pBox->x2 - pBox->x1; - pRect->height = pBox->y2 - pBox->y1; - pBox++; - pRect++; - } - XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window, - ShapeClip, 0, 0, - pRectFirst, nRect, - ShapeSet, YXBanded); - xfree(pRectFirst); - } else { - XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window, - ShapeClip, 0, 0, None, ShapeSet); - } - - if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) { - ErrorF("Input selected for window %x on Screen %d\n", - (unsigned int)pWinPriv->window, pScreen->myNum); - } -} - -/** Set shape of \a pWindow on the back-end server. */ -void dmxSetShape(WindowPtr pWindow) -{ - ScreenPtr pScreen = pWindow->drawable.pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); - - DMX_UNWRAP(SetShape, dmxScreen, pScreen); -#if 1 - if (pScreen->SetShape) - pScreen->SetShape(pWindow); -#endif - - if (pWinPriv->window) { - /* Handle setting the current shape on the back-end server */ - dmxDoSetShape(pWindow); - dmxSync(dmxScreen, False); - } else { - pWinPriv->isShaped = TRUE; - } - - DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen); -} +/* + * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 + * + */ + +/** \file + * This file provides support for window-related functions. */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include "dmx.h" +#include "dmxsync.h" +#include "dmxwindow.h" +#include "dmxpixmap.h" +#include "dmxcmap.h" +#include "dmxvisual.h" +#include "dmxinput.h" +#include "dmxextension.h" +#include "dmxpict.h" + +#include "windowstr.h" + +static void dmxDoRestackWindow(WindowPtr pWindow); +static void dmxDoChangeWindowAttributes(WindowPtr pWindow, + unsigned long *mask, + XSetWindowAttributes *attribs); + +static void dmxDoSetShape(WindowPtr pWindow); + +/** Initialize the private area for the window functions. */ +Bool dmxInitWindow(ScreenPtr pScreen) +{ + if (!dixRequestPrivate(dmxWinPrivateKey, sizeof(dmxWinPrivRec))) + return FALSE; + + return TRUE; +} + + +Window dmxCreateRootWindow(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + Window parent; + Visual *visual; + unsigned long mask; + XSetWindowAttributes attribs; + ColormapPtr pCmap; + dmxColormapPrivPtr pCmapPriv; + + /* Create root window */ + + parent = dmxScreen->scrnWin; /* This is our "Screen" window */ + visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual; + + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP); + pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); + + mask = CWEventMask | CWBackingStore | CWColormap | CWBorderPixel; + attribs.event_mask = ExposureMask; + attribs.backing_store = NotUseful; + attribs.colormap = pCmapPriv->cmap; + attribs.border_pixel = 0; + + /* Incorporate new attributes, if needed */ + if (pWinPriv->attribMask) { + dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs); + mask |= pWinPriv->attribMask; + } + + return XCreateWindow(dmxScreen->beDisplay, + parent, + pWindow->origin.x - wBorderWidth(pWindow), + pWindow->origin.y - wBorderWidth(pWindow), + pWindow->drawable.width, + pWindow->drawable.height, + pWindow->borderWidth, + pWindow->drawable.depth, + pWindow->drawable.class, + visual, + mask, + &attribs); +} + +/** Change the location and size of the "screen" window. Called from + * #dmxConfigureScreenWindow(). */ +void dmxResizeScreenWindow(ScreenPtr pScreen, + int x, int y, int w, int h) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + unsigned int m; + XWindowChanges c; + + if (!dmxScreen->beDisplay) + return; + + /* Handle resizing on back-end server */ + m = CWX | CWY | CWWidth | CWHeight; + c.x = x; + c.y = y; + c.width = w; + c.height = h; + + XConfigureWindow(dmxScreen->beDisplay, dmxScreen->scrnWin, m, &c); + dmxSync(dmxScreen, False); +} + +/** Change the location and size of the "root" window. Called from + * #dmxConfigureRootWindow. */ +void dmxResizeRootWindow(WindowPtr pRoot, + int x, int y, int w, int h) +{ + DMXScreenInfo *dmxScreen = &dmxScreens[pRoot->drawable.pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot); + unsigned int m; + XWindowChanges c; + + /* Handle resizing on back-end server */ + if (dmxScreen->beDisplay) { + m = CWX | CWY | CWWidth | CWHeight; + c.x = x; + c.y = y; + c.width = (w > 0) ? w : 1; + c.height = (h > 0) ? h : 1; + + XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); + } + + if (w == 0 || h == 0) { + if (pWinPriv->mapped) { + if (dmxScreen->beDisplay) + XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window); + pWinPriv->mapped = FALSE; + } + } else if (!pWinPriv->mapped) { + if (dmxScreen->beDisplay) + XMapWindow(dmxScreen->beDisplay, pWinPriv->window); + pWinPriv->mapped = TRUE; + } + + if (dmxScreen->beDisplay) + dmxSync(dmxScreen, False); +} + +void dmxGetDefaultWindowAttributes(WindowPtr pWindow, + Colormap *cmap, + Visual **visual) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + + if (pWindow->drawable.class != InputOnly && + pWindow->optional && + pWindow->optional->visual != wVisual(pWindow->parent)) { + + /* Find the matching visual */ + *visual = dmxLookupVisualFromID(pScreen, wVisual(pWindow)); + + /* Handle optional colormaps */ + if (pWindow->optional->colormap) { + ColormapPtr pCmap; + dmxColormapPrivPtr pCmapPriv; + + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), + RT_COLORMAP); + pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); + *cmap = pCmapPriv->cmap; + } else { + *cmap = dmxColormapFromDefaultVisual(pScreen, *visual); + } + } else { + *visual = CopyFromParent; + *cmap = (Colormap)0; + } +} + +static Window dmxCreateNonRootWindow(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + Window parent; + unsigned long mask = 0L; + XSetWindowAttributes attribs; + dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent); + + /* Create window on back-end server */ + + parent = pParentPriv->window; + + /* The parent won't exist if this call to CreateNonRootWindow came + from ReparentWindow and the grandparent window has not yet been + created */ + if (!parent) { + dmxCreateAndRealizeWindow(pWindow->parent, FALSE); + parent = pParentPriv->window; + } + + /* Incorporate new attributes, if needed */ + if (pWinPriv->attribMask) { + dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs); + mask |= pWinPriv->attribMask; + } + + /* Add in default attributes */ + if (pWindow->drawable.class != InputOnly) { + mask |= CWBackingStore; + attribs.backing_store = NotUseful; + + if (!(mask & CWColormap) && pWinPriv->cmap) { + mask |= CWColormap; + attribs.colormap = pWinPriv->cmap; + if (!(mask & CWBorderPixel)) { + mask |= CWBorderPixel; + attribs.border_pixel = 0; + } + } + } + + /* Handle case where subwindows are being mapped, but created out of + order -- if current window has a previous sibling, then it cannot + be created on top of the stack, so we must restack the windows */ + pWinPriv->restacked = (pWindow->prevSib != NullWindow); + + return XCreateWindow(dmxScreen->beDisplay, + parent, + pWindow->origin.x - wBorderWidth(pWindow), + pWindow->origin.y - wBorderWidth(pWindow), + pWindow->drawable.width, + pWindow->drawable.height, + pWindow->borderWidth, + pWindow->drawable.depth, + pWindow->drawable.class, + pWinPriv->visual, + mask, + &attribs); +} + +/** This function handles lazy window creation and realization. Window + * creation is handled by #dmxCreateNonRootWindow(). It also handles + * any stacking changes that have occured since the window was + * originally created by calling #dmxDoRestackWindow(). If the window + * is shaped, the shape is set on the back-end server by calling + * #dmxDoSetShape(), and if the window has pictures (from RENDER) + * associated with it, those pictures are created on the back-end + * server by calling #dmxCreatePictureList(). If \a doSync is TRUE, + * then #dmxSync() is called. */ +void dmxCreateAndRealizeWindow(WindowPtr pWindow, Bool doSync) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + + if (!dmxScreen->beDisplay) return; + + pWinPriv->window = dmxCreateNonRootWindow(pWindow); + if (pWinPriv->restacked) dmxDoRestackWindow(pWindow); + if (pWinPriv->isShaped) dmxDoSetShape(pWindow); + if (pWinPriv->hasPict) dmxCreatePictureList(pWindow); + if (pWinPriv->mapped) XMapWindow(dmxScreen->beDisplay, + pWinPriv->window); + if (doSync) dmxSync(dmxScreen, False); +} + +/** Create \a pWindow on the back-end server. If the lazy window + * creation optimization is enabled, then the actual creation and + * realization of the window is handled by + * #dmxCreateAndRealizeWindow(). */ +Bool dmxCreateWindow(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + Bool ret = TRUE; + + DMX_UNWRAP(CreateWindow, dmxScreen, pScreen); +#if 0 + if (pScreen->CreateWindow) + ret = pScreen->CreateWindow(pWindow); +#endif + + /* Set up the defaults */ + pWinPriv->window = (Window)0; + pWinPriv->offscreen = TRUE; + pWinPriv->mapped = FALSE; + pWinPriv->restacked = FALSE; + pWinPriv->attribMask = 0; + pWinPriv->isShaped = FALSE; + pWinPriv->hasPict = FALSE; +#ifdef GLXEXT + pWinPriv->swapGroup = NULL; + pWinPriv->barrier = 0; +#endif + + if (dmxScreen->beDisplay) { + /* Only create the root window at this stage -- non-root windows are + created when they are mapped and are on-screen */ + if (!pWindow->parent) { + dmxScreen->rootWin = pWinPriv->window + = dmxCreateRootWindow(pWindow); + if (dmxScreen->scrnX != dmxScreen->rootX + || dmxScreen->scrnY != dmxScreen->rootY + || dmxScreen->scrnWidth != dmxScreen->rootWidth + || dmxScreen->scrnHeight != dmxScreen->rootHeight) { + dmxResizeRootWindow(pWindow, + dmxScreen->rootX, + dmxScreen->rootY, + dmxScreen->rootWidth, + dmxScreen->rootHeight); + dmxUpdateScreenResources(screenInfo.screens[dmxScreen->index], + dmxScreen->rootX, + dmxScreen->rootY, + dmxScreen->rootWidth, + dmxScreen->rootHeight); + pWindow->origin.x = dmxScreen->rootX; + pWindow->origin.y = dmxScreen->rootY; + } + } else { + dmxGetDefaultWindowAttributes(pWindow, + &pWinPriv->cmap, + &pWinPriv->visual); + + if (dmxLazyWindowCreation) { + /* Save parent's visual for use later */ + if (pWinPriv->visual == CopyFromParent) + pWinPriv->visual = + dmxLookupVisualFromID(pScreen, + wVisual(pWindow->parent)); + } else { + pWinPriv->window = dmxCreateNonRootWindow(pWindow); + } + } + + dmxSync(dmxScreen, False); + } + + DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen); + + return ret; +} + +/** Destroy \a pWindow on the back-end server. */ +Bool dmxBEDestroyWindow(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + + if (pWinPriv->window) { + XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window); + pWinPriv->window = (Window)0; + return TRUE; + } + + return FALSE; +} + +/** Destroy \a pWindow on the back-end server. If any RENDER pictures + were created, destroy them as well. */ +Bool dmxDestroyWindow(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Bool ret = TRUE; + Bool needSync = FALSE; +#ifdef GLXEXT + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); +#endif + + DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen); + + /* Destroy any picture list associated with this window */ + needSync |= dmxDestroyPictureList(pWindow); + + /* Destroy window on back-end server */ + needSync |= dmxBEDestroyWindow(pWindow); + if (needSync) dmxSync(dmxScreen, FALSE); + +#ifdef GLXEXT + if (pWinPriv->swapGroup && pWinPriv->windowDestroyed) + pWinPriv->windowDestroyed(pWindow); +#endif + + if (pScreen->DestroyWindow) + ret = pScreen->DestroyWindow(pWindow); + + DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen); + + return ret; +} + +/** Change the position of \a pWindow to be \a x, \a y. */ +Bool dmxPositionWindow(WindowPtr pWindow, int x, int y) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Bool ret = TRUE; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + unsigned int m; + XWindowChanges c; + + DMX_UNWRAP(PositionWindow, dmxScreen, pScreen); +#if 0 + if (pScreen->PositionWindow) + ret = pScreen->PositionWindow(pWindow, x, y); +#endif + + /* Determine if the window is completely off the visible portion of + the screen */ + pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); + + /* If the window is now on-screen and it is mapped and it has not + been created yet, create it and map it */ + if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { + dmxCreateAndRealizeWindow(pWindow, TRUE); + } else if (pWinPriv->window) { + /* Position window on back-end server */ + m = CWX | CWY | CWWidth | CWHeight; + c.x = pWindow->origin.x - wBorderWidth(pWindow); + c.y = pWindow->origin.y - wBorderWidth(pWindow); + c.width = pWindow->drawable.width; + c.height = pWindow->drawable.height; + if (pWindow->drawable.class != InputOnly) { + m |= CWBorderWidth; + c.border_width = pWindow->borderWidth; + } + + XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); + dmxSync(dmxScreen, False); + } + + DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen); + + return ret; +} + +static void dmxDoChangeWindowAttributes(WindowPtr pWindow, + unsigned long *mask, + XSetWindowAttributes *attribs) +{ + dmxPixPrivPtr pPixPriv; + + if (*mask & CWBackPixmap) { + switch (pWindow->backgroundState) { + case None: + attribs->background_pixmap = None; + break; + + case ParentRelative: + attribs->background_pixmap = ParentRelative; + break; + + case BackgroundPixmap: + pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->background.pixmap); + attribs->background_pixmap = pPixPriv->pixmap; + break; + + case BackgroundPixel: + *mask &= ~CWBackPixmap; + break; + } + } + + if (*mask & CWBackPixel) { + if (pWindow->backgroundState == BackgroundPixel) + attribs->background_pixel = pWindow->background.pixel; + else + *mask &= ~CWBackPixel; + } + + if (*mask & CWBorderPixmap) { + if (pWindow->borderIsPixel) + *mask &= ~CWBorderPixmap; + else { + pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->border.pixmap); + attribs->border_pixmap = pPixPriv->pixmap; + } + } + + if (*mask & CWBorderPixel) { + if (pWindow->borderIsPixel) + attribs->border_pixel = pWindow->border.pixel; + else + *mask &= ~CWBorderPixel; + } + + if (*mask & CWBitGravity) + attribs->bit_gravity = pWindow->bitGravity; + + if (*mask & CWWinGravity) + *mask &= ~CWWinGravity; /* Handled by dix */ + + if (*mask & CWBackingStore) + *mask &= ~CWBackingStore; /* Backing store not supported */ + + if (*mask & CWBackingPlanes) + *mask &= ~CWBackingPlanes; /* Backing store not supported */ + + if (*mask & CWBackingPixel) + *mask &= ~CWBackingPixel; /* Backing store not supported */ + + if (*mask & CWOverrideRedirect) + attribs->override_redirect = pWindow->overrideRedirect; + + if (*mask & CWSaveUnder) + *mask &= ~CWSaveUnder; /* Save unders not supported */ + + if (*mask & CWEventMask) + *mask &= ~CWEventMask; /* Events are handled by dix */ + + if (*mask & CWDontPropagate) + *mask &= ~CWDontPropagate; /* Events are handled by dix */ + + if (*mask & CWColormap) { + ColormapPtr pCmap; + dmxColormapPrivPtr pCmapPriv; + + pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP); + pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap); + attribs->colormap = pCmapPriv->cmap; + } + + if (*mask & CWCursor) + *mask &= ~CWCursor; /* Handled by the cursor code */ +} + +/** Change the window attributes of \a pWindow. */ +Bool dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Bool ret = TRUE; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + XSetWindowAttributes attribs; + + DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen); +#if 0 + if (pScreen->ChangeWindowAttributes) + ret = pScreen->ChangeWindowAttributes(pWindow, mask); +#endif + + /* Change window attribs on back-end server */ + dmxDoChangeWindowAttributes(pWindow, &mask, &attribs); + + /* Save mask for lazy window creation optimization */ + pWinPriv->attribMask |= mask; + + if (mask && pWinPriv->window) { + XChangeWindowAttributes(dmxScreen->beDisplay, pWinPriv->window, + mask, &attribs); + dmxSync(dmxScreen, False); + } + + DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen, + pScreen); + + return ret; +} + +/** Realize \a pWindow on the back-end server. If the lazy window + * creation optimization is enabled, the window is only realized when + * it at least partially overlaps the screen. */ +Bool dmxRealizeWindow(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Bool ret = TRUE; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + + DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen); +#if 0 + if (pScreen->RealizeWindow) + ret = pScreen->RealizeWindow(pWindow); +#endif + + /* Determine if the window is completely off the visible portion of + the screen */ + pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); + + /* If the window hasn't been created and it's not offscreen, then + create it */ + if (!pWinPriv->window && !pWinPriv->offscreen) { + dmxCreateAndRealizeWindow(pWindow, FALSE); + } + + if (pWinPriv->window) { + /* Realize window on back-end server */ + XMapWindow(dmxScreen->beDisplay, pWinPriv->window); + dmxSync(dmxScreen, False); + } + + /* Let the other functions know that the window is now mapped */ + pWinPriv->mapped = TRUE; + + DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen); + + dmxUpdateWindowInfo(DMX_UPDATE_REALIZE, pWindow); + return ret; +} + +/** Unrealize \a pWindow on the back-end server. */ +Bool dmxUnrealizeWindow(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Bool ret = TRUE; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + + DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen); +#if 0 + if (pScreen->UnrealizeWindow) + ret = pScreen->UnrealizeWindow(pWindow); +#endif + + if (pWinPriv->window) { + /* Unrealize window on back-end server */ + XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window); + dmxSync(dmxScreen, False); + } + + /* When unrealized (i.e., unmapped), the window is always considered + off of the visible portion of the screen */ + pWinPriv->offscreen = TRUE; + pWinPriv->mapped = FALSE; + +#ifdef GLXEXT + if (pWinPriv->swapGroup && pWinPriv->windowUnmapped) + pWinPriv->windowUnmapped(pWindow); +#endif + + DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen); + + dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE, pWindow); + return ret; +} + +static void dmxDoRestackWindow(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + WindowPtr pNextSib = pWindow->nextSib; + unsigned int m; + XWindowChanges c; + + if (pNextSib == NullWindow) { + /* Window is at the bottom of the stack */ + m = CWStackMode; + c.sibling = (Window)0; + c.stack_mode = Below; + XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); + } else { + /* Window is not at the bottom of the stack */ + dmxWinPrivPtr pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib); + + /* Handle case where siblings have not yet been created due to + lazy window creation optimization by first finding the next + sibling in the sibling list that has been created (if any) + and then putting the current window just above that sibling, + and if no next siblings have been created yet, then put it at + the bottom of the stack (since it might have a previous + sibling that should be above it). */ + while (!pNextSibPriv->window) { + pNextSib = pNextSib->nextSib; + if (pNextSib == NullWindow) { + /* Window is at the bottom of the stack */ + m = CWStackMode; + c.sibling = (Window)0; + c.stack_mode = Below; + XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); + return; + } + pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib); + } + + m = CWStackMode | CWSibling; + c.sibling = pNextSibPriv->window; + c.stack_mode = Above; + XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); + } +} + +/** Handle window restacking. The actual restacking occurs in + * #dmxDoRestackWindow(). */ +void dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + + DMX_UNWRAP(RestackWindow, dmxScreen, pScreen); +#if 0 + if (pScreen->RestackWindow) + pScreen->RestackWindow(pWindow, pOldNextSib); +#endif + + if (pOldNextSib != pWindow->nextSib) { + /* Track restacking for lazy window creation optimization */ + pWinPriv->restacked = TRUE; + + /* Restack window on back-end server */ + if (pWinPriv->window) { + dmxDoRestackWindow(pWindow); + dmxSync(dmxScreen, False); + } + } + + DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen); + dmxUpdateWindowInfo(DMX_UPDATE_RESTACK, pWindow); +} + +static Bool dmxWindowExposurePredicate(Display *dpy, XEvent *ev, XPointer ptr) +{ + return (ev->type == Expose && ev->xexpose.window == *(Window *)ptr); +} + +/** Handle exposures on \a pWindow. Since window exposures are handled + * in DMX, the events that are generated by the back-end server are + * redundant, so we eat them here. */ +void dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn, + RegionPtr other_exposed) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + XEvent ev; + + DMX_UNWRAP(WindowExposures, dmxScreen, pScreen); + + dmxSync(dmxScreen, False); + + if (pWinPriv->window) { + while (XCheckIfEvent(dmxScreen->beDisplay, &ev, + dmxWindowExposurePredicate, + (XPointer)&pWinPriv->window)) { + /* Handle expose events -- this should not be necessary + since the base window in which the root window was + created is guaranteed to be on top (override_redirect), + so we should just swallow these events. If for some + reason the window is not on top, then we'd need to + collect these events and send them to the client later + (e.g., during the block handler as Xnest does). */ + } + } + +#if 1 + if (pScreen->WindowExposures) + pScreen->WindowExposures(pWindow, prgn, other_exposed); +#endif + DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen); +} + +/** Move \a pWindow on the back-end server. Determine whether or not it + * is on or offscreen, and realize it if it is newly on screen and the + * lazy window creation optimization is enabled. */ +void dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + unsigned int m; + XWindowChanges c; + + DMX_UNWRAP(CopyWindow, dmxScreen, pScreen); +#if 0 + if (pScreen->CopyWindow) + pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc); +#endif + + /* Determine if the window is completely off the visible portion of + the screen */ + pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); + + /* If the window is now on-screen and it is mapped and it has not + been created yet, create it and map it */ + if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { + dmxCreateAndRealizeWindow(pWindow, TRUE); + } else if (pWinPriv->window) { + /* Move window on back-end server */ + m = CWX | CWY | CWWidth | CWHeight; + c.x = pWindow->origin.x - wBorderWidth(pWindow); + c.y = pWindow->origin.y - wBorderWidth(pWindow); + c.width = pWindow->drawable.width; + c.height = pWindow->drawable.height; + + XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); + dmxSync(dmxScreen, False); + } + + DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen); + dmxUpdateWindowInfo(DMX_UPDATE_COPY, pWindow); +} + +/** Resize \a pWindow on the back-end server. Determine whether or not + * it is on or offscreen, and realize it if it is newly on screen and + * the lazy window creation optimization is enabled. */ +void dmxResizeWindow(WindowPtr pWindow, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + dmxWinPrivPtr pSibPriv; + unsigned int m; + XWindowChanges c; + + if (pSib) + pSibPriv = DMX_GET_WINDOW_PRIV(pSib); + + DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen); +#if 1 + if (pScreen->ResizeWindow) + pScreen->ResizeWindow(pWindow, x, y, w, h, pSib); +#endif + + /* Determine if the window is completely off the visible portion of + the screen */ + pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow); + + /* If the window is now on-screen and it is mapped and it has not + been created yet, create it and map it */ + if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) { + dmxCreateAndRealizeWindow(pWindow, TRUE); + } else if (pWinPriv->window) { + /* Handle resizing on back-end server */ + m = CWX | CWY | CWWidth | CWHeight; + c.x = pWindow->origin.x - wBorderWidth(pWindow); + c.y = pWindow->origin.y - wBorderWidth(pWindow); + c.width = pWindow->drawable.width; + c.height = pWindow->drawable.height; + + XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); + dmxSync(dmxScreen, False); + } + + DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen); + dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow); +} + +/** Reparent \a pWindow on the back-end server. */ +void dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent); + + DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen); +#if 0 + if (pScreen->ReparentWindow) + pScreen->ReparentWindow(pWindow, pPriorParent); +#endif + + if (pWinPriv->window) { + if (!pParentPriv->window) { + dmxCreateAndRealizeWindow(pWindow->parent, FALSE); + } + + /* Handle reparenting on back-end server */ + XReparentWindow(dmxScreen->beDisplay, pWinPriv->window, + pParentPriv->window, + pWindow->origin.x - wBorderWidth(pWindow), + pWindow->origin.x - wBorderWidth(pWindow)); + dmxSync(dmxScreen, False); + } + + DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen); + dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow); +} + +/** Change border width for \a pWindow to \a width pixels. */ +void dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + unsigned int m; + XWindowChanges c; + + DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen); +#if 1 + if (pScreen->ChangeBorderWidth) + pScreen->ChangeBorderWidth(pWindow, width); +#endif + + /* NOTE: Do we need to check for on/off screen here? */ + + if (pWinPriv->window) { + /* Handle border width change on back-end server */ + m = CWBorderWidth; + c.border_width = width; + + XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c); + dmxSync(dmxScreen, False); + } + + DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen); +} + +static void dmxDoSetShape(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + int nBox; + BoxPtr pBox; + int nRect; + XRectangle *pRect; + XRectangle *pRectFirst; + + /* First, set the bounding shape */ + if (wBoundingShape(pWindow)) { + pBox = REGION_RECTS(wBoundingShape(pWindow)); + nRect = nBox = REGION_NUM_RECTS(wBoundingShape(pWindow)); + pRectFirst = pRect = malloc(nRect * sizeof(*pRect)); + while (nBox--) { + pRect->x = pBox->x1; + pRect->y = pBox->y1; + pRect->width = pBox->x2 - pBox->x1; + pRect->height = pBox->y2 - pBox->y1; + pBox++; + pRect++; + } + XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window, + ShapeBounding, 0, 0, + pRectFirst, nRect, + ShapeSet, YXBanded); + free(pRectFirst); + } else { + XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window, + ShapeBounding, 0, 0, None, ShapeSet); + } + + /* Next, set the clip shape */ + if (wClipShape(pWindow)) { + pBox = REGION_RECTS(wClipShape(pWindow)); + nRect = nBox = REGION_NUM_RECTS(wClipShape(pWindow)); + pRectFirst = pRect = malloc(nRect * sizeof(*pRect)); + while (nBox--) { + pRect->x = pBox->x1; + pRect->y = pBox->y1; + pRect->width = pBox->x2 - pBox->x1; + pRect->height = pBox->y2 - pBox->y1; + pBox++; + pRect++; + } + XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window, + ShapeClip, 0, 0, + pRectFirst, nRect, + ShapeSet, YXBanded); + free(pRectFirst); + } else { + XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window, + ShapeClip, 0, 0, None, ShapeSet); + } + + if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) { + ErrorF("Input selected for window %x on Screen %d\n", + (unsigned int)pWinPriv->window, pScreen->myNum); + } +} + +/** Set shape of \a pWindow on the back-end server. */ +void dmxSetShape(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow); + + DMX_UNWRAP(SetShape, dmxScreen, pScreen); +#if 1 + if (pScreen->SetShape) + pScreen->SetShape(pWindow); +#endif + + if (pWinPriv->window) { + /* Handle setting the current shape on the back-end server */ + dmxDoSetShape(pWindow); + dmxSync(dmxScreen, False); + } else { + pWinPriv->isShaped = TRUE; + } + + DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen); +} diff --git a/xorg-server/hw/dmx/doc/dmx.sgml b/xorg-server/hw/dmx/doc/dmx.sgml index ef66d1195..4342c2fce 100644 --- a/xorg-server/hw/dmx/doc/dmx.sgml +++ b/xorg-server/hw/dmx/doc/dmx.sgml @@ -1,2778 +1,2777 @@ - -
- - - Distributed Multihead X design - <author>Kevin E. Martin, David H. Dawes, and Rickard E. Faith - <date>29 June 2004 (created 25 July 2001) - <abstract> - This document covers the motivation, background, design, and - implementation of the distributed multihead X (DMX) system. It - is a living document and describes the current design and - implementation details of the DMX system. As the project - progresses, this document will be continually updated to reflect - the changes in the code and/or design. <it>Copyright 2001 by VA - Linux Systems, Inc., Fremont, California. Copyright 2001-2004 - by Red Hat, Inc., Raleigh, North Carolina</it> - </abstract> - - <!-- Table of contents --> - <toc> - -<!-- Begin the document --> -<sect>Introduction - -<sect1>The Distributed Multihead X Server - -<p>Current Open Source multihead solutions are limited to a single -physical machine. A single X server controls multiple display devices, -which can be arranged as independent heads or unified into a single -desktop (with Xinerama). These solutions are limited to the number of -physical devices that can co-exist in a single machine (e.g., due to the -number of AGP/PCI slots available for graphics cards). Thus, large -tiled displays are not currently possible. The work described in this -paper will eliminate the requirement that the display devices reside in -the same physical machine. This will be accomplished by developing a -front-end proxy X server that will control multiple back-end X servers -that make up the large display. - -<p>The overall structure of the distributed multihead X (DMX) project is -as follows: A single front-end X server will act as a proxy to a set of -back-end X servers, which handle all of the visible rendering. X -clients will connect to the front-end server just as they normally would -to a regular X server. The front-end server will present an abstracted -view to the client of a single large display. This will ensure that all -standard X clients will continue to operate without modification -(limited, as always, by the visuals and extensions provided by the X -server). Clients that are DMX-aware will be able to use an extension to -obtain information about the back-end servers (e.g., for placement of -pop-up windows, window alignments by the window manager, etc.). - -<p>The architecture of the DMX server is divided into two main sections: -input (e.g., mouse and keyboard events) and output (e.g., rendering and -windowing requests). Each of these are describe briefly below, and the -rest of this design document will describe them in greater detail. - -<p>The DMX server can receive input from three general types of input -devices: "local" devices that are physically attached to the machine on -which DMX is running, "backend" devices that are physically attached to -one or more of the back-end X servers (and that generate events via the -X protocol stream from the backend), and "console" devices that can be -abstracted from any non-back-end X server. Backend and console devices -are treated differently because the pointer device on the back-end X -server also controls the location of the hardware X cursor. Full -support for XInput extension devices is provided. - -<p>Rendering requests will be accepted by the front-end server; however, -rendering to visible windows will be broken down as needed and sent to -the appropriate back-end server(s) via X11 library calls for actual -rendering. The basic framework will follow a Xnest-style approach. GC -state will be managed in the front-end server and sent to the -appropriate back-end server(s) as required. Pixmap rendering will (at -least initially) be handled by the front-end X server. Windowing -requests (e.g., ordering, mapping, moving, etc.) will handled in the -front-end server. If the request requires a visible change, the -windowing operation will be translated into requests for the appropriate -back-end server(s). Window state will be mirrored in the back-end -server(s) as needed. - -<sect1>Layout of Paper - -<p>The next section describes the general development plan that was -actually used for implementation. The final section discusses -outstanding issues at the conclusion of development. The first appendix -provides low-level technical detail that may be of interest to those -intimately familiar with the X server architecture. The final appendix -describes the four phases of development that were performed during the -first two years of development. - -<p>The final year of work was divided into 9 tasks that are not -described in specific sections of this document. The major tasks during -that time were the enhancement of the reconfiguration ability added in -Phase IV, addition of support for a dynamic number of back-end displays -(instead of a hard-coded limit), and the support for back-end display -and input removal and addition. This work is mentioned in this paper, -but is not covered in detail. - -<!-- ============================================================ --> -<sect>Development plan - -<p>This section describes the development plan from approximately June -2001 through July 2003. - -<sect1>Bootstrap code - -<p>To allow for rapid development of the DMX server by multiple -developers during the first development stage, the problem will be -broken down into three tasks: the overall DMX framework, back-end -rendering services and input device handling services. However, before -the work begins on these tasks, a simple framework that each developer -could use was implemented to bootstrap the development effort. This -framework renders to a single back-end server and provides dummy input -devices (i.e., the keyboard and mouse). The simple back-end rendering -service was implemented using the shadow framebuffer support currently -available in the XFree86 environment. - -<p>Using this bootstrapping framework, each developer has been able to -work on each of the tasks listed above independently as follows: the -framework will be extended to handle arbitrary back-end server -configurations; the back-end rendering services will be transitioned to -the more efficient Xnest-style implementation; and, an input device -framework to handle various input devices via the input extension will -be developed. - -<p>Status: The boot strap code is complete. <!-- August 2001 --> - - -<sect1>Input device handling - -<p>An X server (including the front-end X server) requires two core -input devices -- a keyboard and a pointer (mouse). These core devices -are handled and required by the core X11 protocol. Additional types of -input devices may be attached and utilized via the XInput extension. -These are usually referred to as ``XInput extension devices'', - -<p>There are some options as to how the front-end X server gets its core -input devices: - -<enum> - <item>Local Input. The physical input devices (e.g., keyboard and - mouse) can be attached directly to the front-end X server. In this - case, the keyboard and mouse on the machine running the front-end X - server will be used. The front-end will have drivers to read the - raw input from those devices and convert it into the required X - input events (e.g., key press/release, pointer button press/release, - pointer motion). The front-end keyboard driver will keep track of - keyboard properties such as key and modifier mappings, autorepeat - state, keyboard sound and led state. Similarly the front-end - pointer driver will keep track if pointer properties such as the - button mapping and movement acceleration parameters. With this - option, input is handled fully in the front-end X server, and the - back-end X servers are used in a display-only mode. This option was - implemented and works for a limited number of Linux-specific - devices. Adding additional local input devices for other - architectures is expected to be relatively simple. - - <p>The following options are available for implementing local input - devices: - - <enum> - <item>The XFree86 X server has modular input drivers that could - be adapted for this purpose. The mouse driver supports a wide - range of mouse types and interfaces, as well as a range of - Operating System platforms. The keyboard driver in XFree86 is - not currently as modular as the mouse driver, but could be made - so. The XFree86 X server also has a range of other input - drivers for extended input devices such as tablets and touch - screens. Unfortunately, the XFree86 drivers are generally - complex, often simultaneously providing support for multiple - devices across multiple architectures; and rely so heavily on - XFree86-specific helper-functions, that this option was not - pursued. - - - <item>The <tt/kdrive/ X server in XFree86 has built-in drivers that - support PS/2 mice and keyboard under Linux. The mouse driver - can indirectly handle other mouse types if the Linux utility - <tt/gpm/ is used as to translate the native mouse protocol into - PS/2 mouse format. These drivers could be adapted and built in - to the front-end X server if this range of hardware and OS - support is sufficient. While much simpler than the XFree86 - drivers, the <tt/kdrive/ drivers were not used for the DMX - implementation. - - <item>Reimplementation of keyboard and mouse drivers from - scratch for the DMX framework. Because keyboard and mouse - drivers are relatively trivial to implement, this pathway was - selected. Other drivers in the X source tree were referenced, - and significant contributions from other drivers are noted in - the DMX source code. - </enum> - - <item>Backend Input. The front-end can make use of the core input - devices attached to one or more of the back-end X servers. Core - input events from multiple back-ends are merged into a single input - event stream. This can work sanely when only a single set of input - devices is used at any given time. The keyboard and pointer state - will be handled in the front-end, with changes propagated to the - back-end servers as needed. This option was implemented and works - well. Because the core pointer on a back-end controls the hardware - mouse on that back-end, core pointers cannot be treated as XInput - extension devices. However, all back-end XInput extensions devices - can be mapped to either DMX core or DMX XInput extension devices. - - <item>Console Input. The front-end server could create a console - window that is displayed on an X server independent of the back-end - X servers. This console window could display things like the - physical screen layout, and the front-end could get its core input - events from events delivered to the console window. This option was - implemented and works well. To help the human navigate, window - outlines are also displayed in the console window. Further, console - windows can be used as either core or XInput extension devices. - - <item>Other options were initially explored, but they were all - partial subsets of the options listed above and, hence, are - irrelevant. - -</enum> - -<p>Although extended input devices are not specifically mentioned in the -Distributed X requirements, the options above were all implemented so -that XInput extension devices were supported. - -<p>The bootstrap code (Xdmx) had dummy input devices, and these are -still supported in the final version. These do the necessary -initialization to satisfy the X server's requirements for core pointer -and keyboard devices, but no input events are ever generated. - -<p>Status: The input code is complete. Because of the complexity of the -XFree86 input device drivers (and their heavy reliance on XFree86 -infrastructure), separate low-level device drivers were implemented for -Xdmx. The following kinds of drivers are supported (in general, the -devices can be treated arbitrarily as "core" input devices or as XInput -"extension" devices; and multiple instances of different kinds of -devices can be simultaneously available): - <enum> - <item> A "dummy" device drive that never generates events. - - <item> "Local" input is from the low-level hardware on which the - Xdmx binary is running. This is the only area where using the - XFree86 driver infrastructure would have been helpful, and then - only partially, since good support for generic USB devices does - not yet exist in XFree86 (in any case, XFree86 and kdrive driver - code was used where possible). Currently, the following local - devices are supported under Linux (porting to other operating - systems should be fairly straightforward): - <itemize> - <item>Linux keyboard - <item>Linux serial mouse (MS) - <item>Linux PS/2 mouse - <item>USB keyboard - <item>USB mouse - <item>USB generic device (e.g., joystick, gamepad, etc.) - </itemize> - - <item> "Backend" input is taken from one or more of the back-end - displays. In this case, events are taken from the back-end X - server and are converted to Xdmx events. Care must be taken so - that the sprite moves properly on the display from which input - is being taken. - - <item> "Console" input is taken from an X window that Xdmx - creates on the operator's display (i.e., on the machine running - the Xdmx binary). When the operator's mouse is inside the - console window, then those events are converted to Xdmx events. - Several special features are available: the console can display - outlines of windows that are on the Xdmx display (to facilitate - navigation), the cursor can be confined to the console, and a - "fine" mode can be activated to allow very precise cursor - positioning. - </enum> - - -<!-- May 2002; July 2003 --> - -<sect1>Output device handling - -<p>The output of the DMX system displays rendering and windowing -requests across multiple screens. The screens are typically arranged in -a grid such that together they represent a single large display. - -<p>The output section of the DMX code consists of two parts. The first -is in the front-end proxy X server (Xdmx), which accepts client -connections, manages the windows, and potentially renders primitives but -does not actually display any of the drawing primitives. The second -part is the back-end X server(s), which accept commands from the -front-end server and display the results on their screens. - -<sect2>Initialization - -<p>The DMX front-end must first initialize its screens by connecting to -each of the back-end X servers and collecting information about each of -these screens. However, the information collected from the back-end X -servers might be inconsistent. Handling these cases can be difficult -and/or inefficient. For example, a two screen system has one back-end X -server running at 16bpp while the second is running at 32bpp. -Converting rendering requests (e.g., XPutImage() or XGetImage() -requests) to the appropriate bit depth can be very time consuming. -Analyzing these cases to determine how or even if it is possible to -handle them is required. The current Xinerama code handles many of -these cases (e.g., in PanoramiXConsolidate()) and will be used as a -starting point. In general, the best solution is to use homogeneous X -servers and display devices. Using back-end servers with the same depth -is a requirement of the final DMX implementation. - -<p>Once this screen consolidation is finished, the relative position of -each back-end X server's screen in the unified screen is initialized. A -full-screen window is opened on each of the back-end X servers, and the -cursor on each screen is turned off. The final DMX implementation can -also make use of a partial-screen window, or multiple windows per -back-end screen. - -<sect2>Handling rendering requests - -<p>After initialization, X applications connect to the front-end server. -There are two possible implementations of how rendering and windowing -requests are handled in the DMX system: - -<enum> - <item>A shadow framebuffer is used in the front-end server as the - render target. In this option, all protocol requests are completely - handled in the front-end server. All state and resources are - maintained in the front-end including a shadow copy of the entire - framebuffer. The framebuffers attached to the back-end servers are - updated by XPutImage() calls with data taken directly from the - shadow framebuffer. - - <p>This solution suffers from two main problems. First, it does not - take advantage of any accelerated hardware available in the system. - Second, the size of the XPutImage() calls can be quite large and - thus will be limited by the bandwidth available. - - <p>The initial DMX implementation used a shadow framebuffer by - default. - - <item>Rendering requests are sent to each back-end server for - handling (as is done in the Xnest server described above). In this - option, certain protocol requests are handled in the front-end - server and certain requests are repackaged and then sent to the - back-end servers. The framebuffer is distributed across the - multiple back-end servers. Rendering to the framebuffer is handled - on each back-end and can take advantage of any acceleration - available on the back-end servers' graphics display device. State - is maintained both in the front and back-end servers. - - <p>This solution suffers from two main drawbacks. First, protocol - requests are sent to all back-end servers -- even those that will - completely clip the rendering primitive -- which wastes bandwidth - and processing time. Second, state is maintained both in the front- - and back-end servers. These drawbacks are not as severe as in - option 1 (above) and can either be overcome through optimizations or - are acceptable. Therefore, this option will be used in the final - implementation. - - <p>The final DMX implementation defaults to this mechanism, but also - supports the shadow framebuffer mechanism. Several optimizations - were implemented to eliminate the drawbacks of the default - mechanism. These optimizations are described the section below and - in Phase II of the Development Results (see appendix). - -</enum> - -<p>Status: Both the shadow framebuffer and Xnest-style code is complete. -<!-- May 2002 --> - - -<sect1>Optimizing DMX - -<p>Initially, the Xnest-style solution's performance will be measured -and analyzed to determine where the performance bottlenecks exist. -There are four main areas that will be addressed. - -<p>First, to obtain reasonable interactivity with the first development -phase, XSync() was called after each protocol request. The XSync() -function flushes any pending protocol requests. It then waits for the -back-end to process the request and send a reply that the request has -completed. This happens with each back-end server and performance -greatly suffers. As a result of the way XSync() is called in the first -development phase, the batching that the X11 library performs is -effectively defeated. The XSync() call usage will be analyzed and -optimized by batching calls and performing them at regular intervals, -except where interactivity will suffer (e.g., on cursor movements). - -<p>Second, the initial Xnest-style solution described above sends the -repackaged protocol requests to all back-end servers regardless of -whether or not they would be completely clipped out. The requests that -are trivially rejected on the back-end server wastes the limited -bandwidth available. By tracking clipping changes in the DMX X server's -windowing code (e.g., by opening, closing, moving or resizing windows), -we can determine whether or not back-end windows are visible so that -trivial tests in the front-end server's GC ops drawing functions can -eliminate these unnecessary protocol requests. - -<p>Third, each protocol request will be analyzed to determine if it is -possible to break the request into smaller pieces at display boundaries. -The initial ones to be analyzed are put and get image requests since -they will require the greatest bandwidth to transmit data between the -front and back-end servers. Other protocol requests will be analyzed -and those that will benefit from breaking them into smaller requests -will be implemented. - -<p>Fourth, an extension is being considered that will allow font glyphs to -be transferred from the front-end DMX X server to each back-end server. -This extension will permit the front-end to handle all font requests and -eliminate the requirement that all back-end X servers share the exact -same fonts as the front-end server. We are investigating the -feasibility of this extension during this development phase. - -<p>Other potential optimizations will be determined from the performance -analysis. - -<p>Please note that in our initial design, we proposed optimizing BLT -operations (e.g., XCopyArea() and window moves) by developing an -extension that would allow individual back-end servers to directly copy -pixel data to other back-end servers. This potential optimization was -in response to the simple image movement implementation that required -potentially many calls to GetImage() and PutImage(). However, the -current Xinerama implementation handles these BLT operations -differently. Instead of copying data to and from screens, they generate -expose events -- just as happens in the case when a window is moved from -off a screen to on screen. This approach saves the limited bandwidth -available between front and back-end servers and is being standardized -with Xinerama. It also eliminates the potential setup problems and -security issues resulting from having each back-end server open -connections to all other back-end servers. Therefore, we suggest -accepting Xinerama's expose event solution. - -<p>Also note that the approach proposed in the second and third -optimizations might cause backing store algorithms in the back-end to be -defeated, so a DMX X server configuration flag will be added to disable -these optimizations. - -<p>Status: The optimizations proposed above are complete. It was -determined that the using the xfs font server was sufficient and -creating a new mechanism to pass glyphs was redundant; therefore, the -fourth optimization proposed above was not included in DMX. -<!-- September 2002 --> - - -<sect1>DMX X extension support - -<p>The DMX X server keeps track of all the windowing information on the -back-end X servers, but does not currently export this information to -any client applications. An extension will be developed to pass the -screen information and back-end window IDs to DMX-aware clients. These -clients can then use this information to directly connect to and render -to the back-end windows. Bypassing the DMX X server allows DMX-aware -clients to break up complex rendering requests on their own and send -them directly to the windows on the back-end server's screens. An -example of a client that can make effective use of this extension is -Chromium. - -<p>Status: The extension, as implemented, is fully documented in -"Client-to-Server DMX Extension to the X Protocol". Future changes -might be required based on feedback and other proposed enhancements to -DMX. Currently, the following facilities are supported: -<enum> - <item> - Screen information (clipping rectangle for each screen relative - to the virtual screen) - <item> - Window information (window IDs and clipping information for each - back-end window that corresponds to each DMX window) - <item> - Input device information (mappings from DMX device IDs to - back-end device IDs) - <item> - Force window creation (so that a client can override the - server-side lazy window creation optimization) - <item> - Reconfiguration (so that a client can request that a screen - position be changed) - <item> - Addition and removal of back-end servers and back-end and - console inputs. -</enum> -<!-- September 2002; July 2003 --> - - -<sect1>Common X extension support - -<p>The XInput, XKeyboard and Shape extensions are commonly used -extensions to the base X11 protocol. XInput allows multiple and -non-standard input devices to be accessed simultaneously. These input -devices can be connected to either the front-end or back-end servers. -XKeyboard allows much better keyboard mappings control. Shape adds -support for arbitrarily shaped windows and is used by various window -managers. Nearly all potential back-end X servers make these extensions -available, and support for each one will be added to the DMX system. - -<p>In addition to the extensions listed above, support for the X -Rendering extension (Render) is being developed. Render adds digital -image composition to the rendering model used by the X Window System. -While this extension is still under development by Keith Packard of HP, -support for the current version will be added to the DMX system. - -<p>Support for the XTest extension was added during the first -development phase. - -<!-- WARNING: this list is duplicated in the Phase IV discussion --> -<p>Status: The following extensions are supported and are discussed in -more detail in Phase IV of the Development Results (see appendix): - BIG-REQUESTS, - DEC-XTRAP, - DMX, - DPMS, - Extended-Visual-Information, - GLX, - LBX, - RECORD, - RENDER, - SECURITY, - SHAPE, - SYNC, - X-Resource, - XC-APPGROUP, - XC-MISC, - XFree86-Bigfont, - XINERAMA, - XInputExtension, - XKEYBOARD, and - XTEST. -<!-- November 2002; updated February 2003, July 2003 --> - -<sect1>OpenGL support - -<p>OpenGL support using the Mesa code base exists in XFree86 release 4 -and later. Currently, the direct rendering infrastructure (DRI) -provides accelerated OpenGL support for local clients and unaccelerated -OpenGL support (i.e., software rendering) is provided for non-local -clients. - -<p>The single head OpenGL support in XFree86 4.x will be extended to use -the DMX system. When the front and back-end servers are on the same -physical hardware, it is possible to use the DRI to directly render to -the back-end servers. First, the existing DRI will be extended to -support multiple display heads, and then to support the DMX system. -OpenGL rendering requests will be direct rendering to each back-end X -server. The DRI will request the screen layout (either from the -existing Xinerama extension or a DMX-specific extension). Support for -synchronized swap buffers will also be added (on hardware that supports -it). Note that a single front-end server with a single back-end server -on the same physical machine can emulate accelerated indirect rendering. - -<p>When the front and back-end servers are on different physical -hardware or are using non-XFree86 4.x X servers, a mechanism to render -primitives across the back-end servers will be provided. There are -several options as to how this can be implemented. - -<enum> - <item>The existing OpenGL support in each back-end server can be - used by repackaging rendering primitives and sending them to each - back-end server. This option is similar to the unoptimized - Xnest-style approach mentioned above. Optimization of this solution - is beyond the scope of this project and is better suited to other - distributed rendering systems. - - <item>Rendering to a pixmap in the front-end server using the - current XFree86 4.x code, and then displaying to the back-ends via - calls to XPutImage() is another option. This option is similar to - the shadow frame buffer approach mentioned above. It is slower and - bandwidth intensive, but has the advantage that the back-end servers - are not required to have OpenGL support. -</enum> - -<p>These, and other, options will be investigated in this phase of the -work. - -<p>Work by others have made Chromium DMX-aware. Chromium will use the -DMX X protocol extension to obtain information about the back-end -servers and will render directly to those servers, bypassing DMX. - -<p>Status: OpenGL support by the glxProxy extension was implemented by -SGI and has been integrated into the DMX code base. -<!-- May 2003--> - - -<!-- ============================================================ --> -<sect>Current issues - -<p>In this sections the current issues are outlined that require further -investigation. - -<sect1>Fonts - -<p>The font path and glyphs need to be the same for the front-end and -each of the back-end servers. Font glyphs could be sent to the back-end -servers as necessary but this would consume a significant amount of -available bandwidth during font rendering for clients that use many -different fonts (e.g., Netscape). Initially, the font server (xfs) will -be used to provide the fonts to both the front-end and back-end servers. -Other possibilities will be investigated during development. - -<sect1>Zero width rendering primitives - -<p>To allow pixmap and on-screen rendering to be pixel perfect, all -back-end servers must render zero width primitives exactly the same as -the front-end renders the primitives to pixmaps. For those back-end -servers that do not exactly match, zero width primitives will be -automatically converted to one width primitives. This can be handled in -the front-end server via the GC state. - -<sect1>Output scaling - -<p>With very large tiled displays, it might be difficult to read the -information on the standard X desktop. In particular, the cursor can be -easily lost and fonts could be difficult to read. Automatic primitive -scaling might prove to be very useful. We will investigate the -possibility of scaling the cursor and providing a set of alternate -pre-scaled fonts to replace the standard fonts that many applications -use (e.g., fixed). Other options for automatic scaling will also be -investigated. - -<sect1>Per-screen colormaps - -<p>Each screen's default colormap in the set of back-end X servers -should be able to be adjusted via a configuration utility. This support -is would allow the back-end screens to be calibrated via custom gamma -tables. On 24-bit systems that support a DirectColor visual, this type -of correction can be accommodated. One possible implementation would be -to advertise to X client of the DMX server a TrueColor visual while -using DirectColor visuals on the back-end servers to implement this type -of color correction. Other options will be investigated. - -<!-- ============================================================ --> -<appendix> - -<sect>Background - -<p>This section describes the existing Open Source architectures that -can be used to handle multiple screens and upon which this development -project is based. This section was written before the implementation -was finished, and may not reflect actual details of the implementation. -It is left for historical interest only. - -<sect1>Core input device handling - -<p>The following is a description of how core input devices are handled -by an X server. - -<sect2>InitInput() - -<p>InitInput() is a DDX function that is called at the start of each -server generation from the X server's main() function. Its purpose is -to determine what input devices are connected to the X server, register -them with the DIX and MI layers, and initialize the input event queue. -InitInput() does not have a return value, but the X server will abort if -either a core keyboard device or a core pointer device are not -registered. Extended input (XInput) devices can also be registered in -InitInput(). - -<p>InitInput() usually has implementation specific code to determine -which input devices are available. For each input device it will be -using, it calls AddInputDevice(): - -<descrip> -<tag/AddInputDevice()/ This DIX function allocates the device structure, -registers a callback function (which handles device init, close, on and -off), and returns the input handle, which can be treated as opaque. It -is called once for each input device. -</descrip> - -<p>Once input handles for core keyboard and core pointer devices have -been obtained from AddInputDevice(), they are registered as core devices -by calling RegisterPointerDevice() and RegisterKeyboardDevice(). Each -of these should be called once. If both core devices are not -registered, then the X server will exit with a fatal error when it -attempts to start the input devices in InitAndStartDevices(), which is -called directly after InitInput() (see below). - -<descrip> -<tag/Register{Pointer,Keyboard}Device()/ These DIX functions take a -handle returned from AddInputDevice() and initialize the core input -device fields in inputInfo, and initialize the input processing and grab -functions for each core input device. -</descrip> - -<p>The core pointer device is then registered with the miPointer code -(which does the high level cursor handling). While this registration -is not necessary for correct miPointer operation in the current XFree86 -code, it is still done mostly for compatibility reasons. - -<descrip> -<tag/miRegisterPointerDevice()/ This MI function registers the core -pointer's input handle with with the miPointer code. -</descrip> - -<p>The final part of InitInput() is the initialization of the input -event queue handling. In most cases, the event queue handling provided -in the MI layer is used. The primary XFree86 X server uses its own -event queue handling to support some special cases related to the XInput -extension and the XFree86-specific DGA extension. For our purposes, the -MI event queue handling should be suitable. It is initialized by -calling mieqInit(): - -<descrip> -<tag/mieqInit()/ This MI function initializes the MI event queue for the -core devices, and is passed the public component of the input handles -for the two core devices. -</descrip> - -<p>If a wakeup handler is required to deliver synchronous input -events, it can be registered here by calling the DIX function -RegisterBlockAndWakeupHandlers(). (See the devReadInput() description -below.) - -<sect2>InitAndStartDevices() - -<p>InitAndStartDevices() is a DIX function that is called immediately -after InitInput() from the X server's main() function. Its purpose is -to initialize each input device that was registered with -AddInputDevice(), enable each input device that was successfully -initialized, and create the list of enabled input devices. Once each -registered device is processed in this way, the list of enabled input -devices is checked to make sure that both a core keyboard device and -core pointer device were registered and successfully enabled. If not, -InitAndStartDevices() returns failure, and results in the the X server -exiting with a fatal error. - -<p>Each registered device is initialized by calling its callback -(dev->deviceProc) with the DEVICE_INIT argument: - -<descrip> -<tag/(*dev->deviceProc)(dev, DEVICE_INIT)/ This function initializes the -device structs with core information relevant to the device. - -<p>For pointer devices, this means specifying the number of buttons, -default button mapping, the function used to get motion events (usually -miPointerGetMotionEvents()), the function used to change/control the -core pointer motion parameters (acceleration and threshold), and the -motion buffer size. - -<p>For keyboard devices, this means specifying the keycode range, -default keycode to keysym mapping, default modifier mapping, and the -functions used to sound the keyboard bell and modify/control the -keyboard parameters (LEDs, bell pitch and duration, key click, which -keys are auto-repeating, etc). -</descrip> - -<p>Each initialized device is enabled by calling EnableDevice(): - -<descrip> -<tag/EnableDevice()/ EnableDevice() calls the device callback with -DEVICE_ON: - <descrip> - <tag/(*dev->deviceProc)(dev, DEVICE_ON)/ This typically opens and - initializes the relevant physical device, and when appropriate, - registers the device's file descriptor (or equivalent) as a valid - input source. - </descrip> - - <p>EnableDevice() then adds the device handle to the X server's - global list of enabled devices. -</descrip> - -<p>InitAndStartDevices() then verifies that a valid core keyboard and -pointer has been initialized and enabled. It returns failure if either -are missing. - -<sect2>devReadInput() - -<p>Each device will have some function that gets called to read its -physical input. These may be called in a number of different ways. In -the case of synchronous I/O, they will be called from a DDX -wakeup-handler that gets called after the server detects that new input is -available. In the case of asynchronous I/O, they will be called from a -(SIGIO) signal handler triggered when new input is available. This -function should do at least two things: make sure that input events get -enqueued, and make sure that the cursor gets moved for motion events -(except if these are handled later by the driver's own event queue -processing function, which cannot be done when using the MI event queue -handling). - -<p>Events are queued by calling mieqEnqueue(): - -<descrip> -<tag/mieqEnqueue()/ This MI function is used to add input events to the -event queue. It is simply passed the event to be queued. -</descrip> - -<p>The cursor position should be updated when motion events are -enqueued, by calling either miPointerAbsoluteCursor() or -miPointerDeltaCursor(): - -<descrip> -<tag/miPointerAbsoluteCursor()/ This MI function is used to move the -cursor to the absolute coordinates provided. -<tag/miPointerDeltaCursor()/ This MI function is used to move the cursor -relative to its current position. -</descrip> - -<sect2>ProcessInputEvents() - -<p>ProcessInputEvents() is a DDX function that is called from the X -server's main dispatch loop when new events are available in the input -event queue. It typically processes the enqueued events, and updates -the cursor/pointer position. It may also do other DDX-specific event -processing. - -<p>Enqueued events are processed by mieqProcessInputEvents() and passed -to the DIX layer for transmission to clients: - -<descrip> -<tag/mieqProcessInputEvents()/ This function processes each event in the -event queue, and passes it to the device's input processing function. -The DIX layer provides default functions to do this processing, and they -handle the task of getting the events passed back to the relevant -clients. -<tag/miPointerUpdate()/ This function resynchronized the cursor position -with the new pointer position. It also takes care of moving the cursor -between screens when needed in multi-head configurations. -</descrip> - - -<sect2>DisableDevice() - -<p>DisableDevice is a DIX function that removes an input device from the -list of enabled devices. The result of this is that the device no -longer generates input events. The device's data structures are kept in -place, and disabling a device like this can be reversed by calling -EnableDevice(). DisableDevice() may be called from the DDX when it is -desirable to do so (e.g., the XFree86 server does this when VT -switching). Except for special cases, this is not normally called for -core input devices. - -<p>DisableDevice() calls the device's callback function with -<tt/DEVICE_OFF/: - -<descrip> -<tag/(*dev->deviceProc)(dev, DEVICE_OFF)/ This typically closes the -relevant physical device, and when appropriate, unregisters the device's -file descriptor (or equivalent) as a valid input source. -</descrip> - -<p>DisableDevice() then removes the device handle from the X server's -global list of enabled devices. - - -<sect2>CloseDevice() - -<p>CloseDevice is a DIX function that removes an input device from the -list of available devices. It disables input from the device and frees -all data structures associated with the device. This function is -usually called from CloseDownDevices(), which is called from main() at -the end of each server generation to close all input devices. - -<p>CloseDevice() calls the device's callback function with -<tt/DEVICE_CLOSE/: - -<descrip> -<tag/(*dev->deviceProc)(dev, DEVICE_CLOSE)/ This typically closes the -relevant physical device, and when appropriate, unregisters the device's -file descriptor (or equivalent) as a valid input source. If any device -specific data structures were allocated when the device was initialized, -they are freed here. -</descrip> - -<p>CloseDevice() then frees the data structures that were allocated -for the device when it was registered/initialized. - - -<sect2>LegalModifier() -<!-- dmx/dmxinput.c - currently returns TRUE --> -<p>LegalModifier() is a required DDX function that can be used to -restrict which keys may be modifier keys. This seems to be present for -historical reasons, so this function should simply return TRUE -unconditionally. - - -<sect1>Output handling - -<p>The following sections describe the main functions required to -initialize, use and close the output device(s) for each screen in the X -server. - -<sect2>InitOutput() - -<p>This DDX function is called near the start of each server generation -from the X server's main() function. InitOutput()'s main purpose is to -initialize each screen and fill in the global screenInfo structure for -each screen. It is passed three arguments: a pointer to the screenInfo -struct, which it is to initialize, and argc and argv from main(), which -can be used to determine additional configuration information. - -<p>The primary tasks for this function are outlined below: - -<enum> - <item><bf/Parse configuration info:/ The first task of InitOutput() - is to parses any configuration information from the configuration - file. In addition to the XF86Config file, other configuration - information can be taken from the command line. The command line - options can be gathered either in InitOutput() or earlier in the - ddxProcessArgument() function, which is called by - ProcessCommandLine(). The configuration information determines the - characteristics of the screen(s). For example, in the XFree86 X - server, the XF86Config file specifies the monitor information, the - screen resolution, the graphics devices and slots in which they are - located, and, for Xinerama, the screens' layout. - - <item><bf/Initialize screen info:/ The next task is to initialize - the screen-dependent internal data structures. For example, part of - what the XFree86 X server does is to allocate its screen and pixmap - private indices, probe for graphics devices, compare the probed - devices to the ones listed in the XF86Config file, and add the ones that - match to the internal xf86Screens[] structure. - - <item><bf/Set pixmap formats:/ The next task is to initialize the - screenInfo's image byte order, bitmap bit order and bitmap scanline - unit/pad. The screenInfo's pixmap format's depth, bits per pixel - and scanline padding is also initialized at this stage. - - <item><bf/Unify screen info:/ An optional task that might be done at - this stage is to compare all of the information from the various - screens and determines if they are compatible (i.e., if the set of - screens can be unified into a single desktop). This task has - potential to be useful to the DMX front-end server, if Xinerama's - PanoramiXConsolidate() function is not sufficient. -</enum> - -<p>Once these tasks are complete, the valid screens are known and each -of these screens can be initialized by calling AddScreen(). - -<sect2>AddScreen() - -<p>This DIX function is called from InitOutput(), in the DDX layer, to -add each new screen to the screenInfo structure. The DDX screen -initialization function and command line arguments (i.e., argc and argv) -are passed to it as arguments. - -<p>This function first allocates a new Screen structure and any privates -that are required. It then initializes some of the fields in the Screen -struct and sets up the pixmap padding information. Finally, it calls -the DDX screen initialization function ScreenInit(), which is described -below. It returns the number of the screen that were just added, or -1 -if there is insufficient memory to add the screen or if the DDX screen -initialization fails. - -<sect2>ScreenInit() - -<p>This DDX function initializes the rest of the Screen structure with -either generic or screen-specific functions (as necessary). It also -fills in various screen attributes (e.g., width and height in -millimeters, black and white pixel values). - -<p>The screen init function usually calls several functions to perform -certain screen initialization functions. They are described below: - -<descrip> -<tag/{mi,*fb}ScreenInit()/ The DDX layer's ScreenInit() function usually -calls another layer's ScreenInit() function (e.g., miScreenInit() or -fbScreenInit()) to initialize the fallbacks that the DDX driver does not -specifically handle. - -<p>After calling another layer's ScreenInit() function, any -screen-specific functions either wrap or replace the other layer's -function pointers. If a function is to be wrapped, each of the old -function pointers from the other layer are stored in a screen private -area. Common functions to wrap are CloseScreen() and SaveScreen(). - -<tag/miInitializeBackingStore()/ This MI function initializes the -screen's backing storage functions, which are used to save areas of -windows that are currently covered by other windows. - -<tag/miDCInitialize()/ This MI function initializes the MI cursor -display structures and function pointers. If a hardware cursor is used, -the DDX layer's ScreenInit() function will wrap additional screen and -the MI cursor display function pointers. -</descrip> - -<p>Another common task for ScreenInit() function is to initialize the -output device state. For example, in the XFree86 X server, the -ScreenInit() function saves the original state of the video card and -then initializes the video mode of the graphics device. - -<sect2>CloseScreen() - -<p>This function restores any wrapped screen functions (and in -particular the wrapped CloseScreen() function) and restores the state of -the output device to its original state. It should also free any -private data it created during the screen initialization. - -<sect2>GC operations - -<p>When the X server is requested to render drawing primitives, it does -so by calling drawing functions through the graphics context's operation -function pointer table (i.e., the GCOps functions). These functions -render the basic graphics operations such as drawing rectangles, lines, -text or copying pixmaps. Default routines are provided either by the MI -layer, which draws indirectly through a simple span interface, or by the -framebuffer layers (e.g., CFB, MFB, FB), which draw directly to a -linearly mapped frame buffer. - -<p>To take advantage of special hardware on the graphics device, -specific GCOps functions can be replaced by device specific code. -However, many times the graphics devices can handle only a subset of the -possible states of the GC, so during graphics context validation, -appropriate routines are selected based on the state and capabilities of -the hardware. For example, some graphics hardware can accelerate single -pixel width lines with certain dash patterns. Thus, for dash patterns -that are not supported by hardware or for width 2 or greater lines, the -default routine is chosen during GC validation. - -<p>Note that some pointers to functions that draw to the screen are -stored in the Screen structure. They include GetImage(), GetSpans(), -PaintWindowBackground(), PaintWindowBorder(), CopyWindow() and -RestoreAreas(). - -<sect2>Xnest - -<p>The Xnest X server is a special proxy X server that relays the X -protocol requests that it receives to a ``real'' X server that then -processes the requests and displays the results, if applicable. To the X -applications, Xnest appears as if it is a regular X server. However, -Xnest is both server to the X application and client of the real X -server, which will actually handle the requests. - -<p>The Xnest server implements all of the standard input and output -initialization steps outlined above. - -<descrip> -<tag/InitOutput()/ Xnest takes its configuration information from -command line arguments via ddxProcessArguments(). This information -includes the real X server display to connect to, its default visual -class, the screen depth, the Xnest window's geometry, etc. Xnest then -connects to the real X server and gathers visual, colormap, depth and -pixmap information about that server's display, creates a window on that -server, which will be used as the root window for Xnest. - -<p>Next, Xnest initializes its internal data structures and uses the -data from the real X server's pixmaps to initialize its own pixmap -formats. Finally, it calls AddScreen(xnestOpenScreen, argc, argv) to -initialize each of its screens. - -<tag/ScreenInit()/ Xnest's ScreenInit() function is called -xnestOpenScreen(). This function initializes its screen's depth and -visual information, and then calls miScreenInit() to set up the default -screen functions. It then calls miInitializeBackingStore() and -miDCInitialize() to initialize backing store and the software cursor. -Finally, it replaces many of the screen functions with its own -functions that repackage and send the requests to the real X server to -which Xnest is attached. - -<tag/CloseScreen()/ This function frees its internal data structure -allocations. Since it replaces instead of wrapping screen functions, -there are no function pointers to unwrap. This can potentially lead to -problems during server regeneration. - -<tag/GC operations/ The GC operations in Xnest are very simple since -they leave all of the drawing to the real X server to which Xnest is -attached. Each of the GCOps takes the request and sends it to the -real X server using standard Xlib calls. For example, the X -application issues a XDrawLines() call. This function turns into a -protocol request to Xnest, which calls the xnestPolylines() function -through Xnest's GCOps function pointer table. The xnestPolylines() -function is only a single line, which calls XDrawLines() using the same -arguments that were passed into it. Other GCOps functions are very -similar. Two exceptions to the simple GCOps functions described above -are the image functions and the BLT operations. - -<p>The image functions, GetImage() and PutImage(), must use a temporary -image to hold the image to be put of the image that was just grabbed -from the screen while it is in transit to the real X server or the -client. When the image has been transmitted, the temporary image is -destroyed. - -<p>The BLT operations, CopyArea() and CopyPlane(), handle not only the -copy function, which is the same as the simple cases described above, -but also the graphics exposures that result when the GC's graphics -exposure bit is set to True. Graphics exposures are handled in a helper -function, xnestBitBlitHelper(). This function collects the exposure -events from the real X server and, if any resulting in regions being -exposed, then those regions are passed back to the MI layer so that it -can generate exposure events for the X application. -</descrip> - -<p>The Xnest server takes its input from the X server to which it is -connected. When the mouse is in the Xnest server's window, keyboard and -mouse events are received by the Xnest server, repackaged and sent back -to any client that requests those events. - -<sect2>Shadow framebuffer - -<p>The most common type of framebuffer is a linear array memory that -maps to the video memory on the graphics device. However, accessing -that video memory over an I/O bus (e.g., ISA or PCI) can be slow. The -shadow framebuffer layer allows the developer to keep the entire -framebuffer in main memory and copy it back to video memory at regular -intervals. It also has been extended to handle planar video memory and -rotated framebuffers. - -<p>There are two main entry points to the shadow framebuffer code: - -<descrip> -<tag/shadowAlloc(width, height, bpp)/ This function allocates the in -memory copy of the framebuffer of size width*height*bpp. It returns a -pointer to that memory, which will be used by the framebuffer -ScreenInit() code during the screen's initialization. - -<tag/shadowInit(pScreen, updateProc, windowProc)/ This function -initializes the shadow framebuffer layer. It wraps several screen -drawing functions, and registers a block handler that will update the -screen. The updateProc is a function that will copy the damaged regions -to the screen, and the windowProc is a function that is used when the -entire linear video memory range cannot be accessed simultaneously so -that only a window into that memory is available (e.g., when using the -VGA aperture). -</descrip> - -<p>The shadow framebuffer code keeps track of the damaged area of each -screen by calculating the bounding box of all drawing operations that -have occurred since the last screen update. Then, when the block handler -is next called, only the damaged portion of the screen is updated. - -<p>Note that since the shadow framebuffer is kept in main memory, all -drawing operations are performed by the CPU and, thus, no accelerated -hardware drawing operations are possible. - - -<sect1>Xinerama - -<p>Xinerama is an X extension that allows multiple physical screens -controlled by a single X server to appear as a single screen. Although -the extension allows clients to find the physical screen layout via -extension requests, it is completely transparent to clients at the core -X11 protocol level. The original public implementation of Xinerama came -from Digital/Compaq. XFree86 rewrote it, filling in some missing pieces -and improving both X11 core protocol compliance and performance. The -Xinerama extension will be passing through X.Org's standardization -process in the near future, and the sample implementation will be based -on this rewritten version. - -<p>The current implementation of Xinerama is based primarily in the DIX -(device independent) and MI (machine independent) layers of the X -server. With few exceptions the DDX layers do not need any changes to -support Xinerama. X server extensions often do need modifications to -provide full Xinerama functionality. - -<p>The following is a code-level description of how Xinerama functions. - -<p>Note: Because the Xinerama extension was originally called the -PanoramiX extension, many of the Xinerama functions still have the -PanoramiX prefix. - -<descrip> - <tag/PanoramiXExtensionInit()/ PanoramiXExtensionInit() is a - device-independent extension function that is called at the start of - each server generation from InitExtensions(), which is called from - the X server's main() function after all output devices have been - initialized, but before any input devices have been initialized. - - <p>PanoramiXNumScreens is set to the number of physical screens. If - only one physical screen is present, the extension is disabled, and - PanoramiXExtensionInit() returns without doing anything else. - - <p>The Xinerama extension is registered by calling AddExtension(). - - <p>A local per-screen array of data structures - (panoramiXdataPtr[]) - is allocated for each physical screen, and GC and Screen private - indexes are allocated, and both GC and Screen private areas are - allocated for each physical screen. These hold Xinerama-specific - per-GC and per-Screen data. Each screen's CreateGC and CloseScreen - functions are wrapped by XineramaCreateGC() and - XineramaCloseScreen() respectively. Some new resource classes are - created for Xinerama drawables and GCs, and resource types for - Xinerama windows, pixmaps and colormaps. - - <p>A region (XineramaScreenRegions[i]) is initialized for each - physical screen, and single region (PanoramiXScreenRegion) is - initialized to be the union of the screen regions. The - panoramiXdataPtr[] array is also initialized with the size and - origin of each screen. The relative positioning information for the - physical screens is taken from the array - dixScreenOrigins[], which - the DDX layer must initialize in InitOutput(). The bounds of the - combined screen is also calculated (PanoramiXPixWidth and - PanoramiXPixHeight). - - <p>The DIX layer has a list of function pointers - (ProcVector[]) that - holds the entry points for the functions that process core protocol - requests. The requests that Xinerama must intercept and break up - into physical screen-specific requests are wrapped. The original - set is copied to SavedProcVector[]. The types of requests - intercepted are Window requests, GC requests, colormap requests, - drawing requests, and some geometry-related requests. This wrapping - allows the bulk of the protocol request processing to be handled - transparently to the DIX layer. Some operations cannot be dealt with - in this way and are handled with Xinerama-specific code within the - DIX layer. - - <tag/PanoramiXConsolidate()/ PanoramiXConsolidate() is a - device-independent extension function that is called directly from - the X server's main() function after extensions and input/output - devices have been initialized, and before the root windows are - defined and initialized. - - <p>This function finds the set of depths (PanoramiXDepths[]) and - visuals (PanoramiXVisuals[]) - common to all of the physical screens. - PanoramiXNumDepths is set to the number of common depths, and - PanoramiXNumVisuals is set to the number of common visuals. - Resources are created for the single root window and the default - colormap. Each of these resources has per-physical screen entries. - - <tag/PanoramiXCreateConnectionBlock()/ PanoramiXConsolidate() is a - device-independent extension function that is called directly from - the X server's main() function after the per-physical screen root - windows are created. It is called instead of the standard DIX - CreateConnectionBlock() function. If this function returns FALSE, - the X server exits with a fatal error. This function will return - FALSE if no common depths were found in PanoramiXConsolidate(). - With no common depths, Xinerama mode is not possible. - - <p>The connection block holds the information that clients get when - they open a connection to the X server. It includes information - such as the supported pixmap formats, number of screens and the - sizes, depths, visuals, default colormap information, etc, for each - of the screens (much of information that <tt/xdpyinfo/ shows). The - connection block is initialized with the combined single screen - values that were calculated in the above two functions. - - <p>The Xinerama extension allows the registration of connection - block callback functions. The purpose of these is to allow other - extensions to do processing at this point. These callbacks can be - registered by calling XineramaRegisterConnectionBlockCallback() from - the other extension's ExtensionInit() function. Each registered - connection block callback is called at the end of - PanoramiXCreateConnectionBlock(). -</descrip> - -<sect2>Xinerama-specific changes to the DIX code - -<p>There are a few types of Xinerama-specific changes within the DIX -code. The main ones are described here. - -<p>Functions that deal with colormap or GC -related operations outside of -the intercepted protocol requests have a test added to only do the -processing for screen numbers > 0. This is because they are handled for -the single Xinerama screen and the processing is done once for screen 0. - -<p>The handling of motion events does some coordinate translation between -the physical screen's origin and screen zero's origin. Also, motion -events must be reported relative to the composite screen origin rather -than the physical screen origins. - -<p>There is some special handling for cursor, window and event processing -that cannot (either not at all or not conveniently) be done via the -intercepted protocol requests. A particular case is the handling of -pointers moving between physical screens. - -<sect2>Xinerama-specific changes to the MI code - -<p>The only Xinerama-specific change to the MI code is in miSendExposures() -to handle the coordinate (and window ID) translation for expose events. - -<sect2>Intercepted DIX core requests - -<p>Xinerama breaks up drawing requests for dispatch to each physical -screen. It also breaks up windows into pieces for each physical screen. -GCs are translated into per-screen GCs. Colormaps are replicated on -each physical screen. The functions handling the intercepted requests -take care of breaking the requests and repackaging them so that they can -be passed to the standard request handling functions for each screen in -turn. In addition, and to aid the repackaging, the information from -many of the intercepted requests is used to keep up to date the -necessary state information for the single composite screen. Requests -(usually those with replies) that can be satisfied completely from this -stored state information do not call the standard request handling -functions. - -<!-- ============================================================ --> - -<sect>Development Results - -<p>In this section the results of each phase of development are -discussed. This development took place between approximately June 2001 -and July 2003. - -<sect1>Phase I - -<p>The initial development phase dealt with the basic implementation -including the bootstrap code, which used the shadow framebuffer, and the -unoptimized implementation, based on an Xnest-style implementation. - -<sect2>Scope - -<p>The goal of Phase I is to provide fundamental functionality that can -act as a foundation for ongoing work: -<enum> - <item>Develop the proxy X server - <itemize> - <item>The proxy X server will operate on the X11 protocol and - relay requests as necessary to correctly perform the request. - <item>Work will be based on the existing work for Xinerama and - Xnest. - <item>Input events and windowing operations are handled in the - proxy server and rendering requests are repackaged and sent to - each of the back-end servers for display. - <item>The multiple screen layout (including support for - overlapping screens) will be user configurable via a - configuration file or through the configuration tool. - </itemize> - <item>Develop graphical configuration tool - <itemize> - <item>There will be potentially a large number of X servers to - configure into a single display. The tool will allow the user - to specify which servers are involved in the configuration and - how they should be laid out. - </itemize> - <item>Pass the X Test Suite - <itemize> - <item>The X Test Suite covers the basic X11 operations. All - tests known to succeed must correctly operate in the distributed - X environment. - </itemize> -</enum> - -<p>For this phase, the back-end X servers are assumed to be unmodified X -servers that do not support any DMX-related protocol extensions; future -optimization pathways are considered, but are not implemented; and the -configuration tool is assumed to rely only on libraries in the X source -tree (e.g., Xt). - -<sect2>Results - -<p>The proxy X server, Xdmx, was developed to distribute X11 protocol -requests to the set of back-end X servers. It opens a window on each -back-end server, which represents the part of the front-end's root -window that is visible on that screen. It mirrors window, pixmap and -other state in each back-end server. Drawing requests are sent to -either windows or pixmaps on each back-end server. This code is based -on Xnest and uses the existing Xinerama extension. - -<p>Input events can be taken from (1) devices attached to the back-end -server, (2) core devices attached directly to the Xdmx server, or (3) -from a ``console'' window on another X server. Events for these devices -are gathered, processed and delivered to clients attached to the Xdmx -server. - -<p>An intuitive configuration format was developed to help the user -easily configure the multiple back-end X servers. It was defined (see -grammar in Xdmx man page) and a parser was implemented that is used by -the Xdmx server and by a standalone xdmxconfig utility. The parsing -support was implemented such that it can be easily factored out of the X -source tree for use with other tools (e.g., vdl). Support for -converting legacy vdl-format configuration files to the DMX format is -provided by the vdltodmx utility. - -<p>Originally, the configuration file was going to be a subsection of -XFree86's XF86Config file, but that was not possible since Xdmx is a -completely separate X server. Thus, a separate config file format was -developed. In addition, a graphical configuration -tool, xdmxconfig, was developed to allow the user to create and arrange -the screens in the configuration file. The <bf/-configfile/ and <bf/-config/ -command-line options can be used to start Xdmx using a configuration -file. - -<p>An extension that enables remote input testing is required for the X -Test Suite to function. During this phase, this extension (XTEST) was -implemented in the Xdmx server. The results from running the X Test -Suite are described in detail below. - -<sect2>X Test Suite - - <sect3> Introduction - <p> - The X Test Suite contains tests that verify Xlib functions - operate correctly. The test suite is designed to run on a - single X server; however, since X applications will not be - able to tell the difference between the DMX server and a - standard X server, the X Test Suite should also run on the - DMX server. - <p> - The Xdmx server was tested with the X Test Suite, and the - existing failures are noted in this section. To put these - results in perspective, we first discuss expected X Test - failures and how errors in underlying systems can impact - Xdmx test results. - - <sect3>Expected Failures for a Single Head - <p> - A correctly implemented X server with a single screen is - expected to fail certain X Test tests. The following - well-known errors occur because of rounding error in the X - server code: - <verb> -XDrawArc: Tests 42, 63, 66, 73 -XDrawArcs: Tests 45, 66, 69, 76 - </verb> - <p> - The following failures occur because of the high-level X - server implementation: - <verb> -XLoadQueryFont: Test 1 -XListFontsWithInfo: Tests 3, 4 -XQueryFont: Tests 1, 2 - </verb> - <p> - The following test fails when running the X server as root - under Linux because of the way directory modes are - interpreted: - <verb> -XWriteBitmapFile: Test 3 - </verb> - <p> - Depending on the video card used for the back-end, other - failures may also occur because of bugs in the low-level - driver implementation. Over time, failures of this kind - are usually fixed by XFree86, but will show up in Xdmx - testing until then. - - <sect3>Expected Failures for Xinerama - <p> - Xinerama fails several X Test Suite tests because of - design decisions made for the current implementation of - Xinerama. Over time, many of these errors will be - corrected by XFree86 and the group working on a new - Xinerama implementation. Therefore, Xdmx will also share - X Suite Test failures with Xinerama. - <p> - We may be able to fix or work-around some of these - failures at the Xdmx level, but this will require - additional exploration that was not part of Phase I. - <p> - Xinerama is constantly improving, and the list of - Xinerama-related failures depends on XFree86 version and - the underlying graphics hardware. We tested with a - variety of hardware, including nVidia, S3, ATI Radeon, - and Matrox G400 (in dual-head mode). The list below - includes only those failures that appear to be from the - Xinerama layer, and does not include failures listed in - the previous section, or failures that appear to be from - the low-level graphics driver itself: - <p> - These failures were noted with multiple Xinerama - configurations: - <verb> -XCopyPlane: Tests 13, 22, 31 (well-known Xinerama implementation issue) -XSetFontPath: Test 4 -XGetDefault: Test 5 -XMatchVisualInfo: Test 1 - </verb> - <p> - These failures were noted only when using one dual-head - video card with a 4.2.99.x XFree86 server: - <verb> -XListPixmapFormats: Test 1 -XDrawRectangles: Test 45 - </verb> - <p> - These failures were noted only when using two video cards - from different vendors with a 4.1.99.x XFree86 server: - <verb> -XChangeWindowAttributes: Test 32 -XCreateWindow: Test 30 -XDrawLine: Test 22 -XFillArc: Test 22 -XChangeKeyboardControl: Tests 9, 10 -XRebindKeysym: Test 1 - </verb> - - <sect3>Additional Failures from Xdmx - <p> - When running Xdmx, no unexpected failures were noted. - Since the Xdmx server is based on Xinerama, we expect to - have most of the Xinerama failures present in the Xdmx - server. Similarly, since the Xdmx server must rely on the - low-level device drivers on each back-end server, we also - expect that Xdmx will exhibit most of the back-end - failures. Here is a summary: - <verb> -XListPixmapFormats: Test 1 (configuration dependent) -XChangeWindowAttributes: Test 32 -XCreateWindow: Test 30 -XCopyPlane: Test 13, 22, 31 -XSetFontPath: Test 4 -XGetDefault: Test 5 (configuration dependent) -XMatchVisualInfo: Test 1 -XRebindKeysym: Test 1 (configuration dependent) - </verb> - <p> - Note that this list is shorter than the combined list for - Xinerama because Xdmx uses different code paths to perform - some Xinerama operations. Further, some Xinerama failures - have been fixed in the XFree86 4.2.99.x CVS repository. - - <sect3>Summary and Future Work - <p> - Running the X Test Suite on Xdmx does not produce any - failures that cannot be accounted for by the underlying - Xinerama subsystem used by the front-end or by the - low-level device-driver code running on the back-end X - servers. The Xdmx server therefore is as ``correct'' as - possible with respect to the standard set of X Test Suite - tests. - <p> - During the following phases, we will continue to verify - Xdmx correctness using the X Test Suite. We may also use - other tests suites or write additional tests that run - under the X Test Suite that specifically verify the - expected behavior of DMX. - -<sect2>Fonts - -<p>In Phase I, fonts are handled directly by both the front-end and the -back-end servers, which is required since we must treat each back-end -server during this phase as a ``black box''. What this requires is that -<bf/the front- and back-end servers must share the exact same font -path/. There are two ways to help make sure that all servers share the -same font path: - -<enum> - <item>First, each server can be configured to use the same font - server. The font server, xfs, can be configured to serve fonts to - multiple X servers via TCP. - - <item>Second, each server can be configured to use the same font - path and either those font paths can be copied to each back-end - machine or they can be mounted (e.g., via NFS) on each back-end - machine. -</enum> - -<p>One additional concern is that a client program can set its own font -path, and if it does so, then that font path must be available on each -back-end machine. - -<p>The -fontpath command line option was added to allow users to -initialize the font path of the front end server. This font path is -propagated to each back-end server when the default font is loaded. If -there are any problems, an error message is printed, which will describe -the problem and list the current font path. For more information about -setting the font path, see the -fontpath option description in the man -page. - -<sect2>Performance - -<p>Phase I of development was not intended to optimize performance. Its -focus was on completely and correctly handling the base X11 protocol in -the Xdmx server. However, several insights were gained during Phase I, -which are listed here for reference during the next phase of -development. - -<enum> - <item>Calls to XSync() can slow down rendering since it requires a - complete round trip to and from a back-end server. This is - especially problematic when communicating over long haul networks. - <item>Sending drawing requests to only the screens that they overlap - should improve performance. -</enum> - -<sect2>Pixmaps - -<p>Pixmaps were originally expected to be handled entirely in the -front-end X server; however, it was found that this overly complicated -the rendering code and would have required sending potentially large -images to each back server that required them when copying from pixmap -to screen. Thus, pixmap state is mirrored in the back-end server just -as it is with regular window state. With this implementation, the same -rendering code that draws to windows can be used to draw to pixmaps on -the back-end server, and no large image transfers are required to copy -from pixmap to window. - -<!-- ============================================================ --> -<sect1>Phase II - -<p>The second phase of development concentrates on performance -optimizations. These optimizations are documented here, with -<tt/x11perf/ data to show how the optimizations improve performance. - -<p>All benchmarks were performed by running Xdmx on a dual processor -1.4GHz AMD Athlon machine with 1GB of RAM connecting over 100baseT to -two single-processor 1GHz Pentium III machines with 256MB of RAM and ATI -Rage 128 (RF) video cards. The front end was running Linux -2.4.20-pre1-ac1 and the back ends were running Linux 2.4.7-10 and -version 4.2.99.1 of XFree86 pulled from the XFree86 CVS repository on -August 7, 2002. All systems were running Red Hat Linux 7.2. - -<sect2>Moving from XFree86 4.1.99.1 to 4.2.0.0 - -<p>For phase II, the working source tree was moved to the branch tagged -with dmx-1-0-branch and was updated from version 4.1.99.1 (20 August -2001) of the XFree86 sources to version 4.2.0.0 (18 January 2002). -After this update, the following tests were noted to be more than 10% -faster: - <verb> -1.13 Fill 300x300 opaque stippled trapezoid (161x145 stipple) -1.16 Fill 1x1 tiled trapezoid (161x145 tile) -1.13 Fill 10x10 tiled trapezoid (161x145 tile) -1.17 Fill 100x100 tiled trapezoid (161x145 tile) -1.16 Fill 1x1 tiled trapezoid (216x208 tile) -1.20 Fill 10x10 tiled trapezoid (216x208 tile) -1.15 Fill 100x100 tiled trapezoid (216x208 tile) -1.37 Circulate Unmapped window (200 kids) - </verb> -And the following tests were noted to be more than 10% slower: - <verb> -0.88 Unmap window via parent (25 kids) -0.75 Circulate Unmapped window (4 kids) -0.79 Circulate Unmapped window (16 kids) -0.80 Circulate Unmapped window (25 kids) -0.82 Circulate Unmapped window (50 kids) -0.85 Circulate Unmapped window (75 kids) - </verb> -<p>These changes were not caused by any changes in the DMX system, and -may point to changes in the XFree86 tree or to tests that have more -"jitter" than most other <tt/x11perf/ tests. - -<sect2>Global changes - -<p>During the development of the Phase II DMX server, several global -changes were made. These changes were also compared with the Phase I -server. The following tests were noted to be more than 10% faster: - <verb> -1.13 Fill 300x300 opaque stippled trapezoid (161x145 stipple) -1.15 Fill 1x1 tiled trapezoid (161x145 tile) -1.13 Fill 10x10 tiled trapezoid (161x145 tile) -1.17 Fill 100x100 tiled trapezoid (161x145 tile) -1.16 Fill 1x1 tiled trapezoid (216x208 tile) -1.19 Fill 10x10 tiled trapezoid (216x208 tile) -1.15 Fill 100x100 tiled trapezoid (216x208 tile) -1.15 Circulate Unmapped window (4 kids) - </verb> - -<p>The following tests were noted to be more than 10% slower: - <verb> -0.69 Scroll 10x10 pixels -0.68 Scroll 100x100 pixels -0.68 Copy 10x10 from window to window -0.68 Copy 100x100 from window to window -0.76 Circulate Unmapped window (75 kids) -0.83 Circulate Unmapped window (100 kids) - </verb> - -<p>For the remainder of this analysis, the baseline of comparison will -be the Phase II deliverable with all optimizations disabled (unless -otherwise noted). This will highlight how the optimizations in -isolation impact performance. - -<sect2>XSync() Batching - -<p>During the Phase I implementation, XSync() was called after every -protocol request made by the DMX server. This provided the DMX server -with an interactive feel, but defeated X11's protocol buffering system -and introduced round-trip wire latency into every operation. During -Phase II, DMX was changed so that protocol requests are no longer -followed by calls to XSync(). Instead, the need for an XSync() is -noted, and XSync() calls are only made every 100mS or when the DMX -server specifically needs to make a call to guarantee interactivity. -With this new system, X11 buffers protocol as much as possible during a -100mS interval, and many unnecessary XSync() calls are avoided. - -<p>Out of more than 300 <tt/x11perf/ tests, 8 tests became more than 100 -times faster, with 68 more than 50X faster, 114 more than 10X faster, -and 181 more than 2X faster. See table below for summary. - -<p>The following tests were noted to be more than 10% slower with -XSync() batching on: - <verb> -0.88 500x500 tiled rectangle (161x145 tile) -0.89 Copy 500x500 from window to window - </verb> - -<sect2>Offscreen Optimization - -<p>Windows span one or more of the back-end servers' screens; however, -during Phase I development, windows were created on every back-end -server and every rendering request was sent to every window regardless -of whether or not that window was visible. With the offscreen -optimization, the DMX server tracks when a window is completely off of a -back-end server's screen and, in that case, it does not send rendering -requests to those back-end windows. This optimization saves bandwidth -between the front and back-end servers, and it reduces the number of -XSync() calls. The performance tests were run on a DMX system with only -two back-end servers. Greater performance gains will be had as the -number of back-end servers increases. - -<p>Out of more than 300 <tt/x11perf/ tests, 3 tests were at least twice as -fast, and 146 tests were at least 10% faster. Two tests were more than -10% slower with the offscreen optimization: - <verb> -0.88 Hide/expose window via popup (4 kids) -0.89 Resize unmapped window (75 kids) - </verb> - -<sect2>Lazy Window Creation Optimization - -<p>As mentioned above, during Phase I, windows were created on every -back-end server even if they were not visible on that back-end. With -the lazy window creation optimization, the DMX server does not create -windows on a back-end server until they are either visible or they -become the parents of a visible window. This optimization builds on the -offscreen optimization (described above) and requires it to be enabled. - -<p>The lazy window creation optimization works by creating the window -data structures in the front-end server when a client creates a window, -but delays creation of the window on the back-end server(s). A private -window structure in the DMX server saves the relevant window data and -tracks changes to the window's attributes and stacking order for later -use. The only times a window is created on a back-end server are (1) -when it is mapped and is at least partially overlapping the back-end -server's screen (tracked by the offscreen optimization), or (2) when the -window becomes the parent of a previously visible window. The first -case occurs when a window is mapped or when a visible window is copied, -moved or resized and now overlaps the back-end server's screen. The -second case occurs when starting a window manager after having created -windows to which the window manager needs to add decorations. - -<p>When either case occurs, a window on the back-end server is created -using the data saved in the DMX server's window private data structure. -The stacking order is then adjusted to correctly place the window on the -back-end and lastly the window is mapped. From this time forward, the -window is handled exactly as if the window had been created at the time -of the client's request. - -<p>Note that when a window is no longer visible on a back-end server's -screen (e.g., it is moved offscreen), the window is not destroyed; -rather, it is kept and reused later if the window once again becomes -visible on the back-end server's screen. Originally with this -optimization, destroying windows was implemented but was later rejected -because it increased bandwidth when windows were opaquely moved or -resized, which is common in many window managers. - -<p>The performance tests were run on a DMX system with only two back-end -servers. Greater performance gains will be had as the number of -back-end servers increases. - -<p>This optimization improved the following <tt/x11perf/ tests by more -than 10%: - <verb> -1.10 500x500 rectangle outline -1.12 Fill 100x100 stippled trapezoid (161x145 stipple) -1.20 Circulate Unmapped window (50 kids) -1.19 Circulate Unmapped window (75 kids) - </verb> - -<sect2>Subdividing Rendering Primitives - -<p>X11 imaging requests transfer significant data between the client and -the X server. During Phase I, the DMX server would then transfer the -image data to each back-end server. Even with the offscreen -optimization (above), these requests still required transferring -significant data to each back-end server that contained a visible -portion of the window. For example, if the client uses XPutImage() to -copy an image to a window that overlaps the entire DMX screen, then the -entire image is copied by the DMX server to every back-end server. - -<p>To reduce the amount of data transferred between the DMX server and -the back-end servers when XPutImage() is called, the image data is -subdivided and only the data that will be visible on a back-end server's -screen is sent to that back-end server. Xinerama already implements a -subdivision algorithm for XGetImage() and no further optimization was -needed. - -<p>Other rendering primitives were analyzed, but the time required to -subdivide these primitives was a significant proportion of the time -required to send the entire rendering request to the back-end server, so -this optimization was rejected for the other rendering primitives. - -<p>Again, the performance tests were run on a DMX system with only two -back-end servers. Greater performance gains will be had as the number -of back-end servers increases. - -<p>This optimization improved the following <tt/x11perf/ tests by more -than 10%: - <verb> -1.12 Fill 100x100 stippled trapezoid (161x145 stipple) -1.26 PutImage 10x10 square -1.83 PutImage 100x100 square -1.91 PutImage 500x500 square -1.40 PutImage XY 10x10 square -1.48 PutImage XY 100x100 square -1.50 PutImage XY 500x500 square -1.45 Circulate Unmapped window (75 kids) -1.74 Circulate Unmapped window (100 kids) - </verb> - -<p>The following test was noted to be more than 10% slower with this -optimization: - <verb> -0.88 10-pixel fill chord partial circle - </verb> - -<sect2>Summary of x11perf Data - -<p>With all of the optimizations on, 53 <tt/x11perf/ tests are more than -100X faster than the unoptimized Phase II deliverable, with 69 more than -50X faster, 73 more than 10X faster, and 199 more than twice as fast. -No tests were more than 10% slower than the unoptimized Phase II -deliverable. (Compared with the Phase I deliverable, only Circulate -Unmapped window (100 kids) was more than 10% slower than the Phase II -deliverable. As noted above, this test seems to have wider variability -than other <tt/x11perf/ tests.) - -<p>The following table summarizes relative <tt/x11perf/ test changes for -all optimizations individually and collectively. Note that some of the -optimizations have a synergistic effect when used together. - <verb> - -1: XSync() batching only -2: Off screen optimizations only -3: Window optimizations only -4: Subdivprims only -5: All optimizations - - 1 2 3 4 5 Operation ------- ---- ---- ---- ------ --------- - 2.14 1.85 1.00 1.00 4.13 Dot - 1.67 1.80 1.00 1.00 3.31 1x1 rectangle - 2.38 1.43 1.00 1.00 2.44 10x10 rectangle - 1.00 1.00 0.92 0.98 1.00 100x100 rectangle - 1.00 1.00 1.00 1.00 1.00 500x500 rectangle - 1.83 1.85 1.05 1.06 3.54 1x1 stippled rectangle (8x8 stipple) - 2.43 1.43 1.00 1.00 2.41 10x10 stippled rectangle (8x8 stipple) - 0.98 1.00 1.00 1.00 1.00 100x100 stippled rectangle (8x8 stipple) - 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (8x8 stipple) - 1.75 1.75 1.00 1.00 3.40 1x1 opaque stippled rectangle (8x8 stipple) - 2.38 1.42 1.00 1.00 2.34 10x10 opaque stippled rectangle (8x8 stipple) - 1.00 1.00 0.97 0.97 1.00 100x100 opaque stippled rectangle (8x8 stipple) - 1.00 1.00 1.00 1.00 0.99 500x500 opaque stippled rectangle (8x8 stipple) - 1.82 1.82 1.04 1.04 3.56 1x1 tiled rectangle (4x4 tile) - 2.33 1.42 1.00 1.00 2.37 10x10 tiled rectangle (4x4 tile) - 1.00 0.92 1.00 1.00 1.00 100x100 tiled rectangle (4x4 tile) - 1.00 1.00 1.00 1.00 1.00 500x500 tiled rectangle (4x4 tile) - 1.94 1.62 1.00 1.00 3.66 1x1 stippled rectangle (17x15 stipple) - 1.74 1.28 1.00 1.00 1.73 10x10 stippled rectangle (17x15 stipple) - 1.00 1.00 1.00 0.89 0.98 100x100 stippled rectangle (17x15 stipple) - 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (17x15 stipple) - 1.94 1.62 1.00 1.00 3.67 1x1 opaque stippled rectangle (17x15 stipple) - 1.69 1.26 1.00 1.00 1.66 10x10 opaque stippled rectangle (17x15 stipple) - 1.00 0.95 1.00 1.00 1.00 100x100 opaque stippled rectangle (17x15 stipple) - 1.00 1.00 1.00 1.00 0.97 500x500 opaque stippled rectangle (17x15 stipple) - 1.93 1.61 0.99 0.99 3.69 1x1 tiled rectangle (17x15 tile) - 1.73 1.27 1.00 1.00 1.72 10x10 tiled rectangle (17x15 tile) - 1.00 1.00 1.00 1.00 0.98 100x100 tiled rectangle (17x15 tile) - 1.00 1.00 0.97 0.97 1.00 500x500 tiled rectangle (17x15 tile) - 1.95 1.63 1.00 1.00 3.83 1x1 stippled rectangle (161x145 stipple) - 1.80 1.30 1.00 1.00 1.83 10x10 stippled rectangle (161x145 stipple) - 0.97 1.00 1.00 1.00 1.01 100x100 stippled rectangle (161x145 stipple) - 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (161x145 stipple) - 1.95 1.63 1.00 1.00 3.56 1x1 opaque stippled rectangle (161x145 stipple) - 1.65 1.25 1.00 1.00 1.68 10x10 opaque stippled rectangle (161x145 stipple) - 1.00 1.00 1.00 1.00 1.01 100x100 opaque stippled rectangle (161x145... - 1.00 1.00 1.00 1.00 0.97 500x500 opaque stippled rectangle (161x145... - 1.95 1.63 0.98 0.99 3.80 1x1 tiled rectangle (161x145 tile) - 1.67 1.26 1.00 1.00 1.67 10x10 tiled rectangle (161x145 tile) - 1.13 1.14 1.14 1.14 1.14 100x100 tiled rectangle (161x145 tile) - 0.88 1.00 1.00 1.00 0.99 500x500 tiled rectangle (161x145 tile) - 1.93 1.63 1.00 1.00 3.53 1x1 tiled rectangle (216x208 tile) - 1.69 1.26 1.00 1.00 1.66 10x10 tiled rectangle (216x208 tile) - 1.00 1.00 1.00 1.00 1.00 100x100 tiled rectangle (216x208 tile) - 1.00 1.00 1.00 1.00 1.00 500x500 tiled rectangle (216x208 tile) - 1.82 1.70 1.00 1.00 3.38 1-pixel line segment - 2.07 1.56 0.90 1.00 3.31 10-pixel line segment - 1.29 1.10 1.00 1.00 1.27 100-pixel line segment - 1.05 1.06 1.03 1.03 1.09 500-pixel line segment - 1.30 1.13 1.00 1.00 1.29 100-pixel line segment (1 kid) - 1.32 1.15 1.00 1.00 1.32 100-pixel line segment (2 kids) - 1.33 1.16 1.00 1.00 1.33 100-pixel line segment (3 kids) - 1.92 1.64 1.00 1.00 3.73 10-pixel dashed segment - 1.34 1.16 1.00 1.00 1.34 100-pixel dashed segment - 1.24 1.11 0.99 0.97 1.23 100-pixel double-dashed segment - 1.72 1.77 1.00 1.00 3.25 10-pixel horizontal line segment - 1.83 1.66 1.01 1.00 3.54 100-pixel horizontal line segment - 1.86 1.30 1.00 1.00 1.84 500-pixel horizontal line segment - 2.11 1.52 1.00 0.99 3.02 10-pixel vertical line segment - 1.21 1.10 1.00 1.00 1.20 100-pixel vertical line segment - 1.03 1.03 1.00 1.00 1.02 500-pixel vertical line segment - 4.42 1.68 1.00 1.01 4.64 10x1 wide horizontal line segment - 1.83 1.31 1.00 1.00 1.83 100x10 wide horizontal line segment - 1.07 1.00 0.96 1.00 1.07 500x50 wide horizontal line segment - 4.10 1.67 1.00 1.00 4.62 10x1 wide vertical line segment - 1.50 1.24 1.06 1.06 1.48 100x10 wide vertical line segment - 1.06 1.03 1.00 1.00 1.05 500x50 wide vertical line segment - 2.54 1.61 1.00 1.00 3.61 1-pixel line - 2.71 1.48 1.00 1.00 2.67 10-pixel line - 1.19 1.09 1.00 1.00 1.19 100-pixel line - 1.04 1.02 1.00 1.00 1.03 500-pixel line - 2.68 1.51 0.98 1.00 3.17 10-pixel dashed line - 1.23 1.11 0.99 0.99 1.23 100-pixel dashed line - 1.15 1.08 1.00 1.00 1.15 100-pixel double-dashed line - 2.27 1.39 1.00 1.00 2.23 10x1 wide line - 1.20 1.09 1.00 1.00 1.20 100x10 wide line - 1.04 1.02 1.00 1.00 1.04 500x50 wide line - 1.52 1.45 1.00 1.00 1.52 100x10 wide dashed line - 1.54 1.47 1.00 1.00 1.54 100x10 wide double-dashed line - 1.97 1.30 0.96 0.95 1.95 10x10 rectangle outline - 1.44 1.27 1.00 1.00 1.43 100x100 rectangle outline - 3.22 2.16 1.10 1.09 3.61 500x500 rectangle outline - 1.95 1.34 1.00 1.00 1.90 10x10 wide rectangle outline - 1.14 1.14 1.00 1.00 1.13 100x100 wide rectangle outline - 1.00 1.00 1.00 1.00 1.00 500x500 wide rectangle outline - 1.57 1.72 1.00 1.00 3.03 1-pixel circle - 1.96 1.35 1.00 1.00 1.92 10-pixel circle - 1.21 1.07 0.86 0.97 1.20 100-pixel circle - 1.08 1.04 1.00 1.00 1.08 500-pixel circle - 1.39 1.19 1.03 1.03 1.38 100-pixel dashed circle - 1.21 1.11 1.00 1.00 1.23 100-pixel double-dashed circle - 1.59 1.28 1.00 1.00 1.58 10-pixel wide circle - 1.22 1.12 0.99 1.00 1.22 100-pixel wide circle - 1.06 1.04 1.00 1.00 1.05 500-pixel wide circle - 1.87 1.84 1.00 1.00 1.85 100-pixel wide dashed circle - 1.90 1.93 1.01 1.01 1.90 100-pixel wide double-dashed circle - 2.13 1.43 1.00 1.00 2.32 10-pixel partial circle - 1.42 1.18 1.00 1.00 1.42 100-pixel partial circle - 1.92 1.85 1.01 1.01 1.89 10-pixel wide partial circle - 1.73 1.67 1.00 1.00 1.73 100-pixel wide partial circle - 1.36 1.95 1.00 1.00 2.64 1-pixel solid circle - 2.02 1.37 1.00 1.00 2.03 10-pixel solid circle - 1.19 1.09 1.00 1.00 1.19 100-pixel solid circle - 1.02 0.99 1.00 1.00 1.01 500-pixel solid circle - 1.74 1.28 1.00 0.88 1.73 10-pixel fill chord partial circle - 1.31 1.13 1.00 1.00 1.31 100-pixel fill chord partial circle - 1.67 1.31 1.03 1.03 1.72 10-pixel fill slice partial circle - 1.30 1.13 1.00 1.00 1.28 100-pixel fill slice partial circle - 2.45 1.49 1.01 1.00 2.71 10-pixel ellipse - 1.22 1.10 1.00 1.00 1.22 100-pixel ellipse - 1.09 1.04 1.00 1.00 1.09 500-pixel ellipse - 1.90 1.28 1.00 1.00 1.89 100-pixel dashed ellipse - 1.62 1.24 0.96 0.97 1.61 100-pixel double-dashed ellipse - 2.43 1.50 1.00 1.00 2.42 10-pixel wide ellipse - 1.61 1.28 1.03 1.03 1.60 100-pixel wide ellipse - 1.08 1.05 1.00 1.00 1.08 500-pixel wide ellipse - 1.93 1.88 1.00 1.00 1.88 100-pixel wide dashed ellipse - 1.94 1.89 1.01 1.00 1.94 100-pixel wide double-dashed ellipse - 2.31 1.48 1.00 1.00 2.67 10-pixel partial ellipse - 1.38 1.17 1.00 1.00 1.38 100-pixel partial ellipse - 2.00 1.85 0.98 0.97 1.98 10-pixel wide partial ellipse - 1.89 1.86 1.00 1.00 1.89 100-pixel wide partial ellipse - 3.49 1.60 1.00 1.00 3.65 10-pixel filled ellipse - 1.67 1.26 1.00 1.00 1.67 100-pixel filled ellipse - 1.06 1.04 1.00 1.00 1.06 500-pixel filled ellipse - 2.38 1.43 1.01 1.00 2.32 10-pixel fill chord partial ellipse - 2.06 1.30 1.00 1.00 2.05 100-pixel fill chord partial ellipse - 2.27 1.41 1.00 1.00 2.27 10-pixel fill slice partial ellipse - 1.98 1.33 1.00 0.97 1.97 100-pixel fill slice partial ellipse - 57.46 1.99 1.01 1.00 114.92 Fill 1x1 equivalent triangle - 56.94 1.98 1.01 1.00 73.89 Fill 10x10 equivalent triangle - 6.07 1.75 1.00 1.00 6.07 Fill 100x100 equivalent triangle - 51.12 1.98 1.00 1.00 102.81 Fill 1x1 trapezoid - 51.42 1.82 1.01 1.00 94.89 Fill 10x10 trapezoid - 6.47 1.80 1.00 1.00 6.44 Fill 100x100 trapezoid - 1.56 1.28 1.00 0.99 1.56 Fill 300x300 trapezoid - 51.27 1.97 0.96 0.97 102.54 Fill 1x1 stippled trapezoid (8x8 stipple) - 51.73 2.00 1.02 1.02 67.92 Fill 10x10 stippled trapezoid (8x8 stipple) - 5.36 1.72 1.00 1.00 5.36 Fill 100x100 stippled trapezoid (8x8 stipple) - 1.54 1.26 1.00 1.00 1.59 Fill 300x300 stippled trapezoid (8x8 stipple) - 51.41 1.94 1.01 1.00 102.82 Fill 1x1 opaque stippled trapezoid (8x8 stipple) - 50.71 1.95 0.99 1.00 65.44 Fill 10x10 opaque stippled trapezoid (8x8... - 5.33 1.73 1.00 1.00 5.36 Fill 100x100 opaque stippled trapezoid (8x8... - 1.58 1.25 1.00 1.00 1.58 Fill 300x300 opaque stippled trapezoid (8x8... - 51.56 1.96 0.99 0.90 103.68 Fill 1x1 tiled trapezoid (4x4 tile) - 51.59 1.99 1.01 1.01 62.25 Fill 10x10 tiled trapezoid (4x4 tile) - 5.38 1.72 1.00 1.00 5.38 Fill 100x100 tiled trapezoid (4x4 tile) - 1.54 1.25 1.00 0.99 1.58 Fill 300x300 tiled trapezoid (4x4 tile) - 51.70 1.98 1.01 1.01 103.98 Fill 1x1 stippled trapezoid (17x15 stipple) - 44.86 1.97 1.00 1.00 44.86 Fill 10x10 stippled trapezoid (17x15 stipple) - 2.74 1.56 1.00 1.00 2.73 Fill 100x100 stippled trapezoid (17x15 stipple) - 1.29 1.14 1.00 1.00 1.27 Fill 300x300 stippled trapezoid (17x15 stipple) - 51.41 1.96 0.96 0.95 103.39 Fill 1x1 opaque stippled trapezoid (17x15... - 45.14 1.96 1.01 1.00 45.14 Fill 10x10 opaque stippled trapezoid (17x15... - 2.68 1.56 1.00 1.00 2.68 Fill 100x100 opaque stippled trapezoid (17x15... - 1.26 1.10 1.00 1.00 1.28 Fill 300x300 opaque stippled trapezoid (17x15... - 51.13 1.97 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (17x15 tile) - 47.58 1.96 1.00 1.00 47.86 Fill 10x10 tiled trapezoid (17x15 tile) - 2.74 1.56 1.00 1.00 2.74 Fill 100x100 tiled trapezoid (17x15 tile) - 1.29 1.14 1.00 1.00 1.28 Fill 300x300 tiled trapezoid (17x15 tile) - 51.13 1.97 0.99 0.97 103.39 Fill 1x1 stippled trapezoid (161x145 stipple) - 45.14 1.97 1.00 1.00 44.29 Fill 10x10 stippled trapezoid (161x145 stipple) - 3.02 1.77 1.12 1.12 3.38 Fill 100x100 stippled trapezoid (161x145 stipple) - 1.31 1.13 1.00 1.00 1.30 Fill 300x300 stippled trapezoid (161x145 stipple) - 51.27 1.97 1.00 1.00 103.10 Fill 1x1 opaque stippled trapezoid (161x145... - 45.01 1.97 1.00 1.00 45.01 Fill 10x10 opaque stippled trapezoid (161x145... - 2.67 1.56 1.00 1.00 2.69 Fill 100x100 opaque stippled trapezoid (161x145.. - 1.29 1.13 1.00 1.01 1.27 Fill 300x300 opaque stippled trapezoid (161x145.. - 51.41 1.96 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (161x145 tile) - 45.01 1.96 0.98 1.00 45.01 Fill 10x10 tiled trapezoid (161x145 tile) - 2.62 1.36 1.00 1.00 2.69 Fill 100x100 tiled trapezoid (161x145 tile) - 1.27 1.13 1.00 1.00 1.22 Fill 300x300 tiled trapezoid (161x145 tile) - 51.13 1.98 1.00 1.00 103.39 Fill 1x1 tiled trapezoid (216x208 tile) - 45.14 1.97 1.01 0.99 45.14 Fill 10x10 tiled trapezoid (216x208 tile) - 2.62 1.55 1.00 1.00 2.71 Fill 100x100 tiled trapezoid (216x208 tile) - 1.28 1.13 1.00 1.00 1.20 Fill 300x300 tiled trapezoid (216x208 tile) - 50.71 1.95 1.00 1.00 54.70 Fill 10x10 equivalent complex polygon - 5.51 1.71 0.96 0.98 5.47 Fill 100x100 equivalent complex polygons - 8.39 1.97 1.00 1.00 16.75 Fill 10x10 64-gon (Convex) - 8.38 1.83 1.00 1.00 8.43 Fill 100x100 64-gon (Convex) - 8.50 1.96 1.00 1.00 16.64 Fill 10x10 64-gon (Complex) - 8.26 1.83 1.00 1.00 8.35 Fill 100x100 64-gon (Complex) - 14.09 1.87 1.00 1.00 14.05 Char in 80-char line (6x13) - 11.91 1.87 1.00 1.00 11.95 Char in 70-char line (8x13) - 11.16 1.85 1.01 1.00 11.10 Char in 60-char line (9x15) - 10.09 1.78 1.00 1.00 10.09 Char16 in 40-char line (k14) - 6.15 1.75 1.00 1.00 6.31 Char16 in 23-char line (k24) - 11.92 1.90 1.03 1.03 11.88 Char in 80-char line (TR 10) - 8.18 1.78 1.00 0.99 8.17 Char in 30-char line (TR 24) - 42.83 1.44 1.01 1.00 42.11 Char in 20/40/20 line (6x13, TR 10) - 27.45 1.43 1.01 1.01 27.45 Char16 in 7/14/7 line (k14, k24) - 12.13 1.85 1.00 1.00 12.05 Char in 80-char image line (6x13) - 10.00 1.84 1.00 1.00 10.00 Char in 70-char image line (8x13) - 9.18 1.83 1.00 1.00 9.12 Char in 60-char image line (9x15) - 9.66 1.82 0.98 0.95 9.66 Char16 in 40-char image line (k14) - 5.82 1.72 1.00 1.00 5.99 Char16 in 23-char image line (k24) - 8.70 1.80 1.00 1.00 8.65 Char in 80-char image line (TR 10) - 4.67 1.66 1.00 1.00 4.67 Char in 30-char image line (TR 24) - 84.43 1.47 1.00 1.00 124.18 Scroll 10x10 pixels - 3.73 1.50 1.00 0.98 3.73 Scroll 100x100 pixels - 1.00 1.00 1.00 1.00 1.00 Scroll 500x500 pixels - 84.43 1.51 1.00 1.00 134.02 Copy 10x10 from window to window - 3.62 1.51 0.98 0.98 3.62 Copy 100x100 from window to window - 0.89 1.00 1.00 1.00 1.00 Copy 500x500 from window to window - 57.06 1.99 1.00 1.00 88.64 Copy 10x10 from pixmap to window - 2.49 2.00 1.00 1.00 2.48 Copy 100x100 from pixmap to window - 1.00 0.91 1.00 1.00 0.98 Copy 500x500 from pixmap to window - 2.04 1.01 1.00 1.00 2.03 Copy 10x10 from window to pixmap - 1.05 1.00 1.00 1.00 1.05 Copy 100x100 from window to pixmap - 1.00 1.00 0.93 1.00 1.04 Copy 500x500 from window to pixmap - 58.52 1.03 1.03 1.02 57.95 Copy 10x10 from pixmap to pixmap - 2.40 1.00 1.00 1.00 2.45 Copy 100x100 from pixmap to pixmap - 1.00 1.00 1.00 1.00 1.00 Copy 500x500 from pixmap to pixmap - 51.57 1.92 1.00 1.00 85.75 Copy 10x10 1-bit deep plane - 6.37 1.75 1.01 1.01 6.37 Copy 100x100 1-bit deep plane - 1.26 1.11 1.00 1.00 1.24 Copy 500x500 1-bit deep plane - 4.23 1.63 0.98 0.97 4.38 Copy 10x10 n-bit deep plane - 1.04 1.02 1.00 1.00 1.04 Copy 100x100 n-bit deep plane - 1.00 1.00 1.00 1.00 1.00 Copy 500x500 n-bit deep plane - 6.45 1.98 1.00 1.26 12.80 PutImage 10x10 square - 1.10 1.87 1.00 1.83 2.11 PutImage 100x100 square - 1.02 1.93 1.00 1.91 1.91 PutImage 500x500 square - 4.17 1.78 1.00 1.40 7.18 PutImage XY 10x10 square - 1.27 1.49 0.97 1.48 2.10 PutImage XY 100x100 square - 1.00 1.50 1.00 1.50 1.52 PutImage XY 500x500 square - 1.07 1.01 1.00 1.00 1.06 GetImage 10x10 square - 1.01 1.00 1.00 1.00 1.01 GetImage 100x100 square - 1.00 1.00 1.00 1.00 1.00 GetImage 500x500 square - 1.56 1.00 0.99 0.97 1.56 GetImage XY 10x10 square - 1.02 1.00 1.00 1.00 1.02 GetImage XY 100x100 square - 1.00 1.00 1.00 1.00 1.00 GetImage XY 500x500 square - 1.00 1.00 1.01 0.98 0.95 X protocol NoOperation - 1.02 1.03 1.04 1.03 1.00 QueryPointer - 1.03 1.02 1.04 1.03 1.00 GetProperty -100.41 1.51 1.00 1.00 198.76 Change graphics context - 45.81 1.00 0.99 0.97 57.10 Create and map subwindows (4 kids) - 78.45 1.01 1.02 1.02 63.07 Create and map subwindows (16 kids) - 73.91 1.01 1.00 1.00 56.37 Create and map subwindows (25 kids) - 73.22 1.00 1.00 1.00 49.07 Create and map subwindows (50 kids) - 72.36 1.01 0.99 1.00 32.14 Create and map subwindows (75 kids) - 70.34 1.00 1.00 1.00 30.12 Create and map subwindows (100 kids) - 55.00 1.00 1.00 0.99 23.75 Create and map subwindows (200 kids) - 55.30 1.01 1.00 1.00 141.03 Create unmapped window (4 kids) - 55.38 1.01 1.01 1.00 163.25 Create unmapped window (16 kids) - 54.75 0.96 1.00 0.99 166.95 Create unmapped window (25 kids) - 54.83 1.00 1.00 0.99 178.81 Create unmapped window (50 kids) - 55.38 1.01 1.01 1.00 181.20 Create unmapped window (75 kids) - 55.38 1.01 1.01 1.00 181.20 Create unmapped window (100 kids) - 54.87 1.01 1.01 1.00 182.05 Create unmapped window (200 kids) - 28.13 1.00 1.00 1.00 30.75 Map window via parent (4 kids) - 36.14 1.01 1.01 1.01 32.58 Map window via parent (16 kids) - 26.13 1.00 0.98 0.95 29.85 Map window via parent (25 kids) - 40.07 1.00 1.01 1.00 27.57 Map window via parent (50 kids) - 23.26 0.99 1.00 1.00 18.23 Map window via parent (75 kids) - 22.91 0.99 1.00 0.99 16.52 Map window via parent (100 kids) - 27.79 1.00 1.00 0.99 12.50 Map window via parent (200 kids) - 22.35 1.00 1.00 1.00 56.19 Unmap window via parent (4 kids) - 9.57 1.00 0.99 1.00 89.78 Unmap window via parent (16 kids) - 80.77 1.01 1.00 1.00 103.85 Unmap window via parent (25 kids) - 96.34 1.00 1.00 1.00 116.06 Unmap window via parent (50 kids) - 99.72 1.00 1.00 1.00 124.93 Unmap window via parent (75 kids) -112.36 1.00 1.00 1.00 125.27 Unmap window via parent (100 kids) -105.41 1.00 1.00 0.99 120.00 Unmap window via parent (200 kids) - 51.29 1.03 1.02 1.02 74.19 Destroy window via parent (4 kids) - 86.75 0.99 0.99 0.99 116.87 Destroy window via parent (16 kids) -106.43 1.01 1.01 1.01 127.49 Destroy window via parent (25 kids) -120.34 1.01 1.01 1.00 140.11 Destroy window via parent (50 kids) -126.67 1.00 0.99 0.99 145.00 Destroy window via parent (75 kids) -126.11 1.01 1.01 1.00 140.56 Destroy window via parent (100 kids) -128.57 1.01 1.00 1.00 137.91 Destroy window via parent (200 kids) - 16.04 0.88 1.00 1.00 20.36 Hide/expose window via popup (4 kids) - 19.04 1.01 1.00 1.00 23.48 Hide/expose window via popup (16 kids) - 19.22 1.00 1.00 1.00 20.44 Hide/expose window via popup (25 kids) - 17.41 1.00 0.91 0.97 17.68 Hide/expose window via popup (50 kids) - 17.29 1.01 1.00 1.01 17.07 Hide/expose window via popup (75 kids) - 16.74 1.00 1.00 1.00 16.17 Hide/expose window via popup (100 kids) - 10.30 1.00 1.00 1.00 10.51 Hide/expose window via popup (200 kids) - 16.48 1.01 1.00 1.00 26.05 Move window (4 kids) - 17.01 0.95 1.00 1.00 23.97 Move window (16 kids) - 16.95 1.00 1.00 1.00 22.90 Move window (25 kids) - 16.05 1.01 1.00 1.00 21.32 Move window (50 kids) - 15.58 1.00 0.98 0.98 19.44 Move window (75 kids) - 14.98 1.02 1.03 1.03 18.17 Move window (100 kids) - 10.90 1.01 1.01 1.00 12.68 Move window (200 kids) - 49.42 1.00 1.00 1.00 198.27 Moved unmapped window (4 kids) - 50.72 0.97 1.00 1.00 193.66 Moved unmapped window (16 kids) - 50.87 1.00 0.99 1.00 195.09 Moved unmapped window (25 kids) - 50.72 1.00 1.00 1.00 189.34 Moved unmapped window (50 kids) - 50.87 1.00 1.00 1.00 191.33 Moved unmapped window (75 kids) - 50.87 1.00 1.00 0.90 186.71 Moved unmapped window (100 kids) - 50.87 1.00 1.00 1.00 179.19 Moved unmapped window (200 kids) - 41.04 1.00 1.00 1.00 56.61 Move window via parent (4 kids) - 69.81 1.00 1.00 1.00 130.82 Move window via parent (16 kids) - 95.81 1.00 1.00 1.00 141.92 Move window via parent (25 kids) - 95.98 1.00 1.00 1.00 149.43 Move window via parent (50 kids) - 96.59 1.01 1.01 1.00 153.98 Move window via parent (75 kids) - 97.19 1.00 1.00 1.00 157.30 Move window via parent (100 kids) - 96.67 1.00 0.99 0.96 159.44 Move window via parent (200 kids) - 17.75 1.01 1.00 1.00 27.61 Resize window (4 kids) - 17.94 1.00 1.00 0.99 25.42 Resize window (16 kids) - 17.92 1.01 1.00 1.00 24.47 Resize window (25 kids) - 17.24 0.97 1.00 1.00 24.14 Resize window (50 kids) - 16.81 1.00 1.00 0.99 22.75 Resize window (75 kids) - 16.08 1.00 1.00 1.00 21.20 Resize window (100 kids) - 12.92 1.00 0.99 1.00 16.26 Resize window (200 kids) - 52.94 1.01 1.00 1.00 327.12 Resize unmapped window (4 kids) - 53.60 1.01 1.01 1.01 333.71 Resize unmapped window (16 kids) - 52.99 1.00 1.00 1.00 337.29 Resize unmapped window (25 kids) - 51.98 1.00 1.00 1.00 329.38 Resize unmapped window (50 kids) - 53.05 0.89 1.00 1.00 322.60 Resize unmapped window (75 kids) - 53.05 1.00 1.00 1.00 318.08 Resize unmapped window (100 kids) - 53.11 1.00 1.00 0.99 306.21 Resize unmapped window (200 kids) - 16.76 1.00 0.96 1.00 19.46 Circulate window (4 kids) - 17.24 1.00 1.00 0.97 16.24 Circulate window (16 kids) - 16.30 1.03 1.03 1.03 15.85 Circulate window (25 kids) - 13.45 1.00 1.00 1.00 14.90 Circulate window (50 kids) - 12.91 1.00 1.00 1.00 13.06 Circulate window (75 kids) - 11.30 0.98 1.00 1.00 11.03 Circulate window (100 kids) - 7.58 1.01 1.01 0.99 7.47 Circulate window (200 kids) - 1.01 1.01 0.98 1.00 0.95 Circulate Unmapped window (4 kids) - 1.07 1.07 1.01 1.07 1.02 Circulate Unmapped window (16 kids) - 1.04 1.09 1.06 1.05 0.97 Circulate Unmapped window (25 kids) - 1.04 1.23 1.20 1.18 1.05 Circulate Unmapped window (50 kids) - 1.18 1.53 1.19 1.45 1.24 Circulate Unmapped window (75 kids) - 1.08 1.02 1.01 1.74 1.01 Circulate Unmapped window (100 kids) - 1.01 1.12 0.98 0.91 0.97 Circulate Unmapped window (200 kids) - </verb> - -<sect2>Profiling with OProfile - -<p>OProfile (available from http://oprofile.sourceforge.net/) is a -system-wide profiler for Linux systems that uses processor-level -counters to collect sampling data. OProfile can provide information -that is similar to that provided by <tt/gprof/, but without the -necessity of recompiling the program with special instrumentation (i.e., -OProfile can collect statistical profiling information about optimized -programs). A test harness was developed to collect OProfile data for -each <tt/x11perf/ test individually. - -<p>Test runs were performed using the RETIRED_INSNS counter on the AMD -Athlon and the CPU_CLK_HALTED counter on the Intel Pentium III (with a -test configuration different from the one described above). We have -examined OProfile output and have compared it with <tt/gprof/ output. -This investigation has not produced results that yield performance -increases in <tt/x11perf/ numbers. - -<!-- -<sect3>Retired Instructions - -<p>The initial tests using OProfile were done using the RETIRED_INSNS -counter with DMX running on the dual-processor AMD Athlon machine - the -same test configuration that was described above and that was used for -other tests. The RETIRED_INSNS counter counts retired instructions and -showed drawing, text, copying, and image tests to be dominated (> -30%) by calls to Hash(), SecurityLookupIDByClass(), -SecurityLookupIDByType(), and StandardReadRequestFromClient(). Some of -these tests also executed significant instructions in -WaitForSomething(). - -<p>In contrast, the window tests executed significant -instructions in SecurityLookupIDByType(), Hash(), -StandardReadRequestFromClient(), but also executed significant -instructions in other routines, such as ConfigureWindow(). Some time -was spent looking at Hash() function, but optimizations in this routine -did not lead to a dramatic increase in <tt/x11perf/ performance. ---> - -<!-- -<sect3>Clock Cycles - -<p>Retired instructions can be misleading because Intel/AMD instructions -execute in variable amounts of time. The OProfile tests were repeated -using the Intel CPU_CLK_HALTED counter with DMX running on the second -back-end machine. Note that this is a different test configuration that -the one described above. However, these tests show the amount of time -(as measured in CPU cycles) that are spent in each routine. Because -<tt/x11perf/ was running on the first back-end machine and because -window optimizations were on, the load on the second back-end machine -was not significant. - -<p>Using CPU_CLK_HALTED, DMX showed simple drawing -tests spending more than 10% of their time in -StandardReadRequestFromClient(), with significant time (> 20% total) -spent in SecurityLookupIDByClass(), WaitForSomething(), and Dispatch(). -For these tests, < 5% of the time was spent in Hash(), which explains -why optimizing the Hash() routine did not impact <tt/x11perf/ results. - -<p>The trapezoid, text, scrolling, copying, and image tests were -dominated by time in ProcFillPoly(), PanoramiXFillPoly(), dmxFillPolygon(), -SecurityLookupIDByClass(), SecurityLookupIDByType(), and -StandardReadRequestFromClient(). Hash() time was generally above 5% but -less than 10% of total time. ---> - -<sect2>X Test Suite - -<p>The X Test Suite was run on the fully optimized DMX server using the -configuration described above. The following failures were noted: - <verb> -XListPixmapFormats: Test 1 [1] -XChangeWindowAttributes: Test 32 [1] -XCreateWindow: Test 30 [1] -XFreeColors: Test 4 [3] -XCopyArea: Test 13, 17, 21, 25, 30 [2] -XCopyPlane: Test 11, 15, 27, 31 [2] -XSetFontPath: Test 4 [1] -XChangeKeyboardControl: Test 9, 10 [1] - -[1] Previously documented errors expected from the Xinerama - implementation (see Phase I discussion). -[2] Newly noted errors that have been verified as expected - behavior of the Xinerama implementation. -[3] Newly noted error that has been verified as a Xinerama - implementation bug. - </verb> - -<!-- ============================================================ --> -<sect1>Phase III - -<p>During the third phase of development, support was provided for the -following extensions: SHAPE, RENDER, XKEYBOARD, XInput. - -<sect2>SHAPE - -<p>The SHAPE extension is supported. Test applications (e.g., xeyes and -oclock) and window managers that make use of the SHAPE extension will -work as expected. - -<sect2>RENDER - -<p>The RENDER extension is supported. The version included in the DMX -CVS tree is version 0.2, and this version is fully supported by Xdmx. -Applications using only version 0.2 functions will work correctly; -however, some apps that make use of functions from later versions do not -properly check the extension's major/minor version numbers. These apps -will fail with a Bad Implementation error when using post-version 0.2 -functions. This is expected behavior. When the DMX CVS tree is updated -to include newer versions of RENDER, support for these newer functions -will be added to the DMX X server. - -<sect2>XKEYBOARD - -<p>The XKEYBOARD extension is supported. If present on the back-end X -servers, the XKEYBOARD extension will be used to obtain information -about the type of the keyboard for initialization. Otherwise, the -keyboard will be initialized using defaults. Note that this departs -from older behavior: when Xdmx is compiled without XKEYBOARD support, -the map from the back-end X server will be preserved. With XKEYBOARD -support, the map is not preserved because better information and control -of the keyboard is available. - -<sect2>XInput - -<p>The XInput extension is supported. Any device can be used as a core -device and be used as an XInput extension device, with the exception of -core devices on the back-end servers. This limitation is present -because cursor handling on the back-end requires that the back-end -cursor sometimes track the Xdmx core cursor -- behavior that is -incompatible with using the back-end pointer as a non-core device. - -<p>Currently, back-end extension devices are not available as Xdmx -extension devices, but this limitation should be removed in the future. - -<p>To demonstrate the XInput extension, and to provide more examples for -low-level input device driver writers, USB device drivers have been -written for mice (usb-mou), keyboards (usb-kbd), and -non-mouse/non-keyboard USB devices (usb-oth). Please see the man page -for information on Linux kernel drivers that are required for using -these Xdmx drivers. - -<sect2>DPMS - -<p>The DPMS extension is exported but does not do anything at this time. - -<sect2>Other Extensions - -<p>The LBX, - SECURITY, - XC-APPGROUP, and - XFree86-Bigfont -extensions do not require any special Xdmx support and have been exported. - -<p>The - BIG-REQUESTS, - DEC-XTRAP, - DOUBLE-BUFFER, - Extended-Visual-Information, - FontCache, - GLX, - MIT-SCREEN-SAVER, - MIT-SHM, - MIT-SUNDRY-NONSTANDARD, - RECORD, - SECURITY, - SGI-GLX, - SYNC, - TOG-CUP, - X-Resource, - XC-MISC, - XFree86-DGA, - XFree86-DRI, - XFree86-Misc, - XFree86-VidModeExtension, and - XVideo -extensions are <it/not/ supported at this time, but will be evaluated -for inclusion in future DMX releases. <bf>See below for additional work -on extensions after Phase III.</bf> - -<sect1>Phase IV - -<sect2>Moving to XFree86 4.3.0 - -<p>For Phase IV, the recent release of XFree86 4.3.0 (27 February 2003) -was merged onto the dmx.sourceforge.net CVS trunk and all work is -proceeding using this tree. - -<sect2>Extensions - -<sect3>XC-MISC (supported) - -<p>XC-MISC is used internally by the X library to recycle XIDs from the -X server. This is important for long-running X server sessions. Xdmx -supports this extension. The X Test Suite passed and failed the exact -same tests before and after this extension was enabled. -<!-- Tested February/March 2003 --> - -<sect3>Extended-Visual-Information (supported) - -<p>The Extended-Visual-Information extension provides a method for an X -client to obtain detailed visual information. Xdmx supports this -extension. It was tested using the <tt>hw/dmx/examples/evi</tt> example -program. <bf/Note that this extension is not Xinerama-aware/ -- it will -return visual information for each screen even though Xinerama is -causing the X server to export a single logical screen. -<!-- Tested March 2003 --> - -<sect3>RES (supported) - -<p>The X-Resource extension provides a mechanism for a client to obtain -detailed information about the resources used by other clients. This -extension was tested with the <tt>hw/dmx/examples/res</tt> program. The -X Test Suite passed and failed the exact same tests before and after -this extension was enabled. -<!-- Tested March 2003 --> - -<sect3>BIG-REQUESTS (supported) - -<p>This extension enables the X11 protocol to handle requests longer -than 262140 bytes. The X Test Suite passed and failed the exact same -tests before and after this extension was enabled. -<!-- Tested March 2003 --> - -<sect3>XSYNC (supported) - -<p>This extension provides facilities for two different X clients to -synchronize their requests. This extension was minimally tested with -<tt/xdpyinfo/ and the X Test Suite passed and failed the exact same -tests before and after this extension was enabled. -<!-- Tested March 2003 --> - -<sect3>XTEST, RECORD, DEC-XTRAP (supported) and XTestExtension1 (not supported) - -<p>The XTEST and RECORD extension were developed by the X Consortium for -use in the X Test Suite and are supported as a standard in the X11R6 -tree. They are also supported in Xdmx. When X Test Suite tests that -make use of the XTEST extension are run, Xdmx passes and fails exactly -the same tests as does a standard XFree86 X server. When the -<tt/rcrdtest/ test (a part of the X Test Suite that verifies the RECORD -extension) is run, Xdmx passes and fails exactly the same tests as does -a standard XFree86 X server. <!-- Tested February/March 2003 --> - -<p>There are two older XTEST-like extensions: DEC-XTRAP and -XTestExtension1. The XTestExtension1 extension was developed for use by -the X Testing Consortium for use with a test suite that eventually -became (part of?) the X Test Suite. Unlike XTEST, which only allows -events to be sent to the server, the XTestExtension1 extension also -allowed events to be recorded (similar to the RECORD extension). The -second is the DEC-XTRAP extension that was developed by the Digital -Equipment Corporation. - -<p>The DEC-XTRAP extension is available from Xdmx and has been tested -with the <tt/xtrap*/ tools which are distributed as standard X11R6 -clients. <!-- Tested March 2003 --> - -<p>The XTestExtension1 is <em/not/ supported because it does not appear -to be used by any modern X clients (the few that support it also support -XTEST) and because there are no good methods available for testing that -it functions correctly (unlike XTEST and DEC-XTRAP, the code for -XTestExtension1 is not part of the standard X server source tree, so -additional testing is important). <!-- Tested March 2003 --> - -<p>Most of these extensions are documented in the X11R6 source tree. -Further, several original papers exist that this author was unable to -locate -- for completeness and historical interest, citations are -provide: -<descrip> -<tag/XRECORD/ Martha Zimet. Extending X For Recording. 8th Annual X -Technical Conference Boston, MA January 24-26, 1994. -<tag/DEC-XTRAP/ Dick Annicchiarico, Robert Chesler, Alan Jamison. XTrap -Architecture. Digital Equipment Corporation, July 1991. -<tag/XTestExtension1/ Larry Woestman. X11 Input Synthesis Extension -Proposal. Hewlett Packard, November 1991. -</descrip> - -<sect3>MIT-MISC (not supported) - -<p>The MIT-MISC extension is used to control a bug-compatibility flag -that provides compatibility with xterm programs from X11R1 and X11R2. -There does not appear to be a single client available that makes use of -this extension and there is not way to verify that it works correctly. -The Xdmx server does <em/not/ support MIT-MISC. - -<sect3>SCREENSAVER (not supported) - -<p>This extension provides special support for the X screen saver. It -was tested with beforelight, which appears to be the only client that -works with it. When Xinerama was not active, <tt/beforelight/ behaved -as expected. However, when Xinerama was active, <tt/beforelight/ did -not behave as expected. Further, when this extension is not active, -<tt/xscreensaver/ (a widely-used X screen saver program) did not behave -as expected. Since this extension is not Xinerama-aware and is not -commonly used with expected results by clients, we have left this -extension disabled at this time. - -<sect3>GLX (supported) - -<p>The GLX extension provides OpenGL and GLX windowing support. In -Xdmx, the extension is called glxProxy, and it is Xinerama aware. It -works by either feeding requests forward through Xdmx to each of the -back-end servers or handling them locally. All rendering requests are -handled on the back-end X servers. This code was donated to the DMX -project by SGI. For the X Test Suite results comparison, see below. - -<sect3>RENDER (supported) - -<p>The X Rendering Extension (RENDER) provides support for digital image -composition. Geometric and text rendering are supported. RENDER is -partially Xinerama-aware, with text and the most basic compositing -operator; however, its higher level primitives (triangles, triangle -strips, and triangle fans) are not yet Xinerama-aware. The RENDER -extension is still under development, and is currently at version 0.8. -Additional support will be required in DMX as more primitives and/or -requests are added to the extension. - -<p>There is currently no test suite for the X Rendering Extension; -however, there has been discussion of developing a test suite as the -extension matures. When that test suite becomes available, additional -testing can be performed with Xdmx. The X Test Suite passed and failed -the exact same tests before and after this extension was enabled. - -<sect3>Summary - -<!-- WARNING: this list is duplicated in the "Common X extension -support" section --> -<p>To summarize, the following extensions are currently supported: - BIG-REQUESTS, - DEC-XTRAP, - DMX, - DPMS, - Extended-Visual-Information, - GLX, - LBX, - RECORD, - RENDER, - SECURITY, - SHAPE, - SYNC, - X-Resource, - XC-APPGROUP, - XC-MISC, - XFree86-Bigfont, - XINERAMA, - XInputExtension, - XKEYBOARD, and - XTEST. - -<p>The following extensions are <em/not/ supported at this time: - DOUBLE-BUFFER, - FontCache, - MIT-SCREEN-SAVER, - MIT-SHM, - MIT-SUNDRY-NONSTANDARD, - TOG-CUP, - XFree86-DGA, - XFree86-Misc, - XFree86-VidModeExtension, - XTestExtensionExt1, and - XVideo. - -<sect2>Additional Testing with the X Test Suite - -<sect3>XFree86 without XTEST - -<p>After the release of XFree86 4.3.0, we retested the XFree86 X server -with and without using the XTEST extension. When the XTEST extension -was <em/not/ used for testing, the XFree86 4.3.0 server running on our -usual test system with a Radeon VE card reported unexpected failures in -the following tests: -<verb> -XListPixmapFormats: Test 1 -XChangeKeyboardControl: Tests 9, 10 -XGetDefault: Test 5 -XRebindKeysym: Test 1 -</verb> - -<sect3>XFree86 with XTEST - -<p>When using the XTEST extension, the XFree86 4.3.0 server reported the -following errors: -<verb> -XListPixmapFormats: Test 1 -XChangeKeyboardControl: Tests 9, 10 -XGetDefault: Test 5 -XRebindKeysym: Test 1 - -XAllowEvents: Tests 20, 21, 24 -XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 -XGrabKey: Test 8 -XSetPointerMapping: Test 3 -XUngrabButton: Test 4 -</verb> - -<p>While these errors may be important, they will probably be fixed -eventually in the XFree86 source tree. We are particularly interested -in demonstrating that the Xdmx server does not introduce additional -failures that are not known Xinerama failures. - -<sect3>Xdmx with XTEST, without Xinerama, without GLX - -<p>Without Xinerama, but using the XTEST extension, the following errors -were reported from Xdmx (note that these are the same as for the XFree86 -4.3.0, except that XGetDefault no longer fails): -<verb> -XListPixmapFormats: Test 1 -XChangeKeyboardControl: Tests 9, 10 -XRebindKeysym: Test 1 - -XAllowEvents: Tests 20, 21, 24 -XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 -XGrabKey: Test 8 -XSetPointerMapping: Test 3 -XUngrabButton: Test 4 -</verb> - -<sect3>Xdmx with XTEST, with Xinerama, without GLX - -<p>With Xinerama, using the XTEST extension, the following errors -were reported from Xdmx: -<verb> -XListPixmapFormats: Test 1 -XChangeKeyboardControl: Tests 9, 10 -XRebindKeysym: Test 1 - -XAllowEvents: Tests 20, 21, 24 -XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 -XGrabKey: Test 8 -XSetPointerMapping: Test 3 -XUngrabButton: Test 4 - -XCopyPlane: Tests 13, 22, 31 (well-known XTEST/Xinerama interaction issue) -XDrawLine: Test 67 -XDrawLines: Test 91 -XDrawSegments: Test 68 -</verb> -Note that the first two sets of errors are the same as for the XFree86 -4.3.0 server, and that the XCopyPlane error is a well-known error -resulting from an XTEST/Xinerama interaction when the request crosses a -screen boundary. The XDraw* errors are resolved when the tests are run -individually and they do not cross a screen boundary. We will -investigate these errors further to determine their cause. - -<sect3>Xdmx with XTEST, with Xinerama, with GLX - -<p>With GLX enabled, using the XTEST extension, the following errors -were reported from Xdmx (these results are from early during the Phase -IV development, but were confirmed with a late Phase IV snapshot): -<verb> -XListPixmapFormats: Test 1 -XChangeKeyboardControl: Tests 9, 10 -XRebindKeysym: Test 1 - -XAllowEvents: Tests 20, 21, 24 -XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 -XGrabKey: Test 8 -XSetPointerMapping: Test 3 -XUngrabButton: Test 4 - -XClearArea: Test 8 -XCopyArea: Tests 4, 5, 11, 14, 17, 23, 25, 27, 30 -XCopyPlane: Tests 6, 7, 10, 19, 22, 31 -XDrawArcs: Tests 89, 100, 102 -XDrawLine: Test 67 -XDrawSegments: Test 68 -</verb> -Note that the first two sets of errors are the same as for the XFree86 -4.3.0 server, and that the third set has different failures than when -Xdmx does not include GLX support. Since the GLX extension adds new -visuals to support GLX's visual configs and the X Test Suite runs tests -over the entire set of visuals, additional rendering tests were run and -presumably more of them crossed a screen boundary. This conclusion is -supported by the fact that nearly all of the rendering errors reported -are resolved when the tests are run individually and they do no cross a -screen boundary. - -<p>Further, when hardware rendering is disabled on the back-end displays, -many of the errors in the third set are eliminated, leaving only: -<verb> -XClearArea: Test 8 -XCopyArea: Test 4, 5, 11, 14, 17, 23, 25, 27, 30 -XCopyPlane: Test 6, 7, 10, 19, 22, 31 -</verb> - -<sect3>Conclusion - -<p>We conclude that all of the X Test Suite errors reported for Xdmx are -the result of errors in the back-end X server or the Xinerama -implementation. Further, all of these errors that can be reasonably -fixed at the Xdmx layer have been. (Where appropriate, we have -submitted patches to the XFree86 and Xinerama upstream maintainers.) - -<sect2>Dynamic Reconfiguration - -<p>During this development phase, dynamic reconfiguration support was -added to DMX. This support allows an application to change the position -and offset of a back-end server's screen. For example, if the -application would like to shift a screen slightly to the left, it could -query Xdmx for the screen's <x,y> position and then dynamically -reconfigure that screen to be at position <x+10,y>. When a screen -is dynamically reconfigured, input handling and a screen's root window -dimensions are adjusted as needed. These adjustments are transparent to -the user. - -<sect3>Dynamic reconfiguration extension - -<p>The application interface to DMX's dynamic reconfiguration is through -a function in the DMX extension library: -<verb> -Bool DMXReconfigureScreen(Display *dpy, int screen, int x, int y) -</verb> -where <it/dpy/ is DMX server's display, <it/screen/ is the number of the -screen to be reconfigured, and <it/x/ and <it/y/ are the new upper, -left-hand coordinates of the screen to be reconfigured. - -<p>The coordinates are not limited other than as required by the X -protocol, which limits all coordinates to a signed 16 bit number. In -addition, all coordinates within a screen must also be legal values. -Therefore, setting a screen's upper, left-hand coordinates such that the -right or bottom edges of the screen is greater than 32,767 is illegal. - -<sect3>Bounding box - -<p>When the Xdmx server is started, a bounding box is calculated from -the screens' layout given either on the command line or in the -configuration file. This bounding box is currently fixed for the -lifetime of the Xdmx server. - -<p>While it is possible to move a screen outside of the bounding box, it -is currently not possible to change the dimensions of the bounding box. -For example, it is possible to specify coordinates of <-100,-100> -for the upper, left-hand corner of the bounding box, which was -previously at coordinates <0,0>. As expected, the screen is moved -down and to the right; however, since the bounding box is fixed, the -left side and upper portions of the screen exposed by the -reconfiguration are no longer accessible on that screen. Those -inaccessible regions are filled with black. - -<p>This fixed bounding box limitation will be addressed in a future -development phase. - -<sect3>Sample applications - -<p>An example of where this extension is useful is in setting up a video -wall. It is not always possible to get everything perfectly aligned, -and sometimes the positions are changed (e.g., someone might bump into a -projector). Instead of physically moving projectors or monitors, it is -now possible to adjust the positions of the back-end server's screens -using the dynamic reconfiguration support in DMX. - -<p>Other applications, such as automatic setup and calibration tools, -can make use of dynamic reconfiguration to correct for projector -alignment problems, as long as the projectors are still arranged -rectilinearly. Horizontal and vertical keystone correction could be -applied to projectors to correct for non-rectilinear alignment problems; -however, this must be done external to Xdmx. - -<p>A sample test program is included in the DMX server's examples -directory to demonstrate the interface and how an application might use -dynamic reconfiguration. See <tt/dmxreconfig.c/ for details. - -<sect3>Additional notes - -<p>In the original development plan, Phase IV was primarily devoted to -adding OpenGL support to DMX; however, SGI became interested in the DMX -project and developed code to support OpenGL/GLX. This code was later -donated to the DMX project and integrated into the DMX code base, which -freed the DMX developers to concentrate on dynamic reconfiguration (as -described above). - -<sect2>Doxygen documentation - -<p>Doxygen is an open-source (GPL) documentation system for generating -browseable documentation from stylized comments in the source code. We -have placed all of the Xdmx server and DMX protocol source code files -under Doxygen so that comprehensive documentation for the Xdmx source -code is available in an easily browseable format. - -<sect2>Valgrind - -<p>Valgrind, an open-source (GPL) memory debugger for Linux, was used to -search for memory management errors. Several memory leaks were detected -and repaired. The following errors were not addressed: -<enum> - <item> - When the X11 transport layer sends a reply to the client, only - those fields that are required by the protocol are filled in -- - unused fields are left as uninitialized memory and are therefore - noted by valgrind. These instances are not errors and were not - repaired. - <item> - At each server generation, glxInitVisuals allocates memory that - is never freed. The amount of memory lost each generation - approximately equal to 128 bytes for each back-end visual. - Because the code involved is automatically generated, this bug - has not been fixed and will be referred to SGI. - <item> - At each server generation, dmxRealizeFont calls XLoadQueryFont, - which allocates a font structure that is not freed. - dmxUnrealizeFont can free the font structure for the first - screen, but cannot free it for the other screens since they are - already closed by the time dmxUnrealizeFont could free them. - The amount of memory lost each generation is approximately equal - to 80 bytes per font per back-end. When this bug is fixed in - the the X server's device-independent (dix) code, DMX will be - able to properly free the memory allocated by XLoadQueryFont. -</enum> - -<sect2>RATS - -<p>RATS (Rough Auditing Tool for Security) is an open-source (GPL) -security analysis tool that scans source code for common -security-related programming errors (e.g., buffer overflows and TOCTOU -races). RATS was used to audit all of the code in the hw/dmx directory -and all "High" notations were checked manually. The code was either -re-written to eliminate the warning, or a comment containing "RATS" was -inserted on the line to indicate that a human had checked the code. -Unrepaired warnings are as follows: -<enum> - <item> - Fixed-size buffers are used in many areas, but code has been - added to protect against buffer overflows (e.g., XmuSnprint). - The only instances that have not yet been fixed are in - config/xdmxconfig.c (which is not part of the Xdmx server) and - input/usb-common.c. - <item> - vprintf and vfprintf are used in the logging routines. In - general, all uses of these functions (e.g., dmxLog) provide a - constant format string from a trusted source, so the use is - relatively benign. - <item> - glxProxy/glxscreens.c uses getenv and strcat. The use of these - functions is safe and will remain safe as long as - ExtensionsString is longer then GLXServerExtensions (ensuring - this may not be ovious to the casual programmer, but this is in - automatically generated code, so we hope that the generator - enforces this constraint). -</enum> - - </article> - - <!-- Local Variables: --> - <!-- fill-column: 72 --> - <!-- End: --> +<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN"> + <article> + + <!-- Title information --> + <title>Distributed Multihead X design + <author>Kevin E. Martin, David H. Dawes, and Rickard E. Faith + <date>29 June 2004 (created 25 July 2001) + <abstract> + This document covers the motivation, background, design, and + implementation of the distributed multihead X (DMX) system. It + is a living document and describes the current design and + implementation details of the DMX system. As the project + progresses, this document will be continually updated to reflect + the changes in the code and/or design. <it>Copyright 2001 by VA + Linux Systems, Inc., Fremont, California. Copyright 2001-2004 + by Red Hat, Inc., Raleigh, North Carolina</it> + </abstract> + + <!-- Table of contents --> + <toc> + +<!-- Begin the document --> +<sect>Introduction + +<sect1>The Distributed Multihead X Server + +<p>Current Open Source multihead solutions are limited to a single +physical machine. A single X server controls multiple display devices, +which can be arranged as independent heads or unified into a single +desktop (with Xinerama). These solutions are limited to the number of +physical devices that can co-exist in a single machine (e.g., due to the +number of AGP/PCI slots available for graphics cards). Thus, large +tiled displays are not currently possible. The work described in this +paper will eliminate the requirement that the display devices reside in +the same physical machine. This will be accomplished by developing a +front-end proxy X server that will control multiple back-end X servers +that make up the large display. + +<p>The overall structure of the distributed multihead X (DMX) project is +as follows: A single front-end X server will act as a proxy to a set of +back-end X servers, which handle all of the visible rendering. X +clients will connect to the front-end server just as they normally would +to a regular X server. The front-end server will present an abstracted +view to the client of a single large display. This will ensure that all +standard X clients will continue to operate without modification +(limited, as always, by the visuals and extensions provided by the X +server). Clients that are DMX-aware will be able to use an extension to +obtain information about the back-end servers (e.g., for placement of +pop-up windows, window alignments by the window manager, etc.). + +<p>The architecture of the DMX server is divided into two main sections: +input (e.g., mouse and keyboard events) and output (e.g., rendering and +windowing requests). Each of these are describe briefly below, and the +rest of this design document will describe them in greater detail. + +<p>The DMX server can receive input from three general types of input +devices: "local" devices that are physically attached to the machine on +which DMX is running, "backend" devices that are physically attached to +one or more of the back-end X servers (and that generate events via the +X protocol stream from the backend), and "console" devices that can be +abstracted from any non-back-end X server. Backend and console devices +are treated differently because the pointer device on the back-end X +server also controls the location of the hardware X cursor. Full +support for XInput extension devices is provided. + +<p>Rendering requests will be accepted by the front-end server; however, +rendering to visible windows will be broken down as needed and sent to +the appropriate back-end server(s) via X11 library calls for actual +rendering. The basic framework will follow a Xnest-style approach. GC +state will be managed in the front-end server and sent to the +appropriate back-end server(s) as required. Pixmap rendering will (at +least initially) be handled by the front-end X server. Windowing +requests (e.g., ordering, mapping, moving, etc.) will handled in the +front-end server. If the request requires a visible change, the +windowing operation will be translated into requests for the appropriate +back-end server(s). Window state will be mirrored in the back-end +server(s) as needed. + +<sect1>Layout of Paper + +<p>The next section describes the general development plan that was +actually used for implementation. The final section discusses +outstanding issues at the conclusion of development. The first appendix +provides low-level technical detail that may be of interest to those +intimately familiar with the X server architecture. The final appendix +describes the four phases of development that were performed during the +first two years of development. + +<p>The final year of work was divided into 9 tasks that are not +described in specific sections of this document. The major tasks during +that time were the enhancement of the reconfiguration ability added in +Phase IV, addition of support for a dynamic number of back-end displays +(instead of a hard-coded limit), and the support for back-end display +and input removal and addition. This work is mentioned in this paper, +but is not covered in detail. + +<!-- ============================================================ --> +<sect>Development plan + +<p>This section describes the development plan from approximately June +2001 through July 2003. + +<sect1>Bootstrap code + +<p>To allow for rapid development of the DMX server by multiple +developers during the first development stage, the problem will be +broken down into three tasks: the overall DMX framework, back-end +rendering services and input device handling services. However, before +the work begins on these tasks, a simple framework that each developer +could use was implemented to bootstrap the development effort. This +framework renders to a single back-end server and provides dummy input +devices (i.e., the keyboard and mouse). The simple back-end rendering +service was implemented using the shadow framebuffer support currently +available in the XFree86 environment. + +<p>Using this bootstrapping framework, each developer has been able to +work on each of the tasks listed above independently as follows: the +framework will be extended to handle arbitrary back-end server +configurations; the back-end rendering services will be transitioned to +the more efficient Xnest-style implementation; and, an input device +framework to handle various input devices via the input extension will +be developed. + +<p>Status: The boot strap code is complete. <!-- August 2001 --> + + +<sect1>Input device handling + +<p>An X server (including the front-end X server) requires two core +input devices -- a keyboard and a pointer (mouse). These core devices +are handled and required by the core X11 protocol. Additional types of +input devices may be attached and utilized via the XInput extension. +These are usually referred to as ``XInput extension devices'', + +<p>There are some options as to how the front-end X server gets its core +input devices: + +<enum> + <item>Local Input. The physical input devices (e.g., keyboard and + mouse) can be attached directly to the front-end X server. In this + case, the keyboard and mouse on the machine running the front-end X + server will be used. The front-end will have drivers to read the + raw input from those devices and convert it into the required X + input events (e.g., key press/release, pointer button press/release, + pointer motion). The front-end keyboard driver will keep track of + keyboard properties such as key and modifier mappings, autorepeat + state, keyboard sound and led state. Similarly the front-end + pointer driver will keep track if pointer properties such as the + button mapping and movement acceleration parameters. With this + option, input is handled fully in the front-end X server, and the + back-end X servers are used in a display-only mode. This option was + implemented and works for a limited number of Linux-specific + devices. Adding additional local input devices for other + architectures is expected to be relatively simple. + + <p>The following options are available for implementing local input + devices: + + <enum> + <item>The XFree86 X server has modular input drivers that could + be adapted for this purpose. The mouse driver supports a wide + range of mouse types and interfaces, as well as a range of + Operating System platforms. The keyboard driver in XFree86 is + not currently as modular as the mouse driver, but could be made + so. The XFree86 X server also has a range of other input + drivers for extended input devices such as tablets and touch + screens. Unfortunately, the XFree86 drivers are generally + complex, often simultaneously providing support for multiple + devices across multiple architectures; and rely so heavily on + XFree86-specific helper-functions, that this option was not + pursued. + + + <item>The <tt/kdrive/ X server in XFree86 has built-in drivers that + support PS/2 mice and keyboard under Linux. The mouse driver + can indirectly handle other mouse types if the Linux utility + <tt/gpm/ is used as to translate the native mouse protocol into + PS/2 mouse format. These drivers could be adapted and built in + to the front-end X server if this range of hardware and OS + support is sufficient. While much simpler than the XFree86 + drivers, the <tt/kdrive/ drivers were not used for the DMX + implementation. + + <item>Reimplementation of keyboard and mouse drivers from + scratch for the DMX framework. Because keyboard and mouse + drivers are relatively trivial to implement, this pathway was + selected. Other drivers in the X source tree were referenced, + and significant contributions from other drivers are noted in + the DMX source code. + </enum> + + <item>Backend Input. The front-end can make use of the core input + devices attached to one or more of the back-end X servers. Core + input events from multiple back-ends are merged into a single input + event stream. This can work sanely when only a single set of input + devices is used at any given time. The keyboard and pointer state + will be handled in the front-end, with changes propagated to the + back-end servers as needed. This option was implemented and works + well. Because the core pointer on a back-end controls the hardware + mouse on that back-end, core pointers cannot be treated as XInput + extension devices. However, all back-end XInput extensions devices + can be mapped to either DMX core or DMX XInput extension devices. + + <item>Console Input. The front-end server could create a console + window that is displayed on an X server independent of the back-end + X servers. This console window could display things like the + physical screen layout, and the front-end could get its core input + events from events delivered to the console window. This option was + implemented and works well. To help the human navigate, window + outlines are also displayed in the console window. Further, console + windows can be used as either core or XInput extension devices. + + <item>Other options were initially explored, but they were all + partial subsets of the options listed above and, hence, are + irrelevant. + +</enum> + +<p>Although extended input devices are not specifically mentioned in the +Distributed X requirements, the options above were all implemented so +that XInput extension devices were supported. + +<p>The bootstrap code (Xdmx) had dummy input devices, and these are +still supported in the final version. These do the necessary +initialization to satisfy the X server's requirements for core pointer +and keyboard devices, but no input events are ever generated. + +<p>Status: The input code is complete. Because of the complexity of the +XFree86 input device drivers (and their heavy reliance on XFree86 +infrastructure), separate low-level device drivers were implemented for +Xdmx. The following kinds of drivers are supported (in general, the +devices can be treated arbitrarily as "core" input devices or as XInput +"extension" devices; and multiple instances of different kinds of +devices can be simultaneously available): + <enum> + <item> A "dummy" device drive that never generates events. + + <item> "Local" input is from the low-level hardware on which the + Xdmx binary is running. This is the only area where using the + XFree86 driver infrastructure would have been helpful, and then + only partially, since good support for generic USB devices does + not yet exist in XFree86 (in any case, XFree86 and kdrive driver + code was used where possible). Currently, the following local + devices are supported under Linux (porting to other operating + systems should be fairly straightforward): + <itemize> + <item>Linux keyboard + <item>Linux serial mouse (MS) + <item>Linux PS/2 mouse + <item>USB keyboard + <item>USB mouse + <item>USB generic device (e.g., joystick, gamepad, etc.) + </itemize> + + <item> "Backend" input is taken from one or more of the back-end + displays. In this case, events are taken from the back-end X + server and are converted to Xdmx events. Care must be taken so + that the sprite moves properly on the display from which input + is being taken. + + <item> "Console" input is taken from an X window that Xdmx + creates on the operator's display (i.e., on the machine running + the Xdmx binary). When the operator's mouse is inside the + console window, then those events are converted to Xdmx events. + Several special features are available: the console can display + outlines of windows that are on the Xdmx display (to facilitate + navigation), the cursor can be confined to the console, and a + "fine" mode can be activated to allow very precise cursor + positioning. + </enum> + + +<!-- May 2002; July 2003 --> + +<sect1>Output device handling + +<p>The output of the DMX system displays rendering and windowing +requests across multiple screens. The screens are typically arranged in +a grid such that together they represent a single large display. + +<p>The output section of the DMX code consists of two parts. The first +is in the front-end proxy X server (Xdmx), which accepts client +connections, manages the windows, and potentially renders primitives but +does not actually display any of the drawing primitives. The second +part is the back-end X server(s), which accept commands from the +front-end server and display the results on their screens. + +<sect2>Initialization + +<p>The DMX front-end must first initialize its screens by connecting to +each of the back-end X servers and collecting information about each of +these screens. However, the information collected from the back-end X +servers might be inconsistent. Handling these cases can be difficult +and/or inefficient. For example, a two screen system has one back-end X +server running at 16bpp while the second is running at 32bpp. +Converting rendering requests (e.g., XPutImage() or XGetImage() +requests) to the appropriate bit depth can be very time consuming. +Analyzing these cases to determine how or even if it is possible to +handle them is required. The current Xinerama code handles many of +these cases (e.g., in PanoramiXConsolidate()) and will be used as a +starting point. In general, the best solution is to use homogeneous X +servers and display devices. Using back-end servers with the same depth +is a requirement of the final DMX implementation. + +<p>Once this screen consolidation is finished, the relative position of +each back-end X server's screen in the unified screen is initialized. A +full-screen window is opened on each of the back-end X servers, and the +cursor on each screen is turned off. The final DMX implementation can +also make use of a partial-screen window, or multiple windows per +back-end screen. + +<sect2>Handling rendering requests + +<p>After initialization, X applications connect to the front-end server. +There are two possible implementations of how rendering and windowing +requests are handled in the DMX system: + +<enum> + <item>A shadow framebuffer is used in the front-end server as the + render target. In this option, all protocol requests are completely + handled in the front-end server. All state and resources are + maintained in the front-end including a shadow copy of the entire + framebuffer. The framebuffers attached to the back-end servers are + updated by XPutImage() calls with data taken directly from the + shadow framebuffer. + + <p>This solution suffers from two main problems. First, it does not + take advantage of any accelerated hardware available in the system. + Second, the size of the XPutImage() calls can be quite large and + thus will be limited by the bandwidth available. + + <p>The initial DMX implementation used a shadow framebuffer by + default. + + <item>Rendering requests are sent to each back-end server for + handling (as is done in the Xnest server described above). In this + option, certain protocol requests are handled in the front-end + server and certain requests are repackaged and then sent to the + back-end servers. The framebuffer is distributed across the + multiple back-end servers. Rendering to the framebuffer is handled + on each back-end and can take advantage of any acceleration + available on the back-end servers' graphics display device. State + is maintained both in the front and back-end servers. + + <p>This solution suffers from two main drawbacks. First, protocol + requests are sent to all back-end servers -- even those that will + completely clip the rendering primitive -- which wastes bandwidth + and processing time. Second, state is maintained both in the front- + and back-end servers. These drawbacks are not as severe as in + option 1 (above) and can either be overcome through optimizations or + are acceptable. Therefore, this option will be used in the final + implementation. + + <p>The final DMX implementation defaults to this mechanism, but also + supports the shadow framebuffer mechanism. Several optimizations + were implemented to eliminate the drawbacks of the default + mechanism. These optimizations are described the section below and + in Phase II of the Development Results (see appendix). + +</enum> + +<p>Status: Both the shadow framebuffer and Xnest-style code is complete. +<!-- May 2002 --> + + +<sect1>Optimizing DMX + +<p>Initially, the Xnest-style solution's performance will be measured +and analyzed to determine where the performance bottlenecks exist. +There are four main areas that will be addressed. + +<p>First, to obtain reasonable interactivity with the first development +phase, XSync() was called after each protocol request. The XSync() +function flushes any pending protocol requests. It then waits for the +back-end to process the request and send a reply that the request has +completed. This happens with each back-end server and performance +greatly suffers. As a result of the way XSync() is called in the first +development phase, the batching that the X11 library performs is +effectively defeated. The XSync() call usage will be analyzed and +optimized by batching calls and performing them at regular intervals, +except where interactivity will suffer (e.g., on cursor movements). + +<p>Second, the initial Xnest-style solution described above sends the +repackaged protocol requests to all back-end servers regardless of +whether or not they would be completely clipped out. The requests that +are trivially rejected on the back-end server wastes the limited +bandwidth available. By tracking clipping changes in the DMX X server's +windowing code (e.g., by opening, closing, moving or resizing windows), +we can determine whether or not back-end windows are visible so that +trivial tests in the front-end server's GC ops drawing functions can +eliminate these unnecessary protocol requests. + +<p>Third, each protocol request will be analyzed to determine if it is +possible to break the request into smaller pieces at display boundaries. +The initial ones to be analyzed are put and get image requests since +they will require the greatest bandwidth to transmit data between the +front and back-end servers. Other protocol requests will be analyzed +and those that will benefit from breaking them into smaller requests +will be implemented. + +<p>Fourth, an extension is being considered that will allow font glyphs to +be transferred from the front-end DMX X server to each back-end server. +This extension will permit the front-end to handle all font requests and +eliminate the requirement that all back-end X servers share the exact +same fonts as the front-end server. We are investigating the +feasibility of this extension during this development phase. + +<p>Other potential optimizations will be determined from the performance +analysis. + +<p>Please note that in our initial design, we proposed optimizing BLT +operations (e.g., XCopyArea() and window moves) by developing an +extension that would allow individual back-end servers to directly copy +pixel data to other back-end servers. This potential optimization was +in response to the simple image movement implementation that required +potentially many calls to GetImage() and PutImage(). However, the +current Xinerama implementation handles these BLT operations +differently. Instead of copying data to and from screens, they generate +expose events -- just as happens in the case when a window is moved from +off a screen to on screen. This approach saves the limited bandwidth +available between front and back-end servers and is being standardized +with Xinerama. It also eliminates the potential setup problems and +security issues resulting from having each back-end server open +connections to all other back-end servers. Therefore, we suggest +accepting Xinerama's expose event solution. + +<p>Also note that the approach proposed in the second and third +optimizations might cause backing store algorithms in the back-end to be +defeated, so a DMX X server configuration flag will be added to disable +these optimizations. + +<p>Status: The optimizations proposed above are complete. It was +determined that the using the xfs font server was sufficient and +creating a new mechanism to pass glyphs was redundant; therefore, the +fourth optimization proposed above was not included in DMX. +<!-- September 2002 --> + + +<sect1>DMX X extension support + +<p>The DMX X server keeps track of all the windowing information on the +back-end X servers, but does not currently export this information to +any client applications. An extension will be developed to pass the +screen information and back-end window IDs to DMX-aware clients. These +clients can then use this information to directly connect to and render +to the back-end windows. Bypassing the DMX X server allows DMX-aware +clients to break up complex rendering requests on their own and send +them directly to the windows on the back-end server's screens. An +example of a client that can make effective use of this extension is +Chromium. + +<p>Status: The extension, as implemented, is fully documented in +"Client-to-Server DMX Extension to the X Protocol". Future changes +might be required based on feedback and other proposed enhancements to +DMX. Currently, the following facilities are supported: +<enum> + <item> + Screen information (clipping rectangle for each screen relative + to the virtual screen) + <item> + Window information (window IDs and clipping information for each + back-end window that corresponds to each DMX window) + <item> + Input device information (mappings from DMX device IDs to + back-end device IDs) + <item> + Force window creation (so that a client can override the + server-side lazy window creation optimization) + <item> + Reconfiguration (so that a client can request that a screen + position be changed) + <item> + Addition and removal of back-end servers and back-end and + console inputs. +</enum> +<!-- September 2002; July 2003 --> + + +<sect1>Common X extension support + +<p>The XInput, XKeyboard and Shape extensions are commonly used +extensions to the base X11 protocol. XInput allows multiple and +non-standard input devices to be accessed simultaneously. These input +devices can be connected to either the front-end or back-end servers. +XKeyboard allows much better keyboard mappings control. Shape adds +support for arbitrarily shaped windows and is used by various window +managers. Nearly all potential back-end X servers make these extensions +available, and support for each one will be added to the DMX system. + +<p>In addition to the extensions listed above, support for the X +Rendering extension (Render) is being developed. Render adds digital +image composition to the rendering model used by the X Window System. +While this extension is still under development by Keith Packard of HP, +support for the current version will be added to the DMX system. + +<p>Support for the XTest extension was added during the first +development phase. + +<!-- WARNING: this list is duplicated in the Phase IV discussion --> +<p>Status: The following extensions are supported and are discussed in +more detail in Phase IV of the Development Results (see appendix): + BIG-REQUESTS, + DEC-XTRAP, + DMX, + DPMS, + Extended-Visual-Information, + GLX, + LBX, + RECORD, + RENDER, + SECURITY, + SHAPE, + SYNC, + X-Resource, + XC-APPGROUP, + XC-MISC, + XFree86-Bigfont, + XINERAMA, + XInputExtension, + XKEYBOARD, and + XTEST. +<!-- November 2002; updated February 2003, July 2003 --> + +<sect1>OpenGL support + +<p>OpenGL support using the Mesa code base exists in XFree86 release 4 +and later. Currently, the direct rendering infrastructure (DRI) +provides accelerated OpenGL support for local clients and unaccelerated +OpenGL support (i.e., software rendering) is provided for non-local +clients. + +<p>The single head OpenGL support in XFree86 4.x will be extended to use +the DMX system. When the front and back-end servers are on the same +physical hardware, it is possible to use the DRI to directly render to +the back-end servers. First, the existing DRI will be extended to +support multiple display heads, and then to support the DMX system. +OpenGL rendering requests will be direct rendering to each back-end X +server. The DRI will request the screen layout (either from the +existing Xinerama extension or a DMX-specific extension). Support for +synchronized swap buffers will also be added (on hardware that supports +it). Note that a single front-end server with a single back-end server +on the same physical machine can emulate accelerated indirect rendering. + +<p>When the front and back-end servers are on different physical +hardware or are using non-XFree86 4.x X servers, a mechanism to render +primitives across the back-end servers will be provided. There are +several options as to how this can be implemented. + +<enum> + <item>The existing OpenGL support in each back-end server can be + used by repackaging rendering primitives and sending them to each + back-end server. This option is similar to the unoptimized + Xnest-style approach mentioned above. Optimization of this solution + is beyond the scope of this project and is better suited to other + distributed rendering systems. + + <item>Rendering to a pixmap in the front-end server using the + current XFree86 4.x code, and then displaying to the back-ends via + calls to XPutImage() is another option. This option is similar to + the shadow frame buffer approach mentioned above. It is slower and + bandwidth intensive, but has the advantage that the back-end servers + are not required to have OpenGL support. +</enum> + +<p>These, and other, options will be investigated in this phase of the +work. + +<p>Work by others have made Chromium DMX-aware. Chromium will use the +DMX X protocol extension to obtain information about the back-end +servers and will render directly to those servers, bypassing DMX. + +<p>Status: OpenGL support by the glxProxy extension was implemented by +SGI and has been integrated into the DMX code base. +<!-- May 2003--> + + +<!-- ============================================================ --> +<sect>Current issues + +<p>In this sections the current issues are outlined that require further +investigation. + +<sect1>Fonts + +<p>The font path and glyphs need to be the same for the front-end and +each of the back-end servers. Font glyphs could be sent to the back-end +servers as necessary but this would consume a significant amount of +available bandwidth during font rendering for clients that use many +different fonts (e.g., Netscape). Initially, the font server (xfs) will +be used to provide the fonts to both the front-end and back-end servers. +Other possibilities will be investigated during development. + +<sect1>Zero width rendering primitives + +<p>To allow pixmap and on-screen rendering to be pixel perfect, all +back-end servers must render zero width primitives exactly the same as +the front-end renders the primitives to pixmaps. For those back-end +servers that do not exactly match, zero width primitives will be +automatically converted to one width primitives. This can be handled in +the front-end server via the GC state. + +<sect1>Output scaling + +<p>With very large tiled displays, it might be difficult to read the +information on the standard X desktop. In particular, the cursor can be +easily lost and fonts could be difficult to read. Automatic primitive +scaling might prove to be very useful. We will investigate the +possibility of scaling the cursor and providing a set of alternate +pre-scaled fonts to replace the standard fonts that many applications +use (e.g., fixed). Other options for automatic scaling will also be +investigated. + +<sect1>Per-screen colormaps + +<p>Each screen's default colormap in the set of back-end X servers +should be able to be adjusted via a configuration utility. This support +is would allow the back-end screens to be calibrated via custom gamma +tables. On 24-bit systems that support a DirectColor visual, this type +of correction can be accommodated. One possible implementation would be +to advertise to X client of the DMX server a TrueColor visual while +using DirectColor visuals on the back-end servers to implement this type +of color correction. Other options will be investigated. + +<!-- ============================================================ --> +<appendix> + +<sect>Background + +<p>This section describes the existing Open Source architectures that +can be used to handle multiple screens and upon which this development +project is based. This section was written before the implementation +was finished, and may not reflect actual details of the implementation. +It is left for historical interest only. + +<sect1>Core input device handling + +<p>The following is a description of how core input devices are handled +by an X server. + +<sect2>InitInput() + +<p>InitInput() is a DDX function that is called at the start of each +server generation from the X server's main() function. Its purpose is +to determine what input devices are connected to the X server, register +them with the DIX and MI layers, and initialize the input event queue. +InitInput() does not have a return value, but the X server will abort if +either a core keyboard device or a core pointer device are not +registered. Extended input (XInput) devices can also be registered in +InitInput(). + +<p>InitInput() usually has implementation specific code to determine +which input devices are available. For each input device it will be +using, it calls AddInputDevice(): + +<descrip> +<tag/AddInputDevice()/ This DIX function allocates the device structure, +registers a callback function (which handles device init, close, on and +off), and returns the input handle, which can be treated as opaque. It +is called once for each input device. +</descrip> + +<p>Once input handles for core keyboard and core pointer devices have +been obtained from AddInputDevice(), they are registered as core devices +by calling RegisterPointerDevice() and RegisterKeyboardDevice(). Each +of these should be called once. If both core devices are not +registered, then the X server will exit with a fatal error when it +attempts to start the input devices in InitAndStartDevices(), which is +called directly after InitInput() (see below). + +<descrip> +<tag/Register{Pointer,Keyboard}Device()/ These DIX functions take a +handle returned from AddInputDevice() and initialize the core input +device fields in inputInfo, and initialize the input processing and grab +functions for each core input device. +</descrip> + +<p>The core pointer device is then registered with the miPointer code +(which does the high level cursor handling). While this registration +is not necessary for correct miPointer operation in the current XFree86 +code, it is still done mostly for compatibility reasons. + +<descrip> +<tag/miRegisterPointerDevice()/ This MI function registers the core +pointer's input handle with with the miPointer code. +</descrip> + +<p>The final part of InitInput() is the initialization of the input +event queue handling. In most cases, the event queue handling provided +in the MI layer is used. The primary XFree86 X server uses its own +event queue handling to support some special cases related to the XInput +extension and the XFree86-specific DGA extension. For our purposes, the +MI event queue handling should be suitable. It is initialized by +calling mieqInit(): + +<descrip> +<tag/mieqInit()/ This MI function initializes the MI event queue for the +core devices, and is passed the public component of the input handles +for the two core devices. +</descrip> + +<p>If a wakeup handler is required to deliver synchronous input +events, it can be registered here by calling the DIX function +RegisterBlockAndWakeupHandlers(). (See the devReadInput() description +below.) + +<sect2>InitAndStartDevices() + +<p>InitAndStartDevices() is a DIX function that is called immediately +after InitInput() from the X server's main() function. Its purpose is +to initialize each input device that was registered with +AddInputDevice(), enable each input device that was successfully +initialized, and create the list of enabled input devices. Once each +registered device is processed in this way, the list of enabled input +devices is checked to make sure that both a core keyboard device and +core pointer device were registered and successfully enabled. If not, +InitAndStartDevices() returns failure, and results in the the X server +exiting with a fatal error. + +<p>Each registered device is initialized by calling its callback +(dev->deviceProc) with the DEVICE_INIT argument: + +<descrip> +<tag/(*dev->deviceProc)(dev, DEVICE_INIT)/ This function initializes the +device structs with core information relevant to the device. + +<p>For pointer devices, this means specifying the number of buttons, +default button mapping, the function used to get motion events (usually +miPointerGetMotionEvents()), the function used to change/control the +core pointer motion parameters (acceleration and threshold), and the +motion buffer size. + +<p>For keyboard devices, this means specifying the keycode range, +default keycode to keysym mapping, default modifier mapping, and the +functions used to sound the keyboard bell and modify/control the +keyboard parameters (LEDs, bell pitch and duration, key click, which +keys are auto-repeating, etc). +</descrip> + +<p>Each initialized device is enabled by calling EnableDevice(): + +<descrip> +<tag/EnableDevice()/ EnableDevice() calls the device callback with +DEVICE_ON: + <descrip> + <tag/(*dev->deviceProc)(dev, DEVICE_ON)/ This typically opens and + initializes the relevant physical device, and when appropriate, + registers the device's file descriptor (or equivalent) as a valid + input source. + </descrip> + + <p>EnableDevice() then adds the device handle to the X server's + global list of enabled devices. +</descrip> + +<p>InitAndStartDevices() then verifies that a valid core keyboard and +pointer has been initialized and enabled. It returns failure if either +are missing. + +<sect2>devReadInput() + +<p>Each device will have some function that gets called to read its +physical input. These may be called in a number of different ways. In +the case of synchronous I/O, they will be called from a DDX +wakeup-handler that gets called after the server detects that new input is +available. In the case of asynchronous I/O, they will be called from a +(SIGIO) signal handler triggered when new input is available. This +function should do at least two things: make sure that input events get +enqueued, and make sure that the cursor gets moved for motion events +(except if these are handled later by the driver's own event queue +processing function, which cannot be done when using the MI event queue +handling). + +<p>Events are queued by calling mieqEnqueue(): + +<descrip> +<tag/mieqEnqueue()/ This MI function is used to add input events to the +event queue. It is simply passed the event to be queued. +</descrip> + +<p>The cursor position should be updated when motion events are +enqueued, by calling either miPointerAbsoluteCursor() or +miPointerDeltaCursor(): + +<descrip> +<tag/miPointerAbsoluteCursor()/ This MI function is used to move the +cursor to the absolute coordinates provided. +<tag/miPointerDeltaCursor()/ This MI function is used to move the cursor +relative to its current position. +</descrip> + +<sect2>ProcessInputEvents() + +<p>ProcessInputEvents() is a DDX function that is called from the X +server's main dispatch loop when new events are available in the input +event queue. It typically processes the enqueued events, and updates +the cursor/pointer position. It may also do other DDX-specific event +processing. + +<p>Enqueued events are processed by mieqProcessInputEvents() and passed +to the DIX layer for transmission to clients: + +<descrip> +<tag/mieqProcessInputEvents()/ This function processes each event in the +event queue, and passes it to the device's input processing function. +The DIX layer provides default functions to do this processing, and they +handle the task of getting the events passed back to the relevant +clients. +<tag/miPointerUpdate()/ This function resynchronized the cursor position +with the new pointer position. It also takes care of moving the cursor +between screens when needed in multi-head configurations. +</descrip> + + +<sect2>DisableDevice() + +<p>DisableDevice is a DIX function that removes an input device from the +list of enabled devices. The result of this is that the device no +longer generates input events. The device's data structures are kept in +place, and disabling a device like this can be reversed by calling +EnableDevice(). DisableDevice() may be called from the DDX when it is +desirable to do so (e.g., the XFree86 server does this when VT +switching). Except for special cases, this is not normally called for +core input devices. + +<p>DisableDevice() calls the device's callback function with +<tt/DEVICE_OFF/: + +<descrip> +<tag/(*dev->deviceProc)(dev, DEVICE_OFF)/ This typically closes the +relevant physical device, and when appropriate, unregisters the device's +file descriptor (or equivalent) as a valid input source. +</descrip> + +<p>DisableDevice() then removes the device handle from the X server's +global list of enabled devices. + + +<sect2>CloseDevice() + +<p>CloseDevice is a DIX function that removes an input device from the +list of available devices. It disables input from the device and frees +all data structures associated with the device. This function is +usually called from CloseDownDevices(), which is called from main() at +the end of each server generation to close all input devices. + +<p>CloseDevice() calls the device's callback function with +<tt/DEVICE_CLOSE/: + +<descrip> +<tag/(*dev->deviceProc)(dev, DEVICE_CLOSE)/ This typically closes the +relevant physical device, and when appropriate, unregisters the device's +file descriptor (or equivalent) as a valid input source. If any device +specific data structures were allocated when the device was initialized, +they are freed here. +</descrip> + +<p>CloseDevice() then frees the data structures that were allocated +for the device when it was registered/initialized. + + +<sect2>LegalModifier() +<!-- dmx/dmxinput.c - currently returns TRUE --> +<p>LegalModifier() is a required DDX function that can be used to +restrict which keys may be modifier keys. This seems to be present for +historical reasons, so this function should simply return TRUE +unconditionally. + + +<sect1>Output handling + +<p>The following sections describe the main functions required to +initialize, use and close the output device(s) for each screen in the X +server. + +<sect2>InitOutput() + +<p>This DDX function is called near the start of each server generation +from the X server's main() function. InitOutput()'s main purpose is to +initialize each screen and fill in the global screenInfo structure for +each screen. It is passed three arguments: a pointer to the screenInfo +struct, which it is to initialize, and argc and argv from main(), which +can be used to determine additional configuration information. + +<p>The primary tasks for this function are outlined below: + +<enum> + <item><bf/Parse configuration info:/ The first task of InitOutput() + is to parses any configuration information from the configuration + file. In addition to the XF86Config file, other configuration + information can be taken from the command line. The command line + options can be gathered either in InitOutput() or earlier in the + ddxProcessArgument() function, which is called by + ProcessCommandLine(). The configuration information determines the + characteristics of the screen(s). For example, in the XFree86 X + server, the XF86Config file specifies the monitor information, the + screen resolution, the graphics devices and slots in which they are + located, and, for Xinerama, the screens' layout. + + <item><bf/Initialize screen info:/ The next task is to initialize + the screen-dependent internal data structures. For example, part of + what the XFree86 X server does is to allocate its screen and pixmap + private indices, probe for graphics devices, compare the probed + devices to the ones listed in the XF86Config file, and add the ones that + match to the internal xf86Screens[] structure. + + <item><bf/Set pixmap formats:/ The next task is to initialize the + screenInfo's image byte order, bitmap bit order and bitmap scanline + unit/pad. The screenInfo's pixmap format's depth, bits per pixel + and scanline padding is also initialized at this stage. + + <item><bf/Unify screen info:/ An optional task that might be done at + this stage is to compare all of the information from the various + screens and determines if they are compatible (i.e., if the set of + screens can be unified into a single desktop). This task has + potential to be useful to the DMX front-end server, if Xinerama's + PanoramiXConsolidate() function is not sufficient. +</enum> + +<p>Once these tasks are complete, the valid screens are known and each +of these screens can be initialized by calling AddScreen(). + +<sect2>AddScreen() + +<p>This DIX function is called from InitOutput(), in the DDX layer, to +add each new screen to the screenInfo structure. The DDX screen +initialization function and command line arguments (i.e., argc and argv) +are passed to it as arguments. + +<p>This function first allocates a new Screen structure and any privates +that are required. It then initializes some of the fields in the Screen +struct and sets up the pixmap padding information. Finally, it calls +the DDX screen initialization function ScreenInit(), which is described +below. It returns the number of the screen that were just added, or -1 +if there is insufficient memory to add the screen or if the DDX screen +initialization fails. + +<sect2>ScreenInit() + +<p>This DDX function initializes the rest of the Screen structure with +either generic or screen-specific functions (as necessary). It also +fills in various screen attributes (e.g., width and height in +millimeters, black and white pixel values). + +<p>The screen init function usually calls several functions to perform +certain screen initialization functions. They are described below: + +<descrip> +<tag/{mi,*fb}ScreenInit()/ The DDX layer's ScreenInit() function usually +calls another layer's ScreenInit() function (e.g., miScreenInit() or +fbScreenInit()) to initialize the fallbacks that the DDX driver does not +specifically handle. + +<p>After calling another layer's ScreenInit() function, any +screen-specific functions either wrap or replace the other layer's +function pointers. If a function is to be wrapped, each of the old +function pointers from the other layer are stored in a screen private +area. Common functions to wrap are CloseScreen() and SaveScreen(). + +<tag/miInitializeBackingStore()/ This MI function initializes the +screen's backing storage functions, which are used to save areas of +windows that are currently covered by other windows. + +<tag/miDCInitialize()/ This MI function initializes the MI cursor +display structures and function pointers. If a hardware cursor is used, +the DDX layer's ScreenInit() function will wrap additional screen and +the MI cursor display function pointers. +</descrip> + +<p>Another common task for ScreenInit() function is to initialize the +output device state. For example, in the XFree86 X server, the +ScreenInit() function saves the original state of the video card and +then initializes the video mode of the graphics device. + +<sect2>CloseScreen() + +<p>This function restores any wrapped screen functions (and in +particular the wrapped CloseScreen() function) and restores the state of +the output device to its original state. It should also free any +private data it created during the screen initialization. + +<sect2>GC operations + +<p>When the X server is requested to render drawing primitives, it does +so by calling drawing functions through the graphics context's operation +function pointer table (i.e., the GCOps functions). These functions +render the basic graphics operations such as drawing rectangles, lines, +text or copying pixmaps. Default routines are provided either by the MI +layer, which draws indirectly through a simple span interface, or by the +framebuffer layers (e.g., CFB, MFB, FB), which draw directly to a +linearly mapped frame buffer. + +<p>To take advantage of special hardware on the graphics device, +specific GCOps functions can be replaced by device specific code. +However, many times the graphics devices can handle only a subset of the +possible states of the GC, so during graphics context validation, +appropriate routines are selected based on the state and capabilities of +the hardware. For example, some graphics hardware can accelerate single +pixel width lines with certain dash patterns. Thus, for dash patterns +that are not supported by hardware or for width 2 or greater lines, the +default routine is chosen during GC validation. + +<p>Note that some pointers to functions that draw to the screen are +stored in the Screen structure. They include GetImage(), GetSpans(), +CopyWindow() and RestoreAreas(). + +<sect2>Xnest + +<p>The Xnest X server is a special proxy X server that relays the X +protocol requests that it receives to a ``real'' X server that then +processes the requests and displays the results, if applicable. To the X +applications, Xnest appears as if it is a regular X server. However, +Xnest is both server to the X application and client of the real X +server, which will actually handle the requests. + +<p>The Xnest server implements all of the standard input and output +initialization steps outlined above. + +<descrip> +<tag/InitOutput()/ Xnest takes its configuration information from +command line arguments via ddxProcessArguments(). This information +includes the real X server display to connect to, its default visual +class, the screen depth, the Xnest window's geometry, etc. Xnest then +connects to the real X server and gathers visual, colormap, depth and +pixmap information about that server's display, creates a window on that +server, which will be used as the root window for Xnest. + +<p>Next, Xnest initializes its internal data structures and uses the +data from the real X server's pixmaps to initialize its own pixmap +formats. Finally, it calls AddScreen(xnestOpenScreen, argc, argv) to +initialize each of its screens. + +<tag/ScreenInit()/ Xnest's ScreenInit() function is called +xnestOpenScreen(). This function initializes its screen's depth and +visual information, and then calls miScreenInit() to set up the default +screen functions. It then calls miInitializeBackingStore() and +miDCInitialize() to initialize backing store and the software cursor. +Finally, it replaces many of the screen functions with its own +functions that repackage and send the requests to the real X server to +which Xnest is attached. + +<tag/CloseScreen()/ This function frees its internal data structure +allocations. Since it replaces instead of wrapping screen functions, +there are no function pointers to unwrap. This can potentially lead to +problems during server regeneration. + +<tag/GC operations/ The GC operations in Xnest are very simple since +they leave all of the drawing to the real X server to which Xnest is +attached. Each of the GCOps takes the request and sends it to the +real X server using standard Xlib calls. For example, the X +application issues a XDrawLines() call. This function turns into a +protocol request to Xnest, which calls the xnestPolylines() function +through Xnest's GCOps function pointer table. The xnestPolylines() +function is only a single line, which calls XDrawLines() using the same +arguments that were passed into it. Other GCOps functions are very +similar. Two exceptions to the simple GCOps functions described above +are the image functions and the BLT operations. + +<p>The image functions, GetImage() and PutImage(), must use a temporary +image to hold the image to be put of the image that was just grabbed +from the screen while it is in transit to the real X server or the +client. When the image has been transmitted, the temporary image is +destroyed. + +<p>The BLT operations, CopyArea() and CopyPlane(), handle not only the +copy function, which is the same as the simple cases described above, +but also the graphics exposures that result when the GC's graphics +exposure bit is set to True. Graphics exposures are handled in a helper +function, xnestBitBlitHelper(). This function collects the exposure +events from the real X server and, if any resulting in regions being +exposed, then those regions are passed back to the MI layer so that it +can generate exposure events for the X application. +</descrip> + +<p>The Xnest server takes its input from the X server to which it is +connected. When the mouse is in the Xnest server's window, keyboard and +mouse events are received by the Xnest server, repackaged and sent back +to any client that requests those events. + +<sect2>Shadow framebuffer + +<p>The most common type of framebuffer is a linear array memory that +maps to the video memory on the graphics device. However, accessing +that video memory over an I/O bus (e.g., ISA or PCI) can be slow. The +shadow framebuffer layer allows the developer to keep the entire +framebuffer in main memory and copy it back to video memory at regular +intervals. It also has been extended to handle planar video memory and +rotated framebuffers. + +<p>There are two main entry points to the shadow framebuffer code: + +<descrip> +<tag/shadowAlloc(width, height, bpp)/ This function allocates the in +memory copy of the framebuffer of size width*height*bpp. It returns a +pointer to that memory, which will be used by the framebuffer +ScreenInit() code during the screen's initialization. + +<tag/shadowInit(pScreen, updateProc, windowProc)/ This function +initializes the shadow framebuffer layer. It wraps several screen +drawing functions, and registers a block handler that will update the +screen. The updateProc is a function that will copy the damaged regions +to the screen, and the windowProc is a function that is used when the +entire linear video memory range cannot be accessed simultaneously so +that only a window into that memory is available (e.g., when using the +VGA aperture). +</descrip> + +<p>The shadow framebuffer code keeps track of the damaged area of each +screen by calculating the bounding box of all drawing operations that +have occurred since the last screen update. Then, when the block handler +is next called, only the damaged portion of the screen is updated. + +<p>Note that since the shadow framebuffer is kept in main memory, all +drawing operations are performed by the CPU and, thus, no accelerated +hardware drawing operations are possible. + + +<sect1>Xinerama + +<p>Xinerama is an X extension that allows multiple physical screens +controlled by a single X server to appear as a single screen. Although +the extension allows clients to find the physical screen layout via +extension requests, it is completely transparent to clients at the core +X11 protocol level. The original public implementation of Xinerama came +from Digital/Compaq. XFree86 rewrote it, filling in some missing pieces +and improving both X11 core protocol compliance and performance. The +Xinerama extension will be passing through X.Org's standardization +process in the near future, and the sample implementation will be based +on this rewritten version. + +<p>The current implementation of Xinerama is based primarily in the DIX +(device independent) and MI (machine independent) layers of the X +server. With few exceptions the DDX layers do not need any changes to +support Xinerama. X server extensions often do need modifications to +provide full Xinerama functionality. + +<p>The following is a code-level description of how Xinerama functions. + +<p>Note: Because the Xinerama extension was originally called the +PanoramiX extension, many of the Xinerama functions still have the +PanoramiX prefix. + +<descrip> + <tag/PanoramiXExtensionInit()/ PanoramiXExtensionInit() is a + device-independent extension function that is called at the start of + each server generation from InitExtensions(), which is called from + the X server's main() function after all output devices have been + initialized, but before any input devices have been initialized. + + <p>PanoramiXNumScreens is set to the number of physical screens. If + only one physical screen is present, the extension is disabled, and + PanoramiXExtensionInit() returns without doing anything else. + + <p>The Xinerama extension is registered by calling AddExtension(). + + <p>A local per-screen array of data structures + (panoramiXdataPtr[]) + is allocated for each physical screen, and GC and Screen private + indexes are allocated, and both GC and Screen private areas are + allocated for each physical screen. These hold Xinerama-specific + per-GC and per-Screen data. Each screen's CreateGC and CloseScreen + functions are wrapped by XineramaCreateGC() and + XineramaCloseScreen() respectively. Some new resource classes are + created for Xinerama drawables and GCs, and resource types for + Xinerama windows, pixmaps and colormaps. + + <p>A region (XineramaScreenRegions[i]) is initialized for each + physical screen, and single region (PanoramiXScreenRegion) is + initialized to be the union of the screen regions. The + panoramiXdataPtr[] array is also initialized with the size and + origin of each screen. The relative positioning information for the + physical screens is taken from the array + dixScreenOrigins[], which + the DDX layer must initialize in InitOutput(). The bounds of the + combined screen is also calculated (PanoramiXPixWidth and + PanoramiXPixHeight). + + <p>The DIX layer has a list of function pointers + (ProcVector[]) that + holds the entry points for the functions that process core protocol + requests. The requests that Xinerama must intercept and break up + into physical screen-specific requests are wrapped. The original + set is copied to SavedProcVector[]. The types of requests + intercepted are Window requests, GC requests, colormap requests, + drawing requests, and some geometry-related requests. This wrapping + allows the bulk of the protocol request processing to be handled + transparently to the DIX layer. Some operations cannot be dealt with + in this way and are handled with Xinerama-specific code within the + DIX layer. + + <tag/PanoramiXConsolidate()/ PanoramiXConsolidate() is a + device-independent extension function that is called directly from + the X server's main() function after extensions and input/output + devices have been initialized, and before the root windows are + defined and initialized. + + <p>This function finds the set of depths (PanoramiXDepths[]) and + visuals (PanoramiXVisuals[]) + common to all of the physical screens. + PanoramiXNumDepths is set to the number of common depths, and + PanoramiXNumVisuals is set to the number of common visuals. + Resources are created for the single root window and the default + colormap. Each of these resources has per-physical screen entries. + + <tag/PanoramiXCreateConnectionBlock()/ PanoramiXConsolidate() is a + device-independent extension function that is called directly from + the X server's main() function after the per-physical screen root + windows are created. It is called instead of the standard DIX + CreateConnectionBlock() function. If this function returns FALSE, + the X server exits with a fatal error. This function will return + FALSE if no common depths were found in PanoramiXConsolidate(). + With no common depths, Xinerama mode is not possible. + + <p>The connection block holds the information that clients get when + they open a connection to the X server. It includes information + such as the supported pixmap formats, number of screens and the + sizes, depths, visuals, default colormap information, etc, for each + of the screens (much of information that <tt/xdpyinfo/ shows). The + connection block is initialized with the combined single screen + values that were calculated in the above two functions. + + <p>The Xinerama extension allows the registration of connection + block callback functions. The purpose of these is to allow other + extensions to do processing at this point. These callbacks can be + registered by calling XineramaRegisterConnectionBlockCallback() from + the other extension's ExtensionInit() function. Each registered + connection block callback is called at the end of + PanoramiXCreateConnectionBlock(). +</descrip> + +<sect2>Xinerama-specific changes to the DIX code + +<p>There are a few types of Xinerama-specific changes within the DIX +code. The main ones are described here. + +<p>Functions that deal with colormap or GC -related operations outside of +the intercepted protocol requests have a test added to only do the +processing for screen numbers > 0. This is because they are handled for +the single Xinerama screen and the processing is done once for screen 0. + +<p>The handling of motion events does some coordinate translation between +the physical screen's origin and screen zero's origin. Also, motion +events must be reported relative to the composite screen origin rather +than the physical screen origins. + +<p>There is some special handling for cursor, window and event processing +that cannot (either not at all or not conveniently) be done via the +intercepted protocol requests. A particular case is the handling of +pointers moving between physical screens. + +<sect2>Xinerama-specific changes to the MI code + +<p>The only Xinerama-specific change to the MI code is in miSendExposures() +to handle the coordinate (and window ID) translation for expose events. + +<sect2>Intercepted DIX core requests + +<p>Xinerama breaks up drawing requests for dispatch to each physical +screen. It also breaks up windows into pieces for each physical screen. +GCs are translated into per-screen GCs. Colormaps are replicated on +each physical screen. The functions handling the intercepted requests +take care of breaking the requests and repackaging them so that they can +be passed to the standard request handling functions for each screen in +turn. In addition, and to aid the repackaging, the information from +many of the intercepted requests is used to keep up to date the +necessary state information for the single composite screen. Requests +(usually those with replies) that can be satisfied completely from this +stored state information do not call the standard request handling +functions. + +<!-- ============================================================ --> + +<sect>Development Results + +<p>In this section the results of each phase of development are +discussed. This development took place between approximately June 2001 +and July 2003. + +<sect1>Phase I + +<p>The initial development phase dealt with the basic implementation +including the bootstrap code, which used the shadow framebuffer, and the +unoptimized implementation, based on an Xnest-style implementation. + +<sect2>Scope + +<p>The goal of Phase I is to provide fundamental functionality that can +act as a foundation for ongoing work: +<enum> + <item>Develop the proxy X server + <itemize> + <item>The proxy X server will operate on the X11 protocol and + relay requests as necessary to correctly perform the request. + <item>Work will be based on the existing work for Xinerama and + Xnest. + <item>Input events and windowing operations are handled in the + proxy server and rendering requests are repackaged and sent to + each of the back-end servers for display. + <item>The multiple screen layout (including support for + overlapping screens) will be user configurable via a + configuration file or through the configuration tool. + </itemize> + <item>Develop graphical configuration tool + <itemize> + <item>There will be potentially a large number of X servers to + configure into a single display. The tool will allow the user + to specify which servers are involved in the configuration and + how they should be laid out. + </itemize> + <item>Pass the X Test Suite + <itemize> + <item>The X Test Suite covers the basic X11 operations. All + tests known to succeed must correctly operate in the distributed + X environment. + </itemize> +</enum> + +<p>For this phase, the back-end X servers are assumed to be unmodified X +servers that do not support any DMX-related protocol extensions; future +optimization pathways are considered, but are not implemented; and the +configuration tool is assumed to rely only on libraries in the X source +tree (e.g., Xt). + +<sect2>Results + +<p>The proxy X server, Xdmx, was developed to distribute X11 protocol +requests to the set of back-end X servers. It opens a window on each +back-end server, which represents the part of the front-end's root +window that is visible on that screen. It mirrors window, pixmap and +other state in each back-end server. Drawing requests are sent to +either windows or pixmaps on each back-end server. This code is based +on Xnest and uses the existing Xinerama extension. + +<p>Input events can be taken from (1) devices attached to the back-end +server, (2) core devices attached directly to the Xdmx server, or (3) +from a ``console'' window on another X server. Events for these devices +are gathered, processed and delivered to clients attached to the Xdmx +server. + +<p>An intuitive configuration format was developed to help the user +easily configure the multiple back-end X servers. It was defined (see +grammar in Xdmx man page) and a parser was implemented that is used by +the Xdmx server and by a standalone xdmxconfig utility. The parsing +support was implemented such that it can be easily factored out of the X +source tree for use with other tools (e.g., vdl). Support for +converting legacy vdl-format configuration files to the DMX format is +provided by the vdltodmx utility. + +<p>Originally, the configuration file was going to be a subsection of +XFree86's XF86Config file, but that was not possible since Xdmx is a +completely separate X server. Thus, a separate config file format was +developed. In addition, a graphical configuration +tool, xdmxconfig, was developed to allow the user to create and arrange +the screens in the configuration file. The <bf/-configfile/ and <bf/-config/ +command-line options can be used to start Xdmx using a configuration +file. + +<p>An extension that enables remote input testing is required for the X +Test Suite to function. During this phase, this extension (XTEST) was +implemented in the Xdmx server. The results from running the X Test +Suite are described in detail below. + +<sect2>X Test Suite + + <sect3> Introduction + <p> + The X Test Suite contains tests that verify Xlib functions + operate correctly. The test suite is designed to run on a + single X server; however, since X applications will not be + able to tell the difference between the DMX server and a + standard X server, the X Test Suite should also run on the + DMX server. + <p> + The Xdmx server was tested with the X Test Suite, and the + existing failures are noted in this section. To put these + results in perspective, we first discuss expected X Test + failures and how errors in underlying systems can impact + Xdmx test results. + + <sect3>Expected Failures for a Single Head + <p> + A correctly implemented X server with a single screen is + expected to fail certain X Test tests. The following + well-known errors occur because of rounding error in the X + server code: + <verb> +XDrawArc: Tests 42, 63, 66, 73 +XDrawArcs: Tests 45, 66, 69, 76 + </verb> + <p> + The following failures occur because of the high-level X + server implementation: + <verb> +XLoadQueryFont: Test 1 +XListFontsWithInfo: Tests 3, 4 +XQueryFont: Tests 1, 2 + </verb> + <p> + The following test fails when running the X server as root + under Linux because of the way directory modes are + interpreted: + <verb> +XWriteBitmapFile: Test 3 + </verb> + <p> + Depending on the video card used for the back-end, other + failures may also occur because of bugs in the low-level + driver implementation. Over time, failures of this kind + are usually fixed by XFree86, but will show up in Xdmx + testing until then. + + <sect3>Expected Failures for Xinerama + <p> + Xinerama fails several X Test Suite tests because of + design decisions made for the current implementation of + Xinerama. Over time, many of these errors will be + corrected by XFree86 and the group working on a new + Xinerama implementation. Therefore, Xdmx will also share + X Suite Test failures with Xinerama. + <p> + We may be able to fix or work-around some of these + failures at the Xdmx level, but this will require + additional exploration that was not part of Phase I. + <p> + Xinerama is constantly improving, and the list of + Xinerama-related failures depends on XFree86 version and + the underlying graphics hardware. We tested with a + variety of hardware, including nVidia, S3, ATI Radeon, + and Matrox G400 (in dual-head mode). The list below + includes only those failures that appear to be from the + Xinerama layer, and does not include failures listed in + the previous section, or failures that appear to be from + the low-level graphics driver itself: + <p> + These failures were noted with multiple Xinerama + configurations: + <verb> +XCopyPlane: Tests 13, 22, 31 (well-known Xinerama implementation issue) +XSetFontPath: Test 4 +XGetDefault: Test 5 +XMatchVisualInfo: Test 1 + </verb> + <p> + These failures were noted only when using one dual-head + video card with a 4.2.99.x XFree86 server: + <verb> +XListPixmapFormats: Test 1 +XDrawRectangles: Test 45 + </verb> + <p> + These failures were noted only when using two video cards + from different vendors with a 4.1.99.x XFree86 server: + <verb> +XChangeWindowAttributes: Test 32 +XCreateWindow: Test 30 +XDrawLine: Test 22 +XFillArc: Test 22 +XChangeKeyboardControl: Tests 9, 10 +XRebindKeysym: Test 1 + </verb> + + <sect3>Additional Failures from Xdmx + <p> + When running Xdmx, no unexpected failures were noted. + Since the Xdmx server is based on Xinerama, we expect to + have most of the Xinerama failures present in the Xdmx + server. Similarly, since the Xdmx server must rely on the + low-level device drivers on each back-end server, we also + expect that Xdmx will exhibit most of the back-end + failures. Here is a summary: + <verb> +XListPixmapFormats: Test 1 (configuration dependent) +XChangeWindowAttributes: Test 32 +XCreateWindow: Test 30 +XCopyPlane: Test 13, 22, 31 +XSetFontPath: Test 4 +XGetDefault: Test 5 (configuration dependent) +XMatchVisualInfo: Test 1 +XRebindKeysym: Test 1 (configuration dependent) + </verb> + <p> + Note that this list is shorter than the combined list for + Xinerama because Xdmx uses different code paths to perform + some Xinerama operations. Further, some Xinerama failures + have been fixed in the XFree86 4.2.99.x CVS repository. + + <sect3>Summary and Future Work + <p> + Running the X Test Suite on Xdmx does not produce any + failures that cannot be accounted for by the underlying + Xinerama subsystem used by the front-end or by the + low-level device-driver code running on the back-end X + servers. The Xdmx server therefore is as ``correct'' as + possible with respect to the standard set of X Test Suite + tests. + <p> + During the following phases, we will continue to verify + Xdmx correctness using the X Test Suite. We may also use + other tests suites or write additional tests that run + under the X Test Suite that specifically verify the + expected behavior of DMX. + +<sect2>Fonts + +<p>In Phase I, fonts are handled directly by both the front-end and the +back-end servers, which is required since we must treat each back-end +server during this phase as a ``black box''. What this requires is that +<bf/the front- and back-end servers must share the exact same font +path/. There are two ways to help make sure that all servers share the +same font path: + +<enum> + <item>First, each server can be configured to use the same font + server. The font server, xfs, can be configured to serve fonts to + multiple X servers via TCP. + + <item>Second, each server can be configured to use the same font + path and either those font paths can be copied to each back-end + machine or they can be mounted (e.g., via NFS) on each back-end + machine. +</enum> + +<p>One additional concern is that a client program can set its own font +path, and if it does so, then that font path must be available on each +back-end machine. + +<p>The -fontpath command line option was added to allow users to +initialize the font path of the front end server. This font path is +propagated to each back-end server when the default font is loaded. If +there are any problems, an error message is printed, which will describe +the problem and list the current font path. For more information about +setting the font path, see the -fontpath option description in the man +page. + +<sect2>Performance + +<p>Phase I of development was not intended to optimize performance. Its +focus was on completely and correctly handling the base X11 protocol in +the Xdmx server. However, several insights were gained during Phase I, +which are listed here for reference during the next phase of +development. + +<enum> + <item>Calls to XSync() can slow down rendering since it requires a + complete round trip to and from a back-end server. This is + especially problematic when communicating over long haul networks. + <item>Sending drawing requests to only the screens that they overlap + should improve performance. +</enum> + +<sect2>Pixmaps + +<p>Pixmaps were originally expected to be handled entirely in the +front-end X server; however, it was found that this overly complicated +the rendering code and would have required sending potentially large +images to each back server that required them when copying from pixmap +to screen. Thus, pixmap state is mirrored in the back-end server just +as it is with regular window state. With this implementation, the same +rendering code that draws to windows can be used to draw to pixmaps on +the back-end server, and no large image transfers are required to copy +from pixmap to window. + +<!-- ============================================================ --> +<sect1>Phase II + +<p>The second phase of development concentrates on performance +optimizations. These optimizations are documented here, with +<tt/x11perf/ data to show how the optimizations improve performance. + +<p>All benchmarks were performed by running Xdmx on a dual processor +1.4GHz AMD Athlon machine with 1GB of RAM connecting over 100baseT to +two single-processor 1GHz Pentium III machines with 256MB of RAM and ATI +Rage 128 (RF) video cards. The front end was running Linux +2.4.20-pre1-ac1 and the back ends were running Linux 2.4.7-10 and +version 4.2.99.1 of XFree86 pulled from the XFree86 CVS repository on +August 7, 2002. All systems were running Red Hat Linux 7.2. + +<sect2>Moving from XFree86 4.1.99.1 to 4.2.0.0 + +<p>For phase II, the working source tree was moved to the branch tagged +with dmx-1-0-branch and was updated from version 4.1.99.1 (20 August +2001) of the XFree86 sources to version 4.2.0.0 (18 January 2002). +After this update, the following tests were noted to be more than 10% +faster: + <verb> +1.13 Fill 300x300 opaque stippled trapezoid (161x145 stipple) +1.16 Fill 1x1 tiled trapezoid (161x145 tile) +1.13 Fill 10x10 tiled trapezoid (161x145 tile) +1.17 Fill 100x100 tiled trapezoid (161x145 tile) +1.16 Fill 1x1 tiled trapezoid (216x208 tile) +1.20 Fill 10x10 tiled trapezoid (216x208 tile) +1.15 Fill 100x100 tiled trapezoid (216x208 tile) +1.37 Circulate Unmapped window (200 kids) + </verb> +And the following tests were noted to be more than 10% slower: + <verb> +0.88 Unmap window via parent (25 kids) +0.75 Circulate Unmapped window (4 kids) +0.79 Circulate Unmapped window (16 kids) +0.80 Circulate Unmapped window (25 kids) +0.82 Circulate Unmapped window (50 kids) +0.85 Circulate Unmapped window (75 kids) + </verb> +<p>These changes were not caused by any changes in the DMX system, and +may point to changes in the XFree86 tree or to tests that have more +"jitter" than most other <tt/x11perf/ tests. + +<sect2>Global changes + +<p>During the development of the Phase II DMX server, several global +changes were made. These changes were also compared with the Phase I +server. The following tests were noted to be more than 10% faster: + <verb> +1.13 Fill 300x300 opaque stippled trapezoid (161x145 stipple) +1.15 Fill 1x1 tiled trapezoid (161x145 tile) +1.13 Fill 10x10 tiled trapezoid (161x145 tile) +1.17 Fill 100x100 tiled trapezoid (161x145 tile) +1.16 Fill 1x1 tiled trapezoid (216x208 tile) +1.19 Fill 10x10 tiled trapezoid (216x208 tile) +1.15 Fill 100x100 tiled trapezoid (216x208 tile) +1.15 Circulate Unmapped window (4 kids) + </verb> + +<p>The following tests were noted to be more than 10% slower: + <verb> +0.69 Scroll 10x10 pixels +0.68 Scroll 100x100 pixels +0.68 Copy 10x10 from window to window +0.68 Copy 100x100 from window to window +0.76 Circulate Unmapped window (75 kids) +0.83 Circulate Unmapped window (100 kids) + </verb> + +<p>For the remainder of this analysis, the baseline of comparison will +be the Phase II deliverable with all optimizations disabled (unless +otherwise noted). This will highlight how the optimizations in +isolation impact performance. + +<sect2>XSync() Batching + +<p>During the Phase I implementation, XSync() was called after every +protocol request made by the DMX server. This provided the DMX server +with an interactive feel, but defeated X11's protocol buffering system +and introduced round-trip wire latency into every operation. During +Phase II, DMX was changed so that protocol requests are no longer +followed by calls to XSync(). Instead, the need for an XSync() is +noted, and XSync() calls are only made every 100mS or when the DMX +server specifically needs to make a call to guarantee interactivity. +With this new system, X11 buffers protocol as much as possible during a +100mS interval, and many unnecessary XSync() calls are avoided. + +<p>Out of more than 300 <tt/x11perf/ tests, 8 tests became more than 100 +times faster, with 68 more than 50X faster, 114 more than 10X faster, +and 181 more than 2X faster. See table below for summary. + +<p>The following tests were noted to be more than 10% slower with +XSync() batching on: + <verb> +0.88 500x500 tiled rectangle (161x145 tile) +0.89 Copy 500x500 from window to window + </verb> + +<sect2>Offscreen Optimization + +<p>Windows span one or more of the back-end servers' screens; however, +during Phase I development, windows were created on every back-end +server and every rendering request was sent to every window regardless +of whether or not that window was visible. With the offscreen +optimization, the DMX server tracks when a window is completely off of a +back-end server's screen and, in that case, it does not send rendering +requests to those back-end windows. This optimization saves bandwidth +between the front and back-end servers, and it reduces the number of +XSync() calls. The performance tests were run on a DMX system with only +two back-end servers. Greater performance gains will be had as the +number of back-end servers increases. + +<p>Out of more than 300 <tt/x11perf/ tests, 3 tests were at least twice as +fast, and 146 tests were at least 10% faster. Two tests were more than +10% slower with the offscreen optimization: + <verb> +0.88 Hide/expose window via popup (4 kids) +0.89 Resize unmapped window (75 kids) + </verb> + +<sect2>Lazy Window Creation Optimization + +<p>As mentioned above, during Phase I, windows were created on every +back-end server even if they were not visible on that back-end. With +the lazy window creation optimization, the DMX server does not create +windows on a back-end server until they are either visible or they +become the parents of a visible window. This optimization builds on the +offscreen optimization (described above) and requires it to be enabled. + +<p>The lazy window creation optimization works by creating the window +data structures in the front-end server when a client creates a window, +but delays creation of the window on the back-end server(s). A private +window structure in the DMX server saves the relevant window data and +tracks changes to the window's attributes and stacking order for later +use. The only times a window is created on a back-end server are (1) +when it is mapped and is at least partially overlapping the back-end +server's screen (tracked by the offscreen optimization), or (2) when the +window becomes the parent of a previously visible window. The first +case occurs when a window is mapped or when a visible window is copied, +moved or resized and now overlaps the back-end server's screen. The +second case occurs when starting a window manager after having created +windows to which the window manager needs to add decorations. + +<p>When either case occurs, a window on the back-end server is created +using the data saved in the DMX server's window private data structure. +The stacking order is then adjusted to correctly place the window on the +back-end and lastly the window is mapped. From this time forward, the +window is handled exactly as if the window had been created at the time +of the client's request. + +<p>Note that when a window is no longer visible on a back-end server's +screen (e.g., it is moved offscreen), the window is not destroyed; +rather, it is kept and reused later if the window once again becomes +visible on the back-end server's screen. Originally with this +optimization, destroying windows was implemented but was later rejected +because it increased bandwidth when windows were opaquely moved or +resized, which is common in many window managers. + +<p>The performance tests were run on a DMX system with only two back-end +servers. Greater performance gains will be had as the number of +back-end servers increases. + +<p>This optimization improved the following <tt/x11perf/ tests by more +than 10%: + <verb> +1.10 500x500 rectangle outline +1.12 Fill 100x100 stippled trapezoid (161x145 stipple) +1.20 Circulate Unmapped window (50 kids) +1.19 Circulate Unmapped window (75 kids) + </verb> + +<sect2>Subdividing Rendering Primitives + +<p>X11 imaging requests transfer significant data between the client and +the X server. During Phase I, the DMX server would then transfer the +image data to each back-end server. Even with the offscreen +optimization (above), these requests still required transferring +significant data to each back-end server that contained a visible +portion of the window. For example, if the client uses XPutImage() to +copy an image to a window that overlaps the entire DMX screen, then the +entire image is copied by the DMX server to every back-end server. + +<p>To reduce the amount of data transferred between the DMX server and +the back-end servers when XPutImage() is called, the image data is +subdivided and only the data that will be visible on a back-end server's +screen is sent to that back-end server. Xinerama already implements a +subdivision algorithm for XGetImage() and no further optimization was +needed. + +<p>Other rendering primitives were analyzed, but the time required to +subdivide these primitives was a significant proportion of the time +required to send the entire rendering request to the back-end server, so +this optimization was rejected for the other rendering primitives. + +<p>Again, the performance tests were run on a DMX system with only two +back-end servers. Greater performance gains will be had as the number +of back-end servers increases. + +<p>This optimization improved the following <tt/x11perf/ tests by more +than 10%: + <verb> +1.12 Fill 100x100 stippled trapezoid (161x145 stipple) +1.26 PutImage 10x10 square +1.83 PutImage 100x100 square +1.91 PutImage 500x500 square +1.40 PutImage XY 10x10 square +1.48 PutImage XY 100x100 square +1.50 PutImage XY 500x500 square +1.45 Circulate Unmapped window (75 kids) +1.74 Circulate Unmapped window (100 kids) + </verb> + +<p>The following test was noted to be more than 10% slower with this +optimization: + <verb> +0.88 10-pixel fill chord partial circle + </verb> + +<sect2>Summary of x11perf Data + +<p>With all of the optimizations on, 53 <tt/x11perf/ tests are more than +100X faster than the unoptimized Phase II deliverable, with 69 more than +50X faster, 73 more than 10X faster, and 199 more than twice as fast. +No tests were more than 10% slower than the unoptimized Phase II +deliverable. (Compared with the Phase I deliverable, only Circulate +Unmapped window (100 kids) was more than 10% slower than the Phase II +deliverable. As noted above, this test seems to have wider variability +than other <tt/x11perf/ tests.) + +<p>The following table summarizes relative <tt/x11perf/ test changes for +all optimizations individually and collectively. Note that some of the +optimizations have a synergistic effect when used together. + <verb> + +1: XSync() batching only +2: Off screen optimizations only +3: Window optimizations only +4: Subdivprims only +5: All optimizations + + 1 2 3 4 5 Operation +------ ---- ---- ---- ------ --------- + 2.14 1.85 1.00 1.00 4.13 Dot + 1.67 1.80 1.00 1.00 3.31 1x1 rectangle + 2.38 1.43 1.00 1.00 2.44 10x10 rectangle + 1.00 1.00 0.92 0.98 1.00 100x100 rectangle + 1.00 1.00 1.00 1.00 1.00 500x500 rectangle + 1.83 1.85 1.05 1.06 3.54 1x1 stippled rectangle (8x8 stipple) + 2.43 1.43 1.00 1.00 2.41 10x10 stippled rectangle (8x8 stipple) + 0.98 1.00 1.00 1.00 1.00 100x100 stippled rectangle (8x8 stipple) + 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (8x8 stipple) + 1.75 1.75 1.00 1.00 3.40 1x1 opaque stippled rectangle (8x8 stipple) + 2.38 1.42 1.00 1.00 2.34 10x10 opaque stippled rectangle (8x8 stipple) + 1.00 1.00 0.97 0.97 1.00 100x100 opaque stippled rectangle (8x8 stipple) + 1.00 1.00 1.00 1.00 0.99 500x500 opaque stippled rectangle (8x8 stipple) + 1.82 1.82 1.04 1.04 3.56 1x1 tiled rectangle (4x4 tile) + 2.33 1.42 1.00 1.00 2.37 10x10 tiled rectangle (4x4 tile) + 1.00 0.92 1.00 1.00 1.00 100x100 tiled rectangle (4x4 tile) + 1.00 1.00 1.00 1.00 1.00 500x500 tiled rectangle (4x4 tile) + 1.94 1.62 1.00 1.00 3.66 1x1 stippled rectangle (17x15 stipple) + 1.74 1.28 1.00 1.00 1.73 10x10 stippled rectangle (17x15 stipple) + 1.00 1.00 1.00 0.89 0.98 100x100 stippled rectangle (17x15 stipple) + 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (17x15 stipple) + 1.94 1.62 1.00 1.00 3.67 1x1 opaque stippled rectangle (17x15 stipple) + 1.69 1.26 1.00 1.00 1.66 10x10 opaque stippled rectangle (17x15 stipple) + 1.00 0.95 1.00 1.00 1.00 100x100 opaque stippled rectangle (17x15 stipple) + 1.00 1.00 1.00 1.00 0.97 500x500 opaque stippled rectangle (17x15 stipple) + 1.93 1.61 0.99 0.99 3.69 1x1 tiled rectangle (17x15 tile) + 1.73 1.27 1.00 1.00 1.72 10x10 tiled rectangle (17x15 tile) + 1.00 1.00 1.00 1.00 0.98 100x100 tiled rectangle (17x15 tile) + 1.00 1.00 0.97 0.97 1.00 500x500 tiled rectangle (17x15 tile) + 1.95 1.63 1.00 1.00 3.83 1x1 stippled rectangle (161x145 stipple) + 1.80 1.30 1.00 1.00 1.83 10x10 stippled rectangle (161x145 stipple) + 0.97 1.00 1.00 1.00 1.01 100x100 stippled rectangle (161x145 stipple) + 1.00 1.00 1.00 1.00 0.98 500x500 stippled rectangle (161x145 stipple) + 1.95 1.63 1.00 1.00 3.56 1x1 opaque stippled rectangle (161x145 stipple) + 1.65 1.25 1.00 1.00 1.68 10x10 opaque stippled rectangle (161x145 stipple) + 1.00 1.00 1.00 1.00 1.01 100x100 opaque stippled rectangle (161x145... + 1.00 1.00 1.00 1.00 0.97 500x500 opaque stippled rectangle (161x145... + 1.95 1.63 0.98 0.99 3.80 1x1 tiled rectangle (161x145 tile) + 1.67 1.26 1.00 1.00 1.67 10x10 tiled rectangle (161x145 tile) + 1.13 1.14 1.14 1.14 1.14 100x100 tiled rectangle (161x145 tile) + 0.88 1.00 1.00 1.00 0.99 500x500 tiled rectangle (161x145 tile) + 1.93 1.63 1.00 1.00 3.53 1x1 tiled rectangle (216x208 tile) + 1.69 1.26 1.00 1.00 1.66 10x10 tiled rectangle (216x208 tile) + 1.00 1.00 1.00 1.00 1.00 100x100 tiled rectangle (216x208 tile) + 1.00 1.00 1.00 1.00 1.00 500x500 tiled rectangle (216x208 tile) + 1.82 1.70 1.00 1.00 3.38 1-pixel line segment + 2.07 1.56 0.90 1.00 3.31 10-pixel line segment + 1.29 1.10 1.00 1.00 1.27 100-pixel line segment + 1.05 1.06 1.03 1.03 1.09 500-pixel line segment + 1.30 1.13 1.00 1.00 1.29 100-pixel line segment (1 kid) + 1.32 1.15 1.00 1.00 1.32 100-pixel line segment (2 kids) + 1.33 1.16 1.00 1.00 1.33 100-pixel line segment (3 kids) + 1.92 1.64 1.00 1.00 3.73 10-pixel dashed segment + 1.34 1.16 1.00 1.00 1.34 100-pixel dashed segment + 1.24 1.11 0.99 0.97 1.23 100-pixel double-dashed segment + 1.72 1.77 1.00 1.00 3.25 10-pixel horizontal line segment + 1.83 1.66 1.01 1.00 3.54 100-pixel horizontal line segment + 1.86 1.30 1.00 1.00 1.84 500-pixel horizontal line segment + 2.11 1.52 1.00 0.99 3.02 10-pixel vertical line segment + 1.21 1.10 1.00 1.00 1.20 100-pixel vertical line segment + 1.03 1.03 1.00 1.00 1.02 500-pixel vertical line segment + 4.42 1.68 1.00 1.01 4.64 10x1 wide horizontal line segment + 1.83 1.31 1.00 1.00 1.83 100x10 wide horizontal line segment + 1.07 1.00 0.96 1.00 1.07 500x50 wide horizontal line segment + 4.10 1.67 1.00 1.00 4.62 10x1 wide vertical line segment + 1.50 1.24 1.06 1.06 1.48 100x10 wide vertical line segment + 1.06 1.03 1.00 1.00 1.05 500x50 wide vertical line segment + 2.54 1.61 1.00 1.00 3.61 1-pixel line + 2.71 1.48 1.00 1.00 2.67 10-pixel line + 1.19 1.09 1.00 1.00 1.19 100-pixel line + 1.04 1.02 1.00 1.00 1.03 500-pixel line + 2.68 1.51 0.98 1.00 3.17 10-pixel dashed line + 1.23 1.11 0.99 0.99 1.23 100-pixel dashed line + 1.15 1.08 1.00 1.00 1.15 100-pixel double-dashed line + 2.27 1.39 1.00 1.00 2.23 10x1 wide line + 1.20 1.09 1.00 1.00 1.20 100x10 wide line + 1.04 1.02 1.00 1.00 1.04 500x50 wide line + 1.52 1.45 1.00 1.00 1.52 100x10 wide dashed line + 1.54 1.47 1.00 1.00 1.54 100x10 wide double-dashed line + 1.97 1.30 0.96 0.95 1.95 10x10 rectangle outline + 1.44 1.27 1.00 1.00 1.43 100x100 rectangle outline + 3.22 2.16 1.10 1.09 3.61 500x500 rectangle outline + 1.95 1.34 1.00 1.00 1.90 10x10 wide rectangle outline + 1.14 1.14 1.00 1.00 1.13 100x100 wide rectangle outline + 1.00 1.00 1.00 1.00 1.00 500x500 wide rectangle outline + 1.57 1.72 1.00 1.00 3.03 1-pixel circle + 1.96 1.35 1.00 1.00 1.92 10-pixel circle + 1.21 1.07 0.86 0.97 1.20 100-pixel circle + 1.08 1.04 1.00 1.00 1.08 500-pixel circle + 1.39 1.19 1.03 1.03 1.38 100-pixel dashed circle + 1.21 1.11 1.00 1.00 1.23 100-pixel double-dashed circle + 1.59 1.28 1.00 1.00 1.58 10-pixel wide circle + 1.22 1.12 0.99 1.00 1.22 100-pixel wide circle + 1.06 1.04 1.00 1.00 1.05 500-pixel wide circle + 1.87 1.84 1.00 1.00 1.85 100-pixel wide dashed circle + 1.90 1.93 1.01 1.01 1.90 100-pixel wide double-dashed circle + 2.13 1.43 1.00 1.00 2.32 10-pixel partial circle + 1.42 1.18 1.00 1.00 1.42 100-pixel partial circle + 1.92 1.85 1.01 1.01 1.89 10-pixel wide partial circle + 1.73 1.67 1.00 1.00 1.73 100-pixel wide partial circle + 1.36 1.95 1.00 1.00 2.64 1-pixel solid circle + 2.02 1.37 1.00 1.00 2.03 10-pixel solid circle + 1.19 1.09 1.00 1.00 1.19 100-pixel solid circle + 1.02 0.99 1.00 1.00 1.01 500-pixel solid circle + 1.74 1.28 1.00 0.88 1.73 10-pixel fill chord partial circle + 1.31 1.13 1.00 1.00 1.31 100-pixel fill chord partial circle + 1.67 1.31 1.03 1.03 1.72 10-pixel fill slice partial circle + 1.30 1.13 1.00 1.00 1.28 100-pixel fill slice partial circle + 2.45 1.49 1.01 1.00 2.71 10-pixel ellipse + 1.22 1.10 1.00 1.00 1.22 100-pixel ellipse + 1.09 1.04 1.00 1.00 1.09 500-pixel ellipse + 1.90 1.28 1.00 1.00 1.89 100-pixel dashed ellipse + 1.62 1.24 0.96 0.97 1.61 100-pixel double-dashed ellipse + 2.43 1.50 1.00 1.00 2.42 10-pixel wide ellipse + 1.61 1.28 1.03 1.03 1.60 100-pixel wide ellipse + 1.08 1.05 1.00 1.00 1.08 500-pixel wide ellipse + 1.93 1.88 1.00 1.00 1.88 100-pixel wide dashed ellipse + 1.94 1.89 1.01 1.00 1.94 100-pixel wide double-dashed ellipse + 2.31 1.48 1.00 1.00 2.67 10-pixel partial ellipse + 1.38 1.17 1.00 1.00 1.38 100-pixel partial ellipse + 2.00 1.85 0.98 0.97 1.98 10-pixel wide partial ellipse + 1.89 1.86 1.00 1.00 1.89 100-pixel wide partial ellipse + 3.49 1.60 1.00 1.00 3.65 10-pixel filled ellipse + 1.67 1.26 1.00 1.00 1.67 100-pixel filled ellipse + 1.06 1.04 1.00 1.00 1.06 500-pixel filled ellipse + 2.38 1.43 1.01 1.00 2.32 10-pixel fill chord partial ellipse + 2.06 1.30 1.00 1.00 2.05 100-pixel fill chord partial ellipse + 2.27 1.41 1.00 1.00 2.27 10-pixel fill slice partial ellipse + 1.98 1.33 1.00 0.97 1.97 100-pixel fill slice partial ellipse + 57.46 1.99 1.01 1.00 114.92 Fill 1x1 equivalent triangle + 56.94 1.98 1.01 1.00 73.89 Fill 10x10 equivalent triangle + 6.07 1.75 1.00 1.00 6.07 Fill 100x100 equivalent triangle + 51.12 1.98 1.00 1.00 102.81 Fill 1x1 trapezoid + 51.42 1.82 1.01 1.00 94.89 Fill 10x10 trapezoid + 6.47 1.80 1.00 1.00 6.44 Fill 100x100 trapezoid + 1.56 1.28 1.00 0.99 1.56 Fill 300x300 trapezoid + 51.27 1.97 0.96 0.97 102.54 Fill 1x1 stippled trapezoid (8x8 stipple) + 51.73 2.00 1.02 1.02 67.92 Fill 10x10 stippled trapezoid (8x8 stipple) + 5.36 1.72 1.00 1.00 5.36 Fill 100x100 stippled trapezoid (8x8 stipple) + 1.54 1.26 1.00 1.00 1.59 Fill 300x300 stippled trapezoid (8x8 stipple) + 51.41 1.94 1.01 1.00 102.82 Fill 1x1 opaque stippled trapezoid (8x8 stipple) + 50.71 1.95 0.99 1.00 65.44 Fill 10x10 opaque stippled trapezoid (8x8... + 5.33 1.73 1.00 1.00 5.36 Fill 100x100 opaque stippled trapezoid (8x8... + 1.58 1.25 1.00 1.00 1.58 Fill 300x300 opaque stippled trapezoid (8x8... + 51.56 1.96 0.99 0.90 103.68 Fill 1x1 tiled trapezoid (4x4 tile) + 51.59 1.99 1.01 1.01 62.25 Fill 10x10 tiled trapezoid (4x4 tile) + 5.38 1.72 1.00 1.00 5.38 Fill 100x100 tiled trapezoid (4x4 tile) + 1.54 1.25 1.00 0.99 1.58 Fill 300x300 tiled trapezoid (4x4 tile) + 51.70 1.98 1.01 1.01 103.98 Fill 1x1 stippled trapezoid (17x15 stipple) + 44.86 1.97 1.00 1.00 44.86 Fill 10x10 stippled trapezoid (17x15 stipple) + 2.74 1.56 1.00 1.00 2.73 Fill 100x100 stippled trapezoid (17x15 stipple) + 1.29 1.14 1.00 1.00 1.27 Fill 300x300 stippled trapezoid (17x15 stipple) + 51.41 1.96 0.96 0.95 103.39 Fill 1x1 opaque stippled trapezoid (17x15... + 45.14 1.96 1.01 1.00 45.14 Fill 10x10 opaque stippled trapezoid (17x15... + 2.68 1.56 1.00 1.00 2.68 Fill 100x100 opaque stippled trapezoid (17x15... + 1.26 1.10 1.00 1.00 1.28 Fill 300x300 opaque stippled trapezoid (17x15... + 51.13 1.97 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (17x15 tile) + 47.58 1.96 1.00 1.00 47.86 Fill 10x10 tiled trapezoid (17x15 tile) + 2.74 1.56 1.00 1.00 2.74 Fill 100x100 tiled trapezoid (17x15 tile) + 1.29 1.14 1.00 1.00 1.28 Fill 300x300 tiled trapezoid (17x15 tile) + 51.13 1.97 0.99 0.97 103.39 Fill 1x1 stippled trapezoid (161x145 stipple) + 45.14 1.97 1.00 1.00 44.29 Fill 10x10 stippled trapezoid (161x145 stipple) + 3.02 1.77 1.12 1.12 3.38 Fill 100x100 stippled trapezoid (161x145 stipple) + 1.31 1.13 1.00 1.00 1.30 Fill 300x300 stippled trapezoid (161x145 stipple) + 51.27 1.97 1.00 1.00 103.10 Fill 1x1 opaque stippled trapezoid (161x145... + 45.01 1.97 1.00 1.00 45.01 Fill 10x10 opaque stippled trapezoid (161x145... + 2.67 1.56 1.00 1.00 2.69 Fill 100x100 opaque stippled trapezoid (161x145.. + 1.29 1.13 1.00 1.01 1.27 Fill 300x300 opaque stippled trapezoid (161x145.. + 51.41 1.96 1.00 0.99 103.39 Fill 1x1 tiled trapezoid (161x145 tile) + 45.01 1.96 0.98 1.00 45.01 Fill 10x10 tiled trapezoid (161x145 tile) + 2.62 1.36 1.00 1.00 2.69 Fill 100x100 tiled trapezoid (161x145 tile) + 1.27 1.13 1.00 1.00 1.22 Fill 300x300 tiled trapezoid (161x145 tile) + 51.13 1.98 1.00 1.00 103.39 Fill 1x1 tiled trapezoid (216x208 tile) + 45.14 1.97 1.01 0.99 45.14 Fill 10x10 tiled trapezoid (216x208 tile) + 2.62 1.55 1.00 1.00 2.71 Fill 100x100 tiled trapezoid (216x208 tile) + 1.28 1.13 1.00 1.00 1.20 Fill 300x300 tiled trapezoid (216x208 tile) + 50.71 1.95 1.00 1.00 54.70 Fill 10x10 equivalent complex polygon + 5.51 1.71 0.96 0.98 5.47 Fill 100x100 equivalent complex polygons + 8.39 1.97 1.00 1.00 16.75 Fill 10x10 64-gon (Convex) + 8.38 1.83 1.00 1.00 8.43 Fill 100x100 64-gon (Convex) + 8.50 1.96 1.00 1.00 16.64 Fill 10x10 64-gon (Complex) + 8.26 1.83 1.00 1.00 8.35 Fill 100x100 64-gon (Complex) + 14.09 1.87 1.00 1.00 14.05 Char in 80-char line (6x13) + 11.91 1.87 1.00 1.00 11.95 Char in 70-char line (8x13) + 11.16 1.85 1.01 1.00 11.10 Char in 60-char line (9x15) + 10.09 1.78 1.00 1.00 10.09 Char16 in 40-char line (k14) + 6.15 1.75 1.00 1.00 6.31 Char16 in 23-char line (k24) + 11.92 1.90 1.03 1.03 11.88 Char in 80-char line (TR 10) + 8.18 1.78 1.00 0.99 8.17 Char in 30-char line (TR 24) + 42.83 1.44 1.01 1.00 42.11 Char in 20/40/20 line (6x13, TR 10) + 27.45 1.43 1.01 1.01 27.45 Char16 in 7/14/7 line (k14, k24) + 12.13 1.85 1.00 1.00 12.05 Char in 80-char image line (6x13) + 10.00 1.84 1.00 1.00 10.00 Char in 70-char image line (8x13) + 9.18 1.83 1.00 1.00 9.12 Char in 60-char image line (9x15) + 9.66 1.82 0.98 0.95 9.66 Char16 in 40-char image line (k14) + 5.82 1.72 1.00 1.00 5.99 Char16 in 23-char image line (k24) + 8.70 1.80 1.00 1.00 8.65 Char in 80-char image line (TR 10) + 4.67 1.66 1.00 1.00 4.67 Char in 30-char image line (TR 24) + 84.43 1.47 1.00 1.00 124.18 Scroll 10x10 pixels + 3.73 1.50 1.00 0.98 3.73 Scroll 100x100 pixels + 1.00 1.00 1.00 1.00 1.00 Scroll 500x500 pixels + 84.43 1.51 1.00 1.00 134.02 Copy 10x10 from window to window + 3.62 1.51 0.98 0.98 3.62 Copy 100x100 from window to window + 0.89 1.00 1.00 1.00 1.00 Copy 500x500 from window to window + 57.06 1.99 1.00 1.00 88.64 Copy 10x10 from pixmap to window + 2.49 2.00 1.00 1.00 2.48 Copy 100x100 from pixmap to window + 1.00 0.91 1.00 1.00 0.98 Copy 500x500 from pixmap to window + 2.04 1.01 1.00 1.00 2.03 Copy 10x10 from window to pixmap + 1.05 1.00 1.00 1.00 1.05 Copy 100x100 from window to pixmap + 1.00 1.00 0.93 1.00 1.04 Copy 500x500 from window to pixmap + 58.52 1.03 1.03 1.02 57.95 Copy 10x10 from pixmap to pixmap + 2.40 1.00 1.00 1.00 2.45 Copy 100x100 from pixmap to pixmap + 1.00 1.00 1.00 1.00 1.00 Copy 500x500 from pixmap to pixmap + 51.57 1.92 1.00 1.00 85.75 Copy 10x10 1-bit deep plane + 6.37 1.75 1.01 1.01 6.37 Copy 100x100 1-bit deep plane + 1.26 1.11 1.00 1.00 1.24 Copy 500x500 1-bit deep plane + 4.23 1.63 0.98 0.97 4.38 Copy 10x10 n-bit deep plane + 1.04 1.02 1.00 1.00 1.04 Copy 100x100 n-bit deep plane + 1.00 1.00 1.00 1.00 1.00 Copy 500x500 n-bit deep plane + 6.45 1.98 1.00 1.26 12.80 PutImage 10x10 square + 1.10 1.87 1.00 1.83 2.11 PutImage 100x100 square + 1.02 1.93 1.00 1.91 1.91 PutImage 500x500 square + 4.17 1.78 1.00 1.40 7.18 PutImage XY 10x10 square + 1.27 1.49 0.97 1.48 2.10 PutImage XY 100x100 square + 1.00 1.50 1.00 1.50 1.52 PutImage XY 500x500 square + 1.07 1.01 1.00 1.00 1.06 GetImage 10x10 square + 1.01 1.00 1.00 1.00 1.01 GetImage 100x100 square + 1.00 1.00 1.00 1.00 1.00 GetImage 500x500 square + 1.56 1.00 0.99 0.97 1.56 GetImage XY 10x10 square + 1.02 1.00 1.00 1.00 1.02 GetImage XY 100x100 square + 1.00 1.00 1.00 1.00 1.00 GetImage XY 500x500 square + 1.00 1.00 1.01 0.98 0.95 X protocol NoOperation + 1.02 1.03 1.04 1.03 1.00 QueryPointer + 1.03 1.02 1.04 1.03 1.00 GetProperty +100.41 1.51 1.00 1.00 198.76 Change graphics context + 45.81 1.00 0.99 0.97 57.10 Create and map subwindows (4 kids) + 78.45 1.01 1.02 1.02 63.07 Create and map subwindows (16 kids) + 73.91 1.01 1.00 1.00 56.37 Create and map subwindows (25 kids) + 73.22 1.00 1.00 1.00 49.07 Create and map subwindows (50 kids) + 72.36 1.01 0.99 1.00 32.14 Create and map subwindows (75 kids) + 70.34 1.00 1.00 1.00 30.12 Create and map subwindows (100 kids) + 55.00 1.00 1.00 0.99 23.75 Create and map subwindows (200 kids) + 55.30 1.01 1.00 1.00 141.03 Create unmapped window (4 kids) + 55.38 1.01 1.01 1.00 163.25 Create unmapped window (16 kids) + 54.75 0.96 1.00 0.99 166.95 Create unmapped window (25 kids) + 54.83 1.00 1.00 0.99 178.81 Create unmapped window (50 kids) + 55.38 1.01 1.01 1.00 181.20 Create unmapped window (75 kids) + 55.38 1.01 1.01 1.00 181.20 Create unmapped window (100 kids) + 54.87 1.01 1.01 1.00 182.05 Create unmapped window (200 kids) + 28.13 1.00 1.00 1.00 30.75 Map window via parent (4 kids) + 36.14 1.01 1.01 1.01 32.58 Map window via parent (16 kids) + 26.13 1.00 0.98 0.95 29.85 Map window via parent (25 kids) + 40.07 1.00 1.01 1.00 27.57 Map window via parent (50 kids) + 23.26 0.99 1.00 1.00 18.23 Map window via parent (75 kids) + 22.91 0.99 1.00 0.99 16.52 Map window via parent (100 kids) + 27.79 1.00 1.00 0.99 12.50 Map window via parent (200 kids) + 22.35 1.00 1.00 1.00 56.19 Unmap window via parent (4 kids) + 9.57 1.00 0.99 1.00 89.78 Unmap window via parent (16 kids) + 80.77 1.01 1.00 1.00 103.85 Unmap window via parent (25 kids) + 96.34 1.00 1.00 1.00 116.06 Unmap window via parent (50 kids) + 99.72 1.00 1.00 1.00 124.93 Unmap window via parent (75 kids) +112.36 1.00 1.00 1.00 125.27 Unmap window via parent (100 kids) +105.41 1.00 1.00 0.99 120.00 Unmap window via parent (200 kids) + 51.29 1.03 1.02 1.02 74.19 Destroy window via parent (4 kids) + 86.75 0.99 0.99 0.99 116.87 Destroy window via parent (16 kids) +106.43 1.01 1.01 1.01 127.49 Destroy window via parent (25 kids) +120.34 1.01 1.01 1.00 140.11 Destroy window via parent (50 kids) +126.67 1.00 0.99 0.99 145.00 Destroy window via parent (75 kids) +126.11 1.01 1.01 1.00 140.56 Destroy window via parent (100 kids) +128.57 1.01 1.00 1.00 137.91 Destroy window via parent (200 kids) + 16.04 0.88 1.00 1.00 20.36 Hide/expose window via popup (4 kids) + 19.04 1.01 1.00 1.00 23.48 Hide/expose window via popup (16 kids) + 19.22 1.00 1.00 1.00 20.44 Hide/expose window via popup (25 kids) + 17.41 1.00 0.91 0.97 17.68 Hide/expose window via popup (50 kids) + 17.29 1.01 1.00 1.01 17.07 Hide/expose window via popup (75 kids) + 16.74 1.00 1.00 1.00 16.17 Hide/expose window via popup (100 kids) + 10.30 1.00 1.00 1.00 10.51 Hide/expose window via popup (200 kids) + 16.48 1.01 1.00 1.00 26.05 Move window (4 kids) + 17.01 0.95 1.00 1.00 23.97 Move window (16 kids) + 16.95 1.00 1.00 1.00 22.90 Move window (25 kids) + 16.05 1.01 1.00 1.00 21.32 Move window (50 kids) + 15.58 1.00 0.98 0.98 19.44 Move window (75 kids) + 14.98 1.02 1.03 1.03 18.17 Move window (100 kids) + 10.90 1.01 1.01 1.00 12.68 Move window (200 kids) + 49.42 1.00 1.00 1.00 198.27 Moved unmapped window (4 kids) + 50.72 0.97 1.00 1.00 193.66 Moved unmapped window (16 kids) + 50.87 1.00 0.99 1.00 195.09 Moved unmapped window (25 kids) + 50.72 1.00 1.00 1.00 189.34 Moved unmapped window (50 kids) + 50.87 1.00 1.00 1.00 191.33 Moved unmapped window (75 kids) + 50.87 1.00 1.00 0.90 186.71 Moved unmapped window (100 kids) + 50.87 1.00 1.00 1.00 179.19 Moved unmapped window (200 kids) + 41.04 1.00 1.00 1.00 56.61 Move window via parent (4 kids) + 69.81 1.00 1.00 1.00 130.82 Move window via parent (16 kids) + 95.81 1.00 1.00 1.00 141.92 Move window via parent (25 kids) + 95.98 1.00 1.00 1.00 149.43 Move window via parent (50 kids) + 96.59 1.01 1.01 1.00 153.98 Move window via parent (75 kids) + 97.19 1.00 1.00 1.00 157.30 Move window via parent (100 kids) + 96.67 1.00 0.99 0.96 159.44 Move window via parent (200 kids) + 17.75 1.01 1.00 1.00 27.61 Resize window (4 kids) + 17.94 1.00 1.00 0.99 25.42 Resize window (16 kids) + 17.92 1.01 1.00 1.00 24.47 Resize window (25 kids) + 17.24 0.97 1.00 1.00 24.14 Resize window (50 kids) + 16.81 1.00 1.00 0.99 22.75 Resize window (75 kids) + 16.08 1.00 1.00 1.00 21.20 Resize window (100 kids) + 12.92 1.00 0.99 1.00 16.26 Resize window (200 kids) + 52.94 1.01 1.00 1.00 327.12 Resize unmapped window (4 kids) + 53.60 1.01 1.01 1.01 333.71 Resize unmapped window (16 kids) + 52.99 1.00 1.00 1.00 337.29 Resize unmapped window (25 kids) + 51.98 1.00 1.00 1.00 329.38 Resize unmapped window (50 kids) + 53.05 0.89 1.00 1.00 322.60 Resize unmapped window (75 kids) + 53.05 1.00 1.00 1.00 318.08 Resize unmapped window (100 kids) + 53.11 1.00 1.00 0.99 306.21 Resize unmapped window (200 kids) + 16.76 1.00 0.96 1.00 19.46 Circulate window (4 kids) + 17.24 1.00 1.00 0.97 16.24 Circulate window (16 kids) + 16.30 1.03 1.03 1.03 15.85 Circulate window (25 kids) + 13.45 1.00 1.00 1.00 14.90 Circulate window (50 kids) + 12.91 1.00 1.00 1.00 13.06 Circulate window (75 kids) + 11.30 0.98 1.00 1.00 11.03 Circulate window (100 kids) + 7.58 1.01 1.01 0.99 7.47 Circulate window (200 kids) + 1.01 1.01 0.98 1.00 0.95 Circulate Unmapped window (4 kids) + 1.07 1.07 1.01 1.07 1.02 Circulate Unmapped window (16 kids) + 1.04 1.09 1.06 1.05 0.97 Circulate Unmapped window (25 kids) + 1.04 1.23 1.20 1.18 1.05 Circulate Unmapped window (50 kids) + 1.18 1.53 1.19 1.45 1.24 Circulate Unmapped window (75 kids) + 1.08 1.02 1.01 1.74 1.01 Circulate Unmapped window (100 kids) + 1.01 1.12 0.98 0.91 0.97 Circulate Unmapped window (200 kids) + </verb> + +<sect2>Profiling with OProfile + +<p>OProfile (available from http://oprofile.sourceforge.net/) is a +system-wide profiler for Linux systems that uses processor-level +counters to collect sampling data. OProfile can provide information +that is similar to that provided by <tt/gprof/, but without the +necessity of recompiling the program with special instrumentation (i.e., +OProfile can collect statistical profiling information about optimized +programs). A test harness was developed to collect OProfile data for +each <tt/x11perf/ test individually. + +<p>Test runs were performed using the RETIRED_INSNS counter on the AMD +Athlon and the CPU_CLK_HALTED counter on the Intel Pentium III (with a +test configuration different from the one described above). We have +examined OProfile output and have compared it with <tt/gprof/ output. +This investigation has not produced results that yield performance +increases in <tt/x11perf/ numbers. + +<!-- +<sect3>Retired Instructions + +<p>The initial tests using OProfile were done using the RETIRED_INSNS +counter with DMX running on the dual-processor AMD Athlon machine - the +same test configuration that was described above and that was used for +other tests. The RETIRED_INSNS counter counts retired instructions and +showed drawing, text, copying, and image tests to be dominated (> +30%) by calls to Hash(), SecurityLookupIDByClass(), +SecurityLookupIDByType(), and StandardReadRequestFromClient(). Some of +these tests also executed significant instructions in +WaitForSomething(). + +<p>In contrast, the window tests executed significant +instructions in SecurityLookupIDByType(), Hash(), +StandardReadRequestFromClient(), but also executed significant +instructions in other routines, such as ConfigureWindow(). Some time +was spent looking at Hash() function, but optimizations in this routine +did not lead to a dramatic increase in <tt/x11perf/ performance. +--> + +<!-- +<sect3>Clock Cycles + +<p>Retired instructions can be misleading because Intel/AMD instructions +execute in variable amounts of time. The OProfile tests were repeated +using the Intel CPU_CLK_HALTED counter with DMX running on the second +back-end machine. Note that this is a different test configuration that +the one described above. However, these tests show the amount of time +(as measured in CPU cycles) that are spent in each routine. Because +<tt/x11perf/ was running on the first back-end machine and because +window optimizations were on, the load on the second back-end machine +was not significant. + +<p>Using CPU_CLK_HALTED, DMX showed simple drawing +tests spending more than 10% of their time in +StandardReadRequestFromClient(), with significant time (> 20% total) +spent in SecurityLookupIDByClass(), WaitForSomething(), and Dispatch(). +For these tests, < 5% of the time was spent in Hash(), which explains +why optimizing the Hash() routine did not impact <tt/x11perf/ results. + +<p>The trapezoid, text, scrolling, copying, and image tests were +dominated by time in ProcFillPoly(), PanoramiXFillPoly(), dmxFillPolygon(), +SecurityLookupIDByClass(), SecurityLookupIDByType(), and +StandardReadRequestFromClient(). Hash() time was generally above 5% but +less than 10% of total time. +--> + +<sect2>X Test Suite + +<p>The X Test Suite was run on the fully optimized DMX server using the +configuration described above. The following failures were noted: + <verb> +XListPixmapFormats: Test 1 [1] +XChangeWindowAttributes: Test 32 [1] +XCreateWindow: Test 30 [1] +XFreeColors: Test 4 [3] +XCopyArea: Test 13, 17, 21, 25, 30 [2] +XCopyPlane: Test 11, 15, 27, 31 [2] +XSetFontPath: Test 4 [1] +XChangeKeyboardControl: Test 9, 10 [1] + +[1] Previously documented errors expected from the Xinerama + implementation (see Phase I discussion). +[2] Newly noted errors that have been verified as expected + behavior of the Xinerama implementation. +[3] Newly noted error that has been verified as a Xinerama + implementation bug. + </verb> + +<!-- ============================================================ --> +<sect1>Phase III + +<p>During the third phase of development, support was provided for the +following extensions: SHAPE, RENDER, XKEYBOARD, XInput. + +<sect2>SHAPE + +<p>The SHAPE extension is supported. Test applications (e.g., xeyes and +oclock) and window managers that make use of the SHAPE extension will +work as expected. + +<sect2>RENDER + +<p>The RENDER extension is supported. The version included in the DMX +CVS tree is version 0.2, and this version is fully supported by Xdmx. +Applications using only version 0.2 functions will work correctly; +however, some apps that make use of functions from later versions do not +properly check the extension's major/minor version numbers. These apps +will fail with a Bad Implementation error when using post-version 0.2 +functions. This is expected behavior. When the DMX CVS tree is updated +to include newer versions of RENDER, support for these newer functions +will be added to the DMX X server. + +<sect2>XKEYBOARD + +<p>The XKEYBOARD extension is supported. If present on the back-end X +servers, the XKEYBOARD extension will be used to obtain information +about the type of the keyboard for initialization. Otherwise, the +keyboard will be initialized using defaults. Note that this departs +from older behavior: when Xdmx is compiled without XKEYBOARD support, +the map from the back-end X server will be preserved. With XKEYBOARD +support, the map is not preserved because better information and control +of the keyboard is available. + +<sect2>XInput + +<p>The XInput extension is supported. Any device can be used as a core +device and be used as an XInput extension device, with the exception of +core devices on the back-end servers. This limitation is present +because cursor handling on the back-end requires that the back-end +cursor sometimes track the Xdmx core cursor -- behavior that is +incompatible with using the back-end pointer as a non-core device. + +<p>Currently, back-end extension devices are not available as Xdmx +extension devices, but this limitation should be removed in the future. + +<p>To demonstrate the XInput extension, and to provide more examples for +low-level input device driver writers, USB device drivers have been +written for mice (usb-mou), keyboards (usb-kbd), and +non-mouse/non-keyboard USB devices (usb-oth). Please see the man page +for information on Linux kernel drivers that are required for using +these Xdmx drivers. + +<sect2>DPMS + +<p>The DPMS extension is exported but does not do anything at this time. + +<sect2>Other Extensions + +<p>The LBX, + SECURITY, + XC-APPGROUP, and + XFree86-Bigfont +extensions do not require any special Xdmx support and have been exported. + +<p>The + BIG-REQUESTS, + DEC-XTRAP, + DOUBLE-BUFFER, + Extended-Visual-Information, + FontCache, + GLX, + MIT-SCREEN-SAVER, + MIT-SHM, + MIT-SUNDRY-NONSTANDARD, + RECORD, + SECURITY, + SGI-GLX, + SYNC, + TOG-CUP, + X-Resource, + XC-MISC, + XFree86-DGA, + XFree86-DRI, + XFree86-Misc, + XFree86-VidModeExtension, and + XVideo +extensions are <it/not/ supported at this time, but will be evaluated +for inclusion in future DMX releases. <bf>See below for additional work +on extensions after Phase III.</bf> + +<sect1>Phase IV + +<sect2>Moving to XFree86 4.3.0 + +<p>For Phase IV, the recent release of XFree86 4.3.0 (27 February 2003) +was merged onto the dmx.sourceforge.net CVS trunk and all work is +proceeding using this tree. + +<sect2>Extensions + +<sect3>XC-MISC (supported) + +<p>XC-MISC is used internally by the X library to recycle XIDs from the +X server. This is important for long-running X server sessions. Xdmx +supports this extension. The X Test Suite passed and failed the exact +same tests before and after this extension was enabled. +<!-- Tested February/March 2003 --> + +<sect3>Extended-Visual-Information (supported) + +<p>The Extended-Visual-Information extension provides a method for an X +client to obtain detailed visual information. Xdmx supports this +extension. It was tested using the <tt>hw/dmx/examples/evi</tt> example +program. <bf/Note that this extension is not Xinerama-aware/ -- it will +return visual information for each screen even though Xinerama is +causing the X server to export a single logical screen. +<!-- Tested March 2003 --> + +<sect3>RES (supported) + +<p>The X-Resource extension provides a mechanism for a client to obtain +detailed information about the resources used by other clients. This +extension was tested with the <tt>hw/dmx/examples/res</tt> program. The +X Test Suite passed and failed the exact same tests before and after +this extension was enabled. +<!-- Tested March 2003 --> + +<sect3>BIG-REQUESTS (supported) + +<p>This extension enables the X11 protocol to handle requests longer +than 262140 bytes. The X Test Suite passed and failed the exact same +tests before and after this extension was enabled. +<!-- Tested March 2003 --> + +<sect3>XSYNC (supported) + +<p>This extension provides facilities for two different X clients to +synchronize their requests. This extension was minimally tested with +<tt/xdpyinfo/ and the X Test Suite passed and failed the exact same +tests before and after this extension was enabled. +<!-- Tested March 2003 --> + +<sect3>XTEST, RECORD, DEC-XTRAP (supported) and XTestExtension1 (not supported) + +<p>The XTEST and RECORD extension were developed by the X Consortium for +use in the X Test Suite and are supported as a standard in the X11R6 +tree. They are also supported in Xdmx. When X Test Suite tests that +make use of the XTEST extension are run, Xdmx passes and fails exactly +the same tests as does a standard XFree86 X server. When the +<tt/rcrdtest/ test (a part of the X Test Suite that verifies the RECORD +extension) is run, Xdmx passes and fails exactly the same tests as does +a standard XFree86 X server. <!-- Tested February/March 2003 --> + +<p>There are two older XTEST-like extensions: DEC-XTRAP and +XTestExtension1. The XTestExtension1 extension was developed for use by +the X Testing Consortium for use with a test suite that eventually +became (part of?) the X Test Suite. Unlike XTEST, which only allows +events to be sent to the server, the XTestExtension1 extension also +allowed events to be recorded (similar to the RECORD extension). The +second is the DEC-XTRAP extension that was developed by the Digital +Equipment Corporation. + +<p>The DEC-XTRAP extension is available from Xdmx and has been tested +with the <tt/xtrap*/ tools which are distributed as standard X11R6 +clients. <!-- Tested March 2003 --> + +<p>The XTestExtension1 is <em/not/ supported because it does not appear +to be used by any modern X clients (the few that support it also support +XTEST) and because there are no good methods available for testing that +it functions correctly (unlike XTEST and DEC-XTRAP, the code for +XTestExtension1 is not part of the standard X server source tree, so +additional testing is important). <!-- Tested March 2003 --> + +<p>Most of these extensions are documented in the X11R6 source tree. +Further, several original papers exist that this author was unable to +locate -- for completeness and historical interest, citations are +provide: +<descrip> +<tag/XRECORD/ Martha Zimet. Extending X For Recording. 8th Annual X +Technical Conference Boston, MA January 24-26, 1994. +<tag/DEC-XTRAP/ Dick Annicchiarico, Robert Chesler, Alan Jamison. XTrap +Architecture. Digital Equipment Corporation, July 1991. +<tag/XTestExtension1/ Larry Woestman. X11 Input Synthesis Extension +Proposal. Hewlett Packard, November 1991. +</descrip> + +<sect3>MIT-MISC (not supported) + +<p>The MIT-MISC extension is used to control a bug-compatibility flag +that provides compatibility with xterm programs from X11R1 and X11R2. +There does not appear to be a single client available that makes use of +this extension and there is not way to verify that it works correctly. +The Xdmx server does <em/not/ support MIT-MISC. + +<sect3>SCREENSAVER (not supported) + +<p>This extension provides special support for the X screen saver. It +was tested with beforelight, which appears to be the only client that +works with it. When Xinerama was not active, <tt/beforelight/ behaved +as expected. However, when Xinerama was active, <tt/beforelight/ did +not behave as expected. Further, when this extension is not active, +<tt/xscreensaver/ (a widely-used X screen saver program) did not behave +as expected. Since this extension is not Xinerama-aware and is not +commonly used with expected results by clients, we have left this +extension disabled at this time. + +<sect3>GLX (supported) + +<p>The GLX extension provides OpenGL and GLX windowing support. In +Xdmx, the extension is called glxProxy, and it is Xinerama aware. It +works by either feeding requests forward through Xdmx to each of the +back-end servers or handling them locally. All rendering requests are +handled on the back-end X servers. This code was donated to the DMX +project by SGI. For the X Test Suite results comparison, see below. + +<sect3>RENDER (supported) + +<p>The X Rendering Extension (RENDER) provides support for digital image +composition. Geometric and text rendering are supported. RENDER is +partially Xinerama-aware, with text and the most basic compositing +operator; however, its higher level primitives (triangles, triangle +strips, and triangle fans) are not yet Xinerama-aware. The RENDER +extension is still under development, and is currently at version 0.8. +Additional support will be required in DMX as more primitives and/or +requests are added to the extension. + +<p>There is currently no test suite for the X Rendering Extension; +however, there has been discussion of developing a test suite as the +extension matures. When that test suite becomes available, additional +testing can be performed with Xdmx. The X Test Suite passed and failed +the exact same tests before and after this extension was enabled. + +<sect3>Summary + +<!-- WARNING: this list is duplicated in the "Common X extension +support" section --> +<p>To summarize, the following extensions are currently supported: + BIG-REQUESTS, + DEC-XTRAP, + DMX, + DPMS, + Extended-Visual-Information, + GLX, + LBX, + RECORD, + RENDER, + SECURITY, + SHAPE, + SYNC, + X-Resource, + XC-APPGROUP, + XC-MISC, + XFree86-Bigfont, + XINERAMA, + XInputExtension, + XKEYBOARD, and + XTEST. + +<p>The following extensions are <em/not/ supported at this time: + DOUBLE-BUFFER, + FontCache, + MIT-SCREEN-SAVER, + MIT-SHM, + MIT-SUNDRY-NONSTANDARD, + TOG-CUP, + XFree86-DGA, + XFree86-Misc, + XFree86-VidModeExtension, + XTestExtensionExt1, and + XVideo. + +<sect2>Additional Testing with the X Test Suite + +<sect3>XFree86 without XTEST + +<p>After the release of XFree86 4.3.0, we retested the XFree86 X server +with and without using the XTEST extension. When the XTEST extension +was <em/not/ used for testing, the XFree86 4.3.0 server running on our +usual test system with a Radeon VE card reported unexpected failures in +the following tests: +<verb> +XListPixmapFormats: Test 1 +XChangeKeyboardControl: Tests 9, 10 +XGetDefault: Test 5 +XRebindKeysym: Test 1 +</verb> + +<sect3>XFree86 with XTEST + +<p>When using the XTEST extension, the XFree86 4.3.0 server reported the +following errors: +<verb> +XListPixmapFormats: Test 1 +XChangeKeyboardControl: Tests 9, 10 +XGetDefault: Test 5 +XRebindKeysym: Test 1 + +XAllowEvents: Tests 20, 21, 24 +XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 +XGrabKey: Test 8 +XSetPointerMapping: Test 3 +XUngrabButton: Test 4 +</verb> + +<p>While these errors may be important, they will probably be fixed +eventually in the XFree86 source tree. We are particularly interested +in demonstrating that the Xdmx server does not introduce additional +failures that are not known Xinerama failures. + +<sect3>Xdmx with XTEST, without Xinerama, without GLX + +<p>Without Xinerama, but using the XTEST extension, the following errors +were reported from Xdmx (note that these are the same as for the XFree86 +4.3.0, except that XGetDefault no longer fails): +<verb> +XListPixmapFormats: Test 1 +XChangeKeyboardControl: Tests 9, 10 +XRebindKeysym: Test 1 + +XAllowEvents: Tests 20, 21, 24 +XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 +XGrabKey: Test 8 +XSetPointerMapping: Test 3 +XUngrabButton: Test 4 +</verb> + +<sect3>Xdmx with XTEST, with Xinerama, without GLX + +<p>With Xinerama, using the XTEST extension, the following errors +were reported from Xdmx: +<verb> +XListPixmapFormats: Test 1 +XChangeKeyboardControl: Tests 9, 10 +XRebindKeysym: Test 1 + +XAllowEvents: Tests 20, 21, 24 +XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 +XGrabKey: Test 8 +XSetPointerMapping: Test 3 +XUngrabButton: Test 4 + +XCopyPlane: Tests 13, 22, 31 (well-known XTEST/Xinerama interaction issue) +XDrawLine: Test 67 +XDrawLines: Test 91 +XDrawSegments: Test 68 +</verb> +Note that the first two sets of errors are the same as for the XFree86 +4.3.0 server, and that the XCopyPlane error is a well-known error +resulting from an XTEST/Xinerama interaction when the request crosses a +screen boundary. The XDraw* errors are resolved when the tests are run +individually and they do not cross a screen boundary. We will +investigate these errors further to determine their cause. + +<sect3>Xdmx with XTEST, with Xinerama, with GLX + +<p>With GLX enabled, using the XTEST extension, the following errors +were reported from Xdmx (these results are from early during the Phase +IV development, but were confirmed with a late Phase IV snapshot): +<verb> +XListPixmapFormats: Test 1 +XChangeKeyboardControl: Tests 9, 10 +XRebindKeysym: Test 1 + +XAllowEvents: Tests 20, 21, 24 +XGrabButton: Tests 5, 9-12, 14, 16, 19, 21-25 +XGrabKey: Test 8 +XSetPointerMapping: Test 3 +XUngrabButton: Test 4 + +XClearArea: Test 8 +XCopyArea: Tests 4, 5, 11, 14, 17, 23, 25, 27, 30 +XCopyPlane: Tests 6, 7, 10, 19, 22, 31 +XDrawArcs: Tests 89, 100, 102 +XDrawLine: Test 67 +XDrawSegments: Test 68 +</verb> +Note that the first two sets of errors are the same as for the XFree86 +4.3.0 server, and that the third set has different failures than when +Xdmx does not include GLX support. Since the GLX extension adds new +visuals to support GLX's visual configs and the X Test Suite runs tests +over the entire set of visuals, additional rendering tests were run and +presumably more of them crossed a screen boundary. This conclusion is +supported by the fact that nearly all of the rendering errors reported +are resolved when the tests are run individually and they do no cross a +screen boundary. + +<p>Further, when hardware rendering is disabled on the back-end displays, +many of the errors in the third set are eliminated, leaving only: +<verb> +XClearArea: Test 8 +XCopyArea: Test 4, 5, 11, 14, 17, 23, 25, 27, 30 +XCopyPlane: Test 6, 7, 10, 19, 22, 31 +</verb> + +<sect3>Conclusion + +<p>We conclude that all of the X Test Suite errors reported for Xdmx are +the result of errors in the back-end X server or the Xinerama +implementation. Further, all of these errors that can be reasonably +fixed at the Xdmx layer have been. (Where appropriate, we have +submitted patches to the XFree86 and Xinerama upstream maintainers.) + +<sect2>Dynamic Reconfiguration + +<p>During this development phase, dynamic reconfiguration support was +added to DMX. This support allows an application to change the position +and offset of a back-end server's screen. For example, if the +application would like to shift a screen slightly to the left, it could +query Xdmx for the screen's <x,y> position and then dynamically +reconfigure that screen to be at position <x+10,y>. When a screen +is dynamically reconfigured, input handling and a screen's root window +dimensions are adjusted as needed. These adjustments are transparent to +the user. + +<sect3>Dynamic reconfiguration extension + +<p>The application interface to DMX's dynamic reconfiguration is through +a function in the DMX extension library: +<verb> +Bool DMXReconfigureScreen(Display *dpy, int screen, int x, int y) +</verb> +where <it/dpy/ is DMX server's display, <it/screen/ is the number of the +screen to be reconfigured, and <it/x/ and <it/y/ are the new upper, +left-hand coordinates of the screen to be reconfigured. + +<p>The coordinates are not limited other than as required by the X +protocol, which limits all coordinates to a signed 16 bit number. In +addition, all coordinates within a screen must also be legal values. +Therefore, setting a screen's upper, left-hand coordinates such that the +right or bottom edges of the screen is greater than 32,767 is illegal. + +<sect3>Bounding box + +<p>When the Xdmx server is started, a bounding box is calculated from +the screens' layout given either on the command line or in the +configuration file. This bounding box is currently fixed for the +lifetime of the Xdmx server. + +<p>While it is possible to move a screen outside of the bounding box, it +is currently not possible to change the dimensions of the bounding box. +For example, it is possible to specify coordinates of <-100,-100> +for the upper, left-hand corner of the bounding box, which was +previously at coordinates <0,0>. As expected, the screen is moved +down and to the right; however, since the bounding box is fixed, the +left side and upper portions of the screen exposed by the +reconfiguration are no longer accessible on that screen. Those +inaccessible regions are filled with black. + +<p>This fixed bounding box limitation will be addressed in a future +development phase. + +<sect3>Sample applications + +<p>An example of where this extension is useful is in setting up a video +wall. It is not always possible to get everything perfectly aligned, +and sometimes the positions are changed (e.g., someone might bump into a +projector). Instead of physically moving projectors or monitors, it is +now possible to adjust the positions of the back-end server's screens +using the dynamic reconfiguration support in DMX. + +<p>Other applications, such as automatic setup and calibration tools, +can make use of dynamic reconfiguration to correct for projector +alignment problems, as long as the projectors are still arranged +rectilinearly. Horizontal and vertical keystone correction could be +applied to projectors to correct for non-rectilinear alignment problems; +however, this must be done external to Xdmx. + +<p>A sample test program is included in the DMX server's examples +directory to demonstrate the interface and how an application might use +dynamic reconfiguration. See <tt/dmxreconfig.c/ for details. + +<sect3>Additional notes + +<p>In the original development plan, Phase IV was primarily devoted to +adding OpenGL support to DMX; however, SGI became interested in the DMX +project and developed code to support OpenGL/GLX. This code was later +donated to the DMX project and integrated into the DMX code base, which +freed the DMX developers to concentrate on dynamic reconfiguration (as +described above). + +<sect2>Doxygen documentation + +<p>Doxygen is an open-source (GPL) documentation system for generating +browseable documentation from stylized comments in the source code. We +have placed all of the Xdmx server and DMX protocol source code files +under Doxygen so that comprehensive documentation for the Xdmx source +code is available in an easily browseable format. + +<sect2>Valgrind + +<p>Valgrind, an open-source (GPL) memory debugger for Linux, was used to +search for memory management errors. Several memory leaks were detected +and repaired. The following errors were not addressed: +<enum> + <item> + When the X11 transport layer sends a reply to the client, only + those fields that are required by the protocol are filled in -- + unused fields are left as uninitialized memory and are therefore + noted by valgrind. These instances are not errors and were not + repaired. + <item> + At each server generation, glxInitVisuals allocates memory that + is never freed. The amount of memory lost each generation + approximately equal to 128 bytes for each back-end visual. + Because the code involved is automatically generated, this bug + has not been fixed and will be referred to SGI. + <item> + At each server generation, dmxRealizeFont calls XLoadQueryFont, + which allocates a font structure that is not freed. + dmxUnrealizeFont can free the font structure for the first + screen, but cannot free it for the other screens since they are + already closed by the time dmxUnrealizeFont could free them. + The amount of memory lost each generation is approximately equal + to 80 bytes per font per back-end. When this bug is fixed in + the the X server's device-independent (dix) code, DMX will be + able to properly free the memory allocated by XLoadQueryFont. +</enum> + +<sect2>RATS + +<p>RATS (Rough Auditing Tool for Security) is an open-source (GPL) +security analysis tool that scans source code for common +security-related programming errors (e.g., buffer overflows and TOCTOU +races). RATS was used to audit all of the code in the hw/dmx directory +and all "High" notations were checked manually. The code was either +re-written to eliminate the warning, or a comment containing "RATS" was +inserted on the line to indicate that a human had checked the code. +Unrepaired warnings are as follows: +<enum> + <item> + Fixed-size buffers are used in many areas, but code has been + added to protect against buffer overflows (e.g., XmuSnprint). + The only instances that have not yet been fixed are in + config/xdmxconfig.c (which is not part of the Xdmx server) and + input/usb-common.c. + <item> + vprintf and vfprintf are used in the logging routines. In + general, all uses of these functions (e.g., dmxLog) provide a + constant format string from a trusted source, so the use is + relatively benign. + <item> + glxProxy/glxscreens.c uses getenv and strcat. The use of these + functions is safe and will remain safe as long as + ExtensionsString is longer then GLXServerExtensions (ensuring + this may not be ovious to the casual programmer, but this is in + automatically generated code, so we hope that the generator + enforces this constraint). +</enum> + + </article> + + <!-- Local Variables: --> + <!-- fill-column: 72 --> + <!-- End: --> diff --git a/xorg-server/hw/dmx/glxProxy/glxcmds.c b/xorg-server/hw/dmx/glxProxy/glxcmds.c index 31fd431e7..a2fe0b27b 100644 --- a/xorg-server/hw/dmx/glxProxy/glxcmds.c +++ b/xorg-server/hw/dmx/glxProxy/glxcmds.c @@ -1,3610 +1,3610 @@ -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "dmx.h" -#include "dmxwindow.h" -#include "dmxpixmap.h" -#include "dmxfont.h" -#include "dmxsync.h" - -#undef Xmalloc -#undef Xcalloc -#undef Xrealloc -#undef Xfree - -#include "glxserver.h" -#include <GL/glxtokens.h> -#include "g_disptab.h" -#include <pixmapstr.h> -#include <windowstr.h> -#include "glxutil.h" -#include "glxext.h" -#include "unpack.h" - -#include "GL/glxproto.h" -#include "glxvendor.h" -#include "glxvisuals.h" -#include "glxswap.h" - -#ifdef PANORAMIX -#include "panoramiXsrv.h" -#endif - -extern __GLXFBConfig **__glXFBConfigs; -extern int __glXNumFBConfigs; - -extern __GLXFBConfig *glxLookupFBConfig( GLXFBConfigID id ); -extern __GLXFBConfig *glxLookupFBConfigByVID( VisualID vid ); -extern __GLXFBConfig *glxLookupBackEndFBConfig( GLXFBConfigID id, int screen ); -extern int glxIsExtensionSupported( char *ext ); -extern int __glXGetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc); - -#define BE_TO_CLIENT_ERROR(x) \ - ( (x) >= __glXerrorBase ? \ - (x) - dmxScreen->glxErrorBase + __glXerrorBase \ - : (x) ) - -Display *GetBackEndDisplay( __GLXclientState *cl, int s ) -{ - if (! cl->be_displays[s] ) { - cl->be_displays[s] = XOpenDisplay( DisplayString(dmxScreens[s].beDisplay) ); - } - return( cl->be_displays[s] ); -} - -/* -** Create a GL context with the given properties. -*/ -static int CreateContext(__GLXclientState *cl, - GLXContextID gcId, - VisualID vid, GLXFBConfigID fbconfigId, - int screen, - GLXContextID shareList, - int isDirect ) -{ - ClientPtr client = cl->client; - xGLXCreateContextReq *be_req; - xGLXCreateNewContextReq *be_new_req; - VisualPtr pVisual; - ScreenPtr pScreen; - __GLXcontext *glxc, *shareglxc; - __GLXvisualConfig *pGlxVisual; - __GLXscreenInfo *pGlxScreen; - VisualID visual = vid; - GLint i; - int from_screen = screen; - int to_screen = screen; - DMXScreenInfo *dmxScreen; - VisualID be_vid; - GLXFBConfigID be_fbconfigId; - int num_be_screens; - Display *dpy; - - /* - ** Check if screen exists. - */ - if (screen >= screenInfo.numScreens) { - client->errorValue = screen; - return BadValue; - } - - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - /* - ** Find the display list space that we want to share. - ** - */ - if (shareList == None) { - shareglxc = NULL; - } else { - shareglxc = (__GLXcontext *) LookupIDByType(shareList, __glXContextRes); - if (!shareglxc) { - client->errorValue = shareList; - return __glXBadContext; - } - } - - /* - ** Allocate memory for the new context - */ - glxc = __glXCalloc(1, sizeof(__GLXcontext)); - if (!glxc) { - return BadAlloc; - } - - pScreen = screenInfo.screens[screen]; - pGlxScreen = &__glXActiveScreens[screen]; - - if (fbconfigId != None) { - glxc->pFBConfig = glxLookupFBConfig( fbconfigId ); - if (!glxc->pFBConfig) { - client->errorValue = fbconfigId; - __glXFree( glxc ); - return BadValue; - } - visual = glxc->pFBConfig->associatedVisualId; - } - else { - glxc->pFBConfig = NULL; - } - - if (visual != None) { - /* - ** Check if the visual ID is valid for this screen. - */ - pVisual = pScreen->visuals; - for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { - if (pVisual->vid == visual) { - break; - } - } - if (i == pScreen->numVisuals) { - client->errorValue = visual; - __glXFree( glxc ); - return BadValue; - } - - pGlxVisual = pGlxScreen->pGlxVisual; - for (i = 0; i < pGlxScreen->numVisuals; i++, pGlxVisual++) { - if (pGlxVisual->vid == visual) { - break; - } - } - if (i == pGlxScreen->numVisuals) { - /* - ** Visual not support on this screen by this OpenGL implementation. - */ - client->errorValue = visual; - __glXFree( glxc ); - return BadValue; - } - - if ( glxc->pFBConfig == NULL ) { - glxc->pFBConfig = glxLookupFBConfigByVID( visual ); - - if ( glxc->pFBConfig == NULL ) { - /* - * visual does not have an FBConfig ??? - client->errorValue = visual; - __glXFree( glxc ); - return BadValue; - */ - } - } - } - else { - pVisual = NULL; - pGlxVisual = NULL; - } - - glxc->pScreen = pScreen; - glxc->pGlxScreen = pGlxScreen; - glxc->pVisual = pVisual; - glxc->pGlxVisual = pGlxVisual; - - /* - * allocate memory for back-end servers info - */ - num_be_screens = to_screen - from_screen + 1; - glxc->real_ids = (XID *)__glXMalloc(sizeof(XID) * num_be_screens); - if (!glxc->real_ids) { - return BadAlloc; - } - glxc->real_vids = (XID *)__glXMalloc(sizeof(XID) * num_be_screens); - if (!glxc->real_vids) { - return BadAlloc; - } - - for (screen = from_screen; screen <= to_screen; screen++) { - int sent = 0; - pScreen = screenInfo.screens[screen]; - pGlxScreen = &__glXActiveScreens[screen]; - dmxScreen = &dmxScreens[screen]; - - if (glxc->pFBConfig) { - __GLXFBConfig *beFBConfig = glxLookupBackEndFBConfig( glxc->pFBConfig->id, - screen ); - be_fbconfigId = beFBConfig->id; - } - - if (pGlxVisual) { - - be_vid = glxMatchGLXVisualInConfigList( pGlxVisual, - dmxScreen->glxVisuals, - dmxScreen->numGlxVisuals ); - - if (!be_vid) { - /* visual is not supported on the back-end server */ - __glXFree( glxc->real_ids ); - __glXFree( glxc->real_vids ); - __glXFree( glxc ); - return BadValue; - } - } - - glxc->real_ids[screen-from_screen] = XAllocID(GetBackEndDisplay(cl,screen)); - - /* send the create context request to the back-end server */ - dpy = GetBackEndDisplay(cl,screen); - if (glxc->pFBConfig) { - /*Since for a certain visual both RGB and COLOR INDEX - *can be on then the only parmeter to choose the renderType - * should be the class of the colormap since all 4 first - * classes does not support RGB mode only COLOR INDEX , - * and so TrueColor and DirectColor does not support COLOR INDEX*/ - int renderType = glxc->pFBConfig->renderType; - if ( pVisual ) { - switch ( pVisual->class ){ - case PseudoColor: - case StaticColor: - case GrayScale: - case StaticGray: - renderType = GLX_COLOR_INDEX_TYPE; - break; - case TrueColor: - case DirectColor: - default: - renderType = GLX_RGBA_TYPE; - break; - } - } - if ( __GLX_IS_VERSION_SUPPORTED(1,3) ) { - LockDisplay(dpy); - GetReq(GLXCreateNewContext,be_new_req); - be_new_req->reqType = dmxScreen->glxMajorOpcode; - be_new_req->glxCode = X_GLXCreateNewContext; - be_new_req->context = (unsigned int)glxc->real_ids[screen-from_screen]; - be_new_req->fbconfig = (unsigned int)be_fbconfigId; - be_new_req->screen = DefaultScreen(dpy); - be_new_req->renderType = renderType; - - be_new_req->shareList = (shareglxc ? shareglxc->real_ids[screen-from_screen] : 0); - be_new_req->isDirect = 0; - UnlockDisplay(dpy); - glxc->real_vids[screen-from_screen] = be_fbconfigId; - sent = 1; - } - else if (glxIsExtensionSupported("GLX_SGIX_fbconfig")) { - - xGLXCreateContextWithConfigSGIXReq *ext_req; - xGLXVendorPrivateReq *vpreq; - LockDisplay(dpy); - GetReqExtra(GLXVendorPrivate, - sz_xGLXCreateContextWithConfigSGIXReq - sz_xGLXVendorPrivateReq, - vpreq); - ext_req = (xGLXCreateContextWithConfigSGIXReq *)vpreq; - ext_req->reqType = dmxScreen->glxMajorOpcode; - ext_req->glxCode = X_GLXVendorPrivate; - ext_req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX; - ext_req->context = (unsigned int)glxc->real_ids[screen-from_screen]; - ext_req->fbconfig = (unsigned int)be_fbconfigId; - ext_req->screen = DefaultScreen(dpy); - ext_req->renderType = renderType; - ext_req->shareList = (shareglxc ? shareglxc->real_ids[screen-from_screen] : 0); - ext_req->isDirect = 0; - UnlockDisplay(dpy); - glxc->real_vids[screen-from_screen] = be_fbconfigId; - sent = 1; - } - } - - if (!sent) { - LockDisplay(dpy); - GetReq(GLXCreateContext,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXCreateContext; - be_req->context = (unsigned int)glxc->real_ids[screen-from_screen]; - be_req->visual = (unsigned int)be_vid; - be_req->screen = DefaultScreen(dpy); - be_req->shareList = (shareglxc ? shareglxc->real_ids[screen-from_screen] : 0); - be_req->isDirect = 0; - UnlockDisplay(dpy); - glxc->real_vids[screen-from_screen] = be_vid; - } - SyncHandle(); - - } - - /* - ** Register this context as a resource. - */ - if (!AddResource(gcId, __glXContextRes, (pointer)glxc)) { - __glXFree( glxc->real_ids ); - __glXFree( glxc->real_vids ); - __glXFree( glxc ); - client->errorValue = gcId; - return BadAlloc; - } - - /* - ** Finally, now that everything is working, setup the rest of the - ** context. - */ - glxc->id = gcId; - glxc->share_id = shareList; - glxc->idExists = GL_TRUE; - glxc->isCurrent = GL_FALSE; - - return Success; -} - -int __glXCreateContext(__GLXclientState *cl, GLbyte *pc) -{ - xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; - - return( CreateContext(cl, req->context,req->visual, None, - req->screen, req->shareList, req->isDirect) ); - -} - -int __glXCreateNewContext(__GLXclientState *cl, GLbyte *pc) -{ - xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; - - return( CreateContext(cl, req->context,None, req->fbconfig, - req->screen, req->shareList, req->isDirect) ); - -} - -int __glXCreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) -{ - xGLXCreateContextWithConfigSGIXReq *req = (xGLXCreateContextWithConfigSGIXReq *) pc; - - return( CreateContext(cl, req->context, None, req->fbconfig, - req->screen, req->shareList, req->isDirect) ); - -} - -int __glXQueryMaxSwapBarriersSGIX(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXQueryMaxSwapBarriersSGIXReq *req = - (xGLXQueryMaxSwapBarriersSGIXReq *)pc; - xGLXQueryMaxSwapBarriersSGIXReply reply; - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = 0; - reply.max = QueryMaxSwapBarriersSGIX(req->screen); - - if (client->swapped) { - __glXSwapQueryMaxSwapBarriersSGIXReply(client, &reply); - } else { - WriteToClient(client, sz_xGLXQueryMaxSwapBarriersSGIXReply, - (char *)&reply); - } - - return Success; -} - -int __glXBindSwapBarrierSGIX(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXBindSwapBarrierSGIXReq *req = (xGLXBindSwapBarrierSGIXReq *)pc; - DrawablePtr pDraw; - __GLXpixmap *pGlxPixmap = NULL; - __glXWindow *pGlxWindow = NULL; - int rc; - - rc = dixLookupDrawable(&pDraw, req->drawable, client, 0, DixGetAttrAccess); - if (rc != Success) { - pGlxPixmap = (__GLXpixmap *) LookupIDByType(req->drawable, - __glXPixmapRes); - if (pGlxPixmap) pDraw = pGlxPixmap->pDraw; - } - - if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxWindow = (__glXWindow *) LookupIDByType(req->drawable, - __glXWindowRes); - if (pGlxWindow) pDraw = pGlxWindow->pDraw; - } - - if (!pDraw) { - client->errorValue = req->drawable; - return __glXBadDrawable; - } - - return BindSwapBarrierSGIX(pDraw, req->barrier); -} - -int __glXJoinSwapGroupSGIX(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXJoinSwapGroupSGIXReq *req = (xGLXJoinSwapGroupSGIXReq *)pc; - DrawablePtr pDraw, pMember = NULL; - __GLXpixmap *pGlxPixmap = NULL; - __glXWindow *pGlxWindow = NULL; - int rc; - - rc = dixLookupDrawable(&pDraw, req->drawable, client, 0, DixManageAccess); - if (rc != Success) { - pGlxPixmap = (__GLXpixmap *) LookupIDByType(req->drawable, - __glXPixmapRes); - if (pGlxPixmap) pDraw = pGlxPixmap->pDraw; - } - - if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxWindow = (__glXWindow *) LookupIDByType(req->drawable, - __glXWindowRes); - if (pGlxWindow) pDraw = pGlxWindow->pDraw; - } - - if (!pDraw) { - client->errorValue = req->drawable; - return __glXBadDrawable; - } - - if (req->member != None) { - rc = dixLookupDrawable(&pMember, req->member, client, 0, - DixGetAttrAccess); - if (rc != Success) { - pGlxPixmap = (__GLXpixmap *) LookupIDByType(req->member, - __glXPixmapRes); - if (pGlxPixmap) pMember = pGlxPixmap->pDraw; - } - - if (!pMember && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxWindow = (__glXWindow *) LookupIDByType(req->member, - __glXWindowRes); - if (pGlxWindow) pMember = pGlxWindow->pDraw; - } - - if (!pMember) { - client->errorValue = req->member; - return __glXBadDrawable; - } - } - - return JoinSwapGroupSGIX(pDraw, pMember); -} - - -/* -** Destroy a GL context as an X resource. -*/ -int __glXDestroyContext(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc; - xGLXDestroyContextReq *be_req; - GLXContextID gcId = req->context; - __GLXcontext *glxc; - int from_screen = 0; - int to_screen = 0; - int s; - - glxc = (__GLXcontext *) LookupIDByType(gcId, __glXContextRes); - if (glxc) { - /* - ** Just free the resource; don't actually destroy the context, - ** because it might be in use. The - ** destroy method will be called by the resource destruction routine - ** if necessary. - */ - FreeResourceByType(gcId, __glXContextRes, FALSE); - - from_screen = to_screen = glxc->pScreen->myNum; - - } else { - client->errorValue = gcId; - return __glXBadContext; - } - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - /* - * send DestroyContext request to all back-end servers - */ - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReq(GLXDestroyContext,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXDestroyContext; - be_req->context = glxc->real_ids[s-from_screen]; - UnlockDisplay(dpy); - SyncHandle(); - } - - return Success; -} - -/*****************************************************************************/ - -/* -** For each client, the server keeps a table of all the contexts that are -** current for that client (each thread of a client may have its own current -** context). These routines add, change, and lookup contexts in the table. -*/ - -/* -** Add a current context, and return the tag that will be used to refer to it. -*/ -static int AddCurrentContext(__GLXclientState *cl, __GLXcontext *glxc, DrawablePtr pDraw) -{ - int i; - int num = cl->numCurrentContexts; - __GLXcontext **table = cl->currentContexts; - - if (!glxc) return -1; - - /* - ** Try to find an empty slot and use it. - */ - for (i=0; i < num; i++) { - if (!table[i]) { - table[i] = glxc; - return i+1; - } - } - /* - ** Didn't find a free slot, so we'll have to grow the table. - */ - if (!num) { - table = (__GLXcontext **) __glXMalloc(sizeof(__GLXcontext *)); - cl->currentDrawables = (DrawablePtr *) __glXMalloc(sizeof(DrawablePtr)); - cl->be_currentCTag = (GLXContextTag *) __glXMalloc(screenInfo.numScreens *sizeof(GLXContextTag)); - } else { - table = (__GLXcontext **) __glXRealloc(table, - (num+1)*sizeof(__GLXcontext *)); - cl->currentDrawables = (DrawablePtr *) __glXRealloc( - cl->currentDrawables , - (num+1)*sizeof(DrawablePtr)); - cl->be_currentCTag = (GLXContextTag *) __glXRealloc(cl->be_currentCTag, - (num+1)*screenInfo.numScreens*sizeof(GLXContextTag)); - } - table[num] = glxc; - cl->currentDrawables[num] = pDraw; - cl->currentContexts = table; - cl->numCurrentContexts++; - - memset(cl->be_currentCTag + num*screenInfo.numScreens, 0, - screenInfo.numScreens * sizeof(GLXContextTag)); - - return num+1; -} - -/* -** Given a tag, change the current context for the corresponding entry. -*/ -static void ChangeCurrentContext(__GLXclientState *cl, __GLXcontext *glxc, - GLXContextTag tag) -{ - __GLXcontext **table = cl->currentContexts; - table[tag-1] = glxc; -} - -/* -** Given a tag, and back-end screen number, retrives the current back-end -** tag. -*/ -int GetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s) -{ - if (tag >0) { - return( cl->be_currentCTag[ (tag-1)*screenInfo.numScreens + s ] ); - } - else { - return( 0 ); - } -} - -/* -** Given a tag, and back-end screen number, sets the current back-end -** tag. -*/ -static void SetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s, GLXContextTag be_tag) -{ - if (tag >0) { - cl->be_currentCTag[ (tag-1)*screenInfo.numScreens + s ] = be_tag; - } -} - -/* -** For this implementation we have chosen to simply use the index of the -** context's entry in the table as the context tag. A tag must be greater -** than 0. -*/ -__GLXcontext *__glXLookupContextByTag(__GLXclientState *cl, GLXContextTag tag) -{ - int num = cl->numCurrentContexts; - - if (tag < 1 || tag > num) { - return 0; - } else { - return cl->currentContexts[tag-1]; - } -} - -DrawablePtr __glXLookupDrawableByTag(__GLXclientState *cl, GLXContextTag tag) -{ - int num = cl->numCurrentContexts; - - if (tag < 1 || tag > num) { - return 0; - } else { - return cl->currentDrawables[tag-1]; - } -} - -/*****************************************************************************/ - -static void StopUsingContext(__GLXcontext *glxc) -{ - if (glxc) { - if (glxc == __glXLastContext) { - /* Tell server GL library */ - __glXLastContext = 0; - } - glxc->isCurrent = GL_FALSE; - if (!glxc->idExists) { - __glXFreeContext(glxc); - } - } -} - -static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc) -{ - glxc->isCurrent = GL_TRUE; -} - -/*****************************************************************************/ -/* -** Make an OpenGL context and drawable current. -*/ -static int MakeCurrent(__GLXclientState *cl, - GLXDrawable drawable, - GLXDrawable readdrawable, - GLXContextID context, - GLXContextTag oldContextTag) -{ - ClientPtr client = cl->client; - DrawablePtr pDraw = NULL; - DrawablePtr pReadDraw = NULL; - xGLXMakeCurrentReadSGIReply new_reply; - xGLXMakeCurrentReq *be_req; - xGLXMakeCurrentReply be_reply; - xGLXMakeContextCurrentReq *be_new_req; - xGLXMakeContextCurrentReply be_new_reply; - GLXDrawable drawId = drawable; - GLXDrawable readId = readdrawable; - GLXContextID contextId = context; - __GLXpixmap *pGlxPixmap = 0; - __GLXpixmap *pReadGlxPixmap = 0; - __GLXcontext *glxc, *prevglxc; - GLXContextTag tag = oldContextTag; - WindowPtr pWin = NULL; - WindowPtr pReadWin = NULL; - __glXWindow *pGlxWindow = NULL; - __glXWindow *pGlxReadWindow = NULL; - __glXPbuffer *pGlxPbuffer = NULL; - __glXPbuffer *pGlxReadPbuffer = NULL; -#ifdef PANORAMIX - PanoramiXRes *pXinDraw = NULL; - PanoramiXRes *pXinReadDraw = NULL; -#endif - int from_screen = 0; - int to_screen = 0; - int s, rc; - - /* - ** If one is None and the other isn't, it's a bad match. - */ - if ((drawId == None && contextId != None) || - (drawId != None && contextId == None)) { - return BadMatch; - } - - /* - ** Lookup old context. If we have one, it must be in a usable state. - */ - if (tag != 0) { - prevglxc = __glXLookupContextByTag(cl, tag); - if (!prevglxc) { - /* - ** Tag for previous context is invalid. - */ - return __glXBadContextTag; - } - } else { - prevglxc = 0; - } - - /* - ** Lookup new context. It must not be current for someone else. - */ - if (contextId != None) { - glxc = (__GLXcontext *) LookupIDByType(contextId, __glXContextRes); - if (!glxc) { - client->errorValue = contextId; - return __glXBadContext; - } - if ((glxc != prevglxc) && glxc->isCurrent) { - /* Context is current to somebody else */ - return BadAccess; - } - } else { - /* Switching to no context. Ignore new drawable. */ - glxc = 0; - } - - if (drawId != None) { - rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixWriteAccess); - if (rc == Success) { - if (pDraw->type == DRAWABLE_WINDOW) { - /* - ** Drawable is an X Window. - */ - VisualID vid; - pWin = (WindowPtr)pDraw; - vid = wVisual(pWin); - - new_reply.writeVid = (glxc->pFBConfig ? glxc->pFBConfig->id : vid); - new_reply.writeType = GLX_WINDOW_TYPE; - - /* - ** Check if window and context are similar. - */ - if ((vid != glxc->pVisual->vid) || - (pWin->drawable.pScreen != glxc->pScreen)) { - client->errorValue = drawId; - return BadMatch; - } - - from_screen = to_screen = pWin->drawable.pScreen->myNum; - - } else { - /* - ** An X Pixmap is not allowed as a parameter (a GLX Pixmap - ** is, but it must first be created with glxCreateGLXPixmap). - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - if (!pDraw) { - pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, - __glXPixmapRes); - if (pGlxPixmap) { - /* - ** Check if pixmap and context are similar. - */ - if (pGlxPixmap->pScreen != glxc->pScreen || - pGlxPixmap->pGlxVisual != glxc->pGlxVisual) { - client->errorValue = drawId; - return BadMatch; - } - pDraw = pGlxPixmap->pDraw; - - new_reply.writeVid = (glxc->pFBConfig ? glxc->pFBConfig->id : - pGlxPixmap->pGlxVisual->vid); - - new_reply.writeType = GLX_PIXMAP_TYPE; - - from_screen = to_screen = pGlxPixmap->pScreen->myNum; - - } - } - - if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); - if (pGlxWindow) { - /* - ** Drawable is a GLXWindow. - ** - ** Check if GLX window and context are similar. - */ - if (pGlxWindow->pScreen != glxc->pScreen || - pGlxWindow->pGlxFBConfig != glxc->pFBConfig) { - client->errorValue = drawId; - return BadMatch; - } - - pDraw = pGlxWindow->pDraw; - new_reply.writeVid = pGlxWindow->pGlxFBConfig->id; - new_reply.writeType = GLX_GLXWINDOW_TYPE; - } - - } - - if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxPbuffer = (__glXPbuffer *)LookupIDByType(drawId, __glXPbufferRes); - if (pGlxPbuffer) { - if (pGlxPbuffer->pScreen != glxc->pScreen || - pGlxPbuffer->pFBConfig != glxc->pFBConfig) { - client->errorValue = drawId; - return BadMatch; - } - - pDraw = (DrawablePtr)pGlxPbuffer; - new_reply.writeVid = pGlxPbuffer->pFBConfig->id; - new_reply.writeType = GLX_PBUFFER_TYPE; - } - } - - if (!pDraw) { - /* - ** Drawable is not a Window , GLXWindow or a GLXPixmap. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - - } else { - pDraw = 0; - } - - if (readId != None && readId != drawId ) { - rc = dixLookupDrawable(&pReadDraw, readId, client, 0, DixReadAccess); - if (rc == Success) { - if (pReadDraw->type == DRAWABLE_WINDOW) { - /* - ** Drawable is an X Window. - */ - VisualID vid; - pReadWin = (WindowPtr)pDraw; - vid = wVisual(pReadWin); - - new_reply.readVid = (glxc->pFBConfig ? glxc->pFBConfig->id : vid); - new_reply.readType = GLX_WINDOW_TYPE; - - /* - ** Check if window and context are similar. - */ - if ((vid != glxc->pVisual->vid) || - (pReadWin->drawable.pScreen != glxc->pScreen)) { - client->errorValue = readId; - return BadMatch; - } - - } else { - - /* - ** An X Pixmap is not allowed as a parameter (a GLX Pixmap - ** is, but it must first be created with glxCreateGLXPixmap). - */ - client->errorValue = readId; - return __glXBadDrawable; - } - } - - if (!pReadDraw) { - pReadGlxPixmap = (__GLXpixmap *) LookupIDByType(readId, - __glXPixmapRes); - if (pReadGlxPixmap) { - /* - ** Check if pixmap and context are similar. - */ - if (pReadGlxPixmap->pScreen != glxc->pScreen || - pReadGlxPixmap->pGlxVisual != glxc->pGlxVisual) { - client->errorValue = readId; - return BadMatch; - } - pReadDraw = pReadGlxPixmap->pDraw; - - new_reply.readVid = (glxc->pFBConfig ? glxc->pFBConfig->id : - pReadGlxPixmap->pGlxVisual->vid ); - new_reply.readType = GLX_PIXMAP_TYPE; - - } - } - - if (!pReadDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxReadWindow = (__glXWindow *) - LookupIDByType(readId, __glXWindowRes); - if (pGlxReadWindow) { - /* - ** Drawable is a GLXWindow. - ** - ** Check if GLX window and context are similar. - */ - if (pGlxReadWindow->pScreen != glxc->pScreen || - pGlxReadWindow->pGlxFBConfig != glxc->pFBConfig) { - client->errorValue = readId; - return BadMatch; - } - - pReadDraw = pGlxReadWindow->pDraw; - new_reply.readVid = pGlxReadWindow->pGlxFBConfig->id; - new_reply.readType = GLX_GLXWINDOW_TYPE; - } - } - - if (!pReadDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxReadPbuffer = (__glXPbuffer *)LookupIDByType(readId, __glXPbufferRes); - if (pGlxReadPbuffer) { - if (pGlxReadPbuffer->pScreen != glxc->pScreen || - pGlxReadPbuffer->pFBConfig != glxc->pFBConfig) { - client->errorValue = drawId; - return BadMatch; - } - - pReadDraw = (DrawablePtr)pGlxReadPbuffer; - new_reply.readVid = pGlxReadPbuffer->pFBConfig->id; - new_reply.readType = GLX_PBUFFER_TYPE; - } - } - - if (!pReadDraw) { - /* - ** Drawable is neither a Window nor a GLXPixmap. - */ - client->errorValue = readId; - return __glXBadDrawable; - } - - } else { - pReadDraw = pDraw; - pReadGlxPixmap = pGlxPixmap; - pReadWin = pWin; - new_reply.readVid = new_reply.writeVid; - new_reply.readType = new_reply.writeType; - } - - if (prevglxc) { - - if (prevglxc->pGlxPixmap) { - /* - ** The previous drawable was a glx pixmap, release it. - */ - prevglxc->pGlxPixmap->refcnt--; - __glXFreeGLXPixmap( prevglxc->pGlxPixmap ); - prevglxc->pGlxPixmap = 0; - } - - if (prevglxc->pGlxReadPixmap) { - /* - ** The previous drawable was a glx pixmap, release it. - */ - prevglxc->pGlxReadPixmap->refcnt--; - __glXFreeGLXPixmap( prevglxc->pGlxReadPixmap ); - prevglxc->pGlxReadPixmap = 0; - } - - if (prevglxc->pGlxWindow) { - /* - ** The previous drawable was a glx window, release it. - */ - prevglxc->pGlxWindow->refcnt--; - __glXFreeGLXWindow( prevglxc->pGlxWindow ); - prevglxc->pGlxWindow = 0; - } - - if (prevglxc->pGlxReadWindow) { - /* - ** The previous drawable was a glx window, release it. - */ - prevglxc->pGlxReadWindow->refcnt--; - __glXFreeGLXWindow( prevglxc->pGlxReadWindow ); - prevglxc->pGlxReadWindow = 0; - } - - if (prevglxc->pGlxPbuffer) { - /* - ** The previous drawable was a glx Pbuffer, release it. - */ - prevglxc->pGlxPbuffer->refcnt--; - __glXFreeGLXPbuffer( prevglxc->pGlxPbuffer ); - prevglxc->pGlxPbuffer = 0; - } - - if (prevglxc->pGlxReadPbuffer) { - /* - ** The previous drawable was a glx Pbuffer, release it. - */ - prevglxc->pGlxReadPbuffer->refcnt--; - __glXFreeGLXPbuffer( prevglxc->pGlxReadPbuffer ); - prevglxc->pGlxReadPbuffer = 0; - } - - ChangeCurrentContext(cl, glxc, tag); - ChangeCurrentContext(cl, glxc, tag); - StopUsingContext(prevglxc); - } else { - tag = AddCurrentContext(cl, glxc, pDraw); - } - if (glxc) { - - glxc->pGlxPixmap = pGlxPixmap; - glxc->pGlxReadPixmap = pReadGlxPixmap; - glxc->pGlxWindow = pGlxWindow; - glxc->pGlxReadWindow = pGlxReadWindow; - glxc->pGlxPbuffer = pGlxPbuffer; - glxc->pGlxReadPbuffer = pGlxReadPbuffer; - - if (pGlxPixmap) { - pGlxPixmap->refcnt++; - } - - if (pReadGlxPixmap) { - pReadGlxPixmap->refcnt++; - } - - if (pGlxWindow) { - pGlxWindow->refcnt++; - } - - if (pGlxReadWindow) { - pGlxReadWindow->refcnt++; - } - - if (pGlxPbuffer) { - pGlxPbuffer->refcnt++; - } - - if (pGlxReadPbuffer) { - pGlxReadPbuffer->refcnt++; - } - - StartUsingContext(cl, glxc); - new_reply.contextTag = tag; - } else { - new_reply.contextTag = 0; - } - new_reply.length = 0; - new_reply.type = X_Reply; - new_reply.sequenceNumber = client->sequence; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - - if (pDraw && new_reply.writeType != GLX_PBUFFER_TYPE) { - pXinDraw = (PanoramiXRes *) - SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); - } - - if (pReadDraw && pReadDraw != pDraw && - new_reply.readType != GLX_PBUFFER_TYPE) { - pXinReadDraw = (PanoramiXRes *) - SecurityLookupIDByClass(client, pReadDraw->id, XRC_DRAWABLE, DixReadAccess); - } - else { - pXinReadDraw = pXinDraw; - } - } -#endif - - - /* send the MakeCurrent request to all required - * back-end servers. - */ - for (s = from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - unsigned int be_draw = None; - unsigned int be_read_draw = None; - - if (pGlxPixmap) { - be_draw = pGlxPixmap->be_xids[s]; - } - else if (pGlxPbuffer) { - be_draw = pGlxPbuffer->be_xids[s]; - } -#ifdef PANORAMIX - else if (pXinDraw) { - dixLookupWindow(&pWin, pXinDraw->info[s].id, client, DixReadAccess); - } -#endif - else if (pGlxWindow) { - pWin = (WindowPtr)pGlxWindow->pDraw; - } - - if (pWin && be_draw == None) { - be_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; - if (!be_draw) { - /* it might be that the window did not created yet on the */ - /* back-end server (lazy window creation option), force */ - /* creation of the window */ - dmxCreateAndRealizeWindow( pWin, TRUE ); - be_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; - } - } - - /* - * Before sending the MakeCurrent request - sync the - * X11 connection to the back-end servers to make sure - * that drawable is already created - */ - dmxSync( dmxScreen, 1 ); - - if (drawId == readId) { - LockDisplay(dpy); - GetReq(GLXMakeCurrent, be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXMakeCurrent; - be_req->drawable = be_draw; - be_req->context = (unsigned int)(glxc ? glxc->real_ids[s-from_screen] : 0); - be_req->oldContextTag = GetCurrentBackEndTag(cl, tag, s); - if (!_XReply(dpy, (xReply *) &be_reply, 0, False)) { - - /* The make current failed */ - UnlockDisplay(dpy); - SyncHandle(); - return( BE_TO_CLIENT_ERROR(dmxLastErrorEvent.error_code) ); - } - - UnlockDisplay(dpy); - SyncHandle(); - - SetCurrentBackEndTag( cl, tag, s, be_reply.contextTag ); - } - else { - - if (pReadGlxPixmap) { - be_read_draw = pReadGlxPixmap->be_xids[s]; - } - else if (pGlxReadPbuffer) { - be_read_draw = pGlxReadPbuffer->be_xids[s]; - } -#ifdef PANORAMIX - else if (pXinReadDraw) { - dixLookupWindow(&pReadWin, pXinReadDraw->info[s].id, client, - DixReadAccess); - } -#endif - else if (pGlxReadWindow) { - pReadWin = (WindowPtr)pGlxReadWindow->pDraw; - } - - if (pReadWin && be_read_draw == None) { - be_read_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pReadWin))->window; - if (!be_read_draw) { - /* it might be that the window did not created yet on the */ - /* back-end server (lazy window creation option), force */ - /* creation of the window */ - dmxCreateAndRealizeWindow( pReadWin, TRUE ); - be_read_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pReadWin))->window; - dmxSync( dmxScreen, 1 ); - } - } - - if ( __GLX_IS_VERSION_SUPPORTED(1,3) ) { - LockDisplay(dpy); - GetReq(GLXMakeContextCurrent, be_new_req); - be_new_req->reqType = dmxScreen->glxMajorOpcode; - be_new_req->glxCode = X_GLXMakeContextCurrent; - be_new_req->drawable = be_draw; - be_new_req->readdrawable = be_read_draw; - be_new_req->context = (unsigned int)(glxc ? glxc->real_ids[s-from_screen] : 0); - be_new_req->oldContextTag = GetCurrentBackEndTag(cl, tag, s); - if (!_XReply(dpy, (xReply *) &be_new_reply, 0, False)) { - - /* The make current failed */ - UnlockDisplay(dpy); - SyncHandle(); - return( BE_TO_CLIENT_ERROR(dmxLastErrorEvent.error_code) ); - } - - UnlockDisplay(dpy); - SyncHandle(); - - SetCurrentBackEndTag( cl, tag, s, be_new_reply.contextTag ); - } - else if (glxIsExtensionSupported("GLX_SGI_make_current_read")) { - xGLXMakeCurrentReadSGIReq *ext_req; - xGLXVendorPrivateWithReplyReq *vpreq; - xGLXMakeCurrentReadSGIReply ext_reply; - - LockDisplay(dpy); - GetReqExtra(GLXVendorPrivateWithReply, - sz_xGLXMakeCurrentReadSGIReq - sz_xGLXVendorPrivateWithReplyReq, - vpreq); - ext_req = (xGLXMakeCurrentReadSGIReq *)vpreq; - ext_req->reqType = dmxScreen->glxMajorOpcode; - ext_req->glxCode = X_GLXVendorPrivateWithReply; - ext_req->vendorCode = X_GLXvop_MakeCurrentReadSGI; - ext_req->drawable = be_draw; - ext_req->readable = be_read_draw; - ext_req->context = (unsigned int)(glxc ? glxc->real_ids[s-from_screen] : 0); - ext_req->oldContextTag = GetCurrentBackEndTag(cl, tag, s); - if (!_XReply(dpy, (xReply *) &ext_reply, 0, False)) { - - /* The make current failed */ - UnlockDisplay(dpy); - SyncHandle(); - return( BE_TO_CLIENT_ERROR(dmxLastErrorEvent.error_code) ); - } - - UnlockDisplay(dpy); - SyncHandle(); - - SetCurrentBackEndTag( cl, tag, s, ext_reply.contextTag ); - - } - else { - return BadMatch; - } - } - - XFlush( dpy ); - } - - if (client->swapped) { - __glXSwapMakeCurrentReply(client, &new_reply); - } else { - WriteToClient(client, sz_xGLXMakeContextCurrentReply, (char *)&new_reply); - } - - return Success; -} - -int __glXMakeCurrent(__GLXclientState *cl, GLbyte *pc) -{ - xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc; - - return( MakeCurrent(cl, req->drawable, req->drawable, - req->context, req->oldContextTag ) ); -} - -int __glXMakeContextCurrent(__GLXclientState *cl, GLbyte *pc) -{ - xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc; - - return( MakeCurrent(cl, req->drawable, req->readdrawable, - req->context, req->oldContextTag ) ); -} - -int __glXMakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) -{ - xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc; - - return( MakeCurrent(cl, req->drawable, req->readable, - req->context, req->oldContextTag ) ); -} - -int __glXIsDirect(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc; - xGLXIsDirectReply reply; - __GLXcontext *glxc; - - /* - ** Find the GL context. - */ - glxc = (__GLXcontext *) LookupIDByType(req->context, __glXContextRes); - if (!glxc) { - client->errorValue = req->context; - return __glXBadContext; - } - - reply.isDirect = 0; - reply.length = 0; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - - if (client->swapped) { - __glXSwapIsDirectReply(client, &reply); - } else { - WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); - } - - return Success; -} - -int __glXQueryVersion(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; -/* xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc; */ - xGLXQueryVersionReply reply; - - /* - ** Server should take into consideration the version numbers sent by the - ** client if it wants to work with older clients; however, in this - ** implementation the server just returns its version number. - */ - reply.majorVersion = __glXVersionMajor; - reply.minorVersion = __glXVersionMinor; - reply.length = 0; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - - if (client->swapped) { - __glXSwapQueryVersionReply(client, &reply); - } else { - WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply); - } - return Success; -} - -int __glXWaitGL(__GLXclientState *cl, GLbyte *pc) -{ - xGLXWaitGLReq *req = (xGLXWaitGLReq *)pc; - xGLXWaitGLReq *be_req = (xGLXWaitGLReq *)pc; - int from_screen = 0; - int to_screen = 0; - int s; - __GLXcontext *glxc = NULL; - - if (req->contextTag != 0) { - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (glxc) { - from_screen = to_screen = glxc->pScreen->myNum; - } - } - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReq(GLXWaitGL,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXWaitGL; - be_req->contextTag = (glxc ? GetCurrentBackEndTag(cl,req->contextTag,s) : 0); - UnlockDisplay(dpy); - SyncHandle(); - - XSync(dpy, False); - } - - return Success; -} - -int __glXWaitX(__GLXclientState *cl, GLbyte *pc) -{ - xGLXWaitXReq *req = (xGLXWaitXReq *)pc; - xGLXWaitXReq *be_req; - int from_screen = 0; - int to_screen = 0; - int s; - __GLXcontext *glxc = NULL; - - if (req->contextTag != 0) { - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (glxc) { - from_screen = to_screen = glxc->pScreen->myNum; - } - } - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - dmxSync( dmxScreen, 1 ); - - LockDisplay(dpy); - GetReq(GLXWaitX,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXWaitX; - be_req->contextTag = (glxc ? GetCurrentBackEndTag(cl,req->contextTag,s) : 0); - UnlockDisplay(dpy); - SyncHandle(); - - XFlush( dpy ); - } - - return Success; -} - -int __glXCopyContext(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXCopyContextReq *be_req; - xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc; - GLXContextID source = req->source; - GLXContextID dest = req->dest; - GLXContextTag tag = req->contextTag; - unsigned long mask = req->mask; - __GLXcontext *src, *dst; - int s; - int from_screen = 0; - int to_screen = 0; - - /* - ** Check that each context exists. - */ - src = (__GLXcontext *) LookupIDByType(source, __glXContextRes); - if (!src) { - client->errorValue = source; - return __glXBadContext; - } - dst = (__GLXcontext *) LookupIDByType(dest, __glXContextRes); - if (!dst) { - client->errorValue = dest; - return __glXBadContext; - } - - /* - ** They must be in the same address space, and same screen. - */ - if (src->pGlxScreen != dst->pGlxScreen) { - client->errorValue = source; - return BadMatch; - } - - /* - ** The destination context must not be current for any client. - */ - if (dst->isCurrent) { - client->errorValue = dest; - return BadAccess; - } - - if (tag) { - __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag); - - if (!tagcx) { - return __glXBadContextTag; - } - if (tagcx != src) { - /* - ** This would be caused by a faulty implementation of the client - ** library. - */ - return BadMatch; - } - } - - from_screen = to_screen = src->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReq(GLXCopyContext,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXCopyContext; - be_req->source = (unsigned int)src->real_ids[s-from_screen]; - be_req->dest = (unsigned int)dst->real_ids[s-from_screen]; - be_req->mask = mask; - be_req->contextTag = (tag ? GetCurrentBackEndTag(cl,req->contextTag,s) : 0); - UnlockDisplay(dpy); - SyncHandle(); - } - - return Success; -} - -int __glXGetVisualConfigs(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc; - xGLXGetVisualConfigsReply reply; - __GLXscreenInfo *pGlxScreen; - __GLXvisualConfig *pGlxVisual; - CARD32 buf[__GLX_TOTAL_CONFIG]; - unsigned int screen; - int i, p; - - screen = req->screen; - if (screen > screenInfo.numScreens) { - /* The client library must send a valid screen number. */ - client->errorValue = screen; - return BadValue; - } - pGlxScreen = &__glXActiveScreens[screen]; - - reply.numVisuals = pGlxScreen->numGLXVisuals; - reply.numProps = __GLX_TOTAL_CONFIG; - reply.length = (pGlxScreen->numGLXVisuals * __GLX_SIZE_CARD32 * - __GLX_TOTAL_CONFIG) >> 2; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - - WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char *)&reply); - - for (i=0; i < pGlxScreen->numVisuals; i++) { - pGlxVisual = &pGlxScreen->pGlxVisual[i]; - if (!pGlxScreen->isGLXvis[i] || pGlxVisual->vid == 0) { - /* not a usable visual */ - continue; - } - p = 0; - buf[p++] = pGlxVisual->vid; - buf[p++] = pGlxVisual->class; - buf[p++] = pGlxVisual->rgba; - - buf[p++] = pGlxVisual->redSize; - buf[p++] = pGlxVisual->greenSize; - buf[p++] = pGlxVisual->blueSize; - buf[p++] = pGlxVisual->alphaSize; - buf[p++] = pGlxVisual->accumRedSize; - buf[p++] = pGlxVisual->accumGreenSize; - buf[p++] = pGlxVisual->accumBlueSize; - buf[p++] = pGlxVisual->accumAlphaSize; - - buf[p++] = pGlxVisual->doubleBuffer; - buf[p++] = pGlxVisual->stereo; - - buf[p++] = pGlxVisual->bufferSize; - buf[p++] = pGlxVisual->depthSize; - buf[p++] = pGlxVisual->stencilSize; - buf[p++] = pGlxVisual->auxBuffers; - buf[p++] = pGlxVisual->level; - /* - ** Add token/value pairs for extensions. - */ - buf[p++] = GLX_VISUAL_CAVEAT_EXT; - buf[p++] = pGlxVisual->visualRating; - buf[p++] = GLX_TRANSPARENT_TYPE_EXT; - buf[p++] = pGlxVisual->transparentPixel; - buf[p++] = GLX_TRANSPARENT_RED_VALUE_EXT; - buf[p++] = pGlxVisual->transparentRed; - buf[p++] = GLX_TRANSPARENT_GREEN_VALUE_EXT; - buf[p++] = pGlxVisual->transparentGreen; - buf[p++] = GLX_TRANSPARENT_BLUE_VALUE_EXT; - buf[p++] = pGlxVisual->transparentBlue; - buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE_EXT; - buf[p++] = pGlxVisual->transparentAlpha; - buf[p++] = GLX_TRANSPARENT_INDEX_VALUE_EXT; - buf[p++] = pGlxVisual->transparentIndex; - buf[p++] = GLX_SAMPLES_SGIS; - buf[p++] = pGlxVisual->multiSampleSize; - buf[p++] = GLX_SAMPLE_BUFFERS_SGIS; - buf[p++] = pGlxVisual->nMultiSampleBuffers; - buf[p++] = GLX_VISUAL_SELECT_GROUP_SGIX; - buf[p++] = pGlxVisual->visualSelectGroup; - - WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_TOTAL_CONFIG, - (char *)buf); - } - return Success; -} - -/* -** Create a GLX Pixmap from an X Pixmap. -*/ -static int CreateGLXPixmap(__GLXclientState *cl, - VisualID visual, GLXFBConfigID fbconfigId, - int screenNum, XID pixmapId, XID glxpixmapId ) -{ - ClientPtr client = cl->client; - xGLXCreateGLXPixmapReq *be_req; - xGLXCreatePixmapReq *be_new_req; - DrawablePtr pDraw; - ScreenPtr pScreen; - VisualPtr pVisual; - __GLXpixmap *pGlxPixmap; - __GLXscreenInfo *pGlxScreen; - __GLXvisualConfig *pGlxVisual; - __GLXFBConfig *pFBConfig; - int i, s, rc; - int from_screen, to_screen; -#ifdef PANORAMIX - PanoramiXRes *pXinDraw = NULL; -#endif - - rc = dixLookupDrawable(&pDraw, pixmapId, client, M_DRAWABLE_PIXMAP, - DixAddAccess); - if (rc != Success) - return rc; - - /* - ** Check if screen of visual matches screen of pixmap. - */ - pScreen = pDraw->pScreen; - if (screenNum != pScreen->myNum) { - return BadMatch; - } - - if (fbconfigId == NULL && visual == NULL) { - return BadValue; - } - - if (fbconfigId != None) { - pFBConfig = glxLookupFBConfig( fbconfigId ); - if (!pFBConfig) { - client->errorValue = fbconfigId; - return BadValue; - } - visual = pFBConfig->associatedVisualId; - } - else { - pFBConfig = NULL; - } - - if (visual != None) { - /* - ** Find the VisualRec for this visual. - */ - pVisual = pScreen->visuals; - for (i=0; i < pScreen->numVisuals; i++, pVisual++) { - if (pVisual->vid == visual) { - break; - } - } - if (i == pScreen->numVisuals) { - client->errorValue = visual; - return BadValue; - } - /* - ** Check if depth of visual matches depth of pixmap. - */ - if (pVisual->nplanes != pDraw->depth) { - client->errorValue = visual; - return BadMatch; - } - - /* - ** Get configuration of the visual. - */ - pGlxScreen = &__glXActiveScreens[screenNum]; - pGlxVisual = pGlxScreen->pGlxVisual; - for (i = 0; i < pGlxScreen->numVisuals; i++, pGlxVisual++) { - if (pGlxVisual->vid == visual) { - break; - } - } - if (i == pGlxScreen->numVisuals) { - /* - ** Visual not support on this screen by this OpenGL implementation. - */ - client->errorValue = visual; - return BadValue; - } - - - /* find the FBConfig for that visual (if any) */ - if ( pFBConfig == NULL ) { - pFBConfig = glxLookupFBConfigByVID( visual ); - - if ( pFBConfig == NULL ) { - /* - * visual does not have an FBConfig ??? - client->errorValue = visual; - return BadValue; - */ - } - } - } - else { - pVisual = NULL; - pGlxVisual = NULL; - } - - pGlxPixmap = (__GLXpixmap *) __glXMalloc(sizeof(__GLXpixmap)); - if (!pGlxPixmap) { - return BadAlloc; - } - pGlxPixmap->be_xids = (XID *) __glXMalloc(sizeof(XID) * screenInfo.numScreens); - if (!pGlxPixmap->be_xids) { - __glXFree( pGlxPixmap ); - return BadAlloc; - } - - pGlxPixmap->pDraw = pDraw; - pGlxPixmap->pGlxScreen = pGlxScreen; - pGlxPixmap->pGlxVisual = pGlxVisual; - pGlxPixmap->pFBConfig = pFBConfig; - pGlxPixmap->pScreen = pScreen; - pGlxPixmap->idExists = True; - pGlxPixmap->refcnt = 0; - - /* - ** Bump the ref count on the X pixmap so it won't disappear. - */ - ((PixmapPtr) pDraw)->refcnt++; - - /* - * send the request to the back-end server(s) - */ - from_screen = to_screen = screenNum; -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - - pXinDraw = (PanoramiXRes *) - SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); - } -#endif - - for (s=from_screen; s<=to_screen; s++) { - - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - Pixmap be_pixmap; - DrawablePtr pRealDraw = pDraw; - -#ifdef PANORAMIX - if (pXinDraw) { - dixLookupDrawable(&pRealDraw, pXinDraw->info[s].id, client, 0, - DixAddAccess); - } -#endif - - be_pixmap = (DMX_GET_PIXMAP_PRIV((PixmapPtr)pRealDraw))->pixmap; - - /* make sure pixmap already created on back-end */ - dmxSync( dmxScreen, 1 ); - - if ( pFBConfig && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - __GLXFBConfig *be_FBConfig = glxLookupBackEndFBConfig( pFBConfig->id, s ); - - LockDisplay(dpy); - pGlxPixmap->be_xids[s] = XAllocID(dpy); - GetReq(GLXCreatePixmap,be_new_req); - be_new_req->reqType = dmxScreen->glxMajorOpcode; - be_new_req->glxCode = X_GLXCreatePixmap; - be_new_req->screen = DefaultScreen(dpy); - be_new_req->fbconfig = be_FBConfig->id; - be_new_req->pixmap = (unsigned int)be_pixmap; - be_new_req->glxpixmap = (unsigned int)pGlxPixmap->be_xids[s]; - be_new_req->numAttribs = 0; - UnlockDisplay(dpy); - SyncHandle(); - } - else if (pFBConfig && glxIsExtensionSupported("GLX_SGIX_fbconfig")) { - __GLXFBConfig *be_FBConfig = glxLookupBackEndFBConfig( pFBConfig->id, s ); - xGLXCreateGLXPixmapWithConfigSGIXReq *ext_req; - xGLXVendorPrivateReq *vpreq; - - LockDisplay(dpy); - pGlxPixmap->be_xids[s] = XAllocID(dpy); - GetReqExtra(GLXVendorPrivate, - sz_xGLXCreateGLXPixmapWithConfigSGIXReq-sz_xGLXVendorPrivateReq, - vpreq); - ext_req = (xGLXCreateGLXPixmapWithConfigSGIXReq *)vpreq; - ext_req->reqType = dmxScreen->glxMajorOpcode; - ext_req->glxCode = X_GLXVendorPrivate; - ext_req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; - ext_req->screen = DefaultScreen(dpy); - ext_req->fbconfig = be_FBConfig->id; - ext_req->pixmap = (unsigned int)be_pixmap; - ext_req->glxpixmap = (unsigned int)pGlxPixmap->be_xids[s]; - UnlockDisplay(dpy); - SyncHandle(); - } - else if (pGlxVisual) { - LockDisplay(dpy); - pGlxPixmap->be_xids[s] = XAllocID(dpy); - GetReq(GLXCreateGLXPixmap,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXCreateGLXPixmap; - be_req->screen = DefaultScreen(dpy); - be_req->visual = (unsigned int)glxMatchGLXVisualInConfigList( - pGlxVisual, - dmxScreen->glxVisuals, - dmxScreen->numGlxVisuals ); - be_req->pixmap = (unsigned int)be_pixmap; - be_req->glxpixmap = (unsigned int)pGlxPixmap->be_xids[s]; - UnlockDisplay(dpy); - SyncHandle(); - } - else { - client->errorValue = ( visual ? visual : fbconfigId ); - __glXFree( pGlxPixmap ); - return BadValue; - } - - XFlush( dpy ); - } - - if (!(AddResource(glxpixmapId, __glXPixmapRes, pGlxPixmap))) { - __glXFree( pGlxPixmap ); - return BadAlloc; - } - - return Success; -} - -int __glXCreateGLXPixmap(__GLXclientState *cl, GLbyte *pc) -{ - xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc; - - return( CreateGLXPixmap(cl, req->visual, None, - req->screen, req->pixmap, req->glxpixmap) ); -} - -int __glXCreatePixmap(__GLXclientState *cl, GLbyte *pc) -{ - xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; - - return( CreateGLXPixmap(cl, None, req->fbconfig, - req->screen, req->pixmap, req->glxpixmap) ); -} - -int __glXDestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc; - XID glxpixmap = req->glxpixmap; - __GLXpixmap *pGlxPixmap; - int s; - int from_screen, to_screen; - - /* - ** Check if it's a valid GLX pixmap. - */ - pGlxPixmap = (__GLXpixmap *)LookupIDByType(glxpixmap, __glXPixmapRes); - if (!pGlxPixmap) { - client->errorValue = glxpixmap; - return __glXBadPixmap; - } - FreeResource(glxpixmap, FALSE); - - /* - * destroy the pixmap on the back-end server(s). - */ - from_screen = to_screen = pGlxPixmap->pDraw->pScreen->myNum; -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - /* make sure pixmap exist in back-end */ - dmxSync( dmxScreen, 1 ); - - LockDisplay(dpy); - GetReq(GLXDestroyGLXPixmap,req); - req->reqType = dmxScreen->glxMajorOpcode; - req->glxCode = X_GLXDestroyGLXPixmap; - req->glxpixmap = (unsigned int)pGlxPixmap->be_xids[s]; - UnlockDisplay(dpy); - SyncHandle(); - } - - - return Success; -} - -/*****************************************************************************/ - -/* -** NOTE: There is no portable implementation for swap buffers as of -** this time that is of value. Consequently, this code must be -** implemented by somebody other than SGI. -*/ -int __glXDoSwapBuffers(__GLXclientState *cl, XID drawId, GLXContextTag tag) -{ - ClientPtr client = cl->client; - DrawablePtr pDraw; - xGLXSwapBuffersReq *be_req; - WindowPtr pWin = NULL; - __GLXpixmap *pGlxPixmap = NULL; - __GLXcontext *glxc = NULL; -#ifdef PANORAMIX - PanoramiXRes *pXinDraw = NULL; -#endif - __glXWindow *pGlxWindow = NULL; - int from_screen = 0; - int to_screen = 0; - int s, rc; - - /* - ** Check that the GLX drawable is valid. - */ - rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixWriteAccess); - if (rc == Success) { - from_screen = to_screen = pDraw->pScreen->myNum; - - if (pDraw->type == DRAWABLE_WINDOW) { - /* - ** Drawable is an X window. - */ - pWin = (WindowPtr)pDraw; - } else { - /* - ** Drawable is an X pixmap, which is not allowed. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - if (!pDraw) { - pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, - __glXPixmapRes); - if (pGlxPixmap) { - /* - ** Drawable is a GLX pixmap. - */ - pDraw = pGlxPixmap->pDraw; - from_screen = to_screen = pGlxPixmap->pScreen->myNum; - } - } - - if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); - if (pGlxWindow) { - /* - ** Drawable is a GLXWindow. - */ - pDraw = pGlxWindow->pDraw; - from_screen = to_screen = pGlxWindow->pScreen->myNum; - } - } - - if (!pDraw) { - /* - ** Drawable is neither a X window nor a GLX pixmap. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - - if (tag) { - glxc = __glXLookupContextByTag(cl, tag); - if (!glxc) { - return __glXBadContextTag; - } - } - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - pXinDraw = (PanoramiXRes *) - SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); - } -#endif - - /* If requested, send a glFinish to all back-end servers before swapping. */ - if (dmxGLXFinishSwap) { - for (s=from_screen; s<=to_screen; s++) { - Display *dpy = GetBackEndDisplay(cl,s); - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - xGLXSingleReq *finishReq; - xGLXSingleReply reply; - -#define X_GLXSingle 0 /* needed by GetReq below */ - - LockDisplay(dpy); - GetReq(GLXSingle,finishReq); - finishReq->reqType = dmxScreen->glxMajorOpcode; - finishReq->glxCode = X_GLsop_Finish; - finishReq->contextTag = (tag ? GetCurrentBackEndTag(cl,tag,s) : 0); - (void) _XReply(dpy, (xReply*) &reply, 0, False); - UnlockDisplay(dpy); - SyncHandle(); - } - } - - /* If requested, send an XSync to all back-end servers before swapping. */ - if (dmxGLXSyncSwap) { - for (s=from_screen; s<=to_screen; s++) - XSync(GetBackEndDisplay(cl,s), False); - } - - - /* send the SwapBuffers request to all back-end servers */ - - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - unsigned int be_draw = 0; - - if (pGlxPixmap) { - be_draw = (unsigned int)pGlxPixmap->be_xids[s]; - } -#ifdef PANORAMIX - else if (pXinDraw) { - dixLookupWindow(&pWin, pXinDraw->info[s].id, client, DixReadAccess); - } -#endif - else if (pGlxWindow) { - pWin = (WindowPtr)pGlxWindow->pDraw; - } - - if (pWin && !be_draw) { - be_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; - if (!be_draw) { - /* it might be that the window did not created yet on the */ - /* back-end server (lazy window creation option), force */ - /* creation of the window */ - dmxCreateAndRealizeWindow( pWin, TRUE ); - be_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; - } - } - - dmxSync( dmxScreen, 1 ); - - LockDisplay(dpy); - GetReq(GLXSwapBuffers,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXSwapBuffers; - be_req->drawable = be_draw; - be_req->contextTag = ( tag ? GetCurrentBackEndTag(cl,tag,s) : 0 ); - UnlockDisplay(dpy); - SyncHandle(); - XFlush(dpy); - } - - return Success; -} - -int __glXSwapBuffers(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - DrawablePtr pDraw; - xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc; - GLXContextTag tag = req->contextTag; - XID drawId = req->drawable; - __GLXpixmap *pGlxPixmap = NULL; - __GLXcontext *glxc = NULL; - __glXWindow *pGlxWindow = NULL; - int rc; - - /* - ** Check that the GLX drawable is valid. - */ - rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixWriteAccess); - if (rc == Success) { - if (pDraw->type != DRAWABLE_WINDOW) { - /* - ** Drawable is an X pixmap, which is not allowed. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - if (!pDraw) { - pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, - __glXPixmapRes); - if (pGlxPixmap) { - /* - ** Drawable is a GLX pixmap. - */ - pDraw = pGlxPixmap->pDraw; - } - } - - if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { - pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); - if (pGlxWindow) { - /* - ** Drawable is a GLXWindow. - */ - pDraw = pGlxWindow->pDraw; - } - } - - if (!pDraw) { - /* - ** Drawable is neither a X window nor a GLX pixmap. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - - if (tag) { - glxc = __glXLookupContextByTag(cl, tag); - if (!glxc) { - return __glXBadContextTag; - } - } - - if (pDraw && - pDraw->type == DRAWABLE_WINDOW && - DMX_GET_WINDOW_PRIV((WindowPtr)pDraw)->swapGroup) { - return SGSwapBuffers(cl, drawId, tag, pDraw); - } - - return __glXDoSwapBuffers(cl, drawId, tag); -} - - -/************************************************************************/ - -/* -** Render and Renderlarge are not in the GLX API. They are used by the GLX -** client library to send batches of GL rendering commands. -*/ - -/* -** Execute all the drawing commands in a request. -*/ -int __glXRender(__GLXclientState *cl, GLbyte *pc) -{ - xGLXRenderReq *req; - xGLXRenderReq *be_req; - int size; - __GLXcontext *glxc; - int from_screen = 0; - int to_screen = 0; - int s; - - /* - ** NOTE: much of this code also appears in the byteswapping version of this - ** routine, __glXSwapRender(). Any changes made here should also be - ** duplicated there. - */ - - req = (xGLXRenderReq *) pc; - - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return 0; - } - from_screen = to_screen = glxc->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - pc += sz_xGLXRenderReq; - size = (req->length << 2) - sz_xGLXRenderReq; - - /* - * just forward the request to back-end server(s) - */ - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReq(GLXRender,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXRender; - be_req->length = req->length; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); - _XSend(dpy, (const char *)pc, size); - UnlockDisplay(dpy); - SyncHandle(); - } - - return Success; -} - -/* -** Execute a large rendering request (one that spans multiple X requests). -*/ -int __glXRenderLarge(__GLXclientState *cl, GLbyte *pc) -{ - xGLXRenderLargeReq *req; - xGLXRenderLargeReq *be_req; - __GLXcontext *glxc; - int from_screen = 0; - int to_screen = 0; - int s; - - /* - ** NOTE: much of this code also appears in the byteswapping version of this - ** routine, __glXSwapRenderLarge(). Any changes made here should also be - ** duplicated there. - */ - - req = (xGLXRenderLargeReq *) pc; - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return 0; - } - from_screen = to_screen = glxc->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - pc += sz_xGLXRenderLargeReq; - - /* - * just forward the request to back-end server(s) - */ - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - GetReq(GLXRenderLarge,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXRenderLarge; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); - be_req->length = req->length; - be_req->requestNumber = req->requestNumber; - be_req->requestTotal = req->requestTotal; - be_req->dataBytes = req->dataBytes; - Data(dpy, (const char *)pc, req->dataBytes); - UnlockDisplay(dpy); - SyncHandle(); - - } - - return Success; -} - - -/************************************************************************/ - -int __glXVendorPrivate(__GLXclientState *cl, GLbyte *pc) -{ - xGLXVendorPrivateReq *req; - - req = (xGLXVendorPrivateReq *) pc; - - switch( req->vendorCode ) { - - case X_GLvop_DeleteTexturesEXT: - return __glXVForwardSingleReq( cl, pc ); - break; - - case X_GLXvop_SwapIntervalSGI: - if (glxIsExtensionSupported("SGI_swap_control")) { - return __glXVForwardSingleReq( cl, pc ); - } - else { - return Success; - } - break; - -#if 0 /* glx 1.3 */ - case X_GLXvop_CreateGLXVideoSourceSGIX: - break; - case X_GLXvop_DestroyGLXVideoSourceSGIX: - break; - case X_GLXvop_CreateGLXPixmapWithConfigSGIX: - break; - case X_GLXvop_DestroyGLXPbufferSGIX: - break; - case X_GLXvop_ChangeDrawableAttributesSGIX: - break; -#endif - - case X_GLXvop_BindSwapBarrierSGIX: - return __glXBindSwapBarrierSGIX( cl, pc ); - break; - - case X_GLXvop_JoinSwapGroupSGIX: - return __glXJoinSwapGroupSGIX( cl, pc ); - break; - - case X_GLXvop_CreateContextWithConfigSGIX: - return __glXCreateContextWithConfigSGIX( cl, pc ); - break; - - default: - /* - ** unsupported private request - */ - cl->client->errorValue = req->vendorCode; - return __glXUnsupportedPrivateRequest; - } - - cl->client->errorValue = req->vendorCode; - return __glXUnsupportedPrivateRequest; - -} - -int __glXVendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc) -{ - xGLXVendorPrivateWithReplyReq *req; - - req = (xGLXVendorPrivateWithReplyReq *) pc; - - switch( req->vendorCode ) { - - case X_GLvop_GetConvolutionFilterEXT: - case X_GLvop_GetConvolutionParameterfvEXT: - case X_GLvop_GetConvolutionParameterivEXT: - case X_GLvop_GetSeparableFilterEXT: - case X_GLvop_GetHistogramEXT: - case X_GLvop_GetHistogramParameterivEXT: - case X_GLvop_GetMinmaxEXT: - case X_GLvop_GetMinmaxParameterfvEXT: - case X_GLvop_GetMinmaxParameterivEXT: - case X_GLvop_AreTexturesResidentEXT: - case X_GLvop_IsTextureEXT: - return( __glXVForwardPipe0WithReply(cl, pc) ); - break; - - case X_GLvop_GenTexturesEXT: - return( __glXVForwardAllWithReply(cl, pc) ); - break; - - -#if 0 /* glx1.3 */ - case X_GLvop_GetDetailTexFuncSGIS: - case X_GLvop_GetSharpenTexFuncSGIS: - case X_GLvop_GetColorTableSGI: - case X_GLvop_GetColorTableParameterfvSGI: - case X_GLvop_GetColorTableParameterivSGI: - case X_GLvop_GetTexFilterFuncSGIS: - case X_GLvop_GetInstrumentsSGIX: - case X_GLvop_InstrumentsBufferSGIX: - case X_GLvop_PollInstrumentsSGIX: - case X_GLvop_FlushRasterSGIX: - case X_GLXvop_CreateGLXPbufferSGIX: - case X_GLXvop_GetDrawableAttributesSGIX: - case X_GLXvop_QueryHyperpipeNetworkSGIX: - case X_GLXvop_QueryHyperpipeConfigSGIX: - case X_GLXvop_HyperpipeConfigSGIX: - case X_GLXvop_DestroyHyperpipeConfigSGIX: -#endif - case X_GLXvop_QueryMaxSwapBarriersSGIX: - return( __glXQueryMaxSwapBarriersSGIX(cl, pc) ); - break; - - case X_GLXvop_GetFBConfigsSGIX: - return( __glXGetFBConfigsSGIX(cl, pc) ); - break; - - case X_GLXvop_MakeCurrentReadSGI: - return( __glXMakeCurrentReadSGI(cl, pc) ); - break; - - case X_GLXvop_QueryContextInfoEXT: - return( __glXQueryContextInfoEXT(cl,pc) ); - break; - - default: - /* - ** unsupported private request - */ - cl->client->errorValue = req->vendorCode; - return __glXUnsupportedPrivateRequest; - } - -} - -int __glXQueryExtensionsString(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc; - xGLXQueryExtensionsStringReply reply; - GLint screen; - size_t length; - int len, numbytes; - char *be_buf; - -#ifdef FWD_QUERY_REQ - xGLXQueryExtensionsStringReq *be_req; - xGLXQueryExtensionsStringReply be_reply; - DMXScreenInfo *dmxScreen; - Display *dpy; - int slop; -#endif - - screen = req->screen; - - /* - ** Check if screen exists. - */ - if ((screen < 0) || (screen >= screenInfo.numScreens)) { - client->errorValue = screen; - return BadValue; - } - -#ifdef FWD_QUERY_REQ - dmxScreen = &dmxScreens[screen]; - - /* Send the glXQueryServerString request */ - dpy = GetBackEndDisplay(cl,screen); - LockDisplay(dpy); - GetReq(GLXQueryExtensionsString,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXQueryServerString; - be_req->screen = DefaultScreen(dpy); - _XReply(dpy, (xReply*) &be_reply, 0, False); - len = (int)be_reply.length; - numbytes = (int)be_reply.n; - slop = numbytes * __GLX_SIZE_INT8 & 3; - be_buf = (char *)Xalloc(numbytes); - if (!be_buf) { - /* Throw data on the floor */ - _XEatData(dpy, len); - } else { - _XRead(dpy, (char *)be_buf, numbytes); - if (slop) _XEatData(dpy,4-slop); - } - UnlockDisplay(dpy); - SyncHandle(); - -#else - - be_buf = __glXGetServerString(GLX_EXTENSIONS); - numbytes = strlen(be_buf) + 1; - len = __GLX_PAD(numbytes) >> 2; - -#endif - - length = len; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = len; - reply.n = numbytes; - - if (client->swapped) { - glxSwapQueryExtensionsStringReply(client, &reply, be_buf); - } else { - WriteToClient(client, sz_xGLXQueryExtensionsStringReply,(char *)&reply); - WriteToClient(client, (int)(length << 2), (char *)be_buf); - } - - return Success; -} - -int __glXQueryServerString(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc; - xGLXQueryServerStringReply reply; - int name; - GLint screen; - size_t length; - int len, numbytes; - char *be_buf; -#ifdef FWD_QUERY_REQ - xGLXQueryServerStringReq *be_req; - xGLXQueryServerStringReply be_reply; - DMXScreenInfo *dmxScreen; - Display *dpy; - int slop; -#endif - - name = req->name; - screen = req->screen; - /* - ** Check if screen exists. - */ - if ((screen < 0) || (screen >= screenInfo.numScreens)) { - client->errorValue = screen; - return BadValue; - } - -#ifdef FWD_QUERY_REQ - dmxScreen = &dmxScreens[screen]; - - /* Send the glXQueryServerString request */ - dpy = GetBackEndDisplay(cl,screen); - LockDisplay(dpy); - GetReq(GLXQueryServerString,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXQueryServerString; - be_req->screen = DefaultScreen(dpy); - be_req->name = name; - _XReply(dpy, (xReply*) &be_reply, 0, False); - len = (int)be_reply.length; - numbytes = (int)be_reply.n; - slop = numbytes * __GLX_SIZE_INT8 & 3; - be_buf = (char *)Xalloc(numbytes); - if (!be_buf) { - /* Throw data on the floor */ - _XEatData(dpy, len); - } else { - _XRead(dpy, (char *)be_buf, numbytes); - if (slop) _XEatData(dpy,4-slop); - } - UnlockDisplay(dpy); - SyncHandle(); - -#else - be_buf = __glXGetServerString(name); - numbytes = strlen(be_buf) + 1; - len = __GLX_PAD(numbytes) >> 2; -#endif - - length = len; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = length; - reply.n = numbytes; - - if (client->swapped) { - glxSwapQueryServerStringReply(client, &reply, be_buf); - } else { - WriteToClient(client, sz_xGLXQueryServerStringReply, (char *)&reply); - WriteToClient(client, (int)(length << 2), be_buf); - } - - return Success; -} - -int __glXClientInfo(__GLXclientState *cl, GLbyte *pc) -{ - xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc; - xGLXClientInfoReq *be_req; - const char *buf; - int from_screen = 0; - int to_screen = 0; - int s; - - cl->GLClientmajorVersion = req->major; - cl->GLClientminorVersion = req->minor; - if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); - buf = (const char *)(req+1); - cl->GLClientextensions = strdup(buf); - - to_screen = screenInfo.numScreens - 1; - - for (s=from_screen; s<=to_screen; s++) - { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReq(GLXClientInfo,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXClientInfo; - be_req->major = req->major; - be_req->minor = req->minor; - be_req->length = req->length; - be_req->numbytes = req->numbytes; - Data(dpy, buf, req->numbytes); - - UnlockDisplay(dpy); - SyncHandle(); - } - - return Success; -} - -int __glXUseXFont(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXUseXFontReq *req; - xGLXUseXFontReq *be_req; - FontPtr pFont; - __GLXcontext *glxc = NULL; - int from_screen = 0; - int to_screen = 0; - int s; - dmxFontPrivPtr pFontPriv; - DMXScreenInfo *dmxScreen; - Display *dpy; - - req = (xGLXUseXFontReq *) pc; - - if (req->contextTag != 0) { - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (glxc) { - from_screen = to_screen = glxc->pScreen->myNum; - } - } - - /* - ** Font can actually be either the ID of a font or the ID of a GC - ** containing a font. - */ - pFont = (FontPtr)LookupIDByType(req->font, RT_FONT); - if (!pFont) { - GC *pGC = (GC *)LookupIDByType(req->font, RT_GC); - if (!pGC) { - client->errorValue = req->font; - return BadFont; - } - pFont = pGC->font; - } - - pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex); - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - - for (s=from_screen; s<=to_screen; s++) { - dmxScreen = &dmxScreens[s]; - dpy = GetBackEndDisplay(cl,s); - - dmxSync( dmxScreen, 1 ); - - LockDisplay(dpy); - GetReq(GLXUseXFont,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXUseXFont; - be_req->contextTag = (glxc ? GetCurrentBackEndTag(cl,req->contextTag,s) : 0); - be_req->font = pFontPriv->font[s]->fid; - be_req->first = req->first; - be_req->count = req->count; - be_req->listBase = req->listBase; - UnlockDisplay(dpy); - SyncHandle(); - - XSync( dpy, False ); - } - - return Success; -} - -/* - * start GLX 1.3 here - */ - -int __glXGetFBConfigs(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc; - xGLXGetFBConfigsReply reply; - __GLXFBConfig *pFBConfig; - CARD32 buf[2 * __GLX_TOTAL_FBCONFIG_PROPS]; - int numAttribs = __GLX_TOTAL_FBCONFIG_PROPS; - unsigned int screen = req->screen; - int numFBConfigs, i, p; - __GLXscreenInfo *pGlxScreen; - - if (screen > screenInfo.numScreens) { - /* The client library must send a valid screen number. */ - client->errorValue = screen; - return BadValue; - } - - pGlxScreen = &__glXActiveScreens[screen]; - numFBConfigs = __glXNumFBConfigs; - - reply.numFBConfigs = numFBConfigs; - reply.numAttribs = numAttribs; - reply.length = (numFBConfigs * 2 * numAttribs * __GLX_SIZE_CARD32) >> 2; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - - if (client->swapped) { - __GLX_DECLARE_SWAP_VARIABLES; - __GLX_SWAP_SHORT(&reply.sequenceNumber); - __GLX_SWAP_INT(&reply.length); - __GLX_SWAP_INT(&reply.numFBConfigs); - __GLX_SWAP_INT(&reply.numAttribs); - } - WriteToClient(client, sz_xGLXGetFBConfigsReply, (char *)&reply); - - for (i=0; i < numFBConfigs; i++) { - int associatedVisualId = 0; - int drawableTypeIndex; - pFBConfig = __glXFBConfigs[ i * (screenInfo.numScreens+1) ]; - - p = 0; - /* core attributes */ - buf[p++] = GLX_FBCONFIG_ID; - buf[p++] = pFBConfig->id; - buf[p++] = GLX_BUFFER_SIZE; - buf[p++] = pFBConfig->indexBits; - buf[p++] = GLX_LEVEL; - buf[p++] = pFBConfig->level; - buf[p++] = GLX_DOUBLEBUFFER; - buf[p++] = pFBConfig->doubleBufferMode; - buf[p++] = GLX_STEREO; - buf[p++] = pFBConfig->stereoMode; - buf[p++] = GLX_AUX_BUFFERS; - buf[p++] = pFBConfig->maxAuxBuffers; - buf[p++] = GLX_RED_SIZE; - buf[p++] = pFBConfig->redBits; - buf[p++] = GLX_GREEN_SIZE; - buf[p++] = pFBConfig->greenBits; - buf[p++] = GLX_BLUE_SIZE; - buf[p++] = pFBConfig->blueBits; - buf[p++] = GLX_ALPHA_SIZE; - buf[p++] = pFBConfig->alphaBits; - buf[p++] = GLX_DEPTH_SIZE; - buf[p++] = pFBConfig->depthBits; - buf[p++] = GLX_STENCIL_SIZE; - buf[p++] = pFBConfig->stencilBits; - buf[p++] = GLX_ACCUM_RED_SIZE; - buf[p++] = pFBConfig->accumRedBits; - buf[p++] = GLX_ACCUM_GREEN_SIZE; - buf[p++] = pFBConfig->accumGreenBits; - buf[p++] = GLX_ACCUM_BLUE_SIZE; - buf[p++] = pFBConfig->accumBlueBits; - buf[p++] = GLX_ACCUM_ALPHA_SIZE; - buf[p++] = pFBConfig->accumAlphaBits; - buf[p++] = GLX_RENDER_TYPE; - buf[p++] = pFBConfig->renderType; - buf[p++] = GLX_DRAWABLE_TYPE; - drawableTypeIndex = p; - buf[p++] = pFBConfig->drawableType; - buf[p++] = GLX_X_VISUAL_TYPE; - buf[p++] = pFBConfig->visualType; - buf[p++] = GLX_CONFIG_CAVEAT; - buf[p++] = pFBConfig->visualCaveat; - buf[p++] = GLX_TRANSPARENT_TYPE; - buf[p++] = pFBConfig->transparentType; - buf[p++] = GLX_TRANSPARENT_RED_VALUE; - buf[p++] = pFBConfig->transparentRed; - buf[p++] = GLX_TRANSPARENT_GREEN_VALUE; - buf[p++] = pFBConfig->transparentGreen; - buf[p++] = GLX_TRANSPARENT_BLUE_VALUE; - buf[p++] = pFBConfig->transparentBlue; - buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE; - buf[p++] = pFBConfig->transparentAlpha; - buf[p++] = GLX_TRANSPARENT_INDEX_VALUE; - buf[p++] = pFBConfig->transparentIndex; - buf[p++] = GLX_MAX_PBUFFER_WIDTH; - buf[p++] = pFBConfig->maxPbufferWidth; - buf[p++] = GLX_MAX_PBUFFER_HEIGHT; - buf[p++] = pFBConfig->maxPbufferHeight; - buf[p++] = GLX_MAX_PBUFFER_PIXELS; - buf[p++] = pFBConfig->maxPbufferPixels; - - /* - * find the visual of the back-end server and match a visual - * on the proxy. - * do only once - if a visual is not yet associated. - */ - if (pFBConfig->associatedVisualId == (unsigned int)-1) { - DMXScreenInfo *dmxScreen = &dmxScreens[screen]; - __GLXFBConfig *be_pFBConfig = __glXFBConfigs[ i * (screenInfo.numScreens+1)+screen+1 ]; - __GLXvisualConfig *pGlxVisual = NULL; - int v; - int found = 0; - for (v=0; v<dmxScreen->numGlxVisuals; v++) { - if (dmxScreen->glxVisuals[v].vid == be_pFBConfig->associatedVisualId) { - pGlxVisual = &dmxScreen->glxVisuals[v]; - break; - } - } - - if (pGlxVisual) { - for (v=0; v<pGlxScreen->numVisuals; v++) { - if (glxVisualsMatch(&pGlxScreen->pGlxVisual[v], pGlxVisual)) { - associatedVisualId = pGlxScreen->pGlxVisual[v].vid; - found = 1; - break; - } - } - } - - if (!found) { - associatedVisualId = 0; - pFBConfig->drawableType &= ~(GLX_WINDOW_BIT); - buf[drawableTypeIndex] = pFBConfig->drawableType; - } -#ifdef PANORAMIX - else if (!noPanoramiXExtension) { - /* convert the associated visualId to the panoramix one */ - pFBConfig->associatedVisualId = - PanoramiXTranslateVisualID(screen, v); - } -#endif - } - else { - associatedVisualId = pFBConfig->associatedVisualId; - } - - buf[p++] = GLX_VISUAL_ID; - buf[p++] = associatedVisualId; - - /* SGIS_multisample attributes */ - buf[p++] = GLX_SAMPLES_SGIS; - buf[p++] = pFBConfig->multiSampleSize; - buf[p++] = GLX_SAMPLE_BUFFERS_SGIS; - buf[p++] = pFBConfig->nMultiSampleBuffers; - - /* SGIX_pbuffer specific attributes */ - buf[p++] = GLX_OPTIMAL_PBUFFER_WIDTH_SGIX; - buf[p++] = pFBConfig->optimalPbufferWidth; - buf[p++] = GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX; - buf[p++] = pFBConfig->optimalPbufferHeight; - - buf[p++] = GLX_VISUAL_SELECT_GROUP_SGIX; - buf[p++] = pFBConfig->visualSelectGroup; - - if (client->swapped) { - __GLX_DECLARE_SWAP_VARIABLES; - __GLX_SWAP_INT_ARRAY((int *)buf, 2*numAttribs); - } - WriteToClient(client, 2*numAttribs * __GLX_SIZE_CARD32, (char *)buf); - } - return Success; -} - -int __glXGetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc) -{ - xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)pc; - xGLXGetFBConfigsReq new_req; - - new_req.reqType = req->reqType; - new_req.glxCode = req->glxCode; - new_req.length = req->length; - new_req.screen = req->screen; - - return( __glXGetFBConfigs( cl, (GLbyte *)&new_req ) ); -} - - -int __glXCreateWindow(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; - int screen = req->screen; - GLXFBConfigID fbconfigId = req->fbconfig; - XID windowId = req->window; - XID glxwindowId = req->glxwindow; - DrawablePtr pDraw; - ScreenPtr pScreen; - __glXWindow *pGlxWindow; - __GLXFBConfig *pGlxFBConfig = NULL; - VisualPtr pVisual; - VisualID visId; - int i, rc; - - /* - ** Check if windowId is valid - */ - rc = dixLookupDrawable(&pDraw, windowId, client, M_DRAWABLE_WINDOW, - DixAddAccess); - if (rc != Success) - return rc; - - /* - ** Check if screen of window matches screen of fbconfig. - */ - pScreen = pDraw->pScreen; - if (screen != pScreen->myNum) { - return BadMatch; - } - - /* - ** Find the FBConfigRec for this fbconfigid. - */ - if (!(pGlxFBConfig = glxLookupFBConfig(fbconfigId))) { - client->errorValue = fbconfigId; - return __glXBadFBConfig; - } - visId = pGlxFBConfig->associatedVisualId; - - /* - ** Check if the fbconfig supports rendering to windows - */ - if( !(pGlxFBConfig->drawableType & GLX_WINDOW_BIT) ) { - return BadMatch; - } - - if (visId != None) { - /* - ** Check if the visual ID is valid for this screen. - */ - pVisual = pScreen->visuals; - for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { - if (pVisual->vid == visId) { - break; - } - } - if (i == pScreen->numVisuals) { - client->errorValue = visId; - return BadValue; - } - - /* - ** Check if color buffer depth of fbconfig matches depth - ** of window. - */ - if (pVisual->nplanes != pDraw->depth) { - return BadMatch; - } - } else - /* - ** The window was created with no visual that corresponds - ** to fbconfig - */ - return BadMatch; - - /* - ** Check if there is already a fbconfig associated with this window - */ - if ( LookupIDByType(glxwindowId, __glXWindowRes) ) { - client->errorValue = glxwindowId; - return BadAlloc; - } - - pGlxWindow = (__glXWindow *) xalloc(sizeof(__glXWindow)); - if (!pGlxWindow) { - return BadAlloc; - } - - /* - ** Register this GLX window as a resource - */ - if (!(AddResource(glxwindowId, __glXWindowRes, pGlxWindow))) { - return BadAlloc; - } - - pGlxWindow->pDraw = pDraw; - pGlxWindow->type = GLX_GLXWINDOW_TYPE; - pGlxWindow->idExists = True; - pGlxWindow->refcnt = 0; - pGlxWindow->pGlxFBConfig = pGlxFBConfig; - pGlxWindow->pScreen = pScreen; - - return Success; -} - -int __glXDestroyWindow(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; - XID glxwindow = req->glxwindow; - - /* - ** Check if it's a valid GLX window. - */ - if (!LookupIDByType(glxwindow, __glXWindowRes)) { - client->errorValue = glxwindow; - return __glXBadDrawable; - } - /* - ** The glx window destructor will check whether it's current before - ** freeing anything. - */ - FreeResource(glxwindow, RT_NONE); - - return Success; -} - -int __glXQueryContext(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - __GLXcontext *ctx; - xGLXQueryContextReq *req; - xGLXQueryContextReply reply; - int nProps; - int *sendBuf, *pSendBuf; - int nReplyBytes; - - req = (xGLXQueryContextReq *)pc; - ctx = (__GLXcontext *) LookupIDByType(req->context, __glXContextRes); - if (!ctx) { - client->errorValue = req->context; - return __glXBadContext; - } - - nProps = 3; - - reply.length = nProps << 1; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.n = nProps; - - nReplyBytes = reply.length << 2; - sendBuf = (int *)xalloc(nReplyBytes); - pSendBuf = sendBuf; - *pSendBuf++ = GLX_FBCONFIG_ID; - *pSendBuf++ = (int)(ctx->pFBConfig->id); - *pSendBuf++ = GLX_RENDER_TYPE; - *pSendBuf++ = (int)(ctx->pFBConfig->renderType); - *pSendBuf++ = GLX_SCREEN; - *pSendBuf++ = (int)(ctx->pScreen->myNum); - - if (client->swapped) { - __glXSwapQueryContextReply(client, &reply, sendBuf); - } else { - WriteToClient(client, sz_xGLXQueryContextReply, (char *)&reply); - WriteToClient(client, nReplyBytes, (char *)sendBuf); - } - xfree((char *)sendBuf); - - return Success; -} - -int __glXQueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - __GLXcontext *ctx; - xGLXQueryContextInfoEXTReq *req; - xGLXQueryContextInfoEXTReply reply; - int nProps; - int *sendBuf, *pSendBuf; - int nReplyBytes; - - req = (xGLXQueryContextInfoEXTReq *)pc; - ctx = (__GLXcontext *) SecurityLookupIDByType(client, req->context, __glXContextRes, DixReadAccess); - if (!ctx) { - client->errorValue = req->context; - return __glXBadContext; - } - - nProps = 4; - - reply.length = nProps << 1; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.n = nProps; - - nReplyBytes = reply.length << 2; - sendBuf = (int *)xalloc(nReplyBytes); - pSendBuf = sendBuf; - *pSendBuf++ = GLX_SHARE_CONTEXT_EXT; - *pSendBuf++ = (int)(ctx->share_id); - *pSendBuf++ = GLX_VISUAL_ID_EXT; - *pSendBuf++ = (int)(ctx->pVisual ? ctx->pVisual->vid : 0); - *pSendBuf++ = GLX_SCREEN_EXT; - *pSendBuf++ = (int)(ctx->pScreen->myNum); - *pSendBuf++ = GLX_FBCONFIG_ID; - *pSendBuf++ = (int)(ctx->pFBConfig ? ctx->pFBConfig->id : 0); - - if (client->swapped) { - __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf); - } else { - WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, (char *)&reply); - WriteToClient(client, nReplyBytes, (char *)sendBuf); - } - xfree((char *)sendBuf); - - return Success; -} - -int __glXCreatePbuffer(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *)pc; - xGLXCreatePbufferReq *be_req; - int screen = req->screen; - GLXFBConfigID fbconfigId = req->fbconfig; - GLXPbuffer pbuffer = req->pbuffer; - __glXPbuffer *pGlxPbuffer; - int numAttribs = req->numAttribs; - int *attr; - ScreenPtr pScreen; - __GLXFBConfig *pGlxFBConfig; - __GLXFBConfig *be_pGlxFBConfig; - XID be_xid; - Display *dpy; - DMXScreenInfo *dmxScreen; - int s; - int from_screen, to_screen; - - /* - ** Look up screen and FBConfig. - */ - if (screen > screenInfo.numScreens) { - /* The client library must send a valid screen number. */ - client->errorValue = screen; - return BadValue; - } - pScreen = screenInfo.screens[screen]; - - /* - ** Find the FBConfigRec for this fbconfigid. - */ - if (!(pGlxFBConfig = glxLookupFBConfig(fbconfigId))) { - client->errorValue = fbconfigId; - return __glXBadFBConfig; - } - - /* - ** Create the GLX part of the Pbuffer. - */ - pGlxPbuffer = (__glXPbuffer *) xalloc(sizeof(__glXPbuffer)); - if (!pGlxPbuffer) { - return BadAlloc; - } - - pGlxPbuffer->be_xids = (XID *) xalloc( sizeof(XID) * screenInfo.numScreens ); - if (!pGlxPbuffer->be_xids) { - xfree(pGlxPbuffer); - return BadAlloc; - } - - /* - * Allocate an XID on the back-end server(s) and send him the request - */ - from_screen = to_screen = screen; -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - for (s=from_screen; s<=to_screen; s++) { - dpy = GetBackEndDisplay(cl,s); - be_xid = XAllocID(dpy); - dmxScreen = &dmxScreens[s]; - be_pGlxFBConfig = glxLookupBackEndFBConfig( pGlxFBConfig->id, s ); - - attr = (int *)( req+1 ); - - LockDisplay(dpy); - GetReqExtra(GLXCreatePbuffer, 2 * numAttribs * __GLX_SIZE_CARD32, be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXCreatePbuffer; - be_req->screen = be_pGlxFBConfig->screen; - be_req->fbconfig = be_pGlxFBConfig->id; - be_req->pbuffer = be_xid; - be_req->numAttribs = numAttribs; - - /* Send attributes */ - if ( attr != NULL ) { - CARD32 *pc = (CARD32 *)(be_req + 1); - - while (numAttribs-- > 0) { - *pc++ = *attr++; /* token */ - *pc++ = *attr++; /* value */ - } - } - - UnlockDisplay(dpy); - SyncHandle(); - - pGlxPbuffer->be_xids[s] = be_xid; - } - - - pGlxPbuffer->idExists = True; - pGlxPbuffer->refcnt = 0; - pGlxPbuffer->pFBConfig = pGlxFBConfig; - pGlxPbuffer->pScreen = pScreen; - - /* - ** Register the resource. - */ - if (!(AddResource(pbuffer, __glXPbufferRes, pGlxPbuffer))) { - return BadAlloc; - } - - return Success; - -} - -int __glXDestroyPbuffer(__GLXclientState *cl, GLbyte *pc) -{ - ClientPtr client = cl->client; - xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc; - xGLXDestroyPbufferReq *be_req; - GLXPbuffer pbuffer = req->pbuffer; - Display *dpy; - int screen; - DMXScreenInfo *dmxScreen; - __glXPbuffer *pGlxPbuffer; - int s; - int from_screen, to_screen; - - /* - ** Check if it's a valid Pbuffer - */ - pGlxPbuffer = (__glXPbuffer *)LookupIDByType(pbuffer, __glXPbufferRes); - if (!pGlxPbuffer) { - client->errorValue = pbuffer; - return __glXBadPbuffer; - } - - screen = pGlxPbuffer->pScreen->myNum; - - from_screen = to_screen = screen; -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - for (s=from_screen; s<=to_screen; s++) { - dpy = GetBackEndDisplay(cl,s); - dmxScreen = &dmxScreens[s]; - - /* send the destroy request to the back-end server */ - LockDisplay(dpy); - GetReq(GLXDestroyPbuffer, be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXDestroyPbuffer; - be_req->pbuffer = pGlxPbuffer->be_xids[s]; - UnlockDisplay(dpy); - SyncHandle(); - } - - FreeResource(pbuffer, RT_NONE); - - return Success; -} - -int __glXGetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) -{ - xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc; - xGLXGetDrawableAttributesReq *be_req; - xGLXGetDrawableAttributesReply reply; - ClientPtr client = cl->client; - GLXDrawable drawId = req->drawable; - GLXDrawable be_drawable = 0; - DrawablePtr pDraw = NULL; - Display *dpy; - int screen, rc; - DMXScreenInfo *dmxScreen; - CARD32 *attribs = NULL; - int attribs_size; -#ifdef PANORAMIX - PanoramiXRes *pXinDraw = NULL; -#endif - - if (drawId != None) { - rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess); - if (rc == Success) { - if (pDraw->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr)pDraw; - be_drawable = 0; - screen = pWin->drawable.pScreen->myNum; - - } - else { - /* - ** Drawable is not a Window , GLXWindow or a GLXPixmap. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - if (!pDraw) { - __GLXpixmap *pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, - __glXPixmapRes); - if (pGlxPixmap) { - pDraw = pGlxPixmap->pDraw; - screen = pGlxPixmap->pScreen->myNum; - be_drawable = pGlxPixmap->be_xids[screen]; - } - } - - if (!pDraw) { - __glXWindow *pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); - if (pGlxWindow) { - pDraw = pGlxWindow->pDraw; - screen = pGlxWindow->pScreen->myNum; - be_drawable = 0; - } - } - - if (!pDraw) { - __glXPbuffer *pGlxPbuffer = (__glXPbuffer *)LookupIDByType(drawId, __glXPbufferRes); - if (pGlxPbuffer) { - pDraw = (DrawablePtr)pGlxPbuffer; - screen = pGlxPbuffer->pScreen->myNum; - be_drawable = pGlxPbuffer->be_xids[screen]; - } - } - - - if (!pDraw) { - /* - ** Drawable is not a Window , GLXWindow or a GLXPixmap. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - - /* if the drawable is a window or GLXWindow - - * we need to find the base id on the back-end server - */ - if (!be_drawable) { - WindowPtr pWin = (WindowPtr)pDraw; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - pXinDraw = (PanoramiXRes *) - SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); - if (!pXinDraw) { - client->errorValue = drawId; - return __glXBadDrawable; - } - - dixLookupWindow(&pWin, pXinDraw->info[screen].id, client, - DixReadAccess); - } -#endif - - if (pWin) { - be_drawable = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; - if (!be_drawable) { - /* it might be that the window did not created yet on the */ - /* back-end server (lazy window creation option), force */ - /* creation of the window */ - dmxCreateAndRealizeWindow( pWin, TRUE ); - be_drawable = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; - } - } - else { - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - - /* send the request to the back-end server */ - dpy = GetBackEndDisplay(cl,screen); - dmxScreen = &dmxScreens[screen]; - - /* make sure drawable exists on back-end */ - dmxSync( dmxScreen, 1 ); - - LockDisplay(dpy); - GetReq(GLXGetDrawableAttributes, be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXGetDrawableAttributes; - be_req->drawable = be_drawable; - be_req->length = req->length; - if (!_XReply(dpy, (xReply *) &reply, 0, False)) { - UnlockDisplay(dpy); - SyncHandle(); - return( BE_TO_CLIENT_ERROR(dmxLastErrorEvent.error_code) ); - } - - if (reply.numAttribs) { - attribs_size = 2 * reply.numAttribs * __GLX_SIZE_CARD32; - attribs = (CARD32 *) Xalloc(attribs_size); - if (attribs == NULL) { - UnlockDisplay(dpy); - SyncHandle(); - return BadAlloc; - } - - _XRead(dpy, (char *) attribs, attribs_size); - } - - UnlockDisplay(dpy); - SyncHandle(); - - - /* send the reply back to the client */ - reply.sequenceNumber = client->sequence; - if (client->swapped) { - __glXSwapGetDrawableAttributesReply(client, &reply, (int *)attribs); - } - else { - WriteToClient(client, sz_xGLXGetDrawableAttributesReply, (char *)&reply); - WriteToClient(client, attribs_size, (char *)attribs); - } - - Xfree(attribs); - - return Success; -} - -int __glXChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc) -{ - xGLXChangeDrawableAttributesReq *req = (xGLXChangeDrawableAttributesReq *)pc; - xGLXChangeDrawableAttributesReq *be_req; - ClientPtr client = cl->client; - GLXDrawable drawId = req->drawable; - GLXDrawable be_drawable = 0; - DrawablePtr pDraw = NULL; - Display *dpy; - int screen, rc; - DMXScreenInfo *dmxScreen; - char *attrbuf; -#ifdef PANORAMIX - PanoramiXRes *pXinDraw = NULL; - PanoramiXRes *pXinReadDraw = NULL; -#endif - - if (drawId != None) { - rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixSetAttrAccess); - if (rc == Success) { - if (pDraw->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr)pDraw; - be_drawable = 0; - screen = pWin->drawable.pScreen->myNum; - - } - else { - /* - ** Drawable is not a Window , GLXWindow or a GLXPixmap. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - if (!pDraw) { - __GLXpixmap *pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, - __glXPixmapRes); - if (pGlxPixmap) { - pDraw = pGlxPixmap->pDraw; - screen = pGlxPixmap->pScreen->myNum; - be_drawable = pGlxPixmap->be_xids[screen]; - } - } - - if (!pDraw) { - __glXWindow *pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); - if (pGlxWindow) { - pDraw = pGlxWindow->pDraw; - screen = pGlxWindow->pScreen->myNum; - be_drawable = 0; - } - } - - if (!pDraw) { - __glXPbuffer *pGlxPbuffer = (__glXPbuffer *)LookupIDByType(drawId, __glXPbufferRes); - if (pGlxPbuffer) { - pDraw = (DrawablePtr)pGlxPbuffer; - screen = pGlxPbuffer->pScreen->myNum; - be_drawable = pGlxPbuffer->be_xids[screen]; - } - } - - - if (!pDraw) { - /* - ** Drawable is not a Window , GLXWindow or a GLXPixmap. - */ - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - - /* if the drawable is a window or GLXWindow - - * we need to find the base id on the back-end server - */ - if (!be_drawable) { - WindowPtr pWin = (WindowPtr)pDraw; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - pXinDraw = (PanoramiXRes *) - SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); - if (!pXinDraw) { - client->errorValue = drawId; - return __glXBadDrawable; - } - - dixLookupWindow(&pWin, pXinDraw->info[screen].id, client, - DixReadAccess); - } -#endif - - if (pWin) { - be_drawable = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; - if (!be_drawable) { - /* it might be that the window did not created yet on the */ - /* back-end server (lazy window creation option), force */ - /* creation of the window */ - dmxCreateAndRealizeWindow( pWin, TRUE ); - be_drawable = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; - } - } - else { - client->errorValue = drawId; - return __glXBadDrawable; - } - } - - - /* send the request to the back-end server */ - dpy = GetBackEndDisplay(cl,screen); - dmxScreen = &dmxScreens[screen]; - - /* make sure drawable exists on back-end */ - dmxSync( dmxScreen, 1 ); - - LockDisplay(dpy); - GetReqExtra(GLXChangeDrawableAttributes, - 2 * req->numAttribs * __GLX_SIZE_CARD32, be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLXChangeDrawableAttributes; - be_req->drawable = be_drawable; - be_req->numAttribs = req->numAttribs; - be_req->length = req->length; - - UnlockDisplay(dpy); - SyncHandle(); - - return Success; -} - -int __glXSendLargeCommand(__GLXclientState *cl, GLXContextTag contextTag) -{ - ClientPtr client = cl->client; - xGLXRenderLargeReq *req; - GLint maxSize, amount; - GLint totalRequests, requestNumber; - GLint dataLen; - GLbyte *data; - __GLXcontext *glxc; - int s; - int from_screen, to_screen; - - maxSize = cl->largeCmdMaxReqDataSize - (GLint)sizeof(xGLXRenderLargeReq); - dataLen = cl->largeCmdBytesTotal; - totalRequests = (dataLen / maxSize); - if (dataLen % maxSize) totalRequests++; - - glxc = __glXLookupContextByTag(cl, contextTag); - if (!glxc) { - client->errorValue = contextTag; - return __glXBadContext; - } - from_screen = to_screen = glxc->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - /* - ** Send enough requests until the whole array is sent. - */ - requestNumber = 1; - data = cl->largeCmdBuf; - while (dataLen > 0) { - amount = dataLen; - if (amount > maxSize) { - amount = maxSize; - } - - for (s=from_screen; s<=to_screen; s++) { - - Display *dpy = GetBackEndDisplay(cl,s); - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - - LockDisplay(dpy); - GetReq(GLXRenderLarge,req); - req->reqType = dmxScreen->glxMajorOpcode; - req->glxCode = X_GLXRenderLarge; - req->contextTag = GetCurrentBackEndTag(cl,contextTag,s); - req->length += (amount + 3) >> 2; - req->requestNumber = requestNumber++; - req->requestTotal = totalRequests; - req->dataBytes = amount; - Data(dpy, ((const char*)data), amount); - dataLen -= amount; - data = ((GLbyte *) data) + amount; - UnlockDisplay(dpy); - SyncHandle(); - } - } - - return Success; -} +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "dmx.h" +#include "dmxwindow.h" +#include "dmxpixmap.h" +#include "dmxfont.h" +#include "dmxsync.h" + +#undef Xmalloc +#undef Xcalloc +#undef Xrealloc +#undef Xfree + +#include "glxserver.h" +#include <GL/glxtokens.h> +#include "g_disptab.h" +#include <pixmapstr.h> +#include <windowstr.h> +#include "glxutil.h" +#include "glxext.h" +#include "unpack.h" + +#include "GL/glxproto.h" +#include "glxvendor.h" +#include "glxvisuals.h" +#include "glxswap.h" + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +extern __GLXFBConfig **__glXFBConfigs; +extern int __glXNumFBConfigs; + +extern __GLXFBConfig *glxLookupFBConfig( GLXFBConfigID id ); +extern __GLXFBConfig *glxLookupFBConfigByVID( VisualID vid ); +extern __GLXFBConfig *glxLookupBackEndFBConfig( GLXFBConfigID id, int screen ); +extern int glxIsExtensionSupported( char *ext ); +extern int __glXGetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc); + +#define BE_TO_CLIENT_ERROR(x) \ + ( (x) >= __glXerrorBase ? \ + (x) - dmxScreen->glxErrorBase + __glXerrorBase \ + : (x) ) + +Display *GetBackEndDisplay( __GLXclientState *cl, int s ) +{ + if (! cl->be_displays[s] ) { + cl->be_displays[s] = XOpenDisplay( DisplayString(dmxScreens[s].beDisplay) ); + } + return( cl->be_displays[s] ); +} + +/* +** Create a GL context with the given properties. +*/ +static int CreateContext(__GLXclientState *cl, + GLXContextID gcId, + VisualID vid, GLXFBConfigID fbconfigId, + int screen, + GLXContextID shareList, + int isDirect ) +{ + ClientPtr client = cl->client; + xGLXCreateContextReq *be_req; + xGLXCreateNewContextReq *be_new_req; + VisualPtr pVisual; + ScreenPtr pScreen; + __GLXcontext *glxc, *shareglxc; + __GLXvisualConfig *pGlxVisual; + __GLXscreenInfo *pGlxScreen; + VisualID visual = vid; + GLint i; + int from_screen = screen; + int to_screen = screen; + DMXScreenInfo *dmxScreen; + VisualID be_vid; + GLXFBConfigID be_fbconfigId; + int num_be_screens; + Display *dpy; + + /* + ** Check if screen exists. + */ + if (screen >= screenInfo.numScreens) { + client->errorValue = screen; + return BadValue; + } + + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + /* + ** Find the display list space that we want to share. + ** + */ + if (shareList == None) { + shareglxc = NULL; + } else { + shareglxc = (__GLXcontext *) LookupIDByType(shareList, __glXContextRes); + if (!shareglxc) { + client->errorValue = shareList; + return __glXBadContext; + } + } + + /* + ** Allocate memory for the new context + */ + glxc = __glXCalloc(1, sizeof(__GLXcontext)); + if (!glxc) { + return BadAlloc; + } + + pScreen = screenInfo.screens[screen]; + pGlxScreen = &__glXActiveScreens[screen]; + + if (fbconfigId != None) { + glxc->pFBConfig = glxLookupFBConfig( fbconfigId ); + if (!glxc->pFBConfig) { + client->errorValue = fbconfigId; + __glXFree( glxc ); + return BadValue; + } + visual = glxc->pFBConfig->associatedVisualId; + } + else { + glxc->pFBConfig = NULL; + } + + if (visual != None) { + /* + ** Check if the visual ID is valid for this screen. + */ + pVisual = pScreen->visuals; + for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { + if (pVisual->vid == visual) { + break; + } + } + if (i == pScreen->numVisuals) { + client->errorValue = visual; + __glXFree( glxc ); + return BadValue; + } + + pGlxVisual = pGlxScreen->pGlxVisual; + for (i = 0; i < pGlxScreen->numVisuals; i++, pGlxVisual++) { + if (pGlxVisual->vid == visual) { + break; + } + } + if (i == pGlxScreen->numVisuals) { + /* + ** Visual not support on this screen by this OpenGL implementation. + */ + client->errorValue = visual; + __glXFree( glxc ); + return BadValue; + } + + if ( glxc->pFBConfig == NULL ) { + glxc->pFBConfig = glxLookupFBConfigByVID( visual ); + + if ( glxc->pFBConfig == NULL ) { + /* + * visual does not have an FBConfig ??? + client->errorValue = visual; + __glXFree( glxc ); + return BadValue; + */ + } + } + } + else { + pVisual = NULL; + pGlxVisual = NULL; + } + + glxc->pScreen = pScreen; + glxc->pGlxScreen = pGlxScreen; + glxc->pVisual = pVisual; + glxc->pGlxVisual = pGlxVisual; + + /* + * allocate memory for back-end servers info + */ + num_be_screens = to_screen - from_screen + 1; + glxc->real_ids = (XID *)__glXMalloc(sizeof(XID) * num_be_screens); + if (!glxc->real_ids) { + return BadAlloc; + } + glxc->real_vids = (XID *)__glXMalloc(sizeof(XID) * num_be_screens); + if (!glxc->real_vids) { + return BadAlloc; + } + + for (screen = from_screen; screen <= to_screen; screen++) { + int sent = 0; + pScreen = screenInfo.screens[screen]; + pGlxScreen = &__glXActiveScreens[screen]; + dmxScreen = &dmxScreens[screen]; + + if (glxc->pFBConfig) { + __GLXFBConfig *beFBConfig = glxLookupBackEndFBConfig( glxc->pFBConfig->id, + screen ); + be_fbconfigId = beFBConfig->id; + } + + if (pGlxVisual) { + + be_vid = glxMatchGLXVisualInConfigList( pGlxVisual, + dmxScreen->glxVisuals, + dmxScreen->numGlxVisuals ); + + if (!be_vid) { + /* visual is not supported on the back-end server */ + __glXFree( glxc->real_ids ); + __glXFree( glxc->real_vids ); + __glXFree( glxc ); + return BadValue; + } + } + + glxc->real_ids[screen-from_screen] = XAllocID(GetBackEndDisplay(cl,screen)); + + /* send the create context request to the back-end server */ + dpy = GetBackEndDisplay(cl,screen); + if (glxc->pFBConfig) { + /*Since for a certain visual both RGB and COLOR INDEX + *can be on then the only parmeter to choose the renderType + * should be the class of the colormap since all 4 first + * classes does not support RGB mode only COLOR INDEX , + * and so TrueColor and DirectColor does not support COLOR INDEX*/ + int renderType = glxc->pFBConfig->renderType; + if ( pVisual ) { + switch ( pVisual->class ){ + case PseudoColor: + case StaticColor: + case GrayScale: + case StaticGray: + renderType = GLX_COLOR_INDEX_TYPE; + break; + case TrueColor: + case DirectColor: + default: + renderType = GLX_RGBA_TYPE; + break; + } + } + if ( __GLX_IS_VERSION_SUPPORTED(1,3) ) { + LockDisplay(dpy); + GetReq(GLXCreateNewContext,be_new_req); + be_new_req->reqType = dmxScreen->glxMajorOpcode; + be_new_req->glxCode = X_GLXCreateNewContext; + be_new_req->context = (unsigned int)glxc->real_ids[screen-from_screen]; + be_new_req->fbconfig = (unsigned int)be_fbconfigId; + be_new_req->screen = DefaultScreen(dpy); + be_new_req->renderType = renderType; + + be_new_req->shareList = (shareglxc ? shareglxc->real_ids[screen-from_screen] : 0); + be_new_req->isDirect = 0; + UnlockDisplay(dpy); + glxc->real_vids[screen-from_screen] = be_fbconfigId; + sent = 1; + } + else if (glxIsExtensionSupported("GLX_SGIX_fbconfig")) { + + xGLXCreateContextWithConfigSGIXReq *ext_req; + xGLXVendorPrivateReq *vpreq; + LockDisplay(dpy); + GetReqExtra(GLXVendorPrivate, + sz_xGLXCreateContextWithConfigSGIXReq - sz_xGLXVendorPrivateReq, + vpreq); + ext_req = (xGLXCreateContextWithConfigSGIXReq *)vpreq; + ext_req->reqType = dmxScreen->glxMajorOpcode; + ext_req->glxCode = X_GLXVendorPrivate; + ext_req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX; + ext_req->context = (unsigned int)glxc->real_ids[screen-from_screen]; + ext_req->fbconfig = (unsigned int)be_fbconfigId; + ext_req->screen = DefaultScreen(dpy); + ext_req->renderType = renderType; + ext_req->shareList = (shareglxc ? shareglxc->real_ids[screen-from_screen] : 0); + ext_req->isDirect = 0; + UnlockDisplay(dpy); + glxc->real_vids[screen-from_screen] = be_fbconfigId; + sent = 1; + } + } + + if (!sent) { + LockDisplay(dpy); + GetReq(GLXCreateContext,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXCreateContext; + be_req->context = (unsigned int)glxc->real_ids[screen-from_screen]; + be_req->visual = (unsigned int)be_vid; + be_req->screen = DefaultScreen(dpy); + be_req->shareList = (shareglxc ? shareglxc->real_ids[screen-from_screen] : 0); + be_req->isDirect = 0; + UnlockDisplay(dpy); + glxc->real_vids[screen-from_screen] = be_vid; + } + SyncHandle(); + + } + + /* + ** Register this context as a resource. + */ + if (!AddResource(gcId, __glXContextRes, (pointer)glxc)) { + __glXFree( glxc->real_ids ); + __glXFree( glxc->real_vids ); + __glXFree( glxc ); + client->errorValue = gcId; + return BadAlloc; + } + + /* + ** Finally, now that everything is working, setup the rest of the + ** context. + */ + glxc->id = gcId; + glxc->share_id = shareList; + glxc->idExists = GL_TRUE; + glxc->isCurrent = GL_FALSE; + + return Success; +} + +int __glXCreateContext(__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + + return( CreateContext(cl, req->context,req->visual, None, + req->screen, req->shareList, req->isDirect) ); + +} + +int __glXCreateNewContext(__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; + + return( CreateContext(cl, req->context,None, req->fbconfig, + req->screen, req->shareList, req->isDirect) ); + +} + +int __glXCreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextWithConfigSGIXReq *req = (xGLXCreateContextWithConfigSGIXReq *) pc; + + return( CreateContext(cl, req->context, None, req->fbconfig, + req->screen, req->shareList, req->isDirect) ); + +} + +int __glXQueryMaxSwapBarriersSGIX(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXQueryMaxSwapBarriersSGIXReq *req = + (xGLXQueryMaxSwapBarriersSGIXReq *)pc; + xGLXQueryMaxSwapBarriersSGIXReply reply; + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = 0; + reply.max = QueryMaxSwapBarriersSGIX(req->screen); + + if (client->swapped) { + __glXSwapQueryMaxSwapBarriersSGIXReply(client, &reply); + } else { + WriteToClient(client, sz_xGLXQueryMaxSwapBarriersSGIXReply, + (char *)&reply); + } + + return Success; +} + +int __glXBindSwapBarrierSGIX(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXBindSwapBarrierSGIXReq *req = (xGLXBindSwapBarrierSGIXReq *)pc; + DrawablePtr pDraw; + __GLXpixmap *pGlxPixmap = NULL; + __glXWindow *pGlxWindow = NULL; + int rc; + + rc = dixLookupDrawable(&pDraw, req->drawable, client, 0, DixGetAttrAccess); + if (rc != Success) { + pGlxPixmap = (__GLXpixmap *) LookupIDByType(req->drawable, + __glXPixmapRes); + if (pGlxPixmap) pDraw = pGlxPixmap->pDraw; + } + + if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxWindow = (__glXWindow *) LookupIDByType(req->drawable, + __glXWindowRes); + if (pGlxWindow) pDraw = pGlxWindow->pDraw; + } + + if (!pDraw) { + client->errorValue = req->drawable; + return __glXBadDrawable; + } + + return BindSwapBarrierSGIX(pDraw, req->barrier); +} + +int __glXJoinSwapGroupSGIX(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXJoinSwapGroupSGIXReq *req = (xGLXJoinSwapGroupSGIXReq *)pc; + DrawablePtr pDraw, pMember = NULL; + __GLXpixmap *pGlxPixmap = NULL; + __glXWindow *pGlxWindow = NULL; + int rc; + + rc = dixLookupDrawable(&pDraw, req->drawable, client, 0, DixManageAccess); + if (rc != Success) { + pGlxPixmap = (__GLXpixmap *) LookupIDByType(req->drawable, + __glXPixmapRes); + if (pGlxPixmap) pDraw = pGlxPixmap->pDraw; + } + + if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxWindow = (__glXWindow *) LookupIDByType(req->drawable, + __glXWindowRes); + if (pGlxWindow) pDraw = pGlxWindow->pDraw; + } + + if (!pDraw) { + client->errorValue = req->drawable; + return __glXBadDrawable; + } + + if (req->member != None) { + rc = dixLookupDrawable(&pMember, req->member, client, 0, + DixGetAttrAccess); + if (rc != Success) { + pGlxPixmap = (__GLXpixmap *) LookupIDByType(req->member, + __glXPixmapRes); + if (pGlxPixmap) pMember = pGlxPixmap->pDraw; + } + + if (!pMember && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxWindow = (__glXWindow *) LookupIDByType(req->member, + __glXWindowRes); + if (pGlxWindow) pMember = pGlxWindow->pDraw; + } + + if (!pMember) { + client->errorValue = req->member; + return __glXBadDrawable; + } + } + + return JoinSwapGroupSGIX(pDraw, pMember); +} + + +/* +** Destroy a GL context as an X resource. +*/ +int __glXDestroyContext(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc; + xGLXDestroyContextReq *be_req; + GLXContextID gcId = req->context; + __GLXcontext *glxc; + int from_screen = 0; + int to_screen = 0; + int s; + + glxc = (__GLXcontext *) LookupIDByType(gcId, __glXContextRes); + if (glxc) { + /* + ** Just free the resource; don't actually destroy the context, + ** because it might be in use. The + ** destroy method will be called by the resource destruction routine + ** if necessary. + */ + FreeResourceByType(gcId, __glXContextRes, FALSE); + + from_screen = to_screen = glxc->pScreen->myNum; + + } else { + client->errorValue = gcId; + return __glXBadContext; + } + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + /* + * send DestroyContext request to all back-end servers + */ + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReq(GLXDestroyContext,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXDestroyContext; + be_req->context = glxc->real_ids[s-from_screen]; + UnlockDisplay(dpy); + SyncHandle(); + } + + return Success; +} + +/*****************************************************************************/ + +/* +** For each client, the server keeps a table of all the contexts that are +** current for that client (each thread of a client may have its own current +** context). These routines add, change, and lookup contexts in the table. +*/ + +/* +** Add a current context, and return the tag that will be used to refer to it. +*/ +static int AddCurrentContext(__GLXclientState *cl, __GLXcontext *glxc, DrawablePtr pDraw) +{ + int i; + int num = cl->numCurrentContexts; + __GLXcontext **table = cl->currentContexts; + + if (!glxc) return -1; + + /* + ** Try to find an empty slot and use it. + */ + for (i=0; i < num; i++) { + if (!table[i]) { + table[i] = glxc; + return i+1; + } + } + /* + ** Didn't find a free slot, so we'll have to grow the table. + */ + if (!num) { + table = (__GLXcontext **) __glXMalloc(sizeof(__GLXcontext *)); + cl->currentDrawables = (DrawablePtr *) __glXMalloc(sizeof(DrawablePtr)); + cl->be_currentCTag = (GLXContextTag *) __glXMalloc(screenInfo.numScreens *sizeof(GLXContextTag)); + } else { + table = (__GLXcontext **) __glXRealloc(table, + (num+1)*sizeof(__GLXcontext *)); + cl->currentDrawables = (DrawablePtr *) __glXRealloc( + cl->currentDrawables , + (num+1)*sizeof(DrawablePtr)); + cl->be_currentCTag = (GLXContextTag *) __glXRealloc(cl->be_currentCTag, + (num+1)*screenInfo.numScreens*sizeof(GLXContextTag)); + } + table[num] = glxc; + cl->currentDrawables[num] = pDraw; + cl->currentContexts = table; + cl->numCurrentContexts++; + + memset(cl->be_currentCTag + num*screenInfo.numScreens, 0, + screenInfo.numScreens * sizeof(GLXContextTag)); + + return num+1; +} + +/* +** Given a tag, change the current context for the corresponding entry. +*/ +static void ChangeCurrentContext(__GLXclientState *cl, __GLXcontext *glxc, + GLXContextTag tag) +{ + __GLXcontext **table = cl->currentContexts; + table[tag-1] = glxc; +} + +/* +** Given a tag, and back-end screen number, retrives the current back-end +** tag. +*/ +int GetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s) +{ + if (tag >0) { + return( cl->be_currentCTag[ (tag-1)*screenInfo.numScreens + s ] ); + } + else { + return( 0 ); + } +} + +/* +** Given a tag, and back-end screen number, sets the current back-end +** tag. +*/ +static void SetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s, GLXContextTag be_tag) +{ + if (tag >0) { + cl->be_currentCTag[ (tag-1)*screenInfo.numScreens + s ] = be_tag; + } +} + +/* +** For this implementation we have chosen to simply use the index of the +** context's entry in the table as the context tag. A tag must be greater +** than 0. +*/ +__GLXcontext *__glXLookupContextByTag(__GLXclientState *cl, GLXContextTag tag) +{ + int num = cl->numCurrentContexts; + + if (tag < 1 || tag > num) { + return 0; + } else { + return cl->currentContexts[tag-1]; + } +} + +DrawablePtr __glXLookupDrawableByTag(__GLXclientState *cl, GLXContextTag tag) +{ + int num = cl->numCurrentContexts; + + if (tag < 1 || tag > num) { + return 0; + } else { + return cl->currentDrawables[tag-1]; + } +} + +/*****************************************************************************/ + +static void StopUsingContext(__GLXcontext *glxc) +{ + if (glxc) { + if (glxc == __glXLastContext) { + /* Tell server GL library */ + __glXLastContext = 0; + } + glxc->isCurrent = GL_FALSE; + if (!glxc->idExists) { + __glXFreeContext(glxc); + } + } +} + +static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc) +{ + glxc->isCurrent = GL_TRUE; +} + +/*****************************************************************************/ +/* +** Make an OpenGL context and drawable current. +*/ +static int MakeCurrent(__GLXclientState *cl, + GLXDrawable drawable, + GLXDrawable readdrawable, + GLXContextID context, + GLXContextTag oldContextTag) +{ + ClientPtr client = cl->client; + DrawablePtr pDraw = NULL; + DrawablePtr pReadDraw = NULL; + xGLXMakeCurrentReadSGIReply new_reply; + xGLXMakeCurrentReq *be_req; + xGLXMakeCurrentReply be_reply; + xGLXMakeContextCurrentReq *be_new_req; + xGLXMakeContextCurrentReply be_new_reply; + GLXDrawable drawId = drawable; + GLXDrawable readId = readdrawable; + GLXContextID contextId = context; + __GLXpixmap *pGlxPixmap = 0; + __GLXpixmap *pReadGlxPixmap = 0; + __GLXcontext *glxc, *prevglxc; + GLXContextTag tag = oldContextTag; + WindowPtr pWin = NULL; + WindowPtr pReadWin = NULL; + __glXWindow *pGlxWindow = NULL; + __glXWindow *pGlxReadWindow = NULL; + __glXPbuffer *pGlxPbuffer = NULL; + __glXPbuffer *pGlxReadPbuffer = NULL; +#ifdef PANORAMIX + PanoramiXRes *pXinDraw = NULL; + PanoramiXRes *pXinReadDraw = NULL; +#endif + int from_screen = 0; + int to_screen = 0; + int s, rc; + + /* + ** If one is None and the other isn't, it's a bad match. + */ + if ((drawId == None && contextId != None) || + (drawId != None && contextId == None)) { + return BadMatch; + } + + /* + ** Lookup old context. If we have one, it must be in a usable state. + */ + if (tag != 0) { + prevglxc = __glXLookupContextByTag(cl, tag); + if (!prevglxc) { + /* + ** Tag for previous context is invalid. + */ + return __glXBadContextTag; + } + } else { + prevglxc = 0; + } + + /* + ** Lookup new context. It must not be current for someone else. + */ + if (contextId != None) { + glxc = (__GLXcontext *) LookupIDByType(contextId, __glXContextRes); + if (!glxc) { + client->errorValue = contextId; + return __glXBadContext; + } + if ((glxc != prevglxc) && glxc->isCurrent) { + /* Context is current to somebody else */ + return BadAccess; + } + } else { + /* Switching to no context. Ignore new drawable. */ + glxc = 0; + } + + if (drawId != None) { + rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixWriteAccess); + if (rc == Success) { + if (pDraw->type == DRAWABLE_WINDOW) { + /* + ** Drawable is an X Window. + */ + VisualID vid; + pWin = (WindowPtr)pDraw; + vid = wVisual(pWin); + + new_reply.writeVid = (glxc->pFBConfig ? glxc->pFBConfig->id : vid); + new_reply.writeType = GLX_WINDOW_TYPE; + + /* + ** Check if window and context are similar. + */ + if ((vid != glxc->pVisual->vid) || + (pWin->drawable.pScreen != glxc->pScreen)) { + client->errorValue = drawId; + return BadMatch; + } + + from_screen = to_screen = pWin->drawable.pScreen->myNum; + + } else { + /* + ** An X Pixmap is not allowed as a parameter (a GLX Pixmap + ** is, but it must first be created with glxCreateGLXPixmap). + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + if (!pDraw) { + pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, + __glXPixmapRes); + if (pGlxPixmap) { + /* + ** Check if pixmap and context are similar. + */ + if (pGlxPixmap->pScreen != glxc->pScreen || + pGlxPixmap->pGlxVisual != glxc->pGlxVisual) { + client->errorValue = drawId; + return BadMatch; + } + pDraw = pGlxPixmap->pDraw; + + new_reply.writeVid = (glxc->pFBConfig ? glxc->pFBConfig->id : + pGlxPixmap->pGlxVisual->vid); + + new_reply.writeType = GLX_PIXMAP_TYPE; + + from_screen = to_screen = pGlxPixmap->pScreen->myNum; + + } + } + + if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); + if (pGlxWindow) { + /* + ** Drawable is a GLXWindow. + ** + ** Check if GLX window and context are similar. + */ + if (pGlxWindow->pScreen != glxc->pScreen || + pGlxWindow->pGlxFBConfig != glxc->pFBConfig) { + client->errorValue = drawId; + return BadMatch; + } + + pDraw = pGlxWindow->pDraw; + new_reply.writeVid = pGlxWindow->pGlxFBConfig->id; + new_reply.writeType = GLX_GLXWINDOW_TYPE; + } + + } + + if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxPbuffer = (__glXPbuffer *)LookupIDByType(drawId, __glXPbufferRes); + if (pGlxPbuffer) { + if (pGlxPbuffer->pScreen != glxc->pScreen || + pGlxPbuffer->pFBConfig != glxc->pFBConfig) { + client->errorValue = drawId; + return BadMatch; + } + + pDraw = (DrawablePtr)pGlxPbuffer; + new_reply.writeVid = pGlxPbuffer->pFBConfig->id; + new_reply.writeType = GLX_PBUFFER_TYPE; + } + } + + if (!pDraw) { + /* + ** Drawable is not a Window , GLXWindow or a GLXPixmap. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + + } else { + pDraw = 0; + } + + if (readId != None && readId != drawId ) { + rc = dixLookupDrawable(&pReadDraw, readId, client, 0, DixReadAccess); + if (rc == Success) { + if (pReadDraw->type == DRAWABLE_WINDOW) { + /* + ** Drawable is an X Window. + */ + VisualID vid; + pReadWin = (WindowPtr)pDraw; + vid = wVisual(pReadWin); + + new_reply.readVid = (glxc->pFBConfig ? glxc->pFBConfig->id : vid); + new_reply.readType = GLX_WINDOW_TYPE; + + /* + ** Check if window and context are similar. + */ + if ((vid != glxc->pVisual->vid) || + (pReadWin->drawable.pScreen != glxc->pScreen)) { + client->errorValue = readId; + return BadMatch; + } + + } else { + + /* + ** An X Pixmap is not allowed as a parameter (a GLX Pixmap + ** is, but it must first be created with glxCreateGLXPixmap). + */ + client->errorValue = readId; + return __glXBadDrawable; + } + } + + if (!pReadDraw) { + pReadGlxPixmap = (__GLXpixmap *) LookupIDByType(readId, + __glXPixmapRes); + if (pReadGlxPixmap) { + /* + ** Check if pixmap and context are similar. + */ + if (pReadGlxPixmap->pScreen != glxc->pScreen || + pReadGlxPixmap->pGlxVisual != glxc->pGlxVisual) { + client->errorValue = readId; + return BadMatch; + } + pReadDraw = pReadGlxPixmap->pDraw; + + new_reply.readVid = (glxc->pFBConfig ? glxc->pFBConfig->id : + pReadGlxPixmap->pGlxVisual->vid ); + new_reply.readType = GLX_PIXMAP_TYPE; + + } + } + + if (!pReadDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxReadWindow = (__glXWindow *) + LookupIDByType(readId, __glXWindowRes); + if (pGlxReadWindow) { + /* + ** Drawable is a GLXWindow. + ** + ** Check if GLX window and context are similar. + */ + if (pGlxReadWindow->pScreen != glxc->pScreen || + pGlxReadWindow->pGlxFBConfig != glxc->pFBConfig) { + client->errorValue = readId; + return BadMatch; + } + + pReadDraw = pGlxReadWindow->pDraw; + new_reply.readVid = pGlxReadWindow->pGlxFBConfig->id; + new_reply.readType = GLX_GLXWINDOW_TYPE; + } + } + + if (!pReadDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxReadPbuffer = (__glXPbuffer *)LookupIDByType(readId, __glXPbufferRes); + if (pGlxReadPbuffer) { + if (pGlxReadPbuffer->pScreen != glxc->pScreen || + pGlxReadPbuffer->pFBConfig != glxc->pFBConfig) { + client->errorValue = drawId; + return BadMatch; + } + + pReadDraw = (DrawablePtr)pGlxReadPbuffer; + new_reply.readVid = pGlxReadPbuffer->pFBConfig->id; + new_reply.readType = GLX_PBUFFER_TYPE; + } + } + + if (!pReadDraw) { + /* + ** Drawable is neither a Window nor a GLXPixmap. + */ + client->errorValue = readId; + return __glXBadDrawable; + } + + } else { + pReadDraw = pDraw; + pReadGlxPixmap = pGlxPixmap; + pReadWin = pWin; + new_reply.readVid = new_reply.writeVid; + new_reply.readType = new_reply.writeType; + } + + if (prevglxc) { + + if (prevglxc->pGlxPixmap) { + /* + ** The previous drawable was a glx pixmap, release it. + */ + prevglxc->pGlxPixmap->refcnt--; + __glXFreeGLXPixmap( prevglxc->pGlxPixmap ); + prevglxc->pGlxPixmap = 0; + } + + if (prevglxc->pGlxReadPixmap) { + /* + ** The previous drawable was a glx pixmap, release it. + */ + prevglxc->pGlxReadPixmap->refcnt--; + __glXFreeGLXPixmap( prevglxc->pGlxReadPixmap ); + prevglxc->pGlxReadPixmap = 0; + } + + if (prevglxc->pGlxWindow) { + /* + ** The previous drawable was a glx window, release it. + */ + prevglxc->pGlxWindow->refcnt--; + __glXFreeGLXWindow( prevglxc->pGlxWindow ); + prevglxc->pGlxWindow = 0; + } + + if (prevglxc->pGlxReadWindow) { + /* + ** The previous drawable was a glx window, release it. + */ + prevglxc->pGlxReadWindow->refcnt--; + __glXFreeGLXWindow( prevglxc->pGlxReadWindow ); + prevglxc->pGlxReadWindow = 0; + } + + if (prevglxc->pGlxPbuffer) { + /* + ** The previous drawable was a glx Pbuffer, release it. + */ + prevglxc->pGlxPbuffer->refcnt--; + __glXFreeGLXPbuffer( prevglxc->pGlxPbuffer ); + prevglxc->pGlxPbuffer = 0; + } + + if (prevglxc->pGlxReadPbuffer) { + /* + ** The previous drawable was a glx Pbuffer, release it. + */ + prevglxc->pGlxReadPbuffer->refcnt--; + __glXFreeGLXPbuffer( prevglxc->pGlxReadPbuffer ); + prevglxc->pGlxReadPbuffer = 0; + } + + ChangeCurrentContext(cl, glxc, tag); + ChangeCurrentContext(cl, glxc, tag); + StopUsingContext(prevglxc); + } else { + tag = AddCurrentContext(cl, glxc, pDraw); + } + if (glxc) { + + glxc->pGlxPixmap = pGlxPixmap; + glxc->pGlxReadPixmap = pReadGlxPixmap; + glxc->pGlxWindow = pGlxWindow; + glxc->pGlxReadWindow = pGlxReadWindow; + glxc->pGlxPbuffer = pGlxPbuffer; + glxc->pGlxReadPbuffer = pGlxReadPbuffer; + + if (pGlxPixmap) { + pGlxPixmap->refcnt++; + } + + if (pReadGlxPixmap) { + pReadGlxPixmap->refcnt++; + } + + if (pGlxWindow) { + pGlxWindow->refcnt++; + } + + if (pGlxReadWindow) { + pGlxReadWindow->refcnt++; + } + + if (pGlxPbuffer) { + pGlxPbuffer->refcnt++; + } + + if (pGlxReadPbuffer) { + pGlxReadPbuffer->refcnt++; + } + + StartUsingContext(cl, glxc); + new_reply.contextTag = tag; + } else { + new_reply.contextTag = 0; + } + new_reply.length = 0; + new_reply.type = X_Reply; + new_reply.sequenceNumber = client->sequence; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + + if (pDraw && new_reply.writeType != GLX_PBUFFER_TYPE) { + pXinDraw = (PanoramiXRes *) + SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); + } + + if (pReadDraw && pReadDraw != pDraw && + new_reply.readType != GLX_PBUFFER_TYPE) { + pXinReadDraw = (PanoramiXRes *) + SecurityLookupIDByClass(client, pReadDraw->id, XRC_DRAWABLE, DixReadAccess); + } + else { + pXinReadDraw = pXinDraw; + } + } +#endif + + + /* send the MakeCurrent request to all required + * back-end servers. + */ + for (s = from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + unsigned int be_draw = None; + unsigned int be_read_draw = None; + + if (pGlxPixmap) { + be_draw = pGlxPixmap->be_xids[s]; + } + else if (pGlxPbuffer) { + be_draw = pGlxPbuffer->be_xids[s]; + } +#ifdef PANORAMIX + else if (pXinDraw) { + dixLookupWindow(&pWin, pXinDraw->info[s].id, client, DixReadAccess); + } +#endif + else if (pGlxWindow) { + pWin = (WindowPtr)pGlxWindow->pDraw; + } + + if (pWin && be_draw == None) { + be_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; + if (!be_draw) { + /* it might be that the window did not created yet on the */ + /* back-end server (lazy window creation option), force */ + /* creation of the window */ + dmxCreateAndRealizeWindow( pWin, TRUE ); + be_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; + } + } + + /* + * Before sending the MakeCurrent request - sync the + * X11 connection to the back-end servers to make sure + * that drawable is already created + */ + dmxSync( dmxScreen, 1 ); + + if (drawId == readId) { + LockDisplay(dpy); + GetReq(GLXMakeCurrent, be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXMakeCurrent; + be_req->drawable = be_draw; + be_req->context = (unsigned int)(glxc ? glxc->real_ids[s-from_screen] : 0); + be_req->oldContextTag = GetCurrentBackEndTag(cl, tag, s); + if (!_XReply(dpy, (xReply *) &be_reply, 0, False)) { + + /* The make current failed */ + UnlockDisplay(dpy); + SyncHandle(); + return( BE_TO_CLIENT_ERROR(dmxLastErrorEvent.error_code) ); + } + + UnlockDisplay(dpy); + SyncHandle(); + + SetCurrentBackEndTag( cl, tag, s, be_reply.contextTag ); + } + else { + + if (pReadGlxPixmap) { + be_read_draw = pReadGlxPixmap->be_xids[s]; + } + else if (pGlxReadPbuffer) { + be_read_draw = pGlxReadPbuffer->be_xids[s]; + } +#ifdef PANORAMIX + else if (pXinReadDraw) { + dixLookupWindow(&pReadWin, pXinReadDraw->info[s].id, client, + DixReadAccess); + } +#endif + else if (pGlxReadWindow) { + pReadWin = (WindowPtr)pGlxReadWindow->pDraw; + } + + if (pReadWin && be_read_draw == None) { + be_read_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pReadWin))->window; + if (!be_read_draw) { + /* it might be that the window did not created yet on the */ + /* back-end server (lazy window creation option), force */ + /* creation of the window */ + dmxCreateAndRealizeWindow( pReadWin, TRUE ); + be_read_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pReadWin))->window; + dmxSync( dmxScreen, 1 ); + } + } + + if ( __GLX_IS_VERSION_SUPPORTED(1,3) ) { + LockDisplay(dpy); + GetReq(GLXMakeContextCurrent, be_new_req); + be_new_req->reqType = dmxScreen->glxMajorOpcode; + be_new_req->glxCode = X_GLXMakeContextCurrent; + be_new_req->drawable = be_draw; + be_new_req->readdrawable = be_read_draw; + be_new_req->context = (unsigned int)(glxc ? glxc->real_ids[s-from_screen] : 0); + be_new_req->oldContextTag = GetCurrentBackEndTag(cl, tag, s); + if (!_XReply(dpy, (xReply *) &be_new_reply, 0, False)) { + + /* The make current failed */ + UnlockDisplay(dpy); + SyncHandle(); + return( BE_TO_CLIENT_ERROR(dmxLastErrorEvent.error_code) ); + } + + UnlockDisplay(dpy); + SyncHandle(); + + SetCurrentBackEndTag( cl, tag, s, be_new_reply.contextTag ); + } + else if (glxIsExtensionSupported("GLX_SGI_make_current_read")) { + xGLXMakeCurrentReadSGIReq *ext_req; + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXMakeCurrentReadSGIReply ext_reply; + + LockDisplay(dpy); + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXMakeCurrentReadSGIReq - sz_xGLXVendorPrivateWithReplyReq, + vpreq); + ext_req = (xGLXMakeCurrentReadSGIReq *)vpreq; + ext_req->reqType = dmxScreen->glxMajorOpcode; + ext_req->glxCode = X_GLXVendorPrivateWithReply; + ext_req->vendorCode = X_GLXvop_MakeCurrentReadSGI; + ext_req->drawable = be_draw; + ext_req->readable = be_read_draw; + ext_req->context = (unsigned int)(glxc ? glxc->real_ids[s-from_screen] : 0); + ext_req->oldContextTag = GetCurrentBackEndTag(cl, tag, s); + if (!_XReply(dpy, (xReply *) &ext_reply, 0, False)) { + + /* The make current failed */ + UnlockDisplay(dpy); + SyncHandle(); + return( BE_TO_CLIENT_ERROR(dmxLastErrorEvent.error_code) ); + } + + UnlockDisplay(dpy); + SyncHandle(); + + SetCurrentBackEndTag( cl, tag, s, ext_reply.contextTag ); + + } + else { + return BadMatch; + } + } + + XFlush( dpy ); + } + + if (client->swapped) { + __glXSwapMakeCurrentReply(client, &new_reply); + } else { + WriteToClient(client, sz_xGLXMakeContextCurrentReply, (char *)&new_reply); + } + + return Success; +} + +int __glXMakeCurrent(__GLXclientState *cl, GLbyte *pc) +{ + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc; + + return( MakeCurrent(cl, req->drawable, req->drawable, + req->context, req->oldContextTag ) ); +} + +int __glXMakeContextCurrent(__GLXclientState *cl, GLbyte *pc) +{ + xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc; + + return( MakeCurrent(cl, req->drawable, req->readdrawable, + req->context, req->oldContextTag ) ); +} + +int __glXMakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) +{ + xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc; + + return( MakeCurrent(cl, req->drawable, req->readable, + req->context, req->oldContextTag ) ); +} + +int __glXIsDirect(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc; + xGLXIsDirectReply reply; + __GLXcontext *glxc; + + /* + ** Find the GL context. + */ + glxc = (__GLXcontext *) LookupIDByType(req->context, __glXContextRes); + if (!glxc) { + client->errorValue = req->context; + return __glXBadContext; + } + + reply.isDirect = 0; + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (client->swapped) { + __glXSwapIsDirectReply(client, &reply); + } else { + WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); + } + + return Success; +} + +int __glXQueryVersion(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; +/* xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc; */ + xGLXQueryVersionReply reply; + + /* + ** Server should take into consideration the version numbers sent by the + ** client if it wants to work with older clients; however, in this + ** implementation the server just returns its version number. + */ + reply.majorVersion = __glXVersionMajor; + reply.minorVersion = __glXVersionMinor; + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (client->swapped) { + __glXSwapQueryVersionReply(client, &reply); + } else { + WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply); + } + return Success; +} + +int __glXWaitGL(__GLXclientState *cl, GLbyte *pc) +{ + xGLXWaitGLReq *req = (xGLXWaitGLReq *)pc; + xGLXWaitGLReq *be_req = (xGLXWaitGLReq *)pc; + int from_screen = 0; + int to_screen = 0; + int s; + __GLXcontext *glxc = NULL; + + if (req->contextTag != 0) { + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (glxc) { + from_screen = to_screen = glxc->pScreen->myNum; + } + } + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReq(GLXWaitGL,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXWaitGL; + be_req->contextTag = (glxc ? GetCurrentBackEndTag(cl,req->contextTag,s) : 0); + UnlockDisplay(dpy); + SyncHandle(); + + XSync(dpy, False); + } + + return Success; +} + +int __glXWaitX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXWaitXReq *req = (xGLXWaitXReq *)pc; + xGLXWaitXReq *be_req; + int from_screen = 0; + int to_screen = 0; + int s; + __GLXcontext *glxc = NULL; + + if (req->contextTag != 0) { + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (glxc) { + from_screen = to_screen = glxc->pScreen->myNum; + } + } + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + dmxSync( dmxScreen, 1 ); + + LockDisplay(dpy); + GetReq(GLXWaitX,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXWaitX; + be_req->contextTag = (glxc ? GetCurrentBackEndTag(cl,req->contextTag,s) : 0); + UnlockDisplay(dpy); + SyncHandle(); + + XFlush( dpy ); + } + + return Success; +} + +int __glXCopyContext(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXCopyContextReq *be_req; + xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc; + GLXContextID source = req->source; + GLXContextID dest = req->dest; + GLXContextTag tag = req->contextTag; + unsigned long mask = req->mask; + __GLXcontext *src, *dst; + int s; + int from_screen = 0; + int to_screen = 0; + + /* + ** Check that each context exists. + */ + src = (__GLXcontext *) LookupIDByType(source, __glXContextRes); + if (!src) { + client->errorValue = source; + return __glXBadContext; + } + dst = (__GLXcontext *) LookupIDByType(dest, __glXContextRes); + if (!dst) { + client->errorValue = dest; + return __glXBadContext; + } + + /* + ** They must be in the same address space, and same screen. + */ + if (src->pGlxScreen != dst->pGlxScreen) { + client->errorValue = source; + return BadMatch; + } + + /* + ** The destination context must not be current for any client. + */ + if (dst->isCurrent) { + client->errorValue = dest; + return BadAccess; + } + + if (tag) { + __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag); + + if (!tagcx) { + return __glXBadContextTag; + } + if (tagcx != src) { + /* + ** This would be caused by a faulty implementation of the client + ** library. + */ + return BadMatch; + } + } + + from_screen = to_screen = src->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReq(GLXCopyContext,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXCopyContext; + be_req->source = (unsigned int)src->real_ids[s-from_screen]; + be_req->dest = (unsigned int)dst->real_ids[s-from_screen]; + be_req->mask = mask; + be_req->contextTag = (tag ? GetCurrentBackEndTag(cl,req->contextTag,s) : 0); + UnlockDisplay(dpy); + SyncHandle(); + } + + return Success; +} + +int __glXGetVisualConfigs(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc; + xGLXGetVisualConfigsReply reply; + __GLXscreenInfo *pGlxScreen; + __GLXvisualConfig *pGlxVisual; + CARD32 buf[__GLX_TOTAL_CONFIG]; + unsigned int screen; + int i, p; + + screen = req->screen; + if (screen > screenInfo.numScreens) { + /* The client library must send a valid screen number. */ + client->errorValue = screen; + return BadValue; + } + pGlxScreen = &__glXActiveScreens[screen]; + + reply.numVisuals = pGlxScreen->numGLXVisuals; + reply.numProps = __GLX_TOTAL_CONFIG; + reply.length = (pGlxScreen->numGLXVisuals * __GLX_SIZE_CARD32 * + __GLX_TOTAL_CONFIG) >> 2; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char *)&reply); + + for (i=0; i < pGlxScreen->numVisuals; i++) { + pGlxVisual = &pGlxScreen->pGlxVisual[i]; + if (!pGlxScreen->isGLXvis[i] || pGlxVisual->vid == 0) { + /* not a usable visual */ + continue; + } + p = 0; + buf[p++] = pGlxVisual->vid; + buf[p++] = pGlxVisual->class; + buf[p++] = pGlxVisual->rgba; + + buf[p++] = pGlxVisual->redSize; + buf[p++] = pGlxVisual->greenSize; + buf[p++] = pGlxVisual->blueSize; + buf[p++] = pGlxVisual->alphaSize; + buf[p++] = pGlxVisual->accumRedSize; + buf[p++] = pGlxVisual->accumGreenSize; + buf[p++] = pGlxVisual->accumBlueSize; + buf[p++] = pGlxVisual->accumAlphaSize; + + buf[p++] = pGlxVisual->doubleBuffer; + buf[p++] = pGlxVisual->stereo; + + buf[p++] = pGlxVisual->bufferSize; + buf[p++] = pGlxVisual->depthSize; + buf[p++] = pGlxVisual->stencilSize; + buf[p++] = pGlxVisual->auxBuffers; + buf[p++] = pGlxVisual->level; + /* + ** Add token/value pairs for extensions. + */ + buf[p++] = GLX_VISUAL_CAVEAT_EXT; + buf[p++] = pGlxVisual->visualRating; + buf[p++] = GLX_TRANSPARENT_TYPE_EXT; + buf[p++] = pGlxVisual->transparentPixel; + buf[p++] = GLX_TRANSPARENT_RED_VALUE_EXT; + buf[p++] = pGlxVisual->transparentRed; + buf[p++] = GLX_TRANSPARENT_GREEN_VALUE_EXT; + buf[p++] = pGlxVisual->transparentGreen; + buf[p++] = GLX_TRANSPARENT_BLUE_VALUE_EXT; + buf[p++] = pGlxVisual->transparentBlue; + buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE_EXT; + buf[p++] = pGlxVisual->transparentAlpha; + buf[p++] = GLX_TRANSPARENT_INDEX_VALUE_EXT; + buf[p++] = pGlxVisual->transparentIndex; + buf[p++] = GLX_SAMPLES_SGIS; + buf[p++] = pGlxVisual->multiSampleSize; + buf[p++] = GLX_SAMPLE_BUFFERS_SGIS; + buf[p++] = pGlxVisual->nMultiSampleBuffers; + buf[p++] = GLX_VISUAL_SELECT_GROUP_SGIX; + buf[p++] = pGlxVisual->visualSelectGroup; + + WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_TOTAL_CONFIG, + (char *)buf); + } + return Success; +} + +/* +** Create a GLX Pixmap from an X Pixmap. +*/ +static int CreateGLXPixmap(__GLXclientState *cl, + VisualID visual, GLXFBConfigID fbconfigId, + int screenNum, XID pixmapId, XID glxpixmapId ) +{ + ClientPtr client = cl->client; + xGLXCreateGLXPixmapReq *be_req; + xGLXCreatePixmapReq *be_new_req; + DrawablePtr pDraw; + ScreenPtr pScreen; + VisualPtr pVisual; + __GLXpixmap *pGlxPixmap; + __GLXscreenInfo *pGlxScreen; + __GLXvisualConfig *pGlxVisual; + __GLXFBConfig *pFBConfig; + int i, s, rc; + int from_screen, to_screen; +#ifdef PANORAMIX + PanoramiXRes *pXinDraw = NULL; +#endif + + rc = dixLookupDrawable(&pDraw, pixmapId, client, M_DRAWABLE_PIXMAP, + DixAddAccess); + if (rc != Success) + return rc; + + /* + ** Check if screen of visual matches screen of pixmap. + */ + pScreen = pDraw->pScreen; + if (screenNum != pScreen->myNum) { + return BadMatch; + } + + if (fbconfigId == NULL && visual == NULL) { + return BadValue; + } + + if (fbconfigId != None) { + pFBConfig = glxLookupFBConfig( fbconfigId ); + if (!pFBConfig) { + client->errorValue = fbconfigId; + return BadValue; + } + visual = pFBConfig->associatedVisualId; + } + else { + pFBConfig = NULL; + } + + if (visual != None) { + /* + ** Find the VisualRec for this visual. + */ + pVisual = pScreen->visuals; + for (i=0; i < pScreen->numVisuals; i++, pVisual++) { + if (pVisual->vid == visual) { + break; + } + } + if (i == pScreen->numVisuals) { + client->errorValue = visual; + return BadValue; + } + /* + ** Check if depth of visual matches depth of pixmap. + */ + if (pVisual->nplanes != pDraw->depth) { + client->errorValue = visual; + return BadMatch; + } + + /* + ** Get configuration of the visual. + */ + pGlxScreen = &__glXActiveScreens[screenNum]; + pGlxVisual = pGlxScreen->pGlxVisual; + for (i = 0; i < pGlxScreen->numVisuals; i++, pGlxVisual++) { + if (pGlxVisual->vid == visual) { + break; + } + } + if (i == pGlxScreen->numVisuals) { + /* + ** Visual not support on this screen by this OpenGL implementation. + */ + client->errorValue = visual; + return BadValue; + } + + + /* find the FBConfig for that visual (if any) */ + if ( pFBConfig == NULL ) { + pFBConfig = glxLookupFBConfigByVID( visual ); + + if ( pFBConfig == NULL ) { + /* + * visual does not have an FBConfig ??? + client->errorValue = visual; + return BadValue; + */ + } + } + } + else { + pVisual = NULL; + pGlxVisual = NULL; + } + + pGlxPixmap = (__GLXpixmap *) __glXMalloc(sizeof(__GLXpixmap)); + if (!pGlxPixmap) { + return BadAlloc; + } + pGlxPixmap->be_xids = (XID *) __glXMalloc(sizeof(XID) * screenInfo.numScreens); + if (!pGlxPixmap->be_xids) { + __glXFree( pGlxPixmap ); + return BadAlloc; + } + + pGlxPixmap->pDraw = pDraw; + pGlxPixmap->pGlxScreen = pGlxScreen; + pGlxPixmap->pGlxVisual = pGlxVisual; + pGlxPixmap->pFBConfig = pFBConfig; + pGlxPixmap->pScreen = pScreen; + pGlxPixmap->idExists = True; + pGlxPixmap->refcnt = 0; + + /* + ** Bump the ref count on the X pixmap so it won't disappear. + */ + ((PixmapPtr) pDraw)->refcnt++; + + /* + * send the request to the back-end server(s) + */ + from_screen = to_screen = screenNum; +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + + pXinDraw = (PanoramiXRes *) + SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); + } +#endif + + for (s=from_screen; s<=to_screen; s++) { + + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + Pixmap be_pixmap; + DrawablePtr pRealDraw = pDraw; + +#ifdef PANORAMIX + if (pXinDraw) { + dixLookupDrawable(&pRealDraw, pXinDraw->info[s].id, client, 0, + DixAddAccess); + } +#endif + + be_pixmap = (DMX_GET_PIXMAP_PRIV((PixmapPtr)pRealDraw))->pixmap; + + /* make sure pixmap already created on back-end */ + dmxSync( dmxScreen, 1 ); + + if ( pFBConfig && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + __GLXFBConfig *be_FBConfig = glxLookupBackEndFBConfig( pFBConfig->id, s ); + + LockDisplay(dpy); + pGlxPixmap->be_xids[s] = XAllocID(dpy); + GetReq(GLXCreatePixmap,be_new_req); + be_new_req->reqType = dmxScreen->glxMajorOpcode; + be_new_req->glxCode = X_GLXCreatePixmap; + be_new_req->screen = DefaultScreen(dpy); + be_new_req->fbconfig = be_FBConfig->id; + be_new_req->pixmap = (unsigned int)be_pixmap; + be_new_req->glxpixmap = (unsigned int)pGlxPixmap->be_xids[s]; + be_new_req->numAttribs = 0; + UnlockDisplay(dpy); + SyncHandle(); + } + else if (pFBConfig && glxIsExtensionSupported("GLX_SGIX_fbconfig")) { + __GLXFBConfig *be_FBConfig = glxLookupBackEndFBConfig( pFBConfig->id, s ); + xGLXCreateGLXPixmapWithConfigSGIXReq *ext_req; + xGLXVendorPrivateReq *vpreq; + + LockDisplay(dpy); + pGlxPixmap->be_xids[s] = XAllocID(dpy); + GetReqExtra(GLXVendorPrivate, + sz_xGLXCreateGLXPixmapWithConfigSGIXReq-sz_xGLXVendorPrivateReq, + vpreq); + ext_req = (xGLXCreateGLXPixmapWithConfigSGIXReq *)vpreq; + ext_req->reqType = dmxScreen->glxMajorOpcode; + ext_req->glxCode = X_GLXVendorPrivate; + ext_req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; + ext_req->screen = DefaultScreen(dpy); + ext_req->fbconfig = be_FBConfig->id; + ext_req->pixmap = (unsigned int)be_pixmap; + ext_req->glxpixmap = (unsigned int)pGlxPixmap->be_xids[s]; + UnlockDisplay(dpy); + SyncHandle(); + } + else if (pGlxVisual) { + LockDisplay(dpy); + pGlxPixmap->be_xids[s] = XAllocID(dpy); + GetReq(GLXCreateGLXPixmap,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXCreateGLXPixmap; + be_req->screen = DefaultScreen(dpy); + be_req->visual = (unsigned int)glxMatchGLXVisualInConfigList( + pGlxVisual, + dmxScreen->glxVisuals, + dmxScreen->numGlxVisuals ); + be_req->pixmap = (unsigned int)be_pixmap; + be_req->glxpixmap = (unsigned int)pGlxPixmap->be_xids[s]; + UnlockDisplay(dpy); + SyncHandle(); + } + else { + client->errorValue = ( visual ? visual : fbconfigId ); + __glXFree( pGlxPixmap ); + return BadValue; + } + + XFlush( dpy ); + } + + if (!(AddResource(glxpixmapId, __glXPixmapRes, pGlxPixmap))) { + __glXFree( pGlxPixmap ); + return BadAlloc; + } + + return Success; +} + +int __glXCreateGLXPixmap(__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc; + + return( CreateGLXPixmap(cl, req->visual, None, + req->screen, req->pixmap, req->glxpixmap) ); +} + +int __glXCreatePixmap(__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; + + return( CreateGLXPixmap(cl, None, req->fbconfig, + req->screen, req->pixmap, req->glxpixmap) ); +} + +int __glXDestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc; + XID glxpixmap = req->glxpixmap; + __GLXpixmap *pGlxPixmap; + int s; + int from_screen, to_screen; + + /* + ** Check if it's a valid GLX pixmap. + */ + pGlxPixmap = (__GLXpixmap *)LookupIDByType(glxpixmap, __glXPixmapRes); + if (!pGlxPixmap) { + client->errorValue = glxpixmap; + return __glXBadPixmap; + } + FreeResource(glxpixmap, FALSE); + + /* + * destroy the pixmap on the back-end server(s). + */ + from_screen = to_screen = pGlxPixmap->pDraw->pScreen->myNum; +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + /* make sure pixmap exist in back-end */ + dmxSync( dmxScreen, 1 ); + + LockDisplay(dpy); + GetReq(GLXDestroyGLXPixmap,req); + req->reqType = dmxScreen->glxMajorOpcode; + req->glxCode = X_GLXDestroyGLXPixmap; + req->glxpixmap = (unsigned int)pGlxPixmap->be_xids[s]; + UnlockDisplay(dpy); + SyncHandle(); + } + + + return Success; +} + +/*****************************************************************************/ + +/* +** NOTE: There is no portable implementation for swap buffers as of +** this time that is of value. Consequently, this code must be +** implemented by somebody other than SGI. +*/ +int __glXDoSwapBuffers(__GLXclientState *cl, XID drawId, GLXContextTag tag) +{ + ClientPtr client = cl->client; + DrawablePtr pDraw; + xGLXSwapBuffersReq *be_req; + WindowPtr pWin = NULL; + __GLXpixmap *pGlxPixmap = NULL; + __GLXcontext *glxc = NULL; +#ifdef PANORAMIX + PanoramiXRes *pXinDraw = NULL; +#endif + __glXWindow *pGlxWindow = NULL; + int from_screen = 0; + int to_screen = 0; + int s, rc; + + /* + ** Check that the GLX drawable is valid. + */ + rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixWriteAccess); + if (rc == Success) { + from_screen = to_screen = pDraw->pScreen->myNum; + + if (pDraw->type == DRAWABLE_WINDOW) { + /* + ** Drawable is an X window. + */ + pWin = (WindowPtr)pDraw; + } else { + /* + ** Drawable is an X pixmap, which is not allowed. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + if (!pDraw) { + pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, + __glXPixmapRes); + if (pGlxPixmap) { + /* + ** Drawable is a GLX pixmap. + */ + pDraw = pGlxPixmap->pDraw; + from_screen = to_screen = pGlxPixmap->pScreen->myNum; + } + } + + if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); + if (pGlxWindow) { + /* + ** Drawable is a GLXWindow. + */ + pDraw = pGlxWindow->pDraw; + from_screen = to_screen = pGlxWindow->pScreen->myNum; + } + } + + if (!pDraw) { + /* + ** Drawable is neither a X window nor a GLX pixmap. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + + if (tag) { + glxc = __glXLookupContextByTag(cl, tag); + if (!glxc) { + return __glXBadContextTag; + } + } + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + pXinDraw = (PanoramiXRes *) + SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); + } +#endif + + /* If requested, send a glFinish to all back-end servers before swapping. */ + if (dmxGLXFinishSwap) { + for (s=from_screen; s<=to_screen; s++) { + Display *dpy = GetBackEndDisplay(cl,s); + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + xGLXSingleReq *finishReq; + xGLXSingleReply reply; + +#define X_GLXSingle 0 /* needed by GetReq below */ + + LockDisplay(dpy); + GetReq(GLXSingle,finishReq); + finishReq->reqType = dmxScreen->glxMajorOpcode; + finishReq->glxCode = X_GLsop_Finish; + finishReq->contextTag = (tag ? GetCurrentBackEndTag(cl,tag,s) : 0); + (void) _XReply(dpy, (xReply*) &reply, 0, False); + UnlockDisplay(dpy); + SyncHandle(); + } + } + + /* If requested, send an XSync to all back-end servers before swapping. */ + if (dmxGLXSyncSwap) { + for (s=from_screen; s<=to_screen; s++) + XSync(GetBackEndDisplay(cl,s), False); + } + + + /* send the SwapBuffers request to all back-end servers */ + + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + unsigned int be_draw = 0; + + if (pGlxPixmap) { + be_draw = (unsigned int)pGlxPixmap->be_xids[s]; + } +#ifdef PANORAMIX + else if (pXinDraw) { + dixLookupWindow(&pWin, pXinDraw->info[s].id, client, DixReadAccess); + } +#endif + else if (pGlxWindow) { + pWin = (WindowPtr)pGlxWindow->pDraw; + } + + if (pWin && !be_draw) { + be_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; + if (!be_draw) { + /* it might be that the window did not created yet on the */ + /* back-end server (lazy window creation option), force */ + /* creation of the window */ + dmxCreateAndRealizeWindow( pWin, TRUE ); + be_draw = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; + } + } + + dmxSync( dmxScreen, 1 ); + + LockDisplay(dpy); + GetReq(GLXSwapBuffers,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXSwapBuffers; + be_req->drawable = be_draw; + be_req->contextTag = ( tag ? GetCurrentBackEndTag(cl,tag,s) : 0 ); + UnlockDisplay(dpy); + SyncHandle(); + XFlush(dpy); + } + + return Success; +} + +int __glXSwapBuffers(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + DrawablePtr pDraw; + xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc; + GLXContextTag tag = req->contextTag; + XID drawId = req->drawable; + __GLXpixmap *pGlxPixmap = NULL; + __GLXcontext *glxc = NULL; + __glXWindow *pGlxWindow = NULL; + int rc; + + /* + ** Check that the GLX drawable is valid. + */ + rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixWriteAccess); + if (rc == Success) { + if (pDraw->type != DRAWABLE_WINDOW) { + /* + ** Drawable is an X pixmap, which is not allowed. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + if (!pDraw) { + pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, + __glXPixmapRes); + if (pGlxPixmap) { + /* + ** Drawable is a GLX pixmap. + */ + pDraw = pGlxPixmap->pDraw; + } + } + + if (!pDraw && __GLX_IS_VERSION_SUPPORTED(1,3) ) { + pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); + if (pGlxWindow) { + /* + ** Drawable is a GLXWindow. + */ + pDraw = pGlxWindow->pDraw; + } + } + + if (!pDraw) { + /* + ** Drawable is neither a X window nor a GLX pixmap. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + + if (tag) { + glxc = __glXLookupContextByTag(cl, tag); + if (!glxc) { + return __glXBadContextTag; + } + } + + if (pDraw && + pDraw->type == DRAWABLE_WINDOW && + DMX_GET_WINDOW_PRIV((WindowPtr)pDraw)->swapGroup) { + return SGSwapBuffers(cl, drawId, tag, pDraw); + } + + return __glXDoSwapBuffers(cl, drawId, tag); +} + + +/************************************************************************/ + +/* +** Render and Renderlarge are not in the GLX API. They are used by the GLX +** client library to send batches of GL rendering commands. +*/ + +/* +** Execute all the drawing commands in a request. +*/ +int __glXRender(__GLXclientState *cl, GLbyte *pc) +{ + xGLXRenderReq *req; + xGLXRenderReq *be_req; + int size; + __GLXcontext *glxc; + int from_screen = 0; + int to_screen = 0; + int s; + + /* + ** NOTE: much of this code also appears in the byteswapping version of this + ** routine, __glXSwapRender(). Any changes made here should also be + ** duplicated there. + */ + + req = (xGLXRenderReq *) pc; + + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return 0; + } + from_screen = to_screen = glxc->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + pc += sz_xGLXRenderReq; + size = (req->length << 2) - sz_xGLXRenderReq; + + /* + * just forward the request to back-end server(s) + */ + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReq(GLXRender,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXRender; + be_req->length = req->length; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); + _XSend(dpy, (const char *)pc, size); + UnlockDisplay(dpy); + SyncHandle(); + } + + return Success; +} + +/* +** Execute a large rendering request (one that spans multiple X requests). +*/ +int __glXRenderLarge(__GLXclientState *cl, GLbyte *pc) +{ + xGLXRenderLargeReq *req; + xGLXRenderLargeReq *be_req; + __GLXcontext *glxc; + int from_screen = 0; + int to_screen = 0; + int s; + + /* + ** NOTE: much of this code also appears in the byteswapping version of this + ** routine, __glXSwapRenderLarge(). Any changes made here should also be + ** duplicated there. + */ + + req = (xGLXRenderLargeReq *) pc; + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return 0; + } + from_screen = to_screen = glxc->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + pc += sz_xGLXRenderLargeReq; + + /* + * just forward the request to back-end server(s) + */ + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + GetReq(GLXRenderLarge,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXRenderLarge; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); + be_req->length = req->length; + be_req->requestNumber = req->requestNumber; + be_req->requestTotal = req->requestTotal; + be_req->dataBytes = req->dataBytes; + Data(dpy, (const char *)pc, req->dataBytes); + UnlockDisplay(dpy); + SyncHandle(); + + } + + return Success; +} + + +/************************************************************************/ + +int __glXVendorPrivate(__GLXclientState *cl, GLbyte *pc) +{ + xGLXVendorPrivateReq *req; + + req = (xGLXVendorPrivateReq *) pc; + + switch( req->vendorCode ) { + + case X_GLvop_DeleteTexturesEXT: + return __glXVForwardSingleReq( cl, pc ); + break; + + case X_GLXvop_SwapIntervalSGI: + if (glxIsExtensionSupported("SGI_swap_control")) { + return __glXVForwardSingleReq( cl, pc ); + } + else { + return Success; + } + break; + +#if 0 /* glx 1.3 */ + case X_GLXvop_CreateGLXVideoSourceSGIX: + break; + case X_GLXvop_DestroyGLXVideoSourceSGIX: + break; + case X_GLXvop_CreateGLXPixmapWithConfigSGIX: + break; + case X_GLXvop_DestroyGLXPbufferSGIX: + break; + case X_GLXvop_ChangeDrawableAttributesSGIX: + break; +#endif + + case X_GLXvop_BindSwapBarrierSGIX: + return __glXBindSwapBarrierSGIX( cl, pc ); + break; + + case X_GLXvop_JoinSwapGroupSGIX: + return __glXJoinSwapGroupSGIX( cl, pc ); + break; + + case X_GLXvop_CreateContextWithConfigSGIX: + return __glXCreateContextWithConfigSGIX( cl, pc ); + break; + + default: + /* + ** unsupported private request + */ + cl->client->errorValue = req->vendorCode; + return __glXUnsupportedPrivateRequest; + } + + cl->client->errorValue = req->vendorCode; + return __glXUnsupportedPrivateRequest; + +} + +int __glXVendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc) +{ + xGLXVendorPrivateWithReplyReq *req; + + req = (xGLXVendorPrivateWithReplyReq *) pc; + + switch( req->vendorCode ) { + + case X_GLvop_GetConvolutionFilterEXT: + case X_GLvop_GetConvolutionParameterfvEXT: + case X_GLvop_GetConvolutionParameterivEXT: + case X_GLvop_GetSeparableFilterEXT: + case X_GLvop_GetHistogramEXT: + case X_GLvop_GetHistogramParameterivEXT: + case X_GLvop_GetMinmaxEXT: + case X_GLvop_GetMinmaxParameterfvEXT: + case X_GLvop_GetMinmaxParameterivEXT: + case X_GLvop_AreTexturesResidentEXT: + case X_GLvop_IsTextureEXT: + return( __glXVForwardPipe0WithReply(cl, pc) ); + break; + + case X_GLvop_GenTexturesEXT: + return( __glXVForwardAllWithReply(cl, pc) ); + break; + + +#if 0 /* glx1.3 */ + case X_GLvop_GetDetailTexFuncSGIS: + case X_GLvop_GetSharpenTexFuncSGIS: + case X_GLvop_GetColorTableSGI: + case X_GLvop_GetColorTableParameterfvSGI: + case X_GLvop_GetColorTableParameterivSGI: + case X_GLvop_GetTexFilterFuncSGIS: + case X_GLvop_GetInstrumentsSGIX: + case X_GLvop_InstrumentsBufferSGIX: + case X_GLvop_PollInstrumentsSGIX: + case X_GLvop_FlushRasterSGIX: + case X_GLXvop_CreateGLXPbufferSGIX: + case X_GLXvop_GetDrawableAttributesSGIX: + case X_GLXvop_QueryHyperpipeNetworkSGIX: + case X_GLXvop_QueryHyperpipeConfigSGIX: + case X_GLXvop_HyperpipeConfigSGIX: + case X_GLXvop_DestroyHyperpipeConfigSGIX: +#endif + case X_GLXvop_QueryMaxSwapBarriersSGIX: + return( __glXQueryMaxSwapBarriersSGIX(cl, pc) ); + break; + + case X_GLXvop_GetFBConfigsSGIX: + return( __glXGetFBConfigsSGIX(cl, pc) ); + break; + + case X_GLXvop_MakeCurrentReadSGI: + return( __glXMakeCurrentReadSGI(cl, pc) ); + break; + + case X_GLXvop_QueryContextInfoEXT: + return( __glXQueryContextInfoEXT(cl,pc) ); + break; + + default: + /* + ** unsupported private request + */ + cl->client->errorValue = req->vendorCode; + return __glXUnsupportedPrivateRequest; + } + +} + +int __glXQueryExtensionsString(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc; + xGLXQueryExtensionsStringReply reply; + GLint screen; + size_t length; + int len, numbytes; + char *be_buf; + +#ifdef FWD_QUERY_REQ + xGLXQueryExtensionsStringReq *be_req; + xGLXQueryExtensionsStringReply be_reply; + DMXScreenInfo *dmxScreen; + Display *dpy; + int slop; +#endif + + screen = req->screen; + + /* + ** Check if screen exists. + */ + if ((screen < 0) || (screen >= screenInfo.numScreens)) { + client->errorValue = screen; + return BadValue; + } + +#ifdef FWD_QUERY_REQ + dmxScreen = &dmxScreens[screen]; + + /* Send the glXQueryServerString request */ + dpy = GetBackEndDisplay(cl,screen); + LockDisplay(dpy); + GetReq(GLXQueryExtensionsString,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXQueryServerString; + be_req->screen = DefaultScreen(dpy); + _XReply(dpy, (xReply*) &be_reply, 0, False); + len = (int)be_reply.length; + numbytes = (int)be_reply.n; + slop = numbytes * __GLX_SIZE_INT8 & 3; + be_buf = (char *)malloc(numbytes); + if (!be_buf) { + /* Throw data on the floor */ + _XEatData(dpy, len); + } else { + _XRead(dpy, (char *)be_buf, numbytes); + if (slop) _XEatData(dpy,4-slop); + } + UnlockDisplay(dpy); + SyncHandle(); + +#else + + be_buf = __glXGetServerString(GLX_EXTENSIONS); + numbytes = strlen(be_buf) + 1; + len = __GLX_PAD(numbytes) >> 2; + +#endif + + length = len; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = len; + reply.n = numbytes; + + if (client->swapped) { + glxSwapQueryExtensionsStringReply(client, &reply, be_buf); + } else { + WriteToClient(client, sz_xGLXQueryExtensionsStringReply,(char *)&reply); + WriteToClient(client, (int)(length << 2), (char *)be_buf); + } + + return Success; +} + +int __glXQueryServerString(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc; + xGLXQueryServerStringReply reply; + int name; + GLint screen; + size_t length; + int len, numbytes; + char *be_buf; +#ifdef FWD_QUERY_REQ + xGLXQueryServerStringReq *be_req; + xGLXQueryServerStringReply be_reply; + DMXScreenInfo *dmxScreen; + Display *dpy; + int slop; +#endif + + name = req->name; + screen = req->screen; + /* + ** Check if screen exists. + */ + if ((screen < 0) || (screen >= screenInfo.numScreens)) { + client->errorValue = screen; + return BadValue; + } + +#ifdef FWD_QUERY_REQ + dmxScreen = &dmxScreens[screen]; + + /* Send the glXQueryServerString request */ + dpy = GetBackEndDisplay(cl,screen); + LockDisplay(dpy); + GetReq(GLXQueryServerString,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXQueryServerString; + be_req->screen = DefaultScreen(dpy); + be_req->name = name; + _XReply(dpy, (xReply*) &be_reply, 0, False); + len = (int)be_reply.length; + numbytes = (int)be_reply.n; + slop = numbytes * __GLX_SIZE_INT8 & 3; + be_buf = (char *)malloc(numbytes); + if (!be_buf) { + /* Throw data on the floor */ + _XEatData(dpy, len); + } else { + _XRead(dpy, (char *)be_buf, numbytes); + if (slop) _XEatData(dpy,4-slop); + } + UnlockDisplay(dpy); + SyncHandle(); + +#else + be_buf = __glXGetServerString(name); + numbytes = strlen(be_buf) + 1; + len = __GLX_PAD(numbytes) >> 2; +#endif + + length = len; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = length; + reply.n = numbytes; + + if (client->swapped) { + glxSwapQueryServerStringReply(client, &reply, be_buf); + } else { + WriteToClient(client, sz_xGLXQueryServerStringReply, (char *)&reply); + WriteToClient(client, (int)(length << 2), be_buf); + } + + return Success; +} + +int __glXClientInfo(__GLXclientState *cl, GLbyte *pc) +{ + xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc; + xGLXClientInfoReq *be_req; + const char *buf; + int from_screen = 0; + int to_screen = 0; + int s; + + cl->GLClientmajorVersion = req->major; + cl->GLClientminorVersion = req->minor; + if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); + buf = (const char *)(req+1); + cl->GLClientextensions = strdup(buf); + + to_screen = screenInfo.numScreens - 1; + + for (s=from_screen; s<=to_screen; s++) + { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReq(GLXClientInfo,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXClientInfo; + be_req->major = req->major; + be_req->minor = req->minor; + be_req->length = req->length; + be_req->numbytes = req->numbytes; + Data(dpy, buf, req->numbytes); + + UnlockDisplay(dpy); + SyncHandle(); + } + + return Success; +} + +int __glXUseXFont(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXUseXFontReq *req; + xGLXUseXFontReq *be_req; + FontPtr pFont; + __GLXcontext *glxc = NULL; + int from_screen = 0; + int to_screen = 0; + int s; + dmxFontPrivPtr pFontPriv; + DMXScreenInfo *dmxScreen; + Display *dpy; + + req = (xGLXUseXFontReq *) pc; + + if (req->contextTag != 0) { + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (glxc) { + from_screen = to_screen = glxc->pScreen->myNum; + } + } + + /* + ** Font can actually be either the ID of a font or the ID of a GC + ** containing a font. + */ + pFont = (FontPtr)LookupIDByType(req->font, RT_FONT); + if (!pFont) { + GC *pGC = (GC *)LookupIDByType(req->font, RT_GC); + if (!pGC) { + client->errorValue = req->font; + return BadFont; + } + pFont = pGC->font; + } + + pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex); + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + + for (s=from_screen; s<=to_screen; s++) { + dmxScreen = &dmxScreens[s]; + dpy = GetBackEndDisplay(cl,s); + + dmxSync( dmxScreen, 1 ); + + LockDisplay(dpy); + GetReq(GLXUseXFont,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXUseXFont; + be_req->contextTag = (glxc ? GetCurrentBackEndTag(cl,req->contextTag,s) : 0); + be_req->font = pFontPriv->font[s]->fid; + be_req->first = req->first; + be_req->count = req->count; + be_req->listBase = req->listBase; + UnlockDisplay(dpy); + SyncHandle(); + + XSync( dpy, False ); + } + + return Success; +} + +/* + * start GLX 1.3 here + */ + +int __glXGetFBConfigs(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc; + xGLXGetFBConfigsReply reply; + __GLXFBConfig *pFBConfig; + CARD32 buf[2 * __GLX_TOTAL_FBCONFIG_PROPS]; + int numAttribs = __GLX_TOTAL_FBCONFIG_PROPS; + unsigned int screen = req->screen; + int numFBConfigs, i, p; + __GLXscreenInfo *pGlxScreen; + + if (screen > screenInfo.numScreens) { + /* The client library must send a valid screen number. */ + client->errorValue = screen; + return BadValue; + } + + pGlxScreen = &__glXActiveScreens[screen]; + numFBConfigs = __glXNumFBConfigs; + + reply.numFBConfigs = numFBConfigs; + reply.numAttribs = numAttribs; + reply.length = (numFBConfigs * 2 * numAttribs * __GLX_SIZE_CARD32) >> 2; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (client->swapped) { + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.numFBConfigs); + __GLX_SWAP_INT(&reply.numAttribs); + } + WriteToClient(client, sz_xGLXGetFBConfigsReply, (char *)&reply); + + for (i=0; i < numFBConfigs; i++) { + int associatedVisualId = 0; + int drawableTypeIndex; + pFBConfig = __glXFBConfigs[ i * (screenInfo.numScreens+1) ]; + + p = 0; + /* core attributes */ + buf[p++] = GLX_FBCONFIG_ID; + buf[p++] = pFBConfig->id; + buf[p++] = GLX_BUFFER_SIZE; + buf[p++] = pFBConfig->indexBits; + buf[p++] = GLX_LEVEL; + buf[p++] = pFBConfig->level; + buf[p++] = GLX_DOUBLEBUFFER; + buf[p++] = pFBConfig->doubleBufferMode; + buf[p++] = GLX_STEREO; + buf[p++] = pFBConfig->stereoMode; + buf[p++] = GLX_AUX_BUFFERS; + buf[p++] = pFBConfig->maxAuxBuffers; + buf[p++] = GLX_RED_SIZE; + buf[p++] = pFBConfig->redBits; + buf[p++] = GLX_GREEN_SIZE; + buf[p++] = pFBConfig->greenBits; + buf[p++] = GLX_BLUE_SIZE; + buf[p++] = pFBConfig->blueBits; + buf[p++] = GLX_ALPHA_SIZE; + buf[p++] = pFBConfig->alphaBits; + buf[p++] = GLX_DEPTH_SIZE; + buf[p++] = pFBConfig->depthBits; + buf[p++] = GLX_STENCIL_SIZE; + buf[p++] = pFBConfig->stencilBits; + buf[p++] = GLX_ACCUM_RED_SIZE; + buf[p++] = pFBConfig->accumRedBits; + buf[p++] = GLX_ACCUM_GREEN_SIZE; + buf[p++] = pFBConfig->accumGreenBits; + buf[p++] = GLX_ACCUM_BLUE_SIZE; + buf[p++] = pFBConfig->accumBlueBits; + buf[p++] = GLX_ACCUM_ALPHA_SIZE; + buf[p++] = pFBConfig->accumAlphaBits; + buf[p++] = GLX_RENDER_TYPE; + buf[p++] = pFBConfig->renderType; + buf[p++] = GLX_DRAWABLE_TYPE; + drawableTypeIndex = p; + buf[p++] = pFBConfig->drawableType; + buf[p++] = GLX_X_VISUAL_TYPE; + buf[p++] = pFBConfig->visualType; + buf[p++] = GLX_CONFIG_CAVEAT; + buf[p++] = pFBConfig->visualCaveat; + buf[p++] = GLX_TRANSPARENT_TYPE; + buf[p++] = pFBConfig->transparentType; + buf[p++] = GLX_TRANSPARENT_RED_VALUE; + buf[p++] = pFBConfig->transparentRed; + buf[p++] = GLX_TRANSPARENT_GREEN_VALUE; + buf[p++] = pFBConfig->transparentGreen; + buf[p++] = GLX_TRANSPARENT_BLUE_VALUE; + buf[p++] = pFBConfig->transparentBlue; + buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE; + buf[p++] = pFBConfig->transparentAlpha; + buf[p++] = GLX_TRANSPARENT_INDEX_VALUE; + buf[p++] = pFBConfig->transparentIndex; + buf[p++] = GLX_MAX_PBUFFER_WIDTH; + buf[p++] = pFBConfig->maxPbufferWidth; + buf[p++] = GLX_MAX_PBUFFER_HEIGHT; + buf[p++] = pFBConfig->maxPbufferHeight; + buf[p++] = GLX_MAX_PBUFFER_PIXELS; + buf[p++] = pFBConfig->maxPbufferPixels; + + /* + * find the visual of the back-end server and match a visual + * on the proxy. + * do only once - if a visual is not yet associated. + */ + if (pFBConfig->associatedVisualId == (unsigned int)-1) { + DMXScreenInfo *dmxScreen = &dmxScreens[screen]; + __GLXFBConfig *be_pFBConfig = __glXFBConfigs[ i * (screenInfo.numScreens+1)+screen+1 ]; + __GLXvisualConfig *pGlxVisual = NULL; + int v; + int found = 0; + for (v=0; v<dmxScreen->numGlxVisuals; v++) { + if (dmxScreen->glxVisuals[v].vid == be_pFBConfig->associatedVisualId) { + pGlxVisual = &dmxScreen->glxVisuals[v]; + break; + } + } + + if (pGlxVisual) { + for (v=0; v<pGlxScreen->numVisuals; v++) { + if (glxVisualsMatch(&pGlxScreen->pGlxVisual[v], pGlxVisual)) { + associatedVisualId = pGlxScreen->pGlxVisual[v].vid; + found = 1; + break; + } + } + } + + if (!found) { + associatedVisualId = 0; + pFBConfig->drawableType &= ~(GLX_WINDOW_BIT); + buf[drawableTypeIndex] = pFBConfig->drawableType; + } +#ifdef PANORAMIX + else if (!noPanoramiXExtension) { + /* convert the associated visualId to the panoramix one */ + pFBConfig->associatedVisualId = + PanoramiXTranslateVisualID(screen, v); + } +#endif + } + else { + associatedVisualId = pFBConfig->associatedVisualId; + } + + buf[p++] = GLX_VISUAL_ID; + buf[p++] = associatedVisualId; + + /* SGIS_multisample attributes */ + buf[p++] = GLX_SAMPLES_SGIS; + buf[p++] = pFBConfig->multiSampleSize; + buf[p++] = GLX_SAMPLE_BUFFERS_SGIS; + buf[p++] = pFBConfig->nMultiSampleBuffers; + + /* SGIX_pbuffer specific attributes */ + buf[p++] = GLX_OPTIMAL_PBUFFER_WIDTH_SGIX; + buf[p++] = pFBConfig->optimalPbufferWidth; + buf[p++] = GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX; + buf[p++] = pFBConfig->optimalPbufferHeight; + + buf[p++] = GLX_VISUAL_SELECT_GROUP_SGIX; + buf[p++] = pFBConfig->visualSelectGroup; + + if (client->swapped) { + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_SWAP_INT_ARRAY((int *)buf, 2*numAttribs); + } + WriteToClient(client, 2*numAttribs * __GLX_SIZE_CARD32, (char *)buf); + } + return Success; +} + +int __glXGetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc) +{ + xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)pc; + xGLXGetFBConfigsReq new_req; + + new_req.reqType = req->reqType; + new_req.glxCode = req->glxCode; + new_req.length = req->length; + new_req.screen = req->screen; + + return( __glXGetFBConfigs( cl, (GLbyte *)&new_req ) ); +} + + +int __glXCreateWindow(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; + int screen = req->screen; + GLXFBConfigID fbconfigId = req->fbconfig; + XID windowId = req->window; + XID glxwindowId = req->glxwindow; + DrawablePtr pDraw; + ScreenPtr pScreen; + __glXWindow *pGlxWindow; + __GLXFBConfig *pGlxFBConfig = NULL; + VisualPtr pVisual; + VisualID visId; + int i, rc; + + /* + ** Check if windowId is valid + */ + rc = dixLookupDrawable(&pDraw, windowId, client, M_DRAWABLE_WINDOW, + DixAddAccess); + if (rc != Success) + return rc; + + /* + ** Check if screen of window matches screen of fbconfig. + */ + pScreen = pDraw->pScreen; + if (screen != pScreen->myNum) { + return BadMatch; + } + + /* + ** Find the FBConfigRec for this fbconfigid. + */ + if (!(pGlxFBConfig = glxLookupFBConfig(fbconfigId))) { + client->errorValue = fbconfigId; + return __glXBadFBConfig; + } + visId = pGlxFBConfig->associatedVisualId; + + /* + ** Check if the fbconfig supports rendering to windows + */ + if( !(pGlxFBConfig->drawableType & GLX_WINDOW_BIT) ) { + return BadMatch; + } + + if (visId != None) { + /* + ** Check if the visual ID is valid for this screen. + */ + pVisual = pScreen->visuals; + for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { + if (pVisual->vid == visId) { + break; + } + } + if (i == pScreen->numVisuals) { + client->errorValue = visId; + return BadValue; + } + + /* + ** Check if color buffer depth of fbconfig matches depth + ** of window. + */ + if (pVisual->nplanes != pDraw->depth) { + return BadMatch; + } + } else + /* + ** The window was created with no visual that corresponds + ** to fbconfig + */ + return BadMatch; + + /* + ** Check if there is already a fbconfig associated with this window + */ + if ( LookupIDByType(glxwindowId, __glXWindowRes) ) { + client->errorValue = glxwindowId; + return BadAlloc; + } + + pGlxWindow = (__glXWindow *) malloc(sizeof(__glXWindow)); + if (!pGlxWindow) { + return BadAlloc; + } + + /* + ** Register this GLX window as a resource + */ + if (!(AddResource(glxwindowId, __glXWindowRes, pGlxWindow))) { + return BadAlloc; + } + + pGlxWindow->pDraw = pDraw; + pGlxWindow->type = GLX_GLXWINDOW_TYPE; + pGlxWindow->idExists = True; + pGlxWindow->refcnt = 0; + pGlxWindow->pGlxFBConfig = pGlxFBConfig; + pGlxWindow->pScreen = pScreen; + + return Success; +} + +int __glXDestroyWindow(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; + XID glxwindow = req->glxwindow; + + /* + ** Check if it's a valid GLX window. + */ + if (!LookupIDByType(glxwindow, __glXWindowRes)) { + client->errorValue = glxwindow; + return __glXBadDrawable; + } + /* + ** The glx window destructor will check whether it's current before + ** freeing anything. + */ + FreeResource(glxwindow, RT_NONE); + + return Success; +} + +int __glXQueryContext(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + __GLXcontext *ctx; + xGLXQueryContextReq *req; + xGLXQueryContextReply reply; + int nProps; + int *sendBuf, *pSendBuf; + int nReplyBytes; + + req = (xGLXQueryContextReq *)pc; + ctx = (__GLXcontext *) LookupIDByType(req->context, __glXContextRes); + if (!ctx) { + client->errorValue = req->context; + return __glXBadContext; + } + + nProps = 3; + + reply.length = nProps << 1; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.n = nProps; + + nReplyBytes = reply.length << 2; + sendBuf = (int *)malloc(nReplyBytes); + pSendBuf = sendBuf; + *pSendBuf++ = GLX_FBCONFIG_ID; + *pSendBuf++ = (int)(ctx->pFBConfig->id); + *pSendBuf++ = GLX_RENDER_TYPE; + *pSendBuf++ = (int)(ctx->pFBConfig->renderType); + *pSendBuf++ = GLX_SCREEN; + *pSendBuf++ = (int)(ctx->pScreen->myNum); + + if (client->swapped) { + __glXSwapQueryContextReply(client, &reply, sendBuf); + } else { + WriteToClient(client, sz_xGLXQueryContextReply, (char *)&reply); + WriteToClient(client, nReplyBytes, (char *)sendBuf); + } + free((char *)sendBuf); + + return Success; +} + +int __glXQueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + __GLXcontext *ctx; + xGLXQueryContextInfoEXTReq *req; + xGLXQueryContextInfoEXTReply reply; + int nProps; + int *sendBuf, *pSendBuf; + int nReplyBytes; + + req = (xGLXQueryContextInfoEXTReq *)pc; + ctx = (__GLXcontext *) SecurityLookupIDByType(client, req->context, __glXContextRes, DixReadAccess); + if (!ctx) { + client->errorValue = req->context; + return __glXBadContext; + } + + nProps = 4; + + reply.length = nProps << 1; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.n = nProps; + + nReplyBytes = reply.length << 2; + sendBuf = (int *)malloc(nReplyBytes); + pSendBuf = sendBuf; + *pSendBuf++ = GLX_SHARE_CONTEXT_EXT; + *pSendBuf++ = (int)(ctx->share_id); + *pSendBuf++ = GLX_VISUAL_ID_EXT; + *pSendBuf++ = (int)(ctx->pVisual ? ctx->pVisual->vid : 0); + *pSendBuf++ = GLX_SCREEN_EXT; + *pSendBuf++ = (int)(ctx->pScreen->myNum); + *pSendBuf++ = GLX_FBCONFIG_ID; + *pSendBuf++ = (int)(ctx->pFBConfig ? ctx->pFBConfig->id : 0); + + if (client->swapped) { + __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf); + } else { + WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, (char *)&reply); + WriteToClient(client, nReplyBytes, (char *)sendBuf); + } + free((char *)sendBuf); + + return Success; +} + +int __glXCreatePbuffer(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *)pc; + xGLXCreatePbufferReq *be_req; + int screen = req->screen; + GLXFBConfigID fbconfigId = req->fbconfig; + GLXPbuffer pbuffer = req->pbuffer; + __glXPbuffer *pGlxPbuffer; + int numAttribs = req->numAttribs; + int *attr; + ScreenPtr pScreen; + __GLXFBConfig *pGlxFBConfig; + __GLXFBConfig *be_pGlxFBConfig; + XID be_xid; + Display *dpy; + DMXScreenInfo *dmxScreen; + int s; + int from_screen, to_screen; + + /* + ** Look up screen and FBConfig. + */ + if (screen > screenInfo.numScreens) { + /* The client library must send a valid screen number. */ + client->errorValue = screen; + return BadValue; + } + pScreen = screenInfo.screens[screen]; + + /* + ** Find the FBConfigRec for this fbconfigid. + */ + if (!(pGlxFBConfig = glxLookupFBConfig(fbconfigId))) { + client->errorValue = fbconfigId; + return __glXBadFBConfig; + } + + /* + ** Create the GLX part of the Pbuffer. + */ + pGlxPbuffer = (__glXPbuffer *) malloc(sizeof(__glXPbuffer)); + if (!pGlxPbuffer) { + return BadAlloc; + } + + pGlxPbuffer->be_xids = (XID *) malloc( sizeof(XID) * screenInfo.numScreens ); + if (!pGlxPbuffer->be_xids) { + free(pGlxPbuffer); + return BadAlloc; + } + + /* + * Allocate an XID on the back-end server(s) and send him the request + */ + from_screen = to_screen = screen; +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + for (s=from_screen; s<=to_screen; s++) { + dpy = GetBackEndDisplay(cl,s); + be_xid = XAllocID(dpy); + dmxScreen = &dmxScreens[s]; + be_pGlxFBConfig = glxLookupBackEndFBConfig( pGlxFBConfig->id, s ); + + attr = (int *)( req+1 ); + + LockDisplay(dpy); + GetReqExtra(GLXCreatePbuffer, 2 * numAttribs * __GLX_SIZE_CARD32, be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXCreatePbuffer; + be_req->screen = be_pGlxFBConfig->screen; + be_req->fbconfig = be_pGlxFBConfig->id; + be_req->pbuffer = be_xid; + be_req->numAttribs = numAttribs; + + /* Send attributes */ + if ( attr != NULL ) { + CARD32 *pc = (CARD32 *)(be_req + 1); + + while (numAttribs-- > 0) { + *pc++ = *attr++; /* token */ + *pc++ = *attr++; /* value */ + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + pGlxPbuffer->be_xids[s] = be_xid; + } + + + pGlxPbuffer->idExists = True; + pGlxPbuffer->refcnt = 0; + pGlxPbuffer->pFBConfig = pGlxFBConfig; + pGlxPbuffer->pScreen = pScreen; + + /* + ** Register the resource. + */ + if (!(AddResource(pbuffer, __glXPbufferRes, pGlxPbuffer))) { + return BadAlloc; + } + + return Success; + +} + +int __glXDestroyPbuffer(__GLXclientState *cl, GLbyte *pc) +{ + ClientPtr client = cl->client; + xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc; + xGLXDestroyPbufferReq *be_req; + GLXPbuffer pbuffer = req->pbuffer; + Display *dpy; + int screen; + DMXScreenInfo *dmxScreen; + __glXPbuffer *pGlxPbuffer; + int s; + int from_screen, to_screen; + + /* + ** Check if it's a valid Pbuffer + */ + pGlxPbuffer = (__glXPbuffer *)LookupIDByType(pbuffer, __glXPbufferRes); + if (!pGlxPbuffer) { + client->errorValue = pbuffer; + return __glXBadPbuffer; + } + + screen = pGlxPbuffer->pScreen->myNum; + + from_screen = to_screen = screen; +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + for (s=from_screen; s<=to_screen; s++) { + dpy = GetBackEndDisplay(cl,s); + dmxScreen = &dmxScreens[s]; + + /* send the destroy request to the back-end server */ + LockDisplay(dpy); + GetReq(GLXDestroyPbuffer, be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXDestroyPbuffer; + be_req->pbuffer = pGlxPbuffer->be_xids[s]; + UnlockDisplay(dpy); + SyncHandle(); + } + + FreeResource(pbuffer, RT_NONE); + + return Success; +} + +int __glXGetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) +{ + xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc; + xGLXGetDrawableAttributesReq *be_req; + xGLXGetDrawableAttributesReply reply; + ClientPtr client = cl->client; + GLXDrawable drawId = req->drawable; + GLXDrawable be_drawable = 0; + DrawablePtr pDraw = NULL; + Display *dpy; + int screen, rc; + DMXScreenInfo *dmxScreen; + CARD32 *attribs = NULL; + int attribs_size; +#ifdef PANORAMIX + PanoramiXRes *pXinDraw = NULL; +#endif + + if (drawId != None) { + rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess); + if (rc == Success) { + if (pDraw->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDraw; + be_drawable = 0; + screen = pWin->drawable.pScreen->myNum; + + } + else { + /* + ** Drawable is not a Window , GLXWindow or a GLXPixmap. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + if (!pDraw) { + __GLXpixmap *pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, + __glXPixmapRes); + if (pGlxPixmap) { + pDraw = pGlxPixmap->pDraw; + screen = pGlxPixmap->pScreen->myNum; + be_drawable = pGlxPixmap->be_xids[screen]; + } + } + + if (!pDraw) { + __glXWindow *pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); + if (pGlxWindow) { + pDraw = pGlxWindow->pDraw; + screen = pGlxWindow->pScreen->myNum; + be_drawable = 0; + } + } + + if (!pDraw) { + __glXPbuffer *pGlxPbuffer = (__glXPbuffer *)LookupIDByType(drawId, __glXPbufferRes); + if (pGlxPbuffer) { + pDraw = (DrawablePtr)pGlxPbuffer; + screen = pGlxPbuffer->pScreen->myNum; + be_drawable = pGlxPbuffer->be_xids[screen]; + } + } + + + if (!pDraw) { + /* + ** Drawable is not a Window , GLXWindow or a GLXPixmap. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + + /* if the drawable is a window or GLXWindow - + * we need to find the base id on the back-end server + */ + if (!be_drawable) { + WindowPtr pWin = (WindowPtr)pDraw; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + pXinDraw = (PanoramiXRes *) + SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); + if (!pXinDraw) { + client->errorValue = drawId; + return __glXBadDrawable; + } + + dixLookupWindow(&pWin, pXinDraw->info[screen].id, client, + DixReadAccess); + } +#endif + + if (pWin) { + be_drawable = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; + if (!be_drawable) { + /* it might be that the window did not created yet on the */ + /* back-end server (lazy window creation option), force */ + /* creation of the window */ + dmxCreateAndRealizeWindow( pWin, TRUE ); + be_drawable = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; + } + } + else { + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + + /* send the request to the back-end server */ + dpy = GetBackEndDisplay(cl,screen); + dmxScreen = &dmxScreens[screen]; + + /* make sure drawable exists on back-end */ + dmxSync( dmxScreen, 1 ); + + LockDisplay(dpy); + GetReq(GLXGetDrawableAttributes, be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXGetDrawableAttributes; + be_req->drawable = be_drawable; + be_req->length = req->length; + if (!_XReply(dpy, (xReply *) &reply, 0, False)) { + UnlockDisplay(dpy); + SyncHandle(); + return( BE_TO_CLIENT_ERROR(dmxLastErrorEvent.error_code) ); + } + + if (reply.numAttribs) { + attribs_size = 2 * reply.numAttribs * __GLX_SIZE_CARD32; + attribs = (CARD32 *) malloc(attribs_size); + if (attribs == NULL) { + UnlockDisplay(dpy); + SyncHandle(); + return BadAlloc; + } + + _XRead(dpy, (char *) attribs, attribs_size); + } + + UnlockDisplay(dpy); + SyncHandle(); + + + /* send the reply back to the client */ + reply.sequenceNumber = client->sequence; + if (client->swapped) { + __glXSwapGetDrawableAttributesReply(client, &reply, (int *)attribs); + } + else { + WriteToClient(client, sz_xGLXGetDrawableAttributesReply, (char *)&reply); + WriteToClient(client, attribs_size, (char *)attribs); + } + + Xfree(attribs); + + return Success; +} + +int __glXChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc) +{ + xGLXChangeDrawableAttributesReq *req = (xGLXChangeDrawableAttributesReq *)pc; + xGLXChangeDrawableAttributesReq *be_req; + ClientPtr client = cl->client; + GLXDrawable drawId = req->drawable; + GLXDrawable be_drawable = 0; + DrawablePtr pDraw = NULL; + Display *dpy; + int screen, rc; + DMXScreenInfo *dmxScreen; + char *attrbuf; +#ifdef PANORAMIX + PanoramiXRes *pXinDraw = NULL; + PanoramiXRes *pXinReadDraw = NULL; +#endif + + if (drawId != None) { + rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixSetAttrAccess); + if (rc == Success) { + if (pDraw->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDraw; + be_drawable = 0; + screen = pWin->drawable.pScreen->myNum; + + } + else { + /* + ** Drawable is not a Window , GLXWindow or a GLXPixmap. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + if (!pDraw) { + __GLXpixmap *pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, + __glXPixmapRes); + if (pGlxPixmap) { + pDraw = pGlxPixmap->pDraw; + screen = pGlxPixmap->pScreen->myNum; + be_drawable = pGlxPixmap->be_xids[screen]; + } + } + + if (!pDraw) { + __glXWindow *pGlxWindow = (__glXWindow *) LookupIDByType(drawId, __glXWindowRes); + if (pGlxWindow) { + pDraw = pGlxWindow->pDraw; + screen = pGlxWindow->pScreen->myNum; + be_drawable = 0; + } + } + + if (!pDraw) { + __glXPbuffer *pGlxPbuffer = (__glXPbuffer *)LookupIDByType(drawId, __glXPbufferRes); + if (pGlxPbuffer) { + pDraw = (DrawablePtr)pGlxPbuffer; + screen = pGlxPbuffer->pScreen->myNum; + be_drawable = pGlxPbuffer->be_xids[screen]; + } + } + + + if (!pDraw) { + /* + ** Drawable is not a Window , GLXWindow or a GLXPixmap. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + + /* if the drawable is a window or GLXWindow - + * we need to find the base id on the back-end server + */ + if (!be_drawable) { + WindowPtr pWin = (WindowPtr)pDraw; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + pXinDraw = (PanoramiXRes *) + SecurityLookupIDByClass(client, pDraw->id, XRC_DRAWABLE, DixReadAccess); + if (!pXinDraw) { + client->errorValue = drawId; + return __glXBadDrawable; + } + + dixLookupWindow(&pWin, pXinDraw->info[screen].id, client, + DixReadAccess); + } +#endif + + if (pWin) { + be_drawable = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; + if (!be_drawable) { + /* it might be that the window did not created yet on the */ + /* back-end server (lazy window creation option), force */ + /* creation of the window */ + dmxCreateAndRealizeWindow( pWin, TRUE ); + be_drawable = (unsigned int)(DMX_GET_WINDOW_PRIV(pWin))->window; + } + } + else { + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + + /* send the request to the back-end server */ + dpy = GetBackEndDisplay(cl,screen); + dmxScreen = &dmxScreens[screen]; + + /* make sure drawable exists on back-end */ + dmxSync( dmxScreen, 1 ); + + LockDisplay(dpy); + GetReqExtra(GLXChangeDrawableAttributes, + 2 * req->numAttribs * __GLX_SIZE_CARD32, be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLXChangeDrawableAttributes; + be_req->drawable = be_drawable; + be_req->numAttribs = req->numAttribs; + be_req->length = req->length; + + UnlockDisplay(dpy); + SyncHandle(); + + return Success; +} + +int __glXSendLargeCommand(__GLXclientState *cl, GLXContextTag contextTag) +{ + ClientPtr client = cl->client; + xGLXRenderLargeReq *req; + GLint maxSize, amount; + GLint totalRequests, requestNumber; + GLint dataLen; + GLbyte *data; + __GLXcontext *glxc; + int s; + int from_screen, to_screen; + + maxSize = cl->largeCmdMaxReqDataSize - (GLint)sizeof(xGLXRenderLargeReq); + dataLen = cl->largeCmdBytesTotal; + totalRequests = (dataLen / maxSize); + if (dataLen % maxSize) totalRequests++; + + glxc = __glXLookupContextByTag(cl, contextTag); + if (!glxc) { + client->errorValue = contextTag; + return __glXBadContext; + } + from_screen = to_screen = glxc->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + /* + ** Send enough requests until the whole array is sent. + */ + requestNumber = 1; + data = cl->largeCmdBuf; + while (dataLen > 0) { + amount = dataLen; + if (amount > maxSize) { + amount = maxSize; + } + + for (s=from_screen; s<=to_screen; s++) { + + Display *dpy = GetBackEndDisplay(cl,s); + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + + LockDisplay(dpy); + GetReq(GLXRenderLarge,req); + req->reqType = dmxScreen->glxMajorOpcode; + req->glxCode = X_GLXRenderLarge; + req->contextTag = GetCurrentBackEndTag(cl,contextTag,s); + req->length += (amount + 3) >> 2; + req->requestNumber = requestNumber++; + req->requestTotal = totalRequests; + req->dataBytes = amount; + Data(dpy, ((const char*)data), amount); + dataLen -= amount; + data = ((GLbyte *) data) + amount; + UnlockDisplay(dpy); + SyncHandle(); + } + } + + return Success; +} diff --git a/xorg-server/hw/dmx/glxProxy/glxext.c b/xorg-server/hw/dmx/glxProxy/glxext.c index 6cd8bb41a..6589e43bb 100644 --- a/xorg-server/hw/dmx/glxProxy/glxext.c +++ b/xorg-server/hw/dmx/glxProxy/glxext.c @@ -1,532 +1,532 @@ -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "dmx.h" - -#include "glxserver.h" -#include <windowstr.h> -#include <propertyst.h> -#include <os.h> -#include "g_disptab.h" -#include "glxutil.h" -#include "glxext.h" -#include "glxvisuals.h" -#include "micmap.h" -#include "glxswap.h" - -/* -** Stubs to satisfy miinitext.c references. -*/ -typedef int __GLXprovider; -__GLXprovider __glXDRISWRastProvider; -void GlxPushProvider(__GLXprovider *provider) { } - -/* -** Forward declarations. -*/ -static int __glXSwapDispatch(ClientPtr); -static int __glXDispatch(ClientPtr); - -/* -** Called when the extension is reset. -*/ -static void ResetExtension(ExtensionEntry* extEntry) -{ - __glXFlushContextCache(); - __glXScreenReset(); - SwapBarrierReset(); -} - -/* -** Initialize the per-client context storage. -*/ -static void ResetClientState(int clientIndex) -{ - __GLXclientState *cl = __glXClients[clientIndex]; - Display **keep_be_displays; - int i; - - if (cl->returnBuf) __glXFree(cl->returnBuf); - if (cl->currentContexts) __glXFree(cl->currentContexts); - if (cl->currentDrawables) __glXFree(cl->currentDrawables); - if (cl->largeCmdBuf) __glXFree(cl->largeCmdBuf); - - for (i=0; i< screenInfo.numScreens; i++) { - if (cl->be_displays[i]) - XCloseDisplay( cl->be_displays[i] ); - } - - keep_be_displays = cl->be_displays; - memset(cl, 0, sizeof(__GLXclientState)); - cl->be_displays = keep_be_displays; - - /* - ** By default, assume that the client supports - ** GLX major version 1 minor version 0 protocol. - */ - cl->GLClientmajorVersion = 1; - cl->GLClientminorVersion = 0; - if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); - - memset(cl->be_displays, 0, screenInfo.numScreens * sizeof(Display *)); -} - - -/* -** This procedure is called when the client who created the context goes -** away OR when glXDestroyContext is called. In either case, all we do is -** flag that the ID is no longer valid, and (maybe) free the context. -** use. -*/ -static int ContextGone(__GLXcontext* cx, XID id) -{ - cx->idExists = GL_FALSE; - if (!cx->isCurrent) { - __glXFreeContext(cx); - } - - return True; -} - -/* -** Free a client's state. -*/ -static int ClientGone(int clientIndex, XID id) -{ - __GLXcontext *cx; - __GLXclientState *cl = __glXClients[clientIndex]; - int i; - - if (cl) { - /* - ** Free all the contexts that are current for this client. - */ - for (i=0; i < cl->numCurrentContexts; i++) { - cx = cl->currentContexts[i]; - if (cx) { - cx->isCurrent = GL_FALSE; - if (!cx->idExists) { - __glXFreeContext(cx); - } - } - } - /* - ** Re-initialize the client state structure. Don't free it because - ** we'll probably get another client with this index and use the struct - ** again. There is a maximum of MAXCLIENTS of these structures. - */ - ResetClientState(clientIndex); - } - - return True; -} - -/* -** Free a GLX Pixmap. -*/ -void __glXFreeGLXPixmap( __GLXpixmap *pGlxPixmap ) -{ - if (!pGlxPixmap->idExists && - !pGlxPixmap->refcnt) { - - PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; - - /* - ** The DestroyPixmap routine should decrement the refcount and free - ** only if it's zero. - */ - (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); - __glXFree(pGlxPixmap->be_xids); - __glXFree(pGlxPixmap); - } - -} - -static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) -{ - - pGlxPixmap->idExists = False; - __glXFreeGLXPixmap( pGlxPixmap ); - - return True; -} - -void __glXFreeGLXWindow(__glXWindow *pGlxWindow) -{ - if (!pGlxWindow->idExists && !pGlxWindow->refcnt) { - WindowPtr pWindow = (WindowPtr) pGlxWindow->pDraw; - - if (LookupIDByType(pWindow->drawable.id, RT_WINDOW) == pWindow) { - (*pGlxWindow->pScreen->DestroyWindow)(pWindow); - } - - xfree(pGlxWindow); - } -} - -static void WindowGone(__glXWindow *pGlxWindow, XID id) -{ - pGlxWindow->idExists = False; - __glXFreeGLXWindow(pGlxWindow); -} - -void __glXFreeGLXPbuffer(__glXPbuffer *pGlxPbuffer) -{ - if (!pGlxPbuffer->idExists && !pGlxPbuffer->refcnt) { - xfree(pGlxPbuffer->be_xids); - xfree(pGlxPbuffer); - } -} - -static void PbufferGone(__glXPbuffer *pGlxPbuffer, XID id) -{ - pGlxPbuffer->idExists = False; - __glXFreeGLXPbuffer(pGlxPbuffer); -} - -/* -** Free a context. -*/ -GLboolean __glXFreeContext(__GLXcontext *cx) -{ - if (cx->idExists || cx->isCurrent) return GL_FALSE; - - if (cx->feedbackBuf) __glXFree(cx->feedbackBuf); - if (cx->selectBuf) __glXFree(cx->selectBuf); - if (cx->real_ids) __glXFree(cx->real_ids); - if (cx->real_vids) __glXFree(cx->real_vids); - - if (cx->pGlxPixmap) { - /* - ** The previous drawable was a glx pixmap, release it. - */ - cx->pGlxPixmap->refcnt--; - __glXFreeGLXPixmap( cx->pGlxPixmap ); - cx->pGlxPixmap = 0; - } - - if (cx->pGlxReadPixmap) { - /* - ** The previous drawable was a glx pixmap, release it. - */ - cx->pGlxReadPixmap->refcnt--; - __glXFreeGLXPixmap( cx->pGlxReadPixmap ); - cx->pGlxReadPixmap = 0; - } - - if (cx->pGlxWindow) { - /* - ** The previous drawable was a glx window, release it. - */ - cx->pGlxWindow->refcnt--; - __glXFreeGLXWindow( cx->pGlxWindow ); - cx->pGlxWindow = 0; - } - - if (cx->pGlxReadWindow) { - /* - ** The previous drawable was a glx window, release it. - */ - cx->pGlxReadWindow->refcnt--; - __glXFreeGLXWindow( cx->pGlxReadWindow ); - cx->pGlxReadWindow = 0; - } - - __glXFree(cx); - - if (cx == __glXLastContext) { - __glXFlushContextCache(); - } - - return GL_TRUE; -} - -/* -** Initialize the GLX extension. -*/ -void GlxExtensionInit(void) -{ - ExtensionEntry *extEntry; - int i; - int glxSupported = 1; - - /* - // do not initialize GLX extension if GLX is not supported - // by ALL back-end servers. - */ - for (i=0; i<screenInfo.numScreens; i++) { - glxSupported &= (dmxScreens[i].glxMajorOpcode > 0); - } - - if (!glxSupported || !dmxGLXProxy) { - return; - } - - __glXContextRes = CreateNewResourceType((DeleteType)ContextGone, - "GLXContext"); - __glXClientRes = CreateNewResourceType((DeleteType)ClientGone, - "GLXClient"); - __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone, - "GLXPixmap"); - __glXWindowRes = CreateNewResourceType((DeleteType)WindowGone, - "GLXWindow"); - __glXPbufferRes = CreateNewResourceType((DeleteType)PbufferGone, - "GLXPbuffer"); - - if (!__glXContextRes || !__glXClientRes || !__glXPixmapRes || - !__glXWindowRes || !__glXPbufferRes) - return; - - /* - ** Add extension to server extensions. - */ - extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, - __GLX_NUMBER_ERRORS, __glXDispatch, - __glXSwapDispatch, ResetExtension, - StandardMinorOpcode); - if (!extEntry) { - FatalError("__glXExtensionInit: AddExtensions failed\n"); - return; - } - /* - if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { - ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); - return; - } - */ - - __glXerrorBase = extEntry->errorBase; - __glXBadContext = extEntry->errorBase + GLXBadContext; - __glXBadContextState = extEntry->errorBase + GLXBadContextState; - __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; - __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; - __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; - __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; - __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; - __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; - __glXUnsupportedPrivateRequest = extEntry->errorBase + - GLXUnsupportedPrivateRequest; - __glXBadFBConfig = extEntry->errorBase + GLXBadFBConfig; - __glXBadPbuffer = extEntry->errorBase + GLXBadPbuffer; - - /* - ** Initialize table of client state. There is never a client 0. - */ - for (i=1; i <= MAXCLIENTS; i++) { - __glXClients[i] = 0; - } - - /* - ** Initialize screen specific data. - */ - __glXScreenInit(screenInfo.numScreens); - - /* - ** Initialize swap barrier support. - */ - SwapBarrierInit(); -} - -/************************************************************************/ - -Bool __glXCoreType(void) -{ - return 0; -} - -/************************************************************************/ - -void GlxSetVisualConfigs(int nconfigs, - __GLXvisualConfig *configs, void **privates) -{ - glxSetVisualConfigs(nconfigs, configs, privates); -} - -static miInitVisualsProcPtr saveInitVisualsProc; - -Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, - int *nvisualp, int *ndepthp, - int *rootDepthp, VisualID *defaultVisp, - unsigned long sizes, int bitsPerRGB, - int preferredVis) -{ - Bool ret; - - if (saveInitVisualsProc) { - ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, - rootDepthp, defaultVisp, sizes, bitsPerRGB, - preferredVis); - if (!ret) - return False; - } - - glxInitVisuals(nvisualp, visualp, defaultVisp, *ndepthp, *depthp,*rootDepthp); - - return True; -} - -void -GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) -{ - if (dmxGLXProxy) { - saveInitVisualsProc = *initVisProc; - *initVisProc = GlxInitVisuals; - } -} - -/************************************************************************/ - -void __glXFlushContextCache(void) -{ - __glXLastContext = 0; -} - -/************************************************************************/ - -/* -** Top level dispatcher; all commands are executed from here down. -*/ -static int __glXDispatch(ClientPtr client) -{ - REQUEST(xGLXSingleReq); - CARD8 opcode; - int (*proc)(__GLXclientState *cl, GLbyte *pc); - __GLXclientState *cl; - - opcode = stuff->glxCode; - cl = __glXClients[client->index]; - if (!cl) { - cl = __glXCalloc(1, sizeof(__GLXclientState)); - __glXClients[client->index] = cl; - if (!cl) { - return BadAlloc; - } - - cl->be_displays = __glXCalloc(screenInfo.numScreens, sizeof(Display *)); - if (!cl->be_displays) { - __glXFree( cl ); - return BadAlloc; - } - } - - if (!cl->inUse) { - /* - ** This is first request from this client. Associate a resource - ** with the client so we will be notified when the client dies. - */ - XID xid = FakeClientID(client->index); - if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { - return BadAlloc; - } - ResetClientState(client->index); - cl->largeCmdRequestsTotal = 0; - cl->inUse = GL_TRUE; - cl->client = client; - } - - /* - ** Check for valid opcode. - */ - if (opcode >= __GLX_SINGLE_TABLE_SIZE) { - return BadRequest; - } - - /* - ** Use the opcode to index into the procedure table. - */ - proc = __glXSingleTable[opcode]; - return (*proc)(cl, (GLbyte *) stuff); -} - -static int __glXSwapDispatch(ClientPtr client) -{ - REQUEST(xGLXSingleReq); - CARD8 opcode; - int (*proc)(__GLXclientState *cl, GLbyte *pc); - __GLXclientState *cl; - - opcode = stuff->glxCode; - cl = __glXClients[client->index]; - if (!cl) { - cl = __glXCalloc(1, sizeof(__GLXclientState)); - __glXClients[client->index] = cl; - if (!cl) { - return BadAlloc; - } - - cl->be_displays = __glXCalloc(screenInfo.numScreens, sizeof(Display *)); - if (!cl->be_displays) { - __glXFree( cl ); - return BadAlloc; - } - } - - if (!cl->inUse) { - /* - ** This is first request from this client. Associate a resource - ** with the client so we will be notified when the client dies. - */ - XID xid = FakeClientID(client->index); - if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { - return BadAlloc; - } - ResetClientState(client->index); - cl->inUse = GL_TRUE; - cl->client = client; - } - - /* - ** Check for valid opcode. - */ - if (opcode >= __GLX_SINGLE_TABLE_SIZE) { - return BadRequest; - } - - /* - ** Use the opcode to index into the procedure table. - */ - proc = __glXSwapSingleTable[opcode]; - return (*proc)(cl, (GLbyte *) stuff); -} - -int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) -{ - return BadRequest; -} - -void __glXNoSuchRenderOpcode(GLbyte *pc) -{ - return; -} - +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "dmx.h" + +#include "glxserver.h" +#include <windowstr.h> +#include <propertyst.h> +#include <os.h> +#include "g_disptab.h" +#include "glxutil.h" +#include "glxext.h" +#include "glxvisuals.h" +#include "micmap.h" +#include "glxswap.h" + +/* +** Stubs to satisfy miinitext.c references. +*/ +typedef int __GLXprovider; +__GLXprovider __glXDRISWRastProvider; +void GlxPushProvider(__GLXprovider *provider) { } + +/* +** Forward declarations. +*/ +static int __glXSwapDispatch(ClientPtr); +static int __glXDispatch(ClientPtr); + +/* +** Called when the extension is reset. +*/ +static void ResetExtension(ExtensionEntry* extEntry) +{ + __glXFlushContextCache(); + __glXScreenReset(); + SwapBarrierReset(); +} + +/* +** Initialize the per-client context storage. +*/ +static void ResetClientState(int clientIndex) +{ + __GLXclientState *cl = __glXClients[clientIndex]; + Display **keep_be_displays; + int i; + + if (cl->returnBuf) __glXFree(cl->returnBuf); + if (cl->currentContexts) __glXFree(cl->currentContexts); + if (cl->currentDrawables) __glXFree(cl->currentDrawables); + if (cl->largeCmdBuf) __glXFree(cl->largeCmdBuf); + + for (i=0; i< screenInfo.numScreens; i++) { + if (cl->be_displays[i]) + XCloseDisplay( cl->be_displays[i] ); + } + + keep_be_displays = cl->be_displays; + memset(cl, 0, sizeof(__GLXclientState)); + cl->be_displays = keep_be_displays; + + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); + + memset(cl->be_displays, 0, screenInfo.numScreens * sizeof(Display *)); +} + + +/* +** This procedure is called when the client who created the context goes +** away OR when glXDestroyContext is called. In either case, all we do is +** flag that the ID is no longer valid, and (maybe) free the context. +** use. +*/ +static int ContextGone(__GLXcontext* cx, XID id) +{ + cx->idExists = GL_FALSE; + if (!cx->isCurrent) { + __glXFreeContext(cx); + } + + return True; +} + +/* +** Free a client's state. +*/ +static int ClientGone(int clientIndex, XID id) +{ + __GLXcontext *cx; + __GLXclientState *cl = __glXClients[clientIndex]; + int i; + + if (cl) { + /* + ** Free all the contexts that are current for this client. + */ + for (i=0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + cx->isCurrent = GL_FALSE; + if (!cx->idExists) { + __glXFreeContext(cx); + } + } + } + /* + ** Re-initialize the client state structure. Don't free it because + ** we'll probably get another client with this index and use the struct + ** again. There is a maximum of MAXCLIENTS of these structures. + */ + ResetClientState(clientIndex); + } + + return True; +} + +/* +** Free a GLX Pixmap. +*/ +void __glXFreeGLXPixmap( __GLXpixmap *pGlxPixmap ) +{ + if (!pGlxPixmap->idExists && + !pGlxPixmap->refcnt) { + + PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; + + /* + ** The DestroyPixmap routine should decrement the refcount and free + ** only if it's zero. + */ + (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); + __glXFree(pGlxPixmap->be_xids); + __glXFree(pGlxPixmap); + } + +} + +static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) +{ + + pGlxPixmap->idExists = False; + __glXFreeGLXPixmap( pGlxPixmap ); + + return True; +} + +void __glXFreeGLXWindow(__glXWindow *pGlxWindow) +{ + if (!pGlxWindow->idExists && !pGlxWindow->refcnt) { + WindowPtr pWindow = (WindowPtr) pGlxWindow->pDraw; + + if (LookupIDByType(pWindow->drawable.id, RT_WINDOW) == pWindow) { + (*pGlxWindow->pScreen->DestroyWindow)(pWindow); + } + + free(pGlxWindow); + } +} + +static void WindowGone(__glXWindow *pGlxWindow, XID id) +{ + pGlxWindow->idExists = False; + __glXFreeGLXWindow(pGlxWindow); +} + +void __glXFreeGLXPbuffer(__glXPbuffer *pGlxPbuffer) +{ + if (!pGlxPbuffer->idExists && !pGlxPbuffer->refcnt) { + free(pGlxPbuffer->be_xids); + free(pGlxPbuffer); + } +} + +static void PbufferGone(__glXPbuffer *pGlxPbuffer, XID id) +{ + pGlxPbuffer->idExists = False; + __glXFreeGLXPbuffer(pGlxPbuffer); +} + +/* +** Free a context. +*/ +GLboolean __glXFreeContext(__GLXcontext *cx) +{ + if (cx->idExists || cx->isCurrent) return GL_FALSE; + + if (cx->feedbackBuf) __glXFree(cx->feedbackBuf); + if (cx->selectBuf) __glXFree(cx->selectBuf); + if (cx->real_ids) __glXFree(cx->real_ids); + if (cx->real_vids) __glXFree(cx->real_vids); + + if (cx->pGlxPixmap) { + /* + ** The previous drawable was a glx pixmap, release it. + */ + cx->pGlxPixmap->refcnt--; + __glXFreeGLXPixmap( cx->pGlxPixmap ); + cx->pGlxPixmap = 0; + } + + if (cx->pGlxReadPixmap) { + /* + ** The previous drawable was a glx pixmap, release it. + */ + cx->pGlxReadPixmap->refcnt--; + __glXFreeGLXPixmap( cx->pGlxReadPixmap ); + cx->pGlxReadPixmap = 0; + } + + if (cx->pGlxWindow) { + /* + ** The previous drawable was a glx window, release it. + */ + cx->pGlxWindow->refcnt--; + __glXFreeGLXWindow( cx->pGlxWindow ); + cx->pGlxWindow = 0; + } + + if (cx->pGlxReadWindow) { + /* + ** The previous drawable was a glx window, release it. + */ + cx->pGlxReadWindow->refcnt--; + __glXFreeGLXWindow( cx->pGlxReadWindow ); + cx->pGlxReadWindow = 0; + } + + __glXFree(cx); + + if (cx == __glXLastContext) { + __glXFlushContextCache(); + } + + return GL_TRUE; +} + +/* +** Initialize the GLX extension. +*/ +void GlxExtensionInit(void) +{ + ExtensionEntry *extEntry; + int i; + int glxSupported = 1; + + /* + // do not initialize GLX extension if GLX is not supported + // by ALL back-end servers. + */ + for (i=0; i<screenInfo.numScreens; i++) { + glxSupported &= (dmxScreens[i].glxMajorOpcode > 0); + } + + if (!glxSupported || !dmxGLXProxy) { + return; + } + + __glXContextRes = CreateNewResourceType((DeleteType)ContextGone, + "GLXContext"); + __glXClientRes = CreateNewResourceType((DeleteType)ClientGone, + "GLXClient"); + __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone, + "GLXPixmap"); + __glXWindowRes = CreateNewResourceType((DeleteType)WindowGone, + "GLXWindow"); + __glXPbufferRes = CreateNewResourceType((DeleteType)PbufferGone, + "GLXPbuffer"); + + if (!__glXContextRes || !__glXClientRes || !__glXPixmapRes || + !__glXWindowRes || !__glXPbufferRes) + return; + + /* + ** Add extension to server extensions. + */ + extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, + __GLX_NUMBER_ERRORS, __glXDispatch, + __glXSwapDispatch, ResetExtension, + StandardMinorOpcode); + if (!extEntry) { + FatalError("__glXExtensionInit: AddExtensions failed\n"); + return; + } + /* + if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { + ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); + return; + } + */ + + __glXerrorBase = extEntry->errorBase; + __glXBadContext = extEntry->errorBase + GLXBadContext; + __glXBadContextState = extEntry->errorBase + GLXBadContextState; + __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; + __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; + __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; + __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; + __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; + __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; + __glXUnsupportedPrivateRequest = extEntry->errorBase + + GLXUnsupportedPrivateRequest; + __glXBadFBConfig = extEntry->errorBase + GLXBadFBConfig; + __glXBadPbuffer = extEntry->errorBase + GLXBadPbuffer; + + /* + ** Initialize table of client state. There is never a client 0. + */ + for (i=1; i <= MAXCLIENTS; i++) { + __glXClients[i] = 0; + } + + /* + ** Initialize screen specific data. + */ + __glXScreenInit(screenInfo.numScreens); + + /* + ** Initialize swap barrier support. + */ + SwapBarrierInit(); +} + +/************************************************************************/ + +Bool __glXCoreType(void) +{ + return 0; +} + +/************************************************************************/ + +void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig *configs, void **privates) +{ + glxSetVisualConfigs(nconfigs, configs, privates); +} + +static miInitVisualsProcPtr saveInitVisualsProc; + +Bool GlxInitVisuals(VisualPtr *visualp, DepthPtr *depthp, + int *nvisualp, int *ndepthp, + int *rootDepthp, VisualID *defaultVisp, + unsigned long sizes, int bitsPerRGB, + int preferredVis) +{ + Bool ret; + + if (saveInitVisualsProc) { + ret = saveInitVisualsProc(visualp, depthp, nvisualp, ndepthp, + rootDepthp, defaultVisp, sizes, bitsPerRGB, + preferredVis); + if (!ret) + return False; + } + + glxInitVisuals(nvisualp, visualp, defaultVisp, *ndepthp, *depthp,*rootDepthp); + + return True; +} + +void +GlxWrapInitVisuals(miInitVisualsProcPtr *initVisProc) +{ + if (dmxGLXProxy) { + saveInitVisualsProc = *initVisProc; + *initVisProc = GlxInitVisuals; + } +} + +/************************************************************************/ + +void __glXFlushContextCache(void) +{ + __glXLastContext = 0; +} + +/************************************************************************/ + +/* +** Top level dispatcher; all commands are executed from here down. +*/ +static int __glXDispatch(ClientPtr client) +{ + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = __glXCalloc(1, sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + + cl->be_displays = __glXCalloc(screenInfo.numScreens, sizeof(Display *)); + if (!cl->be_displays) { + __glXFree( cl ); + return BadAlloc; + } + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->largeCmdRequestsTotal = 0; + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSingleTable[opcode]; + return (*proc)(cl, (GLbyte *) stuff); +} + +static int __glXSwapDispatch(ClientPtr client) +{ + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = __glXCalloc(1, sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + + cl->be_displays = __glXCalloc(screenInfo.numScreens, sizeof(Display *)); + if (!cl->be_displays) { + __glXFree( cl ); + return BadAlloc; + } + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSwapSingleTable[opcode]; + return (*proc)(cl, (GLbyte *) stuff); +} + +int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) +{ + return BadRequest; +} + +void __glXNoSuchRenderOpcode(GLbyte *pc) +{ + return; +} + diff --git a/xorg-server/hw/dmx/glxProxy/glxscreens.c b/xorg-server/hw/dmx/glxProxy/glxscreens.c index 39978a74d..4c40d2315 100644 --- a/xorg-server/hw/dmx/glxProxy/glxscreens.c +++ b/xorg-server/hw/dmx/glxProxy/glxscreens.c @@ -1,377 +1,377 @@ -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "dmx.h" -#include "dmxlog.h" - -#undef Xmalloc -#undef Xcalloc -#undef Xrealloc -#undef Xfree - -#include "glxserver.h" - -#include <windowstr.h> - -#include "glxfbconfig.h" - -#ifdef PANORAMIX -#include "panoramiXsrv.h" -#endif - -__GLXscreenInfo *__glXActiveScreens; -GLint __glXNumActiveScreens; - -__GLXFBConfig **__glXFBConfigs; -int __glXNumFBConfigs; - -static char GLXServerVendorName[] = "SGI DMX/glxProxy"; -static char GLXServerVersion[64]; -static char GLXServerExtensions[] = - "GLX_EXT_visual_info " - "GLX_EXT_visual_rating " - "GLX_EXT_import_context " - "GLX_SGIX_fbconfig " - "GLX_SGI_make_current_read " - "GLX_SGI_swap_control " - ; - -static char ExtensionsString[1024]; - -static void CalcServerVersionAndExtensions( void ) -{ - int s; - xGLXQueryVersionReq *req; - xGLXQueryVersionReply reply; - char **be_extensions; - char *ext; - char *denied_extensions; - - /* - * set the server glx version to be the minimum version - * supported by all back-end servers - */ - __glXVersionMajor = 0; - __glXVersionMinor = 0; - for (s=0; s<__glXNumActiveScreens; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = dmxScreen->beDisplay; - - /* Send the glXQueryVersion request */ - LockDisplay(dpy); - GetReq(GLXQueryVersion,req); - req->reqType = dmxScreen->glxMajorOpcode; - req->glxCode = X_GLXQueryVersion; - req->majorVersion = GLX_SERVER_MAJOR_VERSION; - req->minorVersion = GLX_SERVER_MINOR_VERSION; - _XReply(dpy, (xReply*) &reply, 0, False); - UnlockDisplay(dpy); - SyncHandle(); - - if (s == 0) { - __glXVersionMajor = reply.majorVersion; - __glXVersionMinor = reply.minorVersion; - } - else { - if (reply.majorVersion < __glXVersionMajor) { - __glXVersionMajor = reply.majorVersion; - __glXVersionMinor = reply.minorVersion; - } - else if ( (reply.majorVersion == __glXVersionMajor) && - (reply.minorVersion < __glXVersionMinor) ) { - __glXVersionMinor = reply.minorVersion; - } - } - - } - - if (GLX_SERVER_MAJOR_VERSION < __glXVersionMajor) { - __glXVersionMajor = GLX_SERVER_MAJOR_VERSION; - __glXVersionMinor = GLX_SERVER_MINOR_VERSION; - } - else if ( (GLX_SERVER_MAJOR_VERSION == __glXVersionMajor) && - (GLX_SERVER_MINOR_VERSION < __glXVersionMinor) ) { - __glXVersionMinor = GLX_SERVER_MINOR_VERSION; - } - - sprintf(GLXServerVersion, "%d.%d DMX %d back-end server(s)", - __glXVersionMajor, __glXVersionMinor, __glXNumActiveScreens ); - /* - * set the ExtensionsString to the minimum extensions string - */ - ExtensionsString[0] = '\0'; - - /* - * read extensions strings of all back-end servers - */ - be_extensions = (char **)Xalloc( __glXNumActiveScreens * sizeof(char *) ); - if (!be_extensions) - return; - - for (s=0; s<__glXNumActiveScreens; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = dmxScreen->beDisplay; - xGLXQueryServerStringReq *req; - xGLXQueryServerStringReply reply; - int length, numbytes, slop; - - /* Send the glXQueryServerString request */ - LockDisplay(dpy); - GetReq(GLXQueryServerString,req); - req->reqType = dmxScreen->glxMajorOpcode; - req->glxCode = X_GLXQueryServerString; - req->screen = DefaultScreen(dpy); - req->name = GLX_EXTENSIONS; - _XReply(dpy, (xReply*) &reply, 0, False); - - length = (int)reply.length; - numbytes = (int)reply.n; - slop = numbytes * __GLX_SIZE_INT8 & 3; - be_extensions[s] = (char *)Xalloc(numbytes); - if (!be_extensions[s]) { - /* Throw data on the floor */ - _XEatData(dpy, length); - } else { - _XRead(dpy, (char *)be_extensions[s], numbytes); - if (slop) _XEatData(dpy,4-slop); - } - UnlockDisplay(dpy); - SyncHandle(); - } - - /* - * extensions string will include only extensions that our - * server supports as well as all back-end servers supports. - * extensions that are in the DMX_DENY_EXTENSIONS string will - * not be supported. - */ - denied_extensions = getenv("DMX_DENY_GLX_EXTENSIONS"); - ext = strtok(GLXServerExtensions, " "); - while( ext ) { - int supported = 1; - - if (denied_extensions && strstr(denied_extensions, ext)) { - supported = 0; - } - else { - for (s=0; s<__glXNumActiveScreens && supported; s++) { - if ( !strstr(be_extensions[s], ext) ) { - supported = 0; - } - } - } - - if (supported) { - strcat(ExtensionsString, ext); - strcat(ExtensionsString, " "); - } - - ext = strtok(NULL, " "); - } - - /* - * release temporary storage - */ - for (s=0; s<__glXNumActiveScreens; s++) { - if (be_extensions[s]) Xfree(be_extensions[s]); - } - Xfree( be_extensions ); - - if (dmxGLXSwapGroupSupport) { - if (!denied_extensions || - !strstr(denied_extensions, "GLX_SGIX_swap_group")) { - strcat(ExtensionsString, "GLX_SGIX_swap_group"); - if (!denied_extensions || - !strstr(denied_extensions, "GLX_SGIX_swap_barrier")) { - strcat(ExtensionsString, " GLX_SGIX_swap_barrier"); - } - } - } - -} - -void __glXScreenInit(GLint numscreens) -{ - int s; - int c; - DMXScreenInfo *dmxScreen0 = &dmxScreens[0]; - __glXNumActiveScreens = numscreens; - - - CalcServerVersionAndExtensions(); - - - __glXFBConfigs = NULL; - __glXNumFBConfigs = 0; - - if ( (__glXVersionMajor == 1 && __glXVersionMinor >= 3) || - (__glXVersionMajor > 1) || - ( strstr(ExtensionsString, "GLX_SGIX_fbconfig") ) ) { - - /* - // Initialize FBConfig info. - // find the set of FBConfigs that are present on all back-end - // servers - only those configs will be supported - */ - __glXFBConfigs = (__GLXFBConfig **)Xalloc( dmxScreen0->numFBConfigs * - (numscreens+1) * sizeof(__GLXFBConfig *) ); - __glXNumFBConfigs = 0; - - for (c=0; c<dmxScreen0->numFBConfigs; c++) { - __GLXFBConfig *cfg = NULL; - - if (numscreens > 1) { - for (s=1; s<numscreens; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - __GLXscreenInfo *glxScreen = &__glXActiveScreens[s]; - - cfg = FindMatchingFBConfig( &dmxScreen0->fbconfigs[c], - dmxScreen->fbconfigs, - dmxScreen->numFBConfigs ); - __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + s + 1 ] = cfg; - if (!cfg) { - dmxLog(dmxInfo,"screen0 FBConfig 0x%x is missing on screen#%d\n", dmxScreen0->fbconfigs[c].id, s); - break; - } - else { - dmxLog(dmxInfo,"screen0 FBConfig 0x%x matched to 0x%x on screen#%d\n", dmxScreen0->fbconfigs[c].id, cfg->id, s); - } - } - } - else { - cfg = &dmxScreen0->fbconfigs[c]; - } - - if (cfg) { - - /* filter out overlay visuals */ - if (cfg->level == 0) { - __GLXFBConfig *proxy_cfg; - - __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + 1 ] = - &dmxScreen0->fbconfigs[c]; - - proxy_cfg = Xalloc( sizeof(__GLXFBConfig) ); - memcpy( proxy_cfg, cfg, sizeof(__GLXFBConfig) ); - proxy_cfg->id = FakeClientID(0); - /* visual will be associated later in __glXGetFBConfigs */ - proxy_cfg->associatedVisualId = (unsigned int)-1; - - __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + 0 ] = proxy_cfg; - - __glXNumFBConfigs++; - } - - } - - } - - } - -} - -void __glXScreenReset(void) -{ - __glXNumActiveScreens = 0; -} - -char *__glXGetServerString( unsigned int name ) -{ - char *ret = NULL; - - switch( name) { - - case GLX_VENDOR: - ret = GLXServerVendorName; - break; - - case GLX_VERSION: - ret = GLXServerVersion; - break; - - case GLX_EXTENSIONS: - ret = ExtensionsString; - break; - - default: - break; - } - - return( ret ); - -} - - -__GLXFBConfig *glxLookupFBConfig( GLXFBConfigID id ) -{ - int i,j; - - for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) { - if ( __glXFBConfigs[j]->id == id) - return( __glXFBConfigs[j] ); - } - - return(NULL); -} - -__GLXFBConfig *glxLookupFBConfigByVID( VisualID vid ) -{ - int i,j; - - for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) { - if ( __glXFBConfigs[j]->associatedVisualId == vid) - return( __glXFBConfigs[j] ); - } - - return(NULL); -} - -__GLXFBConfig *glxLookupBackEndFBConfig( GLXFBConfigID id, int screen ) -{ - int i; - int j; - - for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) { - if ( __glXFBConfigs[j]->id == id) - return( __glXFBConfigs[j+screen+1] ); - } - - return(NULL); - -} - -int glxIsExtensionSupported( char *ext ) -{ - return( strstr(ExtensionsString, ext) != NULL ); -} +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "dmx.h" +#include "dmxlog.h" + +#undef Xmalloc +#undef Xcalloc +#undef Xrealloc +#undef Xfree + +#include "glxserver.h" + +#include <windowstr.h> + +#include "glxfbconfig.h" + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +__GLXscreenInfo *__glXActiveScreens; +GLint __glXNumActiveScreens; + +__GLXFBConfig **__glXFBConfigs; +int __glXNumFBConfigs; + +static char GLXServerVendorName[] = "SGI DMX/glxProxy"; +static char GLXServerVersion[64]; +static char GLXServerExtensions[] = + "GLX_EXT_visual_info " + "GLX_EXT_visual_rating " + "GLX_EXT_import_context " + "GLX_SGIX_fbconfig " + "GLX_SGI_make_current_read " + "GLX_SGI_swap_control " + ; + +static char ExtensionsString[1024]; + +static void CalcServerVersionAndExtensions( void ) +{ + int s; + xGLXQueryVersionReq *req; + xGLXQueryVersionReply reply; + char **be_extensions; + char *ext; + char *denied_extensions; + + /* + * set the server glx version to be the minimum version + * supported by all back-end servers + */ + __glXVersionMajor = 0; + __glXVersionMinor = 0; + for (s=0; s<__glXNumActiveScreens; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = dmxScreen->beDisplay; + + /* Send the glXQueryVersion request */ + LockDisplay(dpy); + GetReq(GLXQueryVersion,req); + req->reqType = dmxScreen->glxMajorOpcode; + req->glxCode = X_GLXQueryVersion; + req->majorVersion = GLX_SERVER_MAJOR_VERSION; + req->minorVersion = GLX_SERVER_MINOR_VERSION; + _XReply(dpy, (xReply*) &reply, 0, False); + UnlockDisplay(dpy); + SyncHandle(); + + if (s == 0) { + __glXVersionMajor = reply.majorVersion; + __glXVersionMinor = reply.minorVersion; + } + else { + if (reply.majorVersion < __glXVersionMajor) { + __glXVersionMajor = reply.majorVersion; + __glXVersionMinor = reply.minorVersion; + } + else if ( (reply.majorVersion == __glXVersionMajor) && + (reply.minorVersion < __glXVersionMinor) ) { + __glXVersionMinor = reply.minorVersion; + } + } + + } + + if (GLX_SERVER_MAJOR_VERSION < __glXVersionMajor) { + __glXVersionMajor = GLX_SERVER_MAJOR_VERSION; + __glXVersionMinor = GLX_SERVER_MINOR_VERSION; + } + else if ( (GLX_SERVER_MAJOR_VERSION == __glXVersionMajor) && + (GLX_SERVER_MINOR_VERSION < __glXVersionMinor) ) { + __glXVersionMinor = GLX_SERVER_MINOR_VERSION; + } + + sprintf(GLXServerVersion, "%d.%d DMX %d back-end server(s)", + __glXVersionMajor, __glXVersionMinor, __glXNumActiveScreens ); + /* + * set the ExtensionsString to the minimum extensions string + */ + ExtensionsString[0] = '\0'; + + /* + * read extensions strings of all back-end servers + */ + be_extensions = (char **)malloc( __glXNumActiveScreens * sizeof(char *) ); + if (!be_extensions) + return; + + for (s=0; s<__glXNumActiveScreens; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = dmxScreen->beDisplay; + xGLXQueryServerStringReq *req; + xGLXQueryServerStringReply reply; + int length, numbytes, slop; + + /* Send the glXQueryServerString request */ + LockDisplay(dpy); + GetReq(GLXQueryServerString,req); + req->reqType = dmxScreen->glxMajorOpcode; + req->glxCode = X_GLXQueryServerString; + req->screen = DefaultScreen(dpy); + req->name = GLX_EXTENSIONS; + _XReply(dpy, (xReply*) &reply, 0, False); + + length = (int)reply.length; + numbytes = (int)reply.n; + slop = numbytes * __GLX_SIZE_INT8 & 3; + be_extensions[s] = (char *)malloc(numbytes); + if (!be_extensions[s]) { + /* Throw data on the floor */ + _XEatData(dpy, length); + } else { + _XRead(dpy, (char *)be_extensions[s], numbytes); + if (slop) _XEatData(dpy,4-slop); + } + UnlockDisplay(dpy); + SyncHandle(); + } + + /* + * extensions string will include only extensions that our + * server supports as well as all back-end servers supports. + * extensions that are in the DMX_DENY_EXTENSIONS string will + * not be supported. + */ + denied_extensions = getenv("DMX_DENY_GLX_EXTENSIONS"); + ext = strtok(GLXServerExtensions, " "); + while( ext ) { + int supported = 1; + + if (denied_extensions && strstr(denied_extensions, ext)) { + supported = 0; + } + else { + for (s=0; s<__glXNumActiveScreens && supported; s++) { + if ( !strstr(be_extensions[s], ext) ) { + supported = 0; + } + } + } + + if (supported) { + strcat(ExtensionsString, ext); + strcat(ExtensionsString, " "); + } + + ext = strtok(NULL, " "); + } + + /* + * release temporary storage + */ + for (s=0; s<__glXNumActiveScreens; s++) { + if (be_extensions[s]) Xfree(be_extensions[s]); + } + Xfree( be_extensions ); + + if (dmxGLXSwapGroupSupport) { + if (!denied_extensions || + !strstr(denied_extensions, "GLX_SGIX_swap_group")) { + strcat(ExtensionsString, "GLX_SGIX_swap_group"); + if (!denied_extensions || + !strstr(denied_extensions, "GLX_SGIX_swap_barrier")) { + strcat(ExtensionsString, " GLX_SGIX_swap_barrier"); + } + } + } + +} + +void __glXScreenInit(GLint numscreens) +{ + int s; + int c; + DMXScreenInfo *dmxScreen0 = &dmxScreens[0]; + __glXNumActiveScreens = numscreens; + + + CalcServerVersionAndExtensions(); + + + __glXFBConfigs = NULL; + __glXNumFBConfigs = 0; + + if ( (__glXVersionMajor == 1 && __glXVersionMinor >= 3) || + (__glXVersionMajor > 1) || + ( strstr(ExtensionsString, "GLX_SGIX_fbconfig") ) ) { + + /* + // Initialize FBConfig info. + // find the set of FBConfigs that are present on all back-end + // servers - only those configs will be supported + */ + __glXFBConfigs = (__GLXFBConfig **)malloc( dmxScreen0->numFBConfigs * + (numscreens+1) * sizeof(__GLXFBConfig *) ); + __glXNumFBConfigs = 0; + + for (c=0; c<dmxScreen0->numFBConfigs; c++) { + __GLXFBConfig *cfg = NULL; + + if (numscreens > 1) { + for (s=1; s<numscreens; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + __GLXscreenInfo *glxScreen = &__glXActiveScreens[s]; + + cfg = FindMatchingFBConfig( &dmxScreen0->fbconfigs[c], + dmxScreen->fbconfigs, + dmxScreen->numFBConfigs ); + __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + s + 1 ] = cfg; + if (!cfg) { + dmxLog(dmxInfo,"screen0 FBConfig 0x%x is missing on screen#%d\n", dmxScreen0->fbconfigs[c].id, s); + break; + } + else { + dmxLog(dmxInfo,"screen0 FBConfig 0x%x matched to 0x%x on screen#%d\n", dmxScreen0->fbconfigs[c].id, cfg->id, s); + } + } + } + else { + cfg = &dmxScreen0->fbconfigs[c]; + } + + if (cfg) { + + /* filter out overlay visuals */ + if (cfg->level == 0) { + __GLXFBConfig *proxy_cfg; + + __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + 1 ] = + &dmxScreen0->fbconfigs[c]; + + proxy_cfg = malloc( sizeof(__GLXFBConfig) ); + memcpy( proxy_cfg, cfg, sizeof(__GLXFBConfig) ); + proxy_cfg->id = FakeClientID(0); + /* visual will be associated later in __glXGetFBConfigs */ + proxy_cfg->associatedVisualId = (unsigned int)-1; + + __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + 0 ] = proxy_cfg; + + __glXNumFBConfigs++; + } + + } + + } + + } + +} + +void __glXScreenReset(void) +{ + __glXNumActiveScreens = 0; +} + +char *__glXGetServerString( unsigned int name ) +{ + char *ret = NULL; + + switch( name) { + + case GLX_VENDOR: + ret = GLXServerVendorName; + break; + + case GLX_VERSION: + ret = GLXServerVersion; + break; + + case GLX_EXTENSIONS: + ret = ExtensionsString; + break; + + default: + break; + } + + return( ret ); + +} + + +__GLXFBConfig *glxLookupFBConfig( GLXFBConfigID id ) +{ + int i,j; + + for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) { + if ( __glXFBConfigs[j]->id == id) + return( __glXFBConfigs[j] ); + } + + return(NULL); +} + +__GLXFBConfig *glxLookupFBConfigByVID( VisualID vid ) +{ + int i,j; + + for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) { + if ( __glXFBConfigs[j]->associatedVisualId == vid) + return( __glXFBConfigs[j] ); + } + + return(NULL); +} + +__GLXFBConfig *glxLookupBackEndFBConfig( GLXFBConfigID id, int screen ) +{ + int i; + int j; + + for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) { + if ( __glXFBConfigs[j]->id == id) + return( __glXFBConfigs[j+screen+1] ); + } + + return(NULL); + +} + +int glxIsExtensionSupported( char *ext ) +{ + return( strstr(ExtensionsString, ext) != NULL ); +} diff --git a/xorg-server/hw/dmx/glxProxy/glxsingle.c b/xorg-server/hw/dmx/glxProxy/glxsingle.c index dcc604052..19f12ad58 100644 --- a/xorg-server/hw/dmx/glxProxy/glxsingle.c +++ b/xorg-server/hw/dmx/glxProxy/glxsingle.c @@ -1,1012 +1,1012 @@ -/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED */ -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "dmx.h" -#include "dmxwindow.h" -#include "dmxpixmap.h" -#include "dmxfont.h" -#include "dmxcb.h" - -#undef Xmalloc -#undef Xcalloc -#undef Xrealloc -#undef Xfree - -#include "glxserver.h" -#include "glxext.h" -#include "g_disptab.h" -/* #include "g_disptab_EXT.h" */ -#include "unpack.h" -#include "glxutil.h" - -#include "GL/glxproto.h" - -#ifdef PANORAMIX -#include "panoramiXsrv.h" -#endif - -/* - * GetReqSingle - this is the equivalent of GetReq macro - * from Xlibint.h but it does not set the reqType field (the opcode). - * this is because the GL single opcodes has different naming convension - * the other X opcodes (ie. X_GLsop_GetFloatv). - */ -#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) -#define GetReqSingle(name, req) \ - WORD64ALIGN\ - if ((dpy->bufptr + SIZEOF(x##name##Req)) > dpy->bufmax)\ - _XFlush(dpy);\ - req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\ - req->length = (SIZEOF(x##name##Req))>>2;\ - dpy->bufptr += SIZEOF(x##name##Req);\ - dpy->request++ - -#else /* non-ANSI C uses empty comment instead of "##" for token concatenation */ -#define GetReqSingle(name, req) \ - WORD64ALIGN\ - if ((dpy->bufptr + SIZEOF(x/**/name/**/Req)) > dpy->bufmax)\ - _XFlush(dpy);\ - req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\ - req->length = (SIZEOF(x/**/name/**/Req))>>2;\ - dpy->bufptr += SIZEOF(x/**/name/**/Req);\ - dpy->request++ -#endif - -#define X_GLXSingle 0 /* needed by GetReqExtra */ - -extern Display *GetBackEndDisplay( __GLXclientState *cl, int s ); -extern int GetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s); - -static int swap_vec_element_size = 0; - -static void SendSwappedReply( ClientPtr client, - xGLXSingleReply *reply, - char *buf, - int buf_size ) -{ - __GLX_DECLARE_SWAP_VARIABLES; - __GLX_SWAP_SHORT(&reply->sequenceNumber); - __GLX_SWAP_INT(&reply->length); - __GLX_SWAP_INT(&reply->retval); - __GLX_SWAP_INT(&reply->size); - - if ( (buf_size == 0) && (swap_vec_element_size > 0) ) { - /* - * the reply has single component - need to swap pad3 - */ - if (swap_vec_element_size == 2) { - __GLX_SWAP_SHORT(&reply->pad3); - } - else if (swap_vec_element_size == 4) { - __GLX_SWAP_INT(&reply->pad3); - __GLX_SWAP_INT(&reply->pad4); /* some requests use also pad4 - * i.e GetConvolutionFilter - */ - } - else if (swap_vec_element_size == 8) { - __GLX_SWAP_DOUBLE(&reply->pad3); - } - } - else if ( (buf_size > 0) && (swap_vec_element_size > 0) ) { - /* - * the reply has vector of elements which needs to be swapped - */ - int vsize = buf_size / swap_vec_element_size; - char *p = buf; - int i; - - for (i=0; i<vsize; i++) { - if (swap_vec_element_size == 2) { - __GLX_SWAP_SHORT(p); - } - else if (swap_vec_element_size == 4) { - __GLX_SWAP_INT(p); - } - else if (swap_vec_element_size == 8) { - __GLX_SWAP_DOUBLE(p); - } - - p += swap_vec_element_size; - } - - /* - * swap pad words as well - for case that some single reply uses - * them as well - */ - __GLX_SWAP_INT(&reply->pad3); - __GLX_SWAP_INT(&reply->pad4); - __GLX_SWAP_INT(&reply->pad5); - __GLX_SWAP_INT(&reply->pad6); - - } - - WriteToClient(client, sizeof(xGLXSingleReply),(char *)reply); - if (buf_size > 0) - WriteToClient(client, buf_size, (char *)buf); - -} - -int __glXForwardSingleReq( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - xGLXSingleReq *be_req; - __GLXcontext *glxc; - int from_screen = 0; - int to_screen = 0; - int buf_size; - int s; - - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return 0; - } - from_screen = to_screen = glxc->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - pc += sz_xGLXSingleReq; - buf_size = (req->length << 2) - sz_xGLXSingleReq; - - /* - * just forward the request to back-end server(s) - */ - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReqSingle(GLXSingle,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = req->glxCode; - be_req->length = req->length; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); - if (buf_size > 0) - _XSend(dpy, (const char *)pc, buf_size); - UnlockDisplay(dpy); - SyncHandle(); - - if (req->glxCode == X_GLsop_Flush) { - XFlush(dpy); - } - - } - - return Success; -} - -int __glXForwardPipe0WithReply( __GLXclientState *cl, GLbyte *pc ) -{ - ClientPtr client = cl->client; - xGLXSingleReq *req = (xGLXSingleReq *)pc; - xGLXSingleReq *be_req; - xGLXSingleReply reply; - xGLXSingleReply be_reply; - __GLXcontext *glxc; - int buf_size; - char *be_buf; - int be_buf_size; - DMXScreenInfo *dmxScreen; - Display *dpy; - - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return __glXBadContext; - } - - pc += sz_xGLXSingleReq; - buf_size = (req->length << 2) - sz_xGLXSingleReq; - - dmxScreen = &dmxScreens[glxc->pScreen->myNum]; - dpy = GetBackEndDisplay(cl, glxc->pScreen->myNum); - - /* - * send the request to the first back-end server - */ - LockDisplay(dpy); - GetReqSingle(GLXSingle,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = req->glxCode; - be_req->length = req->length; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,glxc->pScreen->myNum); - if (buf_size > 0) - _XSend(dpy, (const char *)pc, buf_size); - - /* - * get the reply from the back-end server - */ - _XReply(dpy, (xReply*) &be_reply, 0, False); - be_buf_size = be_reply.length << 2; - if (be_buf_size > 0) { - be_buf = (char *)Xalloc( be_buf_size ); - if (be_buf) { - _XRead(dpy, be_buf, be_buf_size); - } - else { - /* Throw data on the floor */ - _XEatData(dpy, be_buf_size); - return BadAlloc; - } - } - - UnlockDisplay(dpy); - SyncHandle(); - - /* - * send the reply to the client - */ - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = be_reply.length; - reply.retval = be_reply.retval; - reply.size = be_reply.size; - reply.pad3 = be_reply.pad3; - reply.pad4 = be_reply.pad4; - - if (client->swapped) { - SendSwappedReply( client, &reply, be_buf, be_buf_size ); - } - else { - WriteToClient(client, sizeof(xGLXSingleReply),(char *)&reply); - if (be_buf_size > 0) - WriteToClient(client, be_buf_size, (char *)be_buf); - } - - if (be_buf_size > 0) Xfree(be_buf); - - return Success; -} - -int __glXForwardAllWithReply( __GLXclientState *cl, GLbyte *pc ) -{ - ClientPtr client = cl->client; - xGLXSingleReq *req = (xGLXSingleReq *)pc; - xGLXSingleReq *be_req; - xGLXSingleReply reply; - xGLXSingleReply be_reply; - __GLXcontext *glxc; - int buf_size; - char *be_buf; - int be_buf_size; - int from_screen = 0; - int to_screen = 0; - int s; - - DMXScreenInfo *dmxScreen; - Display *dpy; - - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return 0; - } - from_screen = to_screen = glxc->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - pc += sz_xGLXSingleReq; - buf_size = (req->length << 2) - sz_xGLXSingleReq; - - /* - * send the request to the first back-end server(s) - */ - for (s=to_screen; s>=from_screen; s--) { - dmxScreen = &dmxScreens[s]; - dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReqSingle(GLXSingle,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = req->glxCode; - be_req->length = req->length; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); - if (buf_size > 0) - _XSend(dpy, (const char *)pc, buf_size); - - /* - * get the reply from the back-end server - */ - _XReply(dpy, (xReply*) &be_reply, 0, False); - be_buf_size = be_reply.length << 2; - if (be_buf_size > 0) { - be_buf = (char *)Xalloc( be_buf_size ); - if (be_buf) { - _XRead(dpy, be_buf, be_buf_size); - } - else { - /* Throw data on the floor */ - _XEatData(dpy, be_buf_size); - return BadAlloc; - } - } - - UnlockDisplay(dpy); - SyncHandle(); - - if (s > from_screen && be_buf_size > 0) { - Xfree(be_buf); - } - } - - /* - * send the reply to the client - */ - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = be_reply.length; - reply.retval = be_reply.retval; - reply.size = be_reply.size; - reply.pad3 = be_reply.pad3; - reply.pad4 = be_reply.pad4; - - if (client->swapped) { - SendSwappedReply( client, &reply, be_buf, be_buf_size ); - } - else { - WriteToClient(client, sizeof(xGLXSingleReply),(char *)&reply); - if (be_buf_size > 0) - WriteToClient(client, be_buf_size, (char *)be_buf); - } - - if (be_buf_size > 0) Xfree(be_buf); - - return Success; -} - -int __glXForwardSingleReqSwap( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 0; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXForwardSingleReq( cl, pc ) ); -} - -int __glXForwardPipe0WithReplySwap( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 0; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXForwardPipe0WithReply( cl, pc ) ); -} - -int __glXForwardPipe0WithReplySwapsv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 2; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - - return( __glXForwardPipe0WithReply( cl, pc ) ); -} - -int __glXForwardPipe0WithReplySwapiv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 4; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - - return( __glXForwardPipe0WithReply( cl, pc ) ); -} - -int __glXForwardPipe0WithReplySwapdv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 8; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - - return( __glXForwardPipe0WithReply( cl, pc ) ); -} - -int __glXForwardAllWithReplySwap( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 0; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - - return( __glXForwardAllWithReply( cl, pc ) ); -} - -int __glXForwardAllWithReplySwapsv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 2; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - - return( __glXForwardAllWithReply( cl, pc ) ); -} - -int __glXForwardAllWithReplySwapiv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 4; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - - return( __glXForwardAllWithReply( cl, pc ) ); -} - -int __glXForwardAllWithReplySwapdv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 8; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXSingleReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXSingleReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - - return( __glXForwardAllWithReply( cl, pc ) ); -} - -static GLint __glReadPixels_size(GLenum format, GLenum type, GLint w, GLint h, - int *elementbits_return, int *rowbytes_return ) -{ - GLint elements, esize; - GLint rowsize, padding; - - if (w < 0 || h < 0) { - return -1; - } - switch (format) { - case GL_COLOR_INDEX: - case GL_STENCIL_INDEX: - case GL_DEPTH_COMPONENT: - elements = 1; - break; - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_LUMINANCE: - elements = 1; - break; - case GL_LUMINANCE_ALPHA: - elements = 2; - break; - case GL_RGB: - case GL_BGR: - elements = 3; - break; - case GL_RGBA: - case GL_BGRA: - case GL_ABGR_EXT: - elements = 4; - break; - default: - return -1; - } - /* - ** According to the GLX protocol, each row must be padded to a multiple of - ** 4 bytes. 4 bytes also happens to be the default alignment in the pixel - ** store modes of the GL. - */ - switch (type) { - case GL_BITMAP: - if (format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX) { - rowsize = ((w * elements)+7)/8; - padding = rowsize % 4; - if (padding) { - rowsize += 4 - padding; - } - if (elementbits_return) *elementbits_return = elements; - if (rowbytes_return) *rowbytes_return = rowsize; - return (rowsize * h); - } else { - return -1; - } - case GL_BYTE: - case GL_UNSIGNED_BYTE: - esize = 1; - break; - case GL_UNSIGNED_BYTE_3_3_2: - case GL_UNSIGNED_BYTE_2_3_3_REV: - esize = 1; - elements = 1; - break; - case GL_SHORT: - case GL_UNSIGNED_SHORT: - esize = 2; - break; - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_5_6_5_REV: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_4_4_4_4_REV: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT_1_5_5_5_REV: - esize = 2; - elements = 1; - break; - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: - esize = 4; - break; - case GL_UNSIGNED_INT_8_8_8_8: - case GL_UNSIGNED_INT_8_8_8_8_REV: - case GL_UNSIGNED_INT_10_10_10_2: - case GL_UNSIGNED_INT_2_10_10_10_REV: - esize = 4; - elements = 1; - break; - default: - return -1; - } - rowsize = w * elements * esize; - padding = rowsize % 4; - if (padding) { - rowsize += 4 - padding; - } - - if (elementbits_return) *elementbits_return = esize*elements*8; - if (rowbytes_return) *rowbytes_return = rowsize; - - return (rowsize * h); -} - -static int intersectRect( int x1, int x2, int y1, int y2, - int X1, int X2, int Y1, int Y2, - int *ix1, int *ix2, int *iy1, int *iy2 ) -{ - int right = (x2 < X2 ? x2 : X2); - int bottom = (y2 < Y2 ? y2 : Y2); - int left = (x1 > X1 ? x1 : X1); - int top = (y1 > Y1 ? y1 : Y1); - int width = right - left + 1; - int height = bottom - top + 1; - - if ( (width <= 0) || (height <= 0) ) { - *ix1 = *ix2 = *iy1 = *iy2 = 0; - return(0); - } - else { - *ix1 = left; - *ix2 = right; - *iy1 = top; - *iy2 = bottom; - return( width * height ); - } - -} - -int __glXDisp_ReadPixels(__GLXclientState *cl, GLbyte *pc) -{ - xGLXSingleReq *req = (xGLXSingleReq *)pc; - xGLXSingleReq *be_req; - xGLXReadPixelsReply reply; - xGLXReadPixelsReply be_reply; - GLbyte *be_pc; - GLint x,y; - GLsizei width, height; - GLenum format, type; - GLboolean swapBytes, lsbFirst; - ClientPtr client = cl->client; - DrawablePtr pDraw; - int error; - __GLXcontext *glxc; - int from_screen = 0; - int to_screen = 0; - char *buf; - int buf_size; - int s; - int win_x1, win_x2; - int win_y1, win_y2; - int ebits, rowsize; - __GLX_DECLARE_SWAP_VARIABLES; - - if (client->swapped) { - __GLX_SWAP_INT(&req->contextTag); - } - - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return 0; - } - from_screen = to_screen = glxc->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - pc += sz_xGLXSingleReq; - x = *(GLint *)(pc + 0); - y = *(GLint *)(pc + 4); - width = *(GLsizei *)(pc + 8); - height = *(GLsizei *)(pc + 12); - format = *(GLenum *)(pc + 16); - type = *(GLenum *)(pc + 20); - swapBytes = *(GLboolean *)(pc + 24); - lsbFirst = *(GLboolean *)(pc + 25); - - if (client->swapped) { - __GLX_SWAP_INT(&x); - __GLX_SWAP_INT(&y); - __GLX_SWAP_INT(&width); - __GLX_SWAP_INT(&height); - __GLX_SWAP_INT(&format); - __GLX_SWAP_INT(&type); - swapBytes = !swapBytes; - } - - buf_size = __glReadPixels_size(format,type,width,height, &ebits, &rowsize); - if (buf_size > 0) { - buf = (char *) Xalloc( buf_size ); - if ( !buf ) { - return( BadAlloc ); - } - } - else { - buf_size = 0; - } - - if (buf_size > 0) { - /* - * Get the current drawable this context is bound to - */ - pDraw = __glXLookupDrawableByTag( cl, req->contextTag ); - win_x1 = pDraw->x + x; - win_x2 = win_x1 + width - 1; - win_y1 = (dmxGlobalHeight - pDraw->y - pDraw->height) + y; - win_y2 = win_y1 + height - 1; - if (pDraw->type != DRAWABLE_WINDOW) { - from_screen = to_screen = 0; - } - - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - int scr_x1 = dmxScreen->rootXOrigin; - int scr_x2 = dmxScreen->rootXOrigin + dmxScreen->scrnWidth - 1; - int scr_y1 = dmxScreen->rootYOrigin; - int scr_y2 = dmxScreen->rootYOrigin + dmxScreen->scrnHeight - 1; - int wx1, wx2, wy1, wy2; - int sx, sy, sw, sh; - int npixels; - - /* - * find the window portion that is on the current screen - */ - if (pDraw->type == DRAWABLE_WINDOW) { - npixels = intersectRect( scr_x1, scr_x2, scr_y1, scr_y2, - win_x1, win_x2, win_y1, win_y2, - &wx1, &wx2, &wy1, &wy2 ); - } - else { - wx1 = win_x1; - wx2 = win_x2; - wy1 = win_y1; - wy2 = win_y2; - npixels = (wx2-wx1+1) * (wy2-wy1+1); - } - - if (npixels > 0) { - - /* send the request to the back-end server */ - LockDisplay(dpy); - GetReqExtra(GLXSingle,__GLX_PAD(26),be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = X_GLsop_ReadPixels; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); - be_pc = ((GLbyte *)(be_req) + sz_xGLXSingleReq); - - sx = wx1 - pDraw->x; - sy = wy1 - (dmxGlobalHeight - pDraw->y - pDraw->height); - sw = (wx2-wx1+1); - sh = (wy2-wy1+1); - - *(GLint *)(be_pc + 0) = sx; /* x */ - *(GLint *)(be_pc + 4) = sy; /* y */ - *(GLsizei *)(be_pc + 8) = sw; /* width */ - *(GLsizei *)(be_pc + 12) = sh; /* height */ - *(GLenum *)(be_pc + 16) = format; - *(GLenum *)(be_pc + 20) = type; - *(GLboolean *)(be_pc + 24) = swapBytes; - *(GLboolean *)(be_pc + 25) = lsbFirst; - - _XReply(dpy, (xReply*) &be_reply, 0, False); - - if (be_reply.length > 0) { - char *be_buf; - int be_buf_size = be_reply.length << 2; - - be_buf = (char *) Xalloc( be_buf_size ); - if (be_buf) { - _XRead(dpy, be_buf, be_buf_size); - - /* copy pixels data to the right location of the */ - /* reply buffer */ - if ( type != GL_BITMAP ) { - int pbytes = ebits / 8; - char *dst = buf + (sy-y)*rowsize + (sx-x)*pbytes; - char *src = be_buf; - int pad = (pbytes * sw) % 4; - int r; - - for (r=0; r<sh; r++) { - memcpy( dst, src, pbytes*sw ); - dst += rowsize; - src += (pbytes*sw + (pad ? 4-pad : 0) ); - } - } - else { - /* this is a GL_BITMAP pixel type, should copy bits */ - int r; - int src_rowsize = bits_to_bytes(sw * ebits); - int src_pad = src_rowsize % 4; - if ( src_pad ) { - src_rowsize += (4 - src_pad); - } - - for (r=0; r<sh; r++) { - unsigned char dst_mask = 0x80 >> (sx % 8); - unsigned char src_mask = 0x80; - char *dst = buf + (sy-y+r)*rowsize + (sx-x)/8; - char *src = be_buf + r*src_rowsize; - int b; - - for (b=0; b<sw*ebits; b++) { - if ( *src & src_mask ) { - *dst |= dst_mask; - } - else { - *dst &= ~dst_mask; - } - - if (dst_mask > 1) dst_mask >>= 1; - else { - dst_mask = 0x80; - dst++; - } - - if (src_mask > 1) src_mask >>= 1; - else { - src_mask = 0x80; - src++; - } - } - } - - } - - Xfree( be_buf ); - } - else { - /* Throw data on the floor */ - _XEatData(dpy, be_buf_size); - Xfree( buf ); - return BadAlloc; - } - } - - UnlockDisplay(dpy); - SyncHandle(); - - } /* of npixels > 0 */ - - } /* of for loop */ - - } /* of if buf_size > 0 */ - - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - reply.length = buf_size >> 2; - - if (client->swapped) { - __GLX_SWAP_SHORT(&reply.sequenceNumber); - __GLX_SWAP_INT(&reply.length); - } - - WriteToClient(client, sizeof(xGLXReadPixelsReply),(char *)&reply); - if (buf_size > 0) { - WriteToClient(client, buf_size, (char *)buf); - Xfree( buf ); - } - - return Success; -} - -int __glXDispSwap_GetTexImage(__GLXclientState *cl, GLbyte *pc) -{ - __GLX_DECLARE_SWAP_VARIABLES; - GLbyte *lpc = pc; - - lpc += sz_xGLXSingleReq; - __GLX_SWAP_INT(lpc+0); - __GLX_SWAP_INT(lpc+4); - __GLX_SWAP_INT(lpc+8); - __GLX_SWAP_INT(lpc+12); - - /* reverse swapBytes */ - *(GLboolean *)(lpc + 16) = ! *(GLboolean *)(lpc + 16); - - return( __glXForwardPipe0WithReplySwap( cl, pc ) ); -} - -int __glXDispSwap_GetColorTable(__GLXclientState *cl, GLbyte *pc) -{ - __GLX_DECLARE_SWAP_VARIABLES; - GLbyte *lpc = pc; - - lpc += sz_xGLXSingleReq; - __GLX_SWAP_INT(lpc+0); - __GLX_SWAP_INT(lpc+4); - __GLX_SWAP_INT(lpc+8); - - /* reverse swapBytes */ - *(GLboolean *)(lpc + 12) = ! *(GLboolean *)(lpc + 12); - - return( __glXForwardPipe0WithReplySwap( cl, pc ) ); -} - - +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED */ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "dmx.h" +#include "dmxwindow.h" +#include "dmxpixmap.h" +#include "dmxfont.h" +#include "dmxcb.h" + +#undef Xmalloc +#undef Xcalloc +#undef Xrealloc +#undef Xfree + +#include "glxserver.h" +#include "glxext.h" +#include "g_disptab.h" +/* #include "g_disptab_EXT.h" */ +#include "unpack.h" +#include "glxutil.h" + +#include "GL/glxproto.h" + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +/* + * GetReqSingle - this is the equivalent of GetReq macro + * from Xlibint.h but it does not set the reqType field (the opcode). + * this is because the GL single opcodes has different naming convension + * the other X opcodes (ie. X_GLsop_GetFloatv). + */ +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define GetReqSingle(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(x##name##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\ + req->length = (SIZEOF(x##name##Req))>>2;\ + dpy->bufptr += SIZEOF(x##name##Req);\ + dpy->request++ + +#else /* non-ANSI C uses empty comment instead of "##" for token concatenation */ +#define GetReqSingle(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(x/**/name/**/Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\ + req->length = (SIZEOF(x/**/name/**/Req))>>2;\ + dpy->bufptr += SIZEOF(x/**/name/**/Req);\ + dpy->request++ +#endif + +#define X_GLXSingle 0 /* needed by GetReqExtra */ + +extern Display *GetBackEndDisplay( __GLXclientState *cl, int s ); +extern int GetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s); + +static int swap_vec_element_size = 0; + +static void SendSwappedReply( ClientPtr client, + xGLXSingleReply *reply, + char *buf, + int buf_size ) +{ + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_SWAP_SHORT(&reply->sequenceNumber); + __GLX_SWAP_INT(&reply->length); + __GLX_SWAP_INT(&reply->retval); + __GLX_SWAP_INT(&reply->size); + + if ( (buf_size == 0) && (swap_vec_element_size > 0) ) { + /* + * the reply has single component - need to swap pad3 + */ + if (swap_vec_element_size == 2) { + __GLX_SWAP_SHORT(&reply->pad3); + } + else if (swap_vec_element_size == 4) { + __GLX_SWAP_INT(&reply->pad3); + __GLX_SWAP_INT(&reply->pad4); /* some requests use also pad4 + * i.e GetConvolutionFilter + */ + } + else if (swap_vec_element_size == 8) { + __GLX_SWAP_DOUBLE(&reply->pad3); + } + } + else if ( (buf_size > 0) && (swap_vec_element_size > 0) ) { + /* + * the reply has vector of elements which needs to be swapped + */ + int vsize = buf_size / swap_vec_element_size; + char *p = buf; + int i; + + for (i=0; i<vsize; i++) { + if (swap_vec_element_size == 2) { + __GLX_SWAP_SHORT(p); + } + else if (swap_vec_element_size == 4) { + __GLX_SWAP_INT(p); + } + else if (swap_vec_element_size == 8) { + __GLX_SWAP_DOUBLE(p); + } + + p += swap_vec_element_size; + } + + /* + * swap pad words as well - for case that some single reply uses + * them as well + */ + __GLX_SWAP_INT(&reply->pad3); + __GLX_SWAP_INT(&reply->pad4); + __GLX_SWAP_INT(&reply->pad5); + __GLX_SWAP_INT(&reply->pad6); + + } + + WriteToClient(client, sizeof(xGLXSingleReply),(char *)reply); + if (buf_size > 0) + WriteToClient(client, buf_size, (char *)buf); + +} + +int __glXForwardSingleReq( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + xGLXSingleReq *be_req; + __GLXcontext *glxc; + int from_screen = 0; + int to_screen = 0; + int buf_size; + int s; + + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return 0; + } + from_screen = to_screen = glxc->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + pc += sz_xGLXSingleReq; + buf_size = (req->length << 2) - sz_xGLXSingleReq; + + /* + * just forward the request to back-end server(s) + */ + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReqSingle(GLXSingle,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = req->glxCode; + be_req->length = req->length; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); + if (buf_size > 0) + _XSend(dpy, (const char *)pc, buf_size); + UnlockDisplay(dpy); + SyncHandle(); + + if (req->glxCode == X_GLsop_Flush) { + XFlush(dpy); + } + + } + + return Success; +} + +int __glXForwardPipe0WithReply( __GLXclientState *cl, GLbyte *pc ) +{ + ClientPtr client = cl->client; + xGLXSingleReq *req = (xGLXSingleReq *)pc; + xGLXSingleReq *be_req; + xGLXSingleReply reply; + xGLXSingleReply be_reply; + __GLXcontext *glxc; + int buf_size; + char *be_buf; + int be_buf_size; + DMXScreenInfo *dmxScreen; + Display *dpy; + + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return __glXBadContext; + } + + pc += sz_xGLXSingleReq; + buf_size = (req->length << 2) - sz_xGLXSingleReq; + + dmxScreen = &dmxScreens[glxc->pScreen->myNum]; + dpy = GetBackEndDisplay(cl, glxc->pScreen->myNum); + + /* + * send the request to the first back-end server + */ + LockDisplay(dpy); + GetReqSingle(GLXSingle,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = req->glxCode; + be_req->length = req->length; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,glxc->pScreen->myNum); + if (buf_size > 0) + _XSend(dpy, (const char *)pc, buf_size); + + /* + * get the reply from the back-end server + */ + _XReply(dpy, (xReply*) &be_reply, 0, False); + be_buf_size = be_reply.length << 2; + if (be_buf_size > 0) { + be_buf = (char *)malloc( be_buf_size ); + if (be_buf) { + _XRead(dpy, be_buf, be_buf_size); + } + else { + /* Throw data on the floor */ + _XEatData(dpy, be_buf_size); + return BadAlloc; + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + /* + * send the reply to the client + */ + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = be_reply.length; + reply.retval = be_reply.retval; + reply.size = be_reply.size; + reply.pad3 = be_reply.pad3; + reply.pad4 = be_reply.pad4; + + if (client->swapped) { + SendSwappedReply( client, &reply, be_buf, be_buf_size ); + } + else { + WriteToClient(client, sizeof(xGLXSingleReply),(char *)&reply); + if (be_buf_size > 0) + WriteToClient(client, be_buf_size, (char *)be_buf); + } + + if (be_buf_size > 0) Xfree(be_buf); + + return Success; +} + +int __glXForwardAllWithReply( __GLXclientState *cl, GLbyte *pc ) +{ + ClientPtr client = cl->client; + xGLXSingleReq *req = (xGLXSingleReq *)pc; + xGLXSingleReq *be_req; + xGLXSingleReply reply; + xGLXSingleReply be_reply; + __GLXcontext *glxc; + int buf_size; + char *be_buf; + int be_buf_size; + int from_screen = 0; + int to_screen = 0; + int s; + + DMXScreenInfo *dmxScreen; + Display *dpy; + + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return 0; + } + from_screen = to_screen = glxc->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + pc += sz_xGLXSingleReq; + buf_size = (req->length << 2) - sz_xGLXSingleReq; + + /* + * send the request to the first back-end server(s) + */ + for (s=to_screen; s>=from_screen; s--) { + dmxScreen = &dmxScreens[s]; + dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReqSingle(GLXSingle,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = req->glxCode; + be_req->length = req->length; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); + if (buf_size > 0) + _XSend(dpy, (const char *)pc, buf_size); + + /* + * get the reply from the back-end server + */ + _XReply(dpy, (xReply*) &be_reply, 0, False); + be_buf_size = be_reply.length << 2; + if (be_buf_size > 0) { + be_buf = (char *)malloc( be_buf_size ); + if (be_buf) { + _XRead(dpy, be_buf, be_buf_size); + } + else { + /* Throw data on the floor */ + _XEatData(dpy, be_buf_size); + return BadAlloc; + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + if (s > from_screen && be_buf_size > 0) { + Xfree(be_buf); + } + } + + /* + * send the reply to the client + */ + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = be_reply.length; + reply.retval = be_reply.retval; + reply.size = be_reply.size; + reply.pad3 = be_reply.pad3; + reply.pad4 = be_reply.pad4; + + if (client->swapped) { + SendSwappedReply( client, &reply, be_buf, be_buf_size ); + } + else { + WriteToClient(client, sizeof(xGLXSingleReply),(char *)&reply); + if (be_buf_size > 0) + WriteToClient(client, be_buf_size, (char *)be_buf); + } + + if (be_buf_size > 0) Xfree(be_buf); + + return Success; +} + +int __glXForwardSingleReqSwap( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 0; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXForwardSingleReq( cl, pc ) ); +} + +int __glXForwardPipe0WithReplySwap( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 0; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXForwardPipe0WithReply( cl, pc ) ); +} + +int __glXForwardPipe0WithReplySwapsv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 2; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + + return( __glXForwardPipe0WithReply( cl, pc ) ); +} + +int __glXForwardPipe0WithReplySwapiv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 4; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + + return( __glXForwardPipe0WithReply( cl, pc ) ); +} + +int __glXForwardPipe0WithReplySwapdv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 8; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + + return( __glXForwardPipe0WithReply( cl, pc ) ); +} + +int __glXForwardAllWithReplySwap( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 0; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + + return( __glXForwardAllWithReply( cl, pc ) ); +} + +int __glXForwardAllWithReplySwapsv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 2; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + + return( __glXForwardAllWithReply( cl, pc ) ); +} + +int __glXForwardAllWithReplySwapiv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 4; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + + return( __glXForwardAllWithReply( cl, pc ) ); +} + +int __glXForwardAllWithReplySwapdv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 8; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXSingleReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXSingleReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + + return( __glXForwardAllWithReply( cl, pc ) ); +} + +static GLint __glReadPixels_size(GLenum format, GLenum type, GLint w, GLint h, + int *elementbits_return, int *rowbytes_return ) +{ + GLint elements, esize; + GLint rowsize, padding; + + if (w < 0 || h < 0) { + return -1; + } + switch (format) { + case GL_COLOR_INDEX: + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + elements = 1; + break; + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + elements = 1; + break; + case GL_LUMINANCE_ALPHA: + elements = 2; + break; + case GL_RGB: + case GL_BGR: + elements = 3; + break; + case GL_RGBA: + case GL_BGRA: + case GL_ABGR_EXT: + elements = 4; + break; + default: + return -1; + } + /* + ** According to the GLX protocol, each row must be padded to a multiple of + ** 4 bytes. 4 bytes also happens to be the default alignment in the pixel + ** store modes of the GL. + */ + switch (type) { + case GL_BITMAP: + if (format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX) { + rowsize = ((w * elements)+7)/8; + padding = rowsize % 4; + if (padding) { + rowsize += 4 - padding; + } + if (elementbits_return) *elementbits_return = elements; + if (rowbytes_return) *rowbytes_return = rowsize; + return (rowsize * h); + } else { + return -1; + } + case GL_BYTE: + case GL_UNSIGNED_BYTE: + esize = 1; + break; + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + esize = 1; + elements = 1; + break; + case GL_SHORT: + case GL_UNSIGNED_SHORT: + esize = 2; + break; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + esize = 2; + elements = 1; + break; + case GL_INT: + case GL_UNSIGNED_INT: + case GL_FLOAT: + esize = 4; + break; + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + esize = 4; + elements = 1; + break; + default: + return -1; + } + rowsize = w * elements * esize; + padding = rowsize % 4; + if (padding) { + rowsize += 4 - padding; + } + + if (elementbits_return) *elementbits_return = esize*elements*8; + if (rowbytes_return) *rowbytes_return = rowsize; + + return (rowsize * h); +} + +static int intersectRect( int x1, int x2, int y1, int y2, + int X1, int X2, int Y1, int Y2, + int *ix1, int *ix2, int *iy1, int *iy2 ) +{ + int right = (x2 < X2 ? x2 : X2); + int bottom = (y2 < Y2 ? y2 : Y2); + int left = (x1 > X1 ? x1 : X1); + int top = (y1 > Y1 ? y1 : Y1); + int width = right - left + 1; + int height = bottom - top + 1; + + if ( (width <= 0) || (height <= 0) ) { + *ix1 = *ix2 = *iy1 = *iy2 = 0; + return(0); + } + else { + *ix1 = left; + *ix2 = right; + *iy1 = top; + *iy2 = bottom; + return( width * height ); + } + +} + +int __glXDisp_ReadPixels(__GLXclientState *cl, GLbyte *pc) +{ + xGLXSingleReq *req = (xGLXSingleReq *)pc; + xGLXSingleReq *be_req; + xGLXReadPixelsReply reply; + xGLXReadPixelsReply be_reply; + GLbyte *be_pc; + GLint x,y; + GLsizei width, height; + GLenum format, type; + GLboolean swapBytes, lsbFirst; + ClientPtr client = cl->client; + DrawablePtr pDraw; + int error; + __GLXcontext *glxc; + int from_screen = 0; + int to_screen = 0; + char *buf; + int buf_size; + int s; + int win_x1, win_x2; + int win_y1, win_y2; + int ebits, rowsize; + __GLX_DECLARE_SWAP_VARIABLES; + + if (client->swapped) { + __GLX_SWAP_INT(&req->contextTag); + } + + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return 0; + } + from_screen = to_screen = glxc->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + pc += sz_xGLXSingleReq; + x = *(GLint *)(pc + 0); + y = *(GLint *)(pc + 4); + width = *(GLsizei *)(pc + 8); + height = *(GLsizei *)(pc + 12); + format = *(GLenum *)(pc + 16); + type = *(GLenum *)(pc + 20); + swapBytes = *(GLboolean *)(pc + 24); + lsbFirst = *(GLboolean *)(pc + 25); + + if (client->swapped) { + __GLX_SWAP_INT(&x); + __GLX_SWAP_INT(&y); + __GLX_SWAP_INT(&width); + __GLX_SWAP_INT(&height); + __GLX_SWAP_INT(&format); + __GLX_SWAP_INT(&type); + swapBytes = !swapBytes; + } + + buf_size = __glReadPixels_size(format,type,width,height, &ebits, &rowsize); + if (buf_size > 0) { + buf = (char *) malloc( buf_size ); + if ( !buf ) { + return( BadAlloc ); + } + } + else { + buf_size = 0; + } + + if (buf_size > 0) { + /* + * Get the current drawable this context is bound to + */ + pDraw = __glXLookupDrawableByTag( cl, req->contextTag ); + win_x1 = pDraw->x + x; + win_x2 = win_x1 + width - 1; + win_y1 = (dmxGlobalHeight - pDraw->y - pDraw->height) + y; + win_y2 = win_y1 + height - 1; + if (pDraw->type != DRAWABLE_WINDOW) { + from_screen = to_screen = 0; + } + + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + int scr_x1 = dmxScreen->rootXOrigin; + int scr_x2 = dmxScreen->rootXOrigin + dmxScreen->scrnWidth - 1; + int scr_y1 = dmxScreen->rootYOrigin; + int scr_y2 = dmxScreen->rootYOrigin + dmxScreen->scrnHeight - 1; + int wx1, wx2, wy1, wy2; + int sx, sy, sw, sh; + int npixels; + + /* + * find the window portion that is on the current screen + */ + if (pDraw->type == DRAWABLE_WINDOW) { + npixels = intersectRect( scr_x1, scr_x2, scr_y1, scr_y2, + win_x1, win_x2, win_y1, win_y2, + &wx1, &wx2, &wy1, &wy2 ); + } + else { + wx1 = win_x1; + wx2 = win_x2; + wy1 = win_y1; + wy2 = win_y2; + npixels = (wx2-wx1+1) * (wy2-wy1+1); + } + + if (npixels > 0) { + + /* send the request to the back-end server */ + LockDisplay(dpy); + GetReqExtra(GLXSingle,__GLX_PAD(26),be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = X_GLsop_ReadPixels; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); + be_pc = ((GLbyte *)(be_req) + sz_xGLXSingleReq); + + sx = wx1 - pDraw->x; + sy = wy1 - (dmxGlobalHeight - pDraw->y - pDraw->height); + sw = (wx2-wx1+1); + sh = (wy2-wy1+1); + + *(GLint *)(be_pc + 0) = sx; /* x */ + *(GLint *)(be_pc + 4) = sy; /* y */ + *(GLsizei *)(be_pc + 8) = sw; /* width */ + *(GLsizei *)(be_pc + 12) = sh; /* height */ + *(GLenum *)(be_pc + 16) = format; + *(GLenum *)(be_pc + 20) = type; + *(GLboolean *)(be_pc + 24) = swapBytes; + *(GLboolean *)(be_pc + 25) = lsbFirst; + + _XReply(dpy, (xReply*) &be_reply, 0, False); + + if (be_reply.length > 0) { + char *be_buf; + int be_buf_size = be_reply.length << 2; + + be_buf = (char *) malloc( be_buf_size ); + if (be_buf) { + _XRead(dpy, be_buf, be_buf_size); + + /* copy pixels data to the right location of the */ + /* reply buffer */ + if ( type != GL_BITMAP ) { + int pbytes = ebits / 8; + char *dst = buf + (sy-y)*rowsize + (sx-x)*pbytes; + char *src = be_buf; + int pad = (pbytes * sw) % 4; + int r; + + for (r=0; r<sh; r++) { + memcpy( dst, src, pbytes*sw ); + dst += rowsize; + src += (pbytes*sw + (pad ? 4-pad : 0) ); + } + } + else { + /* this is a GL_BITMAP pixel type, should copy bits */ + int r; + int src_rowsize = bits_to_bytes(sw * ebits); + int src_pad = src_rowsize % 4; + if ( src_pad ) { + src_rowsize += (4 - src_pad); + } + + for (r=0; r<sh; r++) { + unsigned char dst_mask = 0x80 >> (sx % 8); + unsigned char src_mask = 0x80; + char *dst = buf + (sy-y+r)*rowsize + (sx-x)/8; + char *src = be_buf + r*src_rowsize; + int b; + + for (b=0; b<sw*ebits; b++) { + if ( *src & src_mask ) { + *dst |= dst_mask; + } + else { + *dst &= ~dst_mask; + } + + if (dst_mask > 1) dst_mask >>= 1; + else { + dst_mask = 0x80; + dst++; + } + + if (src_mask > 1) src_mask >>= 1; + else { + src_mask = 0x80; + src++; + } + } + } + + } + + Xfree( be_buf ); + } + else { + /* Throw data on the floor */ + _XEatData(dpy, be_buf_size); + Xfree( buf ); + return BadAlloc; + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + } /* of npixels > 0 */ + + } /* of for loop */ + + } /* of if buf_size > 0 */ + + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + reply.length = buf_size >> 2; + + if (client->swapped) { + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + } + + WriteToClient(client, sizeof(xGLXReadPixelsReply),(char *)&reply); + if (buf_size > 0) { + WriteToClient(client, buf_size, (char *)buf); + Xfree( buf ); + } + + return Success; +} + +int __glXDispSwap_GetTexImage(__GLXclientState *cl, GLbyte *pc) +{ + __GLX_DECLARE_SWAP_VARIABLES; + GLbyte *lpc = pc; + + lpc += sz_xGLXSingleReq; + __GLX_SWAP_INT(lpc+0); + __GLX_SWAP_INT(lpc+4); + __GLX_SWAP_INT(lpc+8); + __GLX_SWAP_INT(lpc+12); + + /* reverse swapBytes */ + *(GLboolean *)(lpc + 16) = ! *(GLboolean *)(lpc + 16); + + return( __glXForwardPipe0WithReplySwap( cl, pc ) ); +} + +int __glXDispSwap_GetColorTable(__GLXclientState *cl, GLbyte *pc) +{ + __GLX_DECLARE_SWAP_VARIABLES; + GLbyte *lpc = pc; + + lpc += sz_xGLXSingleReq; + __GLX_SWAP_INT(lpc+0); + __GLX_SWAP_INT(lpc+4); + __GLX_SWAP_INT(lpc+8); + + /* reverse swapBytes */ + *(GLboolean *)(lpc + 12) = ! *(GLboolean *)(lpc + 12); + + return( __glXForwardPipe0WithReplySwap( cl, pc ) ); +} + + diff --git a/xorg-server/hw/dmx/glxProxy/glxswap.c b/xorg-server/hw/dmx/glxProxy/glxswap.c index 1e184f914..1471d8b5f 100644 --- a/xorg-server/hw/dmx/glxProxy/glxswap.c +++ b/xorg-server/hw/dmx/glxProxy/glxswap.c @@ -1,538 +1,538 @@ -/* - * Copyright 2003 Red Hat Inc., Raleigh, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 <kem@redhat.com> - * - */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "dmx.h" -#include "dmxwindow.h" -#include "glxserver.h" -#include "glxswap.h" - -extern int __glXDoSwapBuffers(__GLXclientState *cl, XID drawId, - GLXContextTag tag); - -typedef struct _SwapGroup *SwapGroupPtr; - -static Bool SwapBarrierIsReadyToSwap(GLuint barrier); -static void SwapSwapBarrier(GLuint barrier); -static void UpdateSwapBarrierList(GLuint barrier, - SwapGroupPtr pOldSwap, - SwapGroupPtr pNewSwap); - - -/************************************************************************ - * - * Swap Groups - * - ************************************************************************/ - -typedef struct _SwapGroup { - WindowPtr pWin; - SwapGroupPtr pNext; - - Bool swapping; - Bool sleeping; - GLuint barrier; - - XID drawable; - GLXContextTag tag; - __GLXclientState *clState; -} SwapGroupRec; - - -static void SwapSwapGroup(SwapGroupPtr pSwap) -{ - SwapGroupPtr pCur; - - /* All drawables in swap group are ready to swap, so just swap all - * drawables buffers and then wake up those clients that were - * previously sleeping */ - - for (pCur = pSwap; pCur; pCur = pCur->pNext) { - if (pCur->swapping) { - /* Swap pCur's buffers */ - __glXDoSwapBuffers(pCur->clState, pCur->drawable, pCur->tag); - pCur->swapping = FALSE; - } - - /* Wakeup client */ - if (pCur->sleeping) { - ClientWakeup(pCur->clState->client); - pCur->sleeping = FALSE; - } - } -} - -static Bool SwapGroupIsReadyToSwap(SwapGroupPtr pSwap) -{ - Bool isReady = TRUE; - - /* The swap group is ready to swap when all drawables are ready to - * swap. NOTE: A drawable is also ready to swap if it is not - * currently mapped */ - for (; pSwap; pSwap = pSwap->pNext) { - isReady &= (pSwap->swapping || !pSwap->pWin->mapped); - /* FIXME: Should we use pSwap->pWin->mapped or ...->realized ??? */ - } - - return isReady; -} - -static Bool SGSwapCleanup(ClientPtr client, pointer closure) -{ - /* SwapGroupPtr pSwap = (SwapGroupPtr)closure; */ - - /* This should not be called unless the client has died in which - * case we should remove the buffer from the swap list */ - - return TRUE; -} - -int SGSwapBuffers(__GLXclientState *cl, XID drawId, GLXContextTag tag, - DrawablePtr pDraw) -{ - WindowPtr pWin = (WindowPtr)pDraw; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin); - SwapGroupPtr pSwap = pWinPriv->swapGroup; - SwapGroupPtr pCur; - - for (pCur = pSwap; pCur && pCur->pWin != pWin; pCur = pCur->pNext); - if (!pCur) - return BadDrawable; - - pCur->clState = cl; - pCur->drawable = drawId; - pCur->tag = tag; - - /* We are now in the process of swapping */ - pCur->swapping = TRUE; - - if (pSwap->barrier && SwapBarrierIsReadyToSwap(pSwap->barrier)) { - /* The swap group is bound to a barrier and the barrier is ready - * to swap, so swap all the swap groups that are bound to this - * group's swap barrier */ - SwapSwapBarrier(pSwap->barrier); - } else if (!pSwap->barrier && SwapGroupIsReadyToSwap(pSwap)) { - /* Do the swap if the entire swap group is ready to swap and the - * group is not bound to a swap barrier */ - SwapSwapGroup(pSwap); - } else { - /* The swap group/barrier is not yet ready to swap, so put - * client to sleep until the rest are ready to swap */ - ClientSleep(cl->client, SGSwapCleanup, (pointer)pWin); - pCur->sleeping = TRUE; - } - - return Success; -} - -static void SGWindowUnmapped(WindowPtr pWin) -{ - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin); - SwapGroupPtr pSwap = pWinPriv->swapGroup; - - /* Now that one of the windows in the swap group has been unmapped, - * see if the entire swap group/barrier is ready to swap */ - - if (pSwap->barrier && SwapBarrierIsReadyToSwap(pSwap->barrier)) { - SwapSwapBarrier(pSwap->barrier); - } else if (!pSwap->barrier && SwapGroupIsReadyToSwap(pSwap)) { - SwapSwapGroup(pSwap); - } -} - -static void SGWindowDestroyed(WindowPtr pWin) -{ - JoinSwapGroupSGIX((DrawablePtr)pWin, NULL); -} - -static SwapGroupPtr CreateSwapEntry(WindowPtr pWin) -{ - SwapGroupPtr pEntry; - - /* Allocate new swap group */ - pEntry = xalloc(sizeof(*pEntry)); - if (!pEntry) return NULL; - - /* Initialize swap group */ - pEntry->pWin = pWin; - pEntry->pNext = NULL; - pEntry->swapping = FALSE; - pEntry->sleeping = FALSE; - pEntry->barrier = 0; - /* The following are not initialized until SwapBuffers is called: - * pEntry->drawable - * pEntry->tag - * pEntry->clState - */ - - return pEntry; -} - -static void FreeSwapEntry(SwapGroupPtr pEntry) -{ - /* Since we have removed the drawable from its previous swap group - * and it won't be added to another swap group, the only thing that - * we need to do is to make sure that the drawable's client is not - * sleeping. This could happen if one thread is sleeping, while - * another thread called glxJoinSwapGroup(). Note that all sleeping - * threads should also be swapping, but there is a small window in - * the SGSwapBuffer() logic, above, where swapping can be set but - * sleeping is not. We check both independently here just to be - * pedantic. */ - - /* Handle swap buffer request */ - if (pEntry->swapping) - __glXDoSwapBuffers(pEntry->clState, pEntry->drawable, pEntry->tag); - - /* Wake up client */ - if (pEntry->sleeping) - ClientWakeup(pEntry->clState->client); - - /* We can free the pEntry entry since it has already been removed - * from the swap group list and it won't be needed any longer */ - xfree(pEntry); -} - -int JoinSwapGroupSGIX(DrawablePtr pDraw, DrawablePtr pMember) -{ - if (pDraw->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr)pDraw; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin); - SwapGroupPtr pOldSwap = NULL; - SwapGroupPtr pEntry; - - /* If pDraw and pMember are already members of the same swap - * group, just return Success since there is nothing to do */ - for (pEntry = pWinPriv->swapGroup; pEntry; pEntry = pEntry->pNext) - if (pEntry->pWin == (WindowPtr)pMember) - return Success; - - /* Remove pDraw from its current swap group */ - if (pWinPriv->swapGroup) { - SwapGroupPtr pSwapGroup = pWinPriv->swapGroup; - SwapGroupPtr pPrev; - - /* Find old swap entry in swap group and save in pOldSwap - * for later use */ - for (pOldSwap = pWinPriv->swapGroup, pPrev = NULL; - pOldSwap && pOldSwap->pWin != pWin; - pPrev = pOldSwap, pOldSwap = pOldSwap->pNext); - if (!pOldSwap) - return BadDrawable; - - /* Remove pDraw's swap group entry from swap group list */ - if (pPrev) { - pPrev->pNext = pOldSwap->pNext; - } else { - /* pWin is at the head of the swap group list, so we - * need to update all other members of this swap - * group */ - for (pEntry = pOldSwap->pNext; pEntry; pEntry = pEntry->pNext) - DMX_GET_WINDOW_PRIV(pEntry->pWin)->swapGroup - = pOldSwap->pNext; - - /* Update the barrier list as well */ - if (pOldSwap->barrier) - UpdateSwapBarrierList(pOldSwap->barrier, - pOldSwap, pOldSwap->pNext); - - /* Set pSwapGroup to point to the swap group without - * pOldSwap */ - pSwapGroup = pOldSwap->pNext; - } - - /* Check to see if current swap group can now swap since we - * know at this point that pDraw and pMember are guaranteed - * to previously be in different swap groups */ - if (pSwapGroup && SwapGroupIsReadyToSwap(pSwapGroup)) { - SwapSwapGroup(pSwapGroup); - } - - /* Make the old swap entry a standalone group */ - pOldSwap->pNext = NULL; - pOldSwap->barrier = 0; - - /* Reset pWin's swap group */ - pWinPriv->swapGroup = NULL; - pWinPriv->windowDestroyed = NULL; - pWinPriv->windowUnmapped = NULL; - } - - if (!pMember || pMember->type != DRAWABLE_WINDOW) { - /* Free old swap group since it is no longer needed */ - if (pOldSwap) FreeSwapEntry(pOldSwap); - } else if (pDraw == pMember && pOldSwap) { - /* Special case where pDraw was previously created and we - * are now just putting it to its own swap group */ - pWinPriv->swapGroup = pOldSwap; - pWinPriv->windowDestroyed = SGWindowDestroyed; - pWinPriv->windowUnmapped = SGWindowUnmapped; - - /* Check to see if pDraw is ready to swap */ - if (SwapGroupIsReadyToSwap(pOldSwap)) - SwapSwapGroup(pOldSwap); - } else if (pMember->type == DRAWABLE_WINDOW) { - WindowPtr pMemberWin = (WindowPtr)pMember; - dmxWinPrivPtr pMemberPriv = DMX_GET_WINDOW_PRIV(pMemberWin); - SwapGroupPtr pMemberSwapGroup = pMemberPriv->swapGroup; - - /* Finally, how we can add pDraw to pMember's swap group */ - - /* If pMember is not currently in a swap group, then create - * one for it since we are just about to add pDraw to it. */ - if (!pMemberSwapGroup) { - /* Create new swap group */ - pMemberSwapGroup = CreateSwapEntry(pMemberWin); - if (!pMemberSwapGroup) { - if (pOldSwap) FreeSwapEntry(pOldSwap); - return BadAlloc; - } - - /* Set pMember's swap group */ - pMemberPriv->swapGroup = pMemberSwapGroup; - pMemberPriv->windowDestroyed = SGWindowDestroyed; - pMemberPriv->windowUnmapped = SGWindowUnmapped; - } - - /* If pDraw == pMember, that means pDraw was not a member of - * a group previously (or it would have been handled by the - * special case above), so no additional work is required - * since we just created a new swap group for pMember (i.e., - * pDraw). */ - - if (pDraw != pMember) { - /* If pDraw was not previously in a swap group, then create - * an entry for it */ - if (!pOldSwap) { - /* Create new swap group */ - pOldSwap = CreateSwapEntry(pWin); - if (!pOldSwap) { - /* If we just created a swap group for pMember, we - * need to free it here */ - if (pMemberSwapGroup->pNext == NULL) { - FreeSwapEntry(pMemberSwapGroup); - pMemberPriv->swapGroup = NULL; - } - return BadAlloc; - } - } - - /* Find last entry in pMember's swap group */ - for (pEntry = pMemberSwapGroup; - pEntry->pNext; - pEntry = pEntry->pNext); - - /* Add pDraw's swap group entry to pMember's swap group list */ - pEntry->pNext = pOldSwap; - - /* Add pDraw to pMember's swap barrier */ - pOldSwap->barrier = pEntry->barrier; - - /* Set pDraw's swap group */ - pWinPriv->swapGroup = pMemberSwapGroup; - pWinPriv->windowDestroyed = SGWindowDestroyed; - pWinPriv->windowUnmapped = SGWindowUnmapped; - } - } - } - - return Success; -} - - -/************************************************************************ - * - * Swap Barriers - * - ************************************************************************/ - -#define GLX_MAX_SWAP_BARRIERS 10 - -typedef struct _SwapBarrier *SwapBarrierPtr; -typedef struct _SwapBarrier { - SwapGroupPtr pSwap; - SwapBarrierPtr pNext; -} SwapBarrierRec; - -static SwapBarrierPtr SwapBarrierList[GLX_MAX_SWAP_BARRIERS+1]; - -void SwapBarrierInit(void) -{ - int i; - - for (i = 0; i <= GLX_MAX_SWAP_BARRIERS; i++) - SwapBarrierList[i] = NULL; -} - -void SwapBarrierReset(void) -{ - int i; - - for (i = 0; i <= GLX_MAX_SWAP_BARRIERS; i++) { - SwapBarrierPtr pBarrier, pNextBarrier; - for (pBarrier = SwapBarrierList[i]; - pBarrier; - pBarrier = pNextBarrier) { - pNextBarrier = pBarrier->pNext; - xfree(pBarrier); - } - SwapBarrierList[i] = NULL; - } -} - -int QueryMaxSwapBarriersSGIX(int screen) -{ - return GLX_MAX_SWAP_BARRIERS; -} - -static Bool BindSwapGroupToBarrier(GLuint barrier, SwapGroupPtr pSwapGroup) -{ - SwapBarrierPtr pBarrier; - - pBarrier = xalloc(sizeof(*pBarrier)); - if (!pBarrier) return FALSE; - - /* Add the swap group to barrier's list */ - pBarrier->pSwap = pSwapGroup; - pBarrier->pNext = SwapBarrierList[barrier]; - SwapBarrierList[barrier] = pBarrier; - - return TRUE; -} - -static Bool UnbindSwapGroupFromBarrier(GLuint barrier, SwapGroupPtr pSwapGroup) -{ - SwapBarrierPtr pBarrier, pPrevBarrier; - - /* Find the swap group in barrier's list */ - for (pBarrier = SwapBarrierList[barrier], pPrevBarrier = NULL; - pBarrier && pBarrier->pSwap != pSwapGroup; - pPrevBarrier = pBarrier, pBarrier = pBarrier->pNext); - if (!pBarrier) return FALSE; - - /* Remove the swap group from barrier's list */ - if (pPrevBarrier) pPrevBarrier->pNext = pBarrier->pNext; - else SwapBarrierList[barrier] = pBarrier->pNext; - - /* Free memory */ - xfree(pBarrier); - - return TRUE; -} - -static void UpdateSwapBarrierList(GLuint barrier, - SwapGroupPtr pOldSwap, - SwapGroupPtr pNewSwap) -{ - SwapBarrierPtr pBarrier; - - /* If the old swap group is being destroyed, then we need to remove - * the swap group from the list entirely */ - if (!pNewSwap) { - UnbindSwapGroupFromBarrier(barrier, pOldSwap); - return; - } - - /* Otherwise, find the old swap group in the barrier list and change - * it to the new swap group */ - for (pBarrier = SwapBarrierList[barrier]; - pBarrier; - pBarrier = pBarrier->pNext) { - if (pBarrier->pSwap == pOldSwap) { - pBarrier->pSwap = pNewSwap; - return; - } - } -} - -static Bool SwapBarrierIsReadyToSwap(GLuint barrier) -{ - SwapBarrierPtr pBarrier; - Bool isReady = TRUE; - - /* The swap barier is ready to swap when swap groups that are bound - * to barrier are ready to swap */ - for (pBarrier = SwapBarrierList[barrier]; - pBarrier; - pBarrier = pBarrier->pNext) - isReady &= SwapGroupIsReadyToSwap(pBarrier->pSwap); - - return isReady; -} - -static void SwapSwapBarrier(GLuint barrier) -{ - SwapBarrierPtr pBarrier; - - /* Swap each group that is a member of this barrier */ - for (pBarrier = SwapBarrierList[barrier]; - pBarrier; - pBarrier = pBarrier->pNext) - SwapSwapGroup(pBarrier->pSwap); -} - -int BindSwapBarrierSGIX(DrawablePtr pDraw, int barrier) -{ - /* FIXME: Check for errors when pDraw->type != DRAWABLE_WINDOW */ - - if (barrier < 0 || barrier > GLX_MAX_SWAP_BARRIERS) - return BadValue; - - if (pDraw->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr)pDraw; - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin); - SwapGroupPtr pSwapGroup = pWinPriv->swapGroup; - SwapGroupPtr pCur; - - if (!pSwapGroup) return BadDrawable; - if (barrier && pSwapGroup->barrier) return BadValue; - - /* Update the swap barrier list */ - if (barrier) { - if (!BindSwapGroupToBarrier(barrier, pSwapGroup)) - return BadAlloc; - } else { - if (!UnbindSwapGroupFromBarrier(pSwapGroup->barrier, pSwapGroup)) - return BadDrawable; - } - - /* Set the barrier for each member of this swap group */ - for (pCur = pSwapGroup; pCur; pCur = pCur->pNext) - pCur->barrier = barrier; - } - - return Success; -} +/* + * Copyright 2003 Red Hat Inc., Raleigh, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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 <kem@redhat.com> + * + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "dmx.h" +#include "dmxwindow.h" +#include "glxserver.h" +#include "glxswap.h" + +extern int __glXDoSwapBuffers(__GLXclientState *cl, XID drawId, + GLXContextTag tag); + +typedef struct _SwapGroup *SwapGroupPtr; + +static Bool SwapBarrierIsReadyToSwap(GLuint barrier); +static void SwapSwapBarrier(GLuint barrier); +static void UpdateSwapBarrierList(GLuint barrier, + SwapGroupPtr pOldSwap, + SwapGroupPtr pNewSwap); + + +/************************************************************************ + * + * Swap Groups + * + ************************************************************************/ + +typedef struct _SwapGroup { + WindowPtr pWin; + SwapGroupPtr pNext; + + Bool swapping; + Bool sleeping; + GLuint barrier; + + XID drawable; + GLXContextTag tag; + __GLXclientState *clState; +} SwapGroupRec; + + +static void SwapSwapGroup(SwapGroupPtr pSwap) +{ + SwapGroupPtr pCur; + + /* All drawables in swap group are ready to swap, so just swap all + * drawables buffers and then wake up those clients that were + * previously sleeping */ + + for (pCur = pSwap; pCur; pCur = pCur->pNext) { + if (pCur->swapping) { + /* Swap pCur's buffers */ + __glXDoSwapBuffers(pCur->clState, pCur->drawable, pCur->tag); + pCur->swapping = FALSE; + } + + /* Wakeup client */ + if (pCur->sleeping) { + ClientWakeup(pCur->clState->client); + pCur->sleeping = FALSE; + } + } +} + +static Bool SwapGroupIsReadyToSwap(SwapGroupPtr pSwap) +{ + Bool isReady = TRUE; + + /* The swap group is ready to swap when all drawables are ready to + * swap. NOTE: A drawable is also ready to swap if it is not + * currently mapped */ + for (; pSwap; pSwap = pSwap->pNext) { + isReady &= (pSwap->swapping || !pSwap->pWin->mapped); + /* FIXME: Should we use pSwap->pWin->mapped or ...->realized ??? */ + } + + return isReady; +} + +static Bool SGSwapCleanup(ClientPtr client, pointer closure) +{ + /* SwapGroupPtr pSwap = (SwapGroupPtr)closure; */ + + /* This should not be called unless the client has died in which + * case we should remove the buffer from the swap list */ + + return TRUE; +} + +int SGSwapBuffers(__GLXclientState *cl, XID drawId, GLXContextTag tag, + DrawablePtr pDraw) +{ + WindowPtr pWin = (WindowPtr)pDraw; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin); + SwapGroupPtr pSwap = pWinPriv->swapGroup; + SwapGroupPtr pCur; + + for (pCur = pSwap; pCur && pCur->pWin != pWin; pCur = pCur->pNext); + if (!pCur) + return BadDrawable; + + pCur->clState = cl; + pCur->drawable = drawId; + pCur->tag = tag; + + /* We are now in the process of swapping */ + pCur->swapping = TRUE; + + if (pSwap->barrier && SwapBarrierIsReadyToSwap(pSwap->barrier)) { + /* The swap group is bound to a barrier and the barrier is ready + * to swap, so swap all the swap groups that are bound to this + * group's swap barrier */ + SwapSwapBarrier(pSwap->barrier); + } else if (!pSwap->barrier && SwapGroupIsReadyToSwap(pSwap)) { + /* Do the swap if the entire swap group is ready to swap and the + * group is not bound to a swap barrier */ + SwapSwapGroup(pSwap); + } else { + /* The swap group/barrier is not yet ready to swap, so put + * client to sleep until the rest are ready to swap */ + ClientSleep(cl->client, SGSwapCleanup, (pointer)pWin); + pCur->sleeping = TRUE; + } + + return Success; +} + +static void SGWindowUnmapped(WindowPtr pWin) +{ + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin); + SwapGroupPtr pSwap = pWinPriv->swapGroup; + + /* Now that one of the windows in the swap group has been unmapped, + * see if the entire swap group/barrier is ready to swap */ + + if (pSwap->barrier && SwapBarrierIsReadyToSwap(pSwap->barrier)) { + SwapSwapBarrier(pSwap->barrier); + } else if (!pSwap->barrier && SwapGroupIsReadyToSwap(pSwap)) { + SwapSwapGroup(pSwap); + } +} + +static void SGWindowDestroyed(WindowPtr pWin) +{ + JoinSwapGroupSGIX((DrawablePtr)pWin, NULL); +} + +static SwapGroupPtr CreateSwapEntry(WindowPtr pWin) +{ + SwapGroupPtr pEntry; + + /* Allocate new swap group */ + pEntry = malloc(sizeof(*pEntry)); + if (!pEntry) return NULL; + + /* Initialize swap group */ + pEntry->pWin = pWin; + pEntry->pNext = NULL; + pEntry->swapping = FALSE; + pEntry->sleeping = FALSE; + pEntry->barrier = 0; + /* The following are not initialized until SwapBuffers is called: + * pEntry->drawable + * pEntry->tag + * pEntry->clState + */ + + return pEntry; +} + +static void FreeSwapEntry(SwapGroupPtr pEntry) +{ + /* Since we have removed the drawable from its previous swap group + * and it won't be added to another swap group, the only thing that + * we need to do is to make sure that the drawable's client is not + * sleeping. This could happen if one thread is sleeping, while + * another thread called glxJoinSwapGroup(). Note that all sleeping + * threads should also be swapping, but there is a small window in + * the SGSwapBuffer() logic, above, where swapping can be set but + * sleeping is not. We check both independently here just to be + * pedantic. */ + + /* Handle swap buffer request */ + if (pEntry->swapping) + __glXDoSwapBuffers(pEntry->clState, pEntry->drawable, pEntry->tag); + + /* Wake up client */ + if (pEntry->sleeping) + ClientWakeup(pEntry->clState->client); + + /* We can free the pEntry entry since it has already been removed + * from the swap group list and it won't be needed any longer */ + free(pEntry); +} + +int JoinSwapGroupSGIX(DrawablePtr pDraw, DrawablePtr pMember) +{ + if (pDraw->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDraw; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin); + SwapGroupPtr pOldSwap = NULL; + SwapGroupPtr pEntry; + + /* If pDraw and pMember are already members of the same swap + * group, just return Success since there is nothing to do */ + for (pEntry = pWinPriv->swapGroup; pEntry; pEntry = pEntry->pNext) + if (pEntry->pWin == (WindowPtr)pMember) + return Success; + + /* Remove pDraw from its current swap group */ + if (pWinPriv->swapGroup) { + SwapGroupPtr pSwapGroup = pWinPriv->swapGroup; + SwapGroupPtr pPrev; + + /* Find old swap entry in swap group and save in pOldSwap + * for later use */ + for (pOldSwap = pWinPriv->swapGroup, pPrev = NULL; + pOldSwap && pOldSwap->pWin != pWin; + pPrev = pOldSwap, pOldSwap = pOldSwap->pNext); + if (!pOldSwap) + return BadDrawable; + + /* Remove pDraw's swap group entry from swap group list */ + if (pPrev) { + pPrev->pNext = pOldSwap->pNext; + } else { + /* pWin is at the head of the swap group list, so we + * need to update all other members of this swap + * group */ + for (pEntry = pOldSwap->pNext; pEntry; pEntry = pEntry->pNext) + DMX_GET_WINDOW_PRIV(pEntry->pWin)->swapGroup + = pOldSwap->pNext; + + /* Update the barrier list as well */ + if (pOldSwap->barrier) + UpdateSwapBarrierList(pOldSwap->barrier, + pOldSwap, pOldSwap->pNext); + + /* Set pSwapGroup to point to the swap group without + * pOldSwap */ + pSwapGroup = pOldSwap->pNext; + } + + /* Check to see if current swap group can now swap since we + * know at this point that pDraw and pMember are guaranteed + * to previously be in different swap groups */ + if (pSwapGroup && SwapGroupIsReadyToSwap(pSwapGroup)) { + SwapSwapGroup(pSwapGroup); + } + + /* Make the old swap entry a standalone group */ + pOldSwap->pNext = NULL; + pOldSwap->barrier = 0; + + /* Reset pWin's swap group */ + pWinPriv->swapGroup = NULL; + pWinPriv->windowDestroyed = NULL; + pWinPriv->windowUnmapped = NULL; + } + + if (!pMember || pMember->type != DRAWABLE_WINDOW) { + /* Free old swap group since it is no longer needed */ + if (pOldSwap) FreeSwapEntry(pOldSwap); + } else if (pDraw == pMember && pOldSwap) { + /* Special case where pDraw was previously created and we + * are now just putting it to its own swap group */ + pWinPriv->swapGroup = pOldSwap; + pWinPriv->windowDestroyed = SGWindowDestroyed; + pWinPriv->windowUnmapped = SGWindowUnmapped; + + /* Check to see if pDraw is ready to swap */ + if (SwapGroupIsReadyToSwap(pOldSwap)) + SwapSwapGroup(pOldSwap); + } else if (pMember->type == DRAWABLE_WINDOW) { + WindowPtr pMemberWin = (WindowPtr)pMember; + dmxWinPrivPtr pMemberPriv = DMX_GET_WINDOW_PRIV(pMemberWin); + SwapGroupPtr pMemberSwapGroup = pMemberPriv->swapGroup; + + /* Finally, how we can add pDraw to pMember's swap group */ + + /* If pMember is not currently in a swap group, then create + * one for it since we are just about to add pDraw to it. */ + if (!pMemberSwapGroup) { + /* Create new swap group */ + pMemberSwapGroup = CreateSwapEntry(pMemberWin); + if (!pMemberSwapGroup) { + if (pOldSwap) FreeSwapEntry(pOldSwap); + return BadAlloc; + } + + /* Set pMember's swap group */ + pMemberPriv->swapGroup = pMemberSwapGroup; + pMemberPriv->windowDestroyed = SGWindowDestroyed; + pMemberPriv->windowUnmapped = SGWindowUnmapped; + } + + /* If pDraw == pMember, that means pDraw was not a member of + * a group previously (or it would have been handled by the + * special case above), so no additional work is required + * since we just created a new swap group for pMember (i.e., + * pDraw). */ + + if (pDraw != pMember) { + /* If pDraw was not previously in a swap group, then create + * an entry for it */ + if (!pOldSwap) { + /* Create new swap group */ + pOldSwap = CreateSwapEntry(pWin); + if (!pOldSwap) { + /* If we just created a swap group for pMember, we + * need to free it here */ + if (pMemberSwapGroup->pNext == NULL) { + FreeSwapEntry(pMemberSwapGroup); + pMemberPriv->swapGroup = NULL; + } + return BadAlloc; + } + } + + /* Find last entry in pMember's swap group */ + for (pEntry = pMemberSwapGroup; + pEntry->pNext; + pEntry = pEntry->pNext); + + /* Add pDraw's swap group entry to pMember's swap group list */ + pEntry->pNext = pOldSwap; + + /* Add pDraw to pMember's swap barrier */ + pOldSwap->barrier = pEntry->barrier; + + /* Set pDraw's swap group */ + pWinPriv->swapGroup = pMemberSwapGroup; + pWinPriv->windowDestroyed = SGWindowDestroyed; + pWinPriv->windowUnmapped = SGWindowUnmapped; + } + } + } + + return Success; +} + + +/************************************************************************ + * + * Swap Barriers + * + ************************************************************************/ + +#define GLX_MAX_SWAP_BARRIERS 10 + +typedef struct _SwapBarrier *SwapBarrierPtr; +typedef struct _SwapBarrier { + SwapGroupPtr pSwap; + SwapBarrierPtr pNext; +} SwapBarrierRec; + +static SwapBarrierPtr SwapBarrierList[GLX_MAX_SWAP_BARRIERS+1]; + +void SwapBarrierInit(void) +{ + int i; + + for (i = 0; i <= GLX_MAX_SWAP_BARRIERS; i++) + SwapBarrierList[i] = NULL; +} + +void SwapBarrierReset(void) +{ + int i; + + for (i = 0; i <= GLX_MAX_SWAP_BARRIERS; i++) { + SwapBarrierPtr pBarrier, pNextBarrier; + for (pBarrier = SwapBarrierList[i]; + pBarrier; + pBarrier = pNextBarrier) { + pNextBarrier = pBarrier->pNext; + free(pBarrier); + } + SwapBarrierList[i] = NULL; + } +} + +int QueryMaxSwapBarriersSGIX(int screen) +{ + return GLX_MAX_SWAP_BARRIERS; +} + +static Bool BindSwapGroupToBarrier(GLuint barrier, SwapGroupPtr pSwapGroup) +{ + SwapBarrierPtr pBarrier; + + pBarrier = malloc(sizeof(*pBarrier)); + if (!pBarrier) return FALSE; + + /* Add the swap group to barrier's list */ + pBarrier->pSwap = pSwapGroup; + pBarrier->pNext = SwapBarrierList[barrier]; + SwapBarrierList[barrier] = pBarrier; + + return TRUE; +} + +static Bool UnbindSwapGroupFromBarrier(GLuint barrier, SwapGroupPtr pSwapGroup) +{ + SwapBarrierPtr pBarrier, pPrevBarrier; + + /* Find the swap group in barrier's list */ + for (pBarrier = SwapBarrierList[barrier], pPrevBarrier = NULL; + pBarrier && pBarrier->pSwap != pSwapGroup; + pPrevBarrier = pBarrier, pBarrier = pBarrier->pNext); + if (!pBarrier) return FALSE; + + /* Remove the swap group from barrier's list */ + if (pPrevBarrier) pPrevBarrier->pNext = pBarrier->pNext; + else SwapBarrierList[barrier] = pBarrier->pNext; + + /* Free memory */ + free(pBarrier); + + return TRUE; +} + +static void UpdateSwapBarrierList(GLuint barrier, + SwapGroupPtr pOldSwap, + SwapGroupPtr pNewSwap) +{ + SwapBarrierPtr pBarrier; + + /* If the old swap group is being destroyed, then we need to remove + * the swap group from the list entirely */ + if (!pNewSwap) { + UnbindSwapGroupFromBarrier(barrier, pOldSwap); + return; + } + + /* Otherwise, find the old swap group in the barrier list and change + * it to the new swap group */ + for (pBarrier = SwapBarrierList[barrier]; + pBarrier; + pBarrier = pBarrier->pNext) { + if (pBarrier->pSwap == pOldSwap) { + pBarrier->pSwap = pNewSwap; + return; + } + } +} + +static Bool SwapBarrierIsReadyToSwap(GLuint barrier) +{ + SwapBarrierPtr pBarrier; + Bool isReady = TRUE; + + /* The swap barier is ready to swap when swap groups that are bound + * to barrier are ready to swap */ + for (pBarrier = SwapBarrierList[barrier]; + pBarrier; + pBarrier = pBarrier->pNext) + isReady &= SwapGroupIsReadyToSwap(pBarrier->pSwap); + + return isReady; +} + +static void SwapSwapBarrier(GLuint barrier) +{ + SwapBarrierPtr pBarrier; + + /* Swap each group that is a member of this barrier */ + for (pBarrier = SwapBarrierList[barrier]; + pBarrier; + pBarrier = pBarrier->pNext) + SwapSwapGroup(pBarrier->pSwap); +} + +int BindSwapBarrierSGIX(DrawablePtr pDraw, int barrier) +{ + /* FIXME: Check for errors when pDraw->type != DRAWABLE_WINDOW */ + + if (barrier < 0 || barrier > GLX_MAX_SWAP_BARRIERS) + return BadValue; + + if (pDraw->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDraw; + dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin); + SwapGroupPtr pSwapGroup = pWinPriv->swapGroup; + SwapGroupPtr pCur; + + if (!pSwapGroup) return BadDrawable; + if (barrier && pSwapGroup->barrier) return BadValue; + + /* Update the swap barrier list */ + if (barrier) { + if (!BindSwapGroupToBarrier(barrier, pSwapGroup)) + return BadAlloc; + } else { + if (!UnbindSwapGroupFromBarrier(pSwapGroup->barrier, pSwapGroup)) + return BadDrawable; + } + + /* Set the barrier for each member of this swap group */ + for (pCur = pSwapGroup; pCur; pCur = pCur->pNext) + pCur->barrier = barrier; + } + + return Success; +} diff --git a/xorg-server/hw/dmx/glxProxy/glxutil.c b/xorg-server/hw/dmx/glxProxy/glxutil.c index d0ce50486..2460ed0dc 100644 --- a/xorg-server/hw/dmx/glxProxy/glxutil.c +++ b/xorg-server/hw/dmx/glxProxy/glxutil.c @@ -1,111 +1,111 @@ -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#include "glxserver.h" -#include <GL/glxtokens.h> -#include <pixmapstr.h> -#include <windowstr.h> -#include "glxutil.h" -#include <stdlib.h> - -/************************************************************************/ - -void __glXNop(void) {} - -/************************************************************************/ - -/* Memory Allocation for GLX */ - -void * -__glXMalloc(size_t size) -{ - void *addr; - - if (size == 0) { - return NULL; - } - addr = malloc(size); - if (addr == NULL) { - /* XXX: handle out of memory error */ - return NULL; - } - return addr; -} - -void * -__glXCalloc(size_t numElements, size_t elementSize) -{ - void *addr; - size_t size; - - if ((numElements == 0) || (elementSize == 0)) { - return NULL; - } - addr = calloc(numElements, elementSize); - if (addr == NULL) { - /* XXX: handle out of memory error */ - return NULL; - } - return addr; -} - -void * -__glXRealloc(void *addr, size_t newSize) -{ - void *newAddr; - - if (addr) { - if (newSize == 0) { - xfree(addr); - return NULL; - } else { - newAddr = realloc(addr, newSize); - } - } else { - if (newSize == 0) { - return NULL; - } else { - newAddr = malloc(newSize); - } - } - if (newAddr == NULL) { - return NULL; /* XXX: out of memory */ - } - - return newAddr; -} - -void -__glXFree(void *addr) -{ - if (addr) { - free(addr); - } -} +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#include "glxserver.h" +#include <GL/glxtokens.h> +#include <pixmapstr.h> +#include <windowstr.h> +#include "glxutil.h" +#include <stdlib.h> + +/************************************************************************/ + +void __glXNop(void) {} + +/************************************************************************/ + +/* Memory Allocation for GLX */ + +void * +__glXMalloc(size_t size) +{ + void *addr; + + if (size == 0) { + return NULL; + } + addr = malloc(size); + if (addr == NULL) { + /* XXX: handle out of memory error */ + return NULL; + } + return addr; +} + +void * +__glXCalloc(size_t numElements, size_t elementSize) +{ + void *addr; + size_t size; + + if ((numElements == 0) || (elementSize == 0)) { + return NULL; + } + addr = calloc(numElements, elementSize); + if (addr == NULL) { + /* XXX: handle out of memory error */ + return NULL; + } + return addr; +} + +void * +__glXRealloc(void *addr, size_t newSize) +{ + void *newAddr; + + if (addr) { + if (newSize == 0) { + free(addr); + return NULL; + } else { + newAddr = realloc(addr, newSize); + } + } else { + if (newSize == 0) { + return NULL; + } else { + newAddr = malloc(newSize); + } + } + if (newAddr == NULL) { + return NULL; /* XXX: out of memory */ + } + + return newAddr; +} + +void +__glXFree(void *addr) +{ + if (addr) { + free(addr); + } +} diff --git a/xorg-server/hw/dmx/glxProxy/glxvendor.c b/xorg-server/hw/dmx/glxProxy/glxvendor.c index 6b1f9a820..e8460fad8 100644 --- a/xorg-server/hw/dmx/glxProxy/glxvendor.c +++ b/xorg-server/hw/dmx/glxProxy/glxvendor.c @@ -1,582 +1,582 @@ -/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED */ -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "dmx.h" -#include "dmxwindow.h" -#include "dmxpixmap.h" -#include "dmxfont.h" - -#undef Xmalloc -#undef Xcalloc -#undef Xrealloc -#undef Xfree - -#include "glxserver.h" -#include "glxext.h" -#include "g_disptab.h" -/* #include "g_disptab_EXT.h" */ -#include "unpack.h" -#include "glxutil.h" - -#include "GL/glxproto.h" - -#ifdef PANORAMIX -#include "panoramiXsrv.h" -#endif - -/* - * GetReqVendorPrivate - this is the equivalent of GetReq macro - * from Xlibint.h but it does not set the reqType field (the opcode). - * this is because the GL single opcodes has different naming convension - * the other X opcodes (ie. X_GLsop_GetFloatv). - */ -#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) -#define GetReqVendorPrivate(name, req) \ - WORD64ALIGN\ - if ((dpy->bufptr + SIZEOF(x##name##Req)) > dpy->bufmax)\ - _XFlush(dpy);\ - req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\ - req->length = (SIZEOF(x##name##Req))>>2;\ - dpy->bufptr += SIZEOF(x##name##Req);\ - dpy->request++ - -#else /* non-ANSI C uses empty comment instead of "##" for token concatenation */ -#define GetReqVendorPrivate(name, req) \ - WORD64ALIGN\ - if ((dpy->bufptr + SIZEOF(x/**/name/**/Req)) > dpy->bufmax)\ - _XFlush(dpy);\ - req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\ - req->length = (SIZEOF(x/**/name/**/Req))>>2;\ - dpy->bufptr += SIZEOF(x/**/name/**/Req);\ - dpy->request++ -#endif - -extern Display *GetBackEndDisplay( __GLXclientState *cl, int s ); -extern int GetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s); - -static int swap_vec_element_size = 0; - -static void SendSwappedReply( ClientPtr client, - xGLXVendorPrivReply *reply, - char *buf, - int buf_size ) -{ - __GLX_DECLARE_SWAP_VARIABLES; - __GLX_SWAP_SHORT(&reply->sequenceNumber); - __GLX_SWAP_INT(&reply->length); - __GLX_SWAP_INT(&reply->retval); - __GLX_SWAP_INT(&reply->size); - - if ( (buf_size == 0) && (swap_vec_element_size > 0) ) { - /* - * the reply has single component - need to swap pad3 - */ - if (swap_vec_element_size == 2) { - __GLX_SWAP_SHORT(&reply->pad3); - } - else if (swap_vec_element_size == 4) { - __GLX_SWAP_INT(&reply->pad3); - __GLX_SWAP_INT(&reply->pad4); - } - else if (swap_vec_element_size == 8) { - __GLX_SWAP_DOUBLE(&reply->pad3); - } - } - else if ( (buf_size > 0) && (swap_vec_element_size > 0) ) { - /* - * the reply has vector of elements which needs to be swapped - */ - int vsize = buf_size / swap_vec_element_size; - char *p = buf; - int i; - - for (i=0; i<vsize; i++) { - if (swap_vec_element_size == 2) { - __GLX_SWAP_SHORT(p); - } - else if (swap_vec_element_size == 4) { - __GLX_SWAP_INT(p); - } - else if (swap_vec_element_size == 8) { - __GLX_SWAP_DOUBLE(p); - } - - p += swap_vec_element_size; - } - - __GLX_SWAP_INT(&reply->pad3); - __GLX_SWAP_INT(&reply->pad4); - __GLX_SWAP_INT(&reply->pad5); - __GLX_SWAP_INT(&reply->pad6); - - } - - WriteToClient(client, sizeof(xGLXVendorPrivReply),(char *)reply); - if (buf_size > 0) - WriteToClient(client, buf_size, (char *)buf); - -} - -int __glXVForwardSingleReq( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - xGLXVendorPrivateReq *be_req; - __GLXcontext *glxc; - int from_screen = 0; - int to_screen = 0; - int buf_size; - int s; - - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return 0; - } - from_screen = to_screen = glxc->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - pc += sz_xGLXVendorPrivateReq; - buf_size = (req->length << 2) - sz_xGLXVendorPrivateReq; - - /* - * just forward the request to back-end server(s) - */ - for (s=from_screen; s<=to_screen; s++) { - DMXScreenInfo *dmxScreen = &dmxScreens[s]; - Display *dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReqVendorPrivate(GLXVendorPrivate,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = req->glxCode; - be_req->length = req->length; - be_req->vendorCode = req->vendorCode; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); - if (buf_size > 0) - _XSend(dpy, (const char *)pc, buf_size); - UnlockDisplay(dpy); - SyncHandle(); - } - - return Success; -} - -int __glXVForwardPipe0WithReply( __GLXclientState *cl, GLbyte *pc ) -{ - ClientPtr client = cl->client; - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - xGLXVendorPrivateReq *be_req; - xGLXVendorPrivReply reply; - xGLXVendorPrivReply be_reply; - __GLXcontext *glxc; - int buf_size; - char *be_buf; - int be_buf_size; - DMXScreenInfo *dmxScreen; - Display *dpy; - - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return __glXBadContext; - } - - pc += sz_xGLXVendorPrivateReq; - buf_size = (req->length << 2) - sz_xGLXVendorPrivateReq; - - dmxScreen = &dmxScreens[glxc->pScreen->myNum]; - dpy = GetBackEndDisplay(cl, glxc->pScreen->myNum); - - /* - * send the request to the first back-end server - */ - LockDisplay(dpy); - GetReqVendorPrivate(GLXVendorPrivate,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = req->glxCode; - be_req->length = req->length; - be_req->vendorCode = req->vendorCode; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag, glxc->pScreen->myNum); - if (buf_size > 0) - _XSend(dpy, (const char *)pc, buf_size); - - /* - * get the reply from the back-end server - */ - _XReply(dpy, (xReply*) &be_reply, 0, False); - be_buf_size = be_reply.length << 2; - if (be_buf_size > 0) { - be_buf = (char *)Xalloc( be_buf_size ); - if (be_buf) { - _XRead(dpy, be_buf, be_buf_size); - } - else { - /* Throw data on the floor */ - _XEatData(dpy, be_buf_size); - return BadAlloc; - } - } - - UnlockDisplay(dpy); - SyncHandle(); - - /* - * send the reply to the client - */ - memcpy( &reply, &be_reply, sz_xGLXVendorPrivReply ); - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - - if (client->swapped) { - SendSwappedReply( client, &reply, be_buf, be_buf_size ); - } - else { - WriteToClient(client, sizeof(xGLXVendorPrivReply),(char *)&reply); - if (be_buf_size > 0) - WriteToClient(client, be_buf_size, (char *)be_buf); - } - - if (be_buf_size > 0) Xfree(be_buf); - - return Success; -} - -int __glXVForwardAllWithReply( __GLXclientState *cl, GLbyte *pc ) -{ - ClientPtr client = cl->client; - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - xGLXVendorPrivateReq *be_req; - xGLXVendorPrivReply reply; - xGLXVendorPrivReply be_reply; - __GLXcontext *glxc; - int buf_size; - char *be_buf; - int be_buf_size; - int from_screen = 0; - int to_screen = 0; - int s; - - DMXScreenInfo *dmxScreen; - Display *dpy; - - glxc = __glXLookupContextByTag(cl, req->contextTag); - if (!glxc) { - return 0; - } - from_screen = to_screen = glxc->pScreen->myNum; - -#ifdef PANORAMIX - if (!noPanoramiXExtension) { - from_screen = 0; - to_screen = screenInfo.numScreens - 1; - } -#endif - - pc += sz_xGLXVendorPrivateReq; - buf_size = (req->length << 2) - sz_xGLXVendorPrivateReq; - - /* - * send the request to the first back-end server(s) - */ - for (s=to_screen; s>=from_screen; s--) { - dmxScreen = &dmxScreens[s]; - dpy = GetBackEndDisplay(cl,s); - - LockDisplay(dpy); - GetReqVendorPrivate(GLXVendorPrivate,be_req); - be_req->reqType = dmxScreen->glxMajorOpcode; - be_req->glxCode = req->glxCode; - be_req->length = req->length; - be_req->vendorCode = req->vendorCode; - be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); - if (buf_size > 0) - _XSend(dpy, (const char *)pc, buf_size); - - /* - * get the reply from the back-end server - */ - _XReply(dpy, (xReply*) &be_reply, 0, False); - be_buf_size = be_reply.length << 2; - if (be_buf_size > 0) { - be_buf = (char *)Xalloc( be_buf_size ); - if (be_buf) { - _XRead(dpy, be_buf, be_buf_size); - } - else { - /* Throw data on the floor */ - _XEatData(dpy, be_buf_size); - return BadAlloc; - } - } - - UnlockDisplay(dpy); - SyncHandle(); - - if (s > from_screen && be_buf_size > 0) { - Xfree(be_buf); - } - } - - /* - * send the reply to the client - */ - memcpy( &reply, &be_reply, sz_xGLXVendorPrivReply ); - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - - if (client->swapped) { - SendSwappedReply( client, &reply, be_buf, be_buf_size ); - } - else { - WriteToClient(client, sizeof(xGLXVendorPrivReply),(char *)&reply); - if (be_buf_size > 0) - WriteToClient(client, be_buf_size, (char *)be_buf); - } - - if (be_buf_size > 0) Xfree(be_buf); - - return Success; -} - -int __glXVForwardSingleReqSwap( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 0; - - return( __glXVForwardSingleReq( cl, pc ) ); -} - -int __glXVForwardPipe0WithReplySwap( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 0; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXVendorPrivateReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXVendorPrivateReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXVForwardPipe0WithReply( cl, pc ) ); -} - -int __glXVForwardPipe0WithReplySwapsv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 2; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXVendorPrivateReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXVendorPrivateReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXVForwardPipe0WithReply( cl, pc ) ); -} - -int __glXVForwardPipe0WithReplySwapiv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 4; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXVendorPrivateReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXVendorPrivateReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXVForwardPipe0WithReply( cl, pc ) ); -} - -int __glXVForwardPipe0WithReplySwapdv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 8; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXVendorPrivateReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXVendorPrivateReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXVForwardPipe0WithReply( cl, pc ) ); -} - -int __glXVForwardAllWithReplySwap( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 0; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXVendorPrivateReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXVendorPrivateReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXVForwardAllWithReply( cl, pc ) ); -} - -int __glXVForwardAllWithReplySwapsv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 2; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXVendorPrivateReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXVendorPrivateReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXVForwardAllWithReply( cl, pc ) ); -} - -int __glXVForwardAllWithReplySwapiv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 4; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXVendorPrivateReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXVendorPrivateReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXVForwardAllWithReply( cl, pc ) ); -} - -int __glXVForwardAllWithReplySwapdv( __GLXclientState *cl, GLbyte *pc ) -{ - xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT(&req->length); - __GLX_SWAP_INT(&req->vendorCode); - __GLX_SWAP_INT(&req->contextTag); - - swap_vec_element_size = 8; - - /* - * swap extra data in request - assuming all data - * (if available) are arrays of 4 bytes components ! - */ - if (req->length > sz_xGLXVendorPrivateReq/4) { - int *data = (int *)(req+1); - int count = req->length - sz_xGLXVendorPrivateReq/4; - __GLX_SWAP_INT_ARRAY(data, count ); - } - - return( __glXVForwardAllWithReply( cl, pc ) ); -} - +/* DO NOT EDIT - THIS FILE IS AUTOMATICALLY GENERATED */ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "dmx.h" +#include "dmxwindow.h" +#include "dmxpixmap.h" +#include "dmxfont.h" + +#undef Xmalloc +#undef Xcalloc +#undef Xrealloc +#undef Xfree + +#include "glxserver.h" +#include "glxext.h" +#include "g_disptab.h" +/* #include "g_disptab_EXT.h" */ +#include "unpack.h" +#include "glxutil.h" + +#include "GL/glxproto.h" + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +/* + * GetReqVendorPrivate - this is the equivalent of GetReq macro + * from Xlibint.h but it does not set the reqType field (the opcode). + * this is because the GL single opcodes has different naming convension + * the other X opcodes (ie. X_GLsop_GetFloatv). + */ +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define GetReqVendorPrivate(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(x##name##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\ + req->length = (SIZEOF(x##name##Req))>>2;\ + dpy->bufptr += SIZEOF(x##name##Req);\ + dpy->request++ + +#else /* non-ANSI C uses empty comment instead of "##" for token concatenation */ +#define GetReqVendorPrivate(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(x/**/name/**/Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\ + req->length = (SIZEOF(x/**/name/**/Req))>>2;\ + dpy->bufptr += SIZEOF(x/**/name/**/Req);\ + dpy->request++ +#endif + +extern Display *GetBackEndDisplay( __GLXclientState *cl, int s ); +extern int GetCurrentBackEndTag(__GLXclientState *cl, GLXContextTag tag, int s); + +static int swap_vec_element_size = 0; + +static void SendSwappedReply( ClientPtr client, + xGLXVendorPrivReply *reply, + char *buf, + int buf_size ) +{ + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_SWAP_SHORT(&reply->sequenceNumber); + __GLX_SWAP_INT(&reply->length); + __GLX_SWAP_INT(&reply->retval); + __GLX_SWAP_INT(&reply->size); + + if ( (buf_size == 0) && (swap_vec_element_size > 0) ) { + /* + * the reply has single component - need to swap pad3 + */ + if (swap_vec_element_size == 2) { + __GLX_SWAP_SHORT(&reply->pad3); + } + else if (swap_vec_element_size == 4) { + __GLX_SWAP_INT(&reply->pad3); + __GLX_SWAP_INT(&reply->pad4); + } + else if (swap_vec_element_size == 8) { + __GLX_SWAP_DOUBLE(&reply->pad3); + } + } + else if ( (buf_size > 0) && (swap_vec_element_size > 0) ) { + /* + * the reply has vector of elements which needs to be swapped + */ + int vsize = buf_size / swap_vec_element_size; + char *p = buf; + int i; + + for (i=0; i<vsize; i++) { + if (swap_vec_element_size == 2) { + __GLX_SWAP_SHORT(p); + } + else if (swap_vec_element_size == 4) { + __GLX_SWAP_INT(p); + } + else if (swap_vec_element_size == 8) { + __GLX_SWAP_DOUBLE(p); + } + + p += swap_vec_element_size; + } + + __GLX_SWAP_INT(&reply->pad3); + __GLX_SWAP_INT(&reply->pad4); + __GLX_SWAP_INT(&reply->pad5); + __GLX_SWAP_INT(&reply->pad6); + + } + + WriteToClient(client, sizeof(xGLXVendorPrivReply),(char *)reply); + if (buf_size > 0) + WriteToClient(client, buf_size, (char *)buf); + +} + +int __glXVForwardSingleReq( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + xGLXVendorPrivateReq *be_req; + __GLXcontext *glxc; + int from_screen = 0; + int to_screen = 0; + int buf_size; + int s; + + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return 0; + } + from_screen = to_screen = glxc->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + pc += sz_xGLXVendorPrivateReq; + buf_size = (req->length << 2) - sz_xGLXVendorPrivateReq; + + /* + * just forward the request to back-end server(s) + */ + for (s=from_screen; s<=to_screen; s++) { + DMXScreenInfo *dmxScreen = &dmxScreens[s]; + Display *dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReqVendorPrivate(GLXVendorPrivate,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = req->glxCode; + be_req->length = req->length; + be_req->vendorCode = req->vendorCode; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); + if (buf_size > 0) + _XSend(dpy, (const char *)pc, buf_size); + UnlockDisplay(dpy); + SyncHandle(); + } + + return Success; +} + +int __glXVForwardPipe0WithReply( __GLXclientState *cl, GLbyte *pc ) +{ + ClientPtr client = cl->client; + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + xGLXVendorPrivateReq *be_req; + xGLXVendorPrivReply reply; + xGLXVendorPrivReply be_reply; + __GLXcontext *glxc; + int buf_size; + char *be_buf; + int be_buf_size; + DMXScreenInfo *dmxScreen; + Display *dpy; + + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return __glXBadContext; + } + + pc += sz_xGLXVendorPrivateReq; + buf_size = (req->length << 2) - sz_xGLXVendorPrivateReq; + + dmxScreen = &dmxScreens[glxc->pScreen->myNum]; + dpy = GetBackEndDisplay(cl, glxc->pScreen->myNum); + + /* + * send the request to the first back-end server + */ + LockDisplay(dpy); + GetReqVendorPrivate(GLXVendorPrivate,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = req->glxCode; + be_req->length = req->length; + be_req->vendorCode = req->vendorCode; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag, glxc->pScreen->myNum); + if (buf_size > 0) + _XSend(dpy, (const char *)pc, buf_size); + + /* + * get the reply from the back-end server + */ + _XReply(dpy, (xReply*) &be_reply, 0, False); + be_buf_size = be_reply.length << 2; + if (be_buf_size > 0) { + be_buf = (char *)malloc( be_buf_size ); + if (be_buf) { + _XRead(dpy, be_buf, be_buf_size); + } + else { + /* Throw data on the floor */ + _XEatData(dpy, be_buf_size); + return BadAlloc; + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + /* + * send the reply to the client + */ + memcpy( &reply, &be_reply, sz_xGLXVendorPrivReply ); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (client->swapped) { + SendSwappedReply( client, &reply, be_buf, be_buf_size ); + } + else { + WriteToClient(client, sizeof(xGLXVendorPrivReply),(char *)&reply); + if (be_buf_size > 0) + WriteToClient(client, be_buf_size, (char *)be_buf); + } + + if (be_buf_size > 0) Xfree(be_buf); + + return Success; +} + +int __glXVForwardAllWithReply( __GLXclientState *cl, GLbyte *pc ) +{ + ClientPtr client = cl->client; + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + xGLXVendorPrivateReq *be_req; + xGLXVendorPrivReply reply; + xGLXVendorPrivReply be_reply; + __GLXcontext *glxc; + int buf_size; + char *be_buf; + int be_buf_size; + int from_screen = 0; + int to_screen = 0; + int s; + + DMXScreenInfo *dmxScreen; + Display *dpy; + + glxc = __glXLookupContextByTag(cl, req->contextTag); + if (!glxc) { + return 0; + } + from_screen = to_screen = glxc->pScreen->myNum; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + from_screen = 0; + to_screen = screenInfo.numScreens - 1; + } +#endif + + pc += sz_xGLXVendorPrivateReq; + buf_size = (req->length << 2) - sz_xGLXVendorPrivateReq; + + /* + * send the request to the first back-end server(s) + */ + for (s=to_screen; s>=from_screen; s--) { + dmxScreen = &dmxScreens[s]; + dpy = GetBackEndDisplay(cl,s); + + LockDisplay(dpy); + GetReqVendorPrivate(GLXVendorPrivate,be_req); + be_req->reqType = dmxScreen->glxMajorOpcode; + be_req->glxCode = req->glxCode; + be_req->length = req->length; + be_req->vendorCode = req->vendorCode; + be_req->contextTag = GetCurrentBackEndTag(cl,req->contextTag,s); + if (buf_size > 0) + _XSend(dpy, (const char *)pc, buf_size); + + /* + * get the reply from the back-end server + */ + _XReply(dpy, (xReply*) &be_reply, 0, False); + be_buf_size = be_reply.length << 2; + if (be_buf_size > 0) { + be_buf = (char *)malloc( be_buf_size ); + if (be_buf) { + _XRead(dpy, be_buf, be_buf_size); + } + else { + /* Throw data on the floor */ + _XEatData(dpy, be_buf_size); + return BadAlloc; + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + if (s > from_screen && be_buf_size > 0) { + Xfree(be_buf); + } + } + + /* + * send the reply to the client + */ + memcpy( &reply, &be_reply, sz_xGLXVendorPrivReply ); + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (client->swapped) { + SendSwappedReply( client, &reply, be_buf, be_buf_size ); + } + else { + WriteToClient(client, sizeof(xGLXVendorPrivReply),(char *)&reply); + if (be_buf_size > 0) + WriteToClient(client, be_buf_size, (char *)be_buf); + } + + if (be_buf_size > 0) Xfree(be_buf); + + return Success; +} + +int __glXVForwardSingleReqSwap( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 0; + + return( __glXVForwardSingleReq( cl, pc ) ); +} + +int __glXVForwardPipe0WithReplySwap( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 0; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXVendorPrivateReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXVendorPrivateReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXVForwardPipe0WithReply( cl, pc ) ); +} + +int __glXVForwardPipe0WithReplySwapsv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 2; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXVendorPrivateReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXVendorPrivateReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXVForwardPipe0WithReply( cl, pc ) ); +} + +int __glXVForwardPipe0WithReplySwapiv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 4; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXVendorPrivateReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXVendorPrivateReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXVForwardPipe0WithReply( cl, pc ) ); +} + +int __glXVForwardPipe0WithReplySwapdv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 8; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXVendorPrivateReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXVendorPrivateReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXVForwardPipe0WithReply( cl, pc ) ); +} + +int __glXVForwardAllWithReplySwap( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 0; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXVendorPrivateReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXVendorPrivateReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXVForwardAllWithReply( cl, pc ) ); +} + +int __glXVForwardAllWithReplySwapsv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 2; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXVendorPrivateReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXVendorPrivateReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXVForwardAllWithReply( cl, pc ) ); +} + +int __glXVForwardAllWithReplySwapiv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 4; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXVendorPrivateReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXVendorPrivateReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXVForwardAllWithReply( cl, pc ) ); +} + +int __glXVForwardAllWithReplySwapdv( __GLXclientState *cl, GLbyte *pc ) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *)pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->vendorCode); + __GLX_SWAP_INT(&req->contextTag); + + swap_vec_element_size = 8; + + /* + * swap extra data in request - assuming all data + * (if available) are arrays of 4 bytes components ! + */ + if (req->length > sz_xGLXVendorPrivateReq/4) { + int *data = (int *)(req+1); + int count = req->length - sz_xGLXVendorPrivateReq/4; + __GLX_SWAP_INT_ARRAY(data, count ); + } + + return( __glXVForwardAllWithReply( cl, pc ) ); +} + diff --git a/xorg-server/hw/dmx/glxProxy/glxvisuals.c b/xorg-server/hw/dmx/glxProxy/glxvisuals.c index 898c6be7b..6e30b4edc 100644 --- a/xorg-server/hw/dmx/glxProxy/glxvisuals.c +++ b/xorg-server/hw/dmx/glxProxy/glxvisuals.c @@ -1,539 +1,539 @@ -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include <assert.h> -#include "dmx.h" -#include "glxserver.h" -#include "glxutil.h" -#include "dmx_glxvisuals.h" -#include <stdlib.h> - -static int numConfigs = 0; -static __GLXvisualConfig *visualConfigs = NULL; -static void **visualPrivates = NULL; - -int glxVisualsMatch( __GLXvisualConfig *v1, __GLXvisualConfig *v2 ) -{ - if ( (v1->class == v2->class) && - (v1->rgba == v2->rgba) && - (v1->redSize == v2->redSize) && - (v1->greenSize == v2->greenSize) && - (v1->blueSize == v2->blueSize) && - (v1->alphaSize == v2->alphaSize) && - (v1->redMask == v2->redMask) && - (v1->greenMask == v2->greenMask) && - (v1->blueMask == v2->blueMask) && - (v1->alphaMask == v2->alphaMask) && - (v1->accumRedSize == v2->accumRedSize) && - (v1->accumGreenSize == v2->accumGreenSize) && - (v1->accumBlueSize == v2->accumBlueSize) && - (v1->accumAlphaSize == v2->accumAlphaSize) && - (v1->doubleBuffer == v2->doubleBuffer) && - (v1->stereo == v2->stereo) && - (v1->bufferSize == v2->bufferSize) && - (v1->depthSize == v2->depthSize) && - (v1->stencilSize == v2->stencilSize) && - (v1->auxBuffers == v2->auxBuffers) && - (v1->level == v2->level) && - (v1->visualRating == v2->visualRating) && - (v1->transparentPixel == v2->transparentPixel) && - (v1->transparentRed == v2->transparentRed) && - (v1->transparentGreen == v2->transparentGreen) && - (v1->transparentBlue == v2->transparentBlue) && - (v1->transparentAlpha == v2->transparentAlpha) && - (v1->transparentIndex == v2->transparentIndex) && - (v1->multiSampleSize == v2->multiSampleSize) && - (v1->nMultiSampleBuffers == v2->nMultiSampleBuffers) && - (v1->visualSelectGroup == v2->visualSelectGroup) ) { - - return(1); - - } - - return(0); - -} - -VisualID glxMatchGLXVisualInConfigList( __GLXvisualConfig *pGlxVisual, __GLXvisualConfig *configs, int nconfigs ) -{ - int i; - - for (i=0; i<nconfigs; i++) { - - if (glxVisualsMatch( pGlxVisual, &configs[i] )) { - - return( configs[i].vid ); - - } - } - - return(0); -} - -VisualID glxMatchVisualInConfigList( ScreenPtr pScreen, VisualPtr pVisual, __GLXvisualConfig *configs, int nconfigs ) -{ - __GLXscreenInfo *pGlxScreen; - __GLXvisualConfig *pGlxVisual; - int i; - - /* check that the glx extension has been initialized */ - if ( !__glXActiveScreens ) - return(0); - - pGlxScreen = &__glXActiveScreens[pScreen->myNum]; - pGlxVisual = pGlxScreen->pGlxVisual; - - /* find the glx visual info for pVisual */ - for (i = 0; i < pGlxScreen->numVisuals; i++, pGlxVisual++) { - if (pGlxVisual->vid == pVisual->vid) { - break; - } - } - if (i == pGlxScreen->numVisuals) { - /* - * the visual is not supported by glx - */ - return(0); - } - - return( glxMatchGLXVisualInConfigList(pGlxVisual, configs, nconfigs) ); -} - -VisualPtr glxMatchVisual( ScreenPtr pScreen, VisualPtr pVisual, ScreenPtr pMatchScreen ) -{ - __GLXscreenInfo *pGlxScreen2; - int j; - VisualID vid; - - /* check that the glx extension has been initialized */ - if ( !__glXActiveScreens ) - return NULL; - - pGlxScreen2 = &__glXActiveScreens[pMatchScreen->myNum]; - - vid = glxMatchVisualInConfigList( pScreen, pVisual, - pGlxScreen2->pGlxVisual, - pGlxScreen2->numVisuals ); - if (vid) { - /* - * find the X visual of the matching glx visual - */ - for (j=0; j<pMatchScreen->numVisuals; j++) { - if (vid == pMatchScreen->visuals[j].vid) { - return( &pMatchScreen->visuals[j] ); - } - } - } - - return(0); -} - -void glxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, - void **privates) -{ - numConfigs = nconfigs; - visualConfigs = configs; - visualPrivates = privates; -} - -static int count_bits(unsigned int n) -{ - int bits = 0; - - while (n > 0) { - if (n & 1) bits++; - n >>= 1; - } - return bits; -} - -static VisualID FindClosestVisual( VisualPtr pVisual, int rootDepth, - DepthPtr pdepth, int ndepths, - VisualPtr pNewVisual, int numNewVisuals) -{ - int d, v; - VisualPtr vis; - - /* - * find the first visual with the same or deeper depth - * of the same class. - */ - for (d=0; d<ndepths; d++) { - if (pdepth[d].depth >= rootDepth) { - for (v=0; v<pdepth[d].numVids; v++) { - - /* find the new visual structure */ - vis = pNewVisual; - while( pdepth[d].vids[v] != vis->vid ) vis++; - - if (vis->class == pVisual->class) { - return( pdepth[d].vids[v] ); - } - } - } - } - - /* - * did not find any. - * try to look for the same class only. - */ - for (d=0; d<ndepths; d++) { - for (v=0; v<pdepth[d].numVids; v++) { - - /* find the new visual structure */ - vis = pNewVisual; - while( pdepth[d].vids[v] != vis->vid ) vis++; - - if (vis->class == pVisual->class) { - return( pdepth[d].vids[v] ); - } - } - } - - /* - * if not found - just take the first visual - */ - return( pdepth[0].vids[0] ); -} - -Bool glxInitVisuals(int *nvisualp, VisualPtr *visualp, - VisualID *defaultVisp, - int ndepth, DepthPtr pdepth, - int rootDepth) -{ - int numRGBconfigs; - int numCIconfigs; - int numVisuals = *nvisualp; - int numNewVisuals; - int numNewConfigs; - VisualPtr pVisual = *visualp; - VisualPtr pVisualNew = NULL; - VisualID *orig_vid = NULL; - __GLXvisualConfig *glXVisualPtr = NULL; - __GLXvisualConfig *pNewVisualConfigs = NULL; - void **glXVisualPriv; - dmxGlxVisualPrivate **pNewVisualPriv; - int found_default; - int i, j, k; - int numGLXvis = 0; - GLint *isGLXvis; - - if (numConfigs > 0) - numNewConfigs = numConfigs; - else - return False; - - MAXSCREENSALLOC(__glXActiveScreens); - if (!__glXActiveScreens) - return False; - - /* Alloc space for the list of new GLX visuals */ - pNewVisualConfigs = (__GLXvisualConfig *) - __glXMalloc(numNewConfigs * sizeof(__GLXvisualConfig)); - if (!pNewVisualConfigs) { - return FALSE; - } - - /* Alloc space for the list of new GLX visual privates */ - pNewVisualPriv = (dmxGlxVisualPrivate **) __glXMalloc(numNewConfigs * sizeof(dmxGlxVisualPrivate *)); - if (!pNewVisualPriv) { - __glXFree(pNewVisualConfigs); - return FALSE; - } - - /* copy driver's visual config info */ - for (i = 0; i < numConfigs; i++) { - pNewVisualConfigs[i] = visualConfigs[i]; - pNewVisualPriv[i] = (dmxGlxVisualPrivate *)visualPrivates[i]; - } - -#if 1 - /* FIXME: This is a hack to workaround a hang in xtest caused by a - * mismatch between what the front end (i.e., DMX) server calculates - * for the visual configs and what the back-end servers have. - */ - { - int numTCRGBconfigs = 0; - int numDCRGBconfigs = 0; - - numRGBconfigs = 0; - numCIconfigs = 0; - - for (i = 0; i < numNewConfigs; i++) { - if (pNewVisualConfigs[i].rgba) { - if (pNewVisualConfigs[i].class == TrueColor) - numTCRGBconfigs++; - else - numDCRGBconfigs++; - numRGBconfigs++; - } else - numCIconfigs++; - } - - /* Count the total number of visuals to compute */ - numNewVisuals = 0; - for (i = 0; i < numVisuals; i++) { - numNewVisuals += - (pVisual[i].class == TrueColor) ? numTCRGBconfigs : - (pVisual[i].class == DirectColor) ? numDCRGBconfigs : - numCIconfigs; - } - } -#else - /* Count the number of RGB and CI visual configs */ - numRGBconfigs = 0; - numCIconfigs = 0; - for (i = 0; i < numNewConfigs; i++) { - if (pNewVisualConfigs[i].rgba) - numRGBconfigs++; - else - numCIconfigs++; - } - - /* Count the total number of visuals to compute */ - numNewVisuals = 0; - for (i = 0; i < numVisuals; i++) { - numNewVisuals += - (pVisual[i].class == TrueColor || pVisual[i].class == DirectColor) - ? numRGBconfigs : numCIconfigs; - } -#endif - - /* Reset variables for use with the next screen/driver's visual configs */ - visualConfigs = NULL; - numConfigs = 0; - - /* Alloc temp space for the list of orig VisualIDs for each new visual */ - orig_vid = (VisualID *)__glXMalloc(numNewVisuals * sizeof(VisualID)); - if (!orig_vid) { - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - return FALSE; - } - - /* Alloc space for the list of glXVisuals */ - glXVisualPtr = (__GLXvisualConfig *)__glXMalloc(numNewVisuals * - sizeof(__GLXvisualConfig)); - if (!glXVisualPtr) { - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - return FALSE; - } - - /* Alloc space for the list of glXVisualPrivates */ - glXVisualPriv = (void **)__glXMalloc(numNewVisuals * sizeof(void *)); - if (!glXVisualPriv) { - __glXFree(glXVisualPtr); - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - return FALSE; - } - - /* Alloc space for the new list of the X server's visuals */ - pVisualNew = (VisualPtr)__glXMalloc(numNewVisuals * sizeof(VisualRec)); - if (!pVisualNew) { - __glXFree(glXVisualPriv); - __glXFree(glXVisualPtr); - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - return FALSE; - } - - isGLXvis = (GLint *) __glXMalloc(numNewVisuals * sizeof(GLint)); - if (!isGLXvis) { - __glXFree(glXVisualPriv); - __glXFree(glXVisualPtr); - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - __glXFree(pVisualNew); - return FALSE; - } - - /* Initialize the new visuals */ - found_default = FALSE; - for (i = j = 0; i < numVisuals; i++) { - - for (k = 0; k < numNewConfigs; k++) { - - int new_depth; - int depth; - int d,v; - - /* find the depth of the new visual config */ - new_depth = pNewVisualPriv[k]->x_visual_depth; - - /* find the depth of the original visual */ - depth = 0; - d = 0; - while( (depth==0) && (d < ndepth) ) { - v = 0; - while( (depth==0) && (v < pdepth[d].numVids) ) { - if (pdepth[d].vids[v] == pVisual[i].vid) { - depth = pdepth[d].depth; - } - v++; - } - d++; - } - - /* check that the visual has the same class and depth - * as the new config - */ - if ( pVisual[i].class != pNewVisualPriv[k]->x_visual_class || - (depth != new_depth) ) - continue; - - /* Initialize the new visual */ - pVisualNew[j] = pVisual[i]; - pVisualNew[j].vid = FakeClientID(0); - - /* Check for the default visual */ - if (!found_default && pVisual[i].vid == *defaultVisp) { - *defaultVisp = pVisualNew[j].vid; - found_default = TRUE; - } - - /* Save the old VisualID */ - orig_vid[j] = pVisual[i].vid; - - /* Initialize the glXVisual */ - glXVisualPtr[j] = pNewVisualConfigs[k]; - glXVisualPtr[j].vid = pVisualNew[j].vid; - - /* - * If the class is -1, then assume the X visual information - * is identical to what GLX needs, and take them from the X - * visual. NOTE: if class != -1, then all other fields MUST - * be initialized. - */ - if (glXVisualPtr[j].class == -1) { - glXVisualPtr[j].class = pVisual[i].class; - glXVisualPtr[j].redSize = count_bits(pVisual[i].redMask); - glXVisualPtr[j].greenSize = count_bits(pVisual[i].greenMask); - glXVisualPtr[j].blueSize = count_bits(pVisual[i].blueMask); - glXVisualPtr[j].alphaSize = glXVisualPtr[j].alphaSize; - glXVisualPtr[j].redMask = pVisual[i].redMask; - glXVisualPtr[j].greenMask = pVisual[i].greenMask; - glXVisualPtr[j].blueMask = pVisual[i].blueMask; - glXVisualPtr[j].alphaMask = glXVisualPtr[j].alphaMask; - glXVisualPtr[j].bufferSize = rootDepth; - } - - /* Save the device-dependent private for this visual */ - glXVisualPriv[j] = pNewVisualPriv[k]; - - isGLXvis[j] = glxMatchGLXVisualInConfigList( &glXVisualPtr[j], - dmxScreens[screenInfo.numScreens-1].glxVisuals, - dmxScreens[screenInfo.numScreens-1].numGlxVisuals ); - if (isGLXvis[j]) numGLXvis++; - - j++; - } - } - - assert(j <= numNewVisuals); - numNewVisuals = j; /* correct number of new visuals */ - - /* Save the GLX visuals in the screen structure */ - __glXActiveScreens[screenInfo.numScreens-1].numVisuals = numNewVisuals; - __glXActiveScreens[screenInfo.numScreens-1].numGLXVisuals = numGLXvis; - __glXActiveScreens[screenInfo.numScreens-1].isGLXvis = isGLXvis; - __glXActiveScreens[screenInfo.numScreens-1].pGlxVisual = glXVisualPtr; - - - /* Set up depth's VisualIDs */ - for (i = 0; i < ndepth; i++) { - int numVids = 0; - VisualID *pVids = NULL; - int k, n = 0; - - /* Count the new number of VisualIDs at this depth */ - for (j = 0; j < pdepth[i].numVids; j++) - for (k = 0; k < numNewVisuals; k++) - if (pdepth[i].vids[j] == orig_vid[k]) - numVids++; - - /* Allocate a new list of VisualIDs for this depth */ - pVids = (VisualID *)__glXMalloc(numVids * sizeof(VisualID)); - - /* Initialize the new list of VisualIDs for this depth */ - for (j = 0; j < pdepth[i].numVids; j++) - for (k = 0; k < numNewVisuals; k++) - if (pdepth[i].vids[j] == orig_vid[k]) - pVids[n++] = pVisualNew[k].vid; - - /* Update this depth's list of VisualIDs */ - __glXFree(pdepth[i].vids); - pdepth[i].vids = pVids; - pdepth[i].numVids = numVids; - } - - /* - * if the default visual was rejected - need to choose new - * default visual ! - */ - if ( !found_default ) { - - for (i=0; i<numVisuals; i++) - if (pVisual[i].vid == *defaultVisp) - break; - - if (i < numVisuals) { - *defaultVisp = FindClosestVisual( &pVisual[i], rootDepth, pdepth, ndepth, pVisualNew, numNewVisuals ); - } - } - - /* Update the X server's visuals */ - *nvisualp = numNewVisuals; - *visualp = pVisualNew; - - /* Free the old list of the X server's visuals */ - __glXFree(pVisual); - - /* Clean up temporary allocations */ - __glXFree(orig_vid); - __glXFree(pNewVisualPriv); - __glXFree(pNewVisualConfigs); - - /* Free the private list created by DDX HW driver */ - if (visualPrivates) - xfree(visualPrivates); - visualPrivates = NULL; - - return TRUE; -} +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include <assert.h> +#include "dmx.h" +#include "glxserver.h" +#include "glxutil.h" +#include "dmx_glxvisuals.h" +#include <stdlib.h> + +static int numConfigs = 0; +static __GLXvisualConfig *visualConfigs = NULL; +static void **visualPrivates = NULL; + +int glxVisualsMatch( __GLXvisualConfig *v1, __GLXvisualConfig *v2 ) +{ + if ( (v1->class == v2->class) && + (v1->rgba == v2->rgba) && + (v1->redSize == v2->redSize) && + (v1->greenSize == v2->greenSize) && + (v1->blueSize == v2->blueSize) && + (v1->alphaSize == v2->alphaSize) && + (v1->redMask == v2->redMask) && + (v1->greenMask == v2->greenMask) && + (v1->blueMask == v2->blueMask) && + (v1->alphaMask == v2->alphaMask) && + (v1->accumRedSize == v2->accumRedSize) && + (v1->accumGreenSize == v2->accumGreenSize) && + (v1->accumBlueSize == v2->accumBlueSize) && + (v1->accumAlphaSize == v2->accumAlphaSize) && + (v1->doubleBuffer == v2->doubleBuffer) && + (v1->stereo == v2->stereo) && + (v1->bufferSize == v2->bufferSize) && + (v1->depthSize == v2->depthSize) && + (v1->stencilSize == v2->stencilSize) && + (v1->auxBuffers == v2->auxBuffers) && + (v1->level == v2->level) && + (v1->visualRating == v2->visualRating) && + (v1->transparentPixel == v2->transparentPixel) && + (v1->transparentRed == v2->transparentRed) && + (v1->transparentGreen == v2->transparentGreen) && + (v1->transparentBlue == v2->transparentBlue) && + (v1->transparentAlpha == v2->transparentAlpha) && + (v1->transparentIndex == v2->transparentIndex) && + (v1->multiSampleSize == v2->multiSampleSize) && + (v1->nMultiSampleBuffers == v2->nMultiSampleBuffers) && + (v1->visualSelectGroup == v2->visualSelectGroup) ) { + + return(1); + + } + + return(0); + +} + +VisualID glxMatchGLXVisualInConfigList( __GLXvisualConfig *pGlxVisual, __GLXvisualConfig *configs, int nconfigs ) +{ + int i; + + for (i=0; i<nconfigs; i++) { + + if (glxVisualsMatch( pGlxVisual, &configs[i] )) { + + return( configs[i].vid ); + + } + } + + return(0); +} + +VisualID glxMatchVisualInConfigList( ScreenPtr pScreen, VisualPtr pVisual, __GLXvisualConfig *configs, int nconfigs ) +{ + __GLXscreenInfo *pGlxScreen; + __GLXvisualConfig *pGlxVisual; + int i; + + /* check that the glx extension has been initialized */ + if ( !__glXActiveScreens ) + return(0); + + pGlxScreen = &__glXActiveScreens[pScreen->myNum]; + pGlxVisual = pGlxScreen->pGlxVisual; + + /* find the glx visual info for pVisual */ + for (i = 0; i < pGlxScreen->numVisuals; i++, pGlxVisual++) { + if (pGlxVisual->vid == pVisual->vid) { + break; + } + } + if (i == pGlxScreen->numVisuals) { + /* + * the visual is not supported by glx + */ + return(0); + } + + return( glxMatchGLXVisualInConfigList(pGlxVisual, configs, nconfigs) ); +} + +VisualPtr glxMatchVisual( ScreenPtr pScreen, VisualPtr pVisual, ScreenPtr pMatchScreen ) +{ + __GLXscreenInfo *pGlxScreen2; + int j; + VisualID vid; + + /* check that the glx extension has been initialized */ + if ( !__glXActiveScreens ) + return NULL; + + pGlxScreen2 = &__glXActiveScreens[pMatchScreen->myNum]; + + vid = glxMatchVisualInConfigList( pScreen, pVisual, + pGlxScreen2->pGlxVisual, + pGlxScreen2->numVisuals ); + if (vid) { + /* + * find the X visual of the matching glx visual + */ + for (j=0; j<pMatchScreen->numVisuals; j++) { + if (vid == pMatchScreen->visuals[j].vid) { + return( &pMatchScreen->visuals[j] ); + } + } + } + + return(0); +} + +void glxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, + void **privates) +{ + numConfigs = nconfigs; + visualConfigs = configs; + visualPrivates = privates; +} + +static int count_bits(unsigned int n) +{ + int bits = 0; + + while (n > 0) { + if (n & 1) bits++; + n >>= 1; + } + return bits; +} + +static VisualID FindClosestVisual( VisualPtr pVisual, int rootDepth, + DepthPtr pdepth, int ndepths, + VisualPtr pNewVisual, int numNewVisuals) +{ + int d, v; + VisualPtr vis; + + /* + * find the first visual with the same or deeper depth + * of the same class. + */ + for (d=0; d<ndepths; d++) { + if (pdepth[d].depth >= rootDepth) { + for (v=0; v<pdepth[d].numVids; v++) { + + /* find the new visual structure */ + vis = pNewVisual; + while( pdepth[d].vids[v] != vis->vid ) vis++; + + if (vis->class == pVisual->class) { + return( pdepth[d].vids[v] ); + } + } + } + } + + /* + * did not find any. + * try to look for the same class only. + */ + for (d=0; d<ndepths; d++) { + for (v=0; v<pdepth[d].numVids; v++) { + + /* find the new visual structure */ + vis = pNewVisual; + while( pdepth[d].vids[v] != vis->vid ) vis++; + + if (vis->class == pVisual->class) { + return( pdepth[d].vids[v] ); + } + } + } + + /* + * if not found - just take the first visual + */ + return( pdepth[0].vids[0] ); +} + +Bool glxInitVisuals(int *nvisualp, VisualPtr *visualp, + VisualID *defaultVisp, + int ndepth, DepthPtr pdepth, + int rootDepth) +{ + int numRGBconfigs; + int numCIconfigs; + int numVisuals = *nvisualp; + int numNewVisuals; + int numNewConfigs; + VisualPtr pVisual = *visualp; + VisualPtr pVisualNew = NULL; + VisualID *orig_vid = NULL; + __GLXvisualConfig *glXVisualPtr = NULL; + __GLXvisualConfig *pNewVisualConfigs = NULL; + void **glXVisualPriv; + dmxGlxVisualPrivate **pNewVisualPriv; + int found_default; + int i, j, k; + int numGLXvis = 0; + GLint *isGLXvis; + + if (numConfigs > 0) + numNewConfigs = numConfigs; + else + return False; + + MAXSCREENSALLOC(__glXActiveScreens); + if (!__glXActiveScreens) + return False; + + /* Alloc space for the list of new GLX visuals */ + pNewVisualConfigs = (__GLXvisualConfig *) + __glXMalloc(numNewConfigs * sizeof(__GLXvisualConfig)); + if (!pNewVisualConfigs) { + return FALSE; + } + + /* Alloc space for the list of new GLX visual privates */ + pNewVisualPriv = (dmxGlxVisualPrivate **) __glXMalloc(numNewConfigs * sizeof(dmxGlxVisualPrivate *)); + if (!pNewVisualPriv) { + __glXFree(pNewVisualConfigs); + return FALSE; + } + + /* copy driver's visual config info */ + for (i = 0; i < numConfigs; i++) { + pNewVisualConfigs[i] = visualConfigs[i]; + pNewVisualPriv[i] = (dmxGlxVisualPrivate *)visualPrivates[i]; + } + +#if 1 + /* FIXME: This is a hack to workaround a hang in xtest caused by a + * mismatch between what the front end (i.e., DMX) server calculates + * for the visual configs and what the back-end servers have. + */ + { + int numTCRGBconfigs = 0; + int numDCRGBconfigs = 0; + + numRGBconfigs = 0; + numCIconfigs = 0; + + for (i = 0; i < numNewConfigs; i++) { + if (pNewVisualConfigs[i].rgba) { + if (pNewVisualConfigs[i].class == TrueColor) + numTCRGBconfigs++; + else + numDCRGBconfigs++; + numRGBconfigs++; + } else + numCIconfigs++; + } + + /* Count the total number of visuals to compute */ + numNewVisuals = 0; + for (i = 0; i < numVisuals; i++) { + numNewVisuals += + (pVisual[i].class == TrueColor) ? numTCRGBconfigs : + (pVisual[i].class == DirectColor) ? numDCRGBconfigs : + numCIconfigs; + } + } +#else + /* Count the number of RGB and CI visual configs */ + numRGBconfigs = 0; + numCIconfigs = 0; + for (i = 0; i < numNewConfigs; i++) { + if (pNewVisualConfigs[i].rgba) + numRGBconfigs++; + else + numCIconfigs++; + } + + /* Count the total number of visuals to compute */ + numNewVisuals = 0; + for (i = 0; i < numVisuals; i++) { + numNewVisuals += + (pVisual[i].class == TrueColor || pVisual[i].class == DirectColor) + ? numRGBconfigs : numCIconfigs; + } +#endif + + /* Reset variables for use with the next screen/driver's visual configs */ + visualConfigs = NULL; + numConfigs = 0; + + /* Alloc temp space for the list of orig VisualIDs for each new visual */ + orig_vid = (VisualID *)__glXMalloc(numNewVisuals * sizeof(VisualID)); + if (!orig_vid) { + __glXFree(pNewVisualPriv); + __glXFree(pNewVisualConfigs); + return FALSE; + } + + /* Alloc space for the list of glXVisuals */ + glXVisualPtr = (__GLXvisualConfig *)__glXMalloc(numNewVisuals * + sizeof(__GLXvisualConfig)); + if (!glXVisualPtr) { + __glXFree(orig_vid); + __glXFree(pNewVisualPriv); + __glXFree(pNewVisualConfigs); + return FALSE; + } + + /* Alloc space for the list of glXVisualPrivates */ + glXVisualPriv = (void **)__glXMalloc(numNewVisuals * sizeof(void *)); + if (!glXVisualPriv) { + __glXFree(glXVisualPtr); + __glXFree(orig_vid); + __glXFree(pNewVisualPriv); + __glXFree(pNewVisualConfigs); + return FALSE; + } + + /* Alloc space for the new list of the X server's visuals */ + pVisualNew = (VisualPtr)__glXMalloc(numNewVisuals * sizeof(VisualRec)); + if (!pVisualNew) { + __glXFree(glXVisualPriv); + __glXFree(glXVisualPtr); + __glXFree(orig_vid); + __glXFree(pNewVisualPriv); + __glXFree(pNewVisualConfigs); + return FALSE; + } + + isGLXvis = (GLint *) __glXMalloc(numNewVisuals * sizeof(GLint)); + if (!isGLXvis) { + __glXFree(glXVisualPriv); + __glXFree(glXVisualPtr); + __glXFree(orig_vid); + __glXFree(pNewVisualPriv); + __glXFree(pNewVisualConfigs); + __glXFree(pVisualNew); + return FALSE; + } + + /* Initialize the new visuals */ + found_default = FALSE; + for (i = j = 0; i < numVisuals; i++) { + + for (k = 0; k < numNewConfigs; k++) { + + int new_depth; + int depth; + int d,v; + + /* find the depth of the new visual config */ + new_depth = pNewVisualPriv[k]->x_visual_depth; + + /* find the depth of the original visual */ + depth = 0; + d = 0; + while( (depth==0) && (d < ndepth) ) { + v = 0; + while( (depth==0) && (v < pdepth[d].numVids) ) { + if (pdepth[d].vids[v] == pVisual[i].vid) { + depth = pdepth[d].depth; + } + v++; + } + d++; + } + + /* check that the visual has the same class and depth + * as the new config + */ + if ( pVisual[i].class != pNewVisualPriv[k]->x_visual_class || + (depth != new_depth) ) + continue; + + /* Initialize the new visual */ + pVisualNew[j] = pVisual[i]; + pVisualNew[j].vid = FakeClientID(0); + + /* Check for the default visual */ + if (!found_default && pVisual[i].vid == *defaultVisp) { + *defaultVisp = pVisualNew[j].vid; + found_default = TRUE; + } + + /* Save the old VisualID */ + orig_vid[j] = pVisual[i].vid; + + /* Initialize the glXVisual */ + glXVisualPtr[j] = pNewVisualConfigs[k]; + glXVisualPtr[j].vid = pVisualNew[j].vid; + + /* + * If the class is -1, then assume the X visual information + * is identical to what GLX needs, and take them from the X + * visual. NOTE: if class != -1, then all other fields MUST + * be initialized. + */ + if (glXVisualPtr[j].class == -1) { + glXVisualPtr[j].class = pVisual[i].class; + glXVisualPtr[j].redSize = count_bits(pVisual[i].redMask); + glXVisualPtr[j].greenSize = count_bits(pVisual[i].greenMask); + glXVisualPtr[j].blueSize = count_bits(pVisual[i].blueMask); + glXVisualPtr[j].alphaSize = glXVisualPtr[j].alphaSize; + glXVisualPtr[j].redMask = pVisual[i].redMask; + glXVisualPtr[j].greenMask = pVisual[i].greenMask; + glXVisualPtr[j].blueMask = pVisual[i].blueMask; + glXVisualPtr[j].alphaMask = glXVisualPtr[j].alphaMask; + glXVisualPtr[j].bufferSize = rootDepth; + } + + /* Save the device-dependent private for this visual */ + glXVisualPriv[j] = pNewVisualPriv[k]; + + isGLXvis[j] = glxMatchGLXVisualInConfigList( &glXVisualPtr[j], + dmxScreens[screenInfo.numScreens-1].glxVisuals, + dmxScreens[screenInfo.numScreens-1].numGlxVisuals ); + if (isGLXvis[j]) numGLXvis++; + + j++; + } + } + + assert(j <= numNewVisuals); + numNewVisuals = j; /* correct number of new visuals */ + + /* Save the GLX visuals in the screen structure */ + __glXActiveScreens[screenInfo.numScreens-1].numVisuals = numNewVisuals; + __glXActiveScreens[screenInfo.numScreens-1].numGLXVisuals = numGLXvis; + __glXActiveScreens[screenInfo.numScreens-1].isGLXvis = isGLXvis; + __glXActiveScreens[screenInfo.numScreens-1].pGlxVisual = glXVisualPtr; + + + /* Set up depth's VisualIDs */ + for (i = 0; i < ndepth; i++) { + int numVids = 0; + VisualID *pVids = NULL; + int k, n = 0; + + /* Count the new number of VisualIDs at this depth */ + for (j = 0; j < pdepth[i].numVids; j++) + for (k = 0; k < numNewVisuals; k++) + if (pdepth[i].vids[j] == orig_vid[k]) + numVids++; + + /* Allocate a new list of VisualIDs for this depth */ + pVids = (VisualID *)__glXMalloc(numVids * sizeof(VisualID)); + + /* Initialize the new list of VisualIDs for this depth */ + for (j = 0; j < pdepth[i].numVids; j++) + for (k = 0; k < numNewVisuals; k++) + if (pdepth[i].vids[j] == orig_vid[k]) + pVids[n++] = pVisualNew[k].vid; + + /* Update this depth's list of VisualIDs */ + __glXFree(pdepth[i].vids); + pdepth[i].vids = pVids; + pdepth[i].numVids = numVids; + } + + /* + * if the default visual was rejected - need to choose new + * default visual ! + */ + if ( !found_default ) { + + for (i=0; i<numVisuals; i++) + if (pVisual[i].vid == *defaultVisp) + break; + + if (i < numVisuals) { + *defaultVisp = FindClosestVisual( &pVisual[i], rootDepth, pdepth, ndepth, pVisualNew, numNewVisuals ); + } + } + + /* Update the X server's visuals */ + *nvisualp = numNewVisuals; + *visualp = pVisualNew; + + /* Free the old list of the X server's visuals */ + __glXFree(pVisual); + + /* Clean up temporary allocations */ + __glXFree(orig_vid); + __glXFree(pNewVisualPriv); + __glXFree(pNewVisualConfigs); + + /* Free the private list created by DDX HW driver */ + if (visualPrivates) + free(visualPrivates); + visualPrivates = NULL; + + return TRUE; +} diff --git a/xorg-server/hw/dmx/glxProxy/unpack.h b/xorg-server/hw/dmx/glxProxy/unpack.h index 98fa10ee7..73d0485e3 100644 --- a/xorg-server/hw/dmx/glxProxy/unpack.h +++ b/xorg-server/hw/dmx/glxProxy/unpack.h @@ -1,228 +1,228 @@ -#ifndef __GLX_unpack_h__ -#define __GLX_unpack_h__ - -/* - * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) - * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and - * either this permission notice or a reference to - * http://oss.sgi.com/projects/FreeB/ - * 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 - * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. - * shall not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization from - * Silicon Graphics, Inc. - */ - -#define __GLX_PAD(s) (((s)+3) & (GLuint)~3) - -/* -** Fetch the context-id out of a SingleReq request pointed to by pc. -*/ -#define __GLX_GET_SINGLE_CONTEXT_TAG(pc) (((xGLXSingleReq*)pc)->contextTag) -#define __GLX_GET_VENDPRIV_CONTEXT_TAG(pc) (((xGLXVendorPrivateReq*)pc)->contextTag) - -/* -** Fetch a double from potentially unaligned memory. -*/ -#ifdef __GLX_ALIGN64 -#define __GLX_MEM_COPY(dst,src,n) memcpy(dst,src,n) -#define __GLX_GET_DOUBLE(dst,src) __GLX_MEM_COPY(&dst,src,8) -#else -#define __GLX_GET_DOUBLE(dst,src) (dst) = *((GLdouble*)(src)) -#endif - -extern void __glXMemInit(void); - -extern xGLXSingleReply __glXReply; - -#define __GLX_BEGIN_REPLY(size) \ - __glXReply.length = __GLX_PAD(size) >> 2; \ - __glXReply.type = X_Reply; \ - __glXReply.sequenceNumber = client->sequence; - -#define __GLX_SEND_HEADER() \ - WriteToClient( client, sz_xGLXSingleReply, (char *)&__glXReply); - -#define __GLX_PUT_RETVAL(a) \ - __glXReply.retval = (a); - -#define __GLX_PUT_SIZE(a) \ - __glXReply.size = (a); - -#define __GLX_PUT_RENDERMODE(m) \ - __glXReply.pad3 = (m) - -/* -** Get a buffer to hold returned data, with the given alignment. If we have -** to realloc, allocate size+align, in case the pointer has to be bumped for -** alignment. The answerBuffer should already be aligned. -** -** NOTE: the cast (long)res below assumes a long is large enough to hold a -** pointer. -*/ -#define __GLX_GET_ANSWER_BUFFER(res,cl,size,align) \ - if ((size) > sizeof(answerBuffer)) { \ - int bump; \ - if ((cl)->returnBufSize < (size)+(align)) { \ - (cl)->returnBuf = (GLbyte*)Xrealloc((cl)->returnBuf, \ - (size)+(align)); \ - if (!(cl)->returnBuf) { \ - return BadAlloc; \ - } \ - (cl)->returnBufSize = (size)+(align); \ - } \ - res = (char*)cl->returnBuf; \ - bump = (long)(res) % (align); \ - if (bump) res += (align) - (bump); \ - } else { \ - res = (char *)answerBuffer; \ - } - -#define __GLX_PUT_BYTE() \ - *(GLbyte *)&__glXReply.pad3 = *(GLbyte *)answer - -#define __GLX_PUT_SHORT() \ - *(GLshort *)&__glXReply.pad3 = *(GLshort *)answer - -#define __GLX_PUT_INT() \ - *(GLint *)&__glXReply.pad3 = *(GLint *)answer - -#define __GLX_PUT_FLOAT() \ - *(GLfloat *)&__glXReply.pad3 = *(GLfloat *)answer - -#define __GLX_PUT_DOUBLE() \ - *(GLdouble *)&__glXReply.pad3 = *(GLdouble *)answer - -#define __GLX_SEND_BYTE_ARRAY(len) \ - WriteToClient(client, __GLX_PAD((len)*__GLX_SIZE_INT8), (char *)answer) - -#define __GLX_SEND_SHORT_ARRAY(len) \ - WriteToClient(client, __GLX_PAD((len)*__GLX_SIZE_INT16), (char *)answer) - -#define __GLX_SEND_INT_ARRAY(len) \ - WriteToClient(client, (len)*__GLX_SIZE_INT32, (char *)answer) - -#define __GLX_SEND_FLOAT_ARRAY(len) \ - WriteToClient(client, (len)*__GLX_SIZE_FLOAT32, (char *)answer) - -#define __GLX_SEND_DOUBLE_ARRAY(len) \ - WriteToClient(client, (len)*__GLX_SIZE_FLOAT64, (char *)answer) - - -#define __GLX_SEND_VOID_ARRAY(len) __GLX_SEND_BYTE_ARRAY(len) -#define __GLX_SEND_UBYTE_ARRAY(len) __GLX_SEND_BYTE_ARRAY(len) -#define __GLX_SEND_USHORT_ARRAY(len) __GLX_SEND_SHORT_ARRAY(len) -#define __GLX_SEND_UINT_ARRAY(len) __GLX_SEND_INT_ARRAY(len) - -/* -** PERFORMANCE NOTE: -** Machine dependent optimizations abound here; these swapping macros can -** conceivably be replaced with routines that do the job faster. -*/ -#define __GLX_DECLARE_SWAP_VARIABLES \ - GLbyte sw; \ - GLbyte *swapPC; \ - GLbyte *swapEnd - - -#define __GLX_SWAP_INT(pc) \ - sw = ((GLbyte *)(pc))[0]; \ - ((GLbyte *)(pc))[0] = ((GLbyte *)(pc))[3]; \ - ((GLbyte *)(pc))[3] = sw; \ - sw = ((GLbyte *)(pc))[1]; \ - ((GLbyte *)(pc))[1] = ((GLbyte *)(pc))[2]; \ - ((GLbyte *)(pc))[2] = sw; - -#define __GLX_SWAP_SHORT(pc) \ - sw = ((GLbyte *)(pc))[0]; \ - ((GLbyte *)(pc))[0] = ((GLbyte *)(pc))[1]; \ - ((GLbyte *)(pc))[1] = sw; - -#define __GLX_SWAP_DOUBLE(pc) \ - sw = ((GLbyte *)(pc))[0]; \ - ((GLbyte *)(pc))[0] = ((GLbyte *)(pc))[7]; \ - ((GLbyte *)(pc))[7] = sw; \ - sw = ((GLbyte *)(pc))[1]; \ - ((GLbyte *)(pc))[1] = ((GLbyte *)(pc))[6]; \ - ((GLbyte *)(pc))[6] = sw; \ - sw = ((GLbyte *)(pc))[2]; \ - ((GLbyte *)(pc))[2] = ((GLbyte *)(pc))[5]; \ - ((GLbyte *)(pc))[5] = sw; \ - sw = ((GLbyte *)(pc))[3]; \ - ((GLbyte *)(pc))[3] = ((GLbyte *)(pc))[4]; \ - ((GLbyte *)(pc))[4] = sw; - -#define __GLX_SWAP_FLOAT(pc) \ - sw = ((GLbyte *)(pc))[0]; \ - ((GLbyte *)(pc))[0] = ((GLbyte *)(pc))[3]; \ - ((GLbyte *)(pc))[3] = sw; \ - sw = ((GLbyte *)(pc))[1]; \ - ((GLbyte *)(pc))[1] = ((GLbyte *)(pc))[2]; \ - ((GLbyte *)(pc))[2] = sw; - -#define __GLX_SWAP_INT_ARRAY(pc, count) \ - swapPC = ((GLbyte *)(pc)); \ - swapEnd = ((GLbyte *)(pc)) + (count)*__GLX_SIZE_INT32;\ - while (swapPC < swapEnd) { \ - __GLX_SWAP_INT(swapPC); \ - swapPC += __GLX_SIZE_INT32; \ - } - -#define __GLX_SWAP_SHORT_ARRAY(pc, count) \ - swapPC = ((GLbyte *)(pc)); \ - swapEnd = ((GLbyte *)(pc)) + (count)*__GLX_SIZE_INT16;\ - while (swapPC < swapEnd) { \ - __GLX_SWAP_SHORT(swapPC); \ - swapPC += __GLX_SIZE_INT16; \ - } - -#define __GLX_SWAP_DOUBLE_ARRAY(pc, count) \ - swapPC = ((GLbyte *)(pc)); \ - swapEnd = ((GLbyte *)(pc)) + (count)*__GLX_SIZE_FLOAT64;\ - while (swapPC < swapEnd) { \ - __GLX_SWAP_DOUBLE(swapPC); \ - swapPC += __GLX_SIZE_FLOAT64; \ - } - -#define __GLX_SWAP_FLOAT_ARRAY(pc, count) \ - swapPC = ((GLbyte *)(pc)); \ - swapEnd = ((GLbyte *)(pc)) + (count)*__GLX_SIZE_FLOAT32;\ - while (swapPC < swapEnd) { \ - __GLX_SWAP_FLOAT(swapPC); \ - swapPC += __GLX_SIZE_FLOAT32; \ - } - -#define __GLX_SWAP_REPLY_HEADER() \ - __GLX_SWAP_SHORT(&__glXReply.sequenceNumber); \ - __GLX_SWAP_INT(&__glXReply.length); - -#define __GLX_SWAP_REPLY_RETVAL() \ - __GLX_SWAP_INT(&__glXReply.retval) - -#define __GLX_SWAP_REPLY_SIZE() \ - __GLX_SWAP_INT(&__glXReply.size) - -#endif /* !__GLX_unpack_h__ */ - - - - - +#ifndef __GLX_unpack_h__ +#define __GLX_unpack_h__ + +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, 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 including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * 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 + * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#define __GLX_PAD(s) (((s)+3) & (GLuint)~3) + +/* +** Fetch the context-id out of a SingleReq request pointed to by pc. +*/ +#define __GLX_GET_SINGLE_CONTEXT_TAG(pc) (((xGLXSingleReq*)pc)->contextTag) +#define __GLX_GET_VENDPRIV_CONTEXT_TAG(pc) (((xGLXVendorPrivateReq*)pc)->contextTag) + +/* +** Fetch a double from potentially unaligned memory. +*/ +#ifdef __GLX_ALIGN64 +#define __GLX_MEM_COPY(dst,src,n) memcpy(dst,src,n) +#define __GLX_GET_DOUBLE(dst,src) __GLX_MEM_COPY(&dst,src,8) +#else +#define __GLX_GET_DOUBLE(dst,src) (dst) = *((GLdouble*)(src)) +#endif + +extern void __glXMemInit(void); + +extern xGLXSingleReply __glXReply; + +#define __GLX_BEGIN_REPLY(size) \ + __glXReply.length = __GLX_PAD(size) >> 2; \ + __glXReply.type = X_Reply; \ + __glXReply.sequenceNumber = client->sequence; + +#define __GLX_SEND_HEADER() \ + WriteToClient( client, sz_xGLXSingleReply, (char *)&__glXReply); + +#define __GLX_PUT_RETVAL(a) \ + __glXReply.retval = (a); + +#define __GLX_PUT_SIZE(a) \ + __glXReply.size = (a); + +#define __GLX_PUT_RENDERMODE(m) \ + __glXReply.pad3 = (m) + +/* +** Get a buffer to hold returned data, with the given alignment. If we have +** to realloc, allocate size+align, in case the pointer has to be bumped for +** alignment. The answerBuffer should already be aligned. +** +** NOTE: the cast (long)res below assumes a long is large enough to hold a +** pointer. +*/ +#define __GLX_GET_ANSWER_BUFFER(res,cl,size,align) \ + if ((size) > sizeof(answerBuffer)) { \ + int bump; \ + if ((cl)->returnBufSize < (size)+(align)) { \ + (cl)->returnBuf = (GLbyte*)realloc((cl)->returnBuf, \ + (size)+(align)); \ + if (!(cl)->returnBuf) { \ + return BadAlloc; \ + } \ + (cl)->returnBufSize = (size)+(align); \ + } \ + res = (char*)cl->returnBuf; \ + bump = (long)(res) % (align); \ + if (bump) res += (align) - (bump); \ + } else { \ + res = (char *)answerBuffer; \ + } + +#define __GLX_PUT_BYTE() \ + *(GLbyte *)&__glXReply.pad3 = *(GLbyte *)answer + +#define __GLX_PUT_SHORT() \ + *(GLshort *)&__glXReply.pad3 = *(GLshort *)answer + +#define __GLX_PUT_INT() \ + *(GLint *)&__glXReply.pad3 = *(GLint *)answer + +#define __GLX_PUT_FLOAT() \ + *(GLfloat *)&__glXReply.pad3 = *(GLfloat *)answer + +#define __GLX_PUT_DOUBLE() \ + *(GLdouble *)&__glXReply.pad3 = *(GLdouble *)answer + +#define __GLX_SEND_BYTE_ARRAY(len) \ + WriteToClient(client, __GLX_PAD((len)*__GLX_SIZE_INT8), (char *)answer) + +#define __GLX_SEND_SHORT_ARRAY(len) \ + WriteToClient(client, __GLX_PAD((len)*__GLX_SIZE_INT16), (char *)answer) + +#define __GLX_SEND_INT_ARRAY(len) \ + WriteToClient(client, (len)*__GLX_SIZE_INT32, (char *)answer) + +#define __GLX_SEND_FLOAT_ARRAY(len) \ + WriteToClient(client, (len)*__GLX_SIZE_FLOAT32, (char *)answer) + +#define __GLX_SEND_DOUBLE_ARRAY(len) \ + WriteToClient(client, (len)*__GLX_SIZE_FLOAT64, (char *)answer) + + +#define __GLX_SEND_VOID_ARRAY(len) __GLX_SEND_BYTE_ARRAY(len) +#define __GLX_SEND_UBYTE_ARRAY(len) __GLX_SEND_BYTE_ARRAY(len) +#define __GLX_SEND_USHORT_ARRAY(len) __GLX_SEND_SHORT_ARRAY(len) +#define __GLX_SEND_UINT_ARRAY(len) __GLX_SEND_INT_ARRAY(len) + +/* +** PERFORMANCE NOTE: +** Machine dependent optimizations abound here; these swapping macros can +** conceivably be replaced with routines that do the job faster. +*/ +#define __GLX_DECLARE_SWAP_VARIABLES \ + GLbyte sw; \ + GLbyte *swapPC; \ + GLbyte *swapEnd + + +#define __GLX_SWAP_INT(pc) \ + sw = ((GLbyte *)(pc))[0]; \ + ((GLbyte *)(pc))[0] = ((GLbyte *)(pc))[3]; \ + ((GLbyte *)(pc))[3] = sw; \ + sw = ((GLbyte *)(pc))[1]; \ + ((GLbyte *)(pc))[1] = ((GLbyte *)(pc))[2]; \ + ((GLbyte *)(pc))[2] = sw; + +#define __GLX_SWAP_SHORT(pc) \ + sw = ((GLbyte *)(pc))[0]; \ + ((GLbyte *)(pc))[0] = ((GLbyte *)(pc))[1]; \ + ((GLbyte *)(pc))[1] = sw; + +#define __GLX_SWAP_DOUBLE(pc) \ + sw = ((GLbyte *)(pc))[0]; \ + ((GLbyte *)(pc))[0] = ((GLbyte *)(pc))[7]; \ + ((GLbyte *)(pc))[7] = sw; \ + sw = ((GLbyte *)(pc))[1]; \ + ((GLbyte *)(pc))[1] = ((GLbyte *)(pc))[6]; \ + ((GLbyte *)(pc))[6] = sw; \ + sw = ((GLbyte *)(pc))[2]; \ + ((GLbyte *)(pc))[2] = ((GLbyte *)(pc))[5]; \ + ((GLbyte *)(pc))[5] = sw; \ + sw = ((GLbyte *)(pc))[3]; \ + ((GLbyte *)(pc))[3] = ((GLbyte *)(pc))[4]; \ + ((GLbyte *)(pc))[4] = sw; + +#define __GLX_SWAP_FLOAT(pc) \ + sw = ((GLbyte *)(pc))[0]; \ + ((GLbyte *)(pc))[0] = ((GLbyte *)(pc))[3]; \ + ((GLbyte *)(pc))[3] = sw; \ + sw = ((GLbyte *)(pc))[1]; \ + ((GLbyte *)(pc))[1] = ((GLbyte *)(pc))[2]; \ + ((GLbyte *)(pc))[2] = sw; + +#define __GLX_SWAP_INT_ARRAY(pc, count) \ + swapPC = ((GLbyte *)(pc)); \ + swapEnd = ((GLbyte *)(pc)) + (count)*__GLX_SIZE_INT32;\ + while (swapPC < swapEnd) { \ + __GLX_SWAP_INT(swapPC); \ + swapPC += __GLX_SIZE_INT32; \ + } + +#define __GLX_SWAP_SHORT_ARRAY(pc, count) \ + swapPC = ((GLbyte *)(pc)); \ + swapEnd = ((GLbyte *)(pc)) + (count)*__GLX_SIZE_INT16;\ + while (swapPC < swapEnd) { \ + __GLX_SWAP_SHORT(swapPC); \ + swapPC += __GLX_SIZE_INT16; \ + } + +#define __GLX_SWAP_DOUBLE_ARRAY(pc, count) \ + swapPC = ((GLbyte *)(pc)); \ + swapEnd = ((GLbyte *)(pc)) + (count)*__GLX_SIZE_FLOAT64;\ + while (swapPC < swapEnd) { \ + __GLX_SWAP_DOUBLE(swapPC); \ + swapPC += __GLX_SIZE_FLOAT64; \ + } + +#define __GLX_SWAP_FLOAT_ARRAY(pc, count) \ + swapPC = ((GLbyte *)(pc)); \ + swapEnd = ((GLbyte *)(pc)) + (count)*__GLX_SIZE_FLOAT32;\ + while (swapPC < swapEnd) { \ + __GLX_SWAP_FLOAT(swapPC); \ + swapPC += __GLX_SIZE_FLOAT32; \ + } + +#define __GLX_SWAP_REPLY_HEADER() \ + __GLX_SWAP_SHORT(&__glXReply.sequenceNumber); \ + __GLX_SWAP_INT(&__glXReply.length); + +#define __GLX_SWAP_REPLY_RETVAL() \ + __GLX_SWAP_INT(&__glXReply.retval) + +#define __GLX_SWAP_REPLY_SIZE() \ + __GLX_SWAP_INT(&__glXReply.size) + +#endif /* !__GLX_unpack_h__ */ + + + + + diff --git a/xorg-server/hw/dmx/input/dmxinputinit.c b/xorg-server/hw/dmx/input/dmxinputinit.c index 5a486a464..f9acaa039 100644 --- a/xorg-server/hw/dmx/input/dmxinputinit.c +++ b/xorg-server/hw/dmx/input/dmxinputinit.c @@ -1,1311 +1,1311 @@ -/* - * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: - * Rickard E. (Rik) Faith <faith@redhat.com> - * - */ - -/** \file - * This file provides generic input support. Functions here set up - * input and lead to the calling of low-level device drivers for - * input. */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#define DMX_WINDOW_DEBUG 0 - -#include "dmxinputinit.h" -#include "dmxextension.h" /* For dmxInputCount */ - -#include "dmxdummy.h" -#include "dmxbackend.h" -#include "dmxconsole.h" -#include "dmxcommon.h" -#include "dmxevents.h" -#include "dmxmotion.h" -#include "dmxprop.h" -#include "config/dmxconfig.h" -#include "dmxcursor.h" - -#include "lnx-keyboard.h" -#include "lnx-ms.h" -#include "lnx-ps2.h" -#include "usb-keyboard.h" -#include "usb-mouse.h" -#include "usb-other.h" -#include "usb-common.h" - -#include "dmxsigio.h" -#include "dmxarg.h" - -#include "inputstr.h" -#include "input.h" -#include "mipointer.h" -#include "windowstr.h" -#include "mi.h" -#include "xkbsrv.h" - -#include <X11/extensions/XI.h> -#include <X11/extensions/XIproto.h> -#include "exevents.h" -#include "extinit.h" - -DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard; - -static DMXLocalInputInfoRec DMXDummyMou = { - "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo -}; - -static DMXLocalInputInfoRec DMXDummyKbd = { - "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo -}; - -static DMXLocalInputInfoRec DMXBackendMou = { - "backend-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_BACKEND, 2, - dmxBackendCreatePrivate, dmxBackendDestroyPrivate, - dmxBackendInit, NULL, dmxBackendLateReInit, dmxBackendMouGetInfo, - dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition, - NULL, NULL, NULL, - dmxBackendCollectEvents, dmxBackendProcessInput, dmxBackendFunctions, NULL, - dmxCommonMouCtrl -}; - -static DMXLocalInputInfoRec DMXBackendKbd = { - "backend-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_BACKEND, - 1, /* With backend-mou or console-mou */ - dmxCommonCopyPrivate, NULL, - dmxBackendInit, NULL, NULL, dmxBackendKbdGetInfo, - dmxCommonKbdOn, dmxCommonKbdOff, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, dmxCommonKbdCtrl, dmxCommonKbdBell -}; - -static DMXLocalInputInfoRec DMXConsoleMou = { - "console-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_CONSOLE, 2, - dmxConsoleCreatePrivate, dmxConsoleDestroyPrivate, - dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleMouGetInfo, - dmxCommonMouOn, dmxCommonMouOff, dmxConsoleUpdatePosition, - NULL, NULL, NULL, - dmxConsoleCollectEvents, NULL, dmxConsoleFunctions, dmxConsoleUpdateInfo, - dmxCommonMouCtrl -}; - -static DMXLocalInputInfoRec DMXConsoleKbd = { - "console-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_CONSOLE, - 1, /* With backend-mou or console-mou */ - dmxCommonCopyPrivate, NULL, - dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo, - dmxCommonKbdOn, dmxCommonKbdOff, NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, dmxCommonKbdCtrl, dmxCommonKbdBell -}; - -static DMXLocalInputInfoRec DMXCommonOth = { - "common-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_COMMON, 1, - dmxCommonCopyPrivate, NULL, - NULL, NULL, NULL, dmxCommonOthGetInfo, - dmxCommonOthOn, dmxCommonOthOff -}; - - -static DMXLocalInputInfoRec DMXLocalDevices[] = { - /* Dummy drivers that can compile on any OS */ -#ifdef __linux__ - /* Linux-specific drivers */ - { - "kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - kbdLinuxCreatePrivate, kbdLinuxDestroyPrivate, - kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo, - kbdLinuxOn, kbdLinuxOff, NULL, - kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch, - kbdLinuxRead, NULL, NULL, NULL, - NULL, kbdLinuxCtrl, kbdLinuxBell - }, - { - "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - msLinuxCreatePrivate, msLinuxDestroyPrivate, - msLinuxInit, NULL, NULL, msLinuxGetInfo, - msLinuxOn, msLinuxOff, NULL, - msLinuxVTPreSwitch, msLinuxVTPostSwitch, NULL, - msLinuxRead - }, - { - "ps2", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - ps2LinuxCreatePrivate, ps2LinuxDestroyPrivate, - ps2LinuxInit, NULL, NULL, ps2LinuxGetInfo, - ps2LinuxOn, ps2LinuxOff, NULL, - ps2LinuxVTPreSwitch, ps2LinuxVTPostSwitch, NULL, - ps2LinuxRead - }, -#endif -#ifdef __linux__ - /* USB drivers, currently only for - Linux, but relatively easy to port to - other OSs */ - { - "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - kbdUSBInit, NULL, NULL, kbdUSBGetInfo, - kbdUSBOn, usbOff, NULL, - NULL, NULL, NULL, - kbdUSBRead, NULL, NULL, NULL, - NULL, kbdUSBCtrl - }, - { - "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - mouUSBInit, NULL, NULL, mouUSBGetInfo, - mouUSBOn, usbOff, NULL, - NULL, NULL, NULL, - mouUSBRead - }, - { - "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - othUSBInit, NULL, NULL, othUSBGetInfo, - othUSBOn, usbOff, NULL, - NULL, NULL, NULL, - othUSBRead - }, -#endif - { - "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo - }, - { - "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo - }, - { NULL } /* Must be last */ -}; - - -#if 11 /*BP*/ -void -DDXRingBell(int volume, int pitch, int duration) -{ - /* NO-OP */ -} - -/* taken from kdrive/src/kinput.c: */ -static void -dmxKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl) -{ -#if 0 - KdKeyboardInfo *ki; - - for (ki = kdKeyboards; ki; ki = ki->next) { - if (ki->dixdev && ki->dixdev->id == pDevice->id) - break; - } - - if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver) - return; - - KdSetLeds(ki, ctrl->leds); - ki->bellPitch = ctrl->bell_pitch; - ki->bellDuration = ctrl->bell_duration; -#endif -} - -/* taken from kdrive/src/kinput.c: */ -static void -dmxBell(int volume, DeviceIntPtr pDev, pointer arg, int something) -{ -#if 0 - KeybdCtrl *ctrl = arg; - KdKeyboardInfo *ki = NULL; - - for (ki = kdKeyboards; ki; ki = ki->next) { - if (ki->dixdev && ki->dixdev->id == pDev->id) - break; - } - - if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver) - return; - - KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration); -#endif -} - -#endif /*BP*/ - -static void _dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal, - PtrCtrl *ctrl) -{ - if (!dmxLocal) return; - dmxLocal->mctrl = *ctrl; - if (dmxLocal->mCtrl) dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl); -} - -/** Change the pointer control information for the \a pDevice. If the - * device sends core events, then also change the control information - * for all of the pointer devices that send core events. */ -void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl) -{ - GETDMXLOCALFROMPDEVICE; - int i, j; - - if (dmxLocal->sendsCore) { /* Do for all core devices */ - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; - for (j = 0; j < dmxInput->numDevs; j++) - if (dmxInput->devs[j]->sendsCore) - _dmxChangePointerControl(dmxInput->devs[j], ctrl); - } - } else { /* Do for this device only */ - _dmxChangePointerControl(dmxLocal, ctrl); - } -} - -static void _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal, - KeybdCtrl *ctrl) -{ - dmxLocal->kctrl = *ctrl; - if (dmxLocal->kCtrl) { - dmxLocal->kCtrl(&dmxLocal->pDevice->public, ctrl); - if (dmxLocal->pDevice->kbdfeed) { - XkbEventCauseRec cause; - XkbSetCauseUnknown(&cause); - /* Generate XKB events, as necessary */ - XkbUpdateIndicators(dmxLocal->pDevice, XkbAllIndicatorsMask, False, - NULL, &cause); - } - } -} - - -/** Change the keyboard control information for the \a pDevice. If the - * device sends core events, then also change the control information - * for all of the keyboard devices that send core events. */ -void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl) -{ - GETDMXLOCALFROMPDEVICE; - int i, j; - - if (dmxLocal->sendsCore) { /* Do for all core devices */ - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; - for (j = 0; j < dmxInput->numDevs; j++) - if (dmxInput->devs[j]->sendsCore) - _dmxKeyboardKbdCtrlProc(dmxInput->devs[j], ctrl); - } - } else { /* Do for this device only */ - _dmxKeyboardKbdCtrlProc(dmxLocal, ctrl); - } -} - -static void _dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent) -{ - if (dmxLocal->kBell) dmxLocal->kBell(&dmxLocal->pDevice->public, - percent, - dmxLocal->kctrl.bell, - dmxLocal->kctrl.bell_pitch, - dmxLocal->kctrl.bell_duration); -} - -/** Sound the bell on the device. If the device send core events, then - * sound the bell on all of the devices that send core events. */ -void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice, - pointer ctrl, int unknown) -{ - GETDMXLOCALFROMPDEVICE; - int i, j; - - if (dmxLocal->sendsCore) { /* Do for all core devices */ - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; - for (j = 0; j < dmxInput->numDevs; j++) - if (dmxInput->devs[j]->sendsCore) - _dmxKeyboardBellProc(dmxInput->devs[j], percent); - } - } else { /* Do for this device only */ - _dmxKeyboardBellProc(dmxLocal, percent); - } -} - -static void dmxKeyboardFreeNames(XkbComponentNamesPtr names) -{ - if (names->keycodes) XFree(names->keycodes); - if (names->types) XFree(names->types); - if (names->compat) XFree(names->compat); - if (names->symbols) XFree(names->symbols); - if (names->geometry) XFree(names->geometry); -} - - -static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info) -{ - GETDMXINPUTFROMPDEVICE; - XkbRMLVOSet rmlvo; - - rmlvo.rules = dmxConfigGetXkbRules(); - rmlvo.model = dmxConfigGetXkbModel(); - rmlvo.layout = dmxConfigGetXkbLayout(); - rmlvo.variant = dmxConfigGetXkbVariant(); - rmlvo.options = dmxConfigGetXkbOptions(); - - XkbSetRulesDflts(&rmlvo); - if (!info->force && (dmxInput->keycodes - || dmxInput->symbols - || dmxInput->geometry)) { - if (info->freenames) dmxKeyboardFreeNames(&info->names); - info->freenames = 0; - info->names.keycodes = dmxInput->keycodes; - info->names.types = NULL; - info->names.compat = NULL; - info->names.symbols = dmxInput->symbols; - info->names.geometry = dmxInput->geometry; - - dmxLogInput(dmxInput, "XKEYBOARD: From command line: %s", - info->names.keycodes); - if (info->names.symbols && *info->names.symbols) - dmxLogInputCont(dmxInput, " %s", info->names.symbols); - if (info->names.geometry && *info->names.geometry) - dmxLogInputCont(dmxInput, " %s", info->names.geometry); - dmxLogInputCont(dmxInput, "\n"); - } else if (info->names.keycodes) { - dmxLogInput(dmxInput, "XKEYBOARD: From device: %s", - info->names.keycodes); - if (info->names.symbols && *info->names.symbols) - dmxLogInputCont(dmxInput, " %s", info->names.symbols); - if (info->names.geometry && *info->names.geometry) - dmxLogInputCont(dmxInput, " %s", info->names.geometry); - dmxLogInputCont(dmxInput, "\n"); - } else { - dmxLogInput(dmxInput, "XKEYBOARD: Defaults: %s %s %s %s %s\n", - dmxConfigGetXkbRules(), - dmxConfigGetXkbLayout(), - dmxConfigGetXkbModel(), - dmxConfigGetXkbVariant() - ? dmxConfigGetXkbVariant() : "", - dmxConfigGetXkbOptions() - ? dmxConfigGetXkbOptions() : ""); - } - InitKeyboardDeviceStruct(pDevice, &rmlvo, - dmxKeyboardBellProc, - dmxKeyboardKbdCtrlProc); - - if (info->freenames) dmxKeyboardFreeNames(&info->names); - - return Success; -} - - -static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) -{ - GETDMXINPUTFROMPDEVICE; - int fd; - DMXLocalInitInfo info; - int i; - Atom btn_labels[MAX_BUTTONS] = {0}; /* FIXME */ - Atom axis_labels[MAX_VALUATORS] = {0}; /* FIXME */ - - if (dmxInput->detached) return Success; - - memset(&info, 0, sizeof(info)); - switch (what) { - case DEVICE_INIT: - if (dmxLocal->init) - dmxLocal->init(pDev); - if (dmxLocal->get_info) - dmxLocal->get_info(pDev, &info); - if (info.keyboard) { /* XKEYBOARD makes this a special case */ - dmxKeyboardOn(pDevice, &info); - break; - } - if (info.keyClass) { - XkbRMLVOSet rmlvo; - - rmlvo.rules = dmxConfigGetXkbRules(); - rmlvo.model = dmxConfigGetXkbModel(); - rmlvo.layout = dmxConfigGetXkbLayout(); - rmlvo.variant = dmxConfigGetXkbVariant(); - rmlvo.options = dmxConfigGetXkbOptions(); - - InitKeyboardDeviceStruct(pDevice, - &rmlvo, - dmxBell, dmxKbdCtrl); - } - if (info.buttonClass) { - InitButtonClassDeviceStruct(pDevice, info.numButtons, - btn_labels, info.map); - } - if (info.valuatorClass) { - if (info.numRelAxes && dmxLocal->sendsCore) { - InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, - axis_labels, - GetMaximumEventsNum(), - Relative); - for (i = 0; i < info.numRelAxes; i++) - InitValuatorAxisStruct(pDevice, i, axis_labels[i], - info.minval[i], info.maxval[i], - info.res[i], - info.minres[i], info.maxres[i]); - } else if (info.numRelAxes) { - InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, - axis_labels, - dmxPointerGetMotionBufferSize(), - Relative); - for (i = 0; i < info.numRelAxes; i++) - InitValuatorAxisStruct(pDevice, i, axis_labels[i], - info.minval[i], - info.maxval[i], info.res[i], - info.minres[i], info.maxres[i]); - } else if (info.numAbsAxes) { - InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes, - axis_labels, - dmxPointerGetMotionBufferSize(), - Absolute); - for (i = 0; i < info.numAbsAxes; i++) - InitValuatorAxisStruct(pDevice, i, - axis_labels[i], - info.minval[i], info.maxval[i], - info.res[i], info.minres[i], - info.maxres[i]); - } - } - if (info.focusClass) InitFocusClassDeviceStruct(pDevice); - if (info.proximityClass) InitProximityClassDeviceStruct(pDevice); - if (info.ptrFeedbackClass) - InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl); - if (info.intFeedbackClass || info.strFeedbackClass) - dmxLog(dmxWarning, - "Integer and string feedback not supported for %s\n", - pDevice->name); - if (!info.keyboard && (info.ledFeedbackClass || info.belFeedbackClass)) - dmxLog(dmxWarning, - "Led and bel feedback not supported for non-keyboard %s\n", - pDevice->name); - break; - case DEVICE_ON: - if (!pDev->on) { - if (dmxLocal->on && (fd = dmxLocal->on(pDev)) >= 0) - dmxSigioRegister(dmxInput, fd); - pDev->on = TRUE; - } - break; - case DEVICE_OFF: - case DEVICE_CLOSE: - /* This can get called twice consecutively: once for a - * detached screen (DEVICE_OFF), and then again at server - * generation time (DEVICE_CLOSE). */ - if (pDev->on) { - dmxSigioUnregister(dmxInput); - if (dmxLocal->off) dmxLocal->off(pDev); - pDev->on = FALSE; - } - break; - } - if (info.keySyms.map && info.freemap) { - XFree(info.keySyms.map); - info.keySyms.map = NULL; - } - if (info.xkb) XkbFreeKeyboard(info.xkb, 0, True); - return Success; -} - -static void dmxProcessInputEvents(DMXInputInfo *dmxInput) -{ - int i; - - mieqProcessInputEvents(); -#if 00 /*BP*/ - miPointerUpdate(); -#endif - if (dmxInput->detached) - return; - for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) - if (dmxInput->devs[i]->process_input) { -#if 11 /*BP*/ - miPointerUpdateSprite(dmxInput->devs[i]->pDevice); -#endif - dmxInput->devs[i]->process_input(dmxInput->devs[i]->private); - } - -#if 11 /*BP*/ - mieqProcessInputEvents(); -#endif -} - -static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput, - DMXUpdateType type, - WindowPtr pWindow) -{ - int i; - -#ifdef PANORAMIX - if (!noPanoramiXExtension && pWindow && pWindow->parent != WindowTable[0]) - return; -#endif -#if DMX_WINDOW_DEBUG - { - const char *name = "Unknown"; - switch (type) { - case DMX_UPDATE_REALIZE: name = "Realize"; break; - case DMX_UPDATE_UNREALIZE: name = "Unrealize"; break; - case DMX_UPDATE_RESTACK: name = "Restack"; break; - case DMX_UPDATE_COPY: name = "Copy"; break; - case DMX_UPDATE_RESIZE: name = "Resize"; break; - case DMX_UPDATE_REPARENT: name = "Repaint"; break; - } - dmxLog(dmxDebug, "Window %p changed: %s\n", pWindow, name); - } -#endif - - if (dmxInput->detached) - return; - for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) - if (dmxInput->devs[i]->update_info) - dmxInput->devs[i]->update_info(dmxInput->devs[i]->private, - type, pWindow); -} - -static void dmxCollectAll(DMXInputInfo *dmxInput) -{ - int i; - - if (dmxInput->detached) - return; - for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) - if (dmxInput->devs[i]->collect_events) - dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice->public, - dmxMotion, - dmxEnqueue, - dmxCheckSpecialKeys, DMX_BLOCK); -} - -static void dmxBlockHandler(pointer blockData, OSTimePtr pTimeout, - pointer pReadMask) -{ - DMXInputInfo *dmxInput = &dmxInputs[(int)blockData]; - static unsigned long generation = 0; - - if (generation != serverGeneration) { - generation = serverGeneration; - dmxCollectAll(dmxInput); - } -} - -static void dmxSwitchReturn(pointer p) -{ - DMXInputInfo *dmxInput = p; - int i; - - dmxLog(dmxInfo, "Returning from VT %d\n", dmxInput->vt_switched); - - if (!dmxInput->vt_switched) - dmxLog(dmxFatal, "dmxSwitchReturn called, but not switched\n"); - dmxSigioEnableInput(); - for (i = 0; i < dmxInput->numDevs; i++) - if (dmxInput->devs[i]->vt_post_switch) - dmxInput->devs[i]->vt_post_switch(dmxInput->devs[i]->private); - dmxInput->vt_switched = 0; -} - -static void dmxWakeupHandler(pointer blockData, int result, pointer pReadMask) -{ - DMXInputInfo *dmxInput = &dmxInputs[(int)blockData]; - int i; - - if (dmxInput->vt_switch_pending) { - dmxLog(dmxInfo, "Switching to VT %d\n", dmxInput->vt_switch_pending); - for (i = 0; i < dmxInput->numDevs; i++) - if (dmxInput->devs[i]->vt_pre_switch) - dmxInput->devs[i]->vt_pre_switch(dmxInput->devs[i]->private); - dmxInput->vt_switched = dmxInput->vt_switch_pending; - dmxInput->vt_switch_pending = 0; - for (i = 0; i < dmxInput->numDevs; i++) { - if (dmxInput->devs[i]->vt_switch) { - dmxSigioDisableInput(); - if (!dmxInput->devs[i]->vt_switch(dmxInput->devs[i]->private, - dmxInput->vt_switched, - dmxSwitchReturn, - dmxInput)) - dmxSwitchReturn(dmxInput); - break; /* Only call one vt_switch routine */ - } - } - } - dmxCollectAll(dmxInput); -} - -static char *dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal) -{ - static int k = 0; - static int m = 0; - static int o = 0; - static unsigned long dmxGeneration = 0; -#define LEN 32 - char * buf = xalloc(LEN); - - if (dmxGeneration != serverGeneration) { - k = m = o = 0; - dmxGeneration = serverGeneration; - } - - switch (dmxLocal->type) { - case DMX_LOCAL_KEYBOARD: XmuSnprintf(buf, LEN, "Keyboard%d", k++); break; - case DMX_LOCAL_MOUSE: XmuSnprintf(buf, LEN, "Mouse%d", m++); break; - default: XmuSnprintf(buf, LEN, "Other%d", o++); break; - } - - return buf; -} - -static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal) -{ - DeviceIntPtr pDevice; - Atom atom; - const char *name = NULL; - void (*registerProcPtr)(DeviceIntPtr) = NULL; - char *devname; - DMXInputInfo *dmxInput; - - if (!dmxLocal) - return NULL; - dmxInput = &dmxInputs[dmxLocal->inputIdx]; - - if (dmxLocal->sendsCore) { - if (dmxLocal->type == DMX_LOCAL_KEYBOARD && !dmxLocalCoreKeyboard) { - dmxLocal->isCore = 1; - dmxLocalCoreKeyboard = dmxLocal; - name = "keyboard"; - registerProcPtr = RegisterKeyboardDevice; - } - if (dmxLocal->type == DMX_LOCAL_MOUSE && !dmxLocalCorePointer) { - dmxLocal->isCore = 1; - dmxLocalCorePointer = dmxLocal; - name = "pointer"; - registerProcPtr = RegisterPointerDevice; - } - } - - if (!name) { - name = "extension"; - registerProcPtr = RegisterOtherDevice; - } - - if (!name || !registerProcPtr) - dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name); - - pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE); - if (!pDevice) { - dmxLog(dmxError, "Too many devices -- cannot add device %s\n", - dmxLocal->name); - return NULL; - } - pDevice->public.devicePrivate = dmxLocal; - dmxLocal->pDevice = pDevice; - - devname = dmxMakeUniqueDeviceName(dmxLocal); - atom = MakeAtom((char *)devname, strlen(devname), TRUE); - pDevice->type = atom; - pDevice->name = devname; - - registerProcPtr(pDevice); - - if (dmxLocal->isCore && dmxLocal->type == DMX_LOCAL_MOUSE) { -#if 00 /*BP*/ - miRegisterPointerDevice(screenInfo.screens[0], pDevice); -#else - /* Nothing? dmxDeviceOnOff() should get called to init, right? */ -#endif - } - - if (dmxLocal->create_private) - dmxLocal->private = dmxLocal->create_private(pDevice); - - dmxLogInput(dmxInput, "Added %s as %s device called %s%s\n", - dmxLocal->name, name, devname, - dmxLocal->isCore - ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); - - return pDevice; -} - -static DMXLocalInputInfoPtr dmxLookupLocal(const char *name) -{ - DMXLocalInputInfoPtr pt; - - for (pt = &DMXLocalDevices[0]; pt->name; ++pt) - if (!strcmp(pt->name, name)) return pt; /* search for device name */ - return NULL; -} - -/** Copy the local input information from \a s into a new \a devs slot - * in \a dmxInput. */ -DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput, - DMXLocalInputInfoPtr s) -{ - DMXLocalInputInfoPtr dmxLocal = xalloc(sizeof(*dmxLocal)); - - if (!dmxLocal) - dmxLog(dmxFatal, "DMXLocalInputInfoPtr: out of memory\n"); - - memcpy(dmxLocal, s, sizeof(*dmxLocal)); - dmxLocal->inputIdx = dmxInput->inputIdx; - dmxLocal->sendsCore = dmxInput->core; - dmxLocal->savedSendsCore = dmxInput->core; - dmxLocal->deviceId = -1; - - ++dmxInput->numDevs; - dmxInput->devs = xrealloc(dmxInput->devs, - dmxInput->numDevs * sizeof(*dmxInput->devs)); - dmxInput->devs[dmxInput->numDevs-1] = dmxLocal; - - return dmxLocal; -} - -static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a) -{ - int i; - int help = 0; - DMXLocalInputInfoRec *pt; - - for (i = 1; i < dmxArgC(a); i++) { - const char *name = dmxArgV(a, i); - if ((pt = dmxLookupLocal(name))) { - dmxInputCopyLocal(dmxInput, pt); - } else { - if (strlen(name)) - dmxLog(dmxWarning, - "Could not find a driver called %s\n", name); - ++help; - } - } - if (help) { - dmxLog(dmxInfo, "Available local device drivers:\n"); - for (pt = &DMXLocalDevices[0]; pt->name; ++pt) { - const char *type; - switch (pt->type) { - case DMX_LOCAL_KEYBOARD: type = "keyboard"; break; - case DMX_LOCAL_MOUSE: type = "pointer"; break; - default: type = "unknown"; break; - } - dmxLog(dmxInfo, " %s (%s)\n", pt->name, type); - } - dmxLog(dmxFatal, "Must have valid local device driver\n"); - } -} - -int dmxInputExtensionErrorHandler(Display *dsp, char *name, char *reason) -{ - return 0; -} - -static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI) -{ - XExtensionVersion *ext; - XDeviceInfo *devices; - Display *display; - int num; - int i, j; - DMXLocalInputInfoPtr dmxLocal; - int (*handler)(Display *, char *, char *); - - if (!(display = XOpenDisplay(dmxInput->name))) return; - - /* Print out information about the XInput Extension. */ - handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler); - ext = XGetExtensionVersion(display, INAME); - XSetExtensionErrorHandler(handler); - - if (!ext || ext == (XExtensionVersion *)NoSuchExtension) { - dmxLogInput(dmxInput, "%s is not available\n", INAME); - } else { - dmxLogInput(dmxInput, "Locating devices on %s (%s version %d.%d)\n", - dmxInput->name, INAME, - ext->major_version, ext->minor_version); - devices = XListInputDevices(display, &num); - - XFree(ext); - ext = NULL; - - /* Print a list of all devices */ - for (i = 0; i < num; i++) { - const char *use = "Unknown"; - switch (devices[i].use) { - case IsXPointer: use = "XPointer"; break; - case IsXKeyboard: use = "XKeyboard"; break; - case IsXExtensionDevice: use = "XExtensionDevice"; break; - case IsXExtensionPointer: use = "XExtensionPointer"; break; - case IsXExtensionKeyboard: use = "XExtensionKeyboard"; break; - } - dmxLogInput(dmxInput, " %2d %-10.10s %-16.16s\n", - devices[i].id, - devices[i].name ? devices[i].name : "", - use); - } - - /* Search for extensions */ - for (i = 0; i < num; i++) { - switch (devices[i].use) { - case IsXKeyboard: - for (j = 0; j < dmxInput->numDevs; j++) { - DMXLocalInputInfoPtr dmxL = dmxInput->devs[j]; - if (dmxL->type == DMX_LOCAL_KEYBOARD - && dmxL->deviceId < 0) { - dmxL->deviceId = devices[i].id; - dmxL->deviceName = (devices[i].name - ? xstrdup(devices[i].name) - : NULL); - } - } - break; - case IsXPointer: - for (j = 0; j < dmxInput->numDevs; j++) { - DMXLocalInputInfoPtr dmxL = dmxInput->devs[j]; - if (dmxL->type == DMX_LOCAL_MOUSE && dmxL->deviceId < 0) { - dmxL->deviceId = devices[i].id; - dmxL->deviceName = (devices[i].name - ? xstrdup(devices[i].name) - : NULL); - } - } - break; -#if 0 - case IsXExtensionDevice: - case IsXExtensionKeyboard: - case IsXExtensionPointer: - if (doXI) { - if (!dmxInput->numDevs) { - dmxLog(dmxWarning, - "Cannot use remote (%s) XInput devices if" - " not also using core devices\n", - dmxInput->name); - } else { - dmxLocal = dmxInputCopyLocal(dmxInput, - &DMXCommonOth); - dmxLocal->isCore = FALSE; - dmxLocal->sendsCore = FALSE; - dmxLocal->deviceId = devices[i].id; - dmxLocal->deviceName = (devices[i].name - ? xstrdup(devices[i].name) - : NULL); - } - } - break; -#endif - } - } - XFreeDeviceList(devices); - } - XCloseDisplay(display); -} - -/** Re-initialize all the devices described in \a dmxInput. Called from - #dmxAdjustCursorBoundaries before the cursor is redisplayed. */ -void dmxInputReInit(DMXInputInfo *dmxInput) -{ - int i; - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - if (dmxLocal->reinit) - dmxLocal->reinit(&dmxLocal->pDevice->public); - } -} - -/** Re-initialize all the devices described in \a dmxInput. Called from - #dmxAdjustCursorBoundaries after the cursor is redisplayed. */ -void dmxInputLateReInit(DMXInputInfo *dmxInput) -{ - int i; - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - if (dmxLocal->latereinit) - dmxLocal->latereinit(&dmxLocal->pDevice->public); - } -} - -/** Initialize all of the devices described in \a dmxInput. */ -void dmxInputInit(DMXInputInfo *dmxInput) -{ - DeviceIntPtr pPointer = NULL, pKeyboard = NULL; - dmxArg a; - const char *name; - int i; - int doXI = 1; /* Include by default */ - int forceConsole = 0; - int doWindows = 1; /* On by default */ - int hasXkb = 0; - - a = dmxArgParse(dmxInput->name); - - for (i = 1; i < dmxArgC(a); i++) { - switch (hasXkb) { - case 1: - dmxInput->keycodes = xstrdup(dmxArgV(a, i)); - ++hasXkb; - break; - case 2: - dmxInput->symbols = xstrdup(dmxArgV(a, i)); - ++hasXkb; - break; - case 3: - dmxInput->geometry = xstrdup(dmxArgV(a, i)); - hasXkb = 0; - break; - case 0: - if (!strcmp(dmxArgV(a, i), "noxi")) doXI = 0; - else if (!strcmp(dmxArgV(a, i), "xi")) doXI = 1; - else if (!strcmp(dmxArgV(a, i), "console")) forceConsole = 1; - else if (!strcmp(dmxArgV(a, i), "noconsole")) forceConsole = 0; - else if (!strcmp(dmxArgV(a, i), "windows")) doWindows = 1; - else if (!strcmp(dmxArgV(a, i), "nowindows")) doWindows = 0; - else if (!strcmp(dmxArgV(a, i), "xkb")) hasXkb = 1; - else { - dmxLog(dmxFatal, - "Unknown input argument: %s\n", dmxArgV(a, i)); - } - } - } - - name = dmxArgV(a, 0); - - if (!strcmp(name, "local")) { - dmxPopulateLocal(dmxInput, a); - } else if (!strcmp(name, "dummy")) { - dmxInputCopyLocal(dmxInput, &DMXDummyMou); - dmxInputCopyLocal(dmxInput, &DMXDummyKbd); - dmxLogInput(dmxInput, "Using dummy input\n"); - } else { - int found; - - for (found = 0, i = 0; i < dmxNumScreens; i++) { - if (dmxPropertySameDisplay(&dmxScreens[i], name)) { - if (dmxScreens[i].shared) - dmxLog(dmxFatal, - "Cannot take input from shared backend (%s)\n", - name); - if (!dmxInput->core) { - dmxLog(dmxWarning, - "Cannot use core devices on a backend (%s)" - " as XInput devices\n", name); - } else { - char *pt; - for (pt = (char *)dmxInput->name; pt && *pt; pt++) - if (*pt == ',') *pt = '\0'; - dmxInputCopyLocal(dmxInput, &DMXBackendMou); - dmxInputCopyLocal(dmxInput, &DMXBackendKbd); - dmxInput->scrnIdx = i; - dmxLogInput(dmxInput, - "Using backend input from %s\n", name); - } - ++found; - break; - } - } - if (!found || forceConsole) { - char *pt; - if (found) dmxInput->console = TRUE; - for (pt = (char *)dmxInput->name; pt && *pt; pt++) - if (*pt == ',') *pt = '\0'; - dmxInputCopyLocal(dmxInput, &DMXConsoleMou); - dmxInputCopyLocal(dmxInput, &DMXConsoleKbd); - if (doWindows) { - dmxInput->windows = TRUE; - dmxInput->updateWindowInfo = dmxUpdateWindowInformation; - } - dmxLogInput(dmxInput, - "Using console input from %s (%s windows)\n", - name, doWindows ? "with" : "without"); - } - } - - dmxArgFree(a); - - /* Locate extensions we may be interested in */ - dmxInputScanForExtensions(dmxInput, doXI); - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - dmxLocal->pDevice = dmxAddDevice(dmxLocal); - if (dmxLocal->isCore) { - if (dmxLocal->type == DMX_LOCAL_MOUSE) - pPointer = dmxLocal->pDevice; - if (dmxLocal->type == DMX_LOCAL_KEYBOARD) - pKeyboard = dmxLocal->pDevice; - } - } - - dmxInput->processInputEvents = dmxProcessInputEvents; - dmxInput->detached = False; - - RegisterBlockAndWakeupHandlers(dmxBlockHandler, - dmxWakeupHandler, - (void *)dmxInput->inputIdx); -} - -static void dmxInputFreeLocal(DMXLocalInputInfoRec *local) -{ - if (!local) return; - if (local->isCore && local->type == DMX_LOCAL_MOUSE) - dmxLocalCorePointer = NULL; - if (local->isCore && local->type == DMX_LOCAL_KEYBOARD) - dmxLocalCoreKeyboard = NULL; - if (local->destroy_private) local->destroy_private(local->private); - if (local->history) xfree(local->history); - if (local->valuators) xfree(local->valuators); - if (local->deviceName) xfree(local->deviceName); - local->private = NULL; - local->history = NULL; - local->deviceName = NULL; - xfree(local); -} - -/** Free all of the memory associated with \a dmxInput */ -void dmxInputFree(DMXInputInfo *dmxInput) -{ - int i; - - if (!dmxInput) return; - - if (dmxInput->keycodes) xfree(dmxInput->keycodes); - if (dmxInput->symbols) xfree(dmxInput->symbols); - if (dmxInput->geometry) xfree(dmxInput->geometry); - - for (i = 0; i < dmxInput->numDevs; i++) { - dmxInputFreeLocal(dmxInput->devs[i]); - dmxInput->devs[i] = NULL; - } - xfree(dmxInput->devs); - dmxInput->devs = NULL; - dmxInput->numDevs = 0; - if (dmxInput->freename) xfree(dmxInput->name); - dmxInput->name = NULL; -} - -/** Log information about all of the known devices using #dmxLog(). */ -void dmxInputLogDevices(void) -{ - int i, j; - - dmxLog(dmxInfo, "%d devices:\n", dmxGetInputCount()); - dmxLog(dmxInfo, " Id Name Classes\n"); - for (j = 0; j < dmxNumInputs; j++) { - DMXInputInfo *dmxInput = &dmxInputs[j]; - const char *pt = strchr(dmxInput->name, ','); - int len = (pt - ? (size_t)(pt-dmxInput->name) - : strlen(dmxInput->name)); - - for (i = 0; i < dmxInput->numDevs; i++) { - DeviceIntPtr pDevice = dmxInput->devs[i]->pDevice; - if (pDevice) { - dmxLog(dmxInfo, " %2d%c %-20.20s", - pDevice->id, - dmxInput->detached ? 'D' : ' ', - pDevice->name); - if (pDevice->key) dmxLogCont(dmxInfo, " key"); - if (pDevice->valuator) dmxLogCont(dmxInfo, " val"); - if (pDevice->button) dmxLogCont(dmxInfo, " btn"); - if (pDevice->focus) dmxLogCont(dmxInfo, " foc"); - if (pDevice->kbdfeed) dmxLogCont(dmxInfo, " fb/kbd"); - if (pDevice->ptrfeed) dmxLogCont(dmxInfo, " fb/ptr"); - if (pDevice->intfeed) dmxLogCont(dmxInfo, " fb/int"); - if (pDevice->stringfeed) dmxLogCont(dmxInfo, " fb/str"); - if (pDevice->bell) dmxLogCont(dmxInfo, " fb/bel"); - if (pDevice->leds) dmxLogCont(dmxInfo, " fb/led"); - if (!pDevice->key && !pDevice->valuator && !pDevice->button - && !pDevice->focus && !pDevice->kbdfeed - && !pDevice->ptrfeed && !pDevice->intfeed - && !pDevice->stringfeed && !pDevice->bell - && !pDevice->leds) dmxLogCont(dmxInfo, " (none)"); - - dmxLogCont(dmxInfo, "\t[i%d/%*.*s", - dmxInput->inputIdx, len, len, dmxInput->name); - if (dmxInput->devs[i]->deviceId >= 0) - dmxLogCont(dmxInfo, "/id%d", dmxInput->devs[i]->deviceId); - if (dmxInput->devs[i]->deviceName) - dmxLogCont(dmxInfo, "=%s", dmxInput->devs[i]->deviceName); - dmxLogCont(dmxInfo, "] %s\n", - dmxInput->devs[i]->isCore - ? "core" - : (dmxInput->devs[i]->sendsCore - ? "extension (sends core events)" - : "extension")); - } - } - } -} - -/** Detach an input */ -int dmxInputDetach(DMXInputInfo *dmxInput) -{ - int i; - - if (dmxInput->detached) return BadAccess; - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - dmxLogInput(dmxInput, "Detaching device id %d: %s%s\n", - dmxLocal->pDevice->id, - dmxLocal->pDevice->name, - dmxLocal->isCore - ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); - DisableDevice(dmxLocal->pDevice, TRUE); - } - dmxInput->detached = True; - dmxInputLogDevices(); - return 0; -} - -/** Search for input associated with \a dmxScreen, and detach. */ -void dmxInputDetachAll(DMXScreenInfo *dmxScreen) -{ - int i; - - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->scrnIdx == dmxScreen->index) dmxInputDetach(dmxInput); - } -} - -/** Search for input associated with \a deviceId, and detach. */ -int dmxInputDetachId(int id) -{ - DMXInputInfo *dmxInput = dmxInputLocateId(id); - - if (!dmxInput) return BadValue; - - return dmxInputDetach(dmxInput); -} - -DMXInputInfo *dmxInputLocateId(int id) -{ - int i, j; - - for (i = 0; i < dmxNumInputs; i++) { - DMXInputInfo *dmxInput = &dmxInputs[i]; - for (j = 0; j < dmxInput->numDevs; j++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j]; - if (dmxLocal->pDevice->id == id) return dmxInput; - } - } - return NULL; -} - -static int dmxInputAttachNew(DMXInputInfo *dmxInput, int *id) -{ - dmxInputInit(dmxInput); - InitAndStartDevices(); - if (id && dmxInput->devs) *id = dmxInput->devs[0]->pDevice->id; - dmxInputLogDevices(); - return 0; -} - -static int dmxInputAttachOld(DMXInputInfo *dmxInput, int *id) -{ - int i; - - dmxInput->detached = False; - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - if (id) *id = dmxLocal->pDevice->id; - dmxLogInput(dmxInput, - "Attaching device id %d: %s%s\n", - dmxLocal->pDevice->id, - dmxLocal->pDevice->name, - dmxLocal->isCore - ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); - EnableDevice(dmxLocal->pDevice, TRUE); - } - dmxInputLogDevices(); - return 0; -} - -int dmxInputAttachConsole(const char *name, int isCore, int *id) -{ - DMXInputInfo *dmxInput; - int i; - - for (i = 0; i < dmxNumInputs; i++) { - dmxInput = &dmxInputs[i]; - if (dmxInput->scrnIdx == -1 - && dmxInput->detached - && !strcmp(dmxInput->name, name)) { - /* Found match */ - dmxLogInput(dmxInput, "Reattaching detached console input\n"); - return dmxInputAttachOld(dmxInput, id); - } - } - - /* No match found */ - dmxInput = dmxConfigAddInput(xstrdup(name), isCore); - dmxInput->freename = TRUE; - dmxLogInput(dmxInput, "Attaching new console input\n"); - return dmxInputAttachNew(dmxInput, id); -} - -int dmxInputAttachBackend(int physicalScreen, int isCore, int *id) -{ - DMXInputInfo *dmxInput; - DMXScreenInfo *dmxScreen; - int i; - - if (physicalScreen < 0 || physicalScreen >= dmxNumScreens) return BadValue; - for (i = 0; i < dmxNumInputs; i++) { - dmxInput = &dmxInputs[i]; - if (dmxInput->scrnIdx != -1 && dmxInput->scrnIdx == physicalScreen) { - /* Found match */ - if (!dmxInput->detached) return BadAccess; /* Already attached */ - dmxScreen = &dmxScreens[physicalScreen]; - if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ - dmxLogInput(dmxInput, "Reattaching detached backend input\n"); - return dmxInputAttachOld(dmxInput, id); - } - } - /* No match found */ - dmxScreen = &dmxScreens[physicalScreen]; - if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ - dmxInput = dmxConfigAddInput(dmxScreen->name, isCore); - dmxLogInput(dmxInput, "Attaching new backend input\n"); - return dmxInputAttachNew(dmxInput, id); -} +/* + * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: + * Rickard E. (Rik) Faith <faith@redhat.com> + * + */ + +/** \file + * This file provides generic input support. Functions here set up + * input and lead to the calling of low-level device drivers for + * input. */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#define DMX_WINDOW_DEBUG 0 + +#include "dmxinputinit.h" +#include "dmxextension.h" /* For dmxInputCount */ + +#include "dmxdummy.h" +#include "dmxbackend.h" +#include "dmxconsole.h" +#include "dmxcommon.h" +#include "dmxevents.h" +#include "dmxmotion.h" +#include "dmxprop.h" +#include "config/dmxconfig.h" +#include "dmxcursor.h" + +#include "lnx-keyboard.h" +#include "lnx-ms.h" +#include "lnx-ps2.h" +#include "usb-keyboard.h" +#include "usb-mouse.h" +#include "usb-other.h" +#include "usb-common.h" + +#include "dmxsigio.h" +#include "dmxarg.h" + +#include "inputstr.h" +#include "input.h" +#include "mipointer.h" +#include "windowstr.h" +#include "mi.h" +#include "xkbsrv.h" + +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "exevents.h" +#include "extinit.h" + +DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard; + +static DMXLocalInputInfoRec DMXDummyMou = { + "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo +}; + +static DMXLocalInputInfoRec DMXDummyKbd = { + "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, + NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo +}; + +static DMXLocalInputInfoRec DMXBackendMou = { + "backend-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_BACKEND, 2, + dmxBackendCreatePrivate, dmxBackendDestroyPrivate, + dmxBackendInit, NULL, dmxBackendLateReInit, dmxBackendMouGetInfo, + dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition, + NULL, NULL, NULL, + dmxBackendCollectEvents, dmxBackendProcessInput, dmxBackendFunctions, NULL, + dmxCommonMouCtrl +}; + +static DMXLocalInputInfoRec DMXBackendKbd = { + "backend-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_BACKEND, + 1, /* With backend-mou or console-mou */ + dmxCommonCopyPrivate, NULL, + dmxBackendInit, NULL, NULL, dmxBackendKbdGetInfo, + dmxCommonKbdOn, dmxCommonKbdOff, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, dmxCommonKbdCtrl, dmxCommonKbdBell +}; + +static DMXLocalInputInfoRec DMXConsoleMou = { + "console-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_CONSOLE, 2, + dmxConsoleCreatePrivate, dmxConsoleDestroyPrivate, + dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleMouGetInfo, + dmxCommonMouOn, dmxCommonMouOff, dmxConsoleUpdatePosition, + NULL, NULL, NULL, + dmxConsoleCollectEvents, NULL, dmxConsoleFunctions, dmxConsoleUpdateInfo, + dmxCommonMouCtrl +}; + +static DMXLocalInputInfoRec DMXConsoleKbd = { + "console-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_CONSOLE, + 1, /* With backend-mou or console-mou */ + dmxCommonCopyPrivate, NULL, + dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo, + dmxCommonKbdOn, dmxCommonKbdOff, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, dmxCommonKbdCtrl, dmxCommonKbdBell +}; + +static DMXLocalInputInfoRec DMXCommonOth = { + "common-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_COMMON, 1, + dmxCommonCopyPrivate, NULL, + NULL, NULL, NULL, dmxCommonOthGetInfo, + dmxCommonOthOn, dmxCommonOthOff +}; + + +static DMXLocalInputInfoRec DMXLocalDevices[] = { + /* Dummy drivers that can compile on any OS */ +#ifdef __linux__ + /* Linux-specific drivers */ + { + "kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, + kbdLinuxCreatePrivate, kbdLinuxDestroyPrivate, + kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo, + kbdLinuxOn, kbdLinuxOff, NULL, + kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch, + kbdLinuxRead, NULL, NULL, NULL, + NULL, kbdLinuxCtrl, kbdLinuxBell + }, + { + "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + msLinuxCreatePrivate, msLinuxDestroyPrivate, + msLinuxInit, NULL, NULL, msLinuxGetInfo, + msLinuxOn, msLinuxOff, NULL, + msLinuxVTPreSwitch, msLinuxVTPostSwitch, NULL, + msLinuxRead + }, + { + "ps2", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + ps2LinuxCreatePrivate, ps2LinuxDestroyPrivate, + ps2LinuxInit, NULL, NULL, ps2LinuxGetInfo, + ps2LinuxOn, ps2LinuxOff, NULL, + ps2LinuxVTPreSwitch, ps2LinuxVTPostSwitch, NULL, + ps2LinuxRead + }, +#endif +#ifdef __linux__ + /* USB drivers, currently only for + Linux, but relatively easy to port to + other OSs */ + { + "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, + usbCreatePrivate, usbDestroyPrivate, + kbdUSBInit, NULL, NULL, kbdUSBGetInfo, + kbdUSBOn, usbOff, NULL, + NULL, NULL, NULL, + kbdUSBRead, NULL, NULL, NULL, + NULL, kbdUSBCtrl + }, + { + "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + usbCreatePrivate, usbDestroyPrivate, + mouUSBInit, NULL, NULL, mouUSBGetInfo, + mouUSBOn, usbOff, NULL, + NULL, NULL, NULL, + mouUSBRead + }, + { + "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1, + usbCreatePrivate, usbDestroyPrivate, + othUSBInit, NULL, NULL, othUSBGetInfo, + othUSBOn, usbOff, NULL, + NULL, NULL, NULL, + othUSBRead + }, +#endif + { + "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo + }, + { + "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, + NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo + }, + { NULL } /* Must be last */ +}; + + +#if 11 /*BP*/ +void +DDXRingBell(int volume, int pitch, int duration) +{ + /* NO-OP */ +} + +/* taken from kdrive/src/kinput.c: */ +static void +dmxKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl) +{ +#if 0 + KdKeyboardInfo *ki; + + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki->dixdev && ki->dixdev->id == pDevice->id) + break; + } + + if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver) + return; + + KdSetLeds(ki, ctrl->leds); + ki->bellPitch = ctrl->bell_pitch; + ki->bellDuration = ctrl->bell_duration; +#endif +} + +/* taken from kdrive/src/kinput.c: */ +static void +dmxBell(int volume, DeviceIntPtr pDev, pointer arg, int something) +{ +#if 0 + KeybdCtrl *ctrl = arg; + KdKeyboardInfo *ki = NULL; + + for (ki = kdKeyboards; ki; ki = ki->next) { + if (ki->dixdev && ki->dixdev->id == pDev->id) + break; + } + + if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver) + return; + + KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration); +#endif +} + +#endif /*BP*/ + +static void _dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal, + PtrCtrl *ctrl) +{ + if (!dmxLocal) return; + dmxLocal->mctrl = *ctrl; + if (dmxLocal->mCtrl) dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl); +} + +/** Change the pointer control information for the \a pDevice. If the + * device sends core events, then also change the control information + * for all of the pointer devices that send core events. */ +void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl) +{ + GETDMXLOCALFROMPDEVICE; + int i, j; + + if (dmxLocal->sendsCore) { /* Do for all core devices */ + for (i = 0; i < dmxNumInputs; i++) { + DMXInputInfo *dmxInput = &dmxInputs[i]; + if (dmxInput->detached) continue; + for (j = 0; j < dmxInput->numDevs; j++) + if (dmxInput->devs[j]->sendsCore) + _dmxChangePointerControl(dmxInput->devs[j], ctrl); + } + } else { /* Do for this device only */ + _dmxChangePointerControl(dmxLocal, ctrl); + } +} + +static void _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal, + KeybdCtrl *ctrl) +{ + dmxLocal->kctrl = *ctrl; + if (dmxLocal->kCtrl) { + dmxLocal->kCtrl(&dmxLocal->pDevice->public, ctrl); + if (dmxLocal->pDevice->kbdfeed) { + XkbEventCauseRec cause; + XkbSetCauseUnknown(&cause); + /* Generate XKB events, as necessary */ + XkbUpdateIndicators(dmxLocal->pDevice, XkbAllIndicatorsMask, False, + NULL, &cause); + } + } +} + + +/** Change the keyboard control information for the \a pDevice. If the + * device sends core events, then also change the control information + * for all of the keyboard devices that send core events. */ +void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl) +{ + GETDMXLOCALFROMPDEVICE; + int i, j; + + if (dmxLocal->sendsCore) { /* Do for all core devices */ + for (i = 0; i < dmxNumInputs; i++) { + DMXInputInfo *dmxInput = &dmxInputs[i]; + if (dmxInput->detached) continue; + for (j = 0; j < dmxInput->numDevs; j++) + if (dmxInput->devs[j]->sendsCore) + _dmxKeyboardKbdCtrlProc(dmxInput->devs[j], ctrl); + } + } else { /* Do for this device only */ + _dmxKeyboardKbdCtrlProc(dmxLocal, ctrl); + } +} + +static void _dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent) +{ + if (dmxLocal->kBell) dmxLocal->kBell(&dmxLocal->pDevice->public, + percent, + dmxLocal->kctrl.bell, + dmxLocal->kctrl.bell_pitch, + dmxLocal->kctrl.bell_duration); +} + +/** Sound the bell on the device. If the device send core events, then + * sound the bell on all of the devices that send core events. */ +void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice, + pointer ctrl, int unknown) +{ + GETDMXLOCALFROMPDEVICE; + int i, j; + + if (dmxLocal->sendsCore) { /* Do for all core devices */ + for (i = 0; i < dmxNumInputs; i++) { + DMXInputInfo *dmxInput = &dmxInputs[i]; + if (dmxInput->detached) continue; + for (j = 0; j < dmxInput->numDevs; j++) + if (dmxInput->devs[j]->sendsCore) + _dmxKeyboardBellProc(dmxInput->devs[j], percent); + } + } else { /* Do for this device only */ + _dmxKeyboardBellProc(dmxLocal, percent); + } +} + +static void dmxKeyboardFreeNames(XkbComponentNamesPtr names) +{ + if (names->keycodes) XFree(names->keycodes); + if (names->types) XFree(names->types); + if (names->compat) XFree(names->compat); + if (names->symbols) XFree(names->symbols); + if (names->geometry) XFree(names->geometry); +} + + +static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info) +{ + GETDMXINPUTFROMPDEVICE; + XkbRMLVOSet rmlvo; + + rmlvo.rules = dmxConfigGetXkbRules(); + rmlvo.model = dmxConfigGetXkbModel(); + rmlvo.layout = dmxConfigGetXkbLayout(); + rmlvo.variant = dmxConfigGetXkbVariant(); + rmlvo.options = dmxConfigGetXkbOptions(); + + XkbSetRulesDflts(&rmlvo); + if (!info->force && (dmxInput->keycodes + || dmxInput->symbols + || dmxInput->geometry)) { + if (info->freenames) dmxKeyboardFreeNames(&info->names); + info->freenames = 0; + info->names.keycodes = dmxInput->keycodes; + info->names.types = NULL; + info->names.compat = NULL; + info->names.symbols = dmxInput->symbols; + info->names.geometry = dmxInput->geometry; + + dmxLogInput(dmxInput, "XKEYBOARD: From command line: %s", + info->names.keycodes); + if (info->names.symbols && *info->names.symbols) + dmxLogInputCont(dmxInput, " %s", info->names.symbols); + if (info->names.geometry && *info->names.geometry) + dmxLogInputCont(dmxInput, " %s", info->names.geometry); + dmxLogInputCont(dmxInput, "\n"); + } else if (info->names.keycodes) { + dmxLogInput(dmxInput, "XKEYBOARD: From device: %s", + info->names.keycodes); + if (info->names.symbols && *info->names.symbols) + dmxLogInputCont(dmxInput, " %s", info->names.symbols); + if (info->names.geometry && *info->names.geometry) + dmxLogInputCont(dmxInput, " %s", info->names.geometry); + dmxLogInputCont(dmxInput, "\n"); + } else { + dmxLogInput(dmxInput, "XKEYBOARD: Defaults: %s %s %s %s %s\n", + dmxConfigGetXkbRules(), + dmxConfigGetXkbLayout(), + dmxConfigGetXkbModel(), + dmxConfigGetXkbVariant() + ? dmxConfigGetXkbVariant() : "", + dmxConfigGetXkbOptions() + ? dmxConfigGetXkbOptions() : ""); + } + InitKeyboardDeviceStruct(pDevice, &rmlvo, + dmxKeyboardBellProc, + dmxKeyboardKbdCtrlProc); + + if (info->freenames) dmxKeyboardFreeNames(&info->names); + + return Success; +} + + +static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) +{ + GETDMXINPUTFROMPDEVICE; + int fd; + DMXLocalInitInfo info; + int i; + Atom btn_labels[MAX_BUTTONS] = {0}; /* FIXME */ + Atom axis_labels[MAX_VALUATORS] = {0}; /* FIXME */ + + if (dmxInput->detached) return Success; + + memset(&info, 0, sizeof(info)); + switch (what) { + case DEVICE_INIT: + if (dmxLocal->init) + dmxLocal->init(pDev); + if (dmxLocal->get_info) + dmxLocal->get_info(pDev, &info); + if (info.keyboard) { /* XKEYBOARD makes this a special case */ + dmxKeyboardOn(pDevice, &info); + break; + } + if (info.keyClass) { + XkbRMLVOSet rmlvo; + + rmlvo.rules = dmxConfigGetXkbRules(); + rmlvo.model = dmxConfigGetXkbModel(); + rmlvo.layout = dmxConfigGetXkbLayout(); + rmlvo.variant = dmxConfigGetXkbVariant(); + rmlvo.options = dmxConfigGetXkbOptions(); + + InitKeyboardDeviceStruct(pDevice, + &rmlvo, + dmxBell, dmxKbdCtrl); + } + if (info.buttonClass) { + InitButtonClassDeviceStruct(pDevice, info.numButtons, + btn_labels, info.map); + } + if (info.valuatorClass) { + if (info.numRelAxes && dmxLocal->sendsCore) { + InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, + axis_labels, + GetMaximumEventsNum(), + Relative); + for (i = 0; i < info.numRelAxes; i++) + InitValuatorAxisStruct(pDevice, i, axis_labels[i], + info.minval[i], info.maxval[i], + info.res[i], + info.minres[i], info.maxres[i]); + } else if (info.numRelAxes) { + InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, + axis_labels, + dmxPointerGetMotionBufferSize(), + Relative); + for (i = 0; i < info.numRelAxes; i++) + InitValuatorAxisStruct(pDevice, i, axis_labels[i], + info.minval[i], + info.maxval[i], info.res[i], + info.minres[i], info.maxres[i]); + } else if (info.numAbsAxes) { + InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes, + axis_labels, + dmxPointerGetMotionBufferSize(), + Absolute); + for (i = 0; i < info.numAbsAxes; i++) + InitValuatorAxisStruct(pDevice, i, + axis_labels[i], + info.minval[i], info.maxval[i], + info.res[i], info.minres[i], + info.maxres[i]); + } + } + if (info.focusClass) InitFocusClassDeviceStruct(pDevice); + if (info.proximityClass) InitProximityClassDeviceStruct(pDevice); + if (info.ptrFeedbackClass) + InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl); + if (info.intFeedbackClass || info.strFeedbackClass) + dmxLog(dmxWarning, + "Integer and string feedback not supported for %s\n", + pDevice->name); + if (!info.keyboard && (info.ledFeedbackClass || info.belFeedbackClass)) + dmxLog(dmxWarning, + "Led and bel feedback not supported for non-keyboard %s\n", + pDevice->name); + break; + case DEVICE_ON: + if (!pDev->on) { + if (dmxLocal->on && (fd = dmxLocal->on(pDev)) >= 0) + dmxSigioRegister(dmxInput, fd); + pDev->on = TRUE; + } + break; + case DEVICE_OFF: + case DEVICE_CLOSE: + /* This can get called twice consecutively: once for a + * detached screen (DEVICE_OFF), and then again at server + * generation time (DEVICE_CLOSE). */ + if (pDev->on) { + dmxSigioUnregister(dmxInput); + if (dmxLocal->off) dmxLocal->off(pDev); + pDev->on = FALSE; + } + break; + } + if (info.keySyms.map && info.freemap) { + XFree(info.keySyms.map); + info.keySyms.map = NULL; + } + if (info.xkb) XkbFreeKeyboard(info.xkb, 0, True); + return Success; +} + +static void dmxProcessInputEvents(DMXInputInfo *dmxInput) +{ + int i; + + mieqProcessInputEvents(); +#if 00 /*BP*/ + miPointerUpdate(); +#endif + if (dmxInput->detached) + return; + for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) + if (dmxInput->devs[i]->process_input) { +#if 11 /*BP*/ + miPointerUpdateSprite(dmxInput->devs[i]->pDevice); +#endif + dmxInput->devs[i]->process_input(dmxInput->devs[i]->private); + } + +#if 11 /*BP*/ + mieqProcessInputEvents(); +#endif +} + +static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput, + DMXUpdateType type, + WindowPtr pWindow) +{ + int i; + +#ifdef PANORAMIX + if (!noPanoramiXExtension && pWindow && pWindow->parent != WindowTable[0]) + return; +#endif +#if DMX_WINDOW_DEBUG + { + const char *name = "Unknown"; + switch (type) { + case DMX_UPDATE_REALIZE: name = "Realize"; break; + case DMX_UPDATE_UNREALIZE: name = "Unrealize"; break; + case DMX_UPDATE_RESTACK: name = "Restack"; break; + case DMX_UPDATE_COPY: name = "Copy"; break; + case DMX_UPDATE_RESIZE: name = "Resize"; break; + case DMX_UPDATE_REPARENT: name = "Repaint"; break; + } + dmxLog(dmxDebug, "Window %p changed: %s\n", pWindow, name); + } +#endif + + if (dmxInput->detached) + return; + for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) + if (dmxInput->devs[i]->update_info) + dmxInput->devs[i]->update_info(dmxInput->devs[i]->private, + type, pWindow); +} + +static void dmxCollectAll(DMXInputInfo *dmxInput) +{ + int i; + + if (dmxInput->detached) + return; + for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) + if (dmxInput->devs[i]->collect_events) + dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice->public, + dmxMotion, + dmxEnqueue, + dmxCheckSpecialKeys, DMX_BLOCK); +} + +static void dmxBlockHandler(pointer blockData, OSTimePtr pTimeout, + pointer pReadMask) +{ + DMXInputInfo *dmxInput = &dmxInputs[(int)blockData]; + static unsigned long generation = 0; + + if (generation != serverGeneration) { + generation = serverGeneration; + dmxCollectAll(dmxInput); + } +} + +static void dmxSwitchReturn(pointer p) +{ + DMXInputInfo *dmxInput = p; + int i; + + dmxLog(dmxInfo, "Returning from VT %d\n", dmxInput->vt_switched); + + if (!dmxInput->vt_switched) + dmxLog(dmxFatal, "dmxSwitchReturn called, but not switched\n"); + dmxSigioEnableInput(); + for (i = 0; i < dmxInput->numDevs; i++) + if (dmxInput->devs[i]->vt_post_switch) + dmxInput->devs[i]->vt_post_switch(dmxInput->devs[i]->private); + dmxInput->vt_switched = 0; +} + +static void dmxWakeupHandler(pointer blockData, int result, pointer pReadMask) +{ + DMXInputInfo *dmxInput = &dmxInputs[(int)blockData]; + int i; + + if (dmxInput->vt_switch_pending) { + dmxLog(dmxInfo, "Switching to VT %d\n", dmxInput->vt_switch_pending); + for (i = 0; i < dmxInput->numDevs; i++) + if (dmxInput->devs[i]->vt_pre_switch) + dmxInput->devs[i]->vt_pre_switch(dmxInput->devs[i]->private); + dmxInput->vt_switched = dmxInput->vt_switch_pending; + dmxInput->vt_switch_pending = 0; + for (i = 0; i < dmxInput->numDevs; i++) { + if (dmxInput->devs[i]->vt_switch) { + dmxSigioDisableInput(); + if (!dmxInput->devs[i]->vt_switch(dmxInput->devs[i]->private, + dmxInput->vt_switched, + dmxSwitchReturn, + dmxInput)) + dmxSwitchReturn(dmxInput); + break; /* Only call one vt_switch routine */ + } + } + } + dmxCollectAll(dmxInput); +} + +static char *dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal) +{ + static int k = 0; + static int m = 0; + static int o = 0; + static unsigned long dmxGeneration = 0; +#define LEN 32 + char * buf = malloc(LEN); + + if (dmxGeneration != serverGeneration) { + k = m = o = 0; + dmxGeneration = serverGeneration; + } + + switch (dmxLocal->type) { + case DMX_LOCAL_KEYBOARD: XmuSnprintf(buf, LEN, "Keyboard%d", k++); break; + case DMX_LOCAL_MOUSE: XmuSnprintf(buf, LEN, "Mouse%d", m++); break; + default: XmuSnprintf(buf, LEN, "Other%d", o++); break; + } + + return buf; +} + +static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal) +{ + DeviceIntPtr pDevice; + Atom atom; + const char *name = NULL; + void (*registerProcPtr)(DeviceIntPtr) = NULL; + char *devname; + DMXInputInfo *dmxInput; + + if (!dmxLocal) + return NULL; + dmxInput = &dmxInputs[dmxLocal->inputIdx]; + + if (dmxLocal->sendsCore) { + if (dmxLocal->type == DMX_LOCAL_KEYBOARD && !dmxLocalCoreKeyboard) { + dmxLocal->isCore = 1; + dmxLocalCoreKeyboard = dmxLocal; + name = "keyboard"; + registerProcPtr = RegisterKeyboardDevice; + } + if (dmxLocal->type == DMX_LOCAL_MOUSE && !dmxLocalCorePointer) { + dmxLocal->isCore = 1; + dmxLocalCorePointer = dmxLocal; + name = "pointer"; + registerProcPtr = RegisterPointerDevice; + } + } + + if (!name) { + name = "extension"; + registerProcPtr = RegisterOtherDevice; + } + + if (!name || !registerProcPtr) + dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name); + + pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE); + if (!pDevice) { + dmxLog(dmxError, "Too many devices -- cannot add device %s\n", + dmxLocal->name); + return NULL; + } + pDevice->public.devicePrivate = dmxLocal; + dmxLocal->pDevice = pDevice; + + devname = dmxMakeUniqueDeviceName(dmxLocal); + atom = MakeAtom((char *)devname, strlen(devname), TRUE); + pDevice->type = atom; + pDevice->name = devname; + + registerProcPtr(pDevice); + + if (dmxLocal->isCore && dmxLocal->type == DMX_LOCAL_MOUSE) { +#if 00 /*BP*/ + miRegisterPointerDevice(screenInfo.screens[0], pDevice); +#else + /* Nothing? dmxDeviceOnOff() should get called to init, right? */ +#endif + } + + if (dmxLocal->create_private) + dmxLocal->private = dmxLocal->create_private(pDevice); + + dmxLogInput(dmxInput, "Added %s as %s device called %s%s\n", + dmxLocal->name, name, devname, + dmxLocal->isCore + ? " [core]" + : (dmxLocal->sendsCore + ? " [sends core events]" + : "")); + + return pDevice; +} + +static DMXLocalInputInfoPtr dmxLookupLocal(const char *name) +{ + DMXLocalInputInfoPtr pt; + + for (pt = &DMXLocalDevices[0]; pt->name; ++pt) + if (!strcmp(pt->name, name)) return pt; /* search for device name */ + return NULL; +} + +/** Copy the local input information from \a s into a new \a devs slot + * in \a dmxInput. */ +DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput, + DMXLocalInputInfoPtr s) +{ + DMXLocalInputInfoPtr dmxLocal = malloc(sizeof(*dmxLocal)); + + if (!dmxLocal) + dmxLog(dmxFatal, "DMXLocalInputInfoPtr: out of memory\n"); + + memcpy(dmxLocal, s, sizeof(*dmxLocal)); + dmxLocal->inputIdx = dmxInput->inputIdx; + dmxLocal->sendsCore = dmxInput->core; + dmxLocal->savedSendsCore = dmxInput->core; + dmxLocal->deviceId = -1; + + ++dmxInput->numDevs; + dmxInput->devs = realloc(dmxInput->devs, + dmxInput->numDevs * sizeof(*dmxInput->devs)); + dmxInput->devs[dmxInput->numDevs-1] = dmxLocal; + + return dmxLocal; +} + +static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a) +{ + int i; + int help = 0; + DMXLocalInputInfoRec *pt; + + for (i = 1; i < dmxArgC(a); i++) { + const char *name = dmxArgV(a, i); + if ((pt = dmxLookupLocal(name))) { + dmxInputCopyLocal(dmxInput, pt); + } else { + if (strlen(name)) + dmxLog(dmxWarning, + "Could not find a driver called %s\n", name); + ++help; + } + } + if (help) { + dmxLog(dmxInfo, "Available local device drivers:\n"); + for (pt = &DMXLocalDevices[0]; pt->name; ++pt) { + const char *type; + switch (pt->type) { + case DMX_LOCAL_KEYBOARD: type = "keyboard"; break; + case DMX_LOCAL_MOUSE: type = "pointer"; break; + default: type = "unknown"; break; + } + dmxLog(dmxInfo, " %s (%s)\n", pt->name, type); + } + dmxLog(dmxFatal, "Must have valid local device driver\n"); + } +} + +int dmxInputExtensionErrorHandler(Display *dsp, char *name, char *reason) +{ + return 0; +} + +static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI) +{ + XExtensionVersion *ext; + XDeviceInfo *devices; + Display *display; + int num; + int i, j; + DMXLocalInputInfoPtr dmxLocal; + int (*handler)(Display *, char *, char *); + + if (!(display = XOpenDisplay(dmxInput->name))) return; + + /* Print out information about the XInput Extension. */ + handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler); + ext = XGetExtensionVersion(display, INAME); + XSetExtensionErrorHandler(handler); + + if (!ext || ext == (XExtensionVersion *)NoSuchExtension) { + dmxLogInput(dmxInput, "%s is not available\n", INAME); + } else { + dmxLogInput(dmxInput, "Locating devices on %s (%s version %d.%d)\n", + dmxInput->name, INAME, + ext->major_version, ext->minor_version); + devices = XListInputDevices(display, &num); + + XFree(ext); + ext = NULL; + + /* Print a list of all devices */ + for (i = 0; i < num; i++) { + const char *use = "Unknown"; + switch (devices[i].use) { + case IsXPointer: use = "XPointer"; break; + case IsXKeyboard: use = "XKeyboard"; break; + case IsXExtensionDevice: use = "XExtensionDevice"; break; + case IsXExtensionPointer: use = "XExtensionPointer"; break; + case IsXExtensionKeyboard: use = "XExtensionKeyboard"; break; + } + dmxLogInput(dmxInput, " %2d %-10.10s %-16.16s\n", + devices[i].id, + devices[i].name ? devices[i].name : "", + use); + } + + /* Search for extensions */ + for (i = 0; i < num; i++) { + switch (devices[i].use) { + case IsXKeyboard: + for (j = 0; j < dmxInput->numDevs; j++) { + DMXLocalInputInfoPtr dmxL = dmxInput->devs[j]; + if (dmxL->type == DMX_LOCAL_KEYBOARD + && dmxL->deviceId < 0) { + dmxL->deviceId = devices[i].id; + dmxL->deviceName = (devices[i].name + ? xstrdup(devices[i].name) + : NULL); + } + } + break; + case IsXPointer: + for (j = 0; j < dmxInput->numDevs; j++) { + DMXLocalInputInfoPtr dmxL = dmxInput->devs[j]; + if (dmxL->type == DMX_LOCAL_MOUSE && dmxL->deviceId < 0) { + dmxL->deviceId = devices[i].id; + dmxL->deviceName = (devices[i].name + ? xstrdup(devices[i].name) + : NULL); + } + } + break; +#if 0 + case IsXExtensionDevice: + case IsXExtensionKeyboard: + case IsXExtensionPointer: + if (doXI) { + if (!dmxInput->numDevs) { + dmxLog(dmxWarning, + "Cannot use remote (%s) XInput devices if" + " not also using core devices\n", + dmxInput->name); + } else { + dmxLocal = dmxInputCopyLocal(dmxInput, + &DMXCommonOth); + dmxLocal->isCore = FALSE; + dmxLocal->sendsCore = FALSE; + dmxLocal->deviceId = devices[i].id; + dmxLocal->deviceName = (devices[i].name + ? xstrdup(devices[i].name) + : NULL); + } + } + break; +#endif + } + } + XFreeDeviceList(devices); + } + XCloseDisplay(display); +} + +/** Re-initialize all the devices described in \a dmxInput. Called from + #dmxAdjustCursorBoundaries before the cursor is redisplayed. */ +void dmxInputReInit(DMXInputInfo *dmxInput) +{ + int i; + + for (i = 0; i < dmxInput->numDevs; i++) { + DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + if (dmxLocal->reinit) + dmxLocal->reinit(&dmxLocal->pDevice->public); + } +} + +/** Re-initialize all the devices described in \a dmxInput. Called from + #dmxAdjustCursorBoundaries after the cursor is redisplayed. */ +void dmxInputLateReInit(DMXInputInfo *dmxInput) +{ + int i; + + for (i = 0; i < dmxInput->numDevs; i++) { + DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + if (dmxLocal->latereinit) + dmxLocal->latereinit(&dmxLocal->pDevice->public); + } +} + +/** Initialize all of the devices described in \a dmxInput. */ +void dmxInputInit(DMXInputInfo *dmxInput) +{ + DeviceIntPtr pPointer = NULL, pKeyboard = NULL; + dmxArg a; + const char *name; + int i; + int doXI = 1; /* Include by default */ + int forceConsole = 0; + int doWindows = 1; /* On by default */ + int hasXkb = 0; + + a = dmxArgParse(dmxInput->name); + + for (i = 1; i < dmxArgC(a); i++) { + switch (hasXkb) { + case 1: + dmxInput->keycodes = xstrdup(dmxArgV(a, i)); + ++hasXkb; + break; + case 2: + dmxInput->symbols = xstrdup(dmxArgV(a, i)); + ++hasXkb; + break; + case 3: + dmxInput->geometry = xstrdup(dmxArgV(a, i)); + hasXkb = 0; + break; + case 0: + if (!strcmp(dmxArgV(a, i), "noxi")) doXI = 0; + else if (!strcmp(dmxArgV(a, i), "xi")) doXI = 1; + else if (!strcmp(dmxArgV(a, i), "console")) forceConsole = 1; + else if (!strcmp(dmxArgV(a, i), "noconsole")) forceConsole = 0; + else if (!strcmp(dmxArgV(a, i), "windows")) doWindows = 1; + else if (!strcmp(dmxArgV(a, i), "nowindows")) doWindows = 0; + else if (!strcmp(dmxArgV(a, i), "xkb")) hasXkb = 1; + else { + dmxLog(dmxFatal, + "Unknown input argument: %s\n", dmxArgV(a, i)); + } + } + } + + name = dmxArgV(a, 0); + + if (!strcmp(name, "local")) { + dmxPopulateLocal(dmxInput, a); + } else if (!strcmp(name, "dummy")) { + dmxInputCopyLocal(dmxInput, &DMXDummyMou); + dmxInputCopyLocal(dmxInput, &DMXDummyKbd); + dmxLogInput(dmxInput, "Using dummy input\n"); + } else { + int found; + + for (found = 0, i = 0; i < dmxNumScreens; i++) { + if (dmxPropertySameDisplay(&dmxScreens[i], name)) { + if (dmxScreens[i].shared) + dmxLog(dmxFatal, + "Cannot take input from shared backend (%s)\n", + name); + if (!dmxInput->core) { + dmxLog(dmxWarning, + "Cannot use core devices on a backend (%s)" + " as XInput devices\n", name); + } else { + char *pt; + for (pt = (char *)dmxInput->name; pt && *pt; pt++) + if (*pt == ',') *pt = '\0'; + dmxInputCopyLocal(dmxInput, &DMXBackendMou); + dmxInputCopyLocal(dmxInput, &DMXBackendKbd); + dmxInput->scrnIdx = i; + dmxLogInput(dmxInput, + "Using backend input from %s\n", name); + } + ++found; + break; + } + } + if (!found || forceConsole) { + char *pt; + if (found) dmxInput->console = TRUE; + for (pt = (char *)dmxInput->name; pt && *pt; pt++) + if (*pt == ',') *pt = '\0'; + dmxInputCopyLocal(dmxInput, &DMXConsoleMou); + dmxInputCopyLocal(dmxInput, &DMXConsoleKbd); + if (doWindows) { + dmxInput->windows = TRUE; + dmxInput->updateWindowInfo = dmxUpdateWindowInformation; + } + dmxLogInput(dmxInput, + "Using console input from %s (%s windows)\n", + name, doWindows ? "with" : "without"); + } + } + + dmxArgFree(a); + + /* Locate extensions we may be interested in */ + dmxInputScanForExtensions(dmxInput, doXI); + + for (i = 0; i < dmxInput->numDevs; i++) { + DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + dmxLocal->pDevice = dmxAddDevice(dmxLocal); + if (dmxLocal->isCore) { + if (dmxLocal->type == DMX_LOCAL_MOUSE) + pPointer = dmxLocal->pDevice; + if (dmxLocal->type == DMX_LOCAL_KEYBOARD) + pKeyboard = dmxLocal->pDevice; + } + } + + dmxInput->processInputEvents = dmxProcessInputEvents; + dmxInput->detached = False; + + RegisterBlockAndWakeupHandlers(dmxBlockHandler, + dmxWakeupHandler, + (void *)dmxInput->inputIdx); +} + +static void dmxInputFreeLocal(DMXLocalInputInfoRec *local) +{ + if (!local) return; + if (local->isCore && local->type == DMX_LOCAL_MOUSE) + dmxLocalCorePointer = NULL; + if (local->isCore && local->type == DMX_LOCAL_KEYBOARD) + dmxLocalCoreKeyboard = NULL; + if (local->destroy_private) local->destroy_private(local->private); + if (local->history) free(local->history); + if (local->valuators) free(local->valuators); + if (local->deviceName) free(local->deviceName); + local->private = NULL; + local->history = NULL; + local->deviceName = NULL; + free(local); +} + +/** Free all of the memory associated with \a dmxInput */ +void dmxInputFree(DMXInputInfo *dmxInput) +{ + int i; + + if (!dmxInput) return; + + if (dmxInput->keycodes) free(dmxInput->keycodes); + if (dmxInput->symbols) free(dmxInput->symbols); + if (dmxInput->geometry) free(dmxInput->geometry); + + for (i = 0; i < dmxInput->numDevs; i++) { + dmxInputFreeLocal(dmxInput->devs[i]); + dmxInput->devs[i] = NULL; + } + free(dmxInput->devs); + dmxInput->devs = NULL; + dmxInput->numDevs = 0; + if (dmxInput->freename) free(dmxInput->name); + dmxInput->name = NULL; +} + +/** Log information about all of the known devices using #dmxLog(). */ +void dmxInputLogDevices(void) +{ + int i, j; + + dmxLog(dmxInfo, "%d devices:\n", dmxGetInputCount()); + dmxLog(dmxInfo, " Id Name Classes\n"); + for (j = 0; j < dmxNumInputs; j++) { + DMXInputInfo *dmxInput = &dmxInputs[j]; + const char *pt = strchr(dmxInput->name, ','); + int len = (pt + ? (size_t)(pt-dmxInput->name) + : strlen(dmxInput->name)); + + for (i = 0; i < dmxInput->numDevs; i++) { + DeviceIntPtr pDevice = dmxInput->devs[i]->pDevice; + if (pDevice) { + dmxLog(dmxInfo, " %2d%c %-20.20s", + pDevice->id, + dmxInput->detached ? 'D' : ' ', + pDevice->name); + if (pDevice->key) dmxLogCont(dmxInfo, " key"); + if (pDevice->valuator) dmxLogCont(dmxInfo, " val"); + if (pDevice->button) dmxLogCont(dmxInfo, " btn"); + if (pDevice->focus) dmxLogCont(dmxInfo, " foc"); + if (pDevice->kbdfeed) dmxLogCont(dmxInfo, " fb/kbd"); + if (pDevice->ptrfeed) dmxLogCont(dmxInfo, " fb/ptr"); + if (pDevice->intfeed) dmxLogCont(dmxInfo, " fb/int"); + if (pDevice->stringfeed) dmxLogCont(dmxInfo, " fb/str"); + if (pDevice->bell) dmxLogCont(dmxInfo, " fb/bel"); + if (pDevice->leds) dmxLogCont(dmxInfo, " fb/led"); + if (!pDevice->key && !pDevice->valuator && !pDevice->button + && !pDevice->focus && !pDevice->kbdfeed + && !pDevice->ptrfeed && !pDevice->intfeed + && !pDevice->stringfeed && !pDevice->bell + && !pDevice->leds) dmxLogCont(dmxInfo, " (none)"); + + dmxLogCont(dmxInfo, "\t[i%d/%*.*s", + dmxInput->inputIdx, len, len, dmxInput->name); + if (dmxInput->devs[i]->deviceId >= 0) + dmxLogCont(dmxInfo, "/id%d", dmxInput->devs[i]->deviceId); + if (dmxInput->devs[i]->deviceName) + dmxLogCont(dmxInfo, "=%s", dmxInput->devs[i]->deviceName); + dmxLogCont(dmxInfo, "] %s\n", + dmxInput->devs[i]->isCore + ? "core" + : (dmxInput->devs[i]->sendsCore + ? "extension (sends core events)" + : "extension")); + } + } + } +} + +/** Detach an input */ +int dmxInputDetach(DMXInputInfo *dmxInput) +{ + int i; + + if (dmxInput->detached) return BadAccess; + + for (i = 0; i < dmxInput->numDevs; i++) { + DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + dmxLogInput(dmxInput, "Detaching device id %d: %s%s\n", + dmxLocal->pDevice->id, + dmxLocal->pDevice->name, + dmxLocal->isCore + ? " [core]" + : (dmxLocal->sendsCore + ? " [sends core events]" + : "")); + DisableDevice(dmxLocal->pDevice, TRUE); + } + dmxInput->detached = True; + dmxInputLogDevices(); + return 0; +} + +/** Search for input associated with \a dmxScreen, and detach. */ +void dmxInputDetachAll(DMXScreenInfo *dmxScreen) +{ + int i; + + for (i = 0; i < dmxNumInputs; i++) { + DMXInputInfo *dmxInput = &dmxInputs[i]; + if (dmxInput->scrnIdx == dmxScreen->index) dmxInputDetach(dmxInput); + } +} + +/** Search for input associated with \a deviceId, and detach. */ +int dmxInputDetachId(int id) +{ + DMXInputInfo *dmxInput = dmxInputLocateId(id); + + if (!dmxInput) return BadValue; + + return dmxInputDetach(dmxInput); +} + +DMXInputInfo *dmxInputLocateId(int id) +{ + int i, j; + + for (i = 0; i < dmxNumInputs; i++) { + DMXInputInfo *dmxInput = &dmxInputs[i]; + for (j = 0; j < dmxInput->numDevs; j++) { + DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j]; + if (dmxLocal->pDevice->id == id) return dmxInput; + } + } + return NULL; +} + +static int dmxInputAttachNew(DMXInputInfo *dmxInput, int *id) +{ + dmxInputInit(dmxInput); + InitAndStartDevices(); + if (id && dmxInput->devs) *id = dmxInput->devs[0]->pDevice->id; + dmxInputLogDevices(); + return 0; +} + +static int dmxInputAttachOld(DMXInputInfo *dmxInput, int *id) +{ + int i; + + dmxInput->detached = False; + for (i = 0; i < dmxInput->numDevs; i++) { + DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + if (id) *id = dmxLocal->pDevice->id; + dmxLogInput(dmxInput, + "Attaching device id %d: %s%s\n", + dmxLocal->pDevice->id, + dmxLocal->pDevice->name, + dmxLocal->isCore + ? " [core]" + : (dmxLocal->sendsCore + ? " [sends core events]" + : "")); + EnableDevice(dmxLocal->pDevice, TRUE); + } + dmxInputLogDevices(); + return 0; +} + +int dmxInputAttachConsole(const char *name, int isCore, int *id) +{ + DMXInputInfo *dmxInput; + int i; + + for (i = 0; i < dmxNumInputs; i++) { + dmxInput = &dmxInputs[i]; + if (dmxInput->scrnIdx == -1 + && dmxInput->detached + && !strcmp(dmxInput->name, name)) { + /* Found match */ + dmxLogInput(dmxInput, "Reattaching detached console input\n"); + return dmxInputAttachOld(dmxInput, id); + } + } + + /* No match found */ + dmxInput = dmxConfigAddInput(xstrdup(name), isCore); + dmxInput->freename = TRUE; + dmxLogInput(dmxInput, "Attaching new console input\n"); + return dmxInputAttachNew(dmxInput, id); +} + +int dmxInputAttachBackend(int physicalScreen, int isCore, int *id) +{ + DMXInputInfo *dmxInput; + DMXScreenInfo *dmxScreen; + int i; + + if (physicalScreen < 0 || physicalScreen >= dmxNumScreens) return BadValue; + for (i = 0; i < dmxNumInputs; i++) { + dmxInput = &dmxInputs[i]; + if (dmxInput->scrnIdx != -1 && dmxInput->scrnIdx == physicalScreen) { + /* Found match */ + if (!dmxInput->detached) return BadAccess; /* Already attached */ + dmxScreen = &dmxScreens[physicalScreen]; + if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ + dmxLogInput(dmxInput, "Reattaching detached backend input\n"); + return dmxInputAttachOld(dmxInput, id); + } + } + /* No match found */ + dmxScreen = &dmxScreens[physicalScreen]; + if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ + dmxInput = dmxConfigAddInput(dmxScreen->name, isCore); + dmxLogInput(dmxInput, "Attaching new backend input\n"); + return dmxInputAttachNew(dmxInput, id); +} diff --git a/xorg-server/hw/dmx/input/dmxmotion.c b/xorg-server/hw/dmx/input/dmxmotion.c index 73580a215..d1c79f126 100644 --- a/xorg-server/hw/dmx/input/dmxmotion.c +++ b/xorg-server/hw/dmx/input/dmxmotion.c @@ -1,142 +1,142 @@ -/* - * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: - * Rickard E. (Rik) Faith <faith@redhat.com> - * - */ - -/** \file - * This file provides functions similar to miPointerGetMotionEvents and - * miPointerPutMotionEvents, with the exception that devices with more - * than two axes are fully supported. These routines may be used only - * for motion buffers for extension devices, and are \a not compatible - * replacements for the mi routines. */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "inputstr.h" -#include "dmxinputinit.h" -#include "dmxcommon.h" -#include "dmxmotion.h" - -#define OFFSET(offset,element) ((offset) * (numAxes + 1) + (element)) - -/** Return size of motion buffer. \see DMX_MOTION_SIZE */ -int dmxPointerGetMotionBufferSize(void) -{ - return DMX_MOTION_SIZE; -} - -/** This routine performs the same function as \a miPointerGetMotionEvents: - * the events in the motion history that are between the start and stop - * times (in mS) are placed in the coords vector, and the count of the - * number of items so placed is returned. This routine is called from - * dix/devices.c so that coords can hold valuator->numMotionEvents - * events. This routine is called from \a Xi/gtmotion.c with coords large - * enough to hold the same number of events in a variable-length - * extended \a xTimecoord structure. This provides sufficient data for the - * \a XGetDeviceMotionEvents library call, and would be identical to - * \a miPointerGetMotionEvents for devices with only 2 axes (i.e., core - * pointers) if \a xTimecoord used 32bit integers. - * - * Because DMX uses the mi* routines for all core devices, this routine - * only has to support extension devices using the polymorphic coords. - * Because compatibility with miPointerGetMotionEvents is not possible, - * it is not provided. */ -int dmxPointerGetMotionEvents(DeviceIntPtr pDevice, - xTimecoord *coords, - unsigned long start, - unsigned long stop, - ScreenPtr pScreen) -{ - GETDMXLOCALFROMPDEVICE; - int numAxes = pDevice->valuator->numAxes; - unsigned long *c = (unsigned long *)coords; - int count = 0; - int i, j; - - if (!dmxLocal->history) return 0; - for (i = dmxLocal->head; i != dmxLocal->tail;) { - if (dmxLocal->history[OFFSET(i,0)] >= stop) break; - if (dmxLocal->history[OFFSET(i,0)] >= start) { - for (j = 0; j < numAxes + 1; j++) - c[OFFSET(count,j)] = dmxLocal->history[OFFSET(i,j)]; - ++count; - } - if (++i >= DMX_MOTION_SIZE) i = 0; - } - return count; -} - -/** This routine adds an event to the motion history. A similar - * function is performed by miPointerMove for the mi versions of these - * routines. */ -void dmxPointerPutMotionEvent(DeviceIntPtr pDevice, - int firstAxis, int axesCount, int *v, - unsigned long time) -{ - GETDMXLOCALFROMPDEVICE; - int numAxes = pDevice->valuator->numAxes; - int i; - - if (!dmxLocal->history) { - dmxLocal->history = xalloc(sizeof(*dmxLocal->history) - * (numAxes + 1) - * DMX_MOTION_SIZE); - dmxLocal->head = 0; - dmxLocal->tail = 0; - dmxLocal->valuators = calloc(sizeof(*dmxLocal->valuators), numAxes); - } else { - if (++dmxLocal->tail >= DMX_MOTION_SIZE) dmxLocal->tail = 0; - if (dmxLocal->head == dmxLocal->tail) - if (++dmxLocal->head >= DMX_MOTION_SIZE) dmxLocal->head = 0; - } - - dmxLocal->history[OFFSET(dmxLocal->tail,0)] = time; - - /* Initialize the data from the known - * values (if Absolute) or to zero (if - * Relative) */ - if (pDevice->valuator->mode == Absolute) { - for (i = 0; i < numAxes; i++) - dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] - = dmxLocal->valuators[i]; - } else { - for (i = 0; i < numAxes; i++) - dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0; - } - - for (i = firstAxis; i < axesCount; i++) { - dmxLocal->history[OFFSET(dmxLocal->tail,i+i)] - = (unsigned long)v[i-firstAxis]; - dmxLocal->valuators[i] = v[i-firstAxis]; - } -} +/* + * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: + * Rickard E. (Rik) Faith <faith@redhat.com> + * + */ + +/** \file + * This file provides functions similar to miPointerGetMotionEvents and + * miPointerPutMotionEvents, with the exception that devices with more + * than two axes are fully supported. These routines may be used only + * for motion buffers for extension devices, and are \a not compatible + * replacements for the mi routines. */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "inputstr.h" +#include "dmxinputinit.h" +#include "dmxcommon.h" +#include "dmxmotion.h" + +#define OFFSET(offset,element) ((offset) * (numAxes + 1) + (element)) + +/** Return size of motion buffer. \see DMX_MOTION_SIZE */ +int dmxPointerGetMotionBufferSize(void) +{ + return DMX_MOTION_SIZE; +} + +/** This routine performs the same function as \a miPointerGetMotionEvents: + * the events in the motion history that are between the start and stop + * times (in mS) are placed in the coords vector, and the count of the + * number of items so placed is returned. This routine is called from + * dix/devices.c so that coords can hold valuator->numMotionEvents + * events. This routine is called from \a Xi/gtmotion.c with coords large + * enough to hold the same number of events in a variable-length + * extended \a xTimecoord structure. This provides sufficient data for the + * \a XGetDeviceMotionEvents library call, and would be identical to + * \a miPointerGetMotionEvents for devices with only 2 axes (i.e., core + * pointers) if \a xTimecoord used 32bit integers. + * + * Because DMX uses the mi* routines for all core devices, this routine + * only has to support extension devices using the polymorphic coords. + * Because compatibility with miPointerGetMotionEvents is not possible, + * it is not provided. */ +int dmxPointerGetMotionEvents(DeviceIntPtr pDevice, + xTimecoord *coords, + unsigned long start, + unsigned long stop, + ScreenPtr pScreen) +{ + GETDMXLOCALFROMPDEVICE; + int numAxes = pDevice->valuator->numAxes; + unsigned long *c = (unsigned long *)coords; + int count = 0; + int i, j; + + if (!dmxLocal->history) return 0; + for (i = dmxLocal->head; i != dmxLocal->tail;) { + if (dmxLocal->history[OFFSET(i,0)] >= stop) break; + if (dmxLocal->history[OFFSET(i,0)] >= start) { + for (j = 0; j < numAxes + 1; j++) + c[OFFSET(count,j)] = dmxLocal->history[OFFSET(i,j)]; + ++count; + } + if (++i >= DMX_MOTION_SIZE) i = 0; + } + return count; +} + +/** This routine adds an event to the motion history. A similar + * function is performed by miPointerMove for the mi versions of these + * routines. */ +void dmxPointerPutMotionEvent(DeviceIntPtr pDevice, + int firstAxis, int axesCount, int *v, + unsigned long time) +{ + GETDMXLOCALFROMPDEVICE; + int numAxes = pDevice->valuator->numAxes; + int i; + + if (!dmxLocal->history) { + dmxLocal->history = malloc(sizeof(*dmxLocal->history) + * (numAxes + 1) + * DMX_MOTION_SIZE); + dmxLocal->head = 0; + dmxLocal->tail = 0; + dmxLocal->valuators = calloc(sizeof(*dmxLocal->valuators), numAxes); + } else { + if (++dmxLocal->tail >= DMX_MOTION_SIZE) dmxLocal->tail = 0; + if (dmxLocal->head == dmxLocal->tail) + if (++dmxLocal->head >= DMX_MOTION_SIZE) dmxLocal->head = 0; + } + + dmxLocal->history[OFFSET(dmxLocal->tail,0)] = time; + + /* Initialize the data from the known + * values (if Absolute) or to zero (if + * Relative) */ + if (pDevice->valuator->mode == Absolute) { + for (i = 0; i < numAxes; i++) + dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] + = dmxLocal->valuators[i]; + } else { + for (i = 0; i < numAxes; i++) + dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0; + } + + for (i = firstAxis; i < axesCount; i++) { + dmxLocal->history[OFFSET(dmxLocal->tail,i+i)] + = (unsigned long)v[i-firstAxis]; + dmxLocal->valuators[i] = v[i-firstAxis]; + } +} diff --git a/xorg-server/hw/dmx/input/lnx-keyboard.c b/xorg-server/hw/dmx/input/lnx-keyboard.c index 939a32f07..11f21e25c 100644 --- a/xorg-server/hw/dmx/input/lnx-keyboard.c +++ b/xorg-server/hw/dmx/input/lnx-keyboard.c @@ -1,990 +1,990 @@ -/* Portions of this file were derived from the following files: - * - ********************************************************************** - * - * xfree86/common/{xf86Io.c,xf86Kbd.c,xf86Events.c} - * - * 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. - * - ********************************************************************** - * - * xfree86/common/xf86KbdLnx.c - * - * Linux version of keymapping setup. The kernel (since 0.99.14) has support - * for fully remapping the keyboard, but there are some differences between - * the Linux map and the SVR4 map (esp. in the extended keycodes). We also - * remove the restriction on what keycodes can be remapped. - * Orest Zborowski. - * - * 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. - * - ********************************************************************** - * - * xfree86/os-support/linux/lnx_io.c - * - * Copyright 1992 by Orest Zborowski <obz@Kodak.com> - * Copyright 1993 by David Dawes <dawes@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 names of Orest Zborowski and David Dawes - * not be used in advertising or publicity pertaining to distribution of - * the software without specific, written prior permission. Orest Zborowski - * and David Dawes 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 DAWES DISCLAIMS ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES 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 2001-2003 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: - * Rickard E. (Rik) Faith <faith@redhat.com> - * - */ - -/** \file - * - * This code implements a low-level device driver for the Linux - * keyboard. The code is derived from code by Thomas Roell, Orest - * Zborowski, and David Dawes (see the source code for complete - * references). */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -/*****************************************************************************/ -/* Define some macros to make it easier to move this file to another - * part of the Xserver tree. All calls to the dmx* layer are #defined - * here for the .c file. The .h file will also have to be edited. */ -#include "dmxinputinit.h" -#include "lnx-keyboard.h" - -#define GETPRIV myPrivate *priv \ - = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private - -#define LOG0(f) dmxLog(dmxDebug,f) -#define LOG1(f,a) dmxLog(dmxDebug,f,a) -#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b) -#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) -#define FATAL0(f) dmxLog(dmxFatal,f) -#define FATAL1(f,a) dmxLog(dmxFatal,f,a) -#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b) -#define MOTIONPROC dmxMotionProcPtr -#define ENQUEUEPROC dmxEnqueueProcPtr -#define CHECKPROC dmxCheckSpecialProcPtr -#define SWITCHRETPROC dmxVTSwitchReturnProcPtr -#define BLOCK DMXBlockType -#define MESSAGE "\033c\n\n\nDMX taking input from this console..." -#define FINALMESSAGE "\033cDMX terminated." - -/* End of interface definitions. */ -/*****************************************************************************/ - -#include "inputstr.h" -#include <X11/Xos.h> -#include <sys/ioctl.h> -#include <errno.h> -#include <signal.h> -#include <sys/vt.h> -#include <sys/kd.h> -#include <termios.h> -#include "atKeynames.h" -#if 00 -#include "xf86Keymap.h" -#endif -#include <linux/keyboard.h> -#include <xkbsrv.h> - -#define NUM_AT2LNX (sizeof(at2lnx) / sizeof(at2lnx[0])) -#define NUM_STATE_ENTRIES (256/32) - - -/* Private area for Linux-style keyboards. */ -typedef struct _myPrivate { - int fd; - int vtno; - int vtcurrent; - int kbdtrans; - struct termios kbdtty; - int kbdType; - CARD32 kbdState[NUM_STATE_ENTRIES]; - DeviceIntPtr pKeyboard; - unsigned char prefix; - - int switched; - SWITCHRETPROC switch_return; - void *switch_return_data; - - /* For bell */ - int pitch; - unsigned long duration; -} myPrivate; - -static myPrivate *PRIV = NULL; - -#undef SYSCALL -#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) - -static int kbdLinuxKeyDown(myPrivate *priv, int keyCode) -{ - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return 0; - return priv->kbdState[byte] & bit; -} - -static void kbdLinuxKeyState(myPrivate *priv, int type, int keyCode) -{ - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return; - if (type == KeyPress) priv->kbdState[byte] |= bit; - else priv->kbdState[byte] &= ~bit; -} - -static KeySym linux_to_x[256] = { - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, XK_Escape, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_space, XK_exclam, XK_quotedbl, XK_numbersign, - XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, - XK_parenleft, XK_parenright, XK_asterisk, XK_plus, - XK_comma, XK_minus, XK_period, XK_slash, - XK_0, XK_1, XK_2, XK_3, - XK_4, XK_5, XK_6, XK_7, - XK_8, XK_9, XK_colon, XK_semicolon, - XK_less, XK_equal, XK_greater, XK_question, - XK_at, XK_A, XK_B, XK_C, - XK_D, XK_E, XK_F, XK_G, - XK_H, XK_I, XK_J, XK_K, - XK_L, XK_M, XK_N, XK_O, - XK_P, XK_Q, XK_R, XK_S, - XK_T, XK_U, XK_V, XK_W, - XK_X, XK_Y, XK_Z, XK_bracketleft, - XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, - XK_grave, XK_a, XK_b, XK_c, - XK_d, XK_e, XK_f, XK_g, - XK_h, XK_i, XK_j, XK_k, - XK_l, XK_m, XK_n, XK_o, - XK_p, XK_q, XK_r, XK_s, - XK_t, XK_u, XK_v, XK_w, - XK_x, XK_y, XK_z, XK_braceleft, - XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, - XK_currency, XK_yen, XK_brokenbar, XK_section, - XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, - XK_notsign, XK_hyphen, XK_registered, XK_macron, - XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, - XK_acute, XK_mu, XK_paragraph, XK_periodcentered, - XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, - XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, - XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, - XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, - XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, - XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, - XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, - XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, - XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, - XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, - XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, - XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, - XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, - XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, - XK_eth, XK_ntilde, XK_ograve, XK_oacute, - XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, - XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, - XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis -}; - -/* - * Maps the AT keycodes to Linux keycodes - */ -static unsigned char at2lnx[NUM_KEYCODES] = -{ - 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ - 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ - 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ - 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ - 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ - 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ - 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ - 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ - 0x11, /* KEY_W */ 0x12, /* KEY_E */ - 0x13, /* KEY_R */ 0x14, /* KEY_T */ - 0x15, /* KEY_Y */ 0x16, /* KEY_U */ - 0x17, /* KEY_I */ 0x18, /* KEY_O */ - 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ - 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ - 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ - 0x1f, /* KEY_S */ 0x20, /* KEY_D */ - 0x21, /* KEY_F */ 0x22, /* KEY_G */ - 0x23, /* KEY_H */ 0x24, /* KEY_J */ - 0x25, /* KEY_K */ 0x26, /* KEY_L */ - 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ - 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ - 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ - 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ - 0x2f, /* KEY_V */ 0x30, /* KEY_B */ - 0x31, /* KEY_N */ 0x32, /* KEY_M */ - 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ - 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ - 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ - 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ - 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ - 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ - 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ - 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ - 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ - 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ - 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ - 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ - 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ - 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ - 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ - 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ - 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ - 0x00, /* 0x55 */ 0x56, /* KEY_Less */ - 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ - 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ - 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ - 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ - 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ - 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ - 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ - 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ - 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ - 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ - 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ - 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ - 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ - 0x00, /* 0x71 */ 0x00, /* 0x72 */ - 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ - 0x00, /* 0x75 */ 0x00, /* 0x76 */ - 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ - 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ - 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ - 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ - 0x00, /* 0x7f */ -}; - -/** Create a private structure for use within this file. */ -pointer kbdLinuxCreatePrivate(DeviceIntPtr pKeyboard) -{ - myPrivate *priv = calloc(1, sizeof(*priv)); - priv->fd = -1; - priv->pKeyboard = pKeyboard; - return priv; -} - -/** Destroy a private structure. */ -void kbdLinuxDestroyPrivate(pointer priv) -{ - if (priv) free(priv); -} - -/** Ring the bell. - * - * Note: we completely ignore the \a volume, since Linux's ioctl() - * interface does not provide a way to control it. If it did, the XBell - * manpage tells how the actual volume is a function of the percent and - * the (base) volume. - * - * Note that most of the other PC-based bell drivers compute the - * duration for KDMKTONE as a function of the volume and the duration. - * For some drivers, the duration is only measured in mS if the volume - * is 50, and is scaled by the volume for other values. This seems - * confusing and possibly incorrect (the xset man page says that the - * bell will be "as closely as it can to the user's specifications" -- - * if we ignore the volume and set the duration correctly, then we'll - * get one parameter "wrong" -- but if we use the volume to scale the - * duration, then we'll get both parameters "wrong"). */ -void kbdLinuxBell(DevicePtr pDev, int percent, - int volume, int pitch, int duration) -{ - GETPRIV; - - if (duration && pitch) { - ioctl(priv->fd, - KDMKTONE, - ((1193190 / pitch) & 0xffff) /* Low bits specify cycle time */ - | (duration << 16)); /* High bits are duration in msec */ - } -} - -/** Set the LEDs. */ -void kbdLinuxCtrl(DevicePtr pDev, KeybdCtrl *ctrl) -{ - GETPRIV; - - ioctl(priv->fd, KDSETLED, ctrl->leds & 0x07); -} - -static int kbdLinuxGetFreeVTNumber(void) -{ - int fd = -1; - int vtno; - int i; - const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; - - for (i = 0; tty0[i]; i++) - if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) break; - if (fd < 0) - FATAL1("kbdLinuxGetFreeVTNumber: Cannot open tty0 (%s)\n", - strerror(errno)); - if (ioctl(fd, VT_OPENQRY, &vtno) < 0 || vtno < 0) - FATAL0("kbdLinuxGetFreeVTNumber: Cannot find a free VT\n"); - return vtno; -} - -static int kbdLinuxOpenVT(int vtno) -{ - int fd = -1; - int i; - const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; - char name[64]; /* RATS: Only used in XmuSnprintf */ - - for (i = 0; vcs[i]; i++) { - XmuSnprintf(name, sizeof(name), vcs[i], vtno); - if ((fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) break; - } - if (fd < 0) - FATAL2("kbdLinuxOpenVT: Cannot open VT %d (%s)\n", - vtno, strerror(errno)); - return fd; -} - -static int kbdLinuxGetCurrentVTNumber(int fd) -{ - struct vt_stat vts; - - if (!ioctl(fd, VT_GETSTATE, &vts)) return vts.v_active; - return -1; -} - -static int kbdLinuxActivate(int fd, int vtno, int setSig); - -/** Currently unused hook called prior to an VT switch. */ -void kbdLinuxVTPreSwitch(pointer p) -{ -} - -/** Currently unused hook called after returning from a VT switch. */ -void kbdLinuxVTPostSwitch(pointer p) -{ -} - -/** Tell the operating system to switch to \a vt. The \a switch_return - * function is called with the \a switch_return_data when the VT is - * switched back to the pre-switch VT (i.e., the user returns to the DMX - * session). */ -int kbdLinuxVTSwitch(pointer p, int vt, - void (*switch_return)(pointer), - pointer switch_return_data) -{ - myPrivate *priv = p; - - if (priv->switched) FATAL0("kbdLinuxVTSwitch: already switched...\n"); - if (priv->vtno == vt) return 0; - - PRIV = priv; - priv->switched = 0; /* Will switch to 1 in handler */ - priv->switch_return = switch_return; - priv->switch_return_data = switch_return_data; - kbdLinuxActivate(priv->fd, vt, 0); - return 1; -} - -/* RATS: This function is only ever used to handle SIGUSR1. */ -static void kbdLinuxVTSignalHandler(int sig) -{ - myPrivate *priv = PRIV; - - signal(sig, kbdLinuxVTSignalHandler); - if (priv) { - ioctl(priv->fd, VT_RELDISP, VT_ACKACQ); - priv->switched = !priv->switched; - LOG2("kbdLinuxVTSignalHandler: got signal %d, switched = %d\n", - sig, priv->switched); - if (!priv->switched && priv->switch_return) - priv->switch_return(priv->switch_return_data); - } -} - -static int kbdLinuxActivate(int fd, int vtno, int setSig) -{ - int result; - struct vt_mode VT; - - SYSCALL(result = ioctl(fd, VT_ACTIVATE, vtno)); - if (result) FATAL0("kbdLinuxActivate: VT_ACTIVATE failed\n"); - SYSCALL(result = ioctl(fd, VT_WAITACTIVE, vtno)); - if (result) FATAL0("kbdLinuxActivate: VT_WAITACTIVE failed\n"); - if (setSig) { - SYSCALL(result = ioctl(fd, VT_GETMODE, &VT)); - if (result < 0) FATAL0("kbdLinuxActivate: VT_GETMODE failed\n"); - VT.mode = VT_PROCESS; - VT.relsig = SIGUSR1; - VT.acqsig = SIGUSR1; - if (ioctl(fd, VT_SETMODE, &VT)) - FATAL0("kbdLinuxActivate: VT_SETMODE VT_PROCESS failed\n"); - signal(SIGUSR1, kbdLinuxVTSignalHandler); - } - return Success; -} - -static void kbdLinuxOpenConsole(DevicePtr pDev) -{ - GETPRIV; - const char *msg = MESSAGE; - - if (priv->fd >= 0) return; - priv->vtno = kbdLinuxGetFreeVTNumber(); - priv->fd = kbdLinuxOpenVT(priv->vtno); - priv->vtcurrent = kbdLinuxGetCurrentVTNumber(priv->fd); - LOG2("kbdLinuxOpenConsole: current VT %d; using free VT %d\n", - priv->vtcurrent, priv->vtno); - kbdLinuxActivate(priv->fd, priv->vtno, 1); - ioctl(priv->fd, KDSETMODE, KD_GRAPHICS); /* To turn off gpm */ - if (msg) write(priv->fd, msg, strlen(msg)); -} - -static void kbdLinuxCloseConsole(DevicePtr pDev) -{ - GETPRIV; - struct vt_mode VT; - const char *msg = FINALMESSAGE; - - if (priv->fd < 0) return; - - ioctl(priv->fd, KDSETMODE, KD_TEXT); - if (msg) write(priv->fd, msg, strlen(msg)); - if (ioctl(priv->fd, VT_GETMODE, &VT) != -1) { - VT.mode = VT_AUTO; - ioctl(priv->fd, VT_SETMODE, &VT); - } - - LOG1("kbdLinuxCloseConsole: switching to VT %d\n", priv->vtcurrent); - if (priv->vtcurrent >= 0) kbdLinuxActivate(priv->fd, priv->vtcurrent, 0); - - close(priv->fd); - priv->fd = -1; -} - -/** Initialize the \a pDev as a Linux keyboard. */ -void kbdLinuxInit(DevicePtr pDev) -{ - GETPRIV; - - if (priv->fd <= 0) kbdLinuxOpenConsole(pDev); - - ioctl(priv->fd, KDGKBMODE, &priv->kbdtrans); - if (tcgetattr(priv->fd, &priv->kbdtty) < 0) - FATAL1("kbdLinuxInit: tcgetattr failed (%s)\n", strerror(errno)); -} - -static int kbdLinuxPrefix0Mapping(unsigned char *scanCode) -{ - /* Table from xfree86/common/xf86Events.c */ - switch (*scanCode) { - case KEY_KP_7: *scanCode = KEY_Home; break; /* curs home */ - case KEY_KP_8: *scanCode = KEY_Up; break; /* curs up */ - case KEY_KP_9: *scanCode = KEY_PgUp; break; /* curs pgup */ - case KEY_KP_4: *scanCode = KEY_Left; break; /* curs left */ - case KEY_KP_5: *scanCode = KEY_Begin; break; /* curs begin */ - case KEY_KP_6: *scanCode = KEY_Right; break; /* curs right */ - case KEY_KP_1: *scanCode = KEY_End; break; /* curs end */ - case KEY_KP_2: *scanCode = KEY_Down; break; /* curs down */ - case KEY_KP_3: *scanCode = KEY_PgDown; break; /* curs pgdown */ - case KEY_KP_0: *scanCode = KEY_Insert; break; /* curs insert */ - case KEY_KP_Decimal: *scanCode = KEY_Delete; break; /* curs delete */ - case KEY_Enter: *scanCode = KEY_KP_Enter; break; /* keypad enter */ - case KEY_LCtrl: *scanCode = KEY_RCtrl; break; /* right ctrl */ - case KEY_KP_Multiply: *scanCode = KEY_Print; break; /* print */ - case KEY_Slash: *scanCode = KEY_KP_Divide; break; /* keyp divide */ - case KEY_Alt: *scanCode = KEY_AltLang; break; /* right alt */ - case KEY_ScrollLock: *scanCode = KEY_Break; break; /* curs break */ - case 0x5b: *scanCode = KEY_LMeta; break; - case 0x5c: *scanCode = KEY_RMeta; break; - case 0x5d: *scanCode = KEY_Menu; break; - case KEY_F3: *scanCode = KEY_F13; break; - case KEY_F4: *scanCode = KEY_F14; break; - case KEY_F5: *scanCode = KEY_F15; break; - case KEY_F6: *scanCode = KEY_F16; break; - case KEY_F7: *scanCode = KEY_F17; break; - case KEY_KP_Plus: *scanCode = KEY_KP_DEC; break; - /* - * Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) - */ - case 0x2A: - case 0x36: - return 1; - default: - /* - * "Internet" keyboards are generating lots of new codes. - * Let them pass. There is little consistency between them, - * so don't bother with symbolic names at this level. - */ - scanCode += 0x78; - } - return 0; -} - -static int kbdLinuxPrefixMapping(myPrivate *priv, unsigned char *scanCode) -{ - int pressed = *scanCode & 0x80; - unsigned char code = *scanCode & 0x7f; - - /* If we don't have a prefix, check for one */ - if (!priv->prefix) { - switch (code) { - case KEY_Prefix0: - case KEY_Prefix1: - priv->prefix = code; - return 1; - } - return 0; /* No change */ - } - - /* We have a prefix from the last scanCode */ - switch (priv->prefix) { - case KEY_Prefix0: - priv->prefix = 0; - if (kbdLinuxPrefix0Mapping(&code)) return 1; /* Skip sequence */ - break; - case KEY_Prefix1: - priv->prefix = (code = KEY_LCtrl) ? KEY_LCtrl : 0; - return 1; /* Use new prefix */ - case KEY_LCtrl: - priv->prefix = 0; - if (code != KEY_NumLock) return 1; /* Skip sequence*/ - code = KEY_Pause; - break; - } - - *scanCode = code | (pressed ? 0x80 : 0x00); - return 0; /* Use old scanCode */ -} - -static void kbdLinuxConvert(DevicePtr pDev, - unsigned char scanCode, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) -{ - GETPRIV; - XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; - int type; - KeySym keySym = NoSymbol; - int keyCode; - int switching; - - /* Do special PC/AT prefix mapping -- may change scanCode! */ - if (kbdLinuxPrefixMapping(priv, &scanCode)) return; - - type = (scanCode & 0x80) ? KeyRelease : KeyPress; - keyCode = (scanCode & 0x7f) + MIN_KEYCODE; - - /* Handle repeats */ - - if (keyCode >= xkbi->desc->min_key_code && - keyCode <= xkbi->desc->max_key_code) { - - int effectiveGroup = XkbGetEffectiveGroup(xkbi, - &xkbi->state, - scanCode); - keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); -#if 0 - switch (keySym) { - case XK_Num_Lock: - case XK_Scroll_Lock: - case XK_Shift_Lock: - case XK_Caps_Lock: - /* Ignore releases and all but first press */ - if (kbdLinuxModIgnore(priv, &xE, keySym)) return; - if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease; - else xE.u.u.type = KeyPress; - break; - } -#endif - - /* If key is already down, ignore or autorepeat */ - if (type == KeyPress && kbdLinuxKeyDown(priv, keyCode)) { - KbdFeedbackClassRec *feed = priv->pKeyboard->kbdfeed; - - /* No auto-repeat? */ - if ((feed && !feed->ctrl.autoRepeat) - || priv->pKeyboard->key->xkbInfo->desc->map->modmap[keyCode] - || (feed - && !(feed->ctrl.autoRepeats[keyCode >> 3] - & (1 << (keyCode & 7))))) return; /* Ignore */ - - /* Do auto-repeat */ - enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); - type = KeyPress; - } - - /* If key is already up, ignore */ - if (type == KeyRelease && !kbdLinuxKeyDown(priv, keyCode)) return; - } - - switching = 0; - if (checkspecial && type == KeyPress) - switching = checkspecial(pDev, keySym); - if (!switching) { - if (enqueue) - enqueue(pDev, type, keyCode, keySym, NULL, block); - kbdLinuxKeyState(priv, type, keyCode); /* Update our state bitmap */ - } -} - -/** Read an event from the \a pDev device. If the event is a motion - * event, enqueue it with the \a motion function. Otherwise, check for - * special keys with the \a checkspecial function and enqueue the event - * with the \a enqueue function. The \a block type is passed to the - * functions so that they may block SIGIO handling as appropriate to the - * caller of this function. */ -void kbdLinuxRead(DevicePtr pDev, - MOTIONPROC motion, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) -{ - GETPRIV; - unsigned char buf[256]; /* RATS: Only used in length-limited call */ - unsigned char *pt; - int n; - - while ((n = read(priv->fd, buf, sizeof(buf))) > 0) - for (pt = buf; n; --n, ++pt) - kbdLinuxConvert(pDev, *pt, enqueue, checkspecial, block); -} - -/** Turn \a pDev on (i.e., take input from \a pDev). */ -int kbdLinuxOn(DevicePtr pDev) -{ - GETPRIV; - struct termios nTty; - - ioctl(priv->fd, KDSKBMODE, K_RAW); - - nTty = priv->kbdtty; - nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); - nTty.c_oflag = 0; - nTty.c_cflag = CREAD | CS8; - nTty.c_lflag = 0; - nTty.c_cc[VTIME] = 0; - nTty.c_cc[VMIN] = 1; - cfsetispeed(&nTty, B9600); - cfsetospeed(&nTty, B9600); - if (tcsetattr(priv->fd, TCSANOW, &nTty) < 0) - FATAL1("kbdLinuxOn: tcsetattr failed (%s)\n", strerror(errno)); - return priv->fd; -} - -/** Turn \a pDev off (i.e., stop taking input from \a pDev). */ -void kbdLinuxOff(DevicePtr pDev) -{ - GETPRIV; - - ioctl(priv->fd, KDSKBMODE, priv->kbdtrans); - tcsetattr(priv->fd, TCSANOW, &priv->kbdtty); - kbdLinuxCloseConsole(pDev); -} - - -static void kbdLinuxReadKernelMapping(int fd, KeySymsPtr pKeySyms) -{ - KeySym *k; - int i; - int maxkey; - static unsigned char tbl[GLYPHS_PER_KEY] = { /* RATS: Use ok */ - 0, /* unshifted */ - 1, /* shifted */ - 0, /* modeswitch unshifted */ - 0 /* modeswitch shifted */ - }; - - /* - * Read the mapping from the kernel. - * Since we're still using the XFree86 scancode->AT keycode mapping - * routines, we need to convert the AT keycodes to Linux keycodes, - * then translate the Linux keysyms into X keysyms. - * - * First, figure out which tables to use for the modeswitch columns - * above, from the XF86Config fields. - */ - tbl[2] = 8; /* alt */ - tbl[3] = tbl[2] | 1; - -#if 00/*BP*/ - k = map+GLYPHS_PER_KEY; -#else - ErrorF("kbdLinuxReadKernelMapping() is broken/no-op'd\n"); - return; -#endif - maxkey = NUM_AT2LNX; - - for (i = 0; i < maxkey; ++i) { - struct kbentry kbe; - int j; - - kbe.kb_index = at2lnx[i]; - - for (j = 0; j < GLYPHS_PER_KEY; ++j, ++k) { - unsigned short kval; - - *k = NoSymbol; - - kbe.kb_table = tbl[j]; - if (kbe.kb_index == 0 || ioctl(fd, KDGKBENT, &kbe)) continue; - - kval = KVAL(kbe.kb_value); - switch (KTYP(kbe.kb_value)) { - case KT_LATIN: - case KT_LETTER: *k = linux_to_x[kval]; break; - case KT_FN: - if (kval <= 19) *k = XK_F1 + kval; - else switch (kbe.kb_value) { - case K_FIND: *k = XK_Home; /* or XK_Find */ break; - case K_INSERT: *k = XK_Insert; break; - case K_REMOVE: *k = XK_Delete; break; - case K_SELECT: *k = XK_End; /* or XK_Select */ break; - case K_PGUP: *k = XK_Prior; break; - case K_PGDN: *k = XK_Next; break; - case K_HELP: *k = XK_Help; break; - case K_DO: *k = XK_Execute; break; - case K_PAUSE: *k = XK_Pause; break; - case K_MACRO: *k = XK_Menu; break; - default: break; - } - break; - case KT_SPEC: - switch (kbe.kb_value) { - case K_ENTER: *k = XK_Return; break; - case K_BREAK: *k = XK_Break; break; - case K_CAPS: *k = XK_Caps_Lock; break; - case K_NUM: *k = XK_Num_Lock; break; - case K_HOLD: *k = XK_Scroll_Lock; break; - case K_COMPOSE: *k = XK_Multi_key; break; - default: break; - } - break; - case KT_PAD: - switch (kbe.kb_value) { - case K_PPLUS: *k = XK_KP_Add; break; - case K_PMINUS: *k = XK_KP_Subtract; break; - case K_PSTAR: *k = XK_KP_Multiply; break; - case K_PSLASH: *k = XK_KP_Divide; break; - case K_PENTER: *k = XK_KP_Enter; break; - case K_PCOMMA: *k = XK_KP_Separator; break; - case K_PDOT: *k = XK_KP_Decimal; break; - case K_PPLUSMINUS: *k = XK_KP_Subtract; break; - default: if (kval <= 9) *k = XK_KP_0 + kval; break; - } - break; - case KT_DEAD: - /* KT_DEAD keys are for accelerated diacritical creation. */ - switch (kbe.kb_value) { - case K_DGRAVE: *k = XK_dead_grave; break; - case K_DACUTE: *k = XK_dead_acute; break; - case K_DCIRCM: *k = XK_dead_circumflex; break; - case K_DTILDE: *k = XK_dead_tilde; break; - case K_DDIERE: *k = XK_dead_diaeresis; break; - } - break; - case KT_CUR: - switch (kbe.kb_value) { - case K_DOWN: *k = XK_Down; break; - case K_LEFT: *k = XK_Left; break; - case K_RIGHT: *k = XK_Right; break; - case K_UP: *k = XK_Up; break; - } - break; - case KT_SHIFT: - switch (kbe.kb_value) { - case K_ALTGR: *k = XK_Alt_R; break; - case K_ALT: - *k = (kbe.kb_index == 0x64 ? XK_Alt_R : XK_Alt_L); - break; - case K_CTRL: - *k = (kbe.kb_index == 0x61 ? XK_Control_R : XK_Control_L); - break; - case K_CTRLL: *k = XK_Control_L; break; - case K_CTRLR: *k = XK_Control_R; break; - case K_SHIFT: - *k = (kbe.kb_index == 0x36 ? XK_Shift_R : XK_Shift_L); - break; - case K_SHIFTL: *k = XK_Shift_L; break; - case K_SHIFTR: *k = XK_Shift_R; break; - default: break; - } - break; - case KT_ASCII: - /* KT_ASCII keys accumulate a 3 digit decimal number that - * gets emitted when the shift state changes. We can't - * emulate that. - */ - break; - case KT_LOCK: - if (kbe.kb_value == K_SHIFTLOCK) *k = XK_Shift_Lock; - break; - default: break; - } - } - - if (k[-1] == k[-2]) k[-1] = NoSymbol; - if (k[-2] == k[-3]) k[-2] = NoSymbol; - if (k[-3] == k[-4]) k[-3] = NoSymbol; - if (k[-4] == k[-2] && k[-3] == k[-1]) k[-2] = k[-1] = NoSymbol; - if (k[-1] == k[-4] && k[-2] == k[-3] - && k[-2] == NoSymbol) k[-1] = NoSymbol; - } -} - -static void kbdLinuxGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) -{ - GETPRIV; - KeySym *k, *mapCopy; - char type; - int i; - -#if 00/*BP*/ - mapCopy = xalloc(sizeof(map)); - memcpy(mapCopy, map, sizeof(map)); -#else - ErrorF("kbdLinuxGetMap() is broken/no-op'd\n"); - return; -#endif - - kbdLinuxReadKernelMapping(priv->fd, pKeySyms); - - /* compute the modifier map */ - for (i = 0; i < MAP_LENGTH; i++) - pModMap[i] = NoSymbol; /* make sure it is restored */ - - for (k = mapCopy, i = MIN_KEYCODE; - i < NUM_KEYCODES + MIN_KEYCODE; - i++, k += 4) { - switch(*k) { - case XK_Shift_L: - case XK_Shift_R: pModMap[i] = ShiftMask; break; - case XK_Control_L: - case XK_Control_R: pModMap[i] = ControlMask; break; - case XK_Caps_Lock: pModMap[i] = LockMask; break; - case XK_Alt_L: - case XK_Alt_R: pModMap[i] = AltMask; break; - case XK_Num_Lock: pModMap[i] = NumLockMask; break; - case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break; - case XK_Kana_Lock: - case XK_Kana_Shift: pModMap[i] = KanaMask; break; - case XK_Mode_switch: pModMap[i] = AltLangMask; break; - } - } - - priv->kbdType = (ioctl(priv->fd, KDGKBTYPE, &type) < 0) ? KB_101 : type; - - pKeySyms->map = mapCopy; /* Must be XFree'able */ - pKeySyms->mapWidth = GLYPHS_PER_KEY; - pKeySyms->minKeyCode = MIN_KEYCODE; - pKeySyms->maxKeyCode = MAX_KEYCODE; -} - -/** Fill the \a info structure with information needed to initialize \a - * pDev. */ -void kbdLinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) -{ - info->keyboard = 1; - info->keyClass = 1; - kbdLinuxGetMap(pDev, &info->keySyms, info->modMap); - info->focusClass = 1; - info->kbdFeedbackClass = 1; -} +/* Portions of this file were derived from the following files: + * + ********************************************************************** + * + * xfree86/common/{xf86Io.c,xf86Kbd.c,xf86Events.c} + * + * 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. + * + ********************************************************************** + * + * xfree86/common/xf86KbdLnx.c + * + * Linux version of keymapping setup. The kernel (since 0.99.14) has support + * for fully remapping the keyboard, but there are some differences between + * the Linux map and the SVR4 map (esp. in the extended keycodes). We also + * remove the restriction on what keycodes can be remapped. + * Orest Zborowski. + * + * 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. + * + ********************************************************************** + * + * xfree86/os-support/linux/lnx_io.c + * + * Copyright 1992 by Orest Zborowski <obz@Kodak.com> + * Copyright 1993 by David Dawes <dawes@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 names of Orest Zborowski and David Dawes + * not be used in advertising or publicity pertaining to distribution of + * the software without specific, written prior permission. Orest Zborowski + * and David Dawes 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 DAWES DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID DAWES 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 2001-2003 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: + * Rickard E. (Rik) Faith <faith@redhat.com> + * + */ + +/** \file + * + * This code implements a low-level device driver for the Linux + * keyboard. The code is derived from code by Thomas Roell, Orest + * Zborowski, and David Dawes (see the source code for complete + * references). */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +/*****************************************************************************/ +/* Define some macros to make it easier to move this file to another + * part of the Xserver tree. All calls to the dmx* layer are #defined + * here for the .c file. The .h file will also have to be edited. */ +#include "dmxinputinit.h" +#include "lnx-keyboard.h" + +#define GETPRIV myPrivate *priv \ + = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private + +#define LOG0(f) dmxLog(dmxDebug,f) +#define LOG1(f,a) dmxLog(dmxDebug,f,a) +#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b) +#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) +#define FATAL0(f) dmxLog(dmxFatal,f) +#define FATAL1(f,a) dmxLog(dmxFatal,f,a) +#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b) +#define MOTIONPROC dmxMotionProcPtr +#define ENQUEUEPROC dmxEnqueueProcPtr +#define CHECKPROC dmxCheckSpecialProcPtr +#define SWITCHRETPROC dmxVTSwitchReturnProcPtr +#define BLOCK DMXBlockType +#define MESSAGE "\033c\n\n\nDMX taking input from this console..." +#define FINALMESSAGE "\033cDMX terminated." + +/* End of interface definitions. */ +/*****************************************************************************/ + +#include "inputstr.h" +#include <X11/Xos.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <signal.h> +#include <sys/vt.h> +#include <sys/kd.h> +#include <termios.h> +#include "atKeynames.h" +#if 00 +#include "xf86Keymap.h" +#endif +#include <linux/keyboard.h> +#include <xkbsrv.h> + +#define NUM_AT2LNX (sizeof(at2lnx) / sizeof(at2lnx[0])) +#define NUM_STATE_ENTRIES (256/32) + + +/* Private area for Linux-style keyboards. */ +typedef struct _myPrivate { + int fd; + int vtno; + int vtcurrent; + int kbdtrans; + struct termios kbdtty; + int kbdType; + CARD32 kbdState[NUM_STATE_ENTRIES]; + DeviceIntPtr pKeyboard; + unsigned char prefix; + + int switched; + SWITCHRETPROC switch_return; + void *switch_return_data; + + /* For bell */ + int pitch; + unsigned long duration; +} myPrivate; + +static myPrivate *PRIV = NULL; + +#undef SYSCALL +#define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) + +static int kbdLinuxKeyDown(myPrivate *priv, int keyCode) +{ + CARD8 byte = keyCode >> 5; + CARD32 bit = 1 << (keyCode & 0x1f); + + if (byte > NUM_STATE_ENTRIES) return 0; + return priv->kbdState[byte] & bit; +} + +static void kbdLinuxKeyState(myPrivate *priv, int type, int keyCode) +{ + CARD8 byte = keyCode >> 5; + CARD32 bit = 1 << (keyCode & 0x1f); + + if (byte > NUM_STATE_ENTRIES) return; + if (type == KeyPress) priv->kbdState[byte] |= bit; + else priv->kbdState[byte] &= ~bit; +} + +static KeySym linux_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, + XK_currency, XK_yen, XK_brokenbar, XK_section, + XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, + XK_notsign, XK_hyphen, XK_registered, XK_macron, + XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, + XK_acute, XK_mu, XK_paragraph, XK_periodcentered, + XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, + XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, + XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, + XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, + XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, + XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, + XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, + XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, + XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, + XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, + XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, + XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, + XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, + XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, + XK_eth, XK_ntilde, XK_ograve, XK_oacute, + XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, + XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, + XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis +}; + +/* + * Maps the AT keycodes to Linux keycodes + */ +static unsigned char at2lnx[NUM_KEYCODES] = +{ + 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ + 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ + 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ + 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ + 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ + 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ + 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ + 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ + 0x11, /* KEY_W */ 0x12, /* KEY_E */ + 0x13, /* KEY_R */ 0x14, /* KEY_T */ + 0x15, /* KEY_Y */ 0x16, /* KEY_U */ + 0x17, /* KEY_I */ 0x18, /* KEY_O */ + 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ + 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ + 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ + 0x1f, /* KEY_S */ 0x20, /* KEY_D */ + 0x21, /* KEY_F */ 0x22, /* KEY_G */ + 0x23, /* KEY_H */ 0x24, /* KEY_J */ + 0x25, /* KEY_K */ 0x26, /* KEY_L */ + 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ + 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ + 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ + 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ + 0x2f, /* KEY_V */ 0x30, /* KEY_B */ + 0x31, /* KEY_N */ 0x32, /* KEY_M */ + 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ + 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ + 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ + 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ + 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ + 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ + 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ + 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ + 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ + 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ + 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ + 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ + 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ + 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ + 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ + 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ + 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ + 0x00, /* 0x55 */ 0x56, /* KEY_Less */ + 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ + 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ + 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ + 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ + 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ + 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ + 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ + 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ + 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ + 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ + 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ + 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ + 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ + 0x00, /* 0x71 */ 0x00, /* 0x72 */ + 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ + 0x00, /* 0x75 */ 0x00, /* 0x76 */ + 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ + 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ + 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ + 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ + 0x00, /* 0x7f */ +}; + +/** Create a private structure for use within this file. */ +pointer kbdLinuxCreatePrivate(DeviceIntPtr pKeyboard) +{ + myPrivate *priv = calloc(1, sizeof(*priv)); + priv->fd = -1; + priv->pKeyboard = pKeyboard; + return priv; +} + +/** Destroy a private structure. */ +void kbdLinuxDestroyPrivate(pointer priv) +{ + if (priv) free(priv); +} + +/** Ring the bell. + * + * Note: we completely ignore the \a volume, since Linux's ioctl() + * interface does not provide a way to control it. If it did, the XBell + * manpage tells how the actual volume is a function of the percent and + * the (base) volume. + * + * Note that most of the other PC-based bell drivers compute the + * duration for KDMKTONE as a function of the volume and the duration. + * For some drivers, the duration is only measured in mS if the volume + * is 50, and is scaled by the volume for other values. This seems + * confusing and possibly incorrect (the xset man page says that the + * bell will be "as closely as it can to the user's specifications" -- + * if we ignore the volume and set the duration correctly, then we'll + * get one parameter "wrong" -- but if we use the volume to scale the + * duration, then we'll get both parameters "wrong"). */ +void kbdLinuxBell(DevicePtr pDev, int percent, + int volume, int pitch, int duration) +{ + GETPRIV; + + if (duration && pitch) { + ioctl(priv->fd, + KDMKTONE, + ((1193190 / pitch) & 0xffff) /* Low bits specify cycle time */ + | (duration << 16)); /* High bits are duration in msec */ + } +} + +/** Set the LEDs. */ +void kbdLinuxCtrl(DevicePtr pDev, KeybdCtrl *ctrl) +{ + GETPRIV; + + ioctl(priv->fd, KDSETLED, ctrl->leds & 0x07); +} + +static int kbdLinuxGetFreeVTNumber(void) +{ + int fd = -1; + int vtno; + int i; + const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; + + for (i = 0; tty0[i]; i++) + if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) break; + if (fd < 0) + FATAL1("kbdLinuxGetFreeVTNumber: Cannot open tty0 (%s)\n", + strerror(errno)); + if (ioctl(fd, VT_OPENQRY, &vtno) < 0 || vtno < 0) + FATAL0("kbdLinuxGetFreeVTNumber: Cannot find a free VT\n"); + return vtno; +} + +static int kbdLinuxOpenVT(int vtno) +{ + int fd = -1; + int i; + const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; + char name[64]; /* RATS: Only used in XmuSnprintf */ + + for (i = 0; vcs[i]; i++) { + XmuSnprintf(name, sizeof(name), vcs[i], vtno); + if ((fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) break; + } + if (fd < 0) + FATAL2("kbdLinuxOpenVT: Cannot open VT %d (%s)\n", + vtno, strerror(errno)); + return fd; +} + +static int kbdLinuxGetCurrentVTNumber(int fd) +{ + struct vt_stat vts; + + if (!ioctl(fd, VT_GETSTATE, &vts)) return vts.v_active; + return -1; +} + +static int kbdLinuxActivate(int fd, int vtno, int setSig); + +/** Currently unused hook called prior to an VT switch. */ +void kbdLinuxVTPreSwitch(pointer p) +{ +} + +/** Currently unused hook called after returning from a VT switch. */ +void kbdLinuxVTPostSwitch(pointer p) +{ +} + +/** Tell the operating system to switch to \a vt. The \a switch_return + * function is called with the \a switch_return_data when the VT is + * switched back to the pre-switch VT (i.e., the user returns to the DMX + * session). */ +int kbdLinuxVTSwitch(pointer p, int vt, + void (*switch_return)(pointer), + pointer switch_return_data) +{ + myPrivate *priv = p; + + if (priv->switched) FATAL0("kbdLinuxVTSwitch: already switched...\n"); + if (priv->vtno == vt) return 0; + + PRIV = priv; + priv->switched = 0; /* Will switch to 1 in handler */ + priv->switch_return = switch_return; + priv->switch_return_data = switch_return_data; + kbdLinuxActivate(priv->fd, vt, 0); + return 1; +} + +/* RATS: This function is only ever used to handle SIGUSR1. */ +static void kbdLinuxVTSignalHandler(int sig) +{ + myPrivate *priv = PRIV; + + signal(sig, kbdLinuxVTSignalHandler); + if (priv) { + ioctl(priv->fd, VT_RELDISP, VT_ACKACQ); + priv->switched = !priv->switched; + LOG2("kbdLinuxVTSignalHandler: got signal %d, switched = %d\n", + sig, priv->switched); + if (!priv->switched && priv->switch_return) + priv->switch_return(priv->switch_return_data); + } +} + +static int kbdLinuxActivate(int fd, int vtno, int setSig) +{ + int result; + struct vt_mode VT; + + SYSCALL(result = ioctl(fd, VT_ACTIVATE, vtno)); + if (result) FATAL0("kbdLinuxActivate: VT_ACTIVATE failed\n"); + SYSCALL(result = ioctl(fd, VT_WAITACTIVE, vtno)); + if (result) FATAL0("kbdLinuxActivate: VT_WAITACTIVE failed\n"); + if (setSig) { + SYSCALL(result = ioctl(fd, VT_GETMODE, &VT)); + if (result < 0) FATAL0("kbdLinuxActivate: VT_GETMODE failed\n"); + VT.mode = VT_PROCESS; + VT.relsig = SIGUSR1; + VT.acqsig = SIGUSR1; + if (ioctl(fd, VT_SETMODE, &VT)) + FATAL0("kbdLinuxActivate: VT_SETMODE VT_PROCESS failed\n"); + signal(SIGUSR1, kbdLinuxVTSignalHandler); + } + return Success; +} + +static void kbdLinuxOpenConsole(DevicePtr pDev) +{ + GETPRIV; + const char *msg = MESSAGE; + + if (priv->fd >= 0) return; + priv->vtno = kbdLinuxGetFreeVTNumber(); + priv->fd = kbdLinuxOpenVT(priv->vtno); + priv->vtcurrent = kbdLinuxGetCurrentVTNumber(priv->fd); + LOG2("kbdLinuxOpenConsole: current VT %d; using free VT %d\n", + priv->vtcurrent, priv->vtno); + kbdLinuxActivate(priv->fd, priv->vtno, 1); + ioctl(priv->fd, KDSETMODE, KD_GRAPHICS); /* To turn off gpm */ + if (msg) write(priv->fd, msg, strlen(msg)); +} + +static void kbdLinuxCloseConsole(DevicePtr pDev) +{ + GETPRIV; + struct vt_mode VT; + const char *msg = FINALMESSAGE; + + if (priv->fd < 0) return; + + ioctl(priv->fd, KDSETMODE, KD_TEXT); + if (msg) write(priv->fd, msg, strlen(msg)); + if (ioctl(priv->fd, VT_GETMODE, &VT) != -1) { + VT.mode = VT_AUTO; + ioctl(priv->fd, VT_SETMODE, &VT); + } + + LOG1("kbdLinuxCloseConsole: switching to VT %d\n", priv->vtcurrent); + if (priv->vtcurrent >= 0) kbdLinuxActivate(priv->fd, priv->vtcurrent, 0); + + close(priv->fd); + priv->fd = -1; +} + +/** Initialize the \a pDev as a Linux keyboard. */ +void kbdLinuxInit(DevicePtr pDev) +{ + GETPRIV; + + if (priv->fd <= 0) kbdLinuxOpenConsole(pDev); + + ioctl(priv->fd, KDGKBMODE, &priv->kbdtrans); + if (tcgetattr(priv->fd, &priv->kbdtty) < 0) + FATAL1("kbdLinuxInit: tcgetattr failed (%s)\n", strerror(errno)); +} + +static int kbdLinuxPrefix0Mapping(unsigned char *scanCode) +{ + /* Table from xfree86/common/xf86Events.c */ + switch (*scanCode) { + case KEY_KP_7: *scanCode = KEY_Home; break; /* curs home */ + case KEY_KP_8: *scanCode = KEY_Up; break; /* curs up */ + case KEY_KP_9: *scanCode = KEY_PgUp; break; /* curs pgup */ + case KEY_KP_4: *scanCode = KEY_Left; break; /* curs left */ + case KEY_KP_5: *scanCode = KEY_Begin; break; /* curs begin */ + case KEY_KP_6: *scanCode = KEY_Right; break; /* curs right */ + case KEY_KP_1: *scanCode = KEY_End; break; /* curs end */ + case KEY_KP_2: *scanCode = KEY_Down; break; /* curs down */ + case KEY_KP_3: *scanCode = KEY_PgDown; break; /* curs pgdown */ + case KEY_KP_0: *scanCode = KEY_Insert; break; /* curs insert */ + case KEY_KP_Decimal: *scanCode = KEY_Delete; break; /* curs delete */ + case KEY_Enter: *scanCode = KEY_KP_Enter; break; /* keypad enter */ + case KEY_LCtrl: *scanCode = KEY_RCtrl; break; /* right ctrl */ + case KEY_KP_Multiply: *scanCode = KEY_Print; break; /* print */ + case KEY_Slash: *scanCode = KEY_KP_Divide; break; /* keyp divide */ + case KEY_Alt: *scanCode = KEY_AltLang; break; /* right alt */ + case KEY_ScrollLock: *scanCode = KEY_Break; break; /* curs break */ + case 0x5b: *scanCode = KEY_LMeta; break; + case 0x5c: *scanCode = KEY_RMeta; break; + case 0x5d: *scanCode = KEY_Menu; break; + case KEY_F3: *scanCode = KEY_F13; break; + case KEY_F4: *scanCode = KEY_F14; break; + case KEY_F5: *scanCode = KEY_F15; break; + case KEY_F6: *scanCode = KEY_F16; break; + case KEY_F7: *scanCode = KEY_F17; break; + case KEY_KP_Plus: *scanCode = KEY_KP_DEC; break; + /* + * Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) + */ + case 0x2A: + case 0x36: + return 1; + default: + /* + * "Internet" keyboards are generating lots of new codes. + * Let them pass. There is little consistency between them, + * so don't bother with symbolic names at this level. + */ + scanCode += 0x78; + } + return 0; +} + +static int kbdLinuxPrefixMapping(myPrivate *priv, unsigned char *scanCode) +{ + int pressed = *scanCode & 0x80; + unsigned char code = *scanCode & 0x7f; + + /* If we don't have a prefix, check for one */ + if (!priv->prefix) { + switch (code) { + case KEY_Prefix0: + case KEY_Prefix1: + priv->prefix = code; + return 1; + } + return 0; /* No change */ + } + + /* We have a prefix from the last scanCode */ + switch (priv->prefix) { + case KEY_Prefix0: + priv->prefix = 0; + if (kbdLinuxPrefix0Mapping(&code)) return 1; /* Skip sequence */ + break; + case KEY_Prefix1: + priv->prefix = (code = KEY_LCtrl) ? KEY_LCtrl : 0; + return 1; /* Use new prefix */ + case KEY_LCtrl: + priv->prefix = 0; + if (code != KEY_NumLock) return 1; /* Skip sequence*/ + code = KEY_Pause; + break; + } + + *scanCode = code | (pressed ? 0x80 : 0x00); + return 0; /* Use old scanCode */ +} + +static void kbdLinuxConvert(DevicePtr pDev, + unsigned char scanCode, + ENQUEUEPROC enqueue, + CHECKPROC checkspecial, + BLOCK block) +{ + GETPRIV; + XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; + int type; + KeySym keySym = NoSymbol; + int keyCode; + int switching; + + /* Do special PC/AT prefix mapping -- may change scanCode! */ + if (kbdLinuxPrefixMapping(priv, &scanCode)) return; + + type = (scanCode & 0x80) ? KeyRelease : KeyPress; + keyCode = (scanCode & 0x7f) + MIN_KEYCODE; + + /* Handle repeats */ + + if (keyCode >= xkbi->desc->min_key_code && + keyCode <= xkbi->desc->max_key_code) { + + int effectiveGroup = XkbGetEffectiveGroup(xkbi, + &xkbi->state, + scanCode); + keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); +#if 0 + switch (keySym) { + case XK_Num_Lock: + case XK_Scroll_Lock: + case XK_Shift_Lock: + case XK_Caps_Lock: + /* Ignore releases and all but first press */ + if (kbdLinuxModIgnore(priv, &xE, keySym)) return; + if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease; + else xE.u.u.type = KeyPress; + break; + } +#endif + + /* If key is already down, ignore or autorepeat */ + if (type == KeyPress && kbdLinuxKeyDown(priv, keyCode)) { + KbdFeedbackClassRec *feed = priv->pKeyboard->kbdfeed; + + /* No auto-repeat? */ + if ((feed && !feed->ctrl.autoRepeat) + || priv->pKeyboard->key->xkbInfo->desc->map->modmap[keyCode] + || (feed + && !(feed->ctrl.autoRepeats[keyCode >> 3] + & (1 << (keyCode & 7))))) return; /* Ignore */ + + /* Do auto-repeat */ + enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); + type = KeyPress; + } + + /* If key is already up, ignore */ + if (type == KeyRelease && !kbdLinuxKeyDown(priv, keyCode)) return; + } + + switching = 0; + if (checkspecial && type == KeyPress) + switching = checkspecial(pDev, keySym); + if (!switching) { + if (enqueue) + enqueue(pDev, type, keyCode, keySym, NULL, block); + kbdLinuxKeyState(priv, type, keyCode); /* Update our state bitmap */ + } +} + +/** Read an event from the \a pDev device. If the event is a motion + * event, enqueue it with the \a motion function. Otherwise, check for + * special keys with the \a checkspecial function and enqueue the event + * with the \a enqueue function. The \a block type is passed to the + * functions so that they may block SIGIO handling as appropriate to the + * caller of this function. */ +void kbdLinuxRead(DevicePtr pDev, + MOTIONPROC motion, + ENQUEUEPROC enqueue, + CHECKPROC checkspecial, + BLOCK block) +{ + GETPRIV; + unsigned char buf[256]; /* RATS: Only used in length-limited call */ + unsigned char *pt; + int n; + + while ((n = read(priv->fd, buf, sizeof(buf))) > 0) + for (pt = buf; n; --n, ++pt) + kbdLinuxConvert(pDev, *pt, enqueue, checkspecial, block); +} + +/** Turn \a pDev on (i.e., take input from \a pDev). */ +int kbdLinuxOn(DevicePtr pDev) +{ + GETPRIV; + struct termios nTty; + + ioctl(priv->fd, KDSKBMODE, K_RAW); + + nTty = priv->kbdtty; + nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8; + nTty.c_lflag = 0; + nTty.c_cc[VTIME] = 0; + nTty.c_cc[VMIN] = 1; + cfsetispeed(&nTty, B9600); + cfsetospeed(&nTty, B9600); + if (tcsetattr(priv->fd, TCSANOW, &nTty) < 0) + FATAL1("kbdLinuxOn: tcsetattr failed (%s)\n", strerror(errno)); + return priv->fd; +} + +/** Turn \a pDev off (i.e., stop taking input from \a pDev). */ +void kbdLinuxOff(DevicePtr pDev) +{ + GETPRIV; + + ioctl(priv->fd, KDSKBMODE, priv->kbdtrans); + tcsetattr(priv->fd, TCSANOW, &priv->kbdtty); + kbdLinuxCloseConsole(pDev); +} + + +static void kbdLinuxReadKernelMapping(int fd, KeySymsPtr pKeySyms) +{ + KeySym *k; + int i; + int maxkey; + static unsigned char tbl[GLYPHS_PER_KEY] = { /* RATS: Use ok */ + 0, /* unshifted */ + 1, /* shifted */ + 0, /* modeswitch unshifted */ + 0 /* modeswitch shifted */ + }; + + /* + * Read the mapping from the kernel. + * Since we're still using the XFree86 scancode->AT keycode mapping + * routines, we need to convert the AT keycodes to Linux keycodes, + * then translate the Linux keysyms into X keysyms. + * + * First, figure out which tables to use for the modeswitch columns + * above, from the XF86Config fields. + */ + tbl[2] = 8; /* alt */ + tbl[3] = tbl[2] | 1; + +#if 00/*BP*/ + k = map+GLYPHS_PER_KEY; +#else + ErrorF("kbdLinuxReadKernelMapping() is broken/no-op'd\n"); + return; +#endif + maxkey = NUM_AT2LNX; + + for (i = 0; i < maxkey; ++i) { + struct kbentry kbe; + int j; + + kbe.kb_index = at2lnx[i]; + + for (j = 0; j < GLYPHS_PER_KEY; ++j, ++k) { + unsigned short kval; + + *k = NoSymbol; + + kbe.kb_table = tbl[j]; + if (kbe.kb_index == 0 || ioctl(fd, KDGKBENT, &kbe)) continue; + + kval = KVAL(kbe.kb_value); + switch (KTYP(kbe.kb_value)) { + case KT_LATIN: + case KT_LETTER: *k = linux_to_x[kval]; break; + case KT_FN: + if (kval <= 19) *k = XK_F1 + kval; + else switch (kbe.kb_value) { + case K_FIND: *k = XK_Home; /* or XK_Find */ break; + case K_INSERT: *k = XK_Insert; break; + case K_REMOVE: *k = XK_Delete; break; + case K_SELECT: *k = XK_End; /* or XK_Select */ break; + case K_PGUP: *k = XK_Prior; break; + case K_PGDN: *k = XK_Next; break; + case K_HELP: *k = XK_Help; break; + case K_DO: *k = XK_Execute; break; + case K_PAUSE: *k = XK_Pause; break; + case K_MACRO: *k = XK_Menu; break; + default: break; + } + break; + case KT_SPEC: + switch (kbe.kb_value) { + case K_ENTER: *k = XK_Return; break; + case K_BREAK: *k = XK_Break; break; + case K_CAPS: *k = XK_Caps_Lock; break; + case K_NUM: *k = XK_Num_Lock; break; + case K_HOLD: *k = XK_Scroll_Lock; break; + case K_COMPOSE: *k = XK_Multi_key; break; + default: break; + } + break; + case KT_PAD: + switch (kbe.kb_value) { + case K_PPLUS: *k = XK_KP_Add; break; + case K_PMINUS: *k = XK_KP_Subtract; break; + case K_PSTAR: *k = XK_KP_Multiply; break; + case K_PSLASH: *k = XK_KP_Divide; break; + case K_PENTER: *k = XK_KP_Enter; break; + case K_PCOMMA: *k = XK_KP_Separator; break; + case K_PDOT: *k = XK_KP_Decimal; break; + case K_PPLUSMINUS: *k = XK_KP_Subtract; break; + default: if (kval <= 9) *k = XK_KP_0 + kval; break; + } + break; + case KT_DEAD: + /* KT_DEAD keys are for accelerated diacritical creation. */ + switch (kbe.kb_value) { + case K_DGRAVE: *k = XK_dead_grave; break; + case K_DACUTE: *k = XK_dead_acute; break; + case K_DCIRCM: *k = XK_dead_circumflex; break; + case K_DTILDE: *k = XK_dead_tilde; break; + case K_DDIERE: *k = XK_dead_diaeresis; break; + } + break; + case KT_CUR: + switch (kbe.kb_value) { + case K_DOWN: *k = XK_Down; break; + case K_LEFT: *k = XK_Left; break; + case K_RIGHT: *k = XK_Right; break; + case K_UP: *k = XK_Up; break; + } + break; + case KT_SHIFT: + switch (kbe.kb_value) { + case K_ALTGR: *k = XK_Alt_R; break; + case K_ALT: + *k = (kbe.kb_index == 0x64 ? XK_Alt_R : XK_Alt_L); + break; + case K_CTRL: + *k = (kbe.kb_index == 0x61 ? XK_Control_R : XK_Control_L); + break; + case K_CTRLL: *k = XK_Control_L; break; + case K_CTRLR: *k = XK_Control_R; break; + case K_SHIFT: + *k = (kbe.kb_index == 0x36 ? XK_Shift_R : XK_Shift_L); + break; + case K_SHIFTL: *k = XK_Shift_L; break; + case K_SHIFTR: *k = XK_Shift_R; break; + default: break; + } + break; + case KT_ASCII: + /* KT_ASCII keys accumulate a 3 digit decimal number that + * gets emitted when the shift state changes. We can't + * emulate that. + */ + break; + case KT_LOCK: + if (kbe.kb_value == K_SHIFTLOCK) *k = XK_Shift_Lock; + break; + default: break; + } + } + + if (k[-1] == k[-2]) k[-1] = NoSymbol; + if (k[-2] == k[-3]) k[-2] = NoSymbol; + if (k[-3] == k[-4]) k[-3] = NoSymbol; + if (k[-4] == k[-2] && k[-3] == k[-1]) k[-2] = k[-1] = NoSymbol; + if (k[-1] == k[-4] && k[-2] == k[-3] + && k[-2] == NoSymbol) k[-1] = NoSymbol; + } +} + +static void kbdLinuxGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) +{ + GETPRIV; + KeySym *k, *mapCopy; + char type; + int i; + +#if 00/*BP*/ + mapCopy = malloc(sizeof(map)); + memcpy(mapCopy, map, sizeof(map)); +#else + ErrorF("kbdLinuxGetMap() is broken/no-op'd\n"); + return; +#endif + + kbdLinuxReadKernelMapping(priv->fd, pKeySyms); + + /* compute the modifier map */ + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; /* make sure it is restored */ + + for (k = mapCopy, i = MIN_KEYCODE; + i < NUM_KEYCODES + MIN_KEYCODE; + i++, k += 4) { + switch(*k) { + case XK_Shift_L: + case XK_Shift_R: pModMap[i] = ShiftMask; break; + case XK_Control_L: + case XK_Control_R: pModMap[i] = ControlMask; break; + case XK_Caps_Lock: pModMap[i] = LockMask; break; + case XK_Alt_L: + case XK_Alt_R: pModMap[i] = AltMask; break; + case XK_Num_Lock: pModMap[i] = NumLockMask; break; + case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break; + case XK_Kana_Lock: + case XK_Kana_Shift: pModMap[i] = KanaMask; break; + case XK_Mode_switch: pModMap[i] = AltLangMask; break; + } + } + + priv->kbdType = (ioctl(priv->fd, KDGKBTYPE, &type) < 0) ? KB_101 : type; + + pKeySyms->map = mapCopy; /* Must be XFree'able */ + pKeySyms->mapWidth = GLYPHS_PER_KEY; + pKeySyms->minKeyCode = MIN_KEYCODE; + pKeySyms->maxKeyCode = MAX_KEYCODE; +} + +/** Fill the \a info structure with information needed to initialize \a + * pDev. */ +void kbdLinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) +{ + info->keyboard = 1; + info->keyClass = 1; + kbdLinuxGetMap(pDev, &info->keySyms, info->modMap); + info->focusClass = 1; + info->kbdFeedbackClass = 1; +} diff --git a/xorg-server/hw/dmx/input/usb-keyboard.c b/xorg-server/hw/dmx/input/usb-keyboard.c index c4667a3c3..fcbea47f9 100644 --- a/xorg-server/hw/dmx/input/usb-keyboard.c +++ b/xorg-server/hw/dmx/input/usb-keyboard.c @@ -1,444 +1,444 @@ -/* Portions of this file were derived from the following files: - * - ********************************************************************** - * - * xfree86/common/xf86KbdLnx.c - * - * Linux version of keymapping setup. The kernel (since 0.99.14) has support - * for fully remapping the keyboard, but there are some differences between - * the Linux map and the SVR4 map (esp. in the extended keycodes). We also - * remove the restriction on what keycodes can be remapped. - * Orest Zborowski. - * - * 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. - * - */ - -/* - * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina. - * - * 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 on 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 - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: - * Rickard E. (Rik) Faith <faith@redhat.com> - * - */ - -/** \file - * - * This code implements a low-level device driver for a USB keyboard - * under Linux. The keymap description is derived from code by Thomas - * Roell, Orest Zborowski. */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "atKeynames.h" -#include "usb-private.h" - -#define USB_KEYBOARD_DEBUG 0 - -/*****************************************************************************/ -/* Define some macros to make it easier to move this file to another - * part of the Xserver tree. All calls to the dmx* layer are #defined - * here for the .c file. The .h file will also have to be edited. */ -#include "usb-keyboard.h" -#include <xkbsrv.h> - -#define GETPRIV myPrivate *priv \ - = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private - -#define LOG0(f) dmxLog(dmxDebug,f) -#define LOG1(f,a) dmxLog(dmxDebug,f,a) -#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b) -#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) -#define FATAL0(f) dmxLog(dmxFatal,f) -#define FATAL1(f,a) dmxLog(dmxFatal,f,a) -#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b) -#define MOTIONPROC dmxMotionProcPtr -#define ENQUEUEPROC dmxEnqueueProcPtr -#define CHECKPROC dmxCheckSpecialProcPtr -#define BLOCK DMXBlockType - -/* End of interface definitions. */ -/*****************************************************************************/ - -#define GLYPHS_PER_KEY 4 -#define NUM_KEYCODES 248 -#define MIN_KEYCODE 8 -#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1) - -static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = { -/* Table modified from xc/programs/Xserver/hw/xfree86/common/xf86Keymap.h */ - /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, - /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, - /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, - /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, - /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, - /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, - /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, - /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, - /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, - /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, - /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, - /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, - /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, - /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, - /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol, - /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol, - /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol, - /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol, - /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol, - /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol, - /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol, - /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol, - /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol, - /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol, - /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol, - /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, - /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, - /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, - /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, - /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol, - /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol, - /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol, - /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol, - /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol, - /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol, - /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol, - /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol, - /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol, - /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, - /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, - /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, - /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, - /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, - /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol, - /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol, - /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol, - /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol, - /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol, - /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol, - /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol, - /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, - /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, - /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, - /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, - /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, - /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, - /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, - /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, - /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, - /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, - /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, - /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, - /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, - /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, - /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, - /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, - /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, - /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, - /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, - /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, - /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, - /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, - /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, - /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, - /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, - /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, - /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, - /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, - /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, - /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, - /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, - /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, - /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, - /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, - /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, - /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, - /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, - /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, - /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x60 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, - /* 0x61 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, - /* 0x62 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, - /* 0x63 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, - /* 0x64 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, - /* 0x65 */ XK_Break, NoSymbol, NoSymbol, NoSymbol, - /* 0x66 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, - /* 0x67 */ XK_Up, NoSymbol, NoSymbol, NoSymbol, - /* 0x68 */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, - /* 0x69 */ XK_Left, NoSymbol, NoSymbol, NoSymbol, - /* 0x6a */ XK_Right, NoSymbol, NoSymbol, NoSymbol, - /* 0x6b */ XK_End, NoSymbol, NoSymbol, NoSymbol, - /* 0x6c */ XK_Down, NoSymbol, NoSymbol, NoSymbol, - /* 0x6d */ XK_Next, NoSymbol, NoSymbol, NoSymbol, - /* 0x6e */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, - /* 0x6f */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, - /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x77 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, - /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x7a */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, - /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, - /* 0x7d */ XK_Super_L, NoSymbol, NoSymbol, NoSymbol, - /* 0x7e */ XK_Super_R, NoSymbol, NoSymbol, NoSymbol, - /* 0x7f */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, -}; - -static int kbdUSBKeyDown(myPrivate *priv, int keyCode) -{ - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return 0; - return priv->kbdState[byte] & bit; -} - -static void kbdUSBKeyState(myPrivate *priv, int type, int keyCode) -{ - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return; - if (type == KeyPress) priv->kbdState[byte] |= bit; - else priv->kbdState[byte] &= ~bit; -} - -/** Set the LEDs. */ -void kbdUSBCtrl(DevicePtr pDev, KeybdCtrl *ctrl) -{ - GETPRIV; - struct timeval tv; - struct input_event event; - int i, led; - - gettimeofday(&tv, NULL); - for (i = 0; i < 5; i++) { - event.time.tv_sec = tv.tv_sec; - event.time.tv_usec = tv.tv_usec; - event.type = EV_LED; - if (i == 0) led = 1; /* LED_CAPSL == 0x01 */ - else if (i == 1) led = 0; /* LED_NUML == 0x00 */ - else led = i; - event.code = led; - event.value = !!(ctrl->leds & (1 << led)); - write(priv->fd, &event, sizeof(event)); - } -} - -/** Initialize \a pDev using #usbInit. */ -void kbdUSBInit(DevicePtr pDev) -{ - usbInit(pDev, usbKeyboard); -} - -static void kbdUSBConvert(DevicePtr pDev, - unsigned int scanCode, - int value, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) -{ - GETPRIV; - XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; - int type; - int keyCode; - KeySym keySym = NoSymbol; - int switching; - - /* Set up xEvent information */ - type = value ? KeyPress : KeyRelease; - keyCode = (scanCode & 0xff) + MIN_KEYCODE; - - /* Handle repeats */ - - if (keyCode >= xkbi->desc->min_key_code && - keyCode <= xkbi->desc->max_key_code) { - - int effectiveGroup = XkbGetEffectiveGroup(xkbi, - &xkbi->state, - scanCode); - keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); -#if 0 - switch (keySym) { - case XK_Num_Lock: - case XK_Scroll_Lock: - case XK_Shift_Lock: - case XK_Caps_Lock: - /* Ignore releases and all but first press */ - if (kbdLinuxModIgnore(priv, &xE, keySym)) return; - if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease; - else xE.u.u.type = KeyPress; - break; - } -#endif - - /* If key is already down, ignore or autorepeat */ - if (type == KeyPress && kbdUSBKeyDown(priv, keyCode)) { - KbdFeedbackClassRec *feed = priv->pDevice->kbdfeed; - - /* No auto-repeat? */ - if ((feed && !feed->ctrl.autoRepeat) - || priv->pDevice->key->xkbInfo->desc->map->modmap[keyCode] - || (feed - && !(feed->ctrl.autoRepeats[keyCode >> 3] - & (1 << (keyCode & 7))))) return; /* Ignore */ - - /* Do auto-repeat */ - enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); - type = KeyPress; - } - - /* If key is already up, ignore */ - if (type == KeyRelease && !kbdUSBKeyDown(priv, keyCode)) return; - } - - switching = 0; - if (checkspecial && type == KeyPress) - switching = checkspecial(pDev, keySym); - if (!switching) { - if (enqueue) - enqueue(pDev, type, keyCode, keySym, NULL, block); - kbdUSBKeyState(priv, type, keyCode); /* Update our state bitmap */ - } -} - -/** Read an event from the \a pDev device. If the event is a motion - * event, enqueue it with the \a motion function. Otherwise, check for - * special keys with the \a checkspecial function and enqueue the event - * with the \a enqueue function. The \a block type is passed to the - * functions so that they may block SIGIO handling as appropriate to the - * caller of this function. */ -void kbdUSBRead(DevicePtr pDev, - MOTIONPROC motion, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) -{ - GETPRIV; - struct input_event raw; - - while (read(priv->fd, &raw, sizeof(raw)) > 0) { -#if USB_KEYBOARD_DEBUG - LOG3("KBD: type = %d, code = 0x%02x, value = %d\n", - raw.type, raw.code, raw.value); -#endif - kbdUSBConvert(pDev, raw.code, raw.value, enqueue, checkspecial, block); - } -} - -/** Turn \a pDev on (i.e., take input from \a pDev). */ -int kbdUSBOn(DevicePtr pDev) -{ - GETPRIV; - - if (priv->fd < 0) kbdUSBInit(pDev); - return priv->fd; -} - -static void kbdUSBGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) -{ - KeySym *k, *mapCopy; - int i; - - mapCopy = xalloc(sizeof(map)); - memcpy(mapCopy, map, sizeof(map)); - - /* compute the modifier map */ - for (i = 0; i < MAP_LENGTH; i++) - pModMap[i] = NoSymbol; /* make sure it is restored */ - - for (k = mapCopy, i = MIN_KEYCODE; - i < NUM_KEYCODES + MIN_KEYCODE; - i++, k += 4) { - switch(*k) { - case XK_Shift_L: - case XK_Shift_R: pModMap[i] = ShiftMask; break; - case XK_Control_L: - case XK_Control_R: pModMap[i] = ControlMask; break; - case XK_Caps_Lock: pModMap[i] = LockMask; break; - case XK_Alt_L: - case XK_Alt_R: pModMap[i] = AltMask; break; - case XK_Num_Lock: pModMap[i] = NumLockMask; break; - case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break; - case XK_Kana_Lock: - case XK_Kana_Shift: pModMap[i] = KanaMask; break; - case XK_Mode_switch: pModMap[i] = AltLangMask; break; - } - } - - pKeySyms->map = mapCopy; /* Must be XFree'able */ - pKeySyms->mapWidth = GLYPHS_PER_KEY; - pKeySyms->minKeyCode = MIN_KEYCODE; - pKeySyms->maxKeyCode = MAX_KEYCODE; -} - -/** Fill the \a info structure with information needed to initialize \a - * pDev. */ -void kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) -{ - info->keyboard = 1; - info->keyClass = 1; - kbdUSBGetMap(pDev, &info->keySyms, info->modMap); - info->focusClass = 1; - info->kbdFeedbackClass = 1; - info->names.keycodes = xstrdup("powerpcps2"); - info->force = 1; -} +/* Portions of this file were derived from the following files: + * + ********************************************************************** + * + * xfree86/common/xf86KbdLnx.c + * + * Linux version of keymapping setup. The kernel (since 0.99.14) has support + * for fully remapping the keyboard, but there are some differences between + * the Linux map and the SVR4 map (esp. in the extended keycodes). We also + * remove the restriction on what keycodes can be remapped. + * Orest Zborowski. + * + * 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. + * + */ + +/* + * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR 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: + * Rickard E. (Rik) Faith <faith@redhat.com> + * + */ + +/** \file + * + * This code implements a low-level device driver for a USB keyboard + * under Linux. The keymap description is derived from code by Thomas + * Roell, Orest Zborowski. */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "atKeynames.h" +#include "usb-private.h" + +#define USB_KEYBOARD_DEBUG 0 + +/*****************************************************************************/ +/* Define some macros to make it easier to move this file to another + * part of the Xserver tree. All calls to the dmx* layer are #defined + * here for the .c file. The .h file will also have to be edited. */ +#include "usb-keyboard.h" +#include <xkbsrv.h> + +#define GETPRIV myPrivate *priv \ + = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private + +#define LOG0(f) dmxLog(dmxDebug,f) +#define LOG1(f,a) dmxLog(dmxDebug,f,a) +#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b) +#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c) +#define FATAL0(f) dmxLog(dmxFatal,f) +#define FATAL1(f,a) dmxLog(dmxFatal,f,a) +#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b) +#define MOTIONPROC dmxMotionProcPtr +#define ENQUEUEPROC dmxEnqueueProcPtr +#define CHECKPROC dmxCheckSpecialProcPtr +#define BLOCK DMXBlockType + +/* End of interface definitions. */ +/*****************************************************************************/ + +#define GLYPHS_PER_KEY 4 +#define NUM_KEYCODES 248 +#define MIN_KEYCODE 8 +#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1) + +static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = { +/* Table modified from xc/programs/Xserver/hw/xfree86/common/xf86Keymap.h */ + /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, + /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, + /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, + /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, + /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, + /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, + /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, + /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, + /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, + /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, + /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, + /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, + /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, + /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, + /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol, + /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol, + /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol, + /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol, + /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol, + /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol, + /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol, + /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol, + /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol, + /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol, + /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, + /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol, + /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, + /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol, + /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol, + /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol, + /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol, + /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol, + /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol, + /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol, + /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol, + /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, + /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, + /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, + /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, + /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol, + /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol, + /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol, + /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol, + /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol, + /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol, + /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol, + /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, + /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, + /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, + /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, + /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, + /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, + /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, + /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, + /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, + /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, + /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, + /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, + /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, + /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, + /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, + /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, + /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, + /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, + /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, + /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, + /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, + /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, + /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, + /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, + /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, + /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, + /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, + /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, + /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, + /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, + /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, + /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, + /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, + /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, + /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x60 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, + /* 0x61 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x62 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, + /* 0x63 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, + /* 0x64 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, + /* 0x65 */ XK_Break, NoSymbol, NoSymbol, NoSymbol, + /* 0x66 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, + /* 0x67 */ XK_Up, NoSymbol, NoSymbol, NoSymbol, + /* 0x68 */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, + /* 0x69 */ XK_Left, NoSymbol, NoSymbol, NoSymbol, + /* 0x6a */ XK_Right, NoSymbol, NoSymbol, NoSymbol, + /* 0x6b */ XK_End, NoSymbol, NoSymbol, NoSymbol, + /* 0x6c */ XK_Down, NoSymbol, NoSymbol, NoSymbol, + /* 0x6d */ XK_Next, NoSymbol, NoSymbol, NoSymbol, + /* 0x6e */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, + /* 0x6f */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, + /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x77 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, + /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7a */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, + /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7d */ XK_Super_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x7e */ XK_Super_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x7f */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, +}; + +static int kbdUSBKeyDown(myPrivate *priv, int keyCode) +{ + CARD8 byte = keyCode >> 5; + CARD32 bit = 1 << (keyCode & 0x1f); + + if (byte > NUM_STATE_ENTRIES) return 0; + return priv->kbdState[byte] & bit; +} + +static void kbdUSBKeyState(myPrivate *priv, int type, int keyCode) +{ + CARD8 byte = keyCode >> 5; + CARD32 bit = 1 << (keyCode & 0x1f); + + if (byte > NUM_STATE_ENTRIES) return; + if (type == KeyPress) priv->kbdState[byte] |= bit; + else priv->kbdState[byte] &= ~bit; +} + +/** Set the LEDs. */ +void kbdUSBCtrl(DevicePtr pDev, KeybdCtrl *ctrl) +{ + GETPRIV; + struct timeval tv; + struct input_event event; + int i, led; + + gettimeofday(&tv, NULL); + for (i = 0; i < 5; i++) { + event.time.tv_sec = tv.tv_sec; + event.time.tv_usec = tv.tv_usec; + event.type = EV_LED; + if (i == 0) led = 1; /* LED_CAPSL == 0x01 */ + else if (i == 1) led = 0; /* LED_NUML == 0x00 */ + else led = i; + event.code = led; + event.value = !!(ctrl->leds & (1 << led)); + write(priv->fd, &event, sizeof(event)); + } +} + +/** Initialize \a pDev using #usbInit. */ +void kbdUSBInit(DevicePtr pDev) +{ + usbInit(pDev, usbKeyboard); +} + +static void kbdUSBConvert(DevicePtr pDev, + unsigned int scanCode, + int value, + ENQUEUEPROC enqueue, + CHECKPROC checkspecial, + BLOCK block) +{ + GETPRIV; + XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; + int type; + int keyCode; + KeySym keySym = NoSymbol; + int switching; + + /* Set up xEvent information */ + type = value ? KeyPress : KeyRelease; + keyCode = (scanCode & 0xff) + MIN_KEYCODE; + + /* Handle repeats */ + + if (keyCode >= xkbi->desc->min_key_code && + keyCode <= xkbi->desc->max_key_code) { + + int effectiveGroup = XkbGetEffectiveGroup(xkbi, + &xkbi->state, + scanCode); + keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); +#if 0 + switch (keySym) { + case XK_Num_Lock: + case XK_Scroll_Lock: + case XK_Shift_Lock: + case XK_Caps_Lock: + /* Ignore releases and all but first press */ + if (kbdLinuxModIgnore(priv, &xE, keySym)) return; + if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease; + else xE.u.u.type = KeyPress; + break; + } +#endif + + /* If key is already down, ignore or autorepeat */ + if (type == KeyPress && kbdUSBKeyDown(priv, keyCode)) { + KbdFeedbackClassRec *feed = priv->pDevice->kbdfeed; + + /* No auto-repeat? */ + if ((feed && !feed->ctrl.autoRepeat) + || priv->pDevice->key->xkbInfo->desc->map->modmap[keyCode] + || (feed + && !(feed->ctrl.autoRepeats[keyCode >> 3] + & (1 << (keyCode & 7))))) return; /* Ignore */ + + /* Do auto-repeat */ + enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); + type = KeyPress; + } + + /* If key is already up, ignore */ + if (type == KeyRelease && !kbdUSBKeyDown(priv, keyCode)) return; + } + + switching = 0; + if (checkspecial && type == KeyPress) + switching = checkspecial(pDev, keySym); + if (!switching) { + if (enqueue) + enqueue(pDev, type, keyCode, keySym, NULL, block); + kbdUSBKeyState(priv, type, keyCode); /* Update our state bitmap */ + } +} + +/** Read an event from the \a pDev device. If the event is a motion + * event, enqueue it with the \a motion function. Otherwise, check for + * special keys with the \a checkspecial function and enqueue the event + * with the \a enqueue function. The \a block type is passed to the + * functions so that they may block SIGIO handling as appropriate to the + * caller of this function. */ +void kbdUSBRead(DevicePtr pDev, + MOTIONPROC motion, + ENQUEUEPROC enqueue, + CHECKPROC checkspecial, + BLOCK block) +{ + GETPRIV; + struct input_event raw; + + while (read(priv->fd, &raw, sizeof(raw)) > 0) { +#if USB_KEYBOARD_DEBUG + LOG3("KBD: type = %d, code = 0x%02x, value = %d\n", + raw.type, raw.code, raw.value); +#endif + kbdUSBConvert(pDev, raw.code, raw.value, enqueue, checkspecial, block); + } +} + +/** Turn \a pDev on (i.e., take input from \a pDev). */ +int kbdUSBOn(DevicePtr pDev) +{ + GETPRIV; + + if (priv->fd < 0) kbdUSBInit(pDev); + return priv->fd; +} + +static void kbdUSBGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) +{ + KeySym *k, *mapCopy; + int i; + + mapCopy = malloc(sizeof(map)); + memcpy(mapCopy, map, sizeof(map)); + + /* compute the modifier map */ + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; /* make sure it is restored */ + + for (k = mapCopy, i = MIN_KEYCODE; + i < NUM_KEYCODES + MIN_KEYCODE; + i++, k += 4) { + switch(*k) { + case XK_Shift_L: + case XK_Shift_R: pModMap[i] = ShiftMask; break; + case XK_Control_L: + case XK_Control_R: pModMap[i] = ControlMask; break; + case XK_Caps_Lock: pModMap[i] = LockMask; break; + case XK_Alt_L: + case XK_Alt_R: pModMap[i] = AltMask; break; + case XK_Num_Lock: pModMap[i] = NumLockMask; break; + case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break; + case XK_Kana_Lock: + case XK_Kana_Shift: pModMap[i] = KanaMask; break; + case XK_Mode_switch: pModMap[i] = AltLangMask; break; + } + } + + pKeySyms->map = mapCopy; /* Must be XFree'able */ + pKeySyms->mapWidth = GLYPHS_PER_KEY; + pKeySyms->minKeyCode = MIN_KEYCODE; + pKeySyms->maxKeyCode = MAX_KEYCODE; +} + +/** Fill the \a info structure with information needed to initialize \a + * pDev. */ +void kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) +{ + info->keyboard = 1; + info->keyClass = 1; + kbdUSBGetMap(pDev, &info->keySyms, info->modMap); + info->focusClass = 1; + info->kbdFeedbackClass = 1; + info->names.keycodes = xstrdup("powerpcps2"); + info->force = 1; +} diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.c b/xorg-server/hw/kdrive/ephyr/ephyr.c index 6e61b8c5d..21c696c20 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr.c +++ b/xorg-server/hw/kdrive/ephyr/ephyr.c @@ -76,13 +76,13 @@ ephyrCardInit (KdCardInfo *card) { EphyrPriv *priv; - priv = (EphyrPriv *) xalloc (sizeof (EphyrPriv)); + priv = (EphyrPriv *) malloc(sizeof (EphyrPriv)); if (!priv) return FALSE; if (!ephyrInitialize (card, priv)) { - xfree (priv); + free(priv); return FALSE; } card->driver = priv; @@ -188,7 +188,7 @@ ephyrScreenInit (KdScreenInfo *screen) { EphyrScrPriv *scrpriv; - scrpriv = xcalloc (1, sizeof (EphyrScrPriv)); + scrpriv = calloc(1, sizeof (EphyrScrPriv)); if (!scrpriv) return FALSE; @@ -198,7 +198,7 @@ ephyrScreenInit (KdScreenInfo *screen) if (!ephyrScreenInitialize (screen, scrpriv)) { screen->driver = 0; - xfree (scrpriv); + free(scrpriv); return FALSE; } @@ -740,7 +740,7 @@ ephyrScreenFini (KdScreenInfo *screen) if (scrpriv->shadow) { KdShadowFbFree (screen); } - xfree(screen->driver); + free(screen->driver); screen->driver = NULL; } @@ -1034,7 +1034,7 @@ void ephyrCardFini (KdCardInfo *card) { EphyrPriv *priv = card->driver; - xfree (priv); + free(priv); } void @@ -1086,11 +1086,11 @@ static Status MouseInit (KdPointerInfo *pi) { pi->driverPrivate = (EphyrPointerPrivate *) - xcalloc(sizeof(EphyrPointerPrivate), 1); + calloc(sizeof(EphyrPointerPrivate), 1); ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE; pi->nAxes = 3; pi->nButtons = 32; - xfree(pi->name); + free(pi->name); pi->name = strdup("Xephyr virtual mouse"); ephyrMouse = pi; return Success; @@ -1132,7 +1132,7 @@ static Status EphyrKeyboardInit (KdKeyboardInfo *ki) { ki->driverPrivate = (EphyrKbdPrivate *) - xcalloc(sizeof(EphyrKbdPrivate), 1); + calloc(sizeof(EphyrKbdPrivate), 1); hostx_load_keymap(); if (!ephyrKeySyms.map) { ErrorF("Couldn't load keymap from host\n"); @@ -1140,7 +1140,7 @@ EphyrKeyboardInit (KdKeyboardInfo *ki) } ki->minScanCode = ephyrKeySyms.minKeyCode; ki->maxScanCode = ephyrKeySyms.maxKeyCode; - xfree(ki->name); + free(ki->name); ki->name = strdup("Xephyr virtual keyboard"); ephyrKbd = ki; return Success; diff --git a/xorg-server/hw/kdrive/ephyr/ephyr_draw.c b/xorg-server/hw/kdrive/ephyr/ephyr_draw.c index f9fac8007..f3e2be6eb 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyr_draw.c +++ b/xorg-server/hw/kdrive/ephyr/ephyr_draw.c @@ -1,524 +1,523 @@ -/* - * 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 <eric@anholt.net> - * - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif - -#include "ephyr.h" -#include "exa_priv.h" -#include "fbpict.h" - -#define EPHYR_TRACE_DRAW 0 - -#if EPHYR_TRACE_DRAW -#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__); -#else -#define TRACE_DRAW() do { } while (0) -#endif - -/* Use some oddball alignments, to expose issues in alignment handling in EXA. */ -#define EPHYR_OFFSET_ALIGN 24 -#define EPHYR_PITCH_ALIGN 24 - -#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024) -#define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024) - -/** - * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to - * fb functions. - */ -static void -ephyrPreparePipelinedAccess(PixmapPtr pPix, int index) -{ - KdScreenPriv(pPix->drawable.pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - assert(fakexa->saved_ptrs[index] == NULL); - fakexa->saved_ptrs[index] = pPix->devPrivate.ptr; - - if (pPix->devPrivate.ptr != NULL) - return; - - pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix); -} - -/** - * Restores the original devPrivate.ptr of the pixmap from before we messed with - * it. - */ -static void -ephyrFinishPipelinedAccess(PixmapPtr pPix, int index) -{ - KdScreenPriv(pPix->drawable.pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - pPix->devPrivate.ptr = fakexa->saved_ptrs[index]; - fakexa->saved_ptrs[index] = NULL; -} - -/** - * Sets up a scratch GC for fbFill, and saves other parameters for the - * ephyrSolid implementation. - */ -static Bool -ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) -{ - ScreenPtr pScreen = pPix->drawable.pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - CARD32 tmpval[3]; - - ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST); - - fakexa->pDst = pPix; - fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen); - - tmpval[0] = alu; - tmpval[1] = pm; - tmpval[2] = fg; - ChangeGC(fakexa->pGC, GCFunction | GCPlaneMask | GCForeground, - tmpval); - - ValidateGC(&pPix->drawable, fakexa->pGC); - - TRACE_DRAW(); - - return TRUE; -} - -/** - * Does an fbFill of the rectangle to be drawn. - */ -static void -ephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2) -{ - ScreenPtr pScreen = pPix->drawable.pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1); -} - -/** - * Cleans up the scratch GC created in ephyrPrepareSolid. - */ -static void -ephyrDoneSolid(PixmapPtr pPix) -{ - ScreenPtr pScreen = pPix->drawable.pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - FreeScratchGC(fakexa->pGC); - - ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST); -} - -/** - * Sets up a scratch GC for fbCopyArea, and saves other parameters for the - * ephyrCopy implementation. - */ -static Bool -ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, - Pixel pm) -{ - ScreenPtr pScreen = pDst->drawable.pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - CARD32 tmpval[2]; - - ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); - ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); - - fakexa->pSrc = pSrc; - fakexa->pDst = pDst; - fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen); - - tmpval[0] = alu; - tmpval[1] = pm; - ChangeGC (fakexa->pGC, GCFunction | GCPlaneMask, tmpval); - - ValidateGC(&pDst->drawable, fakexa->pGC); - - TRACE_DRAW(); - - return TRUE; -} - -/** - * Does an fbCopyArea to take care of the requested copy. - */ -static void -ephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h) -{ - ScreenPtr pScreen = pDst->drawable.pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC, - srcX, srcY, w, h, dstX, dstY); -} - -/** - * Cleans up the scratch GC created in ephyrPrepareCopy. - */ -static void -ephyrDoneCopy(PixmapPtr pDst) -{ - ScreenPtr pScreen = pDst->drawable.pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - FreeScratchGC (fakexa->pGC); - - ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC); - ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST); -} - -/** - * Reports that we can always accelerate the given operation. This may not be - * desirable from an EXA testing standpoint -- testing the fallback paths would - * be useful, too. - */ -static Bool -ephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, - PicturePtr pDstPicture) -{ - /* Exercise the component alpha helper, so fail on this case like a normal - * driver - */ - if (pMaskPicture && pMaskPicture->componentAlpha && op == PictOpOver) - return FALSE; - - return TRUE; -} - -/** - * Saves off the parameters for ephyrComposite. - */ -static Bool -ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, - PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, - PixmapPtr pDst) -{ - KdScreenPriv(pDst->drawable.pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); - ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); - if (pMask != NULL) - ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK); - - fakexa->op = op; - fakexa->pSrcPicture = pSrcPicture; - fakexa->pMaskPicture = pMaskPicture; - fakexa->pDstPicture = pDstPicture; - fakexa->pSrc = pSrc; - fakexa->pMask = pMask; - fakexa->pDst = pDst; - - TRACE_DRAW(); - - return TRUE; -} - -/** - * Does an fbComposite to complete the requested drawing operation. - */ -static void -ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, - int dstX, int dstY, int w, int h) -{ - KdScreenPriv(pDst->drawable.pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture, - fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY, - w, h); -} - -static void -ephyrDoneComposite(PixmapPtr pDst) -{ - KdScreenPriv(pDst->drawable.pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - if (fakexa->pMask != NULL) - ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK); - ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC); - ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST); -} - -/** - * Does fake acceleration of DownloadFromScren using memcpy. - */ -static Bool -ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, - int dst_pitch) -{ - KdScreenPriv(pSrc->drawable.pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - unsigned char *src; - int src_pitch, cpp; - - if (pSrc->drawable.bitsPerPixel < 8) - return FALSE; - - ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); - - cpp = pSrc->drawable.bitsPerPixel / 8; - src_pitch = exaGetPixmapPitch(pSrc); - src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc); - src += y * src_pitch + x * cpp; - - for (; h > 0; h--) { - memcpy(dst, src, w * cpp); - dst += dst_pitch; - src += src_pitch; - } - - exaMarkSync(pSrc->drawable.pScreen); - - ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC); - - return TRUE; -} - -/** - * Does fake acceleration of UploadToScreen using memcpy. - */ -static Bool -ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, - int src_pitch) -{ - KdScreenPriv(pDst->drawable.pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - unsigned char *dst; - int dst_pitch, cpp; - - if (pDst->drawable.bitsPerPixel < 8) - return FALSE; - - ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); - - cpp = pDst->drawable.bitsPerPixel / 8; - dst_pitch = exaGetPixmapPitch(pDst); - dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst); - dst += y * dst_pitch + x * cpp; - - for (; h > 0; h--) { - memcpy(dst, src, w * cpp); - dst += dst_pitch; - src += src_pitch; - } - - exaMarkSync(pDst->drawable.pScreen); - - ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST); - - return TRUE; -} - -static Bool -ephyrPrepareAccess(PixmapPtr pPix, int index) -{ - /* Make sure we don't somehow end up with a pointer that is in framebuffer - * and hasn't been readied for us. - */ - assert(pPix->devPrivate.ptr != NULL); - - return TRUE; -} - -/** - * In fakexa, we currently only track whether we have synced to the latest - * "accelerated" drawing that has happened or not. It's not used for anything - * yet. - */ -static int -ephyrMarkSync(ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - fakexa->is_synced = FALSE; - - return 0; -} - -/** - * Assumes that we're waiting on the latest marker. When EXA gets smarter and - * starts using markers in a fine-grained way (for example, waiting on drawing - * to required pixmaps to complete, rather than waiting for all drawing to - * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker - * implementation fine-grained as well. - */ -static void -ephyrWaitMarker(ScreenPtr pScreen, int marker) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrFakexaPriv *fakexa = scrpriv->fakexa; - - fakexa->is_synced = TRUE; -} - -/** - * This function initializes EXA to use the fake acceleration implementation - * which just falls through to software. The purpose is to have a reliable, - * correct driver with which to test changes to the EXA core. - */ -Bool -ephyrDrawInit(ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - EphyrScrPriv *scrpriv = screen->driver; - EphyrPriv *priv = screen->card->driver; - EphyrFakexaPriv *fakexa; - Bool success; - - fakexa = xcalloc(1, sizeof(*fakexa)); - if (fakexa == NULL) - return FALSE; - - fakexa->exa = exaDriverAlloc(); - if (fakexa->exa == NULL) { - xfree(fakexa); - return FALSE; - } - - fakexa->exa->memoryBase = (CARD8 *) (priv->base); - fakexa->exa->memorySize = priv->bytes_per_line * ephyrBufferHeight(screen); - fakexa->exa->offScreenBase = priv->bytes_per_line * screen->height; - - /* Since we statically link against EXA, we shouldn't have to be smart about - * versioning. - */ - fakexa->exa->exa_major = 2; - fakexa->exa->exa_minor = 0; - - fakexa->exa->PrepareSolid = ephyrPrepareSolid; - fakexa->exa->Solid = ephyrSolid; - fakexa->exa->DoneSolid = ephyrDoneSolid; - - fakexa->exa->PrepareCopy = ephyrPrepareCopy; - fakexa->exa->Copy = ephyrCopy; - fakexa->exa->DoneCopy = ephyrDoneCopy; - - fakexa->exa->CheckComposite = ephyrCheckComposite; - fakexa->exa->PrepareComposite = ephyrPrepareComposite; - fakexa->exa->Composite = ephyrComposite; - fakexa->exa->DoneComposite = ephyrDoneComposite; - - fakexa->exa->DownloadFromScreen = ephyrDownloadFromScreen; - fakexa->exa->UploadToScreen = ephyrUploadToScreen; - - fakexa->exa->MarkSync = ephyrMarkSync; - fakexa->exa->WaitMarker = ephyrWaitMarker; - - fakexa->exa->PrepareAccess = ephyrPrepareAccess; - - fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN; - fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN; - - fakexa->exa->maxX = 1023; - fakexa->exa->maxY = 1023; - - fakexa->exa->flags = EXA_OFFSCREEN_PIXMAPS; - - success = exaDriverInit(pScreen, fakexa->exa); - if (success) { - ErrorF("Initialized fake EXA acceleration\n"); - scrpriv->fakexa = fakexa; - } else { - ErrorF("Failed to initialize EXA\n"); - xfree(fakexa->exa); - xfree(fakexa); - } - - return success; -} - -void -ephyrDrawEnable(ScreenPtr pScreen) -{ -} - -void -ephyrDrawDisable(ScreenPtr pScreen) -{ -} - -void -ephyrDrawFini(ScreenPtr pScreen) -{ -} - -/** - * exaDDXDriverInit is required by the top-level EXA module, and is used by - * the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since - * we won't be enabling/disabling the FB. - */ -void -exaDDXDriverInit(ScreenPtr pScreen) -{ - ExaScreenPriv(pScreen); - - pExaScr->migration = ExaMigrationSmart; - pExaScr->checkDirtyCorrectness = TRUE; -} +/* + * 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 <eric@anholt.net> + * + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include "ephyr.h" +#include "exa_priv.h" +#include "fbpict.h" + +#define EPHYR_TRACE_DRAW 0 + +#if EPHYR_TRACE_DRAW +#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__); +#else +#define TRACE_DRAW() do { } while (0) +#endif + +/* Use some oddball alignments, to expose issues in alignment handling in EXA. */ +#define EPHYR_OFFSET_ALIGN 24 +#define EPHYR_PITCH_ALIGN 24 + +#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024) +#define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024) + +/** + * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to + * fb functions. + */ +static void +ephyrPreparePipelinedAccess(PixmapPtr pPix, int index) +{ + KdScreenPriv(pPix->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + assert(fakexa->saved_ptrs[index] == NULL); + fakexa->saved_ptrs[index] = pPix->devPrivate.ptr; + + if (pPix->devPrivate.ptr != NULL) + return; + + pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix); +} + +/** + * Restores the original devPrivate.ptr of the pixmap from before we messed with + * it. + */ +static void +ephyrFinishPipelinedAccess(PixmapPtr pPix, int index) +{ + KdScreenPriv(pPix->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + pPix->devPrivate.ptr = fakexa->saved_ptrs[index]; + fakexa->saved_ptrs[index] = NULL; +} + +/** + * Sets up a scratch GC for fbFill, and saves other parameters for the + * ephyrSolid implementation. + */ +static Bool +ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + ChangeGCVal tmpval[3]; + + ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST); + + fakexa->pDst = pPix; + fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen); + + tmpval[0].val = alu; + tmpval[1].val = pm; + tmpval[2].val = fg; + ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask | GCForeground, tmpval); + + ValidateGC(&pPix->drawable, fakexa->pGC); + + TRACE_DRAW(); + + return TRUE; +} + +/** + * Does an fbFill of the rectangle to be drawn. + */ +static void +ephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1); +} + +/** + * Cleans up the scratch GC created in ephyrPrepareSolid. + */ +static void +ephyrDoneSolid(PixmapPtr pPix) +{ + ScreenPtr pScreen = pPix->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + FreeScratchGC(fakexa->pGC); + + ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST); +} + +/** + * Sets up a scratch GC for fbCopyArea, and saves other parameters for the + * ephyrCopy implementation. + */ +static Bool +ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, + Pixel pm) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + ChangeGCVal tmpval[2]; + + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + + fakexa->pSrc = pSrc; + fakexa->pDst = pDst; + fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen); + + tmpval[0].val = alu; + tmpval[1].val = pm; + ChangeGC (NullClient, fakexa->pGC, GCFunction | GCPlaneMask, tmpval); + + ValidateGC(&pDst->drawable, fakexa->pGC); + + TRACE_DRAW(); + + return TRUE; +} + +/** + * Does an fbCopyArea to take care of the requested copy. + */ +static void +ephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC, + srcX, srcY, w, h, dstX, dstY); +} + +/** + * Cleans up the scratch GC created in ephyrPrepareCopy. + */ +static void +ephyrDoneCopy(PixmapPtr pDst) +{ + ScreenPtr pScreen = pDst->drawable.pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + FreeScratchGC (fakexa->pGC); + + ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC); + ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST); +} + +/** + * Reports that we can always accelerate the given operation. This may not be + * desirable from an EXA testing standpoint -- testing the fallback paths would + * be useful, too. + */ +static Bool +ephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + /* Exercise the component alpha helper, so fail on this case like a normal + * driver + */ + if (pMaskPicture && pMaskPicture->componentAlpha && op == PictOpOver) + return FALSE; + + return TRUE; +} + +/** + * Saves off the parameters for ephyrComposite. + */ +static Bool +ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, + PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, + PixmapPtr pDst) +{ + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + if (pMask != NULL) + ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK); + + fakexa->op = op; + fakexa->pSrcPicture = pSrcPicture; + fakexa->pMaskPicture = pMaskPicture; + fakexa->pDstPicture = pDstPicture; + fakexa->pSrc = pSrc; + fakexa->pMask = pMask; + fakexa->pDst = pDst; + + TRACE_DRAW(); + + return TRUE; +} + +/** + * Does an fbComposite to complete the requested drawing operation. + */ +static void +ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int w, int h) +{ + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture, + fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY, + w, h); +} + +static void +ephyrDoneComposite(PixmapPtr pDst) +{ + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + if (fakexa->pMask != NULL) + ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK); + ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC); + ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST); +} + +/** + * Does fake acceleration of DownloadFromScren using memcpy. + */ +static Bool +ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, + int dst_pitch) +{ + KdScreenPriv(pSrc->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + unsigned char *src; + int src_pitch, cpp; + + if (pSrc->drawable.bitsPerPixel < 8) + return FALSE; + + ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC); + + cpp = pSrc->drawable.bitsPerPixel / 8; + src_pitch = exaGetPixmapPitch(pSrc); + src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc); + src += y * src_pitch + x * cpp; + + for (; h > 0; h--) { + memcpy(dst, src, w * cpp); + dst += dst_pitch; + src += src_pitch; + } + + exaMarkSync(pSrc->drawable.pScreen); + + ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC); + + return TRUE; +} + +/** + * Does fake acceleration of UploadToScreen using memcpy. + */ +static Bool +ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, + int src_pitch) +{ + KdScreenPriv(pDst->drawable.pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + unsigned char *dst; + int dst_pitch, cpp; + + if (pDst->drawable.bitsPerPixel < 8) + return FALSE; + + ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST); + + cpp = pDst->drawable.bitsPerPixel / 8; + dst_pitch = exaGetPixmapPitch(pDst); + dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst); + dst += y * dst_pitch + x * cpp; + + for (; h > 0; h--) { + memcpy(dst, src, w * cpp); + dst += dst_pitch; + src += src_pitch; + } + + exaMarkSync(pDst->drawable.pScreen); + + ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST); + + return TRUE; +} + +static Bool +ephyrPrepareAccess(PixmapPtr pPix, int index) +{ + /* Make sure we don't somehow end up with a pointer that is in framebuffer + * and hasn't been readied for us. + */ + assert(pPix->devPrivate.ptr != NULL); + + return TRUE; +} + +/** + * In fakexa, we currently only track whether we have synced to the latest + * "accelerated" drawing that has happened or not. It's not used for anything + * yet. + */ +static int +ephyrMarkSync(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fakexa->is_synced = FALSE; + + return 0; +} + +/** + * Assumes that we're waiting on the latest marker. When EXA gets smarter and + * starts using markers in a fine-grained way (for example, waiting on drawing + * to required pixmaps to complete, rather than waiting for all drawing to + * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker + * implementation fine-grained as well. + */ +static void +ephyrWaitMarker(ScreenPtr pScreen, int marker) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrFakexaPriv *fakexa = scrpriv->fakexa; + + fakexa->is_synced = TRUE; +} + +/** + * This function initializes EXA to use the fake acceleration implementation + * which just falls through to software. The purpose is to have a reliable, + * correct driver with which to test changes to the EXA core. + */ +Bool +ephyrDrawInit(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + EphyrScrPriv *scrpriv = screen->driver; + EphyrPriv *priv = screen->card->driver; + EphyrFakexaPriv *fakexa; + Bool success; + + fakexa = calloc(1, sizeof(*fakexa)); + if (fakexa == NULL) + return FALSE; + + fakexa->exa = exaDriverAlloc(); + if (fakexa->exa == NULL) { + free(fakexa); + return FALSE; + } + + fakexa->exa->memoryBase = (CARD8 *) (priv->base); + fakexa->exa->memorySize = priv->bytes_per_line * ephyrBufferHeight(screen); + fakexa->exa->offScreenBase = priv->bytes_per_line * screen->height; + + /* Since we statically link against EXA, we shouldn't have to be smart about + * versioning. + */ + fakexa->exa->exa_major = 2; + fakexa->exa->exa_minor = 0; + + fakexa->exa->PrepareSolid = ephyrPrepareSolid; + fakexa->exa->Solid = ephyrSolid; + fakexa->exa->DoneSolid = ephyrDoneSolid; + + fakexa->exa->PrepareCopy = ephyrPrepareCopy; + fakexa->exa->Copy = ephyrCopy; + fakexa->exa->DoneCopy = ephyrDoneCopy; + + fakexa->exa->CheckComposite = ephyrCheckComposite; + fakexa->exa->PrepareComposite = ephyrPrepareComposite; + fakexa->exa->Composite = ephyrComposite; + fakexa->exa->DoneComposite = ephyrDoneComposite; + + fakexa->exa->DownloadFromScreen = ephyrDownloadFromScreen; + fakexa->exa->UploadToScreen = ephyrUploadToScreen; + + fakexa->exa->MarkSync = ephyrMarkSync; + fakexa->exa->WaitMarker = ephyrWaitMarker; + + fakexa->exa->PrepareAccess = ephyrPrepareAccess; + + fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN; + fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN; + + fakexa->exa->maxX = 1023; + fakexa->exa->maxY = 1023; + + fakexa->exa->flags = EXA_OFFSCREEN_PIXMAPS; + + success = exaDriverInit(pScreen, fakexa->exa); + if (success) { + ErrorF("Initialized fake EXA acceleration\n"); + scrpriv->fakexa = fakexa; + } else { + ErrorF("Failed to initialize EXA\n"); + free(fakexa->exa); + free(fakexa); + } + + return success; +} + +void +ephyrDrawEnable(ScreenPtr pScreen) +{ +} + +void +ephyrDrawDisable(ScreenPtr pScreen) +{ +} + +void +ephyrDrawFini(ScreenPtr pScreen) +{ +} + +/** + * exaDDXDriverInit is required by the top-level EXA module, and is used by + * the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since + * we won't be enabling/disabling the FB. + */ +void +exaDDXDriverInit(ScreenPtr pScreen) +{ + ExaScreenPriv(pScreen); + + pExaScr->migration = ExaMigrationSmart; + pExaScr->checkDirtyCorrectness = TRUE; +} diff --git a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c index 5f5fd3bff..3d3d18a39 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c @@ -1,1429 +1,1429 @@ -/* - * Xephyr - A kdrive X server thats runs in a host X window. - * Authored by Matthew Allum <mallum@openedhand.com> - * - * Copyright © 2007 OpenedHand Ltd - * - * 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 OpenedHand Ltd not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. OpenedHand Ltd makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL OpenedHand Ltd 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. - * - * This file is heavily copied from hw/xfree86/dri/xf86dri.c - * - * Authors: - * Dodji Seketeli <dodji@openedhand.com> - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif - -#include <string.h> - -#include <X11/X.h> -#include <X11/Xproto.h> -#define _XF86DRI_SERVER_ -#include <X11/dri/xf86dri.h> -#include <X11/dri/xf86driproto.h> -#include "misc.h" -#include "privates.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "servermd.h" -#include "swaprep.h" -#include "ephyrdri.h" -#include "ephyrdriext.h" -#include "hostx.h" -#define _HAVE_XALLOC_DECLS -#include "ephyrlog.h" -#include "protocol-versions.h" - -typedef struct { - int foo; -} EphyrDRIWindowPrivRec; -typedef EphyrDRIWindowPrivRec* EphyrDRIWindowPrivPtr; - -typedef struct { - CreateWindowProcPtr CreateWindow ; - DestroyWindowProcPtr DestroyWindow ; - MoveWindowProcPtr MoveWindow ; - PositionWindowProcPtr PositionWindow ; - ClipNotifyProcPtr ClipNotify ; -} EphyrDRIScreenPrivRec; -typedef EphyrDRIScreenPrivRec* EphyrDRIScreenPrivPtr; - -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 Bool ephyrDRIScreenInit (ScreenPtr a_screen) ; -static Bool ephyrDRICreateWindow (WindowPtr a_win) ; -static Bool ephyrDRIDestroyWindow (WindowPtr a_win) ; -static void ephyrDRIMoveWindow (WindowPtr a_win, - int a_x, int a_y, - WindowPtr a_siblings, - VTKind a_kind); -static Bool ephyrDRIPositionWindow (WindowPtr a_win, - int x, int y) ; -static void ephyrDRIClipNotify (WindowPtr a_win, - int a_x, int a_y) ; - -static Bool EphyrMirrorHostVisuals (ScreenPtr a_screen) ; -static Bool destroyHostPeerWindow (const WindowPtr a_win) ; -static Bool findWindowPairFromLocal (WindowPtr a_local, - EphyrWindowPair **a_pair); - -static unsigned char DRIReqCode = 0; - -static int ephyrDRIWindowKeyIndex; -static DevPrivateKey ephyrDRIWindowKey = &ephyrDRIWindowKeyIndex; -static int ephyrDRIScreenKeyIndex; -static DevPrivateKey ephyrDRIScreenKey = &ephyrDRIScreenKeyIndex; - -#define GET_EPHYR_DRI_WINDOW_PRIV(win) ((EphyrDRIWindowPrivPtr) \ - dixLookupPrivate(&(win)->devPrivates, ephyrDRIWindowKey)) -#define GET_EPHYR_DRI_SCREEN_PRIV(screen) ((EphyrDRIScreenPrivPtr) \ - dixLookupPrivate(&(screen)->devPrivates, ephyrDRIScreenKey)) - - -Bool -ephyrDRIExtensionInit (ScreenPtr a_screen) -{ - Bool is_ok=FALSE ; - ExtensionEntry* extEntry=NULL; - EphyrDRIScreenPrivPtr screen_priv=NULL ; - - EPHYR_LOG ("enter\n") ; - if (!hostx_has_dri ()) { - EPHYR_LOG ("host does not have DRI extension\n") ; - goto out ; - } - EPHYR_LOG ("host X does have DRI extension\n") ; - if (!hostx_has_xshape ()) { - EPHYR_LOG ("host does not have XShape extension\n") ; - goto out ; - } - EPHYR_LOG ("host X does have XShape extension\n") ; - -#ifdef XF86DRI_EVENTS - EventType = CreateNewResourceType (XF86DRIFreeEvents, "DRIEvents"); - if (!EventType) { - EPHYR_LOG_ERROR ("failed to register DRI event resource type\n") ; - goto out ; - } -#endif - - if ((extEntry = AddExtension(XF86DRINAME, - XF86DRINumberEvents, - XF86DRINumberErrors, - ProcXF86DRIDispatch, - SProcXF86DRIDispatch, - NULL, - StandardMinorOpcode))) { - DRIReqCode = (unsigned char)extEntry->base; - DRIErrorBase = extEntry->errorBase; - } else { - EPHYR_LOG_ERROR ("failed to register DRI extension\n") ; - goto out ; - } - screen_priv = xcalloc (1, sizeof (EphyrDRIScreenPrivRec)) ; - if (!screen_priv) { - EPHYR_LOG_ERROR ("failed to allocate screen_priv\n") ; - goto out ; - } - dixSetPrivate(&a_screen->devPrivates, ephyrDRIScreenKey, screen_priv); - - if (!ephyrDRIScreenInit (a_screen)) { - EPHYR_LOG_ERROR ("ephyrDRIScreenInit() failed\n") ; - goto out ; - } - EphyrMirrorHostVisuals (a_screen) ; - is_ok=TRUE ; -out: - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -static Bool -ephyrDRIScreenInit (ScreenPtr a_screen) -{ - Bool is_ok=FALSE ; - EphyrDRIScreenPrivPtr screen_priv=NULL ; - - EPHYR_RETURN_VAL_IF_FAIL (a_screen, FALSE) ; - - screen_priv=GET_EPHYR_DRI_SCREEN_PRIV (a_screen) ; - EPHYR_RETURN_VAL_IF_FAIL (screen_priv, FALSE) ; - - screen_priv->CreateWindow = a_screen->CreateWindow ; - screen_priv->DestroyWindow = a_screen->DestroyWindow ; - screen_priv->MoveWindow = a_screen->MoveWindow ; - screen_priv->PositionWindow = a_screen->PositionWindow ; - screen_priv->ClipNotify = a_screen->ClipNotify ; - - a_screen->CreateWindow = ephyrDRICreateWindow ; - a_screen->DestroyWindow = ephyrDRIDestroyWindow ; - a_screen->MoveWindow = ephyrDRIMoveWindow ; - a_screen->PositionWindow = ephyrDRIPositionWindow ; - a_screen->ClipNotify = ephyrDRIClipNotify ; - - is_ok = TRUE ; - - return is_ok ; -} - -static Bool -ephyrDRICreateWindow (WindowPtr a_win) -{ - Bool is_ok=FALSE ; - ScreenPtr screen=NULL ; - EphyrDRIScreenPrivPtr screen_priv =NULL; - - EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; - screen = a_win->drawable.pScreen ; - EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; - screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; - EPHYR_RETURN_VAL_IF_FAIL (screen_priv - && screen_priv->CreateWindow, - FALSE) ; - - EPHYR_LOG ("enter. win:%p\n", a_win) ; - - screen->CreateWindow = screen_priv->CreateWindow ; - is_ok = (*screen->CreateWindow) (a_win) ; - screen->CreateWindow = ephyrDRICreateWindow ; - - if (is_ok) { - dixSetPrivate(&a_win->devPrivates, ephyrDRIWindowKey, NULL); - } - return is_ok ; -} - -static Bool -ephyrDRIDestroyWindow (WindowPtr a_win) -{ - Bool is_ok=FALSE ; - ScreenPtr screen=NULL ; - EphyrDRIScreenPrivPtr screen_priv =NULL; - - EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; - screen = a_win->drawable.pScreen ; - EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; - screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; - EPHYR_RETURN_VAL_IF_FAIL (screen_priv - && screen_priv->DestroyWindow, - FALSE) ; - - screen->DestroyWindow = screen_priv->DestroyWindow ; - if (screen->DestroyWindow) { - is_ok = (*screen->DestroyWindow) (a_win) ; - } - screen->DestroyWindow = ephyrDRIDestroyWindow ; - - if (is_ok) { - EphyrDRIWindowPrivPtr win_priv=GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; - if (win_priv) { - destroyHostPeerWindow (a_win) ; - xfree (win_priv) ; - dixSetPrivate(&a_win->devPrivates, ephyrDRIWindowKey, NULL); - EPHYR_LOG ("destroyed the remote peer window\n") ; - } - } - return is_ok ; -} - -static void -ephyrDRIMoveWindow (WindowPtr a_win, - int a_x, int a_y, - WindowPtr a_siblings, - VTKind a_kind) -{ - Bool is_ok=FALSE ; - ScreenPtr screen=NULL ; - EphyrDRIScreenPrivPtr screen_priv =NULL; - EphyrDRIWindowPrivPtr win_priv=NULL ; - EphyrWindowPair *pair=NULL ; - EphyrBox geo; - int x=0,y=0;/*coords relative to parent window*/ - - EPHYR_RETURN_IF_FAIL (a_win) ; - - EPHYR_LOG ("enter\n") ; - screen = a_win->drawable.pScreen ; - EPHYR_RETURN_IF_FAIL (screen) ; - screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; - EPHYR_RETURN_IF_FAIL (screen_priv - && screen_priv->MoveWindow) ; - - screen->MoveWindow = screen_priv->MoveWindow ; - if (screen->MoveWindow) { - (*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ; - } - screen->MoveWindow = ephyrDRIMoveWindow ; - - EPHYR_LOG ("window: %p\n", a_win) ; - if (!a_win->parent) { - EPHYR_LOG ("cannot move root window\n") ; - is_ok = TRUE ; - goto out ; - } - win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; - if (!win_priv) { - EPHYR_LOG ("not a DRI peered window\n") ; - is_ok = TRUE ; - goto out ; - } - if (!findWindowPairFromLocal (a_win, &pair) || !pair) { - EPHYR_LOG_ERROR ("failed to get window pair\n") ; - goto out ; - } - /*compute position relative to parent window*/ - x = a_win->drawable.x - a_win->parent->drawable.x ; - y = a_win->drawable.y - a_win->parent->drawable.y ; - /*set the geometry to pass to hostx_set_window_geometry*/ - memset (&geo, 0, sizeof (geo)) ; - geo.x = x ; - geo.y = y ; - geo.width = a_win->drawable.width ; - geo.height = a_win->drawable.height ; - hostx_set_window_geometry (pair->remote, &geo) ; - is_ok = TRUE ; - -out: - EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; - /*do cleanup here*/ -} - -static Bool -ephyrDRIPositionWindow (WindowPtr a_win, - int a_x, int a_y) -{ - Bool is_ok=FALSE ; - ScreenPtr screen=NULL ; - EphyrDRIScreenPrivPtr screen_priv =NULL; - EphyrDRIWindowPrivPtr win_priv=NULL ; - EphyrWindowPair *pair=NULL ; - EphyrBox geo; - - EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; - - EPHYR_LOG ("enter\n") ; - screen = a_win->drawable.pScreen ; - EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; - screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; - EPHYR_RETURN_VAL_IF_FAIL (screen_priv - && screen_priv->PositionWindow, - FALSE) ; - - screen->PositionWindow = screen_priv->PositionWindow ; - if (screen->PositionWindow) { - (*screen->PositionWindow) (a_win, a_x, a_y) ; - } - screen->PositionWindow = ephyrDRIPositionWindow ; - - EPHYR_LOG ("window: %p\n", a_win) ; - win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; - if (!win_priv) { - EPHYR_LOG ("not a DRI peered window\n") ; - is_ok = TRUE ; - goto out ; - } - if (!findWindowPairFromLocal (a_win, &pair) || !pair) { - EPHYR_LOG_ERROR ("failed to get window pair\n") ; - goto out ; - } - /*set the geometry to pass to hostx_set_window_geometry*/ - memset (&geo, 0, sizeof (geo)) ; - geo.x = a_x ; - geo.y = a_y ; - geo.width = a_win->drawable.width ; - geo.height = a_win->drawable.height ; - hostx_set_window_geometry (pair->remote, &geo) ; - is_ok = TRUE ; - -out: - EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; - /*do cleanup here*/ - return is_ok ; -} - -static void -ephyrDRIClipNotify (WindowPtr a_win, - int a_x, int a_y) -{ - Bool is_ok=FALSE ; - ScreenPtr screen=NULL ; - EphyrDRIScreenPrivPtr screen_priv =NULL; - EphyrDRIWindowPrivPtr win_priv=NULL ; - EphyrWindowPair *pair=NULL ; - EphyrRect *rects=NULL; - int i=0 ; - - EPHYR_RETURN_IF_FAIL (a_win) ; - - EPHYR_LOG ("enter\n") ; - screen = a_win->drawable.pScreen ; - EPHYR_RETURN_IF_FAIL (screen) ; - screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; - EPHYR_RETURN_IF_FAIL (screen_priv && screen_priv->ClipNotify) ; - - screen->ClipNotify = screen_priv->ClipNotify ; - if (screen->ClipNotify) { - (*screen->ClipNotify) (a_win, a_x, a_y) ; - } - screen->ClipNotify = ephyrDRIClipNotify ; - - EPHYR_LOG ("window: %p\n", a_win) ; - win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; - if (!win_priv) { - EPHYR_LOG ("not a DRI peered window\n") ; - is_ok = TRUE ; - goto out ; - } - if (!findWindowPairFromLocal (a_win, &pair) || !pair) { - EPHYR_LOG_ERROR ("failed to get window pair\n") ; - goto out ; - } - rects = xcalloc (REGION_NUM_RECTS (&a_win->clipList), - sizeof (EphyrRect)) ; - for (i=0; i < REGION_NUM_RECTS (&a_win->clipList); i++) { - memmove (&rects[i], - ®ION_RECTS (&a_win->clipList)[i], - sizeof (EphyrRect)) ; - rects[i].x1 -= a_win->drawable.x; - rects[i].x2 -= a_win->drawable.x; - rects[i].y1 -= a_win->drawable.y; - rects[i].y2 -= a_win->drawable.y; - } - /* - * push the clipping region of this window - * to the peer window in the host - */ - is_ok = hostx_set_window_bounding_rectangles - (pair->remote, - rects, - REGION_NUM_RECTS (&a_win->clipList)) ; - is_ok = TRUE ; - -out: - xfree (rects) ; - rects = NULL ; - - EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; - /*do cleanup here*/ -} - -/** - * Duplicates a visual of a_screen - * In screen a_screen, for depth a_depth, find a visual which - * bitsPerRGBValue and colormap size equal - * a_bits_per_rgb_values and a_colormap_entries. - * The ID of that duplicated visual is set to a_new_id. - * That duplicated visual is then added to the list of visuals - * of the screen. - */ -static Bool -EphyrDuplicateVisual (unsigned int a_screen, - short a_depth, - short a_class, - short a_bits_per_rgb_values, - short a_colormap_entries, - unsigned int a_red_mask, - unsigned int a_green_mask, - unsigned int a_blue_mask, - unsigned int a_new_id) -{ - Bool is_ok = FALSE, found_visual=FALSE, found_depth=FALSE ; - ScreenPtr screen=NULL ; - VisualRec new_visual, *new_visuals=NULL ; - int i=0 ; - - EPHYR_LOG ("enter\n") ; - if (a_screen > screenInfo.numScreens) { - EPHYR_LOG_ERROR ("bad screen number\n") ; - goto out; - } - memset (&new_visual, 0, sizeof (VisualRec)) ; - - /*get the screen pointed to by a_screen*/ - screen = screenInfo.screens[a_screen] ; - EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; - - /* - * In that screen, first look for an existing visual that has the - * same characteristics as those passed in parameter - * to this function and copy it. - */ - for (i=0; i < screen->numVisuals; i++) { - if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values && - screen->visuals[i].ColormapEntries == a_colormap_entries ) { - /*copy the visual found*/ - memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ; - new_visual.vid = a_new_id ; - new_visual.class = a_class ; - new_visual.redMask = a_red_mask ; - new_visual.greenMask = a_green_mask ; - new_visual.blueMask = a_blue_mask ; - found_visual = TRUE ; - EPHYR_LOG ("found a visual that matches visual id: %d\n", - a_new_id) ; - break; - } - } - if (!found_visual) { - EPHYR_LOG ("did not find any visual matching %d\n", a_new_id) ; - goto out ; - } - /* - * be prepare to extend screen->visuals to add new_visual to it - */ - new_visuals = xcalloc (screen->numVisuals+1, sizeof (VisualRec)) ; - memmove (new_visuals, - screen->visuals, - screen->numVisuals*sizeof (VisualRec)) ; - memmove (&new_visuals[screen->numVisuals], - &new_visual, - sizeof (VisualRec)) ; - /* - * Now, in that same screen, update the screen->allowedDepths member. - * In that array, each element represents the visuals applicable to - * a given depth. So we need to add an entry matching the new visual - * that we are going to add to screen->visuals - */ - for (i=0; i<screen->numDepths; i++) { - VisualID *vids=NULL; - DepthPtr cur_depth=NULL ; - /*find the entry matching a_depth*/ - if (screen->allowedDepths[i].depth != a_depth) - continue ; - cur_depth = &screen->allowedDepths[i]; - /* - * extend the list of visual IDs in that entry, - * so to add a_new_id in there. - */ - vids = xrealloc (cur_depth->vids, - (cur_depth->numVids+1)*sizeof (VisualID)); - if (!vids) { - EPHYR_LOG_ERROR ("failed to realloc numids\n") ; - goto out ; - } - vids[cur_depth->numVids] = a_new_id ; - /* - * Okay now commit our change. - * Do really update screen->allowedDepths[i] - */ - cur_depth->numVids++ ; - cur_depth->vids = vids ; - found_depth=TRUE; - } - if (!found_depth) { - EPHYR_LOG_ERROR ("failed to update screen[%d]->allowedDepth\n", - a_screen) ; - goto out ; - } - /* - * Commit our change to screen->visuals - */ - xfree (screen->visuals) ; - screen->visuals = new_visuals ; - screen->numVisuals++ ; - new_visuals = NULL ; - - is_ok = TRUE ; -out: - xfree (new_visuals) ; - new_visuals = NULL ; - - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -/** - * Duplicates the visuals of the host X server. - * This is necessary to have visuals that have the same - * ID as those of the host X. It is important to have that for - * GLX. - */ -static Bool -EphyrMirrorHostVisuals (ScreenPtr a_screen) -{ - Bool is_ok=FALSE; - EphyrHostVisualInfo *visuals=NULL; - int nb_visuals=0, i=0; - - EPHYR_LOG ("enter\n") ; - if (!hostx_get_visuals_info (&visuals, &nb_visuals)) { - EPHYR_LOG_ERROR ("failed to get host visuals\n") ; - goto out ; - } - for (i=0; i<nb_visuals; i++) { - if (!EphyrDuplicateVisual (a_screen->myNum, - visuals[i].depth, - visuals[i].class, - visuals[i].bits_per_rgb, - visuals[i].colormap_size, - visuals[i].red_mask, - visuals[i].green_mask, - visuals[i].blue_mask, - visuals[i].visualid)) { - EPHYR_LOG_ERROR ("failed to duplicate host visual %d\n", - (int)visuals[i].visualid) ; - } - } - - is_ok = TRUE ; -out: - EPHYR_LOG ("leave\n") ; - return is_ok; -} - - -static int -ProcXF86DRIQueryVersion (register ClientPtr client) -{ - xXF86DRIQueryVersionReply rep; - register int n; - REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); - - EPHYR_LOG ("enter\n") ; - - 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); - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client) -{ - xXF86DRIQueryDirectRenderingCapableReply rep; - Bool isCapable; - register int n; - REQUEST(xXF86DRIQueryDirectRenderingCapableReq); - REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); - - EPHYR_LOG ("enter\n") ; - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if (!ephyrDRIQueryDirectRenderingCapable (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); - EPHYR_LOG ("leave\n") ; - - return (client->noClientException); -} - -static int -ProcXF86DRIOpenConnection (register ClientPtr client) -{ - xXF86DRIOpenConnectionReply rep; - drm_handle_t hSAREA; - char* busIdString; - REQUEST(xXF86DRIOpenConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); - - EPHYR_LOG ("enter\n") ; - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - if (!ephyrDRIOpenConnection(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); - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRIAuthConnection (register ClientPtr client) -{ - xXF86DRIAuthConnectionReply rep; - REQUEST(xXF86DRIAuthConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); - - EPHYR_LOG ("enter\n") ; - 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 (!ephyrDRIAuthConnection (stuff->screen, stuff->magic)) { - ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); - rep.authenticated = 0; - } - WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRICloseConnection (register ClientPtr client) -{ - REQUEST(xXF86DRICloseConnectionReq); - REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); - EPHYR_LOG ("enter\n") ; - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - /* - DRICloseConnection( screenInfo.screens[stuff->screen]); - */ - - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRIGetClientDriverName (register ClientPtr client) -{ - xXF86DRIGetClientDriverNameReply rep; - char* clientDriverName; - REQUEST(xXF86DRIGetClientDriverNameReq); - REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); - - EPHYR_LOG ("enter\n") ; - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - ephyrDRIGetClientDriverName (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); - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRICreateContext (register ClientPtr client) -{ - xXF86DRICreateContextReply rep; - ScreenPtr pScreen; - VisualPtr visual; - int i=0; - unsigned long context_id=0; - REQUEST(xXF86DRICreateContextReq); - REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); - - EPHYR_LOG ("enter\n") ; - 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]; - visual = pScreen->visuals; - - /* Find the requested X visual */ - for (i = 0; i < pScreen->numVisuals; i++, visual++) - if (visual->vid == stuff->visual) - break; - if (i == pScreen->numVisuals) { - /* No visual found */ - return BadValue; - } - - context_id = stuff->context ; - if (!ephyrDRICreateContext (stuff->screen, - stuff->visual, - &context_id, - (drm_context_t *)&rep.hHWContext)) { - return BadValue; - } - - WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRIDestroyContext (register ClientPtr client) -{ - REQUEST(xXF86DRIDestroyContextReq); - REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); - EPHYR_LOG ("enter\n") ; - - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - if (!ephyrDRIDestroyContext (stuff->screen, stuff->context)) { - return BadValue; - } - - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static Bool -getWindowVisual (const WindowPtr a_win, - VisualPtr *a_visual) -{ - int i=0, visual_id=0 ; - EPHYR_RETURN_VAL_IF_FAIL (a_win - && a_win->drawable.pScreen - && a_win->drawable.pScreen->visuals, - FALSE) ; - - visual_id = wVisual (a_win) ; - for (i=0; i < a_win->drawable.pScreen->numVisuals; i++) { - if (a_win->drawable.pScreen->visuals[i].vid == visual_id) { - *a_visual = &a_win->drawable.pScreen->visuals[i] ; - return TRUE ; - } - } - return FALSE ; -} - - -#define NUM_WINDOW_PAIRS 256 -static EphyrWindowPair window_pairs[NUM_WINDOW_PAIRS] ; - -static Bool -appendWindowPairToList (WindowPtr a_local, - int a_remote) -{ - int i=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_local, FALSE) ; - - EPHYR_LOG ("(local,remote):(%p, %d)\n", a_local, a_remote) ; - - for (i=0; i < NUM_WINDOW_PAIRS; i++) { - if (window_pairs[i].local == NULL) { - window_pairs[i].local = a_local ; - window_pairs[i].remote = a_remote ; - return TRUE ; - } - } - return FALSE ; -} - -static Bool -findWindowPairFromLocal (WindowPtr a_local, - EphyrWindowPair **a_pair) -{ - int i=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_pair && a_local, FALSE) ; - - for (i=0; i < NUM_WINDOW_PAIRS; i++) { - if (window_pairs[i].local == a_local) { - *a_pair = &window_pairs[i] ; - EPHYR_LOG ("found (%p, %d)\n", - (*a_pair)->local, - (*a_pair)->remote) ; - return TRUE ; - } - } - return FALSE ; -} - -Bool -findWindowPairFromRemote (int a_remote, - EphyrWindowPair **a_pair) -{ - int i=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_pair, FALSE) ; - - for (i=0; i < NUM_WINDOW_PAIRS; i++) { - if (window_pairs[i].remote == a_remote) { - *a_pair = &window_pairs[i] ; - EPHYR_LOG ("found (%p, %d)\n", - (*a_pair)->local, - (*a_pair)->remote) ; - return TRUE ; - } - } - return FALSE ; -} - -static Bool -createHostPeerWindow (const WindowPtr a_win, - int *a_peer_win) -{ - Bool is_ok=FALSE ; - VisualPtr visual=NULL; - EphyrBox geo ; - - EPHYR_RETURN_VAL_IF_FAIL (a_win && a_peer_win, FALSE) ; - EPHYR_RETURN_VAL_IF_FAIL (a_win->drawable.pScreen, - FALSE) ; - - EPHYR_LOG ("enter. a_win '%p'\n", a_win) ; - if (!getWindowVisual (a_win, &visual)) { - EPHYR_LOG_ERROR ("failed to get window visual\n") ; - goto out ; - } - if (!visual) { - EPHYR_LOG_ERROR ("failed to create visual\n") ; - goto out ; - } - memset (&geo, 0, sizeof (geo)) ; - geo.x = a_win->drawable.x ; - geo.y = a_win->drawable.y ; - geo.width = a_win->drawable.width ; - geo.height = a_win->drawable.height ; - if (!hostx_create_window (a_win->drawable.pScreen->myNum, - &geo, visual->vid, a_peer_win)) { - EPHYR_LOG_ERROR ("failed to create host peer window\n") ; - goto out ; - } - if (!appendWindowPairToList (a_win, *a_peer_win)) { - EPHYR_LOG_ERROR ("failed to append window to pair list\n") ; - goto out ; - } - is_ok = TRUE ; -out: - EPHYR_LOG ("leave:remote win%d\n", *a_peer_win) ; - return is_ok ; -} - -static Bool -destroyHostPeerWindow (const WindowPtr a_win) -{ - Bool is_ok = FALSE ; - EphyrWindowPair *pair=NULL ; - EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; - - EPHYR_LOG ("enter\n") ; - - if (!findWindowPairFromLocal (a_win, &pair) || !pair) { - EPHYR_LOG_ERROR ("failed to find peer to local window\n") ; - goto out; - } - hostx_destroy_window (pair->remote) ; - is_ok = TRUE ; - -out: - EPHYR_LOG ("leave\n") ; - return is_ok; -} - -static int -ProcXF86DRICreateDrawable (ClientPtr client) -{ - xXF86DRICreateDrawableReply rep; - DrawablePtr drawable=NULL; - WindowPtr window=NULL ; - EphyrWindowPair *pair=NULL ; - EphyrDRIWindowPrivPtr win_priv=NULL; - int rc=0, remote_win=0; - REQUEST(xXF86DRICreateDrawableReq); - REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); - - EPHYR_LOG ("enter\n") ; - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rc = dixLookupDrawable (&drawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - if (drawable->type != DRAWABLE_WINDOW) { - EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ; - return BadImplementation ; - } - EPHYR_LOG ("lookedup drawable %p\n", drawable) ; - window = (WindowPtr)drawable; - if (findWindowPairFromLocal (window, &pair) && pair) { - remote_win = pair->remote ; - EPHYR_LOG ("found window '%p' paire with remote '%d'\n", - window, remote_win) ; - } else if (!createHostPeerWindow (window, &remote_win)) { - EPHYR_LOG_ERROR ("failed to create host peer window\n") ; - return BadAlloc ; - } - - if (!ephyrDRICreateDrawable (stuff->screen, - remote_win, - (drm_drawable_t *)&rep.hHWDrawable)) { - EPHYR_LOG_ERROR ("failed to create dri drawable\n") ; - return BadValue; - } - - win_priv = GET_EPHYR_DRI_WINDOW_PRIV (window) ; - if (!win_priv) { - win_priv = xcalloc (1, sizeof (EphyrDRIWindowPrivRec)) ; - if (!win_priv) { - EPHYR_LOG_ERROR ("failed to allocate window private\n") ; - return BadAlloc ; - } - dixSetPrivate(&window->devPrivates, ephyrDRIWindowKey, win_priv); - EPHYR_LOG ("paired window '%p' with remote '%d'\n", - window, remote_win) ; - } - - WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRIDestroyDrawable (register ClientPtr client) -{ - DrawablePtr drawable=NULL; - WindowPtr window=NULL; - EphyrWindowPair *pair=NULL; - int rc=0; - REQUEST(xXF86DRIDestroyDrawableReq); - REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); - - EPHYR_LOG ("enter\n") ; - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rc = dixLookupDrawable(&drawable, - stuff->drawable, - client, - 0, - DixReadAccess); - if (rc != Success) - return rc; - if (drawable->type != DRAWABLE_WINDOW) { - EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ; - return BadImplementation ; - } - window = (WindowPtr)drawable; - if (!findWindowPairFromLocal (window, &pair) && pair) { - EPHYR_LOG_ERROR ("failed to find pair window\n") ; - return BadImplementation; - } - if (!ephyrDRIDestroyDrawable(stuff->screen, - pair->remote/*drawable in host x*/)) { - EPHYR_LOG_ERROR ("failed to destroy dri drawable\n") ; - return BadImplementation; - } - pair->local=NULL ; - pair->remote=0; - - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRIGetDrawableInfo (register ClientPtr client) -{ - xXF86DRIGetDrawableInfoReply rep; - DrawablePtr drawable; - WindowPtr window=NULL; - EphyrWindowPair *pair=NULL; - int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0, i=0; - drm_clip_rect_t *clipRects=NULL; - drm_clip_rect_t *backClipRects=NULL; - REQUEST(xXF86DRIGetDrawableInfoReq); - REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); - - EPHYR_LOG ("enter\n") ; - memset (&rep, 0, sizeof (rep)) ; - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success || !drawable) { - EPHYR_LOG_ERROR ("could not get drawable\n") ; - return rc; - } - - if (drawable->type != DRAWABLE_WINDOW) { - EPHYR_LOG_ERROR ("non windows type drawables are not yes supported\n") ; - return BadImplementation ; - } - window = (WindowPtr)drawable ; - memset (&pair, 0, sizeof (pair)) ; - if (!findWindowPairFromLocal (window, &pair) || !pair) { - EPHYR_LOG_ERROR ("failed to find remote peer drawable\n") ; - return BadMatch ; - } - EPHYR_LOG ("clip list of xephyr gl drawable:\n") ; - for (i=0; i < REGION_NUM_RECTS (&window->clipList); i++) { - EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", - REGION_RECTS (&window->clipList)[i].x1, - REGION_RECTS (&window->clipList)[i].y1, - REGION_RECTS (&window->clipList)[i].x2, - REGION_RECTS (&window->clipList)[i].y2) ; - } - - if (!ephyrDRIGetDrawableInfo (stuff->screen, - pair->remote/*the drawable in hostx*/, - (unsigned int*)&rep.drawableTableIndex, - (unsigned int*)&rep.drawableTableStamp, - (int*)&X, - (int*)&Y, - (int*)&W, - (int*)&H, - (int*)&rep.numClipRects, - &clipRects, - &backX, - &backY, - (int*)&rep.numBackClipRects, - &backClipRects)) { - return BadValue; - } - EPHYR_LOG ("num clip rects:%d, num back clip rects:%d\n", - (int)rep.numClipRects, (int)rep.numBackClipRects) ; - - 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.numClipRects) { - if (clipRects) { - ScreenPtr pScreen = screenInfo.screens[stuff->screen]; - int i=0; - EPHYR_LOG ("clip list of host gl drawable:\n") ; - for (i = 0; i < rep.numClipRects; i++) { - clipRects[i].x1 = max (clipRects[i].x1, 0); - clipRects[i].y1 = max (clipRects[i].y1, 0); - clipRects[i].x2 = min (clipRects[i].x2, - pScreen->width + clipRects[i].x1) ; - clipRects[i].y2 = min (clipRects[i].y2, - pScreen->width + clipRects[i].y1) ; - - EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", - clipRects[i].x1, clipRects[i].y1, - clipRects[i].x2, clipRects[i].y2) ; - } - } else { - rep.numClipRects = 0; - } - } else { - EPHYR_LOG ("got zero host gl drawable clipping rects\n") ; - } - rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; - backClipRects = clipRects ; - rep.numBackClipRects = rep.numClipRects ; - if (rep.numBackClipRects) - rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; - EPHYR_LOG ("num host clip rects:%d\n", (int)rep.numClipRects) ; - EPHYR_LOG ("num host back clip rects:%d\n", (int)rep.numBackClipRects) ; - - 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 *)clipRects); - } - - if (rep.numBackClipRects) { - WriteToClient(client, - sizeof(drm_clip_rect_t) * rep.numBackClipRects, - (char *)backClipRects); - } - xfree(clipRects); - clipRects = NULL ; - - EPHYR_LOG ("leave\n") ; - - return (client->noClientException); -} - -static int -ProcXF86DRIGetDeviceInfo (register ClientPtr client) -{ - xXF86DRIGetDeviceInfoReply rep; - drm_handle_t hFrameBuffer; - void *pDevPrivate; - REQUEST(xXF86DRIGetDeviceInfoReq); - REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); - - EPHYR_LOG ("enter\n") ; - if (stuff->screen >= screenInfo.numScreens) { - client->errorValue = stuff->screen; - return BadValue; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - if (!ephyrDRIGetDeviceInfo (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); - } - EPHYR_LOG ("leave\n") ; - return (client->noClientException); -} - -static int -ProcXF86DRIDispatch (register ClientPtr client) -{ - REQUEST(xReq); - EPHYR_LOG ("enter\n") ; - - switch (stuff->data) - { - case X_XF86DRIQueryVersion: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIQueryVersion(client); - } - case X_XF86DRIQueryDirectRenderingCapable: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIQueryDirectRenderingCapable(client); - } - } - - if (!LocalClient(client)) - return DRIErrorBase + XF86DRIClientNotLocal; - - switch (stuff->data) - { - case X_XF86DRIOpenConnection: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIOpenConnection(client); - } - case X_XF86DRICloseConnection: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRICloseConnection(client); - } - case X_XF86DRIGetClientDriverName: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIGetClientDriverName(client); - } - case X_XF86DRICreateContext: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRICreateContext(client); - } - case X_XF86DRIDestroyContext: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIDestroyContext(client); - } - case X_XF86DRICreateDrawable: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRICreateDrawable(client); - } - case X_XF86DRIDestroyDrawable: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIDestroyDrawable(client); - } - case X_XF86DRIGetDrawableInfo: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIGetDrawableInfo(client); - } - case X_XF86DRIGetDeviceInfo: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIGetDeviceInfo(client); - } - case X_XF86DRIAuthConnection: { - EPHYR_LOG ("leave\n") ; - return ProcXF86DRIAuthConnection(client); - } - /* {Open,Close}FullScreen are deprecated now */ - default: { - EPHYR_LOG ("leave\n") ; - 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); - - EPHYR_LOG ("enter\n") ; - /* - * Only local clients are allowed DRI access, but remote clients still need - * these requests to find out cleanly. - */ - switch (stuff->data) - { - case X_XF86DRIQueryVersion: { - EPHYR_LOG ("leave\n") ; - return SProcXF86DRIQueryVersion(client); - } - case X_XF86DRIQueryDirectRenderingCapable: { - EPHYR_LOG ("leave\n") ; - return SProcXF86DRIQueryDirectRenderingCapable(client); - } - default: { - EPHYR_LOG ("leave\n") ; - return DRIErrorBase + XF86DRIClientNotLocal; - } - } -} +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum <mallum@openedhand.com> + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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. + * + * This file is heavily copied from hw/xfree86/dri/xf86dri.c + * + * Authors: + * Dodji Seketeli <dodji@openedhand.com> + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include <string.h> + +#include <X11/X.h> +#include <X11/Xproto.h> +#define _XF86DRI_SERVER_ +#include <X11/dri/xf86dri.h> +#include <X11/dri/xf86driproto.h> +#include "misc.h" +#include "privates.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "swaprep.h" +#include "ephyrdri.h" +#include "ephyrdriext.h" +#include "hostx.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include "protocol-versions.h" + +typedef struct { + int foo; +} EphyrDRIWindowPrivRec; +typedef EphyrDRIWindowPrivRec* EphyrDRIWindowPrivPtr; + +typedef struct { + CreateWindowProcPtr CreateWindow ; + DestroyWindowProcPtr DestroyWindow ; + MoveWindowProcPtr MoveWindow ; + PositionWindowProcPtr PositionWindow ; + ClipNotifyProcPtr ClipNotify ; +} EphyrDRIScreenPrivRec; +typedef EphyrDRIScreenPrivRec* EphyrDRIScreenPrivPtr; + +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 Bool ephyrDRIScreenInit (ScreenPtr a_screen) ; +static Bool ephyrDRICreateWindow (WindowPtr a_win) ; +static Bool ephyrDRIDestroyWindow (WindowPtr a_win) ; +static void ephyrDRIMoveWindow (WindowPtr a_win, + int a_x, int a_y, + WindowPtr a_siblings, + VTKind a_kind); +static Bool ephyrDRIPositionWindow (WindowPtr a_win, + int x, int y) ; +static void ephyrDRIClipNotify (WindowPtr a_win, + int a_x, int a_y) ; + +static Bool EphyrMirrorHostVisuals (ScreenPtr a_screen) ; +static Bool destroyHostPeerWindow (const WindowPtr a_win) ; +static Bool findWindowPairFromLocal (WindowPtr a_local, + EphyrWindowPair **a_pair); + +static unsigned char DRIReqCode = 0; + +static int ephyrDRIWindowKeyIndex; +static DevPrivateKey ephyrDRIWindowKey = &ephyrDRIWindowKeyIndex; +static int ephyrDRIScreenKeyIndex; +static DevPrivateKey ephyrDRIScreenKey = &ephyrDRIScreenKeyIndex; + +#define GET_EPHYR_DRI_WINDOW_PRIV(win) ((EphyrDRIWindowPrivPtr) \ + dixLookupPrivate(&(win)->devPrivates, ephyrDRIWindowKey)) +#define GET_EPHYR_DRI_SCREEN_PRIV(screen) ((EphyrDRIScreenPrivPtr) \ + dixLookupPrivate(&(screen)->devPrivates, ephyrDRIScreenKey)) + + +Bool +ephyrDRIExtensionInit (ScreenPtr a_screen) +{ + Bool is_ok=FALSE ; + ExtensionEntry* extEntry=NULL; + EphyrDRIScreenPrivPtr screen_priv=NULL ; + + EPHYR_LOG ("enter\n") ; + if (!hostx_has_dri ()) { + EPHYR_LOG ("host does not have DRI extension\n") ; + goto out ; + } + EPHYR_LOG ("host X does have DRI extension\n") ; + if (!hostx_has_xshape ()) { + EPHYR_LOG ("host does not have XShape extension\n") ; + goto out ; + } + EPHYR_LOG ("host X does have XShape extension\n") ; + +#ifdef XF86DRI_EVENTS + EventType = CreateNewResourceType (XF86DRIFreeEvents, "DRIEvents"); + if (!EventType) { + EPHYR_LOG_ERROR ("failed to register DRI event resource type\n") ; + goto out ; + } +#endif + + if ((extEntry = AddExtension(XF86DRINAME, + XF86DRINumberEvents, + XF86DRINumberErrors, + ProcXF86DRIDispatch, + SProcXF86DRIDispatch, + NULL, + StandardMinorOpcode))) { + DRIReqCode = (unsigned char)extEntry->base; + DRIErrorBase = extEntry->errorBase; + } else { + EPHYR_LOG_ERROR ("failed to register DRI extension\n") ; + goto out ; + } + screen_priv = calloc(1, sizeof (EphyrDRIScreenPrivRec)) ; + if (!screen_priv) { + EPHYR_LOG_ERROR ("failed to allocate screen_priv\n") ; + goto out ; + } + dixSetPrivate(&a_screen->devPrivates, ephyrDRIScreenKey, screen_priv); + + if (!ephyrDRIScreenInit (a_screen)) { + EPHYR_LOG_ERROR ("ephyrDRIScreenInit() failed\n") ; + goto out ; + } + EphyrMirrorHostVisuals (a_screen) ; + is_ok=TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrDRIScreenInit (ScreenPtr a_screen) +{ + Bool is_ok=FALSE ; + EphyrDRIScreenPrivPtr screen_priv=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_screen, FALSE) ; + + screen_priv=GET_EPHYR_DRI_SCREEN_PRIV (a_screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv, FALSE) ; + + screen_priv->CreateWindow = a_screen->CreateWindow ; + screen_priv->DestroyWindow = a_screen->DestroyWindow ; + screen_priv->MoveWindow = a_screen->MoveWindow ; + screen_priv->PositionWindow = a_screen->PositionWindow ; + screen_priv->ClipNotify = a_screen->ClipNotify ; + + a_screen->CreateWindow = ephyrDRICreateWindow ; + a_screen->DestroyWindow = ephyrDRIDestroyWindow ; + a_screen->MoveWindow = ephyrDRIMoveWindow ; + a_screen->PositionWindow = ephyrDRIPositionWindow ; + a_screen->ClipNotify = ephyrDRIClipNotify ; + + is_ok = TRUE ; + + return is_ok ; +} + +static Bool +ephyrDRICreateWindow (WindowPtr a_win) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->CreateWindow, + FALSE) ; + + EPHYR_LOG ("enter. win:%p\n", a_win) ; + + screen->CreateWindow = screen_priv->CreateWindow ; + is_ok = (*screen->CreateWindow) (a_win) ; + screen->CreateWindow = ephyrDRICreateWindow ; + + if (is_ok) { + dixSetPrivate(&a_win->devPrivates, ephyrDRIWindowKey, NULL); + } + return is_ok ; +} + +static Bool +ephyrDRIDestroyWindow (WindowPtr a_win) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->DestroyWindow, + FALSE) ; + + screen->DestroyWindow = screen_priv->DestroyWindow ; + if (screen->DestroyWindow) { + is_ok = (*screen->DestroyWindow) (a_win) ; + } + screen->DestroyWindow = ephyrDRIDestroyWindow ; + + if (is_ok) { + EphyrDRIWindowPrivPtr win_priv=GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (win_priv) { + destroyHostPeerWindow (a_win) ; + free(win_priv) ; + dixSetPrivate(&a_win->devPrivates, ephyrDRIWindowKey, NULL); + EPHYR_LOG ("destroyed the remote peer window\n") ; + } + } + return is_ok ; +} + +static void +ephyrDRIMoveWindow (WindowPtr a_win, + int a_x, int a_y, + WindowPtr a_siblings, + VTKind a_kind) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrBox geo; + int x=0,y=0;/*coords relative to parent window*/ + + EPHYR_RETURN_IF_FAIL (a_win) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_IF_FAIL (screen) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_IF_FAIL (screen_priv + && screen_priv->MoveWindow) ; + + screen->MoveWindow = screen_priv->MoveWindow ; + if (screen->MoveWindow) { + (*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ; + } + screen->MoveWindow = ephyrDRIMoveWindow ; + + EPHYR_LOG ("window: %p\n", a_win) ; + if (!a_win->parent) { + EPHYR_LOG ("cannot move root window\n") ; + is_ok = TRUE ; + goto out ; + } + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + /*compute position relative to parent window*/ + x = a_win->drawable.x - a_win->parent->drawable.x ; + y = a_win->drawable.y - a_win->parent->drawable.y ; + /*set the geometry to pass to hostx_set_window_geometry*/ + memset (&geo, 0, sizeof (geo)) ; + geo.x = x ; + geo.y = y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + hostx_set_window_geometry (pair->remote, &geo) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ +} + +static Bool +ephyrDRIPositionWindow (WindowPtr a_win, + int a_x, int a_y) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrBox geo; + + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_VAL_IF_FAIL (screen_priv + && screen_priv->PositionWindow, + FALSE) ; + + screen->PositionWindow = screen_priv->PositionWindow ; + if (screen->PositionWindow) { + (*screen->PositionWindow) (a_win, a_x, a_y) ; + } + screen->PositionWindow = ephyrDRIPositionWindow ; + + EPHYR_LOG ("window: %p\n", a_win) ; + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + /*set the geometry to pass to hostx_set_window_geometry*/ + memset (&geo, 0, sizeof (geo)) ; + geo.x = a_x ; + geo.y = a_y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + hostx_set_window_geometry (pair->remote, &geo) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ + return is_ok ; +} + +static void +ephyrDRIClipNotify (WindowPtr a_win, + int a_x, int a_y) +{ + Bool is_ok=FALSE ; + ScreenPtr screen=NULL ; + EphyrDRIScreenPrivPtr screen_priv =NULL; + EphyrDRIWindowPrivPtr win_priv=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrRect *rects=NULL; + int i=0 ; + + EPHYR_RETURN_IF_FAIL (a_win) ; + + EPHYR_LOG ("enter\n") ; + screen = a_win->drawable.pScreen ; + EPHYR_RETURN_IF_FAIL (screen) ; + screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ; + EPHYR_RETURN_IF_FAIL (screen_priv && screen_priv->ClipNotify) ; + + screen->ClipNotify = screen_priv->ClipNotify ; + if (screen->ClipNotify) { + (*screen->ClipNotify) (a_win, a_x, a_y) ; + } + screen->ClipNotify = ephyrDRIClipNotify ; + + EPHYR_LOG ("window: %p\n", a_win) ; + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ; + if (!win_priv) { + EPHYR_LOG ("not a DRI peered window\n") ; + is_ok = TRUE ; + goto out ; + } + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to get window pair\n") ; + goto out ; + } + rects = calloc(REGION_NUM_RECTS (&a_win->clipList), + sizeof (EphyrRect)) ; + for (i=0; i < REGION_NUM_RECTS (&a_win->clipList); i++) { + memmove (&rects[i], + ®ION_RECTS (&a_win->clipList)[i], + sizeof (EphyrRect)) ; + rects[i].x1 -= a_win->drawable.x; + rects[i].x2 -= a_win->drawable.x; + rects[i].y1 -= a_win->drawable.y; + rects[i].y2 -= a_win->drawable.y; + } + /* + * push the clipping region of this window + * to the peer window in the host + */ + is_ok = hostx_set_window_bounding_rectangles + (pair->remote, + rects, + REGION_NUM_RECTS (&a_win->clipList)) ; + is_ok = TRUE ; + +out: + free(rects) ; + rects = NULL ; + + EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ; + /*do cleanup here*/ +} + +/** + * Duplicates a visual of a_screen + * In screen a_screen, for depth a_depth, find a visual which + * bitsPerRGBValue and colormap size equal + * a_bits_per_rgb_values and a_colormap_entries. + * The ID of that duplicated visual is set to a_new_id. + * That duplicated visual is then added to the list of visuals + * of the screen. + */ +static Bool +EphyrDuplicateVisual (unsigned int a_screen, + short a_depth, + short a_class, + short a_bits_per_rgb_values, + short a_colormap_entries, + unsigned int a_red_mask, + unsigned int a_green_mask, + unsigned int a_blue_mask, + unsigned int a_new_id) +{ + Bool is_ok = FALSE, found_visual=FALSE, found_depth=FALSE ; + ScreenPtr screen=NULL ; + VisualRec new_visual, *new_visuals=NULL ; + int i=0 ; + + EPHYR_LOG ("enter\n") ; + if (a_screen > screenInfo.numScreens) { + EPHYR_LOG_ERROR ("bad screen number\n") ; + goto out; + } + memset (&new_visual, 0, sizeof (VisualRec)) ; + + /*get the screen pointed to by a_screen*/ + screen = screenInfo.screens[a_screen] ; + EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ; + + /* + * In that screen, first look for an existing visual that has the + * same characteristics as those passed in parameter + * to this function and copy it. + */ + for (i=0; i < screen->numVisuals; i++) { + if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values && + screen->visuals[i].ColormapEntries == a_colormap_entries ) { + /*copy the visual found*/ + memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ; + new_visual.vid = a_new_id ; + new_visual.class = a_class ; + new_visual.redMask = a_red_mask ; + new_visual.greenMask = a_green_mask ; + new_visual.blueMask = a_blue_mask ; + found_visual = TRUE ; + EPHYR_LOG ("found a visual that matches visual id: %d\n", + a_new_id) ; + break; + } + } + if (!found_visual) { + EPHYR_LOG ("did not find any visual matching %d\n", a_new_id) ; + goto out ; + } + /* + * be prepare to extend screen->visuals to add new_visual to it + */ + new_visuals = calloc(screen->numVisuals+1, sizeof (VisualRec)) ; + memmove (new_visuals, + screen->visuals, + screen->numVisuals*sizeof (VisualRec)) ; + memmove (&new_visuals[screen->numVisuals], + &new_visual, + sizeof (VisualRec)) ; + /* + * Now, in that same screen, update the screen->allowedDepths member. + * In that array, each element represents the visuals applicable to + * a given depth. So we need to add an entry matching the new visual + * that we are going to add to screen->visuals + */ + for (i=0; i<screen->numDepths; i++) { + VisualID *vids=NULL; + DepthPtr cur_depth=NULL ; + /*find the entry matching a_depth*/ + if (screen->allowedDepths[i].depth != a_depth) + continue ; + cur_depth = &screen->allowedDepths[i]; + /* + * extend the list of visual IDs in that entry, + * so to add a_new_id in there. + */ + vids = realloc(cur_depth->vids, + (cur_depth->numVids+1)*sizeof (VisualID)); + if (!vids) { + EPHYR_LOG_ERROR ("failed to realloc numids\n") ; + goto out ; + } + vids[cur_depth->numVids] = a_new_id ; + /* + * Okay now commit our change. + * Do really update screen->allowedDepths[i] + */ + cur_depth->numVids++ ; + cur_depth->vids = vids ; + found_depth=TRUE; + } + if (!found_depth) { + EPHYR_LOG_ERROR ("failed to update screen[%d]->allowedDepth\n", + a_screen) ; + goto out ; + } + /* + * Commit our change to screen->visuals + */ + free(screen->visuals) ; + screen->visuals = new_visuals ; + screen->numVisuals++ ; + new_visuals = NULL ; + + is_ok = TRUE ; +out: + free(new_visuals) ; + new_visuals = NULL ; + + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +/** + * Duplicates the visuals of the host X server. + * This is necessary to have visuals that have the same + * ID as those of the host X. It is important to have that for + * GLX. + */ +static Bool +EphyrMirrorHostVisuals (ScreenPtr a_screen) +{ + Bool is_ok=FALSE; + EphyrHostVisualInfo *visuals=NULL; + int nb_visuals=0, i=0; + + EPHYR_LOG ("enter\n") ; + if (!hostx_get_visuals_info (&visuals, &nb_visuals)) { + EPHYR_LOG_ERROR ("failed to get host visuals\n") ; + goto out ; + } + for (i=0; i<nb_visuals; i++) { + if (!EphyrDuplicateVisual (a_screen->myNum, + visuals[i].depth, + visuals[i].class, + visuals[i].bits_per_rgb, + visuals[i].colormap_size, + visuals[i].red_mask, + visuals[i].green_mask, + visuals[i].blue_mask, + visuals[i].visualid)) { + EPHYR_LOG_ERROR ("failed to duplicate host visual %d\n", + (int)visuals[i].visualid) ; + } + } + + is_ok = TRUE ; +out: + EPHYR_LOG ("leave\n") ; + return is_ok; +} + + +static int +ProcXF86DRIQueryVersion (register ClientPtr client) +{ + xXF86DRIQueryVersionReply rep; + register int n; + REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); + + EPHYR_LOG ("enter\n") ; + + 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); + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client) +{ + xXF86DRIQueryDirectRenderingCapableReply rep; + Bool isCapable; + register int n; + REQUEST(xXF86DRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); + + EPHYR_LOG ("enter\n") ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!ephyrDRIQueryDirectRenderingCapable (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); + EPHYR_LOG ("leave\n") ; + + return Success; +} + +static int +ProcXF86DRIOpenConnection (register ClientPtr client) +{ + xXF86DRIOpenConnectionReply rep; + drm_handle_t hSAREA; + char* busIdString; + REQUEST(xXF86DRIOpenConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); + + EPHYR_LOG ("enter\n") ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!ephyrDRIOpenConnection(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); + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRIAuthConnection (register ClientPtr client) +{ + xXF86DRIAuthConnectionReply rep; + REQUEST(xXF86DRIAuthConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); + + EPHYR_LOG ("enter\n") ; + 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 (!ephyrDRIAuthConnection (stuff->screen, stuff->magic)) { + ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); + rep.authenticated = 0; + } + WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRICloseConnection (register ClientPtr client) +{ + REQUEST(xXF86DRICloseConnectionReq); + REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); + EPHYR_LOG ("enter\n") ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + /* + DRICloseConnection( screenInfo.screens[stuff->screen]); + */ + + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRIGetClientDriverName (register ClientPtr client) +{ + xXF86DRIGetClientDriverNameReply rep; + char* clientDriverName; + REQUEST(xXF86DRIGetClientDriverNameReq); + REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); + + EPHYR_LOG ("enter\n") ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + ephyrDRIGetClientDriverName (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); + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRICreateContext (register ClientPtr client) +{ + xXF86DRICreateContextReply rep; + ScreenPtr pScreen; + VisualPtr visual; + int i=0; + unsigned long context_id=0; + REQUEST(xXF86DRICreateContextReq); + REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); + + EPHYR_LOG ("enter\n") ; + 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]; + visual = pScreen->visuals; + + /* Find the requested X visual */ + for (i = 0; i < pScreen->numVisuals; i++, visual++) + if (visual->vid == stuff->visual) + break; + if (i == pScreen->numVisuals) { + /* No visual found */ + return BadValue; + } + + context_id = stuff->context ; + if (!ephyrDRICreateContext (stuff->screen, + stuff->visual, + &context_id, + (drm_context_t *)&rep.hHWContext)) { + return BadValue; + } + + WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRIDestroyContext (register ClientPtr client) +{ + REQUEST(xXF86DRIDestroyContextReq); + REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); + EPHYR_LOG ("enter\n") ; + + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + if (!ephyrDRIDestroyContext (stuff->screen, stuff->context)) { + return BadValue; + } + + EPHYR_LOG ("leave\n") ; + return Success; +} + +static Bool +getWindowVisual (const WindowPtr a_win, + VisualPtr *a_visual) +{ + int i=0, visual_id=0 ; + EPHYR_RETURN_VAL_IF_FAIL (a_win + && a_win->drawable.pScreen + && a_win->drawable.pScreen->visuals, + FALSE) ; + + visual_id = wVisual (a_win) ; + for (i=0; i < a_win->drawable.pScreen->numVisuals; i++) { + if (a_win->drawable.pScreen->visuals[i].vid == visual_id) { + *a_visual = &a_win->drawable.pScreen->visuals[i] ; + return TRUE ; + } + } + return FALSE ; +} + + +#define NUM_WINDOW_PAIRS 256 +static EphyrWindowPair window_pairs[NUM_WINDOW_PAIRS] ; + +static Bool +appendWindowPairToList (WindowPtr a_local, + int a_remote) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_local, FALSE) ; + + EPHYR_LOG ("(local,remote):(%p, %d)\n", a_local, a_remote) ; + + for (i=0; i < NUM_WINDOW_PAIRS; i++) { + if (window_pairs[i].local == NULL) { + window_pairs[i].local = a_local ; + window_pairs[i].remote = a_remote ; + return TRUE ; + } + } + return FALSE ; +} + +static Bool +findWindowPairFromLocal (WindowPtr a_local, + EphyrWindowPair **a_pair) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_pair && a_local, FALSE) ; + + for (i=0; i < NUM_WINDOW_PAIRS; i++) { + if (window_pairs[i].local == a_local) { + *a_pair = &window_pairs[i] ; + EPHYR_LOG ("found (%p, %d)\n", + (*a_pair)->local, + (*a_pair)->remote) ; + return TRUE ; + } + } + return FALSE ; +} + +Bool +findWindowPairFromRemote (int a_remote, + EphyrWindowPair **a_pair) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_pair, FALSE) ; + + for (i=0; i < NUM_WINDOW_PAIRS; i++) { + if (window_pairs[i].remote == a_remote) { + *a_pair = &window_pairs[i] ; + EPHYR_LOG ("found (%p, %d)\n", + (*a_pair)->local, + (*a_pair)->remote) ; + return TRUE ; + } + } + return FALSE ; +} + +static Bool +createHostPeerWindow (const WindowPtr a_win, + int *a_peer_win) +{ + Bool is_ok=FALSE ; + VisualPtr visual=NULL; + EphyrBox geo ; + + EPHYR_RETURN_VAL_IF_FAIL (a_win && a_peer_win, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_win->drawable.pScreen, + FALSE) ; + + EPHYR_LOG ("enter. a_win '%p'\n", a_win) ; + if (!getWindowVisual (a_win, &visual)) { + EPHYR_LOG_ERROR ("failed to get window visual\n") ; + goto out ; + } + if (!visual) { + EPHYR_LOG_ERROR ("failed to create visual\n") ; + goto out ; + } + memset (&geo, 0, sizeof (geo)) ; + geo.x = a_win->drawable.x ; + geo.y = a_win->drawable.y ; + geo.width = a_win->drawable.width ; + geo.height = a_win->drawable.height ; + if (!hostx_create_window (a_win->drawable.pScreen->myNum, + &geo, visual->vid, a_peer_win)) { + EPHYR_LOG_ERROR ("failed to create host peer window\n") ; + goto out ; + } + if (!appendWindowPairToList (a_win, *a_peer_win)) { + EPHYR_LOG_ERROR ("failed to append window to pair list\n") ; + goto out ; + } + is_ok = TRUE ; +out: + EPHYR_LOG ("leave:remote win%d\n", *a_peer_win) ; + return is_ok ; +} + +static Bool +destroyHostPeerWindow (const WindowPtr a_win) +{ + Bool is_ok = FALSE ; + EphyrWindowPair *pair=NULL ; + EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!findWindowPairFromLocal (a_win, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to find peer to local window\n") ; + goto out; + } + hostx_destroy_window (pair->remote) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok; +} + +static int +ProcXF86DRICreateDrawable (ClientPtr client) +{ + xXF86DRICreateDrawableReply rep; + DrawablePtr drawable=NULL; + WindowPtr window=NULL ; + EphyrWindowPair *pair=NULL ; + EphyrDRIWindowPrivPtr win_priv=NULL; + int rc=0, remote_win=0; + REQUEST(xXF86DRICreateDrawableReq); + REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); + + EPHYR_LOG ("enter\n") ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable (&drawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ; + return BadImplementation ; + } + EPHYR_LOG ("lookedup drawable %p\n", drawable) ; + window = (WindowPtr)drawable; + if (findWindowPairFromLocal (window, &pair) && pair) { + remote_win = pair->remote ; + EPHYR_LOG ("found window '%p' paire with remote '%d'\n", + window, remote_win) ; + } else if (!createHostPeerWindow (window, &remote_win)) { + EPHYR_LOG_ERROR ("failed to create host peer window\n") ; + return BadAlloc ; + } + + if (!ephyrDRICreateDrawable (stuff->screen, + remote_win, + (drm_drawable_t *)&rep.hHWDrawable)) { + EPHYR_LOG_ERROR ("failed to create dri drawable\n") ; + return BadValue; + } + + win_priv = GET_EPHYR_DRI_WINDOW_PRIV (window) ; + if (!win_priv) { + win_priv = calloc(1, sizeof (EphyrDRIWindowPrivRec)) ; + if (!win_priv) { + EPHYR_LOG_ERROR ("failed to allocate window private\n") ; + return BadAlloc ; + } + dixSetPrivate(&window->devPrivates, ephyrDRIWindowKey, win_priv); + EPHYR_LOG ("paired window '%p' with remote '%d'\n", + window, remote_win) ; + } + + WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRIDestroyDrawable (register ClientPtr client) +{ + DrawablePtr drawable=NULL; + WindowPtr window=NULL; + EphyrWindowPair *pair=NULL; + int rc=0; + REQUEST(xXF86DRIDestroyDrawableReq); + REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); + + EPHYR_LOG ("enter\n") ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rc = dixLookupDrawable(&drawable, + stuff->drawable, + client, + 0, + DixReadAccess); + if (rc != Success) + return rc; + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ; + return BadImplementation ; + } + window = (WindowPtr)drawable; + if (!findWindowPairFromLocal (window, &pair) && pair) { + EPHYR_LOG_ERROR ("failed to find pair window\n") ; + return BadImplementation; + } + if (!ephyrDRIDestroyDrawable(stuff->screen, + pair->remote/*drawable in host x*/)) { + EPHYR_LOG_ERROR ("failed to destroy dri drawable\n") ; + return BadImplementation; + } + pair->local=NULL ; + pair->remote=0; + + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRIGetDrawableInfo (register ClientPtr client) +{ + xXF86DRIGetDrawableInfoReply rep; + DrawablePtr drawable; + WindowPtr window=NULL; + EphyrWindowPair *pair=NULL; + int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0, i=0; + drm_clip_rect_t *clipRects=NULL; + drm_clip_rect_t *backClipRects=NULL; + REQUEST(xXF86DRIGetDrawableInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); + + EPHYR_LOG ("enter\n") ; + memset (&rep, 0, sizeof (rep)) ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success || !drawable) { + EPHYR_LOG_ERROR ("could not get drawable\n") ; + return rc; + } + + if (drawable->type != DRAWABLE_WINDOW) { + EPHYR_LOG_ERROR ("non windows type drawables are not yes supported\n") ; + return BadImplementation ; + } + window = (WindowPtr)drawable ; + memset (&pair, 0, sizeof (pair)) ; + if (!findWindowPairFromLocal (window, &pair) || !pair) { + EPHYR_LOG_ERROR ("failed to find remote peer drawable\n") ; + return BadMatch ; + } + EPHYR_LOG ("clip list of xephyr gl drawable:\n") ; + for (i=0; i < REGION_NUM_RECTS (&window->clipList); i++) { + EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", + REGION_RECTS (&window->clipList)[i].x1, + REGION_RECTS (&window->clipList)[i].y1, + REGION_RECTS (&window->clipList)[i].x2, + REGION_RECTS (&window->clipList)[i].y2) ; + } + + if (!ephyrDRIGetDrawableInfo (stuff->screen, + pair->remote/*the drawable in hostx*/, + (unsigned int*)&rep.drawableTableIndex, + (unsigned int*)&rep.drawableTableStamp, + (int*)&X, + (int*)&Y, + (int*)&W, + (int*)&H, + (int*)&rep.numClipRects, + &clipRects, + &backX, + &backY, + (int*)&rep.numBackClipRects, + &backClipRects)) { + return BadValue; + } + EPHYR_LOG ("num clip rects:%d, num back clip rects:%d\n", + (int)rep.numClipRects, (int)rep.numBackClipRects) ; + + 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.numClipRects) { + if (clipRects) { + ScreenPtr pScreen = screenInfo.screens[stuff->screen]; + int i=0; + EPHYR_LOG ("clip list of host gl drawable:\n") ; + for (i = 0; i < rep.numClipRects; i++) { + clipRects[i].x1 = max (clipRects[i].x1, 0); + clipRects[i].y1 = max (clipRects[i].y1, 0); + clipRects[i].x2 = min (clipRects[i].x2, + pScreen->width + clipRects[i].x1) ; + clipRects[i].y2 = min (clipRects[i].y2, + pScreen->width + clipRects[i].y1) ; + + EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n", + clipRects[i].x1, clipRects[i].y1, + clipRects[i].x2, clipRects[i].y2) ; + } + } else { + rep.numClipRects = 0; + } + } else { + EPHYR_LOG ("got zero host gl drawable clipping rects\n") ; + } + rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; + backClipRects = clipRects ; + rep.numBackClipRects = rep.numClipRects ; + if (rep.numBackClipRects) + rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; + EPHYR_LOG ("num host clip rects:%d\n", (int)rep.numClipRects) ; + EPHYR_LOG ("num host back clip rects:%d\n", (int)rep.numBackClipRects) ; + + 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 *)clipRects); + } + + if (rep.numBackClipRects) { + WriteToClient(client, + sizeof(drm_clip_rect_t) * rep.numBackClipRects, + (char *)backClipRects); + } + free(clipRects); + clipRects = NULL ; + + EPHYR_LOG ("leave\n") ; + + return Success; +} + +static int +ProcXF86DRIGetDeviceInfo (register ClientPtr client) +{ + xXF86DRIGetDeviceInfoReply rep; + drm_handle_t hFrameBuffer; + void *pDevPrivate; + REQUEST(xXF86DRIGetDeviceInfoReq); + REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); + + EPHYR_LOG ("enter\n") ; + if (stuff->screen >= screenInfo.numScreens) { + client->errorValue = stuff->screen; + return BadValue; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + if (!ephyrDRIGetDeviceInfo (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); + } + EPHYR_LOG ("leave\n") ; + return Success; +} + +static int +ProcXF86DRIDispatch (register ClientPtr client) +{ + REQUEST(xReq); + EPHYR_LOG ("enter\n") ; + + switch (stuff->data) + { + case X_XF86DRIQueryVersion: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIQueryVersion(client); + } + case X_XF86DRIQueryDirectRenderingCapable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIQueryDirectRenderingCapable(client); + } + } + + if (!LocalClient(client)) + return DRIErrorBase + XF86DRIClientNotLocal; + + switch (stuff->data) + { + case X_XF86DRIOpenConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIOpenConnection(client); + } + case X_XF86DRICloseConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICloseConnection(client); + } + case X_XF86DRIGetClientDriverName: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetClientDriverName(client); + } + case X_XF86DRICreateContext: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICreateContext(client); + } + case X_XF86DRIDestroyContext: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIDestroyContext(client); + } + case X_XF86DRICreateDrawable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRICreateDrawable(client); + } + case X_XF86DRIDestroyDrawable: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIDestroyDrawable(client); + } + case X_XF86DRIGetDrawableInfo: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetDrawableInfo(client); + } + case X_XF86DRIGetDeviceInfo: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIGetDeviceInfo(client); + } + case X_XF86DRIAuthConnection: { + EPHYR_LOG ("leave\n") ; + return ProcXF86DRIAuthConnection(client); + } + /* {Open,Close}FullScreen are deprecated now */ + default: { + EPHYR_LOG ("leave\n") ; + 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); + + EPHYR_LOG ("enter\n") ; + /* + * Only local clients are allowed DRI access, but remote clients still need + * these requests to find out cleanly. + */ + switch (stuff->data) + { + case X_XF86DRIQueryVersion: { + EPHYR_LOG ("leave\n") ; + return SProcXF86DRIQueryVersion(client); + } + case X_XF86DRIQueryDirectRenderingCapable: { + EPHYR_LOG ("leave\n") ; + return SProcXF86DRIQueryDirectRenderingCapable(client); + } + default: { + EPHYR_LOG ("leave\n") ; + return DRIErrorBase + XF86DRIClientNotLocal; + } + } +} diff --git a/xorg-server/hw/kdrive/ephyr/ephyrglxext.c b/xorg-server/hw/kdrive/ephyr/ephyrglxext.c index a0278cc2b..d6b8ca66d 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrglxext.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrglxext.c @@ -1,723 +1,723 @@ -/* - * Xephyr - A kdrive X server thats runs in a host X window. - * Authored by Matthew Allum <mallum@openedhand.com> - * - * Copyright © 2007 OpenedHand Ltd - * - * 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 OpenedHand Ltd not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. OpenedHand Ltd makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL OpenedHand Ltd 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: - * Dodji Seketeli <dodji@openedhand.com> - */ -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif - -#include "extnsionst.h" -#include "ephyrglxext.h" -#include "ephyrhostglx.h" -#define _HAVE_XALLOC_DECLS -#include "ephyrlog.h" -#include <GL/glxproto.h> -#include "glx/glxserver.h" -#include "glx/indirect_table.h" -#include "glx/indirect_util.h" -#include "glx/unpack.h" -#include "hostx.h" - - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - - -int ephyrGLXQueryVersion (__GLXclientState *cl, GLbyte *pc) ; -int ephyrGLXQueryVersionSwap (__GLXclientState *cl, GLbyte *pc) ; -int ephyrGLXGetVisualConfigs (__GLXclientState *cl, GLbyte *pc) ; -int ephyrGLXGetVisualConfigsSwap (__GLXclientState *cl, GLbyte *pc) ; -int ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ; -int ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ; -int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc); -int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc); -int ephyrGLXCreateContext (__GLXclientState *a_cl, GLbyte *a_pc); -int ephyrGLXCreateContextSwap (__GLXclientState *a_cl, GLbyte *a_pc); -int ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ; -int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; - -Bool -ephyrHijackGLXExtension (void) -{ - const void *(*dispatch_functions)[2]; - - if (!hostx_has_glx ()) { - EPHYR_LOG ("host X does not have GLX\n") ; - return FALSE ; - } - EPHYR_LOG ("host X does have GLX\n") ; - - if (!Single_dispatch_info.dispatch_functions) { - EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ; - return FALSE ; - } - /* - * hijack some single entry point dispatch functions - */ - dispatch_functions = Single_dispatch_info.dispatch_functions ; - EPHYR_RETURN_VAL_IF_FAIL (dispatch_functions, FALSE) ; - - dispatch_functions[X_GLXQueryVersion][0] = ephyrGLXQueryVersion ; - dispatch_functions[X_GLXQueryVersion][1] = ephyrGLXQueryVersionSwap ; - - dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ; - dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ; - dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ; - dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ; - - dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString ; - dispatch_functions[X_GLXQueryServerString][1] = - ephyrGLXQueryServerStringSwap ; - - dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext ; - dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap ; - - dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext ; - dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap ; - - dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent ; - dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap ; - - dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect ; - dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap ; - - dispatch_functions[73][0] = ephyrGLXGetString ; - dispatch_functions[73][1] = ephyrGLXGetStringSwap ; - - dispatch_functions[61][0] = ephyrGLXGetIntegerv ; - dispatch_functions[61][1] = ephyrGLXGetIntegervSwap ; - - /* - * hijack some vendor priv entry point dispatch functions - */ - dispatch_functions = VendorPriv_dispatch_info.dispatch_functions ; - dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX; - dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap; - EPHYR_LOG ("hijacked glx entry points to forward requests to host X\n") ; - - return TRUE ; -} - -/********************* - * implementation of - * hijacked GLX entry - * points - ********************/ - -int -ephyrGLXQueryVersion(__GLXclientState *a_cl, GLbyte *a_pc) -{ - ClientPtr client = a_cl->client; - xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; - xGLXQueryVersionReply reply; - int major, minor; - int res = BadImplementation ; - - EPHYR_LOG ("enter\n") ; - - major = req->majorVersion ; - minor = req->minorVersion ; - - if (!ephyrHostGLXQueryVersion (&major, &minor)) { - EPHYR_LOG_ERROR ("ephyrHostGLXQueryVersion() failed\n") ; - goto out ; - } - EPHYR_LOG ("major:%d, minor:%d\n", - major, minor); - reply.majorVersion = major ; - reply.minorVersion = minor ; - reply.length = 0 ; - reply.type = X_Reply ; - reply.sequenceNumber = client->sequence ; - - if (client->swapped) { - __glXSwapQueryVersionReply(client, &reply); - } else { - WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply); - } - - res = Success ; -out: - EPHYR_LOG ("leave\n") ; - return res; -} - -int -ephyrGLXQueryVersionSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT (&req->length); - __GLX_SWAP_INT (&req->majorVersion); - __GLX_SWAP_INT (&req->minorVersion); - return ephyrGLXQueryVersion (a_cl, a_pc) ; -} - -static int -ephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl, - GLbyte *a_pc, - Bool a_do_swap) -{ - xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc; - ClientPtr client = a_cl->client; - xGLXGetVisualConfigsReply reply; - int32_t *props_buf=NULL, num_visuals=0, - num_props=0, res=BadImplementation, i=0, - props_per_visual_size=0, - props_buf_size=0; - __GLX_DECLARE_SWAP_VARIABLES; - __GLX_DECLARE_SWAP_ARRAY_VARIABLES; - - EPHYR_LOG ("enter\n") ; - - if (!ephyrHostGLXGetVisualConfigs (req->screen, - &num_visuals, - &num_props, - &props_buf_size, - &props_buf)) { - EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; - goto out ; - } - EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; - - reply.numVisuals = num_visuals; - reply.numProps = num_props; - reply.length = (num_visuals *__GLX_SIZE_CARD32 * num_props) >> 2; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - - if (a_do_swap) { - __GLX_SWAP_SHORT(&reply.sequenceNumber); - __GLX_SWAP_INT(&reply.length); - __GLX_SWAP_INT(&reply.numVisuals); - __GLX_SWAP_INT(&reply.numProps); - __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; - } - WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); - props_per_visual_size = props_buf_size/num_visuals ; - for (i=0; i < num_visuals; i++) { - WriteToClient (client, - props_per_visual_size, - (char*)props_buf +i*props_per_visual_size); - } - res = Success ; - -out: - EPHYR_LOG ("leave\n") ; - xfree (props_buf) ; - props_buf = NULL ; - - return res ; -} - -static int -ephyrGLXGetFBConfigsSGIXReal (__GLXclientState *a_cl, - GLbyte *a_pc, - Bool a_do_swap) -{ - xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)a_pc; - ClientPtr client = a_cl->client; - xGLXGetVisualConfigsReply reply; - int32_t *props_buf=NULL, num_visuals=0, - num_props=0, res=BadImplementation, i=0, - props_per_visual_size=0, - props_buf_size=0; - __GLX_DECLARE_SWAP_VARIABLES; - __GLX_DECLARE_SWAP_ARRAY_VARIABLES; - - EPHYR_LOG ("enter\n") ; - - if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX (req->screen, - &num_visuals, - &num_props, - &props_buf_size, - &props_buf)) { - EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; - goto out ; - } - EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; - - reply.numVisuals = num_visuals; - reply.numProps = num_props; - reply.length = props_buf_size >> 2; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - - if (a_do_swap) { - __GLX_SWAP_SHORT(&reply.sequenceNumber); - __GLX_SWAP_INT(&reply.length); - __GLX_SWAP_INT(&reply.numVisuals); - __GLX_SWAP_INT(&reply.numProps); - __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; - } - WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); - props_per_visual_size = props_buf_size/num_visuals ; - for (i=0; i < num_visuals; i++) { - WriteToClient (client, - props_per_visual_size, - &((char*)props_buf)[i*props_per_visual_size]); - } - res = Success ; - -out: - EPHYR_LOG ("leave\n") ; - xfree (props_buf) ; - props_buf = NULL ; - - return res ; -} - -int -ephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, FALSE) ; -} - -int -ephyrGLXGetVisualConfigsSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, TRUE) ; -} - - -int -ephyrGLXClientInfo(__GLXclientState *a_cl, GLbyte *a_pc) -{ - int res=BadImplementation ; - xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc; - - EPHYR_LOG ("enter\n") ; - if (!ephyrHostGLXSendClientInfo (req->major, req->minor, (char*)req+1)) { - EPHYR_LOG_ERROR ("failed to send client info to host\n") ; - goto out ; - } - res = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -int -ephyrGLXClientInfoSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - xGLXClientInfoReq *req = (xGLXClientInfoReq *)a_pc; - __GLX_DECLARE_SWAP_VARIABLES; - - __GLX_SWAP_SHORT (&req->length); - __GLX_SWAP_INT (&req->major); - __GLX_SWAP_INT (&req->minor); - __GLX_SWAP_INT (&req->numbytes); - - return ephyrGLXClientInfo (a_cl, a_pc) ; -} - -int -ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) -{ - int res = BadImplementation ; - ClientPtr client = a_cl->client; - xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc; - xGLXQueryServerStringReply reply; - char *server_string=NULL, *buf=NULL; - int length=0 ; - - EPHYR_LOG ("enter\n") ; - if (!ephyrHostGLXGetStringFromServer (req->screen, - req->name, - EPHYR_HOST_GLX_QueryServerString, - &server_string)) { - EPHYR_LOG_ERROR ("failed to query string from host\n") ; - goto out ; - } - EPHYR_LOG ("string: %s\n", server_string) ; - length= strlen (server_string) + 1; - reply.type = X_Reply ; - reply.sequenceNumber = client->sequence ; - reply.length = __GLX_PAD (length) >> 2 ; - reply.n = length ; - buf = xcalloc (reply.length << 2, 1); - if (!buf) { - EPHYR_LOG_ERROR ("failed to allocate string\n;"); - return BadAlloc; - } - memcpy (buf, server_string, length); - - WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply); - WriteToClient(client, (int)(reply.length << 2), server_string); - - res = Success ; - -out: - EPHYR_LOG ("leave\n") ; - xfree (server_string) ; - server_string = NULL; - - xfree (buf); - buf = NULL; - - return res ; -} - -int -ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) -{ - EPHYR_LOG_ERROR ("not yet implemented\n") ; - return BadImplementation ; -} - - -int -ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, FALSE) ; -} - -int -ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ; -} - -static int -ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap) -{ - int res=BadImplementation; - EphyrHostWindowAttributes host_w_attrs ; - __GLX_DECLARE_SWAP_VARIABLES; - - EPHYR_RETURN_VAL_IF_FAIL (a_req, BadValue) ; - EPHYR_LOG ("enter\n") ; - - if (a_do_swap) { - __GLX_SWAP_SHORT(&a_req->length); - __GLX_SWAP_INT(&a_req->context); - __GLX_SWAP_INT(&a_req->visual); - __GLX_SWAP_INT(&a_req->screen); - __GLX_SWAP_INT(&a_req->shareList); - } - - EPHYR_LOG ("context creation requested. localid:%d, " - "screen:%d, visual:%d, direct:%d\n", - (int)a_req->context, (int)a_req->screen, - (int)a_req->visual, (int)a_req->isDirect) ; - - memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ; - if (!hostx_get_window_attributes (hostx_get_window (a_req->screen), - &host_w_attrs)) { - EPHYR_LOG_ERROR ("failed to get host window attrs\n") ; - goto out ; - } - - EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ; - - if (!ephyrHostGLXCreateContext (a_req->screen, - host_w_attrs.visualid, - a_req->context, - a_req->shareList, - a_req->isDirect)) { - EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ; - goto out ; - } - res = Success; -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -int -ephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc) -{ - xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; - - return ephyrGLXCreateContextReal (req, FALSE) ; -} - -int ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc) -{ - xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; - return ephyrGLXCreateContextReal (req, TRUE) ; -} - -static int -ephyrGLXDestroyContextReal (__GLXclientState *a_cl, - GLbyte *a_pc, - Bool a_do_swap) -{ - int res=BadImplementation; - ClientPtr client = a_cl->client; - xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc; - - EPHYR_LOG ("enter. id:%d\n", (int)req->context) ; - if (!ephyrHostDestroyContext (req->context)) { - EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ; - client->errorValue = req->context ; - goto out ; - } - res = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -int -ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ; -} - -int -ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ; -} - -static int -ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) -{ - int res=BadImplementation; - xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; - xGLXMakeCurrentReply reply ; - DrawablePtr drawable=NULL; - int rc=0; - - EPHYR_LOG ("enter\n") ; - rc = dixLookupDrawable (&drawable, - req->drawable, - a_cl->client, - 0, - DixReadAccess); - EPHYR_RETURN_VAL_IF_FAIL (drawable, BadValue) ; - EPHYR_RETURN_VAL_IF_FAIL (drawable->pScreen, BadValue) ; - EPHYR_LOG ("screen nummber requested:%d\n", - drawable->pScreen->myNum) ; - - memset (&reply, 0, sizeof (reply)) ; - if (!ephyrHostGLXMakeCurrent (hostx_get_window (drawable->pScreen->myNum), - req->context, - req->oldContextTag, - (int*)&reply.contextTag)) { - EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ; - goto out; - } - reply.length = 0; - reply.type = X_Reply; - reply.sequenceNumber = a_cl->client->sequence; - if (a_do_swap) { - __GLX_DECLARE_SWAP_VARIABLES; - __GLX_SWAP_SHORT(&reply.sequenceNumber); - __GLX_SWAP_INT(&reply.length); - __GLX_SWAP_INT(&reply.contextTag); - } - WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply); - - res = Success ; -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -int -ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ; -} - -int -ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ; -} - -static int -ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) -{ - ClientPtr client=NULL ; - int context_tag=0, name=0, res=BadImplementation, length=0 ; - char *string=NULL; - __GLX_DECLARE_SWAP_VARIABLES; - - EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ; - - EPHYR_LOG ("enter\n") ; - - client = a_cl->client ; - - if (a_do_swap) { - __GLX_SWAP_INT (a_pc + 4); - __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE); - } - context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ; - a_pc += __GLX_SINGLE_HDR_SIZE; - name = *(GLenum*)(a_pc + 0); - EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ; - if (!ephyrHostGLXGetStringFromServer (context_tag, - name, - EPHYR_HOST_GLX_GetString, - &string)) { - EPHYR_LOG_ERROR ("failed to get string from server\n") ; - goto out ; - } - if (string) { - length = strlen (string) + 1; - EPHYR_LOG ("got string:'%s', size:%d\n", string, length) ; - } else { - EPHYR_LOG ("got string: string (null)\n") ; - } - __GLX_BEGIN_REPLY (length); - __GLX_PUT_SIZE (length); - __GLX_SEND_HEADER (); - if (a_do_swap) { - __GLX_SWAP_REPLY_SIZE (); - __GLX_SWAP_REPLY_HEADER (); - } - WriteToClient (client, length, (char *)string); - - res = Success ; -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -int -ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ; -} - -int -ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ; -} - -static int -ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) -{ - int res=BadImplementation; - xGLXSingleReq * const req = (xGLXSingleReq *) a_pc; - GLenum int_name ; - int value=0 ; - GLint answer_buf_room[200]; - GLint *buf=NULL ; - - EPHYR_LOG ("enter\n") ; - - a_pc += __GLX_SINGLE_HDR_SIZE; - - int_name = *(GLenum*) (a_pc+0) ; - if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) { - EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ; - goto out ; - } - buf = __glXGetAnswerBuffer (a_cl, sizeof (value), - answer_buf_room, - sizeof (answer_buf_room), - 4) ; - - if (!buf) { - EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ; - res = BadAlloc ; - goto out ; - } - __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ; - res = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -int -ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ; -} - -int -ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ; -} - -static int -ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) -{ - int res=BadImplementation; - ClientPtr client = a_cl->client; - xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc; - xGLXIsDirectReply reply; - int is_direct=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ; - - EPHYR_LOG ("enter\n") ; - - memset (&reply, 0, sizeof (reply)) ; - if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) { - EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ; - goto out ; - } - reply.isDirect = is_direct ; - reply.length = 0; - reply.type = X_Reply; - reply.sequenceNumber = client->sequence; - WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); - res = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -int -ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ; -} - -int -ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) -{ - return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ; -} +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum <mallum@openedhand.com> + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli <dodji@openedhand.com> + */ +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include "extnsionst.h" +#include "ephyrglxext.h" +#include "ephyrhostglx.h" +#define _HAVE_XALLOC_DECLS +#include "ephyrlog.h" +#include <GL/glxproto.h> +#include "glx/glxserver.h" +#include "glx/indirect_table.h" +#include "glx/indirect_util.h" +#include "glx/unpack.h" +#include "hostx.h" + + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + +int ephyrGLXQueryVersion (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXQueryVersionSwap (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXGetVisualConfigs (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXGetVisualConfigsSwap (__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ; +int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXCreateContext (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXCreateContextSwap (__GLXclientState *a_cl, GLbyte *a_pc); +int ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ; +int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; + +Bool +ephyrHijackGLXExtension (void) +{ + const void *(*dispatch_functions)[2]; + + if (!hostx_has_glx ()) { + EPHYR_LOG ("host X does not have GLX\n") ; + return FALSE ; + } + EPHYR_LOG ("host X does have GLX\n") ; + + if (!Single_dispatch_info.dispatch_functions) { + EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ; + return FALSE ; + } + /* + * hijack some single entry point dispatch functions + */ + dispatch_functions = Single_dispatch_info.dispatch_functions ; + EPHYR_RETURN_VAL_IF_FAIL (dispatch_functions, FALSE) ; + + dispatch_functions[X_GLXQueryVersion][0] = ephyrGLXQueryVersion ; + dispatch_functions[X_GLXQueryVersion][1] = ephyrGLXQueryVersionSwap ; + + dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ; + dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ; + dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ; + dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ; + + dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString ; + dispatch_functions[X_GLXQueryServerString][1] = + ephyrGLXQueryServerStringSwap ; + + dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext ; + dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap ; + + dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext ; + dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap ; + + dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent ; + dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap ; + + dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect ; + dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap ; + + dispatch_functions[73][0] = ephyrGLXGetString ; + dispatch_functions[73][1] = ephyrGLXGetStringSwap ; + + dispatch_functions[61][0] = ephyrGLXGetIntegerv ; + dispatch_functions[61][1] = ephyrGLXGetIntegervSwap ; + + /* + * hijack some vendor priv entry point dispatch functions + */ + dispatch_functions = VendorPriv_dispatch_info.dispatch_functions ; + dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX; + dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap; + EPHYR_LOG ("hijacked glx entry points to forward requests to host X\n") ; + + return TRUE ; +} + +/********************* + * implementation of + * hijacked GLX entry + * points + ********************/ + +int +ephyrGLXQueryVersion(__GLXclientState *a_cl, GLbyte *a_pc) +{ + ClientPtr client = a_cl->client; + xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; + xGLXQueryVersionReply reply; + int major, minor; + int res = BadImplementation ; + + EPHYR_LOG ("enter\n") ; + + major = req->majorVersion ; + minor = req->minorVersion ; + + if (!ephyrHostGLXQueryVersion (&major, &minor)) { + EPHYR_LOG_ERROR ("ephyrHostGLXQueryVersion() failed\n") ; + goto out ; + } + EPHYR_LOG ("major:%d, minor:%d\n", + major, minor); + reply.majorVersion = major ; + reply.minorVersion = minor ; + reply.length = 0 ; + reply.type = X_Reply ; + reply.sequenceNumber = client->sequence ; + + if (client->swapped) { + __glXSwapQueryVersionReply(client, &reply); + } else { + WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply); + } + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res; +} + +int +ephyrGLXQueryVersionSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT (&req->length); + __GLX_SWAP_INT (&req->majorVersion); + __GLX_SWAP_INT (&req->minorVersion); + return ephyrGLXQueryVersion (a_cl, a_pc) ; +} + +static int +ephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc; + ClientPtr client = a_cl->client; + xGLXGetVisualConfigsReply reply; + int32_t *props_buf=NULL, num_visuals=0, + num_props=0, res=BadImplementation, i=0, + props_per_visual_size=0, + props_buf_size=0; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostGLXGetVisualConfigs (req->screen, + &num_visuals, + &num_props, + &props_buf_size, + &props_buf)) { + EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; + goto out ; + } + EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; + + reply.numVisuals = num_visuals; + reply.numProps = num_props; + reply.length = (num_visuals *__GLX_SIZE_CARD32 * num_props) >> 2; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.numVisuals); + __GLX_SWAP_INT(&reply.numProps); + __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; + } + WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); + props_per_visual_size = props_buf_size/num_visuals ; + for (i=0; i < num_visuals; i++) { + WriteToClient (client, + props_per_visual_size, + (char*)props_buf +i*props_per_visual_size); + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + free(props_buf) ; + props_buf = NULL ; + + return res ; +} + +static int +ephyrGLXGetFBConfigsSGIXReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)a_pc; + ClientPtr client = a_cl->client; + xGLXGetVisualConfigsReply reply; + int32_t *props_buf=NULL, num_visuals=0, + num_props=0, res=BadImplementation, i=0, + props_per_visual_size=0, + props_buf_size=0; + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_DECLARE_SWAP_ARRAY_VARIABLES; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX (req->screen, + &num_visuals, + &num_props, + &props_buf_size, + &props_buf)) { + EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; + goto out ; + } + EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; + + reply.numVisuals = num_visuals; + reply.numProps = num_props; + reply.length = props_buf_size >> 2; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.numVisuals); + __GLX_SWAP_INT(&reply.numProps); + __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; + } + WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); + props_per_visual_size = props_buf_size/num_visuals ; + for (i=0; i < num_visuals; i++) { + WriteToClient (client, + props_per_visual_size, + &((char*)props_buf)[i*props_per_visual_size]); + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + free(props_buf) ; + props_buf = NULL ; + + return res ; +} + +int +ephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetVisualConfigsSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, TRUE) ; +} + + +int +ephyrGLXClientInfo(__GLXclientState *a_cl, GLbyte *a_pc) +{ + int res=BadImplementation ; + xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXSendClientInfo (req->major, req->minor, (char*)req+1)) { + EPHYR_LOG_ERROR ("failed to send client info to host\n") ; + goto out ; + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXClientInfoSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + xGLXClientInfoReq *req = (xGLXClientInfoReq *)a_pc; + __GLX_DECLARE_SWAP_VARIABLES; + + __GLX_SWAP_SHORT (&req->length); + __GLX_SWAP_INT (&req->major); + __GLX_SWAP_INT (&req->minor); + __GLX_SWAP_INT (&req->numbytes); + + return ephyrGLXClientInfo (a_cl, a_pc) ; +} + +int +ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) +{ + int res = BadImplementation ; + ClientPtr client = a_cl->client; + xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc; + xGLXQueryServerStringReply reply; + char *server_string=NULL, *buf=NULL; + int length=0 ; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostGLXGetStringFromServer (req->screen, + req->name, + EPHYR_HOST_GLX_QueryServerString, + &server_string)) { + EPHYR_LOG_ERROR ("failed to query string from host\n") ; + goto out ; + } + EPHYR_LOG ("string: %s\n", server_string) ; + length= strlen (server_string) + 1; + reply.type = X_Reply ; + reply.sequenceNumber = client->sequence ; + reply.length = __GLX_PAD (length) >> 2 ; + reply.n = length ; + buf = calloc(reply.length << 2, 1); + if (!buf) { + EPHYR_LOG_ERROR ("failed to allocate string\n;"); + return BadAlloc; + } + memcpy (buf, server_string, length); + + WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply); + WriteToClient(client, (int)(reply.length << 2), server_string); + + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + free(server_string) ; + server_string = NULL; + + free(buf); + buf = NULL; + + return res ; +} + +int +ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) +{ + EPHYR_LOG_ERROR ("not yet implemented\n") ; + return BadImplementation ; +} + + +int +ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap) +{ + int res=BadImplementation; + EphyrHostWindowAttributes host_w_attrs ; + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL (a_req, BadValue) ; + EPHYR_LOG ("enter\n") ; + + if (a_do_swap) { + __GLX_SWAP_SHORT(&a_req->length); + __GLX_SWAP_INT(&a_req->context); + __GLX_SWAP_INT(&a_req->visual); + __GLX_SWAP_INT(&a_req->screen); + __GLX_SWAP_INT(&a_req->shareList); + } + + EPHYR_LOG ("context creation requested. localid:%d, " + "screen:%d, visual:%d, direct:%d\n", + (int)a_req->context, (int)a_req->screen, + (int)a_req->visual, (int)a_req->isDirect) ; + + memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ; + if (!hostx_get_window_attributes (hostx_get_window (a_req->screen), + &host_w_attrs)) { + EPHYR_LOG_ERROR ("failed to get host window attrs\n") ; + goto out ; + } + + EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ; + + if (!ephyrHostGLXCreateContext (a_req->screen, + host_w_attrs.visualid, + a_req->context, + a_req->shareList, + a_req->isDirect)) { + EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ; + goto out ; + } + res = Success; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + + return ephyrGLXCreateContextReal (req, FALSE) ; +} + +int ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc) +{ + xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; + return ephyrGLXCreateContextReal (req, TRUE) ; +} + +static int +ephyrGLXDestroyContextReal (__GLXclientState *a_cl, + GLbyte *a_pc, + Bool a_do_swap) +{ + int res=BadImplementation; + ClientPtr client = a_cl->client; + xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc; + + EPHYR_LOG ("enter. id:%d\n", (int)req->context) ; + if (!ephyrHostDestroyContext (req->context)) { + EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ; + client->errorValue = req->context ; + goto out ; + } + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; + xGLXMakeCurrentReply reply ; + DrawablePtr drawable=NULL; + int rc=0; + + EPHYR_LOG ("enter\n") ; + rc = dixLookupDrawable (&drawable, + req->drawable, + a_cl->client, + 0, + DixReadAccess); + EPHYR_RETURN_VAL_IF_FAIL (drawable, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (drawable->pScreen, BadValue) ; + EPHYR_LOG ("screen nummber requested:%d\n", + drawable->pScreen->myNum) ; + + memset (&reply, 0, sizeof (reply)) ; + if (!ephyrHostGLXMakeCurrent (hostx_get_window (drawable->pScreen->myNum), + req->context, + req->oldContextTag, + (int*)&reply.contextTag)) { + EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ; + goto out; + } + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = a_cl->client->sequence; + if (a_do_swap) { + __GLX_DECLARE_SWAP_VARIABLES; + __GLX_SWAP_SHORT(&reply.sequenceNumber); + __GLX_SWAP_INT(&reply.length); + __GLX_SWAP_INT(&reply.contextTag); + } + WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply); + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + ClientPtr client=NULL ; + int context_tag=0, name=0, res=BadImplementation, length=0 ; + char *string=NULL; + __GLX_DECLARE_SWAP_VARIABLES; + + EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + client = a_cl->client ; + + if (a_do_swap) { + __GLX_SWAP_INT (a_pc + 4); + __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE); + } + context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ; + a_pc += __GLX_SINGLE_HDR_SIZE; + name = *(GLenum*)(a_pc + 0); + EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ; + if (!ephyrHostGLXGetStringFromServer (context_tag, + name, + EPHYR_HOST_GLX_GetString, + &string)) { + EPHYR_LOG_ERROR ("failed to get string from server\n") ; + goto out ; + } + if (string) { + length = strlen (string) + 1; + EPHYR_LOG ("got string:'%s', size:%d\n", string, length) ; + } else { + EPHYR_LOG ("got string: string (null)\n") ; + } + __GLX_BEGIN_REPLY (length); + __GLX_PUT_SIZE (length); + __GLX_SEND_HEADER (); + if (a_do_swap) { + __GLX_SWAP_REPLY_SIZE (); + __GLX_SWAP_REPLY_HEADER (); + } + WriteToClient (client, length, (char *)string); + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + xGLXSingleReq * const req = (xGLXSingleReq *) a_pc; + GLenum int_name ; + int value=0 ; + GLint answer_buf_room[200]; + GLint *buf=NULL ; + + EPHYR_LOG ("enter\n") ; + + a_pc += __GLX_SINGLE_HDR_SIZE; + + int_name = *(GLenum*) (a_pc+0) ; + if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) { + EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ; + goto out ; + } + buf = __glXGetAnswerBuffer (a_cl, sizeof (value), + answer_buf_room, + sizeof (answer_buf_room), + 4) ; + + if (!buf) { + EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ; + res = BadAlloc ; + goto out ; + } + __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ; + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ; +} + +static int +ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) +{ + int res=BadImplementation; + ClientPtr client = a_cl->client; + xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc; + xGLXIsDirectReply reply; + int is_direct=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + memset (&reply, 0, sizeof (reply)) ; + if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) { + EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ; + goto out ; + } + reply.isDirect = is_direct ; + reply.length = 0; + reply.type = X_Reply; + reply.sequenceNumber = client->sequence; + WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); + res = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +int +ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ; +} + +int +ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) +{ + return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ; +} diff --git a/xorg-server/hw/kdrive/ephyr/ephyrhostvideo.c b/xorg-server/hw/kdrive/ephyr/ephyrhostvideo.c index f4a1b9d17..60f200629 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrhostvideo.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrhostvideo.c @@ -1,1012 +1,1012 @@ -/* - * Xephyr - A kdrive X server thats runs in a host X window. - * Authored by Matthew Allum <mallum@openedhand.com> - * - * Copyright © 2007 OpenedHand Ltd - * - * 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 OpenedHand Ltd not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. OpenedHand Ltd makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL OpenedHand Ltd 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: - * Dodji Seketeli <dodji@openedhand.com> - */ -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -/* - * including some server headers (like kdrive-config.h) - * might define the macro _XSERVER64 - * on 64 bits machines. That macro must _NOT_ be defined for Xlib - * client code, otherwise bad things happen. - * So let's undef that macro if necessary. - */ -#ifdef _XSERVER64 -#undef _XSERVER64 -#endif -#include <X11/Xutil.h> -#include <X11/Xlibint.h> -#include <X11/extensions/Xvlib.h> -#include <X11/extensions/Xvproto.h> -#include <X11/extensions/Xext.h> -#include <X11/extensions/extutil.h> -#define _HAVE_XALLOC_DECLS - -#include "hostx.h" -#include "ephyrhostvideo.h" -#include "ephyrlog.h" - -#ifndef TRUE -#define TRUE 1 -#endif /*TRUE*/ - -#ifndef FALSE -#define FALSE 0 -#endif /*FALSE*/ - -static XExtensionInfo _xv_info_data; -static XExtensionInfo *xv_info = &_xv_info_data; -static char *xv_extension_name = XvName; -static char *xv_error_string(Display *dpy, int code, XExtCodes *codes, - char * buf, int n); -static int xv_close_display(Display *dpy, XExtCodes *codes); -static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire); - -static XExtensionHooks xv_extension_hooks = { - NULL, /* create_gc */ - NULL, /* copy_gc */ - NULL, /* flush_gc */ - NULL, /* free_gc */ - NULL, /* create_font */ - NULL, /* free_font */ - xv_close_display, /* close_display */ - xv_wire_to_event, /* wire_to_event */ - NULL, /* event_to_wire */ - NULL, /* error */ - xv_error_string /* error_string */ -}; - - -static char *xv_error_list[] = -{ - "BadPort", /* XvBadPort */ - "BadEncoding", /* XvBadEncoding */ - "BadControl" /* XvBadControl */ -}; - - -#define XvCheckExtension(dpy, i, val) \ - XextCheckExtension(dpy, i, xv_extension_name, val) -#define XvGetReq(name, req) \ - WORD64ALIGN\ - if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ - _XFlush(dpy);\ - req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ - req->reqType = info->codes->major_opcode;\ - req->xvReqType = xv_##name; \ - req->length = (SIZEOF(xv##name##Req))>>2;\ - dpy->bufptr += SIZEOF(xv##name##Req);\ - dpy->request++ - -static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) - - -static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, - xv_extension_name, - &xv_extension_hooks, - XvNumEvents, NULL) - -static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, - XvNumErrors, xv_error_list) - -struct _EphyrHostXVAdaptorArray { - XvAdaptorInfo *adaptors ; - unsigned int nb_adaptors ; -}; - -/*heavily copied from libx11*/ -#define BUFSIZE 2048 -static void -ephyrHostXVLogXErrorEvent (Display *a_display, - XErrorEvent *a_err_event, - FILE *a_fp) -{ - char buffer[BUFSIZ]; - char mesg[BUFSIZ]; - char number[32]; - const char *mtype = "XlibMessage"; - register _XExtension *ext = (_XExtension *)NULL; - _XExtension *bext = (_XExtension *)NULL; - Display *dpy = a_display ; - - XGetErrorText(dpy, a_err_event->error_code, buffer, BUFSIZ); - XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); - (void) fprintf(a_fp, "%s: %s\n ", mesg, buffer); - XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", - mesg, BUFSIZ); - (void) fprintf(a_fp, mesg, a_err_event->request_code); - if (a_err_event->request_code < 128) { - sprintf(number, "%d", a_err_event->request_code); - XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); - } else { - for (ext = dpy->ext_procs; - ext && (ext->codes.major_opcode != a_err_event->request_code); - ext = ext->next) - ; - if (ext) - strcpy(buffer, ext->name); - else - buffer[0] = '\0'; - } - (void) fprintf(a_fp, " (%s)\n", buffer); - if (a_err_event->request_code >= 128) { - XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", - mesg, BUFSIZ); - fputs(" ", a_fp); - (void) fprintf(a_fp, mesg, a_err_event->minor_code); - if (ext) { - sprintf(mesg, "%s.%d", ext->name, a_err_event->minor_code); - XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); - (void) fprintf(a_fp, " (%s)", buffer); - } - fputs("\n", a_fp); - } - if (a_err_event->error_code >= 128) { - /* kludge, try to find the extension that caused it */ - buffer[0] = '\0'; - for (ext = dpy->ext_procs; ext; ext = ext->next) { - if (ext->error_string) - (*ext->error_string)(dpy, a_err_event->error_code, &ext->codes, - buffer, BUFSIZ); - if (buffer[0]) { - bext = ext; - break; - } - if (ext->codes.first_error && - ext->codes.first_error < (int)a_err_event->error_code && - (!bext || ext->codes.first_error > bext->codes.first_error)) - bext = ext; - } - if (bext) - sprintf(buffer, "%s.%d", bext->name, - a_err_event->error_code - bext->codes.first_error); - else - strcpy(buffer, "Value"); - XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); - if (mesg[0]) { - fputs(" ", a_fp); - (void) fprintf(a_fp, mesg, a_err_event->resourceid); - fputs("\n", a_fp); - } - /* let extensions try to print the values */ - for (ext = dpy->ext_procs; ext; ext = ext->next) { - if (ext->error_values) - (*ext->error_values)(dpy, a_err_event, a_fp); - } - } else if ((a_err_event->error_code == BadWindow) || - (a_err_event->error_code == BadPixmap) || - (a_err_event->error_code == BadCursor) || - (a_err_event->error_code == BadFont) || - (a_err_event->error_code == BadDrawable) || - (a_err_event->error_code == BadColor) || - (a_err_event->error_code == BadGC) || - (a_err_event->error_code == BadIDChoice) || - (a_err_event->error_code == BadValue) || - (a_err_event->error_code == BadAtom)) { - if (a_err_event->error_code == BadValue) - XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", - mesg, BUFSIZ); - else if (a_err_event->error_code == BadAtom) - XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", - mesg, BUFSIZ); - else - XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", - mesg, BUFSIZ); - fputs(" ", a_fp); - (void) fprintf(a_fp, mesg, a_err_event->resourceid); - fputs("\n", a_fp); - } - XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", - mesg, BUFSIZ); - fputs(" ", a_fp); - (void) fprintf(a_fp, mesg, a_err_event->serial); - XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", - mesg, BUFSIZ); - fputs("\n ", a_fp); - (void) fprintf(a_fp, mesg, dpy->request); - fputs("\n", a_fp); -} - -static int -ephyrHostXVErrorHandler (Display *a_display, - XErrorEvent *a_error_event) -{ - EPHYR_LOG_ERROR ("got an error from the host xserver:\n") ; - ephyrHostXVLogXErrorEvent (a_display, a_error_event, stderr) ; - return Success ; -} - -void -ephyrHostXVInit (void) -{ - static Bool s_initialized ; - - if (s_initialized) - return ; - XSetErrorHandler (ephyrHostXVErrorHandler) ; - s_initialized = TRUE ; -} - -Bool -ephyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) -{ - EphyrHostXVAdaptorArray *result=NULL ; - int ret=0 ; - Bool is_ok=FALSE ; - - EPHYR_RETURN_VAL_IF_FAIL (a_adaptors, FALSE) ; - - EPHYR_LOG ("enter\n") ; - - result = Xcalloc (1, sizeof (EphyrHostXVAdaptorArray)) ; - if (!result) - goto out ; - - ret = XvQueryAdaptors (hostx_get_display (), - DefaultRootWindow (hostx_get_display ()), - &result->nb_adaptors, - &result->adaptors) ; - if (ret != Success) { - EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", ret) ; - goto out ; - } - *a_adaptors = result ; - is_ok = TRUE ; - -out: - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -void -ephyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) -{ - if (!a_adaptors) - return ; - if (a_adaptors->adaptors) { - XvFreeAdaptorInfo (a_adaptors->adaptors) ; - a_adaptors->adaptors = NULL ; - a_adaptors->nb_adaptors = 0 ; - } - XFree (a_adaptors) ; -} - -int -ephyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; - return a_this->nb_adaptors ; -} - -EphyrHostXVAdaptor* -ephyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, - int a_index) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; - - if (a_index >= a_this->nb_adaptors) - return NULL ; - return (EphyrHostXVAdaptor*)&a_this->adaptors[a_index] ; -} - -char -ephyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; - return ((XvAdaptorInfo*)a_this)->type ; -} - -const char* -ephyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; - - return ((XvAdaptorInfo*)a_this)->name ; -} - -EphyrHostVideoFormat* -ephyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, - int *a_nb_formats) -{ - EphyrHostVideoFormat *formats=NULL ; - int nb_formats=0, i=0 ; - XVisualInfo *visual_info, visual_info_template ; - int nb_visual_info ; - - EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; - - nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; - formats = Xcalloc (nb_formats, sizeof (EphyrHostVideoFormat)) ; - for (i=0; i < nb_formats; i++) { - memset (&visual_info_template, 0, sizeof (visual_info_template)) ; - visual_info_template.visualid = - ((XvAdaptorInfo*)a_this)->formats[i].visual_id; - visual_info = XGetVisualInfo (hostx_get_display (), - VisualIDMask, - &visual_info_template, - &nb_visual_info) ; - formats[i].depth = ((XvAdaptorInfo*)a_this)->formats[i].depth ; - formats[i].visual_class = visual_info->class ; - XFree (visual_info) ; - } - if (a_nb_formats) - *a_nb_formats = nb_formats ; - return formats ; -} - -int -ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; - - return ((XvAdaptorInfo*)a_this)->num_ports ; -} - -int -ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; - - return ((XvAdaptorInfo*)a_this)->base_id ; -} - -Bool -ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, - Bool *a_result) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; - - if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvInputMask) - *a_result = TRUE ; - else - *a_result = FALSE ; - return TRUE ; -} - -Bool -ephyrHostXVAdaptorHasGetVideo (const EphyrHostXVAdaptor *a_this, - Bool *a_result) -{ - if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvOutputMask) - *a_result = TRUE ; - else - *a_result = FALSE ; - return TRUE ; -} - -Bool -ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, - Bool *a_result) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; - - if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvInputMask) - *a_result = TRUE ; - else - *a_result = FALSE ; - return TRUE ; -} - -Bool -ephyrHostXVAdaptorHasGetStill (const EphyrHostXVAdaptor *a_this, - Bool *a_result) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; - - if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvOutputMask) - *a_result = TRUE ; - else - *a_result = FALSE ; - return TRUE ; -} - -Bool -ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, - Bool *a_result) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; - - if (((XvAdaptorInfo*)a_this)->type & XvImageMask && XvInputMask) - *a_result = TRUE ; - else - *a_result = FALSE ; - return TRUE ; -} - -Bool -ephyrHostXVQueryEncodings (int a_port_id, - EphyrHostEncoding **a_encodings, - unsigned int *a_num_encodings) -{ - EphyrHostEncoding *encodings=NULL ; - XvEncodingInfo *encoding_info=NULL ; - unsigned int num_encodings=0, i; - int ret=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, FALSE) ; - - ret = XvQueryEncodings (hostx_get_display (), - a_port_id, - &num_encodings, - &encoding_info) ; - if (num_encodings && encoding_info) { - encodings = Xcalloc (num_encodings, sizeof (EphyrHostEncoding)) ; - for (i=0; i<num_encodings; i++) { - encodings[i].id = encoding_info[i].encoding_id ; - encodings[i].name = strdup (encoding_info[i].name) ; - encodings[i].width = encoding_info[i].width ; - encodings[i].height = encoding_info[i].height ; - encodings[i].rate.numerator = encoding_info[i].rate.numerator ; - encodings[i].rate.denominator = encoding_info[i].rate.denominator ; - } - } - if (encoding_info) { - XvFreeEncodingInfo (encoding_info) ; - encoding_info = NULL ; - } - *a_encodings = encodings ; - *a_num_encodings = num_encodings ; - - if (ret != Success) - return FALSE ; - return TRUE ; -} - -void -ephyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, - int a_num_encodings) -{ - int i=0 ; - - if (!a_encodings) - return ; - for (i=0; i < a_num_encodings; i++) { - xfree (a_encodings[i].name) ; - a_encodings[i].name = NULL ; - } - xfree (a_encodings) ; -} - -void -ephyrHostAttributesDelete (EphyrHostAttribute *a_attributes) -{ - if (!a_attributes) - return ; - XFree (a_attributes) ; -} - -Bool -ephyrHostXVQueryPortAttributes (int a_port_id, - EphyrHostAttribute **a_attributes, - int *a_num_attributes) -{ - EPHYR_RETURN_VAL_IF_FAIL (a_attributes && a_num_attributes, FALSE) ; - - *a_attributes = - (EphyrHostAttribute*)XvQueryPortAttributes (hostx_get_display (), - a_port_id, - a_num_attributes); - - return TRUE ; -} - -Bool -ephyrHostXVQueryImageFormats (int a_port_id, - EphyrHostImageFormat **a_formats, - int *a_num_format) -{ - XvImageFormatValues *result=NULL ; - - EPHYR_RETURN_VAL_IF_FAIL (a_formats && a_num_format, FALSE) ; - - result = XvListImageFormats (hostx_get_display (), - a_port_id, - a_num_format) ; - *a_formats = (EphyrHostImageFormat*) result ; - return TRUE ; - -} - -Bool -ephyrHostXVSetPortAttribute (int a_port_id, - int a_atom, - int a_attr_value) -{ - int res=Success ; - - EPHYR_LOG ("atom,name,value: (%d,%s,%d)\n", - a_atom, - XGetAtomName (hostx_get_display (), a_atom), - a_attr_value) ; - - res = XvSetPortAttribute (hostx_get_display (), - a_port_id, - a_atom, - a_attr_value) ; - if (res != Success) { - EPHYR_LOG_ERROR ("XvSetPortAttribute() failed: %d\n", res) ; - return FALSE ; - } - XFlush (hostx_get_display ()) ; - EPHYR_LOG ("leave\n") ; - - return TRUE ; -} - -Bool -ephyrHostXVGetPortAttribute (int a_port_id, - int a_atom, - int *a_attr_value) -{ - int res=Success ; - Bool ret=FALSE ; - - EPHYR_RETURN_VAL_IF_FAIL (a_attr_value, FALSE) ; - - EPHYR_LOG ("enter, a_port_id: %d, a_atomid: %d, attr_name: %s\n", - a_port_id, a_atom, XGetAtomName (hostx_get_display (), a_atom)) ; - - res = XvGetPortAttribute (hostx_get_display (), - a_port_id, - a_atom, - a_attr_value) ; - if (res != Success) { - EPHYR_LOG_ERROR ("XvGetPortAttribute() failed: %d \n", res) ; - goto out ; - } - EPHYR_LOG ("atom,value: (%d, %d)\n", a_atom, *a_attr_value) ; - - ret = TRUE ; - -out: - EPHYR_LOG ("leave\n") ; - return ret ; -} - -Bool -ephyrHostXVQueryBestSize (int a_port_id, - Bool a_motion, - unsigned int a_frame_w, - unsigned int a_frame_h, - unsigned int a_drw_w, - unsigned int a_drw_h, - unsigned int *a_actual_w, - unsigned int *a_actual_h) -{ - int res=0 ; - Bool is_ok=FALSE ; - - EPHYR_RETURN_VAL_IF_FAIL (a_actual_w && a_actual_h, FALSE) ; - - EPHYR_LOG ("enter: frame (%dx%d), drw (%dx%d)\n", - a_frame_w, a_frame_h, - a_drw_w, a_drw_h) ; - - res = XvQueryBestSize (hostx_get_display (), - a_port_id, - a_motion, - a_frame_w, a_frame_h, - a_drw_w, a_drw_h, - a_actual_w, a_actual_h) ; - if (res != Success) { - EPHYR_LOG_ERROR ("XvQueryBestSize() failed: %d\n", res) ; - goto out ; - } - XSync (hostx_get_display (), FALSE) ; - - EPHYR_LOG ("actual (%dx%d)\n", *a_actual_w, *a_actual_h) ; - is_ok = TRUE ; - -out: - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -static Bool -xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) -{ - XExtDisplayInfo *info = xv_find_display (dpy); - XvEvent *re = (XvEvent *)host; - xvEvent *event = (xvEvent *)wire; - - XvCheckExtension(dpy, info, False); - - switch ((event->u.u.type & 0x7F) - info->codes->first_event) { - case XvVideoNotify: - re->xvvideo.type = event->u.u.type & 0x7f; - re->xvvideo.serial = - _XSetLastRequestRead(dpy, (xGenericReply *)event); - re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); - re->xvvideo.display = dpy; - re->xvvideo.time = event->u.videoNotify.time; - re->xvvideo.reason = event->u.videoNotify.reason; - re->xvvideo.drawable = event->u.videoNotify.drawable; - re->xvvideo.port_id = event->u.videoNotify.port; - break; - case XvPortNotify: - re->xvport.type = event->u.u.type & 0x7f; - re->xvport.serial = - _XSetLastRequestRead(dpy, (xGenericReply *)event); - re->xvport.send_event = ((event->u.u.type & 0x80) != 0); - re->xvport.display = dpy; - re->xvport.time = event->u.portNotify.time; - re->xvport.port_id = event->u.portNotify.port; - re->xvport.attribute = event->u.portNotify.attribute; - re->xvport.value = event->u.portNotify.value; - break; - default: - return False; - } - - return True ; -} - -Bool -ephyrHostXVQueryImageAttributes (int a_port_id, - int a_image_id /*image fourcc code*/, - unsigned short *a_width, - unsigned short *a_height, - int *a_image_size, - int *a_pitches, - int *a_offsets) -{ - Display *dpy = hostx_get_display () ; - Bool ret=FALSE ; - XExtDisplayInfo *info = xv_find_display (dpy); - xvQueryImageAttributesReq *req=NULL; - xvQueryImageAttributesReply rep; - - EPHYR_RETURN_VAL_IF_FAIL (a_width, FALSE) ; - EPHYR_RETURN_VAL_IF_FAIL (a_height, FALSE) ; - EPHYR_RETURN_VAL_IF_FAIL (a_image_size, FALSE) ; - - XvCheckExtension (dpy, info, FALSE); - - LockDisplay (dpy); - - XvGetReq (QueryImageAttributes, req); - req->id = a_image_id; - req->port = a_port_id; - req->width = *a_width; - req->height = *a_height; - /* - * read the reply - */ - if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { - EPHYR_LOG_ERROR ("QeryImageAttribute req failed\n") ; - goto out ; - } - if (a_pitches && a_offsets) { - _XRead (dpy, - (char*)a_pitches, - rep.num_planes << 2); - _XRead (dpy, - (char*)a_offsets, - rep.num_planes << 2); - } else { - _XEatData(dpy, rep.length << 2); - } - *a_width = rep.width ; - *a_height = rep.height ; - *a_image_size = rep.data_size ; - - ret = TRUE ; - -out: - UnlockDisplay (dpy) ; - SyncHandle (); - return ret ; -} - -Bool -ephyrHostGetAtom (const char* a_name, - Bool a_create_if_not_exists, - int *a_atom) -{ - int atom=None ; - - EPHYR_RETURN_VAL_IF_FAIL (a_atom, FALSE) ; - - atom = XInternAtom (hostx_get_display (), a_name, a_create_if_not_exists); - if (atom == None) { - return FALSE ; - } - *a_atom = atom ; - return TRUE ; -} - -char* -ephyrHostGetAtomName (int a_atom) -{ - return XGetAtomName (hostx_get_display (), a_atom) ; -} - -void -ephyrHostFree (void *a_pointer) -{ - if (a_pointer) - XFree (a_pointer) ; -} - -Bool -ephyrHostXVPutImage (int a_screen_num, - int a_port_id, - int a_image_id, - int a_drw_x, - int a_drw_y, - int a_drw_w, - int a_drw_h, - int a_src_x, - int a_src_y, - int a_src_w, - int a_src_h, - int a_image_width, - int a_image_height, - unsigned char *a_buf, - EphyrHostBox *a_clip_rects, - int a_clip_rect_nums ) -{ - Bool is_ok=TRUE ; - XvImage *xv_image=NULL ; - GC gc=0 ; - XGCValues gc_values; - Display *dpy = hostx_get_display () ; - XRectangle *rects=NULL ; - int res = 0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_buf, FALSE) ; - - EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ; - - memset (&gc_values, 0, sizeof (gc_values)) ; - gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); - if (!gc) { - EPHYR_LOG_ERROR ("failed to create gc \n") ; - goto out ; - } - xv_image = (XvImage*) XvCreateImage (hostx_get_display (), - a_port_id, a_image_id, - NULL, a_image_width, a_image_height) ; - if (!xv_image) { - EPHYR_LOG_ERROR ("failed to create image\n") ; - goto out ; - } - xv_image->data = (char*)a_buf ; - if (a_clip_rect_nums) { - int i=0 ; - rects = calloc (a_clip_rect_nums, sizeof (XRectangle)) ; - for (i=0; i < a_clip_rect_nums; i++) { - rects[i].x = a_clip_rects[i].x1 ; - rects[i].y = a_clip_rects[i].y1 ; - rects[i].width = a_clip_rects[i].x2 - a_clip_rects[i].x1; - rects[i].height = a_clip_rects[i].y2 - a_clip_rects[i].y1; - EPHYR_LOG ("(x,y,w,h): (%d,%d,%d,%d)\n", - rects[i].x, rects[i].y, - rects[i].width, rects[i].height) ; - } - XSetClipRectangles (dpy, gc, 0, 0, rects, a_clip_rect_nums, YXBanded) ; - /*this always returns 1*/ - } - res = XvPutImage (dpy, a_port_id, - hostx_get_window (a_screen_num), - gc, xv_image, - a_src_x, a_src_y, a_src_w, a_src_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; - if (res != Success) { - EPHYR_LOG_ERROR ("XvPutImage() failed: %d\n", res) ; - goto out ; - } - is_ok = TRUE ; - -out: - if (xv_image) { - XFree (xv_image) ; - xv_image = NULL ; - } - if (gc) { - XFreeGC (dpy, gc) ; - gc = NULL ; - } - if (rects) { - free (rects) ; - rects = NULL ; - } - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -Bool -ephyrHostXVPutVideo (int a_screen_num, int a_port_id, - int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, - int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) -{ - Bool is_ok=FALSE ; - int res=FALSE ; - GC gc=0 ; - XGCValues gc_values; - Display *dpy=hostx_get_display () ; - - EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - - gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); - if (!gc) { - EPHYR_LOG_ERROR ("failed to create gc \n") ; - goto out ; - } - res = XvPutVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, - a_vid_x, a_vid_y, a_vid_w, a_vid_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; - - if (res != Success) { - EPHYR_LOG_ERROR ("XvPutVideo() failed: %d\n", res) ; - goto out ; - } - - is_ok = TRUE ; - -out: - if (gc) { - XFreeGC (dpy, gc) ; - gc = NULL ; - } - return is_ok ; -} - -Bool -ephyrHostXVGetVideo (int a_screen_num, int a_port_id, - int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, - int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) -{ - Bool is_ok=FALSE ; - int res=FALSE ; - GC gc=0 ; - XGCValues gc_values; - Display *dpy=hostx_get_display () ; - - EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - - gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); - if (!gc) { - EPHYR_LOG_ERROR ("failed to create gc \n") ; - goto out ; - } - res = XvGetVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, - a_vid_x, a_vid_y, a_vid_w, a_vid_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; - - if (res != Success) { - EPHYR_LOG_ERROR ("XvGetVideo() failed: %d\n", res) ; - goto out ; - } - - is_ok = TRUE ; - -out: - if (gc) { - XFreeGC (dpy, gc) ; - gc = NULL ; - } - return is_ok ; -} - -Bool -ephyrHostXVPutStill (int a_screen_num, int a_port_id, - int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, - int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) -{ - Bool is_ok=FALSE ; - int res=FALSE ; - GC gc=0 ; - XGCValues gc_values; - Display *dpy=hostx_get_display () ; - - EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - - gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); - if (!gc) { - EPHYR_LOG_ERROR ("failed to create gc \n") ; - goto out ; - } - res = XvPutStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, - a_vid_x, a_vid_y, a_vid_w, a_vid_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; - - if (res != Success) { - EPHYR_LOG_ERROR ("XvPutStill() failed: %d\n", res) ; - goto out ; - } - - is_ok = TRUE ; - -out: - if (gc) { - XFreeGC (dpy, gc) ; - gc = NULL ; - } - return is_ok ; -} - -Bool -ephyrHostXVGetStill (int a_screen_num, int a_port_id, - int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, - int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) -{ - Bool is_ok=FALSE ; - int res=FALSE ; - GC gc=0 ; - XGCValues gc_values; - Display *dpy=hostx_get_display () ; - - EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - - gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); - if (!gc) { - EPHYR_LOG_ERROR ("failed to create gc \n") ; - goto out ; - } - res = XvGetStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, - a_vid_x, a_vid_y, a_vid_w, a_vid_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; - - if (res != Success) { - EPHYR_LOG_ERROR ("XvGetStill() failed: %d\n", res) ; - goto out ; - } - - is_ok = TRUE ; - -out: - if (gc) { - XFreeGC (dpy, gc) ; - gc = NULL ; - } - return is_ok ; -} - -Bool -ephyrHostXVStopVideo (int a_screen_num, int a_port_id) -{ - int ret=0 ; - Bool is_ok=FALSE ; - Display *dpy = hostx_get_display () ; - - EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; - - EPHYR_LOG ("enter\n") ; - - ret = XvStopVideo (dpy, a_port_id, hostx_get_window (a_screen_num)) ; - if (ret != Success) { - EPHYR_LOG_ERROR ("XvStopVideo() failed: %d \n", ret) ; - goto out ; - } - is_ok = TRUE ; - -out: - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum <mallum@openedhand.com> + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli <dodji@openedhand.com> + */ +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +/* + * including some server headers (like kdrive-config.h) + * might define the macro _XSERVER64 + * on 64 bits machines. That macro must _NOT_ be defined for Xlib + * client code, otherwise bad things happen. + * So let's undef that macro if necessary. + */ +#ifdef _XSERVER64 +#undef _XSERVER64 +#endif +#include <X11/Xutil.h> +#include <X11/Xlibint.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/Xvproto.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#define _HAVE_XALLOC_DECLS + +#include "hostx.h" +#include "ephyrhostvideo.h" +#include "ephyrlog.h" + +#ifndef TRUE +#define TRUE 1 +#endif /*TRUE*/ + +#ifndef FALSE +#define FALSE 0 +#endif /*FALSE*/ + +static XExtensionInfo _xv_info_data; +static XExtensionInfo *xv_info = &_xv_info_data; +static char *xv_extension_name = XvName; +static char *xv_error_string(Display *dpy, int code, XExtCodes *codes, + char * buf, int n); +static int xv_close_display(Display *dpy, XExtCodes *codes); +static Bool xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire); + +static XExtensionHooks xv_extension_hooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + xv_close_display, /* close_display */ + xv_wire_to_event, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + xv_error_string /* error_string */ +}; + + +static char *xv_error_list[] = +{ + "BadPort", /* XvBadPort */ + "BadEncoding", /* XvBadEncoding */ + "BadControl" /* XvBadControl */ +}; + + +#define XvCheckExtension(dpy, i, val) \ + XextCheckExtension(dpy, i, xv_extension_name, val) +#define XvGetReq(name, req) \ + WORD64ALIGN\ + if ((dpy->bufptr + SIZEOF(xv##name##Req)) > dpy->bufmax)\ + _XFlush(dpy);\ + req = (xv##name##Req *)(dpy->last_req = dpy->bufptr);\ + req->reqType = info->codes->major_opcode;\ + req->xvReqType = xv_##name; \ + req->length = (SIZEOF(xv##name##Req))>>2;\ + dpy->bufptr += SIZEOF(xv##name##Req);\ + dpy->request++ + +static XEXT_GENERATE_CLOSE_DISPLAY (xv_close_display, xv_info) + + +static XEXT_GENERATE_FIND_DISPLAY (xv_find_display, xv_info, + xv_extension_name, + &xv_extension_hooks, + XvNumEvents, NULL) + +static XEXT_GENERATE_ERROR_STRING (xv_error_string, xv_extension_name, + XvNumErrors, xv_error_list) + +struct _EphyrHostXVAdaptorArray { + XvAdaptorInfo *adaptors ; + unsigned int nb_adaptors ; +}; + +/*heavily copied from libx11*/ +#define BUFSIZE 2048 +static void +ephyrHostXVLogXErrorEvent (Display *a_display, + XErrorEvent *a_err_event, + FILE *a_fp) +{ + char buffer[BUFSIZ]; + char mesg[BUFSIZ]; + char number[32]; + const char *mtype = "XlibMessage"; + register _XExtension *ext = (_XExtension *)NULL; + _XExtension *bext = (_XExtension *)NULL; + Display *dpy = a_display ; + + XGetErrorText(dpy, a_err_event->error_code, buffer, BUFSIZ); + XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); + (void) fprintf(a_fp, "%s: %s\n ", mesg, buffer); + XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", + mesg, BUFSIZ); + (void) fprintf(a_fp, mesg, a_err_event->request_code); + if (a_err_event->request_code < 128) { + sprintf(number, "%d", a_err_event->request_code); + XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); + } else { + for (ext = dpy->ext_procs; + ext && (ext->codes.major_opcode != a_err_event->request_code); + ext = ext->next) + ; + if (ext) + strcpy(buffer, ext->name); + else + buffer[0] = '\0'; + } + (void) fprintf(a_fp, " (%s)\n", buffer); + if (a_err_event->request_code >= 128) { + XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->minor_code); + if (ext) { + sprintf(mesg, "%s.%d", ext->name, a_err_event->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); + (void) fprintf(a_fp, " (%s)", buffer); + } + fputs("\n", a_fp); + } + if (a_err_event->error_code >= 128) { + /* kludge, try to find the extension that caused it */ + buffer[0] = '\0'; + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_string) + (*ext->error_string)(dpy, a_err_event->error_code, &ext->codes, + buffer, BUFSIZ); + if (buffer[0]) { + bext = ext; + break; + } + if (ext->codes.first_error && + ext->codes.first_error < (int)a_err_event->error_code && + (!bext || ext->codes.first_error > bext->codes.first_error)) + bext = ext; + } + if (bext) + sprintf(buffer, "%s.%d", bext->name, + a_err_event->error_code - bext->codes.first_error); + else + strcpy(buffer, "Value"); + XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); + if (mesg[0]) { + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->resourceid); + fputs("\n", a_fp); + } + /* let extensions try to print the values */ + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->error_values) + (*ext->error_values)(dpy, a_err_event, a_fp); + } + } else if ((a_err_event->error_code == BadWindow) || + (a_err_event->error_code == BadPixmap) || + (a_err_event->error_code == BadCursor) || + (a_err_event->error_code == BadFont) || + (a_err_event->error_code == BadDrawable) || + (a_err_event->error_code == BadColor) || + (a_err_event->error_code == BadGC) || + (a_err_event->error_code == BadIDChoice) || + (a_err_event->error_code == BadValue) || + (a_err_event->error_code == BadAtom)) { + if (a_err_event->error_code == BadValue) + XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", + mesg, BUFSIZ); + else if (a_err_event->error_code == BadAtom) + XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", + mesg, BUFSIZ); + else + XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->resourceid); + fputs("\n", a_fp); + } + XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", + mesg, BUFSIZ); + fputs(" ", a_fp); + (void) fprintf(a_fp, mesg, a_err_event->serial); + XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", + mesg, BUFSIZ); + fputs("\n ", a_fp); + (void) fprintf(a_fp, mesg, dpy->request); + fputs("\n", a_fp); +} + +static int +ephyrHostXVErrorHandler (Display *a_display, + XErrorEvent *a_error_event) +{ + EPHYR_LOG_ERROR ("got an error from the host xserver:\n") ; + ephyrHostXVLogXErrorEvent (a_display, a_error_event, stderr) ; + return Success ; +} + +void +ephyrHostXVInit (void) +{ + static Bool s_initialized ; + + if (s_initialized) + return ; + XSetErrorHandler (ephyrHostXVErrorHandler) ; + s_initialized = TRUE ; +} + +Bool +ephyrHostXVQueryAdaptors (EphyrHostXVAdaptorArray **a_adaptors) +{ + EphyrHostXVAdaptorArray *result=NULL ; + int ret=0 ; + Bool is_ok=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_adaptors, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + result = Xcalloc (1, sizeof (EphyrHostXVAdaptorArray)) ; + if (!result) + goto out ; + + ret = XvQueryAdaptors (hostx_get_display (), + DefaultRootWindow (hostx_get_display ()), + &result->nb_adaptors, + &result->adaptors) ; + if (ret != Success) { + EPHYR_LOG_ERROR ("failed to query host adaptors: %d\n", ret) ; + goto out ; + } + *a_adaptors = result ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +void +ephyrHostXVAdaptorArrayDelete (EphyrHostXVAdaptorArray *a_adaptors) +{ + if (!a_adaptors) + return ; + if (a_adaptors->adaptors) { + XvFreeAdaptorInfo (a_adaptors->adaptors) ; + a_adaptors->adaptors = NULL ; + a_adaptors->nb_adaptors = 0 ; + } + XFree (a_adaptors) ; +} + +int +ephyrHostXVAdaptorArrayGetSize (const EphyrHostXVAdaptorArray *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + return a_this->nb_adaptors ; +} + +EphyrHostXVAdaptor* +ephyrHostXVAdaptorArrayAt (const EphyrHostXVAdaptorArray *a_this, + int a_index) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + if (a_index >= a_this->nb_adaptors) + return NULL ; + return (EphyrHostXVAdaptor*)&a_this->adaptors[a_index] ; +} + +char +ephyrHostXVAdaptorGetType (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + return ((XvAdaptorInfo*)a_this)->type ; +} + +const char* +ephyrHostXVAdaptorGetName (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + return ((XvAdaptorInfo*)a_this)->name ; +} + +EphyrHostVideoFormat* +ephyrHostXVAdaptorGetVideoFormats (const EphyrHostXVAdaptor *a_this, + int *a_nb_formats) +{ + EphyrHostVideoFormat *formats=NULL ; + int nb_formats=0, i=0 ; + XVisualInfo *visual_info, visual_info_template ; + int nb_visual_info ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this, NULL) ; + + nb_formats = ((XvAdaptorInfo*)a_this)->num_formats ; + formats = Xcalloc (nb_formats, sizeof (EphyrHostVideoFormat)) ; + for (i=0; i < nb_formats; i++) { + memset (&visual_info_template, 0, sizeof (visual_info_template)) ; + visual_info_template.visualid = + ((XvAdaptorInfo*)a_this)->formats[i].visual_id; + visual_info = XGetVisualInfo (hostx_get_display (), + VisualIDMask, + &visual_info_template, + &nb_visual_info) ; + formats[i].depth = ((XvAdaptorInfo*)a_this)->formats[i].depth ; + formats[i].visual_class = visual_info->class ; + XFree (visual_info) ; + } + if (a_nb_formats) + *a_nb_formats = nb_formats ; + return formats ; +} + +int +ephyrHostXVAdaptorGetNbPorts (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + + return ((XvAdaptorInfo*)a_this)->num_ports ; +} + +int +ephyrHostXVAdaptorGetFirstPortID (const EphyrHostXVAdaptor *a_this) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this, -1) ; + + return ((XvAdaptorInfo*)a_this)->base_id ; +} + +Bool +ephyrHostXVAdaptorHasPutVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvInputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasGetVideo (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + if (((XvAdaptorInfo*)a_this)->type & XvVideoMask & XvOutputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasPutStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvInputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasGetStill (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvStillMask && XvOutputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVAdaptorHasPutImage (const EphyrHostXVAdaptor *a_this, + Bool *a_result) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_result, FALSE) ; + + if (((XvAdaptorInfo*)a_this)->type & XvImageMask && XvInputMask) + *a_result = TRUE ; + else + *a_result = FALSE ; + return TRUE ; +} + +Bool +ephyrHostXVQueryEncodings (int a_port_id, + EphyrHostEncoding **a_encodings, + unsigned int *a_num_encodings) +{ + EphyrHostEncoding *encodings=NULL ; + XvEncodingInfo *encoding_info=NULL ; + unsigned int num_encodings=0, i; + int ret=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, FALSE) ; + + ret = XvQueryEncodings (hostx_get_display (), + a_port_id, + &num_encodings, + &encoding_info) ; + if (num_encodings && encoding_info) { + encodings = Xcalloc (num_encodings, sizeof (EphyrHostEncoding)) ; + for (i=0; i<num_encodings; i++) { + encodings[i].id = encoding_info[i].encoding_id ; + encodings[i].name = strdup (encoding_info[i].name) ; + encodings[i].width = encoding_info[i].width ; + encodings[i].height = encoding_info[i].height ; + encodings[i].rate.numerator = encoding_info[i].rate.numerator ; + encodings[i].rate.denominator = encoding_info[i].rate.denominator ; + } + } + if (encoding_info) { + XvFreeEncodingInfo (encoding_info) ; + encoding_info = NULL ; + } + *a_encodings = encodings ; + *a_num_encodings = num_encodings ; + + if (ret != Success) + return FALSE ; + return TRUE ; +} + +void +ephyrHostEncodingsDelete (EphyrHostEncoding *a_encodings, + int a_num_encodings) +{ + int i=0 ; + + if (!a_encodings) + return ; + for (i=0; i < a_num_encodings; i++) { + free(a_encodings[i].name) ; + a_encodings[i].name = NULL ; + } + free(a_encodings) ; +} + +void +ephyrHostAttributesDelete (EphyrHostAttribute *a_attributes) +{ + if (!a_attributes) + return ; + XFree (a_attributes) ; +} + +Bool +ephyrHostXVQueryPortAttributes (int a_port_id, + EphyrHostAttribute **a_attributes, + int *a_num_attributes) +{ + EPHYR_RETURN_VAL_IF_FAIL (a_attributes && a_num_attributes, FALSE) ; + + *a_attributes = + (EphyrHostAttribute*)XvQueryPortAttributes (hostx_get_display (), + a_port_id, + a_num_attributes); + + return TRUE ; +} + +Bool +ephyrHostXVQueryImageFormats (int a_port_id, + EphyrHostImageFormat **a_formats, + int *a_num_format) +{ + XvImageFormatValues *result=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_formats && a_num_format, FALSE) ; + + result = XvListImageFormats (hostx_get_display (), + a_port_id, + a_num_format) ; + *a_formats = (EphyrHostImageFormat*) result ; + return TRUE ; + +} + +Bool +ephyrHostXVSetPortAttribute (int a_port_id, + int a_atom, + int a_attr_value) +{ + int res=Success ; + + EPHYR_LOG ("atom,name,value: (%d,%s,%d)\n", + a_atom, + XGetAtomName (hostx_get_display (), a_atom), + a_attr_value) ; + + res = XvSetPortAttribute (hostx_get_display (), + a_port_id, + a_atom, + a_attr_value) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvSetPortAttribute() failed: %d\n", res) ; + return FALSE ; + } + XFlush (hostx_get_display ()) ; + EPHYR_LOG ("leave\n") ; + + return TRUE ; +} + +Bool +ephyrHostXVGetPortAttribute (int a_port_id, + int a_atom, + int *a_attr_value) +{ + int res=Success ; + Bool ret=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_attr_value, FALSE) ; + + EPHYR_LOG ("enter, a_port_id: %d, a_atomid: %d, attr_name: %s\n", + a_port_id, a_atom, XGetAtomName (hostx_get_display (), a_atom)) ; + + res = XvGetPortAttribute (hostx_get_display (), + a_port_id, + a_atom, + a_attr_value) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetPortAttribute() failed: %d \n", res) ; + goto out ; + } + EPHYR_LOG ("atom,value: (%d, %d)\n", a_atom, *a_attr_value) ; + + ret = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return ret ; +} + +Bool +ephyrHostXVQueryBestSize (int a_port_id, + Bool a_motion, + unsigned int a_frame_w, + unsigned int a_frame_h, + unsigned int a_drw_w, + unsigned int a_drw_h, + unsigned int *a_actual_w, + unsigned int *a_actual_h) +{ + int res=0 ; + Bool is_ok=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_actual_w && a_actual_h, FALSE) ; + + EPHYR_LOG ("enter: frame (%dx%d), drw (%dx%d)\n", + a_frame_w, a_frame_h, + a_drw_w, a_drw_h) ; + + res = XvQueryBestSize (hostx_get_display (), + a_port_id, + a_motion, + a_frame_w, a_frame_h, + a_drw_w, a_drw_h, + a_actual_w, a_actual_h) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvQueryBestSize() failed: %d\n", res) ; + goto out ; + } + XSync (hostx_get_display (), FALSE) ; + + EPHYR_LOG ("actual (%dx%d)\n", *a_actual_w, *a_actual_h) ; + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +xv_wire_to_event(Display *dpy, XEvent *host, xEvent *wire) +{ + XExtDisplayInfo *info = xv_find_display (dpy); + XvEvent *re = (XvEvent *)host; + xvEvent *event = (xvEvent *)wire; + + XvCheckExtension(dpy, info, False); + + switch ((event->u.u.type & 0x7F) - info->codes->first_event) { + case XvVideoNotify: + re->xvvideo.type = event->u.u.type & 0x7f; + re->xvvideo.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvvideo.send_event = ((event->u.u.type & 0x80) != 0); + re->xvvideo.display = dpy; + re->xvvideo.time = event->u.videoNotify.time; + re->xvvideo.reason = event->u.videoNotify.reason; + re->xvvideo.drawable = event->u.videoNotify.drawable; + re->xvvideo.port_id = event->u.videoNotify.port; + break; + case XvPortNotify: + re->xvport.type = event->u.u.type & 0x7f; + re->xvport.serial = + _XSetLastRequestRead(dpy, (xGenericReply *)event); + re->xvport.send_event = ((event->u.u.type & 0x80) != 0); + re->xvport.display = dpy; + re->xvport.time = event->u.portNotify.time; + re->xvport.port_id = event->u.portNotify.port; + re->xvport.attribute = event->u.portNotify.attribute; + re->xvport.value = event->u.portNotify.value; + break; + default: + return False; + } + + return True ; +} + +Bool +ephyrHostXVQueryImageAttributes (int a_port_id, + int a_image_id /*image fourcc code*/, + unsigned short *a_width, + unsigned short *a_height, + int *a_image_size, + int *a_pitches, + int *a_offsets) +{ + Display *dpy = hostx_get_display () ; + Bool ret=FALSE ; + XExtDisplayInfo *info = xv_find_display (dpy); + xvQueryImageAttributesReq *req=NULL; + xvQueryImageAttributesReply rep; + + EPHYR_RETURN_VAL_IF_FAIL (a_width, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_height, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_image_size, FALSE) ; + + XvCheckExtension (dpy, info, FALSE); + + LockDisplay (dpy); + + XvGetReq (QueryImageAttributes, req); + req->id = a_image_id; + req->port = a_port_id; + req->width = *a_width; + req->height = *a_height; + /* + * read the reply + */ + if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) { + EPHYR_LOG_ERROR ("QeryImageAttribute req failed\n") ; + goto out ; + } + if (a_pitches && a_offsets) { + _XRead (dpy, + (char*)a_pitches, + rep.num_planes << 2); + _XRead (dpy, + (char*)a_offsets, + rep.num_planes << 2); + } else { + _XEatData(dpy, rep.length << 2); + } + *a_width = rep.width ; + *a_height = rep.height ; + *a_image_size = rep.data_size ; + + ret = TRUE ; + +out: + UnlockDisplay (dpy) ; + SyncHandle (); + return ret ; +} + +Bool +ephyrHostGetAtom (const char* a_name, + Bool a_create_if_not_exists, + int *a_atom) +{ + int atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_atom, FALSE) ; + + atom = XInternAtom (hostx_get_display (), a_name, a_create_if_not_exists); + if (atom == None) { + return FALSE ; + } + *a_atom = atom ; + return TRUE ; +} + +char* +ephyrHostGetAtomName (int a_atom) +{ + return XGetAtomName (hostx_get_display (), a_atom) ; +} + +void +ephyrHostFree (void *a_pointer) +{ + if (a_pointer) + XFree (a_pointer) ; +} + +Bool +ephyrHostXVPutImage (int a_screen_num, + int a_port_id, + int a_image_id, + int a_drw_x, + int a_drw_y, + int a_drw_w, + int a_drw_h, + int a_src_x, + int a_src_y, + int a_src_w, + int a_src_h, + int a_image_width, + int a_image_height, + unsigned char *a_buf, + EphyrHostBox *a_clip_rects, + int a_clip_rect_nums ) +{ + Bool is_ok=TRUE ; + XvImage *xv_image=NULL ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy = hostx_get_display () ; + XRectangle *rects=NULL ; + int res = 0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_buf, FALSE) ; + + EPHYR_LOG ("enter, num_clip_rects: %d\n", a_clip_rect_nums) ; + + memset (&gc_values, 0, sizeof (gc_values)) ; + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + xv_image = (XvImage*) XvCreateImage (hostx_get_display (), + a_port_id, a_image_id, + NULL, a_image_width, a_image_height) ; + if (!xv_image) { + EPHYR_LOG_ERROR ("failed to create image\n") ; + goto out ; + } + xv_image->data = (char*)a_buf ; + if (a_clip_rect_nums) { + int i=0 ; + rects = calloc (a_clip_rect_nums, sizeof (XRectangle)) ; + for (i=0; i < a_clip_rect_nums; i++) { + rects[i].x = a_clip_rects[i].x1 ; + rects[i].y = a_clip_rects[i].y1 ; + rects[i].width = a_clip_rects[i].x2 - a_clip_rects[i].x1; + rects[i].height = a_clip_rects[i].y2 - a_clip_rects[i].y1; + EPHYR_LOG ("(x,y,w,h): (%d,%d,%d,%d)\n", + rects[i].x, rects[i].y, + rects[i].width, rects[i].height) ; + } + XSetClipRectangles (dpy, gc, 0, 0, rects, a_clip_rect_nums, YXBanded) ; + /*this always returns 1*/ + } + res = XvPutImage (dpy, a_port_id, + hostx_get_window (a_screen_num), + gc, xv_image, + a_src_x, a_src_y, a_src_w, a_src_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutImage() failed: %d\n", res) ; + goto out ; + } + is_ok = TRUE ; + +out: + if (xv_image) { + XFree (xv_image) ; + xv_image = NULL ; + } + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + if (rects) { + free (rects) ; + rects = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +Bool +ephyrHostXVPutVideo (int a_screen_num, int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvPutVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutVideo() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVGetVideo (int a_screen_num, int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvGetVideo (dpy, a_port_id, hostx_get_window (a_screen_num), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetVideo() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVPutStill (int a_screen_num, int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvPutStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvPutStill() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVGetStill (int a_screen_num, int a_port_id, + int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h, + int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) +{ + Bool is_ok=FALSE ; + int res=FALSE ; + GC gc=0 ; + XGCValues gc_values; + Display *dpy=hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + gc = XCreateGC (dpy, hostx_get_window (a_screen_num), 0L, &gc_values); + if (!gc) { + EPHYR_LOG_ERROR ("failed to create gc \n") ; + goto out ; + } + res = XvGetStill (dpy, a_port_id, hostx_get_window (a_screen_num), gc, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h) ; + + if (res != Success) { + EPHYR_LOG_ERROR ("XvGetStill() failed: %d\n", res) ; + goto out ; + } + + is_ok = TRUE ; + +out: + if (gc) { + XFreeGC (dpy, gc) ; + gc = NULL ; + } + return is_ok ; +} + +Bool +ephyrHostXVStopVideo (int a_screen_num, int a_port_id) +{ + int ret=0 ; + Bool is_ok=FALSE ; + Display *dpy = hostx_get_display () ; + + EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + ret = XvStopVideo (dpy, a_port_id, hostx_get_window (a_screen_num)) ; + if (ret != Success) { + EPHYR_LOG_ERROR ("XvStopVideo() failed: %d \n", ret) ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + diff --git a/xorg-server/hw/kdrive/ephyr/ephyrvideo.c b/xorg-server/hw/kdrive/ephyr/ephyrvideo.c index 6624ab98a..14213c966 100644 --- a/xorg-server/hw/kdrive/ephyr/ephyrvideo.c +++ b/xorg-server/hw/kdrive/ephyr/ephyrvideo.c @@ -1,1273 +1,1273 @@ -/* - * Xephyr - A kdrive X server thats runs in a host X window. - * Authored by Matthew Allum <mallum@openedhand.com> - * - * Copyright © 2007 OpenedHand Ltd - * - * 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 OpenedHand Ltd not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. OpenedHand Ltd makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL OpenedHand Ltd 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: - * Dodji Seketeli <dodji@openedhand.com> - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include <string.h> -#include <X11/extensions/Xv.h> -#include "ephyrlog.h" -#include "kdrive.h" -#include "kxv.h" -#include "ephyr.h" -#include "hostx.h" -#include "ephyrhostvideo.h" - -struct _EphyrXVPriv { - EphyrHostXVAdaptorArray *host_adaptors ; - KdVideoAdaptorPtr adaptors ; - int num_adaptors ; -}; -typedef struct _EphyrXVPriv EphyrXVPriv ; - -struct _EphyrPortPriv { - int port_number ; - KdVideoAdaptorPtr current_adaptor ; - EphyrXVPriv *xv_priv; - unsigned char *image_buf ; - int image_buf_size ; - int image_id ; - int drw_x, drw_y, drw_w, drw_h ; - int src_x, src_y, src_w, src_h ; - int image_width, image_height ; -}; -typedef struct _EphyrPortPriv EphyrPortPriv ; - -static Bool DoSimpleClip (BoxPtr a_dst_drw, - BoxPtr a_clipper, - BoxPtr a_result) ; - -static Bool ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; - -/* -static Bool ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; -*/ - -static EphyrXVPriv* ephyrXVPrivNew (void) ; -static void ephyrXVPrivDelete (EphyrXVPriv *a_this) ; -static Bool ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; -static Bool ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ; -static Bool ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, - ScreenPtr a_screen) ; - -static Bool ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, - int a_attrs_len, - const char *a_attr_name, - int a_attr_value, - Bool *a_is_valid) ; - -static Bool ephyrXVPrivGetImageBufSize (int a_port_id, - int a_image_id, - unsigned short a_width, - unsigned short a_height, - int *a_size) ; - -static Bool ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv, - const unsigned char *a_image, - int a_image_len) ; - -static void ephyrStopVideo (KdScreenInfo *a_info, - pointer a_xv_priv, - Bool a_exit); - -static int ephyrSetPortAttribute (KdScreenInfo *a_info, - Atom a_attr_name, - int a_attr_value, - pointer a_port_priv); - -static int ephyrGetPortAttribute (KdScreenInfo *a_screen_info, - Atom a_attr_name, - int *a_attr_value, - pointer a_port_priv); - -static void ephyrQueryBestSize (KdScreenInfo *a_info, - Bool a_motion, - short a_src_w, - short a_src_h, - short a_drw_w, - short a_drw_h, - unsigned int *a_prefered_w, - unsigned int *a_prefered_h, - pointer a_port_priv); - -static int ephyrPutImage (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_src_x, - short a_src_y, - short a_drw_x, - short a_drw_y, - short a_src_w, - short a_src_h, - short a_drw_w, - short a_drw_h, - int a_id, - unsigned char *a_buf, - short a_width, - short a_height, - Bool a_sync, - RegionPtr a_clipping_region, - pointer a_port_priv); - -static int ephyrReputImage (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_drw_x, - short a_drw_y, - RegionPtr a_clipping_region, - pointer a_port_priv) ; - -static int ephyrPutVideo (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clip_region, - pointer a_port_priv) ; - -static int ephyrGetVideo (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clip_region, - pointer a_port_priv) ; - -static int ephyrPutStill (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clip_region, - pointer a_port_priv) ; - -static int ephyrGetStill (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clip_region, - pointer a_port_priv) ; - -static int ephyrQueryImageAttributes (KdScreenInfo *a_info, - int a_id, - unsigned short *a_w, - unsigned short *a_h, - int *a_pitches, - int *a_offsets); -static int s_base_port_id ; - -/************** - * <helpers> - * ************/ - -static Bool -DoSimpleClip (BoxPtr a_dst_box, - BoxPtr a_clipper, - BoxPtr a_result) -{ - BoxRec dstClippedBox ; - - EPHYR_RETURN_VAL_IF_FAIL (a_dst_box && a_clipper && a_result, FALSE) ; - - /* - * setup the clipbox inside the destination. - */ - dstClippedBox.x1 = a_dst_box->x1 ; - dstClippedBox.x2 = a_dst_box->x2 ; - dstClippedBox.y1 = a_dst_box->y1 ; - dstClippedBox.y2 = a_dst_box->y2 ; - - /* - * if the cliper leftmost edge is inside - * the destination area then the leftmost edge of the resulting - * clipped box is the leftmost edge of the cliper. - */ - if (a_clipper->x1 > dstClippedBox.x1) - dstClippedBox.x1 = a_clipper->x1 ; - - /* - * if the cliper top edge is inside the destination area - * then the bottom horizontal edge of the resulting clipped box - * is the bottom edge of the cliper - */ - if (a_clipper->y1 > dstClippedBox.y1) - dstClippedBox.y1 = a_clipper->y1 ; - - /*ditto for right edge*/ - if (a_clipper->x2 < dstClippedBox.x2) - dstClippedBox.x2 = a_clipper->x2 ; - - /*ditto for bottom edge*/ - if (a_clipper->y2 < dstClippedBox.y2) - dstClippedBox.y2 = a_clipper->y2 ; - - memcpy (a_result, &dstClippedBox, sizeof (dstClippedBox)) ; - return TRUE ; -} - -static Bool -ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) -{ - const char *atom_name=NULL; - int host_atom=None ; - - EPHYR_RETURN_VAL_IF_FAIL (a_host_atom, FALSE) ; - - if (!ValidAtom (a_local_atom)) - return FALSE ; - - atom_name = NameForAtom (a_local_atom) ; - - if (!atom_name) - return FALSE ; - - if (!ephyrHostGetAtom (atom_name, FALSE, &host_atom) || host_atom == None) { - EPHYR_LOG_ERROR ("no atom for string %s defined in host X\n", - atom_name) ; - return FALSE ; - } - *a_host_atom = host_atom ; - return TRUE ; -} - -/* - Not used yed. -static Bool -ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) -{ - Bool is_ok=FALSE ; - char *atom_name=NULL ; - int atom=None ; - - EPHYR_RETURN_VAL_IF_FAIL (a_local_atom, FALSE) ; - - atom_name = ephyrHostGetAtomName (a_host_atom) ; - if (!atom_name) - goto out ; - - atom = MakeAtom (atom_name, strlen (atom_name), TRUE) ; - if (atom == None) - goto out ; - - *a_local_atom = atom ; - is_ok = TRUE ; - -out: - if (atom_name) { - ephyrHostFree (atom_name) ; - } - return is_ok ; -} -*/ - -/************** - *</helpers> - * ************/ - -Bool -ephyrInitVideo (ScreenPtr pScreen) -{ - Bool is_ok = FALSE ; - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - static EphyrXVPriv *xv_priv; - - EPHYR_LOG ("enter\n") ; - - if (screen->fb.bitsPerPixel == 8) { - EPHYR_LOG_ERROR ("8 bits depth not supported\n") ; - return FALSE ; - } - - if (!xv_priv) { - xv_priv = ephyrXVPrivNew () ; - } - if (!xv_priv) { - EPHYR_LOG_ERROR ("failed to create xv_priv\n") ; - goto out ; - } - - if (!ephyrXVPrivRegisterAdaptors (xv_priv, pScreen)) { - EPHYR_LOG_ERROR ("failed to register adaptors\n") ; - goto out ; - } - is_ok = TRUE ; - -out: - return is_ok ; -} - -static EphyrXVPriv* -ephyrXVPrivNew (void) -{ - EphyrXVPriv *xv_priv=NULL ; - - EPHYR_LOG ("enter\n") ; - - xv_priv = xcalloc (1, sizeof (EphyrXVPriv)) ; - if (!xv_priv) { - EPHYR_LOG_ERROR ("failed to create EphyrXVPriv\n") ; - goto error ; - } - - ephyrHostXVInit () ; - - if (!ephyrXVPrivQueryHostAdaptors (xv_priv)) { - EPHYR_LOG_ERROR ("failed to query the host x for xv properties\n") ; - goto error ; - } - if (!ephyrXVPrivSetAdaptorsHooks (xv_priv)) { - EPHYR_LOG_ERROR ("failed to set xv_priv hooks\n") ; - goto error ; - } - - EPHYR_LOG ("leave\n") ; - return xv_priv ; - -error: - if (xv_priv) { - ephyrXVPrivDelete (xv_priv) ; - xv_priv = NULL ; - } - return NULL ; -} - -static void -ephyrXVPrivDelete (EphyrXVPriv *a_this) -{ - EPHYR_LOG ("enter\n") ; - - if (!a_this) - return ; - if (a_this->host_adaptors) { - ephyrHostXVAdaptorArrayDelete (a_this->host_adaptors) ; - a_this->host_adaptors = NULL ; - } - xfree (a_this->adaptors) ; - a_this->adaptors = NULL ; - xfree (a_this) ; - EPHYR_LOG ("leave\n") ; -} - -static KdVideoEncodingPtr -videoEncodingDup (EphyrHostEncoding *a_encodings, - int a_num_encodings) -{ - KdVideoEncodingPtr result = NULL ; - int i=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ; - - result = xcalloc (a_num_encodings, sizeof (KdVideoEncodingRec)) ; - for (i=0 ; i < a_num_encodings; i++) { - result[i].id = a_encodings[i].id ; - result[i].name = strdup (a_encodings[i].name) ; - result[i].width = a_encodings[i].width ; - result[i].height = a_encodings[i].height ; - result[i].rate.numerator = a_encodings[i].rate.numerator ; - result[i].rate.denominator = a_encodings[i].rate.denominator ; - } - return result ; -} - -static KdAttributePtr -portAttributesDup (EphyrHostAttribute *a_encodings, - int a_num_encodings) -{ - int i=0 ; - KdAttributePtr result=NULL ; - - EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ; - - result = xcalloc (a_num_encodings, sizeof (KdAttributeRec)) ; - if (!result) { - EPHYR_LOG_ERROR ("failed to allocate attributes\n") ; - return NULL ; - } - for (i=0; i < a_num_encodings; i++) { - result[i].flags = a_encodings[i].flags ; - result[i].min_value = a_encodings[i].min_value ; - result[i].max_value = a_encodings[i].max_value ; - result[i].name = strdup (a_encodings[i].name) ; - } - return result ; -} - -static Bool -ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) -{ - EphyrHostXVAdaptor *cur_host_adaptor=NULL ; - EphyrHostVideoFormat *video_formats=NULL ; - EphyrHostEncoding *encodings=NULL ; - EphyrHostAttribute *attributes=NULL ; - EphyrHostImageFormat *image_formats=NULL ; - int num_video_formats=0, base_port_id=0, - num_attributes=0, num_formats=0, i=0, - port_priv_offset=0; - unsigned num_encodings=0 ; - Bool is_ok = FALSE ; - - EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; - - EPHYR_LOG ("enter\n") ; - - if (!ephyrHostXVQueryAdaptors (&a_this->host_adaptors)) { - EPHYR_LOG_ERROR ("failed to query host adaptors\n") ; - goto out ; - } - if (a_this->host_adaptors) - a_this->num_adaptors = - ephyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; - if (a_this->num_adaptors < 0) { - EPHYR_LOG_ERROR ("failed to get number of host adaptors\n") ; - goto out ; - } - EPHYR_LOG ("host has %d adaptors\n", a_this->num_adaptors) ; - /* - * copy what we can from adaptors into a_this->adaptors - */ - if (a_this->num_adaptors) { - a_this->adaptors = xcalloc (a_this->num_adaptors, - sizeof (KdVideoAdaptorRec)) ; - if (!a_this->adaptors) { - EPHYR_LOG_ERROR ("failed to create internal adaptors\n") ; - goto out ; - } - } - for (i=0; i < a_this->num_adaptors; i++) { - int j=0 ; - cur_host_adaptor = - ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; - if (!cur_host_adaptor) - continue ; - a_this->adaptors[i].nPorts = - ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; - if (a_this->adaptors[i].nPorts <=0) { - EPHYR_LOG_ERROR ("Could not find any port of adaptor %d\n", i) ; - continue ; - } - a_this->adaptors[i].type = - ephyrHostXVAdaptorGetType (cur_host_adaptor) ; - a_this->adaptors[i].type |= XvWindowMask ; - a_this->adaptors[i].flags = - VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; - if (ephyrHostXVAdaptorGetName (cur_host_adaptor)) - a_this->adaptors[i].name = - strdup (ephyrHostXVAdaptorGetName (cur_host_adaptor)) ; - else - a_this->adaptors[i].name = strdup ("Xephyr Video Overlay"); - base_port_id = ephyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ; - if (base_port_id < 0) { - EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; - continue ; - } - if (!s_base_port_id) - s_base_port_id = base_port_id ; - - if (!ephyrHostXVQueryEncodings (base_port_id, - &encodings, - &num_encodings)) { - EPHYR_LOG_ERROR ("failed to get encodings for port port id %d," - " adaptors %d\n", - base_port_id, i) ; - continue ; - } - a_this->adaptors[i].nEncodings = num_encodings ; - a_this->adaptors[i].pEncodings = - videoEncodingDup (encodings, num_encodings) ; - video_formats = (EphyrHostVideoFormat*) - ephyrHostXVAdaptorGetVideoFormats (cur_host_adaptor, - &num_video_formats); - a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats ; - a_this->adaptors[i].nFormats = num_video_formats ; - /* got a_this->adaptors[i].nPorts already - a_this->adaptors[i].nPorts = - ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; - */ - a_this->adaptors[i].pPortPrivates = - xcalloc (a_this->adaptors[i].nPorts, - sizeof (DevUnion) + sizeof (EphyrPortPriv)) ; - port_priv_offset = a_this->adaptors[i].nPorts; - for (j=0; j < a_this->adaptors[i].nPorts; j++) { - EphyrPortPriv *port_privs_base = - (EphyrPortPriv*)&a_this->adaptors[i].pPortPrivates[port_priv_offset]; - EphyrPortPriv *port_priv = &port_privs_base[j] ; - port_priv->port_number = base_port_id + j; - port_priv->current_adaptor = &a_this->adaptors[i] ; - port_priv->xv_priv = a_this ; - a_this->adaptors[i].pPortPrivates[j].ptr = port_priv; - } - if (!ephyrHostXVQueryPortAttributes (base_port_id, - &attributes, - &num_attributes)) { - EPHYR_LOG_ERROR ("failed to get port attribute " - "for adaptor %d\n", i) ; - continue ; - } - a_this->adaptors[i].pAttributes = - portAttributesDup (attributes, num_attributes); - a_this->adaptors[i].nAttributes = num_attributes ; - /*make sure atoms of attrs names are created in xephyr*/ - for (j=0; j < a_this->adaptors[i].nAttributes; j++) { - if (a_this->adaptors[i].pAttributes[j].name) - MakeAtom (a_this->adaptors[i].pAttributes[j].name, - strlen (a_this->adaptors[i].pAttributes[j].name), - TRUE) ; - } - if (!ephyrHostXVQueryImageFormats (base_port_id, - &image_formats, - &num_formats)) { - EPHYR_LOG_ERROR ("failed to get image formats " - "for adaptor %d\n", i) ; - continue ; - } - a_this->adaptors[i].pImages = (KdImagePtr) image_formats ; - a_this->adaptors[i].nImages = num_formats ; - } - is_ok = TRUE ; - -out: - if (encodings) { - ephyrHostEncodingsDelete (encodings, num_encodings) ; - encodings = NULL ; - } - if (attributes) { - ephyrHostAttributesDelete (attributes) ; - attributes = NULL ; - } - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -static Bool -ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) -{ - int i=0 ; - Bool has_it=FALSE ; - EphyrHostXVAdaptor *cur_host_adaptor=NULL ; - - EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; - - EPHYR_LOG ("enter\n") ; - - for (i=0; i < a_this->num_adaptors; i++) { - a_this->adaptors[i].ReputImage = ephyrReputImage ; - a_this->adaptors[i].StopVideo = ephyrStopVideo ; - a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute ; - a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute ; - a_this->adaptors[i].QueryBestSize = ephyrQueryBestSize ; - a_this->adaptors[i].QueryImageAttributes = ephyrQueryImageAttributes ; - - cur_host_adaptor = - ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; - if (!cur_host_adaptor) { - EPHYR_LOG_ERROR ("failed to get host adaptor at index %d\n", i) ; - continue ; - } - has_it = FALSE ; - if (!ephyrHostXVAdaptorHasPutImage (cur_host_adaptor, &has_it)) { - EPHYR_LOG_ERROR ("error\n") ; - } - if (has_it) { - a_this->adaptors[i].PutImage = ephyrPutImage; - } - - has_it = FALSE ; - if (!ephyrHostXVAdaptorHasPutVideo (cur_host_adaptor, &has_it)) { - EPHYR_LOG_ERROR ("error\n") ; - } - if (has_it) { - a_this->adaptors[i].PutVideo = ephyrPutVideo; - } - - has_it = FALSE ; - if (!ephyrHostXVAdaptorHasGetVideo (cur_host_adaptor, &has_it)) { - EPHYR_LOG_ERROR ("error\n") ; - } - if (has_it) { - a_this->adaptors[i].GetVideo = ephyrGetVideo; - } - - has_it = FALSE ; - if (!ephyrHostXVAdaptorHasPutStill (cur_host_adaptor, &has_it)) { - EPHYR_LOG_ERROR ("error\n") ; - } - if (has_it) { - a_this->adaptors[i].PutStill = ephyrPutStill; - } - - has_it = FALSE ; - if (!ephyrHostXVAdaptorHasGetStill (cur_host_adaptor, &has_it)) { - EPHYR_LOG_ERROR ("error\n") ; - } - if (has_it) { - a_this->adaptors[i].GetStill = ephyrGetStill; - } - } - EPHYR_LOG ("leave\n") ; - return TRUE ; -} - -static Bool -ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, - ScreenPtr a_screen) -{ - KdScreenPriv(a_screen); - KdScreenInfo *screen = pScreenPriv->screen; - Bool is_ok = FALSE ; - KdVideoAdaptorPtr *adaptors=NULL, *registered_adaptors=NULL ; - int num_registered_adaptors=0, i=0, num_adaptors=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_this && a_screen, FALSE) ; - - EPHYR_LOG ("enter\n") ; - - if (!a_this->num_adaptors) - goto out ; - num_registered_adaptors = - KdXVListGenericAdaptors (screen, ®istered_adaptors); - - num_adaptors = num_registered_adaptors + a_this->num_adaptors ; - adaptors = xcalloc (num_adaptors, sizeof (KdVideoAdaptorPtr)) ; - if (!adaptors) { - EPHYR_LOG_ERROR ("failed to allocate adaptors tab\n") ; - goto out ; - } - memmove (adaptors, registered_adaptors, num_registered_adaptors) ; - for (i=0 ; i < a_this->num_adaptors; i++) { - *(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i] ; - } - if (!KdXVScreenInit (a_screen, adaptors, num_adaptors)) { - EPHYR_LOG_ERROR ("failed to register adaptors\n"); - goto out ; - } - EPHYR_LOG ("there are %d registered adaptors\n", num_adaptors) ; - is_ok = TRUE ; - -out: - xfree (registered_adaptors) ; - registered_adaptors = NULL ; - xfree (adaptors) ; - adaptors = NULL ; - - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -static Bool -ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, - int a_attrs_len, - const char *a_attr_name, - int a_attr_value, - Bool *a_is_valid) -{ - int i=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_attrs && a_attr_name && a_is_valid, - FALSE) ; - - for (i=0; i < a_attrs_len; i++) { - if (a_attrs[i].name && strcmp (a_attrs[i].name, a_attr_name)) - continue ; - if (a_attrs[i].min_value > a_attr_value || - a_attrs[i].max_value < a_attr_value) { - *a_is_valid = FALSE ; - EPHYR_LOG_ERROR ("attribute was not valid\n" - "value:%d. min:%d. max:%d\n", - a_attr_value, - a_attrs[i].min_value, - a_attrs[i].max_value) ; - } else { - *a_is_valid = TRUE ; - } - return TRUE ; - } - return FALSE ; -} - -static Bool -ephyrXVPrivGetImageBufSize (int a_port_id, - int a_image_id, - unsigned short a_width, - unsigned short a_height, - int *a_size) -{ - Bool is_ok=FALSE ; - unsigned short width=a_width, height=a_height ; - - EPHYR_RETURN_VAL_IF_FAIL (a_size, FALSE) ; - - EPHYR_LOG ("enter\n") ; - - if (!ephyrHostXVQueryImageAttributes (a_port_id, a_image_id, - &width, &height, a_size, NULL, NULL)) { - EPHYR_LOG_ERROR ("failed to get image attributes\n") ; - goto out ; - } - is_ok = TRUE ; - -out: - EPHYR_LOG ("leave\n") ; - return is_ok ; -} - -static Bool -ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv, - const unsigned char *a_image_buf, - int a_image_len) -{ - Bool is_ok=FALSE ; - - EPHYR_LOG ("enter\n") ; - - if (a_port_priv->image_buf_size < a_image_len) { - unsigned char *buf=NULL ; - buf = realloc (a_port_priv->image_buf, a_image_len) ; - if (!buf) { - EPHYR_LOG_ERROR ("failed to realloc image buffer\n") ; - goto out ; - } - a_port_priv->image_buf = buf ; - a_port_priv->image_buf_size = a_image_len; - } - memmove (a_port_priv->image_buf, a_image_buf, a_image_len) ; - is_ok = TRUE ; - -out: - return is_ok ; - EPHYR_LOG ("leave\n") ; -} - -static void -ephyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit) -{ - EphyrPortPriv *port_priv = a_port_priv ; - - EPHYR_RETURN_IF_FAIL (a_info && a_info->pScreen) ; - EPHYR_RETURN_IF_FAIL (port_priv) ; - - EPHYR_LOG ("enter\n") ; - if (!ephyrHostXVStopVideo (a_info->pScreen->myNum, - port_priv->port_number)) { - EPHYR_LOG_ERROR ("XvStopVideo() failed\n") ; - } - EPHYR_LOG ("leave\n") ; -} - -static int -ephyrSetPortAttribute (KdScreenInfo *a_info, - Atom a_attr_name, - int a_attr_value, - pointer a_port_priv) -{ - int res=Success, host_atom=0 ; - EphyrPortPriv *port_priv = a_port_priv ; - Bool is_attr_valid=FALSE ; - - EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; - EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor, BadMatch) ; - EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->pAttributes, - BadMatch) ; - EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->nAttributes, - BadMatch) ; - EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; - - EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n", - port_priv->port_number, - (int)a_attr_name, - NameForAtom (a_attr_name), - a_attr_value) ; - - if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) { - EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; - res = BadMatch ; - goto out ; - } - - if (!ephyrXVPrivIsAttrValueValid (port_priv->current_adaptor->pAttributes, - port_priv->current_adaptor->nAttributes, - NameForAtom (a_attr_name), - a_attr_value, - &is_attr_valid)) { - EPHYR_LOG_ERROR ("failed to validate attribute %s\n", - NameForAtom (a_attr_name)) ; - /* - res = BadMatch ; - goto out ; - */ - } - if (!is_attr_valid) { - EPHYR_LOG_ERROR ("attribute %s is not valid\n", - NameForAtom (a_attr_name)) ; - /* - res = BadMatch ; - goto out ; - */ - } - - if (!ephyrHostXVSetPortAttribute (port_priv->port_number, - host_atom, - a_attr_value)) { - EPHYR_LOG_ERROR ("failed to set port attribute\n") ; - res = BadMatch ; - goto out ; - } - - res = Success ; -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -static int -ephyrGetPortAttribute (KdScreenInfo *a_screen_info, - Atom a_attr_name, - int *a_attr_value, - pointer a_port_priv) -{ - int res=Success, host_atom=0 ; - EphyrPortPriv *port_priv = a_port_priv ; - - EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; - EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; - - EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s\n", - port_priv->port_number, - (int)a_attr_name, - NameForAtom (a_attr_name)) ; - - if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) { - EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; - res = BadMatch ; - goto out ; - } - - if (!ephyrHostXVGetPortAttribute (port_priv->port_number, - host_atom, - a_attr_value)) { - EPHYR_LOG_ERROR ("failed to get port attribute\n") ; - res = BadMatch ; - goto out ; - } - - res = Success ; -out: - EPHYR_LOG ("leave\n") ; - return res ; -} - -static void -ephyrQueryBestSize (KdScreenInfo *a_info, - Bool a_motion, - short a_src_w, - short a_src_h, - short a_drw_w, - short a_drw_h, - unsigned int *a_prefered_w, - unsigned int *a_prefered_h, - pointer a_port_priv) -{ - int res=0 ; - EphyrPortPriv *port_priv = a_port_priv ; - - EPHYR_RETURN_IF_FAIL (port_priv) ; - - EPHYR_LOG ("enter\n") ; - res = ephyrHostXVQueryBestSize (port_priv->port_number, - a_motion, - a_src_w, a_src_h, - a_drw_w, a_drw_h, - a_prefered_w, a_prefered_h) ; - if (!res) { - EPHYR_LOG_ERROR ("Failed to query best size\n") ; - } - EPHYR_LOG ("leave\n") ; -} - -static int -ephyrPutImage (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_src_x, - short a_src_y, - short a_drw_x, - short a_drw_y, - short a_src_w, - short a_src_h, - short a_drw_w, - short a_drw_h, - int a_id, - unsigned char *a_buf, - short a_width, - short a_height, - Bool a_sync, - RegionPtr a_clipping_region, - pointer a_port_priv) -{ - EphyrPortPriv *port_priv = a_port_priv ; - Bool is_ok=FALSE ; - int result=BadImplementation, image_size=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; - EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ; - - EPHYR_LOG ("enter\n") ; - - if (!ephyrHostXVPutImage (a_info->pScreen->myNum, - port_priv->port_number, - a_id, - a_drw_x, a_drw_y, a_drw_w, a_drw_h, - a_src_x, a_src_y, a_src_w, a_src_h, - a_width, a_height, a_buf, - (EphyrHostBox*)REGION_RECTS (a_clipping_region), - REGION_NUM_RECTS (a_clipping_region))) { - EPHYR_LOG_ERROR ("EphyrHostXVPutImage() failed\n") ; - goto out ; - } - - /* - * Now save the image so that we can resend it to host it - * later, in ReputImage. - */ - if (!ephyrXVPrivGetImageBufSize (port_priv->port_number, - a_id, a_width, a_height, &image_size)) { - EPHYR_LOG_ERROR ("failed to get image size\n") ; - /*this is a minor error so we won't get bail out abruptly*/ - is_ok = FALSE ; - } else { - is_ok = TRUE ; - } - if (is_ok) { - if (!ephyrXVPrivSaveImageToPortPriv (port_priv, a_buf, image_size)) { - is_ok=FALSE ; - } else { - port_priv->image_id = a_id; - port_priv->drw_x = a_drw_x; - port_priv->drw_y = a_drw_y; - port_priv->drw_w = a_drw_w ; - port_priv->drw_h = a_drw_h ; - port_priv->src_x = a_src_x; - port_priv->src_y = a_src_y ; - port_priv->src_w = a_src_w ; - port_priv->src_h = a_src_h ; - port_priv->image_width = a_width ; - port_priv->image_height = a_height ; - } - } - if (!is_ok) { - if (port_priv->image_buf) { - free (port_priv->image_buf) ; - port_priv->image_buf = NULL ; - port_priv->image_buf_size = 0 ; - } - } - - result = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return result ; -} - -static int -ephyrReputImage (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_drw_x, - short a_drw_y, - RegionPtr a_clipping_region, - pointer a_port_priv) -{ - EphyrPortPriv *port_priv = a_port_priv ; - int result=BadImplementation ; - - EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, FALSE) ; - EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; - - EPHYR_LOG ("enter\n") ; - - if (!port_priv->image_buf_size || !port_priv->image_buf) { - EPHYR_LOG_ERROR ("has null image buf in cache\n") ; - goto out ; - } - if (!ephyrHostXVPutImage (a_info->pScreen->myNum, - port_priv->port_number, - port_priv->image_id, - a_drw_x, a_drw_y, - port_priv->drw_w, port_priv->drw_h, - port_priv->src_x, port_priv->src_y, - port_priv->src_w, port_priv->src_h, - port_priv->image_width, port_priv->image_height, - port_priv->image_buf, - (EphyrHostBox*)REGION_RECTS (a_clipping_region), - REGION_NUM_RECTS (a_clipping_region))) { - EPHYR_LOG_ERROR ("ephyrHostXVPutImage() failed\n") ; - goto out ; - } - - result = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return result ; -} - -static int -ephyrPutVideo (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clipping_region, - pointer a_port_priv) -{ - EphyrPortPriv *port_priv = a_port_priv ; - BoxRec clipped_area, dst_box ; - int result=BadImplementation ; - int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, BadValue) ; - EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; - - EPHYR_LOG ("enter\n") ; - - dst_box.x1 = a_drw_x ; - dst_box.x2 = a_drw_x + a_drw_w; - dst_box.y1 = a_drw_y ; - dst_box.y2 = a_drw_y + a_drw_h; - - if (!DoSimpleClip (&dst_box, - REGION_EXTENTS (pScreen->pScreen, a_clipping_region), - &clipped_area)) { - EPHYR_LOG_ERROR ("failed to simple clip\n") ; - goto out ; - } - - drw_x = clipped_area.x1 ; - drw_y = clipped_area.y1 ; - drw_w = clipped_area.x2 - clipped_area.x1 ; - drw_h = clipped_area.y2 - clipped_area.y1 ; - - if (!ephyrHostXVPutVideo (a_info->pScreen->myNum, - port_priv->port_number, - a_vid_x, a_vid_y, a_vid_w, a_vid_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { - EPHYR_LOG_ERROR ("ephyrHostXVPutVideo() failed\n") ; - goto out ; - } - result = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return result ; -} - -static int -ephyrGetVideo (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clipping_region, - pointer a_port_priv) -{ - EphyrPortPriv *port_priv = a_port_priv ; - BoxRec clipped_area, dst_box ; - int result=BadImplementation ; - int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; - EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; - - EPHYR_LOG ("enter\n") ; - - dst_box.x1 = a_drw_x ; - dst_box.x2 = a_drw_x + a_drw_w; - dst_box.y1 = a_drw_y ; - dst_box.y2 = a_drw_y + a_drw_h; - - if (!DoSimpleClip (&dst_box, - REGION_EXTENTS (pScreen->pScreen, a_clipping_region), - &clipped_area)) { - EPHYR_LOG_ERROR ("failed to simple clip\n") ; - goto out ; - } - - drw_x = clipped_area.x1 ; - drw_y = clipped_area.y1 ; - drw_w = clipped_area.x2 - clipped_area.x1 ; - drw_h = clipped_area.y2 - clipped_area.y1 ; - - if (!ephyrHostXVGetVideo (a_info->pScreen->myNum, - port_priv->port_number, - a_vid_x, a_vid_y, a_vid_w, a_vid_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { - EPHYR_LOG_ERROR ("ephyrHostXVGetVideo() failed\n") ; - goto out ; - } - result = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return result ; -} - -static int -ephyrPutStill (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clipping_region, - pointer a_port_priv) -{ - EphyrPortPriv *port_priv = a_port_priv ; - BoxRec clipped_area, dst_box ; - int result=BadImplementation ; - int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; - EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; - - EPHYR_LOG ("enter\n") ; - - dst_box.x1 = a_drw_x ; - dst_box.x2 = a_drw_x + a_drw_w; - dst_box.y1 = a_drw_y ; - dst_box.y2 = a_drw_y + a_drw_h; - - if (!DoSimpleClip (&dst_box, - REGION_EXTENTS (pScreen->pScreen, a_clipping_region), - &clipped_area)) { - EPHYR_LOG_ERROR ("failed to simple clip\n") ; - goto out ; - } - - drw_x = clipped_area.x1 ; - drw_y = clipped_area.y1 ; - drw_w = clipped_area.x2 - clipped_area.x1 ; - drw_h = clipped_area.y2 - clipped_area.y1 ; - - if (!ephyrHostXVPutStill (a_info->pScreen->myNum, - port_priv->port_number, - a_vid_x, a_vid_y, a_vid_w, a_vid_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { - EPHYR_LOG_ERROR ("ephyrHostXVPutStill() failed\n") ; - goto out ; - } - result = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return result ; -} - -static int -ephyrGetStill (KdScreenInfo *a_info, - DrawablePtr a_drawable, - short a_vid_x, short a_vid_y, - short a_drw_x, short a_drw_y, - short a_vid_w, short a_vid_h, - short a_drw_w, short a_drw_h, - RegionPtr a_clipping_region, - pointer a_port_priv) -{ - EphyrPortPriv *port_priv = a_port_priv ; - BoxRec clipped_area, dst_box ; - int result=BadImplementation ; - int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; - EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; - - EPHYR_LOG ("enter\n") ; - - dst_box.x1 = a_drw_x ; - dst_box.x2 = a_drw_x + a_drw_w; - dst_box.y1 = a_drw_y ; - dst_box.y2 = a_drw_y + a_drw_h; - - if (!DoSimpleClip (&dst_box, - REGION_EXTENTS (pScreen->pScreen, a_clipping_region), - &clipped_area)) { - EPHYR_LOG_ERROR ("failed to simple clip\n") ; - goto out ; - } - - drw_x = clipped_area.x1 ; - drw_y = clipped_area.y1 ; - drw_w = clipped_area.x2 - clipped_area.x1 ; - drw_h = clipped_area.y2 - clipped_area.y1 ; - - if (!ephyrHostXVGetStill (a_info->pScreen->myNum, - port_priv->port_number, - a_vid_x, a_vid_y, a_vid_w, a_vid_h, - a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { - EPHYR_LOG_ERROR ("ephyrHostXVGetStill() failed\n") ; - goto out ; - } - result = Success ; - -out: - EPHYR_LOG ("leave\n") ; - return result ; -} - -static int -ephyrQueryImageAttributes (KdScreenInfo *a_info, - int a_id, - unsigned short *a_w, - unsigned short *a_h, - int *a_pitches, - int *a_offsets) -{ - int image_size=0 ; - - EPHYR_RETURN_VAL_IF_FAIL (a_w && a_h, FALSE) ; - - EPHYR_LOG ("enter: dim (%dx%d), pitches: %p, offsets: %p\n", - *a_w, *a_h, a_pitches, a_offsets) ; - - if (!ephyrHostXVQueryImageAttributes (s_base_port_id, - a_id, - a_w, a_h, - &image_size, - a_pitches, a_offsets)) { - EPHYR_LOG_ERROR ("EphyrHostXVQueryImageAttributes() failed\n") ; - goto out ; - } - EPHYR_LOG ("image size: %d, dim (%dx%d)\n", image_size, *a_w, *a_h) ; - -out: - EPHYR_LOG ("leave\n") ; - return image_size ; -} +/* + * Xephyr - A kdrive X server thats runs in a host X window. + * Authored by Matthew Allum <mallum@openedhand.com> + * + * Copyright © 2007 OpenedHand Ltd + * + * 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 OpenedHand Ltd not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OpenedHand Ltd makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OpenedHand Ltd 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: + * Dodji Seketeli <dodji@openedhand.com> + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include <string.h> +#include <X11/extensions/Xv.h> +#include "ephyrlog.h" +#include "kdrive.h" +#include "kxv.h" +#include "ephyr.h" +#include "hostx.h" +#include "ephyrhostvideo.h" + +struct _EphyrXVPriv { + EphyrHostXVAdaptorArray *host_adaptors ; + KdVideoAdaptorPtr adaptors ; + int num_adaptors ; +}; +typedef struct _EphyrXVPriv EphyrXVPriv ; + +struct _EphyrPortPriv { + int port_number ; + KdVideoAdaptorPtr current_adaptor ; + EphyrXVPriv *xv_priv; + unsigned char *image_buf ; + int image_buf_size ; + int image_id ; + int drw_x, drw_y, drw_w, drw_h ; + int src_x, src_y, src_w, src_h ; + int image_width, image_height ; +}; +typedef struct _EphyrPortPriv EphyrPortPriv ; + +static Bool DoSimpleClip (BoxPtr a_dst_drw, + BoxPtr a_clipper, + BoxPtr a_result) ; + +static Bool ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ; + +/* +static Bool ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ; +*/ + +static EphyrXVPriv* ephyrXVPrivNew (void) ; +static void ephyrXVPrivDelete (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ; +static Bool ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, + ScreenPtr a_screen) ; + +static Bool ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, + int a_attrs_len, + const char *a_attr_name, + int a_attr_value, + Bool *a_is_valid) ; + +static Bool ephyrXVPrivGetImageBufSize (int a_port_id, + int a_image_id, + unsigned short a_width, + unsigned short a_height, + int *a_size) ; + +static Bool ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv, + const unsigned char *a_image, + int a_image_len) ; + +static void ephyrStopVideo (KdScreenInfo *a_info, + pointer a_xv_priv, + Bool a_exit); + +static int ephyrSetPortAttribute (KdScreenInfo *a_info, + Atom a_attr_name, + int a_attr_value, + pointer a_port_priv); + +static int ephyrGetPortAttribute (KdScreenInfo *a_screen_info, + Atom a_attr_name, + int *a_attr_value, + pointer a_port_priv); + +static void ephyrQueryBestSize (KdScreenInfo *a_info, + Bool a_motion, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + unsigned int *a_prefered_w, + unsigned int *a_prefered_h, + pointer a_port_priv); + +static int ephyrPutImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_src_x, + short a_src_y, + short a_drw_x, + short a_drw_y, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + int a_id, + unsigned char *a_buf, + short a_width, + short a_height, + Bool a_sync, + RegionPtr a_clipping_region, + pointer a_port_priv); + +static int ephyrReputImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_drw_x, + short a_drw_y, + RegionPtr a_clipping_region, + pointer a_port_priv) ; + +static int ephyrPutVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrGetVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrPutStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrGetStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clip_region, + pointer a_port_priv) ; + +static int ephyrQueryImageAttributes (KdScreenInfo *a_info, + int a_id, + unsigned short *a_w, + unsigned short *a_h, + int *a_pitches, + int *a_offsets); +static int s_base_port_id ; + +/************** + * <helpers> + * ************/ + +static Bool +DoSimpleClip (BoxPtr a_dst_box, + BoxPtr a_clipper, + BoxPtr a_result) +{ + BoxRec dstClippedBox ; + + EPHYR_RETURN_VAL_IF_FAIL (a_dst_box && a_clipper && a_result, FALSE) ; + + /* + * setup the clipbox inside the destination. + */ + dstClippedBox.x1 = a_dst_box->x1 ; + dstClippedBox.x2 = a_dst_box->x2 ; + dstClippedBox.y1 = a_dst_box->y1 ; + dstClippedBox.y2 = a_dst_box->y2 ; + + /* + * if the cliper leftmost edge is inside + * the destination area then the leftmost edge of the resulting + * clipped box is the leftmost edge of the cliper. + */ + if (a_clipper->x1 > dstClippedBox.x1) + dstClippedBox.x1 = a_clipper->x1 ; + + /* + * if the cliper top edge is inside the destination area + * then the bottom horizontal edge of the resulting clipped box + * is the bottom edge of the cliper + */ + if (a_clipper->y1 > dstClippedBox.y1) + dstClippedBox.y1 = a_clipper->y1 ; + + /*ditto for right edge*/ + if (a_clipper->x2 < dstClippedBox.x2) + dstClippedBox.x2 = a_clipper->x2 ; + + /*ditto for bottom edge*/ + if (a_clipper->y2 < dstClippedBox.y2) + dstClippedBox.y2 = a_clipper->y2 ; + + memcpy (a_result, &dstClippedBox, sizeof (dstClippedBox)) ; + return TRUE ; +} + +static Bool +ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) +{ + const char *atom_name=NULL; + int host_atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_host_atom, FALSE) ; + + if (!ValidAtom (a_local_atom)) + return FALSE ; + + atom_name = NameForAtom (a_local_atom) ; + + if (!atom_name) + return FALSE ; + + if (!ephyrHostGetAtom (atom_name, FALSE, &host_atom) || host_atom == None) { + EPHYR_LOG_ERROR ("no atom for string %s defined in host X\n", + atom_name) ; + return FALSE ; + } + *a_host_atom = host_atom ; + return TRUE ; +} + +/* + Not used yed. +static Bool +ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) +{ + Bool is_ok=FALSE ; + char *atom_name=NULL ; + int atom=None ; + + EPHYR_RETURN_VAL_IF_FAIL (a_local_atom, FALSE) ; + + atom_name = ephyrHostGetAtomName (a_host_atom) ; + if (!atom_name) + goto out ; + + atom = MakeAtom (atom_name, strlen (atom_name), TRUE) ; + if (atom == None) + goto out ; + + *a_local_atom = atom ; + is_ok = TRUE ; + +out: + if (atom_name) { + ephyrHostFree (atom_name) ; + } + return is_ok ; +} +*/ + +/************** + *</helpers> + * ************/ + +Bool +ephyrInitVideo (ScreenPtr pScreen) +{ + Bool is_ok = FALSE ; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + static EphyrXVPriv *xv_priv; + + EPHYR_LOG ("enter\n") ; + + if (screen->fb.bitsPerPixel == 8) { + EPHYR_LOG_ERROR ("8 bits depth not supported\n") ; + return FALSE ; + } + + if (!xv_priv) { + xv_priv = ephyrXVPrivNew () ; + } + if (!xv_priv) { + EPHYR_LOG_ERROR ("failed to create xv_priv\n") ; + goto out ; + } + + if (!ephyrXVPrivRegisterAdaptors (xv_priv, pScreen)) { + EPHYR_LOG_ERROR ("failed to register adaptors\n") ; + goto out ; + } + is_ok = TRUE ; + +out: + return is_ok ; +} + +static EphyrXVPriv* +ephyrXVPrivNew (void) +{ + EphyrXVPriv *xv_priv=NULL ; + + EPHYR_LOG ("enter\n") ; + + xv_priv = calloc(1, sizeof (EphyrXVPriv)) ; + if (!xv_priv) { + EPHYR_LOG_ERROR ("failed to create EphyrXVPriv\n") ; + goto error ; + } + + ephyrHostXVInit () ; + + if (!ephyrXVPrivQueryHostAdaptors (xv_priv)) { + EPHYR_LOG_ERROR ("failed to query the host x for xv properties\n") ; + goto error ; + } + if (!ephyrXVPrivSetAdaptorsHooks (xv_priv)) { + EPHYR_LOG_ERROR ("failed to set xv_priv hooks\n") ; + goto error ; + } + + EPHYR_LOG ("leave\n") ; + return xv_priv ; + +error: + if (xv_priv) { + ephyrXVPrivDelete (xv_priv) ; + xv_priv = NULL ; + } + return NULL ; +} + +static void +ephyrXVPrivDelete (EphyrXVPriv *a_this) +{ + EPHYR_LOG ("enter\n") ; + + if (!a_this) + return ; + if (a_this->host_adaptors) { + ephyrHostXVAdaptorArrayDelete (a_this->host_adaptors) ; + a_this->host_adaptors = NULL ; + } + free(a_this->adaptors) ; + a_this->adaptors = NULL ; + free(a_this) ; + EPHYR_LOG ("leave\n") ; +} + +static KdVideoEncodingPtr +videoEncodingDup (EphyrHostEncoding *a_encodings, + int a_num_encodings) +{ + KdVideoEncodingPtr result = NULL ; + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ; + + result = calloc(a_num_encodings, sizeof (KdVideoEncodingRec)) ; + for (i=0 ; i < a_num_encodings; i++) { + result[i].id = a_encodings[i].id ; + result[i].name = strdup (a_encodings[i].name) ; + result[i].width = a_encodings[i].width ; + result[i].height = a_encodings[i].height ; + result[i].rate.numerator = a_encodings[i].rate.numerator ; + result[i].rate.denominator = a_encodings[i].rate.denominator ; + } + return result ; +} + +static KdAttributePtr +portAttributesDup (EphyrHostAttribute *a_encodings, + int a_num_encodings) +{ + int i=0 ; + KdAttributePtr result=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ; + + result = calloc(a_num_encodings, sizeof (KdAttributeRec)) ; + if (!result) { + EPHYR_LOG_ERROR ("failed to allocate attributes\n") ; + return NULL ; + } + for (i=0; i < a_num_encodings; i++) { + result[i].flags = a_encodings[i].flags ; + result[i].min_value = a_encodings[i].min_value ; + result[i].max_value = a_encodings[i].max_value ; + result[i].name = strdup (a_encodings[i].name) ; + } + return result ; +} + +static Bool +ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) +{ + EphyrHostXVAdaptor *cur_host_adaptor=NULL ; + EphyrHostVideoFormat *video_formats=NULL ; + EphyrHostEncoding *encodings=NULL ; + EphyrHostAttribute *attributes=NULL ; + EphyrHostImageFormat *image_formats=NULL ; + int num_video_formats=0, base_port_id=0, + num_attributes=0, num_formats=0, i=0, + port_priv_offset=0; + unsigned num_encodings=0 ; + Bool is_ok = FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostXVQueryAdaptors (&a_this->host_adaptors)) { + EPHYR_LOG_ERROR ("failed to query host adaptors\n") ; + goto out ; + } + if (a_this->host_adaptors) + a_this->num_adaptors = + ephyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ; + if (a_this->num_adaptors < 0) { + EPHYR_LOG_ERROR ("failed to get number of host adaptors\n") ; + goto out ; + } + EPHYR_LOG ("host has %d adaptors\n", a_this->num_adaptors) ; + /* + * copy what we can from adaptors into a_this->adaptors + */ + if (a_this->num_adaptors) { + a_this->adaptors = calloc(a_this->num_adaptors, + sizeof (KdVideoAdaptorRec)) ; + if (!a_this->adaptors) { + EPHYR_LOG_ERROR ("failed to create internal adaptors\n") ; + goto out ; + } + } + for (i=0; i < a_this->num_adaptors; i++) { + int j=0 ; + cur_host_adaptor = + ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; + if (!cur_host_adaptor) + continue ; + a_this->adaptors[i].nPorts = + ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + if (a_this->adaptors[i].nPorts <=0) { + EPHYR_LOG_ERROR ("Could not find any port of adaptor %d\n", i) ; + continue ; + } + a_this->adaptors[i].type = + ephyrHostXVAdaptorGetType (cur_host_adaptor) ; + a_this->adaptors[i].type |= XvWindowMask ; + a_this->adaptors[i].flags = + VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + if (ephyrHostXVAdaptorGetName (cur_host_adaptor)) + a_this->adaptors[i].name = + strdup (ephyrHostXVAdaptorGetName (cur_host_adaptor)) ; + else + a_this->adaptors[i].name = strdup ("Xephyr Video Overlay"); + base_port_id = ephyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ; + if (base_port_id < 0) { + EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ; + continue ; + } + if (!s_base_port_id) + s_base_port_id = base_port_id ; + + if (!ephyrHostXVQueryEncodings (base_port_id, + &encodings, + &num_encodings)) { + EPHYR_LOG_ERROR ("failed to get encodings for port port id %d," + " adaptors %d\n", + base_port_id, i) ; + continue ; + } + a_this->adaptors[i].nEncodings = num_encodings ; + a_this->adaptors[i].pEncodings = + videoEncodingDup (encodings, num_encodings) ; + video_formats = (EphyrHostVideoFormat*) + ephyrHostXVAdaptorGetVideoFormats (cur_host_adaptor, + &num_video_formats); + a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats ; + a_this->adaptors[i].nFormats = num_video_formats ; + /* got a_this->adaptors[i].nPorts already + a_this->adaptors[i].nPorts = + ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ; + */ + a_this->adaptors[i].pPortPrivates = + calloc(a_this->adaptors[i].nPorts, + sizeof (DevUnion) + sizeof (EphyrPortPriv)) ; + port_priv_offset = a_this->adaptors[i].nPorts; + for (j=0; j < a_this->adaptors[i].nPorts; j++) { + EphyrPortPriv *port_privs_base = + (EphyrPortPriv*)&a_this->adaptors[i].pPortPrivates[port_priv_offset]; + EphyrPortPriv *port_priv = &port_privs_base[j] ; + port_priv->port_number = base_port_id + j; + port_priv->current_adaptor = &a_this->adaptors[i] ; + port_priv->xv_priv = a_this ; + a_this->adaptors[i].pPortPrivates[j].ptr = port_priv; + } + if (!ephyrHostXVQueryPortAttributes (base_port_id, + &attributes, + &num_attributes)) { + EPHYR_LOG_ERROR ("failed to get port attribute " + "for adaptor %d\n", i) ; + continue ; + } + a_this->adaptors[i].pAttributes = + portAttributesDup (attributes, num_attributes); + a_this->adaptors[i].nAttributes = num_attributes ; + /*make sure atoms of attrs names are created in xephyr*/ + for (j=0; j < a_this->adaptors[i].nAttributes; j++) { + if (a_this->adaptors[i].pAttributes[j].name) + MakeAtom (a_this->adaptors[i].pAttributes[j].name, + strlen (a_this->adaptors[i].pAttributes[j].name), + TRUE) ; + } + if (!ephyrHostXVQueryImageFormats (base_port_id, + &image_formats, + &num_formats)) { + EPHYR_LOG_ERROR ("failed to get image formats " + "for adaptor %d\n", i) ; + continue ; + } + a_this->adaptors[i].pImages = (KdImagePtr) image_formats ; + a_this->adaptors[i].nImages = num_formats ; + } + is_ok = TRUE ; + +out: + if (encodings) { + ephyrHostEncodingsDelete (encodings, num_encodings) ; + encodings = NULL ; + } + if (attributes) { + ephyrHostAttributesDelete (attributes) ; + attributes = NULL ; + } + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) +{ + int i=0 ; + Bool has_it=FALSE ; + EphyrHostXVAdaptor *cur_host_adaptor=NULL ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + for (i=0; i < a_this->num_adaptors; i++) { + a_this->adaptors[i].ReputImage = ephyrReputImage ; + a_this->adaptors[i].StopVideo = ephyrStopVideo ; + a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute ; + a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute ; + a_this->adaptors[i].QueryBestSize = ephyrQueryBestSize ; + a_this->adaptors[i].QueryImageAttributes = ephyrQueryImageAttributes ; + + cur_host_adaptor = + ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ; + if (!cur_host_adaptor) { + EPHYR_LOG_ERROR ("failed to get host adaptor at index %d\n", i) ; + continue ; + } + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutImage (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].PutImage = ephyrPutImage; + } + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutVideo (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].PutVideo = ephyrPutVideo; + } + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasGetVideo (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].GetVideo = ephyrGetVideo; + } + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasPutStill (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].PutStill = ephyrPutStill; + } + + has_it = FALSE ; + if (!ephyrHostXVAdaptorHasGetStill (cur_host_adaptor, &has_it)) { + EPHYR_LOG_ERROR ("error\n") ; + } + if (has_it) { + a_this->adaptors[i].GetStill = ephyrGetStill; + } + } + EPHYR_LOG ("leave\n") ; + return TRUE ; +} + +static Bool +ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this, + ScreenPtr a_screen) +{ + KdScreenPriv(a_screen); + KdScreenInfo *screen = pScreenPriv->screen; + Bool is_ok = FALSE ; + KdVideoAdaptorPtr *adaptors=NULL, *registered_adaptors=NULL ; + int num_registered_adaptors=0, i=0, num_adaptors=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_this && a_screen, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!a_this->num_adaptors) + goto out ; + num_registered_adaptors = + KdXVListGenericAdaptors (screen, ®istered_adaptors); + + num_adaptors = num_registered_adaptors + a_this->num_adaptors ; + adaptors = calloc(num_adaptors, sizeof (KdVideoAdaptorPtr)) ; + if (!adaptors) { + EPHYR_LOG_ERROR ("failed to allocate adaptors tab\n") ; + goto out ; + } + memmove (adaptors, registered_adaptors, num_registered_adaptors) ; + for (i=0 ; i < a_this->num_adaptors; i++) { + *(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i] ; + } + if (!KdXVScreenInit (a_screen, adaptors, num_adaptors)) { + EPHYR_LOG_ERROR ("failed to register adaptors\n"); + goto out ; + } + EPHYR_LOG ("there are %d registered adaptors\n", num_adaptors) ; + is_ok = TRUE ; + +out: + free(registered_adaptors) ; + registered_adaptors = NULL ; + free(adaptors) ; + adaptors = NULL ; + + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs, + int a_attrs_len, + const char *a_attr_name, + int a_attr_value, + Bool *a_is_valid) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_attrs && a_attr_name && a_is_valid, + FALSE) ; + + for (i=0; i < a_attrs_len; i++) { + if (a_attrs[i].name && strcmp (a_attrs[i].name, a_attr_name)) + continue ; + if (a_attrs[i].min_value > a_attr_value || + a_attrs[i].max_value < a_attr_value) { + *a_is_valid = FALSE ; + EPHYR_LOG_ERROR ("attribute was not valid\n" + "value:%d. min:%d. max:%d\n", + a_attr_value, + a_attrs[i].min_value, + a_attrs[i].max_value) ; + } else { + *a_is_valid = TRUE ; + } + return TRUE ; + } + return FALSE ; +} + +static Bool +ephyrXVPrivGetImageBufSize (int a_port_id, + int a_image_id, + unsigned short a_width, + unsigned short a_height, + int *a_size) +{ + Bool is_ok=FALSE ; + unsigned short width=a_width, height=a_height ; + + EPHYR_RETURN_VAL_IF_FAIL (a_size, FALSE) ; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostXVQueryImageAttributes (a_port_id, a_image_id, + &width, &height, a_size, NULL, NULL)) { + EPHYR_LOG_ERROR ("failed to get image attributes\n") ; + goto out ; + } + is_ok = TRUE ; + +out: + EPHYR_LOG ("leave\n") ; + return is_ok ; +} + +static Bool +ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv, + const unsigned char *a_image_buf, + int a_image_len) +{ + Bool is_ok=FALSE ; + + EPHYR_LOG ("enter\n") ; + + if (a_port_priv->image_buf_size < a_image_len) { + unsigned char *buf=NULL ; + buf = realloc (a_port_priv->image_buf, a_image_len) ; + if (!buf) { + EPHYR_LOG_ERROR ("failed to realloc image buffer\n") ; + goto out ; + } + a_port_priv->image_buf = buf ; + a_port_priv->image_buf_size = a_image_len; + } + memmove (a_port_priv->image_buf, a_image_buf, a_image_len) ; + is_ok = TRUE ; + +out: + return is_ok ; + EPHYR_LOG ("leave\n") ; +} + +static void +ephyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit) +{ + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_IF_FAIL (a_info && a_info->pScreen) ; + EPHYR_RETURN_IF_FAIL (port_priv) ; + + EPHYR_LOG ("enter\n") ; + if (!ephyrHostXVStopVideo (a_info->pScreen->myNum, + port_priv->port_number)) { + EPHYR_LOG_ERROR ("XvStopVideo() failed\n") ; + } + EPHYR_LOG ("leave\n") ; +} + +static int +ephyrSetPortAttribute (KdScreenInfo *a_info, + Atom a_attr_name, + int a_attr_value, + pointer a_port_priv) +{ + int res=Success, host_atom=0 ; + EphyrPortPriv *port_priv = a_port_priv ; + Bool is_attr_valid=FALSE ; + + EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->pAttributes, + BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->nAttributes, + BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; + + EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n", + port_priv->port_number, + (int)a_attr_name, + NameForAtom (a_attr_name), + a_attr_value) ; + + if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) { + EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; + res = BadMatch ; + goto out ; + } + + if (!ephyrXVPrivIsAttrValueValid (port_priv->current_adaptor->pAttributes, + port_priv->current_adaptor->nAttributes, + NameForAtom (a_attr_name), + a_attr_value, + &is_attr_valid)) { + EPHYR_LOG_ERROR ("failed to validate attribute %s\n", + NameForAtom (a_attr_name)) ; + /* + res = BadMatch ; + goto out ; + */ + } + if (!is_attr_valid) { + EPHYR_LOG_ERROR ("attribute %s is not valid\n", + NameForAtom (a_attr_name)) ; + /* + res = BadMatch ; + goto out ; + */ + } + + if (!ephyrHostXVSetPortAttribute (port_priv->port_number, + host_atom, + a_attr_value)) { + EPHYR_LOG_ERROR ("failed to set port attribute\n") ; + res = BadMatch ; + goto out ; + } + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +static int +ephyrGetPortAttribute (KdScreenInfo *a_screen_info, + Atom a_attr_name, + int *a_attr_value, + pointer a_port_priv) +{ + int res=Success, host_atom=0 ; + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ; + EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ; + + EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s\n", + port_priv->port_number, + (int)a_attr_name, + NameForAtom (a_attr_name)) ; + + if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) { + EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ; + res = BadMatch ; + goto out ; + } + + if (!ephyrHostXVGetPortAttribute (port_priv->port_number, + host_atom, + a_attr_value)) { + EPHYR_LOG_ERROR ("failed to get port attribute\n") ; + res = BadMatch ; + goto out ; + } + + res = Success ; +out: + EPHYR_LOG ("leave\n") ; + return res ; +} + +static void +ephyrQueryBestSize (KdScreenInfo *a_info, + Bool a_motion, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + unsigned int *a_prefered_w, + unsigned int *a_prefered_h, + pointer a_port_priv) +{ + int res=0 ; + EphyrPortPriv *port_priv = a_port_priv ; + + EPHYR_RETURN_IF_FAIL (port_priv) ; + + EPHYR_LOG ("enter\n") ; + res = ephyrHostXVQueryBestSize (port_priv->port_number, + a_motion, + a_src_w, a_src_h, + a_drw_w, a_drw_h, + a_prefered_w, a_prefered_h) ; + if (!res) { + EPHYR_LOG_ERROR ("Failed to query best size\n") ; + } + EPHYR_LOG ("leave\n") ; +} + +static int +ephyrPutImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_src_x, + short a_src_y, + short a_drw_x, + short a_drw_y, + short a_src_w, + short a_src_h, + short a_drw_w, + short a_drw_h, + int a_id, + unsigned char *a_buf, + short a_width, + short a_height, + Bool a_sync, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + Bool is_ok=FALSE ; + int result=BadImplementation, image_size=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + if (!ephyrHostXVPutImage (a_info->pScreen->myNum, + port_priv->port_number, + a_id, + a_drw_x, a_drw_y, a_drw_w, a_drw_h, + a_src_x, a_src_y, a_src_w, a_src_h, + a_width, a_height, a_buf, + (EphyrHostBox*)REGION_RECTS (a_clipping_region), + REGION_NUM_RECTS (a_clipping_region))) { + EPHYR_LOG_ERROR ("EphyrHostXVPutImage() failed\n") ; + goto out ; + } + + /* + * Now save the image so that we can resend it to host it + * later, in ReputImage. + */ + if (!ephyrXVPrivGetImageBufSize (port_priv->port_number, + a_id, a_width, a_height, &image_size)) { + EPHYR_LOG_ERROR ("failed to get image size\n") ; + /*this is a minor error so we won't get bail out abruptly*/ + is_ok = FALSE ; + } else { + is_ok = TRUE ; + } + if (is_ok) { + if (!ephyrXVPrivSaveImageToPortPriv (port_priv, a_buf, image_size)) { + is_ok=FALSE ; + } else { + port_priv->image_id = a_id; + port_priv->drw_x = a_drw_x; + port_priv->drw_y = a_drw_y; + port_priv->drw_w = a_drw_w ; + port_priv->drw_h = a_drw_h ; + port_priv->src_x = a_src_x; + port_priv->src_y = a_src_y ; + port_priv->src_w = a_src_w ; + port_priv->src_h = a_src_h ; + port_priv->image_width = a_width ; + port_priv->image_height = a_height ; + } + } + if (!is_ok) { + if (port_priv->image_buf) { + free (port_priv->image_buf) ; + port_priv->image_buf = NULL ; + port_priv->image_buf_size = 0 ; + } + } + + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrReputImage (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_drw_x, + short a_drw_y, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + int result=BadImplementation ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, FALSE) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + if (!port_priv->image_buf_size || !port_priv->image_buf) { + EPHYR_LOG_ERROR ("has null image buf in cache\n") ; + goto out ; + } + if (!ephyrHostXVPutImage (a_info->pScreen->myNum, + port_priv->port_number, + port_priv->image_id, + a_drw_x, a_drw_y, + port_priv->drw_w, port_priv->drw_h, + port_priv->src_x, port_priv->src_y, + port_priv->src_w, port_priv->src_h, + port_priv->image_width, port_priv->image_height, + port_priv->image_buf, + (EphyrHostBox*)REGION_RECTS (a_clipping_region), + REGION_NUM_RECTS (a_clipping_region))) { + EPHYR_LOG_ERROR ("ephyrHostXVPutImage() failed\n") ; + goto out ; + } + + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrPutVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVPutVideo (a_info->pScreen->myNum, + port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVPutVideo() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrGetVideo (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVGetVideo (a_info->pScreen->myNum, + port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVGetVideo() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrPutStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVPutStill (a_info->pScreen->myNum, + port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVPutStill() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrGetStill (KdScreenInfo *a_info, + DrawablePtr a_drawable, + short a_vid_x, short a_vid_y, + short a_drw_x, short a_drw_y, + short a_vid_w, short a_vid_h, + short a_drw_w, short a_drw_h, + RegionPtr a_clipping_region, + pointer a_port_priv) +{ + EphyrPortPriv *port_priv = a_port_priv ; + BoxRec clipped_area, dst_box ; + int result=BadImplementation ; + int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ; + EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ; + + EPHYR_LOG ("enter\n") ; + + dst_box.x1 = a_drw_x ; + dst_box.x2 = a_drw_x + a_drw_w; + dst_box.y1 = a_drw_y ; + dst_box.y2 = a_drw_y + a_drw_h; + + if (!DoSimpleClip (&dst_box, + REGION_EXTENTS (pScreen->pScreen, a_clipping_region), + &clipped_area)) { + EPHYR_LOG_ERROR ("failed to simple clip\n") ; + goto out ; + } + + drw_x = clipped_area.x1 ; + drw_y = clipped_area.y1 ; + drw_w = clipped_area.x2 - clipped_area.x1 ; + drw_h = clipped_area.y2 - clipped_area.y1 ; + + if (!ephyrHostXVGetStill (a_info->pScreen->myNum, + port_priv->port_number, + a_vid_x, a_vid_y, a_vid_w, a_vid_h, + a_drw_x, a_drw_y, a_drw_w, a_drw_h)) { + EPHYR_LOG_ERROR ("ephyrHostXVGetStill() failed\n") ; + goto out ; + } + result = Success ; + +out: + EPHYR_LOG ("leave\n") ; + return result ; +} + +static int +ephyrQueryImageAttributes (KdScreenInfo *a_info, + int a_id, + unsigned short *a_w, + unsigned short *a_h, + int *a_pitches, + int *a_offsets) +{ + int image_size=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_w && a_h, FALSE) ; + + EPHYR_LOG ("enter: dim (%dx%d), pitches: %p, offsets: %p\n", + *a_w, *a_h, a_pitches, a_offsets) ; + + if (!ephyrHostXVQueryImageAttributes (s_base_port_id, + a_id, + a_w, a_h, + &image_size, + a_pitches, a_offsets)) { + EPHYR_LOG_ERROR ("EphyrHostXVQueryImageAttributes() failed\n") ; + goto out ; + } + EPHYR_LOG ("image size: %d, dim (%dx%d)\n", image_size, *a_w, *a_h) ; + +out: + EPHYR_LOG ("leave\n") ; + return image_size ; +} diff --git a/xorg-server/hw/kdrive/fake/fake.c b/xorg-server/hw/kdrive/fake/fake.c index 809e309a6..9f2327d94 100644 --- a/xorg-server/hw/kdrive/fake/fake.c +++ b/xorg-server/hw/kdrive/fake/fake.c @@ -1,476 +1,476 @@ -/* - * Copyright © 2004 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include "fake.h" - -extern int KdTsPhyScreen; - -Bool -fakeInitialize (KdCardInfo *card, FakePriv *priv) -{ - priv->base = 0; - priv->bytes_per_line = 0; - return TRUE; -} - -Bool -fakeCardInit (KdCardInfo *card) -{ - FakePriv *priv; - - priv = (FakePriv *) xalloc (sizeof (FakePriv)); - if (!priv) - return FALSE; - - if (!fakeInitialize (card, priv)) - { - xfree (priv); - return FALSE; - } - card->driver = priv; - - return TRUE; -} - -Bool -fakeScreenInitialize (KdScreenInfo *screen, FakeScrPriv *scrpriv) -{ - if (!screen->width || !screen->height) - { - screen->width = 1024; - screen->height = 768; - screen->rate = 72; - } - - if (screen->width <= 0) - screen->width = 1; - if (screen->height <= 0) - screen->height = 1; - - if (!screen->fb.depth) - screen->fb.depth = 16; - - if (screen->fb.depth <= 8) - { - screen->fb.visuals = ((1 << StaticGray) | - (1 << GrayScale) | - (1 << StaticColor) | - (1 << PseudoColor) | - (1 << TrueColor) | - (1 << DirectColor)); - } - else - { - screen->fb.visuals = (1 << TrueColor); -#define Mask(o,l) (((1 << l) - 1) << o) - if (screen->fb.depth <= 15) - { - screen->fb.depth = 15; - screen->fb.bitsPerPixel = 16; - screen->fb.redMask = Mask (10, 5); - screen->fb.greenMask = Mask (5, 5); - screen->fb.blueMask = Mask (0, 5); - } - else if (screen->fb.depth <= 16) - { - screen->fb.depth = 16; - screen->fb.bitsPerPixel = 16; - screen->fb.redMask = Mask (11, 5); - screen->fb.greenMask = Mask (5, 6); - screen->fb.blueMask = Mask (0, 5); - } - else - { - screen->fb.depth = 24; - screen->fb.bitsPerPixel = 32; - screen->fb.redMask = Mask (16, 8); - screen->fb.greenMask = Mask (8, 8); - screen->fb.blueMask = Mask (0, 8); - } - } - - scrpriv->randr = screen->randr; - - return fakeMapFramebuffer (screen); -} - -Bool -fakeScreenInit (KdScreenInfo *screen) -{ - FakeScrPriv *scrpriv; - - scrpriv = xcalloc (1, sizeof (FakeScrPriv)); - if (!scrpriv) - return FALSE; - screen->driver = scrpriv; - if (!fakeScreenInitialize (screen, scrpriv)) - { - screen->driver = 0; - xfree (scrpriv); - return FALSE; - } - return TRUE; -} - -void * -fakeWindowLinear (ScreenPtr pScreen, - CARD32 row, - CARD32 offset, - int mode, - CARD32 *size, - void *closure) -{ - KdScreenPriv(pScreen); - FakePriv *priv = pScreenPriv->card->driver; - - if (!pScreenPriv->enabled) - return 0; - *size = priv->bytes_per_line; - return priv->base + row * priv->bytes_per_line; -} - -Bool -fakeMapFramebuffer (KdScreenInfo *screen) -{ - FakeScrPriv *scrpriv = screen->driver; - KdPointerMatrix m; - FakePriv *priv = screen->card->driver; - - if (scrpriv->randr != RR_Rotate_0) - scrpriv->shadow = TRUE; - else - scrpriv->shadow = FALSE; - - KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); - - KdSetPointerMatrix (&m); - - priv->bytes_per_line = ((screen->width * screen->fb.bitsPerPixel + 31) >> 5) << 2; - if (priv->base) - free (priv->base); - priv->base = malloc (priv->bytes_per_line * screen->height); - - if (scrpriv->shadow) - { - if (!KdShadowFbAlloc (screen, scrpriv->randr & (RR_Rotate_90|RR_Rotate_270))) - return FALSE; - } - else - { - screen->fb.byteStride = priv->bytes_per_line; - screen->fb.pixelStride = (priv->bytes_per_line * 8/ - screen->fb.bitsPerPixel); - screen->fb.frameBuffer = (CARD8 *) (priv->base); - } - - return TRUE; -} - -void -fakeSetScreenSizes (ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - FakeScrPriv *scrpriv = screen->driver; - - if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) - { - pScreen->width = screen->width; - pScreen->height = screen->height; - pScreen->mmWidth = screen->width_mm; - pScreen->mmHeight = screen->height_mm; - } - else - { - pScreen->width = screen->width; - pScreen->height = screen->height; - pScreen->mmWidth = screen->height_mm; - pScreen->mmHeight = screen->width_mm; - } -} - -Bool -fakeUnmapFramebuffer (KdScreenInfo *screen) -{ - FakePriv *priv = screen->card->driver; - KdShadowFbFree (screen); - if (priv->base) - { - free (priv->base); - priv->base = 0; - } - return TRUE; -} - -Bool -fakeSetShadow (ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - FakeScrPriv *scrpriv = screen->driver; - ShadowUpdateProc update; - ShadowWindowProc window; - - window = fakeWindowLinear; - update = 0; - if (scrpriv->randr) - update = shadowUpdateRotatePacked; - else - update = shadowUpdatePacked; - return KdShadowSet (pScreen, scrpriv->randr, update, window); -} - - -#ifdef RANDR -Bool -fakeRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - FakeScrPriv *scrpriv = screen->driver; - RRScreenSizePtr pSize; - Rotation randr; - int n; - - *rotations = RR_Rotate_All|RR_Reflect_All; - - for (n = 0; n < pScreen->numDepths; n++) - if (pScreen->allowedDepths[n].numVids) - break; - if (n == pScreen->numDepths) - return FALSE; - - pSize = RRRegisterSize (pScreen, - screen->width, - screen->height, - screen->width_mm, - screen->height_mm); - - randr = KdSubRotation (scrpriv->randr, screen->randr); - - RRSetCurrentConfig (pScreen, randr, 0, pSize); - - return TRUE; -} - -Bool -fakeRandRSetConfig (ScreenPtr pScreen, - Rotation randr, - int rate, - RRScreenSizePtr pSize) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - FakeScrPriv *scrpriv = screen->driver; - Bool wasEnabled = pScreenPriv->enabled; - FakeScrPriv oldscr; - int oldwidth; - int oldheight; - int oldmmwidth; - int oldmmheight; - int newwidth, newheight; - - if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) - { - newwidth = pSize->width; - newheight = pSize->height; - } - else - { - newwidth = pSize->height; - newheight = pSize->width; - } - - if (wasEnabled) - KdDisableScreen (pScreen); - - oldscr = *scrpriv; - - oldwidth = screen->width; - oldheight = screen->height; - oldmmwidth = pScreen->mmWidth; - oldmmheight = pScreen->mmHeight; - - /* - * Set new configuration - */ - - scrpriv->randr = KdAddRotation (screen->randr, randr); - - fakeUnmapFramebuffer (screen); - - if (!fakeMapFramebuffer (screen)) - goto bail4; - - KdShadowUnset (screen->pScreen); - - if (!fakeSetShadow (screen->pScreen)) - goto bail4; - - fakeSetScreenSizes (screen->pScreen); - - /* - * Set frame buffer mapping - */ - (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), - pScreen->width, - pScreen->height, - screen->fb.depth, - screen->fb.bitsPerPixel, - screen->fb.byteStride, - screen->fb.frameBuffer); - - /* set the subpixel order */ - - KdSetSubpixelOrder (pScreen, scrpriv->randr); - if (wasEnabled) - KdEnableScreen (pScreen); - - return TRUE; - -bail4: - fakeUnmapFramebuffer (screen); - *scrpriv = oldscr; - (void) fakeMapFramebuffer (screen); - pScreen->width = oldwidth; - pScreen->height = oldheight; - pScreen->mmWidth = oldmmwidth; - pScreen->mmHeight = oldmmheight; - - if (wasEnabled) - KdEnableScreen (pScreen); - return FALSE; -} - -Bool -fakeRandRInit (ScreenPtr pScreen) -{ - rrScrPrivPtr pScrPriv; - - if (!RRScreenInit (pScreen)) - return FALSE; - - pScrPriv = rrGetScrPriv(pScreen); - pScrPriv->rrGetInfo = fakeRandRGetInfo; - pScrPriv->rrSetConfig = fakeRandRSetConfig; - return TRUE; -} -#endif - -Bool -fakeCreateColormap (ColormapPtr pmap) -{ - return fbInitializeColormap (pmap); -} - -Bool -fakeInitScreen (ScreenPtr pScreen) -{ -#ifdef TOUCHSCREEN - KdTsPhyScreen = pScreen->myNum; -#endif - - pScreen->CreateColormap = fakeCreateColormap; - return TRUE; -} - -Bool -fakeFinishInitScreen (ScreenPtr pScreen) -{ - if (!shadowSetup (pScreen)) - return FALSE; - -#ifdef RANDR - if (!fakeRandRInit (pScreen)) - return FALSE; -#endif - - return TRUE; -} - - -Bool -fakeCreateResources (ScreenPtr pScreen) -{ - return fakeSetShadow (pScreen); -} - -void -fakePreserve (KdCardInfo *card) -{ -} - -Bool -fakeEnable (ScreenPtr pScreen) -{ - return TRUE; -} - -Bool -fakeDPMS (ScreenPtr pScreen, int mode) -{ - return TRUE; -} - -void -fakeDisable (ScreenPtr pScreen) -{ -} - -void -fakeRestore (KdCardInfo *card) -{ -} - -void -fakeScreenFini (KdScreenInfo *screen) -{ -} - -void -fakeCardFini (KdCardInfo *card) -{ - FakePriv *priv = card->driver; - - free (priv->base); - xfree (priv); -} - -void -fakeGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs) -{ - while (n--) - { - pdefs->red = 0; - pdefs->green = 0; - pdefs->blue = 0; - pdefs++; - } -} - -void -fakePutColors (ScreenPtr pScreen, int n, xColorItem *pdefs) -{ -} +/* + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "fake.h" + +extern int KdTsPhyScreen; + +Bool +fakeInitialize (KdCardInfo *card, FakePriv *priv) +{ + priv->base = 0; + priv->bytes_per_line = 0; + return TRUE; +} + +Bool +fakeCardInit (KdCardInfo *card) +{ + FakePriv *priv; + + priv = (FakePriv *) malloc(sizeof (FakePriv)); + if (!priv) + return FALSE; + + if (!fakeInitialize (card, priv)) + { + free(priv); + return FALSE; + } + card->driver = priv; + + return TRUE; +} + +Bool +fakeScreenInitialize (KdScreenInfo *screen, FakeScrPriv *scrpriv) +{ + if (!screen->width || !screen->height) + { + screen->width = 1024; + screen->height = 768; + screen->rate = 72; + } + + if (screen->width <= 0) + screen->width = 1; + if (screen->height <= 0) + screen->height = 1; + + if (!screen->fb.depth) + screen->fb.depth = 16; + + if (screen->fb.depth <= 8) + { + screen->fb.visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)); + } + else + { + screen->fb.visuals = (1 << TrueColor); +#define Mask(o,l) (((1 << l) - 1) << o) + if (screen->fb.depth <= 15) + { + screen->fb.depth = 15; + screen->fb.bitsPerPixel = 16; + screen->fb.redMask = Mask (10, 5); + screen->fb.greenMask = Mask (5, 5); + screen->fb.blueMask = Mask (0, 5); + } + else if (screen->fb.depth <= 16) + { + screen->fb.depth = 16; + screen->fb.bitsPerPixel = 16; + screen->fb.redMask = Mask (11, 5); + screen->fb.greenMask = Mask (5, 6); + screen->fb.blueMask = Mask (0, 5); + } + else + { + screen->fb.depth = 24; + screen->fb.bitsPerPixel = 32; + screen->fb.redMask = Mask (16, 8); + screen->fb.greenMask = Mask (8, 8); + screen->fb.blueMask = Mask (0, 8); + } + } + + scrpriv->randr = screen->randr; + + return fakeMapFramebuffer (screen); +} + +Bool +fakeScreenInit (KdScreenInfo *screen) +{ + FakeScrPriv *scrpriv; + + scrpriv = calloc(1, sizeof (FakeScrPriv)); + if (!scrpriv) + return FALSE; + screen->driver = scrpriv; + if (!fakeScreenInitialize (screen, scrpriv)) + { + screen->driver = 0; + free(scrpriv); + return FALSE; + } + return TRUE; +} + +void * +fakeWindowLinear (ScreenPtr pScreen, + CARD32 row, + CARD32 offset, + int mode, + CARD32 *size, + void *closure) +{ + KdScreenPriv(pScreen); + FakePriv *priv = pScreenPriv->card->driver; + + if (!pScreenPriv->enabled) + return 0; + *size = priv->bytes_per_line; + return priv->base + row * priv->bytes_per_line; +} + +Bool +fakeMapFramebuffer (KdScreenInfo *screen) +{ + FakeScrPriv *scrpriv = screen->driver; + KdPointerMatrix m; + FakePriv *priv = screen->card->driver; + + if (scrpriv->randr != RR_Rotate_0) + scrpriv->shadow = TRUE; + else + scrpriv->shadow = FALSE; + + KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); + + KdSetPointerMatrix (&m); + + priv->bytes_per_line = ((screen->width * screen->fb.bitsPerPixel + 31) >> 5) << 2; + if (priv->base) + free (priv->base); + priv->base = malloc (priv->bytes_per_line * screen->height); + + if (scrpriv->shadow) + { + if (!KdShadowFbAlloc (screen, scrpriv->randr & (RR_Rotate_90|RR_Rotate_270))) + return FALSE; + } + else + { + screen->fb.byteStride = priv->bytes_per_line; + screen->fb.pixelStride = (priv->bytes_per_line * 8/ + screen->fb.bitsPerPixel); + screen->fb.frameBuffer = (CARD8 *) (priv->base); + } + + return TRUE; +} + +void +fakeSetScreenSizes (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FakeScrPriv *scrpriv = screen->driver; + + if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) + { + pScreen->width = screen->width; + pScreen->height = screen->height; + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + } + else + { + pScreen->width = screen->width; + pScreen->height = screen->height; + pScreen->mmWidth = screen->height_mm; + pScreen->mmHeight = screen->width_mm; + } +} + +Bool +fakeUnmapFramebuffer (KdScreenInfo *screen) +{ + FakePriv *priv = screen->card->driver; + KdShadowFbFree (screen); + if (priv->base) + { + free (priv->base); + priv->base = 0; + } + return TRUE; +} + +Bool +fakeSetShadow (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FakeScrPriv *scrpriv = screen->driver; + ShadowUpdateProc update; + ShadowWindowProc window; + + window = fakeWindowLinear; + update = 0; + if (scrpriv->randr) + update = shadowUpdateRotatePacked; + else + update = shadowUpdatePacked; + return KdShadowSet (pScreen, scrpriv->randr, update, window); +} + + +#ifdef RANDR +Bool +fakeRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FakeScrPriv *scrpriv = screen->driver; + RRScreenSizePtr pSize; + Rotation randr; + int n; + + *rotations = RR_Rotate_All|RR_Reflect_All; + + for (n = 0; n < pScreen->numDepths; n++) + if (pScreen->allowedDepths[n].numVids) + break; + if (n == pScreen->numDepths) + return FALSE; + + pSize = RRRegisterSize (pScreen, + screen->width, + screen->height, + screen->width_mm, + screen->height_mm); + + randr = KdSubRotation (scrpriv->randr, screen->randr); + + RRSetCurrentConfig (pScreen, randr, 0, pSize); + + return TRUE; +} + +Bool +fakeRandRSetConfig (ScreenPtr pScreen, + Rotation randr, + int rate, + RRScreenSizePtr pSize) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FakeScrPriv *scrpriv = screen->driver; + Bool wasEnabled = pScreenPriv->enabled; + FakeScrPriv oldscr; + int oldwidth; + int oldheight; + int oldmmwidth; + int oldmmheight; + int newwidth, newheight; + + if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) + { + newwidth = pSize->width; + newheight = pSize->height; + } + else + { + newwidth = pSize->height; + newheight = pSize->width; + } + + if (wasEnabled) + KdDisableScreen (pScreen); + + oldscr = *scrpriv; + + oldwidth = screen->width; + oldheight = screen->height; + oldmmwidth = pScreen->mmWidth; + oldmmheight = pScreen->mmHeight; + + /* + * Set new configuration + */ + + scrpriv->randr = KdAddRotation (screen->randr, randr); + + fakeUnmapFramebuffer (screen); + + if (!fakeMapFramebuffer (screen)) + goto bail4; + + KdShadowUnset (screen->pScreen); + + if (!fakeSetShadow (screen->pScreen)) + goto bail4; + + fakeSetScreenSizes (screen->pScreen); + + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); + + /* set the subpixel order */ + + KdSetSubpixelOrder (pScreen, scrpriv->randr); + if (wasEnabled) + KdEnableScreen (pScreen); + + return TRUE; + +bail4: + fakeUnmapFramebuffer (screen); + *scrpriv = oldscr; + (void) fakeMapFramebuffer (screen); + pScreen->width = oldwidth; + pScreen->height = oldheight; + pScreen->mmWidth = oldmmwidth; + pScreen->mmHeight = oldmmheight; + + if (wasEnabled) + KdEnableScreen (pScreen); + return FALSE; +} + +Bool +fakeRandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit (pScreen)) + return FALSE; + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = fakeRandRGetInfo; + pScrPriv->rrSetConfig = fakeRandRSetConfig; + return TRUE; +} +#endif + +Bool +fakeCreateColormap (ColormapPtr pmap) +{ + return fbInitializeColormap (pmap); +} + +Bool +fakeInitScreen (ScreenPtr pScreen) +{ +#ifdef TOUCHSCREEN + KdTsPhyScreen = pScreen->myNum; +#endif + + pScreen->CreateColormap = fakeCreateColormap; + return TRUE; +} + +Bool +fakeFinishInitScreen (ScreenPtr pScreen) +{ + if (!shadowSetup (pScreen)) + return FALSE; + +#ifdef RANDR + if (!fakeRandRInit (pScreen)) + return FALSE; +#endif + + return TRUE; +} + + +Bool +fakeCreateResources (ScreenPtr pScreen) +{ + return fakeSetShadow (pScreen); +} + +void +fakePreserve (KdCardInfo *card) +{ +} + +Bool +fakeEnable (ScreenPtr pScreen) +{ + return TRUE; +} + +Bool +fakeDPMS (ScreenPtr pScreen, int mode) +{ + return TRUE; +} + +void +fakeDisable (ScreenPtr pScreen) +{ +} + +void +fakeRestore (KdCardInfo *card) +{ +} + +void +fakeScreenFini (KdScreenInfo *screen) +{ +} + +void +fakeCardFini (KdCardInfo *card) +{ + FakePriv *priv = card->driver; + + free (priv->base); + free(priv); +} + +void +fakeGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs) +{ + while (n--) + { + pdefs->red = 0; + pdefs->green = 0; + pdefs->blue = 0; + pdefs++; + } +} + +void +fakePutColors (ScreenPtr pScreen, int n, xColorItem *pdefs) +{ +} diff --git a/xorg-server/hw/kdrive/fbdev/fbdev.c b/xorg-server/hw/kdrive/fbdev/fbdev.c index d4604ad29..b127ab89b 100644 --- a/xorg-server/hw/kdrive/fbdev/fbdev.c +++ b/xorg-server/hw/kdrive/fbdev/fbdev.c @@ -1,826 +1,826 @@ -/* - * Copyright © 1999 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include "fbdev.h" -#include <sys/ioctl.h> - -#include <errno.h> - -extern int KdTsPhyScreen; - -char *fbdevDevicePath = NULL; - -static Bool -fbdevInitialize (KdCardInfo *card, FbdevPriv *priv) -{ - unsigned long off; - - if (fbdevDevicePath == NULL) - fbdevDevicePath = "/dev/fb0"; - - if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0) - { - ErrorF("Error opening framebuffer %s: %s\n", - fbdevDevicePath, strerror(errno)); - return FALSE; - } - - /* quiet valgrind */ - memset (&priv->fix, '\0', sizeof (priv->fix)); - if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) { - perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO"); - close (priv->fd); - return FALSE; - } - /* quiet valgrind */ - memset (&priv->var, '\0', sizeof (priv->var)); - if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) { - perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO"); - close (priv->fd); - return FALSE; - } - - priv->fb_base = (char *) mmap ((caddr_t) NULL, - priv->fix.smem_len, - PROT_READ|PROT_WRITE, - MAP_SHARED, - priv->fd, 0); - - if (priv->fb_base == (char *)-1) - { - perror("ERROR: mmap framebuffer fails!"); - close (priv->fd); - return FALSE; - } - off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize(); - priv->fb = priv->fb_base + off; - return TRUE; -} - -Bool -fbdevCardInit (KdCardInfo *card) -{ - FbdevPriv *priv; - - priv = (FbdevPriv *) xalloc (sizeof (FbdevPriv)); - if (!priv) - return FALSE; - - if (!fbdevInitialize (card, priv)) - { - xfree (priv); - return FALSE; - } - card->driver = priv; - - return TRUE; -} - -static Pixel -fbdevMakeContig (Pixel orig, Pixel others) -{ - Pixel low; - - low = lowbit (orig) >> 1; - while (low && (others & low) == 0) - { - orig |= low; - low >>= 1; - } - return orig; -} - -static Bool -fbdevModeSupported (KdScreenInfo *screen, - const KdMonitorTiming *t) -{ - return TRUE; -} - -static void -fbdevConvertMonitorTiming (const KdMonitorTiming *t, struct fb_var_screeninfo *var) -{ - memset (var, 0, sizeof (struct fb_var_screeninfo)); - - var->xres = t->horizontal; - var->yres = t->vertical; - var->xres_virtual = t->horizontal; - var->yres_virtual = t->vertical; - var->xoffset = 0; - var->yoffset = 0; - var->pixclock = t->clock ? 1000000000 / t->clock : 0; - var->left_margin = t->hbp; - var->right_margin = t->hfp; - var->upper_margin = t->vbp; - var->lower_margin = t->vfp; - var->hsync_len = t->hblank - t->hfp - t->hbp; - var->vsync_len = t->vblank - t->vfp - t->vbp; - - var->sync = 0; - var->vmode = 0; - - if (t->hpol == KdSyncPositive) - var->sync |= FB_SYNC_HOR_HIGH_ACT; - if (t->vpol == KdSyncPositive) - var->sync |= FB_SYNC_VERT_HIGH_ACT; -} - -static Bool -fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv) -{ - FbdevPriv *priv = screen->card->driver; - Pixel allbits; - int depth; - Bool gray; - struct fb_var_screeninfo var; - const KdMonitorTiming *t; - int k; - - k = ioctl (priv->fd, FBIOGET_VSCREENINFO, &var); - - if (!screen->width || !screen->height) - { - if (k >= 0) - { - screen->width = var.xres; - screen->height = var.yres; - } - else - { - screen->width = 1024; - screen->height = 768; - } - screen->rate = 103; /* FIXME: should get proper value from fb driver */ - } - if (!screen->fb.depth) - { - if (k >= 0) - screen->fb.depth = var.bits_per_pixel; - else - screen->fb.depth = 16; - } - - if ((screen->width != var.xres) || (screen->height != var.yres)) - { - t = KdFindMode (screen, fbdevModeSupported); - screen->rate = t->rate; - screen->width = t->horizontal; - screen->height = t->vertical; - - /* Now try setting the mode */ - if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres)) - fbdevConvertMonitorTiming (t, &var); - } - - var.activate = FB_ACTIVATE_NOW; - var.bits_per_pixel = screen->fb.depth; - var.nonstd = 0; - var.grayscale = 0; - - k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &var); - - if (k < 0) - { - fprintf (stderr, "error: %s\n", strerror (errno)); - return FALSE; - } - - /* Re-get the "fixed" parameters since they might have changed */ - k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix); - if (k < 0) - perror ("FBIOGET_FSCREENINFO"); - - /* Now get the new screeninfo */ - ioctl (priv->fd, FBIOGET_VSCREENINFO, &priv->var); - depth = priv->var.bits_per_pixel; - gray = priv->var.grayscale; - - switch (priv->fix.visual) { - case FB_VISUAL_PSEUDOCOLOR: - if (gray) - { - screen->fb.visuals = (1 << StaticGray); - /* could also support GrayScale, but what's the point? */ - } - else - { - screen->fb.visuals = ((1 << StaticGray) | - (1 << GrayScale) | - (1 << StaticColor) | - (1 << PseudoColor) | - (1 << TrueColor) | - (1 << DirectColor)); - } - screen->fb.blueMask = 0x00; - screen->fb.greenMask = 0x00; - screen->fb.redMask = 0x00; - break; - case FB_VISUAL_STATIC_PSEUDOCOLOR: - if (gray) - { - screen->fb.visuals = (1 << StaticGray); - } - else - { - screen->fb.visuals = (1 << StaticColor); - } - screen->fb.blueMask = 0x00; - screen->fb.greenMask = 0x00; - screen->fb.redMask = 0x00; - break; - case FB_VISUAL_TRUECOLOR: - case FB_VISUAL_DIRECTCOLOR: - screen->fb.visuals = (1 << TrueColor); -#define Mask(o,l) (((1 << l) - 1) << o) - screen->fb.redMask = Mask (priv->var.red.offset, priv->var.red.length); - screen->fb.greenMask = Mask (priv->var.green.offset, priv->var.green.length); - screen->fb.blueMask = Mask (priv->var.blue.offset, priv->var.blue.length); - - /* - * This is a kludge so that Render will work -- fill in the gaps - * in the pixel - */ - screen->fb.redMask = fbdevMakeContig (screen->fb.redMask, - screen->fb.greenMask| - screen->fb.blueMask); - - screen->fb.greenMask = fbdevMakeContig (screen->fb.greenMask, - screen->fb.redMask| - screen->fb.blueMask); - - screen->fb.blueMask = fbdevMakeContig (screen->fb.blueMask, - screen->fb.redMask| - screen->fb.greenMask); - - allbits = screen->fb.redMask | screen->fb.greenMask | screen->fb.blueMask; - depth = 32; - while (depth && !(allbits & (1 << (depth - 1)))) - depth--; - break; - default: - return FALSE; - break; - } - screen->fb.depth = depth; - screen->fb.bitsPerPixel = priv->var.bits_per_pixel; - - scrpriv->randr = screen->randr; - - return fbdevMapFramebuffer (screen); -} - -Bool -fbdevScreenInit (KdScreenInfo *screen) -{ - FbdevScrPriv *scrpriv; - - scrpriv = xcalloc (1, sizeof (FbdevScrPriv)); - if (!scrpriv) - return FALSE; - screen->driver = scrpriv; - if (!fbdevScreenInitialize (screen, scrpriv)) - { - screen->driver = 0; - xfree (scrpriv); - return FALSE; - } - return TRUE; -} - -static void * -fbdevWindowLinear (ScreenPtr pScreen, - CARD32 row, - CARD32 offset, - int mode, - CARD32 *size, - void *closure) -{ - KdScreenPriv(pScreen); - FbdevPriv *priv = pScreenPriv->card->driver; - - if (!pScreenPriv->enabled) - return 0; - *size = priv->fix.line_length; - return (CARD8 *) priv->fb + row * priv->fix.line_length + offset; -} - -Bool -fbdevMapFramebuffer (KdScreenInfo *screen) -{ - FbdevScrPriv *scrpriv = screen->driver; - KdPointerMatrix m; - FbdevPriv *priv = screen->card->driver; - - if (scrpriv->randr != RR_Rotate_0) - scrpriv->shadow = TRUE; - else - scrpriv->shadow = FALSE; - - KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); - - KdSetPointerMatrix (&m); - - screen->width = priv->var.xres; - screen->height = priv->var.yres; - - if (scrpriv->shadow) - { - if (!KdShadowFbAlloc (screen, - scrpriv->randr & (RR_Rotate_90|RR_Rotate_270))) - return FALSE; - } - else - { - screen->fb.byteStride = priv->fix.line_length; - screen->fb.pixelStride = (priv->fix.line_length * 8 / - priv->var.bits_per_pixel); - screen->fb.frameBuffer = (CARD8 *) (priv->fb); - } - - return TRUE; -} - -static void -fbdevSetScreenSizes (ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - FbdevScrPriv *scrpriv = screen->driver; - FbdevPriv *priv = screen->card->driver; - - if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) - { - pScreen->width = priv->var.xres; - pScreen->height = priv->var.yres; - pScreen->mmWidth = screen->width_mm; - pScreen->mmHeight = screen->height_mm; - } - else - { - pScreen->width = priv->var.yres; - pScreen->height = priv->var.xres; - pScreen->mmWidth = screen->height_mm; - pScreen->mmHeight = screen->width_mm; - } -} - -static Bool -fbdevUnmapFramebuffer (KdScreenInfo *screen) -{ - KdShadowFbFree (screen); - return TRUE; -} - -static Bool -fbdevSetShadow (ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - FbdevScrPriv *scrpriv = screen->driver; - FbdevPriv *priv = screen->card->driver; - ShadowUpdateProc update; - ShadowWindowProc window; - int useYX = 0; - -#ifdef __arm__ - /* Use variant copy routines that always read left to right in the - shadow framebuffer. Reading vertical strips is exceptionally - slow on XScale due to cache effects. */ - useYX = 1; -#endif - - window = fbdevWindowLinear; - update = 0; - if (scrpriv->randr) - if (priv->var.bits_per_pixel == 16) { - switch (scrpriv->randr) { - case RR_Rotate_90: - if (useYX) - update = shadowUpdateRotate16_90YX; - else - update = shadowUpdateRotate16_90; - break; - case RR_Rotate_180: - update = shadowUpdateRotate16_180; - break; - case RR_Rotate_270: - if (useYX) - update = shadowUpdateRotate16_270YX; - else - update = shadowUpdateRotate16_270; - break; - default: - update = shadowUpdateRotate16; - break; - } - } else - update = shadowUpdateRotatePacked; - else - update = shadowUpdatePacked; - return KdShadowSet (pScreen, scrpriv->randr, update, window); -} - - -#ifdef RANDR -static Bool -fbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - FbdevScrPriv *scrpriv = screen->driver; - RRScreenSizePtr pSize; - Rotation randr; - int n; - - *rotations = RR_Rotate_All|RR_Reflect_All; - - for (n = 0; n < pScreen->numDepths; n++) - if (pScreen->allowedDepths[n].numVids) - break; - if (n == pScreen->numDepths) - return FALSE; - - pSize = RRRegisterSize (pScreen, - screen->width, - screen->height, - screen->width_mm, - screen->height_mm); - - randr = KdSubRotation (scrpriv->randr, screen->randr); - - RRSetCurrentConfig (pScreen, randr, 0, pSize); - - return TRUE; -} - -static Bool -fbdevRandRSetConfig (ScreenPtr pScreen, - Rotation randr, - int rate, - RRScreenSizePtr pSize) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - FbdevScrPriv *scrpriv = screen->driver; - Bool wasEnabled = pScreenPriv->enabled; - FbdevScrPriv oldscr; - int oldwidth; - int oldheight; - int oldmmwidth; - int oldmmheight; - int newwidth, newheight; - - if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) - { - newwidth = pSize->width; - newheight = pSize->height; - } - else - { - newwidth = pSize->height; - newheight = pSize->width; - } - - if (wasEnabled) - KdDisableScreen (pScreen); - - oldscr = *scrpriv; - - oldwidth = screen->width; - oldheight = screen->height; - oldmmwidth = pScreen->mmWidth; - oldmmheight = pScreen->mmHeight; - - /* - * Set new configuration - */ - - scrpriv->randr = KdAddRotation (screen->randr, randr); - - fbdevUnmapFramebuffer (screen); - - if (!fbdevMapFramebuffer (screen)) - goto bail4; - - KdShadowUnset (screen->pScreen); - - if (!fbdevSetShadow (screen->pScreen)) - goto bail4; - - fbdevSetScreenSizes (screen->pScreen); - - /* - * Set frame buffer mapping - */ - (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), - pScreen->width, - pScreen->height, - screen->fb.depth, - screen->fb.bitsPerPixel, - screen->fb.byteStride, - screen->fb.frameBuffer); - - /* set the subpixel order */ - - KdSetSubpixelOrder (pScreen, scrpriv->randr); - if (wasEnabled) - KdEnableScreen (pScreen); - - return TRUE; - -bail4: - fbdevUnmapFramebuffer (screen); - *scrpriv = oldscr; - (void) fbdevMapFramebuffer (screen); - pScreen->width = oldwidth; - pScreen->height = oldheight; - pScreen->mmWidth = oldmmwidth; - pScreen->mmHeight = oldmmheight; - - if (wasEnabled) - KdEnableScreen (pScreen); - return FALSE; -} - -static Bool -fbdevRandRInit (ScreenPtr pScreen) -{ - rrScrPrivPtr pScrPriv; - - if (!RRScreenInit (pScreen)) - return FALSE; - - pScrPriv = rrGetScrPriv(pScreen); - pScrPriv->rrGetInfo = fbdevRandRGetInfo; - pScrPriv->rrSetConfig = fbdevRandRSetConfig; - return TRUE; -} -#endif - -static Bool -fbdevCreateColormap (ColormapPtr pmap) -{ - ScreenPtr pScreen = pmap->pScreen; - KdScreenPriv(pScreen); - FbdevPriv *priv = pScreenPriv->card->driver; - VisualPtr pVisual; - int i; - int nent; - xColorItem *pdefs; - - switch (priv->fix.visual) { - case FB_VISUAL_STATIC_PSEUDOCOLOR: - pVisual = pmap->pVisual; - nent = pVisual->ColormapEntries; - pdefs = xalloc (nent * sizeof (xColorItem)); - if (!pdefs) - return FALSE; - for (i = 0; i < nent; i++) - pdefs[i].pixel = i; - fbdevGetColors (pScreen, nent, pdefs); - for (i = 0; i < nent; i++) - { - pmap->red[i].co.local.red = pdefs[i].red; - pmap->red[i].co.local.green = pdefs[i].green; - pmap->red[i].co.local.blue = pdefs[i].blue; - } - xfree (pdefs); - return TRUE; - default: - return fbInitializeColormap (pmap); - } -} - -Bool -fbdevInitScreen (ScreenPtr pScreen) -{ -#ifdef TOUCHSCREEN - KdTsPhyScreen = pScreen->myNum; -#endif - - pScreen->CreateColormap = fbdevCreateColormap; - return TRUE; -} - -Bool -fbdevFinishInitScreen (ScreenPtr pScreen) -{ - if (!shadowSetup (pScreen)) - return FALSE; - -#ifdef RANDR - if (!fbdevRandRInit (pScreen)) - return FALSE; -#endif - - return TRUE; -} - - -Bool -fbdevCreateResources (ScreenPtr pScreen) -{ - return fbdevSetShadow (pScreen); -} - -void -fbdevPreserve (KdCardInfo *card) -{ -} - -static int -fbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx) -{ - struct fb_cmap cmap; - - cmap.start = minidx; - cmap.len = maxidx - minidx + 1; - cmap.red = &priv->red[minidx]; - cmap.green = &priv->green[minidx]; - cmap.blue = &priv->blue[minidx]; - cmap.transp = 0; - - return ioctl(priv->fd, FBIOPUTCMAP, &cmap); -} - -Bool -fbdevEnable (ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - FbdevPriv *priv = pScreenPriv->card->driver; - int k; - - priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL; - - /* display it on the LCD */ - k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var); - if (k < 0) - { - perror ("FBIOPUT_VSCREENINFO"); - return FALSE; - } - - if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR) - { - int i; - - for (i = 0; - i < (1 << priv->var.red.length) || - i < (1 << priv->var.green.length) || - i < (1 << priv->var.blue.length); i++) - { - priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1); - priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1); - priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1); - } - - fbdevUpdateFbColormap(priv, 0, i); - } - return TRUE; -} - -Bool -fbdevDPMS (ScreenPtr pScreen, int mode) -{ - KdScreenPriv(pScreen); - FbdevPriv *priv = pScreenPriv->card->driver; - static int oldmode = -1; - - if (mode == oldmode) - return TRUE; -#ifdef FBIOPUT_POWERMODE - if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0) - { - oldmode = mode; - return TRUE; - } -#endif -#ifdef FBIOBLANK - if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0) - { - oldmode = mode; - return TRUE; - } -#endif - return FALSE; -} - -void -fbdevDisable (ScreenPtr pScreen) -{ -} - -void -fbdevRestore (KdCardInfo *card) -{ -} - -void -fbdevScreenFini (KdScreenInfo *screen) -{ -} - -void -fbdevCardFini (KdCardInfo *card) -{ - FbdevPriv *priv = card->driver; - - munmap (priv->fb_base, priv->fix.smem_len); - close (priv->fd); - xfree (priv); -} - -/* - * Retrieve actual colormap and return selected n entries in pdefs. - */ -void -fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs) -{ - KdScreenPriv(pScreen); - FbdevPriv *priv = pScreenPriv->card->driver; - struct fb_cmap cmap; - int p; - int k; - int min, max; - - min = 256; - max = 0; - for (k = 0; k < n; k++) - { - if (pdefs[k].pixel < min) - min = pdefs[k].pixel; - if (pdefs[k].pixel > max) - max = pdefs[k].pixel; - } - cmap.start = min; - cmap.len = max - min + 1; - cmap.red = &priv->red[min]; - cmap.green = &priv->green[min]; - cmap.blue = &priv->blue[min]; - cmap.transp = 0; - k = ioctl (priv->fd, FBIOGETCMAP, &cmap); - if (k < 0) - { - perror ("can't get colormap"); - return; - } - while (n--) - { - p = pdefs->pixel; - pdefs->red = priv->red[p]; - pdefs->green = priv->green[p]; - pdefs->blue = priv->blue[p]; - pdefs++; - } -} - -/* - * Change colormap by updating n entries described in pdefs. - */ -void -fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs) -{ - KdScreenPriv(pScreen); - FbdevPriv *priv = pScreenPriv->card->driver; - int p; - int min, max; - - min = 256; - max = 0; - while (n--) - { - p = pdefs->pixel; - priv->red[p] = pdefs->red; - priv->green[p] = pdefs->green; - priv->blue[p] = pdefs->blue; - if (p < min) - min = p; - if (p > max) - max = p; - pdefs++; - } - - fbdevUpdateFbColormap(priv, min, max); -} +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "fbdev.h" +#include <sys/ioctl.h> + +#include <errno.h> + +extern int KdTsPhyScreen; + +char *fbdevDevicePath = NULL; + +static Bool +fbdevInitialize (KdCardInfo *card, FbdevPriv *priv) +{ + unsigned long off; + + if (fbdevDevicePath == NULL) + fbdevDevicePath = "/dev/fb0"; + + if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0) + { + ErrorF("Error opening framebuffer %s: %s\n", + fbdevDevicePath, strerror(errno)); + return FALSE; + } + + /* quiet valgrind */ + memset (&priv->fix, '\0', sizeof (priv->fix)); + if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) { + perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO"); + close (priv->fd); + return FALSE; + } + /* quiet valgrind */ + memset (&priv->var, '\0', sizeof (priv->var)); + if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) { + perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO"); + close (priv->fd); + return FALSE; + } + + priv->fb_base = (char *) mmap ((caddr_t) NULL, + priv->fix.smem_len, + PROT_READ|PROT_WRITE, + MAP_SHARED, + priv->fd, 0); + + if (priv->fb_base == (char *)-1) + { + perror("ERROR: mmap framebuffer fails!"); + close (priv->fd); + return FALSE; + } + off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize(); + priv->fb = priv->fb_base + off; + return TRUE; +} + +Bool +fbdevCardInit (KdCardInfo *card) +{ + FbdevPriv *priv; + + priv = (FbdevPriv *) malloc(sizeof (FbdevPriv)); + if (!priv) + return FALSE; + + if (!fbdevInitialize (card, priv)) + { + free(priv); + return FALSE; + } + card->driver = priv; + + return TRUE; +} + +static Pixel +fbdevMakeContig (Pixel orig, Pixel others) +{ + Pixel low; + + low = lowbit (orig) >> 1; + while (low && (others & low) == 0) + { + orig |= low; + low >>= 1; + } + return orig; +} + +static Bool +fbdevModeSupported (KdScreenInfo *screen, + const KdMonitorTiming *t) +{ + return TRUE; +} + +static void +fbdevConvertMonitorTiming (const KdMonitorTiming *t, struct fb_var_screeninfo *var) +{ + memset (var, 0, sizeof (struct fb_var_screeninfo)); + + var->xres = t->horizontal; + var->yres = t->vertical; + var->xres_virtual = t->horizontal; + var->yres_virtual = t->vertical; + var->xoffset = 0; + var->yoffset = 0; + var->pixclock = t->clock ? 1000000000 / t->clock : 0; + var->left_margin = t->hbp; + var->right_margin = t->hfp; + var->upper_margin = t->vbp; + var->lower_margin = t->vfp; + var->hsync_len = t->hblank - t->hfp - t->hbp; + var->vsync_len = t->vblank - t->vfp - t->vbp; + + var->sync = 0; + var->vmode = 0; + + if (t->hpol == KdSyncPositive) + var->sync |= FB_SYNC_HOR_HIGH_ACT; + if (t->vpol == KdSyncPositive) + var->sync |= FB_SYNC_VERT_HIGH_ACT; +} + +static Bool +fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv) +{ + FbdevPriv *priv = screen->card->driver; + Pixel allbits; + int depth; + Bool gray; + struct fb_var_screeninfo var; + const KdMonitorTiming *t; + int k; + + k = ioctl (priv->fd, FBIOGET_VSCREENINFO, &var); + + if (!screen->width || !screen->height) + { + if (k >= 0) + { + screen->width = var.xres; + screen->height = var.yres; + } + else + { + screen->width = 1024; + screen->height = 768; + } + screen->rate = 103; /* FIXME: should get proper value from fb driver */ + } + if (!screen->fb.depth) + { + if (k >= 0) + screen->fb.depth = var.bits_per_pixel; + else + screen->fb.depth = 16; + } + + if ((screen->width != var.xres) || (screen->height != var.yres)) + { + t = KdFindMode (screen, fbdevModeSupported); + screen->rate = t->rate; + screen->width = t->horizontal; + screen->height = t->vertical; + + /* Now try setting the mode */ + if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres)) + fbdevConvertMonitorTiming (t, &var); + } + + var.activate = FB_ACTIVATE_NOW; + var.bits_per_pixel = screen->fb.depth; + var.nonstd = 0; + var.grayscale = 0; + + k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &var); + + if (k < 0) + { + fprintf (stderr, "error: %s\n", strerror (errno)); + return FALSE; + } + + /* Re-get the "fixed" parameters since they might have changed */ + k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix); + if (k < 0) + perror ("FBIOGET_FSCREENINFO"); + + /* Now get the new screeninfo */ + ioctl (priv->fd, FBIOGET_VSCREENINFO, &priv->var); + depth = priv->var.bits_per_pixel; + gray = priv->var.grayscale; + + switch (priv->fix.visual) { + case FB_VISUAL_PSEUDOCOLOR: + if (gray) + { + screen->fb.visuals = (1 << StaticGray); + /* could also support GrayScale, but what's the point? */ + } + else + { + screen->fb.visuals = ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)); + } + screen->fb.blueMask = 0x00; + screen->fb.greenMask = 0x00; + screen->fb.redMask = 0x00; + break; + case FB_VISUAL_STATIC_PSEUDOCOLOR: + if (gray) + { + screen->fb.visuals = (1 << StaticGray); + } + else + { + screen->fb.visuals = (1 << StaticColor); + } + screen->fb.blueMask = 0x00; + screen->fb.greenMask = 0x00; + screen->fb.redMask = 0x00; + break; + case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_DIRECTCOLOR: + screen->fb.visuals = (1 << TrueColor); +#define Mask(o,l) (((1 << l) - 1) << o) + screen->fb.redMask = Mask (priv->var.red.offset, priv->var.red.length); + screen->fb.greenMask = Mask (priv->var.green.offset, priv->var.green.length); + screen->fb.blueMask = Mask (priv->var.blue.offset, priv->var.blue.length); + + /* + * This is a kludge so that Render will work -- fill in the gaps + * in the pixel + */ + screen->fb.redMask = fbdevMakeContig (screen->fb.redMask, + screen->fb.greenMask| + screen->fb.blueMask); + + screen->fb.greenMask = fbdevMakeContig (screen->fb.greenMask, + screen->fb.redMask| + screen->fb.blueMask); + + screen->fb.blueMask = fbdevMakeContig (screen->fb.blueMask, + screen->fb.redMask| + screen->fb.greenMask); + + allbits = screen->fb.redMask | screen->fb.greenMask | screen->fb.blueMask; + depth = 32; + while (depth && !(allbits & (1 << (depth - 1)))) + depth--; + break; + default: + return FALSE; + break; + } + screen->fb.depth = depth; + screen->fb.bitsPerPixel = priv->var.bits_per_pixel; + + scrpriv->randr = screen->randr; + + return fbdevMapFramebuffer (screen); +} + +Bool +fbdevScreenInit (KdScreenInfo *screen) +{ + FbdevScrPriv *scrpriv; + + scrpriv = calloc(1, sizeof (FbdevScrPriv)); + if (!scrpriv) + return FALSE; + screen->driver = scrpriv; + if (!fbdevScreenInitialize (screen, scrpriv)) + { + screen->driver = 0; + free(scrpriv); + return FALSE; + } + return TRUE; +} + +static void * +fbdevWindowLinear (ScreenPtr pScreen, + CARD32 row, + CARD32 offset, + int mode, + CARD32 *size, + void *closure) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + + if (!pScreenPriv->enabled) + return 0; + *size = priv->fix.line_length; + return (CARD8 *) priv->fb + row * priv->fix.line_length + offset; +} + +Bool +fbdevMapFramebuffer (KdScreenInfo *screen) +{ + FbdevScrPriv *scrpriv = screen->driver; + KdPointerMatrix m; + FbdevPriv *priv = screen->card->driver; + + if (scrpriv->randr != RR_Rotate_0) + scrpriv->shadow = TRUE; + else + scrpriv->shadow = FALSE; + + KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); + + KdSetPointerMatrix (&m); + + screen->width = priv->var.xres; + screen->height = priv->var.yres; + + if (scrpriv->shadow) + { + if (!KdShadowFbAlloc (screen, + scrpriv->randr & (RR_Rotate_90|RR_Rotate_270))) + return FALSE; + } + else + { + screen->fb.byteStride = priv->fix.line_length; + screen->fb.pixelStride = (priv->fix.line_length * 8 / + priv->var.bits_per_pixel); + screen->fb.frameBuffer = (CARD8 *) (priv->fb); + } + + return TRUE; +} + +static void +fbdevSetScreenSizes (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + FbdevPriv *priv = screen->card->driver; + + if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) + { + pScreen->width = priv->var.xres; + pScreen->height = priv->var.yres; + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + } + else + { + pScreen->width = priv->var.yres; + pScreen->height = priv->var.xres; + pScreen->mmWidth = screen->height_mm; + pScreen->mmHeight = screen->width_mm; + } +} + +static Bool +fbdevUnmapFramebuffer (KdScreenInfo *screen) +{ + KdShadowFbFree (screen); + return TRUE; +} + +static Bool +fbdevSetShadow (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + FbdevPriv *priv = screen->card->driver; + ShadowUpdateProc update; + ShadowWindowProc window; + int useYX = 0; + +#ifdef __arm__ + /* Use variant copy routines that always read left to right in the + shadow framebuffer. Reading vertical strips is exceptionally + slow on XScale due to cache effects. */ + useYX = 1; +#endif + + window = fbdevWindowLinear; + update = 0; + if (scrpriv->randr) + if (priv->var.bits_per_pixel == 16) { + switch (scrpriv->randr) { + case RR_Rotate_90: + if (useYX) + update = shadowUpdateRotate16_90YX; + else + update = shadowUpdateRotate16_90; + break; + case RR_Rotate_180: + update = shadowUpdateRotate16_180; + break; + case RR_Rotate_270: + if (useYX) + update = shadowUpdateRotate16_270YX; + else + update = shadowUpdateRotate16_270; + break; + default: + update = shadowUpdateRotate16; + break; + } + } else + update = shadowUpdateRotatePacked; + else + update = shadowUpdatePacked; + return KdShadowSet (pScreen, scrpriv->randr, update, window); +} + + +#ifdef RANDR +static Bool +fbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + RRScreenSizePtr pSize; + Rotation randr; + int n; + + *rotations = RR_Rotate_All|RR_Reflect_All; + + for (n = 0; n < pScreen->numDepths; n++) + if (pScreen->allowedDepths[n].numVids) + break; + if (n == pScreen->numDepths) + return FALSE; + + pSize = RRRegisterSize (pScreen, + screen->width, + screen->height, + screen->width_mm, + screen->height_mm); + + randr = KdSubRotation (scrpriv->randr, screen->randr); + + RRSetCurrentConfig (pScreen, randr, 0, pSize); + + return TRUE; +} + +static Bool +fbdevRandRSetConfig (ScreenPtr pScreen, + Rotation randr, + int rate, + RRScreenSizePtr pSize) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + FbdevScrPriv *scrpriv = screen->driver; + Bool wasEnabled = pScreenPriv->enabled; + FbdevScrPriv oldscr; + int oldwidth; + int oldheight; + int oldmmwidth; + int oldmmheight; + int newwidth, newheight; + + if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) + { + newwidth = pSize->width; + newheight = pSize->height; + } + else + { + newwidth = pSize->height; + newheight = pSize->width; + } + + if (wasEnabled) + KdDisableScreen (pScreen); + + oldscr = *scrpriv; + + oldwidth = screen->width; + oldheight = screen->height; + oldmmwidth = pScreen->mmWidth; + oldmmheight = pScreen->mmHeight; + + /* + * Set new configuration + */ + + scrpriv->randr = KdAddRotation (screen->randr, randr); + + fbdevUnmapFramebuffer (screen); + + if (!fbdevMapFramebuffer (screen)) + goto bail4; + + KdShadowUnset (screen->pScreen); + + if (!fbdevSetShadow (screen->pScreen)) + goto bail4; + + fbdevSetScreenSizes (screen->pScreen); + + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); + + /* set the subpixel order */ + + KdSetSubpixelOrder (pScreen, scrpriv->randr); + if (wasEnabled) + KdEnableScreen (pScreen); + + return TRUE; + +bail4: + fbdevUnmapFramebuffer (screen); + *scrpriv = oldscr; + (void) fbdevMapFramebuffer (screen); + pScreen->width = oldwidth; + pScreen->height = oldheight; + pScreen->mmWidth = oldmmwidth; + pScreen->mmHeight = oldmmheight; + + if (wasEnabled) + KdEnableScreen (pScreen); + return FALSE; +} + +static Bool +fbdevRandRInit (ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit (pScreen)) + return FALSE; + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = fbdevRandRGetInfo; + pScrPriv->rrSetConfig = fbdevRandRSetConfig; + return TRUE; +} +#endif + +static Bool +fbdevCreateColormap (ColormapPtr pmap) +{ + ScreenPtr pScreen = pmap->pScreen; + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + VisualPtr pVisual; + int i; + int nent; + xColorItem *pdefs; + + switch (priv->fix.visual) { + case FB_VISUAL_STATIC_PSEUDOCOLOR: + pVisual = pmap->pVisual; + nent = pVisual->ColormapEntries; + pdefs = malloc(nent * sizeof (xColorItem)); + if (!pdefs) + return FALSE; + for (i = 0; i < nent; i++) + pdefs[i].pixel = i; + fbdevGetColors (pScreen, nent, pdefs); + for (i = 0; i < nent; i++) + { + pmap->red[i].co.local.red = pdefs[i].red; + pmap->red[i].co.local.green = pdefs[i].green; + pmap->red[i].co.local.blue = pdefs[i].blue; + } + free(pdefs); + return TRUE; + default: + return fbInitializeColormap (pmap); + } +} + +Bool +fbdevInitScreen (ScreenPtr pScreen) +{ +#ifdef TOUCHSCREEN + KdTsPhyScreen = pScreen->myNum; +#endif + + pScreen->CreateColormap = fbdevCreateColormap; + return TRUE; +} + +Bool +fbdevFinishInitScreen (ScreenPtr pScreen) +{ + if (!shadowSetup (pScreen)) + return FALSE; + +#ifdef RANDR + if (!fbdevRandRInit (pScreen)) + return FALSE; +#endif + + return TRUE; +} + + +Bool +fbdevCreateResources (ScreenPtr pScreen) +{ + return fbdevSetShadow (pScreen); +} + +void +fbdevPreserve (KdCardInfo *card) +{ +} + +static int +fbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx) +{ + struct fb_cmap cmap; + + cmap.start = minidx; + cmap.len = maxidx - minidx + 1; + cmap.red = &priv->red[minidx]; + cmap.green = &priv->green[minidx]; + cmap.blue = &priv->blue[minidx]; + cmap.transp = 0; + + return ioctl(priv->fd, FBIOPUTCMAP, &cmap); +} + +Bool +fbdevEnable (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + int k; + + priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL; + + /* display it on the LCD */ + k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var); + if (k < 0) + { + perror ("FBIOPUT_VSCREENINFO"); + return FALSE; + } + + if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR) + { + int i; + + for (i = 0; + i < (1 << priv->var.red.length) || + i < (1 << priv->var.green.length) || + i < (1 << priv->var.blue.length); i++) + { + priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1); + priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1); + priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1); + } + + fbdevUpdateFbColormap(priv, 0, i); + } + return TRUE; +} + +Bool +fbdevDPMS (ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + static int oldmode = -1; + + if (mode == oldmode) + return TRUE; +#ifdef FBIOPUT_POWERMODE + if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0) + { + oldmode = mode; + return TRUE; + } +#endif +#ifdef FBIOBLANK + if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0) + { + oldmode = mode; + return TRUE; + } +#endif + return FALSE; +} + +void +fbdevDisable (ScreenPtr pScreen) +{ +} + +void +fbdevRestore (KdCardInfo *card) +{ +} + +void +fbdevScreenFini (KdScreenInfo *screen) +{ +} + +void +fbdevCardFini (KdCardInfo *card) +{ + FbdevPriv *priv = card->driver; + + munmap (priv->fb_base, priv->fix.smem_len); + close (priv->fd); + free(priv); +} + +/* + * Retrieve actual colormap and return selected n entries in pdefs. + */ +void +fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + struct fb_cmap cmap; + int p; + int k; + int min, max; + + min = 256; + max = 0; + for (k = 0; k < n; k++) + { + if (pdefs[k].pixel < min) + min = pdefs[k].pixel; + if (pdefs[k].pixel > max) + max = pdefs[k].pixel; + } + cmap.start = min; + cmap.len = max - min + 1; + cmap.red = &priv->red[min]; + cmap.green = &priv->green[min]; + cmap.blue = &priv->blue[min]; + cmap.transp = 0; + k = ioctl (priv->fd, FBIOGETCMAP, &cmap); + if (k < 0) + { + perror ("can't get colormap"); + return; + } + while (n--) + { + p = pdefs->pixel; + pdefs->red = priv->red[p]; + pdefs->green = priv->green[p]; + pdefs->blue = priv->blue[p]; + pdefs++; + } +} + +/* + * Change colormap by updating n entries described in pdefs. + */ +void +fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs) +{ + KdScreenPriv(pScreen); + FbdevPriv *priv = pScreenPriv->card->driver; + int p; + int min, max; + + min = 256; + max = 0; + while (n--) + { + p = pdefs->pixel; + priv->red[p] = pdefs->red; + priv->green[p] = pdefs->green; + priv->blue[p] = pdefs->blue; + if (p < min) + min = p; + if (p > max) + max = p; + pdefs++; + } + + fbdevUpdateFbColormap(priv, min, max); +} diff --git a/xorg-server/hw/kdrive/linux/evdev.c b/xorg-server/hw/kdrive/linux/evdev.c index 0e4c9f735..20df77b99 100644 --- a/xorg-server/hw/kdrive/linux/evdev.c +++ b/xorg-server/hw/kdrive/linux/evdev.c @@ -1,539 +1,539 @@ -/* - * Copyright © 2004 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include <errno.h> -#include <linux/input.h> -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/Xpoll.h> -#include "inputstr.h" -#include "scrnintstr.h" -#include "kdrive.h" - -#define NUM_EVENTS 128 -#define ABS_UNSET -65535 - -#define BITS_PER_LONG (sizeof(long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y)) -#define OFF(x) ((x)%BITS_PER_LONG) -#define LONG(x) ((x)/BITS_PER_LONG) -#define BIT(x) (1 << OFF(x)) - -typedef struct _kevdev { - /* current device state */ - int rel[REL_MAX + 1]; - int abs[ABS_MAX + 1]; - int prevabs[ABS_MAX + 1]; - long key[NBITS(KEY_MAX + 1)]; - - /* supported device info */ - long relbits[NBITS(REL_MAX + 1)]; - long absbits[NBITS(ABS_MAX + 1)]; - long keybits[NBITS(KEY_MAX + 1)]; - struct input_absinfo absinfo[ABS_MAX + 1]; - int max_rel; - int max_abs; - - int fd; -} Kevdev; - -static void -EvdevPtrBtn (KdPointerInfo *pi, struct input_event *ev) -{ - int flags = KD_MOUSE_DELTA | pi->buttonState; - - if (ev->code >= BTN_MOUSE && ev->code < BTN_JOYSTICK) { - switch (ev->code) { - case BTN_LEFT: - if (ev->value == 1) - flags |= KD_BUTTON_1; - else - flags &= ~KD_BUTTON_1; - break; - case BTN_MIDDLE: - if (ev->value == 1) - flags |= KD_BUTTON_2; - else - flags &= ~KD_BUTTON_2; - break; - case BTN_RIGHT: - if (ev->value == 1) - flags |= KD_BUTTON_3; - else - flags &= ~KD_BUTTON_3; - break; - default: - /* Unknow button */ - break; - } - - KdEnqueuePointerEvent (pi, flags, 0, 0, 0); - } -} -static void -EvdevPtrMotion (KdPointerInfo *pi, struct input_event *ev) -{ - Kevdev *ke = pi->driverPrivate; - int i; - int flags = KD_MOUSE_DELTA | pi->buttonState; - - for (i = 0; i <= ke->max_rel; i++) - if (ke->rel[i]) - { - int a; - for (a = 0; a <= ke->max_rel; a++) - { - if (ISBITSET (ke->relbits, a)) - { - if (a == 0) - KdEnqueuePointerEvent(pi, flags, ke->rel[a], 0, 0); - else if (a == 1) - KdEnqueuePointerEvent(pi, flags, 0, ke->rel[a], 0); - } - ke->rel[a] = 0; - } - break; - } - for (i = 0; i < ke->max_abs; i++) - if (ke->abs[i] != ke->prevabs[i]) - { - int a; - ErrorF ("abs"); - for (a = 0; a <= ke->max_abs; a++) - { - if (ISBITSET (ke->absbits, a)) - ErrorF (" %d=%d", a, ke->abs[a]); - ke->prevabs[a] = ke->abs[a]; - } - ErrorF ("\n"); - break; - } - - if (ev->code == REL_WHEEL) { - for (i = 0; i < abs (ev->value); i++) - { - if (ev->value > 0) - flags |= KD_BUTTON_4; - else - flags |= KD_BUTTON_5; - - KdEnqueuePointerEvent (pi, flags, 0, 0, 0); - - if (ev->value > 0) - flags &= ~KD_BUTTON_4; - else - flags &= ~KD_BUTTON_5; - - KdEnqueuePointerEvent (pi, flags, 0, 0, 0); - } - } - -} - -static void -EvdevPtrRead (int evdevPort, void *closure) -{ - KdPointerInfo *pi = closure; - Kevdev *ke = pi->driverPrivate; - int i; - struct input_event events[NUM_EVENTS]; - int n; - - n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event)); - if (n <= 0) { - if (errno == ENODEV) - DeleteInputDeviceRequest(pi->dixdev); - return; - } - - n /= sizeof (struct input_event); - for (i = 0; i < n; i++) - { - switch (events[i].type) { - case EV_SYN: - break; - case EV_KEY: - EvdevPtrBtn (pi, &events[i]); - break; - case EV_REL: - ke->rel[events[i].code] += events[i].value; - EvdevPtrMotion (pi, &events[i]); - break; - case EV_ABS: - ke->abs[events[i].code] = events[i].value; - EvdevPtrMotion (pi, &events[i]); - break; - } - } -} - -char *kdefaultEvdev[] = { - "/dev/input/event0", - "/dev/input/event1", - "/dev/input/event2", - "/dev/input/event3", -}; - -#define NUM_DEFAULT_EVDEV (sizeof (kdefaultEvdev) / sizeof (kdefaultEvdev[0])) - -static Status -EvdevPtrInit (KdPointerInfo *pi) -{ - int i; - int fd; - - if (!pi->path) { - for (i = 0; i < NUM_DEFAULT_EVDEV; i++) { - fd = open (kdefaultEvdev[i], 2); - if (fd >= 0) { - pi->path = strdup (kdefaultEvdev[i]); - break; - } - } - } - else { - fd = open (pi->path, O_RDWR); - if (fd < 0) { - ErrorF("Failed to open evdev device %s\n", pi->path); - return BadMatch; - } - } - - close(fd); - - pi->name = strdup("Evdev mouse"); - - return Success; -} - -static Status -EvdevPtrEnable (KdPointerInfo *pi) -{ - int fd; - unsigned long ev[NBITS(EV_MAX)]; - Kevdev *ke; - - if (!pi || !pi->path) - return BadImplementation; - - fd = open(pi->path, 2); - if (fd < 0) - return BadMatch; - - if (ioctl (fd, EVIOCGRAB, 1) < 0) - perror ("Grabbing evdev mouse device failed"); - - if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) - { - perror ("EVIOCGBIT 0"); - close (fd); - return BadMatch; - } - ke = xcalloc (1, sizeof (Kevdev)); - if (!ke) - { - close (fd); - return BadAlloc; - } - if (ISBITSET (ev, EV_KEY)) - { - if (ioctl (fd, EVIOCGBIT (EV_KEY, sizeof (ke->keybits)), - ke->keybits) < 0) - { - perror ("EVIOCGBIT EV_KEY"); - xfree (ke); - close (fd); - return BadMatch; - } - } - if (ISBITSET (ev, EV_REL)) - { - if (ioctl (fd, EVIOCGBIT (EV_REL, sizeof (ke->relbits)), - ke->relbits) < 0) - { - perror ("EVIOCGBIT EV_REL"); - xfree (ke); - close (fd); - return BadMatch; - } - for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--) - if (ISBITSET(ke->relbits, ke->max_rel)) - break; - } - if (ISBITSET (ev, EV_ABS)) - { - int i; - - if (ioctl (fd, EVIOCGBIT (EV_ABS, sizeof (ke->absbits)), - ke->absbits) < 0) - { - perror ("EVIOCGBIT EV_ABS"); - xfree (ke); - close (fd); - return BadMatch; - } - for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--) - if (ISBITSET(ke->absbits, ke->max_abs)) - break; - for (i = 0; i <= ke->max_abs; i++) - { - if (ISBITSET (ke->absbits, i)) - if (ioctl (fd, EVIOCGABS(i), &ke->absinfo[i]) < 0) - { - perror ("EVIOCGABS"); - break; - } - ke->prevabs[i] = ABS_UNSET; - } - if (i <= ke->max_abs) - { - xfree (ke); - close (fd); - return BadValue; - } - } - if (!KdRegisterFd (fd, EvdevPtrRead, pi)) { - xfree (ke); - close (fd); - return BadAlloc; - } - pi->driverPrivate = ke; - ke->fd = fd; - - return Success; -} - -static void -EvdevPtrDisable (KdPointerInfo *pi) -{ - Kevdev *ke; - - ke = pi->driverPrivate; - - if (!pi || !pi->driverPrivate) - return; - - KdUnregisterFd (pi, ke->fd, TRUE); - - if (ioctl (ke->fd, EVIOCGRAB, 0) < 0) - perror ("Ungrabbing evdev mouse device failed"); - - xfree (ke); - pi->driverPrivate = 0; -} - -static void -EvdevPtrFini (KdPointerInfo *pi) -{ -} - - -/* - * Evdev keyboard functions - */ - -static void -readMapping (KdKeyboardInfo *ki) -{ - if (!ki) - return; - - ki->minScanCode = 0; - ki->maxScanCode = 247; -} - -static void -EvdevKbdRead (int evdevPort, void *closure) -{ - KdKeyboardInfo *ki = closure; - struct input_event events[NUM_EVENTS]; - int i, n; - - n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event)); - if (n <= 0) { - if (errno == ENODEV) - DeleteInputDeviceRequest(ki->dixdev); - return; - } - - n /= sizeof (struct input_event); - for (i = 0; i < n; i++) - { - if (events[i].type == EV_KEY) - KdEnqueueKeyboardEvent (ki, events[i].code, !events[i].value); -/* FIXME: must implement other types of events - else - ErrorF("Event type (%d) not delivered\n", events[i].type); -*/ - } -} - -static Status -EvdevKbdInit (KdKeyboardInfo *ki) -{ - int fd; - - if (!ki->path) { - ErrorF("Couldn't find evdev device path\n"); - return BadValue; - } - else { - fd = open (ki->path, O_RDWR); - if (fd < 0) { - ErrorF("Failed to open evdev device %s\n", ki->path); - return BadMatch; - } - } - - close (fd); - - ki->name = strdup("Evdev keyboard"); - - readMapping(ki); - - return Success; -} - -static Status -EvdevKbdEnable (KdKeyboardInfo *ki) -{ - unsigned long ev[NBITS(EV_MAX)]; - Kevdev *ke; - int fd; - - if (!ki || !ki->path) - return BadImplementation; - - fd = open(ki->path, O_RDWR); - if (fd < 0) - return BadMatch; - - if (ioctl (fd, EVIOCGRAB, 1) < 0) - perror ("Grabbing evdev keyboard device failed"); - - if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) { - perror ("EVIOCGBIT 0"); - close (fd); - return BadMatch; - } - - ke = xcalloc (1, sizeof (Kevdev)); - if (!ke) { - close (fd); - return BadAlloc; - } - - if (!KdRegisterFd (fd, EvdevKbdRead, ki)) { - xfree (ke); - close (fd); - return BadAlloc; - } - ki->driverPrivate = ke; - ke->fd = fd; - - return Success; -} - -static void -EvdevKbdLeds (KdKeyboardInfo *ki, int leds) -{ -/* struct input_event event; - Kevdev *ke; - - ki->driverPrivate = ke; - - memset(&event, 0, sizeof(event)); - - event.type = EV_LED; - event.code = LED_CAPSL; - event.value = leds & (1 << 0) ? 1 : 0; - write(ke->fd, (char *) &event, sizeof(event)); - - event.type = EV_LED; - event.code = LED_NUML; - event.value = leds & (1 << 1) ? 1 : 0; - write(ke->fd, (char *) &event, sizeof(event)); - - event.type = EV_LED; - event.code = LED_SCROLLL; - event.value = leds & (1 << 2) ? 1 : 0; - write(ke->fd, (char *) &event, sizeof(event)); - - event.type = EV_LED; - event.code = LED_COMPOSE; - event.value = leds & (1 << 3) ? 1 : 0; - write(ke->fd, (char *) &event, sizeof(event)); -*/ -} - -static void -EvdevKbdBell (KdKeyboardInfo *ki, int volume, int frequency, int duration) -{ -} - -static void -EvdevKbdDisable (KdKeyboardInfo *ki) -{ - Kevdev *ke; - - ke = ki->driverPrivate; - - if (!ki || !ki->driverPrivate) - return; - - KdUnregisterFd (ki, ke->fd, TRUE); - - if (ioctl (ke->fd, EVIOCGRAB, 0) < 0) - perror ("Ungrabbing evdev keyboard device failed"); - - xfree (ke); - ki->driverPrivate = 0; -} - -static void -EvdevKbdFini (KdKeyboardInfo *ki) -{ -} - -KdPointerDriver LinuxEvdevMouseDriver = { - "evdev", - EvdevPtrInit, - EvdevPtrEnable, - EvdevPtrDisable, - EvdevPtrFini, - NULL, -}; - -KdKeyboardDriver LinuxEvdevKeyboardDriver = { - "evdev", - EvdevKbdInit, - EvdevKbdEnable, - EvdevKbdLeds, - EvdevKbdBell, - EvdevKbdDisable, - EvdevKbdFini, - NULL, -}; +/* + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include <errno.h> +#include <linux/input.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xpoll.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "kdrive.h" + +#define NUM_EVENTS 128 +#define ABS_UNSET -65535 + +#define BITS_PER_LONG (sizeof(long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y)) +#define OFF(x) ((x)%BITS_PER_LONG) +#define LONG(x) ((x)/BITS_PER_LONG) +#define BIT(x) (1 << OFF(x)) + +typedef struct _kevdev { + /* current device state */ + int rel[REL_MAX + 1]; + int abs[ABS_MAX + 1]; + int prevabs[ABS_MAX + 1]; + long key[NBITS(KEY_MAX + 1)]; + + /* supported device info */ + long relbits[NBITS(REL_MAX + 1)]; + long absbits[NBITS(ABS_MAX + 1)]; + long keybits[NBITS(KEY_MAX + 1)]; + struct input_absinfo absinfo[ABS_MAX + 1]; + int max_rel; + int max_abs; + + int fd; +} Kevdev; + +static void +EvdevPtrBtn (KdPointerInfo *pi, struct input_event *ev) +{ + int flags = KD_MOUSE_DELTA | pi->buttonState; + + if (ev->code >= BTN_MOUSE && ev->code < BTN_JOYSTICK) { + switch (ev->code) { + case BTN_LEFT: + if (ev->value == 1) + flags |= KD_BUTTON_1; + else + flags &= ~KD_BUTTON_1; + break; + case BTN_MIDDLE: + if (ev->value == 1) + flags |= KD_BUTTON_2; + else + flags &= ~KD_BUTTON_2; + break; + case BTN_RIGHT: + if (ev->value == 1) + flags |= KD_BUTTON_3; + else + flags &= ~KD_BUTTON_3; + break; + default: + /* Unknow button */ + break; + } + + KdEnqueuePointerEvent (pi, flags, 0, 0, 0); + } +} +static void +EvdevPtrMotion (KdPointerInfo *pi, struct input_event *ev) +{ + Kevdev *ke = pi->driverPrivate; + int i; + int flags = KD_MOUSE_DELTA | pi->buttonState; + + for (i = 0; i <= ke->max_rel; i++) + if (ke->rel[i]) + { + int a; + for (a = 0; a <= ke->max_rel; a++) + { + if (ISBITSET (ke->relbits, a)) + { + if (a == 0) + KdEnqueuePointerEvent(pi, flags, ke->rel[a], 0, 0); + else if (a == 1) + KdEnqueuePointerEvent(pi, flags, 0, ke->rel[a], 0); + } + ke->rel[a] = 0; + } + break; + } + for (i = 0; i < ke->max_abs; i++) + if (ke->abs[i] != ke->prevabs[i]) + { + int a; + ErrorF ("abs"); + for (a = 0; a <= ke->max_abs; a++) + { + if (ISBITSET (ke->absbits, a)) + ErrorF (" %d=%d", a, ke->abs[a]); + ke->prevabs[a] = ke->abs[a]; + } + ErrorF ("\n"); + break; + } + + if (ev->code == REL_WHEEL) { + for (i = 0; i < abs (ev->value); i++) + { + if (ev->value > 0) + flags |= KD_BUTTON_4; + else + flags |= KD_BUTTON_5; + + KdEnqueuePointerEvent (pi, flags, 0, 0, 0); + + if (ev->value > 0) + flags &= ~KD_BUTTON_4; + else + flags &= ~KD_BUTTON_5; + + KdEnqueuePointerEvent (pi, flags, 0, 0, 0); + } + } + +} + +static void +EvdevPtrRead (int evdevPort, void *closure) +{ + KdPointerInfo *pi = closure; + Kevdev *ke = pi->driverPrivate; + int i; + struct input_event events[NUM_EVENTS]; + int n; + + n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event)); + if (n <= 0) { + if (errno == ENODEV) + DeleteInputDeviceRequest(pi->dixdev); + return; + } + + n /= sizeof (struct input_event); + for (i = 0; i < n; i++) + { + switch (events[i].type) { + case EV_SYN: + break; + case EV_KEY: + EvdevPtrBtn (pi, &events[i]); + break; + case EV_REL: + ke->rel[events[i].code] += events[i].value; + EvdevPtrMotion (pi, &events[i]); + break; + case EV_ABS: + ke->abs[events[i].code] = events[i].value; + EvdevPtrMotion (pi, &events[i]); + break; + } + } +} + +char *kdefaultEvdev[] = { + "/dev/input/event0", + "/dev/input/event1", + "/dev/input/event2", + "/dev/input/event3", +}; + +#define NUM_DEFAULT_EVDEV (sizeof (kdefaultEvdev) / sizeof (kdefaultEvdev[0])) + +static Status +EvdevPtrInit (KdPointerInfo *pi) +{ + int i; + int fd; + + if (!pi->path) { + for (i = 0; i < NUM_DEFAULT_EVDEV; i++) { + fd = open (kdefaultEvdev[i], 2); + if (fd >= 0) { + pi->path = strdup (kdefaultEvdev[i]); + break; + } + } + } + else { + fd = open (pi->path, O_RDWR); + if (fd < 0) { + ErrorF("Failed to open evdev device %s\n", pi->path); + return BadMatch; + } + } + + close(fd); + + pi->name = strdup("Evdev mouse"); + + return Success; +} + +static Status +EvdevPtrEnable (KdPointerInfo *pi) +{ + int fd; + unsigned long ev[NBITS(EV_MAX)]; + Kevdev *ke; + + if (!pi || !pi->path) + return BadImplementation; + + fd = open(pi->path, 2); + if (fd < 0) + return BadMatch; + + if (ioctl (fd, EVIOCGRAB, 1) < 0) + perror ("Grabbing evdev mouse device failed"); + + if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) + { + perror ("EVIOCGBIT 0"); + close (fd); + return BadMatch; + } + ke = calloc(1, sizeof (Kevdev)); + if (!ke) + { + close (fd); + return BadAlloc; + } + if (ISBITSET (ev, EV_KEY)) + { + if (ioctl (fd, EVIOCGBIT (EV_KEY, sizeof (ke->keybits)), + ke->keybits) < 0) + { + perror ("EVIOCGBIT EV_KEY"); + free(ke); + close (fd); + return BadMatch; + } + } + if (ISBITSET (ev, EV_REL)) + { + if (ioctl (fd, EVIOCGBIT (EV_REL, sizeof (ke->relbits)), + ke->relbits) < 0) + { + perror ("EVIOCGBIT EV_REL"); + free(ke); + close (fd); + return BadMatch; + } + for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--) + if (ISBITSET(ke->relbits, ke->max_rel)) + break; + } + if (ISBITSET (ev, EV_ABS)) + { + int i; + + if (ioctl (fd, EVIOCGBIT (EV_ABS, sizeof (ke->absbits)), + ke->absbits) < 0) + { + perror ("EVIOCGBIT EV_ABS"); + free(ke); + close (fd); + return BadMatch; + } + for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--) + if (ISBITSET(ke->absbits, ke->max_abs)) + break; + for (i = 0; i <= ke->max_abs; i++) + { + if (ISBITSET (ke->absbits, i)) + if (ioctl (fd, EVIOCGABS(i), &ke->absinfo[i]) < 0) + { + perror ("EVIOCGABS"); + break; + } + ke->prevabs[i] = ABS_UNSET; + } + if (i <= ke->max_abs) + { + free(ke); + close (fd); + return BadValue; + } + } + if (!KdRegisterFd (fd, EvdevPtrRead, pi)) { + free(ke); + close (fd); + return BadAlloc; + } + pi->driverPrivate = ke; + ke->fd = fd; + + return Success; +} + +static void +EvdevPtrDisable (KdPointerInfo *pi) +{ + Kevdev *ke; + + ke = pi->driverPrivate; + + if (!pi || !pi->driverPrivate) + return; + + KdUnregisterFd (pi, ke->fd, TRUE); + + if (ioctl (ke->fd, EVIOCGRAB, 0) < 0) + perror ("Ungrabbing evdev mouse device failed"); + + free(ke); + pi->driverPrivate = 0; +} + +static void +EvdevPtrFini (KdPointerInfo *pi) +{ +} + + +/* + * Evdev keyboard functions + */ + +static void +readMapping (KdKeyboardInfo *ki) +{ + if (!ki) + return; + + ki->minScanCode = 0; + ki->maxScanCode = 247; +} + +static void +EvdevKbdRead (int evdevPort, void *closure) +{ + KdKeyboardInfo *ki = closure; + struct input_event events[NUM_EVENTS]; + int i, n; + + n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event)); + if (n <= 0) { + if (errno == ENODEV) + DeleteInputDeviceRequest(ki->dixdev); + return; + } + + n /= sizeof (struct input_event); + for (i = 0; i < n; i++) + { + if (events[i].type == EV_KEY) + KdEnqueueKeyboardEvent (ki, events[i].code, !events[i].value); +/* FIXME: must implement other types of events + else + ErrorF("Event type (%d) not delivered\n", events[i].type); +*/ + } +} + +static Status +EvdevKbdInit (KdKeyboardInfo *ki) +{ + int fd; + + if (!ki->path) { + ErrorF("Couldn't find evdev device path\n"); + return BadValue; + } + else { + fd = open (ki->path, O_RDWR); + if (fd < 0) { + ErrorF("Failed to open evdev device %s\n", ki->path); + return BadMatch; + } + } + + close (fd); + + ki->name = strdup("Evdev keyboard"); + + readMapping(ki); + + return Success; +} + +static Status +EvdevKbdEnable (KdKeyboardInfo *ki) +{ + unsigned long ev[NBITS(EV_MAX)]; + Kevdev *ke; + int fd; + + if (!ki || !ki->path) + return BadImplementation; + + fd = open(ki->path, O_RDWR); + if (fd < 0) + return BadMatch; + + if (ioctl (fd, EVIOCGRAB, 1) < 0) + perror ("Grabbing evdev keyboard device failed"); + + if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) { + perror ("EVIOCGBIT 0"); + close (fd); + return BadMatch; + } + + ke = calloc(1, sizeof (Kevdev)); + if (!ke) { + close (fd); + return BadAlloc; + } + + if (!KdRegisterFd (fd, EvdevKbdRead, ki)) { + free(ke); + close (fd); + return BadAlloc; + } + ki->driverPrivate = ke; + ke->fd = fd; + + return Success; +} + +static void +EvdevKbdLeds (KdKeyboardInfo *ki, int leds) +{ +/* struct input_event event; + Kevdev *ke; + + ki->driverPrivate = ke; + + memset(&event, 0, sizeof(event)); + + event.type = EV_LED; + event.code = LED_CAPSL; + event.value = leds & (1 << 0) ? 1 : 0; + write(ke->fd, (char *) &event, sizeof(event)); + + event.type = EV_LED; + event.code = LED_NUML; + event.value = leds & (1 << 1) ? 1 : 0; + write(ke->fd, (char *) &event, sizeof(event)); + + event.type = EV_LED; + event.code = LED_SCROLLL; + event.value = leds & (1 << 2) ? 1 : 0; + write(ke->fd, (char *) &event, sizeof(event)); + + event.type = EV_LED; + event.code = LED_COMPOSE; + event.value = leds & (1 << 3) ? 1 : 0; + write(ke->fd, (char *) &event, sizeof(event)); +*/ +} + +static void +EvdevKbdBell (KdKeyboardInfo *ki, int volume, int frequency, int duration) +{ +} + +static void +EvdevKbdDisable (KdKeyboardInfo *ki) +{ + Kevdev *ke; + + ke = ki->driverPrivate; + + if (!ki || !ki->driverPrivate) + return; + + KdUnregisterFd (ki, ke->fd, TRUE); + + if (ioctl (ke->fd, EVIOCGRAB, 0) < 0) + perror ("Ungrabbing evdev keyboard device failed"); + + free(ke); + ki->driverPrivate = 0; +} + +static void +EvdevKbdFini (KdKeyboardInfo *ki) +{ +} + +KdPointerDriver LinuxEvdevMouseDriver = { + "evdev", + EvdevPtrInit, + EvdevPtrEnable, + EvdevPtrDisable, + EvdevPtrFini, + NULL, +}; + +KdKeyboardDriver LinuxEvdevKeyboardDriver = { + "evdev", + EvdevKbdInit, + EvdevKbdEnable, + EvdevKbdLeds, + EvdevKbdBell, + EvdevKbdDisable, + EvdevKbdFini, + NULL, +}; diff --git a/xorg-server/hw/kdrive/linux/keyboard.c b/xorg-server/hw/kdrive/linux/keyboard.c index 6eed7aed3..c888d14dc 100644 --- a/xorg-server/hw/kdrive/linux/keyboard.c +++ b/xorg-server/hw/kdrive/linux/keyboard.c @@ -1,765 +1,765 @@ -/* - * Copyright © 1999 Keith Packard - * XKB integration © 2006 Nokia Corporation, author: Tomas Frydrych <tf@o-hand.com> - * - * LinuxKeyboardRead() XKB code based on xf86KbdLnx.c: - * Copyright © 1990,91 by Thomas Roell, Dinkelscherben, Germany. - * Copyright © 1994-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_CONFIG_H -#include <kdrive-config.h> -#endif -#include "kdrive.h" -#include <linux/keyboard.h> -#include <linux/kd.h> -#define XK_PUBLISHING -#include <X11/keysym.h> -#include <termios.h> -#include <sys/ioctl.h> - -extern int LinuxConsoleFd; - -static const KeySym linux_to_x[256] = { - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, XK_Escape, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_space, XK_exclam, XK_quotedbl, XK_numbersign, - XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, - XK_parenleft, XK_parenright, XK_asterisk, XK_plus, - XK_comma, XK_minus, XK_period, XK_slash, - XK_0, XK_1, XK_2, XK_3, - XK_4, XK_5, XK_6, XK_7, - XK_8, XK_9, XK_colon, XK_semicolon, - XK_less, XK_equal, XK_greater, XK_question, - XK_at, XK_A, XK_B, XK_C, - XK_D, XK_E, XK_F, XK_G, - XK_H, XK_I, XK_J, XK_K, - XK_L, XK_M, XK_N, XK_O, - XK_P, XK_Q, XK_R, XK_S, - XK_T, XK_U, XK_V, XK_W, - XK_X, XK_Y, XK_Z, XK_bracketleft, - XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, - XK_grave, XK_a, XK_b, XK_c, - XK_d, XK_e, XK_f, XK_g, - XK_h, XK_i, XK_j, XK_k, - XK_l, XK_m, XK_n, XK_o, - XK_p, XK_q, XK_r, XK_s, - XK_t, XK_u, XK_v, XK_w, - XK_x, XK_y, XK_z, XK_braceleft, - XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, - XK_currency, XK_yen, XK_brokenbar, XK_section, - XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, - XK_notsign, XK_hyphen, XK_registered, XK_macron, - XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, - XK_acute, XK_mu, XK_paragraph, XK_periodcentered, - XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, - XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, - XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, - XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, - XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, - XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, - XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, - XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, - XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, - XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, - XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, - XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, - XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, - XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, - XK_eth, XK_ntilde, XK_ograve, XK_oacute, - XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, - XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, - XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis -}; - -/* - * Getting a keycode from scancode - * - * With XKB - * -------- - * - * We have to enqueue keyboard events using standard X keycodes which correspond - * to AT scancode + 8; this means that we need to translate the Linux scancode - * provided by the kernel to an AT scancode -- this translation is not linear - * and requires that we use a LUT. - * - * - * Without XKB - * ----------- - * - * We can use custom keycodes, which makes things simpler; we define our custom - * keycodes as Linux scancodes + KD_KEY_OFFSET -*/ - -/* - This LUT translates AT scancodes into Linux ones -- the keymap we create - for the core X keyboard protocol has to be AT-scancode based so that it - corresponds to the Xkb keymap. -*/ -#if 0 -static unsigned char at2lnx[] = -{ - 0x0, /* no valid scancode */ - 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ - 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ - 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ - 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ - 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ - 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ - 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ - 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ - 0x11, /* KEY_W */ 0x12, /* KEY_E */ - 0x13, /* KEY_R */ 0x14, /* KEY_T */ - 0x15, /* KEY_Y */ 0x16, /* KEY_U */ - 0x17, /* KEY_I */ 0x18, /* KEY_O */ - 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ - 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ - 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ - 0x1f, /* KEY_S */ 0x20, /* KEY_D */ - 0x21, /* KEY_F */ 0x22, /* KEY_G */ - 0x23, /* KEY_H */ 0x24, /* KEY_J */ - 0x25, /* KEY_K */ 0x26, /* KEY_L */ - 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ - 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ - 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ - 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ - 0x2f, /* KEY_V */ 0x30, /* KEY_B */ - 0x31, /* KEY_N */ 0x32, /* KEY_M */ - 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ - 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ - 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ - 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ - 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ - 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ - 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ - 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ - 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ - 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ - 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ - 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ - 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ - 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ - 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ - 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ - 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ - 0x00, /* 0x55 */ 0x56, /* KEY_Less */ - 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ - 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ - 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ - 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ - 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ - 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ - 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ - 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ - 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ - 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ - 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ - 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ - 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ - 0x00, /* 0x71 */ 0x00, /* 0x72 */ - 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ - 0x00, /* 0x75 */ 0x00, /* 0x76 */ - 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ - 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ - 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ - 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ - 0x00, /* 0x7f */ -}; - -#define NUM_AT_KEYS (sizeof(at2lnx)/sizeof(at2lnx[0])) -#define LNX_KEY_INDEX(n) n < NUM_AT_KEYS ? at2lnx[n] : 0 - -static unsigned char tbl[KD_MAX_WIDTH] = -{ - 0, - 1 << KG_SHIFT, - (1 << KG_ALTGR), - (1 << KG_ALTGR) | (1 << KG_SHIFT) -}; -#endif - -static void -readKernelMapping(KdKeyboardInfo *ki) -{ -#if 0 - KeySym *k; - int i, j; - struct kbentry kbe; - int minKeyCode, maxKeyCode; - int row; - int fd; - - if (!ki) - return; - - fd = LinuxConsoleFd; - - minKeyCode = NR_KEYS; - maxKeyCode = 0; - row = 0; - ki->keySyms.mapWidth = KD_MAX_WIDTH; - for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i) - { - kbe.kb_index = LNX_KEY_INDEX(i); - - k = ki->keySyms.map + row * ki->keySyms.mapWidth; - - for (j = 0; j < ki->keySyms.mapWidth; ++j) - { - unsigned short kval; - - k[j] = NoSymbol; - - kbe.kb_table = tbl[j]; - kbe.kb_value = 0; - if (ioctl(fd, KDGKBENT, &kbe)) - continue; - - kval = KVAL(kbe.kb_value); - switch (KTYP(kbe.kb_value)) - { - case KT_LATIN: - case KT_LETTER: - k[j] = linux_to_x[kval]; - break; - - case KT_FN: - if (kval <= 19) - k[j] = XK_F1 + kval; - else switch (kbe.kb_value) - { - case K_FIND: - k[j] = XK_Home; /* or XK_Find */ - break; - case K_INSERT: - k[j] = XK_Insert; - break; - case K_REMOVE: - k[j] = XK_Delete; - break; - case K_SELECT: - k[j] = XK_End; /* or XK_Select */ - break; - case K_PGUP: - k[j] = XK_Prior; - break; - case K_PGDN: - k[j] = XK_Next; - break; - case K_HELP: - k[j] = XK_Help; - break; - case K_DO: - k[j] = XK_Execute; - break; - case K_PAUSE: - k[j] = XK_Pause; - break; - case K_MACRO: - k[j] = XK_Menu; - break; - default: - break; - } - break; - - case KT_SPEC: - switch (kbe.kb_value) - { - case K_ENTER: - k[j] = XK_Return; - break; - case K_BREAK: - k[j] = XK_Break; - break; - case K_CAPS: - k[j] = XK_Caps_Lock; - break; - case K_NUM: - k[j] = XK_Num_Lock; - break; - case K_HOLD: - k[j] = XK_Scroll_Lock; - break; - case K_COMPOSE: - k[j] = XK_Multi_key; - break; - default: - break; - } - break; - - case KT_PAD: - switch (kbe.kb_value) - { - case K_PPLUS: - k[j] = XK_KP_Add; - break; - case K_PMINUS: - k[j] = XK_KP_Subtract; - break; - case K_PSTAR: - k[j] = XK_KP_Multiply; - break; - case K_PSLASH: - k[j] = XK_KP_Divide; - break; - case K_PENTER: - k[j] = XK_KP_Enter; - break; - case K_PCOMMA: - k[j] = XK_KP_Separator; - break; - case K_PDOT: - k[j] = XK_KP_Decimal; - break; - case K_PPLUSMINUS: - k[j] = XK_KP_Subtract; - break; - default: - if (kval <= 9) - k[j] = XK_KP_0 + kval; - break; - } - break; - - /* - * KT_DEAD keys are for accelerated diacritical creation. - */ - case KT_DEAD: - switch (kbe.kb_value) - { - case K_DGRAVE: - k[j] = XK_dead_grave; - break; - case K_DACUTE: - k[j] = XK_dead_acute; - break; - case K_DCIRCM: - k[j] = XK_dead_circumflex; - break; - case K_DTILDE: - k[j] = XK_dead_tilde; - break; - case K_DDIERE: - k[j] = XK_dead_diaeresis; - break; - } - break; - - case KT_CUR: - switch (kbe.kb_value) - { - case K_DOWN: - k[j] = XK_Down; - break; - case K_LEFT: - k[j] = XK_Left; - break; - case K_RIGHT: - k[j] = XK_Right; - break; - case K_UP: - k[j] = XK_Up; - break; - } - break; - - case KT_SHIFT: - switch (kbe.kb_value) - { - case K_ALTGR: - k[j] = XK_Mode_switch; - break; - case K_ALT: - k[j] = (kbe.kb_index == 0x64 ? - XK_Alt_R : XK_Alt_L); - break; - case K_CTRL: - k[j] = (kbe.kb_index == 0x61 ? - XK_Control_R : XK_Control_L); - break; - case K_CTRLL: - k[j] = XK_Control_L; - break; - case K_CTRLR: - k[j] = XK_Control_R; - break; - case K_SHIFT: - k[j] = (kbe.kb_index == 0x36 ? - XK_Shift_R : XK_Shift_L); - break; - case K_SHIFTL: - k[j] = XK_Shift_L; - break; - case K_SHIFTR: - k[j] = XK_Shift_R; - break; - default: - break; - } - break; - - /* - * KT_ASCII keys accumulate a 3 digit decimal number that gets - * emitted when the shift state changes. We can't emulate that. - */ - case KT_ASCII: - break; - - case KT_LOCK: - if (kbe.kb_value == K_SHIFTLOCK) - k[j] = XK_Shift_Lock; - break; - -#ifdef KT_X - case KT_X: - /* depends on new keyboard symbols in file linux/keyboard.h */ - if(kbe.kb_value == K_XMENU) k[j] = XK_Menu; - if(kbe.kb_value == K_XTELEPHONE) k[j] = XK_telephone; - break; -#endif -#ifdef KT_XF - case KT_XF: - /* special linux keysyms which map directly to XF86 keysyms */ - k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00; - break; -#endif - - default: - break; - } - if (i < minKeyCode) - minKeyCode = i; - if (i > maxKeyCode) - maxKeyCode = i; - } - - if (minKeyCode == NR_KEYS) - continue; - - if (k[3] == k[2]) k[3] = NoSymbol; - if (k[2] == k[1]) k[2] = NoSymbol; - if (k[1] == k[0]) k[1] = NoSymbol; - if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; - if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol; - row++; - } - ki->minScanCode = minKeyCode; - ki->maxScanCode = maxKeyCode; -#endif -} - -/* - * We need these to handle extended scancodes correctly (I could just use the - * numbers below, but this makes the code more readable - */ - -/* The prefix codes */ -#define KEY_Prefix0 /* special 0x60 */ 96 -#define KEY_Prefix1 /* special 0x61 */ 97 - -/* The raw scancodes */ -#define KEY_Enter /* Enter 0x1c */ 28 -#define KEY_LCtrl /* Ctrl(left) 0x1d */ 29 -#define KEY_Slash /* / (Slash) ? 0x35 */ 53 -#define KEY_KP_Multiply /* * 0x37 */ 55 -#define KEY_Alt /* Alt(left) 0x38 */ 56 -#define KEY_F3 /* F3 0x3d */ 61 -#define KEY_F4 /* F4 0x3e */ 62 -#define KEY_F5 /* F5 0x3f */ 63 -#define KEY_F6 /* F6 0x40 */ 64 -#define KEY_F7 /* F7 0x41 */ 65 -#define KEY_ScrollLock /* ScrollLock 0x46 */ 70 -#define KEY_KP_7 /* 7 Home 0x47 */ 71 -#define KEY_KP_8 /* 8 Up 0x48 */ 72 -#define KEY_KP_9 /* 9 PgUp 0x49 */ 73 -#define KEY_KP_Minus /* - (Minus) 0x4a */ 74 -#define KEY_KP_4 /* 4 Left 0x4b */ 75 -#define KEY_KP_5 /* 5 0x4c */ 76 -#define KEY_KP_6 /* 6 Right 0x4d */ 77 -#define KEY_KP_Plus /* + (Plus) 0x4e */ 78 -#define KEY_KP_1 /* 1 End 0x4f */ 79 -#define KEY_KP_2 /* 2 Down 0x50 */ 80 -#define KEY_KP_3 /* 3 PgDown 0x51 */ 81 -#define KEY_KP_0 /* 0 Insert 0x52 */ 82 -#define KEY_KP_Decimal /* . (Decimal) Delete 0x53 */ 83 -#define KEY_Home /* Home 0x59 */ 89 -#define KEY_Up /* Up 0x5a */ 90 -#define KEY_PgUp /* PgUp 0x5b */ 91 -#define KEY_Left /* Left 0x5c */ 92 -#define KEY_Begin /* Begin 0x5d */ 93 -#define KEY_Right /* Right 0x5e */ 94 -#define KEY_End /* End 0x5f */ 95 -#define KEY_Down /* Down 0x60 */ 96 -#define KEY_PgDown /* PgDown 0x61 */ 97 -#define KEY_Insert /* Insert 0x62 */ 98 -#define KEY_Delete /* Delete 0x63 */ 99 -#define KEY_KP_Enter /* Enter 0x64 */ 100 -#define KEY_RCtrl /* Ctrl(right) 0x65 */ 101 -#define KEY_Pause /* Pause 0x66 */ 102 -#define KEY_Print /* Print 0x67 */ 103 -#define KEY_KP_Divide /* Divide 0x68 */ 104 -#define KEY_AltLang /* AtlLang(right) 0x69 */ 105 -#define KEY_Break /* Break 0x6a */ 106 -#define KEY_LMeta /* Left Meta 0x6b */ 107 -#define KEY_RMeta /* Right Meta 0x6c */ 108 -#define KEY_Menu /* Menu 0x6d */ 109 -#define KEY_F13 /* F13 0x6e */ 110 -#define KEY_F14 /* F14 0x6f */ 111 -#define KEY_F15 /* F15 0x70 */ 112 -#define KEY_F16 /* F16 0x71 */ 113 -#define KEY_F17 /* F17 0x72 */ 114 -#define KEY_KP_DEC /* KP_DEC 0x73 */ 115 - -static void -LinuxKeyboardRead (int fd, void *closure) -{ - unsigned char buf[256], *b; - int n; - unsigned char prefix = 0, scancode = 0; - - while ((n = read (fd, buf, sizeof (buf))) > 0) { - b = buf; - while (n--) { - /* - * With xkb we use RAW mode for reading the console, which allows us - * process extended scancodes. - * - * See if this is a prefix extending the following keycode - */ - if (!prefix && ((b[0] & 0x7f) == KEY_Prefix0)) - { - prefix = KEY_Prefix0; - /* swallow this up */ - b++; - continue; - } - else if (!prefix && ((b[0] & 0x7f) == KEY_Prefix1)) - { - prefix = KEY_Prefix1; - /* swallow this up */ - b++; - continue; - } - scancode = b[0] & 0x7f; - - switch (prefix) { - /* from xf86Events.c */ - case KEY_Prefix0: - { - switch (scancode) { - case KEY_KP_7: - scancode = KEY_Home; break; /* curs home */ - case KEY_KP_8: - scancode = KEY_Up; break; /* curs up */ - case KEY_KP_9: - scancode = KEY_PgUp; break; /* curs pgup */ - case KEY_KP_4: - scancode = KEY_Left; break; /* curs left */ - case KEY_KP_5: - scancode = KEY_Begin; break; /* curs begin */ - case KEY_KP_6: - scancode = KEY_Right; break; /* curs right */ - case KEY_KP_1: - scancode = KEY_End; break; /* curs end */ - case KEY_KP_2: - scancode = KEY_Down; break; /* curs down */ - case KEY_KP_3: - scancode = KEY_PgDown; break; /* curs pgdown */ - case KEY_KP_0: - scancode = KEY_Insert; break; /* curs insert */ - case KEY_KP_Decimal: - scancode = KEY_Delete; break; /* curs delete */ - case KEY_Enter: - scancode = KEY_KP_Enter; break; /* keypad enter */ - case KEY_LCtrl: - scancode = KEY_RCtrl; break; /* right ctrl */ - case KEY_KP_Multiply: - scancode = KEY_Print; break; /* print */ - case KEY_Slash: - scancode = KEY_KP_Divide; break; /* keyp divide */ - case KEY_Alt: - scancode = KEY_AltLang; break; /* right alt */ - case KEY_ScrollLock: - scancode = KEY_Break; break; /* curs break */ - case 0x5b: - scancode = KEY_LMeta; break; - case 0x5c: - scancode = KEY_RMeta; break; - case 0x5d: - scancode = KEY_Menu; break; - case KEY_F3: - scancode = KEY_F13; break; - case KEY_F4: - scancode = KEY_F14; break; - case KEY_F5: - scancode = KEY_F15; break; - case KEY_F6: - scancode = KEY_F16; break; - case KEY_F7: - scancode = KEY_F17; break; - case KEY_KP_Plus: - scancode = KEY_KP_DEC; break; - /* Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */ - case 0x2A: - case 0x36: - b++; - prefix = 0; - continue; - default: - /* - * "Internet" keyboards are generating lots of new - * codes. Let them pass. There is little consistency - * between them, so don't bother with symbolic names at - * this level. - */ - scancode += 0x78; - } - break; - } - - case KEY_Prefix1: - { - /* we do no handle these */ - b++; - prefix = 0; - continue; - } - - default: /* should not happen*/ - case 0: /* do nothing */ - ; - } - - prefix = 0; - KdEnqueueKeyboardEvent (closure, scancode, b[0] & 0x80); - b++; - } - } -} - -static int LinuxKbdTrans; -static struct termios LinuxTermios; - -static Status -LinuxKeyboardEnable (KdKeyboardInfo *ki) -{ - struct termios nTty; - unsigned char buf[256]; - int n; - int fd; - - if (!ki) - return !Success; - - fd = LinuxConsoleFd; - ki->driverPrivate = (void *) fd; - - ioctl (fd, KDGKBMODE, &LinuxKbdTrans); - tcgetattr (fd, &LinuxTermios); - ioctl(fd, KDSKBMODE, K_RAW); - nTty = LinuxTermios; - nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); - nTty.c_oflag = 0; - nTty.c_cflag = CREAD | CS8; - nTty.c_lflag = 0; - nTty.c_cc[VTIME]=0; - nTty.c_cc[VMIN]=1; - cfsetispeed(&nTty, 9600); - cfsetospeed(&nTty, 9600); - tcsetattr(fd, TCSANOW, &nTty); - /* - * Flush any pending keystrokes - */ - while ((n = read (fd, buf, sizeof (buf))) > 0) - ; - KdRegisterFd (fd, LinuxKeyboardRead, ki); - return Success; -} - -static void -LinuxKeyboardDisable (KdKeyboardInfo *ki) -{ - int fd; - - if (!ki) - return; - - fd = (int) ki->driverPrivate; - - KdUnregisterFd(ki, fd, FALSE); - ioctl(fd, KDSKBMODE, LinuxKbdTrans); - tcsetattr(fd, TCSANOW, &LinuxTermios); -} - -static Status -LinuxKeyboardInit (KdKeyboardInfo *ki) -{ - if (!ki) - return !Success; - - xfree(ki->path); - ki->path = strdup("console"); - xfree(ki->name); - ki->name = strdup("Linux console keyboard"); - - readKernelMapping (ki); - - return Success; -} - -static void -LinuxKeyboardLeds (KdKeyboardInfo *ki, int leds) -{ - if (!ki) - return; - - ioctl ((int)ki->driverPrivate, KDSETLED, leds & 7); -} - -KdKeyboardDriver LinuxKeyboardDriver = { - "keyboard", - .Init = LinuxKeyboardInit, - .Enable = LinuxKeyboardEnable, - .Leds = LinuxKeyboardLeds, - .Disable = LinuxKeyboardDisable, -}; +/* + * Copyright © 1999 Keith Packard + * XKB integration © 2006 Nokia Corporation, author: Tomas Frydrych <tf@o-hand.com> + * + * LinuxKeyboardRead() XKB code based on xf86KbdLnx.c: + * Copyright © 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * Copyright © 1994-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_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" +#include <linux/keyboard.h> +#include <linux/kd.h> +#define XK_PUBLISHING +#include <X11/keysym.h> +#include <termios.h> +#include <sys/ioctl.h> + +extern int LinuxConsoleFd; + +static const KeySym linux_to_x[256] = { + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, + XK_currency, XK_yen, XK_brokenbar, XK_section, + XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, + XK_notsign, XK_hyphen, XK_registered, XK_macron, + XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, + XK_acute, XK_mu, XK_paragraph, XK_periodcentered, + XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, + XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, + XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, + XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, + XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, + XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, + XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, + XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, + XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, + XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, + XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, + XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, + XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, + XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, + XK_eth, XK_ntilde, XK_ograve, XK_oacute, + XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, + XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, + XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis +}; + +/* + * Getting a keycode from scancode + * + * With XKB + * -------- + * + * We have to enqueue keyboard events using standard X keycodes which correspond + * to AT scancode + 8; this means that we need to translate the Linux scancode + * provided by the kernel to an AT scancode -- this translation is not linear + * and requires that we use a LUT. + * + * + * Without XKB + * ----------- + * + * We can use custom keycodes, which makes things simpler; we define our custom + * keycodes as Linux scancodes + KD_KEY_OFFSET +*/ + +/* + This LUT translates AT scancodes into Linux ones -- the keymap we create + for the core X keyboard protocol has to be AT-scancode based so that it + corresponds to the Xkb keymap. +*/ +#if 0 +static unsigned char at2lnx[] = +{ + 0x0, /* no valid scancode */ + 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ + 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ + 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ + 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ + 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ + 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ + 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ + 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ + 0x11, /* KEY_W */ 0x12, /* KEY_E */ + 0x13, /* KEY_R */ 0x14, /* KEY_T */ + 0x15, /* KEY_Y */ 0x16, /* KEY_U */ + 0x17, /* KEY_I */ 0x18, /* KEY_O */ + 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ + 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ + 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ + 0x1f, /* KEY_S */ 0x20, /* KEY_D */ + 0x21, /* KEY_F */ 0x22, /* KEY_G */ + 0x23, /* KEY_H */ 0x24, /* KEY_J */ + 0x25, /* KEY_K */ 0x26, /* KEY_L */ + 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ + 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ + 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ + 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ + 0x2f, /* KEY_V */ 0x30, /* KEY_B */ + 0x31, /* KEY_N */ 0x32, /* KEY_M */ + 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ + 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ + 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ + 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ + 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ + 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ + 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ + 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ + 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ + 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ + 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ + 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ + 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ + 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ + 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ + 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ + 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ + 0x00, /* 0x55 */ 0x56, /* KEY_Less */ + 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ + 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ + 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ + 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ + 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ + 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ + 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ + 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ + 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ + 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ + 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ + 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ + 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ + 0x00, /* 0x71 */ 0x00, /* 0x72 */ + 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ + 0x00, /* 0x75 */ 0x00, /* 0x76 */ + 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ + 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ + 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ + 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ + 0x00, /* 0x7f */ +}; + +#define NUM_AT_KEYS (sizeof(at2lnx)/sizeof(at2lnx[0])) +#define LNX_KEY_INDEX(n) n < NUM_AT_KEYS ? at2lnx[n] : 0 + +static unsigned char tbl[KD_MAX_WIDTH] = +{ + 0, + 1 << KG_SHIFT, + (1 << KG_ALTGR), + (1 << KG_ALTGR) | (1 << KG_SHIFT) +}; +#endif + +static void +readKernelMapping(KdKeyboardInfo *ki) +{ +#if 0 + KeySym *k; + int i, j; + struct kbentry kbe; + int minKeyCode, maxKeyCode; + int row; + int fd; + + if (!ki) + return; + + fd = LinuxConsoleFd; + + minKeyCode = NR_KEYS; + maxKeyCode = 0; + row = 0; + ki->keySyms.mapWidth = KD_MAX_WIDTH; + for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i) + { + kbe.kb_index = LNX_KEY_INDEX(i); + + k = ki->keySyms.map + row * ki->keySyms.mapWidth; + + for (j = 0; j < ki->keySyms.mapWidth; ++j) + { + unsigned short kval; + + k[j] = NoSymbol; + + kbe.kb_table = tbl[j]; + kbe.kb_value = 0; + if (ioctl(fd, KDGKBENT, &kbe)) + continue; + + kval = KVAL(kbe.kb_value); + switch (KTYP(kbe.kb_value)) + { + case KT_LATIN: + case KT_LETTER: + k[j] = linux_to_x[kval]; + break; + + case KT_FN: + if (kval <= 19) + k[j] = XK_F1 + kval; + else switch (kbe.kb_value) + { + case K_FIND: + k[j] = XK_Home; /* or XK_Find */ + break; + case K_INSERT: + k[j] = XK_Insert; + break; + case K_REMOVE: + k[j] = XK_Delete; + break; + case K_SELECT: + k[j] = XK_End; /* or XK_Select */ + break; + case K_PGUP: + k[j] = XK_Prior; + break; + case K_PGDN: + k[j] = XK_Next; + break; + case K_HELP: + k[j] = XK_Help; + break; + case K_DO: + k[j] = XK_Execute; + break; + case K_PAUSE: + k[j] = XK_Pause; + break; + case K_MACRO: + k[j] = XK_Menu; + break; + default: + break; + } + break; + + case KT_SPEC: + switch (kbe.kb_value) + { + case K_ENTER: + k[j] = XK_Return; + break; + case K_BREAK: + k[j] = XK_Break; + break; + case K_CAPS: + k[j] = XK_Caps_Lock; + break; + case K_NUM: + k[j] = XK_Num_Lock; + break; + case K_HOLD: + k[j] = XK_Scroll_Lock; + break; + case K_COMPOSE: + k[j] = XK_Multi_key; + break; + default: + break; + } + break; + + case KT_PAD: + switch (kbe.kb_value) + { + case K_PPLUS: + k[j] = XK_KP_Add; + break; + case K_PMINUS: + k[j] = XK_KP_Subtract; + break; + case K_PSTAR: + k[j] = XK_KP_Multiply; + break; + case K_PSLASH: + k[j] = XK_KP_Divide; + break; + case K_PENTER: + k[j] = XK_KP_Enter; + break; + case K_PCOMMA: + k[j] = XK_KP_Separator; + break; + case K_PDOT: + k[j] = XK_KP_Decimal; + break; + case K_PPLUSMINUS: + k[j] = XK_KP_Subtract; + break; + default: + if (kval <= 9) + k[j] = XK_KP_0 + kval; + break; + } + break; + + /* + * KT_DEAD keys are for accelerated diacritical creation. + */ + case KT_DEAD: + switch (kbe.kb_value) + { + case K_DGRAVE: + k[j] = XK_dead_grave; + break; + case K_DACUTE: + k[j] = XK_dead_acute; + break; + case K_DCIRCM: + k[j] = XK_dead_circumflex; + break; + case K_DTILDE: + k[j] = XK_dead_tilde; + break; + case K_DDIERE: + k[j] = XK_dead_diaeresis; + break; + } + break; + + case KT_CUR: + switch (kbe.kb_value) + { + case K_DOWN: + k[j] = XK_Down; + break; + case K_LEFT: + k[j] = XK_Left; + break; + case K_RIGHT: + k[j] = XK_Right; + break; + case K_UP: + k[j] = XK_Up; + break; + } + break; + + case KT_SHIFT: + switch (kbe.kb_value) + { + case K_ALTGR: + k[j] = XK_Mode_switch; + break; + case K_ALT: + k[j] = (kbe.kb_index == 0x64 ? + XK_Alt_R : XK_Alt_L); + break; + case K_CTRL: + k[j] = (kbe.kb_index == 0x61 ? + XK_Control_R : XK_Control_L); + break; + case K_CTRLL: + k[j] = XK_Control_L; + break; + case K_CTRLR: + k[j] = XK_Control_R; + break; + case K_SHIFT: + k[j] = (kbe.kb_index == 0x36 ? + XK_Shift_R : XK_Shift_L); + break; + case K_SHIFTL: + k[j] = XK_Shift_L; + break; + case K_SHIFTR: + k[j] = XK_Shift_R; + break; + default: + break; + } + break; + + /* + * KT_ASCII keys accumulate a 3 digit decimal number that gets + * emitted when the shift state changes. We can't emulate that. + */ + case KT_ASCII: + break; + + case KT_LOCK: + if (kbe.kb_value == K_SHIFTLOCK) + k[j] = XK_Shift_Lock; + break; + +#ifdef KT_X + case KT_X: + /* depends on new keyboard symbols in file linux/keyboard.h */ + if(kbe.kb_value == K_XMENU) k[j] = XK_Menu; + if(kbe.kb_value == K_XTELEPHONE) k[j] = XK_telephone; + break; +#endif +#ifdef KT_XF + case KT_XF: + /* special linux keysyms which map directly to XF86 keysyms */ + k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00; + break; +#endif + + default: + break; + } + if (i < minKeyCode) + minKeyCode = i; + if (i > maxKeyCode) + maxKeyCode = i; + } + + if (minKeyCode == NR_KEYS) + continue; + + if (k[3] == k[2]) k[3] = NoSymbol; + if (k[2] == k[1]) k[2] = NoSymbol; + if (k[1] == k[0]) k[1] = NoSymbol; + if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol; + if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol; + row++; + } + ki->minScanCode = minKeyCode; + ki->maxScanCode = maxKeyCode; +#endif +} + +/* + * We need these to handle extended scancodes correctly (I could just use the + * numbers below, but this makes the code more readable + */ + +/* The prefix codes */ +#define KEY_Prefix0 /* special 0x60 */ 96 +#define KEY_Prefix1 /* special 0x61 */ 97 + +/* The raw scancodes */ +#define KEY_Enter /* Enter 0x1c */ 28 +#define KEY_LCtrl /* Ctrl(left) 0x1d */ 29 +#define KEY_Slash /* / (Slash) ? 0x35 */ 53 +#define KEY_KP_Multiply /* * 0x37 */ 55 +#define KEY_Alt /* Alt(left) 0x38 */ 56 +#define KEY_F3 /* F3 0x3d */ 61 +#define KEY_F4 /* F4 0x3e */ 62 +#define KEY_F5 /* F5 0x3f */ 63 +#define KEY_F6 /* F6 0x40 */ 64 +#define KEY_F7 /* F7 0x41 */ 65 +#define KEY_ScrollLock /* ScrollLock 0x46 */ 70 +#define KEY_KP_7 /* 7 Home 0x47 */ 71 +#define KEY_KP_8 /* 8 Up 0x48 */ 72 +#define KEY_KP_9 /* 9 PgUp 0x49 */ 73 +#define KEY_KP_Minus /* - (Minus) 0x4a */ 74 +#define KEY_KP_4 /* 4 Left 0x4b */ 75 +#define KEY_KP_5 /* 5 0x4c */ 76 +#define KEY_KP_6 /* 6 Right 0x4d */ 77 +#define KEY_KP_Plus /* + (Plus) 0x4e */ 78 +#define KEY_KP_1 /* 1 End 0x4f */ 79 +#define KEY_KP_2 /* 2 Down 0x50 */ 80 +#define KEY_KP_3 /* 3 PgDown 0x51 */ 81 +#define KEY_KP_0 /* 0 Insert 0x52 */ 82 +#define KEY_KP_Decimal /* . (Decimal) Delete 0x53 */ 83 +#define KEY_Home /* Home 0x59 */ 89 +#define KEY_Up /* Up 0x5a */ 90 +#define KEY_PgUp /* PgUp 0x5b */ 91 +#define KEY_Left /* Left 0x5c */ 92 +#define KEY_Begin /* Begin 0x5d */ 93 +#define KEY_Right /* Right 0x5e */ 94 +#define KEY_End /* End 0x5f */ 95 +#define KEY_Down /* Down 0x60 */ 96 +#define KEY_PgDown /* PgDown 0x61 */ 97 +#define KEY_Insert /* Insert 0x62 */ 98 +#define KEY_Delete /* Delete 0x63 */ 99 +#define KEY_KP_Enter /* Enter 0x64 */ 100 +#define KEY_RCtrl /* Ctrl(right) 0x65 */ 101 +#define KEY_Pause /* Pause 0x66 */ 102 +#define KEY_Print /* Print 0x67 */ 103 +#define KEY_KP_Divide /* Divide 0x68 */ 104 +#define KEY_AltLang /* AtlLang(right) 0x69 */ 105 +#define KEY_Break /* Break 0x6a */ 106 +#define KEY_LMeta /* Left Meta 0x6b */ 107 +#define KEY_RMeta /* Right Meta 0x6c */ 108 +#define KEY_Menu /* Menu 0x6d */ 109 +#define KEY_F13 /* F13 0x6e */ 110 +#define KEY_F14 /* F14 0x6f */ 111 +#define KEY_F15 /* F15 0x70 */ 112 +#define KEY_F16 /* F16 0x71 */ 113 +#define KEY_F17 /* F17 0x72 */ 114 +#define KEY_KP_DEC /* KP_DEC 0x73 */ 115 + +static void +LinuxKeyboardRead (int fd, void *closure) +{ + unsigned char buf[256], *b; + int n; + unsigned char prefix = 0, scancode = 0; + + while ((n = read (fd, buf, sizeof (buf))) > 0) { + b = buf; + while (n--) { + /* + * With xkb we use RAW mode for reading the console, which allows us + * process extended scancodes. + * + * See if this is a prefix extending the following keycode + */ + if (!prefix && ((b[0] & 0x7f) == KEY_Prefix0)) + { + prefix = KEY_Prefix0; + /* swallow this up */ + b++; + continue; + } + else if (!prefix && ((b[0] & 0x7f) == KEY_Prefix1)) + { + prefix = KEY_Prefix1; + /* swallow this up */ + b++; + continue; + } + scancode = b[0] & 0x7f; + + switch (prefix) { + /* from xf86Events.c */ + case KEY_Prefix0: + { + switch (scancode) { + case KEY_KP_7: + scancode = KEY_Home; break; /* curs home */ + case KEY_KP_8: + scancode = KEY_Up; break; /* curs up */ + case KEY_KP_9: + scancode = KEY_PgUp; break; /* curs pgup */ + case KEY_KP_4: + scancode = KEY_Left; break; /* curs left */ + case KEY_KP_5: + scancode = KEY_Begin; break; /* curs begin */ + case KEY_KP_6: + scancode = KEY_Right; break; /* curs right */ + case KEY_KP_1: + scancode = KEY_End; break; /* curs end */ + case KEY_KP_2: + scancode = KEY_Down; break; /* curs down */ + case KEY_KP_3: + scancode = KEY_PgDown; break; /* curs pgdown */ + case KEY_KP_0: + scancode = KEY_Insert; break; /* curs insert */ + case KEY_KP_Decimal: + scancode = KEY_Delete; break; /* curs delete */ + case KEY_Enter: + scancode = KEY_KP_Enter; break; /* keypad enter */ + case KEY_LCtrl: + scancode = KEY_RCtrl; break; /* right ctrl */ + case KEY_KP_Multiply: + scancode = KEY_Print; break; /* print */ + case KEY_Slash: + scancode = KEY_KP_Divide; break; /* keyp divide */ + case KEY_Alt: + scancode = KEY_AltLang; break; /* right alt */ + case KEY_ScrollLock: + scancode = KEY_Break; break; /* curs break */ + case 0x5b: + scancode = KEY_LMeta; break; + case 0x5c: + scancode = KEY_RMeta; break; + case 0x5d: + scancode = KEY_Menu; break; + case KEY_F3: + scancode = KEY_F13; break; + case KEY_F4: + scancode = KEY_F14; break; + case KEY_F5: + scancode = KEY_F15; break; + case KEY_F6: + scancode = KEY_F16; break; + case KEY_F7: + scancode = KEY_F17; break; + case KEY_KP_Plus: + scancode = KEY_KP_DEC; break; + /* Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */ + case 0x2A: + case 0x36: + b++; + prefix = 0; + continue; + default: + /* + * "Internet" keyboards are generating lots of new + * codes. Let them pass. There is little consistency + * between them, so don't bother with symbolic names at + * this level. + */ + scancode += 0x78; + } + break; + } + + case KEY_Prefix1: + { + /* we do no handle these */ + b++; + prefix = 0; + continue; + } + + default: /* should not happen*/ + case 0: /* do nothing */ + ; + } + + prefix = 0; + KdEnqueueKeyboardEvent (closure, scancode, b[0] & 0x80); + b++; + } + } +} + +static int LinuxKbdTrans; +static struct termios LinuxTermios; + +static Status +LinuxKeyboardEnable (KdKeyboardInfo *ki) +{ + struct termios nTty; + unsigned char buf[256]; + int n; + int fd; + + if (!ki) + return !Success; + + fd = LinuxConsoleFd; + ki->driverPrivate = (void *) fd; + + ioctl (fd, KDGKBMODE, &LinuxKbdTrans); + tcgetattr (fd, &LinuxTermios); + ioctl(fd, KDSKBMODE, K_RAW); + nTty = LinuxTermios; + nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8; + nTty.c_lflag = 0; + nTty.c_cc[VTIME]=0; + nTty.c_cc[VMIN]=1; + cfsetispeed(&nTty, 9600); + cfsetospeed(&nTty, 9600); + tcsetattr(fd, TCSANOW, &nTty); + /* + * Flush any pending keystrokes + */ + while ((n = read (fd, buf, sizeof (buf))) > 0) + ; + KdRegisterFd (fd, LinuxKeyboardRead, ki); + return Success; +} + +static void +LinuxKeyboardDisable (KdKeyboardInfo *ki) +{ + int fd; + + if (!ki) + return; + + fd = (int) ki->driverPrivate; + + KdUnregisterFd(ki, fd, FALSE); + ioctl(fd, KDSKBMODE, LinuxKbdTrans); + tcsetattr(fd, TCSANOW, &LinuxTermios); +} + +static Status +LinuxKeyboardInit (KdKeyboardInfo *ki) +{ + if (!ki) + return !Success; + + free(ki->path); + ki->path = strdup("console"); + free(ki->name); + ki->name = strdup("Linux console keyboard"); + + readKernelMapping (ki); + + return Success; +} + +static void +LinuxKeyboardLeds (KdKeyboardInfo *ki, int leds) +{ + if (!ki) + return; + + ioctl ((int)ki->driverPrivate, KDSETLED, leds & 7); +} + +KdKeyboardDriver LinuxKeyboardDriver = { + "keyboard", + .Init = LinuxKeyboardInit, + .Enable = LinuxKeyboardEnable, + .Leds = LinuxKeyboardLeds, + .Disable = LinuxKeyboardDisable, +}; diff --git a/xorg-server/hw/kdrive/linux/mouse.c b/xorg-server/hw/kdrive/linux/mouse.c index 007263e4b..2e39d240e 100644 --- a/xorg-server/hw/kdrive/linux/mouse.c +++ b/xorg-server/hw/kdrive/linux/mouse.c @@ -1,1030 +1,1030 @@ -/* - * Copyright © 2001 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include <errno.h> -#include <termios.h> -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/Xpoll.h> -#include "inputstr.h" -#include "scrnintstr.h" -#include "kdrive.h" - -#undef DEBUG -#undef DEBUG_BYTES -#define KBUFIO_SIZE 256 -#define MOUSE_TIMEOUT 100 - -typedef struct _kbufio { - int fd; - unsigned char buf[KBUFIO_SIZE]; - int avail; - int used; -} Kbufio; - -static Bool -MouseWaitForReadable (int fd, int timeout) -{ - fd_set set; - struct timeval tv, *tp; - int n; - CARD32 done; - - done = GetTimeInMillis () + timeout; - for (;;) - { - FD_ZERO (&set); - FD_SET (fd, &set); - if (timeout == -1) - tp = 0; - else - { - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - tp = &tv; - } - n = select (fd + 1, &set, 0, 0, tp); - if (n > 0) - return TRUE; - if (n < 0 && (errno == EAGAIN || errno == EINTR)) - { - timeout = (int) (done - GetTimeInMillis ()); - if (timeout > 0) - continue; - } - break; - } - return FALSE; -} - -static int -MouseReadByte (Kbufio *b, int timeout) -{ - int n; - if (b->avail <= b->used) - { - if (timeout && !MouseWaitForReadable (b->fd, timeout)) - { -#ifdef DEBUG_BYTES - ErrorF ("\tTimeout %d\n", timeout); -#endif - return -1; - } - n = read (b->fd, b->buf, KBUFIO_SIZE); - if (n <= 0) - return -1; - b->avail = n; - b->used = 0; - } -#ifdef DEBUG_BYTES - ErrorF ("\tget %02x\n", b->buf[b->used]); -#endif - return b->buf[b->used++]; -} - -#if NOTUSED -static int -MouseFlush (Kbufio *b, char *buf, int size) -{ - CARD32 now = GetTimeInMillis (); - CARD32 done = now + 100; - int c; - int n = 0; - - while ((c = MouseReadByte (b, done - now)) != -1) - { - if (buf) - { - if (n == size) - { - memmove (buf, buf + 1, size - 1); - n--; - } - buf[n++] = c; - } - now = GetTimeInMillis (); - if ((INT32) (now - done) >= 0) - break; - } - return n; -} - -static int -MousePeekByte (Kbufio *b, int timeout) -{ - int c; - - c = MouseReadByte (b, timeout); - if (c != -1) - --b->used; - return c; -} -#endif /* NOTUSED */ - -static Bool -MouseWaitForWritable (int fd, int timeout) -{ - fd_set set; - struct timeval tv, *tp; - int n; - - FD_ZERO (&set); - FD_SET (fd, &set); - if (timeout == -1) - tp = 0; - else - { - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - tp = &tv; - } - n = select (fd + 1, 0, &set, 0, tp); - if (n > 0) - return TRUE; - return FALSE; -} - -static Bool -MouseWriteByte (int fd, unsigned char c, int timeout) -{ - int ret; - -#ifdef DEBUG_BYTES - ErrorF ("\tput %02x\n", c); -#endif - for (;;) - { - ret = write (fd, &c, 1); - if (ret == 1) - return TRUE; - if (ret == 0) - return FALSE; - if (errno != EWOULDBLOCK) - return FALSE; - if (!MouseWaitForWritable (fd, timeout)) - return FALSE; - } -} - -static Bool -MouseWriteBytes (int fd, unsigned char *c, int n, int timeout) -{ - while (n--) - if (!MouseWriteByte (fd, *c++, timeout)) - return FALSE; - return TRUE; -} - -#define MAX_MOUSE 10 /* maximum length of mouse protocol */ -#define MAX_SKIP 16 /* number of error bytes before switching */ -#define MAX_VALID 4 /* number of valid packets before accepting */ - -typedef struct _kmouseProt { - char *name; - Bool (*Complete) (KdPointerInfo *pi, unsigned char *ev, int ne); - int (*Valid) (KdPointerInfo *pi, unsigned char *ev, int ne); - Bool (*Parse) (KdPointerInfo *pi, unsigned char *ev, int ne); - Bool (*Init) (KdPointerInfo *pi); - unsigned char headerMask, headerValid; - unsigned char dataMask, dataValid; - Bool tty; - unsigned int c_iflag; - unsigned int c_oflag; - unsigned int c_lflag; - unsigned int c_cflag; - unsigned int speed; - unsigned char *init; - unsigned long state; -} KmouseProt; - -typedef enum _kmouseStage { - MouseBroken, MouseTesting, MouseWorking -} KmouseStage; - -typedef struct _kmouse { - Kbufio iob; - const KmouseProt *prot; - int i_prot; - KmouseStage stage; /* protocol verification stage */ - Bool tty; /* mouse device is a tty */ - int valid; /* sequential valid events */ - int tested; /* bytes scanned during Testing phase */ - int invalid;/* total invalid bytes for this protocol */ - unsigned long state; /* private per protocol, init to prot->state */ -} Kmouse; - -static int mouseValid (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - Kmouse *km = pi->driverPrivate; - const KmouseProt *prot = km->prot; - int i; - - for (i = 0; i < ne; i++) - if ((ev[i] & prot->headerMask) == prot->headerValid) - break; - if (i != 0) - return i; - for (i = 1; i < ne; i++) - if ((ev[i] & prot->dataMask) != prot->dataValid) - return -1; - return 0; -} - -static Bool threeComplete (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - return ne == 3; -} - -static Bool fourComplete (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - return ne == 4; -} - -static Bool fiveComplete (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - return ne == 5; -} - -static Bool MouseReasonable (KdPointerInfo *pi, unsigned long flags, int dx, int dy) -{ - Kmouse *km = pi->driverPrivate; - - if (km->stage == MouseWorking) - return TRUE; - if (dx < -50 || dx > 50) - { -#ifdef DEBUG - ErrorF ("Large X %d\n", dx); -#endif - return FALSE; - } - if (dy < -50 || dy > 50) - { -#ifdef DEBUG - ErrorF ("Large Y %d\n", dy); -#endif - return FALSE; - } - return TRUE; -} - -/* - * Standard PS/2 mouse protocol - */ -static Bool ps2Parse (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - Kmouse *km = pi->driverPrivate; - int dx, dy, dz; - unsigned long flags; - unsigned long flagsrelease = 0; - - flags = KD_MOUSE_DELTA; - if (ev[0] & 4) - flags |= KD_BUTTON_2; - if (ev[0] & 2) - flags |= KD_BUTTON_3; - if (ev[0] & 1) - flags |= KD_BUTTON_1; - - if (ne > 3) - { - dz = (int) (signed char) ev[3]; - if (dz < 0) - { - flags |= KD_BUTTON_4; - flagsrelease = KD_BUTTON_4; - } - else if (dz > 0) - { - flags |= KD_BUTTON_5; - flagsrelease = KD_BUTTON_5; - } - } - - dx = ev[1]; - if (ev[0] & 0x10) - dx -= 256; - dy = ev[2]; - if (ev[0] & 0x20) - dy -= 256; - dy = -dy; - if (!MouseReasonable (pi, flags, dx, dy)) - return FALSE; - if (km->stage == MouseWorking) - { - KdEnqueuePointerEvent (pi, flags, dx, dy, 0); - if (flagsrelease) - { - flags &= ~flagsrelease; - KdEnqueuePointerEvent (pi, flags, dx, dy, 0); - } - } - return TRUE; -} - -static Bool ps2Init (KdPointerInfo *pi); - -static const KmouseProt ps2Prot = { - "ps/2", - threeComplete, mouseValid, ps2Parse, ps2Init, - 0x08, 0x08, 0x00, 0x00, - FALSE -}; - -static const KmouseProt imps2Prot = { - "imps/2", - fourComplete, mouseValid, ps2Parse, ps2Init, - 0x08, 0x08, 0x00, 0x00, - FALSE -}; - -static const KmouseProt exps2Prot = { - "exps/2", - fourComplete, mouseValid, ps2Parse, ps2Init, - 0x08, 0x08, 0x00, 0x00, - FALSE -}; - -/* - * Once the mouse is known to speak ps/2 protocol, go and find out - * what advanced capabilities it has and turn them on - */ - -/* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */ - -/* aux device commands (sent to KBD_DATA_PORT) */ -#define PSMC_SET_SCALING11 0x00e6 -#define PSMC_SET_SCALING21 0x00e7 -#define PSMC_SET_RESOLUTION 0x00e8 -#define PSMC_SEND_DEV_STATUS 0x00e9 -#define PSMC_SET_STREAM_MODE 0x00ea -#define PSMC_SEND_DEV_DATA 0x00eb -#define PSMC_SET_REMOTE_MODE 0x00f0 -#define PSMC_SEND_DEV_ID 0x00f2 -#define PSMC_SET_SAMPLING_RATE 0x00f3 -#define PSMC_ENABLE_DEV 0x00f4 -#define PSMC_DISABLE_DEV 0x00f5 -#define PSMC_SET_DEFAULTS 0x00f6 -#define PSMC_RESET_DEV 0x00ff - -/* PSMC_SET_RESOLUTION argument */ -#define PSMD_RES_LOW 0 /* typically 25ppi */ -#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */ -#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */ -#define PSMD_RES_HIGH 3 /* typically 200ppi */ -#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH - -/* PSMC_SET_SAMPLING_RATE */ -#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */ - -/* aux device ID */ -#define PSM_MOUSE_ID 0 -#define PSM_BALLPOINT_ID 2 -#define PSM_INTELLI_ID 3 -#define PSM_EXPLORER_ID 4 -#define PSM_4DMOUSE_ID 6 -#define PSM_4DPLUS_ID 8 - -static unsigned char ps2_init[] = { - PSMC_ENABLE_DEV, - 0, -}; - -#define NINIT_PS2 1 - -static unsigned char wheel_3button_init[] = { - PSMC_SET_SAMPLING_RATE, 200, - PSMC_SET_SAMPLING_RATE, 100, - PSMC_SET_SAMPLING_RATE, 80, - PSMC_SEND_DEV_ID, - 0, -}; - -#define NINIT_IMPS2 4 - -static unsigned char wheel_5button_init[] = { - PSMC_SET_SAMPLING_RATE, 200, - PSMC_SET_SAMPLING_RATE, 100, - PSMC_SET_SAMPLING_RATE, 80, - PSMC_SET_SAMPLING_RATE, 200, - PSMC_SET_SAMPLING_RATE, 200, - PSMC_SET_SAMPLING_RATE, 80, - PSMC_SEND_DEV_ID, - 0 -}; - -#define NINIT_EXPS2 7 - -static unsigned char intelli_init[] = { - PSMC_SET_SAMPLING_RATE, 200, - PSMC_SET_SAMPLING_RATE, 100, - PSMC_SET_SAMPLING_RATE, 80, - 0 -}; - -#define NINIT_INTELLI 3 - -static int -ps2SkipInit (KdPointerInfo *pi, int ninit, Bool ret_next) -{ - Kmouse *km = pi->driverPrivate; - int c = -1; - int skipping; - Bool waiting; - - skipping = 0; - waiting = FALSE; - while (ninit || ret_next) - { - c = MouseReadByte (&km->iob, MOUSE_TIMEOUT); - if (c == -1) - break; - /* look for ACK */ - if (c == 0xfa) - { - ninit--; - if (ret_next) - waiting = TRUE; - } - /* look for packet start -- not the response */ - else if ((c & 0x08) == 0x08) - waiting = FALSE; - else if (waiting) - break; - } - return c; -} - -static Bool -ps2Init (KdPointerInfo *pi) -{ - Kmouse *km = pi->driverPrivate; - int skipping; - Bool waiting; - int id; - unsigned char *init; - int ninit; - - /* Send Intellimouse initialization sequence */ - MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *) intelli_init), 100); - /* - * Send ID command - */ - if (!MouseWriteByte (km->iob.fd, PSMC_SEND_DEV_ID, 100)) - return FALSE; - skipping = 0; - waiting = FALSE; - id = ps2SkipInit (pi, 0, TRUE); - switch (id) { - case 3: - init = wheel_3button_init; - ninit = NINIT_IMPS2; - km->prot = &imps2Prot; - break; - case 4: - init = wheel_5button_init; - ninit = NINIT_EXPS2; - km->prot = &exps2Prot; - break; - default: - init = ps2_init; - ninit = NINIT_PS2; - km->prot = &ps2Prot; - break; - } - if (init) - MouseWriteBytes (km->iob.fd, init, strlen ((char *) init), 100); - /* - * Flush out the available data to eliminate responses to the - * initialization string. Make sure any partial event is - * skipped - */ - (void) ps2SkipInit (pi, ninit, FALSE); - return TRUE; -} - -static Bool busParse (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - Kmouse *km = pi->driverPrivate; - int dx, dy; - unsigned long flags; - - flags = KD_MOUSE_DELTA; - dx = (signed char) ev[1]; - dy = -(signed char) ev[2]; - if ((ev[0] & 4) == 0) - flags |= KD_BUTTON_1; - if ((ev[0] & 2) == 0) - flags |= KD_BUTTON_2; - if ((ev[0] & 1) == 0) - flags |= KD_BUTTON_3; - if (!MouseReasonable (pi, flags, dx, dy)) - return FALSE; - if (km->stage == MouseWorking) - KdEnqueuePointerEvent (pi, flags, dx, dy, 0); - return TRUE; -} - -static const KmouseProt busProt = { - "bus", - threeComplete, mouseValid, busParse, 0, - 0xf8, 0x00, 0x00, 0x00, - FALSE -}; - -/* - * Standard MS serial protocol, three bytes - */ - -static Bool msParse (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - Kmouse *km = pi->driverPrivate; - int dx, dy; - unsigned long flags; - - flags = KD_MOUSE_DELTA; - - if (ev[0] & 0x20) - flags |= KD_BUTTON_1; - if (ev[0] & 0x10) - flags |= KD_BUTTON_3; - - dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F)); - dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F)); - if (!MouseReasonable (pi, flags, dx, dy)) - return FALSE; - if (km->stage == MouseWorking) - KdEnqueuePointerEvent (pi, flags, dx, dy, 0); - return TRUE; -} - -static const KmouseProt msProt = { - "ms", - threeComplete, mouseValid, msParse, 0, - 0xc0, 0x40, 0xc0, 0x00, - TRUE, - IGNPAR, - 0, - 0, - CS7 | CSTOPB | CREAD | CLOCAL, - B1200, -}; - -/* - * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the - * first byte of a synchronized protocol stream and see if it's got - * any bits turned on that can't occur in that fourth byte - */ -static Bool logiComplete (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - Kmouse *km = pi->driverPrivate; - - if ((ev[0] & 0x40) == 0x40) - return ne == 3; - if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0) - return ne == 1; - return FALSE; -} - -static int logiValid (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - Kmouse *km = pi->driverPrivate; - const KmouseProt *prot = km->prot; - int i; - - for (i = 0; i < ne; i++) - { - if ((ev[i] & 0x40) == 0x40) - break; - if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0) - break; - } - if (i != 0) - return i; - for (i = 1; i < ne; i++) - if ((ev[i] & prot->dataMask) != prot->dataValid) - return -1; - return 0; -} - -static Bool logiParse (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - Kmouse *km = pi->driverPrivate; - int dx, dy; - unsigned long flags; - - flags = KD_MOUSE_DELTA; - - if (ne == 3) - { - if (ev[0] & 0x20) - flags |= KD_BUTTON_1; - if (ev[0] & 0x10) - flags |= KD_BUTTON_3; - - dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F)); - dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F)); - flags |= km->state & KD_BUTTON_2; - } - else - { - if (ev[0] & 0x20) - flags |= KD_BUTTON_2; - dx = 0; - dy = 0; - flags |= km->state & (KD_BUTTON_1|KD_BUTTON_3); - } - - if (!MouseReasonable (pi, flags, dx, dy)) - return FALSE; - if (km->stage == MouseWorking) - KdEnqueuePointerEvent (pi, flags, dx, dy, 0); - return TRUE; -} - -static const KmouseProt logiProt = { - "logitech", - logiComplete, logiValid, logiParse, 0, - 0xc0, 0x40, 0xc0, 0x00, - TRUE, - IGNPAR, - 0, - 0, - CS7 | CSTOPB | CREAD | CLOCAL, - B1200, -}; - -/* - * Mouse systems protocol, 5 bytes - */ -static Bool mscParse (KdPointerInfo *pi, unsigned char *ev, int ne) -{ - Kmouse *km = pi->driverPrivate; - int dx, dy; - unsigned long flags; - - flags = KD_MOUSE_DELTA; - - if (!(ev[0] & 0x4)) - flags |= KD_BUTTON_1; - if (!(ev[0] & 0x2)) - flags |= KD_BUTTON_2; - if (!(ev[0] & 0x1)) - flags |= KD_BUTTON_3; - dx = (signed char)(ev[1]) + (signed char)(ev[3]); - dy = - ((signed char)(ev[2]) + (signed char)(ev[4])); - - if (!MouseReasonable (pi, flags, dx, dy)) - return FALSE; - if (km->stage == MouseWorking) - KdEnqueuePointerEvent (pi, flags, dx, dy, 0); - return TRUE; -} - -static const KmouseProt mscProt = { - "msc", - fiveComplete, mouseValid, mscParse, 0, - 0xf8, 0x80, 0x00, 0x00, - TRUE, - IGNPAR, - 0, - 0, - CS8 | CSTOPB | CREAD | CLOCAL, - B1200, -}; - -/* - * Use logitech before ms -- they're the same except that - * logitech sometimes has a fourth byte - */ -static const KmouseProt *kmouseProts[] = { - &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, &mscProt, -}; - -#define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0])) - -static void -MouseInitProtocol (Kmouse *km) -{ - int ret; - struct termios t; - - if (km->prot->tty) - { - ret = tcgetattr (km->iob.fd, &t); - - if (ret >= 0) - { - t.c_iflag = km->prot->c_iflag; - t.c_oflag = km->prot->c_oflag; - t.c_lflag = km->prot->c_lflag; - t.c_cflag = km->prot->c_cflag; - cfsetispeed (&t, km->prot->speed); - cfsetospeed (&t, km->prot->speed); - ret = tcsetattr (km->iob.fd, TCSANOW, &t); - } - } - km->stage = MouseBroken; - km->valid = 0; - km->tested = 0; - km->invalid = 0; - km->state = km->prot->state; -} - -static void -MouseFirstProtocol (Kmouse *km, char *prot) -{ - if (prot) - { - for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++) - if (!strcmp (prot, kmouseProts[km->i_prot]->name)) - break; - if (km->i_prot == NUM_PROT) - { - int i; - ErrorF ("Unknown mouse protocol \"%s\". Pick one of:", prot); - for (i = 0; i < NUM_PROT; i++) - ErrorF (" %s", kmouseProts[i]->name); - ErrorF ("\n"); - } - else - { - km->prot = kmouseProts[km->i_prot]; - if (km->tty && !km->prot->tty) - ErrorF ("Mouse device is serial port, protocol %s is not serial protocol\n", - prot); - else if (!km->tty && km->prot->tty) - ErrorF ("Mouse device is not serial port, protocol %s is serial protocol\n", - prot); - } - } - if (!km->prot) - { - for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; km->i_prot++) - ; - km->prot = kmouseProts[km->i_prot]; - } - MouseInitProtocol (km); -} - -static void -MouseNextProtocol (Kmouse *km) -{ - do - { - if (!km->prot) - km->i_prot = 0; - else - if (++km->i_prot == NUM_PROT) km->i_prot = 0; - km->prot = kmouseProts[km->i_prot]; - } while (km->prot->tty != km->tty); - MouseInitProtocol (km); - ErrorF ("Switching to mouse protocol \"%s\"\n", km->prot->name); -} - -static void -MouseRead (int mousePort, void *closure) -{ - KdPointerInfo *pi = closure; - Kmouse *km = pi->driverPrivate; - unsigned char event[MAX_MOUSE]; - int ne; - int c; - int i; - int timeout; - - timeout = 0; - ne = 0; - for(;;) - { - c = MouseReadByte (&km->iob, timeout); - if (c == -1) - { - if (ne) - { - km->invalid += ne + km->tested; - km->valid = 0; - km->tested = 0; - km->stage = MouseBroken; - } - break; - } - event[ne++] = c; - i = (*km->prot->Valid) (pi, event, ne); - if (i != 0) - { -#ifdef DEBUG - ErrorF ("Mouse protocol %s broken %d of %d bytes bad\n", - km->prot->name, i > 0 ? i : ne, ne); -#endif - if (i > 0 && i < ne) - { - ne -= i; - memmove (event, event + i, ne); - } - else - { - i = ne; - ne = 0; - } - km->invalid += i + km->tested; - km->valid = 0; - km->tested = 0; - if (km->stage == MouseWorking) - km->i_prot--; - km->stage = MouseBroken; - if (km->invalid > MAX_SKIP) - { - MouseNextProtocol (km); - ne = 0; - } - timeout = 0; - } - else - { - if ((*km->prot->Complete) (pi, event, ne)) - { - if ((*km->prot->Parse) (pi, event, ne)) - { - switch (km->stage) - { - case MouseBroken: -#ifdef DEBUG - ErrorF ("Mouse protocol %s seems OK\n", - km->prot->name); -#endif - /* do not zero invalid to accumulate invalid bytes */ - km->valid = 0; - km->tested = 0; - km->stage = MouseTesting; - /* fall through ... */ - case MouseTesting: - km->valid++; - km->tested += ne; - if (km->valid > MAX_VALID) - { -#ifdef DEBUG - ErrorF ("Mouse protocol %s working\n", - km->prot->name); -#endif - km->stage = MouseWorking; - km->invalid = 0; - km->tested = 0; - km->valid = 0; - if (km->prot->Init && !(*km->prot->Init) (pi)) - km->stage = MouseBroken; - } - break; - case MouseWorking: - break; - } - } - else - { - km->invalid += ne + km->tested; - km->valid = 0; - km->tested = 0; - km->stage = MouseBroken; - } - ne = 0; - timeout = 0; - } - else - timeout = MOUSE_TIMEOUT; - } - } -} - -int MouseInputType; - -char *kdefaultMouse[] = { - "/dev/input/mice", - "/dev/mouse", - "/dev/psaux", - "/dev/adbmouse", - "/dev/ttyS0", - "/dev/ttyS1", -}; - -#define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0])) - -static Status -MouseInit (KdPointerInfo *pi) -{ - int i; - int fd; - Kmouse *km; - - if (!pi) - return BadImplementation; - - if (!pi->path || strcmp(pi->path, "auto") == 0) { - for (i = 0; i < NUM_DEFAULT_MOUSE; i++) { - fd = open (kdefaultMouse[i], 2); - if (fd >= 0) { - pi->path = strdup (kdefaultMouse[i]); - break; - } - } - } - else { - fd = open (pi->path, 2); - } - - if (fd < 0) - return BadMatch; - - close(fd); - - km = (Kmouse *) xalloc (sizeof (Kmouse)); - if (km) { - km->iob.avail = km->iob.used = 0; - MouseFirstProtocol(km, pi->protocol ? pi->protocol : "exps/2"); - /* MouseFirstProtocol sets state to MouseBroken for later protocol - * checks. Skip these checks if a protocol was supplied */ - if (pi->protocol) - km->state = MouseWorking; - km->i_prot = 0; - km->tty = isatty (fd); - km->iob.fd = -1; - pi->driverPrivate = km; - } - else { - close (fd); - return BadAlloc; - } - - return Success; -} - -static Status -MouseEnable (KdPointerInfo *pi) -{ - Kmouse *km; - - if (!pi || !pi->driverPrivate || !pi->path) - return BadImplementation; - - km = pi->driverPrivate; - - km->iob.fd = open(pi->path, 2); - if (km->iob.fd < 0) - return BadMatch; - - if (!KdRegisterFd (km->iob.fd, MouseRead, pi)) - { - close(km->iob.fd); - return BadAlloc; - } - - return Success; -} - -static void -MouseDisable (KdPointerInfo *pi) -{ - Kmouse *km; - if (!pi || !pi->driverPrivate) - return; - - km = pi->driverPrivate; - KdUnregisterFd (pi, km->iob.fd, TRUE); -} - -static void -MouseFini (KdPointerInfo *pi) -{ - xfree (pi->driverPrivate); - pi->driverPrivate = NULL; -} - -KdPointerDriver LinuxMouseDriver = { - "mouse", - MouseInit, - MouseEnable, - MouseDisable, - MouseFini, - NULL, -}; +/* + * Copyright © 2001 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include <errno.h> +#include <termios.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xpoll.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "kdrive.h" + +#undef DEBUG +#undef DEBUG_BYTES +#define KBUFIO_SIZE 256 +#define MOUSE_TIMEOUT 100 + +typedef struct _kbufio { + int fd; + unsigned char buf[KBUFIO_SIZE]; + int avail; + int used; +} Kbufio; + +static Bool +MouseWaitForReadable (int fd, int timeout) +{ + fd_set set; + struct timeval tv, *tp; + int n; + CARD32 done; + + done = GetTimeInMillis () + timeout; + for (;;) + { + FD_ZERO (&set); + FD_SET (fd, &set); + if (timeout == -1) + tp = 0; + else + { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + tp = &tv; + } + n = select (fd + 1, &set, 0, 0, tp); + if (n > 0) + return TRUE; + if (n < 0 && (errno == EAGAIN || errno == EINTR)) + { + timeout = (int) (done - GetTimeInMillis ()); + if (timeout > 0) + continue; + } + break; + } + return FALSE; +} + +static int +MouseReadByte (Kbufio *b, int timeout) +{ + int n; + if (b->avail <= b->used) + { + if (timeout && !MouseWaitForReadable (b->fd, timeout)) + { +#ifdef DEBUG_BYTES + ErrorF ("\tTimeout %d\n", timeout); +#endif + return -1; + } + n = read (b->fd, b->buf, KBUFIO_SIZE); + if (n <= 0) + return -1; + b->avail = n; + b->used = 0; + } +#ifdef DEBUG_BYTES + ErrorF ("\tget %02x\n", b->buf[b->used]); +#endif + return b->buf[b->used++]; +} + +#if NOTUSED +static int +MouseFlush (Kbufio *b, char *buf, int size) +{ + CARD32 now = GetTimeInMillis (); + CARD32 done = now + 100; + int c; + int n = 0; + + while ((c = MouseReadByte (b, done - now)) != -1) + { + if (buf) + { + if (n == size) + { + memmove (buf, buf + 1, size - 1); + n--; + } + buf[n++] = c; + } + now = GetTimeInMillis (); + if ((INT32) (now - done) >= 0) + break; + } + return n; +} + +static int +MousePeekByte (Kbufio *b, int timeout) +{ + int c; + + c = MouseReadByte (b, timeout); + if (c != -1) + --b->used; + return c; +} +#endif /* NOTUSED */ + +static Bool +MouseWaitForWritable (int fd, int timeout) +{ + fd_set set; + struct timeval tv, *tp; + int n; + + FD_ZERO (&set); + FD_SET (fd, &set); + if (timeout == -1) + tp = 0; + else + { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + tp = &tv; + } + n = select (fd + 1, 0, &set, 0, tp); + if (n > 0) + return TRUE; + return FALSE; +} + +static Bool +MouseWriteByte (int fd, unsigned char c, int timeout) +{ + int ret; + +#ifdef DEBUG_BYTES + ErrorF ("\tput %02x\n", c); +#endif + for (;;) + { + ret = write (fd, &c, 1); + if (ret == 1) + return TRUE; + if (ret == 0) + return FALSE; + if (errno != EWOULDBLOCK) + return FALSE; + if (!MouseWaitForWritable (fd, timeout)) + return FALSE; + } +} + +static Bool +MouseWriteBytes (int fd, unsigned char *c, int n, int timeout) +{ + while (n--) + if (!MouseWriteByte (fd, *c++, timeout)) + return FALSE; + return TRUE; +} + +#define MAX_MOUSE 10 /* maximum length of mouse protocol */ +#define MAX_SKIP 16 /* number of error bytes before switching */ +#define MAX_VALID 4 /* number of valid packets before accepting */ + +typedef struct _kmouseProt { + char *name; + Bool (*Complete) (KdPointerInfo *pi, unsigned char *ev, int ne); + int (*Valid) (KdPointerInfo *pi, unsigned char *ev, int ne); + Bool (*Parse) (KdPointerInfo *pi, unsigned char *ev, int ne); + Bool (*Init) (KdPointerInfo *pi); + unsigned char headerMask, headerValid; + unsigned char dataMask, dataValid; + Bool tty; + unsigned int c_iflag; + unsigned int c_oflag; + unsigned int c_lflag; + unsigned int c_cflag; + unsigned int speed; + unsigned char *init; + unsigned long state; +} KmouseProt; + +typedef enum _kmouseStage { + MouseBroken, MouseTesting, MouseWorking +} KmouseStage; + +typedef struct _kmouse { + Kbufio iob; + const KmouseProt *prot; + int i_prot; + KmouseStage stage; /* protocol verification stage */ + Bool tty; /* mouse device is a tty */ + int valid; /* sequential valid events */ + int tested; /* bytes scanned during Testing phase */ + int invalid;/* total invalid bytes for this protocol */ + unsigned long state; /* private per protocol, init to prot->state */ +} Kmouse; + +static int mouseValid (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + const KmouseProt *prot = km->prot; + int i; + + for (i = 0; i < ne; i++) + if ((ev[i] & prot->headerMask) == prot->headerValid) + break; + if (i != 0) + return i; + for (i = 1; i < ne; i++) + if ((ev[i] & prot->dataMask) != prot->dataValid) + return -1; + return 0; +} + +static Bool threeComplete (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + return ne == 3; +} + +static Bool fourComplete (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + return ne == 4; +} + +static Bool fiveComplete (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + return ne == 5; +} + +static Bool MouseReasonable (KdPointerInfo *pi, unsigned long flags, int dx, int dy) +{ + Kmouse *km = pi->driverPrivate; + + if (km->stage == MouseWorking) + return TRUE; + if (dx < -50 || dx > 50) + { +#ifdef DEBUG + ErrorF ("Large X %d\n", dx); +#endif + return FALSE; + } + if (dy < -50 || dy > 50) + { +#ifdef DEBUG + ErrorF ("Large Y %d\n", dy); +#endif + return FALSE; + } + return TRUE; +} + +/* + * Standard PS/2 mouse protocol + */ +static Bool ps2Parse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy, dz; + unsigned long flags; + unsigned long flagsrelease = 0; + + flags = KD_MOUSE_DELTA; + if (ev[0] & 4) + flags |= KD_BUTTON_2; + if (ev[0] & 2) + flags |= KD_BUTTON_3; + if (ev[0] & 1) + flags |= KD_BUTTON_1; + + if (ne > 3) + { + dz = (int) (signed char) ev[3]; + if (dz < 0) + { + flags |= KD_BUTTON_4; + flagsrelease = KD_BUTTON_4; + } + else if (dz > 0) + { + flags |= KD_BUTTON_5; + flagsrelease = KD_BUTTON_5; + } + } + + dx = ev[1]; + if (ev[0] & 0x10) + dx -= 256; + dy = ev[2]; + if (ev[0] & 0x20) + dy -= 256; + dy = -dy; + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + { + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + if (flagsrelease) + { + flags &= ~flagsrelease; + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + } + } + return TRUE; +} + +static Bool ps2Init (KdPointerInfo *pi); + +static const KmouseProt ps2Prot = { + "ps/2", + threeComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +static const KmouseProt imps2Prot = { + "imps/2", + fourComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +static const KmouseProt exps2Prot = { + "exps/2", + fourComplete, mouseValid, ps2Parse, ps2Init, + 0x08, 0x08, 0x00, 0x00, + FALSE +}; + +/* + * Once the mouse is known to speak ps/2 protocol, go and find out + * what advanced capabilities it has and turn them on + */ + +/* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */ + +/* aux device commands (sent to KBD_DATA_PORT) */ +#define PSMC_SET_SCALING11 0x00e6 +#define PSMC_SET_SCALING21 0x00e7 +#define PSMC_SET_RESOLUTION 0x00e8 +#define PSMC_SEND_DEV_STATUS 0x00e9 +#define PSMC_SET_STREAM_MODE 0x00ea +#define PSMC_SEND_DEV_DATA 0x00eb +#define PSMC_SET_REMOTE_MODE 0x00f0 +#define PSMC_SEND_DEV_ID 0x00f2 +#define PSMC_SET_SAMPLING_RATE 0x00f3 +#define PSMC_ENABLE_DEV 0x00f4 +#define PSMC_DISABLE_DEV 0x00f5 +#define PSMC_SET_DEFAULTS 0x00f6 +#define PSMC_RESET_DEV 0x00ff + +/* PSMC_SET_RESOLUTION argument */ +#define PSMD_RES_LOW 0 /* typically 25ppi */ +#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */ +#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */ +#define PSMD_RES_HIGH 3 /* typically 200ppi */ +#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH + +/* PSMC_SET_SAMPLING_RATE */ +#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */ + +/* aux device ID */ +#define PSM_MOUSE_ID 0 +#define PSM_BALLPOINT_ID 2 +#define PSM_INTELLI_ID 3 +#define PSM_EXPLORER_ID 4 +#define PSM_4DMOUSE_ID 6 +#define PSM_4DPLUS_ID 8 + +static unsigned char ps2_init[] = { + PSMC_ENABLE_DEV, + 0, +}; + +#define NINIT_PS2 1 + +static unsigned char wheel_3button_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SEND_DEV_ID, + 0, +}; + +#define NINIT_IMPS2 4 + +static unsigned char wheel_5button_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 80, + PSMC_SEND_DEV_ID, + 0 +}; + +#define NINIT_EXPS2 7 + +static unsigned char intelli_init[] = { + PSMC_SET_SAMPLING_RATE, 200, + PSMC_SET_SAMPLING_RATE, 100, + PSMC_SET_SAMPLING_RATE, 80, + 0 +}; + +#define NINIT_INTELLI 3 + +static int +ps2SkipInit (KdPointerInfo *pi, int ninit, Bool ret_next) +{ + Kmouse *km = pi->driverPrivate; + int c = -1; + int skipping; + Bool waiting; + + skipping = 0; + waiting = FALSE; + while (ninit || ret_next) + { + c = MouseReadByte (&km->iob, MOUSE_TIMEOUT); + if (c == -1) + break; + /* look for ACK */ + if (c == 0xfa) + { + ninit--; + if (ret_next) + waiting = TRUE; + } + /* look for packet start -- not the response */ + else if ((c & 0x08) == 0x08) + waiting = FALSE; + else if (waiting) + break; + } + return c; +} + +static Bool +ps2Init (KdPointerInfo *pi) +{ + Kmouse *km = pi->driverPrivate; + int skipping; + Bool waiting; + int id; + unsigned char *init; + int ninit; + + /* Send Intellimouse initialization sequence */ + MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *) intelli_init), 100); + /* + * Send ID command + */ + if (!MouseWriteByte (km->iob.fd, PSMC_SEND_DEV_ID, 100)) + return FALSE; + skipping = 0; + waiting = FALSE; + id = ps2SkipInit (pi, 0, TRUE); + switch (id) { + case 3: + init = wheel_3button_init; + ninit = NINIT_IMPS2; + km->prot = &imps2Prot; + break; + case 4: + init = wheel_5button_init; + ninit = NINIT_EXPS2; + km->prot = &exps2Prot; + break; + default: + init = ps2_init; + ninit = NINIT_PS2; + km->prot = &ps2Prot; + break; + } + if (init) + MouseWriteBytes (km->iob.fd, init, strlen ((char *) init), 100); + /* + * Flush out the available data to eliminate responses to the + * initialization string. Make sure any partial event is + * skipped + */ + (void) ps2SkipInit (pi, ninit, FALSE); + return TRUE; +} + +static Bool busParse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + dx = (signed char) ev[1]; + dy = -(signed char) ev[2]; + if ((ev[0] & 4) == 0) + flags |= KD_BUTTON_1; + if ((ev[0] & 2) == 0) + flags |= KD_BUTTON_2; + if ((ev[0] & 1) == 0) + flags |= KD_BUTTON_3; + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + return TRUE; +} + +static const KmouseProt busProt = { + "bus", + threeComplete, mouseValid, busParse, 0, + 0xf8, 0x00, 0x00, 0x00, + FALSE +}; + +/* + * Standard MS serial protocol, three bytes + */ + +static Bool msParse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (ev[0] & 0x20) + flags |= KD_BUTTON_1; + if (ev[0] & 0x10) + flags |= KD_BUTTON_3; + + dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F)); + dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F)); + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + return TRUE; +} + +static const KmouseProt msProt = { + "ms", + threeComplete, mouseValid, msParse, 0, + 0xc0, 0x40, 0xc0, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS7 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the + * first byte of a synchronized protocol stream and see if it's got + * any bits turned on that can't occur in that fourth byte + */ +static Bool logiComplete (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + + if ((ev[0] & 0x40) == 0x40) + return ne == 3; + if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0) + return ne == 1; + return FALSE; +} + +static int logiValid (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + const KmouseProt *prot = km->prot; + int i; + + for (i = 0; i < ne; i++) + { + if ((ev[i] & 0x40) == 0x40) + break; + if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0) + break; + } + if (i != 0) + return i; + for (i = 1; i < ne; i++) + if ((ev[i] & prot->dataMask) != prot->dataValid) + return -1; + return 0; +} + +static Bool logiParse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (ne == 3) + { + if (ev[0] & 0x20) + flags |= KD_BUTTON_1; + if (ev[0] & 0x10) + flags |= KD_BUTTON_3; + + dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F)); + dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F)); + flags |= km->state & KD_BUTTON_2; + } + else + { + if (ev[0] & 0x20) + flags |= KD_BUTTON_2; + dx = 0; + dy = 0; + flags |= km->state & (KD_BUTTON_1|KD_BUTTON_3); + } + + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + return TRUE; +} + +static const KmouseProt logiProt = { + "logitech", + logiComplete, logiValid, logiParse, 0, + 0xc0, 0x40, 0xc0, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS7 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Mouse systems protocol, 5 bytes + */ +static Bool mscParse (KdPointerInfo *pi, unsigned char *ev, int ne) +{ + Kmouse *km = pi->driverPrivate; + int dx, dy; + unsigned long flags; + + flags = KD_MOUSE_DELTA; + + if (!(ev[0] & 0x4)) + flags |= KD_BUTTON_1; + if (!(ev[0] & 0x2)) + flags |= KD_BUTTON_2; + if (!(ev[0] & 0x1)) + flags |= KD_BUTTON_3; + dx = (signed char)(ev[1]) + (signed char)(ev[3]); + dy = - ((signed char)(ev[2]) + (signed char)(ev[4])); + + if (!MouseReasonable (pi, flags, dx, dy)) + return FALSE; + if (km->stage == MouseWorking) + KdEnqueuePointerEvent (pi, flags, dx, dy, 0); + return TRUE; +} + +static const KmouseProt mscProt = { + "msc", + fiveComplete, mouseValid, mscParse, 0, + 0xf8, 0x80, 0x00, 0x00, + TRUE, + IGNPAR, + 0, + 0, + CS8 | CSTOPB | CREAD | CLOCAL, + B1200, +}; + +/* + * Use logitech before ms -- they're the same except that + * logitech sometimes has a fourth byte + */ +static const KmouseProt *kmouseProts[] = { + &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, &mscProt, +}; + +#define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0])) + +static void +MouseInitProtocol (Kmouse *km) +{ + int ret; + struct termios t; + + if (km->prot->tty) + { + ret = tcgetattr (km->iob.fd, &t); + + if (ret >= 0) + { + t.c_iflag = km->prot->c_iflag; + t.c_oflag = km->prot->c_oflag; + t.c_lflag = km->prot->c_lflag; + t.c_cflag = km->prot->c_cflag; + cfsetispeed (&t, km->prot->speed); + cfsetospeed (&t, km->prot->speed); + ret = tcsetattr (km->iob.fd, TCSANOW, &t); + } + } + km->stage = MouseBroken; + km->valid = 0; + km->tested = 0; + km->invalid = 0; + km->state = km->prot->state; +} + +static void +MouseFirstProtocol (Kmouse *km, char *prot) +{ + if (prot) + { + for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++) + if (!strcmp (prot, kmouseProts[km->i_prot]->name)) + break; + if (km->i_prot == NUM_PROT) + { + int i; + ErrorF ("Unknown mouse protocol \"%s\". Pick one of:", prot); + for (i = 0; i < NUM_PROT; i++) + ErrorF (" %s", kmouseProts[i]->name); + ErrorF ("\n"); + } + else + { + km->prot = kmouseProts[km->i_prot]; + if (km->tty && !km->prot->tty) + ErrorF ("Mouse device is serial port, protocol %s is not serial protocol\n", + prot); + else if (!km->tty && km->prot->tty) + ErrorF ("Mouse device is not serial port, protocol %s is serial protocol\n", + prot); + } + } + if (!km->prot) + { + for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; km->i_prot++) + ; + km->prot = kmouseProts[km->i_prot]; + } + MouseInitProtocol (km); +} + +static void +MouseNextProtocol (Kmouse *km) +{ + do + { + if (!km->prot) + km->i_prot = 0; + else + if (++km->i_prot == NUM_PROT) km->i_prot = 0; + km->prot = kmouseProts[km->i_prot]; + } while (km->prot->tty != km->tty); + MouseInitProtocol (km); + ErrorF ("Switching to mouse protocol \"%s\"\n", km->prot->name); +} + +static void +MouseRead (int mousePort, void *closure) +{ + KdPointerInfo *pi = closure; + Kmouse *km = pi->driverPrivate; + unsigned char event[MAX_MOUSE]; + int ne; + int c; + int i; + int timeout; + + timeout = 0; + ne = 0; + for(;;) + { + c = MouseReadByte (&km->iob, timeout); + if (c == -1) + { + if (ne) + { + km->invalid += ne + km->tested; + km->valid = 0; + km->tested = 0; + km->stage = MouseBroken; + } + break; + } + event[ne++] = c; + i = (*km->prot->Valid) (pi, event, ne); + if (i != 0) + { +#ifdef DEBUG + ErrorF ("Mouse protocol %s broken %d of %d bytes bad\n", + km->prot->name, i > 0 ? i : ne, ne); +#endif + if (i > 0 && i < ne) + { + ne -= i; + memmove (event, event + i, ne); + } + else + { + i = ne; + ne = 0; + } + km->invalid += i + km->tested; + km->valid = 0; + km->tested = 0; + if (km->stage == MouseWorking) + km->i_prot--; + km->stage = MouseBroken; + if (km->invalid > MAX_SKIP) + { + MouseNextProtocol (km); + ne = 0; + } + timeout = 0; + } + else + { + if ((*km->prot->Complete) (pi, event, ne)) + { + if ((*km->prot->Parse) (pi, event, ne)) + { + switch (km->stage) + { + case MouseBroken: +#ifdef DEBUG + ErrorF ("Mouse protocol %s seems OK\n", + km->prot->name); +#endif + /* do not zero invalid to accumulate invalid bytes */ + km->valid = 0; + km->tested = 0; + km->stage = MouseTesting; + /* fall through ... */ + case MouseTesting: + km->valid++; + km->tested += ne; + if (km->valid > MAX_VALID) + { +#ifdef DEBUG + ErrorF ("Mouse protocol %s working\n", + km->prot->name); +#endif + km->stage = MouseWorking; + km->invalid = 0; + km->tested = 0; + km->valid = 0; + if (km->prot->Init && !(*km->prot->Init) (pi)) + km->stage = MouseBroken; + } + break; + case MouseWorking: + break; + } + } + else + { + km->invalid += ne + km->tested; + km->valid = 0; + km->tested = 0; + km->stage = MouseBroken; + } + ne = 0; + timeout = 0; + } + else + timeout = MOUSE_TIMEOUT; + } + } +} + +int MouseInputType; + +char *kdefaultMouse[] = { + "/dev/input/mice", + "/dev/mouse", + "/dev/psaux", + "/dev/adbmouse", + "/dev/ttyS0", + "/dev/ttyS1", +}; + +#define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0])) + +static Status +MouseInit (KdPointerInfo *pi) +{ + int i; + int fd; + Kmouse *km; + + if (!pi) + return BadImplementation; + + if (!pi->path || strcmp(pi->path, "auto") == 0) { + for (i = 0; i < NUM_DEFAULT_MOUSE; i++) { + fd = open (kdefaultMouse[i], 2); + if (fd >= 0) { + pi->path = strdup (kdefaultMouse[i]); + break; + } + } + } + else { + fd = open (pi->path, 2); + } + + if (fd < 0) + return BadMatch; + + close(fd); + + km = (Kmouse *) malloc(sizeof (Kmouse)); + if (km) { + km->iob.avail = km->iob.used = 0; + MouseFirstProtocol(km, pi->protocol ? pi->protocol : "exps/2"); + /* MouseFirstProtocol sets state to MouseBroken for later protocol + * checks. Skip these checks if a protocol was supplied */ + if (pi->protocol) + km->state = MouseWorking; + km->i_prot = 0; + km->tty = isatty (fd); + km->iob.fd = -1; + pi->driverPrivate = km; + } + else { + close (fd); + return BadAlloc; + } + + return Success; +} + +static Status +MouseEnable (KdPointerInfo *pi) +{ + Kmouse *km; + + if (!pi || !pi->driverPrivate || !pi->path) + return BadImplementation; + + km = pi->driverPrivate; + + km->iob.fd = open(pi->path, 2); + if (km->iob.fd < 0) + return BadMatch; + + if (!KdRegisterFd (km->iob.fd, MouseRead, pi)) + { + close(km->iob.fd); + return BadAlloc; + } + + return Success; +} + +static void +MouseDisable (KdPointerInfo *pi) +{ + Kmouse *km; + if (!pi || !pi->driverPrivate) + return; + + km = pi->driverPrivate; + KdUnregisterFd (pi, km->iob.fd, TRUE); +} + +static void +MouseFini (KdPointerInfo *pi) +{ + free(pi->driverPrivate); + pi->driverPrivate = NULL; +} + +KdPointerDriver LinuxMouseDriver = { + "mouse", + MouseInit, + MouseEnable, + MouseDisable, + MouseFini, + NULL, +}; diff --git a/xorg-server/hw/kdrive/linux/tslib.c b/xorg-server/hw/kdrive/linux/tslib.c index 322ccc7d5..ee0f779f3 100644 --- a/xorg-server/hw/kdrive/linux/tslib.c +++ b/xorg-server/hw/kdrive/linux/tslib.c @@ -1,190 +1,190 @@ -/* - * TSLIB based touchscreen driver for KDrive - * Porting to new input API and event queueing by Daniel Stone. - * Derived from ts.c by Keith Packard - * Derived from ps2.c by Jim Gettys - * - * Copyright © 1999 Keith Packard - * Copyright © 2000 Compaq Computer Corporation - * Copyright © 2002 MontaVista Software Inc. - * Copyright © 2005 OpenedHand Ltd. - * Copyright © 2006 Nokia Corporation - * - * 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 authors and/or copyright holders - * not be used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. The authors and/or - * 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 AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD - * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR 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_KDRIVE_CONFIG_H -#include <kdrive-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/Xpoll.h> -#include "inputstr.h" -#include "scrnintstr.h" -#include "kdrive.h" -#include <sys/ioctl.h> -#include <tslib.h> -#include <dirent.h> -#include <linux/input.h> - -struct TslibPrivate { - int fd; - int lastx, lasty; - struct tsdev *tsDev; - void (*raw_event_hook)(int x, int y, int pressure, void *closure); - void *raw_event_closure; - int phys_screen; -}; - - -static void -TsRead (int fd, void *closure) -{ - KdPointerInfo *pi = closure; - struct TslibPrivate *private = pi->driverPrivate; - struct ts_sample event; - long x = 0, y = 0; - unsigned long flags; - - if (private->raw_event_hook) { - while (ts_read_raw(private->tsDev, &event, 1) == 1) - private->raw_event_hook (event.x, event.y, event.pressure, - private->raw_event_closure); - return; - } - - while (ts_read(private->tsDev, &event, 1) == 1) { - if (event.pressure) { - flags = KD_BUTTON_1; - - /* - * Here we test for the touch screen driver actually being on the - * touch screen, if it is we send absolute coordinates. If not, - * then we send delta's so that we can track the entire vga screen. - */ - if (KdCurScreen == private->phys_screen) { - x = event.x; - y = event.y; - } else { - flags |= KD_MOUSE_DELTA; - if ((private->lastx == 0) || (private->lasty == 0)) { - x = event.x; - y = event.y; - } else { - x = event.x - private->lastx; - y = event.y - private->lasty; - } - } - private->lastx = event.x; - private->lasty = event.y; - } else { - flags = 0; - x = private->lastx; - y = private->lasty; - } - - KdEnqueuePointerEvent (pi, flags, x, y, event.pressure); - } -} - -static Status -TslibEnable (KdPointerInfo *pi) -{ - struct TslibPrivate *private = pi->driverPrivate; - - private->raw_event_hook = NULL; - private->raw_event_closure = NULL; - if (!pi->path) { - pi->path = strdup("/dev/input/touchscreen0"); - ErrorF("[tslib/TslibEnable] no device path given, trying %s\n", pi->path); - } - private->tsDev = ts_open(pi->path, 0); - private->fd = ts_fd(private->tsDev); - if (!private->tsDev || ts_config(private->tsDev) || private->fd < 0) { - ErrorF("[tslib/TslibEnable] failed to open %s\n", pi->path); - if (private->fd >= 0) - close(private->fd); - return BadAlloc; - } - - KdRegisterFd(private->fd, TsRead, pi); - - return Success; -} - - -static void -TslibDisable (KdPointerInfo *pi) -{ - struct TslibPrivate *private = pi->driverPrivate; - - if (private->fd) - KdUnregisterFd(pi, private->fd, TRUE); - - if (private->tsDev) - ts_close(private->tsDev); - - private->fd = 0; - private->tsDev = NULL; -} - - -static Status -TslibInit (KdPointerInfo *pi) -{ - struct TslibPrivate *private = NULL; - - if (!pi || !pi->dixdev) - return !Success; - - pi->driverPrivate = (struct TslibPrivate *) - xcalloc(sizeof(struct TslibPrivate), 1); - if (!pi->driverPrivate) - return !Success; - - private = pi->driverPrivate; - /* hacktastic */ - private->phys_screen = 0; - pi->nAxes = 3; - pi->name = strdup("Touchscreen"); - pi->inputClass = KD_TOUCHSCREEN; - - return Success; -} - - -static void -TslibFini (KdPointerInfo *pi) -{ - xfree(pi->driverPrivate); - pi->driverPrivate = NULL; -} - - -KdPointerDriver TsDriver = { - "tslib", - TslibInit, - TslibEnable, - TslibDisable, - TslibFini, - NULL, -}; +/* + * TSLIB based touchscreen driver for KDrive + * Porting to new input API and event queueing by Daniel Stone. + * Derived from ts.c by Keith Packard + * Derived from ps2.c by Jim Gettys + * + * Copyright © 1999 Keith Packard + * Copyright © 2000 Compaq Computer Corporation + * Copyright © 2002 MontaVista Software Inc. + * Copyright © 2005 OpenedHand Ltd. + * Copyright © 2006 Nokia Corporation + * + * 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 authors and/or copyright holders + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. The authors and/or + * 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 AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR 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_KDRIVE_CONFIG_H +#include <kdrive-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xpoll.h> +#include "inputstr.h" +#include "scrnintstr.h" +#include "kdrive.h" +#include <sys/ioctl.h> +#include <tslib.h> +#include <dirent.h> +#include <linux/input.h> + +struct TslibPrivate { + int fd; + int lastx, lasty; + struct tsdev *tsDev; + void (*raw_event_hook)(int x, int y, int pressure, void *closure); + void *raw_event_closure; + int phys_screen; +}; + + +static void +TsRead (int fd, void *closure) +{ + KdPointerInfo *pi = closure; + struct TslibPrivate *private = pi->driverPrivate; + struct ts_sample event; + long x = 0, y = 0; + unsigned long flags; + + if (private->raw_event_hook) { + while (ts_read_raw(private->tsDev, &event, 1) == 1) + private->raw_event_hook (event.x, event.y, event.pressure, + private->raw_event_closure); + return; + } + + while (ts_read(private->tsDev, &event, 1) == 1) { + if (event.pressure) { + flags = KD_BUTTON_1; + + /* + * Here we test for the touch screen driver actually being on the + * touch screen, if it is we send absolute coordinates. If not, + * then we send delta's so that we can track the entire vga screen. + */ + if (KdCurScreen == private->phys_screen) { + x = event.x; + y = event.y; + } else { + flags |= KD_MOUSE_DELTA; + if ((private->lastx == 0) || (private->lasty == 0)) { + x = event.x; + y = event.y; + } else { + x = event.x - private->lastx; + y = event.y - private->lasty; + } + } + private->lastx = event.x; + private->lasty = event.y; + } else { + flags = 0; + x = private->lastx; + y = private->lasty; + } + + KdEnqueuePointerEvent (pi, flags, x, y, event.pressure); + } +} + +static Status +TslibEnable (KdPointerInfo *pi) +{ + struct TslibPrivate *private = pi->driverPrivate; + + private->raw_event_hook = NULL; + private->raw_event_closure = NULL; + if (!pi->path) { + pi->path = strdup("/dev/input/touchscreen0"); + ErrorF("[tslib/TslibEnable] no device path given, trying %s\n", pi->path); + } + private->tsDev = ts_open(pi->path, 0); + private->fd = ts_fd(private->tsDev); + if (!private->tsDev || ts_config(private->tsDev) || private->fd < 0) { + ErrorF("[tslib/TslibEnable] failed to open %s\n", pi->path); + if (private->fd >= 0) + close(private->fd); + return BadAlloc; + } + + KdRegisterFd(private->fd, TsRead, pi); + + return Success; +} + + +static void +TslibDisable (KdPointerInfo *pi) +{ + struct TslibPrivate *private = pi->driverPrivate; + + if (private->fd) + KdUnregisterFd(pi, private->fd, TRUE); + + if (private->tsDev) + ts_close(private->tsDev); + + private->fd = 0; + private->tsDev = NULL; +} + + +static Status +TslibInit (KdPointerInfo *pi) +{ + struct TslibPrivate *private = NULL; + + if (!pi || !pi->dixdev) + return !Success; + + pi->driverPrivate = (struct TslibPrivate *) + calloc(sizeof(struct TslibPrivate), 1); + if (!pi->driverPrivate) + return !Success; + + private = pi->driverPrivate; + /* hacktastic */ + private->phys_screen = 0; + pi->nAxes = 3; + pi->name = strdup("Touchscreen"); + pi->inputClass = KD_TOUCHSCREEN; + + return Success; +} + + +static void +TslibFini (KdPointerInfo *pi) +{ + free(pi->driverPrivate); + pi->driverPrivate = NULL; +} + + +KdPointerDriver TsDriver = { + "tslib", + TslibInit, + TslibEnable, + TslibDisable, + TslibFini, + NULL, +}; diff --git a/xorg-server/hw/kdrive/src/kcmap.c b/xorg-server/hw/kdrive/src/kcmap.c index 40697e091..127c7a078 100644 --- a/xorg-server/hw/kdrive/src/kcmap.c +++ b/xorg-server/hw/kdrive/src/kcmap.c @@ -1,246 +1,246 @@ -/* - * Copyright © 1999 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include "kdrive.h" - -/* - * Put the entire colormap into the DAC - */ - -void -KdSetColormap (ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - ColormapPtr pCmap = pScreenPriv->pInstalledmap; - Pixel pixels[KD_MAX_PSEUDO_SIZE]; - xrgb colors[KD_MAX_PSEUDO_SIZE]; - xColorItem defs[KD_MAX_PSEUDO_SIZE]; - int i; - - if (!pScreenPriv->card->cfuncs->putColors) - return; - if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH) - return; - - if (!pScreenPriv->enabled) - return; - - if (!pCmap) - return; - - /* - * Make DIX convert pixels into RGB values -- this handles - * true/direct as well as pseudo/static visuals - */ - - for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) - pixels[i] = i; - - QueryColors (pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, colors); - - for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) - { - defs[i].pixel = i; - defs[i].red = colors[i].red; - defs[i].green = colors[i].green; - defs[i].blue = colors[i].blue; - defs[i].flags = DoRed|DoGreen|DoBlue; - } - - (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, - (1 << pScreenPriv->screen->fb.depth), - defs); - - /* recolor hardware cursor */ - if (pScreenPriv->card->cfuncs->recolorCursor) - (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, 0); -} - -/* - * When the hardware is enabled, save the hardware colors and store - * the current colormap - */ -void -KdEnableColormap (ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - int i; - - if (!pScreenPriv->card->cfuncs->putColors) - return; - - if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) - { - for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) - pScreenPriv->systemPalette[i].pixel = i; - (*pScreenPriv->card->cfuncs->getColors) (pScreen, - (1 << pScreenPriv->screen->fb.depth), - pScreenPriv->systemPalette); - } - KdSetColormap (pScreen); -} - -void -KdDisableColormap (ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - - if (!pScreenPriv->card->cfuncs->putColors) - return; - - if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) - { - (*pScreenPriv->card->cfuncs->putColors) (pScreen, - (1 << pScreenPriv->screen->fb.depth), - pScreenPriv->systemPalette); - } -} - -/* - * KdInstallColormap - * - * This function is called when the server receives a request to install a - * colormap or when the server needs to install one on its own, like when - * there's no window manager running and the user has moved the pointer over - * an X client window. It needs to build an identity Windows palette for the - * colormap and realize it into the Windows system palette. - */ -void -KdInstallColormap (ColormapPtr pCmap) -{ - KdScreenPriv(pCmap->pScreen); - - if (pCmap == pScreenPriv->pInstalledmap) - return; - - /* Tell X clients that the installed colormap is going away. */ - if (pScreenPriv->pInstalledmap) - WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap, - (pointer) &(pScreenPriv->pInstalledmap->mid)); - - /* Take note of the new installed colorscreen-> */ - pScreenPriv->pInstalledmap = pCmap; - - KdSetColormap (pCmap->pScreen); - - /* Tell X clients of the new colormap */ - WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &(pCmap->mid)); -} - -/* - * KdUninstallColormap - * - * This function uninstalls a colormap by either installing - * the default X colormap or erasing the installed colormap pointer. - * The default X colormap itself cannot be uninstalled. - */ -void -KdUninstallColormap (ColormapPtr pCmap) -{ - KdScreenPriv(pCmap->pScreen); - Colormap defMapID; - ColormapPtr defMap; - - /* ignore if not installed */ - if (pCmap != pScreenPriv->pInstalledmap) - return; - - /* ignore attempts to uninstall default colormap */ - defMapID = pCmap->pScreen->defColormap; - if ((Colormap) pCmap->mid == defMapID) - return; - - /* install default */ - dixLookupResourceByType((pointer *)&defMap, defMapID, RT_COLORMAP, - serverClient, DixInstallAccess); - if (defMap) - (*pCmap->pScreen->InstallColormap)(defMap); - else - { - /* uninstall and clear colormap pointer */ - WalkTree(pCmap->pScreen, TellLostMap, - (pointer) &(pCmap->mid)); - pScreenPriv->pInstalledmap = 0; - } -} - -int -KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps) -{ - KdScreenPriv(pScreen); - int n = 0; - - if (pScreenPriv->pInstalledmap) - { - *pCmaps++ = pScreenPriv->pInstalledmap->mid; - n++; - } - return n; -} - -/* - * KdStoreColors - * - * This function is called whenever the server receives a request to store - * color values into one or more entries in the currently installed X - * colormap; it can be either the default colormap or a private colorscreen-> - */ -void -KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs) -{ - KdScreenPriv(pCmap->pScreen); - VisualPtr pVisual; - xColorItem expanddefs[KD_MAX_PSEUDO_SIZE]; - - if (pCmap != pScreenPriv->pInstalledmap) - return; - - if (!pScreenPriv->card->cfuncs->putColors) - return; - - if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH) - return; - - if (!pScreenPriv->enabled) - return; - - /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */ - pVisual = pCmap->pVisual; - if ((pVisual->class | DynamicClass) == DirectColor) - { - /* - * Expand DirectColor or TrueColor color values into a PseudoColor - * format. Defer to the Color Framebuffer (CFB) code to do that. - */ - ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs); - pdefs = expanddefs; - } - - (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs); - - /* recolor hardware cursor */ - if (pScreenPriv->card->cfuncs->recolorCursor) - (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, ndef, pdefs); -} +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" + +/* + * Put the entire colormap into the DAC + */ + +void +KdSetColormap (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + ColormapPtr pCmap = pScreenPriv->pInstalledmap; + Pixel pixels[KD_MAX_PSEUDO_SIZE]; + xrgb colors[KD_MAX_PSEUDO_SIZE]; + xColorItem defs[KD_MAX_PSEUDO_SIZE]; + int i; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH) + return; + + if (!pScreenPriv->enabled) + return; + + if (!pCmap) + return; + + /* + * Make DIX convert pixels into RGB values -- this handles + * true/direct as well as pseudo/static visuals + */ + + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) + pixels[i] = i; + + QueryColors (pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, colors, serverClient); + + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) + { + defs[i].pixel = i; + defs[i].red = colors[i].red; + defs[i].green = colors[i].green; + defs[i].blue = colors[i].blue; + defs[i].flags = DoRed|DoGreen|DoBlue; + } + + (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, + (1 << pScreenPriv->screen->fb.depth), + defs); + + /* recolor hardware cursor */ + if (pScreenPriv->card->cfuncs->recolorCursor) + (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, 0); +} + +/* + * When the hardware is enabled, save the hardware colors and store + * the current colormap + */ +void +KdEnableColormap (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + int i; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + + if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) + { + for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) + pScreenPriv->systemPalette[i].pixel = i; + (*pScreenPriv->card->cfuncs->getColors) (pScreen, + (1 << pScreenPriv->screen->fb.depth), + pScreenPriv->systemPalette); + } + KdSetColormap (pScreen); +} + +void +KdDisableColormap (ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + + if (!pScreenPriv->card->cfuncs->putColors) + return; + + if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) + { + (*pScreenPriv->card->cfuncs->putColors) (pScreen, + (1 << pScreenPriv->screen->fb.depth), + pScreenPriv->systemPalette); + } +} + +/* + * KdInstallColormap + * + * This function is called when the server receives a request to install a + * colormap or when the server needs to install one on its own, like when + * there's no window manager running and the user has moved the pointer over + * an X client window. It needs to build an identity Windows palette for the + * colormap and realize it into the Windows system palette. + */ +void +KdInstallColormap (ColormapPtr pCmap) +{ + KdScreenPriv(pCmap->pScreen); + + if (pCmap == pScreenPriv->pInstalledmap) + return; + + /* Tell X clients that the installed colormap is going away. */ + if (pScreenPriv->pInstalledmap) + WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap, + (pointer) &(pScreenPriv->pInstalledmap->mid)); + + /* Take note of the new installed colorscreen-> */ + pScreenPriv->pInstalledmap = pCmap; + + KdSetColormap (pCmap->pScreen); + + /* Tell X clients of the new colormap */ + WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &(pCmap->mid)); +} + +/* + * KdUninstallColormap + * + * This function uninstalls a colormap by either installing + * the default X colormap or erasing the installed colormap pointer. + * The default X colormap itself cannot be uninstalled. + */ +void +KdUninstallColormap (ColormapPtr pCmap) +{ + KdScreenPriv(pCmap->pScreen); + Colormap defMapID; + ColormapPtr defMap; + + /* ignore if not installed */ + if (pCmap != pScreenPriv->pInstalledmap) + return; + + /* ignore attempts to uninstall default colormap */ + defMapID = pCmap->pScreen->defColormap; + if ((Colormap) pCmap->mid == defMapID) + return; + + /* install default */ + dixLookupResourceByType((pointer *)&defMap, defMapID, RT_COLORMAP, + serverClient, DixInstallAccess); + if (defMap) + (*pCmap->pScreen->InstallColormap)(defMap); + else + { + /* uninstall and clear colormap pointer */ + WalkTree(pCmap->pScreen, TellLostMap, + (pointer) &(pCmap->mid)); + pScreenPriv->pInstalledmap = 0; + } +} + +int +KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps) +{ + KdScreenPriv(pScreen); + int n = 0; + + if (pScreenPriv->pInstalledmap) + { + *pCmaps++ = pScreenPriv->pInstalledmap->mid; + n++; + } + return n; +} + +/* + * KdStoreColors + * + * This function is called whenever the server receives a request to store + * color values into one or more entries in the currently installed X + * colormap; it can be either the default colormap or a private colorscreen-> + */ +void +KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs) +{ + KdScreenPriv(pCmap->pScreen); + VisualPtr pVisual; + xColorItem expanddefs[KD_MAX_PSEUDO_SIZE]; + + if (pCmap != pScreenPriv->pInstalledmap) + return; + + if (!pScreenPriv->card->cfuncs->putColors) + return; + + if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH) + return; + + if (!pScreenPriv->enabled) + return; + + /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */ + pVisual = pCmap->pVisual; + if ((pVisual->class | DynamicClass) == DirectColor) + { + /* + * Expand DirectColor or TrueColor color values into a PseudoColor + * format. Defer to the Color Framebuffer (CFB) code to do that. + */ + ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs); + pdefs = expanddefs; + } + + (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs); + + /* recolor hardware cursor */ + if (pScreenPriv->card->cfuncs->recolorCursor) + (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, ndef, pdefs); +} diff --git a/xorg-server/hw/kdrive/src/kdrive.c b/xorg-server/hw/kdrive/src/kdrive.c index a8eb3996b..a7db41379 100644 --- a/xorg-server/hw/kdrive/src/kdrive.c +++ b/xorg-server/hw/kdrive/src/kdrive.c @@ -207,7 +207,7 @@ KdDoSwitchCmd (char *reason) { if (kdSwitchCmd) { - char *command = xalloc (strlen (kdSwitchCmd) + + char *command = malloc(strlen (kdSwitchCmd) + 1 + strlen (reason) + 1); @@ -217,7 +217,7 @@ KdDoSwitchCmd (char *reason) strcat (command, " "); strcat (command, reason); system (command); - xfree (command); + free(command); } } @@ -701,7 +701,7 @@ KdAllocatePrivates (ScreenPtr pScreen) if (kdGeneration != serverGeneration) kdGeneration = serverGeneration; - pScreenPriv = xcalloc(1, sizeof (*pScreenPriv)); + pScreenPriv = calloc(1, sizeof (*pScreenPriv)); if (!pScreenPriv) return FALSE; KdSetScreenPriv (pScreen, pScreenPriv); @@ -790,7 +790,7 @@ KdCloseScreen (int index, ScreenPtr pScreen) pScreenPriv->screen->pScreen = 0; - xfree ((pointer) pScreenPriv); + free((pointer) pScreenPriv); return ret; } diff --git a/xorg-server/hw/kdrive/src/kinfo.c b/xorg-server/hw/kdrive/src/kinfo.c index 0825ee24f..90fe37ae9 100644 --- a/xorg-server/hw/kdrive/src/kinfo.c +++ b/xorg-server/hw/kdrive/src/kinfo.c @@ -1,163 +1,163 @@ -/* - * Copyright © 1999 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include "kdrive.h" - -KdCardInfo *kdCardInfo; - -KdCardInfo * -KdCardInfoAdd (KdCardFuncs *funcs, - void *closure) -{ - KdCardInfo *ci, **prev; - - ci = xcalloc (1, sizeof (KdCardInfo)); - if (!ci) - return 0; - for (prev = &kdCardInfo; *prev; prev = &(*prev)->next); - *prev = ci; - ci->cfuncs = funcs; - ci->closure = closure; - ci->screenList = 0; - ci->selected = 0; - ci->next = 0; - return ci; -} - -KdCardInfo * -KdCardInfoLast (void) -{ - KdCardInfo *ci; - - if (!kdCardInfo) - return 0; - for (ci = kdCardInfo; ci->next; ci = ci->next); - return ci; -} - -void -KdCardInfoDispose (KdCardInfo *ci) -{ - KdCardInfo **prev; - - for (prev = &kdCardInfo; *prev; prev = &(*prev)->next) - if (*prev == ci) - { - *prev = ci->next; - xfree (ci); - break; - } -} - -KdScreenInfo * -KdScreenInfoAdd (KdCardInfo *ci) -{ - KdScreenInfo *si, **prev; - int n; - - si = xcalloc (1, sizeof (KdScreenInfo)); - if (!si) - return 0; - for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++); - *prev = si; - si->next = 0; - si->card = ci; - si->mynum = n; - return si; -} - -void -KdScreenInfoDispose (KdScreenInfo *si) -{ - KdCardInfo *ci = si->card; - KdScreenInfo **prev; - - for (prev = &ci->screenList; *prev; prev = &(*prev)->next) { - if (*prev == si) - { - *prev = si->next; - xfree (si); - if (!ci->screenList) - KdCardInfoDispose (ci); - break; - } - } -} - -KdPointerInfo * -KdNewPointer (void) -{ - KdPointerInfo *pi; - int i; - - pi = (KdPointerInfo *)xcalloc(1, sizeof(KdPointerInfo)); - if (!pi) - return NULL; - - pi->name = strdup("Generic Pointer"); - pi->path = NULL; - pi->inputClass = KD_MOUSE; - pi->driver = NULL; - pi->driverPrivate = NULL; - pi->next = NULL; - pi->options = NULL; - pi->nAxes = 3; - pi->nButtons = KD_MAX_BUTTON; - for (i = 1; i < KD_MAX_BUTTON; i++) - pi->map[i] = i; - - return pi; -} - -void -KdFreePointer(KdPointerInfo *pi) -{ - InputOption *option, *prev = NULL; - - xfree(pi->name); - xfree(pi->path); - - for (option = pi->options; option; option = option->next) { - xfree(prev); - xfree(option->key); - xfree(option->value); - prev = option; - } - - xfree(prev); - xfree(pi); -} - -void -KdFreeKeyboard(KdKeyboardInfo *ki) -{ - xfree(ki->name); - xfree(ki->path); - xfree(ki->xkbRules); - xfree(ki->xkbModel); - xfree(ki->xkbLayout); - ki->next = NULL; - xfree(ki); -} +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" + +KdCardInfo *kdCardInfo; + +KdCardInfo * +KdCardInfoAdd (KdCardFuncs *funcs, + void *closure) +{ + KdCardInfo *ci, **prev; + + ci = calloc(1, sizeof (KdCardInfo)); + if (!ci) + return 0; + for (prev = &kdCardInfo; *prev; prev = &(*prev)->next); + *prev = ci; + ci->cfuncs = funcs; + ci->closure = closure; + ci->screenList = 0; + ci->selected = 0; + ci->next = 0; + return ci; +} + +KdCardInfo * +KdCardInfoLast (void) +{ + KdCardInfo *ci; + + if (!kdCardInfo) + return 0; + for (ci = kdCardInfo; ci->next; ci = ci->next); + return ci; +} + +void +KdCardInfoDispose (KdCardInfo *ci) +{ + KdCardInfo **prev; + + for (prev = &kdCardInfo; *prev; prev = &(*prev)->next) + if (*prev == ci) + { + *prev = ci->next; + free(ci); + break; + } +} + +KdScreenInfo * +KdScreenInfoAdd (KdCardInfo *ci) +{ + KdScreenInfo *si, **prev; + int n; + + si = calloc(1, sizeof (KdScreenInfo)); + if (!si) + return 0; + for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++); + *prev = si; + si->next = 0; + si->card = ci; + si->mynum = n; + return si; +} + +void +KdScreenInfoDispose (KdScreenInfo *si) +{ + KdCardInfo *ci = si->card; + KdScreenInfo **prev; + + for (prev = &ci->screenList; *prev; prev = &(*prev)->next) { + if (*prev == si) + { + *prev = si->next; + free(si); + if (!ci->screenList) + KdCardInfoDispose (ci); + break; + } + } +} + +KdPointerInfo * +KdNewPointer (void) +{ + KdPointerInfo *pi; + int i; + + pi = (KdPointerInfo *)calloc(1, sizeof(KdPointerInfo)); + if (!pi) + return NULL; + + pi->name = strdup("Generic Pointer"); + pi->path = NULL; + pi->inputClass = KD_MOUSE; + pi->driver = NULL; + pi->driverPrivate = NULL; + pi->next = NULL; + pi->options = NULL; + pi->nAxes = 3; + pi->nButtons = KD_MAX_BUTTON; + for (i = 1; i < KD_MAX_BUTTON; i++) + pi->map[i] = i; + + return pi; +} + +void +KdFreePointer(KdPointerInfo *pi) +{ + InputOption *option, *prev = NULL; + + free(pi->name); + free(pi->path); + + for (option = pi->options; option; option = option->next) { + free(prev); + free(option->key); + free(option->value); + prev = option; + } + + free(prev); + free(pi); +} + +void +KdFreeKeyboard(KdKeyboardInfo *ki) +{ + free(ki->name); + free(ki->path); + free(ki->xkbRules); + free(ki->xkbModel); + free(ki->xkbLayout); + ki->next = NULL; + free(ki); +} diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c index 9ba90e63f..d1b12b890 100644 --- a/xorg-server/hw/kdrive/src/kinput.c +++ b/xorg-server/hw/kdrive/src/kinput.c @@ -440,7 +440,7 @@ KdPointerProc(DeviceIntPtr pDevice, int onoff) "(unnamed)"); return !Success; } - xfree(pi->driverPrivate); + free(pi->driverPrivate); pi->driverPrivate = NULL; } @@ -453,12 +453,12 @@ KdPointerProc(DeviceIntPtr pDevice, int onoff) return !Success; } - btn_labels = xcalloc(pi->nButtons, sizeof(Atom)); + btn_labels = calloc(pi->nButtons, sizeof(Atom)); if (!btn_labels) return BadAlloc; - axes_labels = xcalloc(pi->nAxes, sizeof(Atom)); + axes_labels = calloc(pi->nAxes, sizeof(Atom)); if (!axes_labels) { - xfree(btn_labels); + free(btn_labels); return BadAlloc; } @@ -492,8 +492,8 @@ KdPointerProc(DeviceIntPtr pDevice, int onoff) (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), pi->nAxes, axes_labels); - xfree(btn_labels); - xfree(axes_labels); + free(btn_labels); + free(axes_labels); if (pi->inputClass == KD_TOUCHSCREEN) { InitAbsoluteClassDeviceStruct(pDevice); @@ -759,7 +759,7 @@ KdKeyboardProc(DeviceIntPtr pDevice, int onoff) "(unnamed)"); return !Success; } - xfree(ki->driverPrivate); + free(ki->driverPrivate); ki->driverPrivate = NULL; } @@ -910,7 +910,7 @@ KdRemoveKeyboardDriver (KdKeyboardDriver *driver) KdKeyboardInfo * KdNewKeyboard (void) { - KdKeyboardInfo *ki = xcalloc(sizeof(KdKeyboardInfo), 1); + KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1); if (!ki) return NULL; @@ -938,7 +938,7 @@ KdAddConfigKeyboard (char *keyboard) if (!keyboard) return Success; - new = (struct KdConfigDevice *) xcalloc(sizeof(struct KdConfigDevice), 1); + new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); if (!new) return BadAlloc; @@ -1006,7 +1006,7 @@ KdAddConfigPointer (char *pointer) if (!pointer) return Success; - new = (struct KdConfigDevice *) xcalloc(sizeof(struct KdConfigDevice), 1); + new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); if (!new) return BadAlloc; @@ -1076,7 +1076,7 @@ KdGetOptions (InputOption **options, char *string) InputOption *newopt = NULL, **tmpo = NULL; int tam_key = 0; - newopt = xcalloc(1, sizeof (InputOption)); + newopt = calloc(1, sizeof (InputOption)); if (!newopt) return FALSE; @@ -1087,7 +1087,7 @@ KdGetOptions (InputOption **options, char *string) if (strchr(string, '=')) { tam_key = (strchr(string, '=') - string); - newopt->key = (char *)xalloc(tam_key); + newopt->key = (char *)malloc(tam_key); strncpy(newopt->key, string, tam_key); newopt->key[tam_key] = '\0'; newopt->value = xstrdup(strchr(string, '=') + 1); diff --git a/xorg-server/hw/kdrive/src/kshadow.c b/xorg-server/hw/kdrive/src/kshadow.c index cf3391dba..4454020f0 100644 --- a/xorg-server/hw/kdrive/src/kshadow.c +++ b/xorg-server/hw/kdrive/src/kshadow.c @@ -1,81 +1,81 @@ -/* - * Copyright © 1999 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include "kdrive.h" - -Bool -KdShadowFbAlloc (KdScreenInfo *screen, Bool rotate) -{ - int paddedWidth; - void *buf; - int width = rotate ? screen->height : screen->width; - int height = rotate ? screen->width : screen->height; - int bpp = screen->fb.bitsPerPixel; - - /* use fb computation for width */ - paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits); - buf = xalloc (paddedWidth * height); - if (!buf) - return FALSE; - if (screen->fb.shadow) - xfree (screen->fb.frameBuffer); - screen->fb.shadow = TRUE; - screen->fb.frameBuffer = buf; - screen->fb.byteStride = paddedWidth; - screen->fb.pixelStride = paddedWidth * 8 / bpp; - return TRUE; -} - -void -KdShadowFbFree (KdScreenInfo *screen) -{ - if (screen->fb.shadow) - { - xfree (screen->fb.frameBuffer); - screen->fb.frameBuffer = 0; - screen->fb.shadow = FALSE; - } -} - -Bool -KdShadowSet (ScreenPtr pScreen, int randr, ShadowUpdateProc update, ShadowWindowProc window) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - - shadowRemove (pScreen, pScreen->GetScreenPixmap(pScreen)); - if(screen->fb.shadow) - { - return shadowAdd (pScreen, pScreen->GetScreenPixmap(pScreen), - update, window, randr, 0); - } - return TRUE; -} - -void -KdShadowUnset (ScreenPtr pScreen) -{ - shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); -} +/* + * Copyright © 1999 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" + +Bool +KdShadowFbAlloc (KdScreenInfo *screen, Bool rotate) +{ + int paddedWidth; + void *buf; + int width = rotate ? screen->height : screen->width; + int height = rotate ? screen->width : screen->height; + int bpp = screen->fb.bitsPerPixel; + + /* use fb computation for width */ + paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits); + buf = malloc(paddedWidth * height); + if (!buf) + return FALSE; + if (screen->fb.shadow) + free(screen->fb.frameBuffer); + screen->fb.shadow = TRUE; + screen->fb.frameBuffer = buf; + screen->fb.byteStride = paddedWidth; + screen->fb.pixelStride = paddedWidth * 8 / bpp; + return TRUE; +} + +void +KdShadowFbFree (KdScreenInfo *screen) +{ + if (screen->fb.shadow) + { + free(screen->fb.frameBuffer); + screen->fb.frameBuffer = 0; + screen->fb.shadow = FALSE; + } +} + +Bool +KdShadowSet (ScreenPtr pScreen, int randr, ShadowUpdateProc update, ShadowWindowProc window) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + + shadowRemove (pScreen, pScreen->GetScreenPixmap(pScreen)); + if(screen->fb.shadow) + { + return shadowAdd (pScreen, pScreen->GetScreenPixmap(pScreen), + update, window, randr, 0); + } + return TRUE; +} + +void +KdShadowUnset (ScreenPtr pScreen) +{ + shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen)); +} diff --git a/xorg-server/hw/kdrive/src/kxv.c b/xorg-server/hw/kdrive/src/kxv.c index 27ecc5d6c..9fef34d1f 100644 --- a/xorg-server/hw/kdrive/src/kxv.c +++ b/xorg-server/hw/kdrive/src/kxv.c @@ -1,1907 +1,1907 @@ -/* - - XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com) - Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com> - - Copyright (C) 2000, 2001 - Nokia Home Communications - Copyright (C) 1998, 1999 - The XFree86 Project 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, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -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 -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. - -*/ - -#ifdef HAVE_CONFIG_H -#include <kdrive-config.h> -#endif -#include "kdrive.h" - -#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 <X11/extensions/Xv.h> -#include <X11/extensions/Xvproto.h> - -#include "kxv.h" -#include "fourcc.h" - - -/* XvScreenRec fields */ - -static Bool KdXVCloseScreen(int, ScreenPtr); -static int KdXVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *); - -/* XvAdaptorRec fields */ - -static int KdXVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*); -static int KdXVFreePort(XvPortPtr); -static int KdXVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -static int KdXVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -static int KdXVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -static int KdXVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -static int KdXVStopVideo(ClientPtr, XvPortPtr, DrawablePtr); -static int KdXVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); -static int KdXVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32 *); -static int KdXVQueryBestSize(ClientPtr, XvPortPtr, CARD8, - CARD16, CARD16,CARD16, CARD16, - unsigned int*, unsigned int*); -static int KdXVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16, - XvImagePtr, unsigned char*, Bool, - CARD16, CARD16); -static int KdXVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, - CARD16*, CARD16*, int*, int*); - - -/* ScreenRec fields */ - -static Bool KdXVCreateWindow(WindowPtr pWin); -static Bool KdXVDestroyWindow(WindowPtr pWin); -static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2); -static void KdXVClipNotify(WindowPtr pWin, int dx, int dy); - -/* misc */ -static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr*, int); - -static int KdXVWindowKeyIndex; -DevPrivateKey KdXVWindowKey = &KdXVWindowKeyIndex; -static int KdXvScreenKeyIndex; -DevPrivateKey KdXvScreenKey = &KdXvScreenKeyIndex; -static unsigned long KdXVGeneration = 0; -static unsigned long PortResource = 0; - -DevPrivateKey (*XvGetScreenKeyProc)(void) = XvGetScreenKey; -unsigned long (*XvGetRTPortProc)(void) = XvGetRTPort; -int (*XvScreenInitProc)(ScreenPtr) = XvScreenInit; - -#define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \ - dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey)) - -#define GET_KDXV_SCREEN(pScreen) \ - ((KdXVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr)) - -#define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \ - dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey)) - -static KdXVInitGenericAdaptorPtr *GenDrivers = NULL; -static int NumGenDrivers = 0; - -int -KdXVRegisterGenericAdaptorDriver( - KdXVInitGenericAdaptorPtr InitFunc -){ - KdXVInitGenericAdaptorPtr *newdrivers; - -/* fprintf(stderr,"KdXVRegisterGenericAdaptorDriver\n"); */ - - newdrivers = xrealloc(GenDrivers, sizeof(KdXVInitGenericAdaptorPtr) * - (1 + NumGenDrivers)); - if (!newdrivers) - return 0; - GenDrivers = newdrivers; - - GenDrivers[NumGenDrivers++] = InitFunc; - - return 1; -} - -int -KdXVListGenericAdaptors( - KdScreenInfo * screen, - KdVideoAdaptorPtr **adaptors -){ - int i,j,n,num; - KdVideoAdaptorPtr *DrivAdap,*new; - - num = 0; - *adaptors = NULL; - for (i = 0; i < NumGenDrivers; i++) { - n = GenDrivers[i](screen,&DrivAdap); - if (0 == n) - continue; - new = xrealloc(*adaptors, sizeof(KdVideoAdaptorPtr) * (num+n)); - if (NULL == new) - continue; - *adaptors = new; - for (j = 0; j < n; j++, num++) - (*adaptors)[num] = DrivAdap[j]; - } - return num; -} - -KdVideoAdaptorPtr -KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen) -{ - return xcalloc(1, sizeof(KdVideoAdaptorRec)); -} - -void -KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr) -{ - xfree(ptr); -} - - -Bool -KdXVScreenInit( - ScreenPtr pScreen, - KdVideoAdaptorPtr *adaptors, - int num -){ - KdXVScreenPtr ScreenPriv; - XvScreenPtr pxvs; - -/* fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */ - - if (KdXVGeneration != serverGeneration) - KdXVGeneration = serverGeneration; - - if(!XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc) - return FALSE; - - if(Success != (*XvScreenInitProc)(pScreen)) return FALSE; - - KdXvScreenKey = (*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 = KdXVCloseScreen; - pxvs->ddQueryAdaptors = KdXVQueryAdaptors; - - /* 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(KdXVScreenRec)); - pxvs->devPriv.ptr = (pointer)ScreenPriv; - - if(!ScreenPriv) return FALSE; - - - ScreenPriv->CreateWindow = pScreen->CreateWindow; - ScreenPriv->DestroyWindow = pScreen->DestroyWindow; - ScreenPriv->WindowExposures = pScreen->WindowExposures; - ScreenPriv->ClipNotify = pScreen->ClipNotify; - -/* fprintf(stderr,"XV: Wrapping screen funcs\n"); */ - - pScreen->CreateWindow = KdXVCreateWindow; - pScreen->DestroyWindow = KdXVDestroyWindow; - pScreen->WindowExposures = KdXVWindowExposures; - pScreen->ClipNotify = KdXVClipNotify; - - if(!KdXVInitAdaptors(pScreen, adaptors, num)) - return FALSE; - - return TRUE; -} - -static void -KdXVFreeAdaptor(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 -KdXVInitAdaptors( - ScreenPtr pScreen, - KdVideoAdaptorPtr *infoPtr, - int number -) { - KdScreenPriv(pScreen); - KdScreenInfo * screen = pScreenPriv->screen; - - XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); - KdVideoAdaptorPtr adaptorPtr; - XvAdaptorPtr pAdaptor, pa; - XvAdaptorRecPrivatePtr adaptorPriv; - int na, numAdaptor; - XvPortRecPrivatePtr portPriv; - XvPortPtr pPort, pp; - int numPort; - KdAttributePtr attributePtr; - XvAttributePtr pAttribute, pat; - KdVideoFormatPtr formatPtr; - XvFormatPtr pFormat, pf; - int numFormat, totFormat; - KdVideoEncodingPtr encodingPtr; - XvEncodingPtr pEncode, pe; - KdImagePtr 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 = KdXVAllocatePort; - pa->ddFreePort = KdXVFreePort; - pa->ddPutVideo = KdXVPutVideo; - pa->ddPutStill = KdXVPutStill; - pa->ddGetVideo = KdXVGetVideo; - pa->ddGetStill = KdXVGetStill; - pa->ddStopVideo = KdXVStopVideo; - pa->ddPutImage = KdXVPutImage; - pa->ddSetPortAttribute = KdXVSetPortAttribute; - pa->ddGetPortAttribute = KdXVGetPortAttribute; - pa->ddQueryBestSize = KdXVQueryBestSize; - pa->ddQueryImageAttributes = KdXVQueryImageAttributes; - 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)))) { - KdXVFreeAdaptor(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) { - KdXVFreeAdaptor(pa); - continue; - } - - if(!(adaptorPriv = xcalloc(1, sizeof(XvAdaptorRecPrivate)))) { - KdXVFreeAdaptor(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)))) { - KdXVFreeAdaptor(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->screen = screen; - portPriv->AdaptorRec = adaptorPriv; - portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; - - pp++; - numPort++; - } - pa->nPorts = numPort; - pa->pPorts = pPort; - if(!numPort) { - KdXVFreeAdaptor(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 KdXVUpdateCompositeClip 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 -KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) -{ - RegionPtr pregWin, pCompositeClip; - WindowPtr pWin; - Bool freeCompClip = FALSE; - - if(portPriv->pCompositeClip) - return; - - pWin = (WindowPtr)portPriv->pDraw; - - /* 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(pWin->pScreen, NullBox, 1); - REGION_COPY(pWin->pScreen, pCompositeClip, portPriv->clientClip); - REGION_TRANSLATE(pWin->pScreen, pCompositeClip, - portPriv->pDraw->x + portPriv->clipOrg.x, - portPriv->pDraw->y + portPriv->clipOrg.y); - REGION_INTERSECT(pWin->pScreen, pCompositeClip, pregWin, pCompositeClip); - - portPriv->pCompositeClip = pCompositeClip; - portPriv->FreeCompositeClip = TRUE; - - if(freeCompClip) { - REGION_DESTROY(pWin->pScreen, pregWin); - } -} - -/* Save the current clientClip and update the CompositeClip whenever - we have a fresh GC */ - -static void -KdXVCopyClip( - 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(pGC->pScreen, NullBox, 1); - /* Note: this is in window coordinates */ - REGION_COPY(pGC->pScreen, portPriv->clientClip, pGC->clientClip); - } else if(portPriv->clientClip) { /* free the old clientClip */ - REGION_DESTROY(pGC->pScreen, portPriv->clientClip); - portPriv->clientClip = NULL; - } - - /* get rid of the old clip list */ - if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) { - REGION_DESTROY(pWin->pScreen, portPriv->pCompositeClip); - } - - portPriv->clipOrg = pGC->clipOrg; - portPriv->pCompositeClip = pGC->pCompositeClip; - portPriv->FreeCompositeClip = FALSE; - portPriv->subWindowMode = pGC->subWindowMode; -} - -static int -KdXVRegetVideo(XvPortRecPrivatePtr portPriv) -{ - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - int ret = Success; - Bool clippedAway = FALSE; - - KdXVUpdateCompositeClip(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(portPriv->pDraw->pScreen, &WinRegion, &WinBox, 1); - REGION_INIT(portPriv->pDraw->pScreen, &ClipRegion, NullBox, 1); - REGION_INTERSECT(portPriv->pDraw->pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); - - /* that's all if it's totally obscured */ - if(!REGION_NOTEMPTY(portPriv->pDraw->pScreen, &ClipRegion)) { - clippedAway = TRUE; - goto CLIP_VIDEO_BAILOUT; - } - - if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { - REGION_SUBTRACT(portPriv->pDraw->pScreen, &ClipRegion, &WinRegion, &ClipRegion); - } - - ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->screen, portPriv->pDraw, - 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); - - if(ret == Success) - portPriv->isOn = XV_ON; - -CLIP_VIDEO_BAILOUT: - - if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->screen, 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(portPriv->pDraw->pScreen, &WinRegion); - REGION_UNINIT(portPriv->pDraw->pScreen, &ClipRegion); - - return ret; -} - - -static int -KdXVReputVideo(XvPortRecPrivatePtr portPriv) -{ - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - ScreenPtr pScreen = portPriv->pDraw->pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen=pScreenPriv->screen; - int ret = Success; - Bool clippedAway = FALSE; - - KdXVUpdateCompositeClip(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_INIT(pScreen, &ClipRegion, NullBox, 1); - REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); - - /* clip and translate to the viewport */ - if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { - RegionRec VPReg; - BoxRec VPBox; - - VPBox.x1 = 0; - VPBox.y1 = 0; - VPBox.x2 = screen->width; - VPBox.y2 = screen->height; - - REGION_INIT(pScreen, &VPReg, &VPBox, 1); - REGION_INTERSECT(Screen, &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->screen, portPriv->pDraw, - 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); - - if(ret == Success) portPriv->isOn = XV_ON; - -CLIP_VIDEO_BAILOUT: - - if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->screen, 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 -KdXVReputImage(XvPortRecPrivatePtr portPriv) -{ - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - ScreenPtr pScreen = portPriv->pDraw->pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen=pScreenPriv->screen; - int ret = Success; - Bool clippedAway = FALSE; - - KdXVUpdateCompositeClip(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_INIT(pScreen, &ClipRegion, NullBox, 1); - REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); - - /* clip and translate to the viewport */ - if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { - RegionRec VPReg; - BoxRec VPBox; - - VPBox.x1 = 0; - VPBox.y1 = 0; - VPBox.x2 = screen->width; - VPBox.y2 = screen->height; - - REGION_INIT(pScreen, &VPReg, &VPBox, 1); - REGION_INTERSECT(Screen, &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->screen, portPriv->pDraw, - WinBox.x1, WinBox.y1, - &ClipRegion, portPriv->DevPriv.ptr); - - portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; - -CLIP_VIDEO_BAILOUT: - - if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->screen, 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 -KdXVReputAllVideo(WindowPtr pWin, pointer data) -{ - KdXVWindowPtr WinPriv; - - if (pWin->drawable.type != DRAWABLE_WINDOW) - return WT_DONTWALKCHILDREN; - - WinPriv = GET_KDXV_WINDOW(pWin); - - while(WinPriv) { - if(WinPriv->PortRec->type == XvInputMask) - KdXVReputVideo(WinPriv->PortRec); - else - KdXVRegetVideo(WinPriv->PortRec); - WinPriv = WinPriv->next; - } - - return WT_WALKCHILDREN; -} - -static int -KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) -{ - KdXVWindowPtr winPriv, PrivRoot; - - winPriv = PrivRoot = GET_KDXV_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 = xalloc(sizeof(KdXVWindowRec)); - if(!winPriv) return BadAlloc; - winPriv->PortRec = portPriv; - winPriv->next = PrivRoot; - dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv); - } - return Success; -} - - -static void -KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) -{ - KdXVWindowPtr winPriv, prevPriv = NULL; - - winPriv = GET_KDXV_WINDOW(pWin); - - while(winPriv) { - if(winPriv->PortRec == portPriv) { - if(prevPriv) - prevPriv->next = winPriv->next; - else - dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next); - xfree(winPriv); - break; - } - prevPriv = winPriv; - winPriv = winPriv->next; - } - portPriv->pDraw = NULL; -} - -/**** ScreenRec fields ****/ - - -static Bool -KdXVCreateWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); - int ret; - - pScreen->CreateWindow = ScreenPriv->CreateWindow; - ret = (*pScreen->CreateWindow)(pWin); - pScreen->CreateWindow = KdXVCreateWindow; - - if (ret) - dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL); - - return ret; -} - - -static Bool -KdXVDestroyWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); - KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin); - int ret; - - while(WinPriv) { - XvPortRecPrivatePtr pPriv = WinPriv->PortRec; - - if(pPriv->isOn > XV_OFF) { - (*pPriv->AdaptorRec->StopVideo)( - pPriv->screen, pPriv->DevPriv.ptr, TRUE); - pPriv->isOn = XV_OFF; - } - - pPriv->pDraw = NULL; - tmp = WinPriv; - WinPriv = WinPriv->next; - xfree(tmp); - } - - dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL); - - pScreen->DestroyWindow = ScreenPriv->DestroyWindow; - ret = (*pScreen->DestroyWindow)(pWin); - pScreen->DestroyWindow = KdXVDestroyWindow; - - return ret; -} - - -static void -KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); - KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin); - KdXVWindowPtr pPrev; - XvPortRecPrivatePtr pPriv; - Bool AreasExposed; - - AreasExposed = (WinPriv && reg1 && REGION_NOTEMPTY(pScreen, reg1)); - - pScreen->WindowExposures = ScreenPriv->WindowExposures; - (*pScreen->WindowExposures)(pWin, reg1, reg2); - pScreen->WindowExposures = KdXVWindowExposures; - - /* 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: - KdXVReputVideo(pPriv); - break; - case XvOutputMask: - KdXVRegetVideo(pPriv); - break; - default: /* overlaid still/image*/ - if (pPriv->AdaptorRec->ReputImage) - KdXVReputImage(pPriv); - else if(AreasExposed) { - KdXVWindowPtr tmp; - - if (pPriv->isOn == XV_ON) { - (*pPriv->AdaptorRec->StopVideo)( - pPriv->screen, pPriv->DevPriv.ptr, FALSE); - pPriv->isOn = XV_PENDING; - } - pPriv->pDraw = NULL; - - if(!pPrev) - dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, WinPriv->next); - else - pPrev->next = WinPriv->next; - tmp = WinPriv; - WinPriv = WinPriv->next; - xfree(tmp); - continue; - } - break; - } - pPrev = WinPriv; - WinPriv = WinPriv->next; - } -} - - -static void -KdXVClipNotify(WindowPtr pWin, int dx, int dy) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); - KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin); - KdXVWindowPtr tmp, pPrev = NULL; - XvPortRecPrivatePtr pPriv; - Bool visible = (pWin->visibility == VisibilityUnobscured) || - (pWin->visibility == VisibilityPartiallyObscured); - - while(WinPriv) { - pPriv = WinPriv->PortRec; - - if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) - REGION_DESTROY(pScreen, pPriv->pCompositeClip); - - pPriv->pCompositeClip = NULL; - - /* 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->screen, pPriv->DevPriv.ptr, FALSE); - pPriv->isOn = XV_PENDING; - } - - if(!pPriv->type) { /* overlaid still/image */ - pPriv->pDraw = NULL; - - if(!pPrev) - dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, WinPriv->next); - else - pPrev->next = WinPriv->next; - tmp = WinPriv; - WinPriv = WinPriv->next; - xfree(tmp); - continue; - } - } - - pPrev = WinPriv; - WinPriv = WinPriv->next; - } - - if(ScreenPriv->ClipNotify) { - pScreen->ClipNotify = ScreenPriv->ClipNotify; - (*pScreen->ClipNotify)(pWin, dx, dy); - pScreen->ClipNotify = KdXVClipNotify; - } -} - - - -/**** Required XvScreenRec fields ****/ - -static Bool -KdXVCloseScreen(int i, ScreenPtr pScreen) -{ - XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); - KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); - XvAdaptorPtr pa; - int c; - - if(!ScreenPriv) return TRUE; - - pScreen->CreateWindow = ScreenPriv->CreateWindow; - pScreen->DestroyWindow = ScreenPriv->DestroyWindow; - pScreen->WindowExposures = ScreenPriv->WindowExposures; - pScreen->ClipNotify = ScreenPriv->ClipNotify; - -/* fprintf(stderr,"XV: Unwrapping screen funcs\n"); */ - - for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { - KdXVFreeAdaptor(pa); - } - - xfree(pxvs->pAdaptors); - xfree(ScreenPriv); - - return TRUE; -} - - -static int -KdXVQueryAdaptors( - ScreenPtr pScreen, - XvAdaptorPtr *p_pAdaptors, - int *p_nAdaptors -){ - XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); - - *p_nAdaptors = pxvs->nAdaptors; - *p_pAdaptors = pxvs->pAdaptors; - - return (Success); -} - -static Bool -KdXVRunning (ScreenPtr pScreen) -{ - return (KdXVGeneration == serverGeneration && - GET_XV_SCREEN(pScreen) != 0); -} - -Bool -KdXVEnable(ScreenPtr pScreen) -{ - if (!KdXVRunning (pScreen)) - return TRUE; - - WalkTree(pScreen, KdXVReputAllVideo, 0); - - return TRUE; -} - -void -KdXVDisable(ScreenPtr pScreen) -{ - XvScreenPtr pxvs; - KdXVScreenPtr ScreenPriv; - XvAdaptorPtr pAdaptor; - XvPortPtr pPort; - XvPortRecPrivatePtr pPriv; - int i, j; - - if (!KdXVRunning (pScreen)) - return; - - pxvs = GET_XV_SCREEN(pScreen); - ScreenPriv = GET_KDXV_SCREEN(pScreen); - - 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->screen, 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 */ - KdXVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv); - } - } - } - } -} - -/**** XvAdaptorRec fields ****/ - -static int -KdXVAllocatePort( - unsigned long port, - XvPortPtr pPort, - XvPortPtr *ppPort -){ - *ppPort = pPort; - return Success; -} - -static int -KdXVFreePort(XvPortPtr pPort) -{ - return Success; -} - -static int -KdXVPutVideo( - 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); - KdScreenPriv(portPriv->screen->pScreen); - 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)) - KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); - - /* Register our port with the new window */ - result = KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv); - if(result != Success) return result; - - portPriv->pDraw = pDraw; - 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 */ - KdXVCopyClip(portPriv, pGC); - - /* To indicate to the DI layer that we were successful */ - pPort->pDraw = pDraw; - - if (!pScreenPriv->enabled) return Success; - - return(KdXVReputVideo(portPriv)); -} - -static int -KdXVPutStill( - 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 = pDraw->pScreen; - KdScreenPriv(pScreen); - KdScreenInfo *screen=pScreenPriv->screen; - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - int ret = Success; - Bool clippedAway = FALSE; - - if (pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - if (!pScreenPriv->enabled) return Success; - - 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_INIT(pScreen, &ClipRegion, NullBox, 1); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); - - if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { - RegionRec VPReg; - BoxRec VPBox; - - VPBox.x1 = 0; - VPBox.y1 = 0; - VPBox.x2 = screen->width; - VPBox.y2 = screen->height; - - REGION_INIT(pScreen, &VPReg, &VPBox, 1); - REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg); - REGION_UNINIT(pScreen, &VPReg); - } - - if(portPriv->pDraw) { - KdXVRemovePortFromWindow((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->screen, pDraw, - vid_x, vid_y, WinBox.x1, WinBox.y1, - vid_w, vid_h, drw_w, drw_h, - &ClipRegion, portPriv->DevPriv.ptr); - - if((ret == Success) && - (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { - - KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv); - portPriv->isOn = XV_ON; - portPriv->pDraw = pDraw; - 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->screen, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - -static int -KdXVGetVideo( - 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; - KdScreenPriv(portPriv->screen->pScreen); - - /* 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)) - KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); - - /* Register our port with the new window */ - result = KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv); - if(result != Success) return result; - - portPriv->pDraw = pDraw; - 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 */ - KdXVCopyClip(portPriv, pGC); - - /* To indicate to the DI layer that we were successful */ - pPort->pDraw = pDraw; - - if(!pScreenPriv->enabled) return Success; - - return(KdXVRegetVideo(portPriv)); -} - -static int -KdXVGetStill( - 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 = pDraw->pScreen; - KdScreenPriv(pScreen); - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - int ret = Success; - Bool clippedAway = FALSE; - - if (pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - if(!pScreenPriv->enabled) return Success; - - 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_INIT(pScreen, &ClipRegion, NullBox, 1); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); - - if(portPriv->pDraw) { - KdXVRemovePortFromWindow((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->screen, pDraw, - vid_x, vid_y, WinBox.x1, WinBox.y1, - vid_w, vid_h, drw_w, drw_h, - &ClipRegion, portPriv->DevPriv.ptr); - -GET_STILL_BAILOUT: - - if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->screen, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - - - -static int -KdXVStopVideo( - ClientPtr client, - XvPortPtr pPort, - DrawablePtr pDraw -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - KdScreenPriv(portPriv->screen->pScreen); - - if(pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - KdXVRemovePortFromWindow((WindowPtr)pDraw, portPriv); - - if(!pScreenPriv->enabled) return Success; - - /* Must free resources. */ - - if(portPriv->isOn > XV_OFF) { - (*portPriv->AdaptorRec->StopVideo)( - portPriv->screen, portPriv->DevPriv.ptr, TRUE); - portPriv->isOn = XV_OFF; - } - - return Success; -} - -static int -KdXVSetPortAttribute( - ClientPtr client, - XvPortPtr pPort, - Atom attribute, - INT32 value -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - - return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->screen, - attribute, value, portPriv->DevPriv.ptr)); -} - - -static int -KdXVGetPortAttribute( - ClientPtr client, - XvPortPtr pPort, - Atom attribute, - INT32 *p_value -){ - XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); - - return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->screen, - attribute, (int *) p_value, portPriv->DevPriv.ptr)); -} - - - -static int -KdXVQueryBestSize( - 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->screen, - (Bool)motion, vid_w, vid_h, drw_w, drw_h, - p_w, p_h, portPriv->DevPriv.ptr); - - return Success; -} - - -static int -KdXVPutImage( - 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 = pDraw->pScreen; - KdScreenPriv(pScreen); - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - int ret = Success; - Bool clippedAway = FALSE; - - if (pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - if(!pScreenPriv->enabled) return Success; - - 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_INIT(pScreen, &ClipRegion, NullBox, 1); - REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); - - if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { - RegionRec VPReg; - BoxRec VPBox; - - VPBox.x1 = 0; - VPBox.y1 = 0; - VPBox.x2 = pScreen->width; - VPBox.y2 = pScreen->height; - - REGION_INIT(pScreen, &VPReg, &VPBox, 1); - REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg); - REGION_UNINIT(pScreen, &VPReg); - } - - if(portPriv->pDraw) { - KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); - } - - 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->screen, pDraw, - 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); - - if((ret == Success) && - (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { - - KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv); - portPriv->isOn = XV_ON; - portPriv->pDraw = pDraw; - 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->screen, portPriv->DevPriv.ptr, FALSE); - portPriv->isOn = XV_PENDING; - } - - REGION_UNINIT(pScreen, &WinRegion); - REGION_UNINIT(pScreen, &ClipRegion); - - return ret; -} - - -static int -KdXVQueryImageAttributes( - 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->screen, - format->id, width, height, pitches, offsets); -} - - -/**************** Common video manipulation functions *******************/ - -void -KdXVCopyPackedData(KdScreenInfo *screen, CARD8 *src, CARD8 *dst, int randr, - int srcPitch, int dstPitch, int srcW, int srcH, int top, int left, - int h, int w) -{ - int srcDown = srcPitch, srcRight = 2, srcNext; - int p; - - switch (randr & RR_Rotate_All) { - case RR_Rotate_0: - srcDown = srcPitch; - srcRight = 2; - break; - case RR_Rotate_90: - src += (srcH - 1) * 2; - srcDown = -2; - srcRight = srcPitch; - break; - case RR_Rotate_180: - src += srcPitch * (srcH - 1) + (srcW - 1) * 2; - srcDown = -srcPitch; - srcRight = -2; - break; - case RR_Rotate_270: - src += srcPitch * (srcW - 1); - srcDown = 2; - srcRight = -srcPitch; - break; - } - - src = src + top * srcDown + left * srcRight; - - w >>= 1; - /* srcRight >>= 1; */ - srcNext = srcRight >> 1; - while (h--) { - CARD16 *s = (CARD16 *)src; - CARD32 *d = (CARD32 *)dst; - p = w; - while (p--) { - *d++ = s[0] | (s[srcNext] << 16); - s += srcRight; - } - src += srcPitch; - dst += dstPitch; - } -} - -void -KdXVCopyPlanarData(KdScreenInfo *screen, CARD8 *src, CARD8 *dst, int randr, - int srcPitch, int srcPitch2, int dstPitch, int srcW, int srcH, int height, - int top, int left, int h, int w, int id) -{ - int i, j; - CARD8 *src1, *src2, *src3, *dst1; - int srcDown = srcPitch, srcDown2 = srcPitch2; - int srcRight = 2, srcRight2 = 1, srcNext = 1; - - /* compute source data pointers */ - src1 = src; - src2 = src1 + height * srcPitch; - src3 = src2 + (height >> 1) * srcPitch2; - switch (randr & RR_Rotate_All) { - case RR_Rotate_0: - srcDown = srcPitch; - srcDown2 = srcPitch2; - srcRight = 2; - srcRight2 = 1; - srcNext = 1; - break; - case RR_Rotate_90: - src1 = src1 + srcH - 1; - src2 = src2 + (srcH >> 1) - 1; - src3 = src3 + (srcH >> 1) - 1; - srcDown = -1; - srcDown2 = -1; - srcRight = srcPitch * 2; - srcRight2 = srcPitch2; - srcNext = srcPitch; - break; - case RR_Rotate_180: - src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1); - src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); - src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); - srcDown = -srcPitch; - srcDown2 = -srcPitch2; - srcRight = -2; - srcRight2 = -1; - srcNext = -1; - break; - case RR_Rotate_270: - src1 = src1 + srcPitch * (srcW - 1); - src2 = src2 + srcPitch2 * ((srcW >> 1) - 1); - src3 = src3 + srcPitch2 * ((srcW >> 1) - 1); - srcDown = 1; - srcDown2 = 1; - srcRight = -srcPitch * 2; - srcRight2 = -srcPitch2; - srcNext = -srcPitch; - break; - } - - /* adjust for origin */ - src1 += top * srcDown + left * srcNext; - src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; - src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; - - if (id == FOURCC_I420) { - CARD8 *srct = src2; - src2 = src3; - src3 = srct; - } - - dst1 = dst; - - w >>= 1; - for (j = 0; j < h; j++) { - CARD32 *dst = (CARD32 *)dst1; - CARD8 *s1l = src1; - CARD8 *s1r = src1 + srcNext; - CARD8 *s2 = src2; - CARD8 *s3 = src3; - - for (i = 0; i < w; i++) { - *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24); - s1l += srcRight; - s1r += srcRight; - s2 += srcRight2; - s3 += srcRight2; - } - src1 += srcDown; - dst1 += dstPitch; - if (j & 1) { - src2 += srcDown2; - src3 += srcDown2; - } - } -} - -void -KXVPaintRegion (DrawablePtr pDraw, RegionPtr pRgn, Pixel fg) -{ - GCPtr pGC; - CARD32 val[2]; - xRectangle *rects, *r; - BoxPtr pBox = REGION_RECTS (pRgn); - int nBox = REGION_NUM_RECTS (pRgn); - - rects = xalloc (nBox * sizeof (xRectangle)); - if (!rects) - goto bail0; - r = rects; - while (nBox--) - { - r->x = pBox->x1 - pDraw->x; - r->y = pBox->y1 - pDraw->y; - r->width = pBox->x2 - pBox->x1; - r->height = pBox->y2 - pBox->y1; - r++; - pBox++; - } - - pGC = GetScratchGC (pDraw->depth, pDraw->pScreen); - if (!pGC) - goto bail1; - - val[0] = fg; - val[1] = IncludeInferiors; - ChangeGC (pGC, GCForeground|GCSubwindowMode, val); - - ValidateGC (pDraw, pGC); - - (*pGC->ops->PolyFillRect) (pDraw, pGC, - REGION_NUM_RECTS (pRgn), rects); - - FreeScratchGC (pGC); -bail1: - xfree (rects); -bail0: - ; -} +/* + + XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com) + Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com> + + Copyright (C) 2000, 2001 - Nokia Home Communications + Copyright (C) 1998, 1999 - The XFree86 Project 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, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +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 +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +*/ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" + +#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 <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> + +#include "kxv.h" +#include "fourcc.h" + + +/* XvScreenRec fields */ + +static Bool KdXVCloseScreen(int, ScreenPtr); +static int KdXVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *); + +/* XvAdaptorRec fields */ + +static int KdXVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*); +static int KdXVFreePort(XvPortPtr); +static int KdXVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int KdXVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int KdXVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int KdXVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int KdXVStopVideo(ClientPtr, XvPortPtr, DrawablePtr); +static int KdXVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); +static int KdXVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32 *); +static int KdXVQueryBestSize(ClientPtr, XvPortPtr, CARD8, + CARD16, CARD16,CARD16, CARD16, + unsigned int*, unsigned int*); +static int KdXVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char*, Bool, + CARD16, CARD16); +static int KdXVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, + CARD16*, CARD16*, int*, int*); + + +/* ScreenRec fields */ + +static Bool KdXVCreateWindow(WindowPtr pWin); +static Bool KdXVDestroyWindow(WindowPtr pWin); +static void KdXVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2); +static void KdXVClipNotify(WindowPtr pWin, int dx, int dy); + +/* misc */ +static Bool KdXVInitAdaptors(ScreenPtr, KdVideoAdaptorPtr*, int); + +static int KdXVWindowKeyIndex; +DevPrivateKey KdXVWindowKey = &KdXVWindowKeyIndex; +static int KdXvScreenKeyIndex; +DevPrivateKey KdXvScreenKey = &KdXvScreenKeyIndex; +static unsigned long KdXVGeneration = 0; +static unsigned long PortResource = 0; + +DevPrivateKey (*XvGetScreenKeyProc)(void) = XvGetScreenKey; +unsigned long (*XvGetRTPortProc)(void) = XvGetRTPort; +int (*XvScreenInitProc)(ScreenPtr) = XvScreenInit; + +#define GET_XV_SCREEN(pScreen) ((XvScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, KdXvScreenKey)) + +#define GET_KDXV_SCREEN(pScreen) \ + ((KdXVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr)) + +#define GET_KDXV_WINDOW(pWin) ((KdXVWindowPtr) \ + dixLookupPrivate(&(pWin)->devPrivates, KdXVWindowKey)) + +static KdXVInitGenericAdaptorPtr *GenDrivers = NULL; +static int NumGenDrivers = 0; + +int +KdXVRegisterGenericAdaptorDriver( + KdXVInitGenericAdaptorPtr InitFunc +){ + KdXVInitGenericAdaptorPtr *newdrivers; + +/* fprintf(stderr,"KdXVRegisterGenericAdaptorDriver\n"); */ + + newdrivers = realloc(GenDrivers, sizeof(KdXVInitGenericAdaptorPtr) * + (1 + NumGenDrivers)); + if (!newdrivers) + return 0; + GenDrivers = newdrivers; + + GenDrivers[NumGenDrivers++] = InitFunc; + + return 1; +} + +int +KdXVListGenericAdaptors( + KdScreenInfo * screen, + KdVideoAdaptorPtr **adaptors +){ + int i,j,n,num; + KdVideoAdaptorPtr *DrivAdap,*new; + + num = 0; + *adaptors = NULL; + for (i = 0; i < NumGenDrivers; i++) { + n = GenDrivers[i](screen,&DrivAdap); + if (0 == n) + continue; + new = realloc(*adaptors, sizeof(KdVideoAdaptorPtr) * (num+n)); + if (NULL == new) + continue; + *adaptors = new; + for (j = 0; j < n; j++, num++) + (*adaptors)[num] = DrivAdap[j]; + } + return num; +} + +KdVideoAdaptorPtr +KdXVAllocateVideoAdaptorRec(KdScreenInfo * screen) +{ + return calloc(1, sizeof(KdVideoAdaptorRec)); +} + +void +KdXVFreeVideoAdaptorRec(KdVideoAdaptorPtr ptr) +{ + free(ptr); +} + + +Bool +KdXVScreenInit( + ScreenPtr pScreen, + KdVideoAdaptorPtr *adaptors, + int num +){ + KdXVScreenPtr ScreenPriv; + XvScreenPtr pxvs; + +/* fprintf(stderr,"KdXVScreenInit initializing %d adaptors\n",num); */ + + if (KdXVGeneration != serverGeneration) + KdXVGeneration = serverGeneration; + + if(!XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc) + return FALSE; + + if(Success != (*XvScreenInitProc)(pScreen)) return FALSE; + + KdXvScreenKey = (*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 = KdXVCloseScreen; + pxvs->ddQueryAdaptors = KdXVQueryAdaptors; + + /* 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(KdXVScreenRec)); + pxvs->devPriv.ptr = (pointer)ScreenPriv; + + if(!ScreenPriv) return FALSE; + + + ScreenPriv->CreateWindow = pScreen->CreateWindow; + ScreenPriv->DestroyWindow = pScreen->DestroyWindow; + ScreenPriv->WindowExposures = pScreen->WindowExposures; + ScreenPriv->ClipNotify = pScreen->ClipNotify; + +/* fprintf(stderr,"XV: Wrapping screen funcs\n"); */ + + pScreen->CreateWindow = KdXVCreateWindow; + pScreen->DestroyWindow = KdXVDestroyWindow; + pScreen->WindowExposures = KdXVWindowExposures; + pScreen->ClipNotify = KdXVClipNotify; + + if(!KdXVInitAdaptors(pScreen, adaptors, num)) + return FALSE; + + return TRUE; +} + +static void +KdXVFreeAdaptor(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 +KdXVInitAdaptors( + ScreenPtr pScreen, + KdVideoAdaptorPtr *infoPtr, + int number +) { + KdScreenPriv(pScreen); + KdScreenInfo * screen = pScreenPriv->screen; + + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + KdVideoAdaptorPtr adaptorPtr; + XvAdaptorPtr pAdaptor, pa; + XvAdaptorRecPrivatePtr adaptorPriv; + int na, numAdaptor; + XvPortRecPrivatePtr portPriv; + XvPortPtr pPort, pp; + int numPort; + KdAttributePtr attributePtr; + XvAttributePtr pAttribute, pat; + KdVideoFormatPtr formatPtr; + XvFormatPtr pFormat, pf; + int numFormat, totFormat; + KdVideoEncodingPtr encodingPtr; + XvEncodingPtr pEncode, pe; + KdImagePtr 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 = KdXVAllocatePort; + pa->ddFreePort = KdXVFreePort; + pa->ddPutVideo = KdXVPutVideo; + pa->ddPutStill = KdXVPutStill; + pa->ddGetVideo = KdXVGetVideo; + pa->ddGetStill = KdXVGetStill; + pa->ddStopVideo = KdXVStopVideo; + pa->ddPutImage = KdXVPutImage; + pa->ddSetPortAttribute = KdXVSetPortAttribute; + pa->ddGetPortAttribute = KdXVGetPortAttribute; + pa->ddQueryBestSize = KdXVQueryBestSize; + pa->ddQueryImageAttributes = KdXVQueryImageAttributes; + 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)))) { + KdXVFreeAdaptor(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) { + KdXVFreeAdaptor(pa); + continue; + } + + if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) { + KdXVFreeAdaptor(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)))) { + KdXVFreeAdaptor(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->screen = screen; + portPriv->AdaptorRec = adaptorPriv; + portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; + + pp++; + numPort++; + } + pa->nPorts = numPort; + pa->pPorts = pPort; + if(!numPort) { + KdXVFreeAdaptor(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 KdXVUpdateCompositeClip 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 +KdXVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) +{ + RegionPtr pregWin, pCompositeClip; + WindowPtr pWin; + Bool freeCompClip = FALSE; + + if(portPriv->pCompositeClip) + return; + + pWin = (WindowPtr)portPriv->pDraw; + + /* 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(pWin->pScreen, NullBox, 1); + REGION_COPY(pWin->pScreen, pCompositeClip, portPriv->clientClip); + REGION_TRANSLATE(pWin->pScreen, pCompositeClip, + portPriv->pDraw->x + portPriv->clipOrg.x, + portPriv->pDraw->y + portPriv->clipOrg.y); + REGION_INTERSECT(pWin->pScreen, pCompositeClip, pregWin, pCompositeClip); + + portPriv->pCompositeClip = pCompositeClip; + portPriv->FreeCompositeClip = TRUE; + + if(freeCompClip) { + REGION_DESTROY(pWin->pScreen, pregWin); + } +} + +/* Save the current clientClip and update the CompositeClip whenever + we have a fresh GC */ + +static void +KdXVCopyClip( + 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(pGC->pScreen, NullBox, 1); + /* Note: this is in window coordinates */ + REGION_COPY(pGC->pScreen, portPriv->clientClip, pGC->clientClip); + } else if(portPriv->clientClip) { /* free the old clientClip */ + REGION_DESTROY(pGC->pScreen, portPriv->clientClip); + portPriv->clientClip = NULL; + } + + /* get rid of the old clip list */ + if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) { + REGION_DESTROY(pWin->pScreen, portPriv->pCompositeClip); + } + + portPriv->clipOrg = pGC->clipOrg; + portPriv->pCompositeClip = pGC->pCompositeClip; + portPriv->FreeCompositeClip = FALSE; + portPriv->subWindowMode = pGC->subWindowMode; +} + +static int +KdXVRegetVideo(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + KdXVUpdateCompositeClip(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(portPriv->pDraw->pScreen, &WinRegion, &WinBox, 1); + REGION_INIT(portPriv->pDraw->pScreen, &ClipRegion, NullBox, 1); + REGION_INTERSECT(portPriv->pDraw->pScreen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* that's all if it's totally obscured */ + if(!REGION_NOTEMPTY(portPriv->pDraw->pScreen, &ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + REGION_SUBTRACT(portPriv->pDraw->pScreen, &ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->screen, portPriv->pDraw, + 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); + + if(ret == Success) + portPriv->isOn = XV_ON; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->screen, 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(portPriv->pDraw->pScreen, &WinRegion); + REGION_UNINIT(portPriv->pDraw->pScreen, &ClipRegion); + + return ret; +} + + +static int +KdXVReputVideo(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + ScreenPtr pScreen = portPriv->pDraw->pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen=pScreenPriv->screen; + int ret = Success; + Bool clippedAway = FALSE; + + KdXVUpdateCompositeClip(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_INIT(pScreen, &ClipRegion, NullBox, 1); + REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* clip and translate to the viewport */ + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = 0; + VPBox.y1 = 0; + VPBox.x2 = screen->width; + VPBox.y2 = screen->height; + + REGION_INIT(pScreen, &VPReg, &VPBox, 1); + REGION_INTERSECT(Screen, &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->screen, portPriv->pDraw, + 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); + + if(ret == Success) portPriv->isOn = XV_ON; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->screen, 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 +KdXVReputImage(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + ScreenPtr pScreen = portPriv->pDraw->pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen=pScreenPriv->screen; + int ret = Success; + Bool clippedAway = FALSE; + + KdXVUpdateCompositeClip(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_INIT(pScreen, &ClipRegion, NullBox, 1); + REGION_INTERSECT(Screen, &ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* clip and translate to the viewport */ + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = 0; + VPBox.y1 = 0; + VPBox.x2 = screen->width; + VPBox.y2 = screen->height; + + REGION_INIT(pScreen, &VPReg, &VPBox, 1); + REGION_INTERSECT(Screen, &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->screen, portPriv->pDraw, + WinBox.x1, WinBox.y1, + &ClipRegion, portPriv->DevPriv.ptr); + + portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->screen, 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 +KdXVReputAllVideo(WindowPtr pWin, pointer data) +{ + KdXVWindowPtr WinPriv; + + if (pWin->drawable.type != DRAWABLE_WINDOW) + return WT_DONTWALKCHILDREN; + + WinPriv = GET_KDXV_WINDOW(pWin); + + while(WinPriv) { + if(WinPriv->PortRec->type == XvInputMask) + KdXVReputVideo(WinPriv->PortRec); + else + KdXVRegetVideo(WinPriv->PortRec); + WinPriv = WinPriv->next; + } + + return WT_WALKCHILDREN; +} + +static int +KdXVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) +{ + KdXVWindowPtr winPriv, PrivRoot; + + winPriv = PrivRoot = GET_KDXV_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 = malloc(sizeof(KdXVWindowRec)); + if(!winPriv) return BadAlloc; + winPriv->PortRec = portPriv; + winPriv->next = PrivRoot; + dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv); + } + return Success; +} + + +static void +KdXVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) +{ + KdXVWindowPtr winPriv, prevPriv = NULL; + + winPriv = GET_KDXV_WINDOW(pWin); + + while(winPriv) { + if(winPriv->PortRec == portPriv) { + if(prevPriv) + prevPriv->next = winPriv->next; + else + dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, winPriv->next); + free(winPriv); + break; + } + prevPriv = winPriv; + winPriv = winPriv->next; + } + portPriv->pDraw = NULL; +} + +/**** ScreenRec fields ****/ + + +static Bool +KdXVCreateWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); + int ret; + + pScreen->CreateWindow = ScreenPriv->CreateWindow; + ret = (*pScreen->CreateWindow)(pWin); + pScreen->CreateWindow = KdXVCreateWindow; + + if (ret) + dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL); + + return ret; +} + + +static Bool +KdXVDestroyWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); + KdXVWindowPtr tmp, WinPriv = GET_KDXV_WINDOW(pWin); + int ret; + + while(WinPriv) { + XvPortRecPrivatePtr pPriv = WinPriv->PortRec; + + if(pPriv->isOn > XV_OFF) { + (*pPriv->AdaptorRec->StopVideo)( + pPriv->screen, pPriv->DevPriv.ptr, TRUE); + pPriv->isOn = XV_OFF; + } + + pPriv->pDraw = NULL; + tmp = WinPriv; + WinPriv = WinPriv->next; + free(tmp); + } + + dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, NULL); + + pScreen->DestroyWindow = ScreenPriv->DestroyWindow; + ret = (*pScreen->DestroyWindow)(pWin); + pScreen->DestroyWindow = KdXVDestroyWindow; + + return ret; +} + + +static void +KdXVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); + KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin); + KdXVWindowPtr pPrev; + XvPortRecPrivatePtr pPriv; + Bool AreasExposed; + + AreasExposed = (WinPriv && reg1 && REGION_NOTEMPTY(pScreen, reg1)); + + pScreen->WindowExposures = ScreenPriv->WindowExposures; + (*pScreen->WindowExposures)(pWin, reg1, reg2); + pScreen->WindowExposures = KdXVWindowExposures; + + /* 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: + KdXVReputVideo(pPriv); + break; + case XvOutputMask: + KdXVRegetVideo(pPriv); + break; + default: /* overlaid still/image*/ + if (pPriv->AdaptorRec->ReputImage) + KdXVReputImage(pPriv); + else if(AreasExposed) { + KdXVWindowPtr tmp; + + if (pPriv->isOn == XV_ON) { + (*pPriv->AdaptorRec->StopVideo)( + pPriv->screen, pPriv->DevPriv.ptr, FALSE); + pPriv->isOn = XV_PENDING; + } + pPriv->pDraw = NULL; + + if(!pPrev) + dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, WinPriv->next); + else + pPrev->next = WinPriv->next; + tmp = WinPriv; + WinPriv = WinPriv->next; + free(tmp); + continue; + } + break; + } + pPrev = WinPriv; + WinPriv = WinPriv->next; + } +} + + +static void +KdXVClipNotify(WindowPtr pWin, int dx, int dy) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); + KdXVWindowPtr WinPriv = GET_KDXV_WINDOW(pWin); + KdXVWindowPtr tmp, pPrev = NULL; + XvPortRecPrivatePtr pPriv; + Bool visible = (pWin->visibility == VisibilityUnobscured) || + (pWin->visibility == VisibilityPartiallyObscured); + + while(WinPriv) { + pPriv = WinPriv->PortRec; + + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + REGION_DESTROY(pScreen, pPriv->pCompositeClip); + + pPriv->pCompositeClip = NULL; + + /* 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->screen, pPriv->DevPriv.ptr, FALSE); + pPriv->isOn = XV_PENDING; + } + + if(!pPriv->type) { /* overlaid still/image */ + pPriv->pDraw = NULL; + + if(!pPrev) + dixSetPrivate(&pWin->devPrivates, KdXVWindowKey, WinPriv->next); + else + pPrev->next = WinPriv->next; + tmp = WinPriv; + WinPriv = WinPriv->next; + free(tmp); + continue; + } + } + + pPrev = WinPriv; + WinPriv = WinPriv->next; + } + + if(ScreenPriv->ClipNotify) { + pScreen->ClipNotify = ScreenPriv->ClipNotify; + (*pScreen->ClipNotify)(pWin, dx, dy); + pScreen->ClipNotify = KdXVClipNotify; + } +} + + + +/**** Required XvScreenRec fields ****/ + +static Bool +KdXVCloseScreen(int i, ScreenPtr pScreen) +{ + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + KdXVScreenPtr ScreenPriv = GET_KDXV_SCREEN(pScreen); + XvAdaptorPtr pa; + int c; + + if(!ScreenPriv) return TRUE; + + pScreen->CreateWindow = ScreenPriv->CreateWindow; + pScreen->DestroyWindow = ScreenPriv->DestroyWindow; + pScreen->WindowExposures = ScreenPriv->WindowExposures; + pScreen->ClipNotify = ScreenPriv->ClipNotify; + +/* fprintf(stderr,"XV: Unwrapping screen funcs\n"); */ + + for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { + KdXVFreeAdaptor(pa); + } + + free(pxvs->pAdaptors); + free(ScreenPriv); + + return TRUE; +} + + +static int +KdXVQueryAdaptors( + ScreenPtr pScreen, + XvAdaptorPtr *p_pAdaptors, + int *p_nAdaptors +){ + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + + *p_nAdaptors = pxvs->nAdaptors; + *p_pAdaptors = pxvs->pAdaptors; + + return (Success); +} + +static Bool +KdXVRunning (ScreenPtr pScreen) +{ + return (KdXVGeneration == serverGeneration && + GET_XV_SCREEN(pScreen) != 0); +} + +Bool +KdXVEnable(ScreenPtr pScreen) +{ + if (!KdXVRunning (pScreen)) + return TRUE; + + WalkTree(pScreen, KdXVReputAllVideo, 0); + + return TRUE; +} + +void +KdXVDisable(ScreenPtr pScreen) +{ + XvScreenPtr pxvs; + KdXVScreenPtr ScreenPriv; + XvAdaptorPtr pAdaptor; + XvPortPtr pPort; + XvPortRecPrivatePtr pPriv; + int i, j; + + if (!KdXVRunning (pScreen)) + return; + + pxvs = GET_XV_SCREEN(pScreen); + ScreenPriv = GET_KDXV_SCREEN(pScreen); + + 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->screen, 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 */ + KdXVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv); + } + } + } + } +} + +/**** XvAdaptorRec fields ****/ + +static int +KdXVAllocatePort( + unsigned long port, + XvPortPtr pPort, + XvPortPtr *ppPort +){ + *ppPort = pPort; + return Success; +} + +static int +KdXVFreePort(XvPortPtr pPort) +{ + return Success; +} + +static int +KdXVPutVideo( + 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); + KdScreenPriv(portPriv->screen->pScreen); + 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)) + KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + result = KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(result != Success) return result; + + portPriv->pDraw = pDraw; + 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 */ + KdXVCopyClip(portPriv, pGC); + + /* To indicate to the DI layer that we were successful */ + pPort->pDraw = pDraw; + + if (!pScreenPriv->enabled) return Success; + + return(KdXVReputVideo(portPriv)); +} + +static int +KdXVPutStill( + 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 = pDraw->pScreen; + KdScreenPriv(pScreen); + KdScreenInfo *screen=pScreenPriv->screen; + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if (!pScreenPriv->enabled) return Success; + + 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_INIT(pScreen, &ClipRegion, NullBox, 1); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = 0; + VPBox.y1 = 0; + VPBox.x2 = screen->width; + VPBox.y2 = screen->height; + + REGION_INIT(pScreen, &VPReg, &VPBox, 1); + REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg); + REGION_UNINIT(pScreen, &VPReg); + } + + if(portPriv->pDraw) { + KdXVRemovePortFromWindow((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->screen, pDraw, + vid_x, vid_y, WinBox.x1, WinBox.y1, + vid_w, vid_h, drw_w, drw_h, + &ClipRegion, portPriv->DevPriv.ptr); + + if((ret == Success) && + (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { + + KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + portPriv->isOn = XV_ON; + portPriv->pDraw = pDraw; + 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->screen, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + +static int +KdXVGetVideo( + 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; + KdScreenPriv(portPriv->screen->pScreen); + + /* 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)) + KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + result = KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(result != Success) return result; + + portPriv->pDraw = pDraw; + 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 */ + KdXVCopyClip(portPriv, pGC); + + /* To indicate to the DI layer that we were successful */ + pPort->pDraw = pDraw; + + if(!pScreenPriv->enabled) return Success; + + return(KdXVRegetVideo(portPriv)); +} + +static int +KdXVGetStill( + 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 = pDraw->pScreen; + KdScreenPriv(pScreen); + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!pScreenPriv->enabled) return Success; + + 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_INIT(pScreen, &ClipRegion, NullBox, 1); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->pDraw) { + KdXVRemovePortFromWindow((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->screen, pDraw, + vid_x, vid_y, WinBox.x1, WinBox.y1, + vid_w, vid_h, drw_w, drw_h, + &ClipRegion, portPriv->DevPriv.ptr); + +GET_STILL_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->screen, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + + + +static int +KdXVStopVideo( + ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDraw +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + KdScreenPriv(portPriv->screen->pScreen); + + if(pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + KdXVRemovePortFromWindow((WindowPtr)pDraw, portPriv); + + if(!pScreenPriv->enabled) return Success; + + /* Must free resources. */ + + if(portPriv->isOn > XV_OFF) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->screen, portPriv->DevPriv.ptr, TRUE); + portPriv->isOn = XV_OFF; + } + + return Success; +} + +static int +KdXVSetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 value +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->screen, + attribute, value, portPriv->DevPriv.ptr)); +} + + +static int +KdXVGetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 *p_value +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->screen, + attribute, (int *) p_value, portPriv->DevPriv.ptr)); +} + + + +static int +KdXVQueryBestSize( + 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->screen, + (Bool)motion, vid_w, vid_h, drw_w, drw_h, + p_w, p_h, portPriv->DevPriv.ptr); + + return Success; +} + + +static int +KdXVPutImage( + 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 = pDraw->pScreen; + KdScreenPriv(pScreen); + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!pScreenPriv->enabled) return Success; + + 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_INIT(pScreen, &ClipRegion, NullBox, 1); + REGION_INTERSECT(pScreen, &ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = 0; + VPBox.y1 = 0; + VPBox.x2 = pScreen->width; + VPBox.y2 = pScreen->height; + + REGION_INIT(pScreen, &VPReg, &VPBox, 1); + REGION_INTERSECT(Screen, &ClipRegion, &ClipRegion, &VPReg); + REGION_UNINIT(pScreen, &VPReg); + } + + if(portPriv->pDraw) { + KdXVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + } + + 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->screen, pDraw, + 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); + + if((ret == Success) && + (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { + + KdXVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + portPriv->isOn = XV_ON; + portPriv->pDraw = pDraw; + 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->screen, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + REGION_UNINIT(pScreen, &WinRegion); + REGION_UNINIT(pScreen, &ClipRegion); + + return ret; +} + + +static int +KdXVQueryImageAttributes( + 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->screen, + format->id, width, height, pitches, offsets); +} + + +/**************** Common video manipulation functions *******************/ + +void +KdXVCopyPackedData(KdScreenInfo *screen, CARD8 *src, CARD8 *dst, int randr, + int srcPitch, int dstPitch, int srcW, int srcH, int top, int left, + int h, int w) +{ + int srcDown = srcPitch, srcRight = 2, srcNext; + int p; + + switch (randr & RR_Rotate_All) { + case RR_Rotate_0: + srcDown = srcPitch; + srcRight = 2; + break; + case RR_Rotate_90: + src += (srcH - 1) * 2; + srcDown = -2; + srcRight = srcPitch; + break; + case RR_Rotate_180: + src += srcPitch * (srcH - 1) + (srcW - 1) * 2; + srcDown = -srcPitch; + srcRight = -2; + break; + case RR_Rotate_270: + src += srcPitch * (srcW - 1); + srcDown = 2; + srcRight = -srcPitch; + break; + } + + src = src + top * srcDown + left * srcRight; + + w >>= 1; + /* srcRight >>= 1; */ + srcNext = srcRight >> 1; + while (h--) { + CARD16 *s = (CARD16 *)src; + CARD32 *d = (CARD32 *)dst; + p = w; + while (p--) { + *d++ = s[0] | (s[srcNext] << 16); + s += srcRight; + } + src += srcPitch; + dst += dstPitch; + } +} + +void +KdXVCopyPlanarData(KdScreenInfo *screen, CARD8 *src, CARD8 *dst, int randr, + int srcPitch, int srcPitch2, int dstPitch, int srcW, int srcH, int height, + int top, int left, int h, int w, int id) +{ + int i, j; + CARD8 *src1, *src2, *src3, *dst1; + int srcDown = srcPitch, srcDown2 = srcPitch2; + int srcRight = 2, srcRight2 = 1, srcNext = 1; + + /* compute source data pointers */ + src1 = src; + src2 = src1 + height * srcPitch; + src3 = src2 + (height >> 1) * srcPitch2; + switch (randr & RR_Rotate_All) { + case RR_Rotate_0: + srcDown = srcPitch; + srcDown2 = srcPitch2; + srcRight = 2; + srcRight2 = 1; + srcNext = 1; + break; + case RR_Rotate_90: + src1 = src1 + srcH - 1; + src2 = src2 + (srcH >> 1) - 1; + src3 = src3 + (srcH >> 1) - 1; + srcDown = -1; + srcDown2 = -1; + srcRight = srcPitch * 2; + srcRight2 = srcPitch2; + srcNext = srcPitch; + break; + case RR_Rotate_180: + src1 = src1 + srcPitch * (srcH - 1) + (srcW - 1); + src2 = src2 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); + src3 = src3 + srcPitch2 * ((srcH >> 1) - 1) + ((srcW >> 1) - 1); + srcDown = -srcPitch; + srcDown2 = -srcPitch2; + srcRight = -2; + srcRight2 = -1; + srcNext = -1; + break; + case RR_Rotate_270: + src1 = src1 + srcPitch * (srcW - 1); + src2 = src2 + srcPitch2 * ((srcW >> 1) - 1); + src3 = src3 + srcPitch2 * ((srcW >> 1) - 1); + srcDown = 1; + srcDown2 = 1; + srcRight = -srcPitch * 2; + srcRight2 = -srcPitch2; + srcNext = -srcPitch; + break; + } + + /* adjust for origin */ + src1 += top * srcDown + left * srcNext; + src2 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; + src3 += (top >> 1) * srcDown2 + (left >> 1) * srcRight2; + + if (id == FOURCC_I420) { + CARD8 *srct = src2; + src2 = src3; + src3 = srct; + } + + dst1 = dst; + + w >>= 1; + for (j = 0; j < h; j++) { + CARD32 *dst = (CARD32 *)dst1; + CARD8 *s1l = src1; + CARD8 *s1r = src1 + srcNext; + CARD8 *s2 = src2; + CARD8 *s3 = src3; + + for (i = 0; i < w; i++) { + *dst++ = *s1l | (*s1r << 16) | (*s3 << 8) | (*s2 << 24); + s1l += srcRight; + s1r += srcRight; + s2 += srcRight2; + s3 += srcRight2; + } + src1 += srcDown; + dst1 += dstPitch; + if (j & 1) { + src2 += srcDown2; + src3 += srcDown2; + } + } +} + +void +KXVPaintRegion (DrawablePtr pDraw, RegionPtr pRgn, Pixel fg) +{ + GCPtr pGC; + ChangeGCVal val[2]; + xRectangle *rects, *r; + BoxPtr pBox = REGION_RECTS (pRgn); + int nBox = REGION_NUM_RECTS (pRgn); + + rects = malloc(nBox * sizeof (xRectangle)); + if (!rects) + goto bail0; + r = rects; + while (nBox--) + { + r->x = pBox->x1 - pDraw->x; + r->y = pBox->y1 - pDraw->y; + r->width = pBox->x2 - pBox->x1; + r->height = pBox->y2 - pBox->y1; + r++; + pBox++; + } + + pGC = GetScratchGC (pDraw->depth, pDraw->pScreen); + if (!pGC) + goto bail1; + + val[0].val = fg; + val[1].val = IncludeInferiors; + ChangeGC (NullClient, pGC, GCForeground|GCSubwindowMode, val); + + ValidateGC (pDraw, pGC); + + (*pGC->ops->PolyFillRect) (pDraw, pGC, + REGION_NUM_RECTS (pRgn), rects); + + FreeScratchGC (pGC); +bail1: + free(rects); +bail0: + ; +} diff --git a/xorg-server/hw/vfb/InitOutput.c b/xorg-server/hw/vfb/InitOutput.c index 29857877e..30e68e5d3 100644 --- a/xorg-server/hw/vfb/InitOutput.c +++ b/xorg-server/hw/vfb/InitOutput.c @@ -1,973 +1,973 @@ -/* - -Copyright 1993, 1998 The Open Group - -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. - -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 OPEN GROUP 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 Open Group 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 Open Group. - -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#if defined(WIN32) -#include <X11/Xwinsock.h> -#endif -#include <stdio.h> -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/Xos.h> -#include "scrnintstr.h" -#include "servermd.h" -#define PSZ 8 -#include "fb.h" -#include "mibstore.h" -#include "colormapst.h" -#include "gcstruct.h" -#include "input.h" -#include "mipointer.h" -#include "micmap.h" -#include <sys/types.h> -#ifdef HAS_MMAP -#include <sys/mman.h> -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif -#endif /* HAS_MMAP */ -#include <sys/stat.h> -#include <errno.h> -#ifndef WIN32 -#include <sys/param.h> -#endif -#include <X11/XWDFile.h> -#ifdef HAS_SHM -#include <sys/ipc.h> -#include <sys/shm.h> -#endif /* HAS_SHM */ -#include "dix.h" -#include "miline.h" - -#define VFB_DEFAULT_WIDTH 1280 -#define VFB_DEFAULT_HEIGHT 1024 -#define VFB_DEFAULT_DEPTH 8 -#define VFB_DEFAULT_WHITEPIXEL 1 -#define VFB_DEFAULT_BLACKPIXEL 0 -#define VFB_DEFAULT_LINEBIAS 0 -#define XWD_WINDOW_NAME_LEN 60 - -typedef struct -{ - int width; - int paddedBytesWidth; - int paddedWidth; - int height; - int depth; - int bitsPerPixel; - int sizeInBytes; - int ncolors; - char *pfbMemory; - XWDColor *pXWDCmap; - XWDFileHeader *pXWDHeader; - Pixel blackPixel; - Pixel whitePixel; - unsigned int lineBias; - CloseScreenProcPtr closeScreen; - -#ifdef HAS_MMAP - int mmap_fd; - char mmap_file[MAXPATHLEN]; -#endif - -#ifdef HAS_SHM - int shmid; -#endif -} vfbScreenInfo, *vfbScreenInfoPtr; - -static int vfbNumScreens; -static vfbScreenInfo *vfbScreens; -static vfbScreenInfo defaultScreenInfo = { - .width = VFB_DEFAULT_WIDTH, - .height = VFB_DEFAULT_HEIGHT, - .depth = VFB_DEFAULT_DEPTH, - .blackPixel = VFB_DEFAULT_BLACKPIXEL, - .whitePixel = VFB_DEFAULT_WHITEPIXEL, - .lineBias = VFB_DEFAULT_LINEBIAS, -}; -static Bool vfbPixmapDepths[33]; -#ifdef HAS_MMAP -static char *pfbdir = NULL; -#endif -typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType; -static fbMemType fbmemtype = NORMAL_MEMORY_FB; -static char needswap = 0; -static Bool Render = TRUE; - -#define swapcopy16(_dst, _src) \ - if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \ - else _dst = _src; - -#define swapcopy32(_dst, _src) \ - if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \ - else _dst = _src; - - -static void -vfbInitializePixmapDepths(void) -{ - int i; - vfbPixmapDepths[1] = TRUE; /* always need bitmaps */ - for (i = 2; i <= 32; i++) - vfbPixmapDepths[i] = FALSE; -} - -static int -vfbBitsPerPixel(int depth) -{ - if (depth == 1) return 1; - else if (depth <= 8) return 8; - else if (depth <= 16) return 16; - else return 32; -} - -void -ddxGiveUp(void) -{ - int i; - - /* clean up the framebuffers */ - - switch (fbmemtype) - { -#ifdef HAS_MMAP - case MMAPPED_FILE_FB: - for (i = 0; i < vfbNumScreens; i++) - { - if (-1 == unlink(vfbScreens[i].mmap_file)) - { - perror("unlink"); - ErrorF("unlink %s failed, %s", - vfbScreens[i].mmap_file, strerror(errno)); - } - } - break; -#else /* HAS_MMAP */ - case MMAPPED_FILE_FB: - break; -#endif /* HAS_MMAP */ - -#ifdef HAS_SHM - case SHARED_MEMORY_FB: - for (i = 0; i < vfbNumScreens; i++) - { - if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader)) - { - perror("shmdt"); - ErrorF("shmdt failed, %s", strerror(errno)); - } - } - break; -#else /* HAS_SHM */ - case SHARED_MEMORY_FB: - break; -#endif /* HAS_SHM */ - - case NORMAL_MEMORY_FB: - for (i = 0; i < vfbNumScreens; i++) - { - Xfree(vfbScreens[i].pXWDHeader); - } - break; - } -} - -void -AbortDDX(void) -{ - ddxGiveUp(); -} - -#ifdef __APPLE__ -void -DarwinHandleGUI(int argc, char *argv[]) -{ -} -#endif - -void -OsVendorInit(void) -{ -} - -void -OsVendorFatalError(void) -{ -} - -#if defined(DDXBEFORERESET) -void ddxBeforeReset(void) -{ - return; -} -#endif - -void -ddxUseMsg(void) -{ - ErrorF("-screen scrn WxHxD set screen's width, height, depth\n"); - ErrorF("-pixdepths list-of-int support given pixmap depths\n"); - ErrorF("+/-render turn on/off RENDER extension support" - "(default on)\n"); - ErrorF("-linebias n adjust thin line pixelization\n"); - ErrorF("-blackpixel n pixel value for black\n"); - ErrorF("-whitepixel n pixel value for white\n"); - -#ifdef HAS_MMAP - ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n"); -#endif - -#ifdef HAS_SHM - ErrorF("-shmem put framebuffers in shared memory\n"); -#endif -} - -int -ddxProcessArgument(int argc, char *argv[], int i) -{ - static Bool firstTime = TRUE; - static int lastScreen = -1; - vfbScreenInfo *currentScreen; - - if (firstTime) - { - vfbInitializePixmapDepths(); - firstTime = FALSE; - } - - if (lastScreen == -1) - currentScreen = &defaultScreenInfo; - else - currentScreen = &vfbScreens[lastScreen]; - -#define CHECK_FOR_REQUIRED_ARGUMENTS(num) \ - if (((i + num) >= argc) || (!argv[i + num])) { \ - ErrorF("Required argument to %s not specified\n", argv[i]); \ - UseMsg(); \ - FatalError("Required argument to %s not specified\n", argv[i]); \ - } - - if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */ - { - int screenNum; - CHECK_FOR_REQUIRED_ARGUMENTS(2); - screenNum = atoi(argv[i+1]); - if (screenNum < 0) - { - ErrorF("Invalid screen number %d\n", screenNum); - UseMsg(); - FatalError("Invalid screen number %d passed to -screen\n", - screenNum); - } - - if (vfbNumScreens <= screenNum) - { - vfbScreens = xrealloc(vfbScreens, sizeof(*vfbScreens) * (screenNum + 1)); - if (!vfbScreens) - FatalError("Not enough memory for screen %d\n", screenNum); - for (; vfbNumScreens <= screenNum; ++vfbNumScreens) - vfbScreens[vfbNumScreens] = defaultScreenInfo; - } - - if (3 != sscanf(argv[i+2], "%dx%dx%d", - &vfbScreens[screenNum].width, - &vfbScreens[screenNum].height, - &vfbScreens[screenNum].depth)) - { - ErrorF("Invalid screen configuration %s\n", argv[i+2]); - UseMsg(); - FatalError("Invalid screen configuration %s for -screen %d\n", - argv[i+2], screenNum); - } - - lastScreen = screenNum; - return 3; - } - - if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */ - { - int depth, ret = 1; - - CHECK_FOR_REQUIRED_ARGUMENTS(1); - while ((++i < argc) && (depth = atoi(argv[i])) != 0) - { - if (depth < 0 || depth > 32) - { - ErrorF("Invalid pixmap depth %d\n", depth); - UseMsg(); - FatalError("Invalid pixmap depth %d passed to -pixdepths\n", - depth); - } - vfbPixmapDepths[depth] = TRUE; - ret++; - } - return ret; - } - - if (strcmp (argv[i], "+render") == 0) /* +render */ - { - Render = TRUE; - return 1; - } - - if (strcmp (argv[i], "-render") == 0) /* -render */ - { - Render = FALSE; -#ifdef COMPOSITE - noCompositeExtension = TRUE; -#endif - return 1; - } - - if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */ - { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - currentScreen->blackPixel = atoi(argv[++i]); - return 2; - } - - if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */ - { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - currentScreen->whitePixel = atoi(argv[++i]); - return 2; - } - - if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */ - { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - currentScreen->lineBias = atoi(argv[++i]); - return 2; - } - -#ifdef HAS_MMAP - if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */ - { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - pfbdir = argv[++i]; - fbmemtype = MMAPPED_FILE_FB; - return 2; - } -#endif /* HAS_MMAP */ - -#ifdef HAS_SHM - if (strcmp (argv[i], "-shmem") == 0) /* -shmem */ - { - fbmemtype = SHARED_MEMORY_FB; - return 1; - } -#endif - - return 0; -} - -static int cmapScrPrivateKeyIndex; -static DevPrivateKey cmapScrPrivateKey = &cmapScrPrivateKeyIndex; - -#define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey)) -#define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c)) - -static int -vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) -{ - /* By the time we are processing requests, we can guarantee that there - * is always a colormap installed */ - *pmaps = GetInstalledColormap(pScreen)->mid; - return (1); -} - - -static void -vfbInstallColormap(ColormapPtr pmap) -{ - ColormapPtr oldpmap = GetInstalledColormap(pmap->pScreen); - - if (pmap != oldpmap) - { - int entries; - XWDFileHeader *pXWDHeader; - XWDColor *pXWDCmap; - VisualPtr pVisual; - Pixel * ppix; - xrgb * prgb; - xColorItem *defs; - int i; - - if(oldpmap != (ColormapPtr)None) - WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); - /* Install pmap */ - SetInstalledColormap(pmap->pScreen, pmap); - WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); - - entries = pmap->pVisual->ColormapEntries; - pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader; - pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; - pVisual = pmap->pVisual; - - swapcopy32(pXWDHeader->visual_class, pVisual->class); - swapcopy32(pXWDHeader->red_mask, pVisual->redMask); - swapcopy32(pXWDHeader->green_mask, pVisual->greenMask); - swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask); - swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue); - swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries); - - ppix = (Pixel *)xalloc(entries * sizeof(Pixel)); - prgb = (xrgb *)xalloc(entries * sizeof(xrgb)); - defs = (xColorItem *)xalloc(entries * sizeof(xColorItem)); - - for (i = 0; i < entries; i++) ppix[i] = i; - /* XXX truecolor */ - QueryColors(pmap, entries, ppix, prgb); - - for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */ - defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */ - defs[i].red = prgb[i].red; - defs[i].green = prgb[i].green; - defs[i].blue = prgb[i].blue; - defs[i].flags = DoRed|DoGreen|DoBlue; - } - (*pmap->pScreen->StoreColors)(pmap, entries, defs); - - xfree(ppix); - xfree(prgb); - xfree(defs); - } -} - -static void -vfbUninstallColormap(ColormapPtr pmap) -{ - ColormapPtr curpmap = GetInstalledColormap(pmap->pScreen); - - if(pmap == curpmap) - { - if (pmap->mid != pmap->pScreen->defColormap) - { - dixLookupResourceByType((pointer *)&curpmap, - pmap->pScreen->defColormap, - RT_COLORMAP, serverClient, - DixInstallAccess); - (*pmap->pScreen->InstallColormap)(curpmap); - } - } -} - -static void -vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs) -{ - XWDColor *pXWDCmap; - int i; - - if (pmap != GetInstalledColormap(pmap->pScreen)) - { - return; - } - - pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; - - if ((pmap->pVisual->class | DynamicClass) == DirectColor) - { - return; - } - - for (i = 0; i < ndef; i++) - { - if (pdefs[i].flags & DoRed) - { - swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red); - } - if (pdefs[i].flags & DoGreen) - { - swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green); - } - if (pdefs[i].flags & DoBlue) - { - swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue); - } - } -} - -static Bool -vfbSaveScreen(ScreenPtr pScreen, int on) -{ - return TRUE; -} - -#ifdef HAS_MMAP - -/* this flushes any changes to the screens out to the mmapped file */ -static void -vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) -{ - int i; - - for (i = 0; i < vfbNumScreens; i++) - { -#ifdef MS_ASYNC - if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, - (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC)) -#else - /* silly NetBSD and who else? */ - if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, - (size_t)vfbScreens[i].sizeInBytes)) -#endif - { - perror("msync"); - ErrorF("msync failed, %s", strerror(errno)); - } - } -} - - -static void -vfbWakeupHandler(pointer blockData, int result, pointer pReadmask) -{ -} - - -static void -vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb) -{ -#define DUMMY_BUFFER_SIZE 65536 - char dummyBuffer[DUMMY_BUFFER_SIZE]; - int currentFileSize, writeThisTime; - - sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, (int) (pvfb - vfbScreens)); - if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666))) - { - perror("open"); - ErrorF("open %s failed, %s", pvfb->mmap_file, strerror(errno)); - return; - } - - /* Extend the file to be the proper size */ - - bzero(dummyBuffer, DUMMY_BUFFER_SIZE); - for (currentFileSize = 0; - currentFileSize < pvfb->sizeInBytes; - currentFileSize += writeThisTime) - { - writeThisTime = min(DUMMY_BUFFER_SIZE, - pvfb->sizeInBytes - currentFileSize); - if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime)) - { - perror("write"); - ErrorF("write %s failed, %s", pvfb->mmap_file, strerror(errno)); - return; - } - } - - /* try to mmap the file */ - - pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes, - PROT_READ|PROT_WRITE, - MAP_FILE|MAP_SHARED, - pvfb->mmap_fd, 0); - if (-1 == (long)pvfb->pXWDHeader) - { - perror("mmap"); - ErrorF("mmap %s failed, %s", pvfb->mmap_file, strerror(errno)); - pvfb->pXWDHeader = NULL; - return; - } - - if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler, - NULL)) - { - pvfb->pXWDHeader = NULL; - } -} -#endif /* HAS_MMAP */ - - -#ifdef HAS_SHM -static void -vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb) -{ - /* create the shared memory segment */ - - pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777); - if (pvfb->shmid < 0) - { - perror("shmget"); - ErrorF("shmget %d bytes failed, %s", pvfb->sizeInBytes, strerror(errno)); - return; - } - - /* try to attach it */ - - pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0); - if (-1 == (long)pvfb->pXWDHeader) - { - perror("shmat"); - ErrorF("shmat failed, %s", strerror(errno)); - pvfb->pXWDHeader = NULL; - return; - } - - ErrorF("screen %d shmid %d\n", (int) (pvfb - vfbScreens), pvfb->shmid); -} -#endif /* HAS_SHM */ - -static char * -vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb) -{ - if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */ - - pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height; - - /* Calculate how many entries in colormap. This is rather bogus, because - * the visuals haven't even been set up yet, but we need to know because we - * have to allocate space in the file for the colormap. The number 10 - * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c. - */ - - if (pvfb->depth <= 10) - { /* single index colormaps */ - pvfb->ncolors = 1 << pvfb->depth; - } - else - { /* decomposed colormaps */ - int nplanes_per_color_component = pvfb->depth / 3; - if (pvfb->depth % 3) nplanes_per_color_component++; - pvfb->ncolors = 1 << nplanes_per_color_component; - } - - /* add extra bytes for XWDFileHeader, window name, and colormap */ - - pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN + - pvfb->ncolors * SIZEOF(XWDColor); - - pvfb->pXWDHeader = NULL; - switch (fbmemtype) - { -#ifdef HAS_MMAP - case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break; -#else - case MMAPPED_FILE_FB: break; -#endif - -#ifdef HAS_SHM - case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break; -#else - case SHARED_MEMORY_FB: break; -#endif - - case NORMAL_MEMORY_FB: - pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes); - break; - } - - if (pvfb->pXWDHeader) - { - pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader - + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN); - pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors); - - return pvfb->pfbMemory; - } - else - return NULL; -} - - -static void -vfbWriteXWDFileHeader(ScreenPtr pScreen) -{ - vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; - XWDFileHeader *pXWDHeader = pvfb->pXWDHeader; - char hostname[XWD_WINDOW_NAME_LEN]; - unsigned long swaptest = 1; - int i; - - needswap = *(char *) &swaptest; - - pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader; - pXWDHeader->file_version = XWD_FILE_VERSION; - - pXWDHeader->pixmap_format = ZPixmap; - pXWDHeader->pixmap_depth = pvfb->depth; - pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height; - pXWDHeader->xoffset = 0; - pXWDHeader->byte_order = IMAGE_BYTE_ORDER; - pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER; -#ifndef INTERNAL_VS_EXTERNAL_PADDING - pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width; - pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT; - pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD; -#else - pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth; - pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO; - pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO; -#endif - pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel; - pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth; - pXWDHeader->ncolors = pvfb->ncolors; - - /* visual related fields are written when colormap is installed */ - - pXWDHeader->window_x = pXWDHeader->window_y = 0; - pXWDHeader->window_bdrwidth = 0; - - /* write xwd "window" name: Xvfb hostname:server.screen */ - - if (-1 == gethostname(hostname, sizeof(hostname))) - hostname[0] = 0; - else - hostname[XWD_WINDOW_NAME_LEN-1] = 0; - sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display, - pScreen->myNum); - - /* write colormap pixel slot values */ - - for (i = 0; i < pvfb->ncolors; i++) - { - pvfb->pXWDCmap[i].pixel = i; - } - - /* byte swap to most significant byte first */ - - if (needswap) - { - SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4); - for (i = 0; i < pvfb->ncolors; i++) - { - register char n; - swapl(&pvfb->pXWDCmap[i].pixel, n); - } - } -} - - -static Bool -vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y) -{ - return FALSE; -} - -static void -vfbCrossScreen (ScreenPtr pScreen, Bool entering) -{ -} - -static miPointerScreenFuncRec vfbPointerCursorFuncs = -{ - vfbCursorOffScreen, - vfbCrossScreen, - miPointerWarpCursor -}; - -static Bool -vfbCloseScreen(int index, ScreenPtr pScreen) -{ - vfbScreenInfoPtr pvfb = &vfbScreens[index]; - int i; - - pScreen->CloseScreen = pvfb->closeScreen; - - /* - * XXX probably lots of stuff to clean. For now, - * clear installed colormaps so that server reset works correctly. - */ - for (i = 0; i < screenInfo.numScreens; i++) - SetInstalledColormap(screenInfo.screens[i], NULL); - - return pScreen->CloseScreen(index, pScreen); -} - -static Bool -vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) -{ - vfbScreenInfoPtr pvfb = &vfbScreens[index]; - int dpix = monitorResolution, dpiy = monitorResolution; - int ret; - char *pbits; - - if (dpix == 0) - dpix = 100; - - if (dpiy == 0) - dpiy = 100; - - pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth); - pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth); - if (pvfb->bitsPerPixel >= 8 ) - pvfb->paddedWidth = pvfb->paddedBytesWidth / (pvfb->bitsPerPixel / 8); - else - pvfb->paddedWidth = pvfb->paddedBytesWidth * 8; - pbits = vfbAllocateFramebufferMemory(pvfb); - if (!pbits) return FALSE; - - switch (pvfb->depth) { - case 8: - miSetVisualTypesAndMasks (8, - ((1 << StaticGray) | - (1 << GrayScale) | - (1 << StaticColor) | - (1 << PseudoColor) | - (1 << TrueColor) | - (1 << DirectColor)), - 8, PseudoColor, 0, 0, 0); - break; - case 15: - miSetVisualTypesAndMasks (15, - ((1 << TrueColor) | - (1 << DirectColor)), - 8, TrueColor, 0x7c00, 0x03e0, 0x001f); - break; - case 16: - miSetVisualTypesAndMasks (16, - ((1 << TrueColor) | - (1 << DirectColor)), - 8, TrueColor, 0xf800, 0x07e0, 0x001f); - break; - case 24: - miSetVisualTypesAndMasks (24, - ((1 << TrueColor) | - (1 << DirectColor)), - 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff); - break; - case 30: - miSetVisualTypesAndMasks (30, - ((1 << TrueColor) | - (1 << DirectColor)), - 10, TrueColor, 0x3ff00000, 0x000ffc00, 0x000003ff); - break; - } - - miSetPixmapDepths (); - - ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height, - dpix, dpiy, pvfb->paddedWidth,pvfb->bitsPerPixel); - if (ret && Render) - fbPictureInit (pScreen, 0, 0); - - if (!ret) return FALSE; - - miInitializeBackingStore(pScreen); - - /* - * Circumvent the backing store that was just initialised. This amounts - * to a truely bizarre way of initialising SaveDoomedAreas and friends. - */ - - pScreen->InstallColormap = vfbInstallColormap; - pScreen->UninstallColormap = vfbUninstallColormap; - pScreen->ListInstalledColormaps = vfbListInstalledColormaps; - - pScreen->SaveScreen = vfbSaveScreen; - pScreen->StoreColors = vfbStoreColors; - - miDCInitialize(pScreen, &vfbPointerCursorFuncs); - - vfbWriteXWDFileHeader(pScreen); - - pScreen->blackPixel = pvfb->blackPixel; - pScreen->whitePixel = pvfb->whitePixel; - - ret = fbCreateDefColormap(pScreen); - - miSetZeroLineBias(pScreen, pvfb->lineBias); - - pvfb->closeScreen = pScreen->CloseScreen; - pScreen->CloseScreen = vfbCloseScreen; - - return ret; - -} /* end vfbScreenInit */ - - -void -InitOutput(ScreenInfo *screenInfo, int argc, char **argv) -{ - int i; - int NumFormats = 0; - - /* initialize pixmap formats */ - - /* must have a pixmap depth to match every screen depth */ - for (i = 0; i < vfbNumScreens; i++) - { - vfbPixmapDepths[vfbScreens[i].depth] = TRUE; - } - - /* RENDER needs a good set of pixmaps. */ - if (Render) { - vfbPixmapDepths[1] = TRUE; - vfbPixmapDepths[4] = TRUE; - vfbPixmapDepths[8] = TRUE; -#if 0 - vfbPixmapDepths[12] = TRUE; -#endif -/* vfbPixmapDepths[15] = TRUE; */ - vfbPixmapDepths[16] = TRUE; - vfbPixmapDepths[24] = TRUE; -#if 0 - vfbPixmapDepths[30] = TRUE; -#endif - vfbPixmapDepths[32] = TRUE; - } - - for (i = 1; i <= 32; i++) - { - if (vfbPixmapDepths[i]) - { - if (NumFormats >= MAXFORMATS) - FatalError ("MAXFORMATS is too small for this server\n"); - screenInfo->formats[NumFormats].depth = i; - screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i); - screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD; - NumFormats++; - } - } - - screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; - screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; - screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; - screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; - screenInfo->numPixmapFormats = NumFormats; - - /* initialize screens */ - - if (vfbNumScreens < 1) - { - vfbScreens = &defaultScreenInfo; - vfbNumScreens = 1; - } - for (i = 0; i < vfbNumScreens; i++) - { - if (-1 == AddScreen(vfbScreenInit, argc, argv)) - { - FatalError("Couldn't add screen %d", i); - } - } - -} /* end InitOutput */ +/* + +Copyright 1993, 1998 The Open Group + +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. + +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 OPEN GROUP 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 Open Group 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 Open Group. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#if defined(WIN32) +#include <X11/Xwinsock.h> +#endif +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xos.h> +#include "scrnintstr.h" +#include "servermd.h" +#define PSZ 8 +#include "fb.h" +#include "mibstore.h" +#include "colormapst.h" +#include "gcstruct.h" +#include "input.h" +#include "mipointer.h" +#include "micmap.h" +#include <sys/types.h> +#ifdef HAS_MMAP +#include <sys/mman.h> +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif +#endif /* HAS_MMAP */ +#include <sys/stat.h> +#include <errno.h> +#ifndef WIN32 +#include <sys/param.h> +#endif +#include <X11/XWDFile.h> +#ifdef HAS_SHM +#include <sys/ipc.h> +#include <sys/shm.h> +#endif /* HAS_SHM */ +#include "dix.h" +#include "miline.h" + +#define VFB_DEFAULT_WIDTH 1280 +#define VFB_DEFAULT_HEIGHT 1024 +#define VFB_DEFAULT_DEPTH 8 +#define VFB_DEFAULT_WHITEPIXEL 1 +#define VFB_DEFAULT_BLACKPIXEL 0 +#define VFB_DEFAULT_LINEBIAS 0 +#define XWD_WINDOW_NAME_LEN 60 + +typedef struct +{ + int width; + int paddedBytesWidth; + int paddedWidth; + int height; + int depth; + int bitsPerPixel; + int sizeInBytes; + int ncolors; + char *pfbMemory; + XWDColor *pXWDCmap; + XWDFileHeader *pXWDHeader; + Pixel blackPixel; + Pixel whitePixel; + unsigned int lineBias; + CloseScreenProcPtr closeScreen; + +#ifdef HAS_MMAP + int mmap_fd; + char mmap_file[MAXPATHLEN]; +#endif + +#ifdef HAS_SHM + int shmid; +#endif +} vfbScreenInfo, *vfbScreenInfoPtr; + +static int vfbNumScreens; +static vfbScreenInfo *vfbScreens; +static vfbScreenInfo defaultScreenInfo = { + .width = VFB_DEFAULT_WIDTH, + .height = VFB_DEFAULT_HEIGHT, + .depth = VFB_DEFAULT_DEPTH, + .blackPixel = VFB_DEFAULT_BLACKPIXEL, + .whitePixel = VFB_DEFAULT_WHITEPIXEL, + .lineBias = VFB_DEFAULT_LINEBIAS, +}; +static Bool vfbPixmapDepths[33]; +#ifdef HAS_MMAP +static char *pfbdir = NULL; +#endif +typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType; +static fbMemType fbmemtype = NORMAL_MEMORY_FB; +static char needswap = 0; +static Bool Render = TRUE; + +#define swapcopy16(_dst, _src) \ + if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \ + else _dst = _src; + +#define swapcopy32(_dst, _src) \ + if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \ + else _dst = _src; + + +static void +vfbInitializePixmapDepths(void) +{ + int i; + vfbPixmapDepths[1] = TRUE; /* always need bitmaps */ + for (i = 2; i <= 32; i++) + vfbPixmapDepths[i] = FALSE; +} + +static int +vfbBitsPerPixel(int depth) +{ + if (depth == 1) return 1; + else if (depth <= 8) return 8; + else if (depth <= 16) return 16; + else return 32; +} + +void +ddxGiveUp(void) +{ + int i; + + /* clean up the framebuffers */ + + switch (fbmemtype) + { +#ifdef HAS_MMAP + case MMAPPED_FILE_FB: + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == unlink(vfbScreens[i].mmap_file)) + { + perror("unlink"); + ErrorF("unlink %s failed, %s", + vfbScreens[i].mmap_file, strerror(errno)); + } + } + break; +#else /* HAS_MMAP */ + case MMAPPED_FILE_FB: + break; +#endif /* HAS_MMAP */ + +#ifdef HAS_SHM + case SHARED_MEMORY_FB: + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader)) + { + perror("shmdt"); + ErrorF("shmdt failed, %s", strerror(errno)); + } + } + break; +#else /* HAS_SHM */ + case SHARED_MEMORY_FB: + break; +#endif /* HAS_SHM */ + + case NORMAL_MEMORY_FB: + for (i = 0; i < vfbNumScreens; i++) + { + free(vfbScreens[i].pXWDHeader); + } + break; + } +} + +void +AbortDDX(void) +{ + ddxGiveUp(); +} + +#ifdef __APPLE__ +void +DarwinHandleGUI(int argc, char *argv[]) +{ +} +#endif + +void +OsVendorInit(void) +{ +} + +void +OsVendorFatalError(void) +{ +} + +#if defined(DDXBEFORERESET) +void ddxBeforeReset(void) +{ + return; +} +#endif + +void +ddxUseMsg(void) +{ + ErrorF("-screen scrn WxHxD set screen's width, height, depth\n"); + ErrorF("-pixdepths list-of-int support given pixmap depths\n"); + ErrorF("+/-render turn on/off RENDER extension support" + "(default on)\n"); + ErrorF("-linebias n adjust thin line pixelization\n"); + ErrorF("-blackpixel n pixel value for black\n"); + ErrorF("-whitepixel n pixel value for white\n"); + +#ifdef HAS_MMAP + ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n"); +#endif + +#ifdef HAS_SHM + ErrorF("-shmem put framebuffers in shared memory\n"); +#endif +} + +int +ddxProcessArgument(int argc, char *argv[], int i) +{ + static Bool firstTime = TRUE; + static int lastScreen = -1; + vfbScreenInfo *currentScreen; + + if (firstTime) + { + vfbInitializePixmapDepths(); + firstTime = FALSE; + } + + if (lastScreen == -1) + currentScreen = &defaultScreenInfo; + else + currentScreen = &vfbScreens[lastScreen]; + +#define CHECK_FOR_REQUIRED_ARGUMENTS(num) \ + if (((i + num) >= argc) || (!argv[i + num])) { \ + ErrorF("Required argument to %s not specified\n", argv[i]); \ + UseMsg(); \ + FatalError("Required argument to %s not specified\n", argv[i]); \ + } + + if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */ + { + int screenNum; + CHECK_FOR_REQUIRED_ARGUMENTS(2); + screenNum = atoi(argv[i+1]); + if (screenNum < 0) + { + ErrorF("Invalid screen number %d\n", screenNum); + UseMsg(); + FatalError("Invalid screen number %d passed to -screen\n", + screenNum); + } + + if (vfbNumScreens <= screenNum) + { + vfbScreens = realloc(vfbScreens, sizeof(*vfbScreens) * (screenNum + 1)); + if (!vfbScreens) + FatalError("Not enough memory for screen %d\n", screenNum); + for (; vfbNumScreens <= screenNum; ++vfbNumScreens) + vfbScreens[vfbNumScreens] = defaultScreenInfo; + } + + if (3 != sscanf(argv[i+2], "%dx%dx%d", + &vfbScreens[screenNum].width, + &vfbScreens[screenNum].height, + &vfbScreens[screenNum].depth)) + { + ErrorF("Invalid screen configuration %s\n", argv[i+2]); + UseMsg(); + FatalError("Invalid screen configuration %s for -screen %d\n", + argv[i+2], screenNum); + } + + lastScreen = screenNum; + return 3; + } + + if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */ + { + int depth, ret = 1; + + CHECK_FOR_REQUIRED_ARGUMENTS(1); + while ((++i < argc) && (depth = atoi(argv[i])) != 0) + { + if (depth < 0 || depth > 32) + { + ErrorF("Invalid pixmap depth %d\n", depth); + UseMsg(); + FatalError("Invalid pixmap depth %d passed to -pixdepths\n", + depth); + } + vfbPixmapDepths[depth] = TRUE; + ret++; + } + return ret; + } + + if (strcmp (argv[i], "+render") == 0) /* +render */ + { + Render = TRUE; + return 1; + } + + if (strcmp (argv[i], "-render") == 0) /* -render */ + { + Render = FALSE; +#ifdef COMPOSITE + noCompositeExtension = TRUE; +#endif + return 1; + } + + if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */ + { + CHECK_FOR_REQUIRED_ARGUMENTS(1); + currentScreen->blackPixel = atoi(argv[++i]); + return 2; + } + + if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */ + { + CHECK_FOR_REQUIRED_ARGUMENTS(1); + currentScreen->whitePixel = atoi(argv[++i]); + return 2; + } + + if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */ + { + CHECK_FOR_REQUIRED_ARGUMENTS(1); + currentScreen->lineBias = atoi(argv[++i]); + return 2; + } + +#ifdef HAS_MMAP + if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */ + { + CHECK_FOR_REQUIRED_ARGUMENTS(1); + pfbdir = argv[++i]; + fbmemtype = MMAPPED_FILE_FB; + return 2; + } +#endif /* HAS_MMAP */ + +#ifdef HAS_SHM + if (strcmp (argv[i], "-shmem") == 0) /* -shmem */ + { + fbmemtype = SHARED_MEMORY_FB; + return 1; + } +#endif + + return 0; +} + +static int cmapScrPrivateKeyIndex; +static DevPrivateKey cmapScrPrivateKey = &cmapScrPrivateKeyIndex; + +#define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey)) +#define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c)) + +static int +vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) +{ + /* By the time we are processing requests, we can guarantee that there + * is always a colormap installed */ + *pmaps = GetInstalledColormap(pScreen)->mid; + return (1); +} + + +static void +vfbInstallColormap(ColormapPtr pmap) +{ + ColormapPtr oldpmap = GetInstalledColormap(pmap->pScreen); + + if (pmap != oldpmap) + { + int entries; + XWDFileHeader *pXWDHeader; + XWDColor *pXWDCmap; + VisualPtr pVisual; + Pixel * ppix; + xrgb * prgb; + xColorItem *defs; + int i; + + if(oldpmap != (ColormapPtr)None) + WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); + /* Install pmap */ + SetInstalledColormap(pmap->pScreen, pmap); + WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); + + entries = pmap->pVisual->ColormapEntries; + pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader; + pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; + pVisual = pmap->pVisual; + + swapcopy32(pXWDHeader->visual_class, pVisual->class); + swapcopy32(pXWDHeader->red_mask, pVisual->redMask); + swapcopy32(pXWDHeader->green_mask, pVisual->greenMask); + swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask); + swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue); + swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries); + + ppix = (Pixel *)malloc(entries * sizeof(Pixel)); + prgb = (xrgb *)malloc(entries * sizeof(xrgb)); + defs = (xColorItem *)malloc(entries * sizeof(xColorItem)); + + for (i = 0; i < entries; i++) ppix[i] = i; + /* XXX truecolor */ + QueryColors(pmap, entries, ppix, prgb, serverClient); + + for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */ + defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */ + defs[i].red = prgb[i].red; + defs[i].green = prgb[i].green; + defs[i].blue = prgb[i].blue; + defs[i].flags = DoRed|DoGreen|DoBlue; + } + (*pmap->pScreen->StoreColors)(pmap, entries, defs); + + free(ppix); + free(prgb); + free(defs); + } +} + +static void +vfbUninstallColormap(ColormapPtr pmap) +{ + ColormapPtr curpmap = GetInstalledColormap(pmap->pScreen); + + if(pmap == curpmap) + { + if (pmap->mid != pmap->pScreen->defColormap) + { + dixLookupResourceByType((pointer *)&curpmap, + pmap->pScreen->defColormap, + RT_COLORMAP, serverClient, + DixInstallAccess); + (*pmap->pScreen->InstallColormap)(curpmap); + } + } +} + +static void +vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs) +{ + XWDColor *pXWDCmap; + int i; + + if (pmap != GetInstalledColormap(pmap->pScreen)) + { + return; + } + + pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap; + + if ((pmap->pVisual->class | DynamicClass) == DirectColor) + { + return; + } + + for (i = 0; i < ndef; i++) + { + if (pdefs[i].flags & DoRed) + { + swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red); + } + if (pdefs[i].flags & DoGreen) + { + swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green); + } + if (pdefs[i].flags & DoBlue) + { + swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue); + } + } +} + +static Bool +vfbSaveScreen(ScreenPtr pScreen, int on) +{ + return TRUE; +} + +#ifdef HAS_MMAP + +/* this flushes any changes to the screens out to the mmapped file */ +static void +vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +{ + int i; + + for (i = 0; i < vfbNumScreens; i++) + { +#ifdef MS_ASYNC + if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, + (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC)) +#else + /* silly NetBSD and who else? */ + if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader, + (size_t)vfbScreens[i].sizeInBytes)) +#endif + { + perror("msync"); + ErrorF("msync failed, %s", strerror(errno)); + } + } +} + + +static void +vfbWakeupHandler(pointer blockData, int result, pointer pReadmask) +{ +} + + +static void +vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb) +{ +#define DUMMY_BUFFER_SIZE 65536 + char dummyBuffer[DUMMY_BUFFER_SIZE]; + int currentFileSize, writeThisTime; + + sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, (int) (pvfb - vfbScreens)); + if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666))) + { + perror("open"); + ErrorF("open %s failed, %s", pvfb->mmap_file, strerror(errno)); + return; + } + + /* Extend the file to be the proper size */ + + bzero(dummyBuffer, DUMMY_BUFFER_SIZE); + for (currentFileSize = 0; + currentFileSize < pvfb->sizeInBytes; + currentFileSize += writeThisTime) + { + writeThisTime = min(DUMMY_BUFFER_SIZE, + pvfb->sizeInBytes - currentFileSize); + if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime)) + { + perror("write"); + ErrorF("write %s failed, %s", pvfb->mmap_file, strerror(errno)); + return; + } + } + + /* try to mmap the file */ + + pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes, + PROT_READ|PROT_WRITE, + MAP_FILE|MAP_SHARED, + pvfb->mmap_fd, 0); + if (-1 == (long)pvfb->pXWDHeader) + { + perror("mmap"); + ErrorF("mmap %s failed, %s", pvfb->mmap_file, strerror(errno)); + pvfb->pXWDHeader = NULL; + return; + } + + if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler, + NULL)) + { + pvfb->pXWDHeader = NULL; + } +} +#endif /* HAS_MMAP */ + + +#ifdef HAS_SHM +static void +vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb) +{ + /* create the shared memory segment */ + + pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777); + if (pvfb->shmid < 0) + { + perror("shmget"); + ErrorF("shmget %d bytes failed, %s", pvfb->sizeInBytes, strerror(errno)); + return; + } + + /* try to attach it */ + + pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0); + if (-1 == (long)pvfb->pXWDHeader) + { + perror("shmat"); + ErrorF("shmat failed, %s", strerror(errno)); + pvfb->pXWDHeader = NULL; + return; + } + + ErrorF("screen %d shmid %d\n", (int) (pvfb - vfbScreens), pvfb->shmid); +} +#endif /* HAS_SHM */ + +static char * +vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb) +{ + if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */ + + pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height; + + /* Calculate how many entries in colormap. This is rather bogus, because + * the visuals haven't even been set up yet, but we need to know because we + * have to allocate space in the file for the colormap. The number 10 + * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c. + */ + + if (pvfb->depth <= 10) + { /* single index colormaps */ + pvfb->ncolors = 1 << pvfb->depth; + } + else + { /* decomposed colormaps */ + int nplanes_per_color_component = pvfb->depth / 3; + if (pvfb->depth % 3) nplanes_per_color_component++; + pvfb->ncolors = 1 << nplanes_per_color_component; + } + + /* add extra bytes for XWDFileHeader, window name, and colormap */ + + pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN + + pvfb->ncolors * SIZEOF(XWDColor); + + pvfb->pXWDHeader = NULL; + switch (fbmemtype) + { +#ifdef HAS_MMAP + case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break; +#else + case MMAPPED_FILE_FB: break; +#endif + +#ifdef HAS_SHM + case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break; +#else + case SHARED_MEMORY_FB: break; +#endif + + case NORMAL_MEMORY_FB: + pvfb->pXWDHeader = (XWDFileHeader *)malloc(pvfb->sizeInBytes); + break; + } + + if (pvfb->pXWDHeader) + { + pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader + + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN); + pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors); + + return pvfb->pfbMemory; + } + else + return NULL; +} + + +static void +vfbWriteXWDFileHeader(ScreenPtr pScreen) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; + XWDFileHeader *pXWDHeader = pvfb->pXWDHeader; + char hostname[XWD_WINDOW_NAME_LEN]; + unsigned long swaptest = 1; + int i; + + needswap = *(char *) &swaptest; + + pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader; + pXWDHeader->file_version = XWD_FILE_VERSION; + + pXWDHeader->pixmap_format = ZPixmap; + pXWDHeader->pixmap_depth = pvfb->depth; + pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height; + pXWDHeader->xoffset = 0; + pXWDHeader->byte_order = IMAGE_BYTE_ORDER; + pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER; +#ifndef INTERNAL_VS_EXTERNAL_PADDING + pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width; + pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT; + pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD; +#else + pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth; + pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO; + pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO; +#endif + pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel; + pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth; + pXWDHeader->ncolors = pvfb->ncolors; + + /* visual related fields are written when colormap is installed */ + + pXWDHeader->window_x = pXWDHeader->window_y = 0; + pXWDHeader->window_bdrwidth = 0; + + /* write xwd "window" name: Xvfb hostname:server.screen */ + + if (-1 == gethostname(hostname, sizeof(hostname))) + hostname[0] = 0; + else + hostname[XWD_WINDOW_NAME_LEN-1] = 0; + sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display, + pScreen->myNum); + + /* write colormap pixel slot values */ + + for (i = 0; i < pvfb->ncolors; i++) + { + pvfb->pXWDCmap[i].pixel = i; + } + + /* byte swap to most significant byte first */ + + if (needswap) + { + SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4); + for (i = 0; i < pvfb->ncolors; i++) + { + register char n; + swapl(&pvfb->pXWDCmap[i].pixel, n); + } + } +} + + +static Bool +vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y) +{ + return FALSE; +} + +static void +vfbCrossScreen (ScreenPtr pScreen, Bool entering) +{ +} + +static miPointerScreenFuncRec vfbPointerCursorFuncs = +{ + vfbCursorOffScreen, + vfbCrossScreen, + miPointerWarpCursor +}; + +static Bool +vfbCloseScreen(int index, ScreenPtr pScreen) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[index]; + int i; + + pScreen->CloseScreen = pvfb->closeScreen; + + /* + * XXX probably lots of stuff to clean. For now, + * clear installed colormaps so that server reset works correctly. + */ + for (i = 0; i < screenInfo.numScreens; i++) + SetInstalledColormap(screenInfo.screens[i], NULL); + + return pScreen->CloseScreen(index, pScreen); +} + +static Bool +vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[index]; + int dpix = monitorResolution, dpiy = monitorResolution; + int ret; + char *pbits; + + if (dpix == 0) + dpix = 100; + + if (dpiy == 0) + dpiy = 100; + + pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth); + pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth); + if (pvfb->bitsPerPixel >= 8 ) + pvfb->paddedWidth = pvfb->paddedBytesWidth / (pvfb->bitsPerPixel / 8); + else + pvfb->paddedWidth = pvfb->paddedBytesWidth * 8; + pbits = vfbAllocateFramebufferMemory(pvfb); + if (!pbits) return FALSE; + + switch (pvfb->depth) { + case 8: + miSetVisualTypesAndMasks (8, + ((1 << StaticGray) | + (1 << GrayScale) | + (1 << StaticColor) | + (1 << PseudoColor) | + (1 << TrueColor) | + (1 << DirectColor)), + 8, PseudoColor, 0, 0, 0); + break; + case 15: + miSetVisualTypesAndMasks (15, + ((1 << TrueColor) | + (1 << DirectColor)), + 8, TrueColor, 0x7c00, 0x03e0, 0x001f); + break; + case 16: + miSetVisualTypesAndMasks (16, + ((1 << TrueColor) | + (1 << DirectColor)), + 8, TrueColor, 0xf800, 0x07e0, 0x001f); + break; + case 24: + miSetVisualTypesAndMasks (24, + ((1 << TrueColor) | + (1 << DirectColor)), + 8, TrueColor, 0xff0000, 0x00ff00, 0x0000ff); + break; + case 30: + miSetVisualTypesAndMasks (30, + ((1 << TrueColor) | + (1 << DirectColor)), + 10, TrueColor, 0x3ff00000, 0x000ffc00, 0x000003ff); + break; + } + + miSetPixmapDepths (); + + ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height, + dpix, dpiy, pvfb->paddedWidth,pvfb->bitsPerPixel); + if (ret && Render) + fbPictureInit (pScreen, 0, 0); + + if (!ret) return FALSE; + + miInitializeBackingStore(pScreen); + + /* + * Circumvent the backing store that was just initialised. This amounts + * to a truely bizarre way of initialising SaveDoomedAreas and friends. + */ + + pScreen->InstallColormap = vfbInstallColormap; + pScreen->UninstallColormap = vfbUninstallColormap; + pScreen->ListInstalledColormaps = vfbListInstalledColormaps; + + pScreen->SaveScreen = vfbSaveScreen; + pScreen->StoreColors = vfbStoreColors; + + miDCInitialize(pScreen, &vfbPointerCursorFuncs); + + vfbWriteXWDFileHeader(pScreen); + + pScreen->blackPixel = pvfb->blackPixel; + pScreen->whitePixel = pvfb->whitePixel; + + ret = fbCreateDefColormap(pScreen); + + miSetZeroLineBias(pScreen, pvfb->lineBias); + + pvfb->closeScreen = pScreen->CloseScreen; + pScreen->CloseScreen = vfbCloseScreen; + + return ret; + +} /* end vfbScreenInit */ + + +void +InitOutput(ScreenInfo *screenInfo, int argc, char **argv) +{ + int i; + int NumFormats = 0; + + /* initialize pixmap formats */ + + /* must have a pixmap depth to match every screen depth */ + for (i = 0; i < vfbNumScreens; i++) + { + vfbPixmapDepths[vfbScreens[i].depth] = TRUE; + } + + /* RENDER needs a good set of pixmaps. */ + if (Render) { + vfbPixmapDepths[1] = TRUE; + vfbPixmapDepths[4] = TRUE; + vfbPixmapDepths[8] = TRUE; +#if 0 + vfbPixmapDepths[12] = TRUE; +#endif +/* vfbPixmapDepths[15] = TRUE; */ + vfbPixmapDepths[16] = TRUE; + vfbPixmapDepths[24] = TRUE; +#if 0 + vfbPixmapDepths[30] = TRUE; +#endif + vfbPixmapDepths[32] = TRUE; + } + + for (i = 1; i <= 32; i++) + { + if (vfbPixmapDepths[i]) + { + if (NumFormats >= MAXFORMATS) + FatalError ("MAXFORMATS is too small for this server\n"); + screenInfo->formats[NumFormats].depth = i; + screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i); + screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD; + NumFormats++; + } + } + + screenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + screenInfo->numPixmapFormats = NumFormats; + + /* initialize screens */ + + if (vfbNumScreens < 1) + { + vfbScreens = &defaultScreenInfo; + vfbNumScreens = 1; + } + for (i = 0; i < vfbNumScreens; i++) + { + if (-1 == AddScreen(vfbScreenInit, argc, argv)) + { + FatalError("Couldn't add screen %d", i); + } + } + +} /* end InitOutput */ 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 <xorg-config.h> -#elif HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <pciaccess.h> - -#include "xf86str.h" -#include "xf86Opt.h" -#include <X11/Xfuncproto.h> -#include <stdarg.h> -#ifdef RANDR -#include <X11/extensions/randr.h> -#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 <xorg-config.h> +#elif HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <pciaccess.h> + +#include "xf86str.h" +#include "xf86Opt.h" +#include <X11/Xfuncproto.h> +#include <stdarg.h> +#ifdef RANDR +#include <X11/extensions/randr.h> +#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 <dawes@XFree86.Org>. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#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 <sys/visual_io.h> -# include <ctype.h> -#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 <dawes@XFree86.Org>. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#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 <sys/visual_io.h> +# include <ctype.h> +#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 <xorg-config.h> -#endif - -#include <ctype.h> -#include <stdlib.h> -#include <unistd.h> -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <X11/X.h> +#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 <hohndel@XFree86.Org> - * David Dawes <dawes@XFree86.Org> - * Marc La France <tsi@XFree86.Org> - * Egbert Eich <eich@XFree86.Org> - * ... and others - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#ifdef XF86DRI -#include <sys/types.h> -#include <grp.h> -#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("<default pointer>"); - 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("<default pointer>"); - 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("<default keyboard>"); - 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 = "<default monitor>"; - 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<ExtensionName>" */ - 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 <hohndel@XFree86.Org> + * David Dawes <dawes@XFree86.Org> + * Marc La France <tsi@XFree86.Org> + * Egbert Eich <eich@XFree86.Org> + * ... and others + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifdef XF86DRI +#include <sys/types.h> +#include <grp.h> +#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("<default pointer>"); + 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("<default pointer>"); + 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("<default keyboard>"); + 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 = "<default monitor>"; + 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<ExtensionName>" */ + 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 <xorg-config.h> -#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; i<sizeof(depths)/sizeof(depths[0]); i++) - { - XF86ConfDisplayPtr display; - - display = calloc(1, sizeof(XF86ConfDisplayRec)); - display->disp_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 "<i>"; - case OPTV_STRING: - return "<str>"; - case OPTV_ANYSTR: - return "[<str>]"; - case OPTV_REAL: - return "<f>"; - case OPTV_BOOLEAN: - return "[<bool>]"; - case OPTV_FREQ: - return "<freq>"; - 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: <i>: integer, <f>: float, " - "<bool>: \"True\"/\"False\",\n" - " ### <string>: \"String\", <freq>: \"<f> 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 && displaySizeLen<displaySizeMaxLen) { - if (ptr->mon_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; n<xf86Screens[l]->numEntities; 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 <xorg-config.h> +#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; i<sizeof(depths)/sizeof(depths[0]); i++) + { + XF86ConfDisplayPtr display; + + display = calloc(1, sizeof(XF86ConfDisplayRec)); + display->disp_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 "<i>"; + case OPTV_STRING: + return "<str>"; + case OPTV_ANYSTR: + return "[<str>]"; + case OPTV_REAL: + return "<f>"; + case OPTV_BOOLEAN: + return "[<bool>]"; + case OPTV_FREQ: + return "<freq>"; + 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: <i>: integer, <f>: float, " + "<bool>: \"True\"/\"False\",\n" + " ### <string>: \"String\", <freq>: \"<f> 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 && displaySizeLen<displaySizeMaxLen) { + if (ptr->mon_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; n<xf86Screens[l]->numEntities; 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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xmd.h> -#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 <X11/extensions/XIproto.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xmd.h> +#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 <X11/extensions/XIproto.h> +#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 <xorg-config.h> -#endif - -#include "xf86.h" -#include "xf86str.h" -#include "xf86Priv.h" -#include "dgaproc.h" -#include <X11/extensions/xf86dgaproto.h> -#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 <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86str.h" +#include "xf86Priv.h" +#include "dgaproc.h" +#include <X11/extensions/xf86dgaproto.h> +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include "os.h" -#include "globals.h" -#include "xf86.h" -#include "xf86Priv.h" -#ifdef DPMSExtension -#include <X11/extensions/dpmsconst.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "globals.h" +#include "xf86.h" +#include "xf86Priv.h" +#ifdef DPMSExtension +#include <X11/extensions/dpmsconst.h> +#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 <hohndel@XFree86.Org> - * David Dawes <dawes@XFree86.Org> - * ... and others - * - * This file includes the helper functions that the server provides for - * different drivers. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <pciaccess.h> -#include "Pci.h" - -#include <X11/X.h> -#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 <sys/resource.h> -#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; i<xf86NumScreens; i++) { - xf86RegisteredPropertiesTable[i] = NULL; - } - } - - DebugF("xf86RegisteredPropertiesTable %p\n", - (void *)xf86RegisteredPropertiesTable); - DebugF("xf86RegisteredPropertiesTable[%d] %p\n", - ScrnIndex, (void *)xf86RegisteredPropertiesTable[ScrnIndex]); - - if (!existing) { - if ( xf86RegisteredPropertiesTable[ScrnIndex] == NULL) { - xf86RegisteredPropertiesTable[ScrnIndex] = pNewProp; - } else { - pRegProp = xf86RegisteredPropertiesTable[ScrnIndex]; - while (pRegProp->next != 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 <hohndel@XFree86.Org> + * David Dawes <dawes@XFree86.Org> + * ... and others + * + * This file includes the helper functions that the server provides for + * different drivers. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <pciaccess.h> +#include "Pci.h" + +#include <X11/X.h> +#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 <sys/resource.h> +#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; i<xf86NumScreens; i++) { + xf86RegisteredPropertiesTable[i] = NULL; + } + } + + DebugF("xf86RegisteredPropertiesTable %p\n", + (void *)xf86RegisteredPropertiesTable); + DebugF("xf86RegisteredPropertiesTable[%d] %p\n", + ScrnIndex, (void *)xf86RegisteredPropertiesTable[ScrnIndex]); + + if (!existing) { + if ( xf86RegisteredPropertiesTable[ScrnIndex] == NULL) { + xf86RegisteredPropertiesTable[ScrnIndex] = pNewProp; + } else { + pRegProp = xf86RegisteredPropertiesTable[ScrnIndex]; + while (pRegProp->next != 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 <xorg-config.h> -#endif - -#include <stdlib.h> -#include <errno.h> - -#undef HAS_UTSNAME -#if !defined(WIN32) -#define HAS_UTSNAME 1 -#include <sys/utsname.h> -#endif - -#include <X11/X.h> -#include <X11/Xmd.h> -#include <X11/Xproto.h> -#include <X11/Xatom.h> -#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 <X11/extensions/XI.h> -#include <X11/extensions/XIproto.h> -#include "xf86DDC.h" -#include "xf86Xinput.h" -#include "xf86InPriv.h" -#include "picturestr.h" - -#include "xf86VGAarbiter.h" -#include "globals.h" - -#ifdef DPMSExtension -#include <X11/extensions/dpmsconst.h> -#include "dpmsproc.h" -#endif - -#include <pciaccess.h> -#include "Pci.h" -#include "xf86Bus.h" - -#include <hotplug.h> - -/* 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 <xorg-config.h> +#endif + +#include <stdlib.h> +#include <errno.h> + +#undef HAS_UTSNAME +#if !defined(WIN32) +#define HAS_UTSNAME 1 +#include <sys/utsname.h> +#endif + +#include <X11/X.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include <X11/Xatom.h> +#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 <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "xf86DDC.h" +#include "xf86Xinput.h" +#include "xf86InPriv.h" +#include "picturestr.h" + +#include "xf86VGAarbiter.h" +#include "globals.h" + +#ifdef DPMSExtension +#include <X11/extensions/dpmsconst.h> +#include "dpmsproc.h" +#endif + +#include <pciaccess.h> +#include "Pci.h" +#include "xf86Bus.h" + +#include <hotplug.h> + +/* 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 <hohndel@XFree86.Org> - * David Dawes <dawes@XFree86.Org> - * Marc La France <tsi@XFree86.Org> - * ... and others - * - * This file includes helper functions for mode related things. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <X11/X.h> -#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 <hohndel@XFree86.Org> + * David Dawes <dawes@XFree86.Org> + * Marc La France <tsi@XFree86.Org> + * ... and others + * + * This file includes helper functions for mode related things. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <X11/X.h> +#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 <dawes@xfree86.org> - * - * This file includes public option handling functions. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <stdlib.h> -#include <ctype.h> -#include <X11/X.h> -#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 <dawes@xfree86.org> + * + * This file includes public option handling functions. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <stdlib.h> +#include <ctype.h> +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include "os.h" -#include "globals.h" -#include "xf86.h" -#include "xf86str.h" -#include "xf86Priv.h" -#include "xf86DDC.h" -#include "mipointer.h" -#include <randrstr.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include "os.h" +#include "globals.h" +#include "xf86.h" +#include "xf86str.h" +#include "xf86Priv.h" +#include "xf86DDC.h" +#include "mipointer.h" +#include <randrstr.h> +#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 <ctype.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <X11/X.h> -#include <X11/Xmd.h> -#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 "<int>"; - case OPTV_STRING: - return "<str>"; - case OPTV_ANYSTR: - return "<str>"; - case OPTV_REAL: - return "<real>"; - case OPTV_BOOLEAN: - return "<bool>"; - case OPTV_FREQ: - return "<freq>"; - default: - return "<undef>"; - } -} - -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 <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <X11/X.h> +#include <X11/Xmd.h> +#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 "<int>"; + case OPTV_STRING: + return "<str>"; + case OPTV_ANYSTR: + return "<str>"; + case OPTV_REAL: + return "<real>"; + case OPTV_BOOLEAN: + return "<bool>"; + case OPTV_FREQ: + return "<freq>"; + default: + return "<undef>"; + } +} + +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 <xorg-config.h> -#endif - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#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. <Lepied@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 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 <xorg-config.h> -#endif - -#include <X11/Xfuncproto.h> -#include <X11/Xmd.h> -#include <X11/extensions/XI.h> -#include <X11/extensions/XIproto.h> -#include <X11/Xatom.h> -#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 <X11/extensions/dpmsconst.h> -#include "dpmsproc.h" -#endif - -#include "exevents.h" /* AddInputDevice */ -#include "exglobals.h" -#include "eventstr.h" - -#include <string.h> /* InputClassMatches */ -#ifdef HAVE_FNMATCH_H -#include <fnmatch.h> -#endif - -#include "extnsionst.h" - -#include "windowstr.h" /* screenIsSaved */ - -#include <stdarg.h> -#include <stdint.h> /* for int64_t */ - -#include <X11/Xpoll.h> - -#include "mi.h" - -#include <ptrveloc.h> /* dix pointer acceleration */ -#include <xserver-properties.h> - -#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. <Lepied@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 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 <xorg-config.h> +#endif + +#include <X11/Xfuncproto.h> +#include <X11/Xmd.h> +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include <X11/Xatom.h> +#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 <X11/extensions/dpmsconst.h> +#include "dpmsproc.h" +#endif + +#include "exevents.h" /* AddInputDevice */ +#include "exglobals.h" +#include "eventstr.h" + +#include <string.h> /* InputClassMatches */ +#ifdef HAVE_FNMATCH_H +#include <fnmatch.h> +#endif + +#include "extnsionst.h" + +#include "windowstr.h" /* screenIsSaved */ + +#include <stdarg.h> +#include <stdint.h> /* for int64_t */ + +#include <X11/Xpoll.h> + +#include "mi.h" + +#include <ptrveloc.h> /* dix pointer acceleration */ +#include <xserver-properties.h> + +#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 <xorg-config.h> -#endif - -#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) -#include <math.h> -#else -#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ -#include <math.h> -#undef _XOPEN_SOURCE -#endif - -#include <X11/X.h> -#include "misc.h" -#include <X11/Xproto.h> -#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 <X11/extensions/xf86dgaproto.h> -#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 <xorg-config.h> +#endif + +#if defined(_XOPEN_SOURCE) || defined(sun) && defined(__SVR4) +#include <math.h> +#else +#define _XOPEN_SOURCE /* to get prototype for pow on some systems */ +#include <math.h> +#undef _XOPEN_SOURCE +#endif + +#include <X11/X.h> +#include "misc.h" +#include <X11/Xproto.h> +#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 <X11/extensions/xf86dgaproto.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <ctype.h> -#include <stdlib.h> -#include <unistd.h> -#include <X11/X.h> -#include <pciaccess.h> -#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 <xorg-config.h> +#endif + +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <X11/X.h> +#include <pciaccess.h> +#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 <xorg-config.h> -#endif - -#include <ctype.h> -#include <stdio.h> -#include <unistd.h> -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <ctype.h> +#include <stdio.h> +#include <unistd.h> +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#include <X11/Xproto.h> -#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 <X11/extensions/Xv.h> -#include <X11/extensions/Xvproto.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/Xproto.h> +#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 <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#include <X11/Xproto.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/Xproto.h> +#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 <xorg-config.h> -#endif - -#include <misc.h> -#include <xf86.h> -#include <xf86_OSproc.h> -#include <xf86_OSlib.h> -#include <xf86Xinput.h> -#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 <xorg-config.h> +#endif + +#include <misc.h> +#include <xf86.h> +#include <xf86_OSproc.h> +#include <xf86_OSlib.h> +#include <xf86Xinput.h> +#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 <Egbert.Eich@Physik.TU-Darmstadt.DE> - */ - -/* - * 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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#include "xf86DDC.h" -#include <string.h> - -#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 (ptr<end) { - int i; - head_ptr = ptr; - for (i=0;i<8;i++){ - if (header[i] != *(head_ptr++)) break; - if (head_ptr == end) head_ptr = block; - } - if (i==8) break; - ptr++; - } - if (ptr == end) return (NULL); - return (ptr); -} - -static unsigned char * -resort(unsigned char *s_block) -{ - unsigned char *d_new, *d_ptr, *d_end, *s_ptr, *s_end; - unsigned char tmp; - - s_end = s_block + EDID1_LEN; - d_new = xalloc(EDID1_LEN); - if (!d_new) return NULL; - d_end = d_new + EDID1_LEN; - - s_ptr = find_header(s_block); - if (!s_ptr) return NULL; - for (d_ptr=d_new;d_ptr<d_end;d_ptr++){ - tmp = *(s_ptr++); - *d_ptr = tmp; - if (s_ptr == s_end) s_ptr = s_block; - } - xfree(s_block); - return (d_new); -} - -static int -DDC_checksum(unsigned char *block, int len) -{ - int i, result = 0; - int not_null = 0; - - for (i=0;i<len;i++) { - not_null |= block[i]; - result += block[i]; - } - -#ifdef DEBUG - if (result & 0xFF) ErrorF("DDC checksum not correct\n"); - if (!not_null) ErrorF("DDC read all Null\n"); -#endif - - /* catch the trivial case where all bytes are 0 */ - if (!not_null) return 1; - - return (result&0xFF); -} - -static unsigned char * -GetEDID_DDC1(unsigned int *s_ptr) -{ - unsigned char *d_block, *d_pos; - unsigned int *s_pos, *s_end; - int s_start; - int i,j; - s_start = find_start(s_ptr); - if (s_start==-1) return NULL; - s_end = s_ptr + NUM; - s_pos = s_ptr + s_start; - d_block=xalloc(EDID1_LEN); - if (!d_block) return NULL; - d_pos = d_block; - for (i=0;i<EDID1_LEN;i++) { - for (j=0;j<8;j++) { - *d_pos <<= 1; - if (*s_pos) { - *d_pos |= 0x01; - } - s_pos++; if (s_pos == s_end) s_pos=s_ptr; - }; - s_pos++; if (s_pos == s_end) s_pos=s_ptr; - d_pos++; - } - xfree(s_ptr); - if (d_block && DDC_checksum(d_block,EDID1_LEN)) return NULL; - return (resort(d_block)); -} - -/* fetch entire EDID record; DDC bit needs to be masked */ -static unsigned int * -FetchEDID_DDC1(register ScrnInfoPtr pScrn, - register unsigned int (*read_DDC)(ScrnInfoPtr)) -{ - int count = NUM; - unsigned int *ptr, *xp; - - ptr=xp=xalloc(sizeof(int)*NUM); - - if (!ptr) return NULL; - do { - /* wait for next retrace */ - *xp = read_DDC(pScrn); - xp++; - } while(--count); - return (ptr); -} - -/* test if DDC1 return 0 if not */ -static Bool -TestDDC1(ScrnInfoPtr pScrn, unsigned int (*read_DDC)(ScrnInfoPtr)) -{ - int old, count; - - old = read_DDC(pScrn); - count = HEADER * BITS_PER_BYTE; - do { - /* wait for next retrace */ - if (old != read_DDC(pScrn)) break; - } while(count--); - return (count); -} - -/* - * read EDID record , pass it to callback function to interpret. - * callback function will store it for further use by calling - * function; it will also decide if we need to reread it - */ -static unsigned char * -EDIDRead_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDCSpeed, - unsigned int (*read_DDC)(ScrnInfoPtr)) -{ - unsigned char *EDID_block = NULL; - int count = RETRIES; - - if (!read_DDC) { - xf86DrvMsg(pScrn->scrnIndex, 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 <Egbert.Eich@Physik.TU-Darmstadt.DE> + */ + +/* + * 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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86DDC.h" +#include <string.h> + +#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 (ptr<end) { + int i; + head_ptr = ptr; + for (i=0;i<8;i++){ + if (header[i] != *(head_ptr++)) break; + if (head_ptr == end) head_ptr = block; + } + if (i==8) break; + ptr++; + } + if (ptr == end) return (NULL); + return (ptr); +} + +static unsigned char * +resort(unsigned char *s_block) +{ + unsigned char *d_new, *d_ptr, *d_end, *s_ptr, *s_end; + unsigned char tmp; + + s_end = s_block + EDID1_LEN; + d_new = malloc(EDID1_LEN); + if (!d_new) return NULL; + d_end = d_new + EDID1_LEN; + + s_ptr = find_header(s_block); + if (!s_ptr) return NULL; + for (d_ptr=d_new;d_ptr<d_end;d_ptr++){ + tmp = *(s_ptr++); + *d_ptr = tmp; + if (s_ptr == s_end) s_ptr = s_block; + } + free(s_block); + return (d_new); +} + +static int +DDC_checksum(unsigned char *block, int len) +{ + int i, result = 0; + int not_null = 0; + + for (i=0;i<len;i++) { + not_null |= block[i]; + result += block[i]; + } + +#ifdef DEBUG + if (result & 0xFF) ErrorF("DDC checksum not correct\n"); + if (!not_null) ErrorF("DDC read all Null\n"); +#endif + + /* catch the trivial case where all bytes are 0 */ + if (!not_null) return 1; + + return (result&0xFF); +} + +static unsigned char * +GetEDID_DDC1(unsigned int *s_ptr) +{ + unsigned char *d_block, *d_pos; + unsigned int *s_pos, *s_end; + int s_start; + int i,j; + s_start = find_start(s_ptr); + if (s_start==-1) return NULL; + s_end = s_ptr + NUM; + s_pos = s_ptr + s_start; + d_block=malloc(EDID1_LEN); + if (!d_block) return NULL; + d_pos = d_block; + for (i=0;i<EDID1_LEN;i++) { + for (j=0;j<8;j++) { + *d_pos <<= 1; + if (*s_pos) { + *d_pos |= 0x01; + } + s_pos++; if (s_pos == s_end) s_pos=s_ptr; + }; + s_pos++; if (s_pos == s_end) s_pos=s_ptr; + d_pos++; + } + free(s_ptr); + if (d_block && DDC_checksum(d_block,EDID1_LEN)) return NULL; + return (resort(d_block)); +} + +/* fetch entire EDID record; DDC bit needs to be masked */ +static unsigned int * +FetchEDID_DDC1(register ScrnInfoPtr pScrn, + register unsigned int (*read_DDC)(ScrnInfoPtr)) +{ + int count = NUM; + unsigned int *ptr, *xp; + + ptr=xp=malloc(sizeof(int)*NUM); + + if (!ptr) return NULL; + do { + /* wait for next retrace */ + *xp = read_DDC(pScrn); + xp++; + } while(--count); + return (ptr); +} + +/* test if DDC1 return 0 if not */ +static Bool +TestDDC1(ScrnInfoPtr pScrn, unsigned int (*read_DDC)(ScrnInfoPtr)) +{ + int old, count; + + old = read_DDC(pScrn); + count = HEADER * BITS_PER_BYTE; + do { + /* wait for next retrace */ + if (old != read_DDC(pScrn)) break; + } while(count--); + return (count); +} + +/* + * read EDID record , pass it to callback function to interpret. + * callback function will store it for further use by calling + * function; it will also decide if we need to reread it + */ +static unsigned char * +EDIDRead_DDC1(ScrnInfoPtr pScrn, DDC1SetSpeedProc DDCSpeed, + unsigned int (*read_DDC)(ScrnInfoPtr)) +{ + unsigned char *EDID_block = NULL; + int count = RETRIES; + + if (!read_DDC) { + xf86DrvMsg(pScrn->scrnIndex, 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 <xorg-config.h> -#endif - -#include "xf86.h" -#include "xf86DDC.h" -#include <X11/Xatom.h> -#include "property.h" -#include "propertyst.h" -#include "xf86DDC.h" -#include <string.h> - -#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 <xorg-config.h> +#endif + +#include "xf86.h" +#include "xf86DDC.h" +#include <X11/Xatom.h> +#include "property.h" +#include "propertyst.h" +#include "xf86DDC.h" +#include <string.h> + +#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 <Egbert.Eich@Physik.TU-Darmstadt.DE> - * 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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#define _PARSE_EDID_ -#include "xf86DDC.h" -#include <string.h> - -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;i<STD_TIMINGS;i++){ - if (VALID_TIMING) { - r[i].hsize = HSIZE1; - VSIZE1(r[i].vsize); - r[i].refresh = REFRESH_R; - r[i].id = STD_TIMING_ID; - } else { - r[i].hsize = r[i].vsize = r[i].refresh = r[i].id = 0; - } - NEXT_STD_TIMING; - } -} - -static const unsigned char empty_block[18]; - -static void -fetch_detailed_block(Uchar *c, struct edid_version *ver, - struct detailed_monitor_section *det_mon) -{ - if (ver->version == 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 <Egbert.Eich@Physik.TU-Darmstadt.DE> + * 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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#define _PARSE_EDID_ +#include "xf86DDC.h" +#include <string.h> + +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;i<STD_TIMINGS;i++){ + if (VALID_TIMING) { + r[i].hsize = HSIZE1; + VSIZE1(r[i].vsize); + r[i].refresh = REFRESH_R; + r[i].id = STD_TIMING_ID; + } else { + r[i].hsize = r[i].vsize = r[i].refresh = r[i].id = 0; + } + NEXT_STD_TIMING; + } +} + +static const unsigned char empty_block[18]; + +static void +fetch_detailed_block(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon) +{ + if (ver->version == 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 <xorg-config.h> -#endif - -#include "xf86Module.h" -#include "xf86Opt.h" - -#include <X11/Xproto.h> - -#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 <xorg-config.h> +#endif + +#include "xf86Module.h" +#include "xf86Opt.h" + +#include <X11/Xproto.h> + +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#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 <X11/extensions/xf86dgaproto.h> -#include "swaprep.h" -#include "dgaproc.h" -#include "xf86dgaext.h" -#include "protocol-versions.h" - -#include <string.h> - -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#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 <X11/extensions/xf86dgaproto.h> +#include "swaprep.h" +#include "dgaproc.h" +#include "xf86dgaext.h" +#include "protocol-versions.h" + +#include <string.h> + +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "scrnintstr.h" -#include "servermd.h" -#include <X11/extensions/xf86vmproto.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "scrnintstr.h" +#include "servermd.h" +#include <X11/extensions/xf86vmproto.h> +#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 <jens@tungstengraphics.com> - * Rickard E. (Rik) Faith <faith@valinux.com> - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include "xf86.h" -#include <sys/time.h> -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include <sys/ioctl.h> -#include <errno.h> - -#include <X11/X.h> -#include <X11/Xproto.h> -#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 <X11/dri/xf86driproto.h> -#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 <jens@tungstengraphics.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "xf86.h" +#include <sys/time.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <errno.h> + +#include <X11/X.h> +#include <X11/Xproto.h> +#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 <X11/dri/xf86driproto.h> +#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 <martin@valinux.com> - * Jens Owen <jens@tungstengraphics.com> - * Rickard E. (Rik) Faith <faith@valinux.com> - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <string.h> - -#include "xf86.h" - -#include <X11/X.h> -#include <X11/Xproto.h> -#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 <X11/dri/xf86driproto.h> -#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 <martin@valinux.com> + * Jens Owen <jens@tungstengraphics.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <string.h> + +#include "xf86.h" + +#include <X11/X.h> +#include <X11/Xproto.h> +#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 <X11/dri/xf86driproto.h> +#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 <anholt@FreeBSD.org> - * - */ - -#ifdef HAVE_CONFIG_H -#include <xorg-config.h> -#endif - -#include <string.h> - -#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 <anholt@FreeBSD.org> + * + */ + +#ifdef HAVE_CONFIG_H +#include <xorg-config.h> +#endif + +#include <string.h> + +#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 <xorg-config.h> -#endif - -#include <string.h> - -#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 <X11/extensions/dpmsconst.h> - -#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 <fcntl.h> -#include <errno.h> -#include <sys/mman.h> -#include <sys/ioctl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> - -/* -------------------------------------------------------------------- */ -/* 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 <xorg-config.h> +#endif + +#include <string.h> + +#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 <X11/extensions/dpmsconst.h> + +#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 <fcntl.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +/* -------------------------------------------------------------------- */ +/* 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 <xorg-config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#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_valid<CC_FIFO_SIZE;data->num_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 <xorg-config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#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_valid<CC_FIFO_SIZE;data->num_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 <xorg-config.h> -#endif - -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#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 <xorg-config.h> +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#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 <xorg-config.h> -#endif - -#include <string.h> -#include <unistd.h> - -#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<m;i++) usleep(20000); -} - -/*----------------------------------------------------------------- -| specific functions for all MSP34xxG chips -|----------------------------------------------------------------*/ - -void InitMSP34xxG(MSP3430Ptr m) -{ - - #if __MSPDEBUG__ > 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 (standard<MSPSTANDARD_NICAM_BG) { - /* get old value of ident. mode register*/ - GetMSP3430Data (m, RD_DSP, 0x00, 0x15, &high, &low); - /* reset Ident-Filter */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x3F); - /* put back old value to ident. mode register*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, low); - } - } - - if (standard<=MSPSTANDARD_AUTO) { - m->c_format=MSPFORMAT_1xFM; - } - else if (standard<MSPSTANDARD_NICAM_BG) { - /* set FM prescale */ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0); - /* set FM deemphasis*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, ((standard==MSPSTANDARD_FM_M)?0:1), 0); - - /* check if FM2 carrier is present */ - /*turn off FM DC Notch*/ - SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x3f); - /*matrix source for Quasi-Peak Detector - stereo: ch2->L 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 <xorg-config.h> +#endif + +#include <string.h> +#include <unistd.h> + +#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<m;i++) usleep(20000); +} + +/*----------------------------------------------------------------- +| specific functions for all MSP34xxG chips +|----------------------------------------------------------------*/ + +void InitMSP34xxG(MSP3430Ptr m) +{ + + #if __MSPDEBUG__ > 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 (standard<MSPSTANDARD_NICAM_BG) { + /* get old value of ident. mode register*/ + GetMSP3430Data (m, RD_DSP, 0x00, 0x15, &high, &low); + /* reset Ident-Filter */ + SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, 0x3F); + /* put back old value to ident. mode register*/ + SetMSP3430Data (m, WR_DSP, 0x00, 0x14, 0x00, low); + } + } + + if (standard<=MSPSTANDARD_AUTO) { + m->c_format=MSPFORMAT_1xFM; + } + else if (standard<MSPSTANDARD_NICAM_BG) { + /* set FM prescale */ + SetMSP3430Data (m, WR_DSP, 0x00, 0x0e, 0x30, 0); + /* set FM deemphasis*/ + SetMSP3430Data (m, WR_DSP, 0x00, 0x0f, ((standard==MSPSTANDARD_FM_M)?0:1), 0); + + /* check if FM2 carrier is present */ + /*turn off FM DC Notch*/ + SetMSP3430Data (m, WR_DSP, 0x00, 0x17, 0x00, 0x3f); + /*matrix source for Quasi-Peak Detector - stereo: ch2->L 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 <xorg-config.h> -#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 <xorg-config.h> +#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 <xorg-config.h> -#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 <xorg-config.h> +#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 <xorg-config.h> -#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 <xorg-config.h> +#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 <xorg-config.h> -#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 <xorg-config.h> +#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 <kraxel@cs.tu-berlin.de> - */ - - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <sys/time.h> -#include <string.h> - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#include <X11/Xos.h> -#include <X11/Xproto.h> -#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 <last> 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 <unalloc> 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 <unalloc> to free it. If you set <devs_too>, the function - * xf86DestroyI2CDevRec will be called for all devices linked to the bus - * first, passing down the <unalloc> 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 <kraxel@cs.tu-berlin.de> + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <sys/time.h> +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/Xproto.h> +#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 <last> 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 <unalloc> 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 <unalloc> to free it. If you set <devs_too>, the function + * xf86DestroyI2CDevRec will be called for all devices linked to the bus + * first, passing down the <unalloc> 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 <xorg-config.h> -#endif - -#include <string.h> -#include <unistd.h> - -#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 <xorg-config.h> +#endif + +#include <string.h> +#include <unistd.h> + +#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 <xorg-config.h> -#endif - -#define PRINT_PORT 0 - -#include <unistd.h> - -#include <X11/Xos.h> -#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 <pciaccess.h> - -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 <xorg-config.h> +#endif + +#define PRINT_PORT 0 + +#include <unistd.h> + +#include <X11/Xos.h> +#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 <pciaccess.h> + +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 <xorg-config.h> -#endif - -#include <string.h> -#include <stdlib.h> - -#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 <xorg-config.h> +#endif + +#include <string.h> +#include <stdlib.h> + +#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 <xorg-config.h> -#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 <xorg-config.h> +#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 <xorg-config.h> -#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 <sys/types.h> -#include <regex.h> -#include <dirent.h> -#include <limits.h> - -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 : "<NONE>", - 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 : "<NONE>", - 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 <modulename>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 <xorg-config.h> +#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 <sys/types.h> +#include <regex.h> +#include <dirent.h> +#include <limits.h> + +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 : "<NONE>", + 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 : "<NONE>", + 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 <modulename>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 <xorg-config.h> -#else -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#endif - -#include <stddef.h> -#include <string.h> -#include <stdio.h> - -#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<<o); - /* If we can't tell where it's mapped, force it off */ - if (!output->funcs->get_crtc) { - desired_outputs = 0; - break; - } - if ((*output->funcs->get_crtc)(output) == crtc) - current_outputs |= (1<<o); - } - - /* - * If mappings are different or the CRTC is unused, - * we need to disable it - */ - if (desired_outputs != current_outputs || - !desired_outputs) - (*crtc->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 <xorg-config.h> +#else +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#endif + +#include <stddef.h> +#include <string.h> +#include <stdio.h> + +#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<<o); + /* If we can't tell where it's mapped, force it off */ + if (!output->funcs->get_crtc) { + desired_outputs = 0; + break; + } + if ((*output->funcs->get_crtc)(output) == crtc) + current_outputs |= (1<<o); + } + + /* + * If mappings are different or the CRTC is unused, + * we need to disable it + */ + if (desired_outputs != current_outputs || + !desired_outputs) + (*crtc->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 <xorg-config.h> -#else -#ifdef HAVE_CONFIG_H -#include <config.h> -#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 <xorg-config.h> +#else +#ifdef HAVE_CONFIG_H +#include <config.h> +#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 <ajax@redhat.com> - */ - -#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 <ajax@redhat.com> + */ + +#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 <xorg-config.h> -#else -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#endif - -#define _PARSE_EDID_ -#include "xf86.h" -#include "xf86DDC.h" -#include <X11/Xatom.h> -#include "property.h" -#include "propertyst.h" -#include "xf86Crtc.h" -#include <string.h> -#include <math.h> - -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 <xorg-config.h> +#else +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#endif + +#define _PARSE_EDID_ +#include "xf86.h" +#include "xf86DDC.h" +#include <X11/Xatom.h> +#include "property.h" +#include "propertyst.h" +#include "xf86Crtc.h" +#include <string.h> +#include <math.h> + +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 <xorg-config.h> -#else -#ifdef HAVE_CONFIG_H -#include <config.h> -#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 <width>x<height> 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 <xorg-config.h> +#else +#ifdef HAVE_CONFIG_H +#include <config.h> +#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 <width>x<height> 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 <xorg-config.h> -#else -#ifdef HAVE_CONFIG_H -#include <config.h> -#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 <randrstr.h> -#include <X11/extensions/render.h> - -#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 <xorg-config.h> +#else +#ifdef HAVE_CONFIG_H +#include <config.h> +#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 <randrstr.h> +#include <X11/extensions/render.h> + +#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 <xorg-config.h> -#else -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#endif - -#include <stddef.h> -#include <string.h> -#include <stdio.h> - -#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 <xorg-config.h> +#else +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#endif + +#include <stddef.h> +#include <string.h> +#include <stdio.h> + +#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 <Rich@Rice.edu> - * Copyright 1993 by David Wexelblat <dwex@goblin.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 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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include "xf86.h" -#include "xf86Priv.h" - -#include <errno.h> -#include <sys/mman.h> - -#ifdef HAS_MTRR_SUPPORT -#ifndef __NetBSD__ -#include <sys/types.h> -#include <sys/memrange.h> -#else -#include "memrange.h" -#endif -#define X_MTRR_ID "XFree86" -#endif - -#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) -#include <machine/mtrr.h> -#include <machine/sysarch.h> -#include <sys/queue.h> -#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 <Rich@Rice.edu> + * Copyright 1993 by David Wexelblat <dwex@goblin.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 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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include "xf86.h" +#include "xf86Priv.h" + +#include <errno.h> +#include <sys/mman.h> + +#ifdef HAS_MTRR_SUPPORT +#ifndef __NetBSD__ +#include <sys/types.h> +#include <sys/memrange.h> +#else +#include "memrange.h" +#endif +#define X_MTRR_ID "XFree86" +#endif + +#if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) +#include <machine/mtrr.h> +#include <machine/sysarch.h> +#include <sys/queue.h> +#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 <xorg-config.h> -#endif - -#include <fcntl.h> -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#ifdef sun -#include <sys/utsname.h> -#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 <xorg-config.h> +#endif + +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#ifdef sun +#include <sys/utsname.h> +#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 <xorg-config.h> -#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 <fcntl.h> -#include <errno.h> -#include <sys/mman.h> -#include <sys/ipc.h> -#include <sys/shm.h> -#include <unistd.h> -#include <string.h> - -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 <xorg-config.h> +#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 <fcntl.h> +#include <errno.h> +#include <sys/mman.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <unistd.h> +#include <string.h> + +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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86OSpriv.h" - -#if defined(linux) -#include <asm/ioctl.h> -#include <linux/agpgart.h> -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) -#include <sys/ioctl.h> -#include <sys/agpio.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86OSpriv.h" + +#if defined(linux) +#include <asm/ioctl.h> +#include <linux/agpgart.h> +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +#include <sys/ioctl.h> +#include <sys/agpio.h> +#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 <obz@Kodak.com> - * Copyright 1993 by David Wexelblat <dwex@goblin.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 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 <xorg-config.h> -#endif - -#include <errno.h> -#include <string.h> - -#include <X11/X.h> -#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 <asm/mtrr.h> -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -static Bool ExtendedEnabled = FALSE; - -#ifdef __ia64__ - -#include "compiler.h" -#include <sys/io.h> - -#elif !defined(__powerpc__) && \ - !defined(__mc68000__) && \ - !defined(__sparc__) && \ - !defined(__mips__) && \ - !defined(__arm__) - -/* - * Due to conflicts with "compiler.h", don't rely on <sys/io.h> 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 <obz@Kodak.com> + * Copyright 1993 by David Wexelblat <dwex@goblin.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 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 <xorg-config.h> +#endif + +#include <errno.h> +#include <string.h> + +#include <X11/X.h> +#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 <asm/mtrr.h> +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +static Bool ExtendedEnabled = FALSE; + +#ifdef __ia64__ + +#include "compiler.h" +#include <sys/io.h> + +#elif !defined(__powerpc__) && \ + !defined(__mc68000__) && \ + !defined(__sparc__) && \ + !defined(__mips__) && \ + !defined(__arm__) + +/* + * Due to conflicts with "compiler.h", don't rely on <sys/io.h> 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 <xorg-config.h> -#endif - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86_OSlib.h" -#include "xf86_OSproc.h" -#include <unistd.h> -#include <sys/ioccom.h> -#include <sys/types.h> -#include <fcntl.h> -#include <sys/agpgart.h> - -/* 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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86_OSproc.h" +#include <unistd.h> +#include <sys/ioccom.h> +#include <sys/types.h> +#include <fcntl.h> +#include <sys/agpgart.h> + +/* 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 <xorg-config.h> -#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 <xorg-config.h> +#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 <xorg-config.h> -#endif - -#include <string.h> - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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, <alanh@fairlite.demon.co.uk> - * - * Generic RAMDAC access routines. - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#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, <alanh@fairlite.demon.co.uk> + * + * Generic RAMDAC access routines. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "pixmapstr.h" -#include "input.h" -#include <X11/fonts/font.h> -#include "mi.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "gcstruct.h" -#include "dixfontstr.h" -#include <X11/fonts/fontstruct.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "pixmapstr.h" +#include "input.h" +#include <X11/fonts/font.h> +#include "mi.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "dixfontstr.h" +#include <X11/fonts/fontstruct.h> +#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 <pcpa@conectiva.com.br> - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <string.h> - -#include "xf86.h" -#include "vbe.h" -#include <X11/Xarch.h> -#include <X11/extensions/dpmsconst.h> - -#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 <pcpa@conectiva.com.br> + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <string.h> + +#include "xf86.h" +#include "vbe.h" +#include <X11/Xarch.h> +#include <X11/extensions/dpmsconst.h> + +#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 <pcpa@conectiva.com.br> - */ - -#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 <pcpa@conectiva.com.br> + */ + +#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 <dawes@xfree86.org> - * - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <stdio.h> -#include <string.h> - -#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 <dawes@xfree86.org> + * + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include <stdio.h> +#include <string.h> + +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "windowstr.h" -#include "compiler.h" -#include "mipointer.h" -#include "micmap.h" - -#include "xf86.h" -#include "vgaHW.h" - -#include <X11/extensions/xf86dgaproto.h> -#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; i<entries; i++) ppix[i] = i; - - QueryColors( pmap, entries, ppix, prgb); - - for ( i=0; i<entries; i++) /* convert xrgbs to xColorItems */ - { - defs[i].pixel = ppix[i]; - defs[i].red = prgb[i].red; - defs[i].green = prgb[i].green; - defs[i].blue = prgb[i].blue; - defs[i].flags = DoRed|DoGreen|DoBlue; - } - pmap->pScreen->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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "windowstr.h" +#include "compiler.h" +#include "mipointer.h" +#include "micmap.h" + +#include "xf86.h" +#include "vgaHW.h" + +#include <X11/extensions/xf86dgaproto.h> +#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; i<entries; i++) ppix[i] = i; + + QueryColors(pmap, entries, ppix, prgb, serverClient); + + for ( i=0; i<entries; i++) /* convert xrgbs to xColorItems */ + { + defs[i].pixel = ppix[i]; + defs[i].red = prgb[i].red; + defs[i].green = prgb[i].green; + defs[i].blue = prgb[i].blue; + defs[i].flags = DoRed|DoGreen|DoBlue; + } + pmap->pScreen->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 <xorg-config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <string.h> - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#include "servermd.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "servermd.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <string.h> - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" -#include "servermd.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" +#include "servermd.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <string.h> - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <string.h> - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#include <X11/fonts/font.h> -#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 <xorg-config.h> +#endif + +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/fonts/font.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <string.h> - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include <string.h> - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include <string.h> + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#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 <xorg-config.h> -#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 <xorg-config.h> +#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 <xorg-config.h> -#endif - -#include "misc.h" -#include "xf86.h" -#include "xf86_OSproc.h" - -#include <X11/X.h> -#include <X11/fonts/font.h> -#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 <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/fonts/font.h> +#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 <xorg-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#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 <xorg-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#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 */ diff --git a/xorg-server/hw/xnest/Color.c b/xorg-server/hw/xnest/Color.c index 2e6de15e4..985b5ad95 100644 --- a/xorg-server/hw/xnest/Color.c +++ b/xorg-server/hw/xnest/Color.c @@ -1,495 +1,495 @@ -/* - -Copyright 1993 by Davor Matic - -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. Davor Matic makes no representations about -the suitability of this software for any purpose. It is provided "as -is" without express or implied warranty. - -*/ - -#ifdef HAVE_XNEST_CONFIG_H -#include <xnest-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "scrnintstr.h" -#include "window.h" -#include "windowstr.h" -#include "colormapst.h" -#include "resource.h" - -#include "Xnest.h" - - -#include "Display.h" -#include "Screen.h" -#include "Color.h" -#include "Visual.h" -#include "XNWindow.h" -#include "Args.h" - -static int cmapScrPrivateKeyIndex; -static DevPrivateKey cmapScrPrivateKey = &cmapScrPrivateKeyIndex; - -#define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey)) -#define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c)) - -Bool -xnestCreateColormap(ColormapPtr pCmap) -{ - VisualPtr pVisual; - XColor *colors; - int i, ncolors; - Pixel red, green, blue; - Pixel redInc, greenInc, blueInc; - - pVisual = pCmap->pVisual; - ncolors = pVisual->ColormapEntries; - - pCmap->devPriv = (pointer)xalloc(sizeof(xnestPrivColormap)); - - xnestColormapPriv(pCmap)->colormap = - XCreateColormap(xnestDisplay, - xnestDefaultWindows[pCmap->pScreen->myNum], - xnestVisual(pVisual), - (pVisual->class & DynamicClass) ? - AllocAll : AllocNone); - - - switch (pVisual->class) { - case StaticGray: /* read only */ - colors = (XColor *)xalloc(ncolors * sizeof(XColor)); - for (i = 0; i < ncolors; i++) - colors[i].pixel = i; - XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); - for (i = 0; i < ncolors; i++) { - pCmap->red[i].co.local.red = colors[i].red; - pCmap->red[i].co.local.green = colors[i].red; - pCmap->red[i].co.local.blue = colors[i].red; - } - xfree(colors); - break; - - case StaticColor: /* read only */ - colors = (XColor *)xalloc(ncolors * sizeof(XColor)); - for (i = 0; i < ncolors; i++) - colors[i].pixel = i; - XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); - for (i = 0; i < ncolors; i++) { - pCmap->red[i].co.local.red = colors[i].red; - pCmap->red[i].co.local.green = colors[i].green; - pCmap->red[i].co.local.blue = colors[i].blue; - } - xfree(colors); - break; - - case TrueColor: /* read only */ - colors = (XColor *)xalloc(ncolors * sizeof(XColor)); - red = green = blue = 0L; - redInc = lowbit(pVisual->redMask); - greenInc = lowbit(pVisual->greenMask); - blueInc = lowbit(pVisual->blueMask); - for (i = 0; i < ncolors; i++) { - colors[i].pixel = red | green | blue; - red += redInc; - if (red > pVisual->redMask) red = 0L; - green += greenInc; - if (green > pVisual->greenMask) green = 0L; - blue += blueInc; - if (blue > pVisual->blueMask) blue = 0L; - } - XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); - for (i = 0; i < ncolors; i++) { - pCmap->red[i].co.local.red = colors[i].red; - pCmap->green[i].co.local.green = colors[i].green; - pCmap->blue[i].co.local.blue = colors[i].blue; - } - xfree(colors); - break; - - case GrayScale: /* read and write */ - break; - - case PseudoColor: /* read and write */ - break; - - case DirectColor: /* read and write */ - break; - } - - return True; -} - -void -xnestDestroyColormap(ColormapPtr pCmap) -{ - XFreeColormap(xnestDisplay, xnestColormap(pCmap)); - xfree(pCmap->devPriv); -} - -#define SEARCH_PREDICATE \ - (xnestWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i]) - -static int -xnestCountInstalledColormapWindows(WindowPtr pWin, pointer ptr) -{ - xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *)ptr; - int i; - - for (i = 0; i < icws->numCmapIDs; i++) - if (SEARCH_PREDICATE) { - icws->numWindows++; - return WT_DONTWALKCHILDREN; - } - - return WT_WALKCHILDREN; -} - -static int -xnestGetInstalledColormapWindows(WindowPtr pWin, pointer ptr) -{ - xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *)ptr; - int i; - - for (i = 0; i < icws->numCmapIDs; i++) - if (SEARCH_PREDICATE) { - icws->windows[icws->index++] = xnestWindow(pWin); - return WT_DONTWALKCHILDREN; - } - - return WT_WALKCHILDREN; -} - -static Window *xnestOldInstalledColormapWindows = NULL; -static int xnestNumOldInstalledColormapWindows = 0; - -static Bool -xnestSameInstalledColormapWindows(Window *windows, int numWindows) -{ - if (xnestNumOldInstalledColormapWindows != numWindows) - return False; - - if (xnestOldInstalledColormapWindows == windows) - return True; - - if (xnestOldInstalledColormapWindows == NULL || windows == NULL) - return False; - - if (memcmp(xnestOldInstalledColormapWindows, windows, - numWindows * sizeof(Window))) - return False; - - return True; -} - -void -xnestSetInstalledColormapWindows(ScreenPtr pScreen) -{ - xnestInstalledColormapWindows icws; - int numWindows; - - icws.cmapIDs = (Colormap *)xalloc(pScreen->maxInstalledCmaps * - sizeof(Colormap)); - icws.numCmapIDs = xnestListInstalledColormaps(pScreen, icws.cmapIDs); - icws.numWindows = 0; - WalkTree(pScreen, xnestCountInstalledColormapWindows, (pointer)&icws); - if (icws.numWindows) { - icws.windows = (Window *)xalloc((icws.numWindows + 1) * sizeof(Window)); - icws.index = 0; - WalkTree(pScreen, xnestGetInstalledColormapWindows, (pointer)&icws); - icws.windows[icws.numWindows] = xnestDefaultWindows[pScreen->myNum]; - numWindows = icws.numWindows + 1; - } - else { - icws.windows = NULL; - numWindows = 0; - } - - xfree(icws.cmapIDs); - - if (!xnestSameInstalledColormapWindows(icws.windows, icws.numWindows)) { - if (xnestOldInstalledColormapWindows) - xfree(xnestOldInstalledColormapWindows); - -#ifdef _XSERVER64 - { - int i; - Window64 *windows = (Window64 *)xalloc(numWindows * sizeof(Window64)); - - for(i = 0; i < numWindows; ++i) - windows[i] = icws.windows[i]; - XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], - windows, numWindows); - xfree(windows); - } -#else - XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], - icws.windows, numWindows); -#endif - - xnestOldInstalledColormapWindows = icws.windows; - xnestNumOldInstalledColormapWindows = icws.numWindows; - -#ifdef DUMB_WINDOW_MANAGERS - /* - This code is for dumb window managers. - This will only work with default local visual colormaps. - */ - if (icws.numWindows) - { - WindowPtr pWin; - Visual *visual; - ColormapPtr pCmap; - - pWin = xnestWindowPtr(icws.windows[0]); - visual = xnestVisualFromID(pScreen, wVisual(pWin)); - - if (visual == xnestDefaultVisual(pScreen)) - dixLookupResourceByType((pointer *)&pCmap, wColormap(pWin), - RT_COLORMAP, serverClient, DixUseAccess); - else - dixLookupResourceByType((pointer *)&pCmap, pScreen->defColormap, - RT_COLORMAP, serverClient, DixUseAccess); - - XSetWindowColormap(xnestDisplay, - xnestDefaultWindows[pScreen->myNum], - xnestColormap(pCmap)); - } -#endif /* DUMB_WINDOW_MANAGERS */ - } - else - if (icws.windows) xfree(icws.windows); -} - -void -xnestSetScreenSaverColormapWindow(ScreenPtr pScreen) -{ - if (xnestOldInstalledColormapWindows) - xfree(xnestOldInstalledColormapWindows); - -#ifdef _XSERVER64 - { - Window64 window; - - window = xnestScreenSaverWindows[pScreen->myNum]; - XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], - &window, 1); - xnestScreenSaverWindows[pScreen->myNum] = window; - } -#else - XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], - &xnestScreenSaverWindows[pScreen->myNum], 1); -#endif /* _XSERVER64 */ - - xnestOldInstalledColormapWindows = NULL; - xnestNumOldInstalledColormapWindows = 0; - - xnestDirectUninstallColormaps(pScreen); -} - -void -xnestDirectInstallColormaps(ScreenPtr pScreen) -{ - int i, n; - Colormap pCmapIDs[MAXCMAPS]; - - if (!xnestDoDirectColormaps) return; - - n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs); - - for (i = 0; i < n; i++) { - ColormapPtr pCmap; - - dixLookupResourceByType((pointer *)&pCmap, pCmapIDs[i], RT_COLORMAP, - serverClient, DixInstallAccess); - if (pCmap) - XInstallColormap(xnestDisplay, xnestColormap(pCmap)); - } -} - -void -xnestDirectUninstallColormaps(ScreenPtr pScreen) -{ - int i, n; - Colormap pCmapIDs[MAXCMAPS]; - - if (!xnestDoDirectColormaps) return; - - n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs); - - for (i = 0; i < n; i++) { - ColormapPtr pCmap; - - dixLookupResourceByType((pointer *)&pCmap, pCmapIDs[i], RT_COLORMAP, - serverClient, DixUninstallAccess); - if (pCmap) - XUninstallColormap(xnestDisplay, xnestColormap(pCmap)); - } -} - -void -xnestInstallColormap(ColormapPtr pCmap) -{ - ColormapPtr pOldCmap = GetInstalledColormap(pCmap->pScreen); - - if(pCmap != pOldCmap) - { - xnestDirectUninstallColormaps(pCmap->pScreen); - - /* Uninstall pInstalledMap. Notify all interested parties. */ - if(pOldCmap != (ColormapPtr)None) - WalkTree(pCmap->pScreen, TellLostMap, (pointer)&pOldCmap->mid); - - SetInstalledColormap(pCmap->pScreen, pCmap); - WalkTree(pCmap->pScreen, TellGainedMap, (pointer)&pCmap->mid); - - xnestSetInstalledColormapWindows(pCmap->pScreen); - xnestDirectInstallColormaps(pCmap->pScreen); - } -} - -void -xnestUninstallColormap(ColormapPtr pCmap) -{ - ColormapPtr pCurCmap = GetInstalledColormap(pCmap->pScreen); - - if(pCmap == pCurCmap) - { - if (pCmap->mid != pCmap->pScreen->defColormap) - { - dixLookupResourceByType((pointer *)&pCurCmap, - pCmap->pScreen->defColormap, - RT_COLORMAP, - serverClient, DixInstallAccess); - (*pCmap->pScreen->InstallColormap)(pCurCmap); - } - } -} - -static Bool xnestInstalledDefaultColormap = False; - -int -xnestListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIDs) -{ - if (xnestInstalledDefaultColormap) { - *pCmapIDs = GetInstalledColormap(pScreen)->mid; - return 1; - } - else - return 0; -} - -void -xnestStoreColors(ColormapPtr pCmap, int nColors, xColorItem *pColors) -{ - if (pCmap->pVisual->class & DynamicClass) -#ifdef _XSERVER64 - { - int i; - XColor *pColors64 = (XColor *)xalloc(nColors * sizeof(XColor) ); - - for(i = 0; i < nColors; ++i) - { - pColors64[i].pixel = pColors[i].pixel; - pColors64[i].red = pColors[i].red; - pColors64[i].green = pColors[i].green; - pColors64[i].blue = pColors[i].blue; - pColors64[i].flags = pColors[i].flags; - } - XStoreColors(xnestDisplay, xnestColormap(pCmap), pColors64, nColors); - xfree(pColors64); - } -#else - XStoreColors(xnestDisplay, xnestColormap(pCmap), - (XColor *)pColors, nColors); -#endif -} - -void -xnestResolveColor(unsigned short *pRed, unsigned short *pGreen, - unsigned short *pBlue, VisualPtr pVisual) -{ - int shift; - unsigned int lim; - - shift = 16 - pVisual->bitsPerRGBValue; - lim = (1 << pVisual->bitsPerRGBValue) - 1; - - if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor)) - { - /* rescale to rgb bits */ - *pRed = ((*pRed >> shift) * 65535) / lim; - *pGreen = ((*pGreen >> shift) * 65535) / lim; - *pBlue = ((*pBlue >> shift) * 65535) / lim; - } - else if (pVisual->class == GrayScale) - { - /* rescale to gray then rgb bits */ - *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; - *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; - } - else if (pVisual->class == StaticGray) - { - unsigned int limg; - - limg = pVisual->ColormapEntries - 1; - /* rescale to gray then [0..limg] then [0..65535] then rgb bits */ - *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; - *pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg; - *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; - } - else - { - unsigned limr, limg, limb; - - limr = pVisual->redMask >> pVisual->offsetRed; - limg = pVisual->greenMask >> pVisual->offsetGreen; - limb = pVisual->blueMask >> pVisual->offsetBlue; - /* rescale to [0..limN] then [0..65535] then rgb bits */ - *pRed = ((((((*pRed * (limr + 1)) >> 16) * - 65535) / limr) >> shift) * 65535) / lim; - *pGreen = ((((((*pGreen * (limg + 1)) >> 16) * - 65535) / limg) >> shift) * 65535) / lim; - *pBlue = ((((((*pBlue * (limb + 1)) >> 16) * - 65535) / limb) >> shift) * 65535) / lim; - } -} - -Bool -xnestCreateDefaultColormap(ScreenPtr pScreen) -{ - VisualPtr pVisual; - ColormapPtr pCmap; - unsigned short zero = 0, ones = 0xFFFF; - Pixel wp, bp; - - for (pVisual = pScreen->visuals; - pVisual->vid != pScreen->rootVisual; - pVisual++); - - if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap, - (pVisual->class & DynamicClass) ? AllocNone : AllocAll, 0) - != Success) - return False; - - wp = pScreen->whitePixel; - bp = pScreen->blackPixel; - if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) != - Success) || - (AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) != - Success)) - return FALSE; - pScreen->whitePixel = wp; - pScreen->blackPixel = bp; - (*pScreen->InstallColormap)(pCmap); - - xnestInstalledDefaultColormap = True; - - return True; -} +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "window.h" +#include "windowstr.h" +#include "colormapst.h" +#include "resource.h" + +#include "Xnest.h" + + +#include "Display.h" +#include "Screen.h" +#include "Color.h" +#include "Visual.h" +#include "XNWindow.h" +#include "Args.h" + +static int cmapScrPrivateKeyIndex; +static DevPrivateKey cmapScrPrivateKey = &cmapScrPrivateKeyIndex; + +#define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey)) +#define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c)) + +Bool +xnestCreateColormap(ColormapPtr pCmap) +{ + VisualPtr pVisual; + XColor *colors; + int i, ncolors; + Pixel red, green, blue; + Pixel redInc, greenInc, blueInc; + + pVisual = pCmap->pVisual; + ncolors = pVisual->ColormapEntries; + + pCmap->devPriv = (pointer)malloc(sizeof(xnestPrivColormap)); + + xnestColormapPriv(pCmap)->colormap = + XCreateColormap(xnestDisplay, + xnestDefaultWindows[pCmap->pScreen->myNum], + xnestVisual(pVisual), + (pVisual->class & DynamicClass) ? + AllocAll : AllocNone); + + + switch (pVisual->class) { + case StaticGray: /* read only */ + colors = (XColor *)malloc(ncolors * sizeof(XColor)); + for (i = 0; i < ncolors; i++) + colors[i].pixel = i; + XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->red[i].co.local.green = colors[i].red; + pCmap->red[i].co.local.blue = colors[i].red; + } + free(colors); + break; + + case StaticColor: /* read only */ + colors = (XColor *)malloc(ncolors * sizeof(XColor)); + for (i = 0; i < ncolors; i++) + colors[i].pixel = i; + XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->red[i].co.local.green = colors[i].green; + pCmap->red[i].co.local.blue = colors[i].blue; + } + free(colors); + break; + + case TrueColor: /* read only */ + colors = (XColor *)malloc(ncolors * sizeof(XColor)); + red = green = blue = 0L; + redInc = lowbit(pVisual->redMask); + greenInc = lowbit(pVisual->greenMask); + blueInc = lowbit(pVisual->blueMask); + for (i = 0; i < ncolors; i++) { + colors[i].pixel = red | green | blue; + red += redInc; + if (red > pVisual->redMask) red = 0L; + green += greenInc; + if (green > pVisual->greenMask) green = 0L; + blue += blueInc; + if (blue > pVisual->blueMask) blue = 0L; + } + XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); + for (i = 0; i < ncolors; i++) { + pCmap->red[i].co.local.red = colors[i].red; + pCmap->green[i].co.local.green = colors[i].green; + pCmap->blue[i].co.local.blue = colors[i].blue; + } + free(colors); + break; + + case GrayScale: /* read and write */ + break; + + case PseudoColor: /* read and write */ + break; + + case DirectColor: /* read and write */ + break; + } + + return True; +} + +void +xnestDestroyColormap(ColormapPtr pCmap) +{ + XFreeColormap(xnestDisplay, xnestColormap(pCmap)); + free(pCmap->devPriv); +} + +#define SEARCH_PREDICATE \ + (xnestWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i]) + +static int +xnestCountInstalledColormapWindows(WindowPtr pWin, pointer ptr) +{ + xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *)ptr; + int i; + + for (i = 0; i < icws->numCmapIDs; i++) + if (SEARCH_PREDICATE) { + icws->numWindows++; + return WT_DONTWALKCHILDREN; + } + + return WT_WALKCHILDREN; +} + +static int +xnestGetInstalledColormapWindows(WindowPtr pWin, pointer ptr) +{ + xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *)ptr; + int i; + + for (i = 0; i < icws->numCmapIDs; i++) + if (SEARCH_PREDICATE) { + icws->windows[icws->index++] = xnestWindow(pWin); + return WT_DONTWALKCHILDREN; + } + + return WT_WALKCHILDREN; +} + +static Window *xnestOldInstalledColormapWindows = NULL; +static int xnestNumOldInstalledColormapWindows = 0; + +static Bool +xnestSameInstalledColormapWindows(Window *windows, int numWindows) +{ + if (xnestNumOldInstalledColormapWindows != numWindows) + return False; + + if (xnestOldInstalledColormapWindows == windows) + return True; + + if (xnestOldInstalledColormapWindows == NULL || windows == NULL) + return False; + + if (memcmp(xnestOldInstalledColormapWindows, windows, + numWindows * sizeof(Window))) + return False; + + return True; +} + +void +xnestSetInstalledColormapWindows(ScreenPtr pScreen) +{ + xnestInstalledColormapWindows icws; + int numWindows; + + icws.cmapIDs = (Colormap *)malloc(pScreen->maxInstalledCmaps * + sizeof(Colormap)); + icws.numCmapIDs = xnestListInstalledColormaps(pScreen, icws.cmapIDs); + icws.numWindows = 0; + WalkTree(pScreen, xnestCountInstalledColormapWindows, (pointer)&icws); + if (icws.numWindows) { + icws.windows = (Window *)malloc((icws.numWindows + 1) * sizeof(Window)); + icws.index = 0; + WalkTree(pScreen, xnestGetInstalledColormapWindows, (pointer)&icws); + icws.windows[icws.numWindows] = xnestDefaultWindows[pScreen->myNum]; + numWindows = icws.numWindows + 1; + } + else { + icws.windows = NULL; + numWindows = 0; + } + + free(icws.cmapIDs); + + if (!xnestSameInstalledColormapWindows(icws.windows, icws.numWindows)) { + if (xnestOldInstalledColormapWindows) + free(xnestOldInstalledColormapWindows); + +#ifdef _XSERVER64 + { + int i; + Window64 *windows = (Window64 *)malloc(numWindows * sizeof(Window64)); + + for(i = 0; i < numWindows; ++i) + windows[i] = icws.windows[i]; + XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], + windows, numWindows); + free(windows); + } +#else + XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], + icws.windows, numWindows); +#endif + + xnestOldInstalledColormapWindows = icws.windows; + xnestNumOldInstalledColormapWindows = icws.numWindows; + +#ifdef DUMB_WINDOW_MANAGERS + /* + This code is for dumb window managers. + This will only work with default local visual colormaps. + */ + if (icws.numWindows) + { + WindowPtr pWin; + Visual *visual; + ColormapPtr pCmap; + + pWin = xnestWindowPtr(icws.windows[0]); + visual = xnestVisualFromID(pScreen, wVisual(pWin)); + + if (visual == xnestDefaultVisual(pScreen)) + dixLookupResourceByType((pointer *)&pCmap, wColormap(pWin), + RT_COLORMAP, serverClient, DixUseAccess); + else + dixLookupResourceByType((pointer *)&pCmap, pScreen->defColormap, + RT_COLORMAP, serverClient, DixUseAccess); + + XSetWindowColormap(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + xnestColormap(pCmap)); + } +#endif /* DUMB_WINDOW_MANAGERS */ + } + else + if (icws.windows) free(icws.windows); +} + +void +xnestSetScreenSaverColormapWindow(ScreenPtr pScreen) +{ + if (xnestOldInstalledColormapWindows) + free(xnestOldInstalledColormapWindows); + +#ifdef _XSERVER64 + { + Window64 window; + + window = xnestScreenSaverWindows[pScreen->myNum]; + XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], + &window, 1); + xnestScreenSaverWindows[pScreen->myNum] = window; + } +#else + XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], + &xnestScreenSaverWindows[pScreen->myNum], 1); +#endif /* _XSERVER64 */ + + xnestOldInstalledColormapWindows = NULL; + xnestNumOldInstalledColormapWindows = 0; + + xnestDirectUninstallColormaps(pScreen); +} + +void +xnestDirectInstallColormaps(ScreenPtr pScreen) +{ + int i, n; + Colormap pCmapIDs[MAXCMAPS]; + + if (!xnestDoDirectColormaps) return; + + n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs); + + for (i = 0; i < n; i++) { + ColormapPtr pCmap; + + dixLookupResourceByType((pointer *)&pCmap, pCmapIDs[i], RT_COLORMAP, + serverClient, DixInstallAccess); + if (pCmap) + XInstallColormap(xnestDisplay, xnestColormap(pCmap)); + } +} + +void +xnestDirectUninstallColormaps(ScreenPtr pScreen) +{ + int i, n; + Colormap pCmapIDs[MAXCMAPS]; + + if (!xnestDoDirectColormaps) return; + + n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs); + + for (i = 0; i < n; i++) { + ColormapPtr pCmap; + + dixLookupResourceByType((pointer *)&pCmap, pCmapIDs[i], RT_COLORMAP, + serverClient, DixUninstallAccess); + if (pCmap) + XUninstallColormap(xnestDisplay, xnestColormap(pCmap)); + } +} + +void +xnestInstallColormap(ColormapPtr pCmap) +{ + ColormapPtr pOldCmap = GetInstalledColormap(pCmap->pScreen); + + if(pCmap != pOldCmap) + { + xnestDirectUninstallColormaps(pCmap->pScreen); + + /* Uninstall pInstalledMap. Notify all interested parties. */ + if(pOldCmap != (ColormapPtr)None) + WalkTree(pCmap->pScreen, TellLostMap, (pointer)&pOldCmap->mid); + + SetInstalledColormap(pCmap->pScreen, pCmap); + WalkTree(pCmap->pScreen, TellGainedMap, (pointer)&pCmap->mid); + + xnestSetInstalledColormapWindows(pCmap->pScreen); + xnestDirectInstallColormaps(pCmap->pScreen); + } +} + +void +xnestUninstallColormap(ColormapPtr pCmap) +{ + ColormapPtr pCurCmap = GetInstalledColormap(pCmap->pScreen); + + if(pCmap == pCurCmap) + { + if (pCmap->mid != pCmap->pScreen->defColormap) + { + dixLookupResourceByType((pointer *)&pCurCmap, + pCmap->pScreen->defColormap, + RT_COLORMAP, + serverClient, DixInstallAccess); + (*pCmap->pScreen->InstallColormap)(pCurCmap); + } + } +} + +static Bool xnestInstalledDefaultColormap = False; + +int +xnestListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIDs) +{ + if (xnestInstalledDefaultColormap) { + *pCmapIDs = GetInstalledColormap(pScreen)->mid; + return 1; + } + else + return 0; +} + +void +xnestStoreColors(ColormapPtr pCmap, int nColors, xColorItem *pColors) +{ + if (pCmap->pVisual->class & DynamicClass) +#ifdef _XSERVER64 + { + int i; + XColor *pColors64 = (XColor *)malloc(nColors * sizeof(XColor) ); + + for(i = 0; i < nColors; ++i) + { + pColors64[i].pixel = pColors[i].pixel; + pColors64[i].red = pColors[i].red; + pColors64[i].green = pColors[i].green; + pColors64[i].blue = pColors[i].blue; + pColors64[i].flags = pColors[i].flags; + } + XStoreColors(xnestDisplay, xnestColormap(pCmap), pColors64, nColors); + free(pColors64); + } +#else + XStoreColors(xnestDisplay, xnestColormap(pCmap), + (XColor *)pColors, nColors); +#endif +} + +void +xnestResolveColor(unsigned short *pRed, unsigned short *pGreen, + unsigned short *pBlue, VisualPtr pVisual) +{ + int shift; + unsigned int lim; + + shift = 16 - pVisual->bitsPerRGBValue; + lim = (1 << pVisual->bitsPerRGBValue) - 1; + + if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor)) + { + /* rescale to rgb bits */ + *pRed = ((*pRed >> shift) * 65535) / lim; + *pGreen = ((*pGreen >> shift) * 65535) / lim; + *pBlue = ((*pBlue >> shift) * 65535) / lim; + } + else if (pVisual->class == GrayScale) + { + /* rescale to gray then rgb bits */ + *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; + *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; + } + else if (pVisual->class == StaticGray) + { + unsigned int limg; + + limg = pVisual->ColormapEntries - 1; + /* rescale to gray then [0..limg] then [0..65535] then rgb bits */ + *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; + *pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg; + *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; + } + else + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + /* rescale to [0..limN] then [0..65535] then rgb bits */ + *pRed = ((((((*pRed * (limr + 1)) >> 16) * + 65535) / limr) >> shift) * 65535) / lim; + *pGreen = ((((((*pGreen * (limg + 1)) >> 16) * + 65535) / limg) >> shift) * 65535) / lim; + *pBlue = ((((((*pBlue * (limb + 1)) >> 16) * + 65535) / limb) >> shift) * 65535) / lim; + } +} + +Bool +xnestCreateDefaultColormap(ScreenPtr pScreen) +{ + VisualPtr pVisual; + ColormapPtr pCmap; + unsigned short zero = 0, ones = 0xFFFF; + Pixel wp, bp; + + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++); + + if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap, + (pVisual->class & DynamicClass) ? AllocNone : AllocAll, 0) + != Success) + return False; + + wp = pScreen->whitePixel; + bp = pScreen->blackPixel; + if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) != + Success) || + (AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) != + Success)) + return FALSE; + pScreen->whitePixel = wp; + pScreen->blackPixel = bp; + (*pScreen->InstallColormap)(pCmap); + + xnestInstalledDefaultColormap = True; + + return True; +} diff --git a/xorg-server/hw/xnest/Cursor.c b/xorg-server/hw/xnest/Cursor.c index 12f47e725..290074d4e 100644 --- a/xorg-server/hw/xnest/Cursor.c +++ b/xorg-server/hw/xnest/Cursor.c @@ -1,183 +1,183 @@ -/* - -Copyright 1993 by Davor Matic - -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. Davor Matic makes no representations about -the suitability of this software for any purpose. It is provided "as -is" without express or implied warranty. - -*/ - -#ifdef HAVE_XNEST_CONFIG_H -#include <xnest-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "screenint.h" -#include "input.h" -#include "misc.h" -#include "cursor.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "servermd.h" -#include "mipointrst.h" - -#include "Xnest.h" - -#include "Display.h" -#include "Screen.h" -#include "XNCursor.h" -#include "Visual.h" -#include "Keyboard.h" -#include "Args.h" - -xnestCursorFuncRec xnestCursorFuncs = {NULL}; - -Bool -xnestRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - XImage *ximage; - Pixmap source, mask; - XColor fg_color, bg_color; - unsigned long valuemask; - XGCValues values; - - valuemask = GCFunction | - GCPlaneMask | - GCForeground | - GCBackground | - GCClipMask; - - values.function = GXcopy; - values.plane_mask = AllPlanes; - values.foreground = 1L; - values.background = 0L; - values.clip_mask = None; - - XChangeGC(xnestDisplay, xnestBitmapGC, valuemask, &values); - - source = XCreatePixmap(xnestDisplay, - xnestDefaultWindows[pScreen->myNum], - pCursor->bits->width, - pCursor->bits->height, - 1); - - mask = XCreatePixmap(xnestDisplay, - xnestDefaultWindows[pScreen->myNum], - pCursor->bits->width, - pCursor->bits->height, - 1); - - ximage = XCreateImage(xnestDisplay, - xnestDefaultVisual(pScreen), - 1, XYBitmap, 0, - (char *)pCursor->bits->source, - pCursor->bits->width, - pCursor->bits->height, - BitmapPad(xnestDisplay), 0); - - XPutImage(xnestDisplay, source, xnestBitmapGC, ximage, - 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); - - XFree(ximage); - - ximage = XCreateImage(xnestDisplay, - xnestDefaultVisual(pScreen), - 1, XYBitmap, 0, - (char *)pCursor->bits->mask, - pCursor->bits->width, - pCursor->bits->height, - BitmapPad(xnestDisplay), 0); - - XPutImage(xnestDisplay, mask, xnestBitmapGC, ximage, - 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); - - XFree(ximage); - - fg_color.red = pCursor->foreRed; - fg_color.green = pCursor->foreGreen; - fg_color.blue = pCursor->foreBlue; - - bg_color.red = pCursor->backRed; - bg_color.green = pCursor->backGreen; - bg_color.blue = pCursor->backBlue; - - xnestSetCursorPriv(pCursor, pScreen, xalloc(sizeof(xnestPrivCursor))); - xnestCursor(pCursor, pScreen) = - XCreatePixmapCursor(xnestDisplay, source, mask, &fg_color, &bg_color, - pCursor->bits->xhot, pCursor->bits->yhot); - - XFreePixmap(xnestDisplay, source); - XFreePixmap(xnestDisplay, mask); - - return True; -} - -Bool -xnestUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - XFreeCursor(xnestDisplay, xnestCursor(pCursor, pScreen)); - xfree(xnestGetCursorPriv(pCursor, pScreen)); - return True; -} - -void -xnestRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor, Bool displayed) -{ - XColor fg_color, bg_color; - - fg_color.red = pCursor->foreRed; - fg_color.green = pCursor->foreGreen; - fg_color.blue = pCursor->foreBlue; - - bg_color.red = pCursor->backRed; - bg_color.green = pCursor->backGreen; - bg_color.blue = pCursor->backBlue; - - XRecolorCursor(xnestDisplay, - xnestCursor(pCursor, pScreen), - &fg_color, &bg_color); -} - -void xnestSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) -{ - if (pCursor) - { - XDefineCursor(xnestDisplay, - xnestDefaultWindows[pScreen->myNum], - xnestCursor(pCursor, pScreen)); - } -} - -void -xnestMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ -} - -Bool -xnestDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - xnestCursorFuncPtr pScreenPriv; - - pScreenPriv = (xnestCursorFuncPtr) - dixLookupPrivate(&pScreen->devPrivates, xnestCursorScreenKey); - - pScreenPriv->spriteFuncs->DeviceCursorInitialize(pDev, pScreen); - return TRUE; -} - -void -xnestDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - xnestCursorFuncPtr pScreenPriv; - - pScreenPriv = (xnestCursorFuncPtr) - dixLookupPrivate(&pScreen->devPrivates, xnestCursorScreenKey); - - pScreenPriv->spriteFuncs->DeviceCursorCleanup(pDev, pScreen); -} +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "cursor.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#include "mipointrst.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "XNCursor.h" +#include "Visual.h" +#include "Keyboard.h" +#include "Args.h" + +xnestCursorFuncRec xnestCursorFuncs = {NULL}; + +Bool +xnestRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + XImage *ximage; + Pixmap source, mask; + XColor fg_color, bg_color; + unsigned long valuemask; + XGCValues values; + + valuemask = GCFunction | + GCPlaneMask | + GCForeground | + GCBackground | + GCClipMask; + + values.function = GXcopy; + values.plane_mask = AllPlanes; + values.foreground = 1L; + values.background = 0L; + values.clip_mask = None; + + XChangeGC(xnestDisplay, xnestBitmapGC, valuemask, &values); + + source = XCreatePixmap(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + pCursor->bits->width, + pCursor->bits->height, + 1); + + mask = XCreatePixmap(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + pCursor->bits->width, + pCursor->bits->height, + 1); + + ximage = XCreateImage(xnestDisplay, + xnestDefaultVisual(pScreen), + 1, XYBitmap, 0, + (char *)pCursor->bits->source, + pCursor->bits->width, + pCursor->bits->height, + BitmapPad(xnestDisplay), 0); + + XPutImage(xnestDisplay, source, xnestBitmapGC, ximage, + 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); + + XFree(ximage); + + ximage = XCreateImage(xnestDisplay, + xnestDefaultVisual(pScreen), + 1, XYBitmap, 0, + (char *)pCursor->bits->mask, + pCursor->bits->width, + pCursor->bits->height, + BitmapPad(xnestDisplay), 0); + + XPutImage(xnestDisplay, mask, xnestBitmapGC, ximage, + 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height); + + XFree(ximage); + + fg_color.red = pCursor->foreRed; + fg_color.green = pCursor->foreGreen; + fg_color.blue = pCursor->foreBlue; + + bg_color.red = pCursor->backRed; + bg_color.green = pCursor->backGreen; + bg_color.blue = pCursor->backBlue; + + xnestSetCursorPriv(pCursor, pScreen, malloc(sizeof(xnestPrivCursor))); + xnestCursor(pCursor, pScreen) = + XCreatePixmapCursor(xnestDisplay, source, mask, &fg_color, &bg_color, + pCursor->bits->xhot, pCursor->bits->yhot); + + XFreePixmap(xnestDisplay, source); + XFreePixmap(xnestDisplay, mask); + + return True; +} + +Bool +xnestUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + XFreeCursor(xnestDisplay, xnestCursor(pCursor, pScreen)); + free(xnestGetCursorPriv(pCursor, pScreen)); + return True; +} + +void +xnestRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor, Bool displayed) +{ + XColor fg_color, bg_color; + + fg_color.red = pCursor->foreRed; + fg_color.green = pCursor->foreGreen; + fg_color.blue = pCursor->foreBlue; + + bg_color.red = pCursor->backRed; + bg_color.green = pCursor->backGreen; + bg_color.blue = pCursor->backBlue; + + XRecolorCursor(xnestDisplay, + xnestCursor(pCursor, pScreen), + &fg_color, &bg_color); +} + +void xnestSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + if (pCursor) + { + XDefineCursor(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + xnestCursor(pCursor, pScreen)); + } +} + +void +xnestMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ +} + +Bool +xnestDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + xnestCursorFuncPtr pScreenPriv; + + pScreenPriv = (xnestCursorFuncPtr) + dixLookupPrivate(&pScreen->devPrivates, xnestCursorScreenKey); + + pScreenPriv->spriteFuncs->DeviceCursorInitialize(pDev, pScreen); + return TRUE; +} + +void +xnestDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + xnestCursorFuncPtr pScreenPriv; + + pScreenPriv = (xnestCursorFuncPtr) + dixLookupPrivate(&pScreen->devPrivates, xnestCursorScreenKey); + + pScreenPriv->spriteFuncs->DeviceCursorCleanup(pDev, pScreen); +} diff --git a/xorg-server/hw/xnest/Display.c b/xorg-server/hw/xnest/Display.c index 01290417c..72c640186 100644 --- a/xorg-server/hw/xnest/Display.c +++ b/xorg-server/hw/xnest/Display.c @@ -1,193 +1,193 @@ -/* - -Copyright 1993 by Davor Matic - -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. Davor Matic makes no representations about -the suitability of this software for any purpose. It is provided "as -is" without express or implied warranty. - -*/ - - -#ifdef HAVE_XNEST_CONFIG_H -#include <xnest-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "screenint.h" -#include "input.h" -#include "misc.h" -#include "scrnintstr.h" -#include "servermd.h" - -#include "Xnest.h" - -#include "Display.h" -#include "Init.h" -#include "Args.h" - -#include "icon" -#include "screensaver" - -Display *xnestDisplay = NULL; -XVisualInfo *xnestVisuals; -int xnestNumVisuals; -int xnestDefaultVisualIndex; -Colormap *xnestDefaultColormaps; -static int xnestNumDefaultColormaps; -int *xnestDepths; -int xnestNumDepths; -XPixmapFormatValues *xnestPixmapFormats; -int xnestNumPixmapFormats; -Pixel xnestBlackPixel; -Pixel xnestWhitePixel; -Drawable xnestDefaultDrawables[MAXDEPTH + 1]; -Pixmap xnestIconBitmap; -Pixmap xnestScreenSaverPixmap; -XlibGC xnestBitmapGC; -unsigned long xnestEventMask; - -void -xnestOpenDisplay(int argc, char *argv[]) -{ - XVisualInfo vi; - long mask; - int i, j; - - if (!xnestDoFullGeneration) return; - - xnestCloseDisplay(); - - xnestDisplay = XOpenDisplay(xnestDisplayName); - if (xnestDisplay == NULL) - FatalError("Unable to open display \"%s\".\n", - XDisplayName(xnestDisplayName)); - - if (xnestSynchronize) - XSynchronize(xnestDisplay, True); - - mask = VisualScreenMask; - vi.screen = DefaultScreen(xnestDisplay); - xnestVisuals = XGetVisualInfo(xnestDisplay, mask, &vi, &xnestNumVisuals); - if (xnestNumVisuals == 0 || xnestVisuals == NULL) - FatalError("Unable to find any visuals.\n"); - - if (xnestUserDefaultClass || xnestUserDefaultDepth) { - xnestDefaultVisualIndex = UNDEFINED; - for (i = 0; i < xnestNumVisuals; i++) - if ((!xnestUserDefaultClass || - xnestVisuals[i].class == xnestDefaultClass) - && - (!xnestUserDefaultDepth || - xnestVisuals[i].depth == xnestDefaultDepth)) { - xnestDefaultVisualIndex = i; - break; - } - if (xnestDefaultVisualIndex == UNDEFINED) - FatalError("Unable to find desired default visual.\n"); - } - else { - vi.visualid = XVisualIDFromVisual(DefaultVisual(xnestDisplay, - DefaultScreen(xnestDisplay))); - xnestDefaultVisualIndex = 0; - for (i = 0; i < xnestNumVisuals; i++) - if (vi.visualid == xnestVisuals[i].visualid) - xnestDefaultVisualIndex = i; - } - - xnestNumDefaultColormaps = xnestNumVisuals; - xnestDefaultColormaps = (Colormap *)xalloc(xnestNumDefaultColormaps * - sizeof(Colormap)); - for (i = 0; i < xnestNumDefaultColormaps; i++) - xnestDefaultColormaps[i] = XCreateColormap(xnestDisplay, - DefaultRootWindow(xnestDisplay), - xnestVisuals[i].visual, - AllocNone); - - xnestDepths = XListDepths(xnestDisplay, DefaultScreen(xnestDisplay), - &xnestNumDepths); - - xnestPixmapFormats = XListPixmapFormats(xnestDisplay, - &xnestNumPixmapFormats); - - xnestBlackPixel = BlackPixel(xnestDisplay, DefaultScreen(xnestDisplay)); - xnestWhitePixel = WhitePixel(xnestDisplay, DefaultScreen(xnestDisplay)); - - if (xnestParentWindow != (Window) 0) - xnestEventMask = StructureNotifyMask; - else - xnestEventMask = 0L; - - for (i = 0; i <= MAXDEPTH; i++) - xnestDefaultDrawables[i] = None; - - for (i = 0; i < xnestNumPixmapFormats; i++) - for (j = 0; j < xnestNumDepths; j++) - if (xnestPixmapFormats[i].depth == 1 || - xnestPixmapFormats[i].depth == xnestDepths[j]) { - xnestDefaultDrawables[xnestPixmapFormats[i].depth] = - XCreatePixmap(xnestDisplay, DefaultRootWindow(xnestDisplay), - 1, 1, xnestPixmapFormats[i].depth); - } - - xnestBitmapGC = XCreateGC(xnestDisplay, xnestDefaultDrawables[1], 0L, NULL); - - if (!(xnestUserGeometry & XValue)) - xnestX = 0; - - if (!(xnestUserGeometry & YValue)) - xnestY = 0; - - if (xnestParentWindow == 0) { - if (!(xnestUserGeometry & WidthValue)) - xnestWidth = 3 * DisplayWidth(xnestDisplay, - DefaultScreen(xnestDisplay)) / 4; - - if (!(xnestUserGeometry & HeightValue)) - xnestHeight = 3 * DisplayHeight(xnestDisplay, - DefaultScreen(xnestDisplay)) / 4; - } - - if (!xnestUserBorderWidth) - xnestBorderWidth = 1; - - xnestIconBitmap = - XCreateBitmapFromData(xnestDisplay, - DefaultRootWindow(xnestDisplay), - (char *)icon_bits, - icon_width, - icon_height); - - xnestScreenSaverPixmap = - XCreatePixmapFromBitmapData(xnestDisplay, - DefaultRootWindow(xnestDisplay), - (char *)screensaver_bits, - screensaver_width, - screensaver_height, - xnestWhitePixel, - xnestBlackPixel, - DefaultDepth(xnestDisplay, - DefaultScreen(xnestDisplay))); -} - -void -xnestCloseDisplay(void) -{ - if (!xnestDoFullGeneration || !xnestDisplay) return; - - /* - If xnestDoFullGeneration all x resources will be destroyed upon closing - the display connection. There is no need to generate extra protocol. - */ - - xfree(xnestDefaultColormaps); - XFree(xnestVisuals); - XFree(xnestDepths); - XFree(xnestPixmapFormats); - XCloseDisplay(xnestDisplay); -} +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "screenint.h" +#include "input.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Init.h" +#include "Args.h" + +#include "icon" +#include "screensaver" + +Display *xnestDisplay = NULL; +XVisualInfo *xnestVisuals; +int xnestNumVisuals; +int xnestDefaultVisualIndex; +Colormap *xnestDefaultColormaps; +static int xnestNumDefaultColormaps; +int *xnestDepths; +int xnestNumDepths; +XPixmapFormatValues *xnestPixmapFormats; +int xnestNumPixmapFormats; +Pixel xnestBlackPixel; +Pixel xnestWhitePixel; +Drawable xnestDefaultDrawables[MAXDEPTH + 1]; +Pixmap xnestIconBitmap; +Pixmap xnestScreenSaverPixmap; +XlibGC xnestBitmapGC; +unsigned long xnestEventMask; + +void +xnestOpenDisplay(int argc, char *argv[]) +{ + XVisualInfo vi; + long mask; + int i, j; + + if (!xnestDoFullGeneration) return; + + xnestCloseDisplay(); + + xnestDisplay = XOpenDisplay(xnestDisplayName); + if (xnestDisplay == NULL) + FatalError("Unable to open display \"%s\".\n", + XDisplayName(xnestDisplayName)); + + if (xnestSynchronize) + XSynchronize(xnestDisplay, True); + + mask = VisualScreenMask; + vi.screen = DefaultScreen(xnestDisplay); + xnestVisuals = XGetVisualInfo(xnestDisplay, mask, &vi, &xnestNumVisuals); + if (xnestNumVisuals == 0 || xnestVisuals == NULL) + FatalError("Unable to find any visuals.\n"); + + if (xnestUserDefaultClass || xnestUserDefaultDepth) { + xnestDefaultVisualIndex = UNDEFINED; + for (i = 0; i < xnestNumVisuals; i++) + if ((!xnestUserDefaultClass || + xnestVisuals[i].class == xnestDefaultClass) + && + (!xnestUserDefaultDepth || + xnestVisuals[i].depth == xnestDefaultDepth)) { + xnestDefaultVisualIndex = i; + break; + } + if (xnestDefaultVisualIndex == UNDEFINED) + FatalError("Unable to find desired default visual.\n"); + } + else { + vi.visualid = XVisualIDFromVisual(DefaultVisual(xnestDisplay, + DefaultScreen(xnestDisplay))); + xnestDefaultVisualIndex = 0; + for (i = 0; i < xnestNumVisuals; i++) + if (vi.visualid == xnestVisuals[i].visualid) + xnestDefaultVisualIndex = i; + } + + xnestNumDefaultColormaps = xnestNumVisuals; + xnestDefaultColormaps = (Colormap *)malloc(xnestNumDefaultColormaps * + sizeof(Colormap)); + for (i = 0; i < xnestNumDefaultColormaps; i++) + xnestDefaultColormaps[i] = XCreateColormap(xnestDisplay, + DefaultRootWindow(xnestDisplay), + xnestVisuals[i].visual, + AllocNone); + + xnestDepths = XListDepths(xnestDisplay, DefaultScreen(xnestDisplay), + &xnestNumDepths); + + xnestPixmapFormats = XListPixmapFormats(xnestDisplay, + &xnestNumPixmapFormats); + + xnestBlackPixel = BlackPixel(xnestDisplay, DefaultScreen(xnestDisplay)); + xnestWhitePixel = WhitePixel(xnestDisplay, DefaultScreen(xnestDisplay)); + + if (xnestParentWindow != (Window) 0) + xnestEventMask = StructureNotifyMask; + else + xnestEventMask = 0L; + + for (i = 0; i <= MAXDEPTH; i++) + xnestDefaultDrawables[i] = None; + + for (i = 0; i < xnestNumPixmapFormats; i++) + for (j = 0; j < xnestNumDepths; j++) + if (xnestPixmapFormats[i].depth == 1 || + xnestPixmapFormats[i].depth == xnestDepths[j]) { + xnestDefaultDrawables[xnestPixmapFormats[i].depth] = + XCreatePixmap(xnestDisplay, DefaultRootWindow(xnestDisplay), + 1, 1, xnestPixmapFormats[i].depth); + } + + xnestBitmapGC = XCreateGC(xnestDisplay, xnestDefaultDrawables[1], 0L, NULL); + + if (!(xnestUserGeometry & XValue)) + xnestX = 0; + + if (!(xnestUserGeometry & YValue)) + xnestY = 0; + + if (xnestParentWindow == 0) { + if (!(xnestUserGeometry & WidthValue)) + xnestWidth = 3 * DisplayWidth(xnestDisplay, + DefaultScreen(xnestDisplay)) / 4; + + if (!(xnestUserGeometry & HeightValue)) + xnestHeight = 3 * DisplayHeight(xnestDisplay, + DefaultScreen(xnestDisplay)) / 4; + } + + if (!xnestUserBorderWidth) + xnestBorderWidth = 1; + + xnestIconBitmap = + XCreateBitmapFromData(xnestDisplay, + DefaultRootWindow(xnestDisplay), + (char *)icon_bits, + icon_width, + icon_height); + + xnestScreenSaverPixmap = + XCreatePixmapFromBitmapData(xnestDisplay, + DefaultRootWindow(xnestDisplay), + (char *)screensaver_bits, + screensaver_width, + screensaver_height, + xnestWhitePixel, + xnestBlackPixel, + DefaultDepth(xnestDisplay, + DefaultScreen(xnestDisplay))); +} + +void +xnestCloseDisplay(void) +{ + if (!xnestDoFullGeneration || !xnestDisplay) return; + + /* + If xnestDoFullGeneration all x resources will be destroyed upon closing + the display connection. There is no need to generate extra protocol. + */ + + free(xnestDefaultColormaps); + XFree(xnestVisuals); + XFree(xnestDepths); + XFree(xnestPixmapFormats); + XCloseDisplay(xnestDisplay); +} diff --git a/xorg-server/hw/xnest/Font.c b/xorg-server/hw/xnest/Font.c index 7b388f0f4..87e622680 100644 --- a/xorg-server/hw/xnest/Font.c +++ b/xorg-server/hw/xnest/Font.c @@ -1,86 +1,86 @@ -/* - -Copyright 1993 by Davor Matic - -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. Davor Matic makes no representations about -the suitability of this software for any purpose. It is provided "as -is" without express or implied warranty. - -*/ - -#ifdef HAVE_XNEST_CONFIG_H -#include <xnest-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xatom.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "regionstr.h" -#include <X11/fonts/font.h> -#include <X11/fonts/fontstruct.h> -#include "scrnintstr.h" - -#include "Xnest.h" - -#include "Display.h" -#include "XNFont.h" - -int xnestFontPrivateIndex; - -Bool -xnestRealizeFont(ScreenPtr pScreen, FontPtr pFont) -{ - pointer priv; - Atom name_atom, value_atom; - int nprops; - FontPropPtr props; - int i; - const char *name; - - FontSetPrivate(pFont, xnestFontPrivateIndex, NULL); - - name_atom = MakeAtom("FONT", 4, True); - value_atom = 0L; - - nprops = pFont->info.nprops; - props = pFont->info.props; - - for (i = 0; i < nprops; i++) - if (props[i].name == name_atom) { - value_atom = props[i].value; - break; - } - - if (!value_atom) return False; - - name = NameForAtom(value_atom); - - if (!name) return False; - - priv = (pointer)xalloc(sizeof(xnestPrivFont)); - FontSetPrivate(pFont, xnestFontPrivateIndex, priv); - - xnestFontPriv(pFont)->font_struct = XLoadQueryFont(xnestDisplay, name); - - if (!xnestFontStruct(pFont)) return False; - - return True; -} - - -Bool -xnestUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) -{ - if (xnestFontPriv(pFont)) { - if (xnestFontStruct(pFont)) - XFreeFont(xnestDisplay, xnestFontStruct(pFont)); - xfree(xnestFontPriv(pFont)); - FontSetPrivate(pFont, xnestFontPrivateIndex, NULL); - } - return True; -} +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xatom.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "regionstr.h" +#include <X11/fonts/font.h> +#include <X11/fonts/fontstruct.h> +#include "scrnintstr.h" + +#include "Xnest.h" + +#include "Display.h" +#include "XNFont.h" + +int xnestFontPrivateIndex; + +Bool +xnestRealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + pointer priv; + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + const char *name; + + FontSetPrivate(pFont, xnestFontPrivateIndex, NULL); + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if (props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return False; + + name = NameForAtom(value_atom); + + if (!name) return False; + + priv = (pointer)malloc(sizeof(xnestPrivFont)); + FontSetPrivate(pFont, xnestFontPrivateIndex, priv); + + xnestFontPriv(pFont)->font_struct = XLoadQueryFont(xnestDisplay, name); + + if (!xnestFontStruct(pFont)) return False; + + return True; +} + + +Bool +xnestUnrealizeFont(ScreenPtr pScreen, FontPtr pFont) +{ + if (xnestFontPriv(pFont)) { + if (xnestFontStruct(pFont)) + XFreeFont(xnestDisplay, xnestFontStruct(pFont)); + free(xnestFontPriv(pFont)); + FontSetPrivate(pFont, xnestFontPrivateIndex, NULL); + } + return True; +} diff --git a/xorg-server/hw/xnest/GC.c b/xorg-server/hw/xnest/GC.c index 65425e98f..9df015728 100644 --- a/xorg-server/hw/xnest/GC.c +++ b/xorg-server/hw/xnest/GC.c @@ -1,339 +1,339 @@ -/* - -Copyright 1993 by Davor Matic - -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. Davor Matic makes no representations about -the suitability of this software for any purpose. It is provided "as -is" without express or implied warranty. - -*/ - -#ifdef HAVE_XNEST_CONFIG_H -#include <xnest-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "gcstruct.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "scrnintstr.h" -#include <X11/fonts/fontstruct.h> -#include "mistruct.h" -#include "region.h" - -#include "Xnest.h" - -#include "Display.h" -#include "XNGC.h" -#include "GCOps.h" -#include "Drawable.h" -#include "XNFont.h" -#include "Color.h" - -static int xnestGCPrivateKeyIndex; -DevPrivateKey xnestGCPrivateKey = &xnestGCPrivateKeyIndex; - -static GCFuncs xnestFuncs = { - xnestValidateGC, - xnestChangeGC, - xnestCopyGC, - xnestDestroyGC, - xnestChangeClip, - xnestDestroyClip, - xnestCopyClip, -}; - -static GCOps xnestOps = { - xnestFillSpans, - xnestSetSpans, - xnestPutImage, - xnestCopyArea, - xnestCopyPlane, - xnestPolyPoint, - xnestPolylines, - xnestPolySegment, - xnestPolyRectangle, - xnestPolyArc, - xnestFillPolygon, - xnestPolyFillRect, - xnestPolyFillArc, - xnestPolyText8, - xnestPolyText16, - xnestImageText8, - xnestImageText16, - xnestImageGlyphBlt, - xnestPolyGlyphBlt, - xnestPushPixels -}; - -Bool -xnestCreateGC(GCPtr pGC) -{ - pGC->clientClipType = CT_NONE; - pGC->clientClip = NULL; - - pGC->funcs = &xnestFuncs; - pGC->ops = &xnestOps; - - pGC->miTranslate = 1; - - xnestGCPriv(pGC)->gc = XCreateGC(xnestDisplay, - xnestDefaultDrawables[pGC->depth], - 0L, NULL); - xnestGCPriv(pGC)->nClipRects = 0; - - return True; -} - -void -xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) -{ - pGC->lastWinOrg.x = pDrawable->x; - pGC->lastWinOrg.y = pDrawable->y; -} - -void -xnestChangeGC(GCPtr pGC, unsigned long mask) -{ - XGCValues values; - - if (mask & GCFunction) - values.function = pGC->alu; - - if (mask & GCPlaneMask) - values.plane_mask = pGC->planemask; - - if (mask & GCForeground) - values.foreground = xnestPixel(pGC->fgPixel); - - if (mask & GCBackground) - values.background = xnestPixel(pGC->bgPixel); - - if (mask & GCLineWidth) - values.line_width = pGC->lineWidth; - - if (mask & GCLineStyle) - values.line_style = pGC->lineStyle; - - if (mask & GCCapStyle) - values.cap_style = pGC->capStyle; - - if (mask & GCJoinStyle) - values.join_style = pGC->joinStyle; - - if (mask & GCFillStyle) - values.fill_style = pGC->fillStyle; - - if (mask & GCFillRule) - values.fill_rule = pGC->fillRule; - - if (mask & GCTile) { - if (pGC->tileIsPixel) - mask &= ~GCTile; - else - values.tile = xnestPixmap(pGC->tile.pixmap); - } - - if (mask & GCStipple) - values.stipple = xnestPixmap(pGC->stipple); - - if (mask & GCTileStipXOrigin) - values.ts_x_origin = pGC->patOrg.x; - - if (mask & GCTileStipYOrigin) - values.ts_y_origin = pGC->patOrg.y; - - if (mask & GCFont) - values.font = xnestFont(pGC->font); - - if (mask & GCSubwindowMode) - values.subwindow_mode = pGC->subWindowMode; - - if (mask & GCGraphicsExposures) - values.graphics_exposures = pGC->graphicsExposures; - - if (mask & GCClipXOrigin) - values.clip_x_origin = pGC->clipOrg.x; - - if (mask & GCClipYOrigin) - values.clip_y_origin = pGC->clipOrg.y; - - if (mask & GCClipMask) /* this is handled in change clip */ - mask &= ~GCClipMask; - - if (mask & GCDashOffset) - values.dash_offset = pGC->dashOffset; - - if (mask & GCDashList) { - mask &= ~GCDashList; - XSetDashes(xnestDisplay, xnestGC(pGC), - pGC->dashOffset, (char *)pGC->dash, pGC->numInDashList); - } - - if (mask & GCArcMode) - values.arc_mode = pGC->arcMode; - - if (mask) - XChangeGC(xnestDisplay, xnestGC(pGC), mask, &values); -} - -void -xnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) -{ - XCopyGC(xnestDisplay, xnestGC(pGCSrc), mask, xnestGC(pGCDst)); -} - -void -xnestDestroyGC(GCPtr pGC) -{ - XFreeGC(xnestDisplay, xnestGC(pGC)); -} - -void -xnestChangeClip(GCPtr pGC, int type, pointer pValue, int nRects) -{ - int i, size; - BoxPtr pBox; - XRectangle *pRects; - - xnestDestroyClipHelper(pGC); - - switch(type) - { - case CT_NONE: - XSetClipMask(xnestDisplay, xnestGC(pGC), None); - break; - - case CT_REGION: - nRects = REGION_NUM_RECTS((RegionPtr)pValue); - size = nRects * sizeof(*pRects); - pRects = (XRectangle *) xalloc(size); - pBox = REGION_RECTS((RegionPtr)pValue); - for (i = nRects; i-- > 0; ) { - pRects[i].x = pBox[i].x1; - pRects[i].y = pBox[i].y1; - pRects[i].width = pBox[i].x2 - pBox[i].x1; - pRects[i].height = pBox[i].y2 - pBox[i].y1; - } - XSetClipRectangles(xnestDisplay, xnestGC(pGC), 0, 0, - pRects, nRects, Unsorted); - xfree((char *) pRects); - break; - - case CT_PIXMAP: - XSetClipMask(xnestDisplay, xnestGC(pGC), - xnestPixmap((PixmapPtr)pValue)); - /* - * Need to change into region, so subsequent uses are with - * current pixmap contents. - */ - pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr)pValue); - (*pGC->pScreen->DestroyPixmap)((PixmapPtr)pValue); - pValue = pGC->clientClip; - type = CT_REGION; - break; - - case CT_UNSORTED: - XSetClipRectangles(xnestDisplay, xnestGC(pGC), - pGC->clipOrg.x, pGC->clipOrg.y, - (XRectangle *)pValue, nRects, Unsorted); - break; - - case CT_YSORTED: - XSetClipRectangles(xnestDisplay, xnestGC(pGC), - pGC->clipOrg.x, pGC->clipOrg.y, - (XRectangle *)pValue, nRects, YSorted); - break; - - case CT_YXSORTED: - XSetClipRectangles(xnestDisplay, xnestGC(pGC), - pGC->clipOrg.x, pGC->clipOrg.y, - (XRectangle *)pValue, nRects, YXSorted); - break; - - case CT_YXBANDED: - XSetClipRectangles(xnestDisplay, xnestGC(pGC), - pGC->clipOrg.x, pGC->clipOrg.y, - (XRectangle *)pValue, nRects, YXBanded); - break; - } - - switch(type) - { - default: - break; - - case CT_UNSORTED: - case CT_YSORTED: - case CT_YXSORTED: - case CT_YXBANDED: - - /* - * other parts of server can only deal with CT_NONE, - * CT_PIXMAP and CT_REGION client clips. - */ - pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nRects, - (xRectangle *)pValue, type); - xfree(pValue); - pValue = pGC->clientClip; - type = CT_REGION; - - break; - } - - pGC->clientClipType = type; - pGC->clientClip = pValue; - xnestGCPriv(pGC)->nClipRects = nRects; -} - -void -xnestDestroyClip(GCPtr pGC) -{ - xnestDestroyClipHelper(pGC); - - XSetClipMask(xnestDisplay, xnestGC(pGC), None); - - pGC->clientClipType = CT_NONE; - pGC->clientClip = NULL; - xnestGCPriv(pGC)->nClipRects = 0; -} - -void -xnestDestroyClipHelper(GCPtr pGC) -{ - switch (pGC->clientClipType) - { - default: - case CT_NONE: - break; - - case CT_REGION: - REGION_DESTROY(pGC->pScreen, pGC->clientClip); - break; - } -} - -void -xnestCopyClip(GCPtr pGCDst, GCPtr pGCSrc) -{ - RegionPtr pRgn; - - switch (pGCSrc->clientClipType) - { - default: - case CT_NONE: - xnestDestroyClip(pGCDst); - break; - - case CT_REGION: - pRgn = REGION_CREATE(pGCDst->pScreen, NULL, 1); - REGION_COPY(pGCDst->pScreen, pRgn, pGCSrc->clientClip); - xnestChangeClip(pGCDst, CT_REGION, pRgn, 0); - break; - } -} +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include <X11/fonts/fontstruct.h> +#include "mistruct.h" +#include "region.h" + +#include "Xnest.h" + +#include "Display.h" +#include "XNGC.h" +#include "GCOps.h" +#include "Drawable.h" +#include "XNFont.h" +#include "Color.h" + +static int xnestGCPrivateKeyIndex; +DevPrivateKey xnestGCPrivateKey = &xnestGCPrivateKeyIndex; + +static GCFuncs xnestFuncs = { + xnestValidateGC, + xnestChangeGC, + xnestCopyGC, + xnestDestroyGC, + xnestChangeClip, + xnestDestroyClip, + xnestCopyClip, +}; + +static GCOps xnestOps = { + xnestFillSpans, + xnestSetSpans, + xnestPutImage, + xnestCopyArea, + xnestCopyPlane, + xnestPolyPoint, + xnestPolylines, + xnestPolySegment, + xnestPolyRectangle, + xnestPolyArc, + xnestFillPolygon, + xnestPolyFillRect, + xnestPolyFillArc, + xnestPolyText8, + xnestPolyText16, + xnestImageText8, + xnestImageText16, + xnestImageGlyphBlt, + xnestPolyGlyphBlt, + xnestPushPixels +}; + +Bool +xnestCreateGC(GCPtr pGC) +{ + pGC->clientClipType = CT_NONE; + pGC->clientClip = NULL; + + pGC->funcs = &xnestFuncs; + pGC->ops = &xnestOps; + + pGC->miTranslate = 1; + + xnestGCPriv(pGC)->gc = XCreateGC(xnestDisplay, + xnestDefaultDrawables[pGC->depth], + 0L, NULL); + xnestGCPriv(pGC)->nClipRects = 0; + + return True; +} + +void +xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + pGC->lastWinOrg.x = pDrawable->x; + pGC->lastWinOrg.y = pDrawable->y; +} + +void +xnestChangeGC(GCPtr pGC, unsigned long mask) +{ + XGCValues values; + + if (mask & GCFunction) + values.function = pGC->alu; + + if (mask & GCPlaneMask) + values.plane_mask = pGC->planemask; + + if (mask & GCForeground) + values.foreground = xnestPixel(pGC->fgPixel); + + if (mask & GCBackground) + values.background = xnestPixel(pGC->bgPixel); + + if (mask & GCLineWidth) + values.line_width = pGC->lineWidth; + + if (mask & GCLineStyle) + values.line_style = pGC->lineStyle; + + if (mask & GCCapStyle) + values.cap_style = pGC->capStyle; + + if (mask & GCJoinStyle) + values.join_style = pGC->joinStyle; + + if (mask & GCFillStyle) + values.fill_style = pGC->fillStyle; + + if (mask & GCFillRule) + values.fill_rule = pGC->fillRule; + + if (mask & GCTile) { + if (pGC->tileIsPixel) + mask &= ~GCTile; + else + values.tile = xnestPixmap(pGC->tile.pixmap); + } + + if (mask & GCStipple) + values.stipple = xnestPixmap(pGC->stipple); + + if (mask & GCTileStipXOrigin) + values.ts_x_origin = pGC->patOrg.x; + + if (mask & GCTileStipYOrigin) + values.ts_y_origin = pGC->patOrg.y; + + if (mask & GCFont) + values.font = xnestFont(pGC->font); + + if (mask & GCSubwindowMode) + values.subwindow_mode = pGC->subWindowMode; + + if (mask & GCGraphicsExposures) + values.graphics_exposures = pGC->graphicsExposures; + + if (mask & GCClipXOrigin) + values.clip_x_origin = pGC->clipOrg.x; + + if (mask & GCClipYOrigin) + values.clip_y_origin = pGC->clipOrg.y; + + if (mask & GCClipMask) /* this is handled in change clip */ + mask &= ~GCClipMask; + + if (mask & GCDashOffset) + values.dash_offset = pGC->dashOffset; + + if (mask & GCDashList) { + mask &= ~GCDashList; + XSetDashes(xnestDisplay, xnestGC(pGC), + pGC->dashOffset, (char *)pGC->dash, pGC->numInDashList); + } + + if (mask & GCArcMode) + values.arc_mode = pGC->arcMode; + + if (mask) + XChangeGC(xnestDisplay, xnestGC(pGC), mask, &values); +} + +void +xnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ + XCopyGC(xnestDisplay, xnestGC(pGCSrc), mask, xnestGC(pGCDst)); +} + +void +xnestDestroyGC(GCPtr pGC) +{ + XFreeGC(xnestDisplay, xnestGC(pGC)); +} + +void +xnestChangeClip(GCPtr pGC, int type, pointer pValue, int nRects) +{ + int i, size; + BoxPtr pBox; + XRectangle *pRects; + + xnestDestroyClipHelper(pGC); + + switch(type) + { + case CT_NONE: + XSetClipMask(xnestDisplay, xnestGC(pGC), None); + break; + + case CT_REGION: + nRects = REGION_NUM_RECTS((RegionPtr)pValue); + size = nRects * sizeof(*pRects); + pRects = (XRectangle *) malloc(size); + pBox = REGION_RECTS((RegionPtr)pValue); + for (i = nRects; i-- > 0; ) { + pRects[i].x = pBox[i].x1; + pRects[i].y = pBox[i].y1; + pRects[i].width = pBox[i].x2 - pBox[i].x1; + pRects[i].height = pBox[i].y2 - pBox[i].y1; + } + XSetClipRectangles(xnestDisplay, xnestGC(pGC), 0, 0, + pRects, nRects, Unsorted); + free((char *) pRects); + break; + + case CT_PIXMAP: + XSetClipMask(xnestDisplay, xnestGC(pGC), + xnestPixmap((PixmapPtr)pValue)); + /* + * Need to change into region, so subsequent uses are with + * current pixmap contents. + */ + pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr)pValue); + (*pGC->pScreen->DestroyPixmap)((PixmapPtr)pValue); + pValue = pGC->clientClip; + type = CT_REGION; + break; + + case CT_UNSORTED: + XSetClipRectangles(xnestDisplay, xnestGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, Unsorted); + break; + + case CT_YSORTED: + XSetClipRectangles(xnestDisplay, xnestGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YSorted); + break; + + case CT_YXSORTED: + XSetClipRectangles(xnestDisplay, xnestGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YXSorted); + break; + + case CT_YXBANDED: + XSetClipRectangles(xnestDisplay, xnestGC(pGC), + pGC->clipOrg.x, pGC->clipOrg.y, + (XRectangle *)pValue, nRects, YXBanded); + break; + } + + switch(type) + { + default: + break; + + case CT_UNSORTED: + case CT_YSORTED: + case CT_YXSORTED: + case CT_YXBANDED: + + /* + * other parts of server can only deal with CT_NONE, + * CT_PIXMAP and CT_REGION client clips. + */ + pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nRects, + (xRectangle *)pValue, type); + free(pValue); + pValue = pGC->clientClip; + type = CT_REGION; + + break; + } + + pGC->clientClipType = type; + pGC->clientClip = pValue; + xnestGCPriv(pGC)->nClipRects = nRects; +} + +void +xnestDestroyClip(GCPtr pGC) +{ + xnestDestroyClipHelper(pGC); + + XSetClipMask(xnestDisplay, xnestGC(pGC), None); + + pGC->clientClipType = CT_NONE; + pGC->clientClip = NULL; + xnestGCPriv(pGC)->nClipRects = 0; +} + +void +xnestDestroyClipHelper(GCPtr pGC) +{ + switch (pGC->clientClipType) + { + default: + case CT_NONE: + break; + + case CT_REGION: + REGION_DESTROY(pGC->pScreen, pGC->clientClip); + break; + } +} + +void +xnestCopyClip(GCPtr pGCDst, GCPtr pGCSrc) +{ + RegionPtr pRgn; + + switch (pGCSrc->clientClipType) + { + default: + case CT_NONE: + xnestDestroyClip(pGCDst); + break; + + case CT_REGION: + pRgn = REGION_CREATE(pGCDst->pScreen, NULL, 1); + REGION_COPY(pGCDst->pScreen, pRgn, pGCSrc->clientClip); + xnestChangeClip(pGCDst, CT_REGION, pRgn, 0); + break; + } +} diff --git a/xorg-server/hw/xnest/Keyboard.c b/xorg-server/hw/xnest/Keyboard.c index 1835c7071..473724a04 100644 --- a/xorg-server/hw/xnest/Keyboard.c +++ b/xorg-server/hw/xnest/Keyboard.c @@ -1,257 +1,257 @@ -/* - -Copyright 1993 by Davor Matic - -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. Davor Matic makes no representations about -the suitability of this software for any purpose. It is provided "as -is" without express or implied warranty. - -*/ - -#ifdef HAVE_XNEST_CONFIG_H -#include <xnest-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/keysym.h> -#include "screenint.h" -#include "inputstr.h" -#include "misc.h" -#include "scrnintstr.h" -#include "servermd.h" - -#include "Xnest.h" - -#include "Display.h" -#include "Screen.h" -#include "Keyboard.h" -#include "Args.h" -#include "Events.h" - -#include <X11/extensions/XKB.h> -#include "xkbsrv.h" -#include <X11/extensions/XKBconfig.h> - -extern Bool -XkbQueryExtension( - Display * /* dpy */, - int * /* opcodeReturn */, - int * /* eventBaseReturn */, - int * /* errorBaseReturn */, - int * /* majorRtrn */, - int * /* minorRtrn */ -); - -extern XkbDescPtr XkbGetKeyboard( - Display * /* dpy */, - unsigned int /* which */, - unsigned int /* deviceSpec */ -); - -extern Status XkbGetControls( - Display * /* dpy */, - unsigned long /* which */, - XkbDescPtr /* desc */ -); - -DeviceIntPtr xnestKeyboardDevice = NULL; - -void -xnestBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls) -{ - XBell(xnestDisplay, volume); -} - -void -DDXRingBell(int volume, int pitch, int duration) -{ - XBell(xnestDisplay, volume); -} - -void -xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) -{ -#if 0 - unsigned long value_mask; - XKeyboardControl values; - int i; - - value_mask = KBKeyClickPercent | - KBBellPercent | - KBBellPitch | - KBBellDuration | - KBAutoRepeatMode; - - values.key_click_percent = ctrl->click; - values.bell_percent = ctrl->bell; - values.bell_pitch = ctrl->bell_pitch; - values.bell_duration = ctrl->bell_duration; - values.auto_repeat_mode = ctrl->autoRepeat ? - AutoRepeatModeOn : AutoRepeatModeOff; - - XChangeKeyboardControl(xnestDisplay, value_mask, &values); - - /* - value_mask = KBKey | KBAutoRepeatMode; - At this point, we need to walk through the vector and compare it - to the current server vector. If there are differences, report them. - */ - - value_mask = KBLed | KBLedMode; - for (i = 1; i <= 32; i++) { - values.led = i; - values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff; - XChangeKeyboardControl(xnestDisplay, value_mask, &values); - } -#endif -} - -int -xnestKeyboardProc(DeviceIntPtr pDev, int onoff) -{ - KeySym *keymap; - int mapWidth; - int min_keycode, max_keycode; - KeySymsRec keySyms; - int i; - XKeyboardState values; - XkbDescPtr xkb; - int op, event, error, major, minor; - - switch (onoff) - { - case DEVICE_INIT: - XDisplayKeycodes(xnestDisplay, &min_keycode, &max_keycode); -#ifdef _XSERVER64 - { - KeySym64 *keymap64; - int i, len; - keymap64 = XGetKeyboardMapping(xnestDisplay, - min_keycode, - max_keycode - min_keycode + 1, - &mapWidth); - len = (max_keycode - min_keycode + 1) * mapWidth; - keymap = (KeySym *)xalloc(len * sizeof(KeySym)); - for(i = 0; i < len; ++i) - keymap[i] = keymap64[i]; - XFree(keymap64); - } -#else - keymap = XGetKeyboardMapping(xnestDisplay, - min_keycode, - max_keycode - min_keycode + 1, - &mapWidth); -#endif - - keySyms.minKeyCode = min_keycode; - keySyms.maxKeyCode = max_keycode; - keySyms.mapWidth = mapWidth; - keySyms.map = keymap; - - if (XkbQueryExtension(xnestDisplay, &op, &event, &error, &major, &minor) == 0) { - ErrorF("Unable to initialize XKEYBOARD extension.\n"); - goto XkbError; - } - xkb = XkbGetKeyboard(xnestDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd); - if (xkb == NULL || xkb->geom == NULL) { - ErrorF("Couldn't get keyboard.\n"); - goto XkbError; - } - XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb); - - InitKeyboardDeviceStruct(pDev, NULL, - xnestBell, xnestChangeKeyboardControl); - XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls); - XkbFreeKeyboard(xkb, 0, False); - xfree(keymap); - break; - case DEVICE_ON: - xnestEventMask |= XNEST_KEYBOARD_EVENT_MASK; - for (i = 0; i < xnestNumScreens; i++) - XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask); - break; - case DEVICE_OFF: - xnestEventMask &= ~XNEST_KEYBOARD_EVENT_MASK; - for (i = 0; i < xnestNumScreens; i++) - XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask); - break; - case DEVICE_CLOSE: - break; - } - return Success; - -XkbError: - XGetKeyboardControl(xnestDisplay, &values); - memmove((char *)defaultKeyboardControl.autoRepeats, - (char *)values.auto_repeats, - sizeof(values.auto_repeats)); - - InitKeyboardDeviceStruct(pDev, NULL, - xnestBell, xnestChangeKeyboardControl); - xfree(keymap); - return Success; -} - -Bool -LegalModifier(unsigned int key, DeviceIntPtr pDev) -{ - return TRUE; -} - -void -xnestUpdateModifierState(unsigned int state) -{ - DeviceIntPtr pDev = xnestKeyboardDevice; - KeyClassPtr keyc = pDev->key; - int i; - CARD8 mask; - int xkb_state; - - if (!pDev) - return; - - xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state); - state = state & 0xff; - - if (xkb_state == state) - return; - - for (i = 0, mask = 1; i < 8; i++, mask <<= 1) { - int key; - - /* Modifier is down, but shouldn't be - */ - if ((xkb_state & mask) && !(state & mask)) { - int count = keyc->modifierKeyCount[i]; - - for (key = 0; key < MAP_LENGTH; key++) - if (keyc->xkbInfo->desc->map->modmap[key] & mask) { - int bit; - BYTE *kptr; - - kptr = &keyc->down[key >> 3]; - bit = 1 << (key & 7); - - if (*kptr & bit) - xnestQueueKeyEvent(KeyRelease, key); - - if (--count == 0) - break; - } - } - - /* Modifier shoud be down, but isn't - */ - if (!(xkb_state & mask) && (state & mask)) - for (key = 0; key < MAP_LENGTH; key++) - if (keyc->xkbInfo->desc->map->modmap[key] & mask) { - xnestQueueKeyEvent(KeyPress, key); - break; - } - } -} +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include "screenint.h" +#include "inputstr.h" +#include "misc.h" +#include "scrnintstr.h" +#include "servermd.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "Keyboard.h" +#include "Args.h" +#include "Events.h" + +#include <X11/extensions/XKB.h> +#include "xkbsrv.h" +#include <X11/extensions/XKBconfig.h> + +extern Bool +XkbQueryExtension( + Display * /* dpy */, + int * /* opcodeReturn */, + int * /* eventBaseReturn */, + int * /* errorBaseReturn */, + int * /* majorRtrn */, + int * /* minorRtrn */ +); + +extern XkbDescPtr XkbGetKeyboard( + Display * /* dpy */, + unsigned int /* which */, + unsigned int /* deviceSpec */ +); + +extern Status XkbGetControls( + Display * /* dpy */, + unsigned long /* which */, + XkbDescPtr /* desc */ +); + +DeviceIntPtr xnestKeyboardDevice = NULL; + +void +xnestBell(int volume, DeviceIntPtr pDev, pointer ctrl, int cls) +{ + XBell(xnestDisplay, volume); +} + +void +DDXRingBell(int volume, int pitch, int duration) +{ + XBell(xnestDisplay, volume); +} + +void +xnestChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) +{ +#if 0 + unsigned long value_mask; + XKeyboardControl values; + int i; + + value_mask = KBKeyClickPercent | + KBBellPercent | + KBBellPitch | + KBBellDuration | + KBAutoRepeatMode; + + values.key_click_percent = ctrl->click; + values.bell_percent = ctrl->bell; + values.bell_pitch = ctrl->bell_pitch; + values.bell_duration = ctrl->bell_duration; + values.auto_repeat_mode = ctrl->autoRepeat ? + AutoRepeatModeOn : AutoRepeatModeOff; + + XChangeKeyboardControl(xnestDisplay, value_mask, &values); + + /* + value_mask = KBKey | KBAutoRepeatMode; + At this point, we need to walk through the vector and compare it + to the current server vector. If there are differences, report them. + */ + + value_mask = KBLed | KBLedMode; + for (i = 1; i <= 32; i++) { + values.led = i; + values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff; + XChangeKeyboardControl(xnestDisplay, value_mask, &values); + } +#endif +} + +int +xnestKeyboardProc(DeviceIntPtr pDev, int onoff) +{ + KeySym *keymap; + int mapWidth; + int min_keycode, max_keycode; + KeySymsRec keySyms; + int i; + XKeyboardState values; + XkbDescPtr xkb; + int op, event, error, major, minor; + + switch (onoff) + { + case DEVICE_INIT: + XDisplayKeycodes(xnestDisplay, &min_keycode, &max_keycode); +#ifdef _XSERVER64 + { + KeySym64 *keymap64; + int i, len; + keymap64 = XGetKeyboardMapping(xnestDisplay, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); + len = (max_keycode - min_keycode + 1) * mapWidth; + keymap = (KeySym *)malloc(len * sizeof(KeySym)); + for(i = 0; i < len; ++i) + keymap[i] = keymap64[i]; + XFree(keymap64); + } +#else + keymap = XGetKeyboardMapping(xnestDisplay, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); +#endif + + keySyms.minKeyCode = min_keycode; + keySyms.maxKeyCode = max_keycode; + keySyms.mapWidth = mapWidth; + keySyms.map = keymap; + + if (XkbQueryExtension(xnestDisplay, &op, &event, &error, &major, &minor) == 0) { + ErrorF("Unable to initialize XKEYBOARD extension.\n"); + goto XkbError; + } + xkb = XkbGetKeyboard(xnestDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd); + if (xkb == NULL || xkb->geom == NULL) { + ErrorF("Couldn't get keyboard.\n"); + goto XkbError; + } + XkbGetControls(xnestDisplay, XkbAllControlsMask, xkb); + + InitKeyboardDeviceStruct(pDev, NULL, + xnestBell, xnestChangeKeyboardControl); + XkbDDXChangeControls(pDev, xkb->ctrls, xkb->ctrls); + XkbFreeKeyboard(xkb, 0, False); + free(keymap); + break; + case DEVICE_ON: + xnestEventMask |= XNEST_KEYBOARD_EVENT_MASK; + for (i = 0; i < xnestNumScreens; i++) + XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask); + break; + case DEVICE_OFF: + xnestEventMask &= ~XNEST_KEYBOARD_EVENT_MASK; + for (i = 0; i < xnestNumScreens; i++) + XSelectInput(xnestDisplay, xnestDefaultWindows[i], xnestEventMask); + break; + case DEVICE_CLOSE: + break; + } + return Success; + +XkbError: + XGetKeyboardControl(xnestDisplay, &values); + memmove((char *)defaultKeyboardControl.autoRepeats, + (char *)values.auto_repeats, + sizeof(values.auto_repeats)); + + InitKeyboardDeviceStruct(pDev, NULL, + xnestBell, xnestChangeKeyboardControl); + free(keymap); + return Success; +} + +Bool +LegalModifier(unsigned int key, DeviceIntPtr pDev) +{ + return TRUE; +} + +void +xnestUpdateModifierState(unsigned int state) +{ + DeviceIntPtr pDev = xnestKeyboardDevice; + KeyClassPtr keyc = pDev->key; + int i; + CARD8 mask; + int xkb_state; + + if (!pDev) + return; + + xkb_state = XkbStateFieldFromRec(&pDev->key->xkbInfo->state); + state = state & 0xff; + + if (xkb_state == state) + return; + + for (i = 0, mask = 1; i < 8; i++, mask <<= 1) { + int key; + + /* Modifier is down, but shouldn't be + */ + if ((xkb_state & mask) && !(state & mask)) { + int count = keyc->modifierKeyCount[i]; + + for (key = 0; key < MAP_LENGTH; key++) + if (keyc->xkbInfo->desc->map->modmap[key] & mask) { + int bit; + BYTE *kptr; + + kptr = &keyc->down[key >> 3]; + bit = 1 << (key & 7); + + if (*kptr & bit) + xnestQueueKeyEvent(KeyRelease, key); + + if (--count == 0) + break; + } + } + + /* Modifier shoud be down, but isn't + */ + if (!(xkb_state & mask) && (state & mask)) + for (key = 0; key < MAP_LENGTH; key++) + if (keyc->xkbInfo->desc->map->modmap[key] & mask) { + xnestQueueKeyEvent(KeyPress, key); + break; + } + } +} diff --git a/xorg-server/hw/xnest/Pixmap.c b/xorg-server/hw/xnest/Pixmap.c index 676a2ba95..cd2245b46 100644 --- a/xorg-server/hw/xnest/Pixmap.c +++ b/xorg-server/hw/xnest/Pixmap.c @@ -1,141 +1,141 @@ -/* - -Copyright 1993 by Davor Matic - -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. Davor Matic makes no representations about -the suitability of this software for any purpose. It is provided "as -is" without express or implied warranty. - -*/ - -#ifdef HAVE_XNEST_CONFIG_H -#include <xnest-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "regionstr.h" -#include "pixmapstr.h" -#include "scrnintstr.h" -#include "regionstr.h" -#include "gc.h" -#include "servermd.h" -#include "privates.h" -#include "mi.h" - -#include "Xnest.h" - -#include "Display.h" -#include "Screen.h" -#include "XNPixmap.h" - -static int xnestPixmapPrivateKeyIndex; -DevPrivateKey xnestPixmapPrivateKey = &xnestPixmapPrivateKeyIndex; - -PixmapPtr -xnestCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, - unsigned usage_hint) -{ - PixmapPtr pPixmap; - - pPixmap = AllocatePixmap(pScreen, sizeof(xnestPrivPixmap)); - if (!pPixmap) - return NullPixmap; - pPixmap->drawable.type = DRAWABLE_PIXMAP; - pPixmap->drawable.class = 0; - pPixmap->drawable.depth = depth; - pPixmap->drawable.bitsPerPixel = depth; - pPixmap->drawable.id = 0; - pPixmap->drawable.x = 0; - pPixmap->drawable.y = 0; - pPixmap->drawable.width = width; - pPixmap->drawable.height = height; - pPixmap->drawable.pScreen = pScreen; - pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - pPixmap->refcnt = 1; - pPixmap->devKind = PixmapBytePad(width, depth); - pPixmap->usage_hint = usage_hint; - dixSetPrivate(&pPixmap->devPrivates, xnestPixmapPrivateKey, - (char *)pPixmap + pScreen->totalPixmapSize); - if (width && height) - xnestPixmapPriv(pPixmap)->pixmap = - XCreatePixmap(xnestDisplay, - xnestDefaultWindows[pScreen->myNum], - width, height, depth); - else - xnestPixmapPriv(pPixmap)->pixmap = 0; - - return pPixmap; -} - -Bool -xnestDestroyPixmap(PixmapPtr pPixmap) -{ - if(--pPixmap->refcnt) - return TRUE; - XFreePixmap(xnestDisplay, xnestPixmap(pPixmap)); - dixFreePrivates(pPixmap->devPrivates); - xfree(pPixmap); - return TRUE; -} - -RegionPtr -xnestPixmapToRegion(PixmapPtr pPixmap) -{ - XImage *ximage; - register RegionPtr pReg, pTmpReg; - register int x, y; - unsigned long previousPixel, currentPixel; - BoxRec Box = { 0, 0, 0, 0 }; - Bool overlap; - - ximage = XGetImage(xnestDisplay, xnestPixmap(pPixmap), 0, 0, - pPixmap->drawable.width, pPixmap->drawable.height, - 1, XYPixmap); - - pReg = REGION_CREATE(pPixmap->drawable.pScreen, NULL, 1); - pTmpReg = REGION_CREATE(pPixmap->drawable.pScreen, NULL, 1); - if(!pReg || !pTmpReg) { - XDestroyImage(ximage); - return NullRegion; - } - - for (y = 0; y < pPixmap->drawable.height; y++) { - Box.y1 = y; - Box.y2 = y + 1; - previousPixel = 0L; - for (x = 0; x < pPixmap->drawable.width; x++) { - currentPixel = XGetPixel(ximage, x, y); - if (previousPixel != currentPixel) { - if (previousPixel == 0L) { - /* left edge */ - Box.x1 = x; - } - else if (currentPixel == 0L) { - /* right edge */ - Box.x2 = x; - REGION_RESET(pPixmap->drawable.pScreen, pTmpReg, &Box); - REGION_APPEND(pPixmap->drawable.pScreen, pReg, pTmpReg); - } - previousPixel = currentPixel; - } - } - if (previousPixel != 0L) { - /* right edge because of the end of pixmap */ - Box.x2 = pPixmap->drawable.width; - REGION_RESET(pPixmap->drawable.pScreen, pTmpReg, &Box); - REGION_APPEND(pPixmap->drawable.pScreen, pReg, pTmpReg); - } - } - - REGION_DESTROY(pPixmap->drawable.pScreen, pTmpReg); - XDestroyImage(ximage); - - REGION_VALIDATE(pPixmap->drawable.pScreen, pReg, &overlap); - - return(pReg); -} +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "regionstr.h" +#include "pixmapstr.h" +#include "scrnintstr.h" +#include "regionstr.h" +#include "gc.h" +#include "servermd.h" +#include "privates.h" +#include "mi.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "XNPixmap.h" + +static int xnestPixmapPrivateKeyIndex; +DevPrivateKey xnestPixmapPrivateKey = &xnestPixmapPrivateKeyIndex; + +PixmapPtr +xnestCreatePixmap(ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint) +{ + PixmapPtr pPixmap; + + pPixmap = AllocatePixmap(pScreen, sizeof(xnestPrivPixmap)); + if (!pPixmap) + return NullPixmap; + pPixmap->drawable.type = DRAWABLE_PIXMAP; + pPixmap->drawable.class = 0; + pPixmap->drawable.depth = depth; + pPixmap->drawable.bitsPerPixel = depth; + pPixmap->drawable.id = 0; + pPixmap->drawable.x = 0; + pPixmap->drawable.y = 0; + pPixmap->drawable.width = width; + pPixmap->drawable.height = height; + pPixmap->drawable.pScreen = pScreen; + pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pPixmap->refcnt = 1; + pPixmap->devKind = PixmapBytePad(width, depth); + pPixmap->usage_hint = usage_hint; + dixSetPrivate(&pPixmap->devPrivates, xnestPixmapPrivateKey, + (char *)pPixmap + pScreen->totalPixmapSize); + if (width && height) + xnestPixmapPriv(pPixmap)->pixmap = + XCreatePixmap(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + width, height, depth); + else + xnestPixmapPriv(pPixmap)->pixmap = 0; + + return pPixmap; +} + +Bool +xnestDestroyPixmap(PixmapPtr pPixmap) +{ + if(--pPixmap->refcnt) + return TRUE; + XFreePixmap(xnestDisplay, xnestPixmap(pPixmap)); + dixFreePrivates(pPixmap->devPrivates); + free(pPixmap); + return TRUE; +} + +RegionPtr +xnestPixmapToRegion(PixmapPtr pPixmap) +{ + XImage *ximage; + register RegionPtr pReg, pTmpReg; + register int x, y; + unsigned long previousPixel, currentPixel; + BoxRec Box = { 0, 0, 0, 0 }; + Bool overlap; + + ximage = XGetImage(xnestDisplay, xnestPixmap(pPixmap), 0, 0, + pPixmap->drawable.width, pPixmap->drawable.height, + 1, XYPixmap); + + pReg = REGION_CREATE(pPixmap->drawable.pScreen, NULL, 1); + pTmpReg = REGION_CREATE(pPixmap->drawable.pScreen, NULL, 1); + if(!pReg || !pTmpReg) { + XDestroyImage(ximage); + return NullRegion; + } + + for (y = 0; y < pPixmap->drawable.height; y++) { + Box.y1 = y; + Box.y2 = y + 1; + previousPixel = 0L; + for (x = 0; x < pPixmap->drawable.width; x++) { + currentPixel = XGetPixel(ximage, x, y); + if (previousPixel != currentPixel) { + if (previousPixel == 0L) { + /* left edge */ + Box.x1 = x; + } + else if (currentPixel == 0L) { + /* right edge */ + Box.x2 = x; + REGION_RESET(pPixmap->drawable.pScreen, pTmpReg, &Box); + REGION_APPEND(pPixmap->drawable.pScreen, pReg, pTmpReg); + } + previousPixel = currentPixel; + } + } + if (previousPixel != 0L) { + /* right edge because of the end of pixmap */ + Box.x2 = pPixmap->drawable.width; + REGION_RESET(pPixmap->drawable.pScreen, pTmpReg, &Box); + REGION_APPEND(pPixmap->drawable.pScreen, pReg, pTmpReg); + } + } + + REGION_DESTROY(pPixmap->drawable.pScreen, pTmpReg); + XDestroyImage(ximage); + + REGION_VALIDATE(pPixmap->drawable.pScreen, pReg, &overlap); + + return(pReg); +} diff --git a/xorg-server/hw/xnest/Screen.c b/xorg-server/hw/xnest/Screen.c index ca903d7ac..5a035ac8f 100644 --- a/xorg-server/hw/xnest/Screen.c +++ b/xorg-server/hw/xnest/Screen.c @@ -1,421 +1,420 @@ -/* - -Copyright 1993 by Davor Matic - -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. Davor Matic makes no representations about -the suitability of this software for any purpose. It is provided "as -is" without express or implied warranty. - -*/ - -#ifdef HAVE_XNEST_CONFIG_H -#include <xnest-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "scrnintstr.h" -#include "dix.h" -#include "mi.h" -#include "mibstore.h" -#include "micmap.h" -#include "colormapst.h" -#include "resource.h" - -#include "Xnest.h" - -#include "Display.h" -#include "Screen.h" -#include "XNGC.h" -#include "GCOps.h" -#include "Drawable.h" -#include "XNFont.h" -#include "Color.h" -#include "XNCursor.h" -#include "Visual.h" -#include "Events.h" -#include "Init.h" -#include "mipointer.h" -#include "Args.h" -#include "mipointrst.h" - -Window xnestDefaultWindows[MAXSCREENS]; -Window xnestScreenSaverWindows[MAXSCREENS]; -static int xnestCursorScreenKeyIndex; -DevPrivateKey xnestCursorScreenKey = &xnestCursorScreenKeyIndex; - -ScreenPtr -xnestScreen(Window window) -{ - int i; - - for (i = 0; i < xnestNumScreens; i++) - if (xnestDefaultWindows[i] == window) - return screenInfo.screens[i]; - - return NULL; -} - -static int -offset(unsigned long mask) -{ - int count; - - for (count = 0; !(mask & 1) && count < 32; count++) - mask >>= 1; - - return count; -} - -static Bool -xnestSaveScreen(ScreenPtr pScreen, int what) -{ - if (xnestSoftwareScreenSaver) - return False; - else { - switch (what) { - case SCREEN_SAVER_ON: - XMapRaised(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); - xnestSetScreenSaverColormapWindow(pScreen); - break; - - case SCREEN_SAVER_OFF: - XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); - xnestSetInstalledColormapWindows(pScreen); - break; - - case SCREEN_SAVER_FORCER: - lastEventTime = GetTimeInMillis(); - XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); - xnestSetInstalledColormapWindows(pScreen); - break; - - case SCREEN_SAVER_CYCLE: - XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); - xnestSetInstalledColormapWindows(pScreen); - break; - } - return True; - } -} - -static Bool -xnestCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) -{ - return FALSE; -} - -static void -xnestCrossScreen(ScreenPtr pScreen, Bool entering) -{ -} - -static miPointerScreenFuncRec xnestPointerCursorFuncs = -{ - xnestCursorOffScreen, - xnestCrossScreen, - miPointerWarpCursor -}; - -static miPointerSpriteFuncRec xnestPointerSpriteFuncs = -{ - xnestRealizeCursor, - xnestUnrealizeCursor, - xnestSetCursor, - xnestMoveCursor, - xnestDeviceCursorInitialize, - xnestDeviceCursorCleanup -}; - -Bool -xnestOpenScreen(int index, ScreenPtr pScreen, int argc, char *argv[]) -{ - VisualPtr visuals; - DepthPtr depths; - int numVisuals, numDepths; - int i, j, depthIndex; - unsigned long valuemask; - XSetWindowAttributes attributes; - XWindowAttributes gattributes; - XSizeHints sizeHints; - VisualID defaultVisual; - int rootDepth; - miPointerScreenPtr PointPriv; - - if (!dixRequestPrivate(xnestWindowPrivateKey, sizeof(xnestPrivWin))) - return False; - if (!dixRequestPrivate(xnestGCPrivateKey, sizeof(xnestPrivGC))) - return False; - - visuals = (VisualPtr)xalloc(xnestNumVisuals * sizeof(VisualRec)); - numVisuals = 0; - - depths = (DepthPtr)xalloc(MAXDEPTH * sizeof(DepthRec)); - depths[0].depth = 1; - depths[0].numVids = 0; - depths[0].vids = (VisualID *)xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); - numDepths = 1; - - for (i = 0; i < xnestNumVisuals; i++) { - visuals[numVisuals].class = xnestVisuals[i].class; - visuals[numVisuals].bitsPerRGBValue = xnestVisuals[i].bits_per_rgb; - visuals[numVisuals].ColormapEntries = xnestVisuals[i].colormap_size; - visuals[numVisuals].nplanes = xnestVisuals[i].depth; - visuals[numVisuals].redMask = xnestVisuals[i].red_mask; - visuals[numVisuals].greenMask = xnestVisuals[i].green_mask; - visuals[numVisuals].blueMask = xnestVisuals[i].blue_mask; - visuals[numVisuals].offsetRed = offset(xnestVisuals[i].red_mask); - visuals[numVisuals].offsetGreen = offset(xnestVisuals[i].green_mask); - visuals[numVisuals].offsetBlue = offset(xnestVisuals[i].blue_mask); - - /* Check for and remove duplicates. */ - for (j = 0; j < numVisuals; j++) { - if (visuals[numVisuals].class == visuals[j].class && - visuals[numVisuals].bitsPerRGBValue == visuals[j].bitsPerRGBValue && - visuals[numVisuals].ColormapEntries == visuals[j].ColormapEntries && - visuals[numVisuals].nplanes == visuals[j].nplanes && - visuals[numVisuals].redMask == visuals[j].redMask && - visuals[numVisuals].greenMask == visuals[j].greenMask && - visuals[numVisuals].blueMask == visuals[j].blueMask && - visuals[numVisuals].offsetRed == visuals[j].offsetRed && - visuals[numVisuals].offsetGreen == visuals[j].offsetGreen && - visuals[numVisuals].offsetBlue == visuals[j].offsetBlue) - break; - } - if (j < numVisuals) - break; - - visuals[numVisuals].vid = FakeClientID(0); - - depthIndex = UNDEFINED; - for (j = 0; j < numDepths; j++) - if (depths[j].depth == xnestVisuals[i].depth) { - depthIndex = j; - break; - } - - if (depthIndex == UNDEFINED) { - depthIndex = numDepths; - depths[depthIndex].depth = xnestVisuals[i].depth; - depths[depthIndex].numVids = 0; - depths[depthIndex].vids = - (VisualID *)xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); - numDepths++; - } - if (depths[depthIndex].numVids >= MAXVISUALSPERDEPTH) { - FatalError("Visual table overflow"); - } - depths[depthIndex].vids[depths[depthIndex].numVids] = - visuals[numVisuals].vid; - depths[depthIndex].numVids++; - - numVisuals++; - } - visuals = (VisualPtr)xrealloc(visuals, numVisuals * sizeof(VisualRec)); - - defaultVisual = visuals[xnestDefaultVisualIndex].vid; - rootDepth = visuals[xnestDefaultVisualIndex].nplanes; - - if (xnestParentWindow != 0) { - XGetWindowAttributes(xnestDisplay, xnestParentWindow, &gattributes); - xnestWidth = gattributes.width; - xnestHeight = gattributes.height; - } - - /* myNum */ - /* id */ - miScreenInit(pScreen, NULL, xnestWidth, xnestHeight, 1, 1, xnestWidth, - rootDepth, - numDepths, depths, - defaultVisual, /* root visual */ - numVisuals, visuals); - -/* miInitializeBackingStore(pScreen); */ - - pScreen->defColormap = (Colormap) FakeClientID(0); - pScreen->minInstalledCmaps = MINCMAPS; - pScreen->maxInstalledCmaps = MAXCMAPS; - pScreen->backingStoreSupport = NotUseful; - pScreen->saveUnderSupport = NotUseful; - pScreen->whitePixel = xnestWhitePixel; - pScreen->blackPixel = xnestBlackPixel; - /* rgf */ - /* GCperDepth */ - /* PixmapPerDepth */ - pScreen->devPrivate = NULL; - /* WindowPrivateLen */ - /* WindowPrivateSizes */ - /* totalWindowSize */ - /* GCPrivateLen */ - /* GCPrivateSizes */ - /* totalGCSize */ - - /* Random screen procedures */ - - pScreen->QueryBestSize = xnestQueryBestSize; - pScreen->SaveScreen = xnestSaveScreen; - pScreen->GetImage = xnestGetImage; - pScreen->GetSpans = xnestGetSpans; - pScreen->PointerNonInterestBox = NULL; - pScreen->SourceValidate = NULL; - - /* Window Procedures */ - - pScreen->CreateWindow = xnestCreateWindow; - pScreen->DestroyWindow = xnestDestroyWindow; - pScreen->PositionWindow = xnestPositionWindow; - pScreen->ChangeWindowAttributes = xnestChangeWindowAttributes; - pScreen->RealizeWindow = xnestRealizeWindow; - pScreen->UnrealizeWindow = xnestUnrealizeWindow; - pScreen->PostValidateTree = NULL; - pScreen->WindowExposures = xnestWindowExposures; - pScreen->CopyWindow = xnestCopyWindow; - pScreen->ClipNotify = xnestClipNotify; - - /* Pixmap procedures */ - - pScreen->CreatePixmap = xnestCreatePixmap; - pScreen->DestroyPixmap = xnestDestroyPixmap; - - /* Font procedures */ - - pScreen->RealizeFont = xnestRealizeFont; - pScreen->UnrealizeFont = xnestUnrealizeFont; - - /* GC procedures */ - - pScreen->CreateGC = xnestCreateGC; - - /* Colormap procedures */ - - pScreen->CreateColormap = xnestCreateColormap; - pScreen->DestroyColormap = xnestDestroyColormap; - pScreen->InstallColormap = xnestInstallColormap; - pScreen->UninstallColormap = xnestUninstallColormap; - pScreen->ListInstalledColormaps = xnestListInstalledColormaps; - pScreen->StoreColors = xnestStoreColors; - pScreen->ResolveColor = xnestResolveColor; - - pScreen->BitmapToRegion = xnestPixmapToRegion; - - /* OS layer procedures */ - - pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA; - pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA; - pScreen->blockData = NULL; - pScreen->wakeupData = NULL; - - miDCInitialize(pScreen, &xnestPointerCursorFuncs); /* init SW rendering */ - PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); - xnestCursorFuncs.spriteFuncs = PointPriv->spriteFuncs; - dixSetPrivate(&pScreen->devPrivates, xnestCursorScreenKey, &xnestCursorFuncs); - PointPriv->spriteFuncs = &xnestPointerSpriteFuncs; - - pScreen->mmWidth = xnestWidth * DisplayWidthMM(xnestDisplay, - DefaultScreen(xnestDisplay)) / - DisplayWidth(xnestDisplay, - DefaultScreen(xnestDisplay)); - pScreen->mmHeight = xnestHeight * DisplayHeightMM(xnestDisplay, - DefaultScreen(xnestDisplay)) / - DisplayHeight(xnestDisplay, - DefaultScreen(xnestDisplay)); - - /* overwrite miCloseScreen with our own */ - pScreen->CloseScreen = xnestCloseScreen; - - if (!miScreenDevPrivateInit(pScreen, xnestWidth, NULL)) - return FALSE; - - /* overwrite miSetShape with our own */ - pScreen->SetShape = xnestSetShape; - - /* devPrivates */ - -#define POSITION_OFFSET (pScreen->myNum * (xnestWidth + xnestHeight) / 32) - - if (xnestDoFullGeneration) { - - valuemask = CWBackPixel | CWEventMask | CWColormap; - attributes.background_pixel = xnestWhitePixel; - attributes.event_mask = xnestEventMask; - attributes.colormap = xnestDefaultVisualColormap(xnestDefaultVisual(pScreen)); - - if (xnestParentWindow != 0) { - xnestDefaultWindows[pScreen->myNum] = xnestParentWindow; - XSelectInput (xnestDisplay, xnestDefaultWindows[pScreen->myNum], - xnestEventMask); - } else - xnestDefaultWindows[pScreen->myNum] = - XCreateWindow(xnestDisplay, - DefaultRootWindow(xnestDisplay), - xnestX + POSITION_OFFSET, - xnestY + POSITION_OFFSET, - xnestWidth, xnestHeight, - xnestBorderWidth, - pScreen->rootDepth, - InputOutput, - xnestDefaultVisual(pScreen), - valuemask, &attributes); - - if (!xnestWindowName) - xnestWindowName = argv[0]; - - sizeHints.flags = PPosition | PSize | PMaxSize; - sizeHints.x = xnestX + POSITION_OFFSET; - sizeHints.y = xnestY + POSITION_OFFSET; - sizeHints.width = sizeHints.max_width = xnestWidth; - sizeHints.height = sizeHints.max_height = xnestHeight; - if (xnestUserGeometry & XValue || xnestUserGeometry & YValue) - sizeHints.flags |= USPosition; - if (xnestUserGeometry & WidthValue || xnestUserGeometry & HeightValue) - sizeHints.flags |= USSize; - XSetStandardProperties(xnestDisplay, - xnestDefaultWindows[pScreen->myNum], - xnestWindowName, - xnestWindowName, - xnestIconBitmap, - argv, argc, &sizeHints); - - XMapWindow(xnestDisplay, xnestDefaultWindows[pScreen->myNum]); - - valuemask = CWBackPixmap | CWColormap; - attributes.background_pixmap = xnestScreenSaverPixmap; - attributes.colormap = - DefaultColormap(xnestDisplay, DefaultScreen(xnestDisplay)); - xnestScreenSaverWindows[pScreen->myNum] = - XCreateWindow(xnestDisplay, - xnestDefaultWindows[pScreen->myNum], - 0, 0, xnestWidth, xnestHeight, 0, - DefaultDepth(xnestDisplay, DefaultScreen(xnestDisplay)), - InputOutput, - DefaultVisual(xnestDisplay, DefaultScreen(xnestDisplay)), - valuemask, &attributes); - } - - if (!xnestCreateDefaultColormap(pScreen)) return False; - - return True; -} - -Bool -xnestCloseScreen(int index, ScreenPtr pScreen) -{ - int i; - - for (i = 0; i < pScreen->numDepths; i++) - xfree(pScreen->allowedDepths[i].vids); - xfree(pScreen->allowedDepths); - xfree(pScreen->visuals); - xfree(pScreen->devPrivate); - - /* - If xnestDoFullGeneration all x resources will be destroyed upon closing - the display connection. There is no need to generate extra protocol. - */ - - return True; -} +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#ifdef HAVE_XNEST_CONFIG_H +#include <xnest-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "dix.h" +#include "mi.h" +#include "mibstore.h" +#include "micmap.h" +#include "colormapst.h" +#include "resource.h" + +#include "Xnest.h" + +#include "Display.h" +#include "Screen.h" +#include "XNGC.h" +#include "GCOps.h" +#include "Drawable.h" +#include "XNFont.h" +#include "Color.h" +#include "XNCursor.h" +#include "Visual.h" +#include "Events.h" +#include "Init.h" +#include "mipointer.h" +#include "Args.h" +#include "mipointrst.h" + +Window xnestDefaultWindows[MAXSCREENS]; +Window xnestScreenSaverWindows[MAXSCREENS]; +static int xnestCursorScreenKeyIndex; +DevPrivateKey xnestCursorScreenKey = &xnestCursorScreenKeyIndex; + +ScreenPtr +xnestScreen(Window window) +{ + int i; + + for (i = 0; i < xnestNumScreens; i++) + if (xnestDefaultWindows[i] == window) + return screenInfo.screens[i]; + + return NULL; +} + +static int +offset(unsigned long mask) +{ + int count; + + for (count = 0; !(mask & 1) && count < 32; count++) + mask >>= 1; + + return count; +} + +static Bool +xnestSaveScreen(ScreenPtr pScreen, int what) +{ + if (xnestSoftwareScreenSaver) + return False; + else { + switch (what) { + case SCREEN_SAVER_ON: + XMapRaised(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); + xnestSetScreenSaverColormapWindow(pScreen); + break; + + case SCREEN_SAVER_OFF: + XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); + xnestSetInstalledColormapWindows(pScreen); + break; + + case SCREEN_SAVER_FORCER: + lastEventTime = GetTimeInMillis(); + XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); + xnestSetInstalledColormapWindows(pScreen); + break; + + case SCREEN_SAVER_CYCLE: + XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); + xnestSetInstalledColormapWindows(pScreen); + break; + } + return True; + } +} + +static Bool +xnestCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) +{ + return FALSE; +} + +static void +xnestCrossScreen(ScreenPtr pScreen, Bool entering) +{ +} + +static miPointerScreenFuncRec xnestPointerCursorFuncs = +{ + xnestCursorOffScreen, + xnestCrossScreen, + miPointerWarpCursor +}; + +static miPointerSpriteFuncRec xnestPointerSpriteFuncs = +{ + xnestRealizeCursor, + xnestUnrealizeCursor, + xnestSetCursor, + xnestMoveCursor, + xnestDeviceCursorInitialize, + xnestDeviceCursorCleanup +}; + +Bool +xnestOpenScreen(int index, ScreenPtr pScreen, int argc, char *argv[]) +{ + VisualPtr visuals; + DepthPtr depths; + int numVisuals, numDepths; + int i, j, depthIndex; + unsigned long valuemask; + XSetWindowAttributes attributes; + XWindowAttributes gattributes; + XSizeHints sizeHints; + VisualID defaultVisual; + int rootDepth; + miPointerScreenPtr PointPriv; + + if (!dixRequestPrivate(xnestWindowPrivateKey, sizeof(xnestPrivWin))) + return False; + if (!dixRequestPrivate(xnestGCPrivateKey, sizeof(xnestPrivGC))) + return False; + + visuals = (VisualPtr)malloc(xnestNumVisuals * sizeof(VisualRec)); + numVisuals = 0; + + depths = (DepthPtr)malloc(MAXDEPTH * sizeof(DepthRec)); + depths[0].depth = 1; + depths[0].numVids = 0; + depths[0].vids = (VisualID *)malloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); + numDepths = 1; + + for (i = 0; i < xnestNumVisuals; i++) { + visuals[numVisuals].class = xnestVisuals[i].class; + visuals[numVisuals].bitsPerRGBValue = xnestVisuals[i].bits_per_rgb; + visuals[numVisuals].ColormapEntries = xnestVisuals[i].colormap_size; + visuals[numVisuals].nplanes = xnestVisuals[i].depth; + visuals[numVisuals].redMask = xnestVisuals[i].red_mask; + visuals[numVisuals].greenMask = xnestVisuals[i].green_mask; + visuals[numVisuals].blueMask = xnestVisuals[i].blue_mask; + visuals[numVisuals].offsetRed = offset(xnestVisuals[i].red_mask); + visuals[numVisuals].offsetGreen = offset(xnestVisuals[i].green_mask); + visuals[numVisuals].offsetBlue = offset(xnestVisuals[i].blue_mask); + + /* Check for and remove duplicates. */ + for (j = 0; j < numVisuals; j++) { + if (visuals[numVisuals].class == visuals[j].class && + visuals[numVisuals].bitsPerRGBValue == visuals[j].bitsPerRGBValue && + visuals[numVisuals].ColormapEntries == visuals[j].ColormapEntries && + visuals[numVisuals].nplanes == visuals[j].nplanes && + visuals[numVisuals].redMask == visuals[j].redMask && + visuals[numVisuals].greenMask == visuals[j].greenMask && + visuals[numVisuals].blueMask == visuals[j].blueMask && + visuals[numVisuals].offsetRed == visuals[j].offsetRed && + visuals[numVisuals].offsetGreen == visuals[j].offsetGreen && + visuals[numVisuals].offsetBlue == visuals[j].offsetBlue) + break; + } + if (j < numVisuals) + break; + + visuals[numVisuals].vid = FakeClientID(0); + + depthIndex = UNDEFINED; + for (j = 0; j < numDepths; j++) + if (depths[j].depth == xnestVisuals[i].depth) { + depthIndex = j; + break; + } + + if (depthIndex == UNDEFINED) { + depthIndex = numDepths; + depths[depthIndex].depth = xnestVisuals[i].depth; + depths[depthIndex].numVids = 0; + depths[depthIndex].vids = + (VisualID *)malloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); + numDepths++; + } + if (depths[depthIndex].numVids >= MAXVISUALSPERDEPTH) { + FatalError("Visual table overflow"); + } + depths[depthIndex].vids[depths[depthIndex].numVids] = + visuals[numVisuals].vid; + depths[depthIndex].numVids++; + + numVisuals++; + } + visuals = (VisualPtr)realloc(visuals, numVisuals * sizeof(VisualRec)); + + defaultVisual = visuals[xnestDefaultVisualIndex].vid; + rootDepth = visuals[xnestDefaultVisualIndex].nplanes; + + if (xnestParentWindow != 0) { + XGetWindowAttributes(xnestDisplay, xnestParentWindow, &gattributes); + xnestWidth = gattributes.width; + xnestHeight = gattributes.height; + } + + /* myNum */ + /* id */ + miScreenInit(pScreen, NULL, xnestWidth, xnestHeight, 1, 1, xnestWidth, + rootDepth, + numDepths, depths, + defaultVisual, /* root visual */ + numVisuals, visuals); + +/* miInitializeBackingStore(pScreen); */ + + pScreen->defColormap = (Colormap) FakeClientID(0); + pScreen->minInstalledCmaps = MINCMAPS; + pScreen->maxInstalledCmaps = MAXCMAPS; + pScreen->backingStoreSupport = NotUseful; + pScreen->saveUnderSupport = NotUseful; + pScreen->whitePixel = xnestWhitePixel; + pScreen->blackPixel = xnestBlackPixel; + /* rgf */ + /* GCperDepth */ + /* PixmapPerDepth */ + pScreen->devPrivate = NULL; + /* WindowPrivateLen */ + /* WindowPrivateSizes */ + /* totalWindowSize */ + /* GCPrivateLen */ + /* GCPrivateSizes */ + /* totalGCSize */ + + /* Random screen procedures */ + + pScreen->QueryBestSize = xnestQueryBestSize; + pScreen->SaveScreen = xnestSaveScreen; + pScreen->GetImage = xnestGetImage; + pScreen->GetSpans = xnestGetSpans; + pScreen->SourceValidate = NULL; + + /* Window Procedures */ + + pScreen->CreateWindow = xnestCreateWindow; + pScreen->DestroyWindow = xnestDestroyWindow; + pScreen->PositionWindow = xnestPositionWindow; + pScreen->ChangeWindowAttributes = xnestChangeWindowAttributes; + pScreen->RealizeWindow = xnestRealizeWindow; + pScreen->UnrealizeWindow = xnestUnrealizeWindow; + pScreen->PostValidateTree = NULL; + pScreen->WindowExposures = xnestWindowExposures; + pScreen->CopyWindow = xnestCopyWindow; + pScreen->ClipNotify = xnestClipNotify; + + /* Pixmap procedures */ + + pScreen->CreatePixmap = xnestCreatePixmap; + pScreen->DestroyPixmap = xnestDestroyPixmap; + + /* Font procedures */ + + pScreen->RealizeFont = xnestRealizeFont; + pScreen->UnrealizeFont = xnestUnrealizeFont; + + /* GC procedures */ + + pScreen->CreateGC = xnestCreateGC; + + /* Colormap procedures */ + + pScreen->CreateColormap = xnestCreateColormap; + pScreen->DestroyColormap = xnestDestroyColormap; + pScreen->InstallColormap = xnestInstallColormap; + pScreen->UninstallColormap = xnestUninstallColormap; + pScreen->ListInstalledColormaps = xnestListInstalledColormaps; + pScreen->StoreColors = xnestStoreColors; + pScreen->ResolveColor = xnestResolveColor; + + pScreen->BitmapToRegion = xnestPixmapToRegion; + + /* OS layer procedures */ + + pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA; + pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA; + pScreen->blockData = NULL; + pScreen->wakeupData = NULL; + + miDCInitialize(pScreen, &xnestPointerCursorFuncs); /* init SW rendering */ + PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + xnestCursorFuncs.spriteFuncs = PointPriv->spriteFuncs; + dixSetPrivate(&pScreen->devPrivates, xnestCursorScreenKey, &xnestCursorFuncs); + PointPriv->spriteFuncs = &xnestPointerSpriteFuncs; + + pScreen->mmWidth = xnestWidth * DisplayWidthMM(xnestDisplay, + DefaultScreen(xnestDisplay)) / + DisplayWidth(xnestDisplay, + DefaultScreen(xnestDisplay)); + pScreen->mmHeight = xnestHeight * DisplayHeightMM(xnestDisplay, + DefaultScreen(xnestDisplay)) / + DisplayHeight(xnestDisplay, + DefaultScreen(xnestDisplay)); + + /* overwrite miCloseScreen with our own */ + pScreen->CloseScreen = xnestCloseScreen; + + if (!miScreenDevPrivateInit(pScreen, xnestWidth, NULL)) + return FALSE; + + /* overwrite miSetShape with our own */ + pScreen->SetShape = xnestSetShape; + + /* devPrivates */ + +#define POSITION_OFFSET (pScreen->myNum * (xnestWidth + xnestHeight) / 32) + + if (xnestDoFullGeneration) { + + valuemask = CWBackPixel | CWEventMask | CWColormap; + attributes.background_pixel = xnestWhitePixel; + attributes.event_mask = xnestEventMask; + attributes.colormap = xnestDefaultVisualColormap(xnestDefaultVisual(pScreen)); + + if (xnestParentWindow != 0) { + xnestDefaultWindows[pScreen->myNum] = xnestParentWindow; + XSelectInput (xnestDisplay, xnestDefaultWindows[pScreen->myNum], + xnestEventMask); + } else + xnestDefaultWindows[pScreen->myNum] = + XCreateWindow(xnestDisplay, + DefaultRootWindow(xnestDisplay), + xnestX + POSITION_OFFSET, + xnestY + POSITION_OFFSET, + xnestWidth, xnestHeight, + xnestBorderWidth, + pScreen->rootDepth, + InputOutput, + xnestDefaultVisual(pScreen), + valuemask, &attributes); + + if (!xnestWindowName) + xnestWindowName = argv[0]; + + sizeHints.flags = PPosition | PSize | PMaxSize; + sizeHints.x = xnestX + POSITION_OFFSET; + sizeHints.y = xnestY + POSITION_OFFSET; + sizeHints.width = sizeHints.max_width = xnestWidth; + sizeHints.height = sizeHints.max_height = xnestHeight; + if (xnestUserGeometry & XValue || xnestUserGeometry & YValue) + sizeHints.flags |= USPosition; + if (xnestUserGeometry & WidthValue || xnestUserGeometry & HeightValue) + sizeHints.flags |= USSize; + XSetStandardProperties(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + xnestWindowName, + xnestWindowName, + xnestIconBitmap, + argv, argc, &sizeHints); + + XMapWindow(xnestDisplay, xnestDefaultWindows[pScreen->myNum]); + + valuemask = CWBackPixmap | CWColormap; + attributes.background_pixmap = xnestScreenSaverPixmap; + attributes.colormap = + DefaultColormap(xnestDisplay, DefaultScreen(xnestDisplay)); + xnestScreenSaverWindows[pScreen->myNum] = + XCreateWindow(xnestDisplay, + xnestDefaultWindows[pScreen->myNum], + 0, 0, xnestWidth, xnestHeight, 0, + DefaultDepth(xnestDisplay, DefaultScreen(xnestDisplay)), + InputOutput, + DefaultVisual(xnestDisplay, DefaultScreen(xnestDisplay)), + valuemask, &attributes); + } + + if (!xnestCreateDefaultColormap(pScreen)) return False; + + return True; +} + +Bool +xnestCloseScreen(int index, ScreenPtr pScreen) +{ + int i; + + for (i = 0; i < pScreen->numDepths; i++) + free(pScreen->allowedDepths[i].vids); + free(pScreen->allowedDepths); + free(pScreen->visuals); + free(pScreen->devPrivate); + + /* + If xnestDoFullGeneration all x resources will be destroyed upon closing + the display connection. There is no need to generate extra protocol. + */ + + return True; +} diff --git a/xorg-server/hw/xquartz/GL/glcontextmodes.c b/xorg-server/hw/xquartz/GL/glcontextmodes.c index 326c8b235..52a9ca440 100644 --- a/xorg-server/hw/xquartz/GL/glcontextmodes.c +++ b/xorg-server/hw/xquartz/GL/glcontextmodes.c @@ -1,550 +1,550 @@ -/* - * (C) Copyright IBM Corporation 2003 - * 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 - * 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 - * 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 - * VA LINUX SYSTEM, IBM AND/OR THEIR 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. - */ - -/** - * \file glcontextmodes.c - * Utility routines for working with \c __GLcontextModes structures. At - * some point most or all of these functions will be moved to the Mesa - * code base. - * - * \author Ian Romanick <idr@us.ibm.com> - */ - -#if defined(IN_MINI_GLX) -#include <GL/gl.h> -#else -#if defined(HAVE_DIX_CONFIG_H) -# include <dix-config.h> -#endif -#include <X11/X.h> -#include <GL/glx.h> -#include "GL/glxint.h" -#endif - -/* Memory macros */ -#if defined(IN_MINI_GLX) -# include <stdlib.h> -# include <string.h> -# define _mesa_malloc(b) malloc(b) -# define _mesa_free(m) free(m) -# define _mesa_memset memset -#else -# ifdef XFree86Server -# include <os.h> -# include <string.h> -# define _mesa_malloc(b) xalloc(b) -# define _mesa_free(m) xfree(m) -# define _mesa_memset memset -# else -# include <X11/Xlibint.h> -# define _mesa_memset memset -# define _mesa_malloc(b) Xmalloc(b) -# define _mesa_free(m) Xfree(m) -# endif /* XFree86Server */ -#endif /* !defined(IN_MINI_GLX) */ - -#include "glcontextmodes.h" - -#if !defined(IN_MINI_GLX) -#define NUM_VISUAL_TYPES 6 - -/** - * Convert an X visual type to a GLX visual type. - * - * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) - * to be converted. - * \return If \c visualType is a valid X visual type, a GLX visual type will - * be returned. Otherwise \c GLX_NONE will be returned. - */ -GLint -_gl_convert_from_x_visual_type( int visualType ) -{ - static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { - GLX_STATIC_GRAY, GLX_GRAY_SCALE, - GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, - GLX_TRUE_COLOR, GLX_DIRECT_COLOR - }; - - return ( (unsigned) visualType < NUM_VISUAL_TYPES ) - ? glx_visual_types[ visualType ] : GLX_NONE; -} - - -/** - * Convert a GLX visual type to an X visual type. - * - * \param visualType GLX visual type (i.e., \c GLX_TRUE_COLOR, - * \c GLX_STATIC_GRAY, etc.) to be converted. - * \return If \c visualType is a valid GLX visual type, an X visual type will - * be returned. Otherwise -1 will be returned. - */ -GLint -_gl_convert_to_x_visual_type( int visualType ) -{ - static const int x_visual_types[ NUM_VISUAL_TYPES ] = { - TrueColor, DirectColor, - PseudoColor, StaticColor, - GrayScale, StaticGray - }; - - return ( (unsigned) (visualType - GLX_TRUE_COLOR) < NUM_VISUAL_TYPES ) - ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1; -} - - -/** - * Copy a GLX visual config structure to a GL context mode structure. All - * of the fields in \c config are copied to \c mode. Additional fields in - * \c mode that can be derrived from the fields of \c config (i.e., - * \c haveDepthBuffer) are also filled in. The remaining fields in \c mode - * that cannot be derived are set to default values. - * - * \param mode Destination GL context mode. - * \param config Source GLX visual config. - * - * \note - * The \c fbconfigID and \c visualID fields of the \c __GLcontextModes - * structure will be set to the \c vid of the \c __GLXvisualConfig structure. - */ -void -_gl_copy_visual_to_context_mode( __GLcontextModes * mode, - const __GLXvisualConfig * config ) -{ - __GLcontextModes * const next = mode->next; - - (void) _mesa_memset( mode, 0, sizeof( __GLcontextModes ) ); - mode->next = next; - - mode->visualID = config->vid; - mode->visualType = _gl_convert_from_x_visual_type( config->class ); - mode->xRenderable = GL_TRUE; - mode->fbconfigID = config->vid; - mode->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT; - - mode->rgbMode = (config->rgba != 0); - mode->renderType = (mode->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; - - mode->colorIndexMode = !(mode->rgbMode); - mode->doubleBufferMode = (config->doubleBuffer != 0); - mode->stereoMode = (config->stereo != 0); - - mode->haveAccumBuffer = ((config->accumRedSize + - config->accumGreenSize + - config->accumBlueSize + - config->accumAlphaSize) > 0); - mode->haveDepthBuffer = (config->depthSize > 0); - mode->haveStencilBuffer = (config->stencilSize > 0); - - mode->redBits = config->redSize; - mode->greenBits = config->greenSize; - mode->blueBits = config->blueSize; - mode->alphaBits = config->alphaSize; - mode->redMask = config->redMask; - mode->greenMask = config->greenMask; - mode->blueMask = config->blueMask; - mode->alphaMask = config->alphaMask; - mode->rgbBits = mode->rgbMode ? config->bufferSize : 0; - mode->indexBits = mode->colorIndexMode ? config->bufferSize : 0; - - mode->accumRedBits = config->accumRedSize; - mode->accumGreenBits = config->accumGreenSize; - mode->accumBlueBits = config->accumBlueSize; - mode->accumAlphaBits = config->accumAlphaSize; - mode->depthBits = config->depthSize; - mode->stencilBits = config->stencilSize; - - mode->numAuxBuffers = config->auxBuffers; - mode->level = config->level; - - mode->visualRating = config->visualRating; - mode->transparentPixel = config->transparentPixel; - mode->transparentRed = config->transparentRed; - mode->transparentGreen = config->transparentGreen; - mode->transparentBlue = config->transparentBlue; - mode->transparentAlpha = config->transparentAlpha; - mode->transparentIndex = config->transparentIndex; - mode->samples = config->multiSampleSize; - mode->sampleBuffers = config->nMultiSampleBuffers; - /* mode->visualSelectGroup = config->visualSelectGroup; ? */ - - mode->swapMethod = GLX_SWAP_UNDEFINED_OML; - - mode->bindToTextureRgb = (mode->rgbMode) ? GL_TRUE : GL_FALSE; - mode->bindToTextureRgba = (mode->rgbMode && mode->alphaBits) ? - GL_TRUE : GL_FALSE; - mode->bindToMipmapTexture = mode->rgbMode ? GL_TRUE : GL_FALSE; - mode->bindToTextureTargets = mode->rgbMode ? - GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | - GLX_TEXTURE_RECTANGLE_BIT_EXT : 0; - mode->yInverted = GL_FALSE; -} - - -/** - * Get data from a GL context mode. - * - * \param mode GL context mode whose data is to be returned. - * \param attribute Attribute of \c mode that is to be returned. - * \param value_return Location to store the data member of \c mode. - * \return If \c attribute is a valid attribute of \c mode, zero is - * returned. Otherwise \c GLX_BAD_ATTRIBUTE is returned. - */ -int -_gl_get_context_mode_data(const __GLcontextModes *mode, int attribute, - int *value_return) -{ - switch (attribute) { - case GLX_USE_GL: - *value_return = GL_TRUE; - return 0; - case GLX_BUFFER_SIZE: - *value_return = mode->rgbBits; - return 0; - case GLX_RGBA: - *value_return = mode->rgbMode; - return 0; - case GLX_RED_SIZE: - *value_return = mode->redBits; - return 0; - case GLX_GREEN_SIZE: - *value_return = mode->greenBits; - return 0; - case GLX_BLUE_SIZE: - *value_return = mode->blueBits; - return 0; - case GLX_ALPHA_SIZE: - *value_return = mode->alphaBits; - return 0; - case GLX_DOUBLEBUFFER: - *value_return = mode->doubleBufferMode; - return 0; - case GLX_STEREO: - *value_return = mode->stereoMode; - return 0; - case GLX_AUX_BUFFERS: - *value_return = mode->numAuxBuffers; - return 0; - case GLX_DEPTH_SIZE: - *value_return = mode->depthBits; - return 0; - case GLX_STENCIL_SIZE: - *value_return = mode->stencilBits; - return 0; - case GLX_ACCUM_RED_SIZE: - *value_return = mode->accumRedBits; - return 0; - case GLX_ACCUM_GREEN_SIZE: - *value_return = mode->accumGreenBits; - return 0; - case GLX_ACCUM_BLUE_SIZE: - *value_return = mode->accumBlueBits; - return 0; - case GLX_ACCUM_ALPHA_SIZE: - *value_return = mode->accumAlphaBits; - return 0; - case GLX_LEVEL: - *value_return = mode->level; - return 0; - case GLX_TRANSPARENT_TYPE_EXT: - *value_return = mode->transparentPixel; - return 0; - case GLX_TRANSPARENT_RED_VALUE: - *value_return = mode->transparentRed; - return 0; - case GLX_TRANSPARENT_GREEN_VALUE: - *value_return = mode->transparentGreen; - return 0; - case GLX_TRANSPARENT_BLUE_VALUE: - *value_return = mode->transparentBlue; - return 0; - case GLX_TRANSPARENT_ALPHA_VALUE: - *value_return = mode->transparentAlpha; - return 0; - case GLX_TRANSPARENT_INDEX_VALUE: - *value_return = mode->transparentIndex; - return 0; - case GLX_X_VISUAL_TYPE: - *value_return = mode->visualType; - return 0; - case GLX_CONFIG_CAVEAT: - *value_return = mode->visualRating; - return 0; - case GLX_VISUAL_ID: - *value_return = mode->visualID; - return 0; - case GLX_DRAWABLE_TYPE: - *value_return = mode->drawableType; - return 0; - case GLX_RENDER_TYPE: - *value_return = mode->renderType; - return 0; - case GLX_X_RENDERABLE: - *value_return = mode->xRenderable; - return 0; - case GLX_FBCONFIG_ID: - *value_return = mode->fbconfigID; - return 0; - case GLX_MAX_PBUFFER_WIDTH: - *value_return = mode->maxPbufferWidth; - return 0; - case GLX_MAX_PBUFFER_HEIGHT: - *value_return = mode->maxPbufferHeight; - return 0; - case GLX_MAX_PBUFFER_PIXELS: - *value_return = mode->maxPbufferPixels; - return 0; - case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: - *value_return = mode->optimalPbufferWidth; - return 0; - case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: - *value_return = mode->optimalPbufferHeight; - return 0; - case GLX_SWAP_METHOD_OML: - *value_return = mode->swapMethod; - return 0; - case GLX_SAMPLE_BUFFERS_SGIS: - *value_return = mode->sampleBuffers; - return 0; - case GLX_SAMPLES_SGIS: - *value_return = mode->samples; - return 0; - case GLX_BIND_TO_TEXTURE_RGB_EXT: - *value_return = mode->bindToTextureRgb; - return 0; - case GLX_BIND_TO_TEXTURE_RGBA_EXT: - *value_return = mode->bindToTextureRgba; - return 0; - case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: - *value_return = mode->bindToMipmapTexture == GL_TRUE ? GL_TRUE : - GL_FALSE; - return 0; - case GLX_BIND_TO_TEXTURE_TARGETS_EXT: - *value_return = mode->bindToTextureTargets; - return 0; - case GLX_Y_INVERTED_EXT: - *value_return = mode->yInverted; - return 0; - - /* Applications are NOT allowed to query GLX_VISUAL_SELECT_GROUP_SGIX. - * It is ONLY for communication between the GLX client and the GLX - * server. - */ - case GLX_VISUAL_SELECT_GROUP_SGIX: - default: - return GLX_BAD_ATTRIBUTE; - } -} -#endif /* !defined(IN_MINI_GLX) */ - - -/** - * Allocate a linked list of \c __GLcontextModes structures. The fields of - * each structure will be initialized to "reasonable" default values. In - * most cases this is the default value defined by table 3.4 of the GLX - * 1.3 specification. This means that most values are either initialized to - * zero or \c GLX_DONT_CARE (which is -1). As support for additional - * extensions is added, the new values will be initialized to appropriate - * values from the extension specification. - * - * \param count Number of structures to allocate. - * \param minimum_size Minimum size of a structure to allocate. This allows - * for differences in the version of the - * \c __GLcontextModes stucture used in libGL and in a - * DRI-based driver. - * \returns A pointer to the first element in a linked list of \c count - * stuctures on success, or \c NULL on failure. - * - * \warning Use of \c minimum_size does \b not guarantee binary compatibility. - * The fundamental assumption is that if the \c minimum_size - * specified by the driver and the size of the \c __GLcontextModes - * structure in libGL is the same, then the meaning of each byte in - * the structure is the same in both places. \b Be \b careful! - * Basically this means that fields have to be added in libGL and - * then propagated to drivers. Drivers should \b never arbitrarilly - * extend the \c __GLcontextModes data-structure. - */ -__GLcontextModes * -_gl_context_modes_create( unsigned count, size_t minimum_size ) -{ - const size_t size = (minimum_size > sizeof( __GLcontextModes )) - ? minimum_size : sizeof( __GLcontextModes ); - __GLcontextModes * base = NULL; - __GLcontextModes ** next; - unsigned i; - - next = & base; - for ( i = 0 ; i < count ; i++ ) { - *next = (__GLcontextModes *) _mesa_malloc( size ); - if ( *next == NULL ) { - _gl_context_modes_destroy( base ); - base = NULL; - break; - } - - (void) _mesa_memset( *next, 0, size ); - (*next)->visualID = GLX_DONT_CARE; - (*next)->visualType = GLX_DONT_CARE; - (*next)->visualRating = GLX_NONE; - (*next)->transparentPixel = GLX_NONE; - (*next)->transparentRed = GLX_DONT_CARE; - (*next)->transparentGreen = GLX_DONT_CARE; - (*next)->transparentBlue = GLX_DONT_CARE; - (*next)->transparentAlpha = GLX_DONT_CARE; - (*next)->transparentIndex = GLX_DONT_CARE; - (*next)->xRenderable = GLX_DONT_CARE; - (*next)->fbconfigID = GLX_DONT_CARE; - (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; - (*next)->bindToTextureRgb = GLX_DONT_CARE; - (*next)->bindToTextureRgba = GLX_DONT_CARE; - (*next)->bindToMipmapTexture = GLX_DONT_CARE; - (*next)->bindToTextureTargets = GLX_DONT_CARE; - (*next)->yInverted = GLX_DONT_CARE; - - next = & ((*next)->next); - } - - return base; -} - - -/** - * Destroy a linked list of \c __GLcontextModes structures created by - * \c _gl_context_modes_create. - * - * \param modes Linked list of structures to be destroyed. All structres - * in the list will be freed. - */ -void -_gl_context_modes_destroy( __GLcontextModes * modes ) -{ - while ( modes != NULL ) { - __GLcontextModes * const next = modes->next; - - _mesa_free( modes ); - modes = next; - } -} - - -/** - * Find a context mode matching a Visual ID. - * - * \param modes List list of context-mode structures to be searched. - * \param vid Visual ID to be found. - * \returns A pointer to a context-mode in \c modes if \c vid was found in - * the list, or \c NULL if it was not. - */ - -__GLcontextModes * -_gl_context_modes_find_visual(__GLcontextModes *modes, int vid) -{ - __GLcontextModes *m; - - for (m = modes; m != NULL; m = m->next) - if (m->visualID == vid) - return m; - - return NULL; -} - -__GLcontextModes * -_gl_context_modes_find_fbconfig(__GLcontextModes *modes, int fbid) -{ - __GLcontextModes *m; - - for (m = modes; m != NULL; m = m->next) - if (m->fbconfigID == fbid) - return m; - - return NULL; -} - -/** - * Determine if two context-modes are the same. This is intended to be used - * by libGL implementations to compare to sets of driver generated FBconfigs. - * - * \param a Context-mode to be compared. - * \param b Context-mode to be compared. - * \returns \c GL_TRUE if the two context-modes are the same. \c GL_FALSE is - * returned otherwise. - */ -GLboolean -_gl_context_modes_are_same( const __GLcontextModes * a, - const __GLcontextModes * b ) -{ - return( (a->rgbMode == b->rgbMode) && - (a->floatMode == b->floatMode) && - (a->colorIndexMode == b->colorIndexMode) && - (a->doubleBufferMode == b->doubleBufferMode) && - (a->stereoMode == b->stereoMode) && - (a->redBits == b->redBits) && - (a->greenBits == b->greenBits) && - (a->blueBits == b->blueBits) && - (a->alphaBits == b->alphaBits) && -#if 0 /* For some reason these don't get set on the client-side in libGL. */ - (a->redMask == b->redMask) && - (a->greenMask == b->greenMask) && - (a->blueMask == b->blueMask) && - (a->alphaMask == b->alphaMask) && -#endif - (a->rgbBits == b->rgbBits) && - (a->indexBits == b->indexBits) && - (a->accumRedBits == b->accumRedBits) && - (a->accumGreenBits == b->accumGreenBits) && - (a->accumBlueBits == b->accumBlueBits) && - (a->accumAlphaBits == b->accumAlphaBits) && - (a->depthBits == b->depthBits) && - (a->stencilBits == b->stencilBits) && - (a->numAuxBuffers == b->numAuxBuffers) && - (a->level == b->level) && - (a->pixmapMode == b->pixmapMode) && - (a->visualRating == b->visualRating) && - - (a->transparentPixel == b->transparentPixel) && - - ((a->transparentPixel != GLX_TRANSPARENT_RGB) || - ((a->transparentRed == b->transparentRed) && - (a->transparentGreen == b->transparentGreen) && - (a->transparentBlue == b->transparentBlue) && - (a->transparentAlpha == b->transparentAlpha))) && - - ((a->transparentPixel != GLX_TRANSPARENT_INDEX) || - (a->transparentIndex == b->transparentIndex)) && - - (a->sampleBuffers == b->sampleBuffers) && - (a->samples == b->samples) && - ((a->drawableType & b->drawableType) != 0) && - (a->renderType == b->renderType) && - (a->maxPbufferWidth == b->maxPbufferWidth) && - (a->maxPbufferHeight == b->maxPbufferHeight) && - (a->maxPbufferPixels == b->maxPbufferPixels) && - (a->optimalPbufferWidth == b->optimalPbufferWidth) && - (a->optimalPbufferHeight == b->optimalPbufferHeight) && - (a->swapMethod == b->swapMethod) && - (a->bindToTextureRgb == b->bindToTextureRgb) && - (a->bindToTextureRgba == b->bindToTextureRgba) && - (a->bindToMipmapTexture == b->bindToMipmapTexture) && - (a->bindToTextureTargets == b->bindToTextureTargets) && - (a->yInverted == b->yInverted) ); -} +/* + * (C) Copyright IBM Corporation 2003 + * 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 + * 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 + * 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 + * VA LINUX SYSTEM, IBM AND/OR THEIR 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. + */ + +/** + * \file glcontextmodes.c + * Utility routines for working with \c __GLcontextModes structures. At + * some point most or all of these functions will be moved to the Mesa + * code base. + * + * \author Ian Romanick <idr@us.ibm.com> + */ + +#if defined(IN_MINI_GLX) +#include <GL/gl.h> +#else +#if defined(HAVE_DIX_CONFIG_H) +# include <dix-config.h> +#endif +#include <X11/X.h> +#include <GL/glx.h> +#include "GL/glxint.h" +#endif + +/* Memory macros */ +#if defined(IN_MINI_GLX) +# include <stdlib.h> +# include <string.h> +# define _mesa_malloc(b) malloc(b) +# define _mesa_free(m) free(m) +# define _mesa_memset memset +#else +# ifdef XFree86Server +# include <os.h> +# include <string.h> +# define _mesa_malloc(b) malloc(b) +# define _mesa_free(m) free(m) +# define _mesa_memset memset +# else +# include <X11/Xlibint.h> +# define _mesa_memset memset +# define _mesa_malloc(b) Xmalloc(b) +# define _mesa_free(m) free(m) +# endif /* XFree86Server */ +#endif /* !defined(IN_MINI_GLX) */ + +#include "glcontextmodes.h" + +#if !defined(IN_MINI_GLX) +#define NUM_VISUAL_TYPES 6 + +/** + * Convert an X visual type to a GLX visual type. + * + * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) + * to be converted. + * \return If \c visualType is a valid X visual type, a GLX visual type will + * be returned. Otherwise \c GLX_NONE will be returned. + */ +GLint +_gl_convert_from_x_visual_type( int visualType ) +{ + static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { + GLX_STATIC_GRAY, GLX_GRAY_SCALE, + GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, + GLX_TRUE_COLOR, GLX_DIRECT_COLOR + }; + + return ( (unsigned) visualType < NUM_VISUAL_TYPES ) + ? glx_visual_types[ visualType ] : GLX_NONE; +} + + +/** + * Convert a GLX visual type to an X visual type. + * + * \param visualType GLX visual type (i.e., \c GLX_TRUE_COLOR, + * \c GLX_STATIC_GRAY, etc.) to be converted. + * \return If \c visualType is a valid GLX visual type, an X visual type will + * be returned. Otherwise -1 will be returned. + */ +GLint +_gl_convert_to_x_visual_type( int visualType ) +{ + static const int x_visual_types[ NUM_VISUAL_TYPES ] = { + TrueColor, DirectColor, + PseudoColor, StaticColor, + GrayScale, StaticGray + }; + + return ( (unsigned) (visualType - GLX_TRUE_COLOR) < NUM_VISUAL_TYPES ) + ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1; +} + + +/** + * Copy a GLX visual config structure to a GL context mode structure. All + * of the fields in \c config are copied to \c mode. Additional fields in + * \c mode that can be derrived from the fields of \c config (i.e., + * \c haveDepthBuffer) are also filled in. The remaining fields in \c mode + * that cannot be derived are set to default values. + * + * \param mode Destination GL context mode. + * \param config Source GLX visual config. + * + * \note + * The \c fbconfigID and \c visualID fields of the \c __GLcontextModes + * structure will be set to the \c vid of the \c __GLXvisualConfig structure. + */ +void +_gl_copy_visual_to_context_mode( __GLcontextModes * mode, + const __GLXvisualConfig * config ) +{ + __GLcontextModes * const next = mode->next; + + (void) _mesa_memset( mode, 0, sizeof( __GLcontextModes ) ); + mode->next = next; + + mode->visualID = config->vid; + mode->visualType = _gl_convert_from_x_visual_type( config->class ); + mode->xRenderable = GL_TRUE; + mode->fbconfigID = config->vid; + mode->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT; + + mode->rgbMode = (config->rgba != 0); + mode->renderType = (mode->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; + + mode->colorIndexMode = !(mode->rgbMode); + mode->doubleBufferMode = (config->doubleBuffer != 0); + mode->stereoMode = (config->stereo != 0); + + mode->haveAccumBuffer = ((config->accumRedSize + + config->accumGreenSize + + config->accumBlueSize + + config->accumAlphaSize) > 0); + mode->haveDepthBuffer = (config->depthSize > 0); + mode->haveStencilBuffer = (config->stencilSize > 0); + + mode->redBits = config->redSize; + mode->greenBits = config->greenSize; + mode->blueBits = config->blueSize; + mode->alphaBits = config->alphaSize; + mode->redMask = config->redMask; + mode->greenMask = config->greenMask; + mode->blueMask = config->blueMask; + mode->alphaMask = config->alphaMask; + mode->rgbBits = mode->rgbMode ? config->bufferSize : 0; + mode->indexBits = mode->colorIndexMode ? config->bufferSize : 0; + + mode->accumRedBits = config->accumRedSize; + mode->accumGreenBits = config->accumGreenSize; + mode->accumBlueBits = config->accumBlueSize; + mode->accumAlphaBits = config->accumAlphaSize; + mode->depthBits = config->depthSize; + mode->stencilBits = config->stencilSize; + + mode->numAuxBuffers = config->auxBuffers; + mode->level = config->level; + + mode->visualRating = config->visualRating; + mode->transparentPixel = config->transparentPixel; + mode->transparentRed = config->transparentRed; + mode->transparentGreen = config->transparentGreen; + mode->transparentBlue = config->transparentBlue; + mode->transparentAlpha = config->transparentAlpha; + mode->transparentIndex = config->transparentIndex; + mode->samples = config->multiSampleSize; + mode->sampleBuffers = config->nMultiSampleBuffers; + /* mode->visualSelectGroup = config->visualSelectGroup; ? */ + + mode->swapMethod = GLX_SWAP_UNDEFINED_OML; + + mode->bindToTextureRgb = (mode->rgbMode) ? GL_TRUE : GL_FALSE; + mode->bindToTextureRgba = (mode->rgbMode && mode->alphaBits) ? + GL_TRUE : GL_FALSE; + mode->bindToMipmapTexture = mode->rgbMode ? GL_TRUE : GL_FALSE; + mode->bindToTextureTargets = mode->rgbMode ? + GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT : 0; + mode->yInverted = GL_FALSE; +} + + +/** + * Get data from a GL context mode. + * + * \param mode GL context mode whose data is to be returned. + * \param attribute Attribute of \c mode that is to be returned. + * \param value_return Location to store the data member of \c mode. + * \return If \c attribute is a valid attribute of \c mode, zero is + * returned. Otherwise \c GLX_BAD_ATTRIBUTE is returned. + */ +int +_gl_get_context_mode_data(const __GLcontextModes *mode, int attribute, + int *value_return) +{ + switch (attribute) { + case GLX_USE_GL: + *value_return = GL_TRUE; + return 0; + case GLX_BUFFER_SIZE: + *value_return = mode->rgbBits; + return 0; + case GLX_RGBA: + *value_return = mode->rgbMode; + return 0; + case GLX_RED_SIZE: + *value_return = mode->redBits; + return 0; + case GLX_GREEN_SIZE: + *value_return = mode->greenBits; + return 0; + case GLX_BLUE_SIZE: + *value_return = mode->blueBits; + return 0; + case GLX_ALPHA_SIZE: + *value_return = mode->alphaBits; + return 0; + case GLX_DOUBLEBUFFER: + *value_return = mode->doubleBufferMode; + return 0; + case GLX_STEREO: + *value_return = mode->stereoMode; + return 0; + case GLX_AUX_BUFFERS: + *value_return = mode->numAuxBuffers; + return 0; + case GLX_DEPTH_SIZE: + *value_return = mode->depthBits; + return 0; + case GLX_STENCIL_SIZE: + *value_return = mode->stencilBits; + return 0; + case GLX_ACCUM_RED_SIZE: + *value_return = mode->accumRedBits; + return 0; + case GLX_ACCUM_GREEN_SIZE: + *value_return = mode->accumGreenBits; + return 0; + case GLX_ACCUM_BLUE_SIZE: + *value_return = mode->accumBlueBits; + return 0; + case GLX_ACCUM_ALPHA_SIZE: + *value_return = mode->accumAlphaBits; + return 0; + case GLX_LEVEL: + *value_return = mode->level; + return 0; + case GLX_TRANSPARENT_TYPE_EXT: + *value_return = mode->transparentPixel; + return 0; + case GLX_TRANSPARENT_RED_VALUE: + *value_return = mode->transparentRed; + return 0; + case GLX_TRANSPARENT_GREEN_VALUE: + *value_return = mode->transparentGreen; + return 0; + case GLX_TRANSPARENT_BLUE_VALUE: + *value_return = mode->transparentBlue; + return 0; + case GLX_TRANSPARENT_ALPHA_VALUE: + *value_return = mode->transparentAlpha; + return 0; + case GLX_TRANSPARENT_INDEX_VALUE: + *value_return = mode->transparentIndex; + return 0; + case GLX_X_VISUAL_TYPE: + *value_return = mode->visualType; + return 0; + case GLX_CONFIG_CAVEAT: + *value_return = mode->visualRating; + return 0; + case GLX_VISUAL_ID: + *value_return = mode->visualID; + return 0; + case GLX_DRAWABLE_TYPE: + *value_return = mode->drawableType; + return 0; + case GLX_RENDER_TYPE: + *value_return = mode->renderType; + return 0; + case GLX_X_RENDERABLE: + *value_return = mode->xRenderable; + return 0; + case GLX_FBCONFIG_ID: + *value_return = mode->fbconfigID; + return 0; + case GLX_MAX_PBUFFER_WIDTH: + *value_return = mode->maxPbufferWidth; + return 0; + case GLX_MAX_PBUFFER_HEIGHT: + *value_return = mode->maxPbufferHeight; + return 0; + case GLX_MAX_PBUFFER_PIXELS: + *value_return = mode->maxPbufferPixels; + return 0; + case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: + *value_return = mode->optimalPbufferWidth; + return 0; + case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: + *value_return = mode->optimalPbufferHeight; + return 0; + case GLX_SWAP_METHOD_OML: + *value_return = mode->swapMethod; + return 0; + case GLX_SAMPLE_BUFFERS_SGIS: + *value_return = mode->sampleBuffers; + return 0; + case GLX_SAMPLES_SGIS: + *value_return = mode->samples; + return 0; + case GLX_BIND_TO_TEXTURE_RGB_EXT: + *value_return = mode->bindToTextureRgb; + return 0; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + *value_return = mode->bindToTextureRgba; + return 0; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + *value_return = mode->bindToMipmapTexture == GL_TRUE ? GL_TRUE : + GL_FALSE; + return 0; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + *value_return = mode->bindToTextureTargets; + return 0; + case GLX_Y_INVERTED_EXT: + *value_return = mode->yInverted; + return 0; + + /* Applications are NOT allowed to query GLX_VISUAL_SELECT_GROUP_SGIX. + * It is ONLY for communication between the GLX client and the GLX + * server. + */ + case GLX_VISUAL_SELECT_GROUP_SGIX: + default: + return GLX_BAD_ATTRIBUTE; + } +} +#endif /* !defined(IN_MINI_GLX) */ + + +/** + * Allocate a linked list of \c __GLcontextModes structures. The fields of + * each structure will be initialized to "reasonable" default values. In + * most cases this is the default value defined by table 3.4 of the GLX + * 1.3 specification. This means that most values are either initialized to + * zero or \c GLX_DONT_CARE (which is -1). As support for additional + * extensions is added, the new values will be initialized to appropriate + * values from the extension specification. + * + * \param count Number of structures to allocate. + * \param minimum_size Minimum size of a structure to allocate. This allows + * for differences in the version of the + * \c __GLcontextModes stucture used in libGL and in a + * DRI-based driver. + * \returns A pointer to the first element in a linked list of \c count + * stuctures on success, or \c NULL on failure. + * + * \warning Use of \c minimum_size does \b not guarantee binary compatibility. + * The fundamental assumption is that if the \c minimum_size + * specified by the driver and the size of the \c __GLcontextModes + * structure in libGL is the same, then the meaning of each byte in + * the structure is the same in both places. \b Be \b careful! + * Basically this means that fields have to be added in libGL and + * then propagated to drivers. Drivers should \b never arbitrarilly + * extend the \c __GLcontextModes data-structure. + */ +__GLcontextModes * +_gl_context_modes_create( unsigned count, size_t minimum_size ) +{ + const size_t size = (minimum_size > sizeof( __GLcontextModes )) + ? minimum_size : sizeof( __GLcontextModes ); + __GLcontextModes * base = NULL; + __GLcontextModes ** next; + unsigned i; + + next = & base; + for ( i = 0 ; i < count ; i++ ) { + *next = (__GLcontextModes *) _mesa_malloc( size ); + if ( *next == NULL ) { + _gl_context_modes_destroy( base ); + base = NULL; + break; + } + + (void) _mesa_memset( *next, 0, size ); + (*next)->visualID = GLX_DONT_CARE; + (*next)->visualType = GLX_DONT_CARE; + (*next)->visualRating = GLX_NONE; + (*next)->transparentPixel = GLX_NONE; + (*next)->transparentRed = GLX_DONT_CARE; + (*next)->transparentGreen = GLX_DONT_CARE; + (*next)->transparentBlue = GLX_DONT_CARE; + (*next)->transparentAlpha = GLX_DONT_CARE; + (*next)->transparentIndex = GLX_DONT_CARE; + (*next)->xRenderable = GLX_DONT_CARE; + (*next)->fbconfigID = GLX_DONT_CARE; + (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; + (*next)->bindToTextureRgb = GLX_DONT_CARE; + (*next)->bindToTextureRgba = GLX_DONT_CARE; + (*next)->bindToMipmapTexture = GLX_DONT_CARE; + (*next)->bindToTextureTargets = GLX_DONT_CARE; + (*next)->yInverted = GLX_DONT_CARE; + + next = & ((*next)->next); + } + + return base; +} + + +/** + * Destroy a linked list of \c __GLcontextModes structures created by + * \c _gl_context_modes_create. + * + * \param modes Linked list of structures to be destroyed. All structres + * in the list will be freed. + */ +void +_gl_context_modes_destroy( __GLcontextModes * modes ) +{ + while ( modes != NULL ) { + __GLcontextModes * const next = modes->next; + + _mesa_free( modes ); + modes = next; + } +} + + +/** + * Find a context mode matching a Visual ID. + * + * \param modes List list of context-mode structures to be searched. + * \param vid Visual ID to be found. + * \returns A pointer to a context-mode in \c modes if \c vid was found in + * the list, or \c NULL if it was not. + */ + +__GLcontextModes * +_gl_context_modes_find_visual(__GLcontextModes *modes, int vid) +{ + __GLcontextModes *m; + + for (m = modes; m != NULL; m = m->next) + if (m->visualID == vid) + return m; + + return NULL; +} + +__GLcontextModes * +_gl_context_modes_find_fbconfig(__GLcontextModes *modes, int fbid) +{ + __GLcontextModes *m; + + for (m = modes; m != NULL; m = m->next) + if (m->fbconfigID == fbid) + return m; + + return NULL; +} + +/** + * Determine if two context-modes are the same. This is intended to be used + * by libGL implementations to compare to sets of driver generated FBconfigs. + * + * \param a Context-mode to be compared. + * \param b Context-mode to be compared. + * \returns \c GL_TRUE if the two context-modes are the same. \c GL_FALSE is + * returned otherwise. + */ +GLboolean +_gl_context_modes_are_same( const __GLcontextModes * a, + const __GLcontextModes * b ) +{ + return( (a->rgbMode == b->rgbMode) && + (a->floatMode == b->floatMode) && + (a->colorIndexMode == b->colorIndexMode) && + (a->doubleBufferMode == b->doubleBufferMode) && + (a->stereoMode == b->stereoMode) && + (a->redBits == b->redBits) && + (a->greenBits == b->greenBits) && + (a->blueBits == b->blueBits) && + (a->alphaBits == b->alphaBits) && +#if 0 /* For some reason these don't get set on the client-side in libGL. */ + (a->redMask == b->redMask) && + (a->greenMask == b->greenMask) && + (a->blueMask == b->blueMask) && + (a->alphaMask == b->alphaMask) && +#endif + (a->rgbBits == b->rgbBits) && + (a->indexBits == b->indexBits) && + (a->accumRedBits == b->accumRedBits) && + (a->accumGreenBits == b->accumGreenBits) && + (a->accumBlueBits == b->accumBlueBits) && + (a->accumAlphaBits == b->accumAlphaBits) && + (a->depthBits == b->depthBits) && + (a->stencilBits == b->stencilBits) && + (a->numAuxBuffers == b->numAuxBuffers) && + (a->level == b->level) && + (a->pixmapMode == b->pixmapMode) && + (a->visualRating == b->visualRating) && + + (a->transparentPixel == b->transparentPixel) && + + ((a->transparentPixel != GLX_TRANSPARENT_RGB) || + ((a->transparentRed == b->transparentRed) && + (a->transparentGreen == b->transparentGreen) && + (a->transparentBlue == b->transparentBlue) && + (a->transparentAlpha == b->transparentAlpha))) && + + ((a->transparentPixel != GLX_TRANSPARENT_INDEX) || + (a->transparentIndex == b->transparentIndex)) && + + (a->sampleBuffers == b->sampleBuffers) && + (a->samples == b->samples) && + ((a->drawableType & b->drawableType) != 0) && + (a->renderType == b->renderType) && + (a->maxPbufferWidth == b->maxPbufferWidth) && + (a->maxPbufferHeight == b->maxPbufferHeight) && + (a->maxPbufferPixels == b->maxPbufferPixels) && + (a->optimalPbufferWidth == b->optimalPbufferWidth) && + (a->optimalPbufferHeight == b->optimalPbufferHeight) && + (a->swapMethod == b->swapMethod) && + (a->bindToTextureRgb == b->bindToTextureRgb) && + (a->bindToTextureRgba == b->bindToTextureRgba) && + (a->bindToMipmapTexture == b->bindToMipmapTexture) && + (a->bindToTextureTargets == b->bindToTextureTargets) && + (a->yInverted == b->yInverted) ); +} diff --git a/xorg-server/hw/xquartz/GL/indirect.c b/xorg-server/hw/xquartz/GL/indirect.c index e56dac1a1..b40f38d31 100644 --- a/xorg-server/hw/xquartz/GL/indirect.c +++ b/xorg-server/hw/xquartz/GL/indirect.c @@ -222,7 +222,7 @@ __glXAquaScreenCreateContext(__GLXscreen *screen, GLAQUA_DEBUG_MSG("glXAquaScreenCreateContext\n"); - context = xcalloc(1, sizeof (__GLXAquaContext)); + context = calloc(1, sizeof (__GLXAquaContext)); if (context == NULL) return NULL; @@ -241,7 +241,7 @@ __glXAquaScreenCreateContext(__GLXscreen *screen, context->pixelFormat = makeFormat(conf); if (!context->pixelFormat) { - xfree(context); + free(context); return NULL; } @@ -253,7 +253,7 @@ __glXAquaScreenCreateContext(__GLXscreen *screen, if (gl_err != 0) { ErrorF("CGLCreateContext error: %s\n", CGLErrorString(gl_err)); CGLDestroyPixelFormat(context->pixelFormat); - xfree(context); + free(context); return NULL; } @@ -286,7 +286,7 @@ static void __glXAquaContextDestroy(__GLXcontext *baseContext) { if (context->pixelFormat != NULL) CGLDestroyPixelFormat(context->pixelFormat); - xfree(context); + free(context); } } @@ -566,7 +566,7 @@ static void __glXAquaScreenDestroy(__GLXscreen *screen) { GLAQUA_DEBUG_MSG("glXAquaScreenDestroy(%p)\n", screen); __glXScreenDestroy(screen); - xfree(screen); + free(screen); } /* This is called by __glXInitScreens(). */ @@ -578,7 +578,7 @@ static __GLXscreen * __glXAquaScreenProbe(ScreenPtr pScreen) { if (pScreen == NULL) return NULL; - screen = xcalloc(1, sizeof *screen); + screen = calloc(1, sizeof *screen); if(NULL == screen) return NULL; @@ -635,7 +635,7 @@ static void __glXAquaDrawableDestroy(__GLXdrawable *base) { *to validate the test, beyond using gdb with print. */ - xfree(glxPriv); + free(glxPriv); } static __GLXdrawable * @@ -648,7 +648,7 @@ __glXAquaScreenCreateDrawable(ClientPtr client, __GLXconfig *conf) { __GLXAquaDrawable *glxPriv; - glxPriv = xalloc(sizeof *glxPriv); + glxPriv = malloc(sizeof *glxPriv); if(glxPriv == NULL) return NULL; @@ -656,7 +656,7 @@ __glXAquaScreenCreateDrawable(ClientPtr client, memset(glxPriv, 0, sizeof *glxPriv); if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, glxDrawId, conf)) { - xfree(glxPriv); + free(glxPriv); return NULL; } diff --git a/xorg-server/hw/xquartz/GL/visualConfigs.c b/xorg-server/hw/xquartz/GL/visualConfigs.c index cecc90265..0d5793262 100644 --- a/xorg-server/hw/xquartz/GL/visualConfigs.c +++ b/xorg-server/hw/xquartz/GL/visualConfigs.c @@ -1,285 +1,285 @@ -/* - * Copyright (c) 2007, 2008 Apple Inc. - * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved. - * Copyright (c) 2002 Greg Parker. All Rights Reserved. - * - * Portions of this file are copied from Mesa's xf86glx.c, - * which contains the following copyright: - * - * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - * 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 ABOVE LISTED COPYRIGHT HOLDER(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. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "dri.h" - -#include <OpenGL/OpenGL.h> -#include <OpenGL/gl.h> -#include <OpenGL/glext.h> -#include <OpenGL/CGLContext.h> - -#include <GL/glxproto.h> -#include <windowstr.h> -#include <resource.h> -#include <GL/glxint.h> -#include <GL/glxtokens.h> -#include <scrnintstr.h> -#include <glxserver.h> -#include <glxscreens.h> -#include <glxdrawable.h> -#include <glxcontext.h> -#include <glxext.h> -#include <glxutil.h> -#include <glxscreens.h> -#include <GL/internal/glcore.h> - -#include "capabilities.h" -#include "visualConfigs.h" -#include "darwinfb.h" - -/* Based originally on code from indirect.c which was based on code from i830_dri.c. */ -__GLXconfig *__glXAquaCreateVisualConfigs(int *numConfigsPtr, int screenNumber) { - int numConfigs = 0; - __GLXconfig *visualConfigs, *c; - struct glCapabilities caps; - struct glCapabilitiesConfig *conf; - int stereo, depth, aux, buffers, stencil, accum, color, msample; - - if(getGlCapabilities(&caps)) { - ErrorF("error from getGlCapabilities()!\n"); - return NULL; - } - - /* - conf->stereo is 0 or 1, but we need at least 1 iteration of the loop, - so we treat a true conf->stereo as 2. - - The depth size is 0 or 24. Thus we do 2 iterations for that. - - conf->aux_buffers (when available/non-zero) result in 2 iterations instead of 1. - - conf->buffers indicates whether we have single or double buffering. - - conf->total_stencil_bit_depths - - conf->total_color_buffers indicates the RGB/RGBA color depths. - - conf->total_accum_buffers iterations for accum (with at least 1 if equal to 0) - - conf->total_depth_buffer_depths - - conf->multisample_buffers iterations (with at least 1 if equal to 0). We add 1 - for the 0 multisampling config. - - */ - - assert(NULL != caps.configurations); - - numConfigs = 0; - - for(conf = caps.configurations; conf; conf = conf->next) { - if(conf->total_color_buffers <= 0) - continue; - - numConfigs += (conf->stereo ? 2 : 1) - * (conf->aux_buffers ? 2 : 1) - * conf->buffers - * ((conf->total_stencil_bit_depths > 0) ? conf->total_stencil_bit_depths : 1) - * conf->total_color_buffers - * ((conf->total_accum_buffers > 0) ? conf->total_accum_buffers : 1) - * conf->total_depth_buffer_depths - * (conf->multisample_buffers + 1); - } - - if(numConfigsPtr) - *numConfigsPtr = numConfigs; - - visualConfigs = xcalloc(sizeof(*visualConfigs), numConfigs); - - if(NULL == visualConfigs) { - ErrorF("xcalloc failure when allocating visualConfigs\n"); - freeGlCapabilities(&caps); - return NULL; - } - - c = visualConfigs; /* current buffer */ - for(conf = caps.configurations; conf; conf = conf->next) { - for(stereo = 0; stereo < (conf->stereo ? 2 : 1); ++stereo) { - for(aux = 0; aux < (conf->aux_buffers ? 2 : 1); ++aux) { - for(buffers = 0; buffers < conf->buffers; ++buffers) { - for(stencil = 0; stencil < ((conf->total_stencil_bit_depths > 0) ? - conf->total_stencil_bit_depths : 1); ++stencil) { - for(color = 0; color < conf->total_color_buffers; ++color) { - for(accum = 0; accum < ((conf->total_accum_buffers > 0) ? - conf->total_accum_buffers : 1); ++accum) { - for(depth = 0; depth < conf->total_depth_buffer_depths; ++depth) { - for(msample = 0; msample < (conf->multisample_buffers + 1); ++msample) { - - // Global - c->visualID = -1; - c->visualType = GLX_TRUE_COLOR; - c->next = c + 1; - - c->screen = screenNumber; - - c->level = 0; - c->indexBits = 0; - c->pixmapMode = 0; // TODO: What should this be? - - if(conf->accelerated) { - c->visualRating = GLX_NONE; - } else { - c->visualRating = GLX_SLOW_VISUAL_EXT; - } - - c->transparentPixel = GLX_NONE; - c->transparentRed = GLX_NONE; - c->transparentGreen = GLX_NONE; - c->transparentBlue = GLX_NONE; - c->transparentAlpha = GLX_NONE; - c->transparentIndex = GLX_NONE; - - c->visualSelectGroup = 0; - - c->swapMethod = GLX_SWAP_UNDEFINED_OML; - - // Stereo - c->stereoMode = stereo ? TRUE : FALSE; - - // Aux buffers - c->numAuxBuffers = aux ? conf->aux_buffers : 0; - - // Double Buffered - c->doubleBufferMode = buffers ? TRUE : FALSE; - - // Stencil Buffer - if(conf->total_stencil_bit_depths > 0) { - c->stencilBits = conf->stencil_bit_depths[stencil]; - } else { - c->stencilBits = 0; - } - - // Color - if(GLCAPS_COLOR_BUF_INVALID_VALUE != conf->color_buffers[color].a) { - c->alphaBits = conf->color_buffers[color].a; - } else { - c->alphaBits = 0; - } - c->redBits = conf->color_buffers[color].r; - c->greenBits = conf->color_buffers[color].g; - c->blueBits = conf->color_buffers[color].b; - - c->rgbBits = c->alphaBits + c->redBits + c->greenBits + c->blueBits; - - c->alphaMask = AM_ARGB(c->alphaBits, c->redBits, c->greenBits, c->blueBits); - c->redMask = RM_ARGB(c->alphaBits, c->redBits, c->greenBits, c->blueBits); - c->greenMask = GM_ARGB(c->alphaBits, c->redBits, c->greenBits, c->blueBits); - c->blueMask = BM_ARGB(c->alphaBits, c->redBits, c->greenBits, c->blueBits); - - // Accumulation Buffers - if(conf->total_accum_buffers > 0) { - c->accumRedBits = conf->accum_buffers[accum].r; - c->accumGreenBits = conf->accum_buffers[accum].g; - c->accumBlueBits = conf->accum_buffers[accum].b; - if(GLCAPS_COLOR_BUF_INVALID_VALUE != conf->accum_buffers[accum].a) { - c->accumAlphaBits = conf->accum_buffers[accum].a; - } else { - c->accumAlphaBits = 0; - } - } else { - c->accumRedBits = 0; - c->accumGreenBits = 0; - c->accumBlueBits = 0; - c->accumAlphaBits = 0; - } - - // Depth - c->depthBits = conf->depth_buffers[depth]; - - // MultiSample - if(msample > 0) { - c->samples = conf->multisample_samples; - c->sampleBuffers = conf->multisample_buffers; - } else { - c->samples = 0; - c->sampleBuffers = 0; - } - - /* - * The Apple libGL supports GLXPixmaps and - * GLXPbuffers in direct mode. - */ - /* SGIX_fbconfig / GLX 1.3 */ - c->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; - c->renderType = GLX_RGBA_BIT; - c->xRenderable = GL_TRUE; - c->fbconfigID = -1; - - /* SGIX_pbuffer / GLX 1.3 */ - - /* - * The CGL layer provides a way of retrieving - * the maximum pbuffer width/height, but only - * if we create a context and call glGetIntegerv. - * - * The following values are from a test program - * that does so. - */ - c->maxPbufferWidth = 8192; - c->maxPbufferHeight = 8192; - c->maxPbufferPixels = /*Do we need this?*/ 0; - /* - * There is no introspection for this sort of thing - * with CGL. What should we do realistically? - */ - c->optimalPbufferWidth = 0; - c->optimalPbufferHeight = 0; - - /* EXT_texture_from_pixmap */ - c->bindToTextureRgb = 0; - c->bindToTextureRgba = 0; - c->bindToMipmapTexture = 0; - c->bindToTextureTargets = 0; - c->yInverted = 0; - - c = c->next; - } - } - } - } - } - } - } - } - } - - (c-1)->next = NULL; - - if (c - visualConfigs != numConfigs) { - FatalError("numConfigs calculation error in setVisualConfigs! numConfigs is %d i is %d\n", numConfigs, (int)(c - visualConfigs)); - } - - freeGlCapabilities(&caps); - return visualConfigs; -} +/* + * Copyright (c) 2007, 2008 Apple Inc. + * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002 Greg Parker. All Rights Reserved. + * + * Portions of this file are copied from Mesa's xf86glx.c, + * which contains the following copyright: + * + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * 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 ABOVE LISTED COPYRIGHT HOLDER(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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "dri.h" + +#include <OpenGL/OpenGL.h> +#include <OpenGL/gl.h> +#include <OpenGL/glext.h> +#include <OpenGL/CGLContext.h> + +#include <GL/glxproto.h> +#include <windowstr.h> +#include <resource.h> +#include <GL/glxint.h> +#include <GL/glxtokens.h> +#include <scrnintstr.h> +#include <glxserver.h> +#include <glxscreens.h> +#include <glxdrawable.h> +#include <glxcontext.h> +#include <glxext.h> +#include <glxutil.h> +#include <glxscreens.h> +#include <GL/internal/glcore.h> + +#include "capabilities.h" +#include "visualConfigs.h" +#include "darwinfb.h" + +/* Based originally on code from indirect.c which was based on code from i830_dri.c. */ +__GLXconfig *__glXAquaCreateVisualConfigs(int *numConfigsPtr, int screenNumber) { + int numConfigs = 0; + __GLXconfig *visualConfigs, *c; + struct glCapabilities caps; + struct glCapabilitiesConfig *conf; + int stereo, depth, aux, buffers, stencil, accum, color, msample; + + if(getGlCapabilities(&caps)) { + ErrorF("error from getGlCapabilities()!\n"); + return NULL; + } + + /* + conf->stereo is 0 or 1, but we need at least 1 iteration of the loop, + so we treat a true conf->stereo as 2. + + The depth size is 0 or 24. Thus we do 2 iterations for that. + + conf->aux_buffers (when available/non-zero) result in 2 iterations instead of 1. + + conf->buffers indicates whether we have single or double buffering. + + conf->total_stencil_bit_depths + + conf->total_color_buffers indicates the RGB/RGBA color depths. + + conf->total_accum_buffers iterations for accum (with at least 1 if equal to 0) + + conf->total_depth_buffer_depths + + conf->multisample_buffers iterations (with at least 1 if equal to 0). We add 1 + for the 0 multisampling config. + + */ + + assert(NULL != caps.configurations); + + numConfigs = 0; + + for(conf = caps.configurations; conf; conf = conf->next) { + if(conf->total_color_buffers <= 0) + continue; + + numConfigs += (conf->stereo ? 2 : 1) + * (conf->aux_buffers ? 2 : 1) + * conf->buffers + * ((conf->total_stencil_bit_depths > 0) ? conf->total_stencil_bit_depths : 1) + * conf->total_color_buffers + * ((conf->total_accum_buffers > 0) ? conf->total_accum_buffers : 1) + * conf->total_depth_buffer_depths + * (conf->multisample_buffers + 1); + } + + if(numConfigsPtr) + *numConfigsPtr = numConfigs; + + visualConfigs = calloc(sizeof(*visualConfigs), numConfigs); + + if(NULL == visualConfigs) { + ErrorF("xcalloc failure when allocating visualConfigs\n"); + freeGlCapabilities(&caps); + return NULL; + } + + c = visualConfigs; /* current buffer */ + for(conf = caps.configurations; conf; conf = conf->next) { + for(stereo = 0; stereo < (conf->stereo ? 2 : 1); ++stereo) { + for(aux = 0; aux < (conf->aux_buffers ? 2 : 1); ++aux) { + for(buffers = 0; buffers < conf->buffers; ++buffers) { + for(stencil = 0; stencil < ((conf->total_stencil_bit_depths > 0) ? + conf->total_stencil_bit_depths : 1); ++stencil) { + for(color = 0; color < conf->total_color_buffers; ++color) { + for(accum = 0; accum < ((conf->total_accum_buffers > 0) ? + conf->total_accum_buffers : 1); ++accum) { + for(depth = 0; depth < conf->total_depth_buffer_depths; ++depth) { + for(msample = 0; msample < (conf->multisample_buffers + 1); ++msample) { + + // Global + c->visualID = -1; + c->visualType = GLX_TRUE_COLOR; + c->next = c + 1; + + c->screen = screenNumber; + + c->level = 0; + c->indexBits = 0; + c->pixmapMode = 0; // TODO: What should this be? + + if(conf->accelerated) { + c->visualRating = GLX_NONE; + } else { + c->visualRating = GLX_SLOW_VISUAL_EXT; + } + + c->transparentPixel = GLX_NONE; + c->transparentRed = GLX_NONE; + c->transparentGreen = GLX_NONE; + c->transparentBlue = GLX_NONE; + c->transparentAlpha = GLX_NONE; + c->transparentIndex = GLX_NONE; + + c->visualSelectGroup = 0; + + c->swapMethod = GLX_SWAP_UNDEFINED_OML; + + // Stereo + c->stereoMode = stereo ? TRUE : FALSE; + + // Aux buffers + c->numAuxBuffers = aux ? conf->aux_buffers : 0; + + // Double Buffered + c->doubleBufferMode = buffers ? TRUE : FALSE; + + // Stencil Buffer + if(conf->total_stencil_bit_depths > 0) { + c->stencilBits = conf->stencil_bit_depths[stencil]; + } else { + c->stencilBits = 0; + } + + // Color + if(GLCAPS_COLOR_BUF_INVALID_VALUE != conf->color_buffers[color].a) { + c->alphaBits = conf->color_buffers[color].a; + } else { + c->alphaBits = 0; + } + c->redBits = conf->color_buffers[color].r; + c->greenBits = conf->color_buffers[color].g; + c->blueBits = conf->color_buffers[color].b; + + c->rgbBits = c->alphaBits + c->redBits + c->greenBits + c->blueBits; + + c->alphaMask = AM_ARGB(c->alphaBits, c->redBits, c->greenBits, c->blueBits); + c->redMask = RM_ARGB(c->alphaBits, c->redBits, c->greenBits, c->blueBits); + c->greenMask = GM_ARGB(c->alphaBits, c->redBits, c->greenBits, c->blueBits); + c->blueMask = BM_ARGB(c->alphaBits, c->redBits, c->greenBits, c->blueBits); + + // Accumulation Buffers + if(conf->total_accum_buffers > 0) { + c->accumRedBits = conf->accum_buffers[accum].r; + c->accumGreenBits = conf->accum_buffers[accum].g; + c->accumBlueBits = conf->accum_buffers[accum].b; + if(GLCAPS_COLOR_BUF_INVALID_VALUE != conf->accum_buffers[accum].a) { + c->accumAlphaBits = conf->accum_buffers[accum].a; + } else { + c->accumAlphaBits = 0; + } + } else { + c->accumRedBits = 0; + c->accumGreenBits = 0; + c->accumBlueBits = 0; + c->accumAlphaBits = 0; + } + + // Depth + c->depthBits = conf->depth_buffers[depth]; + + // MultiSample + if(msample > 0) { + c->samples = conf->multisample_samples; + c->sampleBuffers = conf->multisample_buffers; + } else { + c->samples = 0; + c->sampleBuffers = 0; + } + + /* + * The Apple libGL supports GLXPixmaps and + * GLXPbuffers in direct mode. + */ + /* SGIX_fbconfig / GLX 1.3 */ + c->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; + c->renderType = GLX_RGBA_BIT; + c->xRenderable = GL_TRUE; + c->fbconfigID = -1; + + /* SGIX_pbuffer / GLX 1.3 */ + + /* + * The CGL layer provides a way of retrieving + * the maximum pbuffer width/height, but only + * if we create a context and call glGetIntegerv. + * + * The following values are from a test program + * that does so. + */ + c->maxPbufferWidth = 8192; + c->maxPbufferHeight = 8192; + c->maxPbufferPixels = /*Do we need this?*/ 0; + /* + * There is no introspection for this sort of thing + * with CGL. What should we do realistically? + */ + c->optimalPbufferWidth = 0; + c->optimalPbufferHeight = 0; + + /* EXT_texture_from_pixmap */ + c->bindToTextureRgb = 0; + c->bindToTextureRgba = 0; + c->bindToMipmapTexture = 0; + c->bindToTextureTargets = 0; + c->yInverted = 0; + + c = c->next; + } + } + } + } + } + } + } + } + } + + (c-1)->next = NULL; + + if (c - visualConfigs != numConfigs) { + FatalError("numConfigs calculation error in setVisualConfigs! numConfigs is %d i is %d\n", numConfigs, (int)(c - visualConfigs)); + } + + freeGlCapabilities(&caps); + return visualConfigs; +} diff --git a/xorg-server/hw/xquartz/applewm.c b/xorg-server/hw/xquartz/applewm.c index 15c86de00..b0f811750 100644 --- a/xorg-server/hw/xquartz/applewm.c +++ b/xorg-server/hw/xquartz/applewm.c @@ -1,746 +1,746 @@ -/************************************************************************** - -Copyright (c) 2002-2007 Apple Inc. All Rights Reserved. -Copyright (c) 2003 Torrey T. Lyons. 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. - -**************************************************************************/ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "quartzCommon.h" - -#include "misc.h" -#include "dixstruct.h" -#include "globals.h" -#include "extnsionst.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "servermd.h" -#include "swaprep.h" -#include "propertyst.h" -#include <X11/Xatom.h> -#include "darwin.h" -#define _APPLEWM_SERVER_ -#include <X11/extensions/applewmproto.h> -#include "applewmExt.h" -#include "X11Application.h" -#include "protocol-versions.h" - -#define DEFINE_ATOM_HELPER(func,atom_name) \ -static Atom func (void) { \ - static int generation; \ - static Atom atom; \ - if (generation != serverGeneration) { \ - generation = serverGeneration; \ - atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ - } \ - return atom; \ -} - -DEFINE_ATOM_HELPER(xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN") -DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN") - -static AppleWMProcsPtr appleWMProcs; - -static int WMErrorBase; - -static DISPATCH_PROC(ProcAppleWMDispatch); -static DISPATCH_PROC(SProcAppleWMDispatch); - -static unsigned char WMReqCode = 0; -static int WMEventBase = 0; - -static RESTYPE ClientType, EventType; /* resource types for event masks */ -static XID eventResource; - -/* Currently selected events */ -static unsigned int eventMask = 0; - -static int WMFreeClient (pointer data, XID id); -static int WMFreeEvents (pointer data, XID id); -static void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to); - -typedef struct _WMEvent *WMEventPtr; -typedef struct _WMEvent { - WMEventPtr next; - ClientPtr client; - XID clientResource; - unsigned int mask; -} WMEventRec; - -static inline BoxRec -make_box (int x, int y, int w, int h) -{ - BoxRec r; - r.x1 = x; - r.y1 = y; - r.x2 = x + w; - r.y2 = y + h; - return r; -} - -void -AppleWMExtensionInit( - AppleWMProcsPtr procsPtr) -{ - ExtensionEntry* extEntry; - - ClientType = CreateNewResourceType(WMFreeClient, "WMClient"); - EventType = CreateNewResourceType(WMFreeEvents, "WMEvent"); - eventResource = FakeClientID(0); - - if (ClientType && EventType && - (extEntry = AddExtension(APPLEWMNAME, - AppleWMNumberEvents, - AppleWMNumberErrors, - ProcAppleWMDispatch, - SProcAppleWMDispatch, - NULL, - StandardMinorOpcode))) - { - WMReqCode = (unsigned char)extEntry->base; - WMErrorBase = extEntry->errorBase; - WMEventBase = extEntry->eventBase; - EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent; - appleWMProcs = procsPtr; - } -} - -/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */ -void -AppleWMSetScreenOrigin( - WindowPtr pWin -) -{ - int32_t data[2]; - - data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x - + darwinMainScreenX); - data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y - + darwinMainScreenY); - - dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(), - XA_INTEGER, 32, PropModeReplace, 2, data, TRUE); -} - -/* Window managers can set the _APPLE_NO_ORDER_IN property on windows - that are being genie-restored from the Dock. We want them to - be mapped but remain ordered-out until the animation - completes (when the Dock will order them in). */ -Bool -AppleWMDoReorderWindow( - WindowPtr pWin -) -{ - Atom atom; - PropertyPtr prop; - int rc; - - atom = xa_apple_no_order_in(); - rc = dixLookupProperty(&prop, pWin, atom, serverClient, DixReadAccess); - - if(Success == rc && prop->type == atom) - return 0; - - return 1; -} - - -static int -ProcAppleWMQueryVersion( - register ClientPtr client -) -{ - xAppleWMQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_APPLEWM_MAJOR_VERSION; - rep.minorVersion = SERVER_APPLEWM_MINOR_VERSION; - rep.patchVersion = SERVER_APPLEWM_PATCH_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - } - WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - - -/* events */ - -static inline void -updateEventMask (WMEventPtr *pHead) -{ - WMEventPtr pCur; - - eventMask = 0; - for (pCur = *pHead; pCur != NULL; pCur = pCur->next) - eventMask |= pCur->mask; -} - -/*ARGSUSED*/ -static int -WMFreeClient (pointer data, XID id) { - WMEventPtr pEvent; - WMEventPtr *pHead, pCur, pPrev; - int i; - - pEvent = (WMEventPtr) data; - i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess | DixWriteAccess | DixDestroyAccess); - if (i == Success && pHead) { - pPrev = 0; - for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next) - pPrev = pCur; - if (pCur) { - if (pPrev) - pPrev->next = pEvent->next; - else - *pHead = pEvent->next; - } - updateEventMask (pHead); - } - xfree ((pointer) pEvent); - return 1; -} - -/*ARGSUSED*/ -static int -WMFreeEvents (pointer data, XID id) { - WMEventPtr *pHead, pCur, pNext; - - pHead = (WMEventPtr *) data; - for (pCur = *pHead; pCur; pCur = pNext) { - pNext = pCur->next; - FreeResource (pCur->clientResource, ClientType); - xfree ((pointer) pCur); - } - xfree ((pointer) pHead); - eventMask = 0; - return 1; -} - -static int -ProcAppleWMSelectInput (register ClientPtr client) -{ - REQUEST(xAppleWMSelectInputReq); - WMEventPtr pEvent, pNewEvent, *pHead; - XID clientResource; - int i; - - REQUEST_SIZE_MATCH (xAppleWMSelectInputReq); - i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, client, DixWriteAccess); - if (stuff->mask != 0) { - if (i == Success && pHead) { - /* check for existing entry. */ - for (pEvent = *pHead; pEvent; pEvent = pEvent->next) - { - if (pEvent->client == client) - { - pEvent->mask = stuff->mask; - updateEventMask (pHead); - return Success; - } - } - } - - /* build the entry */ - pNewEvent = (WMEventPtr) xalloc (sizeof (WMEventRec)); - if (!pNewEvent) - return BadAlloc; - pNewEvent->next = 0; - pNewEvent->client = client; - pNewEvent->mask = stuff->mask; - /* - * add a resource that will be deleted when - * the client goes away - */ - clientResource = FakeClientID (client->index); - pNewEvent->clientResource = clientResource; - if (!AddResource (clientResource, ClientType, (pointer)pNewEvent)) - return BadAlloc; - /* - * create a resource to contain a pointer to the list - * of clients selecting input. This must be indirect as - * the list may be arbitrarily rearranged which cannot be - * done through the resource database. - */ - if (i != Success || !pHead) - { - pHead = (WMEventPtr *) xalloc (sizeof (WMEventPtr)); - if (!pHead || - !AddResource (eventResource, EventType, (pointer)pHead)) - { - FreeResource (clientResource, RT_NONE); - return BadAlloc; - } - *pHead = 0; - } - pNewEvent->next = *pHead; - *pHead = pNewEvent; - updateEventMask (pHead); - } else if (stuff->mask == 0) { - /* delete the interest */ - if (i == Success && pHead) { - pNewEvent = 0; - for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { - if (pEvent->client == client) - break; - pNewEvent = pEvent; - } - if (pEvent) { - FreeResource (pEvent->clientResource, ClientType); - if (pNewEvent) - pNewEvent->next = pEvent->next; - else - *pHead = pEvent->next; - xfree (pEvent); - updateEventMask (pHead); - } - } - } else { - client->errorValue = stuff->mask; - return BadValue; - } - return Success; -} - -/* - * deliver the event - */ - -void -AppleWMSendEvent (int type, unsigned int mask, int which, int arg) { - WMEventPtr *pHead, pEvent; - ClientPtr client; - xAppleWMNotifyEvent se; - int i; - - i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess); - if (i != Success || !pHead) - return; - for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { - client = pEvent->client; - if ((pEvent->mask & mask) == 0 - || client == serverClient || client->clientGone) - { - continue; - } - se.type = type + WMEventBase; - se.kind = which; - se.arg = arg; - se.sequenceNumber = client->sequence; - se.time = currentTime.milliseconds; - WriteEventsToClient (client, 1, (xEvent *) &se); - } -} - -/* Safe to call from any thread. */ -unsigned int -AppleWMSelectedEvents (void) -{ - return eventMask; -} - - -/* general utility functions */ - -static int -ProcAppleWMDisableUpdate( - register ClientPtr client -) -{ - REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq); - - appleWMProcs->DisableUpdate(); - - return (client->noClientException); -} - -static int -ProcAppleWMReenableUpdate( - register ClientPtr client -) -{ - REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq); - - appleWMProcs->EnableUpdate(); - - return (client->noClientException); -} - - -/* window functions */ - -static int -ProcAppleWMSetWindowMenu( - register ClientPtr client -) -{ - const char *bytes, **items; - char *shortcuts; - int max_len, nitems, i, j; - REQUEST(xAppleWMSetWindowMenuReq); - - REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq); - - nitems = stuff->nitems; - items = xalloc (sizeof (char *) * nitems); - shortcuts = xalloc (sizeof (char) * nitems); - - max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq); - bytes = (char *) &stuff[1]; - - for (i = j = 0; i < max_len && j < nitems;) - { - shortcuts[j] = bytes[i++]; - items[j++] = bytes + i; - - while (i < max_len) - { - if (bytes[i++] == 0) - break; - } - } - X11ApplicationSetWindowMenu (nitems, items, shortcuts); - free(items); - free(shortcuts); - - return (client->noClientException); -} - -static int -ProcAppleWMSetWindowMenuCheck( - register ClientPtr client -) -{ - REQUEST(xAppleWMSetWindowMenuCheckReq); - - REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq); - X11ApplicationSetWindowMenuCheck(stuff->index); - return (client->noClientException); -} - -static int -ProcAppleWMSetFrontProcess( - register ClientPtr client -) -{ - REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq); - - X11ApplicationSetFrontProcess(); - return (client->noClientException); -} - -static int -ProcAppleWMSetWindowLevel(register ClientPtr client) -{ - REQUEST(xAppleWMSetWindowLevelReq); - WindowPtr pWin; - int err; - - REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq); - - if (Success != dixLookupWindow(&pWin, stuff->window, client, - DixReadAccess)) - return BadValue; - - if (stuff->level < 0 || stuff->level >= AppleWMNumWindowLevels) { - return BadValue; - } - - err = appleWMProcs->SetWindowLevel(pWin, stuff->level); - if (err != Success) { - return err; - } - - return (client->noClientException); -} - -static int -ProcAppleWMSendPSN(register ClientPtr client) -{ - REQUEST(xAppleWMSendPSNReq); - int err; - - REQUEST_SIZE_MATCH(xAppleWMSendPSNReq); - - if(!appleWMProcs->SendPSN) - return BadRequest; - - err = appleWMProcs->SendPSN(stuff->psn_hi, stuff->psn_lo); - if (err != Success) { - return err; - } - - return (client->noClientException); -} - -static int -ProcAppleWMAttachTransient(register ClientPtr client) -{ - WindowPtr pWinChild, pWinParent; - REQUEST(xAppleWMAttachTransientReq); - int err; - - REQUEST_SIZE_MATCH(xAppleWMAttachTransientReq); - - if(!appleWMProcs->AttachTransient) - return BadRequest; - - if (Success != dixLookupWindow(&pWinChild, stuff->child, client, DixReadAccess)) - return BadValue; - - if(stuff->parent) { - if(Success != dixLookupWindow(&pWinParent, stuff->parent, client, DixReadAccess)) - return BadValue; - } else { - pWinParent = NULL; - } - - err = appleWMProcs->AttachTransient(pWinChild, pWinParent); - if (err != Success) { - return err; - } - - return (client->noClientException); -} - -static int -ProcAppleWMSetCanQuit( - register ClientPtr client -) -{ - REQUEST(xAppleWMSetCanQuitReq); - - REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq); - - X11ApplicationSetCanQuit(stuff->state); - return (client->noClientException); -} - - -/* frame functions */ - -static int -ProcAppleWMFrameGetRect( - register ClientPtr client -) -{ - xAppleWMFrameGetRectReply rep; - BoxRec ir, or, rr; - REQUEST(xAppleWMFrameGetRectReq); - - REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); - or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); - - if (appleWMProcs->FrameGetRect(stuff->frame_rect, - stuff->frame_class, - &or, &ir, &rr) != Success) - { - return BadValue; - } - - rep.x = rr.x1; - rep.y = rr.y1; - rep.w = rr.x2 - rr.x1; - rep.h = rr.y2 - rr.y1; - - WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcAppleWMFrameHitTest( - register ClientPtr client -) -{ - xAppleWMFrameHitTestReply rep; - BoxRec ir, or; - int ret; - REQUEST(xAppleWMFrameHitTestReq); - - REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); - or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); - - if (appleWMProcs->FrameHitTest(stuff->frame_class, stuff->px, - stuff->py, &or, &ir, &ret) != Success) - { - return BadValue; - } - - rep.ret = ret; - - WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcAppleWMFrameDraw( - register ClientPtr client -) -{ - BoxRec ir, or; - unsigned int title_length, title_max; - unsigned char *title_bytes; - REQUEST(xAppleWMFrameDrawReq); - WindowPtr pWin; - - REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq); - - if (Success != dixLookupWindow(&pWin, stuff->window, client, - DixReadAccess)) - return BadValue; - - ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); - or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); - - title_length = stuff->title_length; - title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq); - - if (title_max < title_length) - return BadValue; - - title_bytes = (unsigned char *) &stuff[1]; - - errno = appleWMProcs->FrameDraw(pWin, stuff->frame_class, - stuff->frame_attr, &or, &ir, - title_length, title_bytes); - if (errno != Success) { - return errno; - } - - return (client->noClientException); -} - - -/* dispatch */ - -static int -ProcAppleWMDispatch ( - register ClientPtr client -) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_AppleWMQueryVersion: - return ProcAppleWMQueryVersion(client); - } - - if (!LocalClient(client)) - return WMErrorBase + AppleWMClientNotLocal; - - switch (stuff->data) - { - case X_AppleWMSelectInput: - return ProcAppleWMSelectInput(client); - case X_AppleWMDisableUpdate: - return ProcAppleWMDisableUpdate(client); - case X_AppleWMReenableUpdate: - return ProcAppleWMReenableUpdate(client); - case X_AppleWMSetWindowMenu: - return ProcAppleWMSetWindowMenu(client); - case X_AppleWMSetWindowMenuCheck: - return ProcAppleWMSetWindowMenuCheck(client); - case X_AppleWMSetFrontProcess: - return ProcAppleWMSetFrontProcess(client); - case X_AppleWMSetWindowLevel: - return ProcAppleWMSetWindowLevel(client); - case X_AppleWMSetCanQuit: - return ProcAppleWMSetCanQuit(client); - case X_AppleWMFrameGetRect: - return ProcAppleWMFrameGetRect(client); - case X_AppleWMFrameHitTest: - return ProcAppleWMFrameHitTest(client); - case X_AppleWMFrameDraw: - return ProcAppleWMFrameDraw(client); - case X_AppleWMSendPSN: - return ProcAppleWMSendPSN(client); - case X_AppleWMAttachTransient: - return ProcAppleWMAttachTransient(client); - default: - return BadRequest; - } -} - -static void -SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to) { - to->type = from->type; - to->kind = from->kind; - cpswaps (from->sequenceNumber, to->sequenceNumber); - cpswapl (from->time, to->time); - cpswapl (from->arg, to->arg); -} - -static int -SProcAppleWMQueryVersion( - register ClientPtr client -) -{ - register int n; - REQUEST(xAppleWMQueryVersionReq); - swaps(&stuff->length, n); - return ProcAppleWMQueryVersion(client); -} - -static int -SProcAppleWMDispatch ( - register ClientPtr client -) -{ - REQUEST(xReq); - - /* It is bound to be non-local when there is byte swapping */ - if (!LocalClient(client)) - return WMErrorBase + AppleWMClientNotLocal; - - /* only local clients are allowed WM access */ - switch (stuff->data) - { - case X_AppleWMQueryVersion: - return SProcAppleWMQueryVersion(client); - default: - return BadRequest; - } -} +/************************************************************************** + +Copyright (c) 2002-2007 Apple Inc. All Rights Reserved. +Copyright (c) 2003 Torrey T. Lyons. 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. + +**************************************************************************/ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "quartzCommon.h" + +#include "misc.h" +#include "dixstruct.h" +#include "globals.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "servermd.h" +#include "swaprep.h" +#include "propertyst.h" +#include <X11/Xatom.h> +#include "darwin.h" +#define _APPLEWM_SERVER_ +#include <X11/extensions/applewmproto.h> +#include "applewmExt.h" +#include "X11Application.h" +#include "protocol-versions.h" + +#define DEFINE_ATOM_HELPER(func,atom_name) \ +static Atom func (void) { \ + static int generation; \ + static Atom atom; \ + if (generation != serverGeneration) { \ + generation = serverGeneration; \ + atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ + } \ + return atom; \ +} + +DEFINE_ATOM_HELPER(xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN") +DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN") + +static AppleWMProcsPtr appleWMProcs; + +static int WMErrorBase; + +static DISPATCH_PROC(ProcAppleWMDispatch); +static DISPATCH_PROC(SProcAppleWMDispatch); + +static unsigned char WMReqCode = 0; +static int WMEventBase = 0; + +static RESTYPE ClientType, EventType; /* resource types for event masks */ +static XID eventResource; + +/* Currently selected events */ +static unsigned int eventMask = 0; + +static int WMFreeClient (pointer data, XID id); +static int WMFreeEvents (pointer data, XID id); +static void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to); + +typedef struct _WMEvent *WMEventPtr; +typedef struct _WMEvent { + WMEventPtr next; + ClientPtr client; + XID clientResource; + unsigned int mask; +} WMEventRec; + +static inline BoxRec +make_box (int x, int y, int w, int h) +{ + BoxRec r; + r.x1 = x; + r.y1 = y; + r.x2 = x + w; + r.y2 = y + h; + return r; +} + +void +AppleWMExtensionInit( + AppleWMProcsPtr procsPtr) +{ + ExtensionEntry* extEntry; + + ClientType = CreateNewResourceType(WMFreeClient, "WMClient"); + EventType = CreateNewResourceType(WMFreeEvents, "WMEvent"); + eventResource = FakeClientID(0); + + if (ClientType && EventType && + (extEntry = AddExtension(APPLEWMNAME, + AppleWMNumberEvents, + AppleWMNumberErrors, + ProcAppleWMDispatch, + SProcAppleWMDispatch, + NULL, + StandardMinorOpcode))) + { + WMReqCode = (unsigned char)extEntry->base; + WMErrorBase = extEntry->errorBase; + WMEventBase = extEntry->eventBase; + EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent; + appleWMProcs = procsPtr; + } +} + +/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */ +void +AppleWMSetScreenOrigin( + WindowPtr pWin +) +{ + int32_t data[2]; + + data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x + + darwinMainScreenX); + data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y + + darwinMainScreenY); + + dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(), + XA_INTEGER, 32, PropModeReplace, 2, data, TRUE); +} + +/* Window managers can set the _APPLE_NO_ORDER_IN property on windows + that are being genie-restored from the Dock. We want them to + be mapped but remain ordered-out until the animation + completes (when the Dock will order them in). */ +Bool +AppleWMDoReorderWindow( + WindowPtr pWin +) +{ + Atom atom; + PropertyPtr prop; + int rc; + + atom = xa_apple_no_order_in(); + rc = dixLookupProperty(&prop, pWin, atom, serverClient, DixReadAccess); + + if(Success == rc && prop->type == atom) + return 0; + + return 1; +} + + +static int +ProcAppleWMQueryVersion( + register ClientPtr client +) +{ + xAppleWMQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_APPLEWM_MAJOR_VERSION; + rep.minorVersion = SERVER_APPLEWM_MINOR_VERSION; + rep.patchVersion = SERVER_APPLEWM_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep); + return Success; +} + + +/* events */ + +static inline void +updateEventMask (WMEventPtr *pHead) +{ + WMEventPtr pCur; + + eventMask = 0; + for (pCur = *pHead; pCur != NULL; pCur = pCur->next) + eventMask |= pCur->mask; +} + +/*ARGSUSED*/ +static int +WMFreeClient (pointer data, XID id) { + WMEventPtr pEvent; + WMEventPtr *pHead, pCur, pPrev; + int i; + + pEvent = (WMEventPtr) data; + i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess | DixWriteAccess | DixDestroyAccess); + if (i == Success && pHead) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) { + if (pPrev) + pPrev->next = pEvent->next; + else + *pHead = pEvent->next; + } + updateEventMask (pHead); + } + free((pointer) pEvent); + return 1; +} + +/*ARGSUSED*/ +static int +WMFreeEvents (pointer data, XID id) { + WMEventPtr *pHead, pCur, pNext; + + pHead = (WMEventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + free((pointer) pCur); + } + free((pointer) pHead); + eventMask = 0; + return 1; +} + +static int +ProcAppleWMSelectInput (register ClientPtr client) +{ + REQUEST(xAppleWMSelectInputReq); + WMEventPtr pEvent, pNewEvent, *pHead; + XID clientResource; + int i; + + REQUEST_SIZE_MATCH (xAppleWMSelectInputReq); + i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, client, DixWriteAccess); + if (stuff->mask != 0) { + if (i == Success && pHead) { + /* check for existing entry. */ + for (pEvent = *pHead; pEvent; pEvent = pEvent->next) + { + if (pEvent->client == client) + { + pEvent->mask = stuff->mask; + updateEventMask (pHead); + return Success; + } + } + } + + /* build the entry */ + pNewEvent = (WMEventPtr) malloc(sizeof (WMEventRec)); + if (!pNewEvent) + return BadAlloc; + pNewEvent->next = 0; + pNewEvent->client = client; + pNewEvent->mask = stuff->mask; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewEvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewEvent)) + return BadAlloc; + /* + * create a resource to contain a pointer to the list + * of clients selecting input. This must be indirect as + * the list may be arbitrarily rearranged which cannot be + * done through the resource database. + */ + if (i != Success || !pHead) + { + pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr)); + if (!pHead || + !AddResource (eventResource, EventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewEvent->next = *pHead; + *pHead = pNewEvent; + updateEventMask (pHead); + } else if (stuff->mask == 0) { + /* delete the interest */ + if (i == Success && pHead) { + pNewEvent = 0; + for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { + if (pEvent->client == client) + break; + pNewEvent = pEvent; + } + if (pEvent) { + FreeResource (pEvent->clientResource, ClientType); + if (pNewEvent) + pNewEvent->next = pEvent->next; + else + *pHead = pEvent->next; + free(pEvent); + updateEventMask (pHead); + } + } + } else { + client->errorValue = stuff->mask; + return BadValue; + } + return Success; +} + +/* + * deliver the event + */ + +void +AppleWMSendEvent (int type, unsigned int mask, int which, int arg) { + WMEventPtr *pHead, pEvent; + ClientPtr client; + xAppleWMNotifyEvent se; + int i; + + i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess); + if (i != Success || !pHead) + return; + for (pEvent = *pHead; pEvent; pEvent = pEvent->next) { + client = pEvent->client; + if ((pEvent->mask & mask) == 0 + || client == serverClient || client->clientGone) + { + continue; + } + se.type = type + WMEventBase; + se.kind = which; + se.arg = arg; + se.sequenceNumber = client->sequence; + se.time = currentTime.milliseconds; + WriteEventsToClient (client, 1, (xEvent *) &se); + } +} + +/* Safe to call from any thread. */ +unsigned int +AppleWMSelectedEvents (void) +{ + return eventMask; +} + + +/* general utility functions */ + +static int +ProcAppleWMDisableUpdate( + register ClientPtr client +) +{ + REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq); + + appleWMProcs->DisableUpdate(); + + return Success; +} + +static int +ProcAppleWMReenableUpdate( + register ClientPtr client +) +{ + REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq); + + appleWMProcs->EnableUpdate(); + + return Success; +} + + +/* window functions */ + +static int +ProcAppleWMSetWindowMenu( + register ClientPtr client +) +{ + const char *bytes, **items; + char *shortcuts; + int max_len, nitems, i, j; + REQUEST(xAppleWMSetWindowMenuReq); + + REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq); + + nitems = stuff->nitems; + items = malloc(sizeof (char *) * nitems); + shortcuts = malloc(sizeof (char) * nitems); + + max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq); + bytes = (char *) &stuff[1]; + + for (i = j = 0; i < max_len && j < nitems;) + { + shortcuts[j] = bytes[i++]; + items[j++] = bytes + i; + + while (i < max_len) + { + if (bytes[i++] == 0) + break; + } + } + X11ApplicationSetWindowMenu (nitems, items, shortcuts); + free(items); + free(shortcuts); + + return Success; +} + +static int +ProcAppleWMSetWindowMenuCheck( + register ClientPtr client +) +{ + REQUEST(xAppleWMSetWindowMenuCheckReq); + + REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq); + X11ApplicationSetWindowMenuCheck(stuff->index); + return Success; +} + +static int +ProcAppleWMSetFrontProcess( + register ClientPtr client +) +{ + REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq); + + X11ApplicationSetFrontProcess(); + return Success; +} + +static int +ProcAppleWMSetWindowLevel(register ClientPtr client) +{ + REQUEST(xAppleWMSetWindowLevelReq); + WindowPtr pWin; + int err; + + REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq); + + if (Success != dixLookupWindow(&pWin, stuff->window, client, + DixReadAccess)) + return BadValue; + + if (stuff->level < 0 || stuff->level >= AppleWMNumWindowLevels) { + return BadValue; + } + + err = appleWMProcs->SetWindowLevel(pWin, stuff->level); + if (err != Success) { + return err; + } + + return Success; +} + +static int +ProcAppleWMSendPSN(register ClientPtr client) +{ + REQUEST(xAppleWMSendPSNReq); + int err; + + REQUEST_SIZE_MATCH(xAppleWMSendPSNReq); + + if(!appleWMProcs->SendPSN) + return BadRequest; + + err = appleWMProcs->SendPSN(stuff->psn_hi, stuff->psn_lo); + if (err != Success) { + return err; + } + + return Success; +} + +static int +ProcAppleWMAttachTransient(register ClientPtr client) +{ + WindowPtr pWinChild, pWinParent; + REQUEST(xAppleWMAttachTransientReq); + int err; + + REQUEST_SIZE_MATCH(xAppleWMAttachTransientReq); + + if(!appleWMProcs->AttachTransient) + return BadRequest; + + if (Success != dixLookupWindow(&pWinChild, stuff->child, client, DixReadAccess)) + return BadValue; + + if(stuff->parent) { + if(Success != dixLookupWindow(&pWinParent, stuff->parent, client, DixReadAccess)) + return BadValue; + } else { + pWinParent = NULL; + } + + err = appleWMProcs->AttachTransient(pWinChild, pWinParent); + if (err != Success) { + return err; + } + + return Success; +} + +static int +ProcAppleWMSetCanQuit( + register ClientPtr client +) +{ + REQUEST(xAppleWMSetCanQuitReq); + + REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq); + + X11ApplicationSetCanQuit(stuff->state); + return Success; +} + + +/* frame functions */ + +static int +ProcAppleWMFrameGetRect( + register ClientPtr client +) +{ + xAppleWMFrameGetRectReply rep; + BoxRec ir, or, rr; + REQUEST(xAppleWMFrameGetRectReq); + + REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); + or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); + + if (appleWMProcs->FrameGetRect(stuff->frame_rect, + stuff->frame_class, + &or, &ir, &rr) != Success) + { + return BadValue; + } + + rep.x = rr.x1; + rep.y = rr.y1; + rep.w = rr.x2 - rr.x1; + rep.h = rr.y2 - rr.y1; + + WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep); + return Success; +} + +static int +ProcAppleWMFrameHitTest( + register ClientPtr client +) +{ + xAppleWMFrameHitTestReply rep; + BoxRec ir, or; + int ret; + REQUEST(xAppleWMFrameHitTestReq); + + REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); + or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); + + if (appleWMProcs->FrameHitTest(stuff->frame_class, stuff->px, + stuff->py, &or, &ir, &ret) != Success) + { + return BadValue; + } + + rep.ret = ret; + + WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep); + return Success; +} + +static int +ProcAppleWMFrameDraw( + register ClientPtr client +) +{ + BoxRec ir, or; + unsigned int title_length, title_max; + unsigned char *title_bytes; + REQUEST(xAppleWMFrameDrawReq); + WindowPtr pWin; + + REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq); + + if (Success != dixLookupWindow(&pWin, stuff->window, client, + DixReadAccess)) + return BadValue; + + ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih); + or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh); + + title_length = stuff->title_length; + title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq); + + if (title_max < title_length) + return BadValue; + + title_bytes = (unsigned char *) &stuff[1]; + + errno = appleWMProcs->FrameDraw(pWin, stuff->frame_class, + stuff->frame_attr, &or, &ir, + title_length, title_bytes); + if (errno != Success) { + return errno; + } + + return Success; +} + + +/* dispatch */ + +static int +ProcAppleWMDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_AppleWMQueryVersion: + return ProcAppleWMQueryVersion(client); + } + + if (!LocalClient(client)) + return WMErrorBase + AppleWMClientNotLocal; + + switch (stuff->data) + { + case X_AppleWMSelectInput: + return ProcAppleWMSelectInput(client); + case X_AppleWMDisableUpdate: + return ProcAppleWMDisableUpdate(client); + case X_AppleWMReenableUpdate: + return ProcAppleWMReenableUpdate(client); + case X_AppleWMSetWindowMenu: + return ProcAppleWMSetWindowMenu(client); + case X_AppleWMSetWindowMenuCheck: + return ProcAppleWMSetWindowMenuCheck(client); + case X_AppleWMSetFrontProcess: + return ProcAppleWMSetFrontProcess(client); + case X_AppleWMSetWindowLevel: + return ProcAppleWMSetWindowLevel(client); + case X_AppleWMSetCanQuit: + return ProcAppleWMSetCanQuit(client); + case X_AppleWMFrameGetRect: + return ProcAppleWMFrameGetRect(client); + case X_AppleWMFrameHitTest: + return ProcAppleWMFrameHitTest(client); + case X_AppleWMFrameDraw: + return ProcAppleWMFrameDraw(client); + case X_AppleWMSendPSN: + return ProcAppleWMSendPSN(client); + case X_AppleWMAttachTransient: + return ProcAppleWMAttachTransient(client); + default: + return BadRequest; + } +} + +static void +SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to) { + to->type = from->type; + to->kind = from->kind; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->time, to->time); + cpswapl (from->arg, to->arg); +} + +static int +SProcAppleWMQueryVersion( + register ClientPtr client +) +{ + register int n; + REQUEST(xAppleWMQueryVersionReq); + swaps(&stuff->length, n); + return ProcAppleWMQueryVersion(client); +} + +static int +SProcAppleWMDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + /* It is bound to be non-local when there is byte swapping */ + if (!LocalClient(client)) + return WMErrorBase + AppleWMClientNotLocal; + + /* only local clients are allowed WM access */ + switch (stuff->data) + { + case X_AppleWMQueryVersion: + return SProcAppleWMQueryVersion(client); + default: + return BadRequest; + } +} diff --git a/xorg-server/hw/xquartz/darwin.c b/xorg-server/hw/xquartz/darwin.c index 1fb158b26..ed9543eb2 100644 --- a/xorg-server/hw/xquartz/darwin.c +++ b/xorg-server/hw/xquartz/darwin.c @@ -1,908 +1,908 @@ -/************************************************************** - * - * Xquartz initialization code - * - * Copyright (c) 2007-2008 Apple Inc. - * Copyright (c) 2001-2004 Torrey T. Lyons. 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 ABOVE LISTED COPYRIGHT HOLDER(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(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "os.h" -#include "servermd.h" -#include "inputstr.h" -#include "scrnintstr.h" -#include "mibstore.h" // mi backing store implementation -#include "mipointer.h" // mi software cursor -#include "micmap.h" // mi colormap code -#include "fb.h" // fb framebuffer code -#include "site.h" -#include "globals.h" -#include "dix.h" -#include "xkbsrv.h" - -#include <X11/extensions/XI.h> -#include <X11/extensions/XIproto.h> -#include "exevents.h" -#include "extinit.h" - -#include "xserver-properties.h" - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/syslimits.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> - -#define HAS_UTSNAME 1 -#include <sys/utsname.h> - -#define NO_CFPLUGIN -#include <IOKit/hidsystem/IOHIDLib.h> - -#ifdef MITSHM -#include "shmint.h" -#endif - -#include "darwin.h" -#include "darwinEvents.h" -#include "quartzKeyboard.h" -#include "quartz.h" - -#ifdef ENABLE_DEBUG_LOG -FILE *debug_log_fp = NULL; -#endif - -/* - * X server shared global variables - */ -int darwinScreensFound = 0; -static int darwinScreenKeyIndex; -DevPrivateKey darwinScreenKey = &darwinScreenKeyIndex; -io_connect_t darwinParamConnect = 0; -int darwinEventReadFD = -1; -int darwinEventWriteFD = -1; -// int darwinMouseAccelChange = 1; -int darwinFakeButtons = 0; - -// location of X11's (0,0) point in global screen coordinates -int darwinMainScreenX = 0; -int darwinMainScreenY = 0; - -// parameters read from the command line or user preferences -int darwinDesiredDepth = -1; -int darwinSyncKeymap = FALSE; - -// modifier masks for faking mouse buttons - ANY of these bits trigger it (not all) -#ifdef NX_DEVICELCMDKEYMASK -int darwinFakeMouse2Mask = NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; -int darwinFakeMouse3Mask = NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK; -#else -int darwinFakeMouse2Mask = NX_ALTERNATEMASK; -int darwinFakeMouse3Mask = NX_COMMANDMASK; -#endif - -// Modifier mask for overriding event delivery to appkit (might be useful to set this to rcommand for input menu -unsigned int darwinAppKitModMask = 0; // Any of these bits - -// Modifier mask for items in the Window menu (0 and -1 cause shortcuts to be disabled) -unsigned int windowItemModMask = NX_COMMANDMASK; - -// devices -DeviceIntPtr darwinKeyboard = NULL; -DeviceIntPtr darwinPointer = NULL; -DeviceIntPtr darwinTabletCurrent = NULL; -DeviceIntPtr darwinTabletStylus = NULL; -DeviceIntPtr darwinTabletCursor = NULL; -DeviceIntPtr darwinTabletEraser = NULL; - -// Common pixmap formats -static PixmapFormatRec formats[] = { - { 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 } -}; -const int NUMFORMATS = sizeof(formats)/sizeof(formats[0]); - -#ifndef OSNAME -#define OSNAME " Darwin" -#endif -#ifndef OSVENDOR -#define OSVENDOR "" -#endif -#ifndef PRE_RELEASE -#define PRE_RELEASE XORG_VERSION_SNAP -#endif -#ifndef BUILD_DATE -#define BUILD_DATE "" -#endif -#ifndef XORG_RELEASE -#define XORG_RELEASE "?" -#endif - -void -DarwinPrintBanner(void) -{ - // this should change depending on which specific server we are building - ErrorF("Xquartz starting:\n"); - ErrorF("X.Org X Server %s\nBuild Date: %s\n", XSERVER_VERSION, BUILD_DATE ); -} - - -/* - * DarwinSaveScreen - * X screensaver support. Not implemented. - */ -static Bool DarwinSaveScreen(ScreenPtr pScreen, int on) -{ - // FIXME - if (on == SCREEN_SAVER_FORCER) { - } else if (on == SCREEN_SAVER_ON) { - } else { - } - return TRUE; -} - -/* - * DarwinScreenInit - * This is a callback from dix during AddScreen() from InitOutput(). - * Initialize the screen and communicate information about it back to dix. - */ -static Bool DarwinScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) { - int dpi; - static int foundIndex = 0; - Bool ret; - DarwinFramebufferPtr dfb; - - // reset index of found screens for each server generation - if (index == 0) { - foundIndex = 0; - - // reset the visual list - miClearVisualTypes(); - } - - // allocate space for private per screen storage - dfb = xalloc(sizeof(DarwinFramebufferRec)); - - // SCREEN_PRIV(pScreen) = dfb; - dixSetPrivate(&pScreen->devPrivates, darwinScreenKey, dfb); - - // setup hardware/mode specific details - ret = QuartzAddScreen(foundIndex, pScreen); - foundIndex++; - if (! ret) - return FALSE; - - // setup a single visual appropriate for our pixel type - if(!miSetVisualTypesAndMasks(dfb->depth, dfb->visuals, dfb->bitsPerRGB, - dfb->preferredCVC, dfb->redMask, - dfb->greenMask, dfb->blueMask)) { - return FALSE; - } - -// TODO: Make PseudoColor visuals not suck in TrueColor mode -// if(dfb->depth > 8) -// miSetVisualTypesAndMasks(8, PseudoColorMask, 8, PseudoColor, 0, 0, 0); - if(dfb->depth > 15) - miSetVisualTypesAndMasks(15, TrueColorMask, 5, TrueColor, RM_ARGB(0,5,5,5), GM_ARGB(0,5,5,5), BM_ARGB(0,5,5,5)); - if(dfb->depth > 24) - miSetVisualTypesAndMasks(24, TrueColorMask, 8, TrueColor, RM_ARGB(0,8,8,8), GM_ARGB(0,8,8,8), BM_ARGB(0,8,8,8)); - - miSetPixmapDepths(); - - // machine independent screen init - // setup _Screen structure in pScreen - if (monitorResolution) - dpi = monitorResolution; - else - dpi = 96; - - // initialize fb - if (! fbScreenInit(pScreen, - dfb->framebuffer, // pointer to screen bitmap - dfb->width, dfb->height, // screen size in pixels - dpi, dpi, // dots per inch - dfb->pitch/(dfb->bitsPerPixel/8), // pixel width of framebuffer - dfb->bitsPerPixel)) // bits per pixel for screen - { - return FALSE; - } - - if (! fbPictureInit(pScreen, 0, 0)) { - return FALSE; - } - -#ifdef MITSHM - ShmRegisterFbFuncs(pScreen); -#endif - - // this must be initialized (why doesn't X have a default?) - pScreen->SaveScreen = DarwinSaveScreen; - - // finish mode dependent screen setup including cursor support - if (!QuartzSetupScreen(index, pScreen)) { - return FALSE; - } - - // create and install the default colormap and - // set pScreen->blackPixel / pScreen->white - if (!miCreateDefColormap( pScreen )) { - return FALSE; - } - - dixScreenOrigins[index].x = dfb->x; - dixScreenOrigins[index].y = dfb->y; - - /* ErrorF("Screen %d added: %dx%d @ (%d,%d)\n", - index, dfb->width, dfb->height, dfb->x, dfb->y); */ - - return TRUE; -} - -/* - ============================================================================= - - mouse and keyboard callbacks - - ============================================================================= -*/ - -/* - * DarwinMouseProc: Handle the initialization, etc. of a mouse - */ -static int DarwinMouseProc(DeviceIntPtr pPointer, int what) { -#define NBUTTONS 7 -#define NAXES 2 - // 7 buttons: left, right, middle, then four scroll wheel "buttons" - CARD8 map[NBUTTONS + 1] = {0, 1, 2, 3, 4, 5, 6, 7}; - Atom btn_labels[NBUTTONS] = {0}; - Atom axes_labels[NAXES] = {0}; - - switch (what) { - case DEVICE_INIT: - pPointer->public.on = FALSE; - - btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); - btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); - btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); - btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); - btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); - btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); - btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); - - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); - - - // Set button map. - InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS, - btn_labels, - (PtrCtrlProcPtr)NoopDDA, - GetMotionHistorySize(), NAXES, - axes_labels); - pPointer->valuator->mode = Absolute; // Relative - InitAbsoluteClassDeviceStruct(pPointer); -// InitValuatorAxisStruct(pPointer, 0, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); -// InitValuatorAxisStruct(pPointer, 1, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); - break; - case DEVICE_ON: - pPointer->public.on = TRUE; - AddEnabledDevice( darwinEventReadFD ); - return Success; - case DEVICE_CLOSE: - case DEVICE_OFF: - pPointer->public.on = FALSE; - RemoveEnabledDevice(darwinEventReadFD); - return Success; - } - - return Success; -#undef NBUTTONS -#undef NAXES -} - -static int DarwinTabletProc(DeviceIntPtr pPointer, int what) { -#define NBUTTONS 3 -#define NAXES 5 - CARD8 map[NBUTTONS + 1] = {0, 1, 2, 3}; - Atom btn_labels[NBUTTONS] = {0}; - Atom axes_labels[NAXES] = {0}; - - switch (what) { - case DEVICE_INIT: - pPointer->public.on = FALSE; - - btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); - btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); - btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); - - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); - axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE); - axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X); - axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y); - - // Set button map. - InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS, - btn_labels, - (PtrCtrlProcPtr)NoopDDA, - GetMotionHistorySize(), NAXES, - axes_labels); - pPointer->valuator->mode = Absolute; // Relative - InitProximityClassDeviceStruct(pPointer); - InitAbsoluteClassDeviceStruct(pPointer); - - InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); - InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); - InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); - InitValuatorAxisStruct(pPointer, 3, axes_labels[3], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); - InitValuatorAxisStruct(pPointer, 4, axes_labels[4], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); -// pPointer->use = IsXExtensionDevice; - break; - case DEVICE_ON: - pPointer->public.on = TRUE; - AddEnabledDevice( darwinEventReadFD ); - return Success; - case DEVICE_CLOSE: - case DEVICE_OFF: - pPointer->public.on = FALSE; - RemoveEnabledDevice(darwinEventReadFD); - return Success; - } - return Success; -#undef NBUTTONS -#undef NAXES -} - -/* - * DarwinKeybdProc - * Callback from X - */ -static int DarwinKeybdProc( DeviceIntPtr pDev, int onoff ) -{ - switch ( onoff ) { - case DEVICE_INIT: - DarwinKeyboardInit( pDev ); - break; - case DEVICE_ON: - pDev->public.on = TRUE; - AddEnabledDevice( darwinEventReadFD ); - break; - case DEVICE_OFF: - pDev->public.on = FALSE; - RemoveEnabledDevice( darwinEventReadFD ); - break; - case DEVICE_CLOSE: - break; - } - - return Success; -} - -/* -=========================================================================== - - Utility routines - -=========================================================================== -*/ - -/* - * DarwinParseModifierList - * Parse a list of modifier names and return a corresponding modifier mask - */ -int DarwinParseModifierList(const char *constmodifiers, int separatelr) -{ - int result = 0; - - if (constmodifiers) { - char *modifiers = strdup(constmodifiers); - char *modifier; - int nxkey; - char *p = modifiers; - - while (p) { - modifier = strsep(&p, " ,+&|/"); // allow lots of separators - nxkey = DarwinModifierStringToNXMask(modifier, separatelr); - if(nxkey) - result |= nxkey; - else - ErrorF("fakebuttons: Unknown modifier \"%s\"\n", modifier); - } - free(modifiers); - } - return result; -} - -/* -=========================================================================== - - Functions needed to link against device independent X - -=========================================================================== -*/ - -/* - * InitInput - * Register the keyboard and mouse devices - */ -void InitInput( int argc, char **argv ) -{ - XkbRMLVOSet rmlvo = { .rules = "base", .model = "empty", .layout = "empty", - .variant = NULL, .options = NULL }; - /* We need to really have rules... or something... */ - XkbSetRulesDflts(&rmlvo); - - darwinKeyboard = AddInputDevice(serverClient, DarwinKeybdProc, TRUE); - RegisterKeyboardDevice( darwinKeyboard ); - darwinKeyboard->name = strdup("keyboard"); - - /* here's the snippet from the current gdk sources: - if (!strcmp (tmp_name, "pointer")) - gdkdev->info.source = GDK_SOURCE_MOUSE; - else if (!strcmp (tmp_name, "wacom") || - !strcmp (tmp_name, "pen")) - gdkdev->info.source = GDK_SOURCE_PEN; - else if (!strcmp (tmp_name, "eraser")) - gdkdev->info.source = GDK_SOURCE_ERASER; - else if (!strcmp (tmp_name, "cursor")) - gdkdev->info.source = GDK_SOURCE_CURSOR; - else - gdkdev->info.source = GDK_SOURCE_PEN; - */ - - darwinPointer = AddInputDevice(serverClient, DarwinMouseProc, TRUE); - RegisterPointerDevice( darwinPointer ); - darwinPointer->name = strdup("pointer"); - - darwinTabletStylus = AddInputDevice(serverClient, DarwinTabletProc, TRUE); - RegisterPointerDevice( darwinTabletStylus ); - darwinTabletStylus->name = strdup("pen"); - - darwinTabletCursor = AddInputDevice(serverClient, DarwinTabletProc, TRUE); - RegisterPointerDevice( darwinTabletCursor ); - darwinTabletCursor->name = strdup("cursor"); - - darwinTabletEraser = AddInputDevice(serverClient, DarwinTabletProc, TRUE); - RegisterPointerDevice( darwinTabletEraser ); - darwinTabletEraser->name = strdup("eraser"); - - darwinTabletCurrent = darwinTabletStylus; - - DarwinEQInit(); - - QuartzInitInput(argc, argv); -} - - -/* - * DarwinAdjustScreenOrigins - * Shift all screens so the X11 (0, 0) coordinate is at the top - * left of the global screen coordinates. - * - * Screens can be arranged so the top left isn't on any screen, so - * instead use the top left of the leftmost screen as (0,0). This - * may mean some screen space is in -y, but it's better that (0,0) - * be onscreen, or else default xterms disappear. It's better that - * -y be used than -x, because when popup menus are forced - * "onscreen" by dumb window managers like twm, they'll shift the - * menus down instead of left, which still looks funny but is an - * easier target to hit. - */ -void -DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo) -{ - int i, left, top; - - left = dixScreenOrigins[0].x; - top = dixScreenOrigins[0].y; - - /* Find leftmost screen. If there's a tie, take the topmost of the two. */ - for (i = 1; i < pScreenInfo->numScreens; i++) { - if (dixScreenOrigins[i].x < left || - (dixScreenOrigins[i].x == left && dixScreenOrigins[i].y < top)) - { - left = dixScreenOrigins[i].x; - top = dixScreenOrigins[i].y; - } - } - - darwinMainScreenX = left; - darwinMainScreenY = top; - - DEBUG_LOG("top = %d, left=%d\n", top, left); - - /* Shift all screens so that there is a screen whose top left - * is at X11 (0,0) and at global screen coordinate - * (darwinMainScreenX, darwinMainScreenY). - */ - - if (darwinMainScreenX != 0 || darwinMainScreenY != 0) { - for (i = 0; i < pScreenInfo->numScreens; i++) { - dixScreenOrigins[i].x -= darwinMainScreenX; - dixScreenOrigins[i].y -= darwinMainScreenY; - DEBUG_LOG("Screen %d placed at X11 coordinate (%d,%d).\n", - i, dixScreenOrigins[i].x, dixScreenOrigins[i].y); - } - } -} - - -/* - * InitOutput - * Initialize screenInfo for all actually accessible framebuffers. - * - * The display mode dependent code gets called three times. The mode - * specific InitOutput routines are expected to discover the number - * of potentially useful screens and cache routes to them internally. - * Inside DarwinScreenInit are two other mode specific calls. - * A mode specific AddScreen routine is called for each screen to - * actually initialize the screen with the ScreenPtr structure. - * After other screen setup has been done, a mode specific - * SetupScreen function can be called to finalize screen setup. - */ -void InitOutput( ScreenInfo *pScreenInfo, int argc, char **argv ) -{ - int i; - - pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; - pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; - pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; - pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; - - // List how we want common pixmap formats to be padded - pScreenInfo->numPixmapFormats = NUMFORMATS; - for (i = 0; i < NUMFORMATS; i++) - pScreenInfo->formats[i] = formats[i]; - - // Discover screens and do mode specific initialization - QuartzInitOutput(argc, argv); - - // Add screens - for (i = 0; i < darwinScreensFound; i++) { - AddScreen(DarwinScreenInit, argc, argv); - } - - DarwinAdjustScreenOrigins(pScreenInfo); -} - - -/* - * OsVendorFatalError - */ -void OsVendorFatalError( void ) -{ - ErrorF( " OsVendorFatalError\n" ); -} - - -/* - * OsVendorInit - * Initialization of Darwin OS support. - */ -void OsVendorInit(void) -{ - if (serverGeneration == 1) { - DarwinPrintBanner(); -#ifdef ENABLE_DEBUG_LOG - { - char *home_dir=NULL, *log_file_path=NULL; - home_dir = getenv("HOME"); - if (home_dir) asprintf(&log_file_path, "%s/%s", home_dir, DEBUG_LOG_NAME); - if (log_file_path) { - if (!access(log_file_path, F_OK)) { - debug_log_fp = fopen(log_file_path, "a"); - if (debug_log_fp) ErrorF("Debug logging enabled to %s\n", log_file_path); - } - free(log_file_path); - } - } -#endif - } -} - - -/* - * 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. - */ -int ddxProcessArgument( int argc, char *argv[], int i ) -{ -// if ( !strcmp( argv[i], "-fullscreen" ) ) { -// ErrorF( "Running full screen in parallel with Mac OS X Quartz window server.\n" ); -// return 1; -// } - -// if ( !strcmp( argv[i], "-rootless" ) ) { -// ErrorF( "Running rootless inside Mac OS X window server.\n" ); -// return 1; -// } - - // This command line arg is passed when launched from the Aqua GUI. - if ( !strncmp( argv[i], "-psn_", 5 ) ) { - return 1; - } - - if ( !strcmp( argv[i], "-fakebuttons" ) ) { - darwinFakeButtons = TRUE; - ErrorF( "Faking a three button mouse\n" ); - return 1; - } - - if ( !strcmp( argv[i], "-nofakebuttons" ) ) { - darwinFakeButtons = FALSE; - ErrorF( "Not faking a three button mouse\n" ); - return 1; - } - - if (!strcmp( argv[i], "-fakemouse2" ) ) { - if ( i == argc-1 ) { - FatalError( "-fakemouse2 must be followed by a modifer list\n" ); - } - if (!strcasecmp(argv[i+1], "none") || !strcmp(argv[i+1], "")) - darwinFakeMouse2Mask = 0; - else - darwinFakeMouse2Mask = DarwinParseModifierList(argv[i+1], 1); - ErrorF("Modifier mask to fake mouse button 2 = 0x%x\n", - darwinFakeMouse2Mask); - return 2; - } - - if (!strcmp( argv[i], "-fakemouse3" ) ) { - if ( i == argc-1 ) { - FatalError( "-fakemouse3 must be followed by a modifer list\n" ); - } - if (!strcasecmp(argv[i+1], "none") || !strcmp(argv[i+1], "")) - darwinFakeMouse3Mask = 0; - else - darwinFakeMouse3Mask = DarwinParseModifierList(argv[i+1], 1); - ErrorF("Modifier mask to fake mouse button 3 = 0x%x\n", - darwinFakeMouse3Mask); - return 2; - } - - if ( !strcmp( argv[i], "+synckeymap" ) ) { - darwinSyncKeymap = TRUE; - return 1; - } - - if ( !strcmp( argv[i], "-synckeymap" ) ) { - darwinSyncKeymap = FALSE; - return 1; - } - - if ( !strcmp( argv[i], "-depth" ) ) { - if ( i == argc-1 ) { - FatalError( "-depth must be followed by a number\n" ); - } - darwinDesiredDepth = atoi( argv[i+1] ); - if(darwinDesiredDepth != -1 && - darwinDesiredDepth != 8 && - darwinDesiredDepth != 15 && - darwinDesiredDepth != 24) { - FatalError( "Unsupported pixel depth. Use 8, 15, or 24 bits\n" ); - } - - ErrorF( "Attempting to use pixel depth of %i\n", darwinDesiredDepth ); - return 2; - } - - if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) { - DarwinPrintBanner(); - exit(0); - } - - return 0; -} - - -/* - * 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"); - ErrorF("\n"); - ErrorF("-depth <8,15,24> : use this bit depth.\n"); - ErrorF("-fakebuttons : fake a three button mouse with Command and Option keys.\n"); - ErrorF("-nofakebuttons : don't fake a three button mouse.\n"); - ErrorF("-fakemouse2 <modifiers> : fake middle mouse button with modifier keys.\n"); - ErrorF("-fakemouse3 <modifiers> : fake right mouse button with modifier keys.\n"); - ErrorF(" ex: -fakemouse2 \"option,shift\" = option-shift-click is middle button.\n"); - ErrorF("-version : show the server version.\n"); - ErrorF("\n"); -} - - -/* - * ddxGiveUp -- - * Device dependent cleanup. Called by dix before normal server death. - */ -void ddxGiveUp( void ) -{ - ErrorF( "Quitting Xquartz\n" ); -} - - -/* - * 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 ) -{ - ErrorF( " AbortDDX\n" ); - OsAbort(); -} - -#include "mivalidate.h" // for union _Validate used by windowstr.h -#include "windowstr.h" // for struct _Window -#include "scrnintstr.h" // for struct _Screen - -// This is copied from Xserver/hw/xfree86/common/xf86Helper.c. -// Quartz mode uses this when switching in and out of Quartz. -// Quartz or IOKit can use this when waking from sleep. -// Copyright (c) 1997-1998 by The XFree86 Project, Inc. - -/* - * xf86SetRootClip -- - * Enable or disable rendering to the screen by - * setting the root clip list and revalidating - * all of the windows - */ - -void -xf86SetRootClip (ScreenPtr pScreen, int enable) -{ - WindowPtr pWin = WindowTable[pScreen->myNum]; - WindowPtr pChild; - Bool WasViewable = (Bool)(pWin->viewable); - Bool anyMarked = TRUE; - RegionPtr pOldClip = NULL, bsExposed; - 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_RESET(pScreen, &pWin->borderClip, &box); - REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); - } - else - { - REGION_EMPTY(pScreen, &pWin->borderClip); - REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); - } - - ResizeChildrenWinSize (pWin, 0, 0, 0, 0); - - if (WasViewable) - { - if (pWin->backStorage) - { - pOldClip = REGION_CREATE(pScreen, NullBox, 1); - REGION_COPY(pScreen, pOldClip, &pWin->clipList); - } - - if (pWin->firstChild) - { - anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, - pWin->firstChild, - (WindowPtr *)NULL); - } - else - { - (*pScreen->MarkWindow) (pWin); - anyMarked = TRUE; - } - - - if (anyMarked) - (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); - } - - if (pWin->backStorage && - ((pWin->backingStore == Always) || WasViewable)) - { - if (!WasViewable) - pOldClip = &pWin->clipList; /* a convenient empty region */ - bsExposed = (*pScreen->TranslateBackingStore) - (pWin, 0, 0, pOldClip, - pWin->drawable.x, pWin->drawable.y); - if (WasViewable) - REGION_DESTROY(pScreen, pOldClip); - if (bsExposed) - { - RegionPtr valExposed = NullRegion; - - if (pWin->valdata) - valExposed = &pWin->valdata->after.exposed; - (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); - if (valExposed) - REGION_EMPTY(pScreen, valExposed); - REGION_DESTROY(pScreen, bsExposed); - } - } - if (WasViewable) - { - if (anyMarked) - (*pScreen->HandleExposures)(pWin); - if (anyMarked && pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); - } - if (pWin->realized) - WindowsRestructured (); - FlushAllOutput (); -} +/************************************************************** + * + * Xquartz initialization code + * + * Copyright (c) 2007-2008 Apple Inc. + * Copyright (c) 2001-2004 Torrey T. Lyons. 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 ABOVE LISTED COPYRIGHT HOLDER(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(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "os.h" +#include "servermd.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "mibstore.h" // mi backing store implementation +#include "mipointer.h" // mi software cursor +#include "micmap.h" // mi colormap code +#include "fb.h" // fb framebuffer code +#include "site.h" +#include "globals.h" +#include "dix.h" +#include "xkbsrv.h" + +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "exevents.h" +#include "extinit.h" + +#include "xserver-properties.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/syslimits.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> + +#define HAS_UTSNAME 1 +#include <sys/utsname.h> + +#define NO_CFPLUGIN +#include <IOKit/hidsystem/IOHIDLib.h> + +#ifdef MITSHM +#include "shmint.h" +#endif + +#include "darwin.h" +#include "darwinEvents.h" +#include "quartzKeyboard.h" +#include "quartz.h" + +#ifdef ENABLE_DEBUG_LOG +FILE *debug_log_fp = NULL; +#endif + +/* + * X server shared global variables + */ +int darwinScreensFound = 0; +static int darwinScreenKeyIndex; +DevPrivateKey darwinScreenKey = &darwinScreenKeyIndex; +io_connect_t darwinParamConnect = 0; +int darwinEventReadFD = -1; +int darwinEventWriteFD = -1; +// int darwinMouseAccelChange = 1; +int darwinFakeButtons = 0; + +// location of X11's (0,0) point in global screen coordinates +int darwinMainScreenX = 0; +int darwinMainScreenY = 0; + +// parameters read from the command line or user preferences +int darwinDesiredDepth = -1; +int darwinSyncKeymap = FALSE; + +// modifier masks for faking mouse buttons - ANY of these bits trigger it (not all) +#ifdef NX_DEVICELCMDKEYMASK +int darwinFakeMouse2Mask = NX_DEVICELALTKEYMASK | NX_DEVICERALTKEYMASK; +int darwinFakeMouse3Mask = NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK; +#else +int darwinFakeMouse2Mask = NX_ALTERNATEMASK; +int darwinFakeMouse3Mask = NX_COMMANDMASK; +#endif + +// Modifier mask for overriding event delivery to appkit (might be useful to set this to rcommand for input menu +unsigned int darwinAppKitModMask = 0; // Any of these bits + +// Modifier mask for items in the Window menu (0 and -1 cause shortcuts to be disabled) +unsigned int windowItemModMask = NX_COMMANDMASK; + +// devices +DeviceIntPtr darwinKeyboard = NULL; +DeviceIntPtr darwinPointer = NULL; +DeviceIntPtr darwinTabletCurrent = NULL; +DeviceIntPtr darwinTabletStylus = NULL; +DeviceIntPtr darwinTabletCursor = NULL; +DeviceIntPtr darwinTabletEraser = NULL; + +// Common pixmap formats +static PixmapFormatRec formats[] = { + { 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 } +}; +const int NUMFORMATS = sizeof(formats)/sizeof(formats[0]); + +#ifndef OSNAME +#define OSNAME " Darwin" +#endif +#ifndef OSVENDOR +#define OSVENDOR "" +#endif +#ifndef PRE_RELEASE +#define PRE_RELEASE XORG_VERSION_SNAP +#endif +#ifndef BUILD_DATE +#define BUILD_DATE "" +#endif +#ifndef XORG_RELEASE +#define XORG_RELEASE "?" +#endif + +void +DarwinPrintBanner(void) +{ + // this should change depending on which specific server we are building + ErrorF("Xquartz starting:\n"); + ErrorF("X.Org X Server %s\nBuild Date: %s\n", XSERVER_VERSION, BUILD_DATE ); +} + + +/* + * DarwinSaveScreen + * X screensaver support. Not implemented. + */ +static Bool DarwinSaveScreen(ScreenPtr pScreen, int on) +{ + // FIXME + if (on == SCREEN_SAVER_FORCER) { + } else if (on == SCREEN_SAVER_ON) { + } else { + } + return TRUE; +} + +/* + * DarwinScreenInit + * This is a callback from dix during AddScreen() from InitOutput(). + * Initialize the screen and communicate information about it back to dix. + */ +static Bool DarwinScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) { + int dpi; + static int foundIndex = 0; + Bool ret; + DarwinFramebufferPtr dfb; + + // reset index of found screens for each server generation + if (index == 0) { + foundIndex = 0; + + // reset the visual list + miClearVisualTypes(); + } + + // allocate space for private per screen storage + dfb = malloc(sizeof(DarwinFramebufferRec)); + + // SCREEN_PRIV(pScreen) = dfb; + dixSetPrivate(&pScreen->devPrivates, darwinScreenKey, dfb); + + // setup hardware/mode specific details + ret = QuartzAddScreen(foundIndex, pScreen); + foundIndex++; + if (! ret) + return FALSE; + + // setup a single visual appropriate for our pixel type + if(!miSetVisualTypesAndMasks(dfb->depth, dfb->visuals, dfb->bitsPerRGB, + dfb->preferredCVC, dfb->redMask, + dfb->greenMask, dfb->blueMask)) { + return FALSE; + } + +// TODO: Make PseudoColor visuals not suck in TrueColor mode +// if(dfb->depth > 8) +// miSetVisualTypesAndMasks(8, PseudoColorMask, 8, PseudoColor, 0, 0, 0); + if(dfb->depth > 15) + miSetVisualTypesAndMasks(15, TrueColorMask, 5, TrueColor, RM_ARGB(0,5,5,5), GM_ARGB(0,5,5,5), BM_ARGB(0,5,5,5)); + if(dfb->depth > 24) + miSetVisualTypesAndMasks(24, TrueColorMask, 8, TrueColor, RM_ARGB(0,8,8,8), GM_ARGB(0,8,8,8), BM_ARGB(0,8,8,8)); + + miSetPixmapDepths(); + + // machine independent screen init + // setup _Screen structure in pScreen + if (monitorResolution) + dpi = monitorResolution; + else + dpi = 96; + + // initialize fb + if (! fbScreenInit(pScreen, + dfb->framebuffer, // pointer to screen bitmap + dfb->width, dfb->height, // screen size in pixels + dpi, dpi, // dots per inch + dfb->pitch/(dfb->bitsPerPixel/8), // pixel width of framebuffer + dfb->bitsPerPixel)) // bits per pixel for screen + { + return FALSE; + } + + if (! fbPictureInit(pScreen, 0, 0)) { + return FALSE; + } + +#ifdef MITSHM + ShmRegisterFbFuncs(pScreen); +#endif + + // this must be initialized (why doesn't X have a default?) + pScreen->SaveScreen = DarwinSaveScreen; + + // finish mode dependent screen setup including cursor support + if (!QuartzSetupScreen(index, pScreen)) { + return FALSE; + } + + // create and install the default colormap and + // set pScreen->blackPixel / pScreen->white + if (!miCreateDefColormap( pScreen )) { + return FALSE; + } + + dixScreenOrigins[index].x = dfb->x; + dixScreenOrigins[index].y = dfb->y; + + /* ErrorF("Screen %d added: %dx%d @ (%d,%d)\n", + index, dfb->width, dfb->height, dfb->x, dfb->y); */ + + return TRUE; +} + +/* + ============================================================================= + + mouse and keyboard callbacks + + ============================================================================= +*/ + +/* + * DarwinMouseProc: Handle the initialization, etc. of a mouse + */ +static int DarwinMouseProc(DeviceIntPtr pPointer, int what) { +#define NBUTTONS 7 +#define NAXES 2 + // 7 buttons: left, right, middle, then four scroll wheel "buttons" + CARD8 map[NBUTTONS + 1] = {0, 1, 2, 3, 4, 5, 6, 7}; + Atom btn_labels[NBUTTONS] = {0}; + Atom axes_labels[NAXES] = {0}; + + switch (what) { + case DEVICE_INIT: + pPointer->public.on = FALSE; + + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); + btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); + btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); + btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); + btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); + + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); + + + // Set button map. + InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS, + btn_labels, + (PtrCtrlProcPtr)NoopDDA, + GetMotionHistorySize(), NAXES, + axes_labels); + pPointer->valuator->mode = Absolute; // Relative + InitAbsoluteClassDeviceStruct(pPointer); +// InitValuatorAxisStruct(pPointer, 0, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); +// InitValuatorAxisStruct(pPointer, 1, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); + break; + case DEVICE_ON: + pPointer->public.on = TRUE; + AddEnabledDevice( darwinEventReadFD ); + return Success; + case DEVICE_CLOSE: + case DEVICE_OFF: + pPointer->public.on = FALSE; + RemoveEnabledDevice(darwinEventReadFD); + return Success; + } + + return Success; +#undef NBUTTONS +#undef NAXES +} + +static int DarwinTabletProc(DeviceIntPtr pPointer, int what) { +#define NBUTTONS 3 +#define NAXES 5 + CARD8 map[NBUTTONS + 1] = {0, 1, 2, 3}; + Atom btn_labels[NBUTTONS] = {0}; + Atom axes_labels[NAXES] = {0}; + + switch (what) { + case DEVICE_INIT: + pPointer->public.on = FALSE; + + btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); + btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); + btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); + + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); + axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE); + axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X); + axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y); + + // Set button map. + InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS, + btn_labels, + (PtrCtrlProcPtr)NoopDDA, + GetMotionHistorySize(), NAXES, + axes_labels); + pPointer->valuator->mode = Absolute; // Relative + InitProximityClassDeviceStruct(pPointer); + InitAbsoluteClassDeviceStruct(pPointer); + + InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); + InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); + InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); + InitValuatorAxisStruct(pPointer, 3, axes_labels[3], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); + InitValuatorAxisStruct(pPointer, 4, axes_labels[4], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); +// pPointer->use = IsXExtensionDevice; + break; + case DEVICE_ON: + pPointer->public.on = TRUE; + AddEnabledDevice( darwinEventReadFD ); + return Success; + case DEVICE_CLOSE: + case DEVICE_OFF: + pPointer->public.on = FALSE; + RemoveEnabledDevice(darwinEventReadFD); + return Success; + } + return Success; +#undef NBUTTONS +#undef NAXES +} + +/* + * DarwinKeybdProc + * Callback from X + */ +static int DarwinKeybdProc( DeviceIntPtr pDev, int onoff ) +{ + switch ( onoff ) { + case DEVICE_INIT: + DarwinKeyboardInit( pDev ); + break; + case DEVICE_ON: + pDev->public.on = TRUE; + AddEnabledDevice( darwinEventReadFD ); + break; + case DEVICE_OFF: + pDev->public.on = FALSE; + RemoveEnabledDevice( darwinEventReadFD ); + break; + case DEVICE_CLOSE: + break; + } + + return Success; +} + +/* +=========================================================================== + + Utility routines + +=========================================================================== +*/ + +/* + * DarwinParseModifierList + * Parse a list of modifier names and return a corresponding modifier mask + */ +int DarwinParseModifierList(const char *constmodifiers, int separatelr) +{ + int result = 0; + + if (constmodifiers) { + char *modifiers = strdup(constmodifiers); + char *modifier; + int nxkey; + char *p = modifiers; + + while (p) { + modifier = strsep(&p, " ,+&|/"); // allow lots of separators + nxkey = DarwinModifierStringToNXMask(modifier, separatelr); + if(nxkey) + result |= nxkey; + else + ErrorF("fakebuttons: Unknown modifier \"%s\"\n", modifier); + } + free(modifiers); + } + return result; +} + +/* +=========================================================================== + + Functions needed to link against device independent X + +=========================================================================== +*/ + +/* + * InitInput + * Register the keyboard and mouse devices + */ +void InitInput( int argc, char **argv ) +{ + XkbRMLVOSet rmlvo = { .rules = "base", .model = "empty", .layout = "empty", + .variant = NULL, .options = NULL }; + /* We need to really have rules... or something... */ + XkbSetRulesDflts(&rmlvo); + + darwinKeyboard = AddInputDevice(serverClient, DarwinKeybdProc, TRUE); + RegisterKeyboardDevice( darwinKeyboard ); + darwinKeyboard->name = strdup("keyboard"); + + /* here's the snippet from the current gdk sources: + if (!strcmp (tmp_name, "pointer")) + gdkdev->info.source = GDK_SOURCE_MOUSE; + else if (!strcmp (tmp_name, "wacom") || + !strcmp (tmp_name, "pen")) + gdkdev->info.source = GDK_SOURCE_PEN; + else if (!strcmp (tmp_name, "eraser")) + gdkdev->info.source = GDK_SOURCE_ERASER; + else if (!strcmp (tmp_name, "cursor")) + gdkdev->info.source = GDK_SOURCE_CURSOR; + else + gdkdev->info.source = GDK_SOURCE_PEN; + */ + + darwinPointer = AddInputDevice(serverClient, DarwinMouseProc, TRUE); + RegisterPointerDevice( darwinPointer ); + darwinPointer->name = strdup("pointer"); + + darwinTabletStylus = AddInputDevice(serverClient, DarwinTabletProc, TRUE); + RegisterPointerDevice( darwinTabletStylus ); + darwinTabletStylus->name = strdup("pen"); + + darwinTabletCursor = AddInputDevice(serverClient, DarwinTabletProc, TRUE); + RegisterPointerDevice( darwinTabletCursor ); + darwinTabletCursor->name = strdup("cursor"); + + darwinTabletEraser = AddInputDevice(serverClient, DarwinTabletProc, TRUE); + RegisterPointerDevice( darwinTabletEraser ); + darwinTabletEraser->name = strdup("eraser"); + + darwinTabletCurrent = darwinTabletStylus; + + DarwinEQInit(); + + QuartzInitInput(argc, argv); +} + + +/* + * DarwinAdjustScreenOrigins + * Shift all screens so the X11 (0, 0) coordinate is at the top + * left of the global screen coordinates. + * + * Screens can be arranged so the top left isn't on any screen, so + * instead use the top left of the leftmost screen as (0,0). This + * may mean some screen space is in -y, but it's better that (0,0) + * be onscreen, or else default xterms disappear. It's better that + * -y be used than -x, because when popup menus are forced + * "onscreen" by dumb window managers like twm, they'll shift the + * menus down instead of left, which still looks funny but is an + * easier target to hit. + */ +void +DarwinAdjustScreenOrigins(ScreenInfo *pScreenInfo) +{ + int i, left, top; + + left = dixScreenOrigins[0].x; + top = dixScreenOrigins[0].y; + + /* Find leftmost screen. If there's a tie, take the topmost of the two. */ + for (i = 1; i < pScreenInfo->numScreens; i++) { + if (dixScreenOrigins[i].x < left || + (dixScreenOrigins[i].x == left && dixScreenOrigins[i].y < top)) + { + left = dixScreenOrigins[i].x; + top = dixScreenOrigins[i].y; + } + } + + darwinMainScreenX = left; + darwinMainScreenY = top; + + DEBUG_LOG("top = %d, left=%d\n", top, left); + + /* Shift all screens so that there is a screen whose top left + * is at X11 (0,0) and at global screen coordinate + * (darwinMainScreenX, darwinMainScreenY). + */ + + if (darwinMainScreenX != 0 || darwinMainScreenY != 0) { + for (i = 0; i < pScreenInfo->numScreens; i++) { + dixScreenOrigins[i].x -= darwinMainScreenX; + dixScreenOrigins[i].y -= darwinMainScreenY; + DEBUG_LOG("Screen %d placed at X11 coordinate (%d,%d).\n", + i, dixScreenOrigins[i].x, dixScreenOrigins[i].y); + } + } +} + + +/* + * InitOutput + * Initialize screenInfo for all actually accessible framebuffers. + * + * The display mode dependent code gets called three times. The mode + * specific InitOutput routines are expected to discover the number + * of potentially useful screens and cache routes to them internally. + * Inside DarwinScreenInit are two other mode specific calls. + * A mode specific AddScreen routine is called for each screen to + * actually initialize the screen with the ScreenPtr structure. + * After other screen setup has been done, a mode specific + * SetupScreen function can be called to finalize screen setup. + */ +void InitOutput( ScreenInfo *pScreenInfo, int argc, char **argv ) +{ + int i; + + pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; + pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; + pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; + pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; + + // List how we want common pixmap formats to be padded + pScreenInfo->numPixmapFormats = NUMFORMATS; + for (i = 0; i < NUMFORMATS; i++) + pScreenInfo->formats[i] = formats[i]; + + // Discover screens and do mode specific initialization + QuartzInitOutput(argc, argv); + + // Add screens + for (i = 0; i < darwinScreensFound; i++) { + AddScreen(DarwinScreenInit, argc, argv); + } + + DarwinAdjustScreenOrigins(pScreenInfo); +} + + +/* + * OsVendorFatalError + */ +void OsVendorFatalError( void ) +{ + ErrorF( " OsVendorFatalError\n" ); +} + + +/* + * OsVendorInit + * Initialization of Darwin OS support. + */ +void OsVendorInit(void) +{ + if (serverGeneration == 1) { + DarwinPrintBanner(); +#ifdef ENABLE_DEBUG_LOG + { + char *home_dir=NULL, *log_file_path=NULL; + home_dir = getenv("HOME"); + if (home_dir) asprintf(&log_file_path, "%s/%s", home_dir, DEBUG_LOG_NAME); + if (log_file_path) { + if (!access(log_file_path, F_OK)) { + debug_log_fp = fopen(log_file_path, "a"); + if (debug_log_fp) ErrorF("Debug logging enabled to %s\n", log_file_path); + } + free(log_file_path); + } + } +#endif + } +} + + +/* + * 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. + */ +int ddxProcessArgument( int argc, char *argv[], int i ) +{ +// if ( !strcmp( argv[i], "-fullscreen" ) ) { +// ErrorF( "Running full screen in parallel with Mac OS X Quartz window server.\n" ); +// return 1; +// } + +// if ( !strcmp( argv[i], "-rootless" ) ) { +// ErrorF( "Running rootless inside Mac OS X window server.\n" ); +// return 1; +// } + + // This command line arg is passed when launched from the Aqua GUI. + if ( !strncmp( argv[i], "-psn_", 5 ) ) { + return 1; + } + + if ( !strcmp( argv[i], "-fakebuttons" ) ) { + darwinFakeButtons = TRUE; + ErrorF( "Faking a three button mouse\n" ); + return 1; + } + + if ( !strcmp( argv[i], "-nofakebuttons" ) ) { + darwinFakeButtons = FALSE; + ErrorF( "Not faking a three button mouse\n" ); + return 1; + } + + if (!strcmp( argv[i], "-fakemouse2" ) ) { + if ( i == argc-1 ) { + FatalError( "-fakemouse2 must be followed by a modifer list\n" ); + } + if (!strcasecmp(argv[i+1], "none") || !strcmp(argv[i+1], "")) + darwinFakeMouse2Mask = 0; + else + darwinFakeMouse2Mask = DarwinParseModifierList(argv[i+1], 1); + ErrorF("Modifier mask to fake mouse button 2 = 0x%x\n", + darwinFakeMouse2Mask); + return 2; + } + + if (!strcmp( argv[i], "-fakemouse3" ) ) { + if ( i == argc-1 ) { + FatalError( "-fakemouse3 must be followed by a modifer list\n" ); + } + if (!strcasecmp(argv[i+1], "none") || !strcmp(argv[i+1], "")) + darwinFakeMouse3Mask = 0; + else + darwinFakeMouse3Mask = DarwinParseModifierList(argv[i+1], 1); + ErrorF("Modifier mask to fake mouse button 3 = 0x%x\n", + darwinFakeMouse3Mask); + return 2; + } + + if ( !strcmp( argv[i], "+synckeymap" ) ) { + darwinSyncKeymap = TRUE; + return 1; + } + + if ( !strcmp( argv[i], "-synckeymap" ) ) { + darwinSyncKeymap = FALSE; + return 1; + } + + if ( !strcmp( argv[i], "-depth" ) ) { + if ( i == argc-1 ) { + FatalError( "-depth must be followed by a number\n" ); + } + darwinDesiredDepth = atoi( argv[i+1] ); + if(darwinDesiredDepth != -1 && + darwinDesiredDepth != 8 && + darwinDesiredDepth != 15 && + darwinDesiredDepth != 24) { + FatalError( "Unsupported pixel depth. Use 8, 15, or 24 bits\n" ); + } + + ErrorF( "Attempting to use pixel depth of %i\n", darwinDesiredDepth ); + return 2; + } + + if (!strcmp( argv[i], "-showconfig" ) || !strcmp( argv[i], "-version" )) { + DarwinPrintBanner(); + exit(0); + } + + return 0; +} + + +/* + * 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"); + ErrorF("\n"); + ErrorF("-depth <8,15,24> : use this bit depth.\n"); + ErrorF("-fakebuttons : fake a three button mouse with Command and Option keys.\n"); + ErrorF("-nofakebuttons : don't fake a three button mouse.\n"); + ErrorF("-fakemouse2 <modifiers> : fake middle mouse button with modifier keys.\n"); + ErrorF("-fakemouse3 <modifiers> : fake right mouse button with modifier keys.\n"); + ErrorF(" ex: -fakemouse2 \"option,shift\" = option-shift-click is middle button.\n"); + ErrorF("-version : show the server version.\n"); + ErrorF("\n"); +} + + +/* + * ddxGiveUp -- + * Device dependent cleanup. Called by dix before normal server death. + */ +void ddxGiveUp( void ) +{ + ErrorF( "Quitting Xquartz\n" ); +} + + +/* + * 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 ) +{ + ErrorF( " AbortDDX\n" ); + OsAbort(); +} + +#include "mivalidate.h" // for union _Validate used by windowstr.h +#include "windowstr.h" // for struct _Window +#include "scrnintstr.h" // for struct _Screen + +// This is copied from Xserver/hw/xfree86/common/xf86Helper.c. +// Quartz mode uses this when switching in and out of Quartz. +// Quartz or IOKit can use this when waking from sleep. +// Copyright (c) 1997-1998 by The XFree86 Project, Inc. + +/* + * xf86SetRootClip -- + * Enable or disable rendering to the screen by + * setting the root clip list and revalidating + * all of the windows + */ + +void +xf86SetRootClip (ScreenPtr pScreen, int enable) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + WindowPtr pChild; + Bool WasViewable = (Bool)(pWin->viewable); + Bool anyMarked = TRUE; + RegionPtr pOldClip = NULL, bsExposed; + 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_RESET(pScreen, &pWin->borderClip, &box); + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + else + { + REGION_EMPTY(pScreen, &pWin->borderClip); + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + + ResizeChildrenWinSize (pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + if (pWin->firstChild) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, + pWin->firstChild, + (WindowPtr *)NULL); + } + else + { + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + } + + + if (anyMarked) + (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pWin); + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + FlushAllOutput (); +} diff --git a/xorg-server/hw/xquartz/pseudoramiX.c b/xorg-server/hw/xquartz/pseudoramiX.c index 1de7af6dc..1a357528c 100644 --- a/xorg-server/hw/xquartz/pseudoramiX.c +++ b/xorg-server/hw/xquartz/pseudoramiX.c @@ -1,471 +1,471 @@ -/* - * Minimal implementation of PanoramiX/Xinerama - * - * This is used in rootless mode where the underlying window server - * already provides an abstracted view of multiple screens as one - * large screen area. - * - * This code is largely based on panoramiX.c, which contains the - * following copyright notice: - */ -/***************************************************************** -Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. -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. - -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 -DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, -BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation -shall not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization from Digital -Equipment Corporation. -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "darwin.h" -#include "pseudoramiX.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "window.h" -#include <X11/extensions/panoramiXproto.h> -#include "globals.h" - -Bool noPseudoramiXExtension = FALSE; - -extern int ProcPanoramiXQueryVersion (ClientPtr client); - -static void PseudoramiXResetProc(ExtensionEntry *extEntry); - -static int ProcPseudoramiXQueryVersion(ClientPtr client); -static int ProcPseudoramiXGetState(ClientPtr client); -static int ProcPseudoramiXGetScreenCount(ClientPtr client); -static int ProcPseudoramiXGetScreenSize(ClientPtr client); -static int ProcPseudoramiXIsActive(ClientPtr client); -static int ProcPseudoramiXQueryScreens(ClientPtr client); -static int ProcPseudoramiXDispatch(ClientPtr client); - -static int SProcPseudoramiXQueryVersion(ClientPtr client); -static int SProcPseudoramiXGetState(ClientPtr client); -static int SProcPseudoramiXGetScreenCount(ClientPtr client); -static int SProcPseudoramiXGetScreenSize(ClientPtr client); -static int SProcPseudoramiXIsActive(ClientPtr client); -static int SProcPseudoramiXQueryScreens(ClientPtr client); -static int SProcPseudoramiXDispatch(ClientPtr client); - - -typedef struct { - int x; - int y; - int w; - int h; -} PseudoramiXScreenRec; - -static PseudoramiXScreenRec *pseudoramiXScreens = NULL; -static int pseudoramiXScreensAllocated = 0; -static int pseudoramiXNumScreens = 0; -static unsigned long pseudoramiXGeneration = 0; - - -// Add a PseudoramiX screen. -// The rest of the X server will know nothing about this screen. -// Can be called before or after extension init. -// Screens must be re-added once per generation. -void -PseudoramiXAddScreen(int x, int y, int w, int h) -{ - PseudoramiXScreenRec *s; - - if (noPseudoramiXExtension) return; - - if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) { - pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1; - pseudoramiXScreens = xrealloc(pseudoramiXScreens, - pseudoramiXScreensAllocated * - sizeof(PseudoramiXScreenRec)); - } - - DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x, y, w, h); - - s = &pseudoramiXScreens[pseudoramiXNumScreens++]; - s->x = x; - s->y = y; - s->w = w; - s->h = h; -} - - -// Initialize PseudoramiX. -// Copied from PanoramiXExtensionInit -void PseudoramiXExtensionInit(int argc, char *argv[]) -{ - Bool success = FALSE; - ExtensionEntry *extEntry; - - if (noPseudoramiXExtension) return; - - TRACE(); - - /* Even with only one screen we need to enable PseudoramiX to allow - dynamic screen configuration changes. */ -#if 0 - if (pseudoramiXNumScreens == 1) { - // Only one screen - disable Xinerama extension. - noPseudoramiXExtension = TRUE; - return; - } -#endif - - if (pseudoramiXGeneration != serverGeneration) { - extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0, - ProcPseudoramiXDispatch, - SProcPseudoramiXDispatch, - PseudoramiXResetProc, - StandardMinorOpcode); - if (!extEntry) { - ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n"); - } else { - pseudoramiXGeneration = serverGeneration; - success = TRUE; - } - } - - if (!success) { - ErrorF("%s Extension (PseudoramiX) failed to initialize\n", - PANORAMIX_PROTOCOL_NAME); - return; - } -} - - -void PseudoramiXResetScreens(void) -{ - TRACE(); - - pseudoramiXNumScreens = 0; -} - - -static void PseudoramiXResetProc(ExtensionEntry *extEntry) -{ - TRACE(); - - PseudoramiXResetScreens(); -} - - -// was PanoramiX -static int ProcPseudoramiXQueryVersion(ClientPtr client) -{ - TRACE(); - - return ProcPanoramiXQueryVersion(client); -} - - -// was PanoramiX -static int ProcPseudoramiXGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - WindowPtr pWin; - xPanoramiXGetStateReply rep; - register int n, rc; - - TRACE(); - - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = !noPseudoramiXExtension; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swaps (&rep.state, n); - } - WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); - return client->noClientException; -} - - -// was PanoramiX -static int ProcPseudoramiXGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - WindowPtr pWin; - xPanoramiXGetScreenCountReply rep; - register int n, rc; - - TRACE(); - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.ScreenCount = pseudoramiXNumScreens; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swaps (&rep.ScreenCount, n); - } - WriteToClient (client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); - return client->noClientException; -} - - -// was PanoramiX -static int ProcPseudoramiXGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - WindowPtr pWin; - xPanoramiXGetScreenSizeReply rep; - register int n, rc; - - TRACE(); - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - /* screen dimensions */ - rep.width = pseudoramiXScreens[stuff->screen].w; - // was panoramiXdataPtr[stuff->screen].width; - rep.height = pseudoramiXScreens[stuff->screen].h; - // was panoramiXdataPtr[stuff->screen].height; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swaps (&rep.width, n); - swaps (&rep.height, n); - } - WriteToClient (client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); - return client->noClientException; -} - - -// was Xinerama -static int ProcPseudoramiXIsActive(ClientPtr client) -{ - /* REQUEST(xXineramaIsActiveReq); */ - xXineramaIsActiveReply rep; - - TRACE(); - - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = !noPseudoramiXExtension; - if (client->swapped) { - register int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.state, n); - } - WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); - return client->noClientException; -} - - -// was Xinerama -static int ProcPseudoramiXQueryScreens(ClientPtr client) -{ - /* REQUEST(xXineramaQueryScreensReq); */ - xXineramaQueryScreensReply rep; - - DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n", noPseudoramiXExtension, pseudoramiXNumScreens); - - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens; - rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); - if (client->swapped) { - register int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.number, n); - } - WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); - - if (!noPseudoramiXExtension) { - xXineramaScreenInfo scratch; - int i; - - for(i = 0; i < pseudoramiXNumScreens; i++) { - scratch.x_org = pseudoramiXScreens[i].x; - scratch.y_org = pseudoramiXScreens[i].y; - scratch.width = pseudoramiXScreens[i].w; - scratch.height = pseudoramiXScreens[i].h; - - if(client->swapped) { - register int n; - swaps (&scratch.x_org, n); - swaps (&scratch.y_org, n); - swaps (&scratch.width, n); - swaps (&scratch.height, n); - } - WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); - } - } - - return client->noClientException; -} - - -// was PanoramiX -static int ProcPseudoramiXDispatch (ClientPtr client) -{ REQUEST(xReq); - TRACE(); - switch (stuff->data) - { - case X_PanoramiXQueryVersion: - return ProcPseudoramiXQueryVersion(client); - case X_PanoramiXGetState: - return ProcPseudoramiXGetState(client); - case X_PanoramiXGetScreenCount: - return ProcPseudoramiXGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return ProcPseudoramiXGetScreenSize(client); - case X_XineramaIsActive: - return ProcPseudoramiXIsActive(client); - case X_XineramaQueryScreens: - return ProcPseudoramiXQueryScreens(client); - } - return BadRequest; -} - - - -static int -SProcPseudoramiXQueryVersion (ClientPtr client) -{ - REQUEST(xPanoramiXQueryVersionReq); - register int n; - - TRACE(); - - swaps(&stuff->length,n); - REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); - return ProcPseudoramiXQueryVersion(client); -} - -static int -SProcPseudoramiXGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - register int n; - - TRACE(); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - return ProcPseudoramiXGetState(client); -} - -static int -SProcPseudoramiXGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - register int n; - - TRACE(); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - return ProcPseudoramiXGetScreenCount(client); -} - -static int -SProcPseudoramiXGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - register int n; - - TRACE(); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - return ProcPseudoramiXGetScreenSize(client); -} - - -static int -SProcPseudoramiXIsActive(ClientPtr client) -{ - REQUEST(xXineramaIsActiveReq); - register int n; - - TRACE(); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - return ProcPseudoramiXIsActive(client); -} - - -static int -SProcPseudoramiXQueryScreens(ClientPtr client) -{ - REQUEST(xXineramaQueryScreensReq); - register int n; - - TRACE(); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - return ProcPseudoramiXQueryScreens(client); -} - - -static int -SProcPseudoramiXDispatch (ClientPtr client) -{ REQUEST(xReq); - - TRACE(); - - switch (stuff->data) - { - case X_PanoramiXQueryVersion: - return SProcPseudoramiXQueryVersion(client); - case X_PanoramiXGetState: - return SProcPseudoramiXGetState(client); - case X_PanoramiXGetScreenCount: - return SProcPseudoramiXGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return SProcPseudoramiXGetScreenSize(client); - case X_XineramaIsActive: - return SProcPseudoramiXIsActive(client); - case X_XineramaQueryScreens: - return SProcPseudoramiXQueryScreens(client); - } - return BadRequest; -} +/* + * Minimal implementation of PanoramiX/Xinerama + * + * This is used in rootless mode where the underlying window server + * already provides an abstracted view of multiple screens as one + * large screen area. + * + * This code is largely based on panoramiX.c, which contains the + * following copyright notice: + */ +/***************************************************************** +Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. +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. + +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 +DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, +BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization from Digital +Equipment Corporation. +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "darwin.h" +#include "pseudoramiX.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "window.h" +#include <X11/extensions/panoramiXproto.h> +#include "globals.h" + +Bool noPseudoramiXExtension = FALSE; + +extern int ProcPanoramiXQueryVersion (ClientPtr client); + +static void PseudoramiXResetProc(ExtensionEntry *extEntry); + +static int ProcPseudoramiXQueryVersion(ClientPtr client); +static int ProcPseudoramiXGetState(ClientPtr client); +static int ProcPseudoramiXGetScreenCount(ClientPtr client); +static int ProcPseudoramiXGetScreenSize(ClientPtr client); +static int ProcPseudoramiXIsActive(ClientPtr client); +static int ProcPseudoramiXQueryScreens(ClientPtr client); +static int ProcPseudoramiXDispatch(ClientPtr client); + +static int SProcPseudoramiXQueryVersion(ClientPtr client); +static int SProcPseudoramiXGetState(ClientPtr client); +static int SProcPseudoramiXGetScreenCount(ClientPtr client); +static int SProcPseudoramiXGetScreenSize(ClientPtr client); +static int SProcPseudoramiXIsActive(ClientPtr client); +static int SProcPseudoramiXQueryScreens(ClientPtr client); +static int SProcPseudoramiXDispatch(ClientPtr client); + + +typedef struct { + int x; + int y; + int w; + int h; +} PseudoramiXScreenRec; + +static PseudoramiXScreenRec *pseudoramiXScreens = NULL; +static int pseudoramiXScreensAllocated = 0; +static int pseudoramiXNumScreens = 0; +static unsigned long pseudoramiXGeneration = 0; + + +// Add a PseudoramiX screen. +// The rest of the X server will know nothing about this screen. +// Can be called before or after extension init. +// Screens must be re-added once per generation. +void +PseudoramiXAddScreen(int x, int y, int w, int h) +{ + PseudoramiXScreenRec *s; + + if (noPseudoramiXExtension) return; + + if (pseudoramiXNumScreens == pseudoramiXScreensAllocated) { + pseudoramiXScreensAllocated += pseudoramiXScreensAllocated + 1; + pseudoramiXScreens = realloc(pseudoramiXScreens, + pseudoramiXScreensAllocated * + sizeof(PseudoramiXScreenRec)); + } + + DEBUG_LOG("x: %d, y: %d, w: %d, h: %d\n", x, y, w, h); + + s = &pseudoramiXScreens[pseudoramiXNumScreens++]; + s->x = x; + s->y = y; + s->w = w; + s->h = h; +} + + +// Initialize PseudoramiX. +// Copied from PanoramiXExtensionInit +void PseudoramiXExtensionInit(int argc, char *argv[]) +{ + Bool success = FALSE; + ExtensionEntry *extEntry; + + if (noPseudoramiXExtension) return; + + TRACE(); + + /* Even with only one screen we need to enable PseudoramiX to allow + dynamic screen configuration changes. */ +#if 0 + if (pseudoramiXNumScreens == 1) { + // Only one screen - disable Xinerama extension. + noPseudoramiXExtension = TRUE; + return; + } +#endif + + if (pseudoramiXGeneration != serverGeneration) { + extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0, + ProcPseudoramiXDispatch, + SProcPseudoramiXDispatch, + PseudoramiXResetProc, + StandardMinorOpcode); + if (!extEntry) { + ErrorF("PseudoramiXExtensionInit(): AddExtension failed\n"); + } else { + pseudoramiXGeneration = serverGeneration; + success = TRUE; + } + } + + if (!success) { + ErrorF("%s Extension (PseudoramiX) failed to initialize\n", + PANORAMIX_PROTOCOL_NAME); + return; + } +} + + +void PseudoramiXResetScreens(void) +{ + TRACE(); + + pseudoramiXNumScreens = 0; +} + + +static void PseudoramiXResetProc(ExtensionEntry *extEntry) +{ + TRACE(); + + PseudoramiXResetScreens(); +} + + +// was PanoramiX +static int ProcPseudoramiXQueryVersion(ClientPtr client) +{ + TRACE(); + + return ProcPanoramiXQueryVersion(client); +} + + +// was PanoramiX +static int ProcPseudoramiXGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + register int n, rc; + + TRACE(); + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !noPseudoramiXExtension; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.state, n); + } + WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); + return Success; +} + + +// was PanoramiX +static int ProcPseudoramiXGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + register int n, rc; + + TRACE(); + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = pseudoramiXNumScreens; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.ScreenCount, n); + } + WriteToClient (client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep); + return Success; +} + + +// was PanoramiX +static int ProcPseudoramiXGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + xPanoramiXGetScreenSizeReply rep; + register int n, rc; + + TRACE(); + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + /* screen dimensions */ + rep.width = pseudoramiXScreens[stuff->screen].w; + // was panoramiXdataPtr[stuff->screen].width; + rep.height = pseudoramiXScreens[stuff->screen].h; + // was panoramiXdataPtr[stuff->screen].height; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swaps (&rep.width, n); + swaps (&rep.height, n); + } + WriteToClient (client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep); + return Success; +} + + +// was Xinerama +static int ProcPseudoramiXIsActive(ClientPtr client) +{ + /* REQUEST(xXineramaIsActiveReq); */ + xXineramaIsActiveReply rep; + + TRACE(); + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !noPseudoramiXExtension; + if (client->swapped) { + register int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.state, n); + } + WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); + return Success; +} + + +// was Xinerama +static int ProcPseudoramiXQueryScreens(ClientPtr client) +{ + /* REQUEST(xXineramaQueryScreensReq); */ + xXineramaQueryScreensReply rep; + + DEBUG_LOG("noPseudoramiXExtension=%d, pseudoramiXNumScreens=%d\n", noPseudoramiXExtension, pseudoramiXNumScreens); + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = noPseudoramiXExtension ? 0 : pseudoramiXNumScreens; + rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); + if (client->swapped) { + register int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.number, n); + } + WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); + + if (!noPseudoramiXExtension) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < pseudoramiXNumScreens; i++) { + scratch.x_org = pseudoramiXScreens[i].x; + scratch.y_org = pseudoramiXScreens[i].y; + scratch.width = pseudoramiXScreens[i].w; + scratch.height = pseudoramiXScreens[i].h; + + if(client->swapped) { + register int n; + swaps (&scratch.x_org, n); + swaps (&scratch.y_org, n); + swaps (&scratch.width, n); + swaps (&scratch.height, n); + } + WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); + } + } + + return Success; +} + + +// was PanoramiX +static int ProcPseudoramiXDispatch (ClientPtr client) +{ REQUEST(xReq); + TRACE(); + switch (stuff->data) + { + case X_PanoramiXQueryVersion: + return ProcPseudoramiXQueryVersion(client); + case X_PanoramiXGetState: + return ProcPseudoramiXGetState(client); + case X_PanoramiXGetScreenCount: + return ProcPseudoramiXGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return ProcPseudoramiXGetScreenSize(client); + case X_XineramaIsActive: + return ProcPseudoramiXIsActive(client); + case X_XineramaQueryScreens: + return ProcPseudoramiXQueryScreens(client); + } + return BadRequest; +} + + + +static int +SProcPseudoramiXQueryVersion (ClientPtr client) +{ + REQUEST(xPanoramiXQueryVersionReq); + register int n; + + TRACE(); + + swaps(&stuff->length,n); + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + return ProcPseudoramiXQueryVersion(client); +} + +static int +SProcPseudoramiXGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + register int n; + + TRACE(); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + return ProcPseudoramiXGetState(client); +} + +static int +SProcPseudoramiXGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + register int n; + + TRACE(); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + return ProcPseudoramiXGetScreenCount(client); +} + +static int +SProcPseudoramiXGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + register int n; + + TRACE(); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + return ProcPseudoramiXGetScreenSize(client); +} + + +static int +SProcPseudoramiXIsActive(ClientPtr client) +{ + REQUEST(xXineramaIsActiveReq); + register int n; + + TRACE(); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + return ProcPseudoramiXIsActive(client); +} + + +static int +SProcPseudoramiXQueryScreens(ClientPtr client) +{ + REQUEST(xXineramaQueryScreensReq); + register int n; + + TRACE(); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + return ProcPseudoramiXQueryScreens(client); +} + + +static int +SProcPseudoramiXDispatch (ClientPtr client) +{ REQUEST(xReq); + + TRACE(); + + switch (stuff->data) + { + case X_PanoramiXQueryVersion: + return SProcPseudoramiXQueryVersion(client); + case X_PanoramiXGetState: + return SProcPseudoramiXGetState(client); + case X_PanoramiXGetScreenCount: + return SProcPseudoramiXGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return SProcPseudoramiXGetScreenSize(client); + case X_XineramaIsActive: + return SProcPseudoramiXIsActive(client); + case X_XineramaQueryScreens: + return SProcPseudoramiXQueryScreens(client); + } + return BadRequest; +} diff --git a/xorg-server/hw/xquartz/quartz.c b/xorg-server/hw/xquartz/quartz.c index a8c0d4b47..e073b0586 100644 --- a/xorg-server/hw/xquartz/quartz.c +++ b/xorg-server/hw/xquartz/quartz.c @@ -1,449 +1,448 @@ -/* - * - * Quartz-specific support for the Darwin X Server - * - * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons. - * 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 ABOVE LISTED COPYRIGHT HOLDER(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(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "quartzCommon.h" -#include "inputstr.h" -#include "quartz.h" -#include "darwin.h" -#include "darwinEvents.h" -#include "pseudoramiX.h" -#define _APPLEWM_SERVER_ -#include "applewmExt.h" - -#include "X11Application.h" - -#include <X11/extensions/applewmconst.h> -#include <X11/extensions/randr.h> - -// X headers -#include "scrnintstr.h" -#include "windowstr.h" -#include "colormapst.h" -#include "globals.h" -#include "mi.h" - -// System headers -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <IOKit/pwr_mgt/IOPMLib.h> - -#include <rootlessCommon.h> -#include <Xplugin.h> - -#define FAKE_RANDR 1 - -// Shared global variables for Quartz modes -int quartzEventWriteFD = -1; -int quartzUseSysBeep = 0; -int quartzUseAGL = 1; -int quartzEnableKeyEquivalents = 1; -int quartzServerVisible = FALSE; -int quartzServerQuitting = FALSE; -static int quartzScreenKeyIndex; -DevPrivateKey quartzScreenKey = &quartzScreenKeyIndex; -int aquaMenuBarHeight = 0; -QuartzModeProcsPtr quartzProcs = NULL; -const char *quartzOpenGLBundle = NULL; -int quartzFullscreenDisableHotkeys = TRUE; -int quartzOptionSendsAlt = FALSE; - -#if defined(RANDR) && !defined(FAKE_RANDR) -Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { - return FALSE; -} - -Bool QuartzRandRSetConfig (ScreenPtr pScreen, - Rotation randr, - int rate, - RRScreenSizePtr pSize) { - return FALSE; -} - -Bool QuartzRandRInit (ScreenPtr pScreen) { - rrScrPrivPtr pScrPriv; - - if (!RRScreenInit (pScreen)) return FALSE; - - pScrPriv = rrGetScrPriv(pScreen); - pScrPriv->rrGetInfo = QuartzRandRGetInfo; - pScrPriv->rrSetConfig = QuartzRandRSetConfig; - return TRUE; -} -#endif - -/* -=========================================================================== - - Screen functions - -=========================================================================== -*/ - -/* - * QuartzAddScreen - * Do mode dependent initialization of each screen for Quartz. - */ -Bool QuartzAddScreen( - int index, - ScreenPtr pScreen) -{ - // allocate space for private per screen Quartz specific storage - QuartzScreenPtr displayInfo = xcalloc(sizeof(QuartzScreenRec), 1); - - // QUARTZ_PRIV(pScreen) = displayInfo; - dixSetPrivate(&pScreen->devPrivates, quartzScreenKey, displayInfo); - - // do Quartz mode specific initialization - return quartzProcs->AddScreen(index, pScreen); -} - - -/* - * QuartzSetupScreen - * Finalize mode specific setup of each screen. - */ -Bool QuartzSetupScreen( - int index, - ScreenPtr pScreen) -{ - // do Quartz mode specific setup - if (! quartzProcs->SetupScreen(index, pScreen)) - return FALSE; - - // setup cursor support - if (! quartzProcs->InitCursor(pScreen)) - return FALSE; - - return TRUE; -} - - -/* - * QuartzInitOutput - * Quartz display initialization. - */ -void QuartzInitOutput( - int argc, - char **argv ) -{ - if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler, - QuartzWakeupHandler, - NULL)) - { - FatalError("Could not register block and wakeup handlers."); - } - -#if defined(RANDR) && !defined(FAKE_RANDR) - if(!QuartzRandRInit(pScreen)) - FatalError("Failed to init RandR extension.\n"); -#endif - - // Do display mode specific initialization - quartzProcs->DisplayInit(); -} - - -/* - * QuartzInitInput - * Inform the main thread the X server is ready to handle events. - */ -void QuartzInitInput( - int argc, - char **argv ) -{ - X11ApplicationSetCanQuit(0); - X11ApplicationServerReady(); - // Do final display mode specific initialization before handling events - if (quartzProcs->InitInput) - quartzProcs->InitInput(argc, argv); -} - - -#ifdef FAKE_RANDR - -static const int padlength[4] = {0, 3, 2, 1}; - -static void -RREditConnectionInfo (ScreenPtr pScreen) -{ - xConnSetup *connSetup; - char *vendor; - xPixmapFormat *formats; - xWindowRoot *root; - xDepth *depth; - xVisualType *visual; - int screen = 0; - int d; - - connSetup = (xConnSetup *) ConnectionInfo; - vendor = (char *) connSetup + sizeof (xConnSetup); - formats = (xPixmapFormat *) ((char *) vendor + - connSetup->nbytesVendor + - padlength[connSetup->nbytesVendor & 3]); - root = (xWindowRoot *) ((char *) formats + - sizeof (xPixmapFormat) * screenInfo.numPixmapFormats); - while (screen != pScreen->myNum) - { - depth = (xDepth *) ((char *) root + - sizeof (xWindowRoot)); - for (d = 0; d < root->nDepths; d++) - { - visual = (xVisualType *) ((char *) depth + - sizeof (xDepth)); - depth = (xDepth *) ((char *) visual + - depth->nVisuals * sizeof (xVisualType)); - } - root = (xWindowRoot *) ((char *) depth); - screen++; - } - root->pixWidth = pScreen->width; - root->pixHeight = pScreen->height; - root->mmWidth = pScreen->mmWidth; - root->mmHeight = pScreen->mmHeight; -} -#endif - -void QuartzUpdateScreens(void) { - ScreenPtr pScreen; - WindowPtr pRoot; - int x, y, width, height, sx, sy; - xEvent e; - BoxRec bounds; - - if (noPseudoramiXExtension || screenInfo.numScreens != 1) - { - /* FIXME: if not using Xinerama, we have multiple screens, and - to do this properly may need to add or remove screens. Which - isn't possible. So don't do anything. Another reason why - we default to running with Xinerama. */ - - return; - } - - pScreen = screenInfo.screens[0]; - - PseudoramiXResetScreens(); - quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height); - - dixScreenOrigins[pScreen->myNum].x = x; - dixScreenOrigins[pScreen->myNum].y = y; - pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width); - pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height); - pScreen->width = width; - pScreen->height = height; - - DarwinAdjustScreenOrigins(&screenInfo); - quartzProcs->UpdateScreen(pScreen); - - /* DarwinAdjustScreenOrigins or UpdateScreen may change dixScreenOrigins, - * so use it rather than x/y - */ - sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX; - sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY; - - /* Adjust the root window. */ - pRoot = WindowTable[pScreen->myNum]; - AppleWMSetScreenOrigin(pRoot); - pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL); - //pScreen->PaintWindowBackground (pRoot, &pRoot->borderClip, PW_BACKGROUND); - miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); - - /* <rdar://problem/7770779> pointer events are clipped to old display region after display reconfiguration - * http://xquartz.macosforge.org/trac/ticket/346 - */ - bounds.x1 = 0; - bounds.x2 = width; - bounds.y1 = 0; - bounds.y2 = height; - pScreen->ConstrainCursor(inputInfo.pointer, pScreen, &bounds); - inputInfo.pointer->spriteInfo->sprite->physLimits = bounds; - inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds; - - DEBUG_LOG("Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n", width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY, x, y, dixScreenOrigins[pScreen->myNum].x, dixScreenOrigins[pScreen->myNum].y); - - /* Send an event for the root reconfigure */ - e.u.u.type = ConfigureNotify; - e.u.configureNotify.window = pRoot->drawable.id; - e.u.configureNotify.aboveSibling = None; - e.u.configureNotify.x = x - sx; - e.u.configureNotify.y = y - sy; - e.u.configureNotify.width = width; - e.u.configureNotify.height = height; - e.u.configureNotify.borderWidth = wBorderWidth(pRoot); - e.u.configureNotify.override = pRoot->overrideRedirect; - DeliverEvents(pRoot, &e, 1, NullWindow); - -#ifdef FAKE_RANDR - RREditConnectionInfo(pScreen); -#endif -} - -void QuartzSetFullscreen(Bool state) { - - DEBUG_LOG("QuartzSetFullscreen: state=%d\n", state); - - if(quartzHasRoot == state) - return; - - quartzHasRoot = state; - - xp_disable_update (); - - if (!quartzHasRoot && !quartzEnableRootless) - RootlessHideAllWindows(); - - RootlessUpdateRooted(quartzHasRoot); - - if (quartzHasRoot && !quartzEnableRootless) - RootlessShowAllWindows (); - - if (quartzHasRoot || quartzEnableRootless) { - RootlessRepositionWindows(screenInfo.screens[0]); - } - - /* Somehow the menubar manages to interfere with our event stream - * in fullscreen mode, even though it's not visible. - */ - X11ApplicationShowHideMenubar(!quartzHasRoot); - - xp_reenable_update (); - - if (quartzFullscreenDisableHotkeys) - xp_disable_hot_keys(quartzHasRoot); -} - -void QuartzSetRootless(Bool state) { - if(quartzEnableRootless == state) - return; - - quartzEnableRootless = state; - - xp_disable_update(); - - /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */ - QuartzUpdateScreens(); - - if(!quartzHasRoot) { - if(!quartzEnableRootless) { - RootlessHideAllWindows(); - } else { - RootlessShowAllWindows(); - } - } - - X11ApplicationShowHideMenubar(!quartzHasRoot); - - xp_reenable_update(); - - if (!quartzEnableRootless && quartzFullscreenDisableHotkeys) - xp_disable_hot_keys(quartzHasRoot); -} - -/* - * QuartzShow - * Show the X server on screen. Does nothing if already shown. - * Calls mode specific screen resume to restore the X clip regions - * (if needed) and the X server cursor state. - */ -void QuartzShow(void) { - int i; - - if (quartzServerVisible) - return; - - quartzServerVisible = TRUE; - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i]) { - quartzProcs->ResumeScreen(screenInfo.screens[i]); - } - } - - if (!quartzEnableRootless) - QuartzSetFullscreen(TRUE); -} - - -/* - * QuartzHide - * Remove the X server display from the screen. Does nothing if already - * hidden. Calls mode specific screen suspend to set X clip regions to - * prevent drawing (if needed) and restore the Aqua cursor. - */ -void QuartzHide(void) -{ - int i; - - if (quartzServerVisible) { - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i]) { - quartzProcs->SuspendScreen(screenInfo.screens[i]); - } - } - } - - QuartzSetFullscreen(FALSE); - quartzServerVisible = FALSE; -} - - -/* - * QuartzSetRootClip - * Enable or disable rendering to the X screen. - */ -void QuartzSetRootClip( - BOOL enable) -{ - int i; - - if (!quartzServerVisible) - return; - - for (i = 0; i < screenInfo.numScreens; i++) { - if (screenInfo.screens[i]) { - xf86SetRootClip(screenInfo.screens[i], enable); - } - } -} - -/* - * QuartzSpaceChanged - * Unmap offscreen windows, map onscreen windows - */ -void QuartzSpaceChanged(uint32_t space_id) { - /* Do something special here, so we don't depend on quartz-wm for spaces to work... */ - DEBUG_LOG("Space Changed (%u) ... do something interesting...\n", space_id); -} +/* + * + * Quartz-specific support for the Darwin X Server + * + * Copyright (c) 2001-2004 Greg Parker and Torrey T. Lyons. + * 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 ABOVE LISTED COPYRIGHT HOLDER(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(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "quartzCommon.h" +#include "inputstr.h" +#include "quartz.h" +#include "darwin.h" +#include "darwinEvents.h" +#include "pseudoramiX.h" +#define _APPLEWM_SERVER_ +#include "applewmExt.h" + +#include "X11Application.h" + +#include <X11/extensions/applewmconst.h> +#include <X11/extensions/randr.h> + +// X headers +#include "scrnintstr.h" +#include "windowstr.h" +#include "colormapst.h" +#include "globals.h" +#include "mi.h" + +// System headers +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <IOKit/pwr_mgt/IOPMLib.h> + +#include <rootlessCommon.h> +#include <Xplugin.h> + +#define FAKE_RANDR 1 + +// Shared global variables for Quartz modes +int quartzEventWriteFD = -1; +int quartzUseSysBeep = 0; +int quartzUseAGL = 1; +int quartzEnableKeyEquivalents = 1; +int quartzServerVisible = FALSE; +int quartzServerQuitting = FALSE; +static int quartzScreenKeyIndex; +DevPrivateKey quartzScreenKey = &quartzScreenKeyIndex; +int aquaMenuBarHeight = 0; +QuartzModeProcsPtr quartzProcs = NULL; +const char *quartzOpenGLBundle = NULL; +int quartzFullscreenDisableHotkeys = TRUE; +int quartzOptionSendsAlt = FALSE; + +#if defined(RANDR) && !defined(FAKE_RANDR) +Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { + return FALSE; +} + +Bool QuartzRandRSetConfig (ScreenPtr pScreen, + Rotation randr, + int rate, + RRScreenSizePtr pSize) { + return FALSE; +} + +Bool QuartzRandRInit (ScreenPtr pScreen) { + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit (pScreen)) return FALSE; + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = QuartzRandRGetInfo; + pScrPriv->rrSetConfig = QuartzRandRSetConfig; + return TRUE; +} +#endif + +/* +=========================================================================== + + Screen functions + +=========================================================================== +*/ + +/* + * QuartzAddScreen + * Do mode dependent initialization of each screen for Quartz. + */ +Bool QuartzAddScreen( + int index, + ScreenPtr pScreen) +{ + // allocate space for private per screen Quartz specific storage + QuartzScreenPtr displayInfo = calloc(sizeof(QuartzScreenRec), 1); + + // QUARTZ_PRIV(pScreen) = displayInfo; + dixSetPrivate(&pScreen->devPrivates, quartzScreenKey, displayInfo); + + // do Quartz mode specific initialization + return quartzProcs->AddScreen(index, pScreen); +} + + +/* + * QuartzSetupScreen + * Finalize mode specific setup of each screen. + */ +Bool QuartzSetupScreen( + int index, + ScreenPtr pScreen) +{ + // do Quartz mode specific setup + if (! quartzProcs->SetupScreen(index, pScreen)) + return FALSE; + + // setup cursor support + if (! quartzProcs->InitCursor(pScreen)) + return FALSE; + + return TRUE; +} + + +/* + * QuartzInitOutput + * Quartz display initialization. + */ +void QuartzInitOutput( + int argc, + char **argv ) +{ + if (!RegisterBlockAndWakeupHandlers(QuartzBlockHandler, + QuartzWakeupHandler, + NULL)) + { + FatalError("Could not register block and wakeup handlers."); + } + +#if defined(RANDR) && !defined(FAKE_RANDR) + if(!QuartzRandRInit(pScreen)) + FatalError("Failed to init RandR extension.\n"); +#endif + + // Do display mode specific initialization + quartzProcs->DisplayInit(); +} + + +/* + * QuartzInitInput + * Inform the main thread the X server is ready to handle events. + */ +void QuartzInitInput( + int argc, + char **argv ) +{ + X11ApplicationSetCanQuit(0); + X11ApplicationServerReady(); + // Do final display mode specific initialization before handling events + if (quartzProcs->InitInput) + quartzProcs->InitInput(argc, argv); +} + + +#ifdef FAKE_RANDR + +static const int padlength[4] = {0, 3, 2, 1}; + +static void +RREditConnectionInfo (ScreenPtr pScreen) +{ + xConnSetup *connSetup; + char *vendor; + xPixmapFormat *formats; + xWindowRoot *root; + xDepth *depth; + xVisualType *visual; + int screen = 0; + int d; + + connSetup = (xConnSetup *) ConnectionInfo; + vendor = (char *) connSetup + sizeof (xConnSetup); + formats = (xPixmapFormat *) ((char *) vendor + + connSetup->nbytesVendor + + padlength[connSetup->nbytesVendor & 3]); + root = (xWindowRoot *) ((char *) formats + + sizeof (xPixmapFormat) * screenInfo.numPixmapFormats); + while (screen != pScreen->myNum) + { + depth = (xDepth *) ((char *) root + + sizeof (xWindowRoot)); + for (d = 0; d < root->nDepths; d++) + { + visual = (xVisualType *) ((char *) depth + + sizeof (xDepth)); + depth = (xDepth *) ((char *) visual + + depth->nVisuals * sizeof (xVisualType)); + } + root = (xWindowRoot *) ((char *) depth); + screen++; + } + root->pixWidth = pScreen->width; + root->pixHeight = pScreen->height; + root->mmWidth = pScreen->mmWidth; + root->mmHeight = pScreen->mmHeight; +} +#endif + +void QuartzUpdateScreens(void) { + ScreenPtr pScreen; + WindowPtr pRoot; + int x, y, width, height, sx, sy; + xEvent e; + BoxRec bounds; + + if (noPseudoramiXExtension || screenInfo.numScreens != 1) + { + /* FIXME: if not using Xinerama, we have multiple screens, and + to do this properly may need to add or remove screens. Which + isn't possible. So don't do anything. Another reason why + we default to running with Xinerama. */ + + return; + } + + pScreen = screenInfo.screens[0]; + + PseudoramiXResetScreens(); + quartzProcs->AddPseudoramiXScreens(&x, &y, &width, &height); + + dixScreenOrigins[pScreen->myNum].x = x; + dixScreenOrigins[pScreen->myNum].y = y; + pScreen->mmWidth = pScreen->mmWidth * ((double) width / pScreen->width); + pScreen->mmHeight = pScreen->mmHeight * ((double) height / pScreen->height); + pScreen->width = width; + pScreen->height = height; + + DarwinAdjustScreenOrigins(&screenInfo); + quartzProcs->UpdateScreen(pScreen); + + /* DarwinAdjustScreenOrigins or UpdateScreen may change dixScreenOrigins, + * so use it rather than x/y + */ + sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX; + sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY; + + /* Adjust the root window. */ + pRoot = WindowTable[pScreen->myNum]; + AppleWMSetScreenOrigin(pRoot); + pScreen->ResizeWindow(pRoot, x - sx, y - sy, width, height, NULL); + miPaintWindow(pRoot, &pRoot->borderClip, PW_BACKGROUND); + + /* <rdar://problem/7770779> pointer events are clipped to old display region after display reconfiguration + * http://xquartz.macosforge.org/trac/ticket/346 + */ + bounds.x1 = 0; + bounds.x2 = width; + bounds.y1 = 0; + bounds.y2 = height; + pScreen->ConstrainCursor(inputInfo.pointer, pScreen, &bounds); + inputInfo.pointer->spriteInfo->sprite->physLimits = bounds; + inputInfo.pointer->spriteInfo->sprite->hotLimits = bounds; + + DEBUG_LOG("Root Window: %dx%d @ (%d, %d) darwinMainScreen (%d, %d) xy (%d, %d) dixScreenOrigins (%d, %d)\n", width, height, x - sx, y - sy, darwinMainScreenX, darwinMainScreenY, x, y, dixScreenOrigins[pScreen->myNum].x, dixScreenOrigins[pScreen->myNum].y); + + /* Send an event for the root reconfigure */ + e.u.u.type = ConfigureNotify; + e.u.configureNotify.window = pRoot->drawable.id; + e.u.configureNotify.aboveSibling = None; + e.u.configureNotify.x = x - sx; + e.u.configureNotify.y = y - sy; + e.u.configureNotify.width = width; + e.u.configureNotify.height = height; + e.u.configureNotify.borderWidth = wBorderWidth(pRoot); + e.u.configureNotify.override = pRoot->overrideRedirect; + DeliverEvents(pRoot, &e, 1, NullWindow); + +#ifdef FAKE_RANDR + RREditConnectionInfo(pScreen); +#endif +} + +void QuartzSetFullscreen(Bool state) { + + DEBUG_LOG("QuartzSetFullscreen: state=%d\n", state); + + if(quartzHasRoot == state) + return; + + quartzHasRoot = state; + + xp_disable_update (); + + if (!quartzHasRoot && !quartzEnableRootless) + RootlessHideAllWindows(); + + RootlessUpdateRooted(quartzHasRoot); + + if (quartzHasRoot && !quartzEnableRootless) + RootlessShowAllWindows (); + + if (quartzHasRoot || quartzEnableRootless) { + RootlessRepositionWindows(screenInfo.screens[0]); + } + + /* Somehow the menubar manages to interfere with our event stream + * in fullscreen mode, even though it's not visible. + */ + X11ApplicationShowHideMenubar(!quartzHasRoot); + + xp_reenable_update (); + + if (quartzFullscreenDisableHotkeys) + xp_disable_hot_keys(quartzHasRoot); +} + +void QuartzSetRootless(Bool state) { + if(quartzEnableRootless == state) + return; + + quartzEnableRootless = state; + + xp_disable_update(); + + /* When in rootless, the menubar is not part of the screen, so we need to update our screens on toggle */ + QuartzUpdateScreens(); + + if(!quartzHasRoot) { + if(!quartzEnableRootless) { + RootlessHideAllWindows(); + } else { + RootlessShowAllWindows(); + } + } + + X11ApplicationShowHideMenubar(!quartzHasRoot); + + xp_reenable_update(); + + if (!quartzEnableRootless && quartzFullscreenDisableHotkeys) + xp_disable_hot_keys(quartzHasRoot); +} + +/* + * QuartzShow + * Show the X server on screen. Does nothing if already shown. + * Calls mode specific screen resume to restore the X clip regions + * (if needed) and the X server cursor state. + */ +void QuartzShow(void) { + int i; + + if (quartzServerVisible) + return; + + quartzServerVisible = TRUE; + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i]) { + quartzProcs->ResumeScreen(screenInfo.screens[i]); + } + } + + if (!quartzEnableRootless) + QuartzSetFullscreen(TRUE); +} + + +/* + * QuartzHide + * Remove the X server display from the screen. Does nothing if already + * hidden. Calls mode specific screen suspend to set X clip regions to + * prevent drawing (if needed) and restore the Aqua cursor. + */ +void QuartzHide(void) +{ + int i; + + if (quartzServerVisible) { + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i]) { + quartzProcs->SuspendScreen(screenInfo.screens[i]); + } + } + } + + QuartzSetFullscreen(FALSE); + quartzServerVisible = FALSE; +} + + +/* + * QuartzSetRootClip + * Enable or disable rendering to the X screen. + */ +void QuartzSetRootClip( + BOOL enable) +{ + int i; + + if (!quartzServerVisible) + return; + + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i]) { + xf86SetRootClip(screenInfo.screens[i], enable); + } + } +} + +/* + * QuartzSpaceChanged + * Unmap offscreen windows, map onscreen windows + */ +void QuartzSpaceChanged(uint32_t space_id) { + /* Do something special here, so we don't depend on quartz-wm for spaces to work... */ + DEBUG_LOG("Space Changed (%u) ... do something interesting...\n", space_id); +} diff --git a/xorg-server/hw/xquartz/xpr/appledri.c b/xorg-server/hw/xquartz/xpr/appledri.c index 74a4ec315..87cb9016a 100644 --- a/xorg-server/hw/xquartz/xpr/appledri.c +++ b/xorg-server/hw/xquartz/xpr/appledri.c @@ -1,429 +1,429 @@ -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -Copyright 2000 VA Linux Systems, Inc. -Copyright (c) 2002, 2009 Apple Computer, 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 <martin@valinux.com> - * Jens Owen <jens@valinux.com> - * Rickard E. (Rik) Faith <faith@valinux.com> - * - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "servermd.h" -#define _APPLEDRI_SERVER_ -#include "appledristr.h" -#include "swaprep.h" -#include "dri.h" -#include "dristruct.h" -#include "xpr.h" -#include "x-hash.h" -#include "protocol-versions.h" - -static int DRIErrorBase = 0; - -static DISPATCH_PROC(ProcAppleDRIDispatch); -static DISPATCH_PROC(SProcAppleDRIDispatch); - -static void AppleDRIResetProc(ExtensionEntry* extEntry); -static int ProcAppleDRICreatePixmap(ClientPtr client); - -static unsigned char DRIReqCode = 0; -static int DRIEventBase = 0; - -static void SNotifyEvent(xAppleDRINotifyEvent *from, xAppleDRINotifyEvent *to); - -typedef struct _DRIEvent *DRIEventPtr; -typedef struct _DRIEvent { - DRIEventPtr next; - ClientPtr client; - XID clientResource; - unsigned int mask; -} DRIEventRec; - - -void -AppleDRIExtensionInit(void) -{ - ExtensionEntry* extEntry; - - if (DRIExtensionInit() && - (extEntry = AddExtension(APPLEDRINAME, - AppleDRINumberEvents, - AppleDRINumberErrors, - ProcAppleDRIDispatch, - SProcAppleDRIDispatch, - AppleDRIResetProc, - StandardMinorOpcode))) { - DRIReqCode = (unsigned char)extEntry->base; - DRIErrorBase = extEntry->errorBase; - DRIEventBase = extEntry->eventBase; - EventSwapVector[DRIEventBase] = (EventSwapPtr) SNotifyEvent; - } -} - -/*ARGSUSED*/ -static void -AppleDRIResetProc ( - ExtensionEntry* extEntry -) -{ - DRIReset(); -} - -static int -ProcAppleDRIQueryVersion( - register ClientPtr client -) -{ - xAppleDRIQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH(xAppleDRIQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_APPLEDRI_MAJOR_VERSION; - rep.minorVersion = SERVER_APPLEDRI_MINOR_VERSION; - rep.patchVersion = SERVER_APPLEDRI_PATCH_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - } - WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - - -/* surfaces */ - -static int -ProcAppleDRIQueryDirectRenderingCapable( - register ClientPtr client -) -{ - xAppleDRIQueryDirectRenderingCapableReply rep; - Bool isCapable; - - REQUEST(xAppleDRIQueryDirectRenderingCapableReq); - REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq); - 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)) - rep.isCapable = 0; - - WriteToClient(client, - sizeof(xAppleDRIQueryDirectRenderingCapableReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcAppleDRIAuthConnection( - register ClientPtr client -) -{ - xAppleDRIAuthConnectionReply rep; - - REQUEST(xAppleDRIAuthConnectionReq); - REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq); - - 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 %u\n", (unsigned int)stuff->magic); - rep.authenticated = 0; - } - WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), (char *)&rep); - return (client->noClientException); -} - -static void surface_notify( - void *_arg, - void *data -) -{ - DRISurfaceNotifyArg *arg = _arg; - int client_index = (int) x_cvt_vptr_to_uint(data); - ClientPtr client; - xAppleDRINotifyEvent se; - - if (client_index < 0 || client_index >= currentMaxClients) - return; - - client = clients[client_index]; - if (client == NULL || client == serverClient || client->clientGone) - return; - - se.type = DRIEventBase + AppleDRISurfaceNotify; - se.kind = arg->kind; - se.arg = arg->id; - se.sequenceNumber = client->sequence; - se.time = currentTime.milliseconds; - WriteEventsToClient (client, 1, (xEvent *) &se); -} - -static int -ProcAppleDRICreateSurface( - ClientPtr client -) -{ - xAppleDRICreateSurfaceReply rep; - DrawablePtr pDrawable; - xp_surface_id sid; - unsigned int key[2]; - int rc; - - REQUEST(xAppleDRICreateSurfaceReq); - REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - rep.key_0 = rep.key_1 = rep.uid = 0; - - if (!DRICreateSurface( screenInfo.screens[stuff->screen], - (Drawable)stuff->drawable, pDrawable, - stuff->client_id, &sid, key, - surface_notify, - x_cvt_uint_to_vptr(client->index))) { - return BadValue; - } - - rep.key_0 = key[0]; - rep.key_1 = key[1]; - rep.uid = sid; - - WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcAppleDRIDestroySurface( - register ClientPtr client -) -{ - int rc; - REQUEST(xAppleDRIDestroySurfaceReq); - DrawablePtr pDrawable; - REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq); - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if (!DRIDestroySurface( screenInfo.screens[stuff->screen], - (Drawable)stuff->drawable, - pDrawable, NULL, NULL)) { - return BadValue; - } - - return (client->noClientException); -} - -static int -ProcAppleDRICreatePixmap(ClientPtr client) -{ - REQUEST(xAppleDRICreatePixmapReq); - DrawablePtr pDrawable; - int rc; - char path[PATH_MAX]; - xAppleDRICreatePixmapReply rep; - int width, height, pitch, bpp; - void *ptr; - - REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq); - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - - if(rc != Success) - return rc; - - if(!DRICreatePixmap(screenInfo.screens[stuff->screen], - (Drawable)stuff->drawable, - pDrawable, - path, PATH_MAX)) { - return BadValue; - } - - if(!DRIGetPixmapData(pDrawable, &width, &height, - &pitch, &bpp, &ptr)) { - return BadValue; - } - - rep.stringLength = strlen(path) + 1; - - /* No need for swapping, because this only runs if LocalClient is true. */ - rep.type = X_Reply; - rep.length = sizeof(rep) + rep.stringLength; - rep.sequenceNumber = client->sequence; - rep.width = width; - rep.height = height; - rep.pitch = pitch; - rep.bpp = bpp; - rep.size = pitch * height; - - if(sizeof(rep) != sz_xAppleDRICreatePixmapReply) - ErrorF("error sizeof(rep) is %zu\n", sizeof(rep)); - - WriteReplyToClient(client, sizeof(rep), &rep); - (void)WriteToClient(client, rep.stringLength, path); - - return (client->noClientException); -} - -static int -ProcAppleDRIDestroyPixmap(ClientPtr client) -{ - DrawablePtr pDrawable; - int rc; - REQUEST(xAppleDRIDestroyPixmapReq); - REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq); - - rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, - DixReadAccess); - - if(rc != Success) - return rc; - - DRIDestroyPixmap(pDrawable); - - return (client->noClientException); -} - -/* dispatch */ - -static int -ProcAppleDRIDispatch ( - register ClientPtr client -) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_AppleDRIQueryVersion: - return ProcAppleDRIQueryVersion(client); - case X_AppleDRIQueryDirectRenderingCapable: - return ProcAppleDRIQueryDirectRenderingCapable(client); - } - - if (!LocalClient(client)) - return DRIErrorBase + AppleDRIClientNotLocal; - - switch (stuff->data) - { - case X_AppleDRIAuthConnection: - return ProcAppleDRIAuthConnection(client); - case X_AppleDRICreateSurface: - return ProcAppleDRICreateSurface(client); - case X_AppleDRIDestroySurface: - return ProcAppleDRIDestroySurface(client); - case X_AppleDRICreatePixmap: - return ProcAppleDRICreatePixmap(client); - case X_AppleDRIDestroyPixmap: - return ProcAppleDRIDestroyPixmap(client); - - default: - return BadRequest; - } -} - -static void -SNotifyEvent( - xAppleDRINotifyEvent *from, - xAppleDRINotifyEvent *to -) -{ - to->type = from->type; - to->kind = from->kind; - cpswaps (from->sequenceNumber, to->sequenceNumber); - cpswapl (from->time, to->time); - cpswapl (from->arg, to->arg); -} - -static int -SProcAppleDRIQueryVersion( - register ClientPtr client -) -{ - register int n; - REQUEST(xAppleDRIQueryVersionReq); - swaps(&stuff->length, n); - return ProcAppleDRIQueryVersion(client); -} - -static int -SProcAppleDRIDispatch ( - register ClientPtr client -) -{ - REQUEST(xReq); - - /* It is bound to be non-local when there is byte swapping */ - if (!LocalClient(client)) - return DRIErrorBase + AppleDRIClientNotLocal; - - /* only local clients are allowed DRI access */ - switch (stuff->data) - { - case X_AppleDRIQueryVersion: - return SProcAppleDRIQueryVersion(client); - default: - return BadRequest; - } -} +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +Copyright (c) 2002, 2009 Apple Computer, 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 <martin@valinux.com> + * Jens Owen <jens@valinux.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "colormapst.h" +#include "cursorstr.h" +#include "scrnintstr.h" +#include "servermd.h" +#define _APPLEDRI_SERVER_ +#include "appledristr.h" +#include "swaprep.h" +#include "dri.h" +#include "dristruct.h" +#include "xpr.h" +#include "x-hash.h" +#include "protocol-versions.h" + +static int DRIErrorBase = 0; + +static DISPATCH_PROC(ProcAppleDRIDispatch); +static DISPATCH_PROC(SProcAppleDRIDispatch); + +static void AppleDRIResetProc(ExtensionEntry* extEntry); +static int ProcAppleDRICreatePixmap(ClientPtr client); + +static unsigned char DRIReqCode = 0; +static int DRIEventBase = 0; + +static void SNotifyEvent(xAppleDRINotifyEvent *from, xAppleDRINotifyEvent *to); + +typedef struct _DRIEvent *DRIEventPtr; +typedef struct _DRIEvent { + DRIEventPtr next; + ClientPtr client; + XID clientResource; + unsigned int mask; +} DRIEventRec; + + +void +AppleDRIExtensionInit(void) +{ + ExtensionEntry* extEntry; + + if (DRIExtensionInit() && + (extEntry = AddExtension(APPLEDRINAME, + AppleDRINumberEvents, + AppleDRINumberErrors, + ProcAppleDRIDispatch, + SProcAppleDRIDispatch, + AppleDRIResetProc, + StandardMinorOpcode))) { + DRIReqCode = (unsigned char)extEntry->base; + DRIErrorBase = extEntry->errorBase; + DRIEventBase = extEntry->eventBase; + EventSwapVector[DRIEventBase] = (EventSwapPtr) SNotifyEvent; + } +} + +/*ARGSUSED*/ +static void +AppleDRIResetProc ( + ExtensionEntry* extEntry +) +{ + DRIReset(); +} + +static int +ProcAppleDRIQueryVersion( + register ClientPtr client +) +{ + xAppleDRIQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH(xAppleDRIQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_APPLEDRI_MAJOR_VERSION; + rep.minorVersion = SERVER_APPLEDRI_MINOR_VERSION; + rep.patchVersion = SERVER_APPLEDRI_PATCH_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), (char *)&rep); + return Success; +} + + +/* surfaces */ + +static int +ProcAppleDRIQueryDirectRenderingCapable( + register ClientPtr client +) +{ + xAppleDRIQueryDirectRenderingCapableReply rep; + Bool isCapable; + + REQUEST(xAppleDRIQueryDirectRenderingCapableReq); + REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq); + 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)) + rep.isCapable = 0; + + WriteToClient(client, + sizeof(xAppleDRIQueryDirectRenderingCapableReply), (char *)&rep); + return Success; +} + +static int +ProcAppleDRIAuthConnection( + register ClientPtr client +) +{ + xAppleDRIAuthConnectionReply rep; + + REQUEST(xAppleDRIAuthConnectionReq); + REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq); + + 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 %u\n", (unsigned int)stuff->magic); + rep.authenticated = 0; + } + WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), (char *)&rep); + return Success; +} + +static void surface_notify( + void *_arg, + void *data +) +{ + DRISurfaceNotifyArg *arg = _arg; + int client_index = (int) x_cvt_vptr_to_uint(data); + ClientPtr client; + xAppleDRINotifyEvent se; + + if (client_index < 0 || client_index >= currentMaxClients) + return; + + client = clients[client_index]; + if (client == NULL || client == serverClient || client->clientGone) + return; + + se.type = DRIEventBase + AppleDRISurfaceNotify; + se.kind = arg->kind; + se.arg = arg->id; + se.sequenceNumber = client->sequence; + se.time = currentTime.milliseconds; + WriteEventsToClient (client, 1, (xEvent *) &se); +} + +static int +ProcAppleDRICreateSurface( + ClientPtr client +) +{ + xAppleDRICreateSurfaceReply rep; + DrawablePtr pDrawable; + xp_surface_id sid; + unsigned int key[2]; + int rc; + + REQUEST(xAppleDRICreateSurfaceReq); + REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + rep.key_0 = rep.key_1 = rep.uid = 0; + + if (!DRICreateSurface( screenInfo.screens[stuff->screen], + (Drawable)stuff->drawable, pDrawable, + stuff->client_id, &sid, key, + surface_notify, + x_cvt_uint_to_vptr(client->index))) { + return BadValue; + } + + rep.key_0 = key[0]; + rep.key_1 = key[1]; + rep.uid = sid; + + WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), (char *)&rep); + return Success; +} + +static int +ProcAppleDRIDestroySurface( + register ClientPtr client +) +{ + int rc; + REQUEST(xAppleDRIDestroySurfaceReq); + DrawablePtr pDrawable; + REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq); + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if (!DRIDestroySurface( screenInfo.screens[stuff->screen], + (Drawable)stuff->drawable, + pDrawable, NULL, NULL)) { + return BadValue; + } + + return Success; +} + +static int +ProcAppleDRICreatePixmap(ClientPtr client) +{ + REQUEST(xAppleDRICreatePixmapReq); + DrawablePtr pDrawable; + int rc; + char path[PATH_MAX]; + xAppleDRICreatePixmapReply rep; + int width, height, pitch, bpp; + void *ptr; + + REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq); + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + + if(rc != Success) + return rc; + + if(!DRICreatePixmap(screenInfo.screens[stuff->screen], + (Drawable)stuff->drawable, + pDrawable, + path, PATH_MAX)) { + return BadValue; + } + + if(!DRIGetPixmapData(pDrawable, &width, &height, + &pitch, &bpp, &ptr)) { + return BadValue; + } + + rep.stringLength = strlen(path) + 1; + + /* No need for swapping, because this only runs if LocalClient is true. */ + rep.type = X_Reply; + rep.length = sizeof(rep) + rep.stringLength; + rep.sequenceNumber = client->sequence; + rep.width = width; + rep.height = height; + rep.pitch = pitch; + rep.bpp = bpp; + rep.size = pitch * height; + + if(sizeof(rep) != sz_xAppleDRICreatePixmapReply) + ErrorF("error sizeof(rep) is %zu\n", sizeof(rep)); + + WriteReplyToClient(client, sizeof(rep), &rep); + (void)WriteToClient(client, rep.stringLength, path); + + return Success; +} + +static int +ProcAppleDRIDestroyPixmap(ClientPtr client) +{ + DrawablePtr pDrawable; + int rc; + REQUEST(xAppleDRIDestroyPixmapReq); + REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq); + + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixReadAccess); + + if(rc != Success) + return rc; + + DRIDestroyPixmap(pDrawable); + + return Success; +} + +/* dispatch */ + +static int +ProcAppleDRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_AppleDRIQueryVersion: + return ProcAppleDRIQueryVersion(client); + case X_AppleDRIQueryDirectRenderingCapable: + return ProcAppleDRIQueryDirectRenderingCapable(client); + } + + if (!LocalClient(client)) + return DRIErrorBase + AppleDRIClientNotLocal; + + switch (stuff->data) + { + case X_AppleDRIAuthConnection: + return ProcAppleDRIAuthConnection(client); + case X_AppleDRICreateSurface: + return ProcAppleDRICreateSurface(client); + case X_AppleDRIDestroySurface: + return ProcAppleDRIDestroySurface(client); + case X_AppleDRICreatePixmap: + return ProcAppleDRICreatePixmap(client); + case X_AppleDRIDestroyPixmap: + return ProcAppleDRIDestroyPixmap(client); + + default: + return BadRequest; + } +} + +static void +SNotifyEvent( + xAppleDRINotifyEvent *from, + xAppleDRINotifyEvent *to +) +{ + to->type = from->type; + to->kind = from->kind; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->time, to->time); + cpswapl (from->arg, to->arg); +} + +static int +SProcAppleDRIQueryVersion( + register ClientPtr client +) +{ + register int n; + REQUEST(xAppleDRIQueryVersionReq); + swaps(&stuff->length, n); + return ProcAppleDRIQueryVersion(client); +} + +static int +SProcAppleDRIDispatch ( + register ClientPtr client +) +{ + REQUEST(xReq); + + /* It is bound to be non-local when there is byte swapping */ + if (!LocalClient(client)) + return DRIErrorBase + AppleDRIClientNotLocal; + + /* only local clients are allowed DRI access */ + switch (stuff->data) + { + case X_AppleDRIQueryVersion: + return SProcAppleDRIQueryVersion(client); + default: + return BadRequest; + } +} diff --git a/xorg-server/hw/xquartz/xpr/dri.c b/xorg-server/hw/xquartz/xpr/dri.c index 0a58b29f3..363809d0d 100644 --- a/xorg-server/hw/xquartz/xpr/dri.c +++ b/xorg-server/hw/xquartz/xpr/dri.c @@ -1,953 +1,953 @@ -/************************************************************************** - -Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. -Copyright 2000 VA Linux Systems, Inc. -Copyright (c) 2002, 2009 Apple Computer, 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 <jens@valinux.com> - * Rickard E. (Rik) Faith <faith@valinux.com> - * - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#ifdef XFree86LOADER -#include "xf86.h" -#include "xf86_ansic.h" -#else -#include <sys/time.h> -#include <unistd.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.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 _APPLEDRI_SERVER_ -#include "appledristr.h" -#include "swaprep.h" -#include "dri.h" -#include "dristruct.h" -#include "mi.h" -#include "mipointer.h" -#include "rootless.h" -#include "x-hash.h" -#include "x-hook.h" -#include "driWrap.h" - -#include <AvailabilityMacros.h> - -static int DRIScreenPrivKeyIndex; -static DevPrivateKey DRIScreenPrivKey = &DRIScreenPrivKeyIndex; -static int DRIWindowPrivKeyIndex; -static DevPrivateKey DRIWindowPrivKey = &DRIWindowPrivKeyIndex; -static int DRIPixmapPrivKeyIndex; -static DevPrivateKey DRIPixmapPrivKey = &DRIPixmapPrivKeyIndex; -static int DRIPixmapBufferPrivKeyIndex; -static DevPrivateKey DRIPixmapBufferPrivKey = &DRIPixmapBufferPrivKeyIndex; - -static RESTYPE DRIDrawablePrivResType; - -static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */ - -static Bool DRIFreePixmapImp(DrawablePtr pDrawable); - -/* FIXME: don't hardcode this? */ -#define CG_INFO_FILE "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Resources/Info-macos.plist" - -/* Corresponds to SU Jaguar Green */ -#define CG_REQUIRED_MAJOR 1 -#define CG_REQUIRED_MINOR 157 -#define CG_REQUIRED_MICRO 11 - -typedef struct { - DrawablePtr pDrawable; - int refCount; - int bytesPerPixel; - int width; - int height; - char shmPath[PATH_MAX]; - int fd; /* From shm_open (for now) */ - size_t length; /* length of buffer */ - void *buffer; -} DRIPixmapBuffer, *DRIPixmapBufferPtr; - -/* Returns version as major.minor.micro in 10.10.10 fixed form */ -static unsigned int -get_cg_version (void) -{ - static unsigned int version; - - FILE *fh; - char *ptr; - - if (version != 0) - return version; - - /* I tried CFBundleGetVersion, but it returns zero, so.. */ - - fh = fopen (CG_INFO_FILE, "r"); - if (fh != NULL) - { - char buf[256]; - - while (fgets (buf, sizeof (buf), fh) != NULL) - { - unsigned char c; - - if (!strstr (buf, "<key>CFBundleShortVersionString</key>") - || fgets (buf, sizeof (buf), fh) == NULL) - { - continue; - } - - ptr = strstr (buf, "<string>"); - if (ptr == NULL) - continue; - - ptr += strlen ("<string>"); - - /* Now PTR points to "MAJOR.MINOR.MICRO". */ - - version = 0; - - again: - switch ((c = *ptr++)) - { - case '.': - version = version * 1024; - goto again; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - version = ((version & ~0x3ff) - + (version & 0x3ff) * 10 + (c - '0')); - goto again; - } - break; - } - - fclose (fh); - } - - return version; -} - -static Bool -test_cg_version (unsigned int major, unsigned int minor, unsigned int micro) -{ - unsigned int cg_ver = get_cg_version (); - - unsigned int cg_major = (cg_ver >> 20) & 0x3ff; - unsigned int cg_minor = (cg_ver >> 10) & 0x3ff; - unsigned int cg_micro = cg_ver & 0x3ff; - - if (cg_major > major) - return TRUE; - else if (cg_major < major) - return FALSE; - - /* cg_major == major */ - - if (cg_minor > minor) - return TRUE; - else if (cg_minor < minor) - return FALSE; - - /* cg_minor == minor */ - - if (cg_micro < micro) - return FALSE; - - return TRUE; -} - -Bool -DRIScreenInit(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv; - int i; - - pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec)); - if (!pDRIPriv) { - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); - return FALSE; - } - - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); - pDRIPriv->directRenderingSupport = TRUE; - pDRIPriv->nrWindows = 0; - - /* Need recent cg for window access update */ - if (!test_cg_version (CG_REQUIRED_MAJOR, - CG_REQUIRED_MINOR, - CG_REQUIRED_MICRO)) - { - ErrorF ("[DRI] disabled direct rendering; requires CoreGraphics %d.%d.%d\n", - CG_REQUIRED_MAJOR, CG_REQUIRED_MINOR, CG_REQUIRED_MICRO); - - pDRIPriv->directRenderingSupport = FALSE; - - /* Note we don't nuke the dri private, since we need it for - managing indirect surfaces. */ - } - - /* Initialize drawable tables */ - for (i = 0; i < DRI_MAX_DRAWABLES; i++) { - pDRIPriv->DRIDrawables[i] = NULL; - } - - return TRUE; -} - -Bool -DRIFinishScreenInit(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - /* Wrap DRI support */ - pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; - pScreen->ValidateTree = DRIValidateTree; - - pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; - pScreen->PostValidateTree = DRIPostValidateTree; - - pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; - pScreen->WindowExposures = DRIWindowExposures; - - pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; - pScreen->CopyWindow = DRICopyWindow; - - pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; - pScreen->ClipNotify = DRIClipNotify; - - // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum); - - return DRIWrapInit(pScreen); -} - -void -DRICloseScreen(ScreenPtr pScreen) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (pDRIPriv && pDRIPriv->directRenderingSupport) { - xfree(pDRIPriv); - dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); - } -} - -Bool -DRIExtensionInit(void) -{ - DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, - "DRIDrawable"); - - return (DRIDrawablePrivResType != 0); -} - -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 -DRIAuthConnection(ScreenPtr pScreen, unsigned int magic) -{ -#if 0 - /* FIXME: something? */ - - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; -#endif - return TRUE; -} - -static void -DRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw) -{ - xp_window_changes wc; - unsigned int flags = 0; - - if (pDRIDrawablePriv->sid == 0) - return; - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 - wc.depth = (pDraw->bitsPerPixel == 32 ? XP_DEPTH_ARGB8888 - : pDraw->bitsPerPixel == 16 ? XP_DEPTH_RGB555 : XP_DEPTH_NIL); - if (wc.depth != XP_DEPTH_NIL) - flags |= XP_DEPTH; -#endif - - if (pDraw->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr) pDraw; - WindowPtr pTopWin = TopLevelParent(pWin); - - wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth); - wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth); - wc.width = pWin->drawable.width + 2 * pWin->borderWidth; - wc.height = pWin->drawable.height + 2 * pWin->borderWidth; - wc.bit_gravity = XP_GRAVITY_NONE; - - wc.shape_nrects = REGION_NUM_RECTS(&pWin->clipList); - wc.shape_rects = REGION_RECTS(&pWin->clipList); - wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth); - wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth); - - flags |= XP_BOUNDS | XP_SHAPE; - - } else if (pDraw->type == DRAWABLE_PIXMAP) { - wc.x = 0; - wc.y = 0; - wc.width = pDraw->width; - wc.height = pDraw->height; - wc.bit_gravity = XP_GRAVITY_NONE; - flags |= XP_BOUNDS; - } - - xp_configure_surface(pDRIDrawablePriv->sid, flags, &wc); -} - -/* Return NULL if an error occurs. */ -static DRIDrawablePrivPtr -CreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin, xp_window_id *widPtr) { - DRIDrawablePrivPtr pDRIDrawablePriv; - xp_window_id wid = 0; - - *widPtr = 0; - - pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - - if (pDRIDrawablePriv == NULL) { - xp_error err; - xp_window_changes wc; - - /* allocate a DRI Window Private record */ - if (!(pDRIDrawablePriv = xalloc(sizeof(*pDRIDrawablePriv)))) { - return NULL; - } - - pDRIDrawablePriv->pDraw = (DrawablePtr)pWin; - pDRIDrawablePriv->pScreen = pScreen; - pDRIDrawablePriv->refCount = 0; - pDRIDrawablePriv->drawableIndex = -1; - pDRIDrawablePriv->notifiers = NULL; - - /* find the physical window */ - wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE)); - - if (wid == 0) { - xfree(pDRIDrawablePriv); - return NULL; - } - - /* allocate the physical surface */ - err = xp_create_surface(wid, &pDRIDrawablePriv->sid); - - if (err != Success) { - xfree(pDRIDrawablePriv); - return NULL; - } - - /* Make it visible */ - wc.stack_mode = XP_MAPPED_ABOVE; - wc.sibling = 0; - err = xp_configure_surface(pDRIDrawablePriv->sid, XP_STACKING, &wc); - - if (err != Success) { - xp_destroy_surface(pDRIDrawablePriv->sid); - xfree(pDRIDrawablePriv); - return NULL; - } - - /* save private off of preallocated index */ - dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, - pDRIDrawablePriv); - } - - *widPtr = wid; - - return pDRIDrawablePriv; -} - -/* Return NULL if an error occurs. */ -static DRIDrawablePrivPtr -CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) { - DRIDrawablePrivPtr pDRIDrawablePriv; - - pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); - - if (pDRIDrawablePriv == NULL) { - xp_error err; - - /* allocate a DRI Window Private record */ - if (!(pDRIDrawablePriv = xcalloc(1, sizeof(*pDRIDrawablePriv)))) { - return NULL; - } - - pDRIDrawablePriv->pDraw = (DrawablePtr)pPix; - pDRIDrawablePriv->pScreen = pScreen; - pDRIDrawablePriv->refCount = 0; - pDRIDrawablePriv->drawableIndex = -1; - pDRIDrawablePriv->notifiers = NULL; - - /* Passing a null window id to Xplugin in 10.3+ asks for - an accelerated offscreen surface. */ - - err = xp_create_surface(0, &pDRIDrawablePriv->sid); - if (err != Success) { - xfree(pDRIDrawablePriv); - return NULL; - } - - /* - * The DRIUpdateSurface will be called to resize the surface - * after this function, if the export is successful. - */ - - /* save private off of preallocated index */ - dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, - pDRIDrawablePriv); - } - - return pDRIDrawablePriv; -} - - -Bool -DRICreateSurface(ScreenPtr pScreen, Drawable id, - DrawablePtr pDrawable, xp_client_id client_id, - xp_surface_id *surface_id, unsigned int ret_key[2], - void (*notify) (void *arg, void *data), void *notify_data) -{ - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - xp_window_id wid = 0; - DRIDrawablePrivPtr pDRIDrawablePriv; - - if (pDrawable->type == DRAWABLE_WINDOW) { - pDRIDrawablePriv = CreateSurfaceForWindow(pScreen, - (WindowPtr)pDrawable, &wid); - - if(NULL == pDRIDrawablePriv) - return FALSE; /*error*/ - } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 - else if (pDrawable->type == DRAWABLE_PIXMAP) { - pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen, - (PixmapPtr)pDrawable); - - if(NULL == pDRIDrawablePriv) - return FALSE; /*error*/ - } -#endif - else { /* for GLX 1.3, a PBuffer */ - /* NOT_DONE */ - return FALSE; - } - - - /* Finish initialization of new surfaces */ - if (pDRIDrawablePriv->refCount == 0) { - unsigned int key[2] = {0}; - xp_error err; - - /* try to give the client access to the surface */ - if (client_id != 0) { - /* - * Xplugin accepts a 0 wid if the surface id is offscreen, such - * as for a pixmap. - */ - err = xp_export_surface(wid, pDRIDrawablePriv->sid, - client_id, key); - if (err != Success) { - xp_destroy_surface(pDRIDrawablePriv->sid); - xfree(pDRIDrawablePriv); - - /* - * Now set the dix privates to NULL that were previously set. - * This prevents reusing an invalid pointer. - */ - if(pDrawable->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr)pDrawable; - - dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); - } else if(pDrawable->type == DRAWABLE_PIXMAP) { - PixmapPtr pPix = (PixmapPtr)pDrawable; - - dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); - } - - return FALSE; - } - } - - pDRIDrawablePriv->key[0] = key[0]; - pDRIDrawablePriv->key[1] = key[1]; - - ++pDRIPriv->nrWindows; - - /* and stash it by surface id */ - if (surface_hash == NULL) - surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL); - x_hash_table_insert(surface_hash, - x_cvt_uint_to_vptr(pDRIDrawablePriv->sid), pDRIDrawablePriv); - - /* track this in case this window is destroyed */ - AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); - - /* Initialize shape */ - DRIUpdateSurface(pDRIDrawablePriv, pDrawable); - } - - pDRIDrawablePriv->refCount++; - - *surface_id = pDRIDrawablePriv->sid; - - if (ret_key != NULL) { - ret_key[0] = pDRIDrawablePriv->key[0]; - ret_key[1] = pDRIDrawablePriv->key[1]; - } - - if (notify != NULL) { - pDRIDrawablePriv->notifiers = x_hook_add(pDRIDrawablePriv->notifiers, - notify, notify_data); - } - - return TRUE; -} - -Bool -DRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable, - void (*notify) (void *, void *), void *notify_data) -{ - DRIDrawablePrivPtr pDRIDrawablePriv; - - if (pDrawable->type == DRAWABLE_WINDOW) { - pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable); - } else if (pDrawable->type == DRAWABLE_PIXMAP) { - pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable); - } else { - return FALSE; - } - - if (pDRIDrawablePriv != NULL) { - if (notify != NULL) { - pDRIDrawablePriv->notifiers = x_hook_remove(pDRIDrawablePriv->notifiers, - notify, notify_data); - } - if (--pDRIDrawablePriv->refCount <= 0) { - /* This calls back to DRIDrawablePrivDelete - which frees the private area */ - FreeResourceByType(id, DRIDrawablePrivResType, FALSE); - } - } - - return TRUE; -} - -Bool -DRIDrawablePrivDelete(pointer pResource, XID id) -{ - DrawablePtr pDrawable = (DrawablePtr)pResource; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen); - DRIDrawablePrivPtr pDRIDrawablePriv = NULL; - WindowPtr pWin = NULL; - PixmapPtr pPix = NULL; - - if (pDrawable->type == DRAWABLE_WINDOW) { - pWin = (WindowPtr)pDrawable; - pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - } else if (pDrawable->type == DRAWABLE_PIXMAP) { - pPix = (PixmapPtr)pDrawable; - pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); - } - - if (pDRIDrawablePriv == NULL) { - return DRIFreePixmapImp(pDrawable); - } - - if (pDRIDrawablePriv->drawableIndex != -1) { - /* release drawable table entry */ - pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; - } - - if (pDRIDrawablePriv->sid != 0) { - xp_destroy_surface(pDRIDrawablePriv->sid); - x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(pDRIDrawablePriv->sid)); - } - - if (pDRIDrawablePriv->notifiers != NULL) - x_hook_free(pDRIDrawablePriv->notifiers); - - xfree(pDRIDrawablePriv); - - if (pDrawable->type == DRAWABLE_WINDOW) { - dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); - } else if (pDrawable->type == DRAWABLE_PIXMAP) { - dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); - } - - --pDRIPriv->nrWindows; - - return TRUE; -} - -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) { - /* FIXME: something? */ - } - - pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; - - (*pScreen->WindowExposures)(pWin, prgn, bsreg); - - pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; - pScreen->WindowExposures = DRIWindowExposures; -} - -void -DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - DRIDrawablePrivPtr pDRIDrawablePriv; - - if (pDRIPriv->nrWindows > 0) { - pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); - if (pDRIDrawablePriv != NULL) { - DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable); - } - } - - /* unwrap */ - pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; - - /* call lower layers */ - (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); - - /* rewrap */ - pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; - pScreen->CopyWindow = DRICopyWindow; -} - -int -DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) -{ - ScreenPtr pScreen = pParent->drawable.pScreen; - DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); - int returnValue; - - /* 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; - } - pDRIPriv = DRI_SCREEN_PRIV(pScreen); - - 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 ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { - DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable); - } - - if (pDRIPriv->wrap.ClipNotify) { - pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; - - (*pScreen->ClipNotify)(pWin, dx, dy); - - pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; - pScreen->ClipNotify = DRIClipNotify; - } -} - -/* This lets us get at the unwrapped functions so that they can correctly - * call the lower level 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); -} - -void -DRIQueryVersion(int *majorVersion, - int *minorVersion, - int *patchVersion) -{ - *majorVersion = APPLE_DRI_MAJOR_VERSION; - *minorVersion = APPLE_DRI_MINOR_VERSION; - *patchVersion = APPLE_DRI_PATCH_VERSION; -} - -void -DRISurfaceNotify(xp_surface_id id, int kind) -{ - DRIDrawablePrivPtr pDRIDrawablePriv = NULL; - DRISurfaceNotifyArg arg; - - arg.id = id; - arg.kind = kind; - - if (surface_hash != NULL) - { - pDRIDrawablePriv = x_hash_table_lookup(surface_hash, - x_cvt_uint_to_vptr(id), NULL); - } - - if (pDRIDrawablePriv == NULL) - return; - - if (kind == AppleDRISurfaceNotifyDestroyed) - { - pDRIDrawablePriv->sid = 0; - x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(id)); - } - - x_hook_run(pDRIDrawablePriv->notifiers, &arg); - - if (kind == AppleDRISurfaceNotifyDestroyed) - { - /* Kill off the handle. */ - - FreeResourceByType(pDRIDrawablePriv->pDraw->id, - DRIDrawablePrivResType, FALSE); - } -} - -Bool DRICreatePixmap(ScreenPtr pScreen, Drawable id, - DrawablePtr pDrawable, char *path, - size_t pathmax) -{ - DRIPixmapBufferPtr shared; - PixmapPtr pPix; - - if(pDrawable->type != DRAWABLE_PIXMAP) - return FALSE; - - pPix = (PixmapPtr)pDrawable; - - shared = xalloc(sizeof(*shared)); - if(NULL == shared) { - FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__); - } - - shared->pDrawable = pDrawable; - shared->refCount = 1; - - if(pDrawable->bitsPerPixel >= 24) { - shared->bytesPerPixel = 4; - } else if(pDrawable->bitsPerPixel <= 16) { - shared->bytesPerPixel = 2; - } - - shared->width = pDrawable->width; - shared->height = pDrawable->height; - - if(-1 == snprintf(shared->shmPath, sizeof(shared->shmPath), - "%d_0x%lx", getpid(), - (unsigned long)id)) { - FatalError("buffer overflow in %s\n", __func__); - } - - shared->fd = shm_open(shared->shmPath, - O_RDWR | O_EXCL | O_CREAT, - S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); - - if(-1 == shared->fd) { - xfree(shared); - return FALSE; - } - - shared->length = shared->width * shared->height * shared->bytesPerPixel; - - if(-1 == ftruncate(shared->fd, shared->length)) { - ErrorF("failed to ftruncate (extend) file."); - shm_unlink(shared->shmPath); - close(shared->fd); - xfree(shared); - return FALSE; - } - - shared->buffer = mmap(NULL, shared->length, - PROT_READ | PROT_WRITE, - MAP_FILE | MAP_SHARED, shared->fd, 0); - - if(MAP_FAILED == shared->buffer) { - ErrorF("failed to mmap shared memory."); - shm_unlink(shared->shmPath); - close(shared->fd); - xfree(shared); - return FALSE; - } - - strncpy(path, shared->shmPath, pathmax); - path[pathmax - 1] = '\0'; - - dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, shared); - - AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); - - return TRUE; -} - - -Bool DRIGetPixmapData(DrawablePtr pDrawable, int *width, int *height, - int *pitch, int *bpp, void **ptr) { - PixmapPtr pPix; - DRIPixmapBufferPtr shared; - - if(pDrawable->type != DRAWABLE_PIXMAP) - return FALSE; - - pPix = (PixmapPtr)pDrawable; - - shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); - - if(NULL == shared) - return FALSE; - - assert(pDrawable->width == shared->width); - assert(pDrawable->height == shared->height); - - *width = shared->width; - *height = shared->height; - *bpp = shared->bytesPerPixel; - *pitch = shared->width * shared->bytesPerPixel; - *ptr = shared->buffer; - - return TRUE; -} - -static Bool -DRIFreePixmapImp(DrawablePtr pDrawable) { - DRIPixmapBufferPtr shared; - PixmapPtr pPix; - - if(pDrawable->type != DRAWABLE_PIXMAP) - return FALSE; - - pPix = (PixmapPtr)pDrawable; - - shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); - - if(NULL == shared) - return FALSE; - - close(shared->fd); - munmap(shared->buffer, shared->length); - shm_unlink(shared->shmPath); - xfree(shared); - - dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL); - - return TRUE; -} - -void -DRIDestroyPixmap(DrawablePtr pDrawable) { - if(DRIFreePixmapImp(pDrawable)) - FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE); - -} +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright 2000 VA Linux Systems, Inc. +Copyright (c) 2002, 2009 Apple Computer, 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 <jens@valinux.com> + * Rickard E. (Rik) Faith <faith@valinux.com> + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifdef XFree86LOADER +#include "xf86.h" +#include "xf86_ansic.h" +#else +#include <sys/time.h> +#include <unistd.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.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 _APPLEDRI_SERVER_ +#include "appledristr.h" +#include "swaprep.h" +#include "dri.h" +#include "dristruct.h" +#include "mi.h" +#include "mipointer.h" +#include "rootless.h" +#include "x-hash.h" +#include "x-hook.h" +#include "driWrap.h" + +#include <AvailabilityMacros.h> + +static int DRIScreenPrivKeyIndex; +static DevPrivateKey DRIScreenPrivKey = &DRIScreenPrivKeyIndex; +static int DRIWindowPrivKeyIndex; +static DevPrivateKey DRIWindowPrivKey = &DRIWindowPrivKeyIndex; +static int DRIPixmapPrivKeyIndex; +static DevPrivateKey DRIPixmapPrivKey = &DRIPixmapPrivKeyIndex; +static int DRIPixmapBufferPrivKeyIndex; +static DevPrivateKey DRIPixmapBufferPrivKey = &DRIPixmapBufferPrivKeyIndex; + +static RESTYPE DRIDrawablePrivResType; + +static x_hash_table *surface_hash; /* maps surface ids -> drawablePrivs */ + +static Bool DRIFreePixmapImp(DrawablePtr pDrawable); + +/* FIXME: don't hardcode this? */ +#define CG_INFO_FILE "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Resources/Info-macos.plist" + +/* Corresponds to SU Jaguar Green */ +#define CG_REQUIRED_MAJOR 1 +#define CG_REQUIRED_MINOR 157 +#define CG_REQUIRED_MICRO 11 + +typedef struct { + DrawablePtr pDrawable; + int refCount; + int bytesPerPixel; + int width; + int height; + char shmPath[PATH_MAX]; + int fd; /* From shm_open (for now) */ + size_t length; /* length of buffer */ + void *buffer; +} DRIPixmapBuffer, *DRIPixmapBufferPtr; + +/* Returns version as major.minor.micro in 10.10.10 fixed form */ +static unsigned int +get_cg_version (void) +{ + static unsigned int version; + + FILE *fh; + char *ptr; + + if (version != 0) + return version; + + /* I tried CFBundleGetVersion, but it returns zero, so.. */ + + fh = fopen (CG_INFO_FILE, "r"); + if (fh != NULL) + { + char buf[256]; + + while (fgets (buf, sizeof (buf), fh) != NULL) + { + unsigned char c; + + if (!strstr (buf, "<key>CFBundleShortVersionString</key>") + || fgets (buf, sizeof (buf), fh) == NULL) + { + continue; + } + + ptr = strstr (buf, "<string>"); + if (ptr == NULL) + continue; + + ptr += strlen ("<string>"); + + /* Now PTR points to "MAJOR.MINOR.MICRO". */ + + version = 0; + + again: + switch ((c = *ptr++)) + { + case '.': + version = version * 1024; + goto again; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + version = ((version & ~0x3ff) + + (version & 0x3ff) * 10 + (c - '0')); + goto again; + } + break; + } + + fclose (fh); + } + + return version; +} + +static Bool +test_cg_version (unsigned int major, unsigned int minor, unsigned int micro) +{ + unsigned int cg_ver = get_cg_version (); + + unsigned int cg_major = (cg_ver >> 20) & 0x3ff; + unsigned int cg_minor = (cg_ver >> 10) & 0x3ff; + unsigned int cg_micro = cg_ver & 0x3ff; + + if (cg_major > major) + return TRUE; + else if (cg_major < major) + return FALSE; + + /* cg_major == major */ + + if (cg_minor > minor) + return TRUE; + else if (cg_minor < minor) + return FALSE; + + /* cg_minor == minor */ + + if (cg_micro < micro) + return FALSE; + + return TRUE; +} + +Bool +DRIScreenInit(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv; + int i; + + pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec)); + if (!pDRIPriv) { + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + return FALSE; + } + + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv); + pDRIPriv->directRenderingSupport = TRUE; + pDRIPriv->nrWindows = 0; + + /* Need recent cg for window access update */ + if (!test_cg_version (CG_REQUIRED_MAJOR, + CG_REQUIRED_MINOR, + CG_REQUIRED_MICRO)) + { + ErrorF ("[DRI] disabled direct rendering; requires CoreGraphics %d.%d.%d\n", + CG_REQUIRED_MAJOR, CG_REQUIRED_MINOR, CG_REQUIRED_MICRO); + + pDRIPriv->directRenderingSupport = FALSE; + + /* Note we don't nuke the dri private, since we need it for + managing indirect surfaces. */ + } + + /* Initialize drawable tables */ + for (i = 0; i < DRI_MAX_DRAWABLES; i++) { + pDRIPriv->DRIDrawables[i] = NULL; + } + + return TRUE; +} + +Bool +DRIFinishScreenInit(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + /* Wrap DRI support */ + pDRIPriv->wrap.ValidateTree = pScreen->ValidateTree; + pScreen->ValidateTree = DRIValidateTree; + + pDRIPriv->wrap.PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = DRIPostValidateTree; + + pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = DRIWindowExposures; + + pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = DRICopyWindow; + + pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = DRIClipNotify; + + // ErrorF("[DRI] screen %d installation complete\n", pScreen->myNum); + + return DRIWrapInit(pScreen); +} + +void +DRICloseScreen(ScreenPtr pScreen) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (pDRIPriv && pDRIPriv->directRenderingSupport) { + free(pDRIPriv); + dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL); + } +} + +Bool +DRIExtensionInit(void) +{ + DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete, + "DRIDrawable"); + + return (DRIDrawablePrivResType != 0); +} + +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 +DRIAuthConnection(ScreenPtr pScreen, unsigned int magic) +{ +#if 0 + /* FIXME: something? */ + + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + if (drmAuthMagic(pDRIPriv->drmFD, magic)) return FALSE; +#endif + return TRUE; +} + +static void +DRIUpdateSurface(DRIDrawablePrivPtr pDRIDrawablePriv, DrawablePtr pDraw) +{ + xp_window_changes wc; + unsigned int flags = 0; + + if (pDRIDrawablePriv->sid == 0) + return; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + wc.depth = (pDraw->bitsPerPixel == 32 ? XP_DEPTH_ARGB8888 + : pDraw->bitsPerPixel == 16 ? XP_DEPTH_RGB555 : XP_DEPTH_NIL); + if (wc.depth != XP_DEPTH_NIL) + flags |= XP_DEPTH; +#endif + + if (pDraw->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr) pDraw; + WindowPtr pTopWin = TopLevelParent(pWin); + + wc.x = pWin->drawable.x - (pTopWin->drawable.x - pTopWin->borderWidth); + wc.y = pWin->drawable.y - (pTopWin->drawable.y - pTopWin->borderWidth); + wc.width = pWin->drawable.width + 2 * pWin->borderWidth; + wc.height = pWin->drawable.height + 2 * pWin->borderWidth; + wc.bit_gravity = XP_GRAVITY_NONE; + + wc.shape_nrects = REGION_NUM_RECTS(&pWin->clipList); + wc.shape_rects = REGION_RECTS(&pWin->clipList); + wc.shape_tx = - (pTopWin->drawable.x - pTopWin->borderWidth); + wc.shape_ty = - (pTopWin->drawable.y - pTopWin->borderWidth); + + flags |= XP_BOUNDS | XP_SHAPE; + + } else if (pDraw->type == DRAWABLE_PIXMAP) { + wc.x = 0; + wc.y = 0; + wc.width = pDraw->width; + wc.height = pDraw->height; + wc.bit_gravity = XP_GRAVITY_NONE; + flags |= XP_BOUNDS; + } + + xp_configure_surface(pDRIDrawablePriv->sid, flags, &wc); +} + +/* Return NULL if an error occurs. */ +static DRIDrawablePrivPtr +CreateSurfaceForWindow(ScreenPtr pScreen, WindowPtr pWin, xp_window_id *widPtr) { + DRIDrawablePrivPtr pDRIDrawablePriv; + xp_window_id wid = 0; + + *widPtr = 0; + + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + + if (pDRIDrawablePriv == NULL) { + xp_error err; + xp_window_changes wc; + + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = malloc(sizeof(*pDRIDrawablePriv)))) { + return NULL; + } + + pDRIDrawablePriv->pDraw = (DrawablePtr)pWin; + pDRIDrawablePriv->pScreen = pScreen; + pDRIDrawablePriv->refCount = 0; + pDRIDrawablePriv->drawableIndex = -1; + pDRIDrawablePriv->notifiers = NULL; + + /* find the physical window */ + wid = x_cvt_vptr_to_uint(RootlessFrameForWindow(pWin, TRUE)); + + if (wid == 0) { + free(pDRIDrawablePriv); + return NULL; + } + + /* allocate the physical surface */ + err = xp_create_surface(wid, &pDRIDrawablePriv->sid); + + if (err != Success) { + free(pDRIDrawablePriv); + return NULL; + } + + /* Make it visible */ + wc.stack_mode = XP_MAPPED_ABOVE; + wc.sibling = 0; + err = xp_configure_surface(pDRIDrawablePriv->sid, XP_STACKING, &wc); + + if (err != Success) { + xp_destroy_surface(pDRIDrawablePriv->sid); + free(pDRIDrawablePriv); + return NULL; + } + + /* save private off of preallocated index */ + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, + pDRIDrawablePriv); + } + + *widPtr = wid; + + return pDRIDrawablePriv; +} + +/* Return NULL if an error occurs. */ +static DRIDrawablePrivPtr +CreateSurfaceForPixmap(ScreenPtr pScreen, PixmapPtr pPix) { + DRIDrawablePrivPtr pDRIDrawablePriv; + + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); + + if (pDRIDrawablePriv == NULL) { + xp_error err; + + /* allocate a DRI Window Private record */ + if (!(pDRIDrawablePriv = calloc(1, sizeof(*pDRIDrawablePriv)))) { + return NULL; + } + + pDRIDrawablePriv->pDraw = (DrawablePtr)pPix; + pDRIDrawablePriv->pScreen = pScreen; + pDRIDrawablePriv->refCount = 0; + pDRIDrawablePriv->drawableIndex = -1; + pDRIDrawablePriv->notifiers = NULL; + + /* Passing a null window id to Xplugin in 10.3+ asks for + an accelerated offscreen surface. */ + + err = xp_create_surface(0, &pDRIDrawablePriv->sid); + if (err != Success) { + free(pDRIDrawablePriv); + return NULL; + } + + /* + * The DRIUpdateSurface will be called to resize the surface + * after this function, if the export is successful. + */ + + /* save private off of preallocated index */ + dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, + pDRIDrawablePriv); + } + + return pDRIDrawablePriv; +} + + +Bool +DRICreateSurface(ScreenPtr pScreen, Drawable id, + DrawablePtr pDrawable, xp_client_id client_id, + xp_surface_id *surface_id, unsigned int ret_key[2], + void (*notify) (void *arg, void *data), void *notify_data) +{ + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + xp_window_id wid = 0; + DRIDrawablePrivPtr pDRIDrawablePriv; + + if (pDrawable->type == DRAWABLE_WINDOW) { + pDRIDrawablePriv = CreateSurfaceForWindow(pScreen, + (WindowPtr)pDrawable, &wid); + + if(NULL == pDRIDrawablePriv) + return FALSE; /*error*/ + } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + else if (pDrawable->type == DRAWABLE_PIXMAP) { + pDRIDrawablePriv = CreateSurfaceForPixmap(pScreen, + (PixmapPtr)pDrawable); + + if(NULL == pDRIDrawablePriv) + return FALSE; /*error*/ + } +#endif + else { /* for GLX 1.3, a PBuffer */ + /* NOT_DONE */ + return FALSE; + } + + + /* Finish initialization of new surfaces */ + if (pDRIDrawablePriv->refCount == 0) { + unsigned int key[2] = {0}; + xp_error err; + + /* try to give the client access to the surface */ + if (client_id != 0) { + /* + * Xplugin accepts a 0 wid if the surface id is offscreen, such + * as for a pixmap. + */ + err = xp_export_surface(wid, pDRIDrawablePriv->sid, + client_id, key); + if (err != Success) { + xp_destroy_surface(pDRIDrawablePriv->sid); + free(pDRIDrawablePriv); + + /* + * Now set the dix privates to NULL that were previously set. + * This prevents reusing an invalid pointer. + */ + if(pDrawable->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDrawable; + + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); + } else if(pDrawable->type == DRAWABLE_PIXMAP) { + PixmapPtr pPix = (PixmapPtr)pDrawable; + + dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); + } + + return FALSE; + } + } + + pDRIDrawablePriv->key[0] = key[0]; + pDRIDrawablePriv->key[1] = key[1]; + + ++pDRIPriv->nrWindows; + + /* and stash it by surface id */ + if (surface_hash == NULL) + surface_hash = x_hash_table_new(NULL, NULL, NULL, NULL); + x_hash_table_insert(surface_hash, + x_cvt_uint_to_vptr(pDRIDrawablePriv->sid), pDRIDrawablePriv); + + /* track this in case this window is destroyed */ + AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); + + /* Initialize shape */ + DRIUpdateSurface(pDRIDrawablePriv, pDrawable); + } + + pDRIDrawablePriv->refCount++; + + *surface_id = pDRIDrawablePriv->sid; + + if (ret_key != NULL) { + ret_key[0] = pDRIDrawablePriv->key[0]; + ret_key[1] = pDRIDrawablePriv->key[1]; + } + + if (notify != NULL) { + pDRIDrawablePriv->notifiers = x_hook_add(pDRIDrawablePriv->notifiers, + notify, notify_data); + } + + return TRUE; +} + +Bool +DRIDestroySurface(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable, + void (*notify) (void *, void *), void *notify_data) +{ + DRIDrawablePrivPtr pDRIDrawablePriv; + + if (pDrawable->type == DRAWABLE_WINDOW) { + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW((WindowPtr)pDrawable); + } else if (pDrawable->type == DRAWABLE_PIXMAP) { + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP((PixmapPtr)pDrawable); + } else { + return FALSE; + } + + if (pDRIDrawablePriv != NULL) { + if (notify != NULL) { + pDRIDrawablePriv->notifiers = x_hook_remove(pDRIDrawablePriv->notifiers, + notify, notify_data); + } + if (--pDRIDrawablePriv->refCount <= 0) { + /* This calls back to DRIDrawablePrivDelete + which frees the private area */ + FreeResourceByType(id, DRIDrawablePrivResType, FALSE); + } + } + + return TRUE; +} + +Bool +DRIDrawablePrivDelete(pointer pResource, XID id) +{ + DrawablePtr pDrawable = (DrawablePtr)pResource; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv = NULL; + WindowPtr pWin = NULL; + PixmapPtr pPix = NULL; + + if (pDrawable->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr)pDrawable; + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + } else if (pDrawable->type == DRAWABLE_PIXMAP) { + pPix = (PixmapPtr)pDrawable; + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_PIXMAP(pPix); + } + + if (pDRIDrawablePriv == NULL) { + return DRIFreePixmapImp(pDrawable); + } + + if (pDRIDrawablePriv->drawableIndex != -1) { + /* release drawable table entry */ + pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL; + } + + if (pDRIDrawablePriv->sid != 0) { + xp_destroy_surface(pDRIDrawablePriv->sid); + x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(pDRIDrawablePriv->sid)); + } + + if (pDRIDrawablePriv->notifiers != NULL) + x_hook_free(pDRIDrawablePriv->notifiers); + + free(pDRIDrawablePriv); + + if (pDrawable->type == DRAWABLE_WINDOW) { + dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL); + } else if (pDrawable->type == DRAWABLE_PIXMAP) { + dixSetPrivate(&pPix->devPrivates, DRIPixmapPrivKey, NULL); + } + + --pDRIPriv->nrWindows; + + return TRUE; +} + +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) { + /* FIXME: something? */ + } + + pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures; + + (*pScreen->WindowExposures)(pWin, prgn, bsreg); + + pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures; + pScreen->WindowExposures = DRIWindowExposures; +} + +void +DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + DRIDrawablePrivPtr pDRIDrawablePriv; + + if (pDRIPriv->nrWindows > 0) { + pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin); + if (pDRIDrawablePriv != NULL) { + DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable); + } + } + + /* unwrap */ + pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow; + + /* call lower layers */ + (*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc); + + /* rewrap */ + pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = DRICopyWindow; +} + +int +DRIValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen); + int returnValue; + + /* 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; + } + pDRIPriv = DRI_SCREEN_PRIV(pScreen); + + 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 ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) { + DRIUpdateSurface(pDRIDrawablePriv, &pWin->drawable); + } + + if (pDRIPriv->wrap.ClipNotify) { + pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify; + + (*pScreen->ClipNotify)(pWin, dx, dy); + + pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify; + pScreen->ClipNotify = DRIClipNotify; + } +} + +/* This lets us get at the unwrapped functions so that they can correctly + * call the lower level 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); +} + +void +DRIQueryVersion(int *majorVersion, + int *minorVersion, + int *patchVersion) +{ + *majorVersion = APPLE_DRI_MAJOR_VERSION; + *minorVersion = APPLE_DRI_MINOR_VERSION; + *patchVersion = APPLE_DRI_PATCH_VERSION; +} + +void +DRISurfaceNotify(xp_surface_id id, int kind) +{ + DRIDrawablePrivPtr pDRIDrawablePriv = NULL; + DRISurfaceNotifyArg arg; + + arg.id = id; + arg.kind = kind; + + if (surface_hash != NULL) + { + pDRIDrawablePriv = x_hash_table_lookup(surface_hash, + x_cvt_uint_to_vptr(id), NULL); + } + + if (pDRIDrawablePriv == NULL) + return; + + if (kind == AppleDRISurfaceNotifyDestroyed) + { + pDRIDrawablePriv->sid = 0; + x_hash_table_remove(surface_hash, x_cvt_uint_to_vptr(id)); + } + + x_hook_run(pDRIDrawablePriv->notifiers, &arg); + + if (kind == AppleDRISurfaceNotifyDestroyed) + { + /* Kill off the handle. */ + + FreeResourceByType(pDRIDrawablePriv->pDraw->id, + DRIDrawablePrivResType, FALSE); + } +} + +Bool DRICreatePixmap(ScreenPtr pScreen, Drawable id, + DrawablePtr pDrawable, char *path, + size_t pathmax) +{ + DRIPixmapBufferPtr shared; + PixmapPtr pPix; + + if(pDrawable->type != DRAWABLE_PIXMAP) + return FALSE; + + pPix = (PixmapPtr)pDrawable; + + shared = malloc(sizeof(*shared)); + if(NULL == shared) { + FatalError("failed to allocate DRIPixmapBuffer in %s\n", __func__); + } + + shared->pDrawable = pDrawable; + shared->refCount = 1; + + if(pDrawable->bitsPerPixel >= 24) { + shared->bytesPerPixel = 4; + } else if(pDrawable->bitsPerPixel <= 16) { + shared->bytesPerPixel = 2; + } + + shared->width = pDrawable->width; + shared->height = pDrawable->height; + + if(-1 == snprintf(shared->shmPath, sizeof(shared->shmPath), + "%d_0x%lx", getpid(), + (unsigned long)id)) { + FatalError("buffer overflow in %s\n", __func__); + } + + shared->fd = shm_open(shared->shmPath, + O_RDWR | O_EXCL | O_CREAT, + S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH); + + if(-1 == shared->fd) { + free(shared); + return FALSE; + } + + shared->length = shared->width * shared->height * shared->bytesPerPixel; + + if(-1 == ftruncate(shared->fd, shared->length)) { + ErrorF("failed to ftruncate (extend) file."); + shm_unlink(shared->shmPath); + close(shared->fd); + free(shared); + return FALSE; + } + + shared->buffer = mmap(NULL, shared->length, + PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, shared->fd, 0); + + if(MAP_FAILED == shared->buffer) { + ErrorF("failed to mmap shared memory."); + shm_unlink(shared->shmPath); + close(shared->fd); + free(shared); + return FALSE; + } + + strncpy(path, shared->shmPath, pathmax); + path[pathmax - 1] = '\0'; + + dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, shared); + + AddResource(id, DRIDrawablePrivResType, (pointer)pDrawable); + + return TRUE; +} + + +Bool DRIGetPixmapData(DrawablePtr pDrawable, int *width, int *height, + int *pitch, int *bpp, void **ptr) { + PixmapPtr pPix; + DRIPixmapBufferPtr shared; + + if(pDrawable->type != DRAWABLE_PIXMAP) + return FALSE; + + pPix = (PixmapPtr)pDrawable; + + shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); + + if(NULL == shared) + return FALSE; + + assert(pDrawable->width == shared->width); + assert(pDrawable->height == shared->height); + + *width = shared->width; + *height = shared->height; + *bpp = shared->bytesPerPixel; + *pitch = shared->width * shared->bytesPerPixel; + *ptr = shared->buffer; + + return TRUE; +} + +static Bool +DRIFreePixmapImp(DrawablePtr pDrawable) { + DRIPixmapBufferPtr shared; + PixmapPtr pPix; + + if(pDrawable->type != DRAWABLE_PIXMAP) + return FALSE; + + pPix = (PixmapPtr)pDrawable; + + shared = dixLookupPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey); + + if(NULL == shared) + return FALSE; + + close(shared->fd); + munmap(shared->buffer, shared->length); + shm_unlink(shared->shmPath); + free(shared); + + dixSetPrivate(&pPix->devPrivates, DRIPixmapBufferPrivKey, (pointer)NULL); + + return TRUE; +} + +void +DRIDestroyPixmap(DrawablePtr pDrawable) { + if(DRIFreePixmapImp(pDrawable)) + FreeResourceByType(pDrawable->id, DRIDrawablePrivResType, FALSE); + +} diff --git a/xorg-server/hw/xquartz/xpr/driWrap.c b/xorg-server/hw/xquartz/xpr/driWrap.c index 8c57fd4bd..2e23cbbf5 100644 --- a/xorg-server/hw/xquartz/xpr/driWrap.c +++ b/xorg-server/hw/xquartz/xpr/driWrap.c @@ -1,547 +1,547 @@ -/* -Copyright (c) 2009 Apple Computer, 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. -*/ -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <stddef.h> -#include "mi.h" -#include "scrnintstr.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "windowstr.h" -#include "dixfontstr.h" -#include "mivalidate.h" -#include "driWrap.h" -#include "dri.h" - -#include <OpenGL/OpenGL.h> - -typedef struct { - GCOps *originalOps; - GCOps *driOps; -} DRIGCRec; - -typedef struct { - GCOps *originalOps; - CreateGCProcPtr CreateGC; -} DRIWrapScreenRec; - -typedef struct { - Bool didSave; - int devKind; - DevUnion devPrivate; -} DRISavedDrawableState; - -static int driGCKeyIndex; -static DevPrivateKey driGCKey = &driGCKeyIndex; - -static int driWrapScreenKeyIndex; -static DevPrivateKey driWrapScreenKey = &driWrapScreenKeyIndex; - -static GCOps driGCOps; - -#define wrap(priv, real, member, func) { \ - priv->member = real->member; \ - real->member = func; \ - } - -#define unwrap(priv, real, member) { \ - real->member = priv->member; \ - } - -static DRIGCRec * -DRIGetGCPriv(GCPtr pGC) { - return dixLookupPrivate(&pGC->devPrivates, driGCKey); -} - -static void -DRIUnwrapGC(GCPtr pGC) { - DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); - - pGC->ops = pGCPriv->originalOps; -} - -static void -DRIWrapGC(GCPtr pGC) { - DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); - - pGC->ops = pGCPriv->driOps; -} - -static void -DRISurfaceSetDrawable(DrawablePtr pDraw, - DRISavedDrawableState *saved) { - saved->didSave = FALSE; - - if(pDraw->type == DRAWABLE_PIXMAP) { - int pitch, width, height, bpp; - void *buffer; - - if(DRIGetPixmapData(pDraw, &width, &height, &pitch, &bpp, &buffer)) { - PixmapPtr pPix = (PixmapPtr)pDraw; - - saved->devKind = pPix->devKind; - saved->devPrivate.ptr = pPix->devPrivate.ptr; - saved->didSave = TRUE; - - pPix->devKind = pitch; - pPix->devPrivate.ptr = buffer; - } - } -} - -static void -DRISurfaceRestoreDrawable(DrawablePtr pDraw, - DRISavedDrawableState *saved) { - PixmapPtr pPix = (PixmapPtr)pDraw; - - if(!saved->didSave) - return; - - pPix->devKind = saved->devKind; - pPix->devPrivate.ptr = saved->devPrivate.ptr; -} - -static void -DRIFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, - DDXPointPtr pptInit, int *pwidthInit, - int sorted) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRISetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, - DDXPointPtr pptInit, int *pwidthInit, - int nspans, int sorted) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIPutImage(DrawablePtr dst, GCPtr pGC, - int depth, int x, int y, int w, int h, - int leftPad, int format, char *pBits) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static RegionPtr -DRICopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, - int srcx, int srcy, int w, int h, - int dstx, int dsty) { - RegionPtr pReg; - DRISavedDrawableState pSrcSaved, dstSaved; - - DRISurfaceSetDrawable(pSrc, &pSrcSaved); - DRISurfaceSetDrawable(dst, &dstSaved); - - DRIUnwrapGC(pGC); - - pReg = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); - DRISurfaceRestoreDrawable(dst, &dstSaved); - - return pReg; -} - -static RegionPtr -DRICopyPlane(DrawablePtr pSrc, DrawablePtr dst, - GCPtr pGC, int srcx, int srcy, - int w, int h, int dstx, int dsty, - unsigned long plane) { - RegionPtr pReg; - DRISavedDrawableState pSrcSaved, dstSaved; - - DRISurfaceSetDrawable(pSrc, &pSrcSaved); - DRISurfaceSetDrawable(dst, &dstSaved); - - - DRIUnwrapGC(pGC); - - pReg = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty, - plane); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); - DRISurfaceRestoreDrawable(dst, &dstSaved); - - return pReg; -} - -static void -DRIPolyPoint(DrawablePtr dst, GCPtr pGC, - int mode, int npt, DDXPointPtr pptInit) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIPolylines(DrawablePtr dst, GCPtr pGC, - int mode, int npt, DDXPointPtr pptInit) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIPolySegment(DrawablePtr dst, GCPtr pGC, - int nseg, xSegment *pSeg) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->PolySegment(dst, pGC, nseg, pSeg); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIPolyRectangle(DrawablePtr dst, GCPtr pGC, - int nRects, xRectangle *pRects) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} -static void -DRIPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->PolyArc(dst, pGC, narcs, parcs); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIFillPolygon(DrawablePtr dst, GCPtr pGC, - int shape, int mode, int count, - DDXPointPtr pptInit) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIPolyFillRect(DrawablePtr dst, GCPtr pGC, - int nRectsInit, xRectangle *pRectsInit) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIPolyFillArc(DrawablePtr dst, GCPtr pGC, - int narcsInit, xArc *parcsInit) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static int -DRIPolyText8(DrawablePtr dst, GCPtr pGC, - int x, int y, int count, char *chars) { - int ret; - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - ret = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); - - return ret; -} - -static int -DRIPolyText16(DrawablePtr dst, GCPtr pGC, - int x, int y, int count, unsigned short *chars) { - int ret; - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - ret = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); - - return ret; -} - -static void -DRIImageText8(DrawablePtr dst, GCPtr pGC, - int x, int y, int count, char *chars) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->ImageText8(dst, pGC, x, y, count, chars); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIImageText16(DrawablePtr dst, GCPtr pGC, - int x, int y, int count, unsigned short *chars) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->ImageText16(dst, pGC, x, y, count, chars); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIImageGlyphBlt(DrawablePtr dst, GCPtr pGC, - int x, int y, unsigned int nglyphInit, - CharInfoPtr *ppciInit, pointer unused) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void DRIPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, - int x, int y, unsigned int nglyph, - CharInfoPtr *ppci, pointer pglyphBase) { - DRISavedDrawableState saved; - - DRISurfaceSetDrawable(dst, &saved); - - DRIUnwrapGC(pGC); - - pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(dst, &saved); -} - -static void -DRIPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, - int dx, int dy, int xOrg, int yOrg) { - DRISavedDrawableState bitMapSaved, dstSaved; - - DRISurfaceSetDrawable(&pBitMap->drawable, &bitMapSaved); - DRISurfaceSetDrawable(dst, &dstSaved); - - DRIUnwrapGC(pGC); - - pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); - - DRIWrapGC(pGC); - - DRISurfaceRestoreDrawable(&pBitMap->drawable, &bitMapSaved); - DRISurfaceRestoreDrawable(dst, &dstSaved); -} - - -static GCOps driGCOps = { - DRIFillSpans, - DRISetSpans, - DRIPutImage, - DRICopyArea, - DRICopyPlane, - DRIPolyPoint, - DRIPolylines, - DRIPolySegment, - DRIPolyRectangle, - DRIPolyArc, - DRIFillPolygon, - DRIPolyFillRect, - DRIPolyFillArc, - DRIPolyText8, - DRIPolyText16, - DRIImageText8, - DRIImageText16, - DRIImageGlyphBlt, - DRIPolyGlyphBlt, - DRIPushPixels -}; - - -static Bool -DRICreateGC(GCPtr pGC) { - ScreenPtr pScreen = pGC->pScreen; - DRIWrapScreenRec *pScreenPriv; - DRIGCRec *pGCPriv; - Bool ret; - - pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, driWrapScreenKey); - - pGCPriv = DRIGetGCPriv(pGC); - - unwrap(pScreenPriv, pScreen, CreateGC); - ret = pScreen->CreateGC(pGC); - - if(ret) { - pGCPriv->originalOps = pGC->ops; - pGC->ops = &driGCOps; - pGCPriv->driOps = &driGCOps; - } - - wrap(pScreenPriv, pScreen, CreateGC, DRICreateGC); - - return ret; -} - - -/* Return false if an error occurred. */ -Bool -DRIWrapInit(ScreenPtr pScreen) { - DRIWrapScreenRec *pScreenPriv; - - if(!dixRequestPrivate(driGCKey, sizeof(DRIGCRec))) - return FALSE; - - if(!dixRequestPrivate(driWrapScreenKey, sizeof(DRIWrapScreenRec))) - return FALSE; - - pScreenPriv = xalloc(sizeof(*pScreenPriv)); - - if(NULL == pScreenPriv) - return FALSE; - - pScreenPriv->CreateGC = pScreen->CreateGC; - pScreen->CreateGC = DRICreateGC; - - dixSetPrivate(&pScreen->devPrivates, driWrapScreenKey, pScreenPriv); - - return TRUE; -} +/* +Copyright (c) 2009 Apple Computer, 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. +*/ +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stddef.h> +#include "mi.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "dixfontstr.h" +#include "mivalidate.h" +#include "driWrap.h" +#include "dri.h" + +#include <OpenGL/OpenGL.h> + +typedef struct { + GCOps *originalOps; + GCOps *driOps; +} DRIGCRec; + +typedef struct { + GCOps *originalOps; + CreateGCProcPtr CreateGC; +} DRIWrapScreenRec; + +typedef struct { + Bool didSave; + int devKind; + DevUnion devPrivate; +} DRISavedDrawableState; + +static int driGCKeyIndex; +static DevPrivateKey driGCKey = &driGCKeyIndex; + +static int driWrapScreenKeyIndex; +static DevPrivateKey driWrapScreenKey = &driWrapScreenKeyIndex; + +static GCOps driGCOps; + +#define wrap(priv, real, member, func) { \ + priv->member = real->member; \ + real->member = func; \ + } + +#define unwrap(priv, real, member) { \ + real->member = priv->member; \ + } + +static DRIGCRec * +DRIGetGCPriv(GCPtr pGC) { + return dixLookupPrivate(&pGC->devPrivates, driGCKey); +} + +static void +DRIUnwrapGC(GCPtr pGC) { + DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); + + pGC->ops = pGCPriv->originalOps; +} + +static void +DRIWrapGC(GCPtr pGC) { + DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); + + pGC->ops = pGCPriv->driOps; +} + +static void +DRISurfaceSetDrawable(DrawablePtr pDraw, + DRISavedDrawableState *saved) { + saved->didSave = FALSE; + + if(pDraw->type == DRAWABLE_PIXMAP) { + int pitch, width, height, bpp; + void *buffer; + + if(DRIGetPixmapData(pDraw, &width, &height, &pitch, &bpp, &buffer)) { + PixmapPtr pPix = (PixmapPtr)pDraw; + + saved->devKind = pPix->devKind; + saved->devPrivate.ptr = pPix->devPrivate.ptr; + saved->didSave = TRUE; + + pPix->devKind = pitch; + pPix->devPrivate.ptr = buffer; + } + } +} + +static void +DRISurfaceRestoreDrawable(DrawablePtr pDraw, + DRISavedDrawableState *saved) { + PixmapPtr pPix = (PixmapPtr)pDraw; + + if(!saved->didSave) + return; + + pPix->devKind = saved->devKind; + pPix->devPrivate.ptr = saved->devPrivate.ptr; +} + +static void +DRIFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, + int sorted) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRISetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, + DDXPointPtr pptInit, int *pwidthInit, + int nspans, int sorted) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIPutImage(DrawablePtr dst, GCPtr pGC, + int depth, int x, int y, int w, int h, + int leftPad, int format, char *pBits) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static RegionPtr +DRICopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty) { + RegionPtr pReg; + DRISavedDrawableState pSrcSaved, dstSaved; + + DRISurfaceSetDrawable(pSrc, &pSrcSaved); + DRISurfaceSetDrawable(dst, &dstSaved); + + DRIUnwrapGC(pGC); + + pReg = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); + DRISurfaceRestoreDrawable(dst, &dstSaved); + + return pReg; +} + +static RegionPtr +DRICopyPlane(DrawablePtr pSrc, DrawablePtr dst, + GCPtr pGC, int srcx, int srcy, + int w, int h, int dstx, int dsty, + unsigned long plane) { + RegionPtr pReg; + DRISavedDrawableState pSrcSaved, dstSaved; + + DRISurfaceSetDrawable(pSrc, &pSrcSaved); + DRISurfaceSetDrawable(dst, &dstSaved); + + + DRIUnwrapGC(pGC); + + pReg = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty, + plane); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); + DRISurfaceRestoreDrawable(dst, &dstSaved); + + return pReg; +} + +static void +DRIPolyPoint(DrawablePtr dst, GCPtr pGC, + int mode, int npt, DDXPointPtr pptInit) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIPolylines(DrawablePtr dst, GCPtr pGC, + int mode, int npt, DDXPointPtr pptInit) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIPolySegment(DrawablePtr dst, GCPtr pGC, + int nseg, xSegment *pSeg) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->PolySegment(dst, pGC, nseg, pSeg); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIPolyRectangle(DrawablePtr dst, GCPtr pGC, + int nRects, xRectangle *pRects) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} +static void +DRIPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->PolyArc(dst, pGC, narcs, parcs); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIFillPolygon(DrawablePtr dst, GCPtr pGC, + int shape, int mode, int count, + DDXPointPtr pptInit) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIPolyFillRect(DrawablePtr dst, GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIPolyFillArc(DrawablePtr dst, GCPtr pGC, + int narcsInit, xArc *parcsInit) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static int +DRIPolyText8(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, char *chars) { + int ret; + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + ret = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); + + return ret; +} + +static int +DRIPolyText16(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, unsigned short *chars) { + int ret; + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + ret = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); + + return ret; +} + +static void +DRIImageText8(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, char *chars) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->ImageText8(dst, pGC, x, y, count, chars); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIImageText16(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, unsigned short *chars) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->ImageText16(dst, pGC, x, y, count, chars); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIImageGlyphBlt(DrawablePtr dst, GCPtr pGC, + int x, int y, unsigned int nglyphInit, + CharInfoPtr *ppciInit, pointer unused) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void DRIPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr *ppci, pointer pglyphBase) { + DRISavedDrawableState saved; + + DRISurfaceSetDrawable(dst, &saved); + + DRIUnwrapGC(pGC); + + pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(dst, &saved); +} + +static void +DRIPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, + int dx, int dy, int xOrg, int yOrg) { + DRISavedDrawableState bitMapSaved, dstSaved; + + DRISurfaceSetDrawable(&pBitMap->drawable, &bitMapSaved); + DRISurfaceSetDrawable(dst, &dstSaved); + + DRIUnwrapGC(pGC); + + pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); + + DRIWrapGC(pGC); + + DRISurfaceRestoreDrawable(&pBitMap->drawable, &bitMapSaved); + DRISurfaceRestoreDrawable(dst, &dstSaved); +} + + +static GCOps driGCOps = { + DRIFillSpans, + DRISetSpans, + DRIPutImage, + DRICopyArea, + DRICopyPlane, + DRIPolyPoint, + DRIPolylines, + DRIPolySegment, + DRIPolyRectangle, + DRIPolyArc, + DRIFillPolygon, + DRIPolyFillRect, + DRIPolyFillArc, + DRIPolyText8, + DRIPolyText16, + DRIImageText8, + DRIImageText16, + DRIImageGlyphBlt, + DRIPolyGlyphBlt, + DRIPushPixels +}; + + +static Bool +DRICreateGC(GCPtr pGC) { + ScreenPtr pScreen = pGC->pScreen; + DRIWrapScreenRec *pScreenPriv; + DRIGCRec *pGCPriv; + Bool ret; + + pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, driWrapScreenKey); + + pGCPriv = DRIGetGCPriv(pGC); + + unwrap(pScreenPriv, pScreen, CreateGC); + ret = pScreen->CreateGC(pGC); + + if(ret) { + pGCPriv->originalOps = pGC->ops; + pGC->ops = &driGCOps; + pGCPriv->driOps = &driGCOps; + } + + wrap(pScreenPriv, pScreen, CreateGC, DRICreateGC); + + return ret; +} + + +/* Return false if an error occurred. */ +Bool +DRIWrapInit(ScreenPtr pScreen) { + DRIWrapScreenRec *pScreenPriv; + + if(!dixRequestPrivate(driGCKey, sizeof(DRIGCRec))) + return FALSE; + + if(!dixRequestPrivate(driWrapScreenKey, sizeof(DRIWrapScreenRec))) + return FALSE; + + pScreenPriv = malloc(sizeof(*pScreenPriv)); + + if(NULL == pScreenPriv) + return FALSE; + + pScreenPriv->CreateGC = pScreen->CreateGC; + pScreen->CreateGC = DRICreateGC; + + dixSetPrivate(&pScreen->devPrivates, driWrapScreenKey, pScreenPriv); + + return TRUE; +} diff --git a/xorg-server/hw/xquartz/xpr/x-hook.c b/xorg-server/hw/xquartz/xpr/x-hook.c index 5b850fe88..c65b6fc68 100644 --- a/xorg-server/hw/xquartz/xpr/x-hook.c +++ b/xorg-server/hw/xquartz/xpr/x-hook.c @@ -1,120 +1,120 @@ -/* x-hook.c - - Copyright (c) 2003 Apple Computer, 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 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 ABOVE LISTED COPYRIGHT - HOLDER(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(s) of the above - copyright holders shall not be used in advertising or otherwise to - promote the sale, use or other dealings in this Software without - prior written authorization. */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "x-hook.h" -#include <stdlib.h> -#include <assert.h> -#include "os.h" - -#define CELL_NEW(f,d) X_PFX (list_prepend) ((x_list *) (f), (d)) -#define CELL_FREE(c) X_PFX (list_free_1) (c) -#define CELL_FUN(c) ((x_hook_function *) ((c)->next)) -#define CELL_DATA(c) ((c)->data) - -X_EXTERN x_list * -X_PFX (hook_add) (x_list *lst, x_hook_function *fun, void *data) -{ - return X_PFX (list_prepend) (lst, CELL_NEW (fun, data)); -} - -X_EXTERN x_list * -X_PFX (hook_remove) (x_list *lst, x_hook_function *fun, void *data) -{ - x_list *node, *cell; - x_list *to_delete = NULL; - - for (node = lst; node != NULL; node = node->next) - { - cell = node->data; - if (CELL_FUN (cell) == fun && CELL_DATA (cell) == data) - to_delete = X_PFX (list_prepend) (to_delete, cell); - } - - for (node = to_delete; node != NULL; node = node->next) - { - cell = node->data; - lst = X_PFX (list_remove) (lst, cell); - CELL_FREE (cell); - } - - X_PFX (list_free) (to_delete); - return lst; -} - -X_EXTERN void -X_PFX (hook_run) (x_list *lst, void *arg) -{ - x_list *node, *cell; - x_hook_function **fun; - void **data; - int length, i; - - if(!lst) - return; - - length = X_PFX (list_length) (lst); - fun = xalloc (sizeof (x_hook_function *) * length); - data = xalloc (sizeof (void *) * length); - - if(!fun || !data) { - FatalError("Failed to allocate memory in %s\n", __func__); - } - - for (i = 0, node = lst; node != NULL; node = node->next, i++) - { - cell = node->data; - fun[i] = CELL_FUN (cell); - data[i] = CELL_DATA (cell); - } - - for (i = 0; i < length; i++) - { - (*fun[i]) (arg, data[i]); - } - - xfree(fun); - xfree(data); -} - -X_EXTERN void -X_PFX (hook_free) (x_list *lst) -{ - x_list *node; - - for (node = lst; node != NULL; node = node->next) - { - CELL_FREE (node->data); - } - - X_PFX (list_free) (lst); -} +/* x-hook.c + + Copyright (c) 2003 Apple Computer, 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 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 ABOVE LISTED COPYRIGHT + HOLDER(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(s) of the above + copyright holders shall not be used in advertising or otherwise to + promote the sale, use or other dealings in this Software without + prior written authorization. */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "x-hook.h" +#include <stdlib.h> +#include <assert.h> +#include "os.h" + +#define CELL_NEW(f,d) X_PFX (list_prepend) ((x_list *) (f), (d)) +#define CELL_FREE(c) X_PFX (list_free_1) (c) +#define CELL_FUN(c) ((x_hook_function *) ((c)->next)) +#define CELL_DATA(c) ((c)->data) + +X_EXTERN x_list * +X_PFX (hook_add) (x_list *lst, x_hook_function *fun, void *data) +{ + return X_PFX (list_prepend) (lst, CELL_NEW (fun, data)); +} + +X_EXTERN x_list * +X_PFX (hook_remove) (x_list *lst, x_hook_function *fun, void *data) +{ + x_list *node, *cell; + x_list *to_delete = NULL; + + for (node = lst; node != NULL; node = node->next) + { + cell = node->data; + if (CELL_FUN (cell) == fun && CELL_DATA (cell) == data) + to_delete = X_PFX (list_prepend) (to_delete, cell); + } + + for (node = to_delete; node != NULL; node = node->next) + { + cell = node->data; + lst = X_PFX (list_remove) (lst, cell); + CELL_FREE (cell); + } + + X_PFX (list_free) (to_delete); + return lst; +} + +X_EXTERN void +X_PFX (hook_run) (x_list *lst, void *arg) +{ + x_list *node, *cell; + x_hook_function **fun; + void **data; + int length, i; + + if(!lst) + return; + + length = X_PFX (list_length) (lst); + fun = malloc(sizeof (x_hook_function *) * length); + data = malloc(sizeof (void *) * length); + + if(!fun || !data) { + FatalError("Failed to allocate memory in %s\n", __func__); + } + + for (i = 0, node = lst; node != NULL; node = node->next, i++) + { + cell = node->data; + fun[i] = CELL_FUN (cell); + data[i] = CELL_DATA (cell); + } + + for (i = 0; i < length; i++) + { + (*fun[i]) (arg, data[i]); + } + + free(fun); + free(data); +} + +X_EXTERN void +X_PFX (hook_free) (x_list *lst) +{ + x_list *node; + + for (node = lst; node != NULL; node = node->next) + { + CELL_FREE (node->data); + } + + X_PFX (list_free) (lst); +} diff --git a/xorg-server/hw/xquartz/xpr/xprCursor.c b/xorg-server/hw/xquartz/xpr/xprCursor.c index fbaf825de..df9eef95e 100644 --- a/xorg-server/hw/xquartz/xpr/xprCursor.c +++ b/xorg-server/hw/xquartz/xpr/xprCursor.c @@ -1,418 +1,418 @@ -/************************************************************** - * - * Xplugin cursor support - * - * Copyright (c) 2001 Torrey T. Lyons and Greg Parker. - * Copyright (c) 2002 Apple Computer, 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 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 ABOVE LISTED COPYRIGHT HOLDER(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(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in this Software without prior written authorization. - */ - -#include "sanitizedCarbon.h" - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include "quartzCommon.h" -#include "xpr.h" -#include "darwin.h" -#include "darwinEvents.h" -#include <Xplugin.h> - -#include "mi.h" -#include "scrnintstr.h" -#include "cursorstr.h" -#include "mipointrst.h" -#include "windowstr.h" -#include "globals.h" -#include "servermd.h" -#include "dixevents.h" -#include "x-hash.h" - -typedef struct { - int cursorVisible; - QueryBestSizeProcPtr QueryBestSize; - miPointerSpriteFuncPtr spriteFuncs; -} QuartzCursorScreenRec, *QuartzCursorScreenPtr; - -static int darwinCursorScreenKeyIndex; -static DevPrivateKey darwinCursorScreenKey = &darwinCursorScreenKeyIndex; - -#define CURSOR_PRIV(pScreen) ((QuartzCursorScreenPtr) \ - dixLookupPrivate(&pScreen->devPrivates, darwinCursorScreenKey)) - - -static Bool -load_cursor(CursorPtr src, int screen) -{ - uint32_t *data; - uint32_t rowbytes; - int width, height; - int hot_x, hot_y; - - uint32_t fg_color, bg_color; - uint8_t *srow, *sptr; - uint8_t *mrow, *mptr; - uint32_t *drow, *dptr; - unsigned xcount, ycount; - - xp_error err; - - width = src->bits->width; - height = src->bits->height; - hot_x = src->bits->xhot; - hot_y = src->bits->yhot; - -#ifdef ARGB_CURSOR - if (src->bits->argb != NULL) - { -#if BITMAP_BIT_ORDER == MSBFirst - rowbytes = src->bits->width * sizeof (CARD32); - data = (uint32_t *) src->bits->argb; -#else - const uint32_t *be_data=(uint32_t *) src->bits->argb; - unsigned i; - rowbytes = src->bits->width * sizeof (CARD32); - data = xalloc(rowbytes * src->bits->height); - if(!data) { - FatalError("Failed to allocate memory in %s\n", __func__); - } - for(i=0;i<(src->bits->width*src->bits->height);i++) - data[i]=ntohl(be_data[i]); -#endif - } - else -#endif - { - fg_color = 0xFF00 | (src->foreRed >> 8); - fg_color <<= 16; - fg_color |= src->foreGreen & 0xFF00; - fg_color |= src->foreBlue >> 8; - - bg_color = 0xFF00 | (src->backRed >> 8); - bg_color <<= 16; - bg_color |= src->backGreen & 0xFF00; - bg_color |= src->backBlue >> 8; - - fg_color = htonl(fg_color); - bg_color = htonl(bg_color); - - /* round up to 8 pixel boundary so we can convert whole bytes */ - rowbytes = ((src->bits->width * 4) + 31) & ~31; - data = xalloc(rowbytes * src->bits->height); - if(!data) { - FatalError("Failed to allocate memory in %s\n", __func__); - } - - if (!src->bits->emptyMask) - { - ycount = src->bits->height; - srow = src->bits->source; mrow = src->bits->mask; - drow = data; - - while (ycount-- > 0) - { - xcount = bits_to_bytes(src->bits->width); - sptr = srow; mptr = mrow; - dptr = drow; - - while (xcount-- > 0) - { - uint8_t s, m; - int i; - - s = *sptr++; m = *mptr++; - for (i = 0; i < 8; i++) - { -#if BITMAP_BIT_ORDER == MSBFirst - if (m & 128) - *dptr++ = (s & 128) ? fg_color : bg_color; - else - *dptr++ = 0; - s <<= 1; m <<= 1; -#else - if (m & 1) - *dptr++ = (s & 1) ? fg_color : bg_color; - else - *dptr++ = 0; - s >>= 1; m >>= 1; -#endif - } - } - - srow += BitmapBytePad(src->bits->width); - mrow += BitmapBytePad(src->bits->width); - drow = (uint32_t *) ((char *) drow + rowbytes); - } - } - else - { - memset(data, 0, src->bits->height * rowbytes); - } - } - - err = xp_set_cursor(width, height, hot_x, hot_y, data, rowbytes); - xfree(data); - return err == Success; -} - - -/* -=========================================================================== - - Pointer sprite functions - -=========================================================================== -*/ - -/* - * QuartzRealizeCursor - * Convert the X cursor representation to native format if possible. - */ -static Bool -QuartzRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - if(pCursor == NULL || pCursor->bits == NULL) - return FALSE; - - /* FIXME: cache ARGB8888 representation? */ - - return TRUE; -} - - -/* - * QuartzUnrealizeCursor - * Free the storage space associated with a realized cursor. - */ -static Bool -QuartzUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - return TRUE; -} - - -/* - * QuartzSetCursor - * Set the cursor sprite and position. - */ -static void -QuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) -{ - QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); - - if (!quartzServerVisible) - return; - - if (pCursor == NULL) - { - if (ScreenPriv->cursorVisible) - { - xp_hide_cursor(); - ScreenPriv->cursorVisible = FALSE; - } - } - else - { - load_cursor(pCursor, pScreen->myNum); - - if (!ScreenPriv->cursorVisible) - { - xp_show_cursor(); - ScreenPriv->cursorVisible = TRUE; - } - } -} - -/* - * QuartzMoveCursor - * Move the cursor. This is a noop for us. - */ -static void -QuartzMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ -} - -/* -=========================================================================== - - Pointer screen functions - -=========================================================================== -*/ - -/* - * QuartzCursorOffScreen - */ -static Bool -QuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) -{ - return FALSE; -} - - -/* - * QuartzCrossScreen - */ -static void -QuartzCrossScreen(ScreenPtr pScreen, Bool entering) -{ - return; -} - - -/* - * QuartzWarpCursor - * Change the cursor position without generating an event or motion history. - * The input coordinates (x,y) are in pScreen-local X11 coordinates. - * - */ -static void -QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - if (quartzServerVisible) - { - int sx, sy; - - sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX; - sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY; - - CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y)); - } - - miPointerWarpCursor(pDev, pScreen, x, y); - miPointerUpdateSprite(pDev); -} - - -static miPointerScreenFuncRec quartzScreenFuncsRec = { - QuartzCursorOffScreen, - QuartzCrossScreen, - QuartzWarpCursor, - NULL, - NULL -}; - - -/* -=========================================================================== - - Other screen functions - -=========================================================================== -*/ - -/* - * QuartzCursorQueryBestSize - * Handle queries for best cursor size - */ -static void -QuartzCursorQueryBestSize(int class, unsigned short *width, - unsigned short *height, ScreenPtr pScreen) -{ - QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); - - if (class == CursorShape) - { - /* FIXME: query window server? */ - *width = 32; - *height = 32; - } - else - { - (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); - } -} - -/* - * QuartzInitCursor - * Initialize cursor support - */ -Bool -QuartzInitCursor(ScreenPtr pScreen) -{ - QuartzCursorScreenPtr ScreenPriv; - miPointerScreenPtr PointPriv; - - /* initialize software cursor handling (always needed as backup) */ - if (!miDCInitialize(pScreen, &quartzScreenFuncsRec)) - return FALSE; - - ScreenPriv = xcalloc(1, sizeof(QuartzCursorScreenRec)); - if (ScreenPriv == NULL) - return FALSE; - - /* CURSOR_PRIV(pScreen) = ScreenPriv; */ - dixSetPrivate(&pScreen->devPrivates, darwinCursorScreenKey, ScreenPriv); - - /* override some screen procedures */ - ScreenPriv->QueryBestSize = pScreen->QueryBestSize; - pScreen->QueryBestSize = QuartzCursorQueryBestSize; - - PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); - - ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; - - PointPriv->spriteFuncs->RealizeCursor = QuartzRealizeCursor; - PointPriv->spriteFuncs->UnrealizeCursor = QuartzUnrealizeCursor; - PointPriv->spriteFuncs->SetCursor = QuartzSetCursor; - PointPriv->spriteFuncs->MoveCursor = QuartzMoveCursor; - - ScreenPriv->cursorVisible = TRUE; - return TRUE; -} - -/* - * QuartzSuspendXCursor - * X server is hiding. Restore the Aqua cursor. - */ -void -QuartzSuspendXCursor(ScreenPtr pScreen) -{ -} - - -/* - * QuartzResumeXCursor - * X server is showing. Restore the X cursor. - */ -void -QuartzResumeXCursor(ScreenPtr pScreen) -{ - WindowPtr pWin; - CursorPtr pCursor; - - /* TODO: Tablet? */ - - pWin = GetSpriteWindow(darwinPointer); - if (pWin->drawable.pScreen != pScreen) - return; - - pCursor = GetSpriteCursor(darwinPointer); - if (pCursor == NULL) - return; - - QuartzSetCursor(darwinPointer, pScreen, pCursor, /* x */ 0, /* y */ 0); -} +/************************************************************** + * + * Xplugin cursor support + * + * Copyright (c) 2001 Torrey T. Lyons and Greg Parker. + * Copyright (c) 2002 Apple Computer, 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 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 ABOVE LISTED COPYRIGHT HOLDER(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(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#include "sanitizedCarbon.h" + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "quartzCommon.h" +#include "xpr.h" +#include "darwin.h" +#include "darwinEvents.h" +#include <Xplugin.h> + +#include "mi.h" +#include "scrnintstr.h" +#include "cursorstr.h" +#include "mipointrst.h" +#include "windowstr.h" +#include "globals.h" +#include "servermd.h" +#include "dixevents.h" +#include "x-hash.h" + +typedef struct { + int cursorVisible; + QueryBestSizeProcPtr QueryBestSize; + miPointerSpriteFuncPtr spriteFuncs; +} QuartzCursorScreenRec, *QuartzCursorScreenPtr; + +static int darwinCursorScreenKeyIndex; +static DevPrivateKey darwinCursorScreenKey = &darwinCursorScreenKeyIndex; + +#define CURSOR_PRIV(pScreen) ((QuartzCursorScreenPtr) \ + dixLookupPrivate(&pScreen->devPrivates, darwinCursorScreenKey)) + + +static Bool +load_cursor(CursorPtr src, int screen) +{ + uint32_t *data; + uint32_t rowbytes; + int width, height; + int hot_x, hot_y; + + uint32_t fg_color, bg_color; + uint8_t *srow, *sptr; + uint8_t *mrow, *mptr; + uint32_t *drow, *dptr; + unsigned xcount, ycount; + + xp_error err; + + width = src->bits->width; + height = src->bits->height; + hot_x = src->bits->xhot; + hot_y = src->bits->yhot; + +#ifdef ARGB_CURSOR + if (src->bits->argb != NULL) + { +#if BITMAP_BIT_ORDER == MSBFirst + rowbytes = src->bits->width * sizeof (CARD32); + data = (uint32_t *) src->bits->argb; +#else + const uint32_t *be_data=(uint32_t *) src->bits->argb; + unsigned i; + rowbytes = src->bits->width * sizeof (CARD32); + data = malloc(rowbytes * src->bits->height); + if(!data) { + FatalError("Failed to allocate memory in %s\n", __func__); + } + for(i=0;i<(src->bits->width*src->bits->height);i++) + data[i]=ntohl(be_data[i]); +#endif + } + else +#endif + { + fg_color = 0xFF00 | (src->foreRed >> 8); + fg_color <<= 16; + fg_color |= src->foreGreen & 0xFF00; + fg_color |= src->foreBlue >> 8; + + bg_color = 0xFF00 | (src->backRed >> 8); + bg_color <<= 16; + bg_color |= src->backGreen & 0xFF00; + bg_color |= src->backBlue >> 8; + + fg_color = htonl(fg_color); + bg_color = htonl(bg_color); + + /* round up to 8 pixel boundary so we can convert whole bytes */ + rowbytes = ((src->bits->width * 4) + 31) & ~31; + data = malloc(rowbytes * src->bits->height); + if(!data) { + FatalError("Failed to allocate memory in %s\n", __func__); + } + + if (!src->bits->emptyMask) + { + ycount = src->bits->height; + srow = src->bits->source; mrow = src->bits->mask; + drow = data; + + while (ycount-- > 0) + { + xcount = bits_to_bytes(src->bits->width); + sptr = srow; mptr = mrow; + dptr = drow; + + while (xcount-- > 0) + { + uint8_t s, m; + int i; + + s = *sptr++; m = *mptr++; + for (i = 0; i < 8; i++) + { +#if BITMAP_BIT_ORDER == MSBFirst + if (m & 128) + *dptr++ = (s & 128) ? fg_color : bg_color; + else + *dptr++ = 0; + s <<= 1; m <<= 1; +#else + if (m & 1) + *dptr++ = (s & 1) ? fg_color : bg_color; + else + *dptr++ = 0; + s >>= 1; m >>= 1; +#endif + } + } + + srow += BitmapBytePad(src->bits->width); + mrow += BitmapBytePad(src->bits->width); + drow = (uint32_t *) ((char *) drow + rowbytes); + } + } + else + { + memset(data, 0, src->bits->height * rowbytes); + } + } + + err = xp_set_cursor(width, height, hot_x, hot_y, data, rowbytes); + free(data); + return err == Success; +} + + +/* +=========================================================================== + + Pointer sprite functions + +=========================================================================== +*/ + +/* + * QuartzRealizeCursor + * Convert the X cursor representation to native format if possible. + */ +static Bool +QuartzRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + if(pCursor == NULL || pCursor->bits == NULL) + return FALSE; + + /* FIXME: cache ARGB8888 representation? */ + + return TRUE; +} + + +/* + * QuartzUnrealizeCursor + * Free the storage space associated with a realized cursor. + */ +static Bool +QuartzUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + return TRUE; +} + + +/* + * QuartzSetCursor + * Set the cursor sprite and position. + */ +static void +QuartzSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); + + if (!quartzServerVisible) + return; + + if (pCursor == NULL) + { + if (ScreenPriv->cursorVisible) + { + xp_hide_cursor(); + ScreenPriv->cursorVisible = FALSE; + } + } + else + { + load_cursor(pCursor, pScreen->myNum); + + if (!ScreenPriv->cursorVisible) + { + xp_show_cursor(); + ScreenPriv->cursorVisible = TRUE; + } + } +} + +/* + * QuartzMoveCursor + * Move the cursor. This is a noop for us. + */ +static void +QuartzMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ +} + +/* +=========================================================================== + + Pointer screen functions + +=========================================================================== +*/ + +/* + * QuartzCursorOffScreen + */ +static Bool +QuartzCursorOffScreen(ScreenPtr *pScreen, int *x, int *y) +{ + return FALSE; +} + + +/* + * QuartzCrossScreen + */ +static void +QuartzCrossScreen(ScreenPtr pScreen, Bool entering) +{ + return; +} + + +/* + * QuartzWarpCursor + * Change the cursor position without generating an event or motion history. + * The input coordinates (x,y) are in pScreen-local X11 coordinates. + * + */ +static void +QuartzWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + if (quartzServerVisible) + { + int sx, sy; + + sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX; + sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY; + + CGWarpMouseCursorPosition(CGPointMake(sx + x, sy + y)); + } + + miPointerWarpCursor(pDev, pScreen, x, y); + miPointerUpdateSprite(pDev); +} + + +static miPointerScreenFuncRec quartzScreenFuncsRec = { + QuartzCursorOffScreen, + QuartzCrossScreen, + QuartzWarpCursor, + NULL, + NULL +}; + + +/* +=========================================================================== + + Other screen functions + +=========================================================================== +*/ + +/* + * QuartzCursorQueryBestSize + * Handle queries for best cursor size + */ +static void +QuartzCursorQueryBestSize(int class, unsigned short *width, + unsigned short *height, ScreenPtr pScreen) +{ + QuartzCursorScreenPtr ScreenPriv = CURSOR_PRIV(pScreen); + + if (class == CursorShape) + { + /* FIXME: query window server? */ + *width = 32; + *height = 32; + } + else + { + (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); + } +} + +/* + * QuartzInitCursor + * Initialize cursor support + */ +Bool +QuartzInitCursor(ScreenPtr pScreen) +{ + QuartzCursorScreenPtr ScreenPriv; + miPointerScreenPtr PointPriv; + + /* initialize software cursor handling (always needed as backup) */ + if (!miDCInitialize(pScreen, &quartzScreenFuncsRec)) + return FALSE; + + ScreenPriv = calloc(1, sizeof(QuartzCursorScreenRec)); + if (ScreenPriv == NULL) + return FALSE; + + /* CURSOR_PRIV(pScreen) = ScreenPriv; */ + dixSetPrivate(&pScreen->devPrivates, darwinCursorScreenKey, ScreenPriv); + + /* override some screen procedures */ + ScreenPriv->QueryBestSize = pScreen->QueryBestSize; + pScreen->QueryBestSize = QuartzCursorQueryBestSize; + + PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + + ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; + + PointPriv->spriteFuncs->RealizeCursor = QuartzRealizeCursor; + PointPriv->spriteFuncs->UnrealizeCursor = QuartzUnrealizeCursor; + PointPriv->spriteFuncs->SetCursor = QuartzSetCursor; + PointPriv->spriteFuncs->MoveCursor = QuartzMoveCursor; + + ScreenPriv->cursorVisible = TRUE; + return TRUE; +} + +/* + * QuartzSuspendXCursor + * X server is hiding. Restore the Aqua cursor. + */ +void +QuartzSuspendXCursor(ScreenPtr pScreen) +{ +} + + +/* + * QuartzResumeXCursor + * X server is showing. Restore the X cursor. + */ +void +QuartzResumeXCursor(ScreenPtr pScreen) +{ + WindowPtr pWin; + CursorPtr pCursor; + + /* TODO: Tablet? */ + + pWin = GetSpriteWindow(darwinPointer); + if (pWin->drawable.pScreen != pScreen) + return; + + pCursor = GetSpriteCursor(darwinPointer); + if (pCursor == NULL) + return; + + QuartzSetCursor(darwinPointer, pScreen, pCursor, /* x */ 0, /* y */ 0); +} diff --git a/xorg-server/hw/xquartz/xpr/xprScreen.c b/xorg-server/hw/xquartz/xpr/xprScreen.c index 44067862f..bc68f7923 100644 --- a/xorg-server/hw/xquartz/xpr/xprScreen.c +++ b/xorg-server/hw/xquartz/xpr/xprScreen.c @@ -195,7 +195,7 @@ xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height) return; } - displayList = xalloc(displayCount * sizeof(CGDirectDisplayID)); + displayList = malloc(displayCount * sizeof(CGDirectDisplayID)); if(!displayList) FatalError("Unable to allocate memory for list of displays.\n"); CGGetActiveDisplayList(displayCount, displayList, &displayCount); @@ -232,7 +232,7 @@ xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height) frame.size.width, frame.size.height); } - xfree(displayList); + free(displayList); } /* diff --git a/xorg-server/hw/xwin/glx/indirect.c b/xorg-server/hw/xwin/glx/indirect.c index 48094a69e..08c16f85d 100644 --- a/xorg-server/hw/xwin/glx/indirect.c +++ b/xorg-server/hw/xwin/glx/indirect.c @@ -1,2464 +1,2464 @@ -/* - * File: indirect.c - * Purpose: A GLX implementation that uses Windows OpenGL library - * - * Authors: Alexander Gottwald - * Jon TURNEY - * - * Copyright (c) Jon TURNEY 2009 - * Copyright (c) Alexander Gottwald 2004 - * - * Portions of this file are copied from GL/apple/indirect.c, - * which contains the following copyright: - * - * Copyright (c) 2007, 2008, 2009 Apple Inc. - * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved. - * Copyright (c) 2002 Greg Parker. All Rights Reserved. - * - * Portions of this file are copied from Mesa's xf86glx.c, - * which contains the following copyright: - * - * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - * 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 ABOVE LISTED COPYRIGHT HOLDER(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. - */ - -/* - TODO: - - hook up remaining unimplemented extensions - - research what guarantees glXWaitX, glXWaitGL are supposed to offer, and implement then - using GdiFlush and/or glFinish - - pbuffer clobbering: we don't get async notification, but can we arrange to emit the - event when we notice it's been clobbered? at the very least, check if it's been clobbered - before using it? - - are the __GLXConfig * we get handed back ones we are made (so we can extend the structure - with privates?) Or are they created inside the GLX core as well? -*/ - -/* - MSDN clarifications: - - It says SetPixelFormat()'s PIXELFORMATDESCRIPTOR pointer argument has no effect - except on metafiles, this seems to mean that as it's ok to supply NULL if the DC - is not for a metafile - - wglMakeCurrent ignores the hdc if hglrc is NULL, so wglMakeCurrent(NULL, NULL) - is used to make no context current - -*/ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif - -#include "glwindows.h" -#include <glx/glxserver.h> -#include <glx/glxutil.h> -#include <glx/extension_string.h> -#include <GL/glxtokens.h> - -#include <winpriv.h> -#include <wgl_ext_api.h> -#include "win.h" -#include <winmsg.h> - -extern Bool g_fXdmcpEnabled; -extern Bool g_fNativeGl; - -#define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1])) - -/* ---------------------------------------------------------------------- */ -/* - * structure definitions - */ - -typedef struct __GLXWinContext __GLXWinContext; -typedef struct __GLXWinDrawable __GLXWinDrawable; -typedef struct __GLXWinScreen glxWinScreen; -typedef struct __GLXWinConfig GLXWinConfig; - -struct __GLXWinContext { - __GLXcontext base; - HGLRC ctx; /* Windows GL Context */ - HDC hDC; /* Windows device context */ - HDC hreadDC; /* Windows device read context */ - __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */ - HWND hwnd; /* For detecting when HWND has changed */ - HWND hreadwnd; -}; - -struct __GLXWinDrawable -{ - __GLXdrawable base; - __GLXWinContext *drawContext; - - /* If this drawable is GLX_DRAWABLE_PBUFFER */ - HPBUFFERARB hPbuffer; - - /* If this drawable is GLX_DRAWABLE_PIXMAP */ - HDC dibDC; - HBITMAP hDIB; - HBITMAP hOldDIB; /* original DIB for DC */ - void *pOldBits; /* original pBits for this drawable's pixmap */ -}; - -struct __GLXWinScreen -{ - __GLXscreen base; - - /* Supported GLX extensions */ - unsigned char glx_enable_bits[__GLX_EXT_BYTES]; - - Bool has_WGL_ARB_multisample; - Bool has_WGL_ARB_pixel_format; - Bool has_WGL_ARB_pbuffer; - Bool has_WGL_ARB_render_texture; - - /* wrapped screen functions */ - RealizeWindowProcPtr RealizeWindow; - UnrealizeWindowProcPtr UnrealizeWindow; - DestroyWindowProcPtr DestroyWindow; - CopyWindowProcPtr CopyWindow; - PositionWindowProcPtr PositionWindow; -}; - -struct __GLXWinConfig -{ - __GLXconfig base; - int pixelFormatIndex; -}; - -/* ---------------------------------------------------------------------- */ -/* - * Various debug helpers - */ - -#ifdef _DEBUG -void GLWIN_DEBUG_HWND(HWND hwnd) -{ - if (glxWinDebugSettings.dumpHWND) - { - char buffer[1024]; - RECT Rect; - HDC hDc=GetDC(hwnd); - - if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; - GetWindowRect(hwnd,&Rect); - - GLWIN_DEBUG_MSG("Got HWND %p (hdc %p) for window '%s' (%d,%d,%d,%d)", hwnd, hDc, buffer, Rect.left, Rect.top, Rect.right, Rect.bottom); - ReleaseDC(hwnd,hDc); - } -} - -void GLWIN_HDC_DEBUG_MSG(const char *Message, HDC hDc, HWND hwnd) -{ - char buffer[1024]; - RECT Rect; - - if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; - GetWindowRect(hwnd,&Rect); - - GLWIN_DEBUG_MSG("Got HDC %p (hwnd %p) for window '%s' (%d,%d,%d,%d)", hDc, hwnd, buffer, Rect.left, Rect.top, Rect.right, Rect.bottom); - -} - -glxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0}; - -static void glxWinInitDebugSettings(void) -{ - char *envptr; - - envptr = getenv("GLWIN_ENABLE_DEBUG"); - if (envptr != NULL) - glxWinDebugSettings.enableDebug = (atoi(envptr) == 1); - - envptr = getenv("GLWIN_ENABLE_TRACE"); - if (envptr != NULL) - glxWinDebugSettings.enableTrace = (atoi(envptr) == 1); - - envptr = getenv("GLWIN_DUMP_PFD"); - if (envptr != NULL) - glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1); - - envptr = getenv("GLWIN_DUMP_HWND"); - if (envptr != NULL) - glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1); - - envptr = getenv("GLWIN_DUMP_DC"); - if (envptr != NULL) - glxWinDebugSettings.dumpDC = (atoi(envptr) == 1); - - envptr = getenv("GLWIN_ENABLE_GLCALL_TRACE"); - if (envptr != NULL) - glxWinDebugSettings.enableGLcallTrace = (atoi(envptr) == 1); - - envptr = getenv("GLWIN_ENABLE_WGLCALL_TRACE"); - if (envptr != NULL) - glxWinDebugSettings.enableWGLcallTrace = (atoi(envptr) == 1); - - envptr = getenv("GLWIN_DEBUG_ALL"); - if (envptr != NULL) - { - glxWinDebugSettings.enableDebug = 1; - glxWinDebugSettings.enableTrace = 1; - glxWinDebugSettings.dumpPFD = 1; - glxWinDebugSettings.dumpHWND = 1; - glxWinDebugSettings.dumpDC = 1; - glxWinDebugSettings.enableGLcallTrace = 1; - glxWinDebugSettings.enableWGLcallTrace = 1; - } -} -#endif - -static -const char *glxWinErrorMessage(void) -{ - static char errorbuffer[1024]; - DWORD Error=GetLastError(); - int offset; - - sprintf(errorbuffer, "%p ",Error); - offset=strlen(errorbuffer); - - if (!FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - Error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &errorbuffer[offset], - sizeof(errorbuffer), - NULL )) - { - snprintf(errorbuffer, sizeof(errorbuffer), "Unknown error in FormatMessage: %08x!", (unsigned)GetLastError()); - } - - if (errorbuffer[strlen(errorbuffer)-1] == '\n') - errorbuffer[strlen(errorbuffer)-1] = 0; - - return errorbuffer; -} - -static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd); - -#ifdef _DEBUG - -#define DUMP_PFD_FLAG(flag) \ - if (pfd->dwFlags & flag) { \ - ErrorF("%s%s", pipesym, #flag); \ - pipesym = " | "; \ - } - -static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd) -{ - const char *pipesym = ""; /* will be set after first flag dump */ - ErrorF("PIXELFORMATDESCRIPTOR:\n"); - ErrorF("nSize = %u\n", pfd->nSize); - ErrorF("nVersion = %u\n", pfd->nVersion); - ErrorF("dwFlags = %lu = {", pfd->dwFlags); - DUMP_PFD_FLAG(PFD_DOUBLEBUFFER); - DUMP_PFD_FLAG(PFD_STEREO); - DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW); - DUMP_PFD_FLAG(PFD_DRAW_TO_BITMAP); - DUMP_PFD_FLAG(PFD_SUPPORT_GDI); - DUMP_PFD_FLAG(PFD_SUPPORT_OPENGL); - DUMP_PFD_FLAG(PFD_GENERIC_FORMAT); - DUMP_PFD_FLAG(PFD_NEED_PALETTE); - DUMP_PFD_FLAG(PFD_NEED_SYSTEM_PALETTE); - DUMP_PFD_FLAG(PFD_SWAP_EXCHANGE); - DUMP_PFD_FLAG(PFD_SWAP_COPY); - DUMP_PFD_FLAG(PFD_SWAP_LAYER_BUFFERS); - DUMP_PFD_FLAG(PFD_GENERIC_ACCELERATED); - DUMP_PFD_FLAG(PFD_DEPTH_DONTCARE); - DUMP_PFD_FLAG(PFD_DOUBLEBUFFER_DONTCARE); - DUMP_PFD_FLAG(PFD_STEREO_DONTCARE); - ErrorF("}\n"); - - ErrorF("iPixelType = %hu = %s\n", pfd->iPixelType, - (pfd->iPixelType == PFD_TYPE_RGBA ? "PFD_TYPE_RGBA" : "PFD_TYPE_COLORINDEX")); - ErrorF("cColorBits = %hhu\n", pfd->cColorBits); - ErrorF("cRedBits = %hhu\n", pfd->cRedBits); - ErrorF("cRedShift = %hhu\n", pfd->cRedShift); - ErrorF("cGreenBits = %hhu\n", pfd->cGreenBits); - ErrorF("cGreenShift = %hhu\n", pfd->cGreenShift); - ErrorF("cBlueBits = %hhu\n", pfd->cBlueBits); - ErrorF("cBlueShift = %hhu\n", pfd->cBlueShift); - ErrorF("cAlphaBits = %hhu\n", pfd->cAlphaBits); - ErrorF("cAlphaShift = %hhu\n", pfd->cAlphaShift); - ErrorF("cAccumBits = %hhu\n", pfd->cAccumBits); - ErrorF("cAccumRedBits = %hhu\n", pfd->cAccumRedBits); - ErrorF("cAccumGreenBits = %hhu\n", pfd->cAccumGreenBits); - ErrorF("cAccumBlueBits = %hhu\n", pfd->cAccumBlueBits); - ErrorF("cAccumAlphaBits = %hhu\n", pfd->cAccumAlphaBits); - ErrorF("cDepthBits = %hhu\n", pfd->cDepthBits); - ErrorF("cStencilBits = %hhu\n", pfd->cStencilBits); - ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers); - ErrorF("iLayerType = %hhu\n", pfd->iLayerType); - ErrorF("bReserved = %hhu\n", pfd->bReserved); - ErrorF("dwLayerMask = %lu\n", pfd->dwLayerMask); - ErrorF("dwVisibleMask = %lu\n", pfd->dwVisibleMask); - ErrorF("dwDamageMask = %lu\n", pfd->dwDamageMask); - ErrorF("\n"); -} - -static const char * -visual_class_name(int cls) -{ - switch (cls) { - case GLX_STATIC_COLOR: - return "StaticColor"; - case GLX_PSEUDO_COLOR: - return "PseudoColor"; - case GLX_STATIC_GRAY: - return "StaticGray"; - case GLX_GRAY_SCALE: - return "GrayScale"; - case GLX_TRUE_COLOR: - return "TrueColor"; - case GLX_DIRECT_COLOR: - return "DirectColor"; - default: - return "-none-"; - } -} - -static const char * -swap_method_name(int mthd) -{ - switch (mthd) - { - case GLX_SWAP_EXCHANGE_OML: - return "xchg"; - case GLX_SWAP_COPY_OML: - return "copy"; - case GLX_SWAP_UNDEFINED_OML: - return " "; - default: - return "????"; - } -} - -static void -fbConfigsDump(unsigned int n, __GLXconfig *c) -{ - ErrorF("%d fbConfigs\n", n); - ErrorF("pxf vis fb render Ste aux accum MS drawable Group/\n"); - ErrorF("idx ID ID VisualType Depth Lvl RGB CI DB Swap reo R G B A Z S buf AR AG AB AA bufs num W P Pb Float Trans Caveat\n"); - ErrorF("-----------------------------------------------------------------------------------------------------------------------------\n"); - - while (c != NULL) - { - unsigned int i = ((GLXWinConfig *)c)->pixelFormatIndex; - - ErrorF("%3d %2x %2x " - "%-11s" - " %3d %3d %s %s %s %s %s " - "%2d %2d %2d %2d " - "%2d %2d " - "%2d " - "%2d %2d %2d %2d" - " %2d %2d" - " %s %s %s " - " %s " - " %s " - " %d %s" - "\n", - i, c->visualID, c->fbconfigID, - visual_class_name(c->visualType), - c->rgbBits ? c->rgbBits : c->indexBits, - c->level, - (c->renderType & GLX_RGBA_BIT) ? "y" : ".", - (c->renderType & GLX_COLOR_INDEX_BIT) ? "y" : ".", - c->doubleBufferMode ? "y" : ".", - swap_method_name(c->swapMethod), - c->stereoMode ? "y" : ".", - c->redBits, c->greenBits, c->blueBits, c->alphaBits, - c->depthBits, c->stencilBits, - c->numAuxBuffers, - c->accumRedBits, c->accumGreenBits, c->accumBlueBits, c->accumAlphaBits, - c->sampleBuffers, c->samples, - (c->drawableType & GLX_WINDOW_BIT) ? "y" : ".", - (c->drawableType & GLX_PIXMAP_BIT) ? "y" : ".", - (c->drawableType & GLX_PBUFFER_BIT) ? "y" : ".", - ".", - (c->transparentPixel != GLX_NONE_EXT) ? "y" : ".", - c->visualSelectGroup, (c->visualRating == GLX_SLOW_VISUAL_EXT) ? "*" : " "); - - c = c->next; - } -} -#endif - -/* ---------------------------------------------------------------------- */ -/* - * Forward declarations - */ - -static __GLXscreen *glxWinScreenProbe(ScreenPtr pScreen); -static __GLXcontext *glxWinCreateContext(__GLXscreen *screen, - __GLXconfig *modes, - __GLXcontext *baseShareContext); -static __GLXdrawable *glxWinCreateDrawable(ClientPtr client, - __GLXscreen *screen, - DrawablePtr pDraw, - XID drawId, - int type, - XID glxDrawId, - __GLXconfig *conf); - -static Bool glxWinRealizeWindow(WindowPtr pWin); -static Bool glxWinUnrealizeWindow(WindowPtr pWin); -static Bool glxWinDestroyWindow(WindowPtr pWin); -static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc); -static Bool glxWinPositionWindow(WindowPtr pWindow, int x, int y); - -static HDC glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HWND *hwnd); -static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable *draw); - -static void glxWinCreateConfigs(HDC dc, glxWinScreen *screen); -static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen); -static int fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride); -static int fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen); - -/* ---------------------------------------------------------------------- */ -/* - * The GLX provider - */ - -__GLXprovider __glXWGLProvider = { - glxWinScreenProbe, - "Win32 native WGL", - NULL -}; - -void -glxWinPushNativeProvider(void) -{ - if (g_fNativeGl) - GlxPushProvider(&__glXWGLProvider); -} - -/* ---------------------------------------------------------------------- */ -/* - * Screen functions - */ - -static void -glxWinScreenDestroy(__GLXscreen *screen) -{ - GLWIN_DEBUG_MSG("glxWinScreenDestroy(%p)", screen); - __glXScreenDestroy(screen); - xfree(screen); -} - -static int -glxWinScreenSwapInterval(__GLXdrawable *drawable, int interval) -{ - BOOL ret = wglSwapIntervalEXTWrapper(interval); - if (!ret) - { - ErrorF("wglSwapIntervalEXT interval %d failed:%s\n", interval, glxWinErrorMessage()); - } - return ret; -} - -static LRESULT CALLBACK GlxWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg== WM_NCHITTEST) - { - return HTTRANSPARENT; - } - else - return DefWindowProc(hwnd, uMsg, wParam, lParam); -} - -/* - Report the extensions split and formatted to avoid overflowing a line - */ -static void -glxLogExtensions(const char *prefix, const char *extensions) -{ - int length = 0; - char *strl; - char *str = xalloc(strlen(extensions) + 1); - - if (str == NULL) - { - ErrorF("glxLogExtensions: xalloc error\n"); - return; - } - - str[strlen(extensions)] = '\0'; - strncpy (str, extensions, strlen(extensions)); - - strl = strtok(str, " "); - winDebug("%s%s", prefix, strl); - length = strlen(prefix) + strlen(strl); - - while (1) - { - strl = strtok(NULL, " "); - if (strl == NULL) break; - - if (length + strlen(strl) + 1 > 120) - { - winDebug("\n"); - winDebug("%s",prefix); - length = strlen(prefix); - } - else - { - winDebug(" "); - length++; - } - - winDebug("%s", strl); - length = length + strlen(strl); - } - - winDebug("\n"); - - xfree(str); -} - -/* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */ -static __GLXscreen * -glxWinScreenProbe(ScreenPtr pScreen) -{ - glxWinScreen *screen; - const char *gl_extensions; - const char *wgl_extensions; - HWND hwnd; - HDC hdc; - HGLRC hglrc; - - GLWIN_DEBUG_MSG("glxWinScreenProbe"); - -#ifdef _DEBUG - glxWinInitDebugSettings(); -#endif - - if (pScreen == NULL) - return NULL; - - if (!winCheckScreenAiglxIsSupported(pScreen)) - { - LogMessage(X_ERROR,"AIGLX: No native OpenGL in modes with a root window\n"); - return NULL; - } - - screen = xcalloc(1, sizeof(glxWinScreen)); - - if (NULL == screen) - return NULL; - - /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */ - screen->RealizeWindow = pScreen->RealizeWindow; - pScreen->RealizeWindow = glxWinRealizeWindow; - screen->UnrealizeWindow = pScreen->UnrealizeWindow; - pScreen->UnrealizeWindow = glxWinUnrealizeWindow; - screen->CopyWindow = pScreen->CopyWindow; - pScreen->CopyWindow = glxWinCopyWindow; - screen->PositionWindow = pScreen->PositionWindow; - pScreen->PositionWindow = glxWinPositionWindow; - screen->DestroyWindow = pScreen->DestroyWindow; - pScreen->DestroyWindow = glxWinDestroyWindow; - - /* Dump out some useful information about the native renderer */ - - // create window class - { - static wATOM glTestWndClass = 0; - if (glTestWndClass == 0) - { - WNDCLASSEX wc; - glTestWndClass=1; - wc.cbSize = sizeof(WNDCLASSEX); - wc.style = CS_OWNDC ; - wc.lpfnWndProc = GlxWindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = GetModuleHandle(NULL); - wc.hIcon = 0; - wc.hCursor = 0; - wc.hbrBackground = 0; - wc.lpszMenuName = NULL; - wc.lpszClassName = WIN_GL_WINDOW_CLASS; - wc.hIconSm = 0; - RegisterClassEx (&wc); - } - } - - // create an invisible window for a scratch DC - hwnd = CreateWindowExA(0, - WIN_GL_WINDOW_CLASS, - "XWin GL Renderer Capabilities Test Window", - 0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL); - if (hwnd == NULL) - LogMessage(X_ERROR,"AIGLX: Couldn't create a window for render capabilities testing\n"); - - hdc = GetDC(hwnd); - - // we must set a pixel format before we can create a context, just use the first one... - SetPixelFormat(hdc, 1, NULL); - hglrc = wglCreateContext(hdc); - wglMakeCurrent(hdc, hglrc); - - // initialize wgl extension proc pointers (don't call them before here...) - // (but we need to have a current context for them to be resolvable) - wglResolveExtensionProcs(); - - winDebug("GL_VERSION: %s\n", glGetStringWrapperNonstatic(GL_VERSION)); - winDebug("GL_VENDOR: %s\n", glGetStringWrapperNonstatic(GL_VENDOR)); - winDebug("GL_RENDERER: %s\n", glGetStringWrapperNonstatic(GL_RENDERER)); - gl_extensions = (const char *)glGetStringWrapperNonstatic(GL_EXTENSIONS); - glxLogExtensions("GL_EXTENSIONS: ", gl_extensions); - wgl_extensions = wglGetExtensionsStringARBWrapper(hdc); - if (!wgl_extensions) wgl_extensions = ""; - glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions); - - // Can you see the problem here? The extensions string is DC specific - // Different DCs for windows on a multimonitor system driven by multiple cards - // might have completely different capabilities. Of course, good luck getting - // those screens to be accelerated in XP and earlier... - - { - // testing facility to not use any WGL extensions - char *envptr = getenv("GLWIN_NO_WGL_EXTENSIONS"); - if ((envptr != NULL) && (atoi(envptr) != 0)) - { - ErrorF("GLWIN_NO_WGL_EXTENSIONS is set, ignoring WGL_EXTENSIONS\n"); - wgl_extensions = ""; - } - } - - { - Bool glx_sgi_make_current_read = FALSE; - - // - // Based on the WGL extensions available, enable various GLX extensions - // XXX: make this table-driven ? - // - memset(screen->glx_enable_bits, 0, __GLX_EXT_BYTES); - - __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_visual_info"); - __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_visual_rating"); - __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_import_context"); - __glXEnableExtension(screen->glx_enable_bits, "GLX_OML_swap_method"); - __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIX_fbconfig"); - - if (strstr(wgl_extensions, "WGL_ARB_make_current_read")) - { - __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_make_current_read"); - LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n"); - glx_sgi_make_current_read = TRUE; - } - - if (strstr(gl_extensions, "GL_WIN_swap_hint")) - { - __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer"); - LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n"); - } - - if (strstr(wgl_extensions, "WGL_EXT_swap_control")) - { - __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control"); - __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_swap_control"); - LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n"); - } - -/* // Hmm? screen->texOffset */ -/* if (strstr(wgl_extensions, "WGL_ARB_render_texture")) */ -/* { */ -/* __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_texture_from_pixmap"); */ -/* LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); */ -/* screen->has_WGL_ARB_render_texture = TRUE; */ -/* } */ - - if (strstr(wgl_extensions, "WGL_ARB_pbuffer")) - { - __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIX_pbuffer"); - LogMessage(X_INFO, "AIGLX: enabled GLX_SGIX_pbuffer\n"); - screen->has_WGL_ARB_pbuffer = TRUE; - } - - if (strstr(wgl_extensions, "WGL_ARB_multisample")) - { - __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_multisample"); - __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIS_multisample"); - LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_multisample and GLX_SGIS_multisample\n"); - screen->has_WGL_ARB_multisample = TRUE; - } - - screen->base.destroy = glxWinScreenDestroy; - screen->base.createContext = glxWinCreateContext; - screen->base.createDrawable = glxWinCreateDrawable; - screen->base.swapInterval = glxWinScreenSwapInterval; - screen->base.hyperpipeFuncs = NULL; - screen->base.swapBarrierFuncs = NULL; - screen->base.pScreen = pScreen; - - if (strstr(wgl_extensions, "WGL_ARB_pixel_format")) - { - glxWinCreateConfigsExt(hdc, screen); - screen->has_WGL_ARB_pixel_format = TRUE; - } - else - { - glxWinCreateConfigs(hdc, screen); - screen->has_WGL_ARB_pixel_format = FALSE; - } - // Initializes screen->base.fbconfigs and screen->base.numFBConfigs - - /* These will be set by __glXScreenInit */ - screen->base.visuals = NULL; - screen->base.numVisuals = 0; - - __glXScreenInit(&screen->base, pScreen); - -#ifdef _DEBUG - // dump out fbConfigs now fbConfigIds and visualIDs have been assigned - fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs); -#endif - - // Override the GL extensions string set by __glXScreenInit() - screen->base.GLextensions = xstrdup(gl_extensions); - - // Generate the GLX extensions string (overrides that set by __glXScreenInit()) - { - unsigned int buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL); - if (buffer_size > 0) - { - if (screen->base.GLXextensions != NULL) - { - xfree(screen->base.GLXextensions); - } - - screen->base.GLXextensions = xnfalloc(buffer_size); - __glXGetExtensionString(screen->glx_enable_bits, screen->base.GLXextensions); - } - } - - // - // Override the GLX version (__glXScreenInit() sets it to "1.2") - // if we have all the needed extensionsto operate as a higher version - // - // SGIX_fbconfig && SGIX_pbuffer && SGI_make_current_read -> 1.3 - // ARB_multisample -> 1.4 - // - if (screen->has_WGL_ARB_pbuffer && glx_sgi_make_current_read) - { - xfree(screen->base.GLXversion); - - if (screen->has_WGL_ARB_multisample) - { - screen->base.GLXversion = xstrdup("1.4"); - screen->base.GLXmajor = 1; - screen->base.GLXminor = 4; - } - else - { - screen->base.GLXversion = xstrdup("1.3"); - screen->base.GLXmajor = 1; - screen->base.GLXminor = 3; - } - LogMessage(X_INFO, "AIGLX: Set GLX version to %s\n", screen->base.GLXversion); - } - } - - wglMakeCurrent(NULL, NULL); - wglDeleteContext(hglrc); - ReleaseDC(hwnd, hdc); - DestroyWindow(hwnd); - - return &screen->base; -} - -/* ---------------------------------------------------------------------- */ -/* - * Window functions - */ - -static Bool -glxWinRealizeWindow(WindowPtr pWin) -{ - Bool result; - ScreenPtr pScreen = pWin->drawable.pScreen; - glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen); - winWindowPriv(pWin); - - GLWIN_DEBUG_MSG("glxWinRealizeWindow"); - - /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */ - pScreen->RealizeWindow = screenPriv->RealizeWindow; - result = pScreen->RealizeWindow(pWin); - pScreen->RealizeWindow = glxWinRealizeWindow; - - // Check if ze need to move the window\n - if (pWinPriv->GlCtxWnd && pWinPriv->hWnd) - { - ShowWindow(pWinPriv->hWnd,SW_SHOW); - } - return result; -} - - -static void -glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) -{ - __GLXWinDrawable *pGlxDraw; - ScreenPtr pScreen = pWindow->drawable.pScreen; - glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen); - - GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow); - - dixLookupResourceByType((pointer) &pGlxDraw, pWindow->drawable.id, __glXDrawableRes, - NullClient, DixUnknownAccess); - - - /* - Discard any CopyWindow requests if a GL drawing context is pointing at the window - - For regions which are being drawn by GL, the shadow framebuffer doesn't have the - correct bits, so we wish to avoid shadow framebuffer damage occuring, which will - cause those incorrect bits to be transferred to the display.... - */ - if (pGlxDraw && pGlxDraw->drawContext) - { - GLWIN_DEBUG_MSG("glxWinCopyWindow: discarding"); - return; - } - - GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer"); - - pScreen->CopyWindow = screenPriv->CopyWindow; - pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc); - pScreen->CopyWindow = glxWinCopyWindow; - -} - -static Bool -glxWinPositionWindow(WindowPtr pWin, int x, int y) -{ - Bool result; - ScreenPtr pScreen = pWin->drawable.pScreen; - glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen); - winWindowPriv(pWin); - - pScreen->PositionWindow = screenPriv->PositionWindow; - result = pScreen->PositionWindow(pWin, x, y); - pScreen->PositionWindow = glxWinPositionWindow; - - if (pWinPriv->GlCtxWnd && pWinPriv->hWnd) - { - MoveWindow(pWinPriv->hWnd, - pWin->drawable.x, - pWin->drawable.y, - pWin->drawable.width, - pWin->drawable.height, - FALSE); - } - return result; -} - - -static Bool -glxWinUnrealizeWindow(WindowPtr pWin) -{ - Bool result; - ScreenPtr pScreen = pWin->drawable.pScreen; - glxWinScreen *screenPriv = (glxWinScreen *)glxGetScreen(pScreen); - winWindowPriv(pWin); - - GLWIN_DEBUG_MSG("glxWinUnrealizeWindow"); - - pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow; - result = pScreen->UnrealizeWindow(pWin); - pScreen->UnrealizeWindow = glxWinUnrealizeWindow; - - if (pWinPriv->GlCtxWnd && pWinPriv->hWnd) - ShowWindow(pWinPriv->hWnd,SW_HIDE); - - return result; -} - -static Bool -glxWinDestroyWindow(WindowPtr pWin) -{ - Bool result; - ScreenPtr pScreen = pWin->drawable.pScreen; - glxWinScreen *screenPriv = (glxWinScreen *)glxGetScreen(pScreen); - winWindowPriv(pWin); - - GLWIN_DEBUG_MSG("glxWinDestroyWindow"); - - if (pWinPriv->GlCtxWnd && pWinPriv->hWnd) - { - __GLXWinDrawable *pGlxDraw; - - dixLookupResourceByType((pointer) &pGlxDraw, pWin->drawable.id, __glXDrawableRes, NullClient, DixUnknownAccess); - - if (pGlxDraw && pGlxDraw->drawContext) - { - if (pGlxDraw->drawContext->hwnd!=pWinPriv->hWnd) - ErrorF("Wrong assumption\n"); - glxWinReleaseDC(pGlxDraw->drawContext->hwnd, pGlxDraw->drawContext->hDC, pGlxDraw); - pGlxDraw->drawContext->hDC=NULL; - pGlxDraw->drawContext->hwnd=NULL; - } - DestroyWindow(pWinPriv->hWnd); - pWinPriv->hWnd=NULL; - pWinPriv->GlCtxWnd=0; - } - - pScreen->DestroyWindow = screenPriv->DestroyWindow; - result = pScreen->DestroyWindow(pWin); - pScreen->DestroyWindow = glxWinDestroyWindow; - - return result; -} - -/* ---------------------------------------------------------------------- */ -/* - * Drawable functions - */ - -static GLboolean -glxWinDrawableSwapBuffers(ClientPtr client, __GLXdrawable *base) -{ - BOOL ret; - __GLXWinDrawable *draw = (__GLXWinDrawable *)base; - - /* Swap buffers on the last active context for drawing on the drawable */ - if (draw->drawContext == NULL) - { - GLWIN_TRACE_MSG("glxWinSwapBuffers - no context for drawable"); - return GL_FALSE; - } - - GLWIN_TRACE_MSG("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)", base, draw->drawContext, draw->drawContext->ctx); - - /* - draw->drawContext->base.drawPriv will not be set if the context is not current anymore, - but if it is, it should point to this drawable.... - */ - assert((draw->drawContext->base.drawPriv == NULL) || (draw->drawContext->base.drawPriv == base)); - - ret = SwapBuffers(draw->drawContext->hDC); - - if (!ret) - { - ErrorF("wglSwapBuffers failed: %s\n", glxWinErrorMessage()); - return GL_FALSE; - } - - return GL_TRUE; -} - -static void -glxWinDrawableCopySubBuffer(__GLXdrawable *drawable, - int x, int y, int w, int h) -{ - glAddSwapHintRectWINWrapperNonstatic(x, y, w, h); - glxWinDrawableSwapBuffers(NULL, drawable); -} - -static void -glxWinDrawableDestroy(__GLXdrawable *base) -{ - __GLXWinDrawable *glxPriv = (__GLXWinDrawable *)base; - - if (glxPriv->drawContext && (__glXLastContext == &((glxPriv->drawContext)->base))) - { - // if this context is current and has unflushed commands, say we have flushed them - // (don't actually flush them, the window is going away anyhow, and an implict flush occurs - // on the next context change) - // (GLX core considers it an error when we try to select a new current context if the old one - // has unflushed commands, but the window has disappeared..) - __GLX_NOTE_FLUSHED_CMDS(__glXLastContext); - __glXLastContext = NULL; - } - - if (glxPriv->hPbuffer) - if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer)) - { - ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage()); - } - - if (glxPriv->dibDC) - { - // restore the default DIB - SelectObject(glxPriv->dibDC, glxPriv->hOldDIB); - - if (!DeleteDC(glxPriv->dibDC)) - { - ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage()); - } - } - - if (glxPriv->hDIB) - { - if (!DeleteObject(glxPriv->hDIB)) - { - ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage()); - } - - ((PixmapPtr)glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits; - } - - GLWIN_DEBUG_MSG("glxWinDestroyDrawable"); - xfree(glxPriv); -} - -static __GLXdrawable * -glxWinCreateDrawable(ClientPtr client, - __GLXscreen *screen, - DrawablePtr pDraw, - XID drawId, - int type, - XID glxDrawId, - __GLXconfig *conf) -{ - __GLXWinDrawable *glxPriv; - - glxPriv = xcalloc(1,sizeof(*glxPriv)); - - if (glxPriv == NULL) - return NULL; - - if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, glxDrawId, conf)) { - xfree(glxPriv); - return NULL; - } - - glxPriv->base.destroy = glxWinDrawableDestroy; - glxPriv->base.swapBuffers = glxWinDrawableSwapBuffers; - glxPriv->base.copySubBuffer = glxWinDrawableCopySubBuffer; - // glxPriv->base.waitX what are these for? - // glxPriv->base.waitGL - - GLWIN_DEBUG_MSG("glxWinCreateDrawable %p", glxPriv); - - return &glxPriv->base; -} - -/* ---------------------------------------------------------------------- */ -/* - * Texture functions - */ - -static -int glxWinBindTexImage(__GLXcontext *baseContext, - int buffer, - __GLXdrawable *pixmap) -{ - ErrorF("glxWinBindTexImage: not implemented\n"); - return FALSE; -} - -static -int glxWinReleaseTexImage(__GLXcontext *baseContext, - int buffer, - __GLXdrawable *pixmap) -{ - ErrorF(" glxWinReleaseTexImage: not implemented\n"); - return FALSE; -} - -/* ---------------------------------------------------------------------- */ -/* - * Lazy update context implementation - * - * WGL contexts are created for a specific HDC, so we cannot create the WGL - * context in glxWinCreateContext(), we must defer creation until the context - * is actually used on a specifc drawable which is connected to a native window, - * pbuffer or DIB - * - * The WGL context may be used on other, compatible HDCs, so we don't need to - * recreate it for every new native window - * - * XXX: I wonder why we can't create the WGL context on the screen HDC ? - * Basically we assume all HDCs are compatible at the moment: if they are not - * we are in a muddle, there was some code in the old implementation to attempt - * to transparently migrate a context to a new DC by copying state and sharing - * lists with the old one... - */ - -static void -glxWinSetPixelFormat(__GLXWinContext *gc, HDC hdc, int bppOverride, int drawableTypeOverride) -{ - __GLXscreen *screen = gc->base.pGlxScreen; - glxWinScreen *winScreen = (glxWinScreen *)screen; - - __GLXconfig *config = gc->base.config; - GLXWinConfig *winConfig = (GLXWinConfig *)config; - - GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d", winConfig->pixelFormatIndex); - - /* - Normally, we can just use the the pixelFormatIndex corresponding - to the fbconfig which has been specified by the client - */ - - if (!((bppOverride && (bppOverride != (config->redBits + config->greenBits + config->blueBits) )) - || ((config->drawableType & drawableTypeOverride) == 0))) - { - if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL)) - { - ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); - return; - } - - return; - } - - /* - However, in certain special cases this pixel format will be incompatible with the - use we are going to put it to, so we need to re-evaluate the pixel format to use: - - 1) When PFD_DRAW_TO_BITMAP is set, ChoosePixelFormat() always returns a format with - the cColorBits we asked for, so we need to ensure it matches the bpp of the bitmap - - 2) Applications may assume that visuals selected with glXChooseVisual() work with - pixmap drawables (there is no attribute to explicitly query for pixmap drawable - support as there is for glXChooseFBConfig()) - (it's arguable this is an error in the application, but we try to make it work) - - pixmap rendering is always slow for us, so we don't want to choose those visuals - by default, but if the actual drawable type we're trying to select the context - on (drawableTypeOverride) isn't supported by the selected fbConfig, reconsider - and see if we can find a suitable one... - */ - ErrorF("glxWinSetPixelFormat: having second thoughts: cColorbits %d, bppOveride %d; config->drawableType %d, drawableTypeOverride %d\n", - (config->redBits + config->greenBits + config->blueBits), bppOverride, config->drawableType, drawableTypeOverride); - - if (!winScreen->has_WGL_ARB_pixel_format) - { - PIXELFORMATDESCRIPTOR pfd; - int pixelFormat; - - /* convert fbConfig to PFD */ - if (fbConfigToPixelFormat(gc->base.config, &pfd, drawableTypeOverride)) - { - ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n"); - return; - } - -#ifdef _DEBUG - if (glxWinDebugSettings.dumpPFD) - pfdOut(&pfd); -#endif - - if (bppOverride) - { - GLWIN_DEBUG_MSG("glxWinSetPixelFormat: Forcing bpp from %d to %d\n", pfd.cColorBits, bppOverride); - pfd.cColorBits = bppOverride; - } - - pixelFormat = ChoosePixelFormat(hdc, &pfd); - if (pixelFormat == 0) - { - ErrorF("ChoosePixelFormat error: %s\n", glxWinErrorMessage()); - return; - } - - GLWIN_DEBUG_MSG("ChoosePixelFormat: chose pixelFormatIndex %d", pixelFormat); - ErrorF("ChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", pixelFormat, winConfig->pixelFormatIndex); - - if (!SetPixelFormat(hdc, pixelFormat, &pfd)) - { - ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); - return; - } - } - else - { - int pixelFormat = fbConfigToPixelFormatIndex(hdc, gc->base.config, drawableTypeOverride, winScreen); - if (pixelFormat == 0) - { - ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage()); - return; - } - - GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d", pixelFormat); - ErrorF("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", pixelFormat, winConfig->pixelFormatIndex); - - if (!SetPixelFormat(hdc, pixelFormat, NULL)) - { - ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); - return; - } - } -} - -static HDC -glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HWND *hwnd) -{ - HDC hdc = NULL; - *hwnd = NULL; - - if (draw == NULL) - { - GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc, gc->ctx); - return NULL; - } - - switch (draw->base.type) - { - case GLX_DRAWABLE_WINDOW: - { - WindowPtr pWin; - - pWin = (WindowPtr) draw->base.pDraw; - if (pWin == NULL) - { - GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin); - return NULL; - } - - *hwnd = winGetWindowInfo(pWin); - - if (*hwnd == NULL) - { - ErrorF("No HWND error: %s\n", glxWinErrorMessage()); - return NULL; - } - - hdc = GetDC(*hwnd); - - if (hdc == NULL) - ErrorF("GetDC error: %s: hwnd %x, gc %p, gc->ctx %p ,gc->hwnd %p\n", glxWinErrorMessage(), *hwnd, gc, gc->ctx, gc->hwnd); - - if (gc->hDC) - { - glxWinReleaseDC(gc->hwnd, gc->hDC, draw); - gc->hDC=NULL; - } -#ifdef _DEBUG - if (glxWinDebugSettings.enableTrace) - GLWIN_DEBUG_HWND(*hwnd); - - GLWIN_TRACE_MSG("for context %p (native ctx %p), hWnd changed from %p to %p", gc, gc->ctx, gc->hwnd, *hwnd); -#endif - gc->hwnd = *hwnd; - - /* Check if we need to set the pixelformat */ - { - winWindowPriv(pWin); - if (!pWinPriv->PixelFormatSet) - { - pWinPriv->PixelFormatSet=TRUE; - /* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */ - glxWinSetPixelFormat(gc, hdc, 0, GLX_WINDOW_BIT); - } - } - } - break; - - case GLX_DRAWABLE_PBUFFER: - { - hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer); - - if (hdc == NULL) - ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage()); - } - break; - - case GLX_DRAWABLE_PIXMAP: - { - hdc = draw->dibDC; -#ifdef _DEBUG - if (glxWinDebugSettings.dumpDC) - GLWIN_DEBUG_MSG("Got PIXMAP HDC %p for window %p", hdc, *hwnd); -#endif - } - break; - - default: - { - ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n", draw->base.type); - } - } - -#ifdef _DEBUG - if (glxWinDebugSettings.dumpDC) - GLWIN_HDC_DEBUG_MSG("Got HDC %p for window %p", hdc, *hwnd); -#endif - - return hdc; -} - -static void -glxWinReleaseDC(HWND hwnd, HDC hdc,__GLXWinDrawable *draw) -{ - switch (draw->base.type) - { - case GLX_DRAWABLE_WINDOW: - { - ReleaseDC(hwnd, hdc); - } - break; - - case GLX_DRAWABLE_PBUFFER: - { - if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc)) - { - ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage()); - } - } - break; - - case GLX_DRAWABLE_PIXMAP: - { - // don't release DC, the memory DC lives as long as the bitmap - - // We must ensure that all GDI drawing into the bitmap has completed - // in case we subsequently access the bits from it - GdiFlush(); - } - break; - - default: - { - ErrorF("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n", draw->base.type); - } - } -} - -static void -glxWinDeferredCreateContext(__GLXWinContext *gc, __GLXWinDrawable *draw) -{ - HWND hwnd; - GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attach context %p to drawable %p", gc, draw); - - switch (draw->base.type) - { - case GLX_DRAWABLE_WINDOW: - { - WindowPtr pWin = (WindowPtr) draw->base.pDraw; - - if (!(gc->base.config->drawableType & GLX_WINDOW_BIT)) - { - ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable\n"); - } - - if (pWin == NULL) - { - GLWIN_DEBUG_MSG("Deferring until X window is created"); - return; - } - - GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pWin %p", pWin); - - if (winGetWindowInfo(pWin) == NULL) - { - GLWIN_DEBUG_MSG("Deferring until native window is created"); - return; - } - } - break; - - case GLX_DRAWABLE_PBUFFER: - { - if (draw->hPbuffer == NULL) - { - __GLXscreen *screen; - glxWinScreen *winScreen; - int pixelFormat; - // XXX: which DC are supposed to use??? - HDC screenDC = GetDC(NULL); - - if (!(gc->base.config->drawableType & GLX_PBUFFER_BIT)) - { - ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable\n"); - } - - screen = gc->base.pGlxScreen; - winScreen = (glxWinScreen *)screen; - - pixelFormat = fbConfigToPixelFormatIndex(screenDC, gc->base.config, GLX_DRAWABLE_PBUFFER, winScreen); - if (pixelFormat == 0) - { - ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage()); - return; - } - - draw->hPbuffer = wglCreatePbufferARBWrapper(screenDC, pixelFormat, draw->base.pDraw->width, draw->base.pDraw->height, NULL); - ReleaseDC(NULL, screenDC); - - if (draw->hPbuffer == NULL) - { - ErrorF("wglCreatePbufferARBWrapper error: %s\n", glxWinErrorMessage()); - return; - } - - GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pBuffer %p created for drawable %p", draw->hPbuffer, draw); - } - } - break; - - case GLX_DRAWABLE_PIXMAP: - { - if (draw->dibDC == NULL) - { - BITMAPINFOHEADER bmpHeader; - void *pBits; - - memset (&bmpHeader, 0, sizeof(BITMAPINFOHEADER)); - bmpHeader.biSize = sizeof(BITMAPINFOHEADER); - bmpHeader.biWidth = draw->base.pDraw->width; - bmpHeader.biHeight = draw->base.pDraw->height; - bmpHeader.biPlanes = 1; - bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel; - bmpHeader.biCompression = BI_RGB; - - if (!(gc->base.config->drawableType & GLX_PIXMAP_BIT)) - { - ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n"); - } - - draw->dibDC = CreateCompatibleDC(NULL); - if (draw->dibDC == NULL) - { - ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage()); - return; - } - - draw->hDIB = CreateDIBSection(draw->dibDC, (BITMAPINFO *)&bmpHeader, DIB_RGB_COLORS, &pBits, 0, 0); - if (draw->dibDC == NULL) - { - ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage()); - return; - } - - // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to - // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits - // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are - // even compatible ... - draw->pOldBits = ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr; - ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr = pBits; - - // Select the DIB into the DC - draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB); - if (!draw->hOldDIB) - { - ErrorF("SelectObject error: %s\n", glxWinErrorMessage()); - } - - // Set the pixel format of the bitmap - glxWinSetPixelFormat(gc, draw->dibDC, draw->base.pDraw->bitsPerPixel, GLX_PIXMAP_BIT); - - GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p", draw->hDIB, draw); - } - } - break; - - default: - { - ErrorF("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", draw->base.type); - return; - } - } - - gc->hDC = glxWinMakeDC(gc, draw, &hwnd); - gc->ctx = wglCreateContext(gc->hDC); - - if (gc->ctx == NULL) - { - glxWinReleaseDC(hwnd, gc->hDC, draw); - gc->hDC=0; - - ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage()); - return; - } - - GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p", gc, gc->ctx, draw); - - // if the native context was created successfully, shareLists if needed - if (gc->ctx && gc->shareContext) - { - GLWIN_DEBUG_MSG("glxWinCreateContextReal shareLists with context %p (native ctx %p)", gc->shareContext, gc->shareContext->ctx); - - if (!wglShareLists(gc->shareContext->ctx, gc->ctx)) - { - ErrorF("wglShareLists error: %s\n", glxWinErrorMessage()); - } - } -} - -/* ---------------------------------------------------------------------- */ -/* - * Context functions - */ - - -/* Context manipulation routines should return TRUE on success, FALSE on failure */ -static int -glxWinContextMakeCurrent(__GLXcontext *base) -{ - __GLXWinContext *gc = (__GLXWinContext *)base; - BOOL ret; - __GLXWinDrawable *drawPriv; - -#ifdef _DEBUG - GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc, gc->ctx); - glWinCallDelta(); -#endif - - /* Keep a note of the last active context in the drawable */ - drawPriv = (__GLXWinDrawable *)gc->base.drawPriv; - drawPriv->drawContext = gc; - - if (gc->ctx == NULL) - { - glxWinDeferredCreateContext(gc, drawPriv); - } - - if (gc->ctx == NULL) - { - ErrorF("glxWinContextMakeCurrent: Native context is NULL\n"); - return FALSE; - } - - if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv)) - { - // XXX: should only occur with WGL_ARB_make_current_read - /* - If there is a separate read drawable, create a separate read DC, and - use the wglMakeContextCurrent extension to make the context current drawing - to one DC and reading from the other - */ - gc->hreadDC = glxWinMakeDC(gc, (__GLXWinDrawable *)gc->base.readPriv, &gc->hreadwnd); - if (gc->hreadDC == NULL) - { - ErrorF("glxWinMakeDC failed for readDC\n"); - return FALSE; - } - - ret = wglMakeContextCurrentARBWrapper(gc->hDC, gc->hreadDC, gc->ctx); - if (!ret) - { - ErrorF("wglMakeContextCurrentARBWrapper error: %s\n", glxWinErrorMessage()); - } - } - else - { - /* Otherwise, just use wglMakeCurrent */ - if (!gc->hDC) - { - /* It probably has been release by loseCurrent, so create it again */ - gc->hDC = glxWinMakeDC(gc, drawPriv, &gc->hwnd); - } - ret = wglMakeCurrent(gc->hDC, gc->ctx); - if (!ret) - { - DWORD ErrorCode=GetLastError(); - ErrorF("wglMakeCurrent error: %x dc %p ctx %p\n", ErrorCode,gc->hDC,gc->ctx); - if (!ErrorCode) - { - ErrorF("Error code was 0, assuming no error.\n"); - ret=TRUE; - } - } - } - - // apparently make current could fail if the context is current in a different thread, - // but that shouldn't be able to happen in the current server... - - return ret; -} - -static int -glxWinContextLoseCurrent(__GLXcontext *base) -{ - BOOL ret=TRUE; - __GLXWinContext *gc = (__GLXWinContext *)base; - -#ifdef _DEBUG - GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc, gc->ctx); - glWinCallDelta(); -#endif - - - if (wglGetCurrentContext()==gc->ctx) - { - /* Only do this when we are sure we are currently the active, otherwise we are deactivating the wrong one (this is happening!!!) */ - ret = wglMakeCurrent(NULL, NULL); - if (!ret) - ErrorF("glxWinContextLoseCurrent error: %s\n", glxWinErrorMessage()); - } - else - { - return FALSE; - } - - /* Since drawPriv is going to be set to zero in the context, we have to release the DC to */ - if (gc->hDC && gc->base.drawPriv) glxWinReleaseDC(gc->hwnd, gc->hDC, (__GLXWinDrawable *)gc->base.drawPriv); - if (gc->hreadDC && gc->base.readPriv) glxWinReleaseDC(gc->hreadwnd, gc->hreadDC, (__GLXWinDrawable *)gc->base.readPriv); - gc->hDC=NULL; - gc->hreadDC=NULL; - - base->isCurrent=FALSE; /* It looks like glx is not doing this */ - - return ret; -} - -static int -glxWinContextCopy(__GLXcontext *dst_base, __GLXcontext *src_base, unsigned long mask) -{ - __GLXWinContext *dst = (__GLXWinContext *)dst_base; - __GLXWinContext *src = (__GLXWinContext *)src_base; - BOOL ret; - - GLWIN_DEBUG_MSG("glxWinContextCopy"); - - ret = wglCopyContext(src->ctx, dst->ctx, mask); - if (!ret) - { - ErrorF("wglCopyContext error: %s\n", glxWinErrorMessage()); - } - - return ret; -} - -static int -glxWinContextForceCurrent(__GLXcontext *base) -{ - /* wglMakeCurrent always flushes the previous context, so this is equivalent to glxWinContextMakeCurrent */ - return glxWinContextMakeCurrent(base); -} - -static void -glxWinContextDestroy(__GLXcontext *base) -{ - __GLXWinContext *gc = (__GLXWinContext *)base; - - if (gc != NULL) - { - GLWIN_DEBUG_MSG("GLXcontext %p destroyed (native ctx %p)", base, gc->ctx); - - if (gc->ctx) - { - BOOL ret; - /* It's bad style to delete the context while it's still current */ - if (wglGetCurrentContext() == gc->ctx) - { - wglMakeCurrent(NULL, NULL); - } - - ret = wglDeleteContext(gc->ctx); - if (!ret) - ErrorF("wglDeleteContext error: %s\n", glxWinErrorMessage()); - if (gc->base.drawPriv && gc->hDC) glxWinReleaseDC(gc->hwnd, gc->hDC, (__GLXWinDrawable *)gc->base.drawPriv); - if (gc->base.readPriv && gc->hreadDC) glxWinReleaseDC(gc->hreadwnd, gc->hreadDC, (__GLXWinDrawable *)gc->base.readPriv); - gc->hDC=NULL; - gc->hreadDC=NULL; - gc->ctx = NULL; - } - - xfree(gc); - } -} - -static __GLXcontext * -glxWinCreateContext(__GLXscreen *screen, - __GLXconfig *modes, - __GLXcontext *baseShareContext) -{ - __GLXWinContext *context; - __GLXWinContext *shareContext = (__GLXWinContext *)baseShareContext; - - static __GLXtextureFromPixmap glxWinTextureFromPixmap = - { - glxWinBindTexImage, - glxWinReleaseTexImage - }; - - context = (__GLXWinContext *)xcalloc(1, sizeof(__GLXWinContext)); - - if (!context) - return NULL; - - memset(context, 0, sizeof *context); - context->base.destroy = glxWinContextDestroy; - context->base.makeCurrent = glxWinContextMakeCurrent; - context->base.loseCurrent = glxWinContextLoseCurrent; - context->base.copy = glxWinContextCopy; - context->base.forceCurrent = glxWinContextForceCurrent; - context->base.textureFromPixmap = &glxWinTextureFromPixmap; - context->base.config = modes; - context->base.pGlxScreen = screen; - - // actual native GL context creation is deferred until attach() - //context->ctx = NULL; already done with memset - context->shareContext = shareContext; - - glWinSetupDispatchTable(); - - GLWIN_DEBUG_MSG("GLXcontext %p created", context); - - return &(context->base); -} - -/* ---------------------------------------------------------------------- */ -/* - * Utility functions - */ - -static int -fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride) -{ - PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ - 1, /* version number */ - PFD_SUPPORT_OPENGL, /* support OpenGL */ - PFD_TYPE_RGBA, /* RGBA type */ - 24, /* 24-bit color depth */ - 0, 0, 0, 0, 0, 0, /* color bits ignored */ - 0, /* no alpha buffer */ - 0, /* shift bit ignored */ - 0, /* no accumulation buffer */ - 0, 0, 0, 0, /* accum bits ignored */ - 32, /* 32-bit z-buffer */ - 0, /* no stencil buffer */ - 0, /* no auxiliary buffer */ - PFD_MAIN_PLANE, /* main layer */ - 0, /* reserved */ - 0, 0, 0 /* layer masks ignored */ - }; - - if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT) - pfd.dwFlags |= PFD_DRAW_TO_WINDOW; /* support window */ - - if ((mode->drawableType | drawableTypeOverride) & GLX_PIXMAP_BIT) - pfd.dwFlags |= (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI); /* supports software rendering to bitmap */ - - if (mode->stereoMode) { - pfd.dwFlags |= PFD_STEREO; - } - if (mode->doubleBufferMode) { - pfd.dwFlags |= PFD_DOUBLEBUFFER; - } - - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = mode->redBits + mode->greenBits + mode->blueBits; - pfd.cRedBits = mode->redBits; - pfd.cRedShift = 0; /* FIXME */ - pfd.cGreenBits = mode->greenBits; - pfd.cGreenShift = 0; /* FIXME */ - pfd.cBlueBits = mode->blueBits; - pfd.cBlueShift = 0; /* FIXME */ - pfd.cAlphaBits = mode->alphaBits; - pfd.cAlphaShift = 0; /* FIXME */ - - pfd.cAccumBits = mode->accumRedBits + mode->accumGreenBits + mode->accumBlueBits + mode->accumAlphaBits; - pfd.cAccumRedBits = mode->accumRedBits; - pfd.cAccumGreenBits = mode->accumGreenBits; - pfd.cAccumBlueBits = mode->accumBlueBits; - pfd.cAccumAlphaBits = mode->accumAlphaBits; - - pfd.cDepthBits = mode->depthBits; - pfd.cStencilBits = mode->stencilBits; - pfd.cAuxBuffers = mode->numAuxBuffers; - - /* mode->level ? */ - /* mode->pixmapMode ? */ - - *pfdret = pfd; - - return 0; -} - -#define SET_ATTR_VALUE(attr, value) { attribList[i++] = attr; attribList[i++] = value; assert(i < NUM_ELEMENTS(attribList)); } - -static int -fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen) -{ - UINT numFormats; - unsigned int i = 0; - - /* convert fbConfig to attr-value list */ - int attribList[60]; - - SET_ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, TRUE); - SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, (mode->visualType == GLX_TRUE_COLOR) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB); - SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, (mode->visualType == GLX_TRUE_COLOR) ? mode->rgbBits : mode->indexBits); - SET_ATTR_VALUE(WGL_RED_BITS_ARB, mode->redBits); - SET_ATTR_VALUE(WGL_GREEN_BITS_ARB, mode->greenBits); - SET_ATTR_VALUE(WGL_BLUE_BITS_ARB, mode->blueBits); - SET_ATTR_VALUE(WGL_ALPHA_BITS_ARB, mode->alphaBits); - SET_ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, mode->accumRedBits); - SET_ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, mode->accumGreenBits); - SET_ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, mode->accumBlueBits); - SET_ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, mode->accumAlphaBits); - SET_ATTR_VALUE(WGL_DEPTH_BITS_ARB, mode->depthBits); - SET_ATTR_VALUE(WGL_STENCIL_BITS_ARB, mode->stencilBits); - SET_ATTR_VALUE(WGL_AUX_BUFFERS_ARB, mode->numAuxBuffers); - - if (mode->doubleBufferMode) - SET_ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, TRUE); - - if (mode->stereoMode) - SET_ATTR_VALUE(WGL_STEREO_ARB, TRUE); - - // Some attributes are only added to the list if the value requested is not 'don't care', as exactly matching that is daft.. - if (mode->swapMethod == GLX_SWAP_EXCHANGE_OML) - SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB); - - if (mode->swapMethod == GLX_SWAP_COPY_OML) - SET_ATTR_VALUE(WGL_SWAP_COPY_ARB, TRUE); - - // XXX: this should probably be the other way around, but that messes up drawableTypeOverride - if (mode->visualRating == GLX_SLOW_VISUAL_EXT) - SET_ATTR_VALUE(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB); - - // must support all the drawable types the mode supports - if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT) - SET_ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB,TRUE); - - // XXX: this is a horrible hacky heuristic, in fact this whole drawableTypeOverride thing is a bad idea - // try to avoid asking for formats which don't exist (by not asking for all when adjusting the config to include the drawableTypeOverride) - if (drawableTypeOverride == GLX_WINDOW_BIT) - { - if (mode->drawableType & GLX_PIXMAP_BIT) - SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE); - - if (mode->drawableType & GLX_PBUFFER_BIT) - if (winScreen->has_WGL_ARB_pbuffer) - SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE); - } - else - { - if (drawableTypeOverride & GLX_PIXMAP_BIT) - SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE); - - if (drawableTypeOverride & GLX_PBUFFER_BIT) - if (winScreen->has_WGL_ARB_pbuffer) - SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE); - } - - SET_ATTR_VALUE(0, 0); // terminator - - /* choose the first match */ - { - int pixelFormatIndex; - - if (!wglChoosePixelFormatARBWrapper(hdc, attribList, NULL, 1, &pixelFormatIndex, &numFormats)) - { - ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage()); - } - else - { - if (numFormats > 0) - { - GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d)", pixelFormatIndex); - return pixelFormatIndex; - } - else - ErrorF("wglChoosePixelFormat couldn't decide\n"); - } - } - - return 0; -} - -/* ---------------------------------------------------------------------- */ - -#define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask)) - -// -// Create the GLXconfigs using DescribePixelFormat() -// -static void -glxWinCreateConfigs(HDC hdc, glxWinScreen *screen) -{ - GLXWinConfig *c, *result, *prev = NULL; - int numConfigs = 0; - int i = 0; - int n = 0; - PIXELFORMATDESCRIPTOR pfd; - - GLWIN_DEBUG_MSG("glxWinCreateConfigs"); - - screen->base.numFBConfigs = 0; - screen->base.fbconfigs = NULL; - - // get the number of pixelformats - numConfigs = DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL); - GLWIN_DEBUG_MSG("DescribePixelFormat says %d possible pixel formats", numConfigs); - - /* alloc */ - result = xalloc(sizeof(GLXWinConfig) * numConfigs); - - if (NULL == result) - { - return; - } - - memset(result, 0, sizeof(GLXWinConfig) * numConfigs); - n = 0; - - /* fill in configs */ - for (i = 0; i < numConfigs; i++) - { - int rc; - - c = &(result[i]); - c->base.next = NULL; - c->pixelFormatIndex = i+1; - - rc = DescribePixelFormat(hdc, i+1, sizeof(PIXELFORMATDESCRIPTOR), &pfd); - - if (!rc) - { - ErrorF("DescribePixelFormat failed for index %d, error %s\n", i+1, glxWinErrorMessage()); - break; - } - -#ifdef _DEBUG - if (glxWinDebugSettings.dumpPFD) - pfdOut(&pfd); -#endif - - if (!(pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP)) || !(pfd.dwFlags & PFD_SUPPORT_OPENGL)) - { - GLWIN_DEBUG_MSG("pixelFormat %d has unsuitable flags 0x%08lx, skipping", i+1, pfd.dwFlags); - continue; - } - - c->base.doubleBufferMode = (pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE; - c->base.stereoMode = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE; - - c->base.redBits = pfd.cRedBits; - c->base.greenBits = pfd.cGreenBits; - c->base.blueBits = pfd.cBlueBits; - c->base.alphaBits = pfd.cAlphaBits; - - c->base.redMask = BITS_AND_SHIFT_TO_MASK(pfd.cRedBits, pfd.cRedShift); - c->base.greenMask = BITS_AND_SHIFT_TO_MASK(pfd.cGreenBits, pfd.cGreenShift); - c->base.blueMask = BITS_AND_SHIFT_TO_MASK(pfd.cBlueBits, pfd.cBlueShift); - c->base.alphaMask = BITS_AND_SHIFT_TO_MASK(pfd.cAlphaBits, pfd.cAlphaShift); - - c->base.rgbBits = pfd.cColorBits; - - if (pfd.iPixelType == PFD_TYPE_COLORINDEX) - { - c->base.indexBits = pfd.cColorBits; - } - else - { - c->base.indexBits = 0; - } - - c->base.accumRedBits = pfd.cAccumRedBits; - c->base.accumGreenBits = pfd.cAccumGreenBits; - c->base.accumBlueBits = pfd.cAccumBlueBits; - c->base.accumAlphaBits = pfd.cAccumAlphaBits; - // pfd.cAccumBits; - - c->base.depthBits = pfd.cDepthBits; - c->base.stencilBits = pfd.cStencilBits; - c->base.numAuxBuffers = pfd.cAuxBuffers; - - // pfd.iLayerType; // ignored - c->base.level = 0; - // pfd.dwLayerMask; // ignored - // pfd.dwDamageMask; // ignored - - c->base.pixmapMode = 0; - c->base.visualID = -1; // will be set by __glXScreenInit() - - /* EXT_visual_rating / GLX 1.2 */ - if (pfd.dwFlags & PFD_GENERIC_FORMAT) - { - c->base.visualRating = GLX_SLOW_VISUAL_EXT; - } - else - { - // PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated... - c->base.visualRating = GLX_NONE_EXT; - } - - /* EXT_visual_info / GLX 1.2 */ - if (pfd.iPixelType == PFD_TYPE_COLORINDEX) - { - c->base.visualType = GLX_STATIC_COLOR; - } - else - { - c->base.visualType = GLX_TRUE_COLOR; - } - - // pfd.dwVisibleMask; ??? - c->base.transparentPixel = GLX_NONE; - c->base.transparentRed = GLX_NONE; - c->base.transparentGreen = GLX_NONE; - c->base.transparentBlue = GLX_NONE; - c->base.transparentAlpha = GLX_NONE; - c->base.transparentIndex = GLX_NONE; - - /* ARB_multisample / SGIS_multisample */ - c->base.sampleBuffers = 0; - c->base.samples = 0; - - /* SGIX_fbconfig / GLX 1.3 */ - c->base.drawableType = (((pfd.dwFlags & PFD_DRAW_TO_WINDOW) ? GLX_WINDOW_BIT : 0) - | ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) ? GLX_PIXMAP_BIT : 0)); - - if (pfd.iPixelType == PFD_TYPE_COLORINDEX) - { - c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT; - } - else - { - c->base.renderType = GLX_RGBA_BIT; - } - - c->base.xRenderable = GL_TRUE; - c->base.fbconfigID = -1; // will be set by __glXScreenInit() - - /* SGIX_pbuffer / GLX 1.3 */ - // XXX: How can we find these values out ??? - c->base.maxPbufferWidth = -1; - c->base.maxPbufferHeight = -1; - c->base.maxPbufferPixels = -1; - c->base.optimalPbufferWidth = 0; // there is no optimal value - c->base.optimalPbufferHeight = 0; - - /* SGIX_visual_select_group */ - // arrange for visuals with the best acceleration to be preferred in selection - switch (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) - { - case 0: - c->base.visualSelectGroup = 2; - break; - - case PFD_GENERIC_ACCELERATED: - c->base.visualSelectGroup = 1; - break; - - case PFD_GENERIC_FORMAT: - c->base.visualSelectGroup = 0; - break; - - default: - ; - // "can't happen" - } - - /* OML_swap_method */ - if (pfd.dwFlags & PFD_SWAP_EXCHANGE) - c->base.swapMethod = GLX_SWAP_EXCHANGE_OML; - else if (pfd.dwFlags & PFD_SWAP_COPY) - c->base.swapMethod = GLX_SWAP_COPY_OML; - else - c->base.swapMethod = GLX_SWAP_UNDEFINED_OML; - - /* EXT_import_context */ - c->base.screen = screen->base.pScreen->myNum; - - /* EXT_texture_from_pixmap */ - c->base.bindToTextureRgb = -1; - c->base.bindToTextureRgba = -1; - c->base.bindToMipmapTexture = -1; - c->base.bindToTextureTargets = -1; - c->base.yInverted = -1; - - n++; - - // update previous config to point to this config - if (prev) - prev->base.next = &(c->base); - - prev = c; - } - - GLWIN_DEBUG_MSG("found %d pixelFormats suitable for conversion to fbConfigs", n); - - screen->base.numFBConfigs = n; - screen->base.fbconfigs = &(result->base); -} - -// helper function to access an attribute value from an attribute value array by attribute -static -int getAttrValue(const int attrs[], int values[], unsigned int num, int attr, int fallback) -{ - unsigned int i; - for (i = 0; i < num; i++) - { - if (attrs[i] == attr) - { - GLWIN_TRACE_MSG("getAttrValue attr 0x%x, value %d", attr, values[i]); - return values[i]; - } - } - - ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n", attr, fallback); - return fallback; -} - -// -// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension -// -static void -glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen) -{ - GLXWinConfig *c, *result, *prev = NULL; - int i = 0; - int n = 0; - - const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB; - int numConfigs; - - int attrs[50]; - unsigned int num_attrs = 0; - - GLWIN_DEBUG_MSG("glxWinCreateConfigsExt"); - - screen->base.numFBConfigs = 0; - screen->base.fbconfigs = NULL; - - if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs)) - { - ErrorF("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n", glxWinErrorMessage()); - return; - } - - GLWIN_DEBUG_MSG("wglGetPixelFormatAttribivARB says %d possible pixel formats", numConfigs); - - /* alloc */ - result = xalloc(sizeof(GLXWinConfig) * numConfigs); - - if (NULL == result) - { - return; - } - - memset(result, 0, sizeof(GLXWinConfig) * numConfigs); - n = 0; - -#define ADD_ATTR(a) { attrs[num_attrs++] = a; assert(num_attrs < NUM_ELEMENTS(attrs)); } - - ADD_ATTR(WGL_DRAW_TO_WINDOW_ARB); - ADD_ATTR(WGL_DRAW_TO_BITMAP_ARB); - ADD_ATTR(WGL_ACCELERATION_ARB); - ADD_ATTR(WGL_SWAP_LAYER_BUFFERS_ARB); - ADD_ATTR(WGL_NUMBER_OVERLAYS_ARB); - ADD_ATTR(WGL_NUMBER_UNDERLAYS_ARB); - ADD_ATTR(WGL_TRANSPARENT_ARB); - ADD_ATTR(WGL_TRANSPARENT_RED_VALUE_ARB); - ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB); - ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB); - ADD_ATTR(WGL_TRANSPARENT_ALPHA_VALUE_ARB); - ADD_ATTR(WGL_SUPPORT_OPENGL_ARB); - ADD_ATTR(WGL_DOUBLE_BUFFER_ARB); - ADD_ATTR(WGL_STEREO_ARB); - ADD_ATTR(WGL_PIXEL_TYPE_ARB); - ADD_ATTR(WGL_COLOR_BITS_ARB); - ADD_ATTR(WGL_RED_BITS_ARB); - ADD_ATTR(WGL_RED_SHIFT_ARB); - ADD_ATTR(WGL_GREEN_BITS_ARB); - ADD_ATTR(WGL_GREEN_SHIFT_ARB); - ADD_ATTR(WGL_BLUE_BITS_ARB); - ADD_ATTR(WGL_BLUE_SHIFT_ARB); - ADD_ATTR(WGL_ALPHA_BITS_ARB); - ADD_ATTR(WGL_ALPHA_SHIFT_ARB); - ADD_ATTR(WGL_ACCUM_RED_BITS_ARB); - ADD_ATTR(WGL_ACCUM_GREEN_BITS_ARB); - ADD_ATTR(WGL_ACCUM_BLUE_BITS_ARB); - ADD_ATTR(WGL_ACCUM_ALPHA_BITS_ARB); - ADD_ATTR(WGL_DEPTH_BITS_ARB); - ADD_ATTR(WGL_STENCIL_BITS_ARB); - ADD_ATTR(WGL_AUX_BUFFERS_ARB); - ADD_ATTR(WGL_SWAP_METHOD_ARB); - - if (screen->has_WGL_ARB_multisample) - { - // we may not query these attrs if WGL_ARB_multisample is not offered - ADD_ATTR(WGL_SAMPLE_BUFFERS_ARB); - ADD_ATTR(WGL_SAMPLES_ARB); - } - - if (screen->has_WGL_ARB_render_texture) - { - // we may not query these attrs if WGL_ARB_render_texture is not offered - ADD_ATTR(WGL_BIND_TO_TEXTURE_RGB_ARB); - ADD_ATTR(WGL_BIND_TO_TEXTURE_RGBA_ARB); - } - - if (screen->has_WGL_ARB_pbuffer) - { - // we may not query these attrs if WGL_ARB_pbuffer is not offered - ADD_ATTR(WGL_DRAW_TO_PBUFFER_ARB); - ADD_ATTR(WGL_MAX_PBUFFER_PIXELS_ARB); - ADD_ATTR(WGL_MAX_PBUFFER_WIDTH_ARB); - ADD_ATTR(WGL_MAX_PBUFFER_HEIGHT_ARB); - } - - /* fill in configs */ - for (i = 0; i < numConfigs; i++) - { - int sizevalues=num_attrs*sizeof(int); - int *values=(int*)_alloca(sizevalues); - - memset(values,0,sizevalues); - - c = &(result[i]); - c->base.next = NULL; - c->pixelFormatIndex = i+1; - - if (!wglGetPixelFormatAttribivARBWrapper(hdc, i+1, 0, num_attrs, attrs, values)) - { - ErrorF("wglGetPixelFormatAttribivARB failed for index %d, error %s\n", i+1, glxWinErrorMessage()); - break; - } - -#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d)) - - if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0)) - { - GLWIN_DEBUG_MSG("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping", i+1); - continue; - } - - c->base.doubleBufferMode = ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, 0) ? GL_TRUE : GL_FALSE; - c->base.stereoMode = ATTR_VALUE(WGL_STEREO_ARB, 0) ? GL_TRUE : GL_FALSE; - - c->base.redBits = ATTR_VALUE(WGL_RED_BITS_ARB, 0); - c->base.greenBits = ATTR_VALUE(WGL_GREEN_BITS_ARB, 0); - c->base.blueBits = ATTR_VALUE(WGL_BLUE_BITS_ARB, 0); - c->base.alphaBits = ATTR_VALUE(WGL_ALPHA_BITS_ARB, 0); - - c->base.redMask = BITS_AND_SHIFT_TO_MASK(c->base.redBits, ATTR_VALUE(WGL_RED_SHIFT_ARB, 0)); - c->base.greenMask = BITS_AND_SHIFT_TO_MASK(c->base.greenBits, ATTR_VALUE(WGL_GREEN_SHIFT_ARB, 0)); - c->base.blueMask = BITS_AND_SHIFT_TO_MASK(c->base.blueBits, ATTR_VALUE(WGL_BLUE_SHIFT_ARB, 0)); - c->base.alphaMask = BITS_AND_SHIFT_TO_MASK(c->base.alphaBits, ATTR_VALUE(WGL_ALPHA_SHIFT_ARB, 0)); - - switch (ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)) - { - case WGL_TYPE_COLORINDEX_ARB: - c->base.indexBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0); - c->base.rgbBits = 0; - c->base.visualType = GLX_STATIC_COLOR; - break; - - case WGL_TYPE_RGBA_FLOAT_ARB: - GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i+1); - continue; - - case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: - GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping", i+1); - continue; - - case WGL_TYPE_RGBA_ARB: - c->base.indexBits = 0; - c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0); - c->base.visualType = GLX_TRUE_COLOR; - break; - - default: - ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n", ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)); - continue; - } - - c->base.accumRedBits = ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, 0); - c->base.accumGreenBits = ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, 0); - c->base.accumBlueBits = ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, 0); - c->base.accumAlphaBits = ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, 0); - - c->base.depthBits = ATTR_VALUE(WGL_DEPTH_BITS_ARB, 0); - c->base.stencilBits = ATTR_VALUE(WGL_STENCIL_BITS_ARB, 0); - c->base.numAuxBuffers = ATTR_VALUE(WGL_AUX_BUFFERS_ARB, 0); - - { - int layers = ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0); - - if (layers > 0) - { - ErrorF("pixelFormat %d: has %d overlay, %d underlays which aren't currently handled", i, ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0), ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0)); - // XXX: need to iterate over layers? - } - } - c->base.level = 0; - - c->base.pixmapMode = 0; // ??? - c->base.visualID = -1; // will be set by __glXScreenInit() - - /* EXT_visual_rating / GLX 1.2 */ - switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) - { - default: - ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_ACCELERATION_ARB\n", ATTR_VALUE(WGL_ACCELERATION_ARB, 0)); - - case WGL_NO_ACCELERATION_ARB: - c->base.visualRating = GLX_SLOW_VISUAL_EXT; - break; - - case WGL_GENERIC_ACCELERATION_ARB: - case WGL_FULL_ACCELERATION_ARB: - c->base.visualRating = GLX_NONE_EXT; - break; - } - - /* EXT_visual_info / GLX 1.2 */ - // c->base.visualType is set above - if (ATTR_VALUE(WGL_TRANSPARENT_ARB, 0)) - { - c->base.transparentPixel = (c->base.visualType == GLX_TRUE_COLOR) ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; - c->base.transparentRed = ATTR_VALUE(WGL_TRANSPARENT_RED_VALUE_ARB, 0); - c->base.transparentGreen = ATTR_VALUE(WGL_TRANSPARENT_GREEN_VALUE_ARB, 0); - c->base.transparentBlue = ATTR_VALUE(WGL_TRANSPARENT_BLUE_VALUE_ARB, 0); - c->base.transparentAlpha = ATTR_VALUE(WGL_TRANSPARENT_ALPHA_VALUE_ARB, 0); - c->base.transparentIndex = ATTR_VALUE(WGL_TRANSPARENT_INDEX_VALUE_ARB, 0); - } - else - { - c->base.transparentPixel = GLX_NONE_EXT; - c->base.transparentRed = GLX_NONE; - c->base.transparentGreen = GLX_NONE; - c->base.transparentBlue = GLX_NONE; - c->base.transparentAlpha = GLX_NONE; - c->base.transparentIndex = GLX_NONE; - } - - /* ARB_multisample / SGIS_multisample */ - if (screen->has_WGL_ARB_multisample) - { - c->base.sampleBuffers = ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, 0); - c->base.samples = ATTR_VALUE(WGL_SAMPLES_ARB, 0); - } - else - { - c->base.sampleBuffers = 0; - c->base.samples = 0; - } - - /* SGIX_fbconfig / GLX 1.3 */ - c->base.drawableType = ((ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, 0) ? GLX_WINDOW_BIT : 0) - | (ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, 0) ? GLX_PIXMAP_BIT : 0) - | (ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, 0) ? GLX_PBUFFER_BIT : 0)); - - /* - Assume OpenGL RGBA rendering is available on all visuals - (it is specified to render to red component in single-channel visuals, - if supported, but there doesn't seem to be any mechanism to check if it - is supported) - - Color index rendering is only supported on single-channel visuals - */ - if (c->base.visualType == GLX_STATIC_COLOR) - { - c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT; - } - else - { - c->base.renderType = GLX_RGBA_BIT; - } - - c->base.xRenderable = GL_TRUE; - c->base.fbconfigID = -1; // will be set by __glXScreenInit() - - /* SGIX_pbuffer / GLX 1.3 */ - if (screen->has_WGL_ARB_pbuffer) - { - c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1); - c->base.maxPbufferHeight = ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1); - c->base.maxPbufferPixels = ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1); - } - else - { - c->base.maxPbufferWidth = -1; - c->base.maxPbufferHeight = -1; - c->base.maxPbufferPixels = -1; - } - c->base.optimalPbufferWidth = 0; // there is no optimal value - c->base.optimalPbufferHeight = 0; - - /* SGIX_visual_select_group */ - // arrange for visuals with the best acceleration to be preferred in selection - switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) - { - case WGL_FULL_ACCELERATION_ARB: - c->base.visualSelectGroup = 2; - break; - - case WGL_GENERIC_ACCELERATION_ARB: - c->base.visualSelectGroup = 1; - break; - - default: - case WGL_NO_ACCELERATION_ARB: - c->base.visualSelectGroup = 0; - break; - } - - /* OML_swap_method */ - switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0)) - { - case WGL_SWAP_EXCHANGE_ARB: - c->base.swapMethod = GLX_SWAP_EXCHANGE_OML; - break; - - case WGL_SWAP_COPY_ARB: - c->base.swapMethod = GLX_SWAP_COPY_OML; - break; - - default: - ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n", ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0)); - - case WGL_SWAP_UNDEFINED_ARB: - c->base.swapMethod = GLX_SWAP_UNDEFINED_OML; - } - - /* EXT_import_context */ - c->base.screen = screen->base.pScreen->myNum; - - /* EXT_texture_from_pixmap */ - /* - Mesa's DRI configs always have bindToTextureRgb/Rgba TRUE (see driCreateConfigs(), so setting - bindToTextureRgb/bindToTextureRgba to FALSE means that swrast can't find any fbConfigs to use, - so setting these to 0, even if we know bindToTexture isn't available, isn't a good idea... - */ - if (screen->has_WGL_ARB_render_texture) - { - c->base.bindToTextureRgb = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGB_ARB, -1); - c->base.bindToTextureRgba = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGBA_ARB, -1); - } - else - { - c->base.bindToTextureRgb = -1; - c->base.bindToTextureRgba = -1; - } - c->base.bindToMipmapTexture = -1; - c->base.bindToTextureTargets = GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | GLX_TEXTURE_RECTANGLE_BIT_EXT; - c->base.yInverted = -1; - - n++; - - // update previous config to point to this config - if (prev) - prev->base.next = &(c->base); - - prev = c; - } - - screen->base.numFBConfigs = n; - screen->base.fbconfigs = &(result->base); -} +/* + * File: indirect.c + * Purpose: A GLX implementation that uses Windows OpenGL library + * + * Authors: Alexander Gottwald + * Jon TURNEY + * + * Copyright (c) Jon TURNEY 2009 + * Copyright (c) Alexander Gottwald 2004 + * + * Portions of this file are copied from GL/apple/indirect.c, + * which contains the following copyright: + * + * Copyright (c) 2007, 2008, 2009 Apple Inc. + * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002 Greg Parker. All Rights Reserved. + * + * Portions of this file are copied from Mesa's xf86glx.c, + * which contains the following copyright: + * + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * 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 ABOVE LISTED COPYRIGHT HOLDER(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. + */ + +/* + TODO: + - hook up remaining unimplemented extensions + - research what guarantees glXWaitX, glXWaitGL are supposed to offer, and implement then + using GdiFlush and/or glFinish + - pbuffer clobbering: we don't get async notification, but can we arrange to emit the + event when we notice it's been clobbered? at the very least, check if it's been clobbered + before using it? + - are the __GLXConfig * we get handed back ones we are made (so we can extend the structure + with privates?) Or are they created inside the GLX core as well? +*/ + +/* + MSDN clarifications: + + It says SetPixelFormat()'s PIXELFORMATDESCRIPTOR pointer argument has no effect + except on metafiles, this seems to mean that as it's ok to supply NULL if the DC + is not for a metafile + + wglMakeCurrent ignores the hdc if hglrc is NULL, so wglMakeCurrent(NULL, NULL) + is used to make no context current + +*/ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif + +#include "glwindows.h" +#include <glx/glxserver.h> +#include <glx/glxutil.h> +#include <glx/extension_string.h> +#include <GL/glxtokens.h> + +#include <winpriv.h> +#include <wgl_ext_api.h> +#include "win.h" +#include <winmsg.h> + +extern Bool g_fXdmcpEnabled; +extern Bool g_fNativeGl; + +#define NUM_ELEMENTS(x) (sizeof(x)/ sizeof(x[1])) + +/* ---------------------------------------------------------------------- */ +/* + * structure definitions + */ + +typedef struct __GLXWinContext __GLXWinContext; +typedef struct __GLXWinDrawable __GLXWinDrawable; +typedef struct __GLXWinScreen glxWinScreen; +typedef struct __GLXWinConfig GLXWinConfig; + +struct __GLXWinContext { + __GLXcontext base; + HGLRC ctx; /* Windows GL Context */ + HDC hDC; /* Windows device context */ + HDC hreadDC; /* Windows device read context */ + __GLXWinContext *shareContext; /* Context with which we will share display lists and textures */ + HWND hwnd; /* For detecting when HWND has changed */ + HWND hreadwnd; +}; + +struct __GLXWinDrawable +{ + __GLXdrawable base; + __GLXWinContext *drawContext; + + /* If this drawable is GLX_DRAWABLE_PBUFFER */ + HPBUFFERARB hPbuffer; + + /* If this drawable is GLX_DRAWABLE_PIXMAP */ + HDC dibDC; + HBITMAP hDIB; + HBITMAP hOldDIB; /* original DIB for DC */ + void *pOldBits; /* original pBits for this drawable's pixmap */ +}; + +struct __GLXWinScreen +{ + __GLXscreen base; + + /* Supported GLX extensions */ + unsigned char glx_enable_bits[__GLX_EXT_BYTES]; + + Bool has_WGL_ARB_multisample; + Bool has_WGL_ARB_pixel_format; + Bool has_WGL_ARB_pbuffer; + Bool has_WGL_ARB_render_texture; + + /* wrapped screen functions */ + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + DestroyWindowProcPtr DestroyWindow; + CopyWindowProcPtr CopyWindow; + PositionWindowProcPtr PositionWindow; +}; + +struct __GLXWinConfig +{ + __GLXconfig base; + int pixelFormatIndex; +}; + +/* ---------------------------------------------------------------------- */ +/* + * Various debug helpers + */ + +#ifdef _DEBUG +void GLWIN_DEBUG_HWND(HWND hwnd) +{ + if (glxWinDebugSettings.dumpHWND) + { + char buffer[1024]; + RECT Rect; + HDC hDc=GetDC(hwnd); + + if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; + GetWindowRect(hwnd,&Rect); + + GLWIN_DEBUG_MSG("Got HWND %p (hdc %p) for window '%s' (%d,%d,%d,%d)", hwnd, hDc, buffer, Rect.left, Rect.top, Rect.right, Rect.bottom); + ReleaseDC(hwnd,hDc); + } +} + +void GLWIN_HDC_DEBUG_MSG(const char *Message, HDC hDc, HWND hwnd) +{ + char buffer[1024]; + RECT Rect; + + if (GetWindowText(hwnd, buffer, sizeof(buffer))==0) *buffer=0; + GetWindowRect(hwnd,&Rect); + + GLWIN_DEBUG_MSG("Got HDC %p (hwnd %p) for window '%s' (%d,%d,%d,%d)", hDc, hwnd, buffer, Rect.left, Rect.top, Rect.right, Rect.bottom); + +} + +glxWinDebugSettingsRec glxWinDebugSettings = { 0, 0, 0, 0, 0, 0}; + +static void glxWinInitDebugSettings(void) +{ + char *envptr; + + envptr = getenv("GLWIN_ENABLE_DEBUG"); + if (envptr != NULL) + glxWinDebugSettings.enableDebug = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_ENABLE_TRACE"); + if (envptr != NULL) + glxWinDebugSettings.enableTrace = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_DUMP_PFD"); + if (envptr != NULL) + glxWinDebugSettings.dumpPFD = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_DUMP_HWND"); + if (envptr != NULL) + glxWinDebugSettings.dumpHWND = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_DUMP_DC"); + if (envptr != NULL) + glxWinDebugSettings.dumpDC = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_ENABLE_GLCALL_TRACE"); + if (envptr != NULL) + glxWinDebugSettings.enableGLcallTrace = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_ENABLE_WGLCALL_TRACE"); + if (envptr != NULL) + glxWinDebugSettings.enableWGLcallTrace = (atoi(envptr) == 1); + + envptr = getenv("GLWIN_DEBUG_ALL"); + if (envptr != NULL) + { + glxWinDebugSettings.enableDebug = 1; + glxWinDebugSettings.enableTrace = 1; + glxWinDebugSettings.dumpPFD = 1; + glxWinDebugSettings.dumpHWND = 1; + glxWinDebugSettings.dumpDC = 1; + glxWinDebugSettings.enableGLcallTrace = 1; + glxWinDebugSettings.enableWGLcallTrace = 1; + } +} +#endif + +static +const char *glxWinErrorMessage(void) +{ + static char errorbuffer[1024]; + DWORD Error=GetLastError(); + int offset; + + sprintf(errorbuffer, "%p ",Error); + offset=strlen(errorbuffer); + + if (!FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + Error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &errorbuffer[offset], + sizeof(errorbuffer), + NULL )) + { + snprintf(errorbuffer, sizeof(errorbuffer), "Unknown error in FormatMessage: %08x!", (unsigned)GetLastError()); + } + + if (errorbuffer[strlen(errorbuffer)-1] == '\n') + errorbuffer[strlen(errorbuffer)-1] = 0; + + return errorbuffer; +} + +static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd); + +#ifdef _DEBUG + +#define DUMP_PFD_FLAG(flag) \ + if (pfd->dwFlags & flag) { \ + ErrorF("%s%s", pipesym, #flag); \ + pipesym = " | "; \ + } + +static void pfdOut(const PIXELFORMATDESCRIPTOR *pfd) +{ + const char *pipesym = ""; /* will be set after first flag dump */ + ErrorF("PIXELFORMATDESCRIPTOR:\n"); + ErrorF("nSize = %u\n", pfd->nSize); + ErrorF("nVersion = %u\n", pfd->nVersion); + ErrorF("dwFlags = %lu = {", pfd->dwFlags); + DUMP_PFD_FLAG(PFD_DOUBLEBUFFER); + DUMP_PFD_FLAG(PFD_STEREO); + DUMP_PFD_FLAG(PFD_DRAW_TO_WINDOW); + DUMP_PFD_FLAG(PFD_DRAW_TO_BITMAP); + DUMP_PFD_FLAG(PFD_SUPPORT_GDI); + DUMP_PFD_FLAG(PFD_SUPPORT_OPENGL); + DUMP_PFD_FLAG(PFD_GENERIC_FORMAT); + DUMP_PFD_FLAG(PFD_NEED_PALETTE); + DUMP_PFD_FLAG(PFD_NEED_SYSTEM_PALETTE); + DUMP_PFD_FLAG(PFD_SWAP_EXCHANGE); + DUMP_PFD_FLAG(PFD_SWAP_COPY); + DUMP_PFD_FLAG(PFD_SWAP_LAYER_BUFFERS); + DUMP_PFD_FLAG(PFD_GENERIC_ACCELERATED); + DUMP_PFD_FLAG(PFD_DEPTH_DONTCARE); + DUMP_PFD_FLAG(PFD_DOUBLEBUFFER_DONTCARE); + DUMP_PFD_FLAG(PFD_STEREO_DONTCARE); + ErrorF("}\n"); + + ErrorF("iPixelType = %hu = %s\n", pfd->iPixelType, + (pfd->iPixelType == PFD_TYPE_RGBA ? "PFD_TYPE_RGBA" : "PFD_TYPE_COLORINDEX")); + ErrorF("cColorBits = %hhu\n", pfd->cColorBits); + ErrorF("cRedBits = %hhu\n", pfd->cRedBits); + ErrorF("cRedShift = %hhu\n", pfd->cRedShift); + ErrorF("cGreenBits = %hhu\n", pfd->cGreenBits); + ErrorF("cGreenShift = %hhu\n", pfd->cGreenShift); + ErrorF("cBlueBits = %hhu\n", pfd->cBlueBits); + ErrorF("cBlueShift = %hhu\n", pfd->cBlueShift); + ErrorF("cAlphaBits = %hhu\n", pfd->cAlphaBits); + ErrorF("cAlphaShift = %hhu\n", pfd->cAlphaShift); + ErrorF("cAccumBits = %hhu\n", pfd->cAccumBits); + ErrorF("cAccumRedBits = %hhu\n", pfd->cAccumRedBits); + ErrorF("cAccumGreenBits = %hhu\n", pfd->cAccumGreenBits); + ErrorF("cAccumBlueBits = %hhu\n", pfd->cAccumBlueBits); + ErrorF("cAccumAlphaBits = %hhu\n", pfd->cAccumAlphaBits); + ErrorF("cDepthBits = %hhu\n", pfd->cDepthBits); + ErrorF("cStencilBits = %hhu\n", pfd->cStencilBits); + ErrorF("cAuxBuffers = %hhu\n", pfd->cAuxBuffers); + ErrorF("iLayerType = %hhu\n", pfd->iLayerType); + ErrorF("bReserved = %hhu\n", pfd->bReserved); + ErrorF("dwLayerMask = %lu\n", pfd->dwLayerMask); + ErrorF("dwVisibleMask = %lu\n", pfd->dwVisibleMask); + ErrorF("dwDamageMask = %lu\n", pfd->dwDamageMask); + ErrorF("\n"); +} + +static const char * +visual_class_name(int cls) +{ + switch (cls) { + case GLX_STATIC_COLOR: + return "StaticColor"; + case GLX_PSEUDO_COLOR: + return "PseudoColor"; + case GLX_STATIC_GRAY: + return "StaticGray"; + case GLX_GRAY_SCALE: + return "GrayScale"; + case GLX_TRUE_COLOR: + return "TrueColor"; + case GLX_DIRECT_COLOR: + return "DirectColor"; + default: + return "-none-"; + } +} + +static const char * +swap_method_name(int mthd) +{ + switch (mthd) + { + case GLX_SWAP_EXCHANGE_OML: + return "xchg"; + case GLX_SWAP_COPY_OML: + return "copy"; + case GLX_SWAP_UNDEFINED_OML: + return " "; + default: + return "????"; + } +} + +static void +fbConfigsDump(unsigned int n, __GLXconfig *c) +{ + ErrorF("%d fbConfigs\n", n); + ErrorF("pxf vis fb render Ste aux accum MS drawable Group/\n"); + ErrorF("idx ID ID VisualType Depth Lvl RGB CI DB Swap reo R G B A Z S buf AR AG AB AA bufs num W P Pb Float Trans Caveat\n"); + ErrorF("-----------------------------------------------------------------------------------------------------------------------------\n"); + + while (c != NULL) + { + unsigned int i = ((GLXWinConfig *)c)->pixelFormatIndex; + + ErrorF("%3d %2x %2x " + "%-11s" + " %3d %3d %s %s %s %s %s " + "%2d %2d %2d %2d " + "%2d %2d " + "%2d " + "%2d %2d %2d %2d" + " %2d %2d" + " %s %s %s " + " %s " + " %s " + " %d %s" + "\n", + i, c->visualID, c->fbconfigID, + visual_class_name(c->visualType), + c->rgbBits ? c->rgbBits : c->indexBits, + c->level, + (c->renderType & GLX_RGBA_BIT) ? "y" : ".", + (c->renderType & GLX_COLOR_INDEX_BIT) ? "y" : ".", + c->doubleBufferMode ? "y" : ".", + swap_method_name(c->swapMethod), + c->stereoMode ? "y" : ".", + c->redBits, c->greenBits, c->blueBits, c->alphaBits, + c->depthBits, c->stencilBits, + c->numAuxBuffers, + c->accumRedBits, c->accumGreenBits, c->accumBlueBits, c->accumAlphaBits, + c->sampleBuffers, c->samples, + (c->drawableType & GLX_WINDOW_BIT) ? "y" : ".", + (c->drawableType & GLX_PIXMAP_BIT) ? "y" : ".", + (c->drawableType & GLX_PBUFFER_BIT) ? "y" : ".", + ".", + (c->transparentPixel != GLX_NONE_EXT) ? "y" : ".", + c->visualSelectGroup, (c->visualRating == GLX_SLOW_VISUAL_EXT) ? "*" : " "); + + c = c->next; + } +} +#endif + +/* ---------------------------------------------------------------------- */ +/* + * Forward declarations + */ + +static __GLXscreen *glxWinScreenProbe(ScreenPtr pScreen); +static __GLXcontext *glxWinCreateContext(__GLXscreen *screen, + __GLXconfig *modes, + __GLXcontext *baseShareContext); +static __GLXdrawable *glxWinCreateDrawable(ClientPtr client, + __GLXscreen *screen, + DrawablePtr pDraw, + XID drawId, + int type, + XID glxDrawId, + __GLXconfig *conf); + +static Bool glxWinRealizeWindow(WindowPtr pWin); +static Bool glxWinUnrealizeWindow(WindowPtr pWin); +static Bool glxWinDestroyWindow(WindowPtr pWin); +static void glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc); +static Bool glxWinPositionWindow(WindowPtr pWindow, int x, int y); + +static HDC glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HWND *hwnd); +static void glxWinReleaseDC(HWND hwnd, HDC hdc, __GLXWinDrawable *draw); + +static void glxWinCreateConfigs(HDC dc, glxWinScreen *screen); +static void glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen); +static int fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride); +static int fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen); + +/* ---------------------------------------------------------------------- */ +/* + * The GLX provider + */ + +__GLXprovider __glXWGLProvider = { + glxWinScreenProbe, + "Win32 native WGL", + NULL +}; + +void +glxWinPushNativeProvider(void) +{ + if (g_fNativeGl) + GlxPushProvider(&__glXWGLProvider); +} + +/* ---------------------------------------------------------------------- */ +/* + * Screen functions + */ + +static void +glxWinScreenDestroy(__GLXscreen *screen) +{ + GLWIN_DEBUG_MSG("glxWinScreenDestroy(%p)", screen); + __glXScreenDestroy(screen); + free(screen); +} + +static int +glxWinScreenSwapInterval(__GLXdrawable *drawable, int interval) +{ + BOOL ret = wglSwapIntervalEXTWrapper(interval); + if (!ret) + { + ErrorF("wglSwapIntervalEXT interval %d failed:%s\n", interval, glxWinErrorMessage()); + } + return ret; +} + +static LRESULT CALLBACK GlxWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg== WM_NCHITTEST) + { + return HTTRANSPARENT; + } + else + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +/* + Report the extensions split and formatted to avoid overflowing a line + */ +static void +glxLogExtensions(const char *prefix, const char *extensions) +{ + int length = 0; + char *strl; + char *str = malloc(strlen(extensions) + 1); + + if (str == NULL) + { + ErrorF("glxLogExtensions: xalloc error\n"); + return; + } + + str[strlen(extensions)] = '\0'; + strncpy (str, extensions, strlen(extensions)); + + strl = strtok(str, " "); + winDebug("%s%s", prefix, strl); + length = strlen(prefix) + strlen(strl); + + while (1) + { + strl = strtok(NULL, " "); + if (strl == NULL) break; + + if (length + strlen(strl) + 1 > 120) + { + winDebug("\n"); + winDebug("%s",prefix); + length = strlen(prefix); + } + else + { + winDebug(" "); + length++; + } + + winDebug("%s", strl); + length = length + strlen(strl); + } + + winDebug("\n"); + + free(str); +} + +/* This is called by GlxExtensionInit() asking the GLX provider if it can handle the screen... */ +static __GLXscreen * +glxWinScreenProbe(ScreenPtr pScreen) +{ + glxWinScreen *screen; + const char *gl_extensions; + const char *wgl_extensions; + HWND hwnd; + HDC hdc; + HGLRC hglrc; + + GLWIN_DEBUG_MSG("glxWinScreenProbe"); + +#ifdef _DEBUG + glxWinInitDebugSettings(); +#endif + + if (pScreen == NULL) + return NULL; + + if (!winCheckScreenAiglxIsSupported(pScreen)) + { + LogMessage(X_ERROR,"AIGLX: No native OpenGL in modes with a root window\n"); + return NULL; + } + + screen = calloc(1, sizeof(glxWinScreen)); + + if (NULL == screen) + return NULL; + + /* Wrap RealizeWindow, UnrealizeWindow and CopyWindow on this screen */ + screen->RealizeWindow = pScreen->RealizeWindow; + pScreen->RealizeWindow = glxWinRealizeWindow; + screen->UnrealizeWindow = pScreen->UnrealizeWindow; + pScreen->UnrealizeWindow = glxWinUnrealizeWindow; + screen->CopyWindow = pScreen->CopyWindow; + pScreen->CopyWindow = glxWinCopyWindow; + screen->PositionWindow = pScreen->PositionWindow; + pScreen->PositionWindow = glxWinPositionWindow; + screen->DestroyWindow = pScreen->DestroyWindow; + pScreen->DestroyWindow = glxWinDestroyWindow; + + /* Dump out some useful information about the native renderer */ + + // create window class + { + static wATOM glTestWndClass = 0; + if (glTestWndClass == 0) + { + WNDCLASSEX wc; + glTestWndClass=1; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = CS_OWNDC ; + wc.lpfnWndProc = GlxWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(NULL); + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = 0; + wc.lpszMenuName = NULL; + wc.lpszClassName = WIN_GL_WINDOW_CLASS; + wc.hIconSm = 0; + RegisterClassEx (&wc); + } + } + + // create an invisible window for a scratch DC + hwnd = CreateWindowExA(0, + WIN_GL_WINDOW_CLASS, + "XWin GL Renderer Capabilities Test Window", + 0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL); + if (hwnd == NULL) + LogMessage(X_ERROR,"AIGLX: Couldn't create a window for render capabilities testing\n"); + + hdc = GetDC(hwnd); + + // we must set a pixel format before we can create a context, just use the first one... + SetPixelFormat(hdc, 1, NULL); + hglrc = wglCreateContext(hdc); + wglMakeCurrent(hdc, hglrc); + + // initialize wgl extension proc pointers (don't call them before here...) + // (but we need to have a current context for them to be resolvable) + wglResolveExtensionProcs(); + + winDebug("GL_VERSION: %s\n", glGetStringWrapperNonstatic(GL_VERSION)); + winDebug("GL_VENDOR: %s\n", glGetStringWrapperNonstatic(GL_VENDOR)); + winDebug("GL_RENDERER: %s\n", glGetStringWrapperNonstatic(GL_RENDERER)); + gl_extensions = (const char *)glGetStringWrapperNonstatic(GL_EXTENSIONS); + glxLogExtensions("GL_EXTENSIONS: ", gl_extensions); + wgl_extensions = wglGetExtensionsStringARBWrapper(hdc); + if (!wgl_extensions) wgl_extensions = ""; + glxLogExtensions("WGL_EXTENSIONS: ", wgl_extensions); + + // Can you see the problem here? The extensions string is DC specific + // Different DCs for windows on a multimonitor system driven by multiple cards + // might have completely different capabilities. Of course, good luck getting + // those screens to be accelerated in XP and earlier... + + { + // testing facility to not use any WGL extensions + char *envptr = getenv("GLWIN_NO_WGL_EXTENSIONS"); + if ((envptr != NULL) && (atoi(envptr) != 0)) + { + ErrorF("GLWIN_NO_WGL_EXTENSIONS is set, ignoring WGL_EXTENSIONS\n"); + wgl_extensions = ""; + } + } + + { + Bool glx_sgi_make_current_read = FALSE; + + // + // Based on the WGL extensions available, enable various GLX extensions + // XXX: make this table-driven ? + // + memset(screen->glx_enable_bits, 0, __GLX_EXT_BYTES); + + __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_visual_info"); + __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_visual_rating"); + __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_import_context"); + __glXEnableExtension(screen->glx_enable_bits, "GLX_OML_swap_method"); + __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIX_fbconfig"); + + if (strstr(wgl_extensions, "WGL_ARB_make_current_read")) + { + __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_make_current_read"); + LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n"); + glx_sgi_make_current_read = TRUE; + } + + if (strstr(gl_extensions, "GL_WIN_swap_hint")) + { + __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer"); + LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n"); + } + + if (strstr(wgl_extensions, "WGL_EXT_swap_control")) + { + __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control"); + __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_swap_control"); + LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n"); + } + +/* // Hmm? screen->texOffset */ +/* if (strstr(wgl_extensions, "WGL_ARB_render_texture")) */ +/* { */ +/* __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_texture_from_pixmap"); */ +/* LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); */ +/* screen->has_WGL_ARB_render_texture = TRUE; */ +/* } */ + + if (strstr(wgl_extensions, "WGL_ARB_pbuffer")) + { + __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIX_pbuffer"); + LogMessage(X_INFO, "AIGLX: enabled GLX_SGIX_pbuffer\n"); + screen->has_WGL_ARB_pbuffer = TRUE; + } + + if (strstr(wgl_extensions, "WGL_ARB_multisample")) + { + __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_multisample"); + __glXEnableExtension(screen->glx_enable_bits, "GLX_SGIS_multisample"); + LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_multisample and GLX_SGIS_multisample\n"); + screen->has_WGL_ARB_multisample = TRUE; + } + + screen->base.destroy = glxWinScreenDestroy; + screen->base.createContext = glxWinCreateContext; + screen->base.createDrawable = glxWinCreateDrawable; + screen->base.swapInterval = glxWinScreenSwapInterval; + screen->base.hyperpipeFuncs = NULL; + screen->base.swapBarrierFuncs = NULL; + screen->base.pScreen = pScreen; + + if (strstr(wgl_extensions, "WGL_ARB_pixel_format")) + { + glxWinCreateConfigsExt(hdc, screen); + screen->has_WGL_ARB_pixel_format = TRUE; + } + else + { + glxWinCreateConfigs(hdc, screen); + screen->has_WGL_ARB_pixel_format = FALSE; + } + // Initializes screen->base.fbconfigs and screen->base.numFBConfigs + + /* These will be set by __glXScreenInit */ + screen->base.visuals = NULL; + screen->base.numVisuals = 0; + + __glXScreenInit(&screen->base, pScreen); + +#ifdef _DEBUG + // dump out fbConfigs now fbConfigIds and visualIDs have been assigned + fbConfigsDump(screen->base.numFBConfigs, screen->base.fbconfigs); +#endif + + // Override the GL extensions string set by __glXScreenInit() + screen->base.GLextensions = xstrdup(gl_extensions); + + // Generate the GLX extensions string (overrides that set by __glXScreenInit()) + { + unsigned int buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL); + if (buffer_size > 0) + { + if (screen->base.GLXextensions != NULL) + { + free(screen->base.GLXextensions); + } + + screen->base.GLXextensions = xnfalloc(buffer_size); + __glXGetExtensionString(screen->glx_enable_bits, screen->base.GLXextensions); + } + } + + // + // Override the GLX version (__glXScreenInit() sets it to "1.2") + // if we have all the needed extensionsto operate as a higher version + // + // SGIX_fbconfig && SGIX_pbuffer && SGI_make_current_read -> 1.3 + // ARB_multisample -> 1.4 + // + if (screen->has_WGL_ARB_pbuffer && glx_sgi_make_current_read) + { + free(screen->base.GLXversion); + + if (screen->has_WGL_ARB_multisample) + { + screen->base.GLXversion = xstrdup("1.4"); + screen->base.GLXmajor = 1; + screen->base.GLXminor = 4; + } + else + { + screen->base.GLXversion = xstrdup("1.3"); + screen->base.GLXmajor = 1; + screen->base.GLXminor = 3; + } + LogMessage(X_INFO, "AIGLX: Set GLX version to %s\n", screen->base.GLXversion); + } + } + + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hglrc); + ReleaseDC(hwnd, hdc); + DestroyWindow(hwnd); + + return &screen->base; +} + +/* ---------------------------------------------------------------------- */ +/* + * Window functions + */ + +static Bool +glxWinRealizeWindow(WindowPtr pWin) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen); + winWindowPriv(pWin); + + GLWIN_DEBUG_MSG("glxWinRealizeWindow"); + + /* Allow the window to be created (RootlessRealizeWindow is inside our wrap) */ + pScreen->RealizeWindow = screenPriv->RealizeWindow; + result = pScreen->RealizeWindow(pWin); + pScreen->RealizeWindow = glxWinRealizeWindow; + + // Check if ze need to move the window\n + if (pWinPriv->GlCtxWnd && pWinPriv->hWnd) + { + ShowWindow(pWinPriv->hWnd,SW_SHOW); + } + return result; +} + + +static void +glxWinCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + __GLXWinDrawable *pGlxDraw; + ScreenPtr pScreen = pWindow->drawable.pScreen; + glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen); + + GLWIN_TRACE_MSG("glxWinCopyWindow pWindow %p", pWindow); + + dixLookupResourceByType((pointer) &pGlxDraw, pWindow->drawable.id, __glXDrawableRes, + NullClient, DixUnknownAccess); + + + /* + Discard any CopyWindow requests if a GL drawing context is pointing at the window + + For regions which are being drawn by GL, the shadow framebuffer doesn't have the + correct bits, so we wish to avoid shadow framebuffer damage occuring, which will + cause those incorrect bits to be transferred to the display.... + */ + if (pGlxDraw && pGlxDraw->drawContext) + { + GLWIN_DEBUG_MSG("glxWinCopyWindow: discarding"); + return; + } + + GLWIN_DEBUG_MSG("glxWinCopyWindow - passing to hw layer"); + + pScreen->CopyWindow = screenPriv->CopyWindow; + pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc); + pScreen->CopyWindow = glxWinCopyWindow; + +} + +static Bool +glxWinPositionWindow(WindowPtr pWin, int x, int y) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + glxWinScreen *screenPriv = (glxWinScreen *) glxGetScreen(pScreen); + winWindowPriv(pWin); + + pScreen->PositionWindow = screenPriv->PositionWindow; + result = pScreen->PositionWindow(pWin, x, y); + pScreen->PositionWindow = glxWinPositionWindow; + + if (pWinPriv->GlCtxWnd && pWinPriv->hWnd) + { + MoveWindow(pWinPriv->hWnd, + pWin->drawable.x, + pWin->drawable.y, + pWin->drawable.width, + pWin->drawable.height, + FALSE); + } + return result; +} + + +static Bool +glxWinUnrealizeWindow(WindowPtr pWin) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + glxWinScreen *screenPriv = (glxWinScreen *)glxGetScreen(pScreen); + winWindowPriv(pWin); + + GLWIN_DEBUG_MSG("glxWinUnrealizeWindow"); + + pScreen->UnrealizeWindow = screenPriv->UnrealizeWindow; + result = pScreen->UnrealizeWindow(pWin); + pScreen->UnrealizeWindow = glxWinUnrealizeWindow; + + if (pWinPriv->GlCtxWnd && pWinPriv->hWnd) + ShowWindow(pWinPriv->hWnd,SW_HIDE); + + return result; +} + +static Bool +glxWinDestroyWindow(WindowPtr pWin) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + glxWinScreen *screenPriv = (glxWinScreen *)glxGetScreen(pScreen); + winWindowPriv(pWin); + + GLWIN_DEBUG_MSG("glxWinDestroyWindow"); + + if (pWinPriv->GlCtxWnd && pWinPriv->hWnd) + { + __GLXWinDrawable *pGlxDraw; + + dixLookupResourceByType((pointer) &pGlxDraw, pWin->drawable.id, __glXDrawableRes, NullClient, DixUnknownAccess); + + if (pGlxDraw && pGlxDraw->drawContext) + { + if (pGlxDraw->drawContext->hwnd!=pWinPriv->hWnd) + ErrorF("Wrong assumption\n"); + glxWinReleaseDC(pGlxDraw->drawContext->hwnd, pGlxDraw->drawContext->hDC, pGlxDraw); + pGlxDraw->drawContext->hDC=NULL; + pGlxDraw->drawContext->hwnd=NULL; + } + DestroyWindow(pWinPriv->hWnd); + pWinPriv->hWnd=NULL; + pWinPriv->GlCtxWnd=0; + } + + pScreen->DestroyWindow = screenPriv->DestroyWindow; + result = pScreen->DestroyWindow(pWin); + pScreen->DestroyWindow = glxWinDestroyWindow; + + return result; +} + +/* ---------------------------------------------------------------------- */ +/* + * Drawable functions + */ + +static GLboolean +glxWinDrawableSwapBuffers(ClientPtr client, __GLXdrawable *base) +{ + BOOL ret; + __GLXWinDrawable *draw = (__GLXWinDrawable *)base; + + /* Swap buffers on the last active context for drawing on the drawable */ + if (draw->drawContext == NULL) + { + GLWIN_TRACE_MSG("glxWinSwapBuffers - no context for drawable"); + return GL_FALSE; + } + + GLWIN_TRACE_MSG("glxWinSwapBuffers on drawable %p, last context %p (native ctx %p)", base, draw->drawContext, draw->drawContext->ctx); + + /* + draw->drawContext->base.drawPriv will not be set if the context is not current anymore, + but if it is, it should point to this drawable.... + */ + assert((draw->drawContext->base.drawPriv == NULL) || (draw->drawContext->base.drawPriv == base)); + + ret = SwapBuffers(draw->drawContext->hDC); + + if (!ret) + { + ErrorF("wglSwapBuffers failed: %s\n", glxWinErrorMessage()); + return GL_FALSE; + } + + return GL_TRUE; +} + +static void +glxWinDrawableCopySubBuffer(__GLXdrawable *drawable, + int x, int y, int w, int h) +{ + glAddSwapHintRectWINWrapperNonstatic(x, y, w, h); + glxWinDrawableSwapBuffers(NULL, drawable); +} + +static void +glxWinDrawableDestroy(__GLXdrawable *base) +{ + __GLXWinDrawable *glxPriv = (__GLXWinDrawable *)base; + + if (glxPriv->drawContext && (__glXLastContext == &((glxPriv->drawContext)->base))) + { + // if this context is current and has unflushed commands, say we have flushed them + // (don't actually flush them, the window is going away anyhow, and an implict flush occurs + // on the next context change) + // (GLX core considers it an error when we try to select a new current context if the old one + // has unflushed commands, but the window has disappeared..) + __GLX_NOTE_FLUSHED_CMDS(__glXLastContext); + __glXLastContext = NULL; + } + + if (glxPriv->hPbuffer) + if (!wglDestroyPbufferARBWrapper(glxPriv->hPbuffer)) + { + ErrorF("wglDestroyPbufferARB failed: %s\n", glxWinErrorMessage()); + } + + if (glxPriv->dibDC) + { + // restore the default DIB + SelectObject(glxPriv->dibDC, glxPriv->hOldDIB); + + if (!DeleteDC(glxPriv->dibDC)) + { + ErrorF("DeleteDC failed: %s\n", glxWinErrorMessage()); + } + } + + if (glxPriv->hDIB) + { + if (!DeleteObject(glxPriv->hDIB)) + { + ErrorF("DeleteObject failed: %s\n", glxWinErrorMessage()); + } + + ((PixmapPtr)glxPriv->base.pDraw)->devPrivate.ptr = glxPriv->pOldBits; + } + + GLWIN_DEBUG_MSG("glxWinDestroyDrawable"); + free(glxPriv); +} + +static __GLXdrawable * +glxWinCreateDrawable(ClientPtr client, + __GLXscreen *screen, + DrawablePtr pDraw, + XID drawId, + int type, + XID glxDrawId, + __GLXconfig *conf) +{ + __GLXWinDrawable *glxPriv; + + glxPriv = calloc(1,sizeof(*glxPriv)); + + if (glxPriv == NULL) + return NULL; + + if(!__glXDrawableInit(&glxPriv->base, screen, pDraw, type, glxDrawId, conf)) { + free(glxPriv); + return NULL; + } + + glxPriv->base.destroy = glxWinDrawableDestroy; + glxPriv->base.swapBuffers = glxWinDrawableSwapBuffers; + glxPriv->base.copySubBuffer = glxWinDrawableCopySubBuffer; + // glxPriv->base.waitX what are these for? + // glxPriv->base.waitGL + + GLWIN_DEBUG_MSG("glxWinCreateDrawable %p", glxPriv); + + return &glxPriv->base; +} + +/* ---------------------------------------------------------------------- */ +/* + * Texture functions + */ + +static +int glxWinBindTexImage(__GLXcontext *baseContext, + int buffer, + __GLXdrawable *pixmap) +{ + ErrorF("glxWinBindTexImage: not implemented\n"); + return FALSE; +} + +static +int glxWinReleaseTexImage(__GLXcontext *baseContext, + int buffer, + __GLXdrawable *pixmap) +{ + ErrorF(" glxWinReleaseTexImage: not implemented\n"); + return FALSE; +} + +/* ---------------------------------------------------------------------- */ +/* + * Lazy update context implementation + * + * WGL contexts are created for a specific HDC, so we cannot create the WGL + * context in glxWinCreateContext(), we must defer creation until the context + * is actually used on a specifc drawable which is connected to a native window, + * pbuffer or DIB + * + * The WGL context may be used on other, compatible HDCs, so we don't need to + * recreate it for every new native window + * + * XXX: I wonder why we can't create the WGL context on the screen HDC ? + * Basically we assume all HDCs are compatible at the moment: if they are not + * we are in a muddle, there was some code in the old implementation to attempt + * to transparently migrate a context to a new DC by copying state and sharing + * lists with the old one... + */ + +static void +glxWinSetPixelFormat(__GLXWinContext *gc, HDC hdc, int bppOverride, int drawableTypeOverride) +{ + __GLXscreen *screen = gc->base.pGlxScreen; + glxWinScreen *winScreen = (glxWinScreen *)screen; + + __GLXconfig *config = gc->base.config; + GLXWinConfig *winConfig = (GLXWinConfig *)config; + + GLWIN_DEBUG_MSG("glxWinSetPixelFormat: pixelFormatIndex %d", winConfig->pixelFormatIndex); + + /* + Normally, we can just use the the pixelFormatIndex corresponding + to the fbconfig which has been specified by the client + */ + + if (!((bppOverride && (bppOverride != (config->redBits + config->greenBits + config->blueBits) )) + || ((config->drawableType & drawableTypeOverride) == 0))) + { + if (!SetPixelFormat(hdc, winConfig->pixelFormatIndex, NULL)) + { + ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); + return; + } + + return; + } + + /* + However, in certain special cases this pixel format will be incompatible with the + use we are going to put it to, so we need to re-evaluate the pixel format to use: + + 1) When PFD_DRAW_TO_BITMAP is set, ChoosePixelFormat() always returns a format with + the cColorBits we asked for, so we need to ensure it matches the bpp of the bitmap + + 2) Applications may assume that visuals selected with glXChooseVisual() work with + pixmap drawables (there is no attribute to explicitly query for pixmap drawable + support as there is for glXChooseFBConfig()) + (it's arguable this is an error in the application, but we try to make it work) + + pixmap rendering is always slow for us, so we don't want to choose those visuals + by default, but if the actual drawable type we're trying to select the context + on (drawableTypeOverride) isn't supported by the selected fbConfig, reconsider + and see if we can find a suitable one... + */ + ErrorF("glxWinSetPixelFormat: having second thoughts: cColorbits %d, bppOveride %d; config->drawableType %d, drawableTypeOverride %d\n", + (config->redBits + config->greenBits + config->blueBits), bppOverride, config->drawableType, drawableTypeOverride); + + if (!winScreen->has_WGL_ARB_pixel_format) + { + PIXELFORMATDESCRIPTOR pfd; + int pixelFormat; + + /* convert fbConfig to PFD */ + if (fbConfigToPixelFormat(gc->base.config, &pfd, drawableTypeOverride)) + { + ErrorF("glxWinSetPixelFormat: fbConfigToPixelFormat failed\n"); + return; + } + +#ifdef _DEBUG + if (glxWinDebugSettings.dumpPFD) + pfdOut(&pfd); +#endif + + if (bppOverride) + { + GLWIN_DEBUG_MSG("glxWinSetPixelFormat: Forcing bpp from %d to %d\n", pfd.cColorBits, bppOverride); + pfd.cColorBits = bppOverride; + } + + pixelFormat = ChoosePixelFormat(hdc, &pfd); + if (pixelFormat == 0) + { + ErrorF("ChoosePixelFormat error: %s\n", glxWinErrorMessage()); + return; + } + + GLWIN_DEBUG_MSG("ChoosePixelFormat: chose pixelFormatIndex %d", pixelFormat); + ErrorF("ChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", pixelFormat, winConfig->pixelFormatIndex); + + if (!SetPixelFormat(hdc, pixelFormat, &pfd)) + { + ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); + return; + } + } + else + { + int pixelFormat = fbConfigToPixelFormatIndex(hdc, gc->base.config, drawableTypeOverride, winScreen); + if (pixelFormat == 0) + { + ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage()); + return; + } + + GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d", pixelFormat); + ErrorF("wglChoosePixelFormat: chose pixelFormatIndex %d (rather than %d as originally planned)\n", pixelFormat, winConfig->pixelFormatIndex); + + if (!SetPixelFormat(hdc, pixelFormat, NULL)) + { + ErrorF("SetPixelFormat error: %s\n", glxWinErrorMessage()); + return; + } + } +} + +static HDC +glxWinMakeDC(__GLXWinContext *gc, __GLXWinDrawable *draw, HWND *hwnd) +{ + HDC hdc = NULL; + *hwnd = NULL; + + if (draw == NULL) + { + GLWIN_TRACE_MSG("No drawable for context %p (native ctx %p)", gc, gc->ctx); + return NULL; + } + + switch (draw->base.type) + { + case GLX_DRAWABLE_WINDOW: + { + WindowPtr pWin; + + pWin = (WindowPtr) draw->base.pDraw; + if (pWin == NULL) + { + GLWIN_TRACE_MSG("for drawable %p, no WindowPtr", pWin); + return NULL; + } + + *hwnd = winGetWindowInfo(pWin); + + if (*hwnd == NULL) + { + ErrorF("No HWND error: %s\n", glxWinErrorMessage()); + return NULL; + } + + hdc = GetDC(*hwnd); + + if (hdc == NULL) + ErrorF("GetDC error: %s: hwnd %x, gc %p, gc->ctx %p ,gc->hwnd %p\n", glxWinErrorMessage(), *hwnd, gc, gc->ctx, gc->hwnd); + + if (gc->hDC) + { + glxWinReleaseDC(gc->hwnd, gc->hDC, draw); + gc->hDC=NULL; + } +#ifdef _DEBUG + if (glxWinDebugSettings.enableTrace) + GLWIN_DEBUG_HWND(*hwnd); + + GLWIN_TRACE_MSG("for context %p (native ctx %p), hWnd changed from %p to %p", gc, gc->ctx, gc->hwnd, *hwnd); +#endif + gc->hwnd = *hwnd; + + /* Check if we need to set the pixelformat */ + { + winWindowPriv(pWin); + if (!pWinPriv->PixelFormatSet) + { + pWinPriv->PixelFormatSet=TRUE; + /* We must select a pixelformat, but SetPixelFormat can only be called once for a window... */ + glxWinSetPixelFormat(gc, hdc, 0, GLX_WINDOW_BIT); + } + } + } + break; + + case GLX_DRAWABLE_PBUFFER: + { + hdc = wglGetPbufferDCARBWrapper(draw->hPbuffer); + + if (hdc == NULL) + ErrorF("GetDC (pbuffer) error: %s\n", glxWinErrorMessage()); + } + break; + + case GLX_DRAWABLE_PIXMAP: + { + hdc = draw->dibDC; +#ifdef _DEBUG + if (glxWinDebugSettings.dumpDC) + GLWIN_DEBUG_MSG("Got PIXMAP HDC %p for window %p", hdc, *hwnd); +#endif + } + break; + + default: + { + ErrorF("glxWinMakeDC: tried to makeDC for unhandled drawable type %d\n", draw->base.type); + } + } + +#ifdef _DEBUG + if (glxWinDebugSettings.dumpDC) + GLWIN_HDC_DEBUG_MSG("Got HDC %p for window %p", hdc, *hwnd); +#endif + + return hdc; +} + +static void +glxWinReleaseDC(HWND hwnd, HDC hdc,__GLXWinDrawable *draw) +{ + switch (draw->base.type) + { + case GLX_DRAWABLE_WINDOW: + { + ReleaseDC(hwnd, hdc); + } + break; + + case GLX_DRAWABLE_PBUFFER: + { + if (!wglReleasePbufferDCARBWrapper(draw->hPbuffer, hdc)) + { + ErrorF("wglReleasePbufferDCARB error: %s\n", glxWinErrorMessage()); + } + } + break; + + case GLX_DRAWABLE_PIXMAP: + { + // don't release DC, the memory DC lives as long as the bitmap + + // We must ensure that all GDI drawing into the bitmap has completed + // in case we subsequently access the bits from it + GdiFlush(); + } + break; + + default: + { + ErrorF("glxWinReleaseDC: tried to releaseDC for unhandled drawable type %d\n", draw->base.type); + } + } +} + +static void +glxWinDeferredCreateContext(__GLXWinContext *gc, __GLXWinDrawable *draw) +{ + HWND hwnd; + GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attach context %p to drawable %p", gc, draw); + + switch (draw->base.type) + { + case GLX_DRAWABLE_WINDOW: + { + WindowPtr pWin = (WindowPtr) draw->base.pDraw; + + if (!(gc->base.config->drawableType & GLX_WINDOW_BIT)) + { + ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_WINDOW_BIT to a GLX_DRAWABLE_WINDOW drawable\n"); + } + + if (pWin == NULL) + { + GLWIN_DEBUG_MSG("Deferring until X window is created"); + return; + } + + GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pWin %p", pWin); + + if (winGetWindowInfo(pWin) == NULL) + { + GLWIN_DEBUG_MSG("Deferring until native window is created"); + return; + } + } + break; + + case GLX_DRAWABLE_PBUFFER: + { + if (draw->hPbuffer == NULL) + { + __GLXscreen *screen; + glxWinScreen *winScreen; + int pixelFormat; + // XXX: which DC are supposed to use??? + HDC screenDC = GetDC(NULL); + + if (!(gc->base.config->drawableType & GLX_PBUFFER_BIT)) + { + ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PBUFFER_BIT to a GLX_DRAWABLE_PBUFFER drawable\n"); + } + + screen = gc->base.pGlxScreen; + winScreen = (glxWinScreen *)screen; + + pixelFormat = fbConfigToPixelFormatIndex(screenDC, gc->base.config, GLX_DRAWABLE_PBUFFER, winScreen); + if (pixelFormat == 0) + { + ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage()); + return; + } + + draw->hPbuffer = wglCreatePbufferARBWrapper(screenDC, pixelFormat, draw->base.pDraw->width, draw->base.pDraw->height, NULL); + ReleaseDC(NULL, screenDC); + + if (draw->hPbuffer == NULL) + { + ErrorF("wglCreatePbufferARBWrapper error: %s\n", glxWinErrorMessage()); + return; + } + + GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: pBuffer %p created for drawable %p", draw->hPbuffer, draw); + } + } + break; + + case GLX_DRAWABLE_PIXMAP: + { + if (draw->dibDC == NULL) + { + BITMAPINFOHEADER bmpHeader; + void *pBits; + + memset (&bmpHeader, 0, sizeof(BITMAPINFOHEADER)); + bmpHeader.biSize = sizeof(BITMAPINFOHEADER); + bmpHeader.biWidth = draw->base.pDraw->width; + bmpHeader.biHeight = draw->base.pDraw->height; + bmpHeader.biPlanes = 1; + bmpHeader.biBitCount = draw->base.pDraw->bitsPerPixel; + bmpHeader.biCompression = BI_RGB; + + if (!(gc->base.config->drawableType & GLX_PIXMAP_BIT)) + { + ErrorF("glxWinDeferredCreateContext: tried to attach a context whose fbConfig doesn't have drawableType GLX_PIXMAP_BIT to a GLX_DRAWABLE_PIXMAP drawable\n"); + } + + draw->dibDC = CreateCompatibleDC(NULL); + if (draw->dibDC == NULL) + { + ErrorF("CreateCompatibleDC error: %s\n", glxWinErrorMessage()); + return; + } + + draw->hDIB = CreateDIBSection(draw->dibDC, (BITMAPINFO *)&bmpHeader, DIB_RGB_COLORS, &pBits, 0, 0); + if (draw->dibDC == NULL) + { + ErrorF("CreateDIBSection error: %s\n", glxWinErrorMessage()); + return; + } + + // XXX: CreateDIBSection insists on allocating the bitmap memory for us, so we're going to + // need some jiggery pokery to point the underlying X Drawable's bitmap at the same set of bits + // so that they can be read with XGetImage as well as glReadPixels, assuming the formats are + // even compatible ... + draw->pOldBits = ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr; + ((PixmapPtr)draw->base.pDraw)->devPrivate.ptr = pBits; + + // Select the DIB into the DC + draw->hOldDIB = SelectObject(draw->dibDC, draw->hDIB); + if (!draw->hOldDIB) + { + ErrorF("SelectObject error: %s\n", glxWinErrorMessage()); + } + + // Set the pixel format of the bitmap + glxWinSetPixelFormat(gc, draw->dibDC, draw->base.pDraw->bitsPerPixel, GLX_PIXMAP_BIT); + + GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: DIB bitmap %p created for drawable %p", draw->hDIB, draw); + } + } + break; + + default: + { + ErrorF("glxWinDeferredCreateContext: tried to attach unhandled drawable type %d\n", draw->base.type); + return; + } + } + + gc->hDC = glxWinMakeDC(gc, draw, &hwnd); + gc->ctx = wglCreateContext(gc->hDC); + + if (gc->ctx == NULL) + { + glxWinReleaseDC(hwnd, gc->hDC, draw); + gc->hDC=0; + + ErrorF("wglCreateContext error: %s\n", glxWinErrorMessage()); + return; + } + + GLWIN_DEBUG_MSG("glxWinDeferredCreateContext: attached context %p to native context %p drawable %p", gc, gc->ctx, draw); + + // if the native context was created successfully, shareLists if needed + if (gc->ctx && gc->shareContext) + { + GLWIN_DEBUG_MSG("glxWinCreateContextReal shareLists with context %p (native ctx %p)", gc->shareContext, gc->shareContext->ctx); + + if (!wglShareLists(gc->shareContext->ctx, gc->ctx)) + { + ErrorF("wglShareLists error: %s\n", glxWinErrorMessage()); + } + } +} + +/* ---------------------------------------------------------------------- */ +/* + * Context functions + */ + + +/* Context manipulation routines should return TRUE on success, FALSE on failure */ +static int +glxWinContextMakeCurrent(__GLXcontext *base) +{ + __GLXWinContext *gc = (__GLXWinContext *)base; + BOOL ret; + __GLXWinDrawable *drawPriv; + +#ifdef _DEBUG + GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc, gc->ctx); + glWinCallDelta(); +#endif + + /* Keep a note of the last active context in the drawable */ + drawPriv = (__GLXWinDrawable *)gc->base.drawPriv; + drawPriv->drawContext = gc; + + if (gc->ctx == NULL) + { + glxWinDeferredCreateContext(gc, drawPriv); + } + + if (gc->ctx == NULL) + { + ErrorF("glxWinContextMakeCurrent: Native context is NULL\n"); + return FALSE; + } + + if ((gc->base.readPriv != NULL) && (gc->base.readPriv != gc->base.drawPriv)) + { + // XXX: should only occur with WGL_ARB_make_current_read + /* + If there is a separate read drawable, create a separate read DC, and + use the wglMakeContextCurrent extension to make the context current drawing + to one DC and reading from the other + */ + gc->hreadDC = glxWinMakeDC(gc, (__GLXWinDrawable *)gc->base.readPriv, &gc->hreadwnd); + if (gc->hreadDC == NULL) + { + ErrorF("glxWinMakeDC failed for readDC\n"); + return FALSE; + } + + ret = wglMakeContextCurrentARBWrapper(gc->hDC, gc->hreadDC, gc->ctx); + if (!ret) + { + ErrorF("wglMakeContextCurrentARBWrapper error: %s\n", glxWinErrorMessage()); + } + } + else + { + /* Otherwise, just use wglMakeCurrent */ + if (!gc->hDC) + { + /* It probably has been release by loseCurrent, so create it again */ + gc->hDC = glxWinMakeDC(gc, drawPriv, &gc->hwnd); + } + ret = wglMakeCurrent(gc->hDC, gc->ctx); + if (!ret) + { + DWORD ErrorCode=GetLastError(); + ErrorF("wglMakeCurrent error: %x dc %p ctx %p\n", ErrorCode,gc->hDC,gc->ctx); + if (!ErrorCode) + { + ErrorF("Error code was 0, assuming no error.\n"); + ret=TRUE; + } + } + } + + // apparently make current could fail if the context is current in a different thread, + // but that shouldn't be able to happen in the current server... + + return ret; +} + +static int +glxWinContextLoseCurrent(__GLXcontext *base) +{ + BOOL ret=TRUE; + __GLXWinContext *gc = (__GLXWinContext *)base; + +#ifdef _DEBUG + GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc, gc->ctx); + glWinCallDelta(); +#endif + + + if (wglGetCurrentContext()==gc->ctx) + { + /* Only do this when we are sure we are currently the active, otherwise we are deactivating the wrong one (this is happening!!!) */ + ret = wglMakeCurrent(NULL, NULL); + if (!ret) + ErrorF("glxWinContextLoseCurrent error: %s\n", glxWinErrorMessage()); + } + else + { + return FALSE; + } + + /* Since drawPriv is going to be set to zero in the context, we have to release the DC to */ + if (gc->hDC && gc->base.drawPriv) glxWinReleaseDC(gc->hwnd, gc->hDC, (__GLXWinDrawable *)gc->base.drawPriv); + if (gc->hreadDC && gc->base.readPriv) glxWinReleaseDC(gc->hreadwnd, gc->hreadDC, (__GLXWinDrawable *)gc->base.readPriv); + gc->hDC=NULL; + gc->hreadDC=NULL; + + base->isCurrent=FALSE; /* It looks like glx is not doing this */ + + return ret; +} + +static int +glxWinContextCopy(__GLXcontext *dst_base, __GLXcontext *src_base, unsigned long mask) +{ + __GLXWinContext *dst = (__GLXWinContext *)dst_base; + __GLXWinContext *src = (__GLXWinContext *)src_base; + BOOL ret; + + GLWIN_DEBUG_MSG("glxWinContextCopy"); + + ret = wglCopyContext(src->ctx, dst->ctx, mask); + if (!ret) + { + ErrorF("wglCopyContext error: %s\n", glxWinErrorMessage()); + } + + return ret; +} + +static int +glxWinContextForceCurrent(__GLXcontext *base) +{ + /* wglMakeCurrent always flushes the previous context, so this is equivalent to glxWinContextMakeCurrent */ + return glxWinContextMakeCurrent(base); +} + +static void +glxWinContextDestroy(__GLXcontext *base) +{ + __GLXWinContext *gc = (__GLXWinContext *)base; + + if (gc != NULL) + { + GLWIN_DEBUG_MSG("GLXcontext %p destroyed (native ctx %p)", base, gc->ctx); + + if (gc->ctx) + { + BOOL ret; + /* It's bad style to delete the context while it's still current */ + if (wglGetCurrentContext() == gc->ctx) + { + wglMakeCurrent(NULL, NULL); + } + + ret = wglDeleteContext(gc->ctx); + if (!ret) + ErrorF("wglDeleteContext error: %s\n", glxWinErrorMessage()); + if (gc->base.drawPriv && gc->hDC) glxWinReleaseDC(gc->hwnd, gc->hDC, (__GLXWinDrawable *)gc->base.drawPriv); + if (gc->base.readPriv && gc->hreadDC) glxWinReleaseDC(gc->hreadwnd, gc->hreadDC, (__GLXWinDrawable *)gc->base.readPriv); + gc->hDC=NULL; + gc->hreadDC=NULL; + gc->ctx = NULL; + } + + free(gc); + } +} + +static __GLXcontext * +glxWinCreateContext(__GLXscreen *screen, + __GLXconfig *modes, + __GLXcontext *baseShareContext) +{ + __GLXWinContext *context; + __GLXWinContext *shareContext = (__GLXWinContext *)baseShareContext; + + static __GLXtextureFromPixmap glxWinTextureFromPixmap = + { + glxWinBindTexImage, + glxWinReleaseTexImage + }; + + context = (__GLXWinContext *)calloc(1, sizeof(__GLXWinContext)); + + if (!context) + return NULL; + + memset(context, 0, sizeof *context); + context->base.destroy = glxWinContextDestroy; + context->base.makeCurrent = glxWinContextMakeCurrent; + context->base.loseCurrent = glxWinContextLoseCurrent; + context->base.copy = glxWinContextCopy; + context->base.forceCurrent = glxWinContextForceCurrent; + context->base.textureFromPixmap = &glxWinTextureFromPixmap; + context->base.config = modes; + context->base.pGlxScreen = screen; + + // actual native GL context creation is deferred until attach() + //context->ctx = NULL; already done with memset + context->shareContext = shareContext; + + glWinSetupDispatchTable(); + + GLWIN_DEBUG_MSG("GLXcontext %p created", context); + + return &(context->base); +} + +/* ---------------------------------------------------------------------- */ +/* + * Utility functions + */ + +static int +fbConfigToPixelFormat(__GLXconfig *mode, PIXELFORMATDESCRIPTOR *pfdret, int drawableTypeOverride) +{ + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ + 1, /* version number */ + PFD_SUPPORT_OPENGL, /* support OpenGL */ + PFD_TYPE_RGBA, /* RGBA type */ + 24, /* 24-bit color depth */ + 0, 0, 0, 0, 0, 0, /* color bits ignored */ + 0, /* no alpha buffer */ + 0, /* shift bit ignored */ + 0, /* no accumulation buffer */ + 0, 0, 0, 0, /* accum bits ignored */ + 32, /* 32-bit z-buffer */ + 0, /* no stencil buffer */ + 0, /* no auxiliary buffer */ + PFD_MAIN_PLANE, /* main layer */ + 0, /* reserved */ + 0, 0, 0 /* layer masks ignored */ + }; + + if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT) + pfd.dwFlags |= PFD_DRAW_TO_WINDOW; /* support window */ + + if ((mode->drawableType | drawableTypeOverride) & GLX_PIXMAP_BIT) + pfd.dwFlags |= (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI); /* supports software rendering to bitmap */ + + if (mode->stereoMode) { + pfd.dwFlags |= PFD_STEREO; + } + if (mode->doubleBufferMode) { + pfd.dwFlags |= PFD_DOUBLEBUFFER; + } + + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = mode->redBits + mode->greenBits + mode->blueBits; + pfd.cRedBits = mode->redBits; + pfd.cRedShift = 0; /* FIXME */ + pfd.cGreenBits = mode->greenBits; + pfd.cGreenShift = 0; /* FIXME */ + pfd.cBlueBits = mode->blueBits; + pfd.cBlueShift = 0; /* FIXME */ + pfd.cAlphaBits = mode->alphaBits; + pfd.cAlphaShift = 0; /* FIXME */ + + pfd.cAccumBits = mode->accumRedBits + mode->accumGreenBits + mode->accumBlueBits + mode->accumAlphaBits; + pfd.cAccumRedBits = mode->accumRedBits; + pfd.cAccumGreenBits = mode->accumGreenBits; + pfd.cAccumBlueBits = mode->accumBlueBits; + pfd.cAccumAlphaBits = mode->accumAlphaBits; + + pfd.cDepthBits = mode->depthBits; + pfd.cStencilBits = mode->stencilBits; + pfd.cAuxBuffers = mode->numAuxBuffers; + + /* mode->level ? */ + /* mode->pixmapMode ? */ + + *pfdret = pfd; + + return 0; +} + +#define SET_ATTR_VALUE(attr, value) { attribList[i++] = attr; attribList[i++] = value; assert(i < NUM_ELEMENTS(attribList)); } + +static int +fbConfigToPixelFormatIndex(HDC hdc, __GLXconfig *mode, int drawableTypeOverride, glxWinScreen *winScreen) +{ + UINT numFormats; + unsigned int i = 0; + + /* convert fbConfig to attr-value list */ + int attribList[60]; + + SET_ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, TRUE); + SET_ATTR_VALUE(WGL_PIXEL_TYPE_ARB, (mode->visualType == GLX_TRUE_COLOR) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB); + SET_ATTR_VALUE(WGL_COLOR_BITS_ARB, (mode->visualType == GLX_TRUE_COLOR) ? mode->rgbBits : mode->indexBits); + SET_ATTR_VALUE(WGL_RED_BITS_ARB, mode->redBits); + SET_ATTR_VALUE(WGL_GREEN_BITS_ARB, mode->greenBits); + SET_ATTR_VALUE(WGL_BLUE_BITS_ARB, mode->blueBits); + SET_ATTR_VALUE(WGL_ALPHA_BITS_ARB, mode->alphaBits); + SET_ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, mode->accumRedBits); + SET_ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, mode->accumGreenBits); + SET_ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, mode->accumBlueBits); + SET_ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, mode->accumAlphaBits); + SET_ATTR_VALUE(WGL_DEPTH_BITS_ARB, mode->depthBits); + SET_ATTR_VALUE(WGL_STENCIL_BITS_ARB, mode->stencilBits); + SET_ATTR_VALUE(WGL_AUX_BUFFERS_ARB, mode->numAuxBuffers); + + if (mode->doubleBufferMode) + SET_ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, TRUE); + + if (mode->stereoMode) + SET_ATTR_VALUE(WGL_STEREO_ARB, TRUE); + + // Some attributes are only added to the list if the value requested is not 'don't care', as exactly matching that is daft.. + if (mode->swapMethod == GLX_SWAP_EXCHANGE_OML) + SET_ATTR_VALUE(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB); + + if (mode->swapMethod == GLX_SWAP_COPY_OML) + SET_ATTR_VALUE(WGL_SWAP_COPY_ARB, TRUE); + + // XXX: this should probably be the other way around, but that messes up drawableTypeOverride + if (mode->visualRating == GLX_SLOW_VISUAL_EXT) + SET_ATTR_VALUE(WGL_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB); + + // must support all the drawable types the mode supports + if ((mode->drawableType | drawableTypeOverride) & GLX_WINDOW_BIT) + SET_ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB,TRUE); + + // XXX: this is a horrible hacky heuristic, in fact this whole drawableTypeOverride thing is a bad idea + // try to avoid asking for formats which don't exist (by not asking for all when adjusting the config to include the drawableTypeOverride) + if (drawableTypeOverride == GLX_WINDOW_BIT) + { + if (mode->drawableType & GLX_PIXMAP_BIT) + SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE); + + if (mode->drawableType & GLX_PBUFFER_BIT) + if (winScreen->has_WGL_ARB_pbuffer) + SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE); + } + else + { + if (drawableTypeOverride & GLX_PIXMAP_BIT) + SET_ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, TRUE); + + if (drawableTypeOverride & GLX_PBUFFER_BIT) + if (winScreen->has_WGL_ARB_pbuffer) + SET_ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, TRUE); + } + + SET_ATTR_VALUE(0, 0); // terminator + + /* choose the first match */ + { + int pixelFormatIndex; + + if (!wglChoosePixelFormatARBWrapper(hdc, attribList, NULL, 1, &pixelFormatIndex, &numFormats)) + { + ErrorF("wglChoosePixelFormat error: %s\n", glxWinErrorMessage()); + } + else + { + if (numFormats > 0) + { + GLWIN_DEBUG_MSG("wglChoosePixelFormat: chose pixelFormatIndex %d)", pixelFormatIndex); + return pixelFormatIndex; + } + else + ErrorF("wglChoosePixelFormat couldn't decide\n"); + } + } + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +#define BITS_AND_SHIFT_TO_MASK(bits,mask) (((1<<(bits))-1) << (mask)) + +// +// Create the GLXconfigs using DescribePixelFormat() +// +static void +glxWinCreateConfigs(HDC hdc, glxWinScreen *screen) +{ + GLXWinConfig *c, *result, *prev = NULL; + int numConfigs = 0; + int i = 0; + int n = 0; + PIXELFORMATDESCRIPTOR pfd; + + GLWIN_DEBUG_MSG("glxWinCreateConfigs"); + + screen->base.numFBConfigs = 0; + screen->base.fbconfigs = NULL; + + // get the number of pixelformats + numConfigs = DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL); + GLWIN_DEBUG_MSG("DescribePixelFormat says %d possible pixel formats", numConfigs); + + /* alloc */ + result = malloc(sizeof(GLXWinConfig) * numConfigs); + + if (NULL == result) + { + return; + } + + memset(result, 0, sizeof(GLXWinConfig) * numConfigs); + n = 0; + + /* fill in configs */ + for (i = 0; i < numConfigs; i++) + { + int rc; + + c = &(result[i]); + c->base.next = NULL; + c->pixelFormatIndex = i+1; + + rc = DescribePixelFormat(hdc, i+1, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + if (!rc) + { + ErrorF("DescribePixelFormat failed for index %d, error %s\n", i+1, glxWinErrorMessage()); + break; + } + +#ifdef _DEBUG + if (glxWinDebugSettings.dumpPFD) + pfdOut(&pfd); +#endif + + if (!(pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP)) || !(pfd.dwFlags & PFD_SUPPORT_OPENGL)) + { + GLWIN_DEBUG_MSG("pixelFormat %d has unsuitable flags 0x%08lx, skipping", i+1, pfd.dwFlags); + continue; + } + + c->base.doubleBufferMode = (pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE; + c->base.stereoMode = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE; + + c->base.redBits = pfd.cRedBits; + c->base.greenBits = pfd.cGreenBits; + c->base.blueBits = pfd.cBlueBits; + c->base.alphaBits = pfd.cAlphaBits; + + c->base.redMask = BITS_AND_SHIFT_TO_MASK(pfd.cRedBits, pfd.cRedShift); + c->base.greenMask = BITS_AND_SHIFT_TO_MASK(pfd.cGreenBits, pfd.cGreenShift); + c->base.blueMask = BITS_AND_SHIFT_TO_MASK(pfd.cBlueBits, pfd.cBlueShift); + c->base.alphaMask = BITS_AND_SHIFT_TO_MASK(pfd.cAlphaBits, pfd.cAlphaShift); + + c->base.rgbBits = pfd.cColorBits; + + if (pfd.iPixelType == PFD_TYPE_COLORINDEX) + { + c->base.indexBits = pfd.cColorBits; + } + else + { + c->base.indexBits = 0; + } + + c->base.accumRedBits = pfd.cAccumRedBits; + c->base.accumGreenBits = pfd.cAccumGreenBits; + c->base.accumBlueBits = pfd.cAccumBlueBits; + c->base.accumAlphaBits = pfd.cAccumAlphaBits; + // pfd.cAccumBits; + + c->base.depthBits = pfd.cDepthBits; + c->base.stencilBits = pfd.cStencilBits; + c->base.numAuxBuffers = pfd.cAuxBuffers; + + // pfd.iLayerType; // ignored + c->base.level = 0; + // pfd.dwLayerMask; // ignored + // pfd.dwDamageMask; // ignored + + c->base.pixmapMode = 0; + c->base.visualID = -1; // will be set by __glXScreenInit() + + /* EXT_visual_rating / GLX 1.2 */ + if (pfd.dwFlags & PFD_GENERIC_FORMAT) + { + c->base.visualRating = GLX_SLOW_VISUAL_EXT; + } + else + { + // PFD_GENERIC_ACCELERATED is not considered, so this may be MCD or ICD acclerated... + c->base.visualRating = GLX_NONE_EXT; + } + + /* EXT_visual_info / GLX 1.2 */ + if (pfd.iPixelType == PFD_TYPE_COLORINDEX) + { + c->base.visualType = GLX_STATIC_COLOR; + } + else + { + c->base.visualType = GLX_TRUE_COLOR; + } + + // pfd.dwVisibleMask; ??? + c->base.transparentPixel = GLX_NONE; + c->base.transparentRed = GLX_NONE; + c->base.transparentGreen = GLX_NONE; + c->base.transparentBlue = GLX_NONE; + c->base.transparentAlpha = GLX_NONE; + c->base.transparentIndex = GLX_NONE; + + /* ARB_multisample / SGIS_multisample */ + c->base.sampleBuffers = 0; + c->base.samples = 0; + + /* SGIX_fbconfig / GLX 1.3 */ + c->base.drawableType = (((pfd.dwFlags & PFD_DRAW_TO_WINDOW) ? GLX_WINDOW_BIT : 0) + | ((pfd.dwFlags & PFD_DRAW_TO_BITMAP) ? GLX_PIXMAP_BIT : 0)); + + if (pfd.iPixelType == PFD_TYPE_COLORINDEX) + { + c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT; + } + else + { + c->base.renderType = GLX_RGBA_BIT; + } + + c->base.xRenderable = GL_TRUE; + c->base.fbconfigID = -1; // will be set by __glXScreenInit() + + /* SGIX_pbuffer / GLX 1.3 */ + // XXX: How can we find these values out ??? + c->base.maxPbufferWidth = -1; + c->base.maxPbufferHeight = -1; + c->base.maxPbufferPixels = -1; + c->base.optimalPbufferWidth = 0; // there is no optimal value + c->base.optimalPbufferHeight = 0; + + /* SGIX_visual_select_group */ + // arrange for visuals with the best acceleration to be preferred in selection + switch (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) + { + case 0: + c->base.visualSelectGroup = 2; + break; + + case PFD_GENERIC_ACCELERATED: + c->base.visualSelectGroup = 1; + break; + + case PFD_GENERIC_FORMAT: + c->base.visualSelectGroup = 0; + break; + + default: + ; + // "can't happen" + } + + /* OML_swap_method */ + if (pfd.dwFlags & PFD_SWAP_EXCHANGE) + c->base.swapMethod = GLX_SWAP_EXCHANGE_OML; + else if (pfd.dwFlags & PFD_SWAP_COPY) + c->base.swapMethod = GLX_SWAP_COPY_OML; + else + c->base.swapMethod = GLX_SWAP_UNDEFINED_OML; + + /* EXT_import_context */ + c->base.screen = screen->base.pScreen->myNum; + + /* EXT_texture_from_pixmap */ + c->base.bindToTextureRgb = -1; + c->base.bindToTextureRgba = -1; + c->base.bindToMipmapTexture = -1; + c->base.bindToTextureTargets = -1; + c->base.yInverted = -1; + + n++; + + // update previous config to point to this config + if (prev) + prev->base.next = &(c->base); + + prev = c; + } + + GLWIN_DEBUG_MSG("found %d pixelFormats suitable for conversion to fbConfigs", n); + + screen->base.numFBConfigs = n; + screen->base.fbconfigs = &(result->base); +} + +// helper function to access an attribute value from an attribute value array by attribute +static +int getAttrValue(const int attrs[], int values[], unsigned int num, int attr, int fallback) +{ + unsigned int i; + for (i = 0; i < num; i++) + { + if (attrs[i] == attr) + { + GLWIN_TRACE_MSG("getAttrValue attr 0x%x, value %d", attr, values[i]); + return values[i]; + } + } + + ErrorF("getAttrValue failed to find attr 0x%x, using default value %d\n", attr, fallback); + return fallback; +} + +// +// Create the GLXconfigs using wglGetPixelFormatAttribfvARB() extension +// +static void +glxWinCreateConfigsExt(HDC hdc, glxWinScreen *screen) +{ + GLXWinConfig *c, *result, *prev = NULL; + int i = 0; + int n = 0; + + const int attr = WGL_NUMBER_PIXEL_FORMATS_ARB; + int numConfigs; + + int attrs[50]; + unsigned int num_attrs = 0; + + GLWIN_DEBUG_MSG("glxWinCreateConfigsExt"); + + screen->base.numFBConfigs = 0; + screen->base.fbconfigs = NULL; + + if (!wglGetPixelFormatAttribivARBWrapper(hdc, 0, 0, 1, &attr, &numConfigs)) + { + ErrorF("wglGetPixelFormatAttribivARB failed for WGL_NUMBER_PIXEL_FORMATS_ARB: %s\n", glxWinErrorMessage()); + return; + } + + GLWIN_DEBUG_MSG("wglGetPixelFormatAttribivARB says %d possible pixel formats", numConfigs); + + /* alloc */ + result = malloc(sizeof(GLXWinConfig) * numConfigs); + + if (NULL == result) + { + return; + } + + memset(result, 0, sizeof(GLXWinConfig) * numConfigs); + n = 0; + +#define ADD_ATTR(a) { attrs[num_attrs++] = a; assert(num_attrs < NUM_ELEMENTS(attrs)); } + + ADD_ATTR(WGL_DRAW_TO_WINDOW_ARB); + ADD_ATTR(WGL_DRAW_TO_BITMAP_ARB); + ADD_ATTR(WGL_ACCELERATION_ARB); + ADD_ATTR(WGL_SWAP_LAYER_BUFFERS_ARB); + ADD_ATTR(WGL_NUMBER_OVERLAYS_ARB); + ADD_ATTR(WGL_NUMBER_UNDERLAYS_ARB); + ADD_ATTR(WGL_TRANSPARENT_ARB); + ADD_ATTR(WGL_TRANSPARENT_RED_VALUE_ARB); + ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB); + ADD_ATTR(WGL_TRANSPARENT_GREEN_VALUE_ARB); + ADD_ATTR(WGL_TRANSPARENT_ALPHA_VALUE_ARB); + ADD_ATTR(WGL_SUPPORT_OPENGL_ARB); + ADD_ATTR(WGL_DOUBLE_BUFFER_ARB); + ADD_ATTR(WGL_STEREO_ARB); + ADD_ATTR(WGL_PIXEL_TYPE_ARB); + ADD_ATTR(WGL_COLOR_BITS_ARB); + ADD_ATTR(WGL_RED_BITS_ARB); + ADD_ATTR(WGL_RED_SHIFT_ARB); + ADD_ATTR(WGL_GREEN_BITS_ARB); + ADD_ATTR(WGL_GREEN_SHIFT_ARB); + ADD_ATTR(WGL_BLUE_BITS_ARB); + ADD_ATTR(WGL_BLUE_SHIFT_ARB); + ADD_ATTR(WGL_ALPHA_BITS_ARB); + ADD_ATTR(WGL_ALPHA_SHIFT_ARB); + ADD_ATTR(WGL_ACCUM_RED_BITS_ARB); + ADD_ATTR(WGL_ACCUM_GREEN_BITS_ARB); + ADD_ATTR(WGL_ACCUM_BLUE_BITS_ARB); + ADD_ATTR(WGL_ACCUM_ALPHA_BITS_ARB); + ADD_ATTR(WGL_DEPTH_BITS_ARB); + ADD_ATTR(WGL_STENCIL_BITS_ARB); + ADD_ATTR(WGL_AUX_BUFFERS_ARB); + ADD_ATTR(WGL_SWAP_METHOD_ARB); + + if (screen->has_WGL_ARB_multisample) + { + // we may not query these attrs if WGL_ARB_multisample is not offered + ADD_ATTR(WGL_SAMPLE_BUFFERS_ARB); + ADD_ATTR(WGL_SAMPLES_ARB); + } + + if (screen->has_WGL_ARB_render_texture) + { + // we may not query these attrs if WGL_ARB_render_texture is not offered + ADD_ATTR(WGL_BIND_TO_TEXTURE_RGB_ARB); + ADD_ATTR(WGL_BIND_TO_TEXTURE_RGBA_ARB); + } + + if (screen->has_WGL_ARB_pbuffer) + { + // we may not query these attrs if WGL_ARB_pbuffer is not offered + ADD_ATTR(WGL_DRAW_TO_PBUFFER_ARB); + ADD_ATTR(WGL_MAX_PBUFFER_PIXELS_ARB); + ADD_ATTR(WGL_MAX_PBUFFER_WIDTH_ARB); + ADD_ATTR(WGL_MAX_PBUFFER_HEIGHT_ARB); + } + + /* fill in configs */ + for (i = 0; i < numConfigs; i++) + { + int sizevalues=num_attrs*sizeof(int); + int *values=(int*)_alloca(sizevalues); + + memset(values,0,sizevalues); + + c = &(result[i]); + c->base.next = NULL; + c->pixelFormatIndex = i+1; + + if (!wglGetPixelFormatAttribivARBWrapper(hdc, i+1, 0, num_attrs, attrs, values)) + { + ErrorF("wglGetPixelFormatAttribivARB failed for index %d, error %s\n", i+1, glxWinErrorMessage()); + break; + } + +#define ATTR_VALUE(a, d) getAttrValue(attrs, values, num_attrs, (a), (d)) + + if (!ATTR_VALUE(WGL_SUPPORT_OPENGL_ARB, 0)) + { + GLWIN_DEBUG_MSG("pixelFormat %d isn't WGL_SUPPORT_OPENGL_ARB, skipping", i+1); + continue; + } + + c->base.doubleBufferMode = ATTR_VALUE(WGL_DOUBLE_BUFFER_ARB, 0) ? GL_TRUE : GL_FALSE; + c->base.stereoMode = ATTR_VALUE(WGL_STEREO_ARB, 0) ? GL_TRUE : GL_FALSE; + + c->base.redBits = ATTR_VALUE(WGL_RED_BITS_ARB, 0); + c->base.greenBits = ATTR_VALUE(WGL_GREEN_BITS_ARB, 0); + c->base.blueBits = ATTR_VALUE(WGL_BLUE_BITS_ARB, 0); + c->base.alphaBits = ATTR_VALUE(WGL_ALPHA_BITS_ARB, 0); + + c->base.redMask = BITS_AND_SHIFT_TO_MASK(c->base.redBits, ATTR_VALUE(WGL_RED_SHIFT_ARB, 0)); + c->base.greenMask = BITS_AND_SHIFT_TO_MASK(c->base.greenBits, ATTR_VALUE(WGL_GREEN_SHIFT_ARB, 0)); + c->base.blueMask = BITS_AND_SHIFT_TO_MASK(c->base.blueBits, ATTR_VALUE(WGL_BLUE_SHIFT_ARB, 0)); + c->base.alphaMask = BITS_AND_SHIFT_TO_MASK(c->base.alphaBits, ATTR_VALUE(WGL_ALPHA_SHIFT_ARB, 0)); + + switch (ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)) + { + case WGL_TYPE_COLORINDEX_ARB: + c->base.indexBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0); + c->base.rgbBits = 0; + c->base.visualType = GLX_STATIC_COLOR; + break; + + case WGL_TYPE_RGBA_FLOAT_ARB: + GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_FLOAT_ARB, skipping", i+1); + continue; + + case WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT: + GLWIN_DEBUG_MSG("pixelFormat %d is WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT, skipping", i+1); + continue; + + case WGL_TYPE_RGBA_ARB: + c->base.indexBits = 0; + c->base.rgbBits = ATTR_VALUE(WGL_COLOR_BITS_ARB, 0); + c->base.visualType = GLX_TRUE_COLOR; + break; + + default: + ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_PIXEL_TYPE_ARB\n", ATTR_VALUE(WGL_PIXEL_TYPE_ARB, 0)); + continue; + } + + c->base.accumRedBits = ATTR_VALUE(WGL_ACCUM_RED_BITS_ARB, 0); + c->base.accumGreenBits = ATTR_VALUE(WGL_ACCUM_GREEN_BITS_ARB, 0); + c->base.accumBlueBits = ATTR_VALUE(WGL_ACCUM_BLUE_BITS_ARB, 0); + c->base.accumAlphaBits = ATTR_VALUE(WGL_ACCUM_ALPHA_BITS_ARB, 0); + + c->base.depthBits = ATTR_VALUE(WGL_DEPTH_BITS_ARB, 0); + c->base.stencilBits = ATTR_VALUE(WGL_STENCIL_BITS_ARB, 0); + c->base.numAuxBuffers = ATTR_VALUE(WGL_AUX_BUFFERS_ARB, 0); + + { + int layers = ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0) + ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0); + + if (layers > 0) + { + ErrorF("pixelFormat %d: has %d overlay, %d underlays which aren't currently handled", i, ATTR_VALUE(WGL_NUMBER_OVERLAYS_ARB,0), ATTR_VALUE(WGL_NUMBER_UNDERLAYS_ARB, 0)); + // XXX: need to iterate over layers? + } + } + c->base.level = 0; + + c->base.pixmapMode = 0; // ??? + c->base.visualID = -1; // will be set by __glXScreenInit() + + /* EXT_visual_rating / GLX 1.2 */ + switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) + { + default: + ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_ACCELERATION_ARB\n", ATTR_VALUE(WGL_ACCELERATION_ARB, 0)); + + case WGL_NO_ACCELERATION_ARB: + c->base.visualRating = GLX_SLOW_VISUAL_EXT; + break; + + case WGL_GENERIC_ACCELERATION_ARB: + case WGL_FULL_ACCELERATION_ARB: + c->base.visualRating = GLX_NONE_EXT; + break; + } + + /* EXT_visual_info / GLX 1.2 */ + // c->base.visualType is set above + if (ATTR_VALUE(WGL_TRANSPARENT_ARB, 0)) + { + c->base.transparentPixel = (c->base.visualType == GLX_TRUE_COLOR) ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT; + c->base.transparentRed = ATTR_VALUE(WGL_TRANSPARENT_RED_VALUE_ARB, 0); + c->base.transparentGreen = ATTR_VALUE(WGL_TRANSPARENT_GREEN_VALUE_ARB, 0); + c->base.transparentBlue = ATTR_VALUE(WGL_TRANSPARENT_BLUE_VALUE_ARB, 0); + c->base.transparentAlpha = ATTR_VALUE(WGL_TRANSPARENT_ALPHA_VALUE_ARB, 0); + c->base.transparentIndex = ATTR_VALUE(WGL_TRANSPARENT_INDEX_VALUE_ARB, 0); + } + else + { + c->base.transparentPixel = GLX_NONE_EXT; + c->base.transparentRed = GLX_NONE; + c->base.transparentGreen = GLX_NONE; + c->base.transparentBlue = GLX_NONE; + c->base.transparentAlpha = GLX_NONE; + c->base.transparentIndex = GLX_NONE; + } + + /* ARB_multisample / SGIS_multisample */ + if (screen->has_WGL_ARB_multisample) + { + c->base.sampleBuffers = ATTR_VALUE(WGL_SAMPLE_BUFFERS_ARB, 0); + c->base.samples = ATTR_VALUE(WGL_SAMPLES_ARB, 0); + } + else + { + c->base.sampleBuffers = 0; + c->base.samples = 0; + } + + /* SGIX_fbconfig / GLX 1.3 */ + c->base.drawableType = ((ATTR_VALUE(WGL_DRAW_TO_WINDOW_ARB, 0) ? GLX_WINDOW_BIT : 0) + | (ATTR_VALUE(WGL_DRAW_TO_BITMAP_ARB, 0) ? GLX_PIXMAP_BIT : 0) + | (ATTR_VALUE(WGL_DRAW_TO_PBUFFER_ARB, 0) ? GLX_PBUFFER_BIT : 0)); + + /* + Assume OpenGL RGBA rendering is available on all visuals + (it is specified to render to red component in single-channel visuals, + if supported, but there doesn't seem to be any mechanism to check if it + is supported) + + Color index rendering is only supported on single-channel visuals + */ + if (c->base.visualType == GLX_STATIC_COLOR) + { + c->base.renderType = GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT; + } + else + { + c->base.renderType = GLX_RGBA_BIT; + } + + c->base.xRenderable = GL_TRUE; + c->base.fbconfigID = -1; // will be set by __glXScreenInit() + + /* SGIX_pbuffer / GLX 1.3 */ + if (screen->has_WGL_ARB_pbuffer) + { + c->base.maxPbufferWidth = ATTR_VALUE(WGL_MAX_PBUFFER_WIDTH_ARB, -1); + c->base.maxPbufferHeight = ATTR_VALUE(WGL_MAX_PBUFFER_HEIGHT_ARB, -1); + c->base.maxPbufferPixels = ATTR_VALUE(WGL_MAX_PBUFFER_PIXELS_ARB, -1); + } + else + { + c->base.maxPbufferWidth = -1; + c->base.maxPbufferHeight = -1; + c->base.maxPbufferPixels = -1; + } + c->base.optimalPbufferWidth = 0; // there is no optimal value + c->base.optimalPbufferHeight = 0; + + /* SGIX_visual_select_group */ + // arrange for visuals with the best acceleration to be preferred in selection + switch (ATTR_VALUE(WGL_ACCELERATION_ARB, 0)) + { + case WGL_FULL_ACCELERATION_ARB: + c->base.visualSelectGroup = 2; + break; + + case WGL_GENERIC_ACCELERATION_ARB: + c->base.visualSelectGroup = 1; + break; + + default: + case WGL_NO_ACCELERATION_ARB: + c->base.visualSelectGroup = 0; + break; + } + + /* OML_swap_method */ + switch (ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0)) + { + case WGL_SWAP_EXCHANGE_ARB: + c->base.swapMethod = GLX_SWAP_EXCHANGE_OML; + break; + + case WGL_SWAP_COPY_ARB: + c->base.swapMethod = GLX_SWAP_COPY_OML; + break; + + default: + ErrorF("wglGetPixelFormatAttribivARB returned unknown value 0x%x for WGL_SWAP_METHOD_ARB\n", ATTR_VALUE(WGL_SWAP_METHOD_ARB, 0)); + + case WGL_SWAP_UNDEFINED_ARB: + c->base.swapMethod = GLX_SWAP_UNDEFINED_OML; + } + + /* EXT_import_context */ + c->base.screen = screen->base.pScreen->myNum; + + /* EXT_texture_from_pixmap */ + /* + Mesa's DRI configs always have bindToTextureRgb/Rgba TRUE (see driCreateConfigs(), so setting + bindToTextureRgb/bindToTextureRgba to FALSE means that swrast can't find any fbConfigs to use, + so setting these to 0, even if we know bindToTexture isn't available, isn't a good idea... + */ + if (screen->has_WGL_ARB_render_texture) + { + c->base.bindToTextureRgb = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGB_ARB, -1); + c->base.bindToTextureRgba = ATTR_VALUE(WGL_BIND_TO_TEXTURE_RGBA_ARB, -1); + } + else + { + c->base.bindToTextureRgb = -1; + c->base.bindToTextureRgba = -1; + } + c->base.bindToMipmapTexture = -1; + c->base.bindToTextureTargets = GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT | GLX_TEXTURE_RECTANGLE_BIT_EXT; + c->base.yInverted = -1; + + n++; + + // update previous config to point to this config + if (prev) + prev->base.next = &(c->base); + + prev = c; + } + + screen->base.numFBConfigs = n; + screen->base.fbconfigs = &(result->base); +} diff --git a/xorg-server/hw/xwin/win.h b/xorg-server/hw/xwin/win.h index bb069afce..d0a41f9ea 100644 --- a/xorg-server/hw/xwin/win.h +++ b/xorg-server/hw/xwin/win.h @@ -1,1442 +1,1442 @@ -/* - *Copyright (C) 1994-2000 The XFree86 Project, 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 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. - * - * Authors: Dakshinamurthy Karra - * Suhaib M Siddiqi - * Peter Busch - * Harold L Hunt II - * Kensuke Matsuzaki - */ - -#ifndef _WIN_H_ -#define _WIN_H_ - -#ifndef NO -#define NO 0 -#endif -#ifndef YES -#define YES 1 -#endif - -/* WM_XBUTTON Messages. They should go into w32api. */ -#ifndef WM_XBUTTONDOWN -# define WM_XBUTTONDOWN 523 -#endif -#ifndef WM_XBUTTONUP -# define WM_XBUTTONUP 524 -#endif -#ifndef WM_XBUTTONDBLCLK -# define WM_XBUTTONDBLCLK 525 -#endif - - -#define WIN_DEFAULT_BPP 0 -#define WIN_DEFAULT_WHITEPIXEL 255 -#define WIN_DEFAULT_BLACKPIXEL 0 -#define WIN_DEFAULT_LINEBIAS 0 -#define WIN_DEFAULT_E3B_TIME 50 /* milliseconds */ -#define WIN_DEFAULT_DPI 75 -#define WIN_DEFAULT_REFRESH 0 -#define WIN_DEFAULT_WIN_KILL TRUE -#define WIN_DEFAULT_UNIX_KILL FALSE -#define WIN_DEFAULT_CLIP_UPDATES_NBOXES 0 -#ifdef XWIN_EMULATEPSEUDO -#define WIN_DEFAULT_EMULATE_PSEUDO FALSE -#endif -#define WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH FALSE - -#define WIN_DIB_MAXIMUM_SIZE 0x08000000 /* 16 MB on Windows 95, 98, Me */ -#define WIN_DIB_MAXIMUM_SIZE_MB (WIN_DIB_MAXIMUM_SIZE / 8 / 1024 / 1024) - -/* - * Windows only supports 256 color palettes - */ -#define WIN_NUM_PALETTE_ENTRIES 256 - -/* - * Number of times to call Restore in an attempt to restore the primary surface - */ -#define WIN_REGAIN_SURFACE_RETRIES 1 - -/* - * Build a supported display depths mask by shifting one to the left - * by the number of bits in the supported depth. - */ -#define WIN_SUPPORTED_BPPS ( (1 << (32 - 1)) | (1 << (24 - 1)) \ - | (1 << (16 - 1)) | (1 << (15 - 1)) \ - | (1 << ( 8 - 1))) -#define WIN_CHECK_DEPTH YES - -/* - * Timer IDs for WM_TIMER - */ -#define WIN_E3B_TIMER_ID 1 -#define WIN_POLLING_MOUSE_TIMER_ID 2 - -#define MOUSE_POLLING_INTERVAL 50 - -#define WIN_E3B_OFF -1 -#define WIN_FD_INVALID -1 - -#define WIN_SERVER_NONE 0x0L /* 0 */ -#define WIN_SERVER_SHADOW_GDI 0x1L /* 1 */ -#define WIN_SERVER_SHADOW_DD 0x2L /* 2 */ -#define WIN_SERVER_SHADOW_DDNL 0x4L /* 4 */ -#ifdef XWIN_PRIMARYFB -#define WIN_SERVER_PRIMARY_DD 0x8L /* 8 */ -#endif -#ifdef XWIN_NATIVEGDI -# define WIN_SERVER_NATIVE_GDI 0x10L /* 16 */ -#endif - -#define AltMapIndex Mod1MapIndex -#define NumLockMapIndex Mod2MapIndex -#define AltLangMapIndex Mod3MapIndex -#define KanaMapIndex Mod4MapIndex -#define ScrollLockMapIndex Mod5MapIndex - -#define WIN_MOD_LALT 0x00000001 -#define WIN_MOD_RALT 0x00000002 -#define WIN_MOD_LCONTROL 0x00000004 -#define WIN_MOD_RCONTROL 0x00000008 - -#define WIN_24BPP_MASK_RED 0x00FF0000 -#define WIN_24BPP_MASK_GREEN 0x0000FF00 -#define WIN_24BPP_MASK_BLUE 0x000000FF - -#define WIN_MAX_KEYS_PER_KEY 4 - -#include <sys/types.h> -#include <sys/stat.h> -#include <stdio.h> - -#include <errno.h> -#if defined(XWIN_MULTIWINDOWEXTWM) || defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) -#define HANDLE void * -#ifdef _MSC_VER -typedef int pid_t; -#endif -#include <pthread.h> -#undef HANDLE -#endif - -#ifdef HAS_MMAP -#include <sys/mman.h> -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif /* MAP_FILE */ -#endif /* HAS_MMAP */ - -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/Xos.h> -#include <X11/Xprotostr.h> -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "pixmap.h" -#include "region.h" -#include "gcstruct.h" -#include "colormap.h" -#include "colormapst.h" -#include "miscstruct.h" -#include "servermd.h" -#include "windowstr.h" -#include "mi.h" -#include "micmap.h" -#include "mifillarc.h" -#include "mifpoly.h" -#include "mibstore.h" -#include "input.h" -#include "mipointer.h" -#include "X11/keysym.h" -#include "mibstore.h" -#include "micoord.h" -#include "dix.h" -#include "miline.h" -#include "shadow.h" -#include "fb.h" -#include "rootless.h" - -#include "mipict.h" -#include "picturestr.h" - -#ifdef RANDR -#include "randrstr.h" -#endif - -/* - * Windows headers - */ -#include "winms.h" -#include "winresource.h" - - -/* - * Define Windows constants - */ - -#define WM_TRAYICON (WM_USER + 1000) -#define WM_INIT_SYS_MENU (WM_USER + 1001) -#define WM_GIVEUP (WM_USER + 1002) - - -/* Local includes */ -#include "winwindow.h" -#include "winmsg.h" - -#define PROFILEPOINT(point,thresh)\ -{\ -static unsigned int PROFPT##point = 0;\ -if (++PROFPT##point % thresh == 0)\ -ErrorF (#point ": PROFILEPOINT hit %u times\n", PROFPT##point);\ -} - - -/* We use xor this macro for detecting toggle key state changes */ -#define WIN_XOR(a,b) ((!(a) && (b)) || ((a) && !(b))) - -#define DEFINE_ATOM_HELPER(func,atom_name) \ -static Atom func (void) { \ - static int generation; \ - static Atom atom; \ - if (generation != serverGeneration) { \ - generation = serverGeneration; \ - atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ - } \ - return atom; \ -} - -/* - * Typedefs for engine dependent function pointers - */ - -typedef Bool (*winAllocateFBProcPtr)(ScreenPtr); - -typedef void (*winShadowUpdateProcPtr)(ScreenPtr, shadowBufPtr); - -typedef Bool (*winCloseScreenProcPtr)(int, ScreenPtr); - -typedef Bool (*winInitVisualsProcPtr)(ScreenPtr); - -typedef Bool (*winAdjustVideoModeProcPtr)(ScreenPtr); - -typedef Bool (*winCreateBoundingWindowProcPtr)(ScreenPtr); - -typedef Bool (*winFinishScreenInitProcPtr)(int, ScreenPtr, int, char **); - -typedef Bool (*winBltExposedRegionsProcPtr)(ScreenPtr); - -typedef Bool (*winActivateAppProcPtr)(ScreenPtr); - -typedef Bool (*winRedrawScreenProcPtr)(ScreenPtr pScreen); - -typedef Bool (*winRealizeInstalledPaletteProcPtr)(ScreenPtr pScreen); - -typedef Bool (*winInstallColormapProcPtr)(ColormapPtr pColormap); - -typedef Bool (*winStoreColorsProcPtr)(ColormapPtr pmap, - int ndef, xColorItem *pdefs); - -typedef Bool (*winCreateColormapProcPtr)(ColormapPtr pColormap); - -typedef Bool (*winDestroyColormapProcPtr)(ColormapPtr pColormap); - -typedef Bool (*winHotKeyAltTabProcPtr)(ScreenPtr); - -typedef Bool (*winCreatePrimarySurfaceProcPtr)(ScreenPtr); - -typedef Bool (*winReleasePrimarySurfaceProcPtr)(ScreenPtr); - -typedef Bool (*winFinishCreateWindowsWindowProcPtr)(WindowPtr pWin); - -typedef Bool (*winCreateScreenResourcesProc)(ScreenPtr); - -/* Typedef for DIX wrapper functions */ -typedef int (*winDispatchProcPtr) (ClientPtr); - - -/* - * GC (graphics context) privates - */ - -typedef struct -{ - HDC hdc; - HDC hdcMem; -} winPrivGCRec, *winPrivGCPtr; - - -/* - * Pixmap privates - */ - -typedef struct -{ - HDC hdcSelected; - HBITMAP hBitmap; - BYTE *pbBits; - DWORD dwScanlineBytes; - BITMAPINFOHEADER *pbmih; -} winPrivPixmapRec, *winPrivPixmapPtr; - - -/* - * Colormap privates - */ - -typedef struct -{ - HPALETTE hPalette; - LPDIRECTDRAWPALETTE lpDDPalette; - RGBQUAD rgbColors[WIN_NUM_PALETTE_ENTRIES]; - PALETTEENTRY peColors[WIN_NUM_PALETTE_ENTRIES]; -} winPrivCmapRec, *winPrivCmapPtr; - -/* - * Windows Cursor handling. - */ - -typedef struct { - /* from GetSystemMetrics */ - int sm_cx; - int sm_cy; - - BOOL visible; - HCURSOR handle; - QueryBestSizeProcPtr QueryBestSize; - miPointerSpriteFuncPtr spriteFuncs; -} winCursorRec; - -/* - * Screen information structure that we need before privates are available - * in the server startup sequence. - */ - -typedef struct -{ - ScreenPtr pScreen; - - /* Did the user specify a height and width? */ - Bool fUserGaveHeightAndWidth; - - DWORD dwScreen; - DWORD dwUserWidth; - DWORD dwUserHeight; - DWORD dwWidth; - DWORD dwHeight; - DWORD dwWidth_mm; - DWORD dwHeight_mm; - DWORD dwPaddedWidth; - - /* Did the user specify a screen position? */ - Bool fUserGavePosition; - DWORD dwInitialX; - DWORD dwInitialY; - - /* - * dwStride is the number of whole pixels that occupy a scanline, - * including those pixels that are not displayed. This is basically - * a rounding up of the width. - */ - DWORD dwStride; - - /* Offset of the screen in the window when using scrollbars */ - DWORD dwXOffset; - DWORD dwYOffset; - - DWORD dwBPP; - DWORD dwDepth; - DWORD dwRefreshRate; - char *pfb; - DWORD dwEngine; - DWORD dwEnginePreferred; - DWORD dwClipUpdatesNBoxes; -#ifdef XWIN_EMULATEPSEUDO - Bool fEmulatePseudo; -#endif - Bool fFullScreen; - Bool fDecoration; -#ifdef XWIN_MULTIWINDOWEXTWM - Bool fMWExtWM; - Bool fInternalWM; - Bool fAnotherWMRunning; -#endif - Bool fRootless; -#ifdef XWIN_MULTIWINDOW - Bool fMultiWindow; -#endif -#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) - Bool fMultiMonitorOverride; -#endif - Bool fMultipleMonitors; - Bool fLessPointer; - Bool fScrollbars; - Bool fNoTrayIcon; - int iE3BTimeout; - /* Windows (Alt+F4) and Unix (Ctrl+Alt+Backspace) Killkey */ - Bool fUseWinKillKey; - Bool fUseUnixKillKey; - Bool fIgnoreInput; - - /* Did the user explicitly set this screen? */ - Bool fExplicitScreen; -} winScreenInfo, *winScreenInfoPtr; - - -/* - * Screen privates - */ - -typedef struct _winPrivScreenRec -{ - winScreenInfoPtr pScreenInfo; - - Bool fEnabled; - Bool fClosed; - Bool fActive; - Bool fBadDepth; - - int iDeltaZ; - - int iConnectedClients; - - CloseScreenProcPtr CloseScreen; - - DWORD dwRedMask; - DWORD dwGreenMask; - DWORD dwBlueMask; - DWORD dwBitsPerRGB; - - DWORD dwModeKeyStates; - - /* Handle to icons that must be freed */ - HICON hiconNotifyIcon; - - /* Last width, height, and depth of the Windows display */ - DWORD dwLastWindowsWidth; - DWORD dwLastWindowsHeight; - DWORD dwLastWindowsBitsPixel; - - /* Palette management */ - ColormapPtr pcmapInstalled; - - /* Pointer to the root visual so we only have to look it up once */ - VisualPtr pRootVisual; - - /* 3 button emulation variables */ - int iE3BCachedPress; - Bool fE3BFakeButton2Sent; - - /* Privates used by shadow fb GDI server */ - HBITMAP hbmpShadow; - HDC hdcScreen; - HDC hdcShadow; - HWND hwndScreen; - - /* Privates used by shadow fb and primary fb DirectDraw servers */ - LPDIRECTDRAW pdd; - LPDIRECTDRAWSURFACE pddsPrimary; - LPDIRECTDRAW2 pdd2; - - /* Privates used by shadow fb DirectDraw server */ - LPDIRECTDRAWSURFACE pddsShadow; - LPDDSURFACEDESC pddsdShadow; - -#ifdef XWIN_PRIMARYFB - /* Privates used by primary fb DirectDraw server */ - LPDIRECTDRAWSURFACE pddsOffscreen; - LPDDSURFACEDESC pddsdOffscreen; - LPDDSURFACEDESC pddsdPrimary; -#endif - - /* Privates used by shadow fb DirectDraw Nonlocking server */ - LPDIRECTDRAW4 pdd4; - LPDIRECTDRAWSURFACE4 pddsShadow4; - LPDIRECTDRAWSURFACE4 pddsPrimary4; - BOOL fRetryCreateSurface; - - /* Privates used by both shadow fb DirectDraw servers */ - LPDIRECTDRAWCLIPPER pddcPrimary; - -#ifdef XWIN_MULTIWINDOWEXTWM - /* Privates used by multi-window external window manager */ - RootlessFrameID widTop; - Bool fRestacking; -#endif - -#ifdef XWIN_MULTIWINDOW - /* Privates used by multi-window */ - pthread_t ptWMProc; - pthread_t ptXMsgProc; - void *pWMInfo; -#endif - -#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) - /* Privates used by both multi-window and rootless */ - Bool fRootWindowShown; -#endif - -#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) - /* Privates used for any module running in a seperate thread */ - pthread_mutex_t pmServerStarted; - Bool fServerStarted; -#endif - - /* Engine specific functions */ - winAllocateFBProcPtr pwinAllocateFB; - winShadowUpdateProcPtr pwinShadowUpdate; - winCloseScreenProcPtr pwinCloseScreen; - winInitVisualsProcPtr pwinInitVisuals; - winAdjustVideoModeProcPtr pwinAdjustVideoMode; - winCreateBoundingWindowProcPtr pwinCreateBoundingWindow; - winFinishScreenInitProcPtr pwinFinishScreenInit; - winBltExposedRegionsProcPtr pwinBltExposedRegions; - winActivateAppProcPtr pwinActivateApp; - winRedrawScreenProcPtr pwinRedrawScreen; - winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette; - winInstallColormapProcPtr pwinInstallColormap; - winStoreColorsProcPtr pwinStoreColors; - winCreateColormapProcPtr pwinCreateColormap; - winDestroyColormapProcPtr pwinDestroyColormap; - winHotKeyAltTabProcPtr pwinHotKeyAltTab; - winCreatePrimarySurfaceProcPtr pwinCreatePrimarySurface; - winReleasePrimarySurfaceProcPtr pwinReleasePrimarySurface; - - winCreateScreenResourcesProc pwinCreateScreenResources; - -#ifdef XWIN_MULTIWINDOW - /* Window Procedures for MultiWindow mode */ - winFinishCreateWindowsWindowProcPtr pwinFinishCreateWindowsWindow; -#endif - - /* Window Procedures for Rootless mode */ - CreateWindowProcPtr CreateWindow; - DestroyWindowProcPtr DestroyWindow; - PositionWindowProcPtr PositionWindow; - ChangeWindowAttributesProcPtr ChangeWindowAttributes; - RealizeWindowProcPtr RealizeWindow; - UnrealizeWindowProcPtr UnrealizeWindow; - ValidateTreeProcPtr ValidateTree; - PostValidateTreeProcPtr PostValidateTree; - WindowExposuresProcPtr WindowExposures; - CopyWindowProcPtr CopyWindow; - ClearToBackgroundProcPtr ClearToBackground; - ClipNotifyProcPtr ClipNotify; - RestackWindowProcPtr RestackWindow; - ReparentWindowProcPtr ReparentWindow; - ResizeWindowProcPtr ResizeWindow; - MoveWindowProcPtr MoveWindow; - SetShapeProcPtr SetShape; - -#ifdef XWIN_NATIVEGDI - RealizeFontProcPtr RealizeFont; - UnrealizeFontProcPtr UnrealizeFont; -#endif - - winCursorRec cursor; -} winPrivScreenRec; - - -#ifdef XWIN_MULTIWINDOWEXTWM -typedef struct { - RootlessWindowPtr pFrame; - HWND hWnd; - int dwWidthBytes; - BITMAPINFOHEADER *pbmihShadow; - HBITMAP hbmpShadow; - HDC hdcShadow; - HDC hdcScreen; - BOOL fResized; - BOOL fRestackingNow; - BOOL fClose; - BOOL fMovingOrSizing; - BOOL fDestroyed;//for debug - char *pfb; -} win32RootlessWindowRec, *win32RootlessWindowPtr; -#endif - - -typedef struct { - pointer value; - XID id; -} WindowIDPairRec, *WindowIDPairPtr; - - -/* - * Extern declares for general global variables - */ - -extern winScreenInfo * g_ScreenInfo; -extern miPointerScreenFuncRec g_winPointerCursorFuncs; -extern DWORD g_dwEvents; -#ifdef HAS_DEVWINDOWS -extern int g_fdMessageQueue; -#endif -extern DevPrivateKey g_iScreenPrivateKey; -extern DevPrivateKey g_iCmapPrivateKey; -extern DevPrivateKey g_iGCPrivateKey; -extern DevPrivateKey g_iPixmapPrivateKey; -extern DevPrivateKey g_iWindowPrivateKey; -extern unsigned long g_ulServerGeneration; -extern DWORD g_dwEnginesSupported; -extern HINSTANCE g_hInstance; -extern int g_copyROP[]; -extern int g_patternROP[]; -extern const char * g_pszQueryHost; -extern DeviceIntPtr g_pwinPointer; -extern DeviceIntPtr g_pwinKeyboard; - - -/* - * Extern declares for dynamically loaded libraries and function pointers - */ - -extern HMODULE g_hmodDirectDraw; -extern FARPROC g_fpDirectDrawCreate; -extern FARPROC g_fpDirectDrawCreateClipper; - -extern HMODULE g_hmodCommonControls; -extern FARPROC g_fpTrackMouseEvent; - - -/* - * Screen privates macros - */ - -#define winGetScreenPriv(pScreen) ((winPrivScreenPtr) \ - dixLookupPrivate(&(pScreen)->devPrivates, g_iScreenPrivateKey)) - -#define winSetScreenPriv(pScreen,v) \ - dixSetPrivate(&(pScreen)->devPrivates, g_iScreenPrivateKey, v) - -#define winScreenPriv(pScreen) \ - winPrivScreenPtr pScreenPriv = winGetScreenPriv(pScreen) - - -/* - * Colormap privates macros - */ - -#define winGetCmapPriv(pCmap) ((winPrivCmapPtr) \ - dixLookupPrivate(&(pCmap)->devPrivates, g_iCmapPrivateKey)) - -#define winSetCmapPriv(pCmap,v) \ - dixSetPrivate(&(pCmap)->devPrivates, g_iCmapPrivateKey, v) - -#define winCmapPriv(pCmap) \ - winPrivCmapPtr pCmapPriv = winGetCmapPriv(pCmap) - - -/* - * GC privates macros - */ - -#define winGetGCPriv(pGC) ((winPrivGCPtr) \ - dixLookupPrivate(&(pGC)->devPrivates, g_iGCPrivateKey)) - -#define winSetGCPriv(pGC,v) \ - dixSetPrivate(&(pGC)->devPrivates, g_iGCPrivateKey, v) - -#define winGCPriv(pGC) \ - winPrivGCPtr pGCPriv = winGetGCPriv(pGC) - - -/* - * Pixmap privates macros - */ - -#define winGetPixmapPriv(pPixmap) ((winPrivPixmapPtr) \ - dixLookupPrivate(&(pPixmap)->devPrivates, g_iPixmapPrivateKey)) - -#define winSetPixmapPriv(pPixmap,v) \ - dixLookupPrivate(&(pPixmap)->devPrivates, g_iPixmapPrivateKey, v) - -#define winPixmapPriv(pPixmap) \ - winPrivPixmapPtr pPixmapPriv = winGetPixmapPriv(pPixmap) - - -/* - * Window privates macros - */ - -#define winGetWindowPriv(pWin) ((winPrivWinPtr) \ - dixLookupPrivate(&(pWin)->devPrivates, g_iWindowPrivateKey)) - -#define winSetWindowPriv(pWin,v) \ - dixLookupPrivate(&(pWin)->devPrivates, g_iWindowPrivateKey, v) - -#define winWindowPriv(pWin) \ - winPrivWinPtr pWinPriv = winGetWindowPriv(pWin) - -/* - * wrapper macros - */ -#define _WIN_WRAP(priv, real, mem, func) {\ - priv->mem = real->mem; \ - real->mem = func; \ -} - -#define _WIN_UNWRAP(priv, real, mem) {\ - real->mem = priv->mem; \ -} - -#define WIN_WRAP(mem, func) _WIN_WRAP(pScreenPriv, pScreen, mem, func) - -#define WIN_UNWRAP(mem) _WIN_UNWRAP(pScreenPriv, pScreen, mem) - -/* - * BEGIN DDX and DIX Function Prototypes - */ - - -/* - * winallpriv.c - */ - -Bool -winAllocatePrivates (ScreenPtr pScreen); - -Bool -winInitCmapPrivates (ColormapPtr pCmap, int index); - -Bool -winAllocateCmapPrivates (ColormapPtr pCmap); - - -/* - * winauth.c - */ - -#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) -Bool -winGenerateAuthorization (void); -void winSetAuthorization(void); -#endif - - -/* - * winblock.c - */ - -void -winBlockHandler (int nScreen, - pointer pBlockData, - pointer pTimeout, - pointer pReadMask); - - -#ifdef XWIN_NATIVEGDI -/* - * winclip.c - */ - -RegionPtr -winPixmapToRegionNativeGDI (PixmapPtr pPix); -#endif - - -#ifdef XWIN_CLIPBOARD -/* - * winclipboardinit.c - */ - -Bool -winInitClipboard (void); - -void -winFixClipboardChain (void); -#endif - - -/* - * wincmap.c - */ - -void -winSetColormapFunctions (ScreenPtr pScreen); - -Bool -winCreateDefColormap (ScreenPtr pScreen); - - -/* - * wincreatewnd.c - */ - -Bool -winCreateBoundingWindowFullScreen (ScreenPtr pScreen); - -Bool -winCreateBoundingWindowWindowed (ScreenPtr pScreen); - - -/* - * windialogs.c - */ - -int -GetLiveClients (winPrivScreenPtr pScreenPriv); - -void -winDisplayExitDialog (winPrivScreenPtr pScreenPriv); - -void -winDisplayDepthChangeDialog (winPrivScreenPtr pScreenPriv); - -void -winDisplayAboutDialog (winPrivScreenPtr pScreenPriv); - - -/* - * winengine.c - */ - -void -winDetectSupportedEngines (void); - -Bool -winSetEngine (ScreenPtr pScreen); - -Bool -winGetDDProcAddresses (void); - - -/* - * winerror.c - */ - -#ifdef DDXOSVERRORF -void -OSVenderVErrorF (const char *pszFormat, va_list va_args); -#endif - -void -winMessageBoxF (const char *pszError, UINT uType, ...); - - -#ifdef XWIN_NATIVEGDI -/* - * winfillsp.c - */ - -void -winFillSpansNativeGDI (DrawablePtr pDrawable, - GCPtr pGC, - int nSpans, - DDXPointPtr pPoints, - int *pWidths, - int fSorted); -#endif - - -#ifdef XWIN_NATIVEGDI -/* - * winfont.c - */ - -Bool -winRealizeFontNativeGDI (ScreenPtr pScreen, FontPtr pFont); - -Bool -winUnrealizeFontNativeGDI (ScreenPtr pScreen, FontPtr pFont); -#endif - - -#ifdef XWIN_NATIVEGDI -/* - * wingc.c - */ - -Bool -winCreateGCNativeGDI (GCPtr pGC); -#endif - - -#ifdef XWIN_NATIVEGDI -/* - * wingetsp.c - */ - -void -winGetSpansNativeGDI (DrawablePtr pDrawable, - int wMax, - DDXPointPtr pPoints, - int *pWidths, - int nSpans, - char *pDst); -#endif - - -/* - * winglobals.c - */ - -void -winInitializeGlobals (void); - - -/* - * winkeybd.c - */ - -void -winTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode); - -int -winKeybdProc (DeviceIntPtr pDeviceInt, int iState); - -void -winInitializeModeKeyStates (void); - -void -winRestoreModeKeyStates (void); - -Bool -winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam); - -void -winKeybdReleaseKeys (void); - -void -winSendKeyEvent (DWORD dwKey, Bool fDown); - -BOOL -winCheckKeyPressed(WPARAM wParam, LPARAM lParam); - -void -winFixShiftKeys (int iScanCode); - -/* - * winkeyhook.c - */ - -Bool -winInstallKeyboardHookLL (void); - -void -winRemoveKeyboardHookLL (void); - - -/* - * winmisc.c - */ - -#ifdef XWIN_NATIVEGDI -void -winQueryBestSizeNativeGDI (int class, unsigned short *pWidth, - unsigned short *pHeight, ScreenPtr pScreen); -#endif - -CARD8 -winCountBits (DWORD dw); - -Bool -winUpdateFBPointer (ScreenPtr pScreen, void *pbits); - -#ifdef XWIN_NATIVEGDI -BOOL -winPaintBackground (HWND hwnd, COLORREF colorref); -#endif - - -/* - * winmouse.c - */ - -int -winMouseProc (DeviceIntPtr pDeviceInt, int iState); - -int -winMouseWheel (ScreenPtr pScreen, int iDeltaZ); - -void -winMouseButtonsSendEvent (int iEventType, int iButton); - -int -winMouseButtonsHandle (ScreenPtr pScreen, - int iEventType, int iButton, - WPARAM wParam); - -void -winEnqueueMotion(int x, int y); - -#ifdef XWIN_NATIVEGDI -/* - * winnativegdi.c - */ - -HBITMAP -winCreateDIBNativeGDI (int iWidth, int iHeight, int iDepth, - BYTE **ppbBits, BITMAPINFO **ppbmi); - -Bool -winSetEngineFunctionsNativeGDI (ScreenPtr pScreen); -#endif - - -#ifdef XWIN_PRIMARYFB -/* - * winpfbddd.c - */ - -Bool -winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen); -#endif - - -#ifdef XWIN_NATIVEGDI -/* - * winpixmap.c - */ - -PixmapPtr -winCreatePixmapNativeGDI (ScreenPtr pScreen, int width, int height, int depth, - unsigned usage_hint); - -Bool -winDestroyPixmapNativeGDI (PixmapPtr pPixmap); - -Bool -winModifyPixmapHeaderNativeGDI (PixmapPtr pPixmap, - int iWidth, int iHeight, - int iDepth, - int iBitsPerPixel, - int devKind, - pointer pPixData); -#endif - -#ifdef XWIN_NATIVEGDI -/* - * winpolyline.c - */ - -void -winPolyLineNativeGDI (DrawablePtr pDrawable, - GCPtr pGC, - int mode, - int npt, - DDXPointPtr ppt); -#endif - - -#ifdef XWIN_NATIVEGDI -/* - * winpushpxl.c - */ - -void -winPushPixels (GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable, - int dx, int dy, int xOrg, int yOrg); -#endif - - -/* - * winscrinit.c - */ - -Bool -winScreenInit (int index, - ScreenPtr pScreen, - int argc, char **argv); - -Bool -winFinishScreenInitFB (int index, - ScreenPtr pScreen, - int argc, char **argv); - -#if defined(XWIN_NATIVEGDI) -Bool -winFinishScreenInitNativeGDI (int index, - ScreenPtr pScreen, - int argc, char **argv); -#endif - - -#ifdef XWIN_NATIVEGDI -/* - * winsetsp.c - */ - -void -winSetSpansNativeGDI (DrawablePtr pDrawable, - GCPtr pGC, - char *pSrc, - DDXPointPtr pPoints, - int *pWidth, - int nSpans, - int fSorted); -#endif - - -/* - * winshaddd.c - */ - -Bool -winSetEngineFunctionsShadowDD (ScreenPtr pScreen); - - -/* - * winshadddnl.c - */ - -Bool -winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen); - - -/* - * winshadgdi.c - */ - -Bool -winSetEngineFunctionsShadowGDI (ScreenPtr pScreen); - - -/* - * winwakeup.c - */ - -void -winWakeupHandler (int nScreen, - pointer pWakeupData, - unsigned long ulResult, - pointer pReadmask); - - -/* - * winwindow.c - */ - -#ifdef XWIN_NATIVEGDI -Bool -winCreateWindowNativeGDI (WindowPtr pWin); - -Bool -winDestroyWindowNativeGDI (WindowPtr pWin); - -Bool -winPositionWindowNativeGDI (WindowPtr pWin, int x, int y); - -void -winCopyWindowNativeGDI (WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc); - -Bool -winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask); - -Bool -winUnmapWindowNativeGDI (WindowPtr pWindow); - -Bool -winMapWindowNativeGDI (WindowPtr pWindow); -#endif - -Bool -winCreateWindowRootless (WindowPtr pWindow); - -Bool -winDestroyWindowRootless (WindowPtr pWindow); - -Bool -winPositionWindowRootless (WindowPtr pWindow, int x, int y); - -Bool -winChangeWindowAttributesRootless (WindowPtr pWindow, unsigned long mask); - -Bool -winUnmapWindowRootless (WindowPtr pWindow); - -Bool -winMapWindowRootless (WindowPtr pWindow); - -void -winSetShapeRootless (WindowPtr pWindow); - - -/* - * winmultiwindowicons.c - Used by both multi-window and Win32Rootless - */ - -HICON -winXIconToHICON (WindowPtr pWin, int iconSize); - -void -winSelectIcons(WindowPtr pWin, HICON *pIcon, HICON *pSmallIcon); - -#ifdef XWIN_MULTIWINDOW -/* - * winmultiwindowshape.c - */ - -void -winReshapeMultiWindow (WindowPtr pWin); - -void -winSetShapeMultiWindow (WindowPtr pWindow); - -void -winUpdateRgnMultiWindow (WindowPtr pWindow); -#endif - - -#ifdef XWIN_MULTIWINDOW -/* - * winmultiwindowwindow.c - */ - -Bool -winCreateWindowMultiWindow (WindowPtr pWindow); - -Bool -winDestroyWindowMultiWindow (WindowPtr pWindow); - -Bool -winPositionWindowMultiWindow (WindowPtr pWindow, int x, int y); - -Bool -winChangeWindowAttributesMultiWindow (WindowPtr pWindow, unsigned long mask); - -Bool -winUnmapWindowMultiWindow (WindowPtr pWindow); - -Bool -winMapWindowMultiWindow (WindowPtr pWindow); - -void -winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent); - -void -winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib); - -void -winReorderWindowsMultiWindow (void); - -void -winResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w, - unsigned int h, WindowPtr pSib); -void -winMoveWindowMultiWindow (WindowPtr pWin, int x, int y, - WindowPtr pSib, VTKind kind); - -void -winCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt, - RegionPtr oldRegion); - -XID -winGetWindowID (WindowPtr pWin); - -int -winAdjustXWindow (WindowPtr pWin, HWND hwnd); -#endif - - -#ifdef XWIN_MULTIWINDOW -/* - * winmultiwindowwndproc.c - */ - -LRESULT CALLBACK -winTopLevelWindowProc (HWND hwnd, UINT message, - WPARAM wParam, LPARAM lParam); -#endif - - -/* - * wintrayicon.c - */ - -void -winInitNotifyIcon (winPrivScreenPtr pScreenPriv, Bool Modify); - -void -winDeleteNotifyIcon (winPrivScreenPtr pScreenPriv); - -LRESULT -winHandleIconMessage (HWND hwnd, UINT message, - WPARAM wParam, LPARAM lParam, - winPrivScreenPtr pScreenPriv); - - -/* - * winwndproc.c - */ - -LRESULT CALLBACK -winWindowProc (HWND hWnd, UINT message, - WPARAM wParam, LPARAM lParam); - - -#ifdef XWIN_MULTIWINDOWEXTWM -/* - * winwin32rootless.c - */ - -Bool -winMWExtWMCreateFrame (RootlessWindowPtr pFrame, ScreenPtr pScreen, - int newX, int newY, RegionPtr pShape); - -void -winMWExtWMDestroyFrame (RootlessFrameID wid); - -void -winMWExtWMMoveFrame (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); - -void -winMWExtWMResizeFrame (RootlessFrameID wid, ScreenPtr pScreen, - int newX, int newY, unsigned int newW, unsigned int newH, - unsigned int gravity); - -void -winMWExtWMRestackFrame (RootlessFrameID wid, RootlessFrameID nextWid); - -void -winMWExtWMReshapeFrame (RootlessFrameID wid, RegionPtr pShape); - -void -winMWExtWMUnmapFrame (RootlessFrameID wid); - -void -winMWExtWMStartDrawing (RootlessFrameID wid, char **pixelData, int *bytesPerRow); - -void -winMWExtWMStopDrawing (RootlessFrameID wid, Bool flush); - -void -winMWExtWMUpdateRegion (RootlessFrameID wid, RegionPtr pDamage); - -void -winMWExtWMDamageRects (RootlessFrameID wid, int count, const BoxRec *rects, - int shift_x, int shift_y); - -void -winMWExtWMRootlessSwitchWindow (RootlessWindowPtr pFrame, WindowPtr oldWin); - -void -winMWExtWMCopyBytes (unsigned int width, unsigned int height, - const void *src, unsigned int srcRowBytes, - void *dst, unsigned int dstRowBytes); - -void -winMWExtWMFillBytes (unsigned int width, unsigned int height, unsigned int value, - void *dst, unsigned int dstRowBytes); - -int -winMWExtWMCompositePixels (unsigned int width, unsigned int height, unsigned int function, - void *src[2], unsigned int srcRowBytes[2], - void *mask, unsigned int maskRowBytes, - void *dst[2], unsigned int dstRowBytes[2]); - -void -winMWExtWMCopyWindow (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, - int dx, int dy); -#endif - - -#ifdef XWIN_MULTIWINDOWEXTWM -/* - * winwin32rootlesswindow.c - */ - -void -winMWExtWMReorderWindows (ScreenPtr pScreen); - -void -winMWExtWMMoveXWindow (WindowPtr pWin, int x, int y); - -void -winMWExtWMResizeXWindow (WindowPtr pWin, int w, int h); - -void -winMWExtWMMoveResizeXWindow (WindowPtr pWin, int x, int y, int w, int h); - -void -winMWExtWMUpdateIcon (Window id); - -void -winMWExtWMUpdateWindowDecoration (win32RootlessWindowPtr pRLWinPriv, - winScreenInfoPtr pScreenInfo); - -wBOOL CALLBACK -winMWExtWMDecorateWindow (HWND hwnd, LPARAM lParam); - -Bool -winIsInternalWMRunning (winScreenInfoPtr pScreenInfo); - -void -winMWExtWMRestackWindows (ScreenPtr pScreen); -#endif - - -#ifdef XWIN_MULTIWINDOWEXTWM -/* - * winwin32rootlesswndproc.c - */ - -LRESULT CALLBACK -winMWExtWMWindowProc (HWND hwnd, UINT message, - WPARAM wParam, LPARAM lParam); -#endif - - -/* - * winwindowswm.c - */ - -void -winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg, - Window window, int x, int y, int w, int h); - -void -winWindowsWMExtensionInit (void); - -/* - * wincursor.c - */ - -Bool -winInitCursor (ScreenPtr pScreen); - -/* - * winprocarg.c - */ -void -winInitializeScreens(int maxscreens); - -/* - * windisplay.c - */ - -void -winGetDisplayName(char *szDisplay, unsigned int screen); - -/* - * END DDX and DIX Function Prototypes - */ - -#endif /* _WIN_H_ */ - +/* + *Copyright (C) 1994-2000 The XFree86 Project, 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 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. + * + * Authors: Dakshinamurthy Karra + * Suhaib M Siddiqi + * Peter Busch + * Harold L Hunt II + * Kensuke Matsuzaki + */ + +#ifndef _WIN_H_ +#define _WIN_H_ + +#ifndef NO +#define NO 0 +#endif +#ifndef YES +#define YES 1 +#endif + +/* WM_XBUTTON Messages. They should go into w32api. */ +#ifndef WM_XBUTTONDOWN +# define WM_XBUTTONDOWN 523 +#endif +#ifndef WM_XBUTTONUP +# define WM_XBUTTONUP 524 +#endif +#ifndef WM_XBUTTONDBLCLK +# define WM_XBUTTONDBLCLK 525 +#endif + + +#define WIN_DEFAULT_BPP 0 +#define WIN_DEFAULT_WHITEPIXEL 255 +#define WIN_DEFAULT_BLACKPIXEL 0 +#define WIN_DEFAULT_LINEBIAS 0 +#define WIN_DEFAULT_E3B_TIME 50 /* milliseconds */ +#define WIN_DEFAULT_DPI 75 +#define WIN_DEFAULT_REFRESH 0 +#define WIN_DEFAULT_WIN_KILL TRUE +#define WIN_DEFAULT_UNIX_KILL FALSE +#define WIN_DEFAULT_CLIP_UPDATES_NBOXES 0 +#ifdef XWIN_EMULATEPSEUDO +#define WIN_DEFAULT_EMULATE_PSEUDO FALSE +#endif +#define WIN_DEFAULT_USER_GAVE_HEIGHT_AND_WIDTH FALSE + +#define WIN_DIB_MAXIMUM_SIZE 0x08000000 /* 16 MB on Windows 95, 98, Me */ +#define WIN_DIB_MAXIMUM_SIZE_MB (WIN_DIB_MAXIMUM_SIZE / 8 / 1024 / 1024) + +/* + * Windows only supports 256 color palettes + */ +#define WIN_NUM_PALETTE_ENTRIES 256 + +/* + * Number of times to call Restore in an attempt to restore the primary surface + */ +#define WIN_REGAIN_SURFACE_RETRIES 1 + +/* + * Build a supported display depths mask by shifting one to the left + * by the number of bits in the supported depth. + */ +#define WIN_SUPPORTED_BPPS ( (1 << (32 - 1)) | (1 << (24 - 1)) \ + | (1 << (16 - 1)) | (1 << (15 - 1)) \ + | (1 << ( 8 - 1))) +#define WIN_CHECK_DEPTH YES + +/* + * Timer IDs for WM_TIMER + */ +#define WIN_E3B_TIMER_ID 1 +#define WIN_POLLING_MOUSE_TIMER_ID 2 + +#define MOUSE_POLLING_INTERVAL 50 + +#define WIN_E3B_OFF -1 +#define WIN_FD_INVALID -1 + +#define WIN_SERVER_NONE 0x0L /* 0 */ +#define WIN_SERVER_SHADOW_GDI 0x1L /* 1 */ +#define WIN_SERVER_SHADOW_DD 0x2L /* 2 */ +#define WIN_SERVER_SHADOW_DDNL 0x4L /* 4 */ +#ifdef XWIN_PRIMARYFB +#define WIN_SERVER_PRIMARY_DD 0x8L /* 8 */ +#endif +#ifdef XWIN_NATIVEGDI +# define WIN_SERVER_NATIVE_GDI 0x10L /* 16 */ +#endif + +#define AltMapIndex Mod1MapIndex +#define NumLockMapIndex Mod2MapIndex +#define AltLangMapIndex Mod3MapIndex +#define KanaMapIndex Mod4MapIndex +#define ScrollLockMapIndex Mod5MapIndex + +#define WIN_MOD_LALT 0x00000001 +#define WIN_MOD_RALT 0x00000002 +#define WIN_MOD_LCONTROL 0x00000004 +#define WIN_MOD_RCONTROL 0x00000008 + +#define WIN_24BPP_MASK_RED 0x00FF0000 +#define WIN_24BPP_MASK_GREEN 0x0000FF00 +#define WIN_24BPP_MASK_BLUE 0x000000FF + +#define WIN_MAX_KEYS_PER_KEY 4 + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> + +#include <errno.h> +#if defined(XWIN_MULTIWINDOWEXTWM) || defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) +#define HANDLE void * +#ifdef _MSC_VER +typedef int pid_t; +#endif +#include <pthread.h> +#undef HANDLE +#endif + +#ifdef HAS_MMAP +#include <sys/mman.h> +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif /* MAP_FILE */ +#endif /* HAS_MMAP */ + +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/Xos.h> +#include <X11/Xprotostr.h> +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "pixmap.h" +#include "region.h" +#include "gcstruct.h" +#include "colormap.h" +#include "colormapst.h" +#include "miscstruct.h" +#include "servermd.h" +#include "windowstr.h" +#include "mi.h" +#include "micmap.h" +#include "mifillarc.h" +#include "mifpoly.h" +#include "mibstore.h" +#include "input.h" +#include "mipointer.h" +#include "X11/keysym.h" +#include "mibstore.h" +#include "micoord.h" +#include "dix.h" +#include "miline.h" +#include "shadow.h" +#include "fb.h" +#include "rootless.h" + +#include "mipict.h" +#include "picturestr.h" + +#ifdef RANDR +#include "randrstr.h" +#endif + +/* + * Windows headers + */ +#include "winms.h" +#include "winresource.h" + + +/* + * Define Windows constants + */ + +#define WM_TRAYICON (WM_USER + 1000) +#define WM_INIT_SYS_MENU (WM_USER + 1001) +#define WM_GIVEUP (WM_USER + 1002) + + +/* Local includes */ +#include "winwindow.h" +#include "winmsg.h" + +#define PROFILEPOINT(point,thresh)\ +{\ +static unsigned int PROFPT##point = 0;\ +if (++PROFPT##point % thresh == 0)\ +ErrorF (#point ": PROFILEPOINT hit %u times\n", PROFPT##point);\ +} + + +/* We use xor this macro for detecting toggle key state changes */ +#define WIN_XOR(a,b) ((!(a) && (b)) || ((a) && !(b))) + +#define DEFINE_ATOM_HELPER(func,atom_name) \ +static Atom func (void) { \ + static int generation; \ + static Atom atom; \ + if (generation != serverGeneration) { \ + generation = serverGeneration; \ + atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ + } \ + return atom; \ +} + +/* + * Typedefs for engine dependent function pointers + */ + +typedef Bool (*winAllocateFBProcPtr)(ScreenPtr); + +typedef void (*winShadowUpdateProcPtr)(ScreenPtr, shadowBufPtr); + +typedef Bool (*winCloseScreenProcPtr)(int, ScreenPtr); + +typedef Bool (*winInitVisualsProcPtr)(ScreenPtr); + +typedef Bool (*winAdjustVideoModeProcPtr)(ScreenPtr); + +typedef Bool (*winCreateBoundingWindowProcPtr)(ScreenPtr); + +typedef Bool (*winFinishScreenInitProcPtr)(int, ScreenPtr, int, char **); + +typedef Bool (*winBltExposedRegionsProcPtr)(ScreenPtr); + +typedef Bool (*winActivateAppProcPtr)(ScreenPtr); + +typedef Bool (*winRedrawScreenProcPtr)(ScreenPtr pScreen); + +typedef Bool (*winRealizeInstalledPaletteProcPtr)(ScreenPtr pScreen); + +typedef Bool (*winInstallColormapProcPtr)(ColormapPtr pColormap); + +typedef Bool (*winStoreColorsProcPtr)(ColormapPtr pmap, + int ndef, xColorItem *pdefs); + +typedef Bool (*winCreateColormapProcPtr)(ColormapPtr pColormap); + +typedef Bool (*winDestroyColormapProcPtr)(ColormapPtr pColormap); + +typedef Bool (*winHotKeyAltTabProcPtr)(ScreenPtr); + +typedef Bool (*winCreatePrimarySurfaceProcPtr)(ScreenPtr); + +typedef Bool (*winReleasePrimarySurfaceProcPtr)(ScreenPtr); + +typedef Bool (*winFinishCreateWindowsWindowProcPtr)(WindowPtr pWin); + +typedef Bool (*winCreateScreenResourcesProc)(ScreenPtr); + +/* Typedef for DIX wrapper functions */ +typedef int (*winDispatchProcPtr) (ClientPtr); + + +/* + * GC (graphics context) privates + */ + +typedef struct +{ + HDC hdc; + HDC hdcMem; +} winPrivGCRec, *winPrivGCPtr; + + +/* + * Pixmap privates + */ + +typedef struct +{ + HDC hdcSelected; + HBITMAP hBitmap; + BYTE *pbBits; + DWORD dwScanlineBytes; + BITMAPINFOHEADER *pbmih; +} winPrivPixmapRec, *winPrivPixmapPtr; + + +/* + * Colormap privates + */ + +typedef struct +{ + HPALETTE hPalette; + LPDIRECTDRAWPALETTE lpDDPalette; + RGBQUAD rgbColors[WIN_NUM_PALETTE_ENTRIES]; + PALETTEENTRY peColors[WIN_NUM_PALETTE_ENTRIES]; +} winPrivCmapRec, *winPrivCmapPtr; + +/* + * Windows Cursor handling. + */ + +typedef struct { + /* from GetSystemMetrics */ + int sm_cx; + int sm_cy; + + BOOL visible; + HCURSOR handle; + QueryBestSizeProcPtr QueryBestSize; + miPointerSpriteFuncPtr spriteFuncs; +} winCursorRec; + +/* + * Screen information structure that we need before privates are available + * in the server startup sequence. + */ + +typedef struct +{ + ScreenPtr pScreen; + + /* Did the user specify a height and width? */ + Bool fUserGaveHeightAndWidth; + + DWORD dwScreen; + DWORD dwUserWidth; + DWORD dwUserHeight; + DWORD dwWidth; + DWORD dwHeight; + DWORD dwWidth_mm; + DWORD dwHeight_mm; + DWORD dwPaddedWidth; + + /* Did the user specify a screen position? */ + Bool fUserGavePosition; + DWORD dwInitialX; + DWORD dwInitialY; + + /* + * dwStride is the number of whole pixels that occupy a scanline, + * including those pixels that are not displayed. This is basically + * a rounding up of the width. + */ + DWORD dwStride; + + /* Offset of the screen in the window when using scrollbars */ + DWORD dwXOffset; + DWORD dwYOffset; + + DWORD dwBPP; + DWORD dwDepth; + DWORD dwRefreshRate; + char *pfb; + DWORD dwEngine; + DWORD dwEnginePreferred; + DWORD dwClipUpdatesNBoxes; +#ifdef XWIN_EMULATEPSEUDO + Bool fEmulatePseudo; +#endif + Bool fFullScreen; + Bool fDecoration; +#ifdef XWIN_MULTIWINDOWEXTWM + Bool fMWExtWM; + Bool fInternalWM; + Bool fAnotherWMRunning; +#endif + Bool fRootless; +#ifdef XWIN_MULTIWINDOW + Bool fMultiWindow; +#endif +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + Bool fMultiMonitorOverride; +#endif + Bool fMultipleMonitors; + Bool fLessPointer; + Bool fScrollbars; + Bool fNoTrayIcon; + int iE3BTimeout; + /* Windows (Alt+F4) and Unix (Ctrl+Alt+Backspace) Killkey */ + Bool fUseWinKillKey; + Bool fUseUnixKillKey; + Bool fIgnoreInput; + + /* Did the user explicitly set this screen? */ + Bool fExplicitScreen; +} winScreenInfo, *winScreenInfoPtr; + + +/* + * Screen privates + */ + +typedef struct _winPrivScreenRec +{ + winScreenInfoPtr pScreenInfo; + + Bool fEnabled; + Bool fClosed; + Bool fActive; + Bool fBadDepth; + + int iDeltaZ; + + int iConnectedClients; + + CloseScreenProcPtr CloseScreen; + + DWORD dwRedMask; + DWORD dwGreenMask; + DWORD dwBlueMask; + DWORD dwBitsPerRGB; + + DWORD dwModeKeyStates; + + /* Handle to icons that must be freed */ + HICON hiconNotifyIcon; + + /* Last width, height, and depth of the Windows display */ + DWORD dwLastWindowsWidth; + DWORD dwLastWindowsHeight; + DWORD dwLastWindowsBitsPixel; + + /* Palette management */ + ColormapPtr pcmapInstalled; + + /* Pointer to the root visual so we only have to look it up once */ + VisualPtr pRootVisual; + + /* 3 button emulation variables */ + int iE3BCachedPress; + Bool fE3BFakeButton2Sent; + + /* Privates used by shadow fb GDI server */ + HBITMAP hbmpShadow; + HDC hdcScreen; + HDC hdcShadow; + HWND hwndScreen; + + /* Privates used by shadow fb and primary fb DirectDraw servers */ + LPDIRECTDRAW pdd; + LPDIRECTDRAWSURFACE pddsPrimary; + LPDIRECTDRAW2 pdd2; + + /* Privates used by shadow fb DirectDraw server */ + LPDIRECTDRAWSURFACE pddsShadow; + LPDDSURFACEDESC pddsdShadow; + +#ifdef XWIN_PRIMARYFB + /* Privates used by primary fb DirectDraw server */ + LPDIRECTDRAWSURFACE pddsOffscreen; + LPDDSURFACEDESC pddsdOffscreen; + LPDDSURFACEDESC pddsdPrimary; +#endif + + /* Privates used by shadow fb DirectDraw Nonlocking server */ + LPDIRECTDRAW4 pdd4; + LPDIRECTDRAWSURFACE4 pddsShadow4; + LPDIRECTDRAWSURFACE4 pddsPrimary4; + BOOL fRetryCreateSurface; + + /* Privates used by both shadow fb DirectDraw servers */ + LPDIRECTDRAWCLIPPER pddcPrimary; + +#ifdef XWIN_MULTIWINDOWEXTWM + /* Privates used by multi-window external window manager */ + RootlessFrameID widTop; + Bool fRestacking; +#endif + +#ifdef XWIN_MULTIWINDOW + /* Privates used by multi-window */ + pthread_t ptWMProc; + pthread_t ptXMsgProc; + void *pWMInfo; +#endif + +#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) + /* Privates used by both multi-window and rootless */ + Bool fRootWindowShown; +#endif + +#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) + /* Privates used for any module running in a seperate thread */ + pthread_mutex_t pmServerStarted; + Bool fServerStarted; +#endif + + /* Engine specific functions */ + winAllocateFBProcPtr pwinAllocateFB; + winShadowUpdateProcPtr pwinShadowUpdate; + winCloseScreenProcPtr pwinCloseScreen; + winInitVisualsProcPtr pwinInitVisuals; + winAdjustVideoModeProcPtr pwinAdjustVideoMode; + winCreateBoundingWindowProcPtr pwinCreateBoundingWindow; + winFinishScreenInitProcPtr pwinFinishScreenInit; + winBltExposedRegionsProcPtr pwinBltExposedRegions; + winActivateAppProcPtr pwinActivateApp; + winRedrawScreenProcPtr pwinRedrawScreen; + winRealizeInstalledPaletteProcPtr pwinRealizeInstalledPalette; + winInstallColormapProcPtr pwinInstallColormap; + winStoreColorsProcPtr pwinStoreColors; + winCreateColormapProcPtr pwinCreateColormap; + winDestroyColormapProcPtr pwinDestroyColormap; + winHotKeyAltTabProcPtr pwinHotKeyAltTab; + winCreatePrimarySurfaceProcPtr pwinCreatePrimarySurface; + winReleasePrimarySurfaceProcPtr pwinReleasePrimarySurface; + + winCreateScreenResourcesProc pwinCreateScreenResources; + +#ifdef XWIN_MULTIWINDOW + /* Window Procedures for MultiWindow mode */ + winFinishCreateWindowsWindowProcPtr pwinFinishCreateWindowsWindow; +#endif + + /* Window Procedures for Rootless mode */ + CreateWindowProcPtr CreateWindow; + DestroyWindowProcPtr DestroyWindow; + PositionWindowProcPtr PositionWindow; + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + RealizeWindowProcPtr RealizeWindow; + UnrealizeWindowProcPtr UnrealizeWindow; + ValidateTreeProcPtr ValidateTree; + PostValidateTreeProcPtr PostValidateTree; + WindowExposuresProcPtr WindowExposures; + CopyWindowProcPtr CopyWindow; + ClearToBackgroundProcPtr ClearToBackground; + ClipNotifyProcPtr ClipNotify; + RestackWindowProcPtr RestackWindow; + ReparentWindowProcPtr ReparentWindow; + ResizeWindowProcPtr ResizeWindow; + MoveWindowProcPtr MoveWindow; + SetShapeProcPtr SetShape; + +#ifdef XWIN_NATIVEGDI + RealizeFontProcPtr RealizeFont; + UnrealizeFontProcPtr UnrealizeFont; +#endif + + winCursorRec cursor; +} winPrivScreenRec; + + +#ifdef XWIN_MULTIWINDOWEXTWM +typedef struct { + RootlessWindowPtr pFrame; + HWND hWnd; + int dwWidthBytes; + BITMAPINFOHEADER *pbmihShadow; + HBITMAP hbmpShadow; + HDC hdcShadow; + HDC hdcScreen; + BOOL fResized; + BOOL fRestackingNow; + BOOL fClose; + BOOL fMovingOrSizing; + BOOL fDestroyed;//for debug + char *pfb; +} win32RootlessWindowRec, *win32RootlessWindowPtr; +#endif + + +typedef struct { + pointer value; + XID id; +} WindowIDPairRec, *WindowIDPairPtr; + + +/* + * Extern declares for general global variables + */ + +extern winScreenInfo * g_ScreenInfo; +extern miPointerScreenFuncRec g_winPointerCursorFuncs; +extern DWORD g_dwEvents; +#ifdef HAS_DEVWINDOWS +extern int g_fdMessageQueue; +#endif +extern DevPrivateKey g_iScreenPrivateKey; +extern DevPrivateKey g_iCmapPrivateKey; +extern DevPrivateKey g_iGCPrivateKey; +extern DevPrivateKey g_iPixmapPrivateKey; +extern DevPrivateKey g_iWindowPrivateKey; +extern unsigned long g_ulServerGeneration; +extern DWORD g_dwEnginesSupported; +extern HINSTANCE g_hInstance; +extern int g_copyROP[]; +extern int g_patternROP[]; +extern const char * g_pszQueryHost; +extern DeviceIntPtr g_pwinPointer; +extern DeviceIntPtr g_pwinKeyboard; + + +/* + * Extern declares for dynamically loaded libraries and function pointers + */ + +extern HMODULE g_hmodDirectDraw; +extern FARPROC g_fpDirectDrawCreate; +extern FARPROC g_fpDirectDrawCreateClipper; + +extern HMODULE g_hmodCommonControls; +extern FARPROC g_fpTrackMouseEvent; + + +/* + * Screen privates macros + */ + +#define winGetScreenPriv(pScreen) ((winPrivScreenPtr) \ + dixLookupPrivate(&(pScreen)->devPrivates, g_iScreenPrivateKey)) + +#define winSetScreenPriv(pScreen,v) \ + dixSetPrivate(&(pScreen)->devPrivates, g_iScreenPrivateKey, v) + +#define winScreenPriv(pScreen) \ + winPrivScreenPtr pScreenPriv = winGetScreenPriv(pScreen) + + +/* + * Colormap privates macros + */ + +#define winGetCmapPriv(pCmap) ((winPrivCmapPtr) \ + dixLookupPrivate(&(pCmap)->devPrivates, g_iCmapPrivateKey)) + +#define winSetCmapPriv(pCmap,v) \ + dixSetPrivate(&(pCmap)->devPrivates, g_iCmapPrivateKey, v) + +#define winCmapPriv(pCmap) \ + winPrivCmapPtr pCmapPriv = winGetCmapPriv(pCmap) + + +/* + * GC privates macros + */ + +#define winGetGCPriv(pGC) ((winPrivGCPtr) \ + dixLookupPrivate(&(pGC)->devPrivates, g_iGCPrivateKey)) + +#define winSetGCPriv(pGC,v) \ + dixSetPrivate(&(pGC)->devPrivates, g_iGCPrivateKey, v) + +#define winGCPriv(pGC) \ + winPrivGCPtr pGCPriv = winGetGCPriv(pGC) + + +/* + * Pixmap privates macros + */ + +#define winGetPixmapPriv(pPixmap) ((winPrivPixmapPtr) \ + dixLookupPrivate(&(pPixmap)->devPrivates, g_iPixmapPrivateKey)) + +#define winSetPixmapPriv(pPixmap,v) \ + dixLookupPrivate(&(pPixmap)->devPrivates, g_iPixmapPrivateKey, v) + +#define winPixmapPriv(pPixmap) \ + winPrivPixmapPtr pPixmapPriv = winGetPixmapPriv(pPixmap) + + +/* + * Window privates macros + */ + +#define winGetWindowPriv(pWin) ((winPrivWinPtr) \ + dixLookupPrivate(&(pWin)->devPrivates, g_iWindowPrivateKey)) + +#define winSetWindowPriv(pWin,v) \ + dixLookupPrivate(&(pWin)->devPrivates, g_iWindowPrivateKey, v) + +#define winWindowPriv(pWin) \ + winPrivWinPtr pWinPriv = winGetWindowPriv(pWin) + +/* + * wrapper macros + */ +#define _WIN_WRAP(priv, real, mem, func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define _WIN_UNWRAP(priv, real, mem) {\ + real->mem = priv->mem; \ +} + +#define WIN_WRAP(mem, func) _WIN_WRAP(pScreenPriv, pScreen, mem, func) + +#define WIN_UNWRAP(mem) _WIN_UNWRAP(pScreenPriv, pScreen, mem) + +/* + * BEGIN DDX and DIX Function Prototypes + */ + + +/* + * winallpriv.c + */ + +Bool +winAllocatePrivates (ScreenPtr pScreen); + +Bool +winInitCmapPrivates (ColormapPtr pCmap, int index); + +Bool +winAllocateCmapPrivates (ColormapPtr pCmap); + + +/* + * winauth.c + */ + +#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) +Bool +winGenerateAuthorization (void); +void winSetAuthorization(void); +#endif + + +/* + * winblock.c + */ + +void +winBlockHandler (int nScreen, + pointer pBlockData, + pointer pTimeout, + pointer pReadMask); + + +#ifdef XWIN_NATIVEGDI +/* + * winclip.c + */ + +RegionPtr +winPixmapToRegionNativeGDI (PixmapPtr pPix); +#endif + + +#ifdef XWIN_CLIPBOARD +/* + * winclipboardinit.c + */ + +Bool +winInitClipboard (void); + +void +winFixClipboardChain (void); +#endif + + +/* + * wincmap.c + */ + +void +winSetColormapFunctions (ScreenPtr pScreen); + +Bool +winCreateDefColormap (ScreenPtr pScreen); + + +/* + * wincreatewnd.c + */ + +Bool +winCreateBoundingWindowFullScreen (ScreenPtr pScreen); + +Bool +winCreateBoundingWindowWindowed (ScreenPtr pScreen); + + +/* + * windialogs.c + */ + +int +GetLiveClients (winPrivScreenPtr pScreenPriv); + +void +winDisplayExitDialog (winPrivScreenPtr pScreenPriv); + +void +winDisplayDepthChangeDialog (winPrivScreenPtr pScreenPriv); + +void +winDisplayAboutDialog (winPrivScreenPtr pScreenPriv); + + +/* + * winengine.c + */ + +void +winDetectSupportedEngines (void); + +Bool +winSetEngine (ScreenPtr pScreen); + +Bool +winGetDDProcAddresses (void); + + +/* + * winerror.c + */ + +#ifdef DDXOSVERRORF +void +OSVenderVErrorF (const char *pszFormat, va_list va_args); +#endif + +void +winMessageBoxF (const char *pszError, UINT uType, ...); + + +#ifdef XWIN_NATIVEGDI +/* + * winfillsp.c + */ + +void +winFillSpansNativeGDI (DrawablePtr pDrawable, + GCPtr pGC, + int nSpans, + DDXPointPtr pPoints, + int *pWidths, + int fSorted); +#endif + + +#ifdef XWIN_NATIVEGDI +/* + * winfont.c + */ + +Bool +winRealizeFontNativeGDI (ScreenPtr pScreen, FontPtr pFont); + +Bool +winUnrealizeFontNativeGDI (ScreenPtr pScreen, FontPtr pFont); +#endif + + +#ifdef XWIN_NATIVEGDI +/* + * wingc.c + */ + +Bool +winCreateGCNativeGDI (GCPtr pGC); +#endif + + +#ifdef XWIN_NATIVEGDI +/* + * wingetsp.c + */ + +void +winGetSpansNativeGDI (DrawablePtr pDrawable, + int wMax, + DDXPointPtr pPoints, + int *pWidths, + int nSpans, + char *pDst); +#endif + + +/* + * winglobals.c + */ + +void +winInitializeGlobals (void); + + +/* + * winkeybd.c + */ + +void +winTranslateKey (WPARAM wParam, LPARAM lParam, int *piScanCode); + +int +winKeybdProc (DeviceIntPtr pDeviceInt, int iState); + +void +winInitializeModeKeyStates (void); + +void +winRestoreModeKeyStates (void); + +Bool +winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam); + +void +winKeybdReleaseKeys (void); + +void +winSendKeyEvent (DWORD dwKey, Bool fDown); + +BOOL +winCheckKeyPressed(WPARAM wParam, LPARAM lParam); + +void +winFixShiftKeys (int iScanCode); + +/* + * winkeyhook.c + */ + +Bool +winInstallKeyboardHookLL (void); + +void +winRemoveKeyboardHookLL (void); + + +/* + * winmisc.c + */ + +#ifdef XWIN_NATIVEGDI +void +winQueryBestSizeNativeGDI (int class, unsigned short *pWidth, + unsigned short *pHeight, ScreenPtr pScreen); +#endif + +CARD8 +winCountBits (DWORD dw); + +Bool +winUpdateFBPointer (ScreenPtr pScreen, void *pbits); + +#ifdef XWIN_NATIVEGDI +BOOL +winPaintBackground (HWND hwnd, COLORREF colorref); +#endif + + +/* + * winmouse.c + */ + +int +winMouseProc (DeviceIntPtr pDeviceInt, int iState); + +int +winMouseWheel (ScreenPtr pScreen, int iDeltaZ); + +void +winMouseButtonsSendEvent (int iEventType, int iButton); + +int +winMouseButtonsHandle (ScreenPtr pScreen, + int iEventType, int iButton, + WPARAM wParam); + +void +winEnqueueMotion(int x, int y); + +#ifdef XWIN_NATIVEGDI +/* + * winnativegdi.c + */ + +HBITMAP +winCreateDIBNativeGDI (int iWidth, int iHeight, int iDepth, + BYTE **ppbBits, BITMAPINFO **ppbmi); + +Bool +winSetEngineFunctionsNativeGDI (ScreenPtr pScreen); +#endif + + +#ifdef XWIN_PRIMARYFB +/* + * winpfbddd.c + */ + +Bool +winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen); +#endif + + +#ifdef XWIN_NATIVEGDI +/* + * winpixmap.c + */ + +PixmapPtr +winCreatePixmapNativeGDI (ScreenPtr pScreen, int width, int height, int depth, + unsigned usage_hint); + +Bool +winDestroyPixmapNativeGDI (PixmapPtr pPixmap); + +Bool +winModifyPixmapHeaderNativeGDI (PixmapPtr pPixmap, + int iWidth, int iHeight, + int iDepth, + int iBitsPerPixel, + int devKind, + pointer pPixData); +#endif + +#ifdef XWIN_NATIVEGDI +/* + * winpolyline.c + */ + +void +winPolyLineNativeGDI (DrawablePtr pDrawable, + GCPtr pGC, + int mode, + int npt, + DDXPointPtr ppt); +#endif + + +#ifdef XWIN_NATIVEGDI +/* + * winpushpxl.c + */ + +void +winPushPixels (GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable, + int dx, int dy, int xOrg, int yOrg); +#endif + + +/* + * winscrinit.c + */ + +Bool +winScreenInit (int index, + ScreenPtr pScreen, + int argc, char **argv); + +Bool +winFinishScreenInitFB (int index, + ScreenPtr pScreen, + int argc, char **argv); + +#if defined(XWIN_NATIVEGDI) +Bool +winFinishScreenInitNativeGDI (int index, + ScreenPtr pScreen, + int argc, char **argv); +#endif + + +#ifdef XWIN_NATIVEGDI +/* + * winsetsp.c + */ + +void +winSetSpansNativeGDI (DrawablePtr pDrawable, + GCPtr pGC, + char *pSrc, + DDXPointPtr pPoints, + int *pWidth, + int nSpans, + int fSorted); +#endif + + +/* + * winshaddd.c + */ + +Bool +winSetEngineFunctionsShadowDD (ScreenPtr pScreen); + + +/* + * winshadddnl.c + */ + +Bool +winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen); + + +/* + * winshadgdi.c + */ + +Bool +winSetEngineFunctionsShadowGDI (ScreenPtr pScreen); + + +/* + * winwakeup.c + */ + +void +winWakeupHandler (int nScreen, + pointer pWakeupData, + unsigned long ulResult, + pointer pReadmask); + + +/* + * winwindow.c + */ + +#ifdef XWIN_NATIVEGDI +Bool +winCreateWindowNativeGDI (WindowPtr pWin); + +Bool +winDestroyWindowNativeGDI (WindowPtr pWin); + +Bool +winPositionWindowNativeGDI (WindowPtr pWin, int x, int y); + +void +winCopyWindowNativeGDI (WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); + +Bool +winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask); + +Bool +winUnmapWindowNativeGDI (WindowPtr pWindow); + +Bool +winMapWindowNativeGDI (WindowPtr pWindow); +#endif + +Bool +winCreateWindowRootless (WindowPtr pWindow); + +Bool +winDestroyWindowRootless (WindowPtr pWindow); + +Bool +winPositionWindowRootless (WindowPtr pWindow, int x, int y); + +Bool +winChangeWindowAttributesRootless (WindowPtr pWindow, unsigned long mask); + +Bool +winUnmapWindowRootless (WindowPtr pWindow); + +Bool +winMapWindowRootless (WindowPtr pWindow); + +void +winSetShapeRootless (WindowPtr pWindow); + + +/* + * winmultiwindowicons.c - Used by both multi-window and Win32Rootless + */ + +HICON +winXIconToHICON (WindowPtr pWin, int iconSize); + +void +winSelectIcons(WindowPtr pWin, HICON *pIcon, HICON *pSmallIcon); + +#ifdef XWIN_MULTIWINDOW +/* + * winmultiwindowshape.c + */ + +void +winReshapeMultiWindow (WindowPtr pWin); + +void +winSetShapeMultiWindow (WindowPtr pWindow); + +void +winUpdateRgnMultiWindow (WindowPtr pWindow); +#endif + + +#ifdef XWIN_MULTIWINDOW +/* + * winmultiwindowwindow.c + */ + +Bool +winCreateWindowMultiWindow (WindowPtr pWindow); + +Bool +winDestroyWindowMultiWindow (WindowPtr pWindow); + +Bool +winPositionWindowMultiWindow (WindowPtr pWindow, int x, int y); + +Bool +winChangeWindowAttributesMultiWindow (WindowPtr pWindow, unsigned long mask); + +Bool +winUnmapWindowMultiWindow (WindowPtr pWindow); + +Bool +winMapWindowMultiWindow (WindowPtr pWindow); + +void +winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent); + +void +winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib); + +void +winReorderWindowsMultiWindow (void); + +void +winResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w, + unsigned int h, WindowPtr pSib); +void +winMoveWindowMultiWindow (WindowPtr pWin, int x, int y, + WindowPtr pSib, VTKind kind); + +void +winCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt, + RegionPtr oldRegion); + +XID +winGetWindowID (WindowPtr pWin); + +int +winAdjustXWindow (WindowPtr pWin, HWND hwnd); +#endif + + +#ifdef XWIN_MULTIWINDOW +/* + * winmultiwindowwndproc.c + */ + +LRESULT CALLBACK +winTopLevelWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); +#endif + + +/* + * wintrayicon.c + */ + +void +winInitNotifyIcon (winPrivScreenPtr pScreenPriv, Bool Modify); + +void +winDeleteNotifyIcon (winPrivScreenPtr pScreenPriv); + +LRESULT +winHandleIconMessage (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam, + winPrivScreenPtr pScreenPriv); + + +/* + * winwndproc.c + */ + +LRESULT CALLBACK +winWindowProc (HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam); + + +#ifdef XWIN_MULTIWINDOWEXTWM +/* + * winwin32rootless.c + */ + +Bool +winMWExtWMCreateFrame (RootlessWindowPtr pFrame, ScreenPtr pScreen, + int newX, int newY, RegionPtr pShape); + +void +winMWExtWMDestroyFrame (RootlessFrameID wid); + +void +winMWExtWMMoveFrame (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); + +void +winMWExtWMResizeFrame (RootlessFrameID wid, ScreenPtr pScreen, + int newX, int newY, unsigned int newW, unsigned int newH, + unsigned int gravity); + +void +winMWExtWMRestackFrame (RootlessFrameID wid, RootlessFrameID nextWid); + +void +winMWExtWMReshapeFrame (RootlessFrameID wid, RegionPtr pShape); + +void +winMWExtWMUnmapFrame (RootlessFrameID wid); + +void +winMWExtWMStartDrawing (RootlessFrameID wid, char **pixelData, int *bytesPerRow); + +void +winMWExtWMStopDrawing (RootlessFrameID wid, Bool flush); + +void +winMWExtWMUpdateRegion (RootlessFrameID wid, RegionPtr pDamage); + +void +winMWExtWMDamageRects (RootlessFrameID wid, int count, const BoxRec *rects, + int shift_x, int shift_y); + +void +winMWExtWMRootlessSwitchWindow (RootlessWindowPtr pFrame, WindowPtr oldWin); + +void +winMWExtWMCopyBytes (unsigned int width, unsigned int height, + const void *src, unsigned int srcRowBytes, + void *dst, unsigned int dstRowBytes); + +void +winMWExtWMFillBytes (unsigned int width, unsigned int height, unsigned int value, + void *dst, unsigned int dstRowBytes); + +int +winMWExtWMCompositePixels (unsigned int width, unsigned int height, unsigned int function, + void *src[2], unsigned int srcRowBytes[2], + void *mask, unsigned int maskRowBytes, + void *dst[2], unsigned int dstRowBytes[2]); + +void +winMWExtWMCopyWindow (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects, + int dx, int dy); +#endif + + +#ifdef XWIN_MULTIWINDOWEXTWM +/* + * winwin32rootlesswindow.c + */ + +void +winMWExtWMReorderWindows (ScreenPtr pScreen); + +void +winMWExtWMMoveXWindow (WindowPtr pWin, int x, int y); + +void +winMWExtWMResizeXWindow (WindowPtr pWin, int w, int h); + +void +winMWExtWMMoveResizeXWindow (WindowPtr pWin, int x, int y, int w, int h); + +void +winMWExtWMUpdateIcon (Window id); + +void +winMWExtWMUpdateWindowDecoration (win32RootlessWindowPtr pRLWinPriv, + winScreenInfoPtr pScreenInfo); + +wBOOL CALLBACK +winMWExtWMDecorateWindow (HWND hwnd, LPARAM lParam); + +Bool +winIsInternalWMRunning (winScreenInfoPtr pScreenInfo); + +void +winMWExtWMRestackWindows (ScreenPtr pScreen); +#endif + + +#ifdef XWIN_MULTIWINDOWEXTWM +/* + * winwin32rootlesswndproc.c + */ + +LRESULT CALLBACK +winMWExtWMWindowProc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam); +#endif + + +/* + * winwindowswm.c + */ + +void +winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg, + Window window, int x, int y, int w, int h); + +void +winWindowsWMExtensionInit (void); + +/* + * wincursor.c + */ + +Bool +winInitCursor (ScreenPtr pScreen); + +/* + * winprocarg.c + */ +void +winInitializeScreens(int maxscreens); + +/* + * windisplay.c + */ + +void +winGetDisplayName(char *szDisplay, unsigned int screen); + +/* + * END DDX and DIX Function Prototypes + */ + +#endif /* _WIN_H_ */ + diff --git a/xorg-server/hw/xwin/winauth.c b/xorg-server/hw/xwin/winauth.c index 581098694..10bce693b 100644 --- a/xorg-server/hw/xwin/winauth.c +++ b/xorg-server/hw/xwin/winauth.c @@ -163,7 +163,7 @@ winGenerateAuthorization (void) #ifdef XCSECURITY /* Allocate structure for additional auth information */ pAuth = (SecurityAuthorizationPtr) - xalloc (sizeof (SecurityAuthorizationRec)); + malloc(sizeof (SecurityAuthorizationRec)); if (!(pAuth)) { ErrorF ("winGenerateAuthorization - Failed allocating " @@ -199,7 +199,7 @@ winGenerateAuthorization (void) auth_bailout: if (fFreeAuth) - xfree (pAuth); + free(pAuth); return FALSE; } diff --git a/xorg-server/hw/xwin/winconfig.c b/xorg-server/hw/xwin/winconfig.c index c3b9dcc35..afdf6926e 100644 --- a/xorg-server/hw/xwin/winconfig.c +++ b/xorg-server/hw/xwin/winconfig.c @@ -390,10 +390,10 @@ winConfigKeyboard (DeviceIntPtr pDevice) (1000 / g_winInfo.keyboard.rate) < 1) { ErrorF ("\"%s\" is not a valid AutoRepeat value", s); - xfree(s); + free(s); return FALSE; } - xfree(s); + free(s); winDebug ("AutoRepeat: %ld %ld\n", g_winInfo.keyboard.delay, g_winInfo.keyboard.rate); } diff --git a/xorg-server/hw/xwin/windialogs.c b/xorg-server/hw/xwin/windialogs.c index adbec19cb..17d4d3226 100644 --- a/xorg-server/hw/xwin/windialogs.c +++ b/xorg-server/hw/xwin/windialogs.c @@ -373,7 +373,7 @@ winExitDlgProc (HWND hDialog, UINT message, /* Set the number of connected clients */ SetWindowText (GetDlgItem (hDialog, IDC_CLIENTS_CONNECTED), pszConnectedClients); - xfree (pszConnectedClients); + free(pszConnectedClients); } return TRUE; diff --git a/xorg-server/hw/xwin/winerror.c b/xorg-server/hw/xwin/winerror.c index 7cbfd65e2..2e706009c 100644 --- a/xorg-server/hw/xwin/winerror.c +++ b/xorg-server/hw/xwin/winerror.c @@ -1,170 +1,170 @@ -/* - *Copyright (C) 2001-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II - *shall not be used in advertising or otherwise to promote the sale, use - *or other dealings in this Software without prior written authorization - *from Harold L Hunt II. - * - * Authors: Harold L Hunt II - */ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#ifdef XVENDORNAME -#define VENDOR_STRING XVENDORNAME -#define VENDOR_CONTACT BUILDERADDR -#endif - -#include <../xfree86/common/xorgVersion.h> -#include "win.h" - -/* References to external symbols */ -extern char * g_pszCommandLine; -extern const char * g_pszLogFile; -extern Bool g_fSilentFatalError; -extern Bool g_fSilentDupError; -extern Bool g_fLogInited; - -#ifdef DDXOSVERRORF -/* Prototype */ -void -OsVendorVErrorF (const char *pszFormat, va_list va_args); - -void -OsVendorVErrorF (const char *pszFormat, va_list va_args) -{ -#if defined(XWIN_CLIPBOARD) || defined (XWIN_MULTIWINDOW) - /* make sure the clipboard and multiwindow threads do not interfere the - * main thread */ - static pthread_mutex_t s_pmPrinting = PTHREAD_MUTEX_INITIALIZER; - - /* Lock the printing mutex */ - pthread_mutex_lock (&s_pmPrinting); -#endif - - /* - If we want to silence it, - detect if we are going to abort due to duplication error - */ - if (g_fSilentDupError) - { - if ((strcmp(pszFormat, - "InitOutput - Duplicate invocation on display " - "number: %s. Exiting.\n") == 0) - || (strcmp(pszFormat, - "Server is already active for display %s\n%s %s\n%s\n") == 0) - || (strcmp(pszFormat, - "MakeAllCOTSServerListeners: server already running\n") == 0)) - { - g_fSilentFatalError = TRUE; - } - } - - /* Print the error message to a log file, could be stderr */ - LogVWrite (0, pszFormat, va_args); - -#if defined(XWIN_CLIPBOARD) || defined (XWIN_MULTIWINDOW) - /* Unlock the printing mutex */ - pthread_mutex_unlock (&s_pmPrinting); -#endif -} -#endif - - -/* - * os/util.c/FatalError () calls our vendor ErrorF, so the message - * from a FatalError will be logged. Thus, the message for the - * fatal error is not passed to this function. - * - * Attempt to do last-ditch, safe, important cleanup here. - */ -void -OsVendorFatalError (void) -{ - /* Don't give duplicate warning if UseMsg was called */ - if (g_fSilentFatalError) - return; - - if (!g_fLogInited) { - g_fLogInited = TRUE; - g_pszLogFile = LogInit (g_pszLogFile, NULL); - } - LogClose (); - - winMessageBoxF ( - "A fatal error has occurred and " PROJECT_NAME " will now exit.\n" \ - "Please open %s for more information.\n", - MB_ICONERROR, (g_pszLogFile?g_pszLogFile:"the logfile")); -} - - -/* - * winMessageBoxF - Print a formatted error message in a useful - * message box. - */ - -void -winMessageBoxF (const char *pszError, UINT uType, ...) -{ - char * pszErrorF = NULL; - char * pszMsgBox = NULL; - va_list args; - - va_start(args, uType); - pszErrorF = Xvprintf(pszError, args); - va_end(args); - if (!pszErrorF) - goto winMessageBoxF_Cleanup; - -#define MESSAGEBOXF \ - "%s\n" \ - "Vendor: %s\n" \ - "Release: %d.%d.%d.%d (%d)\n" \ - "Contact: %s\n" \ - "%s\n\n" \ - "XWin was started with the following command-line:\n\n" \ - "%s\n" - - pszMsgBox = Xprintf (MESSAGEBOXF, - pszErrorF, VENDOR_STRING, - XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP, XORG_VERSION_CURRENT, - VENDOR_CONTACT, - BUILDERSTRING, - g_pszCommandLine); - if (!pszMsgBox) - goto winMessageBoxF_Cleanup; - - /* Display the message box string */ - MessageBox (NULL, - pszMsgBox, - PROJECT_NAME, - MB_OK | uType); - - winMessageBoxF_Cleanup: - if (pszErrorF) - xfree (pszErrorF); - if (pszMsgBox) - xfree (pszMsgBox); -#undef MESSAGEBOXF -} +/* + *Copyright (C) 2001-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from Harold L Hunt II. + * + * Authors: Harold L Hunt II + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#ifdef XVENDORNAME +#define VENDOR_STRING XVENDORNAME +#define VENDOR_CONTACT BUILDERADDR +#endif + +#include <../xfree86/common/xorgVersion.h> +#include "win.h" + +/* References to external symbols */ +extern char * g_pszCommandLine; +extern const char * g_pszLogFile; +extern Bool g_fSilentFatalError; +extern Bool g_fSilentDupError; +extern Bool g_fLogInited; + +#ifdef DDXOSVERRORF +/* Prototype */ +void +OsVendorVErrorF (const char *pszFormat, va_list va_args); + +void +OsVendorVErrorF (const char *pszFormat, va_list va_args) +{ +#if defined(XWIN_CLIPBOARD) || defined (XWIN_MULTIWINDOW) + /* make sure the clipboard and multiwindow threads do not interfere the + * main thread */ + static pthread_mutex_t s_pmPrinting = PTHREAD_MUTEX_INITIALIZER; + + /* Lock the printing mutex */ + pthread_mutex_lock (&s_pmPrinting); +#endif + + /* + If we want to silence it, + detect if we are going to abort due to duplication error + */ + if (g_fSilentDupError) + { + if ((strcmp(pszFormat, + "InitOutput - Duplicate invocation on display " + "number: %s. Exiting.\n") == 0) + || (strcmp(pszFormat, + "Server is already active for display %s\n%s %s\n%s\n") == 0) + || (strcmp(pszFormat, + "MakeAllCOTSServerListeners: server already running\n") == 0)) + { + g_fSilentFatalError = TRUE; + } + } + + /* Print the error message to a log file, could be stderr */ + LogVWrite (0, pszFormat, va_args); + +#if defined(XWIN_CLIPBOARD) || defined (XWIN_MULTIWINDOW) + /* Unlock the printing mutex */ + pthread_mutex_unlock (&s_pmPrinting); +#endif +} +#endif + + +/* + * os/util.c/FatalError () calls our vendor ErrorF, so the message + * from a FatalError will be logged. Thus, the message for the + * fatal error is not passed to this function. + * + * Attempt to do last-ditch, safe, important cleanup here. + */ +void +OsVendorFatalError (void) +{ + /* Don't give duplicate warning if UseMsg was called */ + if (g_fSilentFatalError) + return; + + if (!g_fLogInited) { + g_fLogInited = TRUE; + g_pszLogFile = LogInit (g_pszLogFile, NULL); + } + LogClose (); + + winMessageBoxF ( + "A fatal error has occurred and " PROJECT_NAME " will now exit.\n" \ + "Please open %s for more information.\n", + MB_ICONERROR, (g_pszLogFile?g_pszLogFile:"the logfile")); +} + + +/* + * winMessageBoxF - Print a formatted error message in a useful + * message box. + */ + +void +winMessageBoxF (const char *pszError, UINT uType, ...) +{ + char * pszErrorF = NULL; + char * pszMsgBox = NULL; + va_list args; + + va_start(args, uType); + pszErrorF = Xvprintf(pszError, args); + va_end(args); + if (!pszErrorF) + goto winMessageBoxF_Cleanup; + +#define MESSAGEBOXF \ + "%s\n" \ + "Vendor: %s\n" \ + "Release: %d.%d.%d.%d (%d)\n" \ + "Contact: %s\n" \ + "%s\n\n" \ + "XWin was started with the following command-line:\n\n" \ + "%s\n" + + pszMsgBox = Xprintf (MESSAGEBOXF, + pszErrorF, VENDOR_STRING, + XORG_VERSION_MAJOR, XORG_VERSION_MINOR, XORG_VERSION_PATCH, XORG_VERSION_SNAP, XORG_VERSION_CURRENT, + VENDOR_CONTACT, + BUILDERSTRING, + g_pszCommandLine); + if (!pszMsgBox) + goto winMessageBoxF_Cleanup; + + /* Display the message box string */ + MessageBox (NULL, + pszMsgBox, + PROJECT_NAME, + MB_OK | uType); + + winMessageBoxF_Cleanup: + if (pszErrorF) + free(pszErrorF); + if (pszMsgBox) + free(pszMsgBox); +#undef MESSAGEBOXF +} diff --git a/xorg-server/hw/xwin/winvideo.c b/xorg-server/hw/xwin/winvideo.c index 529ca76d3..42f46f405 100644 --- a/xorg-server/hw/xwin/winvideo.c +++ b/xorg-server/hw/xwin/winvideo.c @@ -1,210 +1,210 @@ -/* - *Copyright (C) 2003-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II - *shall not be used in advertising or otherwise to promote the sale, use - *or other dealings in this Software without prior written authorization - *from Harold L Hunt II. - * - * Authors: Harold L Hunt II - */ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#include "win.h" -#include <X11/extensions/Xv.h> -#include <X11/extensions/Xvproto.h> - -void -winInitVideo (ScreenPtr pScreen); - -/* - * winInitVideo - Initialize support for the X Video (Xv) Extension. - */ - -void -winInitVideo (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - - if (pScreenInfo->dwBPP > 8) - { - - } - - -} - - - - - - - -#if 0 -#include "../xfree86/common/xf86.h" -#include "../Xext/xvdix.h" -#include "../xfree86/common/xf86xv.h" -#include <X11/extensions/Xv.h> -#endif - -#include "win.h" - - - -#if 0 -/* client libraries expect an encoding */ -static XF86VideoEncodingRec DummyEncoding[1] = -{ - { - 0, - "XV_IMAGE", - IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, - {1, 1} - } -}; - -#define NUM_FORMATS 3 - -static XF86VideoFormatRec Formats[NUM_FORMATS] = -{ - {15, TrueColor}, {16, TrueColor}, {24, TrueColor} -}; - -#define NUM_ATTRIBUTES 3 - -static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = -{ - {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, - {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, - {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} -}; - -#define NUM_IMAGES 4 - -static XF86ImageRec Images[NUM_IMAGES] = -{ - XVIMAGE_YUY2, - XVIMAGE_YV12, - XVIMAGE_I420, - XVIMAGE_UYVY -}; - - - -/* - * winInitVideo - Initialize support for the X Video (Xv) Extension. - */ - -void -winInitVideo (ScreenPtr pScreen) -{ - winScreenPriv(pScreen); - winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; - XF86VideoAdaptorPtr newAdaptor = NULL; - - if (pScreenInfo->dwBPP > 8) - { - newAdaptor = I810SetupImageVideo (pScreen); - I810InitOffscreenImages (pScreen); - } - - xf86XVScreenInit (pScreen, adaptors, 1); -} - - -static XF86VideoAdaptorPtr -winSetupImageVideo (ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; -#if 0 - I810Ptr pI810 = I810PTR(pScrn); -#endif - XF86VideoAdaptorPtr adapt; - - if (!(adapt = xcalloc (1, sizeof(XF86VideoAdaptorRec)))) - return NULL; - - adapt->type = XvWindowMask | XvInputMask | XvImageMask; - adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; - adapt->name = PROJECT_NAME " Video Overlay"; - adapt->nEncodings = 1; - adapt->pEncodings = DummyEncoding; - adapt->nFormats = NUM_FORMATS; - adapt->pFormats = Formats; - adapt->nPorts = 1; - adapt->pPortPrivates = NULL; - - adapt->pPortPrivates[0].ptr = NULL; - adapt->pAttributes = Attributes; - adapt->nImages = NUM_IMAGES; - adapt->nAttributes = NUM_ATTRIBUTES; - adapt->pImages = Images; - adapt->PutVideo = NULL; - adapt->PutStill = NULL; - adapt->GetVideo = NULL; - adapt->GetStill = NULL; -#if 0 - adapt->StopVideo = I810StopVideo; - adapt->SetPortAttribute = I810SetPortAttribute; - adapt->GetPortAttribute = I810GetPortAttribute; - adapt->QueryBestSize = I810QueryBestSize; - adapt->PutImage = I810PutImage; - adapt->QueryImageAttributes = I810QueryImageAttributes; -#endif - -#if 0 - pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1); -#endif - pPriv->videoStatus = 0; - pPriv->brightness = 0; - pPriv->contrast = 64; - pPriv->linear = NULL; - pPriv->currentBuf = 0; - -#if 0 - /* gotta uninit this someplace */ - REGION_NULL(pScreen, &pPriv->clip); -#endif - -#if 0 - pI810->adaptor = adapt; - - pI810->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = I810BlockHandler; -#endif - -#if 0 - xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); - xvContrast = MAKE_ATOM("XV_CONTRAST"); - xvColorKey = MAKE_ATOM("XV_COLORKEY"); -#endif - -#if 0 - I810ResetVideo(pScrn); -#endif - - return adapt; -} -#endif +/* + *Copyright (C) 2003-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from Harold L Hunt II. + * + * Authors: Harold L Hunt II + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#include "win.h" +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> + +void +winInitVideo (ScreenPtr pScreen); + +/* + * winInitVideo - Initialize support for the X Video (Xv) Extension. + */ + +void +winInitVideo (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + + if (pScreenInfo->dwBPP > 8) + { + + } + + +} + + + + + + + +#if 0 +#include "../xfree86/common/xf86.h" +#include "../Xext/xvdix.h" +#include "../xfree86/common/xf86xv.h" +#include <X11/extensions/Xv.h> +#endif + +#include "win.h" + + + +#if 0 +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + {1, 1} + } +}; + +#define NUM_FORMATS 3 + +static XF86VideoFormatRec Formats[NUM_FORMATS] = +{ + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#define NUM_ATTRIBUTES 3 + +static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, + {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} +}; + +#define NUM_IMAGES 4 + +static XF86ImageRec Images[NUM_IMAGES] = +{ + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_UYVY +}; + + + +/* + * winInitVideo - Initialize support for the X Video (Xv) Extension. + */ + +void +winInitVideo (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + XF86VideoAdaptorPtr newAdaptor = NULL; + + if (pScreenInfo->dwBPP > 8) + { + newAdaptor = I810SetupImageVideo (pScreen); + I810InitOffscreenImages (pScreen); + } + + xf86XVScreenInit (pScreen, adaptors, 1); +} + + +static XF86VideoAdaptorPtr +winSetupImageVideo (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; +#if 0 + I810Ptr pI810 = I810PTR(pScrn); +#endif + XF86VideoAdaptorPtr adapt; + + if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = PROJECT_NAME " Video Overlay"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 1; + adapt->pPortPrivates = NULL; + + adapt->pPortPrivates[0].ptr = NULL; + adapt->pAttributes = Attributes; + adapt->nImages = NUM_IMAGES; + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; +#if 0 + adapt->StopVideo = I810StopVideo; + adapt->SetPortAttribute = I810SetPortAttribute; + adapt->GetPortAttribute = I810GetPortAttribute; + adapt->QueryBestSize = I810QueryBestSize; + adapt->PutImage = I810PutImage; + adapt->QueryImageAttributes = I810QueryImageAttributes; +#endif + +#if 0 + pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1); +#endif + pPriv->videoStatus = 0; + pPriv->brightness = 0; + pPriv->contrast = 64; + pPriv->linear = NULL; + pPriv->currentBuf = 0; + +#if 0 + /* gotta uninit this someplace */ + REGION_NULL(pScreen, &pPriv->clip); +#endif + +#if 0 + pI810->adaptor = adapt; + + pI810->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = I810BlockHandler; +#endif + +#if 0 + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); +#endif + +#if 0 + I810ResetVideo(pScrn); +#endif + + return adapt; +} +#endif diff --git a/xorg-server/hw/xwin/winwindow.c b/xorg-server/hw/xwin/winwindow.c index 6f22a5a6e..8156671cd 100644 --- a/xorg-server/hw/xwin/winwindow.c +++ b/xorg-server/hw/xwin/winwindow.c @@ -1,593 +1,593 @@ -/* - *Copyright (C) 1994-2000 The XFree86 Project, 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 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. - * - * Authors: Harold L Hunt II - * Kensuke Matsuzaki - */ - -#ifdef HAVE_XWIN_CONFIG_H -#include <xwin-config.h> -#endif -#include "win.h" - - -/* - * Prototypes for local functions - */ - -static int -winAddRgn (WindowPtr pWindow, pointer data); - -static -void -winUpdateRgnRootless (WindowPtr pWindow); - -static -void -winReshapeRootless (WindowPtr pWin); - - -#ifdef XWIN_NATIVEGDI -/* See Porting Layer Definition - p. 37 */ -/* See mfb/mfbwindow.c - mfbCreateWindow() */ - -Bool -winCreateWindowNativeGDI (WindowPtr pWin) -{ - Bool fResult; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winCreateWindowNativeGDI (%p)\n", pWin); - - WIN_UNWRAP(CreateWindow); - fResult = (*pScreen->CreateWindow) (pWin); - WIN_WRAP(CreateWindow, winCreateWindowNativeGDI); - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 */ -/* See mfb/mfbwindow.c - mfbDestroyWindow() */ - -Bool -winDestroyWindowNativeGDI (WindowPtr pWin) -{ - Bool fResult = TRUE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winDestroyWindowNativeGDI (%p)\n", pWin); - - WIN_UNWRAP(DestroyWindow); - fResult = (*pScreen->DestroyWindow)(pWin); - WIN_WRAP(DestroyWindow, winDestroyWindowNativeGDI); - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 */ -/* See mfb/mfbwindow.c - mfbPositionWindow() */ - -Bool -winPositionWindowNativeGDI (WindowPtr pWin, int x, int y) -{ - Bool fResult = TRUE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winPositionWindowNativeGDI (%p)\n", pWin); - - WIN_UNWRAP(PositionWindow); - fResult = (*pScreen->PositionWindow)(pWin, x, y); - WIN_WRAP(PositionWindow, winPositionWindowNativeGDI); - - return fResult; -} - - -/* See Porting Layer Definition - p. 39 */ -/* See mfb/mfbwindow.c - mfbCopyWindow() */ - -void -winCopyWindowNativeGDI (WindowPtr pWin, - DDXPointRec ptOldOrg, - RegionPtr prgnSrc) -{ - DDXPointPtr pptSrc; - DDXPointPtr ppt; - RegionPtr prgnDst; - BoxPtr pBox; - int dx, dy; - int i, nbox; - WindowPtr pwinRoot; - BoxPtr pBoxDst; - ScreenPtr pScreen = pWin->drawable.pScreen; - winScreenPriv(pScreen); - - /* Get a pointer to the root window */ - pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; - - /* Create a region for the destination */ - prgnDst = REGION_CREATE(pWin->drawable.pScreen, NULL, 1); - - /* Calculate the shift from the source to the destination */ - dx = ptOldOrg.x - pWin->drawable.x; - dy = ptOldOrg.y - pWin->drawable.y; - - /* Translate the region from the destination to the source? */ - REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); - REGION_INTERSECT(pWin->drawable.pScreen, prgnDst, &pWin->borderClip, - prgnSrc); - - /* Get a pointer to the first box in the region to be copied */ - pBox = REGION_RECTS(prgnDst); - - /* Get the number of boxes in the region */ - nbox = REGION_NUM_RECTS(prgnDst); - - /* Allocate source points for each box */ - if(!(pptSrc = (DDXPointPtr )xalloc(nbox * sizeof(DDXPointRec)))) - return; - - /* Set an iterator pointer */ - ppt = pptSrc; - - /* Calculate the source point of each box? */ - for (i = nbox; --i >= 0; ppt++, pBox++) - { - ppt->x = pBox->x1 + dx; - ppt->y = pBox->y1 + dy; - } - - /* Setup loop pointers again */ - pBoxDst = REGION_RECTS(prgnDst); - ppt = pptSrc; - - /* BitBlt each source to the destination point */ - for (i = nbox; --i >= 0; pBoxDst++, ppt++) - { - BitBlt (pScreenPriv->hdcScreen, - pBoxDst->x1, pBoxDst->y1, - pBoxDst->x2 - pBoxDst->x1, pBoxDst->y2 - pBoxDst->y1, - pScreenPriv->hdcScreen, - ppt->x, ppt->y, - SRCCOPY); - } - - /* Cleanup the regions, etc. */ - xfree(pptSrc); - REGION_DESTROY(pWin->drawable.pScreen, prgnDst); -} - - -/* See Porting Layer Definition - p. 37 */ -/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */ - -Bool -winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask) -{ - Bool fResult = TRUE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winChangeWindowAttributesNativeGDI (%p)\n", pWin); - - WIN_UNWRAP(ChangeWindowAttributes); - fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask); - WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesNativeGDI); - - /* - * NOTE: We do not currently need to do anything here. - */ - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 - * Also referred to as UnrealizeWindow - */ - -Bool -winUnmapWindowNativeGDI (WindowPtr pWin) -{ - Bool fResult = TRUE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winUnmapWindowNativeGDI (%p)\n", pWin); - - WIN_UNWRAP(UnrealizeWindow); - fResult = (*pScreen->UnrealizeWindow)(pWin); - WIN_WRAP(UnrealizeWindow, winUnmapWindowNativeGDI); - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 - * Also referred to as RealizeWindow - */ - -Bool -winMapWindowNativeGDI (WindowPtr pWin) -{ - Bool fResult = TRUE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winMapWindowNativeGDI (%p)\n", pWin); - - WIN_UNWRAP(RealizeWindow); - fResult = (*pScreen->RealizeWindow)(pWin); - WIN_WRAP(RealizeWindow, winMapWindowMultiWindow); - - return fResult; - -} -#endif - - -/* See Porting Layer Definition - p. 37 */ -/* See mfb/mfbwindow.c - mfbCreateWindow() */ - -Bool -winCreateWindowRootless (WindowPtr pWin) -{ - Bool fResult = FALSE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winCreateWindowRootless (%p)\n", pWin); - - WIN_UNWRAP(CreateWindow); - fResult = (*pScreen->CreateWindow) (pWin); - WIN_WRAP(CreateWindow, winCreateWindowRootless); - - pWinPriv->hRgn = NULL; - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 */ -/* See mfb/mfbwindow.c - mfbDestroyWindow() */ - -Bool -winDestroyWindowRootless (WindowPtr pWin) -{ - Bool fResult = FALSE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winDestroyWindowRootless (%p)\n", pWin); - - WIN_UNWRAP(DestroyWindow); - fResult = (*pScreen->DestroyWindow)(pWin); - WIN_WRAP(DestroyWindow, winDestroyWindowRootless); - - if (pWinPriv->hRgn != NULL) - { - DeleteObject(pWinPriv->hRgn); - pWinPriv->hRgn = NULL; - } - - winUpdateRgnRootless (pWin); - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 */ -/* See mfb/mfbwindow.c - mfbPositionWindow() */ - -Bool -winPositionWindowRootless (WindowPtr pWin, int x, int y) -{ - Bool fResult = FALSE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winScreenPriv(pScreen); - - winDebug ("winPositionWindowRootless (%p)\n", pWin); - - WIN_UNWRAP(PositionWindow); - fResult = (*pScreen->PositionWindow)(pWin, x, y); - WIN_WRAP(PositionWindow, winPositionWindowRootless); - - winUpdateRgnRootless (pWin); - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 */ -/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */ - -Bool -winChangeWindowAttributesRootless (WindowPtr pWin, unsigned long mask) -{ - Bool fResult = FALSE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winScreenPriv(pScreen); - - winDebug ("winChangeWindowAttributesRootless (%p)\n", pWin); - - WIN_UNWRAP(ChangeWindowAttributes); - fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask); - WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesRootless); - - winUpdateRgnRootless (pWin); - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 - * Also referred to as UnrealizeWindow - */ - -Bool -winUnmapWindowRootless (WindowPtr pWin) -{ - Bool fResult = FALSE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winWindowPriv(pWin); - winScreenPriv(pScreen); - - winDebug ("winUnmapWindowRootless (%p)\n", pWin); - - WIN_UNWRAP(UnrealizeWindow); - fResult = (*pScreen->UnrealizeWindow)(pWin); - WIN_WRAP(UnrealizeWindow, winUnmapWindowRootless); - - if (pWinPriv->hRgn != NULL) - { - DeleteObject(pWinPriv->hRgn); - pWinPriv->hRgn = NULL; - } - - winUpdateRgnRootless (pWin); - - return fResult; -} - - -/* See Porting Layer Definition - p. 37 - * Also referred to as RealizeWindow - */ - -Bool -winMapWindowRootless (WindowPtr pWin) -{ - Bool fResult = FALSE; - ScreenPtr pScreen = pWin->drawable.pScreen; - winScreenPriv(pScreen); - - winDebug ("winMapWindowRootless (%p)\n", pWin); - - WIN_UNWRAP(RealizeWindow); - fResult = (*pScreen->RealizeWindow)(pWin); - WIN_WRAP(RealizeWindow, winMapWindowRootless); - - winReshapeRootless (pWin); - - winUpdateRgnRootless (pWin); - - return fResult; -} - - -void -winSetShapeRootless (WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - winScreenPriv(pScreen); - - winDebug ("winSetShapeRootless (%p)\n", pWin); - - WIN_UNWRAP(SetShape); - (*pScreen->SetShape)(pWin); - WIN_WRAP(SetShape, winSetShapeRootless); - - winReshapeRootless (pWin); - winUpdateRgnRootless (pWin); - - return; -} - - -/* - * Local function for adding a region to the Windows window region - */ - -static -int -winAddRgn (WindowPtr pWin, pointer data) -{ - int iX, iY, iWidth, iHeight, iBorder; - HRGN hRgn = *(HRGN*)data; - HRGN hRgnWin; - winWindowPriv(pWin); - - /* If pWin is not Root */ - if (pWin->parent != NULL) - { - winDebug ("winAddRgn ()\n"); - if (pWin->mapped) - { - iBorder = wBorderWidth (pWin); - - iX = pWin->drawable.x - iBorder; - iY = pWin->drawable.y - iBorder; - - iWidth = pWin->drawable.width + iBorder * 2; - iHeight = pWin->drawable.height + iBorder * 2; - - hRgnWin = CreateRectRgn (0, 0, iWidth, iHeight); - - if (hRgnWin == NULL) - { - winDebug ("winAddRgn - CreateRectRgn () failed\n"); - winDebug (" Rect %d %d %d %d\n", - iX, iY, iX + iWidth, iY + iHeight); - } - - if (pWinPriv->hRgn) - { - if (CombineRgn (hRgnWin, hRgnWin, pWinPriv->hRgn, RGN_AND) - == ERROR) - { - ErrorF ("winAddRgn - CombineRgn () failed\n"); - } - } - - OffsetRgn (hRgnWin, iX, iY); - - if (CombineRgn (hRgn, hRgn, hRgnWin, RGN_OR) == ERROR) - { - ErrorF ("winAddRgn - CombineRgn () failed\n"); - } - - DeleteObject (hRgnWin); - } - return WT_DONTWALKCHILDREN; - } - else - { - return WT_WALKCHILDREN; - } -} - - -/* - * Local function to update the Windows window's region - */ - -static -void -winUpdateRgnRootless (WindowPtr pWin) -{ - HRGN hRgn = CreateRectRgn (0, 0, 0, 0); - - if (hRgn != NULL) - { - WalkTree (pWin->drawable.pScreen, winAddRgn, &hRgn); - SetWindowRgn (winGetScreenPriv(pWin->drawable.pScreen)->hwndScreen, - hRgn, TRUE); - } - else - { - ErrorF ("winUpdateRgnRootless - CreateRectRgn failed.\n"); - } -} - - -static -void -winReshapeRootless (WindowPtr pWin) -{ - int nRects; - /* ScreenPtr pScreen = pWin->drawable.pScreen;*/ - RegionRec rrNewShape; - BoxPtr pShape, pRects, pEnd; - HRGN hRgn, hRgnRect; - winWindowPriv(pWin); - - winDebug ("winReshapeRootless ()\n"); - - /* Bail if the window is the root window */ - if (pWin->parent == NULL) - return; - - /* Bail if the window is not top level */ - if (pWin->parent->parent != NULL) - return; - - /* Free any existing window region stored in the window privates */ - if (pWinPriv->hRgn != NULL) - { - DeleteObject (pWinPriv->hRgn); - pWinPriv->hRgn = NULL; - } - - /* Bail if the window has no bounding region defined */ - if (!wBoundingShape (pWin)) - return; - - REGION_NULL(pScreen, &rrNewShape); - REGION_COPY(pScreen, &rrNewShape, wBoundingShape(pWin)); - REGION_TRANSLATE(pScreen, &rrNewShape, pWin->borderWidth, - pWin->borderWidth); - - nRects = REGION_NUM_RECTS(&rrNewShape); - pShape = REGION_RECTS(&rrNewShape); - - if (nRects > 0) - { - /* Create initial empty Windows region */ - hRgn = CreateRectRgn (0, 0, 0, 0); - - /* Loop through all rectangles in the X region */ - for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) - { - /* Create a Windows region for the X rectangle */ - hRgnRect = CreateRectRgn (pRects->x1, pRects->y1, - pRects->x2, pRects->y2); - if (hRgnRect == NULL) - { - ErrorF("winReshapeRootless - CreateRectRgn() failed\n"); - } - - /* Merge the Windows region with the accumulated region */ - if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) - { - ErrorF("winReshapeRootless - CombineRgn() failed\n"); - } - - /* Delete the temporary Windows region */ - DeleteObject (hRgnRect); - } - - /* Save a handle to the composite region in the window privates */ - pWinPriv->hRgn = hRgn; - } - - REGION_UNINIT(pScreen, &rrNewShape); - - return; -} +/* + *Copyright (C) 1994-2000 The XFree86 Project, 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 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. + * + * Authors: Harold L Hunt II + * Kensuke Matsuzaki + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#include "win.h" + + +/* + * Prototypes for local functions + */ + +static int +winAddRgn (WindowPtr pWindow, pointer data); + +static +void +winUpdateRgnRootless (WindowPtr pWindow); + +static +void +winReshapeRootless (WindowPtr pWin); + + +#ifdef XWIN_NATIVEGDI +/* See Porting Layer Definition - p. 37 */ +/* See mfb/mfbwindow.c - mfbCreateWindow() */ + +Bool +winCreateWindowNativeGDI (WindowPtr pWin) +{ + Bool fResult; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winCreateWindowNativeGDI (%p)\n", pWin); + + WIN_UNWRAP(CreateWindow); + fResult = (*pScreen->CreateWindow) (pWin); + WIN_WRAP(CreateWindow, winCreateWindowNativeGDI); + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 */ +/* See mfb/mfbwindow.c - mfbDestroyWindow() */ + +Bool +winDestroyWindowNativeGDI (WindowPtr pWin) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winDestroyWindowNativeGDI (%p)\n", pWin); + + WIN_UNWRAP(DestroyWindow); + fResult = (*pScreen->DestroyWindow)(pWin); + WIN_WRAP(DestroyWindow, winDestroyWindowNativeGDI); + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 */ +/* See mfb/mfbwindow.c - mfbPositionWindow() */ + +Bool +winPositionWindowNativeGDI (WindowPtr pWin, int x, int y) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winPositionWindowNativeGDI (%p)\n", pWin); + + WIN_UNWRAP(PositionWindow); + fResult = (*pScreen->PositionWindow)(pWin, x, y); + WIN_WRAP(PositionWindow, winPositionWindowNativeGDI); + + return fResult; +} + + +/* See Porting Layer Definition - p. 39 */ +/* See mfb/mfbwindow.c - mfbCopyWindow() */ + +void +winCopyWindowNativeGDI (WindowPtr pWin, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + DDXPointPtr pptSrc; + DDXPointPtr ppt; + RegionPtr prgnDst; + BoxPtr pBox; + int dx, dy; + int i, nbox; + WindowPtr pwinRoot; + BoxPtr pBoxDst; + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + + /* Get a pointer to the root window */ + pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; + + /* Create a region for the destination */ + prgnDst = REGION_CREATE(pWin->drawable.pScreen, NULL, 1); + + /* Calculate the shift from the source to the destination */ + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + + /* Translate the region from the destination to the source? */ + REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); + REGION_INTERSECT(pWin->drawable.pScreen, prgnDst, &pWin->borderClip, + prgnSrc); + + /* Get a pointer to the first box in the region to be copied */ + pBox = REGION_RECTS(prgnDst); + + /* Get the number of boxes in the region */ + nbox = REGION_NUM_RECTS(prgnDst); + + /* Allocate source points for each box */ + if(!(pptSrc = (DDXPointPtr )malloc(nbox * sizeof(DDXPointRec)))) + return; + + /* Set an iterator pointer */ + ppt = pptSrc; + + /* Calculate the source point of each box? */ + for (i = nbox; --i >= 0; ppt++, pBox++) + { + ppt->x = pBox->x1 + dx; + ppt->y = pBox->y1 + dy; + } + + /* Setup loop pointers again */ + pBoxDst = REGION_RECTS(prgnDst); + ppt = pptSrc; + + /* BitBlt each source to the destination point */ + for (i = nbox; --i >= 0; pBoxDst++, ppt++) + { + BitBlt (pScreenPriv->hdcScreen, + pBoxDst->x1, pBoxDst->y1, + pBoxDst->x2 - pBoxDst->x1, pBoxDst->y2 - pBoxDst->y1, + pScreenPriv->hdcScreen, + ppt->x, ppt->y, + SRCCOPY); + } + + /* Cleanup the regions, etc. */ + free(pptSrc); + REGION_DESTROY(pWin->drawable.pScreen, prgnDst); +} + + +/* See Porting Layer Definition - p. 37 */ +/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */ + +Bool +winChangeWindowAttributesNativeGDI (WindowPtr pWin, unsigned long mask) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winChangeWindowAttributesNativeGDI (%p)\n", pWin); + + WIN_UNWRAP(ChangeWindowAttributes); + fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask); + WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesNativeGDI); + + /* + * NOTE: We do not currently need to do anything here. + */ + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 + * Also referred to as UnrealizeWindow + */ + +Bool +winUnmapWindowNativeGDI (WindowPtr pWin) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winUnmapWindowNativeGDI (%p)\n", pWin); + + WIN_UNWRAP(UnrealizeWindow); + fResult = (*pScreen->UnrealizeWindow)(pWin); + WIN_WRAP(UnrealizeWindow, winUnmapWindowNativeGDI); + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 + * Also referred to as RealizeWindow + */ + +Bool +winMapWindowNativeGDI (WindowPtr pWin) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winMapWindowNativeGDI (%p)\n", pWin); + + WIN_UNWRAP(RealizeWindow); + fResult = (*pScreen->RealizeWindow)(pWin); + WIN_WRAP(RealizeWindow, winMapWindowMultiWindow); + + return fResult; + +} +#endif + + +/* See Porting Layer Definition - p. 37 */ +/* See mfb/mfbwindow.c - mfbCreateWindow() */ + +Bool +winCreateWindowRootless (WindowPtr pWin) +{ + Bool fResult = FALSE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winCreateWindowRootless (%p)\n", pWin); + + WIN_UNWRAP(CreateWindow); + fResult = (*pScreen->CreateWindow) (pWin); + WIN_WRAP(CreateWindow, winCreateWindowRootless); + + pWinPriv->hRgn = NULL; + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 */ +/* See mfb/mfbwindow.c - mfbDestroyWindow() */ + +Bool +winDestroyWindowRootless (WindowPtr pWin) +{ + Bool fResult = FALSE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winDestroyWindowRootless (%p)\n", pWin); + + WIN_UNWRAP(DestroyWindow); + fResult = (*pScreen->DestroyWindow)(pWin); + WIN_WRAP(DestroyWindow, winDestroyWindowRootless); + + if (pWinPriv->hRgn != NULL) + { + DeleteObject(pWinPriv->hRgn); + pWinPriv->hRgn = NULL; + } + + winUpdateRgnRootless (pWin); + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 */ +/* See mfb/mfbwindow.c - mfbPositionWindow() */ + +Bool +winPositionWindowRootless (WindowPtr pWin, int x, int y) +{ + Bool fResult = FALSE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + + winDebug ("winPositionWindowRootless (%p)\n", pWin); + + WIN_UNWRAP(PositionWindow); + fResult = (*pScreen->PositionWindow)(pWin, x, y); + WIN_WRAP(PositionWindow, winPositionWindowRootless); + + winUpdateRgnRootless (pWin); + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 */ +/* See mfb/mfbwindow.c - mfbChangeWindowAttributes() */ + +Bool +winChangeWindowAttributesRootless (WindowPtr pWin, unsigned long mask) +{ + Bool fResult = FALSE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + + winDebug ("winChangeWindowAttributesRootless (%p)\n", pWin); + + WIN_UNWRAP(ChangeWindowAttributes); + fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask); + WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesRootless); + + winUpdateRgnRootless (pWin); + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 + * Also referred to as UnrealizeWindow + */ + +Bool +winUnmapWindowRootless (WindowPtr pWin) +{ + Bool fResult = FALSE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + winDebug ("winUnmapWindowRootless (%p)\n", pWin); + + WIN_UNWRAP(UnrealizeWindow); + fResult = (*pScreen->UnrealizeWindow)(pWin); + WIN_WRAP(UnrealizeWindow, winUnmapWindowRootless); + + if (pWinPriv->hRgn != NULL) + { + DeleteObject(pWinPriv->hRgn); + pWinPriv->hRgn = NULL; + } + + winUpdateRgnRootless (pWin); + + return fResult; +} + + +/* See Porting Layer Definition - p. 37 + * Also referred to as RealizeWindow + */ + +Bool +winMapWindowRootless (WindowPtr pWin) +{ + Bool fResult = FALSE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + + winDebug ("winMapWindowRootless (%p)\n", pWin); + + WIN_UNWRAP(RealizeWindow); + fResult = (*pScreen->RealizeWindow)(pWin); + WIN_WRAP(RealizeWindow, winMapWindowRootless); + + winReshapeRootless (pWin); + + winUpdateRgnRootless (pWin); + + return fResult; +} + + +void +winSetShapeRootless (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + + winDebug ("winSetShapeRootless (%p)\n", pWin); + + WIN_UNWRAP(SetShape); + (*pScreen->SetShape)(pWin); + WIN_WRAP(SetShape, winSetShapeRootless); + + winReshapeRootless (pWin); + winUpdateRgnRootless (pWin); + + return; +} + + +/* + * Local function for adding a region to the Windows window region + */ + +static +int +winAddRgn (WindowPtr pWin, pointer data) +{ + int iX, iY, iWidth, iHeight, iBorder; + HRGN hRgn = *(HRGN*)data; + HRGN hRgnWin; + winWindowPriv(pWin); + + /* If pWin is not Root */ + if (pWin->parent != NULL) + { + winDebug ("winAddRgn ()\n"); + if (pWin->mapped) + { + iBorder = wBorderWidth (pWin); + + iX = pWin->drawable.x - iBorder; + iY = pWin->drawable.y - iBorder; + + iWidth = pWin->drawable.width + iBorder * 2; + iHeight = pWin->drawable.height + iBorder * 2; + + hRgnWin = CreateRectRgn (0, 0, iWidth, iHeight); + + if (hRgnWin == NULL) + { + winDebug ("winAddRgn - CreateRectRgn () failed\n"); + winDebug (" Rect %d %d %d %d\n", + iX, iY, iX + iWidth, iY + iHeight); + } + + if (pWinPriv->hRgn) + { + if (CombineRgn (hRgnWin, hRgnWin, pWinPriv->hRgn, RGN_AND) + == ERROR) + { + ErrorF ("winAddRgn - CombineRgn () failed\n"); + } + } + + OffsetRgn (hRgnWin, iX, iY); + + if (CombineRgn (hRgn, hRgn, hRgnWin, RGN_OR) == ERROR) + { + ErrorF ("winAddRgn - CombineRgn () failed\n"); + } + + DeleteObject (hRgnWin); + } + return WT_DONTWALKCHILDREN; + } + else + { + return WT_WALKCHILDREN; + } +} + + +/* + * Local function to update the Windows window's region + */ + +static +void +winUpdateRgnRootless (WindowPtr pWin) +{ + HRGN hRgn = CreateRectRgn (0, 0, 0, 0); + + if (hRgn != NULL) + { + WalkTree (pWin->drawable.pScreen, winAddRgn, &hRgn); + SetWindowRgn (winGetScreenPriv(pWin->drawable.pScreen)->hwndScreen, + hRgn, TRUE); + } + else + { + ErrorF ("winUpdateRgnRootless - CreateRectRgn failed.\n"); + } +} + + +static +void +winReshapeRootless (WindowPtr pWin) +{ + int nRects; + /* ScreenPtr pScreen = pWin->drawable.pScreen;*/ + RegionRec rrNewShape; + BoxPtr pShape, pRects, pEnd; + HRGN hRgn, hRgnRect; + winWindowPriv(pWin); + + winDebug ("winReshapeRootless ()\n"); + + /* Bail if the window is the root window */ + if (pWin->parent == NULL) + return; + + /* Bail if the window is not top level */ + if (pWin->parent->parent != NULL) + return; + + /* Free any existing window region stored in the window privates */ + if (pWinPriv->hRgn != NULL) + { + DeleteObject (pWinPriv->hRgn); + pWinPriv->hRgn = NULL; + } + + /* Bail if the window has no bounding region defined */ + if (!wBoundingShape (pWin)) + return; + + REGION_NULL(pScreen, &rrNewShape); + REGION_COPY(pScreen, &rrNewShape, wBoundingShape(pWin)); + REGION_TRANSLATE(pScreen, &rrNewShape, pWin->borderWidth, + pWin->borderWidth); + + nRects = REGION_NUM_RECTS(&rrNewShape); + pShape = REGION_RECTS(&rrNewShape); + + if (nRects > 0) + { + /* Create initial empty Windows region */ + hRgn = CreateRectRgn (0, 0, 0, 0); + + /* Loop through all rectangles in the X region */ + for (pRects = pShape, pEnd = pShape + nRects; pRects < pEnd; pRects++) + { + /* Create a Windows region for the X rectangle */ + hRgnRect = CreateRectRgn (pRects->x1, pRects->y1, + pRects->x2, pRects->y2); + if (hRgnRect == NULL) + { + ErrorF("winReshapeRootless - CreateRectRgn() failed\n"); + } + + /* Merge the Windows region with the accumulated region */ + if (CombineRgn (hRgn, hRgn, hRgnRect, RGN_OR) == ERROR) + { + ErrorF("winReshapeRootless - CombineRgn() failed\n"); + } + + /* Delete the temporary Windows region */ + DeleteObject (hRgnRect); + } + + /* Save a handle to the composite region in the window privates */ + pWinPriv->hRgn = hRgn; + } + + REGION_UNINIT(pScreen, &rrNewShape); + + return; +} diff --git a/xorg-server/hw/xwin/winwindowswm.c b/xorg-server/hw/xwin/winwindowswm.c index d0c6de9bc..e16f6cfaf 100644 --- a/xorg-server/hw/xwin/winwindowswm.c +++ b/xorg-server/hw/xwin/winwindowswm.c @@ -124,7 +124,7 @@ ProcWindowsWMQueryVersion(register ClientPtr client) swapl(&rep.length, n); } WriteToClient(client, sizeof(xWindowsWMQueryVersionReply), (char *)&rep); - return (client->noClientException); + return Success; } @@ -164,7 +164,7 @@ WMFreeClient (pointer data, XID id) } updateEventMask (pHead); } - xfree ((pointer) pEvent); + free((pointer) pEvent); return 1; } @@ -179,9 +179,9 @@ WMFreeEvents (pointer data, XID id) { pNext = pCur->next; FreeResource (pCur->clientResource, ClientType); - xfree ((pointer) pCur); + free((pointer) pCur); } - xfree ((pointer) pHead); + free((pointer) pHead); eventMask = 0; return 1; } @@ -212,7 +212,7 @@ ProcWindowsWMSelectInput (register ClientPtr client) } /* build the entry */ - pNewEvent = (WMEventPtr) xalloc (sizeof (WMEventRec)); + pNewEvent = (WMEventPtr) malloc(sizeof (WMEventRec)); if (!pNewEvent) return BadAlloc; pNewEvent->next = 0; @@ -234,7 +234,7 @@ ProcWindowsWMSelectInput (register ClientPtr client) */ if (!pHead) { - pHead = (WMEventPtr *) xalloc (sizeof (WMEventPtr)); + pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr)); if (!pHead || !AddResource (eventResource, eventResourceType, (pointer)pHead)) { @@ -266,7 +266,7 @@ ProcWindowsWMSelectInput (register ClientPtr client) pNewEvent->next = pEvent->next; else *pHead = pEvent->next; - xfree (pEvent); + free(pEvent); updateEventMask (pHead); } } @@ -330,7 +330,7 @@ ProcWindowsWMDisableUpdate (register ClientPtr client) //winDisableUpdate(); - return (client->noClientException); + return Success; } static int @@ -340,7 +340,7 @@ ProcWindowsWMReenableUpdate (register ClientPtr client) //winEnableUpdate(); - return (client->noClientException); + return Success; } @@ -353,7 +353,7 @@ ProcWindowsWMSetFrontProcess (register ClientPtr client) //QuartzMessageMainThread(kWindowsSetFrontProcess, NULL, 0); - return (client->noClientException); + return Success; } @@ -403,7 +403,7 @@ ProcWindowsWMFrameGetRect (register ClientPtr client) rep.x, rep.y, rep.w, rep.h); WriteToClient(client, sizeof(xWindowsWMFrameGetRectReply), (char *)&rep); - return (client->noClientException); + return Success; } @@ -490,7 +490,7 @@ ProcWindowsWMFrameDraw (register ClientPtr client) } winDebug ("ProcWindowsWMFrameDraw - done\n"); - return (client->noClientException); + return Success; } static int @@ -541,7 +541,7 @@ ProcWindowsWMFrameSetTitle( winDebug ("ProcWindowsWMFrameSetTitle - done\n"); - return (client->noClientException); + return Success; } -- cgit v1.2.3