e4d11e58ce
This was an attempt to avoid scratch gc creation and validation for paintwin because that was expensive. This is not the case in current servers, and the danger of failure to implement it correctly (as seen in all previous implementations) is high enough to justify removing it. No performance difference detected with x11perf -create -move -resize -circulate on Xvfb. Leave the screen hooks for PaintWindow* in for now to avoid ABI change.
466 lines
14 KiB
C
466 lines
14 KiB
C
/*
|
|
* Copyright © 2006 Sun Microsystems
|
|
*
|
|
* 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 Sun Microsystems not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. Sun Microsystems makes no
|
|
* representations about the suitability of this software for any purpose. It
|
|
* is provided "as is" without express or implied warranty.
|
|
*
|
|
* SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Copyright © 2003 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 "compint.h"
|
|
|
|
int CompScreenPrivateIndex;
|
|
int CompWindowPrivateIndex;
|
|
int CompSubwindowsPrivateIndex;
|
|
static int CompGeneration;
|
|
|
|
|
|
static Bool
|
|
compCloseScreen (int index, ScreenPtr pScreen)
|
|
{
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
Bool ret;
|
|
|
|
xfree (cs->alternateVisuals);
|
|
|
|
pScreen->CloseScreen = cs->CloseScreen;
|
|
pScreen->BlockHandler = cs->BlockHandler;
|
|
pScreen->InstallColormap = cs->InstallColormap;
|
|
pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
|
|
pScreen->ReparentWindow = cs->ReparentWindow;
|
|
pScreen->MoveWindow = cs->MoveWindow;
|
|
pScreen->ResizeWindow = cs->ResizeWindow;
|
|
pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
|
|
|
|
pScreen->ClipNotify = cs->ClipNotify;
|
|
pScreen->UnrealizeWindow = cs->UnrealizeWindow;
|
|
pScreen->RealizeWindow = cs->RealizeWindow;
|
|
pScreen->DestroyWindow = cs->DestroyWindow;
|
|
pScreen->CreateWindow = cs->CreateWindow;
|
|
pScreen->CopyWindow = cs->CopyWindow;
|
|
pScreen->PositionWindow = cs->PositionWindow;
|
|
|
|
deleteCompOverlayClientsForScreen(pScreen);
|
|
|
|
/*
|
|
** Note: no need to call DeleteWindow; the server has
|
|
** already destroyed it.
|
|
*/
|
|
cs->pOverlayWin = NULL;
|
|
|
|
xfree (cs);
|
|
pScreen->devPrivates[CompScreenPrivateIndex].ptr = 0;
|
|
ret = (*pScreen->CloseScreen) (index, pScreen);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
compInstallColormap (ColormapPtr pColormap)
|
|
{
|
|
VisualPtr pVisual = pColormap->pVisual;
|
|
ScreenPtr pScreen = pColormap->pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
int a;
|
|
|
|
for (a = 0; a < cs->numAlternateVisuals; a++)
|
|
if (pVisual->vid == cs->alternateVisuals[a])
|
|
return;
|
|
pScreen->InstallColormap = cs->InstallColormap;
|
|
(*pScreen->InstallColormap) (pColormap);
|
|
cs->InstallColormap = pScreen->InstallColormap;
|
|
pScreen->InstallColormap = compInstallColormap;
|
|
}
|
|
|
|
/* Fake backing store via automatic redirection */
|
|
static Bool
|
|
compChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
Bool ret;
|
|
|
|
pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
|
|
ret = pScreen->ChangeWindowAttributes(pWin, mask);
|
|
|
|
if (ret && (mask & CWBackingStore)) {
|
|
if (pWin->backingStore != NotUseful) {
|
|
compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
|
|
pWin->backStorage = TRUE;
|
|
} else {
|
|
compUnredirectWindow(serverClient, pWin,
|
|
CompositeRedirectAutomatic);
|
|
pWin->backStorage = FALSE;
|
|
}
|
|
}
|
|
|
|
pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
compScreenUpdate (ScreenPtr pScreen)
|
|
{
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
|
|
compCheckTree (pScreen);
|
|
if (cs->damaged)
|
|
{
|
|
compWindowUpdate (WindowTable[pScreen->myNum]);
|
|
cs->damaged = FALSE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
compBlockHandler (int i,
|
|
pointer blockData,
|
|
pointer pTimeout,
|
|
pointer pReadmask)
|
|
{
|
|
ScreenPtr pScreen = screenInfo.screens[i];
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
|
|
pScreen->BlockHandler = cs->BlockHandler;
|
|
compScreenUpdate (pScreen);
|
|
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
|
|
cs->BlockHandler = pScreen->BlockHandler;
|
|
pScreen->BlockHandler = compBlockHandler;
|
|
}
|
|
|
|
/*
|
|
* Add alternate visuals -- always expose an ARGB32 and RGB24 visual
|
|
*/
|
|
|
|
static DepthPtr
|
|
compFindVisuallessDepth (ScreenPtr pScreen, int d)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < pScreen->numDepths; i++)
|
|
{
|
|
DepthPtr depth = &pScreen->allowedDepths[i];
|
|
if (depth->depth == d)
|
|
{
|
|
/*
|
|
* Make sure it doesn't have visuals already
|
|
*/
|
|
if (depth->numVids)
|
|
return 0;
|
|
/*
|
|
* looks fine
|
|
*/
|
|
return depth;
|
|
}
|
|
}
|
|
/*
|
|
* If there isn't one, then it's gonna be hard to have
|
|
* an associated visual
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Add a list of visual IDs to the list of visuals to implicitly redirect.
|
|
*/
|
|
static Bool
|
|
compRegisterAlternateVisuals (CompScreenPtr cs, VisualID *vids, int nVisuals)
|
|
{
|
|
VisualID *p;
|
|
|
|
p = xrealloc(cs->alternateVisuals,
|
|
sizeof(VisualID) * (cs->numAlternateVisuals + nVisuals));
|
|
if(p == NULL)
|
|
return FALSE;
|
|
|
|
memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals);
|
|
|
|
cs->alternateVisuals = p;
|
|
cs->numAlternateVisuals += nVisuals;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
_X_EXPORT
|
|
Bool CompositeRegisterAlternateVisuals (ScreenPtr pScreen, VisualID *vids,
|
|
int nVisuals)
|
|
{
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
return compRegisterAlternateVisuals(cs, vids, nVisuals);
|
|
}
|
|
|
|
typedef struct _alternateVisual {
|
|
int depth;
|
|
CARD32 format;
|
|
} CompAlternateVisual;
|
|
|
|
static CompAlternateVisual altVisuals[] = {
|
|
#if COMP_INCLUDE_RGB24_VISUAL
|
|
{ 24, PICT_r8g8b8 },
|
|
#endif
|
|
{ 32, PICT_a8r8g8b8 },
|
|
};
|
|
|
|
static const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) /
|
|
sizeof(CompAlternateVisual);
|
|
|
|
static Bool
|
|
compAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs,
|
|
CompAlternateVisual *alt)
|
|
{
|
|
VisualPtr visual, visuals;
|
|
int i;
|
|
int numVisuals;
|
|
XID *installedCmaps;
|
|
ColormapPtr installedCmap;
|
|
int numInstalledCmaps;
|
|
DepthPtr depth;
|
|
PictFormatPtr pPictFormat;
|
|
VisualID *vid;
|
|
unsigned long alphaMask;
|
|
|
|
/*
|
|
* The ARGB32 visual is always available. Other alternate depth visuals
|
|
* are only provided if their depth is less than the root window depth.
|
|
* There's no deep reason for this.
|
|
*/
|
|
if (alt->depth >= pScreen->rootDepth && alt->depth != 32)
|
|
return FALSE;
|
|
|
|
depth = compFindVisuallessDepth (pScreen, alt->depth);
|
|
if (!depth)
|
|
/* alt->depth doesn't exist or already has alternate visuals. */
|
|
return TRUE;
|
|
|
|
pPictFormat = PictureMatchFormat (pScreen, alt->depth, alt->format);
|
|
if (!pPictFormat)
|
|
return FALSE;
|
|
|
|
vid = xalloc(sizeof(VisualID));
|
|
if (!vid)
|
|
return FALSE;
|
|
|
|
/* Find the installed colormaps */
|
|
installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID));
|
|
if (!installedCmaps) {
|
|
xfree(vid);
|
|
return FALSE;
|
|
}
|
|
numInstalledCmaps = pScreen->ListInstalledColormaps(pScreen,
|
|
installedCmaps);
|
|
|
|
/* realloc the visual array to fit the new one in place */
|
|
numVisuals = pScreen->numVisuals;
|
|
visuals = xrealloc(pScreen->visuals, (numVisuals + 1) * sizeof(VisualRec));
|
|
if (!visuals) {
|
|
xfree(vid);
|
|
xfree(installedCmaps);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Fix up any existing installed colormaps -- we'll assume that
|
|
* the only ones created so far have been installed. If this
|
|
* isn't true, we'll have to walk the resource database looking
|
|
* for all colormaps.
|
|
*/
|
|
for (i = 0; i < numInstalledCmaps; i++) {
|
|
int j;
|
|
|
|
installedCmap = LookupIDByType (installedCmaps[i], RT_COLORMAP);
|
|
if (!installedCmap)
|
|
continue;
|
|
j = installedCmap->pVisual - pScreen->visuals;
|
|
installedCmap->pVisual = &visuals[j];
|
|
}
|
|
|
|
xfree(installedCmaps);
|
|
|
|
pScreen->visuals = visuals;
|
|
visual = visuals + pScreen->numVisuals; /* the new one */
|
|
pScreen->numVisuals++;
|
|
|
|
/* Initialize the visual */
|
|
visual->vid = FakeClientID (0);
|
|
visual->bitsPerRGBValue = 8;
|
|
if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) {
|
|
visual->class = PseudoColor;
|
|
visual->nplanes = PICT_FORMAT_BPP(alt->format);
|
|
visual->ColormapEntries = 1 << visual->nplanes;
|
|
} else {
|
|
DirectFormatRec *direct = &pPictFormat->direct;
|
|
visual->class = TrueColor;
|
|
visual->redMask = ((unsigned long)direct->redMask) << direct->red;
|
|
visual->greenMask = ((unsigned long)direct->greenMask) << direct->green;
|
|
visual->blueMask = ((unsigned long)direct->blueMask) << direct->blue;
|
|
alphaMask = ((unsigned long)direct->alphaMask) << direct->alpha;
|
|
visual->offsetRed = direct->red;
|
|
visual->offsetGreen = direct->green;
|
|
visual->offsetBlue = direct->blue;
|
|
/*
|
|
* Include A bits in this (unlike GLX which includes only RGB)
|
|
* This lets DIX compute suitable masks for colormap allocations
|
|
*/
|
|
visual->nplanes = Ones (visual->redMask |
|
|
visual->greenMask |
|
|
visual->blueMask |
|
|
alphaMask);
|
|
/* find widest component */
|
|
visual->ColormapEntries = (1 << max (Ones (visual->redMask),
|
|
max (Ones (visual->greenMask),
|
|
Ones (visual->blueMask))));
|
|
}
|
|
|
|
/* remember the visual ID to detect auto-update windows */
|
|
compRegisterAlternateVisuals(cs, &visual->vid, 1);
|
|
|
|
/* Fix up the depth */
|
|
*vid = visual->vid;
|
|
depth->numVids = 1;
|
|
depth->vids = vid;
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
compAddAlternateVisuals (ScreenPtr pScreen, CompScreenPtr cs)
|
|
{
|
|
int alt, ret = 0;
|
|
|
|
for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++)
|
|
ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt);
|
|
|
|
return !!ret;
|
|
}
|
|
|
|
Bool
|
|
compScreenInit (ScreenPtr pScreen)
|
|
{
|
|
CompScreenPtr cs;
|
|
|
|
if (CompGeneration != serverGeneration)
|
|
{
|
|
CompScreenPrivateIndex = AllocateScreenPrivateIndex ();
|
|
if (CompScreenPrivateIndex == -1)
|
|
return FALSE;
|
|
CompWindowPrivateIndex = AllocateWindowPrivateIndex ();
|
|
if (CompWindowPrivateIndex == -1)
|
|
return FALSE;
|
|
CompSubwindowsPrivateIndex = AllocateWindowPrivateIndex ();
|
|
if (CompSubwindowsPrivateIndex == -1)
|
|
return FALSE;
|
|
CompGeneration = serverGeneration;
|
|
}
|
|
if (!AllocateWindowPrivate (pScreen, CompWindowPrivateIndex, 0))
|
|
return FALSE;
|
|
|
|
if (!AllocateWindowPrivate (pScreen, CompSubwindowsPrivateIndex, 0))
|
|
return FALSE;
|
|
|
|
if (GetCompScreen (pScreen))
|
|
return TRUE;
|
|
cs = (CompScreenPtr) xalloc (sizeof (CompScreenRec));
|
|
if (!cs)
|
|
return FALSE;
|
|
|
|
cs->damaged = FALSE;
|
|
cs->pOverlayWin = NULL;
|
|
cs->pOverlayClients = NULL;
|
|
|
|
cs->numAlternateVisuals = 0;
|
|
cs->alternateVisuals = NULL;
|
|
|
|
if (!compAddAlternateVisuals (pScreen, cs))
|
|
{
|
|
xfree (cs);
|
|
return FALSE;
|
|
}
|
|
|
|
cs->PositionWindow = pScreen->PositionWindow;
|
|
pScreen->PositionWindow = compPositionWindow;
|
|
|
|
cs->CopyWindow = pScreen->CopyWindow;
|
|
pScreen->CopyWindow = compCopyWindow;
|
|
|
|
cs->CreateWindow = pScreen->CreateWindow;
|
|
pScreen->CreateWindow = compCreateWindow;
|
|
|
|
cs->DestroyWindow = pScreen->DestroyWindow;
|
|
pScreen->DestroyWindow = compDestroyWindow;
|
|
|
|
cs->RealizeWindow = pScreen->RealizeWindow;
|
|
pScreen->RealizeWindow = compRealizeWindow;
|
|
|
|
cs->UnrealizeWindow = pScreen->UnrealizeWindow;
|
|
pScreen->UnrealizeWindow = compUnrealizeWindow;
|
|
|
|
cs->ClipNotify = pScreen->ClipNotify;
|
|
pScreen->ClipNotify = compClipNotify;
|
|
|
|
cs->MoveWindow = pScreen->MoveWindow;
|
|
pScreen->MoveWindow = compMoveWindow;
|
|
|
|
cs->ResizeWindow = pScreen->ResizeWindow;
|
|
pScreen->ResizeWindow = compResizeWindow;
|
|
|
|
cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
|
|
pScreen->ChangeBorderWidth = compChangeBorderWidth;
|
|
|
|
cs->ReparentWindow = pScreen->ReparentWindow;
|
|
pScreen->ReparentWindow = compReparentWindow;
|
|
|
|
cs->InstallColormap = pScreen->InstallColormap;
|
|
pScreen->InstallColormap = compInstallColormap;
|
|
|
|
cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
|
|
pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
|
|
|
|
cs->BlockHandler = pScreen->BlockHandler;
|
|
pScreen->BlockHandler = compBlockHandler;
|
|
|
|
cs->CloseScreen = pScreen->CloseScreen;
|
|
pScreen->CloseScreen = compCloseScreen;
|
|
|
|
pScreen->devPrivates[CompScreenPrivateIndex].ptr = (pointer) cs;
|
|
|
|
RegisterRealChildHeadProc(CompositeRealChildHead);
|
|
|
|
return TRUE;
|
|
}
|