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