📄 d3dapp.c
字号:
/*
* D3DAppSetRenderState
*/
BOOL
D3DAppSetRenderState(D3DAppRenderState* lpState)
{
/*
* If none was provided, reset the current render state.
*/
if (!lpState)
lpState = &d3dapprs;
/*
* Record this render state and set it.
*/
if (lpState != &d3dapprs)
memcpy(&d3dapprs, lpState, sizeof(D3DAppRenderState));
if (d3dappi.bRenderingIsOK) {
ATTEMPT(D3DAppISetRenderState());
}
return TRUE;
exit_with_error:
return FALSE;
}
/*
* D3DAppGetRenderState
*/
BOOL
D3DAppGetRenderState(D3DAppRenderState* lpState)
{
memcpy(lpState, &d3dapprs, sizeof(D3DAppRenderState));
return TRUE;
}
/*
* D3DAppShowBackBuffer
*/
BOOL
D3DAppShowBackBuffer(DWORD flags)
{
if (!d3dappi.bRenderingIsOK) {
D3DAppISetErrorString("Cannot call D3DAppShowBackBuffer while bRenderingIsOK is FALSE.\n");
return FALSE;
}
if (d3dappi.bPaused)
return TRUE;
if (d3dappi.bFullscreen) {
int numtemp;
D3DRECT temp[D3DAPP_MAXCLEARRECTS];
/*
* Flip the back and front buffers
*/
LastError = d3dappi.lpFrontBuffer->lpVtbl->Flip(d3dappi.lpFrontBuffer,
d3dappi.lpBackBuffer,
1);
if (LastError == DDERR_SURFACELOST) {
d3dappi.lpFrontBuffer->lpVtbl->Restore(d3dappi.lpFrontBuffer);
d3dappi.lpBackBuffer->lpVtbl->Restore(d3dappi.lpBackBuffer);
D3DAppIClearBuffers();
} else if (LastError != DD_OK) {
D3DAppISetErrorString("Flipping complex display surface failed.\n%s", D3DAppErrorToString(LastError));
return FALSE;
}
if (d3dappi.bBackBufferInVideo) {
/*
* This is a real flip, so the client and back buffer dirty
* rectangles also flip
*/
D3DAppICopyRectList(&numtemp, temp, NumDirtyClientRects,
DirtyClient);
D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
NumDirtyBackRects, DirtyBack);
D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, numtemp, temp);
} else {
/*
* The flip is being emulated as a blt from a system memory back
* buffer, so the back buffer's dirty rectangles are now also the
* client's.
*/
D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
NumDirtyBackRects, DirtyBack);
}
} else {
int NumFrontRects, NumBufferRects, i;
RECT front[D3DAPP_MAXCLEARRECTS];
RECT buffer[D3DAPP_MAXCLEARRECTS];
/*
* Set the rectangle to blt from the back to front bufer
*/
if (flags & D3DAPP_SHOWALL) {
/*
* Set to entire client window
*/
NumBufferRects = 1;
SetRect(&buffer[0], 0, 0, d3dappi.szClient.cx,
d3dappi.szClient.cy);
SetRect(&front[0],
d3dappi.pClientOnPrimary.x, d3dappi.pClientOnPrimary.y,
d3dappi.szClient.cx + d3dappi.pClientOnPrimary.x,
d3dappi.szClient.cy + d3dappi.pClientOnPrimary.y);
} else {
/*
* Merge the back and front buffer dirty rectangle lists to get
* a list of rectangles to blt. This will simultaneously clear
* the smallest front buffer region while blt'ing all the back
* buffer which changed.
*/
D3DAppIMergeRectLists(&NumBufferRects, (LPD3DRECT)buffer,
NumDirtyClientRects, DirtyClient,
NumDirtyBackRects, DirtyBack);
D3DAppICopyRectList(&NumFrontRects, (LPD3DRECT)front,
NumBufferRects, (LPD3DRECT)buffer);
for (i = 0; i < NumFrontRects; i++) {
front[i].top += d3dappi.pClientOnPrimary.y;
front[i].left += d3dappi.pClientOnPrimary.x;
front[i].bottom += d3dappi.pClientOnPrimary.y;
front[i].right += d3dappi.pClientOnPrimary.x;
}
}
/*
* Blt the list of rectangles from the back to front buffer
*/
for (i = 0; i < NumBufferRects; i++) {
LastError =
d3dappi.lpFrontBuffer->lpVtbl->Blt(d3dappi.lpFrontBuffer,
&front[i], d3dappi.lpBackBuffer,
&buffer[i], DDBLT_WAIT, NULL);
if (LastError == DDERR_SURFACELOST) {
d3dappi.lpFrontBuffer->lpVtbl->Restore(d3dappi.lpFrontBuffer);
d3dappi.lpBackBuffer->lpVtbl->Restore(d3dappi.lpBackBuffer);
D3DAppIClearBuffers();
} else if (LastError != DD_OK) {
D3DAppISetErrorString("Blt of back buffer to front buffer failed.\n%s", D3DAppErrorToString(LastError));
return FALSE;
}
}
/*
* The back buffer's dirty rectangles are now also the client's
*/
D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient,
NumDirtyBackRects, DirtyBack);
}
return TRUE;
}
/*
* D3DAppRenderExtents
*/
BOOL
D3DAppRenderExtents(DWORD dwCount, LPD3DRECT extent, DWORD flags)
{
if (dwCount > D3DAPP_MAXCLEARRECTS) {
D3DAppISetErrorString("The number of clear rectangles exceeded D3DAPP_MAXCLEARRECTS.");
return FALSE;
}
if (flags & D3DAPP_CLEARALL) {
/*
* Set the back buffer dirty rectangle to the entire client area
*/
D3DRECT dummy;
dummy.x1 = dummy.y1 = 0;
dummy.x2 = d3dappi.szClient.cx;
dummy.y2 = d3dappi.szClient.cy;
D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, 1, &dummy);
D3DAppICopyRectList(&NumDirtyClientRects, DirtyClient, 1, &dummy);
D3DAppICopyRectList(&NumDirtyZRects, DirtyZ, 1, &dummy);
} else {
/*
* Set the back and Z buffer dirty rectangle list as specified
*/
D3DAppICopyRectList(&NumDirtyBackRects, DirtyBack, dwCount, extent);
D3DAppICopyRectList(&NumDirtyZRects, DirtyZ, dwCount, extent);
}
return TRUE;
}
/*
* D3DAppClearBackBuffer
*/
BOOL
D3DAppClearBackBuffer(DWORD flags)
{
if (!d3dappi.bRenderingIsOK) {
D3DAppISetErrorString("Cannot call D3DAppClearBackBuffer while bRenderingIsOK is FALSE.\n");
return FALSE;
}
if (flags & D3DAPP_CLEARALL) {
/*
* Clear the entire back buffer
*/
int clearflags;
D3DRECT dummy;
/*
* Decided wether to clear just back buffer or also z-buffer
*/
clearflags = D3DCLEAR_TARGET;
if (d3dapprs.bZBufferOn)
clearflags |= D3DCLEAR_ZBUFFER;
dummy.x1 = dummy.y1 = 0;
dummy.x2 = d3dappi.szClient.cx;
dummy.y2 = d3dappi.szClient.cy;
LastError =
d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
1, &dummy,
clearflags);
if (LastError != D3D_OK) {
D3DAppISetErrorString("Viewport clear failed.\n%s",
D3DAppErrorToString(LastError));
return FALSE;
}
} else {
/*
* Clear the dirty rectangles on the back buffer
*/
LastError =
d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
NumDirtyBackRects,
DirtyBack, D3DCLEAR_TARGET);
if (LastError != D3D_OK) {
D3DAppISetErrorString("Viewport clear of back buffer failed.\n%s",
D3DAppErrorToString(LastError));
return FALSE;
}
/*
* Clear the dirty rectangles on the Z buffer
*/
LastError =
d3dappi.lpD3DViewport->lpVtbl->Clear(d3dappi.lpD3DViewport,
NumDirtyZRects,
DirtyZ, D3DCLEAR_ZBUFFER);
if (LastError != D3D_OK) {
D3DAppISetErrorString("Viewport clear of Z buffer failed.\n%s",
D3DAppErrorToString(LastError));
return FALSE;
}
}
return TRUE;
}
/*
* D3DAppCheckForLostSurfaces
*/
#define CHECKSURF(x) if (x) { \
if (x->lpVtbl->IsLost(x) == DDERR_SURFACELOST) { \
LastError = x->lpVtbl->Restore(x); \
if (LastError != DD_OK) goto exit_with_error; \
b = TRUE; \
} \
}
BOOL
D3DAppCheckForLostSurfaces(void)
{
int i;
BOOL b = FALSE;
/*
* Check all the surfaces D3DApp owns and restore them if lost.
*/
CHECKSURF(d3dappi.lpFrontBuffer);
CHECKSURF(d3dappi.lpBackBuffer);
CHECKSURF(d3dappi.lpZBuffer);
if (b) {
/*
* If any of the surfaces were lost and restored, clear all the buffers.
* If this fails, that's fine, just move on.
*/
D3DAppIClearBuffers();
}
for (i = 0; i < d3dappi.NumUsableTextures; i++) {
b = FALSE;
CHECKSURF(d3dappi.lpTextureSurf[i]);
if (b) {
ATTEMPT(D3DAppIReloadTextureSurf(i));
}
}
return TRUE;
exit_with_error:
D3DAppISetErrorString("Restoring of a lost surface failed.\n%s",
D3DAppErrorToString(LastError));
return FALSE;
}
/*
* D3DAppPause
*/
BOOL
D3DAppPause(BOOL flag)
{
static int pausecount;
/*
* Keep a count of the number of times D3DAppPause has been called to
* prevent pausing more than once in a row.
*/
if (pausecount != 0) {
if (flag) {
++pausecount;
return TRUE;
} else {
--pausecount;
if (pausecount != 0)
return TRUE;
}
}
d3dappi.bPaused = flag;
if (!flag) {
/*
* Returning from a pause
*/
if (d3dappi.bFullscreen && bPrimaryPalettized && lpPalette) {
/*
* Set front buffer's palette back to what it was before pause
*/
LastError = lpPalette->lpVtbl->SetEntries(lpPalette, 0, 0, 256,
&ppe[0]);
if (LastError != DD_OK) {
D3DAppISetErrorString("Setting palette entries during unpause failed.\n%s", D3DAppErrorToString(LastError));
goto exit_with_error;
}
}
/*
* Dirty rectangle info is no longer valid
*/
D3DAppIValidateDirtyRects();
}
if (flag && d3dappi.bFullscreen) {
/*
* Pausing in a fullscreen mode
*/
if (bPrimaryPalettized && lpPalette) {
/*
* Save the front buffer's current palette and restore the
* original Windows palette.
*/
int i;
LastError = lpPalette->lpVtbl->GetEntries(lpPalette, 0, 0, 256,
&ppe[0]);
if (LastError != DD_OK) {
D3DAppISetErrorString("Getting palette entries before a pause failed.\n%s", D3DAppErrorToString(LastError));
goto exit_with_error;
}
for (i = 10; i < 246; i++)
Originalppe[i] = ppe[i];
LastError = lpPalette->lpVtbl->SetEntries(lpPalette, 0, 0, 256,
&Originalppe[0]);
if (LastError != DD_OK) {
D3DAppISetErrorString("Returning palette entries to defaults failed.\n%s", D3DAppErrorToString(LastError));
goto exit_with_error;
}
}
/*
* Flip to GDI surface (either front or back buffer)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -