Browse Source

Framebuffer-related limit queries.

Also printing the values in magnum-info.
pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
eb24db9b5f
  1. 45
      src/AbstractFramebuffer.cpp
  2. 45
      src/AbstractFramebuffer.h
  3. 5
      src/DefaultFramebuffer.h
  4. 19
      src/Framebuffer.cpp
  5. 19
      src/Framebuffer.h
  6. 2
      src/ImageFormat.h
  7. 11
      src/Implementation/FramebufferState.h
  8. 13
      src/Platform/magnum-info.cpp
  9. 30
      src/Renderbuffer.cpp
  10. 35
      src/Renderbuffer.h

45
src/AbstractFramebuffer.cpp

@ -47,6 +47,51 @@ FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw;
FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw; FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw;
#endif #endif
Vector2i AbstractFramebuffer::maxViewportSize() {
Vector2i& value = Context::current()->state().framebuffer->maxViewportSize;
/* Get the value, if not already cached */
if(value == Vector2i())
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, value.data());
return value;
}
Int AbstractFramebuffer::maxDrawBuffers() {
#ifdef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::NV::draw_buffers>())
return 0;
#endif
GLint& value = Context::current()->state().framebuffer->maxDrawBuffers;
/* Get the value, if not already cached */
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &value);
#else
glGetIntegerv(GL_MAX_DRAW_BUFFERS_NV, &value);
#endif
}
return value;
}
#ifndef MAGNUM_TARGET_GLES
Int AbstractFramebuffer::maxDualSourceDrawBuffers() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::blend_func_extended>())
return 0;
GLint& value = Context::current()->state().framebuffer->maxDualSourceDrawBuffers;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS, &value);
return value;
}
#endif
void AbstractFramebuffer::bind(FramebufferTarget target) { void AbstractFramebuffer::bind(FramebufferTarget target) {
bindInternal(target); bindInternal(target);
setViewportInternal(); setViewportInternal();

45
src/AbstractFramebuffer.h

@ -133,11 +133,13 @@ See DefaultFramebuffer and Framebuffer for more information.
The engine tracks currently bound framebuffer and current viewport to avoid The engine tracks currently bound framebuffer and current viewport to avoid
unnecessary calls to @fn_gl{BindFramebuffer} and @fn_gl{Viewport} when unnecessary calls to @fn_gl{BindFramebuffer} and @fn_gl{Viewport} when
switching framebuffers. switching framebuffers. %Framebuffer limits and implementation-defined values
(such as @ref maxViewportSize()) are cached, so repeated queries don't result
in repeated @fn_gl{Get} calls.
If @extension{ARB,robustness} is available, read() operations are protected If @extension{ARB,robustness} is available, read() operations are protected
from buffer overflow. from buffer overflow.
@todo @extension{ARB,viewport_array} @todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`)
*/ */
class MAGNUM_EXPORT AbstractFramebuffer { class MAGNUM_EXPORT AbstractFramebuffer {
friend class Context; friend class Context;
@ -148,6 +150,43 @@ class MAGNUM_EXPORT AbstractFramebuffer {
AbstractFramebuffer& operator=(AbstractFramebuffer&&) = delete; AbstractFramebuffer& operator=(AbstractFramebuffer&&) = delete;
public: public:
/** @todo `GL_IMPLEMENTATION_COLOR_READ_FORMAT`, `GL_IMPLEMENTATION_COLOR_READ_TYPE`, seems to be depending on currently bound FB (aargh). Also for consistency it might be good to rename ImageFormat and ImageType to `ColorFormat` and `ColorType` (@extension{ARB,ES2_compatibility}). */
/**
* @brief Max supported viewport size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @ref setViewport(), @fn_gl{Get} with @def_gl{MAX_VIEWPORT_DIMS}
*/
static Vector2i maxViewportSize();
/**
* @brief Max supported draw buffer count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If ES extension @extension{NV,draw_buffers} is not
* available, returns `0`.
* @see @ref DefaultFramebuffer::mapForDraw(), @ref Framebuffer::mapForDraw(),
* @fn_gl{Get} with @def_gl{MAX_DRAW_BUFFERS}
*/
static Int maxDrawBuffers();
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Max supported dual-source draw buffer count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,blend_func_extended} is
* not available, returns `0`.
* @see @ref DefaultFramebuffer::mapForDraw(), @ref Framebuffer::mapForDraw(),
* @fn_gl{Get} with @def_gl{MAX_DUAL_SOURCE_DRAW_BUFFERS}
* @requires_gl Multiple blending inputs are not available in
* OpenGL ES.
*/
static Int maxDualSourceDrawBuffers();
#endif
/** /**
* @brief Copy block of pixels * @brief Copy block of pixels
* @param source Source framebuffer * @param source Source framebuffer
@ -211,7 +250,7 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* Saves the viewport to be used at later time in bind(). If the * Saves the viewport to be used at later time in bind(). If the
* framebuffer is currently bound, updates the viewport to given * framebuffer is currently bound, updates the viewport to given
* rectangle. * rectangle.
* @see @fn_gl{Viewport} * @see @ref maxViewportSize(), @fn_gl{Viewport}
*/ */
AbstractFramebuffer& setViewport(const Rectanglei& rectangle); AbstractFramebuffer& setViewport(const Rectanglei& rectangle);

5
src/DefaultFramebuffer.h

@ -323,8 +323,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebuffer is not currently bound, it is bound before the * framebuffer is not currently bound, it is bound before the
* operation. * operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} * @ref mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers}
* or @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}
* @requires_gles30 Draw attachments for default framebuffer are * @requires_gles30 Draw attachments for default framebuffer are
* available only in OpenGL ES 3.0. * available only in OpenGL ES 3.0.
*/ */

19
src/Framebuffer.cpp

@ -52,6 +52,25 @@ const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::DepthStencil
const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Depth = Framebuffer::InvalidationAttachment(GL_DEPTH_ATTACHMENT); const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Depth = Framebuffer::InvalidationAttachment(GL_DEPTH_ATTACHMENT);
const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Stencil = Framebuffer::InvalidationAttachment(GL_STENCIL_ATTACHMENT); const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Stencil = Framebuffer::InvalidationAttachment(GL_STENCIL_ATTACHMENT);
Int Framebuffer::maxColorAttachments() {
#ifdef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::NV::fbo_color_attachments>())
return 0;
#endif
GLint& value = Context::current()->state().framebuffer->maxColorAttachments;
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &value);
#else
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_NV, &value);
#endif
}
return value;
}
Framebuffer::Framebuffer(const Rectanglei& viewport) { Framebuffer::Framebuffer(const Rectanglei& viewport) {
_viewport = viewport; _viewport = viewport;

19
src/Framebuffer.h

@ -272,6 +272,18 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
#endif #endif
}; };
/** @todo `GL_MAX_FRAMEBUFFER_WIDTH` etc. when @extension{ARB,framebuffer_no_attachments} is done */
/**
* @brief Max supported color attachment count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If ES extension @extension{NV,fbo_color_attachments}
* is not available, returns `0`.
* @see @ref mapForDraw(), @fn_gl{Get} with @def_gl{MAX_COLOR_ATTACHMENTS}
*/
static Int maxColorAttachments();
/** /**
* @brief Constructor * @brief Constructor
* *
@ -318,7 +330,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the * framebufferbuffer is not currently bound, it is bound before the
* operation. * operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @ref maxColorAttachments(), @ref mapForRead(),
* @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
*/ */
@ -335,7 +349,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the * framebufferbuffer is not currently bound, it is bound before the
* operation. * operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} or * @see @ref maxColorAttachments(), @ref mapForRead(),
* @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} or
* @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, * @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access},
* @fn_gl{DrawBuffers} in OpenGL ES 3.0 * @fn_gl{DrawBuffers} in OpenGL ES 3.0
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers} * @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}

2
src/ImageFormat.h

@ -258,7 +258,7 @@ Note that some formats can be used only for framebuffer reading (using
AbstractFramebuffer::read()) and some only for texture data (using Texture::setImage() AbstractFramebuffer::read()) and some only for texture data (using Texture::setImage()
and others). and others).
@see Image, ImageReference, BufferImage, Trade::ImageData @see Image, ImageReference, BufferImage, Trade::ImageData
*/ */
enum class ImageType: GLenum { enum class ImageType: GLenum {
/** Each component unsigned byte. */ /** Each component unsigned byte. */
UnsignedByte = GL_UNSIGNED_BYTE, UnsignedByte = GL_UNSIGNED_BYTE,

11
src/Implementation/FramebufferState.h

@ -31,10 +31,19 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
struct FramebufferState { struct FramebufferState {
constexpr FramebufferState(): readBinding(0), drawBinding(0), renderbufferBinding(0) {} constexpr FramebufferState(): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0)
#ifndef MAGNUM_TARGET_GLES
, maxDualSourceDrawBuffers(0)
#endif
{}
GLuint readBinding, drawBinding, renderbufferBinding; GLuint readBinding, drawBinding, renderbufferBinding;
GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize, maxSamples;
#ifndef MAGNUM_TARGET_GLES
GLint maxDualSourceDrawBuffers;
#endif
Rectanglei viewport; Rectanglei viewport;
Vector2i maxViewportSize;
}; };
}} }}

13
src/Platform/magnum-info.cpp

@ -32,7 +32,9 @@
#include "AbstractShaderProgram.h" #include "AbstractShaderProgram.h"
#include "Context.h" #include "Context.h"
#include "Extensions.h" #include "Extensions.h"
#include "Framebuffer.h"
#include "Mesh.h" #include "Mesh.h"
#include "Renderbuffer.h"
#include "Shader.h" #include "Shader.h"
#ifndef CORRADE_TARGET_NACL #ifndef CORRADE_TARGET_NACL
#include "Platform/WindowlessGlxApplication.h" #include "Platform/WindowlessGlxApplication.h"
@ -179,10 +181,15 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
#define _l(val) Debug() << " " << #val << (sizeof(#val) > 64 ? "\n" + std::string(68, ' ') : std::string(64 - sizeof(#val), ' ')) << val; #define _l(val) Debug() << " " << #val << (sizeof(#val) > 64 ? "\n" + std::string(68, ' ') : std::string(64 - sizeof(#val), ' ')) << val;
Debug() << "Limits and implementation-defined values:"; Debug() << "Limits and implementation-defined values:";
_l(AbstractFramebuffer::maxViewportSize())
_l(AbstractFramebuffer::maxDrawBuffers())
_l(Framebuffer::maxColorAttachments())
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
_l(Mesh::maxElementsIndices()) _l(Mesh::maxElementsIndices())
_l(Mesh::maxElementsVertices()) _l(Mesh::maxElementsVertices())
#endif #endif
_l(Renderbuffer::maxSize())
_l(Renderbuffer::maxSamples())
_l(Shader::maxVertexOutputComponents()) _l(Shader::maxVertexOutputComponents())
_l(Shader::maxFragmentInputComponents()) _l(Shader::maxFragmentInputComponents())
_l(Shader::maxTextureImageUnits(Shader::Type::Vertex)) _l(Shader::maxTextureImageUnits(Shader::Type::Vertex))
@ -208,6 +215,12 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_l(AbstractShaderProgram::maxVertexAttributes()) _l(AbstractShaderProgram::maxVertexAttributes())
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(c->isExtensionSupported<Extensions::GL::ARB::blend_func_extended>()) {
_h(ARB::blend_func_extended)
_l(AbstractFramebuffer::maxDualSourceDrawBuffers())
}
if(c->isExtensionSupported<Extensions::GL::ARB::compute_shader>()) { if(c->isExtensionSupported<Extensions::GL::ARB::compute_shader>()) {
_h(ARB::compute_shader) _h(ARB::compute_shader)

30
src/Renderbuffer.cpp

@ -40,6 +40,36 @@ Renderbuffer::StorageMultisampleImplementation Renderbuffer::storageMultisampleI
nullptr; nullptr;
#endif #endif
Int Renderbuffer::maxSize() {
GLint& value = Context::current()->state().framebuffer->maxRenderbufferSize;
/* Get the value, if not already cached */
if(value == 0)
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &value);
return value;
}
Int Renderbuffer::maxSamples() {
#ifdef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>())
return 0;
#endif
GLint& value = Context::current()->state().framebuffer->maxSamples;
/* Get the value, if not already cached */
if(value == 0) {
#ifndef MAGNUM_TARGET_GLES2
glGetIntegerv(GL_MAX_SAMPLES, &value);
#else
glGetIntegerv(GL_MAX_SAMPLES_NV, &value);
#endif
}
return value;
}
Renderbuffer::~Renderbuffer() { Renderbuffer::~Renderbuffer() {
/* If bound, remove itself from state */ /* If bound, remove itself from state */
GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding; GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding;

35
src/Renderbuffer.h

@ -43,10 +43,12 @@ for more information.
@section Renderbuffer-performance-optimization Performance optimizations @section Renderbuffer-performance-optimization Performance optimizations
The engine tracks currently bound renderbuffer to avoid unnecessary calls to The engine tracks currently bound renderbuffer to avoid unnecessary calls to
@fn_gl{BindRenderbuffer} in setStorage(). @fn_gl{BindRenderbuffer} in setStorage(). %Renderbuffer limits and
implementation-defined values (such as @ref maxSize()) are cached, so repeated
queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, function If extension @extension{EXT,direct_state_access} is available, function
setStorage() uses DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}. setStorage() uses DSA to avoid unnecessary calls to @fn_gl{BindRenderbuffer}.
See its documentation for more information. See its documentation for more information.
@requires_gl30 %Extension @extension{ARB,framebuffer_object} @requires_gl30 %Extension @extension{ARB,framebuffer_object}
@ -60,6 +62,27 @@ class MAGNUM_EXPORT Renderbuffer {
Renderbuffer& operator=(Renderbuffer&&) = delete; Renderbuffer& operator=(Renderbuffer&&) = delete;
public: public:
/**
* @brief Max supported renderbuffer size
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls.
* @see @ref setStorage(), @ref setStorageMultisample(), @fn_gl{Get}
* with @def_gl{MAX_RENDERBUFFER_SIZE}
*/
static Int maxSize();
/**
* @brief Max supported sample count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If ES extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample} is not available,
* returns `0`.
* @see @ref setStorageMultisample(), @fn_gl{Get} with @def_gl{MAX_SAMPLES}
*/
static Int maxSamples();
/** /**
* @brief Constructor * @brief Constructor
* *
@ -87,8 +110,8 @@ class MAGNUM_EXPORT Renderbuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the * framebufferbuffer is not currently bound, it is bound before the
* operation. * operation.
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or * @see @ref maxSize(), @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage}
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} * or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
*/ */
void setStorage(RenderbufferFormat internalFormat, const Vector2i& size) { void setStorage(RenderbufferFormat internalFormat, const Vector2i& size) {
(this->*storageImplementation)(internalFormat, size); (this->*storageImplementation)(internalFormat, size);
@ -103,8 +126,8 @@ class MAGNUM_EXPORT Renderbuffer {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the * framebufferbuffer is not currently bound, it is bound before the
* operation. * operation.
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or * @see @ref maxSize(), @ref maxSamples(), @fn_gl{BindRenderbuffer},
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access} * @fn_gl{RenderbufferStorage} or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample} * @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample} * or @es_extension{NV,framebuffer_multisample}
* @todo How about @es_extension{APPLE,framebuffer_multisample}? * @todo How about @es_extension{APPLE,framebuffer_multisample}?

Loading…
Cancel
Save