surfman offscreen

This commit is contained in:
Tsuki 2024-01-21 10:40:40 +08:00
parent 33afd78b9b
commit 04776b4f45
13 changed files with 400 additions and 160 deletions

View File

@ -0,0 +1,171 @@
use crate::render::{Target, CMS};
use crate::{
components::render_panel::messages::{MonitorInputMsg, MonitorOutputMsg},
coords::{proj::Mercator, Mapper},
data::Npz,
dynamic_col::DynamicCol,
render::{predefined::color_mapper::BoundaryNorm, Layer, Render},
OFFSCREEN, RUNTIME,
};
use glib::clone;
use std::sync::Arc;
use super::sidebar::{sidebar::SideBarModel, Msg, SideBarOutputMsg};
use adw::prelude::*;
use gtk::prelude::StyleContextExt;
use gtk::subclass::root;
use relm4::{
component::{AsyncComponent, AsyncComponentParts},
loading_widgets::LoadingWidgets,
*,
};
pub struct MonitorModel {
sidebar_open: bool,
sidebar_width: i32,
layers: Vec<Layer>,
sidebar: Controller<SideBarModel>,
}
pub struct MonitorWidgets {
paned: gtk::Paned,
}
#[relm4::component(async, pub)]
impl AsyncComponent for MonitorModel {
type Init = ();
type Output = MonitorOutputMsg;
type Input = MonitorInputMsg;
type CommandOutput = ();
view! {
adw::BreakpointBin {
set_hexpand: true,
set_vexpand: true,
set_height_request: 500,
set_width_request: 700,
#[wrap(Some)]
#[name="test"]
set_child = &DynamicCol{
set_end_width: 300,
set_hexpand: true,
set_vexpand: true,
#[wrap(Some)]
#[name="paned"]
set_child_paned=&gtk::Paned{
#[wrap(Some)]
#[name="render"]
set_start_child=&gtk::Frame{
add_css_class: "rb",
set_margin_all: 5,
Render{
add_css_class: "rb",
#[watch]
set_interior_layers: model.layers.clone(),
}
},
#[wrap(Some)]
set_end_child=model.sidebar.widget(),
}
},
}
}
async fn init(
init: Self::Init,
root: Self::Root,
sender: relm4::AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
let sidebar: Controller<SideBarModel> =
SideBarModel::builder()
.launch(())
.forward(sender.input_sender(), |msg| match msg {
SideBarOutputMsg::NewLayer(layer) => MonitorInputMsg::AddLayer(layer),
_ => MonitorInputMsg::None,
});
let model = MonitorModel {
sidebar_open: true,
sidebar_width: 400,
layers: vec![],
sidebar,
};
let widgets = view_output! {};
AsyncComponentParts { model, widgets }
}
async fn update(
&mut self,
msg: Self::Input,
_sender: AsyncComponentSender<Self>,
_root: &Self::Root,
) {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
match msg {
MonitorInputMsg::AddLayer(layer) => {
let f = {
let p = layer.get_prepare();
let mut _p = p.lock().unwrap();
_p.take()
};
println!("hi");
let target = if let Some(f) = f {
let imp = layer.get_imp().unwrap();
let map: Mapper = Mercator::default().into();
let cms = CMS::new(map, (500.0, 500.0));
let canvas = OFFSCREEN.canvas();
let c = f(imp, canvas, cms).await;
Some(c)
} else {
None
};
// RUNTIME.spawn_blocking(|| async move {
// let f = {
// let p = layer.get_prepare();
// let mut _p = p.lock().unwrap();
// _p.take()
// };
// println!("hi");
// if let Some(f) = f {
// let imp = layer.get_imp().unwrap();
// let map: Mapper = Mercator::default().into();
// let cms = CMS::new(map, (500.0, 500.0));
// let canvas = OFFSCREEN.canvas();
// let c = f(imp, canvas, cms).await;
// Some(c)
// } else {
// None
// }
// });
// self.layers.push(layer);
_sender
.output_sender()
.send(MonitorOutputMsg::LayerAdded(0))
.unwrap();
self.sidebar
.sender()
.send(Msg::RefreshList(self.layers.clone()));
}
MonitorInputMsg::RemoveLayer(index) => {
self.layers.remove(index);
_sender
.output_sender()
.send(MonitorOutputMsg::LayerRemoved(0))
.unwrap();
}
MonitorInputMsg::UpdateLayer((idx, f)) => {
f(&mut self.layers[idx]);
_sender
.output_sender()
.send(MonitorOutputMsg::LayerUpdated(0))
.unwrap();
}
MonitorInputMsg::None => {}
}
}
}

View File

@ -1,19 +1,31 @@
use crate::pipeline::offscreen_renderer::OffscreenRenderer;
use crate::render::{Target, CMS};
use crate::{ use crate::{
components::render_panel::messages::{MonitorInputMsg, MonitorOutputMsg}, coords::{proj::Mercator, Mapper}, data::Npz, dynamic_col::DynamicCol, render::{predefined::color_mapper::BoundaryNorm, Layer, Render}, OFFSCREEN, RUNTIME components::render_panel::messages::{MonitorInputMsg, MonitorOutputMsg},
coords::{proj::Mercator, Mapper},
data::Npz,
dynamic_col::DynamicCol,
render::{predefined::color_mapper::BoundaryNorm, Layer, Render},
RUNTIME,
}; };
use glib::clone; use glib::clone;
use std::sync::Arc; use std::sync::{Arc, Mutex};
use crate::render::CMS;
use super::sidebar::{sidebar::SideBarModel, Msg, SideBarOutputMsg}; use super::sidebar::{sidebar::SideBarModel, Msg, SideBarOutputMsg};
use adw::prelude::*; use adw::prelude::*;
use gtk::prelude::StyleContextExt; use gtk::prelude::StyleContextExt;
use gtk::subclass::root; use gtk::subclass::root;
use relm4::{ use relm4::{
component::{AsyncComponent, AsyncComponentParts}, component::{AsyncComponent, AsyncComponentParts, Component},
loading_widgets::LoadingWidgets, loading_widgets::LoadingWidgets,
*, *,
}; };
#[derive(Debug)]
pub enum MonitorCommand {
NewLayer(Layer),
None,
}
pub struct MonitorModel { pub struct MonitorModel {
sidebar_open: bool, sidebar_open: bool,
sidebar_width: i32, sidebar_width: i32,
@ -25,14 +37,15 @@ pub struct MonitorWidgets {
paned: gtk::Paned, paned: gtk::Paned,
} }
#[relm4::component(async, pub)] #[relm4::component(pub)]
impl AsyncComponent for MonitorModel { impl Component for MonitorModel {
type CommandOutput = MonitorCommand;
type Input = MonitorInputMsg;
type Init = (); type Init = ();
type Output = MonitorOutputMsg; type Output = MonitorOutputMsg;
type Input = MonitorInputMsg;
type CommandOutput = ();
view! { view! {
#[root]
adw::BreakpointBin { adw::BreakpointBin {
set_hexpand: true, set_hexpand: true,
set_vexpand: true, set_vexpand: true,
@ -66,11 +79,68 @@ impl AsyncComponent for MonitorModel {
} }
} }
async fn init( fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>, root: &Self::Root) {
match message {
MonitorInputMsg::AddLayer(layer) => {
sender.oneshot_command(async move {
let new_canvas = OffscreenRenderer::new().unwrap();
let f = {
let p = layer.get_prepare();
let mut _p = p.lock().unwrap();
_p.take()
};
let target = if let Some(f) = f {
let imp = layer.get_imp().unwrap();
let map: Mapper = Mercator::default().into();
let cms = CMS::new(map, (3000.0, 3000.0));
let canvas = new_canvas.create_canvas();
let canvas = Arc::new(Mutex::new(canvas));
let c = f(imp, canvas, cms).await;
Some(c)
// None
} else {
None
};
if let Some(target) = target {
layer.set_render_target(target);
}
MonitorCommand::NewLayer(layer)
});
sender
.output_sender()
.send(MonitorOutputMsg::LayerAdded(0))
.unwrap();
self.sidebar
.sender()
.send(Msg::RefreshList(self.layers.clone()));
}
MonitorInputMsg::RemoveLayer(index) => {
self.layers.remove(index);
sender
.output_sender()
.send(MonitorOutputMsg::LayerRemoved(0))
.unwrap();
}
MonitorInputMsg::UpdateLayer((idx, f)) => {
f(&mut self.layers[idx]);
sender
.output_sender()
.send(MonitorOutputMsg::LayerUpdated(0))
.unwrap();
}
MonitorInputMsg::None => {}
}
}
fn init(
init: Self::Init, init: Self::Init,
root: Self::Root, root: &Self::Root,
sender: relm4::AsyncComponentSender<Self>, sender: ComponentSender<Self>,
) -> AsyncComponentParts<Self> { ) -> ComponentParts<Self> {
let sidebar: Controller<SideBarModel> = let sidebar: Controller<SideBarModel> =
SideBarModel::builder() SideBarModel::builder()
.launch(()) .launch(())
@ -86,60 +156,23 @@ impl AsyncComponent for MonitorModel {
}; };
let widgets = view_output! {}; let widgets = view_output! {};
AsyncComponentParts { model, widgets } ComponentParts { model, widgets }
} }
async fn update( fn update_cmd(
&mut self, &mut self,
msg: Self::Input, msg: Self::CommandOutput,
_sender: AsyncComponentSender<Self>, _sender: ComponentSender<Self>,
_root: &Self::Root, _root: &Self::Root,
) { ) {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
match msg { match msg {
MonitorInputMsg::AddLayer(layer) => { MonitorCommand::NewLayer(layer) => {
RUNTIME.spawn_blocking(|| async move { self.layers.push(layer);
if let Some(f) = layer.get_prepare() {
let imp = layer.get_imp();
let map: Mapper = Mercator::default().into();
let cms = CMS::new(map, (500.0,500.0));
let imp = &imp.lock().unwrap();
let i = imp.unwrap();
let c = (f)(i.clone(), OFFSCREEN.canvas(),cms).await;
Some(c)
} else {None} });
// self.layers.push(layer);
_sender
.output_sender()
.send(MonitorOutputMsg::LayerAdded(0))
.unwrap();
self.sidebar self.sidebar
.sender() .sender()
.send(Msg::RefreshList(self.layers.clone())); .send(Msg::RefreshList(self.layers.clone()));
} }
MonitorInputMsg::RemoveLayer(index) => { _ => {}
self.layers.remove(index);
_sender
.output_sender()
.send(MonitorOutputMsg::LayerRemoved(0))
.unwrap();
}
MonitorInputMsg::UpdateLayer((idx, f)) => {
f(&mut self.layers[idx]);
_sender
.output_sender()
.send(MonitorOutputMsg::LayerUpdated(0))
.unwrap();
}
MonitorInputMsg::None => {}
} }
} }
} }

View File

@ -25,7 +25,7 @@ pub struct SideBarModel {
#[derive(Debug)] #[derive(Debug)]
pub enum Msg { pub enum Msg {
RefreshList(Vec<Layer>), RefreshList(Vec<Layer>),
None None,
} }
#[derive(Debug)] #[derive(Debug)]
@ -65,6 +65,7 @@ impl SimpleComponent for SideBarModel {
gtk::Button { gtk::Button {
set_label: "Add Layer", set_label: "Add Layer",
connect_clicked[sender] => move |_| { connect_clicked[sender] => move |_| {
println!("hello");
sender.output( sender.output(
SideBarOutputMsg::NewLayer( SideBarOutputMsg::NewLayer(
Layer::grid_render_layer_with_path( Layer::grid_render_layer_with_path(
@ -111,7 +112,6 @@ impl SimpleComponent for SideBarModel {
let mut bottom_bar_vec = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender()); let mut bottom_bar_vec = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
{ {
let mut bottom_bar_vec_guard = bottom_bar_vec.guard(); let mut bottom_bar_vec_guard = bottom_bar_vec.guard();
bottom_bar_vec_guard.push_back(BottomBarModel::new("add-filled".to_string())); bottom_bar_vec_guard.push_back(BottomBarModel::new("add-filled".to_string()));

View File

@ -8,8 +8,8 @@ use relm4::{
}; };
pub struct RenderPanelModel { pub struct RenderPanelModel {
// monitor: Controller<MonitorModel>, monitor: Controller<MonitorModel>,
monitor: AsyncController<MonitorModel>, // monitor: AsyncController<MonitorModel>,
} }
#[relm4::component(pub)] #[relm4::component(pub)]
@ -32,10 +32,13 @@ impl SimpleComponent for RenderPanelModel {
root: &Self::Root, root: &Self::Root,
sender: relm4::ComponentSender<Self>, sender: relm4::ComponentSender<Self>,
) -> relm4::ComponentParts<Self> { ) -> relm4::ComponentParts<Self> {
// let monitor: AsyncController<MonitorModel> = MonitorModel::builder()
// .launch(())
// .forward(sender.input_sender(), |msg| {});
let monitor: AsyncController<MonitorModel> = MonitorModel::builder() let monitor: Controller<MonitorModel> = MonitorModel::builder()
.launch(()) .launch(())
.forward(sender.input_sender(), |msg| {}); .forward(sender.input_sender(), |_| {});
let model = RenderPanelModel { monitor }; let model = RenderPanelModel { monitor };
let widgets = view_output!(); let widgets = view_output!();

View File

@ -25,7 +25,7 @@ const APP_ID: &str = "org.gtk_rs.HelloWorld2";
static RUNTIME: Lazy<Runtime> = static RUNTIME: Lazy<Runtime> =
Lazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed.")); Lazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed."));
static OFFSCREEN: Lazy<OffscreenRenderer> = Lazy::new(|| OffscreenRenderer::new().expect("Can't create offscreen renderer.")); // static OFFSCREEN: Lazy<OffscreenRenderer> = Lazy::new(|| OffscreenRenderer::new().expect("Can't create offscreen renderer."));
fn main() { fn main() {
// Load GL pointers from epoxy (GL context management library used by GTK). // Load GL pointers from epoxy (GL context management library used by GTK).

View File

@ -1,39 +1,42 @@
use euclid::Size2D; use euclid::Size2D;
use std::ops::{Deref, DerefMut};
use femtovg::{renderer::OpenGl, Canvas}; use femtovg::{renderer::OpenGl, Canvas};
use lazy_static::__Deref; use lazy_static::__Deref;
use std::borrow::BorrowMut; use std::borrow::BorrowMut;
use std::num::NonZeroU32; use std::num::NonZeroU32;
use std::ops::{Deref, DerefMut};
use std::sync::{Mutex, RwLock}; use std::sync::{Mutex, RwLock};
use std::{cell::RefCell, sync::Arc}; use std::{cell::RefCell, sync::Arc};
use surfman::{device, Adapter, Connection, Context, Device, Error}; use surfman::platform::system::connection;
use surfman::{
device, Adapter, Connection, Context, ContextAttributeFlags, Device, Error, GLApi,
NativeConnection, NativeDevice,
};
pub struct OffscreenRenderer { pub struct OffscreenRenderer {
context: Arc<RwLock<Context>>, context: Arc<RwLock<Context>>,
device: Device, device: Device,
// renderer: Arc<Mutex<femtovg::renderer::OpenGl>>, fbo: NonZeroU32,
canvas: Arc<Mutex<CanvasWrapper>>, // canvas: Arc<Mutex<CanvasWrapper>>,
} }
impl OffscreenRenderer { impl OffscreenRenderer {
pub fn new() -> Result<Self, surfman::Error> { pub fn new() -> Result<Self, surfman::Error> {
let connection = Connection::new()?; let connection = Connection::new()?;
let adapter = connection.create_adapter()?; let adapter = connection.create_hardware_adapter()?;
let mut device = connection.create_device(&adapter)?; let mut device = connection.create_device(&adapter)?;
let api = connection.gl_api();
let api = device.gl_api();
let descriptor = device.create_context_descriptor(&surfman::ContextAttributes { let descriptor = device.create_context_descriptor(&surfman::ContextAttributes {
version: surfman::GLVersion::new(3, 3), version: surfman::GLVersion::new(3, 3),
flags: surfman::ContextAttributeFlags::empty(), flags: ContextAttributeFlags::DEPTH.union(ContextAttributeFlags::STENCIL),
})?; })?;
let mut context = device.create_context(&descriptor, None)?; let mut context = device.create_context(&descriptor, None)?;
let mut surface = device.create_surface( let surface = device.create_surface(
&context, &context,
surfman::SurfaceAccess::GPUOnly, surfman::SurfaceAccess::GPUCPU,
surfman::SurfaceType::Generic { surfman::SurfaceType::Generic {
size: euclid::Size2D::new(500, 500), size: euclid::Size2D::new(3000, 3000),
}, },
)?; )?;
@ -41,32 +44,39 @@ impl OffscreenRenderer {
device device
.bind_surface_to_context(&mut context, surface) .bind_surface_to_context(&mut context, surface)
.expect("Failed to bind surface to context"); .expect("Failed to bind surface to context");
device.make_context_current(&context).unwrap(); device.make_context_current(&context).unwrap();
Ok(Self {
context: Arc::new(RwLock::new(context)),
device,
fbo: NonZeroU32::new(surface_info.framebuffer_object).unwrap(),
})
}
pub fn create_canvas(&self) -> CanvasWrapper {
use glow::HasContext;
static LOAD_FN: fn(&str) -> *const std::ffi::c_void = static LOAD_FN: fn(&str) -> *const std::ffi::c_void =
|s| epoxy::get_proc_addr(s) as *const _; |s| epoxy::get_proc_addr(s) as *const _;
let (mut renderer, fbo) = unsafe { let (mut renderer, fbo) = unsafe {
let renderer = OpenGl::new_from_function(LOAD_FN).expect("Cannot create renderer"); let renderer = OpenGl::new_from_function(LOAD_FN).expect("Cannot create renderer");
let fbo = let ctx = glow::Context::from_loader_function(LOAD_FN);
glow::NativeFramebuffer(NonZeroU32::new(surface_info.framebuffer_object).unwrap());
let fbo = ctx.create_framebuffer().expect("can't create framebuffer");
let cbo = ctx.create_buffer().expect("can't create color buffer");
// let id = NonZeroU32::new(ctx.get_parameter_i32(glow::DRAW_FRAMEBUFFER_BINDING) as u32)
// .expect("No GTK provided framebuffer binding");
ctx.bind_framebuffer(glow::FRAMEBUFFER, None);
// let fbo = glow::NativeFramebuffer(id);
(renderer, fbo) (renderer, fbo)
}; };
renderer.set_screen_target(Some(fbo)); renderer.set_screen_target(Some(fbo));
let mut canvas = Canvas::new(renderer).expect("Cannot create canvas"); let mut canvas = Canvas::new(renderer).expect("Cannot create canvas");
canvas.set_size(500, 500, 1.0); canvas.set_size(3000, 3000, 1.0);
Ok(Self { CanvasWrapper::new(canvas)
context: Arc::new(RwLock::new(context)),
device,
canvas: Arc::new(Mutex::new(CanvasWrapper::new(canvas))),
})
}
pub fn canvas(&self) -> Arc<Mutex<CanvasWrapper>>{
self.canvas.clone()
} }
} }
@ -78,12 +88,8 @@ impl Drop for OffscreenRenderer {
} }
} }
unsafe impl Send for OffscreenRenderer {} unsafe impl Send for OffscreenRenderer {}
unsafe impl Sync for OffscreenRenderer {} unsafe impl Sync for OffscreenRenderer {}
pub struct CanvasWrapper(femtovg::Canvas<OpenGl>); pub struct CanvasWrapper(femtovg::Canvas<OpenGl>);
impl CanvasWrapper { impl CanvasWrapper {
@ -106,6 +112,7 @@ impl DerefMut for CanvasWrapper {
} }
unsafe impl Send for CanvasWrapper {} unsafe impl Send for CanvasWrapper {}
unsafe impl Sync for CanvasWrapper {}
impl Drop for CanvasWrapper { impl Drop for CanvasWrapper {
fn drop(&mut self) { fn drop(&mut self) {

View File

@ -1,3 +1,5 @@
use std::ops::Range;
use geo_types::LineString; use geo_types::LineString;
use crate::coords::Mapper; use crate::coords::Mapper;
@ -21,6 +23,16 @@ impl CMS {
} }
} }
pub fn set_lat_range(&mut self, lat_range: Range<f64>) {
self.mapper.set_lat_range(lat_range);
self.bounds = self.mapper.get_bounds()
}
pub fn set_lon_range(&mut self, lon_range: Range<f64>) {
self.mapper.set_lon_range(lon_range);
self.bounds = self.mapper.get_bounds();
}
pub fn map(&self, loc: (f64, f64)) -> Option<(f32, f32)> { pub fn map(&self, loc: (f64, f64)) -> Option<(f32, f32)> {
self.mapper.map(loc).ok().map(|(x, y)| { self.mapper.map(loc).ok().map(|(x, y)| {
// println!("x: {}, y: {}", x, y); // println!("x: {}, y: {}", x, y);

View File

@ -10,29 +10,35 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
type PrepareFunc = Box< type PrepareFunc = Arc<
dyn FnOnce( Mutex<
LayerImplSync, Option<
// Box<dyn LayerImpl + Send + Sync>, Box<
Arc<Mutex<CanvasWrapper>>, dyn FnOnce(
CMS, LayerImplSync,
) -> Pin<Box<dyn Future<Output = Target> + Send + Sync>> // Box<dyn LayerImpl + Send + Sync>,
+ Sync Arc<Mutex<CanvasWrapper>>,
+ Send, CMS,
)
-> Pin<Box<dyn Future<Output = Target> + Send + Sync>>
+ Sync
+ Send,
>,
>,
>,
>; >;
type DrawFunc = Box<dyn Fn(&Layer, Render, (f32, f32)) + Send + Sync>; type DrawFunc = Arc<dyn Fn(&Layer, Render, (f32, f32)) + Send + Sync>;
// type LayerImplSync = Box<dyn LayerImpl + Send + Sync>; // type LayerImplSync = Box<dyn LayerImpl + Send + Sync>;
type LayerImplSync = Arc<dyn LayerImpl + Send + Sync>; pub type LayerImplSync = Arc<Mutex<Box<dyn LayerImpl + Send + Sync>>>;
#[derive(Clone)] #[derive(Clone)]
pub struct Layer { pub struct Layer {
pub visiable: bool, pub visiable: bool,
pub name: String, pub name: String,
target: Arc<Mutex<Option<Target>>>, target: Arc<Mutex<Option<Target>>>,
// prepare: Arc<Option<PrepareFunc>>, prepare: PrepareFunc,
prepare:Option<Arc<PrepareFunc>>, imp: Option<Arc<Mutex<Box<dyn LayerImpl + Send + Sync>>>>,
imp: Arc<Mutex<Option<LayerImplSync>>>, draw: DrawFunc,
draw: Arc<DrawFunc>,
} }
impl Debug for Layer { impl Debug for Layer {
@ -46,17 +52,14 @@ impl Debug for Layer {
} }
pub trait LayerImpl: Debug { pub trait LayerImpl: Debug {
fn draw(&self, canvas: &mut Canvas<OpenGl>, cms: &CMS) -> Option<Target>; fn draw(&self, canvas: &mut Canvas<OpenGl>, cms: CMS) -> Option<Target>;
} }
impl Layer { impl Layer {
pub fn new< pub fn new<
FU: Future<Output = Target> + Send + Sync + 'static, FU: Future<Output = Target> + Send + Sync + 'static,
F: 'static + Fn(&Self, Render, (f32, f32)) + Send + Sync, F: 'static + Fn(&Self, Render, (f32, f32)) + Send + Sync,
PREPARE: FnOnce(LayerImplSync, Arc<Mutex<CanvasWrapper>>, CMS) -> FU PREPARE: FnOnce(LayerImplSync, Arc<Mutex<CanvasWrapper>>, CMS) -> FU + Send + Sync + 'static,
+ Send
+ Sync
+ 'static,
IMP: LayerImpl + Sync + Send + 'static, IMP: LayerImpl + Sync + Send + 'static,
>( >(
visiable: bool, visiable: bool,
@ -69,25 +72,28 @@ impl Layer {
visiable, visiable,
target: Arc::new(Mutex::new(None)), target: Arc::new(Mutex::new(None)),
name: layer_name, name: layer_name,
// prepare: Arc::new(prepare), prepare: Arc::new(Mutex::new(prepare.map(|p| {
prepare: prepare.map(|p| { Box::new(move |a, b, c| {
Arc::new(Box::new( Box::pin(p(a, b, c))
move |a: LayerImplSync, as Pin<Box<dyn Future<Output = Target> + Send + Sync + 'static>>
b: Arc<Mutex<CanvasWrapper>>, })
c: CMS| as Box<
-> Pin<Box<dyn Future<Output = Target> + Send + Sync>> { dyn FnOnce(
Box::pin(p(a, b, c)) LayerImplSync,
}, Arc<Mutex<CanvasWrapper>>,
) as PrepareFunc) CMS,
}), )
-> Pin<Box<dyn Future<Output = Target> + Send + Sync>>
+ Sync
+ Send,
>
}))),
draw: Arc::new(Box::new(draw)), draw: Arc::new(Box::new(draw)),
imp: Arc::new(Mutex::new( imp: imp.map(|i| {
imp.map(|x| Arc::new(Mutex::new(x)) as LayerImplSync), Arc::new(Mutex::new(
)), Box::new(i) as Box<dyn LayerImpl + Send + Sync + 'static>
// imp: Arc::new(Mutex::new(imp.map(|x| Box::new(x) as Box<dyn LayerImpl + Send + Sync>))), ))
// imp: RefCell::new( }),
// imp.map(|x| Arc::new(Box::new(x) as Box<dyn LayerImpl + Send + Sync>)),
// ),
} }
} }
@ -98,22 +104,20 @@ impl Layer {
} }
} }
pub fn get_prepare(&self) -> Option<Arc<PrepareFunc>> { pub fn get_prepare(&self) -> PrepareFunc {
let c= self.prepare.clone(); self.prepare.clone()
c
} }
pub fn set_render_target(&self, target: Target) { pub fn set_render_target(&self, target: Target) {
self.target.lock().unwrap().replace(target); self.target.lock().unwrap().replace(target);
// *self.target.borrow_mut() = Some(target);
} }
pub fn render_target(&self) -> Option<Target> { pub fn render_target(&self) -> Option<Target> {
self.target.lock().unwrap().clone() self.target.lock().unwrap().clone()
// self.target.borrow().clone()
} }
pub fn get_imp(&self) -> Arc<Mutex<Option<LayerImplSync>>> { pub fn get_imp(&self) -> Option<Arc<Mutex<Box<dyn LayerImpl + Sync + Send + 'static>>>> {
// self.imp.map(|p| p.clone())
self.imp.clone() self.imp.clone()
} }
} }

View File

@ -2,7 +2,7 @@ mod imp;
mod layers; mod layers;
use crate::render::Render; use crate::render::Render;
use femtovg::{renderer::OpenGl, Canvas}; use femtovg::{renderer::OpenGl, Canvas};
pub use layers::{Layer, LayerImpl, Target}; pub use layers::{Layer, LayerImpl, LayerImplSync, Target};
use std::cell::Ref; use std::cell::Ref;
use crate::render::imp::{RenderConfig, RenderStatus}; use crate::render::imp::{RenderConfig, RenderStatus};

View File

@ -14,7 +14,7 @@ use glib::clone;
pub use glib::subclass::prelude::*; pub use glib::subclass::prelude::*;
use gtk::traits::WidgetExt; use gtk::traits::WidgetExt;
use gtk::{EventControllerScrollFlags, Inhibit}; use gtk::{EventControllerScrollFlags, Inhibit};
pub use interior::{Layer, LayerImpl, Target}; pub use interior::{Layer, LayerImpl, LayerImplSync, Target};
use relm4::once_cell::sync::Lazy; use relm4::once_cell::sync::Lazy;
use std::cell::{Ref, RefCell, RefMut}; use std::cell::{Ref, RefCell, RefMut};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};

View File

@ -100,7 +100,7 @@ where
fn render( fn render(
&self, &self,
canvas: &mut Canvas<OpenGl>, canvas: &mut Canvas<OpenGl>,
cms: &CMS, mut cms: CMS,
data: &Self::Data, data: &Self::Data,
size: (f32, f32), size: (f32, f32),
) -> Target { ) -> Target {
@ -109,18 +109,32 @@ where
.create_image_empty(w as usize, h as usize, Rgba8, ImageFlags::empty()) .create_image_empty(w as usize, h as usize, Rgba8, ImageFlags::empty())
.expect("Can't Create Image"); .expect("Can't Create Image");
canvas.image_size(new_img).unwrap();
canvas.set_render_target(RenderTarget::Image(new_img));
let _data = data.data.view(); let _data = data.data.view();
let (_dim1, _dim2) = meshgrid(data.dim1.view(), data.dim2.view()); let (_dim1, _dim2) = meshgrid(data.dim1.view(), data.dim2.view());
let lat_start = data.dim2.view().first().unwrap().clone();
let lat_end = data.dim2.view().last().unwrap().clone();
let lon_start = data.dim1.view().first().unwrap().clone();
let lon_end = data.dim1.view().last().unwrap().clone();
cms.set_lat_range(lat_start..lat_end);
cms.set_lon_range(lon_start..lon_end);
self.draw_2d( self.draw_2d(
canvas, canvas,
cms, &cms,
_data, _data,
(_dim1.view(), _dim2.view()), (_dim1.view(), _dim2.view()),
(w, h), (w, h),
data.fill_value, data.fill_value,
); );
canvas.set_render_target(RenderTarget::Screen);
let d1_start = (data.dim1.view()).first().unwrap().clone(); let d1_start = (data.dim1.view()).first().unwrap().clone();
let d1_end = (data.dim1.view()).last().unwrap().clone(); let d1_end = (data.dim1.view()).last().unwrap().clone();
@ -170,19 +184,14 @@ where
fn draw( fn draw(
&self, &self,
canvas: &mut femtovg::Canvas<femtovg::renderer::OpenGl>, canvas: &mut femtovg::Canvas<femtovg::renderer::OpenGl>,
cms: &crate::render::cms::CMS, cms: crate::render::cms::CMS,
) -> Option<Target> { ) -> Option<Target> {
let new_img = canvas canvas.save();
.create_image_empty(3000, 3000, Rgba8, ImageFlags::empty()) canvas.reset();
.expect("Can't Create Image"); let result = self
.renderer
if let Ok(_) = canvas.image_size(new_img) { .render(canvas, cms, &self.data, (3000.0, 3000.0));
canvas.reset(); canvas.restore();
canvas.set_render_target(RenderTarget::Image(new_img)); return Some(result);
}
canvas.set_render_target(RenderTarget::Screen);
Some(self.renderer.render(canvas,cms, &self.data, (3000.0, 3000.0)))
} }
} }

View File

@ -1,3 +1,5 @@
use femtovg::ImageFlags;
use femtovg::PixelFormat::Rgba8;
use femtovg::{renderer::OpenGl, Canvas, Paint}; use femtovg::{renderer::OpenGl, Canvas, Paint};
use num_traits::{Num, NumOps}; use num_traits::{Num, NumOps};
use std::path::Path; use std::path::Path;
@ -6,6 +8,7 @@ use std::sync::Mutex;
use crate::pipeline::offscreen_renderer::CanvasWrapper; use crate::pipeline::offscreen_renderer::CanvasWrapper;
use crate::render::cms::CMS; use crate::render::cms::CMS;
use crate::render::LayerImplSync;
use crate::render::{LayerImpl, Target}; use crate::render::{LayerImpl, Target};
use crate::{ use crate::{
data::{AsyncDataLoader, DataLoader, Radar2d}, data::{AsyncDataLoader, DataLoader, Radar2d},
@ -41,12 +44,10 @@ impl Layer {
}, },
layer_name, layer_name,
Some( Some(
|renderer: Arc<Mutex<dyn LayerImpl + Send + Sync>>, |renderer: LayerImplSync, c: Arc<Mutex<CanvasWrapper>>, cms: CMS| async move {
c: Arc<Mutex<CanvasWrapper>>,
cms: CMS| async move {
let mut canvas = c.lock().unwrap(); let mut canvas = c.lock().unwrap();
let c = &mut *canvas; let renderer = renderer.lock().unwrap();
let img = renderer.lock().unwrap().draw(c, &cms).unwrap(); let img = renderer.draw(&mut canvas, cms).unwrap();
img img
}, },
), ),

View File

@ -8,7 +8,7 @@ pub trait DataRenderer {
fn render( fn render(
&self, &self,
canvas: &mut Canvas<OpenGl>, canvas: &mut Canvas<OpenGl>,
cms: &CMS, cms: CMS,
data: &Self::Data, data: &Self::Data,
size: (f32, f32), size: (f32, f32),
) -> Target; ) -> Target;