1
0
Fork 0
forked from wry/wry

text: re-use textures if possible

This commit is contained in:
Julian Orth 2023-11-05 15:54:19 +01:00
parent bf90204db6
commit a04870388f
10 changed files with 153 additions and 45 deletions

View file

@ -410,6 +410,7 @@ fn create_dummy_output(state: &Rc<State>) {
desired_output: CloneCell::new(dummy_output.global.output_id.clone()), desired_output: CloneCell::new(dummy_output.global.output_id.clone()),
jay_workspaces: Default::default(), jay_workspaces: Default::default(),
capture: Cell::new(false), capture: Cell::new(false),
title_texture: Cell::new(None),
}); });
dummy_workspace.output_link.set(Some( dummy_workspace.output_link.set(Some(
dummy_output.workspaces.add_last(dummy_workspace.clone()), dummy_output.workspaces.add_last(dummy_workspace.clone()),

View file

@ -4,12 +4,12 @@ use {
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
format::ARGB8888, format::ARGB8888,
gfx_api::{GfxContext, GfxFramebuffer, GfxTexture}, gfx_api::{GfxContext, GfxFramebuffer},
ifs::zwlr_layer_shell_v1::OVERLAY, ifs::zwlr_layer_shell_v1::OVERLAY,
portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat}, portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat},
renderer::renderer_base::RendererBase, renderer::renderer_base::RendererBase,
scale::Scale, scale::Scale,
text::{self, TextMeasurement}, text::{self, TextMeasurement, TextTexture},
theme::Color, theme::Color,
utils::{ utils::{
asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap, asyncevent::AsyncEvent, clonecell::CloneCell, copyhashmap::CopyHashMap,
@ -118,7 +118,7 @@ pub struct Button {
pub bg_hover_color: Cell<Color>, pub bg_hover_color: Cell<Color>,
pub text: RefCell<String>, pub text: RefCell<String>,
pub font: RefCell<Cow<'static, str>>, pub font: RefCell<Cow<'static, str>>,
pub tex: CloneCell<Option<Rc<dyn GfxTexture>>>, pub tex: CloneCell<Option<TextTexture>>,
pub owner: CloneCell<Option<Rc<dyn ButtonOwner>>>, pub owner: CloneCell<Option<Rc<dyn ButtonOwner>>>,
} }
@ -162,10 +162,12 @@ impl GuiElement for Button {
_max_width: f32, _max_width: f32,
_max_height: f32, _max_height: f32,
) -> (f32, f32) { ) -> (f32, f32) {
let old_tex = self.tex.take();
let font = self.font.borrow_mut(); let font = self.font.borrow_mut();
let text = self.text.borrow_mut(); let text = self.text.borrow_mut();
let tex = text::render_fitting2( let tex = text::render_fitting2(
ctx, ctx,
old_tex,
None, None,
&font, &font,
&text, &text,
@ -213,7 +215,7 @@ impl GuiElement for Button {
if let Some(tex) = self.tex.get() { if let Some(tex) = self.tex.get() {
let (tx, ty) = r.scale_point_f(x1 + self.tex_off_x.get(), y1 + self.tex_off_y.get()); let (tx, ty) = r.scale_point_f(x1 + self.tex_off_x.get(), y1 + self.tex_off_y.get());
r.render_texture( r.render_texture(
&tex, &tex.texture,
tx.round() as _, tx.round() as _,
ty.round() as _, ty.round() as _,
ARGB8888, ARGB8888,
@ -260,7 +262,7 @@ pub struct Label {
pub data: GuiElementData, pub data: GuiElementData,
pub font: RefCell<Cow<'static, str>>, pub font: RefCell<Cow<'static, str>>,
pub text: RefCell<String>, pub text: RefCell<String>,
pub tex: CloneCell<Option<Rc<dyn GfxTexture>>>, pub tex: CloneCell<Option<TextTexture>>,
} }
impl Default for Label { impl Default for Label {
@ -286,10 +288,12 @@ impl GuiElement for Label {
_max_width: f32, _max_width: f32,
_max_height: f32, _max_height: f32,
) -> (f32, f32) { ) -> (f32, f32) {
let old_tex = self.tex.take();
let text = self.text.borrow_mut(); let text = self.text.borrow_mut();
let font = self.font.borrow_mut(); let font = self.font.borrow_mut();
let tex = text::render_fitting2( let tex = text::render_fitting2(
ctx, ctx,
old_tex,
None, None,
&font, &font,
&text, &text,
@ -300,7 +304,7 @@ impl GuiElement for Label {
) )
.ok(); .ok();
let (tex, width, height) = match tex { let (tex, width, height) = match tex {
Some((t, _)) => (Some(t.clone()), t.width(), t.height()), Some((t, _)) => (Some(t.clone()), t.texture.width(), t.texture.height()),
_ => (None, 0, 0), _ => (None, 0, 0),
}; };
self.tex.set(tex); self.tex.set(tex);
@ -311,7 +315,7 @@ impl GuiElement for Label {
if let Some(tex) = self.tex.get() { if let Some(tex) = self.tex.get() {
let (tx, ty) = r.scale_point_f(x, y); let (tx, ty) = r.scale_point_f(x, y);
r.render_texture( r.render_texture(
&tex, &tex.texture,
tx.round() as _, tx.round() as _,
ty.round() as _, ty.round() as _,
ARGB8888, ARGB8888,

View file

@ -155,7 +155,7 @@ impl Renderer<'_> {
if let Some(status) = &rd.status { if let Some(status) = &rd.status {
let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y); let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y);
self.base.render_texture( self.base.render_texture(
&status.tex, &status.tex.texture,
x, x,
y, y,
ARGB8888, ARGB8888,
@ -197,10 +197,10 @@ impl Renderer<'_> {
&Color::from_rgba_straight(20, 20, 20, 255), &Color::from_rgba_straight(20, 20, 20, 255),
); );
if let Some(tex) = placeholder.textures.get(&self.base.scale) { if let Some(tex) = placeholder.textures.get(&self.base.scale) {
let x = x + (pos.width() - tex.width()) / 2; let x = x + (pos.width() - tex.texture.width()) / 2;
let y = y + (pos.height() - tex.height()) / 2; let y = y + (pos.height() - tex.texture.height()) / 2;
self.base.render_texture( self.base.render_texture(
&tex, &tex.texture,
x, x,
y, y,
ARGB8888, ARGB8888,
@ -237,7 +237,7 @@ impl Renderer<'_> {
for title in titles { for title in titles {
let (x, y) = self.base.scale_point(x + title.x, y + title.y); let (x, y) = self.base.scale_point(x + title.x, y + title.y);
self.base.render_texture( self.base.render_texture(
&title.tex, &title.tex.texture,
x, x,
y, y,
ARGB8888, ARGB8888,
@ -439,7 +439,7 @@ impl Renderer<'_> {
if let Some(title) = floating.title_textures.get(&self.base.scale) { if let Some(title) = floating.title_textures.get(&self.base.scale) {
let (x, y) = self.base.scale_point(x + bw, y + bw); let (x, y) = self.base.scale_point(x + bw, y + bw);
self.base.render_texture( self.base.render_texture(
&title, &title.texture,
x, x,
y, y,
ARGB8888, ARGB8888,

View file

@ -237,6 +237,7 @@ impl DrmDevData {
struct UpdateTextTexturesVisitor; struct UpdateTextTexturesVisitor;
impl NodeVisitorBase for UpdateTextTexturesVisitor { impl NodeVisitorBase for UpdateTextTexturesVisitor {
fn visit_container(&mut self, node: &Rc<ContainerNode>) { fn visit_container(&mut self, node: &Rc<ContainerNode>) {
node.children.iter().for_each(|c| c.title_tex.clear());
node.schedule_compute_render_data(); node.schedule_compute_render_data();
node.node_visit_children(self); node.node_visit_children(self);
} }
@ -245,10 +246,12 @@ impl NodeVisitorBase for UpdateTextTexturesVisitor {
node.node_visit_children(self); node.node_visit_children(self);
} }
fn visit_float(&mut self, node: &Rc<FloatNode>) { fn visit_float(&mut self, node: &Rc<FloatNode>) {
node.title_textures.clear();
node.schedule_render_titles(); node.schedule_render_titles();
node.node_visit_children(self); node.node_visit_children(self);
} }
fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) { fn visit_placeholder(&mut self, node: &Rc<PlaceholderNode>) {
node.textures.clear();
node.update_texture(); node.update_texture();
node.node_visit_children(self); node.node_visit_children(self);
} }
@ -339,6 +342,11 @@ impl State {
impl NodeVisitorBase for Walker { impl NodeVisitorBase for Walker {
fn visit_container(&mut self, node: &Rc<ContainerNode>) { fn visit_container(&mut self, node: &Rc<ContainerNode>) {
node.render_data.borrow_mut().titles.clear(); node.render_data.borrow_mut().titles.clear();
node.children.iter().for_each(|c| c.title_tex.clear());
node.node_visit_children(self);
}
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
node.title_texture.set(None);
node.node_visit_children(self); node.node_visit_children(self);
} }
fn visit_output(&mut self, node: &Rc<OutputNode>) { fn visit_output(&mut self, node: &Rc<OutputNode>) {

View file

@ -11,8 +11,13 @@ use {
}, },
rect::Rect, rect::Rect,
theme::Color, theme::Color,
utils::clonecell::UnsafeCellCloneSafe,
},
std::{
borrow::Cow,
ops::{Deref, Neg},
rc::Rc,
}, },
std::{ops::Neg, rc::Rc},
thiserror::Error, thiserror::Error,
}; };
@ -32,6 +37,47 @@ pub enum TextError {
ImageData(#[source] PangoError), ImageData(#[source] PangoError),
} }
#[derive(PartialEq)]
struct Config<'a> {
x: i32,
y: Option<i32>,
width: i32,
height: i32,
padding: i32,
font: Cow<'a, str>,
text: Cow<'a, str>,
color: Color,
ellipsize: bool,
markup: bool,
scale: Option<f64>,
}
impl<'a> Config<'a> {
fn to_static(self) -> Config<'static> {
Config {
x: self.x,
y: self.y,
width: self.width,
height: self.height,
padding: self.padding,
font: Cow::Owned(self.font.into_owned()),
text: Cow::Owned(self.text.into_owned()),
color: self.color,
ellipsize: self.ellipsize,
markup: self.markup,
scale: self.scale,
}
}
}
#[derive(Clone)]
pub struct TextTexture {
config: Rc<Config<'static>>,
pub texture: Rc<dyn GfxTexture>,
}
unsafe impl UnsafeCellCloneSafe for TextTexture {}
struct Data { struct Data {
image: Rc<CairoImageSurface>, image: Rc<CairoImageSurface>,
cctx: Rc<CairoContext>, cctx: Rc<CairoContext>,
@ -95,20 +141,22 @@ pub fn measure(
pub fn render( pub fn render(
ctx: &Rc<dyn GfxContext>, ctx: &Rc<dyn GfxContext>,
old: Option<TextTexture>,
width: i32, width: i32,
height: i32, height: i32,
font: &str, font: &str,
text: &str, text: &str,
color: Color, color: Color,
scale: Option<f64>, scale: Option<f64>,
) -> Result<Rc<dyn GfxTexture>, TextError> { ) -> Result<TextTexture, TextError> {
render2( render2(
ctx, 1, None, width, height, 1, font, text, color, true, false, scale, ctx, old, 1, None, width, height, 1, font, text, color, true, false, scale,
) )
} }
fn render2( fn render2(
ctx: &Rc<dyn GfxContext>, ctx: &Rc<dyn GfxContext>,
old: Option<TextTexture>,
x: i32, x: i32,
y: Option<i32>, y: Option<i32>,
width: i32, width: i32,
@ -120,7 +168,25 @@ fn render2(
ellipsize: bool, ellipsize: bool,
markup: bool, markup: bool,
scale: Option<f64>, scale: Option<f64>,
) -> Result<Rc<dyn GfxTexture>, TextError> { ) -> Result<TextTexture, TextError> {
let config = Config {
x,
y,
width,
height,
padding,
font: Cow::Borrowed(font),
text: Cow::Borrowed(text),
color,
ellipsize,
markup,
scale,
};
if let Some(old2) = &old {
if old2.config.deref() == &config {
return Ok(old.unwrap());
}
}
let data = create_data(font, width, height, scale)?; let data = create_data(font, width, height, scale)?;
if ellipsize { if ellipsize {
data.layout data.layout
@ -148,21 +214,25 @@ fn render2(
.clone() .clone()
.shmem_texture(bytes, ARGB8888, width, height, data.image.stride()) .shmem_texture(bytes, ARGB8888, width, height, data.image.stride())
{ {
Ok(t) => Ok(t), Ok(t) => Ok(TextTexture {
config: Rc::new(config.to_static()),
texture: t,
}),
Err(e) => Err(TextError::RenderError(e)), Err(e) => Err(TextError::RenderError(e)),
} }
} }
pub fn render_fitting( pub fn render_fitting(
ctx: &Rc<dyn GfxContext>, ctx: &Rc<dyn GfxContext>,
old: Option<TextTexture>,
height: Option<i32>, height: Option<i32>,
font: &str, font: &str,
text: &str, text: &str,
color: Color, color: Color,
markup: bool, markup: bool,
scale: Option<f64>, scale: Option<f64>,
) -> Result<Rc<dyn GfxTexture>, TextError> { ) -> Result<TextTexture, TextError> {
render_fitting2(ctx, height, font, text, color, markup, scale, false).map(|(a, _)| a) render_fitting2(ctx, old, height, font, text, color, markup, scale, false).map(|(a, _)| a)
} }
#[derive(Debug, Copy, Clone, Default)] #[derive(Debug, Copy, Clone, Default)]
@ -174,6 +244,7 @@ pub struct TextMeasurement {
pub fn render_fitting2( pub fn render_fitting2(
ctx: &Rc<dyn GfxContext>, ctx: &Rc<dyn GfxContext>,
old: Option<TextTexture>,
height: Option<i32>, height: Option<i32>,
font: &str, font: &str,
text: &str, text: &str,
@ -181,7 +252,7 @@ pub fn render_fitting2(
markup: bool, markup: bool,
scale: Option<f64>, scale: Option<f64>,
include_measurements: bool, include_measurements: bool,
) -> Result<(Rc<dyn GfxTexture>, TextMeasurement), TextError> { ) -> Result<(TextTexture, TextMeasurement), TextError> {
let measurement = measure(font, text, markup, scale, include_measurements)?; let measurement = measure(font, text, markup, scale, include_measurements)?;
let y = match height { let y = match height {
Some(_) => None, Some(_) => None,
@ -189,6 +260,7 @@ pub fn render_fitting2(
}; };
let res = render2( let res = render2(
ctx, ctx,
old,
measurement.ink_rect.x1().neg(), measurement.ink_rect.x1().neg(),
y, y,
measurement.ink_rect.width(), measurement.ink_rect.width(),

View file

@ -3,7 +3,6 @@ use {
backend::KeyState, backend::KeyState,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_api::GfxTexture,
ifs::wl_seat::{ ifs::wl_seat::{
collect_kb_foci, collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId, collect_kb_foci, collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId,
WlSeatGlobal, BTN_LEFT, WlSeatGlobal, BTN_LEFT,
@ -12,7 +11,7 @@ use {
renderer::Renderer, renderer::Renderer,
scale::Scale, scale::Scale,
state::State, state::State,
text, text::{self, TextTexture},
tree::{ tree::{
walker::NodeVisitor, ContainingNode, Direction, FindTreeResult, FoundNode, Node, walker::NodeVisitor, ContainingNode, Direction, FindTreeResult, FoundNode, Node,
NodeId, ToplevelData, ToplevelNode, WorkspaceNode, NodeId, ToplevelData, ToplevelNode, WorkspaceNode,
@ -24,7 +23,7 @@ use {
numcell::NumCell, numcell::NumCell,
rc_eq::rc_eq, rc_eq::rc_eq,
scroller::Scroller, scroller::Scroller,
smallmap::SmallMapMut, smallmap::{SmallMap, SmallMapMut},
}, },
}, },
ahash::AHashMap, ahash::AHashMap,
@ -77,7 +76,7 @@ tree_id!(ContainerNodeId);
pub struct ContainerTitle { pub struct ContainerTitle {
pub x: i32, pub x: i32,
pub y: i32, pub y: i32,
pub tex: Rc<dyn GfxTexture>, pub tex: TextTexture,
} }
#[derive(Default)] #[derive(Default)]
@ -128,6 +127,7 @@ pub struct ContainerChild {
pub node: Rc<dyn ToplevelNode>, pub node: Rc<dyn ToplevelNode>,
pub active: Cell<bool>, pub active: Cell<bool>,
title: RefCell<String>, title: RefCell<String>,
pub title_tex: SmallMap<Scale, TextTexture, 2>,
pub title_rect: Cell<Rect>, pub title_rect: Cell<Rect>,
focus_history: Cell<Option<LinkedNode<NodeRef<ContainerChild>>>>, focus_history: Cell<Option<LinkedNode<NodeRef<ContainerChild>>>>,
@ -182,6 +182,7 @@ impl ContainerNode {
content: Default::default(), content: Default::default(),
factor: Cell::new(1.0), factor: Cell::new(1.0),
title: Default::default(), title: Default::default(),
title_tex: Default::default(),
title_rect: Default::default(), title_rect: Default::default(),
focus_history: Default::default(), focus_history: Default::default(),
}), }),
@ -289,6 +290,7 @@ impl ContainerNode {
content: Default::default(), content: Default::default(),
factor: Default::default(), factor: Default::default(),
title: Default::default(), title: Default::default(),
title_tex: Default::default(),
title_rect: Default::default(), title_rect: Default::default(),
focus_history: Default::default(), focus_history: Default::default(),
}); });
@ -678,6 +680,7 @@ impl ContainerNode {
} }
let title = child.title.borrow_mut(); let title = child.title.borrow_mut();
for (scale, _) in scales.iter() { for (scale, _) in scales.iter() {
let old_tex = child.title_tex.remove(scale);
let titles = rd.titles.get_or_default_mut(*scale); let titles = rd.titles.get_or_default_mut(*scale);
'render_title: { 'render_title: {
let mut th = th; let mut th = th;
@ -693,12 +696,24 @@ impl ContainerNode {
break 'render_title; break 'render_title;
} }
if let Some(ctx) = &ctx { if let Some(ctx) = &ctx {
match text::render(ctx, width, th, &font, title.deref(), color, scalef) { match text::render(
Ok(t) => titles.push(ContainerTitle { ctx,
x: rect.x1(), old_tex,
y: rect.y1(), width,
tex: t, th,
}), &font,
title.deref(),
color,
scalef,
) {
Ok(t) => {
child.title_tex.insert(*scale, t.clone());
titles.push(ContainerTitle {
x: rect.x1(),
y: rect.y1(),
tex: t,
})
}
Err(e) => { Err(e) => {
log::error!("Could not render title {}: {}", title, ErrorFmt(e)); log::error!("Could not render title {}: {}", title, ErrorFmt(e));
} }
@ -1268,6 +1283,7 @@ impl ContainingNode for ContainerNode {
content: Default::default(), content: Default::default(),
factor: Cell::new(node.factor.get()), factor: Cell::new(node.factor.get()),
title: Default::default(), title: Default::default(),
title_tex: Default::default(),
title_rect: Cell::new(node.title_rect.get()), title_rect: Cell::new(node.title_rect.get()),
focus_history: Cell::new(None), focus_history: Cell::new(None),
}); });

View file

@ -3,13 +3,12 @@ use {
backend::KeyState, backend::KeyState,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_api::GfxTexture,
ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT}, ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT},
rect::Rect, rect::Rect,
renderer::Renderer, renderer::Renderer,
scale::Scale, scale::Scale,
state::State, state::State,
text, text::{self, TextTexture},
tree::{ tree::{
walker::NodeVisitor, ContainingNode, FindTreeResult, FoundNode, Node, NodeId, walker::NodeVisitor, ContainingNode, FindTreeResult, FoundNode, Node, NodeId,
StackedNode, ToplevelNode, WorkspaceNode, StackedNode, ToplevelNode, WorkspaceNode,
@ -44,7 +43,7 @@ pub struct FloatNode {
pub layout_scheduled: Cell<bool>, pub layout_scheduled: Cell<bool>,
pub render_titles_scheduled: Cell<bool>, pub render_titles_scheduled: Cell<bool>,
pub title: RefCell<String>, pub title: RefCell<String>,
pub title_textures: CopyHashMap<Scale, Rc<dyn GfxTexture>>, pub title_textures: CopyHashMap<Scale, TextTexture>,
seats: RefCell<AHashMap<SeatId, SeatState>>, seats: RefCell<AHashMap<SeatId, SeatState>>,
} }
@ -179,7 +178,6 @@ impl FloatNode {
let bw = theme.sizes.border_width.get(); let bw = theme.sizes.border_width.get();
let font = theme.font.borrow_mut(); let font = theme.font.borrow_mut();
let title = self.title.borrow_mut(); let title = self.title.borrow_mut();
self.title_textures.clear();
let pos = self.position.get(); let pos = self.position.get();
if pos.width() <= 2 * bw || title.is_empty() { if pos.width() <= 2 * bw || title.is_empty() {
return; return;
@ -190,6 +188,7 @@ impl FloatNode {
}; };
let scales = self.state.scales.lock(); let scales = self.state.scales.lock();
for (scale, _) in scales.iter() { for (scale, _) in scales.iter() {
let old_tex = self.title_textures.remove(scale);
let mut th = th; let mut th = th;
let mut scalef = None; let mut scalef = None;
let mut width = pos.width() - 2 * bw; let mut width = pos.width() - 2 * bw;
@ -202,7 +201,7 @@ impl FloatNode {
if th == 0 || width == 0 { if th == 0 || width == 0 {
continue; continue;
} }
let texture = match text::render(&ctx, width, th, &font, &title, tc, scalef) { let texture = match text::render(&ctx, old_tex, width, th, &font, &title, tc, scalef) {
Ok(t) => t, Ok(t) => t,
Err(e) => { Err(e) => {
log::error!("Could not render title {}: {}", title, ErrorFmt(e)); log::error!("Could not render title {}: {}", title, ErrorFmt(e));

View file

@ -23,7 +23,7 @@ use {
renderer::Renderer, renderer::Renderer,
scale::Scale, scale::Scale,
state::State, state::State,
text, text::{self, TextTexture},
tree::{ tree::{
walker::NodeVisitor, Direction, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode, walker::NodeVisitor, Direction, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode,
}, },
@ -165,6 +165,7 @@ impl OutputNode {
let output_width = self.global.pos.get().width(); let output_width = self.global.pos.get().width();
rd.underline = Rect::new_sized(0, th, output_width, 1).unwrap(); rd.underline = Rect::new_sized(0, th, output_width, 1).unwrap();
for ws in self.workspaces.iter() { for ws in self.workspaces.iter() {
let old_tex = ws.title_texture.take();
let mut title_width = th; let mut title_width = th;
'create_texture: { 'create_texture: {
if let Some(ctx) = self.state.render_ctx.get() { if let Some(ctx) = self.state.render_ctx.get() {
@ -177,6 +178,7 @@ impl OutputNode {
}; };
let title = match text::render_fitting( let title = match text::render_fitting(
&ctx, &ctx,
old_tex,
Some(texture_height), Some(texture_height),
&font, &font,
&ws.name, &ws.name,
@ -190,8 +192,9 @@ impl OutputNode {
break 'create_texture; break 'create_texture;
} }
}; };
ws.title_texture.set(Some(title.clone()));
let mut x = pos + 1; let mut x = pos + 1;
let mut width = title.width(); let mut width = title.texture.width();
if let Some(scale) = scale { if let Some(scale) = scale {
width = (width as f64 / scale).round() as _; width = (width as f64 / scale).round() as _;
} }
@ -205,7 +208,7 @@ impl OutputNode {
x2: pos + title_width, x2: pos + title_width,
tex_x: x, tex_x: x,
tex_y: 0, tex_y: 0,
tex: title, tex: title.texture,
ws: ws.deref().clone(), ws: ws.deref().clone(),
}); });
} }
@ -224,6 +227,7 @@ impl OutputNode {
pos += title_width; pos += title_width;
} }
'set_status: { 'set_status: {
let old_tex = rd.status.take().map(|s| s.tex);
let ctx = match self.state.render_ctx.get() { let ctx = match self.state.render_ctx.get() {
Some(ctx) => ctx, Some(ctx) => ctx,
_ => break 'set_status, _ => break 'set_status,
@ -235,6 +239,7 @@ impl OutputNode {
let tc = self.state.theme.colors.bar_text.get(); let tc = self.state.theme.colors.bar_text.get();
let title = match text::render_fitting( let title = match text::render_fitting(
&ctx, &ctx,
old_tex,
Some(texture_height), Some(texture_height),
&font, &font,
&status, &status,
@ -248,7 +253,7 @@ impl OutputNode {
break 'set_status; break 'set_status;
} }
}; };
let mut width = title.width(); let mut width = title.texture.width();
if let Some(scale) = scale { if let Some(scale) = scale {
width = (width as f64 / scale).round() as _; width = (width as f64 / scale).round() as _;
} }
@ -324,6 +329,7 @@ impl OutputNode {
desired_output: CloneCell::new(self.global.output_id.clone()), desired_output: CloneCell::new(self.global.output_id.clone()),
jay_workspaces: Default::default(), jay_workspaces: Default::default(),
capture: self.state.default_workspace_capture.clone(), capture: self.state.default_workspace_capture.clone(),
title_texture: Default::default(),
}); });
ws.output_link ws.output_link
.set(Some(self.workspaces.add_last(ws.clone()))); .set(Some(self.workspaces.add_last(ws.clone())));
@ -473,7 +479,7 @@ pub struct OutputTitle {
pub struct OutputStatus { pub struct OutputStatus {
pub tex_x: i32, pub tex_x: i32,
pub tex_y: i32, pub tex_y: i32,
pub tex: Rc<dyn GfxTexture>, pub tex: TextTexture,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -3,13 +3,12 @@ use {
client::Client, client::Client,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_api::GfxTexture,
ifs::wl_seat::{NodeSeatState, WlSeatGlobal}, ifs::wl_seat::{NodeSeatState, WlSeatGlobal},
rect::Rect, rect::Rect,
renderer::Renderer, renderer::Renderer,
scale::Scale, scale::Scale,
state::State, state::State,
text, text::{self, TextTexture},
tree::{ tree::{
Direction, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData, Direction, FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, ToplevelData,
ToplevelNode, ToplevelNode,
@ -25,7 +24,7 @@ pub struct PlaceholderNode {
id: PlaceholderNodeId, id: PlaceholderNodeId,
toplevel: ToplevelData, toplevel: ToplevelData,
destroyed: Cell<bool>, destroyed: Cell<bool>,
pub textures: SmallMap<Scale, Rc<dyn GfxTexture>, 2>, pub textures: SmallMap<Scale, TextTexture, 2>,
} }
impl PlaceholderNode { impl PlaceholderNode {
@ -47,11 +46,11 @@ impl PlaceholderNode {
} }
pub fn update_texture(&self) { pub fn update_texture(&self) {
self.textures.clear();
if let Some(ctx) = self.toplevel.state.render_ctx.get() { if let Some(ctx) = self.toplevel.state.render_ctx.get() {
let scales = self.toplevel.state.scales.lock(); let scales = self.toplevel.state.scales.lock();
let rect = self.toplevel.pos.get(); let rect = self.toplevel.pos.get();
for (scale, _) in scales.iter() { for (scale, _) in scales.iter() {
let old_tex = self.textures.remove(scale);
let mut width = rect.width(); let mut width = rect.width();
let mut height = rect.height(); let mut height = rect.height();
if *scale != 1 { if *scale != 1 {
@ -63,6 +62,7 @@ impl PlaceholderNode {
let font = format!("monospace {}", width / 10); let font = format!("monospace {}", width / 10);
match text::render_fitting( match text::render_fitting(
&ctx, &ctx,
old_tex,
Some(height), Some(height),
&font, &font,
"Fullscreen", "Fullscreen",

View file

@ -10,6 +10,7 @@ use {
}, },
rect::Rect, rect::Rect,
renderer::Renderer, renderer::Renderer,
text::TextTexture,
tree::{ tree::{
container::ContainerNode, walker::NodeVisitor, ContainingNode, Direction, container::ContainerNode, walker::NodeVisitor, ContainingNode, Direction,
FindTreeResult, FoundNode, Node, NodeId, NodeVisitorBase, OutputNode, StackedNode, FindTreeResult, FoundNode, Node, NodeId, NodeVisitorBase, OutputNode, StackedNode,
@ -43,6 +44,7 @@ pub struct WorkspaceNode {
pub desired_output: CloneCell<Rc<OutputId>>, pub desired_output: CloneCell<Rc<OutputId>>,
pub jay_workspaces: CopyHashMap<(ClientId, JayWorkspaceId), Rc<JayWorkspace>>, pub jay_workspaces: CopyHashMap<(ClientId, JayWorkspaceId), Rc<JayWorkspace>>,
pub capture: Cell<bool>, pub capture: Cell<bool>,
pub title_texture: Cell<Option<TextTexture>>,
} }
impl WorkspaceNode { impl WorkspaceNode {