80 lines
2.5 KiB
Rust
80 lines
2.5 KiB
Rust
use euclid::Size2D;
|
|
use femtovg::{renderer::OpenGl, Canvas};
|
|
use std::num::NonZeroU32;
|
|
use std::sync::{Mutex, RwLock};
|
|
use std::{cell::RefCell, sync::Arc};
|
|
use surfman::{device, Adapter, Connection, Context, Device, Error};
|
|
|
|
pub struct OffscreenRenderer {
|
|
context: Arc<RwLock<Context>>,
|
|
device: Device,
|
|
// renderer: Arc<Mutex<femtovg::renderer::OpenGl>>,
|
|
canvas: Arc<RwLock<Canvas<OpenGl>>>,
|
|
}
|
|
|
|
impl OffscreenRenderer {
|
|
pub fn new() -> Result<Self, surfman::Error> {
|
|
let connection = Connection::new()?;
|
|
let adapter = connection.create_adapter()?;
|
|
let mut device = connection.create_device(&adapter)?;
|
|
|
|
let api = device.gl_api();
|
|
|
|
let descriptor = device.create_context_descriptor(&surfman::ContextAttributes {
|
|
version: surfman::GLVersion::new(3, 3),
|
|
flags: surfman::ContextAttributeFlags::empty(),
|
|
})?;
|
|
|
|
let mut context = device.create_context(&descriptor, None)?;
|
|
let mut surface = device.create_surface(
|
|
&context,
|
|
surfman::SurfaceAccess::GPUOnly,
|
|
surfman::SurfaceType::Generic {
|
|
size: euclid::Size2D::new(500, 500),
|
|
},
|
|
)?;
|
|
|
|
let surface_info = device.surface_info(&surface);
|
|
device
|
|
.bind_surface_to_context(&mut context, surface)
|
|
.expect("Failed to bind surface to context");
|
|
device.make_context_current(&context).unwrap();
|
|
|
|
static LOAD_FN: fn(&str) -> *const std::ffi::c_void =
|
|
|s| epoxy::get_proc_addr(s) as *const _;
|
|
|
|
let (mut renderer, fbo) = unsafe {
|
|
let renderer = OpenGl::new_from_function(LOAD_FN).expect("Cannot create renderer");
|
|
let fbo =
|
|
glow::NativeFramebuffer(NonZeroU32::new(surface_info.framebuffer_object).unwrap());
|
|
(renderer, fbo)
|
|
};
|
|
|
|
renderer.set_screen_target(Some(fbo));
|
|
|
|
let mut canvas = Canvas::new(renderer).expect("Cannot create canvas");
|
|
canvas.set_size(500, 500, 1.0);
|
|
|
|
Ok(Self {
|
|
context: Arc::new(RwLock::new(context)),
|
|
device,
|
|
canvas: Arc::new(RwLock::new(canvas)),
|
|
})
|
|
}
|
|
|
|
pub fn canvas(&self) -> Arc<RwLock<Canvas<OpenGl>>> {
|
|
self.canvas.clone()
|
|
}
|
|
}
|
|
|
|
impl Drop for OffscreenRenderer {
|
|
fn drop(&mut self) {
|
|
let mut context = self.context.write().unwrap();
|
|
self.device.destroy_context(&mut context).unwrap();
|
|
let _ = self;
|
|
}
|
|
}
|
|
|
|
unsafe impl Send for OffscreenRenderer {}
|
|
unsafe impl Sync for OffscreenRenderer {}
|