Skip to content

Commit

Permalink
Fix slowdown of _ScreenX and _ScreenY
Browse files Browse the repository at this point in the history
The commands _ScreenX and _ScreenY got significantly slower due to the
need to wait for the GLUT thread to wake up and execute the glutGet()
command for them. We've already seen a few programs (including the IDE)
where this behavior completely grinds the program to a halt, so we
definitely can't keep it.

The simple solution here is to not call glutGet() on every _ScreenX/Y
command. Instead every time the idle/timer function runs we get the
current values for the relevant glutGet() variables and store them.
libqb_glut_get() then checks if the value being read is one of the ones
we read in the idle/timer functionand if so just returns the last read
value. By doing it this way the commands no longer has to wait on the
GLUT thread for the result.
  • Loading branch information
mkilgore committed Nov 30, 2022
1 parent f7fabda commit 7ac2eef
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions internal/c/libqb/src/glut-msg-queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,30 @@
#include <unistd.h>
#include <queue>

// note: MacOSX uses Apple's GLUT not FreeGLUT
#ifdef QB64_MACOSX
# include <GLUT/glut.h>
#else
# define CORE_FREEGLUT
# include "freeglut.h"
#endif

#include "mutex.h"
#include "glut-message.h"
#include "glut-thread.h"

static libqb_mutex *glut_msg_queue_lock = libqb_mutex_new();
static std::queue<glut_message *> glut_msg_queue;

// These values from GLUT are read on every process of the msg queue. Calls to
// libqb_glut_get() can then read from these values directly rather than wait
// for the GLUT thread to process the command.
static int glut_window_x, glut_window_y;

#ifdef CORE_FREEGLUT
static int glut_window_border_width, glut_window_header_height;
#endif

bool libqb_queue_glut_message(glut_message *msg) {
if (!libqb_is_glut_up()) {
msg->finish();
Expand All @@ -27,6 +44,14 @@ bool libqb_queue_glut_message(glut_message *msg) {
void libqb_process_glut_queue() {
libqb_mutex_guard guard(glut_msg_queue_lock);

glut_window_x = glutGet(GLUT_WINDOW_X);
glut_window_y = glutGet(GLUT_WINDOW_Y);

#ifdef CORE_FREEGLUT
glut_window_border_width = glutGet(GLUT_WINDOW_BORDER_WIDTH);
glut_window_header_height = glutGet(GLUT_WINDOW_HEADER_HEIGHT);
#endif

while (!glut_msg_queue.empty()) {
glut_message *msg = glut_msg_queue.front();
glut_msg_queue.pop();
Expand All @@ -45,7 +70,34 @@ void libqb_glut_warp_pointer(int x, int y) {
libqb_queue_glut_message(new glut_message_warp_pointer(x, y));
}

static bool is_static_glut_value(int id) {
return id == GLUT_WINDOW_Y
|| id == GLUT_WINDOW_X
#ifdef CORE_FREEGLUT
|| id == GLUT_WINDOW_BORDER_WIDTH
|| id == GLUT_WINDOW_HEADER_HEIGHT
#endif
;
}

static int __get_static_glut_value(int id) {
switch (id) {
case GLUT_WINDOW_Y: return glut_window_y;
case GLUT_WINDOW_X: return glut_window_x;
#ifdef CORE_FREEGLUT
case GLUT_WINDOW_BORDER_WIDTH: return glut_window_border_width;
case GLUT_WINDOW_HEADER_HEIGHT: return glut_window_header_height;
#endif
default: return -1;
}
}

int libqb_glut_get(int id) {
if (is_static_glut_value(id)) {
libqb_mutex_guard guard(glut_msg_queue_lock);
return __get_static_glut_value(id);
}

glut_message_get msg(id);

libqb_queue_glut_message(&msg);
Expand Down

0 comments on commit 7ac2eef

Please sign in to comment.