This commit is contained in:
Junkui Zhang 2025-07-13 13:15:24 +08:00
parent c0bad42968
commit ca3d55ee4d
6 changed files with 904 additions and 220 deletions

View file

@ -84,7 +84,7 @@ impl DirectXAtlas {
let textures = match texture_kind { let textures = match texture_kind {
AtlasTextureKind::Monochrome => &mut lock.monochrome_textures, AtlasTextureKind::Monochrome => &mut lock.monochrome_textures,
AtlasTextureKind::Polychrome => &mut lock.polychrome_textures, AtlasTextureKind::Polychrome => &mut lock.polychrome_textures,
AtlasTextureKind::Path => &mut lock.path_textures, // AtlasTextureKind::Path => &mut lock.path_textures,
}; };
for texture in textures { for texture in textures {
texture.clear(); texture.clear();
@ -131,7 +131,7 @@ impl DirectXAtlasState {
let textures = match texture_kind { let textures = match texture_kind {
AtlasTextureKind::Monochrome => &mut self.monochrome_textures, AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
AtlasTextureKind::Polychrome => &mut self.polychrome_textures, AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
AtlasTextureKind::Path => &mut self.path_textures, // AtlasTextureKind::Path => &mut self.path_textures,
}; };
textures textures
@ -173,12 +173,11 @@ impl DirectXAtlasState {
pixel_format = DXGI_FORMAT_B8G8R8A8_UNORM; pixel_format = DXGI_FORMAT_B8G8R8A8_UNORM;
bind_flag = D3D11_BIND_SHADER_RESOURCE; bind_flag = D3D11_BIND_SHADER_RESOURCE;
bytes_per_pixel = 4; bytes_per_pixel = 4;
} } // AtlasTextureKind::Path => {
AtlasTextureKind::Path => { // pixel_format = DXGI_FORMAT_R16_FLOAT;
pixel_format = DXGI_FORMAT_R16_FLOAT; // bind_flag = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
bind_flag = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; // bytes_per_pixel = 2;
bytes_per_pixel = 2; // }
}
} }
let texture_desc = D3D11_TEXTURE2D_DESC { let texture_desc = D3D11_TEXTURE2D_DESC {
Width: size.width.0 as u32, Width: size.width.0 as u32,
@ -206,16 +205,16 @@ impl DirectXAtlasState {
let textures = match kind { let textures = match kind {
AtlasTextureKind::Monochrome => &mut self.monochrome_textures, AtlasTextureKind::Monochrome => &mut self.monochrome_textures,
AtlasTextureKind::Polychrome => &mut self.polychrome_textures, AtlasTextureKind::Polychrome => &mut self.polychrome_textures,
AtlasTextureKind::Path => &mut self.path_textures, // AtlasTextureKind::Path => &mut self.path_textures,
}; };
let rtv = match kind { let rtv = match kind {
AtlasTextureKind::Path => unsafe { // AtlasTextureKind::Path => unsafe {
let mut view: Option<ID3D11RenderTargetView> = None; // let mut view: Option<ID3D11RenderTargetView> = None;
self.device // self.device
.CreateRenderTargetView(&texture, None, Some(&mut view)) // .CreateRenderTargetView(&texture, None, Some(&mut view))
.unwrap(); // .unwrap();
[view] // [view]
}, // },
_ => [None], _ => [None],
}; };
let view = unsafe { let view = unsafe {
@ -244,7 +243,7 @@ impl DirectXAtlasState {
let textures = match id.kind { let textures = match id.kind {
crate::AtlasTextureKind::Monochrome => &self.monochrome_textures, crate::AtlasTextureKind::Monochrome => &self.monochrome_textures,
crate::AtlasTextureKind::Polychrome => &self.polychrome_textures, crate::AtlasTextureKind::Polychrome => &self.polychrome_textures,
crate::AtlasTextureKind::Path => &self.path_textures, // crate::AtlasTextureKind::Path => &self.path_textures,
}; };
&textures[id.index as usize] &textures[id.index as usize]
} }

View file

@ -3,11 +3,11 @@ use std::{collections::HashMap, hash::BuildHasherDefault, sync::Arc};
use ::util::ResultExt; use ::util::ResultExt;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use collections::FxHasher; use collections::FxHasher;
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
use windows::Win32::Graphics::DirectComposition::*; // use windows::Win32::Graphics::DirectComposition::*;
use windows::{ use windows::{
Win32::{ Win32::{
Foundation::HWND, Foundation::{HMODULE, HWND},
Graphics::{ Graphics::{
Direct3D::*, Direct3D::*,
Direct3D11::*, Direct3D11::*,
@ -41,8 +41,8 @@ struct DirectXContext {
swap_chain: IDXGISwapChain1, swap_chain: IDXGISwapChain1,
back_buffer: [Option<ID3D11RenderTargetView>; 1], back_buffer: [Option<ID3D11RenderTargetView>; 1],
viewport: [D3D11_VIEWPORT; 1], viewport: [D3D11_VIEWPORT; 1],
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
direct_composition: DirectComposition, // direct_composition: DirectComposition,
} }
struct DirectXRenderPipelines { struct DirectXRenderPipelines {
@ -62,12 +62,12 @@ struct DirectXGlobalElements {
blend_state_for_pr: ID3D11BlendState, blend_state_for_pr: ID3D11BlendState,
} }
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
struct DirectComposition { // struct DirectComposition {
comp_device: IDCompositionDevice, // comp_device: IDCompositionDevice,
comp_target: IDCompositionTarget, // comp_target: IDCompositionTarget,
comp_visual: IDCompositionVisual, // comp_visual: IDCompositionVisual,
} // }
impl DirectXDevices { impl DirectXDevices {
pub(crate) fn new() -> Result<Self> { pub(crate) fn new() -> Result<Self> {
@ -91,17 +91,17 @@ impl DirectXDevices {
} }
impl DirectXRenderer { 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( let atlas = Arc::new(DirectXAtlas::new(
devices.device.clone(), devices.device.clone(),
devices.device_context.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 globals = DirectXGlobalElements::new(&devices.device)?;
let pipelines = DirectXRenderPipelines::new(&devices.device)?; let pipelines = DirectXRenderPipelines::new(&devices.device)?;
Ok(DirectXRenderer { Ok(DirectXRenderer {
atlas, atlas,
devices, devices: devices.clone(),
context, context,
globals, globals,
pipelines, 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() self.atlas.clone()
} }
@ -153,7 +153,7 @@ impl DirectXRenderer {
scene.polychrome_sprites.len(), scene.polychrome_sprites.len(),
scene.surfaces.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(()) Ok(())
} }
@ -166,7 +166,7 @@ impl DirectXRenderer {
new_size.width.0 as u32, new_size.width.0 as u32,
new_size.height.0 as u32, new_size.height.0 as u32,
DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
0, DXGI_SWAP_CHAIN_FLAG(0),
)?; )?;
} }
let backbuffer = set_render_target_view( let backbuffer = set_render_target_view(
@ -183,32 +183,32 @@ impl DirectXRenderer {
Ok(()) Ok(())
} }
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
pub(crate) fn update_transparency( // pub(crate) fn update_transparency(
&mut self, // &mut self,
background_appearance: WindowBackgroundAppearance, // background_appearance: WindowBackgroundAppearance,
) -> Result<()> { // ) -> Result<()> {
// We only support setting `Transparent` and `Opaque` for now. // // We only support setting `Transparent` and `Opaque` for now.
match background_appearance { // match background_appearance {
WindowBackgroundAppearance::Opaque => { // WindowBackgroundAppearance::Opaque => {
if self.transparent { // if self.transparent {
return Err(anyhow::anyhow!( // return Err(anyhow::anyhow!(
"Set opaque backgroud from transparent background, a restart is required. Or, you can open a new window." // "Set opaque backgroud from transparent background, a restart is required. Or, you can open a new window."
)); // ));
} // }
} // }
WindowBackgroundAppearance::Transparent | WindowBackgroundAppearance::Blurred => { // WindowBackgroundAppearance::Transparent | WindowBackgroundAppearance::Blurred => {
if !self.transparent { // if !self.transparent {
return Err(anyhow::anyhow!( // return Err(anyhow::anyhow!(
"Set transparent backgroud from opaque background, a restart is required. Or, you can open a new window." // "Set transparent backgroud from opaque background, a restart is required. Or, you can open a new window."
)); // ));
} // }
} // }
} // }
Ok(()) // Ok(())
} // }
#[cfg(feature = "enable-renderdoc")] // #[cfg(feature = "enable-renderdoc")]
pub(crate) fn update_transparency( pub(crate) fn update_transparency(
&mut self, &mut self,
background_appearance: WindowBackgroundAppearance, background_appearance: WindowBackgroundAppearance,
@ -280,77 +280,78 @@ impl DirectXRenderer {
&mut self, &mut self,
paths: &[Path<ScaledPixels>], paths: &[Path<ScaledPixels>],
) -> Option<HashMap<PathId, AtlasTile>> { ) -> Option<HashMap<PathId, AtlasTile>> {
self.atlas.clear_textures(AtlasTextureKind::Path); // self.atlas.clear_textures(AtlasTextureKind::Path);
let mut tiles = HashMap::default(); // let mut tiles = HashMap::default();
let mut vertices_by_texture_id: HashMap< // let mut vertices_by_texture_id: HashMap<
AtlasTextureId, // AtlasTextureId,
Vec<PathVertex<ScaledPixels>>, // Vec<PathVertex<ScaledPixels>>,
BuildHasherDefault<FxHasher>, // BuildHasherDefault<FxHasher>,
> = HashMap::default(); // > = HashMap::default();
for path in paths { // for path in paths {
let clipped_bounds = path.bounds.intersect(&path.content_mask.bounds); // let clipped_bounds = path.bounds.intersect(&path.content_mask.bounds);
let tile = self // let tile = self
.atlas // .atlas
.allocate(clipped_bounds.size.map(Into::into), AtlasTextureKind::Path)?; // .allocate(clipped_bounds.size.map(Into::into), AtlasTextureKind::Path)?;
vertices_by_texture_id // vertices_by_texture_id
.entry(tile.texture_id) // .entry(tile.texture_id)
.or_insert(Vec::new()) // .or_insert(Vec::new())
.extend(path.vertices.iter().map(|vertex| PathVertex { // .extend(path.vertices.iter().map(|vertex| PathVertex {
xy_position: vertex.xy_position - clipped_bounds.origin // xy_position: vertex.xy_position - clipped_bounds.origin
+ tile.bounds.origin.map(Into::into), // + tile.bounds.origin.map(Into::into),
content_mask: ContentMask { // content_mask: ContentMask {
bounds: tile.bounds.map(Into::into), // bounds: tile.bounds.map(Into::into),
}, // },
})); // }));
tiles.insert(path.id, tile); // tiles.insert(path.id, tile);
} // }
for (texture_id, vertices) in vertices_by_texture_id { // for (texture_id, vertices) in vertices_by_texture_id {
let (texture_size, rtv) = self.atlas.get_texture_drawing_info(texture_id); // let (texture_size, rtv) = self.atlas.get_texture_drawing_info(texture_id);
let viewport = [D3D11_VIEWPORT { // let viewport = [D3D11_VIEWPORT {
TopLeftX: 0.0, // TopLeftX: 0.0,
TopLeftY: 0.0, // TopLeftY: 0.0,
Width: texture_size.width, // Width: texture_size.width,
Height: texture_size.height, // Height: texture_size.height,
MinDepth: 0.0, // MinDepth: 0.0,
MaxDepth: 1.0, // MaxDepth: 1.0,
}]; // }];
pre_draw( // pre_draw(
&self.devices.device_context, // &self.devices.device_context,
&self.globals.global_params_buffer, // &self.globals.global_params_buffer,
&viewport, // &viewport,
&rtv, // &rtv,
[0.0, 0.0, 0.0, 1.0], // [0.0, 0.0, 0.0, 1.0],
&self.globals.blend_state_for_pr, // &self.globals.blend_state_for_pr,
) // )
.log_err()?; // .log_err()?;
update_buffer_capacity( // update_buffer_capacity(
&self.pipelines.path_raster_pipeline, // &self.pipelines.path_raster_pipeline,
std::mem::size_of::<PathVertex<ScaledPixels>>(), // std::mem::size_of::<PathVertex<ScaledPixels>>(),
vertices.len(), // vertices.len(),
&self.devices.device, // &self.devices.device,
) // )
.map(|input| update_pipeline(&mut self.pipelines.path_raster_pipeline, input)); // .map(|input| update_pipeline(&mut self.pipelines.path_raster_pipeline, input));
update_buffer( // update_buffer(
&self.devices.device_context, // &self.devices.device_context,
&self.pipelines.path_raster_pipeline.buffer, // &self.pipelines.path_raster_pipeline.buffer,
&vertices, // &vertices,
) // )
.log_err()?; // .log_err()?;
draw_normal( // draw_normal(
&self.devices.device_context, // &self.devices.device_context,
&self.pipelines.path_raster_pipeline, // &self.pipelines.path_raster_pipeline,
&viewport, // &viewport,
&self.globals.global_params_buffer, // &self.globals.global_params_buffer,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
vertices.len() as u32, // vertices.len() as u32,
1, // 1,
) // )
.log_err()?; // .log_err()?;
} // }
Some(tiles) // Some(tiles)
None
} }
fn draw_paths( fn draw_paths(
@ -358,43 +359,43 @@ impl DirectXRenderer {
paths: &[Path<ScaledPixels>], paths: &[Path<ScaledPixels>],
path_tiles: &HashMap<PathId, AtlasTile>, path_tiles: &HashMap<PathId, AtlasTile>,
) -> Result<()> { ) -> Result<()> {
if paths.is_empty() { // if paths.is_empty() {
return Ok(()); // return Ok(());
} // }
for path in paths { // for path in paths {
let tile = &path_tiles[&path.id]; // let tile = &path_tiles[&path.id];
let texture_view = self.atlas.get_texture_view(tile.texture_id); // let texture_view = self.atlas.get_texture_view(tile.texture_id);
let origin = path.bounds.intersect(&path.content_mask.bounds).origin; // let origin = path.bounds.intersect(&path.content_mask.bounds).origin;
let sprites = [PathSprite { // let sprites = [PathSprite {
bounds: Bounds { // bounds: Bounds {
origin: origin.map(|p| p.floor()), // origin: origin.map(|p| p.floor()),
size: tile.bounds.size.map(Into::into), // size: tile.bounds.size.map(Into::into),
}, // },
color: path.color, // color: path.color,
tile: (*tile).clone(), // tile: (*tile).clone(),
}]; // }];
update_buffer_capacity( // update_buffer_capacity(
&self.pipelines.paths_pipeline, // &self.pipelines.paths_pipeline,
std::mem::size_of::<PathSprite>(), // std::mem::size_of::<PathSprite>(),
1, // 1,
&self.devices.device, // &self.devices.device,
) // )
.map(|input| update_pipeline(&mut self.pipelines.paths_pipeline, input)); // .map(|input| update_pipeline(&mut self.pipelines.paths_pipeline, input));
update_buffer( // update_buffer(
&self.devices.device_context, // &self.devices.device_context,
&self.pipelines.paths_pipeline.buffer, // &self.pipelines.paths_pipeline.buffer,
&sprites, // &sprites,
)?; // )?;
draw_with_texture( // draw_with_texture(
&self.devices.device_context, // &self.devices.device_context,
&self.pipelines.paths_pipeline, // &self.pipelines.paths_pipeline,
&texture_view, // &texture_view,
&self.context.viewport, // &self.context.viewport,
&self.globals.global_params_buffer, // &self.globals.global_params_buffer,
&self.globals.sampler, // &self.globals.sampler,
1, // 1,
)?; // )?;
} // }
Ok(()) 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() { if surfaces.is_empty() {
return Ok(()); return Ok(());
} }
@ -499,15 +500,15 @@ impl DirectXRenderer {
impl DirectXContext { impl DirectXContext {
pub fn new(devices: &DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> { pub fn new(devices: &DirectXDevices, hwnd: HWND, transparent: bool) -> Result<Self> {
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, transparent)?; // let swap_chain = create_swap_chain(&devices.dxgi_factory, &devices.device, transparent)?;
#[cfg(feature = "enable-renderdoc")] // #[cfg(feature = "enable-renderdoc")]
let swap_chain = let swap_chain =
create_swap_chain_default(&devices.dxgi_factory, &devices.device, hwnd, transparent)?; create_swap_chain_default(&devices.dxgi_factory, &devices.device, hwnd, transparent)?;
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?; // let direct_composition = DirectComposition::new(&devices.dxgi_device, hwnd)?;
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
direct_composition.set_swap_chain(&swap_chain)?; // direct_composition.set_swap_chain(&swap_chain)?;
let back_buffer = [Some(set_render_target_view( let back_buffer = [Some(set_render_target_view(
&swap_chain, &swap_chain,
&devices.device, &devices.device,
@ -520,8 +521,8 @@ impl DirectXContext {
swap_chain, swap_chain,
back_buffer, back_buffer,
viewport, viewport,
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
direct_composition, // direct_composition,
}) })
} }
} }
@ -590,29 +591,29 @@ impl DirectXRenderPipelines {
} }
} }
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
impl DirectComposition { // impl DirectComposition {
pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result<Self> { // pub fn new(dxgi_device: &IDXGIDevice, hwnd: HWND) -> Result<Self> {
let comp_device = get_comp_device(&dxgi_device)?; // let comp_device = get_comp_device(&dxgi_device)?;
let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?; // let comp_target = unsafe { comp_device.CreateTargetForHwnd(hwnd, true) }?;
let comp_visual = unsafe { comp_device.CreateVisual() }?; // let comp_visual = unsafe { comp_device.CreateVisual() }?;
Ok(Self { // Ok(Self {
comp_device, // comp_device,
comp_target, // comp_target,
comp_visual, // comp_visual,
}) // })
} // }
pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> { // pub fn set_swap_chain(&self, swap_chain: &IDXGISwapChain1) -> Result<()> {
unsafe { // unsafe {
self.comp_visual.SetContent(swap_chain)?; // self.comp_visual.SetContent(swap_chain)?;
self.comp_target.SetRoot(&self.comp_visual)?; // self.comp_target.SetRoot(&self.comp_visual)?;
self.comp_device.Commit()?; // self.comp_device.Commit()?;
} // }
Ok(()) // Ok(())
} // }
} // }
impl DirectXGlobalElements { impl DirectXGlobalElements {
pub fn new(device: &ID3D11Device) -> Result<Self> { pub fn new(device: &ID3D11Device) -> Result<Self> {
@ -726,7 +727,7 @@ fn get_device(
D3D11CreateDevice( D3D11CreateDevice(
adapter, adapter,
D3D_DRIVER_TYPE_UNKNOWN, D3D_DRIVER_TYPE_UNKNOWN,
None, HMODULE::default(),
device_flags, device_flags,
Some(&[D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1]), Some(&[D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1]),
D3D11_SDK_VERSION, D3D11_SDK_VERSION,
@ -737,10 +738,10 @@ fn get_device(
}) })
} }
#[cfg(not(feature = "enable-renderdoc"))] // #[cfg(not(feature = "enable-renderdoc"))]
fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result<IDCompositionDevice> { // fn get_comp_device(dxgi_device: &IDXGIDevice) -> Result<IDCompositionDevice> {
Ok(unsafe { DCompositionCreateDevice(dxgi_device)? }) // Ok(unsafe { DCompositionCreateDevice(dxgi_device)? })
} // }
fn create_swap_chain( fn create_swap_chain(
dxgi_factory: &IDXGIFactory6, dxgi_factory: &IDXGIFactory6,
@ -772,7 +773,7 @@ fn create_swap_chain(
Ok(unsafe { dxgi_factory.CreateSwapChainForComposition(device, &desc, None)? }) Ok(unsafe { dxgi_factory.CreateSwapChainForComposition(device, &desc, None)? })
} }
#[cfg(feature = "enable-renderdoc")] // #[cfg(feature = "enable-renderdoc")]
fn create_swap_chain_default( fn create_swap_chain_default(
dxgi_factory: &IDXGIFactory6, dxgi_factory: &IDXGIFactory6,
device: &ID3D11Device, device: &ID3D11Device,

View file

@ -181,11 +181,13 @@ fn handle_size_msg(
let new_size = size(DevicePixels(width), DevicePixels(height)); let new_size = size(DevicePixels(width), DevicePixels(height));
let scale_factor = lock.scale_factor; let scale_factor = lock.scale_factor;
if lock.restore_from_minimized.is_some() { if lock.restore_from_minimized.is_some() {
lock.renderer // lock.renderer
.update_drawable_size_even_if_unchanged(new_size); // .update_drawable_size_even_if_unchanged(new_size);
lock.renderer.resize(new_size).log_err();
lock.callbacks.request_frame = lock.restore_from_minimized.take(); lock.callbacks.request_frame = lock.restore_from_minimized.take();
} else { } 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); let new_size = new_size.to_pixels(scale_factor);
lock.logical_size = new_size; lock.logical_size = new_size;

View file

@ -34,7 +34,8 @@ pub(crate) struct WindowsPlatform {
state: RefCell<WindowsPlatformState>, state: RefCell<WindowsPlatformState>,
raw_window_handles: RwLock<SmallVec<[HWND; 4]>>, raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
// The below members will never change throughout the entire lifecycle of the app. // The below members will never change throughout the entire lifecycle of the app.
gpu_context: BladeContext, // gpu_context: BladeContext,
directx_devices: DirectXDevices,
icon: HICON, icon: HICON,
main_receiver: flume::Receiver<Runnable>, main_receiver: flume::Receiver<Runnable>,
background_executor: BackgroundExecutor, background_executor: BackgroundExecutor,
@ -111,13 +112,14 @@ impl WindowsPlatform {
let icon = load_icon().unwrap_or_default(); let icon = load_icon().unwrap_or_default();
let state = RefCell::new(WindowsPlatformState::new()); let state = RefCell::new(WindowsPlatformState::new());
let raw_window_handles = RwLock::new(SmallVec::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")?; let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
Ok(Self { Ok(Self {
state, state,
raw_window_handles, raw_window_handles,
gpu_context, directx_devices,
icon, icon,
main_receiver, main_receiver,
background_executor, background_executor,
@ -459,7 +461,7 @@ impl Platform for WindowsPlatform {
handle, handle,
options, options,
self.generate_creation_info(), self.generate_creation_info(),
&self.gpu_context, &self.directx_devices,
)?; )?;
let handle = window.get_raw_handle(); let handle = window.get_raw_handle();
self.raw_window_handles.write().push(handle); self.raw_window_handles.write().push(handle);

View 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;
}

View file

@ -49,7 +49,7 @@ pub struct WindowsWindowState {
pub system_key_handled: bool, pub system_key_handled: bool,
pub hovered: bool, pub hovered: bool,
pub renderer: BladeRenderer, pub renderer: DirectXRenderer,
pub click_state: ClickState, pub click_state: ClickState,
pub system_settings: WindowsSystemSettings, pub system_settings: WindowsSystemSettings,
@ -84,7 +84,7 @@ impl WindowsWindowState {
cs: &CREATESTRUCTW, cs: &CREATESTRUCTW,
current_cursor: Option<HCURSOR>, current_cursor: Option<HCURSOR>,
display: WindowsDisplay, display: WindowsDisplay,
gpu_context: &BladeContext, gpu_context: &DirectXDevices,
min_size: Option<Size<Pixels>>, min_size: Option<Size<Pixels>>,
appearance: WindowAppearance, appearance: WindowAppearance,
) -> Result<Self> { ) -> Result<Self> {
@ -103,7 +103,8 @@ impl WindowsWindowState {
}; };
let border_offset = WindowBorderOffset::default(); let border_offset = WindowBorderOffset::default();
let restore_from_minimized = None; 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 callbacks = Callbacks::default();
let input_handler = None; let input_handler = None;
let pending_surrogate = None; let pending_surrogate = None;
@ -343,7 +344,7 @@ struct WindowCreateContext<'a> {
drop_target_helper: IDropTargetHelper, drop_target_helper: IDropTargetHelper,
validation_number: usize, validation_number: usize,
main_receiver: flume::Receiver<Runnable>, main_receiver: flume::Receiver<Runnable>,
gpu_context: &'a BladeContext, gpu_context: &'a DirectXDevices,
main_thread_id_win32: u32, main_thread_id_win32: u32,
appearance: WindowAppearance, appearance: WindowAppearance,
} }
@ -353,7 +354,7 @@ impl WindowsWindow {
handle: AnyWindowHandle, handle: AnyWindowHandle,
params: WindowParams, params: WindowParams,
creation_info: WindowCreationInfo, creation_info: WindowCreationInfo,
gpu_context: &BladeContext, gpu_context: &DirectXDevices,
) -> Result<Self> { ) -> Result<Self> {
let WindowCreationInfo { let WindowCreationInfo {
icon, icon,
@ -485,7 +486,7 @@ impl rwh::HasDisplayHandle for WindowsWindow {
impl Drop for WindowsWindow { impl Drop for WindowsWindow {
fn drop(&mut self) { 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 // clone this `Rc` to prevent early release of the pointer
let this = self.0.clone(); let this = self.0.clone();
self.0 self.0
@ -706,9 +707,10 @@ impl PlatformWindow for WindowsWindow {
fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) { fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
let mut window_state = self.0.state.borrow_mut(); let mut window_state = self.0.state.borrow_mut();
window_state // todo(zjk)
.renderer // window_state
.update_transparency(background_appearance != WindowBackgroundAppearance::Opaque); // .renderer
// .update_transparency(background_appearance != WindowBackgroundAppearance::Opaque);
match background_appearance { match background_appearance {
WindowBackgroundAppearance::Opaque => { WindowBackgroundAppearance::Opaque => {
@ -794,11 +796,11 @@ impl PlatformWindow for WindowsWindow {
} }
fn draw(&self, scene: &Scene) { 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> { 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 { fn get_raw_handle(&self) -> HWND {
@ -806,7 +808,9 @@ impl PlatformWindow for WindowsWindow {
} }
fn gpu_specs(&self) -> Option<GpuSpecs> { 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>) { fn update_ime_position(&self, _bounds: Bounds<ScaledPixels>) {