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
40static wBOOL CALLBACK winRedrawAllProcShadowGDI(HWND hwnd, LPARAM lParam);
41
42static wBOOL CALLBACK winRedrawDamagedWindowShadowGDI(HWND hwnd, LPARAM lParam);
43
44static Bool
45 winAllocateFBShadowGDI(ScreenPtr pScreen);
46
47static void
48 winShadowUpdateGDI(ScreenPtr pScreen, shadowBufPtr pBuf);
49
50static Bool
51 winCloseScreenShadowGDI(ScreenPtr pScreen);
52
53static Bool
54 winInitVisualsShadowGDI(ScreenPtr pScreen);
55
56static Bool
57 winAdjustVideoModeShadowGDI(ScreenPtr pScreen);
58
59static Bool
60 winBltExposedRegionsShadowGDI(ScreenPtr pScreen);
61
62static Bool
63 winBltExposedWindowRegionShadowGDI(ScreenPtr pScreen, WindowPtr pWin);
64
65static Bool
66 winActivateAppShadowGDI(ScreenPtr pScreen);
67
68static Bool
69 winRedrawScreenShadowGDI(ScreenPtr pScreen);
70
71static Bool
72 winRealizeInstalledPaletteShadowGDI(ScreenPtr pScreen);
73
74static Bool
75 winInstallColormapShadowGDI(ColormapPtr pColormap);
76
77static Bool
78 winStoreColorsShadowGDI(ColormapPtr pmap, int ndef, xColorItem * pdefs);
79
80static Bool
81 winCreateColormapShadowGDI(ColormapPtr pColormap);
82
83static Bool
84 winDestroyColormapShadowGDI(ColormapPtr pColormap);
85
86/*
87 * Internal function to get the DIB format that is compatible with the screen
88 */
89
90static
91    Bool
92winQueryScreenDIBFormat(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
147static
148    Bool
149winQueryRGBBitsAndMasks(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
271static wBOOL CALLBACK
272winRedrawAllProcShadowGDI(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
281static wBOOL CALLBACK
282winRedrawDamagedWindowShadowGDI(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
317static Bool
318winAllocateFBShadowGDI(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
412static void
413winFreeFBShadowGDI(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
429static void
430winShadowUpdateGDI(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
532static Bool
533winInitScreenShadowGDI(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
569static Bool
570winCloseScreenShadowGDI(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
636static Bool
637winInitVisualsShadowGDI(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
712static Bool
713winAdjustVideoModeShadowGDI(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
745static Bool
746winBltExposedRegionsShadowGDI(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
811static Bool
812winBltExposedWindowRegionShadowGDI(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
933static Bool
934winActivateAppShadowGDI(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
976static Bool
977winRedrawScreenShadowGDI(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
999static Bool
1000winRealizeInstalledPaletteShadowGDI(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
1043static Bool
1044winInstallColormapShadowGDI(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
1096static Bool
1097winStoreColorsShadowGDI(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
1148static Bool
1149winCreateColormapShadowGDI(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
1202static Bool
1203winDestroyColormapShadowGDI(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
1251Bool
1252winSetEngineFunctionsShadowGDI(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