winengine.c revision 1b5d61b8
105b261ecSmrg/*
205b261ecSmrg *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
305b261ecSmrg *
405b261ecSmrg *Permission is hereby granted, free of charge, to any person obtaining
505b261ecSmrg * a copy of this software and associated documentation files (the
605b261ecSmrg *"Software"), to deal in the Software without restriction, including
705b261ecSmrg *without limitation the rights to use, copy, modify, merge, publish,
805b261ecSmrg *distribute, sublicense, and/or sell copies of the Software, and to
905b261ecSmrg *permit persons to whom the Software is furnished to do so, subject to
1005b261ecSmrg *the following conditions:
1105b261ecSmrg *
1205b261ecSmrg *The above copyright notice and this permission notice shall be
1305b261ecSmrg *included in all copies or substantial portions of the Software.
1405b261ecSmrg *
1505b261ecSmrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1605b261ecSmrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1705b261ecSmrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1805b261ecSmrg *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
1905b261ecSmrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
2005b261ecSmrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2105b261ecSmrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2205b261ecSmrg *
2305b261ecSmrg *Except as contained in this notice, the name of Harold L Hunt II
2405b261ecSmrg *shall not be used in advertising or otherwise to promote the sale, use
2505b261ecSmrg *or other dealings in this Software without prior written authorization
2605b261ecSmrg *from Harold L Hunt II.
2705b261ecSmrg *
2805b261ecSmrg * Authors:	Harold L Hunt II
2905b261ecSmrg */
3005b261ecSmrg
3105b261ecSmrg#ifdef HAVE_XWIN_CONFIG_H
3205b261ecSmrg#include <xwin-config.h>
3305b261ecSmrg#endif
3405b261ecSmrg#include "win.h"
3505b261ecSmrg#include "winmsg.h"
3605b261ecSmrg
3705b261ecSmrg/*
389ace9065Smrg * Global variables for function pointers into
399ace9065Smrg * dynamically loaded libraries
4005b261ecSmrg */
4135c4bbdfSmrgFARPROC g_fpDirectDrawCreate = NULL;
4235c4bbdfSmrgFARPROC g_fpDirectDrawCreateClipper = NULL;
4305b261ecSmrg
449ace9065Smrg/*
459ace9065Smrg  module handle for dynamically loaded directdraw library
469ace9065Smrg*/
479ace9065Smrgstatic HMODULE g_hmodDirectDraw = NULL;
4805b261ecSmrg
4905b261ecSmrg/*
5005b261ecSmrg * Detect engines supported by current Windows version
5105b261ecSmrg * DirectDraw version and hardware
5205b261ecSmrg */
5305b261ecSmrg
5405b261ecSmrgvoid
5535c4bbdfSmrgwinDetectSupportedEngines(void)
5605b261ecSmrg{
5735c4bbdfSmrg    /* Initialize the engine support flags */
5835c4bbdfSmrg    g_dwEnginesSupported = WIN_SERVER_SHADOW_GDI;
5935c4bbdfSmrg
6035c4bbdfSmrg    /* Do we have DirectDraw? */
6135c4bbdfSmrg    if (g_hmodDirectDraw != NULL) {
6235c4bbdfSmrg        LPDIRECTDRAW lpdd = NULL;
6335c4bbdfSmrg        LPDIRECTDRAW4 lpdd4 = NULL;
6435c4bbdfSmrg        HRESULT ddrval;
6535c4bbdfSmrg
6635c4bbdfSmrg        /* Was the DirectDrawCreate function found? */
6735c4bbdfSmrg        if (g_fpDirectDrawCreate == NULL) {
6835c4bbdfSmrg            /* No DirectDraw support */
6935c4bbdfSmrg            return;
7035c4bbdfSmrg        }
7135c4bbdfSmrg
7235c4bbdfSmrg        /* DirectDrawCreate exists, try to call it */
7335c4bbdfSmrg        /* Create a DirectDraw object, store the address at lpdd */
7435c4bbdfSmrg        ddrval = (*g_fpDirectDrawCreate) (NULL, (void **) &lpdd, NULL);
7535c4bbdfSmrg        if (FAILED(ddrval)) {
7635c4bbdfSmrg            /* No DirectDraw support */
7735c4bbdfSmrg            winErrorFVerb(2,
7835c4bbdfSmrg                          "winDetectSupportedEngines - DirectDraw not installed\n");
7935c4bbdfSmrg            return;
8035c4bbdfSmrg        }
8135c4bbdfSmrg
8235c4bbdfSmrg        /* Try to query for DirectDraw4 interface */
8335c4bbdfSmrg        ddrval = IDirectDraw_QueryInterface(lpdd,
8435c4bbdfSmrg                                            &IID_IDirectDraw4,
8535c4bbdfSmrg                                            (LPVOID *) &lpdd4);
8635c4bbdfSmrg        if (SUCCEEDED(ddrval)) {
8735c4bbdfSmrg            /* We have DirectDraw4 */
8835c4bbdfSmrg            winErrorFVerb(2,
8935c4bbdfSmrg                          "winDetectSupportedEngines - DirectDraw4 installed, allowing ShadowDDNL\n");
9035c4bbdfSmrg            g_dwEnginesSupported |= WIN_SERVER_SHADOW_DDNL;
9135c4bbdfSmrg        }
9235c4bbdfSmrg
9335c4bbdfSmrg        /* Cleanup DirectDraw interfaces */
9435c4bbdfSmrg        if (lpdd4 != NULL)
9535c4bbdfSmrg            IDirectDraw_Release(lpdd4);
9635c4bbdfSmrg        if (lpdd != NULL)
9735c4bbdfSmrg            IDirectDraw_Release(lpdd);
9805b261ecSmrg    }
9905b261ecSmrg
10035c4bbdfSmrg    winErrorFVerb(2,
10135c4bbdfSmrg                  "winDetectSupportedEngines - Returning, supported engines %08x\n",
10235c4bbdfSmrg                  (unsigned int) g_dwEnginesSupported);
10305b261ecSmrg}
10405b261ecSmrg
10505b261ecSmrg/*
10605b261ecSmrg * Set the engine type, depending on the engines
10705b261ecSmrg * supported for this screen, and whether the user
10805b261ecSmrg * suggested an engine type
10905b261ecSmrg */
11005b261ecSmrg
11105b261ecSmrgBool
11235c4bbdfSmrgwinSetEngine(ScreenPtr pScreen)
11305b261ecSmrg{
11435c4bbdfSmrg    winScreenPriv(pScreen);
11535c4bbdfSmrg    winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
11635c4bbdfSmrg    HDC hdc;
11735c4bbdfSmrg    DWORD dwBPP;
11835c4bbdfSmrg
11935c4bbdfSmrg    /* Get a DC */
12035c4bbdfSmrg    hdc = GetDC(NULL);
12135c4bbdfSmrg    if (hdc == NULL) {
12235c4bbdfSmrg        ErrorF("winSetEngine - Couldn't get an HDC\n");
12335c4bbdfSmrg        return FALSE;
12405b261ecSmrg    }
12505b261ecSmrg
12635c4bbdfSmrg    /*
12735c4bbdfSmrg     * pScreenInfo->dwBPP may be 0 to indicate that the current screen
12835c4bbdfSmrg     * depth is to be used.  Thus, we must query for the current display
12935c4bbdfSmrg     * depth here.
13035c4bbdfSmrg     */
13135c4bbdfSmrg    dwBPP = GetDeviceCaps(hdc, BITSPIXEL);
13235c4bbdfSmrg
13335c4bbdfSmrg    /* Release the DC */
13435c4bbdfSmrg    ReleaseDC(NULL, hdc);
13535c4bbdfSmrg    hdc = NULL;
13635c4bbdfSmrg
13735c4bbdfSmrg    /* ShadowGDI is the only engine that supports windowed PseudoColor */
13835c4bbdfSmrg    if (dwBPP == 8 && !pScreenInfo->fFullScreen) {
13935c4bbdfSmrg        winErrorFVerb(2,
14035c4bbdfSmrg                      "winSetEngine - Windowed && PseudoColor => ShadowGDI\n");
14135c4bbdfSmrg        pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
14235c4bbdfSmrg
14335c4bbdfSmrg        /* Set engine function pointers */
14435c4bbdfSmrg        winSetEngineFunctionsShadowGDI(pScreen);
14535c4bbdfSmrg        return TRUE;
14605b261ecSmrg    }
14705b261ecSmrg
14835c4bbdfSmrg    /* ShadowGDI is the only engine that supports Multi Window Mode */
14935c4bbdfSmrg    if (FALSE
15005b261ecSmrg#ifdef XWIN_MULTIWINDOWEXTWM
15135c4bbdfSmrg        || pScreenInfo->fMWExtWM
15205b261ecSmrg#endif
15335c4bbdfSmrg        || pScreenInfo->fMultiWindow
15435c4bbdfSmrg        ) {
15535c4bbdfSmrg        winErrorFVerb(2,
15635c4bbdfSmrg                      "winSetEngine - Multi Window or Rootless => ShadowGDI\n");
15735c4bbdfSmrg        pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
15835c4bbdfSmrg
15935c4bbdfSmrg        /* Set engine function pointers */
16035c4bbdfSmrg        winSetEngineFunctionsShadowGDI(pScreen);
16135c4bbdfSmrg        return TRUE;
16205b261ecSmrg    }
16305b261ecSmrg
16435c4bbdfSmrg    /* If the user's choice is supported, we'll use that */
16535c4bbdfSmrg    if (g_dwEnginesSupported & pScreenInfo->dwEnginePreferred) {
16635c4bbdfSmrg        winErrorFVerb(2, "winSetEngine - Using user's preference: %d\n",
16735c4bbdfSmrg                      (int) pScreenInfo->dwEnginePreferred);
16835c4bbdfSmrg        pScreenInfo->dwEngine = pScreenInfo->dwEnginePreferred;
16935c4bbdfSmrg
17035c4bbdfSmrg        /* Setup engine function pointers */
17135c4bbdfSmrg        switch (pScreenInfo->dwEngine) {
17235c4bbdfSmrg        case WIN_SERVER_SHADOW_GDI:
17335c4bbdfSmrg            winSetEngineFunctionsShadowGDI(pScreen);
17435c4bbdfSmrg            break;
17535c4bbdfSmrg        case WIN_SERVER_SHADOW_DDNL:
17635c4bbdfSmrg            winSetEngineFunctionsShadowDDNL(pScreen);
17735c4bbdfSmrg            break;
17835c4bbdfSmrg        default:
17935c4bbdfSmrg            FatalError("winSetEngine - Invalid engine type\n");
18035c4bbdfSmrg        }
18135c4bbdfSmrg        return TRUE;
18205b261ecSmrg    }
18305b261ecSmrg
18435c4bbdfSmrg    /* ShadowDDNL has good performance, so why not */
18535c4bbdfSmrg    if (g_dwEnginesSupported & WIN_SERVER_SHADOW_DDNL) {
18635c4bbdfSmrg        winErrorFVerb(2, "winSetEngine - Using Shadow DirectDraw NonLocking\n");
18735c4bbdfSmrg        pScreenInfo->dwEngine = WIN_SERVER_SHADOW_DDNL;
18805b261ecSmrg
18935c4bbdfSmrg        /* Set engine function pointers */
19035c4bbdfSmrg        winSetEngineFunctionsShadowDDNL(pScreen);
19135c4bbdfSmrg        return TRUE;
19205b261ecSmrg    }
19305b261ecSmrg
19435c4bbdfSmrg    /* ShadowGDI is next in line */
19535c4bbdfSmrg    if (g_dwEnginesSupported & WIN_SERVER_SHADOW_GDI) {
19635c4bbdfSmrg        winErrorFVerb(2, "winSetEngine - Using Shadow GDI DIB\n");
19735c4bbdfSmrg        pScreenInfo->dwEngine = WIN_SERVER_SHADOW_GDI;
19805b261ecSmrg
19935c4bbdfSmrg        /* Set engine function pointers */
20035c4bbdfSmrg        winSetEngineFunctionsShadowGDI(pScreen);
20135c4bbdfSmrg        return TRUE;
20205b261ecSmrg    }
20305b261ecSmrg
2041b5d61b8Smrg    return FALSE;
20505b261ecSmrg}
20605b261ecSmrg
20705b261ecSmrg/*
20805b261ecSmrg * Get procedure addresses for DirectDrawCreate and DirectDrawCreateClipper
20905b261ecSmrg */
21005b261ecSmrg
21105b261ecSmrgBool
21235c4bbdfSmrgwinGetDDProcAddresses(void)
21305b261ecSmrg{
21435c4bbdfSmrg    Bool fReturn = TRUE;
21535c4bbdfSmrg
21635c4bbdfSmrg    /* Load the DirectDraw library */
21735c4bbdfSmrg    g_hmodDirectDraw = LoadLibraryEx("ddraw.dll", NULL, 0);
21835c4bbdfSmrg    if (g_hmodDirectDraw == NULL) {
21935c4bbdfSmrg        ErrorF("winGetDDProcAddresses - Could not load ddraw.dll\n");
22035c4bbdfSmrg        fReturn = TRUE;
22135c4bbdfSmrg        goto winGetDDProcAddresses_Exit;
22205b261ecSmrg    }
22305b261ecSmrg
22435c4bbdfSmrg    /* Try to get the DirectDrawCreate address */
22535c4bbdfSmrg    g_fpDirectDrawCreate = GetProcAddress(g_hmodDirectDraw, "DirectDrawCreate");
22635c4bbdfSmrg    if (g_fpDirectDrawCreate == NULL) {
22735c4bbdfSmrg        ErrorF("winGetDDProcAddresses - Could not get DirectDrawCreate "
22835c4bbdfSmrg               "address\n");
22935c4bbdfSmrg        fReturn = TRUE;
23035c4bbdfSmrg        goto winGetDDProcAddresses_Exit;
23105b261ecSmrg    }
23205b261ecSmrg
23335c4bbdfSmrg    /* Try to get the DirectDrawCreateClipper address */
23435c4bbdfSmrg    g_fpDirectDrawCreateClipper = GetProcAddress(g_hmodDirectDraw,
23535c4bbdfSmrg                                                 "DirectDrawCreateClipper");
23635c4bbdfSmrg    if (g_fpDirectDrawCreateClipper == NULL) {
23735c4bbdfSmrg        ErrorF("winGetDDProcAddresses - Could not get "
23835c4bbdfSmrg               "DirectDrawCreateClipper address\n");
23935c4bbdfSmrg        fReturn = FALSE;
24035c4bbdfSmrg        goto winGetDDProcAddresses_Exit;
24105b261ecSmrg    }
24205b261ecSmrg
24335c4bbdfSmrg    /*
24435c4bbdfSmrg     * Note: Do not unload ddraw.dll here.  Do it in GiveUp
24535c4bbdfSmrg     */
24605b261ecSmrg
24705b261ecSmrg winGetDDProcAddresses_Exit:
24835c4bbdfSmrg    /* Unload the DirectDraw library if we failed to initialize */
24935c4bbdfSmrg    if (!fReturn && g_hmodDirectDraw != NULL) {
25035c4bbdfSmrg        FreeLibrary(g_hmodDirectDraw);
25135c4bbdfSmrg        g_hmodDirectDraw = NULL;
25205b261ecSmrg    }
25335c4bbdfSmrg
25435c4bbdfSmrg    return fReturn;
25505b261ecSmrg}
2569ace9065Smrg
2579ace9065Smrgvoid
2589ace9065SmrgwinReleaseDDProcAddresses(void)
2599ace9065Smrg{
26035c4bbdfSmrg    if (g_hmodDirectDraw != NULL) {
26135c4bbdfSmrg        FreeLibrary(g_hmodDirectDraw);
26235c4bbdfSmrg        g_hmodDirectDraw = NULL;
26335c4bbdfSmrg        g_fpDirectDrawCreate = NULL;
26435c4bbdfSmrg        g_fpDirectDrawCreateClipper = NULL;
2659ace9065Smrg    }
2669ace9065Smrg}
267