Browse Source

GL: implement ARB_framebuffer_no_attachments and related ES3.1 API.

pull/601/head
Vladimír Vondruš 3 years ago
parent
commit
35e65f19f9
  1. 3
      doc/changelog.dox
  2. 2
      doc/opengl-mapping.dox
  3. 2
      doc/opengl-support.dox
  4. 35
      src/Magnum/GL/Framebuffer.cpp
  5. 124
      src/Magnum/GL/Framebuffer.h
  6. 27
      src/Magnum/GL/Implementation/FramebufferState.cpp
  7. 3
      src/Magnum/GL/Implementation/FramebufferState.h
  8. 3
      src/Magnum/GL/MultisampleTexture.h
  9. 33
      src/Magnum/GL/Test/FramebufferGLTest.cpp

3
doc/changelog.dox

@ -94,6 +94,9 @@ See also:
have undefined behavior and may cause stability issues. This option is also have undefined behavior and may cause stability issues. This option is also
programatically settable via a new programatically settable via a new
@ref GL::Context::Configuration::Flag::GpuValidationNoError flag. @ref GL::Context::Configuration::Flag::GpuValidationNoError flag.
- Implemented the GL 4.3 @gl_extension{ARB,framebuffer_no_attachments}
extension and matching GLES 3.1 functionality, exposed as
@ref GL::Framebuffer::setDefaultSize() and related APIs
- Implemented @gl_extension{EXT,texture_norm16} and - Implemented @gl_extension{EXT,texture_norm16} and
@webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making @webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making
normalized 16-bit texture and renderbuffer formats available on all normalized 16-bit texture and renderbuffer formats available on all

2
doc/opengl-mapping.dox

@ -163,7 +163,7 @@ OpenGL function | Matching API
@fn_gl{Finish} | @ref GL::Renderer::finish() @fn_gl{Finish} | @ref GL::Renderer::finish()
@fn_gl{Flush} | @ref GL::Renderer::flush() @fn_gl{Flush} | @ref GL::Renderer::flush()
@fn_gl{FlushMappedBufferRange}, \n `glFlushMappedNamedBufferRange()` | @ref GL::Buffer::flushMappedRange() @fn_gl{FlushMappedBufferRange}, \n `glFlushMappedNamedBufferRange()` | @ref GL::Buffer::flushMappedRange()
@fn_gl2{FramebufferParameter,FramebufferParameteri}, \n `glNamedFramebufferParameter()` | | @fn_gl2{FramebufferParameter,FramebufferParameteri}, \n `glNamedFramebufferParameter()` | @ref GL::Framebuffer::setDefaultSize(), \n @ref GL::Framebuffer::setDefaultLayerCount(), \n @ref GL::Framebuffer::setDefaultSampleCount(), \n @ref GL::Framebuffer::setDefaultFixedSampleLocations()
@fn_gl{FramebufferRenderbuffer}, \n `glNamedFramebufferRenderbuffer()` | @ref GL::Framebuffer::attachRenderbuffer(), \n @ref GL::Framebuffer::detach() @fn_gl{FramebufferRenderbuffer}, \n `glNamedFramebufferRenderbuffer()` | @ref GL::Framebuffer::attachRenderbuffer(), \n @ref GL::Framebuffer::detach()
@fn_gl_extension{FramebufferSampleLocationsfv,ARB,sample_locations}, \n `glNamedFramebufferSampleLocationsfvARB` | | @fn_gl_extension{FramebufferSampleLocationsfv,ARB,sample_locations}, \n `glNamedFramebufferSampleLocationsfvARB` | |
@fn_gl{FramebufferTexture}, \n `glNamedFramebufferTexture()` | @ref GL::Framebuffer::attachLayeredTexture() @fn_gl{FramebufferTexture}, \n `glNamedFramebufferTexture()` | @ref GL::Framebuffer::attachLayeredTexture()

2
doc/opengl-support.dox

@ -203,7 +203,7 @@ GLSL 4.30 | done
@gl_extension{KHR,debug} | missing log retrieval, sync, pipeline and sampler label @gl_extension{KHR,debug} | missing log retrieval, sync, pipeline and sampler label
@gl_extension{ARB,explicit_uniform_location} | done @gl_extension{ARB,explicit_uniform_location} | done
@gl_extension{ARB,fragment_layer_viewport} | done (shading language only) @gl_extension{ARB,fragment_layer_viewport} | done (shading language only)
@gl_extension{ARB,framebuffer_no_attachments} | | @gl_extension{ARB,framebuffer_no_attachments} | done
@gl_extension{ARB,internalformat_query2} | only compressed texture block queries @gl_extension{ARB,internalformat_query2} | only compressed texture block queries
@gl_extension{ARB,invalidate_subdata} | done @gl_extension{ARB,invalidate_subdata} | done
@gl_extension{ARB,multi_draw_indirect} | | @gl_extension{ARB,multi_draw_indirect} | |

35
src/Magnum/GL/Framebuffer.cpp

@ -356,6 +356,29 @@ Framebuffer& Framebuffer::detach(const BufferAttachment attachment) {
return *this; return *this;
} }
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Framebuffer& Framebuffer::setDefaultSize(const Vector2i& size) {
Context::current().state().framebuffer.parameterImplementation(*this, GL_FRAMEBUFFER_DEFAULT_WIDTH, size.x());
Context::current().state().framebuffer.parameterImplementation(*this, GL_FRAMEBUFFER_DEFAULT_HEIGHT, size.y());
return *this;
}
Framebuffer& Framebuffer::setDefaultLayerCount(const Int count) {
Context::current().state().framebuffer.parameterImplementation(*this, GL_FRAMEBUFFER_DEFAULT_LAYERS, count);
return *this;
}
Framebuffer& Framebuffer::setDefaultSampleCount(const Int count) {
Context::current().state().framebuffer.parameterImplementation(*this, GL_FRAMEBUFFER_DEFAULT_SAMPLES, count);
return *this;
}
Framebuffer& Framebuffer::setDefaultFixedSampleLocations(bool fixed) {
Context::current().state().framebuffer.parameterImplementation(*this, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS, fixed ? GL_TRUE : GL_FALSE);
return *this;
}
#endif
void Framebuffer::renderbufferImplementationDefault(Framebuffer& self, const BufferAttachment attachment, const GLuint renderbufferId) { void Framebuffer::renderbufferImplementationDefault(Framebuffer& self, const BufferAttachment attachment, const GLuint renderbufferId) {
glFramebufferRenderbuffer(GLenum(self.bindInternal()), GLenum(attachment), GL_RENDERBUFFER, renderbufferId); glFramebufferRenderbuffer(GLenum(self.bindInternal()), GLenum(attachment), GL_RENDERBUFFER, renderbufferId);
} }
@ -419,6 +442,18 @@ void Framebuffer::textureLayerImplementationDSA(Framebuffer& self, const BufferA
} }
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void Framebuffer::parameterImplementationDefault(Framebuffer& self, const GLenum parameter, const GLint value) {
glFramebufferParameteri(GLenum(self.bindInternal()), parameter, value);
}
#endif
#ifndef MAGNUM_TARGET_GLES
void Framebuffer::parameterImplementationDSA(Framebuffer& self, const GLenum parameter, const GLint value) {
glNamedFramebufferParameteri(self._id, parameter, value);
}
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
Debug& operator<<(Debug& debug, const Framebuffer::Status value) { Debug& operator<<(Debug& debug, const Framebuffer::Status value) {
debug << "GL::Framebuffer::Status" << Debug::nospace; debug << "GL::Framebuffer::Status" << Debug::nospace;

124
src/Magnum/GL/Framebuffer.h

@ -904,6 +904,123 @@ class MAGNUM_GL_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractO
*/ */
Framebuffer& detach(BufferAttachment attachment); Framebuffer& detach(BufferAttachment attachment);
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/**
* @brief Set default framebuffer size
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Used in case the framebuffer has no attachments. Otherwise the size
* is inferred from renderbuffers or textures specified via
* @ref attachRenderbuffer(), @ref attachTexture(),
* @ref attachCubeMapTexture(), @ref attachTextureLayer() or
* @ref attachLayeredTexture() and this setting is ignored. Initial
* value is a zero vector.
* @see @ref setDefaultLayerCount(), @ref setDefaultSampleCount(),
* @ref setDefaultFixedSampleLocations(),
* @ref Renderbuffer::setStorage(), @ref Texture::setStorage(),
* @ref TextureArray::setStorage(),
* @ref CubeMapTexture::setStorage(),
* @ref CubeMapTextureArray::setStorage(),
* @ref MultisampleTexture::setStorage(),
* @ref RectangleTexture::setStorage(),
* @fn_gl2_keyword{NamedFramebufferParameteri,FramebufferParameteri},
* eventually @fn_gl{BindFramebuffer} and
* @fn_gl_keyword{FramebufferParameteri} with
* @def_gl_keyword{FRAMEBUFFER_DEFAULT_WIDTH} and
* @def_gl_keyword{FRAMEBUFFER_DEFAULT_HEIGHT}
* @requires_gl43 @gl_extension{ARB,framebuffer_no_attachments}
* @requires_gles31 Attachment-less framebuffers are not available in
* OpenGL ES 3.0 and older.
* @requires_gles Attachment-less framebuffers are not available in
* WebGL.
*/
Framebuffer& setDefaultSize(const Vector2i& size);
/**
* @brief Set default framebuffer layer count
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Used in case the framebuffer has no attachments. Otherwise the layer
* count is inferred from renderbuffers or textures specified via
* @ref attachRenderbuffer(), @ref attachTexture(),
* @ref attachCubeMapTexture(), @ref attachTextureLayer() or
* @ref attachLayeredTexture() and this setting is ignored. Initial
* value is @cpp 0 @ce.
* @see @ref setDefaultSize(), @ref setDefaultSampleCount(),
* @ref setDefaultFixedSampleLocations(),
* @ref Texture3D::setStorage(), @ref TextureArray::setStorage(),
* @ref CubeMapTexture::setStorage(),
* @ref CubeMapTextureArray::setStorage(),
* @ref MultisampleTexture2DArray::setStorage(),
* @fn_gl2_keyword{NamedFramebufferParameteri,FramebufferParameteri},
* eventually @fn_gl{BindFramebuffer} and
* @fn_gl_keyword{FramebufferParameteri} with
* @def_gl_keyword{FRAMEBUFFER_DEFAULT_LAYERS}
* @requires_gl43 @gl_extension{ARB,framebuffer_no_attachments}
* @requires_gles31 Attachment-less framebuffers are not available in
* OpenGL ES 3.0 and older.
* @requires_gles Attachment-less framebuffers are not available in
* WebGL.
*/
Framebuffer& setDefaultLayerCount(Int count);
/**
* @brief Set default framebuffer sample count
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Used in case the framebuffer has no attachments. Otherwise the
* sample count is inferred from renderbuffers or textures specified
* via @ref attachRenderbuffer(), @ref attachTexture(),
* @ref attachCubeMapTexture(), @ref attachTextureLayer() or
* @ref attachLayeredTexture() and this setting is ignored. Initial
* value is @cpp 0 @ce.
* @see @ref setDefaultSize(), @ref setDefaultLayerCount(),
* @ref setDefaultFixedSampleLocations(),
* @ref Renderbuffer::setStorageMultisample(),
* @ref MultisampleTexture::setStorage(),
* @fn_gl2_keyword{NamedFramebufferParameteri,FramebufferParameteri},
* eventually @fn_gl{BindFramebuffer} and
* @fn_gl_keyword{FramebufferParameteri} with
* @def_gl_keyword{FRAMEBUFFER_DEFAULT_SAMPLES}
* @requires_gl43 @gl_extension{ARB,framebuffer_no_attachments}
* @requires_gles31 Attachment-less framebuffers are not available in
* OpenGL ES 3.0 and older.
* @requires_gles Attachment-less framebuffers are not available in
* WebGL.
*/
Framebuffer& setDefaultSampleCount(Int count);
/**
* @brief Set default framebuffer fixed sample locations
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Used in case the framebuffer has no attachments. Otherwise the
* fixed sample locations setting is inferred from renderbuffers or
* textures specified via @ref attachRenderbuffer(),
* @ref attachTexture(), @ref attachCubeMapTexture(),
* @ref attachTextureLayer() or @ref attachLayeredTexture() and this
* setting is ignored. Initial value is @cpp false @ce.
* @see @ref setDefaultSize(), @ref setDefaultLayerCount(),
* @ref setDefaultSampleCount(),
* @ref MultisampleTexture::setStorage(),
* @ref MultisampleTextureSampleLocations,
* @fn_gl2_keyword{NamedFramebufferParameteri,FramebufferParameteri},
* eventually @fn_gl{BindFramebuffer} and
* @fn_gl_keyword{FramebufferParameteri} with
* @def_gl_keyword{FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS}
* @requires_gl43 @gl_extension{ARB,framebuffer_no_attachments}
* @requires_gles31 Attachment-less framebuffers are not available in
* OpenGL ES 3.0 and older.
* @requires_gles Attachment-less framebuffers are not available in
* WebGL.
*/
Framebuffer& setDefaultFixedSampleLocations(bool fixed);
#endif
/* Overloads to remove WTF-factor from method chaining order */ /* Overloads to remove WTF-factor from method chaining order */
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
Framebuffer& setViewport(const Range2Di& rectangle) { Framebuffer& setViewport(const Range2Di& rectangle) {
@ -969,6 +1086,13 @@ class MAGNUM_GL_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractO
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
static void MAGNUM_GL_LOCAL textureLayerImplementationDSA(Framebuffer& self, BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); static void MAGNUM_GL_LOCAL textureLayerImplementationDSA(Framebuffer& self, BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
static void MAGNUM_GL_LOCAL parameterImplementationDefault(Framebuffer& self, GLenum parameter, GLint value);
#endif
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_GL_LOCAL parameterImplementationDSA(Framebuffer& self, GLenum parameter, GLint value);
#endif
}; };
/** @debugoperatorclassenum{Framebuffer,Framebuffer::Status} */ /** @debugoperatorclassenum{Framebuffer,Framebuffer::Status} */

27
src/Magnum/GL/Implementation/FramebufferState.cpp

@ -417,6 +417,33 @@ FramebufferState::FramebufferState(Context& context, Containers::StaticArrayView
invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault;
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/* Attachment-less framebuffer implementation on desktop GL */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::ARB::framebuffer_no_attachments>()) {
extensions[Extensions::ARB::framebuffer_no_attachments::Index] =
Extensions::ARB::framebuffer_no_attachments::string();
if(context.isExtensionSupported<Extensions::ARB::direct_state_access>()) {
extensions[Extensions::ARB::direct_state_access::Index] =
Extensions::ARB::direct_state_access::string();
parameterImplementation = &Framebuffer::parameterImplementationDSA;
} else {
parameterImplementation = &Framebuffer::parameterImplementationDefault;
}
}
/* Attachment-less framebuffer implementation on ES3 */
#else
if(context.isVersionSupported(Version::GLES310))
parameterImplementation = &Framebuffer::parameterImplementationDefault;
/* Not available otherwise */
#endif
else {
parameterImplementation = nullptr;
}
#endif
/* Blit implementation on desktop GL */ /* Blit implementation on desktop GL */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::ARB::direct_state_access>()) { if(context.isExtensionSupported<Extensions::ARB::direct_state_access>()) {

3
src/Magnum/GL/Implementation/FramebufferState.h

@ -90,6 +90,9 @@ struct FramebufferState {
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void(*textureLayerImplementation)(Framebuffer&, Framebuffer::BufferAttachment, GLuint, GLint, GLint); void(*textureLayerImplementation)(Framebuffer&, Framebuffer::BufferAttachment, GLuint, GLint, GLint);
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void(*parameterImplementation)(Framebuffer&, GLenum, GLint);
#endif
void(*createRenderbufferImplementation)(Renderbuffer&); void(*createRenderbufferImplementation)(Renderbuffer&);
void(*renderbufferStorageImplementation)(Renderbuffer&, RenderbufferFormat, const Vector2i&); void(*renderbufferStorageImplementation)(Renderbuffer&, RenderbufferFormat, const Vector2i&);

3
src/Magnum/GL/MultisampleTexture.h

@ -57,7 +57,8 @@ namespace Implementation {
/** /**
@brief Multisample texture sample locations @brief Multisample texture sample locations
@see @ref MultisampleTexture::setStorage() @see @ref MultisampleTexture::setStorage(),
@ref Framebuffer::setDefaultFixedSampleLocations()
@m_enum_values_as_keywords @m_enum_values_as_keywords
*/ */
enum class MultisampleTextureSampleLocations: GLboolean { enum class MultisampleTextureSampleLocations: GLboolean {

33
src/Magnum/GL/Test/FramebufferGLTest.cpp

@ -114,6 +114,10 @@ struct FramebufferGLTest: OpenGLTester {
void multipleColorOutputs(); void multipleColorOutputs();
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void setDefaultSize();
#endif
void clear(); void clear();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void clearColorI(); void clearColorI();
@ -260,6 +264,10 @@ FramebufferGLTest::FramebufferGLTest() {
&FramebufferGLTest::multipleColorOutputs, &FramebufferGLTest::multipleColorOutputs,
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
&FramebufferGLTest::setDefaultSize,
#endif
&FramebufferGLTest::clear, &FramebufferGLTest::clear,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&FramebufferGLTest::clearColorI, &FramebufferGLTest::clearColorI,
@ -1041,6 +1049,31 @@ void FramebufferGLTest::detach() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void FramebufferGLTest::setDefaultSize() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::framebuffer_no_attachments>())
CORRADE_SKIP(Extensions::ARB::framebuffer_no_attachments::string() << "is not supported.");
#else
if(!Context::current().isVersionSupported(Version::GLES310))
CORRADE_SKIP(Version::GLES310 << "is not supported.");
#endif
Framebuffer framebuffer{{{}, Vector2i{128}}};
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::IncompleteMissingAttachment);
framebuffer.setDefaultSize({256, 256})
.setDefaultLayerCount(3)
.setDefaultSampleCount(1)
.setDefaultFixedSampleLocations(false);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(framebuffer.checkStatus(FramebufferTarget::Draw), Framebuffer::Status::Complete);
}
#endif
void FramebufferGLTest::multipleColorOutputs() { void FramebufferGLTest::multipleColorOutputs() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::framebuffer_object>()) if(!Context::current().isExtensionSupported<Extensions::ARB::framebuffer_object>())

Loading…
Cancel
Save