mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-22 22:45:39 +00:00
Display driver loop refactor
This commit is contained in:
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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);
|
||||
}
|
@@ -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)
|
||||
{
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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"
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
};
|
@@ -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" />
|
||||
|
@@ -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">
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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)());
|
||||
|
Reference in New Issue
Block a user