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