winengine.c revision 6747b715
1/*
2 *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
3 *
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 *Except as contained in this notice, the name of Harold L Hunt II
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from Harold L Hunt II.
27 *
28 * Authors:	Harold L Hunt II
29 */
30
31#ifdef HAVE_XWIN_CONFIG_H
32#include <xwin-config.h>
33#endif
34#include "win.h"
35#include "winmsg.h"
36
37
38/*
39 * External global variables
40 */
41
42extern const GUID _IID_IDirectDraw4;
43
44
45/*
46 * Detect engines supported by current Windows version
47 * DirectDraw version and hardware
48 */
49
50void
51winDetectSupportedEngines (void)
52{
53  OSVERSIONINFO		osvi;
54
55  /* Initialize the engine support flags */
56  g_dwEnginesSupported = WIN_SERVER_SHADOW_GDI;
57
58#ifdef XWIN_NATIVEGDI
59  g_dwEnginesSupported |= WIN_SERVER_NATIVE_GDI;
60#endif
61
62  /* Get operating system version information */
63  ZeroMemory (&osvi, sizeof (osvi));
64  osvi.dwOSVersionInfoSize = sizeof (osvi);
65  GetVersionEx (&osvi);
66
67  /* Branch on platform ID */
68  switch (osvi.dwPlatformId)
69    {
70    case VER_PLATFORM_WIN32_NT:
71      /* Engine 4 is supported on NT only */
72      winErrorFVerb (2, "winDetectSupportedEngines - Windows NT/2000/XP\n");
73      break;
74
75    case VER_PLATFORM_WIN32_WINDOWS:
76      /* Engine 4 is supported on NT only */
77      winErrorFVerb (2, "winDetectSupportedEngines - Windows 95/98/Me\n");
78      break;
79    }
80
81  /* Do we have DirectDraw? */
82  if (g_hmodDirectDraw != NULL)
83    {
84      LPDIRECTDRAW	lpdd = NULL;
85      LPDIRECTDRAW4	lpdd4 = NULL;
86      HRESULT		ddrval;
87
88      /* Was the DirectDrawCreate function found? */
89      if (g_fpDirectDrawCreate == NULL)
90	{
91	  /* No DirectDraw support */
92	  return;
93	}
94
95      /* DirectDrawCreate exists, try to call it */
96      /* Create a DirectDraw object, store the address at lpdd */
97      ddrval = (*g_fpDirectDrawCreate) (NULL,
98					(void**) &lpdd,
99					NULL);
100      if (FAILED (ddrval))
101	{
102	  /* No DirectDraw support */
103	  winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw not installed\n");
104	  return;
105	}
106      else
107	{
108	  /* We have DirectDraw */
109	  winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw installed\n");
110	  g_dwEnginesSupported |= WIN_SERVER_SHADOW_DD;
111
112#ifdef XWIN_PRIMARYFB
113	  /* Allow PrimaryDD engine if NT */
114	  if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
115	    {
116	      g_dwEnginesSupported |= WIN_SERVER_PRIMARY_DD;
117	      winErrorFVerb (2, "winDetectSupportedEngines - Allowing PrimaryDD\n");
118	    }
119#endif
120	}
121
122      /* Try to query for DirectDraw4 interface */
123      ddrval = IDirectDraw_QueryInterface (lpdd,
124					   &IID_IDirectDraw4,
125					   (LPVOID*) &lpdd4);
126      if (SUCCEEDED (ddrval))
127	{
128	  /* We have DirectDraw4 */
129	  winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw4 installed\n");
130	  g_dwEnginesSupported |= WIN_SERVER_SHADOW_DDNL;
131	}
132
133      /* Cleanup DirectDraw interfaces */
134      if (lpdd4 != NULL)
135	IDirectDraw_Release (lpdd4);
136      if (lpdd != NULL)
137	IDirectDraw_Release (lpdd);
138    }
139
140  winErrorFVerb (2, "winDetectSupportedEngines - Returning, supported engines %08x\n",
141	  (unsigned int) g_dwEnginesSupported);
142}
143
144
145/*
146 * Set the engine type, depending on the engines
147 * supported for this screen, and whether the user
148 * suggested an engine type
149 */
150
151Bool
152winSetEngine (ScreenPtr pScreen)
153{
154  winScreenPriv(pScreen);
155  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
156  HDC			hdc;
157  DWORD			dwBPP;
158
159  /* Get a DC */
160  hdc = GetDC (NULL);
161  if (hdc == NULL)
162    {
163      ErrorF ("winSetEngine - Couldn't get an HDC\n");
164      return FALSE;
165    }
166
167  /*
168   * pScreenInfo->dwBPP may be 0 to indicate that the current screen
169   * depth is to be used.  Thus, we must query for the current display
170   * depth here.
171   */
172  dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
173
174  /* Release the DC */
175  ReleaseDC (NULL, hdc);
176  hdc = NULL;
177
178  /* ShadowGDI is the only engine that supports windowed PseudoColor */
179  if (dwBPP == 8 && !pScreenInfo->fFullScreen)
180    {
181      winErrorFVerb (2, "winSetEngine - Windowed && PseudoColor => ShadowGDI\n");
182      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
183
184      /* Set engine function pointers */
185      winSetEngineFunctionsShadowGDI (pScreen);
186      return TRUE;
187    }
188
189  /* ShadowGDI is the only engine that supports Multi Window Mode */
190  if (
191#ifdef XWIN_MULTIWINDOWEXTWM
192      pScreenInfo->fMWExtWM
193#else
194      FALSE
195#endif
196#ifdef XWIN_MULTIWINDOW
197      || pScreenInfo->fMultiWindow
198#else
199      || FALSE
200#endif
201      )
202    {
203      winErrorFVerb (2, "winSetEngine - Multi Window or Rootless => ShadowGDI\n");
204      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
205
206      /* Set engine function pointers */
207      winSetEngineFunctionsShadowGDI (pScreen);
208      return TRUE;
209    }
210
211  /* If the user's choice is supported, we'll use that */
212  if (g_dwEnginesSupported & pScreenInfo->dwEnginePreferred)
213    {
214      winErrorFVerb (2, "winSetEngine - Using user's preference: %d\n",
215	      (int) pScreenInfo->dwEnginePreferred);
216      pScreenInfo->dwEngine = pScreenInfo->dwEnginePreferred;
217
218      /* Setup engine function pointers */
219      switch (pScreenInfo->dwEngine)
220	{
221	case WIN_SERVER_SHADOW_GDI:
222	  winSetEngineFunctionsShadowGDI (pScreen);
223	  break;
224	case WIN_SERVER_SHADOW_DD:
225	  winSetEngineFunctionsShadowDD (pScreen);
226	  break;
227	case WIN_SERVER_SHADOW_DDNL:
228	  winSetEngineFunctionsShadowDDNL (pScreen);
229	  break;
230#ifdef XWIN_PRIMARYFB
231	case WIN_SERVER_PRIMARY_DD:
232	  winSetEngineFunctionsPrimaryDD (pScreen);
233	  break;
234#endif
235#ifdef XWIN_NATIVEGDI
236	case WIN_SERVER_NATIVE_GDI:
237	  winSetEngineFunctionsNativeGDI (pScreen);
238	  break;
239#endif
240	default:
241	  FatalError ("winSetEngine - Invalid engine type\n");
242	}
243      return TRUE;
244    }
245
246  /* ShadowDDNL has good performance, so why not */
247  if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DDNL)
248    {
249      winErrorFVerb (2, "winSetEngine - Using Shadow DirectDraw NonLocking\n");
250      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DDNL;
251
252      /* Set engine function pointers */
253      winSetEngineFunctionsShadowDDNL (pScreen);
254      return TRUE;
255    }
256
257  /* ShadowDD is next in line */
258  if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DD)
259    {
260      winErrorFVerb (2, "winSetEngine - Using Shadow DirectDraw\n");
261      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DD;
262
263      /* Set engine function pointers */
264      winSetEngineFunctionsShadowDD (pScreen);
265      return TRUE;
266    }
267
268  /* ShadowGDI is next in line */
269  if (g_dwEnginesSupported & WIN_SERVER_SHADOW_GDI)
270    {
271      winErrorFVerb (2, "winSetEngine - Using Shadow GDI DIB\n");
272      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
273
274      /* Set engine function pointers */
275      winSetEngineFunctionsShadowGDI (pScreen);
276      return TRUE;
277    }
278
279  return TRUE;
280}
281
282
283/*
284 * Get procedure addresses for DirectDrawCreate and DirectDrawCreateClipper
285 */
286
287Bool
288winGetDDProcAddresses (void)
289{
290  Bool			fReturn = TRUE;
291
292  /* Load the DirectDraw library */
293  g_hmodDirectDraw = LoadLibraryEx ("ddraw.dll", NULL, 0);
294  if (g_hmodDirectDraw == NULL)
295    {
296      ErrorF ("winGetDDProcAddresses - Could not load ddraw.dll\n");
297      fReturn = TRUE;
298      goto winGetDDProcAddresses_Exit;
299    }
300
301  /* Try to get the DirectDrawCreate address */
302  g_fpDirectDrawCreate = GetProcAddress (g_hmodDirectDraw,
303					 "DirectDrawCreate");
304  if (g_fpDirectDrawCreate == NULL)
305    {
306      ErrorF ("winGetDDProcAddresses - Could not get DirectDrawCreate "
307	      "address\n");
308      fReturn = TRUE;
309      goto winGetDDProcAddresses_Exit;
310    }
311
312  /* Try to get the DirectDrawCreateClipper address */
313  g_fpDirectDrawCreateClipper = GetProcAddress (g_hmodDirectDraw,
314						"DirectDrawCreateClipper");
315  if (g_fpDirectDrawCreateClipper == NULL)
316    {
317      ErrorF ("winGetDDProcAddresses - Could not get "
318	      "DirectDrawCreateClipper address\n");
319      fReturn = FALSE;
320      goto winGetDDProcAddresses_Exit;
321    }
322
323  /*
324   * Note: Do not unload ddraw.dll here.  Do it in GiveUp
325   */
326
327 winGetDDProcAddresses_Exit:
328  /* Unload the DirectDraw library if we failed to initialize */
329  if (!fReturn && g_hmodDirectDraw != NULL)
330    {
331      FreeLibrary (g_hmodDirectDraw);
332      g_hmodDirectDraw = NULL;
333    }
334
335  return fReturn;
336}
337