⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddcalls.c

📁 国外游戏开发者杂志1997年第九期配套代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *  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 + -