📄 d3dmain.cpp
字号:
/**************************************************************************
Mixed Rendering
**************************************************************************/
/***************************************************************
*
* This program has been developed by Intel Corporation.
* You have Intel's permission to incorporate this code
* into your product, royalty free. Intel has various
* intellectual property rights which it may assert under
* certain circumstances, such as if another manufacturer's
* processor mis-identifies itself as being "GenuineIntel"
* when the CPUID instruction is executed.
*
* Intel specifically disclaims all warranties, express or
* implied, and all liability, including consequential and
* other indirect damages, for the use of this code,
* including liability for infringement of any proprietary
* rights, and including the warranties of merchantability
* and fitness for a particular purpose. Intel does not
* assume any responsibility for any errors which may
* appear in this code nor any responsibility to update it.
*
* * Other brands and names are the property of their respective
* owners.
*
* Copyright (c) 1995, Intel Corporation. All rights reserved.
***************************************************************/
/*
* Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
*
* File: d3dmain.cpp
*
* Each of the Direct3D samples must be linked with this file. It contains
* the code which allows them to run in the Windows environment.
*
* A window is created using d3dmain.res which allows the user to select the
* Direct3D driver to use and change the render options. The D3DApp
* collection of functions is used to initialize DirectDraw, Direct3D and
* keep surfaces and D3D devices available for rendering.
*
* Frame rate and a screen mode information buffer is Blt'ed to the screen
* by functions in stats.cpp.
*
* Each sample is executed through the functions: InitScene, InitView,
* RenderScene, ReleaseView, ReleaseScene and OverrideDefaults, as described
* in d3ddemo.h. Samples can also read mouse and keyboard input via
* SetMouseCallback and SetKeyboardCallback.
*/
#include "d3dmain.h"
#include "main.h"
#include "ddutil.h"
#include "d3dappi.h"
/*
* GLOBAL VARIABLES
*/
// These surfaces are used as the destination for the SW rendering
LPDIRECTDRAW lpDD_SW = NULL;
HANDLE SW_Win;
int compositeMethod = TEXTUREMAP_COMPOSITE ;
// Texture generated from the SW buffer after each frame
LPDIRECT3DTEXTURE lpActiveTexture = NULL;
LPDIRECTDRAWSURFACE lpDDTextureSurfaceSPOT = NULL;
LPDIRECT3DTEXTURE lpSPOTTexture = NULL;
D3DTEXTUREHANDLE SPOTTextureHandle;
LPDIRECTDRAWSURFACE lpDDActiveSurfaceSystem = NULL;
LPDIRECTDRAWSURFACE lpDDDevelopSurfaceSystem = NULL;
LPDIRECTDRAWSURFACE lpDDTempSurfaceSystem = NULL;
LPDIRECTDRAWSURFACE lpDDSurfaceSystem = NULL;
LPDIRECTDRAWSURFACE lpDDZBufferSystem = NULL;
HANDLE eventHandle;
HANDLE compositeHandle;
HANDLE th;
DWORD dwThreadId;
int countHW=0, countSW=0;
D3DAppInfo* d3dapp; /* Pointer to read only collection of DD and D3D
objects maintained by D3DApp */
d3dmainglobals myglobs; /* collection of global variables */
BOOL(*MouseHandler)(UINT, WPARAM, LPARAM); /* sample's function which traps
mouse input */
BOOL(*KeyboardHandler)(UINT, WPARAM, LPARAM); /* sample's functions which traps
keyboard input */
/*
* INTERNAL FUNCTION PROTOTYPES
*/
static BOOL AppInit(HINSTANCE hInstance, LPSTR lpCmdLine);
static BOOL CreateD3DApp(LPSTR lpCmdLine);
static BOOL BeforeDeviceDestroyed(LPVOID lpContext);
static BOOL AfterDeviceCreated(int w, int h, LPDIRECT3DVIEWPORT* lpViewport,
LPVOID lpContext);
void CleanUpAndPostQuit(void);
static void InitGlobals(void);
static BOOL AppPause(BOOL f);
void ReportD3DAppError(void);
static BOOL RenderLoop(void);
static BOOL RestoreSurfaces();
long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam );
/****************************************************************************/
/* WinMain */
/****************************************************************************/
/*
* Initializes the application then enters a message loop which calls sample's
* RenderScene until a quit message is received.
*/
int PASCAL
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
int failcount = 0; /* number of times RenderLoop has failed */
MSG msg;
HACCEL hAccelApp;
hPrevInstance;
/*
* Create the window and initialize all objects needed to begin rendering
*/
if(!AppInit(hInstance, lpCmdLine))
return FALSE;
hAccelApp = LoadAccelerators(hInstance, "AppAccel");
while (!myglobs.bQuit) {
/*
* Monitor the message queue until there are no pressing
* messages
*/
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
CleanUpAndPostQuit();
break;
}
if (!myglobs.hWndMain || !TranslateAccelerator(myglobs.hWndMain,
hAccelApp, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/*
* If the app is not minimized, not about to quit, not paused, either the
* active fullscreen app or in a window and D3D has been initialized,
* we can render
*/
} else if (d3dapp->bRenderingIsOK && !d3dapp->bMinimized
&& !d3dapp->bPaused && !myglobs.bQuit
&& (d3dapp->bAppActive || !d3dapp->bFullscreen)) {
/*
* If were are not in single step mode or if we are and the
* bDrawAFrame flag is set, render one frame
*/
if (!(myglobs.bSingleStepMode && !myglobs.bDrawAFrame)) {
/*
* Attempt to render a frame, if it fails, take a note. If
* rendering fails more than twice, abort execution.
*/
if (!RenderLoop()) {
++failcount;
if (failcount == 3) {
Msg("Rendering has failed too many times. Aborting execution.\n");
CleanUpAndPostQuit();
break;
}
}
}
/*
* Reset the bDrawAFrame flag if we are in single step mode
*/
if (myglobs.bSingleStepMode)
myglobs.bDrawAFrame = FALSE;
} else {
WaitMessage();
}
}
DestroyWindow(myglobs.hWndMain);
return msg.wParam;
}
/**********************************************************************************/
/* This is a separate thread and continues in an infinite loop until process is ready
/* to exit (and will be killed by the main thread .
/* For each frame the following operations are executed :
1. Clean the Develop and the Z-buffer (using DDraw Blt() )
2. render the SW scene to the develop buffer
3. synchornize with the HW thread :
a: SIGNAL that SW is ready
b: WAIT for Composite event (The HW actually only switched the buffers now)
c: RESET Composite event
*/
/**********************************************************************************/
void DrawFrameSW(void)
{
HRESULT ddrval;
BOOL bResult;
DDBLTFX ddbltfx;
while (TRUE){
// Erase the system memory buffer
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(DDBLTFX);
ddbltfx.dwFillColor = 0;
if(compositeMethod == TEXTUREMAP_COMPOSITE )
ddrval = lpDDDevelopSurfaceSystem->Blt( NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
else // compositeMethod == BLT_COMPOSITE
ddrval = lpDDSurfaceSystem->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
if (ddrval != DD_OK)
Msg("Clearing the SW Develop buffer failed.\0", ddrval);
// Erase the associated Z-buffer
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(DDBLTFX);
ddbltfx.dwFillDepth = 0x7fff;
ddrval = lpDDZBufferSystem->Blt(NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &ddbltfx);
if (ddrval != DD_OK)
Msg("Clearing the SW Zbuffer failed.\0", ddrval);
// Start to render the SW scene
countSW++;
// render the SW scene
if(compositeMethod == TEXTUREMAP_COMPOSITE )
bResult = RenderSWScene(lpDDDevelopSurfaceSystem );
else // compositeMethod == BLT_COMPOSITE
bResult = RenderSWScene(lpDDSurfaceSystem);
if (bResult == FALSE)
Msg("Call to Software Render Scene failed.\0", 0);
// SIGNAL that SW is ready
SetEvent(eventHandle);
// Suspend SW thread - until SW output is consumed into composite
// the 'consuming' is dependent of the Blit method .
WaitForSingleObject(compositeHandle,1000);
ResetEvent(compositeHandle);
}; // loop indefinitely
}
/****************************************************************************/
/* D3DApp Initialization and callback functions */
/****************************************************************************/
/*
* AppInit
* Creates the window and initializes all objects necessary to begin rendering
*/
static BOOL
AppInit(HINSTANCE hInstance, LPSTR lpCmdLine)
{
WNDCLASS wc;
HMENU hmenu;
int i;
/*
* Initialize the global variables
*/
InitGlobals();
myglobs.hInstApp = hInstance;
myglobs.lpCmdLine = lpCmdLine;
/*
* Enumerate the DD drivers
*/
if (!D3DAppEnumerateDDDevices(&myglobs.NumDDDrivers, &myglobs.DDDriver[0])) {
ReportD3DAppError();
return FALSE;
}
/*
* Choose the last device enumerated which will probably be secondary 3d hardware.
*/
myglobs.CurrDDDriver = myglobs.NumDDDrivers - 1;
/*
* Register the window class
*/
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance, "AppIcon");
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = "AppMenu";
wc.lpszClassName = "Example";
if (!RegisterClass(&wc))
return FALSE;
/*
* Create a window with some default settings that may change
*/
myglobs.hWndMain = CreateWindowEx(
WS_EX_APPWINDOW,
"Example",
"D3D Example",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
WS_THICKFRAME | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
START_WIN_SIZE, START_WIN_SIZE,
NULL, /* parent window */
NULL, /* menu handle */
hInstance, /* program handle */
NULL); /* create parms */
if (!myglobs.hWndMain){
Msg("CreateWindowEx failed");
return FALSE;
}
/*
* Display the window
*/
ShowWindow(myglobs.hWndMain, SW_SHOWNORMAL);
UpdateWindow(myglobs.hWndMain);
#if 0
// DEBUG - helps with fullscreen exclusive debugs!
ShowWindow(myglobs.hWndMain, SW_HIDE);
#endif
#if 1 // I don't want users to be able to change drivers
/*
* Add the list of DD drivers D3DApp found to the file menu
*/
for (i = 0; i < myglobs.NumDDDrivers; i++) {
InsertMenu(hmenu, 6 + i, MF_BYPOSITION | MF_STRING,
MENU_FIRST_DDDRIVER + i, myglobs.DDDriver[i].Name);
}
#endif
/*
* Have the example initialize it components which remain constant
* throughout execution
*/
if (!InitScene())
return FALSE;
/*
* Call D3DApp to initialize all DD and D3D objects necessary to render.
* D3DApp will call the device creation callback which will initialize the
* viewport and the sample's execute buffers.
*/
if (!CreateD3DApp(lpCmdLine))
return FALSE;
#if 0
// DEBUG - helps with fullscreen exclusive debugs!
ShowWindow(myglobs.hWndMain, SW_HIDE);
#endif
// Initialize theSW stuff NOW
{
HRESULT ddrval;
DDSURFACEDESC ddsd;
char *error_str;
ddrval = DirectDrawCreate(NULL, &lpDD_SW, NULL);
if (ddrval != DD_OK)
{
error_str = D3DAppErrorToString(ddrval);
Msg(error_str, ddrval);
return(FALSE);
}
// Set the cooperation level to normal for HEL
// (second window is not necessary and part of the development legacy)
ddrval = lpDD_SW->SetCooperativeLevel(NULL, DDSCL_NORMAL);
if (ddrval != DD_OK)
{
error_str = D3DAppErrorToString(ddrval);
Msg(error_str, ddrval);
return(FALSE);
}
#define sizeX 256
#define sizeY 256
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH ;
ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
ddsd.dwWidth = sizeX;
ddsd.dwHeight = sizeY;
//active and develop buffers for the texture map composite method
ddrval = lpDD_SW->CreateSurface(&ddsd, &lpDDActiveSurfaceSystem, NULL);
ddrval = lpDD_SW->CreateSurface(&ddsd, &lpDDDevelopSurfaceSystem, NULL);
// single system buf for blt coposite method
ddrval = lpDD_SW->CreateSurface(&ddsd, &lpDDSurfaceSystem, NULL);
if (ddrval != DD_OK)
{
error_str = D3DAppErrorToString(ddrval);
Msg(error_str, ddrval);
if (ddrval == DDERR_OUTOFMEMORY || ddrval == DDERR_OUTOFVIDEOMEMORY)
{
Msg("Not enough memory to create the system surface (SW).\0", ddrval);
return(FALSE);
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -