Use built-in OpenGL multisampling in iced_glow
This commit is contained in:
parent
6f71a8e3d5
commit
1dd79c4697
@ -26,8 +26,7 @@ impl Backend {
|
|||||||
pub fn new(gl: &glow::Context, settings: Settings) -> Self {
|
pub fn new(gl: &glow::Context, settings: Settings) -> Self {
|
||||||
let text_pipeline = text::Pipeline::new(gl, settings.default_font);
|
let text_pipeline = text::Pipeline::new(gl, settings.default_font);
|
||||||
let quad_pipeline = quad::Pipeline::new(gl);
|
let quad_pipeline = quad::Pipeline::new(gl);
|
||||||
let triangle_pipeline =
|
let triangle_pipeline = triangle::Pipeline::new(gl);
|
||||||
triangle::Pipeline::new(gl, settings.antialiasing);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
quad_pipeline,
|
quad_pipeline,
|
||||||
@ -56,7 +55,6 @@ impl Backend {
|
|||||||
scale_factor,
|
scale_factor,
|
||||||
projection,
|
projection,
|
||||||
&layer,
|
&layer,
|
||||||
viewport_size.width,
|
|
||||||
viewport_size.height,
|
viewport_size.height,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -70,7 +68,6 @@ impl Backend {
|
|||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
layer: &Layer<'_>,
|
layer: &Layer<'_>,
|
||||||
target_width: u32,
|
|
||||||
target_height: u32,
|
target_height: u32,
|
||||||
) {
|
) {
|
||||||
let mut bounds = (layer.bounds * scale_factor).round();
|
let mut bounds = (layer.bounds * scale_factor).round();
|
||||||
@ -93,7 +90,6 @@ impl Backend {
|
|||||||
|
|
||||||
self.triangle_pipeline.draw(
|
self.triangle_pipeline.draw(
|
||||||
gl,
|
gl,
|
||||||
target_width,
|
|
||||||
target_height,
|
target_height,
|
||||||
scaled,
|
scaled,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
//! Draw meshes of triangles.
|
//! Draw meshes of triangles.
|
||||||
use crate::program;
|
use crate::program;
|
||||||
use crate::settings;
|
|
||||||
use crate::Transformation;
|
use crate::Transformation;
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use iced_graphics::layer;
|
use iced_graphics::layer;
|
||||||
use iced_graphics::Size;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
|
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
|
||||||
@ -20,14 +18,10 @@ pub(crate) struct Pipeline {
|
|||||||
indices: Buffer<u32>,
|
indices: Buffer<u32>,
|
||||||
transform_location: <glow::Context as HasContext>::UniformLocation,
|
transform_location: <glow::Context as HasContext>::UniformLocation,
|
||||||
current_transform: Transformation,
|
current_transform: Transformation,
|
||||||
antialias: Antialias,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
pub fn new(
|
pub fn new(gl: &glow::Context) -> Pipeline {
|
||||||
gl: &glow::Context,
|
|
||||||
antialiasing: Option<settings::Antialiasing>,
|
|
||||||
) -> Pipeline {
|
|
||||||
let program = unsafe {
|
let program = unsafe {
|
||||||
program::create(
|
program::create(
|
||||||
gl,
|
gl,
|
||||||
@ -109,20 +103,19 @@ impl Pipeline {
|
|||||||
indices,
|
indices,
|
||||||
transform_location,
|
transform_location,
|
||||||
current_transform: Transformation::identity(),
|
current_transform: Transformation::identity(),
|
||||||
antialias: Antialias::new(antialiasing),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(
|
pub fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
gl: &glow::Context,
|
gl: &glow::Context,
|
||||||
target_width: u32,
|
|
||||||
target_height: u32,
|
target_height: u32,
|
||||||
transformation: Transformation,
|
transformation: Transformation,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
meshes: &[layer::Mesh<'_>],
|
meshes: &[layer::Mesh<'_>],
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
gl.enable(glow::MULTISAMPLE);
|
||||||
gl.enable(glow::SCISSOR_TEST);
|
gl.enable(glow::SCISSOR_TEST);
|
||||||
gl.use_program(Some(self.program));
|
gl.use_program(Some(self.program));
|
||||||
gl.bind_vertex_array(Some(self.vertex_array));
|
gl.bind_vertex_array(Some(self.vertex_array));
|
||||||
@ -170,15 +163,7 @@ impl Pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let Self {
|
// Then we draw each mesh using offsets
|
||||||
antialias,
|
|
||||||
current_transform,
|
|
||||||
transform_location,
|
|
||||||
..
|
|
||||||
} = self;
|
|
||||||
|
|
||||||
// Then we draw each mesh using offsets with antialiasing
|
|
||||||
antialias.perform(gl, Size::new(target_width, target_height), |gl| {
|
|
||||||
let mut last_vertex = 0;
|
let mut last_vertex = 0;
|
||||||
let mut last_index = 0;
|
let mut last_index = 0;
|
||||||
|
|
||||||
@ -188,21 +173,21 @@ impl Pipeline {
|
|||||||
clip_bounds,
|
clip_bounds,
|
||||||
} in meshes
|
} in meshes
|
||||||
{
|
{
|
||||||
let transform = transformation
|
let transform =
|
||||||
* Transformation::translate(origin.x, origin.y);
|
transformation * Transformation::translate(origin.x, origin.y);
|
||||||
|
|
||||||
let clip_bounds = (*clip_bounds * scale_factor).round();
|
let clip_bounds = (*clip_bounds * scale_factor).round();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if *current_transform != transform {
|
if self.current_transform != transform {
|
||||||
let matrix: [f32; 16] = transform.into();
|
let matrix: [f32; 16] = transform.into();
|
||||||
gl.uniform_matrix_4_f32_slice(
|
gl.uniform_matrix_4_f32_slice(
|
||||||
Some(transform_location),
|
Some(&self.transform_location),
|
||||||
false,
|
false,
|
||||||
&matrix,
|
&matrix,
|
||||||
);
|
);
|
||||||
|
|
||||||
*current_transform = transform;
|
self.current_transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.scissor(
|
gl.scissor(
|
||||||
@ -225,12 +210,12 @@ impl Pipeline {
|
|||||||
last_index += buffers.indices.len();
|
last_index += buffers.indices.len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl.bind_vertex_array(None);
|
gl.bind_vertex_array(None);
|
||||||
gl.use_program(None);
|
gl.use_program(None);
|
||||||
gl.disable(glow::SCISSOR_TEST);
|
gl.disable(glow::SCISSOR_TEST);
|
||||||
|
gl.disable(glow::MULTISAMPLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,146 +290,3 @@ impl<T> Buffer<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Antialias {
|
|
||||||
renderbuffer: Option<Renderbuffer>,
|
|
||||||
sample_count: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Antialias {
|
|
||||||
fn new(antialiasing: Option<settings::Antialiasing>) -> Self {
|
|
||||||
Antialias {
|
|
||||||
renderbuffer: None,
|
|
||||||
sample_count: antialiasing
|
|
||||||
.map(settings::Antialiasing::sample_count)
|
|
||||||
.unwrap_or(1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn perform(
|
|
||||||
&mut self,
|
|
||||||
gl: &glow::Context,
|
|
||||||
size: Size<u32>,
|
|
||||||
f: impl FnOnce(&glow::Context),
|
|
||||||
) {
|
|
||||||
if self.sample_count == 1 {
|
|
||||||
return f(gl);
|
|
||||||
}
|
|
||||||
|
|
||||||
let target = glow::DRAW_FRAMEBUFFER;
|
|
||||||
|
|
||||||
let renderbuffer = if let Some(renderbuffer) = self.renderbuffer.take()
|
|
||||||
{
|
|
||||||
if size == renderbuffer.size {
|
|
||||||
renderbuffer
|
|
||||||
} else {
|
|
||||||
renderbuffer.destroy(gl);
|
|
||||||
|
|
||||||
Renderbuffer::new(gl, target, self.sample_count, size)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Renderbuffer::new(gl, target, self.sample_count, size)
|
|
||||||
};
|
|
||||||
|
|
||||||
renderbuffer.bind(gl, target);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
gl.clear_color(0.0, 0.0, 0.0, 0.0);
|
|
||||||
gl.clear(glow::COLOR_BUFFER_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
f(gl);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
gl.bind_framebuffer(target, None);
|
|
||||||
gl.clear_color(1.0, 1.0, 1.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderbuffer.blit(gl);
|
|
||||||
|
|
||||||
self.renderbuffer = Some(renderbuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Renderbuffer {
|
|
||||||
raw: <glow::Context as HasContext>::Renderbuffer,
|
|
||||||
framebuffer: <glow::Context as HasContext>::Framebuffer,
|
|
||||||
size: Size<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Renderbuffer {
|
|
||||||
fn new(
|
|
||||||
gl: &glow::Context,
|
|
||||||
target: u32,
|
|
||||||
sample_count: u32,
|
|
||||||
size: Size<u32>,
|
|
||||||
) -> Self {
|
|
||||||
let framebuffer = unsafe {
|
|
||||||
gl.create_framebuffer().expect("Create MSAA framebuffer")
|
|
||||||
};
|
|
||||||
|
|
||||||
let raw = unsafe {
|
|
||||||
gl.create_renderbuffer().expect("Create MSAA renderbuffer")
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
gl.bind_renderbuffer(glow::RENDERBUFFER, Some(raw));
|
|
||||||
gl.renderbuffer_storage_multisample(
|
|
||||||
glow::RENDERBUFFER,
|
|
||||||
sample_count as i32,
|
|
||||||
glow::SRGB8_ALPHA8,
|
|
||||||
size.width as i32,
|
|
||||||
size.height as i32,
|
|
||||||
);
|
|
||||||
|
|
||||||
gl.bind_framebuffer(target, Some(framebuffer));
|
|
||||||
gl.framebuffer_renderbuffer(
|
|
||||||
target,
|
|
||||||
glow::COLOR_ATTACHMENT0,
|
|
||||||
glow::RENDERBUFFER,
|
|
||||||
Some(raw),
|
|
||||||
);
|
|
||||||
gl.bind_framebuffer(target, None);
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
|
||||||
raw,
|
|
||||||
framebuffer,
|
|
||||||
size,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bind(&self, gl: &glow::Context, target: u32) {
|
|
||||||
unsafe {
|
|
||||||
gl.bind_framebuffer(target, Some(self.framebuffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn blit(&self, gl: &glow::Context) {
|
|
||||||
unsafe {
|
|
||||||
self.bind(gl, glow::READ_FRAMEBUFFER);
|
|
||||||
|
|
||||||
gl.blit_framebuffer(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
self.size.width as i32,
|
|
||||||
self.size.height as i32,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
self.size.width as i32,
|
|
||||||
self.size.height as i32,
|
|
||||||
glow::COLOR_BUFFER_BIT,
|
|
||||||
glow::NEAREST,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn destroy(self, gl: &glow::Context) {
|
|
||||||
unsafe {
|
|
||||||
gl.delete_renderbuffer(self.raw);
|
|
||||||
gl.delete_framebuffer(self.framebuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,7 @@ use crate::{Backend, Renderer, Settings, Viewport};
|
|||||||
|
|
||||||
use core::ffi::c_void;
|
use core::ffi::c_void;
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use iced_graphics::Size;
|
use iced_graphics::{Antialiasing, Size};
|
||||||
use iced_native::mouse;
|
use iced_native::mouse;
|
||||||
|
|
||||||
/// A window graphics backend for iced powered by `glow`.
|
/// A window graphics backend for iced powered by `glow`.
|
||||||
@ -30,11 +30,21 @@ impl iced_graphics::window::GLCompositor for Compositor {
|
|||||||
gl.enable(glow::BLEND);
|
gl.enable(glow::BLEND);
|
||||||
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
|
gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// Disable multisampling by default
|
||||||
|
gl.disable(glow::MULTISAMPLE);
|
||||||
|
|
||||||
let renderer = Renderer::new(Backend::new(&gl, settings));
|
let renderer = Renderer::new(Backend::new(&gl, settings));
|
||||||
|
|
||||||
(Self { gl }, renderer)
|
(Self { gl }, renderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sample_count(settings: &Settings) -> u32 {
|
||||||
|
settings
|
||||||
|
.antialiasing
|
||||||
|
.map(Antialiasing::sample_count)
|
||||||
|
.unwrap_or(0)
|
||||||
|
}
|
||||||
|
|
||||||
fn resize_viewport(&mut self, physical_size: Size<u32>) {
|
fn resize_viewport(&mut self, physical_size: Size<u32>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.gl.viewport(
|
self.gl.viewport(
|
||||||
|
@ -51,6 +51,7 @@ pub fn run<A, E, C>(
|
|||||||
|
|
||||||
let context = ContextBuilder::new()
|
let context = ContextBuilder::new()
|
||||||
.with_vsync(true)
|
.with_vsync(true)
|
||||||
|
.with_multisampling(C::sample_count(&compositor_settings) as u16)
|
||||||
.build_windowed(builder, &event_loop)
|
.build_windowed(builder, &event_loop)
|
||||||
.expect("Open window");
|
.expect("Open window");
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ pub trait GLCompositor: Sized {
|
|||||||
loader_function: impl FnMut(&str) -> *const c_void,
|
loader_function: impl FnMut(&str) -> *const c_void,
|
||||||
) -> (Self, Self::Renderer);
|
) -> (Self, Self::Renderer);
|
||||||
|
|
||||||
|
fn sample_count(settings: &Self::Settings) -> u32;
|
||||||
|
|
||||||
fn resize_viewport(&mut self, physical_size: Size<u32>);
|
fn resize_viewport(&mut self, physical_size: Size<u32>);
|
||||||
|
|
||||||
fn draw<T: AsRef<str>>(
|
fn draw<T: AsRef<str>>(
|
||||||
|
@ -170,9 +170,9 @@ impl Pipeline {
|
|||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
sample_count: antialiasing
|
sample_count: u32::from(
|
||||||
.map(|a| a.sample_count())
|
antialiasing.map(|a| a.sample_count()).unwrap_or(1),
|
||||||
.unwrap_or(1),
|
),
|
||||||
sample_mask: !0,
|
sample_mask: !0,
|
||||||
alpha_to_coverage_enabled: false,
|
alpha_to_coverage_enabled: false,
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user