changeset 248:37771eaf4245

core: use vsync and improve game loop
author David Demelier <markand@malikania.fr>
date Tue, 01 Dec 2020 12:56:11 +0100
parents e8d6754984dd
children f4dc208aa1e3
files libmlk-core/core/game.c libmlk-core/core/window.c libmlk-core/core/window.h
diffstat 3 files changed, 39 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/libmlk-core/core/game.c	Tue Dec 01 12:55:55 2020 +0100
+++ b/libmlk-core/core/game.c	Tue Dec 01 12:56:11 2020 +0100
@@ -26,6 +26,7 @@
 #include "state.h"
 #include "painter.h"
 #include "util.h"
+#include "window.h"
 
 struct game game;
 
@@ -103,8 +104,14 @@
 game_loop(void)
 {
 	struct clock clock = {0};
-	double frametimemax = 1000.0 / 60.0;
-	unsigned int frametime = 0;
+	unsigned int elapsed = 0;
+	unsigned int frametime;
+
+	if (window.framerate > 0)
+		frametime = 1000 / window.framerate;
+	else
+		/* Assuming 50.0 FPS. */
+		frametime = 1000.0 / 50.0;
 
 	while (game.state) {
 		clock_start(&clock);
@@ -112,17 +119,17 @@
 		for (union event ev; event_poll(&ev); )
 			game_handle(&ev);
 
-		game_update(frametime);
+		game_update(elapsed);
 		game_draw();
 
 		/*
-		 * Sleep not the full left time to allow context switches and
-		 * such.
+		 * If vsync is enabled, it should have wait, otherwise sleep
+		 * a little to save CPU cycles.
 		 */
-		if (frametime < frametimemax)
-			delay((frametimemax - frametime) / 4);
+		if ((elapsed = clock_elapsed(&clock)) < frametime)
+			delay(frametime - elapsed);
 
-		frametime = clock_elapsed(&clock);
+		elapsed = clock_elapsed(&clock);
 	}
 }
 
--- a/libmlk-core/core/window.c	Tue Dec 01 12:55:55 2020 +0100
+++ b/libmlk-core/core/window.c	Tue Dec 01 12:56:11 2020 +0100
@@ -50,6 +50,15 @@
 }
 
 static void
+load_framerate(void)
+{
+	SDL_DisplayMode mode;
+
+	if (SDL_GetWindowDisplayMode(handle.win, &mode) == 0)
+		window.framerate = mode.refresh_rate;
+}
+
+static void
 finish_cursors(void)
 {
 	for (size_t i = 0; i < NELEM(cursors); ++i)
@@ -57,20 +66,30 @@
 			SDL_FreeCursor(cursors[i]);
 }
 
+static bool
+load_window(const char *title, unsigned int w, unsigned int h)
+{
+	return (handle.win = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, 0));
+}
+
+static bool
+load_renderer(void)
+{
+	return (handle.renderer = SDL_CreateRenderer(handle.win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC));
+}
+
 bool
 window_open(const char *title, unsigned int w, unsigned int h)
 {
 	assert(title);
 
-	if (SDL_CreateWindowAndRenderer(w, h, SDL_WINDOW_OPENGL,
-	    &handle.win, &handle.renderer) < 0)
+	if (!load_window(title, w, h) || !load_renderer())
 		return errorf("%s", SDL_GetError());
 
-	SDL_SetWindowTitle(handle.win, title);
-
 	window.w = w;
 	window.h = h;
 
+	load_framerate();
 	load_cursors();
 
 	return true;
--- a/libmlk-core/core/window.h	Tue Dec 01 12:55:55 2020 +0100
+++ b/libmlk-core/core/window.h	Tue Dec 01 12:56:11 2020 +0100
@@ -33,6 +33,7 @@
 struct window {
 	unsigned int w;         /*!< (-) Window width. */
 	unsigned int h;         /*!< (-) Window height. */
+	unsigned int framerate; /*!< (-) Device screen refresh rate. */
 	void *handle;           /*!< (*) Native handle. */
 };