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;
#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) {
bindInternal(target);
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
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
from buffer overflow.
@todo @extension{ARB,viewport_array}
@todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`)
*/
class MAGNUM_EXPORT AbstractFramebuffer {
friend class Context;
@ -148,6 +150,43 @@ class MAGNUM_EXPORT AbstractFramebuffer {
AbstractFramebuffer& operator=(AbstractFramebuffer&&) = delete;
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
* @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
* framebuffer is currently bound, updates the viewport to given
* rectangle.
* @see @fn_gl{Viewport}
* @see @ref maxViewportSize(), @fn_gl{Viewport}
*/
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
* framebuffer is not currently bound, it is bound before the
* operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}
* @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @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
* 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::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) {
_viewport = viewport;

19
src/Framebuffer.h

@ -272,6 +272,18 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
#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
*
@ -318,7 +330,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* 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}
* @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
* framebufferbuffer is not currently bound, it is bound before the
* 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{DrawBuffers} in OpenGL ES 3.0
* @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()
and others).
@see Image, ImageReference, BufferImage, Trade::ImageData
*/
*/
enum class ImageType: GLenum {
/** Each component unsigned byte. */
UnsignedByte = GL_UNSIGNED_BYTE,

11
src/Implementation/FramebufferState.h

@ -31,10 +31,19 @@
namespace Magnum { namespace Implementation {
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;
GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize, maxSamples;
#ifndef MAGNUM_TARGET_GLES
GLint maxDualSourceDrawBuffers;
#endif
Rectanglei viewport;
Vector2i maxViewportSize;
};
}}

13
src/Platform/magnum-info.cpp

@ -32,7 +32,9 @@
#include "AbstractShaderProgram.h"
#include "Context.h"
#include "Extensions.h"
#include "Framebuffer.h"
#include "Mesh.h"
#include "Renderbuffer.h"
#include "Shader.h"
#ifndef CORRADE_TARGET_NACL
#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;
Debug() << "Limits and implementation-defined values:";
_l(AbstractFramebuffer::maxViewportSize())
_l(AbstractFramebuffer::maxDrawBuffers())
_l(Framebuffer::maxColorAttachments())
#ifndef MAGNUM_TARGET_GLES2
_l(Mesh::maxElementsIndices())
_l(Mesh::maxElementsVertices())
#endif
_l(Renderbuffer::maxSize())
_l(Renderbuffer::maxSamples())
_l(Shader::maxVertexOutputComponents())
_l(Shader::maxFragmentInputComponents())
_l(Shader::maxTextureImageUnits(Shader::Type::Vertex))
@ -208,6 +215,12 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
_l(AbstractShaderProgram::maxVertexAttributes())
#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>()) {
_h(ARB::compute_shader)

30
src/Renderbuffer.cpp

@ -40,6 +40,36 @@ Renderbuffer::StorageMultisampleImplementation Renderbuffer::storageMultisampleI
nullptr;
#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() {
/* If bound, remove itself from state */
GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding;

35
src/Renderbuffer.h

@ -43,10 +43,12 @@ for more information.
@section Renderbuffer-performance-optimization Performance optimizations
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
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.
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@ -60,6 +62,27 @@ class MAGNUM_EXPORT Renderbuffer {
Renderbuffer& operator=(Renderbuffer&&) = delete;
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
*
@ -87,8 +110,8 @@ class MAGNUM_EXPORT Renderbuffer {
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
* @see @ref maxSize(), @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage}
* or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
*/
void setStorage(RenderbufferFormat internalFormat, const Vector2i& size) {
(this->*storageImplementation)(internalFormat, size);
@ -103,8 +126,8 @@ class MAGNUM_EXPORT Renderbuffer {
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
* @see @ref maxSize(), @ref maxSamples(), @fn_gl{BindRenderbuffer},
* @fn_gl{RenderbufferStorage} or @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample}
* @todo How about @es_extension{APPLE,framebuffer_multisample}?

Loading…
Cancel
Save