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

📄 d3dapp.c

📁 国外游戏开发者杂志1997年第九期配套代码
💻 C
📖 第 1 页 / 共 4 页
字号:

/*
 * 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 + -