Upgrade Blitz to 0.1.0-alpha.3 and add wgpu-texture example (#4286)
* Use Blitz 0.1.0-alpha.3 * Add wgpu-texture example * Native: Support configuring wgpu Features and Limits
This commit is contained in:
1 parent
544d8cc4da
commit
6fcb496fd5
11 files changed
+796
-162
No files matched your search
@@ -1,16 +1,16 @@
|
||||
use anyrender_vello::VelloWindowRenderer;
|
||||
use blitz_shell::BlitzApplication;
|
||||
use dioxus_core::{ScopeId, VirtualDom};
|
||||
use blitz_shell::{BlitzApplication, View};
|
||||
use dioxus_core::ScopeId;
|
||||
use dioxus_history::{History, MemoryHistory};
|
||||
use std::{collections::HashSet, rc::Rc};
|
||||
use std::rc::Rc;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::{StartCause, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
|
||||
use winit::window::WindowId;
|
||||
|
||||
use crate::DioxusNativeWindowRenderer;
|
||||
use crate::{
|
||||
assets::DioxusNativeNetProvider, contexts::DioxusNativeDocument,
|
||||
mutation_writer::MutationWriter, BlitzShellEvent, DioxusDocument, WindowConfig,
|
||||
contexts::DioxusNativeDocument, mutation_writer::MutationWriter, BlitzShellEvent,
|
||||
DioxusDocument, WindowConfig,
|
||||
};
|
||||
|
||||
/// Dioxus-native specific event type
|
||||
@@ -36,21 +36,24 @@ pub enum DioxusNativeEvent {
|
||||
}
|
||||
|
||||
pub struct DioxusNativeApplication {
|
||||
pending_vdom: Option<VirtualDom>,
|
||||
inner: BlitzApplication<VelloWindowRenderer>,
|
||||
pending_window: Option<WindowConfig<DioxusNativeWindowRenderer>>,
|
||||
inner: BlitzApplication<DioxusNativeWindowRenderer>,
|
||||
proxy: EventLoopProxy<BlitzShellEvent>,
|
||||
}
|
||||
|
||||
impl DioxusNativeApplication {
|
||||
pub fn new(proxy: EventLoopProxy<BlitzShellEvent>, vdom: VirtualDom) -> Self {
|
||||
pub fn new(
|
||||
proxy: EventLoopProxy<BlitzShellEvent>,
|
||||
config: WindowConfig<DioxusNativeWindowRenderer>,
|
||||
) -> Self {
|
||||
Self {
|
||||
pending_vdom: Some(vdom),
|
||||
pending_window: Some(config),
|
||||
inner: BlitzApplication::new(proxy.clone()),
|
||||
proxy,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_window(&mut self, window_config: WindowConfig<VelloWindowRenderer>) {
|
||||
pub fn add_window(&mut self, window_config: WindowConfig<DioxusNativeWindowRenderer>) {
|
||||
self.inner.add_window(window_config);
|
||||
}
|
||||
|
||||
@@ -112,42 +115,27 @@ impl DioxusNativeApplication {
|
||||
impl ApplicationHandler<BlitzShellEvent> for DioxusNativeApplication {
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
tracing::debug!("Injecting document provider into all windows");
|
||||
let vdom = self.pending_vdom.take().unwrap();
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
let net_provider = {
|
||||
let proxy = self.proxy.clone();
|
||||
let net_provider = DioxusNativeNetProvider::shared(proxy);
|
||||
Some(net_provider)
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "net"))]
|
||||
let net_provider = None;
|
||||
|
||||
// Create document + window from the baked virtualdom
|
||||
let doc = DioxusDocument::new(vdom, net_provider);
|
||||
let window = WindowConfig::new(Box::new(doc) as _);
|
||||
|
||||
// little hack since View::init is not public - fix this once alpha-2 is out
|
||||
let old_windows = self.inner.windows.keys().copied().collect::<HashSet<_>>();
|
||||
self.add_window(window);
|
||||
self.inner.resumed(event_loop);
|
||||
let new_windows = self.inner.windows.keys().cloned().collect::<HashSet<_>>();
|
||||
|
||||
// todo(jon): we should actually mess with the pending windows instead of passing along the contexts
|
||||
for window_id in new_windows.difference(&old_windows) {
|
||||
let window = self.inner.windows.get_mut(window_id).unwrap();
|
||||
if let Some(config) = self.pending_window.take() {
|
||||
let mut window = View::init(config, event_loop, &self.proxy);
|
||||
let renderer = window.renderer.clone();
|
||||
let window_id = window.window_id();
|
||||
let doc = window.downcast_doc_mut::<DioxusDocument>();
|
||||
|
||||
doc.vdom.in_runtime(|| {
|
||||
let shared: Rc<dyn dioxus_document::Document> =
|
||||
Rc::new(DioxusNativeDocument::new(self.proxy.clone(), *window_id));
|
||||
Rc::new(DioxusNativeDocument::new(self.proxy.clone(), window_id));
|
||||
ScopeId::ROOT.provide_context(shared);
|
||||
});
|
||||
|
||||
// Add history
|
||||
let history_provider: Rc<dyn History> = Rc::new(MemoryHistory::default());
|
||||
doc.vdom
|
||||
.in_runtime(|| ScopeId::ROOT.provide_context(history_provider));
|
||||
.in_runtime(move || ScopeId::ROOT.provide_context(history_provider));
|
||||
|
||||
// Add renderer
|
||||
doc.vdom
|
||||
.in_runtime(move || ScopeId::ROOT.provide_context(renderer));
|
||||
|
||||
// Queue rebuild
|
||||
let mut writer = MutationWriter::new(&mut doc.inner, &mut doc.vdom_state);
|
||||
@@ -156,7 +144,12 @@ impl ApplicationHandler<BlitzShellEvent> for DioxusNativeApplication {
|
||||
|
||||
// And then request redraw
|
||||
window.request_redraw();
|
||||
|
||||
// todo(jon): we should actually mess with the pending windows instead of passing along the contexts
|
||||
self.inner.windows.insert(window_id, window);
|
||||
}
|
||||
|
||||
self.inner.resumed(event_loop);
|
||||
}
|
||||
|
||||
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyrender::WindowRenderer;
|
||||
|
||||
pub use anyrender_vello::{
|
||||
wgpu::{Features, Limits},
|
||||
CustomPaintSource, VelloWindowRenderer as InnerRenderer,
|
||||
};
|
||||
|
||||
pub fn use_wgpu<T: CustomPaintSource>(create_source: impl FnOnce() -> T) -> u64 {
|
||||
use dioxus_core::prelude::{consume_context, use_hook_with_cleanup};
|
||||
|
||||
let (_renderer, id) = use_hook_with_cleanup(
|
||||
|| {
|
||||
let renderer = consume_context::<DioxusNativeWindowRenderer>();
|
||||
let source = Box::new(create_source());
|
||||
let id = renderer.register_custom_paint_source(source);
|
||||
(renderer, id)
|
||||
},
|
||||
|(renderer, id)| {
|
||||
renderer.unregister_custom_paint_source(id);
|
||||
},
|
||||
);
|
||||
|
||||
id
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DioxusNativeWindowRenderer {
|
||||
inner: Rc<RefCell<InnerRenderer>>,
|
||||
}
|
||||
|
||||
impl Default for DioxusNativeWindowRenderer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl DioxusNativeWindowRenderer {
|
||||
pub fn new() -> Self {
|
||||
let vello_renderer = InnerRenderer::new();
|
||||
Self::with_inner_renderer(vello_renderer)
|
||||
}
|
||||
|
||||
pub fn with_features_and_limits(features: Option<Features>, limits: Option<Limits>) -> Self {
|
||||
let vello_renderer = InnerRenderer::with_features_and_limits(features, limits);
|
||||
Self::with_inner_renderer(vello_renderer)
|
||||
}
|
||||
|
||||
fn with_inner_renderer(vello_renderer: InnerRenderer) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(RefCell::new(vello_renderer)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DioxusNativeWindowRenderer {
|
||||
pub fn register_custom_paint_source(&self, source: Box<dyn CustomPaintSource>) -> u64 {
|
||||
self.inner.borrow_mut().register_custom_paint_source(source)
|
||||
}
|
||||
|
||||
pub fn unregister_custom_paint_source(&self, id: u64) {
|
||||
self.inner.borrow_mut().unregister_custom_paint_source(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl WindowRenderer for DioxusNativeWindowRenderer {
|
||||
type ScenePainter<'a>
|
||||
= <InnerRenderer as WindowRenderer>::ScenePainter<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn resume(&mut self, window: Arc<dyn anyrender::WindowHandle>, width: u32, height: u32) {
|
||||
self.inner.borrow_mut().resume(window, width, height)
|
||||
}
|
||||
|
||||
fn suspend(&mut self) {
|
||||
self.inner.borrow_mut().suspend()
|
||||
}
|
||||
|
||||
fn is_active(&self) -> bool {
|
||||
self.inner.borrow().is_active()
|
||||
}
|
||||
|
||||
fn set_size(&mut self, width: u32, height: u32) {
|
||||
self.inner.borrow_mut().set_size(width, height)
|
||||
}
|
||||
|
||||
fn render<F: FnOnce(&mut Self::ScenePainter<'_>)>(&mut self, draw_fn: F) {
|
||||
self.inner.borrow_mut().render(draw_fn)
|
||||
}
|
||||
}
|
||||
@@ -13,12 +13,16 @@ mod assets;
|
||||
mod contexts;
|
||||
mod dioxus_application;
|
||||
mod dioxus_document;
|
||||
mod dioxus_renderer;
|
||||
mod events;
|
||||
mod mutation_writer;
|
||||
|
||||
use blitz_dom::{ns, Atom, QualName};
|
||||
pub use anyrender_vello::{CustomPaintCtx, CustomPaintSource, TextureHandle};
|
||||
use assets::DioxusNativeNetProvider;
|
||||
use blitz_dom::{ns, LocalName, Namespace, QualName};
|
||||
pub use dioxus_application::{DioxusNativeApplication, DioxusNativeEvent};
|
||||
pub use dioxus_document::DioxusDocument;
|
||||
pub use dioxus_renderer::{use_wgpu, DioxusNativeWindowRenderer, Features, Limits};
|
||||
|
||||
use blitz_shell::{create_default_event_loop, BlitzShellEvent, Config, WindowConfig};
|
||||
use dioxus_core::{ComponentFunction, Element, VirtualDom};
|
||||
@@ -44,12 +48,36 @@ pub fn launch_cfg_with_props<P: Clone + 'static, M: 'static>(
|
||||
app: impl ComponentFunction<P, M>,
|
||||
props: P,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
|
||||
_cfg: Vec<Box<dyn Any>>,
|
||||
configs: Vec<Box<dyn Any>>,
|
||||
) {
|
||||
let _cfg = _cfg
|
||||
.into_iter()
|
||||
.find_map(|cfg| cfg.downcast::<Config>().ok())
|
||||
.unwrap_or_default();
|
||||
// Macro to attempt to downcast a type out of a Box<dyn Any>
|
||||
macro_rules! try_read_config {
|
||||
($input:ident, $store:ident, $kind:ty) => {
|
||||
// Try to downcast the Box<dyn Any> to type $kind
|
||||
match $input.downcast::<$kind>() {
|
||||
// If the type matches then write downcast value to variable $store
|
||||
Ok(value) => {
|
||||
$store = Some(*value);
|
||||
continue;
|
||||
}
|
||||
// Else extract the original Box<dyn Any> value out of the error type
|
||||
// and return it so that we can try again with a different type.
|
||||
Err(cfg) => cfg,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Read config values
|
||||
let mut features = None;
|
||||
let mut limits = None;
|
||||
let mut _config = None;
|
||||
for mut cfg in configs {
|
||||
cfg = try_read_config!(cfg, features, Features);
|
||||
cfg = try_read_config!(cfg, limits, Limits);
|
||||
cfg = try_read_config!(cfg, _config, Config);
|
||||
let _ = cfg;
|
||||
}
|
||||
|
||||
let event_loop = create_default_event_loop::<BlitzShellEvent>();
|
||||
|
||||
// Turn on the runtime and enter it
|
||||
@@ -84,8 +112,23 @@ pub fn launch_cfg_with_props<P: Clone + 'static, M: 'static>(
|
||||
vdom.insert_any_root_context(context());
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
let net_provider = {
|
||||
let proxy = event_loop.create_proxy();
|
||||
let net_provider = DioxusNativeNetProvider::shared(proxy);
|
||||
Some(net_provider)
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "net"))]
|
||||
let net_provider = None;
|
||||
|
||||
// Create document + window from the baked virtualdom
|
||||
let doc = DioxusDocument::new(vdom, net_provider);
|
||||
let renderer = DioxusNativeWindowRenderer::with_features_and_limits(features, limits);
|
||||
let config = WindowConfig::new(Box::new(doc) as _, renderer.clone());
|
||||
|
||||
// Create application
|
||||
let mut application = DioxusNativeApplication::new(event_loop.create_proxy(), vdom);
|
||||
let mut application = DioxusNativeApplication::new(event_loop.create_proxy(), config);
|
||||
|
||||
// Run event loop
|
||||
event_loop.run_app(&mut application).unwrap();
|
||||
@@ -94,8 +137,8 @@ pub fn launch_cfg_with_props<P: Clone + 'static, M: 'static>(
|
||||
pub(crate) fn qual_name(local_name: &str, namespace: Option<&str>) -> QualName {
|
||||
QualName {
|
||||
prefix: None,
|
||||
ns: namespace.map(Atom::from).unwrap_or(ns!(html)),
|
||||
local: Atom::from(local_name),
|
||||
ns: namespace.map(Namespace::from).unwrap_or(ns!(html)),
|
||||
local: LocalName::from(local_name),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user