Skip to content

Commit

Permalink
Merge pull request #1952 from tobias93/master
Browse files Browse the repository at this point in the history
Depth and stencil buffer blitting
  • Loading branch information
est31 committed Jul 28, 2021
2 parents 2ff5a35 + 7ff5c3a commit 2c6caf9
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 77 deletions.
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

0 comments on commit 2c6caf9

Please sign in to comment.