winscrinit.c revision 1b5d61b8
1/* 2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 *"Software"), to deal in the Software without restriction, including 7 *without limitation the rights to use, copy, modify, merge, publish, 8 *distribute, sublicense, and/or sell copies of the Software, and to 9 *permit persons to whom the Software is furnished to do so, subject to 10 *the following conditions: 11 * 12 *The above copyright notice and this permission notice shall be 13 *included in all copies or substantial portions of the Software. 14 * 15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR 19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 *Except as contained in this notice, the name of the XFree86 Project 24 *shall not be used in advertising or otherwise to promote the sale, use 25 *or other dealings in this Software without prior written authorization 26 *from the XFree86 Project. 27 * 28 * Authors: Dakshinamurthy Karra 29 * Suhaib M Siddiqi 30 * Peter Busch 31 * Harold L Hunt II 32 * Kensuke Matsuzaki 33 */ 34 35#ifdef HAVE_XWIN_CONFIG_H 36#include <xwin-config.h> 37#endif 38#include "win.h" 39#include "winmsg.h" 40 41#ifdef XWIN_MULTIWINDOWEXTWM 42static RootlessFrameProcsRec winMWExtWMProcs = { 43 winMWExtWMCreateFrame, 44 winMWExtWMDestroyFrame, 45 46 winMWExtWMMoveFrame, 47 winMWExtWMResizeFrame, 48 winMWExtWMRestackFrame, 49 winMWExtWMReshapeFrame, 50 winMWExtWMUnmapFrame, 51 52 winMWExtWMStartDrawing, 53 winMWExtWMStopDrawing, 54 winMWExtWMUpdateRegion, 55 winMWExtWMDamageRects, 56 winMWExtWMRootlessSwitchWindow, 57 NULL, //winMWExtWMDoReorderWindow, 58 NULL, //winMWExtWMHideWindow, 59 NULL, //winMWExtWMUpdateColorMap, 60 61 NULL, //winMWExtWMCopyBytes, 62 winMWExtWMCopyWindow 63}; 64#endif 65 66/* 67 * Prototypes 68 */ 69 70/* 71 * Local functions 72 */ 73 74static Bool 75 winSaveScreen(ScreenPtr pScreen, int on); 76 77/* 78 * Determine what type of screen we are initializing 79 * and call the appropriate procedure to intiailize 80 * that type of screen. 81 */ 82 83Bool 84winScreenInit(ScreenPtr pScreen, int argc, char **argv) 85{ 86 winScreenInfoPtr pScreenInfo = &g_ScreenInfo[pScreen->myNum]; 87 winPrivScreenPtr pScreenPriv; 88 HDC hdc; 89 DWORD dwInitialBPP; 90 91#if CYGDEBUG || YES 92 winDebug("winScreenInit - dwWidth: %u dwHeight: %u\n", 93 (unsigned int)pScreenInfo->dwWidth, (unsigned int)pScreenInfo->dwHeight); 94#endif 95 96 /* Allocate privates for this screen */ 97 if (!winAllocatePrivates(pScreen)) { 98 ErrorF("winScreenInit - Couldn't allocate screen privates\n"); 99 return FALSE; 100 } 101 102 /* Get a pointer to the privates structure that was allocated */ 103 pScreenPriv = winGetScreenPriv(pScreen); 104 105 /* Save a pointer to this screen in the screen info structure */ 106 pScreenInfo->pScreen = pScreen; 107 108 /* Save a pointer to the screen info in the screen privates structure */ 109 /* This allows us to get back to the screen info from a screen pointer */ 110 pScreenPriv->pScreenInfo = pScreenInfo; 111 112 /* 113 * Determine which engine to use. 114 * 115 * NOTE: This is done once per screen because each screen possibly has 116 * a preferred engine specified on the command line. 117 */ 118 if (!winSetEngine(pScreen)) { 119 ErrorF("winScreenInit - winSetEngine () failed\n"); 120 return FALSE; 121 } 122 123 /* Horribly misnamed function: Allow engine to adjust BPP for screen */ 124 dwInitialBPP = pScreenInfo->dwBPP; 125 126 if (!(*pScreenPriv->pwinAdjustVideoMode) (pScreen)) { 127 ErrorF("winScreenInit - winAdjustVideoMode () failed\n"); 128 return FALSE; 129 } 130 131 if (dwInitialBPP == WIN_DEFAULT_BPP) { 132 /* No -depth parameter was passed, let the user know the depth being used */ 133 ErrorF 134 ("winScreenInit - Using Windows display depth of %d bits per pixel\n", 135 (int) pScreenInfo->dwBPP); 136 } 137 else if (dwInitialBPP != pScreenInfo->dwBPP) { 138 /* Warn user if engine forced a depth different to -depth parameter */ 139 ErrorF 140 ("winScreenInit - Command line depth of %d bpp overidden by engine, using %d bpp\n", 141 (int) dwInitialBPP, (int) pScreenInfo->dwBPP); 142 } 143 else { 144 ErrorF("winScreenInit - Using command line depth of %d bpp\n", 145 (int) pScreenInfo->dwBPP); 146 } 147 148 /* Check for supported display depth */ 149 if (!(WIN_SUPPORTED_BPPS & (1 << (pScreenInfo->dwBPP - 1)))) { 150 ErrorF("winScreenInit - Unsupported display depth: %d\n" 151 "Change your Windows display depth to 15, 16, 24, or 32 bits " 152 "per pixel.\n", (int) pScreenInfo->dwBPP); 153 ErrorF("winScreenInit - Supported depths: %08x\n", WIN_SUPPORTED_BPPS); 154#if WIN_CHECK_DEPTH 155 return FALSE; 156#endif 157 } 158 159 /* 160 * Check that all monitors have the same display depth if we are using 161 * multiple monitors 162 */ 163 if (pScreenInfo->fMultipleMonitors 164 && !GetSystemMetrics(SM_SAMEDISPLAYFORMAT)) { 165 ErrorF("winScreenInit - Monitors do not all have same pixel format / " 166 "display depth.\n"); 167 if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI) { 168 ErrorF 169 ("winScreenInit - Performance may suffer off primary display.\n"); 170 } 171 else { 172 ErrorF("winScreenInit - Using primary display only.\n"); 173 pScreenInfo->fMultipleMonitors = FALSE; 174 } 175 } 176 177 /* Create display window */ 178 if (!(*pScreenPriv->pwinCreateBoundingWindow) (pScreen)) { 179 ErrorF("winScreenInit - pwinCreateBoundingWindow () " "failed\n"); 180 return FALSE; 181 } 182 183 /* Get a device context */ 184 hdc = GetDC(pScreenPriv->hwndScreen); 185 186 /* Are we using multiple monitors? */ 187 if (pScreenInfo->fMultipleMonitors) { 188 /* 189 * In this case, some of the defaults set in 190 * winInitializeScreenDefaults() are not correct ... 191 */ 192 if (!pScreenInfo->fUserGaveHeightAndWidth) { 193 pScreenInfo->dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); 194 pScreenInfo->dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); 195 } 196 } 197 198 /* Release the device context */ 199 ReleaseDC(pScreenPriv->hwndScreen, hdc); 200 201 /* Clear the visuals list */ 202 miClearVisualTypes(); 203 204 /* Call the engine dependent screen initialization procedure */ 205 if (!((*pScreenPriv->pwinFinishScreenInit) (pScreen->myNum, pScreen, argc, argv))) { 206 ErrorF("winScreenInit - winFinishScreenInit () failed\n"); 207 208 /* call the engine dependent screen close procedure to clean up from a failure */ 209 pScreenPriv->pwinCloseScreen(pScreen); 210 211 return FALSE; 212 } 213 214 if (!g_fSoftwareCursor) 215 winInitCursor(pScreen); 216 else 217 winErrorFVerb(2, "winScreenInit - Using software cursor\n"); 218 219 if (!noPanoramiXExtension) { 220 /* 221 Note the screen origin in a normalized coordinate space where (0,0) is at the top left 222 of the native virtual desktop area 223 */ 224 pScreen->x = 225 pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN); 226 pScreen->y = 227 pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN); 228 229 ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n", 230 pScreen->myNum, pScreen->x, pScreen->y); 231 } 232 233#if CYGDEBUG || YES 234 winDebug("winScreenInit - returning\n"); 235#endif 236 237 return TRUE; 238} 239 240static Bool 241winCreateScreenResources(ScreenPtr pScreen) 242{ 243 winScreenPriv(pScreen); 244 Bool result; 245 246 result = pScreenPriv->pwinCreateScreenResources(pScreen); 247 248 /* Now the screen bitmap has been wrapped in a pixmap, 249 add that to the Shadow framebuffer */ 250 if (!shadowAdd(pScreen, pScreen->devPrivate, 251 pScreenPriv->pwinShadowUpdate, NULL, 0, 0)) { 252 ErrorF("winCreateScreenResources - shadowAdd () failed\n"); 253 return FALSE; 254 } 255 256 return result; 257} 258 259/* See Porting Layer Definition - p. 20 */ 260Bool 261winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv) 262{ 263 winScreenPriv(pScreen); 264 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 265 VisualPtr pVisual = NULL; 266 267 int iReturn; 268 269 /* Create framebuffer */ 270 if (!(*pScreenPriv->pwinInitScreen) (pScreen)) { 271 ErrorF("winFinishScreenInitFB - Could not allocate framebuffer\n"); 272 return FALSE; 273 } 274 275 /* 276 * Calculate the number of bits that are used to represent color in each pixel, 277 * the color depth for the screen 278 */ 279 if (pScreenInfo->dwBPP == 8) 280 pScreenInfo->dwDepth = 8; 281 else 282 pScreenInfo->dwDepth = winCountBits(pScreenPriv->dwRedMask) 283 + winCountBits(pScreenPriv->dwGreenMask) 284 + winCountBits(pScreenPriv->dwBlueMask); 285 286 winErrorFVerb(2, "winFinishScreenInitFB - Masks: %08x %08x %08x\n", 287 (unsigned int) pScreenPriv->dwRedMask, 288 (unsigned int) pScreenPriv->dwGreenMask, 289 (unsigned int) pScreenPriv->dwBlueMask); 290 291 /* Init visuals */ 292 if (!(*pScreenPriv->pwinInitVisuals) (pScreen)) { 293 ErrorF("winFinishScreenInitFB - winInitVisuals failed\n"); 294 return FALSE; 295 } 296 297 /* Apparently we need this for the render extension */ 298 miSetPixmapDepths(); 299 300 /* Start fb initialization */ 301 if (!fbSetupScreen(pScreen, 302 pScreenInfo->pfb, 303 pScreenInfo->dwWidth, pScreenInfo->dwHeight, 304 monitorResolution, monitorResolution, 305 pScreenInfo->dwStride, pScreenInfo->dwBPP)) { 306 ErrorF("winFinishScreenInitFB - fbSetupScreen failed\n"); 307 return FALSE; 308 } 309 310 /* Override default colormap routines if visual class is dynamic */ 311 if (pScreenInfo->dwDepth == 8 312 && (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI 313 || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL 314 && pScreenInfo->fFullScreen))) { 315 winSetColormapFunctions(pScreen); 316 317 /* 318 * NOTE: Setting whitePixel to 255 causes Magic 7.1 to allocate its 319 * own colormap, as it cannot allocate 7 planes in the default 320 * colormap. Setting whitePixel to 1 allows Magic to get 7 321 * planes in the default colormap, so it doesn't create its 322 * own colormap. This latter situation is highly desireable, 323 * as it keeps the Magic window viewable when switching to 324 * other X clients that use the default colormap. 325 */ 326 pScreen->blackPixel = 0; 327 pScreen->whitePixel = 1; 328 } 329 330 /* Place our save screen function */ 331 pScreen->SaveScreen = winSaveScreen; 332 333 /* Finish fb initialization */ 334 if (!fbFinishScreenInit(pScreen, 335 pScreenInfo->pfb, 336 pScreenInfo->dwWidth, pScreenInfo->dwHeight, 337 monitorResolution, monitorResolution, 338 pScreenInfo->dwStride, pScreenInfo->dwBPP)) { 339 ErrorF("winFinishScreenInitFB - fbFinishScreenInit failed\n"); 340 return FALSE; 341 } 342 343 /* Save a pointer to the root visual */ 344 for (pVisual = pScreen->visuals; 345 pVisual->vid != pScreen->rootVisual; pVisual++); 346 pScreenPriv->pRootVisual = pVisual; 347 348 /* 349 * Setup points to the block and wakeup handlers. Pass a pointer 350 * to the current screen as pWakeupdata. 351 */ 352 pScreen->BlockHandler = winBlockHandler; 353 pScreen->WakeupHandler = winWakeupHandler; 354 355 /* Render extension initialization, calls miPictureInit */ 356 if (!fbPictureInit(pScreen, NULL, 0)) { 357 ErrorF("winFinishScreenInitFB - fbPictureInit () failed\n"); 358 return FALSE; 359 } 360 361#ifdef RANDR 362 /* Initialize resize and rotate support */ 363 if (!winRandRInit(pScreen)) { 364 ErrorF("winFinishScreenInitFB - winRandRInit () failed\n"); 365 return FALSE; 366 } 367#endif 368 369 /* Setup the cursor routines */ 370#if CYGDEBUG 371 winDebug("winFinishScreenInitFB - Calling miDCInitialize ()\n"); 372#endif 373 miDCInitialize(pScreen, &g_winPointerCursorFuncs); 374 375 /* KDrive does winCreateDefColormap right after miDCInitialize */ 376 /* Create a default colormap */ 377#if CYGDEBUG 378 winDebug("winFinishScreenInitFB - Calling winCreateDefColormap ()\n"); 379#endif 380 if (!winCreateDefColormap(pScreen)) { 381 ErrorF("winFinishScreenInitFB - Could not create colormap\n"); 382 return FALSE; 383 } 384 385 /* Initialize the shadow framebuffer layer */ 386 if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI 387 || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL) 388#ifdef XWIN_MULTIWINDOWEXTWM 389 && !pScreenInfo->fMWExtWM 390#endif 391 ) { 392#if CYGDEBUG 393 winDebug("winFinishScreenInitFB - Calling shadowSetup ()\n"); 394#endif 395 if (!shadowSetup(pScreen)) { 396 ErrorF("winFinishScreenInitFB - shadowSetup () failed\n"); 397 return FALSE; 398 } 399 400 /* Wrap CreateScreenResources so we can add the screen pixmap 401 to the Shadow framebuffer after it's been created */ 402 pScreenPriv->pwinCreateScreenResources = pScreen->CreateScreenResources; 403 pScreen->CreateScreenResources = winCreateScreenResources; 404 } 405 406#ifdef XWIN_MULTIWINDOWEXTWM 407 /* Handle multi-window external window manager mode */ 408 if (pScreenInfo->fMWExtWM) { 409 winDebug("winScreenInit - MultiWindowExtWM - Calling RootlessInit\n"); 410 411 RootlessInit(pScreen, &winMWExtWMProcs); 412 413 winDebug("winScreenInit - MultiWindowExtWM - RootlessInit returned\n"); 414 415 rootless_CopyBytes_threshold = 0; 416 /* FIXME: How many? Profiling needed? */ 417 rootless_CopyWindow_threshold = 1; 418 419 winWindowsWMExtensionInit(); 420 } 421#endif 422 423 /* Handle rootless mode */ 424 if (pScreenInfo->fRootless) { 425 /* Define the WRAP macro temporarily for local use */ 426#define WRAP(a) \ 427 if (pScreen->a) { \ 428 pScreenPriv->a = pScreen->a; \ 429 } else { \ 430 winDebug("winScreenInit - null screen fn " #a "\n"); \ 431 pScreenPriv->a = NULL; \ 432 } 433 434 /* Save a pointer to each lower-level window procedure */ 435 WRAP(CreateWindow); 436 WRAP(DestroyWindow); 437 WRAP(RealizeWindow); 438 WRAP(UnrealizeWindow); 439 WRAP(PositionWindow); 440 WRAP(ChangeWindowAttributes); 441 WRAP(SetShape); 442 443 /* Assign rootless window procedures to be top level procedures */ 444 pScreen->CreateWindow = winCreateWindowRootless; 445 pScreen->DestroyWindow = winDestroyWindowRootless; 446 pScreen->PositionWindow = winPositionWindowRootless; 447 /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesRootless; */ 448 pScreen->RealizeWindow = winMapWindowRootless; 449 pScreen->UnrealizeWindow = winUnmapWindowRootless; 450 pScreen->SetShape = winSetShapeRootless; 451 452 /* Undefine the WRAP macro, as it is not needed elsewhere */ 453#undef WRAP 454 } 455 456 /* Handle multi window mode */ 457 else if (pScreenInfo->fMultiWindow) { 458 /* Define the WRAP macro temporarily for local use */ 459#define WRAP(a) \ 460 if (pScreen->a) { \ 461 pScreenPriv->a = pScreen->a; \ 462 } else { \ 463 winDebug("null screen fn " #a "\n"); \ 464 pScreenPriv->a = NULL; \ 465 } 466 467 /* Save a pointer to each lower-level window procedure */ 468 WRAP(CreateWindow); 469 WRAP(DestroyWindow); 470 WRAP(RealizeWindow); 471 WRAP(UnrealizeWindow); 472 WRAP(PositionWindow); 473 WRAP(ChangeWindowAttributes); 474 WRAP(ReparentWindow); 475 WRAP(RestackWindow); 476 WRAP(ResizeWindow); 477 WRAP(MoveWindow); 478 WRAP(CopyWindow); 479 WRAP(SetShape); 480 481 /* Assign multi-window window procedures to be top level procedures */ 482 pScreen->CreateWindow = winCreateWindowMultiWindow; 483 pScreen->DestroyWindow = winDestroyWindowMultiWindow; 484 pScreen->PositionWindow = winPositionWindowMultiWindow; 485 /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesMultiWindow; */ 486 pScreen->RealizeWindow = winMapWindowMultiWindow; 487 pScreen->UnrealizeWindow = winUnmapWindowMultiWindow; 488 pScreen->ReparentWindow = winReparentWindowMultiWindow; 489 pScreen->RestackWindow = winRestackWindowMultiWindow; 490 pScreen->ResizeWindow = winResizeWindowMultiWindow; 491 pScreen->MoveWindow = winMoveWindowMultiWindow; 492 pScreen->CopyWindow = winCopyWindowMultiWindow; 493 pScreen->SetShape = winSetShapeMultiWindow; 494 495 /* Undefine the WRAP macro, as it is not needed elsewhere */ 496#undef WRAP 497 } 498 499 /* Wrap either fb's or shadow's CloseScreen with our CloseScreen */ 500 pScreenPriv->CloseScreen = pScreen->CloseScreen; 501 pScreen->CloseScreen = pScreenPriv->pwinCloseScreen; 502 503 /* Create a mutex for modules in separate threads to wait for */ 504 iReturn = pthread_mutex_init(&pScreenPriv->pmServerStarted, NULL); 505 if (iReturn != 0) { 506 ErrorF("winFinishScreenInitFB - pthread_mutex_init () failed: %d\n", 507 iReturn); 508 return FALSE; 509 } 510 511 /* Own the mutex for modules in separate threads */ 512 iReturn = pthread_mutex_lock(&pScreenPriv->pmServerStarted); 513 if (iReturn != 0) { 514 ErrorF("winFinishScreenInitFB - pthread_mutex_lock () failed: %d\n", 515 iReturn); 516 return FALSE; 517 } 518 519 /* Set the ServerStarted flag to false */ 520 pScreenPriv->fServerStarted = FALSE; 521 522#ifdef XWIN_MULTIWINDOWEXTWM 523 pScreenPriv->fRestacking = FALSE; 524#endif 525 526 if (pScreenInfo->fMultiWindow) { 527#if CYGDEBUG || YES 528 winDebug("winFinishScreenInitFB - Calling winInitWM.\n"); 529#endif 530 531 /* Initialize multi window mode */ 532 if (!winInitWM(&pScreenPriv->pWMInfo, 533 &pScreenPriv->ptWMProc, 534 &pScreenPriv->ptXMsgProc, 535 &pScreenPriv->pmServerStarted, 536 pScreenInfo->dwScreen, 537 (HWND) &pScreenPriv->hwndScreen)) { 538 ErrorF("winFinishScreenInitFB - winInitWM () failed.\n"); 539 return FALSE; 540 } 541 } 542 543 /* Tell the server that we are enabled */ 544 pScreenPriv->fEnabled = TRUE; 545 546 /* Tell the server that we have a valid depth */ 547 pScreenPriv->fBadDepth = FALSE; 548 549#if CYGDEBUG || YES 550 winDebug("winFinishScreenInitFB - returning\n"); 551#endif 552 553 return TRUE; 554} 555 556/* See Porting Layer Definition - p. 33 */ 557static Bool 558winSaveScreen(ScreenPtr pScreen, int on) 559{ 560 return TRUE; 561} 562