2025-04-27 07:49:33 -04:00

842 lines
23 KiB
C++

#include "pch.cpp"
#pragma hdrstop
#include "d3drend.h"
#include "util.h"
#include "globals.h"
//#define NOTOPMOST_WINDOW
D3dWindow::D3dWindow(void)
{
_pdmatBackground = NULL;
_pdvw = NULL;
_pd3dev = NULL;
_pddpPalette = NULL;
_pddcClipper = NULL;
_pddsBackBuffer = NULL;
_pddsFrontBuffer = NULL;
_pddsZBuffer = NULL;
_hwnd = NULL;
_pdebLast = NULL;
_pdtex = NULL;
_nTextureFormats = 0;
}
LRESULT D3dWindow::WindowProc(HWND hwnd, UINT uiMessage,
WPARAM wpm, LPARAM lpm)
{
switch( uiMessage )
{
case WM_DESTROY:
_hwnd = NULL;
break;
case WM_MOVE:
#if 0
// ATTENTION - How would we get a move in fullscreen mode?
if (app.bFullscreen)
break;
#endif
_rcClient.right += LOWORD(lpm)-_rcClient.left;
_rcClient.bottom += HIWORD(lpm)-_rcClient.top;
_rcClient.left = LOWORD(lpm);
_rcClient.top = HIWORD(lpm);
break;
case WM_SIZE:
if (_bIgnoreWM_SIZE)
{
break;
}
// Currently ignored since the test render size
// stays constant so increasing the flip area
// wouldn't buy anything
break;
case WM_ACTIVATE:
if (_bHandleActivate && _bPrimaryPalettized)
{
hrLast = _pddsFrontBuffer->SetPalette(_pddpPalette);
}
break;
default:
return DefWindowProc(hwnd, uiMessage, wpm, lpm);
}
return 0;
}
/*
* WindowProc
* Window message handler.
*/
long
FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam )
{
D3dWindow *pdwin = (D3dWindow *)GetWindowLong(hWnd, GWL_USERDATA);
if (pdwin != NULL)
{
return pdwin->WindowProc(hWnd, message, wParam, lParam);
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
HWND
D3dWindow::CreateHWND(int x, int y, UINT uiWidth, UINT uiHeight)
{
static BOOL bFirst = TRUE;
RECT rc;
DWORD dwStyle;
if (bFirst)
{
WNDCLASS wc;
bFirst = FALSE;
/*
* set up and register window class
*/
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = ::WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = app.hInstApp;
wc.hIcon = 0;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "Direct3D Test";
if (!RegisterClass(&wc))
return NULL;
}
/*
* create a window
*/
_bIgnoreWM_SIZE = TRUE;
_hwnd = CreateWindow(
"Direct3D Test",
"Direct3D Test",
0,
x,y,uiWidth,uiHeight,
app.hDlg, /* parent window */
NULL, /* menu handle */
app.hInstApp, /* program handle */
NULL); /* create parms */
if (!_hwnd){
Msg("CreateWindow failed");
return _hwnd;
}
UpdateWindow(_hwnd);
/*
* Convert to a normal app window if we are still a WS_POPUP window.
*/
dwStyle = GetWindowLong(_hwnd, GWL_STYLE);
dwStyle &= ~WS_POPUP;
dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME;
SetWindowLong(_hwnd, GWL_STYLE, dwStyle);
SetRect(&rc, 0, 0, uiWidth, uiHeight);
AdjustWindowRectEx(&rc, GetWindowLong(_hwnd, GWL_STYLE),
GetMenu(_hwnd) != NULL,
GetWindowLong(_hwnd, GWL_EXSTYLE));
SetWindowPos(_hwnd, NULL, x, y, rc.right-rc.left,
rc.bottom-rc.top,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
#ifndef NOTOPMOST_WINDOW
SetWindowPos(_hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
#else
SetWindowPos(_hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
#endif
_bIgnoreWM_SIZE = FALSE;
SetWindowLong(_hwnd, GWL_USERDATA, (LONG)this);
return _hwnd;
}
/*
* InitDD
* Given an HWND, creates DD surfaces
*/
BOOL
D3dWindow::InitDD(UINT uiWidth, UINT uiHeight, UINT uiBuffers)
{
DDSURFACEDESC ddsd;
BOOL bOnlySoftRender;
PALETTEENTRY ppe[256];
if (_pdrend->_bCurrentFullscreenMode) {
DDSCAPS ddscaps;
/*
* Create a complex flipping surface for fullscreen mode.
*/
_bIgnoreWM_SIZE = TRUE;
hrLast = _pdd->SetCooperativeLevel(_hwnd, DDSCL_EXCLUSIVE |
DDSCL_FULLSCREEN);
_bIgnoreWM_SIZE = FALSE;
if (hrLast != DD_OK ) {
_pdrend->_bCurrentFullscreenMode = FALSE;
Msg("SetCooperativeLevel failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
_bIgnoreWM_SIZE = TRUE;
hrLast = _pdd->SetDisplayMode(
_pdrend->_mleModeList[_pdrend->_iCurrentMode].iWidth,
_pdrend->_mleModeList[_pdrend->_iCurrentMode].iHeight,
_pdrend->_mleModeList[_pdrend->_iCurrentMode].iDepth);
_bIgnoreWM_SIZE = FALSE;
if(hrLast != DD_OK ) {
_pdrend->_bCurrentFullscreenMode = FALSE;
Msg("SetDisplayMode (%dx%dx%d) failed\n%s",
_pdrend->_mleModeList[_pdrend->_iCurrentMode].iWidth,
_pdrend->_mleModeList[_pdrend->_iCurrentMode].iHeight,
_pdrend->_mleModeList[_pdrend->_iCurrentMode].iDepth,
D3dErrorString(hrLast));
return FALSE;
}
memset(&ddsd,0,sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
ddsd.dwBackBufferCount = 1;
hrLast = _pdd->CreateSurface(&ddsd, &_pddsFrontBuffer, NULL);
if(hrLast != DD_OK) {
Msg("CreateSurface for front/back fullscreen buffer failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
hrLast = _pddsFrontBuffer->GetAttachedSurface(&ddscaps,
&_pddsBackBuffer);
if(hrLast != DD_OK) {
Msg("GetAttachedSurface failed to get back buffer.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
if (!GetDDSurfaceDesc(&ddsd, _pddsBackBuffer))
return FALSE;
if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) {
Msg("Backbuffer failed to go into video memory for "
"fullscreen test.\n");
return FALSE;
}
} else {
memset(&ddsd,0,sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hrLast = _pdd->CreateSurface(&ddsd, &_pddsFrontBuffer, NULL);
if(hrLast != DD_OK ) {
Msg("CreateSurface for window front buffer failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
ddsd.dwHeight = uiHeight;
ddsd.dwWidth = uiWidth;
ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
if (uiBuffers & REND_BUFFER_SYSTEM_MEMORY)
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
hrLast = _pdd->CreateSurface(&ddsd, &_pddsBackBuffer, NULL);
if (hrLast != DD_OK) {
Msg("CreateSurface for window back buffer failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
if (!GetDDSurfaceDesc(&ddsd, _pddsBackBuffer))
return FALSE;
bOnlySoftRender = FALSE;
if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
bOnlySoftRender = TRUE;
if (stat.rgd.bHardwareAssisted && bOnlySoftRender) {
Msg("There was not enough free video memory for the front and/or "
"back buffers for this hardware D3D device.\n");
return FALSE;
}
/*
* Create a DirectDrawClipper object.
*/
hrLast = _pdd->CreateClipper(0, &_pddcClipper, NULL);
if(hrLast != DD_OK ) {
Msg("CreateClipper failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
hrLast = _pddcClipper->SetHWnd(0, _hwnd);
if(hrLast != DD_OK ) {
Msg("Clipper SetHWnd failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
hrLast = _pddsFrontBuffer->SetClipper(_pddcClipper);
if(hrLast != DD_OK ) {
Msg("SetClipper failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
}
/*
* Palettize if we are not in a 16-bit mode.
*/
if (!GetDDSurfaceDesc(&ddsd, _pddsBackBuffer))
return FALSE;
if (ddsd.ddpfPixelFormat.dwRGBBitCount < 16) {
_bPrimaryPalettized = TRUE;
} else {
_bPrimaryPalettized = FALSE;
}
if (_bPrimaryPalettized) {
int i;
HDC hdc = GetDC(NULL);
GetSystemPaletteEntries(hdc, 0, (1 << 8), ppe);
ReleaseDC(NULL, hdc);
for (i = 0; i < 10; i++) ppe[i].peFlags = D3DPAL_READONLY;
for (i = 10; i < 256 - 10; i++) ppe[i].peFlags = PC_RESERVED;
for (i = 256 - 10; i < 256; i++) ppe[i].peFlags = D3DPAL_READONLY;
hrLast = _pdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE,
ppe, &_pddpPalette, NULL);
if (hrLast != DD_OK) {
Msg("CreatePalette failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
hrLast = _pddsBackBuffer->SetPalette(_pddpPalette);
if(hrLast != DD_OK ) {
Msg("SetPalette back failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
hrLast = _pddsFrontBuffer->SetPalette(_pddpPalette);
if(hrLast != DD_OK ) {
Msg("SetPalette failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
_bHandleActivate = TRUE;
}
return TRUE;
}
BOOL
D3dWindow::CreateZBuffer(UINT uiWidth, UINT uiHeight, DWORD dwDepth,
DWORD dwMemoryType)
{
LPDIRECTDRAWSURFACE lpZBuffer;
DDSURFACEDESC ddsd;
BOOL bOnlySoftRender;
/*
* Create a Z-Buffer and attach it to the back buffer.
*/
if (_pdrend->_bCurrentFullscreenMode) {
uiWidth = _pdrend->_mleModeList[_pdrend->_iCurrentMode].iWidth;
uiHeight = _pdrend->_mleModeList[_pdrend->_iCurrentMode].iHeight;
}
memset(&ddsd,0,sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH;
ddsd.dwHeight = uiHeight;
ddsd.dwWidth = uiWidth;
ddsd.dwZBufferBitDepth = dwDepth;
ddsd.ddsCaps.dwCaps= DDSCAPS_ZBUFFER | dwMemoryType;
hrLast = _pdd->CreateSurface(&ddsd, &lpZBuffer, NULL);
if (hrLast != DD_OK) {
Msg("CreateSurface for window Z-buffer failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
if (!GetDDSurfaceDesc(&ddsd, lpZBuffer))
return FALSE;
bOnlySoftRender = FALSE;
if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
bOnlySoftRender = TRUE;
if (stat.rgd.bHardwareAssisted && bOnlySoftRender) {
lpZBuffer->Release();
Msg("Did not have enough free video memory for Z-buffer "
"for this hardware D3D device.\n");
return FALSE;
}
hrLast = _pddsBackBuffer->AddAttachedSurface(lpZBuffer);
if(hrLast != DD_OK) {
Msg("AddAttachedBuffer failed for Z-buffer.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
_pddsZBuffer = lpZBuffer;
return TRUE;
}
HRESULT CALLBACK EnumTextureFormatsCallback(LPDDSURFACEDESC pddsd, LPVOID pv)
{
D3dWindow *pdwin = (D3dWindow *)pv;
if (pddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
{
return DDENUMRET_OK;
}
memcpy(&pdwin->_ddsdTextureFormat[pdwin->_nTextureFormats], pddsd,
sizeof(DDSURFACEDESC));
pdwin->_nTextureFormats++;
// We only care about one format right now
return DDENUMRET_CANCEL;
}
BOOL
D3dWindow::InitializeTextureLoad(void)
{
_nTextureFormats = 0;
hrLast = _pd3dev->EnumTextureFormats(EnumTextureFormatsCallback, this);
return hrLast == D3D_OK;
}
/*
* InitD3D
* Initializes the D3D device and creates the viewport.
*/
BOOL
D3dWindow::InitD3D(LPGUID pguid, UINT uiWidth, UINT uiHeight, UINT uiBuffers)
{
if (uiBuffers & REND_BUFFER_Z) {
if (!CreateZBuffer(uiWidth, uiHeight, _pdrend->_dwZDepth,
_pdrend->_dwZType))
return FALSE;
}
/*
* Create the device
*/
hrLast = _pddsBackBuffer->QueryInterface(*pguid, (LPVOID*)&_pd3dev);
if (hrLast != DD_OK) {
Msg("Create D3D device failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
if (!stat.bTexturesDisabled && !InitializeTextureLoad())
return FALSE;
/*
* Create and setup the viewport which is scaled to the screen mode
*/
hrLast = _pd3d->CreateViewport(&_pdvw, NULL);
if (hrLast != D3D_OK) {
Msg("Create D3D viewport failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
hrLast = _pd3dev->AddViewport(_pdvw);
if (hrLast != D3D_OK) {
Msg("Add D3D viewport failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
return TRUE;
}
BOOL D3dWindow::Initialize(D3dRenderer *pdrend,
LPDIRECTDRAW pdd, LPDIRECT3D pd3d, LPGUID pguid,
int x, int y, UINT uiWidth, UINT uiHeight,
UINT uiBuffers)
{
D3DMATERIAL dmat;
D3DMATERIALHANDLE hdmat;
_pdrend = pdrend;
_pdd = pdd;
_pd3d = pd3d;
if (CreateHWND(x, y, uiWidth, uiHeight) == NULL)
{
return FALSE;
}
/*
* Initialize fullscreen DD and the D3DDevice
*/
if (!InitDD(uiWidth, uiHeight, uiBuffers))
{
return FALSE;
}
if (!InitD3D(pguid, uiWidth, uiHeight, uiBuffers))
{
return FALSE;
}
if (pd3d->CreateMaterial(&_pdmatBackground, NULL) != D3D_OK)
{
return NULL;
}
/*
* Set background to black material
*/
memset(&dmat, 0, sizeof(D3DMATERIAL));
dmat.dwSize = sizeof(D3DMATERIAL);
dmat.dwRampSize = 1;
_pdmatBackground->SetMaterial(&dmat);
_pdmatBackground->GetHandle(_pd3dev, &hdmat);
_pdvw->SetBackground(hdmat);
return SetViewport(0, 0, uiWidth, uiHeight);
}
D3dWindow::~D3dWindow(void)
{
_bHandleActivate = FALSE;
SetWindowPos(_hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE| SWP_HIDEWINDOW);
RELEASE(_pdmatBackground);
RELEASE(_pdvw);
RELEASE(_pd3dev);
RELEASE(_pddpPalette);
RELEASE(_pddcClipper);
RELEASE(_pddsBackBuffer);
RELEASE(_pddsFrontBuffer);
RELEASE(_pddsZBuffer);
if (_hwnd != NULL)
{
DestroyWindow(_hwnd);
}
}
void D3dWindow::Release(void)
{
delete this;
}
BOOL D3dWindow::SetViewport(int x, int y, UINT uiWidth, UINT uiHeight)
{
D3DVIEWPORT viewData;
memset(&viewData, 0, sizeof(D3DVIEWPORT));
viewData.dwSize = sizeof(D3DVIEWPORT);
viewData.dwX = x;
viewData.dwY = y;
viewData.dwWidth = uiWidth;
viewData.dwHeight = uiHeight;
viewData.dvScaleX = viewData.dwWidth / (float)2.0;
viewData.dvScaleY = viewData.dwHeight / (float)2.0;
viewData.dvMaxX = (float)D3DDivide(D3DVAL(viewData.dwWidth),
D3DVAL(2 * viewData.dvScaleX));
viewData.dvMaxY = (float)D3DDivide(D3DVAL(viewData.dwHeight),
D3DVAL(2 * viewData.dvScaleY));
hrLast = _pdvw->SetViewport(&viewData);
if (hrLast != D3D_OK)
{
Msg("SetViewport failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
// If in fullscreen mode, assume the coordinates are in screen space
if (_pdrend->_bCurrentFullscreenMode)
{
_rcClient.left = x;
_rcClient.top = y;
}
else
{
POINT pt;
pt.x = x;
pt.y = y;
ClientToScreen(_hwnd, &pt);
_rcClient.left = pt.x;
_rcClient.top = pt.y;
}
_rcClient.right = _rcClient.left+uiWidth;
_rcClient.bottom = _rcClient.top+uiHeight;
return TRUE;
}
RendLight* D3dWindow::NewLight(int iType)
{
D3dLight *pdlRend;
pdlRend = new D3dLight;
if (pdlRend == NULL)
{
return NULL;
}
if (!pdlRend->Initialize(_pd3d, _pdvw, iType))
{
delete pdlRend;
return NULL;
}
return pdlRend;
}
RendTexture *D3dWindow::NewTexture(char *pszFile, UINT uiFlags)
{
D3dTexture *pdtRend;
DDSURFACEDESC ddsd, *pddsd;
pdtRend = new D3dTexture;
if (pdtRend == NULL)
{
return NULL;
}
if (stat.dtbTextureBlend == D3DTBLEND_COPY)
{
if (!GetDDSurfaceDesc(&ddsd, _pddsFrontBuffer))
{
return NULL;
}
if (ddsd.ddpfPixelFormat.dwRGBBitCount != 8 &&
ddsd.ddpfPixelFormat.dwRGBBitCount != 16)
{
Msg("Copy mode cannot be tested in this display depth. "
"Change display mode and try again.");
return NULL;
}
ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
if (stat.bOnlySystemMemory)
{
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
}
pddsd = &ddsd;
}
else
{
pddsd = &_ddsdTextureFormat[0];
}
if (!pdtRend->Initialize(_pdrend, _pdd, _pd3dev, pddsd, pszFile,
uiFlags, _pdtex))
{
delete pdtRend;
return NULL;
}
return pdtRend;
}
RendExecuteBuffer *D3dWindow::NewExecuteBuffer(UINT cbSize, UINT uiFlags)
{
D3dExecuteBuffer *pdebRend;
pdebRend = new D3dExecuteBuffer;
if (pdebRend == NULL)
{
return NULL;
}
if (!pdebRend->Initialize(_pd3dev, cbSize, uiFlags))
{
delete pdebRend;
return NULL;
}
return pdebRend;
}
RendMatrix *D3dWindow::NewMatrix(void)
{
D3dMatrix *pdmRend;
pdmRend = new D3dMatrix;
if (pdmRend == NULL)
{
return NULL;
}
if (!pdmRend->Initialize(_pd3dev))
{
delete pdmRend;
return NULL;
}
return pdmRend;
}
RendMaterial* D3dWindow::NewMaterial(UINT nColorEntries)
{
D3dMaterial *pdmatRend;
pdmatRend = new D3dMaterial;
if (pdmatRend == NULL)
{
return NULL;
}
if (!pdmatRend->Initialize(_pd3d, _pd3dev, nColorEntries))
{
delete pdmatRend;
return NULL;
}
return pdmatRend;
}
BOOL D3dWindow::BeginScene(void)
{
_pdebLast = NULL;
return _pd3dev->BeginScene() == D3D_OK;
}
BOOL D3dWindow::Execute(RendExecuteBuffer* preb)
{
_pdebLast = ((D3dExecuteBuffer *)preb)->_pdeb;
return _pd3dev->Execute(_pdebLast, _pdvw, D3DEXECUTE_UNCLIPPED) == D3D_OK;
}
BOOL D3dWindow::ExecuteClipped(RendExecuteBuffer* preb)
{
_pdebLast = ((D3dExecuteBuffer *)preb)->_pdeb;
return _pd3dev->Execute(_pdebLast, _pdvw, D3DEXECUTE_CLIPPED) == D3D_OK;
}
BOOL D3dWindow::EndScene(D3DRECT* pdrcBound)
{
if (pdrcBound != NULL)
{
// This whole _pdebLast scheme is an ugly hack but it makes
// the rendering interface cleaner
if (_pdebLast != NULL)
{
D3DEXECUTEDATA ded;
if (_pdebLast->GetExecuteData(&ded) != D3D_OK)
{
return FALSE;
}
*pdrcBound = ded.dsStatus.drExtent;
}
else
{
memset(pdrcBound, 0, sizeof(D3DRECT));
}
}
return _pd3dev->EndScene() == D3D_OK;
}
BOOL D3dWindow::Clear(UINT uiBuffers, D3DRECT* pdrc)
{
DWORD ClearFlags;
RECT src;
if (pdrc == NULL)
{
pdrc = &app.drcViewport;
}
ClearFlags = D3DCLEAR_TARGET;
if (uiBuffers & REND_BUFFER_Z)
{
ClearFlags |= D3DCLEAR_ZBUFFER;
}
hrLast = _pdvw->Clear(1, pdrc, ClearFlags);
if (hrLast != D3D_OK)
{
Msg("Viewport clear failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
if (uiBuffers & REND_BUFFER_FRONT)
{
SetRect(&src, 0, 0,
_rcClient.right-_rcClient.left,
_rcClient.bottom-_rcClient.top);
hrLast = _pddsFrontBuffer->Blt(&_rcClient, _pddsBackBuffer,
&src, DDBLT_WAIT, NULL);
if (hrLast != DD_OK)
{
Msg("Blt of back to front buffer failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
// ATTENTION - Make a RendWindow call for this?
// Front clear marks the start of a test
// Use this opportunity to restore lost surfaces
// It's not optimal but it works
if (!RestoreSurfaces())
{
return FALSE;
}
}
return TRUE;
}
BOOL D3dWindow::Flip(void)
{
hrLast = _pddsFrontBuffer->Flip(_pddsBackBuffer, 1);
if (hrLast != DD_OK) {
Msg("Flip failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
return TRUE;
}
BOOL D3dWindow::CopyForward(D3DRECT* pdrc)
{
RECT src, dst;
if (pdrc == NULL)
{
pdrc = &app.drcViewport;
}
SetRect(&src, pdrc->x1, pdrc->y1, pdrc->x2, pdrc->y2);
SetRect(&dst,
pdrc->x1 + _rcClient.left,
pdrc->y1 + _rcClient.top,
pdrc->x2 + _rcClient.left,
pdrc->y2 + _rcClient.top);
hrLast = _pddsFrontBuffer->Blt(&dst, _pddsBackBuffer,
&src, DDBLT_WAIT, NULL);
if (hrLast != DD_OK) {
Msg("Blt of back to front buffer failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
return TRUE;
}
HWND D3dWindow::Handle(void)
{
return _hwnd;
}
/*
* RestoreSurfaces
* Restores any lost surfaces.
*/
BOOL
D3dWindow::RestoreSurfaces(void)
{
D3dTexture *pdtex;
if (_pddsFrontBuffer->IsLost() == DDERR_SURFACELOST) {
hrLast = _pddsFrontBuffer->Restore();
if (hrLast != DD_OK) {
Msg("Restore of front buffer failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
}
if (_pddsBackBuffer->IsLost() == DDERR_SURFACELOST) {
hrLast = _pddsBackBuffer->Restore();
if (hrLast != DD_OK) {
Msg("Restore of back buffer failed.\n%s",
D3dErrorString(hrLast));
return FALSE;
}
}
if (_pddsZBuffer && _pddsZBuffer->IsLost() == DDERR_SURFACELOST) {
hrLast = _pddsZBuffer->Restore();
if (hrLast != DD_OK) {
Msg("Restore of Z-buffer failed.\n%s", D3dErrorString(hrLast));
return FALSE;
}
}
for (pdtex = _pdtex; pdtex != NULL; pdtex = pdtex->_pdtexNext)
{
if (!pdtex->RestoreSurface())
{
return FALSE;
}
}
return TRUE;
}