More work. Audio driver works enough to play music now.

This commit is contained in:
elasota
2019-12-11 00:51:42 -05:00
parent b1e8e11a56
commit e368cf7235
141 changed files with 8996 additions and 1117 deletions

View File

@@ -1,8 +0,0 @@
#pragma once
enum EGpDisplayDriverType
{
EGpDisplayDriverType_D3D11,
EGpDisplayDriverType_Count,
};

View File

@@ -1,130 +1,139 @@
#include "GpAppEnvironment.h"
#include "GpFiberStarter.h"
#include "GpAppInterface.h"
#include "GpPLGlueDisplayDriver.h"
#include "GpFiber.h"
#include "HostSuspendCallArgument.h"
#include <assert.h>
GpAppEnvironment::GpAppEnvironment()
: m_applicationState(ApplicationState_NotStarted)
, m_displayDriver(nullptr)
, m_applicationFiber(nullptr)
, m_vosFiber(nullptr)
, m_suspendCallID(PortabilityLayer::HostSuspendCallID_Unknown)
, m_suspendArgs(nullptr)
, m_suspendReturnValue(nullptr)
{
}
GpAppEnvironment::~GpAppEnvironment()
{
assert(m_applicationFiber == nullptr);
}
void GpAppEnvironment::Init()
{
}
void GpAppEnvironment::Tick(GpFiber *vosFiber)
{
GpAppInterface_Get()->PL_IncrementTickCounter(1);
m_vosFiber = vosFiber;
if (m_applicationState == ApplicationState_WaitingForEvents)
m_applicationState = ApplicationState_Running;
for (;;)
{
switch (m_applicationState)
{
case ApplicationState_NotStarted:
InitializeApplicationState();
m_applicationFiber = GpFiberStarter::StartFiber(GpAppEnvironment::StaticAppThreadFunc, this, vosFiber);
m_applicationState = ApplicationState_Running;
break;
case ApplicationState_WaitingForEvents:
return;
case ApplicationState_Running:
m_applicationFiber->YieldTo();
break;
case ApplicationState_SystemCall:
{
PortabilityLayer::HostSuspendCallID callID = m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *args = m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *returnValue = m_suspendReturnValue;
DispatchSystemCall(callID, args, returnValue);
assert(m_applicationState != ApplicationState_SystemCall);
}
break;
case ApplicationState_TimedSuspend:
if (m_delaySuspendTicks <= 1)
m_applicationState = ApplicationState_Running;
else
{
m_delaySuspendTicks--;
return;
}
break;
default:
assert(false);
break;
};
}
}
void GpAppEnvironment::SetDisplayDriver(IGpDisplayDriver *displayDriver)
{
m_displayDriver = displayDriver;
}
void GpAppEnvironment::StaticAppThreadFunc(void *context)
{
static_cast<GpAppEnvironment*>(context)->AppThreadFunc();
}
void GpAppEnvironment::AppThreadFunc()
{
GpAppInterface_Get()->ApplicationMain();
}
void GpAppEnvironment::InitializeApplicationState()
{
GpAppInterface_Get()->PL_HostDisplayDriver_SetInstance(GpPLGlueDisplayDriver::GetInstance());
GpAppInterface_Get()->PL_InstallHostSuspendHook(GpAppEnvironment::StaticSuspendHookFunc, this);
SynchronizeState();
}
void GpAppEnvironment::SynchronizeState()
{
GpPLGlueDisplayDriver::GetInstance()->SetGpDisplayDriver(m_displayDriver);
}
void GpAppEnvironment::StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
GpAppEnvironment *appEnv = static_cast<GpAppEnvironment*>(context);
appEnv->m_suspendCallID = callID;
appEnv->m_suspendArgs = args;
appEnv->m_suspendReturnValue = returnValue;
appEnv->m_applicationState = ApplicationState_SystemCall;
appEnv->m_vosFiber->YieldTo();
}
void GpAppEnvironment::DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
switch (callID)
{
case PortabilityLayer::HostSuspendCallID_Delay:
m_applicationState = ApplicationState_TimedSuspend;
m_delaySuspendTicks = args[0].m_uint;
break;
default:
assert(false);
}
}
#include "GpAppEnvironment.h"
#include "GpFiberStarter.h"
#include "GpAppInterface.h"
#include "GpPLGlueAudioDriver.h"
#include "GpPLGlueDisplayDriver.h"
#include "GpFiber.h"
#include "HostSuspendCallArgument.h"
#include <assert.h>
GpAppEnvironment::GpAppEnvironment()
: m_applicationState(ApplicationState_NotStarted)
, m_displayDriver(nullptr)
, m_audioDriver(nullptr)
, m_applicationFiber(nullptr)
, m_vosFiber(nullptr)
, m_suspendCallID(PortabilityLayer::HostSuspendCallID_Unknown)
, m_suspendArgs(nullptr)
, m_suspendReturnValue(nullptr)
{
}
GpAppEnvironment::~GpAppEnvironment()
{
assert(m_applicationFiber == nullptr);
}
void GpAppEnvironment::Init()
{
}
void GpAppEnvironment::Tick(GpFiber *vosFiber)
{
GpAppInterface_Get()->PL_IncrementTickCounter(1);
m_vosFiber = vosFiber;
if (m_applicationState == ApplicationState_WaitingForEvents)
m_applicationState = ApplicationState_Running;
for (;;)
{
switch (m_applicationState)
{
case ApplicationState_NotStarted:
InitializeApplicationState();
m_applicationFiber = GpFiberStarter::StartFiber(GpAppEnvironment::StaticAppThreadFunc, this, vosFiber);
m_applicationState = ApplicationState_Running;
break;
case ApplicationState_WaitingForEvents:
return;
case ApplicationState_Running:
m_applicationFiber->YieldTo();
break;
case ApplicationState_SystemCall:
{
PortabilityLayer::HostSuspendCallID callID = m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *args = m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *returnValue = m_suspendReturnValue;
DispatchSystemCall(callID, args, returnValue);
assert(m_applicationState != ApplicationState_SystemCall);
}
break;
case ApplicationState_TimedSuspend:
if (m_delaySuspendTicks <= 1)
m_applicationState = ApplicationState_Running;
else
{
m_delaySuspendTicks--;
return;
}
break;
default:
assert(false);
break;
};
}
}
void GpAppEnvironment::SetDisplayDriver(IGpDisplayDriver *displayDriver)
{
m_displayDriver = displayDriver;
}
void GpAppEnvironment::SetAudioDriver(IGpAudioDriver *audioDriver)
{
m_audioDriver = audioDriver;
}
void GpAppEnvironment::StaticAppThreadFunc(void *context)
{
static_cast<GpAppEnvironment*>(context)->AppThreadFunc();
}
void GpAppEnvironment::AppThreadFunc()
{
GpAppInterface_Get()->ApplicationMain();
}
void GpAppEnvironment::InitializeApplicationState()
{
GpAppInterface_Get()->PL_HostDisplayDriver_SetInstance(GpPLGlueDisplayDriver::GetInstance());
GpAppInterface_Get()->PL_HostAudioDriver_SetInstance(GpPLGlueAudioDriver::GetInstance());
GpAppInterface_Get()->PL_InstallHostSuspendHook(GpAppEnvironment::StaticSuspendHookFunc, this);
SynchronizeState();
}
void GpAppEnvironment::SynchronizeState()
{
GpPLGlueDisplayDriver::GetInstance()->SetGpDisplayDriver(m_displayDriver);
GpPLGlueAudioDriver::GetInstance()->SetGpAudioDriver(m_audioDriver);
}
void GpAppEnvironment::StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
GpAppEnvironment *appEnv = static_cast<GpAppEnvironment*>(context);
appEnv->m_suspendCallID = callID;
appEnv->m_suspendArgs = args;
appEnv->m_suspendReturnValue = returnValue;
appEnv->m_applicationState = ApplicationState_SystemCall;
appEnv->m_vosFiber->YieldTo();
}
void GpAppEnvironment::DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)
{
switch (callID)
{
case PortabilityLayer::HostSuspendCallID_Delay:
m_applicationState = ApplicationState_TimedSuspend;
m_delaySuspendTicks = args[0].m_uint;
break;
default:
assert(false);
}
}

View File

@@ -1,55 +1,58 @@
#pragma once
#include "HostSuspendCallID.h"
#include <stdint.h>
namespace PortabilityLayer
{
union HostSuspendCallArgument;
}
class IGpDisplayDriver;
class GpFiber;
class GpAppEnvironment
{
public:
GpAppEnvironment();
~GpAppEnvironment();
void Init();
void Tick(GpFiber *vosFiber);
void SetDisplayDriver(IGpDisplayDriver *displayDriver);
private:
enum ApplicationState
{
ApplicationState_NotStarted,
ApplicationState_WaitingForEvents,
ApplicationState_Running,
ApplicationState_Terminated,
ApplicationState_SystemCall,
ApplicationState_TimedSuspend,
};
static void StaticAppThreadFunc(void *context);
void AppThreadFunc();
void InitializeApplicationState();
void SynchronizeState();
static void StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
void DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
ApplicationState m_applicationState;
IGpDisplayDriver *m_displayDriver;
GpFiber *m_applicationFiber;
GpFiber *m_vosFiber;
uint32_t m_delaySuspendTicks;
PortabilityLayer::HostSuspendCallID m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *m_suspendReturnValue;
};
#pragma once
#include "HostSuspendCallID.h"
#include <stdint.h>
namespace PortabilityLayer
{
union HostSuspendCallArgument;
}
class IGpDisplayDriver;
class IGpAudioDriver;
class GpFiber;
class GpAppEnvironment
{
public:
GpAppEnvironment();
~GpAppEnvironment();
void Init();
void Tick(GpFiber *vosFiber);
void SetDisplayDriver(IGpDisplayDriver *displayDriver);
void SetAudioDriver(IGpAudioDriver *audioDriver);
private:
enum ApplicationState
{
ApplicationState_NotStarted,
ApplicationState_WaitingForEvents,
ApplicationState_Running,
ApplicationState_Terminated,
ApplicationState_SystemCall,
ApplicationState_TimedSuspend,
};
static void StaticAppThreadFunc(void *context);
void AppThreadFunc();
void InitializeApplicationState();
void SynchronizeState();
static void StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
void DispatchSystemCall(PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue);
ApplicationState m_applicationState;
IGpDisplayDriver *m_displayDriver;
IGpAudioDriver *m_audioDriver;
GpFiber *m_applicationFiber;
GpFiber *m_vosFiber;
uint32_t m_delaySuspendTicks;
PortabilityLayer::HostSuspendCallID m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *m_suspendArgs;
PortabilityLayer::HostSuspendCallArgument *m_suspendReturnValue;
};

View File

@@ -0,0 +1,23 @@
#include "GpAudioDriverFactory.h"
#include "GpAudioDriverProperties.h"
#include <assert.h>
IGpAudioDriver *GpAudioDriverFactory::CreateAudioDriver(const GpAudioDriverProperties &properties)
{
assert(properties.m_type < EGpAudioDriverType_Count);
if (ms_registry[properties.m_type])
return ms_registry[properties.m_type](properties);
else
return nullptr;
}
void GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType type, FactoryFunc_t func)
{
assert(type < EGpAudioDriverType_Count);
ms_registry[type] = func;
}
GpAudioDriverFactory::FactoryFunc_t GpAudioDriverFactory::ms_registry[EGpAudioDriverType_Count];

View File

@@ -0,0 +1,18 @@
#pragma once
#include "EGpAudioDriverType.h"
class IGpAudioDriver;
struct GpAudioDriverProperties;
class GpAudioDriverFactory
{
public:
typedef IGpAudioDriver *(*FactoryFunc_t)(const GpAudioDriverProperties &properties);
static IGpAudioDriver *CreateAudioDriver(const GpAudioDriverProperties &properties);
static void RegisterAudioDriverFactory(EGpAudioDriverType type, FactoryFunc_t func);
private:
static FactoryFunc_t ms_registry[EGpAudioDriverType_Count];
};

View File

View File

@@ -1,25 +0,0 @@
#pragma once
#if __cplusplus >= 199711L
#define GP_IS_CPP11 1
#else
#define GP_IS_CPP11 0
#endif
#if GP_IS_CPP11
#define GP_DELETED = delete
#else
#ifndef nullptr
#define nullptr 0
#endif
#ifndef override
#define override
#endif
#ifndef final
#define final
#endif
#define GP_DELETED
#endif

View File

@@ -60,21 +60,29 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\GpCommon.props" />
<Import Project="..\GpMainApp.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
@@ -128,9 +136,9 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="GpAppEnvironment.cpp" />
<ClCompile Include="GpAudioDriverFactory.cpp" />
<ClCompile Include="GpDisplayDriverFactory.cpp" />
<ClCompile Include="GpDisplayDriverFactoryD3D11.cpp" />
<ClCompile Include="GpEvent_Win32.cpp" />
<ClCompile Include="GpFiber_Win32.cpp" />
<ClCompile Include="GpFileStream_Win32.cpp" />
<ClCompile Include="GpFileSystem_Win32.cpp" />
@@ -139,19 +147,27 @@
<ClCompile Include="GpMain_Win32.cpp" />
<ClCompile Include="GpDisplayDriverD3D11.cpp" />
<ClCompile Include="GpMemoryBuffer.cpp" />
<ClCompile Include="GpMutex_Win32.cpp" />
<ClCompile Include="GpPLGlueAudioChannel.cpp" />
<ClCompile Include="GpPLGlueAudioDriver.cpp" />
<ClCompile Include="GpPLGlueDisplayDriver.cpp" />
<ClCompile Include="GpSystemServices_Win32.cpp" />
<ClCompile Include="GpFiberStarter_Win32.cpp" />
<ClCompile Include="GpThreadEvent_Win32.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />
<ClInclude Include="EGpAudioDriverType.h" />
<ClInclude Include="EGpDisplayDriverType.h" />
<ClInclude Include="GpAppEnvironment.h" />
<ClInclude Include="GpAudioDriverFactory.h" />
<ClInclude Include="GpAudioDriverProperties.h" />
<ClInclude Include="GpAudioDriverXAudio2.h" />
<ClInclude Include="GpCoreDefs.h" />
<ClInclude Include="GpDisplayDriverD3D11.h" />
<ClInclude Include="GpDisplayDriverFactory.h" />
<ClInclude Include="GpDisplayDriverFactoryD3D11.h" />
<ClInclude Include="GpDisplayDriverProperties.h" />
<ClInclude Include="GpEvent.h" />
<ClInclude Include="GpFiber.h" />
<ClInclude Include="GpFiber_Win32.h" />
<ClInclude Include="GpFileStream_Win32.h" />
@@ -159,17 +175,26 @@
<ClInclude Include="GpGlobalConfig.h" />
<ClInclude Include="GpMain.h" />
<ClInclude Include="GpMemoryBuffer.h" />
<ClInclude Include="GpMutex_Win32.h" />
<ClInclude Include="GpPLGlueAudioChannel.h" />
<ClInclude Include="GpPLGlueAudioDriver.h" />
<ClInclude Include="GpPLGlueDisplayDriver.h" />
<ClInclude Include="GpRingBuffer.h" />
<ClInclude Include="GpSystemServices_Win32.h" />
<ClInclude Include="GpFiberStarter.h" />
<ClInclude Include="GpThreadEvent_Win32.h" />
<ClInclude Include="GpWindows.h" />
<ClInclude Include="IGpAudioChannel.h" />
<ClInclude Include="IGpAudioDriver.h" />
<ClInclude Include="IGpDisplayDriver.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GpApp\GpApp.vcxproj">
<Project>{6233c3f2-5781-488e-b190-4fa8836f5a77}</Project>
</ProjectReference>
<ProjectReference Include="..\GpAudioDriver_XAudio2\GpAudioDriver_XAudio2.vcxproj">
<Project>{e3bdc783-8646-433e-adf0-8b6390d36669}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@@ -36,9 +36,6 @@
<ClCompile Include="GpAppEnvironment.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpEvent_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFileSystem_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -60,6 +57,21 @@
<ClCompile Include="GpFiber_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpPLGlueAudioDriver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpAudioDriverFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpPLGlueAudioChannel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpMutex_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpThreadEvent_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpWindows.h">
@@ -98,9 +110,6 @@
<ClInclude Include="GpRingBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpEvent.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpFileSystem_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -125,5 +134,38 @@
<ClInclude Include="GpFiber.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IGpAudioDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="EGpAudioDriverType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverProperties.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpPLGlueAudioDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverXAudio2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpPLGlueAudioChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IGpAudioChannel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpMutex_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpThreadEvent_Win32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -1,290 +1,294 @@
#include "GpDisplayDriverD3D11.h"
#include "GpWindows.h"
#include "GpFiber_Win32.h"
#include <d3d11.h>
#include <dxgi1_2.h>
#include <stdio.h>
#pragma comment (lib, "d3d11.lib")
void DebugPrintf(const char *fmt, ...)
{
char buf[256];
va_list argp;
va_start(argp, fmt);
vsnprintf_s(buf, 255, fmt, argp);
OutputDebugString(buf);
va_end(argp);
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void StartD3DForWindow(HWND hWnd, IDXGISwapChain1*& swapChain)
{
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 2;
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc;
ZeroMemory(&swapChainFullscreenDesc, sizeof(swapChainFullscreenDesc));
swapChainFullscreenDesc.Windowed = TRUE;
swapChainFullscreenDesc.RefreshRate.Numerator = 60;
swapChainFullscreenDesc.RefreshRate.Denominator = 1;
UINT flags = 0;
const D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_9_1
};
flags |= D3D11_CREATE_DEVICE_DEBUG;
ID3D11Device *device = NULL;
ID3D11DeviceContext *context = NULL;
D3D_FEATURE_LEVEL selectedFeatureLevel;
HRESULT result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, featureLevels, sizeof(featureLevels) / sizeof(featureLevels[0]),
D3D11_SDK_VERSION, &device, &selectedFeatureLevel, &context);
IDXGIDevice2 *dxgiDevice = nullptr;
result = device->QueryInterface(__uuidof(IDXGIDevice2), reinterpret_cast<void**>(&dxgiDevice));
IDXGIAdapter *dxgiAdapter = nullptr;
result = dxgiDevice->GetAdapter(&dxgiAdapter);
IDXGIFactory2 *dxgiFactory = nullptr;
result = dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory));
result = dxgiFactory->CreateSwapChainForHwnd(device, hWnd, &swapChainDesc, nullptr, nullptr, &swapChain);
}
bool GpDisplayDriverD3D11::PresentFrameAndSync()
{
DXGI_PRESENT_PARAMETERS presentParams;
ZeroMemory(&presentParams, sizeof(presentParams));
UINT lastPresentCount = 0;
if (FAILED(m_SwapChain->GetLastPresentCount(&lastPresentCount)))
return false;
if (FAILED(m_SwapChain->Present1(1, 0, &presentParams)))
return false;
//DebugPrintf("r: %i\n", static_cast<int>(r));
DXGI_FRAME_STATISTICS stats;
if (FAILED(m_SwapChain->GetFrameStatistics(&stats)))
return false;
if (stats.SyncQPCTime.QuadPart != 0)
{
if (m_SyncTimeBase.QuadPart == 0)
m_SyncTimeBase = stats.SyncQPCTime;
LARGE_INTEGER timestamp;
timestamp.QuadPart = stats.SyncQPCTime.QuadPart - m_SyncTimeBase.QuadPart;
bool compacted = false;
if (m_PresentHistory.Size() > 0)
{
CompactedPresentHistoryItem &lastItem = m_PresentHistory[m_PresentHistory.Size() - 1];
LONGLONG timeDelta = timestamp.QuadPart - lastItem.m_Timestamp.QuadPart;
if (timeDelta < 0)
timeDelta = 0; // This should never happen
if (timeDelta * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockDenominator) < m_QPFrequency.QuadPart * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockNumerator))
{
lastItem.m_NumFrames++;
compacted = true;
}
}
if (!compacted)
{
if (m_PresentHistory.Size() == m_PresentHistory.CAPACITY)
m_PresentHistory.RemoveFromStart();
CompactedPresentHistoryItem *newItem = m_PresentHistory.Append();
newItem->m_Timestamp = timestamp;
newItem->m_NumFrames = 1;
}
}
if (m_PresentHistory.Size() >= 2)
{
const size_t presentHistorySizeMinusOne = m_PresentHistory.Size() - 1;
unsigned int numFrames = 0;
for (size_t i = 0; i < presentHistorySizeMinusOne; i++)
numFrames += m_PresentHistory[i].m_NumFrames;
LONGLONG timeFrame = m_PresentHistory[presentHistorySizeMinusOne].m_Timestamp.QuadPart - m_PresentHistory[0].m_Timestamp.QuadPart;
unsigned int cancelledFrames = 0;
LONGLONG cancelledTime = 0;
const int overshootTolerance = 2;
for (size_t i = 0; i < presentHistorySizeMinusOne; i++)
{
LONGLONG blockTimeframe = m_PresentHistory[i + 1].m_Timestamp.QuadPart - m_PresentHistory[i].m_Timestamp.QuadPart;
unsigned int blockNumFrames = m_PresentHistory[i].m_NumFrames;
if (blockTimeframe * static_cast<LONGLONG>(numFrames) >= timeFrame * static_cast<LONGLONG>(blockNumFrames) * overshootTolerance)
{
cancelledTime += blockTimeframe;
cancelledFrames += blockNumFrames;
}
}
numFrames -= cancelledFrames;
timeFrame -= cancelledTime;
// timeFrame / numFrames = Frame timestep
// Unless Frame timestep is within the frame lock range, a.k.a.
// timeFrame / numFrames / qpFreq >= minFrameTimeNum / minFrameTimeDenom
bool isInFrameTimeLock = false;
if (timeFrame * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockMinDenominator) >= static_cast<LONGLONG>(numFrames) * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockMinNumerator) * m_QPFrequency.QuadPart
&& timeFrame * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockMaxDenominator) <= static_cast<LONGLONG>(numFrames) * static_cast<LONGLONG>(m_Properties.m_FrameTimeLockMaxNumerator) * m_QPFrequency.QuadPart)
{
isInFrameTimeLock = true;
}
LONGLONG frameTimeStep = m_FrameTimeSliceSize;
if (!isInFrameTimeLock)
{
const int MAX_FRAMES_PER_STEP = 4;
frameTimeStep = timeFrame / numFrames;
if (frameTimeStep > m_FrameTimeSliceSize * MAX_FRAMES_PER_STEP)
frameTimeStep = m_FrameTimeSliceSize * MAX_FRAMES_PER_STEP;
}
m_FrameTimeAccumulated += frameTimeStep;
while (m_FrameTimeAccumulated >= m_FrameTimeSliceSize)
{
m_Properties.m_TickFunc(m_Properties.m_TickFuncContext, m_vosFiber);
m_FrameTimeAccumulated -= m_FrameTimeSliceSize;
}
}
return true;
}
void GpDisplayDriverD3D11::Run()
{
HWND hWnd;
WNDCLASSEX wc;
LPVOID fiber = ConvertThreadToFiberEx(this, 0);
if (!fiber)
return; // ???
m_vosFiber = new GpFiber_Win32(fiber);
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WinProc;
wc.hInstance = g_gpWindowsGlobals.m_hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "GPD3D11WindowClass";
RegisterClassEx(&wc);
LONG windowStyle = WS_OVERLAPPEDWINDOW;
HMENU menus = NULL;
// TODO: Fix the resolution here
RECT wr = { 0, 0, m_windowWidth, m_windowHeight };
AdjustWindowRect(&wr, windowStyle, menus != NULL);
hWnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", L"GlidePort", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, g_gpWindowsGlobals.m_hInstance, NULL);
ShowWindow(hWnd, g_gpWindowsGlobals.m_nCmdShow);
StartD3DForWindow(hWnd, m_SwapChain);
LARGE_INTEGER lastTimestamp;
memset(&lastTimestamp, 0, sizeof(lastTimestamp));
MSG msg;
for (;;)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
else
{
PresentFrameAndSync();
}
}
// Exit
ConvertFiberToThread();
}
void GpDisplayDriverD3D11::Shutdown()
{
delete this;
}
void GpDisplayDriverD3D11::GetDisplayResolution(unsigned int &width, unsigned int &height)
{
width = m_windowWidth;
height = m_windowHeight;
}
GpDisplayDriverD3D11 *GpDisplayDriverD3D11::Create(const GpDisplayDriverProperties &properties)
{
return new GpDisplayDriverD3D11(properties);
}
GpDisplayDriverD3D11::GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties)
: m_Properties(properties)
, m_FrameTimeAccumulated(0)
, m_windowWidth(640)
, m_windowHeight(480)
, m_vosFiber(nullptr)
{
memset(&m_SyncTimeBase, 0, sizeof(m_SyncTimeBase));
QueryPerformanceFrequency(&m_QPFrequency);
m_FrameTimeSliceSize = m_QPFrequency.QuadPart * static_cast<LONGLONG>(properties.m_FrameTimeLockNumerator) / static_cast<LONGLONG>(properties.m_FrameTimeLockDenominator);
}
#include "GpDisplayDriverD3D11.h"
#include "GpWindows.h"
#include "GpFiber_Win32.h"
#include <d3d11.h>
#include <dxgi1_2.h>
#include <stdio.h>
#pragma comment (lib, "d3d11.lib")
void DebugPrintf(const char *fmt, ...)
{
char buf[256];
va_list argp;
va_start(argp, fmt);
vsnprintf_s(buf, 255, fmt, argp);
OutputDebugString(buf);
va_end(argp);
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void StartD3DForWindow(HWND hWnd, IDXGISwapChain1*& swapChain)
{
DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 2;
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC swapChainFullscreenDesc;
ZeroMemory(&swapChainFullscreenDesc, sizeof(swapChainFullscreenDesc));
swapChainFullscreenDesc.Windowed = TRUE;
swapChainFullscreenDesc.RefreshRate.Numerator = 60;
swapChainFullscreenDesc.RefreshRate.Denominator = 1;
UINT flags = 0;
const D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_9_1
};
flags |= D3D11_CREATE_DEVICE_DEBUG;
ID3D11Device *device = NULL;
ID3D11DeviceContext *context = NULL;
D3D_FEATURE_LEVEL selectedFeatureLevel;
HRESULT result = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, featureLevels, sizeof(featureLevels) / sizeof(featureLevels[0]),
D3D11_SDK_VERSION, &device, &selectedFeatureLevel, &context);
IDXGIDevice2 *dxgiDevice = nullptr;
result = device->QueryInterface(__uuidof(IDXGIDevice2), reinterpret_cast<void**>(&dxgiDevice));
IDXGIAdapter *dxgiAdapter = nullptr;
result = dxgiDevice->GetAdapter(&dxgiAdapter);
IDXGIFactory2 *dxgiFactory = nullptr;
result = dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory));
result = dxgiFactory->CreateSwapChainForHwnd(device, hWnd, &swapChainDesc, nullptr, nullptr, &swapChain);
}
bool GpDisplayDriverD3D11::PresentFrameAndSync()
{
DXGI_PRESENT_PARAMETERS presentParams;
ZeroMemory(&presentParams, sizeof(presentParams));
UINT lastPresentCount = 0;
if (FAILED(m_swapChain->GetLastPresentCount(&lastPresentCount)))
return false;
if (FAILED(m_swapChain->Present1(1, 0, &presentParams)))
return false;
//DebugPrintf("r: %i\n", static_cast<int>(r));
DXGI_FRAME_STATISTICS stats;
if (FAILED(m_swapChain->GetFrameStatistics(&stats)))
return false;
if (stats.SyncQPCTime.QuadPart != 0)
{
if (m_syncTimeBase.QuadPart == 0)
m_syncTimeBase = stats.SyncQPCTime;
LARGE_INTEGER timestamp;
timestamp.QuadPart = stats.SyncQPCTime.QuadPart - m_syncTimeBase.QuadPart;
bool compacted = false;
if (m_presentHistory.Size() > 0)
{
CompactedPresentHistoryItem &lastItem = m_presentHistory[m_presentHistory.Size() - 1];
LONGLONG timeDelta = timestamp.QuadPart - lastItem.m_timestamp.QuadPart;
if (timeDelta < 0)
timeDelta = 0; // This should never happen
if (timeDelta * static_cast<LONGLONG>(m_properties.m_frameTimeLockDenominator) < m_QPFrequency.QuadPart * static_cast<LONGLONG>(m_properties.m_frameTimeLockNumerator))
{
lastItem.m_numFrames++;
compacted = true;
}
}
if (!compacted)
{
if (m_presentHistory.Size() == m_presentHistory.CAPACITY)
m_presentHistory.RemoveFromStart();
CompactedPresentHistoryItem *newItem = m_presentHistory.Append();
newItem->m_timestamp = timestamp;
newItem->m_numFrames = 1;
}
}
if (m_presentHistory.Size() >= 2)
{
const size_t presentHistorySizeMinusOne = m_presentHistory.Size() - 1;
unsigned int numFrames = 0;
for (size_t i = 0; i < presentHistorySizeMinusOne; i++)
numFrames += m_presentHistory[i].m_numFrames;
LONGLONG timeFrame = m_presentHistory[presentHistorySizeMinusOne].m_timestamp.QuadPart - m_presentHistory[0].m_timestamp.QuadPart;
unsigned int cancelledFrames = 0;
LONGLONG cancelledTime = 0;
const int overshootTolerance = 2;
for (size_t i = 0; i < presentHistorySizeMinusOne; i++)
{
LONGLONG blockTimeframe = m_presentHistory[i + 1].m_timestamp.QuadPart - m_presentHistory[i].m_timestamp.QuadPart;
unsigned int blockNumFrames = m_presentHistory[i].m_numFrames;
if (blockTimeframe * static_cast<LONGLONG>(numFrames) >= timeFrame * static_cast<LONGLONG>(blockNumFrames) * overshootTolerance)
{
cancelledTime += blockTimeframe;
cancelledFrames += blockNumFrames;
}
}
numFrames -= cancelledFrames;
timeFrame -= cancelledTime;
// timeFrame / numFrames = Frame timestep
// Unless Frame timestep is within the frame lock range, a.k.a.
// timeFrame / numFrames / qpFreq >= minFrameTimeNum / minFrameTimeDenom
bool isInFrameTimeLock = false;
if (timeFrame * static_cast<LONGLONG>(m_properties.m_frameTimeLockMinDenominator) >= static_cast<LONGLONG>(numFrames) * static_cast<LONGLONG>(m_properties.m_frameTimeLockMinNumerator) * m_QPFrequency.QuadPart
&& timeFrame * static_cast<LONGLONG>(m_properties.m_frameTimeLockMaxDenominator) <= static_cast<LONGLONG>(numFrames) * static_cast<LONGLONG>(m_properties.m_frameTimeLockMaxNumerator) * m_QPFrequency.QuadPart)
{
isInFrameTimeLock = true;
}
LONGLONG frameTimeStep = m_frameTimeSliceSize;
if (!isInFrameTimeLock)
{
const int MAX_FRAMES_PER_STEP = 4;
frameTimeStep = timeFrame / numFrames;
if (frameTimeStep > m_frameTimeSliceSize * MAX_FRAMES_PER_STEP)
frameTimeStep = m_frameTimeSliceSize * MAX_FRAMES_PER_STEP;
}
m_frameTimeAccumulated += frameTimeStep;
while (m_frameTimeAccumulated >= m_frameTimeSliceSize)
{
m_properties.m_tickFunc(m_properties.m_tickFuncContext, m_vosFiber);
m_frameTimeAccumulated -= m_frameTimeSliceSize;
}
}
return true;
}
void GpDisplayDriverD3D11::Run()
{
HWND hWnd;
WNDCLASSEX wc;
LPVOID fiber = ConvertThreadToFiberEx(this, 0);
if (!fiber)
return; // ???
m_vosFiber = new GpFiber_Win32(fiber);
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WinProc;
wc.hInstance = g_gpWindowsGlobals.m_hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "GPD3D11WindowClass";
RegisterClassEx(&wc);
LONG windowStyle = WS_OVERLAPPEDWINDOW;
HMENU menus = NULL;
// TODO: Fix the resolution here
RECT wr = { 0, 0, m_windowWidth, m_windowHeight };
AdjustWindowRect(&wr, windowStyle, menus != NULL);
hWnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", L"GlidePort", WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, g_gpWindowsGlobals.m_hInstance, NULL);
ShowWindow(hWnd, g_gpWindowsGlobals.m_nCmdShow);
StartD3DForWindow(hWnd, m_swapChain);
LARGE_INTEGER lastTimestamp;
memset(&lastTimestamp, 0, sizeof(lastTimestamp));
MSG msg;
for (;;)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
}
else
{
PresentFrameAndSync();
}
}
// Exit
ConvertFiberToThread();
}
void GpDisplayDriverD3D11::Shutdown()
{
delete this;
}
void GpDisplayDriverD3D11::GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *pixelFormat)
{
if (width)
*width = m_windowWidth;
if (height)
*height = m_windowHeight;
if (pixelFormat)
*pixelFormat = PortabilityLayer::PixelFormat_8BitStandard;
}
GpDisplayDriverD3D11 *GpDisplayDriverD3D11::Create(const GpDisplayDriverProperties &properties)
{
return new GpDisplayDriverD3D11(properties);
}
GpDisplayDriverD3D11::GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties)
: m_properties(properties)
, m_frameTimeAccumulated(0)
, m_windowWidth(640)
, m_windowHeight(480)
, m_vosFiber(nullptr)
{
memset(&m_syncTimeBase, 0, sizeof(m_syncTimeBase));
QueryPerformanceFrequency(&m_QPFrequency);
m_frameTimeSliceSize = m_QPFrequency.QuadPart * static_cast<LONGLONG>(properties.m_frameTimeLockNumerator) / static_cast<LONGLONG>(properties.m_frameTimeLockDenominator);
}

View File

@@ -1,50 +1,52 @@
#pragma once
#include "GpWindows.h"
#include "GpRingBuffer.h"
#include "IGpDisplayDriver.h"
#include "GpCoreDefs.h"
#include "GpDisplayDriverProperties.h"
struct IDXGISwapChain1;
class GpDisplayDriverD3D11 : public IGpDisplayDriver
{
public:
void Run() override;
void Shutdown() override;
void GetDisplayResolution(unsigned int &width, unsigned int &height) override;
static GpDisplayDriverD3D11 *Create(const GpDisplayDriverProperties &properties);
private:
GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties);
bool PresentFrameAndSync();
IDXGISwapChain1 *m_SwapChain;
struct CompactedPresentHistoryItem
{
LARGE_INTEGER m_Timestamp;
unsigned int m_NumFrames;
};
GpRingBuffer<CompactedPresentHistoryItem, 60> m_PresentHistory;
GpDisplayDriverProperties m_Properties;
LARGE_INTEGER m_SyncTimeBase;
LARGE_INTEGER m_QPFrequency;
UINT m_ExpectedSyncDelta;
bool m_IsResettingSwapChain;
LONGLONG m_FrameTimeAccumulated;
LONGLONG m_FrameTimeSliceSize;
DWORD m_windowWidth;
DWORD m_windowHeight;
GpFiber *m_vosFiber;
};
#pragma once
#include "GpWindows.h"
#include "GpRingBuffer.h"
#include "IGpDisplayDriver.h"
#include "GpCoreDefs.h"
#include "GpDisplayDriverProperties.h"
#include "PixelFormat.h"
struct IDXGISwapChain1;
class GpDisplayDriverD3D11 : public IGpDisplayDriver
{
public:
void Run() override;
void Shutdown() override;
void GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp) override;
static GpDisplayDriverD3D11 *Create(const GpDisplayDriverProperties &properties);
private:
GpDisplayDriverD3D11(const GpDisplayDriverProperties &properties);
bool PresentFrameAndSync();
IDXGISwapChain1 *m_swapChain;
struct CompactedPresentHistoryItem
{
LARGE_INTEGER m_timestamp;
unsigned int m_numFrames;
};
GpRingBuffer<CompactedPresentHistoryItem, 60> m_presentHistory;
GpDisplayDriverProperties m_properties;
LARGE_INTEGER m_syncTimeBase;
LARGE_INTEGER m_QPFrequency;
UINT m_expectedSyncDelta;
bool m_isResettingSwapChain;
LONGLONG m_frameTimeAccumulated;
LONGLONG m_frameTimeSliceSize;
DWORD m_windowWidth;
DWORD m_windowHeight;
GpFiber *m_vosFiber;
};

View File

@@ -5,10 +5,10 @@
IGpDisplayDriver *GpDisplayDriverFactory::CreateDisplayDriver(const GpDisplayDriverProperties &properties)
{
assert(properties.m_Type < EGpDisplayDriverType_Count);
assert(properties.m_type < EGpDisplayDriverType_Count);
if (ms_Registry[properties.m_Type])
return ms_Registry[properties.m_Type](properties);
if (ms_Registry[properties.m_type])
return ms_Registry[properties.m_type](properties);
else
return nullptr;
}

View File

@@ -1,26 +0,0 @@
#pragma once
#include "EGpDisplayDriverType.h"
class IGpDisplayDriver;
class GpFiber;
struct GpDisplayDriverProperties
{
typedef void(*TickFunc_t)(void *context, GpFiber *vosFiber);
EGpDisplayDriverType m_Type;
unsigned int m_FrameTimeLockNumerator;
unsigned int m_FrameTimeLockDenominator;
unsigned int m_FrameTimeLockMinNumerator;
unsigned int m_FrameTimeLockMinDenominator;
unsigned int m_FrameTimeLockMaxNumerator;
unsigned int m_FrameTimeLockMaxDenominator;
// Tick function and context to call when a frame needs to be served.
TickFunc_t m_TickFunc;
void *m_TickFuncContext;
};

View File

@@ -1,21 +0,0 @@
#pragma once
#include "GpCoreDefs.h"
class GpEvent final
{
public:
void Wait();
void WaitMSec(unsigned int msec);
void Signal();
void Reset();
void Destroy();
static GpEvent *Create(bool autoReset, bool startSignalled);
private:
explicit GpEvent(void *privateData);
~GpEvent();
void *m_PrivateData;
};

View File

@@ -1,49 +0,0 @@
#include "GpEvent.h"
#include "GpWindows.h"
#include <assert.h>
GpEvent::~GpEvent()
{
CloseHandle(static_cast<HANDLE>(m_PrivateData));
}
void GpEvent::Wait()
{
WaitForSingleObject(static_cast<HANDLE>(m_PrivateData), INFINITE);
}
void GpEvent::WaitMSec(unsigned int msec)
{
assert(msec < MAXDWORD);
WaitForSingleObject(static_cast<HANDLE>(m_PrivateData), static_cast<DWORD>(msec));
}
void GpEvent::Signal()
{
SetEvent(static_cast<HANDLE>(m_PrivateData));
}
void GpEvent::Reset()
{
ResetEvent(static_cast<HANDLE>(m_PrivateData));
}
void GpEvent::Destroy()
{
delete this;
}
GpEvent *GpEvent::Create(bool autoReset, bool startSignalled)
{
HANDLE handle = CreateEventA(nullptr, autoReset ? FALSE : TRUE, startSignalled ? TRUE : FALSE, nullptr);
if (!handle)
return nullptr;
return new GpEvent(handle);
}
GpEvent::GpEvent(void *privateData)
: m_PrivateData(privateData)
{
}

View File

@@ -1,48 +1,64 @@
#include "GpMain.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverProperties.h"
#include "GpGlobalConfig.h"
#include "GpAppEnvironment.h"
#include "IGpDisplayDriver.h"
#include <string.h>
namespace
{
void TickAppEnvironment(void *context, GpFiber *vosFiber)
{
static_cast<GpAppEnvironment*>(context)->Tick(vosFiber);
}
}
int GpMain::Run()
{
GpAppEnvironment *appEnvironment = new GpAppEnvironment();
GpDisplayDriverProperties ddProps;
memset(&ddProps, 0, sizeof(ddProps));
ddProps.m_FrameTimeLockNumerator = 1;
ddProps.m_FrameTimeLockDenominator = 60;
// +/- 1% tolerance for frame time variance
ddProps.m_FrameTimeLockMinNumerator = 99;
ddProps.m_FrameTimeLockMinDenominator = 6000;
ddProps.m_FrameTimeLockMaxNumerator = 101;
ddProps.m_FrameTimeLockMaxDenominator = 6000;
ddProps.m_TickFunc = TickAppEnvironment;
ddProps.m_TickFuncContext = appEnvironment;
ddProps.m_Type = g_gpGlobalConfig.m_displayDriverType;
IGpDisplayDriver *displayDriver = GpDisplayDriverFactory::CreateDisplayDriver(ddProps);
appEnvironment->Init();
appEnvironment->SetDisplayDriver(displayDriver);
// Start the display loop
displayDriver->Run();
return 0;
}
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpAudioDriverProperties.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverProperties.h"
#include "GpGlobalConfig.h"
#include "GpAppEnvironment.h"
#include "IGpAudioDriver.h"
#include "IGpDisplayDriver.h"
#include <string.h>
namespace
{
void TickAppEnvironment(void *context, GpFiber *vosFiber)
{
static_cast<GpAppEnvironment*>(context)->Tick(vosFiber);
}
}
int GpMain::Run()
{
GpAppEnvironment *appEnvironment = new GpAppEnvironment();
GpDisplayDriverProperties ddProps;
memset(&ddProps, 0, sizeof(ddProps));
ddProps.m_type = EGpDisplayDriverType_D3D11;
ddProps.m_frameTimeLockNumerator = 1;
ddProps.m_frameTimeLockDenominator = 60;
// +/- 1% tolerance for frame time variance
ddProps.m_frameTimeLockMinNumerator = 99;
ddProps.m_frameTimeLockMinDenominator = 6000;
ddProps.m_frameTimeLockMaxNumerator = 101;
ddProps.m_frameTimeLockMaxDenominator = 6000;
ddProps.m_tickFunc = TickAppEnvironment;
ddProps.m_tickFuncContext = appEnvironment;
ddProps.m_type = g_gpGlobalConfig.m_displayDriverType;
GpAudioDriverProperties adProps;
memset(&adProps, 0, sizeof(adProps));
// The sample rate used in all of Glider PRO's sound is 0x56ee8ba3
// This appears to be the "standard" Mac sample rate, probably rounded from 244800/11.
adProps.m_type = EGpAudioDriverType_XAudio2;
adProps.m_sampleRate = (244800 * 2 + 11) / (11 * 2);
adProps.m_debug = true;
IGpDisplayDriver *displayDriver = GpDisplayDriverFactory::CreateDisplayDriver(ddProps);
IGpAudioDriver *audioDriver = GpAudioDriverFactory::CreateAudioDriver(adProps);
appEnvironment->Init();
appEnvironment->SetDisplayDriver(displayDriver);
appEnvironment->SetAudioDriver(audioDriver);
// Start the display loop
displayDriver->Run();
return 0;
}

View File

@@ -1,33 +1,36 @@
#include "GpWindows.h"
#include "GpMain.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverFactoryD3D11.h"
#include "GpGlobalConfig.h"
#include "GpFileSystem_Win32.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Win32.h"
#include "HostFileSystem.h"
#include <d3d11.h>
#include <stdio.h>
GPWindowsGlobals g_gpWindowsGlobals;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
g_gpWindowsGlobals.m_hInstance = hInstance;
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
g_gpWindowsGlobals.m_cmdLine = lpCmdLine;
g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDisplayDriverFactoryD3D11::Create);
return GpMain::Run();
}
#include "GpMain.h"
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverFactoryD3D11.h"
#include "GpGlobalConfig.h"
#include "GpFileSystem_Win32.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Win32.h"
#include "HostFileSystem.h"
#include "GpWindows.h"
#include <stdio.h>
GPWindowsGlobals g_gpWindowsGlobals;
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
GpAppInterface_Get()->PL_HostFileSystem_SetInstance(GpFileSystem_Win32::GetInstance());
GpAppInterface_Get()->PL_HostSystemServices_SetInstance(GpSystemServices_Win32::GetInstance());
g_gpWindowsGlobals.m_hInstance = hInstance;
g_gpWindowsGlobals.m_hPrevInstance = hPrevInstance;
g_gpWindowsGlobals.m_cmdLine = lpCmdLine;
g_gpWindowsGlobals.m_nCmdShow = nCmdShow;
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDisplayDriverFactoryD3D11::Create);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
return GpMain::Run();
}

42
GpD3D/GpMutex_Win32.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include "GpMutex_Win32.h"
#include "GpWindows.h"
#include <stdlib.h>
#include <new>
void GpMutex_Win32::Destroy()
{
this->~GpMutex_Win32();
free(this);
}
void GpMutex_Win32::Lock()
{
EnterCriticalSection(&m_critSection);
}
void GpMutex_Win32::Unlock()
{
LeaveCriticalSection(&m_critSection);
}
GpMutex_Win32 *GpMutex_Win32::Create()
{
void *storage = malloc(sizeof(GpMutex_Win32));
if (!storage)
return nullptr;
return new (storage) GpMutex_Win32();
}
GpMutex_Win32::GpMutex_Win32()
{
InitializeCriticalSection(&m_critSection);
}
GpMutex_Win32::~GpMutex_Win32()
{
DeleteCriticalSection(&m_critSection);
}

21
GpD3D/GpMutex_Win32.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include "HostMutex.h"
#include "GpWindows.h"
class GpMutex_Win32 final : public PortabilityLayer::HostMutex
{
public:
void Destroy() override;
void Lock() override;
void Unlock() override;
static GpMutex_Win32 *Create();
private:
const GpMutex_Win32();
~GpMutex_Win32();
CRITICAL_SECTION m_critSection;
};

View File

@@ -0,0 +1,49 @@
#include "GpPLGlueAudioChannel.h"
#include "ClientAudioChannelContext.h"
#include "IGpAudioChannel.h"
#include <stdlib.h>
#include <new>
void GpPLGlueAudioChannel::SetClientAudioChannelContext(PortabilityLayer::ClientAudioChannelContext *context)
{
m_clientContext = context;
m_audioChannel->SetAudioChannelContext(this);
}
void GpPLGlueAudioChannel::PostBuffer(const void *buffer, size_t bufferSize)
{
m_audioChannel->PostBuffer(buffer, bufferSize);
}
void GpPLGlueAudioChannel::Destroy()
{
this->~GpPLGlueAudioChannel();
free(this);
}
void GpPLGlueAudioChannel::NotifyBufferFinished()
{
if (m_clientContext)
m_clientContext->NotifyBufferFinished();
}
GpPLGlueAudioChannel *GpPLGlueAudioChannel::Create(IGpAudioChannel *audioChannel)
{
void *storage = malloc(sizeof(GpPLGlueAudioChannel));
if (!storage)
return nullptr;
return new (storage) GpPLGlueAudioChannel(audioChannel);
}
GpPLGlueAudioChannel::GpPLGlueAudioChannel(IGpAudioChannel *audioChannel)
: m_audioChannel(audioChannel)
, m_clientContext(nullptr)
{
}
GpPLGlueAudioChannel::~GpPLGlueAudioChannel()
{
m_audioChannel->Destroy();
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include "HostAudioChannel.h"
#include "IGpAudioChannelCallbacks.h"
struct IGpAudioChannel;
class GpPLGlueAudioChannel final : public PortabilityLayer::HostAudioChannel, public IGpAudioChannelCallbacks
{
public:
void SetClientAudioChannelContext(PortabilityLayer::ClientAudioChannelContext *context) override;
void PostBuffer(const void *buffer, size_t bufferSize) override;
void Destroy() override;
void NotifyBufferFinished() override;
static GpPLGlueAudioChannel *Create(IGpAudioChannel *audioChannel);
private:
explicit GpPLGlueAudioChannel(IGpAudioChannel *audioChannel);
~GpPLGlueAudioChannel();
PortabilityLayer::ClientAudioChannelContext *m_clientContext;
IGpAudioChannel *m_audioChannel;
};

View File

@@ -0,0 +1,38 @@
#include "GpPLGlueAudioDriver.h"
#include "GpPLGlueAudioChannel.h"
#include "IGpAudioChannel.h"
#include "IGpAudioDriver.h"
GpPLGlueAudioDriver::GpPLGlueAudioDriver()
: m_audioDriver(nullptr)
{
}
PortabilityLayer::HostAudioChannel *GpPLGlueAudioDriver::CreateChannel()
{
IGpAudioChannel *channel = m_audioDriver->CreateChannel();
if (!channel)
return nullptr;
PortabilityLayer::HostAudioChannel *glueChannel = GpPLGlueAudioChannel::Create(channel);
if (!glueChannel)
{
channel->Destroy();
return nullptr;
}
return glueChannel;
}
GpPLGlueAudioDriver *GpPLGlueAudioDriver::GetInstance()
{
return &ms_instance;
}
void GpPLGlueAudioDriver::SetGpAudioDriver(IGpAudioDriver *audioDriver)
{
m_audioDriver = audioDriver;
}
GpPLGlueAudioDriver GpPLGlueAudioDriver::ms_instance;

View File

@@ -0,0 +1,22 @@
#pragma once
#include "HostAudioDriver.h"
class IGpAudioDriver;
class GpPLGlueAudioDriver final : public PortabilityLayer::HostAudioDriver
{
public:
GpPLGlueAudioDriver();
PortabilityLayer::HostAudioChannel *CreateChannel() override;
void SetGpAudioDriver(IGpAudioDriver *audioDriver);
static GpPLGlueAudioDriver *GetInstance();
private:
IGpAudioDriver *m_audioDriver;
static GpPLGlueAudioDriver ms_instance;
};

View File

@@ -6,9 +6,9 @@ GpPLGlueDisplayDriver::GpPLGlueDisplayDriver()
{
}
void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int &width, unsigned int &height)
void GpPLGlueDisplayDriver::GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp)
{
m_displayDriver->GetDisplayResolution(width, height);
m_displayDriver->GetDisplayResolution(width, height, bpp);
}
void GpPLGlueDisplayDriver::HideCursor()

View File

@@ -9,7 +9,7 @@ class GpPLGlueDisplayDriver final : public PortabilityLayer::HostDisplayDriver
public:
GpPLGlueDisplayDriver();
void GetDisplayResolution(unsigned int &width, unsigned int &height) override;
void GetDisplayResolution(unsigned int *width, unsigned int *height, PortabilityLayer::PixelFormat *bpp) override;
void HideCursor() override;
void SetGpDisplayDriver(IGpDisplayDriver *displayDriver);

View File

@@ -1,19 +1,40 @@
#include "GpSystemServices_Win32.h"
#include "GpSystemServices_Win32.h"
#include "GpMutex_Win32.h"
#include "GpThreadEvent_Win32.h"
#include <assert.h>
#pragma push_macro("CreateMutex")
#ifdef CreateMutex
#undef CreateMutex
#endif
GpSystemServices_Win32::GpSystemServices_Win32()
{
}
uint32_t GpSystemServices_Win32::GetTime() const
{
// PL_NotYetImplemented
return 0;
}
PortabilityLayer::HostMutex *GpSystemServices_Win32::CreateMutex()
{
return GpMutex_Win32::Create();
}
#include <assert.h>
GpSystemServices_Win32::GpSystemServices_Win32()
{
}
uint32_t GpSystemServices_Win32::GetTime() const
{
return 0;
}
GpSystemServices_Win32 *GpSystemServices_Win32::GetInstance()
{
return &ms_instance;
}
GpSystemServices_Win32 GpSystemServices_Win32::ms_instance;
PortabilityLayer::HostThreadEvent *GpSystemServices_Win32::CreateThreadEvent(bool autoReset, bool startSignaled)
{
return GpThreadEvent_Win32::Create(autoReset, startSignaled);
}
GpSystemServices_Win32 *GpSystemServices_Win32::GetInstance()
{
return &ms_instance;
}
GpSystemServices_Win32 GpSystemServices_Win32::ms_instance;
#pragma pop_macro("CreateMutex")

View File

@@ -1,19 +1,28 @@
#pragma once
#include "HostSystemServices.h"
#include "GpCoreDefs.h"
#include "GpWindows.h"
class GpSystemServices_Win32 final : public PortabilityLayer::HostSystemServices
{
public:
GpSystemServices_Win32();
uint32_t GetTime() const override;
static GpSystemServices_Win32 *GetInstance();
private:
static GpSystemServices_Win32 ms_instance;
};
#pragma once
#include "HostSystemServices.h"
#include "GpCoreDefs.h"
#include "GpWindows.h"
#pragma push_macro("CreateMutex")
#ifdef CreateMutex
#undef CreateMutex
#endif
class GpSystemServices_Win32 final : public PortabilityLayer::HostSystemServices
{
public:
GpSystemServices_Win32();
uint32_t GetTime() const override;
PortabilityLayer::HostMutex *CreateMutex() override;
PortabilityLayer::HostThreadEvent *CreateThreadEvent(bool autoReset, bool startSignaled) override;
static GpSystemServices_Win32 *GetInstance();
private:
static GpSystemServices_Win32 ms_instance;
};
#pragma pop_macro("CreateMutex")

View File

@@ -0,0 +1,51 @@
#include "GpThreadEvent_Win32.h"
#include <stdlib.h>
#include <new>
void GpThreadEvent_Win32::Wait()
{
WaitForSingleObject(m_event, INFINITE);
}
void GpThreadEvent_Win32::WaitTimed(uint32_t msec)
{
WaitForSingleObject(m_event, static_cast<DWORD>(msec));
}
void GpThreadEvent_Win32::Signal()
{
SetEvent(m_event);
}
void GpThreadEvent_Win32::Destroy()
{
this->~GpThreadEvent_Win32();
free(this);
}
GpThreadEvent_Win32 *GpThreadEvent_Win32::Create(bool autoReset, bool startSignaled)
{
HANDLE handle = CreateEventA(nullptr, autoReset ? FALSE : TRUE, startSignaled ? TRUE : FALSE, nullptr);
if (handle == nullptr)
return nullptr;
void *storage = malloc(sizeof(GpThreadEvent_Win32));
if (!storage)
{
CloseHandle(handle);
return nullptr;
}
return new (storage) GpThreadEvent_Win32(handle);
}
GpThreadEvent_Win32::GpThreadEvent_Win32(const HANDLE &handle)
: m_event(handle)
{
}
GpThreadEvent_Win32::~GpThreadEvent_Win32()
{
CloseHandle(m_event);
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include "HostThreadEvent.h"
#include "GpWindows.h"
class GpThreadEvent_Win32 final : public PortabilityLayer::HostThreadEvent
{
public:
void Wait() override;
void WaitTimed(uint32_t msec) override;
void Signal() override;
void Destroy() override;
static GpThreadEvent_Win32 *Create(bool autoReset, bool startSignaled);
private:
explicit GpThreadEvent_Win32(const HANDLE &handle);
~GpThreadEvent_Win32();
HANDLE m_event;
};

View File

@@ -1,16 +0,0 @@
#pragma once
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
struct GPWindowsGlobals
{
HINSTANCE m_hInstance;
HINSTANCE m_hPrevInstance;
LPSTR m_cmdLine;
int m_nCmdShow;
};
extern GPWindowsGlobals g_gpWindowsGlobals;

View File

@@ -1,13 +0,0 @@
#pragma once
// Display drivers are responsible for timing and calling the game tick function.
class IGpDisplayDriver
{
public:
virtual ~IGpDisplayDriver() {}
virtual void Run() = 0;
virtual void Shutdown() = 0;
virtual void GetDisplayResolution(unsigned int &width, unsigned int &height) = 0;
};