1706f2543Smrg/*
2706f2543Smrg *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3706f2543Smrg *
4706f2543Smrg *Permission is hereby granted, free of charge, to any person obtaining
5706f2543Smrg * a copy of this software and associated documentation files (the
6706f2543Smrg *"Software"), to deal in the Software without restriction, including
7706f2543Smrg *without limitation the rights to use, copy, modify, merge, publish,
8706f2543Smrg *distribute, sublicense, and/or sell copies of the Software, and to
9706f2543Smrg *permit persons to whom the Software is furnished to do so, subject to
10706f2543Smrg *the following conditions:
11706f2543Smrg *
12706f2543Smrg *The above copyright notice and this permission notice shall be
13706f2543Smrg *included in all copies or substantial portions of the Software.
14706f2543Smrg *
15706f2543Smrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16706f2543Smrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17706f2543Smrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18706f2543Smrg *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19706f2543Smrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20706f2543Smrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21706f2543Smrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22706f2543Smrg *
23706f2543Smrg *Except as contained in this notice, the name of the XFree86 Project
24706f2543Smrg *shall not be used in advertising or otherwise to promote the sale, use
25706f2543Smrg *or other dealings in this Software without prior written authorization
26706f2543Smrg *from the XFree86 Project.
27706f2543Smrg *
28706f2543Smrg * Authors:	Dakshinamurthy Karra
29706f2543Smrg *		Suhaib M Siddiqi
30706f2543Smrg *		Peter Busch
31706f2543Smrg *		Harold L Hunt II
32706f2543Smrg */
33706f2543Smrg
34706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H
35706f2543Smrg#include <xwin-config.h>
36706f2543Smrg#endif
37706f2543Smrg#include "win.h"
38706f2543Smrg
39706f2543Smrg
40706f2543Smrg/*
41706f2543Smrg * Local function prototypes
42706f2543Smrg */
43706f2543Smrg
44706f2543Smrgstatic Bool
45706f2543SmrgwinAllocateFBPrimaryDD (ScreenPtr pScreen);
46706f2543Smrg
47706f2543Smrgstatic Bool
48706f2543SmrgwinCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen);
49706f2543Smrg
50706f2543Smrgstatic Bool
51706f2543SmrgwinInitVisualsPrimaryDD (ScreenPtr pScreen);
52706f2543Smrg
53706f2543Smrgstatic Bool
54706f2543SmrgwinAdjustVideoModePrimaryDD (ScreenPtr pScreen);
55706f2543Smrg
56706f2543Smrgstatic Bool
57706f2543SmrgwinActivateAppPrimaryDD (ScreenPtr pScreen);
58706f2543Smrg
59706f2543Smrgstatic Bool
60706f2543SmrgwinHotKeyAltTabPrimaryDD (ScreenPtr pScreen);
61706f2543Smrg
62706f2543Smrg
63706f2543Smrg/*
64706f2543Smrg * Create a DirectDraw primary surface
65706f2543Smrg */
66706f2543Smrg
67706f2543Smrgstatic Bool
68706f2543SmrgwinAllocateFBPrimaryDD (ScreenPtr pScreen)
69706f2543Smrg{
70706f2543Smrg  winScreenPriv(pScreen);
71706f2543Smrg  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
72706f2543Smrg  HRESULT		ddrval = DD_OK;
73706f2543Smrg  DDSURFACEDESC		ddsd;
74706f2543Smrg  DDSURFACEDESC		*pddsdPrimary = NULL;
75706f2543Smrg  DDSURFACEDESC		*pddsdOffscreen = NULL;
76706f2543Smrg  RECT			rcClient;
77706f2543Smrg
78706f2543Smrg  ErrorF ("winAllocateFBPrimaryDD\n");
79706f2543Smrg
80706f2543Smrg  /* Get client area location in screen coords */
81706f2543Smrg  GetClientRect (pScreenPriv->hwndScreen, &rcClient);
82706f2543Smrg  MapWindowPoints (pScreenPriv->hwndScreen,
83706f2543Smrg		   HWND_DESKTOP,
84706f2543Smrg		   (LPPOINT)&rcClient, 2);
85706f2543Smrg
86706f2543Smrg  /* Create a DirectDraw object, store the address at lpdd */
87706f2543Smrg  ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL);
88706f2543Smrg  if (ddrval != DD_OK)
89706f2543Smrg    FatalError ("winAllocateFBPrimaryDD - Could not start DirectDraw\n");
90706f2543Smrg
91706f2543Smrg  /* Get a DirectDraw2 interface pointer */
92706f2543Smrg  ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd,
93706f2543Smrg				       &IID_IDirectDraw2,
94706f2543Smrg				       (LPVOID*) &pScreenPriv->pdd2);
95706f2543Smrg  if (FAILED (ddrval))
96706f2543Smrg    {
97706f2543Smrg      ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n",
98706f2543Smrg	      (unsigned int) ddrval);
99706f2543Smrg      return FALSE;
100706f2543Smrg    }
101706f2543Smrg
102706f2543Smrg
103706f2543Smrg  ErrorF ("winAllocateFBPrimaryDD - Created and initialized DD\n");
104706f2543Smrg
105706f2543Smrg  /* Are we windowed or fullscreen? */
106706f2543Smrg  if (pScreenInfo->fFullScreen)
107706f2543Smrg    {
108706f2543Smrg      /* Full screen mode */
109706f2543Smrg      ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
110706f2543Smrg						 pScreenPriv->hwndScreen,
111706f2543Smrg						 DDSCL_FULLSCREEN
112706f2543Smrg						 | DDSCL_EXCLUSIVE);
113706f2543Smrg      if (FAILED (ddrval))
114706f2543Smrg	FatalError ("winAllocateFBPrimaryDD - Could not set "
115706f2543Smrg		    "cooperative level\n");
116706f2543Smrg
117706f2543Smrg      /* Change the video mode to the mode requested */
118706f2543Smrg      ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2,
119706f2543Smrg					    pScreenInfo->dwWidth,
120706f2543Smrg					    pScreenInfo->dwHeight,
121706f2543Smrg					    pScreenInfo->dwBPP,
122706f2543Smrg					    pScreenInfo->dwRefreshRate,
123706f2543Smrg					    0);
124706f2543Smrg       if (FAILED (ddrval))
125706f2543Smrg	FatalError ("winAllocateFBPrimaryDD - Could not set "
126706f2543Smrg		    "full screen display mode\n");
127706f2543Smrg    }
128706f2543Smrg  else
129706f2543Smrg    {
130706f2543Smrg      /* Windowed mode */
131706f2543Smrg      ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2,
132706f2543Smrg						 pScreenPriv->hwndScreen,
133706f2543Smrg						 DDSCL_NORMAL);
134706f2543Smrg      if (FAILED (ddrval))
135706f2543Smrg	FatalError ("winAllocateFBPrimaryDD - Could not set "
136706f2543Smrg		    "cooperative level\n");
137706f2543Smrg    }
138706f2543Smrg
139706f2543Smrg  /* Describe the primary surface */
140706f2543Smrg  ZeroMemory (&ddsd, sizeof (ddsd));
141706f2543Smrg  ddsd.dwSize = sizeof (ddsd);
142706f2543Smrg  ddsd.dwFlags = DDSD_CAPS;
143706f2543Smrg  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
144706f2543Smrg
145706f2543Smrg  /* Create the primary surface */
146706f2543Smrg  ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
147706f2543Smrg				       &ddsd,
148706f2543Smrg				       &pScreenPriv->pddsPrimary,
149706f2543Smrg				       NULL);
150706f2543Smrg  if (FAILED (ddrval))
151706f2543Smrg       FatalError ("winAllocateFBPrimaryDD - Could not create primary "
152706f2543Smrg		  "surface %08x\n", (unsigned int) ddrval);
153706f2543Smrg
154706f2543Smrg  ErrorF ("winAllocateFBPrimaryDD - Created primary\n");
155706f2543Smrg
156706f2543Smrg  /* Allocate a DD surface description for our screen privates */
157706f2543Smrg  pddsdPrimary = pScreenPriv->pddsdPrimary
158706f2543Smrg    = malloc (sizeof (DDSURFACEDESC));
159706f2543Smrg  if (pddsdPrimary == NULL)
160706f2543Smrg    FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
161706f2543Smrg		"description memory\n");
162706f2543Smrg  ZeroMemory (pddsdPrimary, sizeof (*pddsdPrimary));
163706f2543Smrg  pddsdPrimary->dwSize = sizeof (*pddsdPrimary);
164706f2543Smrg
165706f2543Smrg  /* Describe the offscreen surface to be created */
166706f2543Smrg  /*
167706f2543Smrg   * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface,
168706f2543Smrg   * as drawing, locking, and unlocking take forever
169706f2543Smrg   * with video memory surfaces.  In addition,
170706f2543Smrg   * video memory is a somewhat scarce resource,
171706f2543Smrg   * so you shouldn't be allocating video memory when
172706f2543Smrg   * you have the option of using system memory instead.
173706f2543Smrg   */
174706f2543Smrg  ZeroMemory (&ddsd, sizeof (ddsd));
175706f2543Smrg  ddsd.dwSize = sizeof (ddsd);
176706f2543Smrg  ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
177706f2543Smrg  ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
178706f2543Smrg  ddsd.dwHeight = pScreenInfo->dwHeight;
179706f2543Smrg  ddsd.dwWidth = pScreenInfo->dwWidth;
180706f2543Smrg
181706f2543Smrg  /* Create the shadow surface */
182706f2543Smrg  ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2,
183706f2543Smrg				       &ddsd,
184706f2543Smrg				       &pScreenPriv->pddsOffscreen,
185706f2543Smrg				       NULL);
186706f2543Smrg  if (ddrval != DD_OK)
187706f2543Smrg    FatalError ("winAllocateFBPrimaryDD - Could not create shadow "
188706f2543Smrg		"surface\n");
189706f2543Smrg
190706f2543Smrg  ErrorF ("winAllocateFBPrimaryDD - Created offscreen\n");
191706f2543Smrg
192706f2543Smrg  /* Allocate a DD surface description for our screen privates */
193706f2543Smrg  pddsdOffscreen = pScreenPriv->pddsdOffscreen
194706f2543Smrg    = malloc (sizeof (DDSURFACEDESC));
195706f2543Smrg  if (pddsdOffscreen == NULL)
196706f2543Smrg    FatalError ("winAllocateFBPrimaryDD - Could not allocate surface "
197706f2543Smrg		"description memory\n");
198706f2543Smrg  ZeroMemory (pddsdOffscreen, sizeof (*pddsdOffscreen));
199706f2543Smrg  pddsdOffscreen->dwSize = sizeof (*pddsdOffscreen);
200706f2543Smrg
201706f2543Smrg  ErrorF ("winAllocateFBPrimaryDD - Locking primary\n");
202706f2543Smrg
203706f2543Smrg  /* Lock the primary surface */
204706f2543Smrg  ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
205706f2543Smrg				    pScreenInfo->fFullScreen ? NULL:&rcClient,
206706f2543Smrg				    pddsdPrimary,
207706f2543Smrg				    DDLOCK_WAIT,
208706f2543Smrg				    NULL);
209706f2543Smrg  if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL)
210706f2543Smrg    FatalError ("winAllocateFBPrimaryDD - Could not lock "
211706f2543Smrg		"primary surface\n");
212706f2543Smrg
213706f2543Smrg  ErrorF ("winAllocateFBPrimaryDD - Locked primary\n");
214706f2543Smrg
215706f2543Smrg  /* We don't know how to deal with anything other than RGB */
216706f2543Smrg  if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB))
217706f2543Smrg    FatalError ("winAllocateFBPrimaryDD - Color format other than RGB\n");
218706f2543Smrg
219706f2543Smrg  /* Grab the pitch from the surface desc */
220706f2543Smrg  pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8)
221706f2543Smrg    / pScreenInfo->dwBPP;
222706f2543Smrg
223706f2543Smrg  /* Save the pointer to our surface memory */
224706f2543Smrg  pScreenInfo->pfb = pddsdPrimary->lpSurface;
225706f2543Smrg
226706f2543Smrg  /* Grab the color depth and masks from the surface description */
227706f2543Smrg  pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask;
228706f2543Smrg  pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask;
229706f2543Smrg  pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask;
230706f2543Smrg
231706f2543Smrg  ErrorF ("winAllocateFBPrimaryDD - Returning\n");
232706f2543Smrg
233706f2543Smrg  return TRUE;
234706f2543Smrg}
235706f2543Smrg
236706f2543Smrgstatic void
237706f2543SmrgwinFreeFBPrimaryDD (ScreenPtr pScreen)
238706f2543Smrg{
239706f2543Smrg  winScreenPriv(pScreen);
240706f2543Smrg  winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
241706f2543Smrg
242706f2543Smrg  /* Free the offscreen surface, if there is one */
243706f2543Smrg  if (pScreenPriv->pddsOffscreen)
244706f2543Smrg    {
245706f2543Smrg      IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, NULL);
246706f2543Smrg      IDirectDrawSurface2_Release (pScreenPriv->pddsOffscreen);
247706f2543Smrg      pScreenPriv->pddsOffscreen = NULL;
248706f2543Smrg    }
249706f2543Smrg
250706f2543Smrg  /* Release the primary surface, if there is one */
251706f2543Smrg  if (pScreenPriv->pddsPrimary)
252706f2543Smrg    {
253706f2543Smrg      IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, NULL);
254706f2543Smrg      IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary);
255706f2543Smrg      pScreenPriv->pddsPrimary = NULL;
256706f2543Smrg    }
257706f2543Smrg
258706f2543Smrg  /* Free the DirectDraw object, if there is one */
259706f2543Smrg  if (pScreenPriv->pdd)
260706f2543Smrg    {
261706f2543Smrg      IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd);
262706f2543Smrg      IDirectDraw2_Release (pScreenPriv->pdd);
263706f2543Smrg      pScreenPriv->pdd = NULL;
264706f2543Smrg    }
265706f2543Smrg
266706f2543Smrg  /* Invalidate the ScreenInfo's fb pointer */
267706f2543Smrg  pScreenInfo->pfb = NULL;
268706f2543Smrg}
269706f2543Smrg
270706f2543Smrgstatic Bool
271706f2543SmrgwinInitScreenPrimaryDD(ScreenPtr pScreen)
272706f2543Smrg{
273706f2543Smrg  return winAllocateFBPrimaryDD(pScreen);
274706f2543Smrg}
275706f2543Smrg
276706f2543Smrg/*
277706f2543Smrg * Call the wrapped CloseScreen function.
278706f2543Smrg *
279706f2543Smrg * Free our resources and private structures.
280706f2543Smrg */
281706f2543Smrg
282706f2543Smrgstatic Bool
283706f2543SmrgwinCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen)
284706f2543Smrg{
285706f2543Smrg  winScreenPriv(pScreen);
286706f2543Smrg  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
287706f2543Smrg  Bool			fReturn;
288706f2543Smrg
289706f2543Smrg  ErrorF ("winCloseScreenPrimaryDD - Freeing screen resources\n");
290706f2543Smrg
291706f2543Smrg  /* Flag that the screen is closed */
292706f2543Smrg  pScreenPriv->fClosed = TRUE;
293706f2543Smrg  pScreenPriv->fActive = FALSE;
294706f2543Smrg
295706f2543Smrg  /* Call the wrapped CloseScreen procedure */
296706f2543Smrg  WIN_UNWRAP(CloseScreen);
297706f2543Smrg  fReturn = (*pScreen->CloseScreen) (nIndex, pScreen);
298706f2543Smrg
299706f2543Smrg  /* Delete the window property */
300706f2543Smrg  RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP);
301706f2543Smrg
302706f2543Smrg  winFreeFBPrimaryDD(pScreen);
303706f2543Smrg
304706f2543Smrg  /* Delete tray icon, if we have one */
305706f2543Smrg  if (!pScreenInfo->fNoTrayIcon)
306706f2543Smrg    winDeleteNotifyIcon (pScreenPriv);
307706f2543Smrg
308706f2543Smrg  /* Free the exit confirmation dialog box, if it exists */
309706f2543Smrg  if (g_hDlgExit != NULL)
310706f2543Smrg    {
311706f2543Smrg      DestroyWindow (g_hDlgExit);
312706f2543Smrg      g_hDlgExit = NULL;
313706f2543Smrg    }
314706f2543Smrg
315706f2543Smrg  /* Kill our window */
316706f2543Smrg  if (pScreenPriv->hwndScreen)
317706f2543Smrg    {
318706f2543Smrg      DestroyWindow (pScreenPriv->hwndScreen);
319706f2543Smrg      pScreenPriv->hwndScreen = NULL;
320706f2543Smrg    }
321706f2543Smrg
322706f2543Smrg  /* Kill our screeninfo's pointer to the screen */
323706f2543Smrg  pScreenInfo->pScreen = NULL;
324706f2543Smrg
325706f2543Smrg  /* Free the screen privates for this screen */
326706f2543Smrg  free ((pointer) pScreenPriv);
327706f2543Smrg
328706f2543Smrg  return fReturn;
329706f2543Smrg}
330706f2543Smrg
331706f2543Smrg
332706f2543Smrg/*
333706f2543Smrg * Tell mi what sort of visuals we need.
334706f2543Smrg *
335706f2543Smrg * Generally we only need one visual, as our screen can only
336706f2543Smrg * handle one format at a time, I believe.  You may want
337706f2543Smrg * to verify that last sentence.
338706f2543Smrg */
339706f2543Smrg
340706f2543Smrgstatic Bool
341706f2543SmrgwinInitVisualsPrimaryDD (ScreenPtr pScreen)
342706f2543Smrg{
343706f2543Smrg  winScreenPriv(pScreen);
344706f2543Smrg  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
345706f2543Smrg  DWORD			dwRedBits, dwGreenBits, dwBlueBits;
346706f2543Smrg
347706f2543Smrg  /* Count the number of ones in each color mask */
348706f2543Smrg  dwRedBits = winCountBits (pScreenPriv->dwRedMask);
349706f2543Smrg  dwGreenBits = winCountBits (pScreenPriv->dwGreenMask);
350706f2543Smrg  dwBlueBits = winCountBits (pScreenPriv->dwBlueMask);
351706f2543Smrg
352706f2543Smrg  /* Store the maximum number of ones in a color mask as the bitsPerRGB */
353706f2543Smrg  if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits)
354706f2543Smrg    pScreenPriv->dwBitsPerRGB = dwRedBits;
355706f2543Smrg  else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits)
356706f2543Smrg    pScreenPriv->dwBitsPerRGB = dwGreenBits;
357706f2543Smrg  else
358706f2543Smrg    pScreenPriv->dwBitsPerRGB = dwBlueBits;
359706f2543Smrg
360706f2543Smrg  ErrorF ("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n",
361706f2543Smrg	  (unsigned int) pScreenPriv->dwRedMask,
362706f2543Smrg	  (unsigned int) pScreenPriv->dwGreenMask,
363706f2543Smrg	  (unsigned int) pScreenPriv->dwBlueMask,
364706f2543Smrg	  (int) pScreenPriv->dwBitsPerRGB);
365706f2543Smrg
366706f2543Smrg  /* Create a single visual according to the Windows screen depth */
367706f2543Smrg  switch (pScreenInfo->dwDepth)
368706f2543Smrg    {
369706f2543Smrg    case 24:
370706f2543Smrg    case 16:
371706f2543Smrg    case 15:
372706f2543Smrg      if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
373706f2543Smrg				     TrueColorMask,
374706f2543Smrg				     pScreenPriv->dwBitsPerRGB,
375706f2543Smrg				     TrueColor,
376706f2543Smrg				     pScreenPriv->dwRedMask,
377706f2543Smrg				     pScreenPriv->dwGreenMask,
378706f2543Smrg				     pScreenPriv->dwBlueMask))
379706f2543Smrg	{
380706f2543Smrg	  ErrorF ("winInitVisualsPrimaryDD - "
381706f2543Smrg		  "miSetVisualTypesAndMasks failed\n");
382706f2543Smrg	  return FALSE;
383706f2543Smrg	}
384706f2543Smrg      break;
385706f2543Smrg
386706f2543Smrg    case 8:
387706f2543Smrg#if CYGDEBUG
388706f2543Smrg      winDebug ("winInitVisuals - Calling miSetVisualTypesAndMasks\n");
389706f2543Smrg#endif /* CYGDEBUG */
390706f2543Smrg      if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth,
391706f2543Smrg				     PseudoColorMask,
392706f2543Smrg				     pScreenPriv->dwBitsPerRGB,
393706f2543Smrg				     PseudoColor,
394706f2543Smrg				     pScreenPriv->dwRedMask,
395706f2543Smrg				     pScreenPriv->dwGreenMask,
396706f2543Smrg				     pScreenPriv->dwBlueMask))
397706f2543Smrg	{
398706f2543Smrg	  ErrorF ("winInitVisualsPrimaryDD - "
399706f2543Smrg		  "miSetVisualTypesAndMasks failed\n");
400706f2543Smrg	  return FALSE;
401706f2543Smrg	}
402706f2543Smrg#if CYGDEBUG
403706f2543Smrg      winDebug ("winInitVisualsPrimaryDD - Returned from "
404706f2543Smrg	      "miSetVisualTypesAndMasks\n");
405706f2543Smrg#endif /* CYGDEBUG */
406706f2543Smrg      break;
407706f2543Smrg
408706f2543Smrg    default:
409706f2543Smrg      ErrorF ("winInitVisualsPrimaryDD - Unknown screen depth\n");
410706f2543Smrg      return FALSE;
411706f2543Smrg    }
412706f2543Smrg
413706f2543Smrg  ErrorF ("winInitVisualsPrimaryDD - Returning\n");
414706f2543Smrg
415706f2543Smrg  return TRUE;
416706f2543Smrg}
417706f2543Smrg
418706f2543Smrg
419706f2543Smrgstatic Bool
420706f2543SmrgwinAdjustVideoModePrimaryDD (ScreenPtr pScreen)
421706f2543Smrg{
422706f2543Smrg  winScreenPriv(pScreen);
423706f2543Smrg  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
424706f2543Smrg  HDC			hdc = NULL;
425706f2543Smrg  DWORD			dwBPP;
426706f2543Smrg
427706f2543Smrg  /* We're in serious trouble if we can't get a DC */
428706f2543Smrg  hdc = GetDC (NULL);
429706f2543Smrg  if (hdc == NULL)
430706f2543Smrg    {
431706f2543Smrg      ErrorF ("winAdjustVideoModePrimaryDD - GetDC failed\n");
432706f2543Smrg      return FALSE;
433706f2543Smrg    }
434706f2543Smrg
435706f2543Smrg  /* Query GDI for current display depth */
436706f2543Smrg  dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
437706f2543Smrg
438706f2543Smrg  /* DirectDraw can only change the depth in fullscreen mode */
439706f2543Smrg  if (!(pScreenInfo->fFullScreen &&
440706f2543Smrg        (pScreenInfo->dwBPP != WIN_DEFAULT_BPP)))
441706f2543Smrg    {
442706f2543Smrg      /* Otherwise, We'll use GDI's depth */
443706f2543Smrg      pScreenInfo->dwBPP = dwBPP;
444706f2543Smrg    }
445706f2543Smrg
446706f2543Smrg  /* Release our DC */
447706f2543Smrg  ReleaseDC (NULL, hdc);
448706f2543Smrg
449706f2543Smrg  return TRUE;
450706f2543Smrg}
451706f2543Smrg
452706f2543Smrg
453706f2543Smrg/*
454706f2543Smrg * We need to blit our offscreen fb to
455706f2543Smrg * the screen when we are activated, and we need to point
456706f2543Smrg * the fb code back to the primary surface memory.
457706f2543Smrg */
458706f2543Smrg
459706f2543Smrgstatic Bool
460706f2543SmrgwinActivateAppPrimaryDD (ScreenPtr pScreen)
461706f2543Smrg{
462706f2543Smrg  winScreenPriv(pScreen);
463706f2543Smrg  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
464706f2543Smrg  RECT			rcSrc, rcClient;
465706f2543Smrg  HRESULT		ddrval = DD_OK;
466706f2543Smrg
467706f2543Smrg  /* Check for errors */
468706f2543Smrg  if (pScreenPriv == NULL
469706f2543Smrg      || pScreenPriv->pddsPrimary == NULL
470706f2543Smrg      || pScreenPriv->pddsOffscreen == NULL)
471706f2543Smrg    return FALSE;
472706f2543Smrg
473706f2543Smrg  /* Check for do-nothing */
474706f2543Smrg  if (!pScreenPriv->fActive)
475706f2543Smrg    return TRUE;
476706f2543Smrg
477706f2543Smrg  /* We are activating */
478706f2543Smrg  ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsOffscreen);
479706f2543Smrg  if (ddrval == DD_OK)
480706f2543Smrg    {
481706f2543Smrg      IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen,
482706f2543Smrg				  NULL);
483706f2543Smrg      /*
484706f2543Smrg       * We don't check for an error from Unlock, because it
485706f2543Smrg       * doesn't matter if the Unlock failed.
486706f2543Smrg       */
487706f2543Smrg    }
488706f2543Smrg
489706f2543Smrg  /* Restore both surfaces, just cause I like it that way */
490706f2543Smrg  IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
491706f2543Smrg  IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
492706f2543Smrg
493706f2543Smrg  /* Get client area in screen coords */
494706f2543Smrg  GetClientRect (pScreenPriv->hwndScreen, &rcClient);
495706f2543Smrg  MapWindowPoints (pScreenPriv->hwndScreen,
496706f2543Smrg		   HWND_DESKTOP,
497706f2543Smrg		   (LPPOINT)&rcClient, 2);
498706f2543Smrg
499706f2543Smrg  /* Setup a source rectangle */
500706f2543Smrg  rcSrc.left = 0;
501706f2543Smrg  rcSrc.top = 0;
502706f2543Smrg  rcSrc.right = pScreenInfo->dwWidth;
503706f2543Smrg  rcSrc.bottom = pScreenInfo->dwHeight;
504706f2543Smrg
505706f2543Smrg  ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
506706f2543Smrg				    &rcClient,
507706f2543Smrg				    pScreenPriv->pddsOffscreen,
508706f2543Smrg				    &rcSrc,
509706f2543Smrg				    DDBLT_WAIT,
510706f2543Smrg				    NULL);
511706f2543Smrg  if (ddrval != DD_OK)
512706f2543Smrg    FatalError ("winActivateAppPrimaryDD () - Failed blitting offscreen "
513706f2543Smrg		"surface to primary surface %08x\n", (unsigned int) ddrval);
514706f2543Smrg
515706f2543Smrg  /* Lock the primary surface */
516706f2543Smrg  ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary,
517706f2543Smrg				     &rcClient,
518706f2543Smrg				     pScreenPriv->pddsdPrimary,
519706f2543Smrg				     DDLOCK_WAIT,
520706f2543Smrg				     NULL);
521706f2543Smrg  if (ddrval != DD_OK
522706f2543Smrg      || pScreenPriv->pddsdPrimary->lpSurface == NULL)
523706f2543Smrg    FatalError ("winActivateAppPrimaryDD () - Could not lock "
524706f2543Smrg		"primary surface\n");
525706f2543Smrg
526706f2543Smrg  /* Notify FB of the new memory pointer */
527706f2543Smrg  winUpdateFBPointer (pScreen,
528706f2543Smrg		      pScreenPriv->pddsdPrimary->lpSurface);
529706f2543Smrg
530706f2543Smrg  /*
531706f2543Smrg   * Register the Alt-Tab combo as a hotkey so we can copy
532706f2543Smrg   * the primary framebuffer before the display mode changes
533706f2543Smrg   */
534706f2543Smrg  RegisterHotKey (pScreenPriv->hwndScreen, 1, MOD_ALT, 9);
535706f2543Smrg
536706f2543Smrg  return TRUE;
537706f2543Smrg}
538706f2543Smrg
539706f2543Smrg
540706f2543Smrg/*
541706f2543Smrg * Handle the Alt+Tab hotkey.
542706f2543Smrg *
543706f2543Smrg * We need to save the primary fb to an offscreen fb when
544706f2543Smrg * we get deactivated, and point the fb code at the offscreen
545706f2543Smrg * fb for the duration of the deactivation.
546706f2543Smrg */
547706f2543Smrg
548706f2543Smrgstatic Bool
549706f2543SmrgwinHotKeyAltTabPrimaryDD (ScreenPtr pScreen)
550706f2543Smrg{
551706f2543Smrg  winScreenPriv(pScreen);
552706f2543Smrg  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
553706f2543Smrg  RECT			rcClient, rcSrc;
554706f2543Smrg  HRESULT		ddrval = DD_OK;
555706f2543Smrg
556706f2543Smrg  ErrorF ("\nwinHotKeyAltTabPrimaryDD\n\n");
557706f2543Smrg
558706f2543Smrg  /* Alt+Tab was pressed, we will lose focus very soon */
559706f2543Smrg  pScreenPriv->fActive = FALSE;
560706f2543Smrg
561706f2543Smrg  /* Check for error conditions */
562706f2543Smrg  if (pScreenPriv->pddsPrimary == NULL
563706f2543Smrg      || pScreenPriv->pddsOffscreen == NULL)
564706f2543Smrg    return FALSE;
565706f2543Smrg
566706f2543Smrg  /* Get client area in screen coords */
567706f2543Smrg  GetClientRect (pScreenPriv->hwndScreen, &rcClient);
568706f2543Smrg  MapWindowPoints (pScreenPriv->hwndScreen,
569706f2543Smrg		   HWND_DESKTOP,
570706f2543Smrg		   (LPPOINT)&rcClient, 2);
571706f2543Smrg
572706f2543Smrg  /* Did we loose the primary surface? */
573706f2543Smrg  ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsPrimary);
574706f2543Smrg  if (ddrval == DD_OK)
575706f2543Smrg    {
576706f2543Smrg      ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary,
577706f2543Smrg					   NULL);
578706f2543Smrg      if (FAILED (ddrval))
579706f2543Smrg	FatalError ("winHotKeyAltTabPrimaryDD - Failed unlocking primary "
580706f2543Smrg		    "surface\n");
581706f2543Smrg    }
582706f2543Smrg
583706f2543Smrg  /* Setup a source rectangle */
584706f2543Smrg  rcSrc.left = 0;
585706f2543Smrg  rcSrc.top = 0;
586706f2543Smrg  rcSrc.right = pScreenInfo->dwWidth;
587706f2543Smrg  rcSrc.bottom = pScreenInfo->dwHeight;
588706f2543Smrg
589706f2543Smrg      /* Blit the primary surface to the offscreen surface */
590706f2543Smrg  ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
591706f2543Smrg				    NULL, /* should be rcDest */
592706f2543Smrg				    pScreenPriv->pddsPrimary,
593706f2543Smrg				    NULL,
594706f2543Smrg				    DDBLT_WAIT,
595706f2543Smrg				    NULL);
596706f2543Smrg  if (ddrval == DDERR_SURFACELOST)
597706f2543Smrg    {
598706f2543Smrg      IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen);
599706f2543Smrg      IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary);
600706f2543Smrg
601706f2543Smrg      /* Blit the primary surface to the offscreen surface */
602706f2543Smrg      ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen,
603706f2543Smrg					NULL,
604706f2543Smrg					pScreenPriv->pddsPrimary,
605706f2543Smrg					NULL,
606706f2543Smrg					DDBLT_WAIT,
607706f2543Smrg					NULL);
608706f2543Smrg      if (FAILED (ddrval))
609706f2543Smrg	FatalError ("winHotKeyAltTabPrimaryDD - Failed blitting primary "
610706f2543Smrg		    "surface to offscreen surface: %08x\n",
611706f2543Smrg		    (unsigned int) ddrval);
612706f2543Smrg    }
613706f2543Smrg  else
614706f2543Smrg    {
615706f2543Smrg      FatalError ("winHotKeyAltTabPrimaryDD - Unknown error from "
616706f2543Smrg		  "Blt: %08dx\n", (unsigned int) ddrval);
617706f2543Smrg    }
618706f2543Smrg
619706f2543Smrg  /* Lock the offscreen surface */
620706f2543Smrg  ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsOffscreen,
621706f2543Smrg				     NULL,
622706f2543Smrg				     pScreenPriv->pddsdOffscreen,
623706f2543Smrg				     DDLOCK_WAIT,
624706f2543Smrg				     NULL);
625706f2543Smrg  if (ddrval != DD_OK
626706f2543Smrg      || pScreenPriv->pddsdPrimary->lpSurface == NULL)
627706f2543Smrg    FatalError ("winHotKeyAltTabPrimaryDD - Could not lock "
628706f2543Smrg		"offscreen surface\n");
629706f2543Smrg
630706f2543Smrg  /* Notify FB of the new memory pointer */
631706f2543Smrg  winUpdateFBPointer (pScreen,
632706f2543Smrg		      pScreenPriv->pddsdOffscreen->lpSurface);
633706f2543Smrg
634706f2543Smrg  /* Unregister our hotkey */
635706f2543Smrg  UnregisterHotKey (pScreenPriv->hwndScreen, 1);
636706f2543Smrg
637706f2543Smrg  return TRUE;
638706f2543Smrg}
639706f2543Smrg
640706f2543Smrg
641706f2543Smrg/* Set engine specific functions */
642706f2543SmrgBool
643706f2543SmrgwinSetEngineFunctionsPrimaryDD (ScreenPtr pScreen)
644706f2543Smrg{
645706f2543Smrg  winScreenPriv(pScreen);
646706f2543Smrg  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
647706f2543Smrg
648706f2543Smrg  /* Set our pointers */
649706f2543Smrg  pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD;
650706f2543Smrg  pScreenPriv->pwinFreeFB = winFreeFBPrimaryDD;
651706f2543Smrg  pScreenPriv->pwinShadowUpdate = (winShadowUpdateProcPtr) (void (*)(void))NoopDDA;
652706f2543Smrg  pScreenPriv->pwinInitScreen = winInitScreenPrimaryDD;
653706f2543Smrg  pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD;
654706f2543Smrg  pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD;
655706f2543Smrg  pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD;
656706f2543Smrg  if (pScreenInfo->fFullScreen)
657706f2543Smrg    pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen;
658706f2543Smrg  else
659706f2543Smrg    pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed;
660706f2543Smrg  pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB;
661706f2543Smrg  pScreenPriv->pwinBltExposedRegions = (winBltExposedRegionsProcPtr) (void (*)(void))NoopDDA;
662706f2543Smrg  pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD;
663706f2543Smrg  pScreenPriv->pwinRedrawScreen = NULL;
664706f2543Smrg  pScreenPriv->pwinRealizeInstalledPalette = NULL;
665706f2543Smrg  pScreenPriv->pwinInstallColormap = NULL;
666706f2543Smrg  pScreenPriv->pwinStoreColors = NULL;
667706f2543Smrg  pScreenPriv->pwinCreateColormap = NULL;
668706f2543Smrg  pScreenPriv->pwinDestroyColormap = NULL;
669706f2543Smrg  pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD;
670706f2543Smrg  pScreenPriv->pwinCreatePrimarySurface = (winCreatePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
671706f2543Smrg  pScreenPriv->pwinReleasePrimarySurface = (winReleasePrimarySurfaceProcPtr) (void (*)(void))NoopDDA;
672706f2543Smrg#ifdef XWIN_MULTIWINDOW
673706f2543Smrg  pScreenPriv->pwinFinishCreateWindowsWindow =
674706f2543Smrg    (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA;
675706f2543Smrg#endif
676706f2543Smrg
677706f2543Smrg  return TRUE;
678706f2543Smrg}
679