Skip to content

Commit 0399e13

Browse files
authored
Fix window_res related bugs (#6753)
1 parent 0bf5714 commit 0399e13

File tree

3 files changed

+72
-15
lines changed

3 files changed

+72
-15
lines changed

code/graphics/opengl/gropengl.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ void gr_opengl_flip()
130130
if (Cmdline_gl_finish)
131131
glFinish();
132132

133+
Assertion(GL_state.ValidForFlip(), "OpenGL state is invalid!");
134+
133135
current_viewport->swapBuffers();
134136

135137
opengl_tcache_frame();
@@ -278,7 +280,11 @@ void gr_opengl_print_screen(const char *filename)
278280

279281
_mkdir(os_get_config_path("screenshots").c_str());
280282

281-
// glReadBuffer(GL_FRONT);
283+
GL_state.PushFramebufferState();
284+
GL_state.BindFrameBuffer(Cmdline_window_res ? Back_framebuffer : 0, GL_FRAMEBUFFER);
285+
286+
//Reading from the front buffer here seems to no longer work correctly; that just reads back all zeros
287+
glReadBuffer(Cmdline_window_res ? GL_COLOR_ATTACHMENT0 : GL_FRONT);
282288

283289
// now for the data
284290
if (Use_PBOs) {
@@ -292,7 +298,6 @@ void gr_opengl_print_screen(const char *filename)
292298
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
293299
glBufferData(GL_PIXEL_PACK_BUFFER, (gr_screen.max_w * gr_screen.max_h * 4), NULL, GL_STATIC_READ);
294300

295-
glReadBuffer(GL_FRONT);
296301
glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
297302

298303
// map the image data so that we can save it to file
@@ -319,6 +324,8 @@ void gr_opengl_print_screen(const char *filename)
319324
glDeleteBuffers(1, &pbo);
320325
}
321326

327+
GL_state.PopFramebufferState();
328+
322329
if (pixels != NULL) {
323330
vm_free(pixels);
324331
}
@@ -329,6 +336,12 @@ SCP_string gr_opengl_blob_screen()
329336
GLubyte* pixels = nullptr;
330337
GLuint pbo = 0;
331338

339+
GL_state.PushFramebufferState();
340+
GL_state.BindFrameBuffer(Cmdline_window_res ? Back_framebuffer : 0, GL_FRAMEBUFFER);
341+
342+
//Reading from the front buffer here seems to no longer work correctly; that just reads back all zeros
343+
glReadBuffer(Cmdline_window_res ? GL_COLOR_ATTACHMENT0 : GL_FRONT);
344+
332345
// now for the data
333346
if (Use_PBOs) {
334347
Assert(!pbo);
@@ -341,7 +354,6 @@ SCP_string gr_opengl_blob_screen()
341354
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
342355
glBufferData(GL_PIXEL_PACK_BUFFER, (gr_screen.max_w * gr_screen.max_h * 4), NULL, GL_STATIC_READ);
343356

344-
glReadBuffer(GL_FRONT);
345357
glReadPixels(0, 0, gr_screen.max_w, gr_screen.max_h, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
346358

347359
// map the image data so that we can save it to file
@@ -367,6 +379,8 @@ SCP_string gr_opengl_blob_screen()
367379
glDeleteBuffers(1, &pbo);
368380
}
369381

382+
GL_state.PopFramebufferState();
383+
370384
if (pixels != nullptr) {
371385
vm_free(pixels);
372386
}
@@ -618,7 +632,7 @@ void gr_opengl_get_region(int /*front*/, int w, int h, ubyte *data)
618632

619633
}
620634

621-
int gr_opengl_save_screen()
635+
int gr_opengl_save_screen()
622636
{
623637
int i;
624638
ubyte *sptr = NULL, *dptr = NULL;
@@ -640,7 +654,12 @@ int gr_opengl_save_screen()
640654
}
641655

642656
GLboolean save_state = GL_state.DepthTest(GL_FALSE);
643-
glReadBuffer(GL_FRONT_LEFT);
657+
658+
GL_state.PushFramebufferState();
659+
GL_state.BindFrameBuffer(Cmdline_window_res ? Back_framebuffer : 0, GL_FRAMEBUFFER);
660+
661+
//Reading from the front buffer here seems to no longer work correctly; that just reads back all zeros
662+
glReadBuffer(Cmdline_window_res ? GL_COLOR_ATTACHMENT0 : GL_FRONT);
644663

645664
if ( Use_PBOs ) {
646665
GLubyte *pixels = NULL;
@@ -713,6 +732,7 @@ int gr_opengl_save_screen()
713732
GL_saved_screen_id = bm_create(32, gr_screen.max_w, gr_screen.max_h, GL_saved_screen, 0);
714733
}
715734

735+
GL_state.PopFramebufferState();
716736
GL_state.DepthTest(save_state);
717737

718738
return GL_saved_screen_id;

code/graphics/opengl/gropenglstate.cpp

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ void opengl_state::init()
193193
current_program = 0;
194194
glUseProgram(0);
195195

196-
current_framebuffer = 0;
196+
current_framebuffer = {0, 0};
197197
glBindFramebuffer(GL_FRAMEBUFFER, 0);
198198

199199
framebuffer_stack.clear();
@@ -552,22 +552,56 @@ bool opengl_state::IsCurrentProgram(GLuint program) {
552552
return current_program == program;
553553
}
554554
void opengl_state::BindFrameBuffer(GLuint name, GLenum mode) {
555-
if (current_framebuffer != name) {
556-
glBindFramebuffer(mode, name);
557-
current_framebuffer = name;
555+
switch(mode) {
556+
case GL_FRAMEBUFFER:
557+
if (current_framebuffer.first != current_framebuffer.second || current_framebuffer.first != name) {
558+
glBindFramebuffer(mode, name);
559+
current_framebuffer = {name, name};
560+
}
561+
break;
562+
case GL_READ_FRAMEBUFFER:
563+
if (current_framebuffer.first != name) {
564+
glBindFramebuffer(mode, name);
565+
current_framebuffer.first = name;
566+
}
567+
break;
568+
case GL_DRAW_FRAMEBUFFER:
569+
if (current_framebuffer.second != name) {
570+
glBindFramebuffer(mode, name);
571+
current_framebuffer.second = name;
572+
}
573+
break;
574+
default:
575+
UNREACHABLE("Invalid BindFrameBuffer mode!");
576+
}
577+
}
578+
void opengl_state::BindFrameBufferBoth(GLuint read, GLuint draw) {
579+
if (read != current_framebuffer.first) {
580+
glBindFramebuffer(GL_READ_FRAMEBUFFER, read);
581+
current_framebuffer.first = read;
582+
}
583+
if (draw != current_framebuffer.second) {
584+
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw);
585+
current_framebuffer.second = draw;
558586
}
559587
}
560588
void opengl_state::PushFramebufferState() {
561589
framebuffer_stack.push_back(current_framebuffer);
562590
}
563591
void opengl_state::PopFramebufferState() {
564-
Assertion(framebuffer_stack.size() > 0, "Tried to pop the framebuffer state stack while it was empty!");
592+
Assertion(!framebuffer_stack.empty(), "Tried to pop the framebuffer state stack while it was empty!");
565593

566-
auto restoreBuffer = framebuffer_stack.back();
594+
auto [restoreBufferRead, restoreBufferDraw] = framebuffer_stack.back();
567595
framebuffer_stack.pop_back();
568596

569-
BindFrameBuffer(restoreBuffer);
597+
BindFrameBufferBoth(restoreBufferRead, restoreBufferDraw);
570598
}
599+
600+
bool opengl_state::ValidForFlip() const {
601+
//Check everything that may put the state into an invalid state for rendering
602+
return framebuffer_stack.empty() && current_framebuffer.first == 0 && current_framebuffer.second == 0;
603+
}
604+
571605
void opengl_state::BindVertexArray(GLuint vao) {
572606
if (current_vao == vao) {
573607
return;

code/graphics/opengl/gropenglstate.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,9 @@ class opengl_state
241241

242242
GLuint current_program;
243243

244-
// The framebuffer state actually consists of draw and read buffers but we only use both at the same time
245-
GLuint current_framebuffer;
246-
SCP_vector<GLuint> framebuffer_stack;
244+
// The first is the read buffer, the second is the draw buffer
245+
std::pair<GLuint, GLuint> current_framebuffer;
246+
SCP_vector<std::pair<GLuint, GLuint>> framebuffer_stack;
247247

248248
GLuint current_vao = 0;
249249
public:
@@ -291,11 +291,14 @@ class opengl_state
291291
bool IsCurrentProgram(GLuint program);
292292

293293
void BindFrameBuffer(GLuint name, GLenum mode = GL_FRAMEBUFFER);
294+
void BindFrameBufferBoth(GLuint read, GLuint draw);
294295

295296
void PushFramebufferState();
296297
void PopFramebufferState();
297298

298299
void BindVertexArray(GLuint vao);
300+
301+
bool ValidForFlip() const;
299302
};
300303

301304
inline GLenum opengl_state::FrontFaceValue(GLenum new_val)

0 commit comments

Comments
 (0)