diff options
Diffstat (limited to 'xorg-server')
-rw-r--r-- | xorg-server/damageext/damageext.c | 1042 | ||||
-rw-r--r-- | xorg-server/dix/cursor.c | 1027 | ||||
-rw-r--r-- | xorg-server/dix/dispatch.c | 12 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86xv.c | 4373 | ||||
-rw-r--r-- | xorg-server/hw/xfree86/loader/loadmod.c | 32 | ||||
-rw-r--r-- | xorg-server/miext/damage/damage.c | 101 | ||||
-rw-r--r-- | xorg-server/miext/damage/damage.h | 4 | ||||
-rw-r--r-- | xorg-server/os/connection.c | 2615 | ||||
-rw-r--r-- | xorg-server/randr/rrdispatch.c | 32 | ||||
-rw-r--r-- | xorg-server/render/render.c | 12 | ||||
-rw-r--r-- | xorg-server/xkeyboard-config/rules/compat/variantsMapping.lst | 1 | ||||
-rw-r--r-- | xorg-server/xkeyboard-config/symbols/hu | 2 |
12 files changed, 4646 insertions, 4607 deletions
diff --git a/xorg-server/damageext/damageext.c b/xorg-server/damageext/damageext.c index 2b1514872..02db88a8e 100644 --- a/xorg-server/damageext/damageext.c +++ b/xorg-server/damageext/damageext.c @@ -1,521 +1,521 @@ -/*
- * Copyright © 2002 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 "damageextint.h"
-#include "protocol-versions.h"
-
-static unsigned char DamageReqCode;
-static int DamageEventBase;
-static RESTYPE DamageExtType;
-static RESTYPE DamageExtWinType;
-
-static DevPrivateKeyRec DamageClientPrivateKeyRec;
-#define DamageClientPrivateKey (&DamageClientPrivateKeyRec)
-
-static void
-DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
-{
- ClientPtr pClient = pDamageExt->pClient;
- DamageClientPtr pDamageClient = GetDamageClient (pClient);
- DrawablePtr pDrawable = pDamageExt->pDrawable;
- xDamageNotifyEvent ev;
- int i;
-
- UpdateCurrentTimeIf ();
- ev.type = DamageEventBase + XDamageNotify;
- ev.level = pDamageExt->level;
- ev.drawable = pDamageExt->drawable;
- ev.damage = pDamageExt->id;
- ev.timestamp = currentTime.milliseconds;
- ev.geometry.x = pDrawable->x;
- ev.geometry.y = pDrawable->y;
- ev.geometry.width = pDrawable->width;
- ev.geometry.height = pDrawable->height;
- if (pBoxes)
- {
- for (i = 0; i < nBoxes; i++)
- {
- ev.level = pDamageExt->level;
- if (i < nBoxes - 1)
- ev.level |= DamageNotifyMore;
- ev.area.x = pBoxes[i].x1;
- ev.area.y = pBoxes[i].y1;
- ev.area.width = pBoxes[i].x2 - pBoxes[i].x1;
- ev.area.height = pBoxes[i].y2 - pBoxes[i].y1;
- WriteEventsToClient (pClient, 1, (xEvent *) &ev);
- }
- }
- else
- {
- ev.area.x = 0;
- ev.area.y = 0;
- ev.area.width = pDrawable->width;
- ev.area.height = pDrawable->height;
- WriteEventsToClient (pClient, 1, (xEvent *) &ev);
- }
- /* Composite extension marks clients with manual Subwindows as critical */
- if (pDamageClient->critical > 0)
- {
- SetCriticalOutputPending ();
- pClient->smart_priority = SMART_MAX_PRIORITY;
- }
-}
-
-static void
-DamageExtReport (DamagePtr pDamage, RegionPtr pRegion, void *closure)
-{
- DamageExtPtr pDamageExt = closure;
-
- switch (pDamageExt->level) {
- case DamageReportRawRegion:
- case DamageReportDeltaRegion:
- DamageExtNotify (pDamageExt, RegionRects(pRegion), RegionNumRects(pRegion));
- break;
- case DamageReportBoundingBox:
- DamageExtNotify (pDamageExt, RegionExtents(pRegion), 1);
- break;
- case DamageReportNonEmpty:
- DamageExtNotify (pDamageExt, NullBox, 0);
- break;
- case DamageReportNone:
- break;
- }
-}
-
-static void
-DamageExtDestroy (DamagePtr pDamage, void *closure)
-{
- DamageExtPtr pDamageExt = closure;
-
- pDamageExt->pDamage = 0;
- if (pDamageExt->id)
- FreeResource (pDamageExt->id, RT_NONE);
-}
-
-void
-DamageExtSetCritical (ClientPtr pClient, Bool critical)
-{
- DamageClientPtr pDamageClient = GetDamageClient (pClient);
-
- if (pDamageClient)
- pDamageClient->critical += critical ? 1 : -1;
-}
-
-static int
-ProcDamageQueryVersion(ClientPtr client)
-{
- DamageClientPtr pDamageClient = GetDamageClient (client);
- xDamageQueryVersionReply rep;
- register int n;
- REQUEST(xDamageQueryVersionReq);
-
- REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- if (stuff->majorVersion < SERVER_DAMAGE_MAJOR_VERSION) {
- rep.majorVersion = stuff->majorVersion;
- rep.minorVersion = stuff->minorVersion;
- } else {
- rep.majorVersion = SERVER_DAMAGE_MAJOR_VERSION;
- if (stuff->majorVersion == SERVER_DAMAGE_MAJOR_VERSION &&
- stuff->minorVersion < SERVER_DAMAGE_MINOR_VERSION)
- rep.minorVersion = stuff->minorVersion;
- else
- rep.minorVersion = SERVER_DAMAGE_MINOR_VERSION;
- }
- pDamageClient->major_version = rep.majorVersion;
- pDamageClient->minor_version = rep.minorVersion;
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.majorVersion, n);
- swapl(&rep.minorVersion, n);
- }
- WriteToClient(client, sizeof(xDamageQueryVersionReply), (char *)&rep);
- return Success;
-}
-
-static int
-ProcDamageCreate (ClientPtr client)
-{
- DrawablePtr pDrawable;
- DamageExtPtr pDamageExt;
- DamageReportLevel level;
- RegionPtr pRegion;
- int rc;
-
- REQUEST(xDamageCreateReq);
-
- REQUEST_SIZE_MATCH(xDamageCreateReq);
- LEGAL_NEW_RESOURCE(stuff->damage, client);
- rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
- DixGetAttrAccess|DixReadAccess);
- if (rc != Success)
- return rc;
-
- switch (stuff->level) {
- case XDamageReportRawRectangles:
- level = DamageReportRawRegion;
- break;
- case XDamageReportDeltaRectangles:
- level = DamageReportDeltaRegion;
- break;
- case XDamageReportBoundingBox:
- level = DamageReportBoundingBox;
- break;
- case XDamageReportNonEmpty:
- level = DamageReportNonEmpty;
- break;
- default:
- client->errorValue = stuff->level;
- return BadValue;
- }
-
- pDamageExt = malloc(sizeof (DamageExtRec));
- if (!pDamageExt)
- return BadAlloc;
- pDamageExt->id = stuff->damage;
- pDamageExt->drawable = stuff->drawable;
- pDamageExt->pDrawable = pDrawable;
- pDamageExt->level = level;
- pDamageExt->pClient = client;
- pDamageExt->pDamage = DamageCreate (DamageExtReport,
- DamageExtDestroy,
- level,
- FALSE,
- pDrawable->pScreen,
- pDamageExt);
- if (!pDamageExt->pDamage)
- {
- free(pDamageExt);
- return BadAlloc;
- }
- if (!AddResource (stuff->damage, DamageExtType, (pointer) pDamageExt))
- return BadAlloc;
-
- DamageSetReportAfterOp (pDamageExt->pDamage, TRUE);
- DamageRegister (pDamageExt->pDrawable, pDamageExt->pDamage);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- pRegion = &((WindowPtr) pDrawable)->borderClip;
- DamageDamageRegion(pDrawable, pRegion);
- }
-
- return Success;
-}
-
-static int
-ProcDamageDestroy (ClientPtr client)
-{
- REQUEST(xDamageDestroyReq);
- DamageExtPtr pDamageExt;
-
- REQUEST_SIZE_MATCH(xDamageDestroyReq);
- VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
- FreeResource (stuff->damage, RT_NONE);
- return Success;
-}
-
-static int
-ProcDamageSubtract (ClientPtr client)
-{
- REQUEST(xDamageSubtractReq);
- DamageExtPtr pDamageExt;
- RegionPtr pRepair;
- RegionPtr pParts;
-
- REQUEST_SIZE_MATCH(xDamageSubtractReq);
- VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
- VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess);
- VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess);
-
- if (pDamageExt->level != DamageReportRawRegion)
- {
- DamagePtr pDamage = pDamageExt->pDamage;
- if (pRepair)
- {
- if (pParts)
- RegionIntersect(pParts, DamageRegion (pDamage), pRepair);
- if (DamageSubtract (pDamage, pRepair))
- DamageExtReport (pDamage, DamageRegion (pDamage), (void *) pDamageExt);
- }
- else
- {
- if (pParts)
- RegionCopy(pParts, DamageRegion (pDamage));
- DamageEmpty (pDamage);
- }
- }
- return Success;
-}
-
-static int
-ProcDamageAdd (ClientPtr client)
-{
- REQUEST(xDamageAddReq);
- DrawablePtr pDrawable;
- RegionPtr pRegion;
- int rc;
-
- REQUEST_SIZE_MATCH(xDamageAddReq);
- VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
- rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
- DixWriteAccess);
- if (rc != Success)
- return rc;
-
- /* The region is relative to the drawable origin, so translate it out to
- * screen coordinates like damage expects.
- */
- RegionTranslate(pRegion, pDrawable->x, pDrawable->y);
- DamageDamageRegion(pDrawable, pRegion);
- RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y);
-
- return Success;
-}
-
-/* Major version controls available requests */
-static const int version_requests[] = {
- X_DamageQueryVersion, /* before client sends QueryVersion */
- X_DamageAdd, /* Version 1 */
-};
-
-#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
-
-static int (*ProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
-/*************** Version 1 ******************/
- ProcDamageQueryVersion,
- ProcDamageCreate,
- ProcDamageDestroy,
- ProcDamageSubtract,
-/*************** Version 1.1 ****************/
- ProcDamageAdd,
-};
-
-
-static int
-ProcDamageDispatch (ClientPtr client)
-{
- REQUEST(xDamageReq);
- DamageClientPtr pDamageClient = GetDamageClient (client);
-
- if (pDamageClient->major_version >= NUM_VERSION_REQUESTS)
- return BadRequest;
- if (stuff->damageReqType > version_requests[pDamageClient->major_version])
- return BadRequest;
- return (*ProcDamageVector[stuff->damageReqType]) (client);
-}
-
-static int
-SProcDamageQueryVersion(ClientPtr client)
-{
- register int n;
- REQUEST(xDamageQueryVersionReq);
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
- swapl(&stuff->majorVersion, n);
- swapl(&stuff->minorVersion, n);
- return (*ProcDamageVector[stuff->damageReqType]) (client);
-}
-
-static int
-SProcDamageCreate (ClientPtr client)
-{
- register int n;
- REQUEST(xDamageCreateReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xDamageCreateReq);
- swapl (&stuff->damage, n);
- swapl (&stuff->drawable, n);
- return (*ProcDamageVector[stuff->damageReqType]) (client);
-}
-
-static int
-SProcDamageDestroy (ClientPtr client)
-{
- register int n;
- REQUEST(xDamageDestroyReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xDamageDestroyReq);
- swapl (&stuff->damage, n);
- return (*ProcDamageVector[stuff->damageReqType]) (client);
-}
-
-static int
-SProcDamageSubtract (ClientPtr client)
-{
- register int n;
- REQUEST(xDamageSubtractReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xDamageSubtractReq);
- swapl (&stuff->damage, n);
- swapl (&stuff->repair, n);
- swapl (&stuff->parts, n);
- return (*ProcDamageVector[stuff->damageReqType]) (client);
-}
-
-static int
-SProcDamageAdd (ClientPtr client)
-{
- register int n;
- REQUEST(xDamageAddReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xDamageSubtractReq);
- swapl (&stuff->drawable, n);
- swapl (&stuff->region, n);
- return (*ProcDamageVector[stuff->damageReqType]) (client);
-}
-
-static int (*SProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
-/*************** Version 1 ******************/
- SProcDamageQueryVersion,
- SProcDamageCreate,
- SProcDamageDestroy,
- SProcDamageSubtract,
-/*************** Version 1.1 ****************/
- SProcDamageAdd,
-};
-
-static int
-SProcDamageDispatch (ClientPtr client)
-{
- REQUEST(xDamageReq);
- if (stuff->damageReqType >= XDamageNumberRequests)
- return BadRequest;
- return (*SProcDamageVector[stuff->damageReqType]) (client);
-}
-
-static void
-DamageClientCallback (CallbackListPtr *list,
- pointer closure,
- pointer data)
-{
- NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
- ClientPtr pClient = clientinfo->client;
- DamageClientPtr pDamageClient = GetDamageClient (pClient);
-
- pDamageClient->critical = 0;
- pDamageClient->major_version = 0;
- pDamageClient->minor_version = 0;
-}
-
-/*ARGSUSED*/
-static void
-DamageResetProc (ExtensionEntry *extEntry)
-{
- DeleteCallback (&ClientStateCallback, DamageClientCallback, 0);
-}
-
-static int
-FreeDamageExt (pointer value, XID did)
-{
- DamageExtPtr pDamageExt = (DamageExtPtr) value;
-
- /*
- * Get rid of the resource table entry hanging from the window id
- */
- pDamageExt->id = 0;
- if (WindowDrawable(pDamageExt->pDrawable->type))
- FreeResourceByType (pDamageExt->pDrawable->id, DamageExtWinType, TRUE);
- if (pDamageExt->pDamage)
- {
- DamageUnregister (pDamageExt->pDrawable, pDamageExt->pDamage);
- DamageDestroy (pDamageExt->pDamage);
- }
- free(pDamageExt);
- return Success;
-}
-
-static int
-FreeDamageExtWin (pointer value, XID wid)
-{
- DamageExtPtr pDamageExt = (DamageExtPtr) value;
-
- if (pDamageExt->id)
- FreeResource (pDamageExt->id, RT_NONE);
- return Success;
-}
-
-static void
-SDamageNotifyEvent (xDamageNotifyEvent *from,
- xDamageNotifyEvent *to)
-{
- to->type = from->type;
- cpswaps (from->sequenceNumber, to->sequenceNumber);
- cpswapl (from->drawable, to->drawable);
- cpswapl (from->damage, to->damage);
- cpswaps (from->area.x, to->area.x);
- cpswaps (from->area.y, to->area.y);
- cpswaps (from->area.width, to->area.width);
- cpswaps (from->area.height, to->area.height);
- cpswaps (from->geometry.x, to->geometry.x);
- cpswaps (from->geometry.y, to->geometry.y);
- cpswaps (from->geometry.width, to->geometry.width);
- cpswaps (from->geometry.height, to->geometry.height);
-}
-
-void
-DamageExtensionInit(void)
-{
- ExtensionEntry *extEntry;
- int s;
-
- for (s = 0; s < screenInfo.numScreens; s++)
- DamageSetup (screenInfo.screens[s]);
-
- DamageExtType = CreateNewResourceType (FreeDamageExt, "DamageExt");
- if (!DamageExtType)
- return;
-
- DamageExtWinType = CreateNewResourceType (FreeDamageExtWin, "DamageExtWin");
- if (!DamageExtWinType)
- return;
-
- if (!dixRegisterPrivateKey(&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (DamageClientRec)))
- return;
-
- if (!AddCallback (&ClientStateCallback, DamageClientCallback, 0))
- return;
-
- if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
- XDamageNumberErrors,
- ProcDamageDispatch, SProcDamageDispatch,
- DamageResetProc, StandardMinorOpcode)) != 0)
- {
- DamageReqCode = (unsigned char)extEntry->base;
- DamageEventBase = extEntry->eventBase;
- EventSwapVector[DamageEventBase + XDamageNotify] =
- (EventSwapPtr) SDamageNotifyEvent;
- SetResourceTypeErrorValue(DamageExtType, extEntry->errorBase + BadDamage);
- }
-}
+/* + * Copyright © 2002 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 "damageextint.h" +#include "protocol-versions.h" + +static unsigned char DamageReqCode; +static int DamageEventBase; +static RESTYPE DamageExtType; +static RESTYPE DamageExtWinType; + +static DevPrivateKeyRec DamageClientPrivateKeyRec; +#define DamageClientPrivateKey (&DamageClientPrivateKeyRec) + +static void +DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes) +{ + ClientPtr pClient = pDamageExt->pClient; + DamageClientPtr pDamageClient = GetDamageClient (pClient); + DrawablePtr pDrawable = pDamageExt->pDrawable; + xDamageNotifyEvent ev; + int i; + + UpdateCurrentTimeIf (); + ev.type = DamageEventBase + XDamageNotify; + ev.level = pDamageExt->level; + ev.drawable = pDamageExt->drawable; + ev.damage = pDamageExt->id; + ev.timestamp = currentTime.milliseconds; + ev.geometry.x = pDrawable->x; + ev.geometry.y = pDrawable->y; + ev.geometry.width = pDrawable->width; + ev.geometry.height = pDrawable->height; + if (pBoxes) + { + for (i = 0; i < nBoxes; i++) + { + ev.level = pDamageExt->level; + if (i < nBoxes - 1) + ev.level |= DamageNotifyMore; + ev.area.x = pBoxes[i].x1; + ev.area.y = pBoxes[i].y1; + ev.area.width = pBoxes[i].x2 - pBoxes[i].x1; + ev.area.height = pBoxes[i].y2 - pBoxes[i].y1; + WriteEventsToClient (pClient, 1, (xEvent *) &ev); + } + } + else + { + ev.area.x = 0; + ev.area.y = 0; + ev.area.width = pDrawable->width; + ev.area.height = pDrawable->height; + WriteEventsToClient (pClient, 1, (xEvent *) &ev); + } + /* Composite extension marks clients with manual Subwindows as critical */ + if (pDamageClient->critical > 0) + { + SetCriticalOutputPending (); + pClient->smart_priority = SMART_MAX_PRIORITY; + } +} + +static void +DamageExtReport (DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + DamageExtPtr pDamageExt = closure; + + switch (pDamageExt->level) { + case DamageReportRawRegion: + case DamageReportDeltaRegion: + DamageExtNotify (pDamageExt, RegionRects(pRegion), RegionNumRects(pRegion)); + break; + case DamageReportBoundingBox: + DamageExtNotify (pDamageExt, RegionExtents(pRegion), 1); + break; + case DamageReportNonEmpty: + DamageExtNotify (pDamageExt, NullBox, 0); + break; + case DamageReportNone: + break; + } +} + +static void +DamageExtDestroy (DamagePtr pDamage, void *closure) +{ + DamageExtPtr pDamageExt = closure; + + pDamageExt->pDamage = 0; + if (pDamageExt->id) + FreeResource (pDamageExt->id, RT_NONE); +} + +void +DamageExtSetCritical (ClientPtr pClient, Bool critical) +{ + DamageClientPtr pDamageClient = GetDamageClient (pClient); + + if (pDamageClient) + pDamageClient->critical += critical ? 1 : -1; +} + +static int +ProcDamageQueryVersion(ClientPtr client) +{ + DamageClientPtr pDamageClient = GetDamageClient (client); + xDamageQueryVersionReply rep; + register int n; + REQUEST(xDamageQueryVersionReq); + + REQUEST_SIZE_MATCH(xDamageQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + if (stuff->majorVersion < SERVER_DAMAGE_MAJOR_VERSION) { + rep.majorVersion = stuff->majorVersion; + rep.minorVersion = stuff->minorVersion; + } else { + rep.majorVersion = SERVER_DAMAGE_MAJOR_VERSION; + if (stuff->majorVersion == SERVER_DAMAGE_MAJOR_VERSION && + stuff->minorVersion < SERVER_DAMAGE_MINOR_VERSION) + rep.minorVersion = stuff->minorVersion; + else + rep.minorVersion = SERVER_DAMAGE_MINOR_VERSION; + } + pDamageClient->major_version = rep.majorVersion; + pDamageClient->minor_version = rep.minorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.majorVersion, n); + swapl(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xDamageQueryVersionReply), (char *)&rep); + return Success; +} + +static int +ProcDamageCreate (ClientPtr client) +{ + DrawablePtr pDrawable; + DamageExtPtr pDamageExt; + DamageReportLevel level; + RegionPtr pRegion; + int rc; + + REQUEST(xDamageCreateReq); + + REQUEST_SIZE_MATCH(xDamageCreateReq); + LEGAL_NEW_RESOURCE(stuff->damage, client); + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixGetAttrAccess|DixReadAccess); + if (rc != Success) + return rc; + + switch (stuff->level) { + case XDamageReportRawRectangles: + level = DamageReportRawRegion; + break; + case XDamageReportDeltaRectangles: + level = DamageReportDeltaRegion; + break; + case XDamageReportBoundingBox: + level = DamageReportBoundingBox; + break; + case XDamageReportNonEmpty: + level = DamageReportNonEmpty; + break; + default: + client->errorValue = stuff->level; + return BadValue; + } + + pDamageExt = malloc(sizeof (DamageExtRec)); + if (!pDamageExt) + return BadAlloc; + pDamageExt->id = stuff->damage; + pDamageExt->drawable = stuff->drawable; + pDamageExt->pDrawable = pDrawable; + pDamageExt->level = level; + pDamageExt->pClient = client; + pDamageExt->pDamage = DamageCreate (DamageExtReport, + DamageExtDestroy, + level, + FALSE, + pDrawable->pScreen, + pDamageExt); + if (!pDamageExt->pDamage) + { + free(pDamageExt); + return BadAlloc; + } + if (!AddResource (stuff->damage, DamageExtType, (pointer) pDamageExt)) + return BadAlloc; + + DamageSetReportAfterOp (pDamageExt->pDamage, TRUE); + DamageRegister (pDamageExt->pDrawable, pDamageExt->pDamage); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + pRegion = &((WindowPtr) pDrawable)->borderClip; + DamageReportDamage(pDamageExt->pDamage, pRegion); + } + + return Success; +} + +static int +ProcDamageDestroy (ClientPtr client) +{ + REQUEST(xDamageDestroyReq); + DamageExtPtr pDamageExt; + + REQUEST_SIZE_MATCH(xDamageDestroyReq); + VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess); + FreeResource (stuff->damage, RT_NONE); + return Success; +} + +static int +ProcDamageSubtract (ClientPtr client) +{ + REQUEST(xDamageSubtractReq); + DamageExtPtr pDamageExt; + RegionPtr pRepair; + RegionPtr pParts; + + REQUEST_SIZE_MATCH(xDamageSubtractReq); + VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess); + VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess); + VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess); + + if (pDamageExt->level != DamageReportRawRegion) + { + DamagePtr pDamage = pDamageExt->pDamage; + if (pRepair) + { + if (pParts) + RegionIntersect(pParts, DamageRegion (pDamage), pRepair); + if (DamageSubtract (pDamage, pRepair)) + DamageExtReport (pDamage, DamageRegion (pDamage), (void *) pDamageExt); + } + else + { + if (pParts) + RegionCopy(pParts, DamageRegion (pDamage)); + DamageEmpty (pDamage); + } + } + return Success; +} + +static int +ProcDamageAdd (ClientPtr client) +{ + REQUEST(xDamageAddReq); + DrawablePtr pDrawable; + RegionPtr pRegion; + int rc; + + REQUEST_SIZE_MATCH(xDamageAddReq); + VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess); + rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, + DixWriteAccess); + if (rc != Success) + return rc; + + /* The region is relative to the drawable origin, so translate it out to + * screen coordinates like damage expects. + */ + RegionTranslate(pRegion, pDrawable->x, pDrawable->y); + DamageDamageRegion(pDrawable, pRegion); + RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y); + + return Success; +} + +/* Major version controls available requests */ +static const int version_requests[] = { + X_DamageQueryVersion, /* before client sends QueryVersion */ + X_DamageAdd, /* Version 1 */ +}; + +#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) + +static int (*ProcDamageVector[XDamageNumberRequests])(ClientPtr) = { +/*************** Version 1 ******************/ + ProcDamageQueryVersion, + ProcDamageCreate, + ProcDamageDestroy, + ProcDamageSubtract, +/*************** Version 1.1 ****************/ + ProcDamageAdd, +}; + + +static int +ProcDamageDispatch (ClientPtr client) +{ + REQUEST(xDamageReq); + DamageClientPtr pDamageClient = GetDamageClient (client); + + if (pDamageClient->major_version >= NUM_VERSION_REQUESTS) + return BadRequest; + if (stuff->damageReqType > version_requests[pDamageClient->major_version]) + return BadRequest; + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageQueryVersion(ClientPtr client) +{ + register int n; + REQUEST(xDamageQueryVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDamageQueryVersionReq); + swapl(&stuff->majorVersion, n); + swapl(&stuff->minorVersion, n); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageCreate (ClientPtr client) +{ + register int n; + REQUEST(xDamageCreateReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xDamageCreateReq); + swapl (&stuff->damage, n); + swapl (&stuff->drawable, n); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageDestroy (ClientPtr client) +{ + register int n; + REQUEST(xDamageDestroyReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xDamageDestroyReq); + swapl (&stuff->damage, n); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageSubtract (ClientPtr client) +{ + register int n; + REQUEST(xDamageSubtractReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xDamageSubtractReq); + swapl (&stuff->damage, n); + swapl (&stuff->repair, n); + swapl (&stuff->parts, n); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int +SProcDamageAdd (ClientPtr client) +{ + register int n; + REQUEST(xDamageAddReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xDamageSubtractReq); + swapl (&stuff->drawable, n); + swapl (&stuff->region, n); + return (*ProcDamageVector[stuff->damageReqType]) (client); +} + +static int (*SProcDamageVector[XDamageNumberRequests])(ClientPtr) = { +/*************** Version 1 ******************/ + SProcDamageQueryVersion, + SProcDamageCreate, + SProcDamageDestroy, + SProcDamageSubtract, +/*************** Version 1.1 ****************/ + SProcDamageAdd, +}; + +static int +SProcDamageDispatch (ClientPtr client) +{ + REQUEST(xDamageReq); + if (stuff->damageReqType >= XDamageNumberRequests) + return BadRequest; + return (*SProcDamageVector[stuff->damageReqType]) (client); +} + +static void +DamageClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + DamageClientPtr pDamageClient = GetDamageClient (pClient); + + pDamageClient->critical = 0; + pDamageClient->major_version = 0; + pDamageClient->minor_version = 0; +} + +/*ARGSUSED*/ +static void +DamageResetProc (ExtensionEntry *extEntry) +{ + DeleteCallback (&ClientStateCallback, DamageClientCallback, 0); +} + +static int +FreeDamageExt (pointer value, XID did) +{ + DamageExtPtr pDamageExt = (DamageExtPtr) value; + + /* + * Get rid of the resource table entry hanging from the window id + */ + pDamageExt->id = 0; + if (WindowDrawable(pDamageExt->pDrawable->type)) + FreeResourceByType (pDamageExt->pDrawable->id, DamageExtWinType, TRUE); + if (pDamageExt->pDamage) + { + DamageUnregister (pDamageExt->pDrawable, pDamageExt->pDamage); + DamageDestroy (pDamageExt->pDamage); + } + free(pDamageExt); + return Success; +} + +static int +FreeDamageExtWin (pointer value, XID wid) +{ + DamageExtPtr pDamageExt = (DamageExtPtr) value; + + if (pDamageExt->id) + FreeResource (pDamageExt->id, RT_NONE); + return Success; +} + +static void +SDamageNotifyEvent (xDamageNotifyEvent *from, + xDamageNotifyEvent *to) +{ + to->type = from->type; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->drawable, to->drawable); + cpswapl (from->damage, to->damage); + cpswaps (from->area.x, to->area.x); + cpswaps (from->area.y, to->area.y); + cpswaps (from->area.width, to->area.width); + cpswaps (from->area.height, to->area.height); + cpswaps (from->geometry.x, to->geometry.x); + cpswaps (from->geometry.y, to->geometry.y); + cpswaps (from->geometry.width, to->geometry.width); + cpswaps (from->geometry.height, to->geometry.height); +} + +void +DamageExtensionInit(void) +{ + ExtensionEntry *extEntry; + int s; + + for (s = 0; s < screenInfo.numScreens; s++) + DamageSetup (screenInfo.screens[s]); + + DamageExtType = CreateNewResourceType (FreeDamageExt, "DamageExt"); + if (!DamageExtType) + return; + + DamageExtWinType = CreateNewResourceType (FreeDamageExtWin, "DamageExtWin"); + if (!DamageExtWinType) + return; + + if (!dixRegisterPrivateKey(&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (DamageClientRec))) + return; + + if (!AddCallback (&ClientStateCallback, DamageClientCallback, 0)) + return; + + if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents, + XDamageNumberErrors, + ProcDamageDispatch, SProcDamageDispatch, + DamageResetProc, StandardMinorOpcode)) != 0) + { + DamageReqCode = (unsigned char)extEntry->base; + DamageEventBase = extEntry->eventBase; + EventSwapVector[DamageEventBase + XDamageNotify] = + (EventSwapPtr) SDamageNotifyEvent; + SetResourceTypeErrorValue(DamageExtType, extEntry->errorBase + BadDamage); + } +} diff --git a/xorg-server/dix/cursor.c b/xorg-server/dix/cursor.c index acd118a1c..c191c1e88 100644 --- a/xorg-server/dix/cursor.c +++ b/xorg-server/dix/cursor.c @@ -1,515 +1,512 @@ -/***********************************************************
-
-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 <X11/Xmd.h>
-#include "servermd.h"
-#include "scrnintstr.h"
-#include "dixstruct.h"
-#include "cursorstr.h"
-#include "dixfontstr.h"
-#include "opaque.h"
-#include "inputstr.h"
-#include "xace.h"
-
-typedef struct _GlyphShare {
- FontPtr font;
- unsigned short sourceChar;
- unsigned short maskChar;
- CursorBitsPtr bits;
- struct _GlyphShare *next;
-} GlyphShare, *GlyphSharePtr;
-
-static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL;
-
-DevPrivateKeyRec cursorScreenDevPriv[MAXSCREENS];
-
-#ifdef XFIXES
-static CARD32 cursorSerial;
-#endif
-
-static void
-FreeCursorBits(CursorBitsPtr bits)
-{
- if (--bits->refcnt > 0)
- return;
- free(bits->source);
- free(bits->mask);
-#ifdef ARGB_CURSOR
- free(bits->argb);
-#endif
- dixFiniPrivates(bits, PRIVATE_CURSOR_BITS);
- if (bits->refcnt == 0)
- {
- GlyphSharePtr *prev, this;
-
- for (prev = &sharedGlyphs;
- (this = *prev) && (this->bits != bits);
- prev = &this->next)
- ;
- if (this)
- {
- *prev = this->next;
- CloseFont(this->font, (Font)0);
- free(this);
- }
- free(bits);
- }
-}
-
-/**
- * To be called indirectly by DeleteResource; must use exactly two args.
- *
- * \param value must conform to DeleteType
- */
-int
-FreeCursor(pointer value, XID cid)
-{
- int nscr;
- CursorPtr pCurs = (CursorPtr)value;
-
- ScreenPtr pscr;
- DeviceIntPtr pDev = NULL; /* unused anyway */
-
- if ( --pCurs->refcnt != 0)
- return Success;
-
- for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
- {
- pscr = screenInfo.screens[nscr];
- (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
- }
- FreeCursorBits(pCurs->bits);
- dixFiniPrivates(pCurs, PRIVATE_CURSOR);
- free( pCurs);
- return Success;
-}
-
-
-/*
- * We check for empty cursors so that we won't have to display them
- */
-static void
-CheckForEmptyMask(CursorBitsPtr bits)
-{
- unsigned char *msk = bits->mask;
- int n = BitmapBytePad(bits->width) * bits->height;
-
- bits->emptyMask = FALSE;
- while(n--)
- if(*(msk++) != 0) return;
-#ifdef ARGB_CURSOR
- if (bits->argb)
- {
- CARD32 *argb = bits->argb;
- int n = bits->width * bits->height;
- while (n--)
- if (*argb++ & 0xff000000) return;
- }
-#endif
- bits->emptyMask = TRUE;
-}
-
-/**
- * realize the cursor for every screen. Do not change the refcnt, this will be
- * changed when ChangeToCursor actually changes the sprite.
- *
- * @return Success if all cursors realize on all screens, BadAlloc if realize
- * failed for a device on a given screen.
- */
-static int
-RealizeCursorAllScreens(CursorPtr pCurs)
-{
- DeviceIntPtr pDev;
- ScreenPtr pscr;
- int nscr;
-
- for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
- {
- pscr = screenInfo.screens[nscr];
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
- {
- /* Realize failed for device pDev on screen pscr.
- * We have to assume that for all devices before, realize
- * worked. We need to rollback all devices so far on the
- * current screen and then all devices on previous
- * screens.
- */
- DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
- while(pDevIt && pDevIt != pDev)
- {
- if (DevHasCursor(pDevIt))
- ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
- pDevIt = pDevIt->next;
- }
- while (--nscr >= 0)
- {
- pscr = screenInfo.screens[nscr];
- /* now unrealize all devices on previous screens */
- pDevIt = inputInfo.devices;
- while (pDevIt)
- {
- if (DevHasCursor(pDevIt))
- ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
- pDevIt = pDevIt->next;
- }
- ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
- }
- return BadAlloc;
- }
- }
- }
- }
-
- return Success;
-}
-
-
-/**
- * does nothing about the resource table, just creates the data structure.
- * does not copy the src and mask bits
- *
- * \param psrcbits server-defined padding
- * \param pmaskbits server-defined padding
- * \param argb no padding
- */
-int
-AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
- CARD32 *argb, CursorMetricPtr cm,
- unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
- unsigned backRed, unsigned backGreen, unsigned backBlue,
- CursorPtr *ppCurs, ClientPtr client, XID cid)
-{
- CursorBitsPtr bits;
- CursorPtr pCurs;
- int rc;
-
- *ppCurs = NULL;
- pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1);
- if (!pCurs)
- {
- free(psrcbits);
- free(pmaskbits);
- return BadAlloc;
- }
- bits = (CursorBitsPtr)((char *)pCurs + CURSOR_REC_SIZE);
- dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
- dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS)
- bits->source = psrcbits;
- bits->mask = pmaskbits;
-#ifdef ARGB_CURSOR
- bits->argb = argb;
-#endif
- bits->width = cm->width;
- bits->height = cm->height;
- bits->xhot = cm->xhot;
- bits->yhot = cm->yhot;
- pCurs->refcnt = 1;
- bits->refcnt = -1;
- CheckForEmptyMask(bits);
- pCurs->bits = bits;
-#ifdef XFIXES
- pCurs->serialNumber = ++cursorSerial;
- pCurs->name = None;
-#endif
-
- pCurs->foreRed = foreRed;
- pCurs->foreGreen = foreGreen;
- pCurs->foreBlue = foreBlue;
-
- pCurs->backRed = backRed;
- pCurs->backGreen = backGreen;
- pCurs->backBlue = backBlue;
-
- pCurs->id = cid;
-
- /* security creation/labeling check */
- rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
- pCurs, RT_NONE, NULL, DixCreateAccess);
- if (rc != Success)
- goto error;
-
- rc = RealizeCursorAllScreens(pCurs);
- if (rc != Success)
- goto error;
-
- *ppCurs = pCurs;
- return Success;
-
-error:
- FreeCursorBits(bits);
- dixFiniPrivates(pCurs, PRIVATE_CURSOR);
- free(pCurs);
-
- return rc;
-}
-
-int
-AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
- unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
- unsigned backRed, unsigned backGreen, unsigned backBlue,
- CursorPtr *ppCurs, ClientPtr client, XID cid)
-{
- FontPtr sourcefont, maskfont;
- unsigned char *srcbits;
- unsigned char *mskbits;
- CursorMetricRec cm;
- int rc;
- CursorBitsPtr bits;
- CursorPtr pCurs;
- GlyphSharePtr pShare;
-
- rc = dixLookupResourceByType((pointer *)&sourcefont, source, RT_FONT, client,
- DixUseAccess);
- if (rc != Success)
- {
- client->errorValue = source;
- return rc;
- }
- rc = dixLookupResourceByType((pointer *)&maskfont, mask, RT_FONT, client,
- DixUseAccess);
- if (rc != Success && mask != None)
- {
- client->errorValue = mask;
- return rc;
- }
- if (sourcefont != maskfont)
- pShare = (GlyphSharePtr)NULL;
- else
- {
- for (pShare = sharedGlyphs;
- pShare &&
- ((pShare->font != sourcefont) ||
- (pShare->sourceChar != sourceChar) ||
- (pShare->maskChar != maskChar));
- pShare = pShare->next)
- ;
- }
- if (pShare)
- {
- pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE, 1);
- if (!pCurs)
- return BadAlloc;
- dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
- bits = pShare->bits;
- bits->refcnt++;
- }
- else
- {
- if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm))
- {
- client->errorValue = sourceChar;
- return BadValue;
- }
- if (!maskfont)
- {
- long n;
- unsigned char *mskptr;
-
- n = BitmapBytePad(cm.width)*(long)cm.height;
- mskptr = mskbits = malloc(n);
- if (!mskptr)
- return BadAlloc;
- while (--n >= 0)
- *mskptr++ = ~0;
- }
- else
- {
- if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm))
- {
- client->errorValue = maskChar;
- return BadValue;
- }
- if ((rc = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)))
- return rc;
- }
- if ((rc = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits)))
- {
- free(mskbits);
- return rc;
- }
- if (sourcefont != maskfont)
- {
- pCurs =
- (CursorPtr)calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1);
- if (pCurs)
- bits = (CursorBitsPtr)((char *)pCurs + CURSOR_REC_SIZE);
- else
- bits = (CursorBitsPtr)NULL;
- }
- else
- {
- pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE, 1);
- if (pCurs)
- bits = (CursorBitsPtr)calloc(CURSOR_BITS_SIZE, 1);
- else
- bits = (CursorBitsPtr)NULL;
- }
- if (!bits)
- {
- free(pCurs);
- free(mskbits);
- free(srcbits);
- return BadAlloc;
- }
- dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR);
- dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS);
- bits->source = srcbits;
- bits->mask = mskbits;
-#ifdef ARGB_CURSOR
- bits->argb = 0;
-#endif
- bits->width = cm.width;
- bits->height = cm.height;
- bits->xhot = cm.xhot;
- bits->yhot = cm.yhot;
- if (sourcefont != maskfont)
- bits->refcnt = -1;
- else
- {
- bits->refcnt = 1;
- pShare = malloc(sizeof(GlyphShare));
- if (!pShare)
- {
- FreeCursorBits(bits);
- return BadAlloc;
- }
- pShare->font = sourcefont;
- sourcefont->refcnt++;
- pShare->sourceChar = sourceChar;
- pShare->maskChar = maskChar;
- pShare->bits = bits;
- pShare->next = sharedGlyphs;
- sharedGlyphs = pShare;
- }
- }
-
- CheckForEmptyMask(bits);
- pCurs->bits = bits;
- pCurs->refcnt = 1;
-#ifdef XFIXES
- pCurs->serialNumber = ++cursorSerial;
- pCurs->name = None;
-#endif
-
- pCurs->foreRed = foreRed;
- pCurs->foreGreen = foreGreen;
- pCurs->foreBlue = foreBlue;
-
- pCurs->backRed = backRed;
- pCurs->backGreen = backGreen;
- pCurs->backBlue = backBlue;
-
- pCurs->id = cid;
-
- /* security creation/labeling check */
- rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
- pCurs, RT_NONE, NULL, DixCreateAccess);
- if (rc != Success)
- goto error;
-
- rc = RealizeCursorAllScreens(pCurs);
- if (rc != Success)
- goto error;
-
- *ppCurs = pCurs;
- return Success;
-
-error:
- FreeCursorBits(bits);
- dixFiniPrivates(pCurs, PRIVATE_CURSOR);
- free(pCurs);
-
- return rc;
-}
-
-/** CreateRootCursor
- *
- * look up the name of a font
- * open the font
- * add the font to the resource table
- * make a cursor from the glyphs
- * add the cursor to the resource table
- *************************************************************/
-
-CursorPtr
-CreateRootCursor(char *unused1, unsigned int unused2)
-{
- CursorPtr curs;
- FontPtr cursorfont;
- int err;
- XID fontID;
-
- fontID = FakeClientID(0);
- err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync,
- (unsigned)strlen(defaultCursorFont), defaultCursorFont);
- if (err != Success)
- return NullCursor;
-
- err = dixLookupResourceByType((pointer *)&cursorfont, fontID, RT_FONT,
- serverClient, DixReadAccess);
- if (err != Success)
- return NullCursor;
- if (AllocGlyphCursor(fontID, 0, fontID, 1, 0, 0, 0, ~0, ~0, ~0,
- &curs, serverClient, (XID)0) != Success)
- return NullCursor;
-
- if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs))
- return NullCursor;
-
- return curs;
-}
+/*********************************************************** + +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 <X11/Xmd.h> +#include "servermd.h" +#include "scrnintstr.h" +#include "dixstruct.h" +#include "cursorstr.h" +#include "dixfontstr.h" +#include "opaque.h" +#include "inputstr.h" +#include "xace.h" + +typedef struct _GlyphShare { + FontPtr font; + unsigned short sourceChar; + unsigned short maskChar; + CursorBitsPtr bits; + struct _GlyphShare *next; +} GlyphShare, *GlyphSharePtr; + +static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL; + +DevPrivateKeyRec cursorScreenDevPriv[MAXSCREENS]; + +#ifdef XFIXES +static CARD32 cursorSerial; +#endif + +static void +FreeCursorBits(CursorBitsPtr bits) +{ + if (--bits->refcnt > 0) + return; + free(bits->source); + free(bits->mask); +#ifdef ARGB_CURSOR + free(bits->argb); +#endif + dixFiniPrivates(bits, PRIVATE_CURSOR_BITS); + if (bits->refcnt == 0) + { + GlyphSharePtr *prev, this; + + for (prev = &sharedGlyphs; + (this = *prev) && (this->bits != bits); + prev = &this->next) + ; + if (this) + { + *prev = this->next; + CloseFont(this->font, (Font)0); + free(this); + } + free(bits); + } +} + +/** + * To be called indirectly by DeleteResource; must use exactly two args. + * + * \param value must conform to DeleteType + */ +int +FreeCursor(pointer value, XID cid) +{ + int nscr; + CursorPtr pCurs = (CursorPtr)value; + + ScreenPtr pscr; + DeviceIntPtr pDev = NULL; /* unused anyway */ + + if ( --pCurs->refcnt != 0) + return Success; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs); + } + FreeCursorBits(pCurs->bits); + dixFiniPrivates(pCurs, PRIVATE_CURSOR); + free( pCurs); + return Success; +} + + +/* + * We check for empty cursors so that we won't have to display them + */ +static void +CheckForEmptyMask(CursorBitsPtr bits) +{ + unsigned char *msk = bits->mask; + int n = BitmapBytePad(bits->width) * bits->height; + + bits->emptyMask = FALSE; + while(n--) + if(*(msk++) != 0) return; +#ifdef ARGB_CURSOR + if (bits->argb) + { + CARD32 *argb = bits->argb; + int n = bits->width * bits->height; + while (n--) + if (*argb++ & 0xff000000) return; + } +#endif + bits->emptyMask = TRUE; +} + +/** + * realize the cursor for every screen. Do not change the refcnt, this will be + * changed when ChangeToCursor actually changes the sprite. + * + * @return Success if all cursors realize on all screens, BadAlloc if realize + * failed for a device on a given screen. + */ +static int +RealizeCursorAllScreens(CursorPtr pCurs) +{ + DeviceIntPtr pDev; + ScreenPtr pscr; + int nscr; + + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) + { + pscr = screenInfo.screens[nscr]; + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs)) + { + /* Realize failed for device pDev on screen pscr. + * We have to assume that for all devices before, realize + * worked. We need to rollback all devices so far on the + * current screen and then all devices on previous + * screens. + */ + DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/ + while(pDevIt && pDevIt != pDev) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + /* now unrealize all devices on previous screens */ + pDevIt = inputInfo.devices; + while (pDevIt) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs); + } + return BadAlloc; + } + } + } + } + + return Success; +} + + +/** + * does nothing about the resource table, just creates the data structure. + * does not copy the src and mask bits + * + * \param psrcbits server-defined padding + * \param pmaskbits server-defined padding + * \param argb no padding + */ +int +AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits, + CARD32 *argb, CursorMetricPtr cm, + unsigned foreRed, unsigned foreGreen, unsigned foreBlue, + unsigned backRed, unsigned backGreen, unsigned backBlue, + CursorPtr *ppCurs, ClientPtr client, XID cid) +{ + CursorBitsPtr bits; + CursorPtr pCurs; + int rc; + + *ppCurs = NULL; + pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1); + if (!pCurs) + return BadAlloc; + + bits = (CursorBitsPtr)((char *)pCurs + CURSOR_REC_SIZE); + dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR); + dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS) + bits->source = psrcbits; + bits->mask = pmaskbits; +#ifdef ARGB_CURSOR + bits->argb = argb; +#endif + bits->width = cm->width; + bits->height = cm->height; + bits->xhot = cm->xhot; + bits->yhot = cm->yhot; + pCurs->refcnt = 1; + bits->refcnt = -1; + CheckForEmptyMask(bits); + pCurs->bits = bits; +#ifdef XFIXES + pCurs->serialNumber = ++cursorSerial; + pCurs->name = None; +#endif + + pCurs->foreRed = foreRed; + pCurs->foreGreen = foreGreen; + pCurs->foreBlue = foreBlue; + + pCurs->backRed = backRed; + pCurs->backGreen = backGreen; + pCurs->backBlue = backBlue; + + pCurs->id = cid; + + /* security creation/labeling check */ + rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR, + pCurs, RT_NONE, NULL, DixCreateAccess); + if (rc != Success) + goto error; + + rc = RealizeCursorAllScreens(pCurs); + if (rc != Success) + goto error; + + *ppCurs = pCurs; + return Success; + +error: + FreeCursorBits(bits); + dixFiniPrivates(pCurs, PRIVATE_CURSOR); + free(pCurs); + + return rc; +} + +int +AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, + unsigned foreRed, unsigned foreGreen, unsigned foreBlue, + unsigned backRed, unsigned backGreen, unsigned backBlue, + CursorPtr *ppCurs, ClientPtr client, XID cid) +{ + FontPtr sourcefont, maskfont; + unsigned char *srcbits; + unsigned char *mskbits; + CursorMetricRec cm; + int rc; + CursorBitsPtr bits; + CursorPtr pCurs; + GlyphSharePtr pShare; + + rc = dixLookupResourceByType((pointer *)&sourcefont, source, RT_FONT, client, + DixUseAccess); + if (rc != Success) + { + client->errorValue = source; + return rc; + } + rc = dixLookupResourceByType((pointer *)&maskfont, mask, RT_FONT, client, + DixUseAccess); + if (rc != Success && mask != None) + { + client->errorValue = mask; + return rc; + } + if (sourcefont != maskfont) + pShare = (GlyphSharePtr)NULL; + else + { + for (pShare = sharedGlyphs; + pShare && + ((pShare->font != sourcefont) || + (pShare->sourceChar != sourceChar) || + (pShare->maskChar != maskChar)); + pShare = pShare->next) + ; + } + if (pShare) + { + pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE, 1); + if (!pCurs) + return BadAlloc; + dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR); + bits = pShare->bits; + bits->refcnt++; + } + else + { + if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm)) + { + client->errorValue = sourceChar; + return BadValue; + } + if (!maskfont) + { + long n; + unsigned char *mskptr; + + n = BitmapBytePad(cm.width)*(long)cm.height; + mskptr = mskbits = malloc(n); + if (!mskptr) + return BadAlloc; + while (--n >= 0) + *mskptr++ = ~0; + } + else + { + if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm)) + { + client->errorValue = maskChar; + return BadValue; + } + if ((rc = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits))) + return rc; + } + if ((rc = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits))) + { + free(mskbits); + return rc; + } + if (sourcefont != maskfont) + { + pCurs = + (CursorPtr)calloc(CURSOR_REC_SIZE + CURSOR_BITS_SIZE, 1); + if (pCurs) + bits = (CursorBitsPtr)((char *)pCurs + CURSOR_REC_SIZE); + else + bits = (CursorBitsPtr)NULL; + } + else + { + pCurs = (CursorPtr)calloc(CURSOR_REC_SIZE, 1); + if (pCurs) + bits = (CursorBitsPtr)calloc(CURSOR_BITS_SIZE, 1); + else + bits = (CursorBitsPtr)NULL; + } + if (!bits) + { + free(pCurs); + free(mskbits); + free(srcbits); + return BadAlloc; + } + dixInitPrivates(pCurs, pCurs + 1, PRIVATE_CURSOR); + dixInitPrivates(bits, bits + 1, PRIVATE_CURSOR_BITS); + bits->source = srcbits; + bits->mask = mskbits; +#ifdef ARGB_CURSOR + bits->argb = 0; +#endif + bits->width = cm.width; + bits->height = cm.height; + bits->xhot = cm.xhot; + bits->yhot = cm.yhot; + if (sourcefont != maskfont) + bits->refcnt = -1; + else + { + bits->refcnt = 1; + pShare = malloc(sizeof(GlyphShare)); + if (!pShare) + { + FreeCursorBits(bits); + return BadAlloc; + } + pShare->font = sourcefont; + sourcefont->refcnt++; + pShare->sourceChar = sourceChar; + pShare->maskChar = maskChar; + pShare->bits = bits; + pShare->next = sharedGlyphs; + sharedGlyphs = pShare; + } + } + + CheckForEmptyMask(bits); + pCurs->bits = bits; + pCurs->refcnt = 1; +#ifdef XFIXES + pCurs->serialNumber = ++cursorSerial; + pCurs->name = None; +#endif + + pCurs->foreRed = foreRed; + pCurs->foreGreen = foreGreen; + pCurs->foreBlue = foreBlue; + + pCurs->backRed = backRed; + pCurs->backGreen = backGreen; + pCurs->backBlue = backBlue; + + pCurs->id = cid; + + /* security creation/labeling check */ + rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR, + pCurs, RT_NONE, NULL, DixCreateAccess); + if (rc != Success) + goto error; + + rc = RealizeCursorAllScreens(pCurs); + if (rc != Success) + goto error; + + *ppCurs = pCurs; + return Success; + +error: + FreeCursorBits(bits); + dixFiniPrivates(pCurs, PRIVATE_CURSOR); + free(pCurs); + + return rc; +} + +/** CreateRootCursor + * + * look up the name of a font + * open the font + * add the font to the resource table + * make a cursor from the glyphs + * add the cursor to the resource table + *************************************************************/ + +CursorPtr +CreateRootCursor(char *unused1, unsigned int unused2) +{ + CursorPtr curs; + FontPtr cursorfont; + int err; + XID fontID; + + fontID = FakeClientID(0); + err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync, + (unsigned)strlen(defaultCursorFont), defaultCursorFont); + if (err != Success) + return NullCursor; + + err = dixLookupResourceByType((pointer *)&cursorfont, fontID, RT_FONT, + serverClient, DixReadAccess); + if (err != Success) + return NullCursor; + if (AllocGlyphCursor(fontID, 0, fontID, 1, 0, 0, 0, ~0, ~0, ~0, + &curs, serverClient, (XID)0) != Success) + return NullCursor; + + if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs)) + return NullCursor; + + return curs; +} diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index 601b14a71..192c8c34e 100644 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -2976,11 +2976,17 @@ ProcCreateCursor (ClientPtr client) &pCursor, client, stuff->cid); if (rc != Success) - return rc; - if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) - return BadAlloc; + goto bail; + if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) { + rc = BadAlloc; + goto bail; + } return Success; +bail: + free(srcbits); + free(mskbits); + return rc; } int diff --git a/xorg-server/hw/xfree86/common/xf86xv.c b/xorg-server/hw/xfree86/common/xf86xv.c index 8115075b3..b46dfefed 100644 --- a/xorg-server/hw/xfree86/common/xf86xv.c +++ b/xorg-server/hw/xfree86/common/xf86xv.c @@ -1,2183 +1,2190 @@ -/*
- * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
- */
-/*
- * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of the copyright holder(s)
- * and author(s) shall not be used in advertising or otherwise to promote
- * the sale, use or other dealings in this Software without prior written
- * authorization from the copyright holder(s) and author(s).
- */
-
-
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#endif
-
-#include "misc.h"
-#include "xf86.h"
-#include "xf86_OSproc.h"
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "scrnintstr.h"
-#include "regionstr.h"
-#include "windowstr.h"
-#include "pixmapstr.h"
-#include "mivalidate.h"
-#include "validate.h"
-#include "resource.h"
-#include "gcstruct.h"
-#include "dixstruct.h"
-
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/Xvproto.h>
-#include "xvdix.h"
-#include "xvmodproc.h"
-
-#include "xf86xvpriv.h"
-
-
-/* XvScreenRec fields */
-
-static Bool xf86XVCloseScreen(int, ScreenPtr);
-static int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *);
-
-/* XvAdaptorRec fields */
-
-static int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*);
-static int xf86XVFreePort(XvPortPtr);
-static int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
- INT16, INT16, CARD16, CARD16,
- INT16, INT16, CARD16, CARD16);
-static int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
- INT16, INT16, CARD16, CARD16,
- INT16, INT16, CARD16, CARD16);
-static int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
- INT16, INT16, CARD16, CARD16,
- INT16, INT16, CARD16, CARD16);
-static int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr,
- INT16, INT16, CARD16, CARD16,
- INT16, INT16, CARD16, CARD16);
-static int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
-static int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
-static int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*);
-static int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8,
- CARD16, CARD16,CARD16, CARD16,
- unsigned int*, unsigned int*);
-static int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
- INT16, INT16, CARD16, CARD16,
- INT16, INT16, CARD16, CARD16,
- XvImagePtr, unsigned char*, Bool,
- CARD16, CARD16);
-static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr,
- CARD16*, CARD16*, int*, int*);
-
-
-/* ScreenRec fields */
-
-static Bool xf86XVDestroyWindow(WindowPtr pWin);
-static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2);
-static void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind);
-static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy);
-
-#define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1)
-
-/* ScrnInfoRec functions */
-
-static Bool xf86XVEnterVT(int, int);
-static void xf86XVLeaveVT(int, int);
-static void xf86XVAdjustFrame(int index, int x, int y, int flags);
-static void xf86XVModeSet(ScrnInfoPtr pScrn);
-
-/* misc */
-
-static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int);
-
-
-static DevPrivateKeyRec XF86XVWindowKeyRec;
-#define XF86XVWindowKey (&XF86XVWindowKeyRec)
-
-DevPrivateKey XF86XvScreenKey;
-
-static unsigned long PortResource = 0;
-
-DevPrivateKey (*XvGetScreenKeyProc)(void) = NULL;
-unsigned long (*XvGetRTPortProc)(void) = NULL;
-int (*XvScreenInitProc)(ScreenPtr) = NULL;
-
-#define GET_XV_SCREEN(pScreen) \
- ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey))
-
-#define GET_XF86XV_SCREEN(pScreen) \
- ((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr))
-
-#define GET_XF86XV_WINDOW(pWin) \
- ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey))
-
-static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL;
-static int NumGenDrivers = 0;
-
-int
-xf86XVRegisterGenericAdaptorDriver(
- xf86XVInitGenericAdaptorPtr InitFunc
-){
- xf86XVInitGenericAdaptorPtr *newdrivers;
-
- newdrivers = realloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) *
- (1 + NumGenDrivers));
- if (!newdrivers)
- return 0;
- GenDrivers = newdrivers;
-
- GenDrivers[NumGenDrivers++] = InitFunc;
-
- return 1;
-}
-
-int
-xf86XVListGenericAdaptors(
- ScrnInfoPtr pScrn,
- XF86VideoAdaptorPtr **adaptors
-){
- int i,j,n,num;
- XF86VideoAdaptorPtr *DrivAdap,*new;
-
- num = 0;
- *adaptors = NULL;
- /*
- * The v4l driver registers itself first, but can use surfaces registered
- * by other drivers. So, call the v4l driver last.
- */
- for (i = NumGenDrivers; --i >= 0; ) {
- DrivAdap = NULL;
- n = (*GenDrivers[i])(pScrn, &DrivAdap);
- if (0 == n)
- continue;
- new = realloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n));
- if (NULL == new)
- continue;
- *adaptors = new;
- for (j = 0; j < n; j++, num++)
- (*adaptors)[num] = DrivAdap[j];
- }
- return num;
-}
-
-
-/**************** Offscreen surface stuff *******************/
-
-typedef struct {
- XF86OffscreenImagePtr images;
- int num;
-} OffscreenImageRec;
-
-static DevPrivateKeyRec OffscreenPrivateKeyRec;
-#define OffscreenPrivateKey (&OffscreenPrivateKeyRec)
-#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey))
-
-Bool
-xf86XVRegisterOffscreenImages(
- ScreenPtr pScreen,
- XF86OffscreenImagePtr images,
- int num
-){
- OffscreenImageRec *OffscreenImage;
- /* This function may be called before xf86XVScreenInit, so there's
- * no better place than this to call dixRegisterPrivateKey to ensure we
- * have space reserved. After the first call it is a no-op. */
- if(!dixRegisterPrivateKey(OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) ||
- !(OffscreenImage = GetOffscreenImage(pScreen)))
- /* Every X.org driver assumes this function always succeeds, so
- * just die on allocation failure. */
- FatalError("Could not allocate private storage for XV offscreen images.\n");
-
- OffscreenImage->num = num;
- OffscreenImage->images = images;
- return TRUE;
-}
-
-XF86OffscreenImagePtr
-xf86XVQueryOffscreenImages(
- ScreenPtr pScreen,
- int *num
-){
- OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen);
- *num = OffscreenImage->num;
- return OffscreenImage->images;
-}
-
-
-XF86VideoAdaptorPtr
-xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn)
-{
- return calloc(1, sizeof(XF86VideoAdaptorRec));
-}
-
-void
-xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr)
-{
- free(ptr);
-}
-
-
-Bool
-xf86XVScreenInit(
- ScreenPtr pScreen,
- XF86VideoAdaptorPtr *adaptors,
- int num
-){
- ScrnInfoPtr pScrn;
- XF86XVScreenPtr ScreenPriv;
- XvScreenPtr pxvs;
-
- if(num <= 0 ||
- !XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc)
- return FALSE;
-
- if(Success != (*XvScreenInitProc)(pScreen)) return FALSE;
-
- if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0))
- return FALSE;
-
- XF86XvScreenKey = (*XvGetScreenKeyProc)();
-
- PortResource = (*XvGetRTPortProc)();
-
- pxvs = GET_XV_SCREEN(pScreen);
-
- /* Anyone initializing the Xv layer must provide these two.
- The Xv di layer calls them without even checking if they exist! */
-
- pxvs->ddCloseScreen = xf86XVCloseScreen;
- pxvs->ddQueryAdaptors = xf86XVQueryAdaptors;
-
- /* The Xv di layer provides us with a private hook so that we don't
- have to allocate our own screen private. They also provide
- a CloseScreen hook so that we don't have to wrap it. I'm not
- sure that I appreciate that. */
-
- ScreenPriv = malloc(sizeof(XF86XVScreenRec));
- pxvs->devPriv.ptr = (pointer)ScreenPriv;
-
- if(!ScreenPriv) return FALSE;
-
- pScrn = xf86Screens[pScreen->myNum];
-
- ScreenPriv->DestroyWindow = pScreen->DestroyWindow;
- ScreenPriv->WindowExposures = pScreen->WindowExposures;
- ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
- ScreenPriv->ClipNotify = pScreen->ClipNotify;
- ScreenPriv->EnterVT = pScrn->EnterVT;
- ScreenPriv->LeaveVT = pScrn->LeaveVT;
- ScreenPriv->AdjustFrame = pScrn->AdjustFrame;
- ScreenPriv->ModeSet = pScrn->ModeSet;
-
- pScreen->DestroyWindow = xf86XVDestroyWindow;
- pScreen->WindowExposures = xf86XVWindowExposures;
- pScreen->ClipNotify = xf86XVClipNotify;
- pScrn->EnterVT = xf86XVEnterVT;
- pScrn->LeaveVT = xf86XVLeaveVT;
- if(pScrn->AdjustFrame)
- pScrn->AdjustFrame = xf86XVAdjustFrame;
- pScrn->ModeSet = xf86XVModeSet;
-
- if(!xf86XVInitAdaptors(pScreen, adaptors, num))
- return FALSE;
-
- return TRUE;
-}
-
-static void
-xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor)
-{
- int i;
-
- free(pAdaptor->name);
-
- if(pAdaptor->pEncodings) {
- XvEncodingPtr pEncode = pAdaptor->pEncodings;
-
- for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++)
- free(pEncode->name);
- free(pAdaptor->pEncodings);
- }
-
- free(pAdaptor->pFormats);
-
- if(pAdaptor->pPorts) {
- XvPortPtr pPort = pAdaptor->pPorts;
- XvPortRecPrivatePtr pPriv;
-
- for(i = 0; i < pAdaptor->nPorts; i++, pPort++) {
- pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
- if(pPriv) {
- if(pPriv->clientClip)
- RegionDestroy(pPriv->clientClip);
- if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
- RegionDestroy(pPriv->pCompositeClip);
- if (pPriv->ckeyFilled)
- RegionDestroy(pPriv->ckeyFilled);
- free(pPriv);
- }
- }
- free(pAdaptor->pPorts);
- }
-
- if(pAdaptor->nAttributes) {
- XvAttributePtr pAttribute = pAdaptor->pAttributes;
-
- for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++)
- free(pAttribute->name);
- free(pAdaptor->pAttributes);
- }
-
- free(pAdaptor->pImages);
- free(pAdaptor->devPriv.ptr);
-}
-
-static Bool
-xf86XVInitAdaptors(
- ScreenPtr pScreen,
- XF86VideoAdaptorPtr *infoPtr,
- int number
-) {
- XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- XF86VideoAdaptorPtr adaptorPtr;
- XvAdaptorPtr pAdaptor, pa;
- XvAdaptorRecPrivatePtr adaptorPriv;
- int na, numAdaptor;
- XvPortRecPrivatePtr portPriv;
- XvPortPtr pPort, pp;
- int numPort;
- XF86AttributePtr attributePtr;
- XvAttributePtr pAttribute, pat;
- XF86VideoFormatPtr formatPtr;
- XvFormatPtr pFormat, pf;
- int numFormat, totFormat;
- XF86VideoEncodingPtr encodingPtr;
- XvEncodingPtr pEncode, pe;
- XF86ImagePtr imagePtr;
- XvImagePtr pImage, pi;
- int numVisuals;
- VisualPtr pVisual;
- int i;
-
- pxvs->nAdaptors = 0;
- pxvs->pAdaptors = NULL;
-
- if(!(pAdaptor = calloc(number, sizeof(XvAdaptorRec))))
- return FALSE;
-
- for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) {
- adaptorPtr = infoPtr[na];
-
- if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute ||
- !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize)
- continue;
-
- /* client libs expect at least one encoding */
- if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings)
- continue;
-
- pa->type = adaptorPtr->type;
-
- if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo)
- pa->type &= ~XvVideoMask;
-
- if(!adaptorPtr->PutStill && !adaptorPtr->GetStill)
- pa->type &= ~XvStillMask;
-
- if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes)
- pa->type &= ~XvImageMask;
-
- if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage &&
- !adaptorPtr->PutStill)
- pa->type &= ~XvInputMask;
-
- if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill)
- pa->type &= ~XvOutputMask;
-
- if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask)))
- continue;
- if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask)))
- continue;
-
- pa->pScreen = pScreen;
- pa->ddAllocatePort = xf86XVAllocatePort;
- pa->ddFreePort = xf86XVFreePort;
- pa->ddPutVideo = xf86XVPutVideo;
- pa->ddPutStill = xf86XVPutStill;
- pa->ddGetVideo = xf86XVGetVideo;
- pa->ddGetStill = xf86XVGetStill;
- pa->ddStopVideo = xf86XVStopVideo;
- pa->ddPutImage = xf86XVPutImage;
- pa->ddSetPortAttribute = xf86XVSetPortAttribute;
- pa->ddGetPortAttribute = xf86XVGetPortAttribute;
- pa->ddQueryBestSize = xf86XVQueryBestSize;
- pa->ddQueryImageAttributes = xf86XVQueryImageAttributes;
- pa->name = strdup(adaptorPtr->name);
-
- if(adaptorPtr->nEncodings &&
- (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) {
-
- for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0;
- i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++)
- {
- pe->id = encodingPtr->id;
- pe->pScreen = pScreen;
- pe->name = strdup(encodingPtr->name);
- pe->width = encodingPtr->width;
- pe->height = encodingPtr->height;
- pe->rate.numerator = encodingPtr->rate.numerator;
- pe->rate.denominator = encodingPtr->rate.denominator;
- }
- pa->nEncodings = adaptorPtr->nEncodings;
- pa->pEncodings = pEncode;
- }
-
- if(adaptorPtr->nImages &&
- (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) {
-
- for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages;
- i < adaptorPtr->nImages; i++, pi++, imagePtr++)
- {
- pi->id = imagePtr->id;
- pi->type = imagePtr->type;
- pi->byte_order = imagePtr->byte_order;
- memcpy(pi->guid, imagePtr->guid, 16);
- pi->bits_per_pixel = imagePtr->bits_per_pixel;
- pi->format = imagePtr->format;
- pi->num_planes = imagePtr->num_planes;
- pi->depth = imagePtr->depth;
- pi->red_mask = imagePtr->red_mask;
- pi->green_mask = imagePtr->green_mask;
- pi->blue_mask = imagePtr->blue_mask;
- pi->y_sample_bits = imagePtr->y_sample_bits;
- pi->u_sample_bits = imagePtr->u_sample_bits;
- pi->v_sample_bits = imagePtr->v_sample_bits;
- pi->horz_y_period = imagePtr->horz_y_period;
- pi->horz_u_period = imagePtr->horz_u_period;
- pi->horz_v_period = imagePtr->horz_v_period;
- pi->vert_y_period = imagePtr->vert_y_period;
- pi->vert_u_period = imagePtr->vert_u_period;
- pi->vert_v_period = imagePtr->vert_v_period;
- memcpy(pi->component_order, imagePtr->component_order, 32);
- pi->scanline_order = imagePtr->scanline_order;
- }
- pa->nImages = adaptorPtr->nImages;
- pa->pImages = pImage;
- }
-
- if(adaptorPtr->nAttributes &&
- (pAttribute = calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec))))
- {
- for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0;
- i < adaptorPtr->nAttributes; pat++, i++, attributePtr++)
- {
- pat->flags = attributePtr->flags;
- pat->min_value = attributePtr->min_value;
- pat->max_value = attributePtr->max_value;
- pat->name = strdup(attributePtr->name);
- }
- pa->nAttributes = adaptorPtr->nAttributes;
- pa->pAttributes = pAttribute;
- }
-
-
- totFormat = adaptorPtr->nFormats;
-
- if(!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) {
- xf86XVFreeAdaptor(pa);
- continue;
- }
- for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats;
- i < adaptorPtr->nFormats; i++, formatPtr++)
- {
- numVisuals = pScreen->numVisuals;
- pVisual = pScreen->visuals;
-
- while(numVisuals--) {
- if((pVisual->class == formatPtr->class) &&
- (pVisual->nplanes == formatPtr->depth)) {
-
- if(numFormat >= totFormat) {
- void *moreSpace;
- totFormat *= 2;
- moreSpace = realloc(pFormat,
- totFormat * sizeof(XvFormatRec));
- if(!moreSpace) break;
- pFormat = moreSpace;
- pf = pFormat + numFormat;
- }
-
- pf->visual = pVisual->vid;
- pf->depth = formatPtr->depth;
-
- pf++;
- numFormat++;
- }
- pVisual++;
- }
- }
- pa->nFormats = numFormat;
- pa->pFormats = pFormat;
- if(!numFormat) {
- xf86XVFreeAdaptor(pa);
- continue;
- }
-
- if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) {
- xf86XVFreeAdaptor(pa);
- continue;
- }
-
- adaptorPriv->flags = adaptorPtr->flags;
- adaptorPriv->PutVideo = adaptorPtr->PutVideo;
- adaptorPriv->PutStill = adaptorPtr->PutStill;
- adaptorPriv->GetVideo = adaptorPtr->GetVideo;
- adaptorPriv->GetStill = adaptorPtr->GetStill;
- adaptorPriv->StopVideo = adaptorPtr->StopVideo;
- adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute;
- adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute;
- adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize;
- adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes;
- adaptorPriv->PutImage = adaptorPtr->PutImage;
- adaptorPriv->ReputImage = adaptorPtr->ReputImage; /* image/still */
-
- pa->devPriv.ptr = (pointer)adaptorPriv;
-
- if(!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) {
- xf86XVFreeAdaptor(pa);
- continue;
- }
- for(pp = pPort, i = 0, numPort = 0;
- i < adaptorPtr->nPorts; i++) {
-
- if(!(pp->id = FakeClientID(0)))
- continue;
-
- if(!(portPriv = calloc(1, sizeof(XvPortRecPrivate))))
- continue;
-
- if(!AddResource(pp->id, PortResource, pp)) {
- free(portPriv);
- continue;
- }
-
- pp->pAdaptor = pa;
- pp->pNotify = (XvPortNotifyPtr)NULL;
- pp->pDraw = (DrawablePtr)NULL;
- pp->client = (ClientPtr)NULL;
- pp->grab.client = (ClientPtr)NULL;
- pp->time = currentTime;
- pp->devPriv.ptr = portPriv;
-
- portPriv->pScrn = pScrn;
- portPriv->AdaptorRec = adaptorPriv;
- portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr;
-
- pp++;
- numPort++;
- }
- pa->nPorts = numPort;
- pa->pPorts = pPort;
- if(!numPort) {
- xf86XVFreeAdaptor(pa);
- continue;
- }
-
- pa->base_id = pPort->id;
-
- pa++;
- numAdaptor++;
- }
-
- if(numAdaptor) {
- pxvs->nAdaptors = numAdaptor;
- pxvs->pAdaptors = pAdaptor;
- } else {
- free(pAdaptor);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Video should be clipped to the intersection of the window cliplist
- and the client cliplist specified in the GC for which the video was
- initialized. When we need to reclip a window, the GC that started
- the video may not even be around anymore. That's why we save the
- client clip from the GC when the video is initialized. We then
- use xf86XVUpdateCompositeClip to calculate the new composite clip
- when we need it. This is different from what DEC did. They saved
- the GC and used it's clip list when they needed to reclip the window,
- even if the client clip was different from the one the video was
- initialized with. If the original GC was destroyed, they had to stop
- the video. I like the new method better (MArk).
-
- This function only works for windows. Will need to rewrite when
- (if) we support pixmap rendering.
-*/
-
-static void
-xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv)
-{
- RegionPtr pregWin, pCompositeClip;
- WindowPtr pWin;
- Bool freeCompClip = FALSE;
-
- if(portPriv->pCompositeClip)
- return;
-
- pWin = (WindowPtr)portPriv->pDraw;
-
- /* get window clip list */
- if(portPriv->subWindowMode == IncludeInferiors) {
- pregWin = NotClippedByChildren(pWin);
- freeCompClip = TRUE;
- } else
- pregWin = &pWin->clipList;
-
- if(!portPriv->clientClip) {
- portPriv->pCompositeClip = pregWin;
- portPriv->FreeCompositeClip = freeCompClip;
- return;
- }
-
- pCompositeClip = RegionCreate(NullBox, 1);
- RegionCopy(pCompositeClip, portPriv->clientClip);
- RegionTranslate(pCompositeClip,
- portPriv->pDraw->x, portPriv->pDraw->y);
- RegionIntersect(pCompositeClip, pregWin, pCompositeClip);
-
- portPriv->pCompositeClip = pCompositeClip;
- portPriv->FreeCompositeClip = TRUE;
-
- if(freeCompClip) {
- RegionDestroy(pregWin);
- }
-}
-
-/* Save the current clientClip and update the CompositeClip whenever
- we have a fresh GC */
-
-static void
-xf86XVCopyClip(
- XvPortRecPrivatePtr portPriv,
- GCPtr pGC
-){
- /* copy the new clip if it exists */
- if((pGC->clientClipType == CT_REGION) && pGC->clientClip) {
- if(!portPriv->clientClip)
- portPriv->clientClip = RegionCreate(NullBox, 1);
- /* Note: this is in window coordinates */
- RegionCopy(portPriv->clientClip, pGC->clientClip);
- RegionTranslate(portPriv->clientClip,
- pGC->clipOrg.x, pGC->clipOrg.y);
- } else if(portPriv->clientClip) { /* free the old clientClip */
- RegionDestroy(portPriv->clientClip);
- portPriv->clientClip = NULL;
- }
-
- /* get rid of the old clip list */
- if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) {
- RegionDestroy(portPriv->pCompositeClip);
- }
-
- portPriv->pCompositeClip = pGC->pCompositeClip;
- portPriv->FreeCompositeClip = FALSE;
- portPriv->subWindowMode = pGC->subWindowMode;
-}
-
-static void
-xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv,
- GCPtr pGC,
- DrawablePtr pDraw)
-{
- if (!portPriv->clientClip)
- portPriv->clientClip = RegionCreate(NullBox, 1);
- /* Keep the original GC composite clip around for ReputImage */
- RegionCopy(portPriv->clientClip, pGC->pCompositeClip);
- RegionTranslate(portPriv->clientClip,
- -pDraw->x, -pDraw->y);
-
- /* get rid of the old clip list */
- if (portPriv->pCompositeClip && portPriv->FreeCompositeClip)
- RegionDestroy(portPriv->pCompositeClip);
-
- portPriv->pCompositeClip = pGC->pCompositeClip;
- portPriv->FreeCompositeClip = FALSE;
- portPriv->subWindowMode = pGC->subWindowMode;
-}
-
-static int
-xf86XVRegetVideo(XvPortRecPrivatePtr portPriv)
-{
- RegionRec WinRegion;
- RegionRec ClipRegion;
- BoxRec WinBox;
- int ret = Success;
- Bool clippedAway = FALSE;
-
- xf86XVUpdateCompositeClip(portPriv);
-
- /* translate the video region to the screen */
- WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
- WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
- WinBox.x2 = WinBox.x1 + portPriv->drw_w;
- WinBox.y2 = WinBox.y1 + portPriv->drw_h;
-
- /* clip to the window composite clip */
- RegionInit(&WinRegion, &WinBox, 1);
- RegionNull(&ClipRegion);
- RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
-
- /* that's all if it's totally obscured */
- if(!RegionNotEmpty(&ClipRegion)) {
- clippedAway = TRUE;
- goto CLIP_VIDEO_BAILOUT;
- }
-
- if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
- RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
- }
-
- ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn,
- portPriv->vid_x, portPriv->vid_y,
- WinBox.x1, WinBox.y1,
- portPriv->vid_w, portPriv->vid_h,
- portPriv->drw_w, portPriv->drw_h,
- &ClipRegion, portPriv->DevPriv.ptr,
- portPriv->pDraw);
-
- if(ret == Success)
- portPriv->isOn = XV_ON;
-
-CLIP_VIDEO_BAILOUT:
-
- if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) {
- (*portPriv->AdaptorRec->StopVideo)(
- portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
- portPriv->isOn = XV_PENDING;
- }
-
- /* This clip was copied and only good for one shot */
- if(!portPriv->FreeCompositeClip)
- portPriv->pCompositeClip = NULL;
-
- RegionUninit(&WinRegion);
- RegionUninit(&ClipRegion);
-
- return ret;
-}
-
-
-static int
-xf86XVReputVideo(XvPortRecPrivatePtr portPriv)
-{
- RegionRec WinRegion;
- RegionRec ClipRegion;
- BoxRec WinBox;
- int ret = Success;
- Bool clippedAway = FALSE;
-
- xf86XVUpdateCompositeClip(portPriv);
-
- /* translate the video region to the screen */
- WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
- WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
- WinBox.x2 = WinBox.x1 + portPriv->drw_w;
- WinBox.y2 = WinBox.y1 + portPriv->drw_h;
-
- /* clip to the window composite clip */
- RegionInit(&WinRegion, &WinBox, 1);
- RegionNull(&ClipRegion);
- RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
-
- /* clip and translate to the viewport */
- if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
- RegionRec VPReg;
- BoxRec VPBox;
-
- VPBox.x1 = portPriv->pScrn->frameX0;
- VPBox.y1 = portPriv->pScrn->frameY0;
- VPBox.x2 = portPriv->pScrn->frameX1 + 1;
- VPBox.y2 = portPriv->pScrn->frameY1 + 1;
-
- RegionInit(&VPReg, &VPBox, 1);
- RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
- RegionUninit(&VPReg);
- }
-
- /* that's all if it's totally obscured */
- if(!RegionNotEmpty(&ClipRegion)) {
- clippedAway = TRUE;
- goto CLIP_VIDEO_BAILOUT;
- }
-
- /* bailout if we have to clip but the hardware doesn't support it */
- if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
- BoxPtr clipBox = RegionRects(&ClipRegion);
- if( (RegionNumRects(&ClipRegion) != 1) ||
- (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
- (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
- {
- clippedAway = TRUE;
- goto CLIP_VIDEO_BAILOUT;
- }
- }
-
- if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
- RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
- }
-
- ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn,
- portPriv->vid_x, portPriv->vid_y,
- WinBox.x1, WinBox.y1,
- portPriv->vid_w, portPriv->vid_h,
- portPriv->drw_w, portPriv->drw_h,
- &ClipRegion, portPriv->DevPriv.ptr,
- portPriv->pDraw);
-
- if(ret == Success) portPriv->isOn = XV_ON;
-
-CLIP_VIDEO_BAILOUT:
-
- if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
- (*portPriv->AdaptorRec->StopVideo)(
- portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
- portPriv->isOn = XV_PENDING;
- }
-
- /* This clip was copied and only good for one shot */
- if(!portPriv->FreeCompositeClip)
- portPriv->pCompositeClip = NULL;
-
- RegionUninit(&WinRegion);
- RegionUninit(&ClipRegion);
-
- return ret;
-}
-
-/* Reput image/still */
-static int
-xf86XVReputImage(XvPortRecPrivatePtr portPriv)
-{
- RegionRec WinRegion;
- RegionRec ClipRegion;
- BoxRec WinBox;
- int ret = Success;
- Bool clippedAway = FALSE;
-
- xf86XVUpdateCompositeClip(portPriv);
-
- /* the clip can get smaller over time */
- RegionCopy(portPriv->clientClip, portPriv->pCompositeClip);
- RegionTranslate(portPriv->clientClip,
- -portPriv->pDraw->x, -portPriv->pDraw->y);
-
- /* translate the video region to the screen */
- WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x;
- WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y;
- WinBox.x2 = WinBox.x1 + portPriv->drw_w;
- WinBox.y2 = WinBox.y1 + portPriv->drw_h;
-
- /* clip to the window composite clip */
- RegionInit(&WinRegion, &WinBox, 1);
- RegionNull(&ClipRegion);
- RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip);
-
- /* clip and translate to the viewport */
- if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
- RegionRec VPReg;
- BoxRec VPBox;
-
- VPBox.x1 = portPriv->pScrn->frameX0;
- VPBox.y1 = portPriv->pScrn->frameY0;
- VPBox.x2 = portPriv->pScrn->frameX1 + 1;
- VPBox.y2 = portPriv->pScrn->frameY1 + 1;
-
- RegionInit(&VPReg, &VPBox, 1);
- RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
- RegionUninit(&VPReg);
- }
-
- /* that's all if it's totally obscured */
- if(!RegionNotEmpty(&ClipRegion)) {
- clippedAway = TRUE;
- goto CLIP_VIDEO_BAILOUT;
- }
-
- /* bailout if we have to clip but the hardware doesn't support it */
- if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
- BoxPtr clipBox = RegionRects(&ClipRegion);
- if( (RegionNumRects(&ClipRegion) != 1) ||
- (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
- (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
- {
- clippedAway = TRUE;
- goto CLIP_VIDEO_BAILOUT;
- }
- }
-
- if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
- RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
- }
-
- ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn,
- portPriv->vid_x, portPriv->vid_y,
- WinBox.x1, WinBox.y1,
- portPriv->vid_w, portPriv->vid_h,
- portPriv->drw_w, portPriv->drw_h,
- &ClipRegion, portPriv->DevPriv.ptr,
- portPriv->pDraw);
-
- portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF;
-
-CLIP_VIDEO_BAILOUT:
-
- if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
- (*portPriv->AdaptorRec->StopVideo)(
- portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
- portPriv->isOn = XV_PENDING;
- }
-
- /* This clip was copied and only good for one shot */
- if(!portPriv->FreeCompositeClip)
- portPriv->pCompositeClip = NULL;
-
- RegionUninit(&WinRegion);
- RegionUninit(&ClipRegion);
-
- return ret;
-}
-
-
-static int
-xf86XVReputAllVideo(WindowPtr pWin, pointer data)
-{
- XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
-
- while(WinPriv) {
- if(WinPriv->PortRec->type == XvInputMask)
- xf86XVReputVideo(WinPriv->PortRec);
- else
- xf86XVRegetVideo(WinPriv->PortRec);
- WinPriv = WinPriv->next;
- }
-
- return WT_WALKCHILDREN;
-}
-
-static int
-xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
-{
- XF86XVWindowPtr winPriv, PrivRoot;
-
- winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin);
-
- /* Enlist our port in the window private */
- while(winPriv) {
- if(winPriv->PortRec == portPriv) /* we're already listed */
- break;
- winPriv = winPriv->next;
- }
-
- if(!winPriv) {
- winPriv = calloc(1, sizeof(XF86XVWindowRec));
- if(!winPriv) return BadAlloc;
- winPriv->PortRec = portPriv;
- winPriv->next = PrivRoot;
- dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv);
- }
-
- portPriv->pDraw = (DrawablePtr)pWin;
-
- return Success;
-}
-
-
-static void
-xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
-{
- XF86XVWindowPtr winPriv, prevPriv = NULL;
- winPriv = GET_XF86XV_WINDOW(pWin);
-
- while(winPriv) {
- if(winPriv->PortRec == portPriv) {
- if(prevPriv)
- prevPriv->next = winPriv->next;
- else
- dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey,
- winPriv->next);
- free(winPriv);
- break;
- }
- prevPriv = winPriv;
- winPriv = winPriv->next;
- }
- portPriv->pDraw = NULL;
- if (portPriv->ckeyFilled) {
- RegionDestroy(portPriv->ckeyFilled);
- portPriv->ckeyFilled = NULL;
- }
- portPriv->clipChanged = FALSE;
-}
-
-static void
-xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv,
- WindowPtr pWin,
- Bool visible)
-{
- if (!visible) {
- if (pPriv->isOn == XV_ON) {
- (*pPriv->AdaptorRec->StopVideo)(pPriv->pScrn, pPriv->DevPriv.ptr, FALSE);
- pPriv->isOn = XV_PENDING;
- }
-
- if (!pPriv->type) /* overlaid still/image*/
- xf86XVRemovePortFromWindow(pWin, pPriv);
-
- return;
- }
-
- switch (pPriv->type) {
- case XvInputMask:
- xf86XVReputVideo(pPriv);
- break;
- case XvOutputMask:
- xf86XVRegetVideo(pPriv);
- break;
- default: /* overlaid still/image*/
- if (pPriv->AdaptorRec->ReputImage)
- xf86XVReputImage(pPriv);
- break;
- }
-}
-
-static void
-xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged)
-{
- ScreenPtr pScreen = pScrn->pScreen;
- XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
- XvAdaptorPtr pa;
- int c, i;
-
- for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) {
- XvPortPtr pPort = pa->pPorts;
-
- for (i = pa->nPorts; i > 0; i--, pPort++) {
- XvPortRecPrivatePtr pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
- WindowPtr pWin = (WindowPtr)pPriv->pDraw;
- Bool visible;
-
- if (pPriv->isOn == XV_OFF || !pWin)
- continue;
-
- if (onlyChanged && !pPriv->clipChanged)
- continue;
-
- visible = pWin->visibility == VisibilityUnobscured ||
- pWin->visibility == VisibilityPartiallyObscured;
-
- /*
- * Stop and remove still/images if
- * ReputImage isn't supported.
- */
- if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
- visible = FALSE;
-
- xf86XVReputOrStopPort(pPriv, pWin, visible);
-
- pPriv->clipChanged = FALSE;
- }
- }
-}
-
-/**** ScreenRec fields ****/
-
-static Bool
-xf86XVDestroyWindow(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
- XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin);
- int ret;
-
- while(WinPriv) {
- XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
-
- if(pPriv->isOn > XV_OFF) {
- (*pPriv->AdaptorRec->StopVideo)(
- pPriv->pScrn, pPriv->DevPriv.ptr, TRUE);
- pPriv->isOn = XV_OFF;
- }
-
- pPriv->pDraw = NULL;
- tmp = WinPriv;
- WinPriv = WinPriv->next;
- free(tmp);
- }
-
- dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL);
-
- pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
- ret = (*pScreen->DestroyWindow)(pWin);
- pScreen->DestroyWindow = xf86XVDestroyWindow;
-
- return ret;
-}
-
-static void
-xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind)
-{
- ScreenPtr pScreen;
- XF86XVScreenPtr ScreenPriv;
- ScrnInfoPtr pScrn;
-
- if (pWin)
- pScreen = pWin->drawable.pScreen;
- else
- pScreen = pLayerWin->drawable.pScreen;
-
- ScreenPriv = GET_XF86XV_SCREEN(pScreen);
- pScrn = xf86Screens[pScreen->myNum];
-
- xf86XVReputOrStopAllPorts(pScrn, TRUE);
-
- pScreen->PostValidateTree = ScreenPriv->PostValidateTree;
- if (pScreen->PostValidateTree) {
- (*pScreen->PostValidateTree)(pWin, pLayerWin, kind);
- }
- ScreenPriv->PostValidateTree = PostValidateTreeUndefined;
-}
-
-static void
-xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
- XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
- XvPortRecPrivatePtr pPriv;
- Bool AreasExposed;
-
- AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1));
-
- pScreen->WindowExposures = ScreenPriv->WindowExposures;
- (*pScreen->WindowExposures)(pWin, reg1, reg2);
- pScreen->WindowExposures = xf86XVWindowExposures;
-
- /* filter out XClearWindow/Area */
- if (!pWin->valdata) return;
-
- while(WinPriv) {
- Bool visible = TRUE;
-
- pPriv = WinPriv->PortRec;
-
- /*
- * Stop and remove still/images if areas were exposed and
- * ReputImage isn't supported.
- */
- if (!pPriv->type && !pPriv->AdaptorRec->ReputImage)
- visible = !AreasExposed;
-
- /*
- * Subtract exposed areas from overlaid image to match textured video
- * behavior.
- */
- if (!pPriv->type && pPriv->clientClip)
- RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1);
-
- if (visible && pPriv->ckeyFilled) {
- RegionRec tmp;
- RegionNull(&tmp);
- RegionCopy(&tmp, reg1);
- RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y);
- RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp);
- }
-
- WinPriv = WinPriv->next;
- xf86XVReputOrStopPort(pPriv, pWin, visible);
-
- pPriv->clipChanged = FALSE;
- }
-}
-
-static void
-xf86XVClipNotify(WindowPtr pWin, int dx, int dy)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
- XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
- XvPortRecPrivatePtr pPriv;
-
- while(WinPriv) {
- pPriv = WinPriv->PortRec;
-
- if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
- RegionDestroy(pPriv->pCompositeClip);
-
- pPriv->pCompositeClip = NULL;
-
- if (pPriv->AdaptorRec->ClipNotify)
- (*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr,
- pWin, dx, dy);
-
- pPriv->clipChanged = TRUE;
-
- if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) {
- ScreenPriv->PostValidateTree = pScreen->PostValidateTree;
- pScreen->PostValidateTree = xf86XVPostValidateTree;
- }
-
- WinPriv = WinPriv->next;
- }
-
- if(ScreenPriv->ClipNotify) {
- pScreen->ClipNotify = ScreenPriv->ClipNotify;
- (*pScreen->ClipNotify)(pWin, dx, dy);
- pScreen->ClipNotify = xf86XVClipNotify;
- }
-}
-
-
-
-/**** Required XvScreenRec fields ****/
-
-static Bool
-xf86XVCloseScreen(int i, ScreenPtr pScreen)
-{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
- XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
- XvAdaptorPtr pa;
- int c;
-
- if(!ScreenPriv) return TRUE;
-
- pScreen->DestroyWindow = ScreenPriv->DestroyWindow;
- pScreen->WindowExposures = ScreenPriv->WindowExposures;
- pScreen->ClipNotify = ScreenPriv->ClipNotify;
-
- pScrn->EnterVT = ScreenPriv->EnterVT;
- pScrn->LeaveVT = ScreenPriv->LeaveVT;
- pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
- pScrn->ModeSet = ScreenPriv->ModeSet;
-
- for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) {
- xf86XVFreeAdaptor(pa);
- }
-
- free(pxvs->pAdaptors);
- free(ScreenPriv);
- return TRUE;
-}
-
-
-static int
-xf86XVQueryAdaptors(
- ScreenPtr pScreen,
- XvAdaptorPtr *p_pAdaptors,
- int *p_nAdaptors
-){
- XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
-
- *p_nAdaptors = pxvs->nAdaptors;
- *p_pAdaptors = pxvs->pAdaptors;
-
- return Success;
-}
-
-
-/**** ScrnInfoRec fields ****/
-
-static Bool
-xf86XVEnterVT(int index, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[index];
- ScreenPtr pScreen = screenInfo.screens[index];
- XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
- Bool ret;
-
- pScrn->EnterVT = ScreenPriv->EnterVT;
- ret = (*ScreenPriv->EnterVT)(index, flags);
- ScreenPriv->EnterVT = pScrn->EnterVT;
- pScrn->EnterVT = xf86XVEnterVT;
-
- if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0);
-
- return ret;
-}
-
-static void
-xf86XVLeaveVT(int index, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[index];
- ScreenPtr pScreen = screenInfo.screens[index];
- XvScreenPtr pxvs = GET_XV_SCREEN(pScreen);
- XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
- XvAdaptorPtr pAdaptor;
- XvPortPtr pPort;
- XvPortRecPrivatePtr pPriv;
- int i, j;
-
- for(i = 0; i < pxvs->nAdaptors; i++) {
- pAdaptor = &pxvs->pAdaptors[i];
- for(j = 0; j < pAdaptor->nPorts; j++) {
- pPort = &pAdaptor->pPorts[j];
- pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr;
- if(pPriv->isOn > XV_OFF) {
-
- (*pPriv->AdaptorRec->StopVideo)(
- pPriv->pScrn, pPriv->DevPriv.ptr, TRUE);
- pPriv->isOn = XV_OFF;
-
- if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
- RegionDestroy(pPriv->pCompositeClip);
-
- pPriv->pCompositeClip = NULL;
-
- if(!pPriv->type && pPriv->pDraw) { /* still */
- xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv);
- }
- }
- }
- }
-
- pScrn->LeaveVT = ScreenPriv->LeaveVT;
- (*ScreenPriv->LeaveVT)(index, flags);
- ScreenPriv->LeaveVT = pScrn->LeaveVT;
- pScrn->LeaveVT = xf86XVLeaveVT;
-}
-
-static void
-xf86XVAdjustFrame(int index, int x, int y, int flags)
-{
- ScrnInfoPtr pScrn = xf86Screens[index];
- ScreenPtr pScreen = pScrn->pScreen;
- XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen);
-
- if(ScreenPriv->AdjustFrame) {
- pScrn->AdjustFrame = ScreenPriv->AdjustFrame;
- (*pScrn->AdjustFrame)(index, x, y, flags);
- pScrn->AdjustFrame = xf86XVAdjustFrame;
- }
-
- xf86XVReputOrStopAllPorts(pScrn, FALSE);
-}
-
-static void
-xf86XVModeSet(ScrnInfoPtr pScrn)
-{
- ScreenPtr pScreen = pScrn->pScreen;
- XF86XVScreenPtr ScreenPriv;
-
- /* Can be called before pScrn->pScreen is set */
- if (!pScreen)
- return;
-
- ScreenPriv = GET_XF86XV_SCREEN(pScreen);
-
- if (ScreenPriv->ModeSet) {
- pScrn->ModeSet = ScreenPriv->ModeSet;
- (*pScrn->ModeSet)(pScrn);
- pScrn->ModeSet = xf86XVModeSet;
- }
-
- xf86XVReputOrStopAllPorts(pScrn, FALSE);
-}
-
-/**** XvAdaptorRec fields ****/
-
-static int
-xf86XVAllocatePort(
- unsigned long port,
- XvPortPtr pPort,
- XvPortPtr *ppPort
-){
- *ppPort = pPort;
- return Success;
-}
-
-
-
-static int
-xf86XVFreePort(XvPortPtr pPort)
-{
- return Success;
-}
-
-
-static int
-xf86XVPutVideo(
- ClientPtr client,
- DrawablePtr pDraw,
- XvPortPtr pPort,
- GCPtr pGC,
- INT16 vid_x, INT16 vid_y,
- CARD16 vid_w, CARD16 vid_h,
- INT16 drw_x, INT16 drw_y,
- CARD16 drw_w, CARD16 drw_h
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
- int result;
-
- /* No dumping video to pixmaps... For now anyhow */
- if(pDraw->type != DRAWABLE_WINDOW) {
- pPort->pDraw = (DrawablePtr)NULL;
- return BadAlloc;
- }
-
- /* If we are changing windows, unregister our port in the old window */
- if(portPriv->pDraw && (portPriv->pDraw != pDraw))
- xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
-
- /* Register our port with the new window */
- result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
- if(result != Success) return result;
-
- portPriv->type = XvInputMask;
-
- /* save a copy of these parameters */
- portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
- portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
- portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
- portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
-
- /* make sure we have the most recent copy of the clientClip */
- xf86XVCopyClip(portPriv, pGC);
-
- /* To indicate to the DI layer that we were successful */
- pPort->pDraw = pDraw;
-
- if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
-
- return(xf86XVReputVideo(portPriv));
-}
-
-static int
-xf86XVPutStill(
- ClientPtr client,
- DrawablePtr pDraw,
- XvPortPtr pPort,
- GCPtr pGC,
- INT16 vid_x, INT16 vid_y,
- CARD16 vid_w, CARD16 vid_h,
- INT16 drw_x, INT16 drw_y,
- CARD16 drw_w, CARD16 drw_h
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
- RegionRec WinRegion;
- RegionRec ClipRegion;
- BoxRec WinBox;
- int ret = Success;
- Bool clippedAway = FALSE;
-
- if (pDraw->type != DRAWABLE_WINDOW)
- return BadAlloc;
-
- if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
-
- WinBox.x1 = pDraw->x + drw_x;
- WinBox.y1 = pDraw->y + drw_y;
- WinBox.x2 = WinBox.x1 + drw_w;
- WinBox.y2 = WinBox.y1 + drw_h;
-
- xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
-
- RegionInit(&WinRegion, &WinBox, 1);
- RegionNull(&ClipRegion);
- RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
-
- if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
- RegionRec VPReg;
- BoxRec VPBox;
-
- VPBox.x1 = portPriv->pScrn->frameX0;
- VPBox.y1 = portPriv->pScrn->frameY0;
- VPBox.x2 = portPriv->pScrn->frameX1 + 1;
- VPBox.y2 = portPriv->pScrn->frameY1 + 1;
-
- RegionInit(&VPReg, &VPBox, 1);
- RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
- RegionUninit(&VPReg);
- }
-
- if(portPriv->pDraw) {
- xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
- }
-
- if(!RegionNotEmpty(&ClipRegion)) {
- clippedAway = TRUE;
- goto PUT_STILL_BAILOUT;
- }
-
- if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
- BoxPtr clipBox = RegionRects(&ClipRegion);
- if( (RegionNumRects(&ClipRegion) != 1) ||
- (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
- (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
- {
- clippedAway = TRUE;
- goto PUT_STILL_BAILOUT;
- }
- }
-
- if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
- RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
- }
-
- ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn,
- vid_x, vid_y, WinBox.x1, WinBox.y1,
- vid_w, vid_h, drw_w, drw_h,
- &ClipRegion, portPriv->DevPriv.ptr,
- pDraw);
-
- if((ret == Success) &&
- (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) {
-
- xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
- portPriv->isOn = XV_ON;
- portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
- portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
- portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
- portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
- portPriv->type = 0; /* no mask means it's transient and should
- not be reput once it's removed */
- pPort->pDraw = pDraw; /* make sure we can get stop requests */
- }
-
-PUT_STILL_BAILOUT:
-
- if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
- (*portPriv->AdaptorRec->StopVideo)(
- portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
- portPriv->isOn = XV_PENDING;
- }
-
- /* This clip was copied and only good for one shot */
- if(!portPriv->FreeCompositeClip)
- portPriv->pCompositeClip = NULL;
-
- RegionUninit(&WinRegion);
- RegionUninit(&ClipRegion);
-
- return ret;
-}
-
-static int
-xf86XVGetVideo(
- ClientPtr client,
- DrawablePtr pDraw,
- XvPortPtr pPort,
- GCPtr pGC,
- INT16 vid_x, INT16 vid_y,
- CARD16 vid_w, CARD16 vid_h,
- INT16 drw_x, INT16 drw_y,
- CARD16 drw_w, CARD16 drw_h
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
- int result;
-
- /* No pixmaps... For now anyhow */
- if(pDraw->type != DRAWABLE_WINDOW) {
- pPort->pDraw = (DrawablePtr)NULL;
- return BadAlloc;
- }
-
- /* If we are changing windows, unregister our port in the old window */
- if(portPriv->pDraw && (portPriv->pDraw != pDraw))
- xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
-
- /* Register our port with the new window */
- result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
- if(result != Success) return result;
-
- portPriv->type = XvOutputMask;
-
- /* save a copy of these parameters */
- portPriv->vid_x = vid_x; portPriv->vid_y = vid_y;
- portPriv->vid_w = vid_w; portPriv->vid_h = vid_h;
- portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
- portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
-
- /* make sure we have the most recent copy of the clientClip */
- xf86XVCopyClip(portPriv, pGC);
-
- /* To indicate to the DI layer that we were successful */
- pPort->pDraw = pDraw;
-
- if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
-
- return(xf86XVRegetVideo(portPriv));
-}
-
-static int
-xf86XVGetStill(
- ClientPtr client,
- DrawablePtr pDraw,
- XvPortPtr pPort,
- GCPtr pGC,
- INT16 vid_x, INT16 vid_y,
- CARD16 vid_w, CARD16 vid_h,
- INT16 drw_x, INT16 drw_y,
- CARD16 drw_w, CARD16 drw_h
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
- RegionRec WinRegion;
- RegionRec ClipRegion;
- BoxRec WinBox;
- int ret = Success;
- Bool clippedAway = FALSE;
-
- if (pDraw->type != DRAWABLE_WINDOW)
- return BadAlloc;
-
- if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
-
- WinBox.x1 = pDraw->x + drw_x;
- WinBox.y1 = pDraw->y + drw_y;
- WinBox.x2 = WinBox.x1 + drw_w;
- WinBox.y2 = WinBox.y1 + drw_h;
-
- RegionInit(&WinRegion, &WinBox, 1);
- RegionNull(&ClipRegion);
- RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
-
- if(portPriv->pDraw) {
- xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
- }
-
- if(!RegionNotEmpty(&ClipRegion)) {
- clippedAway = TRUE;
- goto GET_STILL_BAILOUT;
- }
-
- if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
- RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
- }
-
- ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn,
- vid_x, vid_y, WinBox.x1, WinBox.y1,
- vid_w, vid_h, drw_w, drw_h,
- &ClipRegion, portPriv->DevPriv.ptr,
- pDraw);
-
-GET_STILL_BAILOUT:
-
- if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
- (*portPriv->AdaptorRec->StopVideo)(
- portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
- portPriv->isOn = XV_PENDING;
- }
-
- RegionUninit(&WinRegion);
- RegionUninit(&ClipRegion);
-
- return ret;
-}
-
-
-
-static int
-xf86XVStopVideo(
- ClientPtr client,
- XvPortPtr pPort,
- DrawablePtr pDraw
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
-
- if(pDraw->type != DRAWABLE_WINDOW)
- return BadAlloc;
-
- xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv);
-
- if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
-
- /* Must free resources. */
-
- if(portPriv->isOn > XV_OFF) {
- (*portPriv->AdaptorRec->StopVideo)(
- portPriv->pScrn, portPriv->DevPriv.ptr, TRUE);
- portPriv->isOn = XV_OFF;
- }
-
- return Success;
-}
-
-static int
-xf86XVSetPortAttribute(
- ClientPtr client,
- XvPortPtr pPort,
- Atom attribute,
- INT32 value
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
-
- return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn,
- attribute, value, portPriv->DevPriv.ptr));
-}
-
-
-static int
-xf86XVGetPortAttribute(
- ClientPtr client,
- XvPortPtr pPort,
- Atom attribute,
- INT32 *p_value
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
-
- return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn,
- attribute, p_value, portPriv->DevPriv.ptr));
-}
-
-
-
-static int
-xf86XVQueryBestSize(
- ClientPtr client,
- XvPortPtr pPort,
- CARD8 motion,
- CARD16 vid_w, CARD16 vid_h,
- CARD16 drw_w, CARD16 drw_h,
- unsigned int *p_w, unsigned int *p_h
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
-
- (*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn,
- (Bool)motion, vid_w, vid_h, drw_w, drw_h,
- p_w, p_h, portPriv->DevPriv.ptr);
-
- return Success;
-}
-
-
-static int
-xf86XVPutImage(
- ClientPtr client,
- DrawablePtr pDraw,
- XvPortPtr pPort,
- GCPtr pGC,
- INT16 src_x, INT16 src_y,
- CARD16 src_w, CARD16 src_h,
- INT16 drw_x, INT16 drw_y,
- CARD16 drw_w, CARD16 drw_h,
- XvImagePtr format,
- unsigned char* data,
- Bool sync,
- CARD16 width, CARD16 height
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
- RegionRec WinRegion;
- RegionRec ClipRegion;
- BoxRec WinBox;
- int ret = Success;
- Bool clippedAway = FALSE;
-
- if (pDraw->type != DRAWABLE_WINDOW)
- return BadAlloc;
-
- if(!portPriv->pScrn->vtSema) return Success; /* Success ? */
-
- xf86XVCopyCompositeClip(portPriv, pGC, pDraw);
-
- WinBox.x1 = pDraw->x + drw_x;
- WinBox.y1 = pDraw->y + drw_y;
- WinBox.x2 = WinBox.x1 + drw_w;
- WinBox.y2 = WinBox.y1 + drw_h;
-
- RegionInit(&WinRegion, &WinBox, 1);
- RegionNull(&ClipRegion);
- RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
-
- if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) {
- RegionRec VPReg;
- BoxRec VPBox;
-
- VPBox.x1 = portPriv->pScrn->frameX0;
- VPBox.y1 = portPriv->pScrn->frameY0;
- VPBox.x2 = portPriv->pScrn->frameX1 + 1;
- VPBox.y2 = portPriv->pScrn->frameY1 + 1;
-
- RegionInit(&VPReg, &VPBox, 1);
- RegionIntersect(&ClipRegion, &ClipRegion, &VPReg);
- RegionUninit(&VPReg);
- }
-
- /* If we are changing windows, unregister our port in the old window */
- if(portPriv->pDraw && (portPriv->pDraw != pDraw))
- xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
-
- /* Register our port with the new window */
- ret = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
- if(ret != Success) goto PUT_IMAGE_BAILOUT;
-
- if(!RegionNotEmpty(&ClipRegion)) {
- clippedAway = TRUE;
- goto PUT_IMAGE_BAILOUT;
- }
-
- if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) {
- BoxPtr clipBox = RegionRects(&ClipRegion);
- if( (RegionNumRects(&ClipRegion) != 1) ||
- (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) ||
- (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2))
- {
- clippedAway = TRUE;
- goto PUT_IMAGE_BAILOUT;
- }
- }
-
- if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) {
- RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion);
- }
-
- ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn,
- src_x, src_y, WinBox.x1, WinBox.y1,
- src_w, src_h, drw_w, drw_h, format->id, data, width, height,
- sync, &ClipRegion, portPriv->DevPriv.ptr,
- pDraw);
-
- if((ret == Success) &&
- (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
-
- portPriv->isOn = XV_ON;
- portPriv->vid_x = src_x; portPriv->vid_y = src_y;
- portPriv->vid_w = src_w; portPriv->vid_h = src_h;
- portPriv->drw_x = drw_x; portPriv->drw_y = drw_y;
- portPriv->drw_w = drw_w; portPriv->drw_h = drw_h;
- portPriv->type = 0; /* no mask means it's transient and should
- not be reput once it's removed */
- pPort->pDraw = pDraw; /* make sure we can get stop requests */
- }
-
-PUT_IMAGE_BAILOUT:
-
- if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) {
- (*portPriv->AdaptorRec->StopVideo)(
- portPriv->pScrn, portPriv->DevPriv.ptr, FALSE);
- portPriv->isOn = XV_PENDING;
- }
-
- /* This clip was copied and only good for one shot */
- if(!portPriv->FreeCompositeClip)
- portPriv->pCompositeClip = NULL;
-
- RegionUninit(&WinRegion);
- RegionUninit(&ClipRegion);
-
- return ret;
-}
-
-
-static int
-xf86XVQueryImageAttributes(
- ClientPtr client,
- XvPortPtr pPort,
- XvImagePtr format,
- CARD16 *width,
- CARD16 *height,
- int *pitches,
- int *offsets
-){
- XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr);
-
- return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn,
- format->id, width, height, pitches, offsets);
-}
-
-void
-xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes)
-{
- ScreenPtr pScreen = pDraw->pScreen;
- ChangeGCVal pval[2];
- BoxPtr pbox = RegionRects(fillboxes);
- int i, nbox = RegionNumRects(fillboxes);
- xRectangle *rects;
- GCPtr gc;
-
- if(!xf86Screens[pScreen->myNum]->vtSema) return;
-
- gc = GetScratchGC(pDraw->depth, pScreen);
- pval[0].val = key;
- pval[1].val = IncludeInferiors;
- (void) ChangeGC(NullClient, gc, GCForeground|GCSubwindowMode, pval);
- ValidateGC(pDraw, gc);
-
- rects = malloc(nbox * sizeof(xRectangle));
-
- for(i = 0; i < nbox; i++, pbox++)
- {
- rects[i].x = pbox->x1 - pDraw->x;
- rects[i].y = pbox->y1 - pDraw->y;
- rects[i].width = pbox->x2 - pbox->x1;
- rects[i].height = pbox->y2 - pbox->y1;
- }
-
- (*gc->ops->PolyFillRect)(pDraw, gc, nbox, rects);
-
- free(rects);
- FreeScratchGC (gc);
-}
-
-void
-xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes)
-{
- xf86XVFillKeyHelperDrawable (&pScreen->root->drawable, key, fillboxes);
-}
-
-void
-xf86XVFillKeyHelperPort (DrawablePtr pDraw, pointer data, CARD32 key, RegionPtr clipboxes, Bool fillEverything)
-{
- WindowPtr pWin = (WindowPtr)pDraw;
- XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin);
- XvPortRecPrivatePtr portPriv = NULL;
- RegionRec reg;
- RegionPtr fillboxes;
-
- while (WinPriv) {
- XvPortRecPrivatePtr pPriv = WinPriv->PortRec;
-
- if (data == pPriv->DevPriv.ptr) {
- portPriv = pPriv;
- break;
- }
-
- WinPriv = WinPriv->next;
- }
-
- if (!portPriv)
- return;
-
- if (!portPriv->ckeyFilled)
- portPriv->ckeyFilled = RegionCreate(NULL, 0);
-
- if (!fillEverything) {
- RegionNull(®);
- fillboxes = ®
- RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled);
-
- if (!RegionNotEmpty(fillboxes))
- goto out;
- } else
- fillboxes = clipboxes;
-
-
- RegionCopy(portPriv->ckeyFilled, clipboxes);
-
- xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes);
-out:
- if (!fillEverything)
- RegionUninit(®);
-}
-
-
-/* xf86XVClipVideoHelper -
-
- Takes the dst box in standard X BoxRec form (top and left
- edges inclusive, bottom and right exclusive). The new dst
- box is returned. The source boundaries are given (x1, y1
- inclusive, x2, y2 exclusive) and returned are the new source
- boundaries in 16.16 fixed point.
-*/
-
-Bool
-xf86XVClipVideoHelper(
- BoxPtr dst,
- INT32 *xa,
- INT32 *xb,
- INT32 *ya,
- INT32 *yb,
- RegionPtr reg,
- INT32 width,
- INT32 height
-){
- double xsw, xdw, ysw, ydw;
- INT32 delta;
- BoxPtr extents = RegionExtents(reg);
- int diff;
-
- xsw = (*xb - *xa) << 16;
- xdw = dst->x2 - dst->x1;
- ysw = (*yb - *ya) << 16;
- ydw = dst->y2 - dst->y1;
-
- *xa <<= 16; *xb <<= 16;
- *ya <<= 16; *yb <<= 16;
-
- diff = extents->x1 - dst->x1;
- if (diff > 0) {
- dst->x1 = extents->x1;
- *xa += (diff * xsw) / xdw;
- }
- diff = dst->x2 - extents->x2;
- if (diff > 0) {
- dst->x2 = extents->x2;
- *xb -= (diff * xsw) / xdw;
- }
- diff = extents->y1 - dst->y1;
- if (diff > 0) {
- dst->y1 = extents->y1;
- *ya += (diff * ysw) / ydw;
- }
- diff = dst->y2 - extents->y2;
- if (diff > 0) {
- dst->y2 = extents->y2;
- *yb -= (diff * ysw) / ydw;
- }
-
- if (*xa < 0) {
- diff = (((-*xa) * xdw) + xsw - 1) / xsw;
- dst->x1 += diff;
- *xa += (diff * xsw) / xdw;
- }
- delta = *xb - (width << 16);
- if (delta > 0) {
- diff = ((delta * xdw) + xsw - 1) / xsw;
- dst->x2 -= diff;
- *xb -= (diff * xsw) / xdw;
- }
- if (*xa >= *xb) return FALSE;
-
- if (*ya < 0) {
- diff = (((-*ya) * ydw) + ysw - 1) / ysw;
- dst->y1 += diff;
- *ya += (diff * ysw) / ydw;
- }
- delta = *yb - (height << 16);
- if (delta > 0) {
- diff = ((delta * ydw) + ysw - 1) / ysw;
- dst->y2 -= diff;
- *yb -= (diff * ysw) / ydw;
- }
- if (*ya >= *yb) return FALSE;
-
- if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) ||
- (dst->y1 > extents->y1) || (dst->y2 < extents->y2))
- {
- RegionRec clipReg;
- RegionInit(&clipReg, dst, 1);
- RegionIntersect(reg, reg, &clipReg);
- RegionUninit(&clipReg);
- }
- return TRUE;
-}
-
-void
-xf86XVCopyYUV12ToPacked(
- const void *srcy,
- const void *srcv,
- const void *srcu,
- void *dst,
- int srcPitchy,
- int srcPitchuv,
- int dstPitch,
- int h,
- int w
-){
- CARD32 *Dst;
- const CARD8 *Y, *U, *V;
- int i, j;
-
- w >>= 1;
-
- for (j = 0; j < h; j++) {
- Dst = dst;
- Y = srcy; V = srcv; U = srcu;
- i = w;
- while (i >= 4) {
-#if X_BYTE_ORDER == X_LITTLE_ENDIAN
- Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
- Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24);
- Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24);
- Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24);
-#else
- /* This assumes a little-endian framebuffer */
- Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
- Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1];
- Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2];
- Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3];
-#endif
- Dst += 4; Y += 8; V += 4; U += 4;
- i -= 4;
- }
-
- while (i--) {
-#if X_BYTE_ORDER == X_LITTLE_ENDIAN
- Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24);
-#else
- /* This assumes a little-endian framebuffer */
- Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0];
-#endif
- Dst++; Y += 2; V++; U++;
- }
-
- dst = (CARD8 *)dst + dstPitch;
- srcy = (const CARD8 *)srcy + srcPitchy;
- if (j & 1) {
- srcu = (const CARD8 *)srcu + srcPitchuv;
- srcv = (const CARD8 *)srcv + srcPitchuv;
- }
- }
-}
-
-void
-xf86XVCopyPacked(
- const void *src,
- void *dst,
- int srcPitch,
- int dstPitch,
- int h,
- int w
-){
- const CARD32 *Src;
- CARD32 *Dst;
- int i;
-
- w >>= 1;
- while (--h >= 0) {
- do {
- Dst = dst; Src = src;
- i = w;
- while (i >= 4) {
- Dst[0] = Src[0];
- Dst[1] = Src[1];
- Dst[2] = Src[2];
- Dst[3] = Src[3];
- Dst += 4; Src += 4; i -= 4;
- }
- if (!i) break;
- Dst[0] = Src[0];
- if (i == 1) break;
- Dst[1] = Src[1];
- if (i == 2) break;
- Dst[2] = Src[2];
- } while (0);
-
- src = (const CARD8 *)src + srcPitch;
- dst = (CARD8 *)dst + dstPitch;
- }
-}
+/* + * XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com) + */ +/* + * Copyright (c) 1998-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "misc.h" +#include "xf86.h" +#include "xf86_OSproc.h" + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "regionstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "mivalidate.h" +#include "validate.h" +#include "resource.h" +#include "gcstruct.h" +#include "dixstruct.h" + +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvproto.h> +#include "xvdix.h" +#include "xvmodproc.h" + +#include "xf86xvpriv.h" + + +/* XvScreenRec fields */ + +static Bool xf86XVCloseScreen(int, ScreenPtr); +static int xf86XVQueryAdaptors(ScreenPtr, XvAdaptorPtr *, int *); + +/* XvAdaptorRec fields */ + +static int xf86XVAllocatePort(unsigned long, XvPortPtr, XvPortPtr*); +static int xf86XVFreePort(XvPortPtr); +static int xf86XVPutVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVPutStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVGetVideo(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVGetStill(ClientPtr, DrawablePtr,XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16); +static int xf86XVStopVideo(ClientPtr, XvPortPtr, DrawablePtr); +static int xf86XVSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); +static int xf86XVGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); +static int xf86XVQueryBestSize(ClientPtr, XvPortPtr, CARD8, + CARD16, CARD16,CARD16, CARD16, + unsigned int*, unsigned int*); +static int xf86XVPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, + INT16, INT16, CARD16, CARD16, + INT16, INT16, CARD16, CARD16, + XvImagePtr, unsigned char*, Bool, + CARD16, CARD16); +static int xf86XVQueryImageAttributes(ClientPtr, XvPortPtr, XvImagePtr, + CARD16*, CARD16*, int*, int*); + + +/* ScreenRec fields */ + +static Bool xf86XVDestroyWindow(WindowPtr pWin); +static void xf86XVWindowExposures(WindowPtr pWin, RegionPtr r1, RegionPtr r2); +static void xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind); +static void xf86XVClipNotify(WindowPtr pWin, int dx, int dy); + +#define PostValidateTreeUndefined ((PostValidateTreeProcPtr)-1) + +/* ScrnInfoRec functions */ + +static Bool xf86XVEnterVT(int, int); +static void xf86XVLeaveVT(int, int); +static void xf86XVAdjustFrame(int index, int x, int y, int flags); +static void xf86XVModeSet(ScrnInfoPtr pScrn); + +/* misc */ + +static Bool xf86XVInitAdaptors(ScreenPtr, XF86VideoAdaptorPtr*, int); + + +static DevPrivateKeyRec XF86XVWindowKeyRec; +#define XF86XVWindowKey (&XF86XVWindowKeyRec) + +DevPrivateKey XF86XvScreenKey; + +static unsigned long PortResource = 0; + +DevPrivateKey (*XvGetScreenKeyProc)(void) = NULL; +unsigned long (*XvGetRTPortProc)(void) = NULL; +int (*XvScreenInitProc)(ScreenPtr) = NULL; + +#define GET_XV_SCREEN(pScreen) \ + ((XvScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, XF86XvScreenKey)) + +#define GET_XF86XV_SCREEN(pScreen) \ + ((XF86XVScreenPtr)(GET_XV_SCREEN(pScreen)->devPriv.ptr)) + +#define GET_XF86XV_WINDOW(pWin) \ + ((XF86XVWindowPtr)dixLookupPrivate(&(pWin)->devPrivates, XF86XVWindowKey)) + +static xf86XVInitGenericAdaptorPtr *GenDrivers = NULL; +static int NumGenDrivers = 0; + +int +xf86XVRegisterGenericAdaptorDriver( + xf86XVInitGenericAdaptorPtr InitFunc +){ + xf86XVInitGenericAdaptorPtr *newdrivers; + + newdrivers = realloc(GenDrivers, sizeof(xf86XVInitGenericAdaptorPtr) * + (1 + NumGenDrivers)); + if (!newdrivers) + return 0; + GenDrivers = newdrivers; + + GenDrivers[NumGenDrivers++] = InitFunc; + + return 1; +} + +int +xf86XVListGenericAdaptors( + ScrnInfoPtr pScrn, + XF86VideoAdaptorPtr **adaptors +){ + int i,j,n,num; + XF86VideoAdaptorPtr *DrivAdap,*new; + + num = 0; + *adaptors = NULL; + /* + * The v4l driver registers itself first, but can use surfaces registered + * by other drivers. So, call the v4l driver last. + */ + for (i = NumGenDrivers; --i >= 0; ) { + DrivAdap = NULL; + n = (*GenDrivers[i])(pScrn, &DrivAdap); + if (0 == n) + continue; + new = realloc(*adaptors, sizeof(XF86VideoAdaptorPtr) * (num+n)); + if (NULL == new) + continue; + *adaptors = new; + for (j = 0; j < n; j++, num++) + (*adaptors)[num] = DrivAdap[j]; + } + return num; +} + + +/**************** Offscreen surface stuff *******************/ + +typedef struct { + XF86OffscreenImagePtr images; + int num; +} OffscreenImageRec; + +static DevPrivateKeyRec OffscreenPrivateKeyRec; +#define OffscreenPrivateKey (&OffscreenPrivateKeyRec) +#define GetOffscreenImage(pScreen) ((OffscreenImageRec *) dixLookupPrivate(&(pScreen)->devPrivates, OffscreenPrivateKey)) + +Bool +xf86XVRegisterOffscreenImages( + ScreenPtr pScreen, + XF86OffscreenImagePtr images, + int num +){ + OffscreenImageRec *OffscreenImage; + /* This function may be called before xf86XVScreenInit, so there's + * no better place than this to call dixRegisterPrivateKey to ensure we + * have space reserved. After the first call it is a no-op. */ + if(!dixRegisterPrivateKey(OffscreenPrivateKey, PRIVATE_SCREEN, sizeof(OffscreenImageRec)) || + !(OffscreenImage = GetOffscreenImage(pScreen))) + /* Every X.org driver assumes this function always succeeds, so + * just die on allocation failure. */ + FatalError("Could not allocate private storage for XV offscreen images.\n"); + + OffscreenImage->num = num; + OffscreenImage->images = images; + return TRUE; +} + +XF86OffscreenImagePtr +xf86XVQueryOffscreenImages( + ScreenPtr pScreen, + int *num +){ + OffscreenImageRec *OffscreenImage = GetOffscreenImage(pScreen); + *num = OffscreenImage->num; + return OffscreenImage->images; +} + + +XF86VideoAdaptorPtr +xf86XVAllocateVideoAdaptorRec(ScrnInfoPtr pScrn) +{ + return calloc(1, sizeof(XF86VideoAdaptorRec)); +} + +void +xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr) +{ + free(ptr); +} + + +Bool +xf86XVScreenInit( + ScreenPtr pScreen, + XF86VideoAdaptorPtr *adaptors, + int num +){ + ScrnInfoPtr pScrn; + XF86XVScreenPtr ScreenPriv; + XvScreenPtr pxvs; + + if(num <= 0 || + !XvGetScreenKeyProc || !XvGetRTPortProc || !XvScreenInitProc) + return FALSE; + + if(Success != (*XvScreenInitProc)(pScreen)) return FALSE; + + if (!dixRegisterPrivateKey(&XF86XVWindowKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + + XF86XvScreenKey = (*XvGetScreenKeyProc)(); + + PortResource = (*XvGetRTPortProc)(); + + pxvs = GET_XV_SCREEN(pScreen); + + /* Anyone initializing the Xv layer must provide these two. + The Xv di layer calls them without even checking if they exist! */ + + pxvs->ddCloseScreen = xf86XVCloseScreen; + pxvs->ddQueryAdaptors = xf86XVQueryAdaptors; + + /* The Xv di layer provides us with a private hook so that we don't + have to allocate our own screen private. They also provide + a CloseScreen hook so that we don't have to wrap it. I'm not + sure that I appreciate that. */ + + ScreenPriv = malloc(sizeof(XF86XVScreenRec)); + pxvs->devPriv.ptr = (pointer)ScreenPriv; + + if(!ScreenPriv) return FALSE; + + pScrn = xf86Screens[pScreen->myNum]; + + ScreenPriv->DestroyWindow = pScreen->DestroyWindow; + ScreenPriv->WindowExposures = pScreen->WindowExposures; + ScreenPriv->PostValidateTree = PostValidateTreeUndefined; + ScreenPriv->ClipNotify = pScreen->ClipNotify; + ScreenPriv->EnterVT = pScrn->EnterVT; + ScreenPriv->LeaveVT = pScrn->LeaveVT; + ScreenPriv->AdjustFrame = pScrn->AdjustFrame; + ScreenPriv->ModeSet = pScrn->ModeSet; + + pScreen->DestroyWindow = xf86XVDestroyWindow; + pScreen->WindowExposures = xf86XVWindowExposures; + pScreen->ClipNotify = xf86XVClipNotify; + pScrn->EnterVT = xf86XVEnterVT; + pScrn->LeaveVT = xf86XVLeaveVT; + if(pScrn->AdjustFrame) + pScrn->AdjustFrame = xf86XVAdjustFrame; + pScrn->ModeSet = xf86XVModeSet; + + if(!xf86XVInitAdaptors(pScreen, adaptors, num)) + return FALSE; + + return TRUE; +} + +static void +xf86XVFreeAdaptor(XvAdaptorPtr pAdaptor) +{ + int i; + + free(pAdaptor->name); + pAdaptor->name = NULL; + + if(pAdaptor->pEncodings) { + XvEncodingPtr pEncode = pAdaptor->pEncodings; + + for(i = 0; i < pAdaptor->nEncodings; i++, pEncode++) + free(pEncode->name); + free(pAdaptor->pEncodings); + pAdaptor->pEncodings = NULL; + } + + free(pAdaptor->pFormats); + pAdaptor->pFormats = NULL; + + if(pAdaptor->pPorts) { + XvPortPtr pPort = pAdaptor->pPorts; + XvPortRecPrivatePtr pPriv; + + for(i = 0; i < pAdaptor->nPorts; i++, pPort++) { + pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + if(pPriv) { + if(pPriv->clientClip) + RegionDestroy(pPriv->clientClip); + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + RegionDestroy(pPriv->pCompositeClip); + if (pPriv->ckeyFilled) + RegionDestroy(pPriv->ckeyFilled); + free(pPriv); + } + } + free(pAdaptor->pPorts); + pAdaptor->pPorts = NULL; + } + + if(pAdaptor->pAttributes) { + XvAttributePtr pAttribute = pAdaptor->pAttributes; + + for(i = 0; i < pAdaptor->nAttributes; i++, pAttribute++) + free(pAttribute->name); + free(pAdaptor->pAttributes); + pAdaptor->pAttributes = NULL; + } + + free(pAdaptor->pImages); + free(pAdaptor->devPriv.ptr); + pAdaptor->pImages = NULL; + pAdaptor->devPriv.ptr = NULL; +} + +static Bool +xf86XVInitAdaptors( + ScreenPtr pScreen, + XF86VideoAdaptorPtr *infoPtr, + int number +) { + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr adaptorPtr; + XvAdaptorPtr pAdaptor, pa; + XvAdaptorRecPrivatePtr adaptorPriv; + int na, numAdaptor; + XvPortRecPrivatePtr portPriv; + XvPortPtr pPort, pp; + int numPort; + XF86AttributePtr attributePtr; + XvAttributePtr pAttribute, pat; + XF86VideoFormatPtr formatPtr; + XvFormatPtr pFormat, pf; + int numFormat, totFormat; + XF86VideoEncodingPtr encodingPtr; + XvEncodingPtr pEncode, pe; + XF86ImagePtr imagePtr; + XvImagePtr pImage, pi; + int numVisuals; + VisualPtr pVisual; + int i; + + pxvs->nAdaptors = 0; + pxvs->pAdaptors = NULL; + + if(!(pAdaptor = calloc(number, sizeof(XvAdaptorRec)))) + return FALSE; + + for(pa = pAdaptor, na = 0, numAdaptor = 0; na < number; na++, adaptorPtr++) { + adaptorPtr = infoPtr[na]; + + if(!adaptorPtr->StopVideo || !adaptorPtr->SetPortAttribute || + !adaptorPtr->GetPortAttribute || !adaptorPtr->QueryBestSize) + continue; + + /* client libs expect at least one encoding */ + if(!adaptorPtr->nEncodings || !adaptorPtr->pEncodings) + continue; + + pa->type = adaptorPtr->type; + + if(!adaptorPtr->PutVideo && !adaptorPtr->GetVideo) + pa->type &= ~XvVideoMask; + + if(!adaptorPtr->PutStill && !adaptorPtr->GetStill) + pa->type &= ~XvStillMask; + + if(!adaptorPtr->PutImage || !adaptorPtr->QueryImageAttributes) + pa->type &= ~XvImageMask; + + if(!adaptorPtr->PutVideo && !adaptorPtr->PutImage && + !adaptorPtr->PutStill) + pa->type &= ~XvInputMask; + + if(!adaptorPtr->GetVideo && !adaptorPtr->GetStill) + pa->type &= ~XvOutputMask; + + if(!(adaptorPtr->type & (XvPixmapMask | XvWindowMask))) + continue; + if(!(adaptorPtr->type & (XvImageMask | XvVideoMask | XvStillMask))) + continue; + + pa->pScreen = pScreen; + pa->ddAllocatePort = xf86XVAllocatePort; + pa->ddFreePort = xf86XVFreePort; + pa->ddPutVideo = xf86XVPutVideo; + pa->ddPutStill = xf86XVPutStill; + pa->ddGetVideo = xf86XVGetVideo; + pa->ddGetStill = xf86XVGetStill; + pa->ddStopVideo = xf86XVStopVideo; + pa->ddPutImage = xf86XVPutImage; + pa->ddSetPortAttribute = xf86XVSetPortAttribute; + pa->ddGetPortAttribute = xf86XVGetPortAttribute; + pa->ddQueryBestSize = xf86XVQueryBestSize; + pa->ddQueryImageAttributes = xf86XVQueryImageAttributes; + pa->name = strdup(adaptorPtr->name); + + if(adaptorPtr->nEncodings && + (pEncode = calloc(adaptorPtr->nEncodings, sizeof(XvEncodingRec)))) { + + for(pe = pEncode, encodingPtr = adaptorPtr->pEncodings, i = 0; + i < adaptorPtr->nEncodings; pe++, i++, encodingPtr++) + { + pe->id = encodingPtr->id; + pe->pScreen = pScreen; + pe->name = strdup(encodingPtr->name); + pe->width = encodingPtr->width; + pe->height = encodingPtr->height; + pe->rate.numerator = encodingPtr->rate.numerator; + pe->rate.denominator = encodingPtr->rate.denominator; + } + pa->nEncodings = adaptorPtr->nEncodings; + pa->pEncodings = pEncode; + } + + if(adaptorPtr->nImages && + (pImage = calloc(adaptorPtr->nImages, sizeof(XvImageRec)))) { + + for(i = 0, pi = pImage, imagePtr = adaptorPtr->pImages; + i < adaptorPtr->nImages; i++, pi++, imagePtr++) + { + pi->id = imagePtr->id; + pi->type = imagePtr->type; + pi->byte_order = imagePtr->byte_order; + memcpy(pi->guid, imagePtr->guid, 16); + pi->bits_per_pixel = imagePtr->bits_per_pixel; + pi->format = imagePtr->format; + pi->num_planes = imagePtr->num_planes; + pi->depth = imagePtr->depth; + pi->red_mask = imagePtr->red_mask; + pi->green_mask = imagePtr->green_mask; + pi->blue_mask = imagePtr->blue_mask; + pi->y_sample_bits = imagePtr->y_sample_bits; + pi->u_sample_bits = imagePtr->u_sample_bits; + pi->v_sample_bits = imagePtr->v_sample_bits; + pi->horz_y_period = imagePtr->horz_y_period; + pi->horz_u_period = imagePtr->horz_u_period; + pi->horz_v_period = imagePtr->horz_v_period; + pi->vert_y_period = imagePtr->vert_y_period; + pi->vert_u_period = imagePtr->vert_u_period; + pi->vert_v_period = imagePtr->vert_v_period; + memcpy(pi->component_order, imagePtr->component_order, 32); + pi->scanline_order = imagePtr->scanline_order; + } + pa->nImages = adaptorPtr->nImages; + pa->pImages = pImage; + } + + if(adaptorPtr->nAttributes && + (pAttribute = calloc(adaptorPtr->nAttributes, sizeof(XvAttributeRec)))) + { + for(pat = pAttribute, attributePtr = adaptorPtr->pAttributes, i = 0; + i < adaptorPtr->nAttributes; pat++, i++, attributePtr++) + { + pat->flags = attributePtr->flags; + pat->min_value = attributePtr->min_value; + pat->max_value = attributePtr->max_value; + pat->name = strdup(attributePtr->name); + } + pa->nAttributes = adaptorPtr->nAttributes; + pa->pAttributes = pAttribute; + } + + + totFormat = adaptorPtr->nFormats; + + if(!(pFormat = calloc(totFormat, sizeof(XvFormatRec)))) { + xf86XVFreeAdaptor(pa); + continue; + } + for(pf = pFormat, i = 0, numFormat = 0, formatPtr = adaptorPtr->pFormats; + i < adaptorPtr->nFormats; i++, formatPtr++) + { + numVisuals = pScreen->numVisuals; + pVisual = pScreen->visuals; + + while(numVisuals--) { + if((pVisual->class == formatPtr->class) && + (pVisual->nplanes == formatPtr->depth)) { + + if(numFormat >= totFormat) { + void *moreSpace; + totFormat *= 2; + moreSpace = realloc(pFormat, + totFormat * sizeof(XvFormatRec)); + if(!moreSpace) break; + pFormat = moreSpace; + pf = pFormat + numFormat; + } + + pf->visual = pVisual->vid; + pf->depth = formatPtr->depth; + + pf++; + numFormat++; + } + pVisual++; + } + } + pa->nFormats = numFormat; + pa->pFormats = pFormat; + if(!numFormat) { + xf86XVFreeAdaptor(pa); + continue; + } + + if(!(adaptorPriv = calloc(1, sizeof(XvAdaptorRecPrivate)))) { + xf86XVFreeAdaptor(pa); + continue; + } + + adaptorPriv->flags = adaptorPtr->flags; + adaptorPriv->PutVideo = adaptorPtr->PutVideo; + adaptorPriv->PutStill = adaptorPtr->PutStill; + adaptorPriv->GetVideo = adaptorPtr->GetVideo; + adaptorPriv->GetStill = adaptorPtr->GetStill; + adaptorPriv->StopVideo = adaptorPtr->StopVideo; + adaptorPriv->SetPortAttribute = adaptorPtr->SetPortAttribute; + adaptorPriv->GetPortAttribute = adaptorPtr->GetPortAttribute; + adaptorPriv->QueryBestSize = adaptorPtr->QueryBestSize; + adaptorPriv->QueryImageAttributes = adaptorPtr->QueryImageAttributes; + adaptorPriv->PutImage = adaptorPtr->PutImage; + adaptorPriv->ReputImage = adaptorPtr->ReputImage; /* image/still */ + + pa->devPriv.ptr = (pointer)adaptorPriv; + + if(!(pPort = calloc(adaptorPtr->nPorts, sizeof(XvPortRec)))) { + xf86XVFreeAdaptor(pa); + continue; + } + for(pp = pPort, i = 0, numPort = 0; + i < adaptorPtr->nPorts; i++) { + + if(!(pp->id = FakeClientID(0))) + continue; + + if(!(portPriv = calloc(1, sizeof(XvPortRecPrivate)))) + continue; + + if(!AddResource(pp->id, PortResource, pp)) { + free(portPriv); + continue; + } + + pp->pAdaptor = pa; + pp->pNotify = (XvPortNotifyPtr)NULL; + pp->pDraw = (DrawablePtr)NULL; + pp->client = (ClientPtr)NULL; + pp->grab.client = (ClientPtr)NULL; + pp->time = currentTime; + pp->devPriv.ptr = portPriv; + + portPriv->pScrn = pScrn; + portPriv->AdaptorRec = adaptorPriv; + portPriv->DevPriv.ptr = adaptorPtr->pPortPrivates[i].ptr; + + pp++; + numPort++; + } + pa->nPorts = numPort; + pa->pPorts = pPort; + if(!numPort) { + xf86XVFreeAdaptor(pa); + continue; + } + + pa->base_id = pPort->id; + + pa++; + numAdaptor++; + } + + if(numAdaptor) { + pxvs->nAdaptors = numAdaptor; + pxvs->pAdaptors = pAdaptor; + } else { + free(pAdaptor); + return FALSE; + } + + return TRUE; +} + +/* Video should be clipped to the intersection of the window cliplist + and the client cliplist specified in the GC for which the video was + initialized. When we need to reclip a window, the GC that started + the video may not even be around anymore. That's why we save the + client clip from the GC when the video is initialized. We then + use xf86XVUpdateCompositeClip to calculate the new composite clip + when we need it. This is different from what DEC did. They saved + the GC and used it's clip list when they needed to reclip the window, + even if the client clip was different from the one the video was + initialized with. If the original GC was destroyed, they had to stop + the video. I like the new method better (MArk). + + This function only works for windows. Will need to rewrite when + (if) we support pixmap rendering. +*/ + +static void +xf86XVUpdateCompositeClip(XvPortRecPrivatePtr portPriv) +{ + RegionPtr pregWin, pCompositeClip; + WindowPtr pWin; + Bool freeCompClip = FALSE; + + if(portPriv->pCompositeClip) + return; + + pWin = (WindowPtr)portPriv->pDraw; + + /* get window clip list */ + if(portPriv->subWindowMode == IncludeInferiors) { + pregWin = NotClippedByChildren(pWin); + freeCompClip = TRUE; + } else + pregWin = &pWin->clipList; + + if(!portPriv->clientClip) { + portPriv->pCompositeClip = pregWin; + portPriv->FreeCompositeClip = freeCompClip; + return; + } + + pCompositeClip = RegionCreate(NullBox, 1); + RegionCopy(pCompositeClip, portPriv->clientClip); + RegionTranslate(pCompositeClip, + portPriv->pDraw->x, portPriv->pDraw->y); + RegionIntersect(pCompositeClip, pregWin, pCompositeClip); + + portPriv->pCompositeClip = pCompositeClip; + portPriv->FreeCompositeClip = TRUE; + + if(freeCompClip) { + RegionDestroy(pregWin); + } +} + +/* Save the current clientClip and update the CompositeClip whenever + we have a fresh GC */ + +static void +xf86XVCopyClip( + XvPortRecPrivatePtr portPriv, + GCPtr pGC +){ + /* copy the new clip if it exists */ + if((pGC->clientClipType == CT_REGION) && pGC->clientClip) { + if(!portPriv->clientClip) + portPriv->clientClip = RegionCreate(NullBox, 1); + /* Note: this is in window coordinates */ + RegionCopy(portPriv->clientClip, pGC->clientClip); + RegionTranslate(portPriv->clientClip, + pGC->clipOrg.x, pGC->clipOrg.y); + } else if(portPriv->clientClip) { /* free the old clientClip */ + RegionDestroy(portPriv->clientClip); + portPriv->clientClip = NULL; + } + + /* get rid of the old clip list */ + if(portPriv->pCompositeClip && portPriv->FreeCompositeClip) { + RegionDestroy(portPriv->pCompositeClip); + } + + portPriv->pCompositeClip = pGC->pCompositeClip; + portPriv->FreeCompositeClip = FALSE; + portPriv->subWindowMode = pGC->subWindowMode; +} + +static void +xf86XVCopyCompositeClip(XvPortRecPrivatePtr portPriv, + GCPtr pGC, + DrawablePtr pDraw) +{ + if (!portPriv->clientClip) + portPriv->clientClip = RegionCreate(NullBox, 1); + /* Keep the original GC composite clip around for ReputImage */ + RegionCopy(portPriv->clientClip, pGC->pCompositeClip); + RegionTranslate(portPriv->clientClip, + -pDraw->x, -pDraw->y); + + /* get rid of the old clip list */ + if (portPriv->pCompositeClip && portPriv->FreeCompositeClip) + RegionDestroy(portPriv->pCompositeClip); + + portPriv->pCompositeClip = pGC->pCompositeClip; + portPriv->FreeCompositeClip = FALSE; + portPriv->subWindowMode = pGC->subWindowMode; +} + +static int +xf86XVRegetVideo(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + xf86XVUpdateCompositeClip(portPriv); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* that's all if it's totally obscured */ + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->GetVideo)(portPriv->pScrn, + portPriv->vid_x, portPriv->vid_y, + WinBox.x1, WinBox.y1, + portPriv->vid_w, portPriv->vid_h, + portPriv->drw_w, portPriv->drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + if(ret == Success) + portPriv->isOn = XV_ON; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && portPriv->isOn == XV_ON) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + + +static int +xf86XVReputVideo(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + xf86XVUpdateCompositeClip(portPriv); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* clip and translate to the viewport */ + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + RegionInit(&VPReg, &VPBox, 1); + RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); + RegionUninit(&VPReg); + } + + /* that's all if it's totally obscured */ + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + /* bailout if we have to clip but the hardware doesn't support it */ + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = RegionRects(&ClipRegion); + if( (RegionNumRects(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutVideo)(portPriv->pScrn, + portPriv->vid_x, portPriv->vid_y, + WinBox.x1, WinBox.y1, + portPriv->vid_w, portPriv->vid_h, + portPriv->drw_w, portPriv->drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + if(ret == Success) portPriv->isOn = XV_ON; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + +/* Reput image/still */ +static int +xf86XVReputImage(XvPortRecPrivatePtr portPriv) +{ + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + xf86XVUpdateCompositeClip(portPriv); + + /* the clip can get smaller over time */ + RegionCopy(portPriv->clientClip, portPriv->pCompositeClip); + RegionTranslate(portPriv->clientClip, + -portPriv->pDraw->x, -portPriv->pDraw->y); + + /* translate the video region to the screen */ + WinBox.x1 = portPriv->pDraw->x + portPriv->drw_x; + WinBox.y1 = portPriv->pDraw->y + portPriv->drw_y; + WinBox.x2 = WinBox.x1 + portPriv->drw_w; + WinBox.y2 = WinBox.y1 + portPriv->drw_h; + + /* clip to the window composite clip */ + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, portPriv->pCompositeClip); + + /* clip and translate to the viewport */ + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + RegionInit(&VPReg, &VPBox, 1); + RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); + RegionUninit(&VPReg); + } + + /* that's all if it's totally obscured */ + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + + /* bailout if we have to clip but the hardware doesn't support it */ + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = RegionRects(&ClipRegion); + if( (RegionNumRects(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto CLIP_VIDEO_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->ReputImage)(portPriv->pScrn, + portPriv->vid_x, portPriv->vid_y, + WinBox.x1, WinBox.y1, + portPriv->vid_w, portPriv->vid_h, + portPriv->drw_w, portPriv->drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + portPriv->pDraw); + + portPriv->isOn = (ret == Success) ? XV_ON : XV_OFF; + +CLIP_VIDEO_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + + +static int +xf86XVReputAllVideo(WindowPtr pWin, pointer data) +{ + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + + while(WinPriv) { + if(WinPriv->PortRec->type == XvInputMask) + xf86XVReputVideo(WinPriv->PortRec); + else + xf86XVRegetVideo(WinPriv->PortRec); + WinPriv = WinPriv->next; + } + + return WT_WALKCHILDREN; +} + +static int +xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) +{ + XF86XVWindowPtr winPriv, PrivRoot; + + winPriv = PrivRoot = GET_XF86XV_WINDOW(pWin); + + /* Enlist our port in the window private */ + while(winPriv) { + if(winPriv->PortRec == portPriv) /* we're already listed */ + break; + winPriv = winPriv->next; + } + + if(!winPriv) { + winPriv = calloc(1, sizeof(XF86XVWindowRec)); + if(!winPriv) return BadAlloc; + winPriv->PortRec = portPriv; + winPriv->next = PrivRoot; + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, winPriv); + } + + portPriv->pDraw = (DrawablePtr)pWin; + + return Success; +} + + +static void +xf86XVRemovePortFromWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv) +{ + XF86XVWindowPtr winPriv, prevPriv = NULL; + winPriv = GET_XF86XV_WINDOW(pWin); + + while(winPriv) { + if(winPriv->PortRec == portPriv) { + if(prevPriv) + prevPriv->next = winPriv->next; + else + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, + winPriv->next); + free(winPriv); + break; + } + prevPriv = winPriv; + winPriv = winPriv->next; + } + portPriv->pDraw = NULL; + if (portPriv->ckeyFilled) { + RegionDestroy(portPriv->ckeyFilled); + portPriv->ckeyFilled = NULL; + } + portPriv->clipChanged = FALSE; +} + +static void +xf86XVReputOrStopPort(XvPortRecPrivatePtr pPriv, + WindowPtr pWin, + Bool visible) +{ + if (!visible) { + if (pPriv->isOn == XV_ON) { + (*pPriv->AdaptorRec->StopVideo)(pPriv->pScrn, pPriv->DevPriv.ptr, FALSE); + pPriv->isOn = XV_PENDING; + } + + if (!pPriv->type) /* overlaid still/image*/ + xf86XVRemovePortFromWindow(pWin, pPriv); + + return; + } + + switch (pPriv->type) { + case XvInputMask: + xf86XVReputVideo(pPriv); + break; + case XvOutputMask: + xf86XVRegetVideo(pPriv); + break; + default: /* overlaid still/image*/ + if (pPriv->AdaptorRec->ReputImage) + xf86XVReputImage(pPriv); + break; + } +} + +static void +xf86XVReputOrStopAllPorts(ScrnInfoPtr pScrn, Bool onlyChanged) +{ + ScreenPtr pScreen = pScrn->pScreen; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XvAdaptorPtr pa; + int c, i; + + for (c = pxvs->nAdaptors, pa = pxvs->pAdaptors; c > 0; c--, pa++) { + XvPortPtr pPort = pa->pPorts; + + for (i = pa->nPorts; i > 0; i--, pPort++) { + XvPortRecPrivatePtr pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + WindowPtr pWin = (WindowPtr)pPriv->pDraw; + Bool visible; + + if (pPriv->isOn == XV_OFF || !pWin) + continue; + + if (onlyChanged && !pPriv->clipChanged) + continue; + + visible = pWin->visibility == VisibilityUnobscured || + pWin->visibility == VisibilityPartiallyObscured; + + /* + * Stop and remove still/images if + * ReputImage isn't supported. + */ + if (!pPriv->type && !pPriv->AdaptorRec->ReputImage) + visible = FALSE; + + xf86XVReputOrStopPort(pPriv, pWin, visible); + + pPriv->clipChanged = FALSE; + } + } +} + +/**** ScreenRec fields ****/ + +static Bool +xf86XVDestroyWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr tmp, WinPriv = GET_XF86XV_WINDOW(pWin); + int ret; + + while(WinPriv) { + XvPortRecPrivatePtr pPriv = WinPriv->PortRec; + + if(pPriv->isOn > XV_OFF) { + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); + pPriv->isOn = XV_OFF; + } + + pPriv->pDraw = NULL; + tmp = WinPriv; + WinPriv = WinPriv->next; + free(tmp); + } + + dixSetPrivate(&pWin->devPrivates, XF86XVWindowKey, NULL); + + pScreen->DestroyWindow = ScreenPriv->DestroyWindow; + ret = (*pScreen->DestroyWindow)(pWin); + pScreen->DestroyWindow = xf86XVDestroyWindow; + + return ret; +} + +static void +xf86XVPostValidateTree(WindowPtr pWin, WindowPtr pLayerWin, VTKind kind) +{ + ScreenPtr pScreen; + XF86XVScreenPtr ScreenPriv; + ScrnInfoPtr pScrn; + + if (pWin) + pScreen = pWin->drawable.pScreen; + else + pScreen = pLayerWin->drawable.pScreen; + + ScreenPriv = GET_XF86XV_SCREEN(pScreen); + pScrn = xf86Screens[pScreen->myNum]; + + xf86XVReputOrStopAllPorts(pScrn, TRUE); + + pScreen->PostValidateTree = ScreenPriv->PostValidateTree; + if (pScreen->PostValidateTree) { + (*pScreen->PostValidateTree)(pWin, pLayerWin, kind); + } + ScreenPriv->PostValidateTree = PostValidateTreeUndefined; +} + +static void +xf86XVWindowExposures(WindowPtr pWin, RegionPtr reg1, RegionPtr reg2) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + XvPortRecPrivatePtr pPriv; + Bool AreasExposed; + + AreasExposed = (WinPriv && reg1 && RegionNotEmpty(reg1)); + + pScreen->WindowExposures = ScreenPriv->WindowExposures; + (*pScreen->WindowExposures)(pWin, reg1, reg2); + pScreen->WindowExposures = xf86XVWindowExposures; + + /* filter out XClearWindow/Area */ + if (!pWin->valdata) return; + + while(WinPriv) { + Bool visible = TRUE; + + pPriv = WinPriv->PortRec; + + /* + * Stop and remove still/images if areas were exposed and + * ReputImage isn't supported. + */ + if (!pPriv->type && !pPriv->AdaptorRec->ReputImage) + visible = !AreasExposed; + + /* + * Subtract exposed areas from overlaid image to match textured video + * behavior. + */ + if (!pPriv->type && pPriv->clientClip) + RegionSubtract(pPriv->clientClip, pPriv->clientClip, reg1); + + if (visible && pPriv->ckeyFilled) { + RegionRec tmp; + RegionNull(&tmp); + RegionCopy(&tmp, reg1); + RegionTranslate(&tmp, pWin->drawable.x, pWin->drawable.y); + RegionSubtract(pPriv->ckeyFilled, pPriv->ckeyFilled, &tmp); + } + + WinPriv = WinPriv->next; + xf86XVReputOrStopPort(pPriv, pWin, visible); + + pPriv->clipChanged = FALSE; + } +} + +static void +xf86XVClipNotify(WindowPtr pWin, int dx, int dy) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + XvPortRecPrivatePtr pPriv; + + while(WinPriv) { + pPriv = WinPriv->PortRec; + + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + RegionDestroy(pPriv->pCompositeClip); + + pPriv->pCompositeClip = NULL; + + if (pPriv->AdaptorRec->ClipNotify) + (*pPriv->AdaptorRec->ClipNotify)(pPriv->pScrn, pPriv->DevPriv.ptr, + pWin, dx, dy); + + pPriv->clipChanged = TRUE; + + if (ScreenPriv->PostValidateTree == PostValidateTreeUndefined) { + ScreenPriv->PostValidateTree = pScreen->PostValidateTree; + pScreen->PostValidateTree = xf86XVPostValidateTree; + } + + WinPriv = WinPriv->next; + } + + if(ScreenPriv->ClipNotify) { + pScreen->ClipNotify = ScreenPriv->ClipNotify; + (*pScreen->ClipNotify)(pWin, dx, dy); + pScreen->ClipNotify = xf86XVClipNotify; + } +} + + + +/**** Required XvScreenRec fields ****/ + +static Bool +xf86XVCloseScreen(int i, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XvAdaptorPtr pa; + int c; + + if(!ScreenPriv) return TRUE; + + pScreen->DestroyWindow = ScreenPriv->DestroyWindow; + pScreen->WindowExposures = ScreenPriv->WindowExposures; + pScreen->ClipNotify = ScreenPriv->ClipNotify; + + pScrn->EnterVT = ScreenPriv->EnterVT; + pScrn->LeaveVT = ScreenPriv->LeaveVT; + pScrn->AdjustFrame = ScreenPriv->AdjustFrame; + pScrn->ModeSet = ScreenPriv->ModeSet; + + for(c = 0, pa = pxvs->pAdaptors; c < pxvs->nAdaptors; c++, pa++) { + xf86XVFreeAdaptor(pa); + } + + free(pxvs->pAdaptors); + free(ScreenPriv); + return TRUE; +} + + +static int +xf86XVQueryAdaptors( + ScreenPtr pScreen, + XvAdaptorPtr *p_pAdaptors, + int *p_nAdaptors +){ + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + + *p_nAdaptors = pxvs->nAdaptors; + *p_pAdaptors = pxvs->pAdaptors; + + return Success; +} + + +/**** ScrnInfoRec fields ****/ + +static Bool +xf86XVEnterVT(int index, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = screenInfo.screens[index]; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + Bool ret; + + pScrn->EnterVT = ScreenPriv->EnterVT; + ret = (*ScreenPriv->EnterVT)(index, flags); + ScreenPriv->EnterVT = pScrn->EnterVT; + pScrn->EnterVT = xf86XVEnterVT; + + if(ret) WalkTree(pScreen, xf86XVReputAllVideo, 0); + + return ret; +} + +static void +xf86XVLeaveVT(int index, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = screenInfo.screens[index]; + XvScreenPtr pxvs = GET_XV_SCREEN(pScreen); + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + XvAdaptorPtr pAdaptor; + XvPortPtr pPort; + XvPortRecPrivatePtr pPriv; + int i, j; + + for(i = 0; i < pxvs->nAdaptors; i++) { + pAdaptor = &pxvs->pAdaptors[i]; + for(j = 0; j < pAdaptor->nPorts; j++) { + pPort = &pAdaptor->pPorts[j]; + pPriv = (XvPortRecPrivatePtr)pPort->devPriv.ptr; + if(pPriv->isOn > XV_OFF) { + + (*pPriv->AdaptorRec->StopVideo)( + pPriv->pScrn, pPriv->DevPriv.ptr, TRUE); + pPriv->isOn = XV_OFF; + + if(pPriv->pCompositeClip && pPriv->FreeCompositeClip) + RegionDestroy(pPriv->pCompositeClip); + + pPriv->pCompositeClip = NULL; + + if(!pPriv->type && pPriv->pDraw) { /* still */ + xf86XVRemovePortFromWindow((WindowPtr)pPriv->pDraw, pPriv); + } + } + } + } + + pScrn->LeaveVT = ScreenPriv->LeaveVT; + (*ScreenPriv->LeaveVT)(index, flags); + ScreenPriv->LeaveVT = pScrn->LeaveVT; + pScrn->LeaveVT = xf86XVLeaveVT; +} + +static void +xf86XVAdjustFrame(int index, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + ScreenPtr pScreen = pScrn->pScreen; + XF86XVScreenPtr ScreenPriv = GET_XF86XV_SCREEN(pScreen); + + if(ScreenPriv->AdjustFrame) { + pScrn->AdjustFrame = ScreenPriv->AdjustFrame; + (*pScrn->AdjustFrame)(index, x, y, flags); + pScrn->AdjustFrame = xf86XVAdjustFrame; + } + + xf86XVReputOrStopAllPorts(pScrn, FALSE); +} + +static void +xf86XVModeSet(ScrnInfoPtr pScrn) +{ + ScreenPtr pScreen = pScrn->pScreen; + XF86XVScreenPtr ScreenPriv; + + /* Can be called before pScrn->pScreen is set */ + if (!pScreen) + return; + + ScreenPriv = GET_XF86XV_SCREEN(pScreen); + + if (ScreenPriv->ModeSet) { + pScrn->ModeSet = ScreenPriv->ModeSet; + (*pScrn->ModeSet)(pScrn); + pScrn->ModeSet = xf86XVModeSet; + } + + xf86XVReputOrStopAllPorts(pScrn, FALSE); +} + +/**** XvAdaptorRec fields ****/ + +static int +xf86XVAllocatePort( + unsigned long port, + XvPortPtr pPort, + XvPortPtr *ppPort +){ + *ppPort = pPort; + return Success; +} + + + +static int +xf86XVFreePort(XvPortPtr pPort) +{ + return Success; +} + + +static int +xf86XVPutVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + int result; + + /* No dumping video to pixmaps... For now anyhow */ + if(pDraw->type != DRAWABLE_WINDOW) { + pPort->pDraw = (DrawablePtr)NULL; + return BadAlloc; + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(result != Success) return result; + + portPriv->type = XvInputMask; + + /* save a copy of these parameters */ + portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; + portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + + /* make sure we have the most recent copy of the clientClip */ + xf86XVCopyClip(portPriv, pGC); + + /* To indicate to the DI layer that we were successful */ + pPort->pDraw = pDraw; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + return(xf86XVReputVideo(portPriv)); +} + +static int +xf86XVPutStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + xf86XVCopyCompositeClip(portPriv, pGC, pDraw); + + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + RegionInit(&VPReg, &VPBox, 1); + RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); + RegionUninit(&VPReg); + } + + if(portPriv->pDraw) { + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + } + + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto PUT_STILL_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = RegionRects(&ClipRegion); + if( (RegionNumRects(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto PUT_STILL_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutStill)(portPriv->pScrn, + vid_x, vid_y, WinBox.x1, WinBox.y1, + vid_w, vid_h, drw_w, drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + + if((ret == Success) && + (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_STILLS)) { + + xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + portPriv->isOn = XV_ON; + portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; + portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + portPriv->type = 0; /* no mask means it's transient and should + not be reput once it's removed */ + pPort->pDraw = pDraw; /* make sure we can get stop requests */ + } + +PUT_STILL_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + +static int +xf86XVGetVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + int result; + + /* No pixmaps... For now anyhow */ + if(pDraw->type != DRAWABLE_WINDOW) { + pPort->pDraw = (DrawablePtr)NULL; + return BadAlloc; + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + result = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(result != Success) return result; + + portPriv->type = XvOutputMask; + + /* save a copy of these parameters */ + portPriv->vid_x = vid_x; portPriv->vid_y = vid_y; + portPriv->vid_w = vid_w; portPriv->vid_h = vid_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + + /* make sure we have the most recent copy of the clientClip */ + xf86XVCopyClip(portPriv, pGC); + + /* To indicate to the DI layer that we were successful */ + pPort->pDraw = pDraw; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + return(xf86XVRegetVideo(portPriv)); +} + +static int +xf86XVGetStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->pDraw) { + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + } + + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto GET_STILL_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->GetStill)(portPriv->pScrn, + vid_x, vid_y, WinBox.x1, WinBox.y1, + vid_w, vid_h, drw_w, drw_h, + &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + +GET_STILL_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + + + +static int +xf86XVStopVideo( + ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDraw +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + if(pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + xf86XVRemovePortFromWindow((WindowPtr)pDraw, portPriv); + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + /* Must free resources. */ + + if(portPriv->isOn > XV_OFF) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, TRUE); + portPriv->isOn = XV_OFF; + } + + return Success; +} + +static int +xf86XVSetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 value +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return((*portPriv->AdaptorRec->SetPortAttribute)(portPriv->pScrn, + attribute, value, portPriv->DevPriv.ptr)); +} + + +static int +xf86XVGetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 *p_value +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return((*portPriv->AdaptorRec->GetPortAttribute)(portPriv->pScrn, + attribute, p_value, portPriv->DevPriv.ptr)); +} + + + +static int +xf86XVQueryBestSize( + ClientPtr client, + XvPortPtr pPort, + CARD8 motion, + CARD16 vid_w, CARD16 vid_h, + CARD16 drw_w, CARD16 drw_h, + unsigned int *p_w, unsigned int *p_h +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + (*portPriv->AdaptorRec->QueryBestSize)(portPriv->pScrn, + (Bool)motion, vid_w, vid_h, drw_w, drw_h, + p_w, p_h, portPriv->DevPriv.ptr); + + return Success; +} + + +static int +xf86XVPutImage( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 src_x, INT16 src_y, + CARD16 src_w, CARD16 src_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h, + XvImagePtr format, + unsigned char* data, + Bool sync, + CARD16 width, CARD16 height +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + RegionRec WinRegion; + RegionRec ClipRegion; + BoxRec WinBox; + int ret = Success; + Bool clippedAway = FALSE; + + if (pDraw->type != DRAWABLE_WINDOW) + return BadAlloc; + + if(!portPriv->pScrn->vtSema) return Success; /* Success ? */ + + xf86XVCopyCompositeClip(portPriv, pGC, pDraw); + + WinBox.x1 = pDraw->x + drw_x; + WinBox.y1 = pDraw->y + drw_y; + WinBox.x2 = WinBox.x1 + drw_w; + WinBox.y2 = WinBox.y1 + drw_h; + + RegionInit(&WinRegion, &WinBox, 1); + RegionNull(&ClipRegion); + RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); + + if(portPriv->AdaptorRec->flags & VIDEO_CLIP_TO_VIEWPORT) { + RegionRec VPReg; + BoxRec VPBox; + + VPBox.x1 = portPriv->pScrn->frameX0; + VPBox.y1 = portPriv->pScrn->frameY0; + VPBox.x2 = portPriv->pScrn->frameX1 + 1; + VPBox.y2 = portPriv->pScrn->frameY1 + 1; + + RegionInit(&VPReg, &VPBox, 1); + RegionIntersect(&ClipRegion, &ClipRegion, &VPReg); + RegionUninit(&VPReg); + } + + /* If we are changing windows, unregister our port in the old window */ + if(portPriv->pDraw && (portPriv->pDraw != pDraw)) + xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv); + + /* Register our port with the new window */ + ret = xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv); + if(ret != Success) goto PUT_IMAGE_BAILOUT; + + if(!RegionNotEmpty(&ClipRegion)) { + clippedAway = TRUE; + goto PUT_IMAGE_BAILOUT; + } + + if(portPriv->AdaptorRec->flags & VIDEO_NO_CLIPPING) { + BoxPtr clipBox = RegionRects(&ClipRegion); + if( (RegionNumRects(&ClipRegion) != 1) || + (clipBox->x1 != WinBox.x1) || (clipBox->x2 != WinBox.x2) || + (clipBox->y1 != WinBox.y1) || (clipBox->y2 != WinBox.y2)) + { + clippedAway = TRUE; + goto PUT_IMAGE_BAILOUT; + } + } + + if(portPriv->AdaptorRec->flags & VIDEO_INVERT_CLIPLIST) { + RegionSubtract(&ClipRegion, &WinRegion, &ClipRegion); + } + + ret = (*portPriv->AdaptorRec->PutImage)(portPriv->pScrn, + src_x, src_y, WinBox.x1, WinBox.y1, + src_w, src_h, drw_w, drw_h, format->id, data, width, height, + sync, &ClipRegion, portPriv->DevPriv.ptr, + pDraw); + + if((ret == Success) && + (portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) { + + portPriv->isOn = XV_ON; + portPriv->vid_x = src_x; portPriv->vid_y = src_y; + portPriv->vid_w = src_w; portPriv->vid_h = src_h; + portPriv->drw_x = drw_x; portPriv->drw_y = drw_y; + portPriv->drw_w = drw_w; portPriv->drw_h = drw_h; + portPriv->type = 0; /* no mask means it's transient and should + not be reput once it's removed */ + pPort->pDraw = pDraw; /* make sure we can get stop requests */ + } + +PUT_IMAGE_BAILOUT: + + if((clippedAway || (ret != Success)) && (portPriv->isOn == XV_ON)) { + (*portPriv->AdaptorRec->StopVideo)( + portPriv->pScrn, portPriv->DevPriv.ptr, FALSE); + portPriv->isOn = XV_PENDING; + } + + /* This clip was copied and only good for one shot */ + if(!portPriv->FreeCompositeClip) + portPriv->pCompositeClip = NULL; + + RegionUninit(&WinRegion); + RegionUninit(&ClipRegion); + + return ret; +} + + +static int +xf86XVQueryImageAttributes( + ClientPtr client, + XvPortPtr pPort, + XvImagePtr format, + CARD16 *width, + CARD16 *height, + int *pitches, + int *offsets +){ + XvPortRecPrivatePtr portPriv = (XvPortRecPrivatePtr)(pPort->devPriv.ptr); + + return (*portPriv->AdaptorRec->QueryImageAttributes)(portPriv->pScrn, + format->id, width, height, pitches, offsets); +} + +void +xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr fillboxes) +{ + ScreenPtr pScreen = pDraw->pScreen; + ChangeGCVal pval[2]; + BoxPtr pbox = RegionRects(fillboxes); + int i, nbox = RegionNumRects(fillboxes); + xRectangle *rects; + GCPtr gc; + + if(!xf86Screens[pScreen->myNum]->vtSema) return; + + gc = GetScratchGC(pDraw->depth, pScreen); + pval[0].val = key; + pval[1].val = IncludeInferiors; + (void) ChangeGC(NullClient, gc, GCForeground|GCSubwindowMode, pval); + ValidateGC(pDraw, gc); + + rects = malloc(nbox * sizeof(xRectangle)); + + for(i = 0; i < nbox; i++, pbox++) + { + rects[i].x = pbox->x1 - pDraw->x; + rects[i].y = pbox->y1 - pDraw->y; + rects[i].width = pbox->x2 - pbox->x1; + rects[i].height = pbox->y2 - pbox->y1; + } + + (*gc->ops->PolyFillRect)(pDraw, gc, nbox, rects); + + free(rects); + FreeScratchGC (gc); +} + +void +xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr fillboxes) +{ + xf86XVFillKeyHelperDrawable (&pScreen->root->drawable, key, fillboxes); +} + +void +xf86XVFillKeyHelperPort (DrawablePtr pDraw, pointer data, CARD32 key, RegionPtr clipboxes, Bool fillEverything) +{ + WindowPtr pWin = (WindowPtr)pDraw; + XF86XVWindowPtr WinPriv = GET_XF86XV_WINDOW(pWin); + XvPortRecPrivatePtr portPriv = NULL; + RegionRec reg; + RegionPtr fillboxes; + + while (WinPriv) { + XvPortRecPrivatePtr pPriv = WinPriv->PortRec; + + if (data == pPriv->DevPriv.ptr) { + portPriv = pPriv; + break; + } + + WinPriv = WinPriv->next; + } + + if (!portPriv) + return; + + if (!portPriv->ckeyFilled) + portPriv->ckeyFilled = RegionCreate(NULL, 0); + + if (!fillEverything) { + RegionNull(®); + fillboxes = ® + RegionSubtract(fillboxes, clipboxes, portPriv->ckeyFilled); + + if (!RegionNotEmpty(fillboxes)) + goto out; + } else + fillboxes = clipboxes; + + + RegionCopy(portPriv->ckeyFilled, clipboxes); + + xf86XVFillKeyHelperDrawable(pDraw, key, fillboxes); +out: + if (!fillEverything) + RegionUninit(®); +} + + +/* xf86XVClipVideoHelper - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +Bool +xf86XVClipVideoHelper( + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height +){ + double xsw, xdw, ysw, ydw; + INT32 delta; + BoxPtr extents = RegionExtents(reg); + int diff; + + xsw = (*xb - *xa) << 16; + xdw = dst->x2 - dst->x1; + ysw = (*yb - *ya) << 16; + ydw = dst->y2 - dst->y1; + + *xa <<= 16; *xb <<= 16; + *ya <<= 16; *yb <<= 16; + + diff = extents->x1 - dst->x1; + if (diff > 0) { + dst->x1 = extents->x1; + *xa += (diff * xsw) / xdw; + } + diff = dst->x2 - extents->x2; + if (diff > 0) { + dst->x2 = extents->x2; + *xb -= (diff * xsw) / xdw; + } + diff = extents->y1 - dst->y1; + if (diff > 0) { + dst->y1 = extents->y1; + *ya += (diff * ysw) / ydw; + } + diff = dst->y2 - extents->y2; + if (diff > 0) { + dst->y2 = extents->y2; + *yb -= (diff * ysw) / ydw; + } + + if (*xa < 0) { + diff = (((-*xa) * xdw) + xsw - 1) / xsw; + dst->x1 += diff; + *xa += (diff * xsw) / xdw; + } + delta = *xb - (width << 16); + if (delta > 0) { + diff = ((delta * xdw) + xsw - 1) / xsw; + dst->x2 -= diff; + *xb -= (diff * xsw) / xdw; + } + if (*xa >= *xb) return FALSE; + + if (*ya < 0) { + diff = (((-*ya) * ydw) + ysw - 1) / ysw; + dst->y1 += diff; + *ya += (diff * ysw) / ydw; + } + delta = *yb - (height << 16); + if (delta > 0) { + diff = ((delta * ydw) + ysw - 1) / ysw; + dst->y2 -= diff; + *yb -= (diff * ysw) / ydw; + } + if (*ya >= *yb) return FALSE; + + if ((dst->x1 > extents->x1) || (dst->x2 < extents->x2) || + (dst->y1 > extents->y1) || (dst->y2 < extents->y2)) + { + RegionRec clipReg; + RegionInit(&clipReg, dst, 1); + RegionIntersect(reg, reg, &clipReg); + RegionUninit(&clipReg); + } + return TRUE; +} + +void +xf86XVCopyYUV12ToPacked( + const void *srcy, + const void *srcv, + const void *srcu, + void *dst, + int srcPitchy, + int srcPitchuv, + int dstPitch, + int h, + int w +){ + CARD32 *Dst; + const CARD8 *Y, *U, *V; + int i, j; + + w >>= 1; + + for (j = 0; j < h; j++) { + Dst = dst; + Y = srcy; V = srcv; U = srcu; + i = w; + while (i >= 4) { +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); + Dst[1] = Y[2] | (Y[3] << 16) | (U[1] << 8) | (V[1] << 24); + Dst[2] = Y[4] | (Y[5] << 16) | (U[2] << 8) | (V[2] << 24); + Dst[3] = Y[6] | (Y[7] << 16) | (U[3] << 8) | (V[3] << 24); +#else + /* This assumes a little-endian framebuffer */ + Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; + Dst[1] = (Y[2] << 24) | (Y[3] << 8) | (U[1] << 16) | V[1]; + Dst[2] = (Y[4] << 24) | (Y[5] << 8) | (U[2] << 16) | V[2]; + Dst[3] = (Y[6] << 24) | (Y[7] << 8) | (U[3] << 16) | V[3]; +#endif + Dst += 4; Y += 8; V += 4; U += 4; + i -= 4; + } + + while (i--) { +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + Dst[0] = Y[0] | (Y[1] << 16) | (U[0] << 8) | (V[0] << 24); +#else + /* This assumes a little-endian framebuffer */ + Dst[0] = (Y[0] << 24) | (Y[1] << 8) | (U[0] << 16) | V[0]; +#endif + Dst++; Y += 2; V++; U++; + } + + dst = (CARD8 *)dst + dstPitch; + srcy = (const CARD8 *)srcy + srcPitchy; + if (j & 1) { + srcu = (const CARD8 *)srcu + srcPitchuv; + srcv = (const CARD8 *)srcv + srcPitchuv; + } + } +} + +void +xf86XVCopyPacked( + const void *src, + void *dst, + int srcPitch, + int dstPitch, + int h, + int w +){ + const CARD32 *Src; + CARD32 *Dst; + int i; + + w >>= 1; + while (--h >= 0) { + do { + Dst = dst; Src = src; + i = w; + while (i >= 4) { + Dst[0] = Src[0]; + Dst[1] = Src[1]; + Dst[2] = Src[2]; + Dst[3] = Src[3]; + Dst += 4; Src += 4; i -= 4; + } + if (!i) break; + Dst[0] = Src[0]; + if (i == 1) break; + Dst[1] = Src[1]; + if (i == 2) break; + Dst[2] = Src[2]; + } while (0); + + src = (const CARD8 *)src + srcPitch; + dst = (CARD8 *)dst + dstPitch; + } +} diff --git a/xorg-server/hw/xfree86/loader/loadmod.c b/xorg-server/hw/xfree86/loader/loadmod.c index 46ce68b86..9f820993a 100644 --- a/xorg-server/hw/xfree86/loader/loadmod.c +++ b/xorg-server/hw/xfree86/loader/loadmod.c @@ -483,19 +483,15 @@ LoaderListDirs(const char **subdirlist, const char **patternlist) char *fp; char **listing = NULL; char **save; + char **ret = NULL; int n = 0; if (!(pathlist = InitPathList(NULL))) return NULL; - if (!(subdirs = InitSubdirs(subdirlist))) { - FreePathList(pathlist); - return NULL; - } - if (!(patterns = InitPatterns(patternlist))) { - FreePathList(pathlist); - FreeSubdirs(subdirs); - return NULL; - } + if (!(subdirs = InitSubdirs(subdirlist))) + goto bail; + if (!(patterns = InitPatterns(patternlist))) + goto bail; for (elem = pathlist; *elem; elem++) { for (s = subdirs; *s; s++) { @@ -529,20 +525,14 @@ LoaderListDirs(const char **subdirlist, const char **patternlist) save[n] = NULL; FreeStringList(save); } - FreePathList(pathlist); - FreeSubdirs(subdirs); - FreePatterns(patterns); closedir(d); - return NULL; + goto bail; } listing[n] = malloc(len + 1); if (!listing[n]) { FreeStringList(listing); - FreePathList(pathlist); - FreeSubdirs(subdirs); - FreePatterns(patterns); closedir(d); - return NULL; + goto bail; } strncpy(listing[n], dp->d_name + match[1].rm_so, len); @@ -558,11 +548,13 @@ LoaderListDirs(const char **subdirlist, const char **patternlist) } if (listing) listing[n] = NULL; + ret = listing; - FreePathList(pathlist); - FreeSubdirs(subdirs); +bail: FreePatterns(patterns); - return listing; + FreeSubdirs(subdirs); + FreePathList(pathlist); + return ret; } void diff --git a/xorg-server/miext/damage/damage.c b/xorg-server/miext/damage/damage.c index 0fe1fb603..d79121165 100644 --- a/xorg-server/miext/damage/damage.c +++ b/xorg-server/miext/damage/damage.c @@ -121,54 +121,6 @@ getDrawableDamageRef (DrawablePtr pDrawable) dixLookupPrivateAddr(&(pWindow)->devPrivates, damageWinPrivateKey) static void -damageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion) -{ - BoxRec tmpBox; - RegionRec tmpRegion; - Bool was_empty; - - switch (pDamage->damageLevel) { - case DamageReportRawRegion: - RegionUnion(&pDamage->damage, &pDamage->damage, - pDamageRegion); - (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); - break; - case DamageReportDeltaRegion: - RegionNull(&tmpRegion); - RegionSubtract(&tmpRegion, pDamageRegion, &pDamage->damage); - if (RegionNotEmpty(&tmpRegion)) { - RegionUnion(&pDamage->damage, &pDamage->damage, - pDamageRegion); - (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); - } - RegionUninit(&tmpRegion); - break; - case DamageReportBoundingBox: - tmpBox = *RegionExtents(&pDamage->damage); - RegionUnion(&pDamage->damage, &pDamage->damage, - pDamageRegion); - if (!BOX_SAME (&tmpBox, RegionExtents(&pDamage->damage))) { - (*pDamage->damageReport) (pDamage, &pDamage->damage, - pDamage->closure); - } - break; - case DamageReportNonEmpty: - was_empty = !RegionNotEmpty(&pDamage->damage); - RegionUnion(&pDamage->damage, &pDamage->damage, - pDamageRegion); - if (was_empty && RegionNotEmpty(&pDamage->damage)) { - (*pDamage->damageReport) (pDamage, &pDamage->damage, - pDamage->closure); - } - break; - case DamageReportNone: - RegionUnion(&pDamage->damage, &pDamage->damage, - pDamageRegion); - break; - } -} - -static void damageReportDamagePostRendering (DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pDamageRegion) { BoxRec tmpBox; @@ -360,7 +312,7 @@ damageRegionAppend (DrawablePtr pDrawable, RegionPtr pRegion, Bool clip, /* Report damage now, if desired. */ if (!pDamage->reportAfter) { if (pDamage->damageReport) - damageReportDamage (pDamage, pDamageRegion); + DamageReportDamage (pDamage, pDamageRegion); else RegionUnion(&pDamage->damage, &pDamage->damage, pDamageRegion); @@ -393,7 +345,7 @@ damageRegionProcessPending (DrawablePtr pDrawable) if (pDamage->reportAfter) { /* It's possible that there is only interest in postRendering reporting. */ if (pDamage->damageReport) - damageReportDamage (pDamage, &pDamage->pendingDamage); + DamageReportDamage (pDamage, &pDamage->pendingDamage); else RegionUnion(&pDamage->damage, &pDamage->damage, &pDamage->pendingDamage); @@ -2125,3 +2077,52 @@ DamageGetScreenFuncs (ScreenPtr pScreen) damageScrPriv(pScreen); return &pScrPriv->funcs; } + +void +DamageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion) +{ + BoxRec tmpBox; + RegionRec tmpRegion; + Bool was_empty; + + switch (pDamage->damageLevel) { + case DamageReportRawRegion: + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + (*pDamage->damageReport) (pDamage, pDamageRegion, pDamage->closure); + break; + case DamageReportDeltaRegion: + RegionNull(&tmpRegion); + RegionSubtract(&tmpRegion, pDamageRegion, &pDamage->damage); + if (RegionNotEmpty(&tmpRegion)) { + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + (*pDamage->damageReport) (pDamage, &tmpRegion, pDamage->closure); + } + RegionUninit(&tmpRegion); + break; + case DamageReportBoundingBox: + tmpBox = *RegionExtents(&pDamage->damage); + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + if (!BOX_SAME (&tmpBox, RegionExtents(&pDamage->damage))) { + (*pDamage->damageReport) (pDamage, &pDamage->damage, + pDamage->closure); + } + break; + case DamageReportNonEmpty: + was_empty = !RegionNotEmpty(&pDamage->damage); + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + if (was_empty && RegionNotEmpty(&pDamage->damage)) { + (*pDamage->damageReport) (pDamage, &pDamage->damage, + pDamage->closure); + } + break; + case DamageReportNone: + RegionUnion(&pDamage->damage, &pDamage->damage, + pDamageRegion); + break; + } +} + diff --git a/xorg-server/miext/damage/damage.h b/xorg-server/miext/damage/damage.h index 067016f38..0c7fc316c 100644 --- a/xorg-server/miext/damage/damage.h +++ b/xorg-server/miext/damage/damage.h @@ -110,6 +110,10 @@ DamageRegionProcessPending (DrawablePtr pDrawable); extern _X_EXPORT void DamageRegionRendered (DrawablePtr pDrawable, DamagePtr pDamage, RegionPtr pOldDamage, RegionPtr pRegion); +/* Call this when you create a new Damage and you wish to send an initial damage message (to it). */ +extern _X_EXPORT void +DamageReportDamage (DamagePtr pDamage, RegionPtr pDamageRegion); + /* Avoid using this call, it only exists for API compatibility. */ extern _X_EXPORT void DamageDamageRegion (DrawablePtr pDrawable, diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c index 4eb2c15c7..0c580ab5e 100644 --- a/xorg-server/os/connection.c +++ b/xorg-server/os/connection.c @@ -1,1308 +1,1307 @@ -/***********************************************************
-
-Copyright 1987, 1989, 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, 1989 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.
-
-******************************************************************/
-/*****************************************************************
- * Stuff to create connections --- OS dependent
- *
- * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
- * CloseDownConnection, CheckConnections, AddEnabledDevice,
- * RemoveEnabledDevice, OnlyListToOneClient,
- * ListenToAllClients,
- *
- * (WaitForSomething is in its own file)
- *
- * In this implementation, a client socket table is not kept.
- * Instead, what would be the index into the table is just the
- * file descriptor of the socket. This won't work for if the
- * socket ids aren't small nums (0 - 2^8)
- *
- *****************************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#define XSERV_t
-#define TRANS_SERVER
-#define TRANS_REOPEN
-#include <X11/Xtrans/Xtrans.h>
-#include <X11/Xtrans/Xtransint.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef WIN32
-#include <sys/socket.h>
-
-
-
-#if defined(TCPCONN) || defined(STREAMSCONN)
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# ifdef apollo
-# ifndef NO_TCP_H
-# include <netinet/tcp.h>
-# endif
-# else
-# ifdef CSRG_BASED
-# include <sys/param.h>
-# endif
-# include <netinet/tcp.h>
-# endif
-# include <arpa/inet.h>
-#endif
-
-#include <sys/uio.h>
-
-#endif /* WIN32 */
-#include "misc.h" /* for typedef of pointer */
-#include "osdep.h"
-#include <X11/Xpoll.h>
-#include "opaque.h"
-#include "dixstruct.h"
-#include "xace.h"
-
-#define Pid_t pid_t
-
-
-#ifdef HAS_GETPEERUCRED
-# include <ucred.h>
-# include <zone.h>
-#endif
-
-#ifdef XSERVER_DTRACE
-# include <sys/types.h>
-typedef const char *string;
-# ifndef HAS_GETPEERUCRED
-# define zoneid_t int
-# endif
-# include "../dix/Xserver-dtrace.h"
-#endif
-
-static int lastfdesc; /* maximum file descriptor */
-
-fd_set WellKnownConnections; /* Listener mask */
-fd_set EnabledDevices; /* mask for input devices that are on */
-fd_set AllSockets; /* select on this */
-fd_set AllClients; /* available clients */
-fd_set LastSelectMask; /* mask returned from last select call */
-fd_set ClientsWithInput; /* clients with FULL requests in buffer */
-fd_set ClientsWriteBlocked; /* clients who cannot receive output */
-fd_set OutputPending; /* clients with reply/event data ready to go */
-int MaxClients = 0;
-Bool NewOutputPending; /* not yet attempted to write some new output */
-Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
-
-static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
-Bool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or
- equivalent) will send SIGCONT back. */
-Bool PartialNetwork; /* continue even if unable to bind all addrs */
-static Pid_t ParentProcess;
-
-static Bool debug_conns = FALSE;
-
-fd_set IgnoredClientsWithInput;
-static fd_set GrabImperviousClients;
-static fd_set SavedAllClients;
-static fd_set SavedAllSockets;
-static fd_set SavedClientsWithInput;
-int GrabInProgress = 0;
-
-#if !defined(WIN32)
-int *ConnectionTranslation = NULL;
-#else
-/*
- * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
- * not even a known maximum value, so use something quite arbitrary for now.
- * Do storage is a hash table of size 256. Collisions are handled in a linked
- * list.
- */
-
-#undef MAXSOCKS
-#define MAXSOCKS 500
-#undef MAXSELECT
-#define MAXSELECT 500
-
-struct _ct_node {
- struct _ct_node *next;
- int key;
- int value;
-};
-
-struct _ct_node *ct_head[256];
-
-void InitConnectionTranslation(void)
-{
- memset(ct_head, 0, sizeof(ct_head));
-}
-
-int GetConnectionTranslation(int conn)
-{
- struct _ct_node *node = ct_head[conn & 0xff];
- while (node != NULL)
- {
- if (node->key == conn)
- return node->value;
- node = node->next;
- }
- return 0;
-}
-
-void SetConnectionTranslation(int conn, int client)
-{
- struct _ct_node **node = ct_head + (conn & 0xff);
- if (client == 0) /* remove entry */
- {
- while (*node != NULL)
- {
- if ((*node)->key == conn)
- {
- struct _ct_node *temp = *node;
- *node = (*node)->next;
- free(temp);
- return;
- }
- node = &((*node)->next);
- }
- return;
- } else
- {
- while (*node != NULL)
- {
- if ((*node)->key == conn)
- {
- (*node)->value = client;
- return;
- }
- node = &((*node)->next);
- }
- *node = malloc(sizeof(struct _ct_node));
- (*node)->next = NULL;
- (*node)->key = conn;
- (*node)->value = client;
- return;
- }
-}
-
-void ClearConnectionTranslation(void)
-{
- unsigned i;
- for (i = 0; i < 256; i++)
- {
- struct _ct_node *node = ct_head[i];
- while (node != NULL)
- {
- struct _ct_node *temp = node;
- node = node->next;
- free(temp);
- }
- }
-}
-#endif
-
-static XtransConnInfo *ListenTransConns = NULL;
-static int *ListenTransFds = NULL;
-static int ListenTransCount;
-
-static void ErrorConnMax(XtransConnInfo /* trans_conn */);
-
-static XtransConnInfo
-lookup_trans_conn (int fd)
-{
- if (ListenTransFds)
- {
- int i;
- for (i = 0; i < ListenTransCount; i++)
- if (ListenTransFds[i] == fd)
- return ListenTransConns[i];
- }
-
- return NULL;
-}
-
-/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
-
-void
-InitConnectionLimits(void)
-{
- lastfdesc = -1;
-
-#ifndef __CYGWIN__
-
-#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
- lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
-#endif
-
-#ifdef HAS_GETDTABLESIZE
- if (lastfdesc < 0)
- lastfdesc = getdtablesize() - 1;
-#endif
-
-#ifdef _NFILE
- if (lastfdesc < 0)
- lastfdesc = _NFILE - 1;
-#endif
-
-#endif /* __CYGWIN__ */
-
- /* This is the fallback */
- if (lastfdesc < 0)
- lastfdesc = MAXSOCKS;
-
- if (lastfdesc > MAXSELECT)
- lastfdesc = MAXSELECT;
-
- if (lastfdesc > MAXCLIENTS)
- {
- lastfdesc = MAXCLIENTS;
- if (debug_conns)
- ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
- }
- MaxClients = lastfdesc;
-
-#ifdef DEBUG
- ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
-#endif
-
-#if !defined(WIN32)
- if (!ConnectionTranslation)
- ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
-#else
- InitConnectionTranslation();
-#endif
-}
-
-/*
- * If SIGUSR1 was set to SIG_IGN when the server started, assume that either
- *
- * a- The parent process is ignoring SIGUSR1
- *
- * or
- *
- * b- The parent process is expecting a SIGUSR1
- * when the server is ready to accept connections
- *
- * In the first case, the signal will be harmless, in the second case,
- * the signal will be quite useful.
- */
-static void
-InitParentProcess(void)
-{
-#if !defined(WIN32)
- OsSigHandlerPtr handler;
- handler = OsSignal (SIGUSR1, SIG_IGN);
- if ( handler == SIG_IGN)
- RunFromSmartParent = TRUE;
- OsSignal(SIGUSR1, handler);
- ParentProcess = getppid ();
-#endif
-}
-
-void
-NotifyParentProcess(void)
-{
-#if !defined(WIN32)
- if (RunFromSmartParent) {
- if (ParentProcess > 1) {
- kill (ParentProcess, SIGUSR1);
- }
- }
- if (RunFromSigStopParent)
- raise (SIGSTOP);
-#endif
-}
-
-/*****************
- * CreateWellKnownSockets
- * At initialization, create the sockets to listen on for new clients.
- *****************/
-
-void
-CreateWellKnownSockets(void)
-{
- int i;
- int partial;
- char port[20];
-
- FD_ZERO(&AllSockets);
- FD_ZERO(&AllClients);
- FD_ZERO(&LastSelectMask);
- FD_ZERO(&ClientsWithInput);
-
-#if !defined(WIN32)
- for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
-#else
- ClearConnectionTranslation();
-#endif
-
- FD_ZERO (&WellKnownConnections);
-
- sprintf (port, "%d", atoi (display));
-
- if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
- &ListenTransCount, &ListenTransConns) >= 0) &&
- (ListenTransCount >= 1))
- {
- if (!PartialNetwork && partial)
- {
- FatalError ("Failed to establish all listening sockets");
- }
- else
- {
- ListenTransFds = malloc(ListenTransCount * sizeof (int));
-
- for (i = 0; i < ListenTransCount; i++)
- {
- int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
-
- ListenTransFds[i] = fd;
- FD_SET (fd, &WellKnownConnections);
-
- if (!_XSERVTransIsLocal (ListenTransConns[i]))
- {
- DefineSelf (fd);
- }
- }
- }
- }
-
- if (!XFD_ANYSET (&WellKnownConnections))
- FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
-#if !defined(WIN32)
- OsSignal (SIGPIPE, SIG_IGN);
- OsSignal (SIGHUP, AutoResetServer);
-#endif
- OsSignal (SIGINT, GiveUp);
- OsSignal (SIGTERM, GiveUp);
- XFD_COPYSET (&WellKnownConnections, &AllSockets);
- ResetHosts(display);
-
- InitParentProcess();
-
-#ifdef XDMCP
- XdmcpInit ();
-#endif
-}
-
-void
-ResetWellKnownSockets (void)
-{
- int i;
-
- ResetOsBuffers();
-
- for (i = 0; i < ListenTransCount; i++)
- {
- int status = _XSERVTransResetListener (ListenTransConns[i]);
-
- if (status != TRANS_RESET_NOOP)
- {
- if (status == TRANS_RESET_FAILURE)
- {
- /*
- * ListenTransConns[i] freed by xtrans.
- * Remove it from out list.
- */
-
- FD_CLR (ListenTransFds[i], &WellKnownConnections);
- ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
- ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
- ListenTransCount -= 1;
- i -= 1;
- }
- else if (status == TRANS_RESET_NEW_FD)
- {
- /*
- * A new file descriptor was allocated (the old one was closed)
- */
-
- int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
-
- FD_CLR (ListenTransFds[i], &WellKnownConnections);
- ListenTransFds[i] = newfd;
- FD_SET(newfd, &WellKnownConnections);
- }
- }
- }
-
- ResetAuthorization ();
- ResetHosts(display);
- /*
- * restart XDMCP
- */
-#ifdef XDMCP
- XdmcpReset ();
-#endif
-}
-
-void
-CloseWellKnownConnections(void)
-{
- int i;
-
- for (i = 0; i < ListenTransCount; i++)
- _XSERVTransClose (ListenTransConns[i]);
-}
-
-static void
-AuthAudit (ClientPtr client, Bool letin,
- struct sockaddr *saddr, int len,
- unsigned int proto_n, char *auth_proto, int auth_id)
-{
- char addr[128];
- char *out = addr;
- char client_uid_string[64];
- LocalClientCredRec *lcc;
-#ifdef XSERVER_DTRACE
- pid_t client_pid = -1;
- zoneid_t client_zid = -1;
-#endif
-
- if (!len)
- strcpy(out, "local host");
- else
- switch (saddr->sa_family)
- {
- case AF_UNSPEC:
-#if defined(UNIXCONN) || defined(LOCALCONN)
- case AF_UNIX:
-#endif
- strcpy(out, "local host");
- break;
-#if defined(TCPCONN) || defined(STREAMSCONN)
- case AF_INET:
- sprintf(out, "IP %s",
- inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6: {
- char ipaddr[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
- ipaddr, sizeof(ipaddr));
- sprintf(out, "IP %s", ipaddr);
- }
- break;
-#endif
-#endif
- default:
- strcpy(out, "unknown address");
- }
-
- if (GetLocalClientCreds(client, &lcc) != -1) {
- int slen; /* length written to client_uid_string */
-
- strcpy(client_uid_string, " ( ");
- slen = 3;
-
- if (lcc->fieldsSet & LCC_UID_SET) {
- snprintf(client_uid_string + slen,
- sizeof(client_uid_string) - slen,
- "uid=%ld ", (long) lcc->euid);
- slen = strlen(client_uid_string);
- }
-
- if (lcc->fieldsSet & LCC_GID_SET) {
- snprintf(client_uid_string + slen,
- sizeof(client_uid_string) - slen,
- "gid=%ld ", (long) lcc->egid);
- slen = strlen(client_uid_string);
- }
-
- if (lcc->fieldsSet & LCC_PID_SET) {
-#ifdef XSERVER_DTRACE
- client_pid = lcc->pid;
-#endif
- snprintf(client_uid_string + slen,
- sizeof(client_uid_string) - slen,
- "pid=%ld ", (long) lcc->pid);
- slen = strlen(client_uid_string);
- }
-
- if (lcc->fieldsSet & LCC_ZID_SET) {
-#ifdef XSERVER_DTRACE
- client_zid = lcc->zoneid;
-#endif
- snprintf(client_uid_string + slen,
- sizeof(client_uid_string) - slen,
- "zoneid=%ld ", (long) lcc->zoneid);
- slen = strlen(client_uid_string);
- }
-
- snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
- ")");
- FreeLocalClientCreds(lcc);
- }
- else {
- client_uid_string[0] = '\0';
- }
-
-#ifdef XSERVER_DTRACE
- XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
-#endif
- if (auditTrailLevel > 1) {
- if (proto_n)
- AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n",
- client->index, letin ? "connected" : "rejected", addr,
- client_uid_string, (int)proto_n, auth_proto, auth_id);
- else
- AuditF("client %d %s from %s%s\n",
- client->index, letin ? "connected" : "rejected", addr,
- client_uid_string);
-
- }
-}
-
-XID
-AuthorizationIDOfClient(ClientPtr client)
-{
- if (client->osPrivate)
- return ((OsCommPtr)client->osPrivate)->auth_id;
- else
- return None;
-}
-
-
-/*****************************************************************
- * ClientAuthorized
- *
- * Sent by the client at connection setup:
- * typedef struct _xConnClientPrefix {
- * CARD8 byteOrder;
- * BYTE pad;
- * CARD16 majorVersion, minorVersion;
- * CARD16 nbytesAuthProto;
- * CARD16 nbytesAuthString;
- * } xConnClientPrefix;
- *
- * It is hoped that eventually one protocol will be agreed upon. In the
- * mean time, a server that implements a different protocol than the
- * client expects, or a server that only implements the host-based
- * mechanism, will simply ignore this information.
- *
- *****************************************************************/
-
-char *
-ClientAuthorized(ClientPtr client,
- unsigned int proto_n, char *auth_proto,
- unsigned int string_n, char *auth_string)
-{
- OsCommPtr priv;
- Xtransaddr *from = NULL;
- int family;
- int fromlen;
- XID auth_id;
- char *reason = NULL;
- XtransConnInfo trans_conn;
-
- priv = (OsCommPtr)client->osPrivate;
- trans_conn = priv->trans_conn;
-
- /* Allow any client to connect without authorization on a launchd socket,
- because it is securely created -- this prevents a race condition on launch */
- if(trans_conn->flags & TRANS_NOXAUTH) {
- auth_id = (XID) 0L;
- } else {
- auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
- }
-
- if (auth_id == (XID) ~0L)
- {
- if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
- {
- if (InvalidHost ((struct sockaddr *) from, fromlen, client))
- AuthAudit(client, FALSE, (struct sockaddr *) from,
- fromlen, proto_n, auth_proto, auth_id);
- else
- {
- auth_id = (XID) 0;
-#ifdef XSERVER_DTRACE
- if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
-#else
- if (auditTrailLevel > 1)
-#endif
- AuthAudit(client, TRUE,
- (struct sockaddr *) from, fromlen,
- proto_n, auth_proto, auth_id);
- }
-
- free(from);
- }
-
- if (auth_id == (XID) ~0L) {
- if (reason)
- return reason;
- else
- return "Client is not authorized to connect to Server";
- }
- }
-#ifdef XSERVER_DTRACE
- else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
-#else
- else if (auditTrailLevel > 1)
-#endif
- {
- if (_XSERVTransGetPeerAddr (trans_conn,
- &family, &fromlen, &from) != -1)
- {
- AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
- proto_n, auth_proto, auth_id);
-
- free(from);
- }
- }
- priv->auth_id = auth_id;
- priv->conn_time = 0;
-
-#ifdef XDMCP
- /* indicate to Xdmcp protocol that we've opened new client */
- XdmcpOpenDisplay(priv->fd);
-#endif /* XDMCP */
-
- XaceHook(XACE_AUTH_AVAIL, client, auth_id);
-
- /* At this point, if the client is authorized to change the access control
- * list, we should getpeername() information, and add the client to
- * the selfhosts list. It's not really the host machine, but the
- * true purpose of the selfhosts list is to see who may change the
- * access control list.
- */
- return((char *)NULL);
-}
-
-static ClientPtr
-AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
-{
- OsCommPtr oc;
- ClientPtr client;
-
- if (
-#ifndef WIN32
- fd >= lastfdesc
-#else
- XFD_SETCOUNT(&AllClients) >= MaxClients
-#endif
- )
- return NullClient;
- oc = malloc(sizeof(OsCommRec));
- if (!oc)
- return NullClient;
- oc->trans_conn = trans_conn;
- oc->fd = fd;
- oc->input = (ConnectionInputPtr)NULL;
- oc->output = (ConnectionOutputPtr)NULL;
- oc->auth_id = None;
- oc->conn_time = conn_time;
- if (!(client = NextAvailableClient((pointer)oc)))
- {
- free(oc);
- return NullClient;
- }
- oc->local_client = ComputeLocalClient(client);
-#if !defined(WIN32)
- ConnectionTranslation[fd] = client->index;
-#else
- SetConnectionTranslation(fd, client->index);
-#endif
- if (GrabInProgress)
- {
- FD_SET(fd, &SavedAllClients);
- FD_SET(fd, &SavedAllSockets);
- }
- else
- {
- FD_SET(fd, &AllClients);
- FD_SET(fd, &AllSockets);
- }
-
-#ifdef DEBUG
- ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
- client->index, fd);
-#endif
-#ifdef XSERVER_DTRACE
- XSERVER_CLIENT_CONNECT(client->index, fd);
-#endif
-
- return client;
-}
-
-/*****************
- * EstablishNewConnections
- * If anyone is waiting on listened sockets, accept them.
- * Returns a mask with indices of new clients. Updates AllClients
- * and AllSockets.
- *****************/
-
-/*ARGSUSED*/
-Bool
-EstablishNewConnections(ClientPtr clientUnused, pointer closure)
-{
- fd_set readyconnections; /* set of listeners that are ready */
- int curconn; /* fd of listener that's ready */
- register int newconn; /* fd of new client */
- CARD32 connect_time;
- register int i;
- register ClientPtr client;
- register OsCommPtr oc;
- fd_set tmask;
-
- XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
- XFD_COPYSET(&tmask, &readyconnections);
- if (!XFD_ANYSET(&readyconnections))
- return TRUE;
- connect_time = GetTimeInMillis();
- /* kill off stragglers */
- for (i=1; i<currentMaxClients; i++)
- {
- if ((client = clients[i]))
- {
- oc = (OsCommPtr)(client->osPrivate);
- if ((oc && (oc->conn_time != 0) &&
- (connect_time - oc->conn_time) >= TimeOutValue) ||
- (client->noClientException != Success && !client->clientGone))
- CloseDownClient(client);
- }
- }
-#ifndef WIN32
- for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
- {
- while (readyconnections.fds_bits[i])
-#else
- for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
-#endif
- {
- XtransConnInfo trans_conn, new_trans_conn;
- int status;
-
-#ifndef WIN32
- curconn = mffs (readyconnections.fds_bits[i]) - 1;
- readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
- curconn += (i * (sizeof(fd_mask)*8));
-#else
- curconn = XFD_FD(&readyconnections, i);
-#endif
-
- if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
- continue;
-
- if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
- continue;
-
- newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
-
- if (newconn < lastfdesc)
- {
- int clientid;
-#if !defined(WIN32)
- clientid = ConnectionTranslation[newconn];
-#else
- clientid = GetConnectionTranslation(newconn);
-#endif
- if(clientid && (client = clients[clientid]))
- CloseDownClient(client);
- }
-
- _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
-
- if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
- {
- ErrorConnMax(new_trans_conn);
- _XSERVTransClose(new_trans_conn);
- }
-
- if(trans_conn->flags & TRANS_NOXAUTH)
- new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
-
- }
-#ifndef WIN32
- }
-#endif
- return TRUE;
-}
-
-#define NOROOM "Maximum number of clients reached"
-
-/************
- * ErrorConnMax
- * Fail a connection due to lack of client or file descriptor space
- ************/
-
-static void
-ErrorConnMax(XtransConnInfo trans_conn)
-{
- int fd = _XSERVTransGetConnectionNumber (trans_conn);
- xConnSetupPrefix csp;
- char pad[3];
- struct iovec iov[3];
- char byteOrder = 0;
- int whichbyte = 1;
- struct timeval waittime;
- fd_set mask;
-
- /* if these seems like a lot of trouble to go to, it probably is */
- waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
- waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
- (1000000 / MILLI_PER_SECOND);
- FD_ZERO(&mask);
- FD_SET(fd, &mask);
- (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
- /* try to read the byte-order of the connection */
- (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
- if ((byteOrder == 'l') || (byteOrder == 'B'))
- {
- csp.success = xFalse;
- csp.lengthReason = sizeof(NOROOM) - 1;
- csp.length = (sizeof(NOROOM) + 2) >> 2;
- csp.majorVersion = X_PROTOCOL;
- csp.minorVersion = X_PROTOCOL_REVISION;
- if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
- (!(*(char *) &whichbyte) && (byteOrder == 'l')))
- {
- swaps(&csp.majorVersion, whichbyte);
- swaps(&csp.minorVersion, whichbyte);
- swaps(&csp.length, whichbyte);
- }
- iov[0].iov_len = sz_xConnSetupPrefix;
- iov[0].iov_base = (char *) &csp;
- iov[1].iov_len = csp.lengthReason;
- iov[1].iov_base = NOROOM;
- iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
- iov[2].iov_base = pad;
- (void)_XSERVTransWritev(trans_conn, iov, 3);
- }
-}
-
-/************
- * CloseDownFileDescriptor:
- * Remove this file descriptor and it's I/O buffers, etc.
- ************/
-
-static void
-CloseDownFileDescriptor(OsCommPtr oc)
-{
- int connection = oc->fd;
-
- if (oc->trans_conn) {
- _XSERVTransDisconnect(oc->trans_conn);
- _XSERVTransClose(oc->trans_conn);
- }
-#ifndef WIN32
- ConnectionTranslation[connection] = 0;
-#else
- SetConnectionTranslation(connection, 0);
-#endif
- FD_CLR(connection, &AllSockets);
- FD_CLR(connection, &AllClients);
- FD_CLR(connection, &ClientsWithInput);
- FD_CLR(connection, &GrabImperviousClients);
- if (GrabInProgress)
- {
- FD_CLR(connection, &SavedAllSockets);
- FD_CLR(connection, &SavedAllClients);
- FD_CLR(connection, &SavedClientsWithInput);
- }
- FD_CLR(connection, &ClientsWriteBlocked);
- if (!XFD_ANYSET(&ClientsWriteBlocked))
- AnyClientsWriteBlocked = FALSE;
- FD_CLR(connection, &OutputPending);
-}
-
-/*****************
- * CheckConnections
- * Some connection has died, go find which one and shut it down
- * The file descriptor has been closed, but is still in AllClients.
- * If would truly be wonderful if select() would put the bogus
- * file descriptors in the exception mask, but nooooo. So we have
- * to check each and every socket individually.
- *****************/
-
-void
-CheckConnections(void)
-{
-#ifndef WIN32
- fd_mask mask;
-#endif
- fd_set tmask;
- int curclient, curoff;
- int i;
- struct timeval notime;
- int r;
-#ifdef WIN32
- fd_set savedAllClients;
-#endif
-
- notime.tv_sec = 0;
- notime.tv_usec = 0;
-
-#ifndef WIN32
- for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
- {
- mask = AllClients.fds_bits[i];
- while (mask)
- {
- curoff = mffs (mask) - 1;
- curclient = curoff + (i * (sizeof(fd_mask)*8));
- FD_ZERO(&tmask);
- FD_SET(curclient, &tmask);
- do {
- r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
- } while (r < 0 && (errno == EINTR || errno == EAGAIN));
- if (r < 0)
- if (ConnectionTranslation[curclient] > 0)
- CloseDownClient(clients[ConnectionTranslation[curclient]]);
- mask &= ~((fd_mask)1 << curoff);
- }
- }
-#else
- XFD_COPYSET(&AllClients, &savedAllClients);
- for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
- {
- curclient = XFD_FD(&savedAllClients, i);
- FD_ZERO(&tmask);
- FD_SET(curclient, &tmask);
- do {
- r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
- } while (r < 0 && (errno == EINTR || errno == EAGAIN));
- if (r < 0)
- if (GetConnectionTranslation(curclient) > 0)
- CloseDownClient(clients[GetConnectionTranslation(curclient)]);
- }
-#endif
-}
-
-
-/*****************
- * CloseDownConnection
- * Delete client from AllClients and free resources
- *****************/
-
-void
-CloseDownConnection(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
-
- if (FlushCallback)
- CallCallbacks(&FlushCallback, NULL);
-
- if (oc->output && oc->output->count)
- FlushClient(client, oc, (char *)NULL, 0);
-#ifdef XDMCP
- XdmcpCloseDisplay(oc->fd);
-#endif
- CloseDownFileDescriptor(oc);
- FreeOsBuffers(oc);
- free(client->osPrivate);
- client->osPrivate = (pointer)NULL;
- if (auditTrailLevel > 1)
- AuditF("client %d disconnected\n", client->index);
-}
-
-void
-AddGeneralSocket(int fd)
-{
- FD_SET(fd, &AllSockets);
- if (GrabInProgress)
- FD_SET(fd, &SavedAllSockets);
-}
-
-void
-AddEnabledDevice(int fd)
-{
- FD_SET(fd, &EnabledDevices);
- AddGeneralSocket(fd);
-}
-
-void
-RemoveGeneralSocket(int fd)
-{
- FD_CLR(fd, &AllSockets);
- if (GrabInProgress)
- FD_CLR(fd, &SavedAllSockets);
-}
-
-void
-RemoveEnabledDevice(int fd)
-{
- FD_CLR(fd, &EnabledDevices);
- RemoveGeneralSocket(fd);
-}
-
-/*****************
- * OnlyListenToOneClient:
- * Only accept requests from one client. Continue to handle new
- * connections, but don't take any protocol requests from the new
- * ones. Note that if GrabInProgress is set, EstablishNewConnections
- * needs to put new clients into SavedAllSockets and SavedAllClients.
- * Note also that there is no timeout for this in the protocol.
- * This routine is "undone" by ListenToAllClients()
- *****************/
-
-int
-OnlyListenToOneClient(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int rc, connection = oc->fd;
-
- rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
- if (rc != Success)
- return rc;
-
- if (! GrabInProgress)
- {
- XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
- XFD_ANDSET(&ClientsWithInput,
- &ClientsWithInput, &GrabImperviousClients);
- if (FD_ISSET(connection, &SavedClientsWithInput))
- {
- FD_CLR(connection, &SavedClientsWithInput);
- FD_SET(connection, &ClientsWithInput);
- }
- XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
- XFD_COPYSET(&AllSockets, &SavedAllSockets);
- XFD_COPYSET(&AllClients, &SavedAllClients);
- XFD_UNSET(&AllSockets, &AllClients);
- XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
- FD_SET(connection, &AllClients);
- XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
- GrabInProgress = client->index;
- }
- return rc;
-}
-
-/****************
- * ListenToAllClients:
- * Undoes OnlyListentToOneClient()
- ****************/
-
-void
-ListenToAllClients(void)
-{
- if (GrabInProgress)
- {
- XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
- XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
- XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
- GrabInProgress = 0;
- }
-}
-
-/****************
- * IgnoreClient
- * Removes one client from input masks.
- * Must have cooresponding call to AttendClient.
- ****************/
-
-void
-IgnoreClient (ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
-
- client->ignoreCount++;
- if (client->ignoreCount > 1)
- return;
-
- isItTimeToYield = TRUE;
- if (!GrabInProgress || FD_ISSET(connection, &AllClients))
- {
- if (FD_ISSET (connection, &ClientsWithInput))
- FD_SET(connection, &IgnoredClientsWithInput);
- else
- FD_CLR(connection, &IgnoredClientsWithInput);
- FD_CLR(connection, &ClientsWithInput);
- FD_CLR(connection, &AllSockets);
- FD_CLR(connection, &AllClients);
- FD_CLR(connection, &LastSelectMask);
- }
- else
- {
- if (FD_ISSET (connection, &SavedClientsWithInput))
- FD_SET(connection, &IgnoredClientsWithInput);
- else
- FD_CLR(connection, &IgnoredClientsWithInput);
- FD_CLR(connection, &SavedClientsWithInput);
- FD_CLR(connection, &SavedAllSockets);
- FD_CLR(connection, &SavedAllClients);
- }
-}
-
-/****************
- * AttendClient
- * Adds one client back into the input masks.
- ****************/
-
-void
-AttendClient (ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
-
- client->ignoreCount--;
- if (client->ignoreCount)
- return;
-
- if (!GrabInProgress || GrabInProgress == client->index ||
- FD_ISSET(connection, &GrabImperviousClients))
- {
- FD_SET(connection, &AllClients);
- FD_SET(connection, &AllSockets);
- FD_SET(connection, &LastSelectMask);
- if (FD_ISSET (connection, &IgnoredClientsWithInput))
- FD_SET(connection, &ClientsWithInput);
- }
- else
- {
- FD_SET(connection, &SavedAllClients);
- FD_SET(connection, &SavedAllSockets);
- if (FD_ISSET(connection, &IgnoredClientsWithInput))
- FD_SET(connection, &SavedClientsWithInput);
- }
-}
-
-/* make client impervious to grabs; assume only executing client calls this */
-
-void
-MakeClientGrabImpervious(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
-
- FD_SET(connection, &GrabImperviousClients);
-
- if (ServerGrabCallback)
- {
- ServerGrabInfoRec grabinfo;
- grabinfo.client = client;
- grabinfo.grabstate = CLIENT_IMPERVIOUS;
- CallCallbacks(&ServerGrabCallback, &grabinfo);
- }
-}
-
-/* make client pervious to grabs; assume only executing client calls this */
-
-void
-MakeClientGrabPervious(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
-
- FD_CLR(connection, &GrabImperviousClients);
- if (GrabInProgress && (GrabInProgress != client->index))
- {
- if (FD_ISSET(connection, &ClientsWithInput))
- {
- FD_SET(connection, &SavedClientsWithInput);
- FD_CLR(connection, &ClientsWithInput);
- }
- FD_CLR(connection, &AllSockets);
- FD_CLR(connection, &AllClients);
- isItTimeToYield = TRUE;
- }
-
- if (ServerGrabCallback)
- {
- ServerGrabInfoRec grabinfo;
- grabinfo.client = client;
- grabinfo.grabstate = CLIENT_PERVIOUS;
- CallCallbacks(&ServerGrabCallback, &grabinfo);
- }
-}
-
-#ifdef XQUARTZ
-/* Add a fd (from launchd) to our listeners */
-void ListenOnOpenFD(int fd, int noxauth) {
- char port[256];
- XtransConnInfo ciptr;
- const char *display_env = getenv("DISPLAY");
-
- if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
- /* Make the path the launchd socket if our DISPLAY is set right */
- strcpy(port, display_env);
- } else {
- /* Just some default so things don't break and die. */
- sprintf(port, ":%d", atoi(display));
- }
-
- /* Make our XtransConnInfo
- * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c
- */
- ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
- if(ciptr == NULL) {
- ErrorF("Got NULL while trying to Reopen launchd port.\n");
- return;
- }
-
- if(noxauth)
- ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
-
- /* Allocate space to store it */
- ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
- ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
-
- /* Store it */
- ListenTransConns[ListenTransCount] = ciptr;
- ListenTransFds[ListenTransCount] = fd;
-
- FD_SET(fd, &WellKnownConnections);
- FD_SET(fd, &AllSockets);
-
- /* Increment the count */
- ListenTransCount++;
-
- /* This *might* not be needed... /shrug */
- ResetAuthorization();
- ResetHosts(display);
-#ifdef XDMCP
- XdmcpReset();
-#endif
-}
-
-#endif
+/*********************************************************** + +Copyright 1987, 1989, 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, 1989 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. + +******************************************************************/ +/***************************************************************** + * Stuff to create connections --- OS dependent + * + * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets, + * CloseDownConnection, CheckConnections, AddEnabledDevice, + * RemoveEnabledDevice, OnlyListToOneClient, + * ListenToAllClients, + * + * (WaitForSomething is in its own file) + * + * In this implementation, a client socket table is not kept. + * Instead, what would be the index into the table is just the + * file descriptor of the socket. This won't work for if the + * socket ids aren't small nums (0 - 2^8) + * + *****************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifdef WIN32 +#include <X11/Xwinsock.h> +#endif +#include <X11/X.h> +#include <X11/Xproto.h> +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include <X11/Xtrans/Xtrans.h> +#include <X11/Xtrans/Xtransint.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> + +#ifndef WIN32 +#include <sys/socket.h> + + + +#if defined(TCPCONN) || defined(STREAMSCONN) +# include <netinet/in.h> +# include <arpa/inet.h> +# ifdef apollo +# ifndef NO_TCP_H +# include <netinet/tcp.h> +# endif +# else +# ifdef CSRG_BASED +# include <sys/param.h> +# endif +# include <netinet/tcp.h> +# endif +# include <arpa/inet.h> +#endif + +#include <sys/uio.h> + +#endif /* WIN32 */ +#include "misc.h" /* for typedef of pointer */ +#include "osdep.h" +#include <X11/Xpoll.h> +#include "opaque.h" +#include "dixstruct.h" +#include "xace.h" + +#define Pid_t pid_t + + +#ifdef HAS_GETPEERUCRED +# include <ucred.h> +# include <zone.h> +#endif + +#ifdef XSERVER_DTRACE +# include <sys/types.h> +typedef const char *string; +# ifndef HAS_GETPEERUCRED +# define zoneid_t int +# endif +# include "../dix/Xserver-dtrace.h" +#endif + +static int lastfdesc; /* maximum file descriptor */ + +fd_set WellKnownConnections; /* Listener mask */ +fd_set EnabledDevices; /* mask for input devices that are on */ +fd_set AllSockets; /* select on this */ +fd_set AllClients; /* available clients */ +fd_set LastSelectMask; /* mask returned from last select call */ +fd_set ClientsWithInput; /* clients with FULL requests in buffer */ +fd_set ClientsWriteBlocked; /* clients who cannot receive output */ +fd_set OutputPending; /* clients with reply/event data ready to go */ +int MaxClients = 0; +Bool NewOutputPending; /* not yet attempted to write some new output */ +Bool AnyClientsWriteBlocked; /* true if some client blocked on write */ + +static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ +Bool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or + equivalent) will send SIGCONT back. */ +Bool PartialNetwork; /* continue even if unable to bind all addrs */ +static Pid_t ParentProcess; + +static Bool debug_conns = FALSE; + +fd_set IgnoredClientsWithInput; +static fd_set GrabImperviousClients; +static fd_set SavedAllClients; +static fd_set SavedAllSockets; +static fd_set SavedClientsWithInput; +int GrabInProgress = 0; + +#if !defined(WIN32) +int *ConnectionTranslation = NULL; +#else +/* + * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is + * not even a known maximum value, so use something quite arbitrary for now. + * Do storage is a hash table of size 256. Collisions are handled in a linked + * list. + */ + +#undef MAXSOCKS +#define MAXSOCKS 500 +#undef MAXSELECT +#define MAXSELECT 500 + +struct _ct_node { + struct _ct_node *next; + int key; + int value; +}; + +struct _ct_node *ct_head[256]; + +void InitConnectionTranslation(void) +{ + memset(ct_head, 0, sizeof(ct_head)); +} + +int GetConnectionTranslation(int conn) +{ + struct _ct_node *node = ct_head[conn & 0xff]; + while (node != NULL) + { + if (node->key == conn) + return node->value; + node = node->next; + } + return 0; +} + +void SetConnectionTranslation(int conn, int client) +{ + struct _ct_node **node = ct_head + (conn & 0xff); + if (client == 0) /* remove entry */ + { + while (*node != NULL) + { + if ((*node)->key == conn) + { + struct _ct_node *temp = *node; + *node = (*node)->next; + free(temp); + return; + } + node = &((*node)->next); + } + return; + } else + { + while (*node != NULL) + { + if ((*node)->key == conn) + { + (*node)->value = client; + return; + } + node = &((*node)->next); + } + *node = malloc(sizeof(struct _ct_node)); + (*node)->next = NULL; + (*node)->key = conn; + (*node)->value = client; + return; + } +} + +void ClearConnectionTranslation(void) +{ + unsigned i; + for (i = 0; i < 256; i++) + { + struct _ct_node *node = ct_head[i]; + while (node != NULL) + { + struct _ct_node *temp = node; + node = node->next; + free(temp); + } + } +} +#endif + +static XtransConnInfo *ListenTransConns = NULL; +static int *ListenTransFds = NULL; +static int ListenTransCount; + +static void ErrorConnMax(XtransConnInfo /* trans_conn */); + +static XtransConnInfo +lookup_trans_conn (int fd) +{ + if (ListenTransFds) + { + int i; + for (i = 0; i < ListenTransCount; i++) + if (ListenTransFds[i] == fd) + return ListenTransConns[i]; + } + + return NULL; +} + +/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */ + +void +InitConnectionLimits(void) +{ + lastfdesc = -1; + +#ifndef __CYGWIN__ + +#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX) + lastfdesc = sysconf(_SC_OPEN_MAX) - 1; +#endif + +#ifdef HAS_GETDTABLESIZE + if (lastfdesc < 0) + lastfdesc = getdtablesize() - 1; +#endif + +#ifdef _NFILE + if (lastfdesc < 0) + lastfdesc = _NFILE - 1; +#endif + +#endif /* __CYGWIN__ */ + + /* This is the fallback */ + if (lastfdesc < 0) + lastfdesc = MAXSOCKS; + + if (lastfdesc > MAXSELECT) + lastfdesc = MAXSELECT; + + if (lastfdesc > MAXCLIENTS) + { + lastfdesc = MAXCLIENTS; + if (debug_conns) + ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS); + } + MaxClients = lastfdesc; + +#ifdef DEBUG + ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients); +#endif + +#if !defined(WIN32) + if (!ConnectionTranslation) + ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1)); +#else + InitConnectionTranslation(); +#endif +} + +/* + * If SIGUSR1 was set to SIG_IGN when the server started, assume that either + * + * a- The parent process is ignoring SIGUSR1 + * + * or + * + * b- The parent process is expecting a SIGUSR1 + * when the server is ready to accept connections + * + * In the first case, the signal will be harmless, in the second case, + * the signal will be quite useful. + */ +static void +InitParentProcess(void) +{ +#if !defined(WIN32) + OsSigHandlerPtr handler; + handler = OsSignal (SIGUSR1, SIG_IGN); + if ( handler == SIG_IGN) + RunFromSmartParent = TRUE; + OsSignal(SIGUSR1, handler); + ParentProcess = getppid (); +#endif +} + +void +NotifyParentProcess(void) +{ +#if !defined(WIN32) + if (RunFromSmartParent) { + if (ParentProcess > 1) { + kill (ParentProcess, SIGUSR1); + } + } + if (RunFromSigStopParent) + raise (SIGSTOP); +#endif +} + +/***************** + * CreateWellKnownSockets + * At initialization, create the sockets to listen on for new clients. + *****************/ + +void +CreateWellKnownSockets(void) +{ + int i; + int partial; + char port[20]; + + FD_ZERO(&AllSockets); + FD_ZERO(&AllClients); + FD_ZERO(&LastSelectMask); + FD_ZERO(&ClientsWithInput); + +#if !defined(WIN32) + for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0; +#else + ClearConnectionTranslation(); +#endif + + FD_ZERO (&WellKnownConnections); + + sprintf (port, "%d", atoi (display)); + + if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial, + &ListenTransCount, &ListenTransConns) >= 0) && + (ListenTransCount >= 1)) + { + if (!PartialNetwork && partial) + { + FatalError ("Failed to establish all listening sockets"); + } + else + { + ListenTransFds = malloc(ListenTransCount * sizeof (int)); + + for (i = 0; i < ListenTransCount; i++) + { + int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); + + ListenTransFds[i] = fd; + FD_SET (fd, &WellKnownConnections); + + if (!_XSERVTransIsLocal (ListenTransConns[i])) + { + DefineSelf (fd); + } + } + } + } + + if (!XFD_ANYSET (&WellKnownConnections)) + FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); +#if !defined(WIN32) + OsSignal (SIGPIPE, SIG_IGN); + OsSignal (SIGHUP, AutoResetServer); +#endif + OsSignal (SIGINT, GiveUp); + OsSignal (SIGTERM, GiveUp); + XFD_COPYSET (&WellKnownConnections, &AllSockets); + ResetHosts(display); + + InitParentProcess(); + +#ifdef XDMCP + XdmcpInit (); +#endif +} + +void +ResetWellKnownSockets (void) +{ + int i; + + ResetOsBuffers(); + + for (i = 0; i < ListenTransCount; i++) + { + int status = _XSERVTransResetListener (ListenTransConns[i]); + + if (status != TRANS_RESET_NOOP) + { + if (status == TRANS_RESET_FAILURE) + { + /* + * ListenTransConns[i] freed by xtrans. + * Remove it from out list. + */ + + FD_CLR (ListenTransFds[i], &WellKnownConnections); + ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; + ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; + ListenTransCount -= 1; + i -= 1; + } + else if (status == TRANS_RESET_NEW_FD) + { + /* + * A new file descriptor was allocated (the old one was closed) + */ + + int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); + + FD_CLR (ListenTransFds[i], &WellKnownConnections); + ListenTransFds[i] = newfd; + FD_SET(newfd, &WellKnownConnections); + } + } + } + + ResetAuthorization (); + ResetHosts(display); + /* + * restart XDMCP + */ +#ifdef XDMCP + XdmcpReset (); +#endif +} + +void +CloseWellKnownConnections(void) +{ + int i; + + for (i = 0; i < ListenTransCount; i++) + _XSERVTransClose (ListenTransConns[i]); +} + +static void +AuthAudit (ClientPtr client, Bool letin, + struct sockaddr *saddr, int len, + unsigned int proto_n, char *auth_proto, int auth_id) +{ + char addr[128]; + char *out = addr; + char client_uid_string[64]; + LocalClientCredRec *lcc; +#ifdef XSERVER_DTRACE + pid_t client_pid = -1; + zoneid_t client_zid = -1; +#endif + + if (!len) + strcpy(out, "local host"); + else + switch (saddr->sa_family) + { + case AF_UNSPEC: +#if defined(UNIXCONN) || defined(LOCALCONN) + case AF_UNIX: +#endif + strcpy(out, "local host"); + break; +#if defined(TCPCONN) || defined(STREAMSCONN) + case AF_INET: + sprintf(out, "IP %s", + inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr)); + break; +#if defined(IPv6) && defined(AF_INET6) + case AF_INET6: { + char ipaddr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr, + ipaddr, sizeof(ipaddr)); + sprintf(out, "IP %s", ipaddr); + } + break; +#endif +#endif + default: + strcpy(out, "unknown address"); + } + + if (GetLocalClientCreds(client, &lcc) != -1) { + int slen; /* length written to client_uid_string */ + + strcpy(client_uid_string, " ( "); + slen = 3; + + if (lcc->fieldsSet & LCC_UID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "uid=%ld ", (long) lcc->euid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_GID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "gid=%ld ", (long) lcc->egid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_PID_SET) { +#ifdef XSERVER_DTRACE + client_pid = lcc->pid; +#endif + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "pid=%ld ", (long) lcc->pid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_ZID_SET) { +#ifdef XSERVER_DTRACE + client_zid = lcc->zoneid; +#endif + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "zoneid=%ld ", (long) lcc->zoneid); + slen = strlen(client_uid_string); + } + + snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, + ")"); + FreeLocalClientCreds(lcc); + } + else { + client_uid_string[0] = '\0'; + } + +#ifdef XSERVER_DTRACE + XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid); +#endif + if (auditTrailLevel > 1) { + if (proto_n) + AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n", + client->index, letin ? "connected" : "rejected", addr, + client_uid_string, (int)proto_n, auth_proto, auth_id); + else + AuditF("client %d %s from %s%s\n", + client->index, letin ? "connected" : "rejected", addr, + client_uid_string); + + } +} + +XID +AuthorizationIDOfClient(ClientPtr client) +{ + if (client->osPrivate) + return ((OsCommPtr)client->osPrivate)->auth_id; + else + return None; +} + + +/***************************************************************** + * ClientAuthorized + * + * Sent by the client at connection setup: + * typedef struct _xConnClientPrefix { + * CARD8 byteOrder; + * BYTE pad; + * CARD16 majorVersion, minorVersion; + * CARD16 nbytesAuthProto; + * CARD16 nbytesAuthString; + * } xConnClientPrefix; + * + * It is hoped that eventually one protocol will be agreed upon. In the + * mean time, a server that implements a different protocol than the + * client expects, or a server that only implements the host-based + * mechanism, will simply ignore this information. + * + *****************************************************************/ + +char * +ClientAuthorized(ClientPtr client, + unsigned int proto_n, char *auth_proto, + unsigned int string_n, char *auth_string) +{ + OsCommPtr priv; + Xtransaddr *from = NULL; + int family; + int fromlen; + XID auth_id; + char *reason = NULL; + XtransConnInfo trans_conn; + + priv = (OsCommPtr)client->osPrivate; + trans_conn = priv->trans_conn; + + /* Allow any client to connect without authorization on a launchd socket, + because it is securely created -- this prevents a race condition on launch */ + if(trans_conn->flags & TRANS_NOXAUTH) { + auth_id = (XID) 0L; + } else { + auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason); + } + + if (auth_id == (XID) ~0L) + { + if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1) + { + if (InvalidHost ((struct sockaddr *) from, fromlen, client)) + AuthAudit(client, FALSE, (struct sockaddr *) from, + fromlen, proto_n, auth_proto, auth_id); + else + { + auth_id = (XID) 0; +#ifdef XSERVER_DTRACE + if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) +#else + if (auditTrailLevel > 1) +#endif + AuthAudit(client, TRUE, + (struct sockaddr *) from, fromlen, + proto_n, auth_proto, auth_id); + } + + free(from); + } + + if (auth_id == (XID) ~0L) { + if (reason) + return reason; + else + return "Client is not authorized to connect to Server"; + } + } +#ifdef XSERVER_DTRACE + else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED()) +#else + else if (auditTrailLevel > 1) +#endif + { + if (_XSERVTransGetPeerAddr (trans_conn, + &family, &fromlen, &from) != -1) + { + AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen, + proto_n, auth_proto, auth_id); + + free(from); + } + } + priv->auth_id = auth_id; + priv->conn_time = 0; + +#ifdef XDMCP + /* indicate to Xdmcp protocol that we've opened new client */ + XdmcpOpenDisplay(priv->fd); +#endif /* XDMCP */ + + XaceHook(XACE_AUTH_AVAIL, client, auth_id); + + /* At this point, if the client is authorized to change the access control + * list, we should getpeername() information, and add the client to + * the selfhosts list. It's not really the host machine, but the + * true purpose of the selfhosts list is to see who may change the + * access control list. + */ + return((char *)NULL); +} + +static ClientPtr +AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time) +{ + OsCommPtr oc; + ClientPtr client; + + if ( +#ifndef WIN32 + fd >= lastfdesc +#else + XFD_SETCOUNT(&AllClients) >= MaxClients +#endif + ) + return NullClient; + oc = malloc(sizeof(OsCommRec)); + if (!oc) + return NullClient; + oc->trans_conn = trans_conn; + oc->fd = fd; + oc->input = (ConnectionInputPtr)NULL; + oc->output = (ConnectionOutputPtr)NULL; + oc->auth_id = None; + oc->conn_time = conn_time; + if (!(client = NextAvailableClient((pointer)oc))) + { + free(oc); + return NullClient; + } + oc->local_client = ComputeLocalClient(client); +#if !defined(WIN32) + ConnectionTranslation[fd] = client->index; +#else + SetConnectionTranslation(fd, client->index); +#endif + if (GrabInProgress) + { + FD_SET(fd, &SavedAllClients); + FD_SET(fd, &SavedAllSockets); + } + else + { + FD_SET(fd, &AllClients); + FD_SET(fd, &AllSockets); + } + +#ifdef DEBUG + ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n", + client->index, fd); +#endif +#ifdef XSERVER_DTRACE + XSERVER_CLIENT_CONNECT(client->index, fd); +#endif + + return client; +} + +/***************** + * EstablishNewConnections + * If anyone is waiting on listened sockets, accept them. + * Returns a mask with indices of new clients. Updates AllClients + * and AllSockets. + *****************/ + +/*ARGSUSED*/ +Bool +EstablishNewConnections(ClientPtr clientUnused, pointer closure) +{ + fd_set readyconnections; /* set of listeners that are ready */ + int curconn; /* fd of listener that's ready */ + register int newconn; /* fd of new client */ + CARD32 connect_time; + register int i; + register ClientPtr client; + register OsCommPtr oc; + fd_set tmask; + + XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections); + XFD_COPYSET(&tmask, &readyconnections); + if (!XFD_ANYSET(&readyconnections)) + return TRUE; + connect_time = GetTimeInMillis(); + /* kill off stragglers */ + for (i=1; i<currentMaxClients; i++) + { + if ((client = clients[i])) + { + oc = (OsCommPtr)(client->osPrivate); + if ((oc && (oc->conn_time != 0) && + (connect_time - oc->conn_time) >= TimeOutValue) || + (client->noClientException != Success && !client->clientGone)) + CloseDownClient(client); + } + } +#ifndef WIN32 + for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) + { + while (readyconnections.fds_bits[i]) +#else + for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++) +#endif + { + XtransConnInfo trans_conn, new_trans_conn; + int status; + +#ifndef WIN32 + curconn = mffs (readyconnections.fds_bits[i]) - 1; + readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn); + curconn += (i * (sizeof(fd_mask)*8)); +#else + curconn = XFD_FD(&readyconnections, i); +#endif + + if ((trans_conn = lookup_trans_conn (curconn)) == NULL) + continue; + + if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL) + continue; + + newconn = _XSERVTransGetConnectionNumber (new_trans_conn); + + if (newconn < lastfdesc) + { + int clientid; +#if !defined(WIN32) + clientid = ConnectionTranslation[newconn]; +#else + clientid = GetConnectionTranslation(newconn); +#endif + if(clientid && (client = clients[clientid])) + CloseDownClient(client); + } + + _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); + + if(trans_conn->flags & TRANS_NOXAUTH) + new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; + + if (!AllocNewConnection (new_trans_conn, newconn, connect_time)) + { + ErrorConnMax(new_trans_conn); + _XSERVTransClose(new_trans_conn); + } + } +#ifndef WIN32 + } +#endif + return TRUE; +} + +#define NOROOM "Maximum number of clients reached" + +/************ + * ErrorConnMax + * Fail a connection due to lack of client or file descriptor space + ************/ + +static void +ErrorConnMax(XtransConnInfo trans_conn) +{ + int fd = _XSERVTransGetConnectionNumber (trans_conn); + xConnSetupPrefix csp; + char pad[3]; + struct iovec iov[3]; + char byteOrder = 0; + int whichbyte = 1; + struct timeval waittime; + fd_set mask; + + /* if these seems like a lot of trouble to go to, it probably is */ + waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND; + waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) * + (1000000 / MILLI_PER_SECOND); + FD_ZERO(&mask); + FD_SET(fd, &mask); + (void)Select(fd + 1, &mask, NULL, NULL, &waittime); + /* try to read the byte-order of the connection */ + (void)_XSERVTransRead(trans_conn, &byteOrder, 1); + if ((byteOrder == 'l') || (byteOrder == 'B')) + { + csp.success = xFalse; + csp.lengthReason = sizeof(NOROOM) - 1; + csp.length = (sizeof(NOROOM) + 2) >> 2; + csp.majorVersion = X_PROTOCOL; + csp.minorVersion = X_PROTOCOL_REVISION; + if (((*(char *) &whichbyte) && (byteOrder == 'B')) || + (!(*(char *) &whichbyte) && (byteOrder == 'l'))) + { + swaps(&csp.majorVersion, whichbyte); + swaps(&csp.minorVersion, whichbyte); + swaps(&csp.length, whichbyte); + } + iov[0].iov_len = sz_xConnSetupPrefix; + iov[0].iov_base = (char *) &csp; + iov[1].iov_len = csp.lengthReason; + iov[1].iov_base = NOROOM; + iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; + iov[2].iov_base = pad; + (void)_XSERVTransWritev(trans_conn, iov, 3); + } +} + +/************ + * CloseDownFileDescriptor: + * Remove this file descriptor and it's I/O buffers, etc. + ************/ + +static void +CloseDownFileDescriptor(OsCommPtr oc) +{ + int connection = oc->fd; + + if (oc->trans_conn) { + _XSERVTransDisconnect(oc->trans_conn); + _XSERVTransClose(oc->trans_conn); + } +#ifndef WIN32 + ConnectionTranslation[connection] = 0; +#else + SetConnectionTranslation(connection, 0); +#endif + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + FD_CLR(connection, &ClientsWithInput); + FD_CLR(connection, &GrabImperviousClients); + if (GrabInProgress) + { + FD_CLR(connection, &SavedAllSockets); + FD_CLR(connection, &SavedAllClients); + FD_CLR(connection, &SavedClientsWithInput); + } + FD_CLR(connection, &ClientsWriteBlocked); + if (!XFD_ANYSET(&ClientsWriteBlocked)) + AnyClientsWriteBlocked = FALSE; + FD_CLR(connection, &OutputPending); +} + +/***************** + * CheckConnections + * Some connection has died, go find which one and shut it down + * The file descriptor has been closed, but is still in AllClients. + * If would truly be wonderful if select() would put the bogus + * file descriptors in the exception mask, but nooooo. So we have + * to check each and every socket individually. + *****************/ + +void +CheckConnections(void) +{ +#ifndef WIN32 + fd_mask mask; +#endif + fd_set tmask; + int curclient, curoff; + int i; + struct timeval notime; + int r; +#ifdef WIN32 + fd_set savedAllClients; +#endif + + notime.tv_sec = 0; + notime.tv_usec = 0; + +#ifndef WIN32 + for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++) + { + mask = AllClients.fds_bits[i]; + while (mask) + { + curoff = mffs (mask) - 1; + curclient = curoff + (i * (sizeof(fd_mask)*8)); + FD_ZERO(&tmask); + FD_SET(curclient, &tmask); + do { + r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime); + } while (r < 0 && (errno == EINTR || errno == EAGAIN)); + if (r < 0) + if (ConnectionTranslation[curclient] > 0) + CloseDownClient(clients[ConnectionTranslation[curclient]]); + mask &= ~((fd_mask)1 << curoff); + } + } +#else + XFD_COPYSET(&AllClients, &savedAllClients); + for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++) + { + curclient = XFD_FD(&savedAllClients, i); + FD_ZERO(&tmask); + FD_SET(curclient, &tmask); + do { + r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime); + } while (r < 0 && (errno == EINTR || errno == EAGAIN)); + if (r < 0) + if (GetConnectionTranslation(curclient) > 0) + CloseDownClient(clients[GetConnectionTranslation(curclient)]); + } +#endif +} + + +/***************** + * CloseDownConnection + * Delete client from AllClients and free resources + *****************/ + +void +CloseDownConnection(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + + if (FlushCallback) + CallCallbacks(&FlushCallback, NULL); + + if (oc->output && oc->output->count) + FlushClient(client, oc, (char *)NULL, 0); +#ifdef XDMCP + XdmcpCloseDisplay(oc->fd); +#endif + CloseDownFileDescriptor(oc); + FreeOsBuffers(oc); + free(client->osPrivate); + client->osPrivate = (pointer)NULL; + if (auditTrailLevel > 1) + AuditF("client %d disconnected\n", client->index); +} + +void +AddGeneralSocket(int fd) +{ + FD_SET(fd, &AllSockets); + if (GrabInProgress) + FD_SET(fd, &SavedAllSockets); +} + +void +AddEnabledDevice(int fd) +{ + FD_SET(fd, &EnabledDevices); + AddGeneralSocket(fd); +} + +void +RemoveGeneralSocket(int fd) +{ + FD_CLR(fd, &AllSockets); + if (GrabInProgress) + FD_CLR(fd, &SavedAllSockets); +} + +void +RemoveEnabledDevice(int fd) +{ + FD_CLR(fd, &EnabledDevices); + RemoveGeneralSocket(fd); +} + +/***************** + * OnlyListenToOneClient: + * Only accept requests from one client. Continue to handle new + * connections, but don't take any protocol requests from the new + * ones. Note that if GrabInProgress is set, EstablishNewConnections + * needs to put new clients into SavedAllSockets and SavedAllClients. + * Note also that there is no timeout for this in the protocol. + * This routine is "undone" by ListenToAllClients() + *****************/ + +int +OnlyListenToOneClient(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int rc, connection = oc->fd; + + rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess); + if (rc != Success) + return rc; + + if (! GrabInProgress) + { + XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput); + XFD_ANDSET(&ClientsWithInput, + &ClientsWithInput, &GrabImperviousClients); + if (FD_ISSET(connection, &SavedClientsWithInput)) + { + FD_CLR(connection, &SavedClientsWithInput); + FD_SET(connection, &ClientsWithInput); + } + XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients); + XFD_COPYSET(&AllSockets, &SavedAllSockets); + XFD_COPYSET(&AllClients, &SavedAllClients); + XFD_UNSET(&AllSockets, &AllClients); + XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients); + FD_SET(connection, &AllClients); + XFD_ORSET(&AllSockets, &AllSockets, &AllClients); + GrabInProgress = client->index; + } + return rc; +} + +/**************** + * ListenToAllClients: + * Undoes OnlyListentToOneClient() + ****************/ + +void +ListenToAllClients(void) +{ + if (GrabInProgress) + { + XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets); + XFD_ORSET(&AllClients, &AllClients, &SavedAllClients); + XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput); + GrabInProgress = 0; + } +} + +/**************** + * IgnoreClient + * Removes one client from input masks. + * Must have cooresponding call to AttendClient. + ****************/ + +void +IgnoreClient (ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + client->ignoreCount++; + if (client->ignoreCount > 1) + return; + + isItTimeToYield = TRUE; + if (!GrabInProgress || FD_ISSET(connection, &AllClients)) + { + if (FD_ISSET (connection, &ClientsWithInput)) + FD_SET(connection, &IgnoredClientsWithInput); + else + FD_CLR(connection, &IgnoredClientsWithInput); + FD_CLR(connection, &ClientsWithInput); + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + FD_CLR(connection, &LastSelectMask); + } + else + { + if (FD_ISSET (connection, &SavedClientsWithInput)) + FD_SET(connection, &IgnoredClientsWithInput); + else + FD_CLR(connection, &IgnoredClientsWithInput); + FD_CLR(connection, &SavedClientsWithInput); + FD_CLR(connection, &SavedAllSockets); + FD_CLR(connection, &SavedAllClients); + } +} + +/**************** + * AttendClient + * Adds one client back into the input masks. + ****************/ + +void +AttendClient (ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + client->ignoreCount--; + if (client->ignoreCount) + return; + + if (!GrabInProgress || GrabInProgress == client->index || + FD_ISSET(connection, &GrabImperviousClients)) + { + FD_SET(connection, &AllClients); + FD_SET(connection, &AllSockets); + FD_SET(connection, &LastSelectMask); + if (FD_ISSET (connection, &IgnoredClientsWithInput)) + FD_SET(connection, &ClientsWithInput); + } + else + { + FD_SET(connection, &SavedAllClients); + FD_SET(connection, &SavedAllSockets); + if (FD_ISSET(connection, &IgnoredClientsWithInput)) + FD_SET(connection, &SavedClientsWithInput); + } +} + +/* make client impervious to grabs; assume only executing client calls this */ + +void +MakeClientGrabImpervious(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + FD_SET(connection, &GrabImperviousClients); + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = CLIENT_IMPERVIOUS; + CallCallbacks(&ServerGrabCallback, &grabinfo); + } +} + +/* make client pervious to grabs; assume only executing client calls this */ + +void +MakeClientGrabPervious(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + FD_CLR(connection, &GrabImperviousClients); + if (GrabInProgress && (GrabInProgress != client->index)) + { + if (FD_ISSET(connection, &ClientsWithInput)) + { + FD_SET(connection, &SavedClientsWithInput); + FD_CLR(connection, &ClientsWithInput); + } + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + isItTimeToYield = TRUE; + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = CLIENT_PERVIOUS; + CallCallbacks(&ServerGrabCallback, &grabinfo); + } +} + +#ifdef XQUARTZ +/* Add a fd (from launchd) to our listeners */ +void ListenOnOpenFD(int fd, int noxauth) { + char port[256]; + XtransConnInfo ciptr; + const char *display_env = getenv("DISPLAY"); + + if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) { + /* Make the path the launchd socket if our DISPLAY is set right */ + strcpy(port, display_env); + } else { + /* Just some default so things don't break and die. */ + sprintf(port, ":%d", atoi(display)); + } + + /* Make our XtransConnInfo + * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c + */ + ciptr = _XSERVTransReopenCOTSServer(5, fd, port); + if(ciptr == NULL) { + ErrorF("Got NULL while trying to Reopen launchd port.\n"); + return; + } + + if(noxauth) + ciptr->flags = ciptr->flags | TRANS_NOXAUTH; + + /* Allocate space to store it */ + ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int)); + ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo)); + + /* Store it */ + ListenTransConns[ListenTransCount] = ciptr; + ListenTransFds[ListenTransCount] = fd; + + FD_SET(fd, &WellKnownConnections); + FD_SET(fd, &AllSockets); + + /* Increment the count */ + ListenTransCount++; + + /* This *might* not be needed... /shrug */ + ResetAuthorization(); + ResetHosts(display); +#ifdef XDMCP + XdmcpReset(); +#endif +} + +#endif diff --git a/xorg-server/randr/rrdispatch.c b/xorg-server/randr/rrdispatch.c index ac4d2acc1..213550475 100644 --- a/xorg-server/randr/rrdispatch.c +++ b/xorg-server/randr/rrdispatch.c @@ -146,7 +146,7 @@ ProcRRSelectInput (ClientPtr client) /* * Now see if the client needs an event */ - if (pScrPriv && (pRREvent->mask & RRScreenChangeNotifyMask)) + if (pScrPriv) { pTimes = &((RRTimesPtr) (pRRClient + 1))[pScreen->myNum]; if (CompareTimeStamps (pTimes->setTime, @@ -154,7 +154,35 @@ ProcRRSelectInput (ClientPtr client) CompareTimeStamps (pTimes->configTime, pScrPriv->lastConfigTime) != 0) { - RRDeliverScreenEvent (client, pWin, pScreen); + if (pRREvent->mask & RRScreenChangeNotifyMask) + { + RRDeliverScreenEvent (client, pWin, pScreen); + } + + if (pRREvent->mask & RRCrtcChangeNotifyMask) + { + int i; + + for (i = 0; i < pScrPriv->numCrtcs; i++) + { + RRDeliverCrtcEvent (client, pWin, pScrPriv->crtcs[i]); + } + } + + if (pRREvent->mask & RROutputChangeNotifyMask) + { + int i; + + for (i = 0; i < pScrPriv->numOutputs; i++) + { + RRDeliverOutputEvent (client, pWin, pScrPriv->outputs[i]); + } + } + + /* We don't check for RROutputPropertyNotifyMask, as randrproto.txt doesn't + * say if there ought to be notifications of changes to output properties + * if those changes occurred before the time RRSelectInput is called. + */ } } } diff --git a/xorg-server/render/render.c b/xorg-server/render/render.c index c5da6d78f..ebb1d630a 100644 --- a/xorg-server/render/render.c +++ b/xorg-server/render/render.c @@ -1705,11 +1705,17 @@ ProcRenderCreateCursor (ClientPtr client) GetColor(twocolor[1], 0), &pCursor, client, stuff->cid); if (rc != Success) - return rc; - if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) - return BadAlloc; + goto bail; + if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) { + rc = BadAlloc; + goto bail; + } return Success; +bail: + free(srcbits); + free(mskbits); + return rc; } static int diff --git a/xorg-server/xkeyboard-config/rules/compat/variantsMapping.lst b/xorg-server/xkeyboard-config/rules/compat/variantsMapping.lst index be2a2bc40..d88336fce 100644 --- a/xorg-server/xkeyboard-config/rules/compat/variantsMapping.lst +++ b/xorg-server/xkeyboard-config/rules/compat/variantsMapping.lst @@ -13,7 +13,6 @@ guj basic in guj gur basic in guru ie laptop ie basic ie CloGaelachLaptop ie CloGaelach -il si1452 ie basic in urd in urd-phonetic iu basic ca ike lo basic la basic diff --git a/xorg-server/xkeyboard-config/symbols/hu b/xorg-server/xkeyboard-config/symbols/hu index 16631b7ad..21913a330 100644 --- a/xorg-server/xkeyboard-config/symbols/hu +++ b/xorg-server/xkeyboard-config/symbols/hu @@ -425,7 +425,7 @@ xkb_symbols "def_common" { key <AB06> { [ n, N, braceright ] }; key <AB07> { [ m, M, less ] }; key <AB08> { [ comma, question, semicolon ] }; - key <AB09> { [ period, colon, ellipsis ] }; + key <AB09> { [ period, colon, greater ] }; key <AB10> { [ minus, underscore, asterisk ] }; }; |