diff options
Diffstat (limited to 'docs/release/src/osd/winui/directdraw.cpp')
-rw-r--r-- | docs/release/src/osd/winui/directdraw.cpp | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/docs/release/src/osd/winui/directdraw.cpp b/docs/release/src/osd/winui/directdraw.cpp new file mode 100644 index 00000000000..c85f97f8a76 --- /dev/null +++ b/docs/release/src/osd/winui/directdraw.cpp @@ -0,0 +1,382 @@ +// For licensing and usage information, read docs/winui_license.txt +//**************************************************************************** +/*************************************************************************** + + directdraw.c + + Direct Draw routines. + + ***************************************************************************/ + +// standard windows headers +#include <windows.h> + +// MAME/MAMEUI headers +#include "emu.h" +#include "winui.h" +#include "directdraw.h" +#include "mui_util.h" // For ErrorMsg +#include "dxdecode.h" // For DirectXDecodeError + +// standard C headers +#include <ddraw.h> +#include <tchar.h> + +/*************************************************************************** + function prototypes + ***************************************************************************/ + +static BOOL WINAPI DDEnumInfo(GUID FAR *lpGUID, LPTSTR lpDriverDescription, + LPTSTR lpDriverName, LPVOID lpContext, HMONITOR hm); + +static BOOL WINAPI DDEnumOldInfo(GUID FAR *lpGUID, LPTSTR lpDriverDescription, + LPTSTR lpDriverName, LPVOID lpContext); + +static void CalculateDisplayModes(void); +static HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context); +static HRESULT CALLBACK EnumDisplayModesCallback2(DDSURFACEDESC2* pddsd, LPVOID Context); + +/*************************************************************************** + External variables + ***************************************************************************/ + +/*************************************************************************** + Internal structures + ***************************************************************************/ + +typedef struct +{ + TCHAR* name; + GUID* lpguid; +} display_type; + +typedef HRESULT (WINAPI *ddc_proc)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter); + +/*************************************************************************** + Internal variables + ***************************************************************************/ + +#define MAX_DISPLAYS 100 +static int g_nNumDisplays = 0; +static display_type g_Displays[MAX_DISPLAYS]; + +static HANDLE g_hDLL; +static BOOL g_bHWStretch = 0; +static BOOL g_bRefresh = 0; +static struct tDisplayModes g_DisplayModes; +static IDirectDraw2* g_pDirectDraw2; +static IDirectDraw4* g_pDirectDraw4; + +/*************************************************************************** + External functions + ***************************************************************************/ + +/**************************************************************************** + * DirectDrawInitialize + * + * Initialize the DirectDraw variables. + * + * This entails the following functions: + * + * DirectDrawCreate + * + ****************************************************************************/ + +#if !defined(LPDIRECTDRAWENUMERATE) +#if defined(UNICODE) + +typedef HRESULT (WINAPI* LPDIRECTDRAWENUMERATEW)(LPDDENUMCALLBACKW lpCallback, LPVOID lpContext); + +#define LPDIRECTDRAWENUMERATE LPDIRECTDRAWENUMERATEW + +#define SDirectDrawEnumerateEx "DirectDrawEnumerateExW" +#define SDirectDrawEnumerate "DirectDrawEnumerateW" + +#else + +typedef HRESULT (WINAPI* LPDIRECTDRAWENUMERATEA)(LPDDENUMCALLBACKA lpCallback, LPVOID lpContext); + +#define LPDIRECTDRAWENUMERATE LPDIRECTDRAWENUMERATEA + +#define SDirectDrawEnumerateEx "DirectDrawEnumerateExA" +#define SDirectDrawEnumerate "DirectDrawEnumerateA" + +#endif +#endif /* LPDIRECTDRAWENUMERATE */ + +/****************************************************************************/ + +BOOL DirectDraw_Initialize(void) +{ + HRESULT hr; + UINT error_mode = 0; + ddc_proc ddc; + DDCAPS ddCaps; + DDCAPS ddHelCaps; + IDirectDraw* pDirectDraw1; + LPDIRECTDRAWENUMERATEEX pDDEnumEx; + + if (g_hDLL != NULL) + return TRUE; + + g_nNumDisplays = 0; + g_hDLL = NULL; + g_bHWStretch = FALSE; + g_bRefresh = FALSE; + g_pDirectDraw2 = NULL; + g_pDirectDraw4 = NULL; + + /* Turn off error dialog for this call */ + error_mode = SetErrorMode(0); + g_hDLL = LoadLibrary(TEXT("ddraw.dll")); + SetErrorMode(error_mode); + + if (g_hDLL == NULL) + return FALSE; + + ddc = (ddc_proc)GetProcAddress((HINSTANCE)g_hDLL, "DirectDrawCreate"); + if (ddc == NULL) + return FALSE; + + pDirectDraw1 = NULL; + g_pDirectDraw2 = NULL; + g_pDirectDraw4 = NULL; + hr = ddc(NULL, &pDirectDraw1, NULL); + if (FAILED(hr)) + { + ErrorMsg("DirectDrawCreate failed: %s", DirectXDecodeError(hr)); + return FALSE; + } + + hr = IDirectDraw_QueryInterface(pDirectDraw1, IID_IDirectDraw4, (void**)&g_pDirectDraw4); + if (FAILED(hr)) + { + g_pDirectDraw4 = NULL; + hr = IDirectDraw_QueryInterface(pDirectDraw1, IID_IDirectDraw2, (void**)&g_pDirectDraw2); + if (FAILED(hr)) + { + ErrorMsg("Query Interface for DirectDraw 2 failed: %s", DirectXDecodeError(hr)); + g_pDirectDraw2 = NULL; + IDirectDraw_Release(pDirectDraw1); + return FALSE; + } + } + + memset(&ddCaps, 0, sizeof(DDCAPS)); + memset(&ddHelCaps, 0, sizeof(DDCAPS)); + ddCaps.dwSize = sizeof(DDCAPS); + ddHelCaps.dwSize = sizeof(DDCAPS); + hr = IDirectDraw_GetCaps(pDirectDraw1, &ddCaps, &ddHelCaps); /* 1 2 or 4? */ + if (FAILED(hr)) + { + ErrorMsg("Error getting DirectDraw capabilities: %s", DirectXDecodeError(hr)); + } + else + g_bHWStretch = ((ddCaps.dwCaps & DDCAPS_BLTSTRETCH) != 0) ? TRUE : FALSE; + + IDirectDraw_Release(pDirectDraw1); + + /* + Note that you must know which version of the + function to retrieve (see the following text). + For this example, we use the ANSI version. + */ + pDDEnumEx = (LPDIRECTDRAWENUMERATEEX) GetProcAddress((HINSTANCE)g_hDLL, SDirectDrawEnumerateEx); + + /* + If the function is there, call it to enumerate all display devices + attached to the desktop, and any non-display DirectDraw devices. + */ + if (pDDEnumEx) + { + pDDEnumEx(DDEnumInfo, NULL, DDENUM_ATTACHEDSECONDARYDEVICES | DDENUM_DETACHEDSECONDARYDEVICES); + } + else + { + LPDIRECTDRAWENUMERATE lpDDEnum; + + lpDDEnum = (LPDIRECTDRAWENUMERATE) GetProcAddress((HINSTANCE)g_hDLL, SDirectDrawEnumerate); + /* + * We must be running on an old version of ddraw. Therefore, + * by definiton, multimon isn't supported. Fall back on + * DirectDrawEnumerate to enumerate standard devices on a + * single monitor system. + */ + if (lpDDEnum) + { + lpDDEnum(DDEnumOldInfo, NULL); + } + else + { + return FALSE; + } + } + + return TRUE; +} + +/**************************************************************************** + * + * DirectDraw_Close + * + * Terminate our usage of DirectDraw. + * + ****************************************************************************/ + +void DirectDraw_Close(void) +{ + int i; + + for (i = 0; i < g_nNumDisplays; i++) + { + free(g_Displays[i].name); + g_Displays[i].name = NULL; + if (g_Displays[i].lpguid != NULL) + { + free(g_Displays[i].lpguid); + g_Displays[i].lpguid = NULL; + } + + } + g_nNumDisplays = 0; + + /* + Destroy any lingering IDirectDraw object. + */ + if (g_pDirectDraw2) + { + IDirectDraw2_Release(g_pDirectDraw2); + g_pDirectDraw2 = NULL; + } + + if (g_pDirectDraw4) + { + IDirectDraw4_Release(g_pDirectDraw4); + g_pDirectDraw4 = NULL; + } + + if (g_hDLL) + { + FreeLibrary((HINSTANCE)g_hDLL); + g_hDLL = NULL; + } +} + +/****************************************************************************/ +/* + Return a list of 16, 24 and 32 bit DirectDraw modes. +*/ +struct tDisplayModes* DirectDraw_GetDisplayModes(void) +{ + if (g_DisplayModes.m_nNumModes == 0) + CalculateDisplayModes(); + + return &g_DisplayModes; +} + +int DirectDraw_GetNumDisplays(void) +{ + return g_nNumDisplays; +} + +BOOL DirectDraw_HasHWStretch(void) +{ + return g_bHWStretch; +} + +BOOL DirectDraw_HasRefresh(void) +{ + return g_bRefresh; +} + +LPCTSTR DirectDraw_GetDisplayName(int num_display) +{ + return g_Displays[num_display].name; +} + +/****************************************************************************/ +/* internal functions */ +/****************************************************************************/ + +static BOOL WINAPI DDEnumInfo(GUID FAR *lpGUID, LPTSTR lpDriverDescription, + LPTSTR lpDriverName, LPVOID lpContext, HMONITOR hm) +{ + g_Displays[g_nNumDisplays].name = (TCHAR*)malloc((_tcslen(lpDriverDescription) + 1) * sizeof(TCHAR)); + _tcscpy(g_Displays[g_nNumDisplays].name, lpDriverDescription); + + if (lpGUID == NULL) + g_Displays[g_nNumDisplays].lpguid = NULL; + else + { + g_Displays[g_nNumDisplays].lpguid = (LPGUID)malloc(sizeof(GUID)); + memcpy(g_Displays[g_nNumDisplays].lpguid, lpGUID, sizeof(GUID)); + } + + g_nNumDisplays++; + if (g_nNumDisplays == MAX_DISPLAYS) + return DDENUMRET_CANCEL; + else + return DDENUMRET_OK; +} + +static BOOL WINAPI DDEnumOldInfo(GUID FAR *lpGUID, LPTSTR lpDriverDescription, LPTSTR lpDriverName, LPVOID lpContext) +{ + return DDEnumInfo(lpGUID, lpDriverDescription, lpDriverName, lpContext, NULL); +} + +static HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context) +{ + DWORD dwDepth = pddsd->ddpfPixelFormat.dwRGBBitCount; + + struct tDisplayModes* pDisplayModes = (struct tDisplayModes*)Context; + if (dwDepth == 16 || dwDepth == 24 || dwDepth == 32) + { + pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwWidth = pddsd->dwWidth; + pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwHeight = pddsd->dwHeight; + pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwBPP = dwDepth; + pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwRefresh = 0; + pDisplayModes->m_nNumModes++; + } + + if (pDisplayModes->m_nNumModes == MAXMODES) + return DDENUMRET_CANCEL; + else + return DDENUMRET_OK; +} + +static HRESULT CALLBACK EnumDisplayModesCallback2(DDSURFACEDESC2* pddsd2, LPVOID Context) +{ + struct tDisplayModes* pDisplayModes = (struct tDisplayModes*)Context; + + DWORD dwDepth = pddsd2->ddpfPixelFormat.dwRGBBitCount; + + if (dwDepth == 16 || dwDepth == 24 || dwDepth == 32) + { + pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwWidth = pddsd2->dwWidth; + pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwHeight = pddsd2->dwHeight; + pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwBPP = dwDepth; + pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwRefresh = pddsd2->dwRefreshRate; + pDisplayModes->m_nNumModes++; + + if (pddsd2->dwRefreshRate != 0) + g_bRefresh = TRUE; + } + + if (pDisplayModes->m_nNumModes == MAXMODES) + return DDENUMRET_CANCEL; + else + return DDENUMRET_OK; +} + +static void CalculateDisplayModes(void) +{ + g_DisplayModes.m_nNumModes = 0; + + if (g_pDirectDraw4) + IDirectDraw4_EnumDisplayModes(g_pDirectDraw4, DDEDM_REFRESHRATES, NULL, &g_DisplayModes, EnumDisplayModesCallback2); + else + if (g_pDirectDraw2) + IDirectDraw2_EnumDisplayModes(g_pDirectDraw2, 0, NULL, &g_DisplayModes, EnumDisplayModesCallback); +} + + |