winshadgdi.c revision 05b261ec
1/* 2 *Copyright (C) 2001-2004 Harold L Hunt II 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 HAROLD L HUNT II 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 Harold L Hunt II 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 Harold L Hunt II. 27 * 28 * Authors: Harold L Hunt II 29 */ 30 31#ifdef HAVE_XWIN_CONFIG_H 32#include <xwin-config.h> 33#endif 34#include "win.h" 35 36 37/* 38 * External symbols 39 */ 40 41#ifdef XWIN_MULTIWINDOW 42extern DWORD g_dwCurrentThreadID; 43#endif 44extern HWND g_hDlgExit; 45 46 47/* 48 * Local function prototypes 49 */ 50 51#ifdef XWIN_MULTIWINDOW 52static wBOOL CALLBACK 53winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam); 54 55static wBOOL CALLBACK 56winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam); 57#endif 58 59static Bool 60winAllocateFBShadowGDI (ScreenPtr pScreen); 61 62static void 63winShadowUpdateGDI (ScreenPtr pScreen, 64 shadowBufPtr pBuf); 65 66static Bool 67winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen); 68 69static Bool 70winInitVisualsShadowGDI (ScreenPtr pScreen); 71 72static Bool 73winAdjustVideoModeShadowGDI (ScreenPtr pScreen); 74 75static Bool 76winBltExposedRegionsShadowGDI (ScreenPtr pScreen); 77 78static Bool 79winActivateAppShadowGDI (ScreenPtr pScreen); 80 81static Bool 82winRedrawScreenShadowGDI (ScreenPtr pScreen); 83 84static Bool 85winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen); 86 87static Bool 88winInstallColormapShadowGDI (ColormapPtr pColormap); 89 90static Bool 91winStoreColorsShadowGDI (ColormapPtr pmap, 92 int ndef, 93 xColorItem *pdefs); 94 95static Bool 96winCreateColormapShadowGDI (ColormapPtr pColormap); 97 98static Bool 99winDestroyColormapShadowGDI (ColormapPtr pColormap); 100 101 102/* 103 * Internal function to get the DIB format that is compatible with the screen 104 */ 105 106static 107Bool 108winQueryScreenDIBFormat (ScreenPtr pScreen, BITMAPINFOHEADER *pbmih) 109{ 110 winScreenPriv(pScreen); 111 HBITMAP hbmp; 112#if CYGDEBUG 113 LPDWORD pdw = NULL; 114#endif 115 116 /* Create a memory bitmap compatible with the screen */ 117 hbmp = CreateCompatibleBitmap (pScreenPriv->hdcScreen, 1, 1); 118 if (hbmp == NULL) 119 { 120 ErrorF ("winQueryScreenDIBFormat - CreateCompatibleBitmap failed\n"); 121 return FALSE; 122 } 123 124 /* Initialize our bitmap info header */ 125 ZeroMemory (pbmih, sizeof (BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD)); 126 pbmih->biSize = sizeof (BITMAPINFOHEADER); 127 128 /* Get the biBitCount */ 129 if (!GetDIBits (pScreenPriv->hdcScreen, 130 hbmp, 131 0, 1, 132 NULL, 133 (BITMAPINFO*) pbmih, 134 DIB_RGB_COLORS)) 135 { 136 ErrorF ("winQueryScreenDIBFormat - First call to GetDIBits failed\n"); 137 DeleteObject (hbmp); 138 return FALSE; 139 } 140 141#if CYGDEBUG 142 /* Get a pointer to bitfields */ 143 pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER)); 144 145 winDebug ("winQueryScreenDIBFormat - First call masks: %08x %08x %08x\n", 146 pdw[0], pdw[1], pdw[2]); 147#endif 148 149 /* Get optimal color table, or the optimal bitfields */ 150 if (!GetDIBits (pScreenPriv->hdcScreen, 151 hbmp, 152 0, 1, 153 NULL, 154 (BITMAPINFO*)pbmih, 155 DIB_RGB_COLORS)) 156 { 157 ErrorF ("winQueryScreenDIBFormat - Second call to GetDIBits " 158 "failed\n"); 159 DeleteObject (hbmp); 160 return FALSE; 161 } 162 163 /* Free memory */ 164 DeleteObject (hbmp); 165 166 return TRUE; 167} 168 169 170/* 171 * Internal function to determine the GDI bits per rgb and bit masks 172 */ 173 174static 175Bool 176winQueryRGBBitsAndMasks (ScreenPtr pScreen) 177{ 178 winScreenPriv(pScreen); 179 BITMAPINFOHEADER *pbmih = NULL; 180 Bool fReturn = TRUE; 181 LPDWORD pdw = NULL; 182 DWORD dwRedBits, dwGreenBits, dwBlueBits; 183 184 /* Color masks for 8 bpp are standardized */ 185 if (GetDeviceCaps (pScreenPriv->hdcScreen, RASTERCAPS) & RC_PALETTE) 186 { 187 /* 188 * RGB BPP for 8 bit palletes is always 8 189 * and the color masks are always 0. 190 */ 191 pScreenPriv->dwBitsPerRGB = 8; 192 pScreenPriv->dwRedMask = 0x0L; 193 pScreenPriv->dwGreenMask = 0x0L; 194 pScreenPriv->dwBlueMask = 0x0L; 195 return TRUE; 196 } 197 198 /* Color masks for 24 bpp are standardized */ 199 if (GetDeviceCaps (pScreenPriv->hdcScreen, PLANES) 200 * GetDeviceCaps (pScreenPriv->hdcScreen, BITSPIXEL) == 24) 201 { 202 ErrorF ("winQueryRGBBitsAndMasks - GetDeviceCaps (BITSPIXEL) " 203 "returned 24 for the screen. Using default 24bpp masks.\n"); 204 205 /* 8 bits per primary color */ 206 pScreenPriv->dwBitsPerRGB = 8; 207 208 /* Set screen privates masks */ 209 pScreenPriv->dwRedMask = WIN_24BPP_MASK_RED; 210 pScreenPriv->dwGreenMask = WIN_24BPP_MASK_GREEN; 211 pScreenPriv->dwBlueMask = WIN_24BPP_MASK_BLUE; 212 213 return TRUE; 214 } 215 216 /* Allocate a bitmap header and color table */ 217 pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER) 218 + 256 * sizeof (RGBQUAD)); 219 if (pbmih == NULL) 220 { 221 ErrorF ("winQueryRGBBitsAndMasks - malloc failed\n"); 222 return FALSE; 223 } 224 225 /* Get screen description */ 226 if (winQueryScreenDIBFormat (pScreen, pbmih)) 227 { 228 /* Get a pointer to bitfields */ 229 pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER)); 230 231#if CYGDEBUG 232 winDebug ("%s - Masks: %08x %08x %08x\n", __FUNCTION__, 233 pdw[0], pdw[1], pdw[2]); 234 winDebug ("%s - Bitmap: %dx%d %d bpp %d planes\n", __FUNCTION__, 235 pbmih->biWidth, pbmih->biHeight, pbmih->biBitCount, pbmih->biPlanes); 236 winDebug ("%s - Compression: %d %s\n", __FUNCTION__, 237 pbmih->biCompression, 238 (pbmih->biCompression == BI_RGB?"(BI_RGB)": 239 (pbmih->biCompression == BI_RLE8?"(BI_RLE8)": 240 (pbmih->biCompression == BI_RLE4?"(BI_RLE4)": 241 (pbmih->biCompression == BI_BITFIELDS?"(BI_BITFIELDS)":"" 242 ))))); 243#endif 244 245 /* Handle BI_RGB case, which is returned by Wine */ 246 if (pbmih->biCompression == BI_RGB) 247 { 248 dwRedBits = 5; 249 dwGreenBits = 5; 250 dwBlueBits = 5; 251 252 pScreenPriv->dwBitsPerRGB = 5; 253 254 /* Set screen privates masks */ 255 pScreenPriv->dwRedMask = 0x7c00; 256 pScreenPriv->dwGreenMask = 0x03e0; 257 pScreenPriv->dwBlueMask = 0x001f; 258 } 259 else 260 { 261 /* Count the number of bits in each mask */ 262 dwRedBits = winCountBits (pdw[0]); 263 dwGreenBits = winCountBits (pdw[1]); 264 dwBlueBits = winCountBits (pdw[2]); 265 266 /* Find maximum bits per red, green, blue */ 267 if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) 268 pScreenPriv->dwBitsPerRGB = dwRedBits; 269 else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) 270 pScreenPriv->dwBitsPerRGB = dwGreenBits; 271 else 272 pScreenPriv->dwBitsPerRGB = dwBlueBits; 273 274 /* Set screen privates masks */ 275 pScreenPriv->dwRedMask = pdw[0]; 276 pScreenPriv->dwGreenMask = pdw[1]; 277 pScreenPriv->dwBlueMask = pdw[2]; 278 } 279 } 280 else 281 { 282 ErrorF ("winQueryRGBBitsAndMasks - winQueryScreenDIBFormat failed\n"); 283 free (pbmih); 284 fReturn = FALSE; 285 } 286 287 /* Free memory */ 288 free (pbmih); 289 290 return fReturn; 291} 292 293 294#ifdef XWIN_MULTIWINDOW 295/* 296 * Redraw all ---? 297 */ 298 299static wBOOL CALLBACK 300winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam) 301{ 302 if (hwnd == (HWND)lParam) 303 return TRUE; 304 InvalidateRect (hwnd, NULL, FALSE); 305 UpdateWindow (hwnd); 306 return TRUE; 307} 308 309static wBOOL CALLBACK 310winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam) 311{ 312 BoxPtr pDamage = (BoxPtr)lParam; 313 RECT rcClient, rcDamage, rcRedraw; 314 POINT topLeft, bottomRight; 315 316 if (IsIconic (hwnd)) 317 return TRUE; /* Don't care minimized windows */ 318 319 /* Convert the damaged area from Screen coords to Client coords */ 320 topLeft.x = pDamage->x1; topLeft.y = pDamage->y1; 321 bottomRight.x = pDamage->x2; bottomRight.y = pDamage->y2; 322 topLeft.x += GetSystemMetrics (SM_XVIRTUALSCREEN); 323 bottomRight.x += GetSystemMetrics (SM_XVIRTUALSCREEN); 324 topLeft.y += GetSystemMetrics (SM_YVIRTUALSCREEN); 325 bottomRight.y += GetSystemMetrics (SM_YVIRTUALSCREEN); 326 ScreenToClient (hwnd, &topLeft); 327 ScreenToClient (hwnd, &bottomRight); 328 SetRect (&rcDamage, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); 329 330 GetClientRect (hwnd, &rcClient); 331 332 if (IntersectRect (&rcRedraw, &rcClient, &rcDamage)) 333 { 334 InvalidateRect (hwnd, &rcRedraw, FALSE); 335 UpdateWindow (hwnd); 336 } 337 return TRUE; 338} 339#endif 340 341 342/* 343 * Allocate a DIB for the shadow framebuffer GDI server 344 */ 345 346static Bool 347winAllocateFBShadowGDI (ScreenPtr pScreen) 348{ 349 winScreenPriv(pScreen); 350 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 351 BITMAPINFOHEADER *pbmih = NULL; 352 DIBSECTION dibsection; 353 Bool fReturn = TRUE; 354 355 /* Get device contexts for the screen and shadow bitmap */ 356 pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen); 357 pScreenPriv->hdcShadow = CreateCompatibleDC (pScreenPriv->hdcScreen); 358 359 /* Allocate bitmap info header */ 360 pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER) 361 + 256 * sizeof (RGBQUAD)); 362 if (pbmih == NULL) 363 { 364 ErrorF ("winAllocateFBShadowGDI - malloc () failed\n"); 365 return FALSE; 366 } 367 368 /* Query the screen format */ 369 fReturn = winQueryScreenDIBFormat (pScreen, pbmih); 370 371 /* Describe shadow bitmap to be created */ 372 pbmih->biWidth = pScreenInfo->dwWidth; 373 pbmih->biHeight = -pScreenInfo->dwHeight; 374 375 ErrorF ("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d " 376 "depth: %d\n", 377 (int) pbmih->biWidth, (int) -pbmih->biHeight, pbmih->biBitCount); 378 379 /* Create a DI shadow bitmap with a bit pointer */ 380 pScreenPriv->hbmpShadow = CreateDIBSection (pScreenPriv->hdcScreen, 381 (BITMAPINFO *) pbmih, 382 DIB_RGB_COLORS, 383 (VOID**) &pScreenInfo->pfb, 384 NULL, 385 0); 386 if (pScreenPriv->hbmpShadow == NULL || pScreenInfo->pfb == NULL) 387 { 388 winW32Error (2, "winAllocateFBShadowGDI - CreateDIBSection failed:"); 389 return FALSE; 390 } 391 else 392 { 393#if CYGDEBUG 394 winDebug ("winAllocateFBShadowGDI - Shadow buffer allocated\n"); 395#endif 396 } 397 398 /* Get information about the bitmap that was allocated */ 399 GetObject (pScreenPriv->hbmpShadow, 400 sizeof (dibsection), 401 &dibsection); 402 403#if CYGDEBUG || YES 404 /* Print information about bitmap allocated */ 405 winDebug ("winAllocateFBShadowGDI - Dibsection width: %d height: %d " 406 "depth: %d size image: %d\n", 407 (int) dibsection.dsBmih.biWidth, (int) dibsection.dsBmih.biHeight, 408 dibsection.dsBmih.biBitCount, 409 (int) dibsection.dsBmih.biSizeImage); 410#endif 411 412 /* Select the shadow bitmap into the shadow DC */ 413 SelectObject (pScreenPriv->hdcShadow, 414 pScreenPriv->hbmpShadow); 415 416#if CYGDEBUG 417 winDebug ("winAllocateFBShadowGDI - Attempting a shadow blit\n"); 418#endif 419 420 /* Do a test blit from the shadow to the screen, I think */ 421 fReturn = BitBlt (pScreenPriv->hdcScreen, 422 0, 0, 423 pScreenInfo->dwWidth, pScreenInfo->dwHeight, 424 pScreenPriv->hdcShadow, 425 0, 0, 426 SRCCOPY); 427 if (fReturn) 428 { 429#if CYGDEBUG 430 winDebug ("winAllocateFBShadowGDI - Shadow blit success\n"); 431#endif 432 } 433 else 434 { 435 winW32Error (2, "winAllocateFBShadowGDI - Shadow blit failure\n"); 436#if 0 437 return FALSE; 438#else 439 /* ago: ignore this error. The blit fails with wine, but does not 440 * cause any problems later. */ 441 442 fReturn = TRUE; 443#endif 444 } 445 446 /* Look for height weirdness */ 447 if (dibsection.dsBmih.biHeight < 0) 448 { 449 dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight; 450 } 451 452 /* Set screeninfo stride */ 453 pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage 454 / dibsection.dsBmih.biHeight) 455 * 8) / pScreenInfo->dwBPP; 456 457#if CYGDEBUG || YES 458 winDebug ("winAllocateFBShadowGDI - Created shadow stride: %d\n", 459 (int) pScreenInfo->dwStride); 460#endif 461 462 /* See if the shadow bitmap will be larger than the DIB size limit */ 463 if (pScreenInfo->dwWidth * pScreenInfo->dwHeight * pScreenInfo->dwBPP 464 >= WIN_DIB_MAXIMUM_SIZE) 465 { 466 ErrorF ("winAllocateFBShadowGDI - Requested DIB (bitmap) " 467 "will be larger than %d MB. The surface may fail to be " 468 "allocated on Windows 95, 98, or Me, due to a %d MB limit in " 469 "DIB size. This limit does not apply to Windows NT/2000, and " 470 "this message may be ignored on those platforms.\n", 471 WIN_DIB_MAXIMUM_SIZE_MB, WIN_DIB_MAXIMUM_SIZE_MB); 472 } 473 474 /* Determine our color masks */ 475 if (!winQueryRGBBitsAndMasks (pScreen)) 476 { 477 ErrorF ("winAllocateFBShadowGDI - winQueryRGBBitsAndMasks failed\n"); 478 return FALSE; 479 } 480 481#ifdef XWIN_MULTIWINDOW 482 /* Redraw all windows */ 483 if (pScreenInfo->fMultiWindow) 484 EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0); 485#endif 486 487 return fReturn; 488} 489 490 491/* 492 * Blit the damaged regions of the shadow fb to the screen 493 */ 494 495static void 496winShadowUpdateGDI (ScreenPtr pScreen, 497 shadowBufPtr pBuf) 498{ 499 winScreenPriv(pScreen); 500 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 501 RegionPtr damage = &pBuf->damage; 502 DWORD dwBox = REGION_NUM_RECTS (damage); 503 BoxPtr pBox = REGION_RECTS (damage); 504 int x, y, w, h; 505 HRGN hrgnTemp = NULL, hrgnCombined = NULL; 506#ifdef XWIN_UPDATESTATS 507 static DWORD s_dwNonUnitRegions = 0; 508 static DWORD s_dwTotalUpdates = 0; 509 static DWORD s_dwTotalBoxes = 0; 510#endif 511 BoxPtr pBoxExtents = REGION_EXTENTS (pScreen, damage); 512 513 /* 514 * Return immediately if the app is not active 515 * and we are fullscreen, or if we have a bad display depth 516 */ 517 if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) 518 || pScreenPriv->fBadDepth) return; 519 520#ifdef XWIN_UPDATESTATS 521 ++s_dwTotalUpdates; 522 s_dwTotalBoxes += dwBox; 523 524 if (dwBox != 1) 525 { 526 ++s_dwNonUnitRegions; 527 ErrorF ("winShadowUpdatGDI - dwBox: %d\n", dwBox); 528 } 529 530 if ((s_dwTotalUpdates % 100) == 0) 531 ErrorF ("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d " 532 "nu: %d tu: %d\n", 533 (s_dwNonUnitRegions * 100) / s_dwTotalUpdates, 534 s_dwTotalBoxes / s_dwTotalUpdates, 535 s_dwNonUnitRegions, s_dwTotalUpdates); 536#endif /* XWIN_UPDATESTATS */ 537 538 /* 539 * Handle small regions with multiple blits, 540 * handle large regions by creating a clipping region and 541 * doing a single blit constrained to that clipping region. 542 */ 543 if (!pScreenInfo->fMultiWindow && 544 (pScreenInfo->dwClipUpdatesNBoxes == 0 || 545 dwBox < pScreenInfo->dwClipUpdatesNBoxes)) 546 { 547 /* Loop through all boxes in the damaged region */ 548 while (dwBox--) 549 { 550 /* 551 * Calculate x offset, y offset, width, and height for 552 * current damage box 553 */ 554 x = pBox->x1; 555 y = pBox->y1; 556 w = pBox->x2 - pBox->x1; 557 h = pBox->y2 - pBox->y1; 558 559 BitBlt (pScreenPriv->hdcScreen, 560 x, y, 561 w, h, 562 pScreenPriv->hdcShadow, 563 x, y, 564 SRCCOPY); 565 566 /* Get a pointer to the next box */ 567 ++pBox; 568 } 569 } 570 else if (!pScreenInfo->fMultiWindow) 571 { 572 /* Compute a GDI region from the damaged region */ 573 hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); 574 dwBox--; 575 pBox++; 576 while (dwBox--) 577 { 578 hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); 579 CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); 580 DeleteObject (hrgnTemp); 581 pBox++; 582 } 583 584 /* Install the GDI region as a clipping region */ 585 SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); 586 DeleteObject (hrgnCombined); 587 hrgnCombined = NULL; 588 589 /* 590 * Blit the shadow buffer to the screen, 591 * constrained to the clipping region. 592 */ 593 BitBlt (pScreenPriv->hdcScreen, 594 pBoxExtents->x1, pBoxExtents->y1, 595 pBoxExtents->x2 - pBoxExtents->x1, 596 pBoxExtents->y2 - pBoxExtents->y1, 597 pScreenPriv->hdcShadow, 598 pBoxExtents->x1, pBoxExtents->y1, 599 SRCCOPY); 600 601 /* Reset the clip region */ 602 SelectClipRgn (pScreenPriv->hdcScreen, NULL); 603 } 604 605#ifdef XWIN_MULTIWINDOW 606 /* Redraw all multiwindow windows */ 607 if (pScreenInfo->fMultiWindow) 608 EnumThreadWindows (g_dwCurrentThreadID, 609 winRedrawDamagedWindowShadowGDI, 610 (LPARAM)pBoxExtents); 611#endif 612} 613 614 615/* See Porting Layer Definition - p. 33 */ 616/* 617 * We wrap whatever CloseScreen procedure was specified by fb; 618 * a pointer to said procedure is stored in our privates. 619 */ 620 621static Bool 622winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen) 623{ 624 winScreenPriv(pScreen); 625 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 626 Bool fReturn; 627 628#if CYGDEBUG 629 winDebug ("winCloseScreenShadowGDI - Freeing screen resources\n"); 630#endif 631 632 /* Flag that the screen is closed */ 633 pScreenPriv->fClosed = TRUE; 634 pScreenPriv->fActive = FALSE; 635 636 /* Call the wrapped CloseScreen procedure */ 637 WIN_UNWRAP(CloseScreen); 638 fReturn = (*pScreen->CloseScreen) (nIndex, pScreen); 639 640 /* Delete the window property */ 641 RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP); 642 643 /* Free the shadow DC; which allows the bitmap to be freed */ 644 DeleteDC (pScreenPriv->hdcShadow); 645 646 /* Free the shadow bitmap */ 647 DeleteObject (pScreenPriv->hbmpShadow); 648 649 /* Free the screen DC */ 650 ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen); 651 652 /* Delete tray icon, if we have one */ 653 if (!pScreenInfo->fNoTrayIcon) 654 winDeleteNotifyIcon (pScreenPriv); 655 656 /* Free the exit confirmation dialog box, if it exists */ 657 if (g_hDlgExit != NULL) 658 { 659 DestroyWindow (g_hDlgExit); 660 g_hDlgExit = NULL; 661 } 662 663 /* Kill our window */ 664 if (pScreenPriv->hwndScreen) 665 { 666 DestroyWindow (pScreenPriv->hwndScreen); 667 pScreenPriv->hwndScreen = NULL; 668 } 669 670#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW) 671 /* Destroy the thread startup mutex */ 672 pthread_mutex_destroy (&pScreenPriv->pmServerStarted); 673#endif 674 675 /* Invalidate our screeninfo's pointer to the screen */ 676 pScreenInfo->pScreen = NULL; 677 678 /* Invalidate the ScreenInfo's fb pointer */ 679 pScreenInfo->pfb = NULL; 680 681 /* Free the screen privates for this screen */ 682 free ((pointer) pScreenPriv); 683 684 return fReturn; 685} 686 687 688/* 689 * Tell mi what sort of visuals we need. 690 * 691 * Generally we only need one visual, as our screen can only 692 * handle one format at a time, I believe. You may want 693 * to verify that last sentence. 694 */ 695 696static Bool 697winInitVisualsShadowGDI (ScreenPtr pScreen) 698{ 699 winScreenPriv(pScreen); 700 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 701 702 /* Display debugging information */ 703 ErrorF ("winInitVisualsShadowGDI - Masks %08x %08x %08x BPRGB %d d %d " 704 "bpp %d\n", 705 (unsigned int) pScreenPriv->dwRedMask, 706 (unsigned int) pScreenPriv->dwGreenMask, 707 (unsigned int) pScreenPriv->dwBlueMask, 708 (int) pScreenPriv->dwBitsPerRGB, 709 (int) pScreenInfo->dwDepth, 710 (int) pScreenInfo->dwBPP); 711 712 /* Create a single visual according to the Windows screen depth */ 713 switch (pScreenInfo->dwDepth) 714 { 715 case 24: 716 case 16: 717 case 15: 718#if defined(XFree86Server) 719 /* Setup the real visual */ 720 if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, 721 TrueColorMask, 722 pScreenPriv->dwBitsPerRGB, 723 -1, 724 pScreenPriv->dwRedMask, 725 pScreenPriv->dwGreenMask, 726 pScreenPriv->dwBlueMask)) 727 { 728 ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks " 729 "failed\n"); 730 return FALSE; 731 } 732 733#ifdef XWIN_EMULATEPSEUDO 734 if (!pScreenInfo->fEmulatePseudo) 735 break; 736 737 /* Setup a pseudocolor visual */ 738 if (!miSetVisualTypesAndMasks (8, 739 PseudoColorMask, 740 8, 741 -1, 742 0, 743 0, 744 0)) 745 { 746 ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks " 747 "failed for PseudoColor\n"); 748 return FALSE; 749 } 750#endif 751#else /* XFree86Server */ 752 /* Setup the real visual */ 753 if (!fbSetVisualTypesAndMasks (pScreenInfo->dwDepth, 754 TrueColorMask, 755 pScreenPriv->dwBitsPerRGB, 756 pScreenPriv->dwRedMask, 757 pScreenPriv->dwGreenMask, 758 pScreenPriv->dwBlueMask)) 759 { 760 ErrorF ("winInitVisualsShadowGDI - fbSetVisualTypesAndMasks " 761 "failed for TrueColor\n"); 762 return FALSE; 763 } 764 765#ifdef XWIN_EMULATEPSEUDO 766 if (!pScreenInfo->fEmulatePseudo) 767 break; 768 769 /* Setup a pseudocolor visual */ 770 if (!fbSetVisualTypesAndMasks (8, 771 PseudoColorMask, 772 8, 773 0, 774 0, 775 0)) 776 { 777 ErrorF ("winInitVisualsShadowGDI - fbSetVisualTypesAndMasks " 778 "failed for PseudoColor\n"); 779 return FALSE; 780 } 781#endif 782#endif /* XFree86Server */ 783 break; 784 785 case 8: 786#if defined(XFree86Server) 787 if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, 788 PseudoColorMask, 789 pScreenPriv->dwBitsPerRGB, 790 PseudoColor, 791 pScreenPriv->dwRedMask, 792 pScreenPriv->dwGreenMask, 793 pScreenPriv->dwBlueMask)) 794 { 795 ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks " 796 "failed\n"); 797 return FALSE; 798 } 799#else /* XFree86Server */ 800 if (!fbSetVisualTypesAndMasks (pScreenInfo->dwDepth, 801 PseudoColorMask, 802 pScreenPriv->dwBitsPerRGB, 803 pScreenPriv->dwRedMask, 804 pScreenPriv->dwGreenMask, 805 pScreenPriv->dwBlueMask)) 806 { 807 ErrorF ("winInitVisualsShadowGDI - fbSetVisualTypesAndMasks " 808 "failed\n"); 809 return FALSE; 810 } 811#endif 812 break; 813 814 default: 815 ErrorF ("winInitVisualsShadowGDI - Unknown screen depth\n"); 816 return FALSE; 817 } 818 819#if CYGDEBUG 820 winDebug ("winInitVisualsShadowGDI - Returning\n"); 821#endif 822 823 return TRUE; 824} 825 826 827/* 828 * Adjust the proposed video mode 829 */ 830 831static Bool 832winAdjustVideoModeShadowGDI (ScreenPtr pScreen) 833{ 834 winScreenPriv(pScreen); 835 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 836 HDC hdc; 837 DWORD dwBPP; 838 839 hdc = GetDC (NULL); 840 841 /* We're in serious trouble if we can't get a DC */ 842 if (hdc == NULL) 843 { 844 ErrorF ("winAdjustVideoModeShadowGDI - GetDC () failed\n"); 845 return FALSE; 846 } 847 848 /* Query GDI for current display depth */ 849 dwBPP = GetDeviceCaps (hdc, BITSPIXEL); 850 851 /* GDI cannot change the screen depth */ 852 if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP) 853 { 854 /* No -depth parameter passed, let the user know the depth being used */ 855 ErrorF ("winAdjustVideoModeShadowGDI - Using Windows display " 856 "depth of %d bits per pixel\n", (int) dwBPP); 857 858 /* Use GDI's depth */ 859 pScreenInfo->dwBPP = dwBPP; 860 } 861 else if (dwBPP != pScreenInfo->dwBPP) 862 { 863 /* Warn user if GDI depth is different than -depth parameter */ 864 ErrorF ("winAdjustVideoModeShadowGDI - Command line bpp: %d, "\ 865 "using bpp: %d\n", (int) pScreenInfo->dwBPP, (int) dwBPP); 866 867 /* We'll use GDI's depth */ 868 pScreenInfo->dwBPP = dwBPP; 869 } 870 871 /* Release our DC */ 872 ReleaseDC (NULL, hdc); 873 hdc = NULL; 874 875 return TRUE; 876} 877 878 879/* 880 * Blt exposed regions to the screen 881 */ 882 883static Bool 884winBltExposedRegionsShadowGDI (ScreenPtr pScreen) 885{ 886 winScreenPriv(pScreen); 887 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 888 winPrivCmapPtr pCmapPriv = NULL; 889 HDC hdcUpdate; 890 PAINTSTRUCT ps; 891 892 /* BeginPaint gives us an hdc that clips to the invalidated region */ 893 hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps); 894 895 /* Realize the palette, if we have one */ 896 if (pScreenPriv->pcmapInstalled != NULL) 897 { 898 pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled); 899 900 SelectPalette (hdcUpdate, pCmapPriv->hPalette, FALSE); 901 RealizePalette (hdcUpdate); 902 } 903 904 /* Our BitBlt will be clipped to the invalidated region */ 905 BitBlt (hdcUpdate, 906 0, 0, 907 pScreenInfo->dwWidth, pScreenInfo->dwHeight, 908 pScreenPriv->hdcShadow, 909 0, 0, 910 SRCCOPY); 911 912 /* EndPaint frees the DC */ 913 EndPaint (pScreenPriv->hwndScreen, &ps); 914 915#ifdef XWIN_MULTIWINDOW 916 /* Redraw all windows */ 917 if (pScreenInfo->fMultiWindow) 918 EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 919 (LPARAM)pScreenPriv->hwndScreen); 920#endif 921 922 return TRUE; 923} 924 925 926/* 927 * Do any engine-specific appliation-activation processing 928 */ 929 930static Bool 931winActivateAppShadowGDI (ScreenPtr pScreen) 932{ 933 winScreenPriv(pScreen); 934 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 935 936 /* 937 * 2004/04/12 - Harold - We perform the restoring or minimizing 938 * manually for ShadowGDI in fullscreen modes so that this engine 939 * will perform just like ShadowDD and ShadowDDNL in fullscreen mode; 940 * if we do not do this then our fullscreen window will appear in the 941 * z-order when it is deactivated and it can be uncovered by resizing 942 * or minimizing another window that is on top of it, which is not how 943 * the DirectDraw engines work. Therefore we keep this code here to 944 * make sure that all engines work the same in fullscreen mode. 945 */ 946 947 /* 948 * Are we active? 949 * Are we fullscreen? 950 */ 951 if (pScreenPriv->fActive 952 && pScreenInfo->fFullScreen) 953 { 954 /* 955 * Activating, attempt to bring our window 956 * to the top of the display 957 */ 958 ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE); 959 } 960 else if (!pScreenPriv->fActive 961 && pScreenInfo->fFullScreen) 962 { 963 /* 964 * Deactivating, stuff our window onto the 965 * task bar. 966 */ 967 ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE); 968 } 969 970 return TRUE; 971} 972 973 974/* 975 * Reblit the shadow framebuffer to the screen. 976 */ 977 978static Bool 979winRedrawScreenShadowGDI (ScreenPtr pScreen) 980{ 981 winScreenPriv(pScreen); 982 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 983 984 /* Redraw the whole window, to take account for the new colors */ 985 BitBlt (pScreenPriv->hdcScreen, 986 0, 0, 987 pScreenInfo->dwWidth, pScreenInfo->dwHeight, 988 pScreenPriv->hdcShadow, 989 0, 0, 990 SRCCOPY); 991 992#ifdef XWIN_MULTIWINDOW 993 /* Redraw all windows */ 994 if (pScreenInfo->fMultiWindow) 995 EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0); 996#endif 997 998 return TRUE; 999} 1000 1001 1002 1003/* 1004 * Realize the currently installed colormap 1005 */ 1006 1007static Bool 1008winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen) 1009{ 1010 winScreenPriv(pScreen); 1011 winPrivCmapPtr pCmapPriv = NULL; 1012 1013#if CYGDEBUG 1014 winDebug ("winRealizeInstalledPaletteShadowGDI\n"); 1015#endif 1016 1017 /* Don't do anything if there is not a colormap */ 1018 if (pScreenPriv->pcmapInstalled == NULL) 1019 { 1020#if CYGDEBUG 1021 winDebug ("winRealizeInstalledPaletteShadowGDI - No colormap " 1022 "installed\n"); 1023#endif 1024 return TRUE; 1025 } 1026 1027 pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled); 1028 1029 /* Realize our palette for the screen */ 1030 if (RealizePalette (pScreenPriv->hdcScreen) == GDI_ERROR) 1031 { 1032 ErrorF ("winRealizeInstalledPaletteShadowGDI - RealizePalette () " 1033 "failed\n"); 1034 return FALSE; 1035 } 1036 1037 /* Set the DIB color table */ 1038 if (SetDIBColorTable (pScreenPriv->hdcShadow, 1039 0, 1040 WIN_NUM_PALETTE_ENTRIES, 1041 pCmapPriv->rgbColors) == 0) 1042 { 1043 ErrorF ("winRealizeInstalledPaletteShadowGDI - SetDIBColorTable () " 1044 "failed\n"); 1045 return FALSE; 1046 } 1047 1048 return TRUE; 1049} 1050 1051 1052/* 1053 * Install the specified colormap 1054 */ 1055 1056static Bool 1057winInstallColormapShadowGDI (ColormapPtr pColormap) 1058{ 1059 ScreenPtr pScreen = pColormap->pScreen; 1060 winScreenPriv(pScreen); 1061 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 1062 winCmapPriv(pColormap); 1063 1064 /* 1065 * Tell Windows to install the new colormap 1066 */ 1067 if (SelectPalette (pScreenPriv->hdcScreen, 1068 pCmapPriv->hPalette, 1069 FALSE) == NULL) 1070 { 1071 ErrorF ("winInstallColormapShadowGDI - SelectPalette () failed\n"); 1072 return FALSE; 1073 } 1074 1075 /* Realize the palette */ 1076 if (GDI_ERROR == RealizePalette (pScreenPriv->hdcScreen)) 1077 { 1078 ErrorF ("winInstallColormapShadowGDI - RealizePalette () failed\n"); 1079 return FALSE; 1080 } 1081 1082 /* Set the DIB color table */ 1083 if (SetDIBColorTable (pScreenPriv->hdcShadow, 1084 0, 1085 WIN_NUM_PALETTE_ENTRIES, 1086 pCmapPriv->rgbColors) == 0) 1087 { 1088 ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n"); 1089 return FALSE; 1090 } 1091 1092 /* Redraw the whole window, to take account for the new colors */ 1093 BitBlt (pScreenPriv->hdcScreen, 1094 0, 0, 1095 pScreenInfo->dwWidth, pScreenInfo->dwHeight, 1096 pScreenPriv->hdcShadow, 1097 0, 0, 1098 SRCCOPY); 1099 1100 /* Save a pointer to the newly installed colormap */ 1101 pScreenPriv->pcmapInstalled = pColormap; 1102 1103#ifdef XWIN_MULTIWINDOW 1104 /* Redraw all windows */ 1105 if (pScreenInfo->fMultiWindow) 1106 EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0); 1107#endif 1108 1109 return TRUE; 1110} 1111 1112 1113/* 1114 * Store the specified colors in the specified colormap 1115 */ 1116 1117static Bool 1118winStoreColorsShadowGDI (ColormapPtr pColormap, 1119 int ndef, 1120 xColorItem *pdefs) 1121{ 1122 ScreenPtr pScreen = pColormap->pScreen; 1123 winScreenPriv(pScreen); 1124 winCmapPriv(pColormap); 1125 ColormapPtr curpmap = pScreenPriv->pcmapInstalled; 1126 1127 /* Put the X colormap entries into the Windows logical palette */ 1128 if (SetPaletteEntries (pCmapPriv->hPalette, 1129 pdefs[0].pixel, 1130 ndef, 1131 pCmapPriv->peColors + pdefs[0].pixel) == 0) 1132 { 1133 ErrorF ("winStoreColorsShadowGDI - SetPaletteEntries () failed\n"); 1134 return FALSE; 1135 } 1136 1137 /* Don't install the Windows palette if the colormap is not installed */ 1138 if (pColormap != curpmap) 1139 { 1140 return TRUE; 1141 } 1142 1143 /* Try to install the newly modified colormap */ 1144 if (!winInstallColormapShadowGDI (pColormap)) 1145 { 1146 ErrorF ("winInstallColormapShadowGDI - winInstallColormapShadowGDI " 1147 "failed\n"); 1148 return FALSE; 1149 } 1150 1151#if 0 1152 /* Tell Windows that the palette has changed */ 1153 RealizePalette (pScreenPriv->hdcScreen); 1154 1155 /* Set the DIB color table */ 1156 if (SetDIBColorTable (pScreenPriv->hdcShadow, 1157 pdefs[0].pixel, 1158 ndef, 1159 pCmapPriv->rgbColors + pdefs[0].pixel) == 0) 1160 { 1161 ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n"); 1162 return FALSE; 1163 } 1164 1165 /* Save a pointer to the newly installed colormap */ 1166 pScreenPriv->pcmapInstalled = pColormap; 1167#endif 1168 1169 return TRUE; 1170} 1171 1172 1173/* 1174 * Colormap initialization procedure 1175 */ 1176 1177static Bool 1178winCreateColormapShadowGDI (ColormapPtr pColormap) 1179{ 1180 LPLOGPALETTE lpPaletteNew = NULL; 1181 DWORD dwEntriesMax; 1182 VisualPtr pVisual; 1183 HPALETTE hpalNew = NULL; 1184 winCmapPriv(pColormap); 1185 1186 /* Get a pointer to the visual that the colormap belongs to */ 1187 pVisual = pColormap->pVisual; 1188 1189 /* Get the maximum number of palette entries for this visual */ 1190 dwEntriesMax = pVisual->ColormapEntries; 1191 1192 /* Allocate a Windows logical color palette with max entries */ 1193 lpPaletteNew = malloc (sizeof (LOGPALETTE) 1194 + (dwEntriesMax - 1) * sizeof (PALETTEENTRY)); 1195 if (lpPaletteNew == NULL) 1196 { 1197 ErrorF ("winCreateColormapShadowGDI - Couldn't allocate palette " 1198 "with %d entries\n", 1199 (int) dwEntriesMax); 1200 return FALSE; 1201 } 1202 1203 /* Zero out the colormap */ 1204 ZeroMemory (lpPaletteNew, sizeof (LOGPALETTE) 1205 + (dwEntriesMax - 1) * sizeof (PALETTEENTRY)); 1206 1207 /* Set the logical palette structure */ 1208 lpPaletteNew->palVersion = 0x0300; 1209 lpPaletteNew->palNumEntries = dwEntriesMax; 1210 1211 /* Tell Windows to create the palette */ 1212 hpalNew = CreatePalette (lpPaletteNew); 1213 if (hpalNew == NULL) 1214 { 1215 ErrorF ("winCreateColormapShadowGDI - CreatePalette () failed\n"); 1216 free (lpPaletteNew); 1217 return FALSE; 1218 } 1219 1220 /* Save the Windows logical palette handle in the X colormaps' privates */ 1221 pCmapPriv->hPalette = hpalNew; 1222 1223 /* Free the palette initialization memory */ 1224 free (lpPaletteNew); 1225 1226 return TRUE; 1227} 1228 1229 1230/* 1231 * Colormap destruction procedure 1232 */ 1233 1234static Bool 1235winDestroyColormapShadowGDI (ColormapPtr pColormap) 1236{ 1237 winScreenPriv(pColormap->pScreen); 1238 winCmapPriv(pColormap); 1239 1240 /* 1241 * Is colormap to be destroyed the default? 1242 * 1243 * Non-default colormaps should have had winUninstallColormap 1244 * called on them before we get here. The default colormap 1245 * will not have had winUninstallColormap called on it. Thus, 1246 * we need to handle the default colormap in a special way. 1247 */ 1248 if (pColormap->flags & IsDefault) 1249 { 1250#if CYGDEBUG 1251 winDebug ("winDestroyColormapShadowGDI - Destroying default " 1252 "colormap\n"); 1253#endif 1254 1255 /* 1256 * FIXME: Walk the list of all screens, popping the default 1257 * palette out of each screen device context. 1258 */ 1259 1260 /* Pop the palette out of the device context */ 1261 SelectPalette (pScreenPriv->hdcScreen, 1262 GetStockObject (DEFAULT_PALETTE), 1263 FALSE); 1264 1265 /* Clear our private installed colormap pointer */ 1266 pScreenPriv->pcmapInstalled = NULL; 1267 } 1268 1269 /* Try to delete the logical palette */ 1270 if (DeleteObject (pCmapPriv->hPalette) == 0) 1271 { 1272 ErrorF ("winDestroyColormap - DeleteObject () failed\n"); 1273 return FALSE; 1274 } 1275 1276 /* Invalidate the colormap privates */ 1277 pCmapPriv->hPalette = NULL; 1278 1279 return TRUE; 1280} 1281 1282 1283/* 1284 * Set engine specific funtions 1285 */ 1286 1287Bool 1288winSetEngineFunctionsShadowGDI (ScreenPtr pScreen) 1289{ 1290 winScreenPriv(pScreen); 1291 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; 1292 1293 /* Set our pointers */ 1294 pScreenPriv->pwinAllocateFB = winAllocateFBShadowGDI; 1295 pScreenPriv->pwinShadowUpdate = winShadowUpdateGDI; 1296 pScreenPriv->pwinCloseScreen = winCloseScreenShadowGDI; 1297 pScreenPriv->pwinInitVisuals = winInitVisualsShadowGDI; 1298 pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowGDI; 1299 if (pScreenInfo->fFullScreen) 1300 pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen; 1301 else 1302 pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; 1303 pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; 1304 pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowGDI; 1305 pScreenPriv->pwinActivateApp = winActivateAppShadowGDI; 1306 pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowGDI; 1307 pScreenPriv->pwinRealizeInstalledPalette = 1308 winRealizeInstalledPaletteShadowGDI; 1309 pScreenPriv->pwinInstallColormap = winInstallColormapShadowGDI; 1310 pScreenPriv->pwinStoreColors = winStoreColorsShadowGDI; 1311 pScreenPriv->pwinCreateColormap = winCreateColormapShadowGDI; 1312 pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowGDI; 1313 pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA; 1314 pScreenPriv->pwinCreatePrimarySurface 1315 = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA; 1316 pScreenPriv->pwinReleasePrimarySurface 1317 = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA; 1318#ifdef XWIN_MULTIWINDOW 1319 pScreenPriv->pwinFinishCreateWindowsWindow = 1320 (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA; 1321#endif 1322 1323 return TRUE; 1324} 1325