Display driver loop refactor

This commit is contained in:
elasota
2021-03-26 17:05:38 -04:00
parent 48fe83bb33
commit c87f238563
30 changed files with 595 additions and 735 deletions

View File

@@ -91,7 +91,6 @@
<ClCompile Include="GpMain_Win32.cpp" />
<ClCompile Include="GpMutex_Win32.cpp" />
<ClCompile Include="GpSystemServices_Win32.cpp" />
<ClCompile Include="GpFiberStarter_Win32.cpp" />
<ClCompile Include="GpThreadEvent_Win32.cpp" />
</ItemGroup>
<ItemGroup>

View File

@@ -7,9 +7,6 @@
<ClCompile Include="GpFiber_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFiberStarter_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpFileStream_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@@ -1,56 +0,0 @@
#include "GpFiberStarter.h"
#include "GpFiber_Win32.h"
#include "GpWindows.h"
#include <assert.h>
namespace GpFiberStarter_Win32
{
struct FiberStartState
{
GpFiberStarter::ThreadFunc_t m_threadFunc;
IGpFiber *m_creatingFiber;
void *m_context;
};
static VOID WINAPI FiberStartRoutine(LPVOID lpThreadParameter)
{
const FiberStartState *tss = static_cast<const FiberStartState*>(lpThreadParameter);
GpFiberStarter::ThreadFunc_t threadFunc = tss->m_threadFunc;
IGpFiber *creatingFiber = tss->m_creatingFiber;
void *context = tss->m_context;
SwitchToFiber(static_cast<GpFiber_Win32*>(creatingFiber)->GetFiber());
threadFunc(context);
assert(!"Fiber function exited");
}
}
IGpFiber *GpFiberStarter::StartFiber(IGpSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber)
{
ULONG_PTR lowLimit;
ULONG_PTR highLimit;
#if 0
GetCurrentThreadStackLimits(&lowLimit, &highLimit);
ULONG_PTR stackSize = highLimit - lowLimit;
#else
ULONG_PTR stackSize = 1024 * 1024;
#endif
GpFiberStarter_Win32::FiberStartState startState;
startState.m_context = context;
startState.m_creatingFiber = creatingFiber;
startState.m_threadFunc = threadFunc;
void *fiber = CreateFiber(static_cast<SIZE_T>(stackSize), GpFiberStarter_Win32::FiberStartRoutine, &startState);
if (!fiber)
return nullptr;
SwitchToFiber(fiber);
return GpFiber_Win32::Create(fiber);
}

View File

@@ -319,11 +319,6 @@ bool GpFileSystem_Win32::ValidateFilePathUnicodeChar(uint32_t c) const
return false;
}
void GpFileSystem_Win32::SetMainThreadRelay(IGpThreadRelay *relay)
{
(void)relay;
}
void GpFileSystem_Win32::SetDelayCallback(GpFileSystem_Win32::DelayCallback_t delayCallback)
{
}

View File

@@ -21,7 +21,6 @@ public:
bool ValidateFilePath(const char *path, size_t sz) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
void SetMainThreadRelay(IGpThreadRelay *relay) override;
void SetDelayCallback(DelayCallback_t delayCallback) override;
const wchar_t *GetBasePath() const;

View File

@@ -450,7 +450,6 @@ bool GpFileSystem_Android::ResolvePath(PortabilityLayer::VirtualDirectory_t virt
GpFileSystem_Android::GpFileSystem_Android()
: m_activity(nullptr)
, m_relay(nullptr)
, m_delayCallback(nullptr)
, m_sourceExportMutex(nullptr)
, m_sourceExportFD(0)
@@ -680,25 +679,6 @@ bool GpFileSystem_Android::DeleteFile(PortabilityLayer::VirtualDirectory_t virtu
}
IGpDirectoryCursor *GpFileSystem_Android::ScanDirectoryNested(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
{
ScanDirectoryNestedContext ctx;
ctx.m_this = this;
ctx.m_returnValue = nullptr;
ctx.m_virtualDirectory = virtualDirectory;
ctx.m_paths = paths;
ctx.m_numPaths = numPaths;
m_relay->Invoke(ScanDirectoryNestedThunk, &ctx);
return ctx.m_returnValue;
}
void GpFileSystem_Android::ScanDirectoryNestedThunk(void *context)
{
ScanDirectoryNestedContext *ctx = static_cast<ScanDirectoryNestedContext*>(context);
ctx->m_returnValue = ctx->m_this->ScanDirectoryNestedInternal(ctx->m_virtualDirectory, ctx->m_paths, ctx->m_numPaths);
}
IGpDirectoryCursor *GpFileSystem_Android::ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, const char *const *paths, size_t numPaths)
{
if (virtualDirectory == PortabilityLayer::VirtualDirectories::kGameData || virtualDirectory == PortabilityLayer::VirtualDirectories::kApplicationData)
return ScanAssetDirectory(virtualDirectory, paths, numPaths);
@@ -752,11 +732,6 @@ bool GpFileSystem_Android::ValidateFilePathUnicodeChar(uint32_t c) const
return false;
}
void GpFileSystem_Android::SetMainThreadRelay(IGpThreadRelay *relay)
{
m_relay = relay;
}
void GpFileSystem_Android::SetDelayCallback(DelayCallback_t delayCallback)
{
m_delayCallback = delayCallback;

View File

@@ -27,7 +27,6 @@ public:
bool ValidateFilePath(const char *path, size_t pathLen) const override;
bool ValidateFilePathUnicodeChar(uint32_t ch) const override;
void SetMainThreadRelay(IGpThreadRelay *relay) override;
void SetDelayCallback(DelayCallback_t delayCallback) override;
void PostSourceExportRequest(bool cancelled, int fd, jobject pfd);
@@ -36,26 +35,12 @@ public:
static GpFileSystem_Android *GetInstance();
private:
struct ScanDirectoryNestedContext
{
GpFileSystem_Android *m_this;
IGpDirectoryCursor *m_returnValue;
PortabilityLayer::VirtualDirectory_t m_virtualDirectory;
char const *const *m_paths;
size_t m_numPaths;
};
static void ScanDirectoryNestedThunk(void *context);
IGpDirectoryCursor *ScanDirectoryNestedInternal(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
IGpDirectoryCursor *ScanAssetDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
IGpDirectoryCursor *ScanStorageDirectory(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths);
bool OpenSourceExportFD(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, int &fd, jobject &pfd);
bool ResolvePath(PortabilityLayer::VirtualDirectory_t virtualDirectory, char const* const* paths, size_t numPaths, std::string &resolution, bool &isAsset);
IGpThreadRelay *m_relay;
DelayCallback_t m_delayCallback;
jobject m_activity;

View File

@@ -4,7 +4,6 @@
#include "GpAudioDriverFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpGlobalConfig.h"
#include "GpFiber_Thread.h"
#include "GpFileSystem_Android.h"
#include "GpFontHandlerFactory.h"
#include "GpInputDriverFactory.h"

View File

@@ -15,8 +15,7 @@ LOCAL_CFLAGS := -DGP_DEBUG_CONFIG=0
# Add your application source files here...
LOCAL_SRC_FILES := \
GpThreadEvent_Cpp11.cpp \
GpSystemServices_POSIX.cpp \
GpFiber_Thread.cpp \
GpFiberStarter_Thread.cpp \
GpSystemServices_POSIX.cpp
include $(BUILD_STATIC_LIBRARY)

View File

@@ -1,68 +0,0 @@
#include "GpFiberStarter.h"
#include "GpFiber_Thread.h"
#include "IGpSystemServices.h"
#include "IGpThreadEvent.h"
#include <assert.h>
namespace GpFiberStarter_Thread
{
struct FiberStartState
{
GpFiberStarter::ThreadFunc_t m_threadFunc;
IGpThreadEvent *m_creatingReturnEvent;
IGpThreadEvent *m_creatingWakeEvent;
void *m_context;
};
static int FiberStartRoutine(void *lpThreadParameter)
{
const FiberStartState *tss = static_cast<const FiberStartState*>(lpThreadParameter);
GpFiberStarter::ThreadFunc_t threadFunc = tss->m_threadFunc;
IGpThreadEvent *creatingReturnEvent = tss->m_creatingReturnEvent;
IGpThreadEvent *wakeEvent = tss->m_creatingWakeEvent;
void *context = tss->m_context;
creatingReturnEvent->Signal();
wakeEvent->Wait();
threadFunc(context);
return 0;
}
}
IGpFiber *GpFiberStarter::StartFiber(IGpSystemServices *systemServices, ThreadFunc_t threadFunc, void *context, IGpFiber *creatingFiber)
{
IGpThreadEvent *returnEvent = systemServices->CreateThreadEvent(true, false);
if (!returnEvent)
return nullptr;
IGpThreadEvent *wakeEvent = systemServices->CreateThreadEvent(true, false);
if (!wakeEvent)
{
returnEvent->Destroy();
return nullptr;
}
GpFiberStarter_Thread::FiberStartState startState;
startState.m_context = context;
startState.m_creatingReturnEvent = returnEvent;
startState.m_creatingWakeEvent = wakeEvent;
startState.m_threadFunc = threadFunc;
void *thread = systemServices->CreateThread(GpFiberStarter_Thread::FiberStartRoutine, &startState);
if (!thread)
{
returnEvent->Destroy();
wakeEvent->Destroy();
return nullptr;
}
returnEvent->Wait();
returnEvent->Destroy();
return new GpFiber_Thread(thread, wakeEvent);
}

View File

@@ -1,29 +0,0 @@
#include "GpFiber_Thread.h"
#include "IGpThreadEvent.h"
GpFiber_Thread::GpFiber_Thread(void *thread, IGpThreadEvent *threadEvent)
: m_event(threadEvent)
, m_thread(thread)
{
}
GpFiber_Thread::~GpFiber_Thread()
{
m_event->Destroy();
}
void GpFiber_Thread::YieldTo(IGpFiber *toFiber)
{
static_cast<GpFiber_Thread*>(toFiber)->m_event->Signal();
m_event->Wait();
}
void GpFiber_Thread::YieldToTerminal(IGpFiber *toFiber)
{
static_cast<GpFiber_Thread*>(toFiber)->m_event->Signal();
}
void GpFiber_Thread::Destroy()
{
delete this;
}

View File

@@ -1,23 +0,0 @@
#pragma once
#include "IGpFiber.h"
struct IGpThreadEvent;
class GpFiber_Thread final : public IGpFiber
{
public:
explicit GpFiber_Thread(void *thread, IGpThreadEvent *threadEvent);
~GpFiber_Thread();
void YieldTo(IGpFiber *fromFiber) override;
void YieldToTerminal(IGpFiber *fromFiber) override;
void Destroy() override;
private:
static int InternalThreadFunction(void *data);
bool m_isDestroying;
IGpThreadEvent *m_event;
void *m_thread;
};

View File

@@ -84,8 +84,6 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\AerofoilPortable\GpFiberStarter_Thread.cpp" />
<ClCompile Include="..\AerofoilPortable\GpFiber_Thread.cpp" />
<ClCompile Include="..\Aerofoil\GpColorCursor_Win32.cpp" />
<ClCompile Include="..\Aerofoil\GpFileStream_Win32.cpp" />
<ClCompile Include="..\Aerofoil\GpFileSystem_Win32.cpp" />

View File

@@ -66,12 +66,6 @@
<ClCompile Include="GpInputDriver_SDL_Gamepad.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\AerofoilPortable\GpFiber_Thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\AerofoilPortable\GpFiberStarter_Thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ShaderCode\Functions.h">

View File

@@ -1,8 +1,8 @@
#include "IGpDisplayDriver.h"
#include "CoreDefs.h"
#include "GpApplicationName.h"
#include "GpComPtr.h"
#include "GpFiber_Thread.h"
#include "GpDisplayDriverProperties.h"
#include "GpVOSEvent.h"
#include "GpRingBuffer.h"
@@ -730,12 +730,13 @@ public:
explicit GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties);
~GpDisplayDriver_SDL_GL2();
bool Init();
bool Init() override;
void ServeTicks(int tickCount) override;
void ForceSync() override;
void Shutdown() override;
void TranslateSDLMessage(const SDL_Event *msg, IGpVOSEventQueue *eventQueue, float pixelScaleX, float pixelScaleY, bool obstructiveTextInput);
void Run() override;
void Shutdown() override;
void GetInitialDisplayResolution(unsigned int *width, unsigned int *height) override;
IGpDisplayDriverSurface *CreateSurface(size_t width, size_t height, size_t pitch, GpPixelFormat_t pixelFormat, SurfaceInvalidateCallback_t invalidateCallback, void *invalidateContext) override;
void DrawSurface(IGpDisplayDriverSurface *surface, int32_t x, int32_t y, size_t width, size_t height, const GpDisplayDriverSurfaceEffects *effects) override;
@@ -798,7 +799,7 @@ private:
void ScaleVirtualScreen();
GpDisplayDriverTickStatus_t PresentFrameAndSync();
bool SyncRender();
GpGLFunctions m_gl;
GpDisplayDriverProperties m_properties;
@@ -907,9 +908,6 @@ private:
EGpStandardCursor_t m_pendingStandardCursor;
bool m_mouseIsInClientArea;
IGpFiber *m_vosFiber;
IGpThreadEvent *m_vosEvent;
float m_bgColor[4];
bool m_bgIsDark;
@@ -1194,8 +1192,6 @@ GpDisplayDriver_SDL_GL2::GpDisplayDriver_SDL_GL2(const GpDisplayDriverProperties
, m_pixelScaleX(1.0f)
, m_pixelScaleY(1.0f)
, m_useUpscaleFilter(false)
, m_vosFiber(nullptr)
, m_vosEvent(nullptr)
, m_pendingCursor(nullptr)
, m_activeCursor(nullptr)
, m_currentStandardCursor(EGpStandardCursors::kArrow)
@@ -1340,9 +1336,247 @@ GpDisplayDriver_SDL_GL2::~GpDisplayDriver_SDL_GL2()
bool GpDisplayDriver_SDL_GL2::Init()
{
#if GP_GL_IS_OPENGL_4_CONTEXT
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
#else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
#endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
IGpLogDriver *logger = m_properties.m_logger;
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
if (m_properties.m_systemServices->IsFullscreenOnStartup())
{
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
m_isFullScreen = true;
}
else
windowFlags |= SDL_WINDOW_RESIZABLE;
m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, windowFlags);
if (m_isFullScreen)
{
m_windowModeRevertWidth = m_windowWidthPhysical;
m_windowModeRevertHeight = m_windowHeightPhysical;
int windowWidth = 0;
int windowHeight = 0;
SDL_GetWindowSize(m_window, &windowWidth, &windowHeight);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Initialized fullscreen SDL window %i x %i", windowWidth, windowHeight);
m_windowWidthPhysical = windowWidth;
m_windowHeightPhysical = windowHeight;
uint32_t desiredWidth = windowWidth;
uint32_t desiredHeight = windowHeight;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = m_pixelScaleX;
float pixelScaleY = m_pixelScaleY;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "AdjustedRequestedResolution succeeded. Virtual dimensions %i x %i Pixel scale %f x %f", static_cast<int>(virtualWidth), static_cast<int>(virtualHeight), static_cast<float>(pixelScaleX), static_cast<float>(pixelScaleY));
}
else
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "AdjustedRequestedResolution failed!");
}
}
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
if (!obstructiveTextInput)
SDL_StartTextInput();
StartOpenGLForWindow(logger);
if (!m_gl.LookUpFunctions())
return false;
m_initialWidthVirtual = m_windowWidthVirtual;
m_initialHeightVirtual = m_windowHeightVirtual;
return true;
}
void GpDisplayDriver_SDL_GL2::ServeTicks(int ticks)
{
IGpLogDriver *logger = m_properties.m_logger;
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
for (;;)
{
SDL_Event msg;
if (SDL_PollEvent(&msg) != 0)
{
switch (msg.type)
{
case SDL_MOUSEMOTION:
{
if (!m_mouseIsInClientArea)
m_mouseIsInClientArea = true;
}
break;
//case SDL_MOUSELEAVE: // Does SDL support this??
// m_mouseIsInClientArea = false;
// break;
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to device loss (Type: %i)", static_cast<int>(msg.type));
m_contextLost = true;
}
break;
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERDEVICEREMAPPED:
if (IGpInputDriverSDLGamepad *gamepadDriver = IGpInputDriverSDLGamepad::GetInstance())
gamepadDriver->ProcessSDLEvent(msg);
break;
}
TranslateSDLMessage(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY, obstructiveTextInput);
}
else
{
if (m_isFullScreen != m_isFullScreenDesired)
{
if (m_isFullScreenDesired)
BecomeFullScreen();
else
BecomeWindowed();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to fullscreen state change");
m_contextLost = true;
continue;
}
int clientWidth = 0;
int clientHeight = 0;
SDL_GetWindowSize(m_window, &clientWidth, &clientHeight);
unsigned int desiredWidth = clientWidth;
unsigned int desiredHeight = clientHeight;
if (desiredWidth != m_windowWidthPhysical || desiredHeight != m_windowHeightPhysical || m_isResolutionResetDesired)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Detected window size change");
uint32_t prevWidthPhysical = m_windowWidthPhysical;
uint32_t prevHeightPhysical = m_windowHeightPhysical;
uint32_t prevWidthVirtual = m_windowWidthVirtual;
uint32_t prevHeightVirtual = m_windowHeightVirtual;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = 1.0f;
float pixelScaleY = 1.0f;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
bool resizedOK = ResizeOpenGLWindow(m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, logger);
if (!resizedOK)
break; // Critical video driver error, exit
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
m_isResolutionResetDesired = false;
if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent())
{
resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeightVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
}
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to window size change");
m_contextLost = true;
continue;
}
}
if (m_contextLost)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Resetting OpenGL context. Physical: %i x %i Virtual %i x %i", static_cast<int>(m_windowWidthPhysical), static_cast<int>(m_windowHeightPhysical), static_cast<int>(m_windowWidthVirtual), static_cast<int>(m_windowHeightVirtual));
// Drop everything and reset
m_res.~InstancedResources();
new (&m_res) InstancedResources();
if (m_firstSurface)
m_firstSurface->DestroyAll();
if (!InitResources(m_windowWidthPhysical, m_windowHeightPhysical, m_windowWidthVirtual, m_windowHeightVirtual))
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to InitResources failing");
break;
}
if (m_firstSurface)
m_firstSurface->RecreateAll();
m_contextLost = false;
continue;
}
bool wantTextInput = m_properties.m_systemServices->IsTextInputEnabled();
if (wantTextInput != m_textInputEnabled)
{
m_textInputEnabled = wantTextInput;
if (m_textInputEnabled)
SDL_StartTextInput();
else
SDL_StopTextInput();
}
// Handle dismissal of on-screen keyboard
const bool isTextInputActuallyActive = SDL_IsTextInputActive();
m_textInputEnabled = isTextInputActuallyActive;
m_properties.m_systemServices->SetTextInputEnabled(isTextInputActuallyActive);
if (SyncRender())
{
ticks--;
if (ticks <= 0)
break;
}
}
}
}
void GpDisplayDriver_SDL_GL2::ForceSync()
{
m_frameTimeAccumulated = std::chrono::nanoseconds::zero();
}
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y, float pixelScaleX, float pixelScaleY)
{
if (GpVOSEvent *evt = eventQueue->QueueEvent())
@@ -1836,248 +2070,6 @@ void GpDisplayDriver_SDL_GL2::TranslateSDLMessage(const SDL_Event *msg, IGpVOSEv
}
}
void GpDisplayDriver_SDL_GL2::Run()
{
#if GP_GL_IS_OPENGL_4_CONTEXT
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
#else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
#endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
IGpLogDriver *logger = m_properties.m_logger;
m_vosEvent = m_properties.m_systemServices->CreateThreadEvent(true, false);
m_vosFiber = new GpFiber_Thread(nullptr, m_vosEvent);
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
if (m_properties.m_systemServices->IsFullscreenOnStartup())
{
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
m_isFullScreen = true;
}
else
windowFlags |= SDL_WINDOW_RESIZABLE;
m_window = SDL_CreateWindow(GP_APPLICATION_NAME, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_windowWidthPhysical, m_windowHeightPhysical, windowFlags);
if (m_isFullScreen)
{
m_windowModeRevertWidth = m_windowWidthPhysical;
m_windowModeRevertHeight = m_windowHeightPhysical;
int windowWidth = 0;
int windowHeight = 0;
SDL_GetWindowSize(m_window, &windowWidth, &windowHeight);
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Initialized fullscreen SDL window %i x %i", windowWidth, windowHeight);
m_windowWidthPhysical = windowWidth;
m_windowHeightPhysical = windowHeight;
uint32_t desiredWidth = windowWidth;
uint32_t desiredHeight = windowHeight;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = m_pixelScaleX;
float pixelScaleY = m_pixelScaleY;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "AdjustedRequestedResolution succeeded. Virtual dimensions %i x %i Pixel scale %f x %f", static_cast<int>(virtualWidth), static_cast<int>(virtualHeight), static_cast<float>(pixelScaleX), static_cast<float>(pixelScaleY));
}
else
{
if (logger)
logger->Printf(IGpLogDriver::Category_Error, "AdjustedRequestedResolution failed!");
}
}
const bool obstructiveTextInput = m_properties.m_systemServices->IsTextInputObstructive();
if (!obstructiveTextInput)
SDL_StartTextInput();
StartOpenGLForWindow(logger);
if (!m_gl.LookUpFunctions())
return;
m_initialWidthVirtual = m_windowWidthVirtual;
m_initialHeightVirtual = m_windowHeightVirtual;
for (;;)
{
SDL_Event msg;
if (SDL_PollEvent(&msg) != 0)
{
switch (msg.type)
{
case SDL_MOUSEMOTION:
{
if (!m_mouseIsInClientArea)
m_mouseIsInClientArea = true;
}
break;
//case SDL_MOUSELEAVE: // Does SDL support this??
// m_mouseIsInClientArea = false;
// break;
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to device loss (Type: %i)", static_cast<int>(msg.type));
m_contextLost = true;
}
break;
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERDEVICEADDED:
case SDL_CONTROLLERDEVICEREMOVED:
case SDL_CONTROLLERDEVICEREMAPPED:
if (IGpInputDriverSDLGamepad *gamepadDriver = IGpInputDriverSDLGamepad::GetInstance())
gamepadDriver->ProcessSDLEvent(msg);
break;
}
TranslateSDLMessage(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY, obstructiveTextInput);
}
else
{
if (m_isFullScreen != m_isFullScreenDesired)
{
if (m_isFullScreenDesired)
BecomeFullScreen();
else
BecomeWindowed();
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to fullscreen state change");
m_contextLost = true;
continue;
}
int clientWidth = 0;
int clientHeight = 0;
SDL_GetWindowSize(m_window, &clientWidth, &clientHeight);
unsigned int desiredWidth = clientWidth;
unsigned int desiredHeight = clientHeight;
if (desiredWidth != m_windowWidthPhysical || desiredHeight != m_windowHeightPhysical || m_isResolutionResetDesired)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Detected window size change");
uint32_t prevWidthPhysical = m_windowWidthPhysical;
uint32_t prevHeightPhysical = m_windowHeightPhysical;
uint32_t prevWidthVirtual = m_windowWidthVirtual;
uint32_t prevHeightVirtual = m_windowHeightVirtual;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = 1.0f;
float pixelScaleY = 1.0f;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
bool resizedOK = ResizeOpenGLWindow(m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, logger);
if (!resizedOK)
break; // Critical video driver error, exit
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
m_isResolutionResetDesired = false;
if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent())
{
resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeightVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
}
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Triggering GL context reset due to window size change");
m_contextLost = true;
continue;
}
}
if (m_contextLost)
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Resetting OpenGL context. Physical: %i x %i Virtual %i x %i", static_cast<int>(m_windowWidthPhysical), static_cast<int>(m_windowHeightPhysical), static_cast<int>(m_windowWidthVirtual), static_cast<int>(m_windowHeightVirtual));
// Drop everything and reset
m_res.~InstancedResources();
new (&m_res) InstancedResources();
if (m_firstSurface)
m_firstSurface->DestroyAll();
if (!InitResources(m_windowWidthPhysical, m_windowHeightPhysical, m_windowWidthVirtual, m_windowHeightVirtual))
{
if (logger)
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to InitResources failing");
break;
}
if (m_firstSurface)
m_firstSurface->RecreateAll();
m_contextLost = false;
continue;
}
bool wantTextInput = m_properties.m_systemServices->IsTextInputEnabled();
if (wantTextInput != m_textInputEnabled)
{
m_textInputEnabled = wantTextInput;
if (m_textInputEnabled)
SDL_StartTextInput();
else
SDL_StopTextInput();
}
// Handle dismissal of on-screen keyboard
const bool isTextInputActuallyActive = SDL_IsTextInputActive();
m_textInputEnabled = isTextInputActuallyActive;
m_properties.m_systemServices->SetTextInputEnabled(isTextInputActuallyActive);
GpDisplayDriverTickStatus_t tickStatus = PresentFrameAndSync();
if (tickStatus == GpDisplayDriverTickStatuses::kFatalFault || tickStatus == GpDisplayDriverTickStatuses::kApplicationTerminated)
{
if (logger)
{
if (tickStatus == GpDisplayDriverTickStatuses::kFatalFault)
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to fatal fault");
if (tickStatus == GpDisplayDriverTickStatuses::kApplicationTerminated)
logger->Printf(IGpLogDriver::Category_Information, "Terminating display driver due to application termination");
}
break;
}
}
}
// Exit
}
void GpDisplayDriver_SDL_GL2::Shutdown()
{
this->~GpDisplayDriver_SDL_GL2();
@@ -3059,8 +3051,15 @@ bool GpDisplayDriver_SDL_GL2::BlitQuadProgram::Link(GpDisplayDriver_SDL_GL2 *dri
return true;
}
GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
bool GpDisplayDriver_SDL_GL2::SyncRender()
{
if (m_frameTimeAccumulated >= m_frameTimeSliceSize)
{
m_frameTimeAccumulated -= m_frameTimeSliceSize;
return true;
}
SynchronizeCursors();
float bgColor[4];
@@ -3182,22 +3181,9 @@ GpDisplayDriverTickStatus_t GpDisplayDriver_SDL_GL2::PresentFrameAndSync()
}
m_frameTimeAccumulated += frameTimeStep;
while (m_frameTimeAccumulated >= m_frameTimeSliceSize)
{
GpDisplayDriverTickStatus_t tickStatus = m_properties.m_tickFunc(m_properties.m_tickFuncContext, m_vosFiber);
m_frameTimeAccumulated -= m_frameTimeSliceSize;
if (tickStatus == GpDisplayDriverTickStatuses::kSynchronizing)
{
m_frameTimeAccumulated = std::chrono::high_resolution_clock::duration::zero();
break;
}
else if (tickStatus != GpDisplayDriverTickStatuses::kOK)
return tickStatus;
}
}
return GpDisplayDriverTickStatuses::kOK;
return false;
}
IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProperties &properties)
@@ -3206,18 +3192,9 @@ IGpDisplayDriver *GpDriver_CreateDisplayDriver_SDL_GL2(const GpDisplayDriverProp
if (!driver)
return nullptr;
new (driver) GpDisplayDriver_SDL_GL2(properties);
if (!driver->Init())
{
driver->Shutdown();
return nullptr;
}
return driver;
return new (driver) GpDisplayDriver_SDL_GL2(properties);
}
template<class T>
T *GpGLObjectImpl<T>::Create(GpDisplayDriver_SDL_GL2 *driver)
{

View File

@@ -20,7 +20,6 @@ public:
void PL_IncrementTickCounter(uint32_t count) override;
void PL_Render(IGpDisplayDriver *displayDriver) override;
GpDriverCollection *PL_GetDriverCollection() override;
void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) override;
bool PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY) override;
};
@@ -50,11 +49,6 @@ GpDriverCollection *GpAppInterfaceImpl::PL_GetDriverCollection()
return PLDrivers::GetDriverCollection();
}
void GpAppInterfaceImpl::PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context)
{
PortabilityLayer::InstallHostSuspendHook(hook, context);
}
bool GpAppInterfaceImpl::PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY)
{
PortabilityLayer::DisplayDeviceManager::IResolutionChangeHandler *handler = PortabilityLayer::DisplayDeviceManager::GetInstance()->GetResolutionChangeHandler();

View File

@@ -647,7 +647,7 @@ bool ExportSourceToStream (GpIOStream *stream)
if (!state.m_sourcePkgStream)
return false;
PLSysCalls::ForceSyncFrame();
ForceSyncFrame();
PLSysCalls::Sleep(1);
size_t sourcePkgSize = state.m_sourcePkgStream->Size();
@@ -655,7 +655,7 @@ bool ExportSourceToStream (GpIOStream *stream)
if (!RetrieveCompositeDirSize(PortabilityLayer::VirtualDirectories::kGameData, looseFilesSize))
return false;
PLSysCalls::ForceSyncFrame();
ForceSyncFrame();
PLSysCalls::Sleep(1);
size_t applicationDataSize = 0;
@@ -663,7 +663,7 @@ bool ExportSourceToStream (GpIOStream *stream)
if (!RetrieveSingleFileSize(PortabilityLayer::VirtualDirectories::kApplicationData, &appResourcesPath, 1, applicationDataSize))
return false;
PLSysCalls::ForceSyncFrame();
ForceSyncFrame();
PLSysCalls::Sleep(1);
state.m_dataTotal = applicationDataSize + looseFilesSize + sourcePkgSize;

View File

@@ -29,7 +29,9 @@ struct IGpDisplayDriver
{
typedef void (*SurfaceInvalidateCallback_t) (void *context);
virtual void Run() = 0;
virtual bool Init() = 0;
virtual void ServeTicks(int tickCount) = 0;
virtual void ForceSync() = 0;
virtual void Shutdown() = 0;
// Returns the initial resolution before any display resolution events are posted

View File

@@ -7,7 +7,6 @@
#include <stddef.h>
class GpIOStream;
struct IGpThreadRelay;
struct IGpDirectoryCursor;
struct IGpFileSystem
@@ -24,7 +23,6 @@ public:
virtual bool ValidateFilePath(const char *path, size_t pathLen) const = 0;
virtual bool ValidateFilePathUnicodeChar(uint32_t ch) const = 0;
virtual void SetMainThreadRelay(IGpThreadRelay *relay) = 0;
virtual void SetDelayCallback(DelayCallback_t delayCallback) = 0;
// Helpers

View File

@@ -622,6 +622,161 @@ bool GpDisplayDriverD3D11::InitResources(uint32_t virtualWidth, uint32_t virtual
}
bool GpDisplayDriverD3D11::SyncRender()
{
fprintf(stderr, "Test\n");
if (m_frameTimeAccumulated >= m_frameTimeSliceSize)
{
m_frameTimeAccumulated -= m_frameTimeSliceSize;
return true;
}
SynchronizeCursors();
FLOAT bgColor[4];
for (int i = 0; i < 4; i++)
bgColor[i] = m_bgColor[i];
if (m_bgIsDark)
{
for (int i = 0; i < 3; i++)
bgColor[i] *= 0.25f;
}
m_deviceContext->ClearRenderTargetView(m_virtualScreenTextureRTV, bgColor);
//ID3D11RenderTargetView *const rtv = m_backBufferRTV;
ID3D11RenderTargetView *const vsRTV = m_virtualScreenTextureRTV;
m_deviceContext->OMSetRenderTargets(1, &vsRTV, nullptr);
{
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = static_cast<FLOAT>(m_windowWidthVirtual);
viewport.Height = static_cast<FLOAT>(m_windowHeightVirtual);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
m_deviceContext->RSSetViewports(1, &viewport);
}
m_properties.m_renderFunc(m_properties.m_renderFuncContext);
ScaleVirtualScreen();
DXGI_PRESENT_PARAMETERS presentParams;
ZeroMemory(&presentParams, sizeof(presentParams));
UINT lastPresentCount = 0;
if (FAILED(m_swapChain->GetLastPresentCount(&lastPresentCount)))
return GpDisplayDriverTickStatuses::kNonFatalFault;
if (FAILED(m_swapChain->Present1(1, 0, &presentParams)))
return GpDisplayDriverTickStatuses::kNonFatalFault;
//DebugPrintf("r: %i\n", static_cast<int>(r));
DXGI_FRAME_STATISTICS stats;
if (FAILED(m_swapChain->GetFrameStatistics(&stats)))
return GpDisplayDriverTickStatuses::kNonFatalFault;
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;
}
return false;
}
GpDisplayDriverTickStatus_t GpDisplayDriverD3D11::PresentFrameAndSync()
{
SynchronizeCursors();
@@ -1094,6 +1249,155 @@ void GpDisplayDriverD3D11::BecomeWindowed(LONG &windowStyle)
windowStyle = (WS_VISIBLE | WS_OVERLAPPEDWINDOW);
}
bool GpDisplayDriverD3D11::Init()
{
IGpLogDriver *logger = m_properties.m_logger;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(wc));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WinProc;
wc.hInstance = m_osGlobals->m_hInstance;
wc.hCursor = m_arrowCursor;
wc.hIcon = m_osGlobals->m_hIcon;
wc.hIconSm = m_osGlobals->m_hIconSm;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "GPD3D11WindowClass";
RegisterClassEx(&wc);
m_windowStyle = WS_OVERLAPPEDWINDOW;
HMENU menus = NULL;
// TODO: Fix the resolution here
RECT wr = { 0, 0, static_cast<DWORD>(m_windowWidthPhysical), static_cast<DWORD>(m_windowHeightPhysical) };
AdjustWindowRect(&wr, m_windowStyle, menus != NULL);
m_osGlobals->m_hwnd = CreateWindowExW(NULL, L"GPD3D11WindowClass", GP_APPLICATION_NAME_W, WS_OVERLAPPEDWINDOW, 300, 300, wr.right - wr.left, wr.bottom - wr.top, NULL, menus, m_osGlobals->m_hInstance, NULL);
ShowWindow(m_osGlobals->m_hwnd, m_osGlobals->m_nCmdShow);
StartD3DForWindow(m_osGlobals->m_hwnd, m_swapChain, m_device, m_deviceContext, logger);
InitResources(m_windowWidthVirtual, m_windowHeightVirtual);
LARGE_INTEGER lastTimestamp;
memset(&lastTimestamp, 0, sizeof(lastTimestamp));
m_initialWidth = m_windowWidthVirtual;
m_initialHeight = m_windowHeightVirtual;
return true;
}
void GpDisplayDriverD3D11::ServeTicks(int tickCount)
{
HMENU menus = NULL;
IGpLogDriver *logger = m_properties.m_logger;
MSG msg;
for (;;)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
DispatchMessage(&msg);
{
if (msg.message == WM_MOUSEMOVE)
{
if (!m_mouseIsInClientArea)
{
m_mouseIsInClientArea = true;
TRACKMOUSEEVENT tme;
ZeroMemory(&tme, sizeof(tme));
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_osGlobals->m_hwnd;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
}
}
else if (msg.message == WM_MOUSELEAVE)
m_mouseIsInClientArea = false;
m_osGlobals->m_translateWindowsMessageFunc(&msg, m_properties.m_eventQueue, m_pixelScaleX, m_pixelScaleY);
}
}
else
{
if (m_isFullScreen != m_isFullScreenDesired)
{
if (m_isFullScreenDesired)
BecomeFullScreen(m_windowStyle);
else
BecomeWindowed(m_windowStyle);
}
RECT clientRect;
GetClientRect(m_osGlobals->m_hwnd, &clientRect);
unsigned int desiredWidth = clientRect.right - clientRect.left;
unsigned int desiredHeight = clientRect.bottom - clientRect.top;
if (clientRect.right - clientRect.left != m_windowWidthPhysical || clientRect.bottom - clientRect.top != m_windowHeightPhysical || m_isResolutionResetDesired)
{
uint32_t prevWidthPhysical = m_windowWidthPhysical;
uint32_t prevHeightPhysical = m_windowHeightPhysical;
uint32_t prevWidthVirtual = m_windowWidthVirtual;
uint32_t prevHeightVirtual = m_windowHeightVirtual;
uint32_t virtualWidth = m_windowWidthVirtual;
uint32_t virtualHeight = m_windowHeightVirtual;
float pixelScaleX = 1.0f;
float pixelScaleY = 1.0f;
if (desiredWidth < 640)
desiredWidth = 640;
if (desiredHeight < 480)
desiredHeight = 480;
if (m_properties.m_adjustRequestedResolutionFunc(m_properties.m_adjustRequestedResolutionFuncContext, desiredWidth, desiredHeight, virtualWidth, virtualHeight, pixelScaleX, pixelScaleY))
{
bool resizedOK = ResizeD3DWindow(m_osGlobals->m_hwnd, m_windowWidthPhysical, m_windowHeightPhysical, desiredWidth, desiredHeight, m_windowStyle, menus, logger);
resizedOK = resizedOK && DetachSwapChain();
resizedOK = resizedOK && ResizeSwapChain(m_swapChain, m_windowWidthPhysical, m_windowHeightPhysical);
resizedOK = resizedOK && InitBackBuffer(virtualWidth, virtualHeight);
if (!resizedOK)
break; // Critical video driver error, exit
m_windowWidthVirtual = virtualWidth;
m_windowHeightVirtual = virtualHeight;
m_pixelScaleX = pixelScaleX;
m_pixelScaleY = pixelScaleY;
m_isResolutionResetDesired = false;
if (GpVOSEvent *resizeEvent = m_properties.m_eventQueue->QueueEvent())
{
resizeEvent->m_eventType = GpVOSEventTypes::kVideoResolutionChanged;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevWidth = prevWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_prevHeight = prevHeightVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newWidth = m_windowWidthVirtual;
resizeEvent->m_event.m_resolutionChangedEvent.m_newHeight = m_windowHeightVirtual;
}
}
}
if (SyncRender())
{
tickCount--;
if (tickCount <= 0)
break;
}
}
}
}
void GpDisplayDriverD3D11::Run()
{
IGpLogDriver *logger = m_properties.m_logger;

View File

@@ -36,6 +36,8 @@ struct ID3D11VertexShader;
class GpDisplayDriverD3D11 : public IGpDisplayDriver, public IGpPrefsHandler
{
public:
bool Init() override;
void ServeTicks(int tickCount) override;
void Run() override;
void Shutdown() override;
@@ -116,6 +118,7 @@ private:
bool InitBackBuffer(uint32_t virtualWidth, uint32_t virtualHeight);
bool InitResources(uint32_t virtualWidth, uint32_t virtualHeight);
GpDisplayDriverTickStatus_t PresentFrameAndSync();
bool SyncRender();
void ScaleVirtualScreen();
void SynchronizeCursors();
@@ -157,6 +160,8 @@ private:
GpRingBuffer<CompactedPresentHistoryItem, 60> m_presentHistory;
GpDisplayDriverProperties m_properties;
LONG m_windowStyle;
LARGE_INTEGER m_syncTimeBase;
LARGE_INTEGER m_QPFrequency;
UINT m_expectedSyncDelta;

View File

@@ -11,16 +11,13 @@
#include <assert.h>
GpAppEnvironment::GpAppEnvironment()
: m_applicationState(ApplicationState_NotStarted)
, m_displayDriver(nullptr)
: m_displayDriver(nullptr)
, m_audioDriver(nullptr)
, m_inputDrivers(nullptr)
, m_numInputDrivers(0)
, m_fontHandler(nullptr)
, m_vosEventQueue(nullptr)
, m_systemServices(nullptr)
, m_applicationFiber(nullptr)
, m_vosFiber(nullptr)
, m_suspendCallID(PortabilityLayer::HostSuspendCallID_Unknown)
, m_suspendArgs(nullptr)
, m_suspendReturnValue(nullptr)
@@ -29,7 +26,6 @@ GpAppEnvironment::GpAppEnvironment()
GpAppEnvironment::~GpAppEnvironment()
{
assert(m_applicationFiber == nullptr);
}
void GpAppEnvironment::Init()
@@ -37,69 +33,13 @@ void GpAppEnvironment::Init()
GpAppInterface_Get()->ApplicationInit();
}
GpDisplayDriverTickStatus_t GpAppEnvironment::Tick(IGpFiber *vosFiber)
void GpAppEnvironment::Run()
{
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(m_systemServices, GpAppEnvironment::StaticAppThreadFunc, this, vosFiber);
m_applicationState = ApplicationState_Running;
break;
case ApplicationState_WaitingForEvents:
return GpDisplayDriverTickStatuses::kOK;
case ApplicationState_Running:
SynchronizeState();
m_vosFiber->YieldTo(m_applicationFiber);
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 == 0)
m_applicationState = ApplicationState_Running;
else
{
m_delaySuspendTicks--;
return GpDisplayDriverTickStatuses::kOK;
}
break;
case ApplicationState_Synchronizing:
if (m_delaySuspendTicks == 0)
m_applicationState = ApplicationState_Running;
else
{
m_delaySuspendTicks--;
return GpDisplayDriverTickStatuses::kSynchronizing;
}
break;
case ApplicationState_Terminated:
m_applicationFiber->Destroy();
m_applicationFiber = nullptr;
return GpDisplayDriverTickStatuses::kApplicationTerminated;
default:
assert(false);
break;
};
}
InitializeApplicationState();
GpAppInterface_Get()->ApplicationMain();
}
void GpAppEnvironment::Render()
{
GpAppInterface_Get()->PL_Render(m_displayDriver);
@@ -141,19 +81,6 @@ void GpAppEnvironment::SetSystemServices(IGpSystemServices *systemServices)
m_systemServices = systemServices;
}
void GpAppEnvironment::StaticAppThreadFunc(void *context)
{
static_cast<GpAppEnvironment*>(context)->AppThreadFunc();
}
void GpAppEnvironment::AppThreadFunc()
{
GpAppInterface_Get()->ApplicationMain();
m_applicationState = ApplicationState_Terminated;
m_applicationFiber->YieldToTerminal(m_vosFiber);
}
void GpAppEnvironment::InitializeApplicationState()
{
GpDriverCollection *drivers = GpAppInterface_Get()->PL_GetDriverCollection();
@@ -162,8 +89,6 @@ void GpAppEnvironment::InitializeApplicationState()
drivers->SetDrivers<GpDriverIDs::kInput>(m_inputDrivers, m_numInputDrivers);
drivers->SetDriver<GpDriverIDs::kFont>(m_fontHandler);
drivers->SetDriver<GpDriverIDs::kEventQueue>(m_vosEventQueue);
GpAppInterface_Get()->PL_InstallHostSuspendHook(GpAppEnvironment::StaticSuspendHookFunc, this);
}
void GpAppEnvironment::SynchronizeState()
@@ -172,36 +97,3 @@ void GpAppEnvironment::SynchronizeState()
for (size_t i = 0; i < numInputDrivers; i++)
m_inputDrivers[i]->ProcessInput();
}
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_applicationFiber->YieldTo(appEnv->m_vosFiber);
}
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;
case PortabilityLayer::HostSuspendCallID_ForceSyncFrame:
m_applicationState = ApplicationState_Synchronizing;
m_delaySuspendTicks = 1;
break;
case PortabilityLayer::HostSuspendCallID_CallOnVOSThread:
args[0].m_functionPtr(args[1].m_pointer);
m_applicationState = ApplicationState_Running;
break;
default:
assert(false);
}
}

View File

@@ -26,8 +26,8 @@ public:
~GpAppEnvironment();
void Init();
void Run();
GpDisplayDriverTickStatus_t Tick(IGpFiber *vosFiber);
void Render();
bool AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY);
@@ -39,34 +39,16 @@ public:
void SetSystemServices(IGpSystemServices *systemServices);
private:
enum ApplicationState
{
ApplicationState_NotStarted,
ApplicationState_WaitingForEvents,
ApplicationState_Running,
ApplicationState_Terminated,
ApplicationState_SystemCall,
ApplicationState_TimedSuspend,
ApplicationState_Synchronizing,
};
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;
IGpInputDriver *const* m_inputDrivers;
IGpFontHandler *m_fontHandler;
GpVOSEventQueue *m_vosEventQueue;
IGpSystemServices *m_systemServices;
IGpFiber *m_applicationFiber;
IGpFiber *m_vosFiber;
uint32_t m_delaySuspendTicks;
size_t m_numInputDrivers;

View File

@@ -1,4 +1,5 @@
#include "GpMain.h"
#include "GpAppInterface.h"
#include "GpAudioDriverFactory.h"
#include "GpAudioDriverProperties.h"
#include "GpDisplayDriverFactory.h"
@@ -20,11 +21,6 @@
namespace
{
GpDisplayDriverTickStatus_t TickAppEnvironment(void *context, IGpFiber *vosFiber)
{
return static_cast<GpAppEnvironment*>(context)->Tick(vosFiber);
}
void RenderAppEnvironment(void *context)
{
static_cast<GpAppEnvironment*>(context)->Render();
@@ -53,9 +49,6 @@ int GpMain::Run()
ddProps.m_frameTimeLockMaxNumerator = 101;
ddProps.m_frameTimeLockMaxDenominator = 6000;
ddProps.m_tickFunc = TickAppEnvironment;
ddProps.m_tickFuncContext = appEnvironment;
ddProps.m_renderFunc = RenderAppEnvironment;
ddProps.m_renderFuncContext = appEnvironment;
@@ -120,7 +113,9 @@ int GpMain::Run()
appEnvironment->SetSystemServices(g_gpGlobalConfig.m_systemServices);
// Start the display loop
displayDriver->Run();
displayDriver->Init();
appEnvironment->Run();
// Clean up
if (inputDrivers)

View File

@@ -38,7 +38,6 @@ public:
virtual void PL_Render(IGpDisplayDriver *displayDriver) = 0;
virtual GpDriverCollection *PL_GetDriverCollection() = 0;
virtual void PL_InstallHostSuspendHook(PortabilityLayer::HostSuspendHook_t hook, void *context) = 0;
virtual bool PL_AdjustRequestedResolution(uint32_t &physicalWidth, uint32_t &physicalHeight, uint32_t &virtualWidth, uint32_t &virtualheight, float &pixelScaleX, float &pixelScaleY) = 0;
};

View File

@@ -1,22 +1,17 @@
#include "HostSuspendHook.h"
#include "HostSuspendCallArgument.h"
#include "HostSuspendCallArgument.h"
#include "DisplayDeviceManager.h"
#include "PLDrivers.h"
#include "IGpDisplayDriver.h"
namespace
{
static PortabilityLayer::HostSuspendHook_t gs_suspendHook;
static void *gs_suspendContext;
}
namespace PortabilityLayer
{
void InstallHostSuspendHook(HostSuspendHook_t hook, void *context)
void RenderFrames(unsigned int ticks)
{
gs_suspendHook = hook;
gs_suspendContext = context;
}
void SuspendApplication(HostSuspendCallID callID, const HostSuspendCallArgument *args, HostSuspendCallArgument *returnValue)
{
gs_suspendHook(gs_suspendContext, callID, args, returnValue);
PLDrivers::GetDisplayDriver()->ServeTicks(ticks);
DisplayDeviceManager::GetInstance()->IncrementTickCount(ticks);
}
}

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef __PL_HOST_API_HOOK_H__
#define __PL_HOST_API_HOOK_H__
#include "HostSuspendCallID.h"
@@ -10,8 +8,5 @@ namespace PortabilityLayer
typedef void(*HostSuspendHook_t)(void *context, HostSuspendCallID callID, const HostSuspendCallArgument *args, HostSuspendCallArgument *returnValue);
void InstallHostSuspendHook(HostSuspendHook_t hook, void *context);
void SuspendApplication(HostSuspendCallID callID, const HostSuspendCallArgument *args, HostSuspendCallArgument *returnValue);
}
#endif
void RenderFrames(unsigned int ticks);
}

View File

@@ -52,28 +52,6 @@
#include <algorithm>
#include <limits.h>
class PLMainThreadRelay final : public IGpThreadRelay
{
public:
void Invoke(Callback_t callback, void *context) const override;
static PLMainThreadRelay *GetInstance();
private:
static PLMainThreadRelay ms_instance;
};
void PLMainThreadRelay::Invoke(Callback_t callback, void *context) const
{
PLSysCalls::RunOnVOSThread(callback, context);
}
PLMainThreadRelay *PLMainThreadRelay::GetInstance()
{
return &ms_instance;
}
PLMainThreadRelay PLMainThreadRelay::ms_instance;
static bool ConvertFilenameToSafePStr(const char *str, uint8_t *pstr)
{
@@ -138,7 +116,7 @@ void Delay(int ticks, UInt32 *endTickCount)
void ForceSyncFrame()
{
PLSysCalls::ForceSyncFrame();
PLDrivers::GetDisplayDriver()->ForceSync();
}
short FindWindow(Point point, WindowPtr *window)
@@ -671,7 +649,6 @@ void PL_Init()
PortabilityLayer::MenuManager::GetInstance()->Init();
PortabilityLayer::WindowManager::GetInstance()->Init();
PLDrivers::GetFileSystem()->SetMainThreadRelay(PLMainThreadRelay::GetInstance());
PLDrivers::GetFileSystem()->SetDelayCallback(PLSysCalls::Sleep);
}

View File

@@ -176,11 +176,8 @@ namespace PLSysCalls
void Sleep(uint32_t ticks)
{
if (ticks > 0)
{
PortabilityLayer::HostSuspendCallArgument args[1];
args[0].m_uint = static_cast<uint32_t>(ticks);
PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_Delay, args, nullptr);
{
PortabilityLayer::RenderFrames(ticks);
ImportVOSEvents(PortabilityLayer::DisplayDeviceManager::GetInstance()->GetTickCount());
@@ -188,20 +185,6 @@ namespace PLSysCalls
}
}
void ForceSyncFrame()
{
PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_ForceSyncFrame, nullptr, nullptr);
}
void RunOnVOSThread(void(*callback)(void *context), void *context)
{
PortabilityLayer::HostSuspendCallArgument args[2];
args[0].m_functionPtr = callback;
args[1].m_pointer = context;
PortabilityLayer::SuspendApplication(PortabilityLayer::HostSuspendCallID_CallOnVOSThread, args, nullptr);
}
static jmp_buf gs_mainExitWrapper;
static int gs_exitCode = 0;

View File

@@ -7,8 +7,6 @@
namespace PLSysCalls
{
void Sleep(uint32_t ticks);
void ForceSyncFrame();
void RunOnVOSThread(void(*callback)(void *context), void *context);
void Exit(int exitCode);
int MainExitWrapper(int (*mainFunc)());