wip
This commit is contained in:
parent
c0bad42968
commit
ca3d55ee4d
6 changed files with 904 additions and 220 deletions
|
@ -84,7 +84,7 @@ impl DirectXAtlas {
|
|||
let textures = match texture_kind {
|
||||
AtlasTextureKind::Monochrome => &mut lock.monochrome_textures,
|
||||
AtlasTextureKind::Polychrome => &mut lock.polychrome_textures,
|
||||
AtlasTextureKind::Path => &mut lock.path_textures,
|
||||
// AtlasTextureKind::Path => &mut lock.path_textures,
|
||||
};
|
||||
for texture in textures {
|
||||
texture.clear();
|
||||
|
@ -131,7 +131,7 @@ impl DirectXAtlasState {
|
|||
let textures = match texture_kind {
|
||||
AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
|
||||
AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
|
||||
AtlasTextureKind::Path => &mut self.path_textures,
|
||||
// AtlasTextureKind::Path => &mut self.path_textures,
|
||||
};
|
||||
|
||||
textures
|
||||
|
@ -173,12 +173,11 @@ impl DirectXAtlasState {
|
|||
pixel_format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
bind_flag = D3D11_BIND_SHADER_RESOURCE;
|
||||
bytes_per_pixel = 4;
|
||||
}
|
||||
AtlasTextureKind::Path => {
|
||||
pixel_format = DXGI_FORMAT_R16_FLOAT;
|
||||
bind_flag = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||
bytes_per_pixel = 2;
|
||||
}
|
||||
} // AtlasTextureKind::Path => {
|
||||
// pixel_format = DXGI_FORMAT_R16_FLOAT;
|
||||
// bind_flag = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||
// bytes_per_pixel = 2;
|
||||
// }
|
||||
}
|
||||
let texture_desc = D3D11_TEXTURE2D_DESC {
|
||||
Width: size.width.0 as u32,
|
||||
|
@ -206,16 +205,16 @@ impl DirectXAtlasState {
|
|||
let textures = match kind {
|
||||
AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
|
||||
AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
|
||||
AtlasTextureKind::Path => &mut self.path_textures,
|
||||
// AtlasTextureKind::Path => &mut self.path_textures,
|
||||
};
|
||||
let rtv = match kind {
|
||||
AtlasTextureKind::Path => unsafe {
|
||||
let mut view: Option<ID3D11RenderTargetView> = None;
|
||||
self.device
|
||||
.CreateRenderTargetView(&texture, None, Some(&mut view))
|
||||
.unwrap();
|
||||
[view]
|
||||
},
|
||||
// AtlasTextureKind::Path => unsafe {
|
||||
// let mut view: Option<ID3D11RenderTargetView> = None;
|
||||
// self.device
|
||||
// .CreateRenderTargetView(&texture, None, Some(&mut view))
|
||||
// .unwrap();
|
||||
// [view]
|
||||
// },
|
||||
_ => [None],
|
||||
};
|
||||
let view = unsafe {
|
||||
|
@ -244,7 +243,7 @@ impl DirectXAtlasState {
|
|||
let textures = match id.kind {
|
||||
crate::AtlasTextureKind::Monochrome => &self.monochrome_textures,
|
||||
crate::AtlasTextureKind::Polychrome => &self.polychrome_textures,
|
||||
crate::AtlasTextureKind::Path => &self.path_textures,
|
||||
// crate::AtlasTextureKind::Path => &self.path_textures,
|
||||
};
|
||||
&textures[id.index as usize]
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@ use std::{collections::HashMap, hash::BuildHasherDefault, sync::Arc};
|
|||
use ::util::ResultExt;
|
||||
use anyhow::{Context, Result};
|
||||
use collections::FxHasher;
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
use windows::Win32::Graphics::DirectComposition::*;
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// use windows::Win32::Graphics::DirectComposition::*;
|
||||
use windows::{
|
||||
Win32::{
|
||||
Foundation::HWND,
|
||||
Foundation::{HMODULE, HWND},
|
||||
Graphics::{
|
||||
Direct3D::*,
|
||||
Direct3D11::*,
|
||||
|
@ -41,8 +41,8 @@ struct DirectXContext {
|
|||
swap_chain: IDXGISwapChain1,
|
||||
back_buffer: [Option<ID3D11RenderTargetView>; 1],
|
||||
viewport: [D3D11_VIEWPORT; 1],
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
direct_composition: DirectComposition,
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// direct_composition: DirectComposition,
|
||||
}
|
||||
|
||||
struct DirectXRenderPipelines {
|
||||
|
@ -62,12 +62,12 @@ struct DirectXGlobalElements {
|
|||
blend_state_for_pr: ID3D11BlendState,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
struct DirectComposition {
|
||||
comp_device: IDCompositionDevice,
|
||||
comp_target: IDCompositionTarget,
|
||||
comp_visual: IDCompositionVisual,
|
||||
}
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// struct DirectComposition {
|
||||
// comp_device: IDCompositionDevice,
|
||||
// comp_target: IDCompositionTarget,
|
||||
// comp_visual: IDCompositionVisual,
|
||||
// }
|
||||
|
||||
impl DirectXDevices {
|
||||
pub(crate) fn new() -> Result<Self> {
|
||||
|
@ -91,17 +91,17 @@ impl DirectXDevices {
|
|||
}
|
||||
|
||||
impl DirectXRenderer {
|
||||
pub(crate) fn new(devices: DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> {
|
||||
pub(crate) fn new(devices: &DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> {
|
||||
let atlas = Arc::new(DirectXAtlas::new(
|
||||
devices.device.clone(),
|
||||
devices.device_context.clone(),
|
||||
));
|
||||
let context = DirectXContext::new(&devices, hwnd, transparent)?;
|
||||
let context = DirectXContext::new(devices, hwnd, transparent)?;
|
||||
let globals = DirectXGlobalElements::new(&devices.device)?;
|
||||
let pipelines = DirectXRenderPipelines::new(&devices.device)?;
|
||||
Ok(DirectXRenderer {
|
||||
atlas,
|
||||
devices,
|
||||
devices: devices.clone(),
|
||||
context,
|
||||
globals,
|
||||
pipelines,
|
||||
|
@ -110,7 +110,7 @@ impl DirectXRenderer {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn spirite_atlas(&self) -> Arc<dyn PlatformAtlas> {
|
||||
pub(crate) fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas> {
|
||||
self.atlas.clone()
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ impl DirectXRenderer {
|
|||
scene.polychrome_sprites.len(),
|
||||
scene.surfaces.len(),))?;
|
||||
}
|
||||
unsafe { self.context.swap_chain.Present(0, 0) }.ok()?;
|
||||
unsafe { self.context.swap_chain.Present(0, DXGI_PRESENT(0)) }.ok()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ impl DirectXRenderer {
|
|||
new_size.width.0 as u32,
|
||||
new_size.height.0 as u32,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
0,
|
||||
DXGI_SWAP_CHAIN_FLAG(0),
|
||||
)?;
|
||||
}
|
||||
let backbuffer = set_render_target_view(
|
||||
|
@ -183,32 +183,32 @@ impl DirectXRenderer {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
pub(crate) fn update_transparency(
|
||||
&mut self,
|
||||
background_appearance: WindowBackgroundAppearance,
|
||||
) -> Result<()> {
|
||||
// We only support setting `Transparent` and `Opaque` for now.
|
||||
match background_appearance {
|
||||
WindowBackgroundAppearance::Opaque => {
|
||||
if self.transparent {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Set opaque backgroud from transparent background, a restart is required. Or, you can open a new window."
|
||||
));
|
||||
}
|
||||
}
|
||||
WindowBackgroundAppearance::Transparent | WindowBackgroundAppearance::Blurred => {
|
||||
if !self.transparent {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Set transparent backgroud from opaque background, a restart is required. Or, you can open a new window."
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// pub(crate) fn update_transparency(
|
||||
// &mut self,
|
||||
// background_appearance: WindowBackgroundAppearance,
|
||||
// ) -> Result<()> {
|
||||
// // We only support setting `Transparent` and `Opaque` for now.
|
||||
// match background_appearance {
|
||||
// WindowBackgroundAppearance::Opaque => {
|
||||
// if self.transparent {
|
||||
// return Err(anyhow::anyhow!(
|
||||
// "Set opaque backgroud from transparent background, a restart is required. Or, you can open a new window."
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
// WindowBackgroundAppearance::Transparent | WindowBackgroundAppearance::Blurred => {
|
||||
// if !self.transparent {
|
||||
// return Err(anyhow::anyhow!(
|
||||
// "Set transparent backgroud from opaque background, a restart is required. Or, you can open a new window."
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[cfg(feature = "enable-renderdoc")]
|
||||
// #[cfg(feature = "enable-renderdoc")]
|
||||
pub(crate) fn update_transparency(
|
||||
&mut self,
|
||||
background_appearance: WindowBackgroundAppearance,
|
||||
|
@ -280,77 +280,78 @@ impl DirectXRenderer {
|
|||
&mut self,
|
||||
paths: &[Path<ScaledPixels>],
|
||||
) -> Option<HashMap<PathId, AtlasTile>> {
|
||||
self.atlas.clear_textures(AtlasTextureKind::Path);
|
||||
// self.atlas.clear_textures(AtlasTextureKind::Path);
|
||||
|
||||
let mut tiles = HashMap::default();
|
||||
let mut vertices_by_texture_id: HashMap<
|
||||
AtlasTextureId,
|
||||
Vec<PathVertex<ScaledPixels>>,
|
||||
BuildHasherDefault<FxHasher>,
|
||||
> = HashMap::default();
|
||||
for path in paths {
|
||||
let clipped_bounds = path.bounds.intersect(&path.content_mask.bounds);
|
||||
// let mut tiles = HashMap::default();
|
||||
// let mut vertices_by_texture_id: HashMap<
|
||||
// AtlasTextureId,
|
||||
// Vec<PathVertex<ScaledPixels>>,
|
||||
// BuildHasherDefault<FxHasher>,
|
||||
// > = HashMap::default();
|
||||
// for path in paths {
|
||||
// let clipped_bounds = path.bounds.intersect(&path.content_mask.bounds);
|
||||
|
||||
let tile = self
|
||||
.atlas
|
||||
.allocate(clipped_bounds.size.map(Into::into), AtlasTextureKind::Path)?;
|
||||
vertices_by_texture_id
|
||||
.entry(tile.texture_id)
|
||||
.or_insert(Vec::new())
|
||||
.extend(path.vertices.iter().map(|vertex| PathVertex {
|
||||
xy_position: vertex.xy_position - clipped_bounds.origin
|
||||
+ tile.bounds.origin.map(Into::into),
|
||||
content_mask: ContentMask {
|
||||
bounds: tile.bounds.map(Into::into),
|
||||
},
|
||||
}));
|
||||
tiles.insert(path.id, tile);
|
||||
}
|
||||
// let tile = self
|
||||
// .atlas
|
||||
// .allocate(clipped_bounds.size.map(Into::into), AtlasTextureKind::Path)?;
|
||||
// vertices_by_texture_id
|
||||
// .entry(tile.texture_id)
|
||||
// .or_insert(Vec::new())
|
||||
// .extend(path.vertices.iter().map(|vertex| PathVertex {
|
||||
// xy_position: vertex.xy_position - clipped_bounds.origin
|
||||
// + tile.bounds.origin.map(Into::into),
|
||||
// content_mask: ContentMask {
|
||||
// bounds: tile.bounds.map(Into::into),
|
||||
// },
|
||||
// }));
|
||||
// tiles.insert(path.id, tile);
|
||||
// }
|
||||
|
||||
for (texture_id, vertices) in vertices_by_texture_id {
|
||||
let (texture_size, rtv) = self.atlas.get_texture_drawing_info(texture_id);
|
||||
let viewport = [D3D11_VIEWPORT {
|
||||
TopLeftX: 0.0,
|
||||
TopLeftY: 0.0,
|
||||
Width: texture_size.width,
|
||||
Height: texture_size.height,
|
||||
MinDepth: 0.0,
|
||||
MaxDepth: 1.0,
|
||||
}];
|
||||
pre_draw(
|
||||
&self.devices.device_context,
|
||||
&self.globals.global_params_buffer,
|
||||
&viewport,
|
||||
&rtv,
|
||||
[0.0, 0.0, 0.0, 1.0],
|
||||
&self.globals.blend_state_for_pr,
|
||||
)
|
||||
.log_err()?;
|
||||
update_buffer_capacity(
|
||||
&self.pipelines.path_raster_pipeline,
|
||||
std::mem::size_of::<PathVertex<ScaledPixels>>(),
|
||||
vertices.len(),
|
||||
&self.devices.device,
|
||||
)
|
||||
.map(|input| update_pipeline(&mut self.pipelines.path_raster_pipeline, input));
|
||||
update_buffer(
|
||||
&self.devices.device_context,
|
||||
&self.pipelines.path_raster_pipeline.buffer,
|
||||
&vertices,
|
||||
)
|
||||
.log_err()?;
|
||||
draw_normal(
|
||||
&self.devices.device_context,
|
||||
&self.pipelines.path_raster_pipeline,
|
||||
&viewport,
|
||||
&self.globals.global_params_buffer,
|
||||
D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
|
||||
vertices.len() as u32,
|
||||
1,
|
||||
)
|
||||
.log_err()?;
|
||||
}
|
||||
Some(tiles)
|
||||
// for (texture_id, vertices) in vertices_by_texture_id {
|
||||
// let (texture_size, rtv) = self.atlas.get_texture_drawing_info(texture_id);
|
||||
// let viewport = [D3D11_VIEWPORT {
|
||||
// TopLeftX: 0.0,
|
||||
// TopLeftY: 0.0,
|
||||
// Width: texture_size.width,
|
||||
// Height: texture_size.height,
|
||||
// MinDepth: 0.0,
|
||||
// MaxDepth: 1.0,
|
||||
// }];
|
||||
// pre_draw(
|
||||
// &self.devices.device_context,
|
||||
// &self.globals.global_params_buffer,
|
||||
// &viewport,
|
||||
// &rtv,
|
||||
// [0.0, 0.0, 0.0, 1.0],
|
||||
// &self.globals.blend_state_for_pr,
|
||||
// )
|
||||
// .log_err()?;
|
||||
// update_buffer_capacity(
|
||||
// &self.pipelines.path_raster_pipeline,
|
||||
// std::mem::size_of::<PathVertex<ScaledPixels>>(),
|
||||
// vertices.len(),
|
||||
// &self.devices.device,
|
||||
// )
|
||||
// .map(|input| update_pipeline(&mut self.pipelines.path_raster_pipeline, input));
|
||||
// update_buffer(
|
||||
// &self.devices.device_context,
|
||||
// &self.pipelines.path_raster_pipeline.buffer,
|
||||
// &vertices,
|
||||
// )
|
||||
// .log_err()?;
|
||||
// draw_normal(
|
||||
// &self.devices.device_context,
|
||||
// &self.pipelines.path_raster_pipeline,
|
||||
// &viewport,
|
||||
// &self.globals.global_params_buffer,
|
||||
// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
|
||||
// vertices.len() as u32,
|
||||
// 1,
|
||||
// )
|
||||
// .log_err()?;
|
||||
// }
|
||||
// Some(tiles)
|
||||
None
|
||||
}
|
||||
|
||||
fn draw_paths(
|
||||
|
@ -358,43 +359,43 @@ impl DirectXRenderer {
|
|||
paths: &[Path<ScaledPixels>],
|
||||
path_tiles: &HashMap<PathId, AtlasTile>,
|
||||
) -> Result<()> {
|
||||
if paths.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
for path in paths {
|
||||
let tile = &path_tiles[&path.id];
|
||||
let texture_view = self.atlas.get_texture_view(tile.texture_id);
|
||||
let origin = path.bounds.intersect(&path.content_mask.bounds).origin;
|
||||
let sprites = [PathSprite {
|
||||
bounds: Bounds {
|
||||
origin: origin.map(|p| p.floor()),
|
||||
size: tile.bounds.size.map(Into::into),
|
||||
},
|
||||
color: path.color,
|
||||
tile: (*tile).clone(),
|
||||
}];
|
||||
update_buffer_capacity(
|
||||
&self.pipelines.paths_pipeline,
|
||||
std::mem::size_of::<PathSprite>(),
|
||||
1,
|
||||
&self.devices.device,
|
||||
)
|
||||
.map(|input| update_pipeline(&mut self.pipelines.paths_pipeline, input));
|
||||
update_buffer(
|
||||
&self.devices.device_context,
|
||||
&self.pipelines.paths_pipeline.buffer,
|
||||
&sprites,
|
||||
)?;
|
||||
draw_with_texture(
|
||||
&self.devices.device_context,
|
||||
&self.pipelines.paths_pipeline,
|
||||
&texture_view,
|
||||
&self.context.viewport,
|
||||
&self.globals.global_params_buffer,
|
||||
&self.globals.sampler,
|
||||
1,
|
||||
)?;
|
||||
}
|
||||
// if paths.is_empty() {
|
||||
// return Ok(());
|
||||
// }
|
||||
// for path in paths {
|
||||
// let tile = &path_tiles[&path.id];
|
||||
// let texture_view = self.atlas.get_texture_view(tile.texture_id);
|
||||
// let origin = path.bounds.intersect(&path.content_mask.bounds).origin;
|
||||
// let sprites = [PathSprite {
|
||||
// bounds: Bounds {
|
||||
// origin: origin.map(|p| p.floor()),
|
||||
// size: tile.bounds.size.map(Into::into),
|
||||
// },
|
||||
// color: path.color,
|
||||
// tile: (*tile).clone(),
|
||||
// }];
|
||||
// update_buffer_capacity(
|
||||
// &self.pipelines.paths_pipeline,
|
||||
// std::mem::size_of::<PathSprite>(),
|
||||
// 1,
|
||||
// &self.devices.device,
|
||||
// )
|
||||
// .map(|input| update_pipeline(&mut self.pipelines.paths_pipeline, input));
|
||||
// update_buffer(
|
||||
// &self.devices.device_context,
|
||||
// &self.pipelines.paths_pipeline.buffer,
|
||||
// &sprites,
|
||||
// )?;
|
||||
// draw_with_texture(
|
||||
// &self.devices.device_context,
|
||||
// &self.pipelines.paths_pipeline,
|
||||
// &texture_view,
|
||||
// &self.context.viewport,
|
||||
// &self.globals.global_params_buffer,
|
||||
// &self.globals.sampler,
|
||||
// 1,
|
||||
// )?;
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -489,7 +490,7 @@ impl DirectXRenderer {
|
|||
)
|
||||
}
|
||||
|
||||
fn draw_surfaces(&mut self, surfaces: &[Surface]) -> Result<()> {
|
||||
fn draw_surfaces(&mut self, surfaces: &[PaintSurface]) -> Result<()> {
|
||||
if surfaces.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -499,15 +500,15 @@ impl DirectXRenderer {
|
|||
|
||||
impl DirectXContext {
|
||||
pub fn new(devices: &DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> {
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, transparent)?;
|
||||
#[cfg(feature = "enable-renderdoc")]
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, transparent)?;
|
||||
// #[cfg(feature = "enable-renderdoc")]
|
||||
let swap_chain =
|
||||
create_swap_chain_default(&devices.dxgi_factory, &devices.device, hwnd, transparent)?;
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?;
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
direct_composition.set_swap_chain(&swap_chain)?;
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?;
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// direct_composition.set_swap_chain(&swap_chain)?;
|
||||
let back_buffer = [Some(set_render_target_view(
|
||||
&swap_chain,
|
||||
&devices.device,
|
||||
|
@ -520,8 +521,8 @@ impl DirectXContext {
|
|||
swap_chain,
|
||||
back_buffer,
|
||||
viewport,
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
direct_composition,
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// direct_composition,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -590,29 +591,29 @@ impl DirectXRenderPipelines {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
impl DirectComposition {
|
||||
pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result<Self> {
|
||||
let comp_device = get_comp_device(&dxgi_device)?;
|
||||
let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?;
|
||||
let comp_visual = unsafe { comp_device.CreateVisual() }?;
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// impl DirectComposition {
|
||||
// pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result<Self> {
|
||||
// let comp_device = get_comp_device(&dxgi_device)?;
|
||||
// let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?;
|
||||
// let comp_visual = unsafe { comp_device.CreateVisual() }?;
|
||||
|
||||
Ok(Self {
|
||||
comp_device,
|
||||
comp_target,
|
||||
comp_visual,
|
||||
})
|
||||
}
|
||||
// Ok(Self {
|
||||
// comp_device,
|
||||
// comp_target,
|
||||
// comp_visual,
|
||||
// })
|
||||
// }
|
||||
|
||||
pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> {
|
||||
unsafe {
|
||||
self.comp_visual.SetContent(swap_chain)?;
|
||||
self.comp_target.SetRoot(&self.comp_visual)?;
|
||||
self.comp_device.Commit()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
// pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> {
|
||||
// unsafe {
|
||||
// self.comp_visual.SetContent(swap_chain)?;
|
||||
// self.comp_target.SetRoot(&self.comp_visual)?;
|
||||
// self.comp_device.Commit()?;
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
// }
|
||||
|
||||
impl DirectXGlobalElements {
|
||||
pub fn new(device: &ID3D11Device) -> Result<Self> {
|
||||
|
@ -726,7 +727,7 @@ fn get_device(
|
|||
D3D11CreateDevice(
|
||||
adapter,
|
||||
D3D_DRIVER_TYPE_UNKNOWN,
|
||||
None,
|
||||
HMODULE::default(),
|
||||
device_flags,
|
||||
Some(&[D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1]),
|
||||
D3D11_SDK_VERSION,
|
||||
|
@ -737,10 +738,10 @@ fn get_device(
|
|||
})
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enable-renderdoc"))]
|
||||
fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result<IDCompositionDevice> {
|
||||
Ok(unsafe { DCompositionCreateDevice(dxgi_device)? })
|
||||
}
|
||||
// #[cfg(not(feature = "enable-renderdoc"))]
|
||||
// fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result<IDCompositionDevice> {
|
||||
// Ok(unsafe { DCompositionCreateDevice(dxgi_device)? })
|
||||
// }
|
||||
|
||||
fn create_swap_chain(
|
||||
dxgi_factory: &IDXGIFactory6,
|
||||
|
@ -772,7 +773,7 @@ fn create_swap_chain(
|
|||
Ok(unsafe { dxgi_factory.CreateSwapChainForComposition(device, &desc, None)? })
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable-renderdoc")]
|
||||
// #[cfg(feature = "enable-renderdoc")]
|
||||
fn create_swap_chain_default(
|
||||
dxgi_factory: &IDXGIFactory6,
|
||||
device: &ID3D11Device,
|
||||
|
|
|
@ -181,11 +181,13 @@ fn handle_size_msg(
|
|||
let new_size = size(DevicePixels(width), DevicePixels(height));
|
||||
let scale_factor = lock.scale_factor;
|
||||
if lock.restore_from_minimized.is_some() {
|
||||
lock.renderer
|
||||
.update_drawable_size_even_if_unchanged(new_size);
|
||||
// lock.renderer
|
||||
// .update_drawable_size_even_if_unchanged(new_size);
|
||||
lock.renderer.resize(new_size).log_err();
|
||||
lock.callbacks.request_frame = lock.restore_from_minimized.take();
|
||||
} else {
|
||||
lock.renderer.update_drawable_size(new_size);
|
||||
// lock.renderer.update_drawable_size(new_size);
|
||||
lock.renderer.resize(new_size).log_err();
|
||||
}
|
||||
let new_size = new_size.to_pixels(scale_factor);
|
||||
lock.logical_size = new_size;
|
||||
|
|
|
@ -34,7 +34,8 @@ pub(crate) struct WindowsPlatform {
|
|||
state: RefCell<WindowsPlatformState>,
|
||||
raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
|
||||
// The below members will never change throughout the entire lifecycle of the app.
|
||||
gpu_context: BladeContext,
|
||||
// gpu_context: BladeContext,
|
||||
directx_devices: DirectXDevices,
|
||||
icon: HICON,
|
||||
main_receiver: flume::Receiver<Runnable>,
|
||||
background_executor: BackgroundExecutor,
|
||||
|
@ -111,13 +112,14 @@ impl WindowsPlatform {
|
|||
let icon = load_icon().unwrap_or_default();
|
||||
let state = RefCell::new(WindowsPlatformState::new());
|
||||
let raw_window_handles = RwLock::new(SmallVec::new());
|
||||
let gpu_context = BladeContext::new().context("Unable to init GPU context")?;
|
||||
// let gpu_context = BladeContext::new().context("Unable to init GPU context")?;
|
||||
let directx_devices = DirectXDevices::new().context("Unable to init directx devices.")?;
|
||||
let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
|
||||
|
||||
Ok(Self {
|
||||
state,
|
||||
raw_window_handles,
|
||||
gpu_context,
|
||||
directx_devices,
|
||||
icon,
|
||||
main_receiver,
|
||||
background_executor,
|
||||
|
@ -459,7 +461,7 @@ impl Platform for WindowsPlatform {
|
|||
handle,
|
||||
options,
|
||||
self.generate_creation_info(),
|
||||
&self.gpu_context,
|
||||
&self.directx_devices,
|
||||
)?;
|
||||
let handle = window.get_raw_handle();
|
||||
self.raw_window_handles.write().push(handle);
|
||||
|
|
676
crates/gpui/src/platform/windows/shaders.hlsl
Normal file
676
crates/gpui/src/platform/windows/shaders.hlsl
Normal file
|
@ -0,0 +1,676 @@
|
|||
cbuffer GlobalParams: register(b0) {
|
||||
float2 global_viewport_size;
|
||||
uint2 _global_pad;
|
||||
};
|
||||
|
||||
Texture2D<float4> t_sprite: register(t0);
|
||||
SamplerState s_sprite: register(s0);
|
||||
|
||||
struct Bounds {
|
||||
float2 origin;
|
||||
float2 size;
|
||||
};
|
||||
|
||||
struct Corners {
|
||||
float top_left;
|
||||
float top_right;
|
||||
float bottom_right;
|
||||
float bottom_left;
|
||||
};
|
||||
|
||||
struct Edges {
|
||||
float top;
|
||||
float right;
|
||||
float bottom;
|
||||
float left;
|
||||
};
|
||||
|
||||
struct Hsla {
|
||||
float h;
|
||||
float s;
|
||||
float l;
|
||||
float a;
|
||||
};
|
||||
|
||||
struct AtlasTextureId {
|
||||
uint index;
|
||||
uint kind;
|
||||
};
|
||||
|
||||
struct AtlasBounds {
|
||||
int2 origin;
|
||||
int2 size;
|
||||
};
|
||||
|
||||
struct AtlasTile {
|
||||
AtlasTextureId texture_id;
|
||||
uint tile_id;
|
||||
uint padding;
|
||||
AtlasBounds bounds;
|
||||
};
|
||||
|
||||
struct TransformationMatrix {
|
||||
float2x2 rotation_scale;
|
||||
float2 translation;
|
||||
};
|
||||
|
||||
static const float M_PI_F = 3.141592653f;
|
||||
static const float3 GRAYSCALE_FACTORS = float3(0.2126f, 0.7152f, 0.0722f);
|
||||
|
||||
float4 to_device_position(float2 unit_vertex, Bounds bounds) {
|
||||
float2 position = unit_vertex * bounds.size + bounds.origin;
|
||||
float2 device_position = position / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
|
||||
return float4(device_position, 0., 1.);
|
||||
}
|
||||
|
||||
float4 distance_from_clip_rect(float2 unit_vertex, Bounds bounds, Bounds clip_bounds) {
|
||||
float2 position = unit_vertex * bounds.size + bounds.origin;
|
||||
return float4(position.x - clip_bounds.origin.x,
|
||||
clip_bounds.origin.x + clip_bounds.size.x - position.x,
|
||||
position.y - clip_bounds.origin.y,
|
||||
clip_bounds.origin.y + clip_bounds.size.y - position.y);
|
||||
}
|
||||
|
||||
float4 hsla_to_rgba(Hsla hsla) {
|
||||
float h = hsla.h * 6.0; // Now, it's an angle but scaled in [0, 6) range
|
||||
float s = hsla.s;
|
||||
float l = hsla.l;
|
||||
float a = hsla.a;
|
||||
|
||||
float c = (1.0 - abs(2.0 * l - 1.0)) * s;
|
||||
float x = c * (1.0 - abs(fmod(h, 2.0) - 1.0));
|
||||
float m = l - c / 2.0;
|
||||
|
||||
float r = 0.0;
|
||||
float g = 0.0;
|
||||
float b = 0.0;
|
||||
|
||||
if (h >= 0.0 && h < 1.0) {
|
||||
r = c;
|
||||
g = x;
|
||||
b = 0.0;
|
||||
} else if (h >= 1.0 && h < 2.0) {
|
||||
r = x;
|
||||
g = c;
|
||||
b = 0.0;
|
||||
} else if (h >= 2.0 && h < 3.0) {
|
||||
r = 0.0;
|
||||
g = c;
|
||||
b = x;
|
||||
} else if (h >= 3.0 && h < 4.0) {
|
||||
r = 0.0;
|
||||
g = x;
|
||||
b = c;
|
||||
} else if (h >= 4.0 && h < 5.0) {
|
||||
r = x;
|
||||
g = 0.0;
|
||||
b = c;
|
||||
} else {
|
||||
r = c;
|
||||
g = 0.0;
|
||||
b = x;
|
||||
}
|
||||
|
||||
float4 rgba;
|
||||
rgba.x = (r + m);
|
||||
rgba.y = (g + m);
|
||||
rgba.z = (b + m);
|
||||
rgba.w = a;
|
||||
return rgba;
|
||||
}
|
||||
|
||||
// This approximates the error function, needed for the gaussian integral
|
||||
float2 erf(float2 x) {
|
||||
float2 s = sign(x);
|
||||
float2 a = abs(x);
|
||||
x = 1. + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
|
||||
x *= x;
|
||||
return s - s / (x * x);
|
||||
}
|
||||
|
||||
float blur_along_x(float x, float y, float sigma, float corner, float2 half_size) {
|
||||
float delta = min(half_size.y - corner - abs(y), 0.);
|
||||
float curved = half_size.x - corner + sqrt(max(0., corner * corner - delta * delta));
|
||||
float2 integral = 0.5 + 0.5 * erf((x + float2(-curved, curved)) * (sqrt(0.5) / sigma));
|
||||
return integral.y - integral.x;
|
||||
}
|
||||
|
||||
// A standard gaussian function, used for weighting samples
|
||||
float gaussian(float x, float sigma) {
|
||||
return exp(-(x * x) / (2. * sigma * sigma)) / (sqrt(2. * M_PI_F) * sigma);
|
||||
}
|
||||
|
||||
float4 over(float4 below, float4 above) {
|
||||
float4 result;
|
||||
float alpha = above.a + below.a * (1.0 - above.a);
|
||||
result.rgb = (above.rgb * above.a + below.rgb * below.a * (1.0 - above.a)) / alpha;
|
||||
result.a = alpha;
|
||||
return result;
|
||||
}
|
||||
|
||||
float2 to_tile_position(float2 unit_vertex, AtlasTile tile) {
|
||||
float2 atlas_size;
|
||||
t_sprite.GetDimensions(atlas_size.x, atlas_size.y);
|
||||
return (float2(tile.bounds.origin) + unit_vertex * float2(tile.bounds.size)) / atlas_size;
|
||||
}
|
||||
|
||||
float4 to_device_position_transformed(float2 unit_vertex, Bounds bounds,
|
||||
TransformationMatrix transformation) {
|
||||
float2 position = unit_vertex * bounds.size + bounds.origin;
|
||||
float2 transformed = mul(position, transformation.rotation_scale) + transformation.translation;
|
||||
float2 device_position = transformed / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
|
||||
return float4(device_position, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float quad_sdf(float2 pt, Bounds bounds, Corners corner_radii) {
|
||||
float2 half_size = bounds.size / 2.;
|
||||
float2 center = bounds.origin + half_size;
|
||||
float2 center_to_point = pt - center;
|
||||
float corner_radius;
|
||||
if (center_to_point.x < 0.) {
|
||||
if (center_to_point.y < 0.) {
|
||||
corner_radius = corner_radii.top_left;
|
||||
} else {
|
||||
corner_radius = corner_radii.bottom_left;
|
||||
}
|
||||
} else {
|
||||
if (center_to_point.y < 0.) {
|
||||
corner_radius = corner_radii.top_right;
|
||||
} else {
|
||||
corner_radius = corner_radii.bottom_right;
|
||||
}
|
||||
}
|
||||
|
||||
float2 rounded_edge_to_point = abs(center_to_point) - half_size + corner_radius;
|
||||
float distance =
|
||||
length(max(0., rounded_edge_to_point)) +
|
||||
min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) -
|
||||
corner_radius;
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Shadows
|
||||
**
|
||||
*/
|
||||
|
||||
struct ShadowVertexOutput {
|
||||
float4 position: SV_Position;
|
||||
float4 color: COLOR;
|
||||
uint shadow_id: FLAT;
|
||||
float4 clip_distance: SV_ClipDistance;
|
||||
};
|
||||
|
||||
struct ShadowFragmentInput {
|
||||
float4 position: SV_Position;
|
||||
float4 color: COLOR;
|
||||
uint shadow_id: FLAT;
|
||||
};
|
||||
|
||||
struct Shadow {
|
||||
uint order;
|
||||
float blur_radius;
|
||||
Bounds bounds;
|
||||
Corners corner_radii;
|
||||
Bounds content_mask;
|
||||
Hsla color;
|
||||
};
|
||||
|
||||
StructuredBuffer<Shadow> shadows: register(t1);
|
||||
|
||||
ShadowVertexOutput shadow_vertex(uint vertex_id: SV_VertexID, uint shadow_id: SV_InstanceID) {
|
||||
float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
|
||||
Shadow shadow = shadows[shadow_id];
|
||||
|
||||
float margin = 3.0 * shadow.blur_radius;
|
||||
Bounds bounds = shadow.bounds;
|
||||
bounds.origin -= margin;
|
||||
bounds.size += 2.0 * margin;
|
||||
|
||||
float4 device_position = to_device_position(unit_vertex, bounds);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, bounds, shadow.content_mask);
|
||||
float4 color = hsla_to_rgba(shadow.color);
|
||||
|
||||
ShadowVertexOutput output;
|
||||
output.position = device_position;
|
||||
output.color = color;
|
||||
output.shadow_id = shadow_id;
|
||||
output.clip_distance = clip_distance;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 shadow_fragment(ShadowFragmentInput input): SV_TARGET {
|
||||
Shadow shadow = shadows[input.shadow_id];
|
||||
|
||||
float2 half_size = shadow.bounds.size / 2.;
|
||||
float2 center = shadow.bounds.origin + half_size;
|
||||
float2 point0 = input.position.xy - center;
|
||||
float corner_radius;
|
||||
if (point0.x < 0.) {
|
||||
if (point0.y < 0.) {
|
||||
corner_radius = shadow.corner_radii.top_left;
|
||||
} else {
|
||||
corner_radius = shadow.corner_radii.bottom_left;
|
||||
}
|
||||
} else {
|
||||
if (point0.y < 0.) {
|
||||
corner_radius = shadow.corner_radii.top_right;
|
||||
} else {
|
||||
corner_radius = shadow.corner_radii.bottom_right;
|
||||
}
|
||||
}
|
||||
|
||||
// The signal is only non-zero in a limited range, so don't waste samples
|
||||
float low = point0.y - half_size.y;
|
||||
float high = point0.y + half_size.y;
|
||||
float start = clamp(-3. * shadow.blur_radius, low, high);
|
||||
float end = clamp(3. * shadow.blur_radius, low, high);
|
||||
|
||||
// Accumulate samples (we can get away with surprisingly few samples)
|
||||
float step = (end - start) / 4.;
|
||||
float y = start + step * 0.5;
|
||||
float alpha = 0.;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
alpha += blur_along_x(point0.x, point0.y - y, shadow.blur_radius,
|
||||
corner_radius, half_size) *
|
||||
gaussian(y, shadow.blur_radius) * step;
|
||||
y += step;
|
||||
}
|
||||
|
||||
return input.color * float4(1., 1., 1., alpha);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Quads
|
||||
**
|
||||
*/
|
||||
|
||||
struct Quad {
|
||||
uint order;
|
||||
uint pad;
|
||||
Bounds bounds;
|
||||
Bounds content_mask;
|
||||
Hsla background;
|
||||
Hsla border_color;
|
||||
Corners corner_radii;
|
||||
Edges border_widths;
|
||||
};
|
||||
|
||||
struct QuadVertexOutput {
|
||||
float4 position: SV_Position;
|
||||
float4 background_color: COLOR0;
|
||||
float4 border_color: COLOR1;
|
||||
uint quad_id: FLAT;
|
||||
float4 clip_distance: SV_ClipDistance;
|
||||
};
|
||||
|
||||
struct QuadFragmentInput {
|
||||
float4 position: SV_Position;
|
||||
float4 background_color: COLOR0;
|
||||
float4 border_color: COLOR1;
|
||||
uint quad_id: FLAT;
|
||||
};
|
||||
|
||||
StructuredBuffer<Quad> quads: register(t1);
|
||||
|
||||
QuadVertexOutput quad_vertex(uint vertex_id: SV_VertexID, uint quad_id: SV_InstanceID) {
|
||||
float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
|
||||
Quad quad = quads[quad_id];
|
||||
float4 device_position = to_device_position(unit_vertex, quad.bounds);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, quad.bounds, quad.content_mask);
|
||||
float4 background_color = hsla_to_rgba(quad.background);
|
||||
float4 border_color = hsla_to_rgba(quad.border_color);
|
||||
|
||||
QuadVertexOutput output;
|
||||
output.position = device_position;
|
||||
output.background_color = background_color;
|
||||
output.border_color = border_color;
|
||||
output.quad_id = quad_id;
|
||||
output.clip_distance = clip_distance;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 quad_fragment(QuadFragmentInput input): SV_Target {
|
||||
Quad quad = quads[input.quad_id];
|
||||
|
||||
// Fast path when the quad is not rounded and doesn't have any border.
|
||||
if (quad.corner_radii.top_left == 0. && quad.corner_radii.bottom_left == 0. &&
|
||||
quad.corner_radii.top_right == 0. &&
|
||||
quad.corner_radii.bottom_right == 0. && quad.border_widths.top == 0. &&
|
||||
quad.border_widths.left == 0. && quad.border_widths.right == 0. &&
|
||||
quad.border_widths.bottom == 0.) {
|
||||
return input.background_color;
|
||||
}
|
||||
|
||||
float2 half_size = quad.bounds.size / 2.;
|
||||
float2 center = quad.bounds.origin + half_size;
|
||||
float2 center_to_point = input.position.xy - center;
|
||||
float corner_radius;
|
||||
if (center_to_point.x < 0.) {
|
||||
if (center_to_point.y < 0.) {
|
||||
corner_radius = quad.corner_radii.top_left;
|
||||
} else {
|
||||
corner_radius = quad.corner_radii.bottom_left;
|
||||
}
|
||||
} else {
|
||||
if (center_to_point.y < 0.) {
|
||||
corner_radius = quad.corner_radii.top_right;
|
||||
} else {
|
||||
corner_radius = quad.corner_radii.bottom_right;
|
||||
}
|
||||
}
|
||||
|
||||
float2 rounded_edge_to_point = abs(center_to_point) - half_size + corner_radius;
|
||||
float distance =
|
||||
length(max(0., rounded_edge_to_point)) +
|
||||
min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y)) -
|
||||
corner_radius;
|
||||
|
||||
float vertical_border = center_to_point.x <= 0. ? quad.border_widths.left
|
||||
: quad.border_widths.right;
|
||||
float horizontal_border = center_to_point.y <= 0. ? quad.border_widths.top
|
||||
: quad.border_widths.bottom;
|
||||
float2 inset_size = half_size - corner_radius - float2(vertical_border, horizontal_border);
|
||||
float2 point_to_inset_corner = abs(center_to_point) - inset_size;
|
||||
float border_width;
|
||||
if (point_to_inset_corner.x < 0. && point_to_inset_corner.y < 0.) {
|
||||
border_width = 0.;
|
||||
} else if (point_to_inset_corner.y > point_to_inset_corner.x) {
|
||||
border_width = horizontal_border;
|
||||
} else {
|
||||
border_width = vertical_border;
|
||||
}
|
||||
|
||||
float4 color;
|
||||
if (border_width == 0.) {
|
||||
color = input.background_color;
|
||||
} else {
|
||||
float inset_distance = distance + border_width;
|
||||
// Blend the border on top of the background and then linearly interpolate
|
||||
// between the two as we slide inside the background.
|
||||
float4 blended_border = over(input.background_color, input.border_color);
|
||||
color = lerp(blended_border, input.background_color,
|
||||
saturate(0.5 - inset_distance));
|
||||
}
|
||||
|
||||
return color * float4(1., 1., 1., saturate(0.5 - distance));
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Path raster
|
||||
**
|
||||
*/
|
||||
|
||||
struct PathVertex {
|
||||
float2 xy_position;
|
||||
float2 st_position;
|
||||
Bounds content_mask;
|
||||
};
|
||||
|
||||
struct PathRasterizationOutput {
|
||||
float4 position: SV_Position;
|
||||
float2 st_position: TEXCOORD0;
|
||||
float4 clip_distances: SV_ClipDistance;
|
||||
};
|
||||
|
||||
struct PathRasterizationInput {
|
||||
float4 position: SV_Position;
|
||||
float2 st_position: TEXCOORD0;
|
||||
};
|
||||
|
||||
StructuredBuffer<PathVertex> path_vertices: register(t1);
|
||||
|
||||
PathRasterizationOutput path_rasterization_vertex(uint vertex_id: SV_VertexID) {
|
||||
PathVertex vertex = path_vertices[vertex_id];
|
||||
PathRasterizationOutput output;
|
||||
float2 device_position = vertex.xy_position / global_viewport_size * float2(2.0, -2.0) + float2(-1.0, 1.0);
|
||||
float2 tl = vertex.xy_position - vertex.content_mask.origin;
|
||||
float2 br = vertex.content_mask.origin + vertex.content_mask.size - vertex.xy_position;
|
||||
|
||||
output.position = float4(device_position, 0.0, 1.0);
|
||||
output.st_position = vertex.st_position;
|
||||
output.clip_distances = float4(tl.x, br.x, tl.y, br.y);
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 path_rasterization_fragment(PathRasterizationInput input): SV_Target {
|
||||
float2 dx = ddx(input.st_position);
|
||||
float2 dy = ddy(input.st_position);
|
||||
float2 gradient = float2((2. * input.st_position.x) * dx.x - dx.y,
|
||||
(2. * input.st_position.x) * dy.x - dy.y);
|
||||
float f = (input.st_position.x * input.st_position.x) - input.st_position.y;
|
||||
float distance = f / length(gradient);
|
||||
float alpha = saturate(0.5 - distance);
|
||||
return float4(alpha, 0., 0., 1.);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Paths
|
||||
**
|
||||
*/
|
||||
|
||||
struct PathSprite {
|
||||
Bounds bounds;
|
||||
Hsla color;
|
||||
AtlasTile tile;
|
||||
};
|
||||
|
||||
struct PathVertexOutput {
|
||||
float4 position: SV_Position;
|
||||
float2 tile_position: POSITION1;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
StructuredBuffer<PathSprite> path_sprites: register(t1);
|
||||
|
||||
PathVertexOutput paths_vertex(uint vertex_id: SV_VertexID, uint instance_id: SV_InstanceID) {
|
||||
float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
|
||||
PathSprite sprite = path_sprites[instance_id];
|
||||
// Don't apply content mask because it was already accounted for when rasterizing the path.
|
||||
|
||||
PathVertexOutput output;
|
||||
output.position = to_device_position(unit_vertex, sprite.bounds);
|
||||
output.tile_position = to_tile_position(unit_vertex, sprite.tile);
|
||||
output.color = hsla_to_rgba(sprite.color);
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 paths_fragment(PathVertexOutput input): SV_Target {
|
||||
float sample = t_sprite.Sample(s_sprite, input.tile_position).r;
|
||||
float mask = 1.0 - abs(1.0 - sample % 2.0);
|
||||
float4 color = input.color;
|
||||
color.a *= mask;
|
||||
return color;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Underlines
|
||||
**
|
||||
*/
|
||||
|
||||
struct Underline {
|
||||
uint order;
|
||||
uint pad;
|
||||
Bounds bounds;
|
||||
Bounds content_mask;
|
||||
Hsla color;
|
||||
float thickness;
|
||||
uint wavy;
|
||||
};
|
||||
|
||||
struct UnderlineVertexOutput {
|
||||
float4 position: SV_Position;
|
||||
float4 color: COLOR;
|
||||
uint underline_id: FLAT;
|
||||
float4 clip_distance: SV_ClipDistance;
|
||||
};
|
||||
|
||||
struct UnderlineFragmentInput {
|
||||
float4 position: SV_Position;
|
||||
float4 color: COLOR;
|
||||
uint underline_id: FLAT;
|
||||
};
|
||||
|
||||
StructuredBuffer<Underline> underlines: register(t1);
|
||||
|
||||
UnderlineVertexOutput underline_vertex(uint vertex_id: SV_VertexID, uint underline_id: SV_InstanceID) {
|
||||
float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
|
||||
Underline underline = underlines[underline_id];
|
||||
float4 device_position = to_device_position(unit_vertex, underline.bounds);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, underline.bounds,
|
||||
underline.content_mask);
|
||||
float4 color = hsla_to_rgba(underline.color);
|
||||
|
||||
UnderlineVertexOutput output;
|
||||
output.position = device_position;
|
||||
output.color = color;
|
||||
output.underline_id = underline_id;
|
||||
output.clip_distance = clip_distance;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 underline_fragment(UnderlineFragmentInput input): SV_Target {
|
||||
Underline underline = underlines[input.underline_id];
|
||||
if (underline.wavy) {
|
||||
float half_thickness = underline.thickness * 0.5;
|
||||
float2 origin =
|
||||
float2(underline.bounds.origin.x, underline.bounds.origin.y);
|
||||
float2 st = ((input.position.xy - origin) / underline.bounds.size.y) -
|
||||
float2(0., 0.5);
|
||||
float frequency = (M_PI_F * (3. * underline.thickness)) / 8.;
|
||||
float amplitude = 1. / (2. * underline.thickness);
|
||||
float sine = sin(st.x * frequency) * amplitude;
|
||||
float dSine = cos(st.x * frequency) * amplitude * frequency;
|
||||
float distance = (st.y - sine) / sqrt(1. + dSine * dSine);
|
||||
float distance_in_pixels = distance * underline.bounds.size.y;
|
||||
float distance_from_top_border = distance_in_pixels - half_thickness;
|
||||
float distance_from_bottom_border = distance_in_pixels + half_thickness;
|
||||
float alpha = saturate(
|
||||
0.5 - max(-distance_from_bottom_border, distance_from_top_border));
|
||||
return input.color * float4(1., 1., 1., alpha);
|
||||
} else {
|
||||
return input.color;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Monochrome sprites
|
||||
**
|
||||
*/
|
||||
|
||||
struct MonochromeSprite {
|
||||
uint order;
|
||||
uint pad;
|
||||
Bounds bounds;
|
||||
Bounds content_mask;
|
||||
Hsla color;
|
||||
AtlasTile tile;
|
||||
TransformationMatrix transformation;
|
||||
};
|
||||
|
||||
struct MonochromeSpriteVertexOutput {
|
||||
float4 position: SV_Position;
|
||||
float2 tile_position: POSITION;
|
||||
float4 color: COLOR;
|
||||
float4 clip_distance: SV_ClipDistance;
|
||||
};
|
||||
|
||||
struct MonochromeSpriteFragmentInput {
|
||||
float4 position: SV_Position;
|
||||
float2 tile_position: POSITION;
|
||||
float4 color: COLOR;
|
||||
};
|
||||
|
||||
StructuredBuffer<MonochromeSprite> mono_sprites: register(t1);
|
||||
|
||||
MonochromeSpriteVertexOutput monochrome_sprite_vertex(uint vertex_id: SV_VertexID, uint sprite_id: SV_InstanceID) {
|
||||
float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
|
||||
MonochromeSprite sprite = mono_sprites[sprite_id];
|
||||
float4 device_position =
|
||||
to_device_position_transformed(unit_vertex, sprite.bounds, sprite.transformation);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds, sprite.content_mask);
|
||||
float2 tile_position = to_tile_position(unit_vertex, sprite.tile);
|
||||
float4 color = hsla_to_rgba(sprite.color);
|
||||
|
||||
MonochromeSpriteVertexOutput output;
|
||||
output.position = device_position;
|
||||
output.tile_position = tile_position;
|
||||
output.color = color;
|
||||
output.clip_distance = clip_distance;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 monochrome_sprite_fragment(MonochromeSpriteFragmentInput input): SV_Target {
|
||||
float4 sample = t_sprite.Sample(s_sprite, input.tile_position);
|
||||
float4 color = input.color;
|
||||
color.a *= sample.a;
|
||||
return color;
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** Polychrome sprites
|
||||
**
|
||||
*/
|
||||
|
||||
struct PolychromeSprite {
|
||||
uint order;
|
||||
uint grayscale;
|
||||
Bounds bounds;
|
||||
Bounds content_mask;
|
||||
Corners corner_radii;
|
||||
AtlasTile tile;
|
||||
};
|
||||
|
||||
struct PolychromeSpriteVertexOutput {
|
||||
float4 position: SV_Position;
|
||||
float2 tile_position: POSITION;
|
||||
uint sprite_id: FLAT;
|
||||
float4 clip_distance: SV_ClipDistance;
|
||||
};
|
||||
|
||||
struct PolychromeSpriteFragmentInput {
|
||||
float4 position: SV_Position;
|
||||
float2 tile_position: POSITION;
|
||||
uint sprite_id: FLAT;
|
||||
};
|
||||
|
||||
StructuredBuffer<PolychromeSprite> poly_sprites: register(t1);
|
||||
|
||||
PolychromeSpriteVertexOutput polychrome_sprite_vertex(uint vertex_id: SV_VertexID, uint sprite_id: SV_InstanceID) {
|
||||
float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
|
||||
PolychromeSprite sprite = poly_sprites[sprite_id];
|
||||
float4 device_position = to_device_position(unit_vertex, sprite.bounds);
|
||||
float4 clip_distance = distance_from_clip_rect(unit_vertex, sprite.bounds,
|
||||
sprite.content_mask);
|
||||
float2 tile_position = to_tile_position(unit_vertex, sprite.tile);
|
||||
|
||||
PolychromeSpriteVertexOutput output;
|
||||
output.position = device_position;
|
||||
output.tile_position = tile_position;
|
||||
output.sprite_id = sprite_id;
|
||||
output.clip_distance = clip_distance;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 polychrome_sprite_fragment(PolychromeSpriteFragmentInput input): SV_Target {
|
||||
PolychromeSprite sprite = poly_sprites[input.sprite_id];
|
||||
float4 sample = t_sprite.Sample(s_sprite, input.tile_position);
|
||||
float distance = quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii);
|
||||
|
||||
float4 color = sample;
|
||||
if ((sprite.grayscale & 0xFFu) != 0u) {
|
||||
float3 grayscale = dot(color.rgb, GRAYSCALE_FACTORS);
|
||||
color = float4(grayscale, sample.a);
|
||||
}
|
||||
color.a *= saturate(0.5 - distance);
|
||||
return color;
|
||||
}
|
|
@ -49,7 +49,7 @@ pub struct WindowsWindowState {
|
|||
pub system_key_handled: bool,
|
||||
pub hovered: bool,
|
||||
|
||||
pub renderer: BladeRenderer,
|
||||
pub renderer: DirectXRenderer,
|
||||
|
||||
pub click_state: ClickState,
|
||||
pub system_settings: WindowsSystemSettings,
|
||||
|
@ -84,7 +84,7 @@ impl WindowsWindowState {
|
|||
cs: &CREATESTRUCTW,
|
||||
current_cursor: Option<HCURSOR>,
|
||||
display: WindowsDisplay,
|
||||
gpu_context: &BladeContext,
|
||||
gpu_context: &DirectXDevices,
|
||||
min_size: Option<Size<Pixels>>,
|
||||
appearance: WindowAppearance,
|
||||
) -> Result<Self> {
|
||||
|
@ -103,7 +103,8 @@ impl WindowsWindowState {
|
|||
};
|
||||
let border_offset = WindowBorderOffset::default();
|
||||
let restore_from_minimized = None;
|
||||
let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?;
|
||||
// let renderer = windows_renderer::init(gpu_context, hwnd, transparent)?;
|
||||
let renderer = DirectXRenderer::new(gpu_context, hwnd, transparent)?;
|
||||
let callbacks = Callbacks::default();
|
||||
let input_handler = None;
|
||||
let pending_surrogate = None;
|
||||
|
@ -343,7 +344,7 @@ struct WindowCreateContext<'a> {
|
|||
drop_target_helper: IDropTargetHelper,
|
||||
validation_number: usize,
|
||||
main_receiver: flume::Receiver<Runnable>,
|
||||
gpu_context: &'a BladeContext,
|
||||
gpu_context: &'a DirectXDevices,
|
||||
main_thread_id_win32: u32,
|
||||
appearance: WindowAppearance,
|
||||
}
|
||||
|
@ -353,7 +354,7 @@ impl WindowsWindow {
|
|||
handle: AnyWindowHandle,
|
||||
params: WindowParams,
|
||||
creation_info: WindowCreationInfo,
|
||||
gpu_context: &BladeContext,
|
||||
gpu_context: &DirectXDevices,
|
||||
) -> Result<Self> {
|
||||
let WindowCreationInfo {
|
||||
icon,
|
||||
|
@ -485,7 +486,7 @@ impl rwh::HasDisplayHandle for WindowsWindow {
|
|||
|
||||
impl Drop for WindowsWindow {
|
||||
fn drop(&mut self) {
|
||||
self.0.state.borrow_mut().renderer.destroy();
|
||||
// self.0.state.borrow_mut().renderer.destroy();
|
||||
// clone this `Rc` to prevent early release of the pointer
|
||||
let this = self.0.clone();
|
||||
self.0
|
||||
|
@ -706,9 +707,10 @@ impl PlatformWindow for WindowsWindow {
|
|||
|
||||
fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
|
||||
let mut window_state = self.0.state.borrow_mut();
|
||||
window_state
|
||||
.renderer
|
||||
.update_transparency(background_appearance != WindowBackgroundAppearance::Opaque);
|
||||
// todo(zjk)
|
||||
// window_state
|
||||
// .renderer
|
||||
// .update_transparency(background_appearance != WindowBackgroundAppearance::Opaque);
|
||||
|
||||
match background_appearance {
|
||||
WindowBackgroundAppearance::Opaque => {
|
||||
|
@ -794,11 +796,11 @@ impl PlatformWindow for WindowsWindow {
|
|||
}
|
||||
|
||||
fn draw(&self, scene: &Scene) {
|
||||
self.0.state.borrow_mut().renderer.draw(scene)
|
||||
self.0.state.borrow_mut().renderer.draw(scene).log_err();
|
||||
}
|
||||
|
||||
fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas> {
|
||||
self.0.state.borrow().renderer.sprite_atlas().clone()
|
||||
self.0.state.borrow().renderer.sprite_atlas()
|
||||
}
|
||||
|
||||
fn get_raw_handle(&self) -> HWND {
|
||||
|
@ -806,7 +808,9 @@ impl PlatformWindow for WindowsWindow {
|
|||
}
|
||||
|
||||
fn gpu_specs(&self) -> Option<GpuSpecs> {
|
||||
Some(self.0.state.borrow().renderer.gpu_specs())
|
||||
// todo(zjk)
|
||||
// Some(self.0.state.borrow().renderer.gpu_specs())
|
||||
None
|
||||
}
|
||||
|
||||
fn update_ime_position(&self, _bounds: Bounds<ScaledPixels>) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue