compinit.c revision 35c4bbdf
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 80 pScreen->GetImage = cs->GetImage; 81 pScreen->GetSpans = cs->GetSpans; 82 pScreen->SourceValidate = cs->SourceValidate; 83 84 free(cs); 85 dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, NULL); 86 ret = (*pScreen->CloseScreen) (pScreen); 87 88 return ret; 89} 90 91static void 92compInstallColormap(ColormapPtr pColormap) 93{ 94 VisualPtr pVisual = pColormap->pVisual; 95 ScreenPtr pScreen = pColormap->pScreen; 96 CompScreenPtr cs = GetCompScreen(pScreen); 97 int a; 98 99 for (a = 0; a < cs->numAlternateVisuals; a++) 100 if (pVisual->vid == cs->alternateVisuals[a]) 101 return; 102 pScreen->InstallColormap = cs->InstallColormap; 103 (*pScreen->InstallColormap) (pColormap); 104 cs->InstallColormap = pScreen->InstallColormap; 105 pScreen->InstallColormap = compInstallColormap; 106} 107 108static void 109compCheckBackingStore(WindowPtr pWin) 110{ 111 if (pWin->backingStore != NotUseful && !pWin->backStorage) { 112 compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic); 113 pWin->backStorage = TRUE; 114 } 115 else if (pWin->backingStore == NotUseful && pWin->backStorage) { 116 compUnredirectWindow(serverClient, pWin, 117 CompositeRedirectAutomatic); 118 pWin->backStorage = FALSE; 119 } 120} 121 122/* Fake backing store via automatic redirection */ 123static Bool 124compChangeWindowAttributes(WindowPtr pWin, unsigned long mask) 125{ 126 ScreenPtr pScreen = pWin->drawable.pScreen; 127 CompScreenPtr cs = GetCompScreen(pScreen); 128 Bool ret; 129 130 pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes; 131 ret = pScreen->ChangeWindowAttributes(pWin, mask); 132 133 if (ret && (mask & CWBackingStore) && 134 pScreen->backingStoreSupport != NotUseful) 135 compCheckBackingStore(pWin); 136 137 pScreen->ChangeWindowAttributes = compChangeWindowAttributes; 138 139 return ret; 140} 141 142static void 143compGetImage(DrawablePtr pDrawable, 144 int sx, int sy, 145 int w, int h, 146 unsigned int format, unsigned long planemask, char *pdstLine) 147{ 148 ScreenPtr pScreen = pDrawable->pScreen; 149 CompScreenPtr cs = GetCompScreen(pScreen); 150 151 pScreen->GetImage = cs->GetImage; 152 if (pDrawable->type == DRAWABLE_WINDOW) 153 compPaintChildrenToWindow((WindowPtr) pDrawable); 154 (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine); 155 cs->GetImage = pScreen->GetImage; 156 pScreen->GetImage = compGetImage; 157} 158 159static void 160compGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, 161 int nspans, char *pdstStart) 162{ 163 ScreenPtr pScreen = pDrawable->pScreen; 164 CompScreenPtr cs = GetCompScreen(pScreen); 165 166 pScreen->GetSpans = cs->GetSpans; 167 if (pDrawable->type == DRAWABLE_WINDOW) 168 compPaintChildrenToWindow((WindowPtr) pDrawable); 169 (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 170 cs->GetSpans = pScreen->GetSpans; 171 pScreen->GetSpans = compGetSpans; 172} 173 174static void 175compSourceValidate(DrawablePtr pDrawable, 176 int x, int y, 177 int width, int height, unsigned int subWindowMode) 178{ 179 ScreenPtr pScreen = pDrawable->pScreen; 180 CompScreenPtr cs = GetCompScreen(pScreen); 181 182 pScreen->SourceValidate = cs->SourceValidate; 183 if (pDrawable->type == DRAWABLE_WINDOW && subWindowMode == IncludeInferiors) 184 compPaintChildrenToWindow((WindowPtr) pDrawable); 185 if (pScreen->SourceValidate) 186 (*pScreen->SourceValidate) (pDrawable, x, y, width, height, 187 subWindowMode); 188 cs->SourceValidate = pScreen->SourceValidate; 189 pScreen->SourceValidate = compSourceValidate; 190} 191 192/* 193 * Add alternate visuals -- always expose an ARGB32 and RGB24 visual 194 */ 195 196static DepthPtr 197compFindVisuallessDepth(ScreenPtr pScreen, int d) 198{ 199 int i; 200 201 for (i = 0; i < pScreen->numDepths; i++) { 202 DepthPtr depth = &pScreen->allowedDepths[i]; 203 204 if (depth->depth == d) { 205 /* 206 * Make sure it doesn't have visuals already 207 */ 208 if (depth->numVids) 209 return 0; 210 /* 211 * looks fine 212 */ 213 return depth; 214 } 215 } 216 /* 217 * If there isn't one, then it's gonna be hard to have 218 * an associated visual 219 */ 220 return 0; 221} 222 223/* 224 * Add a list of visual IDs to the list of visuals to implicitly redirect. 225 */ 226static Bool 227compRegisterAlternateVisuals(CompScreenPtr cs, VisualID * vids, int nVisuals) 228{ 229 VisualID *p; 230 231 p = reallocarray(cs->alternateVisuals, 232 cs->numAlternateVisuals + nVisuals, sizeof(VisualID)); 233 if (p == NULL) 234 return FALSE; 235 236 memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals); 237 238 cs->alternateVisuals = p; 239 cs->numAlternateVisuals += nVisuals; 240 241 return TRUE; 242} 243 244Bool 245CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids, 246 int nVisuals) 247{ 248 CompScreenPtr cs = GetCompScreen(pScreen); 249 250 return compRegisterAlternateVisuals(cs, vids, nVisuals); 251} 252 253Bool 254CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen, 255 VisualID parentVisual, 256 VisualID winVisual) 257{ 258 CompScreenPtr cs = GetCompScreen(pScreen); 259 CompImplicitRedirectException *p; 260 261 p = reallocarray(cs->implicitRedirectExceptions, 262 cs->numImplicitRedirectExceptions + 1, sizeof(p[0])); 263 if (p == NULL) 264 return FALSE; 265 266 p[cs->numImplicitRedirectExceptions].parentVisual = parentVisual; 267 p[cs->numImplicitRedirectExceptions].winVisual = winVisual; 268 269 cs->implicitRedirectExceptions = p; 270 cs->numImplicitRedirectExceptions++; 271 272 return TRUE; 273} 274 275typedef struct _alternateVisual { 276 int depth; 277 CARD32 format; 278} CompAlternateVisual; 279 280static CompAlternateVisual altVisuals[] = { 281#if COMP_INCLUDE_RGB24_VISUAL 282 {24, PICT_r8g8b8}, 283#endif 284 {32, PICT_a8r8g8b8}, 285}; 286 287static const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) / 288 sizeof(CompAlternateVisual); 289 290static Bool 291compAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs, 292 CompAlternateVisual * alt) 293{ 294 VisualPtr visual; 295 DepthPtr depth; 296 PictFormatPtr pPictFormat; 297 unsigned long alphaMask; 298 299 /* 300 * The ARGB32 visual is always available. Other alternate depth visuals 301 * are only provided if their depth is less than the root window depth. 302 * There's no deep reason for this. 303 */ 304 if (alt->depth >= pScreen->rootDepth && alt->depth != 32) 305 return FALSE; 306 307 depth = compFindVisuallessDepth(pScreen, alt->depth); 308 if (!depth) 309 /* alt->depth doesn't exist or already has alternate visuals. */ 310 return TRUE; 311 312 pPictFormat = PictureMatchFormat(pScreen, alt->depth, alt->format); 313 if (!pPictFormat) 314 return FALSE; 315 316 if (ResizeVisualArray(pScreen, 1, depth) == FALSE) { 317 return FALSE; 318 } 319 320 visual = pScreen->visuals + (pScreen->numVisuals - 1); /* the new one */ 321 322 /* Initialize the visual */ 323 visual->bitsPerRGBValue = 8; 324 if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) { 325 visual->class = PseudoColor; 326 visual->nplanes = PICT_FORMAT_BPP(alt->format); 327 visual->ColormapEntries = 1 << visual->nplanes; 328 } 329 else { 330 DirectFormatRec *direct = &pPictFormat->direct; 331 332 visual->class = TrueColor; 333 visual->redMask = ((unsigned long) direct->redMask) << direct->red; 334 visual->greenMask = 335 ((unsigned long) direct->greenMask) << direct->green; 336 visual->blueMask = ((unsigned long) direct->blueMask) << direct->blue; 337 alphaMask = ((unsigned long) direct->alphaMask) << direct->alpha; 338 visual->offsetRed = direct->red; 339 visual->offsetGreen = direct->green; 340 visual->offsetBlue = direct->blue; 341 /* 342 * Include A bits in this (unlike GLX which includes only RGB) 343 * This lets DIX compute suitable masks for colormap allocations 344 */ 345 visual->nplanes = Ones(visual->redMask | 346 visual->greenMask | 347 visual->blueMask | alphaMask); 348 /* find widest component */ 349 visual->ColormapEntries = (1 << max(Ones(visual->redMask), 350 max(Ones(visual->greenMask), 351 Ones(visual->blueMask)))); 352 } 353 354 /* remember the visual ID to detect auto-update windows */ 355 compRegisterAlternateVisuals(cs, &visual->vid, 1); 356 357 return TRUE; 358} 359 360static Bool 361compAddAlternateVisuals(ScreenPtr pScreen, CompScreenPtr cs) 362{ 363 int alt, ret = 0; 364 365 for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++) 366 ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt); 367 368 return ! !ret; 369} 370 371Bool 372compScreenInit(ScreenPtr pScreen) 373{ 374 CompScreenPtr cs; 375 376 if (!dixRegisterPrivateKey(&CompScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 377 return FALSE; 378 if (!dixRegisterPrivateKey(&CompWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) 379 return FALSE; 380 if (!dixRegisterPrivateKey(&CompSubwindowsPrivateKeyRec, PRIVATE_WINDOW, 0)) 381 return FALSE; 382 383 if (GetCompScreen(pScreen)) 384 return TRUE; 385 cs = (CompScreenPtr) malloc(sizeof(CompScreenRec)); 386 if (!cs) 387 return FALSE; 388 389 cs->overlayWid = FakeClientID(0); 390 cs->pOverlayWin = NULL; 391 cs->pOverlayClients = NULL; 392 393 cs->numAlternateVisuals = 0; 394 cs->alternateVisuals = NULL; 395 cs->numImplicitRedirectExceptions = 0; 396 cs->implicitRedirectExceptions = NULL; 397 398 if (!compAddAlternateVisuals(pScreen, cs)) { 399 free(cs); 400 return FALSE; 401 } 402 403 if (!disableBackingStore) 404 pScreen->backingStoreSupport = WhenMapped; 405 406 cs->PositionWindow = pScreen->PositionWindow; 407 pScreen->PositionWindow = compPositionWindow; 408 409 cs->CopyWindow = pScreen->CopyWindow; 410 pScreen->CopyWindow = compCopyWindow; 411 412 cs->CreateWindow = pScreen->CreateWindow; 413 pScreen->CreateWindow = compCreateWindow; 414 415 cs->DestroyWindow = pScreen->DestroyWindow; 416 pScreen->DestroyWindow = compDestroyWindow; 417 418 cs->RealizeWindow = pScreen->RealizeWindow; 419 pScreen->RealizeWindow = compRealizeWindow; 420 421 cs->UnrealizeWindow = pScreen->UnrealizeWindow; 422 pScreen->UnrealizeWindow = compUnrealizeWindow; 423 424 cs->ClipNotify = pScreen->ClipNotify; 425 pScreen->ClipNotify = compClipNotify; 426 427 cs->ConfigNotify = pScreen->ConfigNotify; 428 pScreen->ConfigNotify = compConfigNotify; 429 430 cs->MoveWindow = pScreen->MoveWindow; 431 pScreen->MoveWindow = compMoveWindow; 432 433 cs->ResizeWindow = pScreen->ResizeWindow; 434 pScreen->ResizeWindow = compResizeWindow; 435 436 cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; 437 pScreen->ChangeBorderWidth = compChangeBorderWidth; 438 439 cs->ReparentWindow = pScreen->ReparentWindow; 440 pScreen->ReparentWindow = compReparentWindow; 441 442 cs->InstallColormap = pScreen->InstallColormap; 443 pScreen->InstallColormap = compInstallColormap; 444 445 cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; 446 pScreen->ChangeWindowAttributes = compChangeWindowAttributes; 447 448 cs->BlockHandler = NULL; 449 450 cs->CloseScreen = pScreen->CloseScreen; 451 pScreen->CloseScreen = compCloseScreen; 452 453 cs->GetImage = pScreen->GetImage; 454 pScreen->GetImage = compGetImage; 455 456 cs->GetSpans = pScreen->GetSpans; 457 pScreen->GetSpans = compGetSpans; 458 459 cs->SourceValidate = pScreen->SourceValidate; 460 pScreen->SourceValidate = compSourceValidate; 461 462 dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, cs); 463 464 RegisterRealChildHeadProc(CompositeRealChildHead); 465 466 return TRUE; 467} 468