Skip to content

Commit

Permalink
Perform window creation in eventthread
Browse files Browse the repository at this point in the history
  • Loading branch information
Speak2Erase committed Jul 6, 2024
1 parent b8cfec5 commit 027c7a0
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 18 deletions.
25 changes: 13 additions & 12 deletions binding/osfm-screen-binding.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <SDL2/SDL.h>
#include "etc-internal.h"
#include "eventthread.h"
#include "gl-fun.h"
#include "gl-util.h"
#include "gl-meta.h"
Expand Down Expand Up @@ -286,31 +287,31 @@ struct MonitorWindow {
WindowScene scene;

MonitorWindow(int x, int y, int w, int h, unsigned int flags, const char* name) : scene(w, h) {
window = SDL_CreateWindow(name, x, y, w, h, flags);
EventThread::CreateWindowArgs args = {x, y, w, h, flags, name};
window = shState->eThread().requestNewWindow(&args);
shState->monitorWindows.insert(this);
}
~MonitorWindow() {
shState->monitorWindows.erase(this);
if (window)
SDL_DestroyWindow(window);
shState->eThread().destroySDLWindow(window); // do it on the event thread
}

void draw();
// renders to ping pong buffer
void renderScene();
// present the ping pong buffer
void present();
Scene* getScene();
};
// so we can use this from outside this file
Scene* MonitorWindow::getScene() {
return &scene;
}
void MonitorWindow::draw() {
SDL_GLContext ctx = shState->graphics().context();
int err = SDL_GL_MakeCurrent(window, ctx);
if (err != 0) {
GFX_UNLOCK;
rb_raise(rb_eRuntimeError, "Failed to make window current: %s", SDL_GetError());
}

void MonitorWindow::renderScene() {
scene.composite();
}
void MonitorWindow::present() {
SDL_GLContext ctx = shState->graphics().context();
SDL_GL_MakeCurrent(window, ctx);
auto geo = scene.getGeometry();
int w = geo.rect.w;
int h = geo.rect.h;
Expand Down
15 changes: 9 additions & 6 deletions src/display/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
#define AUDIO_BUFFER_LEN_MS 2000

struct MonitorWindow {
void draw();
void renderScene();
void present();
};

typedef struct AudioQueue
Expand Down Expand Up @@ -1185,6 +1186,9 @@ struct GraphicsPrivate {
shState->oneshot().obscuredDirty = false;
}
screen.composite();
for (auto window : shState->monitorWindows) {
window->renderScene(); // renders to an offscreen fbo so we dont need to switch contexts
}

// maybe unspaghetti this later
if (integerScaleStepApplicable() && !integerLastMileScaling)
Expand Down Expand Up @@ -1248,8 +1252,11 @@ struct GraphicsPrivate {

GLMeta::blitEnd();

// perform presents here to avoid constant context switching
swapGLBuffer();

for (auto window : shState->monitorWindows) {
window->present();
}
updateAvgFPS();
}

Expand Down Expand Up @@ -1370,10 +1377,6 @@ void Graphics::update(bool checkForShutdown) {

p->checkResize();
p->redrawScreen();

for (auto window : shState->monitorWindows) {
window->draw();
}
}

void Graphics::freeze() {
Expand Down
37 changes: 37 additions & 0 deletions src/eventthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/

#include "eventthread.h"
#include "SDL_video.h"

#include <SDL_events.h>
#include <SDL_messagebox.h>
Expand Down Expand Up @@ -109,12 +110,15 @@ enum
REQUEST_TEXTMODE,

REQUEST_SETTINGS,
REQUEST_NEW_WINDOW,
REQUEST_DESTROY_WINDOW,

UPDATE_FPS,
UPDATE_SCREEN_RECT,

EVENT_COUNT
};
volatile SDL_Window *new_window;

static uint32_t usrIdStart;

Expand Down Expand Up @@ -594,6 +598,20 @@ void EventThread::process(RGSSThreadData &rtData)
openSettingsWindow();
#endif
break;
case REQUEST_NEW_WINDOW:
{
const CreateWindowArgs *args = static_cast<const CreateWindowArgs*>(event.user.data1);
new_window = SDL_CreateWindow(args->name,
args->x, args->y,
args->w, args->h,
args->flags);
break;
}
case REQUEST_DESTROY_WINDOW:
{
SDL_DestroyWindow(static_cast<SDL_Window*>(event.user.data1));
break;
}

case UPDATE_FPS :
if (rtData.config.printFPS)
Expand Down Expand Up @@ -833,6 +851,25 @@ void EventThread::requestSettingsMenu()
SDL_PushEvent(&event);
}

SDL_Window *EventThread::requestNewWindow(const CreateWindowArgs *args)
{
SDL_Event event;
event.type = usrIdStart + REQUEST_NEW_WINDOW;
event.user.data1 = (void*)args;
new_window = nullptr; // reset
SDL_PushEvent(&event);
while (!new_window)
SDL_Delay(1);
return (SDL_Window*) new_window;
}
void EventThread::destroySDLWindow(SDL_Window *window)
{
SDL_Event event;
event.type = usrIdStart + REQUEST_DESTROY_WINDOW;
event.user.data1 = window;
SDL_PushEvent(&event);
}

void EventThread::showMessageBox(const char *body, int flags)
{
msgBoxDone.clear();
Expand Down
6 changes: 6 additions & 0 deletions src/eventthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include <stdint.h>

#include "SDL_video.h"
#include "config.h"
#include "etc-internal.h"
#include "sdl-util.h"
Expand Down Expand Up @@ -98,6 +99,11 @@ class EventThread
void requestWindowCenter();
void requestWindowRename(const char *title);
void requestShowCursor(bool mode);

struct CreateWindowArgs { int x; int y; int w; int h; unsigned int flags; const char* name; };
// get random freezes without doing this on the event thread
SDL_Window* requestNewWindow(const CreateWindowArgs *args);
void destroySDLWindow(SDL_Window *window);

void requestTextInputMode(bool mode);

Expand Down

0 comments on commit 027c7a0

Please sign in to comment.