only update cells in the render call

This commit is contained in:
Mitchell Hashimoto
2022-04-29 19:47:17 -07:00
parent e0a6836cbd
commit 308050dc7d
3 changed files with 38 additions and 8 deletions

View File

@ -258,6 +258,9 @@ pub fn demoCells(self: *Grid) !void {
/// updateCells updates our GPU cells from the current terminal view.
/// The updated cells will take effect on the next render.
pub fn updateCells(self: *Grid, term: Terminal) !void {
const t = trace(@src());
defer t.end();
// For now, we just ensure that we have enough cells for all the lines
// we have plus a full width. This is very likely too much but its
// the probably close enough while guaranteeing no more allocations.

View File

@ -260,9 +260,6 @@ fn sizeCallback(window: glfw.Window, width: i32, height: i32) void {
// Update the size of our terminal state
win.terminal.resize(win.grid.size.columns, win.grid.size.rows);
// TODO: this is not the right place for this
win.grid.updateCells(win.terminal) catch unreachable;
// Update the size of our pty
win.pty.setSize(.{
.ws_row = @intCast(u16, win.grid.size.rows),
@ -376,7 +373,6 @@ fn focusCallback(window: glfw.Window, focused: bool) void {
} else {
win.grid.cursor_visible = true;
win.grid.cursor_style = .box_hollow;
win.grid.updateCells(win.terminal) catch unreachable;
win.cursor_timer.stop() catch unreachable;
}
}
@ -387,7 +383,6 @@ fn cursorTimerCallback(t: *libuv.Timer) void {
const win = t.getData(Window) orelse return;
win.grid.cursor_visible = !win.grid.cursor_visible;
win.grid.updateCells(win.terminal) catch unreachable;
win.render_timer.schedule() catch unreachable;
}
@ -432,9 +427,6 @@ fn ttyRead(t: *libuv.Tty, n: isize, buf: []const u8) void {
_ = win.cursor_timer.again() catch null;
}
// Update the cells for drawing
win.grid.updateCells(win.terminal) catch unreachable;
// Schedule a render
win.render_timer.schedule() catch unreachable;
}
@ -456,10 +448,14 @@ fn ttyWrite(req: *libuv.WriteReq, status: i32) void {
fn renderTimerCallback(t: *libuv.Timer) void {
const tracy = trace(@src());
tracy.color(0x006E7F); // blue-ish
defer tracy.end();
const win = t.getData(Window).?;
// Update the cells for drawing
win.grid.updateCells(win.terminal) catch unreachable;
// Set our background
gl.clearColor(0.2, 0.3, 0.3, 1.0);
gl.clear(gl.c.GL_COLOR_BUFFER_BIT);

View File

@ -10,6 +10,7 @@ const Allocator = std.mem.Allocator;
const ansi = @import("ansi.zig");
const Parser = @import("Parser.zig");
const Tabstops = @import("Tabstops.zig");
const trace = @import("../tracy/tracy.zig").trace;
const log = std.log.scoped(.terminal);
@ -105,6 +106,9 @@ pub fn plainString(self: Terminal, alloc: Allocator) ![]const u8 {
/// Append a string of characters. See appendChar.
pub fn append(self: *Terminal, alloc: Allocator, str: []const u8) !void {
const tracy = trace(@src());
defer tracy.end();
for (str) |c| {
try self.appendChar(alloc, c);
}
@ -114,6 +118,9 @@ pub fn append(self: *Terminal, alloc: Allocator, str: []const u8) !void {
///
/// This may allocate if necessary to store the character in the grid.
pub fn appendChar(self: *Terminal, alloc: Allocator, c: u8) !void {
const tracy = trace(@src());
defer tracy.end();
//log.debug("char: {}", .{c});
const actions = self.parser.next(c);
for (actions) |action_opt| {
@ -125,6 +132,9 @@ pub fn appendChar(self: *Terminal, alloc: Allocator, c: u8) !void {
}
fn print(self: *Terminal, alloc: Allocator, c: u8) !void {
const tracy = trace(@src());
defer tracy.end();
// Build our cell
const cell = try self.getOrPutCell(alloc, self.cursor.x, self.cursor.y);
cell.* = .{
@ -141,6 +151,9 @@ fn print(self: *Terminal, alloc: Allocator, c: u8) !void {
}
fn execute(self: *Terminal, alloc: Allocator, c: u8) !void {
const tracy = trace(@src());
defer tracy.end();
switch (@intToEnum(ansi.C0, c)) {
.BEL => self.bell(),
.BS => self.backspace(),
@ -158,12 +171,18 @@ pub fn bell(self: *Terminal) void {
/// Backspace moves the cursor back a column (but not less than 0).
pub fn backspace(self: *Terminal) void {
const tracy = trace(@src());
defer tracy.end();
self.cursor.x -|= 1;
}
/// Horizontal tab moves the cursor to the next tabstop, clearing
/// the screen to the left the tabstop.
pub fn horizontal_tab(self: *Terminal, alloc: Allocator) !void {
const tracy = trace(@src());
defer tracy.end();
while (self.cursor.x < self.cols) {
// Clear
try self.print(alloc, ' ');
@ -177,11 +196,17 @@ pub fn horizontal_tab(self: *Terminal, alloc: Allocator) !void {
/// Carriage return moves the cursor to the first column.
pub fn carriage_return(self: *Terminal) void {
const tracy = trace(@src());
defer tracy.end();
self.cursor.x = 0;
}
/// Linefeed moves the cursor to the next line.
pub fn linefeed(self: *Terminal, alloc: Allocator) void {
const tracy = trace(@src());
defer tracy.end();
// If we're at the end of the screen, scroll up. This is surprisingly
// common because most terminals live with a full screen so we do this
// check first.
@ -196,6 +221,9 @@ pub fn linefeed(self: *Terminal, alloc: Allocator) void {
/// Scroll the text up by one row.
pub fn scroll_up(self: *Terminal, alloc: Allocator) void {
const tracy = trace(@src());
defer tracy.end();
// TODO: this is horribly expensive. we need to optimize the screen repr
// If we have no items, scrolling does nothing.
@ -212,6 +240,9 @@ pub fn scroll_up(self: *Terminal, alloc: Allocator) void {
}
fn getOrPutCell(self: *Terminal, alloc: Allocator, x: usize, y: usize) !*Cell {
const tracy = trace(@src());
defer tracy.end();
// If we don't have enough lines to get to y, then add it.
if (self.screen.items.len < y + 1) {
try self.screen.ensureTotalCapacity(alloc, y + 1);