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  */
41 FARPROC g_fpDirectDrawCreate = NULL;
42 FARPROC g_fpDirectDrawCreateClipper = NULL;
43 
44 /*
45   module handle for dynamically loaded directdraw library
46 */
47 static HMODULE g_hmodDirectDraw = NULL;
48 
49 /*
50  * Detect engines supported by current Windows version
51  * DirectDraw version and hardware
52  */
53 
54 void
winDetectSupportedEngines(void)55 winDetectSupportedEngines(void)
56 {
57     /* Initialize the engine support flags */
58     g_dwEnginesSupported = WIN_SERVER_SHADOW_GDI;
59 
60     /* Do we have DirectDraw? */
61     if (g_hmodDirectDraw != NULL) {
62         LPDIRECTDRAW lpdd = NULL;
63         LPDIRECTDRAW4 lpdd4 = NULL;
64         HRESULT ddrval;
65 
66         /* Was the DirectDrawCreate function found? */
67         if (g_fpDirectDrawCreate == NULL) {
68             /* No DirectDraw support */
69             return;
70         }
71 
72         /* DirectDrawCreate exists, try to call it */
73         /* Create a DirectDraw object, store the address at lpdd */
74         ddrval = (*g_fpDirectDrawCreate) (NULL, (void **) &lpdd, NULL);
75         if (FAILED(ddrval)) {
76             /* No DirectDraw support */
77             winErrorFVerb(2,
78                           "winDetectSupportedEngines - DirectDraw not installed\n");
79             return;
80         }
81 
82         /* Try to query for DirectDraw4 interface */
83         ddrval = IDirectDraw_QueryInterface(lpdd,
84                                             &IID_IDirectDraw4,
85                                             (LPVOID *) &lpdd4);
86         if (SUCCEEDED(ddrval)) {
87             /* We have DirectDraw4 */
88             winErrorFVerb(2,
89                           "winDetectSupportedEngines - DirectDraw4 installed, allowing ShadowDDNL\n");
90             g_dwEnginesSupported |= WIN_SERVER_SHADOW_DDNL;
91         }
92 
93         /* Cleanup DirectDraw interfaces */
94         if (lpdd4 != NULL)
95             IDirectDraw_Release(lpdd4);
96         if (lpdd != NULL)
97             IDirectDraw_Release(lpdd);
98     }
99 
100     winErrorFVerb(2,
101                   "winDetectSupportedEngines - Returning, supported engines %08x\n",
102                   (unsigned int) g_dwEnginesSupported);
103 }
104 
105 /*
106  * Set the engine type, depending on the engines
107  * supported for this screen, and whether the user
108  * suggested an engine type
109  */
110 
111 Bool
winSetEngine(ScreenPtr pScreen)112 winSetEngine(ScreenPtr pScreen)
113 {
114     winScreenPriv(pScreen);
115     winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
116     HDC hdc;
117     DWORD dwBPP;
118 
119     /* Get a DC */
120     hdc = GetDC(NULL);
121     if (hdc == NULL) {
122         ErrorF("winSetEngine - Couldn't get an HDC\n");
123         return FALSE;
124     }
125 
126     /*
127      * pScreenInfo->dwBPP may be 0 to indicate that the current screen
128      * depth is to be used.  Thus, we must query for the current display
129      * depth here.
130      */
131     dwBPP = GetDeviceCaps(hdc, BITSPIXEL);
132 
133     /* Release the DC */
134     ReleaseDC(NULL, hdc);
135     hdc = NULL;
136 
137     /* ShadowGDI is the only engine that supports windowed PseudoColor */
138     if (dwBPP == 8 && !pScreenInfo->fFullScreen) {
139         winErrorFVerb(2,
140                       "winSetEngine - Windowed && PseudoColor => ShadowGDI\n");
141         pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
142 
143         /* Set engine function pointers */
144         winSetEngineFunctionsShadowGDI(pScreen);
145         return TRUE;
146     }
147 
148     /* ShadowGDI is the only engine that supports Multi Window Mode */
149     if (FALSE
150         || pScreenInfo->fMultiWindow
151         ) {
152         winErrorFVerb(2,
153                       "winSetEngine - Multi Window or Rootless => ShadowGDI\n");
154         pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
155 
156         /* Set engine function pointers */
157         winSetEngineFunctionsShadowGDI(pScreen);
158         return TRUE;
159     }
160 
161     /* If the user's choice is supported, we'll use that */
162     if (g_dwEnginesSupported & pScreenInfo->dwEnginePreferred) {
163         winErrorFVerb(2, "winSetEngine - Using user's preference: %d\n",
164                       (int) pScreenInfo->dwEnginePreferred);
165         pScreenInfo->dwEngine = pScreenInfo->dwEnginePreferred;
166 
167         /* Setup engine function pointers */
168         switch (pScreenInfo->dwEngine) {
169         case WIN_SERVER_SHADOW_GDI:
170             winSetEngineFunctionsShadowGDI(pScreen);
171             break;
172         case WIN_SERVER_SHADOW_DDNL:
173             winSetEngineFunctionsShadowDDNL(pScreen);
174             break;
175         default:
176             FatalError("winSetEngine - Invalid engine type\n");
177         }
178         return TRUE;
179     }
180 
181     /* ShadowDDNL has good performance, so why not */
182     if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DDNL) {
183         winErrorFVerb(2, "winSetEngine - Using Shadow DirectDraw NonLocking\n");
184         pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DDNL;
185 
186         /* Set engine function pointers */
187         winSetEngineFunctionsShadowDDNL(pScreen);
188         return TRUE;
189     }
190 
191     /* ShadowGDI is next in line */
192     if (g_dwEnginesSupported & WIN_SERVER_SHADOW_GDI) {
193         winErrorFVerb(2, "winSetEngine - Using Shadow GDI DIB\n");
194         pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
195 
196         /* Set engine function pointers */
197         winSetEngineFunctionsShadowGDI(pScreen);
198         return TRUE;
199     }
200 
201     return FALSE;
202 }
203 
204 /*
205  * Get procedure addresses for DirectDrawCreate and DirectDrawCreateClipper
206  */
207 
208 Bool
winGetDDProcAddresses(void)209 winGetDDProcAddresses(void)
210 {
211     Bool fReturn = TRUE;
212 
213     /* Load the DirectDraw library */
214     g_hmodDirectDraw = LoadLibraryEx("ddraw.dll", NULL, 0);
215     if (g_hmodDirectDraw == NULL) {
216         ErrorF("winGetDDProcAddresses - Could not load ddraw.dll\n");
217         fReturn = TRUE;
218         goto winGetDDProcAddresses_Exit;
219     }
220 
221     /* Try to get the DirectDrawCreate address */
222     g_fpDirectDrawCreate = GetProcAddress(g_hmodDirectDraw, "DirectDrawCreate");
223     if (g_fpDirectDrawCreate == NULL) {
224         ErrorF("winGetDDProcAddresses - Could not get DirectDrawCreate "
225                "address\n");
226         fReturn = TRUE;
227         goto winGetDDProcAddresses_Exit;
228     }
229 
230     /* Try to get the DirectDrawCreateClipper address */
231     g_fpDirectDrawCreateClipper = GetProcAddress(g_hmodDirectDraw,
232                                                  "DirectDrawCreateClipper");
233     if (g_fpDirectDrawCreateClipper == NULL) {
234         ErrorF("winGetDDProcAddresses - Could not get "
235                "DirectDrawCreateClipper address\n");
236         fReturn = FALSE;
237         goto winGetDDProcAddresses_Exit;
238     }
239 
240     /*
241      * Note: Do not unload ddraw.dll here.  Do it in GiveUp
242      */
243 
244  winGetDDProcAddresses_Exit:
245     /* Unload the DirectDraw library if we failed to initialize */
246     if (!fReturn && g_hmodDirectDraw != NULL) {
247         FreeLibrary(g_hmodDirectDraw);
248         g_hmodDirectDraw = NULL;
249     }
250 
251     return fReturn;
252 }
253 
254 void
winReleaseDDProcAddresses(void)255 winReleaseDDProcAddresses(void)
256 {
257     if (g_hmodDirectDraw != NULL) {
258         FreeLibrary(g_hmodDirectDraw);
259         g_hmodDirectDraw = NULL;
260         g_fpDirectDrawCreate = NULL;
261         g_fpDirectDrawCreateClipper = NULL;
262     }
263 }
264