dmxscrinit.c revision 706f2543
1/* 2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. 3 * 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation on the rights to use, copy, modify, merge, 10 * publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial 16 * portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS 22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 * SOFTWARE. 26 */ 27 28/* 29 * Authors: 30 * Kevin E. Martin <kem@redhat.com> 31 * David H. Dawes <dawes@xfree86.org> 32 * 33 */ 34 35/** \file 36 * This file provides support for screen initialization. */ 37 38#ifdef HAVE_DMX_CONFIG_H 39#include <dmx-config.h> 40#endif 41 42#include "dmx.h" 43#include "dmxsync.h" 44#include "dmxshadow.h" 45#include "dmxscrinit.h" 46#include "dmxcursor.h" 47#include "dmxgc.h" 48#include "dmxgcops.h" 49#include "dmxwindow.h" 50#include "dmxpixmap.h" 51#include "dmxfont.h" 52#include "dmxcmap.h" 53#include "dmxprop.h" 54#include "dmxdpms.h" 55 56#include "dmxpict.h" 57 58#include "fb.h" 59#include "mipointer.h" 60#include "micmap.h" 61 62extern Bool dmxCloseScreen(int idx, ScreenPtr pScreen); 63static Bool dmxSaveScreen(ScreenPtr pScreen, int what); 64 65static unsigned long dmxGeneration; 66static unsigned long *dmxCursorGeneration; 67 68DevPrivateKeyRec dmxGCPrivateKeyRec; 69DevPrivateKeyRec dmxWinPrivateKeyRec; 70DevPrivateKeyRec dmxPixPrivateKeyRec; 71int dmxFontPrivateIndex; /**< Private index for Fonts */ 72DevPrivateKeyRec dmxScreenPrivateKeyRec; 73DevPrivateKeyRec dmxColormapPrivateKeyRec; 74DevPrivateKeyRec dmxPictPrivateKeyRec; 75DevPrivateKeyRec dmxGlyphSetPrivateKeyRec; 76 77/** Initialize the parts of screen \a idx that require access to the 78 * back-end server. */ 79void dmxBEScreenInit(int idx, ScreenPtr pScreen) 80{ 81 DMXScreenInfo *dmxScreen = &dmxScreens[idx]; 82 XSetWindowAttributes attribs; 83 XGCValues gcvals; 84 unsigned long mask; 85 int i, j; 86 87 /* FIXME: The dmxScreenInit() code currently assumes that it will 88 * not be called if the Xdmx server is started with this screen 89 * detached -- i.e., it assumes that dmxScreen->beDisplay is always 90 * valid. This is not necessarily a valid assumption when full 91 * addition/removal of screens is implemented, but when this code is 92 * broken out for screen reattachment, then we will reevaluate this 93 * assumption. 94 */ 95 96 pScreen->mmWidth = DisplayWidthMM(dmxScreen->beDisplay, 97 DefaultScreen(dmxScreen->beDisplay)); 98 pScreen->mmHeight = DisplayHeightMM(dmxScreen->beDisplay, 99 DefaultScreen(dmxScreen->beDisplay)); 100 101 pScreen->whitePixel = dmxScreen->beWhitePixel; 102 pScreen->blackPixel = dmxScreen->beBlackPixel; 103 104 /* Handle screen savers and DPMS on the backend */ 105 dmxDPMSInit(dmxScreen); 106 107 /* Create root window for screen */ 108 mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect; 109 attribs.background_pixel = dmxScreen->beBlackPixel; 110 attribs.event_mask = (KeyPressMask 111 | KeyReleaseMask 112 | ButtonPressMask 113 | ButtonReleaseMask 114 | EnterWindowMask 115 | LeaveWindowMask 116 | PointerMotionMask 117 | KeymapStateMask 118 | FocusChangeMask); 119 attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex]; 120 attribs.override_redirect = True; 121 122 dmxScreen->scrnWin = 123 XCreateWindow(dmxScreen->beDisplay, 124 DefaultRootWindow(dmxScreen->beDisplay), 125 dmxScreen->scrnX, 126 dmxScreen->scrnY, 127 dmxScreen->scrnWidth, 128 dmxScreen->scrnHeight, 129 0, 130 pScreen->rootDepth, 131 InputOutput, 132 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, 133 mask, 134 &attribs); 135 dmxPropertyWindow(dmxScreen); 136 137 /* 138 * This turns off the cursor by defining a cursor with no visible 139 * components. 140 */ 141 { 142 char noCursorData[] = {0, 0, 0, 0, 143 0, 0, 0, 0}; 144 Pixmap pixmap; 145 XColor color, tmp; 146 147 pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin, 148 noCursorData, 8, 8); 149 XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0], 150 "black", &color, &tmp); 151 dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay, 152 pixmap, pixmap, 153 &color, &color, 0, 0); 154 XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin, 155 dmxScreen->noCursor); 156 157 XFreePixmap(dmxScreen->beDisplay, pixmap); 158 } 159 160 XMapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); 161 162 if (dmxShadowFB) { 163 mask = (GCFunction 164 | GCPlaneMask 165 | GCClipMask); 166 gcvals.function = GXcopy; 167 gcvals.plane_mask = AllPlanes; 168 gcvals.clip_mask = None; 169 170 dmxScreen->shadowGC = XCreateGC(dmxScreen->beDisplay, 171 dmxScreen->scrnWin, 172 mask, &gcvals); 173 174 dmxScreen->shadowFBImage = 175 XCreateImage(dmxScreen->beDisplay, 176 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual, 177 dmxScreen->beDepth, 178 ZPixmap, 179 0, 180 (char *)dmxScreen->shadow, 181 dmxScreen->scrnWidth, dmxScreen->scrnHeight, 182 dmxScreen->beBPP, 183 PixmapBytePad(dmxScreen->scrnWidth, 184 dmxScreen->beBPP)); 185 } else { 186 /* Create default drawables (used during GC creation) */ 187 for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) 188 for (j = 0; j < dmxScreen->beNumDepths; j++) 189 if ((dmxScreen->bePixmapFormats[i].depth == 1) || 190 (dmxScreen->bePixmapFormats[i].depth == 191 dmxScreen->beDepths[j])) { 192 dmxScreen->scrnDefDrawables[i] = (Drawable) 193 XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin, 194 1, 1, dmxScreen->bePixmapFormats[i].depth); 195 break; 196 } 197 } 198} 199 200/** Initialize screen number \a idx. */ 201Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[]) 202{ 203 DMXScreenInfo *dmxScreen = &dmxScreens[idx]; 204 int i, j; 205 206 if (!dixRegisterPrivateKey(&dmxScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 207 return FALSE; 208 if (!dixRegisterPrivateKey(&dmxColormapPrivateKeyRec, PRIVATE_COLORMAP, 0)) 209 return FALSE; 210 if (!dixRegisterPrivateKey(&dmxGlyphSetPrivateKeyRec, PRIVATE_GLYPHSET, 0)) 211 return FALSE; 212 213 if (dmxGeneration != serverGeneration) { 214 /* Allocate font private index */ 215 dmxFontPrivateIndex = AllocateFontPrivateIndex(); 216 if (dmxFontPrivateIndex == -1) 217 return FALSE; 218 219 dmxGeneration = serverGeneration; 220 } 221 222 if (dmxShadowFB) { 223 dmxScreen->shadow = shadowAlloc(dmxScreen->scrnWidth, 224 dmxScreen->scrnHeight, 225 dmxScreen->beBPP); 226 } else { 227 if (!dmxInitGC(pScreen)) return FALSE; 228 if (!dmxInitWindow(pScreen)) return FALSE; 229 if (!dmxInitPixmap(pScreen)) return FALSE; 230 } 231 232 /* 233 * Initalise the visual types. miSetVisualTypesAndMasks() requires 234 * that all of the types for each depth be collected together. It's 235 * intended for slightly different usage to what we would like here. 236 * Maybe a miAddVisualTypeAndMask() function will be added to make 237 * things easier here. 238 */ 239 for (i = 0; i < dmxScreen->beNumDepths; i++) { 240 int depth; 241 int visuals = 0; 242 int bitsPerRgb = 0; 243 int preferredClass = -1; 244 Pixel redMask = 0; 245 Pixel greenMask = 0; 246 Pixel blueMask = 0; 247 248 depth = dmxScreen->beDepths[i]; 249 for (j = 0; j < dmxScreen->beNumVisuals; j++) { 250 XVisualInfo *vi; 251 252 vi = &dmxScreen->beVisuals[j]; 253 if (vi->depth == depth) { 254 /* Assume the masks are all the same. */ 255 visuals |= (1 << vi->class); 256 bitsPerRgb = vi->bits_per_rgb; 257 redMask = vi->red_mask; 258 greenMask = vi->green_mask; 259 blueMask = vi->blue_mask; 260 if (j == dmxScreen->beDefVisualIndex) { 261 preferredClass = vi->class; 262 } 263 } 264 } 265 miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb, preferredClass, 266 redMask, greenMask, blueMask); 267 } 268 269 fbScreenInit(pScreen, 270 dmxShadowFB ? dmxScreen->shadow : NULL, 271 dmxScreen->scrnWidth, 272 dmxScreen->scrnHeight, 273 dmxScreen->beXDPI, 274 dmxScreen->beXDPI, 275 dmxScreen->scrnWidth, 276 dmxScreen->beBPP); 277 (void)dmxPictureInit(pScreen, 0, 0); 278 279 /* Not yet... */ 280 pScreen->GetWindowPixmap = NULL; 281 pScreen->SetWindowPixmap = NULL; 282 283 if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL)) 284 return FALSE; 285 286 if (dmxShadowFB) { 287 miDCInitialize(pScreen, &dmxPointerCursorFuncs); 288 } else { 289 MAXSCREENSALLOC(dmxCursorGeneration); 290 if (dmxCursorGeneration[idx] != serverGeneration) { 291 if (!(miPointerInitialize(pScreen, 292 &dmxPointerSpriteFuncs, 293 &dmxPointerCursorFuncs, 294 FALSE))) 295 return FALSE; 296 297 dmxCursorGeneration[idx] = serverGeneration; 298 } 299 } 300 301 DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen); 302 DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen); 303 304 dmxBEScreenInit(idx, pScreen); 305 306 if (!dmxShadowFB) { 307 /* Wrap GC functions */ 308 DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen); 309 310 /* Wrap Window functions */ 311 DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen); 312 DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen); 313 DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen); 314 DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen, 315 pScreen); 316 DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen); 317 DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen); 318 DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen); 319 DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen); 320 DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen); 321 322 DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen); 323 DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen); 324 325 DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen); 326 327 /* Wrap Image functions */ 328 DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen); 329 DMX_WRAP(GetSpans, dmxGetSpans, dmxScreen, pScreen); 330 331 /* Wrap Pixmap functions */ 332 DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen); 333 DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen); 334 DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen); 335 336 /* Wrap Font functions */ 337 DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen); 338 DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen); 339 340 /* Wrap Colormap functions */ 341 DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen); 342 DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen); 343 DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen); 344 DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen); 345 346 /* Wrap Shape functions */ 347 DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen); 348 } 349 350 if (!dmxCreateDefColormap(pScreen)) 351 return FALSE; 352 353 return TRUE; 354} 355 356/** Close the \a pScreen resources on the back-end server. */ 357void dmxBECloseScreen(ScreenPtr pScreen) 358{ 359 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 360 int i; 361 362 /* Restore the back-end screen-saver and DPMS state. */ 363 dmxDPMSTerm(dmxScreen); 364 365 /* Free the screen resources */ 366 367 XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor); 368 dmxScreen->noCursor = (Cursor)0; 369 370 XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); 371 XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin); 372 dmxScreen->scrnWin = (Window)0; 373 374 if (dmxShadowFB) { 375 /* Free the shadow GC and image assocated with the back-end server */ 376 XFreeGC(dmxScreen->beDisplay, dmxScreen->shadowGC); 377 dmxScreen->shadowGC = NULL; 378 XFree(dmxScreen->shadowFBImage); 379 dmxScreen->shadowFBImage = NULL; 380 } else { 381 /* Free the default drawables */ 382 for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { 383 if (dmxScreen->scrnDefDrawables[i]) { 384 XFreePixmap(dmxScreen->beDisplay, 385 dmxScreen->scrnDefDrawables[i]); 386 dmxScreen->scrnDefDrawables[i] = (Drawable)0; 387 } 388 } 389 } 390 391 /* Free resources allocated during initialization (in dmxinit.c) */ 392 for (i = 0; i < dmxScreen->beNumDefColormaps; i++) 393 XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]); 394 free(dmxScreen->beDefColormaps); 395 dmxScreen->beDefColormaps = NULL; 396 397#if 0 398 /* Do not free visuals, depths and pixmap formats here. Free them 399 * in dmxCloseScreen() instead -- see comment below. */ 400 XFree(dmxScreen->beVisuals); 401 dmxScreen->beVisuals = NULL; 402 403 XFree(dmxScreen->beDepths); 404 dmxScreen->beDepths = NULL; 405 406 XFree(dmxScreen->bePixmapFormats); 407 dmxScreen->bePixmapFormats = NULL; 408#endif 409 410#ifdef GLXEXT 411 if (dmxScreen->glxVisuals) { 412 XFree(dmxScreen->glxVisuals); 413 dmxScreen->glxVisuals = NULL; 414 dmxScreen->numGlxVisuals = 0; 415 } 416#endif 417 418 /* Close display */ 419 XCloseDisplay(dmxScreen->beDisplay); 420 dmxScreen->beDisplay = NULL; 421} 422 423/** Close screen number \a idx. */ 424Bool dmxCloseScreen(int idx, ScreenPtr pScreen) 425{ 426 DMXScreenInfo *dmxScreen = &dmxScreens[idx]; 427 428 /* Reset the proc vectors */ 429 if (idx == 0) { 430 dmxResetRender(); 431 dmxResetFonts(); 432 } 433 434 if (dmxShadowFB) { 435 /* Free the shadow framebuffer */ 436 free(dmxScreen->shadow); 437 } else { 438 439 /* Unwrap Shape functions */ 440 DMX_UNWRAP(SetShape, dmxScreen, pScreen); 441 442 /* Unwrap the pScreen functions */ 443 DMX_UNWRAP(CreateGC, dmxScreen, pScreen); 444 445 DMX_UNWRAP(CreateWindow, dmxScreen, pScreen); 446 DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen); 447 DMX_UNWRAP(PositionWindow, dmxScreen, pScreen); 448 DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen); 449 DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen); 450 DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen); 451 DMX_UNWRAP(RestackWindow, dmxScreen, pScreen); 452 DMX_UNWRAP(WindowExposures, dmxScreen, pScreen); 453 DMX_UNWRAP(CopyWindow, dmxScreen, pScreen); 454 455 DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen); 456 DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen); 457 458 DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen); 459 460 DMX_UNWRAP(GetImage, dmxScreen, pScreen); 461 DMX_UNWRAP(GetSpans, dmxScreen, pScreen); 462 463 DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen); 464 DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen); 465 DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen); 466 467 DMX_UNWRAP(RealizeFont, dmxScreen, pScreen); 468 DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen); 469 470 DMX_UNWRAP(CreateColormap, dmxScreen, pScreen); 471 DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen); 472 DMX_UNWRAP(InstallColormap, dmxScreen, pScreen); 473 DMX_UNWRAP(StoreColors, dmxScreen, pScreen); 474 } 475 476 DMX_UNWRAP(SaveScreen, dmxScreen, pScreen); 477 478 if (dmxScreen->beDisplay) { 479 dmxBECloseScreen(pScreen); 480 481#if 1 482 /* Free visuals, depths and pixmap formats here so that they 483 * won't be freed when a screen is detached, thereby allowing 484 * the screen to be reattached to be compared to the one 485 * previously removed. 486 */ 487 XFree(dmxScreen->beVisuals); 488 dmxScreen->beVisuals = NULL; 489 490 XFree(dmxScreen->beDepths); 491 dmxScreen->beDepths = NULL; 492 493 XFree(dmxScreen->bePixmapFormats); 494 dmxScreen->bePixmapFormats = NULL; 495#endif 496 } 497 498 DMX_UNWRAP(CloseScreen, dmxScreen, pScreen); 499 return pScreen->CloseScreen(idx, pScreen); 500} 501 502static Bool dmxSaveScreen(ScreenPtr pScreen, int what) 503{ 504 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; 505 506 if (dmxScreen->beDisplay) { 507 switch (what) { 508 case SCREEN_SAVER_OFF: 509 case SCREEN_SAVER_FORCER: 510 XResetScreenSaver(dmxScreen->beDisplay); 511 dmxSync(dmxScreen, FALSE); 512 break; 513 case SCREEN_SAVER_ON: 514 case SCREEN_SAVER_CYCLE: 515 XActivateScreenSaver(dmxScreen->beDisplay); 516 dmxSync(dmxScreen, FALSE); 517 break; 518 } 519 } 520 521 return TRUE; 522} 523