Skip to content

Commit

Permalink
various small things
Browse files Browse the repository at this point in the history
Made a few structs non-exhausive that are likely to have future fields added. This includes WindowOptions and BinStyle. Fix the currently remaining clippy warnings. Add style validation for back images. Add Impl's for PartialOrd/Ord on a few ID types.
  • Loading branch information
AustinJ235 committed Mar 20, 2024
1 parent 74fba76 commit 7bcf35d
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 17 deletions.
45 changes: 40 additions & 5 deletions src/interface/bin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use crate::Basalt;
pub struct BinID(pub(super) u64);

/// Information of a `Bin` after an update
///
/// ***Note:** If the `Bin` is hidden, this will reflect its state when it was last visible.*
#[derive(Clone, Default, Debug)]
pub struct BinPostUpdate {
/// Top Left Outer Position (Includes Border)
Expand Down Expand Up @@ -282,7 +284,7 @@ impl Bin {
/// Change window association of this `Bin` and all of its children recursively.
pub fn associate_window_recursive(self: &Arc<Self>, window: &Arc<Window>) {
for bin in self.children_recursive_with_self() {
bin.associate_window(&window);
bin.associate_window(window);
}
}

Expand Down Expand Up @@ -437,7 +439,7 @@ impl Bin {
/// Update the style of this `Bin`.
#[track_caller]
pub fn style_update(self: &Arc<Self>, copy: BinStyle) -> BinStyleValidation {
let validation = copy.validate(self.hrchy.load().parent.is_some());
let validation = copy.validate(self);

if !validation.errors_present() {
self.style.store(Arc::new(copy));
Expand Down Expand Up @@ -1353,9 +1355,42 @@ impl Bin {
// -- Hidden Check ------------------------------------------------------------------ //

if self.is_hidden_inner(Some(&style)) {
// TODO: should the entire BinPostUpdate be reset?
self.post_update.write().text_state = None;
return HashMap::new();
// NOTE: Eventhough the Bin is hidden, create an entry for each image used in the vertex
// data, so that the renderer keeps this image loaded on the gpu.

let mut vertex_data = HashMap::new();

match style.back_image.clone() {
Some(image_cache_key) => {
if self
.basalt
.image_cache_ref()
.obtain_image_info(image_cache_key.clone())
.is_some()
{
vertex_data
.entry(ImageSource::Cache(image_cache_key))
.or_default();
}
},
None => {
if let Some(image_vk) = style.back_image_vk.clone() {
vertex_data
.entry(ImageSource::Vulkano(image_vk))
.or_default();
}
},
}

if let Some(text_state) = self.post_update.read().text_state.as_ref() {
for image_cache_key in text_state.vertex_data.keys() {
vertex_data
.entry(ImageSource::Cache(image_cache_key.clone()))
.or_default();
}
}

return vertex_data;
}

// -- Ancestors Obtain -------------------------------------------------------------- //
Expand Down
161 changes: 155 additions & 6 deletions src/interface/bin/style.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::sync::Arc;

use vulkano::image::Image;
use vulkano::format::FormatFeatures;
use vulkano::image::{Image, ImageType};

use crate::image_cache::ImageCacheKey;
use crate::interface::Bin;
use crate::NonExhaustive;

/// Position of a `Bin`
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
Expand Down Expand Up @@ -120,7 +123,7 @@ impl From<FontStyle> for cosmic_text::Style {
}

/// Style of a `Bin`
#[derive(Default, Clone)]
#[derive(Clone)]
pub struct BinStyle {
/// Determines the positioning type
pub position: Option<BinPosition>,
Expand Down Expand Up @@ -205,6 +208,81 @@ pub struct BinStyle {
pub font_style: Option<FontStyle>,
// Misc
pub custom_verts: Vec<BinVert>,
pub _ne: NonExhaustive,
}

impl Default for BinStyle {
fn default() -> Self {
Self {
position: None,
z_index: None,
add_z_index: None,
hidden: None,
opacity: None,
pos_from_t: None,
pos_from_b: None,
pos_from_l: None,
pos_from_r: None,
pos_from_t_pct: None,
pos_from_b_pct: None,
pos_from_l_pct: None,
pos_from_r_pct: None,
pos_from_l_offset: None,
pos_from_t_offset: None,
pos_from_r_offset: None,
pos_from_b_offset: None,
width: None,
width_pct: None,
width_offset: None,
height: None,
height_pct: None,
height_offset: None,
margin_t: None,
margin_b: None,
margin_l: None,
margin_r: None,
pad_t: None,
pad_b: None,
pad_l: None,
pad_r: None,
scroll_y: None,
scroll_x: None,
overflow_y: None,
overflow_x: None,
border_size_t: None,
border_size_b: None,
border_size_l: None,
border_size_r: None,
border_color_t: None,
border_color_b: None,
border_color_l: None,
border_color_r: None,
border_radius_tl: None,
border_radius_tr: None,
border_radius_bl: None,
border_radius_br: None,
back_color: None,
back_image: None,
back_image_vk: None,
back_image_coords: None,
back_image_effect: None,
text: String::new(),
text_color: None,
text_height: None,
text_secret: None,
line_spacing: None,
line_limit: None,
text_wrap: None,
text_vert_align: None,
text_hori_align: None,
font_family: None,
font_weight: None,
font_stretch: None,
font_style: None,
custom_verts: Vec::new(),
_ne: NonExhaustive(()),
}
}
}

/// Error produced from an invalid style
Expand All @@ -222,15 +300,16 @@ impl std::fmt::Display for BinStyleError {

/// Type of error produced from an invalid style
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum BinStyleErrorType {
/// Two fields are conflicted only one must be set.
ConflictingFields,
/// Too many fields are defining an attribute.
TooManyConstraints,
/// Not enough fields are defining an attribute.
NotEnoughConstraints,
/// Requested font family & weight are not available.
MissingFont,
/// Provided Image isn't valid.
InvalidImage,
}

impl std::fmt::Display for BinStyleErrorType {
Expand All @@ -239,7 +318,7 @@ impl std::fmt::Display for BinStyleErrorType {
Self::ConflictingFields => write!(f, "Conflicting Fields"),
Self::TooManyConstraints => write!(f, "Too Many Constraints"),
Self::NotEnoughConstraints => write!(f, "Not Enough Constraints"),
Self::MissingFont => write!(f, "Missing Font"),
_ => write!(f, "Unknown"),
}
}
}
Expand All @@ -259,6 +338,7 @@ impl std::fmt::Display for BinStyleWarn {

/// Type of warning produced for a suboptimal style
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum BinStyleWarnType {
/// Field is set, but isn't used or incompatible with other styles.
UselessField,
Expand Down Expand Up @@ -457,8 +537,9 @@ macro_rules! useless_field {

impl BinStyle {
#[track_caller]
pub(crate) fn validate(&self, has_parent: bool) -> BinStyleValidation {
pub(crate) fn validate(&self, bin: &Arc<Bin>) -> BinStyleValidation {
let mut validation = BinStyleValidation::new();
let has_parent = bin.hrchy.load().parent.is_some();

match self.position.unwrap_or(BinPosition::Window) {
BinPosition::Window | BinPosition::Parent => {
Expand Down Expand Up @@ -713,6 +794,74 @@ impl BinStyle {
},
}

if self.back_image.is_some() && self.back_image_vk.is_some() {
validation.error(
BinStyleErrorType::ConflictingFields,
"Both 'back_image' and 'back_image_vk' are set.",
);
}

if let Some(back_image_vk) = self.back_image_vk.as_ref() {
if back_image_vk.image_type() != ImageType::Dim2d {
validation.error(
BinStyleErrorType::InvalidImage,
"Image provided with 'back_image_vk' isn't a 2d.",
);
}

if back_image_vk.array_layers() != 1 {
validation.error(
BinStyleErrorType::InvalidImage,
"Image provided with 'back_image_vk' must not have array layers.",
);
}

if back_image_vk.mip_levels() != 1 {
validation.error(
BinStyleErrorType::InvalidImage,
"Image provided with 'back_image_vk' must not have multiple mip levels.",
);
}

if !back_image_vk.format_features().contains(
FormatFeatures::TRANSFER_DST
| FormatFeatures::TRANSFER_SRC
| FormatFeatures::SAMPLED_IMAGE
| FormatFeatures::SAMPLED_IMAGE_FILTER_LINEAR,
) {
validation.error(
BinStyleErrorType::InvalidImage,
"Image provided with 'back_image_vk' must have a format that supports, \
'TRANSFER_DST`, `TRANSFER_SRC`, `SAMPLED_IMAGE`, & \
`SAMPLED_IMAGE_FILTER_LINEAR`.",
);
}
}

if let Some(image_cache_key) = self.back_image.as_ref() {
if matches!(image_cache_key, ImageCacheKey::Glyph(..)) {
validation.error(
BinStyleErrorType::InvalidImage,
"'ImageCacheKey' provided with 'back_image' must not be \
'ImageCacheKey::Glyph'. 'ImageCacheKey::User' should be used instead.",
);
}

if matches!(image_cache_key, ImageCacheKey::User(..))
&& bin
.basalt
.image_cache_ref()
.obtain_image_info(image_cache_key.clone())
.is_none()
{
validation.error(
BinStyleErrorType::InvalidImage,
"'ImageCacheKey::User' provided with 'back_image' must be preloaded into the \
`ImageCache`.",
);
}
}

validation
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ impl BasaltOptions {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct NonExhaustive(pub(crate) ());

struct BasaltConfig {
window_ignore_dpi: bool,
window_default_scale: f32,
Expand Down
13 changes: 10 additions & 3 deletions src/render/worker.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// NOTE: As of vulkano 0.34, Arc<Image> causes this warning though it is ok.
// This should be solved in a future vulkano release.
#![allow(clippy::mutable_key_type)]

use std::collections::{BTreeMap, HashMap, HashSet};
use std::ops::Range;
use std::sync::{Arc, Barrier, Weak};
Expand Down Expand Up @@ -429,10 +433,13 @@ pub fn spawn(
}
}

let mut metrics = WorkerPerfMetrics::default();
metrics.bins_changed = remove_bins.len();
let mut metrics = WorkerPerfMetrics {
bins_changed: remove_bins.len(),
..WorkerPerfMetrics::default()
};

let metrics_inst_total = Instant::now();
let mut metrics_inst = metrics_inst_total.clone();
let mut metrics_inst = metrics_inst_total;

// --- Remove Bin States --- //

Expand Down
8 changes: 5 additions & 3 deletions src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ use winit::window::WindowBuilder;
use crate::input::{InputEvent, MouseButton};
use crate::interface::{Bin, BinID, DefaultFont};
use crate::render::{VSync, MSAA};
use crate::Basalt;
use crate::{Basalt, NonExhaustive};

/// An ID that is used to identify a `Window`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct WindowID(u64);

/// An ID that is used to identify a hook on `WindowManager`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct WMHookID(u64);

/// Options for creating a window.
Expand Down Expand Up @@ -81,6 +81,7 @@ pub struct WindowOptions {
///
/// Default: `true`
pub decorations: bool,
pub _ne: NonExhaustive,
}

impl Default for WindowOptions {
Expand All @@ -96,6 +97,7 @@ impl Default for WindowOptions {
minimized: false,
fullscreen: None,
decorations: true,
_ne: NonExhaustive(()),
}
}
}
Expand Down

0 comments on commit 7bcf35d

Please sign in to comment.