Skip to content

Commit

Permalink
Windows: Pause the rendering thread while switching to full screen
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Sep 20, 2015
1 parent 5f18390 commit 1410d7f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
12 changes: 10 additions & 2 deletions Windows/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,12 @@ namespace MainWindow

void ToggleFullscreen(HWND hWnd, bool goingFullscreen) {
// Make sure no rendering is happening during the switch.
Core_NotifyWindowHidden(true);

bool isOpenGL = g_Config.iGPUBackend == GPU_BACKEND_OPENGL;

if (isOpenGL) {
GL_Pause();
}

int oldWindowState = g_WindowState;
g_IgnoreWM_SIZE = true;
Expand Down Expand Up @@ -361,8 +366,11 @@ namespace MainWindow
ShowOwnedPopups(hwndMain, goingFullscreen ? FALSE : TRUE);
W32Util::MakeTopMost(hwndMain, g_Config.bTopMost);

Core_NotifyWindowHidden(false);
WindowsRawInput::NotifyMenu();

if (isOpenGL) {
GL_Resume();
}
}

RECT DetermineWindowRectangle() {
Expand Down
52 changes: 51 additions & 1 deletion Windows/OpenGLBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
static HDC hDC; // Private GDI Device Context
static HGLRC hRC; // Permanent Rendering Context
static HWND hWnd; // Holds Our Window Handle
static volatile bool pauseRequested;
static volatile bool resumeRequested;
static HANDLE pauseEvent;
static HANDLE resumeEvent;

static int xres, yres;

Expand All @@ -42,11 +46,47 @@ static bool enableGLDebug = false;
void GL_SwapBuffers() {
SwapBuffers(hDC);

if (pauseRequested) {

This comment has been minimized.

Copy link
@unknownbrackets

unknownbrackets Sep 20, 2015

Collaborator

Should probably add a comment here so someone doesn't come along in a few years and say, "who added pausing during rendering? let's delete that nonsense."

-[Unknown]

This comment has been minimized.

Copy link
@hrydgard

hrydgard Sep 20, 2015

Author Owner

you'd probably search for GL_Pause and find the comment in MainWindow.cpp, but yeah, still a good point :)

SetEvent(pauseEvent);
resumeRequested = true;
DWORD result = WaitForSingleObject(resumeEvent, INFINITE);
if (result == WAIT_TIMEOUT) {
ERROR_LOG(G3D, "Wait for resume timed out. Resuming rendering");
}
pauseRequested = false;
}

// According to some sources, doing this *after* swapbuffers can reduce frame latency
// at a large performance cost.
// at a large performance cost. So let's not.
// glFinish();
}

void GL_Pause() {
if (!hRC) {
return;
}

pauseRequested = true;
DWORD result = WaitForSingleObject(pauseEvent, INFINITE);
if (result == WAIT_TIMEOUT) {
ERROR_LOG(G3D, "Wait for pause timed out");
}
// OK, we now know the rendering thread is paused.
}

void GL_Resume() {
if (!hRC) {
return;
}

if (!resumeRequested) {
ERROR_LOG(G3D, "Not waiting to get resumed");
} else {
SetEvent(resumeEvent);
}
resumeRequested = false;
}

void FormatDebugOutputARB(char outStr[], size_t outStrSize, GLenum source, GLenum type,
GLuint id, GLenum severity, const char *msg) {
char sourceStr[32];
Expand Down Expand Up @@ -270,6 +310,14 @@ bool GL_Init(HWND window, std::string *error_message) {
glDebugMessageCallbackARB((GLDEBUGPROCARB)&DebugCallbackARB, 0); // print debug output to stderr
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
}

pauseRequested = false;
resumeRequested = false;

// These are auto-reset events.
pauseEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
resumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

return true; // Success
}

Expand All @@ -280,6 +328,8 @@ void GL_SwapInterval(int interval) {
}

void GL_Shutdown() {
CloseHandle(pauseEvent);
CloseHandle(resumeEvent);
if (hRC) {
// Are we able to release the DC and RC contexts?
if (!wglMakeCurrent(NULL,NULL)) {
Expand Down
5 changes: 5 additions & 0 deletions Windows/OpenGLBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ bool GL_Init(HWND window, std::string *error_message);
void GL_Shutdown();
void GL_SwapInterval(int interval);
void GL_SwapBuffers();

// Used during window resize. Must be called from the window thread,
// not the rendering thread or CPU thread.
void GL_Pause();
void GL_Resume();

0 comments on commit 1410d7f

Please sign in to comment.