Browse Source

Moved global data from framebuffer classes to per-context state.

On the way to unify and reduce the "Using optional features" messages.
pull/51/head
Vladimír Vondruš 12 years ago
parent
commit
c1c71339e4
  1. 83
      src/Magnum/AbstractFramebuffer.cpp
  2. 25
      src/Magnum/AbstractFramebuffer.h
  3. 1
      src/Magnum/CMakeLists.txt
  4. 3
      src/Magnum/Context.cpp
  5. 16
      src/Magnum/DefaultFramebuffer.cpp
  6. 14
      src/Magnum/DefaultFramebuffer.h
  7. 57
      src/Magnum/Framebuffer.cpp
  8. 47
      src/Magnum/Framebuffer.h
  9. 141
      src/Magnum/Implementation/FramebufferState.cpp
  10. 32
      src/Magnum/Implementation/FramebufferState.h
  11. 2
      src/Magnum/Implementation/State.cpp
  12. 39
      src/Magnum/Renderbuffer.cpp
  13. 24
      src/Magnum/Renderbuffer.h

83
src/Magnum/AbstractFramebuffer.cpp

@ -37,19 +37,6 @@
namespace Magnum {
AbstractFramebuffer::CheckStatusImplementation AbstractFramebuffer::checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault;
AbstractFramebuffer::ReadImplementation AbstractFramebuffer::readImplementation = &AbstractFramebuffer::readImplementationDefault;
AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault;
AbstractFramebuffer::DrawBufferImplementation AbstractFramebuffer::drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
AbstractFramebuffer::ReadBufferImplementation AbstractFramebuffer::readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;
#ifdef MAGNUM_TARGET_GLES2
FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw;
FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw;
#endif
Vector2i AbstractFramebuffer::maxViewportSize() {
Vector2i& value = Context::current()->state().framebuffer->maxViewportSize;
@ -136,9 +123,9 @@ FramebufferTarget AbstractFramebuffer::bindInternal() {
glBindFramebuffer(GLenum(FramebufferTarget::Read), _id);
return FramebufferTarget::Read;
#else
if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
glBindFramebuffer(GLenum(readTarget), _id);
return readTarget;
if(state->readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
glBindFramebuffer(GLenum(state->readTarget), _id);
return state->readTarget;
#endif
}
@ -186,20 +173,22 @@ void AbstractFramebuffer::clear(FramebufferClearMask mask) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else
bindInternal(drawTarget);
bindInternal(Context::current()->state().framebuffer->drawTarget);
#endif
glClear(GLbitfield(mask));
}
void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Image2D& image) {
const Implementation::FramebufferState& state = *Context::current()->state().framebuffer;
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Read);
#else
bindInternal(readTarget);
bindInternal(state.readTarget);
#endif
const std::size_t dataSize = image.dataSize(size);
char* const data = new char[dataSize];
readImplementation(offset, size, image.format(), image.type(), dataSize, data);
(state.readImplementation)(offset, size, image.format(), image.type(), dataSize, data);
image.setData(image.format(), image.type(), size, data);
}
@ -216,7 +205,7 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Buf
image.setData(image.format(), image.type(), size, nullptr, usage);
image.buffer().bind(Buffer::Target::PixelPack);
readImplementation(offset, size, image.format(), image.type(), image.dataSize(size), nullptr);
(Context::current()->state().framebuffer->readImplementation)(offset, size, image.format(), image.type(), image.dataSize(size), nullptr);
}
#endif
@ -245,60 +234,6 @@ void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attach
#endif
}
void AbstractFramebuffer::initializeContextBasedFunctionality(Context& context) {
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA;
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA;
}
#endif
#ifdef MAGNUM_TARGET_GLES2
/* Optimistically set separate binding targets and check if one of the
extensions providing them is available */
readTarget = FramebufferTarget::Read;
drawTarget = FramebufferTarget::Draw;
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::ANGLE::framebuffer_blit::string() << "features";
else if(context.isExtensionSupported<Extensions::GL::APPLE::framebuffer_multisample>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::APPLE::framebuffer_multisample::string() << "features";
else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_blit>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_blit::string() << "features";
/* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these
enums. However, on my system only NV_framebuffer_multisample is
supported, but NV_framebuffer_blit isn't. I will hold my breath and
assume these enums are available. */
else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_multisample::string() << "features";
/* If no such extension is available, reset back to unified target */
else readTarget = drawTarget = FramebufferTarget::ReadDraw;
#endif
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::robustness>())
#else
if(context.isExtensionSupported<Extensions::GL::EXT::robustness>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
Debug() << "AbstractFramebuffer: using" << Extensions::GL::ARB::robustness::string() << "features";
#else
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::robustness::string() << "features";
#endif
readImplementation = &AbstractFramebuffer::readImplementationRobustness;
}
}
GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) {
bindInternal(target);
return glCheckFramebufferStatus(GLenum(target));

25
src/Magnum/AbstractFramebuffer.h

@ -127,6 +127,8 @@ enum class FramebufferTarget: GLenum {
ReadDraw = GL_FRAMEBUFFER /**< For both reading and drawing. */
};
namespace Implementation { struct FramebufferState; }
/**
@brief Base for default and named framebuffers
@ -145,7 +147,7 @@ protected from buffer overflow.
@todo @extension{ARB,viewport_array} (and `GL_MAX_VIEWPORTS`)
*/
class MAGNUM_EXPORT AbstractFramebuffer {
friend class Context;
friend class Implementation::FramebufferState;
public:
/** @todo `GL_IMPLEMENTATION_COLOR_READ_FORMAT`, `GL_IMPLEMENTATION_COLOR_READ_TYPE`, seems to be depending on currently bound FB (aargh) (@extension{ARB,ES2_compatibility}). */
@ -311,23 +313,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
FramebufferTarget MAGNUM_LOCAL bindInternal();
void MAGNUM_LOCAL setViewportInternal();
#ifdef MAGNUM_TARGET_GLES2
static MAGNUM_LOCAL FramebufferTarget readTarget;
static MAGNUM_LOCAL FramebufferTarget drawTarget;
#endif
typedef GLenum(AbstractFramebuffer::*CheckStatusImplementation)(FramebufferTarget);
static CheckStatusImplementation checkStatusImplementation;
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;
void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments);
void MAGNUM_LOCAL invalidateImplementation(GLsizei count, GLenum* attachments, const Range2Di& rectangle);
@ -335,8 +320,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
Range2Di _viewport;
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target);
#ifndef MAGNUM_TARGET_GLES
GLenum MAGNUM_LOCAL checkStatusImplementationDSA(FramebufferTarget target);
@ -357,10 +340,8 @@ class MAGNUM_EXPORT AbstractFramebuffer {
void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer);
#endif
typedef void(*ReadImplementation)(const Vector2i&, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*);
static void MAGNUM_LOCAL readImplementationDefault(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
static void MAGNUM_LOCAL readImplementationRobustness(const Vector2i& offset, const Vector2i& size, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
static ReadImplementation MAGNUM_LOCAL readImplementation;
};
CORRADE_ENUMSET_OPERATORS(FramebufferClearMask)

1
src/Magnum/CMakeLists.txt

@ -54,6 +54,7 @@ set(Magnum_SRCS
Implementation/BufferState.cpp
Implementation/DebugState.cpp
Implementation/FramebufferState.cpp
Implementation/State.cpp
Implementation/TextureState.cpp

3
src/Magnum/Context.cpp

@ -448,7 +448,6 @@ Context::Context() {
_state = new Implementation::State(*this);
/* Initialize functionality based on current OpenGL version and extensions */
AbstractFramebuffer::initializeContextBasedFunctionality(*this);
AbstractShaderProgram::initializeContextBasedFunctionality(*this);
AbstractTexture::initializeContextBasedFunctionality(*this);
Buffer::initializeContextBasedFunctionality(*this);
@ -456,9 +455,7 @@ Context::Context() {
BufferTexture::initializeContextBasedFunctionality(*this);
#endif
DefaultFramebuffer::initializeContextBasedFunctionality(*this);
Framebuffer::initializeContextBasedFunctionality(*this);
Mesh::initializeContextBasedFunctionality(*this);
Renderbuffer::initializeContextBasedFunctionality(*this);
Renderer::initializeContextBasedFunctionality(*this);
}

16
src/Magnum/DefaultFramebuffer.cpp

@ -38,6 +38,10 @@ DefaultFramebuffer defaultFramebuffer;
DefaultFramebuffer::DefaultFramebuffer() { _id = 0; }
DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarget target) {
return Status((this->*Context::current()->state().framebuffer->checkStatusImplementation)(target));
}
#ifndef MAGNUM_TARGET_GLES2
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments) {
/* Max attachment location */
@ -52,11 +56,21 @@ DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list<std::pa
for(const auto& attachment: attachments)
_attachments[attachment.first] = GLenum(attachment.second);
(this->*drawBuffersImplementation)(max+1, _attachments);
(this->*Context::current()->state().framebuffer->drawBuffersImplementation)(max+1, _attachments);
return *this;
}
DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) {
(this->*Context::current()->state().framebuffer->drawBufferImplementation)(GLenum(attachment));
return *this;
}
#endif
DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) {
(this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment));
return *this;
}
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments) {
/** @todo C++14: use VLA to avoid heap allocation */
Containers::Array<GLenum> _attachments(attachments.size());

14
src/Magnum/DefaultFramebuffer.h

@ -316,9 +316,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
Status checkStatus(FramebufferTarget target) {
return Status((this->*checkStatusImplementation)(target));
}
Status checkStatus(FramebufferTarget target);
#ifndef MAGNUM_TARGET_GLES2
/**
@ -362,10 +360,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @requires_gles30 Draw attachments for default framebuffer are
* available only in OpenGL ES 3.0.
*/
DefaultFramebuffer& mapForDraw(DrawAttachment attachment) {
(this->*drawBufferImplementation)(GLenum(attachment));
return *this;
}
DefaultFramebuffer& mapForDraw(DrawAttachment attachment);
#endif
/**
@ -380,10 +375,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
*/
DefaultFramebuffer& mapForRead(ReadAttachment attachment) {
(this->*readBufferImplementation)(GLenum(attachment));
return *this;
}
DefaultFramebuffer& mapForRead(ReadAttachment attachment);
/**
* @brief Invalidate framebuffer

57
src/Magnum/Framebuffer.cpp

@ -42,13 +42,6 @@
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;
const Framebuffer::DrawAttachment Framebuffer::DrawAttachment::None = Framebuffer::DrawAttachment(GL_NONE);
const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Depth = Framebuffer::BufferAttachment(GL_DEPTH_ATTACHMENT);
const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Stencil = Framebuffer::BufferAttachment(GL_STENCIL_ATTACHMENT);
@ -104,6 +97,10 @@ Framebuffer& Framebuffer::setLabel(const std::string& label) {
return *this;
}
Framebuffer::Status Framebuffer::checkStatus(const FramebufferTarget target) {
return Status((this->*Context::current()->state().framebuffer->checkStatusImplementation)(target));
}
Framebuffer& Framebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments) {
/* Max attachment location */
std::size_t max = 0;
@ -117,7 +114,17 @@ Framebuffer& Framebuffer::mapForDraw(std::initializer_list<std::pair<UnsignedInt
for(const auto& attachment: attachments)
_attachments[attachment.first] = GLenum(attachment.second);
(this->*drawBuffersImplementation)(max+1, _attachments);
(this->*Context::current()->state().framebuffer->drawBuffersImplementation)(max+1, _attachments);
return *this;
}
Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) {
(this->*Context::current()->state().framebuffer->drawBufferImplementation)(GLenum(attachment));
return *this;
}
Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) {
(this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment));
return *this;
}
@ -139,25 +146,33 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
invalidateImplementation(attachments.size(), _attachments, rectangle);
}
Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) {
(this->*Context::current()->state().framebuffer->renderbufferImplementation)(attachment, renderbuffer);
return *this;
}
#ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachTexture1D(const BufferAttachment attachment, Texture1D& texture, const Int level) {
(this->*Context::current()->state().framebuffer->texture1DImplementation)(attachment, texture, level);
return *this;
}
#endif
Framebuffer& Framebuffer::attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int mipLevel) {
/** @todo Check for texture target compatibility */
(this->*texture2DImplementation)(attachment, GLenum(texture.target()), texture.id(), mipLevel);
(this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(texture.target()), texture.id(), mipLevel);
return *this;
}
void Framebuffer::initializeContextBasedFunctionality(Context& context) {
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "Framebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
Framebuffer& Framebuffer::attachCubeMapTexture(const BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, const Int level) {
(this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GLenum(coordinate), texture.id(), level);
return *this;
}
renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA;
texture1DImplementation = &Framebuffer::texture1DImplementationDSA;
texture2DImplementation = &Framebuffer::texture2DImplementationDSA;
texture3DImplementation = &Framebuffer::texture3DImplementationDSA;
}
#else
static_cast<void>(context);
#endif
Framebuffer& Framebuffer::attachTexture3D(Framebuffer::BufferAttachment attachment, Texture3D& texture, Int level, Int layer) {
/** @todo Check for texture target compatibility */
(this->*Context::current()->state().framebuffer->texture3DImplementation)(attachment, texture, level, layer);
return *this;
}
void Framebuffer::renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer) {

47
src/Magnum/Framebuffer.h

@ -102,7 +102,7 @@ See their respective documentation for more information.
@todo `MAX_COLOR_ATTACHMENTS`
*/
class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObject {
friend class Context;
friend class Implementation::FramebufferState;
public:
/**
@ -364,9 +364,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}
*/
Status checkStatus(FramebufferTarget target) {
return Status((this->*checkStatusImplementation)(target));
}
Status checkStatus(FramebufferTarget target);
/**
* @brief Map shader output to attachments
@ -409,10 +407,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @fn_gl{DrawBuffers} in OpenGL ES 3.0
* @requires_gles30 %Extension @es_extension2{NV,draw_buffers,GL_NV_draw_buffers}
*/
Framebuffer& mapForDraw(DrawAttachment attachment) {
(this->*drawBufferImplementation)(GLenum(attachment));
return *this;
}
Framebuffer& mapForDraw(DrawAttachment attachment);
/**
* @brief Map given color attachment for reading
@ -426,10 +421,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* or @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
*/
Framebuffer& mapForRead(ColorAttachment attachment) {
(this->*readBufferImplementation)(GLenum(attachment));
return *this;
}
Framebuffer& mapForRead(ColorAttachment attachment);
/**
* @brief Invalidate framebuffer
@ -478,10 +470,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @see @fn_gl{BindFramebuffer}, @fn_gl{FramebufferRenderbuffer} or
* @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access}
*/
Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer) {
(this->*renderbufferImplementation)(attachment, renderbuffer);
return *this;
}
Framebuffer& attachRenderbuffer(BufferAttachment attachment, Renderbuffer& renderbuffer);
#ifndef MAGNUM_TARGET_GLES
/**
@ -498,10 +487,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* or @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}
* @requires_gl Only 2D and 3D textures are available in OpenGL ES.
*/
Framebuffer& attachTexture1D(BufferAttachment attachment, Texture1D& texture, Int level) {
(this->*texture1DImplementation)(attachment, texture, level);
return *this;
}
Framebuffer& attachTexture1D(BufferAttachment attachment, Texture1D& texture, Int level);
#endif
/**
@ -535,10 +521,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @fn_gl2{FramebufferTexture2D,FramebufferTexture} or
* @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}
*/
Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level) {
(this->*texture2DImplementation)(attachment, GLenum(coordinate), texture.id(), level);
return *this;
}
Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level);
/**
* @brief Attach 3D texture to given buffer
@ -555,11 +538,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* or @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access}
* @requires_es_extension %Extension @es_extension{OES,texture_3D}
*/
Framebuffer& attachTexture3D(BufferAttachment attachment, Texture3D& texture, Int level, Int layer) {
/** @todo Check for texture target compatibility */
(this->*texture3DImplementation)(attachment, texture, level, layer);
return *this;
}
Framebuffer& attachTexture3D(BufferAttachment attachment, Texture3D& texture, Int level, Int layer);
/* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT
@ -570,35 +549,25 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
#endif
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
typedef void(Framebuffer::*RenderbufferImplementation)(BufferAttachment, Renderbuffer&);
void MAGNUM_LOCAL renderbufferImplementationDefault(BufferAttachment attachment, Renderbuffer& renderbuffer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL renderbufferImplementationDSA(BufferAttachment attachment, Renderbuffer& renderbuffer);
#endif
static RenderbufferImplementation renderbufferImplementation;
#ifndef MAGNUM_TARGET_GLES
typedef void(Framebuffer::*Texture1DImplementation)(BufferAttachment, Texture1D&, GLint);
void MAGNUM_LOCAL texture1DImplementationDefault(BufferAttachment attachment, Texture1D& texture, GLint level);
void MAGNUM_LOCAL texture1DImplementationDSA(BufferAttachment attachment, Texture1D& texture, GLint level);
static Texture1DImplementation texture1DImplementation;
#endif
typedef void(Framebuffer::*Texture2DImplementation)(BufferAttachment, GLenum, GLuint, GLint);
void MAGNUM_LOCAL texture2DImplementationDefault(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture2DImplementationDSA(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#endif
static Texture2DImplementation texture2DImplementation;
typedef void(Framebuffer::*Texture3DImplementation)(BufferAttachment, Texture3D&, GLint, GLint);
void MAGNUM_LOCAL texture3DImplementationDefault(BufferAttachment attachment, Texture3D& texture, GLint level, GLint layer);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL texture3DImplementationDSA(BufferAttachment attachment, Texture3D& texture, GLint level, GLint layer);
#endif
static Texture3DImplementation texture3DImplementation;
};
/** @debugoperator{DefaultFramebuffer} */

141
src/Magnum/Implementation/FramebufferState.cpp

@ -0,0 +1,141 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "FramebufferState.h"
#include "Magnum/Context.h"
#include "Magnum/Extensions.h"
#include "Magnum/Renderbuffer.h"
namespace Magnum { namespace Implementation {
FramebufferState::FramebufferState(Context& context, std::vector<std::string>& extensions): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0)
#ifndef MAGNUM_TARGET_GLES
, maxDualSourceDrawBuffers(0)
#endif
{
/* DSA/non-DSA implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA;
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA;
renderbufferImplementation = &Framebuffer::renderbufferImplementationDSA;
texture1DImplementation = &Framebuffer::texture1DImplementationDSA;
texture2DImplementation = &Framebuffer::texture2DImplementationDSA;
texture3DImplementation = &Framebuffer::texture3DImplementationDSA;
renderbufferStorageImplementation = &Renderbuffer::storageImplementationDSA;
} else
#endif
{
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault;
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;
renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
texture1DImplementation = &Framebuffer::texture1DImplementationDefault;
#endif
texture2DImplementation = &Framebuffer::texture2DImplementationDefault;
texture3DImplementation = &Framebuffer::texture3DImplementationDefault;
renderbufferStorageImplementation = &Renderbuffer::storageImplementationDefault;
}
/* Framebuffer binding on ES2 */
#ifdef MAGNUM_TARGET_GLES2
/* Optimistically set separate binding targets and check if one of the
extensions providing them is available */
readTarget = FramebufferTarget::Read;
drawTarget = FramebufferTarget::Draw;
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>()) {
extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string());
} else if(context.isExtensionSupported<Extensions::GL::APPLE::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::APPLE::framebuffer_multisample::string());
} else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_blit>()) {
extensions.push_back(Extensions::GL::NV::framebuffer_blit::string());
/* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these
enums. However, on my system only NV_framebuffer_multisample is
supported, but NV_framebuffer_blit isn't. I will hold my breath and
assume these enums are available. */
} else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::NV::framebuffer_multisample::string());
/* If no such extension is available, reset back to unified target */
} else readTarget = drawTarget = FramebufferTarget::ReadDraw;
#endif
/* Framebuffer reading implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::robustness>())
#else
if(context.isExtensionSupported<Extensions::GL::EXT::robustness>())
#endif
{
#ifndef MAGNUM_TARGET_GLES
extensions.push_back(Extensions::GL::ARB::robustness::string());
#else
extensions.push_back(Extensions::GL::EXT::robustness::string());
#endif
readImplementation = &AbstractFramebuffer::readImplementationRobustness;
} else readImplementation = &AbstractFramebuffer::readImplementationDefault;
/* Multisample renderbuffer storage implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
/* Extension added above */
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA;
} else
#endif
{
#ifdef MAGNUM_TARGET_GLES2
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::ANGLE::framebuffer_multisample::string());
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationANGLE;
} else if (context.isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::NV::framebuffer_multisample::string());
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationNV;
} else renderbufferStorageMultisampleImplementation = nullptr;
#else
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDefault;
#endif
}
}
}}

32
src/Magnum/Implementation/FramebufferState.h

@ -25,18 +25,34 @@
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/Magnum.h"
#include "Magnum/OpenGL.h"
#include "Magnum/Math/Range.h"
#include <string>
#include <vector>
#include "Magnum/Framebuffer.h"
namespace Magnum { namespace Implementation {
struct FramebufferState {
constexpr FramebufferState(): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0)
#ifndef MAGNUM_TARGET_GLES
, maxDualSourceDrawBuffers(0)
#endif
{}
explicit FramebufferState(Context& context, std::vector<std::string>& extensions);
GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget);
void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*);
void(AbstractFramebuffer::*drawBufferImplementation)(GLenum);
void(AbstractFramebuffer::*readBufferImplementation)(GLenum);
void(Framebuffer::*renderbufferImplementation)(Framebuffer::BufferAttachment, Renderbuffer&);
#ifndef MAGNUM_TARGET_GLES
void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, Texture1D&, GLint);
#endif
void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint);
void(Framebuffer::*texture3DImplementation)(Framebuffer::BufferAttachment, Texture3D&, GLint, GLint);
void(Renderbuffer::*renderbufferStorageImplementation)(RenderbufferFormat, const Vector2i&);
void(Renderbuffer::*renderbufferStorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&);
void(*readImplementation)(const Vector2i&, const Vector2i&, ColorFormat, ColorType, std::size_t, GLvoid*);
FramebufferTarget readTarget, drawTarget;
GLuint readBinding, drawBinding, renderbufferBinding;
GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize, maxSamples;

2
src/Magnum/Implementation/State.cpp

@ -53,7 +53,7 @@ State::State(Context& context) {
buffer = new BufferState;
debug = new DebugState(context, extensions);
framebuffer = new FramebufferState;
framebuffer = new FramebufferState(context, extensions);
mesh = new MeshState;
renderer = new RendererState;
shader = new ShaderState;

39
src/Magnum/Renderbuffer.cpp

@ -34,14 +34,6 @@
namespace Magnum {
Renderbuffer::StorageImplementation Renderbuffer::storageImplementation = &Renderbuffer::storageImplementationDefault;
Renderbuffer::StorageMultisampleImplementation Renderbuffer::storageMultisampleImplementation =
#ifndef MAGNUM_TARGET_GLES2
&Renderbuffer::storageMultisampleImplementationDefault;
#else
nullptr;
#endif
Int Renderbuffer::maxSize() {
GLint& value = Context::current()->state().framebuffer->maxRenderbufferSize;
@ -94,6 +86,14 @@ Renderbuffer& Renderbuffer::setLabel(const std::string& label) {
return *this;
}
void Renderbuffer::setStorage(const RenderbufferFormat internalFormat, const Vector2i& size) {
(this->*Context::current()->state().framebuffer->renderbufferStorageImplementation)(internalFormat, size);
}
void Renderbuffer::setStorageMultisample(const Int samples, const RenderbufferFormat internalFormat, const Vector2i& size) {
(this->*Context::current()->state().framebuffer->renderbufferStorageMultisampleImplementation)(samples, internalFormat, size);
}
void Renderbuffer::bind() {
GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding;
@ -103,29 +103,6 @@ void Renderbuffer::bind() {
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;
storageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA;
}
#elif !defined(MAGNUM_TARGET_GLES3)
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>()) {
Debug() << "Renderbuffer: using" << Extensions::GL::ANGLE::framebuffer_multisample::string() << "features";
storageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationANGLE;
} else if (context.isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>()) {
Debug() << "Renderbuffer: using" << Extensions::GL::NV::framebuffer_multisample::string() << "features";
storageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationNV;
}
#else
static_cast<void>(context);
#endif
}
void Renderbuffer::storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size) {
bind();
glRenderbufferStorage(GL_RENDERBUFFER, GLenum(internalFormat), size.x(), size.y());

24
src/Magnum/Renderbuffer.h

@ -34,6 +34,8 @@
namespace Magnum {
namespace Implementation { struct FramebufferState; }
/**
@brief %Renderbuffer
@ -54,7 +56,7 @@ See its documentation for more information.
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
friend class Context;
friend class Implementation::FramebufferState;
public:
/**
@ -146,9 +148,7 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
* @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);
}
void setStorage(RenderbufferFormat internalFormat, const Vector2i& size);
/**
* @brief Set multisample renderbuffer storage
@ -166,31 +166,23 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
* @todo How about @es_extension{APPLE,framebuffer_multisample}?
* @todo NaCl has @fn_gl_extension{RenderbufferStorageMultisample,EXT,multisampled_render_to_texture}
*/
void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size) {
(this->*storageMultisampleImplementation)(samples, internalFormat, size);
}
void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size);
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context& context);
typedef void(Renderbuffer::*StorageImplementation)(RenderbufferFormat, const Vector2i&);
void MAGNUM_LOCAL storageImplementationDefault(RenderbufferFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(RenderbufferFormat internalFormat, const Vector2i& size);
#endif
static StorageImplementation storageImplementation;
typedef void(Renderbuffer::*StorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&);
#ifndef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#endif
#else
void MAGNUM_LOCAL storageMultisampleImplementationANGLE(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
void MAGNUM_LOCAL storageMultisampleImplementationNV(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#endif
static StorageMultisampleImplementation storageMultisampleImplementation;
void MAGNUM_LOCAL bind();

Loading…
Cancel
Save