1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-20 11:17:15 +03:00

Make quad allocation more dynamic

This commit removes the `Quads` struct which maintained pre-defined quad
indices for each of the cells, the background image and scrollbar thumb.

In its place, we now "dynamically" hand out quads to meet the needs of
what is being rendered.  There are some efficiency gains here with
things like the selection (which can now be a single stretched quad,
rather than `n` quads in width).

This isn't a fully dynamic allocation scheme, as we still allocate the
current worst case number of quads when resizing.

A following commit will adjust that so that we allocate a ballpark and
then employ a mechanism similar to OutOfTextureSpace to grow and retry a
render pass when we need more quads.

Futhermore, this dynamic approach may allow reducing the amount of stuff
we have in the Vertex and "simply" render some quads before others so
that we don't have to have so many draw() passes to build up the
complete scene.

refs: #986
This commit is contained in:
Wez Furlong 2021-07-30 12:59:15 -07:00
parent 72d368440f
commit 6a84f051b6
5 changed files with 211 additions and 237 deletions

View File

@ -4,9 +4,6 @@
use ::window::bitmaps::TextureRect;
use ::window::color::LinearRgba;
use ::window::glium::buffer::Mapping;
use ::window::glium::VertexBuffer;
use std::cell::RefMut;
/// Each cell is composed of two triangles built from 4 vertices.
/// The buffer is organized row by row.
@ -65,70 +62,9 @@ pub struct Vertex {
has_color
);
/// A helper for knowing how to locate the right quad for an element
/// in the UI
#[derive(Default, Debug, Clone)]
pub struct Quads {
/// How many cells per row
pub cols: usize,
/// row number to vertex index for the first vertex on that row
pub row_starts: Vec<usize>,
/// The vertex index for the first vertex of the scroll bar thumb
pub scroll_thumb: usize,
pub background_image: usize,
}
pub struct MappedQuads<'a> {
mapping: Mapping<'a, [Vertex]>,
quads: Quads,
}
impl<'a> MappedQuads<'a> {
pub fn cell<'b>(&'b mut self, x: usize, y: usize) -> anyhow::Result<Quad<'b>> {
if x >= self.quads.cols {
anyhow::bail!("column {} is outside of the vertex buffer range", x);
}
let start = self
.quads
.row_starts
.get(y)
.ok_or_else(|| anyhow::anyhow!("line {} is outside the vertex buffer range", y))?
+ x * VERTICES_PER_CELL;
Ok(Quad {
vert: &mut self.mapping[start..start + VERTICES_PER_CELL],
})
}
pub fn scroll_thumb<'b>(&'b mut self) -> Quad<'b> {
let start = self.quads.scroll_thumb;
Quad {
vert: &mut self.mapping[start..start + VERTICES_PER_CELL],
}
}
pub fn background_image<'b>(&'b mut self) -> Quad<'b> {
let start = self.quads.background_image;
Quad {
vert: &mut self.mapping[start..start + VERTICES_PER_CELL],
}
}
}
impl Quads {
pub fn map<'a>(&self, bufs: &'a mut RefMut<VertexBuffer<Vertex>>) -> MappedQuads<'a> {
let mapping = bufs.slice_mut(..).expect("to map vertex buffer").map();
MappedQuads {
mapping,
quads: self.clone(),
}
}
}
/// A helper for updating the 4 vertices that compose a glyph cell
pub struct Quad<'a> {
vert: &'a mut [Vertex],
pub(crate) vert: &'a mut [Vertex],
}
impl<'a> Quad<'a> {

View File

@ -3,23 +3,69 @@ use super::quad::*;
use super::utilsprites::{RenderMetrics, UtilSprites};
use ::window::bitmaps::atlas::OutOfTextureSpace;
use ::window::glium::backend::Context as GliumContext;
use ::window::glium::buffer::Mapping;
use ::window::glium::texture::SrgbTexture2d;
use ::window::glium::{IndexBuffer, VertexBuffer};
use ::window::*;
use config::ConfigHandle;
use std::cell::{Ref, RefCell, RefMut};
use std::rc::Rc;
use wezterm_font::FontConfiguration;
const INDICES_PER_CELL: usize = 6;
pub struct MappedQuads<'a> {
mapping: Mapping<'a, [Vertex]>,
next: RefMut<'a, usize>,
capacity: usize,
}
impl<'a> MappedQuads<'a> {
pub fn allocate<'b>(&'b mut self) -> anyhow::Result<Quad<'b>> {
let idx = *self.next;
if idx >= self.capacity {
anyhow::bail!("not enough quads! do something like OutOfTextureSpace");
}
*self.next += 1;
let idx = idx * VERTICES_PER_CELL;
let mut quad = Quad {
vert: &mut self.mapping[idx..idx + VERTICES_PER_CELL],
};
quad.set_texture_adjust(0., 0., 0., 0.);
quad.set_has_color(false);
Ok(quad)
}
}
pub struct TripleVertexBuffer {
pub index: RefCell<usize>,
pub bufs: RefCell<[VertexBuffer<Vertex>; 3]>,
pub indices: IndexBuffer<u32>,
pub capacity: usize,
pub quads: Quads,
pub next_quad: RefCell<usize>,
}
impl TripleVertexBuffer {
pub fn clear_quad_allocation(&self) {
*self.next_quad.borrow_mut() = 0;
}
pub fn vertex_index_count(&self) -> (usize, usize) {
let num_quads = *self.next_quad.borrow();
(num_quads * VERTICES_PER_CELL, num_quads * INDICES_PER_CELL)
}
pub fn map<'a>(&'a self, bufs: &'a mut RefMut<VertexBuffer<Vertex>>) -> MappedQuads<'a> {
let mapping = bufs.slice_mut(..).expect("to map vertex buffer").map();
MappedQuads {
mapping,
next: self.next_quad.borrow_mut(),
capacity: self.capacity,
}
}
pub fn current_vb(&self) -> Ref<VertexBuffer<Vertex>> {
let index = *self.index.borrow();
let bufs = self.bufs.borrow();
@ -54,7 +100,6 @@ pub struct RenderState {
impl RenderState {
pub fn new(
config: &ConfigHandle,
context: Rc<GliumContext>,
fonts: &Rc<FontConfiguration>,
metrics: &RenderMetrics,
@ -79,7 +124,6 @@ impl RenderState {
let img_prog = Self::compile_prog(&context, true, Self::img_shader)?;
let glyph_vertex_buffer = Self::compute_vertices(
config,
&context,
metrics,
pixel_width as f32,
@ -141,13 +185,11 @@ impl RenderState {
pub fn advise_of_window_size_change(
&mut self,
config: &ConfigHandle,
metrics: &RenderMetrics,
pixel_width: usize,
pixel_height: usize,
) -> anyhow::Result<()> {
let glyph_vertex_buffer = Self::compute_vertices(
config,
&self.context,
metrics,
pixel_width as f32,
@ -233,7 +275,6 @@ impl RenderState {
/// to a changed cell when we need to repaint the screen, and then just
/// let the GPU figure out the rest.
fn compute_vertices(
config: &ConfigHandle,
context: &Rc<GliumContext>,
metrics: &RenderMetrics,
width: f32,
@ -241,58 +282,25 @@ impl RenderState {
) -> anyhow::Result<TripleVertexBuffer> {
let cell_width = metrics.cell_size.width as f32;
let cell_height = metrics.cell_size.height as f32;
let mut verts = Vec::new();
let mut indices = Vec::new();
let padding_right = super::termwindow::resize::effective_right_padding(&config, metrics);
let avail_width =
(width as usize).saturating_sub((config.window_padding.left + padding_right) as usize);
let avail_height = (height as usize)
.saturating_sub((config.window_padding.top + config.window_padding.bottom) as usize);
let num_cols = avail_width as usize / cell_width as usize;
let num_rows = avail_height as usize / cell_height as usize;
let padding_left = config.window_padding.left as f32;
let padding_top = config.window_padding.top as f32;
let num_cols = width as usize / cell_width as usize;
let num_rows = height as usize / cell_height as usize;
log::debug!(
"compute_vertices {}x{} {}x{} padding={} {}",
"compute_vertices {}x{} {}x{}",
num_cols,
num_rows,
width,
height,
padding_left,
padding_top
);
let mut quads = Quads::default();
quads.cols = num_cols;
let num_quads = num_cols * num_rows + 2 /* bg image, scroll thumb */;
let verts = vec![Vertex::default(); num_quads * VERTICES_PER_CELL];
let mut indices = vec![];
indices.reserve(num_quads * INDICES_PER_CELL);
let mut define_quad = |left, top, right, bottom| -> u32 {
// Remember starting index for this position
let idx = verts.len() as u32;
verts.push(Vertex {
// Top left
position: (left, top),
..Default::default()
});
verts.push(Vertex {
// Top Right
position: (right, top),
..Default::default()
});
verts.push(Vertex {
// Bottom Left
position: (left, bottom),
..Default::default()
});
verts.push(Vertex {
// Bottom Right
position: (right, bottom),
..Default::default()
});
for q in 0..num_quads {
let idx = (q * VERTICES_PER_CELL) as u32;
// Emit two triangles to form the glyph quad
indices.push(idx + V_TOP_LEFT as u32);
@ -302,31 +310,8 @@ impl RenderState {
indices.push(idx + V_TOP_RIGHT as u32);
indices.push(idx + V_BOT_LEFT as u32);
indices.push(idx + V_BOT_RIGHT as u32);
idx
};
// Background image fills the entire window background
quads.background_image =
define_quad(width / -2.0, height / -2.0, width / 2.0, height / 2.0) as usize;
for y in 0..=num_rows {
let y_pos = (height / -2.0) + (y as f32 * cell_height) + padding_top;
for x in 0..num_cols {
let x_pos = (width / -2.0) + (x as f32 * cell_width) + padding_left;
let idx = define_quad(x_pos, y_pos, x_pos + cell_width, y_pos + cell_height);
if x == 0 {
// build row -> vertex mapping
quads.row_starts.push(idx as usize);
}
}
}
// And a quad for the scrollbar thumb
quads.scroll_thumb = define_quad(0.0, 0.0, 0.0, 0.0) as usize;
let buffer = TripleVertexBuffer {
index: RefCell::new(0),
bufs: RefCell::new([
@ -334,13 +319,13 @@ impl RenderState {
VertexBuffer::dynamic(context, &verts)?,
VertexBuffer::dynamic(context, &verts)?,
]),
capacity: verts.len(),
capacity: verts.len() / VERTICES_PER_CELL,
indices: IndexBuffer::new(
context,
glium::index::PrimitiveType::TrianglesList,
&indices,
)?,
quads,
next_quad: RefCell::new(0),
};
Ok(buffer)

View File

@ -1,5 +1,4 @@
#![cfg_attr(feature = "cargo-clippy", allow(clippy::range_plus_one))]
use super::quad::*;
use super::renderstate::*;
use super::utilsprites::RenderMetrics;
use crate::cache::LruCache;
@ -300,7 +299,6 @@ impl TermWindow {
self.render_state = None;
match RenderState::new(
&self.config,
ctx,
&self.fonts,
&self.render_metrics,

View File

@ -218,7 +218,7 @@ impl super::TermWindow {
let start = Instant::now();
let mut vb_mut = vb.current_vb_mut();
let mut quads = vb.quads.map(&mut vb_mut);
let mut quads = vb.map(&mut vb_mut);
log::trace!("quad map elapsed {:?}", start.elapsed());
metrics::histogram!("quad.map", start.elapsed());
@ -229,12 +229,6 @@ impl super::TermWindow {
let window_is_transparent =
self.window_background.is_some() || config.window_background_opacity != 1.0;
// Pre-set the row with the whitespace glyph.
// This is here primarily because clustering/shaping can cause the line updates
// to skip setting a quad that is logically obscured by a double-wide glyph.
// If eg: scrolling the viewport causes the pair of quads to change from two
// individual cells to a single double-wide cell then we might leave the second
// one of the pair with the glyph from the prior viewport position.
let default_bg = rgbcolor_alpha_to_window_color(
palette.resolve_bg(ColorAttribute::Default),
if window_is_transparent {
@ -309,7 +303,7 @@ impl super::TermWindow {
(0., 0., color)
};
let mut quad = quads.scroll_thumb();
let mut quad = quads.allocate()?;
// Adjust the scrollbar thumb position
let top = (self.dimensions.pixel_height as f32 / -2.0) + thumb_top;
@ -335,9 +329,15 @@ impl super::TermWindow {
}
{
let mut quad = quads.background_image();
let mut quad = quads.allocate()?;
quad.set_underline(white_space);
quad.set_cursor(white_space);
quad.set_position(
self.dimensions.pixel_width as f32 / -2.,
self.dimensions.pixel_height as f32 / -2.,
self.dimensions.pixel_width as f32 / 2.,
self.dimensions.pixel_height as f32 / 2.,
);
let background_image_alpha = (config.window_background_opacity * 255.0) as u8;
let color = rgbcolor_alpha_to_window_color(palette.background, background_image_alpha);
@ -411,6 +411,7 @@ impl super::TermWindow {
pub fn call_draw(&mut self, frame: &mut glium::Frame) -> anyhow::Result<()> {
let gl_state = self.render_state.as_ref().unwrap();
let vb = &gl_state.glyph_vertex_buffer;
let (vertex_count, index_count) = vb.vertex_index_count();
let tex = gl_state.glyph_cache.borrow().atlas.texture();
let projection = euclid::Transform3D::<f32, f32, f32>::ortho(
@ -459,10 +460,12 @@ impl super::TermWindow {
foreground_text_hsb.brightness,
);
let vertices = vb.current_vb();
// Pass 1: Draw backgrounds
frame.draw(
&*vb.current_vb(),
&vb.indices,
vertices.slice(0..vertex_count).unwrap(),
vb.indices.slice(0..index_count).unwrap(),
&gl_state.background_prog,
&uniform! {
projection: projection,
@ -474,8 +477,8 @@ impl super::TermWindow {
// Pass 2: strikethrough and underline
frame.draw(
&*vb.current_vb(),
&vb.indices,
vertices.slice(0..vertex_count).unwrap(),
vb.indices.slice(0..index_count).unwrap(),
&gl_state.line_prog,
&uniform! {
projection: projection,
@ -528,8 +531,8 @@ impl super::TermWindow {
// Pass 3: Draw glyphs
frame.draw(
&*vb.current_vb(),
&vb.indices,
vertices.slice(0..vertex_count).unwrap(),
vb.indices.slice(0..index_count).unwrap(),
&gl_state.glyph_prog,
&uniform! {
projection: projection,
@ -542,8 +545,8 @@ impl super::TermWindow {
// Pass 4: Draw image attachments
frame.draw(
&*vb.current_vb(),
&vb.indices,
vertices.slice(0..vertex_count).unwrap(),
vb.indices.slice(0..index_count).unwrap(),
&gl_state.img_prog,
&uniform! {
projection: projection,
@ -567,7 +570,7 @@ impl super::TermWindow {
let gl_state = self.render_state.as_ref().unwrap();
let vb = &gl_state.glyph_vertex_buffer;
let mut vb_mut = vb.current_vb_mut();
let mut quads = vb.quads.map(&mut vb_mut);
let mut quads = vb.map(&mut vb_mut);
let config = &self.config;
let block = BlockKey::from_char(if split.direction == SplitDirection::Horizontal {
'\u{2502}'
@ -599,6 +602,8 @@ impl super::TermWindow {
} else {
Box::new((split.left..split.left + split.size).zip(std::iter::repeat(split.top)))
};
let cell_width = self.render_metrics.cell_size.width as f32;
let cell_height = self.render_metrics.cell_size.height as f32;
for (x, y) in x_y_iter {
let sprite = gl_state
.glyph_cache
@ -606,10 +611,14 @@ impl super::TermWindow {
.cached_block(block)?
.texture_coords();
let mut quad = match quads.cell(x, y + first_row_offset) {
Ok(quad) => quad,
Err(_) => break,
};
let pos_y = (self.dimensions.pixel_height as f32 / -2.)
+ (y + first_row_offset) as f32 * cell_height
+ self.config.window_padding.top as f32;
let pos_x = (self.dimensions.pixel_width as f32 / -2.)
+ x as f32 * cell_width
+ self.config.window_padding.left as f32;
let mut quad = quads.allocate()?;
quad.set_position(pos_x, pos_y, pos_x + cell_width, pos_y + cell_height);
quad.set_fg_color(foreground);
quad.set_underline_color(foreground);
@ -626,6 +635,11 @@ impl super::TermWindow {
}
pub fn paint_opengl_pass(&mut self) -> anyhow::Result<()> {
{
let gl_state = self.render_state.as_ref().unwrap();
gl_state.glyph_vertex_buffer.clear_quad_allocation();
}
let panes = self.get_panes_to_render();
if let Some(pane) = self.get_active_pane_or_overlay() {
@ -668,33 +682,11 @@ impl super::TermWindow {
let uptime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let milli_uptime = uptime.as_secs() as u128 * 1000 + uptime.subsec_millis() as u128;
// Clear the cells to basic blanks to avoid leaving artifacts behind.
// The easiest reproduction for the artifacts is to maximize the window and
// open a vim split horizontally. Backgrounding vim would leave
// the right pane with its prior contents instead of showing the
// cleared lines from the shell in the main screen.
let clear_bg = if params.line.is_reverse() {
params.foreground
} else {
params.default_bg
};
for cell_idx in 0..num_cols {
let mut quad =
match quads.cell(cell_idx + params.pos.left, params.line_idx + params.pos.top) {
Ok(quad) => quad,
Err(_) => break,
};
quad.set_bg_color(clear_bg);
quad.set_texture(params.white_space);
quad.set_image_texture(params.white_space);
quad.set_texture_adjust(0., 0., 0., 0.);
quad.set_underline(params.white_space);
quad.set_cursor(params.white_space);
quad.set_has_color(false);
quad.set_hsv(hsv);
}
let cell_width = self.render_metrics.cell_size.width as f32;
let cell_height = self.render_metrics.cell_size.height as f32;
let pos_y = (self.dimensions.pixel_height as f32 / -2.)
+ (params.line_idx + params.pos.top) as f32 * cell_height
+ self.config.window_padding.top as f32;
// Break the line into clusters of cells with the same attributes
let start = Instant::now();
@ -941,16 +933,15 @@ impl super::TermWindow {
// `left` value to be 0 when glyph_idx > 0.
slice_left = right;
let mut quad = match quads
.cell(cell_idx + params.pos.left, params.line_idx + params.pos.top)
{
Ok(quad) => quad,
Err(_) => break,
};
let mut quad = quads.allocate()?;
let pos_x = (self.dimensions.pixel_width as f32 / -2.)
+ (cell_idx + params.pos.left) as f32 * cell_width
+ self.config.window_padding.left as f32;
quad.set_position(pos_x, pos_y, pos_x + cell_width, pos_y + cell_height);
quad.set_fg_color(glyph_color);
quad.set_bg_color(bg_color);
quad.set_texture(texture_rect);
quad.set_image_texture(params.white_space);
quad.set_texture_adjust(left, top, right, bottom);
quad.set_underline(style_params.underline_tex_rect);
quad.set_underline_color(style_params.underline_color);
@ -987,19 +978,65 @@ impl super::TermWindow {
// of one of the clusters)
let right_fill_start = Instant::now();
if last_cell_idx < num_cols {
// We only need to update the cells that have the cursor or the
// selection.
let mut reverse_left = 0..0;
let mut reverse_right = last_cell_idx..num_cols;
// Render the selection beyond the end of the line
if let Some(sel_range) =
rangeset::range_intersection(&params.selection, &(last_cell_idx + 1..num_cols))
{
for cell_idx in sel_range {
if let Ok(mut quad) =
quads.cell(cell_idx + params.pos.left, params.line_idx + params.pos.top)
{
quad.set_bg_color(params.selection_bg);
quad.set_fg_color(params.selection_fg);
quad.set_underline_color(params.selection_fg);
}
// revise the reverse video range
reverse_left = last_cell_idx..sel_range.start;
reverse_right = sel_range.end..num_cols;
let mut quad = quads.allocate()?;
let pos_x = (self.dimensions.pixel_width as f32 / -2.)
+ (sel_range.start + params.pos.left) as f32 * cell_width
+ self.config.window_padding.left as f32;
quad.set_position(
pos_x,
pos_y,
pos_x + (sel_range.end - sel_range.start) as f32 * cell_width,
pos_y + cell_height,
);
quad.set_bg_color(params.selection_bg);
quad.set_fg_color(params.selection_fg);
quad.set_image_texture(params.white_space);
quad.set_texture_adjust(0., 0., 0., 0.);
quad.set_texture(params.white_space);
quad.set_underline_color(params.selection_fg);
quad.set_underline(params.white_space);
quad.set_cursor(params.white_space);
quad.set_has_color(false);
quad.set_hsv(hsv);
}
if params.line.is_reverse() {
for r in [reverse_left, reverse_right] {
let mut quad = quads.allocate()?;
let pos_x = (self.dimensions.pixel_width as f32 / -2.)
+ (r.start + params.pos.left) as f32 * cell_width
+ self.config.window_padding.left as f32;
quad.set_position(
pos_x,
pos_y,
pos_x + (r.end - r.start) as f32 * cell_width,
pos_y + cell_height,
);
quad.set_bg_color(params.foreground); // reverse video
quad.set_fg_color(params.default_bg);
quad.set_image_texture(params.white_space);
quad.set_texture_adjust(0., 0., 0., 0.);
quad.set_texture(params.white_space);
quad.set_underline_color(params.selection_fg);
quad.set_underline(params.white_space);
quad.set_cursor(params.white_space);
quad.set_has_color(false);
quad.set_hsv(hsv);
}
}
@ -1027,24 +1064,32 @@ impl super::TermWindow {
cursor_bg: params.cursor_bg,
});
if let Ok(mut quad) = quads.cell(
params.cursor.x + params.pos.left,
params.line_idx + params.pos.top,
) {
quad.set_bg_color(bg_color);
quad.set_fg_color(glyph_color);
quad.set_cursor(
gl_state
.util_sprites
.cursor_sprite(cursor_shape)
.texture_coords(),
);
quad.set_cursor_color(if self.config.force_reverse_video_cursor {
bg_color
} else {
params.cursor_border_color
});
}
let mut quad = quads.allocate()?;
let pos_x = (self.dimensions.pixel_width as f32 / -2.)
+ (params.cursor.x + params.pos.left) as f32 * cell_width
+ self.config.window_padding.left as f32;
quad.set_position(pos_x, pos_y, pos_x + cell_width, pos_y + cell_height);
quad.set_texture(params.white_space);
quad.set_image_texture(params.white_space);
quad.set_texture_adjust(0., 0., 0., 0.);
quad.set_underline(params.white_space);
quad.set_has_color(false);
quad.set_hsv(hsv);
quad.set_bg_color(bg_color);
quad.set_fg_color(glyph_color);
quad.set_cursor(
gl_state
.util_sprites
.cursor_sprite(cursor_shape)
.texture_coords(),
);
quad.set_cursor_color(if self.config.force_reverse_video_cursor {
bg_color
} else {
params.cursor_border_color
});
}
}
metrics::histogram!(
@ -1080,17 +1125,22 @@ impl super::TermWindow {
.cached_block(block)?
.texture_coords();
let mut quad =
match quads.cell(cell_idx + params.pos.left, params.line_idx + params.pos.top) {
Ok(quad) => quad,
Err(_) => return Ok(()),
};
let mut quad = quads.allocate()?;
let cell_width = self.render_metrics.cell_size.width as f32;
let cell_height = self.render_metrics.cell_size.height as f32;
let pos_y = (self.dimensions.pixel_height as f32 / -2.)
+ (params.line_idx + params.pos.top) as f32 * cell_height
+ self.config.window_padding.top as f32;
let pos_x = (self.dimensions.pixel_width as f32 / -2.)
+ (cell_idx + params.pos.left) as f32 * cell_width
+ self.config.window_padding.left as f32;
quad.set_position(pos_x, pos_y, pos_x + cell_width, pos_y + cell_height);
quad.set_hsv(hsv);
quad.set_fg_color(glyph_color);
quad.set_underline_color(underline_color);
quad.set_bg_color(bg_color);
quad.set_texture(sprite);
quad.set_image_texture(params.white_space);
quad.set_texture_adjust(0., 0., 0., 0.);
quad.set_underline(params.white_space);
quad.set_has_color(false);
@ -1164,12 +1214,18 @@ impl super::TermWindow {
let texture_rect = TextureRect::new(origin, size);
let mut quad =
match quads.cell(cell_idx + params.pos.left, params.line_idx + params.pos.top) {
Ok(quad) => quad,
Err(_) => return Ok(()),
};
let mut quad = quads.allocate()?;
let cell_width = self.render_metrics.cell_size.width as f32;
let cell_height = self.render_metrics.cell_size.height as f32;
let pos_y = (self.dimensions.pixel_height as f32 / -2.)
+ (params.line_idx + params.pos.top) as f32 * cell_height
+ self.config.window_padding.top as f32;
let pos_x = (self.dimensions.pixel_width as f32 / -2.)
+ (cell_idx + params.pos.left) as f32 * cell_width
+ self.config.window_padding.left as f32;
quad.set_position(pos_x, pos_y, pos_x + cell_width, pos_y + cell_height);
quad.set_hsv(hsv);
quad.set_fg_color(glyph_color);
quad.set_underline_color(underline_color);

View File

@ -145,7 +145,6 @@ impl super::TermWindow {
if let Some(render_state) = self.render_state.as_mut() {
if let Err(err) = render_state.advise_of_window_size_change(
&config,
&self.render_metrics,
dimensions.pixel_width,
dimensions.pixel_height,