📄 ddcalls.c
字号:
/*
* Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
*
* File: ddcalls.c
*
* Manages DirectDraw objects needed for rendering. Part of D3DApp.
*
* D3DApp is a collection of helper functions for Direct3D applications.
* D3DApp consists of the following files:
* d3dapp.h Main D3DApp header to be included by application
* d3dappi.h Internal header
* d3dapp.c D3DApp functions seen by application.
* ddcalls.c All calls to DirectDraw objects except textures
* d3dcalls.c All calls to Direct3D objects except textures
* texture.c Texture loading and managing texture list
* misc.c Miscellaneous calls
*/
#include "d3dappi.h"
/***************************************************************************/
/* Direct Draw Enumeration */
/***************************************************************************/
typedef struct {
D3DAppDDDriver* driver;
int numdriver;
} DDEnumCallbackContext;
/*
* D3DAppIDDEnumCallback
* Callback function used during enumeration of DirectDraw drivers.
*/
BOOL FAR PASCAL D3DAppIDDEnumCallback(GUID FAR* lpGUID, LPSTR lpDriverDesc, LPSTR lpDriverName, LPVOID lpContext)
{
LPDIRECTDRAW lpDD;
DDCAPS DriverCaps, HELCaps;
DDEnumCallbackContext *context = (DDEnumCallbackContext*)lpContext;
D3DAppDDDriver* driver = &context->driver[context->numdriver];
/*
* Create the DirectDraw device using this driver. If it fails,
* just move on to the next driver.
*/
if (FAILED(DirectDrawCreate(lpGUID, &lpDD, NULL))) {
return DDENUMRET_OK;
}
/*
* Get the capabilities of this DirectDraw driver. If it fails,
* just move on to the next driver.
*/
memset(&DriverCaps, 0, sizeof(DDCAPS));
DriverCaps.dwSize = sizeof(DDCAPS);
memset(&HELCaps, 0, sizeof(DDCAPS));
HELCaps.dwSize = sizeof(DDCAPS);
if (FAILED(lpDD->lpVtbl->GetCaps(lpDD, &DriverCaps, &HELCaps))) {
lpDD->lpVtbl->Release(lpDD);
return DDENUMRET_OK;
}
if (lpGUID && (DriverCaps.dwCaps & DDCAPS_3D)) {
/*
* We have found a secondary 3d hardware device. Return the DD object
* and stop enumeration.
*/
memcpy(&driver->Guid, lpGUID, sizeof(GUID));
memcpy(&driver->HWCaps, &DriverCaps, sizeof(DDCAPS));
lstrcpy(driver->Name, lpDriverName);
driver->bIsPrimary = FALSE;
context->numdriver++;
} else {
/*
* It's the primary, fill in some fields.
*/
memset(&driver->Guid, 0, sizeof(GUID));
memcpy(&driver->HWCaps, &DriverCaps, sizeof(DDCAPS));
lstrcpy(driver->Name, "Primary Device");
driver->bIsPrimary = TRUE;
context->numdriver++;
}
lpDD->lpVtbl->Release(lpDD);
if (context->numdriver >= D3DAPP_MAXDDDRIVERS)
return DDENUMRET_CANCEL;
else
return DDENUMRET_OK;
}
/*
* D3DAppIEnumDDDevices
* Enumerate all 3D capable devices and the primary display, filling in
* the driver information variables. lpDriver must point to a region
* with enough room for the maximum DD drivers.
*/
BOOL
D3DAppIEnumDDDevices(int* NumDriver, D3DAppDDDriver* lpDriver)
{
DDEnumCallbackContext context;
context.numdriver = 0;
context.driver = lpDriver;
LastError = DirectDrawEnumerate(D3DAppIDDEnumCallback, &context);
if (LastError != DD_OK) {
D3DAppISetErrorString("DirectDrawEnumerate failed.\n%s",
D3DAppErrorToString(LastError));
return FALSE;
}
*NumDriver = context.numdriver;
return TRUE;
}
/***************************************************************************/
/* Direct Draw Creation */
/***************************************************************************/
/*
* D3DAppICreateDD
* Creates the DirectDraw device and saves the current palette.
* It is assumed that a 3D capable secondary DD driver is not the
* primary device and hence cannot operate in a window (ie it's a
* fullscreen only device displaying on a second monitor). Valid flags:
* D3DAPP_ONLYDDEMULATION Always use the DirectDraw HEL
*/
BOOL
D3DAppICreateDD(DWORD flags, LPGUID lpGuid)
{
HDC hdc;
int i;
LPDIRECTDRAW lpDD = NULL;
if (flags & D3DAPP_ONLYDDEMULATION)
lpGuid = NULL;
if (!lpGuid)
d3dappi.bIsPrimary = TRUE;
else
d3dappi.bIsPrimary = FALSE;
LastError = DirectDrawCreate(lpGuid, &d3dappi.lpDD, NULL);
if (LastError != DD_OK) {
D3DAppISetErrorString("DirectDrawCreate failed.\n%s",
D3DAppErrorToString(LastError));
return FALSE;
}
/*
* Save the original palette for when we are paused. Just in case we
* start in a fullscreen mode, put them in ppe.
*/
hdc = GetDC(NULL);
GetSystemPaletteEntries(hdc, 0, (1 << 8),
(LPPALETTEENTRY)(&Originalppe[0]));
for (i = 0; i < 256; i++)
ppe[i] = Originalppe[i];
ReleaseDC(NULL, hdc);
return TRUE;
}
/***************************************************************************/
/* Enumerating the display modes */
/***************************************************************************/
/*
* EnumDisplayModesCallback
* Callback to save the display mode information.
*/
static HRESULT
CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID lpContext)
{
/*
* Very large resolutions cause problems on some hardware. They are also
* not very useful for real-time rendering. We have chosen to disable
* them by not reporting them as available.
*/
if (pddsd->dwWidth > 1024 || pddsd->dwHeight > 768)
return DDENUMRET_OK;
/*
* Save this mode at the end of the mode array and increment mode count
*/
d3dappi.Mode[d3dappi.NumModes].w = pddsd->dwWidth;
d3dappi.Mode[d3dappi.NumModes].h = pddsd->dwHeight;
d3dappi.Mode[d3dappi.NumModes].bpp = pddsd->ddpfPixelFormat.dwRGBBitCount;
d3dappi.Mode[d3dappi.NumModes].bThisDriverCanDo = FALSE;
d3dappi.NumModes++;
if (d3dappi.NumModes == D3DAPP_MAXMODES)
return DDENUMRET_CANCEL;
else
return DDENUMRET_OK;
}
/*
* CompareModes
* Compare two display modes during sorting. Modes are sorted by depth and
* then resolution.
*/
static int
_cdecl CompareModes(const void* element1, const void* element2) {
D3DAppMode *lpMode1, *lpMode2;
lpMode1 = (D3DAppMode*)element1;
lpMode2 = (D3DAppMode*)element2;
if (lpMode1->bpp > lpMode2->bpp)
return -1;
else if (lpMode2->bpp > lpMode1->bpp)
return 1;
else if (lpMode1->w > lpMode2->w)
return -1;
else if (lpMode2->w > lpMode1->w)
return 1;
else if (lpMode1->h > lpMode2->h)
return -1;
else if (lpMode2->h > lpMode1->h)
return 1;
else
return 0;
}
/*
* EnumerateDisplayModes
* Generates the list of available display modes.
*/
BOOL
D3DAppIEnumDisplayModes(void)
{
int i;
/*
* Get a list of available display modes from DirectDraw
*/
d3dappi.NumModes = 0;
LastError = d3dappi.lpDD->lpVtbl->EnumDisplayModes(d3dappi.lpDD, 0, NULL,
0, EnumDisplayModesCallback);
if(LastError != DD_OK ) {
D3DAppISetErrorString("EnumDisplayModes failed.\n%s",
D3DAppErrorToString(LastError));
d3dappi.NumModes = 0;
return FALSE;
}
/*
* Sort the list of display modes
*/
qsort((void *)&d3dappi.Mode[0], (size_t)d3dappi.NumModes, sizeof(D3DAppMode),
CompareModes);
/*
* Pick a default display mode. 640x480x16 is a very good mode for
* rendering, so choose it over all others. Otherwise, just take the
* first one. This selection may be overriden later if a driver is
* created which cannot render in this mode.
*/
d3dappi.CurrMode = 0;
for (i = 0; i < d3dappi.NumModes; i++) {
if (d3dappi.Mode[i].w == 640 && d3dappi.Mode[i].h == 480 &&
d3dappi.Mode[i].bpp == 16)
d3dappi.CurrMode = i;
}
memcpy(&d3dappi.ThisMode, &d3dappi.Mode[d3dappi.CurrMode],
sizeof(D3DAppMode));
return TRUE;
}
/***************************************************************************/
/* Creating Front and Back Buffers (and misc surf funcs) */
/***************************************************************************/
/*
* D3DAppICreateSurface
* Create a DirectDraw Surface of the given description. Using this function
* ensures that all surfaces end up in system memory if that option was set.
* Returns the result of the CreateSurface call.
*/
HRESULT
D3DAppICreateSurface(LPDDSURFACEDESC lpDDSurfDesc,
LPDIRECTDRAWSURFACE FAR *lpDDSurface) {
HRESULT result;
if (d3dappi.bOnlySystemMemory)
lpDDSurfDesc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
result = d3dappi.lpDD->lpVtbl->CreateSurface(d3dappi.lpDD, lpDDSurfDesc,
lpDDSurface, NULL);
return result;
}
/*
* D3DAppIGetSurfDesc
* Get the description of the given surface. Returns the result of the
* GetSurfaceDesc call.
*/
HRESULT
D3DAppIGetSurfDesc(LPDDSURFACEDESC lpDDSurfDesc,LPDIRECTDRAWSURFACE lpDDSurf)
{
HRESULT result;
memset(lpDDSurfDesc, 0, sizeof(DDSURFACEDESC));
lpDDSurfDesc->dwSize = sizeof(DDSURFACEDESC);
result = lpDDSurf->lpVtbl->GetSurfaceDesc(lpDDSurf, lpDDSurfDesc);
return result;
}
/*
* D3DAppICreateBuffers
* Creates the front and back buffers for the window or fullscreen case
* depending on the bFullscreen flag. In the window case, bpp is ignored.
*/
BOOL
D3DAppICreateBuffers(HWND hwnd, int w, int h, int bpp, BOOL bFullscreen, BOOL bIsHardware)
{
DDSURFACEDESC ddsd;
DDSCAPS ddscaps;
/*
* Release any old objects that might be lying around. This should have
* already been taken care of, but just in case...
*/
RELEASE(lpClipper);
RELEASE(d3dappi.lpBackBuffer);
RELEASE(d3dappi.lpFrontBuffer);
/*
* The size of the buffers is going to be w x h, so record it now
*/
if (w < D3DAPP_WINDOWMINIMUM)
w = D3DAPP_WINDOWMINIMUM;
if (h < D3DAPP_WINDOWMINIMUM)
h = D3DAPP_WINDOWMINIMUM;
szBuffers.cx = w;
szBuffers.cy = h;
if (bFullscreen) {
/*
* Create a complex flipping surface for fullscreen mode with one
* back buffer.
*/
memset(&ddsd,0,sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
if (bIsHardware)
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
LastError = D3DAppICreateSurface(&ddsd, &d3dappi.lpFrontBuffer);
if(LastError != DD_OK) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -