MISC.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:17k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
- *
- * File: misc.c
- *
- * Miscellaneous functions not involving DD and D3D. 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"
- /***************************************************************************/
- /* Setting Defaults */
- /***************************************************************************/
- /*
- * D3DAppISetDefaults
- * Set all the global variables to their default values. Do not reset the
- * image files.
- */
- void
- D3DAppISetDefaults(void)
- {
- int n;
- char backup[D3DAPP_MAXTEXTURES][50];
- n = d3dappi.NumTextures;
- memcpy(&backup[0][0], &d3dappi.ImageFile[0][0], 50 * D3DAPP_MAXTEXTURES);
- ZEROMEM(d3dappi);
- memcpy(&d3dappi.ImageFile[0][0], &backup[0][0], 50 * D3DAPP_MAXTEXTURES);
- d3dappi.NumTextures = n;
- d3dappi.bAppActive = TRUE;
- ZEROMEM(d3dapprs);
- d3dapprs.bZBufferOn = TRUE;
- d3dapprs.bPerspCorrect = FALSE;
- d3dapprs.ShadeMode = D3DSHADE_GOURAUD;
- d3dapprs.TextureFilter = D3DFILTER_NEAREST;
- d3dapprs.TextureBlend = D3DTBLEND_MODULATE;
- d3dapprs.FillMode = D3DFILL_SOLID;
- d3dapprs.bDithering = FALSE;
- d3dapprs.bSpecular = TRUE;
- d3dapprs.bAntialiasing = FALSE;
- d3dapprs.bFogEnabled = FALSE;
- d3dapprs.FogColor = RGB_MAKE(0, 0, 0);
- d3dapprs.FogMode = D3DFOG_LINEAR;
- d3dapprs.FogStart = D3DVAL(6.0);
- d3dapprs.FogEnd = D3DVAL(11.0);
- lpClipper = NULL;
- lpPalette = NULL;
- bPrimaryPalettized = FALSE;
- bPaletteActivate = FALSE;
- bIgnoreWM_SIZE = FALSE;
- ZEROMEM(ppe);
- ZEROMEM(Originalppe);
- LastError = DD_OK;
- ZEROMEM(LastErrorString);
- D3DDeviceDestroyCallback = NULL;
- D3DDeviceDestroyCallbackContext = NULL;
- D3DDeviceCreateCallback = NULL;
- D3DDeviceCreateCallbackContext = NULL;
- }
- /***************************************************************************/
- /* Calling Device Create And Destroy Callbacks */
- /***************************************************************************/
- BOOL
- D3DAppICallDeviceDestroyCallback(void)
- {
- if (D3DDeviceDestroyCallback) {
- if (CallbackRefCount) {
- --CallbackRefCount;
- return (D3DDeviceDestroyCallback)(D3DDeviceDestroyCallbackContext);
- }
- }
- return TRUE;
- }
- BOOL
- D3DAppICallDeviceCreateCallback(int w, int h)
- {
- if (D3DDeviceCreateCallback) {
- ++CallbackRefCount;
- return (D3DDeviceCreateCallback)(w, h, &d3dappi.lpD3DViewport,
- D3DDeviceCreateCallbackContext);
- }
- return TRUE;
- }
- /***************************************************************************/
- /* Choosing and verifying the driver and display mode */
- /***************************************************************************/
- /*
- * D3DAppIPickDriver
- * Choose a driver from the list of available drivers which can render to one
- * of the given depths. Hardware is prefered. Mono-lighting drivers are
- * prefered over RGB.
- */
- BOOL
- D3DAppIPickDriver(int* driver, DWORD depths)
- {
- int i, j;
- j = 0;
- for (i = 0; i < d3dappi.NumDrivers; i++)
- if (d3dappi.Driver[i].Desc.dwDeviceRenderBitDepth & depths)
- break;
- if (i >= d3dappi.NumDrivers) {
- *driver = D3DAPP_BOGUS;
- return TRUE;
- }
- j = i;
- for (i = 0; i < d3dappi.NumDrivers; i++) {
- if (d3dappi.Driver[i].Desc.dwDeviceRenderBitDepth & depths) {
- if (d3dappi.Driver[i].bIsHardware &&
- !d3dappi.Driver[j].bIsHardware)
- j = i;
- else if (d3dappi.Driver[i].bIsHardware ==
- d3dappi.Driver[j].bIsHardware) {
- if (d3dappi.Driver[i].Desc.dcmColorModel & D3DCOLOR_MONO &&
- !(d3dappi.Driver[j].Desc.dcmColorModel & D3DCOLOR_MONO))
- j = i;
- }
- }
- }
- if (j >= d3dappi.NumDrivers)
- *driver = D3DAPP_BOGUS;
- else
- *driver = j;
- return TRUE;
- }
- /*
- * D3DAppIFilterDisplayModes
- * Set the bThisDriverCanDo flag for each display mode if the given driver
- * can render in that depth. Also checks to make sure there is enough
- * total video memory for front/back/z-buffer in video memory if it's a
- * hardware device.
- */
- BOOL
- D3DAppIFilterDisplayModes(int driver)
- {
- int i;
- DWORD depths = d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth;
- for (i = 0; i < d3dappi.NumModes; i++) {
- d3dappi.Mode[i].bThisDriverCanDo = FALSE;
- if (!(D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths))
- continue;
- d3dappi.Mode[i].bThisDriverCanDo = TRUE;
- }
- d3dappi.ThisMode.bThisDriverCanDo =
- d3dappi.Mode[d3dappi.CurrMode].bThisDriverCanDo;
- return TRUE;
- }
- /*
- * D3DAppIPickDisplayMode
- * Pick a display mode of one of the given depths. 640x480x16 is prefered.
- */
- BOOL
- D3DAppIPickDisplayMode(int *mode, DWORD depths)
- {
- int i, j;
- for (i = 0; i < d3dappi.NumModes; i++)
- if (D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths)
- break;
- j = i;
- for (; i < d3dappi.NumModes; i++) {
- if (!(D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths))
- continue;
- if (d3dappi.Mode[i].w == 640 && d3dappi.Mode[i].h == 480 &&
- d3dappi.Mode[i].bpp == 16) {
- j = i;
- break;
- }
- }
- if (j >= d3dappi.NumModes)
- *mode = D3DAPP_BOGUS;
- else
- *mode = j;
- return TRUE;
- }
- /*
- * D3DAppIVerifyDriverAndMode
- * Verifies the selected driver and mode combination. If the driver is
- * specified, the mode will be changed to accomodate the driver if it's not
- * compatible. If the driver is not specified, one will be selected which is
- * compatible with the specified mode. If neither are specified, a suitable
- * pair will be returned.
- */
- BOOL
- D3DAppIVerifyDriverAndMode(int* lpdriver, int* lpmode)
- {
- DWORD depths;
- int driver, mode, i;
- driver = *lpdriver; mode = *lpmode;
- if (mode == D3DAPP_USEWINDOW && !d3dappi.bIsPrimary) {
- D3DAppISetErrorString("Cannot render to a window when the DirectDraw device is not the primary.n");
- goto exit_with_error;
- }
- /*
- * If I've been ask to choose a driver, choose one which is compatible
- * with the specified mode.
- */
- if (driver == D3DAPP_YOUDECIDE) {
- if (mode == D3DAPP_USEWINDOW) {
- /*
- * I must find a driver for this display depth
- */
- depths = D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp);
- ATTEMPT(D3DAppIPickDriver(&driver, depths));
- if (driver == D3DAPP_BOGUS) {
- D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the current display depth.n");
- goto exit_with_error;
- }
- /*
- * I don't need to go through the mode selection since I've
- * verified it here
- */
- goto ret_ok;
- } else if (mode == D3DAPP_YOUDECIDE) {
- /*
- * I'm free to choose any driver which can use even one
- * supported depth
- */
- if (d3dappi.bIsPrimary)
- depths = D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp);
- else
- depths = 0;
- for (i = 0; i < d3dappi.NumModes; i++)
- depths |= D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp);
- ATTEMPT(D3DAppIPickDriver(&driver, depths));
- if (driver == D3DAPP_BOGUS) {
- D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the current display depth or any supported fullscreen mode.n");
- goto exit_with_error;
- }
- /*
- * The mode will be chosen in the next section
- */
- } else {
- /*
- * Must pick a driver which uses the given mode depth
- */
- ATTEMPT(D3DAppIPickDriver(&driver,
- D3DAppIBPPToDDBD(d3dappi.Mode[mode].bpp)));
- if (driver == D3DAPP_BOGUS) {
- D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the specified fullscreen mode.n");
- goto exit_with_error;
- }
- /*
- * I don't need to go through the mode selection since I've
- * verified it here
- */
- goto ret_ok;
- }
- }
- /*
- * At this stage, I have a driver I want to match the mode to.
- */
- if (mode == D3DAPP_YOUDECIDE) {
- /*
- * If it's my choice, I prefer windowed over fullscreen
- */
- if (d3dappi.bIsPrimary) {
- if (D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp) &
- d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth) {
- mode = D3DAPP_USEWINDOW;
- goto ret_ok;
- }
- }
- /*
- * Either this is not a primary DD device or the driver cannot use
- * the Windows display depth
- */
- ATTEMPT(D3DAppIPickDisplayMode(&mode,
- d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth));
- if (mode == D3DAPP_BOGUS) {
- D3DAppISetErrorString("The selected D3D device driver is not compatible with the current display depth or any supported fullscreen modes.n");
- goto exit_with_error;
- }
- goto ret_ok;
- } else if (mode == D3DAPP_USEWINDOW) {
- /*
- * Check to see if this driver can use the Windows display depth
- */
- if (D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp) &
- d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth) {
- goto ret_ok;
- } else {
- /*
- * Since it cannot, call this function again to choose any
- * display mode which is compatible
- */
- mode = D3DAPP_YOUDECIDE;
- ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode));
- if (driver == D3DAPP_BOGUS)
- goto exit_with_error;
- goto ret_ok;
- }
- } else {
- /*
- * Check to see if this driver can use the specified fullscreen mode
- */
- if (D3DAppIBPPToDDBD(d3dappi.Mode[mode].bpp) &
- d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth) {
- goto ret_ok;
- } else {
- /*
- * Since it cannot, call this function again to choose any
- * display mode which is compatible
- */
- mode = D3DAPP_YOUDECIDE;
- ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode));
- if (driver == D3DAPP_BOGUS)
- goto exit_with_error;
- goto ret_ok;
- }
- }
- ret_ok:
- *lpdriver = driver; *lpmode = mode;
- return TRUE;
- exit_with_error:
- return FALSE;
- }
- /***************************************************************************/
- /* Dirty Rectangle Functions */
- /***************************************************************************/
- /*
- * D3DAppIValidateDirtyRects
- * Set the dirty rectangles for the front and back buffers to the entire
- * client size.
- */
- void
- D3DAppIValidateDirtyRects(void)
- {
- NumDirtyClientRects = 1; NumDirtyBackRects = 1; NumDirtyZRects = 1;
- SetRect((LPRECT)&DirtyClient[0], 0, 0, d3dappi.szClient.cx,
- d3dappi.szClient.cy);
- SetRect((LPRECT)&DirtyBack[0], 0, 0, d3dappi.szClient.cx,
- d3dappi.szClient.cy);
- SetRect((LPRECT)&DirtyZ[0], 0, 0, d3dappi.szClient.cx,
- d3dappi.szClient.cy);
- }
- /*
- * D3DAppICopyRectList
- * Copy a list of rectangles to another
- */
- void
- D3DAppICopyRectList(int* dstnum, LPD3DRECT dst, int srcnum, LPD3DRECT src)
- {
- int i;
- for (i = 0; i < srcnum; i++)
- dst[i] = src[i];
- *dstnum = srcnum;
- }
- /*
- * MERGE macro
- * Set first rectangle to be the smallest rectangle containing both rects
- */
- #undef MERGE
- #define MERGE(rc1, rc2)
- do {
- if (rc2.x1 < rc1.x1) rc1.x1 = rc2.x1;
- if (rc2.y1 < rc1.y1) rc1.y1 = rc2.y1;
- if (rc2.x2 > rc1.x2) rc1.x2 = rc2.x2;
- if (rc2.y2 > rc1.y2) rc1.y2 = rc2.y2;
- } while(0)
- /*
- * D3DAppIMergeRectLists
- * Merge two lists of rectangles to create another list of rectangles. The
- * merged list of rectangles covers all the area of the original two with NO
- * OVERLAPPING amongst it's rectangles.
- */
- void
- D3DAppIMergeRectLists(int* dstnum, LPD3DRECT dst, int src1num, LPD3DRECT src1,
- int src2num, LPD3DRECT src2)
- {
- LPD3DRECT rc;
- int* isvalid;
- int num, i, j, intersect;
- rc = (LPD3DRECT)malloc(sizeof(D3DRECT) * D3DAPP_MAXCLEARRECTS * 2);
- memset(rc, 0, sizeof(D3DRECT) * D3DAPP_MAXCLEARRECTS * 2);
- isvalid = (int*)malloc(sizeof(int) * D3DAPP_MAXCLEARRECTS * 2);
- memset(isvalid, 0, sizeof(int) * D3DAPP_MAXCLEARRECTS * 2);
- for (i = 0; i < src1num; i++) {
- memcpy(&rc[i], &src1[i], sizeof(D3DRECT));
- if ((rc[i].x1 == 0 && rc[i].x2 == 0) ||
- (rc[i].y1 == 0 && rc[i].y2 == 0))
- isvalid[i] = 0;
- else if (rc[i].x1 <= rc[i].x2 && rc[i].y1 <= rc[i].y2)
- isvalid[i] = 1;
- else
- isvalid[i] = 0;
- }
- for (i = 0; i < src2num; i++) {
- memcpy(&rc[i + src1num], &src2[i], sizeof(D3DRECT));
- if (rc[i + src1num].x1 <= rc[i + src1num].x2 &&
- rc[i + src1num].y1 <= rc[i + src1num].y2)
- isvalid[i + src1num] = 1;
- else
- isvalid[i + src1num] = 0;
- }
- num = src1num + src2num;
- for (i = 0; i < num - 1; i++) {
- if (!isvalid[i]) continue;
- j = i + 1;
- do {
- intersect = 0;
- for (; j < num; j++) {
- if (j != i && isvalid[j]) {
- if (rc[i].x1 < rc[j].x1) {
- if (rc[i].x2 < rc[j].x1)
- continue;
- } else {
- if (rc[j].x2 < rc[i].x1)
- continue;
- }
- if (rc[i].y1 < rc[j].y1) {
- if (rc[i].y2 < rc[j].y1)
- continue;
- } else {
- if (rc[j].y2 < rc[i].y1)
- continue;
- }
- MERGE(rc[i], rc[j]);
- isvalid[j] = 0;
- j = 0; intersect = 1;
- break;
- }
- }
- } while(intersect);
- }
- for (i = 0, j = 0; i < num; i++)
- if (isvalid[i]) ++j;
- if (j > D3DAPP_MAXCLEARRECTS) {
- for (i = 0; i < num; i++)
- if (isvalid[i]) break;
- if (i < num) {
- *dstnum = 1;
- dst[0] = rc[i];
- for (; i < num; i++) {
- if (isvalid[i]) {
- MERGE(dst[0], rc[i]);
- }
- }
- } else {
- *dstnum = 0;
- }
- } else {
- for (i = 0, j = 0; i < num; i++) {
- if (isvalid[i]) {
- memcpy(&dst[j], &rc[i], sizeof(D3DRECT));
- ++j;
- }
- }
- *dstnum = j;
- }
- free(rc);
- free(isvalid);
- }
- /***************************************************************************/
- /* Getting and Setting Window Attribs */
- /***************************************************************************/
- /*
- * D3DAppISetClientSize
- * Set the client size of the given window. A WM_SIZE message is generated,
- * but ignored.
- */
- void
- D3DAppISetClientSize(HWND hwnd, int w, int h, BOOL bReturnFromFullscreen)
- {
- RECT rc;
- bIgnoreWM_SIZE = TRUE;
- if (bReturnFromFullscreen) {
- SetRect(&rc, 0, 0, w, h);
- AdjustWindowRectEx(&rc, GetWindowLong(hwnd, GWL_STYLE),
- GetMenu(hwnd) != NULL,
- GetWindowLong(hwnd, GWL_EXSTYLE));
- SetWindowPos(hwnd, NULL, 0, 0, rc.right-rc.left,
- rc.bottom-rc.top,
- SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
- SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
- } else {
- /*
- * This is the only way to set the client size correctly if the menu
- * is stacked, so do it unless we are returning from a fullscreen
- * mode.
- */
- SendMessage(hwnd, WM_SIZE, SIZE_RESTORED, w + h << 16);
- GetWindowRect(hwnd, &rc);
- SetWindowPos(hwnd, NULL, 0, 0, rc.right-rc.left,
- rc.bottom-rc.top,
- SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
- SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
- }
- bIgnoreWM_SIZE = FALSE;
- d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0;
- ClientToScreen(hwnd, &d3dappi.pClientOnPrimary);
- d3dappi.szClient.cx = w; d3dappi.szClient.cy = h;
- }
- /*
- * D3DAppIGetClientWin
- * Gets the client window size and sets it in the D3DAppInfo structure
- */
- void
- D3DAppIGetClientWin(HWND hwnd)
- {
- RECT rc;
- if (!d3dappi.bFullscreen) {
- d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0;
- ClientToScreen(hwnd, &d3dappi.pClientOnPrimary);
- GetClientRect(hwnd, &rc);
- d3dappi.szClient.cx = rc.right;
- d3dappi.szClient.cy = rc.bottom;
- } else {
- /*
- * In the fullscreen case, we must be careful because if the window
- * frame has been drawn, the client size has shrunk and this can
- * cause problems, so it's best to report the entire screen.
- */
- d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0;
- d3dappi.szClient.cx = d3dappi.ThisMode.w;
- d3dappi.szClient.cy = d3dappi.ThisMode.h;
- }
- }
- /***************************************************************************/
- /* Error reporting */
- /***************************************************************************/
- /*
- * D3DAppISetErrorString
- * Set the global variable which records the last error string.
- */
- void
- D3DAppISetErrorString( LPSTR fmt, ... )
- {
- char buff[256];
- va_list va;
- buff[0] = 0;
- va_start( va, fmt );
- wvsprintf(&buff[0], fmt, va);
- va_end( va );
- lstrcat(buff, "rn");
- lstrcpy(LastErrorString, buff);
- }
- /* dpf
- * Debug printf. Very useful for fullscreen exclusive mode or when surfaces
- * are in video memory.
- */
- void __cdecl
- dpf( LPSTR fmt, ... )
- {
- char buff[256];
- va_list va;
- lstrcpy(buff, "D3DApp: ");
- va_start( va, fmt );
- wvsprintf(&buff[lstrlen(buff)], fmt, va);
- va_end( va );
- lstrcat(buff, "rn");
- OutputDebugString(buff);
- }