winengine.c revision 9ace9065
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 * Global variables for function pointers into
39 * dynamically loaded libraries
40 */
41FARPROC		g_fpDirectDrawCreate = NULL;
42FARPROC		g_fpDirectDrawCreateClipper = NULL;
43
44/*
45  module handle for dynamically loaded directdraw library
46*/
47static HMODULE g_hmodDirectDraw = NULL;
48
49/*
50 * Detect engines supported by current Windows version
51 * DirectDraw version and hardware
52 */
53
54void
55winDetectSupportedEngines (void)
56{
57  OSVERSIONINFO		osvi;
58
59  /* Initialize the engine support flags */
60  g_dwEnginesSupported = WIN_SERVER_SHADOW_GDI;
61
62#ifdef XWIN_NATIVEGDI
63  g_dwEnginesSupported |= WIN_SERVER_NATIVE_GDI;
64#endif
65
66  /* Get operating system version information */
67  ZeroMemory (&osvi, sizeof (osvi));
68  osvi.dwOSVersionInfoSize = sizeof (osvi);
69  GetVersionEx (&osvi);
70
71  /* Branch on platform ID */
72  switch (osvi.dwPlatformId)
73    {
74    case VER_PLATFORM_WIN32_NT:
75      /* Engine 4 is supported on NT only */
76      winErrorFVerb (2, "winDetectSupportedEngines - Windows NT/2000/XP\n");
77      break;
78
79    case VER_PLATFORM_WIN32_WINDOWS:
80      /* Engine 4 is supported on NT only */
81      winErrorFVerb (2, "winDetectSupportedEngines - Windows 95/98/Me\n");
82      break;
83    }
84
85  /* Do we have DirectDraw? */
86  if (g_hmodDirectDraw != NULL)
87    {
88      LPDIRECTDRAW	lpdd = NULL;
89      LPDIRECTDRAW4	lpdd4 = NULL;
90      HRESULT		ddrval;
91
92      /* Was the DirectDrawCreate function found? */
93      if (g_fpDirectDrawCreate == NULL)
94	{
95	  /* No DirectDraw support */
96	  return;
97	}
98
99      /* DirectDrawCreate exists, try to call it */
100      /* Create a DirectDraw object, store the address at lpdd */
101      ddrval = (*g_fpDirectDrawCreate) (NULL,
102					(void**) &lpdd,
103					NULL);
104      if (FAILED (ddrval))
105	{
106	  /* No DirectDraw support */
107	  winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw not installed\n");
108	  return;
109	}
110      else
111	{
112	  /* We have DirectDraw */
113	  winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw installed\n");
114	  g_dwEnginesSupported |= WIN_SERVER_SHADOW_DD;
115
116#ifdef XWIN_PRIMARYFB
117	  /* Allow PrimaryDD engine if NT */
118	  if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
119	    {
120	      g_dwEnginesSupported |= WIN_SERVER_PRIMARY_DD;
121	      winErrorFVerb (2, "winDetectSupportedEngines - Allowing PrimaryDD\n");
122	    }
123#endif
124	}
125
126      /* Try to query for DirectDraw4 interface */
127      ddrval = IDirectDraw_QueryInterface (lpdd,
128					   &IID_IDirectDraw4,
129					   (LPVOID*) &lpdd4);
130      if (SUCCEEDED (ddrval))
131	{
132	  /* We have DirectDraw4 */
133	  winErrorFVerb (2, "winDetectSupportedEngines - DirectDraw4 installed\n");
134	  g_dwEnginesSupported |= WIN_SERVER_SHADOW_DDNL;
135	}
136
137      /* Cleanup DirectDraw interfaces */
138      if (lpdd4 != NULL)
139	IDirectDraw_Release (lpdd4);
140      if (lpdd != NULL)
141	IDirectDraw_Release (lpdd);
142    }
143
144  winErrorFVerb (2, "winDetectSupportedEngines - Returning, supported engines %08x\n",
145	  (unsigned int) g_dwEnginesSupported);
146}
147
148
149/*
150 * Set the engine type, depending on the engines
151 * supported for this screen, and whether the user
152 * suggested an engine type
153 */
154
155Bool
156winSetEngine (ScreenPtr pScreen)
157{
158  winScreenPriv(pScreen);
159  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
160  HDC			hdc;
161  DWORD			dwBPP;
162
163  /* Get a DC */
164  hdc = GetDC (NULL);
165  if (hdc == NULL)
166    {
167      ErrorF ("winSetEngine - Couldn't get an HDC\n");
168      return FALSE;
169    }
170
171  /*
172   * pScreenInfo->dwBPP may be 0 to indicate that the current screen
173   * depth is to be used.  Thus, we must query for the current display
174   * depth here.
175   */
176  dwBPP = GetDeviceCaps (hdc, BITSPIXEL);
177
178  /* Release the DC */
179  ReleaseDC (NULL, hdc);
180  hdc = NULL;
181
182  /* ShadowGDI is the only engine that supports windowed PseudoColor */
183  if (dwBPP == 8 && !pScreenInfo->fFullScreen)
184    {
185      winErrorFVerb (2, "winSetEngine - Windowed && PseudoColor => ShadowGDI\n");
186      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
187
188      /* Set engine function pointers */
189      winSetEngineFunctionsShadowGDI (pScreen);
190      return TRUE;
191    }
192
193  /* ShadowGDI is the only engine that supports Multi Window Mode */
194  if (
195#ifdef XWIN_MULTIWINDOWEXTWM
196      pScreenInfo->fMWExtWM
197#else
198      FALSE
199#endif
200#ifdef XWIN_MULTIWINDOW
201      || pScreenInfo->fMultiWindow
202#else
203      || FALSE
204#endif
205      )
206    {
207      winErrorFVerb (2, "winSetEngine - Multi Window or Rootless => ShadowGDI\n");
208      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
209
210      /* Set engine function pointers */
211      winSetEngineFunctionsShadowGDI (pScreen);
212      return TRUE;
213    }
214
215  /* If the user's choice is supported, we'll use that */
216  if (g_dwEnginesSupported & pScreenInfo->dwEnginePreferred)
217    {
218      winErrorFVerb (2, "winSetEngine - Using user's preference: %d\n",
219	      (int) pScreenInfo->dwEnginePreferred);
220      pScreenInfo->dwEngine = pScreenInfo->dwEnginePreferred;
221
222      /* Setup engine function pointers */
223      switch (pScreenInfo->dwEngine)
224	{
225	case WIN_SERVER_SHADOW_GDI:
226	  winSetEngineFunctionsShadowGDI (pScreen);
227	  break;
228	case WIN_SERVER_SHADOW_DD:
229	  winSetEngineFunctionsShadowDD (pScreen);
230	  break;
231	case WIN_SERVER_SHADOW_DDNL:
232	  winSetEngineFunctionsShadowDDNL (pScreen);
233	  break;
234#ifdef XWIN_PRIMARYFB
235	case WIN_SERVER_PRIMARY_DD:
236	  winSetEngineFunctionsPrimaryDD (pScreen);
237	  break;
238#endif
239#ifdef XWIN_NATIVEGDI
240	case WIN_SERVER_NATIVE_GDI:
241	  winSetEngineFunctionsNativeGDI (pScreen);
242	  break;
243#endif
244	default:
245	  FatalError ("winSetEngine - Invalid engine type\n");
246	}
247      return TRUE;
248    }
249
250  /* ShadowDDNL has good performance, so why not */
251  if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DDNL)
252    {
253      winErrorFVerb (2, "winSetEngine - Using Shadow DirectDraw NonLocking\n");
254      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DDNL;
255
256      /* Set engine function pointers */
257      winSetEngineFunctionsShadowDDNL (pScreen);
258      return TRUE;
259    }
260
261  /* ShadowDD is next in line */
262  if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DD)
263    {
264      winErrorFVerb (2, "winSetEngine - Using Shadow DirectDraw\n");
265      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DD;
266
267      /* Set engine function pointers */
268      winSetEngineFunctionsShadowDD (pScreen);
269      return TRUE;
270    }
271
272  /* ShadowGDI is next in line */
273  if (g_dwEnginesSupported & WIN_SERVER_SHADOW_GDI)
274    {
275      winErrorFVerb (2, "winSetEngine - Using Shadow GDI DIB\n");
276      pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
277
278      /* Set engine function pointers */
279      winSetEngineFunctionsShadowGDI (pScreen);
280      return TRUE;
281    }
282
283  return TRUE;
284}
285
286
287/*
288 * Get procedure addresses for DirectDrawCreate and DirectDrawCreateClipper
289 */
290
291Bool
292winGetDDProcAddresses (void)
293{
294  Bool			fReturn = TRUE;
295
296  /* Load the DirectDraw library */
297  g_hmodDirectDraw = LoadLibraryEx ("ddraw.dll", NULL, 0);
298  if (g_hmodDirectDraw == NULL)
299    {
300      ErrorF ("winGetDDProcAddresses - Could not load ddraw.dll\n");
301      fReturn = TRUE;
302      goto winGetDDProcAddresses_Exit;
303    }
304
305  /* Try to get the DirectDrawCreate address */
306  g_fpDirectDrawCreate = GetProcAddress (g_hmodDirectDraw,
307					 "DirectDrawCreate");
308  if (g_fpDirectDrawCreate == NULL)
309    {
310      ErrorF ("winGetDDProcAddresses - Could not get DirectDrawCreate "
311	      "address\n");
312      fReturn = TRUE;
313      goto winGetDDProcAddresses_Exit;
314    }
315
316  /* Try to get the DirectDrawCreateClipper address */
317  g_fpDirectDrawCreateClipper = GetProcAddress (g_hmodDirectDraw,
318						"DirectDrawCreateClipper");
319  if (g_fpDirectDrawCreateClipper == NULL)
320    {
321      ErrorF ("winGetDDProcAddresses - Could not get "
322	      "DirectDrawCreateClipper address\n");
323      fReturn = FALSE;
324      goto winGetDDProcAddresses_Exit;
325    }
326
327  /*
328   * Note: Do not unload ddraw.dll here.  Do it in GiveUp
329   */
330
331 winGetDDProcAddresses_Exit:
332  /* Unload the DirectDraw library if we failed to initialize */
333  if (!fReturn && g_hmodDirectDraw != NULL)
334    {
335      FreeLibrary (g_hmodDirectDraw);
336      g_hmodDirectDraw = NULL;
337    }
338
339  return fReturn;
340}
341
342void
343winReleaseDDProcAddresses(void)
344{
345  if (g_hmodDirectDraw != NULL)
346    {
347      FreeLibrary (g_hmodDirectDraw);
348      g_hmodDirectDraw = NULL;
349      g_fpDirectDrawCreate = NULL;
350      g_fpDirectDrawCreateClipper = NULL;
351    }
352}
353