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