First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xwin / winshadgdi.c
blob04cc2f71651b60153e696cebc47712ef41f08889
1 /*
2 *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
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:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
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.
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.
28 * Authors: Harold L Hunt II
31 #ifdef HAVE_XWIN_CONFIG_H
32 #include <xwin-config.h>
33 #endif
34 #include "win.h"
38 * External symbols
41 #ifdef XWIN_MULTIWINDOW
42 extern DWORD g_dwCurrentThreadID;
43 #endif
44 extern HWND g_hDlgExit;
48 * Local function prototypes
51 #ifdef XWIN_MULTIWINDOW
52 static wBOOL CALLBACK
53 winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam);
55 static wBOOL CALLBACK
56 winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam);
57 #endif
59 static Bool
60 winAllocateFBShadowGDI (ScreenPtr pScreen);
62 static void
63 winShadowUpdateGDI (ScreenPtr pScreen,
64 shadowBufPtr pBuf);
66 static Bool
67 winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen);
69 static Bool
70 winInitVisualsShadowGDI (ScreenPtr pScreen);
72 static Bool
73 winAdjustVideoModeShadowGDI (ScreenPtr pScreen);
75 static Bool
76 winBltExposedRegionsShadowGDI (ScreenPtr pScreen);
78 static Bool
79 winActivateAppShadowGDI (ScreenPtr pScreen);
81 static Bool
82 winRedrawScreenShadowGDI (ScreenPtr pScreen);
84 static Bool
85 winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen);
87 static Bool
88 winInstallColormapShadowGDI (ColormapPtr pColormap);
90 static Bool
91 winStoreColorsShadowGDI (ColormapPtr pmap,
92 int ndef,
93 xColorItem *pdefs);
95 static Bool
96 winCreateColormapShadowGDI (ColormapPtr pColormap);
98 static Bool
99 winDestroyColormapShadowGDI (ColormapPtr pColormap);
103 * Internal function to get the DIB format that is compatible with the screen
106 static
107 Bool
108 winQueryScreenDIBFormat (ScreenPtr pScreen, BITMAPINFOHEADER *pbmih)
110 winScreenPriv(pScreen);
111 HBITMAP hbmp;
112 #if CYGDEBUG
113 LPDWORD pdw = NULL;
114 #endif
116 /* Create a memory bitmap compatible with the screen */
117 hbmp = CreateCompatibleBitmap (pScreenPriv->hdcScreen, 1, 1);
118 if (hbmp == NULL)
120 ErrorF ("winQueryScreenDIBFormat - CreateCompatibleBitmap failed\n");
121 return FALSE;
124 /* Initialize our bitmap info header */
125 ZeroMemory (pbmih, sizeof (BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD));
126 pbmih->biSize = sizeof (BITMAPINFOHEADER);
128 /* Get the biBitCount */
129 if (!GetDIBits (pScreenPriv->hdcScreen,
130 hbmp,
131 0, 1,
132 NULL,
133 (BITMAPINFO*) pbmih,
134 DIB_RGB_COLORS))
136 ErrorF ("winQueryScreenDIBFormat - First call to GetDIBits failed\n");
137 DeleteObject (hbmp);
138 return FALSE;
141 #if CYGDEBUG
142 /* Get a pointer to bitfields */
143 pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
145 winDebug ("winQueryScreenDIBFormat - First call masks: %08x %08x %08x\n",
146 pdw[0], pdw[1], pdw[2]);
147 #endif
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))
157 ErrorF ("winQueryScreenDIBFormat - Second call to GetDIBits "
158 "failed\n");
159 DeleteObject (hbmp);
160 return FALSE;
163 /* Free memory */
164 DeleteObject (hbmp);
166 return TRUE;
171 * Internal function to determine the GDI bits per rgb and bit masks
174 static
175 Bool
176 winQueryRGBBitsAndMasks (ScreenPtr pScreen)
178 winScreenPriv(pScreen);
179 BITMAPINFOHEADER *pbmih = NULL;
180 Bool fReturn = TRUE;
181 LPDWORD pdw = NULL;
182 DWORD dwRedBits, dwGreenBits, dwBlueBits;
184 /* Color masks for 8 bpp are standardized */
185 if (GetDeviceCaps (pScreenPriv->hdcScreen, RASTERCAPS) & RC_PALETTE)
188 * RGB BPP for 8 bit palletes is always 8
189 * and the color masks are always 0.
191 pScreenPriv->dwBitsPerRGB = 8;
192 pScreenPriv->dwRedMask = 0x0L;
193 pScreenPriv->dwGreenMask = 0x0L;
194 pScreenPriv->dwBlueMask = 0x0L;
195 return TRUE;
198 /* Color masks for 24 bpp are standardized */
199 if (GetDeviceCaps (pScreenPriv->hdcScreen, PLANES)
200 * GetDeviceCaps (pScreenPriv->hdcScreen, BITSPIXEL) == 24)
202 ErrorF ("winQueryRGBBitsAndMasks - GetDeviceCaps (BITSPIXEL) "
203 "returned 24 for the screen. Using default 24bpp masks.\n");
205 /* 8 bits per primary color */
206 pScreenPriv->dwBitsPerRGB = 8;
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;
213 return TRUE;
216 /* Allocate a bitmap header and color table */
217 pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
218 + 256 * sizeof (RGBQUAD));
219 if (pbmih == NULL)
221 ErrorF ("winQueryRGBBitsAndMasks - malloc failed\n");
222 return FALSE;
225 /* Get screen description */
226 if (winQueryScreenDIBFormat (pScreen, pbmih))
228 /* Get a pointer to bitfields */
229 pdw = (DWORD*) ((CARD8*)pbmih + sizeof (BITMAPINFOHEADER));
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
245 /* Handle BI_RGB case, which is returned by Wine */
246 if (pbmih->biCompression == BI_RGB)
248 dwRedBits = 5;
249 dwGreenBits = 5;
250 dwBlueBits = 5;
252 pScreenPriv->dwBitsPerRGB = 5;
254 /* Set screen privates masks */
255 pScreenPriv->dwRedMask = 0x7c00;
256 pScreenPriv->dwGreenMask = 0x03e0;
257 pScreenPriv->dwBlueMask = 0x001f;
259 else
261 /* Count the number of bits in each mask */
262 dwRedBits = winCountBits (pdw[0]);
263 dwGreenBits = winCountBits (pdw[1]);
264 dwBlueBits = winCountBits (pdw[2]);
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;
274 /* Set screen privates masks */
275 pScreenPriv->dwRedMask = pdw[0];
276 pScreenPriv->dwGreenMask = pdw[1];
277 pScreenPriv->dwBlueMask = pdw[2];
280 else
282 ErrorF ("winQueryRGBBitsAndMasks - winQueryScreenDIBFormat failed\n");
283 free (pbmih);
284 fReturn = FALSE;
287 /* Free memory */
288 free (pbmih);
290 return fReturn;
294 #ifdef XWIN_MULTIWINDOW
296 * Redraw all ---?
299 static wBOOL CALLBACK
300 winRedrawAllProcShadowGDI (HWND hwnd, LPARAM lParam)
302 if (hwnd == (HWND)lParam)
303 return TRUE;
304 InvalidateRect (hwnd, NULL, FALSE);
305 UpdateWindow (hwnd);
306 return TRUE;
309 static wBOOL CALLBACK
310 winRedrawDamagedWindowShadowGDI (HWND hwnd, LPARAM lParam)
312 BoxPtr pDamage = (BoxPtr)lParam;
313 RECT rcClient, rcDamage, rcRedraw;
314 POINT topLeft, bottomRight;
316 if (IsIconic (hwnd))
317 return TRUE; /* Don't care minimized windows */
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);
330 GetClientRect (hwnd, &rcClient);
332 if (IntersectRect (&rcRedraw, &rcClient, &rcDamage))
334 InvalidateRect (hwnd, &rcRedraw, FALSE);
335 UpdateWindow (hwnd);
337 return TRUE;
339 #endif
343 * Allocate a DIB for the shadow framebuffer GDI server
346 static Bool
347 winAllocateFBShadowGDI (ScreenPtr pScreen)
349 winScreenPriv(pScreen);
350 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
351 BITMAPINFOHEADER *pbmih = NULL;
352 DIBSECTION dibsection;
353 Bool fReturn = TRUE;
355 /* Get device contexts for the screen and shadow bitmap */
356 pScreenPriv->hdcScreen = GetDC (pScreenPriv->hwndScreen);
357 pScreenPriv->hdcShadow = CreateCompatibleDC (pScreenPriv->hdcScreen);
359 /* Allocate bitmap info header */
360 pbmih = (BITMAPINFOHEADER*) malloc (sizeof (BITMAPINFOHEADER)
361 + 256 * sizeof (RGBQUAD));
362 if (pbmih == NULL)
364 ErrorF ("winAllocateFBShadowGDI - malloc () failed\n");
365 return FALSE;
368 /* Query the screen format */
369 fReturn = winQueryScreenDIBFormat (pScreen, pbmih);
371 /* Describe shadow bitmap to be created */
372 pbmih->biWidth = pScreenInfo->dwWidth;
373 pbmih->biHeight = -pScreenInfo->dwHeight;
375 ErrorF ("winAllocateFBShadowGDI - Creating DIB with width: %d height: %d "
376 "depth: %d\n",
377 (int) pbmih->biWidth, (int) -pbmih->biHeight, pbmih->biBitCount);
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,
386 if (pScreenPriv->hbmpShadow == NULL || pScreenInfo->pfb == NULL)
388 winW32Error (2, "winAllocateFBShadowGDI - CreateDIBSection failed:");
389 return FALSE;
391 else
393 #if CYGDEBUG
394 winDebug ("winAllocateFBShadowGDI - Shadow buffer allocated\n");
395 #endif
398 /* Get information about the bitmap that was allocated */
399 GetObject (pScreenPriv->hbmpShadow,
400 sizeof (dibsection),
401 &dibsection);
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
412 /* Select the shadow bitmap into the shadow DC */
413 SelectObject (pScreenPriv->hdcShadow,
414 pScreenPriv->hbmpShadow);
416 #if CYGDEBUG
417 winDebug ("winAllocateFBShadowGDI - Attempting a shadow blit\n");
418 #endif
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)
429 #if CYGDEBUG
430 winDebug ("winAllocateFBShadowGDI - Shadow blit success\n");
431 #endif
433 else
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. */
442 fReturn = TRUE;
443 #endif
446 /* Look for height weirdness */
447 if (dibsection.dsBmih.biHeight < 0)
449 dibsection.dsBmih.biHeight = -dibsection.dsBmih.biHeight;
452 /* Set screeninfo stride */
453 pScreenInfo->dwStride = ((dibsection.dsBmih.biSizeImage
454 / dibsection.dsBmih.biHeight)
455 * 8) / pScreenInfo->dwBPP;
457 #if CYGDEBUG || YES
458 winDebug ("winAllocateFBShadowGDI - Created shadow stride: %d\n",
459 (int) pScreenInfo->dwStride);
460 #endif
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)
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);
474 /* Determine our color masks */
475 if (!winQueryRGBBitsAndMasks (pScreen))
477 ErrorF ("winAllocateFBShadowGDI - winQueryRGBBitsAndMasks failed\n");
478 return FALSE;
481 #ifdef XWIN_MULTIWINDOW
482 /* Redraw all windows */
483 if (pScreenInfo->fMultiWindow)
484 EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
485 #endif
487 return fReturn;
492 * Blit the damaged regions of the shadow fb to the screen
495 static void
496 winShadowUpdateGDI (ScreenPtr pScreen,
497 shadowBufPtr pBuf)
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);
514 * Return immediately if the app is not active
515 * and we are fullscreen, or if we have a bad display depth
517 if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
518 || pScreenPriv->fBadDepth) return;
520 #ifdef XWIN_UPDATESTATS
521 ++s_dwTotalUpdates;
522 s_dwTotalBoxes += dwBox;
524 if (dwBox != 1)
526 ++s_dwNonUnitRegions;
527 ErrorF ("winShadowUpdatGDI - dwBox: %d\n", dwBox);
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 */
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.
543 if (!pScreenInfo->fMultiWindow &&
544 (pScreenInfo->dwClipUpdatesNBoxes == 0 ||
545 dwBox < pScreenInfo->dwClipUpdatesNBoxes))
547 /* Loop through all boxes in the damaged region */
548 while (dwBox--)
551 * Calculate x offset, y offset, width, and height for
552 * current damage box
554 x = pBox->x1;
555 y = pBox->y1;
556 w = pBox->x2 - pBox->x1;
557 h = pBox->y2 - pBox->y1;
559 BitBlt (pScreenPriv->hdcScreen,
560 x, y,
561 w, h,
562 pScreenPriv->hdcShadow,
563 x, y,
564 SRCCOPY);
566 /* Get a pointer to the next box */
567 ++pBox;
570 else if (!pScreenInfo->fMultiWindow)
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--)
578 hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
579 CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
580 DeleteObject (hrgnTemp);
581 pBox++;
584 /* Install the GDI region as a clipping region */
585 SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
586 DeleteObject (hrgnCombined);
587 hrgnCombined = NULL;
590 * Blit the shadow buffer to the screen,
591 * constrained to the clipping region.
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);
601 /* Reset the clip region */
602 SelectClipRgn (pScreenPriv->hdcScreen, NULL);
605 #ifdef XWIN_MULTIWINDOW
606 /* Redraw all multiwindow windows */
607 if (pScreenInfo->fMultiWindow)
608 EnumThreadWindows (g_dwCurrentThreadID,
609 winRedrawDamagedWindowShadowGDI,
610 (LPARAM)pBoxExtents);
611 #endif
615 /* See Porting Layer Definition - p. 33 */
617 * We wrap whatever CloseScreen procedure was specified by fb;
618 * a pointer to said procedure is stored in our privates.
621 static Bool
622 winCloseScreenShadowGDI (int nIndex, ScreenPtr pScreen)
624 winScreenPriv(pScreen);
625 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
626 Bool fReturn;
628 #if CYGDEBUG
629 winDebug ("winCloseScreenShadowGDI - Freeing screen resources\n");
630 #endif
632 /* Flag that the screen is closed */
633 pScreenPriv->fClosed = TRUE;
634 pScreenPriv->fActive = FALSE;
636 /* Call the wrapped CloseScreen procedure */
637 WIN_UNWRAP(CloseScreen);
638 fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
640 /* Delete the window property */
641 RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
643 /* Free the shadow DC; which allows the bitmap to be freed */
644 DeleteDC (pScreenPriv->hdcShadow);
646 /* Free the shadow bitmap */
647 DeleteObject (pScreenPriv->hbmpShadow);
649 /* Free the screen DC */
650 ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
652 /* Delete tray icon, if we have one */
653 if (!pScreenInfo->fNoTrayIcon)
654 winDeleteNotifyIcon (pScreenPriv);
656 /* Free the exit confirmation dialog box, if it exists */
657 if (g_hDlgExit != NULL)
659 DestroyWindow (g_hDlgExit);
660 g_hDlgExit = NULL;
663 /* Kill our window */
664 if (pScreenPriv->hwndScreen)
666 DestroyWindow (pScreenPriv->hwndScreen);
667 pScreenPriv->hwndScreen = NULL;
670 #if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
671 /* Destroy the thread startup mutex */
672 pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
673 #endif
675 /* Invalidate our screeninfo's pointer to the screen */
676 pScreenInfo->pScreen = NULL;
678 /* Invalidate the ScreenInfo's fb pointer */
679 pScreenInfo->pfb = NULL;
681 /* Free the screen privates for this screen */
682 free ((pointer) pScreenPriv);
684 return fReturn;
689 * Tell mi what sort of visuals we need.
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.
696 static Bool
697 winInitVisualsShadowGDI (ScreenPtr pScreen)
699 winScreenPriv(pScreen);
700 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
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);
712 /* Create a single visual according to the Windows screen depth */
713 switch (pScreenInfo->dwDepth)
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,
724 pScreenPriv->dwRedMask,
725 pScreenPriv->dwGreenMask,
726 pScreenPriv->dwBlueMask))
728 ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
729 "failed\n");
730 return FALSE;
733 #ifdef XWIN_EMULATEPSEUDO
734 if (!pScreenInfo->fEmulatePseudo)
735 break;
737 /* Setup a pseudocolor visual */
738 if (!miSetVisualTypesAndMasks (8,
739 PseudoColorMask,
746 ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
747 "failed for PseudoColor\n");
748 return FALSE;
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))
760 ErrorF ("winInitVisualsShadowGDI - fbSetVisualTypesAndMasks "
761 "failed for TrueColor\n");
762 return FALSE;
765 #ifdef XWIN_EMULATEPSEUDO
766 if (!pScreenInfo->fEmulatePseudo)
767 break;
769 /* Setup a pseudocolor visual */
770 if (!fbSetVisualTypesAndMasks (8,
771 PseudoColorMask,
777 ErrorF ("winInitVisualsShadowGDI - fbSetVisualTypesAndMasks "
778 "failed for PseudoColor\n");
779 return FALSE;
781 #endif
782 #endif /* XFree86Server */
783 break;
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))
795 ErrorF ("winInitVisualsShadowGDI - miSetVisualTypesAndMasks "
796 "failed\n");
797 return FALSE;
799 #else /* XFree86Server */
800 if (!fbSetVisualTypesAndMasks (pScreenInfo->dwDepth,
801 PseudoColorMask,
802 pScreenPriv->dwBitsPerRGB,
803 pScreenPriv->dwRedMask,
804 pScreenPriv->dwGreenMask,
805 pScreenPriv->dwBlueMask))
807 ErrorF ("winInitVisualsShadowGDI - fbSetVisualTypesAndMasks "
808 "failed\n");
809 return FALSE;
811 #endif
812 break;
814 default:
815 ErrorF ("winInitVisualsShadowGDI - Unknown screen depth\n");
816 return FALSE;
819 #if CYGDEBUG
820 winDebug ("winInitVisualsShadowGDI - Returning\n");
821 #endif
823 return TRUE;
828 * Adjust the proposed video mode
831 static Bool
832 winAdjustVideoModeShadowGDI (ScreenPtr pScreen)
834 winScreenPriv(pScreen);
835 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
836 HDC hdc;
837 DWORD dwBPP;
839 hdc = GetDC (NULL);
841 /* We're in serious trouble if we can't get a DC */
842 if (hdc == NULL)
844 ErrorF ("winAdjustVideoModeShadowGDI - GetDC () failed\n");
845 return FALSE;
848 /* Query GDI for current display depth */
849 dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
851 /* GDI cannot change the screen depth */
852 if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP)
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);
858 /* Use GDI's depth */
859 pScreenInfo->dwBPP = dwBPP;
861 else if (dwBPP != pScreenInfo->dwBPP)
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);
867 /* We'll use GDI's depth */
868 pScreenInfo->dwBPP = dwBPP;
871 /* Release our DC */
872 ReleaseDC (NULL, hdc);
873 hdc = NULL;
875 return TRUE;
880 * Blt exposed regions to the screen
883 static Bool
884 winBltExposedRegionsShadowGDI (ScreenPtr pScreen)
886 winScreenPriv(pScreen);
887 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
888 winPrivCmapPtr pCmapPriv = NULL;
889 HDC hdcUpdate;
890 PAINTSTRUCT ps;
892 /* BeginPaint gives us an hdc that clips to the invalidated region */
893 hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
895 /* Realize the palette, if we have one */
896 if (pScreenPriv->pcmapInstalled != NULL)
898 pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled);
900 SelectPalette (hdcUpdate, pCmapPriv->hPalette, FALSE);
901 RealizePalette (hdcUpdate);
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);
912 /* EndPaint frees the DC */
913 EndPaint (pScreenPriv->hwndScreen, &ps);
915 #ifdef XWIN_MULTIWINDOW
916 /* Redraw all windows */
917 if (pScreenInfo->fMultiWindow)
918 EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI,
919 (LPARAM)pScreenPriv->hwndScreen);
920 #endif
922 return TRUE;
927 * Do any engine-specific appliation-activation processing
930 static Bool
931 winActivateAppShadowGDI (ScreenPtr pScreen)
933 winScreenPriv(pScreen);
934 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
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.
948 * Are we active?
949 * Are we fullscreen?
951 if (pScreenPriv->fActive
952 && pScreenInfo->fFullScreen)
955 * Activating, attempt to bring our window
956 * to the top of the display
958 ShowWindow (pScreenPriv->hwndScreen, SW_RESTORE);
960 else if (!pScreenPriv->fActive
961 && pScreenInfo->fFullScreen)
964 * Deactivating, stuff our window onto the
965 * task bar.
967 ShowWindow (pScreenPriv->hwndScreen, SW_MINIMIZE);
970 return TRUE;
975 * Reblit the shadow framebuffer to the screen.
978 static Bool
979 winRedrawScreenShadowGDI (ScreenPtr pScreen)
981 winScreenPriv(pScreen);
982 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
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);
992 #ifdef XWIN_MULTIWINDOW
993 /* Redraw all windows */
994 if (pScreenInfo->fMultiWindow)
995 EnumThreadWindows(g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
996 #endif
998 return TRUE;
1004 * Realize the currently installed colormap
1007 static Bool
1008 winRealizeInstalledPaletteShadowGDI (ScreenPtr pScreen)
1010 winScreenPriv(pScreen);
1011 winPrivCmapPtr pCmapPriv = NULL;
1013 #if CYGDEBUG
1014 winDebug ("winRealizeInstalledPaletteShadowGDI\n");
1015 #endif
1017 /* Don't do anything if there is not a colormap */
1018 if (pScreenPriv->pcmapInstalled == NULL)
1020 #if CYGDEBUG
1021 winDebug ("winRealizeInstalledPaletteShadowGDI - No colormap "
1022 "installed\n");
1023 #endif
1024 return TRUE;
1027 pCmapPriv = winGetCmapPriv (pScreenPriv->pcmapInstalled);
1029 /* Realize our palette for the screen */
1030 if (RealizePalette (pScreenPriv->hdcScreen) == GDI_ERROR)
1032 ErrorF ("winRealizeInstalledPaletteShadowGDI - RealizePalette () "
1033 "failed\n");
1034 return FALSE;
1037 /* Set the DIB color table */
1038 if (SetDIBColorTable (pScreenPriv->hdcShadow,
1040 WIN_NUM_PALETTE_ENTRIES,
1041 pCmapPriv->rgbColors) == 0)
1043 ErrorF ("winRealizeInstalledPaletteShadowGDI - SetDIBColorTable () "
1044 "failed\n");
1045 return FALSE;
1048 return TRUE;
1053 * Install the specified colormap
1056 static Bool
1057 winInstallColormapShadowGDI (ColormapPtr pColormap)
1059 ScreenPtr pScreen = pColormap->pScreen;
1060 winScreenPriv(pScreen);
1061 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
1062 winCmapPriv(pColormap);
1065 * Tell Windows to install the new colormap
1067 if (SelectPalette (pScreenPriv->hdcScreen,
1068 pCmapPriv->hPalette,
1069 FALSE) == NULL)
1071 ErrorF ("winInstallColormapShadowGDI - SelectPalette () failed\n");
1072 return FALSE;
1075 /* Realize the palette */
1076 if (GDI_ERROR == RealizePalette (pScreenPriv->hdcScreen))
1078 ErrorF ("winInstallColormapShadowGDI - RealizePalette () failed\n");
1079 return FALSE;
1082 /* Set the DIB color table */
1083 if (SetDIBColorTable (pScreenPriv->hdcShadow,
1085 WIN_NUM_PALETTE_ENTRIES,
1086 pCmapPriv->rgbColors) == 0)
1088 ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
1089 return FALSE;
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);
1100 /* Save a pointer to the newly installed colormap */
1101 pScreenPriv->pcmapInstalled = pColormap;
1103 #ifdef XWIN_MULTIWINDOW
1104 /* Redraw all windows */
1105 if (pScreenInfo->fMultiWindow)
1106 EnumThreadWindows (g_dwCurrentThreadID, winRedrawAllProcShadowGDI, 0);
1107 #endif
1109 return TRUE;
1114 * Store the specified colors in the specified colormap
1117 static Bool
1118 winStoreColorsShadowGDI (ColormapPtr pColormap,
1119 int ndef,
1120 xColorItem *pdefs)
1122 ScreenPtr pScreen = pColormap->pScreen;
1123 winScreenPriv(pScreen);
1124 winCmapPriv(pColormap);
1125 ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
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)
1133 ErrorF ("winStoreColorsShadowGDI - SetPaletteEntries () failed\n");
1134 return FALSE;
1137 /* Don't install the Windows palette if the colormap is not installed */
1138 if (pColormap != curpmap)
1140 return TRUE;
1143 /* Try to install the newly modified colormap */
1144 if (!winInstallColormapShadowGDI (pColormap))
1146 ErrorF ("winInstallColormapShadowGDI - winInstallColormapShadowGDI "
1147 "failed\n");
1148 return FALSE;
1151 #if 0
1152 /* Tell Windows that the palette has changed */
1153 RealizePalette (pScreenPriv->hdcScreen);
1155 /* Set the DIB color table */
1156 if (SetDIBColorTable (pScreenPriv->hdcShadow,
1157 pdefs[0].pixel,
1158 ndef,
1159 pCmapPriv->rgbColors + pdefs[0].pixel) == 0)
1161 ErrorF ("winInstallColormapShadowGDI - SetDIBColorTable () failed\n");
1162 return FALSE;
1165 /* Save a pointer to the newly installed colormap */
1166 pScreenPriv->pcmapInstalled = pColormap;
1167 #endif
1169 return TRUE;
1174 * Colormap initialization procedure
1177 static Bool
1178 winCreateColormapShadowGDI (ColormapPtr pColormap)
1180 LPLOGPALETTE lpPaletteNew = NULL;
1181 DWORD dwEntriesMax;
1182 VisualPtr pVisual;
1183 HPALETTE hpalNew = NULL;
1184 winCmapPriv(pColormap);
1186 /* Get a pointer to the visual that the colormap belongs to */
1187 pVisual = pColormap->pVisual;
1189 /* Get the maximum number of palette entries for this visual */
1190 dwEntriesMax = pVisual->ColormapEntries;
1192 /* Allocate a Windows logical color palette with max entries */
1193 lpPaletteNew = malloc (sizeof (LOGPALETTE)
1194 + (dwEntriesMax - 1) * sizeof (PALETTEENTRY));
1195 if (lpPaletteNew == NULL)
1197 ErrorF ("winCreateColormapShadowGDI - Couldn't allocate palette "
1198 "with %d entries\n",
1199 (int) dwEntriesMax);
1200 return FALSE;
1203 /* Zero out the colormap */
1204 ZeroMemory (lpPaletteNew, sizeof (LOGPALETTE)
1205 + (dwEntriesMax - 1) * sizeof (PALETTEENTRY));
1207 /* Set the logical palette structure */
1208 lpPaletteNew->palVersion = 0x0300;
1209 lpPaletteNew->palNumEntries = dwEntriesMax;
1211 /* Tell Windows to create the palette */
1212 hpalNew = CreatePalette (lpPaletteNew);
1213 if (hpalNew == NULL)
1215 ErrorF ("winCreateColormapShadowGDI - CreatePalette () failed\n");
1216 free (lpPaletteNew);
1217 return FALSE;
1220 /* Save the Windows logical palette handle in the X colormaps' privates */
1221 pCmapPriv->hPalette = hpalNew;
1223 /* Free the palette initialization memory */
1224 free (lpPaletteNew);
1226 return TRUE;
1231 * Colormap destruction procedure
1234 static Bool
1235 winDestroyColormapShadowGDI (ColormapPtr pColormap)
1237 winScreenPriv(pColormap->pScreen);
1238 winCmapPriv(pColormap);
1241 * Is colormap to be destroyed the default?
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.
1248 if (pColormap->flags & IsDefault)
1250 #if CYGDEBUG
1251 winDebug ("winDestroyColormapShadowGDI - Destroying default "
1252 "colormap\n");
1253 #endif
1256 * FIXME: Walk the list of all screens, popping the default
1257 * palette out of each screen device context.
1260 /* Pop the palette out of the device context */
1261 SelectPalette (pScreenPriv->hdcScreen,
1262 GetStockObject (DEFAULT_PALETTE),
1263 FALSE);
1265 /* Clear our private installed colormap pointer */
1266 pScreenPriv->pcmapInstalled = NULL;
1269 /* Try to delete the logical palette */
1270 if (DeleteObject (pCmapPriv->hPalette) == 0)
1272 ErrorF ("winDestroyColormap - DeleteObject () failed\n");
1273 return FALSE;
1276 /* Invalidate the colormap privates */
1277 pCmapPriv->hPalette = NULL;
1279 return TRUE;
1284 * Set engine specific funtions
1287 Bool
1288 winSetEngineFunctionsShadowGDI (ScreenPtr pScreen)
1290 winScreenPriv(pScreen);
1291 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
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
1323 return TRUE;