Emscripten: Add "vsync" FPS limit mode
Would be really useful for native versions too, but it's more complicated to pull off. For now, vsync on native is the same as tpt.setfpscap(2).
This commit is contained in:
parent
9f71eb9d77
commit
c725894abd
@ -17,6 +17,7 @@ constexpr bool IGNORE_UPDATES = @IGNORE_UPDATES@;
|
||||
constexpr bool ENFORCE_HTTPS = @ENFORCE_HTTPS@;
|
||||
constexpr bool SECURE_CIPHERS_ONLY = @SECURE_CIPHERS_ONLY@;
|
||||
constexpr bool FFTW_PLAN_MEASURE = @FFTW_PLAN_MEASURE@;
|
||||
constexpr bool DEFAULT_VSYNC = @DEFAULT_VSYNC@;
|
||||
constexpr char PATH_SEP_CHAR = '@PATH_SEP_CHAR@';
|
||||
|
||||
constexpr char SERVER[] = "@SERVER@";
|
||||
|
14
src/FpsLimit.h
Normal file
14
src/FpsLimit.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include <variant>
|
||||
|
||||
struct FpsLimitVsync
|
||||
{
|
||||
};
|
||||
struct FpsLimitNone
|
||||
{
|
||||
};
|
||||
struct FpsLimitExplicit
|
||||
{
|
||||
float value;
|
||||
};
|
||||
using FpsLimit = std::variant<FpsLimitVsync, FpsLimitNone, FpsLimitExplicit>;
|
@ -390,16 +390,17 @@ void EngineProcess()
|
||||
|
||||
blit(engine.g->Data());
|
||||
}
|
||||
auto fpsLimit = ui::Engine::Ref().FpsLimit;
|
||||
auto fpsLimit = ui::Engine::Ref().GetFpsLimit();
|
||||
auto now = uint64_t(SDL_GetTicks()) * UINT64_C(1'000'000);
|
||||
oldFrameStart = frameStart;
|
||||
frameStart = now;
|
||||
if (fpsLimit > 2)
|
||||
if (auto *fpsLimitExplicit = std::get_if<FpsLimitExplicit>(&fpsLimit))
|
||||
{
|
||||
auto timeBlockDuration = uint64_t(UINT64_C(1'000'000'000) / fpsLimit);
|
||||
auto timeBlockDuration = uint64_t(UINT64_C(1'000'000'000) / fpsLimitExplicit->value);
|
||||
auto oldFrameStartTimeBlock = oldFrameStart / timeBlockDuration;
|
||||
auto frameStartTimeBlock = oldFrameStartTimeBlock + 1U;
|
||||
frameStart = std::max(frameStart, frameStartTimeBlock * timeBlockDuration);
|
||||
SDL_Delay((frameStart - now) / UINT64_C(1'000'000));
|
||||
}
|
||||
// TODO: else if (auto *fpsLimitExplicit = std::get_if<FpsLimitVsync>(&fpsLimit))
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#include "common/String.h"
|
||||
#include "graphics/Pixel.h"
|
||||
#include "FpsLimit.h"
|
||||
#include <cstdint>
|
||||
#include <SDL.h>
|
||||
#include <variant>
|
||||
|
||||
extern int desktopWidth;
|
||||
extern int desktopHeight;
|
||||
@ -40,6 +42,7 @@ void blit(pixel *vid);
|
||||
void SDLOpen();
|
||||
void SDLClose();
|
||||
void SDLSetScreen(int scale_, bool resizable_, bool fullscreen_, bool altFullscreen_, bool forceIntegerScaling_);
|
||||
void SetFpsLimit(FpsLimit newFpsLimit);
|
||||
bool RecreateWindow();
|
||||
void LoadWindowPosition();
|
||||
void SaveWindowPosition();
|
||||
|
@ -8,3 +8,7 @@ void MainLoop()
|
||||
EngineProcess();
|
||||
}
|
||||
}
|
||||
|
||||
void SetFpsLimit(FpsLimit newFpsLimit)
|
||||
{
|
||||
}
|
||||
|
@ -3,35 +3,33 @@
|
||||
#include <emscripten.h>
|
||||
#include <iostream>
|
||||
|
||||
static float lastFpsLimit;
|
||||
static void updateFpsLimit()
|
||||
void SetFpsLimit(FpsLimit newFpsLimit)
|
||||
{
|
||||
lastFpsLimit = ui::Engine::Ref().FpsLimit;
|
||||
if (lastFpsLimit == 60.0f) // TODO: rework FPS cap so 60.0 is not the default
|
||||
static bool mainLoopSet = false;
|
||||
if (!mainLoopSet)
|
||||
{
|
||||
emscripten_set_main_loop(EngineProcess, 0, 0);
|
||||
mainLoopSet = true;
|
||||
}
|
||||
if (auto *fpsLimitVsync = std::get_if<FpsLimitVsync>(&newFpsLimit))
|
||||
{
|
||||
emscripten_set_main_loop_timing(EM_TIMING_RAF, 1);
|
||||
std::cerr << "implicit fps limit via vsync" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto delay = int(1000.f / lastFpsLimit);
|
||||
auto delay = 0;
|
||||
if (auto *fpsLimitExplicit = std::get_if<FpsLimitExplicit>(&newFpsLimit))
|
||||
{
|
||||
delay = int(1000.f / fpsLimitExplicit->value);
|
||||
}
|
||||
emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, delay);
|
||||
std::cerr << "explicit fps limit: " << delay << "ms delays" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void mainLoopBody()
|
||||
{
|
||||
EngineProcess();
|
||||
if (lastFpsLimit != ui::Engine::Ref().FpsLimit)
|
||||
{
|
||||
updateFpsLimit();
|
||||
}
|
||||
}
|
||||
|
||||
void MainLoop()
|
||||
{
|
||||
emscripten_set_main_loop(mainLoopBody, 0, 0);
|
||||
updateFpsLimit();
|
||||
mainLoopBody();
|
||||
SetFpsLimit(ui::Engine::Ref().GetFpsLimit());
|
||||
EngineProcess();
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "Engine.h"
|
||||
#include "Config.h"
|
||||
#include "PowderToySDL.h"
|
||||
#include "Window.h"
|
||||
#include "common/platform/Platform.h"
|
||||
@ -10,7 +11,6 @@
|
||||
using namespace ui;
|
||||
|
||||
Engine::Engine():
|
||||
FpsLimit(60.0f),
|
||||
drawingFrequencyLimit(0),
|
||||
Scale(1),
|
||||
Fullscreen(false),
|
||||
@ -27,7 +27,15 @@ Engine::Engine():
|
||||
mousexp_(0),
|
||||
mouseyp_(0)
|
||||
{
|
||||
SetFps(FpsLimit); // populate dt with whatever that makes any sort of sense
|
||||
SetFpsLimit(fpsLimit); // populate dt with whatever that makes any sort of sense
|
||||
if constexpr (DEFAULT_VSYNC)
|
||||
{
|
||||
SetFpsLimit(FpsLimitVsync{});
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFpsLimit(FpsLimitExplicit{ 60.0f });
|
||||
}
|
||||
}
|
||||
|
||||
Engine::~Engine()
|
||||
@ -41,6 +49,12 @@ Engine::~Engine()
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::SetFpsLimit(FpsLimit newFpsLimit)
|
||||
{
|
||||
fpsLimit = newFpsLimit;
|
||||
::SetFpsLimit(fpsLimit);
|
||||
}
|
||||
|
||||
void Engine::Begin()
|
||||
{
|
||||
//engine is now ready
|
||||
@ -194,10 +208,14 @@ void Engine::Draw()
|
||||
void Engine::SetFps(float fps)
|
||||
{
|
||||
this->fps = fps;
|
||||
if(FpsLimit > 2.0f)
|
||||
if (std::holds_alternative<FpsLimitExplicit>(fpsLimit))
|
||||
{
|
||||
this->dt = 60/fps;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->dt = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::onKeyPress(int key, int scan, bool repeat, bool shift, bool ctrl, bool alt)
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "graphics/Pixel.h"
|
||||
#include "gui/interface/Point.h"
|
||||
#include <climits>
|
||||
#include "FpsLimit.h"
|
||||
|
||||
class Graphics;
|
||||
namespace ui
|
||||
@ -76,7 +77,13 @@ namespace ui
|
||||
//void SetState(Window* state);
|
||||
//inline State* GetState() { return state_; }
|
||||
inline Window* GetWindow() { return state_; }
|
||||
float FpsLimit;
|
||||
|
||||
void SetFpsLimit(FpsLimit newFpsLimit);
|
||||
FpsLimit GetFpsLimit() const
|
||||
{
|
||||
return fpsLimit;
|
||||
}
|
||||
|
||||
int drawingFrequencyLimit;
|
||||
Graphics * g;
|
||||
int Scale;
|
||||
@ -85,6 +92,7 @@ namespace ui
|
||||
|
||||
unsigned int FrameIndex;
|
||||
private:
|
||||
FpsLimit fpsLimit;
|
||||
bool altFullscreen;
|
||||
bool forceIntegerScaling = true;
|
||||
bool resizable;
|
||||
|
@ -1222,13 +1222,37 @@ int luatpt_setfpscap(lua_State* l)
|
||||
int acount = lua_gettop(l);
|
||||
if (acount == 0)
|
||||
{
|
||||
lua_pushnumber(l, ui::Engine::Ref().FpsLimit);
|
||||
auto fpsLimit = ui::Engine::Ref().GetFpsLimit();
|
||||
if (std::holds_alternative<FpsLimitVsync>(fpsLimit))
|
||||
{
|
||||
lua_pushliteral(l, "vsync");
|
||||
}
|
||||
else if (std::holds_alternative<FpsLimitNone>(fpsLimit))
|
||||
{
|
||||
lua_pushnumber(l, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pushnumber(l, std::get<FpsLimitExplicit>(fpsLimit).value);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (lua_isstring(l, 1) && byteStringEqualsLiteral(tpt_lua_toByteString(l, 1), "vsync"))
|
||||
{
|
||||
ui::Engine::Ref().SetFpsLimit(FpsLimitVsync{});
|
||||
return 0;
|
||||
}
|
||||
float fpscap = luaL_checknumber(l, 1);
|
||||
if (fpscap < 2)
|
||||
{
|
||||
return luaL_error(l, "fps cap too small");
|
||||
ui::Engine::Ref().FpsLimit = fpscap;
|
||||
}
|
||||
if (fpscap == 2)
|
||||
{
|
||||
ui::Engine::Ref().SetFpsLimit(FpsLimitNone{});
|
||||
return 0;
|
||||
}
|
||||
ui::Engine::Ref().SetFpsLimit(FpsLimitExplicit{ fpscap });
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -50,10 +50,12 @@ if host_platform == 'emscripten'
|
||||
powder_files += files(
|
||||
'PowderToySDLEmscripten.cpp',
|
||||
)
|
||||
conf_data.set('DEFAULT_VSYNC', 'true')
|
||||
else
|
||||
powder_files += files(
|
||||
'PowderToySDLCommon.cpp',
|
||||
)
|
||||
conf_data.set('DEFAULT_VSYNC', 'false')
|
||||
endif
|
||||
if is_x86
|
||||
powder_files += files('X86KillDenormals.cpp')
|
||||
@ -66,6 +68,7 @@ render_files = files(
|
||||
font_files = files(
|
||||
'PowderToyFontEditor.cpp',
|
||||
'PowderToySDL.cpp',
|
||||
'PowderToySDLCommon.cpp',
|
||||
)
|
||||
|
||||
common_files = files(
|
||||
|
Loading…
Reference in New Issue
Block a user