working scissor proof of concept
This commit is contained in:
@@ -11,9 +11,9 @@
|
|||||||
<div margin_left="16" gap="8" flex_direction="column">
|
<div margin_left="16" gap="8" flex_direction="column">
|
||||||
<label id="label_current_option" text="Click any of these buttons" size="20" weight="bold" />
|
<label id="label_current_option" text="Click any of these buttons" size="20" weight="bold" />
|
||||||
<div gap="4">
|
<div gap="4">
|
||||||
<Button id="button_red" text="Red button" width="220" height="32" color="#FF0000" />
|
<Button id="button_red" text="Red button" width="150" height="32" color="#FF0000" />
|
||||||
<Button id="button_aqua" text="Aqua button" width="220" height="32" color="#00FFFF" />
|
<Button id="button_aqua" text="Aqua button" width="150" height="32" color="#00FFFF" />
|
||||||
<Button id="button_yellow" text="Yellow button" width="220" height="32" color="#FFFF00" />
|
<Button id="button_yellow" text="Yellow button" width="150" height="32" color="#FFFF00" />
|
||||||
</div>
|
</div>
|
||||||
<Button id="button_click_me" text="Click me" width="128" height="24" color="#FFFFFF" />
|
<Button id="button_click_me" text="Click me" width="128" height="24" color="#FFFFFF" />
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use glam::{Mat4, Vec2};
|
|||||||
use taffy::TraversePartialTree;
|
use taffy::TraversePartialTree;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
drawing,
|
||||||
layout::Widget,
|
layout::Widget,
|
||||||
renderer_vk::text::custom_glyph::CustomGlyph,
|
renderer_vk::text::custom_glyph::CustomGlyph,
|
||||||
transform_stack::{self, TransformStack},
|
transform_stack::{self, TransformStack},
|
||||||
@@ -111,26 +112,18 @@ pub struct Rectangle {
|
|||||||
pub round_units: u8,
|
pub round_units: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
pub struct PrimitiveExtent {
|
||||||
pub struct Scissor {
|
|
||||||
pub x: u32,
|
|
||||||
pub y: u32,
|
|
||||||
pub w: u32,
|
|
||||||
pub h: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RenderPrimitive {
|
|
||||||
pub(super) boundary: Boundary,
|
pub(super) boundary: Boundary,
|
||||||
pub(super) transform: Mat4,
|
pub(super) transform: Mat4,
|
||||||
pub(super) depth: f32,
|
pub(super) depth: f32, // FIXME: remove this
|
||||||
pub(super) payload: PrimitivePayload,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum PrimitivePayload {
|
pub enum RenderPrimitive {
|
||||||
Rectangle(Rectangle),
|
Rectangle(PrimitiveExtent, Rectangle),
|
||||||
Text(Rc<RefCell<Buffer>>),
|
Text(PrimitiveExtent, Rc<RefCell<Buffer>>),
|
||||||
Sprite(Option<CustomGlyph>), //option because we want as_slice
|
Sprite(PrimitiveExtent, Option<CustomGlyph>), //option because we want as_slice
|
||||||
Scissor(Scissor),
|
ScissorEnable(Boundary),
|
||||||
|
ScissorDisable,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_widget(
|
fn draw_widget(
|
||||||
@@ -161,6 +154,13 @@ fn draw_widget(
|
|||||||
dim: Vec2::new(l.size.width, l.size.height),
|
dim: Vec2::new(l.size.width, l.size.height),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// FIXME: this is temporary
|
||||||
|
// FIXME: implement scissor stack (do not allow growing!)
|
||||||
|
if info.is_some() {
|
||||||
|
let boundary = drawing::Boundary::construct(state.transform_stack);
|
||||||
|
state.primitives.push(drawing::RenderPrimitive::ScissorEnable(boundary));
|
||||||
|
}
|
||||||
|
|
||||||
let draw_params = widget::DrawParams {
|
let draw_params = widget::DrawParams {
|
||||||
node_id,
|
node_id,
|
||||||
taffy_layout: l,
|
taffy_layout: l,
|
||||||
@@ -171,6 +171,10 @@ fn draw_widget(
|
|||||||
|
|
||||||
draw_children(layout, state, node_id, &transform);
|
draw_children(layout, state, node_id, &transform);
|
||||||
|
|
||||||
|
if info.is_some() {
|
||||||
|
state.primitives.push(drawing::RenderPrimitive::ScissorDisable);
|
||||||
|
}
|
||||||
|
|
||||||
state.transform_stack.pop();
|
state.transform_stack.pop();
|
||||||
|
|
||||||
if let Some(info) = &info {
|
if let Some(info) = &info {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use vulkano::{
|
|||||||
},
|
},
|
||||||
pipeline::{
|
pipeline::{
|
||||||
Pipeline, PipelineBindPoint,
|
Pipeline, PipelineBindPoint,
|
||||||
graphics::{vertex_input::Vertex, viewport::Viewport},
|
graphics::{self, vertex_input::Vertex, viewport::Viewport},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -38,6 +38,7 @@ where
|
|||||||
vertices: Range<u32>,
|
vertices: Range<u32>,
|
||||||
instances: Range<u32>,
|
instances: Range<u32>,
|
||||||
descriptor_sets: Vec<Arc<DescriptorSet>>,
|
descriptor_sets: Vec<Arc<DescriptorSet>>,
|
||||||
|
vk_scissor: &graphics::viewport::Scissor,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
let viewport = Viewport {
|
let viewport = Viewport {
|
||||||
offset: [0.0, 0.0],
|
offset: [0.0, 0.0],
|
||||||
@@ -64,6 +65,7 @@ where
|
|||||||
unsafe {
|
unsafe {
|
||||||
command_buffer
|
command_buffer
|
||||||
.set_viewport(0, smallvec![viewport])?
|
.set_viewport(0, smallvec![viewport])?
|
||||||
|
.set_scissor(0, smallvec![*vk_scissor])?
|
||||||
.bind_pipeline_graphics(pipeline_inner)?
|
.bind_pipeline_graphics(pipeline_inner)?
|
||||||
.bind_descriptor_sets(
|
.bind_descriptor_sets(
|
||||||
PipelineBindPoint::Graphics,
|
PipelineBindPoint::Graphics,
|
||||||
@@ -88,12 +90,7 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_sampler(
|
pub fn update_sampler(&self, set: usize, texture: Arc<ImageView>, filter: Filter) -> anyhow::Result<()> {
|
||||||
&self,
|
|
||||||
set: usize,
|
|
||||||
texture: Arc<ImageView>,
|
|
||||||
filter: Filter,
|
|
||||||
) -> anyhow::Result<()> {
|
|
||||||
let sampler = Sampler::new(
|
let sampler = Sampler::new(
|
||||||
self.graphics.device.clone(),
|
self.graphics.device.clone(),
|
||||||
SamplerCreateInfo {
|
SamplerCreateInfo {
|
||||||
@@ -105,10 +102,7 @@ where
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.descriptor_sets[set].update_by_ref(
|
self.descriptor_sets[set].update_by_ref([WriteDescriptorSet::image_view_sampler(0, texture, sampler)], [])?;
|
||||||
[WriteDescriptorSet::image_view_sampler(0, texture, sampler)],
|
|
||||||
[],
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use vulkano::{
|
|||||||
pipeline::{
|
pipeline::{
|
||||||
DynamicState, GraphicsPipeline, Pipeline, PipelineLayout,
|
DynamicState, GraphicsPipeline, Pipeline, PipelineLayout,
|
||||||
graphics::{
|
graphics::{
|
||||||
GraphicsPipelineCreateInfo,
|
self, GraphicsPipelineCreateInfo,
|
||||||
color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState},
|
color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState},
|
||||||
input_assembly::{InputAssemblyState, PrimitiveTopology},
|
input_assembly::{InputAssemblyState, PrimitiveTopology},
|
||||||
multisample::MultisampleState,
|
multisample::MultisampleState,
|
||||||
@@ -91,7 +91,7 @@ where
|
|||||||
}],
|
}],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
dynamic_state: std::iter::once(DynamicState::Viewport).collect(),
|
dynamic_state: [DynamicState::Viewport, DynamicState::Scissor].into_iter().collect(),
|
||||||
subpass: Some(subpass.into()),
|
subpass: Some(subpass.into()),
|
||||||
..GraphicsPipelineCreateInfo::layout(layout)
|
..GraphicsPipelineCreateInfo::layout(layout)
|
||||||
},
|
},
|
||||||
@@ -105,7 +105,6 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn inner(&self) -> Arc<GraphicsPipeline> {
|
pub fn inner(&self) -> Arc<GraphicsPipeline> {
|
||||||
self.pipeline.clone()
|
self.pipeline.clone()
|
||||||
}
|
}
|
||||||
@@ -151,11 +150,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn uniform_buffer_upload<T>(
|
pub fn uniform_buffer_upload<T>(&self, set: usize, data: Vec<T>) -> anyhow::Result<Arc<DescriptorSet>>
|
||||||
&self,
|
|
||||||
set: usize,
|
|
||||||
data: Vec<T>,
|
|
||||||
) -> anyhow::Result<Arc<DescriptorSet>>
|
|
||||||
where
|
where
|
||||||
T: BufferContents + Copy,
|
T: BufferContents + Copy,
|
||||||
{
|
{
|
||||||
@@ -163,8 +158,7 @@ where
|
|||||||
self.graphics.memory_allocator.clone(),
|
self.graphics.memory_allocator.clone(),
|
||||||
SubbufferAllocatorCreateInfo {
|
SubbufferAllocatorCreateInfo {
|
||||||
buffer_usage: BufferUsage::UNIFORM_BUFFER,
|
buffer_usage: BufferUsage::UNIFORM_BUFFER,
|
||||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -219,6 +213,7 @@ where
|
|||||||
vertices: Range<u32>,
|
vertices: Range<u32>,
|
||||||
instances: Range<u32>,
|
instances: Range<u32>,
|
||||||
descriptor_sets: Vec<Arc<DescriptorSet>>,
|
descriptor_sets: Vec<Arc<DescriptorSet>>,
|
||||||
|
vk_scissor: &graphics::viewport::Scissor,
|
||||||
) -> anyhow::Result<WGfxPass<V>> {
|
) -> anyhow::Result<WGfxPass<V>> {
|
||||||
WGfxPass::new(
|
WGfxPass::new(
|
||||||
&self.clone(),
|
&self.clone(),
|
||||||
@@ -227,6 +222,7 @@ where
|
|||||||
vertices,
|
vertices,
|
||||||
instances,
|
instances,
|
||||||
descriptor_sets,
|
descriptor_sets,
|
||||||
|
vk_scissor,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ use std::{cell::RefCell, rc::Rc, sync::Arc};
|
|||||||
use cosmic_text::Buffer;
|
use cosmic_text::Buffer;
|
||||||
use glam::{Mat4, Vec2, Vec3};
|
use glam::{Mat4, Vec2, Vec3};
|
||||||
use slotmap::{SlotMap, new_key_type};
|
use slotmap::{SlotMap, new_key_type};
|
||||||
use vulkano::{buffer::view, pipeline::graphics::viewport};
|
use vulkano::pipeline::graphics::viewport;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{self, Scissor},
|
drawing::{self},
|
||||||
gfx::{WGfx, cmd::GfxCommandBuffer},
|
gfx::{WGfx, cmd::GfxCommandBuffer},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,11 +25,17 @@ struct RendererPass<'a> {
|
|||||||
text_areas: Vec<TextArea<'a>>,
|
text_areas: Vec<TextArea<'a>>,
|
||||||
text_renderer: TextRenderer,
|
text_renderer: TextRenderer,
|
||||||
rect_renderer: RectRenderer,
|
rect_renderer: RectRenderer,
|
||||||
scissor: Option<Scissor>,
|
scissor: Option<drawing::Boundary>,
|
||||||
|
pixel_scale: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RendererPass<'_> {
|
impl RendererPass<'_> {
|
||||||
fn new(text_atlas: &mut TextAtlas, rect_pipeline: RectPipeline, scissor: Option<Scissor>) -> anyhow::Result<Self> {
|
fn new(
|
||||||
|
text_atlas: &mut TextAtlas,
|
||||||
|
rect_pipeline: RectPipeline,
|
||||||
|
scissor: Option<drawing::Boundary>,
|
||||||
|
pixel_scale: f32,
|
||||||
|
) -> anyhow::Result<Self> {
|
||||||
let text_renderer = TextRenderer::new(text_atlas)?;
|
let text_renderer = TextRenderer::new(text_atlas)?;
|
||||||
let rect_renderer = RectRenderer::new(rect_pipeline)?;
|
let rect_renderer = RectRenderer::new(rect_pipeline)?;
|
||||||
|
|
||||||
@@ -39,6 +45,7 @@ impl RendererPass<'_> {
|
|||||||
rect_renderer,
|
rect_renderer,
|
||||||
text_areas: Vec::new(),
|
text_areas: Vec::new(),
|
||||||
scissor,
|
scissor,
|
||||||
|
pixel_scale,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,20 +60,34 @@ impl RendererPass<'_> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let vk_scissor = if let Some(scissor) = self.scissor {
|
let vk_scissor = match self.scissor {
|
||||||
viewport::Scissor {
|
Some(scissor) => {
|
||||||
offset: [scissor.x, scissor.y],
|
let mut x = scissor.pos.x;
|
||||||
extent: [scissor.w, scissor.h],
|
let mut y = scissor.pos.y;
|
||||||
|
let mut w = scissor.size.x;
|
||||||
|
let mut h = scissor.size.y;
|
||||||
|
|
||||||
|
// handle out-of-bounds scissors (x/y < 0)
|
||||||
|
if x < 0.0 {
|
||||||
|
w += x;
|
||||||
|
x = 0.0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
viewport::Scissor::default()
|
if y < 0.0 {
|
||||||
|
h += y;
|
||||||
|
y = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
viewport::Scissor {
|
||||||
|
offset: [(x * self.pixel_scale) as u32, (y * self.pixel_scale) as u32],
|
||||||
|
extent: [(w * self.pixel_scale) as u32, (h * self.pixel_scale) as u32],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => viewport::Scissor::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO?
|
|
||||||
// cmd_buf.command_buffer.set_scissor(0, smallvec::smallvec![vk_scissor])?;
|
|
||||||
|
|
||||||
self.submitted = true;
|
self.submitted = true;
|
||||||
self.rect_renderer.render(gfx, viewport, cmd_buf)?;
|
self.rect_renderer.render(gfx, viewport, &vk_scissor, cmd_buf)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut font_system = FONT_SYSTEM.lock();
|
let mut font_system = FONT_SYSTEM.lock();
|
||||||
@@ -81,7 +102,7 @@ impl RendererPass<'_> {
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.text_renderer.render(text_atlas, viewport, cmd_buf)?;
|
self.text_renderer.render(text_atlas, viewport, &vk_scissor, cmd_buf)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -202,7 +223,7 @@ impl Context {
|
|||||||
|
|
||||||
let mut passes = Vec::<RendererPass>::new();
|
let mut passes = Vec::<RendererPass>::new();
|
||||||
let mut needs_new_pass = true;
|
let mut needs_new_pass = true;
|
||||||
let mut next_scissor: Option<Scissor> = None;
|
let mut next_scissor: Option<drawing::Boundary> = None;
|
||||||
|
|
||||||
for primitive in primitives {
|
for primitive in primitives {
|
||||||
if needs_new_pass {
|
if needs_new_pass {
|
||||||
@@ -210,54 +231,60 @@ impl Context {
|
|||||||
&mut atlas.text_atlas,
|
&mut atlas.text_atlas,
|
||||||
shared.rect_pipeline.clone(),
|
shared.rect_pipeline.clone(),
|
||||||
next_scissor,
|
next_scissor,
|
||||||
|
self.pixel_scale,
|
||||||
)?);
|
)?);
|
||||||
next_scissor = None;
|
|
||||||
needs_new_pass = false;
|
needs_new_pass = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pass = passes.last_mut().unwrap(); // always safe
|
let pass = passes.last_mut().unwrap(); // always safe
|
||||||
|
|
||||||
match &primitive.payload {
|
match &primitive {
|
||||||
drawing::PrimitivePayload::Rectangle(rectangle) => {
|
drawing::RenderPrimitive::Rectangle(extent, rectangle) => {
|
||||||
pass
|
pass
|
||||||
.rect_renderer
|
.rect_renderer
|
||||||
.add_rect(primitive.boundary, *rectangle, &primitive.transform, primitive.depth);
|
.add_rect(extent.boundary, *rectangle, &extent.transform, extent.depth);
|
||||||
}
|
}
|
||||||
drawing::PrimitivePayload::Text(text) => {
|
drawing::RenderPrimitive::Text(extent, text) => {
|
||||||
pass.text_areas.push(TextArea {
|
pass.text_areas.push(TextArea {
|
||||||
buffer: text.clone(),
|
buffer: text.clone(),
|
||||||
left: primitive.boundary.pos.x * self.pixel_scale,
|
left: extent.boundary.pos.x * self.pixel_scale,
|
||||||
top: primitive.boundary.pos.y * self.pixel_scale,
|
top: extent.boundary.pos.y * self.pixel_scale,
|
||||||
bounds: TextBounds::default(), //FIXME: just using boundary coords here doesn't work
|
bounds: TextBounds::default(), //FIXME: just using boundary coords here doesn't work
|
||||||
scale: self.pixel_scale,
|
scale: self.pixel_scale,
|
||||||
default_color: cosmic_text::Color::rgb(0, 0, 0),
|
default_color: cosmic_text::Color::rgb(0, 0, 0),
|
||||||
custom_glyphs: &[],
|
custom_glyphs: &[],
|
||||||
depth: primitive.depth,
|
depth: extent.depth,
|
||||||
transform: primitive.transform,
|
transform: extent.transform,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
drawing::PrimitivePayload::Sprite(sprites) => {
|
drawing::RenderPrimitive::Sprite(extent, sprites) => {
|
||||||
pass.text_areas.push(TextArea {
|
pass.text_areas.push(TextArea {
|
||||||
buffer: self.empty_text.clone(),
|
buffer: self.empty_text.clone(),
|
||||||
left: primitive.boundary.pos.x * self.pixel_scale,
|
left: extent.boundary.pos.x * self.pixel_scale,
|
||||||
top: primitive.boundary.pos.y * self.pixel_scale,
|
top: extent.boundary.pos.y * self.pixel_scale,
|
||||||
bounds: TextBounds::default(),
|
bounds: TextBounds::default(),
|
||||||
scale: self.pixel_scale,
|
scale: self.pixel_scale,
|
||||||
custom_glyphs: sprites.as_slice(),
|
custom_glyphs: sprites.as_slice(),
|
||||||
default_color: cosmic_text::Color::rgb(255, 0, 255),
|
default_color: cosmic_text::Color::rgb(255, 0, 255),
|
||||||
depth: primitive.depth,
|
depth: extent.depth,
|
||||||
transform: primitive.transform,
|
transform: extent.transform,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
drawing::PrimitivePayload::Scissor(scissor) => {
|
drawing::RenderPrimitive::ScissorEnable(boundary) => {
|
||||||
next_scissor = Some(*scissor);
|
next_scissor = Some(*boundary);
|
||||||
|
needs_new_pass = true;
|
||||||
|
}
|
||||||
|
drawing::RenderPrimitive::ScissorDisable => {
|
||||||
|
next_scissor = None;
|
||||||
needs_new_pass = true;
|
needs_new_pass = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::info!("count {}", passes.len());
|
||||||
|
|
||||||
for mut pass in passes {
|
for mut pass in passes {
|
||||||
pass.submit(&shared.gfx, &mut self.viewport, cmd_buf, &mut atlas.text_atlas)?
|
pass.submit(&shared.gfx, &mut self.viewport, cmd_buf, &mut atlas.text_atlas)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use glam::Mat4;
|
|||||||
use vulkano::{
|
use vulkano::{
|
||||||
buffer::{BufferContents, BufferUsage, Subbuffer},
|
buffer::{BufferContents, BufferUsage, Subbuffer},
|
||||||
format::Format,
|
format::Format,
|
||||||
pipeline::graphics::{input_assembly::PrimitiveTopology, vertex_input::Vertex},
|
pipeline::graphics::{self, input_assembly::PrimitiveTopology, vertex_input::Vertex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -136,6 +136,7 @@ impl RectRenderer {
|
|||||||
&mut self,
|
&mut self,
|
||||||
gfx: &Arc<WGfx>,
|
gfx: &Arc<WGfx>,
|
||||||
viewport: &mut Viewport,
|
viewport: &mut Viewport,
|
||||||
|
vk_scissor: &graphics::viewport::Scissor,
|
||||||
cmd_buf: &mut GfxCommandBuffer,
|
cmd_buf: &mut GfxCommandBuffer,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let res = viewport.resolution();
|
let res = viewport.resolution();
|
||||||
@@ -154,6 +155,7 @@ impl RectRenderer {
|
|||||||
0..4,
|
0..4,
|
||||||
0..self.rect_vertices.len() as _,
|
0..self.rect_vertices.len() as _,
|
||||||
vec![set0, set1],
|
vec![set0, set1],
|
||||||
|
vk_scissor,
|
||||||
)?;
|
)?;
|
||||||
CachedPass { pass, res }
|
CachedPass { pass, res }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use glam::{Mat4, Vec2, Vec3};
|
|||||||
use vulkano::{
|
use vulkano::{
|
||||||
buffer::{BufferUsage, Subbuffer},
|
buffer::{BufferUsage, Subbuffer},
|
||||||
command_buffer::CommandBufferUsage,
|
command_buffer::CommandBufferUsage,
|
||||||
|
pipeline::graphics,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CachedPass {
|
struct CachedPass {
|
||||||
@@ -78,12 +79,7 @@ impl TextRenderer {
|
|||||||
let height = (glyph.height * text_area.scale).round() as u16;
|
let height = (glyph.height * text_area.scale).round() as u16;
|
||||||
|
|
||||||
let (x, y, x_bin, y_bin) = if glyph.snap_to_physical_pixel {
|
let (x, y, x_bin, y_bin) = if glyph.snap_to_physical_pixel {
|
||||||
(
|
(x.round() as i32, y.round() as i32, SubpixelBin::Zero, SubpixelBin::Zero)
|
||||||
x.round() as i32,
|
|
||||||
y.round() as i32,
|
|
||||||
SubpixelBin::Zero,
|
|
||||||
SubpixelBin::Zero,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
let (x, x_bin) = SubpixelBin::new(x);
|
let (x, x_bin) = SubpixelBin::new(x);
|
||||||
let (y, y_bin) = SubpixelBin::new(y);
|
let (y, y_bin) = SubpixelBin::new(y);
|
||||||
@@ -252,6 +248,7 @@ impl TextRenderer {
|
|||||||
&mut self,
|
&mut self,
|
||||||
atlas: &TextAtlas,
|
atlas: &TextAtlas,
|
||||||
viewport: &mut Viewport,
|
viewport: &mut Viewport,
|
||||||
|
vk_scissor: &graphics::viewport::Scissor,
|
||||||
cmd_buf: &mut GfxCommandBuffer,
|
cmd_buf: &mut GfxCommandBuffer,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
if self.glyph_vertices.is_empty() {
|
if self.glyph_vertices.is_empty() {
|
||||||
@@ -277,6 +274,7 @@ impl TextRenderer {
|
|||||||
0..4,
|
0..4,
|
||||||
0..self.glyph_vertices.len() as u32,
|
0..self.glyph_vertices.len() as u32,
|
||||||
descriptor_sets,
|
descriptor_sets,
|
||||||
|
vk_scissor,
|
||||||
)?;
|
)?;
|
||||||
CachedPass { pass, res }
|
CachedPass { pass, res }
|
||||||
}
|
}
|
||||||
@@ -351,10 +349,7 @@ fn prepare_glyph(
|
|||||||
if let Some(a) = inner.try_allocate(image.width as usize, image.height as usize) {
|
if let Some(a) = inner.try_allocate(image.width as usize, image.height as usize) {
|
||||||
break a;
|
break a;
|
||||||
}
|
}
|
||||||
if !par
|
if !par.atlas.grow(par.font_system, par.cache, image.content_type)? {
|
||||||
.atlas
|
|
||||||
.grow(par.font_system, par.cache, image.content_type)?
|
|
||||||
{
|
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"Atlas full. atlas: {:?} cache_key: {:?}",
|
"Atlas full. atlas: {:?} cache_key: {:?}",
|
||||||
image.content_type,
|
image.content_type,
|
||||||
@@ -393,9 +388,7 @@ fn prepare_glyph(
|
|||||||
|
|
||||||
inner.glyphs_in_use.insert(par.cache_key);
|
inner.glyphs_in_use.insert(par.cache_key);
|
||||||
// Insert the glyph into the cache and return the details reference
|
// Insert the glyph into the cache and return the details reference
|
||||||
inner
|
inner.glyph_cache.get_or_insert(par.cache_key, || GlyphDetails {
|
||||||
.glyph_cache
|
|
||||||
.get_or_insert(par.cache_key, || GlyphDetails {
|
|
||||||
width: image.width,
|
width: image.width,
|
||||||
height: image.height,
|
height: image.height,
|
||||||
gpu_cache,
|
gpu_cache,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use slotmap::Key;
|
|||||||
use taffy::AvailableSpace;
|
use taffy::AvailableSpace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{self, Boundary},
|
drawing::{self, Boundary, PrimitiveExtent},
|
||||||
event::CallbackDataCommon,
|
event::CallbackDataCommon,
|
||||||
globals::Globals,
|
globals::Globals,
|
||||||
i18n::{I18n, Translation},
|
i18n::{I18n, Translation},
|
||||||
@@ -118,12 +118,14 @@ impl WidgetObj for WidgetLabel {
|
|||||||
buffer.set_size(&mut font_system, Some(boundary.size.x), Some(boundary.size.y));
|
buffer.set_size(&mut font_system, Some(boundary.size.x), Some(boundary.size.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
state.primitives.push(drawing::RenderPrimitive {
|
state.primitives.push(drawing::RenderPrimitive::Text(
|
||||||
|
PrimitiveExtent {
|
||||||
boundary,
|
boundary,
|
||||||
depth: state.depth,
|
depth: state.depth,
|
||||||
payload: drawing::PrimitivePayload::Text(self.buffer.clone()),
|
|
||||||
transform: state.transform_stack.get().transform,
|
transform: state.transform_stack.get().transform,
|
||||||
});
|
},
|
||||||
|
self.buffer.clone(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn measure(
|
fn measure(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use super::drawing::RenderPrimitive;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
any::AnyTrait,
|
any::AnyTrait,
|
||||||
drawing,
|
drawing::{self, PrimitiveExtent},
|
||||||
event::{
|
event::{
|
||||||
self, CallbackData, CallbackDataCommon, CallbackMetadata, Event, EventAlterables, EventListenerKind,
|
self, CallbackData, CallbackDataCommon, CallbackMetadata, Event, EventAlterables, EventListenerKind,
|
||||||
EventListenerVec, MouseWheelEvent,
|
EventListenerVec, MouseWheelEvent,
|
||||||
@@ -244,7 +244,8 @@ impl WidgetState {
|
|||||||
|
|
||||||
// Horizontal handle
|
// Horizontal handle
|
||||||
if enabled_horiz && info.handle_size.x < 1.0 {
|
if enabled_horiz && info.handle_size.x < 1.0 {
|
||||||
state.primitives.push(drawing::RenderPrimitive {
|
state.primitives.push(drawing::RenderPrimitive::Rectangle(
|
||||||
|
PrimitiveExtent {
|
||||||
boundary: drawing::Boundary::from_pos_size(
|
boundary: drawing::Boundary::from_pos_size(
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
transform.pos.x + transform.dim.x * (1.0 - info.handle_size.x) * self.data.scrolling.x,
|
transform.pos.x + transform.dim.x * (1.0 - info.handle_size.x) * self.data.scrolling.x,
|
||||||
@@ -254,13 +255,15 @@ impl WidgetState {
|
|||||||
),
|
),
|
||||||
depth: state.depth,
|
depth: state.depth,
|
||||||
transform: transform.transform,
|
transform: transform.transform,
|
||||||
payload: drawing::PrimitivePayload::Rectangle(rect_params),
|
},
|
||||||
});
|
rect_params,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertical handle
|
// Vertical handle
|
||||||
if enabled_vert && info.handle_size.y < 1.0 {
|
if enabled_vert && info.handle_size.y < 1.0 {
|
||||||
state.primitives.push(drawing::RenderPrimitive {
|
state.primitives.push(drawing::RenderPrimitive::Rectangle(
|
||||||
|
PrimitiveExtent {
|
||||||
boundary: drawing::Boundary::from_pos_size(
|
boundary: drawing::Boundary::from_pos_size(
|
||||||
Vec2::new(
|
Vec2::new(
|
||||||
transform.pos.x + transform.dim.x - thickness - margin,
|
transform.pos.x + transform.dim.x - thickness - margin,
|
||||||
@@ -270,8 +273,9 @@ impl WidgetState {
|
|||||||
),
|
),
|
||||||
depth: state.depth,
|
depth: state.depth,
|
||||||
transform: transform.transform,
|
transform: transform.transform,
|
||||||
payload: drawing::PrimitivePayload::Rectangle(rect_params),
|
},
|
||||||
});
|
rect_params,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use slotmap::Key;
|
use slotmap::Key;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{self, GradientMode},
|
drawing::{self, GradientMode, PrimitiveExtent},
|
||||||
layout::WidgetID,
|
layout::WidgetID,
|
||||||
widget::util::WLength,
|
widget::util::WLength,
|
||||||
};
|
};
|
||||||
@@ -43,19 +43,21 @@ impl WidgetObj for WidgetRectangle {
|
|||||||
WLength::Percent(percent) => (f32::min(boundary.size.x, boundary.size.y) * percent / 2.0) as u8,
|
WLength::Percent(percent) => (f32::min(boundary.size.x, boundary.size.y) * percent / 2.0) as u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
state.primitives.push(drawing::RenderPrimitive {
|
state.primitives.push(drawing::RenderPrimitive::Rectangle(
|
||||||
|
PrimitiveExtent {
|
||||||
boundary,
|
boundary,
|
||||||
depth: state.depth,
|
depth: state.depth,
|
||||||
transform: state.transform_stack.get().transform,
|
transform: state.transform_stack.get().transform,
|
||||||
payload: drawing::PrimitivePayload::Rectangle(drawing::Rectangle {
|
},
|
||||||
|
drawing::Rectangle {
|
||||||
color: self.params.color,
|
color: self.params.color,
|
||||||
color2: self.params.color2,
|
color2: self.params.color2,
|
||||||
gradient: self.params.gradient,
|
gradient: self.params.gradient,
|
||||||
border: self.params.border,
|
border: self.params.border,
|
||||||
border_color: self.params.border_color,
|
border_color: self.params.border_color,
|
||||||
round_units,
|
round_units,
|
||||||
}),
|
},
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_id(&self) -> WidgetID {
|
fn get_id(&self) -> WidgetID {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use cosmic_text::{Attrs, Buffer, Color, Shaping, Weight};
|
|||||||
use slotmap::Key;
|
use slotmap::Key;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{self},
|
drawing::{self, PrimitiveExtent},
|
||||||
layout::WidgetID,
|
layout::WidgetID,
|
||||||
renderer_vk::text::{
|
renderer_vk::text::{
|
||||||
DEFAULT_METRICS, FONT_SYSTEM,
|
DEFAULT_METRICS, FONT_SYSTEM,
|
||||||
@@ -55,12 +55,14 @@ impl WidgetObj for WidgetSprite {
|
|||||||
snap_to_physical_pixel: true,
|
snap_to_physical_pixel: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
state.primitives.push(drawing::RenderPrimitive {
|
state.primitives.push(drawing::RenderPrimitive::Sprite(
|
||||||
|
PrimitiveExtent {
|
||||||
boundary,
|
boundary,
|
||||||
depth: state.depth,
|
depth: state.depth,
|
||||||
payload: drawing::PrimitivePayload::Sprite(Some(glyph)),
|
|
||||||
transform: state.transform_stack.get().transform,
|
transform: state.transform_stack.get().transform,
|
||||||
});
|
},
|
||||||
|
Some(glyph),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
// Source not set or not available, display error text
|
// Source not set or not available, display error text
|
||||||
let mut buffer = Buffer::new_empty(DEFAULT_METRICS);
|
let mut buffer = Buffer::new_empty(DEFAULT_METRICS);
|
||||||
@@ -73,13 +75,16 @@ impl WidgetObj for WidgetSprite {
|
|||||||
// set text last in order to avoid expensive re-shaping
|
// set text last in order to avoid expensive re-shaping
|
||||||
buffer.set_text("Error", &attrs, Shaping::Basic);
|
buffer.set_text("Error", &attrs, Shaping::Basic);
|
||||||
}
|
}
|
||||||
state.primitives.push(drawing::RenderPrimitive {
|
|
||||||
|
state.primitives.push(drawing::RenderPrimitive::Text(
|
||||||
|
PrimitiveExtent {
|
||||||
boundary,
|
boundary,
|
||||||
depth: state.depth,
|
depth: state.depth,
|
||||||
payload: drawing::PrimitivePayload::Text(Rc::new(RefCell::new(buffer))),
|
|
||||||
transform: state.transform_stack.get().transform,
|
transform: state.transform_stack.get().transform,
|
||||||
});
|
},
|
||||||
}
|
Rc::new(RefCell::new(buffer)),
|
||||||
|
))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn measure(
|
fn measure(
|
||||||
|
|||||||
Reference in New Issue
Block a user