From 26843f2e519a85c58be16fccf65c7f204d819c5a Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sun, 6 Oct 2013 07:05:01 +0200 Subject: [PATCH] Implement FPS display (F2 to toggle ON/OFF) --- src/eventthread.cpp | 106 +++++++++++++++++++++++++++++++++++++++++++- src/eventthread.h | 19 +++++++- src/graphics.cpp | 4 ++ 3 files changed, 127 insertions(+), 2 deletions(-) diff --git a/src/eventthread.cpp b/src/eventthread.cpp index f7c1a87..35adc6b 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -54,7 +54,9 @@ enum REQUEST_SETFULLSCREEN, REQUEST_WINRESIZE, REQUEST_MESSAGEBOX, - REQUEST_SETCURSORVISIBLE + REQUEST_SETCURSORVISIBLE, + + UPDATE_FPS }; EventThread::EventThread() @@ -70,6 +72,13 @@ void EventThread::process(RGSSThreadData &rtData) fullscreen = rtData.config.fullscreen; + fps.lastFrame = SDL_GetPerformanceCounter(); + fps.displaying = false; + fps.immInitFlag = false; + fps.immFiniFlag = false; + fps.acc = 0; + fps.accDiv = 0; + bool cursorInWindow = false; bool windowFocused = false; @@ -79,6 +88,11 @@ void EventThread::process(RGSSThreadData &rtData) if (SDL_NumJoysticks() > 0) js = SDL_JoystickOpen(0); + char buffer[128]; + + char pendingTitle[128]; + bool havePendingTitle = false; + while (true) { if (!SDL_WaitEvent(&event)) @@ -135,6 +149,39 @@ void EventThread::process(RGSSThreadData &rtData) (event.key.keysym.mod & KMOD_LALT)) { setFullscreen(win, !fullscreen); + if (!fullscreen && havePendingTitle) + { + SDL_SetWindowTitle(win, pendingTitle); + pendingTitle[0] = '\0'; + havePendingTitle = false; + } + + break; + } + + if (event.key.keysym.scancode == SDL_SCANCODE_F2) + { + if (!fps.displaying) + { + fps.immInitFlag = true; + fps.displaying = true; + } + else + { + fps.displaying = false; + + if (fullscreen) + { + /* Prevent fullscreen flicker */ + strncpy(pendingTitle, rtData.config.game.title.constData(), + sizeof(pendingTitle)); + havePendingTitle = true; + break; + } + + SDL_SetWindowTitle(win, rtData.config.game.title.constData()); + } + break; } @@ -162,6 +209,25 @@ void EventThread::process(RGSSThreadData &rtData) updateCursorState(cursorInWindow); break; + case UPDATE_FPS : + if (!fps.displaying) + break; + + snprintf(buffer, sizeof(buffer), "%s - %d FPS", + rtData.config.game.title.constData(), event.user.code); + + /* Updating the window title in fullscreen + * mode seems to cause flickering */ + if (fullscreen) + { + strncpy(pendingTitle, buffer, sizeof(pendingTitle)); + havePendingTitle = true; + break; + } + + SDL_SetWindowTitle(win, buffer); + break; + case SDL_KEYUP : keyStates[event.key.keysym.scancode] = false; break; @@ -309,3 +375,41 @@ bool EventThread::getShowCursor() const { return showCursor; } + +void EventThread::notifyFrame() +{ + if (!fps.displaying) + return; + + uint64_t current = SDL_GetPerformanceCounter(); + uint64_t diff = current - fps.lastFrame; + fps.lastFrame = current; + + if (fps.immInitFlag) + { + fps.immInitFlag = false; + fps.immFiniFlag = true; + return; + } + + static uint64_t freq = SDL_GetPerformanceFrequency(); + + int32_t currFPS = freq / diff; + fps.acc += currFPS; + ++fps.accDiv; + + fps.displayCounter += diff; + if (fps.displayCounter < freq && !fps.immFiniFlag) + return; + + fps.displayCounter = 0; + fps.immFiniFlag = false; + + int32_t avgFPS = fps.acc / fps.accDiv; + fps.acc = fps.accDiv = 0; + + SDL_Event event; + event.user.code = avgFPS; + event.user.type = UPDATE_FPS; + SDL_PushEvent(&event); +} diff --git a/src/eventthread.h b/src/eventthread.h index 4a686d7..f18a993 100644 --- a/src/eventthread.h +++ b/src/eventthread.h @@ -34,6 +34,8 @@ #include #include +#include + struct RGSSThreadData; struct SDL_Thread; struct SDL_Window; @@ -66,7 +68,7 @@ public: void process(RGSSThreadData &rtData); void cleanup(); - /* Called from rgss thread */ + /* Called from RGSS thread */ void requestFullscreenMode(bool mode); void requestWindowResize(int width, int height); void requestShowCursor(bool mode); @@ -78,13 +80,28 @@ public: void showMessageBox(const char *body, int flags = 0); + /* RGSS thread calls this once per frame */ + void notifyFrame(); + private: void resetInputStates(); void setFullscreen(SDL_Window *, bool mode); void updateCursorState(bool inWindow); + bool fullscreen; bool showCursor; volatile bool msgBoxDone; + + struct + { + uint64_t lastFrame; + uint64_t displayCounter; + bool displaying; + bool immInitFlag; + bool immFiniFlag; + uint64_t acc; + uint32_t accDiv; + } fps; }; /* Used to asynchronously inform the rgss thread diff --git a/src/graphics.cpp b/src/graphics.cpp index d9bc573..b4f219a 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -394,6 +394,8 @@ struct GraphicsPrivate fpsLimiter.delay(); ++frameCount; + + threadData->ethread->notifyFrame(); } void compositeToBuffer(FBO::ID fbo) @@ -716,5 +718,7 @@ void Graphics::repaintWait(volatile bool *exitCond) p->blitBufferFlippedScaled(); SDL_GL_SwapWindow(p->threadData->window); p->fpsLimiter.delay(); + + p->threadData->ethread->notifyFrame(); } }