aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw')
-rw-r--r--xorg-server/hw/dmx/config/xdmxconfig.c23
-rw-r--r--xorg-server/hw/dmx/dmx.c2165
-rw-r--r--xorg-server/hw/dmx/dmxclient.h1
-rw-r--r--xorg-server/hw/dmx/dmxcursor.h4
-rw-r--r--xorg-server/hw/dmx/dmxextension.c2
-rw-r--r--xorg-server/hw/dmx/dmxinit.c11
-rw-r--r--xorg-server/hw/dmx/dmxprop.c695
-rw-r--r--xorg-server/hw/dmx/doc/dmx.xml6860
-rw-r--r--xorg-server/hw/dmx/examples/dmxwininfo.c3
-rw-r--r--xorg-server/hw/dmx/glxProxy/glxcmds.c41
-rw-r--r--xorg-server/hw/dmx/glxProxy/glxscreens.c703
-rw-r--r--xorg-server/hw/dmx/glxProxy/glxserver.h612
-rw-r--r--xorg-server/hw/dmx/glxProxy/render2swap.c2
-rw-r--r--xorg-server/hw/dmx/input/dmxinputinit.c6
-rw-r--r--xorg-server/hw/dmx/input/lnx-keyboard.c1980
-rw-r--r--xorg-server/hw/dmx/input/usb-common.c762
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyrdriext.c24
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyrhostproxy.c2
-rw-r--r--xorg-server/hw/vfb/InitOutput.c3
-rw-r--r--xorg-server/hw/xfree86/common/xf86.h1
-rw-r--r--xorg-server/hw/xfree86/common/xf86Config.c30
-rw-r--r--xorg-server/hw/xfree86/common/xf86Globals.c5
-rw-r--r--xorg-server/hw/xfree86/common/xf86Helper.c10
-rw-r--r--xorg-server/hw/xfree86/common/xf86Init.c12
-rw-r--r--xorg-server/hw/xfree86/common/xf86Module.h2
-rw-r--r--xorg-server/hw/xfree86/common/xf86Privstr.h335
-rw-r--r--xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c4224
-rw-r--r--xorg-server/hw/xfree86/dri/xf86dri.c24
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.c41
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.h31
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2ext.c16
-rw-r--r--xorg-server/hw/xfree86/i2c/fi1236.c1280
-rw-r--r--xorg-server/hw/xfree86/int10/generic.c976
-rw-r--r--xorg-server/hw/xfree86/int10/helper_exec.c1466
-rw-r--r--xorg-server/hw/xfree86/int10/helper_mem.c651
-rw-r--r--xorg-server/hw/xfree86/man/Xorg.man7
-rw-r--r--xorg-server/hw/xfree86/man/xorg.conf.man6
-rw-r--r--xorg-server/hw/xfree86/modes/xf86Cursors.c4
-rw-r--r--xorg-server/hw/xfree86/modes/xf86Modes.c1501
-rw-r--r--xorg-server/hw/xfree86/os-support/bsd/bsd_init.c17
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/lnx_init.c25
-rw-r--r--xorg-server/hw/xfree86/os-support/solaris/sun_init.c866
-rw-r--r--xorg-server/hw/xfree86/ramdac/xf86Cursor.c6
-rw-r--r--xorg-server/hw/xfree86/ramdac/xf86HWCurs.c1054
-rw-r--r--xorg-server/hw/xfree86/utils/man/cvt.man3
-rw-r--r--xorg-server/hw/xfree86/utils/man/gtf.man3
-rw-r--r--xorg-server/hw/xfree86/x86emu/sys.c2
-rw-r--r--xorg-server/hw/xnest/GC.c663
-rw-r--r--xorg-server/hw/xnest/XNCursor.h118
-rw-r--r--xorg-server/hw/xnest/XNGC.h85
-rw-r--r--xorg-server/hw/xquartz/applewm.c8
-rw-r--r--xorg-server/hw/xquartz/pseudoramiX.c933
-rw-r--r--xorg-server/hw/xquartz/xpr/appledri.c838
-rw-r--r--xorg-server/hw/xwin/winwindowswm.c1274
54 files changed, 15226 insertions, 15190 deletions
diff --git a/xorg-server/hw/dmx/config/xdmxconfig.c b/xorg-server/hw/dmx/config/xdmxconfig.c
index 2de7f2b85..3165ba000 100644
--- a/xorg-server/hw/dmx/config/xdmxconfig.c
+++ b/xorg-server/hw/dmx/config/xdmxconfig.c
@@ -49,7 +49,6 @@
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Dialog.h>
#include <X11/keysym.h>
-#include <X11/Xmu/SysUtil.h>
#include "Canvas.h"
#include "dmxparse.h"
@@ -199,8 +198,8 @@ static void dmxConfigDataUpdate(void)
XtVaSetValues(ndbutton1, XtNsensitive, False, NULL);
} else {
name = dmxConfigCurrent->name;
- XmuSnprintf(cnambuf, sizeof(cnambuf), "%s", name ? name : "");
- XmuSnprintf(cdimbuf, sizeof(cdimbuf), "%dx%d",
+ snprintf(cnambuf, sizeof(cnambuf), "%s", name ? name : "");
+ snprintf(cdimbuf, sizeof(cdimbuf), "%dx%d",
dmxConfigWallWidth, dmxConfigWallHeight);
XtVaSetValues(cnamebox, XtNlabel, cnambuf, XtNsensitive, True, NULL);
XtVaSetValues(cdimbox, XtNlabel, cdimbuf, XtNsensitive, True, NULL);
@@ -219,22 +218,22 @@ static void dmxConfigDataUpdate(void)
XtVaSetValues(ddbutton, XtNsensitive, False, NULL);
} else {
name = dmxConfigCurrentDisplay->name;
- XmuSnprintf(nambuf, sizeof(nambuf), "%s", name ? name : "");
- XmuSnprintf(dimbuf, sizeof(dimbuf), "%dx%d%c%d%c%d",
+ snprintf(nambuf, sizeof(nambuf), "%s", name ? name : "");
+ snprintf(dimbuf, sizeof(dimbuf), "%dx%d%c%d%c%d",
dmxConfigCurrentDisplay->scrnWidth,
dmxConfigCurrentDisplay->scrnHeight,
dmxConfigCurrentDisplay->scrnXSign < 0 ? '-' : '+',
dmxConfigCurrentDisplay->scrnX,
dmxConfigCurrentDisplay->scrnYSign < 0 ? '-' : '+',
dmxConfigCurrentDisplay->scrnY);
- XmuSnprintf(rtbuf, sizeof(dimbuf), "%dx%d%c%d%c%d",
+ snprintf(rtbuf, sizeof(dimbuf), "%dx%d%c%d%c%d",
dmxConfigCurrentDisplay->rootWidth,
dmxConfigCurrentDisplay->rootHeight,
dmxConfigCurrentDisplay->rootXSign < 0 ? '-' : '+',
dmxConfigCurrentDisplay->rootX,
dmxConfigCurrentDisplay->rootYSign < 0 ? '-' : '+',
dmxConfigCurrentDisplay->rootY);
- XmuSnprintf(offbuf, sizeof(offbuf), "@%dx%d",
+ snprintf(offbuf, sizeof(offbuf), "@%dx%d",
dmxConfigCurrentDisplay->rootXOrigin,
dmxConfigCurrentDisplay->rootYOrigin);
XtVaSetValues(namebox, XtNlabel, nambuf, XtNsensitive, True, NULL);
@@ -596,14 +595,14 @@ static void dmxConfigCanCallback(Widget w, XtPointer closure,
static void dmxConfigECCallback(Widget w, XtPointer closure,
XtPointer callData)
{
- char buf[256]; /* RATS: Only used in XmuSnprintf */
+ char buf[256]; /* RATS: Only used in snprintf */
if (!dmxConfigCurrent) return;
dmxConfigSetPopupPosition(ecpopup);
XtVaSetValues(ecdialog0, XtNvalue,
dmxConfigCurrent->name ? dmxConfigCurrent->name : "",
NULL);
- XmuSnprintf(buf, sizeof(buf), "%dx%d",
+ snprintf(buf, sizeof(buf), "%dx%d",
dmxConfigCurrent->width, dmxConfigCurrent->height);
XtVaSetValues(ecdialog1, XtNvalue, buf, NULL);
XtPopup(ecpopup, XtGrabExclusive);
@@ -692,7 +691,7 @@ static void dmxConfigECCanCallback(Widget w, XtPointer closure,
static void dmxConfigEDCallback(Widget w, XtPointer closure,
XtPointer callData)
{
- char buf[256]; /* RATS: Only used in XmuSnprintf */
+ char buf[256]; /* RATS: Only used in snprintf */
if (!dmxConfigCurrent || !dmxConfigCurrentDisplay) return;
dmxConfigSetPopupPosition(edpopup);
@@ -701,7 +700,7 @@ static void dmxConfigEDCallback(Widget w, XtPointer closure,
? dmxConfigCurrentDisplay->name
: "",
NULL);
- XmuSnprintf(buf, sizeof(buf), "%dx%d%c%d%c%d",
+ snprintf(buf, sizeof(buf), "%dx%d%c%d%c%d",
dmxConfigCurrentDisplay->scrnWidth,
dmxConfigCurrentDisplay->scrnHeight,
dmxConfigCurrentDisplay->scrnXSign < 0 ? '-' : '+',
@@ -709,7 +708,7 @@ static void dmxConfigEDCallback(Widget w, XtPointer closure,
dmxConfigCurrentDisplay->scrnYSign < 0 ? '-' : '+',
dmxConfigCurrentDisplay->scrnY);
XtVaSetValues(eddialog1, XtNvalue, buf, NULL);
- XmuSnprintf(buf, sizeof(buf), "@%dx%d",
+ snprintf(buf, sizeof(buf), "@%dx%d",
dmxConfigCurrentDisplay->rootXOrigin,
dmxConfigCurrentDisplay->rootYOrigin);
XtVaSetValues(eddialog2, XtNvalue, buf, NULL);
diff --git a/xorg-server/hw/dmx/dmx.c b/xorg-server/hw/dmx/dmx.c
index 5de565f85..01a744849 100644
--- a/xorg-server/hw/dmx/dmx.c
+++ b/xorg-server/hw/dmx/dmx.c
@@ -1,1097 +1,1068 @@
-/*
- * 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 <faith@redhat.com>
- *
- */
-
-/** \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 <dmx-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "extnsionst.h"
-#include "opaque.h"
-
-#include "dmxextension.h"
-#include <X11/extensions/dmxproto.h>
-#include <X11/extensions/dmx.h>
-#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 int _DMXXineramaActive(void)
-{
-#ifdef PANORAMIX
- return !noPanoramiXExtension;
-#endif
- return 0;
-}
-
-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 (Success != dixLookupResourceByType((pointer*) &win,
- stuff->window, XRT_WINDOW,
- client, 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 (Success != dixLookupResourceByType((pointer*) &win,
- window, XRT_WINDOW,
- client, 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;
- }
-}
-
-/** Initialize the extension. */
-void DMXExtensionInit(void)
-{
- ExtensionEntry *extEntry;
-
- if ((extEntry = AddExtension(DMX_EXTENSION_NAME, 0, 0,
- ProcDMXDispatch, SProcDMXDispatch,
- NULL, StandardMinorOpcode)))
- DMXCode = extEntry->base;
-}
+/*
+ * 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 <faith@redhat.com>
+ *
+ */
+
+/** \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 <dmx-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "opaque.h"
+
+#include "dmxextension.h"
+#include <X11/extensions/dmxproto.h>
+#include <X11/extensions/dmx.h>
+#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 int _DMXXineramaActive(void)
+{
+#ifdef PANORAMIX
+ return !noPanoramiXExtension;
+#endif
+ return 0;
+}
+
+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;
+
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.majorVersion);
+ swapl(&rep.minorVersion);
+ swapl(&rep.patchVersion);
+ }
+ WriteToClient(client, sizeof(xDMXQueryVersionReply), (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXSync(ClientPtr client)
+{
+ xDMXSyncReply rep;
+
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ }
+ WriteToClient(client, sizeof(xDMXSyncReply), (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXForceWindowCreation(ClientPtr client)
+{
+ xDMXForceWindowCreationReply rep;
+ REQUEST(xDMXForceWindowCreationReq);
+ WindowPtr pWin;
+
+ REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq);
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) {
+ PanoramiXRes *win;
+ int i;
+
+ if (Success != dixLookupResourceByType((pointer*) &win,
+ stuff->window, XRT_WINDOW,
+ client, 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);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ }
+ WriteToClient(client, sizeof(xDMXForceWindowCreationReply), (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXGetScreenCount(ClientPtr client)
+{
+ xDMXGetScreenCountReply rep;
+
+ REQUEST_SIZE_MATCH(xDMXGetScreenCountReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.screenCount = dmxGetNumScreens();
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.screenCount);
+ }
+ WriteToClient(client, sizeof(xDMXGetScreenCountReply), (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXGetScreenAttributes(ClientPtr client)
+{
+ REQUEST(xDMXGetScreenAttributesReq);
+ xDMXGetScreenAttributesReply rep;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.displayNameLength);
+ swapl(&rep.logicalScreen);
+ swaps(&rep.screenWindowWidth);
+ swaps(&rep.screenWindowHeight);
+ swaps(&rep.screenWindowXoffset);
+ swaps(&rep.screenWindowYoffset);
+ swaps(&rep.rootWindowWidth);
+ swaps(&rep.rootWindowHeight);
+ swaps(&rep.rootWindowXoffset);
+ swaps(&rep.rootWindowYoffset);
+ swaps(&rep.rootWindowXorigin);
+ swaps(&rep.rootWindowYorigin);
+ }
+ 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 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);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ swapl(&rep.errorScreen);
+ }
+ WriteToClient(client,
+ sizeof(xDMXChangeScreensAttributesReply),
+ (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXAddScreen(ClientPtr client)
+{
+ REQUEST(xDMXAddScreenReq);
+ xDMXAddScreenReply rep;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ swapl(&rep.physicalScreen);
+ }
+ WriteToClient(client,
+ sizeof(xDMXAddScreenReply),
+ (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXRemoveScreen(ClientPtr client)
+{
+ REQUEST(xDMXRemoveScreenReq);
+ xDMXRemoveScreenReply rep;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ }
+ 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 (Success != dixLookupResourceByType((pointer*) &win,
+ window, XRT_WINDOW,
+ client, 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;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.screenCount);
+ for (i = 0; i < count; i++) {
+ swapl(&screens[i]);
+ swapl(&windows[i]);
+
+ swaps(&pos[i].x);
+ swaps(&pos[i].y);
+ swaps(&pos[i].width);
+ swaps(&pos[i].height);
+
+ swaps(&vis[i].x);
+ swaps(&vis[i].y);
+ swaps(&vis[i].width);
+ swaps(&vis[i].height);
+ }
+ }
+
+ 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;
+ 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);
+ swapl(&rep.length);
+ swaps(&rep.width);
+ swaps(&rep.height);
+ swaps(&rep.shiftX);
+ swaps(&rep.shiftY);
+ }
+ WriteToClient(client, sizeof(xDMXGetDesktopAttributesReply), (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXChangeDesktopAttributes(ClientPtr client)
+{
+ REQUEST(xDMXChangeDesktopAttributesReq);
+ xDMXChangeDesktopAttributesReply rep;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ }
+ WriteToClient(client,
+ sizeof(xDMXChangeDesktopAttributesReply),
+ (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXGetInputCount(ClientPtr client)
+{
+ xDMXGetInputCountReply rep;
+
+ REQUEST_SIZE_MATCH(xDMXGetInputCountReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.inputCount = dmxGetInputCount();
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.inputCount);
+ }
+ WriteToClient(client, sizeof(xDMXGetInputCountReply), (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXGetInputAttributes(ClientPtr client)
+{
+ REQUEST(xDMXGetInputAttributesReq);
+ xDMXGetInputAttributesReply rep;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.inputType);
+ swapl(&rep.physicalScreen);
+ swapl(&rep.physicalId);
+ swapl(&rep.nameLength);
+ }
+ 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 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);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ swapl(&rep.physicalId);
+ }
+ WriteToClient(client, sizeof(xDMXAddInputReply), (char *)&rep);
+ return Success;
+}
+
+static int ProcDMXRemoveInput(ClientPtr client)
+{
+ REQUEST(xDMXRemoveInputReq);
+ xDMXRemoveInputReply rep;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ }
+ 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)
+{
+ REQUEST(xDMXQueryVersionReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXQueryVersionReq);
+ return ProcDMXQueryVersion(client);
+}
+
+static int SProcDMXSync(ClientPtr client)
+{
+ REQUEST(xDMXSyncReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXSyncReq);
+ return ProcDMXSync(client);
+}
+
+static int SProcDMXForceWindowCreation(ClientPtr client)
+{
+ REQUEST(xDMXForceWindowCreationReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXForceWindowCreationReq);
+ swapl(&stuff->window);
+ return ProcDMXForceWindowCreation(client);
+}
+
+static int SProcDMXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xDMXGetScreenCountReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXGetScreenCountReq);
+ return ProcDMXGetScreenCount(client);
+}
+
+static int SProcDMXGetScreenAttributes(ClientPtr client)
+{
+ REQUEST(xDMXGetScreenAttributesReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq);
+ swapl(&stuff->physicalScreen);
+ return ProcDMXGetScreenAttributes(client);
+}
+
+static int SProcDMXChangeScreensAttributes(ClientPtr client)
+{
+ REQUEST(xDMXChangeScreensAttributesReq);
+
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xDMXGetScreenAttributesReq);
+ swapl(&stuff->screenCount);
+ swapl(&stuff->maskCount);
+ SwapRestL(stuff);
+ return ProcDMXGetScreenAttributes(client);
+}
+
+static int SProcDMXAddScreen(ClientPtr client)
+{
+ int paddedLength;
+ REQUEST(xDMXAddScreenReq);
+
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xDMXAddScreenReq);
+ swapl(&stuff->displayNameLength);
+ swapl(&stuff->valueMask);
+ paddedLength = pad_to_int32(stuff->displayNameLength);
+ SwapLongs((CARD32 *)(stuff+1), LengthRestL(stuff) - paddedLength/4);
+ return ProcDMXAddScreen(client);
+}
+
+static int SProcDMXRemoveScreen(ClientPtr client)
+{
+ REQUEST(xDMXRemoveScreenReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXRemoveScreenReq);
+ swapl(&stuff->physicalScreen);
+ return ProcDMXRemoveScreen(client);
+}
+
+static int SProcDMXGetWindowAttributes(ClientPtr client)
+{
+ REQUEST(xDMXGetWindowAttributesReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXGetWindowAttributesReq);
+ swapl(&stuff->window);
+ return ProcDMXGetWindowAttributes(client);
+}
+
+static int SProcDMXGetDesktopAttributes(ClientPtr client)
+{
+ REQUEST(xDMXGetDesktopAttributesReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXGetDesktopAttributesReq);
+ return ProcDMXGetDesktopAttributes(client);
+}
+
+static int SProcDMXChangeDesktopAttributes(ClientPtr client)
+{
+ REQUEST(xDMXChangeDesktopAttributesReq);
+
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xDMXChangeDesktopAttributesReq);
+ swapl(&stuff->valueMask);
+ SwapRestL(stuff);
+ return ProcDMXChangeDesktopAttributes(client);
+}
+
+static int SProcDMXGetInputCount(ClientPtr client)
+{
+ REQUEST(xDMXGetInputCountReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXGetInputCountReq);
+ return ProcDMXGetInputCount(client);
+}
+
+static int SProcDMXGetInputAttributes(ClientPtr client)
+{
+ REQUEST(xDMXGetInputAttributesReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXGetInputAttributesReq);
+ swapl(&stuff->deviceId);
+ return ProcDMXGetInputAttributes(client);
+}
+
+static int SProcDMXAddInput(ClientPtr client)
+{
+ int paddedLength;
+ REQUEST(xDMXAddInputReq);
+
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xDMXAddInputReq);
+ swapl(&stuff->displayNameLength);
+ swapl(&stuff->valueMask);
+ paddedLength = pad_to_int32(stuff->displayNameLength);
+ SwapLongs((CARD32 *)(stuff+1), LengthRestL(stuff) - paddedLength/4);
+ return ProcDMXAddInput(client);
+}
+
+static int SProcDMXRemoveInput(ClientPtr client)
+{
+ REQUEST(xDMXRemoveInputReq);
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xDMXRemoveInputReq);
+ swapl(&stuff->physicalId);
+ 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;
+ }
+}
+
+/** Initialize the extension. */
+void DMXExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ if ((extEntry = AddExtension(DMX_EXTENSION_NAME, 0, 0,
+ ProcDMXDispatch, SProcDMXDispatch,
+ NULL, StandardMinorOpcode)))
+ DMXCode = extEntry->base;
+}
diff --git a/xorg-server/hw/dmx/dmxclient.h b/xorg-server/hw/dmx/dmxclient.h
index c45f71fc0..f0f235f61 100644
--- a/xorg-server/hw/dmx/dmxclient.h
+++ b/xorg-server/hw/dmx/dmxclient.h
@@ -82,7 +82,6 @@ typedef XID KeySym64;
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
-#include <X11/Xmu/SysUtil.h> /* For XmuSnprintf */
#include <X11/extensions/shape.h>
diff --git a/xorg-server/hw/dmx/dmxcursor.h b/xorg-server/hw/dmx/dmxcursor.h
index 5242268c1..fc2e118e0 100644
--- a/xorg-server/hw/dmx/dmxcursor.h
+++ b/xorg-server/hw/dmx/dmxcursor.h
@@ -64,9 +64,9 @@ extern void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor);
extern Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor);
#define DMX_GET_CURSOR_PRIV(_pCursor, _pScreen) ((dmxCursorPrivPtr) \
- dixLookupPrivate(&(_pCursor)->devPrivates, CursorScreenKey(_pScreen)))
+ dixLookupScreenPrivate(&(_pCursor)->devPrivates, CursorScreenKey, _pScreen))
#define DMX_SET_CURSOR_PRIV(_pCursor, _pScreen, v) \
- dixSetPrivate(&(_pCursor)->devPrivates, CursorScreenKey(_pScreen), v)
+ dixSetScreenPrivate(&(_pCursor)->devPrivates, CursorScreenKey, _pScreen, v)
#endif /* DMXCURSOR_H */
diff --git a/xorg-server/hw/dmx/dmxextension.c b/xorg-server/hw/dmx/dmxextension.c
index db5709ee6..80d11ee89 100644
--- a/xorg-server/hw/dmx/dmxextension.c
+++ b/xorg-server/hw/dmx/dmxextension.c
@@ -455,7 +455,7 @@ static void dmxSetRootWindowOrigin(int idx, int x, int y)
pScreen->y = dmxScreen->rootYOrigin;
/* Recalculate the Xinerama regions and data structs */
- XineramaReinitData(pScreen);
+ XineramaReinitData();
/* Adjust each of the root window's children */
if (!idx) ReinitializeRootWindow(screenInfo.screens[0]->root, xoff, yoff);
diff --git a/xorg-server/hw/dmx/dmxinit.c b/xorg-server/hw/dmx/dmxinit.c
index bc1509b35..165476c5f 100644
--- a/xorg-server/hw/dmx/dmxinit.c
+++ b/xorg-server/hw/dmx/dmxinit.c
@@ -56,6 +56,7 @@
#include "dmxpict.h"
#include <X11/Xos.h> /* For gettimeofday */
+#include <X11/Xmu/SysUtil.h> /* For XmuGetHostname */
#include "dixstruct.h"
#ifdef PANORAMIX
#include "panoramiXsrv.h"
@@ -131,7 +132,7 @@ static int dmxErrorHandler(Display *dpy, XErrorEvent *ev)
/* Find major opcode name */
if (ev->request_code < 128) {
- XmuSnprintf(request, sizeof(request), "%d", ev->request_code);
+ snprintf(request, sizeof(request), "%d", ev->request_code);
XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf));
} else {
for (ext = dpy->ext_procs;
@@ -145,8 +146,8 @@ static int dmxErrorHandler(Display *dpy, XErrorEvent *ev)
/* Find minor opcode name */
if (ev->request_code >= 128 && ext) {
- XmuSnprintf(request, sizeof(request), "%d", ev->request_code);
- XmuSnprintf(request, sizeof(request), "%s.%d",
+ snprintf(request, sizeof(request), "%d", ev->request_code);
+ snprintf(request, sizeof(request), "%s.%d",
ext->name, ev->minor_code);
XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf));
dmxLog(dmxWarning, " Minor opcode: %d (%s)\n",
@@ -515,7 +516,7 @@ static const char *dmxExecOS(void)
if (!initialized++) {
memset(buffer, 0, sizeof(buffer));
uname(&u);
- XmuSnprintf(buffer, sizeof(buffer)-1, "%s %s %s",
+ snprintf(buffer, sizeof(buffer)-1, "%s %s %s",
u.sysname, u.release, u.version);
}
return buffer;
@@ -530,7 +531,7 @@ static const char *dmxBuildCompiler(void)
if (!initialized++) {
memset(buffer, 0, sizeof(buffer));
#if defined(__GNUC__) && defined(__GNUC_MINOR__) &&defined(__GNUC_PATCHLEVEL__)
- XmuSnprintf(buffer, sizeof(buffer)-1, "gcc %d.%d.%d",
+ snprintf(buffer, sizeof(buffer)-1, "gcc %d.%d.%d",
__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#endif
}
diff --git a/xorg-server/hw/dmx/dmxprop.c b/xorg-server/hw/dmx/dmxprop.c
index 95efcb0e0..b4695dd5d 100644
--- a/xorg-server/hw/dmx/dmxprop.c
+++ b/xorg-server/hw/dmx/dmxprop.c
@@ -1,347 +1,348 @@
-/*
- * 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
- *
- * 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 <dmx-config.h>
-#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:<hostname running DMX>:<display name of DMX>,<screen number>"
- */
-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 <faith@redhat.com>
+ *
+ */
+
+/** \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 <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxprop.h"
+#include "dmxlog.h"
+#include <X11/Xmu/SysUtil.h> /* For XmuGetHostname */
+
+/** 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));
+ snprintf(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:<hostname running DMX>:<display name of DMX>,<screen number>"
+ */
+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 snprintf */
+
+ 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);
+ }
+
+ snprintf(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));
+
+ snprintf(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/doc/dmx.xml b/xorg-server/hw/dmx/doc/dmx.xml
index c998485bc..ce472c2bf 100644
--- a/xorg-server/hw/dmx/doc/dmx.xml
+++ b/xorg-server/hw/dmx/doc/dmx.xml
@@ -1,3430 +1,3430 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
- "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
-]>
-
-<article>
-
- <articleinfo>
- <!-- Title information -->
- <title>Distributed Multihead X design</title>
- <authorgroup>
- <author><firstname>Kevin E.</firstname><surname>Martin</surname></author>
- <author><firstname>David H.</firstname><surname>Dawes</surname></author>
- <author><firstname>Rickard E.</firstname><surname>Faith</surname></author>
- </authorgroup>
- <pubdate>29 June 2004 (created 25 July 2001)</pubdate>
- <abstract><para>
- 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. <emphasis remap="it">Copyright 2001 by VA
- Linux Systems, Inc., Fremont, California. Copyright 2001-2004
- by Red Hat, Inc., Raleigh, North Carolina</emphasis>
- </para></abstract>
- </articleinfo>
-
-<!-- Begin the document -->
-<sect1>
-<title>Introduction</title>
-
-<sect2>
-<title>The Distributed Multihead X Server</title>
-
-<para>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.
-</para>
-
-<para>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.).
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-</sect2>
-
-<sect2>
-<title>Layout of Paper</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-</sect2>
-</sect1>
-
-<!-- ============================================================ -->
-<sect1>
-<title>Development plan</title>
-
-<para>This section describes the development plan from approximately June
-2001 through July 2003.
-</para>
-
-<sect2>
-<title>Bootstrap code</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>Status: The boot strap code is complete. <!-- August 2001 -->
-</para>
-
-</sect2>
-
-<sect2>
-<title>Input device handling</title>
-
-<para>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'',
-</para>
-
-<para>There are some options as to how the front-end X server gets its core
-input devices:
-
-<orderedlist>
-<listitem>
- <para>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.
-</para>
-
- <para>The following options are available for implementing local input
- devices:
-
-<orderedlist>
-<listitem>
- <para>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.
-</para>
-</listitem>
-
-<listitem>
- <para>The <command>kdrive</command> 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
- <command>gpm</command> 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 <command>kdrive</command> drivers were not used for the DMX
- implementation.
-</para>
-</listitem>
-
-<listitem>
- <para>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.
-</para>
-</listitem>
-</orderedlist>
-</para>
-</listitem>
-
-<listitem>
- <para>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.
-</para>
-</listitem>
-
-<listitem>
- <para>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.
-</para>
-</listitem>
-
-<listitem>
- <para>Other options were initially explored, but they were all
- partial subsets of the options listed above and, hence, are
- irrelevant.
-</para>
-</listitem>
-
-</orderedlist>
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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):
-<orderedlist>
-<listitem>
- <para> A "dummy" device drive that never generates events.
-</para>
-</listitem>
-
-<listitem>
- <para> "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):
- <itemizedlist>
- <listitem><para>Linux keyboard</para></listitem>
- <listitem><para>Linux serial mouse (MS)</para></listitem>
- <listitem><para>Linux PS/2 mouse</para></listitem>
- <listitem><para>USB keyboard</para></listitem>
- <listitem><para>USB mouse</para></listitem>
- <listitem><para>USB generic device (e.g., joystick, gamepad, etc.)</para></listitem>
- </itemizedlist>
-</para>
-</listitem>
-
-<listitem>
- <para> "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.
-</para>
-</listitem>
-
-<listitem>
- <para> "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.
-</para>
-</listitem>
-</orderedlist>
-
-</para>
-
-</sect2>
-
-<!-- May 2002; July 2003 -->
-
-<sect2>
-<title>Output device handling</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<sect3>
-<title>Initialization</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>Handling rendering requests</title>
-
-<para>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:
-
-<orderedlist>
-<listitem>
- <para>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.
-</para>
-
- <para>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.
-</para>
-
- <para>The initial DMX implementation used a shadow framebuffer by
- default.
-</para>
-</listitem>
-
-<listitem>
- <para>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.
-</para>
-
- <para>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.
-</para>
-
- <para>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).
-</para>
-</listitem>
-
-</orderedlist>
-</para>
-
-<para>Status: Both the shadow framebuffer and Xnest-style code is complete.
-<!-- May 2002 -->
-</para>
-
-</sect3>
-</sect2>
-
-<sect2>
-<title>Optimizing DMX</title>
-
-<para>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.
-</para>
-
-<para>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).
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>Other potential optimizations will be determined from the performance
-analysis.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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 -->
-</para>
-
-</sect2>
-
-<sect2>
-<title>DMX X extension support</title>
-
-<para>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.
-</para>
-
-<para>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:
-<orderedlist>
-<listitem><para>
- Screen information (clipping rectangle for each screen relative
- to the virtual screen)
-</para></listitem>
-<listitem><para>
- Window information (window IDs and clipping information for each
- back-end window that corresponds to each DMX window)
-</para></listitem>
-<listitem><para>
- Input device information (mappings from DMX device IDs to
- back-end device IDs)
-</para></listitem>
-<listitem><para>
- Force window creation (so that a client can override the
- server-side lazy window creation optimization)
-</para></listitem>
-<listitem><para>
- Reconfiguration (so that a client can request that a screen
- position be changed)
-</para></listitem>
-<listitem><para>
- Addition and removal of back-end servers and back-end and
- console inputs.
-</para></listitem>
-</orderedlist>
-</para>
-<!-- September 2002; July 2003 -->
-
-</sect2>
-
-<sect2>
-<title>Common X extension support</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>Support for the XTest extension was added during the first
-development phase.
-</para>
-
-<!-- WARNING: this list is duplicated in the Phase IV discussion -->
-<para>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 -->
-</para>
-</sect2>
-
-<sect2>
-<title>OpenGL support</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<orderedlist>
-<listitem>
- <para>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.
-</para></listitem>
-
-<listitem>
- <para>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.
-</para></listitem>
-</orderedlist>
-
-<para>These, and other, options will be investigated in this phase of the
-work.
-</para>
-
-<para>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.
-</para>
-
-<para>Status: OpenGL support by the glxProxy extension was implemented by
-SGI and has been integrated into the DMX code base.
-</para>
-<!-- May 2003-->
-</sect2>
-
-</sect1>
-
-<!-- ============================================================ -->
-<sect1>
-<title>Current issues</title>
-
-<para>In this sections the current issues are outlined that require further
-investigation.
-</para>
-
-<sect2>
-<title>Fonts</title>
-
-<para>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.
-</para>
-</sect2>
-
-<sect2>
-<title>Zero width rendering primitives</title>
-
-<para>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.
-</para>
-</sect2>
-
-<sect2>
-<title>Output scaling</title>
-
-<para>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.
-</para>
-</sect2>
-
-<sect2>
-<title>Per-screen colormaps</title>
-
-<para>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.
-</para>
-</sect2>
-</sect1>
-
-<!-- ============================================================ -->
-<appendix>
-<title>Appendix</title>
-
-<sect1>
-<title>Background</title>
-
-<para>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.
-</para>
-
-<sect2>
-<title>Core input device handling</title>
-
-<para>The following is a description of how core input devices are handled
-by an X server.
-</para>
-
-<sect3>
-<title>InitInput()</title>
-
-<para>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().
-</para>
-
-<para>InitInput() usually has implementation specific code to determine
-which input devices are available. For each input device it will be
-using, it calls AddInputDevice():
-
-<variablelist>
-<varlistentry>
-<term>AddInputDevice()</term>
-<listitem><para>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.
-</para></listitem>
-</varlistentry>
-</variablelist>
-</para>
-
-<para>Once input handles for core keyboard and core pointer devices have
-been obtained from AddInputDevice(). 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).
-</para>
-
-<para>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.
-</para>
-
-<para><variablelist>
-
-<varlistentry>
-<term>miRegisterPointerDevice()</term>
-<listitem><para>This MI function registers the core
-pointer's input handle with with the miPointer code.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>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():
-
-<variablelist>
-<varlistentry>
-<term>mieqInit()</term>
-<listitem><para>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.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>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.)
-</para>
-</sect3>
-
-<sect3>
-<title>InitAndStartDevices()</title>
-
-<para>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.
-</para>
-
-<para>Each registered device is initialized by calling its callback
-(dev-&gt;deviceProc) with the DEVICE_INIT argument:
-
-<variablelist>
-<varlistentry>
-<term>(*dev-&gt;deviceProc)(dev, DEVICE_INIT)</term>
-<listitem>
-<para>This function initializes the
-device structs with core information relevant to the device.
-</para>
-
-<para>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.
-</para>
-
-<para>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).
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>Each initialized device is enabled by calling EnableDevice():
-
-<variablelist>
-<varlistentry>
-<term>EnableDevice()</term>
-<listitem>
-<para>EnableDevice() calls the device callback with
-DEVICE_ON:
- <variablelist>
- <varlistentry>
- <term>(*dev-&gt;deviceProc)(dev, DEVICE_ON)</term>
- <listitem>
- <para>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.
- </para></listitem></varlistentry>
- </variablelist>
- </para>
-
- <para>EnableDevice() then adds the device handle to the X server's
- global list of enabled devices.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>InitAndStartDevices() then verifies that a valid core keyboard and
-pointer has been initialized and enabled. It returns failure if either
-are missing.
-</para>
-</sect3>
-
-<sect3>
-<title>devReadInput()</title>
-
-<para>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).
-</para>
-
-<para>Events are queued by calling mieqEnqueue():
-
-<variablelist>
-<varlistentry>
-<term>mieqEnqueue()</term>
-<listitem>
-<para>This MI function is used to add input events to the
-event queue. It is simply passed the event to be queued.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>The cursor position should be updated when motion events are
-enqueued, by calling either miPointerAbsoluteCursor() or
-miPointerDeltaCursor():
-
-<variablelist>
-<varlistentry>
-<term>miPointerAbsoluteCursor()</term>
-<listitem>
-<para>This MI function is used to move the
-cursor to the absolute coordinates provided.
-</para></listitem></varlistentry>
-<varlistentry>
-<term>miPointerDeltaCursor()</term>
-<listitem>
-<para>This MI function is used to move the cursor
-relative to its current position.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-</sect3>
-
-<sect3>
-<title>ProcessInputEvents()</title>
-
-<para>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.
-</para>
-
-<para>Enqueued events are processed by mieqProcessInputEvents() and passed
-to the DIX layer for transmission to clients:
-
-<variablelist>
-<varlistentry>
-<term>mieqProcessInputEvents()</term>
-<listitem>
-<para>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.
-</para></listitem></varlistentry>
-<varlistentry>
-<term>miPointerUpdate()</term>
-<listitem>
-<para>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.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-</sect3>
-
-<sect3>
-<title>DisableDevice()</title>
-
-<para>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.
-</para>
-
-<para>DisableDevice() calls the device's callback function with
-<constant>DEVICE_OFF</constant>:
-
-<variablelist>
-<varlistentry>
-<term>(*dev-&gt;deviceProc)(dev, DEVICE_OFF)</term>
-<listitem>
-<para>This typically closes the
-relevant physical device, and when appropriate, unregisters the device's
-file descriptor (or equivalent) as a valid input source.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>DisableDevice() then removes the device handle from the X server's
-global list of enabled devices.
-</para>
-
-</sect3>
-
-<sect3>
-<title>CloseDevice()</title>
-
-<para>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.
-</para>
-
-<para>CloseDevice() calls the device's callback function with
-<constant>DEVICE_CLOSE</constant>:
-
-<variablelist>
-<varlistentry>
-<term>(*dev-&gt;deviceProc)(dev, DEVICE_CLOSE)</term>
-<listitem>
-<para>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.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>CloseDevice() then frees the data structures that were allocated
-for the device when it was registered/initialized.
-</para>
-
-</sect3>
-
-<sect3>
-<title>LegalModifier()</title>
-<!-- dmx/dmxinput.c - currently returns TRUE -->
-<para>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.
-</para>
-
-</sect3>
-</sect2>
-
-<sect2>
-<title>Output handling</title>
-
-<para>The following sections describe the main functions required to
-initialize, use and close the output device(s) for each screen in the X
-server.
-</para>
-
-<sect3>
-<title>InitOutput()</title>
-
-<para>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.
-</para>
-
-<para>The primary tasks for this function are outlined below:
-
-<orderedlist>
-<listitem>
- <para><emphasis remap="bf">Parse configuration info:</emphasis> 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.
-</para>
-</listitem>
-
-<listitem>
- <para><emphasis remap="bf">Initialize screen info:</emphasis> 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&lsqb;&rsqb; structure.
-</para>
-</listitem>
-
-<listitem>
- <para><emphasis remap="bf">Set pixmap formats:</emphasis> 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.
-</para>
-</listitem>
-
-<listitem>
- <para><emphasis remap="bf">Unify screen info:</emphasis> 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.
-</para>
-</listitem>
-</orderedlist>
-</para>
-
-<para>Once these tasks are complete, the valid screens are known and each
-of these screens can be initialized by calling AddScreen().
-</para>
-</sect3>
-
-<sect3>
-<title>AddScreen()</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>ScreenInit()</title>
-
-<para>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).
-</para>
-
-<para>The screen init function usually calls several functions to perform
-certain screen initialization functions. They are described below:
-
-<variablelist>
-<varlistentry>
-<term>{mi,*fb}ScreenInit()</term>
-<listitem>
-<para>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.
-</para>
-
-<para>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().
-</para></listitem></varlistentry>
-
-<varlistentry>
-<term>miInitializeBackingStore()</term>
-<listitem>
-<para>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.
-</para></listitem></varlistentry>
-
-<varlistentry>
-<term>miDCInitialize()</term>
-<listitem>
-<para>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.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>CloseScreen()</title>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>GC operations</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>Note that some pointers to functions that draw to the screen are
-stored in the Screen structure. They include GetImage(), GetSpans(),
-CopyWindow() and RestoreAreas().
-</para>
-</sect3>
-
-<sect3>
-<title>Xnest</title>
-
-<para>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.
-</para>
-
-<para>The Xnest server implements all of the standard input and output
-initialization steps outlined above.
-</para>
-
-<para><variablelist>
-<varlistentry>
-<term>InitOutput()</term>
-<listitem>
-<para>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.
-</para>
-
-<para>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.
-</para></listitem></varlistentry>
-
-<varlistentry>
-<term>ScreenInit()</term>
-<listitem>
-<para>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.
-</para></listitem></varlistentry>
-
-<varlistentry>
-<term>CloseScreen()</term>
-<listitem>
-<para>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.
-</para></listitem></varlistentry>
-
-<varlistentry>
-<term>GC operations</term>
-<listitem>
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>Shadow framebuffer</title>
-
-<para>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.
-</para>
-
-<para>There are two main entry points to the shadow framebuffer code:
-
-<variablelist>
-<varlistentry>
-<term>shadowAlloc(width, height, bpp)</term>
-<listitem>
-<para>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.
-</para></listitem></varlistentry>
-
-<varlistentry>
-<term>shadowInit(pScreen, updateProc, windowProc)</term>
-<listitem>
-<para>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).
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-</sect3>
-</sect2>
-
-<sect2>
-<title>Xinerama</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>The following is a code-level description of how Xinerama functions.
-</para>
-
-<para>Note: Because the Xinerama extension was originally called the
-PanoramiX extension, many of the Xinerama functions still have the
-PanoramiX prefix.
-</para>
-
-<variablelist>
-<varlistentry>
-<term>PanoramiXExtensionInit()</term>
-<listitem>
- <para>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.
- </para>
-
- <para>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.
- </para>
-
- <para>The Xinerama extension is registered by calling AddExtension().
- </para>
-
- <para>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.
- </para>
-
- <para>A region (PanoramiXScreenRegion) is
- initialized to be the union of the screen regions.
- The relative positioning information for the
- physical screens is taken from the ScreenRec x and y members, which
- the DDX layer must initialize in InitOutput(). The bounds of the
- combined screen is also calculated (PanoramiXPixWidth and
- PanoramiXPixHeight).
- </para>
-
- <para>The DIX layer has a list of function pointers
- (ProcVector&lsqb;&rsqb;) 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&lsqb;&rsqb;. 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.
- </para>
-</listitem></varlistentry>
-
-<varlistentry>
-<term>PanoramiXConsolidate()</term>
-<listitem>
- <para>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.
-</para>
-
- <para>This function finds the set of depths (PanoramiXDepths&lsqb;&rsqb;) and
- visuals (PanoramiXVisuals&lsqb;&rsqb;)
- 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.
- </para>
-</listitem></varlistentry>
-
-<varlistentry>
-<term>PanoramiXCreateConnectionBlock()</term>
-<listitem>
- <para>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.
- </para>
-
- <para>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 <command>xdpyinfo</command> shows). The
- connection block is initialized with the combined single screen
- values that were calculated in the above two functions.
- </para>
-
- <para>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().
- </para>
-</listitem></varlistentry>
-</variablelist>
-
-<sect3>
-<title>Xinerama-specific changes to the DIX code</title>
-
-<para>There are a few types of Xinerama-specific changes within the DIX
-code. The main ones are described here.
-</para>
-
-<para>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 &gt; 0. This is because they are handled for
-the single Xinerama screen and the processing is done once for screen 0.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>Xinerama-specific changes to the MI code</title>
-
-<para>The only Xinerama-specific change to the MI code is in miSendExposures()
-to handle the coordinate (and window ID) translation for expose events.
-</para>
-</sect3>
-
-<sect3>
-<title>Intercepted DIX core requests</title>
-
-<para>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.
-</para>
-
-</sect3>
-
-</sect2>
-
-</sect1>
-
-<!-- ============================================================ -->
-
-<sect1>
-<title>Development Results</title>
-
-<para>In this section the results of each phase of development are
-discussed. This development took place between approximately June 2001
-and July 2003.
-</para>
-
-<sect2>
-<title>Phase I</title>
-
-<para>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.
-</para>
-
-<sect3>
-<title>Scope</title>
-
-<para>The goal of Phase I is to provide fundamental functionality that can
-act as a foundation for ongoing work:
-<orderedlist>
-<listitem>
- <para>Develop the proxy X server
- <itemizedlist>
- <listitem>
- <para>The proxy X server will operate on the X11 protocol and
- relay requests as necessary to correctly perform the request.
- </para></listitem>
- <listitem>
- <para>Work will be based on the existing work for Xinerama and
- Xnest.
- </para></listitem>
- <listitem>
- <para>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.
- </para></listitem>
- <listitem>
- <para>The multiple screen layout (including support for
- overlapping screens) will be user configurable via a
- configuration file or through the configuration tool.
- </para></listitem>
- </itemizedlist>
- </para></listitem>
- <listitem>
- <para>Develop graphical configuration tool
- <itemizedlist>
- <listitem>
- <para>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.
- </para></listitem>
- </itemizedlist>
- </para></listitem>
- <listitem>
- <para>Pass the X Test Suite
- <itemizedlist>
- <listitem>
- <para>The X Test Suite covers the basic X11 operations. All
- tests known to succeed must correctly operate in the distributed
- X environment.
- </para></listitem>
- </itemizedlist>
- </para></listitem>
-</orderedlist>
-
-</para>
-
-<para>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).
-</para>
-</sect3>
-
-<sect3>
-<title>Results</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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 <emphasis remap="bf">-configfile</emphasis> and <emphasis remap="bf">-config</emphasis>
-command-line options can be used to start Xdmx using a configuration
-file.
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>X Test Suite</title>
-
- <sect4>
- <title>Introduction</title>
- <para>
- 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.
- </para>
- <para>
- 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.
- </para>
- </sect4>
-
- <sect4>
- <title>Expected Failures for a Single Head</title>
- <para>
- 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:
- <literallayout>
-XDrawArc: Tests 42, 63, 66, 73
-XDrawArcs: Tests 45, 66, 69, 76
- </literallayout>
- </para>
- <para>
- The following failures occur because of the high-level X
- server implementation:
- <literallayout>
-XLoadQueryFont: Test 1
-XListFontsWithInfo: Tests 3, 4
-XQueryFont: Tests 1, 2
- </literallayout>
- </para>
- <para>
- The following test fails when running the X server as root
- under Linux because of the way directory modes are
- interpreted:
- <literallayout>
-XWriteBitmapFile: Test 3
- </literallayout>
- </para>
- <para>
- 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.
- </para>
- </sect4>
-
- <sect4>
- <title>Expected Failures for Xinerama</title>
- <para>
- 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.
- </para>
-
- <para>
- 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.
- </para>
-
- <para>
- 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:
- </para>
-
- <para>
- These failures were noted with multiple Xinerama
- configurations:
- <literallayout>
-XCopyPlane: Tests 13, 22, 31 (well-known Xinerama implementation issue)
-XSetFontPath: Test 4
-XGetDefault: Test 5
-XMatchVisualInfo: Test 1
- </literallayout>
- </para>
- <para>
- These failures were noted only when using one dual-head
- video card with a 4.2.99.x XFree86 server:
- <literallayout>
-XListPixmapFormats: Test 1
-XDrawRectangles: Test 45
- </literallayout>
- </para>
- <para>
- These failures were noted only when using two video cards
- from different vendors with a 4.1.99.x XFree86 server:
- <literallayout>
-XChangeWindowAttributes: Test 32
-XCreateWindow: Test 30
-XDrawLine: Test 22
-XFillArc: Test 22
-XChangeKeyboardControl: Tests 9, 10
-XRebindKeysym: Test 1
- </literallayout>
- </para>
- </sect4>
-
- <sect4>
- <title>Additional Failures from Xdmx</title>
-
- <para>
- 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:
- <literallayout>
-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)
- </literallayout>
- </para>
- <para>
- 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.
- </para>
- </sect4>
-
- <sect4>
- <title>Summary and Future Work</title>
-
- <para>
- 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.
- </para>
-
- <para>
- 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.
- </para>
- </sect4>
-</sect3>
-
-<sect3>
-<title>Fonts</title>
-
-<para>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
-<emphasis remap="bf">the front- and back-end servers must share the exact same font
-path</emphasis>. There are two ways to help make sure that all servers share the
-same font path:
-
-<orderedlist>
- <listitem>
- <para>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.
- </para></listitem>
-
- <listitem>
- <para>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.
- </para></listitem>
-</orderedlist>
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>Performance</title>
-
-<para>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.
-</para>
-
-<orderedlist>
- <listitem>
- <para>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.
- </para></listitem>
-
- <listitem>
- <para>Sending drawing requests to only the screens that they overlap
- should improve performance.
- </para></listitem>
-</orderedlist>
-</sect3>
-
-<sect3>
-<title>Pixmaps</title>
-
-<para>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.
-</para>
-
-</sect3>
-
-</sect2>
-
-<!-- ============================================================ -->
-<sect2>
-<title>Phase II</title>
-
-<para>The second phase of development concentrates on performance
-optimizations. These optimizations are documented here, with
-<command>x11perf</command> data to show how the optimizations improve performance.
-</para>
-
-<para>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.
-</para>
-
-<sect3>
-<title>Moving from XFree86 4.1.99.1 to 4.2.0.0</title>
-
-<para>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:
-<screen>
-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)
-</screen>
-And the following tests were noted to be more than 10% slower:
-<screen>
-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)
-</screen>
-</para>
-
-<para>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 <command>x11perf</command> tests.
-</para>
-</sect3>
-
-<sect3>
-<title>Global changes</title>
-
-<para>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:
-<screen>
-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)
-</screen>
-</para>
-
-<para>The following tests were noted to be more than 10% slower:
-<screen>
-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)
-</screen>
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>XSync() Batching</title>
-
-<para>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.
-</para>
-
-<para>Out of more than 300 <command>x11perf</command> 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.
-</para>
-
-<para>The following tests were noted to be more than 10% slower with
-XSync() batching on:
-<screen>
-0.88 500x500 tiled rectangle (161x145 tile)
-0.89 Copy 500x500 from window to window
-</screen>
-</para>
-</sect3>
-
-<sect3>
-<title>Offscreen Optimization</title>
-
-<para>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.
-</para>
-
-<para>Out of more than 300 <command>x11perf</command> 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:
-<screen>
-0.88 Hide/expose window via popup (4 kids)
-0.89 Resize unmapped window (75 kids)
-</screen>
-</para>
-</sect3>
-
-<sect3>
-<title>Lazy Window Creation Optimization</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>This optimization improved the following <command>x11perf</command> tests by more
-than 10%:
-<screen>
-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)
-</screen>
-</para>
-</sect3>
-
-<sect3>
-<title>Subdividing Rendering Primitives</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>This optimization improved the following <command>x11perf</command> tests by more
-than 10%:
-<screen>
-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)
-</screen>
-</para>
-
-<para>The following test was noted to be more than 10% slower with this
-optimization:
-<screen>
-0.88 10-pixel fill chord partial circle
-</screen>
-</para>
-</sect3>
-
-<sect3>
-<title>Summary of x11perf Data</title>
-
-<para>With all of the optimizations on, 53 <command>x11perf</command> 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 <command>x11perf</command> tests.)
-</para>
-
-<para>The following table summarizes relative <command>x11perf</command> test changes for
-all optimizations individually and collectively. Note that some of the
-optimizations have a synergistic effect when used together.
-<screen>
-
-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)
-</screen>
-</para>
-</sect3>
-
-<sect3>
-<title>Profiling with OProfile</title>
-
-<para>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 <command>gprof</command>, 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 <command>x11perf</command> test individually.
-</para>
-
-<para>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 <command>gprof</command> output.
-This investigation has not produced results that yield performance
-increases in <command>x11perf</command> numbers.
-</para>
-
-</sect3>
-
-<!--
-<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 (&gt;
-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 (&gt; 20% total)
-spent in SecurityLookupIDByClass(), WaitForSomething(), and Dispatch().
-For these tests, &lt; 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.
--->
-
-<sect3>
-<title>X Test Suite</title>
-
-<para>The X Test Suite was run on the fully optimized DMX server using the
-configuration described above. The following failures were noted:
-<screen>
-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.
-</screen>
-</para>
-
-</sect3>
-
-</sect2>
-
-<!-- ============================================================ -->
-<sect2>
-<title>Phase III</title>
-
-<para>During the third phase of development, support was provided for the
-following extensions: SHAPE, RENDER, XKEYBOARD, XInput.
-</para>
-
-<sect3>
-<title>SHAPE</title>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>RENDER</title>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>XKEYBOARD</title>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>XInput</title>
-
-<para>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.
-</para>
-
-<para>Currently, back-end extension devices are not available as Xdmx
-extension devices, but this limitation should be removed in the future.
-</para>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>DPMS</title>
-
-<para>The DPMS extension is exported but does not do anything at this time.
-</para>
-
-</sect3>
-
-<sect3>
-<title>Other Extensions</title>
-
-<para>The LBX,
- SECURITY,
- XC-APPGROUP, and
- XFree86-Bigfont
-extensions do not require any special Xdmx support and have been exported.
-</para>
-
-<para>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 <emphasis remap="it">not</emphasis> supported at this time, but will be evaluated
-for inclusion in future DMX releases. <emphasis remap="bf">See below for additional work
-on extensions after Phase III.</emphasis>
-</para>
-</sect3>
-</sect2>
-
-<sect2>
-<title>Phase IV</title>
-
-<sect3>
-<title>Moving to XFree86 4.3.0</title>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>Extensions </title>
-
-<sect4>
-<title>XC-MISC (supported)</title>
-
-<para>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 -->
-</para>
-</sect4>
-
-<sect4>
-<title>Extended-Visual-Information (supported)</title>
-
-<para>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 <filename>hw/dmx/examples/evi</filename> example
-program. <emphasis remap="bf">Note that this extension is not Xinerama-aware</emphasis> -- 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 -->
-</para>
-</sect4>
-
-<sect4>
-<title>RES (supported)</title>
-
-<para>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 <filename>hw/dmx/examples/res</filename> program. The
-X Test Suite passed and failed the exact same tests before and after
-this extension was enabled.
-<!-- Tested March 2003 -->
-</para>
-</sect4>
-
-<sect4>
-<title>BIG-REQUESTS (supported)</title>
-
-<para>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 -->
-</para>
-</sect4>
-
-<sect4>
-<title>XSYNC (supported)</title>
-
-<para>This extension provides facilities for two different X clients to
-synchronize their requests. This extension was minimally tested with
-<command>xdpyinfo</command> and the X Test Suite passed and failed the exact same
-tests before and after this extension was enabled.
-<!-- Tested March 2003 -->
-</para>
-</sect4>
-
-<sect4>
-<title>XTEST, RECORD, DEC-XTRAP (supported) and XTestExtension1 (not supported)</title>
-
-<para>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
-<literal remap="tt">rcrdtest</literal> 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 -->
-</para>
-
-<para>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.
-</para>
-
-<para>The DEC-XTRAP extension is available from Xdmx and has been tested
-with the <command>xtrap*</command> tools which are distributed as standard X11R6
-clients. <!-- Tested March 2003 -->
-</para>
-
-<para>The XTestExtension1 is <emphasis>not</emphasis> 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 -->
-</para>
-
-<para>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:
-<variablelist>
-<varlistentry>
-<term>XRECORD</term>
-<listitem>
-<para>Martha Zimet. Extending X For Recording. 8th Annual X
-Technical Conference Boston, MA January 24-26, 1994.
-</para></listitem></varlistentry>
-<varlistentry>
-<term>DEC-XTRAP</term>
-<listitem>
-<para>Dick Annicchiarico, Robert Chesler, Alan Jamison. XTrap
-Architecture. Digital Equipment Corporation, July 1991.
-</para></listitem></varlistentry>
-<varlistentry>
-<term>XTestExtension1</term>
-<listitem>
-<para>Larry Woestman. X11 Input Synthesis Extension
-Proposal. Hewlett Packard, November 1991.
-</para></listitem></varlistentry>
-</variablelist>
-</para>
-</sect4>
-
-<sect4>
-<title>MIT-MISC (not supported)</title>
-
-<para>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 <emphasis>not</emphasis> support MIT-MISC.
-</para>
-</sect4>
-
-<sect4>
-<title>SCREENSAVER (not supported)</title>
-
-<para>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, <command>beforelight</command> behaved
-as expected. However, when Xinerama was active, <command>beforelight</command> did
-not behave as expected. Further, when this extension is not active,
-<command>xscreensaver</command> (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.
-</para>
-</sect4>
-
-<sect4>
-<title>GLX (supported)</title>
-
-<para>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.
-</para>
-</sect4>
-
-<sect4>
-<title>RENDER (supported)</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-</sect4>
-
-<sect4>
-<title>Summary</title>
-
-<!-- WARNING: this list is duplicated in the "Common X extension
-support" section -->
-<para>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.
-</para>
-
-<para>The following extensions are <emphasis>not</emphasis> 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.
-</para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Additional Testing with the X Test Suite</title>
-
-<sect4>
-<title>XFree86 without XTEST</title>
-
-<para>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 <emphasis>not</emphasis> 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:
-<literallayout>
-XListPixmapFormats: Test 1
-XChangeKeyboardControl: Tests 9, 10
-XGetDefault: Test 5
-XRebindKeysym: Test 1
-</literallayout>
-</para>
-</sect4>
-
-<sect4>
-<title>XFree86 with XTEST</title>
-
-<para>When using the XTEST extension, the XFree86 4.3.0 server reported the
-following errors:
-<literallayout>
-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
-</literallayout>
-</para>
-
-<para>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.
-</para>
-</sect4>
-
-<sect4>
-<title>Xdmx with XTEST, without Xinerama, without GLX</title>
-
-<para>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):
-<literallayout>
-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
-</literallayout>
-</para>
-</sect4>
-
-<sect4>
-<title>Xdmx with XTEST, with Xinerama, without GLX</title>
-
-<para>With Xinerama, using the XTEST extension, the following errors
-were reported from Xdmx:
-<literallayout>
-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
-</literallayout>
-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.
-</para>
-</sect4>
-
-<sect4>
-<title>Xdmx with XTEST, with Xinerama, with GLX</title>
-
-<para>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):
-<literallayout>
-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
-</literallayout>
-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.
-</para>
-
-<para>Further, when hardware rendering is disabled on the back-end displays,
-many of the errors in the third set are eliminated, leaving only:
-<literallayout>
-XClearArea: Test 8
-XCopyArea: Test 4, 5, 11, 14, 17, 23, 25, 27, 30
-XCopyPlane: Test 6, 7, 10, 19, 22, 31
-</literallayout>
-</para>
-</sect4>
-
-<sect4>
-<title>Conclusion</title>
-
-<para>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.)
-</para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Dynamic Reconfiguration</title>
-
-<para>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 &lt;x,y&gt; position and then dynamically
-reconfigure that screen to be at position &lt;x+10,y&gt;. 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.
-</para>
-
-<sect4>
-<title>Dynamic reconfiguration extension</title>
-
-<para>The application interface to DMX's dynamic reconfiguration is through
-a function in the DMX extension library:
-<programlisting>
-Bool DMXReconfigureScreen(Display *dpy, int screen, int x, int y)
-</programlisting>
-where <parameter>dpy</parameter> is DMX server's display, <parameter>screen</parameter> is the number of the
-screen to be reconfigured, and <parameter>x</parameter> and <parameter>y</parameter> are the new upper,
-left-hand coordinates of the screen to be reconfigured.
-</para>
-
-<para>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.
-</para>
-</sect4>
-
-<sect4>
-<title>Bounding box</title>
-
-<para>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.
-</para>
-
-<para>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 &lt;-100,-100&gt;
-for the upper, left-hand corner of the bounding box, which was
-previously at coordinates &lt;0,0&gt;. 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.
-</para>
-
-<para>This fixed bounding box limitation will be addressed in a future
-development phase.
-</para>
-</sect4>
-
-<sect4>
-<title>Sample applications</title>
-
-<para>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.
-</para>
-
-<para>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.
-</para>
-
-<para>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 <filename>dmxreconfig.c</filename> for details.
-</para>
-</sect4>
-
-<sect4>
-<title>Additional notes</title>
-
-<para>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).
-</para>
-</sect4>
-</sect3>
-
-<sect3>
-<title>Doxygen documentation</title>
-
-<para>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.
-</para>
-</sect3>
-
-<sect3>
-<title>Valgrind</title>
-
-<para>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:
-<orderedlist>
- <listitem><para>
- 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.
- </para></listitem>
- <listitem><para>
- 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.
- </para></listitem>
- <listitem><para>
- 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.
- </para></listitem>
-</orderedlist>
-</para>
-</sect3>
-
-<sect3>
-<title>RATS</title>
-
-<para>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:
-<orderedlist>
- <listitem><para>
- 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.
- </para></listitem>
- <listitem><para>
- 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.
- </para></listitem>
- <listitem><para>
- 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).
- </para></listitem>
-</orderedlist>
-
-</para>
-
-</sect3>
-
-</sect2>
-
-</sect1>
-
-</appendix>
-
- </article>
-
- <!-- Local Variables: -->
- <!-- fill-column: 72 -->
- <!-- End: -->
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+]>
+
+<article>
+
+ <articleinfo>
+ <!-- Title information -->
+ <title>Distributed Multihead X design</title>
+ <authorgroup>
+ <author><firstname>Kevin E.</firstname><surname>Martin</surname></author>
+ <author><firstname>David H.</firstname><surname>Dawes</surname></author>
+ <author><firstname>Rickard E.</firstname><surname>Faith</surname></author>
+ </authorgroup>
+ <pubdate>29 June 2004 (created 25 July 2001)</pubdate>
+ <abstract><para>
+ 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. <emphasis remap="it">Copyright 2001 by VA
+ Linux Systems, Inc., Fremont, California. Copyright 2001-2004
+ by Red Hat, Inc., Raleigh, North Carolina</emphasis>
+ </para></abstract>
+ </articleinfo>
+
+<!-- Begin the document -->
+<sect1>
+<title>Introduction</title>
+
+<sect2>
+<title>The Distributed Multihead X Server</title>
+
+<para>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.
+</para>
+
+<para>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.).
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+</sect2>
+
+<sect2>
+<title>Layout of Paper</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+</sect2>
+</sect1>
+
+<!-- ============================================================ -->
+<sect1>
+<title>Development plan</title>
+
+<para>This section describes the development plan from approximately June
+2001 through July 2003.
+</para>
+
+<sect2>
+<title>Bootstrap code</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>Status: The boot strap code is complete. <!-- August 2001 -->
+</para>
+
+</sect2>
+
+<sect2>
+<title>Input device handling</title>
+
+<para>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'',
+</para>
+
+<para>There are some options as to how the front-end X server gets its core
+input devices:
+
+<orderedlist>
+<listitem>
+ <para>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.
+</para>
+
+ <para>The following options are available for implementing local input
+ devices:
+
+<orderedlist>
+<listitem>
+ <para>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.
+</para>
+</listitem>
+
+<listitem>
+ <para>The <command>kdrive</command> 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
+ <command>gpm</command> 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 <command>kdrive</command> drivers were not used for the DMX
+ implementation.
+</para>
+</listitem>
+
+<listitem>
+ <para>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.
+</para>
+</listitem>
+</orderedlist>
+</para>
+</listitem>
+
+<listitem>
+ <para>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.
+</para>
+</listitem>
+
+<listitem>
+ <para>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.
+</para>
+</listitem>
+
+<listitem>
+ <para>Other options were initially explored, but they were all
+ partial subsets of the options listed above and, hence, are
+ irrelevant.
+</para>
+</listitem>
+
+</orderedlist>
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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):
+<orderedlist>
+<listitem>
+ <para> A "dummy" device drive that never generates events.
+</para>
+</listitem>
+
+<listitem>
+ <para> "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):
+ <itemizedlist>
+ <listitem><para>Linux keyboard</para></listitem>
+ <listitem><para>Linux serial mouse (MS)</para></listitem>
+ <listitem><para>Linux PS/2 mouse</para></listitem>
+ <listitem><para>USB keyboard</para></listitem>
+ <listitem><para>USB mouse</para></listitem>
+ <listitem><para>USB generic device (e.g., joystick, gamepad, etc.)</para></listitem>
+ </itemizedlist>
+</para>
+</listitem>
+
+<listitem>
+ <para> "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.
+</para>
+</listitem>
+
+<listitem>
+ <para> "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.
+</para>
+</listitem>
+</orderedlist>
+
+</para>
+
+</sect2>
+
+<!-- May 2002; July 2003 -->
+
+<sect2>
+<title>Output device handling</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<sect3>
+<title>Initialization</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>Handling rendering requests</title>
+
+<para>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:
+
+<orderedlist>
+<listitem>
+ <para>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.
+</para>
+
+ <para>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.
+</para>
+
+ <para>The initial DMX implementation used a shadow framebuffer by
+ default.
+</para>
+</listitem>
+
+<listitem>
+ <para>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.
+</para>
+
+ <para>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.
+</para>
+
+ <para>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).
+</para>
+</listitem>
+
+</orderedlist>
+</para>
+
+<para>Status: Both the shadow framebuffer and Xnest-style code is complete.
+<!-- May 2002 -->
+</para>
+
+</sect3>
+</sect2>
+
+<sect2>
+<title>Optimizing DMX</title>
+
+<para>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.
+</para>
+
+<para>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).
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>Other potential optimizations will be determined from the performance
+analysis.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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 -->
+</para>
+
+</sect2>
+
+<sect2>
+<title>DMX X extension support</title>
+
+<para>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.
+</para>
+
+<para>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:
+<orderedlist>
+<listitem><para>
+ Screen information (clipping rectangle for each screen relative
+ to the virtual screen)
+</para></listitem>
+<listitem><para>
+ Window information (window IDs and clipping information for each
+ back-end window that corresponds to each DMX window)
+</para></listitem>
+<listitem><para>
+ Input device information (mappings from DMX device IDs to
+ back-end device IDs)
+</para></listitem>
+<listitem><para>
+ Force window creation (so that a client can override the
+ server-side lazy window creation optimization)
+</para></listitem>
+<listitem><para>
+ Reconfiguration (so that a client can request that a screen
+ position be changed)
+</para></listitem>
+<listitem><para>
+ Addition and removal of back-end servers and back-end and
+ console inputs.
+</para></listitem>
+</orderedlist>
+</para>
+<!-- September 2002; July 2003 -->
+
+</sect2>
+
+<sect2>
+<title>Common X extension support</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>Support for the XTest extension was added during the first
+development phase.
+</para>
+
+<!-- WARNING: this list is duplicated in the Phase IV discussion -->
+<para>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 -->
+</para>
+</sect2>
+
+<sect2>
+<title>OpenGL support</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<orderedlist>
+<listitem>
+ <para>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.
+</para></listitem>
+
+<listitem>
+ <para>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.
+</para></listitem>
+</orderedlist>
+
+<para>These, and other, options will be investigated in this phase of the
+work.
+</para>
+
+<para>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.
+</para>
+
+<para>Status: OpenGL support by the glxProxy extension was implemented by
+SGI and has been integrated into the DMX code base.
+</para>
+<!-- May 2003-->
+</sect2>
+
+</sect1>
+
+<!-- ============================================================ -->
+<sect1>
+<title>Current issues</title>
+
+<para>In this sections the current issues are outlined that require further
+investigation.
+</para>
+
+<sect2>
+<title>Fonts</title>
+
+<para>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.
+</para>
+</sect2>
+
+<sect2>
+<title>Zero width rendering primitives</title>
+
+<para>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.
+</para>
+</sect2>
+
+<sect2>
+<title>Output scaling</title>
+
+<para>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.
+</para>
+</sect2>
+
+<sect2>
+<title>Per-screen colormaps</title>
+
+<para>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.
+</para>
+</sect2>
+</sect1>
+
+<!-- ============================================================ -->
+<appendix>
+<title>Appendix</title>
+
+<sect1>
+<title>Background</title>
+
+<para>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.
+</para>
+
+<sect2>
+<title>Core input device handling</title>
+
+<para>The following is a description of how core input devices are handled
+by an X server.
+</para>
+
+<sect3>
+<title>InitInput()</title>
+
+<para>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().
+</para>
+
+<para>InitInput() usually has implementation specific code to determine
+which input devices are available. For each input device it will be
+using, it calls AddInputDevice():
+
+<variablelist>
+<varlistentry>
+<term>AddInputDevice()</term>
+<listitem><para>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.
+</para></listitem>
+</varlistentry>
+</variablelist>
+</para>
+
+<para>Once input handles for core keyboard and core pointer devices have
+been obtained from AddInputDevice(). 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).
+</para>
+
+<para>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.
+</para>
+
+<para><variablelist>
+
+<varlistentry>
+<term>miRegisterPointerDevice()</term>
+<listitem><para>This MI function registers the core
+pointer's input handle with with the miPointer code.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>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():
+
+<variablelist>
+<varlistentry>
+<term>mieqInit()</term>
+<listitem><para>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.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>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.)
+</para>
+</sect3>
+
+<sect3>
+<title>InitAndStartDevices()</title>
+
+<para>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.
+</para>
+
+<para>Each registered device is initialized by calling its callback
+(dev-&gt;deviceProc) with the DEVICE_INIT argument:
+
+<variablelist>
+<varlistentry>
+<term>(*dev-&gt;deviceProc)(dev, DEVICE_INIT)</term>
+<listitem>
+<para>This function initializes the
+device structs with core information relevant to the device.
+</para>
+
+<para>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.
+</para>
+
+<para>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).
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>Each initialized device is enabled by calling EnableDevice():
+
+<variablelist>
+<varlistentry>
+<term>EnableDevice()</term>
+<listitem>
+<para>EnableDevice() calls the device callback with
+DEVICE_ON:
+ <variablelist>
+ <varlistentry>
+ <term>(*dev-&gt;deviceProc)(dev, DEVICE_ON)</term>
+ <listitem>
+ <para>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.
+ </para></listitem></varlistentry>
+ </variablelist>
+ </para>
+
+ <para>EnableDevice() then adds the device handle to the X server's
+ global list of enabled devices.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>InitAndStartDevices() then verifies that a valid core keyboard and
+pointer has been initialized and enabled. It returns failure if either
+are missing.
+</para>
+</sect3>
+
+<sect3>
+<title>devReadInput()</title>
+
+<para>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).
+</para>
+
+<para>Events are queued by calling mieqEnqueue():
+
+<variablelist>
+<varlistentry>
+<term>mieqEnqueue()</term>
+<listitem>
+<para>This MI function is used to add input events to the
+event queue. It is simply passed the event to be queued.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>The cursor position should be updated when motion events are
+enqueued, by calling either miPointerAbsoluteCursor() or
+miPointerDeltaCursor():
+
+<variablelist>
+<varlistentry>
+<term>miPointerAbsoluteCursor()</term>
+<listitem>
+<para>This MI function is used to move the
+cursor to the absolute coordinates provided.
+</para></listitem></varlistentry>
+<varlistentry>
+<term>miPointerDeltaCursor()</term>
+<listitem>
+<para>This MI function is used to move the cursor
+relative to its current position.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+</sect3>
+
+<sect3>
+<title>ProcessInputEvents()</title>
+
+<para>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.
+</para>
+
+<para>Enqueued events are processed by mieqProcessInputEvents() and passed
+to the DIX layer for transmission to clients:
+
+<variablelist>
+<varlistentry>
+<term>mieqProcessInputEvents()</term>
+<listitem>
+<para>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.
+</para></listitem></varlistentry>
+<varlistentry>
+<term>miPointerUpdate()</term>
+<listitem>
+<para>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.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+</sect3>
+
+<sect3>
+<title>DisableDevice()</title>
+
+<para>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.
+</para>
+
+<para>DisableDevice() calls the device's callback function with
+<constant>DEVICE_OFF</constant>:
+
+<variablelist>
+<varlistentry>
+<term>(*dev-&gt;deviceProc)(dev, DEVICE_OFF)</term>
+<listitem>
+<para>This typically closes the
+relevant physical device, and when appropriate, unregisters the device's
+file descriptor (or equivalent) as a valid input source.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>DisableDevice() then removes the device handle from the X server's
+global list of enabled devices.
+</para>
+
+</sect3>
+
+<sect3>
+<title>CloseDevice()</title>
+
+<para>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.
+</para>
+
+<para>CloseDevice() calls the device's callback function with
+<constant>DEVICE_CLOSE</constant>:
+
+<variablelist>
+<varlistentry>
+<term>(*dev-&gt;deviceProc)(dev, DEVICE_CLOSE)</term>
+<listitem>
+<para>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.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>CloseDevice() then frees the data structures that were allocated
+for the device when it was registered/initialized.
+</para>
+
+</sect3>
+
+<sect3>
+<title>LegalModifier()</title>
+<!-- dmx/dmxinput.c - currently returns TRUE -->
+<para>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.
+</para>
+
+</sect3>
+</sect2>
+
+<sect2>
+<title>Output handling</title>
+
+<para>The following sections describe the main functions required to
+initialize, use and close the output device(s) for each screen in the X
+server.
+</para>
+
+<sect3>
+<title>InitOutput()</title>
+
+<para>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.
+</para>
+
+<para>The primary tasks for this function are outlined below:
+
+<orderedlist>
+<listitem>
+ <para><emphasis remap="bf">Parse configuration info:</emphasis> 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.
+</para>
+</listitem>
+
+<listitem>
+ <para><emphasis remap="bf">Initialize screen info:</emphasis> 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&lsqb;&rsqb; structure.
+</para>
+</listitem>
+
+<listitem>
+ <para><emphasis remap="bf">Set pixmap formats:</emphasis> 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.
+</para>
+</listitem>
+
+<listitem>
+ <para><emphasis remap="bf">Unify screen info:</emphasis> 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.
+</para>
+</listitem>
+</orderedlist>
+</para>
+
+<para>Once these tasks are complete, the valid screens are known and each
+of these screens can be initialized by calling AddScreen().
+</para>
+</sect3>
+
+<sect3>
+<title>AddScreen()</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>ScreenInit()</title>
+
+<para>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).
+</para>
+
+<para>The screen init function usually calls several functions to perform
+certain screen initialization functions. They are described below:
+
+<variablelist>
+<varlistentry>
+<term>{mi,*fb}ScreenInit()</term>
+<listitem>
+<para>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.
+</para>
+
+<para>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().
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>miInitializeBackingStore()</term>
+<listitem>
+<para>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.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>miDCInitialize()</term>
+<listitem>
+<para>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.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>CloseScreen()</title>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>GC operations</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>Note that some pointers to functions that draw to the screen are
+stored in the Screen structure. They include GetImage(), GetSpans(),
+CopyWindow() and RestoreAreas().
+</para>
+</sect3>
+
+<sect3>
+<title>Xnest</title>
+
+<para>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.
+</para>
+
+<para>The Xnest server implements all of the standard input and output
+initialization steps outlined above.
+</para>
+
+<para><variablelist>
+<varlistentry>
+<term>InitOutput()</term>
+<listitem>
+<para>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.
+</para>
+
+<para>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.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>ScreenInit()</term>
+<listitem>
+<para>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.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>CloseScreen()</term>
+<listitem>
+<para>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.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>GC operations</term>
+<listitem>
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>Shadow framebuffer</title>
+
+<para>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.
+</para>
+
+<para>There are two main entry points to the shadow framebuffer code:
+
+<variablelist>
+<varlistentry>
+<term>shadowAlloc(width, height, bpp)</term>
+<listitem>
+<para>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.
+</para></listitem></varlistentry>
+
+<varlistentry>
+<term>shadowInit(pScreen, updateProc, windowProc)</term>
+<listitem>
+<para>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).
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+</sect3>
+</sect2>
+
+<sect2>
+<title>Xinerama</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>The following is a code-level description of how Xinerama functions.
+</para>
+
+<para>Note: Because the Xinerama extension was originally called the
+PanoramiX extension, many of the Xinerama functions still have the
+PanoramiX prefix.
+</para>
+
+<variablelist>
+<varlistentry>
+<term>PanoramiXExtensionInit()</term>
+<listitem>
+ <para>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.
+ </para>
+
+ <para>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.
+ </para>
+
+ <para>The Xinerama extension is registered by calling AddExtension().
+ </para>
+
+ <para>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.
+ </para>
+
+ <para>A region (PanoramiXScreenRegion) is
+ initialized to be the union of the screen regions.
+ The relative positioning information for the
+ physical screens is taken from the ScreenRec x and y members, which
+ the DDX layer must initialize in InitOutput(). The bounds of the
+ combined screen is also calculated (PanoramiXPixWidth and
+ PanoramiXPixHeight).
+ </para>
+
+ <para>The DIX layer has a list of function pointers
+ (ProcVector&lsqb;&rsqb;) 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&lsqb;&rsqb;. 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.
+ </para>
+</listitem></varlistentry>
+
+<varlistentry>
+<term>PanoramiXConsolidate()</term>
+<listitem>
+ <para>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.
+</para>
+
+ <para>This function finds the set of depths (PanoramiXDepths&lsqb;&rsqb;) and
+ visuals (PanoramiXVisuals&lsqb;&rsqb;)
+ 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.
+ </para>
+</listitem></varlistentry>
+
+<varlistentry>
+<term>PanoramiXCreateConnectionBlock()</term>
+<listitem>
+ <para>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.
+ </para>
+
+ <para>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 <command>xdpyinfo</command> shows). The
+ connection block is initialized with the combined single screen
+ values that were calculated in the above two functions.
+ </para>
+
+ <para>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().
+ </para>
+</listitem></varlistentry>
+</variablelist>
+
+<sect3>
+<title>Xinerama-specific changes to the DIX code</title>
+
+<para>There are a few types of Xinerama-specific changes within the DIX
+code. The main ones are described here.
+</para>
+
+<para>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 &gt; 0. This is because they are handled for
+the single Xinerama screen and the processing is done once for screen 0.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>Xinerama-specific changes to the MI code</title>
+
+<para>The only Xinerama-specific change to the MI code is in miSendExposures()
+to handle the coordinate (and window ID) translation for expose events.
+</para>
+</sect3>
+
+<sect3>
+<title>Intercepted DIX core requests</title>
+
+<para>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.
+</para>
+
+</sect3>
+
+</sect2>
+
+</sect1>
+
+<!-- ============================================================ -->
+
+<sect1>
+<title>Development Results</title>
+
+<para>In this section the results of each phase of development are
+discussed. This development took place between approximately June 2001
+and July 2003.
+</para>
+
+<sect2>
+<title>Phase I</title>
+
+<para>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.
+</para>
+
+<sect3>
+<title>Scope</title>
+
+<para>The goal of Phase I is to provide fundamental functionality that can
+act as a foundation for ongoing work:
+<orderedlist>
+<listitem>
+ <para>Develop the proxy X server
+ <itemizedlist>
+ <listitem>
+ <para>The proxy X server will operate on the X11 protocol and
+ relay requests as necessary to correctly perform the request.
+ </para></listitem>
+ <listitem>
+ <para>Work will be based on the existing work for Xinerama and
+ Xnest.
+ </para></listitem>
+ <listitem>
+ <para>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.
+ </para></listitem>
+ <listitem>
+ <para>The multiple screen layout (including support for
+ overlapping screens) will be user configurable via a
+ configuration file or through the configuration tool.
+ </para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem>
+ <para>Develop graphical configuration tool
+ <itemizedlist>
+ <listitem>
+ <para>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.
+ </para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem>
+ <para>Pass the X Test Suite
+ <itemizedlist>
+ <listitem>
+ <para>The X Test Suite covers the basic X11 operations. All
+ tests known to succeed must correctly operate in the distributed
+ X environment.
+ </para></listitem>
+ </itemizedlist>
+ </para></listitem>
+</orderedlist>
+
+</para>
+
+<para>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).
+</para>
+</sect3>
+
+<sect3>
+<title>Results</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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 <emphasis remap="bf">-configfile</emphasis> and <emphasis remap="bf">-config</emphasis>
+command-line options can be used to start Xdmx using a configuration
+file.
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>X Test Suite</title>
+
+ <sect4>
+ <title>Introduction</title>
+ <para>
+ 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.
+ </para>
+ <para>
+ 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.
+ </para>
+ </sect4>
+
+ <sect4>
+ <title>Expected Failures for a Single Head</title>
+ <para>
+ 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:
+ <literallayout>
+XDrawArc: Tests 42, 63, 66, 73
+XDrawArcs: Tests 45, 66, 69, 76
+ </literallayout>
+ </para>
+ <para>
+ The following failures occur because of the high-level X
+ server implementation:
+ <literallayout>
+XLoadQueryFont: Test 1
+XListFontsWithInfo: Tests 3, 4
+XQueryFont: Tests 1, 2
+ </literallayout>
+ </para>
+ <para>
+ The following test fails when running the X server as root
+ under Linux because of the way directory modes are
+ interpreted:
+ <literallayout>
+XWriteBitmapFile: Test 3
+ </literallayout>
+ </para>
+ <para>
+ 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.
+ </para>
+ </sect4>
+
+ <sect4>
+ <title>Expected Failures for Xinerama</title>
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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:
+ </para>
+
+ <para>
+ These failures were noted with multiple Xinerama
+ configurations:
+ <literallayout>
+XCopyPlane: Tests 13, 22, 31 (well-known Xinerama implementation issue)
+XSetFontPath: Test 4
+XGetDefault: Test 5
+XMatchVisualInfo: Test 1
+ </literallayout>
+ </para>
+ <para>
+ These failures were noted only when using one dual-head
+ video card with a 4.2.99.x XFree86 server:
+ <literallayout>
+XListPixmapFormats: Test 1
+XDrawRectangles: Test 45
+ </literallayout>
+ </para>
+ <para>
+ These failures were noted only when using two video cards
+ from different vendors with a 4.1.99.x XFree86 server:
+ <literallayout>
+XChangeWindowAttributes: Test 32
+XCreateWindow: Test 30
+XDrawLine: Test 22
+XFillArc: Test 22
+XChangeKeyboardControl: Tests 9, 10
+XRebindKeysym: Test 1
+ </literallayout>
+ </para>
+ </sect4>
+
+ <sect4>
+ <title>Additional Failures from Xdmx</title>
+
+ <para>
+ 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:
+ <literallayout>
+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)
+ </literallayout>
+ </para>
+ <para>
+ 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.
+ </para>
+ </sect4>
+
+ <sect4>
+ <title>Summary and Future Work</title>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+ </sect4>
+</sect3>
+
+<sect3>
+<title>Fonts</title>
+
+<para>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
+<emphasis remap="bf">the front- and back-end servers must share the exact same font
+path</emphasis>. There are two ways to help make sure that all servers share the
+same font path:
+
+<orderedlist>
+ <listitem>
+ <para>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.
+ </para></listitem>
+
+ <listitem>
+ <para>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.
+ </para></listitem>
+</orderedlist>
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>Performance</title>
+
+<para>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.
+</para>
+
+<orderedlist>
+ <listitem>
+ <para>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.
+ </para></listitem>
+
+ <listitem>
+ <para>Sending drawing requests to only the screens that they overlap
+ should improve performance.
+ </para></listitem>
+</orderedlist>
+</sect3>
+
+<sect3>
+<title>Pixmaps</title>
+
+<para>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.
+</para>
+
+</sect3>
+
+</sect2>
+
+<!-- ============================================================ -->
+<sect2>
+<title>Phase II</title>
+
+<para>The second phase of development concentrates on performance
+optimizations. These optimizations are documented here, with
+<command>x11perf</command> data to show how the optimizations improve performance.
+</para>
+
+<para>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.
+</para>
+
+<sect3>
+<title>Moving from XFree86 4.1.99.1 to 4.2.0.0</title>
+
+<para>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:
+<screen>
+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)
+</screen>
+And the following tests were noted to be more than 10% slower:
+<screen>
+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)
+</screen>
+</para>
+
+<para>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 <command>x11perf</command> tests.
+</para>
+</sect3>
+
+<sect3>
+<title>Global changes</title>
+
+<para>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:
+<screen>
+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)
+</screen>
+</para>
+
+<para>The following tests were noted to be more than 10% slower:
+<screen>
+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)
+</screen>
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>XSync() Batching</title>
+
+<para>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.
+</para>
+
+<para>Out of more than 300 <command>x11perf</command> 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.
+</para>
+
+<para>The following tests were noted to be more than 10% slower with
+XSync() batching on:
+<screen>
+0.88 500x500 tiled rectangle (161x145 tile)
+0.89 Copy 500x500 from window to window
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Offscreen Optimization</title>
+
+<para>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.
+</para>
+
+<para>Out of more than 300 <command>x11perf</command> 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:
+<screen>
+0.88 Hide/expose window via popup (4 kids)
+0.89 Resize unmapped window (75 kids)
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Lazy Window Creation Optimization</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>This optimization improved the following <command>x11perf</command> tests by more
+than 10%:
+<screen>
+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)
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Subdividing Rendering Primitives</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>This optimization improved the following <command>x11perf</command> tests by more
+than 10%:
+<screen>
+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)
+</screen>
+</para>
+
+<para>The following test was noted to be more than 10% slower with this
+optimization:
+<screen>
+0.88 10-pixel fill chord partial circle
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Summary of x11perf Data</title>
+
+<para>With all of the optimizations on, 53 <command>x11perf</command> 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 <command>x11perf</command> tests.)
+</para>
+
+<para>The following table summarizes relative <command>x11perf</command> test changes for
+all optimizations individually and collectively. Note that some of the
+optimizations have a synergistic effect when used together.
+<screen>
+
+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)
+</screen>
+</para>
+</sect3>
+
+<sect3>
+<title>Profiling with OProfile</title>
+
+<para>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 <command>gprof</command>, 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 <command>x11perf</command> test individually.
+</para>
+
+<para>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 <command>gprof</command> output.
+This investigation has not produced results that yield performance
+increases in <command>x11perf</command> numbers.
+</para>
+
+</sect3>
+
+<!--
+<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 (&gt;
+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 (&gt; 20% total)
+spent in SecurityLookupIDByClass(), WaitForSomething(), and Dispatch().
+For these tests, &lt; 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.
+-->
+
+<sect3>
+<title>X Test Suite</title>
+
+<para>The X Test Suite was run on the fully optimized DMX server using the
+configuration described above. The following failures were noted:
+<screen>
+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.
+</screen>
+</para>
+
+</sect3>
+
+</sect2>
+
+<!-- ============================================================ -->
+<sect2>
+<title>Phase III</title>
+
+<para>During the third phase of development, support was provided for the
+following extensions: SHAPE, RENDER, XKEYBOARD, XInput.
+</para>
+
+<sect3>
+<title>SHAPE</title>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>RENDER</title>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>XKEYBOARD</title>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>XInput</title>
+
+<para>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.
+</para>
+
+<para>Currently, back-end extension devices are not available as Xdmx
+extension devices, but this limitation should be removed in the future.
+</para>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>DPMS</title>
+
+<para>The DPMS extension is exported but does not do anything at this time.
+</para>
+
+</sect3>
+
+<sect3>
+<title>Other Extensions</title>
+
+<para>The LBX,
+ SECURITY,
+ XC-APPGROUP, and
+ XFree86-Bigfont
+extensions do not require any special Xdmx support and have been exported.
+</para>
+
+<para>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 <emphasis remap="it">not</emphasis> supported at this time, but will be evaluated
+for inclusion in future DMX releases. <emphasis remap="bf">See below for additional work
+on extensions after Phase III.</emphasis>
+</para>
+</sect3>
+</sect2>
+
+<sect2>
+<title>Phase IV</title>
+
+<sect3>
+<title>Moving to XFree86 4.3.0</title>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>Extensions </title>
+
+<sect4>
+<title>XC-MISC (supported)</title>
+
+<para>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 -->
+</para>
+</sect4>
+
+<sect4>
+<title>Extended-Visual-Information (supported)</title>
+
+<para>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 <filename>hw/dmx/examples/evi</filename> example
+program. <emphasis remap="bf">Note that this extension is not Xinerama-aware</emphasis> -- 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 -->
+</para>
+</sect4>
+
+<sect4>
+<title>RES (supported)</title>
+
+<para>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 <filename>hw/dmx/examples/res</filename> program. The
+X Test Suite passed and failed the exact same tests before and after
+this extension was enabled.
+<!-- Tested March 2003 -->
+</para>
+</sect4>
+
+<sect4>
+<title>BIG-REQUESTS (supported)</title>
+
+<para>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 -->
+</para>
+</sect4>
+
+<sect4>
+<title>XSYNC (supported)</title>
+
+<para>This extension provides facilities for two different X clients to
+synchronize their requests. This extension was minimally tested with
+<command>xdpyinfo</command> and the X Test Suite passed and failed the exact same
+tests before and after this extension was enabled.
+<!-- Tested March 2003 -->
+</para>
+</sect4>
+
+<sect4>
+<title>XTEST, RECORD, DEC-XTRAP (supported) and XTestExtension1 (not supported)</title>
+
+<para>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
+<literal remap="tt">rcrdtest</literal> 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 -->
+</para>
+
+<para>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.
+</para>
+
+<para>The DEC-XTRAP extension is available from Xdmx and has been tested
+with the <command>xtrap*</command> tools which are distributed as standard X11R6
+clients. <!-- Tested March 2003 -->
+</para>
+
+<para>The XTestExtension1 is <emphasis>not</emphasis> 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 -->
+</para>
+
+<para>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:
+<variablelist>
+<varlistentry>
+<term>XRECORD</term>
+<listitem>
+<para>Martha Zimet. Extending X For Recording. 8th Annual X
+Technical Conference Boston, MA January 24-26, 1994.
+</para></listitem></varlistentry>
+<varlistentry>
+<term>DEC-XTRAP</term>
+<listitem>
+<para>Dick Annicchiarico, Robert Chesler, Alan Jamison. XTrap
+Architecture. Digital Equipment Corporation, July 1991.
+</para></listitem></varlistentry>
+<varlistentry>
+<term>XTestExtension1</term>
+<listitem>
+<para>Larry Woestman. X11 Input Synthesis Extension
+Proposal. Hewlett Packard, November 1991.
+</para></listitem></varlistentry>
+</variablelist>
+</para>
+</sect4>
+
+<sect4>
+<title>MIT-MISC (not supported)</title>
+
+<para>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 <emphasis>not</emphasis> support MIT-MISC.
+</para>
+</sect4>
+
+<sect4>
+<title>SCREENSAVER (not supported)</title>
+
+<para>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, <command>beforelight</command> behaved
+as expected. However, when Xinerama was active, <command>beforelight</command> did
+not behave as expected. Further, when this extension is not active,
+<command>xscreensaver</command> (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.
+</para>
+</sect4>
+
+<sect4>
+<title>GLX (supported)</title>
+
+<para>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.
+</para>
+</sect4>
+
+<sect4>
+<title>RENDER (supported)</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+</sect4>
+
+<sect4>
+<title>Summary</title>
+
+<!-- WARNING: this list is duplicated in the "Common X extension
+support" section -->
+<para>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.
+</para>
+
+<para>The following extensions are <emphasis>not</emphasis> 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.
+</para>
+</sect4>
+</sect3>
+
+<sect3>
+<title>Additional Testing with the X Test Suite</title>
+
+<sect4>
+<title>XFree86 without XTEST</title>
+
+<para>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 <emphasis>not</emphasis> 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:
+<literallayout>
+XListPixmapFormats: Test 1
+XChangeKeyboardControl: Tests 9, 10
+XGetDefault: Test 5
+XRebindKeysym: Test 1
+</literallayout>
+</para>
+</sect4>
+
+<sect4>
+<title>XFree86 with XTEST</title>
+
+<para>When using the XTEST extension, the XFree86 4.3.0 server reported the
+following errors:
+<literallayout>
+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
+</literallayout>
+</para>
+
+<para>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.
+</para>
+</sect4>
+
+<sect4>
+<title>Xdmx with XTEST, without Xinerama, without GLX</title>
+
+<para>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):
+<literallayout>
+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
+</literallayout>
+</para>
+</sect4>
+
+<sect4>
+<title>Xdmx with XTEST, with Xinerama, without GLX</title>
+
+<para>With Xinerama, using the XTEST extension, the following errors
+were reported from Xdmx:
+<literallayout>
+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
+</literallayout>
+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.
+</para>
+</sect4>
+
+<sect4>
+<title>Xdmx with XTEST, with Xinerama, with GLX</title>
+
+<para>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):
+<literallayout>
+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
+</literallayout>
+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.
+</para>
+
+<para>Further, when hardware rendering is disabled on the back-end displays,
+many of the errors in the third set are eliminated, leaving only:
+<literallayout>
+XClearArea: Test 8
+XCopyArea: Test 4, 5, 11, 14, 17, 23, 25, 27, 30
+XCopyPlane: Test 6, 7, 10, 19, 22, 31
+</literallayout>
+</para>
+</sect4>
+
+<sect4>
+<title>Conclusion</title>
+
+<para>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.)
+</para>
+</sect4>
+</sect3>
+
+<sect3>
+<title>Dynamic Reconfiguration</title>
+
+<para>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 &lt;x,y&gt; position and then dynamically
+reconfigure that screen to be at position &lt;x+10,y&gt;. 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.
+</para>
+
+<sect4>
+<title>Dynamic reconfiguration extension</title>
+
+<para>The application interface to DMX's dynamic reconfiguration is through
+a function in the DMX extension library:
+<programlisting>
+Bool DMXReconfigureScreen(Display *dpy, int screen, int x, int y)
+</programlisting>
+where <parameter>dpy</parameter> is DMX server's display, <parameter>screen</parameter> is the number of the
+screen to be reconfigured, and <parameter>x</parameter> and <parameter>y</parameter> are the new upper,
+left-hand coordinates of the screen to be reconfigured.
+</para>
+
+<para>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.
+</para>
+</sect4>
+
+<sect4>
+<title>Bounding box</title>
+
+<para>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.
+</para>
+
+<para>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 &lt;-100,-100&gt;
+for the upper, left-hand corner of the bounding box, which was
+previously at coordinates &lt;0,0&gt;. 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.
+</para>
+
+<para>This fixed bounding box limitation will be addressed in a future
+development phase.
+</para>
+</sect4>
+
+<sect4>
+<title>Sample applications</title>
+
+<para>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.
+</para>
+
+<para>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.
+</para>
+
+<para>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 <filename>dmxreconfig.c</filename> for details.
+</para>
+</sect4>
+
+<sect4>
+<title>Additional notes</title>
+
+<para>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).
+</para>
+</sect4>
+</sect3>
+
+<sect3>
+<title>Doxygen documentation</title>
+
+<para>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.
+</para>
+</sect3>
+
+<sect3>
+<title>Valgrind</title>
+
+<para>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:
+<orderedlist>
+ <listitem><para>
+ 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.
+ </para></listitem>
+ <listitem><para>
+ 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.
+ </para></listitem>
+ <listitem><para>
+ 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.
+ </para></listitem>
+</orderedlist>
+</para>
+</sect3>
+
+<sect3>
+<title>RATS</title>
+
+<para>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:
+<orderedlist>
+ <listitem><para>
+ Fixed-size buffers are used in many areas, but code has been
+ added to protect against buffer overflows (e.g., snprintf).
+ 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.
+ </para></listitem>
+ <listitem><para>
+ 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.
+ </para></listitem>
+ <listitem><para>
+ 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).
+ </para></listitem>
+</orderedlist>
+
+</para>
+
+</sect3>
+
+</sect2>
+
+</sect1>
+
+</appendix>
+
+ </article>
+
+ <!-- Local Variables: -->
+ <!-- fill-column: 72 -->
+ <!-- End: -->
diff --git a/xorg-server/hw/dmx/examples/dmxwininfo.c b/xorg-server/hw/dmx/examples/dmxwininfo.c
index 6cf1d411e..3d027d530 100644
--- a/xorg-server/hw/dmx/examples/dmxwininfo.c
+++ b/xorg-server/hw/dmx/examples/dmxwininfo.c
@@ -39,7 +39,6 @@
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#include <X11/Xmu/SysUtil.h>
#include <X11/extensions/dmxext.h>
static const char *FontName = "fixed";
@@ -80,7 +79,7 @@ EventLoop(Display *dpy, Window win, GC gc)
y += 20;
for (i = 0; i < count; i++) {
char str[500];
- XmuSnprintf(str, sizeof(str),
+ snprintf(str, sizeof(str),
"screen %d: pos: %dx%d+%d+%d visible: %dx%d+%d+%d",
winInfo[i].screen,
winInfo[i].pos.width, winInfo[i].pos.height,
diff --git a/xorg-server/hw/dmx/glxProxy/glxcmds.c b/xorg-server/hw/dmx/glxProxy/glxcmds.c
index f79264ea9..a76201da0 100644
--- a/xorg-server/hw/dmx/glxProxy/glxcmds.c
+++ b/xorg-server/hw/dmx/glxProxy/glxcmds.c
@@ -59,9 +59,6 @@
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);
@@ -70,6 +67,44 @@ extern int __glXGetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc);
(x) - dmxScreen->glxErrorBase + __glXerrorBase \
: (x) )
+static __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;
+}
+
+static __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;
+}
+
+static __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;
+
+}
+
Display *GetBackEndDisplay( __GLXclientState *cl, int s )
{
if (! cl->be_displays[s] ) {
diff --git a/xorg-server/hw/dmx/glxProxy/glxscreens.c b/xorg-server/hw/dmx/glxProxy/glxscreens.c
index df49fe50d..01e041c8f 100644
--- a/xorg-server/hw/dmx/glxProxy/glxscreens.c
+++ b/xorg-server/hw/dmx/glxProxy/glxscreens.c
@@ -1,371 +1,332 @@
-/*
- * 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"
-
-#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++) {
- free(be_extensions[s]);
- }
- free( 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];
-
- 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 );
-}
+/*
+ * 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"
+
+#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++) {
+ free(be_extensions[s]);
+ }
+ free( 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];
+
+ 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;
+
+}
+
+int glxIsExtensionSupported( char *ext )
+{
+ return( strstr(ExtensionsString, ext) != NULL );
+}
diff --git a/xorg-server/hw/dmx/glxProxy/glxserver.h b/xorg-server/hw/dmx/glxProxy/glxserver.h
index b2be58219..03e95b865 100644
--- a/xorg-server/hw/dmx/glxProxy/glxserver.h
+++ b/xorg-server/hw/dmx/glxProxy/glxserver.h
@@ -1,309 +1,303 @@
-#ifndef _GLX_server_h_
-#define _GLX_server_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.
- */
-
-#include "dmx.h"
-
-#include <misc.h>
-#include <dixstruct.h>
-#include <pixmapstr.h>
-#include <gcstruct.h>
-#include <extnsionst.h>
-#include <resource.h>
-#include <scrnintstr.h>
-
-
-/*
-** The X header misc.h defines these math functions.
-*/
-#undef abs
-#undef fabs
-
-#define GL_GLEXT_PROTOTYPES /* we want prototypes */
-#include <GL/gl.h>
-#include <GL/glxproto.h>
-#include <GL/glxint.h>
-
-#include "glxscreens.h"
-#include "glxdrawable.h"
-#include "glxcontext.h"
-#include "glxerror.h"
-
-
-#define GLX_SERVER_MAJOR_VERSION 1
-#define GLX_SERVER_MINOR_VERSION 3
-
-#ifndef True
-#define True 1
-#endif
-#ifndef False
-#define False 0
-#endif
-
-/*
-** GLX resources.
-typedef XID GLXContextID;
-typedef XID GLXPixmap;
-typedef XID GLXDrawable;
-typedef XID GLXWindow;
-typedef XID GLXPbuffer;
-
-typedef struct __GLXcontextRec *GLXContext;
-*/
-typedef struct __GLXclientStateRec __GLXclientState;
-
-extern __GLXscreenInfo *__glXActiveScreens;
-extern GLint __glXNumActiveScreens;
-
-/************************************************************************/
-
-/*
-** The last context used (from the server's persective) is cached.
-*/
-extern __GLXcontext *__glXLastContext;
-extern __GLXcontext *__glXForceCurrent(__GLXclientState*, GLXContextTag, int*);
-
-/************************************************************************/
-
-typedef struct {
- int elem_size; /* element size in bytes */
- int nelems; /* number of elements to swap */
- void (*swapfunc)(GLbyte *pc);
-} __GLXRenderSwapInfo;
-
-/*
-** State kept per client.
-*/
-struct __GLXclientStateRec {
- /*
- ** Whether this structure is currently being used to support a client.
- */
- Bool inUse;
-
- /*
- ** Buffer for returned data.
- */
- GLbyte *returnBuf;
- GLint returnBufSize;
-
- /*
- ** Keep a list of all the contexts that are current for this client's
- ** threads.
- */
- __GLXcontext **currentContexts;
- DrawablePtr *currentDrawables;
- GLint numCurrentContexts;
-
- /* Back pointer to X client record */
- ClientPtr client;
-
- int GLClientmajorVersion;
- int GLClientminorVersion;
- char *GLClientextensions;
-
- GLXContextTag *be_currentCTag;
- Display **be_displays;
-
- /*
- ** Keep track of large rendering commands, which span multiple requests.
- */
- GLint largeCmdBytesSoFar; /* bytes received so far */
- GLint largeCmdBytesTotal; /* total bytes expected */
- GLint largeCmdRequestsSoFar; /* requests received so far */
- GLint largeCmdRequestsTotal; /* total requests expected */
- void (*largeCmdRequestsSwapProc)(GLbyte *);
- __GLXRenderSwapInfo *largeCmdRequestsSwap_info;
- GLbyte *largeCmdBuf;
- GLint largeCmdBufSize;
- GLint largeCmdMaxReqDataSize;
-
-};
-
-extern __GLXclientState *__glXClients[];
-
-/************************************************************************/
-
-/*
-** Dispatch tables.
-*/
-typedef void (*__GLXdispatchRenderProcPtr)(GLbyte *);
-typedef int (*__GLXdispatchSingleProcPtr)(__GLXclientState *, GLbyte *);
-typedef int (*__GLXdispatchVendorPrivProcPtr)(__GLXclientState *, GLbyte *);
-extern __GLXdispatchSingleProcPtr __glXSingleTable[];
-extern __GLXdispatchVendorPrivProcPtr __glXVendorPrivTable_EXT[];
-extern __GLXdispatchSingleProcPtr __glXSwapSingleTable[];
-extern __GLXdispatchVendorPrivProcPtr __glXSwapVendorPrivTable_EXT[];
-extern __GLXdispatchRenderProcPtr __glXSwapRenderTable[];
-
-extern __GLXRenderSwapInfo __glXSwapRenderTable_EXT[];
-
-/*
- * Dispatch for GLX commands.
- */
-typedef int (*__GLXprocPtr)(__GLXclientState *, char *pc);
-extern __GLXprocPtr __glXProcTable[];
-
-/*
- * Tables for computing the size of each rendering command.
- */
-typedef struct {
- int bytes;
- int (*varsize)(GLbyte *pc, Bool swap);
-} __GLXrenderSizeData;
-extern __GLXrenderSizeData __glXRenderSizeTable[];
-extern __GLXrenderSizeData __glXRenderSizeTable_EXT[];
-
-/************************************************************************/
-
-/*
-** X resources.
-*/
-extern RESTYPE __glXContextRes;
-extern RESTYPE __glXClientRes;
-extern RESTYPE __glXPixmapRes;
-extern RESTYPE __glXDrawableRes;
-extern RESTYPE __glXWindowRes;
-extern RESTYPE __glXPbufferRes;
-
-/************************************************************************/
-
-/*
-** Prototypes.
-*/
-
-
-extern char *__glXcombine_strings(const char *, const char *);
-
-extern void __glXDisp_DrawArrays(GLbyte*);
-extern void __glXDispSwap_DrawArrays(GLbyte*);
-
-
-/*
-** Routines for sending swapped replies.
-*/
-
-extern void __glXSwapMakeCurrentReply(ClientPtr client,
- xGLXMakeCurrentReadSGIReply *reply);
-
-extern void __glXSwapIsDirectReply(ClientPtr client,
- xGLXIsDirectReply *reply);
-extern void __glXSwapQueryVersionReply(ClientPtr client,
- xGLXQueryVersionReply *reply);
-extern void __glXSwapQueryContextInfoEXTReply(ClientPtr client,
- xGLXQueryContextInfoEXTReply *reply,
- int *buf);
-extern void glxSwapQueryExtensionsStringReply(ClientPtr client,
- xGLXQueryExtensionsStringReply *reply, char *buf);
-extern void glxSwapQueryServerStringReply(ClientPtr client,
- xGLXQueryServerStringReply *reply, char *buf);
-extern void __glXSwapQueryContextReply(ClientPtr client,
- xGLXQueryContextReply *reply, int *buf);
-extern void __glXSwapGetDrawableAttributesReply(ClientPtr client,
- xGLXGetDrawableAttributesReply *reply, int *buf);
-extern void __glXSwapQueryMaxSwapBarriersSGIXReply(ClientPtr client,
- xGLXQueryMaxSwapBarriersSGIXReply *reply);
-
-/*
- * Routines for computing the size of variably-sized rendering commands.
- */
-
-extern int __glXTypeSize(GLenum enm);
-extern int __glXImageSize(GLenum format, GLenum type, GLsizei w, GLsizei h,
- GLint rowLength, GLint skipRows, GLint alignment);
-extern int __glXImage3DSize(GLenum format, GLenum type,
- GLsizei w, GLsizei h, GLsizei d,
- GLint imageHeight, GLint rowLength,
- GLint skipImages, GLint skipRows,
- GLint alignment);
-
-extern int __glXCallListsReqSize(GLbyte *pc, Bool swap);
-extern int __glXBitmapReqSize(GLbyte *pc, Bool swap);
-extern int __glXFogfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXFogivReqSize(GLbyte *pc, Bool swap);
-extern int __glXLightfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXLightivReqSize(GLbyte *pc, Bool swap);
-extern int __glXLightModelfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXLightModelivReqSize(GLbyte *pc, Bool swap);
-extern int __glXMaterialfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXMaterialivReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexParameterfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexParameterivReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexImage1DReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexImage2DReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexEnvfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexEnvivReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexGendvReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexGenfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexGenivReqSize(GLbyte *pc, Bool swap);
-extern int __glXMap1dReqSize(GLbyte *pc, Bool swap);
-extern int __glXMap1fReqSize(GLbyte *pc, Bool swap);
-extern int __glXMap2dReqSize(GLbyte *pc, Bool swap);
-extern int __glXMap2fReqSize(GLbyte *pc, Bool swap);
-extern int __glXPixelMapfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXPixelMapuivReqSize(GLbyte *pc, Bool swap);
-extern int __glXPixelMapusvReqSize(GLbyte *pc, Bool swap);
-extern int __glXDrawPixelsReqSize(GLbyte *pc, Bool swap);
-extern int __glXDrawArraysSize(GLbyte *pc, Bool swap);
-extern int __glXPrioritizeTexturesReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexSubImage1DReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexSubImage2DReqSize(GLbyte *pc, Bool swap);
-extern int __glXTexImage3DReqSize(GLbyte *pc, Bool swap );
-extern int __glXTexSubImage3DReqSize(GLbyte *pc, Bool swap);
-extern int __glXConvolutionFilter1DReqSize(GLbyte *pc, Bool swap);
-extern int __glXConvolutionFilter2DReqSize(GLbyte *pc, Bool swap);
-extern int __glXConvolutionParameterivReqSize(GLbyte *pc, Bool swap);
-extern int __glXConvolutionParameterfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXSeparableFilter2DReqSize(GLbyte *pc, Bool swap);
-extern int __glXColorTableReqSize(GLbyte *pc, Bool swap);
-extern int __glXColorSubTableReqSize(GLbyte *pc, Bool swap);
-extern int __glXColorTableParameterfvReqSize(GLbyte *pc, Bool swap);
-extern int __glXColorTableParameterivReqSize(GLbyte *pc, Bool swap);
-
-/*
- * Routines for computing the size of returned data.
- */
-extern int __glXConvolutionParameterivSize(GLenum pname);
-extern int __glXConvolutionParameterfvSize(GLenum pname);
-extern int __glXColorTableParameterfvSize(GLenum pname);
-extern int __glXColorTableParameterivSize(GLenum pname);
-
-extern void __glXFreeGLXWindow(__glXWindow *pGlxWindow);
-extern void __glXFreeGLXPbuffer(__glXPbuffer *pGlxPbuffer);
-
-extern int __glXVersionMajor;
-extern int __glXVersionMinor;
-
-#define __GLX_IS_VERSION_SUPPORTED(major,minor) \
- ( (__glXVersionMajor > (major)) || \
- ((__glXVersionMajor == (major)) && (__glXVersionMinor >= (minor))) )
-
-#endif /* !__GLX_server_h__ */
+#ifndef _GLX_server_h_
+#define _GLX_server_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.
+ */
+
+#include "dmx.h"
+
+#include <misc.h>
+#include <dixstruct.h>
+#include <pixmapstr.h>
+#include <gcstruct.h>
+#include <extnsionst.h>
+#include <resource.h>
+#include <scrnintstr.h>
+
+
+#define GL_GLEXT_PROTOTYPES /* we want prototypes */
+#include <GL/gl.h>
+#include <GL/glxproto.h>
+#include <GL/glxint.h>
+
+#include "glxscreens.h"
+#include "glxdrawable.h"
+#include "glxcontext.h"
+#include "glxerror.h"
+
+
+#define GLX_SERVER_MAJOR_VERSION 1
+#define GLX_SERVER_MINOR_VERSION 3
+
+#ifndef True
+#define True 1
+#endif
+#ifndef False
+#define False 0
+#endif
+
+/*
+** GLX resources.
+typedef XID GLXContextID;
+typedef XID GLXPixmap;
+typedef XID GLXDrawable;
+typedef XID GLXWindow;
+typedef XID GLXPbuffer;
+
+typedef struct __GLXcontextRec *GLXContext;
+*/
+typedef struct __GLXclientStateRec __GLXclientState;
+
+extern __GLXscreenInfo *__glXActiveScreens;
+extern GLint __glXNumActiveScreens;
+
+/************************************************************************/
+
+/*
+** The last context used (from the server's persective) is cached.
+*/
+extern __GLXcontext *__glXLastContext;
+extern __GLXcontext *__glXForceCurrent(__GLXclientState*, GLXContextTag, int*);
+
+/************************************************************************/
+
+typedef struct {
+ int elem_size; /* element size in bytes */
+ int nelems; /* number of elements to swap */
+ void (*swapfunc)(GLbyte *pc);
+} __GLXRenderSwapInfo;
+
+/*
+** State kept per client.
+*/
+struct __GLXclientStateRec {
+ /*
+ ** Whether this structure is currently being used to support a client.
+ */
+ Bool inUse;
+
+ /*
+ ** Buffer for returned data.
+ */
+ GLbyte *returnBuf;
+ GLint returnBufSize;
+
+ /*
+ ** Keep a list of all the contexts that are current for this client's
+ ** threads.
+ */
+ __GLXcontext **currentContexts;
+ DrawablePtr *currentDrawables;
+ GLint numCurrentContexts;
+
+ /* Back pointer to X client record */
+ ClientPtr client;
+
+ int GLClientmajorVersion;
+ int GLClientminorVersion;
+ char *GLClientextensions;
+
+ GLXContextTag *be_currentCTag;
+ Display **be_displays;
+
+ /*
+ ** Keep track of large rendering commands, which span multiple requests.
+ */
+ GLint largeCmdBytesSoFar; /* bytes received so far */
+ GLint largeCmdBytesTotal; /* total bytes expected */
+ GLint largeCmdRequestsSoFar; /* requests received so far */
+ GLint largeCmdRequestsTotal; /* total requests expected */
+ void (*largeCmdRequestsSwapProc)(GLbyte *);
+ __GLXRenderSwapInfo *largeCmdRequestsSwap_info;
+ GLbyte *largeCmdBuf;
+ GLint largeCmdBufSize;
+ GLint largeCmdMaxReqDataSize;
+
+};
+
+extern __GLXclientState *__glXClients[];
+
+/************************************************************************/
+
+/*
+** Dispatch tables.
+*/
+typedef void (*__GLXdispatchRenderProcPtr)(GLbyte *);
+typedef int (*__GLXdispatchSingleProcPtr)(__GLXclientState *, GLbyte *);
+typedef int (*__GLXdispatchVendorPrivProcPtr)(__GLXclientState *, GLbyte *);
+extern __GLXdispatchSingleProcPtr __glXSingleTable[];
+extern __GLXdispatchVendorPrivProcPtr __glXVendorPrivTable_EXT[];
+extern __GLXdispatchSingleProcPtr __glXSwapSingleTable[];
+extern __GLXdispatchVendorPrivProcPtr __glXSwapVendorPrivTable_EXT[];
+extern __GLXdispatchRenderProcPtr __glXSwapRenderTable[];
+
+extern __GLXRenderSwapInfo __glXSwapRenderTable_EXT[];
+
+/*
+ * Dispatch for GLX commands.
+ */
+typedef int (*__GLXprocPtr)(__GLXclientState *, char *pc);
+extern __GLXprocPtr __glXProcTable[];
+
+/*
+ * Tables for computing the size of each rendering command.
+ */
+typedef struct {
+ int bytes;
+ int (*varsize)(GLbyte *pc, Bool swap);
+} __GLXrenderSizeData;
+extern __GLXrenderSizeData __glXRenderSizeTable[];
+extern __GLXrenderSizeData __glXRenderSizeTable_EXT[];
+
+/************************************************************************/
+
+/*
+** X resources.
+*/
+extern RESTYPE __glXContextRes;
+extern RESTYPE __glXClientRes;
+extern RESTYPE __glXPixmapRes;
+extern RESTYPE __glXDrawableRes;
+extern RESTYPE __glXWindowRes;
+extern RESTYPE __glXPbufferRes;
+
+/************************************************************************/
+
+/*
+** Prototypes.
+*/
+
+
+extern char *__glXcombine_strings(const char *, const char *);
+
+extern void __glXDisp_DrawArrays(GLbyte*);
+extern void __glXDispSwap_DrawArrays(GLbyte*);
+
+
+/*
+** Routines for sending swapped replies.
+*/
+
+extern void __glXSwapMakeCurrentReply(ClientPtr client,
+ xGLXMakeCurrentReadSGIReply *reply);
+
+extern void __glXSwapIsDirectReply(ClientPtr client,
+ xGLXIsDirectReply *reply);
+extern void __glXSwapQueryVersionReply(ClientPtr client,
+ xGLXQueryVersionReply *reply);
+extern void __glXSwapQueryContextInfoEXTReply(ClientPtr client,
+ xGLXQueryContextInfoEXTReply *reply,
+ int *buf);
+extern void glxSwapQueryExtensionsStringReply(ClientPtr client,
+ xGLXQueryExtensionsStringReply *reply, char *buf);
+extern void glxSwapQueryServerStringReply(ClientPtr client,
+ xGLXQueryServerStringReply *reply, char *buf);
+extern void __glXSwapQueryContextReply(ClientPtr client,
+ xGLXQueryContextReply *reply, int *buf);
+extern void __glXSwapGetDrawableAttributesReply(ClientPtr client,
+ xGLXGetDrawableAttributesReply *reply, int *buf);
+extern void __glXSwapQueryMaxSwapBarriersSGIXReply(ClientPtr client,
+ xGLXQueryMaxSwapBarriersSGIXReply *reply);
+
+/*
+ * Routines for computing the size of variably-sized rendering commands.
+ */
+
+extern int __glXTypeSize(GLenum enm);
+extern int __glXImageSize(GLenum format, GLenum type, GLsizei w, GLsizei h,
+ GLint rowLength, GLint skipRows, GLint alignment);
+extern int __glXImage3DSize(GLenum format, GLenum type,
+ GLsizei w, GLsizei h, GLsizei d,
+ GLint imageHeight, GLint rowLength,
+ GLint skipImages, GLint skipRows,
+ GLint alignment);
+
+extern int __glXCallListsReqSize(GLbyte *pc, Bool swap);
+extern int __glXBitmapReqSize(GLbyte *pc, Bool swap);
+extern int __glXFogfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXFogivReqSize(GLbyte *pc, Bool swap);
+extern int __glXLightfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXLightivReqSize(GLbyte *pc, Bool swap);
+extern int __glXLightModelfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXLightModelivReqSize(GLbyte *pc, Bool swap);
+extern int __glXMaterialfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXMaterialivReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexParameterfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexParameterivReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexImage1DReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexImage2DReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexEnvfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexEnvivReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexGendvReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexGenfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexGenivReqSize(GLbyte *pc, Bool swap);
+extern int __glXMap1dReqSize(GLbyte *pc, Bool swap);
+extern int __glXMap1fReqSize(GLbyte *pc, Bool swap);
+extern int __glXMap2dReqSize(GLbyte *pc, Bool swap);
+extern int __glXMap2fReqSize(GLbyte *pc, Bool swap);
+extern int __glXPixelMapfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXPixelMapuivReqSize(GLbyte *pc, Bool swap);
+extern int __glXPixelMapusvReqSize(GLbyte *pc, Bool swap);
+extern int __glXDrawPixelsReqSize(GLbyte *pc, Bool swap);
+extern int __glXDrawArraysSize(GLbyte *pc, Bool swap);
+extern int __glXPrioritizeTexturesReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexSubImage1DReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexSubImage2DReqSize(GLbyte *pc, Bool swap);
+extern int __glXTexImage3DReqSize(GLbyte *pc, Bool swap );
+extern int __glXTexSubImage3DReqSize(GLbyte *pc, Bool swap);
+extern int __glXConvolutionFilter1DReqSize(GLbyte *pc, Bool swap);
+extern int __glXConvolutionFilter2DReqSize(GLbyte *pc, Bool swap);
+extern int __glXConvolutionParameterivReqSize(GLbyte *pc, Bool swap);
+extern int __glXConvolutionParameterfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXSeparableFilter2DReqSize(GLbyte *pc, Bool swap);
+extern int __glXColorTableReqSize(GLbyte *pc, Bool swap);
+extern int __glXColorSubTableReqSize(GLbyte *pc, Bool swap);
+extern int __glXColorTableParameterfvReqSize(GLbyte *pc, Bool swap);
+extern int __glXColorTableParameterivReqSize(GLbyte *pc, Bool swap);
+
+/*
+ * Routines for computing the size of returned data.
+ */
+extern int __glXConvolutionParameterivSize(GLenum pname);
+extern int __glXConvolutionParameterfvSize(GLenum pname);
+extern int __glXColorTableParameterfvSize(GLenum pname);
+extern int __glXColorTableParameterivSize(GLenum pname);
+
+extern void __glXFreeGLXWindow(__glXWindow *pGlxWindow);
+extern void __glXFreeGLXPbuffer(__glXPbuffer *pGlxPbuffer);
+
+extern int __glXVersionMajor;
+extern int __glXVersionMinor;
+
+#define __GLX_IS_VERSION_SUPPORTED(major,minor) \
+ ( (__glXVersionMajor > (major)) || \
+ ((__glXVersionMajor == (major)) && (__glXVersionMinor >= (minor))) )
+
+#endif /* !__GLX_server_h__ */
diff --git a/xorg-server/hw/dmx/glxProxy/render2swap.c b/xorg-server/hw/dmx/glxProxy/render2swap.c
index 81bb501ea..da9b565de 100644
--- a/xorg-server/hw/dmx/glxProxy/render2swap.c
+++ b/xorg-server/hw/dmx/glxProxy/render2swap.c
@@ -32,7 +32,7 @@
#include "unpack.h"
#include "g_disptab.h"
-GLint __glEvalComputeK(GLenum target)
+static GLint __glEvalComputeK(GLenum target)
{
switch (target) {
case GL_MAP1_VERTEX_4:
diff --git a/xorg-server/hw/dmx/input/dmxinputinit.c b/xorg-server/hw/dmx/input/dmxinputinit.c
index 1b067c725..16ecae38d 100644
--- a/xorg-server/hw/dmx/input/dmxinputinit.c
+++ b/xorg-server/hw/dmx/input/dmxinputinit.c
@@ -671,9 +671,9 @@ static char *dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal)
}
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;
+ case DMX_LOCAL_KEYBOARD: snprintf(buf, LEN, "Keyboard%d", k++); break;
+ case DMX_LOCAL_MOUSE: snprintf(buf, LEN, "Mouse%d", m++); break;
+ default: snprintf(buf, LEN, "Other%d", o++); break;
}
return buf;
diff --git a/xorg-server/hw/dmx/input/lnx-keyboard.c b/xorg-server/hw/dmx/input/lnx-keyboard.c
index 269e84435..06e9ec722 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)
-{
- 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;
-}
+/* 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)
+{
+ 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/", "/dev/tty", NULL };
+ char name[64]; /* RATS: Only used in snprintf */
+
+ for (i = 0; vcs[i]; i++) {
+ snprintf(name, sizeof(name), "%s%d", 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-common.c b/xorg-server/hw/dmx/input/usb-common.c
index c655a2984..944033eba 100644
--- a/xorg-server/hw/dmx/input/usb-common.c
+++ b/xorg-server/hw/dmx/input/usb-common.c
@@ -1,381 +1,381 @@
-/*
- * 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
- *
- * Routines that are common between \a usb-keyboard.c, \a usb-mouse.c, and
- * \a usb-other.c */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "usb-private.h"
-
-#define USB_COMMON_DEBUG 1
-
-/*****************************************************************************/
-/* 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-mouse.h"
-
-#define GETPRIV myPrivate *priv \
- = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
-
-#define GETNAME ((DMXLocalInputInfoPtr)(pDevice->public.devicePrivate)) \
- ->name
-
-#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 LOG1INPUT(p,f,a) dmxLogInput(p->dmxInput,f,a)
-#define LOG3INPUT(p,f,a,b,c) dmxLogInput(p->dmxInput,f,a,b,c)
-#define LOG5INPUT(p,f,a,b,c,d,e) dmxLogInput(p->dmxInput,f,a,b,c,d,e)
-#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. */
-/*****************************************************************************/
-
-
-/** Read an event from the \a pDev device. If the event is a motion
- * event, enqueue it with the \a motion function. Otherwise, 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.
- *
- * Since USB devices return EV_KEY events for buttons and keys, \a
- * minButton is used to decide if a Button or Key event should be
- * queued.*/
-void usbRead(DevicePtr pDev,
- MOTIONPROC motion,
- ENQUEUEPROC enqueue,
- int minButton,
- BLOCK block)
-{
- GETPRIV;
- struct input_event raw;
- int v[DMX_MAX_AXES];
- int axis;
-
-#define PRESS(b) \
- do { \
- enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
- } while (0)
-
-#define RELEASE(b) \
- do { \
- enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
- } while (0)
-
- while (read(priv->fd, &raw, sizeof(raw)) > 0) {
-#if USB_COMMON_DEBUG > 1
- LOG3("USB: type = %d, code = 0x%02x, value = %d\n",
- raw.type, raw.code, raw.value);
-#endif
- switch (raw.type) {
- case EV_KEY:
- /* raw.value = 1 for first, 2 for repeat */
- if (raw.code > minButton) {
- if (raw.value) PRESS((raw.code & 0x0f) + 1);
- else RELEASE((raw.code & 0x0f) + 1);
- } else {
- enqueue(pDev, raw.value ? KeyPress : KeyRelease,
- 0, 0, NULL, block);
- }
- break;
- case EV_REL:
- switch (raw.code) {
- case REL_X:
- v[0] = -raw.value;
- v[1] = 0;
- motion(pDev, v, 0, 2, DMX_RELATIVE, block);
- break;
- case REL_Y:
- v[0] = 0;
- v[1] = -raw.value;
- motion(pDev, v, 0, 2, DMX_RELATIVE, block);
- break;
- case REL_WHEEL:
- if ((int)raw.value > 0) {
- PRESS(4);
- RELEASE(4);
- } else if ((int)raw.value < 0) {
- PRESS(5);
- RELEASE(5);
- }
- break;
- default:
- memset(v, 0, sizeof(v));
- axis = priv->relmap[raw.code];
- v[axis] = raw.value;
- motion(pDev, v, axis, 1, DMX_RELATIVE, block);
- }
- break;
- case EV_ABS:
- memset(v, 0, sizeof(v));
- axis = priv->absmap[raw.code];
- v[axis] = raw.value;
- motion(pDev, v, axis, 1, DMX_ABSOLUTE, block);
- break;
- }
- }
-}
-
-#define test_bit(bit) (priv->mask[(bit)/8] & (1 << ((bit)%8)))
-#define test_bits(bit) (bits[(bit)/8] & (1 << ((bit)%8)))
-
-static void usbPrint(myPrivate *priv,
- const char *filename, const char *devname, int fd)
-{
- int j, k;
- DeviceIntPtr pDevice = priv->pDevice;
- unsigned char bits[KEY_MAX/8 + 1]; /* RATS: Use ok assuming that
- * KEY_MAX is greater than
- * REL_MAX, ABS_MAX, SND_MAX, and
- * LED_MAX. */
-
- LOG3INPUT(priv, "%s (%s) using %s\n", pDevice->name, GETNAME, filename);
- LOG1INPUT(priv, " %s\n", devname);
- for (j = 0; j < EV_MAX; j++) {
- if (test_bit(j)) {
- const char *type = "unknown";
- char extra[256]; /* FIXME: may cause buffer overflow */
- extra[0] = '\0';
- switch(j) {
- case EV_KEY: type = "keys/buttons"; break;
- case EV_REL: type = "relative";
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_REL, sizeof(bits)), bits);
- for (k = 0; k < REL_MAX; k++) {
- if (test_bits(k)) switch (k) {
- case REL_X: strcat(extra, " X"); break;
- case REL_Y: strcat(extra, " Y"); break;
- case REL_Z: strcat(extra, " Z"); break;
- case REL_HWHEEL: strcat(extra, " HWheel"); break;
- case REL_DIAL: strcat(extra, " Dial"); break;
- case REL_WHEEL: strcat(extra, " Wheel"); break;
- case REL_MISC: strcat(extra, " Misc"); break;
- }
- }
- break;
- case EV_ABS: type = "absolute";
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
- for (k = 0; k < ABS_MAX; k++) {
- if (test_bits(k)) switch (k) {
- case ABS_X: strcat(extra," X"); break;
- case ABS_Y: strcat(extra," Y"); break;
- case ABS_Z: strcat(extra," Z"); break;
- case ABS_RX: strcat(extra," RX"); break;
- case ABS_RY: strcat(extra," RY"); break;
- case ABS_RZ: strcat(extra," RZ"); break;
- case ABS_THROTTLE: strcat(extra," Throttle");break;
- case ABS_RUDDER: strcat(extra," Rudder"); break;
- case ABS_WHEEL: strcat(extra," Wheel"); break;
- case ABS_GAS: strcat(extra," Gas"); break;
- case ABS_BRAKE: strcat(extra," Break"); break;
- case ABS_HAT0X: strcat(extra," Hat0X"); break;
- case ABS_HAT0Y: strcat(extra," Hat0Y"); break;
- case ABS_HAT1X: strcat(extra," Hat1X"); break;
- case ABS_HAT1Y: strcat(extra," Hat1Y"); break;
- case ABS_HAT2X: strcat(extra," Hat2X"); break;
- case ABS_HAT2Y: strcat(extra," Hat2Y"); break;
- case ABS_HAT3X: strcat(extra," Hat3X"); break;
- case ABS_HAT3Y: strcat(extra," Hat3Y"); break;
- case ABS_PRESSURE: strcat(extra," Pressure");break;
- case ABS_DISTANCE: strcat(extra," Distance");break;
- case ABS_TILT_X: strcat(extra," TiltX"); break;
- case ABS_TILT_Y: strcat(extra," TiltY"); break;
- case ABS_MISC: strcat(extra," Misc"); break;
- }
- }
- break;
- case EV_MSC: type = "reserved"; break;
- case EV_LED: type = "leds";
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_LED, sizeof(bits)), bits);
- for (k = 0; k < LED_MAX; k++) {
- if (test_bits(k)) switch (k) {
- case LED_NUML: strcat(extra," NumLock"); break;
- case LED_CAPSL: strcat(extra," CapsLock"); break;
- case LED_SCROLLL: strcat(extra," ScrlLock"); break;
- case LED_COMPOSE: strcat(extra," Compose"); break;
- case LED_KANA: strcat(extra," Kana"); break;
- case LED_SLEEP: strcat(extra," Sleep"); break;
- case LED_SUSPEND: strcat(extra," Suspend"); break;
- case LED_MUTE: strcat(extra," Mute"); break;
- case LED_MISC: strcat(extra," Misc"); break;
- }
- }
- break;
- case EV_SND: type = "sound";
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_SND, sizeof(bits)), bits);
- for (k = 0; k < SND_MAX; k++) {
- if (test_bits(k)) switch (k) {
- case SND_CLICK: strcat(extra," Click"); break;
- case SND_BELL: strcat(extra," Bell"); break;
- }
- }
- break;
- case EV_REP: type = "repeat"; break;
- case EV_FF: type = "feedback"; break;
- }
- LOG5INPUT(priv, " Feature 0x%02x = %s%s%s%s\n", j, type,
- extra[0] ? " [" : "",
- extra[0] ? extra+1 : "",
- extra[0] ? "]" : "");
- }
- }
-}
-
-/** Initialized \a pDev as a \a usbMouse, \a usbKeyboard, or \a usbOther
-device. */
-void usbInit(DevicePtr pDev, usbType type)
-{
- GETPRIV;
- char name[64]; /* RATS: Only used in XmuSnprintf */
- int i, j, k;
- char buf[256] = { 0, }; /* RATS: Use ok */
- int version;
- unsigned char bits[KEY_MAX/8 + 1]; /* RATS: Use ok assuming that
- * KEY_MAX is greater than
- * REL_MAX, ABS_MAX, SND_MAX, and
- * LED_MAX. */
-
- if (priv->fd >=0) return;
-
- for (i = 0; i < 32; i++) {
- XmuSnprintf(name, sizeof(name), "/dev/input/event%d", i);
- if ((priv->fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) {
- ioctl(priv->fd, EVIOCGVERSION, &version);
- ioctl(priv->fd, EVIOCGNAME(sizeof(buf)), buf);
- memset(priv->mask, 0, sizeof(priv->mask));
- ioctl(priv->fd, EVIOCGBIT(0, sizeof(priv->mask)), priv->mask);
-
- for (j = 0; j < EV_MAX; j++) {
- if (test_bit(j)) {
- switch(j) {
- case EV_REL:
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_REL, sizeof(bits)), bits);
- for (k = 0; k < REL_MAX; k++) {
- if (test_bits(k)) {
- if (k == REL_X) priv->relmap[k] = 0;
- else if (k == REL_Y) priv->relmap[k] = 1;
- else priv->relmap[k] = 2 + priv->numAbs;
- ++priv->numRel;
- }
- }
- break;
- case EV_ABS:
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
- for (k = 0; k < ABS_MAX; k++) {
- if (test_bits(k)) {
- priv->absmap[k] = priv->numAbs;
- ++priv->numAbs;
- }
- }
- break;
- case EV_LED:
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_LED, sizeof(bits)), bits);
- for (k = 0; k < LED_MAX; k++) {
- if (test_bits(k)) ++priv->numLeds;
- }
- break;
- }
- }
- }
- switch (type) {
- case usbMouse:
- if (test_bit(EV_REL) && test_bit(EV_KEY))
- goto found;
- break;
- case usbKeyboard:
- if (test_bit(EV_KEY) && test_bit(EV_LED) && !test_bit(EV_ABS))
- goto found;
- break;
- case usbOther:
- if (!(test_bit(EV_REL) && test_bit(EV_KEY))
- && !(test_bit(EV_KEY) && test_bit(EV_LED)
- && !test_bit(EV_ABS)))
- goto found;
- break;
- }
- close(priv->fd);
- priv->fd = -1;
- }
- }
- if (priv->fd < 0)
- FATAL1("usbInit: Cannot open /dev/input/event* port (%s)\n"
- " If you have not done so, you may need to:\n"
- " rmmod mousedev; rmmod keybdev\n"
- " modprobe evdev\n",
- strerror(errno));
- found:
- usbPrint(priv, name, buf, priv->fd);
-}
-
-/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
-void usbOff(DevicePtr pDev)
-{
- GETPRIV;
-
- if (priv->fd >= 0) close(priv->fd);
- priv->fd = -1;
-}
-
-/** Create a private structure for use within this file. */
-pointer usbCreatePrivate(DeviceIntPtr pDevice)
-{
- myPrivate *priv = calloc(1, sizeof(*priv));
- priv->fd = -1;
- priv->pDevice = pDevice;
- return priv;
-}
-
-/** Destroy a private structure. */
-void usbDestroyPrivate(pointer priv)
-{
- free(priv);
-}
+/*
+ * 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
+ *
+ * Routines that are common between \a usb-keyboard.c, \a usb-mouse.c, and
+ * \a usb-other.c */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "usb-private.h"
+
+#define USB_COMMON_DEBUG 1
+
+/*****************************************************************************/
+/* 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-mouse.h"
+
+#define GETPRIV myPrivate *priv \
+ = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
+
+#define GETNAME ((DMXLocalInputInfoPtr)(pDevice->public.devicePrivate)) \
+ ->name
+
+#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 LOG1INPUT(p,f,a) dmxLogInput(p->dmxInput,f,a)
+#define LOG3INPUT(p,f,a,b,c) dmxLogInput(p->dmxInput,f,a,b,c)
+#define LOG5INPUT(p,f,a,b,c,d,e) dmxLogInput(p->dmxInput,f,a,b,c,d,e)
+#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. */
+/*****************************************************************************/
+
+
+/** Read an event from the \a pDev device. If the event is a motion
+ * event, enqueue it with the \a motion function. Otherwise, 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.
+ *
+ * Since USB devices return EV_KEY events for buttons and keys, \a
+ * minButton is used to decide if a Button or Key event should be
+ * queued.*/
+void usbRead(DevicePtr pDev,
+ MOTIONPROC motion,
+ ENQUEUEPROC enqueue,
+ int minButton,
+ BLOCK block)
+{
+ GETPRIV;
+ struct input_event raw;
+ int v[DMX_MAX_AXES];
+ int axis;
+
+#define PRESS(b) \
+ do { \
+ enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
+ } while (0)
+
+#define RELEASE(b) \
+ do { \
+ enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
+ } while (0)
+
+ while (read(priv->fd, &raw, sizeof(raw)) > 0) {
+#if USB_COMMON_DEBUG > 1
+ LOG3("USB: type = %d, code = 0x%02x, value = %d\n",
+ raw.type, raw.code, raw.value);
+#endif
+ switch (raw.type) {
+ case EV_KEY:
+ /* raw.value = 1 for first, 2 for repeat */
+ if (raw.code > minButton) {
+ if (raw.value) PRESS((raw.code & 0x0f) + 1);
+ else RELEASE((raw.code & 0x0f) + 1);
+ } else {
+ enqueue(pDev, raw.value ? KeyPress : KeyRelease,
+ 0, 0, NULL, block);
+ }
+ break;
+ case EV_REL:
+ switch (raw.code) {
+ case REL_X:
+ v[0] = -raw.value;
+ v[1] = 0;
+ motion(pDev, v, 0, 2, DMX_RELATIVE, block);
+ break;
+ case REL_Y:
+ v[0] = 0;
+ v[1] = -raw.value;
+ motion(pDev, v, 0, 2, DMX_RELATIVE, block);
+ break;
+ case REL_WHEEL:
+ if ((int)raw.value > 0) {
+ PRESS(4);
+ RELEASE(4);
+ } else if ((int)raw.value < 0) {
+ PRESS(5);
+ RELEASE(5);
+ }
+ break;
+ default:
+ memset(v, 0, sizeof(v));
+ axis = priv->relmap[raw.code];
+ v[axis] = raw.value;
+ motion(pDev, v, axis, 1, DMX_RELATIVE, block);
+ }
+ break;
+ case EV_ABS:
+ memset(v, 0, sizeof(v));
+ axis = priv->absmap[raw.code];
+ v[axis] = raw.value;
+ motion(pDev, v, axis, 1, DMX_ABSOLUTE, block);
+ break;
+ }
+ }
+}
+
+#define test_bit(bit) (priv->mask[(bit)/8] & (1 << ((bit)%8)))
+#define test_bits(bit) (bits[(bit)/8] & (1 << ((bit)%8)))
+
+static void usbPrint(myPrivate *priv,
+ const char *filename, const char *devname, int fd)
+{
+ int j, k;
+ DeviceIntPtr pDevice = priv->pDevice;
+ unsigned char bits[KEY_MAX/8 + 1]; /* RATS: Use ok assuming that
+ * KEY_MAX is greater than
+ * REL_MAX, ABS_MAX, SND_MAX, and
+ * LED_MAX. */
+
+ LOG3INPUT(priv, "%s (%s) using %s\n", pDevice->name, GETNAME, filename);
+ LOG1INPUT(priv, " %s\n", devname);
+ for (j = 0; j < EV_MAX; j++) {
+ if (test_bit(j)) {
+ const char *type = "unknown";
+ char extra[256]; /* FIXME: may cause buffer overflow */
+ extra[0] = '\0';
+ switch(j) {
+ case EV_KEY: type = "keys/buttons"; break;
+ case EV_REL: type = "relative";
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_REL, sizeof(bits)), bits);
+ for (k = 0; k < REL_MAX; k++) {
+ if (test_bits(k)) switch (k) {
+ case REL_X: strcat(extra, " X"); break;
+ case REL_Y: strcat(extra, " Y"); break;
+ case REL_Z: strcat(extra, " Z"); break;
+ case REL_HWHEEL: strcat(extra, " HWheel"); break;
+ case REL_DIAL: strcat(extra, " Dial"); break;
+ case REL_WHEEL: strcat(extra, " Wheel"); break;
+ case REL_MISC: strcat(extra, " Misc"); break;
+ }
+ }
+ break;
+ case EV_ABS: type = "absolute";
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
+ for (k = 0; k < ABS_MAX; k++) {
+ if (test_bits(k)) switch (k) {
+ case ABS_X: strcat(extra," X"); break;
+ case ABS_Y: strcat(extra," Y"); break;
+ case ABS_Z: strcat(extra," Z"); break;
+ case ABS_RX: strcat(extra," RX"); break;
+ case ABS_RY: strcat(extra," RY"); break;
+ case ABS_RZ: strcat(extra," RZ"); break;
+ case ABS_THROTTLE: strcat(extra," Throttle");break;
+ case ABS_RUDDER: strcat(extra," Rudder"); break;
+ case ABS_WHEEL: strcat(extra," Wheel"); break;
+ case ABS_GAS: strcat(extra," Gas"); break;
+ case ABS_BRAKE: strcat(extra," Break"); break;
+ case ABS_HAT0X: strcat(extra," Hat0X"); break;
+ case ABS_HAT0Y: strcat(extra," Hat0Y"); break;
+ case ABS_HAT1X: strcat(extra," Hat1X"); break;
+ case ABS_HAT1Y: strcat(extra," Hat1Y"); break;
+ case ABS_HAT2X: strcat(extra," Hat2X"); break;
+ case ABS_HAT2Y: strcat(extra," Hat2Y"); break;
+ case ABS_HAT3X: strcat(extra," Hat3X"); break;
+ case ABS_HAT3Y: strcat(extra," Hat3Y"); break;
+ case ABS_PRESSURE: strcat(extra," Pressure");break;
+ case ABS_DISTANCE: strcat(extra," Distance");break;
+ case ABS_TILT_X: strcat(extra," TiltX"); break;
+ case ABS_TILT_Y: strcat(extra," TiltY"); break;
+ case ABS_MISC: strcat(extra," Misc"); break;
+ }
+ }
+ break;
+ case EV_MSC: type = "reserved"; break;
+ case EV_LED: type = "leds";
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_LED, sizeof(bits)), bits);
+ for (k = 0; k < LED_MAX; k++) {
+ if (test_bits(k)) switch (k) {
+ case LED_NUML: strcat(extra," NumLock"); break;
+ case LED_CAPSL: strcat(extra," CapsLock"); break;
+ case LED_SCROLLL: strcat(extra," ScrlLock"); break;
+ case LED_COMPOSE: strcat(extra," Compose"); break;
+ case LED_KANA: strcat(extra," Kana"); break;
+ case LED_SLEEP: strcat(extra," Sleep"); break;
+ case LED_SUSPEND: strcat(extra," Suspend"); break;
+ case LED_MUTE: strcat(extra," Mute"); break;
+ case LED_MISC: strcat(extra," Misc"); break;
+ }
+ }
+ break;
+ case EV_SND: type = "sound";
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_SND, sizeof(bits)), bits);
+ for (k = 0; k < SND_MAX; k++) {
+ if (test_bits(k)) switch (k) {
+ case SND_CLICK: strcat(extra," Click"); break;
+ case SND_BELL: strcat(extra," Bell"); break;
+ }
+ }
+ break;
+ case EV_REP: type = "repeat"; break;
+ case EV_FF: type = "feedback"; break;
+ }
+ LOG5INPUT(priv, " Feature 0x%02x = %s%s%s%s\n", j, type,
+ extra[0] ? " [" : "",
+ extra[0] ? extra+1 : "",
+ extra[0] ? "]" : "");
+ }
+ }
+}
+
+/** Initialized \a pDev as a \a usbMouse, \a usbKeyboard, or \a usbOther
+device. */
+void usbInit(DevicePtr pDev, usbType type)
+{
+ GETPRIV;
+ char name[64]; /* RATS: Only used in snprintf */
+ int i, j, k;
+ char buf[256] = { 0, }; /* RATS: Use ok */
+ int version;
+ unsigned char bits[KEY_MAX/8 + 1]; /* RATS: Use ok assuming that
+ * KEY_MAX is greater than
+ * REL_MAX, ABS_MAX, SND_MAX, and
+ * LED_MAX. */
+
+ if (priv->fd >=0) return;
+
+ for (i = 0; i < 32; i++) {
+ snprintf(name, sizeof(name), "/dev/input/event%d", i);
+ if ((priv->fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) {
+ ioctl(priv->fd, EVIOCGVERSION, &version);
+ ioctl(priv->fd, EVIOCGNAME(sizeof(buf)), buf);
+ memset(priv->mask, 0, sizeof(priv->mask));
+ ioctl(priv->fd, EVIOCGBIT(0, sizeof(priv->mask)), priv->mask);
+
+ for (j = 0; j < EV_MAX; j++) {
+ if (test_bit(j)) {
+ switch(j) {
+ case EV_REL:
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_REL, sizeof(bits)), bits);
+ for (k = 0; k < REL_MAX; k++) {
+ if (test_bits(k)) {
+ if (k == REL_X) priv->relmap[k] = 0;
+ else if (k == REL_Y) priv->relmap[k] = 1;
+ else priv->relmap[k] = 2 + priv->numAbs;
+ ++priv->numRel;
+ }
+ }
+ break;
+ case EV_ABS:
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
+ for (k = 0; k < ABS_MAX; k++) {
+ if (test_bits(k)) {
+ priv->absmap[k] = priv->numAbs;
+ ++priv->numAbs;
+ }
+ }
+ break;
+ case EV_LED:
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_LED, sizeof(bits)), bits);
+ for (k = 0; k < LED_MAX; k++) {
+ if (test_bits(k)) ++priv->numLeds;
+ }
+ break;
+ }
+ }
+ }
+ switch (type) {
+ case usbMouse:
+ if (test_bit(EV_REL) && test_bit(EV_KEY))
+ goto found;
+ break;
+ case usbKeyboard:
+ if (test_bit(EV_KEY) && test_bit(EV_LED) && !test_bit(EV_ABS))
+ goto found;
+ break;
+ case usbOther:
+ if (!(test_bit(EV_REL) && test_bit(EV_KEY))
+ && !(test_bit(EV_KEY) && test_bit(EV_LED)
+ && !test_bit(EV_ABS)))
+ goto found;
+ break;
+ }
+ close(priv->fd);
+ priv->fd = -1;
+ }
+ }
+ if (priv->fd < 0)
+ FATAL1("usbInit: Cannot open /dev/input/event* port (%s)\n"
+ " If you have not done so, you may need to:\n"
+ " rmmod mousedev; rmmod keybdev\n"
+ " modprobe evdev\n",
+ strerror(errno));
+ found:
+ usbPrint(priv, name, buf, priv->fd);
+}
+
+/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
+void usbOff(DevicePtr pDev)
+{
+ GETPRIV;
+
+ if (priv->fd >= 0) close(priv->fd);
+ priv->fd = -1;
+}
+
+/** Create a private structure for use within this file. */
+pointer usbCreatePrivate(DeviceIntPtr pDevice)
+{
+ myPrivate *priv = calloc(1, sizeof(*priv));
+ priv->fd = -1;
+ priv->pDevice = pDevice;
+ return priv;
+}
+
+/** Destroy a private structure. */
+void usbDestroyPrivate(pointer priv)
+{
+ free(priv);
+}
diff --git a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c
index 0bd51b2c7..0741a7294 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c
+++ b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c
@@ -541,7 +541,6 @@ static int
ProcXF86DRIQueryVersion (register ClientPtr client)
{
xXF86DRIQueryVersionReply rep;
- register int n;
REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq);
EPHYR_LOG ("enter\n") ;
@@ -553,11 +552,11 @@ ProcXF86DRIQueryVersion (register ClientPtr client)
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);
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swaps(&rep.majorVersion);
+ swaps(&rep.minorVersion);
+ swapl(&rep.patchVersion);
}
WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep);
EPHYR_LOG ("leave\n") ;
@@ -569,7 +568,6 @@ ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client)
{
xXF86DRIQueryDirectRenderingCapableReply rep;
Bool isCapable;
- register int n;
REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
@@ -592,8 +590,8 @@ ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client)
rep.isCapable = 0;
if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
}
WriteToClient(client, sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep);
@@ -1311,19 +1309,17 @@ ProcXF86DRIDispatch (register ClientPtr client)
static int
SProcXF86DRIQueryVersion (register ClientPtr client)
{
- register int n;
REQUEST(xXF86DRIQueryVersionReq);
- swaps(&stuff->length, n);
+ swaps(&stuff->length);
return ProcXF86DRIQueryVersion(client);
}
static int
SProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client)
{
- register int n;
REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
- swaps(&stuff->length, n);
- swapl(&stuff->screen, n);
+ swaps(&stuff->length);
+ swapl(&stuff->screen);
return ProcXF86DRIQueryDirectRenderingCapable(client);
}
diff --git a/xorg-server/hw/kdrive/ephyr/ephyrhostproxy.c b/xorg-server/hw/kdrive/ephyr/ephyrhostproxy.c
index ce3f01852..3137055ca 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyrhostproxy.c
+++ b/xorg-server/hw/kdrive/ephyr/ephyrhostproxy.c
@@ -68,7 +68,7 @@ ephyrHostProxyDoForward (pointer a_request_buffer,
EPHYR_LOG ("enter\n") ;
if (a_do_swap) {
- swaps (&in_req->length, n) ;
+ swaps(&in_req->length) ;
}
EPHYR_LOG ("Req {type:%d, data:%d, length:%d}\n",
in_req->reqType, in_req->data, in_req->length) ;
diff --git a/xorg-server/hw/vfb/InitOutput.c b/xorg-server/hw/vfb/InitOutput.c
index 31ed50533..0e701e518 100644
--- a/xorg-server/hw/vfb/InitOutput.c
+++ b/xorg-server/hw/vfb/InitOutput.c
@@ -760,8 +760,7 @@ vfbWriteXWDFileHeader(ScreenPtr pScreen)
SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
for (i = 0; i < pvfb->ncolors; i++)
{
- register char n;
- swapl(&pvfb->pXWDCmap[i].pixel, n);
+ swapl(&pvfb->pXWDCmap[i].pixel);
}
}
}
diff --git a/xorg-server/hw/xfree86/common/xf86.h b/xorg-server/hw/xfree86/common/xf86.h
index 54332e381..e1e0cd7e0 100644
--- a/xorg-server/hw/xfree86/common/xf86.h
+++ b/xorg-server/hw/xfree86/common/xf86.h
@@ -263,7 +263,6 @@ 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);
diff --git a/xorg-server/hw/xfree86/common/xf86Config.c b/xorg-server/hw/xfree86/common/xf86Config.c
index 58b30dd68..3aa923a28 100644
--- a/xorg-server/hw/xfree86/common/xf86Config.c
+++ b/xorg-server/hw/xfree86/common/xf86Config.c
@@ -676,7 +676,6 @@ typedef enum {
FLAG_DPMS_SUSPENDTIME,
FLAG_DPMS_OFFTIME,
FLAG_PIXMAP,
- FLAG_PC98,
FLAG_NOPM,
FLAG_XINERAMA,
FLAG_LOG,
@@ -724,8 +723,6 @@ static OptionInfoRec FlagOptions[] = {
{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,
@@ -756,21 +753,6 @@ static OptionInfoRec FlagOptions[] = {
{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)
{
@@ -1026,18 +1008,6 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
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;
diff --git a/xorg-server/hw/xfree86/common/xf86Globals.c b/xorg-server/hw/xfree86/common/xf86Globals.c
index 16d55577e..93533ec80 100644
--- a/xorg-server/hw/xfree86/common/xf86Globals.c
+++ b/xorg-server/hw/xfree86/common/xf86Globals.c
@@ -103,6 +103,8 @@ xf86InfoRec xf86Info = {
.vtPendingNum = -1,
#endif
.dontVTSwitch = FALSE,
+ .autoVTSwitch = TRUE,
+ .ShareVTs = FALSE,
.dontZap = FALSE,
.dontZoom = FALSE,
.notrapSignals = FALSE,
@@ -119,9 +121,6 @@ xf86InfoRec xf86Info = {
.miscModInDevAllowNonLocal = FALSE,
.pixmap24 = Pix24DontCare,
.pix24From = X_DEFAULT,
-#ifdef SUPPORT_PC98
- .pc98 = FALSE,
-#endif
.pmFlag = TRUE,
.log = LogNone,
.disableRandR = FALSE,
diff --git a/xorg-server/hw/xfree86/common/xf86Helper.c b/xorg-server/hw/xfree86/common/xf86Helper.c
index f8e6c8b41..7c76fa8ec 100644
--- a/xorg-server/hw/xfree86/common/xf86Helper.c
+++ b/xorg-server/hw/xfree86/common/xf86Helper.c
@@ -1583,16 +1583,6 @@ xf86GetAllowMouseOpenFail(void)
}
-Bool
-xf86IsPc98(void)
-{
-#if SUPPORT_PC98
- return xf86Info.pc98;
-#else
- return FALSE;
-#endif
-}
-
void
xf86DisableRandR(void)
{
diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c
index 71926f8e7..93ea333bf 100644
--- a/xorg-server/hw/xfree86/common/xf86Init.c
+++ b/xorg-server/hw/xfree86/common/xf86Init.c
@@ -1352,6 +1352,16 @@ ddxProcessArgument(int argc, char **argv, int i)
xf86xkbdirFlag = TRUE;
return 0;
}
+ if (!strcmp(argv[i], "-novtswitch"))
+ {
+ xf86Info.autoVTSwitch = FALSE;
+ return 1;
+ }
+ if (!strcmp(argv[i], "-sharevts"))
+ {
+ xf86Info.ShareVTs = TRUE;
+ return 1;
+ }
/* OS-specific processing */
return xf86ProcessArgument(argc, argv, i);
@@ -1408,6 +1418,8 @@ ddxUseMsg(void)
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");
+ ErrorF("-novtswitch don't automatically switch VT at reset & exit\n");
+ ErrorF("-sharevts share VTs with another X server\n");
/* OS-specific usage */
xf86UseMsg();
ErrorF("\n");
diff --git a/xorg-server/hw/xfree86/common/xf86Module.h b/xorg-server/hw/xfree86/common/xf86Module.h
index 2a5c805c4..3038c0404 100644
--- a/xorg-server/hw/xfree86/common/xf86Module.h
+++ b/xorg-server/hw/xfree86/common/xf86Module.h
@@ -84,7 +84,7 @@ typedef enum {
#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(11, 0)
#define ABI_XINPUT_VERSION SET_ABI_VERSION(13, 0)
-#define ABI_EXTENSION_VERSION SET_ABI_VERSION(5, 0)
+#define ABI_EXTENSION_VERSION SET_ABI_VERSION(6, 0)
#define ABI_FONT_VERSION SET_ABI_VERSION(0, 6)
#define MODINFOSTRING1 0xef23fdc5
diff --git a/xorg-server/hw/xfree86/common/xf86Privstr.h b/xorg-server/hw/xfree86/common/xf86Privstr.h
index 66a73d32b..14cd56a26 100644
--- a/xorg-server/hw/xfree86/common/xf86Privstr.h
+++ b/xorg-server/hw/xfree86/common/xf86Privstr.h
@@ -1,168 +1,167 @@
-
-/*
- * 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 disableRandR;
- MessageType randRFrom;
- Bool aiglx;
- MessageType aiglxFrom;
- XF86_GlxVisuals glxVisuals;
- MessageType glxVisualsFrom;
-
- Bool useDefaultFontPath;
- MessageType useDefaultFontPathFrom;
- Bool ignoreABI;
-
- Bool forceInputDevices; /* force xorg.conf or built-in 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 */
+
+/*
+ * 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 autoVTSwitch;
+ Bool ShareVTs;
+ 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;
+ Bool pmFlag;
+ Log log;
+ Bool disableRandR;
+ MessageType randRFrom;
+ Bool aiglx;
+ MessageType aiglxFrom;
+ XF86_GlxVisuals glxVisuals;
+ MessageType glxVisualsFrom;
+
+ Bool useDefaultFontPath;
+ MessageType useDefaultFontPathFrom;
+ Bool ignoreABI;
+
+ Bool forceInputDevices; /* force xorg.conf or built-in 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/dixmods/extmod/xf86vmode.c b/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c
index 25980b02b..6d3d5fcbc 100644
--- a/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c
+++ b/xorg-server/hw/xfree86/dixmods/extmod/xf86vmode.c
@@ -1,2126 +1,2098 @@
-
-/*
-
-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 DevPrivateKeyRec VidModeClientPrivateKeyRec;
-#define VidModeClientPrivateKey (&VidModeClientPrivateKeyRec)
-
-/* 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)
-
-
-#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 DevPrivateKeyRec ScreenPrivateKeyRec;
-#define ScreenPrivateKey (&ScreenPrivateKeyRec)
-
-#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
-
-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;
- 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)
- {
- if (!(pEv->mask & mask))
- continue;
- ev.type = XF86VidModeNotify + XF86VidModeEventBase;
- ev.state = state;
- ev.timestamp = currentTime.milliseconds;
- ev.root = pScreen->root->drawable.id;
- ev.kind = kind;
- ev.forced = forced;
- WriteEventsToClient (pEv->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:
- 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;
- }
-}
-
-void
-XFree86VidModeExtensionInit(void)
-{
- ExtensionEntry* extEntry;
- ScreenPtr pScreen;
- int i;
- Bool enabled = FALSE;
-
- DEBUG_P("XFree86VidModeExtensionInit");
-
- if (!dixRegisterPrivateKey(&VidModeClientPrivateKeyRec, PRIVATE_CLIENT, 0))
- return;
-#ifdef XF86VIDMODE_EVENTS
- if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
- return;
-#endif
-
-#ifdef XF86VIDMODE_EVENTS
- EventType = CreateNewResourceType(XF86VidModeFreeEvents, "VidModeEvent");
-#endif
-
- for(i = 0; i < screenInfo.numScreens; i++) {
- pScreen = screenInfo.screens[i];
- if (VidModeExtensionInit(pScreen))
- enabled = TRUE;
- }
- /* 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
- }
-}
+
+/*
+
+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 DevPrivateKeyRec VidModeClientPrivateKeyRec;
+#define VidModeClientPrivateKey (&VidModeClientPrivateKeyRec)
+
+/* 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)
+
+
+#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 DevPrivateKeyRec ScreenPrivateKeyRec;
+#define ScreenPrivateKey (&ScreenPrivateKeyRec)
+
+#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
+
+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;
+ 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)
+ {
+ if (!(pEv->mask & mask))
+ continue;
+ ev.type = XF86VidModeNotify + XF86VidModeEventBase;
+ ev.state = state;
+ ev.timestamp = currentTime.milliseconds;
+ ev.root = pScreen->root->drawable.id;
+ ev.kind = kind;
+ ev.forced = forced;
+ WriteEventsToClient (pEv->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;
+
+ 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);
+ swapl(&rep.length);
+ swaps(&rep.majorVersion);
+ swaps(&rep.minorVersion);
+ }
+ WriteToClient(client, sizeof(xXF86VidModeQueryVersionReply), (char *)&rep);
+ return Success;
+}
+
+static int
+ProcXF86VidModeGetModeLine(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetModeLineReq);
+ xXF86VidModeGetModeLineReply rep;
+ xXF86OldVidModeGetModeLineReply oldrep;
+ pointer mode;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.dotclock);
+ swaps(&rep.hdisplay);
+ swaps(&rep.hsyncstart);
+ swaps(&rep.hsyncend);
+ swaps(&rep.htotal);
+ swaps(&rep.hskew);
+ swaps(&rep.vdisplay);
+ swaps(&rep.vsyncstart);
+ swaps(&rep.vsyncend);
+ swaps(&rep.vtotal);
+ swapl(&rep.flags);
+ swapl(&rep.privsize);
+ }
+ 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;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.modecount);
+ }
+ 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);
+ swaps(&mdinf.hdisplay);
+ swaps(&mdinf.hsyncstart);
+ swaps(&mdinf.hsyncend);
+ swaps(&mdinf.htotal);
+ swapl(&mdinf.hskew);
+ swaps(&mdinf.vdisplay);
+ swaps(&mdinf.vsyncstart);
+ swaps(&mdinf.vsyncend);
+ swaps(&mdinf.vtotal);
+ swapl(&mdinf.flags);
+ swapl(&mdinf.privsize);
+ }
+ 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:
+ 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) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.status);
+ }
+ 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;
+ 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);
+ swapl(&rep.length);
+ }
+ 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;
+
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.x);
+ swapl(&rep.y);
+ }
+ 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;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.clocks);
+ swapl(&rep.maxclocks);
+ swapl(&rep.flags);
+ }
+ 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;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.red);
+ swapl(&rep.green);
+ swapl(&rep.blue);
+ }
+ 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 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);
+ swapl(&rep.length);
+ swaps(&rep.size);
+ 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;
+ 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);
+ swapl(&rep.length);
+ swaps(&rep.size);
+ }
+ WriteToClient(client,sizeof(xXF86VidModeGetGammaRampSizeReply),(char*)&rep);
+
+ return Success;
+}
+
+static int
+ProcXF86VidModeGetPermissions(ClientPtr client)
+{
+ xXF86VidModeGetPermissionsReply rep;
+ 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);
+ swapl(&rep.length);
+ swapl(&rep.permissions);
+ }
+ 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)
+{
+ REQUEST(xXF86VidModeQueryVersionReq);
+ swaps(&stuff->length);
+ return ProcXF86VidModeQueryVersion(client);
+}
+
+static int
+SProcXF86VidModeGetModeLine(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetModeLineReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetModeLineReq);
+ swaps(&stuff->screen);
+ return ProcXF86VidModeGetModeLine(client);
+}
+
+static int
+SProcXF86VidModeGetAllModeLines(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetAllModeLinesReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetAllModeLinesReq);
+ swaps(&stuff->screen);
+ return ProcXF86VidModeGetAllModeLines(client);
+}
+
+static int
+SProcXF86VidModeAddModeLine(ClientPtr client)
+{
+ xXF86OldVidModeAddModeLineReq *oldstuff =
+ (xXF86OldVidModeAddModeLineReq *)client->requestBuffer;
+ int ver;
+
+ REQUEST(xXF86VidModeAddModeLineReq);
+ ver = ClientMajorVersion(client);
+ if (ver < 2) {
+ swaps(&oldstuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86OldVidModeAddModeLineReq);
+ swapl(&oldstuff->screen);
+ swaps(&oldstuff->hdisplay);
+ swaps(&oldstuff->hsyncstart);
+ swaps(&oldstuff->hsyncend);
+ swaps(&oldstuff->htotal);
+ swaps(&oldstuff->vdisplay);
+ swaps(&oldstuff->vsyncstart);
+ swaps(&oldstuff->vsyncend);
+ swaps(&oldstuff->vtotal);
+ swapl(&oldstuff->flags);
+ swapl(&oldstuff->privsize);
+ SwapRestL(oldstuff);
+ } else {
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86VidModeAddModeLineReq);
+ swapl(&stuff->screen);
+ swaps(&stuff->hdisplay);
+ swaps(&stuff->hsyncstart);
+ swaps(&stuff->hsyncend);
+ swaps(&stuff->htotal);
+ swaps(&stuff->hskew);
+ swaps(&stuff->vdisplay);
+ swaps(&stuff->vsyncstart);
+ swaps(&stuff->vsyncend);
+ swaps(&stuff->vtotal);
+ swapl(&stuff->flags);
+ swapl(&stuff->privsize);
+ SwapRestL(stuff);
+ }
+ return ProcXF86VidModeAddModeLine(client);
+}
+
+static int
+SProcXF86VidModeDeleteModeLine(ClientPtr client)
+{
+ xXF86OldVidModeDeleteModeLineReq *oldstuff =
+ (xXF86OldVidModeDeleteModeLineReq *)client->requestBuffer;
+ int ver;
+
+ REQUEST(xXF86VidModeDeleteModeLineReq);
+ ver = ClientMajorVersion(client);
+ if (ver < 2) {
+ swaps(&oldstuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86OldVidModeDeleteModeLineReq);
+ swapl(&oldstuff->screen);
+ swaps(&oldstuff->hdisplay);
+ swaps(&oldstuff->hsyncstart);
+ swaps(&oldstuff->hsyncend);
+ swaps(&oldstuff->htotal);
+ swaps(&oldstuff->vdisplay);
+ swaps(&oldstuff->vsyncstart);
+ swaps(&oldstuff->vsyncend);
+ swaps(&oldstuff->vtotal);
+ swapl(&oldstuff->flags);
+ swapl(&oldstuff->privsize);
+ SwapRestL(oldstuff);
+ } else {
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86VidModeDeleteModeLineReq);
+ swapl(&stuff->screen);
+ swaps(&stuff->hdisplay);
+ swaps(&stuff->hsyncstart);
+ swaps(&stuff->hsyncend);
+ swaps(&stuff->htotal);
+ swaps(&stuff->hskew);
+ swaps(&stuff->vdisplay);
+ swaps(&stuff->vsyncstart);
+ swaps(&stuff->vsyncend);
+ swaps(&stuff->vtotal);
+ swapl(&stuff->flags);
+ swapl(&stuff->privsize);
+ SwapRestL(stuff);
+ }
+ return ProcXF86VidModeDeleteModeLine(client);
+}
+
+static int
+SProcXF86VidModeModModeLine(ClientPtr client)
+{
+ xXF86OldVidModeModModeLineReq *oldstuff =
+ (xXF86OldVidModeModModeLineReq *)client->requestBuffer;
+ int ver;
+
+ REQUEST(xXF86VidModeModModeLineReq);
+ ver = ClientMajorVersion(client);
+ if (ver < 2) {
+ swaps(&oldstuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86OldVidModeModModeLineReq);
+ swapl(&oldstuff->screen);
+ swaps(&oldstuff->hdisplay);
+ swaps(&oldstuff->hsyncstart);
+ swaps(&oldstuff->hsyncend);
+ swaps(&oldstuff->htotal);
+ swaps(&oldstuff->vdisplay);
+ swaps(&oldstuff->vsyncstart);
+ swaps(&oldstuff->vsyncend);
+ swaps(&oldstuff->vtotal);
+ swapl(&oldstuff->flags);
+ swapl(&oldstuff->privsize);
+ SwapRestL(oldstuff);
+ } else {
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86VidModeModModeLineReq);
+ swapl(&stuff->screen);
+ swaps(&stuff->hdisplay);
+ swaps(&stuff->hsyncstart);
+ swaps(&stuff->hsyncend);
+ swaps(&stuff->htotal);
+ swaps(&stuff->hskew);
+ swaps(&stuff->vdisplay);
+ swaps(&stuff->vsyncstart);
+ swaps(&stuff->vsyncend);
+ swaps(&stuff->vtotal);
+ swapl(&stuff->flags);
+ swapl(&stuff->privsize);
+ SwapRestL(stuff);
+ }
+ return ProcXF86VidModeModModeLine(client);
+}
+
+static int
+SProcXF86VidModeValidateModeLine(ClientPtr client)
+{
+ xXF86OldVidModeValidateModeLineReq *oldstuff =
+ (xXF86OldVidModeValidateModeLineReq *)client->requestBuffer;
+ int ver;
+
+ REQUEST(xXF86VidModeValidateModeLineReq);
+ ver = ClientMajorVersion(client);
+ if (ver < 2) {
+ swaps(&oldstuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86OldVidModeValidateModeLineReq);
+ swapl(&oldstuff->screen);
+ swaps(&oldstuff->hdisplay);
+ swaps(&oldstuff->hsyncstart);
+ swaps(&oldstuff->hsyncend);
+ swaps(&oldstuff->htotal);
+ swaps(&oldstuff->vdisplay);
+ swaps(&oldstuff->vsyncstart);
+ swaps(&oldstuff->vsyncend);
+ swaps(&oldstuff->vtotal);
+ swapl(&oldstuff->flags);
+ swapl(&oldstuff->privsize);
+ SwapRestL(oldstuff);
+ } else {
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86VidModeValidateModeLineReq);
+ swapl(&stuff->screen);
+ swaps(&stuff->hdisplay);
+ swaps(&stuff->hsyncstart);
+ swaps(&stuff->hsyncend);
+ swaps(&stuff->htotal);
+ swaps(&stuff->hskew);
+ swaps(&stuff->vdisplay);
+ swaps(&stuff->vsyncstart);
+ swaps(&stuff->vsyncend);
+ swaps(&stuff->vtotal);
+ swapl(&stuff->flags);
+ swapl(&stuff->privsize);
+ SwapRestL(stuff);
+ }
+ return ProcXF86VidModeValidateModeLine(client);
+}
+
+static int
+SProcXF86VidModeSwitchMode(ClientPtr client)
+{
+ REQUEST(xXF86VidModeSwitchModeReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeSwitchModeReq);
+ swaps(&stuff->screen);
+ swaps(&stuff->zoom);
+ return ProcXF86VidModeSwitchMode(client);
+}
+
+static int
+SProcXF86VidModeSwitchToMode(ClientPtr client)
+{
+ REQUEST(xXF86VidModeSwitchToModeReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeSwitchToModeReq);
+ swapl(&stuff->screen);
+ return ProcXF86VidModeSwitchToMode(client);
+}
+
+static int
+SProcXF86VidModeLockModeSwitch(ClientPtr client)
+{
+ REQUEST(xXF86VidModeLockModeSwitchReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeLockModeSwitchReq);
+ swaps(&stuff->screen);
+ swaps(&stuff->lock);
+ return ProcXF86VidModeLockModeSwitch(client);
+}
+
+static int
+SProcXF86VidModeGetMonitor(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetMonitorReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetMonitorReq);
+ swaps(&stuff->screen);
+ return ProcXF86VidModeGetMonitor(client);
+}
+
+static int
+SProcXF86VidModeGetViewPort(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetViewPortReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetViewPortReq);
+ swaps(&stuff->screen);
+ return ProcXF86VidModeGetViewPort(client);
+}
+
+static int
+SProcXF86VidModeSetViewPort(ClientPtr client)
+{
+ REQUEST(xXF86VidModeSetViewPortReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeSetViewPortReq);
+ swaps(&stuff->screen);
+ swapl(&stuff->x);
+ swapl(&stuff->y);
+ return ProcXF86VidModeSetViewPort(client);
+}
+
+static int
+SProcXF86VidModeGetDotClocks(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetDotClocksReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetDotClocksReq);
+ swaps(&stuff->screen);
+ return ProcXF86VidModeGetDotClocks(client);
+}
+
+static int
+SProcXF86VidModeSetClientVersion(ClientPtr client)
+{
+ REQUEST(xXF86VidModeSetClientVersionReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeSetClientVersionReq);
+ swaps(&stuff->major);
+ swaps(&stuff->minor);
+ return ProcXF86VidModeSetClientVersion(client);
+}
+
+static int
+SProcXF86VidModeSetGamma(ClientPtr client)
+{
+ REQUEST(xXF86VidModeSetGammaReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeSetGammaReq);
+ swaps(&stuff->screen);
+ swapl(&stuff->red);
+ swapl(&stuff->green);
+ swapl(&stuff->blue);
+ return ProcXF86VidModeSetGamma(client);
+}
+
+static int
+SProcXF86VidModeGetGamma(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetGammaReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetGammaReq);
+ swaps(&stuff->screen);
+ return ProcXF86VidModeGetGamma(client);
+}
+
+static int
+SProcXF86VidModeSetGammaRamp(ClientPtr client)
+{
+ int length;
+ REQUEST(xXF86VidModeSetGammaRampReq);
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xXF86VidModeSetGammaRampReq);
+ swaps(&stuff->size);
+ swaps(&stuff->screen);
+ length = ((stuff->size + 1) & ~1) * 6;
+ REQUEST_FIXED_SIZE(xXF86VidModeSetGammaRampReq, length);
+ SwapRestS(stuff);
+ return ProcXF86VidModeSetGammaRamp(client);
+}
+
+static int
+SProcXF86VidModeGetGammaRamp(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetGammaRampReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampReq);
+ swaps(&stuff->size);
+ swaps(&stuff->screen);
+ return ProcXF86VidModeGetGammaRamp(client);
+}
+
+static int
+SProcXF86VidModeGetGammaRampSize(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetGammaRampSizeReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetGammaRampSizeReq);
+ swaps(&stuff->screen);
+ return ProcXF86VidModeGetGammaRampSize(client);
+}
+
+static int
+SProcXF86VidModeGetPermissions(ClientPtr client)
+{
+ REQUEST(xXF86VidModeGetPermissionsReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXF86VidModeGetPermissionsReq);
+ swaps(&stuff->screen);
+ 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;
+ }
+}
+
+void
+XFree86VidModeExtensionInit(void)
+{
+ ExtensionEntry* extEntry;
+ ScreenPtr pScreen;
+ int i;
+ Bool enabled = FALSE;
+
+ DEBUG_P("XFree86VidModeExtensionInit");
+
+ if (!dixRegisterPrivateKey(&VidModeClientPrivateKeyRec, PRIVATE_CLIENT, 0))
+ return;
+#ifdef XF86VIDMODE_EVENTS
+ if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
+ return;
+#endif
+
+#ifdef XF86VIDMODE_EVENTS
+ EventType = CreateNewResourceType(XF86VidModeFreeEvents, "VidModeEvent");
+#endif
+
+ for(i = 0; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ if (VidModeExtensionInit(pScreen))
+ enabled = TRUE;
+ }
+ /* 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
+ }
+}
diff --git a/xorg-server/hw/xfree86/dri/xf86dri.c b/xorg-server/hw/xfree86/dri/xf86dri.c
index e02644a30..c35ba2f94 100644
--- a/xorg-server/hw/xfree86/dri/xf86dri.c
+++ b/xorg-server/hw/xfree86/dri/xf86dri.c
@@ -86,7 +86,6 @@ ProcXF86DRIQueryVersion(
)
{
xXF86DRIQueryVersionReply rep;
- register int n;
REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq);
rep.type = X_Reply;
@@ -96,11 +95,11 @@ ProcXF86DRIQueryVersion(
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);
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swaps(&rep.majorVersion);
+ swaps(&rep.minorVersion);
+ swapl(&rep.patchVersion);
}
WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep);
return Success;
@@ -113,7 +112,6 @@ ProcXF86DRIQueryDirectRenderingCapable(
{
xXF86DRIQueryDirectRenderingCapableReply rep;
Bool isCapable;
- register int n;
REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
@@ -136,8 +134,8 @@ ProcXF86DRIQueryDirectRenderingCapable(
rep.isCapable = 0;
if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
}
WriteToClient(client,
@@ -595,9 +593,8 @@ SProcXF86DRIQueryVersion(
register ClientPtr client
)
{
- register int n;
REQUEST(xXF86DRIQueryVersionReq);
- swaps(&stuff->length, n);
+ swaps(&stuff->length);
return ProcXF86DRIQueryVersion(client);
}
@@ -606,10 +603,9 @@ SProcXF86DRIQueryDirectRenderingCapable(
register ClientPtr client
)
{
- register int n;
REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
- swaps(&stuff->length, n);
- swapl(&stuff->screen, n);
+ swaps(&stuff->length);
+ swapl(&stuff->screen);
return ProcXF86DRIQueryDirectRenderingCapable(client);
}
diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c
index af3bcaefe..a97508d21 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.c
+++ b/xorg-server/hw/xfree86/dri2/dri2.c
@@ -102,6 +102,8 @@ typedef struct _DRI2Screen {
DRI2GetMSCProcPtr GetMSC;
DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC;
DRI2AuthMagicProcPtr AuthMagic;
+ DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify;
+ DRI2SwapLimitValidateProcPtr SwapLimitValidate;
HandleExposuresProcPtr HandleExposures;
@@ -191,6 +193,36 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
return pPriv;
}
+Bool
+DRI2SwapLimit(DrawablePtr pDraw, int swap_limit)
+{
+ DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw);
+ DRI2ScreenPtr ds;
+ if (!pPriv)
+ return FALSE;
+
+ ds = pPriv->dri2_screen;
+
+ if (!ds->SwapLimitValidate
+ || !ds->SwapLimitValidate(pDraw, swap_limit))
+ return FALSE;
+
+ pPriv->swap_limit = swap_limit;
+
+ /* Check throttling */
+ if (pPriv->swapsPending >= pPriv->swap_limit)
+ return TRUE;
+
+ if (pPriv->target_sbc == -1 && !pPriv->blockedOnMsc) {
+ if (pPriv->blockedClient) {
+ AttendClient(pPriv->blockedClient);
+ pPriv->blockedClient = NULL;
+ }
+ }
+
+ return TRUE;
+}
+
typedef struct DRI2DrawableRefRec {
XID id;
XID dri2_id;
@@ -352,6 +384,10 @@ allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds,
} else {
*buffer = pPriv->buffers[old_buf];
+
+ if (ds->ReuseBufferNotify)
+ (*ds->ReuseBufferNotify)(pDraw, *buffer);
+
pPriv->buffers[old_buf] = NULL;
return FALSE;
}
@@ -1128,6 +1164,11 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
ds->AuthMagic = info->AuthMagic;
}
+ if (info->version >= 6) {
+ ds->ReuseBufferNotify = info->ReuseBufferNotify;
+ ds->SwapLimitValidate = info->SwapLimitValidate;
+ }
+
/*
* if the driver doesn't provide an AuthMagic function or the info struct
* version is too low, it relies on the old method (using libdrm) or fail
diff --git a/xorg-server/hw/xfree86/dri2/dri2.h b/xorg-server/hw/xfree86/dri2/dri2.h
index 2a41ead5b..9c93209d1 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.h
+++ b/xorg-server/hw/xfree86/dri2/dri2.h
@@ -110,6 +110,16 @@ typedef DRI2BufferPtr (*DRI2CreateBufferProcPtr)(DrawablePtr pDraw,
typedef void (*DRI2DestroyBufferProcPtr)(DrawablePtr pDraw,
DRI2BufferPtr buffer);
/**
+ * Notifies driver when DRI2GetBuffers reuses a dri2 buffer.
+ *
+ * Driver may rename the dri2 buffer in this notify if it is required.
+ *
+ * \param pDraw drawable whose count we want
+ * \param buffer buffer that will be returned to client
+ */
+typedef void (*DRI2ReuseBufferNotifyProcPtr)(DrawablePtr pDraw,
+ DRI2BufferPtr buffer);
+/**
* Get current media stamp counter values
*
* This callback is used to support the SGI_video_sync and OML_sync_control
@@ -159,9 +169,22 @@ typedef void (*DRI2InvalidateProcPtr)(DrawablePtr pDraw,
void *data);
/**
+ * DRI2 calls this hook when ever swap_limit is going to be changed. Default
+ * implementation for the hook only accepts one as swap_limit. If driver can
+ * support other swap_limits it has to implement supported limits with this
+ * callback.
+ *
+ * \param pDraw drawable whos swap_limit is going to be changed
+ * \param swap_limit new swap_limit that going to be set
+ * \return TRUE if limit is support, FALSE if not.
+ */
+typedef Bool (*DRI2SwapLimitValidateProcPtr)(DrawablePtr pDraw,
+ int swap_limit);
+
+/**
* Version of the DRI2InfoRec structure defined in this header
*/
-#define DRI2INFOREC_VERSION 5
+#define DRI2INFOREC_VERSION 6
typedef struct {
unsigned int version; /**< Version of this struct */
@@ -189,6 +212,11 @@ typedef struct {
/* added in version 5 */
DRI2AuthMagicProcPtr AuthMagic;
+
+ /* added in version 6 */
+
+ DRI2ReuseBufferNotifyProcPtr ReuseBufferNotify;
+ DRI2SwapLimitValidateProcPtr SwapLimitValidate;
} DRI2InfoRec, *DRI2InfoPtr;
extern _X_EXPORT int DRI2EventBase;
@@ -251,6 +279,7 @@ extern _X_EXPORT DRI2BufferPtr *DRI2GetBuffersWithFormat(DrawablePtr pDraw,
int *out_count);
extern _X_EXPORT void DRI2SwapInterval(DrawablePtr pDrawable, int interval);
+extern _X_EXPORT Bool DRI2SwapLimit(DrawablePtr pDraw, int swap_limit);
extern _X_EXPORT int DRI2SwapBuffers(ClientPtr client, DrawablePtr pDrawable,
CARD64 target_msc, CARD64 divisor,
CARD64 remainder, CARD64 *swap_target,
diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c
index 552b26b7c..934abf6de 100644
--- a/xorg-server/hw/xfree86/dri2/dri2ext.c
+++ b/xorg-server/hw/xfree86/dri2/dri2ext.c
@@ -71,10 +71,9 @@ ProcDRI2QueryVersion(ClientPtr client)
{
REQUEST(xDRI2QueryVersionReq);
xDRI2QueryVersionReply rep;
- int n;
if (client->swapped)
- swaps(&stuff->length, n);
+ swaps(&stuff->length);
REQUEST_SIZE_MATCH(xDRI2QueryVersionReq);
rep.type = X_Reply;
@@ -84,10 +83,10 @@ ProcDRI2QueryVersion(ClientPtr client)
rep.minorVersion = dri2_minor;
if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.majorVersion, n);
- swapl(&rep.minorVersion, n);
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.majorVersion);
+ swapl(&rep.minorVersion);
}
WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep);
@@ -585,16 +584,15 @@ SProcDRI2Connect(ClientPtr client)
{
REQUEST(xDRI2ConnectReq);
xDRI2ConnectReply rep;
- int n;
/* If the client is swapped, it's not local. Talk to the hand. */
- swaps(&stuff->length, n);
+ swaps(&stuff->length);
if (sizeof(*stuff) / 4 != client->req_len)
return BadLength;
rep.sequenceNumber = client->sequence;
- swaps(&rep.sequenceNumber, n);
+ swaps(&rep.sequenceNumber);
rep.length = 0;
rep.driverNameLength = 0;
rep.deviceNameLength = 0;
diff --git a/xorg-server/hw/xfree86/i2c/fi1236.c b/xorg-server/hw/xfree86/i2c/fi1236.c
index 531b64aed..0bc50e566 100644
--- a/xorg-server/hw/xfree86/i2c/fi1236.c
+++ b/xorg-server/hw/xfree86/i2c/fi1236.c
@@ -1,605 +1,675 @@
-
-#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);
- }
-}
+#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/int10/generic.c b/xorg-server/hw/xfree86/int10/generic.c
index c242405cc..994085493 100644
--- a/xorg-server/hw/xfree86/int10/generic.c
+++ b/xorg-server/hw/xfree86/int10/generic.c
@@ -1,494 +1,482 @@
-/*
- * 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);
-}
+/*
+ * 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;
+
+ 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.
+ */
+ memset((char *)base + V_BIOS, 0, SYS_BIOS - V_BIOS);
+ 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 1043fcde7..44d8a7fcd 100644
--- a/xorg-server/hw/xfree86/int10/helper_exec.c
+++ b/xorg-server/hw/xfree86/int10/helper_exec.c
@@ -1,733 +1,733 @@
-/*
- * 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
- OsBlockSignals();
- return 0;
-}
-
-void
-finish_int(xf86Int10InfoPtr pInt, int sig)
-{
- OsReleaseSignals();
- 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_DOM_FROM_TAG(tag) (((tag) >> 24) & (PCI_DOM_MASK))
-#define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK))
-#define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11)
-#define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8)
-
-#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),
- (uint32_t *)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);
-}
+/*
+ * 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
+ OsBlockSignals();
+ return 0;
+}
+
+void
+finish_int(xf86Int10InfoPtr pInt, int sig)
+{
+ OsReleaseSignals();
+ 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;
+ CARD32 lina = SEG_ADR((CARD32), X86_CS, IP);
+
+ xf86DrvMsgVerb(pInt->scrnIndex, X_INFO, 3, "code at 0x%8.8" PRIx32 ":\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) %" PRIu32 " bytes at %8.8" PRIx32 " %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) %" PRIu32 " bytes at %8.8" PRIx32 " %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) %" PRIu32 " bytes at %8.8" PRIx32 " %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) %" PRIu32 " bytes at %8.8" PRIx32 " %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) %" PRIu32 " bytes at %8.8" PRIx32 " %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) %" PRIu32 " bytes at %8.8" PRIx32 " %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 PC'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.8" PRIx32 "\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.8" PRIx32 ")\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_DOM_FROM_TAG(tag) (((tag) >> 24) & (PCI_DOM_MASK))
+#define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK))
+#define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11)
+#define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8)
+
+#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),
+ (uint32_t *)val, PCI_OFFSET(PciCfg1Addr));
+ if (PRINT_PORT && DEBUG_IO_TRACE())
+ ErrorF(" cfg_inl(%#" PRIx32 ") = %8.8" PRIx32 "\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(%#" PRIx32 ", %8.8" PRIx32 ")\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(%#" PRIx32 ") = %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(%#" PRIx32 ", %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(%#" PRIx32 ") = %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(%#" PRIx32 ", %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 610cd42ac..9088298a9 100644
--- a/xorg-server/hw/xfree86/int10/helper_mem.c
+++ b/xorg-server/hw/xfree86/int10/helper_mem.c
@@ -1,327 +1,324 @@
-/*
- * 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];
-
- segments[0] = MEM_RW(pInt, (0x10 << 2) + 2);
- segments[1] = MEM_RW(pInt, (0x42 << 2) + 2);
- segments[2] = V_BIOS >> 4;
- segments[3] = ~0;
-
- 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, "No V_BIOS found\n");
- 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 ((*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];
+
+ segments[0] = MEM_RW(pInt, (0x10 << 2) + 2);
+ segments[1] = MEM_RW(pInt, (0x42 << 2) + 2);
+ segments[2] = V_BIOS >> 4;
+ segments[3] = ~0;
+
+ 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, "No V_BIOS found\n");
+ 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/man/Xorg.man b/xorg-server/hw/xfree86/man/Xorg.man
index c89b5ee68..2fa72d672 100644
--- a/xorg-server/hw/xfree86/man/Xorg.man
+++ b/xorg-server/hw/xfree86/man/Xorg.man
@@ -334,6 +334,10 @@ as root (i.e, with real-uid 0).
.B \-nosilk
Disable Silken Mouse support.
.TP 8
+.B \-novtswitch
+Disable the automatic switching on X server reset and shutdown to the
+VT that was active when the server started, if supported by the OS.
+.TP 8
.B \-pixmap24
Set the internal pixmap format for depth 24 pixmaps to 24 bits per pixel.
The default is usually 32 bits per pixel. There is normally little
@@ -376,6 +380,9 @@ and
.B \-ggamma
options.
.TP 8
+.B \-sharevts
+Share virtual terminals with another X server, if supported by the OS.
+.TP 8
.BI \-screen " screen-name"
Use the __xconfigfile__(__filemansuffix__) file
.B Screen
diff --git a/xorg-server/hw/xfree86/man/xorg.conf.man b/xorg-server/hw/xfree86/man/xorg.conf.man
index f406f82bb..8f14efb64 100644
--- a/xorg-server/hw/xfree86/man/xorg.conf.man
+++ b/xorg-server/hw/xfree86/man/xorg.conf.man
@@ -634,12 +634,6 @@ are 24 and 32.
Default: 32 unless driver constraints don't allow this (which is rare).
Note: some clients don't behave well when this value is set to 24.
.TP 7
-.BI "Option \*qPC98\*q \*q" boolean \*q
-Specify that the machine is a Japanese PC\-98 machine.
-This should not be enabled for anything other than the Japanese\-specific
-PC\-98 architecture.
-Default: auto\-detected.
-.TP 7
.BI "Option \*qNoPM\*q \*q" boolean \*q
Disables something to do with power management events.
Default: PM enabled on platforms that support it.
diff --git a/xorg-server/hw/xfree86/modes/xf86Cursors.c b/xorg-server/hw/xfree86/modes/xf86Cursors.c
index 066744744..23c48eb9e 100644
--- a/xorg-server/hw/xfree86/modes/xf86Cursors.c
+++ b/xorg-server/hw/xfree86/modes/xf86Cursors.c
@@ -252,7 +252,7 @@ xf86_set_cursor_colors (ScrnInfoPtr scrn, int bg, int fg)
CursorPtr cursor = xf86_config->cursor;
int c;
CARD8 *bits = cursor ?
- dixLookupPrivate(&cursor->devPrivates, CursorScreenKey(screen))
+ dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey, screen)
: NULL;
/* Save ARGB versions of these colors */
@@ -650,7 +650,7 @@ xf86_reload_cursors (ScreenPtr screen)
if (cursor)
{
- void *src = dixLookupPrivate(&cursor->devPrivates, CursorScreenKey(screen));
+ void *src = dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey, screen);
#ifdef ARGB_CURSOR
if (cursor->bits->argb && cursor_info->LoadCursorARGB)
(*cursor_info->LoadCursorARGB) (scrn, cursor);
diff --git a/xorg-server/hw/xfree86/modes/xf86Modes.c b/xorg-server/hw/xfree86/modes/xf86Modes.c
index 45308f484..dcd3a2805 100644
--- a/xorg-server/hw/xfree86/modes/xf86Modes.c
+++ b/xorg-server/hw/xfree86/modes/xf86Modes.c
@@ -1,730 +1,771 @@
-/*
- * 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;
-
-/**
- * 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);
-
- XNFasprintf(&mode->name, "%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);
-}
-
-/**
- * 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;
-
- if (maxPitch <= 0)
- maxPitch = MAXINT;
- if (maxX <= 0)
- maxX = MAXINT;
- if (maxY <= 0)
- maxY = MAXINT;
-
- for (mode = modeList; mode != NULL; mode = mode->next) {
- if ((xf86ModeWidth(mode, RR_Rotate_0) > maxPitch ||
- xf86ModeWidth(mode, RR_Rotate_0) > maxX ||
- xf86ModeHeight(mode, RR_Rotate_0) > maxY) &&
- (xf86ModeWidth(mode, RR_Rotate_90) > maxPitch ||
- xf86ModeWidth(mode, RR_Rotate_90) > maxX ||
- xf86ModeHeight(mode, RR_Rotate_90) > maxY)) {
- if (xf86ModeWidth(mode, RR_Rotate_0) > maxPitch ||
- xf86ModeWidth(mode, RR_Rotate_90) > maxPitch)
- mode->status = MODE_BAD_WIDTH;
-
- if (xf86ModeWidth(mode, RR_Rotate_0) > maxX ||
- xf86ModeWidth(mode, RR_Rotate_90) > maxX)
- mode->status = MODE_VIRTUAL_X;
-
- if (xf86ModeHeight(mode, RR_Rotate_0) > maxY ||
- xf86ModeHeight(mode, RR_Rotate_90) > 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)
- mode->status = MODE_BANDWIDTH;
- }
-}
-
-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;
-}
+/*
+ * 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;
+
+/**
+ * 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);
+
+ XNFasprintf(&mode->name, "%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.
+ *
+ * The mode type bits are informational except for the capitalized U
+ * and P bits which give sort order priority. Letter map:
+ *
+ * USERPREF, U, user preferred is set from the xorg.conf Monitor
+ * Option "PreferredMode" or from the Screen Display Modes statement.
+ * This unique modeline is moved to the head of the list after sorting.
+ *
+ * DRIVER, e, is set by the video driver, EDID or flat panel native.
+ *
+ * USERDEF, z, a configured zoom mode Ctrl+Alt+Keypad-{Plus,Minus}.
+ *
+ * DEFAULT, d, a compiled-in default.
+ *
+ * PREFERRED, P, driver preferred is set by the video device driver,
+ * e.g. the EDID detailed timing modeline. This is a true sort
+ * priority and multiple P modes form a sorted sublist at the list
+ * head.
+ *
+ * BUILTIN, b, a hardware fixed CRTC mode.
+ *
+ * See modes/xf86Crtc.c: xf86ProbeOutputModes().
+ */
+void
+xf86PrintModeline(int scrnIndex, DisplayModePtr mode)
+{
+ char tmp[256];
+ char *flags = xnfcalloc(1, 1);
+#define TBITS 6
+ const char tchar[TBITS+1] = "UezdPb";
+ int tbit[TBITS] = {
+ M_T_USERPREF, M_T_DRIVER, M_T_USERDEF,
+ M_T_DEFAULT, M_T_PREFERRED, M_T_BUILTIN
+ };
+ char type[TBITS+2]; /* +1 for leading space */
+#undef TBITS
+ int tlen = 0;
+
+ if (mode->type) {
+ int i;
+
+ type[tlen++] = ' ';
+ for (i = 0; tchar[i]; i++)
+ if (mode->type & tbit[i])
+ type[tlen++] = tchar[i];
+ }
+ type[tlen] = '\0';
+
+ 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%s)\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), type);
+ free(flags);
+}
+
+/**
+ * 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;
+
+ if (maxPitch <= 0)
+ maxPitch = MAXINT;
+ if (maxX <= 0)
+ maxX = MAXINT;
+ if (maxY <= 0)
+ maxY = MAXINT;
+
+ for (mode = modeList; mode != NULL; mode = mode->next) {
+ if ((xf86ModeWidth(mode, RR_Rotate_0) > maxPitch ||
+ xf86ModeWidth(mode, RR_Rotate_0) > maxX ||
+ xf86ModeHeight(mode, RR_Rotate_0) > maxY) &&
+ (xf86ModeWidth(mode, RR_Rotate_90) > maxPitch ||
+ xf86ModeWidth(mode, RR_Rotate_90) > maxX ||
+ xf86ModeHeight(mode, RR_Rotate_90) > maxY)) {
+ if (xf86ModeWidth(mode, RR_Rotate_0) > maxPitch ||
+ xf86ModeWidth(mode, RR_Rotate_90) > maxPitch)
+ mode->status = MODE_BAD_WIDTH;
+
+ if (xf86ModeWidth(mode, RR_Rotate_0) > maxX ||
+ xf86ModeWidth(mode, RR_Rotate_90) > maxX)
+ mode->status = MODE_VIRTUAL_X;
+
+ if (xf86ModeHeight(mode, RR_Rotate_0) > maxY ||
+ xf86ModeHeight(mode, RR_Rotate_90) > 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)
+ mode->status = MODE_BANDWIDTH;
+ }
+}
+
+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/os-support/bsd/bsd_init.c b/xorg-server/hw/xfree86/os-support/bsd/bsd_init.c
index 123eb17d1..837a2f4d1 100644
--- a/xorg-server/hw/xfree86/os-support/bsd/bsd_init.c
+++ b/xorg-server/hw/xfree86/os-support/bsd/bsd_init.c
@@ -45,7 +45,6 @@ static int devConsoleFd = -1;
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
static int VTnum = -1;
static int initialVT = -1;
-static Bool ShareVTs = FALSE;
#endif
#ifdef PCCONS_SUPPORT
@@ -266,7 +265,7 @@ xf86OpenConsole()
}
#endif
acquire_vt:
- if (!ShareVTs) {
+ if (!xf86Info.ShareVTs) {
/*
* now get the VT
*/
@@ -304,7 +303,7 @@ acquire_vt:
{
FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed");
}
- } else { /* ShareVTs */
+ } else { /* xf86Info.ShareVTs */
close(xf86Info.consoleFd);
}
break;
@@ -320,7 +319,8 @@ acquire_vt:
{
/* serverGeneration != 1 */
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
- if (!ShareVTs) if (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT)
+ if (!xf86Info.ShareVTs &&
+ (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT))
{
if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
{
@@ -393,7 +393,7 @@ xf86OpenSyscons()
if (ioctl(fd, VT_GETACTIVE, &initialVT) < 0)
initialVT = -1;
#endif
- if (ShareVTs)
+ if (xf86Info.ShareVTs)
xf86Info.vtno = initialVT;
if (xf86Info.vtno == -1)
@@ -655,7 +655,7 @@ xf86CloseConsole()
struct vt_mode VT;
#endif
- if (ShareVTs) return;
+ if (xf86Info.ShareVTs) return;
switch (xf86Info.consType)
{
@@ -723,11 +723,6 @@ xf86ProcessArgument(int argc, char *argv[], int i)
return 1;
}
#if defined (SYSCONS_SUPPORT) || defined (PCVT_SUPPORT)
- if (!strcmp(argv[i], "-sharevts"))
- {
- ShareVTs = TRUE;
- return 1;
- }
if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
{
if (sscanf(argv[i], "vt%2d", &VTnum) == 0 ||
diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
index 77dfb2f16..9c9174034 100644
--- a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
+++ b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
@@ -39,8 +39,6 @@
#include <sys/stat.h>
static Bool KeepTty = FALSE;
-static Bool VTSwitch = TRUE;
-static Bool ShareVTs = FALSE;
static int activeVT = -1;
static char vtname[11];
@@ -109,7 +107,7 @@ xf86OpenConsole(void)
"xf86OpenConsole: Cannot open /dev/tty0 (%s)\n",
strerror(errno));
- if (ShareVTs)
+ if (xf86Info.ShareVTs)
{
SYSCALL(ret = ioctl(fd, VT_GETSTATE, &vts));
if (ret < 0)
@@ -184,7 +182,7 @@ xf86OpenConsole(void)
}
#endif
- if (!ShareVTs)
+ if (!xf86Info.ShareVTs)
{
struct termios nTty;
@@ -240,7 +238,7 @@ xf86OpenConsole(void)
* of Init?$#*&Device(). So I just place it here */
}
} else { /* serverGeneration != 1 */
- if (!ShareVTs && VTSwitch)
+ if (!xf86Info.ShareVTs && xf86Info.autoVTSwitch)
{
/* now get the VT */
switch_to(xf86Info.vtno, "xf86OpenConsole");
@@ -254,7 +252,7 @@ xf86CloseConsole(void)
struct vt_mode VT;
int ret;
- if (ShareVTs) {
+ if (xf86Info.ShareVTs) {
close(xf86Info.consoleFd);
return;
}
@@ -286,7 +284,7 @@ xf86CloseConsole(void)
strerror(errno));
}
- if (VTSwitch)
+ if (xf86Info.autoVTSwitch)
{
/*
* Perform a switch back to the active VT when we were started
@@ -311,16 +309,7 @@ xf86ProcessArgument(int argc, char *argv[], int i)
KeepTty = TRUE;
return 1;
}
- if (!strcmp(argv[i], "-novtswitch"))
- {
- VTSwitch = FALSE;
- return 1;
- }
- if (!strcmp(argv[i], "-sharevts"))
- {
- ShareVTs = TRUE;
- return 1;
- }
+
if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
{
if (sscanf(argv[i], "vt%2d", &xf86Info.vtno) == 0)
@@ -340,6 +329,4 @@ xf86UseMsg(void)
ErrorF("vtXX use the specified VT number\n");
ErrorF("-keeptty ");
ErrorF("don't detach controlling tty (for debugging only)\n");
- ErrorF("-novtswitch don't immediately switch to new VT\n");
- ErrorF("-sharevts share VTs with another X server\n");
}
diff --git a/xorg-server/hw/xfree86/os-support/solaris/sun_init.c b/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
index ae9adee4b..800fc1c3d 100644
--- a/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
+++ b/xorg-server/hw/xfree86/os-support/solaris/sun_init.c
@@ -1,424 +1,442 @@
-/*
- * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
- * Copyright 1993 by David Wexelblat <dwex@goblin.org>
- * Copyright 1999 by David Holland <davidh@iquest.net>
- *
- * 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 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, AND 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>
-#endif
-
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-#ifdef HAVE_SYS_KD_H
-# include <sys/kd.h>
-#endif
-
-/*
- * Applications see VT number as consecutive integers starting from 1.
- * VT number VT device
- * -------------------------------------------------------
- * 1 : /dev/vt/0 (Alt + Ctrl + F1)
- * 2 : /dev/vt/2 (Alt + Ctrl + F2)
- * 3 : /dev/vt/3 (Alt + Ctrl + F3)
- * ... ...
- */
-#define CONSOLE_VTNO 1
-#define SOL_CONSOLE_DEV "/dev/console"
-
-static Bool KeepTty = FALSE;
-static Bool Protect0 = FALSE;
-static Bool UseConsole = FALSE;
-#ifdef HAS_USL_VTS
-static int VTnum = -1;
-static int xf86StartVT = -1;
-static int vtEnabled = 0;
-extern void xf86VTAcquire(int);
-extern void xf86VTRelease(int);
-#endif
-
-/* Device to open as xf86Info.consoleFd */
-static char consoleDev[PATH_MAX] = "/dev/fb";
-
-/* Set by -dev argument on CLI
- Used by hw/xfree86/common/xf86AutoConfig.c for VIS_GETIDENTIFIER */
-_X_HIDDEN char xf86SolarisFbDev[PATH_MAX] = "/dev/fb";
-
-void
-xf86OpenConsole(void)
-{
- int i;
-#ifdef HAS_USL_VTS
- int fd;
- struct vt_mode VT;
- struct vt_stat vtinfo;
- MessageType from = X_PROBED;
-#endif
-
- if (serverGeneration == 1)
- {
- /* Check if we're run with euid==0 */
- if (geteuid() != 0)
- FatalError("xf86OpenConsole: Server must be suid root\n");
-
- /* Protect page 0 to help find NULL dereferencing */
- /* mprotect() doesn't seem to work */
- if (Protect0)
- {
- int fd = -1;
-
- if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0)
- {
- xf86Msg(X_WARNING,
- "xf86OpenConsole: cannot open /dev/zero (%s)\n",
- strerror(errno));
- }
- else
- {
- if (mmap(0, 0x1000, PROT_NONE,
- MAP_FIXED | MAP_SHARED, fd, 0) == MAP_FAILED)
- xf86Msg(X_WARNING,
- "xf86OpenConsole: failed to protect page 0 (%s)\n",
- strerror(errno));
-
- close(fd);
- }
- }
-
-#ifdef HAS_USL_VTS
-
- /*
- * Setup the virtual terminal manager
- */
- if ((fd = open("/dev/vt/0",O_RDWR,0)) == -1)
- {
- xf86ErrorF("xf86OpenConsole: Cannot open /dev/vt/0 (%s)\n",
- strerror(errno));
- vtEnabled = 0;
- }
- else
- {
- if (ioctl(fd, VT_ENABLED, &vtEnabled) < 0)
- {
- xf86ErrorF("xf86OpenConsole: VT_ENABLED failed (%s)\n",
- strerror(errno));
- vtEnabled = 0;
- }
- }
-#endif /* HAS_USL_VTS */
-
- if (UseConsole)
- {
- strlcpy(consoleDev, SOL_CONSOLE_DEV, sizeof(consoleDev));
-
-#ifdef HAS_USL_VTS
- xf86Info.vtno = CONSOLE_VTNO;
-
- if (vtEnabled == 0)
- {
- xf86StartVT = 0;
- }
- else
- {
- if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0)
- FatalError("xf86OpenConsole: Cannot determine current VT\n");
- xf86StartVT = vtinfo.v_active;
- }
-#endif /* HAS_USL_VTS */
- goto OPENCONSOLE;
- }
-
-#ifdef HAS_USL_VTS
- if (vtEnabled == 0)
- {
- /* VT not enabled - kernel too old or Sparc platforms
- without visual_io support */
- xf86Msg(from, "VT infrastructure is not available\n");
-
- xf86StartVT = 0;
- xf86Info.vtno = 0;
- strlcpy(consoleDev, xf86SolarisFbDev, sizeof(consoleDev));
- goto OPENCONSOLE;
- }
-
- if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0)
- FatalError("xf86OpenConsole: Cannot determine current VT\n");
-
- xf86StartVT = vtinfo.v_active;
-
- if (VTnum != -1)
- {
- xf86Info.vtno = VTnum;
- from = X_CMDLINE;
- }
- else
- {
- if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
- (xf86Info.vtno == -1))
- {
- FatalError("xf86OpenConsole: Cannot find a free VT\n");
- }
- }
-
- xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
- snprintf(consoleDev, PATH_MAX, "/dev/vt/%d", xf86Info.vtno);
-
- if (fd != -1)
- {
- close(fd);
- }
-
-#endif /* HAS_USL_VTS */
-
-OPENCONSOLE:
- if (!KeepTty)
- setpgrp();
-
- if (((xf86Info.consoleFd = open(consoleDev, O_RDWR | O_NDELAY, 0)) < 0))
- FatalError("xf86OpenConsole: Cannot open %s (%s)\n",
- consoleDev, strerror(errno));
-
- /* Change ownership of the vt or console */
- chown(consoleDev, getuid(), getgid());
-
-#ifdef HAS_USL_VTS
- if (vtEnabled)
- {
- /*
- * Now get the VT
- */
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
-
- if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
-
-#ifdef VT_SET_CONSUSER /* added in snv_139 */
- if (strcmp(display, "0") == 0)
- if (ioctl(xf86Info.consoleFd, VT_SET_CONSUSER) != 0)
- xf86Msg(X_WARNING,
- "xf86OpenConsole: VT_SET_CONSUSER failed\n");
-#endif
-
- if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
- FatalError("xf86OpenConsole: VT_GETMODE failed\n");
-
- OsSignal(SIGUSR1, xf86VTAcquire);
- OsSignal(SIGUSR2, xf86VTRelease);
-
- VT.mode = VT_PROCESS;
- VT.acqsig = SIGUSR1;
- VT.relsig = SIGUSR2;
-
- if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
- FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n");
-
- if (ioctl(xf86Info.consoleFd, VT_SETDISPINFO, atoi(display)) < 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_SETDISPINFO failed\n");
- }
-#endif
-
-#ifdef KDSETMODE
- SYSCALL(i = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS));
- if (i < 0) {
- xf86Msg(X_WARNING,
- "xf86OpenConsole: KDSETMODE KD_GRAPHICS failed on %s (%s)\n",
- consoleDev, strerror(errno));
- }
-#endif
- }
- else /* serverGeneration != 1 */
- {
-#ifdef HAS_USL_VTS
- if (vtEnabled)
- {
- /*
- * Now re-get the VT
- */
- if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) != 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed\n");
-
- if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) != 0)
- xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed\n");
-
-#ifdef VT_SET_CONSUSER /* added in snv_139 */
- if (strcmp(display, "0") == 0)
- if (ioctl(xf86Info.consoleFd, VT_SET_CONSUSER) != 0)
- xf86Msg(X_WARNING,
- "xf86OpenConsole: VT_SET_CONSUSER failed\n");
-#endif
-
- /*
- * If the server doesn't have the VT when the reset occurs,
- * this is to make sure we don't continue until the activate
- * signal is received.
- */
- if (!xf86Screens[0]->vtSema)
- sleep(5);
- }
-#endif /* HAS_USL_VTS */
-
- }
-}
-
-void
-xf86CloseConsole(void)
-{
-#ifdef HAS_USL_VTS
- struct vt_mode VT;
-#endif
-
-#if !defined(__i386__) && !defined(__i386) && !defined(__x86)
-
- if (!xf86DoConfigure) {
- int fd;
-
- /*
- * Wipe out framebuffer just like the non-SI Xsun server does. This
- * could be improved by saving framebuffer contents in
- * xf86OpenConsole() above and restoring them here. Also, it's unclear
- * at this point whether this should be done for all framebuffers in
- * the system, rather than only the console.
- */
- if ((fd = open(xf86SolarisFbDev, O_RDWR, 0)) < 0) {
- xf86Msg(X_WARNING,
- "xf86CloseConsole(): unable to open framebuffer (%s)\n",
- strerror(errno));
- } else {
- struct fbgattr fbattr;
-
- if ((ioctl(fd, FBIOGATTR, &fbattr) < 0) &&
- (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0)) {
- xf86Msg(X_WARNING,
- "xf86CloseConsole(): unable to retrieve framebuffer"
- " attributes (%s)\n", strerror(errno));
- } else {
- pointer fbdata;
-
- fbdata = mmap(NULL, fbattr.fbtype.fb_size,
- PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (fbdata == MAP_FAILED) {
- xf86Msg(X_WARNING,
- "xf86CloseConsole(): unable to mmap framebuffer"
- " (%s)\n", strerror(errno));
- } else {
- memset(fbdata, 0, fbattr.fbtype.fb_size);
- munmap(fbdata, fbattr.fbtype.fb_size);
- }
- }
-
- close(fd);
- }
- }
-
-#endif
-
-#ifdef KDSETMODE
- /* Reset the display back to text mode */
- SYSCALL(ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT));
-#endif
-
-#ifdef HAS_USL_VTS
- if (vtEnabled)
- {
- if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
- {
- VT.mode = VT_AUTO; /* Set default vt handling */
- ioctl(xf86Info.consoleFd, VT_SETMODE, &VT);
- }
-
- /* Activate the VT that X was started on */
- ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86StartVT);
- }
-#endif /* HAS_USL_VTS */
-
- close(xf86Info.consoleFd);
-}
-
-int
-xf86ProcessArgument(int argc, char **argv, int i)
-{
- /*
- * Keep server from detaching from controlling tty. This is useful when
- * debugging, so the server can receive keyboard signals.
- */
- if (!strcmp(argv[i], "-keeptty"))
- {
- KeepTty = TRUE;
- return 1;
- }
-
- /*
- * Undocumented flag to protect page 0 from read/write to help catch NULL
- * pointer dereferences. This is purely a debugging flag.
- */
- if (!strcmp(argv[i], "-protect0"))
- {
- Protect0 = TRUE;
- return 1;
- }
-
- /*
- * Use /dev/console as the console device.
- */
- if (!strcmp(argv[i], "-C"))
- {
- UseConsole = TRUE;
- return 1;
- }
-
-#ifdef HAS_USL_VTS
-
- if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
- {
- if (sscanf(argv[i], "vt%d", &VTnum) == 0)
- {
- UseMsg();
- VTnum = -1;
- return 0;
- }
-
- return 1;
- }
-
-#endif /* HAS_USL_VTS */
-
- if ((i + 1) < argc) {
- if (!strcmp(argv[i], "-dev")) {
- strlcpy(xf86SolarisFbDev, argv[i+1], sizeof(xf86SolarisFbDev));
- return 2;
- }
- }
-
- return 0;
-}
-
-void xf86UseMsg(void)
-{
-#ifdef HAS_USL_VTS
- ErrorF("vtX Use the specified VT number\n");
-#endif
- ErrorF("-dev <fb> Framebuffer device\n");
- ErrorF("-keeptty Don't detach controlling tty\n");
- ErrorF(" (for debugging only)\n");
- ErrorF("-C Use /dev/console as the console device\n");
-}
+/*
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany
+ * Copyright 1993 by David Wexelblat <dwex@goblin.org>
+ * Copyright 1999 by David Holland <davidh@iquest.net>
+ *
+ * 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 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, AND 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>
+#endif
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+#ifdef HAVE_SYS_KD_H
+# include <sys/kd.h>
+#endif
+
+/*
+ * Applications see VT number as consecutive integers starting from 1.
+ * VT number VT device
+ * -------------------------------------------------------
+ * 1 : /dev/vt/0 (Alt + Ctrl + F1)
+ * 2 : /dev/vt/2 (Alt + Ctrl + F2)
+ * 3 : /dev/vt/3 (Alt + Ctrl + F3)
+ * ... ...
+ */
+#define CONSOLE_VTNO 1
+#define SOL_CONSOLE_DEV "/dev/console"
+
+static Bool KeepTty = FALSE;
+static Bool Protect0 = FALSE;
+static Bool UseConsole = FALSE;
+#ifdef HAS_USL_VTS
+static int VTnum = -1;
+static int xf86StartVT = -1;
+static int vtEnabled = 0;
+extern void xf86VTAcquire(int);
+extern void xf86VTRelease(int);
+#endif
+
+/* Device to open as xf86Info.consoleFd */
+static char consoleDev[PATH_MAX] = "/dev/fb";
+
+/* Set by -dev argument on CLI
+ Used by hw/xfree86/common/xf86AutoConfig.c for VIS_GETIDENTIFIER */
+_X_HIDDEN char xf86SolarisFbDev[PATH_MAX] = "/dev/fb";
+
+static void
+switch_to(int vt, const char *from)
+{
+ int ret;
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_ACTIVATE, vt));
+ if (ret != 0)
+ xf86Msg(X_WARNING, "%s: VT_ACTIVATE failed: %s\n",
+ from, strerror(errno));
+
+ SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_WAITACTIVE, vt));
+ if (ret != 0)
+ xf86Msg(X_WARNING, "%s: VT_WAITACTIVE failed: %s\n",
+ from, strerror(errno));
+}
+
+void
+xf86OpenConsole(void)
+{
+ int i;
+#ifdef HAS_USL_VTS
+ int fd;
+ struct vt_mode VT;
+ struct vt_stat vtinfo;
+ MessageType from = X_PROBED;
+#endif
+
+ if (serverGeneration == 1)
+ {
+ /* Check if we're run with euid==0 */
+ if (geteuid() != 0)
+ FatalError("xf86OpenConsole: Server must be suid root\n");
+
+ /* Protect page 0 to help find NULL dereferencing */
+ /* mprotect() doesn't seem to work */
+ if (Protect0)
+ {
+ int fd = -1;
+
+ if ((fd = open("/dev/zero", O_RDONLY, 0)) < 0)
+ {
+ xf86Msg(X_WARNING,
+ "xf86OpenConsole: cannot open /dev/zero (%s)\n",
+ strerror(errno));
+ }
+ else
+ {
+ if (mmap(0, 0x1000, PROT_NONE,
+ MAP_FIXED | MAP_SHARED, fd, 0) == MAP_FAILED)
+ xf86Msg(X_WARNING,
+ "xf86OpenConsole: failed to protect page 0 (%s)\n",
+ strerror(errno));
+
+ close(fd);
+ }
+ }
+
+#ifdef HAS_USL_VTS
+
+ /*
+ * Setup the virtual terminal manager
+ */
+ if ((fd = open("/dev/vt/0",O_RDWR,0)) == -1)
+ {
+ xf86ErrorF("xf86OpenConsole: Cannot open /dev/vt/0 (%s)\n",
+ strerror(errno));
+ vtEnabled = 0;
+ }
+ else
+ {
+ if (ioctl(fd, VT_ENABLED, &vtEnabled) < 0)
+ {
+ xf86ErrorF("xf86OpenConsole: VT_ENABLED failed (%s)\n",
+ strerror(errno));
+ vtEnabled = 0;
+ }
+ }
+#endif /* HAS_USL_VTS */
+
+ if (UseConsole)
+ {
+ strlcpy(consoleDev, SOL_CONSOLE_DEV, sizeof(consoleDev));
+
+#ifdef HAS_USL_VTS
+ xf86Info.vtno = CONSOLE_VTNO;
+
+ if (vtEnabled == 0)
+ {
+ xf86StartVT = 0;
+ }
+ else
+ {
+ if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0)
+ FatalError("xf86OpenConsole: Cannot determine current VT\n");
+ xf86StartVT = vtinfo.v_active;
+ }
+#endif /* HAS_USL_VTS */
+ goto OPENCONSOLE;
+ }
+
+#ifdef HAS_USL_VTS
+ if (vtEnabled == 0)
+ {
+ /* VT not enabled - kernel too old or Sparc platforms
+ without visual_io support */
+ xf86Msg(from, "VT infrastructure is not available\n");
+
+ xf86StartVT = 0;
+ xf86Info.vtno = 0;
+ strlcpy(consoleDev, xf86SolarisFbDev, sizeof(consoleDev));
+ goto OPENCONSOLE;
+ }
+
+ if (ioctl(fd, VT_GETSTATE, &vtinfo) < 0)
+ FatalError("xf86OpenConsole: Cannot determine current VT\n");
+
+ xf86StartVT = vtinfo.v_active;
+
+ if (VTnum != -1)
+ {
+ xf86Info.vtno = VTnum;
+ from = X_CMDLINE;
+ }
+ else if (xf86Info.ShareVTs)
+ {
+ xf86Info.vtno = vtinfo.v_active;
+ from = X_CMDLINE;
+ }
+ else
+ {
+ if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) ||
+ (xf86Info.vtno == -1))
+ {
+ FatalError("xf86OpenConsole: Cannot find a free VT\n");
+ }
+ }
+
+ xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
+ snprintf(consoleDev, PATH_MAX, "/dev/vt/%d", xf86Info.vtno);
+
+ if (fd != -1)
+ {
+ close(fd);
+ }
+
+#endif /* HAS_USL_VTS */
+
+OPENCONSOLE:
+ if (!KeepTty)
+ setpgrp();
+
+ if (((xf86Info.consoleFd = open(consoleDev, O_RDWR | O_NDELAY, 0)) < 0))
+ FatalError("xf86OpenConsole: Cannot open %s (%s)\n",
+ consoleDev, strerror(errno));
+
+ /* Change ownership of the vt or console */
+ chown(consoleDev, getuid(), getgid());
+
+#ifdef HAS_USL_VTS
+ if (xf86Info.ShareVTs)
+ return;
+
+ if (vtEnabled)
+ {
+ /*
+ * Now get the VT
+ */
+ switch_to(xf86Info.vtno, "xf86OpenConsole");
+
+#ifdef VT_SET_CONSUSER /* added in snv_139 */
+ if (strcmp(display, "0") == 0)
+ if (ioctl(xf86Info.consoleFd, VT_SET_CONSUSER) != 0)
+ xf86Msg(X_WARNING,
+ "xf86OpenConsole: VT_SET_CONSUSER failed\n");
+#endif
+
+ if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0)
+ FatalError("xf86OpenConsole: VT_GETMODE failed\n");
+
+ OsSignal(SIGUSR1, xf86VTAcquire);
+ OsSignal(SIGUSR2, xf86VTRelease);
+
+ VT.mode = VT_PROCESS;
+ VT.acqsig = SIGUSR1;
+ VT.relsig = SIGUSR2;
+
+ if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0)
+ FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed\n");
+
+ if (ioctl(xf86Info.consoleFd, VT_SETDISPINFO, atoi(display)) < 0)
+ xf86Msg(X_WARNING, "xf86OpenConsole: VT_SETDISPINFO failed\n");
+ }
+#endif
+
+#ifdef KDSETMODE
+ SYSCALL(i = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS));
+ if (i < 0) {
+ xf86Msg(X_WARNING,
+ "xf86OpenConsole: KDSETMODE KD_GRAPHICS failed on %s (%s)\n",
+ consoleDev, strerror(errno));
+ }
+#endif
+ }
+ else /* serverGeneration != 1 */
+ {
+#ifdef HAS_USL_VTS
+ if (vtEnabled && !xf86Info.ShareVTs)
+ {
+ /*
+ * Now re-get the VT
+ */
+ if (xf86Info.autoVTSwitch)
+ switch_to(xf86Info.vtno, "xf86OpenConsole");
+
+#ifdef VT_SET_CONSUSER /* added in snv_139 */
+ if (strcmp(display, "0") == 0)
+ if (ioctl(xf86Info.consoleFd, VT_SET_CONSUSER) != 0)
+ xf86Msg(X_WARNING,
+ "xf86OpenConsole: VT_SET_CONSUSER failed\n");
+#endif
+
+ /*
+ * If the server doesn't have the VT when the reset occurs,
+ * this is to make sure we don't continue until the activate
+ * signal is received.
+ */
+ if (!xf86Screens[0]->vtSema)
+ sleep(5);
+ }
+#endif /* HAS_USL_VTS */
+
+ }
+}
+
+void
+xf86CloseConsole(void)
+{
+#ifdef HAS_USL_VTS
+ struct vt_mode VT;
+#endif
+
+#if !defined(__i386__) && !defined(__i386) && !defined(__x86)
+
+ if (!xf86DoConfigure) {
+ int fd;
+
+ /*
+ * Wipe out framebuffer just like the non-SI Xsun server does. This
+ * could be improved by saving framebuffer contents in
+ * xf86OpenConsole() above and restoring them here. Also, it's unclear
+ * at this point whether this should be done for all framebuffers in
+ * the system, rather than only the console.
+ */
+ if ((fd = open(xf86SolarisFbDev, O_RDWR, 0)) < 0) {
+ xf86Msg(X_WARNING,
+ "xf86CloseConsole(): unable to open framebuffer (%s)\n",
+ strerror(errno));
+ } else {
+ struct fbgattr fbattr;
+
+ if ((ioctl(fd, FBIOGATTR, &fbattr) < 0) &&
+ (ioctl(fd, FBIOGTYPE, &fbattr.fbtype) < 0)) {
+ xf86Msg(X_WARNING,
+ "xf86CloseConsole(): unable to retrieve framebuffer"
+ " attributes (%s)\n", strerror(errno));
+ } else {
+ pointer fbdata;
+
+ fbdata = mmap(NULL, fbattr.fbtype.fb_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (fbdata == MAP_FAILED) {
+ xf86Msg(X_WARNING,
+ "xf86CloseConsole(): unable to mmap framebuffer"
+ " (%s)\n", strerror(errno));
+ } else {
+ memset(fbdata, 0, fbattr.fbtype.fb_size);
+ munmap(fbdata, fbattr.fbtype.fb_size);
+ }
+ }
+
+ close(fd);
+ }
+ }
+
+#endif
+
+#ifdef KDSETMODE
+ /* Reset the display back to text mode */
+ SYSCALL(ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT));
+#endif
+
+#ifdef HAS_USL_VTS
+ if (vtEnabled)
+ {
+ if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) != -1)
+ {
+ VT.mode = VT_AUTO; /* Set default vt handling */
+ ioctl(xf86Info.consoleFd, VT_SETMODE, &VT);
+ }
+
+ /* Activate the VT that X was started on */
+ if (xf86Info.autoVTSwitch)
+ switch_to(xf86StartVT, "xf86CloseConsole");
+ }
+#endif /* HAS_USL_VTS */
+
+ close(xf86Info.consoleFd);
+}
+
+int
+xf86ProcessArgument(int argc, char **argv, int i)
+{
+ /*
+ * Keep server from detaching from controlling tty. This is useful when
+ * debugging, so the server can receive keyboard signals.
+ */
+ if (!strcmp(argv[i], "-keeptty"))
+ {
+ KeepTty = TRUE;
+ return 1;
+ }
+
+ /*
+ * Undocumented flag to protect page 0 from read/write to help catch NULL
+ * pointer dereferences. This is purely a debugging flag.
+ */
+ if (!strcmp(argv[i], "-protect0"))
+ {
+ Protect0 = TRUE;
+ return 1;
+ }
+
+ /*
+ * Use /dev/console as the console device.
+ */
+ if (!strcmp(argv[i], "-C"))
+ {
+ UseConsole = TRUE;
+ return 1;
+ }
+
+#ifdef HAS_USL_VTS
+
+ if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
+ {
+ if (sscanf(argv[i], "vt%d", &VTnum) == 0)
+ {
+ UseMsg();
+ VTnum = -1;
+ return 0;
+ }
+
+ return 1;
+ }
+
+#endif /* HAS_USL_VTS */
+
+ if ((i + 1) < argc) {
+ if (!strcmp(argv[i], "-dev")) {
+ strlcpy(xf86SolarisFbDev, argv[i+1], sizeof(xf86SolarisFbDev));
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+void xf86UseMsg(void)
+{
+#ifdef HAS_USL_VTS
+ ErrorF("vtX Use the specified VT number\n");
+#endif
+ ErrorF("-dev <fb> Framebuffer device\n");
+ ErrorF("-keeptty Don't detach controlling tty\n");
+ ErrorF(" (for debugging only)\n");
+ ErrorF("-C Use /dev/console as the console device\n");
+}
diff --git a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c
index 24c91cc37..1e0f7e0b7 100644
--- a/xorg-server/hw/xfree86/ramdac/xf86Cursor.c
+++ b/xorg-server/hw/xfree86/ramdac/xf86Cursor.c
@@ -273,7 +273,7 @@ xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
&pScreen->devPrivates, xf86CursorScreenKey);
if (pCurs->refcnt <= 1)
- dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL);
+ dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, NULL);
return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs);
}
@@ -286,8 +286,8 @@ xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
&pScreen->devPrivates, xf86CursorScreenKey);
if (pCurs->refcnt <= 1) {
- free(dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen)));
- dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL);
+ free(dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen));
+ dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, NULL);
}
return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs);
diff --git a/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c b/xorg-server/hw/xfree86/ramdac/xf86HWCurs.c
index 43f28ef8e..f9b09fc9a 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 = 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;
-}
+
+#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 = dixLookupScreenPrivate(&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);
+ dixSetScreenPrivate(&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/utils/man/cvt.man b/xorg-server/hw/xfree86/utils/man/cvt.man
index b380171ee..f5075f5bf 100644
--- a/xorg-server/hw/xfree86/utils/man/cvt.man
+++ b/xorg-server/hw/xfree86/utils/man/cvt.man
@@ -1,4 +1,3 @@
-.\" $XFree86$
.TH CVT 1 __vendorversion__
.SH NAME
cvt - calculate VESA CVT mode lines
@@ -32,7 +31,7 @@ Create a mode with reduced blanking. This allows for higher frequency signals,
with a lower or equal dotclock. Not for Cathode Ray Tube based displays though.
.SH "SEE ALSO"
-__xconfigfile__(__filemansuffix__)
+__xconfigfile__(__filemansuffix__), gtf(__appmansuffix__)
.SH AUTHOR
Luc Verhaegen.
.PP
diff --git a/xorg-server/hw/xfree86/utils/man/gtf.man b/xorg-server/hw/xfree86/utils/man/gtf.man
index 74ade74cb..8e83650aa 100644
--- a/xorg-server/hw/xfree86/utils/man/gtf.man
+++ b/xorg-server/hw/xfree86/utils/man/gtf.man
@@ -1,4 +1,3 @@
-.\" $XFree86$
.TH GTF 1 __vendorversion__
.SH NAME
gtf - calculate VESA GTF mode lines
@@ -35,7 +34,7 @@ default format.
Print the mode parameters in a format suitable for
.BR fbset(8) .
.SH "SEE ALSO"
-__xconfigfile__(__filemansuffix__)
+__xconfigfile__(__filemansuffix__), cvt(__appmansuffix__)
.SH AUTHOR
Andy Ritger.
.PP
diff --git a/xorg-server/hw/xfree86/x86emu/sys.c b/xorg-server/hw/xfree86/x86emu/sys.c
index 602b0bbee..f389767f1 100644
--- a/xorg-server/hw/xfree86/x86emu/sys.c
+++ b/xorg-server/hw/xfree86/x86emu/sys.c
@@ -49,7 +49,6 @@
#include <string.h>
#endif
-# ifndef NO_INLINE
# ifdef __GNUC__
/* Define some packed structures to use with unaligned accesses */
@@ -139,7 +138,6 @@ static __inline__ void stw_u(u16 val, u16 *p)
}
# endif /* __GNUC__ */
-# endif /* NO_INLINE */
/*------------------------- Global Variables ------------------------------*/
X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
diff --git a/xorg-server/hw/xnest/GC.c b/xorg-server/hw/xnest/GC.c
index 0aaef6904..48fe4dcbc 100644
--- a/xorg-server/hw/xnest/GC.c
+++ b/xorg-server/hw/xnest/GC.c
@@ -1,333 +1,330 @@
-/*
-
-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"
-
-DevPrivateKeyRec xnestGCPrivateKeyRec;
-
-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->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)
-{
-}
-
-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 = RegionNumRects((RegionPtr)pValue);
- size = nRects * sizeof(*pRects);
- pRects = (XRectangle *) malloc(size);
- pBox = RegionRects((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) RegionFromRects(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:
- RegionDestroy(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 = RegionCreate(NULL, 1);
- RegionCopy(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"
+
+DevPrivateKeyRec xnestGCPrivateKeyRec;
+
+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->funcs = &xnestFuncs;
+ pGC->ops = &xnestOps;
+
+ pGC->miTranslate = 1;
+
+ xnestGCPriv(pGC)->gc = XCreateGC(xnestDisplay,
+ xnestDefaultDrawables[pGC->depth],
+ 0L, NULL);
+
+ return True;
+}
+
+void
+xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+}
+
+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 = RegionNumRects((RegionPtr)pValue);
+ size = nRects * sizeof(*pRects);
+ pRects = (XRectangle *) malloc(size);
+ pBox = RegionRects((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) RegionFromRects(nRects,
+ (xRectangle *)pValue, type);
+ free(pValue);
+ pValue = pGC->clientClip;
+ type = CT_REGION;
+
+ break;
+ }
+
+ pGC->clientClipType = type;
+ pGC->clientClip = pValue;
+}
+
+void
+xnestDestroyClip(GCPtr pGC)
+{
+ xnestDestroyClipHelper(pGC);
+
+ XSetClipMask(xnestDisplay, xnestGC(pGC), None);
+
+ pGC->clientClipType = CT_NONE;
+ pGC->clientClip = NULL;
+}
+
+void
+xnestDestroyClipHelper(GCPtr pGC)
+{
+ switch (pGC->clientClipType)
+ {
+ default:
+ case CT_NONE:
+ break;
+
+ case CT_REGION:
+ RegionDestroy(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 = RegionCreate(NULL, 1);
+ RegionCopy(pRgn, pGCSrc->clientClip);
+ xnestChangeClip(pGCDst, CT_REGION, pRgn, 0);
+ break;
+ }
+}
diff --git a/xorg-server/hw/xnest/XNCursor.h b/xorg-server/hw/xnest/XNCursor.h
index c50b79d1d..473b2017f 100644
--- a/xorg-server/hw/xnest/XNCursor.h
+++ b/xorg-server/hw/xnest/XNCursor.h
@@ -1,59 +1,59 @@
-/*
-
-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.
-
-*/
-
-#ifndef XNESTCURSOR_H
-#define XNESTCURSOR_H
-
-#include "mipointrst.h"
-
-typedef struct {
- miPointerSpriteFuncPtr spriteFuncs;
-} xnestCursorFuncRec, *xnestCursorFuncPtr;
-
-extern DevPrivateKeyRec xnestCursorScreenKeyRec;
-#define xnestCursorScreenKey (&xnestCursorScreenKeyRec)
-extern xnestCursorFuncRec xnestCursorFuncs;
-
-typedef struct {
- Cursor cursor;
-} xnestPrivCursor;
-
-#define xnestGetCursorPriv(pCursor, pScreen) ((xnestPrivCursor *) \
- dixLookupPrivate(&(pCursor)->devPrivates, CursorScreenKey(pScreen)))
-
-#define xnestSetCursorPriv(pCursor, pScreen, v) \
- dixSetPrivate(&(pCursor)->devPrivates, CursorScreenKey(pScreen), v)
-
-#define xnestCursor(pCursor, pScreen) \
- (xnestGetCursorPriv(pCursor, pScreen)->cursor)
-
-Bool xnestRealizeCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor);
-Bool xnestUnrealizeCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor);
-void xnestRecolorCursor(ScreenPtr pScreen,
- CursorPtr pCursor,
- Bool displayed);
-void xnestSetCursor (DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor,
- int x, int y);
-void xnestMoveCursor (DeviceIntPtr pDev,
- ScreenPtr pScreen,
- int x, int y);
-Bool xnestDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
-void xnestDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
-#endif /* XNESTCURSOR_H */
+/*
+
+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.
+
+*/
+
+#ifndef XNESTCURSOR_H
+#define XNESTCURSOR_H
+
+#include "mipointrst.h"
+
+typedef struct {
+ miPointerSpriteFuncPtr spriteFuncs;
+} xnestCursorFuncRec, *xnestCursorFuncPtr;
+
+extern DevPrivateKeyRec xnestCursorScreenKeyRec;
+#define xnestCursorScreenKey (&xnestCursorScreenKeyRec)
+extern xnestCursorFuncRec xnestCursorFuncs;
+
+typedef struct {
+ Cursor cursor;
+} xnestPrivCursor;
+
+#define xnestGetCursorPriv(pCursor, pScreen) ((xnestPrivCursor *) \
+ dixLookupScreenPrivate(&(pCursor)->devPrivates, CursorScreenKey, pScreen))
+
+#define xnestSetCursorPriv(pCursor, pScreen, v) \
+ dixSetScreenPrivate(&(pCursor)->devPrivates, CursorScreenKey, pScreen, v)
+
+#define xnestCursor(pCursor, pScreen) \
+ (xnestGetCursorPriv(pCursor, pScreen)->cursor)
+
+Bool xnestRealizeCursor(DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor);
+Bool xnestUnrealizeCursor(DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor);
+void xnestRecolorCursor(ScreenPtr pScreen,
+ CursorPtr pCursor,
+ Bool displayed);
+void xnestSetCursor (DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ CursorPtr pCursor,
+ int x, int y);
+void xnestMoveCursor (DeviceIntPtr pDev,
+ ScreenPtr pScreen,
+ int x, int y);
+Bool xnestDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
+void xnestDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
+#endif /* XNESTCURSOR_H */
diff --git a/xorg-server/hw/xnest/XNGC.h b/xorg-server/hw/xnest/XNGC.h
index 2eb89533d..c4a6cef77 100644
--- a/xorg-server/hw/xnest/XNGC.h
+++ b/xorg-server/hw/xnest/XNGC.h
@@ -1,43 +1,42 @@
-/*
-
-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.
-
-*/
-
-#ifndef XNESTGC_H
-#define XNESTGC_H
-
-/* This file uses the GC definition form Xlib.h as XlibGC. */
-
-typedef struct {
- XlibGC gc;
- int nClipRects;
-} xnestPrivGC;
-
-extern DevPrivateKeyRec xnestGCPrivateKeyRec;
-#define xnestGCPrivateKey (&xnestGCPrivateKeyRec)
-
-#define xnestGCPriv(pGC) ((xnestPrivGC *) \
- dixLookupPrivate(&(pGC)->devPrivates, xnestGCPrivateKey))
-
-#define xnestGC(pGC) (xnestGCPriv(pGC)->gc)
-
-Bool xnestCreateGC(GCPtr pGC);
-void xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable);
-void xnestChangeGC(GCPtr pGC, unsigned long mask);
-void xnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
-void xnestDestroyGC(GCPtr pGC);
-void xnestChangeClip(GCPtr pGC, int type, pointer pValue, int nRects);
-void xnestDestroyClip(GCPtr pGC);
-void xnestDestroyClipHelper(GCPtr pGC);
-void xnestCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
-
-#endif /* XNESTGC_H */
+/*
+
+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.
+
+*/
+
+#ifndef XNESTGC_H
+#define XNESTGC_H
+
+/* This file uses the GC definition form Xlib.h as XlibGC. */
+
+typedef struct {
+ XlibGC gc;
+} xnestPrivGC;
+
+extern DevPrivateKeyRec xnestGCPrivateKeyRec;
+#define xnestGCPrivateKey (&xnestGCPrivateKeyRec)
+
+#define xnestGCPriv(pGC) ((xnestPrivGC *) \
+ dixLookupPrivate(&(pGC)->devPrivates, xnestGCPrivateKey))
+
+#define xnestGC(pGC) (xnestGCPriv(pGC)->gc)
+
+Bool xnestCreateGC(GCPtr pGC);
+void xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable);
+void xnestChangeGC(GCPtr pGC, unsigned long mask);
+void xnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+void xnestDestroyGC(GCPtr pGC);
+void xnestChangeClip(GCPtr pGC, int type, pointer pValue, int nRects);
+void xnestDestroyClip(GCPtr pGC);
+void xnestDestroyClipHelper(GCPtr pGC);
+void xnestCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
+
+#endif /* XNESTGC_H */
diff --git a/xorg-server/hw/xquartz/applewm.c b/xorg-server/hw/xquartz/applewm.c
index 2f26e61d9..27fb125d3 100644
--- a/xorg-server/hw/xquartz/applewm.c
+++ b/xorg-server/hw/xquartz/applewm.c
@@ -147,7 +147,6 @@ ProcAppleWMQueryVersion(
)
{
xAppleWMQueryVersionReply rep;
- register int n;
REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq);
rep.type = X_Reply;
@@ -157,8 +156,8 @@ ProcAppleWMQueryVersion(
rep.minorVersion = SERVER_APPLEWM_MINOR_VERSION;
rep.patchVersion = SERVER_APPLEWM_PATCH_VERSION;
if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
}
WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep);
return Success;
@@ -681,9 +680,8 @@ SProcAppleWMQueryVersion(
register ClientPtr client
)
{
- register int n;
REQUEST(xAppleWMQueryVersionReq);
- swaps(&stuff->length, n);
+ swaps(&stuff->length);
return ProcAppleWMQueryVersion(client);
}
diff --git a/xorg-server/hw/xquartz/pseudoramiX.c b/xorg-server/hw/xquartz/pseudoramiX.c
index ded242d07..5a5b9c2e7 100644
--- a/xorg-server/hw/xquartz/pseudoramiX.c
+++ b/xorg-server/hw/xquartz/pseudoramiX.c
@@ -1,471 +1,462 @@
-/*
- * 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 screenInfo.screens[stuff->screen]->width;
- rep.height = pseudoramiXScreens[stuff->screen].h;
- // was screenInfo.screens[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;
-}
+/*
+ * 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 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);
+ swapl(&rep.length);
+ swaps(&rep.state);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
+ return Success;
+}
+
+
+// was PanoramiX
+static int ProcPseudoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ register int 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);
+ swapl(&rep.length);
+ swaps(&rep.ScreenCount);
+ }
+ 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 screenInfo.screens[stuff->screen]->width;
+ rep.height = pseudoramiXScreens[stuff->screen].h;
+ // was screenInfo.screens[stuff->screen]->height;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swaps(&rep.width);
+ swaps(&rep.height);
+ }
+ 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) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.state);
+ }
+ 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) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.number);
+ }
+ 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) {
+ swaps(&scratch.x_org);
+ swaps(&scratch.y_org);
+ swaps(&scratch.width);
+ swaps(&scratch.height);
+ }
+ 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);
+
+ TRACE();
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ return ProcPseudoramiXQueryVersion(client);
+}
+
+static int
+SProcPseudoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+
+ TRACE();
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ return ProcPseudoramiXGetState(client);
+}
+
+static int
+SProcPseudoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+
+ TRACE();
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ return ProcPseudoramiXGetScreenCount(client);
+}
+
+static int
+SProcPseudoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+
+ TRACE();
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ return ProcPseudoramiXGetScreenSize(client);
+}
+
+
+static int
+SProcPseudoramiXIsActive(ClientPtr client)
+{
+ REQUEST(xXineramaIsActiveReq);
+
+ TRACE();
+
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+ return ProcPseudoramiXIsActive(client);
+}
+
+
+static int
+SProcPseudoramiXQueryScreens(ClientPtr client)
+{
+ REQUEST(xXineramaQueryScreensReq);
+
+ TRACE();
+
+ swaps(&stuff->length);
+ 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/xpr/appledri.c b/xorg-server/hw/xquartz/xpr/appledri.c
index d42661c22..1304d5a43 100644
--- a/xorg-server/hw/xquartz/xpr/appledri.c
+++ b/xorg-server/hw/xquartz/xpr/appledri.c
@@ -1,420 +1,418 @@
-/**************************************************************************
-
-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 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;
-
-/*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);
- xAppleDRINotifyEvent se;
-
- if (client_index < 0 || client_index >= currentMaxClients)
- return;
-
- se.type = DRIEventBase + AppleDRISurfaceNotify;
- se.kind = arg->kind;
- se.arg = arg->id;
- se.time = currentTime.milliseconds;
- WriteEventsToClient (clients[client_index], 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;
- }
-}
-
-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;
- }
-}
+/**************************************************************************
+
+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 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;
+
+/*ARGSUSED*/
+static void
+AppleDRIResetProc (
+ ExtensionEntry* extEntry
+)
+{
+ DRIReset();
+}
+
+static int
+ProcAppleDRIQueryVersion(
+ register ClientPtr client
+)
+{
+ xAppleDRIQueryVersionReply rep;
+
+ 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);
+ swapl(&rep.length);
+ }
+ 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);
+ xAppleDRINotifyEvent se;
+
+ if (client_index < 0 || client_index >= currentMaxClients)
+ return;
+
+ se.type = DRIEventBase + AppleDRISurfaceNotify;
+ se.kind = arg->kind;
+ se.arg = arg->id;
+ se.time = currentTime.milliseconds;
+ WriteEventsToClient (clients[client_index], 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
+)
+{
+ REQUEST(xAppleDRIQueryVersionReq);
+ swaps(&stuff->length);
+ 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;
+ }
+}
+
+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;
+ }
+}
diff --git a/xorg-server/hw/xwin/winwindowswm.c b/xorg-server/hw/xwin/winwindowswm.c
index 966732a5a..403c859e7 100644
--- a/xorg-server/hw/xwin/winwindowswm.c
+++ b/xorg-server/hw/xwin/winwindowswm.c
@@ -1,637 +1,637 @@
-/* WindowsWM extension is based on AppleWM extension */
-/**************************************************************************
-
-Copyright (c) 2002 Apple Computer, 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.
-
-**************************************************************************/
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-
-#include "misc.h"
-#include "dixstruct.h"
-#include "extnsionst.h"
-#include "colormapst.h"
-#include "cursorstr.h"
-#include "scrnintstr.h"
-#include "servermd.h"
-#include "swaprep.h"
-#define _WINDOWSWM_SERVER_
-#include <X11/extensions/windowswmstr.h>
-#include "protocol-versions.h"
-
-static int WMErrorBase;
-static unsigned char WMReqCode = 0;
-static int WMEventBase = 0;
-
-static RESTYPE ClientType, eventResourceType; /* 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(xWindowsWMNotifyEvent *from, xWindowsWMNotifyEvent *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;
-}
-
-static int
-ProcWindowsWMQueryVersion(ClientPtr client)
-{
- xWindowsWMQueryVersionReply rep;
- int n;
-
- REQUEST_SIZE_MATCH(xWindowsWMQueryVersionReq);
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.majorVersion = SERVER_WINDOWSWM_MAJOR_VERSION;
- rep.minorVersion = SERVER_WINDOWSWM_MINOR_VERSION;
- rep.patchVersion = SERVER_WINDOWSWM_PATCH_VERSION;
- if (client->swapped)
- {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- }
- WriteToClient(client, sizeof(xWindowsWMQueryVersionReply), (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;
-
- pEvent = (WMEventPtr) data;
- dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType,
- NullClient, DixUnknownAccess);
- if (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
-ProcWindowsWMSelectInput (ClientPtr client)
-{
- REQUEST(xWindowsWMSelectInputReq);
- WMEventPtr pEvent, pNewEvent, *pHead;
- XID clientResource;
-
- REQUEST_SIZE_MATCH (xWindowsWMSelectInputReq);
- dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType, client, DixWriteAccess);
- if (stuff->mask != 0)
- {
- if (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 (!pHead)
- {
- pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr));
- if (!pHead ||
- !AddResource (eventResource, eventResourceType, (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 (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
-winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg,
- Window window, int x, int y, int w, int h)
-{
- WMEventPtr *pHead, pEvent;
- ClientPtr client;
- xWindowsWMNotifyEvent se;
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winWindowsWMSendEvent %d %d %d %d, %d %d - %d %d\n",
- type, mask, which, arg, x, y, w, h);
-#endif
- dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType,
- NullClient, DixUnknownAccess);
- if (!pHead)
- return;
- for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
- {
- client = pEvent->client;
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winWindowsWMSendEvent - x%08x\n", (int) client);
-#endif
- if ((pEvent->mask & mask) == 0)
- {
- continue;
- }
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winWindowsWMSendEvent - send\n");
-#endif
- se.type = type + WMEventBase;
- se.kind = which;
- se.window = window;
- se.arg = arg;
- se.x = x;
- se.y = y;
- se.w = w;
- se.h = h;
- se.time = currentTime.milliseconds;
- WriteEventsToClient (client, 1, (xEvent *) &se);
- }
-}
-
-/* general utility functions */
-
-static int
-ProcWindowsWMDisableUpdate (ClientPtr client)
-{
- REQUEST_SIZE_MATCH(xWindowsWMDisableUpdateReq);
-
- //winDisableUpdate();
-
- return Success;
-}
-
-static int
-ProcWindowsWMReenableUpdate (ClientPtr client)
-{
- REQUEST_SIZE_MATCH(xWindowsWMReenableUpdateReq);
-
- //winEnableUpdate();
-
- return Success;
-}
-
-
-/* window functions */
-
-static int
-ProcWindowsWMSetFrontProcess (ClientPtr client)
-{
- REQUEST_SIZE_MATCH(xWindowsWMSetFrontProcessReq);
-
- //QuartzMessageMainThread(kWindowsSetFrontProcess, NULL, 0);
-
- return Success;
-}
-
-
-/* frame functions */
-
-static int
-ProcWindowsWMFrameGetRect (ClientPtr client)
-{
- xWindowsWMFrameGetRectReply rep;
- BoxRec ir;
- RECT rcNew;
- REQUEST(xWindowsWMFrameGetRectReq);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameGetRect %d %d\n",
- (sizeof(xWindowsWMFrameGetRectReq) >> 2), (int) client->req_len);
-#endif
-
- REQUEST_SIZE_MATCH(xWindowsWMFrameGetRectReq);
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
-
- ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
-
- if (stuff->frame_rect != 0)
- {
- ErrorF ("ProcWindowsWMFrameGetRect - stuff->frame_rect != 0\n");
- return BadValue;
- }
-
- /* Store the origin, height, and width in a rectangle structure */
- SetRect (&rcNew, stuff->ix, stuff->iy,
- stuff->ix + stuff->iw, stuff->iy + stuff->ih);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameGetRect - %d %d %d %d\n",
- stuff->ix, stuff->iy, stuff->ix + stuff->iw, stuff->iy + stuff->ih);
-#endif
-
- /*
- * Calculate the required size of the Windows window rectangle,
- * given the size of the Windows window client area.
- */
- AdjustWindowRectEx (&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex);
- rep.x = rcNew.left;
- rep.y = rcNew.top;
- rep.w = rcNew.right - rcNew.left;
- rep.h = rcNew.bottom - rcNew.top;
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameGetRect - %d %d %d %d\n",
- rep.x, rep.y, rep.w, rep.h);
-#endif
-
- WriteToClient(client, sizeof(xWindowsWMFrameGetRectReply), (char *)&rep);
- return Success;
-}
-
-
-static int
-ProcWindowsWMFrameDraw (ClientPtr client)
-{
- REQUEST(xWindowsWMFrameDrawReq);
- WindowPtr pWin;
- win32RootlessWindowPtr pRLWinPriv;
- RECT rcNew;
- int nCmdShow, rc;
- RegionRec newShape;
-
- REQUEST_SIZE_MATCH (xWindowsWMFrameDrawReq);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameDraw\n");
-#endif
- rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
- if (rc != Success)
- return rc;
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameDraw - Window found\n");
-#endif
-
- pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, TRUE);
- if (pRLWinPriv == 0) return BadWindow;
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameDraw - HWND 0x%08x 0x%08x 0x%08x\n",
- (int) pRLWinPriv->hWnd, (int) stuff->frame_style,
- (int) stuff->frame_style_ex);
- ErrorF ("ProcWindowsWMFrameDraw - %d %d %d %d\n",
- stuff->ix, stuff->iy, stuff->iw, stuff->ih);
-#endif
-
- /* Store the origin, height, and width in a rectangle structure */
- SetRect (&rcNew, stuff->ix, stuff->iy,
- stuff->ix + stuff->iw, stuff->iy + stuff->ih);
-
- /*
- * Calculate the required size of the Windows window rectangle,
- * given the size of the Windows window client area.
- */
- AdjustWindowRectEx (&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex);
-
- /* Set the window extended style flags */
- if (!SetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE, stuff->frame_style_ex))
- {
- return BadValue;
- }
-
- /* Set the window standard style flags */
- if (!SetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE, stuff->frame_style))
- {
- return BadValue;
- }
-
- /* Flush the window style */
- if (!SetWindowPos (pRLWinPriv->hWnd, NULL,
- rcNew.left, rcNew.top,
- rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
- SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE))
- {
- return BadValue;
- }
- if (!IsWindowVisible(pRLWinPriv->hWnd))
- nCmdShow = SW_HIDE;
- else
- nCmdShow = SW_SHOWNA;
-
- ShowWindow (pRLWinPriv->hWnd, nCmdShow);
-
- winMWExtWMUpdateIcon (pWin->drawable.id);
-
- if (wBoundingShape(pWin) != NULL)
- {
- /* wBoundingShape is relative to *inner* origin of window.
- Translate by borderWidth to get the outside-relative position. */
-
- RegionNull(&newShape);
- RegionCopy(&newShape, wBoundingShape(pWin));
- RegionTranslate(&newShape, pWin->borderWidth, pWin->borderWidth);
- winMWExtWMReshapeFrame (pRLWinPriv, &newShape);
- RegionUninit(&newShape);
- }
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameDraw - done\n");
-#endif
-
- return Success;
-}
-
-static int
-ProcWindowsWMFrameSetTitle(ClientPtr client)
-{
- unsigned int title_length, title_max;
- char *title_bytes;
- REQUEST(xWindowsWMFrameSetTitleReq);
- WindowPtr pWin;
- win32RootlessWindowPtr pRLWinPriv;
- int rc;
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameSetTitle\n");
-#endif
-
- REQUEST_AT_LEAST_SIZE(xWindowsWMFrameSetTitleReq);
-
- rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
- if (rc != Success)
- return rc;
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameSetTitle - Window found\n");
-#endif
-
- title_length = stuff->title_length;
- title_max = (stuff->length << 2) - sizeof(xWindowsWMFrameSetTitleReq);
-
- if (title_max < title_length)
- return BadValue;
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameSetTitle - length is valid\n");
-#endif
-
- title_bytes = malloc (title_length+1);
- strncpy (title_bytes, (unsigned char *) &stuff[1], title_length);
- title_bytes[title_length] = '\0';
-
- pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
-
- if (pRLWinPriv == 0)
- {
- free (title_bytes);
- return BadWindow;
- }
-
- /* Flush the window style */
- SetWindowText (pRLWinPriv->hWnd, title_bytes);
-
- free (title_bytes);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("ProcWindowsWMFrameSetTitle - done\n");
-#endif
-
- return Success;
-}
-
-
-/* dispatch */
-
-static int
-ProcWindowsWMDispatch (ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data)
- {
- case X_WindowsWMQueryVersion:
- return ProcWindowsWMQueryVersion(client);
- }
-
- if (!LocalClient(client))
- return WMErrorBase + WindowsWMClientNotLocal;
-
- switch (stuff->data)
- {
- case X_WindowsWMSelectInput:
- return ProcWindowsWMSelectInput(client);
- case X_WindowsWMDisableUpdate:
- return ProcWindowsWMDisableUpdate(client);
- case X_WindowsWMReenableUpdate:
- return ProcWindowsWMReenableUpdate(client);
- case X_WindowsWMSetFrontProcess:
- return ProcWindowsWMSetFrontProcess(client);
- case X_WindowsWMFrameGetRect:
- return ProcWindowsWMFrameGetRect(client);
- case X_WindowsWMFrameDraw:
- return ProcWindowsWMFrameDraw(client);
- case X_WindowsWMFrameSetTitle:
- return ProcWindowsWMFrameSetTitle(client);
- default:
- return BadRequest;
- }
-}
-
-static void
-SNotifyEvent (xWindowsWMNotifyEvent *from, xWindowsWMNotifyEvent *to)
-{
- to->type = from->type;
- to->kind = from->kind;
- cpswaps (from->sequenceNumber, to->sequenceNumber);
- cpswapl (from->window, to->window);
- cpswapl (from->time, to->time);
- cpswapl (from->arg, to->arg);
-}
-
-static int
-SProcWindowsWMQueryVersion (ClientPtr client)
-{
- int n;
- REQUEST(xWindowsWMQueryVersionReq);
- swaps(&stuff->length, n);
- return ProcWindowsWMQueryVersion(client);
-}
-
-static int
-SProcWindowsWMDispatch (ClientPtr client)
-{
- REQUEST(xReq);
-
- /* It is bound to be non-local when there is byte swapping */
- if (!LocalClient(client))
- return WMErrorBase + WindowsWMClientNotLocal;
-
- /* only local clients are allowed WM access */
- switch (stuff->data)
- {
- case X_WindowsWMQueryVersion:
- return SProcWindowsWMQueryVersion(client);
- default:
- return BadRequest;
- }
-}
-
-void
-winWindowsWMExtensionInit (void)
-{
- ExtensionEntry* extEntry;
-
- ClientType = CreateNewResourceType(WMFreeClient, "WMClient");
- eventResourceType = CreateNewResourceType(WMFreeEvents, "WMEvent");
- eventResource = FakeClientID(0);
-
- if (ClientType && eventResourceType &&
- (extEntry = AddExtension(WINDOWSWMNAME,
- WindowsWMNumberEvents,
- WindowsWMNumberErrors,
- ProcWindowsWMDispatch,
- SProcWindowsWMDispatch,
- NULL,
- StandardMinorOpcode)))
- {
- WMReqCode = (unsigned char)extEntry->base;
- WMErrorBase = extEntry->errorBase;
- WMEventBase = extEntry->eventBase;
- EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent;
- }
-}
+/* WindowsWM extension is based on AppleWM extension */
+/**************************************************************************
+
+Copyright (c) 2002 Apple Computer, 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.
+
+**************************************************************************/
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "swaprep.h"
+#define _WINDOWSWM_SERVER_
+#include <X11/extensions/windowswmstr.h>
+#include "protocol-versions.h"
+
+static int WMErrorBase;
+static unsigned char WMReqCode = 0;
+static int WMEventBase = 0;
+
+static RESTYPE ClientType, eventResourceType; /* 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(xWindowsWMNotifyEvent *from, xWindowsWMNotifyEvent *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;
+}
+
+static int
+ProcWindowsWMQueryVersion(ClientPtr client)
+{
+ xWindowsWMQueryVersionReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH(xWindowsWMQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_WINDOWSWM_MAJOR_VERSION;
+ rep.minorVersion = SERVER_WINDOWSWM_MINOR_VERSION;
+ rep.patchVersion = SERVER_WINDOWSWM_PATCH_VERSION;
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ }
+ WriteToClient(client, sizeof(xWindowsWMQueryVersionReply), (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;
+
+ pEvent = (WMEventPtr) data;
+ dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType,
+ NullClient, DixUnknownAccess);
+ if (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
+ProcWindowsWMSelectInput (ClientPtr client)
+{
+ REQUEST(xWindowsWMSelectInputReq);
+ WMEventPtr pEvent, pNewEvent, *pHead;
+ XID clientResource;
+
+ REQUEST_SIZE_MATCH (xWindowsWMSelectInputReq);
+ dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType, client, DixWriteAccess);
+ if (stuff->mask != 0)
+ {
+ if (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 (!pHead)
+ {
+ pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr));
+ if (!pHead ||
+ !AddResource (eventResource, eventResourceType, (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 (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
+winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg,
+ Window window, int x, int y, int w, int h)
+{
+ WMEventPtr *pHead, pEvent;
+ ClientPtr client;
+ xWindowsWMNotifyEvent se;
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("winWindowsWMSendEvent %d %d %d %d, %d %d - %d %d\n",
+ type, mask, which, arg, x, y, w, h);
+#endif
+ dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType,
+ NullClient, DixUnknownAccess);
+ if (!pHead)
+ return;
+ for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
+ {
+ client = pEvent->client;
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("winWindowsWMSendEvent - x%08x\n", (int) client);
+#endif
+ if ((pEvent->mask & mask) == 0)
+ {
+ continue;
+ }
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("winWindowsWMSendEvent - send\n");
+#endif
+ se.type = type + WMEventBase;
+ se.kind = which;
+ se.window = window;
+ se.arg = arg;
+ se.x = x;
+ se.y = y;
+ se.w = w;
+ se.h = h;
+ se.time = currentTime.milliseconds;
+ WriteEventsToClient (client, 1, (xEvent *) &se);
+ }
+}
+
+/* general utility functions */
+
+static int
+ProcWindowsWMDisableUpdate (ClientPtr client)
+{
+ REQUEST_SIZE_MATCH(xWindowsWMDisableUpdateReq);
+
+ //winDisableUpdate();
+
+ return Success;
+}
+
+static int
+ProcWindowsWMReenableUpdate (ClientPtr client)
+{
+ REQUEST_SIZE_MATCH(xWindowsWMReenableUpdateReq);
+
+ //winEnableUpdate();
+
+ return Success;
+}
+
+
+/* window functions */
+
+static int
+ProcWindowsWMSetFrontProcess (ClientPtr client)
+{
+ REQUEST_SIZE_MATCH(xWindowsWMSetFrontProcessReq);
+
+ //QuartzMessageMainThread(kWindowsSetFrontProcess, NULL, 0);
+
+ return Success;
+}
+
+
+/* frame functions */
+
+static int
+ProcWindowsWMFrameGetRect (ClientPtr client)
+{
+ xWindowsWMFrameGetRectReply rep;
+ BoxRec ir;
+ RECT rcNew;
+ REQUEST(xWindowsWMFrameGetRectReq);
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameGetRect %d %d\n",
+ (sizeof(xWindowsWMFrameGetRectReq) >> 2), (int) client->req_len);
+#endif
+
+ REQUEST_SIZE_MATCH(xWindowsWMFrameGetRectReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
+
+ if (stuff->frame_rect != 0)
+ {
+ ErrorF ("ProcWindowsWMFrameGetRect - stuff->frame_rect != 0\n");
+ return BadValue;
+ }
+
+ /* Store the origin, height, and width in a rectangle structure */
+ SetRect (&rcNew, stuff->ix, stuff->iy,
+ stuff->ix + stuff->iw, stuff->iy + stuff->ih);
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameGetRect - %d %d %d %d\n",
+ stuff->ix, stuff->iy, stuff->ix + stuff->iw, stuff->iy + stuff->ih);
+#endif
+
+ /*
+ * Calculate the required size of the Windows window rectangle,
+ * given the size of the Windows window client area.
+ */
+ AdjustWindowRectEx (&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex);
+ rep.x = rcNew.left;
+ rep.y = rcNew.top;
+ rep.w = rcNew.right - rcNew.left;
+ rep.h = rcNew.bottom - rcNew.top;
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameGetRect - %d %d %d %d\n",
+ rep.x, rep.y, rep.w, rep.h);
+#endif
+
+ WriteToClient(client, sizeof(xWindowsWMFrameGetRectReply), (char *)&rep);
+ return Success;
+}
+
+
+static int
+ProcWindowsWMFrameDraw (ClientPtr client)
+{
+ REQUEST(xWindowsWMFrameDrawReq);
+ WindowPtr pWin;
+ win32RootlessWindowPtr pRLWinPriv;
+ RECT rcNew;
+ int nCmdShow, rc;
+ RegionRec newShape;
+
+ REQUEST_SIZE_MATCH (xWindowsWMFrameDrawReq);
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameDraw\n");
+#endif
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameDraw - Window found\n");
+#endif
+
+ pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, TRUE);
+ if (pRLWinPriv == 0) return BadWindow;
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameDraw - HWND 0x%08x 0x%08x 0x%08x\n",
+ (int) pRLWinPriv->hWnd, (int) stuff->frame_style,
+ (int) stuff->frame_style_ex);
+ ErrorF ("ProcWindowsWMFrameDraw - %d %d %d %d\n",
+ stuff->ix, stuff->iy, stuff->iw, stuff->ih);
+#endif
+
+ /* Store the origin, height, and width in a rectangle structure */
+ SetRect (&rcNew, stuff->ix, stuff->iy,
+ stuff->ix + stuff->iw, stuff->iy + stuff->ih);
+
+ /*
+ * Calculate the required size of the Windows window rectangle,
+ * given the size of the Windows window client area.
+ */
+ AdjustWindowRectEx (&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex);
+
+ /* Set the window extended style flags */
+ if (!SetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE, stuff->frame_style_ex))
+ {
+ return BadValue;
+ }
+
+ /* Set the window standard style flags */
+ if (!SetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE, stuff->frame_style))
+ {
+ return BadValue;
+ }
+
+ /* Flush the window style */
+ if (!SetWindowPos (pRLWinPriv->hWnd, NULL,
+ rcNew.left, rcNew.top,
+ rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
+ SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE))
+ {
+ return BadValue;
+ }
+ if (!IsWindowVisible(pRLWinPriv->hWnd))
+ nCmdShow = SW_HIDE;
+ else
+ nCmdShow = SW_SHOWNA;
+
+ ShowWindow (pRLWinPriv->hWnd, nCmdShow);
+
+ winMWExtWMUpdateIcon (pWin->drawable.id);
+
+ if (wBoundingShape(pWin) != NULL)
+ {
+ /* wBoundingShape is relative to *inner* origin of window.
+ Translate by borderWidth to get the outside-relative position. */
+
+ RegionNull(&newShape);
+ RegionCopy(&newShape, wBoundingShape(pWin));
+ RegionTranslate(&newShape, pWin->borderWidth, pWin->borderWidth);
+ winMWExtWMReshapeFrame (pRLWinPriv, &newShape);
+ RegionUninit(&newShape);
+ }
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameDraw - done\n");
+#endif
+
+ return Success;
+}
+
+static int
+ProcWindowsWMFrameSetTitle(ClientPtr client)
+{
+ unsigned int title_length, title_max;
+ char *title_bytes;
+ REQUEST(xWindowsWMFrameSetTitleReq);
+ WindowPtr pWin;
+ win32RootlessWindowPtr pRLWinPriv;
+ int rc;
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameSetTitle\n");
+#endif
+
+ REQUEST_AT_LEAST_SIZE(xWindowsWMFrameSetTitleReq);
+
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameSetTitle - Window found\n");
+#endif
+
+ title_length = stuff->title_length;
+ title_max = (stuff->length << 2) - sizeof(xWindowsWMFrameSetTitleReq);
+
+ if (title_max < title_length)
+ return BadValue;
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameSetTitle - length is valid\n");
+#endif
+
+ title_bytes = malloc (title_length+1);
+ strncpy (title_bytes, (unsigned char *) &stuff[1], title_length);
+ title_bytes[title_length] = '\0';
+
+ pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
+
+ if (pRLWinPriv == 0)
+ {
+ free (title_bytes);
+ return BadWindow;
+ }
+
+ /* Flush the window style */
+ SetWindowText (pRLWinPriv->hWnd, title_bytes);
+
+ free (title_bytes);
+
+#if CYGMULTIWINDOW_DEBUG
+ ErrorF ("ProcWindowsWMFrameSetTitle - done\n");
+#endif
+
+ return Success;
+}
+
+
+/* dispatch */
+
+static int
+ProcWindowsWMDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_WindowsWMQueryVersion:
+ return ProcWindowsWMQueryVersion(client);
+ }
+
+ if (!LocalClient(client))
+ return WMErrorBase + WindowsWMClientNotLocal;
+
+ switch (stuff->data)
+ {
+ case X_WindowsWMSelectInput:
+ return ProcWindowsWMSelectInput(client);
+ case X_WindowsWMDisableUpdate:
+ return ProcWindowsWMDisableUpdate(client);
+ case X_WindowsWMReenableUpdate:
+ return ProcWindowsWMReenableUpdate(client);
+ case X_WindowsWMSetFrontProcess:
+ return ProcWindowsWMSetFrontProcess(client);
+ case X_WindowsWMFrameGetRect:
+ return ProcWindowsWMFrameGetRect(client);
+ case X_WindowsWMFrameDraw:
+ return ProcWindowsWMFrameDraw(client);
+ case X_WindowsWMFrameSetTitle:
+ return ProcWindowsWMFrameSetTitle(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+SNotifyEvent (xWindowsWMNotifyEvent *from, xWindowsWMNotifyEvent *to)
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswapl (from->window, to->window);
+ cpswapl (from->time, to->time);
+ cpswapl (from->arg, to->arg);
+}
+
+static int
+SProcWindowsWMQueryVersion (ClientPtr client)
+{
+ int n;
+ REQUEST(xWindowsWMQueryVersionReq);
+ swaps(&stuff->length);
+ return ProcWindowsWMQueryVersion(client);
+}
+
+static int
+SProcWindowsWMDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ /* It is bound to be non-local when there is byte swapping */
+ if (!LocalClient(client))
+ return WMErrorBase + WindowsWMClientNotLocal;
+
+ /* only local clients are allowed WM access */
+ switch (stuff->data)
+ {
+ case X_WindowsWMQueryVersion:
+ return SProcWindowsWMQueryVersion(client);
+ default:
+ return BadRequest;
+ }
+}
+
+void
+winWindowsWMExtensionInit (void)
+{
+ ExtensionEntry* extEntry;
+
+ ClientType = CreateNewResourceType(WMFreeClient, "WMClient");
+ eventResourceType = CreateNewResourceType(WMFreeEvents, "WMEvent");
+ eventResource = FakeClientID(0);
+
+ if (ClientType && eventResourceType &&
+ (extEntry = AddExtension(WINDOWSWMNAME,
+ WindowsWMNumberEvents,
+ WindowsWMNumberErrors,
+ ProcWindowsWMDispatch,
+ SProcWindowsWMDispatch,
+ NULL,
+ StandardMinorOpcode)))
+ {
+ WMReqCode = (unsigned char)extEntry->base;
+ WMErrorBase = extEntry->errorBase;
+ WMEventBase = extEntry->eventBase;
+ EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent;
+ }
+}