compinit.c revision 6747b715
105b261ecSmrg/*
26747b715Smrg * Copyright © 2006 Sun Microsystems, Inc.  All rights reserved.
305b261ecSmrg *
46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
56747b715Smrg * copy of this software and associated documentation files (the "Software"),
66747b715Smrg * to deal in the Software without restriction, including without limitation
76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
96747b715Smrg * Software is furnished to do so, subject to the following conditions:
1005b261ecSmrg *
116747b715Smrg * The above copyright notice and this permission notice (including the next
126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
136747b715Smrg * Software.
146747b715Smrg *
156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
216747b715Smrg * DEALINGS IN THE SOFTWARE.
2205b261ecSmrg *
2305b261ecSmrg * Copyright © 2003 Keith Packard
2405b261ecSmrg *
2505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
2605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
2705b261ecSmrg * the above copyright notice appear in all copies and that both that
2805b261ecSmrg * copyright notice and this permission notice appear in supporting
2905b261ecSmrg * documentation, and that the name of Keith Packard not be used in
3005b261ecSmrg * advertising or publicity pertaining to distribution of the software without
3105b261ecSmrg * specific, written prior permission.  Keith Packard makes no
3205b261ecSmrg * representations about the suitability of this software for any purpose.  It
3305b261ecSmrg * is provided "as is" without express or implied warranty.
3405b261ecSmrg *
3505b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
3605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
3705b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
3805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
3905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
4005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
4205b261ecSmrg */
4305b261ecSmrg
4405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
4505b261ecSmrg#include <dix-config.h>
4605b261ecSmrg#endif
4705b261ecSmrg
4805b261ecSmrg#include "compint.h"
496747b715Smrg#include "compositeext.h"
5005b261ecSmrg
516747b715SmrgDevPrivateKeyRec CompScreenPrivateKeyRec;
526747b715SmrgDevPrivateKeyRec CompWindowPrivateKeyRec;
536747b715SmrgDevPrivateKeyRec CompSubwindowsPrivateKeyRec;
5405b261ecSmrg
5505b261ecSmrgstatic Bool
5605b261ecSmrgcompCloseScreen (int index, ScreenPtr pScreen)
5705b261ecSmrg{
5805b261ecSmrg    CompScreenPtr   cs = GetCompScreen (pScreen);
5905b261ecSmrg    Bool	    ret;
6005b261ecSmrg
616747b715Smrg    free(cs->alternateVisuals);
6205b261ecSmrg
6305b261ecSmrg    pScreen->CloseScreen = cs->CloseScreen;
6405b261ecSmrg    pScreen->BlockHandler = cs->BlockHandler;
6505b261ecSmrg    pScreen->InstallColormap = cs->InstallColormap;
664642e01fSmrg    pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
6705b261ecSmrg    pScreen->ReparentWindow = cs->ReparentWindow;
686747b715Smrg    pScreen->ConfigNotify = cs->ConfigNotify;
6905b261ecSmrg    pScreen->MoveWindow = cs->MoveWindow;
7005b261ecSmrg    pScreen->ResizeWindow = cs->ResizeWindow;
7105b261ecSmrg    pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
7205b261ecSmrg
7305b261ecSmrg    pScreen->ClipNotify = cs->ClipNotify;
7405b261ecSmrg    pScreen->UnrealizeWindow = cs->UnrealizeWindow;
7505b261ecSmrg    pScreen->RealizeWindow = cs->RealizeWindow;
7605b261ecSmrg    pScreen->DestroyWindow = cs->DestroyWindow;
7705b261ecSmrg    pScreen->CreateWindow = cs->CreateWindow;
7805b261ecSmrg    pScreen->CopyWindow = cs->CopyWindow;
7905b261ecSmrg    pScreen->PositionWindow = cs->PositionWindow;
8005b261ecSmrg
816747b715Smrg    free(cs);
824642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, NULL);
8305b261ecSmrg    ret = (*pScreen->CloseScreen) (index, pScreen);
8405b261ecSmrg
8505b261ecSmrg    return ret;
8605b261ecSmrg}
8705b261ecSmrg
8805b261ecSmrgstatic void
8905b261ecSmrgcompInstallColormap (ColormapPtr pColormap)
9005b261ecSmrg{
9105b261ecSmrg    VisualPtr	    pVisual = pColormap->pVisual;
9205b261ecSmrg    ScreenPtr	    pScreen = pColormap->pScreen;
9305b261ecSmrg    CompScreenPtr   cs = GetCompScreen (pScreen);
9405b261ecSmrg    int		    a;
9505b261ecSmrg
9605b261ecSmrg    for (a = 0; a < cs->numAlternateVisuals; a++)
9705b261ecSmrg	if (pVisual->vid == cs->alternateVisuals[a])
9805b261ecSmrg	    return;
9905b261ecSmrg    pScreen->InstallColormap = cs->InstallColormap;
10005b261ecSmrg    (*pScreen->InstallColormap) (pColormap);
10105b261ecSmrg    cs->InstallColormap = pScreen->InstallColormap;
10205b261ecSmrg    pScreen->InstallColormap = compInstallColormap;
10305b261ecSmrg}
10405b261ecSmrg
1054642e01fSmrg/* Fake backing store via automatic redirection */
1064642e01fSmrgstatic Bool
1074642e01fSmrgcompChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
1084642e01fSmrg{
1094642e01fSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
1104642e01fSmrg    CompScreenPtr cs = GetCompScreen (pScreen);
1114642e01fSmrg    Bool ret;
1124642e01fSmrg
1134642e01fSmrg    pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
1144642e01fSmrg    ret = pScreen->ChangeWindowAttributes(pWin, mask);
1154642e01fSmrg
1164642e01fSmrg    if (ret && (mask & CWBackingStore) &&
1174642e01fSmrg	    pScreen->backingStoreSupport != NotUseful) {
1184642e01fSmrg	if (pWin->backingStore != NotUseful) {
1194642e01fSmrg	    compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
1204642e01fSmrg	    pWin->backStorage = (pointer) (intptr_t) 1;
1214642e01fSmrg	} else {
1224642e01fSmrg	    compUnredirectWindow(serverClient, pWin,
1234642e01fSmrg				 CompositeRedirectAutomatic);
1244642e01fSmrg	    pWin->backStorage = NULL;
1254642e01fSmrg	}
1264642e01fSmrg    }
1274642e01fSmrg
1284642e01fSmrg    pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
1294642e01fSmrg
1304642e01fSmrg    return ret;
1314642e01fSmrg}
1324642e01fSmrg
13305b261ecSmrgstatic void
13405b261ecSmrgcompScreenUpdate (ScreenPtr pScreen)
13505b261ecSmrg{
13605b261ecSmrg    CompScreenPtr   cs = GetCompScreen (pScreen);
13705b261ecSmrg
13805b261ecSmrg    compCheckTree (pScreen);
13905b261ecSmrg    if (cs->damaged)
14005b261ecSmrg    {
1416747b715Smrg	compWindowUpdate (pScreen->root);
14205b261ecSmrg	cs->damaged = FALSE;
14305b261ecSmrg    }
14405b261ecSmrg}
14505b261ecSmrg
14605b261ecSmrgstatic void
14705b261ecSmrgcompBlockHandler (int	    i,
14805b261ecSmrg		  pointer   blockData,
14905b261ecSmrg		  pointer   pTimeout,
15005b261ecSmrg		  pointer   pReadmask)
15105b261ecSmrg{
15205b261ecSmrg    ScreenPtr	    pScreen = screenInfo.screens[i];
15305b261ecSmrg    CompScreenPtr   cs = GetCompScreen (pScreen);
15405b261ecSmrg
15505b261ecSmrg    pScreen->BlockHandler = cs->BlockHandler;
15605b261ecSmrg    compScreenUpdate (pScreen);
15705b261ecSmrg    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
15805b261ecSmrg    cs->BlockHandler = pScreen->BlockHandler;
15905b261ecSmrg    pScreen->BlockHandler = compBlockHandler;
16005b261ecSmrg}
16105b261ecSmrg
16205b261ecSmrg/*
16305b261ecSmrg * Add alternate visuals -- always expose an ARGB32 and RGB24 visual
16405b261ecSmrg */
16505b261ecSmrg
16605b261ecSmrgstatic DepthPtr
16705b261ecSmrgcompFindVisuallessDepth (ScreenPtr pScreen, int d)
16805b261ecSmrg{
16905b261ecSmrg    int		i;
17005b261ecSmrg
17105b261ecSmrg    for (i = 0; i < pScreen->numDepths; i++)
17205b261ecSmrg    {
17305b261ecSmrg	DepthPtr    depth = &pScreen->allowedDepths[i];
17405b261ecSmrg	if (depth->depth == d)
17505b261ecSmrg	{
17605b261ecSmrg	    /*
17705b261ecSmrg	     * Make sure it doesn't have visuals already
17805b261ecSmrg	     */
17905b261ecSmrg	    if (depth->numVids)
18005b261ecSmrg		return 0;
18105b261ecSmrg	    /*
18205b261ecSmrg	     * looks fine
18305b261ecSmrg	     */
18405b261ecSmrg	    return depth;
18505b261ecSmrg	}
18605b261ecSmrg    }
18705b261ecSmrg    /*
18805b261ecSmrg     * If there isn't one, then it's gonna be hard to have
18905b261ecSmrg     * an associated visual
19005b261ecSmrg     */
19105b261ecSmrg    return 0;
19205b261ecSmrg}
19305b261ecSmrg
19405b261ecSmrg/*
19505b261ecSmrg * Add a list of visual IDs to the list of visuals to implicitly redirect.
19605b261ecSmrg */
19705b261ecSmrgstatic Bool
19805b261ecSmrgcompRegisterAlternateVisuals (CompScreenPtr cs, VisualID *vids, int nVisuals)
19905b261ecSmrg{
20005b261ecSmrg    VisualID *p;
20105b261ecSmrg
2026747b715Smrg    p = realloc(cs->alternateVisuals,
20305b261ecSmrg		 sizeof(VisualID) * (cs->numAlternateVisuals + nVisuals));
20405b261ecSmrg    if(p == NULL)
20505b261ecSmrg	return FALSE;
20605b261ecSmrg
20705b261ecSmrg    memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals);
20805b261ecSmrg
20905b261ecSmrg    cs->alternateVisuals = p;
21005b261ecSmrg    cs->numAlternateVisuals += nVisuals;
21105b261ecSmrg
21205b261ecSmrg    return TRUE;
21305b261ecSmrg}
21405b261ecSmrg
21505b261ecSmrgBool CompositeRegisterAlternateVisuals (ScreenPtr pScreen, VisualID *vids,
21605b261ecSmrg					int nVisuals)
21705b261ecSmrg{
21805b261ecSmrg    CompScreenPtr cs = GetCompScreen (pScreen);
21905b261ecSmrg    return compRegisterAlternateVisuals(cs, vids, nVisuals);
22005b261ecSmrg}
22105b261ecSmrg
22205b261ecSmrgtypedef struct _alternateVisual {
22305b261ecSmrg    int		depth;
22405b261ecSmrg    CARD32	format;
22505b261ecSmrg} CompAlternateVisual;
22605b261ecSmrg
22705b261ecSmrgstatic CompAlternateVisual  altVisuals[] = {
22805b261ecSmrg#if COMP_INCLUDE_RGB24_VISUAL
22905b261ecSmrg    {	24,	PICT_r8g8b8 },
23005b261ecSmrg#endif
23105b261ecSmrg    {	32,	PICT_a8r8g8b8 },
23205b261ecSmrg};
23305b261ecSmrg
23405b261ecSmrgstatic const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) /
23505b261ecSmrg					      sizeof(CompAlternateVisual);
23605b261ecSmrg
23705b261ecSmrgstatic Bool
23805b261ecSmrgcompAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs,
23905b261ecSmrg		       CompAlternateVisual *alt)
24005b261ecSmrg{
2416747b715Smrg    VisualPtr	    visual;
24205b261ecSmrg    DepthPtr	    depth;
24305b261ecSmrg    PictFormatPtr   pPictFormat;
24405b261ecSmrg    unsigned long   alphaMask;
24505b261ecSmrg
24605b261ecSmrg    /*
24705b261ecSmrg     * The ARGB32 visual is always available.  Other alternate depth visuals
24805b261ecSmrg     * are only provided if their depth is less than the root window depth.
24905b261ecSmrg     * There's no deep reason for this.
25005b261ecSmrg     */
25105b261ecSmrg    if (alt->depth >= pScreen->rootDepth && alt->depth != 32)
25205b261ecSmrg	return FALSE;
25305b261ecSmrg
25405b261ecSmrg    depth = compFindVisuallessDepth (pScreen, alt->depth);
25505b261ecSmrg    if (!depth)
25605b261ecSmrg	/* alt->depth doesn't exist or already has alternate visuals. */
25705b261ecSmrg	return TRUE;
25805b261ecSmrg
25905b261ecSmrg    pPictFormat = PictureMatchFormat (pScreen, alt->depth, alt->format);
26005b261ecSmrg    if (!pPictFormat)
26105b261ecSmrg	return FALSE;
26205b261ecSmrg
2636747b715Smrg    if (ResizeVisualArray(pScreen, 1, depth) == FALSE) {
2646747b715Smrg        return FALSE;
26505b261ecSmrg    }
26605b261ecSmrg
2676747b715Smrg    visual = pScreen->visuals + (pScreen->numVisuals - 1); /* the new one */
26805b261ecSmrg
26905b261ecSmrg    /* Initialize the visual */
27005b261ecSmrg    visual->bitsPerRGBValue = 8;
27105b261ecSmrg    if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) {
27205b261ecSmrg	visual->class = PseudoColor;
27305b261ecSmrg	visual->nplanes = PICT_FORMAT_BPP(alt->format);
27405b261ecSmrg	visual->ColormapEntries = 1 << visual->nplanes;
27505b261ecSmrg    } else {
27605b261ecSmrg	DirectFormatRec *direct = &pPictFormat->direct;
27705b261ecSmrg	visual->class = TrueColor;
27805b261ecSmrg	visual->redMask   = ((unsigned long)direct->redMask) << direct->red;
27905b261ecSmrg	visual->greenMask = ((unsigned long)direct->greenMask) << direct->green;
28005b261ecSmrg	visual->blueMask  = ((unsigned long)direct->blueMask) << direct->blue;
28105b261ecSmrg	alphaMask = ((unsigned long)direct->alphaMask) << direct->alpha;
28205b261ecSmrg	visual->offsetRed   = direct->red;
28305b261ecSmrg	visual->offsetGreen = direct->green;
28405b261ecSmrg	visual->offsetBlue  = direct->blue;
28505b261ecSmrg	/*
28605b261ecSmrg	 * Include A bits in this (unlike GLX which includes only RGB)
28705b261ecSmrg	 * This lets DIX compute suitable masks for colormap allocations
28805b261ecSmrg	 */
28905b261ecSmrg	visual->nplanes = Ones (visual->redMask |
29005b261ecSmrg		visual->greenMask |
29105b261ecSmrg		visual->blueMask |
29205b261ecSmrg		alphaMask);
29305b261ecSmrg	/* find widest component */
29405b261ecSmrg	visual->ColormapEntries = (1 << max (Ones (visual->redMask),
29505b261ecSmrg		    max (Ones (visual->greenMask),
29605b261ecSmrg			Ones (visual->blueMask))));
29705b261ecSmrg    }
29805b261ecSmrg
29905b261ecSmrg    /* remember the visual ID to detect auto-update windows */
30005b261ecSmrg    compRegisterAlternateVisuals(cs, &visual->vid, 1);
30105b261ecSmrg
30205b261ecSmrg    return TRUE;
30305b261ecSmrg}
30405b261ecSmrg
30505b261ecSmrgstatic Bool
30605b261ecSmrgcompAddAlternateVisuals (ScreenPtr pScreen, CompScreenPtr cs)
30705b261ecSmrg{
30805b261ecSmrg    int alt, ret = 0;
30905b261ecSmrg
31005b261ecSmrg    for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++)
31105b261ecSmrg	ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt);
31205b261ecSmrg
31305b261ecSmrg    return !!ret;
31405b261ecSmrg}
31505b261ecSmrg
31605b261ecSmrgBool
31705b261ecSmrgcompScreenInit (ScreenPtr pScreen)
31805b261ecSmrg{
31905b261ecSmrg    CompScreenPtr   cs;
32005b261ecSmrg
3216747b715Smrg    if (!dixRegisterPrivateKey(&CompScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
3226747b715Smrg	return FALSE;
3236747b715Smrg    if (!dixRegisterPrivateKey(&CompWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
3246747b715Smrg	return FALSE;
3256747b715Smrg    if (!dixRegisterPrivateKey(&CompSubwindowsPrivateKeyRec, PRIVATE_WINDOW, 0))
3266747b715Smrg	return FALSE;
3276747b715Smrg
32805b261ecSmrg    if (GetCompScreen (pScreen))
32905b261ecSmrg	return TRUE;
3306747b715Smrg    cs = (CompScreenPtr) malloc(sizeof (CompScreenRec));
33105b261ecSmrg    if (!cs)
33205b261ecSmrg	return FALSE;
33305b261ecSmrg
33405b261ecSmrg    cs->damaged = FALSE;
3354642e01fSmrg    cs->overlayWid = FakeClientID(0);
33605b261ecSmrg    cs->pOverlayWin = NULL;
33705b261ecSmrg    cs->pOverlayClients = NULL;
33805b261ecSmrg
33905b261ecSmrg    cs->numAlternateVisuals = 0;
34005b261ecSmrg    cs->alternateVisuals = NULL;
34105b261ecSmrg
34205b261ecSmrg    if (!compAddAlternateVisuals (pScreen, cs))
34305b261ecSmrg    {
3446747b715Smrg	free(cs);
34505b261ecSmrg	return FALSE;
34605b261ecSmrg    }
34705b261ecSmrg
34805b261ecSmrg    cs->PositionWindow = pScreen->PositionWindow;
34905b261ecSmrg    pScreen->PositionWindow = compPositionWindow;
35005b261ecSmrg
35105b261ecSmrg    cs->CopyWindow = pScreen->CopyWindow;
35205b261ecSmrg    pScreen->CopyWindow = compCopyWindow;
35305b261ecSmrg
35405b261ecSmrg    cs->CreateWindow = pScreen->CreateWindow;
35505b261ecSmrg    pScreen->CreateWindow = compCreateWindow;
35605b261ecSmrg
35705b261ecSmrg    cs->DestroyWindow = pScreen->DestroyWindow;
35805b261ecSmrg    pScreen->DestroyWindow = compDestroyWindow;
35905b261ecSmrg
36005b261ecSmrg    cs->RealizeWindow = pScreen->RealizeWindow;
36105b261ecSmrg    pScreen->RealizeWindow = compRealizeWindow;
36205b261ecSmrg
36305b261ecSmrg    cs->UnrealizeWindow = pScreen->UnrealizeWindow;
36405b261ecSmrg    pScreen->UnrealizeWindow = compUnrealizeWindow;
36505b261ecSmrg
36605b261ecSmrg    cs->ClipNotify = pScreen->ClipNotify;
36705b261ecSmrg    pScreen->ClipNotify = compClipNotify;
36805b261ecSmrg
3696747b715Smrg    cs->ConfigNotify = pScreen->ConfigNotify;
3706747b715Smrg    pScreen->ConfigNotify = compConfigNotify;
3716747b715Smrg
37205b261ecSmrg    cs->MoveWindow = pScreen->MoveWindow;
37305b261ecSmrg    pScreen->MoveWindow = compMoveWindow;
37405b261ecSmrg
37505b261ecSmrg    cs->ResizeWindow = pScreen->ResizeWindow;
37605b261ecSmrg    pScreen->ResizeWindow = compResizeWindow;
37705b261ecSmrg
37805b261ecSmrg    cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
37905b261ecSmrg    pScreen->ChangeBorderWidth = compChangeBorderWidth;
38005b261ecSmrg
38105b261ecSmrg    cs->ReparentWindow = pScreen->ReparentWindow;
38205b261ecSmrg    pScreen->ReparentWindow = compReparentWindow;
38305b261ecSmrg
38405b261ecSmrg    cs->InstallColormap = pScreen->InstallColormap;
38505b261ecSmrg    pScreen->InstallColormap = compInstallColormap;
38605b261ecSmrg
3874642e01fSmrg    cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
3884642e01fSmrg    pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
3894642e01fSmrg
39005b261ecSmrg    cs->BlockHandler = pScreen->BlockHandler;
39105b261ecSmrg    pScreen->BlockHandler = compBlockHandler;
39205b261ecSmrg
39305b261ecSmrg    cs->CloseScreen = pScreen->CloseScreen;
39405b261ecSmrg    pScreen->CloseScreen = compCloseScreen;
39505b261ecSmrg
3964642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, cs);
39705b261ecSmrg
39805b261ecSmrg    RegisterRealChildHeadProc(CompositeRealChildHead);
39905b261ecSmrg
40005b261ecSmrg    return TRUE;
40105b261ecSmrg}
402