This commit is contained in:
Aaron Robinson 2003-09-02 17:46:26 +00:00
parent 1a21b9f163
commit bd4db908c8
4 changed files with 269 additions and 176 deletions

View File

@ -1,5 +1,10 @@
cxbx website: http://www.caustik.com/xbox/
version: 0.7.9 (??/??/??)
--------------------------------
- Spontaneous CreateDevice failures fixed (many, at least)
version: 0.7.8b (08/30/03)
--------------------------------

View File

@ -1,5 +1,8 @@
Cxbx Todo (* denotes high priority, + denotes medium priority)
* CreateDevice/Release must be called in the context of the same thread,
so there needs to be a proxy CreateDevice and Release thread.
* Go lower level with mutants (maybe unnecessary), use \??\ and also
set root directory to null.

View File

@ -68,9 +68,9 @@ typedef signed long sint32;
// * Version information
// ******************************************************************
#ifndef _DEBUG_TRACE
#define _CXBX_VERSION "0.7.8b"
#define _CXBX_VERSION "0.7.9-Pre1"
#else
#define _CXBX_VERSION "0.7.8b-Trace"
#define _CXBX_VERSION "0.7.9-Pre1-Trace"
#endif
// ******************************************************************

View File

@ -68,6 +68,7 @@ HWND XTL::g_hEmuWindow = NULL; // Rendering Window
// * Static Function(s)
// ******************************************************************
static DWORD WINAPI EmuRenderWindow(LPVOID);
static DWORD WINAPI EmuCreateDeviceProxy(LPVOID);
static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static DWORD WINAPI EmuUpdateTickCount(LPVOID);
static DWORD EmuCheckAllocationSize(LPVOID);
@ -114,6 +115,22 @@ DWORD *XTL::EmuD3DDeferredRenderState;
// ******************************************************************
DWORD *XTL::EmuD3DDeferredTextureState;
// ******************************************************************
// * EmuD3D8CreateDeviceProxyData
// ******************************************************************
struct EmuD3D8CreateDeviceProxyData
{
XTL::UINT Adapter;
XTL::D3DDEVTYPE DeviceType;
HWND hFocusWindow;
XTL::DWORD BehaviorFlags;
XTL::X_D3DPRESENT_PARAMETERS *pPresentationParameters;
XTL::IDirect3DDevice8 **ppReturnedDeviceInterface;
volatile bool bReady;
volatile HRESULT hRet;
}
g_EmuD3D8CreateDeviceProxyData = {0};
// ******************************************************************
// * func: XTL::EmuD3DInit
// ******************************************************************
@ -136,6 +153,15 @@ VOID XTL::EmuD3DInit(Xbe::Header *XbeHeader, uint32 XbeHeaderSize)
CreateThread(NULL, NULL, EmuUpdateTickCount, NULL, NULL, &dwThreadId);
}
// ******************************************************************
// * create a thread dedicated to creating devices
// ******************************************************************
{
DWORD dwThreadId;
CreateThread(NULL, NULL, EmuCreateDeviceProxy, NULL, NULL, &dwThreadId);
}
// ******************************************************************
// * spark up a new thread to handle window message processing
// ******************************************************************
@ -416,6 +442,223 @@ static DWORD WINAPI EmuUpdateTickCount(LPVOID)
timeEndPeriod(0);
}
// ******************************************************************
// * func: EmuCreateDeviceProxy
// ******************************************************************
static DWORD WINAPI EmuCreateDeviceProxy(LPVOID)
{
printf("EmuD3D8 (0x%X): CreateDevice proxy thread is running.\n", GetCurrentThreadId());
while(true)
{
// if we have been signalled, create the device with cached parameters
if(g_EmuD3D8CreateDeviceProxyData.bReady)
{
printf("EmuD3D8 (0x%X): CreateDevice proxy thread recieved request.\n", GetCurrentThreadId());
// only one device should be created at once
// TODO: ensure all surfaces are somehow cleaned up?
if(g_pD3DDevice8 != 0)
{
printf("EmuD3D8 (0x%X): CreateDevice proxy thread releasing old Device.\n", GetCurrentThreadId());
g_pD3DDevice8->EndScene();
while(g_pD3DDevice8->Release() != 0);
g_pD3DDevice8 = 0;
}
// ******************************************************************
// * verify no ugly circumstances
// ******************************************************************
if(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BufferSurfaces[0] != NULL || g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->DepthStencilSurface != NULL)
EmuWarning("DepthStencilSurface != NULL and/or BufferSurfaces[0] != NULL");
// ******************************************************************
// * make adjustments to parameters to make sense with windows d3d
// ******************************************************************
{
g_EmuD3D8CreateDeviceProxyData.DeviceType =(g_XBVideo.GetDirect3DDevice() == 0) ? XTL::D3DDEVTYPE_HAL : XTL::D3DDEVTYPE_REF;
g_EmuD3D8CreateDeviceProxyData.Adapter = g_XBVideo.GetDisplayAdapter();
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->Windowed = !g_XBVideo.GetFullscreen();
if(g_XBVideo.GetVSync())
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->SwapEffect = XTL::D3DSWAPEFFECT_COPY_VSYNC;
g_EmuD3D8CreateDeviceProxyData.hFocusWindow = XTL::g_hEmuWindow;
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::EmuXB2PC_D3DFormat(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat);
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->AutoDepthStencilFormat = XTL::EmuXB2PC_D3DFormat(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->AutoDepthStencilFormat);
if(!g_XBVideo.GetVSync() && (g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) && g_XBVideo.GetFullscreen())
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
else
{
if(g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE && g_XBVideo.GetFullscreen())
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
else
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
}
// TODO: Support Xbox extensions if possible
if(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->MultiSampleType != 0)
{
EmuWarning("MultiSampleType 0x%.08X is not supported!", g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->MultiSampleType);
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->MultiSampleType = XTL::D3DMULTISAMPLE_NONE;
// TODO: Check card for multisampling abilities
// if(pPresentationParameters->MultiSampleType == 0x00001121)
// pPresentationParameters->MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
// else
// EmuCleanup("Unknown MultiSampleType (0x%.08X)", pPresentationParameters->MultiSampleType);
}
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
// ******************************************************************
// * Retrieve Resolution from Configuration
// ******************************************************************
if(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->Windowed)
{
sscanf(g_XBVideo.GetVideoResolution(), "%d x %d", &g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferWidth, &g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferHeight);
XTL::D3DDISPLAYMODE D3DDisplayMode;
g_pD3D8->GetAdapterDisplayMode(g_XBVideo.GetDisplayAdapter(), &D3DDisplayMode);
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = D3DDisplayMode.Format;
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_RefreshRateInHz = 0;
}
else
{
char szBackBufferFormat[16];
sscanf(g_XBVideo.GetVideoResolution(), "%d x %d %*dbit %s (%d hz)",
&g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferWidth,
&g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferHeight,
szBackBufferFormat,
&g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_RefreshRateInHz);
if(strcmp(szBackBufferFormat, "x1r5g5b5") == 0)
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_X1R5G5B5;
else if(strcmp(szBackBufferFormat, "r5g6r5") == 0)
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_R5G6B5;
else if(strcmp(szBackBufferFormat, "x8r8g8b8") == 0)
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_X8R8G8B8;
else if(strcmp(szBackBufferFormat, "a8r8g8b8") == 0)
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_A8R8G8B8;
}
}
// ******************************************************************
// * Detect vertex processing capabilities
// ******************************************************************
if((g_D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && g_EmuD3D8CreateDeviceProxyData.DeviceType == XTL::D3DDEVTYPE_HAL)
{
#ifdef _DEBUG_TRACE
printf("EmuD3D8 (0x%X): Using hardware vertex processing\n", GetCurrentThreadId());
#endif
g_EmuD3D8CreateDeviceProxyData.BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
g_dwVertexShaderUsage = 0;
}
else
{
#ifdef _DEBUG_TRACE
printf("EmuD3D8 (0x%X): Using software vertex processing\n", GetCurrentThreadId());
#endif
g_EmuD3D8CreateDeviceProxyData.BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
g_dwVertexShaderUsage = D3DUSAGE_SOFTWAREPROCESSING;
}
// ******************************************************************
// * redirect to windows d3d
// ******************************************************************
g_EmuD3D8CreateDeviceProxyData.hRet = g_pD3D8->CreateDevice
(
g_EmuD3D8CreateDeviceProxyData.Adapter,
g_EmuD3D8CreateDeviceProxyData.DeviceType,
g_EmuD3D8CreateDeviceProxyData.hFocusWindow,
g_EmuD3D8CreateDeviceProxyData.BehaviorFlags,
(XTL::D3DPRESENT_PARAMETERS*)g_EmuD3D8CreateDeviceProxyData.pPresentationParameters,
g_EmuD3D8CreateDeviceProxyData.ppReturnedDeviceInterface
);
// ******************************************************************
// * report error
// ******************************************************************
if(FAILED(g_EmuD3D8CreateDeviceProxyData.hRet))
{
if(g_EmuD3D8CreateDeviceProxyData.hRet == D3DERR_INVALIDCALL)
EmuCleanup("IDirect3D8::CreateDevice failed (Invalid Call)");
else if(g_EmuD3D8CreateDeviceProxyData.hRet == D3DERR_NOTAVAILABLE)
EmuCleanup("IDirect3D8::CreateDevice failed (Not Available)");
else if(g_EmuD3D8CreateDeviceProxyData.hRet == D3DERR_OUTOFVIDEOMEMORY)
EmuCleanup("IDirect3D8::CreateDevice failed (Out of Video Memory)");
EmuCleanup("IDirect3D8::CreateDevice failed (Unknown)");
}
// ******************************************************************
// * it is necessary to store this pointer globally for emulation
// ******************************************************************
g_pD3DDevice8 = *g_EmuD3D8CreateDeviceProxyData.ppReturnedDeviceInterface;
// ******************************************************************
// * check for YUY2 overlay support
// ******************************************************************
{
XTL::D3DDISPLAYMODE DisplayMode;
if(g_pD3DDevice8->GetDisplayMode(&DisplayMode) != D3D_OK)
g_bSupportsYUY2 = FALSE;
else
{
::HRESULT hRet = g_pD3D8->CheckDeviceFormat
(
g_EmuD3D8CreateDeviceProxyData.Adapter, g_EmuD3D8CreateDeviceProxyData.DeviceType,
(XTL::D3DFORMAT)DisplayMode.Format, 0, XTL::D3DRTYPE_TEXTURE, XTL::D3DFMT_YUY2
);
g_bSupportsYUY2 = SUCCEEDED(hRet);
if(!g_bSupportsYUY2)
EmuWarning("YUY2 overlays are not supported in hardware, could be slow!");
}
}
// ******************************************************************
// * Update Caches
// ******************************************************************
{
g_pCachedRenderTarget = new XTL::X_D3DSurface();
g_pD3DDevice8->GetRenderTarget(&g_pCachedRenderTarget->EmuSurface8);
g_pCachedZStencilSurface = new XTL::X_D3DSurface();
g_pD3DDevice8->GetDepthStencilSurface(&g_pCachedZStencilSurface->EmuSurface8);
}
// ******************************************************************
// * Begin Scene
// ******************************************************************
g_pD3DDevice8->BeginScene();
// ******************************************************************
// * Initially, show a black screen
// ******************************************************************
g_pD3DDevice8->Clear(0, 0, D3DCLEAR_TARGET, 0, 0, 0);
g_pD3DDevice8->Present(0, 0, 0, 0);
// signal completion
g_EmuD3D8CreateDeviceProxyData.bReady = false;
}
Sleep(1);
}
}
// ******************************************************************
// * func: EmuCheckAllocationSize
// ******************************************************************
@ -517,183 +760,22 @@ HRESULT WINAPI XTL::EmuIDirect3D8_CreateDevice
}
#endif
// only one device should be created at once
// TODO: ensure all surfaces are somehow cleaned up?
if(g_pD3DDevice8 != 0)
{
g_pD3DDevice8->Release();
g_pD3DDevice8 = 0;
}
// Cache parameters
g_EmuD3D8CreateDeviceProxyData.Adapter = Adapter;
g_EmuD3D8CreateDeviceProxyData.DeviceType = DeviceType;
g_EmuD3D8CreateDeviceProxyData.hFocusWindow = hFocusWindow;
g_EmuD3D8CreateDeviceProxyData.pPresentationParameters = pPresentationParameters;
g_EmuD3D8CreateDeviceProxyData.ppReturnedDeviceInterface = ppReturnedDeviceInterface;
// ******************************************************************
// * verify no ugly circumstances
// ******************************************************************
if(pPresentationParameters->BufferSurfaces[0] != NULL || pPresentationParameters->DepthStencilSurface != NULL)
EmuWarning("DepthStencilSurface != NULL and/or BufferSurfaces[0] != NULL");
// Signal proxy thread, and wait for completion
g_EmuD3D8CreateDeviceProxyData.bReady = true;
// ******************************************************************
// * make adjustments to parameters to make sense with windows d3d
// ******************************************************************
{
DeviceType =(g_XBVideo.GetDirect3DDevice() == 0) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
Adapter = g_XBVideo.GetDisplayAdapter();
pPresentationParameters->Windowed = !g_XBVideo.GetFullscreen();
if(g_XBVideo.GetVSync())
pPresentationParameters->SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;
hFocusWindow = g_hEmuWindow;
pPresentationParameters->BackBufferFormat = EmuXB2PC_D3DFormat(pPresentationParameters->BackBufferFormat);
pPresentationParameters->AutoDepthStencilFormat = EmuXB2PC_D3DFormat(pPresentationParameters->AutoDepthStencilFormat);
if(!g_XBVideo.GetVSync() && (g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) && g_XBVideo.GetFullscreen())
pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
else
{
if(g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE && g_XBVideo.GetFullscreen())
pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
else
pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
}
// TODO: Support Xbox extensions if possible
if(pPresentationParameters->MultiSampleType != 0)
{
EmuWarning("MultiSampleType 0x%.08X is not supported!", pPresentationParameters->MultiSampleType);
pPresentationParameters->MultiSampleType = D3DMULTISAMPLE_NONE;
// TODO: Check card for multisampling abilities
// if(pPresentationParameters->MultiSampleType == 0x00001121)
// pPresentationParameters->MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
// else
// EmuCleanup("Unknown MultiSampleType (0x%.08X)", pPresentationParameters->MultiSampleType);
}
pPresentationParameters->Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
// ******************************************************************
// * Retrieve Resolution from Configuration
// ******************************************************************
if(pPresentationParameters->Windowed)
{
sscanf(g_XBVideo.GetVideoResolution(), "%d x %d", &pPresentationParameters->BackBufferWidth, &pPresentationParameters->BackBufferHeight);
D3DDISPLAYMODE D3DDisplayMode;
g_pD3D8->GetAdapterDisplayMode(g_XBVideo.GetDisplayAdapter(), &D3DDisplayMode);
pPresentationParameters->BackBufferFormat = D3DDisplayMode.Format;
pPresentationParameters->FullScreen_RefreshRateInHz = 0;
}
else
{
char szBackBufferFormat[16];
sscanf(g_XBVideo.GetVideoResolution(), "%d x %d %*dbit %s (%d hz)",
&pPresentationParameters->BackBufferWidth,
&pPresentationParameters->BackBufferHeight,
szBackBufferFormat,
&pPresentationParameters->FullScreen_RefreshRateInHz);
if(strcmp(szBackBufferFormat, "x1r5g5b5") == 0)
pPresentationParameters->BackBufferFormat = D3DFMT_X1R5G5B5;
else if(strcmp(szBackBufferFormat, "r5g6r5") == 0)
pPresentationParameters->BackBufferFormat = D3DFMT_R5G6B5;
else if(strcmp(szBackBufferFormat, "x8r8g8b8") == 0)
pPresentationParameters->BackBufferFormat = D3DFMT_X8R8G8B8;
else if(strcmp(szBackBufferFormat, "a8r8g8b8") == 0)
pPresentationParameters->BackBufferFormat = D3DFMT_A8R8G8B8;
}
}
// ******************************************************************
// * Detect vertex processing capabilities
// ******************************************************************
if((g_D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && DeviceType == D3DDEVTYPE_HAL)
{
#ifdef _DEBUG_TRACE
printf("EmuD3D8 (0x%X): Using hardware vertex processing\n", GetCurrentThreadId());
#endif
BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
g_dwVertexShaderUsage = 0;
}
else
{
#ifdef _DEBUG_TRACE
printf("EmuD3D8 (0x%X): Using software vertex processing\n", GetCurrentThreadId());
#endif
BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
g_dwVertexShaderUsage = D3DUSAGE_SOFTWAREPROCESSING;
}
// ******************************************************************
// * redirect to windows d3d
// ******************************************************************
HRESULT hRet = g_pD3D8->CreateDevice
(
Adapter,
DeviceType,
hFocusWindow,
BehaviorFlags,
(XTL::D3DPRESENT_PARAMETERS*)pPresentationParameters,
ppReturnedDeviceInterface
);
if(FAILED(hRet))
EmuCleanup("IDirect3D8::CreateDevice failed (Invalid Display Settings?)");
// ******************************************************************
// * it is necessary to store this pointer globally for emulation
// ******************************************************************
g_pD3DDevice8 = *ppReturnedDeviceInterface;
// ******************************************************************
// * check for YUY2 overlay support
// ******************************************************************
{
D3DDISPLAYMODE DisplayMode;
if(g_pD3DDevice8->GetDisplayMode(&DisplayMode) != D3D_OK)
g_bSupportsYUY2 = FALSE;
else
{
HRESULT hRet = g_pD3D8->CheckDeviceFormat(Adapter, DeviceType, (XTL::D3DFORMAT)DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2);
g_bSupportsYUY2 = SUCCEEDED(hRet);
if(!g_bSupportsYUY2)
EmuWarning("YUY2 overlays are not supported in hardware, could be slow!");
}
}
// ******************************************************************
// * Update Caches
// ******************************************************************
{
g_pCachedRenderTarget = new X_D3DSurface();
g_pD3DDevice8->GetRenderTarget(&g_pCachedRenderTarget->EmuSurface8);
g_pCachedZStencilSurface = new X_D3DSurface();
g_pD3DDevice8->GetDepthStencilSurface(&g_pCachedZStencilSurface->EmuSurface8);
}
// ******************************************************************
// * Begin Scene
// ******************************************************************
g_pD3DDevice8->BeginScene();
// ******************************************************************
// * Initially, show a black screen
// ******************************************************************
g_pD3DDevice8->Clear(0, 0, D3DCLEAR_TARGET, 0, 0, 0);
g_pD3DDevice8->Present(0, 0, 0, 0);
while(g_EmuD3D8CreateDeviceProxyData.bReady)
Sleep(10);
EmuSwapFS(); // XBox FS
return hRet;
return g_EmuD3D8CreateDeviceProxyData.hRet;
}
// ******************************************************************
@ -1313,18 +1395,18 @@ HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetDepthStencilSurface
X_D3DSurface **ppZStencilSurface
)
{
EmuSwapFS(); // Win2k/XP FS
// ******************************************************************
// * debug trace
// ******************************************************************
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
printf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetDepthStencilSurface\n"
"(\n"
" ppZStencilSurface : 0x%.08X\n"
");\n",
GetCurrentThreadId(), ppZStencilSurface);
EmuSwapFS(); // Xbox FS
}
#endif
@ -1335,6 +1417,8 @@ HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetDepthStencilSurface
*ppZStencilSurface = g_pCachedZStencilSurface;
EmuSwapFS(); // Xbox FS
return D3D_OK;
}
@ -3308,6 +3392,7 @@ ULONG WINAPI XTL::EmuIDirect3DDevice8_Release()
}
#endif
EmuCleanup("Release should use proxy...");
ULONG uRet = g_pD3DDevice8->Release();
EmuSwapFS(); // XBox FS