Browse Source

Use proper ARB_framebuffer_object extension.

Separated EXT_framebuffer_object, EXT_framebuffer_blit,
EXT_framebuffer_multisample and EXT_packed_depth_stencil don't have the
same functionality as ARB_framebuffer_object (e.g. missing
GL_FRAMEBUFFER_UNDEFINED in glCheckFramebufferStatus()) and separated
read/draw binding is only in EXT_framebuffer_blit, which complicates the
internals.

Checked with Mesa 8/9 and OpenGL 2.1, current one has
ARB_framebuffer_object and also all these four, Mesa 7.7 didn't have
EXT_framebuffer_multisample, but that's a long time ago, so not
supporting these separate extensions shouldn't be an issue.

The problem with unavailable separate binding points remains on OpenGL
ES 2.0, there are three different extensions bringing that
functionality, thus the code managing the available binding points
remains there.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
b5a6036d48
  1. 66
      src/AbstractFramebuffer.cpp
  2. 71
      src/AbstractFramebuffer.h
  3. 2
      src/AbstractTexture.h
  4. 9
      src/Context.cpp
  5. 7
      src/Extensions.h
  6. 2
      src/Framebuffer.h
  7. 4
      src/ImageFormat.h
  8. 3
      src/Renderbuffer.h
  9. 2
      src/RenderbufferFormat.h
  10. 2
      src/Renderer.h
  11. 2
      src/TextureFormat.h

66
src/AbstractFramebuffer.cpp

@ -40,8 +40,10 @@ AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersI
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
AbstractFramebuffer::~AbstractFramebuffer() {}
@ -81,10 +83,15 @@ FramebufferTarget AbstractFramebuffer::bindInternal() {
/* Or bind it, if not already */
state->readBinding = _id;
if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
#ifndef MAGNUM_TARGET_GLES2
glBindFramebuffer(GLenum(FramebufferTarget::Read), _id);
return FramebufferTarget::Read;
#else
if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
glBindFramebuffer(GLenum(readTarget), _id);
return readTarget;
#endif
}
void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Rectanglei& sourceRectangle, const Rectanglei& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter) {
@ -126,12 +133,20 @@ void AbstractFramebuffer::setViewportInternal() {
}
void AbstractFramebuffer::clear(FramebufferClearMask mask) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else
bindInternal(drawTarget);
#endif
glClear(static_cast<GLbitfield>(mask));
}
void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Image2D* image) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Read);
#else
bindInternal(readTarget);
#endif
const std::size_t dataSize = image->pixelSize()*size.product();
char* const data = new char[dataSize];
readImplementation(offset, size, image->format(), image->type(), dataSize, data);
@ -140,7 +155,11 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Ima
#ifndef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, BufferImage2D* image, Buffer::Usage usage) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Read);
#else
bindInternal(readTarget);
#endif
/* If the buffer doesn't have sufficient size, resize it */
/** @todo Explicitly reset also when buffer usage changes */
if(image->size() != size)
@ -177,13 +196,6 @@ void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attach
void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context) {
#ifndef MAGNUM_TARGET_GLES
if(context->isExtensionSupported<Extensions::GL::EXT::framebuffer_blit>()) {
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::framebuffer_blit::string() << "features";
readTarget = FramebufferTarget::Read;
drawTarget = FramebufferTarget::Draw;
}
if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
@ -193,6 +205,32 @@ void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context)
}
#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_GLES3
#ifndef MAGNUM_TARGET_GLES
if(context->isExtensionSupported<Extensions::GL::ARB::robustness>())
@ -219,7 +257,11 @@ void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context)
void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers) {
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else
bindInternal(drawTarget);
#endif
glDrawBuffers(count, buffers);
#else
static_cast<void>(count);
@ -236,7 +278,11 @@ void AbstractFramebuffer::drawBuffersImplementationDSA(GLsizei count, const GLen
void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) {
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else
bindInternal(drawTarget);
#endif
#ifndef MAGNUM_TARGET_GLES3
glDrawBuffer(buffer);
#else
@ -256,7 +302,11 @@ void AbstractFramebuffer::drawBufferImplementationDSA(GLenum buffer) {
void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
/** @todo Get some extension wrangler instead to avoid undeclared glReadBuffer() on ES2 */
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Read);
#else
bindInternal(readTarget);
#endif
glReadBuffer(buffer);
#else
static_cast<void>(buffer);

71
src/AbstractFramebuffer.h

@ -36,10 +36,10 @@
namespace Magnum {
/**
* @brief Mask for framebuffer clearing
*
* @see AbstractFramebuffer, FramebufferClearMask
*/
@brief Mask for framebuffer clearing
@see AbstractFramebuffer, FramebufferClearMask
*/
enum class FramebufferClear: GLbitfield {
Color = GL_COLOR_BUFFER_BIT, /**< Color */
Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value */
@ -47,21 +47,21 @@ enum class FramebufferClear: GLbitfield {
};
/**
* @brief Mask for clearing
*
* @see AbstractFramebuffer::clear()
*/
@brief Mask for clearing
@see AbstractFramebuffer::clear()
*/
typedef Containers::EnumSet<FramebufferClear, GLbitfield,
GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT> FramebufferClearMask;
/**
* @brief Mask for framebuffer blitting
*
* @see AbstractFramebuffer, FramebufferBlitMask
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
*/
@brief Mask for framebuffer blitting
@see AbstractFramebuffer, FramebufferBlitMask
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
*/
enum class FramebufferBlit: GLbitfield {
ColorBuffer = GL_COLOR_BUFFER_BIT, /**< Color buffer */
DepthBuffer = GL_DEPTH_BUFFER_BIT, /**< Depth buffer */
@ -69,36 +69,38 @@ enum class FramebufferBlit: GLbitfield {
};
/**
* @brief Mask for framebuffer blitting
*
* @see AbstractFramebuffer::blit()
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
*/
@brief Mask for framebuffer blitting
@see AbstractFramebuffer::blit()
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
*/
typedef Containers::EnumSet<FramebufferBlit, GLbitfield,
GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT> FramebufferBlitMask;
/**
* @brief %Framebuffer blit filtering
*
* @see AbstractFramebuffer::blit()
*/
@brief %Framebuffer blit filtering
@see AbstractFramebuffer::blit()
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
*/
enum class FramebufferBlitFilter: GLenum {
Nearest = GL_NEAREST, /**< Nearest neighbor filtering */
Linear = GL_LINEAR /**< Linear interpolation filtering */
};
/**
* @brief Target for binding framebuffer
*
* @see DefaultFramebuffer::bind(), Framebuffer::bind()
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
*/
@brief Target for binding framebuffer
@see DefaultFramebuffer::bind(), Framebuffer::bind()
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
enum class FramebufferTarget: GLenum {
/**
* For reading only.
* @requires_gl30 %Extension @extension{EXT,framebuffer_blit}
* @requires_gles30 %Extension @es_extension{APPLE,framebuffer_multisample},
* @es_extension{ANGLE,framebuffer_blit} or @es_extension{NV,framebuffer_blit}
*/
@ -110,7 +112,6 @@ enum class FramebufferTarget: GLenum {
/**
* For drawing only.
* @requires_gl30 %Extension @extension{EXT,framebuffer_blit}
* @requires_gles30 %Extension @es_extension{APPLE,framebuffer_multisample},
* @es_extension{ANGLE,framebuffer_blit} or @es_extension{NV,framebuffer_blit}
*/
@ -163,7 +164,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* Framebuffer::mapForDraw() for specifying particular buffers for
* blitting operation.
* @see @fn_gl{BlitFramebuffer}
* @requires_gl30 %Extension @extension{EXT,framebuffer_blit}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
*/
@ -182,7 +182,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* @ref FramebufferBlitFilter "FramebufferBlitFilter::Nearest"
* filtering is used by default.
* @see @fn_gl{BlitFramebuffer}
* @requires_gl30 %Extension @extension{EXT,framebuffer_blit}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
*/
@ -272,8 +271,10 @@ 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 void(AbstractFramebuffer::*DrawBuffersImplementation)(GLsizei, const GLenum*);
static MAGNUM_LOCAL DrawBuffersImplementation drawBuffersImplementation;

2
src/AbstractTexture.h

@ -253,7 +253,7 @@ class MAGNUM_EXPORT AbstractTexture {
* @see setMinificationFilter(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{GenerateMipmap} or
* @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
AbstractTexture* generateMipmap();

9
src/Context.cpp

@ -97,14 +97,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,ARB,texture_float), // done
_extension(GL,ARB,depth_buffer_float), // done
_extension(GL,ARB,texture_rg), // done
/**
* @todo Remove as it doesn't have the same functionality present in
* GL 3.0 and replace with ARB_framebuffer_object?
*/
_extension(GL,EXT,framebuffer_object),
_extension(GL,EXT,packed_depth_stencil), // done
_extension(GL,EXT,framebuffer_blit), // done
_extension(GL,EXT,framebuffer_multisample),
_extension(GL,ARB,framebuffer_object),
_extension(GL,EXT,gpu_shader4),
_extension(GL,EXT,packed_float), // done
_extension(GL,EXT,texture_array),

7
src/Extensions.h

@ -76,6 +76,7 @@ namespace GL {
_extension(GL,ARB,texture_float, GL210, GL300) // #41
_extension(GL,ARB,depth_buffer_float, GL210, GL300) // #43
_extension(GL,ARB,draw_instanced, GL210, GL310) // #44
_extension(GL,ARB,framebuffer_object, GL210, GL300) // #45
_extension(GL,ARB,geometry_shader4, GL210, GL320) // #47
_extension(GL,ARB,instanced_arrays, GL210, GL330) // #49
_extension(GL,ARB,map_buffer_range, GL210, GL300) // #50
@ -154,10 +155,8 @@ namespace GL {
_extension(GL,ARB,texture_storage_multisample, GL210, GL430) // #141
} namespace EXT {
_extension(GL,EXT,texture_filter_anisotropic, GL210, None) // #187
_extension(GL,EXT,framebuffer_object, GL210, GL300) // #310
_extension(GL,EXT,packed_depth_stencil, GL210, GL300) // #312
_extension(GL,EXT,framebuffer_blit, GL210, GL300) // #316
_extension(GL,EXT,framebuffer_multisample, GL210, GL300) // #317
/* EXT_framebuffer_object, EXT_packed_depth_stencil, EXT_framebuffer_blit,
EXT_framebuffer_multisample replaced with ARB_framebuffer_object */
_extension(GL,EXT,gpu_shader4, GL210, GL300) // #326
_extension(GL,EXT,packed_float, GL210, GL300) // #328
_extension(GL,EXT,texture_array, GL210, GL300) // #329

2
src/Framebuffer.h

@ -94,7 +94,7 @@ 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{ARB,framebuffer_object}
*/
class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
friend class Context;

4
src/ImageFormat.h

@ -236,7 +236,7 @@ enum class ImageFormat: GLenum {
/**
* Depth and stencil.
* @requires_gl30 %Extension @extension{EXT,packed_depth_stencil}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension2{NV,read_depth_stencil,GL_NV_read_depth_stencil}.
@ -446,7 +446,7 @@ enum class ImageType: GLenum {
/**
* Unsigned int, depth component 24bit, stencil index 8bit.
* @requires_gl30 %Extension @extension{EXT,packed_depth_stencil}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
*/
#ifndef MAGNUM_TARGET_GLES2

3
src/Renderbuffer.h

@ -49,7 +49,7 @@ 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{ARB,framebuffer_object}
*/
class MAGNUM_EXPORT Renderbuffer {
friend class Context;
@ -105,7 +105,6 @@ class MAGNUM_EXPORT Renderbuffer {
* operation.
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{EXT,framebuffer_multisample}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample}
* @todo How about @es_extension{APPLE,framebuffer_multisample}?

2
src/RenderbufferFormat.h

@ -36,6 +36,7 @@ namespace Magnum {
@brief Internal renderbuffer format
@see Renderbuffer
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@todo RGB, RGB8 ES only (ES3 + @es_extension{OES,rgb8_rgba8})
*/
enum class RenderbufferFormat: GLenum {
@ -481,7 +482,6 @@ enum class RenderbufferFormat: GLenum {
/**
* 24bit depth and 8bit stencil component.
* @requires_gl30 %Extension @extension{EXT,packed_depth_stencil}
* @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil}
*/
#ifdef MAGNUM_TARGET_GLES2

2
src/Renderer.h

@ -892,7 +892,7 @@ class MAGNUM_EXPORT Renderer {
/**
* The framebuffer object is not complete.
* @see AbstractFramebuffer::checkStatus()
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
InvalidFramebufferOperation = GL_INVALID_FRAMEBUFFER_OPERATION,

2
src/TextureFormat.h

@ -823,7 +823,7 @@ enum class TextureFormat: GLenum {
/**
* 24bit depth and 8bit stencil component.
* @requires_gl30 %Extension @extension{EXT,packed_depth_stencil}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} and
* (@es_extension{OES,required_internalformat} or
* (@es_extension{EXT,texture_storage} and @es_extension{ANGLE,depth_texture}))

Loading…
Cancel
Save