mirror of
https://github.com/pevans/erc-c.git
synced 2024-12-21 08:30:55 +00:00
Avoid polling for events until we're ready for a frame redraw
This change drastically cuts the number of times we poll for events, and consequently drastically speeds up the number of frames we can draw within any given span of time. In other words, we go from "this barely moves as fast as the actual Apple II" to "holy shit this moves so fast".
This commit is contained in:
parent
f8dd49e892
commit
281544bf43
@ -1,8 +1,9 @@
|
||||
#ifndef _VM_SCREEN_H_
|
||||
#define _VM_SCREEN_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "vm_area.h"
|
||||
#include "vm_bits.h"
|
||||
@ -45,6 +46,18 @@ typedef struct {
|
||||
int xcoords;
|
||||
int ycoords;
|
||||
|
||||
/*
|
||||
* This is the time we last refreshed the screen.
|
||||
*/
|
||||
struct timeval reftime;
|
||||
|
||||
/*
|
||||
* This field is the number of microseconds we have to wait until we
|
||||
* are ready to redraw the frame. It cannot be greater than 1000000,
|
||||
* which is the number of microseconds within a second.
|
||||
*/
|
||||
int usec_until_refresh;
|
||||
|
||||
/*
|
||||
* Hang onto the last key pressed and the status of whether a key
|
||||
* is pressed right now or not.
|
||||
@ -68,6 +81,7 @@ typedef struct {
|
||||
extern bool vm_screen_active(vm_screen *);
|
||||
extern bool vm_screen_dirty(vm_screen *);
|
||||
extern bool vm_screen_key_pressed(vm_screen *);
|
||||
extern bool vm_screen_needs_frame(vm_screen *);
|
||||
extern char vm_screen_last_key(vm_screen *);
|
||||
extern int vm_screen_add_window(vm_screen *, int, int);
|
||||
extern int vm_screen_init();
|
||||
|
@ -69,6 +69,9 @@ vm_screen_create()
|
||||
screen->key_pressed = false;
|
||||
screen->dirty = false;
|
||||
screen->should_exit = false;
|
||||
screen->usec_until_refresh = 33333;
|
||||
|
||||
memset(&screen->reftime, 0, sizeof(struct timeval));
|
||||
|
||||
screen->window = NULL;
|
||||
screen->render = NULL;
|
||||
@ -177,8 +180,6 @@ vm_screen_free(vm_screen *screen)
|
||||
bool
|
||||
vm_screen_active(vm_screen *scr)
|
||||
{
|
||||
vm_event_poll(scr);
|
||||
|
||||
// If something happened in the event loop that caused the user to
|
||||
// signal an exit, then returning false here will do the trick
|
||||
if (scr->should_exit) {
|
||||
@ -257,6 +258,29 @@ vm_screen_last_key(vm_screen *scr)
|
||||
return scr->last_key;
|
||||
}
|
||||
|
||||
bool
|
||||
vm_screen_needs_frame(vm_screen *scr)
|
||||
{
|
||||
struct timeval now;
|
||||
unsigned int diff;
|
||||
|
||||
if (gettimeofday(&now, NULL) < 0) {
|
||||
log_crit("Failed call to gettimeofday()");
|
||||
return false;
|
||||
}
|
||||
|
||||
diff =
|
||||
((now.tv_sec - scr->reftime.tv_sec) * 1000000) +
|
||||
(now.tv_usec - scr->reftime.tv_usec);
|
||||
|
||||
if (diff > scr->usec_until_refresh) {
|
||||
memcpy(&scr->reftime, &now, sizeof(struct timeval));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the screen is considered dirty (i.e., if the screen
|
||||
* needs to be redrawn).
|
||||
@ -264,22 +288,9 @@ vm_screen_last_key(vm_screen *scr)
|
||||
bool
|
||||
vm_screen_dirty(vm_screen *scr)
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
if (scr->dirty) {
|
||||
// If this returns an error, I have to assume the computer
|
||||
// itself may be on fire, or has grown fangs and is presently
|
||||
// nibbling on the user
|
||||
if (gettimeofday(&now, NULL) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (now.tv_sec > refresh_time.tv_sec ||
|
||||
(now.tv_usec > refresh_time.tv_usec + 50000)
|
||||
) {
|
||||
memcpy(&refresh_time, &now, sizeof(struct timeval));
|
||||
return true;
|
||||
}
|
||||
if (vm_screen_needs_frame(scr)) {
|
||||
vm_event_poll(scr);
|
||||
return scr->dirty;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user