winshadddnl.c revision 6747b715
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 */ 33 34#ifdef HAVE_XWIN_CONFIG_H 35#include <xwin-config.h> 36#endif 37#include "win.h" 38 39 40/* 41 * External symbols 42 */ 43 44extern HWND g_hDlgExit; 45 46 47/* 48 * FIXME: Headers are broken, DEFINE_GUID doesn't work correctly, 49 * so we have to redefine it here. 50 */ 51#ifdef DEFINE_GUID 52#undef DEFINE_GUID 53#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} 54#endif /* DEFINE_GUID */ 55 56/* 57 * FIXME: Headers are broken, IID_IDirectDraw4 has to be defined 58 * here manually. Should be handled by ddraw.h 59 */ 60#ifndef IID_IDirectDraw4 61DEFINE_GUID( IID_IDirectDraw4, 0x9c59509a,0x39bd,0x11d1,0x8c,0x4a,0x00,0xc0,0x4f,0xd9,0x30,0xc5 ); 62#endif /* IID_IDirectDraw4 */ 63 64#define FAIL_MSG_MAX_BLT 10 65 66 67/* 68 * Local prototypes 69 */ 70 71static Bool 72winAllocateFBShadowDDNL (ScreenPtr pScreen); 73 74static void 75winShadowUpdateDDNL (ScreenPtr pScreen, 76 shadowBufPtr pBuf); 77 78static Bool 79winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen); 80 81static Bool 82winInitVisualsShadowDDNL (ScreenPtr pScreen); 83 84static Bool 85winAdjustVideoModeShadowDDNL (ScreenPtr pScreen); 86 87static Bool 88winBltExposedRegionsShadowDDNL (ScreenPtr pScreen); 89 90static Bool 91winActivateAppShadowDDNL (ScreenPtr pScreen); 92 93static Bool 94winRedrawScreenShadowDDNL (ScreenPtr pScreen); 95 96static Bool 97winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen); 98 99static Bool 100winInstallColormapShadowDDNL (ColormapPtr pColormap); 101 102static Bool 103winStoreColorsShadowDDNL (ColormapPtr pmap, 104 int ndef, 105 xColorItem *pdefs); 106 107static Bool 108winCreateColormapShadowDDNL (ColormapPtr pColormap); 109 110static Bool 111winDestroyColormapShadowDDNL (ColormapPtr pColormap); 112 113static Bool 114winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen); 115 116static Bool 117winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen); 118 119 120/* 121 * Create the primary surface and attach the clipper. 122 * Used for both the initial surface creation and during 123 * WM_DISPLAYCHANGE messages. 124 */ 125 126static Bool 127winCreatePrimarySurfaceShadowDDNL (ScreenPtr pScreen) 128{ 129 winScreenPriv(pScreen); 130 HRESULT ddrval = DD_OK; 131 DDSURFACEDESC2 ddsd; 132 133 winDebug ("winCreatePrimarySurfaceShadowDDNL - Creating primary surface\n"); 134 135 /* Describe the primary surface */ 136 ZeroMemory (&ddsd, sizeof (ddsd)); 137 ddsd.dwSize = sizeof (ddsd); 138 ddsd.dwFlags = DDSD_CAPS; 139 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 140 141 /* Create the primary surface */ 142 ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4, 143 &ddsd, 144 &pScreenPriv->pddsPrimary4, 145 NULL); 146 pScreenPriv->fRetryCreateSurface = FALSE; 147 if (FAILED (ddrval)) 148 { 149 if (ddrval == DDERR_NOEXCLUSIVEMODE) 150 { 151 /* Recreating the surface failed. Mark screen to retry later */ 152 pScreenPriv->fRetryCreateSurface = TRUE; 153 winDebug ("winCreatePrimarySurfaceShadowDDNL - Could not create " 154 "primary surface: DDERR_NOEXCLUSIVEMODE\n"); 155 } 156 else 157 { 158 ErrorF ("winCreatePrimarySurfaceShadowDDNL - Could not create " 159 "primary surface: %08x\n", (unsigned int) ddrval); 160 } 161 return FALSE; 162 } 163 164#if 1 165 winDebug ("winCreatePrimarySurfaceShadowDDNL - Created primary surface\n"); 166#endif 167 168 /* Attach our clipper to our primary surface handle */ 169 ddrval = IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4, 170 pScreenPriv->pddcPrimary); 171 if (FAILED (ddrval)) 172 { 173 ErrorF ("winCreatePrimarySurfaceShadowDDNL - Primary attach clipper " 174 "failed: %08x\n", 175 (unsigned int) ddrval); 176 return FALSE; 177 } 178 179#if 1 180 winDebug ("winCreatePrimarySurfaceShadowDDNL - Attached clipper to primary " 181 "surface\n"); 182#endif 183 184 /* Everything was correct */ 185 return TRUE; 186} 187 188 189/* 190 * Detach the clipper and release the primary surface. 191 * Called from WM_DISPLAYCHANGE. 192 */ 193 194static Bool 195winReleasePrimarySurfaceShadowDDNL (ScreenPtr pScreen) 196{ 197 winScreenPriv(pScreen); 198 199 winDebug ("winReleasePrimarySurfaceShadowDDNL - Hello\n"); 200 201 /* Release the primary surface and clipper, if they exist */ 202 if (pScreenPriv->pddsPrimary4) 203 { 204 /* 205 * Detach the clipper from the primary surface. 206 * NOTE: We do this explicity for clarity. The Clipper is not released. 207 */ 208 IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4, 209 NULL); 210 211 winDebug ("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n"); 212 213 /* Release the primary surface */ 214 IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4); 215 pScreenPriv->pddsPrimary4 = NULL; 216 } 217 218 winDebug ("winReleasePrimarySurfaceShadowDDNL - Released primary surface\n"); 219 220 return TRUE; 221} 222 223 224/* 225 * Create a DirectDraw surface for the shadow framebuffer; also create 226 * a primary surface object so we can blit to the display. 227 * 228 * Install a DirectDraw clipper on our primary surface object 229 * that clips our blits to the unobscured client area of our display window. 230 */ 231 232Bool 233winAllocateFBShadowDDNL (ScreenPtr pScreen) 234{ 235 winScreenPriv(pScreen); 236 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 237 HRESULT ddrval = DD_OK; 238 DDSURFACEDESC2 ddsdShadow; 239 char *lpSurface = NULL; 240 DDPIXELFORMAT ddpfPrimary; 241 242#if CYGDEBUG 243 winDebug ("winAllocateFBShadowDDNL - w %d h %d d %d\n", 244 pScreenInfo->dwWidth, pScreenInfo->dwHeight, pScreenInfo->dwDepth); 245#endif 246 247 /* Allocate memory for our shadow surface */ 248 lpSurface = malloc (pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight); 249 if (lpSurface == NULL) 250 { 251 ErrorF ("winAllocateFBShadowDDNL - Could not allocate bits\n"); 252 return FALSE; 253 } 254 255 /* 256 * Initialize the framebuffer memory so we don't get a 257 * strange display at startup 258 */ 259 ZeroMemory (lpSurface, pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight); 260 261 /* Create a clipper */ 262 ddrval = (*g_fpDirectDrawCreateClipper) (0, 263 &pScreenPriv->pddcPrimary, 264 NULL); 265 if (FAILED (ddrval)) 266 { 267 ErrorF ("winAllocateFBShadowDDNL - Could not attach clipper: %08x\n", 268 (unsigned int) ddrval); 269 return FALSE; 270 } 271 272#if CYGDEBUG 273 winDebug ("winAllocateFBShadowDDNL - Created a clipper\n"); 274#endif 275 276 /* Get a device context for the screen */ 277 pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen); 278 279 /* Attach the clipper to our display window */ 280 ddrval = IDirectDrawClipper_SetHWnd (pScreenPriv->pddcPrimary, 281 0, 282 pScreenPriv->hwndScreen); 283 if (FAILED (ddrval)) 284 { 285 ErrorF ("winAllocateFBShadowDDNL - Clipper not attached " 286 "to window: %08x\n", 287 (unsigned int) ddrval); 288 return FALSE; 289 } 290 291#if CYGDEBUG 292 winDebug ("winAllocateFBShadowDDNL - Attached clipper to window\n"); 293#endif 294 295 /* Create a DirectDraw object, store the address at lpdd */ 296 ddrval = (*g_fpDirectDrawCreate) (NULL, 297 (LPDIRECTDRAW*) &pScreenPriv->pdd, 298 NULL); 299 if (FAILED (ddrval)) 300 { 301 ErrorF ("winAllocateFBShadowDDNL - Could not start " 302 "DirectDraw: %08x\n", 303 (unsigned int) ddrval); 304 return FALSE; 305 } 306 307#if CYGDEBUG 308 winDebug ("winAllocateFBShadowDDNL - Created and initialized DD\n"); 309#endif 310 311 /* Get a DirectDraw4 interface pointer */ 312 ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd, 313 &IID_IDirectDraw4, 314 (LPVOID*) &pScreenPriv->pdd4); 315 if (FAILED (ddrval)) 316 { 317 ErrorF ("winAllocateFBShadowDDNL - Failed DD4 query: %08x\n", 318 (unsigned int) ddrval); 319 return FALSE; 320 } 321 322 /* Are we full screen? */ 323 if (pScreenInfo->fFullScreen) 324 { 325 DDSURFACEDESC2 ddsdCurrent; 326 DWORD dwRefreshRateCurrent = 0; 327 HDC hdc = NULL; 328 329 /* Set the cooperative level to full screen */ 330 ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4, 331 pScreenPriv->hwndScreen, 332 DDSCL_EXCLUSIVE 333 | DDSCL_FULLSCREEN); 334 if (FAILED (ddrval)) 335 { 336 ErrorF ("winAllocateFBShadowDDNL - Could not set " 337 "cooperative level: %08x\n", 338 (unsigned int) ddrval); 339 return FALSE; 340 } 341 342 /* 343 * We only need to get the current refresh rate for comparison 344 * if a refresh rate has been passed on the command line. 345 */ 346 if (pScreenInfo->dwRefreshRate != 0) 347 { 348 ZeroMemory (&ddsdCurrent, sizeof (ddsdCurrent)); 349 ddsdCurrent.dwSize = sizeof (ddsdCurrent); 350 351 /* Get information about current display settings */ 352 ddrval = IDirectDraw4_GetDisplayMode (pScreenPriv->pdd4, 353 &ddsdCurrent); 354 if (FAILED (ddrval)) 355 { 356 ErrorF ("winAllocateFBShadowDDNL - Could not get current " 357 "refresh rate: %08x. Continuing.\n", 358 (unsigned int) ddrval); 359 dwRefreshRateCurrent = 0; 360 } 361 else 362 { 363 /* Grab the current refresh rate */ 364 dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate; 365 } 366 } 367 368 /* Clean up the refresh rate */ 369 if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate) 370 { 371 /* 372 * Refresh rate is non-specified or equal to current. 373 */ 374 pScreenInfo->dwRefreshRate = 0; 375 } 376 377 /* Grab a device context for the screen */ 378 hdc = GetDC (NULL); 379 if (hdc == NULL) 380 { 381 ErrorF ("winAllocateFBShadowDDNL - GetDC () failed\n"); 382 return FALSE; 383 } 384 385 /* Only change the video mode when different than current mode */ 386 if (!pScreenInfo->fMultipleMonitors 387 && (pScreenInfo->dwWidth != GetSystemMetrics (SM_CXSCREEN) 388 || pScreenInfo->dwHeight != GetSystemMetrics (SM_CYSCREEN) 389 || pScreenInfo->dwBPP != GetDeviceCaps (hdc, BITSPIXEL) 390 || pScreenInfo->dwRefreshRate != 0)) 391 { 392 winDebug ("winAllocateFBShadowDDNL - Changing video mode\n"); 393 394 /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */ 395 ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4, 396 pScreenInfo->dwWidth, 397 pScreenInfo->dwHeight, 398 pScreenInfo->dwBPP, 399 pScreenInfo->dwRefreshRate, 400 0); 401 if (FAILED (ddrval)) 402 { 403 ErrorF ("winAllocateFBShadowDDNL - Could not set " 404 "full screen display mode: %08x\n", 405 (unsigned int) ddrval); 406 ErrorF ("winAllocateFBShadowDDNL - Using default driver refresh rate\n"); 407 ddrval = IDirectDraw4_SetDisplayMode (pScreenPriv->pdd4, 408 pScreenInfo->dwWidth, 409 pScreenInfo->dwHeight, 410 pScreenInfo->dwBPP, 411 0, 412 0); 413 if (FAILED(ddrval)) 414 { 415 ErrorF ("winAllocateFBShadowDDNL - Could not set default refresh rate " 416 "full screen display mode: %08x\n", 417 (unsigned int) ddrval); 418 return FALSE; 419 } 420 } 421 } 422 else 423 { 424 winDebug ("winAllocateFBShadowDDNL - Not changing video mode\n"); 425 } 426 427 /* Release our DC */ 428 ReleaseDC (NULL, hdc); 429 hdc = NULL; 430 } 431 else 432 { 433 /* Set the cooperative level for windowed mode */ 434 ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4, 435 pScreenPriv->hwndScreen, 436 DDSCL_NORMAL); 437 if (FAILED (ddrval)) 438 { 439 ErrorF ("winAllocateFBShadowDDNL - Could not set " 440 "cooperative level: %08x\n", 441 (unsigned int) ddrval); 442 return FALSE; 443 } 444 } 445 446 /* Create the primary surface */ 447 if (!winCreatePrimarySurfaceShadowDDNL (pScreen)) 448 { 449 ErrorF ("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL " 450 "failed\n"); 451 return FALSE; 452 } 453 454 /* Get primary surface's pixel format */ 455 ZeroMemory (&ddpfPrimary, sizeof (ddpfPrimary)); 456 ddpfPrimary.dwSize = sizeof (ddpfPrimary); 457 ddrval = IDirectDrawSurface4_GetPixelFormat (pScreenPriv->pddsPrimary4, 458 &ddpfPrimary); 459 if (FAILED (ddrval)) 460 { 461 ErrorF ("winAllocateFBShadowDDNL - Could not get primary " 462 "pixformat: %08x\n", 463 (unsigned int) ddrval); 464 return FALSE; 465 } 466 467#if CYGDEBUG 468 winDebug ("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x " 469 "dwRGBBitCount: %d\n", 470 ddpfPrimary.u2.dwRBitMask, 471 ddpfPrimary.u3.dwGBitMask, 472 ddpfPrimary.u4.dwBBitMask, 473 ddpfPrimary.u1.dwRGBBitCount); 474#endif 475 476 /* Describe the shadow surface to be created */ 477 /* 478 * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface, 479 * as drawing, locking, and unlocking take forever 480 * with video memory surfaces. In addition, 481 * video memory is a somewhat scarce resource, 482 * so you shouldn't be allocating video memory when 483 * you have the option of using system memory instead. 484 */ 485 ZeroMemory (&ddsdShadow, sizeof (ddsdShadow)); 486 ddsdShadow.dwSize = sizeof (ddsdShadow); 487 ddsdShadow.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH 488 | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT; 489 ddsdShadow.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; 490 ddsdShadow.dwHeight = pScreenInfo->dwHeight; 491 ddsdShadow.dwWidth = pScreenInfo->dwWidth; 492 ddsdShadow.u1.lPitch = pScreenInfo->dwPaddedWidth; 493 ddsdShadow.lpSurface = lpSurface; 494 ddsdShadow.u4.ddpfPixelFormat = ddpfPrimary; 495 496 winDebug ("winAllocateFBShadowDDNL - lPitch: %d\n", 497 (int) pScreenInfo->dwPaddedWidth); 498 499 /* Create the shadow surface */ 500 ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4, 501 &ddsdShadow, 502 &pScreenPriv->pddsShadow4, 503 NULL); 504 if (FAILED (ddrval)) 505 { 506 ErrorF ("winAllocateFBShadowDDNL - Could not create shadow " 507 "surface: %08x\n", (unsigned int) ddrval); 508 return FALSE; 509 } 510 511#if CYGDEBUG || YES 512 winDebug ("winAllocateFBShadowDDNL - Created shadow pitch: %d\n", 513 (int) ddsdShadow.u1.lPitch); 514#endif 515 516 /* Grab the pitch from the surface desc */ 517 pScreenInfo->dwStride = (ddsdShadow.u1.lPitch * 8) 518 / pScreenInfo->dwBPP; 519 520#if CYGDEBUG || YES 521 winDebug ("winAllocateFBShadowDDNL - Created shadow stride: %d\n", 522 (int) pScreenInfo->dwStride); 523#endif 524 525 /* Save the pointer to our surface memory */ 526 pScreenInfo->pfb = lpSurface; 527 528 /* Grab the masks from the surface description */ 529 pScreenPriv->dwRedMask = ddsdShadow.u4.ddpfPixelFormat.u2.dwRBitMask; 530 pScreenPriv->dwGreenMask = ddsdShadow.u4.ddpfPixelFormat.u3.dwGBitMask; 531 pScreenPriv->dwBlueMask = ddsdShadow.u4.ddpfPixelFormat.u4.dwBBitMask; 532 533#if CYGDEBUG 534 winDebug ("winAllocateFBShadowDDNL - Returning\n"); 535#endif 536 537 return TRUE; 538} 539 540 541#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM) 542/* 543 * Create a DirectDraw surface for the new multi-window window 544 */ 545 546static 547Bool 548winFinishCreateWindowsWindowDDNL (WindowPtr pWin) 549{ 550 winWindowPriv(pWin); 551 winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv; 552 HRESULT ddrval = DD_OK; 553 DDSURFACEDESC2 ddsd; 554 int iWidth, iHeight; 555 int iX, iY; 556 557 winDebug ("winFinishCreateWindowsWindowDDNL!\n\n"); 558 559 iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN); 560 iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN); 561 562 iWidth = pWin->drawable.width; 563 iHeight = pWin->drawable.height; 564 565 /* Describe the primary surface */ 566 ZeroMemory (&ddsd, sizeof (ddsd)); 567 ddsd.dwSize = sizeof (ddsd); 568 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; 569 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 570 ddsd.dwHeight = iHeight; 571 ddsd.dwWidth = iWidth; 572 573 /* Create the primary surface */ 574 ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4, 575 &ddsd, 576 &pWinPriv->pddsPrimary4, 577 NULL); 578 if (FAILED (ddrval)) 579 { 580 ErrorF ("winFinishCreateWindowsWindowDDNL - Could not create primary " 581 "surface: %08x\n", 582 (unsigned int)ddrval); 583 return FALSE; 584 } 585 return TRUE; 586} 587#endif 588 589 590/* 591 * Transfer the damaged regions of the shadow framebuffer to the display. 592 */ 593 594static void 595winShadowUpdateDDNL (ScreenPtr pScreen, 596 shadowBufPtr pBuf) 597{ 598 winScreenPriv(pScreen); 599 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 600 RegionPtr damage = shadowDamage(pBuf); 601 HRESULT ddrval = DD_OK; 602 RECT rcDest, rcSrc; 603 POINT ptOrigin; 604 DWORD dwBox = RegionNumRects (damage); 605 BoxPtr pBox = RegionRects (damage); 606 HRGN hrgnTemp = NULL, hrgnCombined = NULL; 607 608 /* 609 * Return immediately if the app is not active 610 * and we are fullscreen, or if we have a bad display depth 611 */ 612 if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) 613 || pScreenPriv->fBadDepth) return; 614 615 /* Get the origin of the window in the screen coords */ 616 ptOrigin.x = pScreenInfo->dwXOffset; 617 ptOrigin.y = pScreenInfo->dwYOffset; 618 MapWindowPoints (pScreenPriv->hwndScreen, 619 HWND_DESKTOP, 620 (LPPOINT)&ptOrigin, 1); 621 622 /* 623 * Handle small regions with multiple blits, 624 * handle large regions by creating a clipping region and 625 * doing a single blit constrained to that clipping region. 626 */ 627 if (pScreenInfo->dwClipUpdatesNBoxes == 0 628 || dwBox < pScreenInfo->dwClipUpdatesNBoxes) 629 { 630 /* Loop through all boxes in the damaged region */ 631 while (dwBox--) 632 { 633 /* Assign damage box to source rectangle */ 634 rcSrc.left = pBox->x1; 635 rcSrc.top = pBox->y1; 636 rcSrc.right = pBox->x2; 637 rcSrc.bottom = pBox->y2; 638 639 /* Calculate destination rectangle */ 640 rcDest.left = ptOrigin.x + rcSrc.left; 641 rcDest.top = ptOrigin.y + rcSrc.top; 642 rcDest.right = ptOrigin.x + rcSrc.right; 643 rcDest.bottom = ptOrigin.y + rcSrc.bottom; 644 645 /* Blit the damaged areas */ 646 ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, 647 &rcDest, 648 pScreenPriv->pddsShadow4, 649 &rcSrc, 650 DDBLT_WAIT, 651 NULL); 652 if (FAILED (ddrval)) 653 { 654 static int s_iFailCount = 0; 655 656 if (s_iFailCount < FAIL_MSG_MAX_BLT) 657 { 658 ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () " 659 "failed: %08x\n", 660 (unsigned int) ddrval); 661 662 ++s_iFailCount; 663 664 if (s_iFailCount == FAIL_MSG_MAX_BLT) 665 { 666 ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt " 667 "failure message maximum (%d) reached. No " 668 "more failure messages will be printed.\n", 669 FAIL_MSG_MAX_BLT); 670 } 671 } 672 } 673 674 /* Get a pointer to the next box */ 675 ++pBox; 676 } 677 } 678 else 679 { 680 BoxPtr pBoxExtents = RegionExtents(damage); 681 682 /* Compute a GDI region from the damaged region */ 683 hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); 684 dwBox--; 685 pBox++; 686 while (dwBox--) 687 { 688 hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); 689 CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); 690 DeleteObject (hrgnTemp); 691 pBox++; 692 } 693 694 /* Install the GDI region as a clipping region */ 695 SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); 696 DeleteObject (hrgnCombined); 697 hrgnCombined = NULL; 698 699#if CYGDEBUG 700 winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n", 701 pBoxExtents->x1, pBoxExtents->y1, 702 pBoxExtents->x2, pBoxExtents->y2); 703#endif 704 705 /* Calculating a bounding box for the source is easy */ 706 rcSrc.left = pBoxExtents->x1; 707 rcSrc.top = pBoxExtents->y1; 708 rcSrc.right = pBoxExtents->x2; 709 rcSrc.bottom = pBoxExtents->y2; 710 711 /* Calculating a bounding box for the destination is trickier */ 712 rcDest.left = ptOrigin.x + rcSrc.left; 713 rcDest.top = ptOrigin.y + rcSrc.top; 714 rcDest.right = ptOrigin.x + rcSrc.right; 715 rcDest.bottom = ptOrigin.y + rcSrc.bottom; 716 717 /* Our Blt should be clipped to the invalidated region */ 718 ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, 719 &rcDest, 720 pScreenPriv->pddsShadow4, 721 &rcSrc, 722 DDBLT_WAIT, 723 NULL); 724 725 /* Reset the clip region */ 726 SelectClipRgn (pScreenPriv->hdcScreen, NULL); 727 } 728} 729 730 731/* 732 * Call the wrapped CloseScreen function. 733 * 734 * Free our resources and private structures. 735 */ 736 737static Bool 738winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen) 739{ 740 winScreenPriv(pScreen); 741 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 742 Bool fReturn; 743 744#if CYGDEBUG 745 winDebug ("winCloseScreenShadowDDNL - Freeing screen resources\n"); 746#endif 747 748 /* Flag that the screen is closed */ 749 pScreenPriv->fClosed = TRUE; 750 pScreenPriv->fActive = FALSE; 751 752 /* Call the wrapped CloseScreen procedure */ 753 WIN_UNWRAP(CloseScreen); 754 fReturn = (*pScreen->CloseScreen) (nIndex, pScreen); 755 756 /* Free the screen DC */ 757 ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen); 758 759 /* Delete the window property */ 760 RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP); 761 762 /* Free the shadow surface, if there is one */ 763 if (pScreenPriv->pddsShadow4) 764 { 765 IDirectDrawSurface4_Release (pScreenPriv->pddsShadow4); 766 free (pScreenInfo->pfb); 767 pScreenInfo->pfb = NULL; 768 pScreenPriv->pddsShadow4 = NULL; 769 } 770 771 /* Detach the clipper from the primary surface and release the clipper. */ 772 if (pScreenPriv->pddcPrimary) 773 { 774 /* Detach the clipper */ 775 IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4, 776 NULL); 777 778 /* Release the clipper object */ 779 IDirectDrawClipper_Release (pScreenPriv->pddcPrimary); 780 pScreenPriv->pddcPrimary = NULL; 781 } 782 783 /* Release the primary surface, if there is one */ 784 if (pScreenPriv->pddsPrimary4) 785 { 786 IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4); 787 pScreenPriv->pddsPrimary4 = NULL; 788 } 789 790 /* Free the DirectDraw4 object, if there is one */ 791 if (pScreenPriv->pdd4) 792 { 793 IDirectDraw4_RestoreDisplayMode (pScreenPriv->pdd4); 794 IDirectDraw4_Release (pScreenPriv->pdd4); 795 pScreenPriv->pdd4 = NULL; 796 } 797 798 /* Free the DirectDraw object, if there is one */ 799 if (pScreenPriv->pdd) 800 { 801 IDirectDraw_Release (pScreenPriv->pdd); 802 pScreenPriv->pdd = NULL; 803 } 804 805 /* Delete tray icon, if we have one */ 806 if (!pScreenInfo->fNoTrayIcon) 807 winDeleteNotifyIcon (pScreenPriv); 808 809 /* Free the exit confirmation dialog box, if it exists */ 810 if (g_hDlgExit != NULL) 811 { 812 DestroyWindow (g_hDlgExit); 813 g_hDlgExit = NULL; 814 } 815 816 /* Kill our window */ 817 if (pScreenPriv->hwndScreen) 818 { 819 DestroyWindow (pScreenPriv->hwndScreen); 820 pScreenPriv->hwndScreen = NULL; 821 } 822 823#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) 824 /* Destroy the thread startup mutex */ 825 pthread_mutex_destroy (&pScreenPriv->pmServerStarted); 826#endif 827 828 /* Kill our screeninfo's pointer to the screen */ 829 pScreenInfo->pScreen = NULL; 830 831 /* Invalidate the ScreenInfo's fb pointer */ 832 pScreenInfo->pfb = NULL; 833 834 /* Free the screen privates for this screen */ 835 free ((pointer) pScreenPriv); 836 837 return fReturn; 838} 839 840 841/* 842 * Tell mi what sort of visuals we need. 843 * 844 * Generally we only need one visual, as our screen can only 845 * handle one format at a time, I believe. You may want 846 * to verify that last sentence. 847 */ 848 849static Bool 850winInitVisualsShadowDDNL (ScreenPtr pScreen) 851{ 852 winScreenPriv(pScreen); 853 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 854 DWORD dwRedBits, dwGreenBits, dwBlueBits; 855 856 /* Count the number of ones in each color mask */ 857 dwRedBits = winCountBits (pScreenPriv->dwRedMask); 858 dwGreenBits = winCountBits (pScreenPriv->dwGreenMask); 859 dwBlueBits = winCountBits (pScreenPriv->dwBlueMask); 860 861 /* Store the maximum number of ones in a color mask as the bitsPerRGB */ 862 if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0) 863 pScreenPriv->dwBitsPerRGB = 8; 864 else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) 865 pScreenPriv->dwBitsPerRGB = dwRedBits; 866 else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) 867 pScreenPriv->dwBitsPerRGB = dwGreenBits; 868 else 869 pScreenPriv->dwBitsPerRGB = dwBlueBits; 870 871 winDebug ("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d " 872 "bpp %d\n", 873 (unsigned int) pScreenPriv->dwRedMask, 874 (unsigned int) pScreenPriv->dwGreenMask, 875 (unsigned int) pScreenPriv->dwBlueMask, 876 (int) pScreenPriv->dwBitsPerRGB, 877 (int) pScreenInfo->dwDepth, 878 (int) pScreenInfo->dwBPP); 879 880 /* Create a single visual according to the Windows screen depth */ 881 switch (pScreenInfo->dwDepth) 882 { 883 case 24: 884 case 16: 885 case 15: 886#if defined(XFree86Server) 887 /* Setup the real visual */ 888 if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, 889 TrueColorMask, 890 pScreenPriv->dwBitsPerRGB, 891 -1, 892 pScreenPriv->dwRedMask, 893 pScreenPriv->dwGreenMask, 894 pScreenPriv->dwBlueMask)) 895 { 896 ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks " 897 "failed for TrueColor\n"); 898 return FALSE; 899 } 900 901#ifdef XWIN_EMULATEPSEUDO 902 if (!pScreenInfo->fEmulatePseudo) 903 break; 904 905 /* Setup a pseudocolor visual */ 906 if (!miSetVisualTypesAndMasks (8, 907 PseudoColorMask, 908 8, 909 -1, 910 0, 911 0, 912 0)) 913 { 914 ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks " 915 "failed for PseudoColor\n"); 916 return FALSE; 917 } 918#endif 919#else /* XFree86Server */ 920 /* Setup the real visual */ 921 if (!fbSetVisualTypesAndMasks (pScreenInfo->dwDepth, 922 TrueColorMask, 923 pScreenPriv->dwBitsPerRGB, 924 pScreenPriv->dwRedMask, 925 pScreenPriv->dwGreenMask, 926 pScreenPriv->dwBlueMask)) 927 { 928 ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks " 929 "failed for TrueColor\n"); 930 return FALSE; 931 } 932 933#ifdef XWIN_EMULATEPSEUDO 934 if (!pScreenInfo->fEmulatePseudo) 935 break; 936 937 /* Setup a pseudocolor visual */ 938 if (!fbSetVisualTypesAndMasks (8, 939 PseudoColorMask, 940 8, 941 0, 942 0, 943 0)) 944 { 945 ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks " 946 "failed for PseudoColor\n"); 947 return FALSE; 948 } 949#endif 950#endif /* XFree86Server */ 951 break; 952 953 case 8: 954#if defined(XFree86Server) 955 if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, 956 pScreenInfo->fFullScreen 957 ? PseudoColorMask : StaticColorMask, 958 pScreenPriv->dwBitsPerRGB, 959 pScreenInfo->fFullScreen 960 ? PseudoColor : StaticColor, 961 pScreenPriv->dwRedMask, 962 pScreenPriv->dwGreenMask, 963 pScreenPriv->dwBlueMask)) 964 { 965 ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks " 966 "failed\n"); 967 return FALSE; 968 } 969#else /* XFree86Server */ 970 if (!fbSetVisualTypesAndMasks (pScreenInfo->dwDepth, 971 pScreenInfo->fFullScreen 972 ? PseudoColorMask : StaticColorMask, 973 pScreenPriv->dwBitsPerRGB, 974 pScreenPriv->dwRedMask, 975 pScreenPriv->dwGreenMask, 976 pScreenPriv->dwBlueMask)) 977 { 978 ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks " 979 "failed\n"); 980 return FALSE; 981 } 982#endif /* XFree86Server */ 983 break; 984 985 default: 986 ErrorF ("winInitVisualsShadowDDNL - Unknown screen depth\n"); 987 return FALSE; 988 } 989 990#if CYGDEBUG 991 winDebug ("winInitVisualsShadowDDNL - Returning\n"); 992#endif 993 994 return TRUE; 995} 996 997 998/* 999 * Adjust the user proposed video mode 1000 */ 1001 1002static Bool 1003winAdjustVideoModeShadowDDNL (ScreenPtr pScreen) 1004{ 1005 winScreenPriv(pScreen); 1006 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 1007 HDC hdc = NULL; 1008 DWORD dwBPP; 1009 1010 /* We're in serious trouble if we can't get a DC */ 1011 hdc = GetDC (NULL); 1012 if (hdc == NULL) 1013 { 1014 ErrorF ("winAdjustVideoModeShadowDDNL - GetDC () failed\n"); 1015 return FALSE; 1016 } 1017 1018 /* Query GDI for current display depth */ 1019 dwBPP = GetDeviceCaps (hdc, BITSPIXEL); 1020 1021 /* DirectDraw can only change the depth in fullscreen mode */ 1022 if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP) 1023 { 1024 /* No -depth parameter passed, let the user know the depth being used */ 1025 winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - Using Windows display " 1026 "depth of %d bits per pixel\n", (int) dwBPP); 1027 1028 /* Use GDI's depth */ 1029 pScreenInfo->dwBPP = dwBPP; 1030 } 1031 else if (pScreenInfo->fFullScreen 1032 && pScreenInfo->dwBPP != dwBPP) 1033 { 1034 /* FullScreen, and GDI depth differs from -depth parameter */ 1035 winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - FullScreen, using command " 1036 "line bpp: %d\n", (int) pScreenInfo->dwBPP); 1037 } 1038 else if (dwBPP != pScreenInfo->dwBPP) 1039 { 1040 /* Windowed, and GDI depth differs from -depth parameter */ 1041 winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - Windowed, command line " 1042 "bpp: %d, using bpp: %d\n", 1043 (int) pScreenInfo->dwBPP, (int) dwBPP); 1044 1045 /* We'll use GDI's depth */ 1046 pScreenInfo->dwBPP = dwBPP; 1047 } 1048 1049 /* See if the shadow bitmap will be larger than the DIB size limit */ 1050 if (pScreenInfo->dwWidth * pScreenInfo->dwHeight * pScreenInfo->dwBPP 1051 >= WIN_DIB_MAXIMUM_SIZE) 1052 { 1053 winErrorFVerb (1, "winAdjustVideoModeShadowDDNL - Requested DirectDraw surface " 1054 "will be larger than %d MB. The surface may fail to be " 1055 "allocated on Windows 95, 98, or Me, due to a %d MB limit in " 1056 "DIB size. This limit does not apply to Windows NT/2000, and " 1057 "this message may be ignored on those platforms.\n", 1058 WIN_DIB_MAXIMUM_SIZE_MB, WIN_DIB_MAXIMUM_SIZE_MB); 1059 } 1060 1061 /* Release our DC */ 1062 ReleaseDC (NULL, hdc); 1063 1064 return TRUE; 1065} 1066 1067 1068/* 1069 * Blt exposed regions to the screen 1070 */ 1071 1072static Bool 1073winBltExposedRegionsShadowDDNL (ScreenPtr pScreen) 1074{ 1075 winScreenPriv(pScreen); 1076 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 1077 RECT rcSrc, rcDest; 1078 POINT ptOrigin; 1079 HDC hdcUpdate; 1080 PAINTSTRUCT ps; 1081 HRESULT ddrval = DD_OK; 1082 Bool fReturn = TRUE; 1083 int i; 1084 1085 /* Quite common case. The primary surface was lost (maybe because of depth 1086 * change). Try to create a new primary surface. Bail out if this fails */ 1087 if (pScreenPriv->pddsPrimary4 == NULL && pScreenPriv->fRetryCreateSurface && 1088 !winCreatePrimarySurfaceShadowDDNL(pScreen)) 1089 { 1090 Sleep(100); 1091 return FALSE; 1092 } 1093 if (pScreenPriv->pddsPrimary4 == NULL) 1094 return FALSE; 1095 1096 /* BeginPaint gives us an hdc that clips to the invalidated region */ 1097 hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps); 1098 if (hdcUpdate == NULL) 1099 { 1100 fReturn = FALSE; 1101 ErrorF ("winBltExposedRegionsShadowDDNL - BeginPaint () returned " 1102 "a NULL device context handle. Aborting blit attempt.\n"); 1103 goto winBltExposedRegionsShadowDDNL_Exit; 1104 } 1105 1106 /* Get the origin of the window in the screen coords */ 1107 ptOrigin.x = pScreenInfo->dwXOffset; 1108 ptOrigin.y = pScreenInfo->dwYOffset; 1109 1110 MapWindowPoints (pScreenPriv->hwndScreen, 1111 HWND_DESKTOP, 1112 (LPPOINT)&ptOrigin, 1); 1113 rcDest.left = ptOrigin.x; 1114 rcDest.right = ptOrigin.x + pScreenInfo->dwWidth; 1115 rcDest.top = ptOrigin.y; 1116 rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight; 1117 1118 /* Source can be entire shadow surface, as Blt should clip for us */ 1119 rcSrc.left = 0; 1120 rcSrc.top = 0; 1121 rcSrc.right = pScreenInfo->dwWidth; 1122 rcSrc.bottom = pScreenInfo->dwHeight; 1123 1124 /* Try to regain the primary surface and blit again if we've lost it */ 1125 for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i) 1126 { 1127 /* Our Blt should be clipped to the invalidated region */ 1128 ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, 1129 &rcDest, 1130 pScreenPriv->pddsShadow4, 1131 &rcSrc, 1132 DDBLT_WAIT, 1133 NULL); 1134 if (ddrval == DDERR_SURFACELOST) 1135 { 1136 /* Surface was lost */ 1137 winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - " 1138 "IDirectDrawSurface4_Blt reported that the primary " 1139 "surface was lost, trying to restore, retry: %d\n", i + 1); 1140 1141 /* Try to restore the surface, once */ 1142 1143 ddrval = IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4); 1144 winDebug ("winBltExposedRegionsShadowDDNL - " 1145 "IDirectDrawSurface4_Restore returned: "); 1146 if (ddrval == DD_OK) 1147 winDebug ("DD_OK\n"); 1148 else if (ddrval == DDERR_WRONGMODE) 1149 winDebug ("DDERR_WRONGMODE\n"); 1150 else if (ddrval == DDERR_INCOMPATIBLEPRIMARY) 1151 winDebug ("DDERR_INCOMPATIBLEPRIMARY\n"); 1152 else if (ddrval == DDERR_UNSUPPORTED) 1153 winDebug ("DDERR_UNSUPPORTED\n"); 1154 else if (ddrval == DDERR_INVALIDPARAMS) 1155 winDebug ("DDERR_INVALIDPARAMS\n"); 1156 else if (ddrval == DDERR_INVALIDOBJECT) 1157 winDebug ("DDERR_INVALIDOBJECT\n"); 1158 else 1159 winDebug ("unknown error: %08x\n", (unsigned int) ddrval); 1160 1161 /* Loop around to try the blit one more time */ 1162 continue; 1163 } 1164 else if (FAILED (ddrval)) 1165 { 1166 fReturn = FALSE; 1167 winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - " 1168 "IDirectDrawSurface4_Blt failed, but surface not " 1169 "lost: %08x %d\n", 1170 (unsigned int) ddrval, (int) ddrval); 1171 goto winBltExposedRegionsShadowDDNL_Exit; 1172 } 1173 else 1174 { 1175 /* Success, stop looping */ 1176 break; 1177 } 1178 } 1179 1180 winBltExposedRegionsShadowDDNL_Exit: 1181 /* EndPaint frees the DC */ 1182 if (hdcUpdate != NULL) 1183 EndPaint (pScreenPriv->hwndScreen, &ps); 1184 return fReturn; 1185} 1186 1187 1188/* 1189 * Do any engine-specific application-activation processing 1190 */ 1191 1192static Bool 1193winActivateAppShadowDDNL (ScreenPtr pScreen) 1194{ 1195 winScreenPriv(pScreen); 1196 1197 /* 1198 * Do we have a surface? 1199 * Are we active? 1200 * Are we full screen? 1201 */ 1202 if (pScreenPriv != NULL 1203 && pScreenPriv->pddsPrimary4 != NULL 1204 && pScreenPriv->fActive) 1205 { 1206 /* Primary surface was lost, restore it */ 1207 IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4); 1208 } 1209 1210 return TRUE; 1211} 1212 1213 1214/* 1215 * Reblit the shadow framebuffer to the screen. 1216 */ 1217 1218static Bool 1219winRedrawScreenShadowDDNL (ScreenPtr pScreen) 1220{ 1221 winScreenPriv(pScreen); 1222 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 1223 HRESULT ddrval = DD_OK; 1224 RECT rcSrc, rcDest; 1225 POINT ptOrigin; 1226 1227 /* Get the origin of the window in the screen coords */ 1228 ptOrigin.x = pScreenInfo->dwXOffset; 1229 ptOrigin.y = pScreenInfo->dwYOffset; 1230 MapWindowPoints (pScreenPriv->hwndScreen, 1231 HWND_DESKTOP, 1232 (LPPOINT)&ptOrigin, 1); 1233 rcDest.left = ptOrigin.x; 1234 rcDest.right = ptOrigin.x + pScreenInfo->dwWidth; 1235 rcDest.top = ptOrigin.y; 1236 rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight; 1237 1238 /* Source can be entire shadow surface, as Blt should clip for us */ 1239 rcSrc.left = 0; 1240 rcSrc.top = 0; 1241 rcSrc.right = pScreenInfo->dwWidth; 1242 rcSrc.bottom = pScreenInfo->dwHeight; 1243 1244 /* Redraw the whole window, to take account for the new colors */ 1245 ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, 1246 &rcDest, 1247 pScreenPriv->pddsShadow4, 1248 &rcSrc, 1249 DDBLT_WAIT, 1250 NULL); 1251 if (FAILED (ddrval)) 1252 { 1253 ErrorF ("winRedrawScreenShadowDDNL - IDirectDrawSurface4_Blt () " 1254 "failed: %08x\n", 1255 (unsigned int) ddrval); 1256 } 1257 1258 return TRUE; 1259} 1260 1261 1262/* 1263 * Realize the currently installed colormap 1264 */ 1265 1266static Bool 1267winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen) 1268{ 1269 return TRUE; 1270} 1271 1272 1273/* 1274 * Install the specified colormap 1275 */ 1276 1277static Bool 1278winInstallColormapShadowDDNL (ColormapPtr pColormap) 1279{ 1280 ScreenPtr pScreen = pColormap->pScreen; 1281 winScreenPriv(pScreen); 1282 winCmapPriv(pColormap); 1283 HRESULT ddrval = DD_OK; 1284 1285 /* Install the DirectDraw palette on the primary surface */ 1286 ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4, 1287 pCmapPriv->lpDDPalette); 1288 if (FAILED (ddrval)) 1289 { 1290 ErrorF ("winInstallColormapShadowDDNL - Failed installing the " 1291 "DirectDraw palette.\n"); 1292 return FALSE; 1293 } 1294 1295 /* Save a pointer to the newly installed colormap */ 1296 pScreenPriv->pcmapInstalled = pColormap; 1297 1298 return TRUE; 1299} 1300 1301 1302/* 1303 * Store the specified colors in the specified colormap 1304 */ 1305 1306static Bool 1307winStoreColorsShadowDDNL (ColormapPtr pColormap, 1308 int ndef, 1309 xColorItem *pdefs) 1310{ 1311 ScreenPtr pScreen = pColormap->pScreen; 1312 winScreenPriv(pScreen); 1313 winCmapPriv(pColormap); 1314 ColormapPtr curpmap = pScreenPriv->pcmapInstalled; 1315 HRESULT ddrval = DD_OK; 1316 1317 /* Put the X colormap entries into the Windows logical palette */ 1318 ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette, 1319 0, 1320 pdefs[0].pixel, 1321 ndef, 1322 pCmapPriv->peColors 1323 + pdefs[0].pixel); 1324 if (FAILED (ddrval)) 1325 { 1326 ErrorF ("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n", (unsigned int) ddrval); 1327 return FALSE; 1328 } 1329 1330 /* Don't install the DirectDraw palette if the colormap is not installed */ 1331 if (pColormap != curpmap) 1332 { 1333 return TRUE; 1334 } 1335 1336 if (!winInstallColormapShadowDDNL (pColormap)) 1337 { 1338 ErrorF ("winStoreColorsShadowDDNL - Failed installing colormap\n"); 1339 return FALSE; 1340 } 1341 1342 return TRUE; 1343} 1344 1345 1346/* 1347 * Colormap initialization procedure 1348 */ 1349 1350static Bool 1351winCreateColormapShadowDDNL (ColormapPtr pColormap) 1352{ 1353 HRESULT ddrval = DD_OK; 1354 ScreenPtr pScreen = pColormap->pScreen; 1355 winScreenPriv(pScreen); 1356 winCmapPriv(pColormap); 1357 1358 /* Create a DirectDraw palette */ 1359 ddrval = IDirectDraw4_CreatePalette (pScreenPriv->pdd4, 1360 DDPCAPS_8BIT | DDPCAPS_ALLOW256, 1361 pCmapPriv->peColors, 1362 &pCmapPriv->lpDDPalette, 1363 NULL); 1364 if (FAILED (ddrval)) 1365 { 1366 ErrorF ("winCreateColormapShadowDDNL - CreatePalette failed\n"); 1367 return FALSE; 1368 } 1369 1370 return TRUE; 1371} 1372 1373 1374/* 1375 * Colormap destruction procedure 1376 */ 1377 1378static Bool 1379winDestroyColormapShadowDDNL (ColormapPtr pColormap) 1380{ 1381 winScreenPriv(pColormap->pScreen); 1382 winCmapPriv(pColormap); 1383 HRESULT ddrval = DD_OK; 1384 1385 /* 1386 * Is colormap to be destroyed the default? 1387 * 1388 * Non-default colormaps should have had winUninstallColormap 1389 * called on them before we get here. The default colormap 1390 * will not have had winUninstallColormap called on it. Thus, 1391 * we need to handle the default colormap in a special way. 1392 */ 1393 if (pColormap->flags & IsDefault) 1394 { 1395#if CYGDEBUG 1396 winDebug ("winDestroyColormapShadowDDNL - Destroying default colormap\n"); 1397#endif 1398 1399 /* 1400 * FIXME: Walk the list of all screens, popping the default 1401 * palette out of each screen device context. 1402 */ 1403 1404 /* Pop the palette out of the primary surface */ 1405 ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4, 1406 NULL); 1407 if (FAILED (ddrval)) 1408 { 1409 ErrorF ("winDestroyColormapShadowDDNL - Failed freeing the " 1410 "default colormap DirectDraw palette.\n"); 1411 return FALSE; 1412 } 1413 1414 /* Clear our private installed colormap pointer */ 1415 pScreenPriv->pcmapInstalled = NULL; 1416 } 1417 1418 /* Release the palette */ 1419 IDirectDrawPalette_Release (pCmapPriv->lpDDPalette); 1420 1421 /* Invalidate the colormap privates */ 1422 pCmapPriv->lpDDPalette = NULL; 1423 1424 return TRUE; 1425} 1426 1427 1428/* 1429 * Set pointers to our engine specific functions 1430 */ 1431 1432Bool 1433winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen) 1434{ 1435 winScreenPriv(pScreen); 1436 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 1437 1438 /* Set our pointers */ 1439 pScreenPriv->pwinAllocateFB = winAllocateFBShadowDDNL; 1440 pScreenPriv->pwinShadowUpdate = winShadowUpdateDDNL; 1441 pScreenPriv->pwinCloseScreen = winCloseScreenShadowDDNL; 1442 pScreenPriv->pwinInitVisuals = winInitVisualsShadowDDNL; 1443 pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDDNL; 1444 if (pScreenInfo->fFullScreen) 1445 pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen; 1446 else 1447 pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; 1448 pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; 1449 pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL; 1450 pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL; 1451 pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL; 1452 pScreenPriv->pwinRealizeInstalledPalette 1453 = winRealizeInstalledPaletteShadowDDNL; 1454 pScreenPriv->pwinInstallColormap = winInstallColormapShadowDDNL; 1455 pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL; 1456 pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL; 1457 pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL; 1458 pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA; 1459 pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL; 1460 pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL; 1461#ifdef XWIN_MULTIWINDOW 1462 pScreenPriv->pwinFinishCreateWindowsWindow 1463 = winFinishCreateWindowsWindowDDNL; 1464#endif 1465 1466 return TRUE; 1467} 1468