offscreen render success
This commit is contained in:
parent
acbc81b733
commit
ce23512f35
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -913,9 +913,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdeflate"
|
name = "fdeflate"
|
||||||
version = "0.3.0"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
|
checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"simd-adler32",
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
@ -2697,9 +2697,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.9"
|
version = "0.17.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11"
|
checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use adw::prelude::WidgetExt;
|
use adw::prelude::WidgetExt;
|
||||||
use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt};
|
use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt};
|
||||||
use relm4::*;
|
use relm4::*;
|
||||||
|
use relm4_components::open_button::{OpenButton, OpenButtonSettings};
|
||||||
|
use relm4_components::open_dialog::OpenDialogSettings;
|
||||||
|
|
||||||
pub struct ControlPanelModel;
|
pub struct ControlPanelModel {
|
||||||
|
open_button: Controller<OpenButton>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum HeaderOutput {
|
pub enum HeaderOutput {
|
||||||
@ -11,11 +17,16 @@ pub enum HeaderOutput {
|
|||||||
Export,
|
Export,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum AppMsg {
|
||||||
|
Open(PathBuf),
|
||||||
|
}
|
||||||
|
|
||||||
#[relm4::component(pub)]
|
#[relm4::component(pub)]
|
||||||
impl SimpleComponent for ControlPanelModel {
|
impl SimpleComponent for ControlPanelModel {
|
||||||
type Init = i8;
|
type Init = i8;
|
||||||
type Output = HeaderOutput;
|
type Output = HeaderOutput;
|
||||||
type Input = ();
|
type Input = AppMsg;
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
#[root]
|
#[root]
|
||||||
@ -23,9 +34,7 @@ impl SimpleComponent for ControlPanelModel {
|
|||||||
set_orientation: gtk::Orientation::Horizontal,
|
set_orientation: gtk::Orientation::Horizontal,
|
||||||
set_spacing: 10,
|
set_spacing: 10,
|
||||||
set_size_request: (100, 150),
|
set_size_request: (100, 150),
|
||||||
gtk::Button {
|
model.open_button.widget(),
|
||||||
set_label: "View",
|
|
||||||
},
|
|
||||||
gtk::Button {
|
gtk::Button {
|
||||||
set_label: "Edit",
|
set_label: "Edit",
|
||||||
},
|
},
|
||||||
@ -40,11 +49,23 @@ impl SimpleComponent for ControlPanelModel {
|
|||||||
root: &Self::Root,
|
root: &Self::Root,
|
||||||
sender: relm4::ComponentSender<Self>,
|
sender: relm4::ComponentSender<Self>,
|
||||||
) -> relm4::ComponentParts<Self> {
|
) -> relm4::ComponentParts<Self> {
|
||||||
let model = ControlPanelModel {};
|
let open_button = OpenButton::builder()
|
||||||
// Insert the macro code generation here
|
.launch(OpenButtonSettings {
|
||||||
|
dialog_settings: OpenDialogSettings::default(),
|
||||||
|
text: "Open file",
|
||||||
|
recently_opened_files: Some(".recent_files"),
|
||||||
|
max_recent_files: 10,
|
||||||
|
})
|
||||||
|
.forward(sender.input_sender(), AppMsg::Open);
|
||||||
|
|
||||||
|
let model = ControlPanelModel { open_button };
|
||||||
let widgets = view_output!();
|
let widgets = view_output!();
|
||||||
|
|
||||||
ComponentParts { model, widgets }
|
ComponentParts { model, widgets }
|
||||||
}
|
}
|
||||||
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {}
|
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
|
||||||
|
match msg {
|
||||||
|
AppMsg::Open(p) => println!("Open file: {:?}", p),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,9 +100,7 @@ impl Component for MonitorModel {
|
|||||||
let cms = CMS::new(map, (3000.0, 3000.0));
|
let cms = CMS::new(map, (3000.0, 3000.0));
|
||||||
let canvas = Arc::new(Mutex::new(canvas));
|
let canvas = Arc::new(Mutex::new(canvas));
|
||||||
let c = f(imp, canvas, cms).await;
|
let c = f(imp, canvas, cms).await;
|
||||||
|
|
||||||
Some(c)
|
Some(c)
|
||||||
// None
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
use gtk::prelude::*;
|
||||||
use gtk::{gio, glib, Application, ApplicationWindow};
|
use gtk::{gio, glib, Application, ApplicationWindow};
|
||||||
use pipeline::offscreen_renderer::OffscreenRenderer;
|
use pipeline::offscreen_renderer::OffscreenRenderer;
|
||||||
|
use relm4::menu;
|
||||||
|
use relm4::RelmApp;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
use utils::creator;
|
||||||
mod chart;
|
mod chart;
|
||||||
mod components;
|
mod components;
|
||||||
mod coords;
|
mod coords;
|
||||||
@ -15,16 +19,13 @@ mod render;
|
|||||||
mod window;
|
mod window;
|
||||||
use components::app::{AppMode, AppModel};
|
use components::app::{AppMode, AppModel};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
const APP_ID: &str = "org.gtk_rs.HelloWorld2";
|
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<Mutex<OffscreenRenderer>> = Lazy::new(|| {
|
// static OFFSCREEN: Lazy<OffscreenRenderer> = Lazy::new(|| OffscreenRenderer::new().expect("Can't create offscreen renderer."));
|
||||||
// Mutex::new(OffscreenRenderer::new(3000, 3000).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).
|
||||||
|
|||||||
@ -52,8 +52,8 @@ impl OffscreenRenderer {
|
|||||||
gl::load_with(|symbol_name| device.get_proc_address(&context, symbol_name));
|
gl::load_with(|symbol_name| device.get_proc_address(&context, symbol_name));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
debug_assert_eq!(gl::GetError(), gl::NO_ERROR);
|
|
||||||
gl::BindFramebuffer(gl::FRAMEBUFFER, surface_info.framebuffer_object);
|
gl::BindFramebuffer(gl::FRAMEBUFFER, surface_info.framebuffer_object);
|
||||||
|
gl::Viewport(0, 0, width, height);
|
||||||
debug_assert_eq!(gl::GetError(), gl::NO_ERROR);
|
debug_assert_eq!(gl::GetError(), gl::NO_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,9 +68,7 @@ impl OffscreenRenderer {
|
|||||||
|
|
||||||
pub fn create_canvas(&mut self) -> CanvasWrapper {
|
pub fn create_canvas(&mut self) -> CanvasWrapper {
|
||||||
let (w, h) = self.size;
|
let (w, h) = self.size;
|
||||||
let mut pixels: Vec<u8> = vec![0; w as usize * h as usize * 4];
|
let (mut renderer, fbo) = unsafe {
|
||||||
|
|
||||||
let (mut renderer, fbo, ctx) = unsafe {
|
|
||||||
let renderer = OpenGl::new_from_function(|s| {
|
let renderer = OpenGl::new_from_function(|s| {
|
||||||
self.device
|
self.device
|
||||||
.get_proc_address(&self.context.read().unwrap(), s) as *const _
|
.get_proc_address(&self.context.read().unwrap(), s) as *const _
|
||||||
@ -82,66 +80,45 @@ impl OffscreenRenderer {
|
|||||||
.get_proc_address(&self.context.read().unwrap(), s) as *const _
|
.get_proc_address(&self.context.read().unwrap(), s) as *const _
|
||||||
});
|
});
|
||||||
|
|
||||||
let fbo = glow::NativeFramebuffer(self.fbo);
|
let surface_info = self
|
||||||
|
.device
|
||||||
|
.context_surface_info(&self.context.read().unwrap())
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let fbo =
|
||||||
|
glow::NativeFramebuffer(NonZeroU32::new(surface_info.framebuffer_object).unwrap());
|
||||||
ctx.bind_framebuffer(glow::FRAMEBUFFER, None);
|
ctx.bind_framebuffer(glow::FRAMEBUFFER, None);
|
||||||
(renderer, fbo, ctx)
|
(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(3000, 3000, 1.0);
|
canvas.set_size(w as u32, h as u32, 1.0);
|
||||||
|
|
||||||
let img = canvas
|
|
||||||
.create_image_empty(
|
|
||||||
3000,
|
|
||||||
3000,
|
|
||||||
femtovg::PixelFormat::Rgba8,
|
|
||||||
femtovg::ImageFlags::empty(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
canvas.set_render_target(femtovg::RenderTarget::Image(img));
|
|
||||||
let mut path = femtovg::Path::new();
|
|
||||||
path.rect(0.0, 0.0, 300.0, 300.0);
|
|
||||||
canvas.fill_path(
|
|
||||||
&mut path,
|
|
||||||
&femtovg::Paint::color(femtovg::Color::rgb(255, 0, 0)),
|
|
||||||
);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
ctx.get_tex_image(
|
|
||||||
glow::TEXTURE_2D,
|
|
||||||
0,
|
|
||||||
glow::RGBA,
|
|
||||||
glow::UNSIGNED_BYTE,
|
|
||||||
glow::PixelPackData::Slice(&mut pixels),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// unsafe {
|
|
||||||
// let status = gl::CheckFramebufferStatus(gl::FRAMEBUFFER);
|
|
||||||
// println!("status: {}", status);
|
|
||||||
// gl::ReadPixels(
|
|
||||||
// 0,
|
|
||||||
// 0,
|
|
||||||
// w,
|
|
||||||
// h,
|
|
||||||
// gl::RGBA,
|
|
||||||
// gl::UNSIGNED_BYTE,
|
|
||||||
// pixels.as_mut_ptr() as *mut GLvoid,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// debug_assert_eq!(gl::GetError(), gl::NO_ERROR);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if let Some(max) = pixels.iter().max() {
|
|
||||||
println!("The maximum value is {}", max);
|
|
||||||
} else {
|
|
||||||
println!("The vector is empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
CanvasWrapper::new(canvas)
|
CanvasWrapper::new(canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_mem_img(&self) -> Vec<u8> {
|
||||||
|
let (w, h) = self.size;
|
||||||
|
let mut pixels: Vec<u8> = vec![0; w as usize * h as usize * 4];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::ReadPixels(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
gl::RGBA,
|
||||||
|
gl::UNSIGNED_BYTE,
|
||||||
|
pixels.as_mut_ptr() as *mut GLvoid,
|
||||||
|
);
|
||||||
|
|
||||||
|
debug_assert_eq!(gl::GetError(), gl::NO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for OffscreenRenderer {
|
impl Drop for OffscreenRenderer {
|
||||||
|
|||||||
@ -112,8 +112,8 @@ impl Layer {
|
|||||||
self.target.lock().unwrap().replace(target);
|
self.target.lock().unwrap().replace(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_target(&self) -> Option<Target> {
|
pub fn render_target(&self) -> Arc<Mutex<Option<Target>>> {
|
||||||
self.target.lock().unwrap().clone()
|
self.target.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_imp(&self) -> Option<Arc<Mutex<Box<dyn LayerImpl + Sync + Send + 'static>>>> {
|
pub fn get_imp(&self) -> Option<Arc<Mutex<Box<dyn LayerImpl + Sync + Send + 'static>>>> {
|
||||||
@ -122,16 +122,22 @@ impl Layer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Target {
|
pub struct Target {
|
||||||
pub target: ImageId,
|
pub target: TargetType,
|
||||||
width: f32,
|
pub width: f32,
|
||||||
height: f32,
|
pub height: f32,
|
||||||
bounds: (Range, Range),
|
pub bounds: (Range, Range),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum TargetType {
|
||||||
|
ImageId(ImageId),
|
||||||
|
Mem(Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Target {
|
impl Target {
|
||||||
pub fn new(target: ImageId, width: f32, height: f32, bounds: (Range, Range)) -> Self {
|
pub fn new(target: TargetType, width: f32, height: f32, bounds: (Range, Range)) -> Self {
|
||||||
Self {
|
Self {
|
||||||
target,
|
target,
|
||||||
width,
|
width,
|
||||||
@ -157,4 +163,8 @@ impl Target {
|
|||||||
let p1 = (x.0, y.1);
|
let p1 = (x.0, y.1);
|
||||||
render.map(p1).unwrap()
|
render.map(p1).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_target(&mut self, target: TargetType) {
|
||||||
|
self.target = target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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, LayerImplSync, Target};
|
pub use layers::{Layer, LayerImpl, LayerImplSync, Target, TargetType};
|
||||||
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, LayerImplSync, Target};
|
pub use interior::*;
|
||||||
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};
|
||||||
|
|||||||
@ -3,14 +3,16 @@ use femtovg::{
|
|||||||
renderer::OpenGl, Canvas, ImageFlags, Paint, Path, PixelFormat::Rgba8, RenderTarget,
|
renderer::OpenGl, Canvas, ImageFlags, Paint, Path, PixelFormat::Rgba8, RenderTarget,
|
||||||
};
|
};
|
||||||
use geo_types::LineString;
|
use geo_types::LineString;
|
||||||
|
use gl::types::GLvoid;
|
||||||
|
use image::{ImageBuffer, Rgba};
|
||||||
use ndarray::ArrayView2;
|
use ndarray::ArrayView2;
|
||||||
use num_traits::{Num, NumOps};
|
use num_traits::{Num, NumOps};
|
||||||
use std::{fmt::Debug, marker::PhantomData};
|
use std::{fmt::Debug, io::Cursor, marker::PhantomData};
|
||||||
|
|
||||||
use super::super::renders::DataRenderer;
|
use super::super::renders::DataRenderer;
|
||||||
use crate::{
|
use crate::{
|
||||||
data::Radar2d,
|
data::Radar2d,
|
||||||
render::{cms::CMS, LayerImpl, Render, Target},
|
render::{cms::CMS, LayerImpl, Render, Target, TargetType},
|
||||||
utils::meshgrid,
|
utils::meshgrid,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -133,7 +135,31 @@ where
|
|||||||
data.fill_value,
|
data.fill_value,
|
||||||
);
|
);
|
||||||
|
|
||||||
canvas.set_render_target(RenderTarget::Screen);
|
canvas.flush();
|
||||||
|
|
||||||
|
let mut pixels: Vec<u8> = vec![0; w as usize * h as usize * 4];
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::ReadPixels(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
w as i32,
|
||||||
|
h as i32,
|
||||||
|
gl::RGBA,
|
||||||
|
gl::UNSIGNED_BYTE,
|
||||||
|
pixels.as_mut_ptr() as *mut GLvoid,
|
||||||
|
);
|
||||||
|
debug_assert_eq!(gl::GetError(), gl::NO_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
let img: ImageBuffer<Rgba<u8>, Vec<u8>> = ImageBuffer::from_raw(w as u32, h as u32, pixels)
|
||||||
|
.expect("Failed to create ImageBuffer");
|
||||||
|
// 将 ImageBuffer 编码为 PNG
|
||||||
|
let mut png_buffer = Cursor::new(Vec::new());
|
||||||
|
img.write_to(&mut png_buffer, image::ImageOutputFormat::Png)
|
||||||
|
.expect("Failed to write PNG buffer");
|
||||||
|
|
||||||
|
let png_data = png_buffer.into_inner();
|
||||||
|
|
||||||
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();
|
||||||
@ -142,16 +168,12 @@ where
|
|||||||
let d2_end = data.dim2.view().last().unwrap().clone();
|
let d2_end = data.dim2.view().last().unwrap().clone();
|
||||||
|
|
||||||
Target::new(
|
Target::new(
|
||||||
new_img,
|
TargetType::Mem(png_data),
|
||||||
w,
|
w,
|
||||||
h,
|
h,
|
||||||
((d1_start, d1_end).into(), (d2_start, d2_end).into()),
|
((d1_start, d1_end).into(), (d2_start, d2_end).into()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn render(&self, canvas: &mut Canvas<OpenGl>, cms: &CMS, data: &Self::Data) -> Target {
|
|
||||||
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -186,12 +208,9 @@ where
|
|||||||
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> {
|
||||||
canvas.save();
|
|
||||||
canvas.reset();
|
|
||||||
let result = self
|
let result = self
|
||||||
.renderer
|
.renderer
|
||||||
.render(canvas, cms, &self.data, (3000.0, 3000.0));
|
.render(canvas, cms, &self.data, (3000.0, 3000.0));
|
||||||
canvas.restore();
|
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,8 @@ 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::render::{LayerImplSync, TargetType};
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{AsyncDataLoader, DataLoader, Radar2d},
|
data::{AsyncDataLoader, DataLoader, Radar2d},
|
||||||
render::{Layer, Render},
|
render::{Layer, Render},
|
||||||
@ -29,13 +29,33 @@ impl Layer {
|
|||||||
Self::new(
|
Self::new(
|
||||||
true,
|
true,
|
||||||
|s, render, _| {
|
|s, render, _| {
|
||||||
if let Some(target) = s.render_target() {
|
|
||||||
let mut c = render.get_canvas();
|
let mut c = render.get_canvas();
|
||||||
let c = c.as_mut().unwrap();
|
let c = c.as_mut().unwrap();
|
||||||
if let Ok(_) = c.image_size(target.target) {
|
|
||||||
|
let render_target = s.render_target();
|
||||||
|
let mut unlock_target = render_target.lock().unwrap();
|
||||||
|
|
||||||
|
let image_id = if let Some(target) = unlock_target.as_mut() {
|
||||||
|
let result_id = match target.target {
|
||||||
|
TargetType::ImageId(id) => id,
|
||||||
|
TargetType::Mem(ref mem) => {
|
||||||
|
let converted = c
|
||||||
|
.load_image_mem(&mem, femtovg::ImageFlags::empty())
|
||||||
|
.unwrap();
|
||||||
|
target.set_target(TargetType::ImageId(converted));
|
||||||
|
converted
|
||||||
|
}
|
||||||
|
};
|
||||||
let (x, y) = target.size(&render);
|
let (x, y) = target.size(&render);
|
||||||
let (ox, oy) = target.origin(&render);
|
let (ox, oy) = target.origin(&render);
|
||||||
let painter = Paint::image(target.target, ox, oy, x, y, 0.0, 1.0);
|
Some((result_id, (x, y), (ox, oy)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some((id, (x, y), (ox, oy))) = image_id {
|
||||||
|
if let Ok(_) = c.image_size(id) {
|
||||||
|
let painter = Paint::image(id, ox, oy, x, y, 0.0, 1.0);
|
||||||
let mut path = femtovg::Path::new();
|
let mut path = femtovg::Path::new();
|
||||||
path.rect(ox, oy, x, y);
|
path.rect(ox, oy, x, y);
|
||||||
c.fill_path(&path, &painter);
|
c.fill_path(&path, &painter);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user