2020-05-19 14:23:28 +02:00
|
|
|
use crate::{Renderer, Settings, Viewport};
|
|
|
|
|
|
|
|
|
|
use glow::HasContext;
|
|
|
|
|
use iced_native::mouse;
|
|
|
|
|
use raw_window_handle::HasRawWindowHandle;
|
|
|
|
|
|
|
|
|
|
/// A window graphics backend for iced powered by `glow`.
|
|
|
|
|
#[allow(missing_debug_implementations)]
|
|
|
|
|
pub struct Backend {
|
|
|
|
|
connection: surfman::Connection,
|
|
|
|
|
device: surfman::Device,
|
|
|
|
|
gl_context: surfman::Context,
|
|
|
|
|
gl: Option<glow::Context>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl iced_native::window::Backend for Backend {
|
|
|
|
|
type Settings = Settings;
|
|
|
|
|
type Renderer = Renderer;
|
|
|
|
|
type Surface = ();
|
|
|
|
|
type SwapChain = Viewport;
|
|
|
|
|
|
|
|
|
|
fn new(settings: Self::Settings) -> Backend {
|
|
|
|
|
let connection = surfman::Connection::new().expect("Create connection");
|
|
|
|
|
|
|
|
|
|
let adapter = connection
|
|
|
|
|
.create_hardware_adapter()
|
|
|
|
|
.expect("Create adapter");
|
|
|
|
|
|
|
|
|
|
let mut device =
|
|
|
|
|
connection.create_device(&adapter).expect("Create device");
|
|
|
|
|
|
|
|
|
|
let context_descriptor = device
|
|
|
|
|
.create_context_descriptor(&surfman::ContextAttributes {
|
|
|
|
|
version: surfman::GLVersion::new(3, 0),
|
|
|
|
|
flags: surfman::ContextAttributeFlags::empty(),
|
|
|
|
|
})
|
|
|
|
|
.expect("Create context descriptor");
|
|
|
|
|
|
|
|
|
|
let gl_context = device
|
|
|
|
|
.create_context(&context_descriptor)
|
|
|
|
|
.expect("Create context");
|
|
|
|
|
|
|
|
|
|
Backend {
|
|
|
|
|
connection,
|
|
|
|
|
device,
|
|
|
|
|
gl_context,
|
|
|
|
|
gl: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_renderer(&mut self, settings: Settings) -> Renderer {
|
|
|
|
|
self.device
|
|
|
|
|
.make_context_current(&self.gl_context)
|
|
|
|
|
.expect("Make context current");
|
|
|
|
|
|
2020-05-19 17:15:44 +02:00
|
|
|
Renderer::new(crate::Backend::new(self.gl.as_ref().unwrap(), settings))
|
2020-05-19 14:23:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_surface<W: HasRawWindowHandle>(
|
|
|
|
|
&mut self,
|
|
|
|
|
window: &W,
|
|
|
|
|
) -> Self::Surface {
|
|
|
|
|
let native_widget = self
|
|
|
|
|
.connection
|
|
|
|
|
.create_native_widget_from_rwh(window.raw_window_handle())
|
|
|
|
|
.expect("Create widget");
|
|
|
|
|
|
|
|
|
|
let surface = self
|
|
|
|
|
.device
|
|
|
|
|
.create_surface(
|
|
|
|
|
&self.gl_context,
|
|
|
|
|
surfman::SurfaceAccess::GPUOnly,
|
|
|
|
|
surfman::SurfaceType::Widget { native_widget },
|
|
|
|
|
)
|
|
|
|
|
.expect("Create surface");
|
|
|
|
|
|
|
|
|
|
let surfman::SurfaceInfo { .. } = self.device.surface_info(&surface);
|
|
|
|
|
|
|
|
|
|
self.device
|
|
|
|
|
.bind_surface_to_context(&mut self.gl_context, surface)
|
|
|
|
|
.expect("Bind surface to context");
|
|
|
|
|
|
|
|
|
|
self.device
|
|
|
|
|
.make_context_current(&self.gl_context)
|
|
|
|
|
.expect("Make context current");
|
|
|
|
|
|
|
|
|
|
self.gl = Some(glow::Context::from_loader_function(|s| {
|
|
|
|
|
self.device.get_proc_address(&self.gl_context, s)
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
//let mut framebuffer =
|
|
|
|
|
// skia_safe::gpu::gl::FramebufferInfo::from_fboid(framebuffer_object);
|
|
|
|
|
|
|
|
|
|
//framebuffer.format = gl::RGBA8;
|
|
|
|
|
|
|
|
|
|
//framebuffer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_swap_chain(
|
|
|
|
|
&mut self,
|
|
|
|
|
_surface: &Self::Surface,
|
|
|
|
|
width: u32,
|
|
|
|
|
height: u32,
|
|
|
|
|
) -> Self::SwapChain {
|
|
|
|
|
let mut surface = self
|
|
|
|
|
.device
|
|
|
|
|
.unbind_surface_from_context(&mut self.gl_context)
|
|
|
|
|
.expect("Unbind surface")
|
|
|
|
|
.expect("Active surface");
|
|
|
|
|
|
|
|
|
|
self.device
|
|
|
|
|
.resize_surface(
|
|
|
|
|
&self.gl_context,
|
|
|
|
|
&mut surface,
|
|
|
|
|
euclid::Size2D::new(width as i32, height as i32),
|
|
|
|
|
)
|
|
|
|
|
.expect("Resize surface");
|
|
|
|
|
|
|
|
|
|
self.device
|
|
|
|
|
.bind_surface_to_context(&mut self.gl_context, surface)
|
|
|
|
|
.expect("Bind surface to context");
|
|
|
|
|
|
|
|
|
|
let gl = self.gl.as_ref().unwrap();
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
gl.viewport(0, 0, width as i32, height as i32);
|
|
|
|
|
gl.clear_color(1.0, 1.0, 1.0, 1.0);
|
|
|
|
|
|
|
|
|
|
// Enable auto-conversion from/to sRGB
|
|
|
|
|
gl.enable(glow::FRAMEBUFFER_SRGB);
|
|
|
|
|
|
|
|
|
|
// Enable alpha blending
|
|
|
|
|
gl.enable(glow::BLEND);
|
|
|
|
|
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Viewport::new(width, height)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn draw<T: AsRef<str>>(
|
|
|
|
|
&mut self,
|
|
|
|
|
renderer: &mut Self::Renderer,
|
|
|
|
|
swap_chain: &mut Self::SwapChain,
|
|
|
|
|
output: &<Self::Renderer as iced_native::Renderer>::Output,
|
|
|
|
|
scale_factor: f64,
|
|
|
|
|
overlay: &[T],
|
|
|
|
|
) -> mouse::Interaction {
|
|
|
|
|
let gl = self.gl.as_ref().unwrap();
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
gl.clear(glow::COLOR_BUFFER_BIT);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-19 17:15:44 +02:00
|
|
|
let mouse = renderer.backend_mut().draw(
|
|
|
|
|
gl,
|
|
|
|
|
swap_chain,
|
|
|
|
|
output,
|
|
|
|
|
scale_factor,
|
|
|
|
|
overlay,
|
|
|
|
|
);
|
2020-05-19 14:23:28 +02:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
let mut surface = self
|
|
|
|
|
.device
|
|
|
|
|
.unbind_surface_from_context(&mut self.gl_context)
|
|
|
|
|
.expect("Unbind surface")
|
|
|
|
|
.expect("Active surface");
|
|
|
|
|
|
|
|
|
|
self.device
|
|
|
|
|
.present_surface(&self.gl_context, &mut surface)
|
|
|
|
|
.expect("Present surface");
|
|
|
|
|
|
|
|
|
|
self.device
|
|
|
|
|
.bind_surface_to_context(&mut self.gl_context, surface)
|
|
|
|
|
.expect("Bind surface to context");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mouse
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Drop for Backend {
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
self.device
|
|
|
|
|
.destroy_context(&mut self.gl_context)
|
|
|
|
|
.expect("Destroy context");
|
|
|
|
|
}
|
|
|
|
|
}
|