mirror of https://github.com/AxioDL/boo.git
Remove vsync thread from X11 backend
This commit is contained in:
parent
3e1da36f39
commit
45db327fb3
|
@ -251,6 +251,7 @@ public:
|
||||||
virtual void setCursor(EMouseCursor cursor) = 0;
|
virtual void setCursor(EMouseCursor cursor) = 0;
|
||||||
virtual void setWaitCursor(bool wait) = 0;
|
virtual void setWaitCursor(bool wait) = 0;
|
||||||
|
|
||||||
|
virtual double getWindowRefreshRate() const = 0;
|
||||||
virtual void setWindowFrameDefault() = 0;
|
virtual void setWindowFrameDefault() = 0;
|
||||||
virtual void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const = 0;
|
virtual void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const = 0;
|
||||||
virtual void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const = 0;
|
virtual void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const = 0;
|
||||||
|
@ -273,7 +274,7 @@ public:
|
||||||
virtual bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) = 0;
|
virtual bool clipboardCopy(EClipboardType type, const uint8_t* data, size_t sz) = 0;
|
||||||
virtual std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) = 0;
|
virtual std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) = 0;
|
||||||
|
|
||||||
virtual void waitForRetrace() = 0;
|
virtual int waitForRetrace() = 0;
|
||||||
|
|
||||||
virtual uintptr_t getPlatformHandle() const = 0;
|
virtual uintptr_t getPlatformHandle() const = 0;
|
||||||
virtual bool _incomingEvent(void* event) {
|
virtual bool _incomingEvent(void* event) {
|
||||||
|
|
|
@ -149,9 +149,10 @@ public:
|
||||||
std::recursive_mutex m_callbackMutex;
|
std::recursive_mutex m_callbackMutex;
|
||||||
IWindowCallback* m_callback = nullptr;
|
IWindowCallback* m_callback = nullptr;
|
||||||
|
|
||||||
void waitForRetrace() {
|
int waitForRetrace() {
|
||||||
std::unique_lock<std::mutex> lk(m_dlmt);
|
std::unique_lock<std::mutex> lk(m_dlmt);
|
||||||
m_dlcv.wait(lk);
|
m_dlcv.wait(lk);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual BooCocoaResponder* responder() const = 0;
|
virtual BooCocoaResponder* responder() const = 0;
|
||||||
|
@ -1321,6 +1322,11 @@ public:
|
||||||
|
|
||||||
void setWaitCursor(bool wait) {}
|
void setWaitCursor(bool wait) {}
|
||||||
|
|
||||||
|
double getWindowRefreshRate() const {
|
||||||
|
/* TODO: Actually get refresh rate */
|
||||||
|
return 60.0;
|
||||||
|
}
|
||||||
|
|
||||||
void setWindowFrameDefault() {
|
void setWindowFrameDefault() {
|
||||||
dispatch_sync(dispatch_get_main_queue(),
|
dispatch_sync(dispatch_get_main_queue(),
|
||||||
^{
|
^{
|
||||||
|
@ -1456,8 +1462,8 @@ public:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForRetrace() {
|
int waitForRetrace() {
|
||||||
static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace();
|
return static_cast<GraphicsContextCocoa*>(m_gfxCtx)->waitForRetrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t getPlatformHandle() const {
|
uintptr_t getPlatformHandle() const {
|
||||||
|
|
|
@ -322,6 +322,11 @@ public:
|
||||||
|
|
||||||
void setWaitCursor(bool wait) {}
|
void setWaitCursor(bool wait) {}
|
||||||
|
|
||||||
|
double getWindowRefreshRate() const {
|
||||||
|
/* TODO: Actually get refresh rate */
|
||||||
|
return 60.0;
|
||||||
|
}
|
||||||
|
|
||||||
void setWindowFrameDefault() {}
|
void setWindowFrameDefault() {}
|
||||||
|
|
||||||
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const {
|
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const {
|
||||||
|
@ -359,10 +364,11 @@ public:
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { return std::unique_ptr<uint8_t[]>(); }
|
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { return std::unique_ptr<uint8_t[]>(); }
|
||||||
|
|
||||||
void waitForRetrace(IAudioVoiceEngine* engine) {
|
int waitForRetrace(IAudioVoiceEngine* engine) {
|
||||||
if (engine)
|
if (engine)
|
||||||
engine->pumpAndMixVoices();
|
engine->pumpAndMixVoices();
|
||||||
m_gfxCtx->m_output->WaitForVBlank();
|
m_gfxCtx->m_output->WaitForVBlank();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t getPlatformHandle() const { return 0; }
|
uintptr_t getPlatformHandle() const { return 0; }
|
||||||
|
|
|
@ -914,6 +914,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double getWindowRefreshRate() const {
|
||||||
|
/* TODO: Actually get refresh rate */
|
||||||
|
return 60.0;
|
||||||
|
}
|
||||||
|
|
||||||
void setWindowFrameDefault() {
|
void setWindowFrameDefault() {
|
||||||
MONITORINFO monInfo = {};
|
MONITORINFO monInfo = {};
|
||||||
monInfo.cbSize = sizeof(MONITORINFO);
|
monInfo.cbSize = sizeof(MONITORINFO);
|
||||||
|
@ -1063,7 +1068,7 @@ public:
|
||||||
return std::unique_ptr<uint8_t[]>();
|
return std::unique_ptr<uint8_t[]>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForRetrace() { m_gfxCtx->m_output->WaitForVBlank(); }
|
int waitForRetrace() { m_gfxCtx->m_output->WaitForVBlank(); return 1; }
|
||||||
|
|
||||||
uintptr_t getPlatformHandle() const { return uintptr_t(m_hwnd); }
|
uintptr_t getPlatformHandle() const { return uintptr_t(m_hwnd); }
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,8 @@ struct WindowWayland : IWindow {
|
||||||
|
|
||||||
void setWaitCursor(bool wait) {}
|
void setWaitCursor(bool wait) {}
|
||||||
|
|
||||||
|
double getWindowRefreshRate() const { return 60.0; }
|
||||||
|
|
||||||
void setWindowFrameDefault() {}
|
void setWindowFrameDefault() {}
|
||||||
|
|
||||||
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const {}
|
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const {}
|
||||||
|
@ -99,7 +101,7 @@ struct WindowWayland : IWindow {
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { return std::unique_ptr<uint8_t[]>(); }
|
std::unique_ptr<uint8_t[]> clipboardPaste(EClipboardType type, size_t& sz) { return std::unique_ptr<uint8_t[]>(); }
|
||||||
|
|
||||||
void waitForRetrace() {}
|
int waitForRetrace() { return 1; }
|
||||||
|
|
||||||
uintptr_t getPlatformHandle() const { return 0; }
|
uintptr_t getPlatformHandle() const { return 0; }
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
@ -57,8 +58,6 @@
|
||||||
|
|
||||||
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
|
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
|
||||||
static glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
|
static glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
|
||||||
typedef int (*glXWaitVideoSyncSGIProc)(int divisor, int remainder, unsigned int* count);
|
|
||||||
static glXWaitVideoSyncSGIProc glXWaitVideoSyncSGI = 0;
|
|
||||||
static bool s_glxError;
|
static bool s_glxError;
|
||||||
static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) {
|
static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) {
|
||||||
s_glxError = true;
|
s_glxError = true;
|
||||||
|
@ -262,11 +261,6 @@ struct GraphicsContextXlib : IGraphicsContext {
|
||||||
GLContext* m_glCtx;
|
GLContext* m_glCtx;
|
||||||
Display* m_xDisp;
|
Display* m_xDisp;
|
||||||
|
|
||||||
std::mutex m_initmt;
|
|
||||||
std::condition_variable m_initcv;
|
|
||||||
std::mutex m_vsyncmt;
|
|
||||||
std::condition_variable m_vsynccv;
|
|
||||||
|
|
||||||
GraphicsContextXlib(EGraphicsAPI api, EPixelFormat pf, IWindow* parentWindow, Display* disp, GLContext* glCtx)
|
GraphicsContextXlib(EGraphicsAPI api, EPixelFormat pf, IWindow* parentWindow, Display* disp, GLContext* glCtx)
|
||||||
: m_api(api), m_pf(pf), m_parentWindow(parentWindow), m_glCtx(glCtx), m_xDisp(disp) {}
|
: m_api(api), m_pf(pf), m_parentWindow(parentWindow), m_glCtx(glCtx), m_xDisp(disp) {}
|
||||||
virtual void destroy() = 0;
|
virtual void destroy() = 0;
|
||||||
|
@ -287,9 +281,6 @@ struct GraphicsContextXlibGLX : GraphicsContextXlib {
|
||||||
GLXContext m_mainCtx = 0;
|
GLXContext m_mainCtx = 0;
|
||||||
GLXContext m_loadCtx = 0;
|
GLXContext m_loadCtx = 0;
|
||||||
|
|
||||||
std::thread m_vsyncThread;
|
|
||||||
bool m_vsyncRunning;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IWindowCallback* m_callback;
|
IWindowCallback* m_callback;
|
||||||
|
|
||||||
|
@ -371,10 +362,6 @@ public:
|
||||||
glXDestroyContext(m_xDisp, m_loadCtx);
|
glXDestroyContext(m_xDisp, m_loadCtx);
|
||||||
m_loadCtx = nullptr;
|
m_loadCtx = nullptr;
|
||||||
}
|
}
|
||||||
if (m_vsyncRunning) {
|
|
||||||
m_vsyncRunning = false;
|
|
||||||
m_vsyncThread.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~GraphicsContextXlibGLX() { destroy(); }
|
~GraphicsContextXlibGLX() { destroy(); }
|
||||||
|
@ -400,11 +387,6 @@ public:
|
||||||
if (!glXCreateContextAttribsARB)
|
if (!glXCreateContextAttribsARB)
|
||||||
Log.report(logvisor::Fatal, "unable to resolve glXCreateContextAttribsARB");
|
Log.report(logvisor::Fatal, "unable to resolve glXCreateContextAttribsARB");
|
||||||
}
|
}
|
||||||
if (!glXWaitVideoSyncSGI) {
|
|
||||||
glXWaitVideoSyncSGI = (glXWaitVideoSyncSGIProc)glXGetProcAddressARB((const GLubyte*)"glXWaitVideoSyncSGI");
|
|
||||||
if (!glXWaitVideoSyncSGI)
|
|
||||||
Log.report(logvisor::Fatal, "unable to resolve glXWaitVideoSyncSGI");
|
|
||||||
}
|
|
||||||
|
|
||||||
s_glxError = false;
|
s_glxError = false;
|
||||||
XErrorHandler oldHandler = XSetErrorHandler(ctxErrorHandler);
|
XErrorHandler oldHandler = XSetErrorHandler(ctxErrorHandler);
|
||||||
|
@ -427,50 +409,6 @@ public:
|
||||||
Log.report(logvisor::Fatal, "glewInit failed");
|
Log.report(logvisor::Fatal, "glewInit failed");
|
||||||
glXMakeCurrent(m_xDisp, 0, 0);
|
glXMakeCurrent(m_xDisp, 0, 0);
|
||||||
|
|
||||||
/* Spawn vsync thread */
|
|
||||||
m_vsyncRunning = true;
|
|
||||||
std::unique_lock<std::mutex> outerLk(m_initmt);
|
|
||||||
m_vsyncThread = std::thread([&]() {
|
|
||||||
Display* vsyncDisp;
|
|
||||||
GLXContext vsyncCtx;
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> innerLk(m_initmt);
|
|
||||||
|
|
||||||
vsyncDisp = XOpenDisplay(0);
|
|
||||||
if (!vsyncDisp)
|
|
||||||
Log.report(logvisor::Fatal, "unable to open new vsync display");
|
|
||||||
XLockDisplay(vsyncDisp);
|
|
||||||
|
|
||||||
static int attributeList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
|
|
||||||
0};
|
|
||||||
XVisualInfo* vi = glXChooseVisual(vsyncDisp, DefaultScreen(vsyncDisp), attributeList);
|
|
||||||
|
|
||||||
vsyncCtx = glXCreateContext(vsyncDisp, vi, nullptr, True);
|
|
||||||
if (!vsyncCtx)
|
|
||||||
Log.report(logvisor::Fatal, "unable to make new vsync GLX context");
|
|
||||||
|
|
||||||
if (!glXMakeCurrent(vsyncDisp, DefaultRootWindow(vsyncDisp), vsyncCtx))
|
|
||||||
Log.report(logvisor::Fatal, "unable to make vsync context current");
|
|
||||||
}
|
|
||||||
m_initcv.notify_one();
|
|
||||||
|
|
||||||
while (m_vsyncRunning) {
|
|
||||||
{
|
|
||||||
unsigned int sync;
|
|
||||||
int err = glXWaitVideoSyncSGI(1, 0, &sync);
|
|
||||||
if (err)
|
|
||||||
Log.report(logvisor::Fatal, "wait err");
|
|
||||||
}
|
|
||||||
m_vsynccv.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
glXMakeCurrent(vsyncDisp, 0, nullptr);
|
|
||||||
glXDestroyContext(vsyncDisp, vsyncCtx);
|
|
||||||
XUnlockDisplay(vsyncDisp);
|
|
||||||
XCloseDisplay(vsyncDisp);
|
|
||||||
});
|
|
||||||
m_initcv.wait(outerLk);
|
|
||||||
|
|
||||||
XUnlockDisplay(m_xDisp);
|
XUnlockDisplay(m_xDisp);
|
||||||
m_commandQueue = _NewGLCommandQueue(this, m_glCtx);
|
m_commandQueue = _NewGLCommandQueue(this, m_glCtx);
|
||||||
m_commandQueue->startRenderer();
|
m_commandQueue->startRenderer();
|
||||||
|
@ -546,9 +484,6 @@ struct GraphicsContextXlibVulkan : GraphicsContextXlib {
|
||||||
std::unique_ptr<IGraphicsDataFactory> m_dataFactory;
|
std::unique_ptr<IGraphicsDataFactory> m_dataFactory;
|
||||||
std::unique_ptr<IGraphicsCommandQueue> m_commandQueue;
|
std::unique_ptr<IGraphicsCommandQueue> m_commandQueue;
|
||||||
|
|
||||||
std::thread m_vsyncThread;
|
|
||||||
std::atomic_bool m_vsyncRunning;
|
|
||||||
|
|
||||||
static void ThrowIfFailed(VkResult res) {
|
static void ThrowIfFailed(VkResult res) {
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
Log.report(logvisor::Fatal, "%d\n", res);
|
Log.report(logvisor::Fatal, "%d\n", res);
|
||||||
|
@ -576,12 +511,6 @@ public:
|
||||||
vk::DestroySurfaceKHR(m_ctx->m_instance, m_surface, nullptr);
|
vk::DestroySurfaceKHR(m_ctx->m_instance, m_surface, nullptr);
|
||||||
m_surface = VK_NULL_HANDLE;
|
m_surface = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_vsyncRunning.load()) {
|
|
||||||
m_vsyncRunning.store(false);
|
|
||||||
if (m_vsyncThread.joinable())
|
|
||||||
m_vsyncThread.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~GraphicsContextXlibVulkan() { destroy(); }
|
~GraphicsContextXlibVulkan() { destroy(); }
|
||||||
|
@ -606,12 +535,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool initializeContext(void* getVkProc) {
|
bool initializeContext(void* getVkProc) {
|
||||||
if (!glXWaitVideoSyncSGI) {
|
|
||||||
glXWaitVideoSyncSGI = (glXWaitVideoSyncSGIProc)glXGetProcAddressARB((const GLubyte*)"glXWaitVideoSyncSGI");
|
|
||||||
if (!glXWaitVideoSyncSGI)
|
|
||||||
Log.report(logvisor::Fatal, "unable to resolve glXWaitVideoSyncSGI");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ctx->m_instance == VK_NULL_HANDLE)
|
if (m_ctx->m_instance == VK_NULL_HANDLE)
|
||||||
m_ctx->initVulkan(APP->getUniqueName(), PFN_vkGetInstanceProcAddr(getVkProc));
|
m_ctx->initVulkan(APP->getUniqueName(), PFN_vkGetInstanceProcAddr(getVkProc));
|
||||||
|
|
||||||
|
@ -700,49 +623,6 @@ public:
|
||||||
|
|
||||||
m_ctx->initSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace);
|
m_ctx->initSwapChain(*m_windowCtx, m_surface, m_format, m_colorspace);
|
||||||
|
|
||||||
/* Spawn vsync thread */
|
|
||||||
m_vsyncRunning.store(true);
|
|
||||||
std::unique_lock<std::mutex> outerLk(m_initmt);
|
|
||||||
m_vsyncThread = std::thread([&]() {
|
|
||||||
logvisor::RegisterThreadName("Boo VSync");
|
|
||||||
Display* vsyncDisp;
|
|
||||||
GLXContext vsyncCtx;
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> innerLk(m_initmt);
|
|
||||||
|
|
||||||
vsyncDisp = XOpenDisplay(0);
|
|
||||||
if (!vsyncDisp)
|
|
||||||
Log.report(logvisor::Fatal, "unable to open new vsync display");
|
|
||||||
XLockDisplay(vsyncDisp);
|
|
||||||
|
|
||||||
static int attributeList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
|
|
||||||
0};
|
|
||||||
XVisualInfo* vi = glXChooseVisual(vsyncDisp, DefaultScreen(vsyncDisp), attributeList);
|
|
||||||
|
|
||||||
vsyncCtx = glXCreateContext(vsyncDisp, vi, nullptr, True);
|
|
||||||
if (!vsyncCtx)
|
|
||||||
Log.report(logvisor::Fatal, "unable to make new vsync GLX context");
|
|
||||||
|
|
||||||
if (!glXMakeCurrent(vsyncDisp, DefaultRootWindow(vsyncDisp), vsyncCtx))
|
|
||||||
Log.report(logvisor::Fatal, "unable to make vsync context current");
|
|
||||||
}
|
|
||||||
m_initcv.notify_one();
|
|
||||||
|
|
||||||
while (m_vsyncRunning.load()) {
|
|
||||||
unsigned int sync;
|
|
||||||
int err = glXWaitVideoSyncSGI(1, 0, &sync);
|
|
||||||
if (err)
|
|
||||||
Log.report(logvisor::Fatal, "wait err");
|
|
||||||
m_vsynccv.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
glXMakeCurrent(vsyncDisp, 0, nullptr);
|
|
||||||
glXDestroyContext(vsyncDisp, vsyncCtx);
|
|
||||||
XUnlockDisplay(vsyncDisp);
|
|
||||||
XCloseDisplay(vsyncDisp);
|
|
||||||
});
|
|
||||||
m_initcv.wait(outerLk);
|
|
||||||
|
|
||||||
m_dataFactory = _NewVulkanDataFactory(this, m_ctx);
|
m_dataFactory = _NewVulkanDataFactory(this, m_ctx);
|
||||||
m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this);
|
m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this);
|
||||||
m_commandQueue->startRenderer();
|
m_commandQueue->startRenderer();
|
||||||
|
@ -766,7 +646,7 @@ public:
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class WindowXlib : public IWindow {
|
class WindowXlib final : public IWindow {
|
||||||
Display* m_xDisp;
|
Display* m_xDisp;
|
||||||
IWindowCallback* m_callback;
|
IWindowCallback* m_callback;
|
||||||
Colormap m_colormapId;
|
Colormap m_colormapId;
|
||||||
|
@ -776,6 +656,9 @@ class WindowXlib : public IWindow {
|
||||||
std::unique_ptr<GraphicsContextXlib> m_gfxCtx;
|
std::unique_ptr<GraphicsContextXlib> m_gfxCtx;
|
||||||
uint32_t m_visualId;
|
uint32_t m_visualId;
|
||||||
|
|
||||||
|
struct timespec m_waitPeriod = {0, static_cast<long int>(1000000000.0/60.0)};
|
||||||
|
struct timespec m_lastWaitTime = {};
|
||||||
|
|
||||||
/* Key state trackers (for auto-repeat detection) */
|
/* Key state trackers (for auto-repeat detection) */
|
||||||
std::unordered_set<unsigned long> m_charKeys;
|
std::unordered_set<unsigned long> m_charKeys;
|
||||||
std::unordered_set<unsigned long> m_specialKeys;
|
std::unordered_set<unsigned long> m_specialKeys;
|
||||||
|
@ -930,6 +813,9 @@ public:
|
||||||
setStyle(EWindowStyle::Default);
|
setStyle(EWindowStyle::Default);
|
||||||
setCursor(EMouseCursor::Pointer);
|
setCursor(EMouseCursor::Pointer);
|
||||||
setWindowFrameDefault();
|
setWindowFrameDefault();
|
||||||
|
double hz = getWindowRefreshRate();
|
||||||
|
uint64_t nanos = uint64_t(1000000000.0 / hz);
|
||||||
|
m_waitPeriod = {nanos / 1000000000, nanos % 1000000000};
|
||||||
XFlush(m_xDisp);
|
XFlush(m_xDisp);
|
||||||
|
|
||||||
if (!m_gfxCtx->initializeContext(vulkanHandle)) {
|
if (!m_gfxCtx->initializeContext(vulkanHandle)) {
|
||||||
|
@ -1019,6 +905,37 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double calculateRefreshRate(const XRRModeInfo& mi) {
|
||||||
|
if (mi.hTotal && mi.vTotal)
|
||||||
|
return double(mi.dotClock) / (double(mi.hTotal) * double(mi.vTotal));
|
||||||
|
else
|
||||||
|
return 60.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getWindowRefreshRate() const {
|
||||||
|
double ret = 60.0;
|
||||||
|
int nmonitors;
|
||||||
|
Screen* screen = DefaultScreenOfDisplay(m_xDisp);
|
||||||
|
XRRMonitorInfo* mInfo = XRRGetMonitors(m_xDisp, screen->root, true, &nmonitors);
|
||||||
|
if (nmonitors) {
|
||||||
|
XRRScreenResources* res = XRRGetScreenResourcesCurrent(m_xDisp, screen->root);
|
||||||
|
XRROutputInfo* oinfo = XRRGetOutputInfo(m_xDisp, res, *mInfo->outputs);
|
||||||
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(m_xDisp, res, oinfo->crtc);
|
||||||
|
for (int i = 0; i < res->nmode; ++i) {
|
||||||
|
const XRRModeInfo& mode = res->modes[i];
|
||||||
|
if (mode.id == ci->mode) {
|
||||||
|
ret = calculateRefreshRate(mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
XRRFreeOutputInfo(oinfo);
|
||||||
|
XRRFreeScreenResources(res);
|
||||||
|
}
|
||||||
|
XRRFreeMonitors(mInfo);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void setWindowFrameDefault() {
|
void setWindowFrameDefault() {
|
||||||
int x, y, w, h, nmonitors;
|
int x, y, w, h, nmonitors;
|
||||||
Screen* screen = DefaultScreenOfDisplay(m_xDisp);
|
Screen* screen = DefaultScreenOfDisplay(m_xDisp);
|
||||||
|
@ -1279,9 +1196,77 @@ public:
|
||||||
XSendEvent(m_xDisp, se->requestor, False, 0, &reply);
|
XSendEvent(m_xDisp, se->requestor, False, 0, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForRetrace() {
|
#define NSEC_PER_SEC 1000000000
|
||||||
std::unique_lock<std::mutex> lk(m_gfxCtx->m_vsyncmt);
|
|
||||||
m_gfxCtx->m_vsynccv.wait(lk);
|
static void set_normalized_timespec(struct timespec& ts, time_t sec, int64_t nsec) {
|
||||||
|
while (nsec >= NSEC_PER_SEC) {
|
||||||
|
nsec -= NSEC_PER_SEC;
|
||||||
|
++sec;
|
||||||
|
}
|
||||||
|
while (nsec < 0) {
|
||||||
|
nsec += NSEC_PER_SEC;
|
||||||
|
--sec;
|
||||||
|
}
|
||||||
|
ts.tv_sec = sec;
|
||||||
|
ts.tv_nsec = nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct timespec timespec_add(const struct timespec& lhs, const struct timespec& rhs) {
|
||||||
|
struct timespec ts_delta;
|
||||||
|
set_normalized_timespec(ts_delta, lhs.tv_sec + rhs.tv_sec,
|
||||||
|
lhs.tv_nsec + rhs.tv_nsec);
|
||||||
|
return ts_delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct timespec timespec_sub(const struct timespec& lhs, const struct timespec& rhs) {
|
||||||
|
struct timespec ts_delta;
|
||||||
|
set_normalized_timespec(ts_delta, lhs.tv_sec - rhs.tv_sec,
|
||||||
|
lhs.tv_nsec - rhs.tv_nsec);
|
||||||
|
return ts_delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long int timespec_compare(const struct timespec& lhs, const struct timespec& rhs)
|
||||||
|
{
|
||||||
|
if (lhs.tv_sec < rhs.tv_sec)
|
||||||
|
return -1;
|
||||||
|
if (lhs.tv_sec > rhs.tv_sec)
|
||||||
|
return 1;
|
||||||
|
return lhs.tv_nsec - rhs.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
int waitForRetrace() {
|
||||||
|
struct timespec tp;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &tp);
|
||||||
|
if (!m_lastWaitTime.tv_sec) {
|
||||||
|
/* Initialize reference point */
|
||||||
|
sched_param prio = {75};
|
||||||
|
sched_setscheduler(0, SCHED_RR, &prio);
|
||||||
|
m_lastWaitTime = tp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastWaitTime = timespec_add(m_lastWaitTime, m_waitPeriod);
|
||||||
|
long int comp = timespec_compare(m_lastWaitTime, tp);
|
||||||
|
if (comp == 0) {
|
||||||
|
/* Exactly at the due date */
|
||||||
|
return 1;
|
||||||
|
} else if (comp > 0) {
|
||||||
|
/* Not at due date yet, sleep here */
|
||||||
|
struct timespec wait_time = timespec_sub(m_lastWaitTime, tp);
|
||||||
|
nanosleep(&wait_time, nullptr);
|
||||||
|
do {
|
||||||
|
clock_gettime(CLOCK_REALTIME, &tp);
|
||||||
|
} while (timespec_compare(m_lastWaitTime, tp) > 0);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/* Missed due date, assign next one and return passed cycle count */
|
||||||
|
int cycles = 0;
|
||||||
|
do {
|
||||||
|
m_lastWaitTime = timespec_add(m_lastWaitTime, m_waitPeriod);
|
||||||
|
++cycles;
|
||||||
|
} while (timespec_compare(m_lastWaitTime, tp) < 0);
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t getPlatformHandle() const { return (uintptr_t)m_windowId; }
|
uintptr_t getPlatformHandle() const { return (uintptr_t)m_windowId; }
|
||||||
|
|
Loading…
Reference in New Issue