1/*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 THE XFREE86 PROJECT 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 the XFree86 Project
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 the XFree86 Project.
27 *
28 * Authors:	Dakshinamurthy Karra
29 *		Suhaib M Siddiqi
30 *		Peter Busch
31 *		Harold L Hunt II
32 */
33
34#ifdef HAVE_XWIN_CONFIG_H
35#include <xwin-config.h>
36#endif
37#include "win.h"
38
39#define FAIL_MSG_MAX_BLT	10
40
41/*
42 * Local prototypes
43 */
44
45static Bool
46 winAllocateFBShadowDDNL(ScreenPtr pScreen);
47
48static void
49 winShadowUpdateDDNL(ScreenPtr pScreen, shadowBufPtr pBuf);
50
51static Bool
52 winCloseScreenShadowDDNL(ScreenPtr pScreen);
53
54static Bool
55 winInitVisualsShadowDDNL(ScreenPtr pScreen);
56
57static Bool
58 winAdjustVideoModeShadowDDNL(ScreenPtr pScreen);
59
60static Bool
61 winBltExposedRegionsShadowDDNL(ScreenPtr pScreen);
62
63static Bool
64 winActivateAppShadowDDNL(ScreenPtr pScreen);
65
66static Bool
67 winRedrawScreenShadowDDNL(ScreenPtr pScreen);
68
69static Bool
70 winRealizeInstalledPaletteShadowDDNL(ScreenPtr pScreen);
71
72static Bool
73 winInstallColormapShadowDDNL(ColormapPtr pColormap);
74
75static Bool
76 winStoreColorsShadowDDNL(ColormapPtr pmap, int ndef, xColorItem * pdefs);
77
78static Bool
79 winCreateColormapShadowDDNL(ColormapPtr pColormap);
80
81static Bool
82 winDestroyColormapShadowDDNL(ColormapPtr pColormap);
83
84static Bool
85 winCreatePrimarySurfaceShadowDDNL(ScreenPtr pScreen);
86
87static Bool
88 winReleasePrimarySurfaceShadowDDNL(ScreenPtr pScreen);
89
90/*
91 * Create the primary surface and attach the clipper.
92 * Used for both the initial surface creation and during
93 * WM_DISPLAYCHANGE messages.
94 */
95
96static Bool
97winCreatePrimarySurfaceShadowDDNL(ScreenPtr pScreen)
98{
99    winScreenPriv(pScreen);
100    HRESULT ddrval = DD_OK;
101    DDSURFACEDESC2 ddsd;
102
103    winDebug("winCreatePrimarySurfaceShadowDDNL - Creating primary surface\n");
104
105    /* Describe the primary surface */
106    ZeroMemory(&ddsd, sizeof(ddsd));
107    ddsd.dwSize = sizeof(ddsd);
108    ddsd.dwFlags = DDSD_CAPS;
109    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
110
111    /* Create the primary surface */
112    ddrval = IDirectDraw4_CreateSurface(pScreenPriv->pdd4,
113                                        &ddsd,
114                                        &pScreenPriv->pddsPrimary4, NULL);
115    pScreenPriv->fRetryCreateSurface = FALSE;
116    if (FAILED(ddrval)) {
117        if (ddrval == DDERR_NOEXCLUSIVEMODE) {
118            /* Recreating the surface failed. Mark screen to retry later */
119            pScreenPriv->fRetryCreateSurface = TRUE;
120            winDebug("winCreatePrimarySurfaceShadowDDNL - Could not create "
121                     "primary surface: DDERR_NOEXCLUSIVEMODE\n");
122        }
123        else {
124            ErrorF("winCreatePrimarySurfaceShadowDDNL - Could not create "
125                   "primary surface: %08x\n", (unsigned int) ddrval);
126        }
127        return FALSE;
128    }
129
130#if 1
131    winDebug("winCreatePrimarySurfaceShadowDDNL - Created primary surface\n");
132#endif
133
134    /* Attach our clipper to our primary surface handle */
135    ddrval = IDirectDrawSurface4_SetClipper(pScreenPriv->pddsPrimary4,
136                                            pScreenPriv->pddcPrimary);
137    if (FAILED(ddrval)) {
138        ErrorF("winCreatePrimarySurfaceShadowDDNL - Primary attach clipper "
139               "failed: %08x\n", (unsigned int) ddrval);
140        return FALSE;
141    }
142
143#if 1
144    winDebug("winCreatePrimarySurfaceShadowDDNL - Attached clipper to primary "
145             "surface\n");
146#endif
147
148    /* Everything was correct */
149    return TRUE;
150}
151
152/*
153 * Detach the clipper and release the primary surface.
154 * Called from WM_DISPLAYCHANGE.
155 */
156
157static Bool
158winReleasePrimarySurfaceShadowDDNL(ScreenPtr pScreen)
159{
160    winScreenPriv(pScreen);
161
162    winDebug("winReleasePrimarySurfaceShadowDDNL - Hello\n");
163
164    /* Release the primary surface and clipper, if they exist */
165    if (pScreenPriv->pddsPrimary4) {
166        /*
167         * Detach the clipper from the primary surface.
168         * NOTE: We do this explicity for clarity.  The Clipper is not released.
169         */
170        IDirectDrawSurface4_SetClipper(pScreenPriv->pddsPrimary4, NULL);
171
172        winDebug("winReleasePrimarySurfaceShadowDDNL - Detached clipper\n");
173
174        /* Release the primary surface */
175        IDirectDrawSurface4_Release(pScreenPriv->pddsPrimary4);
176        pScreenPriv->pddsPrimary4 = NULL;
177    }
178
179    winDebug("winReleasePrimarySurfaceShadowDDNL - Released primary surface\n");
180
181    return TRUE;
182}
183
184/*
185 * Create a DirectDraw surface for the shadow framebuffer; also create
186 * a primary surface object so we can blit to the display.
187 *
188 * Install a DirectDraw clipper on our primary surface object
189 * that clips our blits to the unobscured client area of our display window.
190 */
191
192Bool
193winAllocateFBShadowDDNL(ScreenPtr pScreen)
194{
195    winScreenPriv(pScreen);
196    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
197    HRESULT ddrval = DD_OK;
198    DDSURFACEDESC2 ddsdShadow;
199    char *lpSurface = NULL;
200    DDPIXELFORMAT ddpfPrimary;
201
202#if CYGDEBUG
203    winDebug("winAllocateFBShadowDDNL - w %u h %u d %u\n",
204             (unsigned int)pScreenInfo->dwWidth,
205             (unsigned int)pScreenInfo->dwHeight,
206             (unsigned int)pScreenInfo->dwDepth);
207#endif
208
209    /* Set the padded screen width */
210    pScreenInfo->dwPaddedWidth = PixmapBytePad(pScreenInfo->dwWidth,
211                                               pScreenInfo->dwBPP);
212
213    /* Allocate memory for our shadow surface */
214    lpSurface = malloc(pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight);
215    if (lpSurface == NULL) {
216        ErrorF("winAllocateFBShadowDDNL - Could not allocate bits\n");
217        return FALSE;
218    }
219
220    /*
221     * Initialize the framebuffer memory so we don't get a
222     * strange display at startup
223     */
224    ZeroMemory(lpSurface, pScreenInfo->dwPaddedWidth * pScreenInfo->dwHeight);
225
226    /* Create a clipper */
227    ddrval = (*g_fpDirectDrawCreateClipper) (0,
228                                             &pScreenPriv->pddcPrimary, NULL);
229    if (FAILED(ddrval)) {
230        ErrorF("winAllocateFBShadowDDNL - Could not attach clipper: %08x\n",
231               (unsigned int) ddrval);
232        return FALSE;
233    }
234
235#if CYGDEBUG
236    winDebug("winAllocateFBShadowDDNL - Created a clipper\n");
237#endif
238
239    /* Attach the clipper to our display window */
240    ddrval = IDirectDrawClipper_SetHWnd(pScreenPriv->pddcPrimary,
241                                        0, pScreenPriv->hwndScreen);
242    if (FAILED(ddrval)) {
243        ErrorF("winAllocateFBShadowDDNL - Clipper not attached "
244               "to window: %08x\n", (unsigned int) ddrval);
245        return FALSE;
246    }
247
248#if CYGDEBUG
249    winDebug("winAllocateFBShadowDDNL - Attached clipper to window\n");
250#endif
251
252    /* Create a DirectDraw object, store the address at lpdd */
253    ddrval = (*g_fpDirectDrawCreate) (NULL,
254                                      (LPDIRECTDRAW *) &pScreenPriv->pdd,
255                                      NULL);
256    if (FAILED(ddrval)) {
257        ErrorF("winAllocateFBShadowDDNL - Could not start "
258               "DirectDraw: %08x\n", (unsigned int) ddrval);
259        return FALSE;
260    }
261
262#if CYGDEBUG
263    winDebug("winAllocateFBShadowDDNL - Created and initialized DD\n");
264#endif
265
266    /* Get a DirectDraw4 interface pointer */
267    ddrval = IDirectDraw_QueryInterface(pScreenPriv->pdd,
268                                        &IID_IDirectDraw4,
269                                        (LPVOID *) &pScreenPriv->pdd4);
270    if (FAILED(ddrval)) {
271        ErrorF("winAllocateFBShadowDDNL - Failed DD4 query: %08x\n",
272               (unsigned int) ddrval);
273        return FALSE;
274    }
275
276    /* Are we full screen? */
277    if (pScreenInfo->fFullScreen) {
278        DDSURFACEDESC2 ddsdCurrent;
279        DWORD dwRefreshRateCurrent = 0;
280        HDC hdc = NULL;
281
282        /* Set the cooperative level to full screen */
283        ddrval = IDirectDraw4_SetCooperativeLevel(pScreenPriv->pdd4,
284                                                  pScreenPriv->hwndScreen,
285                                                  DDSCL_EXCLUSIVE
286                                                  | DDSCL_FULLSCREEN);
287        if (FAILED(ddrval)) {
288            ErrorF("winAllocateFBShadowDDNL - Could not set "
289                   "cooperative level: %08x\n", (unsigned int) ddrval);
290            return FALSE;
291        }
292
293        /*
294         * We only need to get the current refresh rate for comparison
295         * if a refresh rate has been passed on the command line.
296         */
297        if (pScreenInfo->dwRefreshRate != 0) {
298            ZeroMemory(&ddsdCurrent, sizeof(ddsdCurrent));
299            ddsdCurrent.dwSize = sizeof(ddsdCurrent);
300
301            /* Get information about current display settings */
302            ddrval = IDirectDraw4_GetDisplayMode(pScreenPriv->pdd4,
303                                                 &ddsdCurrent);
304            if (FAILED(ddrval)) {
305                ErrorF("winAllocateFBShadowDDNL - Could not get current "
306                       "refresh rate: %08x.  Continuing.\n",
307                       (unsigned int) ddrval);
308                dwRefreshRateCurrent = 0;
309            }
310            else {
311                /* Grab the current refresh rate */
312                dwRefreshRateCurrent = ddsdCurrent.u2.dwRefreshRate;
313            }
314        }
315
316        /* Clean up the refresh rate */
317        if (dwRefreshRateCurrent == pScreenInfo->dwRefreshRate) {
318            /*
319             * Refresh rate is non-specified or equal to current.
320             */
321            pScreenInfo->dwRefreshRate = 0;
322        }
323
324        /* Grab a device context for the screen */
325        hdc = GetDC(NULL);
326        if (hdc == NULL) {
327            ErrorF("winAllocateFBShadowDDNL - GetDC () failed\n");
328            return FALSE;
329        }
330
331        /* Only change the video mode when different than current mode */
332        if (!pScreenInfo->fMultipleMonitors
333            && (pScreenInfo->dwWidth != GetSystemMetrics(SM_CXSCREEN)
334                || pScreenInfo->dwHeight != GetSystemMetrics(SM_CYSCREEN)
335                || pScreenInfo->dwBPP != GetDeviceCaps(hdc, BITSPIXEL)
336                || pScreenInfo->dwRefreshRate != 0)) {
337            winDebug("winAllocateFBShadowDDNL - Changing video mode\n");
338
339            /* Change the video mode to the mode requested, and use the driver default refresh rate on failure */
340            ddrval = IDirectDraw4_SetDisplayMode(pScreenPriv->pdd4,
341                                                 pScreenInfo->dwWidth,
342                                                 pScreenInfo->dwHeight,
343                                                 pScreenInfo->dwBPP,
344                                                 pScreenInfo->dwRefreshRate, 0);
345            if (FAILED(ddrval)) {
346                ErrorF("winAllocateFBShadowDDNL - Could not set "
347                       "full screen display mode: %08x\n",
348                       (unsigned int) ddrval);
349                ErrorF
350                    ("winAllocateFBShadowDDNL - Using default driver refresh rate\n");
351                ddrval =
352                    IDirectDraw4_SetDisplayMode(pScreenPriv->pdd4,
353                                                pScreenInfo->dwWidth,
354                                                pScreenInfo->dwHeight,
355                                                pScreenInfo->dwBPP, 0, 0);
356                if (FAILED(ddrval)) {
357                    ErrorF
358                        ("winAllocateFBShadowDDNL - Could not set default refresh rate "
359                         "full screen display mode: %08x\n",
360                         (unsigned int) ddrval);
361                    return FALSE;
362                }
363            }
364        }
365        else {
366            winDebug("winAllocateFBShadowDDNL - Not changing video mode\n");
367        }
368
369        /* Release our DC */
370        ReleaseDC(NULL, hdc);
371        hdc = NULL;
372    }
373    else {
374        /* Set the cooperative level for windowed mode */
375        ddrval = IDirectDraw4_SetCooperativeLevel(pScreenPriv->pdd4,
376                                                  pScreenPriv->hwndScreen,
377                                                  DDSCL_NORMAL);
378        if (FAILED(ddrval)) {
379            ErrorF("winAllocateFBShadowDDNL - Could not set "
380                   "cooperative level: %08x\n", (unsigned int) ddrval);
381            return FALSE;
382        }
383    }
384
385    /* Create the primary surface */
386    if (!winCreatePrimarySurfaceShadowDDNL(pScreen)) {
387        ErrorF("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL "
388               "failed\n");
389        return FALSE;
390    }
391
392    /* Get primary surface's pixel format */
393    ZeroMemory(&ddpfPrimary, sizeof(ddpfPrimary));
394    ddpfPrimary.dwSize = sizeof(ddpfPrimary);
395    ddrval = IDirectDrawSurface4_GetPixelFormat(pScreenPriv->pddsPrimary4,
396                                                &ddpfPrimary);
397    if (FAILED(ddrval)) {
398        ErrorF("winAllocateFBShadowDDNL - Could not get primary "
399               "pixformat: %08x\n", (unsigned int) ddrval);
400        return FALSE;
401    }
402
403#if CYGDEBUG
404    winDebug("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x "
405             "dwRGBBitCount: %u\n",
406             (unsigned int)ddpfPrimary.u2.dwRBitMask,
407             (unsigned int)ddpfPrimary.u3.dwGBitMask,
408             (unsigned int)ddpfPrimary.u4.dwBBitMask,
409             (unsigned int)ddpfPrimary.u1.dwRGBBitCount);
410#endif
411
412    /* Describe the shadow surface to be created */
413    /*
414     * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
415     * as drawing, locking, and unlocking take forever
416     * with video memory surfaces.  In addition,
417     * video memory is a somewhat scarce resource,
418     * so you shouldn't be allocating video memory when
419     * you have the option of using system memory instead.
420     */
421    ZeroMemory(&ddsdShadow, sizeof(ddsdShadow));
422    ddsdShadow.dwSize = sizeof(ddsdShadow);
423    ddsdShadow.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH
424        | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT;
425    ddsdShadow.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
426    ddsdShadow.dwHeight = pScreenInfo->dwHeight;
427    ddsdShadow.dwWidth = pScreenInfo->dwWidth;
428    ddsdShadow.u1.lPitch = pScreenInfo->dwPaddedWidth;
429    ddsdShadow.lpSurface = lpSurface;
430    ddsdShadow.u4.ddpfPixelFormat = ddpfPrimary;
431
432    winDebug("winAllocateFBShadowDDNL - lPitch: %d\n",
433             (int) pScreenInfo->dwPaddedWidth);
434
435    /* Create the shadow surface */
436    ddrval = IDirectDraw4_CreateSurface(pScreenPriv->pdd4,
437                                        &ddsdShadow,
438                                        &pScreenPriv->pddsShadow4, NULL);
439    if (FAILED(ddrval)) {
440        ErrorF("winAllocateFBShadowDDNL - Could not create shadow "
441               "surface: %08x\n", (unsigned int) ddrval);
442        return FALSE;
443    }
444
445#if CYGDEBUG || YES
446    winDebug("winAllocateFBShadowDDNL - Created shadow pitch: %d\n",
447             (int) ddsdShadow.u1.lPitch);
448#endif
449
450    /* Grab the pitch from the surface desc */
451    pScreenInfo->dwStride = (ddsdShadow.u1.lPitch * 8)
452        / pScreenInfo->dwBPP;
453
454#if CYGDEBUG || YES
455    winDebug("winAllocateFBShadowDDNL - Created shadow stride: %d\n",
456             (int) pScreenInfo->dwStride);
457#endif
458
459    /* Save the pointer to our surface memory */
460    pScreenInfo->pfb = lpSurface;
461
462    /* Grab the masks from the surface description */
463    pScreenPriv->dwRedMask = ddsdShadow.u4.ddpfPixelFormat.u2.dwRBitMask;
464    pScreenPriv->dwGreenMask = ddsdShadow.u4.ddpfPixelFormat.u3.dwGBitMask;
465    pScreenPriv->dwBlueMask = ddsdShadow.u4.ddpfPixelFormat.u4.dwBBitMask;
466
467#if CYGDEBUG
468    winDebug("winAllocateFBShadowDDNL - Returning\n");
469#endif
470
471    return TRUE;
472}
473
474static void
475winFreeFBShadowDDNL(ScreenPtr pScreen)
476{
477    winScreenPriv(pScreen);
478    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
479
480    /* Free the shadow surface, if there is one */
481    if (pScreenPriv->pddsShadow4) {
482        IDirectDrawSurface4_Release(pScreenPriv->pddsShadow4);
483        free(pScreenInfo->pfb);
484        pScreenInfo->pfb = NULL;
485        pScreenPriv->pddsShadow4 = NULL;
486    }
487
488    /* Detach the clipper from the primary surface and release the primary surface, if there is one */
489    winReleasePrimarySurfaceShadowDDNL(pScreen);
490
491    /* Release the clipper object */
492    if (pScreenPriv->pddcPrimary) {
493        IDirectDrawClipper_Release(pScreenPriv->pddcPrimary);
494        pScreenPriv->pddcPrimary = NULL;
495    }
496
497    /* Free the DirectDraw4 object, if there is one */
498    if (pScreenPriv->pdd4) {
499        IDirectDraw4_RestoreDisplayMode(pScreenPriv->pdd4);
500        IDirectDraw4_Release(pScreenPriv->pdd4);
501        pScreenPriv->pdd4 = NULL;
502    }
503
504    /* Free the DirectDraw object, if there is one */
505    if (pScreenPriv->pdd) {
506        IDirectDraw_Release(pScreenPriv->pdd);
507        pScreenPriv->pdd = NULL;
508    }
509
510    /* Invalidate the ScreenInfo's fb pointer */
511    pScreenInfo->pfb = NULL;
512}
513
514/*
515 * Transfer the damaged regions of the shadow framebuffer to the display.
516 */
517
518static void
519winShadowUpdateDDNL(ScreenPtr pScreen, shadowBufPtr pBuf)
520{
521    winScreenPriv(pScreen);
522    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
523    RegionPtr damage = DamageRegion(pBuf->pDamage);
524    HRESULT ddrval = DD_OK;
525    RECT rcDest, rcSrc;
526    POINT ptOrigin;
527    DWORD dwBox = RegionNumRects(damage);
528    BoxPtr pBox = RegionRects(damage);
529    HRGN hrgnCombined = NULL;
530
531    /*
532     * Return immediately if the app is not active
533     * and we are fullscreen, or if we have a bad display depth
534     */
535    if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
536        || pScreenPriv->fBadDepth)
537        return;
538
539    /* Return immediately if we didn't get needed surfaces */
540    if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4)
541        return;
542
543    /* Get the origin of the window in the screen coords */
544    ptOrigin.x = pScreenInfo->dwXOffset;
545    ptOrigin.y = pScreenInfo->dwYOffset;
546    MapWindowPoints(pScreenPriv->hwndScreen,
547                    HWND_DESKTOP, (LPPOINT) &ptOrigin, 1);
548
549    /*
550     * Handle small regions with multiple blits,
551     * handle large regions by creating a clipping region and
552     * doing a single blit constrained to that clipping region.
553     */
554    if (pScreenInfo->dwClipUpdatesNBoxes == 0
555        || dwBox < pScreenInfo->dwClipUpdatesNBoxes) {
556        /* Loop through all boxes in the damaged region */
557        while (dwBox--) {
558            /* Assign damage box to source rectangle */
559            rcSrc.left = pBox->x1;
560            rcSrc.top = pBox->y1;
561            rcSrc.right = pBox->x2;
562            rcSrc.bottom = pBox->y2;
563
564            /* Calculate destination rectangle */
565            rcDest.left = ptOrigin.x + rcSrc.left;
566            rcDest.top = ptOrigin.y + rcSrc.top;
567            rcDest.right = ptOrigin.x + rcSrc.right;
568            rcDest.bottom = ptOrigin.y + rcSrc.bottom;
569
570            /* Blit the damaged areas */
571            ddrval = IDirectDrawSurface4_Blt(pScreenPriv->pddsPrimary4,
572                                             &rcDest,
573                                             pScreenPriv->pddsShadow4,
574                                             &rcSrc, DDBLT_WAIT, NULL);
575            if (FAILED(ddrval)) {
576                static int s_iFailCount = 0;
577
578                if (s_iFailCount < FAIL_MSG_MAX_BLT) {
579                    ErrorF("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () "
580                           "failed: %08x\n", (unsigned int) ddrval);
581
582                    ++s_iFailCount;
583
584                    if (s_iFailCount == FAIL_MSG_MAX_BLT) {
585                        ErrorF("winShadowUpdateDDNL - IDirectDrawSurface4_Blt "
586                               "failure message maximum (%d) reached.  No "
587                               "more failure messages will be printed.\n",
588                               FAIL_MSG_MAX_BLT);
589                    }
590                }
591            }
592
593            /* Get a pointer to the next box */
594            ++pBox;
595        }
596    }
597    else {
598        BoxPtr pBoxExtents = RegionExtents(damage);
599
600        /* Compute a GDI region from the damaged region */
601        hrgnCombined =
602            CreateRectRgn(pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2,
603                          pBoxExtents->y2);
604
605        /* Install the GDI region as a clipping region */
606        SelectClipRgn(pScreenPriv->hdcScreen, hrgnCombined);
607        DeleteObject(hrgnCombined);
608        hrgnCombined = NULL;
609
610#if CYGDEBUG
611        winDebug("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n",
612                 pBoxExtents->x1, pBoxExtents->y1,
613                 pBoxExtents->x2, pBoxExtents->y2);
614#endif
615
616        /* Calculating a bounding box for the source is easy */
617        rcSrc.left = pBoxExtents->x1;
618        rcSrc.top = pBoxExtents->y1;
619        rcSrc.right = pBoxExtents->x2;
620        rcSrc.bottom = pBoxExtents->y2;
621
622        /* Calculating a bounding box for the destination is trickier */
623        rcDest.left = ptOrigin.x + rcSrc.left;
624        rcDest.top = ptOrigin.y + rcSrc.top;
625        rcDest.right = ptOrigin.x + rcSrc.right;
626        rcDest.bottom = ptOrigin.y + rcSrc.bottom;
627
628        /* Our Blt should be clipped to the invalidated region */
629        ddrval = IDirectDrawSurface4_Blt(pScreenPriv->pddsPrimary4,
630                                         &rcDest,
631                                         pScreenPriv->pddsShadow4,
632                                         &rcSrc, DDBLT_WAIT, NULL);
633
634        /* Reset the clip region */
635        SelectClipRgn(pScreenPriv->hdcScreen, NULL);
636    }
637}
638
639static Bool
640winInitScreenShadowDDNL(ScreenPtr pScreen)
641{
642    winScreenPriv(pScreen);
643
644    /* Get a device context for the screen  */
645    pScreenPriv->hdcScreen = GetDC(pScreenPriv->hwndScreen);
646
647    return winAllocateFBShadowDDNL(pScreen);
648}
649
650/*
651 * Call the wrapped CloseScreen function.
652 *
653 * Free our resources and private structures.
654 */
655
656static Bool
657winCloseScreenShadowDDNL(ScreenPtr pScreen)
658{
659    winScreenPriv(pScreen);
660    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
661    Bool fReturn = TRUE;
662
663#if CYGDEBUG
664    winDebug("winCloseScreenShadowDDNL - Freeing screen resources\n");
665#endif
666
667    /* Flag that the screen is closed */
668    pScreenPriv->fClosed = TRUE;
669    pScreenPriv->fActive = FALSE;
670
671    /* Call the wrapped CloseScreen procedure */
672    WIN_UNWRAP(CloseScreen);
673    if (pScreen->CloseScreen)
674        fReturn = (*pScreen->CloseScreen) (pScreen);
675
676    winFreeFBShadowDDNL(pScreen);
677
678    /* Free the screen DC */
679    ReleaseDC(pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
680
681    /* Delete the window property */
682    RemoveProp(pScreenPriv->hwndScreen, WIN_SCR_PROP);
683
684    /* Delete tray icon, if we have one */
685    if (!pScreenInfo->fNoTrayIcon)
686        winDeleteNotifyIcon(pScreenPriv);
687
688    /* Free the exit confirmation dialog box, if it exists */
689    if (g_hDlgExit != NULL) {
690        DestroyWindow(g_hDlgExit);
691        g_hDlgExit = NULL;
692    }
693
694    /* Kill our window */
695    if (pScreenPriv->hwndScreen) {
696        DestroyWindow(pScreenPriv->hwndScreen);
697        pScreenPriv->hwndScreen = NULL;
698    }
699
700    /* Destroy the thread startup mutex */
701    pthread_mutex_destroy(&pScreenPriv->pmServerStarted);
702
703    /* Kill our screeninfo's pointer to the screen */
704    pScreenInfo->pScreen = NULL;
705
706    /* Free the screen privates for this screen */
707    free((void *) pScreenPriv);
708
709    return fReturn;
710}
711
712/*
713 * Tell mi what sort of visuals we need.
714 *
715 * Generally we only need one visual, as our screen can only
716 * handle one format at a time, I believe.  You may want
717 * to verify that last sentence.
718 */
719
720static Bool
721winInitVisualsShadowDDNL(ScreenPtr pScreen)
722{
723    winScreenPriv(pScreen);
724    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
725    DWORD dwRedBits, dwGreenBits, dwBlueBits;
726
727    /* Count the number of ones in each color mask */
728    dwRedBits = winCountBits(pScreenPriv->dwRedMask);
729    dwGreenBits = winCountBits(pScreenPriv->dwGreenMask);
730    dwBlueBits = winCountBits(pScreenPriv->dwBlueMask);
731
732    /* Store the maximum number of ones in a color mask as the bitsPerRGB */
733    if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0)
734        pScreenPriv->dwBitsPerRGB = 8;
735    else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
736        pScreenPriv->dwBitsPerRGB = dwRedBits;
737    else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
738        pScreenPriv->dwBitsPerRGB = dwGreenBits;
739    else
740        pScreenPriv->dwBitsPerRGB = dwBlueBits;
741
742    winDebug("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d "
743             "bpp %d\n",
744             (unsigned int) pScreenPriv->dwRedMask,
745             (unsigned int) pScreenPriv->dwGreenMask,
746             (unsigned int) pScreenPriv->dwBlueMask,
747             (int) pScreenPriv->dwBitsPerRGB,
748             (int) pScreenInfo->dwDepth, (int) pScreenInfo->dwBPP);
749
750    /* Create a single visual according to the Windows screen depth */
751    switch (pScreenInfo->dwDepth) {
752    case 24:
753    case 16:
754    case 15:
755        /* Setup the real visual */
756        if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
757                                      TrueColorMask,
758                                      pScreenPriv->dwBitsPerRGB,
759                                      -1,
760                                      pScreenPriv->dwRedMask,
761                                      pScreenPriv->dwGreenMask,
762                                      pScreenPriv->dwBlueMask)) {
763            ErrorF("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
764                   "failed for TrueColor\n");
765            return FALSE;
766        }
767
768#ifdef XWIN_EMULATEPSEUDO
769        if (!pScreenInfo->fEmulatePseudo)
770            break;
771
772        /* Setup a pseudocolor visual */
773        if (!miSetVisualTypesAndMasks(8, PseudoColorMask, 8, -1, 0, 0, 0)) {
774            ErrorF("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
775                   "failed for PseudoColor\n");
776            return FALSE;
777        }
778#endif
779        break;
780
781    case 8:
782        if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth,
783                                      pScreenInfo->fFullScreen
784                                      ? PseudoColorMask : StaticColorMask,
785                                      pScreenPriv->dwBitsPerRGB,
786                                      pScreenInfo->fFullScreen
787                                      ? PseudoColor : StaticColor,
788                                      pScreenPriv->dwRedMask,
789                                      pScreenPriv->dwGreenMask,
790                                      pScreenPriv->dwBlueMask)) {
791            ErrorF("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
792                   "failed\n");
793            return FALSE;
794        }
795        break;
796
797    default:
798        ErrorF("winInitVisualsShadowDDNL - Unknown screen depth\n");
799        return FALSE;
800    }
801
802#if CYGDEBUG
803    winDebug("winInitVisualsShadowDDNL - Returning\n");
804#endif
805
806    return TRUE;
807}
808
809/*
810 * Adjust the user proposed video mode
811 */
812
813static Bool
814winAdjustVideoModeShadowDDNL(ScreenPtr pScreen)
815{
816    winScreenPriv(pScreen);
817    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
818    HDC hdc = NULL;
819    DWORD dwBPP;
820
821    /* We're in serious trouble if we can't get a DC */
822    hdc = GetDC(NULL);
823    if (hdc == NULL) {
824        ErrorF("winAdjustVideoModeShadowDDNL - GetDC () failed\n");
825        return FALSE;
826    }
827
828    /* Query GDI for current display depth */
829    dwBPP = GetDeviceCaps(hdc, BITSPIXEL);
830
831    /* DirectDraw can only change the depth in fullscreen mode */
832    if (!(pScreenInfo->fFullScreen && (pScreenInfo->dwBPP != WIN_DEFAULT_BPP))) {
833        /* Otherwise, We'll use GDI's depth */
834        pScreenInfo->dwBPP = dwBPP;
835    }
836
837    /* Release our DC */
838    ReleaseDC(NULL, hdc);
839
840    return TRUE;
841}
842
843/*
844 * Blt exposed regions to the screen
845 */
846
847static Bool
848winBltExposedRegionsShadowDDNL(ScreenPtr pScreen)
849{
850    winScreenPriv(pScreen);
851    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
852    RECT rcSrc, rcDest;
853    POINT ptOrigin;
854    HDC hdcUpdate;
855    PAINTSTRUCT ps;
856    HRESULT ddrval = DD_OK;
857    Bool fReturn = TRUE;
858    int i;
859
860    /* Quite common case. The primary surface was lost (maybe because of depth
861     * change). Try to create a new primary surface. Bail out if this fails */
862    if (pScreenPriv->pddsPrimary4 == NULL && pScreenPriv->fRetryCreateSurface &&
863        !winCreatePrimarySurfaceShadowDDNL(pScreen)) {
864        Sleep(100);
865        return FALSE;
866    }
867    if (pScreenPriv->pddsPrimary4 == NULL)
868        return FALSE;
869
870    /* BeginPaint gives us an hdc that clips to the invalidated region */
871    hdcUpdate = BeginPaint(pScreenPriv->hwndScreen, &ps);
872    if (hdcUpdate == NULL) {
873        fReturn = FALSE;
874        ErrorF("winBltExposedRegionsShadowDDNL - BeginPaint () returned "
875               "a NULL device context handle.  Aborting blit attempt.\n");
876        goto winBltExposedRegionsShadowDDNL_Exit;
877    }
878
879    /* Get the origin of the window in the screen coords */
880    ptOrigin.x = pScreenInfo->dwXOffset;
881    ptOrigin.y = pScreenInfo->dwYOffset;
882
883    MapWindowPoints(pScreenPriv->hwndScreen,
884                    HWND_DESKTOP, (LPPOINT) &ptOrigin, 1);
885    rcDest.left = ptOrigin.x;
886    rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
887    rcDest.top = ptOrigin.y;
888    rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
889
890    /* Source can be entire shadow surface, as Blt should clip for us */
891    rcSrc.left = 0;
892    rcSrc.top = 0;
893    rcSrc.right = pScreenInfo->dwWidth;
894    rcSrc.bottom = pScreenInfo->dwHeight;
895
896    /* Try to regain the primary surface and blit again if we've lost it */
897    for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i) {
898        /* Our Blt should be clipped to the invalidated region */
899        ddrval = IDirectDrawSurface4_Blt(pScreenPriv->pddsPrimary4,
900                                         &rcDest,
901                                         pScreenPriv->pddsShadow4,
902                                         &rcSrc, DDBLT_WAIT, NULL);
903        if (ddrval == DDERR_SURFACELOST) {
904            /* Surface was lost */
905            winErrorFVerb(1, "winBltExposedRegionsShadowDDNL - "
906                          "IDirectDrawSurface4_Blt reported that the primary "
907                          "surface was lost, trying to restore, retry: %d\n",
908                          i + 1);
909
910            /* Try to restore the surface, once */
911
912            ddrval = IDirectDrawSurface4_Restore(pScreenPriv->pddsPrimary4);
913            winDebug("winBltExposedRegionsShadowDDNL - "
914                     "IDirectDrawSurface4_Restore returned: ");
915            if (ddrval == DD_OK)
916                winDebug("DD_OK\n");
917            else if (ddrval == DDERR_WRONGMODE)
918                winDebug("DDERR_WRONGMODE\n");
919            else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
920                winDebug("DDERR_INCOMPATIBLEPRIMARY\n");
921            else if (ddrval == DDERR_UNSUPPORTED)
922                winDebug("DDERR_UNSUPPORTED\n");
923            else if (ddrval == DDERR_INVALIDPARAMS)
924                winDebug("DDERR_INVALIDPARAMS\n");
925            else if (ddrval == DDERR_INVALIDOBJECT)
926                winDebug("DDERR_INVALIDOBJECT\n");
927            else
928                winDebug("unknown error: %08x\n", (unsigned int) ddrval);
929
930            /* Loop around to try the blit one more time */
931            continue;
932        }
933        else if (FAILED(ddrval)) {
934            fReturn = FALSE;
935            winErrorFVerb(1, "winBltExposedRegionsShadowDDNL - "
936                          "IDirectDrawSurface4_Blt failed, but surface not "
937                          "lost: %08x %d\n",
938                          (unsigned int) ddrval, (int) ddrval);
939            goto winBltExposedRegionsShadowDDNL_Exit;
940        }
941        else {
942            /* Success, stop looping */
943            break;
944        }
945    }
946
947 winBltExposedRegionsShadowDDNL_Exit:
948    /* EndPaint frees the DC */
949    if (hdcUpdate != NULL)
950        EndPaint(pScreenPriv->hwndScreen, &ps);
951    return fReturn;
952}
953
954/*
955 * Do any engine-specific application-activation processing
956 */
957
958static Bool
959winActivateAppShadowDDNL(ScreenPtr pScreen)
960{
961    winScreenPriv(pScreen);
962
963    /*
964     * Do we have a surface?
965     * Are we active?
966     * Are we full screen?
967     */
968    if (pScreenPriv != NULL
969        && pScreenPriv->pddsPrimary4 != NULL && pScreenPriv->fActive) {
970        /* Primary surface was lost, restore it */
971        IDirectDrawSurface4_Restore(pScreenPriv->pddsPrimary4);
972    }
973
974    return TRUE;
975}
976
977/*
978 * Reblit the shadow framebuffer to the screen.
979 */
980
981static Bool
982winRedrawScreenShadowDDNL(ScreenPtr pScreen)
983{
984    winScreenPriv(pScreen);
985    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
986    HRESULT ddrval = DD_OK;
987    RECT rcSrc, rcDest;
988    POINT ptOrigin;
989
990    /* Return immediately if we didn't get needed surfaces */
991    if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4)
992        return FALSE;
993
994    /* Get the origin of the window in the screen coords */
995    ptOrigin.x = pScreenInfo->dwXOffset;
996    ptOrigin.y = pScreenInfo->dwYOffset;
997    MapWindowPoints(pScreenPriv->hwndScreen,
998                    HWND_DESKTOP, (LPPOINT) &ptOrigin, 1);
999    rcDest.left = ptOrigin.x;
1000    rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
1001    rcDest.top = ptOrigin.y;
1002    rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
1003
1004    /* Source can be entire shadow surface, as Blt should clip for us */
1005    rcSrc.left = 0;
1006    rcSrc.top = 0;
1007    rcSrc.right = pScreenInfo->dwWidth;
1008    rcSrc.bottom = pScreenInfo->dwHeight;
1009
1010    /* Redraw the whole window, to take account for the new colors */
1011    ddrval = IDirectDrawSurface4_Blt(pScreenPriv->pddsPrimary4,
1012                                     &rcDest,
1013                                     pScreenPriv->pddsShadow4,
1014                                     &rcSrc, DDBLT_WAIT, NULL);
1015    if (FAILED(ddrval)) {
1016        ErrorF("winRedrawScreenShadowDDNL - IDirectDrawSurface4_Blt () "
1017               "failed: %08x\n", (unsigned int) ddrval);
1018    }
1019
1020    return TRUE;
1021}
1022
1023/*
1024 * Realize the currently installed colormap
1025 */
1026
1027static Bool
1028winRealizeInstalledPaletteShadowDDNL(ScreenPtr pScreen)
1029{
1030    return TRUE;
1031}
1032
1033/*
1034 * Install the specified colormap
1035 */
1036
1037static Bool
1038winInstallColormapShadowDDNL(ColormapPtr pColormap)
1039{
1040    ScreenPtr pScreen = pColormap->pScreen;
1041
1042    winScreenPriv(pScreen);
1043    winCmapPriv(pColormap);
1044    HRESULT ddrval = DD_OK;
1045
1046    /* Install the DirectDraw palette on the primary surface */
1047    ddrval = IDirectDrawSurface4_SetPalette(pScreenPriv->pddsPrimary4,
1048                                            pCmapPriv->lpDDPalette);
1049    if (FAILED(ddrval)) {
1050        ErrorF("winInstallColormapShadowDDNL - Failed installing the "
1051               "DirectDraw palette.\n");
1052        return FALSE;
1053    }
1054
1055    /* Save a pointer to the newly installed colormap */
1056    pScreenPriv->pcmapInstalled = pColormap;
1057
1058    return TRUE;
1059}
1060
1061/*
1062 * Store the specified colors in the specified colormap
1063 */
1064
1065static Bool
1066winStoreColorsShadowDDNL(ColormapPtr pColormap, int ndef, xColorItem * pdefs)
1067{
1068    ScreenPtr pScreen = pColormap->pScreen;
1069
1070    winScreenPriv(pScreen);
1071    winCmapPriv(pColormap);
1072    ColormapPtr curpmap = pScreenPriv->pcmapInstalled;
1073    HRESULT ddrval = DD_OK;
1074
1075    /* Put the X colormap entries into the Windows logical palette */
1076    ddrval = IDirectDrawPalette_SetEntries(pCmapPriv->lpDDPalette,
1077                                           0,
1078                                           pdefs[0].pixel,
1079                                           ndef,
1080                                           pCmapPriv->peColors
1081                                           + pdefs[0].pixel);
1082    if (FAILED(ddrval)) {
1083        ErrorF("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n",
1084               (unsigned int) ddrval);
1085        return FALSE;
1086    }
1087
1088    /* Don't install the DirectDraw palette if the colormap is not installed */
1089    if (pColormap != curpmap) {
1090        return TRUE;
1091    }
1092
1093    if (!winInstallColormapShadowDDNL(pColormap)) {
1094        ErrorF("winStoreColorsShadowDDNL - Failed installing colormap\n");
1095        return FALSE;
1096    }
1097
1098    return TRUE;
1099}
1100
1101/*
1102 * Colormap initialization procedure
1103 */
1104
1105static Bool
1106winCreateColormapShadowDDNL(ColormapPtr pColormap)
1107{
1108    HRESULT ddrval = DD_OK;
1109    ScreenPtr pScreen = pColormap->pScreen;
1110
1111    winScreenPriv(pScreen);
1112    winCmapPriv(pColormap);
1113
1114    /* Create a DirectDraw palette */
1115    ddrval = IDirectDraw4_CreatePalette(pScreenPriv->pdd4,
1116                                        DDPCAPS_8BIT | DDPCAPS_ALLOW256,
1117                                        pCmapPriv->peColors,
1118                                        &pCmapPriv->lpDDPalette, NULL);
1119    if (FAILED(ddrval)) {
1120        ErrorF("winCreateColormapShadowDDNL - CreatePalette failed\n");
1121        return FALSE;
1122    }
1123
1124    return TRUE;
1125}
1126
1127/*
1128 * Colormap destruction procedure
1129 */
1130
1131static Bool
1132winDestroyColormapShadowDDNL(ColormapPtr pColormap)
1133{
1134    winScreenPriv(pColormap->pScreen);
1135    winCmapPriv(pColormap);
1136    HRESULT ddrval = DD_OK;
1137
1138    /*
1139     * Is colormap to be destroyed the default?
1140     *
1141     * Non-default colormaps should have had winUninstallColormap
1142     * called on them before we get here.  The default colormap
1143     * will not have had winUninstallColormap called on it.  Thus,
1144     * we need to handle the default colormap in a special way.
1145     */
1146    if (pColormap->flags & IsDefault) {
1147#if CYGDEBUG
1148        winDebug
1149            ("winDestroyColormapShadowDDNL - Destroying default colormap\n");
1150#endif
1151
1152        /*
1153         * FIXME: Walk the list of all screens, popping the default
1154         * palette out of each screen device context.
1155         */
1156
1157        /* Pop the palette out of the primary surface */
1158        ddrval = IDirectDrawSurface4_SetPalette(pScreenPriv->pddsPrimary4,
1159                                                NULL);
1160        if (FAILED(ddrval)) {
1161            ErrorF("winDestroyColormapShadowDDNL - Failed freeing the "
1162                   "default colormap DirectDraw palette.\n");
1163            return FALSE;
1164        }
1165
1166        /* Clear our private installed colormap pointer */
1167        pScreenPriv->pcmapInstalled = NULL;
1168    }
1169
1170    /* Release the palette */
1171    IDirectDrawPalette_Release(pCmapPriv->lpDDPalette);
1172
1173    /* Invalidate the colormap privates */
1174    pCmapPriv->lpDDPalette = NULL;
1175
1176    return TRUE;
1177}
1178
1179/*
1180 * Set pointers to our engine specific functions
1181 */
1182
1183Bool
1184winSetEngineFunctionsShadowDDNL(ScreenPtr pScreen)
1185{
1186    winScreenPriv(pScreen);
1187    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
1188
1189    /* Set our pointers */
1190    pScreenPriv->pwinAllocateFB = winAllocateFBShadowDDNL;
1191    pScreenPriv->pwinFreeFB = winFreeFBShadowDDNL;
1192    pScreenPriv->pwinShadowUpdate = winShadowUpdateDDNL;
1193    pScreenPriv->pwinInitScreen = winInitScreenShadowDDNL;
1194    pScreenPriv->pwinCloseScreen = winCloseScreenShadowDDNL;
1195    pScreenPriv->pwinInitVisuals = winInitVisualsShadowDDNL;
1196    pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDDNL;
1197    if (pScreenInfo->fFullScreen)
1198        pScreenPriv->pwinCreateBoundingWindow =
1199            winCreateBoundingWindowFullScreen;
1200    else
1201        pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
1202    pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
1203    pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL;
1204    pScreenPriv->pwinBltExposedWindowRegion = NULL;
1205    pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL;
1206    pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL;
1207    pScreenPriv->pwinRealizeInstalledPalette
1208        = winRealizeInstalledPaletteShadowDDNL;
1209    pScreenPriv->pwinInstallColormap = winInstallColormapShadowDDNL;
1210    pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL;
1211    pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL;
1212    pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL;
1213    pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL;
1214    pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL;
1215
1216    return TRUE;
1217}
1218