Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Depth and stencil buffer blitting #1952

Merged
merged 2 commits into from Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 10 additions & 17 deletions src/framebuffer/default_fb.rs
Expand Up @@ -5,7 +5,7 @@ use std::rc::Rc;
use crate::backend::Facade;
use crate::context::Context;

use crate::DrawParameters;
use crate::{DrawParameters, BlitMask};
use crate::FboAttachments;
use crate::Rect;
use crate::BlitTarget;
Expand All @@ -17,10 +17,11 @@ use crate::uniforms;
use crate::{Program, Surface};
use crate::DrawError;

use crate::{fbo, gl};
use crate::framebuffer;
use crate::fbo;
use crate::index;
use crate::vertex;
use crate::framebuffer::{SimpleFrameBuffer, MultiOutputFrameBuffer};
use crate::uniforms::MagnifySamplerFilter;

/// One of the color attachments on the default framebuffer.
#[derive(Copy, Clone, Debug)]
Expand Down Expand Up @@ -112,29 +113,21 @@ impl Surface for DefaultFramebuffer {
}

#[inline]
fn blit_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, None, self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_simple_framebuffer(&self, source: &framebuffer::SimpleFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_simple_framebuffer(&self, source: &SimpleFrameBuffer<'_>, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_multioutput_framebuffer(&self, source: &framebuffer::MultiOutputFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_multioutput_framebuffer(&self, source: &MultiOutputFrameBuffer<'_>, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}
}

Expand Down
64 changes: 25 additions & 39 deletions src/framebuffer/mod.rs
Expand Up @@ -73,7 +73,7 @@ use crate::texture::TextureAnyImage;

use crate::backend::Facade;
use crate::context::Context;
use crate::CapabilitiesSource;
use crate::{CapabilitiesSource, BlitMask};
use crate::version::Version;
use crate::version::Api;

Expand All @@ -88,14 +88,15 @@ use crate::uniforms;
use crate::{Program, Surface};
use crate::DrawError;

use crate::{fbo, gl};
use crate::fbo;

pub use self::default_fb::{DefaultFramebufferAttachment, DefaultFramebuffer};
pub use self::render_buffer::{RenderBuffer, RenderBufferAny, DepthRenderBuffer};
pub use self::render_buffer::{StencilRenderBuffer, DepthStencilRenderBuffer};
pub use self::render_buffer::CreationError as RenderBufferCreationError;
pub use crate::fbo::is_dimensions_mismatch_supported;
pub use crate::fbo::ValidationError;
use crate::uniforms::MagnifySamplerFilter;

mod default_fb;
mod render_buffer;
Expand Down Expand Up @@ -323,29 +324,21 @@ impl<'a> Surface for SimpleFrameBuffer<'a> {
}

#[inline]
fn blit_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, None, self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_simple_framebuffer(&self, source: &SimpleFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_simple_framebuffer(&self, source: &SimpleFrameBuffer<'_>, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_multioutput_framebuffer(&self, source: &MultiOutputFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_multioutput_framebuffer(&self, source: &MultiOutputFrameBuffer<'_>, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}
}

Expand Down Expand Up @@ -591,29 +584,21 @@ impl<'a> Surface for MultiOutputFrameBuffer<'a> {
}

#[inline]
fn blit_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, None, self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_simple_framebuffer(&self, source: &SimpleFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_simple_framebuffer(&self, source: &SimpleFrameBuffer<'_>, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_multioutput_framebuffer(&self, source: &MultiOutputFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_multioutput_framebuffer(&self, source: &MultiOutputFrameBuffer<'_>, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}
}

Expand Down Expand Up @@ -760,29 +745,30 @@ impl Surface for EmptyFrameBuffer {
}

#[inline]
fn blit_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
fn blit_buffers_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter, mask: BlitMask)
{
ops::blit(&self.context, None, self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_simple_framebuffer(&self, source: &SimpleFrameBuffer<'_>,
fn blit_buffers_from_simple_framebuffer(&self, source: &SimpleFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
filter: uniforms::MagnifySamplerFilter, mask: BlitMask)
{
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_multioutput_framebuffer(&self, source: &MultiOutputFrameBuffer<'_>,
fn blit_buffers_from_multioutput_framebuffer(&self, source: &MultiOutputFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
filter: uniforms::MagnifySamplerFilter,
mask: BlitMask)
{
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}
}

Expand Down
138 changes: 118 additions & 20 deletions src/lib.rs
Expand Up @@ -186,6 +186,7 @@ pub use memoffset::offset_of as __glium_offset_of;
pub use crate::backend::glutin::Display;
#[cfg(feature = "glutin")]
pub use crate::backend::glutin::headless::Headless as HeadlessRenderer;
use crate::uniforms::MagnifySamplerFilter;

/// Trait for objects that describe the capabilities of an OpenGL backend.
pub trait CapabilitiesSource {
Expand Down Expand Up @@ -492,6 +493,75 @@ pub struct BlitTarget {
pub height: i32,
}

/// Mask specifying, which kinds of buffers to copy when blitting between two frame buffers.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct BlitMask {

/// If the color buffer should be copied.
pub color: bool,

/// If the depth buffer should be copied.
pub depth: bool,

/// If the stencil buffer should be copied.
pub stencil: bool,
}

impl BlitMask {

/// Constructs a bit mask, that will only copy the color buffer
pub fn color() -> Self {
BlitMask { color: true, depth: false, stencil: false }
}

/// Constructs a bit mask, that will only copy the depth buffer
pub fn depth() -> Self {
BlitMask { color: false, depth: true, stencil: false }
}

/// Constructs a bit mask, that will only copy the stencil buffer
pub fn stencil() -> Self {
BlitMask { color: false, depth: false, stencil: true }
}

/// Constructs a bit mask, that will copy the color and the depth buffer.
pub fn color_and_depth() -> Self {
BlitMask { color: true, depth: true, stencil: false }
}

/// Constructs a bit mask, that will copy the color and the stencil buffer.
pub fn color_and_stencil() -> Self {
BlitMask { color: true, depth: false, stencil: true }
}

/// Constructs a bit mask, that will copy the depth and the stencil buffer.
pub fn depth_and_stencil() -> Self {
BlitMask { color: false, depth: true, stencil: true }
}

/// Constructs a bit mask, that will copy the color, depth and stencil buffer.
pub fn color_and_depth_and_stencil() -> Self {
BlitMask { color: true, depth: true, stencil: true }
}
}

impl ToGlEnum for BlitMask {
#[inline]
fn to_glenum(&self) -> gl::types::GLenum {
let mut mask = 0;
if self.color {
mask = mask | gl::COLOR_BUFFER_BIT;
}
if self.depth {
mask = mask | gl::DEPTH_BUFFER_BIT;
}
if self.stencil {
mask = mask | gl::STENCIL_BUFFER_BIT;
}
mask
}
}

/// Object that can be drawn upon.
///
/// # What does the GPU do when you draw?
Expand Down Expand Up @@ -796,18 +866,49 @@ pub trait Surface {
U: uniforms::Uniforms;

/// Blits from the default framebuffer.
#[inline]
fn blit_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter);
filter: uniforms::MagnifySamplerFilter)
{
self.blit_buffers_from_frame(source_rect, target_rect, filter, BlitMask::color())
}

/// Blits from a simple framebuffer.
#[inline]
fn blit_from_simple_framebuffer(&self, source: &framebuffer::SimpleFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter);
filter: uniforms::MagnifySamplerFilter)
{
self.blit_buffers_from_simple_framebuffer(source, source_rect, target_rect, filter,
BlitMask::color())
}

/// Blits from a multi-output framebuffer.
#[inline]
fn blit_from_multioutput_framebuffer(&self, source: &framebuffer::MultiOutputFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter);
filter: uniforms::MagnifySamplerFilter)
{
self.blit_buffers_from_multioutput_framebuffer(source, source_rect, target_rect, filter,
BlitMask::color())
}

/// Blits from the default framebuffer.
fn blit_buffers_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter, mask: BlitMask);

/// Blits from a simple framebuffer.
fn blit_buffers_from_simple_framebuffer(&self, source: &framebuffer::SimpleFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter,
mask: BlitMask);

/// Blits from a multi-output framebuffer.
fn blit_buffers_from_multioutput_framebuffer(&self, source: &framebuffer::MultiOutputFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter,
mask: BlitMask);


/// Copies a rectangle of pixels from this surface to another surface.
///
Expand All @@ -824,6 +925,7 @@ pub trait Surface {
fn blit_color<S>(&self, source_rect: &Rect, target: &S, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter) where S: Surface;


/// Copies the entire surface to a target surface. See `blit_color`.
#[inline]
fn blit_whole_color_to<S>(&self, target: &S, target_rect: &BlitTarget,
Expand Down Expand Up @@ -1216,30 +1318,26 @@ impl Surface for Frame {
target.blit_from_frame(source_rect, target_rect, filter)
}

#[inline]
fn blit_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget, filter: MagnifySamplerFilter, mask: BlitMask) {
ops::blit(&self.context, None, self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_simple_framebuffer(&self, source: &framebuffer::SimpleFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_simple_framebuffer(&self, source: &framebuffer::SimpleFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter,
mask: BlitMask) {
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}

#[inline]
fn blit_from_multioutput_framebuffer(&self, source: &framebuffer::MultiOutputFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
fn blit_buffers_from_multioutput_framebuffer(&self,
source: &framebuffer::MultiOutputFrameBuffer<'_>,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter,
mask: BlitMask) {
ops::blit(&self.context, source.get_attachments(), self.get_attachments(),
gl::COLOR_BUFFER_BIT, source_rect, target_rect, filter.to_glenum())
mask.to_glenum(), source_rect, target_rect, filter.to_glenum())
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/ops/blit.rs
Expand Up @@ -15,6 +15,10 @@ pub fn blit(context: &Context, source: Option<&ValidatedAttachments<'_>>,
target: Option<&ValidatedAttachments<'_>>, mask: gl::types::GLbitfield,
src_rect: &Rect, target_rect: &BlitTarget, filter: gl::types::GLenum)
{
assert!(
(mask & gl::DEPTH_BUFFER_BIT == 0 && mask & gl::STENCIL_BUFFER_BIT == 0) || filter == gl::NEAREST,
"Blitting the depth and/or stencil buffer with filter being anything other than GL_NEAREST is an invalid operation."
);
unsafe {
let mut ctxt = context.make_current();

Expand Down