Browse Source

Using EXT_direct_state_access in framebuffers.

Framebuffer::attach*() doesn't need the target at all (meaning the
attachment will be used for both reading and drawing), another
misunderstanding on my side.

Now the extension is used on all places where it can be used (except for
unimplemented features).
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
7d6b7a4b6b
  1. 61
      src/AbstractFramebuffer.cpp
  2. 27
      src/AbstractFramebuffer.h
  3. 4
      src/Context.cpp
  4. 18
      src/DefaultFramebuffer.cpp
  5. 37
      src/DefaultFramebuffer.h
  6. 119
      src/Framebuffer.cpp
  7. 191
      src/Framebuffer.h
  8. 31
      src/Renderbuffer.cpp
  9. 26
      src/Renderbuffer.h

61
src/AbstractFramebuffer.cpp

@ -25,6 +25,10 @@
namespace Magnum { namespace Magnum {
AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault;
AbstractFramebuffer::DrawBufferImplementation AbstractFramebuffer::drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
AbstractFramebuffer::ReadBufferImplementation AbstractFramebuffer::readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
AbstractFramebuffer::Target AbstractFramebuffer::readTarget = AbstractFramebuffer::Target::ReadDraw; AbstractFramebuffer::Target AbstractFramebuffer::readTarget = AbstractFramebuffer::Target::ReadDraw;
AbstractFramebuffer::Target AbstractFramebuffer::drawTarget = AbstractFramebuffer::Target::ReadDraw; AbstractFramebuffer::Target AbstractFramebuffer::drawTarget = AbstractFramebuffer::Target::ReadDraw;
@ -130,9 +134,66 @@ void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context)
readTarget = Target::Read; readTarget = Target::Read;
drawTarget = Target::Draw; drawTarget = Target::Draw;
} }
if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA;
}
#else #else
static_cast<void>(context); static_cast<void>(context);
#endif #endif
} }
void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers) {
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
bindInternal(drawTarget);
glDrawBuffers(count, buffers);
#else
static_cast<void>(count);
static_cast<void>(buffers);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers) {
glFramebufferDrawBuffersEXT(_id, count, buffers);
}
#endif
void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) {
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
bindInternal(drawTarget);
glDrawBuffer(buffer);
#else
static_cast<void>(buffer);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBufferImplementationDSA(GLenum buffer) {
glFramebufferDrawBufferEXT(_id, buffer);
}
#endif
void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
/** @todo Get some extension wrangler instead to avoid undeclared glReadBuffer() on ES2 */
#ifndef MAGNUM_TARGET_GLES2
bindInternal(readTarget);
glReadBuffer(buffer);
#else
static_cast<void>(buffer);
#endif
}
#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::readBufferImplementationDSA(GLenum buffer) {
glFramebufferReadBufferEXT(_id, buffer);
}
#endif
} }

27
src/AbstractFramebuffer.h

@ -255,7 +255,17 @@ class MAGNUM_EXPORT AbstractFramebuffer {
void MAGNUM_LOCAL bindInternal(Target target); void MAGNUM_LOCAL bindInternal(Target target);
void MAGNUM_LOCAL setViewportInternal(); void MAGNUM_LOCAL setViewportInternal();
static Target readTarget, drawTarget; static MAGNUM_LOCAL Target readTarget;
static MAGNUM_LOCAL Target drawTarget;
typedef void(AbstractFramebuffer::*DrawBuffersImplementation)(GLsizei, const GLenum*);
static MAGNUM_LOCAL DrawBuffersImplementation drawBuffersImplementation;
typedef void(AbstractFramebuffer::*DrawBufferImplementation)(GLenum);
static DrawBufferImplementation drawBufferImplementation;
typedef void(AbstractFramebuffer::*ReadBufferImplementation)(GLenum);
static ReadBufferImplementation readBufferImplementation;
GLuint _id; GLuint _id;
Vector2i _viewportPosition, _viewportSize; Vector2i _viewportPosition, _viewportSize;
@ -263,6 +273,21 @@ class MAGNUM_EXPORT AbstractFramebuffer {
private: private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
void MAGNUM_LOCAL drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers);
#endif
void MAGNUM_LOCAL drawBufferImplementationDefault(GLenum buffer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL drawBufferImplementationDSA(GLenum buffer);
#endif
void MAGNUM_LOCAL readBufferImplementationDefault(GLenum buffer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer);
#endif
}; };
inline AbstractFramebuffer::~AbstractFramebuffer() {} inline AbstractFramebuffer::~AbstractFramebuffer() {}

4
src/Context.cpp

@ -28,8 +28,10 @@
#include "DebugMarker.h" #include "DebugMarker.h"
#include "DefaultFramebuffer.h" #include "DefaultFramebuffer.h"
#include "Extensions.h" #include "Extensions.h"
#include "Framebuffer.h"
#include "IndexedMesh.h" #include "IndexedMesh.h"
#include "Mesh.h" #include "Mesh.h"
#include "Renderbuffer.h"
#include "Implementation/State.h" #include "Implementation/State.h"
@ -304,8 +306,10 @@ Context::Context() {
#endif #endif
DebugMarker::initializeContextBasedFunctionality(this); DebugMarker::initializeContextBasedFunctionality(this);
DefaultFramebuffer::initializeContextBasedFunctionality(this); DefaultFramebuffer::initializeContextBasedFunctionality(this);
Framebuffer::initializeContextBasedFunctionality(this);
IndexedMesh::initializeContextBasedFunctionality(this); IndexedMesh::initializeContextBasedFunctionality(this);
Mesh::initializeContextBasedFunctionality(this); Mesh::initializeContextBasedFunctionality(this);
Renderbuffer::initializeContextBasedFunctionality(this);
} }
Context::~Context() { Context::~Context() {

18
src/DefaultFramebuffer.cpp

@ -39,27 +39,11 @@ void DefaultFramebuffer::mapForDraw(std::initializer_list<std::pair<GLuint, Draw
for(const auto& attachment: attachments) for(const auto& attachment: attachments)
_attachments[attachment.first] = static_cast<GLenum>(attachment.second); _attachments[attachment.first] = static_cast<GLenum>(attachment.second);
bindInternal(drawTarget); (this->*drawBuffersImplementation)(max+1, _attachments);
glDrawBuffers(max+1, _attachments);
delete[] _attachments; delete[] _attachments;
} }
void DefaultFramebuffer::mapForDraw(DrawAttachment attachment) {
bindInternal(drawTarget);
glDrawBuffer(static_cast<GLenum>(attachment));
}
#endif #endif
void DefaultFramebuffer::mapForRead(ReadAttachment attachment) {
bindInternal(readTarget);
/** @todo Get some extension wrangler instead to avoid undeclared glReadBuffer() on ES2 */
#ifndef MAGNUM_TARGET_GLES2
glReadBuffer(static_cast<GLenum>(attachment));
#else
static_cast<void>(attachment);
#endif
}
void DefaultFramebuffer::initializeContextBasedFunctionality(Context* context) { void DefaultFramebuffer::initializeContextBasedFunctionality(Context* context) {
Implementation::FramebufferState* state = context->state()->framebuffer; Implementation::FramebufferState* state = context->state()->framebuffer;

37
src/DefaultFramebuffer.h

@ -57,6 +57,15 @@ void drawEvent() {
See Framebuffer documentation for more involved usage, usage of non-default or See Framebuffer documentation for more involved usage, usage of non-default or
multiple framebuffers. multiple framebuffers.
@section DefaultFramebuffer-performance-optimization Performance optimizations
See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer".
If extension @extension{EXT,direct_state_access} is available, functions
mapForDraw() and mapForRead() use DSA to avoid unnecessary calls to
@fn_gl{BindFramebuffer}. See their respective documentation for more
information.
*/ */
class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer { class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
friend class Context; friend class Context;
@ -208,7 +217,12 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* framebuffer.mapForDraw({{MyShader::ColorOutput, DefaultFramebuffer::DrawAttachment::BackLeft}, * framebuffer.mapForDraw({{MyShader::ColorOutput, DefaultFramebuffer::DrawAttachment::BackLeft},
* {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}}); * {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}});
* @endcode * @endcode
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} *
* 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
* @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.
*/ */
@ -220,21 +234,34 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* *
* Similar to above function, can be used in cases when shader has * Similar to above function, can be used in cases when shader has
* only one (unnamed) output. * only one (unnamed) output.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} *
* 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
* @fn_gl_extension{FramebufferDrawBuffer,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.
*/ */
void mapForDraw(DrawAttachment attachment); inline void mapForDraw(DrawAttachment attachment) {
(this->*drawBufferImplementation)(static_cast<GLenum>(attachment));
}
#endif #endif
/** /**
* @brief Map given attachment for reading * @brief Map given attachment for reading
* @param attachment Buffer attachment * @param attachment Buffer attachment
* *
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} or
* @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
*/ */
void mapForRead(ReadAttachment attachment); inline void mapForRead(ReadAttachment attachment) {
(this->*readBufferImplementation)(static_cast<GLenum>(attachment));
}
private: private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);

119
src/Framebuffer.cpp

@ -17,6 +17,7 @@
#include "BufferImage.h" #include "BufferImage.h"
#include "Context.h" #include "Context.h"
#include "Extensions.h"
#include "Image.h" #include "Image.h"
#include "Renderbuffer.h" #include "Renderbuffer.h"
#include "Texture.h" #include "Texture.h"
@ -26,6 +27,13 @@
namespace Magnum { namespace Magnum {
Framebuffer::RenderbufferImplementation Framebuffer::renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
Framebuffer::Texture1DImplementation Framebuffer::texture1DImplementation = &Framebuffer::texture1DImplementationDefault;
#endif
Framebuffer::Texture2DImplementation Framebuffer::texture2DImplementation = &Framebuffer::texture2DImplementationDefault;
Framebuffer::Texture3DImplementation Framebuffer::texture3DImplementation = &Framebuffer::texture3DImplementationDefault;
Framebuffer::Framebuffer(const Vector2i& viewportPosition, const Vector2i& viewportSize) { Framebuffer::Framebuffer(const Vector2i& viewportPosition, const Vector2i& viewportSize) {
_viewportPosition = viewportPosition; _viewportPosition = viewportPosition;
_viewportSize = viewportSize; _viewportSize = viewportSize;
@ -54,103 +62,84 @@ void Framebuffer::mapForDraw(std::initializer_list<std::pair<GLuint, std::int8_t
for(const auto& attachment: attachments) for(const auto& attachment: attachments)
_attachments[attachment.first] = attachment.second < 0 ? GL_NONE : GL_COLOR_ATTACHMENT0 + attachment.second; _attachments[attachment.first] = attachment.second < 0 ? GL_NONE : GL_COLOR_ATTACHMENT0 + attachment.second;
bindInternal(drawTarget); (this->*drawBuffersImplementation)(max+1, _attachments);
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
glDrawBuffers(max+1, _attachments);
#endif
delete[] _attachments; delete[] _attachments;
} }
void Framebuffer::mapForDraw(std::int8_t attachment) { void Framebuffer::attachTexture2D(DepthStencilAttachment depthStencilAttachment, Texture2D* texture, GLint mipLevel) {
bindInternal(drawTarget); /** @todo Check for texture target compatibility */
glDrawBuffer(static_cast<GLenum>(attachment)); (this->*texture2DImplementation)(GLenum(depthStencilAttachment), GLenum(texture->target()), texture->id(), mipLevel);
} }
void Framebuffer::mapForRead(std::uint8_t colorAttachment) { void Framebuffer::attachTexture2D(std::uint8_t colorAttachment, Texture2D* texture, GLint mipLevel) {
bindInternal(Target::Read); /** @todo Check for texture target compatibility */
/** @todo Get some extension wrangler instead to avoid undeclared glReadBuffer() on ES2 */ (this->*texture2DImplementation)(GL_COLOR_ATTACHMENT0 + colorAttachment, GLenum(texture->target()), texture->id(), mipLevel);
#ifndef MAGNUM_TARGET_GLES2
glReadBuffer(GL_COLOR_ATTACHMENT0 + colorAttachment);
#else
static_cast<void>(colorAttachment);
#endif
} }
void Framebuffer::attachRenderbuffer(Target target, DepthStencilAttachment depthStencilAttachment, Renderbuffer* renderbuffer) { void Framebuffer::initializeContextBasedFunctionality(Context* context) {
bindInternal(target); #ifndef MAGNUM_TARGET_GLES
glFramebufferRenderbuffer(static_cast<GLenum>(target), static_cast<GLenum>(depthStencilAttachment), GL_RENDERBUFFER, renderbuffer->id()); if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "Framebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA;
texture1DImplementation = &Framebuffer::texture1DImplementationDSA;
texture2DImplementation = &Framebuffer::texture2DImplementationDSA;
texture3DImplementation = &Framebuffer::texture3DImplementationDSA;
}
#else
static_cast<void>(context);
#endif
} }
void Framebuffer::attachRenderbuffer(Target target, std::uint8_t colorAttachment, Renderbuffer* renderbuffer) { void Framebuffer::renderbufferImplementationDefault(GLenum attachment, Renderbuffer* renderbuffer) {
bindInternal(target); bindInternal(drawTarget);
glFramebufferRenderbuffer(static_cast<GLenum>(target), GL_COLOR_ATTACHMENT0 + colorAttachment, GL_RENDERBUFFER, renderbuffer->id()); glFramebufferRenderbuffer(static_cast<GLenum>(drawTarget), attachment, GL_RENDERBUFFER, renderbuffer->id());
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Framebuffer::attachTexture1D(Target target, DepthStencilAttachment depthStencilAttachment, Texture1D* texture, GLint mipLevel) { void Framebuffer::renderbufferImplementationDSA(GLenum attachment, Renderbuffer* renderbuffer) {
/** @todo Check for texture target compatibility */ glNamedFramebufferRenderbufferEXT(_id, attachment, GL_RENDERBUFFER, renderbuffer->id());
bindInternal(target);
glFramebufferTexture1D(static_cast<GLenum>(target), static_cast<GLenum>(depthStencilAttachment), static_cast<GLenum>(texture->target()), texture->id(), mipLevel);
} }
void Framebuffer::attachTexture1D(Target target, std::uint8_t colorAttachment, Texture1D* texture, GLint mipLevel) { void Framebuffer::texture1DImplementationDefault(GLenum attachment, Texture1D* texture, GLint mipLevel) {
/** @todo Check for texture target compatibility */ bindInternal(drawTarget);
bindInternal(target); glFramebufferTexture1D(static_cast<GLenum>(drawTarget), attachment, static_cast<GLenum>(texture->target()), texture->id(), mipLevel);
glFramebufferTexture1D(static_cast<GLenum>(target), GL_COLOR_ATTACHMENT0 + colorAttachment, static_cast<GLenum>(texture->target()), texture->id(), mipLevel);
}
#endif
void Framebuffer::attachTexture2D(Target target, DepthStencilAttachment depthStencilAttachment, Texture2D* texture, GLint mipLevel) {
/** @todo Check for texture target compatibility */
bindInternal(target);
glFramebufferTexture2D(static_cast<GLenum>(target), static_cast<GLenum>(depthStencilAttachment), static_cast<GLenum>(texture->target()), texture->id(), mipLevel);
} }
void Framebuffer::attachTexture2D(Target target, std::uint8_t colorAttachment, Texture2D* texture, GLint mipLevel) { void Framebuffer::texture1DImplementationDSA(GLenum attachment, Texture1D* texture, GLint mipLevel) {
/** @todo Check for texture target compatibility */ glNamedFramebufferTexture1DEXT(_id, attachment, GLenum(texture->target()), texture->id(), mipLevel);
bindInternal(target);
glFramebufferTexture2D(static_cast<GLenum>(target), GL_COLOR_ATTACHMENT0 + colorAttachment, static_cast<GLenum>(texture->target()), texture->id(), mipLevel);
} }
#endif
void Framebuffer::attachCubeMapTexture(Target target, DepthStencilAttachment depthStencilAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel) { void Framebuffer::texture2DImplementationDefault(GLenum attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel) {
/** @todo Check for internal format compatibility */ bindInternal(drawTarget);
bindInternal(target); glFramebufferTexture2D(static_cast<GLenum>(drawTarget), attachment, textureTarget, textureId, mipLevel);
glFramebufferTexture2D(static_cast<GLenum>(target), static_cast<GLenum>(depthStencilAttachment), static_cast<GLenum>(coordinate), texture->id(), mipLevel);
} }
void Framebuffer::attachCubeMapTexture(Target target, std::uint8_t colorAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel) { #ifndef MAGNUM_TARGET_GLES
/** @todo Check for internal format compatibility */ void Framebuffer::texture2DImplementationDSA(GLenum attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel) {
bindInternal(target); glNamedFramebufferTexture2DEXT(_id, attachment, textureTarget, textureId, mipLevel);
glFramebufferTexture2D(static_cast<GLenum>(target), GL_COLOR_ATTACHMENT0 + colorAttachment, static_cast<GLenum>(coordinate), texture->id(), mipLevel);
} }
#endif
void Framebuffer::attachTexture3D(Target target, DepthStencilAttachment depthStencilAttachment, Texture3D* texture, GLint mipLevel, GLint layer) { void Framebuffer::texture3DImplementationDefault(GLenum attachment, Texture3D* texture, GLint mipLevel, GLint layer) {
/** @todo Check for texture target compatibility */ /** @todo Check for texture target compatibility */
bindInternal(target); bindInternal(drawTarget);
/** @todo Get some extension wrangler for glFramebufferTexture3D() (extension only) */ /** @todo Get some extension wrangler for glFramebufferTexture3D() (extension only) */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glFramebufferTexture3D(static_cast<GLenum>(target), static_cast<GLenum>(depthStencilAttachment), static_cast<GLenum>(texture->target()), texture->id(), mipLevel, layer); glFramebufferTexture3D(static_cast<GLenum>(drawTarget), attachment, static_cast<GLenum>(texture->target()), texture->id(), mipLevel, layer);
#else #else
static_cast<void>(depthStencilAttachment); static_cast<void>(attachment);
static_cast<void>(texture); static_cast<void>(texture);
static_cast<void>(mipLevel); static_cast<void>(mipLevel);
static_cast<void>(layer); static_cast<void>(layer);
#endif #endif
} }
void Framebuffer::attachTexture3D(Target target, std::uint8_t colorAttachment, Texture3D* texture, GLint mipLevel, GLint layer) { #ifndef MAGNUM_TARGET_GLES
/** @todo Check for texture target compatibility */ void Framebuffer::texture3DImplementationDSA(GLenum attachment, Texture3D* texture, GLint mipLevel, GLint layer) {
bindInternal(target); glNamedFramebufferTexture3DEXT(_id, attachment, GLenum(texture->target()), texture->id(), mipLevel, layer);
/** @todo Get some extension wrangler for glFramebufferTexture3D() (extension only) */
#ifndef MAGNUM_TARGET_GLES
glFramebufferTexture3D(static_cast<GLenum>(target), GL_COLOR_ATTACHMENT0 + colorAttachment, static_cast<GLenum>(texture->target()), texture->id(), mipLevel, layer);
#else
static_cast<void>(colorAttachment);
static_cast<void>(texture);
static_cast<void>(mipLevel);
static_cast<void>(layer);
#endif
} }
#endif
} }

191
src/Framebuffer.h

@ -46,9 +46,9 @@ Renderbuffer depthStencil;
// configure the textures and allocate texture memory... // configure the textures and allocate texture memory...
framebuffer.attachTexture2D(Framebuffer::Target::Draw, 0, &color); framebuffer.attachTexture2D(0, &color);
framebuffer.attachTexture2D(Framebuffer::Target::Draw, 1, &normal); framebuffer.attachTexture2D(1, &normal);
framebuffer.attachRenderbuffer(Framebuffer::Target::Draw, Framebuffer::DepthStencilAttachment::DepthStencil, &depthStencil); framebuffer.attachRenderbuffer(Framebuffer::DepthStencilAttachment::DepthStencil, &depthStencil);
@endcode @endcode
Then you need to map outputs of your shader to color attachments in the Then you need to map outputs of your shader to color attachments in the
@ -75,9 +75,21 @@ void drawEvent() {
} }
@endcode @endcode
@section Framebuffer-performance-optimization Performance optimizations
See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer".
If extension @extension{EXT,direct_state_access} is available, functions
mapForDraw(), mapForRead(), attachRenderbuffer(), attachTexture1D(),
attachTexture2D(), attachCubeMapTexture() and attachTexture3D() use DSA
to avoid unnecessary calls to @fn_gl{BindFramebuffer}. See their respective
documentation for more information.
@requires_gl30 %Extension @extension{EXT,framebuffer_object} @requires_gl30 %Extension @extension{EXT,framebuffer_object}
*/ */
class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer { class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
friend class Context;
public: public:
/** /**
* @brief Constructor * @brief Constructor
@ -106,7 +118,12 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
* framebuffer.mapForDraw({{MyShader::ColorOutput, 0}, * framebuffer.mapForDraw({{MyShader::ColorOutput, 0},
* {MyShader::NormalOutput, 1}}); * {MyShader::NormalOutput, 1}});
* @endcode * @endcode
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} *
* 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
* @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}
*/ */
void mapForDraw(std::initializer_list<std::pair<GLuint, std::int8_t>> attachments); void mapForDraw(std::initializer_list<std::pair<GLuint, std::int8_t>> attachments);
@ -117,19 +134,32 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
* *
* Similar to above function, can be used in cases when shader has * Similar to above function, can be used in cases when shader has
* only one (unnamed) output. * only one (unnamed) output.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} *
* 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
* @fn_gl_extension{FramebufferDrawBuffer,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}
*/ */
void mapForDraw(std::int8_t attachment); inline void mapForDraw(std::int8_t attachment) {
(this->*drawBufferImplementation)(static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + attachment));
}
/** /**
* @brief Map given color attachment for reading * @brief Map given color attachment for reading
* @param attachment Color attachment ID * @param attachment Color attachment ID
* *
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} * If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} or
* @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
*/ */
void mapForRead(std::uint8_t attachment); inline void mapForRead(std::uint8_t attachment) {
(this->*readBufferImplementation)(GL_COLOR_ATTACHMENT0 + attachment);
}
/** /**
* @brief Attachment for depth/stencil part of fragment shader output * @brief Attachment for depth/stencil part of fragment shader output
@ -155,127 +185,204 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
/** /**
* @brief Attach renderbuffer to given framebuffer depth/stencil attachment * @brief Attach renderbuffer to given framebuffer depth/stencil attachment
* @param target %Target
* @param depthStencilAttachment Depth/stencil attachment * @param depthStencilAttachment Depth/stencil attachment
* @param renderbuffer %Renderbuffer * @param renderbuffer %Renderbuffer
* *
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} * 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{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} or
* @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access}
*/ */
void attachRenderbuffer(Target target, DepthStencilAttachment depthStencilAttachment, Renderbuffer* renderbuffer); inline void attachRenderbuffer(DepthStencilAttachment depthStencilAttachment, Renderbuffer* renderbuffer) {
(this->*renderbufferImplementation)(GLenum(depthStencilAttachment), renderbuffer);
}
/** /**
* @brief Attach renderbuffer to given framebuffer color attachment * @brief Attach renderbuffer to given framebuffer color attachment
* @param target %Target
* @param colorAttachment Color attachment ID (number between 0 and 15) * @param colorAttachment Color attachment ID (number between 0 and 15)
* @param renderbuffer %Renderbuffer * @param renderbuffer %Renderbuffer
* *
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} * 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{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} or
* @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access}
*/ */
void attachRenderbuffer(Target target, std::uint8_t colorAttachment, Renderbuffer* renderbuffer); inline void attachRenderbuffer(std::uint8_t colorAttachment, Renderbuffer* renderbuffer) {
(this->*renderbufferImplementation)(GL_COLOR_ATTACHMENT0 + colorAttachment, renderbuffer);
}
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Attach 1D texture to given framebuffer depth/stencil attachment * @brief Attach 1D texture to given framebuffer depth/stencil attachment
* @param target %Target
* @param depthStencilAttachment Depth/stencil attachment * @param depthStencilAttachment Depth/stencil attachment
* @param texture 1D texture * @param texture 1D texture
* @param mipLevel Mip level * @param mipLevel Mip level
* *
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferTexture} * 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{BindFramebuffer}, @fn_gl{FramebufferTexture} or
* @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}
* @requires_gl Only 2D and 3D textures are available in OpenGL ES. * @requires_gl Only 2D and 3D textures are available in OpenGL ES.
*/ */
void attachTexture1D(Target target, DepthStencilAttachment depthStencilAttachment, Texture1D* texture, GLint mipLevel); inline void attachTexture1D(DepthStencilAttachment depthStencilAttachment, Texture1D* texture, GLint mipLevel) {
/** @todo Check for texture target compatibility */
(this->*texture1DImplementation)(GLenum(depthStencilAttachment), texture, mipLevel);
}
/** /**
* @brief Attach 1D texture to given framebuffer color attachment * @brief Attach 1D texture to given framebuffer color attachment
* @param target %Target
* @param colorAttachment Color attachment ID (number between 0 and 15) * @param colorAttachment Color attachment ID (number between 0 and 15)
* @param texture 1D texture * @param texture 1D texture
* @param mipLevel Mip level * @param mipLevel Mip level
* *
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferTexture} * 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{BindFramebuffer}, @fn_gl{FramebufferTexture} or
* @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}
* @requires_gl Only 2D and 3D textures are available in OpenGL ES. * @requires_gl Only 2D and 3D textures are available in OpenGL ES.
*/ */
void attachTexture1D(Target target, std::uint8_t colorAttachment, Texture1D* texture, GLint mipLevel); inline void attachTexture1D(std::uint8_t colorAttachment, Texture1D* texture, GLint mipLevel) {
/** @todo Check for texture target compatibility */
(this->*texture1DImplementation)(GL_COLOR_ATTACHMENT0 + colorAttachment, texture, mipLevel);
}
#endif #endif
/** /**
* @brief Attach 2D texture to given framebuffer depth/stencil attachment * @brief Attach 2D texture to given framebuffer depth/stencil attachment
* @param target %Target
* @param depthStencilAttachment Depth/stencil attachment * @param depthStencilAttachment Depth/stencil attachment
* @param texture 2D texture * @param texture 2D texture
* @param mipLevel Mip level. For rectangle textures it * @param mipLevel Mip level. For rectangle textures it
* should be always 0. * should be always 0.
* *
* @see attachCubeMapTexture(), @fn_gl{BindFramebuffer}, * If @extension{EXT,direct_state_access} is not available and the
* @fn_gl{FramebufferTexture} * framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see attachCubeMapTexture(), @fn_gl{BindFramebuffer}, @fn_gl{FramebufferTexture}
* or @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}
*/ */
void attachTexture2D(Target target, DepthStencilAttachment depthStencilAttachment, Texture2D* texture, GLint mipLevel); void attachTexture2D(DepthStencilAttachment depthStencilAttachment, Texture2D* texture, GLint mipLevel);
/** /**
* @brief Attach 2D texture to given framebuffer color attachment * @brief Attach 2D texture to given framebuffer color attachment
* @param target %Target
* @param colorAttachment Color attachment ID (number between 0 and 15) * @param colorAttachment Color attachment ID (number between 0 and 15)
* @param texture 2D texture * @param texture 2D texture
* @param mipLevel Mip level. For rectangle textures it * @param mipLevel Mip level. For rectangle textures it
* should be always 0. * should be always 0.
* *
* @see attachCubeMapTexture(), @fn_gl{BindFramebuffer}, * If @extension{EXT,direct_state_access} is not available and the
* @fn_gl{FramebufferTexture} * framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see attachCubeMapTexture(), @fn_gl{BindFramebuffer}, @fn_gl{FramebufferTexture}
* or @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}
*/ */
void attachTexture2D(Target target, std::uint8_t colorAttachment, Texture2D* texture, GLint mipLevel); void attachTexture2D(std::uint8_t colorAttachment, Texture2D* texture, GLint mipLevel);
/** /**
* @brief Attach cube map texture to given framebuffer depth/stencil attachment * @brief Attach cube map texture to given framebuffer depth/stencil attachment
* @param target %Target
* @param depthStencilAttachment Depth/stencil attachment * @param depthStencilAttachment Depth/stencil attachment
* @param texture Cube map texture * @param texture Cube map texture
* @param coordinate Cube map coordinate * @param coordinate Cube map coordinate
* @param mipLevel Mip level * @param mipLevel Mip level
* *
* @see attachTexture2D(), @fn_gl{BindFramebuffer}, * If @extension{EXT,direct_state_access} is not available and the
* @fn_gl{FramebufferTexture} * framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see attachTexture2D(), @fn_gl{BindFramebuffer}, @fn_gl{FramebufferTexture}
* or @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}
*/ */
void attachCubeMapTexture(Target target, DepthStencilAttachment depthStencilAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel); inline void attachCubeMapTexture(DepthStencilAttachment depthStencilAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel) {
(this->*texture2DImplementation)(GLenum(depthStencilAttachment), GLenum(coordinate), texture->id(), mipLevel);
}
/** /**
* @brief Attach cube map texture to given framebuffer color attachment * @brief Attach cube map texture to given framebuffer color attachment
* @param target %Target
* @param colorAttachment Color attachment ID (number between 0 and 15) * @param colorAttachment Color attachment ID (number between 0 and 15)
* @param texture Cube map texture * @param texture Cube map texture
* @param coordinate Cube map coordinate * @param coordinate Cube map coordinate
* @param mipLevel Mip level * @param mipLevel Mip level
* *
* @see attachTexture2D(), @fn_gl{BindFramebuffer}, * If @extension{EXT,direct_state_access} is not available and the
* @fn_gl{FramebufferTexture} * framebufferbuffer is not currently bound, it is bound before the
* operation.
* @see attachTexture2D(), @fn_gl{BindFramebuffer}, @fn_gl{FramebufferTexture}
* or @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}
*/ */
void attachCubeMapTexture(Target target, std::uint8_t colorAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel); inline void attachCubeMapTexture(std::uint8_t colorAttachment, CubeMapTexture* texture, CubeMapTexture::Coordinate coordinate, GLint mipLevel) {
(this->*texture2DImplementation)(GL_COLOR_ATTACHMENT0 + colorAttachment, GLenum(coordinate), texture->id(), mipLevel);
}
/** /**
* @brief Attach 3D texture to given framebuffer depth/stencil attachment * @brief Attach 3D texture to given framebuffer depth/stencil attachment
* @param target %Target
* @param depthStencilAttachment Depth/stencil attachment * @param depthStencilAttachment Depth/stencil attachment
* @param texture 3D texture * @param texture 3D texture
* @param mipLevel Mip level * @param mipLevel Mip level
* @param layer Layer of 2D image within a 3D texture * @param layer Layer of 2D image within a 3D texture
* *
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferTexture} * 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{BindFramebuffer}, @fn_gl{FramebufferTexture} or
* @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access}
* @requires_es_extension %Extension @es_extension{OES,texture_3D} * @requires_es_extension %Extension @es_extension{OES,texture_3D}
*/ */
void attachTexture3D(Target target, DepthStencilAttachment depthStencilAttachment, Texture3D* texture, GLint mipLevel, GLint layer); inline void attachTexture3D(DepthStencilAttachment depthStencilAttachment, Texture3D* texture, GLint mipLevel, GLint layer) {
/** @todo Check for texture target compatibility */
(this->*texture3DImplementation)(GLenum(depthStencilAttachment), texture, mipLevel, layer);
}
/** /**
* @brief Attach 3D texture to given framebuffer color attachment * @brief Attach 3D texture to given framebuffer color attachment
* @param target %Target
* @param colorAttachment Color attachment ID (number between 0 and 15) * @param colorAttachment Color attachment ID (number between 0 and 15)
* @param texture 3D texture * @param texture 3D texture
* @param mipLevel Mip level * @param mipLevel Mip level
* @param layer Layer of 2D image within a 3D texture. * @param layer Layer of 2D image within a 3D texture.
* *
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferTexture} * 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{BindFramebuffer}, @fn_gl{FramebufferTexture} or
* @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access}
* @requires_es_extension %Extension @es_extension{OES,texture_3D} * @requires_es_extension %Extension @es_extension{OES,texture_3D}
*/ */
void attachTexture3D(Target target, std::uint8_t colorAttachment, Texture3D* texture, GLint mipLevel, GLint layer); inline void attachTexture3D(std::uint8_t colorAttachment, Texture3D* texture, GLint mipLevel, GLint layer) {
/** @todo Check for texture target compatibility */
(this->*texture3DImplementation)(GL_COLOR_ATTACHMENT0 + colorAttachment, texture, mipLevel, layer);
}
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
typedef void(Framebuffer::*RenderbufferImplementation)(GLenum, Renderbuffer*);
void MAGNUM_LOCAL renderbufferImplementationDefault(GLenum attachment, Renderbuffer* renderbuffer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL renderbufferImplementationDSA(GLenum attachment, Renderbuffer* renderbuffer);
#endif
static RenderbufferImplementation renderbufferImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(Framebuffer::*Texture1DImplementation)(GLenum, Texture1D*, GLint);
void MAGNUM_LOCAL texture1DImplementationDefault(GLenum attachment, Texture1D* texture, GLint mipLevel);
void MAGNUM_LOCAL texture1DImplementationDSA(GLenum attachment, Texture1D* texture, GLint mipLevel);
static Texture1DImplementation texture1DImplementation;
#endif
typedef void(Framebuffer::*Texture2DImplementation)(GLenum, GLenum, GLuint, GLint);
void MAGNUM_LOCAL texture2DImplementationDefault(GLenum attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture2DImplementationDSA(GLenum attachment, GLenum textureTarget, GLuint textureId, GLint mipLevel);
#endif
static MAGNUM_LOCAL Texture2DImplementation texture2DImplementation;
typedef void(Framebuffer::*Texture3DImplementation)(GLenum, Texture3D*, GLint, GLint);
void MAGNUM_LOCAL texture3DImplementationDefault(GLenum attachment, Texture3D* texture, GLint mipLevel, GLint layer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture3DImplementationDSA(GLenum attachment, Texture3D* texture, GLint mipLevel, GLint layer);
#endif
static Texture3DImplementation texture3DImplementation;
}; };
} }

31
src/Renderbuffer.cpp

@ -16,12 +16,15 @@
#include "Renderbuffer.h" #include "Renderbuffer.h"
#include "Context.h" #include "Context.h"
#include "Extensions.h"
#include "Implementation/State.h" #include "Implementation/State.h"
#include "Implementation/FramebufferState.h" #include "Implementation/FramebufferState.h"
namespace Magnum { namespace Magnum {
Renderbuffer::StorageImplementation Renderbuffer::storageImplementation = &Renderbuffer::storageImplementationDefault;
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;
@ -30,11 +33,6 @@ Renderbuffer::~Renderbuffer() {
glDeleteRenderbuffers(1, &_id); glDeleteRenderbuffers(1, &_id);
} }
void Renderbuffer::setStorage(Renderbuffer::InternalFormat internalFormat, const Vector2i& size) {
bind();
glRenderbufferStorage(GL_RENDERBUFFER, GLenum(internalFormat), size.x(), size.y());
}
void Renderbuffer::bind() { void Renderbuffer::bind() {
GLuint& binding = Context::current()->state()->framebuffer->renderbufferBinding; GLuint& binding = Context::current()->state()->framebuffer->renderbufferBinding;
@ -44,4 +42,27 @@ void Renderbuffer::bind() {
glBindRenderbuffer(GL_RENDERBUFFER, _id); glBindRenderbuffer(GL_RENDERBUFFER, _id);
} }
void Renderbuffer::initializeContextBasedFunctionality(Context* context) {
#ifndef MAGNUM_TARGET_GLES
if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "Renderbuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
storageImplementation = &Renderbuffer::storageImplementationDSA;
}
#else
static_cast<void>(context);
#endif
}
void Renderbuffer::storageImplementationDefault(Renderbuffer::InternalFormat internalFormat, const Vector2i& size) {
bind();
glRenderbufferStorage(GL_RENDERBUFFER, GLenum(internalFormat), size.x(), size.y());
}
#ifndef MAGNUM_TARGET_GLES
void Renderbuffer::storageImplementationDSA(Renderbuffer::InternalFormat internalFormat, const Vector2i& size) {
glNamedRenderbufferStorageEXT(_id, GLenum(internalFormat), size.x(), size.y());
}
#endif
} }

26
src/Renderbuffer.h

@ -19,7 +19,6 @@
* @brief Class Magnum::Renderbuffer * @brief Class Magnum::Renderbuffer
*/ */
#include "Math/Vector2.h"
#include "Magnum.h" #include "Magnum.h"
#include "magnumVisibility.h" #include "magnumVisibility.h"
@ -37,9 +36,15 @@ for more information.
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().
If extension @extension{EXT,direct_state_access} is available, function
setStorage() uses DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}.
See its documentation for more information.
@requires_gl30 %Extension @extension{EXT,framebuffer_object} @requires_gl30 %Extension @extension{EXT,framebuffer_object}
*/ */
class MAGNUM_EXPORT Renderbuffer { class MAGNUM_EXPORT Renderbuffer {
friend class Context;
Renderbuffer(const Renderbuffer& other) = delete; Renderbuffer(const Renderbuffer& other) = delete;
Renderbuffer(Renderbuffer&& other) = delete; Renderbuffer(Renderbuffer&& other) = delete;
Renderbuffer& operator=(const Renderbuffer& other) = delete; Renderbuffer& operator=(const Renderbuffer& other) = delete;
@ -538,11 +543,26 @@ class MAGNUM_EXPORT Renderbuffer {
* @param internalFormat Internal format * @param internalFormat Internal format
* @param size Renderbuffer size * @param size Renderbuffer size
* *
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} * 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}
*/ */
void setStorage(InternalFormat internalFormat, const Vector2i& size); inline void setStorage(InternalFormat internalFormat, const Vector2i& size) {
(this->*storageImplementation)(internalFormat, size);
}
private: private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
typedef void(Renderbuffer::*StorageImplementation)(InternalFormat, const Vector2i&);
void MAGNUM_LOCAL storageImplementationDefault(InternalFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(InternalFormat internalFormat, const Vector2i& size);
#endif
static StorageImplementation storageImplementation;
void MAGNUM_LOCAL bind(); void MAGNUM_LOCAL bind();
GLuint _id; GLuint _id;

Loading…
Cancel
Save