From b681e8c2775bbb467c0f0607afd9840fda25c563 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 28 Jan 2017 00:56:45 +0100 Subject: [PATCH] Implemented Wait() Now program is halted (OS signal call) for required amount of time every frame, so CPU usage drops to zero, instead of using a busy wait loop. --- src/core.c | 66 ++++++++++++++++++++++++++++++++++++++-------------- src/raylib.h | 4 ++-- src/text.c | 21 ++--------------- 3 files changed, 53 insertions(+), 38 deletions(-) diff --git a/src/core.c b/src/core.c index 2917d8399..8b97314d9 100644 --- a/src/core.c +++ b/src/core.c @@ -67,9 +67,13 @@ #include // Required for: strcmp() //#include // Macros for reporting and retrieving error conditions through error codes +#if defined __linux || defined(PLATFORM_WEB) + #include // Required for: timespec, nanosleep(), select() - POSIX +#endif + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) - //#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3 - #include // GLFW3 library: Windows, OpenGL context and Input management + //#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3 + #include // GLFW3 library: Windows, OpenGL context and Input management #ifdef __linux #define GLFW_EXPOSE_NATIVE_X11 // Linux specific definitions for getting @@ -243,7 +247,7 @@ static int dropFilesCount = 0; // Count stored strings static double currentTime, previousTime; // Used to track timmings static double updateTime, drawTime; // Time measures for update and draw -static double frameTime; // Time measure for one frame +static double frameTime = 0.0; // Time measure for one frame static double targetTime = 0.0; // Desired time for one frame, if 0 not applied static char configFlags = 0; // Configuration flags (bit based) @@ -264,6 +268,7 @@ static void InitGraphicsDevice(int width, int height); // Initialize graphics d static void SetupFramebufferSize(int displayWidth, int displayHeight); static void InitTimer(void); // Initialize timer static double GetTime(void); // Returns time since InitTimer() was run +static void Wait(int ms); // Wait for some milliseconds (stop program execution) static bool GetKeyStatus(int key); // Returns if a key has been pressed static bool GetMouseButtonStatus(int button); // Returns if a mouse button has been pressed static void PollInputEvents(void); // Register user events @@ -313,6 +318,11 @@ static void InitGamepad(void); // Init raw gamepad inpu static void *GamepadThread(void *arg); // Mouse reading thread #endif +#if defined(_WIN32) + // NOTE: We include Sleep() function signature here to avoid windows.h inclusion + void __stdcall Sleep(unsigned long msTimeout); // Required for Delay() +#endif + //---------------------------------------------------------------------------------- // Module Functions Definition - Window and OpenGL Context Functions //---------------------------------------------------------------------------------- @@ -638,15 +648,16 @@ void EndDrawing(void) frameTime = updateTime + drawTime; - double extraTime = 0.0; - - while (frameTime < targetTime) + // Wait for some milliseconds... + if (frameTime < targetTime) { - // Implement a delay + Wait((int)((targetTime - frameTime)*1000)); + currentTime = GetTime(); - extraTime = currentTime - previousTime; + double extraTime = currentTime - previousTime; previousTime = currentTime; - frameTime += extraTime; + + frameTime = updateTime + drawTime + extraTime; } } @@ -780,20 +791,16 @@ void SetTargetFPS(int fps) } // Returns current FPS -float GetFPS(void) +int GetFPS(void) { - return (float)(1.0/frameTime); + return (int)floorf(1.0f/GetFrameTime()); } // Returns time in seconds for one frame float GetFrameTime(void) { - // As we are operate quite a lot with frameTime, - // it could be no stable, so we round it before passing it around - // NOTE: There are still problems with high framerates (>500fps) - double roundedFrameTime = round(frameTime*10000)/10000.0; - - return (float)roundedFrameTime; // Time in seconds to run a frame + // NOTE: We round value to milliseconds + return (roundf(frameTime*1000.0)/1000.0f); } // Converts Color to float array and normalizes @@ -1931,6 +1938,31 @@ static double GetTime(void) #endif } +// Wait for some milliseconds (stop program execution) +static void Wait(int ms) +{ +#if defined _WIN32 + Sleep(ms); +#elif defined __linux || defined(PLATFORM_WEB) + struct timespec req = { 0 }; + time_t sec = (int)(ms/1000); + ms -= (sec*1000); + req.tv_sec=sec; + req.tv_nsec=ms*1000000L; + + // NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated. + while (nanosleep(&req,&req) == -1) continue; +//#elif defined __APPLE__ + // TODO: +#else + double prevTime = GetTime(); + double nextTime = 0.0; + + // Busy wait loop + while ((nextTime - prevTime) < (double)ms/1000.0) nextTime = GetTime(); +#endif +} + // Get one key state static bool GetKeyStatus(int key) { diff --git a/src/raylib.h b/src/raylib.h index f8f17eecf..97130253a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -659,8 +659,8 @@ RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the RLAPI Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum) -RLAPI float GetFPS(void); // Returns current FPS -RLAPI float GetFrameTime(void); // Returns time in seconds for one frame +RLAPI int GetFPS(void); // Returns current FPS (rounded value) +RLAPI float GetFrameTime(void); // Returns time in seconds for one frame (rounded value) RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value RLAPI int GetHexValue(Color color); // Returns hexadecimal value for a Color diff --git a/src/text.c b/src/text.c index 4510b3af4..4e163668d 100644 --- a/src/text.c +++ b/src/text.c @@ -504,25 +504,8 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i // NOTE: Uses default font void DrawFPS(int posX, int posY) { - // NOTE: We are rendering fps every second for better viewing on high framerates - // TODO: Not working properly on ANDROID and RPI (for high framerates) - - static float fps = 0.0f; - static int counter = 0; - static int refreshRate = 20; - - if (counter < refreshRate) - { - counter++; - } - else - { - fps = GetFPS(); - refreshRate = (int)fps; - counter = 0; - } - - DrawText(FormatText("%2.0f FPS", fps), posX, posY, 20, LIME); + // NOTE: We have rounding errors every frame, so it oscillates a lot + DrawText(FormatText("%2i FPS", GetFPS()), posX, posY, 20, LIME); } //----------------------------------------------------------------------------------