surfman offscreen
This commit is contained in:
parent
33afd78b9b
commit
04776b4f45
171
src/components/render_panel/monitor/_monitor.rs
Normal file
171
src/components/render_panel/monitor/_monitor.rs
Normal 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=>k::Paned{
|
||||||
|
#[wrap(Some)]
|
||||||
|
#[name="render"]
|
||||||
|
set_start_child=>k::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 => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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 => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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()));
|
||||||
|
|||||||
@ -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!();
|
||||||
|
|||||||
@ -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).
|
||||||
|
|||||||
@ -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,9 +112,10 @@ 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) {
|
||||||
let _ = self;
|
let _ = self;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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};
|
||||||
|
|||||||
@ -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};
|
||||||
|
|||||||
@ -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)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user