#ifndef Magnum_AbstractFramebuffer_h #define Magnum_AbstractFramebuffer_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš This file is part of Magnum. Magnum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 only, as published by the Free Software Foundation. Magnum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License version 3 for more details. */ /** @file * @brief Class Magnum::AbstractFramebuffer */ #include #include "Math/Vector2.h" #include "AbstractImage.h" #include "Buffer.h" namespace Magnum { /** @brief Base for default and named framebuffers See DefaultFramebuffer and Framebuffer for more information. @section AbstractFramebuffer-performance-optimization Performance optimizations The engine tracks currently bound framebuffer and current viewport to avoid unnecessary calls to @fn_gl{BindFramebuffer} and @fn_gl{Viewport} when switching framebuffers. @todo @extension{ARB,viewport_array} */ class MAGNUM_EXPORT AbstractFramebuffer { friend class Context; AbstractFramebuffer(const AbstractFramebuffer& other) = delete; AbstractFramebuffer(AbstractFramebuffer&& other) = delete; AbstractFramebuffer& operator=(const AbstractFramebuffer& other) = delete; AbstractFramebuffer& operator=(AbstractFramebuffer&& other) = delete; public: /** * @brief Mask for clearing * * @see ClearMask */ enum class Clear: GLbitfield { Color = GL_COLOR_BUFFER_BIT, /**< Color */ Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value */ Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */ }; /** * @brief Mask for clearing * * @see clear() */ typedef Corrade::Containers::EnumSet ClearMask; /** * @brief Mask for blitting * * @see BlitMask * @requires_gl30 %Extension @extension{EXT,framebuffer_object} * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} */ enum class Blit: GLbitfield { ColorBuffer = GL_COLOR_BUFFER_BIT, /**< Color buffer */ DepthBuffer = GL_DEPTH_BUFFER_BIT, /**< Depth buffer */ StencilBuffer = GL_STENCIL_BUFFER_BIT /**< Stencil buffer */ }; /** * @brief Mask for blitting * * @see blit() * @requires_gl30 %Extension @extension{EXT,framebuffer_object} * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} */ typedef Corrade::Containers::EnumSet BlitMask; /** * @brief Blit filtering * * @see blit() */ enum class BlitFilter: GLenum { NearestNeighbor = GL_NEAREST, /**< Nearest neighbor filtering */ LinearInterpolation = GL_LINEAR /**< Linear interpolation filtering */ }; /** * @brief Target for binding framebuffer * * @see DefaultFramebuffer::bind(), Framebuffer::bind() * @requires_gl30 %Extension @extension{EXT,framebuffer_object} */ enum class Target: GLenum { /** * For reading only. * @requires_gl30 %Extension @extension{EXT,framebuffer_blit} * @requires_gles30 %Extension @es_extension{APPLE,framebuffer_multisample} * or @es_extension{ANGLE,framebuffer_blit} */ #ifndef MAGNUM_TARGET_GLES2 Read = GL_READ_FRAMEBUFFER, #else Read = GL_READ_FRAMEBUFFER_APPLE, #endif /** * For drawing only. * @requires_gl30 %Extension @extension{EXT,framebuffer_blit} * @requires_gles30 %Extension @es_extension{APPLE,framebuffer_multisample} * or @es_extension{ANGLE,framebuffer_blit} */ #ifndef MAGNUM_TARGET_GLES2 Draw = GL_DRAW_FRAMEBUFFER, #else Draw = GL_DRAW_FRAMEBUFFER_APPLE, #endif ReadDraw = GL_FRAMEBUFFER /**< For both reading and drawing. */ }; /** * @brief Copy block of pixels * @param source Source framebuffer * @param destination Destination framebuffer * @param sourceBottomLeft Bottom left coordinates of source rectangle * @param sourceTopRight Top right coordinates of source rectangle * @param destinationBottomLeft Bottom left coordinates of destination rectangle * @param destinationTopRight Top right coordinates of destination * rectangle * @param mask Which buffers to perform blit operation on * @param filter Interpolation filter * * Binds @p source framebuffer to @ref Target "Target::Read" and * @p destination framebuffer to @ref Target "Target::Draw" and * performs blitting operation. See DefaultFramebuffer::mapForRead(), * Framebuffer::mapForRead(), DefaultFramebuffer::mapForDraw() and * Framebuffer::mapForDraw() for specifying particular buffers for * blitting operation. * @see @fn_gl{BlitFramebuffer} * @requires_gl30 %Extension @extension{EXT,framebuffer_blit} * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} */ static void blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Vector2i& sourceBottomLeft, const Vector2i& sourceTopRight, const Vector2i& destinationBottomLeft, const Vector2i& destinationTopRight, BlitMask mask, BlitFilter filter); /** * @brief Copy block of pixels * @param source Source framebuffer * @param destination Destination framebuffer * @param bottomLeft Bottom left coordinates of source and * destination rectangle * @param topRight Top right coordinates of source and * destination rectangle * @param mask Which buffers to perform blit operation on * * Convenience alternative to above function when source rectangle is * the same as destination rectangle. As the image is copied * pixel-by-pixel, no interpolation is needed and thus * @ref BlitFilter "BlitFilter::NearestNeighbor" filtering is used by * default. * @see @fn_gl{BlitFramebuffer} * @requires_gl30 %Extension @extension{EXT,framebuffer_blit} * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} */ inline static void blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Vector2i& bottomLeft, const Vector2i& topRight, BlitMask mask) { blit(source, destination, bottomLeft, topRight, bottomLeft, topRight, mask, BlitFilter::NearestNeighbor); } explicit AbstractFramebuffer() = default; virtual ~AbstractFramebuffer() = 0; /** * @brief Bind framebuffer for rendering * * Binds the framebuffer and updates viewport to saved dimensions. * @see setViewport(), DefaultFramebuffer::mapForRead(), * Framebuffer::mapForRead(), DefaultFramebuffer::mapForDraw(), * Framebuffer::mapForDraw(), @fn_gl{BindFramebuffer}, * @fn_gl{Viewport} */ void bind(Target target); /** @brief Viewport position */ inline Vector2i viewportPosition() const { return _viewportPosition; } /** @brief Viewport size */ inline Vector2i viewportSize() const { return _viewportSize; } /** * @brief Set viewport size * * Saves the viewport size to be used at later time in bind(). If the * framebuffer is currently bound, updates the viewport to given * dimensions. * @see @fn_gl{Viewport} */ void setViewport(const Vector2i& position, const Vector2i& size); /** * @brief Clear specified buffers in framebuffer * @param mask Which buffers to clear * * @see Renderer::setClearColor(), Renderer::setClearDepth(), * Renderer::setClearStencil(), @fn_gl{BindFramebuffer}, * @fn_gl{Clear} */ void clear(ClearMask mask); /** * @brief Read block of pixels from framebuffer to image * @param offset Offset in the framebuffer * @param size %Image size * @param format Format of pixel data * @param type Data type of pixel data * @param image %Image where to put the data * * @see @fn_gl{BindFramebuffer}, @fn_gl{ReadPixels} */ void read(const Vector2i& offset, const Vector2i& size, AbstractImage::Format format, AbstractImage::Type type, Image2D* image); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Read block of pixels from framebuffer to buffer image * @param offset Offset in the framebuffer * @param size %Image size * @param format Format of pixel data * @param type Data type of pixel data * @param image %Buffer image where to put the data * @param usage %Buffer usage * * @see @fn_gl{BindFramebuffer}, @fn_gl{ReadPixels} * @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0. */ void read(const Vector2i& offset, const Vector2i& size, AbstractImage::Format format, AbstractImage::Type type, BufferImage2D* image, Buffer::Usage usage); #endif #ifndef DOXYGEN_GENERATING_OUTPUT protected: void MAGNUM_LOCAL bindInternal(Target target); void MAGNUM_LOCAL setViewportInternal(); static Target readTarget, drawTarget; GLuint _id; Vector2i _viewportPosition, _viewportSize; #endif private: static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); }; inline AbstractFramebuffer::~AbstractFramebuffer() {} CORRADE_ENUMSET_OPERATORS(AbstractFramebuffer::ClearMask) #ifndef MAGNUM_TARGET_GLES CORRADE_ENUMSET_OPERATORS(AbstractFramebuffer::BlitMask) #endif } #endif