Fix multiwindow support in GLES3 for X11, Windows, and MacOS.

Instead of updating all viewports, then blitting all viewports
to the backbuffer, then swapping all buffers, we run through
all viewports and render, blit, and swap backbuffer before
going to the next viewport.
This commit is contained in:
clayjohn 2022-09-12 14:57:11 -07:00
parent 79b21e96ad
commit 96b7cb66df
6 changed files with 26 additions and 32 deletions

View file

@ -280,11 +280,6 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
ERR_FAIL_COND(!rt);
// TODO: do we need a keep 3d linear option?
// Make sure we are drawing to the right context.
DisplayServer::get_singleton()->gl_window_make_current(p_screen);
if (rt->external.fbo != 0) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, rt->external.fbo);
} else {
@ -298,9 +293,6 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
// is this p_screen useless in a multi window environment?
void RasterizerGLES3::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
// All blits are going to the system framebuffer, so just bind once.
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
for (int i = 0; i < p_amount; i++) {
const BlitToScreen &blit = p_render_targets[i];

View file

@ -256,7 +256,11 @@ void GLManager_X11::release_current() {
if (!_current_window) {
return;
}
glXMakeCurrent(_x_windisp.x11_display, None, nullptr);
if (!glXMakeCurrent(_x_windisp.x11_display, None, nullptr)) {
ERR_PRINT("glXMakeCurrent failed");
}
_current_window = nullptr;
}
void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) {
@ -276,7 +280,9 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) {
const GLDisplay &disp = get_display(win.gldisplay_id);
glXMakeCurrent(disp.x11_display, win.x11_window, disp.context->glx_context);
if (!glXMakeCurrent(disp.x11_display, win.x11_window, disp.context->glx_context)) {
ERR_PRINT("glXMakeCurrent failed");
}
_internal_set_current_window(&win);
}
@ -290,13 +296,12 @@ void GLManager_X11::make_current() {
return;
}
const GLDisplay &disp = get_current_display();
glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context);
if (!glXMakeCurrent(_x_windisp.x11_display, _x_windisp.x11_window, disp.context->glx_context)) {
ERR_PRINT("glXMakeCurrent failed");
}
}
void GLManager_X11::swap_buffers() {
// NO NEED TO CALL SWAP BUFFERS for each window...
// see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml
if (!_current_window) {
return;
}
@ -315,13 +320,6 @@ void GLManager_X11::swap_buffers() {
}
}
// print_line("\tswap_buffers");
// only for debugging without drawing anything
// glClearColor(Math::randf(), 0, 1, 1);
//glClear(GL_COLOR_BUFFER_BIT);
//const GLDisplay &disp = get_current_display();
glXSwapBuffers(_x_windisp.x11_display, _x_windisp.x11_window);
}

View file

@ -167,9 +167,8 @@ void GLManager_MacOS::make_current() {
}
void GLManager_MacOS::swap_buffers() {
for (const KeyValue<DisplayServer::WindowID, GLWindow> &E : windows) {
[E.value.context flushBuffer];
}
GLWindow &win = windows[current_window];
[win.context flushBuffer];
}
void GLManager_MacOS::window_update(DisplayServer::WindowID p_window_id) {

View file

@ -289,12 +289,7 @@ void GLManager_Windows::make_current() {
}
void GLManager_Windows::swap_buffers() {
// on other platforms, OpenGL swaps buffers for all windows (on all displays, really?)
// Windows swaps buffers on a per-window basis
// REVISIT: this could be structurally bad, should we have "dirty" flags then?
for (KeyValue<DisplayServer::WindowID, GLWindow> &entry : _windows) {
SwapBuffers(entry.value.hDC);
}
SwapBuffers(_current_window->hDC);
}
Error GLManager_Windows::initialize() {

View file

@ -714,7 +714,14 @@ void RendererViewport::draw_viewports() {
blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
}
blit_to_screen_list[vp->viewport_to_screen].push_back(blit);
if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") {
Vector<BlitToScreen> blit_to_screen_vec;
blit_to_screen_vec.push_back(blit);
RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blit_to_screen_vec.ptr(), 1);
RSG::rasterizer->end_frame(true);
} else {
blit_to_screen_list[vp->viewport_to_screen].push_back(blit);
}
}
}

View file

@ -91,7 +91,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::viewport->draw_viewports();
RSG::canvas_render->update();
RSG::rasterizer->end_frame(p_swap_buffers);
if (OS::get_singleton()->get_current_rendering_driver_name() != "opengl3") {
// Already called for gl_compatibility renderer.
RSG::rasterizer->end_frame(p_swap_buffers);
}
XRServer *xr_server = XRServer::get_singleton();
if (xr_server != nullptr) {