renderer/opengl: reduce flickering/stretching on resize
Fixes #2446 Two separate issues: 1. Ensure that our screen size matches the viewport size when drawFrame is called. By the time drawFrame is called, GTK will have updated the OpenGL context, but our deferred screen size may still be incorrect since we wait for the pty to update the screen size. 2. Do not clear our cells buffer when the screen size changes, instead changing to a mechanism that only clears the buffers when we have over 50% wasted space. Co-authored-by: Andrew de los Reyes <adlr@rivosinc.com>pull/7155/head
parent
3e9b5d491c
commit
e5e9d43d52
|
|
@ -1779,6 +1779,15 @@ pub fn rebuildCells(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Free up memory, generally in case where surface has shrunk.
|
||||||
|
// If more than half of the capacity is unused, remove all unused capacity.
|
||||||
|
if (self.cells.items.len * 2 < self.cells.capacity) {
|
||||||
|
self.cells.shrinkAndFree(self.alloc, self.cells.items.len);
|
||||||
|
}
|
||||||
|
if (self.cells_bg.items.len * 2 < self.cells_bg.capacity) {
|
||||||
|
self.cells_bg.shrinkAndFree(self.alloc, self.cells_bg.items.len);
|
||||||
|
}
|
||||||
|
|
||||||
// Some debug mode safety checks
|
// Some debug mode safety checks
|
||||||
if (std.debug.runtime_safety) {
|
if (std.debug.runtime_safety) {
|
||||||
for (self.cells_bg.items) |cell| assert(cell.mode == .bg);
|
for (self.cells_bg.items) |cell| assert(cell.mode == .bg);
|
||||||
|
|
@ -2196,12 +2205,6 @@ pub fn setScreenSize(
|
||||||
if (single_threaded_draw) self.draw_mutex.lock();
|
if (single_threaded_draw) self.draw_mutex.lock();
|
||||||
defer if (single_threaded_draw) self.draw_mutex.unlock();
|
defer if (single_threaded_draw) self.draw_mutex.unlock();
|
||||||
|
|
||||||
// Reset our buffer sizes so that we free memory when the screen shrinks.
|
|
||||||
// This could be made more clever by only doing this when the screen
|
|
||||||
// shrinks but the performance cost really isn't that much.
|
|
||||||
self.cells.clearAndFree(self.alloc);
|
|
||||||
self.cells_bg.clearAndFree(self.alloc);
|
|
||||||
|
|
||||||
// Store our screen size
|
// Store our screen size
|
||||||
self.size = size;
|
self.size = size;
|
||||||
|
|
||||||
|
|
@ -2338,6 +2341,23 @@ pub fn drawFrame(self: *OpenGL, surface: *apprt.Surface) !void {
|
||||||
if (comptime is_darwin) _ = ogl.CGLLockContext(cgl_ctx);
|
if (comptime is_darwin) _ = ogl.CGLLockContext(cgl_ctx);
|
||||||
defer _ = if (comptime is_darwin) ogl.CGLUnlockContext(cgl_ctx);
|
defer _ = if (comptime is_darwin) ogl.CGLUnlockContext(cgl_ctx);
|
||||||
|
|
||||||
|
// If our viewport size doesn't match the saved screen size then
|
||||||
|
// we need to update it. We rely on this over setScreenSize because
|
||||||
|
// we can pull it directly from the OpenGL context instead of relying
|
||||||
|
// on the eventual message.
|
||||||
|
{
|
||||||
|
var viewport: [4]gl.c.GLint = undefined;
|
||||||
|
gl.glad.context.GetIntegerv.?(gl.c.GL_VIEWPORT, &viewport);
|
||||||
|
const screen: renderer.ScreenSize = .{
|
||||||
|
.width = @intCast(viewport[2]),
|
||||||
|
.height = @intCast(viewport[3]),
|
||||||
|
};
|
||||||
|
if (!screen.equals(self.size.screen)) {
|
||||||
|
self.size.screen = screen;
|
||||||
|
self.deferred_screen_size = .{ .size = self.size };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Draw our terminal cells
|
// Draw our terminal cells
|
||||||
try self.drawCellProgram(gl_state);
|
try self.drawCellProgram(gl_state);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue