aboutsummaryrefslogtreecommitdiff
path: root/xorg-server
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server')
-rw-r--r--xorg-server/Xext/xtest.c9
-rw-r--r--xorg-server/dix/dixutils.c1788
-rw-r--r--xorg-server/dix/getevents.c25
-rw-r--r--xorg-server/dix/grabs.c1226
-rw-r--r--xorg-server/dix/window.c141
-rw-r--r--xorg-server/exa/exa.c4
-rw-r--r--xorg-server/exa/exa_accel.c2612
-rw-r--r--xorg-server/exa/exa_classic.c532
-rw-r--r--xorg-server/exa/exa_driver.c452
-rw-r--r--xorg-server/exa/exa_migration_classic.c1490
-rw-r--r--xorg-server/exa/exa_migration_mixed.c522
-rw-r--r--xorg-server/exa/exa_mixed.c580
-rw-r--r--xorg-server/exa/exa_unaccel.c2
-rw-r--r--xorg-server/hw/dmx/dmxinput.c239
-rw-r--r--xorg-server/hw/dmx/input/dmxinputinit.c3
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr.c2
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr.h2
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr_draw.c1046
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyrinit.c3
-rw-r--r--xorg-server/hw/kdrive/ephyr/hostx.c2894
-rw-r--r--xorg-server/hw/kdrive/ephyr/hostx.h2
-rw-r--r--xorg-server/hw/kdrive/ephyr/os.c2
-rw-r--r--xorg-server/hw/kdrive/fake/fakeinit.c1
-rw-r--r--xorg-server/hw/kdrive/fake/kbd.c2
-rw-r--r--xorg-server/hw/kdrive/fbdev/fbdev.c1652
-rw-r--r--xorg-server/hw/kdrive/fbdev/fbdev.h2
-rw-r--r--xorg-server/hw/kdrive/fbdev/fbinit.c3
-rw-r--r--xorg-server/hw/kdrive/linux/keyboard.c1530
-rw-r--r--xorg-server/hw/kdrive/linux/linux.c2
-rw-r--r--xorg-server/hw/kdrive/linux/mouse.c2060
-rw-r--r--xorg-server/hw/kdrive/linux/ps2.c2
-rw-r--r--xorg-server/hw/kdrive/linux/tslib.c394
-rw-r--r--xorg-server/hw/kdrive/src/kcmap.c492
-rw-r--r--xorg-server/hw/kdrive/src/kdrive.h4
-rw-r--r--xorg-server/hw/kdrive/src/kinfo.c326
-rw-r--r--xorg-server/hw/kdrive/src/kinput.c11
-rw-r--r--xorg-server/hw/kdrive/src/kshadow.c162
-rw-r--r--xorg-server/hw/vfb/InitInput.c303
-rw-r--r--xorg-server/hw/xfree86/common/xf86Init.c1
-rw-r--r--xorg-server/hw/xfree86/dixmods/xkbPrivate.c15
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.c1
-rw-r--r--xorg-server/hw/xfree86/exa/examodule.c402
-rw-r--r--xorg-server/hw/xfree86/modes/xf86Modes.h2
-rw-r--r--xorg-server/hw/xfree86/modes/xf86cvt.c586
-rw-r--r--xorg-server/hw/xfree86/os-support/solaris/sun_agp.c654
-rw-r--r--xorg-server/hw/xnest/Init.c1
-rw-r--r--xorg-server/hw/xquartz/darwin.c4
-rw-r--r--xorg-server/hw/xquartz/darwinEvents.c4
-rw-r--r--xorg-server/hw/xquartz/darwinEvents.h1
-rw-r--r--xorg-server/hw/xquartz/darwinXinput.c5
-rw-r--r--xorg-server/hw/xwin/InitInput.c319
-rw-r--r--xorg-server/include/dixgrabs.h3
-rw-r--r--xorg-server/include/input.h9
-rw-r--r--xorg-server/include/window.h2
-rw-r--r--xorg-server/mi/mipointer.c2
-rw-r--r--xorg-server/miext/shadow/shadow.c504
-rw-r--r--xorg-server/test/Makefile.am1
-rw-r--r--xorg-server/test/xi2/protocol-eventconvert.c18
58 files changed, 11659 insertions, 11397 deletions
diff --git a/xorg-server/Xext/xtest.c b/xorg-server/Xext/xtest.c
index daa6430f1..cc675c116 100644
--- a/xorg-server/Xext/xtest.c
+++ b/xorg-server/Xext/xtest.c
@@ -679,12 +679,19 @@ GetXTestDevice(DeviceIntPtr master)
return NULL;
}
+static void
+XTestExtensionTearDown(ExtensionEntry *e)
+{
+ FreeEventList(xtest_evlist, GetMaximumEventsNum());
+ xtest_evlist = NULL;
+}
+
void
XTestExtensionInit(INITARGS)
{
AddExtension(XTestExtensionName, 0, 0,
ProcXTestDispatch, SProcXTestDispatch,
- NULL, StandardMinorOpcode);
+ XTestExtensionTearDown, StandardMinorOpcode);
xtest_evlist = InitEventList(GetMaximumEventsNum());
}
diff --git a/xorg-server/dix/dixutils.c b/xorg-server/dix/dixutils.c
index c23c87e9a..1e3134663 100644
--- a/xorg-server/dix/dixutils.c
+++ b/xorg-server/dix/dixutils.c
@@ -1,893 +1,895 @@
-/***********************************************************
-
-Copyright 1987, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-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 Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL 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.
-
-******************************************************************/
-
-/*
-
-(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved.
-
-Permission to use, copy, modify, distribute, and sublicense this software and its
-documentation for any purpose and without fee is hereby granted, provided that
-the above copyright notices appear in all copies and that both those copyright
-notices and this permission notice appear in supporting documentation and that
-the name of Adobe Systems Incorporated not be used in advertising or publicity
-pertaining to distribution of the software without specific, written prior
-permission. No trademark license to use the Adobe trademarks is hereby
-granted. If the Adobe trademark "Display PostScript"(tm) is used to describe
-this software, its functionality or for any other purpose, such use shall be
-limited to a statement that this software works in conjunction with the Display
-PostScript system. Proper trademark attribution to reflect Adobe's ownership
-of the trademark shall be given whenever any such reference to the Display
-PostScript system is made.
-
-ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
-PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE
-DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
-OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
-LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
-SUPPORT FOR THE SOFTWARE.
-
-Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
-Incorporated which may be registered in certain jurisdictions.
-
-Author: Adobe Systems Incorporated
-
-*/
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xmd.h>
-#include "misc.h"
-#include "windowstr.h"
-#include "dixstruct.h"
-#include "pixmapstr.h"
-#include "gcstruct.h"
-#include "scrnintstr.h"
-#define XK_LATIN1
-#include <X11/keysymdef.h>
-#include "xace.h"
-
-/*
- * CompareTimeStamps returns -1, 0, or +1 depending on if the first
- * argument is less than, equal to or greater than the second argument.
- */
-
-int
-CompareTimeStamps(TimeStamp a, TimeStamp b)
-{
- if (a.months < b.months)
- return EARLIER;
- if (a.months > b.months)
- return LATER;
- if (a.milliseconds < b.milliseconds)
- return EARLIER;
- if (a.milliseconds > b.milliseconds)
- return LATER;
- return SAMETIME;
-}
-
-/*
- * convert client times to server TimeStamps
- */
-
-#define HALFMONTH ((unsigned long) 1<<31)
-TimeStamp
-ClientTimeToServerTime(CARD32 c)
-{
- TimeStamp ts;
- if (c == CurrentTime)
- return currentTime;
- ts.months = currentTime.months;
- ts.milliseconds = c;
- if (c > currentTime.milliseconds)
- {
- if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH)
- ts.months -= 1;
- }
- else if (c < currentTime.milliseconds)
- {
- if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH)
- ts.months += 1;
- }
- return ts;
-}
-
-/*
- * ISO Latin-1 case conversion routine
- *
- * this routine always null-terminates the result, so
- * beware of too-small buffers
- */
-
-static unsigned char
-ISOLatin1ToLower (unsigned char source)
-{
- unsigned char dest;
- if ((source >= XK_A) && (source <= XK_Z))
- dest = source + (XK_a - XK_A);
- else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis))
- dest = source + (XK_agrave - XK_Agrave);
- else if ((source >= XK_Ooblique) && (source <= XK_Thorn))
- dest = source + (XK_oslash - XK_Ooblique);
- else
- dest = source;
- return dest;
-}
-
-
-int
-CompareISOLatin1Lowered(unsigned char *s1, int s1len,
- unsigned char *s2, int s2len)
-{
- unsigned char c1, c2;
-
- for (;;)
- {
- /* note -- compare against zero so that -1 ignores len */
- c1 = s1len-- ? *s1++ : '\0';
- c2 = s2len-- ? *s2++ : '\0';
- if (!c1 ||
- (c1 != c2 &&
- (c1 = ISOLatin1ToLower (c1)) != (c2 = ISOLatin1ToLower (c2))))
- break;
- }
- return (int) c1 - (int) c2;
-}
-
-/*
- * dixLookupWindow and dixLookupDrawable:
- * Look up the window/drawable taking into account the client doing the
- * lookup, the type of drawable desired, and the type of access desired.
- * Return Success with *pDraw set if the window/drawable exists and the client
- * is allowed access, else return an error code with *pDraw set to NULL. The
- * access mask values are defined in resource.h. The type mask values are
- * defined in pixmap.h, with zero equivalent to M_DRAWABLE.
- */
-int
-dixLookupDrawable(DrawablePtr *pDraw, XID id, ClientPtr client,
- Mask type, Mask access)
-{
- DrawablePtr pTmp;
- int rc;
-
- *pDraw = NULL;
- client->errorValue = id;
-
- if (id == INVALID)
- return BadDrawable;
-
- rc = dixLookupResourceByClass((pointer *)&pTmp, id, RC_DRAWABLE, client, access);
-
- if (rc == BadValue)
- return BadDrawable;
- if (rc != Success)
- return rc;
- if (!((1 << pTmp->type) & (type ? type : M_DRAWABLE)))
- return BadMatch;
-
- *pDraw = pTmp;
- return Success;
-}
-
-int
-dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
-{
- int rc;
- rc = dixLookupDrawable((DrawablePtr*)pWin, id, client, M_WINDOW, access);
- return (rc == BadDrawable) ? BadWindow : rc;
-}
-
-int
-dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access)
-{
- return dixLookupResourceByType((pointer *)pGC, id, RT_GC, client, access);
-}
-
-int
-dixLookupFontable(FontPtr *pFont, XID id, ClientPtr client, Mask access)
-{
- int rc;
- GC *pGC;
- client->errorValue = id; /* EITHER font or gc */
- rc = dixLookupResourceByType((pointer *) pFont, id, RT_FONT, client, access);
- if (rc != BadFont)
- return rc;
- rc = dixLookupResourceByType((pointer *) &pGC, id, RT_GC, client, access);
- if (rc == BadGC)
- return BadFont;
- if (rc == Success)
- *pFont = pGC->font;
- return rc;
-}
-
-int
-dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access)
-{
- pointer pRes;
- int rc = BadValue, clientIndex = CLIENT_ID(rid);
-
- if (!clientIndex || !clients[clientIndex] || (rid & SERVER_BIT))
- goto bad;
-
- rc = dixLookupResourceByClass(&pRes, rid, RC_ANY, client, DixGetAttrAccess);
- if (rc != Success)
- goto bad;
-
- rc = XaceHook(XACE_CLIENT_ACCESS, client, clients[clientIndex], access);
- if (rc != Success)
- goto bad;
-
- *pClient = clients[clientIndex];
- return Success;
-bad:
- if(client)
- client->errorValue = rid;
- *pClient = NULL;
- return rc;
-}
-
-int
-AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
- Bool toRoot, Bool map)
-{
- int numnow;
- SaveSetElt *pTmp = NULL;
- int j;
-
- numnow = client->numSaved;
- j = 0;
- if (numnow)
- {
- pTmp = client->saveSet;
- while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (pointer)pWin))
- j++;
- }
- if (mode == SetModeInsert)
- {
- if (j < numnow) /* duplicate */
- return Success;
- numnow++;
- pTmp = (SaveSetElt *)realloc(client->saveSet, sizeof(*pTmp) * numnow);
- if (!pTmp)
- return BadAlloc;
- client->saveSet = pTmp;
- client->numSaved = numnow;
- SaveSetAssignWindow(client->saveSet[numnow - 1], pWin);
- SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot);
- SaveSetAssignMap(client->saveSet[numnow - 1], map);
- return Success;
- }
- else if ((mode == SetModeDelete) && (j < numnow))
- {
- while (j < numnow-1)
- {
- pTmp[j] = pTmp[j+1];
- j++;
- }
- numnow--;
- if (numnow)
- {
- pTmp = (SaveSetElt *)realloc(client->saveSet, sizeof(*pTmp) * numnow);
- if (pTmp)
- client->saveSet = pTmp;
- }
- else
- {
- free(client->saveSet);
- client->saveSet = (SaveSetElt *)NULL;
- }
- client->numSaved = numnow;
- return Success;
- }
- return Success;
-}
-
-void
-DeleteWindowFromAnySaveSet(WindowPtr pWin)
-{
- int i;
- ClientPtr client;
-
- for (i = 0; i< currentMaxClients; i++)
- {
- client = clients[i];
- if (client && client->numSaved)
- (void)AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE, TRUE);
- }
-}
-
-/* No-op Don't Do Anything : sometimes we need to be able to call a procedure
- * that doesn't do anything. For example, on screen with only static
- * colormaps, if someone calls install colormap, it's easier to have a dummy
- * procedure to call than to check if there's a procedure
- */
-void
-NoopDDA(void)
-{
-}
-
-typedef struct _BlockHandler {
- BlockHandlerProcPtr BlockHandler;
- WakeupHandlerProcPtr WakeupHandler;
- pointer blockData;
- Bool deleted;
-} BlockHandlerRec, *BlockHandlerPtr;
-
-static BlockHandlerPtr handlers;
-static int numHandlers;
-static int sizeHandlers;
-static Bool inHandler;
-static Bool handlerDeleted;
-
-/**
- *
- * \param pTimeout DIX doesn't want to know how OS represents time
- * \param pReadMask nor how it represents the det of descriptors
- */
-void
-BlockHandler(pointer pTimeout, pointer pReadmask)
-{
- int i, j;
-
- ++inHandler;
- for (i = 0; i < screenInfo.numScreens; i++)
- (* screenInfo.screens[i]->BlockHandler)(i,
- screenInfo.screens[i]->blockData,
- pTimeout, pReadmask);
- for (i = 0; i < numHandlers; i++)
- (*handlers[i].BlockHandler) (handlers[i].blockData,
- pTimeout, pReadmask);
- if (handlerDeleted)
- {
- for (i = 0; i < numHandlers;)
- if (handlers[i].deleted)
- {
- for (j = i; j < numHandlers - 1; j++)
- handlers[j] = handlers[j+1];
- numHandlers--;
- }
- else
- i++;
- handlerDeleted = FALSE;
- }
- --inHandler;
-}
-
-/**
- *
- * \param result 32 bits of undefined result from the wait
- * \param pReadmask the resulting descriptor mask
- */
-void
-WakeupHandler(int result, pointer pReadmask)
-{
- int i, j;
-
- ++inHandler;
- for (i = numHandlers - 1; i >= 0; i--)
- (*handlers[i].WakeupHandler) (handlers[i].blockData,
- result, pReadmask);
- for (i = 0; i < screenInfo.numScreens; i++)
- (* screenInfo.screens[i]->WakeupHandler)(i,
- screenInfo.screens[i]->wakeupData,
- result, pReadmask);
- if (handlerDeleted)
- {
- for (i = 0; i < numHandlers;)
- if (handlers[i].deleted)
- {
- for (j = i; j < numHandlers - 1; j++)
- handlers[j] = handlers[j+1];
- numHandlers--;
- }
- else
- i++;
- handlerDeleted = FALSE;
- }
- --inHandler;
-}
-
-/**
- * Reentrant with BlockHandler and WakeupHandler, except wakeup won't
- * get called until next time
- */
-Bool
-RegisterBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler,
- WakeupHandlerProcPtr wakeupHandler,
- pointer blockData)
-{
- BlockHandlerPtr new;
-
- if (numHandlers >= sizeHandlers)
- {
- new = (BlockHandlerPtr) realloc(handlers, (numHandlers + 1) *
- sizeof (BlockHandlerRec));
- if (!new)
- return FALSE;
- handlers = new;
- sizeHandlers = numHandlers + 1;
- }
- handlers[numHandlers].BlockHandler = blockHandler;
- handlers[numHandlers].WakeupHandler = wakeupHandler;
- handlers[numHandlers].blockData = blockData;
- handlers[numHandlers].deleted = FALSE;
- numHandlers = numHandlers + 1;
- return TRUE;
-}
-
-void
-RemoveBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler,
- WakeupHandlerProcPtr wakeupHandler,
- pointer blockData)
-{
- int i;
-
- for (i = 0; i < numHandlers; i++)
- if (handlers[i].BlockHandler == blockHandler &&
- handlers[i].WakeupHandler == wakeupHandler &&
- handlers[i].blockData == blockData)
- {
- if (inHandler)
- {
- handlerDeleted = TRUE;
- handlers[i].deleted = TRUE;
- }
- else
- {
- for (; i < numHandlers - 1; i++)
- handlers[i] = handlers[i+1];
- numHandlers--;
- }
- break;
- }
-}
-
-void
-InitBlockAndWakeupHandlers (void)
-{
- free(handlers);
- handlers = (BlockHandlerPtr) 0;
- numHandlers = 0;
- sizeHandlers = 0;
-}
-
-/*
- * A general work queue. Perform some task before the server
- * sleeps for input.
- */
-
-WorkQueuePtr workQueue;
-static WorkQueuePtr *workQueueLast = &workQueue;
-
-void
-ProcessWorkQueue(void)
-{
- WorkQueuePtr q, *p;
-
- p = &workQueue;
- /*
- * Scan the work queue once, calling each function. Those
- * which return TRUE are removed from the queue, otherwise
- * they will be called again. This must be reentrant with
- * QueueWorkProc.
- */
- while ((q = *p))
- {
- if ((*q->function) (q->client, q->closure))
- {
- /* remove q from the list */
- *p = q->next; /* don't fetch until after func called */
- free(q);
- }
- else
- {
- p = &q->next; /* don't fetch until after func called */
- }
- }
- workQueueLast = p;
-}
-
-void
-ProcessWorkQueueZombies(void)
-{
- WorkQueuePtr q, *p;
-
- p = &workQueue;
- while ((q = *p))
- {
- if (q->client && q->client->clientGone)
- {
- (void) (*q->function) (q->client, q->closure);
- /* remove q from the list */
- *p = q->next; /* don't fetch until after func called */
- free(q);
- }
- else
- {
- p = &q->next; /* don't fetch until after func called */
- }
- }
- workQueueLast = p;
-}
-
-Bool
-QueueWorkProc (
- Bool (*function)(ClientPtr /* pClient */, pointer /* closure */),
- ClientPtr client, pointer closure)
-{
- WorkQueuePtr q;
-
- q = malloc(sizeof *q);
- if (!q)
- return FALSE;
- q->function = function;
- q->client = client;
- q->closure = closure;
- q->next = NULL;
- *workQueueLast = q;
- workQueueLast = &q->next;
- return TRUE;
-}
-
-/*
- * Manage a queue of sleeping clients, awakening them
- * when requested, by using the OS functions IgnoreClient
- * and AttendClient. Note that this *ignores* the troubles
- * with request data interleaving itself with events, but
- * we'll leave that until a later time.
- */
-
-typedef struct _SleepQueue {
- struct _SleepQueue *next;
- ClientPtr client;
- ClientSleepProcPtr function;
- pointer closure;
-} SleepQueueRec, *SleepQueuePtr;
-
-static SleepQueuePtr sleepQueue = NULL;
-
-Bool
-ClientSleep (ClientPtr client, ClientSleepProcPtr function, pointer closure)
-{
- SleepQueuePtr q;
-
- q = malloc(sizeof *q);
- if (!q)
- return FALSE;
-
- IgnoreClient (client);
- q->next = sleepQueue;
- q->client = client;
- q->function = function;
- q->closure = closure;
- sleepQueue = q;
- return TRUE;
-}
-
-Bool
-ClientSignal (ClientPtr client)
-{
- SleepQueuePtr q;
-
- for (q = sleepQueue; q; q = q->next)
- if (q->client == client)
- {
- return QueueWorkProc (q->function, q->client, q->closure);
- }
- return FALSE;
-}
-
-void
-ClientWakeup (ClientPtr client)
-{
- SleepQueuePtr q, *prev;
-
- prev = &sleepQueue;
- while ( (q = *prev) )
- {
- if (q->client == client)
- {
- *prev = q->next;
- free(q);
- if (client->clientGone)
- /* Oops -- new zombie cleanup code ensures this only
- * happens from inside CloseDownClient; don't want to
- * recurse here...
- */
- /* CloseDownClient(client) */;
- else
- AttendClient (client);
- break;
- }
- prev = &q->next;
- }
-}
-
-Bool
-ClientIsAsleep (ClientPtr client)
-{
- SleepQueuePtr q;
-
- for (q = sleepQueue; q; q = q->next)
- if (q->client == client)
- return TRUE;
- return FALSE;
-}
-
-/*
- * Generic Callback Manager
- */
-
-/* ===== Private Procedures ===== */
-
-static int numCallbackListsToCleanup = 0;
-static CallbackListPtr **listsToCleanup = NULL;
-
-static Bool
-_AddCallback(
- CallbackListPtr *pcbl,
- CallbackProcPtr callback,
- pointer data)
-{
- CallbackPtr cbr;
-
- cbr = malloc(sizeof(CallbackRec));
- if (!cbr)
- return FALSE;
- cbr->proc = callback;
- cbr->data = data;
- cbr->next = (*pcbl)->list;
- cbr->deleted = FALSE;
- (*pcbl)->list = cbr;
- return TRUE;
-}
-
-static Bool
-_DeleteCallback(
- CallbackListPtr *pcbl,
- CallbackProcPtr callback,
- pointer data)
-{
- CallbackListPtr cbl = *pcbl;
- CallbackPtr cbr, pcbr;
-
- for (pcbr = NULL, cbr = cbl->list;
- cbr != NULL;
- pcbr = cbr, cbr = cbr->next)
- {
- if ((cbr->proc == callback) && (cbr->data == data))
- break;
- }
- if (cbr != NULL)
- {
- if (cbl->inCallback)
- {
- ++(cbl->numDeleted);
- cbr->deleted = TRUE;
- }
- else
- {
- if (pcbr == NULL)
- cbl->list = cbr->next;
- else
- pcbr->next = cbr->next;
- free(cbr);
- }
- return TRUE;
- }
- return FALSE;
-}
-
-void
-_CallCallbacks(
- CallbackListPtr *pcbl,
- pointer call_data)
-{
- CallbackListPtr cbl = *pcbl;
- CallbackPtr cbr, pcbr;
-
- ++(cbl->inCallback);
- for (cbr = cbl->list; cbr != NULL; cbr = cbr->next)
- {
- (*(cbr->proc)) (pcbl, cbr->data, call_data);
- }
- --(cbl->inCallback);
-
- if (cbl->inCallback) return;
-
- /* Was the entire list marked for deletion? */
-
- if (cbl->deleted)
- {
- DeleteCallbackList(pcbl);
- return;
- }
-
- /* Were some individual callbacks on the list marked for deletion?
- * If so, do the deletions.
- */
-
- if (cbl->numDeleted)
- {
- for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; )
- {
- if (cbr->deleted)
- {
- if (pcbr)
- {
- cbr = cbr->next;
- free(pcbr->next);
- pcbr->next = cbr;
- } else
- {
- cbr = cbr->next;
- free(cbl->list);
- cbl->list = cbr;
- }
- cbl->numDeleted--;
- }
- else /* this one wasn't deleted */
- {
- pcbr = cbr;
- cbr = cbr->next;
- }
- }
- }
-}
-
-static void
-_DeleteCallbackList(
- CallbackListPtr *pcbl)
-{
- CallbackListPtr cbl = *pcbl;
- CallbackPtr cbr, nextcbr;
- int i;
-
- if (cbl->inCallback)
- {
- cbl->deleted = TRUE;
- return;
- }
-
- for (i = 0; i < numCallbackListsToCleanup; i++)
- {
- if (listsToCleanup[i] == pcbl)
- {
- listsToCleanup[i] = NULL;
- break;
- }
- }
-
- for (cbr = cbl->list; cbr != NULL; cbr = nextcbr)
- {
- nextcbr = cbr->next;
- free(cbr);
- }
- free(cbl);
- *pcbl = NULL;
-}
-
-static Bool
-CreateCallbackList(CallbackListPtr *pcbl)
-{
- CallbackListPtr cbl;
- int i;
-
- if (!pcbl) return FALSE;
- cbl = malloc(sizeof(CallbackListRec));
- if (!cbl) return FALSE;
- cbl->inCallback = 0;
- cbl->deleted = FALSE;
- cbl->numDeleted = 0;
- cbl->list = NULL;
- *pcbl = cbl;
-
- for (i = 0; i < numCallbackListsToCleanup; i++)
- {
- if (!listsToCleanup[i])
- {
- listsToCleanup[i] = pcbl;
- return TRUE;
- }
- }
-
- listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup,
- sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1));
- listsToCleanup[numCallbackListsToCleanup] = pcbl;
- numCallbackListsToCleanup++;
- return TRUE;
-}
-
-/* ===== Public Procedures ===== */
-
-Bool
-AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
-{
- if (!pcbl) return FALSE;
- if (!*pcbl)
- { /* list hasn't been created yet; go create it */
- if (!CreateCallbackList(pcbl))
- return FALSE;
- }
- return _AddCallback(pcbl, callback, data);
-}
-
-Bool
-DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
-{
- if (!pcbl || !*pcbl) return FALSE;
- return _DeleteCallback(pcbl, callback, data);
-}
-
-void
-DeleteCallbackList(CallbackListPtr *pcbl)
-{
- if (!pcbl || !*pcbl) return;
- _DeleteCallbackList(pcbl);
-}
-
-void
-InitCallbackManager(void)
-{
- int i;
-
- for (i = 0; i < numCallbackListsToCleanup; i++)
- {
- DeleteCallbackList(listsToCleanup[i]);
- }
- free(listsToCleanup);
-
- numCallbackListsToCleanup = 0;
- listsToCleanup = NULL;
-}
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+******************************************************************/
+
+/*
+
+(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved.
+
+Permission to use, copy, modify, distribute, and sublicense this software and its
+documentation for any purpose and without fee is hereby granted, provided that
+the above copyright notices appear in all copies and that both those copyright
+notices and this permission notice appear in supporting documentation and that
+the name of Adobe Systems Incorporated not be used in advertising or publicity
+pertaining to distribution of the software without specific, written prior
+permission. No trademark license to use the Adobe trademarks is hereby
+granted. If the Adobe trademark "Display PostScript"(tm) is used to describe
+this software, its functionality or for any other purpose, such use shall be
+limited to a statement that this software works in conjunction with the Display
+PostScript system. Proper trademark attribution to reflect Adobe's ownership
+of the trademark shall be given whenever any such reference to the Display
+PostScript system is made.
+
+ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
+PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE
+DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
+INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
+OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
+LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
+SUPPORT FOR THE SOFTWARE.
+
+Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+Incorporated which may be registered in certain jurisdictions.
+
+Author: Adobe Systems Incorporated
+
+*/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include "misc.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include "pixmapstr.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#define XK_LATIN1
+#include <X11/keysymdef.h>
+#include "xace.h"
+
+/*
+ * CompareTimeStamps returns -1, 0, or +1 depending on if the first
+ * argument is less than, equal to or greater than the second argument.
+ */
+
+int
+CompareTimeStamps(TimeStamp a, TimeStamp b)
+{
+ if (a.months < b.months)
+ return EARLIER;
+ if (a.months > b.months)
+ return LATER;
+ if (a.milliseconds < b.milliseconds)
+ return EARLIER;
+ if (a.milliseconds > b.milliseconds)
+ return LATER;
+ return SAMETIME;
+}
+
+/*
+ * convert client times to server TimeStamps
+ */
+
+#define HALFMONTH ((unsigned long) 1<<31)
+TimeStamp
+ClientTimeToServerTime(CARD32 c)
+{
+ TimeStamp ts;
+ if (c == CurrentTime)
+ return currentTime;
+ ts.months = currentTime.months;
+ ts.milliseconds = c;
+ if (c > currentTime.milliseconds)
+ {
+ if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH)
+ ts.months -= 1;
+ }
+ else if (c < currentTime.milliseconds)
+ {
+ if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH)
+ ts.months += 1;
+ }
+ return ts;
+}
+
+/*
+ * ISO Latin-1 case conversion routine
+ *
+ * this routine always null-terminates the result, so
+ * beware of too-small buffers
+ */
+
+static unsigned char
+ISOLatin1ToLower (unsigned char source)
+{
+ unsigned char dest;
+ if ((source >= XK_A) && (source <= XK_Z))
+ dest = source + (XK_a - XK_A);
+ else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis))
+ dest = source + (XK_agrave - XK_Agrave);
+ else if ((source >= XK_Ooblique) && (source <= XK_Thorn))
+ dest = source + (XK_oslash - XK_Ooblique);
+ else
+ dest = source;
+ return dest;
+}
+
+
+int
+CompareISOLatin1Lowered(unsigned char *s1, int s1len,
+ unsigned char *s2, int s2len)
+{
+ unsigned char c1, c2;
+
+ for (;;)
+ {
+ /* note -- compare against zero so that -1 ignores len */
+ c1 = s1len-- ? *s1++ : '\0';
+ c2 = s2len-- ? *s2++ : '\0';
+ if (!c1 ||
+ (c1 != c2 &&
+ (c1 = ISOLatin1ToLower (c1)) != (c2 = ISOLatin1ToLower (c2))))
+ break;
+ }
+ return (int) c1 - (int) c2;
+}
+
+/*
+ * dixLookupWindow and dixLookupDrawable:
+ * Look up the window/drawable taking into account the client doing the
+ * lookup, the type of drawable desired, and the type of access desired.
+ * Return Success with *pDraw set if the window/drawable exists and the client
+ * is allowed access, else return an error code with *pDraw set to NULL. The
+ * access mask values are defined in resource.h. The type mask values are
+ * defined in pixmap.h, with zero equivalent to M_DRAWABLE.
+ */
+int
+dixLookupDrawable(DrawablePtr *pDraw, XID id, ClientPtr client,
+ Mask type, Mask access)
+{
+ DrawablePtr pTmp;
+ int rc;
+
+ *pDraw = NULL;
+ client->errorValue = id;
+
+ if (id == INVALID)
+ return BadDrawable;
+
+ rc = dixLookupResourceByClass((pointer *)&pTmp, id, RC_DRAWABLE, client, access);
+
+ if (rc == BadValue)
+ return BadDrawable;
+ if (rc != Success)
+ return rc;
+ if (!((1 << pTmp->type) & (type ? type : M_DRAWABLE)))
+ return BadMatch;
+
+ *pDraw = pTmp;
+ return Success;
+}
+
+int
+dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
+{
+ int rc;
+ rc = dixLookupDrawable((DrawablePtr*)pWin, id, client, M_WINDOW, access);
+ return (rc == BadDrawable) ? BadWindow : rc;
+}
+
+int
+dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access)
+{
+ return dixLookupResourceByType((pointer *)pGC, id, RT_GC, client, access);
+}
+
+int
+dixLookupFontable(FontPtr *pFont, XID id, ClientPtr client, Mask access)
+{
+ int rc;
+ GC *pGC;
+ client->errorValue = id; /* EITHER font or gc */
+ rc = dixLookupResourceByType((pointer *) pFont, id, RT_FONT, client, access);
+ if (rc != BadFont)
+ return rc;
+ rc = dixLookupResourceByType((pointer *) &pGC, id, RT_GC, client, access);
+ if (rc == BadGC)
+ return BadFont;
+ if (rc == Success)
+ *pFont = pGC->font;
+ return rc;
+}
+
+int
+dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access)
+{
+ pointer pRes;
+ int rc = BadValue, clientIndex = CLIENT_ID(rid);
+
+ if (!clientIndex || !clients[clientIndex] || (rid & SERVER_BIT))
+ goto bad;
+
+ rc = dixLookupResourceByClass(&pRes, rid, RC_ANY, client, DixGetAttrAccess);
+ if (rc != Success)
+ goto bad;
+
+ rc = XaceHook(XACE_CLIENT_ACCESS, client, clients[clientIndex], access);
+ if (rc != Success)
+ goto bad;
+
+ *pClient = clients[clientIndex];
+ return Success;
+bad:
+ if(client)
+ client->errorValue = rid;
+ *pClient = NULL;
+ return rc;
+}
+
+int
+AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
+ Bool toRoot, Bool map)
+{
+ int numnow;
+ SaveSetElt *pTmp = NULL;
+ int j;
+
+ numnow = client->numSaved;
+ j = 0;
+ if (numnow)
+ {
+ pTmp = client->saveSet;
+ while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (pointer)pWin))
+ j++;
+ }
+ if (mode == SetModeInsert)
+ {
+ if (j < numnow) /* duplicate */
+ return Success;
+ numnow++;
+ pTmp = (SaveSetElt *)realloc(client->saveSet, sizeof(*pTmp) * numnow);
+ if (!pTmp)
+ return BadAlloc;
+ client->saveSet = pTmp;
+ client->numSaved = numnow;
+ SaveSetAssignWindow(client->saveSet[numnow - 1], pWin);
+ SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot);
+ SaveSetAssignMap(client->saveSet[numnow - 1], map);
+ return Success;
+ }
+ else if ((mode == SetModeDelete) && (j < numnow))
+ {
+ while (j < numnow-1)
+ {
+ pTmp[j] = pTmp[j+1];
+ j++;
+ }
+ numnow--;
+ if (numnow)
+ {
+ pTmp = (SaveSetElt *)realloc(client->saveSet, sizeof(*pTmp) * numnow);
+ if (pTmp)
+ client->saveSet = pTmp;
+ }
+ else
+ {
+ free(client->saveSet);
+ client->saveSet = (SaveSetElt *)NULL;
+ }
+ client->numSaved = numnow;
+ return Success;
+ }
+ return Success;
+}
+
+void
+DeleteWindowFromAnySaveSet(WindowPtr pWin)
+{
+ int i;
+ ClientPtr client;
+
+ for (i = 0; i< currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client && client->numSaved)
+ (void)AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE, TRUE);
+ }
+}
+
+/* No-op Don't Do Anything : sometimes we need to be able to call a procedure
+ * that doesn't do anything. For example, on screen with only static
+ * colormaps, if someone calls install colormap, it's easier to have a dummy
+ * procedure to call than to check if there's a procedure
+ */
+void
+NoopDDA(void)
+{
+}
+
+typedef struct _BlockHandler {
+ BlockHandlerProcPtr BlockHandler;
+ WakeupHandlerProcPtr WakeupHandler;
+ pointer blockData;
+ Bool deleted;
+} BlockHandlerRec, *BlockHandlerPtr;
+
+static BlockHandlerPtr handlers;
+static int numHandlers;
+static int sizeHandlers;
+static Bool inHandler;
+static Bool handlerDeleted;
+
+/**
+ *
+ * \param pTimeout DIX doesn't want to know how OS represents time
+ * \param pReadMask nor how it represents the det of descriptors
+ */
+void
+BlockHandler(pointer pTimeout, pointer pReadmask)
+{
+ int i, j;
+
+ ++inHandler;
+ for (i = 0; i < screenInfo.numScreens; i++)
+ (* screenInfo.screens[i]->BlockHandler)(i,
+ screenInfo.screens[i]->blockData,
+ pTimeout, pReadmask);
+ for (i = 0; i < numHandlers; i++)
+ if (!handlers[i].deleted)
+ (*handlers[i].BlockHandler) (handlers[i].blockData,
+ pTimeout, pReadmask);
+ if (handlerDeleted)
+ {
+ for (i = 0; i < numHandlers;)
+ if (handlers[i].deleted)
+ {
+ for (j = i; j < numHandlers - 1; j++)
+ handlers[j] = handlers[j+1];
+ numHandlers--;
+ }
+ else
+ i++;
+ handlerDeleted = FALSE;
+ }
+ --inHandler;
+}
+
+/**
+ *
+ * \param result 32 bits of undefined result from the wait
+ * \param pReadmask the resulting descriptor mask
+ */
+void
+WakeupHandler(int result, pointer pReadmask)
+{
+ int i, j;
+
+ ++inHandler;
+ for (i = numHandlers - 1; i >= 0; i--)
+ if (!handlers[i].deleted)
+ (*handlers[i].WakeupHandler) (handlers[i].blockData,
+ result, pReadmask);
+ for (i = 0; i < screenInfo.numScreens; i++)
+ (* screenInfo.screens[i]->WakeupHandler)(i,
+ screenInfo.screens[i]->wakeupData,
+ result, pReadmask);
+ if (handlerDeleted)
+ {
+ for (i = 0; i < numHandlers;)
+ if (handlers[i].deleted)
+ {
+ for (j = i; j < numHandlers - 1; j++)
+ handlers[j] = handlers[j+1];
+ numHandlers--;
+ }
+ else
+ i++;
+ handlerDeleted = FALSE;
+ }
+ --inHandler;
+}
+
+/**
+ * Reentrant with BlockHandler and WakeupHandler, except wakeup won't
+ * get called until next time
+ */
+Bool
+RegisterBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler,
+ WakeupHandlerProcPtr wakeupHandler,
+ pointer blockData)
+{
+ BlockHandlerPtr new;
+
+ if (numHandlers >= sizeHandlers)
+ {
+ new = (BlockHandlerPtr) realloc(handlers, (numHandlers + 1) *
+ sizeof (BlockHandlerRec));
+ if (!new)
+ return FALSE;
+ handlers = new;
+ sizeHandlers = numHandlers + 1;
+ }
+ handlers[numHandlers].BlockHandler = blockHandler;
+ handlers[numHandlers].WakeupHandler = wakeupHandler;
+ handlers[numHandlers].blockData = blockData;
+ handlers[numHandlers].deleted = FALSE;
+ numHandlers = numHandlers + 1;
+ return TRUE;
+}
+
+void
+RemoveBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler,
+ WakeupHandlerProcPtr wakeupHandler,
+ pointer blockData)
+{
+ int i;
+
+ for (i = 0; i < numHandlers; i++)
+ if (handlers[i].BlockHandler == blockHandler &&
+ handlers[i].WakeupHandler == wakeupHandler &&
+ handlers[i].blockData == blockData)
+ {
+ if (inHandler)
+ {
+ handlerDeleted = TRUE;
+ handlers[i].deleted = TRUE;
+ }
+ else
+ {
+ for (; i < numHandlers - 1; i++)
+ handlers[i] = handlers[i+1];
+ numHandlers--;
+ }
+ break;
+ }
+}
+
+void
+InitBlockAndWakeupHandlers (void)
+{
+ free(handlers);
+ handlers = (BlockHandlerPtr) 0;
+ numHandlers = 0;
+ sizeHandlers = 0;
+}
+
+/*
+ * A general work queue. Perform some task before the server
+ * sleeps for input.
+ */
+
+WorkQueuePtr workQueue;
+static WorkQueuePtr *workQueueLast = &workQueue;
+
+void
+ProcessWorkQueue(void)
+{
+ WorkQueuePtr q, *p;
+
+ p = &workQueue;
+ /*
+ * Scan the work queue once, calling each function. Those
+ * which return TRUE are removed from the queue, otherwise
+ * they will be called again. This must be reentrant with
+ * QueueWorkProc.
+ */
+ while ((q = *p))
+ {
+ if ((*q->function) (q->client, q->closure))
+ {
+ /* remove q from the list */
+ *p = q->next; /* don't fetch until after func called */
+ free(q);
+ }
+ else
+ {
+ p = &q->next; /* don't fetch until after func called */
+ }
+ }
+ workQueueLast = p;
+}
+
+void
+ProcessWorkQueueZombies(void)
+{
+ WorkQueuePtr q, *p;
+
+ p = &workQueue;
+ while ((q = *p))
+ {
+ if (q->client && q->client->clientGone)
+ {
+ (void) (*q->function) (q->client, q->closure);
+ /* remove q from the list */
+ *p = q->next; /* don't fetch until after func called */
+ free(q);
+ }
+ else
+ {
+ p = &q->next; /* don't fetch until after func called */
+ }
+ }
+ workQueueLast = p;
+}
+
+Bool
+QueueWorkProc (
+ Bool (*function)(ClientPtr /* pClient */, pointer /* closure */),
+ ClientPtr client, pointer closure)
+{
+ WorkQueuePtr q;
+
+ q = malloc(sizeof *q);
+ if (!q)
+ return FALSE;
+ q->function = function;
+ q->client = client;
+ q->closure = closure;
+ q->next = NULL;
+ *workQueueLast = q;
+ workQueueLast = &q->next;
+ return TRUE;
+}
+
+/*
+ * Manage a queue of sleeping clients, awakening them
+ * when requested, by using the OS functions IgnoreClient
+ * and AttendClient. Note that this *ignores* the troubles
+ * with request data interleaving itself with events, but
+ * we'll leave that until a later time.
+ */
+
+typedef struct _SleepQueue {
+ struct _SleepQueue *next;
+ ClientPtr client;
+ ClientSleepProcPtr function;
+ pointer closure;
+} SleepQueueRec, *SleepQueuePtr;
+
+static SleepQueuePtr sleepQueue = NULL;
+
+Bool
+ClientSleep (ClientPtr client, ClientSleepProcPtr function, pointer closure)
+{
+ SleepQueuePtr q;
+
+ q = malloc(sizeof *q);
+ if (!q)
+ return FALSE;
+
+ IgnoreClient (client);
+ q->next = sleepQueue;
+ q->client = client;
+ q->function = function;
+ q->closure = closure;
+ sleepQueue = q;
+ return TRUE;
+}
+
+Bool
+ClientSignal (ClientPtr client)
+{
+ SleepQueuePtr q;
+
+ for (q = sleepQueue; q; q = q->next)
+ if (q->client == client)
+ {
+ return QueueWorkProc (q->function, q->client, q->closure);
+ }
+ return FALSE;
+}
+
+void
+ClientWakeup (ClientPtr client)
+{
+ SleepQueuePtr q, *prev;
+
+ prev = &sleepQueue;
+ while ( (q = *prev) )
+ {
+ if (q->client == client)
+ {
+ *prev = q->next;
+ free(q);
+ if (client->clientGone)
+ /* Oops -- new zombie cleanup code ensures this only
+ * happens from inside CloseDownClient; don't want to
+ * recurse here...
+ */
+ /* CloseDownClient(client) */;
+ else
+ AttendClient (client);
+ break;
+ }
+ prev = &q->next;
+ }
+}
+
+Bool
+ClientIsAsleep (ClientPtr client)
+{
+ SleepQueuePtr q;
+
+ for (q = sleepQueue; q; q = q->next)
+ if (q->client == client)
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Generic Callback Manager
+ */
+
+/* ===== Private Procedures ===== */
+
+static int numCallbackListsToCleanup = 0;
+static CallbackListPtr **listsToCleanup = NULL;
+
+static Bool
+_AddCallback(
+ CallbackListPtr *pcbl,
+ CallbackProcPtr callback,
+ pointer data)
+{
+ CallbackPtr cbr;
+
+ cbr = malloc(sizeof(CallbackRec));
+ if (!cbr)
+ return FALSE;
+ cbr->proc = callback;
+ cbr->data = data;
+ cbr->next = (*pcbl)->list;
+ cbr->deleted = FALSE;
+ (*pcbl)->list = cbr;
+ return TRUE;
+}
+
+static Bool
+_DeleteCallback(
+ CallbackListPtr *pcbl,
+ CallbackProcPtr callback,
+ pointer data)
+{
+ CallbackListPtr cbl = *pcbl;
+ CallbackPtr cbr, pcbr;
+
+ for (pcbr = NULL, cbr = cbl->list;
+ cbr != NULL;
+ pcbr = cbr, cbr = cbr->next)
+ {
+ if ((cbr->proc == callback) && (cbr->data == data))
+ break;
+ }
+ if (cbr != NULL)
+ {
+ if (cbl->inCallback)
+ {
+ ++(cbl->numDeleted);
+ cbr->deleted = TRUE;
+ }
+ else
+ {
+ if (pcbr == NULL)
+ cbl->list = cbr->next;
+ else
+ pcbr->next = cbr->next;
+ free(cbr);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+_CallCallbacks(
+ CallbackListPtr *pcbl,
+ pointer call_data)
+{
+ CallbackListPtr cbl = *pcbl;
+ CallbackPtr cbr, pcbr;
+
+ ++(cbl->inCallback);
+ for (cbr = cbl->list; cbr != NULL; cbr = cbr->next)
+ {
+ (*(cbr->proc)) (pcbl, cbr->data, call_data);
+ }
+ --(cbl->inCallback);
+
+ if (cbl->inCallback) return;
+
+ /* Was the entire list marked for deletion? */
+
+ if (cbl->deleted)
+ {
+ DeleteCallbackList(pcbl);
+ return;
+ }
+
+ /* Were some individual callbacks on the list marked for deletion?
+ * If so, do the deletions.
+ */
+
+ if (cbl->numDeleted)
+ {
+ for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; )
+ {
+ if (cbr->deleted)
+ {
+ if (pcbr)
+ {
+ cbr = cbr->next;
+ free(pcbr->next);
+ pcbr->next = cbr;
+ } else
+ {
+ cbr = cbr->next;
+ free(cbl->list);
+ cbl->list = cbr;
+ }
+ cbl->numDeleted--;
+ }
+ else /* this one wasn't deleted */
+ {
+ pcbr = cbr;
+ cbr = cbr->next;
+ }
+ }
+ }
+}
+
+static void
+_DeleteCallbackList(
+ CallbackListPtr *pcbl)
+{
+ CallbackListPtr cbl = *pcbl;
+ CallbackPtr cbr, nextcbr;
+ int i;
+
+ if (cbl->inCallback)
+ {
+ cbl->deleted = TRUE;
+ return;
+ }
+
+ for (i = 0; i < numCallbackListsToCleanup; i++)
+ {
+ if (listsToCleanup[i] == pcbl)
+ {
+ listsToCleanup[i] = NULL;
+ break;
+ }
+ }
+
+ for (cbr = cbl->list; cbr != NULL; cbr = nextcbr)
+ {
+ nextcbr = cbr->next;
+ free(cbr);
+ }
+ free(cbl);
+ *pcbl = NULL;
+}
+
+static Bool
+CreateCallbackList(CallbackListPtr *pcbl)
+{
+ CallbackListPtr cbl;
+ int i;
+
+ if (!pcbl) return FALSE;
+ cbl = malloc(sizeof(CallbackListRec));
+ if (!cbl) return FALSE;
+ cbl->inCallback = 0;
+ cbl->deleted = FALSE;
+ cbl->numDeleted = 0;
+ cbl->list = NULL;
+ *pcbl = cbl;
+
+ for (i = 0; i < numCallbackListsToCleanup; i++)
+ {
+ if (!listsToCleanup[i])
+ {
+ listsToCleanup[i] = pcbl;
+ return TRUE;
+ }
+ }
+
+ listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup,
+ sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1));
+ listsToCleanup[numCallbackListsToCleanup] = pcbl;
+ numCallbackListsToCleanup++;
+ return TRUE;
+}
+
+/* ===== Public Procedures ===== */
+
+Bool
+AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
+{
+ if (!pcbl) return FALSE;
+ if (!*pcbl)
+ { /* list hasn't been created yet; go create it */
+ if (!CreateCallbackList(pcbl))
+ return FALSE;
+ }
+ return _AddCallback(pcbl, callback, data);
+}
+
+Bool
+DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
+{
+ if (!pcbl || !*pcbl) return FALSE;
+ return _DeleteCallback(pcbl, callback, data);
+}
+
+void
+DeleteCallbackList(CallbackListPtr *pcbl)
+{
+ if (!pcbl || !*pcbl) return;
+ _DeleteCallbackList(pcbl);
+}
+
+void
+InitCallbackManager(void)
+{
+ int i;
+
+ for (i = 0; i < numCallbackListsToCleanup; i++)
+ {
+ DeleteCallbackList(listsToCleanup[i]);
+ }
+ free(listsToCleanup);
+
+ numCallbackListsToCleanup = 0;
+ listsToCleanup = NULL;
+}
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index c935c971c..a12462a4a 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -320,6 +320,8 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
* position of the pointer */
pDev->last.valuators[0] = master->last.valuators[0];
pDev->last.valuators[1] = master->last.valuators[1];
+ pDev->last.remainder[0] = master->last.remainder[0];
+ pDev->last.remainder[1] = master->last.remainder[1];
if (!pDev->valuator)
return;
@@ -339,14 +341,19 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
if ((lastSlave = master->last.slave) && lastSlave->valuator) {
for (i = 2; i < pDev->valuator->numAxes; i++) {
if (i >= lastSlave->valuator->numAxes)
+ {
pDev->last.valuators[i] = 0;
+ pDev->last.remainder[i] = 0;
+ }
else
+ {
pDev->last.valuators[i] =
rescaleValuatorAxis(pDev->last.valuators[i],
pDev->last.remainder[i],
&pDev->last.remainder[i],
lastSlave->valuator->axes + i,
pDev->valuator->axes + i, 0);
+ }
}
}
@@ -1164,14 +1171,17 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
- raw = &events->raw_event;
- events++;
- num_events++;
-
valuator_mask_copy(&mask, mask_in);
- init_raw(pDev, raw, ms, type, buttons);
- set_raw_valuators(raw, &mask, raw->valuators.data_raw);
+ if ((flags & POINTER_NORAW) == 0)
+ {
+ raw = &events->raw_event;
+ events++;
+ num_events++;
+
+ init_raw(pDev, raw, ms, type, buttons);
+ set_raw_valuators(raw, &mask, raw->valuators.data_raw);
+ }
if (flags & POINTER_ABSOLUTE)
{
@@ -1210,7 +1220,8 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
moveRelative(pDev, &x, &y, &mask);
}
- set_raw_valuators(raw, &mask, raw->valuators.data);
+ if ((flags & POINTER_NORAW) == 0)
+ set_raw_valuators(raw, &mask, raw->valuators.data);
positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
&x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
diff --git a/xorg-server/dix/grabs.c b/xorg-server/dix/grabs.c
index a14181108..85ca9eee0 100644
--- a/xorg-server/dix/grabs.c
+++ b/xorg-server/dix/grabs.c
@@ -1,557 +1,669 @@
-/*
-
-Copyright 1987, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-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 Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL 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_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include "misc.h"
-#include <X11/Xproto.h>
-#include <X11/extensions/XI2.h>
-#include "windowstr.h"
-#include "inputstr.h"
-#include "cursorstr.h"
-#include "dixgrabs.h"
-#include "xace.h"
-#include "exevents.h"
-
-#define BITMASK(i) (((Mask)1) << ((i) & 31))
-#define MASKIDX(i) ((i) >> 5)
-#define MASKWORD(buf, i) buf[MASKIDX(i)]
-#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
-#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
-#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
-
-GrabPtr
-CreateGrab(
- int client,
- DeviceIntPtr device,
- DeviceIntPtr modDevice,
- WindowPtr window,
- GrabType grabtype,
- GrabMask *mask,
- GrabParameters *param,
- int type,
- KeyCode keybut, /* key or button */
- WindowPtr confineTo,
- CursorPtr cursor)
-{
- GrabPtr grab;
-
- grab = calloc(1, sizeof(GrabRec));
- if (!grab)
- return (GrabPtr)NULL;
- grab->resource = FakeClientID(client);
- grab->device = device;
- grab->window = window;
- grab->eventMask = mask->core; /* same for XI */
- grab->deviceMask = 0;
- grab->ownerEvents = param->ownerEvents;
- grab->keyboardMode = param->this_device_mode;
- grab->pointerMode = param->other_devices_mode;
- grab->modifiersDetail.exact = param->modifiers;
- grab->modifiersDetail.pMask = NULL;
- grab->modifierDevice = modDevice;
- grab->type = type;
- grab->grabtype = grabtype;
- grab->detail.exact = keybut;
- grab->detail.pMask = NULL;
- grab->confineTo = confineTo;
- grab->cursor = cursor;
- grab->next = NULL;
-
- if (grabtype == GRABTYPE_XI2)
- memcpy(grab->xi2mask, mask->xi2mask, sizeof(mask->xi2mask));
- if (cursor)
- cursor->refcnt++;
- return grab;
-
-}
-
-static void
-FreeGrab(GrabPtr pGrab)
-{
- free(pGrab->modifiersDetail.pMask);
- free(pGrab->detail.pMask);
-
- if (pGrab->cursor)
- FreeCursor(pGrab->cursor, (Cursor)0);
-
- free(pGrab);
-}
-
-int
-DeletePassiveGrab(pointer value, XID id)
-{
- GrabPtr g, prev;
- GrabPtr pGrab = (GrabPtr)value;
-
- /* it is OK if the grab isn't found */
- prev = 0;
- for (g = (wPassiveGrabs (pGrab->window)); g; g = g->next)
- {
- if (pGrab == g)
- {
- if (prev)
- prev->next = g->next;
- else
- if (!(pGrab->window->optional->passiveGrabs = g->next))
- CheckWindowOptionalNeed (pGrab->window);
- break;
- }
- prev = g;
- }
- FreeGrab(pGrab);
- return Success;
-}
-
-static Mask *
-DeleteDetailFromMask(Mask *pDetailMask, unsigned int detail)
-{
- Mask *mask;
- int i;
-
- mask = malloc(sizeof(Mask) * MasksPerDetailMask);
- if (mask)
- {
- if (pDetailMask)
- for (i = 0; i < MasksPerDetailMask; i++)
- mask[i]= pDetailMask[i];
- else
- for (i = 0; i < MasksPerDetailMask; i++)
- mask[i]= ~0L;
- BITCLEAR(mask, detail);
- }
- return mask;
-}
-
-static Bool
-IsInGrabMask(
- DetailRec firstDetail,
- DetailRec secondDetail,
- unsigned int exception)
-{
- if (firstDetail.exact == exception)
- {
- if (firstDetail.pMask == NULL)
- return TRUE;
-
- /* (at present) never called with two non-null pMasks */
- if (secondDetail.exact == exception)
- return FALSE;
-
- if (GETBIT(firstDetail.pMask, secondDetail.exact))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static Bool
-IdenticalExactDetails(
- unsigned int firstExact,
- unsigned int secondExact,
- unsigned int exception)
-{
- if ((firstExact == exception) || (secondExact == exception))
- return FALSE;
-
- if (firstExact == secondExact)
- return TRUE;
-
- return FALSE;
-}
-
-static Bool
-DetailSupersedesSecond(
- DetailRec firstDetail,
- DetailRec secondDetail,
- unsigned int exception)
-{
- if (IsInGrabMask(firstDetail, secondDetail, exception))
- return TRUE;
-
- if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact,
- exception))
- return TRUE;
-
- return FALSE;
-}
-
-static Bool
-GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
-{
- unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ?
- (unsigned int)XIAnyModifier :
- (unsigned int)AnyModifier;
- if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail,
- pSecondGrab->modifiersDetail,
- any_modifier))
- return FALSE;
-
- if (DetailSupersedesSecond(pFirstGrab->detail,
- pSecondGrab->detail, (unsigned int)AnyKey))
- return TRUE;
-
- return FALSE;
-}
-
-/**
- * Compares two grabs and returns TRUE if the first grab matches the second
- * grab.
- *
- * A match is when
- * - the devices set for the grab are equal (this is optional).
- * - the event types for both grabs are equal.
- * - XXX
- *
- * @param ignoreDevice TRUE if the device settings on the grabs are to be
- * ignored.
- * @return TRUE if the grabs match or FALSE otherwise.
- */
-Bool
-GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab, Bool ignoreDevice)
-{
- unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ?
- (unsigned int)XIAnyModifier :
- (unsigned int)AnyModifier;
-
- if (pFirstGrab->grabtype != pSecondGrab->grabtype)
- return FALSE;
-
- if (pFirstGrab->grabtype == GRABTYPE_XI2)
- {
- if (pFirstGrab->device == inputInfo.all_devices ||
- pSecondGrab->device == inputInfo.all_devices)
- {
- /* do nothing */
- } else if (pFirstGrab->device == inputInfo.all_master_devices)
- {
- if (pSecondGrab->device != inputInfo.all_master_devices &&
- !IsMaster(pSecondGrab->device))
- return FALSE;
- } else if (pSecondGrab->device == inputInfo.all_master_devices)
- {
- if (pFirstGrab->device != inputInfo.all_master_devices &&
- !IsMaster(pFirstGrab->device))
- return FALSE;
- } else if (pSecondGrab->device != pFirstGrab->device)
- return FALSE;
- } else if (!ignoreDevice &&
- ((pFirstGrab->device != pSecondGrab->device) ||
- (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice)))
- return FALSE;
-
- if (pFirstGrab->type != pSecondGrab->type)
- return FALSE;
-
- if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
- GrabSupersedesSecond(pSecondGrab, pFirstGrab))
- return TRUE;
-
- if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail,
- (unsigned int)AnyKey)
- &&
- DetailSupersedesSecond(pFirstGrab->modifiersDetail,
- pSecondGrab->modifiersDetail,
- any_modifier))
- return TRUE;
-
- if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail,
- (unsigned int)AnyKey)
- &&
- DetailSupersedesSecond(pSecondGrab->modifiersDetail,
- pFirstGrab->modifiersDetail,
- any_modifier))
- return TRUE;
-
- return FALSE;
-}
-
-static Bool
-GrabsAreIdentical(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
-{
- unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ?
- (unsigned int)XIAnyModifier :
- (unsigned int)AnyModifier;
-
- if (pFirstGrab->grabtype != pSecondGrab->grabtype)
- return FALSE;
-
- if (pFirstGrab->device != pSecondGrab->device ||
- (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) ||
- (pFirstGrab->type != pSecondGrab->type))
- return FALSE;
-
- if (!(DetailSupersedesSecond(pFirstGrab->detail,
- pSecondGrab->detail,
- (unsigned int)AnyKey) &&
- DetailSupersedesSecond(pSecondGrab->detail,
- pFirstGrab->detail,
- (unsigned int)AnyKey)))
- return FALSE;
-
-
- if (!(DetailSupersedesSecond(pFirstGrab->modifiersDetail,
- pSecondGrab->modifiersDetail,
- any_modifier) &&
- DetailSupersedesSecond(pSecondGrab->modifiersDetail,
- pFirstGrab->modifiersDetail,
- any_modifier)))
- return FALSE;
-
- return TRUE;
-}
-
-
-/**
- * Prepend the new grab to the list of passive grabs on the window.
- * Any previously existing grab that matches the new grab will be removed.
- * Adding a new grab that would override another client's grab will result in
- * a BadAccess.
- *
- * @return Success or X error code on failure.
- */
-int
-AddPassiveGrabToList(ClientPtr client, GrabPtr pGrab)
-{
- GrabPtr grab;
- Mask access_mode = DixGrabAccess;
- int rc;
-
- for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
- {
- if (GrabMatchesSecond(pGrab, grab, FALSE))
- {
- if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource))
- {
- FreeGrab(pGrab);
- return BadAccess;
- }
- }
- }
-
- if (pGrab->keyboardMode == GrabModeSync||pGrab->pointerMode == GrabModeSync)
- access_mode |= DixFreezeAccess;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, pGrab->device, access_mode);
- if (rc != Success)
- return rc;
-
- /* Remove all grabs that match the new one exactly */
- for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
- {
- if (GrabsAreIdentical(pGrab, grab))
- {
- DeletePassiveGrabFromList(grab);
- break;
- }
- }
-
- if (!pGrab->window->optional && !MakeWindowOptional (pGrab->window))
- {
- FreeGrab(pGrab);
- return BadAlloc;
- }
-
- pGrab->next = pGrab->window->optional->passiveGrabs;
- pGrab->window->optional->passiveGrabs = pGrab;
- if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab))
- return Success;
- return BadAlloc;
-}
-
-/* the following is kinda complicated, because we need to be able to back out
- * if any allocation fails
- */
-
-Bool
-DeletePassiveGrabFromList(GrabPtr pMinuendGrab)
-{
- GrabPtr grab;
- GrabPtr *deletes, *adds;
- Mask ***updates, **details;
- int i, ndels, nadds, nups;
- Bool ok;
- unsigned int any_modifier;
- unsigned int any_key;
-
-#define UPDATE(mask,exact) \
- if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \
- ok = FALSE; \
- else \
- updates[nups++] = &(mask)
-
- i = 0;
- for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next)
- i++;
- if (!i)
- return TRUE;
- deletes = malloc(i * sizeof(GrabPtr));
- adds = malloc(i * sizeof(GrabPtr));
- updates = malloc(i * sizeof(Mask **));
- details = malloc(i * sizeof(Mask *));
- if (!deletes || !adds || !updates || !details)
- {
- free(details);
- free(updates);
- free(adds);
- free(deletes);
- return FALSE;
- }
-
- any_modifier = (pMinuendGrab->grabtype == GRABTYPE_XI2) ?
- (unsigned int)XIAnyModifier : (unsigned int)AnyModifier;
- any_key = (pMinuendGrab->grabtype == GRABTYPE_XI2) ?
- (unsigned int)XIAnyKeycode : (unsigned int)AnyKey;
- ndels = nadds = nups = 0;
- ok = TRUE;
- for (grab = wPassiveGrabs(pMinuendGrab->window);
- grab && ok;
- grab = grab->next)
- {
- if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) ||
- !GrabMatchesSecond(grab, pMinuendGrab,
- (grab->grabtype == GRABTYPE_CORE)))
- continue;
- if (GrabSupersedesSecond(pMinuendGrab, grab))
- {
- deletes[ndels++] = grab;
- }
- else if ((grab->detail.exact == any_key)
- && (grab->modifiersDetail.exact != any_modifier))
- {
- UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
- }
- else if ((grab->modifiersDetail.exact == any_modifier)
- && (grab->detail.exact != any_key))
- {
- UPDATE(grab->modifiersDetail.pMask,
- pMinuendGrab->modifiersDetail.exact);
- }
- else if ((pMinuendGrab->detail.exact != any_key)
- && (pMinuendGrab->modifiersDetail.exact != any_modifier))
- {
- GrabPtr pNewGrab;
- GrabParameters param;
-
- UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
-
- memset(&param, 0, sizeof(param));
- param.ownerEvents = grab->ownerEvents;
- param.this_device_mode = grab->keyboardMode;
- param.other_devices_mode = grab->pointerMode;
- param.modifiers = any_modifier;
-
- pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device,
- grab->modifierDevice, grab->window,
- grab->grabtype,
- (GrabMask*)&grab->eventMask,
- &param, (int)grab->type,
- pMinuendGrab->detail.exact,
- grab->confineTo, grab->cursor);
- if (!pNewGrab)
- ok = FALSE;
- else if (!(pNewGrab->modifiersDetail.pMask =
- DeleteDetailFromMask(grab->modifiersDetail.pMask,
- pMinuendGrab->modifiersDetail.exact))
- ||
- (!pNewGrab->window->optional &&
- !MakeWindowOptional(pNewGrab->window)))
- {
- FreeGrab(pNewGrab);
- ok = FALSE;
- }
- else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB,
- (pointer)pNewGrab))
- ok = FALSE;
- else
- adds[nadds++] = pNewGrab;
- }
- else if (pMinuendGrab->detail.exact == any_key)
- {
- UPDATE(grab->modifiersDetail.pMask,
- pMinuendGrab->modifiersDetail.exact);
- }
- else
- {
- UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
- }
- }
-
- if (!ok)
- {
- for (i = 0; i < nadds; i++)
- FreeResource(adds[i]->resource, RT_NONE);
- for (i = 0; i < nups; i++)
- free(details[i]);
- }
- else
- {
- for (i = 0; i < ndels; i++)
- FreeResource(deletes[i]->resource, RT_NONE);
- for (i = 0; i < nadds; i++)
- {
- grab = adds[i];
- grab->next = grab->window->optional->passiveGrabs;
- grab->window->optional->passiveGrabs = grab;
- }
- for (i = 0; i < nups; i++)
- {
- free(*updates[i]);
- *updates[i] = details[i];
- }
- }
- free(details);
- free(updates);
- free(adds);
- free(deletes);
- return ok;
-
-#undef UPDATE
-}
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "misc.h"
+#include <X11/Xproto.h>
+#include <X11/extensions/XI2.h>
+#include "windowstr.h"
+#include "inputstr.h"
+#include "cursorstr.h"
+#include "dixgrabs.h"
+#include "xace.h"
+#include "exevents.h"
+
+#define BITMASK(i) (((Mask)1) << ((i) & 31))
+#define MASKIDX(i) ((i) >> 5)
+#define MASKWORD(buf, i) buf[MASKIDX(i)]
+#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
+#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
+#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
+
+void
+PrintDeviceGrabInfo(DeviceIntPtr dev)
+{
+ ClientPtr client;
+ LocalClientCredRec *lcc;
+ int i, j;
+ GrabInfoPtr devGrab = &dev->deviceGrab;
+ GrabPtr grab = devGrab->grab;
+
+ ErrorF("Active grab 0x%lx (%s) on device '%s' (%d):",
+ (unsigned long) grab->resource,
+ (grab->grabtype == GRABTYPE_XI2) ? "xi2" :
+ ((grab->grabtype == GRABTYPE_CORE) ? "core" : "xi1"),
+ dev->name, dev->id);
+
+ client = clients[CLIENT_ID(grab->resource)];
+ if (client && GetLocalClientCreds(client, &lcc) != -1)
+ {
+ ErrorF(" client pid %ld uid %ld gid %ld\n",
+ (lcc->fieldsSet & LCC_PID_SET) ? (long) lcc->pid : 0,
+ (lcc->fieldsSet & LCC_UID_SET) ? (long) lcc->euid : 0,
+ (lcc->fieldsSet & LCC_GID_SET) ? (long) lcc->egid : 0);
+ FreeLocalClientCreds(lcc);
+ }
+ else
+ {
+ ErrorF(" (no client information available)\n");
+ }
+
+ /* XXX is this even correct? */
+ if (devGrab->sync.other)
+ ErrorF(" grab ID 0x%lx from paired device\n",
+ (unsigned long) devGrab->sync.other->resource);
+
+ ErrorF(" at %ld (from %s grab)%s (device %s, state %d)\n",
+ (unsigned long) devGrab->grabTime.milliseconds,
+ devGrab->fromPassiveGrab ? "passive" : "active",
+ devGrab->implicitGrab ? " (implicit)" : "",
+ devGrab->sync.frozen ? "frozen" : "thawed",
+ devGrab->sync.state);
+
+ if (grab->grabtype == GRABTYPE_CORE)
+ {
+ ErrorF(" core event mask 0x%lx\n",
+ (unsigned long) grab->eventMask);
+ }
+ else if (grab->grabtype == GRABTYPE_XI)
+ {
+ ErrorF(" xi1 event mask 0x%lx\n",
+ devGrab->implicitGrab ? (unsigned long) grab->deviceMask :
+ (unsigned long) grab->eventMask);
+ }
+ else if (grab->grabtype == GRABTYPE_XI2)
+ {
+ for (i = 0; i < EMASKSIZE; i++)
+ {
+ int print;
+ print = 0;
+ for (j = 0; j < XI2MASKSIZE; j++)
+ {
+ if (grab->xi2mask[i][j])
+ {
+ print = 1;
+ break;
+ }
+ }
+ if (!print)
+ continue;
+ ErrorF(" xi2 event mask for device %d: 0x", dev->id);
+ for (j = 0; j < XI2MASKSIZE; j++)
+ ErrorF("%x", grab->xi2mask[i][j]);
+ ErrorF("\n");
+ }
+ }
+
+ if (devGrab->fromPassiveGrab)
+ {
+ ErrorF(" passive grab type %d, detail 0x%x, "
+ "activating key %d\n", grab->type, grab->detail.exact,
+ devGrab->activatingKey);
+ }
+
+ ErrorF(" owner-events %s, kb %d ptr %d, confine %lx, cursor 0x%lx\n",
+ grab->ownerEvents ? "true" : "false",
+ grab->keyboardMode, grab->pointerMode,
+ grab->confineTo ? (unsigned long) grab->confineTo->drawable.id : 0,
+ grab->cursor ? (unsigned long) grab->cursor->id : 0);
+}
+
+void
+UngrabAllDevices(Bool kill_client)
+{
+ DeviceIntPtr dev;
+ ClientPtr client;
+
+ ErrorF("Ungrabbing all devices%s; grabs listed below:\n",
+ kill_client ? " and killing their owners" : "");
+
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (!dev->deviceGrab.grab)
+ continue;
+ PrintDeviceGrabInfo(dev);
+ client = clients[CLIENT_ID(dev->deviceGrab.grab->resource)];
+ if (!client || client->clientGone)
+ dev->deviceGrab.DeactivateGrab(dev);
+ CloseDownClient(client);
+ }
+
+ ErrorF("End list of ungrabbed devices\n");
+}
+
+GrabPtr
+CreateGrab(
+ int client,
+ DeviceIntPtr device,
+ DeviceIntPtr modDevice,
+ WindowPtr window,
+ GrabType grabtype,
+ GrabMask *mask,
+ GrabParameters *param,
+ int type,
+ KeyCode keybut, /* key or button */
+ WindowPtr confineTo,
+ CursorPtr cursor)
+{
+ GrabPtr grab;
+
+ grab = calloc(1, sizeof(GrabRec));
+ if (!grab)
+ return (GrabPtr)NULL;
+ grab->resource = FakeClientID(client);
+ grab->device = device;
+ grab->window = window;
+ grab->eventMask = mask->core; /* same for XI */
+ grab->deviceMask = 0;
+ grab->ownerEvents = param->ownerEvents;
+ grab->keyboardMode = param->this_device_mode;
+ grab->pointerMode = param->other_devices_mode;
+ grab->modifiersDetail.exact = param->modifiers;
+ grab->modifiersDetail.pMask = NULL;
+ grab->modifierDevice = modDevice;
+ grab->type = type;
+ grab->grabtype = grabtype;
+ grab->detail.exact = keybut;
+ grab->detail.pMask = NULL;
+ grab->confineTo = confineTo;
+ grab->cursor = cursor;
+ grab->next = NULL;
+
+ if (grabtype == GRABTYPE_XI2)
+ memcpy(grab->xi2mask, mask->xi2mask, sizeof(mask->xi2mask));
+ if (cursor)
+ cursor->refcnt++;
+ return grab;
+
+}
+
+static void
+FreeGrab(GrabPtr pGrab)
+{
+ free(pGrab->modifiersDetail.pMask);
+ free(pGrab->detail.pMask);
+
+ if (pGrab->cursor)
+ FreeCursor(pGrab->cursor, (Cursor)0);
+
+ free(pGrab);
+}
+
+int
+DeletePassiveGrab(pointer value, XID id)
+{
+ GrabPtr g, prev;
+ GrabPtr pGrab = (GrabPtr)value;
+
+ /* it is OK if the grab isn't found */
+ prev = 0;
+ for (g = (wPassiveGrabs (pGrab->window)); g; g = g->next)
+ {
+ if (pGrab == g)
+ {
+ if (prev)
+ prev->next = g->next;
+ else
+ if (!(pGrab->window->optional->passiveGrabs = g->next))
+ CheckWindowOptionalNeed (pGrab->window);
+ break;
+ }
+ prev = g;
+ }
+ FreeGrab(pGrab);
+ return Success;
+}
+
+static Mask *
+DeleteDetailFromMask(Mask *pDetailMask, unsigned int detail)
+{
+ Mask *mask;
+ int i;
+
+ mask = malloc(sizeof(Mask) * MasksPerDetailMask);
+ if (mask)
+ {
+ if (pDetailMask)
+ for (i = 0; i < MasksPerDetailMask; i++)
+ mask[i]= pDetailMask[i];
+ else
+ for (i = 0; i < MasksPerDetailMask; i++)
+ mask[i]= ~0L;
+ BITCLEAR(mask, detail);
+ }
+ return mask;
+}
+
+static Bool
+IsInGrabMask(
+ DetailRec firstDetail,
+ DetailRec secondDetail,
+ unsigned int exception)
+{
+ if (firstDetail.exact == exception)
+ {
+ if (firstDetail.pMask == NULL)
+ return TRUE;
+
+ /* (at present) never called with two non-null pMasks */
+ if (secondDetail.exact == exception)
+ return FALSE;
+
+ if (GETBIT(firstDetail.pMask, secondDetail.exact))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+IdenticalExactDetails(
+ unsigned int firstExact,
+ unsigned int secondExact,
+ unsigned int exception)
+{
+ if ((firstExact == exception) || (secondExact == exception))
+ return FALSE;
+
+ if (firstExact == secondExact)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool
+DetailSupersedesSecond(
+ DetailRec firstDetail,
+ DetailRec secondDetail,
+ unsigned int exception)
+{
+ if (IsInGrabMask(firstDetail, secondDetail, exception))
+ return TRUE;
+
+ if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact,
+ exception))
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool
+GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
+{
+ unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ?
+ (unsigned int)XIAnyModifier :
+ (unsigned int)AnyModifier;
+ if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail,
+ pSecondGrab->modifiersDetail,
+ any_modifier))
+ return FALSE;
+
+ if (DetailSupersedesSecond(pFirstGrab->detail,
+ pSecondGrab->detail, (unsigned int)AnyKey))
+ return TRUE;
+
+ return FALSE;
+}
+
+/**
+ * Compares two grabs and returns TRUE if the first grab matches the second
+ * grab.
+ *
+ * A match is when
+ * - the devices set for the grab are equal (this is optional).
+ * - the event types for both grabs are equal.
+ * - XXX
+ *
+ * @param ignoreDevice TRUE if the device settings on the grabs are to be
+ * ignored.
+ * @return TRUE if the grabs match or FALSE otherwise.
+ */
+Bool
+GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab, Bool ignoreDevice)
+{
+ unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ?
+ (unsigned int)XIAnyModifier :
+ (unsigned int)AnyModifier;
+
+ if (pFirstGrab->grabtype != pSecondGrab->grabtype)
+ return FALSE;
+
+ if (pFirstGrab->grabtype == GRABTYPE_XI2)
+ {
+ if (pFirstGrab->device == inputInfo.all_devices ||
+ pSecondGrab->device == inputInfo.all_devices)
+ {
+ /* do nothing */
+ } else if (pFirstGrab->device == inputInfo.all_master_devices)
+ {
+ if (pSecondGrab->device != inputInfo.all_master_devices &&
+ !IsMaster(pSecondGrab->device))
+ return FALSE;
+ } else if (pSecondGrab->device == inputInfo.all_master_devices)
+ {
+ if (pFirstGrab->device != inputInfo.all_master_devices &&
+ !IsMaster(pFirstGrab->device))
+ return FALSE;
+ } else if (pSecondGrab->device != pFirstGrab->device)
+ return FALSE;
+ } else if (!ignoreDevice &&
+ ((pFirstGrab->device != pSecondGrab->device) ||
+ (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice)))
+ return FALSE;
+
+ if (pFirstGrab->type != pSecondGrab->type)
+ return FALSE;
+
+ if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
+ GrabSupersedesSecond(pSecondGrab, pFirstGrab))
+ return TRUE;
+
+ if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail,
+ (unsigned int)AnyKey)
+ &&
+ DetailSupersedesSecond(pFirstGrab->modifiersDetail,
+ pSecondGrab->modifiersDetail,
+ any_modifier))
+ return TRUE;
+
+ if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail,
+ (unsigned int)AnyKey)
+ &&
+ DetailSupersedesSecond(pSecondGrab->modifiersDetail,
+ pFirstGrab->modifiersDetail,
+ any_modifier))
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool
+GrabsAreIdentical(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
+{
+ unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ?
+ (unsigned int)XIAnyModifier :
+ (unsigned int)AnyModifier;
+
+ if (pFirstGrab->grabtype != pSecondGrab->grabtype)
+ return FALSE;
+
+ if (pFirstGrab->device != pSecondGrab->device ||
+ (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) ||
+ (pFirstGrab->type != pSecondGrab->type))
+ return FALSE;
+
+ if (!(DetailSupersedesSecond(pFirstGrab->detail,
+ pSecondGrab->detail,
+ (unsigned int)AnyKey) &&
+ DetailSupersedesSecond(pSecondGrab->detail,
+ pFirstGrab->detail,
+ (unsigned int)AnyKey)))
+ return FALSE;
+
+
+ if (!(DetailSupersedesSecond(pFirstGrab->modifiersDetail,
+ pSecondGrab->modifiersDetail,
+ any_modifier) &&
+ DetailSupersedesSecond(pSecondGrab->modifiersDetail,
+ pFirstGrab->modifiersDetail,
+ any_modifier)))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * Prepend the new grab to the list of passive grabs on the window.
+ * Any previously existing grab that matches the new grab will be removed.
+ * Adding a new grab that would override another client's grab will result in
+ * a BadAccess.
+ *
+ * @return Success or X error code on failure.
+ */
+int
+AddPassiveGrabToList(ClientPtr client, GrabPtr pGrab)
+{
+ GrabPtr grab;
+ Mask access_mode = DixGrabAccess;
+ int rc;
+
+ for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
+ {
+ if (GrabMatchesSecond(pGrab, grab, FALSE))
+ {
+ if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource))
+ {
+ FreeGrab(pGrab);
+ return BadAccess;
+ }
+ }
+ }
+
+ if (pGrab->keyboardMode == GrabModeSync||pGrab->pointerMode == GrabModeSync)
+ access_mode |= DixFreezeAccess;
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, pGrab->device, access_mode);
+ if (rc != Success)
+ return rc;
+
+ /* Remove all grabs that match the new one exactly */
+ for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
+ {
+ if (GrabsAreIdentical(pGrab, grab))
+ {
+ DeletePassiveGrabFromList(grab);
+ break;
+ }
+ }
+
+ if (!pGrab->window->optional && !MakeWindowOptional (pGrab->window))
+ {
+ FreeGrab(pGrab);
+ return BadAlloc;
+ }
+
+ pGrab->next = pGrab->window->optional->passiveGrabs;
+ pGrab->window->optional->passiveGrabs = pGrab;
+ if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab))
+ return Success;
+ return BadAlloc;
+}
+
+/* the following is kinda complicated, because we need to be able to back out
+ * if any allocation fails
+ */
+
+Bool
+DeletePassiveGrabFromList(GrabPtr pMinuendGrab)
+{
+ GrabPtr grab;
+ GrabPtr *deletes, *adds;
+ Mask ***updates, **details;
+ int i, ndels, nadds, nups;
+ Bool ok;
+ unsigned int any_modifier;
+ unsigned int any_key;
+
+#define UPDATE(mask,exact) \
+ if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \
+ ok = FALSE; \
+ else \
+ updates[nups++] = &(mask)
+
+ i = 0;
+ for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next)
+ i++;
+ if (!i)
+ return TRUE;
+ deletes = malloc(i * sizeof(GrabPtr));
+ adds = malloc(i * sizeof(GrabPtr));
+ updates = malloc(i * sizeof(Mask **));
+ details = malloc(i * sizeof(Mask *));
+ if (!deletes || !adds || !updates || !details)
+ {
+ free(details);
+ free(updates);
+ free(adds);
+ free(deletes);
+ return FALSE;
+ }
+
+ any_modifier = (pMinuendGrab->grabtype == GRABTYPE_XI2) ?
+ (unsigned int)XIAnyModifier : (unsigned int)AnyModifier;
+ any_key = (pMinuendGrab->grabtype == GRABTYPE_XI2) ?
+ (unsigned int)XIAnyKeycode : (unsigned int)AnyKey;
+ ndels = nadds = nups = 0;
+ ok = TRUE;
+ for (grab = wPassiveGrabs(pMinuendGrab->window);
+ grab && ok;
+ grab = grab->next)
+ {
+ if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) ||
+ !GrabMatchesSecond(grab, pMinuendGrab,
+ (grab->grabtype == GRABTYPE_CORE)))
+ continue;
+ if (GrabSupersedesSecond(pMinuendGrab, grab))
+ {
+ deletes[ndels++] = grab;
+ }
+ else if ((grab->detail.exact == any_key)
+ && (grab->modifiersDetail.exact != any_modifier))
+ {
+ UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
+ }
+ else if ((grab->modifiersDetail.exact == any_modifier)
+ && (grab->detail.exact != any_key))
+ {
+ UPDATE(grab->modifiersDetail.pMask,
+ pMinuendGrab->modifiersDetail.exact);
+ }
+ else if ((pMinuendGrab->detail.exact != any_key)
+ && (pMinuendGrab->modifiersDetail.exact != any_modifier))
+ {
+ GrabPtr pNewGrab;
+ GrabParameters param;
+
+ UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
+
+ memset(&param, 0, sizeof(param));
+ param.ownerEvents = grab->ownerEvents;
+ param.this_device_mode = grab->keyboardMode;
+ param.other_devices_mode = grab->pointerMode;
+ param.modifiers = any_modifier;
+
+ pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device,
+ grab->modifierDevice, grab->window,
+ grab->grabtype,
+ (GrabMask*)&grab->eventMask,
+ &param, (int)grab->type,
+ pMinuendGrab->detail.exact,
+ grab->confineTo, grab->cursor);
+ if (!pNewGrab)
+ ok = FALSE;
+ else if (!(pNewGrab->modifiersDetail.pMask =
+ DeleteDetailFromMask(grab->modifiersDetail.pMask,
+ pMinuendGrab->modifiersDetail.exact))
+ ||
+ (!pNewGrab->window->optional &&
+ !MakeWindowOptional(pNewGrab->window)))
+ {
+ FreeGrab(pNewGrab);
+ ok = FALSE;
+ }
+ else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB,
+ (pointer)pNewGrab))
+ ok = FALSE;
+ else
+ adds[nadds++] = pNewGrab;
+ }
+ else if (pMinuendGrab->detail.exact == any_key)
+ {
+ UPDATE(grab->modifiersDetail.pMask,
+ pMinuendGrab->modifiersDetail.exact);
+ }
+ else
+ {
+ UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
+ }
+ }
+
+ if (!ok)
+ {
+ for (i = 0; i < nadds; i++)
+ FreeResource(adds[i]->resource, RT_NONE);
+ for (i = 0; i < nups; i++)
+ free(details[i]);
+ }
+ else
+ {
+ for (i = 0; i < ndels; i++)
+ FreeResource(deletes[i]->resource, RT_NONE);
+ for (i = 0; i < nadds; i++)
+ {
+ grab = adds[i];
+ grab->next = grab->window->optional->passiveGrabs;
+ grab->window->optional->passiveGrabs = grab;
+ }
+ for (i = 0; i < nups; i++)
+ {
+ free(*updates[i]);
+ *updates[i] = details[i];
+ }
+ }
+ free(details);
+ free(updates);
+ free(adds);
+ free(deletes);
+ return ok;
+
+#undef UPDATE
+}
diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c
index 5defe5849..556509ac3 100644
--- a/xorg-server/dix/window.c
+++ b/xorg-server/dix/window.c
@@ -108,6 +108,7 @@ Equipment Corporation.
#include "regionstr.h"
#include "validate.h"
#include "windowstr.h"
+#include "propertyst.h"
#include "input.h"
#include "inputstr.h"
#include "resource.h"
@@ -124,10 +125,13 @@ Equipment Corporation.
#include "dixevents.h"
#include "globals.h"
#include "mi.h" /* miPaintWindow */
+#include "compint.h"
#include "privates.h"
#include "xace.h"
+#include <X11/Xatom.h> /* must come after server includes */
+
/******
* Window stuff for server
*
@@ -176,46 +180,129 @@ static Bool TileScreenSaver(ScreenPtr pScreen, int kind);
#define SubStrSend(pWin,pParent) (StrSend(pWin) || SubSend(pParent))
-#ifdef DEBUG
-/******
- * PrintWindowTree
- * For debugging only
- ******/
+static const char *overlay_win_name = "<composite overlay>";
-static void
-PrintChildren(WindowPtr p1, int indent)
+static const char *
+get_window_name(WindowPtr pWin)
{
- WindowPtr p2;
- int i;
+#define WINDOW_NAME_BUF_LEN 512
+ PropertyPtr prop;
+ CompScreenPtr comp_screen = GetCompScreen(pWin->drawable.pScreen);
+ static char buf[WINDOW_NAME_BUF_LEN];
+ int len;
+
+ if (comp_screen && pWin == comp_screen->pOverlayWin)
+ return overlay_win_name;
- while (p1)
+ for (prop = wUserProps(pWin); prop; prop = prop->next)
{
- p2 = p1->firstChild;
- ErrorF("[dix] ");
- for (i=0; i<indent; i++) ErrorF(" ");
- ErrorF("%lx\n", p1->drawable.id);
- RegionPrint(&p1->clipList);
- PrintChildren(p2, indent+4);
- p1 = p1->nextSib;
+ if (prop->propertyName == XA_WM_NAME && prop->type == XA_STRING &&
+ prop->data)
+ {
+ len = min(prop->size, WINDOW_NAME_BUF_LEN - 1);
+ memcpy(buf, prop->data, len);
+ buf[len] = '\0';
+ return buf;
+ }
}
+
+ return NULL;
+#undef WINDOW_NAME_BUF_LEN
}
-static void
-PrintWindowTree(void)
+static void log_window_info(WindowPtr pWin, int depth)
{
int i;
- WindowPtr pWin, p1;
+ const char *win_name, *visibility;
+ BoxPtr rects;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ for (i = 0; i < (depth << 2); i++)
+ ErrorF(" ");
+
+ win_name = get_window_name(pWin);
+ ErrorF("win 0x%.8x (%s), [%d, %d] to [%d, %d]",
+ pWin->drawable.id,
+ win_name ? win_name : "no name",
+ pWin->drawable.x, pWin->drawable.y,
+ pWin->drawable.x + pWin->drawable.width,
+ pWin->drawable.y + pWin->drawable.height);
+
+ if (pWin->overrideRedirect)
+ ErrorF(" (override redirect)");
+ if (pWin->redirectDraw)
+ ErrorF(" (%s compositing: pixmap %x)",
+ (pWin->redirectDraw == RedirectDrawAutomatic) ?
+ "automatic" : "manual",
+ pScreen->GetWindowPixmap(pWin)->drawable.id);
+
+ switch (pWin->visibility)
+ {
+ case VisibilityUnobscured:
+ visibility = "unobscured";
+ break;
+ case VisibilityPartiallyObscured:
+ visibility = "partially obscured";
+ break;
+ case VisibilityFullyObscured:
+ visibility = "fully obscured";
+ break;
+ case VisibilityNotViewable:
+ visibility = "unviewable";
+ break;
+ }
+ ErrorF(", %s", visibility);
+
+ if (REGION_NOTEMPTY(pScreen, &pWin->clipList))
+ {
+ ErrorF(", clip list:");
+ rects = REGION_RECTS(&pWin->clipList);
+ for (i = 0; i < REGION_NUM_RECTS(&pWin->clipList); i++)
+ ErrorF(" [(%d, %d) to (%d, %d)]",
+ rects[i].x1, rects[i].y1,
+ rects[i].x2, rects[i].y2);
+ ErrorF("; extents [(%d, %d) to (%d, %d)]",
+ pWin->clipList.extents.x1, pWin->clipList.extents.y1,
+ pWin->clipList.extents.x2, pWin->clipList.extents.y2);
+ }
+
+ ErrorF("\n");
+}
+
+void
+PrintWindowTree(void)
+{
+ int scrnum, depth;
+ ScreenPtr pScreen;
+ WindowPtr pWin;
- for (i=0; i<screenInfo.numScreens; i++)
+ for (scrnum = 0; scrnum < screenInfo.numScreens; scrnum++)
{
- ErrorF("[dix] WINDOW %d\n", i);
- pWin = screenInfo.screens[i]->root;
- RegionPrint(&pWin->clipList);
- p1 = pWin->firstChild;
- PrintChildren(p1, 4);
+ pScreen = screenInfo.screens[scrnum];
+ ErrorF("[dix] Dumping windows for screen %d (pixmap %x):\n", scrnum,
+ pScreen->GetScreenPixmap(pScreen)->drawable.id);
+ pWin = pScreen->root;
+ depth = 1;
+ while (pWin)
+ {
+ log_window_info(pWin, depth);
+ if (pWin->firstChild)
+ {
+ pWin = pWin->firstChild;
+ depth++;
+ continue;
+ }
+ while (pWin && !pWin->nextSib)
+ {
+ pWin = pWin->parent;
+ depth--;
+ }
+ if (!pWin)
+ break;
+ pWin = pWin->nextSib;
+ }
}
}
-#endif
int
TraverseTree(WindowPtr pWin, VisitWindowProcPtr func, pointer data)
diff --git a/xorg-server/exa/exa.c b/xorg-server/exa/exa.c
index a4e294a71..4ce983bc3 100644
--- a/xorg-server/exa/exa.c
+++ b/xorg-server/exa/exa.c
@@ -1,7 +1,7 @@
/*
- * Copyright © 2001 Keith Packard
+ * Copyright © 2001 Keith Packard
*
- * Partly based on code that is Copyright © The XFree86 Project Inc.
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/exa/exa_accel.c b/xorg-server/exa/exa_accel.c
index 9192f7e74..5600539d6 100644
--- a/xorg-server/exa/exa_accel.c
+++ b/xorg-server/exa/exa_accel.c
@@ -1,1306 +1,1306 @@
-/*
- * Copyright © 2001 Keith Packard
- *
- * Partly based on code that is Copyright © The XFree86 Project Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- * Michel Dänzer <michel@tungstengraphics.com>
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-#include "exa_priv.h"
-#include <X11/fonts/fontstruct.h>
-#include "dixfontstr.h"
-#include "exa.h"
-
-static void
-exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
- DDXPointPtr ppt, int *pwidth, int fSorted)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- ExaScreenPriv (pScreen);
- RegionPtr pClip = fbGetCompositeClip(pGC);
- PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
- ExaPixmapPriv (pPixmap);
- BoxPtr pextent, pbox;
- int nbox;
- int extentX1, extentX2, extentY1, extentY2;
- int fullX1, fullX2, fullY1;
- int partX1, partX2;
- int off_x, off_y;
-
- if (pExaScr->fallback_counter ||
- pExaScr->swappedOut ||
- pGC->fillStyle != FillSolid ||
- pExaPixmap->accel_blocked)
- {
- ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
- return;
- }
-
- if (pExaScr->do_migration) {
- ExaMigrationRec pixmaps[1];
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = NULL;
-
- exaDoMigration (pixmaps, 1, TRUE);
- }
-
- if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) ||
- !(*pExaScr->info->PrepareSolid) (pPixmap,
- pGC->alu,
- pGC->planemask,
- pGC->fgPixel))
- {
- ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
- return;
- }
-
- pextent = RegionExtents(pClip);
- extentX1 = pextent->x1;
- extentY1 = pextent->y1;
- extentX2 = pextent->x2;
- extentY2 = pextent->y2;
- while (n--)
- {
- fullX1 = ppt->x;
- fullY1 = ppt->y;
- fullX2 = fullX1 + (int) *pwidth;
- ppt++;
- pwidth++;
-
- if (fullY1 < extentY1 || extentY2 <= fullY1)
- continue;
-
- if (fullX1 < extentX1)
- fullX1 = extentX1;
-
- if (fullX2 > extentX2)
- fullX2 = extentX2;
-
- if (fullX1 >= fullX2)
- continue;
-
- nbox = RegionNumRects (pClip);
- if (nbox == 1)
- {
- (*pExaScr->info->Solid) (pPixmap,
- fullX1 + off_x, fullY1 + off_y,
- fullX2 + off_x, fullY1 + 1 + off_y);
- }
- else
- {
- pbox = RegionRects(pClip);
- while(nbox--)
- {
- if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
- {
- partX1 = pbox->x1;
- if (partX1 < fullX1)
- partX1 = fullX1;
- partX2 = pbox->x2;
- if (partX2 > fullX2)
- partX2 = fullX2;
- if (partX2 > partX1) {
- (*pExaScr->info->Solid) (pPixmap,
- partX1 + off_x, fullY1 + off_y,
- partX2 + off_x, fullY1 + 1 + off_y);
- }
- }
- pbox++;
- }
- }
- }
- (*pExaScr->info->DoneSolid) (pPixmap);
- exaMarkSync(pScreen);
-}
-
-static Bool
-exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
- int w, int h, int format, char *bits, int src_stride)
-{
- ExaScreenPriv (pDrawable->pScreen);
- PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
- ExaPixmapPriv(pPix);
- RegionPtr pClip;
- BoxPtr pbox;
- int nbox;
- int xoff, yoff;
- int bpp = pDrawable->bitsPerPixel;
- Bool ret = TRUE;
-
- if (pExaScr->fallback_counter || pExaPixmap->accel_blocked || !pExaScr->info->UploadToScreen)
- return FALSE;
-
- /* If there's a system copy, we want to save the result there */
- if (pExaPixmap->pDamage)
- return FALSE;
-
- /* Don't bother with under 8bpp, XYPixmaps. */
- if (format != ZPixmap || bpp < 8)
- return FALSE;
-
- /* Only accelerate copies: no rop or planemask. */
- if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
- return FALSE;
-
- if (pExaScr->swappedOut)
- return FALSE;
-
- if (pExaScr->do_migration) {
- ExaMigrationRec pixmaps[1];
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPix;
- pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
-
- exaDoMigration (pixmaps, 1, TRUE);
- }
-
- pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
-
- if (!pPix)
- return FALSE;
-
- x += pDrawable->x;
- y += pDrawable->y;
-
- pClip = fbGetCompositeClip(pGC);
- for (nbox = RegionNumRects(pClip),
- pbox = RegionRects(pClip);
- nbox--;
- pbox++)
- {
- int x1 = x;
- int y1 = y;
- int x2 = x + w;
- int y2 = y + h;
- char *src;
- Bool ok;
-
- if (x1 < pbox->x1)
- x1 = pbox->x1;
- if (y1 < pbox->y1)
- y1 = pbox->y1;
- if (x2 > pbox->x2)
- x2 = pbox->x2;
- if (y2 > pbox->y2)
- y2 = pbox->y2;
- if (x1 >= x2 || y1 >= y2)
- continue;
-
- src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
- ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
- x2 - x1, y2 - y1, src, src_stride);
- /* We have to fall back completely, and ignore what has already been completed.
- * Messing with the fb layer directly like we used to is completely unacceptable.
- */
- if (!ok) {
- ret = FALSE;
- break;
- }
- }
-
- if (ret)
- exaMarkSync(pDrawable->pScreen);
-
- return ret;
-}
-
-static void
-exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
- int w, int h, int leftPad, int format, char *bits)
-{
- if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, format, bits,
- PixmapBytePad(w, pDrawable->depth)))
- ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
- bits);
-}
-
-static Bool inline
-exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
- GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
-{
- ExaScreenPriv (pDstDrawable->pScreen);
- PixmapPtr pSrcPixmap, pDstPixmap;
- int src_off_x, src_off_y, dst_off_x, dst_off_y;
- int dirsetup;
-
- /* Need to get both pixmaps to call the driver routines */
- pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y);
- pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y);
- if (!pSrcPixmap || !pDstPixmap)
- return FALSE;
-
- /*
- * Now the case of a chip that only supports xdir = ydir = 1 or
- * xdir = ydir = -1, but we have xdir != ydir.
- */
- dirsetup = 0; /* No direction set up yet. */
- for (; nbox; pbox++, nbox--) {
- if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
- /* Do a xdir = ydir = -1 blit instead. */
- if (dirsetup != -1) {
- if (dirsetup != 0)
- pExaScr->info->DoneCopy(pDstPixmap);
- dirsetup = -1;
- if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
- pDstPixmap,
- -1, -1,
- pGC ? pGC->alu : GXcopy,
- pGC ? pGC->planemask :
- FB_ALLONES))
- return FALSE;
- }
- (*pExaScr->info->Copy)(pDstPixmap,
- src_off_x + pbox->x1 + dx,
- src_off_y + pbox->y1 + dy,
- dst_off_x + pbox->x1,
- dst_off_y + pbox->y1,
- pbox->x2 - pbox->x1,
- pbox->y2 - pbox->y1);
- } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
- /* Do a xdir = ydir = 1 blit instead. */
- if (dirsetup != 1) {
- if (dirsetup != 0)
- pExaScr->info->DoneCopy(pDstPixmap);
- dirsetup = 1;
- if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
- pDstPixmap,
- 1, 1,
- pGC ? pGC->alu : GXcopy,
- pGC ? pGC->planemask :
- FB_ALLONES))
- return FALSE;
- }
- (*pExaScr->info->Copy)(pDstPixmap,
- src_off_x + pbox->x1 + dx,
- src_off_y + pbox->y1 + dy,
- dst_off_x + pbox->x1,
- dst_off_y + pbox->y1,
- pbox->x2 - pbox->x1,
- pbox->y2 - pbox->y1);
- } else if (dx >= 0) {
- /*
- * xdir = 1, ydir = -1.
- * Perform line-by-line xdir = ydir = 1 blits, going up.
- */
- int i;
- if (dirsetup != 1) {
- if (dirsetup != 0)
- pExaScr->info->DoneCopy(pDstPixmap);
- dirsetup = 1;
- if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
- pDstPixmap,
- 1, 1,
- pGC ? pGC->alu : GXcopy,
- pGC ? pGC->planemask :
- FB_ALLONES))
- return FALSE;
- }
- for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
- (*pExaScr->info->Copy)(pDstPixmap,
- src_off_x + pbox->x1 + dx,
- src_off_y + pbox->y1 + dy + i,
- dst_off_x + pbox->x1,
- dst_off_y + pbox->y1 + i,
- pbox->x2 - pbox->x1, 1);
- } else {
- /*
- * xdir = -1, ydir = 1.
- * Perform line-by-line xdir = ydir = -1 blits, going down.
- */
- int i;
- if (dirsetup != -1) {
- if (dirsetup != 0)
- pExaScr->info->DoneCopy(pDstPixmap);
- dirsetup = -1;
- if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
- pDstPixmap,
- -1, -1,
- pGC ? pGC->alu : GXcopy,
- pGC ? pGC->planemask :
- FB_ALLONES))
- return FALSE;
- }
- for (i = 0; i < pbox->y2 - pbox->y1; i++)
- (*pExaScr->info->Copy)(pDstPixmap,
- src_off_x + pbox->x1 + dx,
- src_off_y + pbox->y1 + dy + i,
- dst_off_x + pbox->x1,
- dst_off_y + pbox->y1 + i,
- pbox->x2 - pbox->x1, 1);
- }
- }
- if (dirsetup != 0)
- pExaScr->info->DoneCopy(pDstPixmap);
- exaMarkSync(pDstDrawable->pScreen);
- return TRUE;
-}
-
-Bool
-exaHWCopyNtoN (DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy,
- Bool reverse,
- Bool upsidedown)
-{
- ExaScreenPriv (pDstDrawable->pScreen);
- PixmapPtr pSrcPixmap, pDstPixmap;
- ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap;
- int src_off_x, src_off_y;
- int dst_off_x, dst_off_y;
- RegionPtr srcregion = NULL, dstregion = NULL;
- xRectangle *rects;
- Bool ret = TRUE;
-
- /* avoid doing copy operations if no boxes */
- if (nbox == 0)
- return TRUE;
-
- pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
- pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
-
- exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y);
- exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y);
-
- rects = malloc(nbox * sizeof(xRectangle));
-
- if (rects) {
- int i;
- int ordering;
-
- for (i = 0; i < nbox; i++) {
- rects[i].x = pbox[i].x1 + dx + src_off_x;
- rects[i].y = pbox[i].y1 + dy + src_off_y;
- rects[i].width = pbox[i].x2 - pbox[i].x1;
- rects[i].height = pbox[i].y2 - pbox[i].y1;
- }
-
- /* This must match the RegionCopy() logic for reversing rect order */
- if (nbox == 1 || (dx > 0 && dy > 0) ||
- (pDstDrawable != pSrcDrawable &&
- (pDstDrawable->type != DRAWABLE_WINDOW ||
- pSrcDrawable->type != DRAWABLE_WINDOW)))
- ordering = CT_YXBANDED;
- else
- ordering = CT_UNSORTED;
-
- srcregion = RegionFromRects(nbox, rects, ordering);
- free(rects);
-
- if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask,
- pGC->fillStyle, pGC->alu,
- pGC->clientClipType)) {
- dstregion = RegionCreate(NullBox, 0);
- RegionCopy(dstregion, srcregion);
- RegionTranslate(dstregion, dst_off_x - dx - src_off_x,
- dst_off_y - dy - src_off_y);
- }
- }
-
-
- pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap);
- pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap);
-
- /* Check whether the accelerator can use this pixmap.
- * If the pitch of the pixmaps is out of range, there's nothing
- * we can do but fall back to software rendering.
- */
- if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH ||
- pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH)
- goto fallback;
-
- /* If the width or the height of either of the pixmaps
- * is out of range, check whether the boxes are actually out of the
- * addressable range as well. If they aren't, we can still do
- * the copying in hardware.
- */
- if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) {
- int i;
-
- for (i = 0; i < nbox; i++) {
- /* src */
- if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX ||
- (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY)
- goto fallback;
-
- /* dst */
- if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX ||
- (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY)
- goto fallback;
- }
- }
-
- if (pExaScr->do_migration) {
- ExaMigrationRec pixmaps[2];
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pDstPixmap;
- pixmaps[0].pReg = dstregion;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPixmap;
- pixmaps[1].pReg = srcregion;
-
- exaDoMigration (pixmaps, 2, TRUE);
- }
-
- /* Mixed directions must be handled specially if the card is lame */
- if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
- reverse != upsidedown) {
- if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
- dx, dy))
- goto out;
- goto fallback;
- }
-
- if (exaPixmapHasGpuCopy(pDstPixmap)) {
- /* Normal blitting. */
- if (exaPixmapHasGpuCopy(pSrcPixmap)) {
- if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
- upsidedown ? -1 : 1,
- pGC ? pGC->alu : GXcopy,
- pGC ? pGC->planemask : FB_ALLONES)) {
- goto fallback;
- }
-
- while (nbox--)
- {
- (*pExaScr->info->Copy) (pDstPixmap,
- pbox->x1 + dx + src_off_x,
- pbox->y1 + dy + src_off_y,
- pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
- pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
- pbox++;
- }
-
- (*pExaScr->info->DoneCopy) (pDstPixmap);
- exaMarkSync (pDstDrawable->pScreen);
- /* UTS: mainly for SHM PutImage's secondary path.
- *
- * Only taking this path for directly accessible pixmaps.
- */
- } else if (!pDstExaPixmap->pDamage && pSrcExaPixmap->sys_ptr) {
- int bpp = pSrcDrawable->bitsPerPixel;
- int src_stride = exaGetPixmapPitch(pSrcPixmap);
- CARD8 *src = NULL;
-
- if (!pExaScr->info->UploadToScreen)
- goto fallback;
-
- if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
- goto fallback;
-
- if (pSrcDrawable->bitsPerPixel < 8)
- goto fallback;
-
- if (pGC && !(pGC->alu == GXcopy && EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask)))
- goto fallback;
-
- while (nbox--)
- {
- src = pSrcExaPixmap->sys_ptr + (pbox->y1 + dy + src_off_y) * src_stride + (pbox->x1 + dx + src_off_x) * (bpp / 8);
- if (!pExaScr->info->UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x,
- pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
- (char *) src, src_stride))
- goto fallback;
-
- pbox++;
- }
- } else
- goto fallback;
- } else
- goto fallback;
-
- goto out;
-
-fallback:
- ret = FALSE;
-
-out:
- if (dstregion) {
- RegionUninit(dstregion);
- RegionDestroy(dstregion);
- }
- if (srcregion) {
- RegionUninit(srcregion);
- RegionDestroy(srcregion);
- }
-
- return ret;
-}
-
-void
-exaCopyNtoN (DrawablePtr pSrcDrawable,
- DrawablePtr pDstDrawable,
- GCPtr pGC,
- BoxPtr pbox,
- int nbox,
- int dx,
- int dy,
- Bool reverse,
- Bool upsidedown,
- Pixel bitplane,
- void *closure)
-{
- ExaScreenPriv(pDstDrawable->pScreen);
-
- if (pExaScr->fallback_counter ||
- (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW))
- return;
-
- if (exaHWCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown))
- return;
-
- /* This is a CopyWindow, it's cleaner to fallback at the original call. */
- if (pExaScr->fallback_flags & EXA_ACCEL_COPYWINDOW) {
- pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW;
- return;
- }
-
- /* fallback */
- ExaCheckCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
-}
-
-RegionPtr
-exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
- int srcx, int srcy, int width, int height, int dstx, int dsty)
-{
- ExaScreenPriv (pDstDrawable->pScreen);
-
- if (pExaScr->fallback_counter || pExaScr->swappedOut) {
- return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC,
- srcx, srcy, width, height, dstx, dsty);
- }
-
- return miDoCopy (pSrcDrawable, pDstDrawable, pGC,
- srcx, srcy, width, height,
- dstx, dsty, exaCopyNtoN, 0, NULL);
-}
-
-static void
-exaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
- DDXPointPtr ppt)
-{
- ExaScreenPriv (pDrawable->pScreen);
- int i;
- xRectangle *prect;
-
- /* If we can't reuse the current GC as is, don't bother accelerating the
- * points.
- */
- if (pExaScr->fallback_counter || pGC->fillStyle != FillSolid) {
- ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt);
- return;
- }
-
- prect = malloc(sizeof(xRectangle) * npt);
- for (i = 0; i < npt; i++) {
- prect[i].x = ppt[i].x;
- prect[i].y = ppt[i].y;
- if (i > 0 && mode == CoordModePrevious) {
- prect[i].x += prect[i - 1].x;
- prect[i].y += prect[i - 1].y;
- }
- prect[i].width = 1;
- prect[i].height = 1;
- }
- pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
- free(prect);
-}
-
-/**
- * exaPolylines() checks if it can accelerate the lines as a group of
- * horizontal or vertical lines (rectangles), and uses existing rectangle fill
- * acceleration if so.
- */
-static void
-exaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
- DDXPointPtr ppt)
-{
- ExaScreenPriv (pDrawable->pScreen);
- xRectangle *prect;
- int x1, x2, y1, y2;
- int i;
-
- if (pExaScr->fallback_counter) {
- ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
- return;
- }
-
- /* Don't try to do wide lines or non-solid fill style. */
- if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
- pGC->fillStyle != FillSolid) {
- ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
- return;
- }
-
- prect = malloc(sizeof(xRectangle) * (npt - 1));
- x1 = ppt[0].x;
- y1 = ppt[0].y;
- /* If we have any non-horizontal/vertical, fall back. */
- for (i = 0; i < npt - 1; i++) {
- if (mode == CoordModePrevious) {
- x2 = x1 + ppt[i + 1].x;
- y2 = y1 + ppt[i + 1].y;
- } else {
- x2 = ppt[i + 1].x;
- y2 = ppt[i + 1].y;
- }
-
- if (x1 != x2 && y1 != y2) {
- free(prect);
- ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
- return;
- }
-
- if (x1 < x2) {
- prect[i].x = x1;
- prect[i].width = x2 - x1 + 1;
- } else {
- prect[i].x = x2;
- prect[i].width = x1 - x2 + 1;
- }
- if (y1 < y2) {
- prect[i].y = y1;
- prect[i].height = y2 - y1 + 1;
- } else {
- prect[i].y = y2;
- prect[i].height = y1 - y2 + 1;
- }
-
- x1 = x2;
- y1 = y2;
- }
- pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
- free(prect);
-}
-
-/**
- * exaPolySegment() checks if it can accelerate the lines as a group of
- * horizontal or vertical lines (rectangles), and uses existing rectangle fill
- * acceleration if so.
- */
-static void
-exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
- xSegment *pSeg)
-{
- ExaScreenPriv (pDrawable->pScreen);
- xRectangle *prect;
- int i;
-
- /* Don't try to do wide lines or non-solid fill style. */
- if (pExaScr->fallback_counter || pGC->lineWidth != 0 ||
- pGC->lineStyle != LineSolid || pGC->fillStyle != FillSolid)
- {
- ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg);
- return;
- }
-
- /* If we have any non-horizontal/vertical, fall back. */
- for (i = 0; i < nseg; i++) {
- if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) {
- ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg);
- return;
- }
- }
-
- prect = malloc(sizeof(xRectangle) * nseg);
- for (i = 0; i < nseg; i++) {
- if (pSeg[i].x1 < pSeg[i].x2) {
- prect[i].x = pSeg[i].x1;
- prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
- } else {
- prect[i].x = pSeg[i].x2;
- prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
- }
- if (pSeg[i].y1 < pSeg[i].y2) {
- prect[i].y = pSeg[i].y1;
- prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
- } else {
- prect[i].y = pSeg[i].y2;
- prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
- }
-
- /* don't paint last pixel */
- if (pGC->capStyle == CapNotLast) {
- if (prect[i].width == 1)
- prect[i].height--;
- else
- prect[i].width--;
- }
- }
- pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
- free(prect);
-}
-
-static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion,
- Pixel pixel, CARD32 planemask, CARD32 alu,
- unsigned int clientClipType);
-
-static void
-exaPolyFillRect(DrawablePtr pDrawable,
- GCPtr pGC,
- int nrect,
- xRectangle *prect)
-{
- ExaScreenPriv (pDrawable->pScreen);
- RegionPtr pClip = fbGetCompositeClip(pGC);
- PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
- ExaPixmapPriv (pPixmap);
- register BoxPtr pbox;
- BoxPtr pextent;
- int extentX1, extentX2, extentY1, extentY2;
- int fullX1, fullX2, fullY1, fullY2;
- int partX1, partX2, partY1, partY2;
- int xoff, yoff;
- int xorg, yorg;
- int n;
- RegionPtr pReg = RegionFromRects(nrect, prect, CT_UNSORTED);
-
- /* Compute intersection of rects and clip region */
- RegionTranslate(pReg, pDrawable->x, pDrawable->y);
- RegionIntersect(pReg, pClip, pReg);
-
- if (!RegionNumRects(pReg)) {
- goto out;
- }
-
- exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
-
- if (pExaScr->fallback_counter || pExaScr->swappedOut ||
- pExaPixmap->accel_blocked)
- {
- goto fallback;
- }
-
- /* For ROPs where overlaps don't matter, convert rectangles to region and
- * call exaFillRegion{Solid,Tiled}.
- */
- if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
- (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear ||
- pGC->alu == GXnoop || pGC->alu == GXcopyInverted ||
- pGC->alu == GXset)) {
- if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
- exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ?
- pGC->fgPixel : pGC->tile.pixel, pGC->planemask,
- pGC->alu, pGC->clientClipType)) ||
- (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
- exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
- pGC->planemask, pGC->alu,
- pGC->clientClipType))) {
- goto out;
- }
- }
-
- if (pGC->fillStyle != FillSolid &&
- !(pGC->tileIsPixel && pGC->fillStyle == FillTiled))
- {
- goto fallback;
- }
-
- if (pExaScr->do_migration) {
- ExaMigrationRec pixmaps[1];
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = NULL;
-
- exaDoMigration (pixmaps, 1, TRUE);
- }
-
- if (!exaPixmapHasGpuCopy (pPixmap) ||
- !(*pExaScr->info->PrepareSolid) (pPixmap,
- pGC->alu,
- pGC->planemask,
- pGC->fgPixel))
- {
-fallback:
- ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
- goto out;
- }
-
- xorg = pDrawable->x;
- yorg = pDrawable->y;
-
- pextent = RegionExtents(pClip);
- extentX1 = pextent->x1;
- extentY1 = pextent->y1;
- extentX2 = pextent->x2;
- extentY2 = pextent->y2;
- while (nrect--)
- {
- fullX1 = prect->x + xorg;
- fullY1 = prect->y + yorg;
- fullX2 = fullX1 + (int) prect->width;
- fullY2 = fullY1 + (int) prect->height;
- prect++;
-
- if (fullX1 < extentX1)
- fullX1 = extentX1;
-
- if (fullY1 < extentY1)
- fullY1 = extentY1;
-
- if (fullX2 > extentX2)
- fullX2 = extentX2;
-
- if (fullY2 > extentY2)
- fullY2 = extentY2;
-
- if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
- continue;
- n = RegionNumRects (pClip);
- if (n == 1)
- {
- (*pExaScr->info->Solid) (pPixmap,
- fullX1 + xoff, fullY1 + yoff,
- fullX2 + xoff, fullY2 + yoff);
- }
- else
- {
- pbox = RegionRects(pClip);
- /*
- * clip the rectangle to each box in the clip region
- * this is logically equivalent to calling Intersect(),
- * but rectangles may overlap each other here.
- */
- while(n--)
- {
- partX1 = pbox->x1;
- if (partX1 < fullX1)
- partX1 = fullX1;
- partY1 = pbox->y1;
- if (partY1 < fullY1)
- partY1 = fullY1;
- partX2 = pbox->x2;
- if (partX2 > fullX2)
- partX2 = fullX2;
- partY2 = pbox->y2;
- if (partY2 > fullY2)
- partY2 = fullY2;
-
- pbox++;
-
- if (partX1 < partX2 && partY1 < partY2) {
- (*pExaScr->info->Solid) (pPixmap,
- partX1 + xoff, partY1 + yoff,
- partX2 + xoff, partY2 + yoff);
- }
- }
- }
- }
- (*pExaScr->info->DoneSolid) (pPixmap);
- exaMarkSync(pDrawable->pScreen);
-
-out:
- RegionUninit(pReg);
- RegionDestroy(pReg);
-}
-
-const GCOps exaOps = {
- exaFillSpans,
- ExaCheckSetSpans,
- exaPutImage,
- exaCopyArea,
- ExaCheckCopyPlane,
- exaPolyPoint,
- exaPolylines,
- exaPolySegment,
- miPolyRectangle,
- ExaCheckPolyArc,
- miFillPolygon,
- exaPolyFillRect,
- miPolyFillArc,
- miPolyText8,
- miPolyText16,
- miImageText8,
- miImageText16,
- ExaCheckImageGlyphBlt,
- ExaCheckPolyGlyphBlt,
- ExaCheckPushPixels,
-};
-
-void
-exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- RegionRec rgnDst;
- int dx, dy;
- PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
- ExaScreenPriv(pWin->drawable.pScreen);
-
- dx = ptOldOrg.x - pWin->drawable.x;
- dy = ptOldOrg.y - pWin->drawable.y;
- RegionTranslate(prgnSrc, -dx, -dy);
-
- RegionInit(&rgnDst, NullBox, 0);
-
- RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
-#ifdef COMPOSITE
- if (pPixmap->screen_x || pPixmap->screen_y)
- RegionTranslate(&rgnDst,
- -pPixmap->screen_x, -pPixmap->screen_y);
-#endif
-
- if (pExaScr->fallback_counter) {
- pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW;
- goto fallback;
- }
-
- pExaScr->fallback_flags |= EXA_ACCEL_COPYWINDOW;
- miCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
- NULL,
- &rgnDst, dx, dy, exaCopyNtoN, 0, NULL);
- pExaScr->fallback_flags &= ~EXA_ACCEL_COPYWINDOW;
-
-fallback:
- RegionUninit(&rgnDst);
-
- if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW) {
- pExaScr->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW;
- RegionTranslate(prgnSrc, dx, dy);
- ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc);
- }
-}
-
-static Bool
-exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
- CARD32 planemask, CARD32 alu, unsigned int clientClipType)
-{
- ExaScreenPriv(pDrawable->pScreen);
- PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
- ExaPixmapPriv (pPixmap);
- int xoff, yoff;
- Bool ret = FALSE;
-
- exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
- RegionTranslate(pRegion, xoff, yoff);
-
- if (pExaScr->fallback_counter || pExaPixmap->accel_blocked)
- goto out;
-
- if (pExaScr->do_migration) {
- ExaMigrationRec pixmaps[1];
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
- alu, clientClipType) ? NULL : pRegion;
-
- exaDoMigration (pixmaps, 1, TRUE);
- }
-
- if (exaPixmapHasGpuCopy (pPixmap) &&
- (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
- {
- int nbox;
- BoxPtr pBox;
-
- nbox = RegionNumRects (pRegion);
- pBox = RegionRects (pRegion);
-
- while (nbox--)
- {
- (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
- pBox->y2);
- pBox++;
- }
- (*pExaScr->info->DoneSolid) (pPixmap);
- exaMarkSync(pDrawable->pScreen);
-
- if (pExaPixmap->pDamage &&
- pExaPixmap->sys_ptr && pDrawable->type == DRAWABLE_PIXMAP &&
- pDrawable->width == 1 && pDrawable->height == 1 &&
- pDrawable->bitsPerPixel != 24) {
- ExaPixmapPriv(pPixmap);
- RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
-
- switch (pDrawable->bitsPerPixel) {
- case 32:
- *(CARD32*)pExaPixmap->sys_ptr = pixel;
- break;
- case 16:
- *(CARD16*)pExaPixmap->sys_ptr = pixel;
- break;
- case 8:
- case 4:
- case 1:
- *(CARD8*)pExaPixmap->sys_ptr = pixel;
- }
-
- RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys,
- pRegion);
- RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB,
- pRegion);
- RegionSubtract(pending_damage, pending_damage, pRegion);
- }
-
- ret = TRUE;
- }
-
-out:
- RegionTranslate(pRegion, -xoff, -yoff);
-
- return ret;
-}
-
-/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
- * Based on fbFillRegionTiled(), fbTile().
- */
-Bool
-exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
- DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu,
- unsigned int clientClipType)
-{
- ExaScreenPriv(pDrawable->pScreen);
- PixmapPtr pPixmap;
- ExaPixmapPrivPtr pExaPixmap;
- ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile);
- int xoff, yoff;
- int tileWidth, tileHeight;
- int nbox = RegionNumRects (pRegion);
- BoxPtr pBox = RegionRects (pRegion);
- Bool ret = FALSE;
- int i;
-
- tileWidth = pTile->drawable.width;
- tileHeight = pTile->drawable.height;
-
- /* If we're filling with a solid color, grab it out and go to
- * FillRegionSolid, saving numerous copies.
- */
- if (tileWidth == 1 && tileHeight == 1)
- return exaFillRegionSolid(pDrawable, pRegion,
- exaGetPixmapFirstPixel (pTile), planemask,
- alu, clientClipType);
-
- pPixmap = exaGetDrawablePixmap (pDrawable);
- pExaPixmap = ExaGetPixmapPriv (pPixmap);
-
- if (pExaScr->fallback_counter || pExaPixmap->accel_blocked ||
- pTileExaPixmap->accel_blocked)
- return FALSE;
-
- if (pExaScr->do_migration) {
- ExaMigrationRec pixmaps[2];
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
- alu, clientClipType) ? NULL : pRegion;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pTile;
- pixmaps[1].pReg = NULL;
-
- exaDoMigration (pixmaps, 2, TRUE);
- }
-
- pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
-
- if (!pPixmap || !exaPixmapHasGpuCopy(pTile))
- return FALSE;
-
- if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
- {
- if (xoff || yoff)
- RegionTranslate(pRegion, xoff, yoff);
-
- for (i = 0; i < nbox; i++)
- {
- int height = pBox[i].y2 - pBox[i].y1;
- int dstY = pBox[i].y1;
- int tileY;
-
- if (alu == GXcopy)
- height = min(height, tileHeight);
-
- modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY);
-
- while (height > 0) {
- int width = pBox[i].x2 - pBox[i].x1;
- int dstX = pBox[i].x1;
- int tileX;
- int h = tileHeight - tileY;
-
- if (alu == GXcopy)
- width = min(width, tileWidth);
-
- if (h > height)
- h = height;
- height -= h;
-
- modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth,
- tileX);
-
- while (width > 0) {
- int w = tileWidth - tileX;
- if (w > width)
- w = width;
- width -= w;
-
- (*pExaScr->info->Copy) (pPixmap, tileX, tileY, dstX, dstY,
- w, h);
- dstX += w;
- tileX = 0;
- }
- dstY += h;
- tileY = 0;
- }
- }
- (*pExaScr->info->DoneCopy) (pPixmap);
-
- /* With GXcopy, we only need to do the basic algorithm up to the tile
- * size; then, we can just keep doubling the destination in each
- * direction until it fills the box. This way, the number of copy
- * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where
- * rx/ry is the ratio between box and tile width/height. This can make
- * a big difference if each driver copy incurs a significant constant
- * overhead.
- */
- if (alu != GXcopy)
- ret = TRUE;
- else {
- Bool more_copy = FALSE;
-
- for (i = 0; i < nbox; i++) {
- int dstX = pBox[i].x1 + tileWidth;
- int dstY = pBox[i].y1 + tileHeight;
-
- if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) {
- more_copy = TRUE;
- break;
- }
- }
-
- if (more_copy == FALSE)
- ret = TRUE;
-
- if (more_copy && (*pExaScr->info->PrepareCopy) (pPixmap, pPixmap,
- 1, 1, alu, planemask)) {
- for (i = 0; i < nbox; i++)
- {
- int dstX = pBox[i].x1 + tileWidth;
- int dstY = pBox[i].y1 + tileHeight;
- int width = min(pBox[i].x2 - dstX, tileWidth);
- int height = min(pBox[i].y2 - pBox[i].y1, tileHeight);
-
- while (dstX < pBox[i].x2) {
- (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
- dstX, pBox[i].y1, width, height);
- dstX += width;
- width = min(pBox[i].x2 - dstX, width * 2);
- }
-
- width = pBox[i].x2 - pBox[i].x1;
- height = min(pBox[i].y2 - dstY, tileHeight);
-
- while (dstY < pBox[i].y2) {
- (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
- pBox[i].x1, dstY, width, height);
- dstY += height;
- height = min(pBox[i].y2 - dstY, height * 2);
- }
- }
-
- (*pExaScr->info->DoneCopy) (pPixmap);
-
- ret = TRUE;
- }
- }
-
- exaMarkSync(pDrawable->pScreen);
-
- if (xoff || yoff)
- RegionTranslate(pRegion, -xoff, -yoff);
- }
-
- return ret;
-}
-
-
-/**
- * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
- *
- * This is probably the only case we actually care about. The rest fall through
- * to migration and fbGetImage, which hopefully will result in migration pushing
- * the pixmap out of framebuffer.
- */
-void
-exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
- unsigned int format, unsigned long planeMask, char *d)
-{
- ExaScreenPriv (pDrawable->pScreen);
- PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
- ExaPixmapPriv(pPix);
- int xoff, yoff;
- Bool ok;
-
- if (pExaScr->fallback_counter || pExaScr->swappedOut)
- goto fallback;
-
- /* If there's a system copy, we want to save the result there */
- if (pExaPixmap->pDamage)
- goto fallback;
-
- pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
-
- if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL)
- goto fallback;
-
- /* Only cover the ZPixmap, solid copy case. */
- if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
- goto fallback;
-
- /* Only try to handle the 8bpp and up cases, since we don't want to think
- * about <8bpp.
- */
- if (pDrawable->bitsPerPixel < 8)
- goto fallback;
-
- ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
- pDrawable->y + y + yoff, w, h, d,
- PixmapBytePad(w, pDrawable->depth));
- if (ok) {
- exaWaitSync(pDrawable->pScreen);
- return;
- }
-
-fallback:
- ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d);
-}
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Michel Dänzer <michel@tungstengraphics.com>
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include "exa_priv.h"
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+#include "exa.h"
+
+static void
+exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ ExaScreenPriv (pScreen);
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
+ ExaPixmapPriv (pPixmap);
+ BoxPtr pextent, pbox;
+ int nbox;
+ int extentX1, extentX2, extentY1, extentY2;
+ int fullX1, fullX2, fullY1;
+ int partX1, partX2;
+ int off_x, off_y;
+
+ if (pExaScr->fallback_counter ||
+ pExaScr->swappedOut ||
+ pGC->fillStyle != FillSolid ||
+ pExaPixmap->accel_blocked)
+ {
+ ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
+ return;
+ }
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
+
+ if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) ||
+ !(*pExaScr->info->PrepareSolid) (pPixmap,
+ pGC->alu,
+ pGC->planemask,
+ pGC->fgPixel))
+ {
+ ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
+ return;
+ }
+
+ pextent = RegionExtents(pClip);
+ extentX1 = pextent->x1;
+ extentY1 = pextent->y1;
+ extentX2 = pextent->x2;
+ extentY2 = pextent->y2;
+ while (n--)
+ {
+ fullX1 = ppt->x;
+ fullY1 = ppt->y;
+ fullX2 = fullX1 + (int) *pwidth;
+ ppt++;
+ pwidth++;
+
+ if (fullY1 < extentY1 || extentY2 <= fullY1)
+ continue;
+
+ if (fullX1 < extentX1)
+ fullX1 = extentX1;
+
+ if (fullX2 > extentX2)
+ fullX2 = extentX2;
+
+ if (fullX1 >= fullX2)
+ continue;
+
+ nbox = RegionNumRects (pClip);
+ if (nbox == 1)
+ {
+ (*pExaScr->info->Solid) (pPixmap,
+ fullX1 + off_x, fullY1 + off_y,
+ fullX2 + off_x, fullY1 + 1 + off_y);
+ }
+ else
+ {
+ pbox = RegionRects(pClip);
+ while(nbox--)
+ {
+ if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
+ {
+ partX1 = pbox->x1;
+ if (partX1 < fullX1)
+ partX1 = fullX1;
+ partX2 = pbox->x2;
+ if (partX2 > fullX2)
+ partX2 = fullX2;
+ if (partX2 > partX1) {
+ (*pExaScr->info->Solid) (pPixmap,
+ partX1 + off_x, fullY1 + off_y,
+ partX2 + off_x, fullY1 + 1 + off_y);
+ }
+ }
+ pbox++;
+ }
+ }
+ }
+ (*pExaScr->info->DoneSolid) (pPixmap);
+ exaMarkSync(pScreen);
+}
+
+static Bool
+exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+ int w, int h, int format, char *bits, int src_stride)
+{
+ ExaScreenPriv (pDrawable->pScreen);
+ PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
+ ExaPixmapPriv(pPix);
+ RegionPtr pClip;
+ BoxPtr pbox;
+ int nbox;
+ int xoff, yoff;
+ int bpp = pDrawable->bitsPerPixel;
+ Bool ret = TRUE;
+
+ if (pExaScr->fallback_counter || pExaPixmap->accel_blocked || !pExaScr->info->UploadToScreen)
+ return FALSE;
+
+ /* If there's a system copy, we want to save the result there */
+ if (pExaPixmap->pDamage)
+ return FALSE;
+
+ /* Don't bother with under 8bpp, XYPixmaps. */
+ if (format != ZPixmap || bpp < 8)
+ return FALSE;
+
+ /* Only accelerate copies: no rop or planemask. */
+ if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
+ return FALSE;
+
+ if (pExaScr->swappedOut)
+ return FALSE;
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPix;
+ pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
+
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
+
+ pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
+
+ if (!pPix)
+ return FALSE;
+
+ x += pDrawable->x;
+ y += pDrawable->y;
+
+ pClip = fbGetCompositeClip(pGC);
+ for (nbox = RegionNumRects(pClip),
+ pbox = RegionRects(pClip);
+ nbox--;
+ pbox++)
+ {
+ int x1 = x;
+ int y1 = y;
+ int x2 = x + w;
+ int y2 = y + h;
+ char *src;
+ Bool ok;
+
+ if (x1 < pbox->x1)
+ x1 = pbox->x1;
+ if (y1 < pbox->y1)
+ y1 = pbox->y1;
+ if (x2 > pbox->x2)
+ x2 = pbox->x2;
+ if (y2 > pbox->y2)
+ y2 = pbox->y2;
+ if (x1 >= x2 || y1 >= y2)
+ continue;
+
+ src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
+ ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
+ x2 - x1, y2 - y1, src, src_stride);
+ /* We have to fall back completely, and ignore what has already been completed.
+ * Messing with the fb layer directly like we used to is completely unacceptable.
+ */
+ if (!ok) {
+ ret = FALSE;
+ break;
+ }
+ }
+
+ if (ret)
+ exaMarkSync(pDrawable->pScreen);
+
+ return ret;
+}
+
+static void
+exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char *bits)
+{
+ if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, format, bits,
+ PixmapBytePad(w, pDrawable->depth)))
+ ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+ bits);
+}
+
+static Bool inline
+exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
+{
+ ExaScreenPriv (pDstDrawable->pScreen);
+ PixmapPtr pSrcPixmap, pDstPixmap;
+ int src_off_x, src_off_y, dst_off_x, dst_off_y;
+ int dirsetup;
+
+ /* Need to get both pixmaps to call the driver routines */
+ pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y);
+ pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y);
+ if (!pSrcPixmap || !pDstPixmap)
+ return FALSE;
+
+ /*
+ * Now the case of a chip that only supports xdir = ydir = 1 or
+ * xdir = ydir = -1, but we have xdir != ydir.
+ */
+ dirsetup = 0; /* No direction set up yet. */
+ for (; nbox; pbox++, nbox--) {
+ if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
+ /* Do a xdir = ydir = -1 blit instead. */
+ if (dirsetup != -1) {
+ if (dirsetup != 0)
+ pExaScr->info->DoneCopy(pDstPixmap);
+ dirsetup = -1;
+ if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
+ pDstPixmap,
+ -1, -1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask :
+ FB_ALLONES))
+ return FALSE;
+ }
+ (*pExaScr->info->Copy)(pDstPixmap,
+ src_off_x + pbox->x1 + dx,
+ src_off_y + pbox->y1 + dy,
+ dst_off_x + pbox->x1,
+ dst_off_y + pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
+ /* Do a xdir = ydir = 1 blit instead. */
+ if (dirsetup != 1) {
+ if (dirsetup != 0)
+ pExaScr->info->DoneCopy(pDstPixmap);
+ dirsetup = 1;
+ if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
+ pDstPixmap,
+ 1, 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask :
+ FB_ALLONES))
+ return FALSE;
+ }
+ (*pExaScr->info->Copy)(pDstPixmap,
+ src_off_x + pbox->x1 + dx,
+ src_off_y + pbox->y1 + dy,
+ dst_off_x + pbox->x1,
+ dst_off_y + pbox->y1,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ } else if (dx >= 0) {
+ /*
+ * xdir = 1, ydir = -1.
+ * Perform line-by-line xdir = ydir = 1 blits, going up.
+ */
+ int i;
+ if (dirsetup != 1) {
+ if (dirsetup != 0)
+ pExaScr->info->DoneCopy(pDstPixmap);
+ dirsetup = 1;
+ if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
+ pDstPixmap,
+ 1, 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask :
+ FB_ALLONES))
+ return FALSE;
+ }
+ for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
+ (*pExaScr->info->Copy)(pDstPixmap,
+ src_off_x + pbox->x1 + dx,
+ src_off_y + pbox->y1 + dy + i,
+ dst_off_x + pbox->x1,
+ dst_off_y + pbox->y1 + i,
+ pbox->x2 - pbox->x1, 1);
+ } else {
+ /*
+ * xdir = -1, ydir = 1.
+ * Perform line-by-line xdir = ydir = -1 blits, going down.
+ */
+ int i;
+ if (dirsetup != -1) {
+ if (dirsetup != 0)
+ pExaScr->info->DoneCopy(pDstPixmap);
+ dirsetup = -1;
+ if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
+ pDstPixmap,
+ -1, -1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask :
+ FB_ALLONES))
+ return FALSE;
+ }
+ for (i = 0; i < pbox->y2 - pbox->y1; i++)
+ (*pExaScr->info->Copy)(pDstPixmap,
+ src_off_x + pbox->x1 + dx,
+ src_off_y + pbox->y1 + dy + i,
+ dst_off_x + pbox->x1,
+ dst_off_y + pbox->y1 + i,
+ pbox->x2 - pbox->x1, 1);
+ }
+ }
+ if (dirsetup != 0)
+ pExaScr->info->DoneCopy(pDstPixmap);
+ exaMarkSync(pDstDrawable->pScreen);
+ return TRUE;
+}
+
+Bool
+exaHWCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown)
+{
+ ExaScreenPriv (pDstDrawable->pScreen);
+ PixmapPtr pSrcPixmap, pDstPixmap;
+ ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap;
+ int src_off_x, src_off_y;
+ int dst_off_x, dst_off_y;
+ RegionPtr srcregion = NULL, dstregion = NULL;
+ xRectangle *rects;
+ Bool ret = TRUE;
+
+ /* avoid doing copy operations if no boxes */
+ if (nbox == 0)
+ return TRUE;
+
+ pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
+ pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
+
+ exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y);
+ exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y);
+
+ rects = malloc(nbox * sizeof(xRectangle));
+
+ if (rects) {
+ int i;
+ int ordering;
+
+ for (i = 0; i < nbox; i++) {
+ rects[i].x = pbox[i].x1 + dx + src_off_x;
+ rects[i].y = pbox[i].y1 + dy + src_off_y;
+ rects[i].width = pbox[i].x2 - pbox[i].x1;
+ rects[i].height = pbox[i].y2 - pbox[i].y1;
+ }
+
+ /* This must match the RegionCopy() logic for reversing rect order */
+ if (nbox == 1 || (dx > 0 && dy > 0) ||
+ (pDstDrawable != pSrcDrawable &&
+ (pDstDrawable->type != DRAWABLE_WINDOW ||
+ pSrcDrawable->type != DRAWABLE_WINDOW)))
+ ordering = CT_YXBANDED;
+ else
+ ordering = CT_UNSORTED;
+
+ srcregion = RegionFromRects(nbox, rects, ordering);
+ free(rects);
+
+ if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask,
+ pGC->fillStyle, pGC->alu,
+ pGC->clientClipType)) {
+ dstregion = RegionCreate(NullBox, 0);
+ RegionCopy(dstregion, srcregion);
+ RegionTranslate(dstregion, dst_off_x - dx - src_off_x,
+ dst_off_y - dy - src_off_y);
+ }
+ }
+
+
+ pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap);
+ pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap);
+
+ /* Check whether the accelerator can use this pixmap.
+ * If the pitch of the pixmaps is out of range, there's nothing
+ * we can do but fall back to software rendering.
+ */
+ if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH ||
+ pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH)
+ goto fallback;
+
+ /* If the width or the height of either of the pixmaps
+ * is out of range, check whether the boxes are actually out of the
+ * addressable range as well. If they aren't, we can still do
+ * the copying in hardware.
+ */
+ if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) {
+ int i;
+
+ for (i = 0; i < nbox; i++) {
+ /* src */
+ if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX ||
+ (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY)
+ goto fallback;
+
+ /* dst */
+ if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX ||
+ (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY)
+ goto fallback;
+ }
+ }
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[2];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pDstPixmap;
+ pixmaps[0].pReg = dstregion;
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pSrcPixmap;
+ pixmaps[1].pReg = srcregion;
+
+ exaDoMigration (pixmaps, 2, TRUE);
+ }
+
+ /* Mixed directions must be handled specially if the card is lame */
+ if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
+ reverse != upsidedown) {
+ if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
+ dx, dy))
+ goto out;
+ goto fallback;
+ }
+
+ if (exaPixmapHasGpuCopy(pDstPixmap)) {
+ /* Normal blitting. */
+ if (exaPixmapHasGpuCopy(pSrcPixmap)) {
+ if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
+ upsidedown ? -1 : 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask : FB_ALLONES)) {
+ goto fallback;
+ }
+
+ while (nbox--)
+ {
+ (*pExaScr->info->Copy) (pDstPixmap,
+ pbox->x1 + dx + src_off_x,
+ pbox->y1 + dy + src_off_y,
+ pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
+
+ (*pExaScr->info->DoneCopy) (pDstPixmap);
+ exaMarkSync (pDstDrawable->pScreen);
+ /* UTS: mainly for SHM PutImage's secondary path.
+ *
+ * Only taking this path for directly accessible pixmaps.
+ */
+ } else if (!pDstExaPixmap->pDamage && pSrcExaPixmap->sys_ptr) {
+ int bpp = pSrcDrawable->bitsPerPixel;
+ int src_stride = exaGetPixmapPitch(pSrcPixmap);
+ CARD8 *src = NULL;
+
+ if (!pExaScr->info->UploadToScreen)
+ goto fallback;
+
+ if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
+ goto fallback;
+
+ if (pSrcDrawable->bitsPerPixel < 8)
+ goto fallback;
+
+ if (pGC && !(pGC->alu == GXcopy && EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask)))
+ goto fallback;
+
+ while (nbox--)
+ {
+ src = pSrcExaPixmap->sys_ptr + (pbox->y1 + dy + src_off_y) * src_stride + (pbox->x1 + dx + src_off_x) * (bpp / 8);
+ if (!pExaScr->info->UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x,
+ pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
+ (char *) src, src_stride))
+ goto fallback;
+
+ pbox++;
+ }
+ } else
+ goto fallback;
+ } else
+ goto fallback;
+
+ goto out;
+
+fallback:
+ ret = FALSE;
+
+out:
+ if (dstregion) {
+ RegionUninit(dstregion);
+ RegionDestroy(dstregion);
+ }
+ if (srcregion) {
+ RegionUninit(srcregion);
+ RegionDestroy(srcregion);
+ }
+
+ return ret;
+}
+
+void
+exaCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ ExaScreenPriv(pDstDrawable->pScreen);
+
+ if (pExaScr->fallback_counter ||
+ (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW))
+ return;
+
+ if (exaHWCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown))
+ return;
+
+ /* This is a CopyWindow, it's cleaner to fallback at the original call. */
+ if (pExaScr->fallback_flags & EXA_ACCEL_COPYWINDOW) {
+ pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW;
+ return;
+ }
+
+ /* fallback */
+ ExaCheckCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
+}
+
+RegionPtr
+exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ ExaScreenPriv (pDstDrawable->pScreen);
+
+ if (pExaScr->fallback_counter || pExaScr->swappedOut) {
+ return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty);
+ }
+
+ return miDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, exaCopyNtoN, 0, NULL);
+}
+
+static void
+exaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr ppt)
+{
+ ExaScreenPriv (pDrawable->pScreen);
+ int i;
+ xRectangle *prect;
+
+ /* If we can't reuse the current GC as is, don't bother accelerating the
+ * points.
+ */
+ if (pExaScr->fallback_counter || pGC->fillStyle != FillSolid) {
+ ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ prect = malloc(sizeof(xRectangle) * npt);
+ for (i = 0; i < npt; i++) {
+ prect[i].x = ppt[i].x;
+ prect[i].y = ppt[i].y;
+ if (i > 0 && mode == CoordModePrevious) {
+ prect[i].x += prect[i - 1].x;
+ prect[i].y += prect[i - 1].y;
+ }
+ prect[i].width = 1;
+ prect[i].height = 1;
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
+ free(prect);
+}
+
+/**
+ * exaPolylines() checks if it can accelerate the lines as a group of
+ * horizontal or vertical lines (rectangles), and uses existing rectangle fill
+ * acceleration if so.
+ */
+static void
+exaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr ppt)
+{
+ ExaScreenPriv (pDrawable->pScreen);
+ xRectangle *prect;
+ int x1, x2, y1, y2;
+ int i;
+
+ if (pExaScr->fallback_counter) {
+ ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ /* Don't try to do wide lines or non-solid fill style. */
+ if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
+ pGC->fillStyle != FillSolid) {
+ ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ prect = malloc(sizeof(xRectangle) * (npt - 1));
+ x1 = ppt[0].x;
+ y1 = ppt[0].y;
+ /* If we have any non-horizontal/vertical, fall back. */
+ for (i = 0; i < npt - 1; i++) {
+ if (mode == CoordModePrevious) {
+ x2 = x1 + ppt[i + 1].x;
+ y2 = y1 + ppt[i + 1].y;
+ } else {
+ x2 = ppt[i + 1].x;
+ y2 = ppt[i + 1].y;
+ }
+
+ if (x1 != x2 && y1 != y2) {
+ free(prect);
+ ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ if (x1 < x2) {
+ prect[i].x = x1;
+ prect[i].width = x2 - x1 + 1;
+ } else {
+ prect[i].x = x2;
+ prect[i].width = x1 - x2 + 1;
+ }
+ if (y1 < y2) {
+ prect[i].y = y1;
+ prect[i].height = y2 - y1 + 1;
+ } else {
+ prect[i].y = y2;
+ prect[i].height = y1 - y2 + 1;
+ }
+
+ x1 = x2;
+ y1 = y2;
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
+ free(prect);
+}
+
+/**
+ * exaPolySegment() checks if it can accelerate the lines as a group of
+ * horizontal or vertical lines (rectangles), and uses existing rectangle fill
+ * acceleration if so.
+ */
+static void
+exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg,
+ xSegment *pSeg)
+{
+ ExaScreenPriv (pDrawable->pScreen);
+ xRectangle *prect;
+ int i;
+
+ /* Don't try to do wide lines or non-solid fill style. */
+ if (pExaScr->fallback_counter || pGC->lineWidth != 0 ||
+ pGC->lineStyle != LineSolid || pGC->fillStyle != FillSolid)
+ {
+ ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg);
+ return;
+ }
+
+ /* If we have any non-horizontal/vertical, fall back. */
+ for (i = 0; i < nseg; i++) {
+ if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) {
+ ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg);
+ return;
+ }
+ }
+
+ prect = malloc(sizeof(xRectangle) * nseg);
+ for (i = 0; i < nseg; i++) {
+ if (pSeg[i].x1 < pSeg[i].x2) {
+ prect[i].x = pSeg[i].x1;
+ prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
+ } else {
+ prect[i].x = pSeg[i].x2;
+ prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
+ }
+ if (pSeg[i].y1 < pSeg[i].y2) {
+ prect[i].y = pSeg[i].y1;
+ prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
+ } else {
+ prect[i].y = pSeg[i].y2;
+ prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
+ }
+
+ /* don't paint last pixel */
+ if (pGC->capStyle == CapNotLast) {
+ if (prect[i].width == 1)
+ prect[i].height--;
+ else
+ prect[i].width--;
+ }
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
+ free(prect);
+}
+
+static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion,
+ Pixel pixel, CARD32 planemask, CARD32 alu,
+ unsigned int clientClipType);
+
+static void
+exaPolyFillRect(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int nrect,
+ xRectangle *prect)
+{
+ ExaScreenPriv (pDrawable->pScreen);
+ RegionPtr pClip = fbGetCompositeClip(pGC);
+ PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+ ExaPixmapPriv (pPixmap);
+ register BoxPtr pbox;
+ BoxPtr pextent;
+ int extentX1, extentX2, extentY1, extentY2;
+ int fullX1, fullX2, fullY1, fullY2;
+ int partX1, partX2, partY1, partY2;
+ int xoff, yoff;
+ int xorg, yorg;
+ int n;
+ RegionPtr pReg = RegionFromRects(nrect, prect, CT_UNSORTED);
+
+ /* Compute intersection of rects and clip region */
+ RegionTranslate(pReg, pDrawable->x, pDrawable->y);
+ RegionIntersect(pReg, pClip, pReg);
+
+ if (!RegionNumRects(pReg)) {
+ goto out;
+ }
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+
+ if (pExaScr->fallback_counter || pExaScr->swappedOut ||
+ pExaPixmap->accel_blocked)
+ {
+ goto fallback;
+ }
+
+ /* For ROPs where overlaps don't matter, convert rectangles to region and
+ * call exaFillRegion{Solid,Tiled}.
+ */
+ if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
+ (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear ||
+ pGC->alu == GXnoop || pGC->alu == GXcopyInverted ||
+ pGC->alu == GXset)) {
+ if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
+ exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ?
+ pGC->fgPixel : pGC->tile.pixel, pGC->planemask,
+ pGC->alu, pGC->clientClipType)) ||
+ (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
+ exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
+ pGC->planemask, pGC->alu,
+ pGC->clientClipType))) {
+ goto out;
+ }
+ }
+
+ if (pGC->fillStyle != FillSolid &&
+ !(pGC->tileIsPixel && pGC->fillStyle == FillTiled))
+ {
+ goto fallback;
+ }
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
+
+ if (!exaPixmapHasGpuCopy (pPixmap) ||
+ !(*pExaScr->info->PrepareSolid) (pPixmap,
+ pGC->alu,
+ pGC->planemask,
+ pGC->fgPixel))
+ {
+fallback:
+ ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
+ goto out;
+ }
+
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ pextent = RegionExtents(pClip);
+ extentX1 = pextent->x1;
+ extentY1 = pextent->y1;
+ extentX2 = pextent->x2;
+ extentY2 = pextent->y2;
+ while (nrect--)
+ {
+ fullX1 = prect->x + xorg;
+ fullY1 = prect->y + yorg;
+ fullX2 = fullX1 + (int) prect->width;
+ fullY2 = fullY1 + (int) prect->height;
+ prect++;
+
+ if (fullX1 < extentX1)
+ fullX1 = extentX1;
+
+ if (fullY1 < extentY1)
+ fullY1 = extentY1;
+
+ if (fullX2 > extentX2)
+ fullX2 = extentX2;
+
+ if (fullY2 > extentY2)
+ fullY2 = extentY2;
+
+ if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
+ continue;
+ n = RegionNumRects (pClip);
+ if (n == 1)
+ {
+ (*pExaScr->info->Solid) (pPixmap,
+ fullX1 + xoff, fullY1 + yoff,
+ fullX2 + xoff, fullY2 + yoff);
+ }
+ else
+ {
+ pbox = RegionRects(pClip);
+ /*
+ * clip the rectangle to each box in the clip region
+ * this is logically equivalent to calling Intersect(),
+ * but rectangles may overlap each other here.
+ */
+ while(n--)
+ {
+ partX1 = pbox->x1;
+ if (partX1 < fullX1)
+ partX1 = fullX1;
+ partY1 = pbox->y1;
+ if (partY1 < fullY1)
+ partY1 = fullY1;
+ partX2 = pbox->x2;
+ if (partX2 > fullX2)
+ partX2 = fullX2;
+ partY2 = pbox->y2;
+ if (partY2 > fullY2)
+ partY2 = fullY2;
+
+ pbox++;
+
+ if (partX1 < partX2 && partY1 < partY2) {
+ (*pExaScr->info->Solid) (pPixmap,
+ partX1 + xoff, partY1 + yoff,
+ partX2 + xoff, partY2 + yoff);
+ }
+ }
+ }
+ }
+ (*pExaScr->info->DoneSolid) (pPixmap);
+ exaMarkSync(pDrawable->pScreen);
+
+out:
+ RegionUninit(pReg);
+ RegionDestroy(pReg);
+}
+
+const GCOps exaOps = {
+ exaFillSpans,
+ ExaCheckSetSpans,
+ exaPutImage,
+ exaCopyArea,
+ ExaCheckCopyPlane,
+ exaPolyPoint,
+ exaPolylines,
+ exaPolySegment,
+ miPolyRectangle,
+ ExaCheckPolyArc,
+ miFillPolygon,
+ exaPolyFillRect,
+ miPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ ExaCheckImageGlyphBlt,
+ ExaCheckPolyGlyphBlt,
+ ExaCheckPushPixels,
+};
+
+void
+exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ RegionRec rgnDst;
+ int dx, dy;
+ PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+ ExaScreenPriv(pWin->drawable.pScreen);
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ RegionTranslate(prgnSrc, -dx, -dy);
+
+ RegionInit(&rgnDst, NullBox, 0);
+
+ RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
+#ifdef COMPOSITE
+ if (pPixmap->screen_x || pPixmap->screen_y)
+ RegionTranslate(&rgnDst,
+ -pPixmap->screen_x, -pPixmap->screen_y);
+#endif
+
+ if (pExaScr->fallback_counter) {
+ pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW;
+ goto fallback;
+ }
+
+ pExaScr->fallback_flags |= EXA_ACCEL_COPYWINDOW;
+ miCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
+ NULL,
+ &rgnDst, dx, dy, exaCopyNtoN, 0, NULL);
+ pExaScr->fallback_flags &= ~EXA_ACCEL_COPYWINDOW;
+
+fallback:
+ RegionUninit(&rgnDst);
+
+ if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW) {
+ pExaScr->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW;
+ RegionTranslate(prgnSrc, dx, dy);
+ ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc);
+ }
+}
+
+static Bool
+exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
+ CARD32 planemask, CARD32 alu, unsigned int clientClipType)
+{
+ ExaScreenPriv(pDrawable->pScreen);
+ PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
+ ExaPixmapPriv (pPixmap);
+ int xoff, yoff;
+ Bool ret = FALSE;
+
+ exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
+ RegionTranslate(pRegion, xoff, yoff);
+
+ if (pExaScr->fallback_counter || pExaPixmap->accel_blocked)
+ goto out;
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
+ alu, clientClipType) ? NULL : pRegion;
+
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
+
+ if (exaPixmapHasGpuCopy (pPixmap) &&
+ (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel))
+ {
+ int nbox;
+ BoxPtr pBox;
+
+ nbox = RegionNumRects (pRegion);
+ pBox = RegionRects (pRegion);
+
+ while (nbox--)
+ {
+ (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2,
+ pBox->y2);
+ pBox++;
+ }
+ (*pExaScr->info->DoneSolid) (pPixmap);
+ exaMarkSync(pDrawable->pScreen);
+
+ if (pExaPixmap->pDamage &&
+ pExaPixmap->sys_ptr && pDrawable->type == DRAWABLE_PIXMAP &&
+ pDrawable->width == 1 && pDrawable->height == 1 &&
+ pDrawable->bitsPerPixel != 24) {
+ ExaPixmapPriv(pPixmap);
+ RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
+
+ switch (pDrawable->bitsPerPixel) {
+ case 32:
+ *(CARD32*)pExaPixmap->sys_ptr = pixel;
+ break;
+ case 16:
+ *(CARD16*)pExaPixmap->sys_ptr = pixel;
+ break;
+ case 8:
+ case 4:
+ case 1:
+ *(CARD8*)pExaPixmap->sys_ptr = pixel;
+ }
+
+ RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys,
+ pRegion);
+ RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB,
+ pRegion);
+ RegionSubtract(pending_damage, pending_damage, pRegion);
+ }
+
+ ret = TRUE;
+ }
+
+out:
+ RegionTranslate(pRegion, -xoff, -yoff);
+
+ return ret;
+}
+
+/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
+ * Based on fbFillRegionTiled(), fbTile().
+ */
+Bool
+exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
+ DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu,
+ unsigned int clientClipType)
+{
+ ExaScreenPriv(pDrawable->pScreen);
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile);
+ int xoff, yoff;
+ int tileWidth, tileHeight;
+ int nbox = RegionNumRects (pRegion);
+ BoxPtr pBox = RegionRects (pRegion);
+ Bool ret = FALSE;
+ int i;
+
+ tileWidth = pTile->drawable.width;
+ tileHeight = pTile->drawable.height;
+
+ /* If we're filling with a solid color, grab it out and go to
+ * FillRegionSolid, saving numerous copies.
+ */
+ if (tileWidth == 1 && tileHeight == 1)
+ return exaFillRegionSolid(pDrawable, pRegion,
+ exaGetPixmapFirstPixel (pTile), planemask,
+ alu, clientClipType);
+
+ pPixmap = exaGetDrawablePixmap (pDrawable);
+ pExaPixmap = ExaGetPixmapPriv (pPixmap);
+
+ if (pExaScr->fallback_counter || pExaPixmap->accel_blocked ||
+ pTileExaPixmap->accel_blocked)
+ return FALSE;
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[2];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
+ alu, clientClipType) ? NULL : pRegion;
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pTile;
+ pixmaps[1].pReg = NULL;
+
+ exaDoMigration (pixmaps, 2, TRUE);
+ }
+
+ pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
+
+ if (!pPixmap || !exaPixmapHasGpuCopy(pTile))
+ return FALSE;
+
+ if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask))
+ {
+ if (xoff || yoff)
+ RegionTranslate(pRegion, xoff, yoff);
+
+ for (i = 0; i < nbox; i++)
+ {
+ int height = pBox[i].y2 - pBox[i].y1;
+ int dstY = pBox[i].y1;
+ int tileY;
+
+ if (alu == GXcopy)
+ height = min(height, tileHeight);
+
+ modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY);
+
+ while (height > 0) {
+ int width = pBox[i].x2 - pBox[i].x1;
+ int dstX = pBox[i].x1;
+ int tileX;
+ int h = tileHeight - tileY;
+
+ if (alu == GXcopy)
+ width = min(width, tileWidth);
+
+ if (h > height)
+ h = height;
+ height -= h;
+
+ modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth,
+ tileX);
+
+ while (width > 0) {
+ int w = tileWidth - tileX;
+ if (w > width)
+ w = width;
+ width -= w;
+
+ (*pExaScr->info->Copy) (pPixmap, tileX, tileY, dstX, dstY,
+ w, h);
+ dstX += w;
+ tileX = 0;
+ }
+ dstY += h;
+ tileY = 0;
+ }
+ }
+ (*pExaScr->info->DoneCopy) (pPixmap);
+
+ /* With GXcopy, we only need to do the basic algorithm up to the tile
+ * size; then, we can just keep doubling the destination in each
+ * direction until it fills the box. This way, the number of copy
+ * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where
+ * rx/ry is the ratio between box and tile width/height. This can make
+ * a big difference if each driver copy incurs a significant constant
+ * overhead.
+ */
+ if (alu != GXcopy)
+ ret = TRUE;
+ else {
+ Bool more_copy = FALSE;
+
+ for (i = 0; i < nbox; i++) {
+ int dstX = pBox[i].x1 + tileWidth;
+ int dstY = pBox[i].y1 + tileHeight;
+
+ if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) {
+ more_copy = TRUE;
+ break;
+ }
+ }
+
+ if (more_copy == FALSE)
+ ret = TRUE;
+
+ if (more_copy && (*pExaScr->info->PrepareCopy) (pPixmap, pPixmap,
+ 1, 1, alu, planemask)) {
+ for (i = 0; i < nbox; i++)
+ {
+ int dstX = pBox[i].x1 + tileWidth;
+ int dstY = pBox[i].y1 + tileHeight;
+ int width = min(pBox[i].x2 - dstX, tileWidth);
+ int height = min(pBox[i].y2 - pBox[i].y1, tileHeight);
+
+ while (dstX < pBox[i].x2) {
+ (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
+ dstX, pBox[i].y1, width, height);
+ dstX += width;
+ width = min(pBox[i].x2 - dstX, width * 2);
+ }
+
+ width = pBox[i].x2 - pBox[i].x1;
+ height = min(pBox[i].y2 - dstY, tileHeight);
+
+ while (dstY < pBox[i].y2) {
+ (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1,
+ pBox[i].x1, dstY, width, height);
+ dstY += height;
+ height = min(pBox[i].y2 - dstY, height * 2);
+ }
+ }
+
+ (*pExaScr->info->DoneCopy) (pPixmap);
+
+ ret = TRUE;
+ }
+ }
+
+ exaMarkSync(pDrawable->pScreen);
+
+ if (xoff || yoff)
+ RegionTranslate(pRegion, -xoff, -yoff);
+ }
+
+ return ret;
+}
+
+
+/**
+ * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
+ *
+ * This is probably the only case we actually care about. The rest fall through
+ * to migration and fbGetImage, which hopefully will result in migration pushing
+ * the pixmap out of framebuffer.
+ */
+void
+exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d)
+{
+ ExaScreenPriv (pDrawable->pScreen);
+ PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
+ ExaPixmapPriv(pPix);
+ int xoff, yoff;
+ Bool ok;
+
+ if (pExaScr->fallback_counter || pExaScr->swappedOut)
+ goto fallback;
+
+ /* If there's a system copy, we want to save the result there */
+ if (pExaPixmap->pDamage)
+ goto fallback;
+
+ pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
+
+ if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL)
+ goto fallback;
+
+ /* Only cover the ZPixmap, solid copy case. */
+ if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
+ goto fallback;
+
+ /* Only try to handle the 8bpp and up cases, since we don't want to think
+ * about <8bpp.
+ */
+ if (pDrawable->bitsPerPixel < 8)
+ goto fallback;
+
+ ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff,
+ pDrawable->y + y + yoff, w, h, d,
+ PixmapBytePad(w, pDrawable->depth));
+ if (ok) {
+ exaWaitSync(pDrawable->pScreen);
+ return;
+ }
+
+fallback:
+ ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d);
+}
diff --git a/xorg-server/exa/exa_classic.c b/xorg-server/exa/exa_classic.c
index 1a1467848..919b29df2 100644
--- a/xorg-server/exa/exa_classic.c
+++ b/xorg-server/exa/exa_classic.c
@@ -1,266 +1,266 @@
-/*
- * Copyright © 2009 Maarten Maathuis
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-
-#include "exa_priv.h"
-#include "exa.h"
-
-/* This file holds the classic exa specific implementation. */
-
-static _X_INLINE void*
-ExaGetPixmapAddress(PixmapPtr p)
-{
- ExaPixmapPriv(p);
-
- if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr)
- return pExaPixmap->fb_ptr;
- else
- return pExaPixmap->sys_ptr;
-}
-
-/**
- * exaCreatePixmap() creates a new pixmap.
- *
- * If width and height are 0, this won't be a full-fledged pixmap and it will
- * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
- * ModifyPixmapHeader() would break migration. These types of pixmaps are used
- * for scratch pixmaps, or to represent the visible screen.
- */
-PixmapPtr
-exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
- unsigned usage_hint)
-{
- PixmapPtr pPixmap;
- ExaPixmapPrivPtr pExaPixmap;
- BoxRec box;
- int bpp;
- ExaScreenPriv(pScreen);
-
- if (w > 32767 || h > 32767)
- return NullPixmap;
-
- swap(pExaScr, pScreen, CreatePixmap);
- pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint);
- swap(pExaScr, pScreen, CreatePixmap);
-
- if (!pPixmap)
- return NULL;
-
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
- pExaPixmap->driverPriv = NULL;
-
- bpp = pPixmap->drawable.bitsPerPixel;
-
- pExaPixmap->driverPriv = NULL;
- /* Scratch pixmaps may have w/h equal to zero, and may not be
- * migrated.
- */
- if (!w || !h)
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- else
- pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
-
- pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
- pExaPixmap->sys_pitch = pPixmap->devKind;
-
- pPixmap->devPrivate.ptr = NULL;
- pExaPixmap->use_gpu_copy = FALSE;
-
- pExaPixmap->fb_ptr = NULL;
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
- pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
-
- if (pExaPixmap->fb_pitch > 131071) {
- swap(pExaScr, pScreen, DestroyPixmap);
- pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
- return NULL;
- }
-
- /* Set up damage tracking */
- pExaPixmap->pDamage = DamageCreate (NULL, NULL,
- DamageReportNone, TRUE,
- pScreen, pPixmap);
-
- if (pExaPixmap->pDamage == NULL) {
- swap(pExaScr, pScreen, DestroyPixmap);
- pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
- return NULL;
- }
-
- DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
- /* This ensures that pending damage reflects the current operation. */
- /* This is used by exa to optimize migration. */
- DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
-
- pExaPixmap->area = NULL;
-
- /* We set the initial pixmap as completely valid for a simple reason.
- * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
- * could form single pixel rects as part of a region. Setting the complete region
- * as valid is a natural defragmentation of the region.
- */
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = w;
- box.y2 = h;
- RegionInit(&pExaPixmap->validSys, &box, 0);
- RegionInit(&pExaPixmap->validFB, &box, 0);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- w, h, bpp);
-
- /* During a fallback we must prepare access. */
- if (pExaScr->fallback_counter)
- exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
-
- return pPixmap;
-}
-
-Bool
-exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth,
- int bitsPerPixel, int devKind, pointer pPixData)
-{
- ScreenPtr pScreen;
- ExaScreenPrivPtr pExaScr;
- ExaPixmapPrivPtr pExaPixmap;
- Bool ret;
-
- if (!pPixmap)
- return FALSE;
-
- pScreen = pPixmap->drawable.pScreen;
- pExaScr = ExaGetScreenPriv(pScreen);
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
-
- if (pExaPixmap) {
- if (pPixData)
- pExaPixmap->sys_ptr = pPixData;
-
- if (devKind > 0)
- pExaPixmap->sys_pitch = devKind;
-
- /* Classic EXA:
- * - Framebuffer.
- * - Scratch pixmap with gpu memory.
- */
- if (pExaScr->info->memoryBase && pPixData) {
- if ((CARD8 *)pPixData >= pExaScr->info->memoryBase &&
- ((CARD8 *)pPixData - pExaScr->info->memoryBase) <
- pExaScr->info->memorySize) {
- pExaPixmap->fb_ptr = pPixData;
- pExaPixmap->fb_pitch = devKind;
- pExaPixmap->use_gpu_copy = TRUE;
- }
- }
-
- if (width > 0 && height > 0 && bitsPerPixel > 0) {
- exaSetFbPitch(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
- }
-
- /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
- * gpu memory, so there's no need to track damage.
- */
- if (pExaPixmap->pDamage) {
- DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
- DamageDestroy(pExaPixmap->pDamage);
- pExaPixmap->pDamage = NULL;
- }
- }
-
- swap(pExaScr, pScreen, ModifyPixmapHeader);
- ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
- swap(pExaScr, pScreen, ModifyPixmapHeader);
-
- /* Always NULL this, we don't want lingering pointers. */
- pPixmap->devPrivate.ptr = NULL;
-
- return ret;
-}
-
-Bool
-exaDestroyPixmap_classic (PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
- Bool ret;
-
- if (pPixmap->refcnt == 1)
- {
- ExaPixmapPriv (pPixmap);
-
- exaDestroyPixmap(pPixmap);
-
- if (pExaPixmap->area)
- {
- DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
- (void*)pPixmap->drawable.id,
- ExaGetPixmapPriv(pPixmap)->area->offset,
- pPixmap->drawable.width,
- pPixmap->drawable.height));
- /* Free the offscreen area */
- exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
- pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
- pPixmap->devKind = pExaPixmap->sys_pitch;
- }
- RegionUninit(&pExaPixmap->validSys);
- RegionUninit(&pExaPixmap->validFB);
- }
-
- swap(pExaScr, pScreen, DestroyPixmap);
- ret = pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
-
- return ret;
-}
-
-Bool
-exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
- ExaPixmapPriv(pPixmap);
- Bool ret;
-
- if (pExaScr->info->PixmapIsOffscreen) {
- void* old_ptr = pPixmap->devPrivate.ptr;
- pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
- ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
- pPixmap->devPrivate.ptr = old_ptr;
- } else
- ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr);
-
- return ret;
-}
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the classic exa specific implementation. */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr)
+ return pExaPixmap->fb_ptr;
+ else
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * If width and height are 0, this won't be a full-fledged pixmap and it will
+ * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
+ * ModifyPixmapHeader() would break migration. These types of pixmaps are used
+ * for scratch pixmaps, or to represent the visible screen.
+ */
+PixmapPtr
+exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ BoxRec box;
+ int bpp;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap (pScreen, w, h, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ pExaPixmap->driverPriv = NULL;
+ /* Scratch pixmaps may have w/h equal to zero, and may not be
+ * migrated.
+ */
+ if (!w || !h)
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ else
+ pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
+
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+
+ pPixmap->devPrivate.ptr = NULL;
+ pExaPixmap->use_gpu_copy = FALSE;
+
+ pExaPixmap->fb_ptr = NULL;
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+ pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
+
+ if (pExaPixmap->fb_pitch > 131071) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ /* Set up damage tracking */
+ pExaPixmap->pDamage = DamageCreate (NULL, NULL,
+ DamageReportNone, TRUE,
+ pScreen, pPixmap);
+
+ if (pExaPixmap->pDamage == NULL) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
+ /* This ensures that pending damage reflects the current operation. */
+ /* This is used by exa to optimize migration. */
+ DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
+
+ pExaPixmap->area = NULL;
+
+ /* We set the initial pixmap as completely valid for a simple reason.
+ * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
+ * could form single pixel rects as part of a region. Setting the complete region
+ * as valid is a natural defragmentation of the region.
+ */
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = w;
+ box.y2 = h;
+ RegionInit(&pExaPixmap->validSys, &box, 0);
+ RegionInit(&pExaPixmap->validFB, &box, 0);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ /* During a fallback we must prepare access. */
+ if (pExaScr->fallback_counter)
+ exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pScreen = pPixmap->drawable.pScreen;
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pExaPixmap) {
+ if (pPixData)
+ pExaPixmap->sys_ptr = pPixData;
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ /* Classic EXA:
+ * - Framebuffer.
+ * - Scratch pixmap with gpu memory.
+ */
+ if (pExaScr->info->memoryBase && pPixData) {
+ if ((CARD8 *)pPixData >= pExaScr->info->memoryBase &&
+ ((CARD8 *)pPixData - pExaScr->info->memoryBase) <
+ pExaScr->info->memorySize) {
+ pExaPixmap->fb_ptr = pPixData;
+ pExaPixmap->fb_pitch = devKind;
+ pExaPixmap->use_gpu_copy = TRUE;
+ }
+ }
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+
+ /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
+ * gpu memory, so there's no need to track damage.
+ */
+ if (pExaPixmap->pDamage) {
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ }
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_classic (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ exaDestroyPixmap(pPixmap);
+
+ if (pExaPixmap->area)
+ {
+ DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
+ (void*)pPixmap->drawable.id,
+ ExaGetPixmapPriv(pPixmap)->area->offset,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height));
+ /* Free the offscreen area */
+ exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ }
+ RegionUninit(&pExaPixmap->validSys);
+ RegionUninit(&pExaPixmap->validFB);
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ Bool ret;
+
+ if (pExaScr->info->PixmapIsOffscreen) {
+ void* old_ptr = pPixmap->devPrivate.ptr;
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = old_ptr;
+ } else
+ ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr);
+
+ return ret;
+}
diff --git a/xorg-server/exa/exa_driver.c b/xorg-server/exa/exa_driver.c
index bfc89295f..795cb00cd 100644
--- a/xorg-server/exa/exa_driver.c
+++ b/xorg-server/exa/exa_driver.c
@@ -1,226 +1,226 @@
-/*
- * Copyright © 2009 Maarten Maathuis
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-
-#include "exa_priv.h"
-#include "exa.h"
-
-/* This file holds the driver allocated pixmaps specific implementation. */
-
-static _X_INLINE void*
-ExaGetPixmapAddress(PixmapPtr p)
-{
- ExaPixmapPriv(p);
-
- return pExaPixmap->sys_ptr;
-}
-
-/**
- * exaCreatePixmap() creates a new pixmap.
- *
- * Pixmaps are always marked as pinned, because exa has no control over them.
- */
-PixmapPtr
-exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
- unsigned usage_hint)
-{
- PixmapPtr pPixmap;
- ExaPixmapPrivPtr pExaPixmap;
- int bpp;
- size_t paddedWidth, datasize;
- ExaScreenPriv(pScreen);
-
- if (w > 32767 || h > 32767)
- return NullPixmap;
-
- swap(pExaScr, pScreen, CreatePixmap);
- pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
- swap(pExaScr, pScreen, CreatePixmap);
-
- if (!pPixmap)
- return NULL;
-
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
- pExaPixmap->driverPriv = NULL;
-
- bpp = pPixmap->drawable.bitsPerPixel;
-
- /* Set this before driver hooks, to allow for driver pixmaps without gpu
- * memory to back it. These pixmaps have a valid pointer at all times.
- */
- pPixmap->devPrivate.ptr = NULL;
-
- if (pExaScr->info->CreatePixmap2) {
- int new_pitch = 0;
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
- paddedWidth = pExaPixmap->fb_pitch = new_pitch;
- }
- else {
- paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
- if (paddedWidth / 4 > 32767 || h > 32767)
- return NullPixmap;
-
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
-
- if (paddedWidth < pExaPixmap->fb_pitch)
- paddedWidth = pExaPixmap->fb_pitch;
- datasize = h * paddedWidth;
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
- }
-
- if (!pExaPixmap->driverPriv) {
- swap(pExaScr, pScreen, DestroyPixmap);
- pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
- return NULL;
- }
-
- /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- pExaPixmap->fb_ptr = NULL;
- pExaPixmap->pDamage = NULL;
- pExaPixmap->sys_ptr = NULL;
-
- (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
- paddedWidth, NULL);
-
- pExaPixmap->area = NULL;
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- w, h, bpp);
-
- pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
-
- /* During a fallback we must prepare access. */
- if (pExaScr->fallback_counter)
- exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
-
- return pPixmap;
-}
-
-Bool
-exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth,
- int bitsPerPixel, int devKind, pointer pPixData)
-{
- ScreenPtr pScreen;
- ExaScreenPrivPtr pExaScr;
- ExaPixmapPrivPtr pExaPixmap;
- Bool ret;
-
- if (!pPixmap)
- return FALSE;
-
- pScreen = pPixmap->drawable.pScreen;
- pExaScr = ExaGetScreenPriv(pScreen);
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
-
- if (pExaPixmap) {
- if (pPixData)
- pExaPixmap->sys_ptr = pPixData;
-
- if (devKind > 0)
- pExaPixmap->sys_pitch = devKind;
-
- if (width > 0 && height > 0 && bitsPerPixel > 0) {
- exaSetFbPitch(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
- }
- }
-
- if (pExaScr->info->ModifyPixmapHeader) {
- ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
- /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
- * If pPixmap->devPrivate.ptr is non-NULL, then we've got a
- * !has_gpu_copy pixmap. We need to store the pointer,
- * because PrepareAccess won't be called.
- */
- if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
- pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
- pExaPixmap->sys_pitch = pPixmap->devKind;
- }
- if (ret == TRUE)
- goto out;
- }
-
- swap(pExaScr, pScreen, ModifyPixmapHeader);
- ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
- swap(pExaScr, pScreen, ModifyPixmapHeader);
-
-out:
- /* Always NULL this, we don't want lingering pointers. */
- pPixmap->devPrivate.ptr = NULL;
-
- return ret;
-}
-
-Bool
-exaDestroyPixmap_driver (PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
- Bool ret;
-
- if (pPixmap->refcnt == 1)
- {
- ExaPixmapPriv (pPixmap);
-
- exaDestroyPixmap(pPixmap);
-
- if (pExaPixmap->driverPriv)
- pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
- pExaPixmap->driverPriv = NULL;
- }
-
- swap(pExaScr, pScreen, DestroyPixmap);
- ret = pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
-
- return ret;
-}
-
-Bool
-exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
- pointer saved_ptr;
- Bool ret;
-
- saved_ptr = pPixmap->devPrivate.ptr;
- pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
- ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
- pPixmap->devPrivate.ptr = saved_ptr;
-
- return ret;
-}
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the driver allocated pixmaps specific implementation. */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ *
+ * Pixmaps are always marked as pinned, because exa has no control over them.
+ */
+PixmapPtr
+exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ int bpp;
+ size_t paddedWidth, datasize;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ /* Set this before driver hooks, to allow for driver pixmaps without gpu
+ * memory to back it. These pixmaps have a valid pointer at all times.
+ */
+ pPixmap->devPrivate.ptr = NULL;
+
+ if (pExaScr->info->CreatePixmap2) {
+ int new_pitch = 0;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
+ paddedWidth = pExaPixmap->fb_pitch = new_pitch;
+ }
+ else {
+ paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ if (paddedWidth / 4 > 32767 || h > 32767)
+ return NullPixmap;
+
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+
+ if (paddedWidth < pExaPixmap->fb_pitch)
+ paddedWidth = pExaPixmap->fb_pitch;
+ datasize = h * paddedWidth;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, datasize, 0);
+ }
+
+ if (!pExaPixmap->driverPriv) {
+ swap(pExaScr, pScreen, DestroyPixmap);
+ pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+ return NULL;
+ }
+
+ /* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+ pExaPixmap->sys_ptr = NULL;
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+
+ pExaPixmap->area = NULL;
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+
+ /* During a fallback we must prepare access. */
+ if (pExaScr->fallback_counter)
+ exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pScreen = pPixmap->drawable.pScreen;
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pExaPixmap) {
+ if (pPixData)
+ pExaPixmap->sys_ptr = pPixData;
+
+ if (devKind > 0)
+ pExaPixmap->sys_pitch = devKind;
+
+ if (width > 0 && height > 0 && bitsPerPixel > 0) {
+ exaSetFbPitch(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ }
+ }
+
+ if (pExaScr->info->ModifyPixmapHeader) {
+ ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ /* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
+ * If pPixmap->devPrivate.ptr is non-NULL, then we've got a
+ * !has_gpu_copy pixmap. We need to store the pointer,
+ * because PrepareAccess won't be called.
+ */
+ if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+ }
+ if (ret == TRUE)
+ goto out;
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+out:
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_driver (PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ exaDestroyPixmap(pPixmap);
+
+ if (pExaPixmap->driverPriv)
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ pExaPixmap->driverPriv = NULL;
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ pointer saved_ptr;
+ Bool ret;
+
+ saved_ptr = pPixmap->devPrivate.ptr;
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = saved_ptr;
+
+ return ret;
+}
diff --git a/xorg-server/exa/exa_migration_classic.c b/xorg-server/exa/exa_migration_classic.c
index 5ec2ac0b8..dd3cd491e 100644
--- a/xorg-server/exa/exa_migration_classic.c
+++ b/xorg-server/exa/exa_migration_classic.c
@@ -1,745 +1,745 @@
-/*
- * Copyright © 2006 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- * Michel Dänzer <michel@tungstengraphics.com>
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-
-#include "exa_priv.h"
-#include "exa.h"
-
-#if DEBUG_MIGRATE
-#define DBG_MIGRATE(a) ErrorF a
-#else
-#define DBG_MIGRATE(a)
-#endif
-
-/**
- * The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
- * and exaCopyDirtyToFb both needed to do this loop.
- */
-static void
-exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
- CARD8 *dst, int dst_pitch)
- {
- int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
- int bytes = (pbox->x2 - pbox->x1) * cpp;
-
- src += pbox->y1 * src_pitch + pbox->x1 * cpp;
- dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
-
- for (i = pbox->y2 - pbox->y1; i; i--) {
- memcpy (dst, src, bytes);
- src += src_pitch;
- dst += dst_pitch;
- }
-}
-
-/**
- * Returns TRUE if the pixmap is dirty (has been modified in its current
- * location compared to the other), or lacks a private for tracking
- * dirtiness.
- */
-static Bool
-exaPixmapIsDirty (PixmapPtr pPix)
-{
- ExaPixmapPriv (pPix);
-
- if (pExaPixmap == NULL)
- EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);
-
- if (!pExaPixmap->pDamage)
- return FALSE;
-
- return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) ||
- !RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB);
-}
-
-/**
- * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score
- * to be considered "should be in framebuffer". That's just anything that has
- * had more acceleration than fallbacks, or has no score yet.
- *
- * Only valid if using a migration scheme that tracks score.
- */
-static Bool
-exaPixmapShouldBeInFB (PixmapPtr pPix)
-{
- ExaPixmapPriv (pPix);
-
- if (exaPixmapIsPinned (pPix))
- return TRUE;
-
- return pExaPixmap->score >= 0;
-}
-
-/**
- * If the pixmap is currently dirty, this copies at least the dirty area from
- * FB to system or vice versa. Both areas must be allocated.
- */
-static void
-exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
- Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
- char *sys, int sys_pitch), int fallback_index,
- void (*sync) (ScreenPtr pScreen))
-{
- PixmapPtr pPixmap = migrate->pPix;
- ExaPixmapPriv (pPixmap);
- RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
- RegionRec CopyReg;
- Bool save_use_gpu_copy;
- int save_pitch;
- BoxPtr pBox;
- int nbox;
- Bool access_prepared = FALSE;
- Bool need_sync = FALSE;
-
- /* Damaged bits are valid in current copy but invalid in other one */
- if (pExaPixmap->use_gpu_copy) {
- RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB,
- damage);
- RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys,
- damage);
- } else {
- RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys,
- damage);
- RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB,
- damage);
- }
-
- RegionEmpty(damage);
-
- /* Copy bits valid in source but not in destination */
- RegionNull(&CopyReg);
- RegionSubtract(&CopyReg, pValidSrc, pValidDst);
-
- if (migrate->as_dst) {
- ExaScreenPriv (pPixmap->drawable.pScreen);
-
- /* XXX: The pending damage region will be marked as damaged after the
- * operation, so it should serve as an upper bound for the region that
- * needs to be synchronized for the operation. Unfortunately, this
- * causes corruption in some cases, e.g. when starting compiz. See
- * https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
- */
- if (pExaScr->optimize_migration) {
- RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
-
-#if DEBUG_MIGRATE
- if (RegionNil(pending_damage)) {
- static Bool firsttime = TRUE;
-
- if (firsttime) {
- ErrorF("%s: Pending damage region empty!\n", __func__);
- firsttime = FALSE;
- }
- }
-#endif
-
- /* Try to prevent destination valid region from growing too many
- * rects by filling it up to the extents of the union of the
- * destination valid region and the pending damage region.
- */
- if (RegionNumRects(pValidDst) > 10) {
- BoxRec box;
- BoxPtr pValidExt, pDamageExt;
- RegionRec closure;
-
- pValidExt = RegionExtents(pValidDst);
- pDamageExt = RegionExtents(pending_damage);
-
- box.x1 = min(pValidExt->x1, pDamageExt->x1);
- box.y1 = min(pValidExt->y1, pDamageExt->y1);
- box.x2 = max(pValidExt->x2, pDamageExt->x2);
- box.y2 = max(pValidExt->y2, pDamageExt->y2);
-
- RegionInit(&closure, &box, 0);
- RegionIntersect(&CopyReg, &CopyReg, &closure);
- } else
- RegionIntersect(&CopyReg, &CopyReg, pending_damage);
- }
-
- /* The caller may provide a region to be subtracted from the calculated
- * dirty region. This is to avoid migration of bits that don't
- * contribute to the result of the operation.
- */
- if (migrate->pReg)
- RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
- } else {
- /* The caller may restrict the region to be migrated for source pixmaps
- * to what's relevant for the operation.
- */
- if (migrate->pReg)
- RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
- }
-
- pBox = RegionRects(&CopyReg);
- nbox = RegionNumRects(&CopyReg);
-
- save_use_gpu_copy = pExaPixmap->use_gpu_copy;
- save_pitch = pPixmap->devKind;
- pExaPixmap->use_gpu_copy = TRUE;
- pPixmap->devKind = pExaPixmap->fb_pitch;
-
- while (nbox--) {
- pBox->x1 = max(pBox->x1, 0);
- pBox->y1 = max(pBox->y1, 0);
- pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
- pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
-
- if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
- continue;
-
- if (!transfer || !transfer (pPixmap,
- pBox->x1, pBox->y1,
- pBox->x2 - pBox->x1,
- pBox->y2 - pBox->y1,
- (char *) (pExaPixmap->sys_ptr
- + pBox->y1 * pExaPixmap->sys_pitch
- + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8),
- pExaPixmap->sys_pitch))
- {
- if (!access_prepared) {
- ExaDoPrepareAccess(pPixmap, fallback_index);
- access_prepared = TRUE;
- }
- if (fallback_index == EXA_PREPARE_DEST) {
- exaMemcpyBox (pPixmap, pBox,
- pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
- pPixmap->devPrivate.ptr, pPixmap->devKind);
- } else {
- exaMemcpyBox (pPixmap, pBox,
- pPixmap->devPrivate.ptr, pPixmap->devKind,
- pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
- }
- } else
- need_sync = TRUE;
-
- pBox++;
- }
-
- pExaPixmap->use_gpu_copy = save_use_gpu_copy;
- pPixmap->devKind = save_pitch;
-
- /* Try to prevent source valid region from growing too many rects by
- * removing parts of it which are also in the destination valid region.
- * Removing anything beyond that would lead to data loss.
- */
- if (RegionNumRects(pValidSrc) > 20)
- RegionSubtract(pValidSrc, pValidSrc, pValidDst);
-
- /* The copied bits are now valid in destination */
- RegionUnion(pValidDst, pValidDst, &CopyReg);
-
- RegionUninit(&CopyReg);
-
- if (access_prepared)
- exaFinishAccess(&pPixmap->drawable, fallback_index);
- else if (need_sync && sync)
- sync (pPixmap->drawable.pScreen);
-}
-
-/**
- * If the pixmap is currently dirty, this copies at least the dirty area from
- * the framebuffer memory copy to the system memory copy. Both areas must be
- * allocated.
- */
-void
-exaCopyDirtyToSys (ExaMigrationPtr migrate)
-{
- PixmapPtr pPixmap = migrate->pPix;
- ExaScreenPriv (pPixmap->drawable.pScreen);
- ExaPixmapPriv (pPixmap);
-
- exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
- pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC,
- exaWaitSync);
-}
-
-/**
- * If the pixmap is currently dirty, this copies at least the dirty area from
- * the system memory copy to the framebuffer memory copy. Both areas must be
- * allocated.
- */
-void
-exaCopyDirtyToFb (ExaMigrationPtr migrate)
-{
- PixmapPtr pPixmap = migrate->pPix;
- ExaScreenPriv (pPixmap->drawable.pScreen);
- ExaPixmapPriv (pPixmap);
-
- exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
- pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL);
-}
-
-/**
- * Allocates a framebuffer copy of the pixmap if necessary, and then copies
- * any necessary pixmap data into the framebuffer copy and points the pixmap at
- * it.
- *
- * Note that when first allocated, a pixmap will have FALSE dirty flag.
- * This is intentional because pixmap data starts out undefined. So if we move
- * it in due to the first operation against it being accelerated, it will have
- * undefined framebuffer contents that we didn't have to upload. If we do
- * moveouts (and moveins) after the first movein, then we will only have to copy
- * back and forth if the pixmap was written to after the last synchronization of
- * the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away)
- * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
- * all the data, since it's almost surely all valid now.
- */
-static void
-exaDoMoveInPixmap (ExaMigrationPtr migrate)
-{
- PixmapPtr pPixmap = migrate->pPix;
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv (pScreen);
- ExaPixmapPriv (pPixmap);
-
- /* If we're VT-switched away, no touching card memory allowed. */
- if (pExaScr->swappedOut)
- return;
-
- /* If we're not allowed to move, then fail. */
- if (exaPixmapIsPinned(pPixmap))
- return;
-
- /* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of
- * fragility in EXA, and <8bpp is probably not used enough any more to care
- * (at least, not in acceleratd paths).
- */
- if (pPixmap->drawable.bitsPerPixel < 8)
- return;
-
- if (pExaPixmap->accel_blocked)
- return;
-
- if (pExaPixmap->area == NULL) {
- pExaPixmap->area =
- exaOffscreenAlloc (pScreen, pExaPixmap->fb_size,
- pExaScr->info->pixmapOffsetAlign, FALSE,
- exaPixmapSave, (pointer) pPixmap);
- if (pExaPixmap->area == NULL)
- return;
-
- pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
- pExaPixmap->area->offset;
- }
-
- exaCopyDirtyToFb (migrate);
-
- if (exaPixmapHasGpuCopy(pPixmap))
- return;
-
- DBG_MIGRATE (("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap,
- (ExaGetPixmapPriv(pPixmap)->area ?
- ExaGetPixmapPriv(pPixmap)->area->offset : 0),
- pPixmap->drawable.width,
- pPixmap->drawable.height,
- exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
-
- pExaPixmap->use_gpu_copy = TRUE;
-
- pPixmap->devKind = pExaPixmap->fb_pitch;
- pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
-}
-
-void
-exaMoveInPixmap_classic (PixmapPtr pPixmap)
-{
- static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
- .pReg = NULL };
-
- migrate.pPix = pPixmap;
- exaDoMoveInPixmap (&migrate);
-}
-
-/**
- * Switches the current active location of the pixmap to system memory, copying
- * updated data out if necessary.
- */
-static void
-exaDoMoveOutPixmap (ExaMigrationPtr migrate)
-{
- PixmapPtr pPixmap = migrate->pPix;
- ExaPixmapPriv (pPixmap);
-
- if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
- return;
-
- exaCopyDirtyToSys (migrate);
-
- if (exaPixmapHasGpuCopy(pPixmap)) {
-
- DBG_MIGRATE (("<- %p (%p) (%dx%d) (%c)\n", pPixmap,
- (void*)(ExaGetPixmapPriv(pPixmap)->area ?
- ExaGetPixmapPriv(pPixmap)->area->offset : 0),
- pPixmap->drawable.width,
- pPixmap->drawable.height,
- exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
-
- pExaPixmap->use_gpu_copy = FALSE;
-
- pPixmap->devKind = pExaPixmap->sys_pitch;
- pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
- }
-}
-
-void
-exaMoveOutPixmap_classic (PixmapPtr pPixmap)
-{
- static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
- .pReg = NULL };
-
- migrate.pPix = pPixmap;
- exaDoMoveOutPixmap (&migrate);
-}
-
-
-/**
- * Copies out important pixmap data and removes references to framebuffer area.
- * Called when the memory manager decides it's time to kick the pixmap out of
- * framebuffer entirely.
- */
-void
-exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
-{
- PixmapPtr pPixmap = area->privData;
- ExaPixmapPriv(pPixmap);
-
- exaMoveOutPixmap(pPixmap);
-
- pExaPixmap->fb_ptr = NULL;
- pExaPixmap->area = NULL;
-
- /* Mark all FB bits as invalid, so all valid system bits get copied to FB
- * next time */
- RegionEmpty(&pExaPixmap->validFB);
-}
-
-/**
- * For the "greedy" migration scheme, pushes the pixmap toward being located in
- * framebuffer memory.
- */
-static void
-exaMigrateTowardFb (ExaMigrationPtr migrate)
-{
- PixmapPtr pPixmap = migrate->pPix;
- ExaPixmapPriv (pPixmap);
-
- if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
- DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
- (pointer)pPixmap));
- return;
- }
-
- DBG_MIGRATE(("UseScreen %p score %d\n",
- (pointer)pPixmap, pExaPixmap->score));
-
- if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
- exaDoMoveInPixmap(migrate);
- pExaPixmap->score = 0;
- }
-
- if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
- pExaPixmap->score++;
-
- if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
- !exaPixmapHasGpuCopy(pPixmap))
- {
- exaDoMoveInPixmap(migrate);
- }
-
- if (exaPixmapHasGpuCopy(pPixmap)) {
- exaCopyDirtyToFb (migrate);
- ExaOffscreenMarkUsed (pPixmap);
- } else
- exaCopyDirtyToSys (migrate);
-}
-
-/**
- * For the "greedy" migration scheme, pushes the pixmap toward being located in
- * system memory.
- */
-static void
-exaMigrateTowardSys (ExaMigrationPtr migrate)
-{
- PixmapPtr pPixmap = migrate->pPix;
- ExaPixmapPriv (pPixmap);
-
- DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)pPixmap, pExaPixmap->score));
-
- if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
- return;
-
- if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
- pExaPixmap->score = 0;
-
- if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
- pExaPixmap->score--;
-
- if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
- exaDoMoveOutPixmap(migrate);
-
- if (exaPixmapHasGpuCopy(pPixmap)) {
- exaCopyDirtyToFb (migrate);
- ExaOffscreenMarkUsed (pPixmap);
- } else
- exaCopyDirtyToSys (migrate);
-}
-
-/**
- * If the pixmap has both a framebuffer and system memory copy, this function
- * asserts that both of them are the same.
- */
-static Bool
-exaAssertNotDirty (PixmapPtr pPixmap)
-{
- ExaPixmapPriv (pPixmap);
- CARD8 *dst, *src;
- RegionRec ValidReg;
- int dst_pitch, src_pitch, cpp, y, nbox, save_pitch;
- BoxPtr pBox;
- Bool ret = TRUE, save_use_gpu_copy;
-
- if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
- return ret;
-
- RegionNull(&ValidReg);
- RegionIntersect(&ValidReg, &pExaPixmap->validFB,
- &pExaPixmap->validSys);
- nbox = RegionNumRects(&ValidReg);
-
- if (!nbox)
- goto out;
-
- pBox = RegionRects(&ValidReg);
-
- dst_pitch = pExaPixmap->sys_pitch;
- src_pitch = pExaPixmap->fb_pitch;
- cpp = pPixmap->drawable.bitsPerPixel / 8;
-
- save_use_gpu_copy = pExaPixmap->use_gpu_copy;
- save_pitch = pPixmap->devKind;
- pExaPixmap->use_gpu_copy = TRUE;
- pPixmap->devKind = pExaPixmap->fb_pitch;
-
- if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
- goto skip;
-
- while (nbox--) {
- int rowbytes;
-
- pBox->x1 = max(pBox->x1, 0);
- pBox->y1 = max(pBox->y1, 0);
- pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
- pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
-
- if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
- continue;
-
- rowbytes = (pBox->x2 - pBox->x1) * cpp;
- src = (CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch + pBox->x1 * cpp;
- dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
-
- for (y = pBox->y1; y < pBox->y2;
- y++, src += src_pitch, dst += dst_pitch) {
- if (memcmp(dst, src, rowbytes) != 0) {
- ret = FALSE;
- exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2,
- pBox->y2);
- break;
- }
- }
- }
-
-skip:
- exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
-
- pExaPixmap->use_gpu_copy = save_use_gpu_copy;
- pPixmap->devKind = save_pitch;
-
-out:
- RegionUninit(&ValidReg);
- return ret;
-}
-
-/**
- * Performs migration of the pixmaps according to the operation information
- * provided in pixmaps and can_accel and the migration scheme chosen in the
- * config file.
- */
-void
-exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
-{
- ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
- ExaScreenPriv(pScreen);
- int i, j;
-
- /* If this debugging flag is set, check each pixmap for whether it is marked
- * as clean, and if so, actually check if that's the case. This should help
- * catch issues with failing to mark a drawable as dirty. While it will
- * catch them late (after the operation happened), it at least explains what
- * went wrong, and instrumenting the code to find what operation happened
- * to the pixmap last shouldn't be hard.
- */
- if (pExaScr->checkDirtyCorrectness) {
- for (i = 0; i < npixmaps; i++) {
- if (!exaPixmapIsDirty (pixmaps[i].pPix) &&
- !exaAssertNotDirty (pixmaps[i].pPix))
- ErrorF("%s: Pixmap %d dirty but not marked as such!\n", __func__, i);
- }
- }
- /* If anything is pinned in system memory, we won't be able to
- * accelerate.
- */
- for (i = 0; i < npixmaps; i++) {
- if (exaPixmapIsPinned (pixmaps[i].pPix) &&
- !exaPixmapHasGpuCopy (pixmaps[i].pPix))
- {
- EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix,
- pixmaps[i].pPix->drawable.width,
- pixmaps[i].pPix->drawable.height));
- can_accel = FALSE;
- break;
- }
- }
-
- if (pExaScr->migration == ExaMigrationSmart) {
- /* If we've got something as a destination that we shouldn't cause to
- * become newly dirtied, take the unaccelerated route.
- */
- for (i = 0; i < npixmaps; i++) {
- if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB (pixmaps[i].pPix) &&
- !exaPixmapIsDirty (pixmaps[i].pPix))
- {
- for (i = 0; i < npixmaps; i++) {
- if (!exaPixmapIsDirty (pixmaps[i].pPix))
- exaDoMoveOutPixmap (pixmaps + i);
- }
- return;
- }
- }
-
- /* If we aren't going to accelerate, then we migrate everybody toward
- * system memory, and kick out if it's free.
- */
- if (!can_accel) {
- for (i = 0; i < npixmaps; i++) {
- exaMigrateTowardSys (pixmaps + i);
- if (!exaPixmapIsDirty (pixmaps[i].pPix))
- exaDoMoveOutPixmap (pixmaps + i);
- }
- return;
- }
-
- /* Finally, the acceleration path. Move them all in. */
- for (i = 0; i < npixmaps; i++) {
- exaMigrateTowardFb(pixmaps + i);
- exaDoMoveInPixmap(pixmaps + i);
- }
- } else if (pExaScr->migration == ExaMigrationGreedy) {
- /* If we can't accelerate, either because the driver can't or because one of
- * the pixmaps is pinned in system memory, then we migrate everybody toward
- * system memory.
- *
- * We also migrate toward system if all pixmaps involved are currently in
- * system memory -- this can mitigate thrashing when there are significantly
- * more pixmaps active than would fit in memory.
- *
- * If not, then we migrate toward FB so that hopefully acceleration can
- * happen.
- */
- if (!can_accel) {
- for (i = 0; i < npixmaps; i++)
- exaMigrateTowardSys (pixmaps + i);
- return;
- }
-
- for (i = 0; i < npixmaps; i++) {
- if (exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
- /* Found one in FB, so move all to FB. */
- for (j = 0; j < npixmaps; j++)
- exaMigrateTowardFb(pixmaps + i);
- return;
- }
- }
-
- /* Nobody's in FB, so move all away from FB. */
- for (i = 0; i < npixmaps; i++)
- exaMigrateTowardSys(pixmaps + i);
- } else if (pExaScr->migration == ExaMigrationAlways) {
- /* Always move the pixmaps out if we can't accelerate. If we can
- * accelerate, try to move them all in. If that fails, then move them
- * back out.
- */
- if (!can_accel) {
- for (i = 0; i < npixmaps; i++)
- exaDoMoveOutPixmap(pixmaps + i);
- return;
- }
-
- /* Now, try to move them all into FB */
- for (i = 0; i < npixmaps; i++) {
- exaDoMoveInPixmap(pixmaps + i);
- }
-
- /* If we couldn't fit everything in, abort */
- for (i = 0; i < npixmaps; i++) {
- if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
- return;
- }
- }
-
- /* Yay, everything has a gpu copy, mark memory as used */
- for (i = 0; i < npixmaps; i++) {
- ExaOffscreenMarkUsed (pixmaps[i].pPix);
- }
- }
-}
-
-void
-exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
-{
- ExaMigrationRec pixmaps[1];
-
- if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- } else {
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- }
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = pReg;
-
- exaDoMigration(pixmaps, 1, FALSE);
-
- (void)ExaDoPrepareAccess(pPixmap, index);
-}
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Michel Dänzer <michel@tungstengraphics.com>
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+#if DEBUG_MIGRATE
+#define DBG_MIGRATE(a) ErrorF a
+#else
+#define DBG_MIGRATE(a)
+#endif
+
+/**
+ * The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
+ * and exaCopyDirtyToFb both needed to do this loop.
+ */
+static void
+exaMemcpyBox (PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
+ CARD8 *dst, int dst_pitch)
+ {
+ int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
+ int bytes = (pbox->x2 - pbox->x1) * cpp;
+
+ src += pbox->y1 * src_pitch + pbox->x1 * cpp;
+ dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
+
+ for (i = pbox->y2 - pbox->y1; i; i--) {
+ memcpy (dst, src, bytes);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+}
+
+/**
+ * Returns TRUE if the pixmap is dirty (has been modified in its current
+ * location compared to the other), or lacks a private for tracking
+ * dirtiness.
+ */
+static Bool
+exaPixmapIsDirty (PixmapPtr pPix)
+{
+ ExaPixmapPriv (pPix);
+
+ if (pExaPixmap == NULL)
+ EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);
+
+ if (!pExaPixmap->pDamage)
+ return FALSE;
+
+ return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) ||
+ !RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB);
+}
+
+/**
+ * Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score
+ * to be considered "should be in framebuffer". That's just anything that has
+ * had more acceleration than fallbacks, or has no score yet.
+ *
+ * Only valid if using a migration scheme that tracks score.
+ */
+static Bool
+exaPixmapShouldBeInFB (PixmapPtr pPix)
+{
+ ExaPixmapPriv (pPix);
+
+ if (exaPixmapIsPinned (pPix))
+ return TRUE;
+
+ return pExaPixmap->score >= 0;
+}
+
+/**
+ * If the pixmap is currently dirty, this copies at least the dirty area from
+ * FB to system or vice versa. Both areas must be allocated.
+ */
+static void
+exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
+ Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
+ char *sys, int sys_pitch), int fallback_index,
+ void (*sync) (ScreenPtr pScreen))
+{
+ PixmapPtr pPixmap = migrate->pPix;
+ ExaPixmapPriv (pPixmap);
+ RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
+ RegionRec CopyReg;
+ Bool save_use_gpu_copy;
+ int save_pitch;
+ BoxPtr pBox;
+ int nbox;
+ Bool access_prepared = FALSE;
+ Bool need_sync = FALSE;
+
+ /* Damaged bits are valid in current copy but invalid in other one */
+ if (pExaPixmap->use_gpu_copy) {
+ RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB,
+ damage);
+ RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys,
+ damage);
+ } else {
+ RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys,
+ damage);
+ RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB,
+ damage);
+ }
+
+ RegionEmpty(damage);
+
+ /* Copy bits valid in source but not in destination */
+ RegionNull(&CopyReg);
+ RegionSubtract(&CopyReg, pValidSrc, pValidDst);
+
+ if (migrate->as_dst) {
+ ExaScreenPriv (pPixmap->drawable.pScreen);
+
+ /* XXX: The pending damage region will be marked as damaged after the
+ * operation, so it should serve as an upper bound for the region that
+ * needs to be synchronized for the operation. Unfortunately, this
+ * causes corruption in some cases, e.g. when starting compiz. See
+ * https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
+ */
+ if (pExaScr->optimize_migration) {
+ RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
+
+#if DEBUG_MIGRATE
+ if (RegionNil(pending_damage)) {
+ static Bool firsttime = TRUE;
+
+ if (firsttime) {
+ ErrorF("%s: Pending damage region empty!\n", __func__);
+ firsttime = FALSE;
+ }
+ }
+#endif
+
+ /* Try to prevent destination valid region from growing too many
+ * rects by filling it up to the extents of the union of the
+ * destination valid region and the pending damage region.
+ */
+ if (RegionNumRects(pValidDst) > 10) {
+ BoxRec box;
+ BoxPtr pValidExt, pDamageExt;
+ RegionRec closure;
+
+ pValidExt = RegionExtents(pValidDst);
+ pDamageExt = RegionExtents(pending_damage);
+
+ box.x1 = min(pValidExt->x1, pDamageExt->x1);
+ box.y1 = min(pValidExt->y1, pDamageExt->y1);
+ box.x2 = max(pValidExt->x2, pDamageExt->x2);
+ box.y2 = max(pValidExt->y2, pDamageExt->y2);
+
+ RegionInit(&closure, &box, 0);
+ RegionIntersect(&CopyReg, &CopyReg, &closure);
+ } else
+ RegionIntersect(&CopyReg, &CopyReg, pending_damage);
+ }
+
+ /* The caller may provide a region to be subtracted from the calculated
+ * dirty region. This is to avoid migration of bits that don't
+ * contribute to the result of the operation.
+ */
+ if (migrate->pReg)
+ RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
+ } else {
+ /* The caller may restrict the region to be migrated for source pixmaps
+ * to what's relevant for the operation.
+ */
+ if (migrate->pReg)
+ RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
+ }
+
+ pBox = RegionRects(&CopyReg);
+ nbox = RegionNumRects(&CopyReg);
+
+ save_use_gpu_copy = pExaPixmap->use_gpu_copy;
+ save_pitch = pPixmap->devKind;
+ pExaPixmap->use_gpu_copy = TRUE;
+ pPixmap->devKind = pExaPixmap->fb_pitch;
+
+ while (nbox--) {
+ pBox->x1 = max(pBox->x1, 0);
+ pBox->y1 = max(pBox->y1, 0);
+ pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
+ pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
+
+ if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
+ continue;
+
+ if (!transfer || !transfer (pPixmap,
+ pBox->x1, pBox->y1,
+ pBox->x2 - pBox->x1,
+ pBox->y2 - pBox->y1,
+ (char *) (pExaPixmap->sys_ptr
+ + pBox->y1 * pExaPixmap->sys_pitch
+ + pBox->x1 * pPixmap->drawable.bitsPerPixel / 8),
+ pExaPixmap->sys_pitch))
+ {
+ if (!access_prepared) {
+ ExaDoPrepareAccess(pPixmap, fallback_index);
+ access_prepared = TRUE;
+ }
+ if (fallback_index == EXA_PREPARE_DEST) {
+ exaMemcpyBox (pPixmap, pBox,
+ pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
+ pPixmap->devPrivate.ptr, pPixmap->devKind);
+ } else {
+ exaMemcpyBox (pPixmap, pBox,
+ pPixmap->devPrivate.ptr, pPixmap->devKind,
+ pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
+ }
+ } else
+ need_sync = TRUE;
+
+ pBox++;
+ }
+
+ pExaPixmap->use_gpu_copy = save_use_gpu_copy;
+ pPixmap->devKind = save_pitch;
+
+ /* Try to prevent source valid region from growing too many rects by
+ * removing parts of it which are also in the destination valid region.
+ * Removing anything beyond that would lead to data loss.
+ */
+ if (RegionNumRects(pValidSrc) > 20)
+ RegionSubtract(pValidSrc, pValidSrc, pValidDst);
+
+ /* The copied bits are now valid in destination */
+ RegionUnion(pValidDst, pValidDst, &CopyReg);
+
+ RegionUninit(&CopyReg);
+
+ if (access_prepared)
+ exaFinishAccess(&pPixmap->drawable, fallback_index);
+ else if (need_sync && sync)
+ sync (pPixmap->drawable.pScreen);
+}
+
+/**
+ * If the pixmap is currently dirty, this copies at least the dirty area from
+ * the framebuffer memory copy to the system memory copy. Both areas must be
+ * allocated.
+ */
+void
+exaCopyDirtyToSys (ExaMigrationPtr migrate)
+{
+ PixmapPtr pPixmap = migrate->pPix;
+ ExaScreenPriv (pPixmap->drawable.pScreen);
+ ExaPixmapPriv (pPixmap);
+
+ exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
+ pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC,
+ exaWaitSync);
+}
+
+/**
+ * If the pixmap is currently dirty, this copies at least the dirty area from
+ * the system memory copy to the framebuffer memory copy. Both areas must be
+ * allocated.
+ */
+void
+exaCopyDirtyToFb (ExaMigrationPtr migrate)
+{
+ PixmapPtr pPixmap = migrate->pPix;
+ ExaScreenPriv (pPixmap->drawable.pScreen);
+ ExaPixmapPriv (pPixmap);
+
+ exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
+ pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL);
+}
+
+/**
+ * Allocates a framebuffer copy of the pixmap if necessary, and then copies
+ * any necessary pixmap data into the framebuffer copy and points the pixmap at
+ * it.
+ *
+ * Note that when first allocated, a pixmap will have FALSE dirty flag.
+ * This is intentional because pixmap data starts out undefined. So if we move
+ * it in due to the first operation against it being accelerated, it will have
+ * undefined framebuffer contents that we didn't have to upload. If we do
+ * moveouts (and moveins) after the first movein, then we will only have to copy
+ * back and forth if the pixmap was written to after the last synchronization of
+ * the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away)
+ * we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
+ * all the data, since it's almost surely all valid now.
+ */
+static void
+exaDoMoveInPixmap (ExaMigrationPtr migrate)
+{
+ PixmapPtr pPixmap = migrate->pPix;
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv (pScreen);
+ ExaPixmapPriv (pPixmap);
+
+ /* If we're VT-switched away, no touching card memory allowed. */
+ if (pExaScr->swappedOut)
+ return;
+
+ /* If we're not allowed to move, then fail. */
+ if (exaPixmapIsPinned(pPixmap))
+ return;
+
+ /* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of
+ * fragility in EXA, and <8bpp is probably not used enough any more to care
+ * (at least, not in acceleratd paths).
+ */
+ if (pPixmap->drawable.bitsPerPixel < 8)
+ return;
+
+ if (pExaPixmap->accel_blocked)
+ return;
+
+ if (pExaPixmap->area == NULL) {
+ pExaPixmap->area =
+ exaOffscreenAlloc (pScreen, pExaPixmap->fb_size,
+ pExaScr->info->pixmapOffsetAlign, FALSE,
+ exaPixmapSave, (pointer) pPixmap);
+ if (pExaPixmap->area == NULL)
+ return;
+
+ pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
+ pExaPixmap->area->offset;
+ }
+
+ exaCopyDirtyToFb (migrate);
+
+ if (exaPixmapHasGpuCopy(pPixmap))
+ return;
+
+ DBG_MIGRATE (("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap,
+ (ExaGetPixmapPriv(pPixmap)->area ?
+ ExaGetPixmapPriv(pPixmap)->area->offset : 0),
+ pPixmap->drawable.width,
+ pPixmap->drawable.height,
+ exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
+
+ pExaPixmap->use_gpu_copy = TRUE;
+
+ pPixmap->devKind = pExaPixmap->fb_pitch;
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+}
+
+void
+exaMoveInPixmap_classic (PixmapPtr pPixmap)
+{
+ static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
+ .pReg = NULL };
+
+ migrate.pPix = pPixmap;
+ exaDoMoveInPixmap (&migrate);
+}
+
+/**
+ * Switches the current active location of the pixmap to system memory, copying
+ * updated data out if necessary.
+ */
+static void
+exaDoMoveOutPixmap (ExaMigrationPtr migrate)
+{
+ PixmapPtr pPixmap = migrate->pPix;
+ ExaPixmapPriv (pPixmap);
+
+ if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
+ return;
+
+ exaCopyDirtyToSys (migrate);
+
+ if (exaPixmapHasGpuCopy(pPixmap)) {
+
+ DBG_MIGRATE (("<- %p (%p) (%dx%d) (%c)\n", pPixmap,
+ (void*)(ExaGetPixmapPriv(pPixmap)->area ?
+ ExaGetPixmapPriv(pPixmap)->area->offset : 0),
+ pPixmap->drawable.width,
+ pPixmap->drawable.height,
+ exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
+
+ pExaPixmap->use_gpu_copy = FALSE;
+
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ }
+}
+
+void
+exaMoveOutPixmap_classic (PixmapPtr pPixmap)
+{
+ static ExaMigrationRec migrate = { .as_dst = FALSE, .as_src = TRUE,
+ .pReg = NULL };
+
+ migrate.pPix = pPixmap;
+ exaDoMoveOutPixmap (&migrate);
+}
+
+
+/**
+ * Copies out important pixmap data and removes references to framebuffer area.
+ * Called when the memory manager decides it's time to kick the pixmap out of
+ * framebuffer entirely.
+ */
+void
+exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
+{
+ PixmapPtr pPixmap = area->privData;
+ ExaPixmapPriv(pPixmap);
+
+ exaMoveOutPixmap(pPixmap);
+
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->area = NULL;
+
+ /* Mark all FB bits as invalid, so all valid system bits get copied to FB
+ * next time */
+ RegionEmpty(&pExaPixmap->validFB);
+}
+
+/**
+ * For the "greedy" migration scheme, pushes the pixmap toward being located in
+ * framebuffer memory.
+ */
+static void
+exaMigrateTowardFb (ExaMigrationPtr migrate)
+{
+ PixmapPtr pPixmap = migrate->pPix;
+ ExaPixmapPriv (pPixmap);
+
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
+ DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
+ (pointer)pPixmap));
+ return;
+ }
+
+ DBG_MIGRATE(("UseScreen %p score %d\n",
+ (pointer)pPixmap, pExaPixmap->score));
+
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
+ exaDoMoveInPixmap(migrate);
+ pExaPixmap->score = 0;
+ }
+
+ if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
+ pExaPixmap->score++;
+
+ if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
+ !exaPixmapHasGpuCopy(pPixmap))
+ {
+ exaDoMoveInPixmap(migrate);
+ }
+
+ if (exaPixmapHasGpuCopy(pPixmap)) {
+ exaCopyDirtyToFb (migrate);
+ ExaOffscreenMarkUsed (pPixmap);
+ } else
+ exaCopyDirtyToSys (migrate);
+}
+
+/**
+ * For the "greedy" migration scheme, pushes the pixmap toward being located in
+ * system memory.
+ */
+static void
+exaMigrateTowardSys (ExaMigrationPtr migrate)
+{
+ PixmapPtr pPixmap = migrate->pPix;
+ ExaPixmapPriv (pPixmap);
+
+ DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)pPixmap, pExaPixmap->score));
+
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
+ return;
+
+ if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
+ pExaPixmap->score = 0;
+
+ if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
+ pExaPixmap->score--;
+
+ if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
+ exaDoMoveOutPixmap(migrate);
+
+ if (exaPixmapHasGpuCopy(pPixmap)) {
+ exaCopyDirtyToFb (migrate);
+ ExaOffscreenMarkUsed (pPixmap);
+ } else
+ exaCopyDirtyToSys (migrate);
+}
+
+/**
+ * If the pixmap has both a framebuffer and system memory copy, this function
+ * asserts that both of them are the same.
+ */
+static Bool
+exaAssertNotDirty (PixmapPtr pPixmap)
+{
+ ExaPixmapPriv (pPixmap);
+ CARD8 *dst, *src;
+ RegionRec ValidReg;
+ int dst_pitch, src_pitch, cpp, y, nbox, save_pitch;
+ BoxPtr pBox;
+ Bool ret = TRUE, save_use_gpu_copy;
+
+ if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
+ return ret;
+
+ RegionNull(&ValidReg);
+ RegionIntersect(&ValidReg, &pExaPixmap->validFB,
+ &pExaPixmap->validSys);
+ nbox = RegionNumRects(&ValidReg);
+
+ if (!nbox)
+ goto out;
+
+ pBox = RegionRects(&ValidReg);
+
+ dst_pitch = pExaPixmap->sys_pitch;
+ src_pitch = pExaPixmap->fb_pitch;
+ cpp = pPixmap->drawable.bitsPerPixel / 8;
+
+ save_use_gpu_copy = pExaPixmap->use_gpu_copy;
+ save_pitch = pPixmap->devKind;
+ pExaPixmap->use_gpu_copy = TRUE;
+ pPixmap->devKind = pExaPixmap->fb_pitch;
+
+ if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
+ goto skip;
+
+ while (nbox--) {
+ int rowbytes;
+
+ pBox->x1 = max(pBox->x1, 0);
+ pBox->y1 = max(pBox->y1, 0);
+ pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
+ pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
+
+ if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
+ continue;
+
+ rowbytes = (pBox->x2 - pBox->x1) * cpp;
+ src = (CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch + pBox->x1 * cpp;
+ dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
+
+ for (y = pBox->y1; y < pBox->y2;
+ y++, src += src_pitch, dst += dst_pitch) {
+ if (memcmp(dst, src, rowbytes) != 0) {
+ ret = FALSE;
+ exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2,
+ pBox->y2);
+ break;
+ }
+ }
+ }
+
+skip:
+ exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
+
+ pExaPixmap->use_gpu_copy = save_use_gpu_copy;
+ pPixmap->devKind = save_pitch;
+
+out:
+ RegionUninit(&ValidReg);
+ return ret;
+}
+
+/**
+ * Performs migration of the pixmaps according to the operation information
+ * provided in pixmaps and can_accel and the migration scheme chosen in the
+ * config file.
+ */
+void
+exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+{
+ ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ int i, j;
+
+ /* If this debugging flag is set, check each pixmap for whether it is marked
+ * as clean, and if so, actually check if that's the case. This should help
+ * catch issues with failing to mark a drawable as dirty. While it will
+ * catch them late (after the operation happened), it at least explains what
+ * went wrong, and instrumenting the code to find what operation happened
+ * to the pixmap last shouldn't be hard.
+ */
+ if (pExaScr->checkDirtyCorrectness) {
+ for (i = 0; i < npixmaps; i++) {
+ if (!exaPixmapIsDirty (pixmaps[i].pPix) &&
+ !exaAssertNotDirty (pixmaps[i].pPix))
+ ErrorF("%s: Pixmap %d dirty but not marked as such!\n", __func__, i);
+ }
+ }
+ /* If anything is pinned in system memory, we won't be able to
+ * accelerate.
+ */
+ for (i = 0; i < npixmaps; i++) {
+ if (exaPixmapIsPinned (pixmaps[i].pPix) &&
+ !exaPixmapHasGpuCopy (pixmaps[i].pPix))
+ {
+ EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix,
+ pixmaps[i].pPix->drawable.width,
+ pixmaps[i].pPix->drawable.height));
+ can_accel = FALSE;
+ break;
+ }
+ }
+
+ if (pExaScr->migration == ExaMigrationSmart) {
+ /* If we've got something as a destination that we shouldn't cause to
+ * become newly dirtied, take the unaccelerated route.
+ */
+ for (i = 0; i < npixmaps; i++) {
+ if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB (pixmaps[i].pPix) &&
+ !exaPixmapIsDirty (pixmaps[i].pPix))
+ {
+ for (i = 0; i < npixmaps; i++) {
+ if (!exaPixmapIsDirty (pixmaps[i].pPix))
+ exaDoMoveOutPixmap (pixmaps + i);
+ }
+ return;
+ }
+ }
+
+ /* If we aren't going to accelerate, then we migrate everybody toward
+ * system memory, and kick out if it's free.
+ */
+ if (!can_accel) {
+ for (i = 0; i < npixmaps; i++) {
+ exaMigrateTowardSys (pixmaps + i);
+ if (!exaPixmapIsDirty (pixmaps[i].pPix))
+ exaDoMoveOutPixmap (pixmaps + i);
+ }
+ return;
+ }
+
+ /* Finally, the acceleration path. Move them all in. */
+ for (i = 0; i < npixmaps; i++) {
+ exaMigrateTowardFb(pixmaps + i);
+ exaDoMoveInPixmap(pixmaps + i);
+ }
+ } else if (pExaScr->migration == ExaMigrationGreedy) {
+ /* If we can't accelerate, either because the driver can't or because one of
+ * the pixmaps is pinned in system memory, then we migrate everybody toward
+ * system memory.
+ *
+ * We also migrate toward system if all pixmaps involved are currently in
+ * system memory -- this can mitigate thrashing when there are significantly
+ * more pixmaps active than would fit in memory.
+ *
+ * If not, then we migrate toward FB so that hopefully acceleration can
+ * happen.
+ */
+ if (!can_accel) {
+ for (i = 0; i < npixmaps; i++)
+ exaMigrateTowardSys (pixmaps + i);
+ return;
+ }
+
+ for (i = 0; i < npixmaps; i++) {
+ if (exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
+ /* Found one in FB, so move all to FB. */
+ for (j = 0; j < npixmaps; j++)
+ exaMigrateTowardFb(pixmaps + i);
+ return;
+ }
+ }
+
+ /* Nobody's in FB, so move all away from FB. */
+ for (i = 0; i < npixmaps; i++)
+ exaMigrateTowardSys(pixmaps + i);
+ } else if (pExaScr->migration == ExaMigrationAlways) {
+ /* Always move the pixmaps out if we can't accelerate. If we can
+ * accelerate, try to move them all in. If that fails, then move them
+ * back out.
+ */
+ if (!can_accel) {
+ for (i = 0; i < npixmaps; i++)
+ exaDoMoveOutPixmap(pixmaps + i);
+ return;
+ }
+
+ /* Now, try to move them all into FB */
+ for (i = 0; i < npixmaps; i++) {
+ exaDoMoveInPixmap(pixmaps + i);
+ }
+
+ /* If we couldn't fit everything in, abort */
+ for (i = 0; i < npixmaps; i++) {
+ if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
+ return;
+ }
+ }
+
+ /* Yay, everything has a gpu copy, mark memory as used */
+ for (i = 0; i < npixmaps; i++) {
+ ExaOffscreenMarkUsed (pixmaps[i].pPix);
+ }
+ }
+}
+
+void
+exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
+{
+ ExaMigrationRec pixmaps[1];
+
+ if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ } else {
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ }
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = pReg;
+
+ exaDoMigration(pixmaps, 1, FALSE);
+
+ (void)ExaDoPrepareAccess(pPixmap, index);
+}
diff --git a/xorg-server/exa/exa_migration_mixed.c b/xorg-server/exa/exa_migration_mixed.c
index 9489b2927..4b2261943 100644
--- a/xorg-server/exa/exa_migration_mixed.c
+++ b/xorg-server/exa/exa_migration_mixed.c
@@ -1,261 +1,261 @@
-/*
- * Copyright © 2009 Maarten Maathuis
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-
-#include "exa_priv.h"
-#include "exa.h"
-
-void
-exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
- ExaPixmapPriv(pPixmap);
- int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
- int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
- int usage_hint = pPixmap->usage_hint;
- int paddedWidth = pExaPixmap->sys_pitch;
-
- /* Already done. */
- if (pExaPixmap->driverPriv)
- return;
-
- if (exaPixmapIsPinned(pPixmap))
- return;
-
- /* Can't accel 1/4 bpp. */
- if (pExaPixmap->accel_blocked || bpp < 8)
- return;
-
- if (pExaScr->info->CreatePixmap2) {
- int new_pitch = 0;
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
- paddedWidth = pExaPixmap->fb_pitch = new_pitch;
- } else {
- if (paddedWidth < pExaPixmap->fb_pitch)
- paddedWidth = pExaPixmap->fb_pitch;
- pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, paddedWidth*h, 0);
- }
-
- if (!pExaPixmap->driverPriv)
- return;
-
- (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
- paddedWidth, NULL);
-}
-
-void
-exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
-{
- int i;
-
- /* If anything is pinned in system memory, we won't be able to
- * accelerate.
- */
- for (i = 0; i < npixmaps; i++) {
- if (exaPixmapIsPinned (pixmaps[i].pPix) &&
- !exaPixmapHasGpuCopy (pixmaps[i].pPix))
- {
- can_accel = FALSE;
- break;
- }
- }
-
- /* We can do nothing. */
- if (!can_accel)
- return;
-
- for (i = 0; i < npixmaps; i++) {
- PixmapPtr pPixmap = pixmaps[i].pPix;
- ExaPixmapPriv(pPixmap);
-
- if (!pExaPixmap->driverPriv)
- exaCreateDriverPixmap_mixed(pPixmap);
-
- if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) {
- ExaScreenPriv(pPixmap->drawable.pScreen);
-
- /* This pitch is needed for proper acceleration. For some reason
- * there are pixmaps without pDamage and a bad fb_pitch value.
- * So setting devKind when only exaPixmapHasGpuCopy() is true
- * causes corruption. Pixmaps without pDamage are not migrated
- * and should have a valid devKind at all times, so that's why this
- * isn't causing problems. Pixmaps have their gpu pitch set the
- * first time in the MPH call from exaCreateDriverPixmap_mixed().
- */
- pPixmap->devKind = pExaPixmap->fb_pitch;
- exaCopyDirtyToFb(pixmaps + i);
-
- if (pExaScr->deferred_mixed_pixmap == pPixmap &&
- !pixmaps[i].as_dst && !pixmaps[i].pReg)
- pExaScr->deferred_mixed_pixmap = NULL;
- }
-
- pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
- }
-}
-
-void
-exaMoveInPixmap_mixed(PixmapPtr pPixmap)
-{
- ExaMigrationRec pixmaps[1];
-
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = NULL;
-
- exaDoMigration(pixmaps, 1, TRUE);
-}
-
-void
-exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure)
-{
- PixmapPtr pPixmap = closure;
- ExaPixmapPriv(pPixmap);
-
- /* Move back results of software rendering on system memory copy of mixed driver
- * pixmap (see exaPrepareAccessReg_mixed).
- *
- * Defer moving the destination back into the driver pixmap, to try and save
- * overhead on multiple subsequent software fallbacks.
- */
- if (!pExaPixmap->use_gpu_copy && exaPixmapHasGpuCopy(pPixmap)) {
- ExaScreenPriv(pPixmap->drawable.pScreen);
-
- if (pExaScr->deferred_mixed_pixmap &&
- pExaScr->deferred_mixed_pixmap != pPixmap)
- exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
- pExaScr->deferred_mixed_pixmap = pPixmap;
- }
-}
-
-/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
- * use the DownloadFromScreen hook to retrieve contents to a copy in system
- * memory, perform software rendering on that and move back the results with the
- * UploadToScreen hook (see exaDamageReport_mixed).
- */
-void
-exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
-{
- ExaPixmapPriv(pPixmap);
- Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
- Bool success;
-
- success = ExaDoPrepareAccess(pPixmap, index);
-
- if (success && has_gpu_copy && pExaPixmap->pDamage) {
- /* You cannot do accelerated operations while a buffer is mapped. */
- exaFinishAccess(&pPixmap->drawable, index);
- /* Update the gpu view of both deferred destination pixmaps and of
- * source pixmaps that were migrated with a bounding region.
- */
- exaMoveInPixmap_mixed(pPixmap);
- success = ExaDoPrepareAccess(pPixmap, index);
-
- if (success) {
- /* We have a gpu pixmap that can be accessed, we don't need the cpu
- * copy anymore. Drivers that prefer DFS, should fail prepare
- * access.
- */
- DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
- DamageDestroy(pExaPixmap->pDamage);
- pExaPixmap->pDamage = NULL;
-
- free(pExaPixmap->sys_ptr);
- pExaPixmap->sys_ptr = NULL;
-
- return;
- }
- }
-
- if (!success) {
- ExaMigrationRec pixmaps[1];
-
- /* Do we need to allocate our system buffer? */
- if (!pExaPixmap->sys_ptr) {
- pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch *
- pPixmap->drawable.height);
- if (!pExaPixmap->sys_ptr)
- FatalError("EXA: malloc failed for size %d bytes\n",
- pExaPixmap->sys_pitch * pPixmap->drawable.height);
- }
-
- if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- } else {
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- }
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = pReg;
-
- if (!pExaPixmap->pDamage &&
- (has_gpu_copy || !exaPixmapIsPinned(pPixmap))) {
- Bool as_dst = pixmaps[0].as_dst;
-
- /* Set up damage tracking */
- pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
- DamageReportNonEmpty, TRUE,
- pPixmap->drawable.pScreen,
- pPixmap);
-
- DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
- /* This ensures that pending damage reflects the current operation. */
- /* This is used by exa to optimize migration. */
- DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
-
- if (has_gpu_copy) {
- exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
- pPixmap->drawable.height);
-
- /* We don't know which region of the destination will be damaged,
- * have to assume all of it
- */
- if (as_dst) {
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pReg = NULL;
- }
- exaCopyDirtyToSys(pixmaps);
- }
-
- if (as_dst)
- exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
- pPixmap->drawable.height);
- } else if (has_gpu_copy)
- exaCopyDirtyToSys(pixmaps);
-
- pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
- pPixmap->devKind = pExaPixmap->sys_pitch;
- pExaPixmap->use_gpu_copy = FALSE;
- }
-}
-
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+void
+exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
+ int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
+ int usage_hint = pPixmap->usage_hint;
+ int paddedWidth = pExaPixmap->sys_pitch;
+
+ /* Already done. */
+ if (pExaPixmap->driverPriv)
+ return;
+
+ if (exaPixmapIsPinned(pPixmap))
+ return;
+
+ /* Can't accel 1/4 bpp. */
+ if (pExaPixmap->accel_blocked || bpp < 8)
+ return;
+
+ if (pExaScr->info->CreatePixmap2) {
+ int new_pitch = 0;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp, &new_pitch);
+ paddedWidth = pExaPixmap->fb_pitch = new_pitch;
+ } else {
+ if (paddedWidth < pExaPixmap->fb_pitch)
+ paddedWidth = pExaPixmap->fb_pitch;
+ pExaPixmap->driverPriv = pExaScr->info->CreatePixmap(pScreen, paddedWidth*h, 0);
+ }
+
+ if (!pExaPixmap->driverPriv)
+ return;
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+}
+
+void
+exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
+{
+ int i;
+
+ /* If anything is pinned in system memory, we won't be able to
+ * accelerate.
+ */
+ for (i = 0; i < npixmaps; i++) {
+ if (exaPixmapIsPinned (pixmaps[i].pPix) &&
+ !exaPixmapHasGpuCopy (pixmaps[i].pPix))
+ {
+ can_accel = FALSE;
+ break;
+ }
+ }
+
+ /* We can do nothing. */
+ if (!can_accel)
+ return;
+
+ for (i = 0; i < npixmaps; i++) {
+ PixmapPtr pPixmap = pixmaps[i].pPix;
+ ExaPixmapPriv(pPixmap);
+
+ if (!pExaPixmap->driverPriv)
+ exaCreateDriverPixmap_mixed(pPixmap);
+
+ if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) {
+ ExaScreenPriv(pPixmap->drawable.pScreen);
+
+ /* This pitch is needed for proper acceleration. For some reason
+ * there are pixmaps without pDamage and a bad fb_pitch value.
+ * So setting devKind when only exaPixmapHasGpuCopy() is true
+ * causes corruption. Pixmaps without pDamage are not migrated
+ * and should have a valid devKind at all times, so that's why this
+ * isn't causing problems. Pixmaps have their gpu pitch set the
+ * first time in the MPH call from exaCreateDriverPixmap_mixed().
+ */
+ pPixmap->devKind = pExaPixmap->fb_pitch;
+ exaCopyDirtyToFb(pixmaps + i);
+
+ if (pExaScr->deferred_mixed_pixmap == pPixmap &&
+ !pixmaps[i].as_dst && !pixmaps[i].pReg)
+ pExaScr->deferred_mixed_pixmap = NULL;
+ }
+
+ pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+ }
+}
+
+void
+exaMoveInPixmap_mixed(PixmapPtr pPixmap)
+{
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
+ exaDoMigration(pixmaps, 1, TRUE);
+}
+
+void
+exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+ PixmapPtr pPixmap = closure;
+ ExaPixmapPriv(pPixmap);
+
+ /* Move back results of software rendering on system memory copy of mixed driver
+ * pixmap (see exaPrepareAccessReg_mixed).
+ *
+ * Defer moving the destination back into the driver pixmap, to try and save
+ * overhead on multiple subsequent software fallbacks.
+ */
+ if (!pExaPixmap->use_gpu_copy && exaPixmapHasGpuCopy(pPixmap)) {
+ ExaScreenPriv(pPixmap->drawable.pScreen);
+
+ if (pExaScr->deferred_mixed_pixmap &&
+ pExaScr->deferred_mixed_pixmap != pPixmap)
+ exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
+ pExaScr->deferred_mixed_pixmap = pPixmap;
+ }
+}
+
+/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
+ * use the DownloadFromScreen hook to retrieve contents to a copy in system
+ * memory, perform software rendering on that and move back the results with the
+ * UploadToScreen hook (see exaDamageReport_mixed).
+ */
+void
+exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
+{
+ ExaPixmapPriv(pPixmap);
+ Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+ Bool success;
+
+ success = ExaDoPrepareAccess(pPixmap, index);
+
+ if (success && has_gpu_copy && pExaPixmap->pDamage) {
+ /* You cannot do accelerated operations while a buffer is mapped. */
+ exaFinishAccess(&pPixmap->drawable, index);
+ /* Update the gpu view of both deferred destination pixmaps and of
+ * source pixmaps that were migrated with a bounding region.
+ */
+ exaMoveInPixmap_mixed(pPixmap);
+ success = ExaDoPrepareAccess(pPixmap, index);
+
+ if (success) {
+ /* We have a gpu pixmap that can be accessed, we don't need the cpu
+ * copy anymore. Drivers that prefer DFS, should fail prepare
+ * access.
+ */
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+
+ free(pExaPixmap->sys_ptr);
+ pExaPixmap->sys_ptr = NULL;
+
+ return;
+ }
+ }
+
+ if (!success) {
+ ExaMigrationRec pixmaps[1];
+
+ /* Do we need to allocate our system buffer? */
+ if (!pExaPixmap->sys_ptr) {
+ pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch *
+ pPixmap->drawable.height);
+ if (!pExaPixmap->sys_ptr)
+ FatalError("EXA: malloc failed for size %d bytes\n",
+ pExaPixmap->sys_pitch * pPixmap->drawable.height);
+ }
+
+ if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ } else {
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ }
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = pReg;
+
+ if (!pExaPixmap->pDamage &&
+ (has_gpu_copy || !exaPixmapIsPinned(pPixmap))) {
+ Bool as_dst = pixmaps[0].as_dst;
+
+ /* Set up damage tracking */
+ pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
+ DamageReportNonEmpty, TRUE,
+ pPixmap->drawable.pScreen,
+ pPixmap);
+
+ DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
+ /* This ensures that pending damage reflects the current operation. */
+ /* This is used by exa to optimize migration. */
+ DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
+
+ if (has_gpu_copy) {
+ exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
+ pPixmap->drawable.height);
+
+ /* We don't know which region of the destination will be damaged,
+ * have to assume all of it
+ */
+ if (as_dst) {
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pReg = NULL;
+ }
+ exaCopyDirtyToSys(pixmaps);
+ }
+
+ if (as_dst)
+ exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
+ pPixmap->drawable.height);
+ } else if (has_gpu_copy)
+ exaCopyDirtyToSys(pixmaps);
+
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ pExaPixmap->use_gpu_copy = FALSE;
+ }
+}
+
diff --git a/xorg-server/exa/exa_mixed.c b/xorg-server/exa/exa_mixed.c
index 188a7e0a6..58645aea0 100644
--- a/xorg-server/exa/exa_mixed.c
+++ b/xorg-server/exa/exa_mixed.c
@@ -1,290 +1,290 @@
-/*
- * Copyright © 2009 Maarten Maathuis
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-
-#include "exa_priv.h"
-#include "exa.h"
-
-/* This file holds the driver allocated pixmaps + better initial placement code.
- */
-
-static _X_INLINE void*
-ExaGetPixmapAddress(PixmapPtr p)
-{
- ExaPixmapPriv(p);
-
- return pExaPixmap->sys_ptr;
-}
-
-/**
- * exaCreatePixmap() creates a new pixmap.
- */
-PixmapPtr
-exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
- unsigned usage_hint)
-{
- PixmapPtr pPixmap;
- ExaPixmapPrivPtr pExaPixmap;
- int bpp;
- size_t paddedWidth;
- ExaScreenPriv(pScreen);
-
- if (w > 32767 || h > 32767)
- return NullPixmap;
-
- swap(pExaScr, pScreen, CreatePixmap);
- pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
- swap(pExaScr, pScreen, CreatePixmap);
-
- if (!pPixmap)
- return NULL;
-
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
- pExaPixmap->driverPriv = NULL;
-
- bpp = pPixmap->drawable.bitsPerPixel;
-
- paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
- if (paddedWidth / 4 > 32767 || h > 32767)
- return NullPixmap;
-
- /* We will allocate the system pixmap later if needed. */
- pPixmap->devPrivate.ptr = NULL;
- pExaPixmap->sys_ptr = NULL;
- pExaPixmap->sys_pitch = paddedWidth;
-
- pExaPixmap->area = NULL;
- pExaPixmap->fb_ptr = NULL;
- pExaPixmap->pDamage = NULL;
-
- exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
- exaSetAccelBlock(pExaScr, pExaPixmap,
- w, h, bpp);
-
- (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
- paddedWidth, NULL);
-
- /* A scratch pixmap will become a driver pixmap right away. */
- if (!w || !h) {
- exaCreateDriverPixmap_mixed(pPixmap);
- pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
- } else {
- pExaPixmap->use_gpu_copy = FALSE;
-
- if (w == 1 && h == 1) {
- pExaPixmap->sys_ptr = malloc(paddedWidth);
-
- /* Set up damage tracking */
- pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
- DamageReportNonEmpty, TRUE,
- pPixmap->drawable.pScreen,
- pPixmap);
-
- DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
- /* This ensures that pending damage reflects the current operation. */
- /* This is used by exa to optimize migration. */
- DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
- }
- }
-
- /* During a fallback we must prepare access. */
- if (pExaScr->fallback_counter)
- exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
-
- return pPixmap;
-}
-
-Bool
-exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
- int bitsPerPixel, int devKind, pointer pPixData)
-{
- ScreenPtr pScreen;
- ExaScreenPrivPtr pExaScr;
- ExaPixmapPrivPtr pExaPixmap;
- Bool ret, has_gpu_copy;
-
- if (!pPixmap)
- return FALSE;
-
- pScreen = pPixmap->drawable.pScreen;
- pExaScr = ExaGetScreenPriv(pScreen);
- pExaPixmap = ExaGetPixmapPriv(pPixmap);
-
- if (pPixData) {
- if (pExaPixmap->driverPriv) {
- if (pExaPixmap->pDamage) {
- DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
- DamageDestroy(pExaPixmap->pDamage);
- pExaPixmap->pDamage = NULL;
- }
-
- pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
- pExaPixmap->driverPriv = NULL;
- }
-
- pExaPixmap->use_gpu_copy = FALSE;
- pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
- }
-
- has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
-
- if (width <= 0)
- width = pPixmap->drawable.width;
-
- if (height <= 0)
- height = pPixmap->drawable.height;
-
- if (bitsPerPixel <= 0) {
- if (depth <= 0)
- bitsPerPixel = pPixmap->drawable.bitsPerPixel;
- else
- bitsPerPixel = BitsPerPixel(depth);
- }
-
- if (depth <= 0)
- depth = pPixmap->drawable.depth;
-
- if (width != pPixmap->drawable.width ||
- height != pPixmap->drawable.height ||
- depth != pPixmap->drawable.depth ||
- bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
- if (pExaPixmap->driverPriv) {
- if (devKind > 0)
- pExaPixmap->fb_pitch = devKind;
- else
- exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
-
- exaSetAccelBlock(pExaScr, pExaPixmap,
- width, height, bitsPerPixel);
- RegionEmpty(&pExaPixmap->validFB);
- }
-
- /* Need to re-create system copy if there's also a GPU copy */
- if (has_gpu_copy && pExaPixmap->sys_ptr) {
- free(pExaPixmap->sys_ptr);
- pExaPixmap->sys_ptr = NULL;
- pExaPixmap->sys_pitch = PixmapBytePad(width, depth);
- DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
- DamageDestroy(pExaPixmap->pDamage);
- pExaPixmap->pDamage = NULL;
- RegionEmpty(&pExaPixmap->validSys);
-
- if (pExaScr->deferred_mixed_pixmap == pPixmap)
- pExaScr->deferred_mixed_pixmap = NULL;
- }
- }
-
- if (has_gpu_copy) {
- pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
- pPixmap->devKind = pExaPixmap->fb_pitch;
- } else {
- pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
- pPixmap->devKind = pExaPixmap->sys_pitch;
- }
-
- /* Only pass driver pixmaps to the driver. */
- if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
- ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
- if (ret == TRUE)
- goto out;
- }
-
- swap(pExaScr, pScreen, ModifyPixmapHeader);
- ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
- bitsPerPixel, devKind, pPixData);
- swap(pExaScr, pScreen, ModifyPixmapHeader);
-
-out:
- if (has_gpu_copy) {
- pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
- pExaPixmap->fb_pitch = pPixmap->devKind;
- } else {
- pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
- pExaPixmap->sys_pitch = pPixmap->devKind;
- }
- /* Always NULL this, we don't want lingering pointers. */
- pPixmap->devPrivate.ptr = NULL;
-
- return ret;
-}
-
-Bool
-exaDestroyPixmap_mixed(PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
- Bool ret;
-
- if (pPixmap->refcnt == 1)
- {
- ExaPixmapPriv (pPixmap);
-
- exaDestroyPixmap(pPixmap);
-
- if (pExaScr->deferred_mixed_pixmap == pPixmap)
- pExaScr->deferred_mixed_pixmap = NULL;
-
- if (pExaPixmap->driverPriv)
- pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
- pExaPixmap->driverPriv = NULL;
-
- if (pExaPixmap->pDamage) {
- free(pExaPixmap->sys_ptr);
- pExaPixmap->sys_ptr = NULL;
- pExaPixmap->pDamage = NULL;
- }
- }
-
- swap(pExaScr, pScreen, DestroyPixmap);
- ret = pScreen->DestroyPixmap (pPixmap);
- swap(pExaScr, pScreen, DestroyPixmap);
-
- return ret;
-}
-
-Bool
-exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
-{
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- ExaScreenPriv(pScreen);
- ExaPixmapPriv(pPixmap);
- pointer saved_ptr;
- Bool ret;
-
- if (!pExaPixmap->driverPriv)
- return FALSE;
-
- saved_ptr = pPixmap->devPrivate.ptr;
- pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
- ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
- pPixmap->devPrivate.ptr = saved_ptr;
-
- return ret;
-}
+/*
+ * Copyright © 2009 Maarten Maathuis
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+#include "exa.h"
+
+/* This file holds the driver allocated pixmaps + better initial placement code.
+ */
+
+static _X_INLINE void*
+ExaGetPixmapAddress(PixmapPtr p)
+{
+ ExaPixmapPriv(p);
+
+ return pExaPixmap->sys_ptr;
+}
+
+/**
+ * exaCreatePixmap() creates a new pixmap.
+ */
+PixmapPtr
+exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
+ unsigned usage_hint)
+{
+ PixmapPtr pPixmap;
+ ExaPixmapPrivPtr pExaPixmap;
+ int bpp;
+ size_t paddedWidth;
+ ExaScreenPriv(pScreen);
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ swap(pExaScr, pScreen, CreatePixmap);
+ pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
+ swap(pExaScr, pScreen, CreatePixmap);
+
+ if (!pPixmap)
+ return NULL;
+
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+ pExaPixmap->driverPriv = NULL;
+
+ bpp = pPixmap->drawable.bitsPerPixel;
+
+ paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
+ if (paddedWidth / 4 > 32767 || h > 32767)
+ return NullPixmap;
+
+ /* We will allocate the system pixmap later if needed. */
+ pPixmap->devPrivate.ptr = NULL;
+ pExaPixmap->sys_ptr = NULL;
+ pExaPixmap->sys_pitch = paddedWidth;
+
+ pExaPixmap->area = NULL;
+ pExaPixmap->fb_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+
+ exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ w, h, bpp);
+
+ (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
+ paddedWidth, NULL);
+
+ /* A scratch pixmap will become a driver pixmap right away. */
+ if (!w || !h) {
+ exaCreateDriverPixmap_mixed(pPixmap);
+ pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+ } else {
+ pExaPixmap->use_gpu_copy = FALSE;
+
+ if (w == 1 && h == 1) {
+ pExaPixmap->sys_ptr = malloc(paddedWidth);
+
+ /* Set up damage tracking */
+ pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
+ DamageReportNonEmpty, TRUE,
+ pPixmap->drawable.pScreen,
+ pPixmap);
+
+ DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
+ /* This ensures that pending damage reflects the current operation. */
+ /* This is used by exa to optimize migration. */
+ DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
+ }
+ }
+
+ /* During a fallback we must prepare access. */
+ if (pExaScr->fallback_counter)
+ exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
+
+ return pPixmap;
+}
+
+Bool
+exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, pointer pPixData)
+{
+ ScreenPtr pScreen;
+ ExaScreenPrivPtr pExaScr;
+ ExaPixmapPrivPtr pExaPixmap;
+ Bool ret, has_gpu_copy;
+
+ if (!pPixmap)
+ return FALSE;
+
+ pScreen = pPixmap->drawable.pScreen;
+ pExaScr = ExaGetScreenPriv(pScreen);
+ pExaPixmap = ExaGetPixmapPriv(pPixmap);
+
+ if (pPixData) {
+ if (pExaPixmap->driverPriv) {
+ if (pExaPixmap->pDamage) {
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ }
+
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ pExaPixmap->driverPriv = NULL;
+ }
+
+ pExaPixmap->use_gpu_copy = FALSE;
+ pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+ }
+
+ has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
+
+ if (width <= 0)
+ width = pPixmap->drawable.width;
+
+ if (height <= 0)
+ height = pPixmap->drawable.height;
+
+ if (bitsPerPixel <= 0) {
+ if (depth <= 0)
+ bitsPerPixel = pPixmap->drawable.bitsPerPixel;
+ else
+ bitsPerPixel = BitsPerPixel(depth);
+ }
+
+ if (depth <= 0)
+ depth = pPixmap->drawable.depth;
+
+ if (width != pPixmap->drawable.width ||
+ height != pPixmap->drawable.height ||
+ depth != pPixmap->drawable.depth ||
+ bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
+ if (pExaPixmap->driverPriv) {
+ if (devKind > 0)
+ pExaPixmap->fb_pitch = devKind;
+ else
+ exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
+
+ exaSetAccelBlock(pExaScr, pExaPixmap,
+ width, height, bitsPerPixel);
+ RegionEmpty(&pExaPixmap->validFB);
+ }
+
+ /* Need to re-create system copy if there's also a GPU copy */
+ if (has_gpu_copy && pExaPixmap->sys_ptr) {
+ free(pExaPixmap->sys_ptr);
+ pExaPixmap->sys_ptr = NULL;
+ pExaPixmap->sys_pitch = PixmapBytePad(width, depth);
+ DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
+ DamageDestroy(pExaPixmap->pDamage);
+ pExaPixmap->pDamage = NULL;
+ RegionEmpty(&pExaPixmap->validSys);
+
+ if (pExaScr->deferred_mixed_pixmap == pPixmap)
+ pExaScr->deferred_mixed_pixmap = NULL;
+ }
+ }
+
+ if (has_gpu_copy) {
+ pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
+ pPixmap->devKind = pExaPixmap->fb_pitch;
+ } else {
+ pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+ pPixmap->devKind = pExaPixmap->sys_pitch;
+ }
+
+ /* Only pass driver pixmaps to the driver. */
+ if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
+ ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ if (ret == TRUE)
+ goto out;
+ }
+
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+ ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ swap(pExaScr, pScreen, ModifyPixmapHeader);
+
+out:
+ if (has_gpu_copy) {
+ pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->fb_pitch = pPixmap->devKind;
+ } else {
+ pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+ pExaPixmap->sys_pitch = pPixmap->devKind;
+ }
+ /* Always NULL this, we don't want lingering pointers. */
+ pPixmap->devPrivate.ptr = NULL;
+
+ return ret;
+}
+
+Bool
+exaDestroyPixmap_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ Bool ret;
+
+ if (pPixmap->refcnt == 1)
+ {
+ ExaPixmapPriv (pPixmap);
+
+ exaDestroyPixmap(pPixmap);
+
+ if (pExaScr->deferred_mixed_pixmap == pPixmap)
+ pExaScr->deferred_mixed_pixmap = NULL;
+
+ if (pExaPixmap->driverPriv)
+ pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+ pExaPixmap->driverPriv = NULL;
+
+ if (pExaPixmap->pDamage) {
+ free(pExaPixmap->sys_ptr);
+ pExaPixmap->sys_ptr = NULL;
+ pExaPixmap->pDamage = NULL;
+ }
+ }
+
+ swap(pExaScr, pScreen, DestroyPixmap);
+ ret = pScreen->DestroyPixmap (pPixmap);
+ swap(pExaScr, pScreen, DestroyPixmap);
+
+ return ret;
+}
+
+Bool
+exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
+{
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ ExaScreenPriv(pScreen);
+ ExaPixmapPriv(pPixmap);
+ pointer saved_ptr;
+ Bool ret;
+
+ if (!pExaPixmap->driverPriv)
+ return FALSE;
+
+ saved_ptr = pPixmap->devPrivate.ptr;
+ pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+ ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
+ pPixmap->devPrivate.ptr = saved_ptr;
+
+ return ret;
+}
diff --git a/xorg-server/exa/exa_unaccel.c b/xorg-server/exa/exa_unaccel.c
index df416d5ac..219f903b2 100644
--- a/xorg-server/exa/exa_unaccel.c
+++ b/xorg-server/exa/exa_unaccel.c
@@ -1,6 +1,6 @@
/*
*
- * Copyright © 1999 Keith Packard
+ * Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/dmx/dmxinput.c b/xorg-server/hw/dmx/dmxinput.c
index 517a5ee8c..f006af4d2 100644
--- a/xorg-server/hw/dmx/dmxinput.c
+++ b/xorg-server/hw/dmx/dmxinput.c
@@ -1,119 +1,120 @@
-/*
- * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation on the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/*
- * Authors:
- * David H. Dawes <dawes@xfree86.org>
- * Kevin E. Martin <kem@redhat.com>
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- * Provide the main entry points for input initialization and processing
- * that arequired by the dix layer.
- */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "dmx.h"
-#include "dmxlog.h"
-#include "dmxinput.h"
-
-#include "inputstr.h"
-#include "input.h"
-#include "mi.h"
-
-/** Returns TRUE if the key is a valid modifier. For PC-class
- * keyboards, all keys can be used as modifiers, so return TRUE
- * always. */
-Bool LegalModifier(unsigned int key, DeviceIntPtr pDev)
-{
- return TRUE;
-}
-
-/** Called from dix/main.c on each server generation to initialize
- * inputs. All the work is done in dmxInputInit. \see
- * dmxInputInit() */
-void InitInput(int argc, char **argv)
-{
- int i;
- DMXInputInfo *dmxInput;
-
- if (!dmxNumInputs)
- dmxLog(dmxFatal, "InitInput: no inputs specified\n");
-
- for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
- dmxInputInit(dmxInput);
-
- mieqInit();
-}
-
-void CloseInput(void)
-{
-}
-
-/** Called from dix/dispatch.c in Dispatch() whenever input events
- * require processing. All the work is done in the lower level
- * routines. */
-void ProcessInputEvents(void)
-{
- int i;
- DMXInputInfo *dmxInput;
-
- for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
- if (!dmxInput->detached && dmxInput->processInputEvents)
- dmxInput->processInputEvents(dmxInput);
-}
-
-/** This routine is called from \a dmxwindow.c whenever the layout of
- * windows on the display might have changed. This information is used
- * by input drivers (currently only the console driver) that provide
- * information about window layout to the user. */
-void dmxUpdateWindowInfo(DMXUpdateType type, WindowPtr pWindow)
-{
- int i;
- DMXInputInfo *dmxInput;
-
- for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
- if (!dmxInput->detached && dmxInput->updateWindowInfo)
- dmxInput->updateWindowInfo(dmxInput, type, pWindow);
-}
-
-int
-NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
- DeviceIntPtr *pdev)
-{
- return BadRequest;
-}
-
-void
-DeleteInputDeviceRequest(DeviceIntPtr pDev)
-{
-}
+/*
+ * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * David H. Dawes <dawes@xfree86.org>
+ * Kevin E. Martin <kem@redhat.com>
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * Provide the main entry points for input initialization and processing
+ * that arequired by the dix layer.
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxlog.h"
+#include "dmxinput.h"
+
+#include "inputstr.h"
+#include "input.h"
+#include "mi.h"
+
+/** Returns TRUE if the key is a valid modifier. For PC-class
+ * keyboards, all keys can be used as modifiers, so return TRUE
+ * always. */
+Bool LegalModifier(unsigned int key, DeviceIntPtr pDev)
+{
+ return TRUE;
+}
+
+/** Called from dix/main.c on each server generation to initialize
+ * inputs. All the work is done in dmxInputInit. \see
+ * dmxInputInit() */
+void InitInput(int argc, char **argv)
+{
+ int i;
+ DMXInputInfo *dmxInput;
+
+ if (!dmxNumInputs)
+ dmxLog(dmxFatal, "InitInput: no inputs specified\n");
+
+ for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
+ dmxInputInit(dmxInput);
+
+ mieqInit();
+}
+
+void CloseInput(void)
+{
+ mieqFini();
+}
+
+/** Called from dix/dispatch.c in Dispatch() whenever input events
+ * require processing. All the work is done in the lower level
+ * routines. */
+void ProcessInputEvents(void)
+{
+ int i;
+ DMXInputInfo *dmxInput;
+
+ for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
+ if (!dmxInput->detached && dmxInput->processInputEvents)
+ dmxInput->processInputEvents(dmxInput);
+}
+
+/** This routine is called from \a dmxwindow.c whenever the layout of
+ * windows on the display might have changed. This information is used
+ * by input drivers (currently only the console driver) that provide
+ * information about window layout to the user. */
+void dmxUpdateWindowInfo(DMXUpdateType type, WindowPtr pWindow)
+{
+ int i;
+ DMXInputInfo *dmxInput;
+
+ for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
+ if (!dmxInput->detached && dmxInput->updateWindowInfo)
+ dmxInput->updateWindowInfo(dmxInput, type, pWindow);
+}
+
+int
+NewInputDeviceRequest (InputOption *options, InputAttributes *attrs,
+ DeviceIntPtr *pdev)
+{
+ return BadRequest;
+}
+
+void
+DeleteInputDeviceRequest(DeviceIntPtr pDev)
+{
+}
diff --git a/xorg-server/hw/dmx/input/dmxinputinit.c b/xorg-server/hw/dmx/input/dmxinputinit.c
index 5cbd620c9..1b067c725 100644
--- a/xorg-server/hw/dmx/input/dmxinputinit.c
+++ b/xorg-server/hw/dmx/input/dmxinputinit.c
@@ -546,9 +546,6 @@ static void dmxProcessInputEvents(DMXInputInfo *dmxInput)
return;
for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding)
if (dmxInput->devs[i]->process_input) {
-#if 11 /*BP*/
- miPointerUpdateSprite(dmxInput->devs[i]->pDevice);
-#endif
dmxInput->devs[i]->process_input(dmxInput->devs[i]->private);
}
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.c b/xorg-server/hw/kdrive/ephyr/ephyr.c
index ac8e5bef9..7ebf1c253 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyr.c
+++ b/xorg-server/hw/kdrive/ephyr/ephyr.c
@@ -2,7 +2,7 @@
* Xephyr - A kdrive X server thats runs in a host X window.
* Authored by Matthew Allum <mallum@openedhand.com>
*
- * Copyright © 2004 Nokia
+ * Copyright © 2004 Nokia
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.h b/xorg-server/hw/kdrive/ephyr/ephyr.h
index 41a82bf9d..23848004c 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyr.h
+++ b/xorg-server/hw/kdrive/ephyr/ephyr.h
@@ -2,7 +2,7 @@
* Xephyr - A kdrive X server thats runs in a host X window.
* Authored by Matthew Allum <mallum@o-hand.com>
*
- * Copyright © 2004 Nokia
+ * Copyright © 2004 Nokia
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr_draw.c b/xorg-server/hw/kdrive/ephyr/ephyr_draw.c
index f3e2be6eb..cf5f55394 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyr_draw.c
+++ b/xorg-server/hw/kdrive/ephyr/ephyr_draw.c
@@ -1,523 +1,523 @@
-/*
- * Copyright © 2006 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- * Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-
-#include "ephyr.h"
-#include "exa_priv.h"
-#include "fbpict.h"
-
-#define EPHYR_TRACE_DRAW 0
-
-#if EPHYR_TRACE_DRAW
-#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__);
-#else
-#define TRACE_DRAW() do { } while (0)
-#endif
-
-/* Use some oddball alignments, to expose issues in alignment handling in EXA. */
-#define EPHYR_OFFSET_ALIGN 24
-#define EPHYR_PITCH_ALIGN 24
-
-#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024)
-#define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024)
-
-/**
- * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to
- * fb functions.
- */
-static void
-ephyrPreparePipelinedAccess(PixmapPtr pPix, int index)
-{
- KdScreenPriv(pPix->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- assert(fakexa->saved_ptrs[index] == NULL);
- fakexa->saved_ptrs[index] = pPix->devPrivate.ptr;
-
- if (pPix->devPrivate.ptr != NULL)
- return;
-
- pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix);
-}
-
-/**
- * Restores the original devPrivate.ptr of the pixmap from before we messed with
- * it.
- */
-static void
-ephyrFinishPipelinedAccess(PixmapPtr pPix, int index)
-{
- KdScreenPriv(pPix->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- pPix->devPrivate.ptr = fakexa->saved_ptrs[index];
- fakexa->saved_ptrs[index] = NULL;
-}
-
-/**
- * Sets up a scratch GC for fbFill, and saves other parameters for the
- * ephyrSolid implementation.
- */
-static Bool
-ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
-{
- ScreenPtr pScreen = pPix->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
- ChangeGCVal tmpval[3];
-
- ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST);
-
- fakexa->pDst = pPix;
- fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen);
-
- tmpval[0].val = alu;
- tmpval[1].val = pm;
- tmpval[2].val = fg;
- ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask | GCForeground, tmpval);
-
- ValidateGC(&pPix->drawable, fakexa->pGC);
-
- TRACE_DRAW();
-
- return TRUE;
-}
-
-/**
- * Does an fbFill of the rectangle to be drawn.
- */
-static void
-ephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
-{
- ScreenPtr pScreen = pPix->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1);
-}
-
-/**
- * Cleans up the scratch GC created in ephyrPrepareSolid.
- */
-static void
-ephyrDoneSolid(PixmapPtr pPix)
-{
- ScreenPtr pScreen = pPix->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- FreeScratchGC(fakexa->pGC);
-
- ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST);
-}
-
-/**
- * Sets up a scratch GC for fbCopyArea, and saves other parameters for the
- * ephyrCopy implementation.
- */
-static Bool
-ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu,
- Pixel pm)
-{
- ScreenPtr pScreen = pDst->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
- ChangeGCVal tmpval[2];
-
- ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
- ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
-
- fakexa->pSrc = pSrc;
- fakexa->pDst = pDst;
- fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen);
-
- tmpval[0].val = alu;
- tmpval[1].val = pm;
- ChangeGC (NullClient, fakexa->pGC, GCFunction | GCPlaneMask, tmpval);
-
- ValidateGC(&pDst->drawable, fakexa->pGC);
-
- TRACE_DRAW();
-
- return TRUE;
-}
-
-/**
- * Does an fbCopyArea to take care of the requested copy.
- */
-static void
-ephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h)
-{
- ScreenPtr pScreen = pDst->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC,
- srcX, srcY, w, h, dstX, dstY);
-}
-
-/**
- * Cleans up the scratch GC created in ephyrPrepareCopy.
- */
-static void
-ephyrDoneCopy(PixmapPtr pDst)
-{
- ScreenPtr pScreen = pDst->drawable.pScreen;
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- FreeScratchGC (fakexa->pGC);
-
- ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
- ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
-}
-
-/**
- * Reports that we can always accelerate the given operation. This may not be
- * desirable from an EXA testing standpoint -- testing the fallback paths would
- * be useful, too.
- */
-static Bool
-ephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
- PicturePtr pDstPicture)
-{
- /* Exercise the component alpha helper, so fail on this case like a normal
- * driver
- */
- if (pMaskPicture && pMaskPicture->componentAlpha && op == PictOpOver)
- return FALSE;
-
- return TRUE;
-}
-
-/**
- * Saves off the parameters for ephyrComposite.
- */
-static Bool
-ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
- PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
- PixmapPtr pDst)
-{
- KdScreenPriv(pDst->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
- ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
- if (pMask != NULL)
- ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK);
-
- fakexa->op = op;
- fakexa->pSrcPicture = pSrcPicture;
- fakexa->pMaskPicture = pMaskPicture;
- fakexa->pDstPicture = pDstPicture;
- fakexa->pSrc = pSrc;
- fakexa->pMask = pMask;
- fakexa->pDst = pDst;
-
- TRACE_DRAW();
-
- return TRUE;
-}
-
-/**
- * Does an fbComposite to complete the requested drawing operation.
- */
-static void
-ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
- int dstX, int dstY, int w, int h)
-{
- KdScreenPriv(pDst->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture,
- fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY,
- w, h);
-}
-
-static void
-ephyrDoneComposite(PixmapPtr pDst)
-{
- KdScreenPriv(pDst->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- if (fakexa->pMask != NULL)
- ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK);
- ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
- ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
-}
-
-/**
- * Does fake acceleration of DownloadFromScren using memcpy.
- */
-static Bool
-ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst,
- int dst_pitch)
-{
- KdScreenPriv(pSrc->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
- unsigned char *src;
- int src_pitch, cpp;
-
- if (pSrc->drawable.bitsPerPixel < 8)
- return FALSE;
-
- ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
-
- cpp = pSrc->drawable.bitsPerPixel / 8;
- src_pitch = exaGetPixmapPitch(pSrc);
- src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc);
- src += y * src_pitch + x * cpp;
-
- for (; h > 0; h--) {
- memcpy(dst, src, w * cpp);
- dst += dst_pitch;
- src += src_pitch;
- }
-
- exaMarkSync(pSrc->drawable.pScreen);
-
- ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC);
-
- return TRUE;
-}
-
-/**
- * Does fake acceleration of UploadToScreen using memcpy.
- */
-static Bool
-ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
- int src_pitch)
-{
- KdScreenPriv(pDst->drawable.pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
- unsigned char *dst;
- int dst_pitch, cpp;
-
- if (pDst->drawable.bitsPerPixel < 8)
- return FALSE;
-
- ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
-
- cpp = pDst->drawable.bitsPerPixel / 8;
- dst_pitch = exaGetPixmapPitch(pDst);
- dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst);
- dst += y * dst_pitch + x * cpp;
-
- for (; h > 0; h--) {
- memcpy(dst, src, w * cpp);
- dst += dst_pitch;
- src += src_pitch;
- }
-
- exaMarkSync(pDst->drawable.pScreen);
-
- ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST);
-
- return TRUE;
-}
-
-static Bool
-ephyrPrepareAccess(PixmapPtr pPix, int index)
-{
- /* Make sure we don't somehow end up with a pointer that is in framebuffer
- * and hasn't been readied for us.
- */
- assert(pPix->devPrivate.ptr != NULL);
-
- return TRUE;
-}
-
-/**
- * In fakexa, we currently only track whether we have synced to the latest
- * "accelerated" drawing that has happened or not. It's not used for anything
- * yet.
- */
-static int
-ephyrMarkSync(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fakexa->is_synced = FALSE;
-
- return 0;
-}
-
-/**
- * Assumes that we're waiting on the latest marker. When EXA gets smarter and
- * starts using markers in a fine-grained way (for example, waiting on drawing
- * to required pixmaps to complete, rather than waiting for all drawing to
- * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker
- * implementation fine-grained as well.
- */
-static void
-ephyrWaitMarker(ScreenPtr pScreen, int marker)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrFakexaPriv *fakexa = scrpriv->fakexa;
-
- fakexa->is_synced = TRUE;
-}
-
-/**
- * This function initializes EXA to use the fake acceleration implementation
- * which just falls through to software. The purpose is to have a reliable,
- * correct driver with which to test changes to the EXA core.
- */
-Bool
-ephyrDrawInit(ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- EphyrScrPriv *scrpriv = screen->driver;
- EphyrPriv *priv = screen->card->driver;
- EphyrFakexaPriv *fakexa;
- Bool success;
-
- fakexa = calloc(1, sizeof(*fakexa));
- if (fakexa == NULL)
- return FALSE;
-
- fakexa->exa = exaDriverAlloc();
- if (fakexa->exa == NULL) {
- free(fakexa);
- return FALSE;
- }
-
- fakexa->exa->memoryBase = (CARD8 *) (priv->base);
- fakexa->exa->memorySize = priv->bytes_per_line * ephyrBufferHeight(screen);
- fakexa->exa->offScreenBase = priv->bytes_per_line * screen->height;
-
- /* Since we statically link against EXA, we shouldn't have to be smart about
- * versioning.
- */
- fakexa->exa->exa_major = 2;
- fakexa->exa->exa_minor = 0;
-
- fakexa->exa->PrepareSolid = ephyrPrepareSolid;
- fakexa->exa->Solid = ephyrSolid;
- fakexa->exa->DoneSolid = ephyrDoneSolid;
-
- fakexa->exa->PrepareCopy = ephyrPrepareCopy;
- fakexa->exa->Copy = ephyrCopy;
- fakexa->exa->DoneCopy = ephyrDoneCopy;
-
- fakexa->exa->CheckComposite = ephyrCheckComposite;
- fakexa->exa->PrepareComposite = ephyrPrepareComposite;
- fakexa->exa->Composite = ephyrComposite;
- fakexa->exa->DoneComposite = ephyrDoneComposite;
-
- fakexa->exa->DownloadFromScreen = ephyrDownloadFromScreen;
- fakexa->exa->UploadToScreen = ephyrUploadToScreen;
-
- fakexa->exa->MarkSync = ephyrMarkSync;
- fakexa->exa->WaitMarker = ephyrWaitMarker;
-
- fakexa->exa->PrepareAccess = ephyrPrepareAccess;
-
- fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN;
- fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN;
-
- fakexa->exa->maxX = 1023;
- fakexa->exa->maxY = 1023;
-
- fakexa->exa->flags = EXA_OFFSCREEN_PIXMAPS;
-
- success = exaDriverInit(pScreen, fakexa->exa);
- if (success) {
- ErrorF("Initialized fake EXA acceleration\n");
- scrpriv->fakexa = fakexa;
- } else {
- ErrorF("Failed to initialize EXA\n");
- free(fakexa->exa);
- free(fakexa);
- }
-
- return success;
-}
-
-void
-ephyrDrawEnable(ScreenPtr pScreen)
-{
-}
-
-void
-ephyrDrawDisable(ScreenPtr pScreen)
-{
-}
-
-void
-ephyrDrawFini(ScreenPtr pScreen)
-{
-}
-
-/**
- * exaDDXDriverInit is required by the top-level EXA module, and is used by
- * the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since
- * we won't be enabling/disabling the FB.
- */
-void
-exaDDXDriverInit(ScreenPtr pScreen)
-{
- ExaScreenPriv(pScreen);
-
- pExaScr->migration = ExaMigrationSmart;
- pExaScr->checkDirtyCorrectness = TRUE;
-}
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+
+#include "ephyr.h"
+#include "exa_priv.h"
+#include "fbpict.h"
+
+#define EPHYR_TRACE_DRAW 0
+
+#if EPHYR_TRACE_DRAW
+#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__);
+#else
+#define TRACE_DRAW() do { } while (0)
+#endif
+
+/* Use some oddball alignments, to expose issues in alignment handling in EXA. */
+#define EPHYR_OFFSET_ALIGN 24
+#define EPHYR_PITCH_ALIGN 24
+
+#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024)
+#define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024)
+
+/**
+ * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to
+ * fb functions.
+ */
+static void
+ephyrPreparePipelinedAccess(PixmapPtr pPix, int index)
+{
+ KdScreenPriv(pPix->drawable.pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ assert(fakexa->saved_ptrs[index] == NULL);
+ fakexa->saved_ptrs[index] = pPix->devPrivate.ptr;
+
+ if (pPix->devPrivate.ptr != NULL)
+ return;
+
+ pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix);
+}
+
+/**
+ * Restores the original devPrivate.ptr of the pixmap from before we messed with
+ * it.
+ */
+static void
+ephyrFinishPipelinedAccess(PixmapPtr pPix, int index)
+{
+ KdScreenPriv(pPix->drawable.pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ pPix->devPrivate.ptr = fakexa->saved_ptrs[index];
+ fakexa->saved_ptrs[index] = NULL;
+}
+
+/**
+ * Sets up a scratch GC for fbFill, and saves other parameters for the
+ * ephyrSolid implementation.
+ */
+static Bool
+ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
+{
+ ScreenPtr pScreen = pPix->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+ ChangeGCVal tmpval[3];
+
+ ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST);
+
+ fakexa->pDst = pPix;
+ fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen);
+
+ tmpval[0].val = alu;
+ tmpval[1].val = pm;
+ tmpval[2].val = fg;
+ ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask | GCForeground, tmpval);
+
+ ValidateGC(&pPix->drawable, fakexa->pGC);
+
+ TRACE_DRAW();
+
+ return TRUE;
+}
+
+/**
+ * Does an fbFill of the rectangle to be drawn.
+ */
+static void
+ephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
+{
+ ScreenPtr pScreen = pPix->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1);
+}
+
+/**
+ * Cleans up the scratch GC created in ephyrPrepareSolid.
+ */
+static void
+ephyrDoneSolid(PixmapPtr pPix)
+{
+ ScreenPtr pScreen = pPix->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ FreeScratchGC(fakexa->pGC);
+
+ ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST);
+}
+
+/**
+ * Sets up a scratch GC for fbCopyArea, and saves other parameters for the
+ * ephyrCopy implementation.
+ */
+static Bool
+ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu,
+ Pixel pm)
+{
+ ScreenPtr pScreen = pDst->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+ ChangeGCVal tmpval[2];
+
+ ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
+ ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
+
+ fakexa->pSrc = pSrc;
+ fakexa->pDst = pDst;
+ fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen);
+
+ tmpval[0].val = alu;
+ tmpval[1].val = pm;
+ ChangeGC (NullClient, fakexa->pGC, GCFunction | GCPlaneMask, tmpval);
+
+ ValidateGC(&pDst->drawable, fakexa->pGC);
+
+ TRACE_DRAW();
+
+ return TRUE;
+}
+
+/**
+ * Does an fbCopyArea to take care of the requested copy.
+ */
+static void
+ephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h)
+{
+ ScreenPtr pScreen = pDst->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC,
+ srcX, srcY, w, h, dstX, dstY);
+}
+
+/**
+ * Cleans up the scratch GC created in ephyrPrepareCopy.
+ */
+static void
+ephyrDoneCopy(PixmapPtr pDst)
+{
+ ScreenPtr pScreen = pDst->drawable.pScreen;
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ FreeScratchGC (fakexa->pGC);
+
+ ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
+ ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
+}
+
+/**
+ * Reports that we can always accelerate the given operation. This may not be
+ * desirable from an EXA testing standpoint -- testing the fallback paths would
+ * be useful, too.
+ */
+static Bool
+ephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ /* Exercise the component alpha helper, so fail on this case like a normal
+ * driver
+ */
+ if (pMaskPicture && pMaskPicture->componentAlpha && op == PictOpOver)
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * Saves off the parameters for ephyrComposite.
+ */
+static Bool
+ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
+ PixmapPtr pDst)
+{
+ KdScreenPriv(pDst->drawable.pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
+ ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
+ if (pMask != NULL)
+ ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK);
+
+ fakexa->op = op;
+ fakexa->pSrcPicture = pSrcPicture;
+ fakexa->pMaskPicture = pMaskPicture;
+ fakexa->pDstPicture = pDstPicture;
+ fakexa->pSrc = pSrc;
+ fakexa->pMask = pMask;
+ fakexa->pDst = pDst;
+
+ TRACE_DRAW();
+
+ return TRUE;
+}
+
+/**
+ * Does an fbComposite to complete the requested drawing operation.
+ */
+static void
+ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int w, int h)
+{
+ KdScreenPriv(pDst->drawable.pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture,
+ fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY,
+ w, h);
+}
+
+static void
+ephyrDoneComposite(PixmapPtr pDst)
+{
+ KdScreenPriv(pDst->drawable.pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ if (fakexa->pMask != NULL)
+ ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK);
+ ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
+ ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
+}
+
+/**
+ * Does fake acceleration of DownloadFromScren using memcpy.
+ */
+static Bool
+ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst,
+ int dst_pitch)
+{
+ KdScreenPriv(pSrc->drawable.pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+ unsigned char *src;
+ int src_pitch, cpp;
+
+ if (pSrc->drawable.bitsPerPixel < 8)
+ return FALSE;
+
+ ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
+
+ cpp = pSrc->drawable.bitsPerPixel / 8;
+ src_pitch = exaGetPixmapPitch(pSrc);
+ src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc);
+ src += y * src_pitch + x * cpp;
+
+ for (; h > 0; h--) {
+ memcpy(dst, src, w * cpp);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+
+ exaMarkSync(pSrc->drawable.pScreen);
+
+ ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC);
+
+ return TRUE;
+}
+
+/**
+ * Does fake acceleration of UploadToScreen using memcpy.
+ */
+static Bool
+ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
+ int src_pitch)
+{
+ KdScreenPriv(pDst->drawable.pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+ unsigned char *dst;
+ int dst_pitch, cpp;
+
+ if (pDst->drawable.bitsPerPixel < 8)
+ return FALSE;
+
+ ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
+
+ cpp = pDst->drawable.bitsPerPixel / 8;
+ dst_pitch = exaGetPixmapPitch(pDst);
+ dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst);
+ dst += y * dst_pitch + x * cpp;
+
+ for (; h > 0; h--) {
+ memcpy(dst, src, w * cpp);
+ dst += dst_pitch;
+ src += src_pitch;
+ }
+
+ exaMarkSync(pDst->drawable.pScreen);
+
+ ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST);
+
+ return TRUE;
+}
+
+static Bool
+ephyrPrepareAccess(PixmapPtr pPix, int index)
+{
+ /* Make sure we don't somehow end up with a pointer that is in framebuffer
+ * and hasn't been readied for us.
+ */
+ assert(pPix->devPrivate.ptr != NULL);
+
+ return TRUE;
+}
+
+/**
+ * In fakexa, we currently only track whether we have synced to the latest
+ * "accelerated" drawing that has happened or not. It's not used for anything
+ * yet.
+ */
+static int
+ephyrMarkSync(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ fakexa->is_synced = FALSE;
+
+ return 0;
+}
+
+/**
+ * Assumes that we're waiting on the latest marker. When EXA gets smarter and
+ * starts using markers in a fine-grained way (for example, waiting on drawing
+ * to required pixmaps to complete, rather than waiting for all drawing to
+ * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker
+ * implementation fine-grained as well.
+ */
+static void
+ephyrWaitMarker(ScreenPtr pScreen, int marker)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrFakexaPriv *fakexa = scrpriv->fakexa;
+
+ fakexa->is_synced = TRUE;
+}
+
+/**
+ * This function initializes EXA to use the fake acceleration implementation
+ * which just falls through to software. The purpose is to have a reliable,
+ * correct driver with which to test changes to the EXA core.
+ */
+Bool
+ephyrDrawInit(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = screen->driver;
+ EphyrPriv *priv = screen->card->driver;
+ EphyrFakexaPriv *fakexa;
+ Bool success;
+
+ fakexa = calloc(1, sizeof(*fakexa));
+ if (fakexa == NULL)
+ return FALSE;
+
+ fakexa->exa = exaDriverAlloc();
+ if (fakexa->exa == NULL) {
+ free(fakexa);
+ return FALSE;
+ }
+
+ fakexa->exa->memoryBase = (CARD8 *) (priv->base);
+ fakexa->exa->memorySize = priv->bytes_per_line * ephyrBufferHeight(screen);
+ fakexa->exa->offScreenBase = priv->bytes_per_line * screen->height;
+
+ /* Since we statically link against EXA, we shouldn't have to be smart about
+ * versioning.
+ */
+ fakexa->exa->exa_major = 2;
+ fakexa->exa->exa_minor = 0;
+
+ fakexa->exa->PrepareSolid = ephyrPrepareSolid;
+ fakexa->exa->Solid = ephyrSolid;
+ fakexa->exa->DoneSolid = ephyrDoneSolid;
+
+ fakexa->exa->PrepareCopy = ephyrPrepareCopy;
+ fakexa->exa->Copy = ephyrCopy;
+ fakexa->exa->DoneCopy = ephyrDoneCopy;
+
+ fakexa->exa->CheckComposite = ephyrCheckComposite;
+ fakexa->exa->PrepareComposite = ephyrPrepareComposite;
+ fakexa->exa->Composite = ephyrComposite;
+ fakexa->exa->DoneComposite = ephyrDoneComposite;
+
+ fakexa->exa->DownloadFromScreen = ephyrDownloadFromScreen;
+ fakexa->exa->UploadToScreen = ephyrUploadToScreen;
+
+ fakexa->exa->MarkSync = ephyrMarkSync;
+ fakexa->exa->WaitMarker = ephyrWaitMarker;
+
+ fakexa->exa->PrepareAccess = ephyrPrepareAccess;
+
+ fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN;
+ fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN;
+
+ fakexa->exa->maxX = 1023;
+ fakexa->exa->maxY = 1023;
+
+ fakexa->exa->flags = EXA_OFFSCREEN_PIXMAPS;
+
+ success = exaDriverInit(pScreen, fakexa->exa);
+ if (success) {
+ ErrorF("Initialized fake EXA acceleration\n");
+ scrpriv->fakexa = fakexa;
+ } else {
+ ErrorF("Failed to initialize EXA\n");
+ free(fakexa->exa);
+ free(fakexa);
+ }
+
+ return success;
+}
+
+void
+ephyrDrawEnable(ScreenPtr pScreen)
+{
+}
+
+void
+ephyrDrawDisable(ScreenPtr pScreen)
+{
+}
+
+void
+ephyrDrawFini(ScreenPtr pScreen)
+{
+}
+
+/**
+ * exaDDXDriverInit is required by the top-level EXA module, and is used by
+ * the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since
+ * we won't be enabling/disabling the FB.
+ */
+void
+exaDDXDriverInit(ScreenPtr pScreen)
+{
+ ExaScreenPriv(pScreen);
+
+ pExaScr->migration = ExaMigrationSmart;
+ pExaScr->checkDirtyCorrectness = TRUE;
+}
diff --git a/xorg-server/hw/kdrive/ephyr/ephyrinit.c b/xorg-server/hw/kdrive/ephyr/ephyrinit.c
index 2deb7b81d..b674bb8d0 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyrinit.c
+++ b/xorg-server/hw/kdrive/ephyr/ephyrinit.c
@@ -2,7 +2,7 @@
* Xephyr - A kdrive X server thats runs in a host X window.
* Authored by Matthew Allum <mallum@o-hand.com>
*
- * Copyright © 2004 Nokia
+ * Copyright © 2004 Nokia
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -97,6 +97,7 @@ InitInput (int argc, char **argv)
void
CloseInput (void)
{
+ KdCloseInput();
}
#ifdef DDXBEFORERESET
diff --git a/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c
index 648368124..4caf4516d 100644
--- a/xorg-server/hw/kdrive/ephyr/hostx.c
+++ b/xorg-server/hw/kdrive/ephyr/hostx.c
@@ -1,1447 +1,1447 @@
-/*
- * Xephyr - A kdrive X server thats runs in a host X window.
- * Authored by Matthew Allum <mallum@o-hand.com>
- *
- * Copyright © 2004 Nokia
- *
- * 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 Nokia not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Nokia makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-
-/*
- * including some server headers (like kdrive-config.h)
- * might define the macro _XSERVER64
- * on 64 bits machines. That macro must _NOT_ be defined for Xlib
- * client code, otherwise bad things happen.
- * So let's undef that macro if necessary.
- */
-#ifdef _XSERVER64
-#undef _XSERVER64
-#endif
-
-
-#include "hostx.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h> /* for memset */
-#include <time.h>
-
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/time.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/extensions/XShm.h>
-#include <X11/extensions/shape.h>
-#ifdef XF86DRI
-#include <GL/glx.h>
-#endif /* XF86DRI */
-#include "ephyrlog.h"
-
-#ifdef XF86DRI
-extern Bool XF86DRIQueryExtension (Display *dpy,
- int *event_basep,
- int *error_basep);
-#endif
-
-/*
- * All xlib calls go here, which gets built as its own .a .
- * Mixing kdrive and xlib headers causes all sorts of types
- * to get clobbered.
- */
-
-struct EphyrHostScreen
-{
- Window win;
- Window win_pre_existing; /* Set via -parent option like xnest */
- Window peer_win; /* Used for GL; should be at most one */
- XImage *ximg;
- int win_width, win_height;
- int server_depth;
- unsigned char *fb_data; /* only used when host bpp != server bpp */
- XShmSegmentInfo shminfo;
-
- void *info; /* Pointer to the screen this is associated with */
- int mynum; /* Screen number */
-};
-
-struct EphyrHostXVars
-{
- char *server_dpy_name;
- Display *dpy;
- int screen;
- Visual *visual;
- Window winroot;
- GC gc;
- int depth;
- Bool use_host_cursor;
- Bool use_fullscreen;
- Bool have_shm;
-
- int n_screens;
- struct EphyrHostScreen *screens;
-
- long damage_debug_msec;
-
- unsigned long cmap[256];
-};
-
-/* memset ( missing> ) instead of below */
-/*static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};*/
-static EphyrHostXVars HostX;
-
-static int HostXWantDamageDebug = 0;
-
-extern EphyrKeySyms ephyrKeySyms;
-
-extern int monitorResolution;
-
-char *ephyrResName = NULL;
-int ephyrResNameFromCmd = 0;
-char *ephyrTitle = NULL;
-
-static void
-hostx_set_fullscreen_hint(void);
-
-/* X Error traps */
-
-static int trapped_error_code = 0;
-static int (*old_error_handler) (Display *d, XErrorEvent *e);
-
-#define host_depth_matches_server(_vars) (HostX.depth == (_vars)->server_depth)
-
-static struct EphyrHostScreen *
-host_screen_from_screen_info (EphyrScreenInfo *screen)
-{
- int i;
-
- for (i = 0 ; i < HostX.n_screens ; i++)
- {
- if ( HostX.screens[i].info == screen)
- {
- return &HostX.screens[i];
- }
- }
- return NULL;
-}
-
-static int
-error_handler(Display *display,
- XErrorEvent *error)
-{
- trapped_error_code = error->error_code;
- return 0;
-}
-
-static void
-hostx_errors_trap(void)
-{
- trapped_error_code = 0;
- old_error_handler = XSetErrorHandler(error_handler);
-}
-
-static int
-hostx_errors_untrap(void)
-{
- XSetErrorHandler(old_error_handler);
- return trapped_error_code;
-}
-
-int
-hostx_want_screen_size (EphyrScreenInfo screen, int *width, int *height )
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (host_screen &&
- (host_screen->win_pre_existing != None ||
- HostX.use_fullscreen == True))
- {
- *width = host_screen->win_width;
- *height = host_screen->win_height;
- return 1;
- }
-
- return 0;
-}
-
-void
-hostx_add_screen (EphyrScreenInfo screen,
- unsigned long win_id,
- int screen_num)
-{
- int index = HostX.n_screens;
-
- HostX.n_screens += 1;
- HostX.screens = realloc (HostX.screens,
- HostX.n_screens * sizeof(struct EphyrHostScreen));
- memset (&HostX.screens[index], 0, sizeof (struct EphyrHostScreen));
-
- HostX.screens[index].info = screen;
- HostX.screens[index].win_pre_existing = win_id;
-}
-
-
-void
-hostx_set_display_name (char *name)
-{
- HostX.server_dpy_name = strdup (name);
-}
-
-void
-hostx_set_screen_number(EphyrScreenInfo screen, int number)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
- if (host_screen) {
- host_screen->mynum = number;
- hostx_set_win_title (host_screen->info, "") ;
- }}
-
-void
-hostx_set_win_title (EphyrScreenInfo screen, char *extra_text)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (!host_screen)
- return;
-
- if (ephyrTitle) {
- XStoreName(HostX.dpy, host_screen->win, ephyrTitle);
- } else {
-#define BUF_LEN 256
- char buf[BUF_LEN+1];
-
- memset (buf, 0, BUF_LEN+1) ;
- snprintf (buf, BUF_LEN, "Xephyr on %s.%d %s",
- HostX.server_dpy_name,
- host_screen->mynum,
- (extra_text != NULL) ? extra_text : "");
-
- XStoreName (HostX.dpy, host_screen->win, buf);
- }
-}
-
-int
-hostx_want_host_cursor (void)
-{
- return HostX.use_host_cursor;
-}
-
-void
-hostx_use_host_cursor (void)
-{
- HostX.use_host_cursor = True;
-}
-
-int
-hostx_want_preexisting_window (EphyrScreenInfo screen)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (host_screen && host_screen->win_pre_existing)
- {
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-void
-hostx_use_fullscreen (void)
-{
- HostX.use_fullscreen = True;
-}
-
-int
-hostx_want_fullscreen (void)
-{
- return HostX.use_fullscreen;
-}
-
-static void
-hostx_set_fullscreen_hint (void)
-{
- Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN;
- int index;
-
- atom_WINDOW_STATE
- = XInternAtom(HostX.dpy, "_NET_WM_STATE", False);
- atom_WINDOW_STATE_FULLSCREEN
- = XInternAtom(HostX.dpy, "_NET_WM_STATE_FULLSCREEN",False);
-
- for (index = 0 ; index < HostX.n_screens ; index++)
- {
- XChangeProperty (HostX.dpy, HostX.screens[index].win,
- atom_WINDOW_STATE, XA_ATOM, 32,
- PropModeReplace,
- (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
- }
-}
-
-
-static void
-hostx_toggle_damage_debug (void)
-{
- HostXWantDamageDebug ^= 1;
-}
-
-void
-hostx_handle_signal (int signum)
-{
- hostx_toggle_damage_debug();
- EPHYR_DBG ("Signal caught. Damage Debug:%i\n",
- HostXWantDamageDebug);
-}
-
-void
-hostx_use_resname (char *name, int fromcmd)
-{
- ephyrResName = name;
- ephyrResNameFromCmd = fromcmd;
-}
-
-void
-hostx_set_title (char *title)
-{
- ephyrTitle = title;
-}
-
-int
-hostx_init (void)
-{
- XSetWindowAttributes attr;
- Cursor empty_cursor;
- Pixmap cursor_pxm;
- XColor col;
- int index;
- char *tmpstr;
- XClassHint *class_hint;
-
- attr.event_mask =
- ButtonPressMask
- |ButtonReleaseMask
- |PointerMotionMask
- |KeyPressMask
- |KeyReleaseMask
- |ExposureMask;
-
- EPHYR_DBG("mark");
-
- if ((HostX.dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
- {
- fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
- exit(1);
- }
-
- HostX.screen = DefaultScreen(HostX.dpy);
- HostX.winroot = RootWindow(HostX.dpy, HostX.screen);
- HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL);
- HostX.depth = DefaultDepth(HostX.dpy, HostX.screen);
- HostX.visual = DefaultVisual(HostX.dpy, HostX.screen);
-
- class_hint = XAllocClassHint();
-
- for (index = 0 ; index < HostX.n_screens ; index++)
- {
- struct EphyrHostScreen *host_screen = &HostX.screens[index];
-
- host_screen->server_depth = HostX.depth;
- if (host_screen->win_pre_existing != None)
- {
- Status result;
- XWindowAttributes prewin_attr;
-
- /* Get screen size from existing window */
-
- hostx_errors_trap();
-
- result = XGetWindowAttributes (HostX.dpy,
- host_screen->win_pre_existing,
- &prewin_attr);
-
-
- if (hostx_errors_untrap() || !result)
- {
- fprintf (stderr, "\nXephyr -parent window' does not exist!\n");
- exit (1);
- }
-
- host_screen->win_width = prewin_attr.width;
- host_screen->win_height = prewin_attr.height;
-
- host_screen->win = XCreateWindow (HostX.dpy,
- host_screen->win_pre_existing,
- 0,0,
- host_screen->win_width,
- host_screen->win_height,
- 0,
- CopyFromParent,
- CopyFromParent,
- CopyFromParent,
- CWEventMask,
- &attr);
- }
- else
- {
- host_screen->win = XCreateWindow (HostX.dpy,
- HostX.winroot,
- 0,0,100,100, /* will resize */
- 0,
- CopyFromParent,
- CopyFromParent,
- CopyFromParent,
- CWEventMask,
- &attr);
-
- hostx_set_win_title (host_screen->info,
- "(ctrl+shift grabs mouse and keyboard)");
-
- if (HostX.use_fullscreen)
- {
- host_screen->win_width = DisplayWidth(HostX.dpy, HostX.screen);
- host_screen->win_height = DisplayHeight(HostX.dpy, HostX.screen);
-
- hostx_set_fullscreen_hint();
- }
-
- if (class_hint)
- {
- tmpstr = getenv("RESOURCE_NAME");
- if (tmpstr && (!ephyrResNameFromCmd))
- ephyrResName = tmpstr;
- class_hint->res_name = ephyrResName;
- class_hint->res_class = "Xephyr";
- XSetClassHint(hostx_get_display(), host_screen->win, class_hint);
-
- }
-
- }
- }
-
- if (class_hint)
- XFree(class_hint);
-
- XParseColor (HostX.dpy, DefaultColormap (HostX.dpy,HostX.screen),
- "red", &col);
- XAllocColor (HostX.dpy, DefaultColormap (HostX.dpy, HostX.screen),
- &col);
- XSetForeground (HostX.dpy, HostX.gc, col.pixel);
-
- if (!hostx_want_host_cursor ())
- {
- /* Ditch the cursor, we provide our 'own' */
- cursor_pxm = XCreatePixmap (HostX.dpy, HostX.winroot, 1, 1, 1);
- memset (&col, 0, sizeof (col));
- empty_cursor = XCreatePixmapCursor (HostX.dpy,
- cursor_pxm, cursor_pxm,
- &col, &col, 1, 1);
- for ( index = 0 ; index < HostX.n_screens ; index++ )
- {
- XDefineCursor (HostX.dpy,
- HostX.screens[index].win,
- empty_cursor);
- }
- XFreePixmap (HostX.dpy, cursor_pxm);
- }
-
- for (index = 0 ; index < HostX.n_screens ; index++)
- {
- HostX.screens[index].ximg = NULL;
- }
- /* Try to get share memory ximages for a little bit more speed */
-
- if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM"))
- {
- fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
- HostX.have_shm = False;
- }
- else
- {
- /* Really really check we have shm - better way ?*/
- XShmSegmentInfo shminfo;
-
- HostX.have_shm = True;
-
- shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777);
- shminfo.shmaddr=shmat(shminfo.shmid,0,0);
- shminfo.readOnly=True;
-
- hostx_errors_trap();
-
- XShmAttach(HostX.dpy, &shminfo);
- XSync(HostX.dpy, False);
-
- if (hostx_errors_untrap())
- {
- fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
- HostX.have_shm = False;
- }
-
- shmdt(shminfo.shmaddr);
- shmctl(shminfo.shmid, IPC_RMID, 0);
-}
-
- XFlush(HostX.dpy);
-
- /* Setup the pause time between paints when debugging updates */
-
- HostX.damage_debug_msec = 20000; /* 1/50 th of a second */
-
- if (getenv ("XEPHYR_PAUSE"))
- {
- HostX.damage_debug_msec = strtol (getenv ("XEPHYR_PAUSE"), NULL, 0);
- EPHYR_DBG ("pause is %li\n", HostX.damage_debug_msec);
- }
-
- return 1;
-}
-
-int
-hostx_get_depth (void)
-{
- return HostX.depth;
-}
-
-int
-hostx_get_server_depth (EphyrScreenInfo screen)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- return host_screen ? host_screen->server_depth : 0;
-}
-
-void
-hostx_set_server_depth (EphyrScreenInfo screen, int depth)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (host_screen)
- host_screen->server_depth = depth;
-}
-
-int
-hostx_get_bpp (EphyrScreenInfo screen)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (!host_screen)
- return 0;
-
- if (host_depth_matches_server (host_screen))
- return HostX.visual->bits_per_rgb;
- else
- return host_screen->server_depth; /*XXX correct ?*/
-}
-
-void
-hostx_get_visual_masks (EphyrScreenInfo screen,
- CARD32 *rmsk,
- CARD32 *gmsk,
- CARD32 *bmsk)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- if (!host_screen)
- return;
-
- if (host_depth_matches_server(host_screen))
- {
- *rmsk = HostX.visual->red_mask;
- *gmsk = HostX.visual->green_mask;
- *bmsk = HostX.visual->blue_mask;
- }
- else if (host_screen->server_depth == 16)
- {
- /* Assume 16bpp 565 */
- *rmsk = 0xf800;
- *gmsk = 0x07e0;
- *bmsk = 0x001f;
- }
- else
- {
- *rmsk = 0x0;
- *gmsk = 0x0;
- *bmsk = 0x0;
- }
-}
-
-static int
-hostx_calculate_color_shift(unsigned long mask)
-{
- int shift = 1;
- /* count # of bits in mask */
- while ((mask = (mask >> 1))) shift++;
- /* cmap entry is an unsigned char so adjust it by size of that */
- shift = shift - sizeof(unsigned char) * 8;
- if (shift < 0) shift = 0;
- return shift;
-}
-
-void
-hostx_set_cmap_entry(unsigned char idx,
- unsigned char r,
- unsigned char g,
- unsigned char b)
-{
-/* need to calculate the shifts for RGB because server could be BGR. */
-/* XXX Not sure if this is correct for 8 on 16, but this works for 8 on 24.*/
- static int rshift, bshift, gshift = 0;
- static int first_time = 1;
- if (first_time) {
- first_time = 0;
- rshift = hostx_calculate_color_shift(HostX.visual->red_mask);
- gshift = hostx_calculate_color_shift(HostX.visual->green_mask);
- bshift = hostx_calculate_color_shift(HostX.visual->blue_mask);
- }
- HostX.cmap[idx] = ((r << rshift) & HostX.visual->red_mask) |
- ((g << gshift) & HostX.visual->green_mask) |
- ((b << bshift) & HostX.visual->blue_mask);
-}
-
-/**
- * hostx_screen_init creates the XImage that will contain the front buffer of
- * the ephyr screen, and possibly offscreen memory.
- *
- * @param width width of the screen
- * @param height height of the screen
- * @param buffer_height height of the rectangle to be allocated.
- *
- * hostx_screen_init() creates an XImage, using MIT-SHM if it's available.
- * buffer_height can be used to create a larger offscreen buffer, which is used
- * by fakexa for storing offscreen pixmap data.
- */
-void*
-hostx_screen_init (EphyrScreenInfo screen,
- int width, int height,
- int buffer_height)
-{
- int bitmap_pad;
- Bool shm_success = False;
- XSizeHints *size_hints;
-
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
- if (!host_screen)
- {
- fprintf (stderr, "%s: Error in accessing hostx data\n", __func__ );
- exit(1);
- }
-
- EPHYR_DBG ("host_screen=%p wxh=%dx%d, buffer_height=%d",
- host_screen, width, height, buffer_height);
-
- if (host_screen->ximg != NULL)
- {
- /* Free up the image data if previously used
- * i.ie called by server reset
- */
-
- if (HostX.have_shm)
- {
- XShmDetach(HostX.dpy, &host_screen->shminfo);
- XDestroyImage (host_screen->ximg);
- shmdt(host_screen->shminfo.shmaddr);
- shmctl(host_screen->shminfo.shmid, IPC_RMID, 0);
- }
- else
- {
- free(host_screen->ximg->data);
- host_screen->ximg->data = NULL;
-
- XDestroyImage(host_screen->ximg);
- }
- }
-
- if (HostX.have_shm)
- {
- host_screen->ximg = XShmCreateImage (HostX.dpy, HostX.visual, HostX.depth,
- ZPixmap, NULL, &host_screen->shminfo,
- width, buffer_height );
-
- host_screen->shminfo.shmid =
- shmget(IPC_PRIVATE,
- host_screen->ximg->bytes_per_line * buffer_height,
- IPC_CREAT|0777);
- host_screen->ximg->data = shmat(host_screen->shminfo.shmid, 0, 0);
- host_screen->shminfo.shmaddr = host_screen->ximg->data;
-
- if (host_screen->ximg->data == (char *)-1)
- {
- EPHYR_DBG("Can't attach SHM Segment, falling back to plain XImages");
- HostX.have_shm = False;
- XDestroyImage(host_screen->ximg);
- shmctl(host_screen->shminfo.shmid, IPC_RMID, 0);
- }
- else
- {
- EPHYR_DBG("SHM segment attached %p", host_screen->shminfo.shmaddr);
- host_screen->shminfo.readOnly = False;
- XShmAttach(HostX.dpy, &host_screen->shminfo);
- shm_success = True;
- }
- }
-
- if (!shm_success)
- {
- bitmap_pad = ( HostX.depth > 16 )? 32 : (( HostX.depth > 8 )? 16 : 8 );
-
- EPHYR_DBG("Creating image %dx%d for screen host_screen=%p\n",
- width, buffer_height, host_screen );
- host_screen->ximg = XCreateImage (HostX.dpy,
- HostX.visual,
- HostX.depth,
- ZPixmap, 0, 0,
- width,
- buffer_height,
- bitmap_pad,
- 0);
-
- host_screen->ximg->data =
- malloc (host_screen->ximg->bytes_per_line * buffer_height);
- }
-
- XResizeWindow (HostX.dpy, host_screen->win, width, height);
-
- /* Ask the WM to keep our size static */
- size_hints = XAllocSizeHints();
- size_hints->max_width = size_hints->min_width = width;
- size_hints->max_height = size_hints->min_height = height;
- size_hints->flags = PMinSize|PMaxSize;
- XSetWMNormalHints(HostX.dpy, host_screen->win, size_hints);
- XFree(size_hints);
-
- XMapWindow(HostX.dpy, host_screen->win);
-
- XSync(HostX.dpy, False);
-
- host_screen->win_width = width;
- host_screen->win_height = height;
-
- if (host_depth_matches_server(host_screen))
- {
- EPHYR_DBG("Host matches server");
- return host_screen->ximg->data;
- }
- else
- {
- EPHYR_DBG("server bpp %i", host_screen->server_depth>>3);
- host_screen->fb_data = malloc(width*buffer_height*(host_screen->server_depth>>3));
- return host_screen->fb_data;
- }
-}
-
-static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen,
- int x, int y,
- int width, int height);
-
-void
-hostx_paint_rect (EphyrScreenInfo screen,
- int sx, int sy,
- int dx, int dy,
- int width, int height)
-{
- struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
-
- EPHYR_DBG ("painting in screen %d\n", host_screen->mynum) ;
-
- /*
- * Copy the image data updated by the shadow layer
- * on to the window
- */
-
- if (HostXWantDamageDebug)
- {
- hostx_paint_debug_rect(host_screen, dx, dy, width, height);
- }
-
- /*
- * If the depth of the ephyr server is less than that of the host,
- * the kdrive fb does not point to the ximage data but to a buffer
- * ( fb_data ), we shift the various bits from this onto the XImage
- * so they match the host.
- *
- * Note, This code is pretty new ( and simple ) so may break on
- * endian issues, 32 bpp host etc.
- * Not sure if 8bpp case is right either.
- * ... and it will be slower than the matching depth case.
- */
-
- if (!host_depth_matches_server(host_screen))
- {
- int x,y,idx, bytes_per_pixel = (host_screen->server_depth>>3);
- unsigned char r,g,b;
- unsigned long host_pixel;
-
- EPHYR_DBG("Unmatched host depth host_screen=%p\n", host_screen);
- for (y=sy; y<sy+height; y++)
- for (x=sx; x<sx+width; x++)
- {
- idx = (host_screen->win_width*y*bytes_per_pixel)+(x*bytes_per_pixel);
-
- switch (host_screen->server_depth)
- {
- case 16:
- {
- unsigned short pixel = *(unsigned short*)(host_screen->fb_data+idx);
-
- r = ((pixel & 0xf800) >> 8);
- g = ((pixel & 0x07e0) >> 3);
- b = ((pixel & 0x001f) << 3);
-
- host_pixel = (r << 16) | (g << 8) | (b);
-
- XPutPixel(host_screen->ximg, x, y, host_pixel);
- break;
- }
- case 8:
- {
- unsigned char pixel = *(unsigned char*)(host_screen->fb_data+idx);
- XPutPixel(host_screen->ximg, x, y, HostX.cmap[pixel]);
- break;
- }
- default:
- break;
- }
- }
- }
-
- if (HostX.have_shm)
- {
- XShmPutImage (HostX.dpy, host_screen->win,
- HostX.gc, host_screen->ximg,
- sx, sy, dx, dy, width, height, False);
- }
- else
- {
- XPutImage (HostX.dpy, host_screen->win, HostX.gc, host_screen->ximg,
- sx, sy, dx, dy, width, height);
- }
-
- XSync (HostX.dpy, False);
-}
-
-static void
-hostx_paint_debug_rect (struct EphyrHostScreen *host_screen,
- int x, int y,
- int width, int height)
-{
- struct timespec tspec;
-
- tspec.tv_sec = HostX.damage_debug_msec / (1000000);
- tspec.tv_nsec = (HostX.damage_debug_msec % 1000000) * 1000;
-
- EPHYR_DBG("msec: %li tv_sec %li, tv_msec %li",
- HostX.damage_debug_msec, tspec.tv_sec, tspec.tv_nsec);
-
- /* fprintf(stderr, "Xephyr updating: %i+%i %ix%i\n", x, y, width, height); */
-
- XFillRectangle (HostX.dpy, host_screen->win, HostX.gc, x, y, width,height);
- XSync (HostX.dpy, False);
-
- /* nanosleep seems to work better than usleep for me... */
- nanosleep(&tspec, NULL);
-}
-
-void
-hostx_load_keymap(void)
-{
- XID *keymap;
- int host_width, min_keycode, max_keycode, width;
- int i,j;
-
- XDisplayKeycodes (HostX.dpy, &min_keycode, &max_keycode);
-
- EPHYR_DBG ("min: %d, max: %d", min_keycode, max_keycode);
-
- keymap = XGetKeyboardMapping (HostX.dpy,
- min_keycode,
- max_keycode - min_keycode + 1,
- &host_width);
-
- /* Try and copy the hosts keymap into our keymap to avoid loads
- * of messing around.
- *
- * kdrive cannot can have more than 4 keysyms per keycode
- * so we only copy at most the first 4 ( xorg has 6 per keycode, XVNC 2 )
- */
- width = (host_width > 4) ? 4 : host_width;
-
- ephyrKeySyms.map = (CARD32 *)calloc(sizeof(CARD32),
- (max_keycode - min_keycode + 1) *
- width);
- if (!ephyrKeySyms.map)
- return;
-
- for (i=0; i<(max_keycode - min_keycode+1); i++)
- for (j=0; j<width; j++)
- ephyrKeySyms.map[(i*width)+j] = (CARD32) keymap[(i*host_width) + j];
-
- EPHYR_DBG("keymap width, host:%d kdrive:%d", host_width, width);
-
- ephyrKeySyms.minKeyCode = min_keycode;
- ephyrKeySyms.maxKeyCode = max_keycode;
- ephyrKeySyms.mapWidth = width;
-
- XFree(keymap);
-}
-
-static struct EphyrHostScreen *
-host_screen_from_window (Window w)
-{
- int index = 0;
- struct EphyrHostScreen *result = NULL;
-
- for (index = 0 ; index < HostX.n_screens ; index++)
- {
- if (HostX.screens[index].win == w || HostX.screens[index].peer_win == w)
- {
- result = &HostX.screens[index];
- goto out;
- }
- }
-
-out:
- return result;
-}
-
-int
-hostx_get_event(EphyrHostXEvent *ev)
-{
- XEvent xev;
- static int grabbed_screen = -1;
-
- if (XPending(HostX.dpy))
- {
- XNextEvent(HostX.dpy, &xev);
-
- switch (xev.type)
- {
- case Expose:
- /* Not so great event compression, but works ok */
- while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window,
- Expose, &xev));
- {
- struct EphyrHostScreen *host_screen =
- host_screen_from_window (xev.xexpose.window);
- if (host_screen)
- {
- hostx_paint_rect (host_screen->info, 0, 0, 0, 0,
- host_screen->win_width,
- host_screen->win_height);
- }
- else
- {
- EPHYR_LOG_ERROR ("failed to get host screen\n");
- ev->type = EPHYR_EV_EXPOSE;
- ev->data.expose.window = xev.xexpose.window;
- return 1;
- }
- }
- return 0;
-
- case MotionNotify:
- {
- struct EphyrHostScreen *host_screen =
- host_screen_from_window (xev.xmotion.window);
-
- ev->type = EPHYR_EV_MOUSE_MOTION;
- ev->data.mouse_motion.x = xev.xmotion.x;
- ev->data.mouse_motion.y = xev.xmotion.y;
- ev->data.mouse_motion.window = xev.xmotion.window;
- ev->data.mouse_motion.screen = (host_screen ? host_screen->mynum : -1);
- }
- return 1;
-
- case ButtonPress:
- ev->type = EPHYR_EV_MOUSE_PRESS;
- ev->key_state = xev.xkey.state;
- /*
- * This is a bit hacky. will break for button 5 ( defined as 0x10 )
- * Check KD_BUTTON defines in kdrive.h
- */
- ev->data.mouse_down.button_num = 1<<(xev.xbutton.button-1);
- return 1;
-
- case ButtonRelease:
- ev->type = EPHYR_EV_MOUSE_RELEASE;
- ev->key_state = xev.xkey.state;
- ev->data.mouse_up.button_num = 1<<(xev.xbutton.button-1);
- return 1;
-
- case KeyPress:
- {
- ev->type = EPHYR_EV_KEY_PRESS;
- ev->key_state = xev.xkey.state;
- ev->data.key_down.scancode = xev.xkey.keycode;
- return 1;
- }
- case KeyRelease:
-
- if ((XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_L
- || XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_R)
- && (xev.xkey.state & ControlMask))
- {
- struct EphyrHostScreen *host_screen =
- host_screen_from_window (xev.xexpose.window);
-
- if (grabbed_screen != -1)
- {
- XUngrabKeyboard (HostX.dpy, CurrentTime);
- XUngrabPointer (HostX.dpy, CurrentTime);
- grabbed_screen = -1;
- hostx_set_win_title (host_screen->info,
- "(ctrl+shift grabs mouse and keyboard)");
- }
- else
- {
- /* Attempt grab */
- if (XGrabKeyboard (HostX.dpy, host_screen->win, True,
- GrabModeAsync,
- GrabModeAsync,
- CurrentTime) == 0)
- {
- if (XGrabPointer (HostX.dpy, host_screen->win, True,
- NoEventMask,
- GrabModeAsync,
- GrabModeAsync,
- host_screen->win, None, CurrentTime) == 0)
- {
- grabbed_screen = host_screen->mynum;
- hostx_set_win_title
- (host_screen->info,
- "(ctrl+shift releases mouse and keyboard)");
- }
- else /* Failed pointer grabm ungrab keyboard */
- XUngrabKeyboard (HostX.dpy, CurrentTime);
- }
- }
- }
-
- /* Still send the release event even if above has happened
- * server will get confused with just an up event.
- * Maybe it would be better to just block shift+ctrls getting to
- * kdrive all togeather.
- */
- ev->type = EPHYR_EV_KEY_RELEASE;
- ev->key_state = xev.xkey.state;
- ev->data.key_up.scancode = xev.xkey.keycode;
- return 1;
-
- default:
- break;
-
- }
- }
- return 0;
-}
-
-void*
-hostx_get_display(void)
-{
- return HostX.dpy ;
-}
-
-int
-hostx_get_window (int a_screen_number)
-{
- if (a_screen_number < 0 || a_screen_number >= HostX.n_screens) {
- EPHYR_LOG_ERROR ("bad screen number:%d\n", a_screen_number) ;
- return 0;
- }
- return HostX.screens[a_screen_number].win ;
-}
-
-int
-hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attrs)
-{
- XWindowAttributes attrs ;
-
- memset (&attrs, 0, sizeof (attrs)) ;
-
- if (!XGetWindowAttributes (hostx_get_display (),
- a_window,
- &attrs)) {
- return FALSE ;
- }
- a_attrs->x = attrs.x ;
- a_attrs->y = attrs.y ;
- a_attrs->width = attrs.width ;
- a_attrs->height = attrs.height ;
- if (attrs.visual)
- a_attrs->visualid = attrs.visual->visualid ;
- return TRUE ;
-}
-
-int
-hostx_get_extension_info (const char *a_ext_name,
- int *a_major_opcode,
- int *a_first_event,
- int *a_first_error)
-{
- if (!a_ext_name || !a_major_opcode || !a_first_event || !a_first_error)
- return 0 ;
- if (!XQueryExtension (HostX.dpy,
- a_ext_name,
- a_major_opcode,
- a_first_event,
- a_first_error))
- {
- return 0 ;
- }
- return 1 ;
-}
-
-int
-hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals,
- int *a_num_entries)
-{
- Display *dpy=hostx_get_display () ;
- Bool is_ok=False ;
- XVisualInfo templ, *visuals=NULL;
- EphyrHostVisualInfo *host_visuals=NULL ;
- int nb_items=0, i=0;
-
- EPHYR_RETURN_VAL_IF_FAIL (a_visuals && a_num_entries && dpy,
- False) ;
- EPHYR_LOG ("enter\n") ;
- memset (&templ, 0, sizeof (templ)) ;
- visuals = XGetVisualInfo (dpy, VisualNoMask, &templ, &nb_items) ;
- if (!visuals) {
- EPHYR_LOG_ERROR ("host does not advertise any visual\n") ;
- goto out ;
- }
- EPHYR_LOG ("host advertises %d visuals\n", nb_items) ;
- host_visuals = calloc (nb_items, sizeof (EphyrHostVisualInfo)) ;
- for (i=0; i<nb_items; i++) {
- host_visuals[i].visualid = visuals[i].visualid ;
- host_visuals[i].screen = visuals[i].screen ;
- host_visuals[i].depth = visuals[i].depth ;
- host_visuals[i].class = visuals[i].class ;
- host_visuals[i].red_mask = visuals[i].red_mask ;
- host_visuals[i].green_mask = visuals[i].green_mask ;
- host_visuals[i].blue_mask = visuals[i].blue_mask ;
- host_visuals[i].colormap_size = visuals[i].colormap_size ;
- host_visuals[i].bits_per_rgb = visuals[i].bits_per_rgb ;
- }
- *a_visuals = host_visuals ;
- *a_num_entries = nb_items;
- host_visuals=NULL;
-
- is_ok = TRUE;
-out:
- if (visuals) {
- XFree (visuals) ;
- visuals = NULL;
- }
- free(host_visuals);
- host_visuals = NULL;
- EPHYR_LOG ("leave\n") ;
- return is_ok ;
-
-}
-
-int
-hostx_create_window (int a_screen_number,
- EphyrBox *a_geometry,
- int a_visual_id,
- int *a_host_peer /*out parameter*/)
-{
- Bool is_ok=FALSE ;
- Display *dpy=hostx_get_display () ;
- XVisualInfo *visual_info=NULL, visual_info_templ;
- int visual_mask=VisualIDMask ;
- Window win=None ;
- int nb_visuals=0, winmask=0;
- XSetWindowAttributes attrs;
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geometry, FALSE) ;
-
- EPHYR_LOG ("enter\n") ;
-
- /*get visual*/
- memset (&visual_info, 0, sizeof (visual_info)) ;
- visual_info_templ.visualid = a_visual_id ;
- visual_info = XGetVisualInfo (dpy, visual_mask,
- &visual_info_templ,
- &nb_visuals) ;
- if (!visual_info) {
- EPHYR_LOG_ERROR ("argh, could not find a remote visual with id:%d\n",
- a_visual_id) ;
- goto out ;
- }
- memset (&attrs, 0, sizeof (attrs)) ;
- attrs.colormap = XCreateColormap (dpy,
- RootWindow (dpy,
- visual_info->screen),
- visual_info->visual,
- AllocNone) ;
- attrs.event_mask = ButtonPressMask
- |ButtonReleaseMask
- |PointerMotionMask
- |KeyPressMask
- |KeyReleaseMask
- |ExposureMask;
- winmask = CWColormap|CWEventMask;
-
- win = XCreateWindow (dpy, hostx_get_window (a_screen_number),
- a_geometry->x, a_geometry->y,
- a_geometry->width, a_geometry->height, 0,
- visual_info->depth, CopyFromParent,
- visual_info->visual, winmask, &attrs) ;
- if (win == None) {
- EPHYR_LOG_ERROR ("failed to create peer window\n") ;
- goto out ;
- }
- if (HostX.screens[a_screen_number].peer_win == None) {
- HostX.screens[a_screen_number].peer_win = win;
- } else {
- EPHYR_LOG_ERROR ("multiple peer windows created for same screen\n") ;
- }
- XFlush (dpy) ;
- XMapWindow (dpy, win) ;
- *a_host_peer = win ;
- is_ok = TRUE ;
-out:
- EPHYR_LOG ("leave\n") ;
- return is_ok ;
-}
-
-int
-hostx_destroy_window (int a_win)
-{
- Display *dpy=hostx_get_display () ;
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ;
- XDestroyWindow (dpy, a_win) ;
- XFlush (dpy) ;
- return TRUE ;
-}
-
-int
-hostx_set_window_geometry (int a_win, EphyrBox *a_geo)
-{
- Display *dpy=hostx_get_display ();
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geo, FALSE) ;
-
- EPHYR_LOG ("enter. x,y,w,h:(%d,%d,%d,%d)\n",
- a_geo->x, a_geo->y,
- a_geo->width, a_geo->height) ;
-
- XMoveWindow (dpy, a_win, a_geo->x, a_geo->y) ;
- XResizeWindow (dpy, a_win, a_geo->width, a_geo->height) ;
- EPHYR_LOG ("leave\n") ;
- return TRUE;
-}
-
-int
-hostx_set_window_bounding_rectangles (int a_window,
- EphyrRect *a_rects,
- int a_num_rects)
-{
- Bool is_ok=FALSE;
- Display *dpy=hostx_get_display () ;
- int i=0 ;
- XRectangle *rects=NULL ;
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ;
-
- EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ;
-
- rects = calloc (a_num_rects, sizeof (XRectangle)) ;
- for (i=0; i<a_num_rects; i++) {
- rects[i].x = a_rects[i].x1 ;
- rects[i].y = a_rects[i].y1 ;
- rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1);
- rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ;
- EPHYR_LOG ("borders clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
- rects[i].x, rects[i].y,
- rects[i].width, rects[i].height) ;
- }
- /*this aways returns 1*/
- XShapeCombineRectangles (dpy, a_window, ShapeBounding, 0, 0,
- rects, a_num_rects, ShapeSet, YXBanded) ;
- is_ok = TRUE ;
-
- free(rects);
- rects = NULL;
- EPHYR_LOG ("leave\n") ;
- return is_ok;
-}
-
-int
-hostx_set_window_clipping_rectangles (int a_window,
- EphyrRect *a_rects,
- int a_num_rects)
-{
- Bool is_ok=FALSE;
- Display *dpy=hostx_get_display () ;
- int i=0 ;
- XRectangle *rects=NULL ;
-
- EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ;
-
- EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ;
-
- rects = calloc (a_num_rects, sizeof (XRectangle)) ;
- for (i=0; i<a_num_rects; i++) {
- rects[i].x = a_rects[i].x1 ;
- rects[i].y = a_rects[i].y1 ;
- rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1);
- rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ;
- EPHYR_LOG ("clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
- rects[i].x, rects[i].y,
- rects[i].width, rects[i].height) ;
- }
- /*this aways returns 1*/
- XShapeCombineRectangles (dpy, a_window, ShapeClip, 0, 0,
- rects, a_num_rects, ShapeSet, YXBanded) ;
- is_ok = TRUE ;
-
- free(rects);
- rects = NULL;
- EPHYR_LOG ("leave\n") ;
- return is_ok;
-}
-
-int
-hostx_has_xshape (void)
-{
- int event_base=0, error_base=0 ;
- Display *dpy=hostx_get_display () ;
- if (!XShapeQueryExtension (dpy,
- &event_base,
- &error_base)) {
- return FALSE ;
- }
- return TRUE;
-}
-
-#ifdef XF86DRI
-typedef struct {
- int is_valid ;
- int local_id ;
- int remote_id ;
-} ResourcePair ;
-
-#define RESOURCE_PEERS_SIZE 1024*10
-static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ;
-
-
-int
-hostx_allocate_resource_id_peer (int a_local_resource_id,
- int *a_remote_resource_id)
-{
- int i=0 ;
- ResourcePair *peer=NULL ;
- Display *dpy=hostx_get_display ();
-
- /*
- * first make sure a resource peer
- * does not exist already for
- * a_local_resource_id
- */
- for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
- if (resource_peers[i].is_valid
- && resource_peers[i].local_id == a_local_resource_id) {
- peer = &resource_peers[i] ;
- break ;
- }
- }
- /*
- * find one free peer entry, an feed it with
- */
- if (!peer) {
- for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
- if (!resource_peers[i].is_valid) {
- peer = &resource_peers[i] ;
- break ;
- }
- }
- if (peer) {
- peer->remote_id = XAllocID (dpy);
- peer->local_id = a_local_resource_id ;
- peer->is_valid = TRUE ;
- }
- }
- if (peer) {
- *a_remote_resource_id = peer->remote_id ;
- return TRUE ;
- }
- return FALSE ;
-}
-
-int
-hostx_get_resource_id_peer (int a_local_resource_id,
- int *a_remote_resource_id)
-{
- int i=0 ;
- ResourcePair *peer=NULL ;
- for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
- if (resource_peers[i].is_valid
- && resource_peers[i].local_id == a_local_resource_id) {
- peer = &resource_peers[i] ;
- break ;
- }
- }
- if (peer) {
- *a_remote_resource_id = peer->remote_id ;
- return TRUE ;
- }
- return FALSE ;
-}
-
-int
-hostx_has_dri (void)
-{
- int event_base=0, error_base=0 ;
- Display *dpy=hostx_get_display () ;
-
- if (!dpy)
- return FALSE ;
-
- if (!XF86DRIQueryExtension (dpy,
- &event_base,
- &error_base)) {
- return FALSE ;
- }
- return TRUE ;
-}
-
-int
-hostx_has_glx (void)
-{
- Display *dpy=hostx_get_display () ;
- int event_base=0, error_base=0 ;
-
- if (!glXQueryExtension (dpy, &event_base, &error_base)) {
- return FALSE ;
- }
- return TRUE ;
-}
-
-#endif /* XF86DRI */
+/*
+ * Xephyr - A kdrive X server thats runs in a host X window.
+ * Authored by Matthew Allum <mallum@o-hand.com>
+ *
+ * Copyright © 2004 Nokia
+ *
+ * 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 Nokia not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Nokia makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+
+/*
+ * including some server headers (like kdrive-config.h)
+ * might define the macro _XSERVER64
+ * on 64 bits machines. That macro must _NOT_ be defined for Xlib
+ * client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
+
+#include "hostx.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h> /* for memset */
+#include <time.h>
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/time.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/extensions/XShm.h>
+#include <X11/extensions/shape.h>
+#ifdef XF86DRI
+#include <GL/glx.h>
+#endif /* XF86DRI */
+#include "ephyrlog.h"
+
+#ifdef XF86DRI
+extern Bool XF86DRIQueryExtension (Display *dpy,
+ int *event_basep,
+ int *error_basep);
+#endif
+
+/*
+ * All xlib calls go here, which gets built as its own .a .
+ * Mixing kdrive and xlib headers causes all sorts of types
+ * to get clobbered.
+ */
+
+struct EphyrHostScreen
+{
+ Window win;
+ Window win_pre_existing; /* Set via -parent option like xnest */
+ Window peer_win; /* Used for GL; should be at most one */
+ XImage *ximg;
+ int win_width, win_height;
+ int server_depth;
+ unsigned char *fb_data; /* only used when host bpp != server bpp */
+ XShmSegmentInfo shminfo;
+
+ void *info; /* Pointer to the screen this is associated with */
+ int mynum; /* Screen number */
+};
+
+struct EphyrHostXVars
+{
+ char *server_dpy_name;
+ Display *dpy;
+ int screen;
+ Visual *visual;
+ Window winroot;
+ GC gc;
+ int depth;
+ Bool use_host_cursor;
+ Bool use_fullscreen;
+ Bool have_shm;
+
+ int n_screens;
+ struct EphyrHostScreen *screens;
+
+ long damage_debug_msec;
+
+ unsigned long cmap[256];
+};
+
+/* memset ( missing> ) instead of below */
+/*static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};*/
+static EphyrHostXVars HostX;
+
+static int HostXWantDamageDebug = 0;
+
+extern EphyrKeySyms ephyrKeySyms;
+
+extern int monitorResolution;
+
+char *ephyrResName = NULL;
+int ephyrResNameFromCmd = 0;
+char *ephyrTitle = NULL;
+
+static void
+hostx_set_fullscreen_hint(void);
+
+/* X Error traps */
+
+static int trapped_error_code = 0;
+static int (*old_error_handler) (Display *d, XErrorEvent *e);
+
+#define host_depth_matches_server(_vars) (HostX.depth == (_vars)->server_depth)
+
+static struct EphyrHostScreen *
+host_screen_from_screen_info (EphyrScreenInfo *screen)
+{
+ int i;
+
+ for (i = 0 ; i < HostX.n_screens ; i++)
+ {
+ if ( HostX.screens[i].info == screen)
+ {
+ return &HostX.screens[i];
+ }
+ }
+ return NULL;
+}
+
+static int
+error_handler(Display *display,
+ XErrorEvent *error)
+{
+ trapped_error_code = error->error_code;
+ return 0;
+}
+
+static void
+hostx_errors_trap(void)
+{
+ trapped_error_code = 0;
+ old_error_handler = XSetErrorHandler(error_handler);
+}
+
+static int
+hostx_errors_untrap(void)
+{
+ XSetErrorHandler(old_error_handler);
+ return trapped_error_code;
+}
+
+int
+hostx_want_screen_size (EphyrScreenInfo screen, int *width, int *height )
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+ if (host_screen &&
+ (host_screen->win_pre_existing != None ||
+ HostX.use_fullscreen == True))
+ {
+ *width = host_screen->win_width;
+ *height = host_screen->win_height;
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+hostx_add_screen (EphyrScreenInfo screen,
+ unsigned long win_id,
+ int screen_num)
+{
+ int index = HostX.n_screens;
+
+ HostX.n_screens += 1;
+ HostX.screens = realloc (HostX.screens,
+ HostX.n_screens * sizeof(struct EphyrHostScreen));
+ memset (&HostX.screens[index], 0, sizeof (struct EphyrHostScreen));
+
+ HostX.screens[index].info = screen;
+ HostX.screens[index].win_pre_existing = win_id;
+}
+
+
+void
+hostx_set_display_name (char *name)
+{
+ HostX.server_dpy_name = strdup (name);
+}
+
+void
+hostx_set_screen_number(EphyrScreenInfo screen, int number)
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+ if (host_screen) {
+ host_screen->mynum = number;
+ hostx_set_win_title (host_screen->info, "") ;
+ }}
+
+void
+hostx_set_win_title (EphyrScreenInfo screen, char *extra_text)
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+ if (!host_screen)
+ return;
+
+ if (ephyrTitle) {
+ XStoreName(HostX.dpy, host_screen->win, ephyrTitle);
+ } else {
+#define BUF_LEN 256
+ char buf[BUF_LEN+1];
+
+ memset (buf, 0, BUF_LEN+1) ;
+ snprintf (buf, BUF_LEN, "Xephyr on %s.%d %s",
+ HostX.server_dpy_name,
+ host_screen->mynum,
+ (extra_text != NULL) ? extra_text : "");
+
+ XStoreName (HostX.dpy, host_screen->win, buf);
+ }
+}
+
+int
+hostx_want_host_cursor (void)
+{
+ return HostX.use_host_cursor;
+}
+
+void
+hostx_use_host_cursor (void)
+{
+ HostX.use_host_cursor = True;
+}
+
+int
+hostx_want_preexisting_window (EphyrScreenInfo screen)
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+ if (host_screen && host_screen->win_pre_existing)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void
+hostx_use_fullscreen (void)
+{
+ HostX.use_fullscreen = True;
+}
+
+int
+hostx_want_fullscreen (void)
+{
+ return HostX.use_fullscreen;
+}
+
+static void
+hostx_set_fullscreen_hint (void)
+{
+ Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN;
+ int index;
+
+ atom_WINDOW_STATE
+ = XInternAtom(HostX.dpy, "_NET_WM_STATE", False);
+ atom_WINDOW_STATE_FULLSCREEN
+ = XInternAtom(HostX.dpy, "_NET_WM_STATE_FULLSCREEN",False);
+
+ for (index = 0 ; index < HostX.n_screens ; index++)
+ {
+ XChangeProperty (HostX.dpy, HostX.screens[index].win,
+ atom_WINDOW_STATE, XA_ATOM, 32,
+ PropModeReplace,
+ (unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
+ }
+}
+
+
+static void
+hostx_toggle_damage_debug (void)
+{
+ HostXWantDamageDebug ^= 1;
+}
+
+void
+hostx_handle_signal (int signum)
+{
+ hostx_toggle_damage_debug();
+ EPHYR_DBG ("Signal caught. Damage Debug:%i\n",
+ HostXWantDamageDebug);
+}
+
+void
+hostx_use_resname (char *name, int fromcmd)
+{
+ ephyrResName = name;
+ ephyrResNameFromCmd = fromcmd;
+}
+
+void
+hostx_set_title (char *title)
+{
+ ephyrTitle = title;
+}
+
+int
+hostx_init (void)
+{
+ XSetWindowAttributes attr;
+ Cursor empty_cursor;
+ Pixmap cursor_pxm;
+ XColor col;
+ int index;
+ char *tmpstr;
+ XClassHint *class_hint;
+
+ attr.event_mask =
+ ButtonPressMask
+ |ButtonReleaseMask
+ |PointerMotionMask
+ |KeyPressMask
+ |KeyReleaseMask
+ |ExposureMask;
+
+ EPHYR_DBG("mark");
+
+ if ((HostX.dpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
+ {
+ fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
+ exit(1);
+ }
+
+ HostX.screen = DefaultScreen(HostX.dpy);
+ HostX.winroot = RootWindow(HostX.dpy, HostX.screen);
+ HostX.gc = XCreateGC(HostX.dpy, HostX.winroot, 0, NULL);
+ HostX.depth = DefaultDepth(HostX.dpy, HostX.screen);
+ HostX.visual = DefaultVisual(HostX.dpy, HostX.screen);
+
+ class_hint = XAllocClassHint();
+
+ for (index = 0 ; index < HostX.n_screens ; index++)
+ {
+ struct EphyrHostScreen *host_screen = &HostX.screens[index];
+
+ host_screen->server_depth = HostX.depth;
+ if (host_screen->win_pre_existing != None)
+ {
+ Status result;
+ XWindowAttributes prewin_attr;
+
+ /* Get screen size from existing window */
+
+ hostx_errors_trap();
+
+ result = XGetWindowAttributes (HostX.dpy,
+ host_screen->win_pre_existing,
+ &prewin_attr);
+
+
+ if (hostx_errors_untrap() || !result)
+ {
+ fprintf (stderr, "\nXephyr -parent window' does not exist!\n");
+ exit (1);
+ }
+
+ host_screen->win_width = prewin_attr.width;
+ host_screen->win_height = prewin_attr.height;
+
+ host_screen->win = XCreateWindow (HostX.dpy,
+ host_screen->win_pre_existing,
+ 0,0,
+ host_screen->win_width,
+ host_screen->win_height,
+ 0,
+ CopyFromParent,
+ CopyFromParent,
+ CopyFromParent,
+ CWEventMask,
+ &attr);
+ }
+ else
+ {
+ host_screen->win = XCreateWindow (HostX.dpy,
+ HostX.winroot,
+ 0,0,100,100, /* will resize */
+ 0,
+ CopyFromParent,
+ CopyFromParent,
+ CopyFromParent,
+ CWEventMask,
+ &attr);
+
+ hostx_set_win_title (host_screen->info,
+ "(ctrl+shift grabs mouse and keyboard)");
+
+ if (HostX.use_fullscreen)
+ {
+ host_screen->win_width = DisplayWidth(HostX.dpy, HostX.screen);
+ host_screen->win_height = DisplayHeight(HostX.dpy, HostX.screen);
+
+ hostx_set_fullscreen_hint();
+ }
+
+ if (class_hint)
+ {
+ tmpstr = getenv("RESOURCE_NAME");
+ if (tmpstr && (!ephyrResNameFromCmd))
+ ephyrResName = tmpstr;
+ class_hint->res_name = ephyrResName;
+ class_hint->res_class = "Xephyr";
+ XSetClassHint(hostx_get_display(), host_screen->win, class_hint);
+
+ }
+
+ }
+ }
+
+ if (class_hint)
+ XFree(class_hint);
+
+ XParseColor (HostX.dpy, DefaultColormap (HostX.dpy,HostX.screen),
+ "red", &col);
+ XAllocColor (HostX.dpy, DefaultColormap (HostX.dpy, HostX.screen),
+ &col);
+ XSetForeground (HostX.dpy, HostX.gc, col.pixel);
+
+ if (!hostx_want_host_cursor ())
+ {
+ /* Ditch the cursor, we provide our 'own' */
+ cursor_pxm = XCreatePixmap (HostX.dpy, HostX.winroot, 1, 1, 1);
+ memset (&col, 0, sizeof (col));
+ empty_cursor = XCreatePixmapCursor (HostX.dpy,
+ cursor_pxm, cursor_pxm,
+ &col, &col, 1, 1);
+ for ( index = 0 ; index < HostX.n_screens ; index++ )
+ {
+ XDefineCursor (HostX.dpy,
+ HostX.screens[index].win,
+ empty_cursor);
+ }
+ XFreePixmap (HostX.dpy, cursor_pxm);
+ }
+
+ for (index = 0 ; index < HostX.n_screens ; index++)
+ {
+ HostX.screens[index].ximg = NULL;
+ }
+ /* Try to get share memory ximages for a little bit more speed */
+
+ if (!XShmQueryExtension(HostX.dpy) || getenv("XEPHYR_NO_SHM"))
+ {
+ fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
+ HostX.have_shm = False;
+ }
+ else
+ {
+ /* Really really check we have shm - better way ?*/
+ XShmSegmentInfo shminfo;
+
+ HostX.have_shm = True;
+
+ shminfo.shmid=shmget(IPC_PRIVATE, 1, IPC_CREAT|0777);
+ shminfo.shmaddr=shmat(shminfo.shmid,0,0);
+ shminfo.readOnly=True;
+
+ hostx_errors_trap();
+
+ XShmAttach(HostX.dpy, &shminfo);
+ XSync(HostX.dpy, False);
+
+ if (hostx_errors_untrap())
+ {
+ fprintf(stderr, "\nXephyr unable to use SHM XImages\n");
+ HostX.have_shm = False;
+ }
+
+ shmdt(shminfo.shmaddr);
+ shmctl(shminfo.shmid, IPC_RMID, 0);
+}
+
+ XFlush(HostX.dpy);
+
+ /* Setup the pause time between paints when debugging updates */
+
+ HostX.damage_debug_msec = 20000; /* 1/50 th of a second */
+
+ if (getenv ("XEPHYR_PAUSE"))
+ {
+ HostX.damage_debug_msec = strtol (getenv ("XEPHYR_PAUSE"), NULL, 0);
+ EPHYR_DBG ("pause is %li\n", HostX.damage_debug_msec);
+ }
+
+ return 1;
+}
+
+int
+hostx_get_depth (void)
+{
+ return HostX.depth;
+}
+
+int
+hostx_get_server_depth (EphyrScreenInfo screen)
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+ return host_screen ? host_screen->server_depth : 0;
+}
+
+void
+hostx_set_server_depth (EphyrScreenInfo screen, int depth)
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+ if (host_screen)
+ host_screen->server_depth = depth;
+}
+
+int
+hostx_get_bpp (EphyrScreenInfo screen)
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+ if (!host_screen)
+ return 0;
+
+ if (host_depth_matches_server (host_screen))
+ return HostX.visual->bits_per_rgb;
+ else
+ return host_screen->server_depth; /*XXX correct ?*/
+}
+
+void
+hostx_get_visual_masks (EphyrScreenInfo screen,
+ CARD32 *rmsk,
+ CARD32 *gmsk,
+ CARD32 *bmsk)
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+ if (!host_screen)
+ return;
+
+ if (host_depth_matches_server(host_screen))
+ {
+ *rmsk = HostX.visual->red_mask;
+ *gmsk = HostX.visual->green_mask;
+ *bmsk = HostX.visual->blue_mask;
+ }
+ else if (host_screen->server_depth == 16)
+ {
+ /* Assume 16bpp 565 */
+ *rmsk = 0xf800;
+ *gmsk = 0x07e0;
+ *bmsk = 0x001f;
+ }
+ else
+ {
+ *rmsk = 0x0;
+ *gmsk = 0x0;
+ *bmsk = 0x0;
+ }
+}
+
+static int
+hostx_calculate_color_shift(unsigned long mask)
+{
+ int shift = 1;
+ /* count # of bits in mask */
+ while ((mask = (mask >> 1))) shift++;
+ /* cmap entry is an unsigned char so adjust it by size of that */
+ shift = shift - sizeof(unsigned char) * 8;
+ if (shift < 0) shift = 0;
+ return shift;
+}
+
+void
+hostx_set_cmap_entry(unsigned char idx,
+ unsigned char r,
+ unsigned char g,
+ unsigned char b)
+{
+/* need to calculate the shifts for RGB because server could be BGR. */
+/* XXX Not sure if this is correct for 8 on 16, but this works for 8 on 24.*/
+ static int rshift, bshift, gshift = 0;
+ static int first_time = 1;
+ if (first_time) {
+ first_time = 0;
+ rshift = hostx_calculate_color_shift(HostX.visual->red_mask);
+ gshift = hostx_calculate_color_shift(HostX.visual->green_mask);
+ bshift = hostx_calculate_color_shift(HostX.visual->blue_mask);
+ }
+ HostX.cmap[idx] = ((r << rshift) & HostX.visual->red_mask) |
+ ((g << gshift) & HostX.visual->green_mask) |
+ ((b << bshift) & HostX.visual->blue_mask);
+}
+
+/**
+ * hostx_screen_init creates the XImage that will contain the front buffer of
+ * the ephyr screen, and possibly offscreen memory.
+ *
+ * @param width width of the screen
+ * @param height height of the screen
+ * @param buffer_height height of the rectangle to be allocated.
+ *
+ * hostx_screen_init() creates an XImage, using MIT-SHM if it's available.
+ * buffer_height can be used to create a larger offscreen buffer, which is used
+ * by fakexa for storing offscreen pixmap data.
+ */
+void*
+hostx_screen_init (EphyrScreenInfo screen,
+ int width, int height,
+ int buffer_height)
+{
+ int bitmap_pad;
+ Bool shm_success = False;
+ XSizeHints *size_hints;
+
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+ if (!host_screen)
+ {
+ fprintf (stderr, "%s: Error in accessing hostx data\n", __func__ );
+ exit(1);
+ }
+
+ EPHYR_DBG ("host_screen=%p wxh=%dx%d, buffer_height=%d",
+ host_screen, width, height, buffer_height);
+
+ if (host_screen->ximg != NULL)
+ {
+ /* Free up the image data if previously used
+ * i.ie called by server reset
+ */
+
+ if (HostX.have_shm)
+ {
+ XShmDetach(HostX.dpy, &host_screen->shminfo);
+ XDestroyImage (host_screen->ximg);
+ shmdt(host_screen->shminfo.shmaddr);
+ shmctl(host_screen->shminfo.shmid, IPC_RMID, 0);
+ }
+ else
+ {
+ free(host_screen->ximg->data);
+ host_screen->ximg->data = NULL;
+
+ XDestroyImage(host_screen->ximg);
+ }
+ }
+
+ if (HostX.have_shm)
+ {
+ host_screen->ximg = XShmCreateImage (HostX.dpy, HostX.visual, HostX.depth,
+ ZPixmap, NULL, &host_screen->shminfo,
+ width, buffer_height );
+
+ host_screen->shminfo.shmid =
+ shmget(IPC_PRIVATE,
+ host_screen->ximg->bytes_per_line * buffer_height,
+ IPC_CREAT|0777);
+ host_screen->ximg->data = shmat(host_screen->shminfo.shmid, 0, 0);
+ host_screen->shminfo.shmaddr = host_screen->ximg->data;
+
+ if (host_screen->ximg->data == (char *)-1)
+ {
+ EPHYR_DBG("Can't attach SHM Segment, falling back to plain XImages");
+ HostX.have_shm = False;
+ XDestroyImage(host_screen->ximg);
+ shmctl(host_screen->shminfo.shmid, IPC_RMID, 0);
+ }
+ else
+ {
+ EPHYR_DBG("SHM segment attached %p", host_screen->shminfo.shmaddr);
+ host_screen->shminfo.readOnly = False;
+ XShmAttach(HostX.dpy, &host_screen->shminfo);
+ shm_success = True;
+ }
+ }
+
+ if (!shm_success)
+ {
+ bitmap_pad = ( HostX.depth > 16 )? 32 : (( HostX.depth > 8 )? 16 : 8 );
+
+ EPHYR_DBG("Creating image %dx%d for screen host_screen=%p\n",
+ width, buffer_height, host_screen );
+ host_screen->ximg = XCreateImage (HostX.dpy,
+ HostX.visual,
+ HostX.depth,
+ ZPixmap, 0, 0,
+ width,
+ buffer_height,
+ bitmap_pad,
+ 0);
+
+ host_screen->ximg->data =
+ malloc (host_screen->ximg->bytes_per_line * buffer_height);
+ }
+
+ XResizeWindow (HostX.dpy, host_screen->win, width, height);
+
+ /* Ask the WM to keep our size static */
+ size_hints = XAllocSizeHints();
+ size_hints->max_width = size_hints->min_width = width;
+ size_hints->max_height = size_hints->min_height = height;
+ size_hints->flags = PMinSize|PMaxSize;
+ XSetWMNormalHints(HostX.dpy, host_screen->win, size_hints);
+ XFree(size_hints);
+
+ XMapWindow(HostX.dpy, host_screen->win);
+
+ XSync(HostX.dpy, False);
+
+ host_screen->win_width = width;
+ host_screen->win_height = height;
+
+ if (host_depth_matches_server(host_screen))
+ {
+ EPHYR_DBG("Host matches server");
+ return host_screen->ximg->data;
+ }
+ else
+ {
+ EPHYR_DBG("server bpp %i", host_screen->server_depth>>3);
+ host_screen->fb_data = malloc(width*buffer_height*(host_screen->server_depth>>3));
+ return host_screen->fb_data;
+ }
+}
+
+static void hostx_paint_debug_rect (struct EphyrHostScreen *host_screen,
+ int x, int y,
+ int width, int height);
+
+void
+hostx_paint_rect (EphyrScreenInfo screen,
+ int sx, int sy,
+ int dx, int dy,
+ int width, int height)
+{
+ struct EphyrHostScreen *host_screen = host_screen_from_screen_info (screen);
+
+ EPHYR_DBG ("painting in screen %d\n", host_screen->mynum) ;
+
+ /*
+ * Copy the image data updated by the shadow layer
+ * on to the window
+ */
+
+ if (HostXWantDamageDebug)
+ {
+ hostx_paint_debug_rect(host_screen, dx, dy, width, height);
+ }
+
+ /*
+ * If the depth of the ephyr server is less than that of the host,
+ * the kdrive fb does not point to the ximage data but to a buffer
+ * ( fb_data ), we shift the various bits from this onto the XImage
+ * so they match the host.
+ *
+ * Note, This code is pretty new ( and simple ) so may break on
+ * endian issues, 32 bpp host etc.
+ * Not sure if 8bpp case is right either.
+ * ... and it will be slower than the matching depth case.
+ */
+
+ if (!host_depth_matches_server(host_screen))
+ {
+ int x,y,idx, bytes_per_pixel = (host_screen->server_depth>>3);
+ unsigned char r,g,b;
+ unsigned long host_pixel;
+
+ EPHYR_DBG("Unmatched host depth host_screen=%p\n", host_screen);
+ for (y=sy; y<sy+height; y++)
+ for (x=sx; x<sx+width; x++)
+ {
+ idx = (host_screen->win_width*y*bytes_per_pixel)+(x*bytes_per_pixel);
+
+ switch (host_screen->server_depth)
+ {
+ case 16:
+ {
+ unsigned short pixel = *(unsigned short*)(host_screen->fb_data+idx);
+
+ r = ((pixel & 0xf800) >> 8);
+ g = ((pixel & 0x07e0) >> 3);
+ b = ((pixel & 0x001f) << 3);
+
+ host_pixel = (r << 16) | (g << 8) | (b);
+
+ XPutPixel(host_screen->ximg, x, y, host_pixel);
+ break;
+ }
+ case 8:
+ {
+ unsigned char pixel = *(unsigned char*)(host_screen->fb_data+idx);
+ XPutPixel(host_screen->ximg, x, y, HostX.cmap[pixel]);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ if (HostX.have_shm)
+ {
+ XShmPutImage (HostX.dpy, host_screen->win,
+ HostX.gc, host_screen->ximg,
+ sx, sy, dx, dy, width, height, False);
+ }
+ else
+ {
+ XPutImage (HostX.dpy, host_screen->win, HostX.gc, host_screen->ximg,
+ sx, sy, dx, dy, width, height);
+ }
+
+ XSync (HostX.dpy, False);
+}
+
+static void
+hostx_paint_debug_rect (struct EphyrHostScreen *host_screen,
+ int x, int y,
+ int width, int height)
+{
+ struct timespec tspec;
+
+ tspec.tv_sec = HostX.damage_debug_msec / (1000000);
+ tspec.tv_nsec = (HostX.damage_debug_msec % 1000000) * 1000;
+
+ EPHYR_DBG("msec: %li tv_sec %li, tv_msec %li",
+ HostX.damage_debug_msec, tspec.tv_sec, tspec.tv_nsec);
+
+ /* fprintf(stderr, "Xephyr updating: %i+%i %ix%i\n", x, y, width, height); */
+
+ XFillRectangle (HostX.dpy, host_screen->win, HostX.gc, x, y, width,height);
+ XSync (HostX.dpy, False);
+
+ /* nanosleep seems to work better than usleep for me... */
+ nanosleep(&tspec, NULL);
+}
+
+void
+hostx_load_keymap(void)
+{
+ XID *keymap;
+ int host_width, min_keycode, max_keycode, width;
+ int i,j;
+
+ XDisplayKeycodes (HostX.dpy, &min_keycode, &max_keycode);
+
+ EPHYR_DBG ("min: %d, max: %d", min_keycode, max_keycode);
+
+ keymap = XGetKeyboardMapping (HostX.dpy,
+ min_keycode,
+ max_keycode - min_keycode + 1,
+ &host_width);
+
+ /* Try and copy the hosts keymap into our keymap to avoid loads
+ * of messing around.
+ *
+ * kdrive cannot can have more than 4 keysyms per keycode
+ * so we only copy at most the first 4 ( xorg has 6 per keycode, XVNC 2 )
+ */
+ width = (host_width > 4) ? 4 : host_width;
+
+ ephyrKeySyms.map = (CARD32 *)calloc(sizeof(CARD32),
+ (max_keycode - min_keycode + 1) *
+ width);
+ if (!ephyrKeySyms.map)
+ return;
+
+ for (i=0; i<(max_keycode - min_keycode+1); i++)
+ for (j=0; j<width; j++)
+ ephyrKeySyms.map[(i*width)+j] = (CARD32) keymap[(i*host_width) + j];
+
+ EPHYR_DBG("keymap width, host:%d kdrive:%d", host_width, width);
+
+ ephyrKeySyms.minKeyCode = min_keycode;
+ ephyrKeySyms.maxKeyCode = max_keycode;
+ ephyrKeySyms.mapWidth = width;
+
+ XFree(keymap);
+}
+
+static struct EphyrHostScreen *
+host_screen_from_window (Window w)
+{
+ int index = 0;
+ struct EphyrHostScreen *result = NULL;
+
+ for (index = 0 ; index < HostX.n_screens ; index++)
+ {
+ if (HostX.screens[index].win == w || HostX.screens[index].peer_win == w)
+ {
+ result = &HostX.screens[index];
+ goto out;
+ }
+ }
+
+out:
+ return result;
+}
+
+int
+hostx_get_event(EphyrHostXEvent *ev)
+{
+ XEvent xev;
+ static int grabbed_screen = -1;
+
+ if (XPending(HostX.dpy))
+ {
+ XNextEvent(HostX.dpy, &xev);
+
+ switch (xev.type)
+ {
+ case Expose:
+ /* Not so great event compression, but works ok */
+ while (XCheckTypedWindowEvent(HostX.dpy, xev.xexpose.window,
+ Expose, &xev));
+ {
+ struct EphyrHostScreen *host_screen =
+ host_screen_from_window (xev.xexpose.window);
+ if (host_screen)
+ {
+ hostx_paint_rect (host_screen->info, 0, 0, 0, 0,
+ host_screen->win_width,
+ host_screen->win_height);
+ }
+ else
+ {
+ EPHYR_LOG_ERROR ("failed to get host screen\n");
+ ev->type = EPHYR_EV_EXPOSE;
+ ev->data.expose.window = xev.xexpose.window;
+ return 1;
+ }
+ }
+ return 0;
+
+ case MotionNotify:
+ {
+ struct EphyrHostScreen *host_screen =
+ host_screen_from_window (xev.xmotion.window);
+
+ ev->type = EPHYR_EV_MOUSE_MOTION;
+ ev->data.mouse_motion.x = xev.xmotion.x;
+ ev->data.mouse_motion.y = xev.xmotion.y;
+ ev->data.mouse_motion.window = xev.xmotion.window;
+ ev->data.mouse_motion.screen = (host_screen ? host_screen->mynum : -1);
+ }
+ return 1;
+
+ case ButtonPress:
+ ev->type = EPHYR_EV_MOUSE_PRESS;
+ ev->key_state = xev.xkey.state;
+ /*
+ * This is a bit hacky. will break for button 5 ( defined as 0x10 )
+ * Check KD_BUTTON defines in kdrive.h
+ */
+ ev->data.mouse_down.button_num = 1<<(xev.xbutton.button-1);
+ return 1;
+
+ case ButtonRelease:
+ ev->type = EPHYR_EV_MOUSE_RELEASE;
+ ev->key_state = xev.xkey.state;
+ ev->data.mouse_up.button_num = 1<<(xev.xbutton.button-1);
+ return 1;
+
+ case KeyPress:
+ {
+ ev->type = EPHYR_EV_KEY_PRESS;
+ ev->key_state = xev.xkey.state;
+ ev->data.key_down.scancode = xev.xkey.keycode;
+ return 1;
+ }
+ case KeyRelease:
+
+ if ((XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_L
+ || XKeycodeToKeysym(HostX.dpy,xev.xkey.keycode,0) == XK_Shift_R)
+ && (xev.xkey.state & ControlMask))
+ {
+ struct EphyrHostScreen *host_screen =
+ host_screen_from_window (xev.xexpose.window);
+
+ if (grabbed_screen != -1)
+ {
+ XUngrabKeyboard (HostX.dpy, CurrentTime);
+ XUngrabPointer (HostX.dpy, CurrentTime);
+ grabbed_screen = -1;
+ hostx_set_win_title (host_screen->info,
+ "(ctrl+shift grabs mouse and keyboard)");
+ }
+ else
+ {
+ /* Attempt grab */
+ if (XGrabKeyboard (HostX.dpy, host_screen->win, True,
+ GrabModeAsync,
+ GrabModeAsync,
+ CurrentTime) == 0)
+ {
+ if (XGrabPointer (HostX.dpy, host_screen->win, True,
+ NoEventMask,
+ GrabModeAsync,
+ GrabModeAsync,
+ host_screen->win, None, CurrentTime) == 0)
+ {
+ grabbed_screen = host_screen->mynum;
+ hostx_set_win_title
+ (host_screen->info,
+ "(ctrl+shift releases mouse and keyboard)");
+ }
+ else /* Failed pointer grabm ungrab keyboard */
+ XUngrabKeyboard (HostX.dpy, CurrentTime);
+ }
+ }
+ }
+
+ /* Still send the release event even if above has happened
+ * server will get confused with just an up event.
+ * Maybe it would be better to just block shift+ctrls getting to
+ * kdrive all togeather.
+ */
+ ev->type = EPHYR_EV_KEY_RELEASE;
+ ev->key_state = xev.xkey.state;
+ ev->data.key_up.scancode = xev.xkey.keycode;
+ return 1;
+
+ default:
+ break;
+
+ }
+ }
+ return 0;
+}
+
+void*
+hostx_get_display(void)
+{
+ return HostX.dpy ;
+}
+
+int
+hostx_get_window (int a_screen_number)
+{
+ if (a_screen_number < 0 || a_screen_number >= HostX.n_screens) {
+ EPHYR_LOG_ERROR ("bad screen number:%d\n", a_screen_number) ;
+ return 0;
+ }
+ return HostX.screens[a_screen_number].win ;
+}
+
+int
+hostx_get_window_attributes (int a_window, EphyrHostWindowAttributes *a_attrs)
+{
+ XWindowAttributes attrs ;
+
+ memset (&attrs, 0, sizeof (attrs)) ;
+
+ if (!XGetWindowAttributes (hostx_get_display (),
+ a_window,
+ &attrs)) {
+ return FALSE ;
+ }
+ a_attrs->x = attrs.x ;
+ a_attrs->y = attrs.y ;
+ a_attrs->width = attrs.width ;
+ a_attrs->height = attrs.height ;
+ if (attrs.visual)
+ a_attrs->visualid = attrs.visual->visualid ;
+ return TRUE ;
+}
+
+int
+hostx_get_extension_info (const char *a_ext_name,
+ int *a_major_opcode,
+ int *a_first_event,
+ int *a_first_error)
+{
+ if (!a_ext_name || !a_major_opcode || !a_first_event || !a_first_error)
+ return 0 ;
+ if (!XQueryExtension (HostX.dpy,
+ a_ext_name,
+ a_major_opcode,
+ a_first_event,
+ a_first_error))
+ {
+ return 0 ;
+ }
+ return 1 ;
+}
+
+int
+hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals,
+ int *a_num_entries)
+{
+ Display *dpy=hostx_get_display () ;
+ Bool is_ok=False ;
+ XVisualInfo templ, *visuals=NULL;
+ EphyrHostVisualInfo *host_visuals=NULL ;
+ int nb_items=0, i=0;
+
+ EPHYR_RETURN_VAL_IF_FAIL (a_visuals && a_num_entries && dpy,
+ False) ;
+ EPHYR_LOG ("enter\n") ;
+ memset (&templ, 0, sizeof (templ)) ;
+ visuals = XGetVisualInfo (dpy, VisualNoMask, &templ, &nb_items) ;
+ if (!visuals) {
+ EPHYR_LOG_ERROR ("host does not advertise any visual\n") ;
+ goto out ;
+ }
+ EPHYR_LOG ("host advertises %d visuals\n", nb_items) ;
+ host_visuals = calloc (nb_items, sizeof (EphyrHostVisualInfo)) ;
+ for (i=0; i<nb_items; i++) {
+ host_visuals[i].visualid = visuals[i].visualid ;
+ host_visuals[i].screen = visuals[i].screen ;
+ host_visuals[i].depth = visuals[i].depth ;
+ host_visuals[i].class = visuals[i].class ;
+ host_visuals[i].red_mask = visuals[i].red_mask ;
+ host_visuals[i].green_mask = visuals[i].green_mask ;
+ host_visuals[i].blue_mask = visuals[i].blue_mask ;
+ host_visuals[i].colormap_size = visuals[i].colormap_size ;
+ host_visuals[i].bits_per_rgb = visuals[i].bits_per_rgb ;
+ }
+ *a_visuals = host_visuals ;
+ *a_num_entries = nb_items;
+ host_visuals=NULL;
+
+ is_ok = TRUE;
+out:
+ if (visuals) {
+ XFree (visuals) ;
+ visuals = NULL;
+ }
+ free(host_visuals);
+ host_visuals = NULL;
+ EPHYR_LOG ("leave\n") ;
+ return is_ok ;
+
+}
+
+int
+hostx_create_window (int a_screen_number,
+ EphyrBox *a_geometry,
+ int a_visual_id,
+ int *a_host_peer /*out parameter*/)
+{
+ Bool is_ok=FALSE ;
+ Display *dpy=hostx_get_display () ;
+ XVisualInfo *visual_info=NULL, visual_info_templ;
+ int visual_mask=VisualIDMask ;
+ Window win=None ;
+ int nb_visuals=0, winmask=0;
+ XSetWindowAttributes attrs;
+
+ EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geometry, FALSE) ;
+
+ EPHYR_LOG ("enter\n") ;
+
+ /*get visual*/
+ memset (&visual_info, 0, sizeof (visual_info)) ;
+ visual_info_templ.visualid = a_visual_id ;
+ visual_info = XGetVisualInfo (dpy, visual_mask,
+ &visual_info_templ,
+ &nb_visuals) ;
+ if (!visual_info) {
+ EPHYR_LOG_ERROR ("argh, could not find a remote visual with id:%d\n",
+ a_visual_id) ;
+ goto out ;
+ }
+ memset (&attrs, 0, sizeof (attrs)) ;
+ attrs.colormap = XCreateColormap (dpy,
+ RootWindow (dpy,
+ visual_info->screen),
+ visual_info->visual,
+ AllocNone) ;
+ attrs.event_mask = ButtonPressMask
+ |ButtonReleaseMask
+ |PointerMotionMask
+ |KeyPressMask
+ |KeyReleaseMask
+ |ExposureMask;
+ winmask = CWColormap|CWEventMask;
+
+ win = XCreateWindow (dpy, hostx_get_window (a_screen_number),
+ a_geometry->x, a_geometry->y,
+ a_geometry->width, a_geometry->height, 0,
+ visual_info->depth, CopyFromParent,
+ visual_info->visual, winmask, &attrs) ;
+ if (win == None) {
+ EPHYR_LOG_ERROR ("failed to create peer window\n") ;
+ goto out ;
+ }
+ if (HostX.screens[a_screen_number].peer_win == None) {
+ HostX.screens[a_screen_number].peer_win = win;
+ } else {
+ EPHYR_LOG_ERROR ("multiple peer windows created for same screen\n") ;
+ }
+ XFlush (dpy) ;
+ XMapWindow (dpy, win) ;
+ *a_host_peer = win ;
+ is_ok = TRUE ;
+out:
+ EPHYR_LOG ("leave\n") ;
+ return is_ok ;
+}
+
+int
+hostx_destroy_window (int a_win)
+{
+ Display *dpy=hostx_get_display () ;
+
+ EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ;
+ XDestroyWindow (dpy, a_win) ;
+ XFlush (dpy) ;
+ return TRUE ;
+}
+
+int
+hostx_set_window_geometry (int a_win, EphyrBox *a_geo)
+{
+ Display *dpy=hostx_get_display ();
+
+ EPHYR_RETURN_VAL_IF_FAIL (dpy && a_geo, FALSE) ;
+
+ EPHYR_LOG ("enter. x,y,w,h:(%d,%d,%d,%d)\n",
+ a_geo->x, a_geo->y,
+ a_geo->width, a_geo->height) ;
+
+ XMoveWindow (dpy, a_win, a_geo->x, a_geo->y) ;
+ XResizeWindow (dpy, a_win, a_geo->width, a_geo->height) ;
+ EPHYR_LOG ("leave\n") ;
+ return TRUE;
+}
+
+int
+hostx_set_window_bounding_rectangles (int a_window,
+ EphyrRect *a_rects,
+ int a_num_rects)
+{
+ Bool is_ok=FALSE;
+ Display *dpy=hostx_get_display () ;
+ int i=0 ;
+ XRectangle *rects=NULL ;
+
+ EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ;
+
+ EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ;
+
+ rects = calloc (a_num_rects, sizeof (XRectangle)) ;
+ for (i=0; i<a_num_rects; i++) {
+ rects[i].x = a_rects[i].x1 ;
+ rects[i].y = a_rects[i].y1 ;
+ rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1);
+ rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ;
+ EPHYR_LOG ("borders clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
+ rects[i].x, rects[i].y,
+ rects[i].width, rects[i].height) ;
+ }
+ /*this aways returns 1*/
+ XShapeCombineRectangles (dpy, a_window, ShapeBounding, 0, 0,
+ rects, a_num_rects, ShapeSet, YXBanded) ;
+ is_ok = TRUE ;
+
+ free(rects);
+ rects = NULL;
+ EPHYR_LOG ("leave\n") ;
+ return is_ok;
+}
+
+int
+hostx_set_window_clipping_rectangles (int a_window,
+ EphyrRect *a_rects,
+ int a_num_rects)
+{
+ Bool is_ok=FALSE;
+ Display *dpy=hostx_get_display () ;
+ int i=0 ;
+ XRectangle *rects=NULL ;
+
+ EPHYR_RETURN_VAL_IF_FAIL (dpy && a_rects, FALSE) ;
+
+ EPHYR_LOG ("enter. num rects:%d\n", a_num_rects) ;
+
+ rects = calloc (a_num_rects, sizeof (XRectangle)) ;
+ for (i=0; i<a_num_rects; i++) {
+ rects[i].x = a_rects[i].x1 ;
+ rects[i].y = a_rects[i].y1 ;
+ rects[i].width = abs (a_rects[i].x2 - a_rects[i].x1);
+ rects[i].height = abs (a_rects[i].y2 - a_rects[i].y1) ;
+ EPHYR_LOG ("clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
+ rects[i].x, rects[i].y,
+ rects[i].width, rects[i].height) ;
+ }
+ /*this aways returns 1*/
+ XShapeCombineRectangles (dpy, a_window, ShapeClip, 0, 0,
+ rects, a_num_rects, ShapeSet, YXBanded) ;
+ is_ok = TRUE ;
+
+ free(rects);
+ rects = NULL;
+ EPHYR_LOG ("leave\n") ;
+ return is_ok;
+}
+
+int
+hostx_has_xshape (void)
+{
+ int event_base=0, error_base=0 ;
+ Display *dpy=hostx_get_display () ;
+ if (!XShapeQueryExtension (dpy,
+ &event_base,
+ &error_base)) {
+ return FALSE ;
+ }
+ return TRUE;
+}
+
+#ifdef XF86DRI
+typedef struct {
+ int is_valid ;
+ int local_id ;
+ int remote_id ;
+} ResourcePair ;
+
+#define RESOURCE_PEERS_SIZE 1024*10
+static ResourcePair resource_peers[RESOURCE_PEERS_SIZE] ;
+
+
+int
+hostx_allocate_resource_id_peer (int a_local_resource_id,
+ int *a_remote_resource_id)
+{
+ int i=0 ;
+ ResourcePair *peer=NULL ;
+ Display *dpy=hostx_get_display ();
+
+ /*
+ * first make sure a resource peer
+ * does not exist already for
+ * a_local_resource_id
+ */
+ for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
+ if (resource_peers[i].is_valid
+ && resource_peers[i].local_id == a_local_resource_id) {
+ peer = &resource_peers[i] ;
+ break ;
+ }
+ }
+ /*
+ * find one free peer entry, an feed it with
+ */
+ if (!peer) {
+ for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
+ if (!resource_peers[i].is_valid) {
+ peer = &resource_peers[i] ;
+ break ;
+ }
+ }
+ if (peer) {
+ peer->remote_id = XAllocID (dpy);
+ peer->local_id = a_local_resource_id ;
+ peer->is_valid = TRUE ;
+ }
+ }
+ if (peer) {
+ *a_remote_resource_id = peer->remote_id ;
+ return TRUE ;
+ }
+ return FALSE ;
+}
+
+int
+hostx_get_resource_id_peer (int a_local_resource_id,
+ int *a_remote_resource_id)
+{
+ int i=0 ;
+ ResourcePair *peer=NULL ;
+ for (i=0; i<RESOURCE_PEERS_SIZE; i++) {
+ if (resource_peers[i].is_valid
+ && resource_peers[i].local_id == a_local_resource_id) {
+ peer = &resource_peers[i] ;
+ break ;
+ }
+ }
+ if (peer) {
+ *a_remote_resource_id = peer->remote_id ;
+ return TRUE ;
+ }
+ return FALSE ;
+}
+
+int
+hostx_has_dri (void)
+{
+ int event_base=0, error_base=0 ;
+ Display *dpy=hostx_get_display () ;
+
+ if (!dpy)
+ return FALSE ;
+
+ if (!XF86DRIQueryExtension (dpy,
+ &event_base,
+ &error_base)) {
+ return FALSE ;
+ }
+ return TRUE ;
+}
+
+int
+hostx_has_glx (void)
+{
+ Display *dpy=hostx_get_display () ;
+ int event_base=0, error_base=0 ;
+
+ if (!glXQueryExtension (dpy, &event_base, &error_base)) {
+ return FALSE ;
+ }
+ return TRUE ;
+}
+
+#endif /* XF86DRI */
diff --git a/xorg-server/hw/kdrive/ephyr/hostx.h b/xorg-server/hw/kdrive/ephyr/hostx.h
index e65e0c9bc..42578576a 100644
--- a/xorg-server/hw/kdrive/ephyr/hostx.h
+++ b/xorg-server/hw/kdrive/ephyr/hostx.h
@@ -2,7 +2,7 @@
* Xephyr - A kdrive X server thats runs in a host X window.
* Authored by Matthew Allum <mallum@o-hand.com>
*
- * Copyright © 2004 Nokia
+ * Copyright © 2004 Nokia
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/kdrive/ephyr/os.c b/xorg-server/hw/kdrive/ephyr/os.c
index 4bf6e8858..e4dc6787d 100644
--- a/xorg-server/hw/kdrive/ephyr/os.c
+++ b/xorg-server/hw/kdrive/ephyr/os.c
@@ -2,7 +2,7 @@
* Xephyr - A kdrive X server thats runs in a host X window.
* Authored by Matthew Allum <mallum@o-hand.com>
*
- * Copyright © 2004 Nokia
+ * Copyright © 2004 Nokia
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/kdrive/fake/fakeinit.c b/xorg-server/hw/kdrive/fake/fakeinit.c
index ba61959ef..e25093fbf 100644
--- a/xorg-server/hw/kdrive/fake/fakeinit.c
+++ b/xorg-server/hw/kdrive/fake/fakeinit.c
@@ -61,6 +61,7 @@ InitInput (int argc, char **argv)
void
CloseInput (void)
{
+ KdCloseInput ();
}
#ifdef DDXBEFORERESET
diff --git a/xorg-server/hw/kdrive/fake/kbd.c b/xorg-server/hw/kdrive/fake/kbd.c
index 51fba044d..769730d64 100644
--- a/xorg-server/hw/kdrive/fake/kbd.c
+++ b/xorg-server/hw/kdrive/fake/kbd.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 1999 Keith Packard
+ * Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/kdrive/fbdev/fbdev.c b/xorg-server/hw/kdrive/fbdev/fbdev.c
index b127ab89b..661e5b491 100644
--- a/xorg-server/hw/kdrive/fbdev/fbdev.c
+++ b/xorg-server/hw/kdrive/fbdev/fbdev.c
@@ -1,826 +1,826 @@
-/*
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "fbdev.h"
-#include <sys/ioctl.h>
-
-#include <errno.h>
-
-extern int KdTsPhyScreen;
-
-char *fbdevDevicePath = NULL;
-
-static Bool
-fbdevInitialize (KdCardInfo *card, FbdevPriv *priv)
-{
- unsigned long off;
-
- if (fbdevDevicePath == NULL)
- fbdevDevicePath = "/dev/fb0";
-
- if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0)
- {
- ErrorF("Error opening framebuffer %s: %s\n",
- fbdevDevicePath, strerror(errno));
- return FALSE;
- }
-
- /* quiet valgrind */
- memset (&priv->fix, '\0', sizeof (priv->fix));
- if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) {
- perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO");
- close (priv->fd);
- return FALSE;
- }
- /* quiet valgrind */
- memset (&priv->var, '\0', sizeof (priv->var));
- if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) {
- perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO");
- close (priv->fd);
- return FALSE;
- }
-
- priv->fb_base = (char *) mmap ((caddr_t) NULL,
- priv->fix.smem_len,
- PROT_READ|PROT_WRITE,
- MAP_SHARED,
- priv->fd, 0);
-
- if (priv->fb_base == (char *)-1)
- {
- perror("ERROR: mmap framebuffer fails!");
- close (priv->fd);
- return FALSE;
- }
- off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize();
- priv->fb = priv->fb_base + off;
- return TRUE;
-}
-
-Bool
-fbdevCardInit (KdCardInfo *card)
-{
- FbdevPriv *priv;
-
- priv = (FbdevPriv *) malloc(sizeof (FbdevPriv));
- if (!priv)
- return FALSE;
-
- if (!fbdevInitialize (card, priv))
- {
- free(priv);
- return FALSE;
- }
- card->driver = priv;
-
- return TRUE;
-}
-
-static Pixel
-fbdevMakeContig (Pixel orig, Pixel others)
-{
- Pixel low;
-
- low = lowbit (orig) >> 1;
- while (low && (others & low) == 0)
- {
- orig |= low;
- low >>= 1;
- }
- return orig;
-}
-
-static Bool
-fbdevModeSupported (KdScreenInfo *screen,
- const KdMonitorTiming *t)
-{
- return TRUE;
-}
-
-static void
-fbdevConvertMonitorTiming (const KdMonitorTiming *t, struct fb_var_screeninfo *var)
-{
- memset (var, 0, sizeof (struct fb_var_screeninfo));
-
- var->xres = t->horizontal;
- var->yres = t->vertical;
- var->xres_virtual = t->horizontal;
- var->yres_virtual = t->vertical;
- var->xoffset = 0;
- var->yoffset = 0;
- var->pixclock = t->clock ? 1000000000 / t->clock : 0;
- var->left_margin = t->hbp;
- var->right_margin = t->hfp;
- var->upper_margin = t->vbp;
- var->lower_margin = t->vfp;
- var->hsync_len = t->hblank - t->hfp - t->hbp;
- var->vsync_len = t->vblank - t->vfp - t->vbp;
-
- var->sync = 0;
- var->vmode = 0;
-
- if (t->hpol == KdSyncPositive)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (t->vpol == KdSyncPositive)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
-}
-
-static Bool
-fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv)
-{
- FbdevPriv *priv = screen->card->driver;
- Pixel allbits;
- int depth;
- Bool gray;
- struct fb_var_screeninfo var;
- const KdMonitorTiming *t;
- int k;
-
- k = ioctl (priv->fd, FBIOGET_VSCREENINFO, &var);
-
- if (!screen->width || !screen->height)
- {
- if (k >= 0)
- {
- screen->width = var.xres;
- screen->height = var.yres;
- }
- else
- {
- screen->width = 1024;
- screen->height = 768;
- }
- screen->rate = 103; /* FIXME: should get proper value from fb driver */
- }
- if (!screen->fb.depth)
- {
- if (k >= 0)
- screen->fb.depth = var.bits_per_pixel;
- else
- screen->fb.depth = 16;
- }
-
- if ((screen->width != var.xres) || (screen->height != var.yres))
- {
- t = KdFindMode (screen, fbdevModeSupported);
- screen->rate = t->rate;
- screen->width = t->horizontal;
- screen->height = t->vertical;
-
- /* Now try setting the mode */
- if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres))
- fbdevConvertMonitorTiming (t, &var);
- }
-
- var.activate = FB_ACTIVATE_NOW;
- var.bits_per_pixel = screen->fb.depth;
- var.nonstd = 0;
- var.grayscale = 0;
-
- k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &var);
-
- if (k < 0)
- {
- fprintf (stderr, "error: %s\n", strerror (errno));
- return FALSE;
- }
-
- /* Re-get the "fixed" parameters since they might have changed */
- k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix);
- if (k < 0)
- perror ("FBIOGET_FSCREENINFO");
-
- /* Now get the new screeninfo */
- ioctl (priv->fd, FBIOGET_VSCREENINFO, &priv->var);
- depth = priv->var.bits_per_pixel;
- gray = priv->var.grayscale;
-
- switch (priv->fix.visual) {
- case FB_VISUAL_PSEUDOCOLOR:
- if (gray)
- {
- screen->fb.visuals = (1 << StaticGray);
- /* could also support GrayScale, but what's the point? */
- }
- else
- {
- screen->fb.visuals = ((1 << StaticGray) |
- (1 << GrayScale) |
- (1 << StaticColor) |
- (1 << PseudoColor) |
- (1 << TrueColor) |
- (1 << DirectColor));
- }
- screen->fb.blueMask = 0x00;
- screen->fb.greenMask = 0x00;
- screen->fb.redMask = 0x00;
- break;
- case FB_VISUAL_STATIC_PSEUDOCOLOR:
- if (gray)
- {
- screen->fb.visuals = (1 << StaticGray);
- }
- else
- {
- screen->fb.visuals = (1 << StaticColor);
- }
- screen->fb.blueMask = 0x00;
- screen->fb.greenMask = 0x00;
- screen->fb.redMask = 0x00;
- break;
- case FB_VISUAL_TRUECOLOR:
- case FB_VISUAL_DIRECTCOLOR:
- screen->fb.visuals = (1 << TrueColor);
-#define Mask(o,l) (((1 << l) - 1) << o)
- screen->fb.redMask = Mask (priv->var.red.offset, priv->var.red.length);
- screen->fb.greenMask = Mask (priv->var.green.offset, priv->var.green.length);
- screen->fb.blueMask = Mask (priv->var.blue.offset, priv->var.blue.length);
-
- /*
- * This is a kludge so that Render will work -- fill in the gaps
- * in the pixel
- */
- screen->fb.redMask = fbdevMakeContig (screen->fb.redMask,
- screen->fb.greenMask|
- screen->fb.blueMask);
-
- screen->fb.greenMask = fbdevMakeContig (screen->fb.greenMask,
- screen->fb.redMask|
- screen->fb.blueMask);
-
- screen->fb.blueMask = fbdevMakeContig (screen->fb.blueMask,
- screen->fb.redMask|
- screen->fb.greenMask);
-
- allbits = screen->fb.redMask | screen->fb.greenMask | screen->fb.blueMask;
- depth = 32;
- while (depth && !(allbits & (1 << (depth - 1))))
- depth--;
- break;
- default:
- return FALSE;
- break;
- }
- screen->fb.depth = depth;
- screen->fb.bitsPerPixel = priv->var.bits_per_pixel;
-
- scrpriv->randr = screen->randr;
-
- return fbdevMapFramebuffer (screen);
-}
-
-Bool
-fbdevScreenInit (KdScreenInfo *screen)
-{
- FbdevScrPriv *scrpriv;
-
- scrpriv = calloc(1, sizeof (FbdevScrPriv));
- if (!scrpriv)
- return FALSE;
- screen->driver = scrpriv;
- if (!fbdevScreenInitialize (screen, scrpriv))
- {
- screen->driver = 0;
- free(scrpriv);
- return FALSE;
- }
- return TRUE;
-}
-
-static void *
-fbdevWindowLinear (ScreenPtr pScreen,
- CARD32 row,
- CARD32 offset,
- int mode,
- CARD32 *size,
- void *closure)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
-
- if (!pScreenPriv->enabled)
- return 0;
- *size = priv->fix.line_length;
- return (CARD8 *) priv->fb + row * priv->fix.line_length + offset;
-}
-
-Bool
-fbdevMapFramebuffer (KdScreenInfo *screen)
-{
- FbdevScrPriv *scrpriv = screen->driver;
- KdPointerMatrix m;
- FbdevPriv *priv = screen->card->driver;
-
- if (scrpriv->randr != RR_Rotate_0)
- scrpriv->shadow = TRUE;
- else
- scrpriv->shadow = FALSE;
-
- KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height);
-
- KdSetPointerMatrix (&m);
-
- screen->width = priv->var.xres;
- screen->height = priv->var.yres;
-
- if (scrpriv->shadow)
- {
- if (!KdShadowFbAlloc (screen,
- scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)))
- return FALSE;
- }
- else
- {
- screen->fb.byteStride = priv->fix.line_length;
- screen->fb.pixelStride = (priv->fix.line_length * 8 /
- priv->var.bits_per_pixel);
- screen->fb.frameBuffer = (CARD8 *) (priv->fb);
- }
-
- return TRUE;
-}
-
-static void
-fbdevSetScreenSizes (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- FbdevScrPriv *scrpriv = screen->driver;
- FbdevPriv *priv = screen->card->driver;
-
- if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180))
- {
- pScreen->width = priv->var.xres;
- pScreen->height = priv->var.yres;
- pScreen->mmWidth = screen->width_mm;
- pScreen->mmHeight = screen->height_mm;
- }
- else
- {
- pScreen->width = priv->var.yres;
- pScreen->height = priv->var.xres;
- pScreen->mmWidth = screen->height_mm;
- pScreen->mmHeight = screen->width_mm;
- }
-}
-
-static Bool
-fbdevUnmapFramebuffer (KdScreenInfo *screen)
-{
- KdShadowFbFree (screen);
- return TRUE;
-}
-
-static Bool
-fbdevSetShadow (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- FbdevScrPriv *scrpriv = screen->driver;
- FbdevPriv *priv = screen->card->driver;
- ShadowUpdateProc update;
- ShadowWindowProc window;
- int useYX = 0;
-
-#ifdef __arm__
- /* Use variant copy routines that always read left to right in the
- shadow framebuffer. Reading vertical strips is exceptionally
- slow on XScale due to cache effects. */
- useYX = 1;
-#endif
-
- window = fbdevWindowLinear;
- update = 0;
- if (scrpriv->randr)
- if (priv->var.bits_per_pixel == 16) {
- switch (scrpriv->randr) {
- case RR_Rotate_90:
- if (useYX)
- update = shadowUpdateRotate16_90YX;
- else
- update = shadowUpdateRotate16_90;
- break;
- case RR_Rotate_180:
- update = shadowUpdateRotate16_180;
- break;
- case RR_Rotate_270:
- if (useYX)
- update = shadowUpdateRotate16_270YX;
- else
- update = shadowUpdateRotate16_270;
- break;
- default:
- update = shadowUpdateRotate16;
- break;
- }
- } else
- update = shadowUpdateRotatePacked;
- else
- update = shadowUpdatePacked;
- return KdShadowSet (pScreen, scrpriv->randr, update, window);
-}
-
-
-#ifdef RANDR
-static Bool
-fbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- FbdevScrPriv *scrpriv = screen->driver;
- RRScreenSizePtr pSize;
- Rotation randr;
- int n;
-
- *rotations = RR_Rotate_All|RR_Reflect_All;
-
- for (n = 0; n < pScreen->numDepths; n++)
- if (pScreen->allowedDepths[n].numVids)
- break;
- if (n == pScreen->numDepths)
- return FALSE;
-
- pSize = RRRegisterSize (pScreen,
- screen->width,
- screen->height,
- screen->width_mm,
- screen->height_mm);
-
- randr = KdSubRotation (scrpriv->randr, screen->randr);
-
- RRSetCurrentConfig (pScreen, randr, 0, pSize);
-
- return TRUE;
-}
-
-static Bool
-fbdevRandRSetConfig (ScreenPtr pScreen,
- Rotation randr,
- int rate,
- RRScreenSizePtr pSize)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
- FbdevScrPriv *scrpriv = screen->driver;
- Bool wasEnabled = pScreenPriv->enabled;
- FbdevScrPriv oldscr;
- int oldwidth;
- int oldheight;
- int oldmmwidth;
- int oldmmheight;
- int newwidth, newheight;
-
- if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
- {
- newwidth = pSize->width;
- newheight = pSize->height;
- }
- else
- {
- newwidth = pSize->height;
- newheight = pSize->width;
- }
-
- if (wasEnabled)
- KdDisableScreen (pScreen);
-
- oldscr = *scrpriv;
-
- oldwidth = screen->width;
- oldheight = screen->height;
- oldmmwidth = pScreen->mmWidth;
- oldmmheight = pScreen->mmHeight;
-
- /*
- * Set new configuration
- */
-
- scrpriv->randr = KdAddRotation (screen->randr, randr);
-
- fbdevUnmapFramebuffer (screen);
-
- if (!fbdevMapFramebuffer (screen))
- goto bail4;
-
- KdShadowUnset (screen->pScreen);
-
- if (!fbdevSetShadow (screen->pScreen))
- goto bail4;
-
- fbdevSetScreenSizes (screen->pScreen);
-
- /*
- * Set frame buffer mapping
- */
- (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
- pScreen->width,
- pScreen->height,
- screen->fb.depth,
- screen->fb.bitsPerPixel,
- screen->fb.byteStride,
- screen->fb.frameBuffer);
-
- /* set the subpixel order */
-
- KdSetSubpixelOrder (pScreen, scrpriv->randr);
- if (wasEnabled)
- KdEnableScreen (pScreen);
-
- return TRUE;
-
-bail4:
- fbdevUnmapFramebuffer (screen);
- *scrpriv = oldscr;
- (void) fbdevMapFramebuffer (screen);
- pScreen->width = oldwidth;
- pScreen->height = oldheight;
- pScreen->mmWidth = oldmmwidth;
- pScreen->mmHeight = oldmmheight;
-
- if (wasEnabled)
- KdEnableScreen (pScreen);
- return FALSE;
-}
-
-static Bool
-fbdevRandRInit (ScreenPtr pScreen)
-{
- rrScrPrivPtr pScrPriv;
-
- if (!RRScreenInit (pScreen))
- return FALSE;
-
- pScrPriv = rrGetScrPriv(pScreen);
- pScrPriv->rrGetInfo = fbdevRandRGetInfo;
- pScrPriv->rrSetConfig = fbdevRandRSetConfig;
- return TRUE;
-}
-#endif
-
-static Bool
-fbdevCreateColormap (ColormapPtr pmap)
-{
- ScreenPtr pScreen = pmap->pScreen;
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- VisualPtr pVisual;
- int i;
- int nent;
- xColorItem *pdefs;
-
- switch (priv->fix.visual) {
- case FB_VISUAL_STATIC_PSEUDOCOLOR:
- pVisual = pmap->pVisual;
- nent = pVisual->ColormapEntries;
- pdefs = malloc(nent * sizeof (xColorItem));
- if (!pdefs)
- return FALSE;
- for (i = 0; i < nent; i++)
- pdefs[i].pixel = i;
- fbdevGetColors (pScreen, nent, pdefs);
- for (i = 0; i < nent; i++)
- {
- pmap->red[i].co.local.red = pdefs[i].red;
- pmap->red[i].co.local.green = pdefs[i].green;
- pmap->red[i].co.local.blue = pdefs[i].blue;
- }
- free(pdefs);
- return TRUE;
- default:
- return fbInitializeColormap (pmap);
- }
-}
-
-Bool
-fbdevInitScreen (ScreenPtr pScreen)
-{
-#ifdef TOUCHSCREEN
- KdTsPhyScreen = pScreen->myNum;
-#endif
-
- pScreen->CreateColormap = fbdevCreateColormap;
- return TRUE;
-}
-
-Bool
-fbdevFinishInitScreen (ScreenPtr pScreen)
-{
- if (!shadowSetup (pScreen))
- return FALSE;
-
-#ifdef RANDR
- if (!fbdevRandRInit (pScreen))
- return FALSE;
-#endif
-
- return TRUE;
-}
-
-
-Bool
-fbdevCreateResources (ScreenPtr pScreen)
-{
- return fbdevSetShadow (pScreen);
-}
-
-void
-fbdevPreserve (KdCardInfo *card)
-{
-}
-
-static int
-fbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx)
-{
- struct fb_cmap cmap;
-
- cmap.start = minidx;
- cmap.len = maxidx - minidx + 1;
- cmap.red = &priv->red[minidx];
- cmap.green = &priv->green[minidx];
- cmap.blue = &priv->blue[minidx];
- cmap.transp = 0;
-
- return ioctl(priv->fd, FBIOPUTCMAP, &cmap);
-}
-
-Bool
-fbdevEnable (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- int k;
-
- priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL;
-
- /* display it on the LCD */
- k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var);
- if (k < 0)
- {
- perror ("FBIOPUT_VSCREENINFO");
- return FALSE;
- }
-
- if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR)
- {
- int i;
-
- for (i = 0;
- i < (1 << priv->var.red.length) ||
- i < (1 << priv->var.green.length) ||
- i < (1 << priv->var.blue.length); i++)
- {
- priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1);
- priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1);
- priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1);
- }
-
- fbdevUpdateFbColormap(priv, 0, i);
- }
- return TRUE;
-}
-
-Bool
-fbdevDPMS (ScreenPtr pScreen, int mode)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- static int oldmode = -1;
-
- if (mode == oldmode)
- return TRUE;
-#ifdef FBIOPUT_POWERMODE
- if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0)
- {
- oldmode = mode;
- return TRUE;
- }
-#endif
-#ifdef FBIOBLANK
- if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0)
- {
- oldmode = mode;
- return TRUE;
- }
-#endif
- return FALSE;
-}
-
-void
-fbdevDisable (ScreenPtr pScreen)
-{
-}
-
-void
-fbdevRestore (KdCardInfo *card)
-{
-}
-
-void
-fbdevScreenFini (KdScreenInfo *screen)
-{
-}
-
-void
-fbdevCardFini (KdCardInfo *card)
-{
- FbdevPriv *priv = card->driver;
-
- munmap (priv->fb_base, priv->fix.smem_len);
- close (priv->fd);
- free(priv);
-}
-
-/*
- * Retrieve actual colormap and return selected n entries in pdefs.
- */
-void
-fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- struct fb_cmap cmap;
- int p;
- int k;
- int min, max;
-
- min = 256;
- max = 0;
- for (k = 0; k < n; k++)
- {
- if (pdefs[k].pixel < min)
- min = pdefs[k].pixel;
- if (pdefs[k].pixel > max)
- max = pdefs[k].pixel;
- }
- cmap.start = min;
- cmap.len = max - min + 1;
- cmap.red = &priv->red[min];
- cmap.green = &priv->green[min];
- cmap.blue = &priv->blue[min];
- cmap.transp = 0;
- k = ioctl (priv->fd, FBIOGETCMAP, &cmap);
- if (k < 0)
- {
- perror ("can't get colormap");
- return;
- }
- while (n--)
- {
- p = pdefs->pixel;
- pdefs->red = priv->red[p];
- pdefs->green = priv->green[p];
- pdefs->blue = priv->blue[p];
- pdefs++;
- }
-}
-
-/*
- * Change colormap by updating n entries described in pdefs.
- */
-void
-fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
-{
- KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
- int p;
- int min, max;
-
- min = 256;
- max = 0;
- while (n--)
- {
- p = pdefs->pixel;
- priv->red[p] = pdefs->red;
- priv->green[p] = pdefs->green;
- priv->blue[p] = pdefs->blue;
- if (p < min)
- min = p;
- if (p > max)
- max = p;
- pdefs++;
- }
-
- fbdevUpdateFbColormap(priv, min, max);
-}
+/*
+ * Copyright © 1999 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include "fbdev.h"
+#include <sys/ioctl.h>
+
+#include <errno.h>
+
+extern int KdTsPhyScreen;
+
+char *fbdevDevicePath = NULL;
+
+static Bool
+fbdevInitialize (KdCardInfo *card, FbdevPriv *priv)
+{
+ unsigned long off;
+
+ if (fbdevDevicePath == NULL)
+ fbdevDevicePath = "/dev/fb0";
+
+ if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0)
+ {
+ ErrorF("Error opening framebuffer %s: %s\n",
+ fbdevDevicePath, strerror(errno));
+ return FALSE;
+ }
+
+ /* quiet valgrind */
+ memset (&priv->fix, '\0', sizeof (priv->fix));
+ if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) {
+ perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO");
+ close (priv->fd);
+ return FALSE;
+ }
+ /* quiet valgrind */
+ memset (&priv->var, '\0', sizeof (priv->var));
+ if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) {
+ perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO");
+ close (priv->fd);
+ return FALSE;
+ }
+
+ priv->fb_base = (char *) mmap ((caddr_t) NULL,
+ priv->fix.smem_len,
+ PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ priv->fd, 0);
+
+ if (priv->fb_base == (char *)-1)
+ {
+ perror("ERROR: mmap framebuffer fails!");
+ close (priv->fd);
+ return FALSE;
+ }
+ off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize();
+ priv->fb = priv->fb_base + off;
+ return TRUE;
+}
+
+Bool
+fbdevCardInit (KdCardInfo *card)
+{
+ FbdevPriv *priv;
+
+ priv = (FbdevPriv *) malloc(sizeof (FbdevPriv));
+ if (!priv)
+ return FALSE;
+
+ if (!fbdevInitialize (card, priv))
+ {
+ free(priv);
+ return FALSE;
+ }
+ card->driver = priv;
+
+ return TRUE;
+}
+
+static Pixel
+fbdevMakeContig (Pixel orig, Pixel others)
+{
+ Pixel low;
+
+ low = lowbit (orig) >> 1;
+ while (low && (others & low) == 0)
+ {
+ orig |= low;
+ low >>= 1;
+ }
+ return orig;
+}
+
+static Bool
+fbdevModeSupported (KdScreenInfo *screen,
+ const KdMonitorTiming *t)
+{
+ return TRUE;
+}
+
+static void
+fbdevConvertMonitorTiming (const KdMonitorTiming *t, struct fb_var_screeninfo *var)
+{
+ memset (var, 0, sizeof (struct fb_var_screeninfo));
+
+ var->xres = t->horizontal;
+ var->yres = t->vertical;
+ var->xres_virtual = t->horizontal;
+ var->yres_virtual = t->vertical;
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->pixclock = t->clock ? 1000000000 / t->clock : 0;
+ var->left_margin = t->hbp;
+ var->right_margin = t->hfp;
+ var->upper_margin = t->vbp;
+ var->lower_margin = t->vfp;
+ var->hsync_len = t->hblank - t->hfp - t->hbp;
+ var->vsync_len = t->vblank - t->vfp - t->vbp;
+
+ var->sync = 0;
+ var->vmode = 0;
+
+ if (t->hpol == KdSyncPositive)
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (t->vpol == KdSyncPositive)
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+}
+
+static Bool
+fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv)
+{
+ FbdevPriv *priv = screen->card->driver;
+ Pixel allbits;
+ int depth;
+ Bool gray;
+ struct fb_var_screeninfo var;
+ const KdMonitorTiming *t;
+ int k;
+
+ k = ioctl (priv->fd, FBIOGET_VSCREENINFO, &var);
+
+ if (!screen->width || !screen->height)
+ {
+ if (k >= 0)
+ {
+ screen->width = var.xres;
+ screen->height = var.yres;
+ }
+ else
+ {
+ screen->width = 1024;
+ screen->height = 768;
+ }
+ screen->rate = 103; /* FIXME: should get proper value from fb driver */
+ }
+ if (!screen->fb.depth)
+ {
+ if (k >= 0)
+ screen->fb.depth = var.bits_per_pixel;
+ else
+ screen->fb.depth = 16;
+ }
+
+ if ((screen->width != var.xres) || (screen->height != var.yres))
+ {
+ t = KdFindMode (screen, fbdevModeSupported);
+ screen->rate = t->rate;
+ screen->width = t->horizontal;
+ screen->height = t->vertical;
+
+ /* Now try setting the mode */
+ if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres))
+ fbdevConvertMonitorTiming (t, &var);
+ }
+
+ var.activate = FB_ACTIVATE_NOW;
+ var.bits_per_pixel = screen->fb.depth;
+ var.nonstd = 0;
+ var.grayscale = 0;
+
+ k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &var);
+
+ if (k < 0)
+ {
+ fprintf (stderr, "error: %s\n", strerror (errno));
+ return FALSE;
+ }
+
+ /* Re-get the "fixed" parameters since they might have changed */
+ k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix);
+ if (k < 0)
+ perror ("FBIOGET_FSCREENINFO");
+
+ /* Now get the new screeninfo */
+ ioctl (priv->fd, FBIOGET_VSCREENINFO, &priv->var);
+ depth = priv->var.bits_per_pixel;
+ gray = priv->var.grayscale;
+
+ switch (priv->fix.visual) {
+ case FB_VISUAL_PSEUDOCOLOR:
+ if (gray)
+ {
+ screen->fb.visuals = (1 << StaticGray);
+ /* could also support GrayScale, but what's the point? */
+ }
+ else
+ {
+ screen->fb.visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ }
+ screen->fb.blueMask = 0x00;
+ screen->fb.greenMask = 0x00;
+ screen->fb.redMask = 0x00;
+ break;
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ if (gray)
+ {
+ screen->fb.visuals = (1 << StaticGray);
+ }
+ else
+ {
+ screen->fb.visuals = (1 << StaticColor);
+ }
+ screen->fb.blueMask = 0x00;
+ screen->fb.greenMask = 0x00;
+ screen->fb.redMask = 0x00;
+ break;
+ case FB_VISUAL_TRUECOLOR:
+ case FB_VISUAL_DIRECTCOLOR:
+ screen->fb.visuals = (1 << TrueColor);
+#define Mask(o,l) (((1 << l) - 1) << o)
+ screen->fb.redMask = Mask (priv->var.red.offset, priv->var.red.length);
+ screen->fb.greenMask = Mask (priv->var.green.offset, priv->var.green.length);
+ screen->fb.blueMask = Mask (priv->var.blue.offset, priv->var.blue.length);
+
+ /*
+ * This is a kludge so that Render will work -- fill in the gaps
+ * in the pixel
+ */
+ screen->fb.redMask = fbdevMakeContig (screen->fb.redMask,
+ screen->fb.greenMask|
+ screen->fb.blueMask);
+
+ screen->fb.greenMask = fbdevMakeContig (screen->fb.greenMask,
+ screen->fb.redMask|
+ screen->fb.blueMask);
+
+ screen->fb.blueMask = fbdevMakeContig (screen->fb.blueMask,
+ screen->fb.redMask|
+ screen->fb.greenMask);
+
+ allbits = screen->fb.redMask | screen->fb.greenMask | screen->fb.blueMask;
+ depth = 32;
+ while (depth && !(allbits & (1 << (depth - 1))))
+ depth--;
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+ screen->fb.depth = depth;
+ screen->fb.bitsPerPixel = priv->var.bits_per_pixel;
+
+ scrpriv->randr = screen->randr;
+
+ return fbdevMapFramebuffer (screen);
+}
+
+Bool
+fbdevScreenInit (KdScreenInfo *screen)
+{
+ FbdevScrPriv *scrpriv;
+
+ scrpriv = calloc(1, sizeof (FbdevScrPriv));
+ if (!scrpriv)
+ return FALSE;
+ screen->driver = scrpriv;
+ if (!fbdevScreenInitialize (screen, scrpriv))
+ {
+ screen->driver = 0;
+ free(scrpriv);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void *
+fbdevWindowLinear (ScreenPtr pScreen,
+ CARD32 row,
+ CARD32 offset,
+ int mode,
+ CARD32 *size,
+ void *closure)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+
+ if (!pScreenPriv->enabled)
+ return 0;
+ *size = priv->fix.line_length;
+ return (CARD8 *) priv->fb + row * priv->fix.line_length + offset;
+}
+
+Bool
+fbdevMapFramebuffer (KdScreenInfo *screen)
+{
+ FbdevScrPriv *scrpriv = screen->driver;
+ KdPointerMatrix m;
+ FbdevPriv *priv = screen->card->driver;
+
+ if (scrpriv->randr != RR_Rotate_0)
+ scrpriv->shadow = TRUE;
+ else
+ scrpriv->shadow = FALSE;
+
+ KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height);
+
+ KdSetPointerMatrix (&m);
+
+ screen->width = priv->var.xres;
+ screen->height = priv->var.yres;
+
+ if (scrpriv->shadow)
+ {
+ if (!KdShadowFbAlloc (screen,
+ scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)))
+ return FALSE;
+ }
+ else
+ {
+ screen->fb.byteStride = priv->fix.line_length;
+ screen->fb.pixelStride = (priv->fix.line_length * 8 /
+ priv->var.bits_per_pixel);
+ screen->fb.frameBuffer = (CARD8 *) (priv->fb);
+ }
+
+ return TRUE;
+}
+
+static void
+fbdevSetScreenSizes (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ FbdevScrPriv *scrpriv = screen->driver;
+ FbdevPriv *priv = screen->card->driver;
+
+ if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180))
+ {
+ pScreen->width = priv->var.xres;
+ pScreen->height = priv->var.yres;
+ pScreen->mmWidth = screen->width_mm;
+ pScreen->mmHeight = screen->height_mm;
+ }
+ else
+ {
+ pScreen->width = priv->var.yres;
+ pScreen->height = priv->var.xres;
+ pScreen->mmWidth = screen->height_mm;
+ pScreen->mmHeight = screen->width_mm;
+ }
+}
+
+static Bool
+fbdevUnmapFramebuffer (KdScreenInfo *screen)
+{
+ KdShadowFbFree (screen);
+ return TRUE;
+}
+
+static Bool
+fbdevSetShadow (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ FbdevScrPriv *scrpriv = screen->driver;
+ FbdevPriv *priv = screen->card->driver;
+ ShadowUpdateProc update;
+ ShadowWindowProc window;
+ int useYX = 0;
+
+#ifdef __arm__
+ /* Use variant copy routines that always read left to right in the
+ shadow framebuffer. Reading vertical strips is exceptionally
+ slow on XScale due to cache effects. */
+ useYX = 1;
+#endif
+
+ window = fbdevWindowLinear;
+ update = 0;
+ if (scrpriv->randr)
+ if (priv->var.bits_per_pixel == 16) {
+ switch (scrpriv->randr) {
+ case RR_Rotate_90:
+ if (useYX)
+ update = shadowUpdateRotate16_90YX;
+ else
+ update = shadowUpdateRotate16_90;
+ break;
+ case RR_Rotate_180:
+ update = shadowUpdateRotate16_180;
+ break;
+ case RR_Rotate_270:
+ if (useYX)
+ update = shadowUpdateRotate16_270YX;
+ else
+ update = shadowUpdateRotate16_270;
+ break;
+ default:
+ update = shadowUpdateRotate16;
+ break;
+ }
+ } else
+ update = shadowUpdateRotatePacked;
+ else
+ update = shadowUpdatePacked;
+ return KdShadowSet (pScreen, scrpriv->randr, update, window);
+}
+
+
+#ifdef RANDR
+static Bool
+fbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ FbdevScrPriv *scrpriv = screen->driver;
+ RRScreenSizePtr pSize;
+ Rotation randr;
+ int n;
+
+ *rotations = RR_Rotate_All|RR_Reflect_All;
+
+ for (n = 0; n < pScreen->numDepths; n++)
+ if (pScreen->allowedDepths[n].numVids)
+ break;
+ if (n == pScreen->numDepths)
+ return FALSE;
+
+ pSize = RRRegisterSize (pScreen,
+ screen->width,
+ screen->height,
+ screen->width_mm,
+ screen->height_mm);
+
+ randr = KdSubRotation (scrpriv->randr, screen->randr);
+
+ RRSetCurrentConfig (pScreen, randr, 0, pSize);
+
+ return TRUE;
+}
+
+static Bool
+fbdevRandRSetConfig (ScreenPtr pScreen,
+ Rotation randr,
+ int rate,
+ RRScreenSizePtr pSize)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ FbdevScrPriv *scrpriv = screen->driver;
+ Bool wasEnabled = pScreenPriv->enabled;
+ FbdevScrPriv oldscr;
+ int oldwidth;
+ int oldheight;
+ int oldmmwidth;
+ int oldmmheight;
+ int newwidth, newheight;
+
+ if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
+ {
+ newwidth = pSize->width;
+ newheight = pSize->height;
+ }
+ else
+ {
+ newwidth = pSize->height;
+ newheight = pSize->width;
+ }
+
+ if (wasEnabled)
+ KdDisableScreen (pScreen);
+
+ oldscr = *scrpriv;
+
+ oldwidth = screen->width;
+ oldheight = screen->height;
+ oldmmwidth = pScreen->mmWidth;
+ oldmmheight = pScreen->mmHeight;
+
+ /*
+ * Set new configuration
+ */
+
+ scrpriv->randr = KdAddRotation (screen->randr, randr);
+
+ fbdevUnmapFramebuffer (screen);
+
+ if (!fbdevMapFramebuffer (screen))
+ goto bail4;
+
+ KdShadowUnset (screen->pScreen);
+
+ if (!fbdevSetShadow (screen->pScreen))
+ goto bail4;
+
+ fbdevSetScreenSizes (screen->pScreen);
+
+ /*
+ * Set frame buffer mapping
+ */
+ (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen),
+ pScreen->width,
+ pScreen->height,
+ screen->fb.depth,
+ screen->fb.bitsPerPixel,
+ screen->fb.byteStride,
+ screen->fb.frameBuffer);
+
+ /* set the subpixel order */
+
+ KdSetSubpixelOrder (pScreen, scrpriv->randr);
+ if (wasEnabled)
+ KdEnableScreen (pScreen);
+
+ return TRUE;
+
+bail4:
+ fbdevUnmapFramebuffer (screen);
+ *scrpriv = oldscr;
+ (void) fbdevMapFramebuffer (screen);
+ pScreen->width = oldwidth;
+ pScreen->height = oldheight;
+ pScreen->mmWidth = oldmmwidth;
+ pScreen->mmHeight = oldmmheight;
+
+ if (wasEnabled)
+ KdEnableScreen (pScreen);
+ return FALSE;
+}
+
+static Bool
+fbdevRandRInit (ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+
+ if (!RRScreenInit (pScreen))
+ return FALSE;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+ pScrPriv->rrGetInfo = fbdevRandRGetInfo;
+ pScrPriv->rrSetConfig = fbdevRandRSetConfig;
+ return TRUE;
+}
+#endif
+
+static Bool
+fbdevCreateColormap (ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ VisualPtr pVisual;
+ int i;
+ int nent;
+ xColorItem *pdefs;
+
+ switch (priv->fix.visual) {
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ pVisual = pmap->pVisual;
+ nent = pVisual->ColormapEntries;
+ pdefs = malloc(nent * sizeof (xColorItem));
+ if (!pdefs)
+ return FALSE;
+ for (i = 0; i < nent; i++)
+ pdefs[i].pixel = i;
+ fbdevGetColors (pScreen, nent, pdefs);
+ for (i = 0; i < nent; i++)
+ {
+ pmap->red[i].co.local.red = pdefs[i].red;
+ pmap->red[i].co.local.green = pdefs[i].green;
+ pmap->red[i].co.local.blue = pdefs[i].blue;
+ }
+ free(pdefs);
+ return TRUE;
+ default:
+ return fbInitializeColormap (pmap);
+ }
+}
+
+Bool
+fbdevInitScreen (ScreenPtr pScreen)
+{
+#ifdef TOUCHSCREEN
+ KdTsPhyScreen = pScreen->myNum;
+#endif
+
+ pScreen->CreateColormap = fbdevCreateColormap;
+ return TRUE;
+}
+
+Bool
+fbdevFinishInitScreen (ScreenPtr pScreen)
+{
+ if (!shadowSetup (pScreen))
+ return FALSE;
+
+#ifdef RANDR
+ if (!fbdevRandRInit (pScreen))
+ return FALSE;
+#endif
+
+ return TRUE;
+}
+
+
+Bool
+fbdevCreateResources (ScreenPtr pScreen)
+{
+ return fbdevSetShadow (pScreen);
+}
+
+void
+fbdevPreserve (KdCardInfo *card)
+{
+}
+
+static int
+fbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx)
+{
+ struct fb_cmap cmap;
+
+ cmap.start = minidx;
+ cmap.len = maxidx - minidx + 1;
+ cmap.red = &priv->red[minidx];
+ cmap.green = &priv->green[minidx];
+ cmap.blue = &priv->blue[minidx];
+ cmap.transp = 0;
+
+ return ioctl(priv->fd, FBIOPUTCMAP, &cmap);
+}
+
+Bool
+fbdevEnable (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ int k;
+
+ priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL;
+
+ /* display it on the LCD */
+ k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var);
+ if (k < 0)
+ {
+ perror ("FBIOPUT_VSCREENINFO");
+ return FALSE;
+ }
+
+ if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR)
+ {
+ int i;
+
+ for (i = 0;
+ i < (1 << priv->var.red.length) ||
+ i < (1 << priv->var.green.length) ||
+ i < (1 << priv->var.blue.length); i++)
+ {
+ priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1);
+ priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1);
+ priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1);
+ }
+
+ fbdevUpdateFbColormap(priv, 0, i);
+ }
+ return TRUE;
+}
+
+Bool
+fbdevDPMS (ScreenPtr pScreen, int mode)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ static int oldmode = -1;
+
+ if (mode == oldmode)
+ return TRUE;
+#ifdef FBIOPUT_POWERMODE
+ if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0)
+ {
+ oldmode = mode;
+ return TRUE;
+ }
+#endif
+#ifdef FBIOBLANK
+ if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0)
+ {
+ oldmode = mode;
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+void
+fbdevDisable (ScreenPtr pScreen)
+{
+}
+
+void
+fbdevRestore (KdCardInfo *card)
+{
+}
+
+void
+fbdevScreenFini (KdScreenInfo *screen)
+{
+}
+
+void
+fbdevCardFini (KdCardInfo *card)
+{
+ FbdevPriv *priv = card->driver;
+
+ munmap (priv->fb_base, priv->fix.smem_len);
+ close (priv->fd);
+ free(priv);
+}
+
+/*
+ * Retrieve actual colormap and return selected n entries in pdefs.
+ */
+void
+fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ struct fb_cmap cmap;
+ int p;
+ int k;
+ int min, max;
+
+ min = 256;
+ max = 0;
+ for (k = 0; k < n; k++)
+ {
+ if (pdefs[k].pixel < min)
+ min = pdefs[k].pixel;
+ if (pdefs[k].pixel > max)
+ max = pdefs[k].pixel;
+ }
+ cmap.start = min;
+ cmap.len = max - min + 1;
+ cmap.red = &priv->red[min];
+ cmap.green = &priv->green[min];
+ cmap.blue = &priv->blue[min];
+ cmap.transp = 0;
+ k = ioctl (priv->fd, FBIOGETCMAP, &cmap);
+ if (k < 0)
+ {
+ perror ("can't get colormap");
+ return;
+ }
+ while (n--)
+ {
+ p = pdefs->pixel;
+ pdefs->red = priv->red[p];
+ pdefs->green = priv->green[p];
+ pdefs->blue = priv->blue[p];
+ pdefs++;
+ }
+}
+
+/*
+ * Change colormap by updating n entries described in pdefs.
+ */
+void
+fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ int p;
+ int min, max;
+
+ min = 256;
+ max = 0;
+ while (n--)
+ {
+ p = pdefs->pixel;
+ priv->red[p] = pdefs->red;
+ priv->green[p] = pdefs->green;
+ priv->blue[p] = pdefs->blue;
+ if (p < min)
+ min = p;
+ if (p > max)
+ max = p;
+ pdefs++;
+ }
+
+ fbdevUpdateFbColormap(priv, min, max);
+}
diff --git a/xorg-server/hw/kdrive/fbdev/fbdev.h b/xorg-server/hw/kdrive/fbdev/fbdev.h
index ebac6ad8b..ec53784af 100644
--- a/xorg-server/hw/kdrive/fbdev/fbdev.h
+++ b/xorg-server/hw/kdrive/fbdev/fbdev.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 1999 Keith Packard
+ * Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/kdrive/fbdev/fbinit.c b/xorg-server/hw/kdrive/fbdev/fbinit.c
index 51e7e00d9..1d66fce32 100644
--- a/xorg-server/hw/kdrive/fbdev/fbinit.c
+++ b/xorg-server/hw/kdrive/fbdev/fbinit.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 1999 Keith Packard
+ * Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -47,6 +47,7 @@ InitInput (int argc, char **argv)
void
CloseInput (void)
{
+ KdCloseInput ();
}
void
diff --git a/xorg-server/hw/kdrive/linux/keyboard.c b/xorg-server/hw/kdrive/linux/keyboard.c
index c888d14dc..f5f9d9b8a 100644
--- a/xorg-server/hw/kdrive/linux/keyboard.c
+++ b/xorg-server/hw/kdrive/linux/keyboard.c
@@ -1,765 +1,765 @@
-/*
- * Copyright © 1999 Keith Packard
- * XKB integration © 2006 Nokia Corporation, author: Tomas Frydrych <tf@o-hand.com>
- *
- * LinuxKeyboardRead() XKB code based on xf86KbdLnx.c:
- * Copyright © 1990,91 by Thomas Roell, Dinkelscherben, Germany.
- * Copyright © 1994-2001 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "kdrive.h"
-#include <linux/keyboard.h>
-#include <linux/kd.h>
-#define XK_PUBLISHING
-#include <X11/keysym.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-
-extern int LinuxConsoleFd;
-
-static const KeySym linux_to_x[256] = {
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, XK_Escape,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- XK_space, XK_exclam, XK_quotedbl, XK_numbersign,
- XK_dollar, XK_percent, XK_ampersand, XK_apostrophe,
- XK_parenleft, XK_parenright, XK_asterisk, XK_plus,
- XK_comma, XK_minus, XK_period, XK_slash,
- XK_0, XK_1, XK_2, XK_3,
- XK_4, XK_5, XK_6, XK_7,
- XK_8, XK_9, XK_colon, XK_semicolon,
- XK_less, XK_equal, XK_greater, XK_question,
- XK_at, XK_A, XK_B, XK_C,
- XK_D, XK_E, XK_F, XK_G,
- XK_H, XK_I, XK_J, XK_K,
- XK_L, XK_M, XK_N, XK_O,
- XK_P, XK_Q, XK_R, XK_S,
- XK_T, XK_U, XK_V, XK_W,
- XK_X, XK_Y, XK_Z, XK_bracketleft,
- XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore,
- XK_grave, XK_a, XK_b, XK_c,
- XK_d, XK_e, XK_f, XK_g,
- XK_h, XK_i, XK_j, XK_k,
- XK_l, XK_m, XK_n, XK_o,
- XK_p, XK_q, XK_r, XK_s,
- XK_t, XK_u, XK_v, XK_w,
- XK_x, XK_y, XK_z, XK_braceleft,
- XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling,
- XK_currency, XK_yen, XK_brokenbar, XK_section,
- XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft,
- XK_notsign, XK_hyphen, XK_registered, XK_macron,
- XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior,
- XK_acute, XK_mu, XK_paragraph, XK_periodcentered,
- XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright,
- XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown,
- XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde,
- XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla,
- XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
- XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis,
- XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute,
- XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply,
- XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex,
- XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp,
- XK_agrave, XK_aacute, XK_acircumflex, XK_atilde,
- XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla,
- XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis,
- XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis,
- XK_eth, XK_ntilde, XK_ograve, XK_oacute,
- XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division,
- XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex,
- XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis
-};
-
-/*
- * Getting a keycode from scancode
- *
- * With XKB
- * --------
- *
- * We have to enqueue keyboard events using standard X keycodes which correspond
- * to AT scancode + 8; this means that we need to translate the Linux scancode
- * provided by the kernel to an AT scancode -- this translation is not linear
- * and requires that we use a LUT.
- *
- *
- * Without XKB
- * -----------
- *
- * We can use custom keycodes, which makes things simpler; we define our custom
- * keycodes as Linux scancodes + KD_KEY_OFFSET
-*/
-
-/*
- This LUT translates AT scancodes into Linux ones -- the keymap we create
- for the core X keyboard protocol has to be AT-scancode based so that it
- corresponds to the Xkb keymap.
-*/
-#if 0
-static unsigned char at2lnx[] =
-{
- 0x0, /* no valid scancode */
- 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */
- 0x03, /* KEY_2 */ 0x04, /* KEY_3 */
- 0x05, /* KEY_4 */ 0x06, /* KEY_5 */
- 0x07, /* KEY_6 */ 0x08, /* KEY_7 */
- 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */
- 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */
- 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */
- 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */
- 0x11, /* KEY_W */ 0x12, /* KEY_E */
- 0x13, /* KEY_R */ 0x14, /* KEY_T */
- 0x15, /* KEY_Y */ 0x16, /* KEY_U */
- 0x17, /* KEY_I */ 0x18, /* KEY_O */
- 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */
- 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */
- 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */
- 0x1f, /* KEY_S */ 0x20, /* KEY_D */
- 0x21, /* KEY_F */ 0x22, /* KEY_G */
- 0x23, /* KEY_H */ 0x24, /* KEY_J */
- 0x25, /* KEY_K */ 0x26, /* KEY_L */
- 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */
- 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */
- 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */
- 0x2d, /* KEY_X */ 0x2e, /* KEY_C */
- 0x2f, /* KEY_V */ 0x30, /* KEY_B */
- 0x31, /* KEY_N */ 0x32, /* KEY_M */
- 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */
- 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */
- 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */
- 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */
- 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */
- 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */
- 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */
- 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */
- 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */
- 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */
- 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */
- 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */
- 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */
- 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */
- 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */
- 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */
- 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */
- 0x00, /* 0x55 */ 0x56, /* KEY_Less */
- 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */
- 0x66, /* KEY_Home */ 0x67, /* KEY_Up */
- 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */
- 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */
- 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */
- 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */
- 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */
- 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */
- 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */
- 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */
- 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */
- 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */
- 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */
- 0x00, /* 0x71 */ 0x00, /* 0x72 */
- 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */
- 0x00, /* 0x75 */ 0x00, /* 0x76 */
- 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */
- 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */
- 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */
- 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */
- 0x00, /* 0x7f */
-};
-
-#define NUM_AT_KEYS (sizeof(at2lnx)/sizeof(at2lnx[0]))
-#define LNX_KEY_INDEX(n) n < NUM_AT_KEYS ? at2lnx[n] : 0
-
-static unsigned char tbl[KD_MAX_WIDTH] =
-{
- 0,
- 1 << KG_SHIFT,
- (1 << KG_ALTGR),
- (1 << KG_ALTGR) | (1 << KG_SHIFT)
-};
-#endif
-
-static void
-readKernelMapping(KdKeyboardInfo *ki)
-{
-#if 0
- KeySym *k;
- int i, j;
- struct kbentry kbe;
- int minKeyCode, maxKeyCode;
- int row;
- int fd;
-
- if (!ki)
- return;
-
- fd = LinuxConsoleFd;
-
- minKeyCode = NR_KEYS;
- maxKeyCode = 0;
- row = 0;
- ki->keySyms.mapWidth = KD_MAX_WIDTH;
- for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i)
- {
- kbe.kb_index = LNX_KEY_INDEX(i);
-
- k = ki->keySyms.map + row * ki->keySyms.mapWidth;
-
- for (j = 0; j < ki->keySyms.mapWidth; ++j)
- {
- unsigned short kval;
-
- k[j] = NoSymbol;
-
- kbe.kb_table = tbl[j];
- kbe.kb_value = 0;
- if (ioctl(fd, KDGKBENT, &kbe))
- continue;
-
- kval = KVAL(kbe.kb_value);
- switch (KTYP(kbe.kb_value))
- {
- case KT_LATIN:
- case KT_LETTER:
- k[j] = linux_to_x[kval];
- break;
-
- case KT_FN:
- if (kval <= 19)
- k[j] = XK_F1 + kval;
- else switch (kbe.kb_value)
- {
- case K_FIND:
- k[j] = XK_Home; /* or XK_Find */
- break;
- case K_INSERT:
- k[j] = XK_Insert;
- break;
- case K_REMOVE:
- k[j] = XK_Delete;
- break;
- case K_SELECT:
- k[j] = XK_End; /* or XK_Select */
- break;
- case K_PGUP:
- k[j] = XK_Prior;
- break;
- case K_PGDN:
- k[j] = XK_Next;
- break;
- case K_HELP:
- k[j] = XK_Help;
- break;
- case K_DO:
- k[j] = XK_Execute;
- break;
- case K_PAUSE:
- k[j] = XK_Pause;
- break;
- case K_MACRO:
- k[j] = XK_Menu;
- break;
- default:
- break;
- }
- break;
-
- case KT_SPEC:
- switch (kbe.kb_value)
- {
- case K_ENTER:
- k[j] = XK_Return;
- break;
- case K_BREAK:
- k[j] = XK_Break;
- break;
- case K_CAPS:
- k[j] = XK_Caps_Lock;
- break;
- case K_NUM:
- k[j] = XK_Num_Lock;
- break;
- case K_HOLD:
- k[j] = XK_Scroll_Lock;
- break;
- case K_COMPOSE:
- k[j] = XK_Multi_key;
- break;
- default:
- break;
- }
- break;
-
- case KT_PAD:
- switch (kbe.kb_value)
- {
- case K_PPLUS:
- k[j] = XK_KP_Add;
- break;
- case K_PMINUS:
- k[j] = XK_KP_Subtract;
- break;
- case K_PSTAR:
- k[j] = XK_KP_Multiply;
- break;
- case K_PSLASH:
- k[j] = XK_KP_Divide;
- break;
- case K_PENTER:
- k[j] = XK_KP_Enter;
- break;
- case K_PCOMMA:
- k[j] = XK_KP_Separator;
- break;
- case K_PDOT:
- k[j] = XK_KP_Decimal;
- break;
- case K_PPLUSMINUS:
- k[j] = XK_KP_Subtract;
- break;
- default:
- if (kval <= 9)
- k[j] = XK_KP_0 + kval;
- break;
- }
- break;
-
- /*
- * KT_DEAD keys are for accelerated diacritical creation.
- */
- case KT_DEAD:
- switch (kbe.kb_value)
- {
- case K_DGRAVE:
- k[j] = XK_dead_grave;
- break;
- case K_DACUTE:
- k[j] = XK_dead_acute;
- break;
- case K_DCIRCM:
- k[j] = XK_dead_circumflex;
- break;
- case K_DTILDE:
- k[j] = XK_dead_tilde;
- break;
- case K_DDIERE:
- k[j] = XK_dead_diaeresis;
- break;
- }
- break;
-
- case KT_CUR:
- switch (kbe.kb_value)
- {
- case K_DOWN:
- k[j] = XK_Down;
- break;
- case K_LEFT:
- k[j] = XK_Left;
- break;
- case K_RIGHT:
- k[j] = XK_Right;
- break;
- case K_UP:
- k[j] = XK_Up;
- break;
- }
- break;
-
- case KT_SHIFT:
- switch (kbe.kb_value)
- {
- case K_ALTGR:
- k[j] = XK_Mode_switch;
- break;
- case K_ALT:
- k[j] = (kbe.kb_index == 0x64 ?
- XK_Alt_R : XK_Alt_L);
- break;
- case K_CTRL:
- k[j] = (kbe.kb_index == 0x61 ?
- XK_Control_R : XK_Control_L);
- break;
- case K_CTRLL:
- k[j] = XK_Control_L;
- break;
- case K_CTRLR:
- k[j] = XK_Control_R;
- break;
- case K_SHIFT:
- k[j] = (kbe.kb_index == 0x36 ?
- XK_Shift_R : XK_Shift_L);
- break;
- case K_SHIFTL:
- k[j] = XK_Shift_L;
- break;
- case K_SHIFTR:
- k[j] = XK_Shift_R;
- break;
- default:
- break;
- }
- break;
-
- /*
- * KT_ASCII keys accumulate a 3 digit decimal number that gets
- * emitted when the shift state changes. We can't emulate that.
- */
- case KT_ASCII:
- break;
-
- case KT_LOCK:
- if (kbe.kb_value == K_SHIFTLOCK)
- k[j] = XK_Shift_Lock;
- break;
-
-#ifdef KT_X
- case KT_X:
- /* depends on new keyboard symbols in file linux/keyboard.h */
- if(kbe.kb_value == K_XMENU) k[j] = XK_Menu;
- if(kbe.kb_value == K_XTELEPHONE) k[j] = XK_telephone;
- break;
-#endif
-#ifdef KT_XF
- case KT_XF:
- /* special linux keysyms which map directly to XF86 keysyms */
- k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00;
- break;
-#endif
-
- default:
- break;
- }
- if (i < minKeyCode)
- minKeyCode = i;
- if (i > maxKeyCode)
- maxKeyCode = i;
- }
-
- if (minKeyCode == NR_KEYS)
- continue;
-
- if (k[3] == k[2]) k[3] = NoSymbol;
- if (k[2] == k[1]) k[2] = NoSymbol;
- if (k[1] == k[0]) k[1] = NoSymbol;
- if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
- if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol;
- row++;
- }
- ki->minScanCode = minKeyCode;
- ki->maxScanCode = maxKeyCode;
-#endif
-}
-
-/*
- * We need these to handle extended scancodes correctly (I could just use the
- * numbers below, but this makes the code more readable
- */
-
-/* The prefix codes */
-#define KEY_Prefix0 /* special 0x60 */ 96
-#define KEY_Prefix1 /* special 0x61 */ 97
-
-/* The raw scancodes */
-#define KEY_Enter /* Enter 0x1c */ 28
-#define KEY_LCtrl /* Ctrl(left) 0x1d */ 29
-#define KEY_Slash /* / (Slash) ? 0x35 */ 53
-#define KEY_KP_Multiply /* * 0x37 */ 55
-#define KEY_Alt /* Alt(left) 0x38 */ 56
-#define KEY_F3 /* F3 0x3d */ 61
-#define KEY_F4 /* F4 0x3e */ 62
-#define KEY_F5 /* F5 0x3f */ 63
-#define KEY_F6 /* F6 0x40 */ 64
-#define KEY_F7 /* F7 0x41 */ 65
-#define KEY_ScrollLock /* ScrollLock 0x46 */ 70
-#define KEY_KP_7 /* 7 Home 0x47 */ 71
-#define KEY_KP_8 /* 8 Up 0x48 */ 72
-#define KEY_KP_9 /* 9 PgUp 0x49 */ 73
-#define KEY_KP_Minus /* - (Minus) 0x4a */ 74
-#define KEY_KP_4 /* 4 Left 0x4b */ 75
-#define KEY_KP_5 /* 5 0x4c */ 76
-#define KEY_KP_6 /* 6 Right 0x4d */ 77
-#define KEY_KP_Plus /* + (Plus) 0x4e */ 78
-#define KEY_KP_1 /* 1 End 0x4f */ 79
-#define KEY_KP_2 /* 2 Down 0x50 */ 80
-#define KEY_KP_3 /* 3 PgDown 0x51 */ 81
-#define KEY_KP_0 /* 0 Insert 0x52 */ 82
-#define KEY_KP_Decimal /* . (Decimal) Delete 0x53 */ 83
-#define KEY_Home /* Home 0x59 */ 89
-#define KEY_Up /* Up 0x5a */ 90
-#define KEY_PgUp /* PgUp 0x5b */ 91
-#define KEY_Left /* Left 0x5c */ 92
-#define KEY_Begin /* Begin 0x5d */ 93
-#define KEY_Right /* Right 0x5e */ 94
-#define KEY_End /* End 0x5f */ 95
-#define KEY_Down /* Down 0x60 */ 96
-#define KEY_PgDown /* PgDown 0x61 */ 97
-#define KEY_Insert /* Insert 0x62 */ 98
-#define KEY_Delete /* Delete 0x63 */ 99
-#define KEY_KP_Enter /* Enter 0x64 */ 100
-#define KEY_RCtrl /* Ctrl(right) 0x65 */ 101
-#define KEY_Pause /* Pause 0x66 */ 102
-#define KEY_Print /* Print 0x67 */ 103
-#define KEY_KP_Divide /* Divide 0x68 */ 104
-#define KEY_AltLang /* AtlLang(right) 0x69 */ 105
-#define KEY_Break /* Break 0x6a */ 106
-#define KEY_LMeta /* Left Meta 0x6b */ 107
-#define KEY_RMeta /* Right Meta 0x6c */ 108
-#define KEY_Menu /* Menu 0x6d */ 109
-#define KEY_F13 /* F13 0x6e */ 110
-#define KEY_F14 /* F14 0x6f */ 111
-#define KEY_F15 /* F15 0x70 */ 112
-#define KEY_F16 /* F16 0x71 */ 113
-#define KEY_F17 /* F17 0x72 */ 114
-#define KEY_KP_DEC /* KP_DEC 0x73 */ 115
-
-static void
-LinuxKeyboardRead (int fd, void *closure)
-{
- unsigned char buf[256], *b;
- int n;
- unsigned char prefix = 0, scancode = 0;
-
- while ((n = read (fd, buf, sizeof (buf))) > 0) {
- b = buf;
- while (n--) {
- /*
- * With xkb we use RAW mode for reading the console, which allows us
- * process extended scancodes.
- *
- * See if this is a prefix extending the following keycode
- */
- if (!prefix && ((b[0] & 0x7f) == KEY_Prefix0))
- {
- prefix = KEY_Prefix0;
- /* swallow this up */
- b++;
- continue;
- }
- else if (!prefix && ((b[0] & 0x7f) == KEY_Prefix1))
- {
- prefix = KEY_Prefix1;
- /* swallow this up */
- b++;
- continue;
- }
- scancode = b[0] & 0x7f;
-
- switch (prefix) {
- /* from xf86Events.c */
- case KEY_Prefix0:
- {
- switch (scancode) {
- case KEY_KP_7:
- scancode = KEY_Home; break; /* curs home */
- case KEY_KP_8:
- scancode = KEY_Up; break; /* curs up */
- case KEY_KP_9:
- scancode = KEY_PgUp; break; /* curs pgup */
- case KEY_KP_4:
- scancode = KEY_Left; break; /* curs left */
- case KEY_KP_5:
- scancode = KEY_Begin; break; /* curs begin */
- case KEY_KP_6:
- scancode = KEY_Right; break; /* curs right */
- case KEY_KP_1:
- scancode = KEY_End; break; /* curs end */
- case KEY_KP_2:
- scancode = KEY_Down; break; /* curs down */
- case KEY_KP_3:
- scancode = KEY_PgDown; break; /* curs pgdown */
- case KEY_KP_0:
- scancode = KEY_Insert; break; /* curs insert */
- case KEY_KP_Decimal:
- scancode = KEY_Delete; break; /* curs delete */
- case KEY_Enter:
- scancode = KEY_KP_Enter; break; /* keypad enter */
- case KEY_LCtrl:
- scancode = KEY_RCtrl; break; /* right ctrl */
- case KEY_KP_Multiply:
- scancode = KEY_Print; break; /* print */
- case KEY_Slash:
- scancode = KEY_KP_Divide; break; /* keyp divide */
- case KEY_Alt:
- scancode = KEY_AltLang; break; /* right alt */
- case KEY_ScrollLock:
- scancode = KEY_Break; break; /* curs break */
- case 0x5b:
- scancode = KEY_LMeta; break;
- case 0x5c:
- scancode = KEY_RMeta; break;
- case 0x5d:
- scancode = KEY_Menu; break;
- case KEY_F3:
- scancode = KEY_F13; break;
- case KEY_F4:
- scancode = KEY_F14; break;
- case KEY_F5:
- scancode = KEY_F15; break;
- case KEY_F6:
- scancode = KEY_F16; break;
- case KEY_F7:
- scancode = KEY_F17; break;
- case KEY_KP_Plus:
- scancode = KEY_KP_DEC; break;
- /* Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */
- case 0x2A:
- case 0x36:
- b++;
- prefix = 0;
- continue;
- default:
- /*
- * "Internet" keyboards are generating lots of new
- * codes. Let them pass. There is little consistency
- * between them, so don't bother with symbolic names at
- * this level.
- */
- scancode += 0x78;
- }
- break;
- }
-
- case KEY_Prefix1:
- {
- /* we do no handle these */
- b++;
- prefix = 0;
- continue;
- }
-
- default: /* should not happen*/
- case 0: /* do nothing */
- ;
- }
-
- prefix = 0;
- KdEnqueueKeyboardEvent (closure, scancode, b[0] & 0x80);
- b++;
- }
- }
-}
-
-static int LinuxKbdTrans;
-static struct termios LinuxTermios;
-
-static Status
-LinuxKeyboardEnable (KdKeyboardInfo *ki)
-{
- struct termios nTty;
- unsigned char buf[256];
- int n;
- int fd;
-
- if (!ki)
- return !Success;
-
- fd = LinuxConsoleFd;
- ki->driverPrivate = (void *) fd;
-
- ioctl (fd, KDGKBMODE, &LinuxKbdTrans);
- tcgetattr (fd, &LinuxTermios);
- ioctl(fd, KDSKBMODE, K_RAW);
- nTty = LinuxTermios;
- nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
- nTty.c_oflag = 0;
- nTty.c_cflag = CREAD | CS8;
- nTty.c_lflag = 0;
- nTty.c_cc[VTIME]=0;
- nTty.c_cc[VMIN]=1;
- cfsetispeed(&nTty, 9600);
- cfsetospeed(&nTty, 9600);
- tcsetattr(fd, TCSANOW, &nTty);
- /*
- * Flush any pending keystrokes
- */
- while ((n = read (fd, buf, sizeof (buf))) > 0)
- ;
- KdRegisterFd (fd, LinuxKeyboardRead, ki);
- return Success;
-}
-
-static void
-LinuxKeyboardDisable (KdKeyboardInfo *ki)
-{
- int fd;
-
- if (!ki)
- return;
-
- fd = (int) ki->driverPrivate;
-
- KdUnregisterFd(ki, fd, FALSE);
- ioctl(fd, KDSKBMODE, LinuxKbdTrans);
- tcsetattr(fd, TCSANOW, &LinuxTermios);
-}
-
-static Status
-LinuxKeyboardInit (KdKeyboardInfo *ki)
-{
- if (!ki)
- return !Success;
-
- free(ki->path);
- ki->path = strdup("console");
- free(ki->name);
- ki->name = strdup("Linux console keyboard");
-
- readKernelMapping (ki);
-
- return Success;
-}
-
-static void
-LinuxKeyboardLeds (KdKeyboardInfo *ki, int leds)
-{
- if (!ki)
- return;
-
- ioctl ((int)ki->driverPrivate, KDSETLED, leds & 7);
-}
-
-KdKeyboardDriver LinuxKeyboardDriver = {
- "keyboard",
- .Init = LinuxKeyboardInit,
- .Enable = LinuxKeyboardEnable,
- .Leds = LinuxKeyboardLeds,
- .Disable = LinuxKeyboardDisable,
-};
+/*
+ * Copyright © 1999 Keith Packard
+ * XKB integration © 2006 Nokia Corporation, author: Tomas Frydrych <tf@o-hand.com>
+ *
+ * LinuxKeyboardRead() XKB code based on xf86KbdLnx.c:
+ * Copyright © 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ * Copyright © 1994-2001 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include "kdrive.h"
+#include <linux/keyboard.h>
+#include <linux/kd.h>
+#define XK_PUBLISHING
+#include <X11/keysym.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+extern int LinuxConsoleFd;
+
+static const KeySym linux_to_x[256] = {
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, XK_Escape,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ XK_space, XK_exclam, XK_quotedbl, XK_numbersign,
+ XK_dollar, XK_percent, XK_ampersand, XK_apostrophe,
+ XK_parenleft, XK_parenright, XK_asterisk, XK_plus,
+ XK_comma, XK_minus, XK_period, XK_slash,
+ XK_0, XK_1, XK_2, XK_3,
+ XK_4, XK_5, XK_6, XK_7,
+ XK_8, XK_9, XK_colon, XK_semicolon,
+ XK_less, XK_equal, XK_greater, XK_question,
+ XK_at, XK_A, XK_B, XK_C,
+ XK_D, XK_E, XK_F, XK_G,
+ XK_H, XK_I, XK_J, XK_K,
+ XK_L, XK_M, XK_N, XK_O,
+ XK_P, XK_Q, XK_R, XK_S,
+ XK_T, XK_U, XK_V, XK_W,
+ XK_X, XK_Y, XK_Z, XK_bracketleft,
+ XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore,
+ XK_grave, XK_a, XK_b, XK_c,
+ XK_d, XK_e, XK_f, XK_g,
+ XK_h, XK_i, XK_j, XK_k,
+ XK_l, XK_m, XK_n, XK_o,
+ XK_p, XK_q, XK_r, XK_s,
+ XK_t, XK_u, XK_v, XK_w,
+ XK_x, XK_y, XK_z, XK_braceleft,
+ XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling,
+ XK_currency, XK_yen, XK_brokenbar, XK_section,
+ XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft,
+ XK_notsign, XK_hyphen, XK_registered, XK_macron,
+ XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior,
+ XK_acute, XK_mu, XK_paragraph, XK_periodcentered,
+ XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright,
+ XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown,
+ XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde,
+ XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla,
+ XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
+ XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis,
+ XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute,
+ XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply,
+ XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex,
+ XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp,
+ XK_agrave, XK_aacute, XK_acircumflex, XK_atilde,
+ XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla,
+ XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis,
+ XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis,
+ XK_eth, XK_ntilde, XK_ograve, XK_oacute,
+ XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division,
+ XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex,
+ XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis
+};
+
+/*
+ * Getting a keycode from scancode
+ *
+ * With XKB
+ * --------
+ *
+ * We have to enqueue keyboard events using standard X keycodes which correspond
+ * to AT scancode + 8; this means that we need to translate the Linux scancode
+ * provided by the kernel to an AT scancode -- this translation is not linear
+ * and requires that we use a LUT.
+ *
+ *
+ * Without XKB
+ * -----------
+ *
+ * We can use custom keycodes, which makes things simpler; we define our custom
+ * keycodes as Linux scancodes + KD_KEY_OFFSET
+*/
+
+/*
+ This LUT translates AT scancodes into Linux ones -- the keymap we create
+ for the core X keyboard protocol has to be AT-scancode based so that it
+ corresponds to the Xkb keymap.
+*/
+#if 0
+static unsigned char at2lnx[] =
+{
+ 0x0, /* no valid scancode */
+ 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */
+ 0x03, /* KEY_2 */ 0x04, /* KEY_3 */
+ 0x05, /* KEY_4 */ 0x06, /* KEY_5 */
+ 0x07, /* KEY_6 */ 0x08, /* KEY_7 */
+ 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */
+ 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */
+ 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */
+ 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */
+ 0x11, /* KEY_W */ 0x12, /* KEY_E */
+ 0x13, /* KEY_R */ 0x14, /* KEY_T */
+ 0x15, /* KEY_Y */ 0x16, /* KEY_U */
+ 0x17, /* KEY_I */ 0x18, /* KEY_O */
+ 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */
+ 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */
+ 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */
+ 0x1f, /* KEY_S */ 0x20, /* KEY_D */
+ 0x21, /* KEY_F */ 0x22, /* KEY_G */
+ 0x23, /* KEY_H */ 0x24, /* KEY_J */
+ 0x25, /* KEY_K */ 0x26, /* KEY_L */
+ 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */
+ 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */
+ 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */
+ 0x2d, /* KEY_X */ 0x2e, /* KEY_C */
+ 0x2f, /* KEY_V */ 0x30, /* KEY_B */
+ 0x31, /* KEY_N */ 0x32, /* KEY_M */
+ 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */
+ 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */
+ 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */
+ 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */
+ 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */
+ 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */
+ 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */
+ 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */
+ 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */
+ 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */
+ 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */
+ 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */
+ 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */
+ 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */
+ 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */
+ 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */
+ 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */
+ 0x00, /* 0x55 */ 0x56, /* KEY_Less */
+ 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */
+ 0x66, /* KEY_Home */ 0x67, /* KEY_Up */
+ 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */
+ 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */
+ 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */
+ 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */
+ 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */
+ 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */
+ 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */
+ 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */
+ 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */
+ 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */
+ 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */
+ 0x00, /* 0x71 */ 0x00, /* 0x72 */
+ 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */
+ 0x00, /* 0x75 */ 0x00, /* 0x76 */
+ 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */
+ 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */
+ 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */
+ 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */
+ 0x00, /* 0x7f */
+};
+
+#define NUM_AT_KEYS (sizeof(at2lnx)/sizeof(at2lnx[0]))
+#define LNX_KEY_INDEX(n) n < NUM_AT_KEYS ? at2lnx[n] : 0
+
+static unsigned char tbl[KD_MAX_WIDTH] =
+{
+ 0,
+ 1 << KG_SHIFT,
+ (1 << KG_ALTGR),
+ (1 << KG_ALTGR) | (1 << KG_SHIFT)
+};
+#endif
+
+static void
+readKernelMapping(KdKeyboardInfo *ki)
+{
+#if 0
+ KeySym *k;
+ int i, j;
+ struct kbentry kbe;
+ int minKeyCode, maxKeyCode;
+ int row;
+ int fd;
+
+ if (!ki)
+ return;
+
+ fd = LinuxConsoleFd;
+
+ minKeyCode = NR_KEYS;
+ maxKeyCode = 0;
+ row = 0;
+ ki->keySyms.mapWidth = KD_MAX_WIDTH;
+ for (i = 0; i < NR_KEYS && row < KD_MAX_LENGTH; ++i)
+ {
+ kbe.kb_index = LNX_KEY_INDEX(i);
+
+ k = ki->keySyms.map + row * ki->keySyms.mapWidth;
+
+ for (j = 0; j < ki->keySyms.mapWidth; ++j)
+ {
+ unsigned short kval;
+
+ k[j] = NoSymbol;
+
+ kbe.kb_table = tbl[j];
+ kbe.kb_value = 0;
+ if (ioctl(fd, KDGKBENT, &kbe))
+ continue;
+
+ kval = KVAL(kbe.kb_value);
+ switch (KTYP(kbe.kb_value))
+ {
+ case KT_LATIN:
+ case KT_LETTER:
+ k[j] = linux_to_x[kval];
+ break;
+
+ case KT_FN:
+ if (kval <= 19)
+ k[j] = XK_F1 + kval;
+ else switch (kbe.kb_value)
+ {
+ case K_FIND:
+ k[j] = XK_Home; /* or XK_Find */
+ break;
+ case K_INSERT:
+ k[j] = XK_Insert;
+ break;
+ case K_REMOVE:
+ k[j] = XK_Delete;
+ break;
+ case K_SELECT:
+ k[j] = XK_End; /* or XK_Select */
+ break;
+ case K_PGUP:
+ k[j] = XK_Prior;
+ break;
+ case K_PGDN:
+ k[j] = XK_Next;
+ break;
+ case K_HELP:
+ k[j] = XK_Help;
+ break;
+ case K_DO:
+ k[j] = XK_Execute;
+ break;
+ case K_PAUSE:
+ k[j] = XK_Pause;
+ break;
+ case K_MACRO:
+ k[j] = XK_Menu;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case KT_SPEC:
+ switch (kbe.kb_value)
+ {
+ case K_ENTER:
+ k[j] = XK_Return;
+ break;
+ case K_BREAK:
+ k[j] = XK_Break;
+ break;
+ case K_CAPS:
+ k[j] = XK_Caps_Lock;
+ break;
+ case K_NUM:
+ k[j] = XK_Num_Lock;
+ break;
+ case K_HOLD:
+ k[j] = XK_Scroll_Lock;
+ break;
+ case K_COMPOSE:
+ k[j] = XK_Multi_key;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case KT_PAD:
+ switch (kbe.kb_value)
+ {
+ case K_PPLUS:
+ k[j] = XK_KP_Add;
+ break;
+ case K_PMINUS:
+ k[j] = XK_KP_Subtract;
+ break;
+ case K_PSTAR:
+ k[j] = XK_KP_Multiply;
+ break;
+ case K_PSLASH:
+ k[j] = XK_KP_Divide;
+ break;
+ case K_PENTER:
+ k[j] = XK_KP_Enter;
+ break;
+ case K_PCOMMA:
+ k[j] = XK_KP_Separator;
+ break;
+ case K_PDOT:
+ k[j] = XK_KP_Decimal;
+ break;
+ case K_PPLUSMINUS:
+ k[j] = XK_KP_Subtract;
+ break;
+ default:
+ if (kval <= 9)
+ k[j] = XK_KP_0 + kval;
+ break;
+ }
+ break;
+
+ /*
+ * KT_DEAD keys are for accelerated diacritical creation.
+ */
+ case KT_DEAD:
+ switch (kbe.kb_value)
+ {
+ case K_DGRAVE:
+ k[j] = XK_dead_grave;
+ break;
+ case K_DACUTE:
+ k[j] = XK_dead_acute;
+ break;
+ case K_DCIRCM:
+ k[j] = XK_dead_circumflex;
+ break;
+ case K_DTILDE:
+ k[j] = XK_dead_tilde;
+ break;
+ case K_DDIERE:
+ k[j] = XK_dead_diaeresis;
+ break;
+ }
+ break;
+
+ case KT_CUR:
+ switch (kbe.kb_value)
+ {
+ case K_DOWN:
+ k[j] = XK_Down;
+ break;
+ case K_LEFT:
+ k[j] = XK_Left;
+ break;
+ case K_RIGHT:
+ k[j] = XK_Right;
+ break;
+ case K_UP:
+ k[j] = XK_Up;
+ break;
+ }
+ break;
+
+ case KT_SHIFT:
+ switch (kbe.kb_value)
+ {
+ case K_ALTGR:
+ k[j] = XK_Mode_switch;
+ break;
+ case K_ALT:
+ k[j] = (kbe.kb_index == 0x64 ?
+ XK_Alt_R : XK_Alt_L);
+ break;
+ case K_CTRL:
+ k[j] = (kbe.kb_index == 0x61 ?
+ XK_Control_R : XK_Control_L);
+ break;
+ case K_CTRLL:
+ k[j] = XK_Control_L;
+ break;
+ case K_CTRLR:
+ k[j] = XK_Control_R;
+ break;
+ case K_SHIFT:
+ k[j] = (kbe.kb_index == 0x36 ?
+ XK_Shift_R : XK_Shift_L);
+ break;
+ case K_SHIFTL:
+ k[j] = XK_Shift_L;
+ break;
+ case K_SHIFTR:
+ k[j] = XK_Shift_R;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ /*
+ * KT_ASCII keys accumulate a 3 digit decimal number that gets
+ * emitted when the shift state changes. We can't emulate that.
+ */
+ case KT_ASCII:
+ break;
+
+ case KT_LOCK:
+ if (kbe.kb_value == K_SHIFTLOCK)
+ k[j] = XK_Shift_Lock;
+ break;
+
+#ifdef KT_X
+ case KT_X:
+ /* depends on new keyboard symbols in file linux/keyboard.h */
+ if(kbe.kb_value == K_XMENU) k[j] = XK_Menu;
+ if(kbe.kb_value == K_XTELEPHONE) k[j] = XK_telephone;
+ break;
+#endif
+#ifdef KT_XF
+ case KT_XF:
+ /* special linux keysyms which map directly to XF86 keysyms */
+ k[j] = (kbe.kb_value & 0xFF) + 0x1008FF00;
+ break;
+#endif
+
+ default:
+ break;
+ }
+ if (i < minKeyCode)
+ minKeyCode = i;
+ if (i > maxKeyCode)
+ maxKeyCode = i;
+ }
+
+ if (minKeyCode == NR_KEYS)
+ continue;
+
+ if (k[3] == k[2]) k[3] = NoSymbol;
+ if (k[2] == k[1]) k[2] = NoSymbol;
+ if (k[1] == k[0]) k[1] = NoSymbol;
+ if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
+ if (k[3] == k[0] && k[2] == k[1] && k[2] == NoSymbol) k[3] =NoSymbol;
+ row++;
+ }
+ ki->minScanCode = minKeyCode;
+ ki->maxScanCode = maxKeyCode;
+#endif
+}
+
+/*
+ * We need these to handle extended scancodes correctly (I could just use the
+ * numbers below, but this makes the code more readable
+ */
+
+/* The prefix codes */
+#define KEY_Prefix0 /* special 0x60 */ 96
+#define KEY_Prefix1 /* special 0x61 */ 97
+
+/* The raw scancodes */
+#define KEY_Enter /* Enter 0x1c */ 28
+#define KEY_LCtrl /* Ctrl(left) 0x1d */ 29
+#define KEY_Slash /* / (Slash) ? 0x35 */ 53
+#define KEY_KP_Multiply /* * 0x37 */ 55
+#define KEY_Alt /* Alt(left) 0x38 */ 56
+#define KEY_F3 /* F3 0x3d */ 61
+#define KEY_F4 /* F4 0x3e */ 62
+#define KEY_F5 /* F5 0x3f */ 63
+#define KEY_F6 /* F6 0x40 */ 64
+#define KEY_F7 /* F7 0x41 */ 65
+#define KEY_ScrollLock /* ScrollLock 0x46 */ 70
+#define KEY_KP_7 /* 7 Home 0x47 */ 71
+#define KEY_KP_8 /* 8 Up 0x48 */ 72
+#define KEY_KP_9 /* 9 PgUp 0x49 */ 73
+#define KEY_KP_Minus /* - (Minus) 0x4a */ 74
+#define KEY_KP_4 /* 4 Left 0x4b */ 75
+#define KEY_KP_5 /* 5 0x4c */ 76
+#define KEY_KP_6 /* 6 Right 0x4d */ 77
+#define KEY_KP_Plus /* + (Plus) 0x4e */ 78
+#define KEY_KP_1 /* 1 End 0x4f */ 79
+#define KEY_KP_2 /* 2 Down 0x50 */ 80
+#define KEY_KP_3 /* 3 PgDown 0x51 */ 81
+#define KEY_KP_0 /* 0 Insert 0x52 */ 82
+#define KEY_KP_Decimal /* . (Decimal) Delete 0x53 */ 83
+#define KEY_Home /* Home 0x59 */ 89
+#define KEY_Up /* Up 0x5a */ 90
+#define KEY_PgUp /* PgUp 0x5b */ 91
+#define KEY_Left /* Left 0x5c */ 92
+#define KEY_Begin /* Begin 0x5d */ 93
+#define KEY_Right /* Right 0x5e */ 94
+#define KEY_End /* End 0x5f */ 95
+#define KEY_Down /* Down 0x60 */ 96
+#define KEY_PgDown /* PgDown 0x61 */ 97
+#define KEY_Insert /* Insert 0x62 */ 98
+#define KEY_Delete /* Delete 0x63 */ 99
+#define KEY_KP_Enter /* Enter 0x64 */ 100
+#define KEY_RCtrl /* Ctrl(right) 0x65 */ 101
+#define KEY_Pause /* Pause 0x66 */ 102
+#define KEY_Print /* Print 0x67 */ 103
+#define KEY_KP_Divide /* Divide 0x68 */ 104
+#define KEY_AltLang /* AtlLang(right) 0x69 */ 105
+#define KEY_Break /* Break 0x6a */ 106
+#define KEY_LMeta /* Left Meta 0x6b */ 107
+#define KEY_RMeta /* Right Meta 0x6c */ 108
+#define KEY_Menu /* Menu 0x6d */ 109
+#define KEY_F13 /* F13 0x6e */ 110
+#define KEY_F14 /* F14 0x6f */ 111
+#define KEY_F15 /* F15 0x70 */ 112
+#define KEY_F16 /* F16 0x71 */ 113
+#define KEY_F17 /* F17 0x72 */ 114
+#define KEY_KP_DEC /* KP_DEC 0x73 */ 115
+
+static void
+LinuxKeyboardRead (int fd, void *closure)
+{
+ unsigned char buf[256], *b;
+ int n;
+ unsigned char prefix = 0, scancode = 0;
+
+ while ((n = read (fd, buf, sizeof (buf))) > 0) {
+ b = buf;
+ while (n--) {
+ /*
+ * With xkb we use RAW mode for reading the console, which allows us
+ * process extended scancodes.
+ *
+ * See if this is a prefix extending the following keycode
+ */
+ if (!prefix && ((b[0] & 0x7f) == KEY_Prefix0))
+ {
+ prefix = KEY_Prefix0;
+ /* swallow this up */
+ b++;
+ continue;
+ }
+ else if (!prefix && ((b[0] & 0x7f) == KEY_Prefix1))
+ {
+ prefix = KEY_Prefix1;
+ /* swallow this up */
+ b++;
+ continue;
+ }
+ scancode = b[0] & 0x7f;
+
+ switch (prefix) {
+ /* from xf86Events.c */
+ case KEY_Prefix0:
+ {
+ switch (scancode) {
+ case KEY_KP_7:
+ scancode = KEY_Home; break; /* curs home */
+ case KEY_KP_8:
+ scancode = KEY_Up; break; /* curs up */
+ case KEY_KP_9:
+ scancode = KEY_PgUp; break; /* curs pgup */
+ case KEY_KP_4:
+ scancode = KEY_Left; break; /* curs left */
+ case KEY_KP_5:
+ scancode = KEY_Begin; break; /* curs begin */
+ case KEY_KP_6:
+ scancode = KEY_Right; break; /* curs right */
+ case KEY_KP_1:
+ scancode = KEY_End; break; /* curs end */
+ case KEY_KP_2:
+ scancode = KEY_Down; break; /* curs down */
+ case KEY_KP_3:
+ scancode = KEY_PgDown; break; /* curs pgdown */
+ case KEY_KP_0:
+ scancode = KEY_Insert; break; /* curs insert */
+ case KEY_KP_Decimal:
+ scancode = KEY_Delete; break; /* curs delete */
+ case KEY_Enter:
+ scancode = KEY_KP_Enter; break; /* keypad enter */
+ case KEY_LCtrl:
+ scancode = KEY_RCtrl; break; /* right ctrl */
+ case KEY_KP_Multiply:
+ scancode = KEY_Print; break; /* print */
+ case KEY_Slash:
+ scancode = KEY_KP_Divide; break; /* keyp divide */
+ case KEY_Alt:
+ scancode = KEY_AltLang; break; /* right alt */
+ case KEY_ScrollLock:
+ scancode = KEY_Break; break; /* curs break */
+ case 0x5b:
+ scancode = KEY_LMeta; break;
+ case 0x5c:
+ scancode = KEY_RMeta; break;
+ case 0x5d:
+ scancode = KEY_Menu; break;
+ case KEY_F3:
+ scancode = KEY_F13; break;
+ case KEY_F4:
+ scancode = KEY_F14; break;
+ case KEY_F5:
+ scancode = KEY_F15; break;
+ case KEY_F6:
+ scancode = KEY_F16; break;
+ case KEY_F7:
+ scancode = KEY_F17; break;
+ case KEY_KP_Plus:
+ scancode = KEY_KP_DEC; break;
+ /* Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */
+ case 0x2A:
+ case 0x36:
+ b++;
+ prefix = 0;
+ continue;
+ default:
+ /*
+ * "Internet" keyboards are generating lots of new
+ * codes. Let them pass. There is little consistency
+ * between them, so don't bother with symbolic names at
+ * this level.
+ */
+ scancode += 0x78;
+ }
+ break;
+ }
+
+ case KEY_Prefix1:
+ {
+ /* we do no handle these */
+ b++;
+ prefix = 0;
+ continue;
+ }
+
+ default: /* should not happen*/
+ case 0: /* do nothing */
+ ;
+ }
+
+ prefix = 0;
+ KdEnqueueKeyboardEvent (closure, scancode, b[0] & 0x80);
+ b++;
+ }
+ }
+}
+
+static int LinuxKbdTrans;
+static struct termios LinuxTermios;
+
+static Status
+LinuxKeyboardEnable (KdKeyboardInfo *ki)
+{
+ struct termios nTty;
+ unsigned char buf[256];
+ int n;
+ int fd;
+
+ if (!ki)
+ return !Success;
+
+ fd = LinuxConsoleFd;
+ ki->driverPrivate = (void *) fd;
+
+ ioctl (fd, KDGKBMODE, &LinuxKbdTrans);
+ tcgetattr (fd, &LinuxTermios);
+ ioctl(fd, KDSKBMODE, K_RAW);
+ nTty = LinuxTermios;
+ nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
+ nTty.c_oflag = 0;
+ nTty.c_cflag = CREAD | CS8;
+ nTty.c_lflag = 0;
+ nTty.c_cc[VTIME]=0;
+ nTty.c_cc[VMIN]=1;
+ cfsetispeed(&nTty, 9600);
+ cfsetospeed(&nTty, 9600);
+ tcsetattr(fd, TCSANOW, &nTty);
+ /*
+ * Flush any pending keystrokes
+ */
+ while ((n = read (fd, buf, sizeof (buf))) > 0)
+ ;
+ KdRegisterFd (fd, LinuxKeyboardRead, ki);
+ return Success;
+}
+
+static void
+LinuxKeyboardDisable (KdKeyboardInfo *ki)
+{
+ int fd;
+
+ if (!ki)
+ return;
+
+ fd = (int) ki->driverPrivate;
+
+ KdUnregisterFd(ki, fd, FALSE);
+ ioctl(fd, KDSKBMODE, LinuxKbdTrans);
+ tcsetattr(fd, TCSANOW, &LinuxTermios);
+}
+
+static Status
+LinuxKeyboardInit (KdKeyboardInfo *ki)
+{
+ if (!ki)
+ return !Success;
+
+ free(ki->path);
+ ki->path = strdup("console");
+ free(ki->name);
+ ki->name = strdup("Linux console keyboard");
+
+ readKernelMapping (ki);
+
+ return Success;
+}
+
+static void
+LinuxKeyboardLeds (KdKeyboardInfo *ki, int leds)
+{
+ if (!ki)
+ return;
+
+ ioctl ((int)ki->driverPrivate, KDSETLED, leds & 7);
+}
+
+KdKeyboardDriver LinuxKeyboardDriver = {
+ "keyboard",
+ .Init = LinuxKeyboardInit,
+ .Enable = LinuxKeyboardEnable,
+ .Leds = LinuxKeyboardLeds,
+ .Disable = LinuxKeyboardDisable,
+};
diff --git a/xorg-server/hw/kdrive/linux/linux.c b/xorg-server/hw/kdrive/linux/linux.c
index 9863c1424..a53db4965 100644
--- a/xorg-server/hw/kdrive/linux/linux.c
+++ b/xorg-server/hw/kdrive/linux/linux.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 1999 Keith Packard
+ * Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/kdrive/linux/mouse.c b/xorg-server/hw/kdrive/linux/mouse.c
index 2e39d240e..93c207817 100644
--- a/xorg-server/hw/kdrive/linux/mouse.c
+++ b/xorg-server/hw/kdrive/linux/mouse.c
@@ -1,1030 +1,1030 @@
-/*
- * Copyright © 2001 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include <errno.h>
-#include <termios.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xpoll.h>
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "kdrive.h"
-
-#undef DEBUG
-#undef DEBUG_BYTES
-#define KBUFIO_SIZE 256
-#define MOUSE_TIMEOUT 100
-
-typedef struct _kbufio {
- int fd;
- unsigned char buf[KBUFIO_SIZE];
- int avail;
- int used;
-} Kbufio;
-
-static Bool
-MouseWaitForReadable (int fd, int timeout)
-{
- fd_set set;
- struct timeval tv, *tp;
- int n;
- CARD32 done;
-
- done = GetTimeInMillis () + timeout;
- for (;;)
- {
- FD_ZERO (&set);
- FD_SET (fd, &set);
- if (timeout == -1)
- tp = 0;
- else
- {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- tp = &tv;
- }
- n = select (fd + 1, &set, 0, 0, tp);
- if (n > 0)
- return TRUE;
- if (n < 0 && (errno == EAGAIN || errno == EINTR))
- {
- timeout = (int) (done - GetTimeInMillis ());
- if (timeout > 0)
- continue;
- }
- break;
- }
- return FALSE;
-}
-
-static int
-MouseReadByte (Kbufio *b, int timeout)
-{
- int n;
- if (b->avail <= b->used)
- {
- if (timeout && !MouseWaitForReadable (b->fd, timeout))
- {
-#ifdef DEBUG_BYTES
- ErrorF ("\tTimeout %d\n", timeout);
-#endif
- return -1;
- }
- n = read (b->fd, b->buf, KBUFIO_SIZE);
- if (n <= 0)
- return -1;
- b->avail = n;
- b->used = 0;
- }
-#ifdef DEBUG_BYTES
- ErrorF ("\tget %02x\n", b->buf[b->used]);
-#endif
- return b->buf[b->used++];
-}
-
-#if NOTUSED
-static int
-MouseFlush (Kbufio *b, char *buf, int size)
-{
- CARD32 now = GetTimeInMillis ();
- CARD32 done = now + 100;
- int c;
- int n = 0;
-
- while ((c = MouseReadByte (b, done - now)) != -1)
- {
- if (buf)
- {
- if (n == size)
- {
- memmove (buf, buf + 1, size - 1);
- n--;
- }
- buf[n++] = c;
- }
- now = GetTimeInMillis ();
- if ((INT32) (now - done) >= 0)
- break;
- }
- return n;
-}
-
-static int
-MousePeekByte (Kbufio *b, int timeout)
-{
- int c;
-
- c = MouseReadByte (b, timeout);
- if (c != -1)
- --b->used;
- return c;
-}
-#endif /* NOTUSED */
-
-static Bool
-MouseWaitForWritable (int fd, int timeout)
-{
- fd_set set;
- struct timeval tv, *tp;
- int n;
-
- FD_ZERO (&set);
- FD_SET (fd, &set);
- if (timeout == -1)
- tp = 0;
- else
- {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- tp = &tv;
- }
- n = select (fd + 1, 0, &set, 0, tp);
- if (n > 0)
- return TRUE;
- return FALSE;
-}
-
-static Bool
-MouseWriteByte (int fd, unsigned char c, int timeout)
-{
- int ret;
-
-#ifdef DEBUG_BYTES
- ErrorF ("\tput %02x\n", c);
-#endif
- for (;;)
- {
- ret = write (fd, &c, 1);
- if (ret == 1)
- return TRUE;
- if (ret == 0)
- return FALSE;
- if (errno != EWOULDBLOCK)
- return FALSE;
- if (!MouseWaitForWritable (fd, timeout))
- return FALSE;
- }
-}
-
-static Bool
-MouseWriteBytes (int fd, unsigned char *c, int n, int timeout)
-{
- while (n--)
- if (!MouseWriteByte (fd, *c++, timeout))
- return FALSE;
- return TRUE;
-}
-
-#define MAX_MOUSE 10 /* maximum length of mouse protocol */
-#define MAX_SKIP 16 /* number of error bytes before switching */
-#define MAX_VALID 4 /* number of valid packets before accepting */
-
-typedef struct _kmouseProt {
- char *name;
- Bool (*Complete) (KdPointerInfo *pi, unsigned char *ev, int ne);
- int (*Valid) (KdPointerInfo *pi, unsigned char *ev, int ne);
- Bool (*Parse) (KdPointerInfo *pi, unsigned char *ev, int ne);
- Bool (*Init) (KdPointerInfo *pi);
- unsigned char headerMask, headerValid;
- unsigned char dataMask, dataValid;
- Bool tty;
- unsigned int c_iflag;
- unsigned int c_oflag;
- unsigned int c_lflag;
- unsigned int c_cflag;
- unsigned int speed;
- unsigned char *init;
- unsigned long state;
-} KmouseProt;
-
-typedef enum _kmouseStage {
- MouseBroken, MouseTesting, MouseWorking
-} KmouseStage;
-
-typedef struct _kmouse {
- Kbufio iob;
- const KmouseProt *prot;
- int i_prot;
- KmouseStage stage; /* protocol verification stage */
- Bool tty; /* mouse device is a tty */
- int valid; /* sequential valid events */
- int tested; /* bytes scanned during Testing phase */
- int invalid;/* total invalid bytes for this protocol */
- unsigned long state; /* private per protocol, init to prot->state */
-} Kmouse;
-
-static int mouseValid (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- const KmouseProt *prot = km->prot;
- int i;
-
- for (i = 0; i < ne; i++)
- if ((ev[i] & prot->headerMask) == prot->headerValid)
- break;
- if (i != 0)
- return i;
- for (i = 1; i < ne; i++)
- if ((ev[i] & prot->dataMask) != prot->dataValid)
- return -1;
- return 0;
-}
-
-static Bool threeComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- return ne == 3;
-}
-
-static Bool fourComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- return ne == 4;
-}
-
-static Bool fiveComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- return ne == 5;
-}
-
-static Bool MouseReasonable (KdPointerInfo *pi, unsigned long flags, int dx, int dy)
-{
- Kmouse *km = pi->driverPrivate;
-
- if (km->stage == MouseWorking)
- return TRUE;
- if (dx < -50 || dx > 50)
- {
-#ifdef DEBUG
- ErrorF ("Large X %d\n", dx);
-#endif
- return FALSE;
- }
- if (dy < -50 || dy > 50)
- {
-#ifdef DEBUG
- ErrorF ("Large Y %d\n", dy);
-#endif
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * Standard PS/2 mouse protocol
- */
-static Bool ps2Parse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy, dz;
- unsigned long flags;
- unsigned long flagsrelease = 0;
-
- flags = KD_MOUSE_DELTA;
- if (ev[0] & 4)
- flags |= KD_BUTTON_2;
- if (ev[0] & 2)
- flags |= KD_BUTTON_3;
- if (ev[0] & 1)
- flags |= KD_BUTTON_1;
-
- if (ne > 3)
- {
- dz = (int) (signed char) ev[3];
- if (dz < 0)
- {
- flags |= KD_BUTTON_4;
- flagsrelease = KD_BUTTON_4;
- }
- else if (dz > 0)
- {
- flags |= KD_BUTTON_5;
- flagsrelease = KD_BUTTON_5;
- }
- }
-
- dx = ev[1];
- if (ev[0] & 0x10)
- dx -= 256;
- dy = ev[2];
- if (ev[0] & 0x20)
- dy -= 256;
- dy = -dy;
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- {
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- if (flagsrelease)
- {
- flags &= ~flagsrelease;
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- }
- }
- return TRUE;
-}
-
-static Bool ps2Init (KdPointerInfo *pi);
-
-static const KmouseProt ps2Prot = {
- "ps/2",
- threeComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
-};
-
-static const KmouseProt imps2Prot = {
- "imps/2",
- fourComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
-};
-
-static const KmouseProt exps2Prot = {
- "exps/2",
- fourComplete, mouseValid, ps2Parse, ps2Init,
- 0x08, 0x08, 0x00, 0x00,
- FALSE
-};
-
-/*
- * Once the mouse is known to speak ps/2 protocol, go and find out
- * what advanced capabilities it has and turn them on
- */
-
-/* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */
-
-/* aux device commands (sent to KBD_DATA_PORT) */
-#define PSMC_SET_SCALING11 0x00e6
-#define PSMC_SET_SCALING21 0x00e7
-#define PSMC_SET_RESOLUTION 0x00e8
-#define PSMC_SEND_DEV_STATUS 0x00e9
-#define PSMC_SET_STREAM_MODE 0x00ea
-#define PSMC_SEND_DEV_DATA 0x00eb
-#define PSMC_SET_REMOTE_MODE 0x00f0
-#define PSMC_SEND_DEV_ID 0x00f2
-#define PSMC_SET_SAMPLING_RATE 0x00f3
-#define PSMC_ENABLE_DEV 0x00f4
-#define PSMC_DISABLE_DEV 0x00f5
-#define PSMC_SET_DEFAULTS 0x00f6
-#define PSMC_RESET_DEV 0x00ff
-
-/* PSMC_SET_RESOLUTION argument */
-#define PSMD_RES_LOW 0 /* typically 25ppi */
-#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */
-#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */
-#define PSMD_RES_HIGH 3 /* typically 200ppi */
-#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH
-
-/* PSMC_SET_SAMPLING_RATE */
-#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */
-
-/* aux device ID */
-#define PSM_MOUSE_ID 0
-#define PSM_BALLPOINT_ID 2
-#define PSM_INTELLI_ID 3
-#define PSM_EXPLORER_ID 4
-#define PSM_4DMOUSE_ID 6
-#define PSM_4DPLUS_ID 8
-
-static unsigned char ps2_init[] = {
- PSMC_ENABLE_DEV,
- 0,
-};
-
-#define NINIT_PS2 1
-
-static unsigned char wheel_3button_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SEND_DEV_ID,
- 0,
-};
-
-#define NINIT_IMPS2 4
-
-static unsigned char wheel_5button_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 80,
- PSMC_SEND_DEV_ID,
- 0
-};
-
-#define NINIT_EXPS2 7
-
-static unsigned char intelli_init[] = {
- PSMC_SET_SAMPLING_RATE, 200,
- PSMC_SET_SAMPLING_RATE, 100,
- PSMC_SET_SAMPLING_RATE, 80,
- 0
-};
-
-#define NINIT_INTELLI 3
-
-static int
-ps2SkipInit (KdPointerInfo *pi, int ninit, Bool ret_next)
-{
- Kmouse *km = pi->driverPrivate;
- int c = -1;
- int skipping;
- Bool waiting;
-
- skipping = 0;
- waiting = FALSE;
- while (ninit || ret_next)
- {
- c = MouseReadByte (&km->iob, MOUSE_TIMEOUT);
- if (c == -1)
- break;
- /* look for ACK */
- if (c == 0xfa)
- {
- ninit--;
- if (ret_next)
- waiting = TRUE;
- }
- /* look for packet start -- not the response */
- else if ((c & 0x08) == 0x08)
- waiting = FALSE;
- else if (waiting)
- break;
- }
- return c;
-}
-
-static Bool
-ps2Init (KdPointerInfo *pi)
-{
- Kmouse *km = pi->driverPrivate;
- int skipping;
- Bool waiting;
- int id;
- unsigned char *init;
- int ninit;
-
- /* Send Intellimouse initialization sequence */
- MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *) intelli_init), 100);
- /*
- * Send ID command
- */
- if (!MouseWriteByte (km->iob.fd, PSMC_SEND_DEV_ID, 100))
- return FALSE;
- skipping = 0;
- waiting = FALSE;
- id = ps2SkipInit (pi, 0, TRUE);
- switch (id) {
- case 3:
- init = wheel_3button_init;
- ninit = NINIT_IMPS2;
- km->prot = &imps2Prot;
- break;
- case 4:
- init = wheel_5button_init;
- ninit = NINIT_EXPS2;
- km->prot = &exps2Prot;
- break;
- default:
- init = ps2_init;
- ninit = NINIT_PS2;
- km->prot = &ps2Prot;
- break;
- }
- if (init)
- MouseWriteBytes (km->iob.fd, init, strlen ((char *) init), 100);
- /*
- * Flush out the available data to eliminate responses to the
- * initialization string. Make sure any partial event is
- * skipped
- */
- (void) ps2SkipInit (pi, ninit, FALSE);
- return TRUE;
-}
-
-static Bool busParse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy;
- unsigned long flags;
-
- flags = KD_MOUSE_DELTA;
- dx = (signed char) ev[1];
- dy = -(signed char) ev[2];
- if ((ev[0] & 4) == 0)
- flags |= KD_BUTTON_1;
- if ((ev[0] & 2) == 0)
- flags |= KD_BUTTON_2;
- if ((ev[0] & 1) == 0)
- flags |= KD_BUTTON_3;
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- return TRUE;
-}
-
-static const KmouseProt busProt = {
- "bus",
- threeComplete, mouseValid, busParse, 0,
- 0xf8, 0x00, 0x00, 0x00,
- FALSE
-};
-
-/*
- * Standard MS serial protocol, three bytes
- */
-
-static Bool msParse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy;
- unsigned long flags;
-
- flags = KD_MOUSE_DELTA;
-
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_1;
- if (ev[0] & 0x10)
- flags |= KD_BUTTON_3;
-
- dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
- dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- return TRUE;
-}
-
-static const KmouseProt msProt = {
- "ms",
- threeComplete, mouseValid, msParse, 0,
- 0xc0, 0x40, 0xc0, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS7 | CSTOPB | CREAD | CLOCAL,
- B1200,
-};
-
-/*
- * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the
- * first byte of a synchronized protocol stream and see if it's got
- * any bits turned on that can't occur in that fourth byte
- */
-static Bool logiComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
-
- if ((ev[0] & 0x40) == 0x40)
- return ne == 3;
- if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0)
- return ne == 1;
- return FALSE;
-}
-
-static int logiValid (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- const KmouseProt *prot = km->prot;
- int i;
-
- for (i = 0; i < ne; i++)
- {
- if ((ev[i] & 0x40) == 0x40)
- break;
- if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0)
- break;
- }
- if (i != 0)
- return i;
- for (i = 1; i < ne; i++)
- if ((ev[i] & prot->dataMask) != prot->dataValid)
- return -1;
- return 0;
-}
-
-static Bool logiParse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy;
- unsigned long flags;
-
- flags = KD_MOUSE_DELTA;
-
- if (ne == 3)
- {
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_1;
- if (ev[0] & 0x10)
- flags |= KD_BUTTON_3;
-
- dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
- dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
- flags |= km->state & KD_BUTTON_2;
- }
- else
- {
- if (ev[0] & 0x20)
- flags |= KD_BUTTON_2;
- dx = 0;
- dy = 0;
- flags |= km->state & (KD_BUTTON_1|KD_BUTTON_3);
- }
-
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- return TRUE;
-}
-
-static const KmouseProt logiProt = {
- "logitech",
- logiComplete, logiValid, logiParse, 0,
- 0xc0, 0x40, 0xc0, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS7 | CSTOPB | CREAD | CLOCAL,
- B1200,
-};
-
-/*
- * Mouse systems protocol, 5 bytes
- */
-static Bool mscParse (KdPointerInfo *pi, unsigned char *ev, int ne)
-{
- Kmouse *km = pi->driverPrivate;
- int dx, dy;
- unsigned long flags;
-
- flags = KD_MOUSE_DELTA;
-
- if (!(ev[0] & 0x4))
- flags |= KD_BUTTON_1;
- if (!(ev[0] & 0x2))
- flags |= KD_BUTTON_2;
- if (!(ev[0] & 0x1))
- flags |= KD_BUTTON_3;
- dx = (signed char)(ev[1]) + (signed char)(ev[3]);
- dy = - ((signed char)(ev[2]) + (signed char)(ev[4]));
-
- if (!MouseReasonable (pi, flags, dx, dy))
- return FALSE;
- if (km->stage == MouseWorking)
- KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
- return TRUE;
-}
-
-static const KmouseProt mscProt = {
- "msc",
- fiveComplete, mouseValid, mscParse, 0,
- 0xf8, 0x80, 0x00, 0x00,
- TRUE,
- IGNPAR,
- 0,
- 0,
- CS8 | CSTOPB | CREAD | CLOCAL,
- B1200,
-};
-
-/*
- * Use logitech before ms -- they're the same except that
- * logitech sometimes has a fourth byte
- */
-static const KmouseProt *kmouseProts[] = {
- &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, &mscProt,
-};
-
-#define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0]))
-
-static void
-MouseInitProtocol (Kmouse *km)
-{
- int ret;
- struct termios t;
-
- if (km->prot->tty)
- {
- ret = tcgetattr (km->iob.fd, &t);
-
- if (ret >= 0)
- {
- t.c_iflag = km->prot->c_iflag;
- t.c_oflag = km->prot->c_oflag;
- t.c_lflag = km->prot->c_lflag;
- t.c_cflag = km->prot->c_cflag;
- cfsetispeed (&t, km->prot->speed);
- cfsetospeed (&t, km->prot->speed);
- ret = tcsetattr (km->iob.fd, TCSANOW, &t);
- }
- }
- km->stage = MouseBroken;
- km->valid = 0;
- km->tested = 0;
- km->invalid = 0;
- km->state = km->prot->state;
-}
-
-static void
-MouseFirstProtocol (Kmouse *km, char *prot)
-{
- if (prot)
- {
- for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++)
- if (!strcmp (prot, kmouseProts[km->i_prot]->name))
- break;
- if (km->i_prot == NUM_PROT)
- {
- int i;
- ErrorF ("Unknown mouse protocol \"%s\". Pick one of:", prot);
- for (i = 0; i < NUM_PROT; i++)
- ErrorF (" %s", kmouseProts[i]->name);
- ErrorF ("\n");
- }
- else
- {
- km->prot = kmouseProts[km->i_prot];
- if (km->tty && !km->prot->tty)
- ErrorF ("Mouse device is serial port, protocol %s is not serial protocol\n",
- prot);
- else if (!km->tty && km->prot->tty)
- ErrorF ("Mouse device is not serial port, protocol %s is serial protocol\n",
- prot);
- }
- }
- if (!km->prot)
- {
- for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; km->i_prot++)
- ;
- km->prot = kmouseProts[km->i_prot];
- }
- MouseInitProtocol (km);
-}
-
-static void
-MouseNextProtocol (Kmouse *km)
-{
- do
- {
- if (!km->prot)
- km->i_prot = 0;
- else
- if (++km->i_prot == NUM_PROT) km->i_prot = 0;
- km->prot = kmouseProts[km->i_prot];
- } while (km->prot->tty != km->tty);
- MouseInitProtocol (km);
- ErrorF ("Switching to mouse protocol \"%s\"\n", km->prot->name);
-}
-
-static void
-MouseRead (int mousePort, void *closure)
-{
- KdPointerInfo *pi = closure;
- Kmouse *km = pi->driverPrivate;
- unsigned char event[MAX_MOUSE];
- int ne;
- int c;
- int i;
- int timeout;
-
- timeout = 0;
- ne = 0;
- for(;;)
- {
- c = MouseReadByte (&km->iob, timeout);
- if (c == -1)
- {
- if (ne)
- {
- km->invalid += ne + km->tested;
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseBroken;
- }
- break;
- }
- event[ne++] = c;
- i = (*km->prot->Valid) (pi, event, ne);
- if (i != 0)
- {
-#ifdef DEBUG
- ErrorF ("Mouse protocol %s broken %d of %d bytes bad\n",
- km->prot->name, i > 0 ? i : ne, ne);
-#endif
- if (i > 0 && i < ne)
- {
- ne -= i;
- memmove (event, event + i, ne);
- }
- else
- {
- i = ne;
- ne = 0;
- }
- km->invalid += i + km->tested;
- km->valid = 0;
- km->tested = 0;
- if (km->stage == MouseWorking)
- km->i_prot--;
- km->stage = MouseBroken;
- if (km->invalid > MAX_SKIP)
- {
- MouseNextProtocol (km);
- ne = 0;
- }
- timeout = 0;
- }
- else
- {
- if ((*km->prot->Complete) (pi, event, ne))
- {
- if ((*km->prot->Parse) (pi, event, ne))
- {
- switch (km->stage)
- {
- case MouseBroken:
-#ifdef DEBUG
- ErrorF ("Mouse protocol %s seems OK\n",
- km->prot->name);
-#endif
- /* do not zero invalid to accumulate invalid bytes */
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseTesting;
- /* fall through ... */
- case MouseTesting:
- km->valid++;
- km->tested += ne;
- if (km->valid > MAX_VALID)
- {
-#ifdef DEBUG
- ErrorF ("Mouse protocol %s working\n",
- km->prot->name);
-#endif
- km->stage = MouseWorking;
- km->invalid = 0;
- km->tested = 0;
- km->valid = 0;
- if (km->prot->Init && !(*km->prot->Init) (pi))
- km->stage = MouseBroken;
- }
- break;
- case MouseWorking:
- break;
- }
- }
- else
- {
- km->invalid += ne + km->tested;
- km->valid = 0;
- km->tested = 0;
- km->stage = MouseBroken;
- }
- ne = 0;
- timeout = 0;
- }
- else
- timeout = MOUSE_TIMEOUT;
- }
- }
-}
-
-int MouseInputType;
-
-char *kdefaultMouse[] = {
- "/dev/input/mice",
- "/dev/mouse",
- "/dev/psaux",
- "/dev/adbmouse",
- "/dev/ttyS0",
- "/dev/ttyS1",
-};
-
-#define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))
-
-static Status
-MouseInit (KdPointerInfo *pi)
-{
- int i;
- int fd;
- Kmouse *km;
-
- if (!pi)
- return BadImplementation;
-
- if (!pi->path || strcmp(pi->path, "auto") == 0) {
- for (i = 0; i < NUM_DEFAULT_MOUSE; i++) {
- fd = open (kdefaultMouse[i], 2);
- if (fd >= 0) {
- pi->path = strdup (kdefaultMouse[i]);
- break;
- }
- }
- }
- else {
- fd = open (pi->path, 2);
- }
-
- if (fd < 0)
- return BadMatch;
-
- close(fd);
-
- km = (Kmouse *) malloc(sizeof (Kmouse));
- if (km) {
- km->iob.avail = km->iob.used = 0;
- MouseFirstProtocol(km, pi->protocol ? pi->protocol : "exps/2");
- /* MouseFirstProtocol sets state to MouseBroken for later protocol
- * checks. Skip these checks if a protocol was supplied */
- if (pi->protocol)
- km->state = MouseWorking;
- km->i_prot = 0;
- km->tty = isatty (fd);
- km->iob.fd = -1;
- pi->driverPrivate = km;
- }
- else {
- close (fd);
- return BadAlloc;
- }
-
- return Success;
-}
-
-static Status
-MouseEnable (KdPointerInfo *pi)
-{
- Kmouse *km;
-
- if (!pi || !pi->driverPrivate || !pi->path)
- return BadImplementation;
-
- km = pi->driverPrivate;
-
- km->iob.fd = open(pi->path, 2);
- if (km->iob.fd < 0)
- return BadMatch;
-
- if (!KdRegisterFd (km->iob.fd, MouseRead, pi))
- {
- close(km->iob.fd);
- return BadAlloc;
- }
-
- return Success;
-}
-
-static void
-MouseDisable (KdPointerInfo *pi)
-{
- Kmouse *km;
- if (!pi || !pi->driverPrivate)
- return;
-
- km = pi->driverPrivate;
- KdUnregisterFd (pi, km->iob.fd, TRUE);
-}
-
-static void
-MouseFini (KdPointerInfo *pi)
-{
- free(pi->driverPrivate);
- pi->driverPrivate = NULL;
-}
-
-KdPointerDriver LinuxMouseDriver = {
- "mouse",
- MouseInit,
- MouseEnable,
- MouseDisable,
- MouseFini,
- NULL,
-};
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include <errno.h>
+#include <termios.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xpoll.h>
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "kdrive.h"
+
+#undef DEBUG
+#undef DEBUG_BYTES
+#define KBUFIO_SIZE 256
+#define MOUSE_TIMEOUT 100
+
+typedef struct _kbufio {
+ int fd;
+ unsigned char buf[KBUFIO_SIZE];
+ int avail;
+ int used;
+} Kbufio;
+
+static Bool
+MouseWaitForReadable (int fd, int timeout)
+{
+ fd_set set;
+ struct timeval tv, *tp;
+ int n;
+ CARD32 done;
+
+ done = GetTimeInMillis () + timeout;
+ for (;;)
+ {
+ FD_ZERO (&set);
+ FD_SET (fd, &set);
+ if (timeout == -1)
+ tp = 0;
+ else
+ {
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ tp = &tv;
+ }
+ n = select (fd + 1, &set, 0, 0, tp);
+ if (n > 0)
+ return TRUE;
+ if (n < 0 && (errno == EAGAIN || errno == EINTR))
+ {
+ timeout = (int) (done - GetTimeInMillis ());
+ if (timeout > 0)
+ continue;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static int
+MouseReadByte (Kbufio *b, int timeout)
+{
+ int n;
+ if (b->avail <= b->used)
+ {
+ if (timeout && !MouseWaitForReadable (b->fd, timeout))
+ {
+#ifdef DEBUG_BYTES
+ ErrorF ("\tTimeout %d\n", timeout);
+#endif
+ return -1;
+ }
+ n = read (b->fd, b->buf, KBUFIO_SIZE);
+ if (n <= 0)
+ return -1;
+ b->avail = n;
+ b->used = 0;
+ }
+#ifdef DEBUG_BYTES
+ ErrorF ("\tget %02x\n", b->buf[b->used]);
+#endif
+ return b->buf[b->used++];
+}
+
+#if NOTUSED
+static int
+MouseFlush (Kbufio *b, char *buf, int size)
+{
+ CARD32 now = GetTimeInMillis ();
+ CARD32 done = now + 100;
+ int c;
+ int n = 0;
+
+ while ((c = MouseReadByte (b, done - now)) != -1)
+ {
+ if (buf)
+ {
+ if (n == size)
+ {
+ memmove (buf, buf + 1, size - 1);
+ n--;
+ }
+ buf[n++] = c;
+ }
+ now = GetTimeInMillis ();
+ if ((INT32) (now - done) >= 0)
+ break;
+ }
+ return n;
+}
+
+static int
+MousePeekByte (Kbufio *b, int timeout)
+{
+ int c;
+
+ c = MouseReadByte (b, timeout);
+ if (c != -1)
+ --b->used;
+ return c;
+}
+#endif /* NOTUSED */
+
+static Bool
+MouseWaitForWritable (int fd, int timeout)
+{
+ fd_set set;
+ struct timeval tv, *tp;
+ int n;
+
+ FD_ZERO (&set);
+ FD_SET (fd, &set);
+ if (timeout == -1)
+ tp = 0;
+ else
+ {
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ tp = &tv;
+ }
+ n = select (fd + 1, 0, &set, 0, tp);
+ if (n > 0)
+ return TRUE;
+ return FALSE;
+}
+
+static Bool
+MouseWriteByte (int fd, unsigned char c, int timeout)
+{
+ int ret;
+
+#ifdef DEBUG_BYTES
+ ErrorF ("\tput %02x\n", c);
+#endif
+ for (;;)
+ {
+ ret = write (fd, &c, 1);
+ if (ret == 1)
+ return TRUE;
+ if (ret == 0)
+ return FALSE;
+ if (errno != EWOULDBLOCK)
+ return FALSE;
+ if (!MouseWaitForWritable (fd, timeout))
+ return FALSE;
+ }
+}
+
+static Bool
+MouseWriteBytes (int fd, unsigned char *c, int n, int timeout)
+{
+ while (n--)
+ if (!MouseWriteByte (fd, *c++, timeout))
+ return FALSE;
+ return TRUE;
+}
+
+#define MAX_MOUSE 10 /* maximum length of mouse protocol */
+#define MAX_SKIP 16 /* number of error bytes before switching */
+#define MAX_VALID 4 /* number of valid packets before accepting */
+
+typedef struct _kmouseProt {
+ char *name;
+ Bool (*Complete) (KdPointerInfo *pi, unsigned char *ev, int ne);
+ int (*Valid) (KdPointerInfo *pi, unsigned char *ev, int ne);
+ Bool (*Parse) (KdPointerInfo *pi, unsigned char *ev, int ne);
+ Bool (*Init) (KdPointerInfo *pi);
+ unsigned char headerMask, headerValid;
+ unsigned char dataMask, dataValid;
+ Bool tty;
+ unsigned int c_iflag;
+ unsigned int c_oflag;
+ unsigned int c_lflag;
+ unsigned int c_cflag;
+ unsigned int speed;
+ unsigned char *init;
+ unsigned long state;
+} KmouseProt;
+
+typedef enum _kmouseStage {
+ MouseBroken, MouseTesting, MouseWorking
+} KmouseStage;
+
+typedef struct _kmouse {
+ Kbufio iob;
+ const KmouseProt *prot;
+ int i_prot;
+ KmouseStage stage; /* protocol verification stage */
+ Bool tty; /* mouse device is a tty */
+ int valid; /* sequential valid events */
+ int tested; /* bytes scanned during Testing phase */
+ int invalid;/* total invalid bytes for this protocol */
+ unsigned long state; /* private per protocol, init to prot->state */
+} Kmouse;
+
+static int mouseValid (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ Kmouse *km = pi->driverPrivate;
+ const KmouseProt *prot = km->prot;
+ int i;
+
+ for (i = 0; i < ne; i++)
+ if ((ev[i] & prot->headerMask) == prot->headerValid)
+ break;
+ if (i != 0)
+ return i;
+ for (i = 1; i < ne; i++)
+ if ((ev[i] & prot->dataMask) != prot->dataValid)
+ return -1;
+ return 0;
+}
+
+static Bool threeComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ return ne == 3;
+}
+
+static Bool fourComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ return ne == 4;
+}
+
+static Bool fiveComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ return ne == 5;
+}
+
+static Bool MouseReasonable (KdPointerInfo *pi, unsigned long flags, int dx, int dy)
+{
+ Kmouse *km = pi->driverPrivate;
+
+ if (km->stage == MouseWorking)
+ return TRUE;
+ if (dx < -50 || dx > 50)
+ {
+#ifdef DEBUG
+ ErrorF ("Large X %d\n", dx);
+#endif
+ return FALSE;
+ }
+ if (dy < -50 || dy > 50)
+ {
+#ifdef DEBUG
+ ErrorF ("Large Y %d\n", dy);
+#endif
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Standard PS/2 mouse protocol
+ */
+static Bool ps2Parse (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ Kmouse *km = pi->driverPrivate;
+ int dx, dy, dz;
+ unsigned long flags;
+ unsigned long flagsrelease = 0;
+
+ flags = KD_MOUSE_DELTA;
+ if (ev[0] & 4)
+ flags |= KD_BUTTON_2;
+ if (ev[0] & 2)
+ flags |= KD_BUTTON_3;
+ if (ev[0] & 1)
+ flags |= KD_BUTTON_1;
+
+ if (ne > 3)
+ {
+ dz = (int) (signed char) ev[3];
+ if (dz < 0)
+ {
+ flags |= KD_BUTTON_4;
+ flagsrelease = KD_BUTTON_4;
+ }
+ else if (dz > 0)
+ {
+ flags |= KD_BUTTON_5;
+ flagsrelease = KD_BUTTON_5;
+ }
+ }
+
+ dx = ev[1];
+ if (ev[0] & 0x10)
+ dx -= 256;
+ dy = ev[2];
+ if (ev[0] & 0x20)
+ dy -= 256;
+ dy = -dy;
+ if (!MouseReasonable (pi, flags, dx, dy))
+ return FALSE;
+ if (km->stage == MouseWorking)
+ {
+ KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
+ if (flagsrelease)
+ {
+ flags &= ~flagsrelease;
+ KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
+ }
+ }
+ return TRUE;
+}
+
+static Bool ps2Init (KdPointerInfo *pi);
+
+static const KmouseProt ps2Prot = {
+ "ps/2",
+ threeComplete, mouseValid, ps2Parse, ps2Init,
+ 0x08, 0x08, 0x00, 0x00,
+ FALSE
+};
+
+static const KmouseProt imps2Prot = {
+ "imps/2",
+ fourComplete, mouseValid, ps2Parse, ps2Init,
+ 0x08, 0x08, 0x00, 0x00,
+ FALSE
+};
+
+static const KmouseProt exps2Prot = {
+ "exps/2",
+ fourComplete, mouseValid, ps2Parse, ps2Init,
+ 0x08, 0x08, 0x00, 0x00,
+ FALSE
+};
+
+/*
+ * Once the mouse is known to speak ps/2 protocol, go and find out
+ * what advanced capabilities it has and turn them on
+ */
+
+/* these extracted from FreeBSD 4.3 sys/dev/kbd/atkbdcreg.h */
+
+/* aux device commands (sent to KBD_DATA_PORT) */
+#define PSMC_SET_SCALING11 0x00e6
+#define PSMC_SET_SCALING21 0x00e7
+#define PSMC_SET_RESOLUTION 0x00e8
+#define PSMC_SEND_DEV_STATUS 0x00e9
+#define PSMC_SET_STREAM_MODE 0x00ea
+#define PSMC_SEND_DEV_DATA 0x00eb
+#define PSMC_SET_REMOTE_MODE 0x00f0
+#define PSMC_SEND_DEV_ID 0x00f2
+#define PSMC_SET_SAMPLING_RATE 0x00f3
+#define PSMC_ENABLE_DEV 0x00f4
+#define PSMC_DISABLE_DEV 0x00f5
+#define PSMC_SET_DEFAULTS 0x00f6
+#define PSMC_RESET_DEV 0x00ff
+
+/* PSMC_SET_RESOLUTION argument */
+#define PSMD_RES_LOW 0 /* typically 25ppi */
+#define PSMD_RES_MEDIUM_LOW 1 /* typically 50ppi */
+#define PSMD_RES_MEDIUM_HIGH 2 /* typically 100ppi (default) */
+#define PSMD_RES_HIGH 3 /* typically 200ppi */
+#define PSMD_MAX_RESOLUTION PSMD_RES_HIGH
+
+/* PSMC_SET_SAMPLING_RATE */
+#define PSMD_MAX_RATE 255 /* FIXME: not sure if it's possible */
+
+/* aux device ID */
+#define PSM_MOUSE_ID 0
+#define PSM_BALLPOINT_ID 2
+#define PSM_INTELLI_ID 3
+#define PSM_EXPLORER_ID 4
+#define PSM_4DMOUSE_ID 6
+#define PSM_4DPLUS_ID 8
+
+static unsigned char ps2_init[] = {
+ PSMC_ENABLE_DEV,
+ 0,
+};
+
+#define NINIT_PS2 1
+
+static unsigned char wheel_3button_init[] = {
+ PSMC_SET_SAMPLING_RATE, 200,
+ PSMC_SET_SAMPLING_RATE, 100,
+ PSMC_SET_SAMPLING_RATE, 80,
+ PSMC_SEND_DEV_ID,
+ 0,
+};
+
+#define NINIT_IMPS2 4
+
+static unsigned char wheel_5button_init[] = {
+ PSMC_SET_SAMPLING_RATE, 200,
+ PSMC_SET_SAMPLING_RATE, 100,
+ PSMC_SET_SAMPLING_RATE, 80,
+ PSMC_SET_SAMPLING_RATE, 200,
+ PSMC_SET_SAMPLING_RATE, 200,
+ PSMC_SET_SAMPLING_RATE, 80,
+ PSMC_SEND_DEV_ID,
+ 0
+};
+
+#define NINIT_EXPS2 7
+
+static unsigned char intelli_init[] = {
+ PSMC_SET_SAMPLING_RATE, 200,
+ PSMC_SET_SAMPLING_RATE, 100,
+ PSMC_SET_SAMPLING_RATE, 80,
+ 0
+};
+
+#define NINIT_INTELLI 3
+
+static int
+ps2SkipInit (KdPointerInfo *pi, int ninit, Bool ret_next)
+{
+ Kmouse *km = pi->driverPrivate;
+ int c = -1;
+ int skipping;
+ Bool waiting;
+
+ skipping = 0;
+ waiting = FALSE;
+ while (ninit || ret_next)
+ {
+ c = MouseReadByte (&km->iob, MOUSE_TIMEOUT);
+ if (c == -1)
+ break;
+ /* look for ACK */
+ if (c == 0xfa)
+ {
+ ninit--;
+ if (ret_next)
+ waiting = TRUE;
+ }
+ /* look for packet start -- not the response */
+ else if ((c & 0x08) == 0x08)
+ waiting = FALSE;
+ else if (waiting)
+ break;
+ }
+ return c;
+}
+
+static Bool
+ps2Init (KdPointerInfo *pi)
+{
+ Kmouse *km = pi->driverPrivate;
+ int skipping;
+ Bool waiting;
+ int id;
+ unsigned char *init;
+ int ninit;
+
+ /* Send Intellimouse initialization sequence */
+ MouseWriteBytes (km->iob.fd, intelli_init, strlen ((char *) intelli_init), 100);
+ /*
+ * Send ID command
+ */
+ if (!MouseWriteByte (km->iob.fd, PSMC_SEND_DEV_ID, 100))
+ return FALSE;
+ skipping = 0;
+ waiting = FALSE;
+ id = ps2SkipInit (pi, 0, TRUE);
+ switch (id) {
+ case 3:
+ init = wheel_3button_init;
+ ninit = NINIT_IMPS2;
+ km->prot = &imps2Prot;
+ break;
+ case 4:
+ init = wheel_5button_init;
+ ninit = NINIT_EXPS2;
+ km->prot = &exps2Prot;
+ break;
+ default:
+ init = ps2_init;
+ ninit = NINIT_PS2;
+ km->prot = &ps2Prot;
+ break;
+ }
+ if (init)
+ MouseWriteBytes (km->iob.fd, init, strlen ((char *) init), 100);
+ /*
+ * Flush out the available data to eliminate responses to the
+ * initialization string. Make sure any partial event is
+ * skipped
+ */
+ (void) ps2SkipInit (pi, ninit, FALSE);
+ return TRUE;
+}
+
+static Bool busParse (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ Kmouse *km = pi->driverPrivate;
+ int dx, dy;
+ unsigned long flags;
+
+ flags = KD_MOUSE_DELTA;
+ dx = (signed char) ev[1];
+ dy = -(signed char) ev[2];
+ if ((ev[0] & 4) == 0)
+ flags |= KD_BUTTON_1;
+ if ((ev[0] & 2) == 0)
+ flags |= KD_BUTTON_2;
+ if ((ev[0] & 1) == 0)
+ flags |= KD_BUTTON_3;
+ if (!MouseReasonable (pi, flags, dx, dy))
+ return FALSE;
+ if (km->stage == MouseWorking)
+ KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
+ return TRUE;
+}
+
+static const KmouseProt busProt = {
+ "bus",
+ threeComplete, mouseValid, busParse, 0,
+ 0xf8, 0x00, 0x00, 0x00,
+ FALSE
+};
+
+/*
+ * Standard MS serial protocol, three bytes
+ */
+
+static Bool msParse (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ Kmouse *km = pi->driverPrivate;
+ int dx, dy;
+ unsigned long flags;
+
+ flags = KD_MOUSE_DELTA;
+
+ if (ev[0] & 0x20)
+ flags |= KD_BUTTON_1;
+ if (ev[0] & 0x10)
+ flags |= KD_BUTTON_3;
+
+ dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
+ dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
+ if (!MouseReasonable (pi, flags, dx, dy))
+ return FALSE;
+ if (km->stage == MouseWorking)
+ KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
+ return TRUE;
+}
+
+static const KmouseProt msProt = {
+ "ms",
+ threeComplete, mouseValid, msParse, 0,
+ 0xc0, 0x40, 0xc0, 0x00,
+ TRUE,
+ IGNPAR,
+ 0,
+ 0,
+ CS7 | CSTOPB | CREAD | CLOCAL,
+ B1200,
+};
+
+/*
+ * Logitech mice send 3 or 4 bytes, the only way to tell is to look at the
+ * first byte of a synchronized protocol stream and see if it's got
+ * any bits turned on that can't occur in that fourth byte
+ */
+static Bool logiComplete (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ Kmouse *km = pi->driverPrivate;
+
+ if ((ev[0] & 0x40) == 0x40)
+ return ne == 3;
+ if (km->stage != MouseBroken && (ev[0] & ~0x23) == 0)
+ return ne == 1;
+ return FALSE;
+}
+
+static int logiValid (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ Kmouse *km = pi->driverPrivate;
+ const KmouseProt *prot = km->prot;
+ int i;
+
+ for (i = 0; i < ne; i++)
+ {
+ if ((ev[i] & 0x40) == 0x40)
+ break;
+ if (km->stage != MouseBroken && (ev[i] & ~0x23) == 0)
+ break;
+ }
+ if (i != 0)
+ return i;
+ for (i = 1; i < ne; i++)
+ if ((ev[i] & prot->dataMask) != prot->dataValid)
+ return -1;
+ return 0;
+}
+
+static Bool logiParse (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ Kmouse *km = pi->driverPrivate;
+ int dx, dy;
+ unsigned long flags;
+
+ flags = KD_MOUSE_DELTA;
+
+ if (ne == 3)
+ {
+ if (ev[0] & 0x20)
+ flags |= KD_BUTTON_1;
+ if (ev[0] & 0x10)
+ flags |= KD_BUTTON_3;
+
+ dx = (signed char)(((ev[0] & 0x03) << 6) | (ev[1] & 0x3F));
+ dy = (signed char)(((ev[0] & 0x0C) << 4) | (ev[2] & 0x3F));
+ flags |= km->state & KD_BUTTON_2;
+ }
+ else
+ {
+ if (ev[0] & 0x20)
+ flags |= KD_BUTTON_2;
+ dx = 0;
+ dy = 0;
+ flags |= km->state & (KD_BUTTON_1|KD_BUTTON_3);
+ }
+
+ if (!MouseReasonable (pi, flags, dx, dy))
+ return FALSE;
+ if (km->stage == MouseWorking)
+ KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
+ return TRUE;
+}
+
+static const KmouseProt logiProt = {
+ "logitech",
+ logiComplete, logiValid, logiParse, 0,
+ 0xc0, 0x40, 0xc0, 0x00,
+ TRUE,
+ IGNPAR,
+ 0,
+ 0,
+ CS7 | CSTOPB | CREAD | CLOCAL,
+ B1200,
+};
+
+/*
+ * Mouse systems protocol, 5 bytes
+ */
+static Bool mscParse (KdPointerInfo *pi, unsigned char *ev, int ne)
+{
+ Kmouse *km = pi->driverPrivate;
+ int dx, dy;
+ unsigned long flags;
+
+ flags = KD_MOUSE_DELTA;
+
+ if (!(ev[0] & 0x4))
+ flags |= KD_BUTTON_1;
+ if (!(ev[0] & 0x2))
+ flags |= KD_BUTTON_2;
+ if (!(ev[0] & 0x1))
+ flags |= KD_BUTTON_3;
+ dx = (signed char)(ev[1]) + (signed char)(ev[3]);
+ dy = - ((signed char)(ev[2]) + (signed char)(ev[4]));
+
+ if (!MouseReasonable (pi, flags, dx, dy))
+ return FALSE;
+ if (km->stage == MouseWorking)
+ KdEnqueuePointerEvent (pi, flags, dx, dy, 0);
+ return TRUE;
+}
+
+static const KmouseProt mscProt = {
+ "msc",
+ fiveComplete, mouseValid, mscParse, 0,
+ 0xf8, 0x80, 0x00, 0x00,
+ TRUE,
+ IGNPAR,
+ 0,
+ 0,
+ CS8 | CSTOPB | CREAD | CLOCAL,
+ B1200,
+};
+
+/*
+ * Use logitech before ms -- they're the same except that
+ * logitech sometimes has a fourth byte
+ */
+static const KmouseProt *kmouseProts[] = {
+ &ps2Prot, &imps2Prot, &exps2Prot, &busProt, &logiProt, &msProt, &mscProt,
+};
+
+#define NUM_PROT (sizeof (kmouseProts) / sizeof (kmouseProts[0]))
+
+static void
+MouseInitProtocol (Kmouse *km)
+{
+ int ret;
+ struct termios t;
+
+ if (km->prot->tty)
+ {
+ ret = tcgetattr (km->iob.fd, &t);
+
+ if (ret >= 0)
+ {
+ t.c_iflag = km->prot->c_iflag;
+ t.c_oflag = km->prot->c_oflag;
+ t.c_lflag = km->prot->c_lflag;
+ t.c_cflag = km->prot->c_cflag;
+ cfsetispeed (&t, km->prot->speed);
+ cfsetospeed (&t, km->prot->speed);
+ ret = tcsetattr (km->iob.fd, TCSANOW, &t);
+ }
+ }
+ km->stage = MouseBroken;
+ km->valid = 0;
+ km->tested = 0;
+ km->invalid = 0;
+ km->state = km->prot->state;
+}
+
+static void
+MouseFirstProtocol (Kmouse *km, char *prot)
+{
+ if (prot)
+ {
+ for (km->i_prot = 0; km->i_prot < NUM_PROT; km->i_prot++)
+ if (!strcmp (prot, kmouseProts[km->i_prot]->name))
+ break;
+ if (km->i_prot == NUM_PROT)
+ {
+ int i;
+ ErrorF ("Unknown mouse protocol \"%s\". Pick one of:", prot);
+ for (i = 0; i < NUM_PROT; i++)
+ ErrorF (" %s", kmouseProts[i]->name);
+ ErrorF ("\n");
+ }
+ else
+ {
+ km->prot = kmouseProts[km->i_prot];
+ if (km->tty && !km->prot->tty)
+ ErrorF ("Mouse device is serial port, protocol %s is not serial protocol\n",
+ prot);
+ else if (!km->tty && km->prot->tty)
+ ErrorF ("Mouse device is not serial port, protocol %s is serial protocol\n",
+ prot);
+ }
+ }
+ if (!km->prot)
+ {
+ for (km->i_prot = 0; kmouseProts[km->i_prot]->tty != km->tty; km->i_prot++)
+ ;
+ km->prot = kmouseProts[km->i_prot];
+ }
+ MouseInitProtocol (km);
+}
+
+static void
+MouseNextProtocol (Kmouse *km)
+{
+ do
+ {
+ if (!km->prot)
+ km->i_prot = 0;
+ else
+ if (++km->i_prot == NUM_PROT) km->i_prot = 0;
+ km->prot = kmouseProts[km->i_prot];
+ } while (km->prot->tty != km->tty);
+ MouseInitProtocol (km);
+ ErrorF ("Switching to mouse protocol \"%s\"\n", km->prot->name);
+}
+
+static void
+MouseRead (int mousePort, void *closure)
+{
+ KdPointerInfo *pi = closure;
+ Kmouse *km = pi->driverPrivate;
+ unsigned char event[MAX_MOUSE];
+ int ne;
+ int c;
+ int i;
+ int timeout;
+
+ timeout = 0;
+ ne = 0;
+ for(;;)
+ {
+ c = MouseReadByte (&km->iob, timeout);
+ if (c == -1)
+ {
+ if (ne)
+ {
+ km->invalid += ne + km->tested;
+ km->valid = 0;
+ km->tested = 0;
+ km->stage = MouseBroken;
+ }
+ break;
+ }
+ event[ne++] = c;
+ i = (*km->prot->Valid) (pi, event, ne);
+ if (i != 0)
+ {
+#ifdef DEBUG
+ ErrorF ("Mouse protocol %s broken %d of %d bytes bad\n",
+ km->prot->name, i > 0 ? i : ne, ne);
+#endif
+ if (i > 0 && i < ne)
+ {
+ ne -= i;
+ memmove (event, event + i, ne);
+ }
+ else
+ {
+ i = ne;
+ ne = 0;
+ }
+ km->invalid += i + km->tested;
+ km->valid = 0;
+ km->tested = 0;
+ if (km->stage == MouseWorking)
+ km->i_prot--;
+ km->stage = MouseBroken;
+ if (km->invalid > MAX_SKIP)
+ {
+ MouseNextProtocol (km);
+ ne = 0;
+ }
+ timeout = 0;
+ }
+ else
+ {
+ if ((*km->prot->Complete) (pi, event, ne))
+ {
+ if ((*km->prot->Parse) (pi, event, ne))
+ {
+ switch (km->stage)
+ {
+ case MouseBroken:
+#ifdef DEBUG
+ ErrorF ("Mouse protocol %s seems OK\n",
+ km->prot->name);
+#endif
+ /* do not zero invalid to accumulate invalid bytes */
+ km->valid = 0;
+ km->tested = 0;
+ km->stage = MouseTesting;
+ /* fall through ... */
+ case MouseTesting:
+ km->valid++;
+ km->tested += ne;
+ if (km->valid > MAX_VALID)
+ {
+#ifdef DEBUG
+ ErrorF ("Mouse protocol %s working\n",
+ km->prot->name);
+#endif
+ km->stage = MouseWorking;
+ km->invalid = 0;
+ km->tested = 0;
+ km->valid = 0;
+ if (km->prot->Init && !(*km->prot->Init) (pi))
+ km->stage = MouseBroken;
+ }
+ break;
+ case MouseWorking:
+ break;
+ }
+ }
+ else
+ {
+ km->invalid += ne + km->tested;
+ km->valid = 0;
+ km->tested = 0;
+ km->stage = MouseBroken;
+ }
+ ne = 0;
+ timeout = 0;
+ }
+ else
+ timeout = MOUSE_TIMEOUT;
+ }
+ }
+}
+
+int MouseInputType;
+
+char *kdefaultMouse[] = {
+ "/dev/input/mice",
+ "/dev/mouse",
+ "/dev/psaux",
+ "/dev/adbmouse",
+ "/dev/ttyS0",
+ "/dev/ttyS1",
+};
+
+#define NUM_DEFAULT_MOUSE (sizeof (kdefaultMouse) / sizeof (kdefaultMouse[0]))
+
+static Status
+MouseInit (KdPointerInfo *pi)
+{
+ int i;
+ int fd;
+ Kmouse *km;
+
+ if (!pi)
+ return BadImplementation;
+
+ if (!pi->path || strcmp(pi->path, "auto") == 0) {
+ for (i = 0; i < NUM_DEFAULT_MOUSE; i++) {
+ fd = open (kdefaultMouse[i], 2);
+ if (fd >= 0) {
+ pi->path = strdup (kdefaultMouse[i]);
+ break;
+ }
+ }
+ }
+ else {
+ fd = open (pi->path, 2);
+ }
+
+ if (fd < 0)
+ return BadMatch;
+
+ close(fd);
+
+ km = (Kmouse *) malloc(sizeof (Kmouse));
+ if (km) {
+ km->iob.avail = km->iob.used = 0;
+ MouseFirstProtocol(km, pi->protocol ? pi->protocol : "exps/2");
+ /* MouseFirstProtocol sets state to MouseBroken for later protocol
+ * checks. Skip these checks if a protocol was supplied */
+ if (pi->protocol)
+ km->state = MouseWorking;
+ km->i_prot = 0;
+ km->tty = isatty (fd);
+ km->iob.fd = -1;
+ pi->driverPrivate = km;
+ }
+ else {
+ close (fd);
+ return BadAlloc;
+ }
+
+ return Success;
+}
+
+static Status
+MouseEnable (KdPointerInfo *pi)
+{
+ Kmouse *km;
+
+ if (!pi || !pi->driverPrivate || !pi->path)
+ return BadImplementation;
+
+ km = pi->driverPrivate;
+
+ km->iob.fd = open(pi->path, 2);
+ if (km->iob.fd < 0)
+ return BadMatch;
+
+ if (!KdRegisterFd (km->iob.fd, MouseRead, pi))
+ {
+ close(km->iob.fd);
+ return BadAlloc;
+ }
+
+ return Success;
+}
+
+static void
+MouseDisable (KdPointerInfo *pi)
+{
+ Kmouse *km;
+ if (!pi || !pi->driverPrivate)
+ return;
+
+ km = pi->driverPrivate;
+ KdUnregisterFd (pi, km->iob.fd, TRUE);
+}
+
+static void
+MouseFini (KdPointerInfo *pi)
+{
+ free(pi->driverPrivate);
+ pi->driverPrivate = NULL;
+}
+
+KdPointerDriver LinuxMouseDriver = {
+ "mouse",
+ MouseInit,
+ MouseEnable,
+ MouseDisable,
+ MouseFini,
+ NULL,
+};
diff --git a/xorg-server/hw/kdrive/linux/ps2.c b/xorg-server/hw/kdrive/linux/ps2.c
index 552a3c7cb..465b963f2 100644
--- a/xorg-server/hw/kdrive/linux/ps2.c
+++ b/xorg-server/hw/kdrive/linux/ps2.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 1999 Keith Packard
+ * Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
diff --git a/xorg-server/hw/kdrive/linux/tslib.c b/xorg-server/hw/kdrive/linux/tslib.c
index 8d6007390..1f30ccae7 100644
--- a/xorg-server/hw/kdrive/linux/tslib.c
+++ b/xorg-server/hw/kdrive/linux/tslib.c
@@ -1,197 +1,197 @@
-/*
- * TSLIB based touchscreen driver for KDrive
- * Porting to new input API and event queueing by Daniel Stone.
- * Derived from ts.c by Keith Packard
- * Derived from ps2.c by Jim Gettys
- *
- * Copyright © 1999 Keith Packard
- * Copyright © 2000 Compaq Computer Corporation
- * Copyright © 2002 MontaVista Software Inc.
- * Copyright © 2005 OpenedHand Ltd.
- * Copyright © 2006 Nokia Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the authors and/or copyright holders
- * not be used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. The authors and/or
- * copyright holders make no representations about the suitability of this
- * software for any purpose. It is provided "as is" without express or
- * implied warranty.
- *
- * THE AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
- * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-#ifdef HAVE_KDRIVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xpoll.h>
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "kdrive.h"
-#include <sys/ioctl.h>
-#include <tslib.h>
-#include <dirent.h>
-#include <linux/input.h>
-
-struct TslibPrivate {
- int fd;
- int lastx, lasty;
- struct tsdev *tsDev;
- void (*raw_event_hook)(int x, int y, int pressure, void *closure);
- void *raw_event_closure;
- int phys_screen;
-};
-
-
-static void
-TsRead (int fd, void *closure)
-{
- KdPointerInfo *pi = closure;
- struct TslibPrivate *private = pi->driverPrivate;
- struct ts_sample event;
- long x = 0, y = 0;
- unsigned long flags;
-
- if (private->raw_event_hook) {
- while (ts_read_raw(private->tsDev, &event, 1) == 1)
- private->raw_event_hook (event.x, event.y, event.pressure,
- private->raw_event_closure);
- return;
- }
-
- while (ts_read(private->tsDev, &event, 1) == 1) {
- if (event.pressure) {
- flags = KD_BUTTON_1;
-
- /*
- * Here we test for the touch screen driver actually being on the
- * touch screen, if it is we send absolute coordinates. If not,
- * then we send delta's so that we can track the entire vga screen.
- */
- if (KdCurScreen == private->phys_screen) {
- x = event.x;
- y = event.y;
- } else {
- flags |= KD_MOUSE_DELTA;
- if ((private->lastx == 0) || (private->lasty == 0)) {
- x = event.x;
- y = event.y;
- } else {
- x = event.x - private->lastx;
- y = event.y - private->lasty;
- }
- }
- private->lastx = event.x;
- private->lasty = event.y;
- } else {
- flags = 0;
- x = private->lastx;
- y = private->lasty;
- }
-
- KdEnqueuePointerEvent (pi, flags, x, y, event.pressure);
- }
-}
-
-static Status
-TslibEnable (KdPointerInfo *pi)
-{
- struct TslibPrivate *private = pi->driverPrivate;
-
- private->raw_event_hook = NULL;
- private->raw_event_closure = NULL;
- if (!pi->path) {
- pi->path = strdup("/dev/input/touchscreen0");
- ErrorF("[tslib/TslibEnable] no device path given, trying %s\n", pi->path);
- }
-
- private->tsDev = ts_open(pi->path, 0);
- if (!private->tsDev) {
- ErrorF("[tslib/TslibEnable] failed to open %s\n", pi->path);
- return BadAlloc;
- }
-
- if (ts_config(private->tsDev)) {
- ErrorF("[tslib/TslibEnable] failed to load configuration\n");
- ts_close(private->tsDev);
- private->tsDev = NULL;
- return BadValue;
- }
-
- private->fd = ts_fd(private->tsDev);
-
- KdRegisterFd(private->fd, TsRead, pi);
-
- return Success;
-}
-
-
-static void
-TslibDisable (KdPointerInfo *pi)
-{
- struct TslibPrivate *private = pi->driverPrivate;
-
- if (private->fd)
- KdUnregisterFd(pi, private->fd, TRUE);
-
- if (private->tsDev)
- ts_close(private->tsDev);
-
- private->fd = 0;
- private->tsDev = NULL;
-}
-
-
-static Status
-TslibInit (KdPointerInfo *pi)
-{
- struct TslibPrivate *private = NULL;
-
- if (!pi || !pi->dixdev)
- return !Success;
-
- pi->driverPrivate = (struct TslibPrivate *)
- calloc(sizeof(struct TslibPrivate), 1);
- if (!pi->driverPrivate)
- return !Success;
-
- private = pi->driverPrivate;
- /* hacktastic */
- private->phys_screen = 0;
- pi->nAxes = 3;
- pi->name = strdup("Touchscreen");
- pi->inputClass = KD_TOUCHSCREEN;
-
- return Success;
-}
-
-
-static void
-TslibFini (KdPointerInfo *pi)
-{
- free(pi->driverPrivate);
- pi->driverPrivate = NULL;
-}
-
-
-KdPointerDriver TsDriver = {
- "tslib",
- TslibInit,
- TslibEnable,
- TslibDisable,
- TslibFini,
- NULL,
-};
+/*
+ * TSLIB based touchscreen driver for KDrive
+ * Porting to new input API and event queueing by Daniel Stone.
+ * Derived from ts.c by Keith Packard
+ * Derived from ps2.c by Jim Gettys
+ *
+ * Copyright © 1999 Keith Packard
+ * Copyright © 2000 Compaq Computer Corporation
+ * Copyright © 2002 MontaVista Software Inc.
+ * Copyright © 2005 OpenedHand Ltd.
+ * Copyright © 2006 Nokia Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors and/or copyright holders
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. The authors and/or
+ * copyright holders make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * THE AUTHORS AND/OR COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS AND/OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifdef HAVE_KDRIVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xpoll.h>
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "kdrive.h"
+#include <sys/ioctl.h>
+#include <tslib.h>
+#include <dirent.h>
+#include <linux/input.h>
+
+struct TslibPrivate {
+ int fd;
+ int lastx, lasty;
+ struct tsdev *tsDev;
+ void (*raw_event_hook)(int x, int y, int pressure, void *closure);
+ void *raw_event_closure;
+ int phys_screen;
+};
+
+
+static void
+TsRead (int fd, void *closure)
+{
+ KdPointerInfo *pi = closure;
+ struct TslibPrivate *private = pi->driverPrivate;
+ struct ts_sample event;
+ long x = 0, y = 0;
+ unsigned long flags;
+
+ if (private->raw_event_hook) {
+ while (ts_read_raw(private->tsDev, &event, 1) == 1)
+ private->raw_event_hook (event.x, event.y, event.pressure,
+ private->raw_event_closure);
+ return;
+ }
+
+ while (ts_read(private->tsDev, &event, 1) == 1) {
+ if (event.pressure) {
+ flags = KD_BUTTON_1;
+
+ /*
+ * Here we test for the touch screen driver actually being on the
+ * touch screen, if it is we send absolute coordinates. If not,
+ * then we send delta's so that we can track the entire vga screen.
+ */
+ if (KdCurScreen == private->phys_screen) {
+ x = event.x;
+ y = event.y;
+ } else {
+ flags |= KD_MOUSE_DELTA;
+ if ((private->lastx == 0) || (private->lasty == 0)) {
+ x = event.x;
+ y = event.y;
+ } else {
+ x = event.x - private->lastx;
+ y = event.y - private->lasty;
+ }
+ }
+ private->lastx = event.x;
+ private->lasty = event.y;
+ } else {
+ flags = 0;
+ x = private->lastx;
+ y = private->lasty;
+ }
+
+ KdEnqueuePointerEvent (pi, flags, x, y, event.pressure);
+ }
+}
+
+static Status
+TslibEnable (KdPointerInfo *pi)
+{
+ struct TslibPrivate *private = pi->driverPrivate;
+
+ private->raw_event_hook = NULL;
+ private->raw_event_closure = NULL;
+ if (!pi->path) {
+ pi->path = strdup("/dev/input/touchscreen0");
+ ErrorF("[tslib/TslibEnable] no device path given, trying %s\n", pi->path);
+ }
+
+ private->tsDev = ts_open(pi->path, 0);
+ if (!private->tsDev) {
+ ErrorF("[tslib/TslibEnable] failed to open %s\n", pi->path);
+ return BadAlloc;
+ }
+
+ if (ts_config(private->tsDev)) {
+ ErrorF("[tslib/TslibEnable] failed to load configuration\n");
+ ts_close(private->tsDev);
+ private->tsDev = NULL;
+ return BadValue;
+ }
+
+ private->fd = ts_fd(private->tsDev);
+
+ KdRegisterFd(private->fd, TsRead, pi);
+
+ return Success;
+}
+
+
+static void
+TslibDisable (KdPointerInfo *pi)
+{
+ struct TslibPrivate *private = pi->driverPrivate;
+
+ if (private->fd)
+ KdUnregisterFd(pi, private->fd, TRUE);
+
+ if (private->tsDev)
+ ts_close(private->tsDev);
+
+ private->fd = 0;
+ private->tsDev = NULL;
+}
+
+
+static Status
+TslibInit (KdPointerInfo *pi)
+{
+ struct TslibPrivate *private = NULL;
+
+ if (!pi || !pi->dixdev)
+ return !Success;
+
+ pi->driverPrivate = (struct TslibPrivate *)
+ calloc(sizeof(struct TslibPrivate), 1);
+ if (!pi->driverPrivate)
+ return !Success;
+
+ private = pi->driverPrivate;
+ /* hacktastic */
+ private->phys_screen = 0;
+ pi->nAxes = 3;
+ pi->name = strdup("Touchscreen");
+ pi->inputClass = KD_TOUCHSCREEN;
+
+ return Success;
+}
+
+
+static void
+TslibFini (KdPointerInfo *pi)
+{
+ free(pi->driverPrivate);
+ pi->driverPrivate = NULL;
+}
+
+
+KdPointerDriver TsDriver = {
+ "tslib",
+ TslibInit,
+ TslibEnable,
+ TslibDisable,
+ TslibFini,
+ NULL,
+};
diff --git a/xorg-server/hw/kdrive/src/kcmap.c b/xorg-server/hw/kdrive/src/kcmap.c
index 127c7a078..6e0fc1417 100644
--- a/xorg-server/hw/kdrive/src/kcmap.c
+++ b/xorg-server/hw/kdrive/src/kcmap.c
@@ -1,246 +1,246 @@
-/*
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "kdrive.h"
-
-/*
- * Put the entire colormap into the DAC
- */
-
-void
-KdSetColormap (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- ColormapPtr pCmap = pScreenPriv->pInstalledmap;
- Pixel pixels[KD_MAX_PSEUDO_SIZE];
- xrgb colors[KD_MAX_PSEUDO_SIZE];
- xColorItem defs[KD_MAX_PSEUDO_SIZE];
- int i;
-
- if (!pScreenPriv->card->cfuncs->putColors)
- return;
- if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
- return;
-
- if (!pScreenPriv->enabled)
- return;
-
- if (!pCmap)
- return;
-
- /*
- * Make DIX convert pixels into RGB values -- this handles
- * true/direct as well as pseudo/static visuals
- */
-
- for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
- pixels[i] = i;
-
- QueryColors (pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, colors, serverClient);
-
- for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
- {
- defs[i].pixel = i;
- defs[i].red = colors[i].red;
- defs[i].green = colors[i].green;
- defs[i].blue = colors[i].blue;
- defs[i].flags = DoRed|DoGreen|DoBlue;
- }
-
- (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen,
- (1 << pScreenPriv->screen->fb.depth),
- defs);
-
- /* recolor hardware cursor */
- if (pScreenPriv->card->cfuncs->recolorCursor)
- (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, 0);
-}
-
-/*
- * When the hardware is enabled, save the hardware colors and store
- * the current colormap
- */
-void
-KdEnableColormap (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
- int i;
-
- if (!pScreenPriv->card->cfuncs->putColors)
- return;
-
- if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH)
- {
- for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
- pScreenPriv->systemPalette[i].pixel = i;
- (*pScreenPriv->card->cfuncs->getColors) (pScreen,
- (1 << pScreenPriv->screen->fb.depth),
- pScreenPriv->systemPalette);
- }
- KdSetColormap (pScreen);
-}
-
-void
-KdDisableColormap (ScreenPtr pScreen)
-{
- KdScreenPriv(pScreen);
-
- if (!pScreenPriv->card->cfuncs->putColors)
- return;
-
- if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH)
- {
- (*pScreenPriv->card->cfuncs->putColors) (pScreen,
- (1 << pScreenPriv->screen->fb.depth),
- pScreenPriv->systemPalette);
- }
-}
-
-/*
- * KdInstallColormap
- *
- * This function is called when the server receives a request to install a
- * colormap or when the server needs to install one on its own, like when
- * there's no window manager running and the user has moved the pointer over
- * an X client window. It needs to build an identity Windows palette for the
- * colormap and realize it into the Windows system palette.
- */
-void
-KdInstallColormap (ColormapPtr pCmap)
-{
- KdScreenPriv(pCmap->pScreen);
-
- if (pCmap == pScreenPriv->pInstalledmap)
- return;
-
- /* Tell X clients that the installed colormap is going away. */
- if (pScreenPriv->pInstalledmap)
- WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap,
- (pointer) &(pScreenPriv->pInstalledmap->mid));
-
- /* Take note of the new installed colorscreen-> */
- pScreenPriv->pInstalledmap = pCmap;
-
- KdSetColormap (pCmap->pScreen);
-
- /* Tell X clients of the new colormap */
- WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &(pCmap->mid));
-}
-
-/*
- * KdUninstallColormap
- *
- * This function uninstalls a colormap by either installing
- * the default X colormap or erasing the installed colormap pointer.
- * The default X colormap itself cannot be uninstalled.
- */
-void
-KdUninstallColormap (ColormapPtr pCmap)
-{
- KdScreenPriv(pCmap->pScreen);
- Colormap defMapID;
- ColormapPtr defMap;
-
- /* ignore if not installed */
- if (pCmap != pScreenPriv->pInstalledmap)
- return;
-
- /* ignore attempts to uninstall default colormap */
- defMapID = pCmap->pScreen->defColormap;
- if ((Colormap) pCmap->mid == defMapID)
- return;
-
- /* install default */
- dixLookupResourceByType((pointer *)&defMap, defMapID, RT_COLORMAP,
- serverClient, DixInstallAccess);
- if (defMap)
- (*pCmap->pScreen->InstallColormap)(defMap);
- else
- {
- /* uninstall and clear colormap pointer */
- WalkTree(pCmap->pScreen, TellLostMap,
- (pointer) &(pCmap->mid));
- pScreenPriv->pInstalledmap = 0;
- }
-}
-
-int
-KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps)
-{
- KdScreenPriv(pScreen);
- int n = 0;
-
- if (pScreenPriv->pInstalledmap)
- {
- *pCmaps++ = pScreenPriv->pInstalledmap->mid;
- n++;
- }
- return n;
-}
-
-/*
- * KdStoreColors
- *
- * This function is called whenever the server receives a request to store
- * color values into one or more entries in the currently installed X
- * colormap; it can be either the default colormap or a private colorscreen->
- */
-void
-KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs)
-{
- KdScreenPriv(pCmap->pScreen);
- VisualPtr pVisual;
- xColorItem expanddefs[KD_MAX_PSEUDO_SIZE];
-
- if (pCmap != pScreenPriv->pInstalledmap)
- return;
-
- if (!pScreenPriv->card->cfuncs->putColors)
- return;
-
- if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
- return;
-
- if (!pScreenPriv->enabled)
- return;
-
- /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */
- pVisual = pCmap->pVisual;
- if ((pVisual->class | DynamicClass) == DirectColor)
- {
- /*
- * Expand DirectColor or TrueColor color values into a PseudoColor
- * format. Defer to the Color Framebuffer (CFB) code to do that.
- */
- ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs);
- pdefs = expanddefs;
- }
-
- (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs);
-
- /* recolor hardware cursor */
- if (pScreenPriv->card->cfuncs->recolorCursor)
- (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, ndef, pdefs);
-}
+/*
+ * Copyright © 1999 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include "kdrive.h"
+
+/*
+ * Put the entire colormap into the DAC
+ */
+
+void
+KdSetColormap (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ ColormapPtr pCmap = pScreenPriv->pInstalledmap;
+ Pixel pixels[KD_MAX_PSEUDO_SIZE];
+ xrgb colors[KD_MAX_PSEUDO_SIZE];
+ xColorItem defs[KD_MAX_PSEUDO_SIZE];
+ int i;
+
+ if (!pScreenPriv->card->cfuncs->putColors)
+ return;
+ if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ if (!pCmap)
+ return;
+
+ /*
+ * Make DIX convert pixels into RGB values -- this handles
+ * true/direct as well as pseudo/static visuals
+ */
+
+ for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
+ pixels[i] = i;
+
+ QueryColors (pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, colors, serverClient);
+
+ for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
+ {
+ defs[i].pixel = i;
+ defs[i].red = colors[i].red;
+ defs[i].green = colors[i].green;
+ defs[i].blue = colors[i].blue;
+ defs[i].flags = DoRed|DoGreen|DoBlue;
+ }
+
+ (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen,
+ (1 << pScreenPriv->screen->fb.depth),
+ defs);
+
+ /* recolor hardware cursor */
+ if (pScreenPriv->card->cfuncs->recolorCursor)
+ (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, 0, 0);
+}
+
+/*
+ * When the hardware is enabled, save the hardware colors and store
+ * the current colormap
+ */
+void
+KdEnableColormap (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ int i;
+
+ if (!pScreenPriv->card->cfuncs->putColors)
+ return;
+
+ if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH)
+ {
+ for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
+ pScreenPriv->systemPalette[i].pixel = i;
+ (*pScreenPriv->card->cfuncs->getColors) (pScreen,
+ (1 << pScreenPriv->screen->fb.depth),
+ pScreenPriv->systemPalette);
+ }
+ KdSetColormap (pScreen);
+}
+
+void
+KdDisableColormap (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+
+ if (!pScreenPriv->card->cfuncs->putColors)
+ return;
+
+ if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH)
+ {
+ (*pScreenPriv->card->cfuncs->putColors) (pScreen,
+ (1 << pScreenPriv->screen->fb.depth),
+ pScreenPriv->systemPalette);
+ }
+}
+
+/*
+ * KdInstallColormap
+ *
+ * This function is called when the server receives a request to install a
+ * colormap or when the server needs to install one on its own, like when
+ * there's no window manager running and the user has moved the pointer over
+ * an X client window. It needs to build an identity Windows palette for the
+ * colormap and realize it into the Windows system palette.
+ */
+void
+KdInstallColormap (ColormapPtr pCmap)
+{
+ KdScreenPriv(pCmap->pScreen);
+
+ if (pCmap == pScreenPriv->pInstalledmap)
+ return;
+
+ /* Tell X clients that the installed colormap is going away. */
+ if (pScreenPriv->pInstalledmap)
+ WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap,
+ (pointer) &(pScreenPriv->pInstalledmap->mid));
+
+ /* Take note of the new installed colorscreen-> */
+ pScreenPriv->pInstalledmap = pCmap;
+
+ KdSetColormap (pCmap->pScreen);
+
+ /* Tell X clients of the new colormap */
+ WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &(pCmap->mid));
+}
+
+/*
+ * KdUninstallColormap
+ *
+ * This function uninstalls a colormap by either installing
+ * the default X colormap or erasing the installed colormap pointer.
+ * The default X colormap itself cannot be uninstalled.
+ */
+void
+KdUninstallColormap (ColormapPtr pCmap)
+{
+ KdScreenPriv(pCmap->pScreen);
+ Colormap defMapID;
+ ColormapPtr defMap;
+
+ /* ignore if not installed */
+ if (pCmap != pScreenPriv->pInstalledmap)
+ return;
+
+ /* ignore attempts to uninstall default colormap */
+ defMapID = pCmap->pScreen->defColormap;
+ if ((Colormap) pCmap->mid == defMapID)
+ return;
+
+ /* install default */
+ dixLookupResourceByType((pointer *)&defMap, defMapID, RT_COLORMAP,
+ serverClient, DixInstallAccess);
+ if (defMap)
+ (*pCmap->pScreen->InstallColormap)(defMap);
+ else
+ {
+ /* uninstall and clear colormap pointer */
+ WalkTree(pCmap->pScreen, TellLostMap,
+ (pointer) &(pCmap->mid));
+ pScreenPriv->pInstalledmap = 0;
+ }
+}
+
+int
+KdListInstalledColormaps (ScreenPtr pScreen, Colormap *pCmaps)
+{
+ KdScreenPriv(pScreen);
+ int n = 0;
+
+ if (pScreenPriv->pInstalledmap)
+ {
+ *pCmaps++ = pScreenPriv->pInstalledmap->mid;
+ n++;
+ }
+ return n;
+}
+
+/*
+ * KdStoreColors
+ *
+ * This function is called whenever the server receives a request to store
+ * color values into one or more entries in the currently installed X
+ * colormap; it can be either the default colormap or a private colorscreen->
+ */
+void
+KdStoreColors (ColormapPtr pCmap, int ndef, xColorItem *pdefs)
+{
+ KdScreenPriv(pCmap->pScreen);
+ VisualPtr pVisual;
+ xColorItem expanddefs[KD_MAX_PSEUDO_SIZE];
+
+ if (pCmap != pScreenPriv->pInstalledmap)
+ return;
+
+ if (!pScreenPriv->card->cfuncs->putColors)
+ return;
+
+ if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
+ return;
+
+ if (!pScreenPriv->enabled)
+ return;
+
+ /* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */
+ pVisual = pCmap->pVisual;
+ if ((pVisual->class | DynamicClass) == DirectColor)
+ {
+ /*
+ * Expand DirectColor or TrueColor color values into a PseudoColor
+ * format. Defer to the Color Framebuffer (CFB) code to do that.
+ */
+ ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs);
+ pdefs = expanddefs;
+ }
+
+ (*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs);
+
+ /* recolor hardware cursor */
+ if (pScreenPriv->card->cfuncs->recolorCursor)
+ (*pScreenPriv->card->cfuncs->recolorCursor) (pCmap->pScreen, ndef, pdefs);
+}
diff --git a/xorg-server/hw/kdrive/src/kdrive.h b/xorg-server/hw/kdrive/src/kdrive.h
index 2ab535aef..9ac5a19d7 100644
--- a/xorg-server/hw/kdrive/src/kdrive.h
+++ b/xorg-server/hw/kdrive/src/kdrive.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 1999 Keith Packard
+ * Copyright © 1999 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -500,6 +500,8 @@ KdScreenInfoDispose (KdScreenInfo *si);
/* kinput.c */
void
KdInitInput(void);
+void
+KdCloseInput(void);
void
KdAddPointerDriver(KdPointerDriver *);
diff --git a/xorg-server/hw/kdrive/src/kinfo.c b/xorg-server/hw/kdrive/src/kinfo.c
index 90fe37ae9..7055fbf4a 100644
--- a/xorg-server/hw/kdrive/src/kinfo.c
+++ b/xorg-server/hw/kdrive/src/kinfo.c
@@ -1,163 +1,163 @@
-/*
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "kdrive.h"
-
-KdCardInfo *kdCardInfo;
-
-KdCardInfo *
-KdCardInfoAdd (KdCardFuncs *funcs,
- void *closure)
-{
- KdCardInfo *ci, **prev;
-
- ci = calloc(1, sizeof (KdCardInfo));
- if (!ci)
- return 0;
- for (prev = &kdCardInfo; *prev; prev = &(*prev)->next);
- *prev = ci;
- ci->cfuncs = funcs;
- ci->closure = closure;
- ci->screenList = 0;
- ci->selected = 0;
- ci->next = 0;
- return ci;
-}
-
-KdCardInfo *
-KdCardInfoLast (void)
-{
- KdCardInfo *ci;
-
- if (!kdCardInfo)
- return 0;
- for (ci = kdCardInfo; ci->next; ci = ci->next);
- return ci;
-}
-
-void
-KdCardInfoDispose (KdCardInfo *ci)
-{
- KdCardInfo **prev;
-
- for (prev = &kdCardInfo; *prev; prev = &(*prev)->next)
- if (*prev == ci)
- {
- *prev = ci->next;
- free(ci);
- break;
- }
-}
-
-KdScreenInfo *
-KdScreenInfoAdd (KdCardInfo *ci)
-{
- KdScreenInfo *si, **prev;
- int n;
-
- si = calloc(1, sizeof (KdScreenInfo));
- if (!si)
- return 0;
- for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++);
- *prev = si;
- si->next = 0;
- si->card = ci;
- si->mynum = n;
- return si;
-}
-
-void
-KdScreenInfoDispose (KdScreenInfo *si)
-{
- KdCardInfo *ci = si->card;
- KdScreenInfo **prev;
-
- for (prev = &ci->screenList; *prev; prev = &(*prev)->next) {
- if (*prev == si)
- {
- *prev = si->next;
- free(si);
- if (!ci->screenList)
- KdCardInfoDispose (ci);
- break;
- }
- }
-}
-
-KdPointerInfo *
-KdNewPointer (void)
-{
- KdPointerInfo *pi;
- int i;
-
- pi = (KdPointerInfo *)calloc(1, sizeof(KdPointerInfo));
- if (!pi)
- return NULL;
-
- pi->name = strdup("Generic Pointer");
- pi->path = NULL;
- pi->inputClass = KD_MOUSE;
- pi->driver = NULL;
- pi->driverPrivate = NULL;
- pi->next = NULL;
- pi->options = NULL;
- pi->nAxes = 3;
- pi->nButtons = KD_MAX_BUTTON;
- for (i = 1; i < KD_MAX_BUTTON; i++)
- pi->map[i] = i;
-
- return pi;
-}
-
-void
-KdFreePointer(KdPointerInfo *pi)
-{
- InputOption *option, *prev = NULL;
-
- free(pi->name);
- free(pi->path);
-
- for (option = pi->options; option; option = option->next) {
- free(prev);
- free(option->key);
- free(option->value);
- prev = option;
- }
-
- free(prev);
- free(pi);
-}
-
-void
-KdFreeKeyboard(KdKeyboardInfo *ki)
-{
- free(ki->name);
- free(ki->path);
- free(ki->xkbRules);
- free(ki->xkbModel);
- free(ki->xkbLayout);
- ki->next = NULL;
- free(ki);
-}
+/*
+ * Copyright © 1999 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include "kdrive.h"
+
+KdCardInfo *kdCardInfo;
+
+KdCardInfo *
+KdCardInfoAdd (KdCardFuncs *funcs,
+ void *closure)
+{
+ KdCardInfo *ci, **prev;
+
+ ci = calloc(1, sizeof (KdCardInfo));
+ if (!ci)
+ return 0;
+ for (prev = &kdCardInfo; *prev; prev = &(*prev)->next);
+ *prev = ci;
+ ci->cfuncs = funcs;
+ ci->closure = closure;
+ ci->screenList = 0;
+ ci->selected = 0;
+ ci->next = 0;
+ return ci;
+}
+
+KdCardInfo *
+KdCardInfoLast (void)
+{
+ KdCardInfo *ci;
+
+ if (!kdCardInfo)
+ return 0;
+ for (ci = kdCardInfo; ci->next; ci = ci->next);
+ return ci;
+}
+
+void
+KdCardInfoDispose (KdCardInfo *ci)
+{
+ KdCardInfo **prev;
+
+ for (prev = &kdCardInfo; *prev; prev = &(*prev)->next)
+ if (*prev == ci)
+ {
+ *prev = ci->next;
+ free(ci);
+ break;
+ }
+}
+
+KdScreenInfo *
+KdScreenInfoAdd (KdCardInfo *ci)
+{
+ KdScreenInfo *si, **prev;
+ int n;
+
+ si = calloc(1, sizeof (KdScreenInfo));
+ if (!si)
+ return 0;
+ for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++);
+ *prev = si;
+ si->next = 0;
+ si->card = ci;
+ si->mynum = n;
+ return si;
+}
+
+void
+KdScreenInfoDispose (KdScreenInfo *si)
+{
+ KdCardInfo *ci = si->card;
+ KdScreenInfo **prev;
+
+ for (prev = &ci->screenList; *prev; prev = &(*prev)->next) {
+ if (*prev == si)
+ {
+ *prev = si->next;
+ free(si);
+ if (!ci->screenList)
+ KdCardInfoDispose (ci);
+ break;
+ }
+ }
+}
+
+KdPointerInfo *
+KdNewPointer (void)
+{
+ KdPointerInfo *pi;
+ int i;
+
+ pi = (KdPointerInfo *)calloc(1, sizeof(KdPointerInfo));
+ if (!pi)
+ return NULL;
+
+ pi->name = strdup("Generic Pointer");
+ pi->path = NULL;
+ pi->inputClass = KD_MOUSE;
+ pi->driver = NULL;
+ pi->driverPrivate = NULL;
+ pi->next = NULL;
+ pi->options = NULL;
+ pi->nAxes = 3;
+ pi->nButtons = KD_MAX_BUTTON;
+ for (i = 1; i < KD_MAX_BUTTON; i++)
+ pi->map[i] = i;
+
+ return pi;
+}
+
+void
+KdFreePointer(KdPointerInfo *pi)
+{
+ InputOption *option, *prev = NULL;
+
+ free(pi->name);
+ free(pi->path);
+
+ for (option = pi->options; option; option = option->next) {
+ free(prev);
+ free(option->key);
+ free(option->value);
+ prev = option;
+ }
+
+ free(prev);
+ free(pi);
+}
+
+void
+KdFreeKeyboard(KdKeyboardInfo *ki)
+{
+ free(ki->name);
+ free(ki->path);
+ free(ki->xkbRules);
+ free(ki->xkbModel);
+ free(ki->xkbLayout);
+ ki->next = NULL;
+ free(ki);
+}
diff --git a/xorg-server/hw/kdrive/src/kinput.c b/xorg-server/hw/kdrive/src/kinput.c
index cdf55d7f9..c14dd8241 100644
--- a/xorg-server/hw/kdrive/src/kinput.c
+++ b/xorg-server/hw/kdrive/src/kinput.c
@@ -1,6 +1,6 @@
/*
- * Copyright © 1999 Keith Packard
- * Copyright © 2006 Nokia Corporation
+ * Copyright © 1999 Keith Packard
+ * Copyright © 2006 Nokia Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -1305,6 +1305,12 @@ KdInitInput (void)
mieqInit();
}
+void
+KdCloseInput (void)
+{
+ mieqFini();
+}
+
/*
* Middle button emulation state machine
*
@@ -2159,7 +2165,6 @@ void
ProcessInputEvents (void)
{
mieqProcessInputEvents();
- miPointerUpdateSprite(inputInfo.pointer);
if (kdSwitchPending)
KdProcessSwitch ();
KdCheckLock ();
diff --git a/xorg-server/hw/kdrive/src/kshadow.c b/xorg-server/hw/kdrive/src/kshadow.c
index 4454020f0..63bb87bc6 100644
--- a/xorg-server/hw/kdrive/src/kshadow.c
+++ b/xorg-server/hw/kdrive/src/kshadow.c
@@ -1,81 +1,81 @@
-/*
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <kdrive-config.h>
-#endif
-#include "kdrive.h"
-
-Bool
-KdShadowFbAlloc (KdScreenInfo *screen, Bool rotate)
-{
- int paddedWidth;
- void *buf;
- int width = rotate ? screen->height : screen->width;
- int height = rotate ? screen->width : screen->height;
- int bpp = screen->fb.bitsPerPixel;
-
- /* use fb computation for width */
- paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits);
- buf = malloc(paddedWidth * height);
- if (!buf)
- return FALSE;
- if (screen->fb.shadow)
- free(screen->fb.frameBuffer);
- screen->fb.shadow = TRUE;
- screen->fb.frameBuffer = buf;
- screen->fb.byteStride = paddedWidth;
- screen->fb.pixelStride = paddedWidth * 8 / bpp;
- return TRUE;
-}
-
-void
-KdShadowFbFree (KdScreenInfo *screen)
-{
- if (screen->fb.shadow)
- {
- free(screen->fb.frameBuffer);
- screen->fb.frameBuffer = 0;
- screen->fb.shadow = FALSE;
- }
-}
-
-Bool
-KdShadowSet (ScreenPtr pScreen, int randr, ShadowUpdateProc update, ShadowWindowProc window)
-{
- KdScreenPriv(pScreen);
- KdScreenInfo *screen = pScreenPriv->screen;
-
- shadowRemove (pScreen, pScreen->GetScreenPixmap(pScreen));
- if(screen->fb.shadow)
- {
- return shadowAdd (pScreen, pScreen->GetScreenPixmap(pScreen),
- update, window, randr, 0);
- }
- return TRUE;
-}
-
-void
-KdShadowUnset (ScreenPtr pScreen)
-{
- shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
-}
+/*
+ * Copyright © 1999 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include "kdrive.h"
+
+Bool
+KdShadowFbAlloc (KdScreenInfo *screen, Bool rotate)
+{
+ int paddedWidth;
+ void *buf;
+ int width = rotate ? screen->height : screen->width;
+ int height = rotate ? screen->width : screen->height;
+ int bpp = screen->fb.bitsPerPixel;
+
+ /* use fb computation for width */
+ paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof (FbBits);
+ buf = malloc(paddedWidth * height);
+ if (!buf)
+ return FALSE;
+ if (screen->fb.shadow)
+ free(screen->fb.frameBuffer);
+ screen->fb.shadow = TRUE;
+ screen->fb.frameBuffer = buf;
+ screen->fb.byteStride = paddedWidth;
+ screen->fb.pixelStride = paddedWidth * 8 / bpp;
+ return TRUE;
+}
+
+void
+KdShadowFbFree (KdScreenInfo *screen)
+{
+ if (screen->fb.shadow)
+ {
+ free(screen->fb.frameBuffer);
+ screen->fb.frameBuffer = 0;
+ screen->fb.shadow = FALSE;
+ }
+}
+
+Bool
+KdShadowSet (ScreenPtr pScreen, int randr, ShadowUpdateProc update, ShadowWindowProc window)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+
+ shadowRemove (pScreen, pScreen->GetScreenPixmap(pScreen));
+ if(screen->fb.shadow)
+ {
+ return shadowAdd (pScreen, pScreen->GetScreenPixmap(pScreen),
+ update, window, randr, 0);
+ }
+ return TRUE;
+}
+
+void
+KdShadowUnset (ScreenPtr pScreen)
+{
+ shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
+}
diff --git a/xorg-server/hw/vfb/InitInput.c b/xorg-server/hw/vfb/InitInput.c
index aba1a95fb..8836bbd7f 100644
--- a/xorg-server/hw/vfb/InitInput.c
+++ b/xorg-server/hw/vfb/InitInput.c
@@ -1,151 +1,152 @@
-/*
-
-Copyright 1993, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include "mi.h"
-#include <X11/Xproto.h>
-#include "scrnintstr.h"
-#include "inputstr.h"
-#include <X11/Xos.h>
-#include "mibstore.h"
-#include "mipointer.h"
-#include "xkbsrv.h"
-#include <X11/keysym.h>
-#include "xserver-properties.h"
-#include "exevents.h"
-#include "extinit.h"
-
-Bool
-LegalModifier(unsigned int key, DeviceIntPtr pDev)
-{
- return TRUE;
-}
-
-void
-ProcessInputEvents(void)
-{
- mieqProcessInputEvents();
-}
-
-void DDXRingBell(int volume, int pitch, int duration)
-{
-}
-
-#define VFB_MIN_KEY 8
-#define VFB_MAX_KEY 255
-
-static int
-vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
-{
- DevicePtr pDev = (DevicePtr)pDevice;
-
- switch (onoff)
- {
- case DEVICE_INIT:
- InitKeyboardDeviceStruct(pDevice, NULL, NULL, NULL);
- break;
- case DEVICE_ON:
- pDev->on = TRUE;
- break;
- case DEVICE_OFF:
- pDev->on = FALSE;
- break;
- case DEVICE_CLOSE:
- break;
- }
- return Success;
-}
-
-static int
-vfbMouseProc(DeviceIntPtr pDevice, int onoff)
-{
-#define NBUTTONS 3
-#define NAXES 2
-
- BYTE map[NBUTTONS + 1];
- DevicePtr pDev = (DevicePtr)pDevice;
- Atom btn_labels[NBUTTONS] = {0};
- Atom axes_labels[NAXES] = {0};
-
- switch (onoff)
- {
- case DEVICE_INIT:
- map[1] = 1;
- map[2] = 2;
- map[3] = 3;
-
- btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
- btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
- btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
-
- axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
- axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
-
- InitPointerDeviceStruct(pDev, map, NBUTTONS, btn_labels,
- (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), NAXES, axes_labels);
- break;
-
- case DEVICE_ON:
- pDev->on = TRUE;
- break;
-
- case DEVICE_OFF:
- pDev->on = FALSE;
- break;
-
- case DEVICE_CLOSE:
- break;
- }
- return Success;
-
-#undef NBUTTONS
-#undef NAXES
-}
-
-void
-InitInput(int argc, char *argv[])
-{
- DeviceIntPtr p, k;
- Atom xiclass;
- p = AddInputDevice(serverClient, vfbMouseProc, TRUE);
- k = AddInputDevice(serverClient, vfbKeybdProc, TRUE);
- xiclass = MakeAtom(XI_MOUSE, sizeof(XI_MOUSE) - 1, TRUE);
- AssignTypeAndName(p, xiclass, "Xvfb mouse");
- xiclass = MakeAtom(XI_KEYBOARD, sizeof(XI_KEYBOARD) - 1, TRUE);
- AssignTypeAndName(k, xiclass, "Xvfb keyboard");
- (void)mieqInit();
-}
-
-void
-CloseInput (void)
-{
-}
+/*
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "mi.h"
+#include <X11/Xproto.h>
+#include "scrnintstr.h"
+#include "inputstr.h"
+#include <X11/Xos.h>
+#include "mibstore.h"
+#include "mipointer.h"
+#include "xkbsrv.h"
+#include <X11/keysym.h>
+#include "xserver-properties.h"
+#include "exevents.h"
+#include "extinit.h"
+
+Bool
+LegalModifier(unsigned int key, DeviceIntPtr pDev)
+{
+ return TRUE;
+}
+
+void
+ProcessInputEvents(void)
+{
+ mieqProcessInputEvents();
+}
+
+void DDXRingBell(int volume, int pitch, int duration)
+{
+}
+
+#define VFB_MIN_KEY 8
+#define VFB_MAX_KEY 255
+
+static int
+vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
+{
+ DevicePtr pDev = (DevicePtr)pDevice;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ InitKeyboardDeviceStruct(pDevice, NULL, NULL, NULL);
+ break;
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ break;
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ break;
+ case DEVICE_CLOSE:
+ break;
+ }
+ return Success;
+}
+
+static int
+vfbMouseProc(DeviceIntPtr pDevice, int onoff)
+{
+#define NBUTTONS 3
+#define NAXES 2
+
+ BYTE map[NBUTTONS + 1];
+ DevicePtr pDev = (DevicePtr)pDevice;
+ Atom btn_labels[NBUTTONS] = {0};
+ Atom axes_labels[NAXES] = {0};
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ map[1] = 1;
+ map[2] = 2;
+ map[3] = 3;
+
+ btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+ btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+ btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+
+ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
+ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+
+ InitPointerDeviceStruct(pDev, map, NBUTTONS, btn_labels,
+ (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), NAXES, axes_labels);
+ break;
+
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ break;
+
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ break;
+
+ case DEVICE_CLOSE:
+ break;
+ }
+ return Success;
+
+#undef NBUTTONS
+#undef NAXES
+}
+
+void
+InitInput(int argc, char *argv[])
+{
+ DeviceIntPtr p, k;
+ Atom xiclass;
+ p = AddInputDevice(serverClient, vfbMouseProc, TRUE);
+ k = AddInputDevice(serverClient, vfbKeybdProc, TRUE);
+ xiclass = MakeAtom(XI_MOUSE, sizeof(XI_MOUSE) - 1, TRUE);
+ AssignTypeAndName(p, xiclass, "Xvfb mouse");
+ xiclass = MakeAtom(XI_KEYBOARD, sizeof(XI_KEYBOARD) - 1, TRUE);
+ AssignTypeAndName(k, xiclass, "Xvfb keyboard");
+ (void)mieqInit();
+}
+
+void
+CloseInput (void)
+{
+ mieqFini();
+}
diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c
index 53f763aaf..15fdbc349 100644
--- a/xorg-server/hw/xfree86/common/xf86Init.c
+++ b/xorg-server/hw/xfree86/common/xf86Init.c
@@ -825,6 +825,7 @@ void
CloseInput (void)
{
config_fini();
+ mieqFini();
}
/*
diff --git a/xorg-server/hw/xfree86/dixmods/xkbPrivate.c b/xorg-server/hw/xfree86/dixmods/xkbPrivate.c
index 9742eaf31..06d1c2b3d 100644
--- a/xorg-server/hw/xfree86/dixmods/xkbPrivate.c
+++ b/xorg-server/hw/xfree86/dixmods/xkbPrivate.c
@@ -13,6 +13,7 @@
#define XKBSRV_NEED_FILE_FUNCS
#include <xkbsrv.h>
+#include "dixgrabs.h"
#include "os.h"
#include "xf86.h"
@@ -29,6 +30,20 @@ XkbDDXPrivate(DeviceIntPtr dev,KeyCode key,XkbAction *act)
xf86ProcessActionEvent(ACTION_PREV_MODE, NULL);
else if (strcasecmp(msgbuf, "+vmode")==0)
xf86ProcessActionEvent(ACTION_NEXT_MODE, NULL);
+ else if (strcasecmp(msgbuf, "prgrbs")==0) {
+ DeviceIntPtr tmp;
+ xf86Msg(X_INFO, "Printing all currently active device grabs:\n");
+ for (tmp = inputInfo.devices; tmp; tmp = tmp->next)
+ if (tmp->deviceGrab.grab)
+ PrintDeviceGrabInfo(tmp);
+ xf86Msg(X_INFO, "End list of active device grabs\n");
+ }
+ else if (strcasecmp(msgbuf, "ungrab")==0)
+ UngrabAllDevices(FALSE);
+ else if (strcasecmp(msgbuf, "clsgrb")==0)
+ UngrabAllDevices(TRUE);
+ else if (strcasecmp(msgbuf, "prwins")==0)
+ PrintWindowTree();
}
return 0;
diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c
index bf7ebb9f8..af3bcaefe 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.c
+++ b/xorg-server/hw/xfree86/dri2/dri2.c
@@ -1185,6 +1185,7 @@ void
DRI2CloseScreen(ScreenPtr pScreen)
{
DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+ pScreen->ConfigNotify = ds->ConfigNotify;
free(ds->driverNames);
free(ds);
diff --git a/xorg-server/hw/xfree86/exa/examodule.c b/xorg-server/hw/xfree86/exa/examodule.c
index 356fd16ca..15560513d 100644
--- a/xorg-server/hw/xfree86/exa/examodule.c
+++ b/xorg-server/hw/xfree86/exa/examodule.c
@@ -1,201 +1,201 @@
-/*
- * Copyright © 2006 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- * Eric Anholt <anholt@FreeBSD.org>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <string.h>
-
-#include "exa_priv.h"
-
-#include "xf86str.h"
-#include "xf86.h"
-
-typedef struct _ExaXorgScreenPrivRec {
- CloseScreenProcPtr SavedCloseScreen;
- EnableDisableFBAccessProcPtr SavedEnableDisableFBAccess;
- OptionInfoPtr options;
-} ExaXorgScreenPrivRec, *ExaXorgScreenPrivPtr;
-
-static DevPrivateKeyRec exaXorgScreenPrivateKeyRec;
-#define exaXorgScreenPrivateKey (&exaXorgScreenPrivateKeyRec)
-
-typedef enum {
- EXAOPT_MIGRATION_HEURISTIC,
- EXAOPT_NO_COMPOSITE,
- EXAOPT_NO_UTS,
- EXAOPT_NO_DFS,
- EXAOPT_OPTIMIZE_MIGRATION
-} EXAOpts;
-
-static const OptionInfoRec EXAOptions[] = {
- { EXAOPT_MIGRATION_HEURISTIC, "MigrationHeuristic",
- OPTV_ANYSTR, {0}, FALSE },
- { EXAOPT_NO_COMPOSITE, "EXANoComposite",
- OPTV_BOOLEAN, {0}, FALSE },
- { EXAOPT_NO_UTS, "EXANoUploadToScreen",
- OPTV_BOOLEAN, {0}, FALSE },
- { EXAOPT_NO_DFS, "EXANoDownloadFromScreen",
- OPTV_BOOLEAN, {0}, FALSE },
- { EXAOPT_OPTIMIZE_MIGRATION, "EXAOptimizeMigration",
- OPTV_BOOLEAN, {0}, FALSE },
- { -1, NULL,
- OPTV_NONE, {0}, FALSE }
-};
-
-static Bool
-exaXorgCloseScreen (int i, ScreenPtr pScreen)
-{
- ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
- ExaXorgScreenPrivPtr pScreenPriv = (ExaXorgScreenPrivPtr)
- dixLookupPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey);
-
- pScreen->CloseScreen = pScreenPriv->SavedCloseScreen;
-
- pScrn->EnableDisableFBAccess = pScreenPriv->SavedEnableDisableFBAccess;
-
- free(pScreenPriv->options);
- free(pScreenPriv);
-
- return pScreen->CloseScreen (i, pScreen);
-}
-
-static void
-exaXorgEnableDisableFBAccess (int index, Bool enable)
-{
- ScreenPtr pScreen = screenInfo.screens[index];
- ExaXorgScreenPrivPtr pScreenPriv = (ExaXorgScreenPrivPtr)
- dixLookupPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey);
-
- if (!enable)
- exaEnableDisableFBAccess (index, enable);
-
- if (pScreenPriv->SavedEnableDisableFBAccess)
- pScreenPriv->SavedEnableDisableFBAccess (index, enable);
-
- if (enable)
- exaEnableDisableFBAccess (index, enable);
-}
-
-/**
- * This will be called during exaDriverInit, giving us the chance to set options
- * and hook in our EnableDisableFBAccess.
- */
-void
-exaDDXDriverInit(ScreenPtr pScreen)
-{
- ExaScreenPriv(pScreen);
- /* Do NOT use XF86SCRNINFO macro here!! */
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- ExaXorgScreenPrivPtr pScreenPriv;
-
- if (!dixRegisterPrivateKey(&exaXorgScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
- return;
-
- pScreenPriv = calloc(1, sizeof(ExaXorgScreenPrivRec));
- if (pScreenPriv == NULL)
- return;
-
- pScreenPriv->options = xnfalloc (sizeof(EXAOptions));
- memcpy(pScreenPriv->options, EXAOptions, sizeof(EXAOptions));
- xf86ProcessOptions (pScrn->scrnIndex, pScrn->options, pScreenPriv->options);
-
- if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) {
- if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
- pExaScr->info->offScreenBase < pExaScr->info->memorySize) {
- char *heuristicName;
-
- heuristicName = xf86GetOptValString (pScreenPriv->options,
- EXAOPT_MIGRATION_HEURISTIC);
- if (heuristicName != NULL) {
- if (strcmp(heuristicName, "greedy") == 0)
- pExaScr->migration = ExaMigrationGreedy;
- else if (strcmp(heuristicName, "always") == 0)
- pExaScr->migration = ExaMigrationAlways;
- else if (strcmp(heuristicName, "smart") == 0)
- pExaScr->migration = ExaMigrationSmart;
- else {
- xf86DrvMsg (pScreen->myNum, X_WARNING,
- "EXA: unknown migration heuristic %s\n",
- heuristicName);
- }
- }
- }
-
- pExaScr->optimize_migration =
- xf86ReturnOptValBool(pScreenPriv->options,
- EXAOPT_OPTIMIZE_MIGRATION,
- TRUE);
- }
-
- if (xf86ReturnOptValBool(pScreenPriv->options,
- EXAOPT_NO_COMPOSITE, FALSE)) {
- xf86DrvMsg(pScreen->myNum, X_CONFIG,
- "EXA: Disabling Composite operation "
- "(RENDER acceleration)\n");
- pExaScr->info->CheckComposite = NULL;
- pExaScr->info->PrepareComposite = NULL;
- }
-
- if (xf86ReturnOptValBool(pScreenPriv->options, EXAOPT_NO_UTS, FALSE)) {
- xf86DrvMsg(pScreen->myNum, X_CONFIG,
- "EXA: Disabling UploadToScreen\n");
- pExaScr->info->UploadToScreen = NULL;
- }
-
- if (xf86ReturnOptValBool(pScreenPriv->options, EXAOPT_NO_DFS, FALSE)) {
- xf86DrvMsg(pScreen->myNum, X_CONFIG,
- "EXA: Disabling DownloadFromScreen\n");
- pExaScr->info->DownloadFromScreen = NULL;
- }
-
- dixSetPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey, pScreenPriv);
-
- pScreenPriv->SavedEnableDisableFBAccess = pScrn->EnableDisableFBAccess;
- pScrn->EnableDisableFBAccess = exaXorgEnableDisableFBAccess;
-
- pScreenPriv->SavedCloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = exaXorgCloseScreen;
-
-}
-
-static XF86ModuleVersionInfo exaVersRec =
-{
- "exa",
- MODULEVENDORSTRING,
- MODINFOSTRING1,
- MODINFOSTRING2,
- XORG_VERSION_CURRENT,
- EXA_VERSION_MAJOR, EXA_VERSION_MINOR, EXA_VERSION_RELEASE,
- ABI_CLASS_VIDEODRV, /* requires the video driver ABI */
- ABI_VIDEODRV_VERSION,
- MOD_CLASS_NONE,
- {0,0,0,0}
-};
-
-_X_EXPORT XF86ModuleData exaModuleData = { &exaVersRec, NULL, NULL };
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <anholt@FreeBSD.org>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <string.h>
+
+#include "exa_priv.h"
+
+#include "xf86str.h"
+#include "xf86.h"
+
+typedef struct _ExaXorgScreenPrivRec {
+ CloseScreenProcPtr SavedCloseScreen;
+ EnableDisableFBAccessProcPtr SavedEnableDisableFBAccess;
+ OptionInfoPtr options;
+} ExaXorgScreenPrivRec, *ExaXorgScreenPrivPtr;
+
+static DevPrivateKeyRec exaXorgScreenPrivateKeyRec;
+#define exaXorgScreenPrivateKey (&exaXorgScreenPrivateKeyRec)
+
+typedef enum {
+ EXAOPT_MIGRATION_HEURISTIC,
+ EXAOPT_NO_COMPOSITE,
+ EXAOPT_NO_UTS,
+ EXAOPT_NO_DFS,
+ EXAOPT_OPTIMIZE_MIGRATION
+} EXAOpts;
+
+static const OptionInfoRec EXAOptions[] = {
+ { EXAOPT_MIGRATION_HEURISTIC, "MigrationHeuristic",
+ OPTV_ANYSTR, {0}, FALSE },
+ { EXAOPT_NO_COMPOSITE, "EXANoComposite",
+ OPTV_BOOLEAN, {0}, FALSE },
+ { EXAOPT_NO_UTS, "EXANoUploadToScreen",
+ OPTV_BOOLEAN, {0}, FALSE },
+ { EXAOPT_NO_DFS, "EXANoDownloadFromScreen",
+ OPTV_BOOLEAN, {0}, FALSE },
+ { EXAOPT_OPTIMIZE_MIGRATION, "EXAOptimizeMigration",
+ OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL,
+ OPTV_NONE, {0}, FALSE }
+};
+
+static Bool
+exaXorgCloseScreen (int i, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
+ ExaXorgScreenPrivPtr pScreenPriv = (ExaXorgScreenPrivPtr)
+ dixLookupPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey);
+
+ pScreen->CloseScreen = pScreenPriv->SavedCloseScreen;
+
+ pScrn->EnableDisableFBAccess = pScreenPriv->SavedEnableDisableFBAccess;
+
+ free(pScreenPriv->options);
+ free(pScreenPriv);
+
+ return pScreen->CloseScreen (i, pScreen);
+}
+
+static void
+exaXorgEnableDisableFBAccess (int index, Bool enable)
+{
+ ScreenPtr pScreen = screenInfo.screens[index];
+ ExaXorgScreenPrivPtr pScreenPriv = (ExaXorgScreenPrivPtr)
+ dixLookupPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey);
+
+ if (!enable)
+ exaEnableDisableFBAccess (index, enable);
+
+ if (pScreenPriv->SavedEnableDisableFBAccess)
+ pScreenPriv->SavedEnableDisableFBAccess (index, enable);
+
+ if (enable)
+ exaEnableDisableFBAccess (index, enable);
+}
+
+/**
+ * This will be called during exaDriverInit, giving us the chance to set options
+ * and hook in our EnableDisableFBAccess.
+ */
+void
+exaDDXDriverInit(ScreenPtr pScreen)
+{
+ ExaScreenPriv(pScreen);
+ /* Do NOT use XF86SCRNINFO macro here!! */
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ ExaXorgScreenPrivPtr pScreenPriv;
+
+ if (!dixRegisterPrivateKey(&exaXorgScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
+ return;
+
+ pScreenPriv = calloc(1, sizeof(ExaXorgScreenPrivRec));
+ if (pScreenPriv == NULL)
+ return;
+
+ pScreenPriv->options = xnfalloc (sizeof(EXAOptions));
+ memcpy(pScreenPriv->options, EXAOptions, sizeof(EXAOptions));
+ xf86ProcessOptions (pScrn->scrnIndex, pScrn->options, pScreenPriv->options);
+
+ if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS) {
+ if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
+ pExaScr->info->offScreenBase < pExaScr->info->memorySize) {
+ char *heuristicName;
+
+ heuristicName = xf86GetOptValString (pScreenPriv->options,
+ EXAOPT_MIGRATION_HEURISTIC);
+ if (heuristicName != NULL) {
+ if (strcmp(heuristicName, "greedy") == 0)
+ pExaScr->migration = ExaMigrationGreedy;
+ else if (strcmp(heuristicName, "always") == 0)
+ pExaScr->migration = ExaMigrationAlways;
+ else if (strcmp(heuristicName, "smart") == 0)
+ pExaScr->migration = ExaMigrationSmart;
+ else {
+ xf86DrvMsg (pScreen->myNum, X_WARNING,
+ "EXA: unknown migration heuristic %s\n",
+ heuristicName);
+ }
+ }
+ }
+
+ pExaScr->optimize_migration =
+ xf86ReturnOptValBool(pScreenPriv->options,
+ EXAOPT_OPTIMIZE_MIGRATION,
+ TRUE);
+ }
+
+ if (xf86ReturnOptValBool(pScreenPriv->options,
+ EXAOPT_NO_COMPOSITE, FALSE)) {
+ xf86DrvMsg(pScreen->myNum, X_CONFIG,
+ "EXA: Disabling Composite operation "
+ "(RENDER acceleration)\n");
+ pExaScr->info->CheckComposite = NULL;
+ pExaScr->info->PrepareComposite = NULL;
+ }
+
+ if (xf86ReturnOptValBool(pScreenPriv->options, EXAOPT_NO_UTS, FALSE)) {
+ xf86DrvMsg(pScreen->myNum, X_CONFIG,
+ "EXA: Disabling UploadToScreen\n");
+ pExaScr->info->UploadToScreen = NULL;
+ }
+
+ if (xf86ReturnOptValBool(pScreenPriv->options, EXAOPT_NO_DFS, FALSE)) {
+ xf86DrvMsg(pScreen->myNum, X_CONFIG,
+ "EXA: Disabling DownloadFromScreen\n");
+ pExaScr->info->DownloadFromScreen = NULL;
+ }
+
+ dixSetPrivate(&pScreen->devPrivates, exaXorgScreenPrivateKey, pScreenPriv);
+
+ pScreenPriv->SavedEnableDisableFBAccess = pScrn->EnableDisableFBAccess;
+ pScrn->EnableDisableFBAccess = exaXorgEnableDisableFBAccess;
+
+ pScreenPriv->SavedCloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = exaXorgCloseScreen;
+
+}
+
+static XF86ModuleVersionInfo exaVersRec =
+{
+ "exa",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ EXA_VERSION_MAJOR, EXA_VERSION_MINOR, EXA_VERSION_RELEASE,
+ ABI_CLASS_VIDEODRV, /* requires the video driver ABI */
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_NONE,
+ {0,0,0,0}
+};
+
+_X_EXPORT XF86ModuleData exaModuleData = { &exaVersRec, NULL, NULL };
diff --git a/xorg-server/hw/xfree86/modes/xf86Modes.h b/xorg-server/hw/xfree86/modes/xf86Modes.h
index 38927b128..c72a93537 100644
--- a/xorg-server/hw/xfree86/modes/xf86Modes.h
+++ b/xorg-server/hw/xfree86/modes/xf86Modes.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2006 Intel Corporation
+ * Copyright © 2006 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
diff --git a/xorg-server/hw/xfree86/modes/xf86cvt.c b/xorg-server/hw/xfree86/modes/xf86cvt.c
index 9992fa4c4..d5fecccb5 100644
--- a/xorg-server/hw/xfree86/modes/xf86cvt.c
+++ b/xorg-server/hw/xfree86/modes/xf86cvt.c
@@ -1,293 +1,293 @@
-/*
- * Copyright 2005-2006 Luc Verhaegen.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, 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.
- */
-
-/*
- * The reason for having this function in a file of its own is
- * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
- * code is shared directly.
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#else
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#endif
-
-#include "xf86.h"
-#include "xf86Modes.h"
-
-#include <string.h>
-
-/*
- * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
- *
- * These calculations are stolen from the CVT calculation spreadsheet written
- * by Graham Loveridge. He seems to be claiming no copyright and there seems to
- * be no license attached to this. He apparently just wants to see his name
- * mentioned.
- *
- * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
- *
- * Comments and structure corresponds to the comments and structure of the xls.
- * This should ease importing of future changes to the standard (not very
- * likely though).
- *
- * About margins; i'm sure that they are to be the bit between HDisplay and
- * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
- * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
- * outside sync "margin" for some reason. Since we prefer seeing proper
- * blanking instead of the overscan colour, and since the Crtc* values will
- * probably get altered after us, we will disable margins altogether. With
- * these calculations, Margins will plainly expand H/VDisplay, and we don't
- * want that. -- libv
- *
- */
-DisplayModePtr
-xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
- Bool Interlaced)
-{
- DisplayModeRec *Mode = xnfcalloc(1, sizeof(DisplayModeRec));
-
- /* 1) top/bottom margin size (% of height) - default: 1.8 */
-#define CVT_MARGIN_PERCENTAGE 1.8
-
- /* 2) character cell horizontal granularity (pixels) - default 8 */
-#define CVT_H_GRANULARITY 8
-
- /* 4) Minimum vertical porch (lines) - default 3 */
-#define CVT_MIN_V_PORCH 3
-
- /* 4) Minimum number of vertical back porch lines - default 6 */
-#define CVT_MIN_V_BPORCH 6
-
- /* Pixel Clock step (kHz) */
-#define CVT_CLOCK_STEP 250
-
- Bool Margins = FALSE;
- float VFieldRate, HPeriod;
- int HDisplayRnd, HMargin;
- int VDisplayRnd, VMargin, VSync;
- float Interlace; /* Please rename this */
-
- /* CVT default is 60.0Hz */
- if (!VRefresh)
- VRefresh = 60.0;
-
- /* 1. Required field rate */
- if (Interlaced)
- VFieldRate = VRefresh * 2;
- else
- VFieldRate = VRefresh;
-
- /* 2. Horizontal pixels */
- HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
-
- /* 3. Determine left and right borders */
- if (Margins) {
- /* right margin is actually exactly the same as left */
- HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
- HMargin -= HMargin % CVT_H_GRANULARITY;
- } else
- HMargin = 0;
-
- /* 4. Find total active pixels */
- Mode->HDisplay = HDisplayRnd + 2*HMargin;
-
- /* 5. Find number of lines per field */
- if (Interlaced)
- VDisplayRnd = VDisplay / 2;
- else
- VDisplayRnd = VDisplay;
-
- /* 6. Find top and bottom margins */
- /* nope. */
- if (Margins)
- /* top and bottom margins are equal again. */
- VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
- else
- VMargin = 0;
-
- Mode->VDisplay = VDisplay + 2*VMargin;
-
- /* 7. Interlace */
- if (Interlaced)
- Interlace = 0.5;
- else
- Interlace = 0.0;
-
- /* Determine VSync Width from aspect ratio */
- if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
- VSync = 4;
- else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
- VSync = 5;
- else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
- VSync = 6;
- else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
- VSync = 7;
- else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
- VSync = 7;
- else /* Custom */
- VSync = 10;
-
- if (!Reduced) { /* simplified GTF calculation */
-
- /* 4) Minimum time of vertical sync + back porch interval (µs)
- * default 550.0 */
-#define CVT_MIN_VSYNC_BP 550.0
-
- /* 3) Nominal HSync width (% of line period) - default 8 */
-#define CVT_HSYNC_PERCENTAGE 8
-
- float HBlankPercentage;
- int VSyncAndBackPorch, VBackPorch;
- int HBlank;
-
- /* 8. Estimated Horizontal period */
- HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
- (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
-
- /* 9. Find number of lines in sync + backporch */
- if (((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1) < (VSync + CVT_MIN_V_PORCH))
- VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
- else
- VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1;
-
- /* 10. Find number of lines in back porch */
- VBackPorch = VSyncAndBackPorch - VSync;
-
- /* 11. Find total number of lines in vertical field */
- Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace
- + CVT_MIN_V_PORCH;
-
- /* 5) Definition of Horizontal blanking time limitation */
- /* Gradient (%/kHz) - default 600 */
-#define CVT_M_FACTOR 600
-
- /* Offset (%) - default 40 */
-#define CVT_C_FACTOR 40
-
- /* Blanking time scaling factor - default 128 */
-#define CVT_K_FACTOR 128
-
- /* Scaling factor weighting - default 20 */
-#define CVT_J_FACTOR 20
-
-#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
-#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
- CVT_J_FACTOR
-
- /* 12. Find ideal blanking duty cycle from formula */
- HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod/1000.0;
-
- /* 13. Blanking time */
- if (HBlankPercentage < 20)
- HBlankPercentage = 20;
-
- HBlank = Mode->HDisplay * HBlankPercentage/(100.0 - HBlankPercentage);
- HBlank -= HBlank % (2*CVT_H_GRANULARITY);
-
- /* 14. Find total number of pixels in a line. */
- Mode->HTotal = Mode->HDisplay + HBlank;
-
- /* Fill in HSync values */
- Mode->HSyncEnd = Mode->HDisplay + HBlank / 2;
-
- Mode->HSyncStart = Mode->HSyncEnd -
- (Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100;
- Mode->HSyncStart += CVT_H_GRANULARITY -
- Mode->HSyncStart % CVT_H_GRANULARITY;
-
- /* Fill in VSync values */
- Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH;
- Mode->VSyncEnd = Mode->VSyncStart + VSync;
-
- } else { /* Reduced blanking */
- /* Minimum vertical blanking interval time (µs) - default 460 */
-#define CVT_RB_MIN_VBLANK 460.0
-
- /* Fixed number of clocks for horizontal sync */
-#define CVT_RB_H_SYNC 32.0
-
- /* Fixed number of clocks for horizontal blanking */
-#define CVT_RB_H_BLANK 160.0
-
- /* Fixed number of lines for vertical front porch - default 3 */
-#define CVT_RB_VFPORCH 3
-
- int VBILines;
-
- /* 8. Estimate Horizontal period. */
- HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
- (VDisplayRnd + 2*VMargin);
-
- /* 9. Find number of lines in vertical blanking */
- VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
-
- /* 10. Check if vertical blanking is sufficient */
- if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
- VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
-
- /* 11. Find total number of lines in vertical field */
- Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
-
- /* 12. Find total number of pixels in a line */
- Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK;
-
- /* Fill in HSync values */
- Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2;
- Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC;
-
- /* Fill in VSync values */
- Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH;
- Mode->VSyncEnd = Mode->VSyncStart + VSync;
- }
-
- /* 15/13. Find pixel clock frequency (kHz for xf86) */
- Mode->Clock = Mode->HTotal * 1000.0 / HPeriod;
- Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP;
-
- /* 16/14. Find actual Horizontal Frequency (kHz) */
- Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal);
-
- /* 17/15. Find actual Field rate */
- Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
- ((float) (Mode->HTotal * Mode->VTotal));
-
- /* 18/16. Find actual vertical frame frequency */
- /* ignore - just set the mode flag for interlaced */
- if (Interlaced)
- Mode->VTotal *= 2;
-
- XNFasprintf(&Mode->name, "%dx%d", HDisplay, VDisplay);
-
- if (Reduced)
- Mode->Flags |= V_PHSYNC | V_NVSYNC;
- else
- Mode->Flags |= V_NHSYNC | V_PVSYNC;
-
- if (Interlaced)
- Mode->Flags |= V_INTERLACE;
-
- return Mode;
-}
+/*
+ * Copyright 2005-2006 Luc Verhaegen.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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.
+ */
+
+/*
+ * The reason for having this function in a file of its own is
+ * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
+ * code is shared directly.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include "xf86.h"
+#include "xf86Modes.h"
+
+#include <string.h>
+
+/*
+ * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
+ *
+ * These calculations are stolen from the CVT calculation spreadsheet written
+ * by Graham Loveridge. He seems to be claiming no copyright and there seems to
+ * be no license attached to this. He apparently just wants to see his name
+ * mentioned.
+ *
+ * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
+ *
+ * Comments and structure corresponds to the comments and structure of the xls.
+ * This should ease importing of future changes to the standard (not very
+ * likely though).
+ *
+ * About margins; i'm sure that they are to be the bit between HDisplay and
+ * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
+ * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
+ * outside sync "margin" for some reason. Since we prefer seeing proper
+ * blanking instead of the overscan colour, and since the Crtc* values will
+ * probably get altered after us, we will disable margins altogether. With
+ * these calculations, Margins will plainly expand H/VDisplay, and we don't
+ * want that. -- libv
+ *
+ */
+DisplayModePtr
+xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
+ Bool Interlaced)
+{
+ DisplayModeRec *Mode = xnfcalloc(1, sizeof(DisplayModeRec));
+
+ /* 1) top/bottom margin size (% of height) - default: 1.8 */
+#define CVT_MARGIN_PERCENTAGE 1.8
+
+ /* 2) character cell horizontal granularity (pixels) - default 8 */
+#define CVT_H_GRANULARITY 8
+
+ /* 4) Minimum vertical porch (lines) - default 3 */
+#define CVT_MIN_V_PORCH 3
+
+ /* 4) Minimum number of vertical back porch lines - default 6 */
+#define CVT_MIN_V_BPORCH 6
+
+ /* Pixel Clock step (kHz) */
+#define CVT_CLOCK_STEP 250
+
+ Bool Margins = FALSE;
+ float VFieldRate, HPeriod;
+ int HDisplayRnd, HMargin;
+ int VDisplayRnd, VMargin, VSync;
+ float Interlace; /* Please rename this */
+
+ /* CVT default is 60.0Hz */
+ if (!VRefresh)
+ VRefresh = 60.0;
+
+ /* 1. Required field rate */
+ if (Interlaced)
+ VFieldRate = VRefresh * 2;
+ else
+ VFieldRate = VRefresh;
+
+ /* 2. Horizontal pixels */
+ HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
+
+ /* 3. Determine left and right borders */
+ if (Margins) {
+ /* right margin is actually exactly the same as left */
+ HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+ HMargin -= HMargin % CVT_H_GRANULARITY;
+ } else
+ HMargin = 0;
+
+ /* 4. Find total active pixels */
+ Mode->HDisplay = HDisplayRnd + 2*HMargin;
+
+ /* 5. Find number of lines per field */
+ if (Interlaced)
+ VDisplayRnd = VDisplay / 2;
+ else
+ VDisplayRnd = VDisplay;
+
+ /* 6. Find top and bottom margins */
+ /* nope. */
+ if (Margins)
+ /* top and bottom margins are equal again. */
+ VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
+ else
+ VMargin = 0;
+
+ Mode->VDisplay = VDisplay + 2*VMargin;
+
+ /* 7. Interlace */
+ if (Interlaced)
+ Interlace = 0.5;
+ else
+ Interlace = 0.0;
+
+ /* Determine VSync Width from aspect ratio */
+ if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
+ VSync = 4;
+ else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
+ VSync = 5;
+ else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
+ VSync = 6;
+ else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
+ VSync = 7;
+ else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
+ VSync = 7;
+ else /* Custom */
+ VSync = 10;
+
+ if (!Reduced) { /* simplified GTF calculation */
+
+ /* 4) Minimum time of vertical sync + back porch interval (µs)
+ * default 550.0 */
+#define CVT_MIN_VSYNC_BP 550.0
+
+ /* 3) Nominal HSync width (% of line period) - default 8 */
+#define CVT_HSYNC_PERCENTAGE 8
+
+ float HBlankPercentage;
+ int VSyncAndBackPorch, VBackPorch;
+ int HBlank;
+
+ /* 8. Estimated Horizontal period */
+ HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
+ (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
+
+ /* 9. Find number of lines in sync + backporch */
+ if (((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1) < (VSync + CVT_MIN_V_PORCH))
+ VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
+ else
+ VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1;
+
+ /* 10. Find number of lines in back porch */
+ VBackPorch = VSyncAndBackPorch - VSync;
+
+ /* 11. Find total number of lines in vertical field */
+ Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace
+ + CVT_MIN_V_PORCH;
+
+ /* 5) Definition of Horizontal blanking time limitation */
+ /* Gradient (%/kHz) - default 600 */
+#define CVT_M_FACTOR 600
+
+ /* Offset (%) - default 40 */
+#define CVT_C_FACTOR 40
+
+ /* Blanking time scaling factor - default 128 */
+#define CVT_K_FACTOR 128
+
+ /* Scaling factor weighting - default 20 */
+#define CVT_J_FACTOR 20
+
+#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
+#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
+ CVT_J_FACTOR
+
+ /* 12. Find ideal blanking duty cycle from formula */
+ HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod/1000.0;
+
+ /* 13. Blanking time */
+ if (HBlankPercentage < 20)
+ HBlankPercentage = 20;
+
+ HBlank = Mode->HDisplay * HBlankPercentage/(100.0 - HBlankPercentage);
+ HBlank -= HBlank % (2*CVT_H_GRANULARITY);
+
+ /* 14. Find total number of pixels in a line. */
+ Mode->HTotal = Mode->HDisplay + HBlank;
+
+ /* Fill in HSync values */
+ Mode->HSyncEnd = Mode->HDisplay + HBlank / 2;
+
+ Mode->HSyncStart = Mode->HSyncEnd -
+ (Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100;
+ Mode->HSyncStart += CVT_H_GRANULARITY -
+ Mode->HSyncStart % CVT_H_GRANULARITY;
+
+ /* Fill in VSync values */
+ Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH;
+ Mode->VSyncEnd = Mode->VSyncStart + VSync;
+
+ } else { /* Reduced blanking */
+ /* Minimum vertical blanking interval time (µs) - default 460 */
+#define CVT_RB_MIN_VBLANK 460.0
+
+ /* Fixed number of clocks for horizontal sync */
+#define CVT_RB_H_SYNC 32.0
+
+ /* Fixed number of clocks for horizontal blanking */
+#define CVT_RB_H_BLANK 160.0
+
+ /* Fixed number of lines for vertical front porch - default 3 */
+#define CVT_RB_VFPORCH 3
+
+ int VBILines;
+
+ /* 8. Estimate Horizontal period. */
+ HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
+ (VDisplayRnd + 2*VMargin);
+
+ /* 9. Find number of lines in vertical blanking */
+ VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
+
+ /* 10. Check if vertical blanking is sufficient */
+ if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
+ VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
+
+ /* 11. Find total number of lines in vertical field */
+ Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
+
+ /* 12. Find total number of pixels in a line */
+ Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK;
+
+ /* Fill in HSync values */
+ Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2;
+ Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC;
+
+ /* Fill in VSync values */
+ Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH;
+ Mode->VSyncEnd = Mode->VSyncStart + VSync;
+ }
+
+ /* 15/13. Find pixel clock frequency (kHz for xf86) */
+ Mode->Clock = Mode->HTotal * 1000.0 / HPeriod;
+ Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP;
+
+ /* 16/14. Find actual Horizontal Frequency (kHz) */
+ Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal);
+
+ /* 17/15. Find actual Field rate */
+ Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
+ ((float) (Mode->HTotal * Mode->VTotal));
+
+ /* 18/16. Find actual vertical frame frequency */
+ /* ignore - just set the mode flag for interlaced */
+ if (Interlaced)
+ Mode->VTotal *= 2;
+
+ XNFasprintf(&Mode->name, "%dx%d", HDisplay, VDisplay);
+
+ if (Reduced)
+ Mode->Flags |= V_PHSYNC | V_NVSYNC;
+ else
+ Mode->Flags |= V_NHSYNC | V_PVSYNC;
+
+ if (Interlaced)
+ Mode->Flags |= V_INTERLACE;
+
+ return Mode;
+}
diff --git a/xorg-server/hw/xfree86/os-support/solaris/sun_agp.c b/xorg-server/hw/xfree86/os-support/solaris/sun_agp.c
index 8c5c45843..0331ac1c5 100644
--- a/xorg-server/hw/xfree86/os-support/solaris/sun_agp.c
+++ b/xorg-server/hw/xfree86/os-support/solaris/sun_agp.c
@@ -1,327 +1,327 @@
-/*
- * Abstraction of the AGP GART interface.
- *
- * This version is for Solaris.
- *
- * Copyright © 2000 VA Linux Systems, Inc.
- * Copyright © 2001 The XFree86 Project, Inc.
- */
-/* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include <X11/X.h>
-#include "xf86.h"
-#include "xf86Priv.h"
-#include "xf86_OSlib.h"
-#include "xf86_OSproc.h"
-#include <unistd.h>
-#include <sys/ioccom.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/agpgart.h>
-
-/* AGP page size is independent of the host page size. */
-#ifndef AGP_PAGE_SIZE
-#define AGP_PAGE_SIZE 4096
-#endif
-
-static int gartFd = -1;
-static int acquiredScreen = -1;
-static Bool initDone = FALSE;
-/*
- * Close /dev/agpgart. This frees all associated memory allocated during
- * this server generation.
- */
-Bool
-xf86GARTCloseScreen(int screenNum)
-{
- if (gartFd != -1) {
- close(gartFd);
- acquiredScreen = -1;
- gartFd = -1;
- initDone = FALSE;
-
- xf86DrvMsg(screenNum, X_INFO,
- "xf86GARTCloseScreen: device closed successfully\n");
-
- }
- return TRUE;
-}
-
-/*
- * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called.
- */
-static Bool
-GARTInit(int screenNum)
-{
- if (initDone)
- return gartFd != -1;
-
- if (gartFd == -1)
- gartFd = open(AGP_DEVICE, O_RDWR);
- else
- return FALSE;
-
- if (gartFd == -1) {
- xf86DrvMsg(screenNum, X_ERROR,
- "GARTInit: Unable to open " AGP_DEVICE " (%s)\n",
- strerror(errno));
- return FALSE;
- }
-
- initDone = TRUE;
- xf86DrvMsg(screenNum, X_INFO,
- "GARTInit: " AGP_DEVICE " opened successfully\n");
-
- return TRUE;
-}
-
-Bool
-xf86AgpGARTSupported(void)
-{
- return (GARTInit(-1));
-
-}
-
-AgpInfoPtr
-xf86GetAGPInfo(int screenNum)
-{
- agp_info_t agpinf;
- AgpInfoPtr info;
-
- if (!GARTInit(screenNum))
- return NULL;
-
- if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) {
- xf86DrvMsg(screenNum, X_ERROR,
- "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n",
- strerror(errno));
- return NULL;
- }
-
- if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) {
- xf86DrvMsg(screenNum, X_ERROR,
- "xf86GetAGPInfo: Failed to allocate AgpInfo\n");
- return NULL;
- }
-
- info->bridgeId = agpinf.agpi_devid;
- info->agpMode = agpinf.agpi_mode;
- info->base = agpinf.agpi_aperbase;
- info->size = agpinf.agpi_apersize;
- info->totalPages = (unsigned long)agpinf.agpi_pgtotal;
- info->systemPages = (unsigned long)agpinf.agpi_pgsystem;
- info->usedPages = (unsigned long)agpinf.agpi_pgused;
-
- return info;
-}
-
-Bool
-xf86AcquireGART(int screenNum)
-{
-
- if (!GARTInit(screenNum))
- return FALSE;
-
- if (acquiredScreen != screenNum) {
- if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) {
- xf86DrvMsg(screenNum, X_WARNING,
- "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n",
- strerror(errno));
- return FALSE;
- }
- acquiredScreen = screenNum;
- xf86DrvMsg(screenNum, X_INFO,
- "xf86AcquireGART: AGPIOC_ACQUIRE succeeded\n");
- }
- return TRUE;
-}
-
-Bool
-xf86ReleaseGART(int screenNum)
-{
-
- if (!GARTInit(screenNum))
- return FALSE;
-
- if (acquiredScreen == screenNum) {
- /*
- * The FreeBSD agp driver removes allocations on release.
- * The Solaris driver doesn't. xf86ReleaseGART() is expected
- * to give up access to the GART, but not to remove any
- * allocations.
- */
-
- if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) {
- xf86DrvMsg(screenNum, X_WARNING,
- "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n",
- strerror(errno));
- return FALSE;
- }
- acquiredScreen = -1;
- xf86DrvMsg(screenNum, X_INFO,
- "xf86ReleaseGART: AGPIOC_RELEASE succeeded\n");
- return TRUE;
- }
- return FALSE;
-}
-
-int
-xf86AllocateGARTMemory(int screenNum, unsigned long size, int type,
- unsigned long *physical)
-{
- agp_allocate_t alloc;
- int pages;
-
- /*
- * Allocates "size" bytes of GART memory (rounds up to the next
- * page multiple) or type "type". A handle (key) for the allocated
- * memory is returned. On error, the return value is -1.
- * "size" should be larger than 0, or AGPIOC_ALLOCATE ioctl will
- * return error.
- */
-
- if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
- return -1;
-
- pages = (size / AGP_PAGE_SIZE);
- if (size % AGP_PAGE_SIZE != 0)
- pages++;
-
- alloc.agpa_pgcount = pages;
- alloc.agpa_type = type;
-
- if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) {
- xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: "
- "allocation of %d pages failed\n\t(%s)\n", pages,
- strerror(errno));
- return -1;
- }
-
- if (physical)
- *physical = (unsigned long)alloc.agpa_physical;
-
- return alloc.agpa_key;
-}
-
-Bool
-xf86DeallocateGARTMemory(int screenNum, int key)
-{
- if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
- return FALSE;
-
- if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) {
- xf86DrvMsg(screenNum, X_WARNING, "xf86DeAllocateGARTMemory: "
- "deallocation of gart memory with key %d failed\n"
- "\t(%s)\n", key, strerror(errno));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Bind GART memory with "key" at "offset" */
-Bool
-xf86BindGARTMemory(int screenNum, int key, unsigned long offset)
-{
- agp_bind_t bind;
- int pageOffset;
-
- if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
- return FALSE;
-
- if (offset % AGP_PAGE_SIZE != 0) {
- xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: "
- "offset (0x%lx) is not page-aligned (%d)\n",
- offset, AGP_PAGE_SIZE);
- return FALSE;
- }
- pageOffset = offset / AGP_PAGE_SIZE;
-
- xf86DrvMsgVerb(screenNum, X_INFO, 3,
- "xf86BindGARTMemory: bind key %d at 0x%08lx "
- "(pgoffset %d)\n", key, offset, pageOffset);
-
- bind.agpb_pgstart = pageOffset;
- bind.agpb_key = key;
-
- if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) {
- xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: "
- "binding of gart memory with key %d\n"
- "\tat offset 0x%lx failed (%s)\n",
- key, offset, strerror(errno));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Unbind GART memory with "key" */
-Bool
-xf86UnbindGARTMemory(int screenNum, int key)
-{
- agp_unbind_t unbind;
-
- if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
- return FALSE;
-
- unbind.agpu_pri = 0;
- unbind.agpu_key = key;
-
- if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) {
- xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: "
- "unbinding of gart memory with key %d "
- "failed (%s)\n", key, strerror(errno));
- return FALSE;
- }
-
- xf86DrvMsgVerb(screenNum, X_INFO, 3,
- "xf86UnbindGARTMemory: unbind key %d\n", key);
-
- return TRUE;
-}
-
-
-/* XXX Interface may change. */
-Bool
-xf86EnableAGP(int screenNum, CARD32 mode)
-{
- agp_setup_t setup;
-
- if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
- return FALSE;
-
- setup.agps_mode = mode;
- if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) {
- xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: "
- "AGPIOC_SETUP with mode %x failed (%s)\n",
- (unsigned int) mode, strerror(errno));
- return FALSE;
- }
-
- return TRUE;
-}
-
+/*
+ * Abstraction of the AGP GART interface.
+ *
+ * This version is for Solaris.
+ *
+ * Copyright © 2000 VA Linux Systems, Inc.
+ * Copyright © 2001 The XFree86 Project, Inc.
+ */
+/* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86_OSlib.h"
+#include "xf86_OSproc.h"
+#include <unistd.h>
+#include <sys/ioccom.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/agpgart.h>
+
+/* AGP page size is independent of the host page size. */
+#ifndef AGP_PAGE_SIZE
+#define AGP_PAGE_SIZE 4096
+#endif
+
+static int gartFd = -1;
+static int acquiredScreen = -1;
+static Bool initDone = FALSE;
+/*
+ * Close /dev/agpgart. This frees all associated memory allocated during
+ * this server generation.
+ */
+Bool
+xf86GARTCloseScreen(int screenNum)
+{
+ if (gartFd != -1) {
+ close(gartFd);
+ acquiredScreen = -1;
+ gartFd = -1;
+ initDone = FALSE;
+
+ xf86DrvMsg(screenNum, X_INFO,
+ "xf86GARTCloseScreen: device closed successfully\n");
+
+ }
+ return TRUE;
+}
+
+/*
+ * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called.
+ */
+static Bool
+GARTInit(int screenNum)
+{
+ if (initDone)
+ return gartFd != -1;
+
+ if (gartFd == -1)
+ gartFd = open(AGP_DEVICE, O_RDWR);
+ else
+ return FALSE;
+
+ if (gartFd == -1) {
+ xf86DrvMsg(screenNum, X_ERROR,
+ "GARTInit: Unable to open " AGP_DEVICE " (%s)\n",
+ strerror(errno));
+ return FALSE;
+ }
+
+ initDone = TRUE;
+ xf86DrvMsg(screenNum, X_INFO,
+ "GARTInit: " AGP_DEVICE " opened successfully\n");
+
+ return TRUE;
+}
+
+Bool
+xf86AgpGARTSupported(void)
+{
+ return (GARTInit(-1));
+
+}
+
+AgpInfoPtr
+xf86GetAGPInfo(int screenNum)
+{
+ agp_info_t agpinf;
+ AgpInfoPtr info;
+
+ if (!GARTInit(screenNum))
+ return NULL;
+
+ if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) {
+ xf86DrvMsg(screenNum, X_ERROR,
+ "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) {
+ xf86DrvMsg(screenNum, X_ERROR,
+ "xf86GetAGPInfo: Failed to allocate AgpInfo\n");
+ return NULL;
+ }
+
+ info->bridgeId = agpinf.agpi_devid;
+ info->agpMode = agpinf.agpi_mode;
+ info->base = agpinf.agpi_aperbase;
+ info->size = agpinf.agpi_apersize;
+ info->totalPages = (unsigned long)agpinf.agpi_pgtotal;
+ info->systemPages = (unsigned long)agpinf.agpi_pgsystem;
+ info->usedPages = (unsigned long)agpinf.agpi_pgused;
+
+ return info;
+}
+
+Bool
+xf86AcquireGART(int screenNum)
+{
+
+ if (!GARTInit(screenNum))
+ return FALSE;
+
+ if (acquiredScreen != screenNum) {
+ if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) {
+ xf86DrvMsg(screenNum, X_WARNING,
+ "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n",
+ strerror(errno));
+ return FALSE;
+ }
+ acquiredScreen = screenNum;
+ xf86DrvMsg(screenNum, X_INFO,
+ "xf86AcquireGART: AGPIOC_ACQUIRE succeeded\n");
+ }
+ return TRUE;
+}
+
+Bool
+xf86ReleaseGART(int screenNum)
+{
+
+ if (!GARTInit(screenNum))
+ return FALSE;
+
+ if (acquiredScreen == screenNum) {
+ /*
+ * The FreeBSD agp driver removes allocations on release.
+ * The Solaris driver doesn't. xf86ReleaseGART() is expected
+ * to give up access to the GART, but not to remove any
+ * allocations.
+ */
+
+ if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) {
+ xf86DrvMsg(screenNum, X_WARNING,
+ "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n",
+ strerror(errno));
+ return FALSE;
+ }
+ acquiredScreen = -1;
+ xf86DrvMsg(screenNum, X_INFO,
+ "xf86ReleaseGART: AGPIOC_RELEASE succeeded\n");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int
+xf86AllocateGARTMemory(int screenNum, unsigned long size, int type,
+ unsigned long *physical)
+{
+ agp_allocate_t alloc;
+ int pages;
+
+ /*
+ * Allocates "size" bytes of GART memory (rounds up to the next
+ * page multiple) or type "type". A handle (key) for the allocated
+ * memory is returned. On error, the return value is -1.
+ * "size" should be larger than 0, or AGPIOC_ALLOCATE ioctl will
+ * return error.
+ */
+
+ if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
+ return -1;
+
+ pages = (size / AGP_PAGE_SIZE);
+ if (size % AGP_PAGE_SIZE != 0)
+ pages++;
+
+ alloc.agpa_pgcount = pages;
+ alloc.agpa_type = type;
+
+ if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) {
+ xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: "
+ "allocation of %d pages failed\n\t(%s)\n", pages,
+ strerror(errno));
+ return -1;
+ }
+
+ if (physical)
+ *physical = (unsigned long)alloc.agpa_physical;
+
+ return alloc.agpa_key;
+}
+
+Bool
+xf86DeallocateGARTMemory(int screenNum, int key)
+{
+ if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
+ return FALSE;
+
+ if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) {
+ xf86DrvMsg(screenNum, X_WARNING, "xf86DeAllocateGARTMemory: "
+ "deallocation of gart memory with key %d failed\n"
+ "\t(%s)\n", key, strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Bind GART memory with "key" at "offset" */
+Bool
+xf86BindGARTMemory(int screenNum, int key, unsigned long offset)
+{
+ agp_bind_t bind;
+ int pageOffset;
+
+ if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
+ return FALSE;
+
+ if (offset % AGP_PAGE_SIZE != 0) {
+ xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: "
+ "offset (0x%lx) is not page-aligned (%d)\n",
+ offset, AGP_PAGE_SIZE);
+ return FALSE;
+ }
+ pageOffset = offset / AGP_PAGE_SIZE;
+
+ xf86DrvMsgVerb(screenNum, X_INFO, 3,
+ "xf86BindGARTMemory: bind key %d at 0x%08lx "
+ "(pgoffset %d)\n", key, offset, pageOffset);
+
+ bind.agpb_pgstart = pageOffset;
+ bind.agpb_key = key;
+
+ if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) {
+ xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: "
+ "binding of gart memory with key %d\n"
+ "\tat offset 0x%lx failed (%s)\n",
+ key, offset, strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Unbind GART memory with "key" */
+Bool
+xf86UnbindGARTMemory(int screenNum, int key)
+{
+ agp_unbind_t unbind;
+
+ if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
+ return FALSE;
+
+ unbind.agpu_pri = 0;
+ unbind.agpu_key = key;
+
+ if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) {
+ xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: "
+ "unbinding of gart memory with key %d "
+ "failed (%s)\n", key, strerror(errno));
+ return FALSE;
+ }
+
+ xf86DrvMsgVerb(screenNum, X_INFO, 3,
+ "xf86UnbindGARTMemory: unbind key %d\n", key);
+
+ return TRUE;
+}
+
+
+/* XXX Interface may change. */
+Bool
+xf86EnableAGP(int screenNum, CARD32 mode)
+{
+ agp_setup_t setup;
+
+ if (!GARTInit(screenNum) || (acquiredScreen != screenNum))
+ return FALSE;
+
+ setup.agps_mode = mode;
+ if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) {
+ xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: "
+ "AGPIOC_SETUP with mode %x failed (%s)\n",
+ (unsigned int) mode, strerror(errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
diff --git a/xorg-server/hw/xnest/Init.c b/xorg-server/hw/xnest/Init.c
index ee74101d2..ea0669a6a 100644
--- a/xorg-server/hw/xnest/Init.c
+++ b/xorg-server/hw/xnest/Init.c
@@ -108,6 +108,7 @@ InitInput(int argc, char *argv[])
void
CloseInput(void)
{
+ mieqFini();
}
/*
diff --git a/xorg-server/hw/xquartz/darwin.c b/xorg-server/hw/xquartz/darwin.c
index 29ab83677..73685b0d4 100644
--- a/xorg-server/hw/xquartz/darwin.c
+++ b/xorg-server/hw/xquartz/darwin.c
@@ -505,6 +505,10 @@ void InitInput( int argc, char **argv )
QuartzInitInput(argc, argv);
}
+void CloseInput(void)
+{
+ DarwinEQFini();
+}
/*
* DarwinAdjustScreenOrigins
diff --git a/xorg-server/hw/xquartz/darwinEvents.c b/xorg-server/hw/xquartz/darwinEvents.c
index fe744b741..1f22099d6 100644
--- a/xorg-server/hw/xquartz/darwinEvents.c
+++ b/xorg-server/hw/xquartz/darwinEvents.c
@@ -371,6 +371,10 @@ Bool DarwinEQInit(void) {
return TRUE;
}
+Bool DarwinEQFini(void) {
+ mieqFini();
+}
+
/*
* ProcessInputEvents
* Read and process events from the event queue until it is empty.
diff --git a/xorg-server/hw/xquartz/darwinEvents.h b/xorg-server/hw/xquartz/darwinEvents.h
index 6769c8bd8..bd29d51fd 100644
--- a/xorg-server/hw/xquartz/darwinEvents.h
+++ b/xorg-server/hw/xquartz/darwinEvents.h
@@ -32,6 +32,7 @@
#define XQUARTZ_VALUATOR_LIMIT (1 << 16)
Bool DarwinEQInit(void);
+Bool DarwinEQFini(void);
void DarwinEQEnqueue(const xEventPtr e);
void DarwinEQPointerPost(DeviceIntPtr pDev, xEventPtr e);
void DarwinEQSwitchScreen(ScreenPtr pScreen, Bool fromDIX);
diff --git a/xorg-server/hw/xquartz/darwinXinput.c b/xorg-server/hw/xquartz/darwinXinput.c
index 3ef34fec0..94c31bb23 100644
--- a/xorg-server/hw/xquartz/darwinXinput.c
+++ b/xorg-server/hw/xquartz/darwinXinput.c
@@ -149,8 +149,3 @@ DeleteInputDeviceRequest(DeviceIntPtr dev)
DEBUG_LOG("DeleteInputDeviceRequest(%p)\n", dev);
}
-void
-CloseInput (void)
-{
-}
-
diff --git a/xorg-server/hw/xwin/InitInput.c b/xorg-server/hw/xwin/InitInput.c
index 5f51fc457..bc48a9360 100644
--- a/xorg-server/hw/xwin/InitInput.c
+++ b/xorg-server/hw/xwin/InitInput.c
@@ -1,159 +1,160 @@
-/*
-
- Copyright 1993, 1998 The Open Group
-
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-
- Except as contained in this notice, the name of The Open Group shall
- not be used in advertising or otherwise to promote the sale, use or
- other dealings in this Software without prior written authorization
- from The Open Group.
-
-*/
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include "dixstruct.h"
-#include "inputstr.h"
-
-
-/*
- * Local function prototypes
- */
-
-#ifdef XWIN_CLIPBOARD
-int winProcEstablishConnection(ClientPtr /* client */);
-int winProcQueryTree(ClientPtr /* client */);
-int winProcSetSelectionOwner(ClientPtr /* client */);
-#endif
-
-
-/*
- * Local global declarations
- */
-
-DeviceIntPtr g_pwinPointer;
-DeviceIntPtr g_pwinKeyboard;
-
-/* Called from dix/devices.c */
-/*
- * All of our keys generate up and down transition notifications,
- * so all of our keys can be used as modifiers.
- *
- * An example of a modifier is mapping the A key to the Control key.
- * A has to be a legal modifier. I think.
- */
-
-Bool
-LegalModifier (unsigned int uiKey, DeviceIntPtr pDevice)
-{
- return TRUE;
-}
-
-
-/* Called from dix/dispatch.c */
-/*
- * Run through the Windows message queue(s) one more time.
- * Tell mi to dequeue the events that we have sent it.
- */
-void
-ProcessInputEvents (void)
-{
-#if 0
- ErrorF ("ProcessInputEvents\n");
-#endif
-
- mieqProcessInputEvents ();
-
-#if 0
- ErrorF ("ProcessInputEvents - returning\n");
-#endif
-}
-
-
-void DDXRingBell(int volume, int pitch, int duration)
-{
- /* winKeybdBell is used instead */
- return;
-}
-
-
-/* See Porting Layer Definition - p. 17 */
-void
-InitInput (int argc, char *argv[])
-{
-#if CYGDEBUG
- winDebug ("InitInput\n");
-#endif
-
-#ifdef XWIN_CLIPBOARD
- /*
- * Wrap some functions at every generation of the server.
- */
- if (InitialVector[2] != winProcEstablishConnection)
- {
- winProcEstablishConnectionOrig = InitialVector[2];
- InitialVector[2] = winProcEstablishConnection;
- }
- if (g_fXdmcpEnabled
- && ProcVector[X_QueryTree] != winProcQueryTree)
- {
- winProcQueryTreeOrig = ProcVector[X_QueryTree];
- ProcVector[X_QueryTree] = winProcQueryTree;
- }
-#endif
-
- g_pwinPointer = AddInputDevice (serverClient, winMouseProc, TRUE);
- g_pwinKeyboard = AddInputDevice (serverClient, winKeybdProc, TRUE);
- g_pwinPointer->name = strdup("Windows mouse");
- g_pwinKeyboard->name = strdup("Windows keyboard");
-
- mieqInit ();
-
- /* Initialize the mode key states */
- winInitializeModeKeyStates ();
-
-#ifdef HAS_DEVWINDOWS
- /* Only open the windows message queue device once */
- if (g_fdMessageQueue == WIN_FD_INVALID)
- {
- /* Open a file descriptor for the Windows message queue */
- g_fdMessageQueue = open (WIN_MSG_QUEUE_FNAME, O_RDONLY);
-
- if (g_fdMessageQueue == -1)
- {
- FatalError ("InitInput - Failed opening %s\n",
- WIN_MSG_QUEUE_FNAME);
- }
-
- /* Add the message queue as a device to wait for in WaitForSomething */
- AddEnabledDevice (g_fdMessageQueue);
- }
-#endif
-
-#if CYGDEBUG
- winDebug ("InitInput - returning\n");
-#endif
-}
-
-void
-CloseInput (void)
-{
-}
+/*
+
+ Copyright 1993, 1998 The Open Group
+
+ Permission to use, copy, modify, distribute, and sell this software and its
+ documentation for any purpose is hereby granted without fee, provided that
+ the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation.
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the name of The Open Group shall
+ not be used in advertising or otherwise to promote the sale, use or
+ other dealings in this Software without prior written authorization
+ from The Open Group.
+
+*/
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include "dixstruct.h"
+#include "inputstr.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+#ifdef XWIN_CLIPBOARD
+int winProcEstablishConnection(ClientPtr /* client */);
+int winProcQueryTree(ClientPtr /* client */);
+int winProcSetSelectionOwner(ClientPtr /* client */);
+#endif
+
+
+/*
+ * Local global declarations
+ */
+
+DeviceIntPtr g_pwinPointer;
+DeviceIntPtr g_pwinKeyboard;
+
+/* Called from dix/devices.c */
+/*
+ * All of our keys generate up and down transition notifications,
+ * so all of our keys can be used as modifiers.
+ *
+ * An example of a modifier is mapping the A key to the Control key.
+ * A has to be a legal modifier. I think.
+ */
+
+Bool
+LegalModifier (unsigned int uiKey, DeviceIntPtr pDevice)
+{
+ return TRUE;
+}
+
+
+/* Called from dix/dispatch.c */
+/*
+ * Run through the Windows message queue(s) one more time.
+ * Tell mi to dequeue the events that we have sent it.
+ */
+void
+ProcessInputEvents (void)
+{
+#if 0
+ ErrorF ("ProcessInputEvents\n");
+#endif
+
+ mieqProcessInputEvents ();
+
+#if 0
+ ErrorF ("ProcessInputEvents - returning\n");
+#endif
+}
+
+
+void DDXRingBell(int volume, int pitch, int duration)
+{
+ /* winKeybdBell is used instead */
+ return;
+}
+
+
+/* See Porting Layer Definition - p. 17 */
+void
+InitInput (int argc, char *argv[])
+{
+#if CYGDEBUG
+ winDebug ("InitInput\n");
+#endif
+
+#ifdef XWIN_CLIPBOARD
+ /*
+ * Wrap some functions at every generation of the server.
+ */
+ if (InitialVector[2] != winProcEstablishConnection)
+ {
+ winProcEstablishConnectionOrig = InitialVector[2];
+ InitialVector[2] = winProcEstablishConnection;
+ }
+ if (g_fXdmcpEnabled
+ && ProcVector[X_QueryTree] != winProcQueryTree)
+ {
+ winProcQueryTreeOrig = ProcVector[X_QueryTree];
+ ProcVector[X_QueryTree] = winProcQueryTree;
+ }
+#endif
+
+ g_pwinPointer = AddInputDevice (serverClient, winMouseProc, TRUE);
+ g_pwinKeyboard = AddInputDevice (serverClient, winKeybdProc, TRUE);
+ g_pwinPointer->name = strdup("Windows mouse");
+ g_pwinKeyboard->name = strdup("Windows keyboard");
+
+ mieqInit ();
+
+ /* Initialize the mode key states */
+ winInitializeModeKeyStates ();
+
+#ifdef HAS_DEVWINDOWS
+ /* Only open the windows message queue device once */
+ if (g_fdMessageQueue == WIN_FD_INVALID)
+ {
+ /* Open a file descriptor for the Windows message queue */
+ g_fdMessageQueue = open (WIN_MSG_QUEUE_FNAME, O_RDONLY);
+
+ if (g_fdMessageQueue == -1)
+ {
+ FatalError ("InitInput - Failed opening %s\n",
+ WIN_MSG_QUEUE_FNAME);
+ }
+
+ /* Add the message queue as a device to wait for in WaitForSomething */
+ AddEnabledDevice (g_fdMessageQueue);
+ }
+#endif
+
+#if CYGDEBUG
+ winDebug ("InitInput - returning\n");
+#endif
+}
+
+void
+CloseInput (void)
+{
+ mieqFini ();
+}
diff --git a/xorg-server/include/dixgrabs.h b/xorg-server/include/dixgrabs.h
index 3b2a46d72..229c8bb53 100644
--- a/xorg-server/include/dixgrabs.h
+++ b/xorg-server/include/dixgrabs.h
@@ -28,6 +28,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
struct _GrabParameters;
+extern void PrintDeviceGrabInfo(DeviceIntPtr dev);
+extern void UngrabAllDevices(Bool kill_client);
+
extern GrabPtr CreateGrab(
int /* client */,
DeviceIntPtr /* device */,
diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h
index 56847ed8d..5377a0c13 100644
--- a/xorg-server/include/input.h
+++ b/xorg-server/include/input.h
@@ -62,10 +62,11 @@ SOFTWARE.
#define DEVICE_OFF 2
#define DEVICE_CLOSE 3
-#define POINTER_RELATIVE (1 << 1)
-#define POINTER_ABSOLUTE (1 << 2)
-#define POINTER_ACCELERATE (1 << 3)
-#define POINTER_SCREEN (1 << 4) /* Data in screen coordinates */
+#define POINTER_RELATIVE (1 << 1)
+#define POINTER_ABSOLUTE (1 << 2)
+#define POINTER_ACCELERATE (1 << 3)
+#define POINTER_SCREEN (1 << 4) /* Data in screen coordinates */
+#define POINTER_NORAW (1 << 5) /* Don't generate RawEvents */
/*int constants for pointer acceleration schemes*/
#define PtrAccelNoOp 0
diff --git a/xorg-server/include/window.h b/xorg-server/include/window.h
index 1e4e9bfa4..e13598b88 100644
--- a/xorg-server/include/window.h
+++ b/xorg-server/include/window.h
@@ -267,4 +267,6 @@ extern _X_EXPORT void EnableMapUnmapEvents(
WindowPtr /* pWin */ );
extern _X_EXPORT void SetRootClip(ScreenPtr pScreen, Bool enable);
+extern _X_EXPORT void PrintWindowTree(void);
+
#endif /* WINDOW_H */
diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c
index 322be9e44..7680ca19b 100644
--- a/xorg-server/mi/mipointer.c
+++ b/xorg-server/mi/mipointer.c
@@ -683,7 +683,7 @@ miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
valuator_mask_set_range(&mask, 0, 2, valuators);
nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
- POINTER_SCREEN | POINTER_ABSOLUTE, &mask);
+ POINTER_SCREEN | POINTER_ABSOLUTE | POINTER_NORAW, &mask);
OsBlockSignals();
#ifdef XQUARTZ
diff --git a/xorg-server/miext/shadow/shadow.c b/xorg-server/miext/shadow/shadow.c
index 7bc1d9ca0..95f11cd21 100644
--- a/xorg-server/miext/shadow/shadow.c
+++ b/xorg-server/miext/shadow/shadow.c
@@ -1,252 +1,252 @@
-/*
- * Copyright © 2000 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdlib.h>
-
-#include <X11/X.h>
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "dixfontstr.h"
-#include "mi.h"
-#include "regionstr.h"
-#include "globals.h"
-#include "gcstruct.h"
-#include "shadow.h"
-
-static DevPrivateKeyRec shadowScrPrivateKeyRec;
-#define shadowScrPrivateKey (&shadowScrPrivateKeyRec)
-
-#define wrap(priv, real, mem) {\
- priv->mem = real->mem; \
- real->mem = shadow##mem; \
-}
-
-#define unwrap(priv, real, mem) {\
- real->mem = priv->mem; \
-}
-
-static void
-shadowRedisplay(ScreenPtr pScreen)
-{
- shadowBuf(pScreen);
- RegionPtr pRegion;
-
- if (!pBuf || !pBuf->pDamage || !pBuf->update)
- return;
- pRegion = DamageRegion(pBuf->pDamage);
- if (RegionNotEmpty(pRegion)) {
- (*pBuf->update)(pScreen, pBuf);
- DamageEmpty(pBuf->pDamage);
- }
-}
-
-static void
-shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
-{
- ScreenPtr pScreen = (ScreenPtr) data;
-
- shadowRedisplay(pScreen);
-}
-
-static void
-shadowWakeupHandler(pointer data, int i, pointer LastSelectMask)
-{
-}
-
-static void
-shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
- unsigned int format, unsigned long planeMask, char *pdstLine)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- shadowBuf(pScreen);
-
- /* Many apps use GetImage to sync with the visable frame buffer */
- if (pDrawable->type == DRAWABLE_WINDOW)
- shadowRedisplay(pScreen);
- unwrap(pBuf, pScreen, GetImage);
- pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
- wrap(pBuf, pScreen, GetImage);
-}
-
-#define BACKWARDS_COMPATIBILITY
-
-static Bool
-shadowCloseScreen(int i, ScreenPtr pScreen)
-{
- shadowBuf(pScreen);
-
- unwrap(pBuf, pScreen, GetImage);
- unwrap(pBuf, pScreen, CloseScreen);
- shadowRemove(pScreen, pBuf->pPixmap);
- DamageDestroy(pBuf->pDamage);
-#ifdef BACKWARDS_COMPATIBILITY
- RegionUninit(&pBuf->damage); /* bc */
-#endif
- if (pBuf->pPixmap)
- pScreen->DestroyPixmap(pBuf->pPixmap);
- free(pBuf);
- return pScreen->CloseScreen(i, pScreen);
-}
-
-#ifdef BACKWARDS_COMPATIBILITY
-static void
-shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure)
-{
- ScreenPtr pScreen = closure;
- shadowBufPtr pBuf = (shadowBufPtr)
- dixLookupPrivate(&pScreen->devPrivates, shadowScrPrivateKey);
-
- /* Register the damaged region, use DamageReportNone below when we
- * want to break BC below... */
- RegionUnion(&pDamage->damage, &pDamage->damage, pRegion);
-
- /*
- * BC hack. In 7.0 and earlier several drivers would inspect the
- * 'damage' member directly, so we have to keep it existing.
- */
- RegionCopy(&pBuf->damage, pRegion);
-}
-#endif
-
-Bool
-shadowSetup(ScreenPtr pScreen)
-{
- shadowBufPtr pBuf;
-
- if (!dixRegisterPrivateKey(&shadowScrPrivateKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- if (!DamageSetup(pScreen))
- return FALSE;
-
- pBuf = malloc(sizeof(shadowBufRec));
- if (!pBuf)
- return FALSE;
-#ifdef BACKWARDS_COMPATIBILITY
- pBuf->pDamage = DamageCreate((DamageReportFunc)shadowReportFunc,
- (DamageDestroyFunc)NULL,
- DamageReportRawRegion,
- TRUE, pScreen, pScreen);
-#else
- pBuf->pDamage = DamageCreate((DamageReportFunc)NULL,
- (DamageDestroyFunc)NULL,
- DamageReportNone,
- TRUE, pScreen, pScreen);
-#endif
- if (!pBuf->pDamage) {
- free(pBuf);
- return FALSE;
- }
-
- wrap(pBuf, pScreen, CloseScreen);
- wrap(pBuf, pScreen, GetImage);
- pBuf->update = 0;
- pBuf->window = 0;
- pBuf->pPixmap = 0;
- pBuf->closure = 0;
- pBuf->randr = 0;
-#ifdef BACKWARDS_COMPATIBILITY
- RegionNull(&pBuf->damage); /* bc */
-#endif
-
- dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf);
- return TRUE;
-}
-
-Bool
-shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update,
- ShadowWindowProc window, int randr, void *closure)
-{
- shadowBuf(pScreen);
-
- if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
- (pointer)pScreen))
- return FALSE;
-
- /*
- * Map simple rotation values to bitmasks; fortunately,
- * these are all unique
- */
- switch (randr) {
- case 0:
- randr = SHADOW_ROTATE_0;
- break;
- case 90:
- randr = SHADOW_ROTATE_90;
- break;
- case 180:
- randr = SHADOW_ROTATE_180;
- break;
- case 270:
- randr = SHADOW_ROTATE_270;
- break;
- }
- pBuf->update = update;
- pBuf->window = window;
- pBuf->randr = randr;
- pBuf->closure = closure;
- pBuf->pPixmap = pPixmap;
- DamageRegister(&pPixmap->drawable, pBuf->pDamage);
- return TRUE;
-}
-
-void
-shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap)
-{
- shadowBuf(pScreen);
-
- if (pBuf->pPixmap) {
- DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage);
- pBuf->update = 0;
- pBuf->window = 0;
- pBuf->randr = 0;
- pBuf->closure = 0;
- pBuf->pPixmap = 0;
- }
-
- RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
- (pointer) pScreen);
-}
-
-Bool
-shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window)
-{
- PixmapPtr pPixmap;
-
- pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height,
- pScreen->rootDepth, 0);
- if (!pPixmap)
- return FALSE;
-
- if (!shadowSetup(pScreen)) {
- pScreen->DestroyPixmap(pPixmap);
- return FALSE;
- }
-
- shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0);
-
- return TRUE;
-}
+/*
+ * Copyright © 2000 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "dixfontstr.h"
+#include "mi.h"
+#include "regionstr.h"
+#include "globals.h"
+#include "gcstruct.h"
+#include "shadow.h"
+
+static DevPrivateKeyRec shadowScrPrivateKeyRec;
+#define shadowScrPrivateKey (&shadowScrPrivateKeyRec)
+
+#define wrap(priv, real, mem) {\
+ priv->mem = real->mem; \
+ real->mem = shadow##mem; \
+}
+
+#define unwrap(priv, real, mem) {\
+ real->mem = priv->mem; \
+}
+
+static void
+shadowRedisplay(ScreenPtr pScreen)
+{
+ shadowBuf(pScreen);
+ RegionPtr pRegion;
+
+ if (!pBuf || !pBuf->pDamage || !pBuf->update)
+ return;
+ pRegion = DamageRegion(pBuf->pDamage);
+ if (RegionNotEmpty(pRegion)) {
+ (*pBuf->update)(pScreen, pBuf);
+ DamageEmpty(pBuf->pDamage);
+ }
+}
+
+static void
+shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
+{
+ ScreenPtr pScreen = (ScreenPtr) data;
+
+ shadowRedisplay(pScreen);
+}
+
+static void
+shadowWakeupHandler(pointer data, int i, pointer LastSelectMask)
+{
+}
+
+static void
+shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
+ unsigned int format, unsigned long planeMask, char *pdstLine)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ shadowBuf(pScreen);
+
+ /* Many apps use GetImage to sync with the visable frame buffer */
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ shadowRedisplay(pScreen);
+ unwrap(pBuf, pScreen, GetImage);
+ pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
+ wrap(pBuf, pScreen, GetImage);
+}
+
+#define BACKWARDS_COMPATIBILITY
+
+static Bool
+shadowCloseScreen(int i, ScreenPtr pScreen)
+{
+ shadowBuf(pScreen);
+
+ unwrap(pBuf, pScreen, GetImage);
+ unwrap(pBuf, pScreen, CloseScreen);
+ shadowRemove(pScreen, pBuf->pPixmap);
+ DamageDestroy(pBuf->pDamage);
+#ifdef BACKWARDS_COMPATIBILITY
+ RegionUninit(&pBuf->damage); /* bc */
+#endif
+ if (pBuf->pPixmap)
+ pScreen->DestroyPixmap(pBuf->pPixmap);
+ free(pBuf);
+ return pScreen->CloseScreen(i, pScreen);
+}
+
+#ifdef BACKWARDS_COMPATIBILITY
+static void
+shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+ ScreenPtr pScreen = closure;
+ shadowBufPtr pBuf = (shadowBufPtr)
+ dixLookupPrivate(&pScreen->devPrivates, shadowScrPrivateKey);
+
+ /* Register the damaged region, use DamageReportNone below when we
+ * want to break BC below... */
+ RegionUnion(&pDamage->damage, &pDamage->damage, pRegion);
+
+ /*
+ * BC hack. In 7.0 and earlier several drivers would inspect the
+ * 'damage' member directly, so we have to keep it existing.
+ */
+ RegionCopy(&pBuf->damage, pRegion);
+}
+#endif
+
+Bool
+shadowSetup(ScreenPtr pScreen)
+{
+ shadowBufPtr pBuf;
+
+ if (!dixRegisterPrivateKey(&shadowScrPrivateKeyRec, PRIVATE_SCREEN, 0))
+ return FALSE;
+
+ if (!DamageSetup(pScreen))
+ return FALSE;
+
+ pBuf = malloc(sizeof(shadowBufRec));
+ if (!pBuf)
+ return FALSE;
+#ifdef BACKWARDS_COMPATIBILITY
+ pBuf->pDamage = DamageCreate((DamageReportFunc)shadowReportFunc,
+ (DamageDestroyFunc)NULL,
+ DamageReportRawRegion,
+ TRUE, pScreen, pScreen);
+#else
+ pBuf->pDamage = DamageCreate((DamageReportFunc)NULL,
+ (DamageDestroyFunc)NULL,
+ DamageReportNone,
+ TRUE, pScreen, pScreen);
+#endif
+ if (!pBuf->pDamage) {
+ free(pBuf);
+ return FALSE;
+ }
+
+ wrap(pBuf, pScreen, CloseScreen);
+ wrap(pBuf, pScreen, GetImage);
+ pBuf->update = 0;
+ pBuf->window = 0;
+ pBuf->pPixmap = 0;
+ pBuf->closure = 0;
+ pBuf->randr = 0;
+#ifdef BACKWARDS_COMPATIBILITY
+ RegionNull(&pBuf->damage); /* bc */
+#endif
+
+ dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf);
+ return TRUE;
+}
+
+Bool
+shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update,
+ ShadowWindowProc window, int randr, void *closure)
+{
+ shadowBuf(pScreen);
+
+ if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
+ (pointer)pScreen))
+ return FALSE;
+
+ /*
+ * Map simple rotation values to bitmasks; fortunately,
+ * these are all unique
+ */
+ switch (randr) {
+ case 0:
+ randr = SHADOW_ROTATE_0;
+ break;
+ case 90:
+ randr = SHADOW_ROTATE_90;
+ break;
+ case 180:
+ randr = SHADOW_ROTATE_180;
+ break;
+ case 270:
+ randr = SHADOW_ROTATE_270;
+ break;
+ }
+ pBuf->update = update;
+ pBuf->window = window;
+ pBuf->randr = randr;
+ pBuf->closure = closure;
+ pBuf->pPixmap = pPixmap;
+ DamageRegister(&pPixmap->drawable, pBuf->pDamage);
+ return TRUE;
+}
+
+void
+shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap)
+{
+ shadowBuf(pScreen);
+
+ if (pBuf->pPixmap) {
+ DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage);
+ pBuf->update = 0;
+ pBuf->window = 0;
+ pBuf->randr = 0;
+ pBuf->closure = 0;
+ pBuf->pPixmap = 0;
+ }
+
+ RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
+ (pointer) pScreen);
+}
+
+Bool
+shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window)
+{
+ PixmapPtr pPixmap;
+
+ pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height,
+ pScreen->rootDepth, 0);
+ if (!pPixmap)
+ return FALSE;
+
+ if (!shadowSetup(pScreen)) {
+ pScreen->DestroyPixmap(pPixmap);
+ return FALSE;
+ }
+
+ shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0);
+
+ return TRUE;
+}
diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am
index 370e09a18..7ef408c93 100644
--- a/xorg-server/test/Makefile.am
+++ b/xorg-server/test/Makefile.am
@@ -40,5 +40,6 @@ libxservertest_la_LIBADD = \
$(top_builddir)/mi/libmi.la \
$(top_builddir)/os/libos.la \
@XORG_LIBS@
+libxservertest_la_DEPENDENCIES = $(libxservertest_la_LIBADD)
endif
endif
diff --git a/xorg-server/test/xi2/protocol-eventconvert.c b/xorg-server/test/xi2/protocol-eventconvert.c
index edba974bf..6e61d74b4 100644
--- a/xorg-server/test/xi2/protocol-eventconvert.c
+++ b/xorg-server/test/xi2/protocol-eventconvert.c
@@ -70,6 +70,8 @@ static void test_values_XIRawEvent(RawDeviceEvent *in, xXIRawEvent *out,
for (i = 0; out->valuators_len && i < sizeof(in->valuators.mask) * 8; i++)
{
+ if (i >= MAX_VALUATORS)
+ assert (!XIMaskIsSet(in->valuators.mask, i));
assert (XIMaskIsSet(in->valuators.mask, i) == XIMaskIsSet(ptr, i));
if (XIMaskIsSet(in->valuators.mask, i))
bits_set++;
@@ -238,7 +240,7 @@ static void test_convert_XIRawEvent(void)
test_XIRawEvent(&in);
printf("Testing valuator masks\n");
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ for (i = 0; i < MAX_VALUATORS; i++)
{
XISetMask(in.valuators.mask, i);
test_XIRawEvent(&in);
@@ -257,7 +259,7 @@ static void test_convert_XIRawEvent(void)
XIClearMask(in.valuators.mask, i);
}
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ for (i = 0; i < MAX_VALUATORS; i++)
{
XISetMask(in.valuators.mask, i);
test_XIRawEvent(&in);
@@ -354,7 +356,7 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
valuators = 0;
- for (i = 0; i < sizeof(in->valuators.mask) * 8; i++)
+ for (i = 0; i < MAX_VALUATORS; i++)
if (XIMaskIsSet(in->valuators.mask, i))
valuators++;
@@ -365,7 +367,9 @@ static void test_values_XIDeviceEvent(DeviceEvent *in, xXIDeviceEvent *out,
for (i = 0; i < sizeof(in->valuators.mask) * 8 ||
i < (out->valuators_len * 4) * 8; i++)
{
- if (i > sizeof(in->valuators.mask) * 8)
+ if (i >= MAX_VALUATORS)
+ assert(!XIMaskIsSet(in->valuators.mask, i) && !XIMaskIsSet(ptr, i));
+ else if (i > sizeof(in->valuators.mask) * 8)
assert(!XIMaskIsSet(ptr, i));
else if (i > out->valuators_len * 4 * 8)
assert(!XIMaskIsSet(in->valuators.mask, i));
@@ -610,14 +614,14 @@ static void test_convert_XIDeviceEvent(void)
}
printf("Testing valuator masks\n");
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ for (i = 0; i < MAX_VALUATORS; i++)
{
XISetMask(in.valuators.mask, i);
test_XIDeviceEvent(&in);
XIClearMask(in.valuators.mask, i);
}
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ for (i = 0; i < MAX_VALUATORS; i++)
{
XISetMask(in.valuators.mask, i);
@@ -627,7 +631,7 @@ static void test_convert_XIDeviceEvent(void)
XIClearMask(in.valuators.mask, i);
}
- for (i = 0; i < sizeof(in.valuators.mask) * 8; i++)
+ for (i = 0; i < MAX_VALUATORS; i++)
{
XISetMask(in.valuators.mask, i);
test_XIDeviceEvent(&in);