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 {
|
||||
let text_pipeline = text::Pipeline::new(gl, settings.default_font);
|
||||
let quad_pipeline = quad::Pipeline::new(gl);
|
||||
let triangle_pipeline =
|
||||
triangle::Pipeline::new(gl, settings.antialiasing);
|
||||
let triangle_pipeline = triangle::Pipeline::new(gl);
|
||||
|
||||
Self {
|
||||
quad_pipeline,
|
||||
@ -56,7 +55,6 @@ impl Backend {
|
||||
scale_factor,
|
||||
projection,
|
||||
&layer,
|
||||
viewport_size.width,
|
||||
viewport_size.height,
|
||||
);
|
||||
}
|
||||
@ -70,7 +68,6 @@ impl Backend {
|
||||
scale_factor: f32,
|
||||
transformation: Transformation,
|
||||
layer: &Layer<'_>,
|
||||
target_width: u32,
|
||||
target_height: u32,
|
||||
) {
|
||||
let mut bounds = (layer.bounds * scale_factor).round();
|
||||
@ -93,7 +90,6 @@ impl Backend {
|
||||
|
||||
self.triangle_pipeline.draw(
|
||||
gl,
|
||||
target_width,
|
||||
target_height,
|
||||
scaled,
|
||||
scale_factor,
|
||||
|
@ -1,10 +1,8 @@
|
||||
//! Draw meshes of triangles.
|
||||
use crate::program;
|
||||
use crate::settings;
|
||||
use crate::Transformation;
|
||||
use glow::HasContext;
|
||||
use iced_graphics::layer;
|
||||
use iced_graphics::Size;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub use iced_graphics::triangle::{Mesh2D, Vertex2D};
|
||||
@ -20,14 +18,10 @@ pub(crate) struct Pipeline {
|
||||
indices: Buffer<u32>,
|
||||
transform_location: <glow::Context as HasContext>::UniformLocation,
|
||||
current_transform: Transformation,
|
||||
antialias: Antialias,
|
||||
}
|
||||
|
||||
impl Pipeline {
|
||||
pub fn new(
|
||||
gl: &glow::Context,
|
||||
antialiasing: Option<settings::Antialiasing>,
|
||||
) -> Pipeline {
|
||||
pub fn new(gl: &glow::Context) -> Pipeline {
|
||||
let program = unsafe {
|
||||
program::create(
|
||||
gl,
|
||||
@ -109,20 +103,19 @@ impl Pipeline {
|
||||
indices,
|
||||
transform_location,
|
||||
current_transform: Transformation::identity(),
|
||||
antialias: Antialias::new(antialiasing),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(
|
||||
&mut self,
|
||||
gl: &glow::Context,
|
||||
target_width: u32,
|
||||
target_height: u32,
|
||||
transformation: Transformation,
|
||||
scale_factor: f32,
|
||||
meshes: &[layer::Mesh<'_>],
|
||||
) {
|
||||
unsafe {
|
||||
gl.enable(glow::MULTISAMPLE);
|
||||
gl.enable(glow::SCISSOR_TEST);
|
||||
gl.use_program(Some(self.program));
|
||||
gl.bind_vertex_array(Some(self.vertex_array));
|
||||
@ -170,15 +163,7 @@ impl Pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
let Self {
|
||||
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| {
|
||||
// Then we draw each mesh using offsets
|
||||
let mut last_vertex = 0;
|
||||
let mut last_index = 0;
|
||||
|
||||
@ -188,21 +173,21 @@ impl Pipeline {
|
||||
clip_bounds,
|
||||
} in meshes
|
||||
{
|
||||
let transform = transformation
|
||||
* Transformation::translate(origin.x, origin.y);
|
||||
let transform =
|
||||
transformation * Transformation::translate(origin.x, origin.y);
|
||||
|
||||
let clip_bounds = (*clip_bounds * scale_factor).round();
|
||||
|
||||
unsafe {
|
||||
if *current_transform != transform {
|
||||
if self.current_transform != transform {
|
||||
let matrix: [f32; 16] = transform.into();
|
||||
gl.uniform_matrix_4_f32_slice(
|
||||
Some(transform_location),
|
||||
Some(&self.transform_location),
|
||||
false,
|
||||
&matrix,
|
||||
);
|
||||
|
||||
*current_transform = transform;
|
||||
self.current_transform = transform;
|
||||
}
|
||||
|
||||
gl.scissor(
|
||||
@ -225,12 +210,12 @@ impl Pipeline {
|
||||
last_index += buffers.indices.len();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
unsafe {
|
||||
gl.bind_vertex_array(None);
|
||||
gl.use_program(None);
|
||||
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 glow::HasContext;
|
||||
use iced_graphics::Size;
|
||||
use iced_graphics::{Antialiasing, Size};
|
||||
use iced_native::mouse;
|
||||
|
||||
/// 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.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));
|
||||
|
||||
(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>) {
|
||||
unsafe {
|
||||
self.gl.viewport(
|
||||
|
@ -51,6 +51,7 @@ pub fn run<A, E, C>(
|
||||
|
||||
let context = ContextBuilder::new()
|
||||
.with_vsync(true)
|
||||
.with_multisampling(C::sample_count(&compositor_settings) as u16)
|
||||
.build_windowed(builder, &event_loop)
|
||||
.expect("Open window");
|
||||
|
||||
|
@ -12,6 +12,8 @@ pub trait GLCompositor: Sized {
|
||||
loader_function: impl FnMut(&str) -> *const c_void,
|
||||
) -> (Self, Self::Renderer);
|
||||
|
||||
fn sample_count(settings: &Self::Settings) -> u32;
|
||||
|
||||
fn resize_viewport(&mut self, physical_size: Size<u32>);
|
||||
|
||||
fn draw<T: AsRef<str>>(
|
||||
|
@ -170,9 +170,9 @@ impl Pipeline {
|
||||
],
|
||||
}],
|
||||
},
|
||||
sample_count: antialiasing
|
||||
.map(|a| a.sample_count())
|
||||
.unwrap_or(1),
|
||||
sample_count: u32::from(
|
||||
antialiasing.map(|a| a.sample_count()).unwrap_or(1),
|
||||
),
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user