mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 13:52:55 +03:00
opengl: make it easier to track quads
The offset math around the scroll thumb made me uncomfortable so this commit introduces a struct to keep track of the vertex indices and make it easier to recall them later.
This commit is contained in:
parent
68a2d9f159
commit
fc6d80af0e
@ -3,7 +3,9 @@
|
||||
#![allow(clippy::unneeded_field_pattern)]
|
||||
|
||||
use ::window::bitmaps::TextureRect;
|
||||
use ::window::glium::VertexBuffer;
|
||||
use ::window::*;
|
||||
use std::cell::RefMut;
|
||||
|
||||
/// Each cell is composed of two triangles built from 4 vertices.
|
||||
/// The buffer is organized row by row.
|
||||
@ -44,20 +46,65 @@ 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 struct MappedQuads<'a> {
|
||||
mapping: glium::buffer::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],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Quads {
|
||||
pub fn map<'a>(&self, vb: &'a mut RefMut<VertexBuffer<Vertex>>) -> MappedQuads<'a> {
|
||||
let mapping = vb.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],
|
||||
}
|
||||
|
||||
impl<'a> Quad<'a> {
|
||||
/// Returns a reference to the Quad for the given cell column index
|
||||
/// into the set of vertices for a line.
|
||||
pub fn for_cell(cell_idx: usize, vertices: &'a mut [Vertex]) -> Self {
|
||||
let vert_idx = cell_idx * VERTICES_PER_CELL;
|
||||
let vert = &mut vertices[vert_idx..vert_idx + VERTICES_PER_CELL];
|
||||
Self { vert }
|
||||
}
|
||||
|
||||
/// Assign the texture coordinates
|
||||
pub fn set_texture(&mut self, coords: TextureRect) {
|
||||
self.vert[V_TOP_LEFT].tex = (coords.min_x(), coords.min_y());
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::glyphcache::{CachedGlyph, GlyphCache};
|
||||
use super::quad::*;
|
||||
use super::utilsprites::{RenderMetrics, UtilSprites};
|
||||
use crate::config::{configuration, TextStyle};
|
||||
use crate::font::{FontConfiguration, GlyphInfo};
|
||||
@ -11,8 +12,6 @@ use anyhow::{anyhow, bail};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::quad::*;
|
||||
|
||||
pub struct SoftwareRenderState {
|
||||
pub glyph_cache: RefCell<GlyphCache<ImageTexture>>,
|
||||
pub util_sprites: UtilSprites<ImageTexture>,
|
||||
@ -40,6 +39,7 @@ pub struct OpenGLRenderState {
|
||||
pub program: glium::Program,
|
||||
pub glyph_vertex_buffer: RefCell<VertexBuffer<Vertex>>,
|
||||
pub glyph_index_buffer: IndexBuffer<u32>,
|
||||
pub quads: Quads,
|
||||
}
|
||||
|
||||
impl OpenGLRenderState {
|
||||
@ -80,7 +80,7 @@ impl OpenGLRenderState {
|
||||
let program =
|
||||
program.ok_or_else(|| anyhow!("Failed to compile shaders: {}", errors.join("\n")))?;
|
||||
|
||||
let (glyph_vertex_buffer, glyph_index_buffer) =
|
||||
let (glyph_vertex_buffer, glyph_index_buffer, quads) =
|
||||
Self::compute_vertices(&context, metrics, pixel_width as f32, pixel_height as f32)?;
|
||||
|
||||
Ok(Self {
|
||||
@ -90,6 +90,7 @@ impl OpenGLRenderState {
|
||||
program,
|
||||
glyph_vertex_buffer: RefCell::new(glyph_vertex_buffer),
|
||||
glyph_index_buffer,
|
||||
quads,
|
||||
})
|
||||
}
|
||||
|
||||
@ -99,7 +100,7 @@ impl OpenGLRenderState {
|
||||
pixel_width: usize,
|
||||
pixel_height: usize,
|
||||
) -> anyhow::Result<()> {
|
||||
let (glyph_vertex_buffer, glyph_index_buffer) = Self::compute_vertices(
|
||||
let (glyph_vertex_buffer, glyph_index_buffer, quads) = Self::compute_vertices(
|
||||
&self.context,
|
||||
metrics,
|
||||
pixel_width as f32,
|
||||
@ -108,6 +109,7 @@ impl OpenGLRenderState {
|
||||
|
||||
*self.glyph_vertex_buffer.borrow_mut() = glyph_vertex_buffer;
|
||||
self.glyph_index_buffer = glyph_index_buffer;
|
||||
self.quads = quads;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -130,7 +132,7 @@ impl OpenGLRenderState {
|
||||
metrics: &RenderMetrics,
|
||||
width: f32,
|
||||
height: f32,
|
||||
) -> anyhow::Result<(VertexBuffer<Vertex>, IndexBuffer<u32>)> {
|
||||
) -> anyhow::Result<(VertexBuffer<Vertex>, IndexBuffer<u32>, Quads)> {
|
||||
let cell_width = metrics.cell_size.width as f32;
|
||||
let cell_height = metrics.cell_size.height as f32;
|
||||
let mut verts = Vec::new();
|
||||
@ -159,72 +161,31 @@ impl OpenGLRenderState {
|
||||
padding_top
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
// Remember starting index for this position
|
||||
let idx = verts.len() as u32;
|
||||
verts.push(Vertex {
|
||||
// Top left
|
||||
position: (x_pos, y_pos),
|
||||
..Default::default()
|
||||
});
|
||||
verts.push(Vertex {
|
||||
// Top Right
|
||||
position: (x_pos + cell_width, y_pos),
|
||||
..Default::default()
|
||||
});
|
||||
verts.push(Vertex {
|
||||
// Bottom Left
|
||||
position: (x_pos, y_pos + cell_height),
|
||||
..Default::default()
|
||||
});
|
||||
verts.push(Vertex {
|
||||
// Bottom Right
|
||||
position: (x_pos + cell_width, y_pos + cell_height),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
// Emit two triangles to form the glyph quad
|
||||
indices.push(idx + V_TOP_LEFT as u32);
|
||||
indices.push(idx + V_TOP_RIGHT as u32);
|
||||
indices.push(idx + V_BOT_LEFT as u32);
|
||||
|
||||
indices.push(idx + V_TOP_RIGHT as u32);
|
||||
indices.push(idx + V_BOT_LEFT as u32);
|
||||
indices.push(idx + V_BOT_RIGHT as u32);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// And a quad for the scrollbar thumb
|
||||
let x_pos = (width / 2.0) - cell_width;
|
||||
let y_pos = (height / -2.0) + padding_top;
|
||||
let thumb_width = cell_width;
|
||||
let thumb_height = height;
|
||||
let mut quads = Quads::default();
|
||||
quads.cols = num_cols;
|
||||
|
||||
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: (x_pos, thumb_width),
|
||||
position: (left, top),
|
||||
..Default::default()
|
||||
});
|
||||
verts.push(Vertex {
|
||||
// Top Right
|
||||
position: (x_pos + thumb_width, y_pos),
|
||||
position: (right, top),
|
||||
..Default::default()
|
||||
});
|
||||
verts.push(Vertex {
|
||||
// Bottom Left
|
||||
position: (x_pos, y_pos + thumb_height),
|
||||
position: (left, bottom),
|
||||
..Default::default()
|
||||
});
|
||||
verts.push(Vertex {
|
||||
// Bottom Right
|
||||
position: (x_pos + thumb_width, y_pos + thumb_height),
|
||||
position: (right, bottom),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
@ -236,6 +197,33 @@ impl OpenGLRenderState {
|
||||
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
|
||||
};
|
||||
|
||||
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
|
||||
let x_pos = (width / 2.0) - cell_width;
|
||||
let y_pos = (height / -2.0) + padding_top;
|
||||
let thumb_width = cell_width;
|
||||
let thumb_height = height;
|
||||
|
||||
quads.scroll_thumb =
|
||||
define_quad(x_pos, y_pos, x_pos + thumb_width, y_pos + thumb_height) as usize;
|
||||
}
|
||||
|
||||
Ok((
|
||||
@ -245,6 +233,7 @@ impl OpenGLRenderState {
|
||||
glium::index::PrimitiveType::TrianglesList,
|
||||
&indices,
|
||||
)?,
|
||||
quads,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -1403,6 +1403,10 @@ impl TermWindow {
|
||||
}
|
||||
};
|
||||
|
||||
let gl_state = self.render_state.opengl();
|
||||
let mut vb = gl_state.glyph_vertex_buffer.borrow_mut();
|
||||
let mut quads = gl_state.quads.map(&mut vb);
|
||||
|
||||
if self.show_tab_bar {
|
||||
self.render_screen_line_opengl(
|
||||
0,
|
||||
@ -1411,6 +1415,7 @@ impl TermWindow {
|
||||
&cursor,
|
||||
&*term,
|
||||
&palette,
|
||||
&mut quads,
|
||||
)?;
|
||||
}
|
||||
|
||||
@ -1419,13 +1424,7 @@ impl TermWindow {
|
||||
let thumb_top = info.top as f32;
|
||||
let thumb_size = info.height as f32;
|
||||
|
||||
let gl_state = self.render_state.opengl();
|
||||
|
||||
// We reserved the final quad in the vertex buffer as the scrollbar
|
||||
let mut vb = gl_state.glyph_vertex_buffer.borrow_mut();
|
||||
let num_vert = vb.len() - VERTICES_PER_CELL;
|
||||
let mut vertices = &mut vb.slice_mut(num_vert..).unwrap().map();
|
||||
let mut quad = Quad::for_cell(0, &mut vertices);
|
||||
let mut quad = quads.scroll_thumb();
|
||||
|
||||
// Adjust the scrollbar thumb position
|
||||
let top = (self.dimensions.pixel_height as f32 / -2.0) + thumb_top;
|
||||
@ -1454,11 +1453,11 @@ impl TermWindow {
|
||||
&cursor,
|
||||
&*term,
|
||||
&palette,
|
||||
&mut quads,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
let gl_state = self.render_state.opengl();
|
||||
let tex = gl_state.glyph_cache.borrow().atlas.texture();
|
||||
let projection = euclid::Transform3D::<f32, f32, f32>::ortho(
|
||||
-(self.dimensions.pixel_width as f32) / 2.0,
|
||||
@ -1475,9 +1474,11 @@ impl TermWindow {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
drop(quads);
|
||||
|
||||
// Pass 1: Draw backgrounds, strikethrough and underline
|
||||
frame.draw(
|
||||
&*gl_state.glyph_vertex_buffer.borrow(),
|
||||
&*vb,
|
||||
&gl_state.glyph_index_buffer,
|
||||
&gl_state.program,
|
||||
&uniform! {
|
||||
@ -1490,7 +1491,7 @@ impl TermWindow {
|
||||
|
||||
// Pass 2: Draw glyphs
|
||||
frame.draw(
|
||||
&*gl_state.glyph_vertex_buffer.borrow(),
|
||||
&*vb,
|
||||
&gl_state.glyph_index_buffer,
|
||||
&gl_state.program,
|
||||
&uniform! {
|
||||
@ -1518,27 +1519,11 @@ impl TermWindow {
|
||||
cursor: &CursorPosition,
|
||||
terminal: &dyn Renderable,
|
||||
palette: &ColorPalette,
|
||||
quads: &mut MappedQuads,
|
||||
) -> anyhow::Result<()> {
|
||||
let gl_state = self.render_state.opengl();
|
||||
|
||||
let (_num_rows, num_cols) = terminal.physical_dimensions();
|
||||
let mut vb = gl_state.glyph_vertex_buffer.borrow_mut();
|
||||
let mut vertices = {
|
||||
let per_line = num_cols * VERTICES_PER_CELL;
|
||||
let start_pos = line_idx * per_line;
|
||||
vb.slice_mut(start_pos..start_pos + per_line)
|
||||
.ok_or_else(|| {
|
||||
anyhow!(
|
||||
"we're confused about the screen size; \
|
||||
line_idx={} start_pos={} per_line={} num_cols={}",
|
||||
line_idx,
|
||||
start_pos,
|
||||
per_line,
|
||||
num_cols
|
||||
)
|
||||
})?
|
||||
.map()
|
||||
};
|
||||
|
||||
let current_highlight = terminal.current_highlight();
|
||||
let cursor_border_color = rgbcolor_to_window_color(palette.cursor_border);
|
||||
@ -1673,7 +1658,7 @@ impl TermWindow {
|
||||
|
||||
let texture_rect = sprite.texture.to_texture_coords(coords);
|
||||
|
||||
let mut quad = Quad::for_cell(cell_idx, &mut vertices);
|
||||
let mut quad = quads.cell(cell_idx, line_idx)?;
|
||||
|
||||
quad.set_fg_color(glyph_color);
|
||||
quad.set_bg_color(bg_color);
|
||||
@ -1715,7 +1700,7 @@ impl TermWindow {
|
||||
let right = pixel_rect.size.width as f32 + left
|
||||
- self.render_metrics.cell_size.width as f32;
|
||||
|
||||
let mut quad = Quad::for_cell(cell_idx, &mut vertices);
|
||||
let mut quad = quads.cell(cell_idx, line_idx)?;
|
||||
|
||||
quad.set_fg_color(glyph_color);
|
||||
quad.set_bg_color(bg_color);
|
||||
@ -1757,7 +1742,7 @@ impl TermWindow {
|
||||
palette,
|
||||
);
|
||||
|
||||
let mut quad = Quad::for_cell(cell_idx, &mut vertices);
|
||||
let mut quad = quads.cell(cell_idx, line_idx)?;
|
||||
|
||||
quad.set_bg_color(bg_color);
|
||||
quad.set_fg_color(glyph_color);
|
||||
|
Loading…
Reference in New Issue
Block a user