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