JD2022-TU1/main/extern/Camcam/LIBS/Render/D3D_Win32.cpp

546 lines
14 KiB
C++

#include "D3D_Class.h"
#include <assert.h>
#ifdef __D3D
const DWORD D3D_DI::Vertex::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0);
//const DWORD D3D_DI::Vertex2::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0);
INT_PTR CALLBACK MD3DDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
if (uMsg == WM_ERASEBKGND) return TRUE;
return 0;
}
void D3D_DI::ChangeMode(HWND Mother, bool UseGDI)
{
End();
if (!UseGDI)
AdaptTOWindow(Mother);
else
{
HGLOBAL hgbl;
LPDLGTEMPLATE lpdt;
LPWORD lpw;
LPWSTR lpwsz;
int nchar;
if (!CurrenthWnd)
{
hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
lpdt->style = WS_THICKFRAME;
lpdt->dwExtendedStyle = 0;
lpdt->cx = FB_SX; lpdt->cy = FB_SY;
lpw = (LPWORD) (lpdt + 1);
*lpw++ = 0; // no menu
*lpw++ = 0; // predefined dialog box class (by default)
lpwsz = (LPWSTR) lpw;
nchar = 1+ MultiByteToWideChar (CP_ACP, 0, "My Dialog", -1, lpwsz, 50);
lpw += nchar;
GlobalUnlock(hgbl);
CurrenthWnd = CreateDialogIndirect(NULL, (LPDLGTEMPLATE) hgbl, NULL, (DLGPROC) MD3DDialogProc);
GlobalFree(hgbl);
int Res = GetWindowLong(CurrenthWnd, GWL_STYLE);
Res &= ~(WS_CAPTION | WS_THICKFRAME | WS_BORDER | WS_DLGFRAME); // Turn it off
SetWindowLong(CurrenthWnd, GWL_STYLE, Res);
Res = GetWindowLong(CurrenthWnd, GWL_EXSTYLE);
Res &= ~(WS_EX_DLGMODALFRAME); // Turn it off
SetWindowLong(CurrenthWnd, GWL_EXSTYLE, Res | WS_EX_TOPMOST|WS_EX_TOOLWINDOW);
EnableWindow(CurrenthWnd,FALSE);
SetWindowPos(CurrenthWnd, NULL, 0, 0, FB_SX, FB_SY, 0);
ShowWindow(CurrenthWnd, SW_HIDE);//*/
IsVisible = 0;
UpdateWindow(CurrenthWnd);
}
AdaptTOWindow(CurrenthWnd);
}
}
void D3D_DI::Destroy()
{
End();
}
void D3D_DI::SetResolution(u32 SX,u32 SY)
{
if ((FB_SX != SX) || (FB_SY != SY))
{
FB_SX = SX;
FB_SY = SY;
RECT LocalR = {0,0,FB_SX,FB_SY};
Begin(&LocalR);
}
};
void D3D_DI::AdaptTOWindow(HWND NewWindow)
{
RECT LocalR = {0,0,FB_SX,FB_SY};
OpenglDisplayer = NewWindow;
Begin(&LocalR);
}
void D3D_DI::End()
{
OnDeviceLost();
u32 Counter = MaxOglTexture;
memset(OGLWorkingRef,0xff,sizeof(unsigned int)*NUMBER_OF_OGL_WORKING_REF);
while (Counter--)
{
if (AllRef[Counter].OGLRef != 0xffffffff)
{
AllRef[Counter].OGLRef = -2;
}
}
FontTextureIndex = -1;
d3ddev->Release();
d3ddev = NULL;
d3d->Release();
d3d = NULL;
if (hDC) ReleaseDC( OpenglDisplayer , hDC );
hDC = NULL;
hRC = NULL;
}
void D3D_DI::Begin(RECT *HdcRect)
{
BOOL Err;
int iFormat;
if (!d3d)
{
HRESULT res;
d3d = Direct3DCreate9(D3D_SDK_VERSION);
for (int k = 0 ; k < 2 ; k ++)
{
if (k == 0)
{
memset(&d3dpp, 0, sizeof(d3dpp)); // clear out the struct for use
d3dpp.Windowed = TRUE; // program windowed, not fullscreen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames ???
d3dpp.hDeviceWindow = OpenglDisplayer; // set the window to be used by Direct3D
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
res = d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
OpenglDisplayer,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, // Test D3DCREATE_MIXED_VERTEXPROCESSING or D3DCREATE_HARDWARE_VERTEXPROCESSING
&d3dpp,
&d3ddev);
} else
{
memset(&d3dpp, 0, sizeof(d3dpp)); // clear out the struct for use
d3dpp.Windowed = TRUE; // program windowed, not fullscreen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames ???
d3dpp.hDeviceWindow = OpenglDisplayer; // set the window to be used by Direct3D
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
d3dpp.BackBufferCount = 1;
res = d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
OpenglDisplayer,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, // Test D3DCREATE_MIXED_VERTEXPROCESSING or D3DCREATE_HARDWARE_VERTEXPROCESSING
&d3dpp,
&d3ddev);
}
if (res != S_OK)
res = d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
OpenglDisplayer,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
&d3dpp,
&d3ddev);
if (res != S_OK)
res = d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_SW,
OpenglDisplayer,
D3DCREATE_FPU_PRESERVE, // Test D3DCREATE_MIXED_VERTEXPROCESSING or D3DCREATE_HARDWARE_VERTEXPROCESSING
&d3dpp,
&d3ddev);
if (res != S_OK)
res = d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_NULLREF,
OpenglDisplayer,
D3DCREATE_FPU_PRESERVE, // Test D3DCREATE_MIXED_VERTEXPROCESSING or D3DCREATE_HARDWARE_VERTEXPROCESSING
&d3dpp,
&d3ddev);
if (res == S_OK) k = 1000000; // Break loop
}
if (res != S_OK)
{
//Sleep(10000);
PrintError(res);
}
hDC = GetDC( OpenglDisplayer );
//hRC = wglCreateContext( hDC );
//wglMakeCurrent( hDC, hRC );
hDCRect = *HdcRect;
CurrentColor = 0xffffffff;
ActivRect.left = 0;
ActivRect.top = 0;
ActivRect.right = FB_SX;
ActivRect.bottom = FB_SY;
OGLTextureSizeX = GetUpperPO2((float)FB_SX);
OGLTextureSizeY = GetUpperPO2((float)FB_SY);
CurrentRect = hDCRect;
SetViewport(0,0,hDCRect.right - hDCRect.left,CurrentRect.bottom - CurrentRect.top);
CurrentViewport[0] = 0.0f;
CurrentViewport[1] = 0.0f;
CurrentViewport[2] = hDCRect.right - hDCRect.left;
CurrentViewport[3] = CurrentRect.bottom - CurrentRect.top;
init_font();
// TODO:
if(!m_pVertexBuffer)
{
d3ddev->CreateVertexBuffer(
MaxD3DVertices * sizeof(Vertex),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC,
0, D3DPOOL_DEFAULT, &m_pVertexBuffer, 0);
}
if(!m_pIndexBuffer)
{
d3ddev->CreateIndexBuffer(
MaxD3DIndices*sizeof(WORD),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC,
D3DFMT_INDEX16,
D3DPOOL_DEFAULT, &m_pIndexBuffer, 0);
}
ulCurrentTexture = -1;
for (u32 Counter = 0 ; Counter < NUMBER_OF_OGL_WORKING_REF ; Counter++)
{
if (OGLWorkingRef[Counter] != -1)
_D3D_TEX(OGLWorkingRef[Counter])->Release();
OGLWorkingRef[Counter] = -1;
DisableTextureOps();
}
d3ddev->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL);
Ortho();
/* RecreateTexture If possible*/
for (u32 Counter = 0 ; Counter < MaxOglTexture; Counter++)
{
if (AllRef[Counter].OGLRef == -2)
{
CreateTexture(Counter,AllRef[Counter].ColorMode);
}
}//*/
RS Nullmlml;
GLOB_SetDefaultRS(&Nullmlml);
Nullmlml.BACKFACE = 0;
Nullmlml.BACKFACE_INVERT = 0;
Nullmlml.WIRED = 0;
Nullmlml.NOZWRITE = 1;
Nullmlml.NOZTEST = 1;
Nullmlml.TEXTURED = 0;
Nullmlml.HIDEALPHA = 0;
Nullmlml.SECONDPASS = 0;
SetRS(&Nullmlml,-1);
ZBIas = 1.0f;
ZQuad = 0.0f;
SetQuadDefault();
d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);
} else
{
if (CurrenthWnd)
SetWindowPos(CurrenthWnd, NULL, 0, 0, FB_SX, FB_SY, SWP_NOREDRAW | SWP_NOMOVE);
// Adapt only
hDCRect = *HdcRect;
CurrentColor = 0xffffffff;
ActivRect.left = 0;
ActivRect.top = 0;
ActivRect.right = FB_SX;
ActivRect.bottom = FB_SY;
memset(&d3dpp, 0, sizeof(d3dpp)); // clear out the struct for use
d3dpp.Windowed = TRUE; // program windowed, not fullscreen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames ???
d3dpp.hDeviceWindow = OpenglDisplayer; // set the window to be used by Direct3D
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
CurrentRect = hDCRect;
SetViewport(0,0,hDCRect.right - hDCRect.left,CurrentRect.bottom - CurrentRect.top);
CurrentViewport[0] = 0.0f;
CurrentViewport[1] = 0.0f;
CurrentViewport[2] = hDCRect.right - hDCRect.left;
CurrentViewport[3] = CurrentRect.bottom - CurrentRect.top;
if ((OGLTextureSizeX != GetUpperPO2((float)FB_SX)) ||
(OGLTextureSizeY != GetUpperPO2((float)FB_SY)))
{
OGLTextureSizeX = GetUpperPO2((float)FB_SX);
OGLTextureSizeY = GetUpperPO2((float)FB_SY);
// for (u32 Counter = 0 ; Counter < NUMBER_OF_OGL_WORKING_REF ; Counter++)
// {
// if (OGLWorkingRef[Counter] == -1)
// _D3D_TEX(OGLWorkingRef[Counter])->Release();
// OGLWorkingRef[Counter] = -1;
//DisableTextureOps();
// }
}
// Recreate a device class using this information
// And information from the d3dpp stuct
OnDeviceLost();
while (d3ddev->TestCooperativeLevel()!=D3D_OK)
::Sleep(100);
OnDeviceReset();
}
d3ddev->BeginScene();
d3ddev->SetFVF(Vertex::FVF);
m_uVBCount = m_uIBCount = 0;
d3ddev->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(Vertex));
d3ddev->SetIndices(m_pIndexBuffer);
FORCE_RENDER_FLAG |= 4;
}
void D3D_DI::Flush()
{
}
void D3D_DI::PrintError(HRESULT result)
{
switch(result)
{
case D3DERR_DEVICELOST:
OutputDebugString("D3DERR_DEVICELOST"); break;
case D3DERR_OUTOFVIDEOMEMORY:
OutputDebugString("D3DERR_OUTOFVIDEOMEMORY"); break;
case D3DERR_DRIVERINTERNALERROR:
OutputDebugString("D3DERR_DRIVERINTERNALERROR"); break;
case D3DERR_DEVICEREMOVED:
OutputDebugString("D3DERR_DEVICEREMOVED"); break;
case D3DERR_INVALIDCALL:
OutputDebugString("D3DERR_INVALIDCALL"); break;
case D3DERR_NOTAVAILABLE:
OutputDebugString("D3DERR_NOTAVAILABLE"); break;
}
}
void D3D_DI::OnDeviceReset()
{
// Reset Device
HRESULT hr = d3ddev->Reset(&d3dpp);
assert(SUCCEEDED(hr));
// TODO: Remove these
d3ddev->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL);
d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);
// Create Vertex & Index Buffers
hr = d3ddev->CreateVertexBuffer(MaxD3DVertices * sizeof(Vertex), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_pVertexBuffer, 0);
assert(SUCCEEDED(hr));
hr = d3ddev->CreateIndexBuffer(MaxD3DIndices*sizeof(WORD), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIndexBuffer, 0);
assert(SUCCEEDED(hr));
for (int i=0; i<NUMBER_OF_OGL_WORKING_REF; i++)
{
// Render targets (Shared Textures)
if (OGLWorkingRef[i] == 0xDEADBEEF)
{
OGLWorkingRef[i] = -1;
ValidateLayer(i);
}
}
for (int i=0; i<MaxOglTexture; i++)
{
// Independent texture
if (AllRef[i].OGLRef == 0xDEADBEEF)
CreateTexture(i, AllRef[i].ColorMode);
else if((AllRef[i].OGLRef >> 16) == 0xCAFE)
{
// It's actually using the working ref
int ref = AllRef[i].OGLRef & 0x0000FFFF;
AllRef[i].OGLRef = OGLWorkingRef[ref];
}
}
}
void D3D_DI::OnDeviceLost()
{
D3DSURFACE_DESC desc;
HRESULT result;
for (int i=0; i<MaxOglTexture; i++)
{
if (AllRef[i].OGLRef != -1)
{
_D3D_TEX(AllRef[i].OGLRef)->GetLevelDesc(0, &desc);
for (int j=0; j<NUMBER_OF_OGL_WORKING_REF; j++)
{
if (OGLWorkingRef[j] == AllRef[i].OGLRef)
// This is referencing a texture from OGLWorkingRef
AllRef[i].OGLRef = 0xCAFE0000 | j;
}
// if not shared texture
if ((AllRef[i].OGLRef >> 16) != 0xCAFE)
{
// Release the independent texture if it's in the default pool
if (desc.Pool == D3DPOOL_DEFAULT)
{
int refCount = _D3D_TEX(AllRef[i].OGLRef)->Release();
assert(refCount == 0);
// Set recreate flag
AllRef[i].OGLRef = 0xDEADBEEF;
}
}
}
}
// Release Shared Textures
for (int i=0; i<NUMBER_OF_OGL_WORKING_REF; i++)
{
if (OGLWorkingRef[i] != -1)
{
int refCount = _D3D_TEX(OGLWorkingRef[i])->Release();
assert(refCount == 0);
// Recreate flag
OGLWorkingRef[i] = 0xDEADBEEF;
}
}
// Release Temp Tex
if (srTex != NULL)
{
int refCount = srTex->Release();
assert(refCount == 0);
srTex = NULL;
}
// Release Temp Tex
if (srTex2 != NULL)
{
int refCount = srTex2->Release();
assert(refCount == 0);
srTex2 = NULL;
}
// Release Vertex & Index Buffers
int refCount = m_pVertexBuffer->Release();
assert(refCount == 0);
refCount = m_pIndexBuffer->Release();
assert(refCount == 0);
m_pVertexBuffer = NULL;
m_pIndexBuffer = NULL;
}
void D3D_DI::Flip(s32 ShowMe)
{
d3ddev->EndScene();
if (ShowMe) {
HRESULT result = d3ddev->Present(NULL,NULL,NULL,NULL);
PrintError(result);
}
if (d3ddev->TestCooperativeLevel() == D3DERR_DEVICELOST)
{
OnDeviceLost();
while (d3ddev->TestCooperativeLevel() != D3DERR_DEVICENOTRESET)
::Sleep(100);
OnDeviceReset();
}
//*/
d3ddev->BeginScene();
d3ddev->SetFVF(Vertex::FVF);
m_uVBCount = m_uIBCount = 0;
d3ddev->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(Vertex));
d3ddev->SetIndices(m_pIndexBuffer);
Clear(0);
QuadRotation_ON = 0;
SetQuadDefault();
FORCE_RENDER_FLAG |= 4;
}
void D3D_DI::Init()
{
m_pVertexBuffer = NULL;
m_pIndexBuffer = NULL;
m_uVBStartIndex = m_uVBCount = 0;
m_uIBStartIndex = m_uIBCount = 0;
srTex = NULL;
srTex2 = NULL;
}
DrawInterface *CreateD3DObject(HWND Mother,u32 FrameBuffSizeX,u32 FrameBuffSizeY)
{
D3D_DI *direct3D;
direct3D = new(D3D_DI);
direct3D->MotherClass = NULL;
memset(direct3D->AllRef,0xff,sizeof(direct3D->AllRef));
memset(direct3D->OGLWorkingRef,0xff,sizeof(unsigned int)*NUMBER_OF_OGL_WORKING_REF);
direct3D->FontTextureIndex = -1;
direct3D->FB_SX = FrameBuffSizeX;
direct3D->FB_SY = FrameBuffSizeY;
direct3D->QuadRotation_ON = 0;
direct3D->QuadHideColor = 0;
direct3D->ComputingBufferSize = 0;
direct3D->pComputingBuffer = NULL;
direct3D->ComputeMaskAlpha = 0;
direct3D->OptimiseQuadRender = 0;
direct3D->d3d = NULL;
direct3D->d3ddev = NULL;
direct3D->hDC = NULL;
direct3D->hRC = NULL;
direct3D->CurrenthWnd = NULL;
direct3D->Init();
direct3D->AdaptTOWindow(Mother);
direct3D->ClearLight();
direct3D->RenderTargetState = 0;
direct3D->RectifyTextOrigin = 0;
return direct3D;
}
#else
#include "TRACK.h"
DrawInterface *CreateD3DObject(HWND Mother,u32 FrameBuffSizeX,u32 FrameBuffSizeY)
{
return NULL;
}
#endif