~rabbits/public-inbox

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch

[PATCH] redo timing using a process to ping poll every frame

Details
Message ID
<20220328121619.wnab4bc52zlaqtn6@t480>
DKIM signature
pass
Download raw message
Patch: +68 -25
timerfd_create is Linux-specific; this patch uses only POSIX functions
and has been tested on Linux and OpenBSD.
Also make processEvent return 1 to tell us when to quit.
---
 src/uxn11.c | 93 +++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 68 insertions(+), 25 deletions(-)

diff --git a/src/uxn11.c b/src/uxn11.c
index 3142ddf..5b7e76e 100644
--- a/src/uxn11.c
+++ b/src/uxn11.c
@@ -1,10 +1,12 @@
#define _POSIX_C_SOURCE 199309L
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sys/timerfd.h>
#include <unistd.h>
#include <poll.h>

#include "uxn.h"
#include "devices/system.h"
@@ -117,7 +119,7 @@ hide_cursor(void)
#define XK_Control 0xffe3
#define XK_Alt 0xffe9

static void
static int
processEvent(void)
{
	XEvent ev;
@@ -130,7 +132,7 @@ processEvent(void)
		XDestroyImage(ximage);
		XDestroyWindow(display, window);
		XCloseDisplay(display);
		exit(0);
		return 1;
	} break;
	case KeyPress: {
		XKeyPressedEvent *e = (XKeyPressedEvent *)&ev;
@@ -171,6 +173,7 @@ processEvent(void)
		mouse_pos(devmouse, e->x, e->y);
	} break;
	}
	return 0;
}

static int
@@ -220,14 +223,53 @@ init(void)
	return 1;
}

static void
timer_loop(int fd)
{
	struct timespec s;
	s.tv_sec = 0;
	s.tv_nsec = 16666667; /* 1/60 s in ns */
	while (1) {
		write(fd, "", 1);
		nanosleep(&s, NULL);
	}
}

static void
main_loop(int fd, Uxn *u)
{
	int pollret;
	struct pollfd fds[2];
	fds[0].fd = ConnectionNumber(display);
	fds[1].fd = fd;
	fds[0].events = fds[1].events = POLLIN;

	/* main loop */
	while(1) {
		fds[0].revents = fds[1].revents = 0;
		pollret = poll(fds, 2, -1);
		if (pollret <= 0)
			continue;
		while(XPending(display))
			if (processEvent() != 0)
				return;
		if (fds[1].revents) {
			char discard;
			uxn_eval(u, GETVECTOR(devscreen));
			read(fds[1].fd, &discard, 1);
		}
		if(uxn_screen.fg.changed || uxn_screen.bg.changed)
			redraw();
	}
}

int
main(int argc, char **argv)
{
	Uxn u;
	int i;
	char expirations[8];
	struct pollfd fds[2];
	static const struct itimerspec screen_tspec = {{0, 16666666}, {0, 16666666}};
	int pipes[2];
	pid_t pid;
	if(argc < 2)
		return error("Usage", "uxncli game.rom args");
	if(!start(&u, argv[1]))
@@ -240,23 +282,24 @@ main(int argc, char **argv)
		while(*p) console_input(&u, *p++);
		console_input(&u, '\n');
	}
	fds[0].fd = XConnectionNumber(display);
	fds[1].fd = timerfd_create(CLOCK_MONOTONIC, 0);
	timerfd_settime(fds[1].fd, 0, &screen_tspec, NULL);
	fds[0].events = fds[1].events = POLLIN;
	/* main loop */
	while(1) {
		if(poll(fds, 2, 1000) <= 0)
			continue;
		while(XPending(display))
			processEvent();
		if(poll(&fds[1], 1, 0)) {
			read(fds[1].fd, expirations, 8);    /* Indicate we handled the timer */
			uxn_eval(&u, GETVECTOR(devscreen)); /* Call the vector once, even if the timer fired multiple times */
		}
		if(uxn_screen.fg.changed || uxn_screen.bg.changed)
			redraw();

	if (pipe(pipes) != 0)
		return error("Pipe", "Failed");

	pid = fork();
	if (pid == -1) {
		return error("Fork", "Failed");
	} else if (pid == 0) {
		/* child */
		close(pipes[0]);
		timer_loop(pipes[1]);
	} else {
		/* parent */
		close(pipes[1]);
		main_loop(pipes[0], &u);

		free(u.ram);
		kill(pid, SIGKILL);
	}
	XDestroyImage(ximage);
	return 0;
}
-- 
2.35.1
Reply to thread Export thread (mbox)