winshadddnl.c revision 05b261ec
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 */
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	      return FALSE;
407	    }
408	}
409      else
410	{
411	  winDebug ("winAllocateFBShadowDDNL - Not changing video mode\n");
412	}
413
414      /* Release our DC */
415      ReleaseDC (NULL, hdc);
416      hdc = NULL;
417    }
418  else
419    {
420      /* Set the cooperative level for windowed mode */
421      ddrval = IDirectDraw4_SetCooperativeLevel (pScreenPriv->pdd4,
422						 pScreenPriv->hwndScreen,
423						 DDSCL_NORMAL);
424      if (FAILED (ddrval))
425	{
426	  ErrorF ("winAllocateFBShadowDDNL - Could not set "
427		  "cooperative level: %08x\n",
428		  (unsigned int) ddrval);
429	  return FALSE;
430	}
431    }
432
433  /* Create the primary surface */
434  if (!winCreatePrimarySurfaceShadowDDNL (pScreen))
435    {
436      ErrorF ("winAllocateFBShadowDDNL - winCreatePrimarySurfaceShadowDDNL "
437	      "failed\n");
438      return FALSE;
439    }
440
441  /* Get primary surface's pixel format */
442  ZeroMemory (&ddpfPrimary, sizeof (ddpfPrimary));
443  ddpfPrimary.dwSize = sizeof (ddpfPrimary);
444  ddrval = IDirectDrawSurface4_GetPixelFormat (pScreenPriv->pddsPrimary4,
445					       &ddpfPrimary);
446  if (FAILED (ddrval))
447    {
448      ErrorF ("winAllocateFBShadowDDNL - Could not get primary "
449	      "pixformat: %08x\n",
450	      (unsigned int) ddrval);
451      return FALSE;
452    }
453
454#if CYGDEBUG
455  winDebug ("winAllocateFBShadowDDNL - Primary masks: %08x %08x %08x "
456	  "dwRGBBitCount: %d\n",
457	  ddpfPrimary.u2.dwRBitMask,
458	  ddpfPrimary.u3.dwGBitMask,
459	  ddpfPrimary.u4.dwBBitMask,
460	  ddpfPrimary.u1.dwRGBBitCount);
461#endif
462
463  /* Describe the shadow surface to be created */
464  /*
465   * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
466   * as drawing, locking, and unlocking take forever
467   * with video memory surfaces.  In addition,
468   * video memory is a somewhat scarce resource,
469   * so you shouldn't be allocating video memory when
470   * you have the option of using system memory instead.
471   */
472  ZeroMemory (&ddsdShadow, sizeof (ddsdShadow));
473  ddsdShadow.dwSize = sizeof (ddsdShadow);
474  ddsdShadow.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH
475    | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT;
476  ddsdShadow.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
477  ddsdShadow.dwHeight = pScreenInfo->dwHeight;
478  ddsdShadow.dwWidth = pScreenInfo->dwWidth;
479  ddsdShadow.u1.lPitch = pScreenInfo->dwPaddedWidth;
480  ddsdShadow.lpSurface = lpSurface;
481  ddsdShadow.u4.ddpfPixelFormat = ddpfPrimary;
482
483  winDebug ("winAllocateFBShadowDDNL - lPitch: %d\n",
484	  (int) pScreenInfo->dwPaddedWidth);
485
486  /* Create the shadow surface */
487  ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
488				       &ddsdShadow,
489				       &pScreenPriv->pddsShadow4,
490				       NULL);
491  if (FAILED (ddrval))
492    {
493      ErrorF ("winAllocateFBShadowDDNL - Could not create shadow "
494	      "surface: %08x\n", (unsigned int) ddrval);
495      return FALSE;
496    }
497
498#if CYGDEBUG || YES
499  winDebug ("winAllocateFBShadowDDNL - Created shadow pitch: %d\n",
500	  (int) ddsdShadow.u1.lPitch);
501#endif
502
503  /* Grab the pitch from the surface desc */
504  pScreenInfo->dwStride = (ddsdShadow.u1.lPitch * 8)
505    / pScreenInfo->dwBPP;
506
507#if CYGDEBUG || YES
508  winDebug ("winAllocateFBShadowDDNL - Created shadow stride: %d\n",
509	  (int) pScreenInfo->dwStride);
510#endif
511
512  /* Save the pointer to our surface memory */
513  pScreenInfo->pfb = lpSurface;
514
515  /* Grab the masks from the surface description */
516  pScreenPriv->dwRedMask = ddsdShadow.u4.ddpfPixelFormat.u2.dwRBitMask;
517  pScreenPriv->dwGreenMask = ddsdShadow.u4.ddpfPixelFormat.u3.dwGBitMask;
518  pScreenPriv->dwBlueMask = ddsdShadow.u4.ddpfPixelFormat.u4.dwBBitMask;
519
520#if CYGDEBUG
521  winDebug ("winAllocateFBShadowDDNL - Returning\n");
522#endif
523
524  return TRUE;
525}
526
527
528#if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
529/*
530 * Create a DirectDraw surface for the new multi-window window
531 */
532
533static
534Bool
535winFinishCreateWindowsWindowDDNL (WindowPtr pWin)
536{
537  winWindowPriv(pWin);
538  winPrivScreenPtr	pScreenPriv = pWinPriv->pScreenPriv;
539  HRESULT		ddrval = DD_OK;
540  DDSURFACEDESC2	ddsd;
541  int			iWidth, iHeight;
542  int			iX, iY;
543
544  winDebug ("\nwinFinishCreateWindowsWindowDDNL!\n\n");
545
546  iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
547  iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
548
549  iWidth = pWin->drawable.width;
550  iHeight = pWin->drawable.height;
551
552  /* Describe the primary surface */
553  ZeroMemory (&ddsd, sizeof (ddsd));
554  ddsd.dwSize = sizeof (ddsd);
555  ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
556  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
557  ddsd.dwHeight = iHeight;
558  ddsd.dwWidth = iWidth;
559
560  /* Create the primary surface */
561  ddrval = IDirectDraw4_CreateSurface (pScreenPriv->pdd4,
562				       &ddsd,
563				       &pWinPriv->pddsPrimary4,
564				       NULL);
565  if (FAILED (ddrval))
566    {
567      ErrorF ("winFinishCreateWindowsWindowDDNL - Could not create primary "
568	      "surface: %08x\n",
569	      (unsigned int)ddrval);
570      return FALSE;
571    }
572  return TRUE;
573}
574#endif
575
576
577/*
578 * Transfer the damaged regions of the shadow framebuffer to the display.
579 */
580
581static void
582winShadowUpdateDDNL (ScreenPtr pScreen,
583		     shadowBufPtr pBuf)
584{
585  winScreenPriv(pScreen);
586  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
587  RegionPtr		damage = &pBuf->damage;
588  HRESULT		ddrval = DD_OK;
589  RECT			rcDest, rcSrc;
590  POINT			ptOrigin;
591  DWORD			dwBox = REGION_NUM_RECTS (damage);
592  BoxPtr		pBox = REGION_RECTS (damage);
593  HRGN			hrgnTemp = NULL, hrgnCombined = NULL;
594
595  /*
596   * Return immediately if the app is not active
597   * and we are fullscreen, or if we have a bad display depth
598   */
599  if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
600      || pScreenPriv->fBadDepth) return;
601
602  /* Get the origin of the window in the screen coords */
603  ptOrigin.x = pScreenInfo->dwXOffset;
604  ptOrigin.y = pScreenInfo->dwYOffset;
605  MapWindowPoints (pScreenPriv->hwndScreen,
606		   HWND_DESKTOP,
607		   (LPPOINT)&ptOrigin, 1);
608
609  /*
610   * Handle small regions with multiple blits,
611   * handle large regions by creating a clipping region and
612   * doing a single blit constrained to that clipping region.
613   */
614  if (pScreenInfo->dwClipUpdatesNBoxes == 0
615      || dwBox < pScreenInfo->dwClipUpdatesNBoxes)
616    {
617      /* Loop through all boxes in the damaged region */
618      while (dwBox--)
619	{
620	  /* Assign damage box to source rectangle */
621	  rcSrc.left = pBox->x1;
622	  rcSrc.top = pBox->y1;
623	  rcSrc.right = pBox->x2;
624	  rcSrc.bottom = pBox->y2;
625
626	  /* Calculate destination rectangle */
627	  rcDest.left = ptOrigin.x + rcSrc.left;
628	  rcDest.top = ptOrigin.y + rcSrc.top;
629	  rcDest.right = ptOrigin.x + rcSrc.right;
630	  rcDest.bottom = ptOrigin.y + rcSrc.bottom;
631
632	  /* Blit the damaged areas */
633	  ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
634					    &rcDest,
635					    pScreenPriv->pddsShadow4,
636					    &rcSrc,
637					    DDBLT_WAIT,
638					    NULL);
639	  if (FAILED (ddrval))
640	    {
641	      static int	s_iFailCount = 0;
642
643	      if (s_iFailCount < FAIL_MSG_MAX_BLT)
644		{
645		  ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () "
646			  "failed: %08x\n",
647			  (unsigned int) ddrval);
648
649		  ++s_iFailCount;
650
651		  if (s_iFailCount == FAIL_MSG_MAX_BLT)
652		    {
653		      ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt "
654			      "failure message maximum (%d) reached.  No "
655			      "more failure messages will be printed.\n",
656			      FAIL_MSG_MAX_BLT);
657		    }
658		}
659	    }
660
661	  /* Get a pointer to the next box */
662	  ++pBox;
663	}
664    }
665  else
666    {
667      BoxPtr		pBoxExtents = REGION_EXTENTS (pScreen, damage);
668
669      /* Compute a GDI region from the damaged region */
670      hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
671      dwBox--;
672      pBox++;
673      while (dwBox--)
674	{
675	  hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
676	  CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
677	  DeleteObject (hrgnTemp);
678	  pBox++;
679	}
680
681      /* Install the GDI region as a clipping region */
682      SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
683      DeleteObject (hrgnCombined);
684      hrgnCombined = NULL;
685
686#if CYGDEBUG
687      winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n",
688	      pBoxExtents->x1, pBoxExtents->y1,
689	      pBoxExtents->x2, pBoxExtents->y2);
690#endif
691
692      /* Calculating a bounding box for the source is easy */
693      rcSrc.left = pBoxExtents->x1;
694      rcSrc.top = pBoxExtents->y1;
695      rcSrc.right = pBoxExtents->x2;
696      rcSrc.bottom = pBoxExtents->y2;
697
698      /* Calculating a bounding box for the destination is trickier */
699      rcDest.left = ptOrigin.x + rcSrc.left;
700      rcDest.top = ptOrigin.y + rcSrc.top;
701      rcDest.right = ptOrigin.x + rcSrc.right;
702      rcDest.bottom = ptOrigin.y + rcSrc.bottom;
703
704      /* Our Blt should be clipped to the invalidated region */
705      ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
706					&rcDest,
707					pScreenPriv->pddsShadow4,
708					&rcSrc,
709					DDBLT_WAIT,
710					NULL);
711
712      /* Reset the clip region */
713      SelectClipRgn (pScreenPriv->hdcScreen, NULL);
714    }
715}
716
717
718/*
719 * Call the wrapped CloseScreen function.
720 *
721 * Free our resources and private structures.
722 */
723
724static Bool
725winCloseScreenShadowDDNL (int nIndex, ScreenPtr pScreen)
726{
727  winScreenPriv(pScreen);
728  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
729  Bool			fReturn;
730
731#if CYGDEBUG
732  winDebug ("winCloseScreenShadowDDNL - Freeing screen resources\n");
733#endif
734
735  /* Flag that the screen is closed */
736  pScreenPriv->fClosed = TRUE;
737  pScreenPriv->fActive = FALSE;
738
739  /* Call the wrapped CloseScreen procedure */
740  WIN_UNWRAP(CloseScreen);
741  fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
742
743  /* Free the screen DC */
744  ReleaseDC (pScreenPriv->hwndScreen, pScreenPriv->hdcScreen);
745
746  /* Delete the window property */
747  RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
748
749  /* Free the shadow surface, if there is one */
750  if (pScreenPriv->pddsShadow4)
751    {
752      IDirectDrawSurface4_Release (pScreenPriv->pddsShadow4);
753      free (pScreenInfo->pfb);
754      pScreenInfo->pfb = NULL;
755      pScreenPriv->pddsShadow4 = NULL;
756    }
757
758  /* Detach the clipper from the primary surface and release the clipper. */
759  if (pScreenPriv->pddcPrimary)
760    {
761      /* Detach the clipper */
762      IDirectDrawSurface4_SetClipper (pScreenPriv->pddsPrimary4,
763				      NULL);
764
765      /* Release the clipper object */
766      IDirectDrawClipper_Release (pScreenPriv->pddcPrimary);
767      pScreenPriv->pddcPrimary = NULL;
768    }
769
770  /* Release the primary surface, if there is one */
771  if (pScreenPriv->pddsPrimary4)
772    {
773      IDirectDrawSurface4_Release (pScreenPriv->pddsPrimary4);
774      pScreenPriv->pddsPrimary4 = NULL;
775    }
776
777  /* Free the DirectDraw4 object, if there is one */
778  if (pScreenPriv->pdd4)
779    {
780      IDirectDraw4_RestoreDisplayMode (pScreenPriv->pdd4);
781      IDirectDraw4_Release (pScreenPriv->pdd4);
782      pScreenPriv->pdd4 = NULL;
783    }
784
785  /* Free the DirectDraw object, if there is one */
786  if (pScreenPriv->pdd)
787    {
788      IDirectDraw_Release (pScreenPriv->pdd);
789      pScreenPriv->pdd = NULL;
790    }
791
792  /* Delete tray icon, if we have one */
793  if (!pScreenInfo->fNoTrayIcon)
794    winDeleteNotifyIcon (pScreenPriv);
795
796  /* Free the exit confirmation dialog box, if it exists */
797  if (g_hDlgExit != NULL)
798    {
799      DestroyWindow (g_hDlgExit);
800      g_hDlgExit = NULL;
801    }
802
803  /* Kill our window */
804  if (pScreenPriv->hwndScreen)
805    {
806      DestroyWindow (pScreenPriv->hwndScreen);
807      pScreenPriv->hwndScreen = NULL;
808    }
809
810#if defined(XWIN_CLIPBOARD) || defined(XWIN_MULTIWINDOW)
811  /* Destroy the thread startup mutex */
812  pthread_mutex_destroy (&pScreenPriv->pmServerStarted);
813#endif
814
815  /* Kill our screeninfo's pointer to the screen */
816  pScreenInfo->pScreen = NULL;
817
818  /* Invalidate the ScreenInfo's fb pointer */
819  pScreenInfo->pfb = NULL;
820
821  /* Free the screen privates for this screen */
822  free ((pointer) pScreenPriv);
823
824  return fReturn;
825}
826
827
828/*
829 * Tell mi what sort of visuals we need.
830 *
831 * Generally we only need one visual, as our screen can only
832 * handle one format at a time, I believe.  You may want
833 * to verify that last sentence.
834 */
835
836static Bool
837winInitVisualsShadowDDNL (ScreenPtr pScreen)
838{
839  winScreenPriv(pScreen);
840  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
841  DWORD			dwRedBits, dwGreenBits, dwBlueBits;
842
843  /* Count the number of ones in each color mask */
844  dwRedBits = winCountBits (pScreenPriv->dwRedMask);
845  dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
846  dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
847
848  /* Store the maximum number of ones in a color mask as the bitsPerRGB */
849  if (dwRedBits == 0 || dwGreenBits == 0 || dwBlueBits == 0)
850    pScreenPriv->dwBitsPerRGB = 8;
851  else if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
852    pScreenPriv->dwBitsPerRGB = dwRedBits;
853  else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
854    pScreenPriv->dwBitsPerRGB = dwGreenBits;
855  else
856    pScreenPriv->dwBitsPerRGB = dwBlueBits;
857
858  winDebug ("winInitVisualsShadowDDNL - Masks %08x %08x %08x BPRGB %d d %d "
859	  "bpp %d\n",
860	  (unsigned int) pScreenPriv->dwRedMask,
861	  (unsigned int) pScreenPriv->dwGreenMask,
862	  (unsigned int) pScreenPriv->dwBlueMask,
863	  (int) pScreenPriv->dwBitsPerRGB,
864	  (int) pScreenInfo->dwDepth,
865	  (int) pScreenInfo->dwBPP);
866
867  /* Create a single visual according to the Windows screen depth */
868  switch (pScreenInfo->dwDepth)
869    {
870    case 24:
871    case 16:
872    case 15:
873#if defined(XFree86Server)
874      /* Setup the real visual */
875      if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
876				     TrueColorMask,
877				     pScreenPriv->dwBitsPerRGB,
878				     -1,
879				     pScreenPriv->dwRedMask,
880				     pScreenPriv->dwGreenMask,
881				     pScreenPriv->dwBlueMask))
882	{
883	  ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
884		  "failed for TrueColor\n");
885	  return FALSE;
886	}
887
888#ifdef XWIN_EMULATEPSEUDO
889      if (!pScreenInfo->fEmulatePseudo)
890	break;
891
892      /* Setup a pseudocolor visual */
893      if (!miSetVisualTypesAndMasks (8,
894				     PseudoColorMask,
895				     8,
896				     -1,
897				     0,
898				     0,
899				     0))
900	{
901	  ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
902		  "failed for PseudoColor\n");
903	  return FALSE;
904	}
905#endif
906#else /* XFree86Server */
907      /* Setup the real visual */
908      if (!fbSetVisualTypesAndMasks (pScreenInfo->dwDepth,
909				     TrueColorMask,
910				     pScreenPriv->dwBitsPerRGB,
911				     pScreenPriv->dwRedMask,
912				     pScreenPriv->dwGreenMask,
913				     pScreenPriv->dwBlueMask))
914	{
915	  ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks "
916		  "failed for TrueColor\n");
917	  return FALSE;
918	}
919
920#ifdef XWIN_EMULATEPSEUDO
921      if (!pScreenInfo->fEmulatePseudo)
922	break;
923
924      /* Setup a pseudocolor visual */
925      if (!fbSetVisualTypesAndMasks (8,
926				     PseudoColorMask,
927				     8,
928				     0,
929				     0,
930				     0))
931	{
932	  ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks "
933		  "failed for PseudoColor\n");
934	  return FALSE;
935	}
936#endif
937#endif /* XFree86Server */
938      break;
939
940    case 8:
941#if defined(XFree86Server)
942      if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
943				     pScreenInfo->fFullScreen
944				     ? PseudoColorMask : StaticColorMask,
945				     pScreenPriv->dwBitsPerRGB,
946				     pScreenInfo->fFullScreen
947				     ? PseudoColor : StaticColor,
948				     pScreenPriv->dwRedMask,
949				     pScreenPriv->dwGreenMask,
950				     pScreenPriv->dwBlueMask))
951	{
952	  ErrorF ("winInitVisualsShadowDDNL - miSetVisualTypesAndMasks "
953		  "failed\n");
954	  return FALSE;
955	}
956#else /* XFree86Server */
957        if (!fbSetVisualTypesAndMasks (pScreenInfo->dwDepth,
958				     pScreenInfo->fFullScreen
959				     ? PseudoColorMask : StaticColorMask,
960				     pScreenPriv->dwBitsPerRGB,
961				     pScreenPriv->dwRedMask,
962				     pScreenPriv->dwGreenMask,
963				     pScreenPriv->dwBlueMask))
964	{
965	  ErrorF ("winInitVisualsShadowDDNL - fbSetVisualTypesAndMasks "
966		  "failed\n");
967	  return FALSE;
968	}
969#endif /* XFree86Server */
970      break;
971
972    default:
973      ErrorF ("winInitVisualsShadowDDNL - Unknown screen depth\n");
974      return FALSE;
975    }
976
977#if CYGDEBUG
978  winDebug ("winInitVisualsShadowDDNL - Returning\n");
979#endif
980
981  return TRUE;
982}
983
984
985/*
986 * Adjust the user proposed video mode
987 */
988
989static Bool
990winAdjustVideoModeShadowDDNL (ScreenPtr pScreen)
991{
992  winScreenPriv(pScreen);
993  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
994  HDC			hdc = NULL;
995  DWORD			dwBPP;
996
997  /* We're in serious trouble if we can't get a DC */
998  hdc = GetDC (NULL);
999  if (hdc == NULL)
1000    {
1001      ErrorF ("winAdjustVideoModeShadowDDNL - GetDC () failed\n");
1002      return FALSE;
1003    }
1004
1005  /* Query GDI for current display depth */
1006  dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
1007
1008  /* DirectDraw can only change the depth in fullscreen mode */
1009  if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP)
1010    {
1011      /* No -depth parameter passed, let the user know the depth being used */
1012      winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - Using Windows display "
1013	      "depth of %d bits per pixel\n", (int) dwBPP);
1014
1015      /* Use GDI's depth */
1016      pScreenInfo->dwBPP = dwBPP;
1017    }
1018  else if (pScreenInfo->fFullScreen
1019	   && pScreenInfo->dwBPP != dwBPP)
1020    {
1021      /* FullScreen, and GDI depth differs from -depth parameter */
1022      winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - FullScreen, using command "
1023	      "line bpp: %d\n", (int) pScreenInfo->dwBPP);
1024    }
1025  else if (dwBPP != pScreenInfo->dwBPP)
1026    {
1027      /* Windowed, and GDI depth differs from -depth parameter */
1028      winErrorFVerb (2, "winAdjustVideoModeShadowDDNL - Windowed, command line "
1029	      "bpp: %d, using bpp: %d\n",
1030	      (int) pScreenInfo->dwBPP, (int) dwBPP);
1031
1032      /* We'll use GDI's depth */
1033      pScreenInfo->dwBPP = dwBPP;
1034    }
1035
1036  /* See if the shadow bitmap will be larger than the DIB size limit */
1037  if (pScreenInfo->dwWidth * pScreenInfo->dwHeight * pScreenInfo->dwBPP
1038      >= WIN_DIB_MAXIMUM_SIZE)
1039    {
1040      winErrorFVerb (1, "winAdjustVideoModeShadowDDNL - Requested DirectDraw surface "
1041	      "will be larger than %d MB.  The surface may fail to be "
1042	      "allocated on Windows 95, 98, or Me, due to a %d MB limit in "
1043	      "DIB size.  This limit does not apply to Windows NT/2000, and "
1044	      "this message may be ignored on those platforms.\n",
1045	      WIN_DIB_MAXIMUM_SIZE_MB, WIN_DIB_MAXIMUM_SIZE_MB);
1046    }
1047
1048  /* Release our DC */
1049  ReleaseDC (NULL, hdc);
1050
1051  return TRUE;
1052}
1053
1054
1055/*
1056 * Blt exposed regions to the screen
1057 */
1058
1059static Bool
1060winBltExposedRegionsShadowDDNL (ScreenPtr pScreen)
1061{
1062  winScreenPriv(pScreen);
1063  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
1064  RECT			rcSrc, rcDest;
1065  POINT			ptOrigin;
1066  HDC			hdcUpdate;
1067  PAINTSTRUCT		ps;
1068  HRESULT		ddrval = DD_OK;
1069  Bool			fReturn = TRUE;
1070  int			i;
1071
1072  /* Quite common case. The primary surface was lost (maybe because of depth
1073   * change). Try to create a new primary surface. Bail out if this fails */
1074  if (pScreenPriv->pddsPrimary4 == NULL && pScreenPriv->fRetryCreateSurface &&
1075      !winCreatePrimarySurfaceShadowDDNL(pScreen))
1076    {
1077      Sleep(100);
1078      return FALSE;
1079    }
1080  if (pScreenPriv->pddsPrimary4 == NULL)
1081    return FALSE;
1082
1083  /* BeginPaint gives us an hdc that clips to the invalidated region */
1084  hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
1085  if (hdcUpdate == NULL)
1086    {
1087      fReturn = FALSE;
1088      ErrorF ("winBltExposedRegionsShadowDDNL - BeginPaint () returned "
1089	      "a NULL device context handle.  Aborting blit attempt.\n");
1090      goto winBltExposedRegionsShadowDDNL_Exit;
1091    }
1092
1093  /* Get the origin of the window in the screen coords */
1094  ptOrigin.x = pScreenInfo->dwXOffset;
1095  ptOrigin.y = pScreenInfo->dwYOffset;
1096
1097  MapWindowPoints (pScreenPriv->hwndScreen,
1098		   HWND_DESKTOP,
1099		   (LPPOINT)&ptOrigin, 1);
1100  rcDest.left = ptOrigin.x;
1101  rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
1102  rcDest.top = ptOrigin.y;
1103  rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
1104
1105  /* Source can be entire shadow surface, as Blt should clip for us */
1106  rcSrc.left = 0;
1107  rcSrc.top = 0;
1108  rcSrc.right = pScreenInfo->dwWidth;
1109  rcSrc.bottom = pScreenInfo->dwHeight;
1110
1111  /* Try to regain the primary surface and blit again if we've lost it */
1112  for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i)
1113    {
1114      /* Our Blt should be clipped to the invalidated region */
1115      ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
1116					&rcDest,
1117					pScreenPriv->pddsShadow4,
1118					&rcSrc,
1119					DDBLT_WAIT,
1120					NULL);
1121      if (ddrval == DDERR_SURFACELOST)
1122	{
1123	  /* Surface was lost */
1124	  winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
1125          "IDirectDrawSurface4_Blt reported that the primary "
1126          "surface was lost, trying to restore, retry: %d\n", i + 1);
1127
1128	  /* Try to restore the surface, once */
1129
1130	  ddrval = IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4);
1131	  winDebug ("winBltExposedRegionsShadowDDNL - "
1132		  "IDirectDrawSurface4_Restore returned: ");
1133	  if (ddrval == DD_OK)
1134	    winDebug ("DD_OK\n");
1135	  else if (ddrval == DDERR_WRONGMODE)
1136	    winDebug ("DDERR_WRONGMODE\n");
1137	  else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
1138	    winDebug ("DDERR_INCOMPATIBLEPRIMARY\n");
1139	  else if (ddrval == DDERR_UNSUPPORTED)
1140	    winDebug ("DDERR_UNSUPPORTED\n");
1141	  else if (ddrval == DDERR_INVALIDPARAMS)
1142	    winDebug ("DDERR_INVALIDPARAMS\n");
1143	  else if (ddrval == DDERR_INVALIDOBJECT)
1144	    winDebug ("DDERR_INVALIDOBJECT\n");
1145	  else
1146	    winDebug ("unknown error: %08x\n", (unsigned int) ddrval);
1147
1148	  /* Loop around to try the blit one more time */
1149	  continue;
1150	}
1151      else if (FAILED (ddrval))
1152	{
1153	  fReturn = FALSE;
1154	  winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
1155		  "IDirectDrawSurface4_Blt failed, but surface not "
1156		  "lost: %08x %d\n",
1157		  (unsigned int) ddrval, (int) ddrval);
1158	  goto winBltExposedRegionsShadowDDNL_Exit;
1159	}
1160      else
1161	{
1162	  /* Success, stop looping */
1163	  break;
1164	}
1165    }
1166
1167 winBltExposedRegionsShadowDDNL_Exit:
1168  /* EndPaint frees the DC */
1169  if (hdcUpdate != NULL)
1170    EndPaint (pScreenPriv->hwndScreen, &ps);
1171  return fReturn;
1172}
1173
1174
1175/*
1176 * Do any engine-specific application-activation processing
1177 */
1178
1179static Bool
1180winActivateAppShadowDDNL (ScreenPtr pScreen)
1181{
1182  winScreenPriv(pScreen);
1183
1184  /*
1185   * Do we have a surface?
1186   * Are we active?
1187   * Are we full screen?
1188   */
1189  if (pScreenPriv != NULL
1190      && pScreenPriv->pddsPrimary4 != NULL
1191      && pScreenPriv->fActive)
1192    {
1193      /* Primary surface was lost, restore it */
1194      IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4);
1195    }
1196
1197  return TRUE;
1198}
1199
1200
1201/*
1202 * Reblit the shadow framebuffer to the screen.
1203 */
1204
1205static Bool
1206winRedrawScreenShadowDDNL (ScreenPtr pScreen)
1207{
1208  winScreenPriv(pScreen);
1209  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
1210  HRESULT		ddrval = DD_OK;
1211  RECT			rcSrc, rcDest;
1212  POINT			ptOrigin;
1213
1214  /* Get the origin of the window in the screen coords */
1215  ptOrigin.x = pScreenInfo->dwXOffset;
1216  ptOrigin.y = pScreenInfo->dwYOffset;
1217  MapWindowPoints (pScreenPriv->hwndScreen,
1218		   HWND_DESKTOP,
1219		   (LPPOINT)&ptOrigin, 1);
1220  rcDest.left = ptOrigin.x;
1221  rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
1222  rcDest.top = ptOrigin.y;
1223  rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;
1224
1225  /* Source can be entire shadow surface, as Blt should clip for us */
1226  rcSrc.left = 0;
1227  rcSrc.top = 0;
1228  rcSrc.right = pScreenInfo->dwWidth;
1229  rcSrc.bottom = pScreenInfo->dwHeight;
1230
1231  /* Redraw the whole window, to take account for the new colors */
1232  ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
1233				    &rcDest,
1234				    pScreenPriv->pddsShadow4,
1235				    &rcSrc,
1236				    DDBLT_WAIT,
1237				    NULL);
1238  if (FAILED (ddrval))
1239    {
1240      ErrorF ("winRedrawScreenShadowDDNL - IDirectDrawSurface4_Blt () "
1241	      "failed: %08x\n",
1242	      (unsigned int) ddrval);
1243    }
1244
1245  return TRUE;
1246}
1247
1248
1249/*
1250 * Realize the currently installed colormap
1251 */
1252
1253static Bool
1254winRealizeInstalledPaletteShadowDDNL (ScreenPtr pScreen)
1255{
1256  return TRUE;
1257}
1258
1259
1260/*
1261 * Install the specified colormap
1262 */
1263
1264static Bool
1265winInstallColormapShadowDDNL (ColormapPtr pColormap)
1266{
1267  ScreenPtr		pScreen = pColormap->pScreen;
1268  winScreenPriv(pScreen);
1269  winCmapPriv(pColormap);
1270  HRESULT		ddrval = DD_OK;
1271
1272  /* Install the DirectDraw palette on the primary surface */
1273  ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4,
1274					   pCmapPriv->lpDDPalette);
1275  if (FAILED (ddrval))
1276    {
1277      ErrorF ("winInstallColormapShadowDDNL - Failed installing the "
1278	      "DirectDraw palette.\n");
1279      return FALSE;
1280    }
1281
1282  /* Save a pointer to the newly installed colormap */
1283  pScreenPriv->pcmapInstalled = pColormap;
1284
1285  return TRUE;
1286}
1287
1288
1289/*
1290 * Store the specified colors in the specified colormap
1291 */
1292
1293static Bool
1294winStoreColorsShadowDDNL (ColormapPtr pColormap,
1295			  int ndef,
1296			  xColorItem *pdefs)
1297{
1298  ScreenPtr		pScreen = pColormap->pScreen;
1299  winScreenPriv(pScreen);
1300  winCmapPriv(pColormap);
1301  ColormapPtr		curpmap = pScreenPriv->pcmapInstalled;
1302  HRESULT		ddrval = DD_OK;
1303
1304  /* Put the X colormap entries into the Windows logical palette */
1305  ddrval = IDirectDrawPalette_SetEntries (pCmapPriv->lpDDPalette,
1306					  0,
1307					  pdefs[0].pixel,
1308					  ndef,
1309					  pCmapPriv->peColors
1310					  + pdefs[0].pixel);
1311  if (FAILED (ddrval))
1312    {
1313      ErrorF ("winStoreColorsShadowDDNL - SetEntries () failed: %08x\n", ddrval);
1314      return FALSE;
1315    }
1316
1317  /* Don't install the DirectDraw palette if the colormap is not installed */
1318  if (pColormap != curpmap)
1319    {
1320      return TRUE;
1321    }
1322
1323  if (!winInstallColormapShadowDDNL (pColormap))
1324    {
1325      ErrorF ("winStoreColorsShadowDDNL - Failed installing colormap\n");
1326      return FALSE;
1327    }
1328
1329  return TRUE;
1330}
1331
1332
1333/*
1334 * Colormap initialization procedure
1335 */
1336
1337static Bool
1338winCreateColormapShadowDDNL (ColormapPtr pColormap)
1339{
1340  HRESULT		ddrval = DD_OK;
1341  ScreenPtr		pScreen = pColormap->pScreen;
1342  winScreenPriv(pScreen);
1343  winCmapPriv(pColormap);
1344
1345  /* Create a DirectDraw palette */
1346  ddrval = IDirectDraw4_CreatePalette (pScreenPriv->pdd4,
1347				       DDPCAPS_8BIT | DDPCAPS_ALLOW256,
1348				       pCmapPriv->peColors,
1349				       &pCmapPriv->lpDDPalette,
1350				       NULL);
1351  if (FAILED (ddrval))
1352    {
1353      ErrorF ("winCreateColormapShadowDDNL - CreatePalette failed\n");
1354      return FALSE;
1355    }
1356
1357  return TRUE;
1358}
1359
1360
1361/*
1362 * Colormap destruction procedure
1363 */
1364
1365static Bool
1366winDestroyColormapShadowDDNL (ColormapPtr pColormap)
1367{
1368  winScreenPriv(pColormap->pScreen);
1369  winCmapPriv(pColormap);
1370  HRESULT		ddrval = DD_OK;
1371
1372  /*
1373   * Is colormap to be destroyed the default?
1374   *
1375   * Non-default colormaps should have had winUninstallColormap
1376   * called on them before we get here.  The default colormap
1377   * will not have had winUninstallColormap called on it.  Thus,
1378   * we need to handle the default colormap in a special way.
1379   */
1380  if (pColormap->flags & IsDefault)
1381    {
1382#if CYGDEBUG
1383      winDebug ("winDestroyColormapShadowDDNL - Destroying default colormap\n");
1384#endif
1385
1386      /*
1387       * FIXME: Walk the list of all screens, popping the default
1388       * palette out of each screen device context.
1389       */
1390
1391      /* Pop the palette out of the primary surface */
1392      ddrval = IDirectDrawSurface4_SetPalette (pScreenPriv->pddsPrimary4,
1393					       NULL);
1394      if (FAILED (ddrval))
1395	{
1396	  ErrorF ("winDestroyColormapShadowDDNL - Failed freeing the "
1397		  "default colormap DirectDraw palette.\n");
1398	  return FALSE;
1399	}
1400
1401      /* Clear our private installed colormap pointer */
1402      pScreenPriv->pcmapInstalled = NULL;
1403    }
1404
1405  /* Release the palette */
1406  IDirectDrawPalette_Release (pCmapPriv->lpDDPalette);
1407
1408  /* Invalidate the colormap privates */
1409  pCmapPriv->lpDDPalette = NULL;
1410
1411  return TRUE;
1412}
1413
1414
1415/*
1416 * Set pointers to our engine specific functions
1417 */
1418
1419Bool
1420winSetEngineFunctionsShadowDDNL (ScreenPtr pScreen)
1421{
1422  winScreenPriv(pScreen);
1423  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
1424
1425  /* Set our pointers */
1426  pScreenPriv->pwinAllocateFB = winAllocateFBShadowDDNL;
1427  pScreenPriv->pwinShadowUpdate = winShadowUpdateDDNL;
1428  pScreenPriv->pwinCloseScreen = winCloseScreenShadowDDNL;
1429  pScreenPriv->pwinInitVisuals = winInitVisualsShadowDDNL;
1430  pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModeShadowDDNL;
1431  if (pScreenInfo->fFullScreen)
1432    pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
1433  else
1434    pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
1435  pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
1436  pScreenPriv->pwinBltExposedRegions = winBltExposedRegionsShadowDDNL;
1437  pScreenPriv->pwinActivateApp = winActivateAppShadowDDNL;
1438  pScreenPriv->pwinRedrawScreen = winRedrawScreenShadowDDNL;
1439  pScreenPriv->pwinRealizeInstalledPalette
1440    = winRealizeInstalledPaletteShadowDDNL;
1441  pScreenPriv->pwinInstallColormap = winInstallColormapShadowDDNL;
1442  pScreenPriv->pwinStoreColors = winStoreColorsShadowDDNL;
1443  pScreenPriv->pwinCreateColormap = winCreateColormapShadowDDNL;
1444  pScreenPriv->pwinDestroyColormap = winDestroyColormapShadowDDNL;
1445  pScreenPriv->pwinHotKeyAltTab = (winHotKeyAltTabProcPtr) (void (*)(void))NoopDDA;
1446  pScreenPriv->pwinCreatePrimarySurface = winCreatePrimarySurfaceShadowDDNL;
1447  pScreenPriv->pwinReleasePrimarySurface = winReleasePrimarySurfaceShadowDDNL;
1448#ifdef XWIN_MULTIWINDOW
1449  pScreenPriv->pwinFinishCreateWindowsWindow
1450    = winFinishCreateWindowsWindowDDNL;
1451#endif
1452
1453  return TRUE;
1454}
1455