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