1/* 2 * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Copyright © 2003 Keith Packard 24 * 25 * Permission to use, copy, modify, distribute, and sell this software and its 26 * documentation for any purpose is hereby granted without fee, provided that 27 * the above copyright notice appear in all copies and that both that 28 * copyright notice and this permission notice appear in supporting 29 * documentation, and that the name of Keith Packard not be used in 30 * advertising or publicity pertaining to distribution of the software without 31 * specific, written prior permission. Keith Packard makes no 32 * representations about the suitability of this software for any purpose. It 33 * is provided "as is" without express or implied warranty. 34 * 35 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 36 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 37 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 39 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 40 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 41 * PERFORMANCE OF THIS SOFTWARE. 42 */ 43 44#ifdef HAVE_DIX_CONFIG_H 45#include <dix-config.h> 46#endif 47 48#include "compint.h" 49#include "compositeext.h" 50 51DevPrivateKeyRec CompScreenPrivateKeyRec; 52DevPrivateKeyRec CompWindowPrivateKeyRec; 53DevPrivateKeyRec CompSubwindowsPrivateKeyRec; 54 55static Bool 56compCloseScreen(ScreenPtr pScreen) 57{ 58 CompScreenPtr cs = GetCompScreen(pScreen); 59 Bool ret; 60 61 free(cs->alternateVisuals); 62 63 pScreen->CloseScreen = cs->CloseScreen; 64 pScreen->InstallColormap = cs->InstallColormap; 65 pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes; 66 pScreen->ReparentWindow = cs->ReparentWindow; 67 pScreen->ConfigNotify = cs->ConfigNotify; 68 pScreen->MoveWindow = cs->MoveWindow; 69 pScreen->ResizeWindow = cs->ResizeWindow; 70 pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; 71 72 pScreen->ClipNotify = cs->ClipNotify; 73 pScreen->UnrealizeWindow = cs->UnrealizeWindow; 74 pScreen->RealizeWindow = cs->RealizeWindow; 75 pScreen->DestroyWindow = cs->DestroyWindow; 76 pScreen->CreateWindow = cs->CreateWindow; 77 pScreen->CopyWindow = cs->CopyWindow; 78 pScreen->PositionWindow = cs->PositionWindow; 79 pScreen->SourceValidate = cs->SourceValidate; 80 81 free(cs); 82 dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, NULL); 83 ret = (*pScreen->CloseScreen) (pScreen); 84 85 return ret; 86} 87 88static void 89compInstallColormap(ColormapPtr pColormap) 90{ 91 VisualPtr pVisual = pColormap->pVisual; 92 ScreenPtr pScreen = pColormap->pScreen; 93 CompScreenPtr cs = GetCompScreen(pScreen); 94 int a; 95 96 for (a = 0; a < cs->numAlternateVisuals; a++) 97 if (pVisual->vid == cs->alternateVisuals[a]) 98 return; 99 pScreen->InstallColormap = cs->InstallColormap; 100 (*pScreen->InstallColormap) (pColormap); 101 cs->InstallColormap = pScreen->InstallColormap; 102 pScreen->InstallColormap = compInstallColormap; 103} 104 105static void 106compCheckBackingStore(WindowPtr pWin) 107{ 108 if (pWin->backingStore != NotUseful) { 109 compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic); 110 } 111 else { 112 compUnredirectWindow(serverClient, pWin, 113 CompositeRedirectAutomatic); 114 } 115} 116 117/* Fake backing store via automatic redirection */ 118static Bool 119compChangeWindowAttributes(WindowPtr pWin, unsigned long mask) 120{ 121 ScreenPtr pScreen = pWin->drawable.pScreen; 122 CompScreenPtr cs = GetCompScreen(pScreen); 123 Bool ret; 124 125 pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes; 126 ret = pScreen->ChangeWindowAttributes(pWin, mask); 127 128 if (ret && (mask & CWBackingStore) && 129 pScreen->backingStoreSupport != NotUseful) 130 compCheckBackingStore(pWin); 131 132 pScreen->ChangeWindowAttributes = compChangeWindowAttributes; 133 134 return ret; 135} 136 137static void 138compSourceValidate(DrawablePtr pDrawable, 139 int x, int y, 140 int width, int height, unsigned int subWindowMode) 141{ 142 ScreenPtr pScreen = pDrawable->pScreen; 143 CompScreenPtr cs = GetCompScreen(pScreen); 144 145 pScreen->SourceValidate = cs->SourceValidate; 146 if (pDrawable->type == DRAWABLE_WINDOW && subWindowMode == IncludeInferiors) 147 compPaintChildrenToWindow((WindowPtr) pDrawable); 148 (*pScreen->SourceValidate) (pDrawable, x, y, width, height, 149 subWindowMode); 150 cs->SourceValidate = pScreen->SourceValidate; 151 pScreen->SourceValidate = compSourceValidate; 152} 153 154/* 155 * Add alternate visuals -- always expose an ARGB32 and RGB24 visual 156 */ 157 158static DepthPtr 159compFindVisuallessDepth(ScreenPtr pScreen, int d) 160{ 161 int i; 162 163 for (i = 0; i < pScreen->numDepths; i++) { 164 DepthPtr depth = &pScreen->allowedDepths[i]; 165 166 if (depth->depth == d) { 167 /* 168 * Make sure it doesn't have visuals already 169 */ 170 if (depth->numVids) 171 return 0; 172 /* 173 * looks fine 174 */ 175 return depth; 176 } 177 } 178 /* 179 * If there isn't one, then it's gonna be hard to have 180 * an associated visual 181 */ 182 return 0; 183} 184 185/* 186 * Add a list of visual IDs to the list of visuals to implicitly redirect. 187 */ 188static Bool 189compRegisterAlternateVisuals(CompScreenPtr cs, VisualID * vids, int nVisuals) 190{ 191 VisualID *p; 192 193 p = reallocarray(cs->alternateVisuals, 194 cs->numAlternateVisuals + nVisuals, sizeof(VisualID)); 195 if (p == NULL) 196 return FALSE; 197 198 memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals); 199 200 cs->alternateVisuals = p; 201 cs->numAlternateVisuals += nVisuals; 202 203 return TRUE; 204} 205 206Bool 207CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids, 208 int nVisuals) 209{ 210 CompScreenPtr cs = GetCompScreen(pScreen); 211 212 return compRegisterAlternateVisuals(cs, vids, nVisuals); 213} 214 215Bool 216CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen, 217 VisualID parentVisual, 218 VisualID winVisual) 219{ 220 CompScreenPtr cs = GetCompScreen(pScreen); 221 CompImplicitRedirectException *p; 222 223 p = reallocarray(cs->implicitRedirectExceptions, 224 cs->numImplicitRedirectExceptions + 1, sizeof(p[0])); 225 if (p == NULL) 226 return FALSE; 227 228 p[cs->numImplicitRedirectExceptions].parentVisual = parentVisual; 229 p[cs->numImplicitRedirectExceptions].winVisual = winVisual; 230 231 cs->implicitRedirectExceptions = p; 232 cs->numImplicitRedirectExceptions++; 233 234 return TRUE; 235} 236 237typedef struct _alternateVisual { 238 int depth; 239 CARD32 format; 240} CompAlternateVisual; 241 242static CompAlternateVisual altVisuals[] = { 243#if COMP_INCLUDE_RGB24_VISUAL 244 {24, PICT_r8g8b8}, 245#endif 246 {32, PICT_a8r8g8b8}, 247}; 248 249static Bool 250compAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs, 251 CompAlternateVisual * alt) 252{ 253 VisualPtr visual; 254 DepthPtr depth; 255 PictFormatPtr pPictFormat; 256 unsigned long alphaMask; 257 258 /* 259 * The ARGB32 visual is always available. Other alternate depth visuals 260 * are only provided if their depth is less than the root window depth. 261 * There's no deep reason for this. 262 */ 263 if (alt->depth >= pScreen->rootDepth && alt->depth != 32) 264 return FALSE; 265 266 depth = compFindVisuallessDepth(pScreen, alt->depth); 267 if (!depth) 268 /* alt->depth doesn't exist or already has alternate visuals. */ 269 return TRUE; 270 271 pPictFormat = PictureMatchFormat(pScreen, alt->depth, alt->format); 272 if (!pPictFormat) 273 return FALSE; 274 275 if (ResizeVisualArray(pScreen, 1, depth) == FALSE) { 276 return FALSE; 277 } 278 279 visual = pScreen->visuals + (pScreen->numVisuals - 1); /* the new one */ 280 281 /* Initialize the visual */ 282 visual->bitsPerRGBValue = 8; 283 if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) { 284 visual->class = PseudoColor; 285 visual->nplanes = PICT_FORMAT_BPP(alt->format); 286 visual->ColormapEntries = 1 << visual->nplanes; 287 } 288 else { 289 DirectFormatRec *direct = &pPictFormat->direct; 290 291 visual->class = TrueColor; 292 visual->redMask = ((unsigned long) direct->redMask) << direct->red; 293 visual->greenMask = 294 ((unsigned long) direct->greenMask) << direct->green; 295 visual->blueMask = ((unsigned long) direct->blueMask) << direct->blue; 296 alphaMask = ((unsigned long) direct->alphaMask) << direct->alpha; 297 visual->offsetRed = direct->red; 298 visual->offsetGreen = direct->green; 299 visual->offsetBlue = direct->blue; 300 /* 301 * Include A bits in this (unlike GLX which includes only RGB) 302 * This lets DIX compute suitable masks for colormap allocations 303 */ 304 visual->nplanes = Ones(visual->redMask | 305 visual->greenMask | 306 visual->blueMask | alphaMask); 307 /* find widest component */ 308 visual->ColormapEntries = (1 << max(Ones(visual->redMask), 309 max(Ones(visual->greenMask), 310 Ones(visual->blueMask)))); 311 } 312 313 /* remember the visual ID to detect auto-update windows */ 314 compRegisterAlternateVisuals(cs, &visual->vid, 1); 315 316 return TRUE; 317} 318 319static Bool 320compAddAlternateVisuals(ScreenPtr pScreen, CompScreenPtr cs) 321{ 322 int alt, ret = 0; 323 324 for (alt = 0; alt < ARRAY_SIZE(altVisuals); alt++) 325 ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt); 326 327 return ! !ret; 328} 329 330Bool 331compScreenInit(ScreenPtr pScreen) 332{ 333 CompScreenPtr cs; 334 335 if (!dixRegisterPrivateKey(&CompScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 336 return FALSE; 337 if (!dixRegisterPrivateKey(&CompWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) 338 return FALSE; 339 if (!dixRegisterPrivateKey(&CompSubwindowsPrivateKeyRec, PRIVATE_WINDOW, 0)) 340 return FALSE; 341 342 if (GetCompScreen(pScreen)) 343 return TRUE; 344 cs = (CompScreenPtr) malloc(sizeof(CompScreenRec)); 345 if (!cs) 346 return FALSE; 347 348 cs->overlayWid = FakeClientID(0); 349 cs->pOverlayWin = NULL; 350 cs->pOverlayClients = NULL; 351 352 cs->pendingScreenUpdate = FALSE; 353 354 cs->numAlternateVisuals = 0; 355 cs->alternateVisuals = NULL; 356 cs->numImplicitRedirectExceptions = 0; 357 cs->implicitRedirectExceptions = NULL; 358 359 if (!compAddAlternateVisuals(pScreen, cs)) { 360 free(cs); 361 return FALSE; 362 } 363 364 if (!disableBackingStore) 365 pScreen->backingStoreSupport = WhenMapped; 366 367 cs->PositionWindow = pScreen->PositionWindow; 368 pScreen->PositionWindow = compPositionWindow; 369 370 cs->CopyWindow = pScreen->CopyWindow; 371 pScreen->CopyWindow = compCopyWindow; 372 373 cs->CreateWindow = pScreen->CreateWindow; 374 pScreen->CreateWindow = compCreateWindow; 375 376 cs->DestroyWindow = pScreen->DestroyWindow; 377 pScreen->DestroyWindow = compDestroyWindow; 378 379 cs->RealizeWindow = pScreen->RealizeWindow; 380 pScreen->RealizeWindow = compRealizeWindow; 381 382 cs->UnrealizeWindow = pScreen->UnrealizeWindow; 383 pScreen->UnrealizeWindow = compUnrealizeWindow; 384 385 cs->ClipNotify = pScreen->ClipNotify; 386 pScreen->ClipNotify = compClipNotify; 387 388 cs->ConfigNotify = pScreen->ConfigNotify; 389 pScreen->ConfigNotify = compConfigNotify; 390 391 cs->MoveWindow = pScreen->MoveWindow; 392 pScreen->MoveWindow = compMoveWindow; 393 394 cs->ResizeWindow = pScreen->ResizeWindow; 395 pScreen->ResizeWindow = compResizeWindow; 396 397 cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; 398 pScreen->ChangeBorderWidth = compChangeBorderWidth; 399 400 cs->ReparentWindow = pScreen->ReparentWindow; 401 pScreen->ReparentWindow = compReparentWindow; 402 403 cs->InstallColormap = pScreen->InstallColormap; 404 pScreen->InstallColormap = compInstallColormap; 405 406 cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; 407 pScreen->ChangeWindowAttributes = compChangeWindowAttributes; 408 409 cs->CloseScreen = pScreen->CloseScreen; 410 pScreen->CloseScreen = compCloseScreen; 411 412 cs->SourceValidate = pScreen->SourceValidate; 413 pScreen->SourceValidate = compSourceValidate; 414 415 dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, cs); 416 417 RegisterRealChildHeadProc(CompositeRealChildHead); 418 419 return TRUE; 420} 421