winengine.c revision 35c4bbdf
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    /* 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
111Bool
112winSetEngine(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#ifdef XWIN_MULTIWINDOWEXTWM
151        || pScreenInfo->fMWExtWM
152#endif
153#ifdef XWIN_MULTIWINDOW
154        || pScreenInfo->fMultiWindow
155#endif
156        ) {
157        winErrorFVerb(2,
158                      "winSetEngine - Multi Window or Rootless => ShadowGDI\n");
159        pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
160
161        /* Set engine function pointers */
162        winSetEngineFunctionsShadowGDI(pScreen);
163        return TRUE;
164    }
165
166    /* If the user's choice is supported, we'll use that */
167    if (g_dwEnginesSupported & pScreenInfo->dwEnginePreferred) {
168        winErrorFVerb(2, "winSetEngine - Using user's preference: %d\n",
169                      (int) pScreenInfo->dwEnginePreferred);
170        pScreenInfo->dwEngine = pScreenInfo->dwEnginePreferred;
171
172        /* Setup engine function pointers */
173        switch (pScreenInfo->dwEngine) {
174        case WIN_SERVER_SHADOW_GDI:
175            winSetEngineFunctionsShadowGDI(pScreen);
176            break;
177        case WIN_SERVER_SHADOW_DDNL:
178            winSetEngineFunctionsShadowDDNL(pScreen);
179            break;
180        default:
181            FatalError("winSetEngine - Invalid engine type\n");
182        }
183        return TRUE;
184    }
185
186    /* ShadowDDNL has good performance, so why not */
187    if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DDNL) {
188        winErrorFVerb(2, "winSetEngine - Using Shadow DirectDraw NonLocking\n");
189        pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DDNL;
190
191        /* Set engine function pointers */
192        winSetEngineFunctionsShadowDDNL(pScreen);
193        return TRUE;
194    }
195
196    /* ShadowGDI is next in line */
197    if (g_dwEnginesSupported & WIN_SERVER_SHADOW_GDI) {
198        winErrorFVerb(2, "winSetEngine - Using Shadow GDI DIB\n");
199        pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
200
201        /* Set engine function pointers */
202        winSetEngineFunctionsShadowGDI(pScreen);
203        return TRUE;
204    }
205
206    return TRUE;
207}
208
209/*
210 * Get procedure addresses for DirectDrawCreate and DirectDrawCreateClipper
211 */
212
213Bool
214winGetDDProcAddresses(void)
215{
216    Bool fReturn = TRUE;
217
218    /* Load the DirectDraw library */
219    g_hmodDirectDraw = LoadLibraryEx("ddraw.dll", NULL, 0);
220    if (g_hmodDirectDraw == NULL) {
221        ErrorF("winGetDDProcAddresses - Could not load ddraw.dll\n");
222        fReturn = TRUE;
223        goto winGetDDProcAddresses_Exit;
224    }
225
226    /* Try to get the DirectDrawCreate address */
227    g_fpDirectDrawCreate = GetProcAddress(g_hmodDirectDraw, "DirectDrawCreate");
228    if (g_fpDirectDrawCreate == NULL) {
229        ErrorF("winGetDDProcAddresses - Could not get DirectDrawCreate "
230               "address\n");
231        fReturn = TRUE;
232        goto winGetDDProcAddresses_Exit;
233    }
234
235    /* Try to get the DirectDrawCreateClipper address */
236    g_fpDirectDrawCreateClipper = GetProcAddress(g_hmodDirectDraw,
237                                                 "DirectDrawCreateClipper");
238    if (g_fpDirectDrawCreateClipper == NULL) {
239        ErrorF("winGetDDProcAddresses - Could not get "
240               "DirectDrawCreateClipper address\n");
241        fReturn = FALSE;
242        goto winGetDDProcAddresses_Exit;
243    }
244
245    /*
246     * Note: Do not unload ddraw.dll here.  Do it in GiveUp
247     */
248
249 winGetDDProcAddresses_Exit:
250    /* Unload the DirectDraw library if we failed to initialize */
251    if (!fReturn && g_hmodDirectDraw != NULL) {
252        FreeLibrary(g_hmodDirectDraw);
253        g_hmodDirectDraw = NULL;
254    }
255
256    return fReturn;
257}
258
259void
260winReleaseDDProcAddresses(void)
261{
262    if (g_hmodDirectDraw != NULL) {
263        FreeLibrary(g_hmodDirectDraw);
264        g_hmodDirectDraw = NULL;
265        g_fpDirectDrawCreate = NULL;
266        g_fpDirectDrawCreateClipper = NULL;
267    }
268}
269