Descent3/dd_vidwin32/vidWin32FS.cpp
2024-04-16 12:56:40 -06:00

204 lines
5.9 KiB
C++

/*
* $Logfile: /DescentIII/Main/ddvid_win32/vidWin32FS.cpp $
* $Revision: 7 $
* $Date: 7/15/98 5:56p $
* $Author: Samir $
*
* Fullscreen version of Win32 library
*
* $Log: /DescentIII/Main/ddvid_win32/vidWin32FS.cpp $
*
* 7 7/15/98 5:56p Samir
* commented out GDIX subsystem.
*
* 6 6/04/98 7:04p Samir
* assert res-switch to be at least 16bpp.
*
* 5 3/04/98 5:01p Samir
* May have fixed problem with restoring old display modes.
*
* 4 2/03/98 3:12p Samir
* Enable access to directdraw object by DDAccess libraries.
*
* 3 12/30/97 3:35p Samir
* Added dummy mode to help in mode selection.
*
* 2 12/30/97 2:31p Jason
* Fixed mode finder. (samir)
*
* 1 12/23/97 5:46p Samir
* Initial revision
*
* $NoKeywords: $
*/
#include "ddvidlib.h"
#include "pserror.h"
// DirectDraw Display mode enumeration callback
HRESULT WINAPI DDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext);
// inits fullscreen system
bool ddvidfs_Init() {
HRESULT hres;
hres = DirectDrawCreate(NULL, &DDVideo_info.lpDD, NULL);
if (hres != DD_OK) {
Error("Failure to initialize DirectDraw driver. (%d)", LOWORD(hres));
}
hres =
DDVideo_info.lpDD->SetCooperativeLevel(DDVideo_info.hWnd, DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if (hres != DD_OK) {
Error("Failed to set access mode for DirectDraw driver. (%d)", LOWORD(hres));
}
// dummy mode
DDVideo_info.DDModes[DDVideo_info.nDDModes].ddpfPixelFormat.dwRGBBitCount = 0;
DDVideo_info.DDModes[DDVideo_info.nDDModes].dwWidth = 0;
DDVideo_info.DDModes[DDVideo_info.nDDModes].dwHeight = 0;
DDVideo_info.nDDModes++;
// enumerate all display modes.
if (DDVideo_info.lpDD->EnumDisplayModes(0, NULL, NULL, DDEnumModesCallback) != DD_OK) {
mprintf((0, "DDVID error: Error enumerating display modes.\n"));
return false;
}
mprintf((0, "Video fullscreen system initialized.\n"));
return true;
}
// closes fullscreen system
void ddvidfs_Close() {
if (DDVideo_info.lpDDSFront)
DDVideo_info.lpDDSFront->Release();
if (DDVideo_info.lpDD) {
DDVideo_info.lpDD->RestoreDisplayMode();
DDVideo_info.lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
DDVideo_info.lpDD->Release();
DDVideo_info.lpDD = NULL;
}
DDVideo_info.lpDDSFront = NULL;
DDVideo_info.lpDDSBack = NULL;
DDVideo_info.hWnd = NULL;
DDVideo_info.nDDModes = 0;
}
// uses direct draw. if paged, allows frame buffer access.
bool ddvidfs_SetVideoMode(int w, int h, int color_depth, bool paged) {
HRESULT hres;
DDSCAPS ddscaps;
DDSURFACEDESC ddsd;
int i, mode;
bool found_mode;
mode = 0;
found_mode = false;
// find closest match for video mode.
for (i = 0; i < DDVideo_info.nDDModes; i++) {
if (color_depth == (int)DDVideo_info.DDModes[i].ddpfPixelFormat.dwRGBBitCount) {
if (DDVideo_info.DDModes[i].dwWidth >= (DWORD)w && DDVideo_info.DDModes[mode].dwWidth < (DWORD)w)
if (DDVideo_info.DDModes[i].dwHeight >= (DWORD)h && DDVideo_info.DDModes[mode].dwHeight < (DWORD)h) {
mode = i;
found_mode = true;
}
}
}
if (!found_mode) {
// we couldn't find a mode, error!
return false;
}
if (DDVideo_info.curmode != mode) {
// mode should contain the video mode.
hres = DDVideo_info.lpDD->SetDisplayMode(DDVideo_info.DDModes[mode].dwWidth, DDVideo_info.DDModes[mode].dwHeight,
DDVideo_info.DDModes[mode].ddpfPixelFormat.dwRGBBitCount);
ASSERT(DDVideo_info.DDModes[mode].ddpfPixelFormat.dwRGBBitCount >= BPP_16);
if (hres != DD_OK)
Error("Unable to set DirectDraw display mode. (%d)", LOWORD(hres));
}
DDVideo_info.curmode = mode;
// if not paged, then this is a single paged system (no lfb access, good for opengl)
if (!paged)
return true;
// now create surface, dependant on whether an extra page was requested
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if (paged) {
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = 1;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
} else {
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
}
hres = DDVideo_info.lpDD->CreateSurface(&ddsd, &DDVideo_info.lpDDSFront, NULL);
if (hres != DD_OK)
Error("Unable to capture DirectDraw display surface. (%d)", LOWORD(hres));
if (paged) {
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
hres = DDVideo_info.lpDDSFront->GetAttachedSurface(&ddscaps, &DDVideo_info.lpDDSBack);
if (hres != DD_OK) {
mprintf((0, "Unable to capture DirectDraw display back surface (%d)", LOWORD(hres)));
return false;
}
} else {
DDVideo_info.lpDDSBack = NULL;
}
return true;
}
// closes video mode for fs
void ddvidfs_CloseVideo() {
// uninitialize old screen
if (DDVideo_info.lpDDSFront) {
DDVideo_info.lpDDSFront->Release();
DDVideo_info.lpDDSFront = NULL;
DDVideo_info.lpDDSBack = NULL;
}
}
// retrieves screen information for fullscreen version
void ddvidfs_GetVideoProperties(int *w, int *h, int *color_depth) {
ASSERT(DDVideo_info.curmode > -1);
*w = DDVideo_info.DDModes[DDVideo_info.curmode].dwWidth;
*h = DDVideo_info.DDModes[DDVideo_info.curmode].dwHeight;
*color_depth = (int)DDVideo_info.DDModes[DDVideo_info.curmode].ddpfPixelFormat.dwRGBBitCount;
}
// flips screen if there's a back buffer
void ddvidfs_VideoFlip() {
if (DDVideo_info.lpDDSBack)
DDVideo_info.lpDDSFront->Flip(NULL, DDFLIP_WAIT);
}
// returns the directdraw object
uint ddvidfs_GetDirectDrawObject() { return (uint)DDVideo_info.lpDD; }
// DirectDraw Display mode enumeration callback
HRESULT WINAPI DDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext) {
if (DDVideo_info.nDDModes < VM_MAX_MODES) {
memcpy(&DDVideo_info.DDModes[DDVideo_info.nDDModes], lpDDSurfaceDesc, sizeof(DDSURFACEDESC));
DDVideo_info.nDDModes++;
}
return DDENUMRET_OK;
}