Merge pull request #2095 from qwerasd205/flicker

Fix flickering when resizing surface.
This commit is contained in:
Mitchell Hashimoto
2024-08-15 06:32:45 -07:00
committed by GitHub
5 changed files with 41 additions and 25 deletions

View File

@ -1197,15 +1197,6 @@ fn resize(self: *Surface, size: renderer.ScreenSize) !void {
// Save our screen size
self.screen_size = size;
// Mail the renderer so that it can update the GPU and re-render
_ = self.renderer_thread.mailbox.push(.{
.resize = .{
.screen_size = self.screen_size,
.padding = self.padding,
},
}, .{ .forever = {} });
try self.queueRender();
// Recalculate our grid size. Because Ghostty supports fluid resizing,
// its possible the grid doesn't change at all even if the screen size changes.
// We have to update the IO thread no matter what because we send

View File

@ -908,12 +908,14 @@ pub fn updateFrame(
}
// If our terminal screen size doesn't match our expected renderer
// size then we skip a frame. This can happen if we get resized
// before the terminal gets resized. The terminal resize event also
// wakes up the renderer so we'll get another chance to update frame
// data.
if (self.cells.size.rows < state.terminal.rows or
self.cells.size.columns < state.terminal.cols)
// size then we skip a frame. This can happen if the terminal state
// is resized between when the renderer mailbox is drained and when
// the state mutex is acquired inside this function.
//
// For some reason this doesn't seem to cause any significant issues
// with flickering while resizing. '\_('-')_/'
if (self.cells.size.rows != state.terminal.rows or
self.cells.size.columns != state.terminal.cols)
{
return;
}
@ -2012,11 +2014,13 @@ pub fn setScreenSize(
.cursor_color = old.cursor_color,
};
// Reset our cell contents.
try self.cells.resize(self.alloc, grid_size);
// Reset our cell contents if our grid size has changed.
if (!self.cells.size.equals(grid_size)) {
try self.cells.resize(self.alloc, grid_size);
// Reset our viewport to force a rebuild
self.cells_viewport = null;
// Reset our viewport to force a rebuild
self.cells_viewport = null;
}
// If we have custom shaders then we update the state
if (self.custom_shader_state) |*state| {

View File

@ -739,6 +739,19 @@ pub fn updateFrame(
self.foreground_color = bg;
}
// If our terminal screen size doesn't match our expected renderer
// size then we skip a frame. This can happen if the terminal state
// is resized between when the renderer mailbox is drained and when
// the state mutex is acquired inside this function.
//
// For some reason this doesn't seem to cause any significant issues
// with flickering while resizing. '\_('-')_/'
if (self.grid_size.rows != state.terminal.rows or
self.grid_size.columns != state.terminal.cols)
{
return;
}
// Get the viewport pin so that we can compare it to the current.
const viewport_pin = state.terminal.screen.pages.pin(.{ .viewport = .{} }).?;

View File

@ -480,7 +480,7 @@ fn drawCallback(
r: xev.Timer.RunError!void,
) xev.CallbackAction {
_ = r catch unreachable;
const t = self_ orelse {
const t: *Thread = self_ orelse {
// This shouldn't happen so we log it.
log.warn("render callback fired without data set", .{});
return .disarm;
@ -504,7 +504,7 @@ fn renderCallback(
r: xev.Timer.RunError!void,
) xev.CallbackAction {
_ = r catch unreachable;
const t = self_ orelse {
const t: *Thread = self_ orelse {
// This shouldn't happen so we log it.
log.warn("render callback fired without data set", .{});
return .disarm;
@ -522,6 +522,8 @@ fn renderCallback(
t.flags.cursor_blink_visible,
) catch |err|
log.warn("error rendering err={}", .{err});
// Draw
t.drawFrame(false);
return .disarm;
@ -543,7 +545,7 @@ fn cursorTimerCallback(
},
};
const t = self_ orelse {
const t: *Thread = self_ orelse {
// This shouldn't happen so we log it.
log.warn("render callback fired without data set", .{});
return .disarm;

View File

@ -378,14 +378,20 @@ pub fn resize(
// immediately for a resize. This is allowed by the spec.
self.terminal.modes.set(.synchronized_output, false);
// Wake up our renderer so any changes will be shown asap
self.renderer_wakeup.notify() catch {};
// If we have size reporting enabled we need to send a report.
if (self.terminal.modes.get(.in_band_size_reports)) {
try self.sizeReportLocked(td, .mode_2048);
}
}
// Mail the renderer so that it can update the GPU and re-render
_ = self.renderer_mailbox.push(.{
.resize = .{
.screen_size = screen_size,
.padding = padding,
},
}, .{ .forever = {} });
self.renderer_wakeup.notify() catch {};
}
/// Make a size report.