Browse Source

First-class WebGL support, part 5: reduced framebuffer functionality.

pull/107/head
Vladimír Vondruš 11 years ago
parent
commit
c77848ffac
  1. 27
      src/Magnum/AbstractFramebuffer.cpp
  2. 51
      src/Magnum/AbstractFramebuffer.h
  3. 4
      src/Magnum/DefaultFramebuffer.cpp
  4. 122
      src/Magnum/DefaultFramebuffer.h
  5. 24
      src/Magnum/Framebuffer.cpp
  6. 156
      src/Magnum/Framebuffer.h
  7. 46
      src/Magnum/Implementation/FramebufferState.cpp
  8. 13
      src/Magnum/Implementation/FramebufferState.h
  9. 10
      src/Magnum/Renderbuffer.cpp
  10. 32
      src/Magnum/Renderbuffer.h

27
src/Magnum/AbstractFramebuffer.cpp

@ -49,9 +49,14 @@ Vector2i AbstractFramebuffer::maxViewportSize() {
Int AbstractFramebuffer::maxDrawBuffers() { Int AbstractFramebuffer::maxDrawBuffers() {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_WEBGL
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::draw_buffers>() && if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::draw_buffers>() &&
!Context::current()->isExtensionSupported<Extensions::GL::NV::draw_buffers>()) !Context::current()->isExtensionSupported<Extensions::GL::NV::draw_buffers>())
return 0; return 0;
#else
if(!Context::current()->isExtensionSupported<Extensions::GL::WEBGL::draw_buffers>())
return 0;
#endif
#endif #endif
GLint& value = Context::current()->state().framebuffer->maxDrawBuffers; GLint& value = Context::current()->state().framebuffer->maxDrawBuffers;
@ -187,9 +192,11 @@ FramebufferTarget AbstractFramebuffer::bindImplementationDefault() {
return FramebufferTarget::Read; return FramebufferTarget::Read;
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) {
Context::current()->state().framebuffer->blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter); Context::current()->state().framebuffer->blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter);
} }
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::blitImplementationDefault(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { void AbstractFramebuffer::blitImplementationDefault(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) {
@ -204,9 +211,9 @@ void AbstractFramebuffer::blitImplementationDSA(AbstractFramebuffer& source, Abs
} }
#endif #endif
#else #elif !defined(MAGNUM_TARGET_WEBGL)
void AbstractFramebuffer::blitImplementationANGLE(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { void AbstractFramebuffer::blitImplementationANGLE(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
source.bindInternal(FramebufferTarget::Read); source.bindInternal(FramebufferTarget::Read);
destination.bindInternal(FramebufferTarget::Draw); destination.bindInternal(FramebufferTarget::Draw);
glBlitFramebufferANGLE(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter)); glBlitFramebufferANGLE(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter));
@ -222,7 +229,7 @@ void AbstractFramebuffer::blitImplementationANGLE(AbstractFramebuffer& source, A
} }
void AbstractFramebuffer::blitImplementationNV(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { void AbstractFramebuffer::blitImplementationNV(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
source.bindInternal(FramebufferTarget::Read); source.bindInternal(FramebufferTarget::Read);
destination.bindInternal(FramebufferTarget::Draw); destination.bindInternal(FramebufferTarget::Draw);
glBlitFramebufferNV(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter)); glBlitFramebufferNV(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), GLbitfield(mask), GLenum(filter));
@ -380,7 +387,7 @@ void AbstractFramebuffer::drawBuffersImplementationDSAEXT(GLsizei count, const G
void AbstractFramebuffer::drawBuffersImplementationEXT(GLsizei count, const GLenum* buffers) { void AbstractFramebuffer::drawBuffersImplementationEXT(GLsizei count, const GLenum* buffers) {
bindInternal(FramebufferTarget::Draw); bindInternal(FramebufferTarget::Draw);
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glDrawBuffersEXT(count, buffers); glDrawBuffersEXT(count, buffers);
#else #else
static_cast<void>(count); static_cast<void>(count);
@ -389,10 +396,11 @@ void AbstractFramebuffer::drawBuffersImplementationEXT(GLsizei count, const GLen
#endif #endif
} }
#ifndef MAGNUM_TARGET_WEBGL
void AbstractFramebuffer::drawBuffersImplementationNV(GLsizei count, const GLenum* buffers) { void AbstractFramebuffer::drawBuffersImplementationNV(GLsizei count, const GLenum* buffers) {
bindInternal(FramebufferTarget::Draw); bindInternal(FramebufferTarget::Draw);
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glDrawBuffersNV(count, buffers); glDrawBuffersNV(count, buffers);
#else #else
static_cast<void>(count); static_cast<void>(count);
@ -401,6 +409,7 @@ void AbstractFramebuffer::drawBuffersImplementationNV(GLsizei count, const GLenu
#endif #endif
} }
#endif #endif
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) { void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) {
@ -419,18 +428,20 @@ void AbstractFramebuffer::drawBufferImplementationDSAEXT(GLenum buffer) {
} }
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) { void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
bindInternal(FramebufferTarget::Read); bindInternal(FramebufferTarget::Read);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glReadBuffer(buffer); glReadBuffer(buffer);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_NACL)
glReadBufferNV(buffer); glReadBufferNV(buffer);
#else #else
static_cast<void>(buffer); static_cast<void>(buffer);
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
} }
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::readBufferImplementationDSA(const GLenum buffer) { void AbstractFramebuffer::readBufferImplementationDSA(const GLenum buffer) {
@ -447,10 +458,11 @@ void AbstractFramebuffer::readImplementationDefault(const Range2Di& rectangle, c
glReadPixels(rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), GLenum(format), GLenum(type), data); glReadPixels(rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), GLenum(format), GLenum(type), data);
} }
#ifndef MAGNUM_TARGET_WEBGL
void AbstractFramebuffer::readImplementationRobustness(const Range2Di& rectangle, const ColorFormat format, const ColorType type, const std::size_t dataSize, GLvoid* const data) { void AbstractFramebuffer::readImplementationRobustness(const Range2Di& rectangle, const ColorFormat format, const ColorType type, const std::size_t dataSize, GLvoid* const data) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glReadnPixelsARB(rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), GLenum(format), GLenum(type), dataSize, data); glReadnPixelsARB(rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), GLenum(format), GLenum(type), dataSize, data);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_NACL)
glReadnPixelsEXT(rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), GLenum(format), GLenum(type), dataSize, data); glReadnPixelsEXT(rectangle.min().x(), rectangle.min().y(), rectangle.sizeX(), rectangle.sizeY(), GLenum(format), GLenum(type), dataSize, data);
#else #else
static_cast<void>(rectangle); static_cast<void>(rectangle);
@ -461,5 +473,6 @@ void AbstractFramebuffer::readImplementationRobustness(const Range2Di& rectangle
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
} }
#endif
} }

51
src/Magnum/AbstractFramebuffer.h

@ -61,13 +61,15 @@ typedef Containers::EnumSet<FramebufferClear,
typedef Containers::EnumSet<FramebufferClear> FramebufferClearMask; typedef Containers::EnumSet<FramebufferClear> FramebufferClearMask;
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
@brief Mask for framebuffer blitting @brief Mask for framebuffer blitting
@see @ref AbstractFramebuffer, @ref FramebufferBlitMask @see @ref AbstractFramebuffer, @ref FramebufferBlitMask
@requires_gl30 Extension @extension{ARB,framebuffer_object} @requires_gl30 Extension @extension{ARB,framebuffer_object}
@requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit} in OpenGL ES 2.0 @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0.
@requires_webgl20 Framebuffer blit is not available in WebGL 1.0.
*/ */
enum class FramebufferBlit: GLbitfield { enum class FramebufferBlit: GLbitfield {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
@ -98,7 +100,8 @@ enum class FramebufferBlit: GLbitfield {
@see @ref AbstractFramebuffer::blit() @see @ref AbstractFramebuffer::blit()
@requires_gl30 Extension @extension{ARB,framebuffer_object} @requires_gl30 Extension @extension{ARB,framebuffer_object}
@requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit} in OpenGL ES 2.0 @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0.
@requires_webgl20 Framebuffer blit is not available in WebGL 1.0.
*/ */
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
typedef Containers::EnumSet<FramebufferBlit, typedef Containers::EnumSet<FramebufferBlit,
@ -113,12 +116,14 @@ typedef Containers::EnumSet<FramebufferBlit> FramebufferBlitMask;
@see @ref AbstractFramebuffer::blit() @see @ref AbstractFramebuffer::blit()
@requires_gl30 Extension @extension{ARB,framebuffer_object} @requires_gl30 Extension @extension{ARB,framebuffer_object}
@requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit} in OpenGL ES 2.0 @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0.
@requires_webgl20 Framebuffer blit is not available in WebGL 1.0.
*/ */
enum class FramebufferBlitFilter: GLenum { enum class FramebufferBlitFilter: GLenum {
Nearest = GL_NEAREST, /**< Nearest neighbor filtering */ Nearest = GL_NEAREST, /**< Nearest neighbor filtering */
Linear = GL_LINEAR /**< Linear interpolation filtering */ Linear = GL_LINEAR /**< Linear interpolation filtering */
}; };
#endif
/** /**
@brief Framebuffer target @brief Framebuffer target
@ -130,15 +135,19 @@ enum class FramebufferTarget: GLenum {
/** Frambebuffer reading target */ /** Frambebuffer reading target */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Read = GL_READ_FRAMEBUFFER, Read = GL_READ_FRAMEBUFFER,
#else #elif !defined(MAGNUM_TARGET_WEBGL)
Read = GL_READ_FRAMEBUFFER_APPLE, Read = GL_READ_FRAMEBUFFER_APPLE,
#else
Read,
#endif #endif
/** Framebuffer drawing target */ /** Framebuffer drawing target */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Draw = GL_DRAW_FRAMEBUFFER, Draw = GL_DRAW_FRAMEBUFFER,
#else #elif !defined(MAGNUM_TARGET_WEBGL)
Draw = GL_DRAW_FRAMEBUFFER_APPLE, Draw = GL_DRAW_FRAMEBUFFER_APPLE,
#else
Draw,
#endif #endif
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
@ -149,8 +158,10 @@ enum class FramebufferTarget: GLenum {
ReadDraw CORRADE_DEPRECATED_ENUM("use FramebufferTarget::Draw instead") = ReadDraw CORRADE_DEPRECATED_ENUM("use FramebufferTarget::Draw instead") =
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER
#else #elif !defined(MAGNUM_TARGET_WEBGL)
GL_DRAW_FRAMEBUFFER_APPLE GL_DRAW_FRAMEBUFFER_APPLE
#else
1
#endif #endif
#endif #endif
}; };
@ -197,8 +208,10 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* @brief Max supported draw buffer count * @brief Max supported draw buffer count
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. In OpenGL ES 2.0, if neither @es_extension{EXT,draw_buffers} * OpenGL calls. If neither @es_extension{EXT,draw_buffers} nor
* nor @es_extension{NV,draw_buffers} is available, returns `0`. * @es_extension{NV,draw_buffers} is available in OpenGL ES 2.0 and
* @webgl_extension{WEBGL,draw_buffers} is not available in WebGL 1.0,
* returns `0`.
* @see @ref DefaultFramebuffer::mapForDraw(), @ref Framebuffer::mapForDraw(), * @see @ref DefaultFramebuffer::mapForDraw(), @ref Framebuffer::mapForDraw(),
* @fn_gl{Get} with @def_gl{MAX_DRAW_BUFFERS} * @fn_gl{Get} with @def_gl{MAX_DRAW_BUFFERS}
*/ */
@ -214,11 +227,12 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* @see @ref DefaultFramebuffer::mapForDraw(), @ref Framebuffer::mapForDraw(), * @see @ref DefaultFramebuffer::mapForDraw(), @ref Framebuffer::mapForDraw(),
* @fn_gl{Get} with @def_gl{MAX_DUAL_SOURCE_DRAW_BUFFERS} * @fn_gl{Get} with @def_gl{MAX_DUAL_SOURCE_DRAW_BUFFERS}
* @requires_gl Multiple blending inputs are not available in * @requires_gl Multiple blending inputs are not available in
* OpenGL ES. * OpenGL ES or WebGL.
*/ */
static Int maxDualSourceDrawBuffers(); static Int maxDualSourceDrawBuffers();
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @brief Copy block of pixels * @brief Copy block of pixels
* @param source Source framebuffer * @param source Source framebuffer
@ -238,7 +252,8 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* @see @fn_gl2{BlitNamedFramebuffer,BlitFramebuffer}, eventually * @see @fn_gl2{BlitNamedFramebuffer,BlitFramebuffer}, eventually
* @fn_gl{BlitFramebuffer} * @fn_gl{BlitFramebuffer}
* @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or * @requires_gles30 Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0 * @es_extension{NV,framebuffer_blit} in OpenGL ES 2.0.
* @requires_webgl20 Framebuffer blit is not available in WebGL 1.0.
* @todo NaCl exports `BlitFramebufferEXT` (although no such extension * @todo NaCl exports `BlitFramebufferEXT` (although no such extension
* exists for ES) * exists for ES)
*/ */
@ -255,6 +270,7 @@ class MAGNUM_EXPORT AbstractFramebuffer {
static void blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& rectangle, FramebufferBlitMask mask) { static void blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& rectangle, FramebufferBlitMask mask) {
blit(source, destination, rectangle, rectangle, mask, FramebufferBlitFilter::Nearest); blit(source, destination, rectangle, rectangle, mask, FramebufferBlitFilter::Nearest);
} }
#endif
/** /**
* @brief Bind framebuffer for drawing * @brief Bind framebuffer for drawing
@ -352,7 +368,10 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* *
* See @ref read(const Vector2i&, const Vector2i&, Image2D&) for more * See @ref read(const Vector2i&, const Vector2i&, Image2D&) for more
* information. * information.
* @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES
* 2.0.
* @requires_webgl20 Pixel buffer objects are not available in WebGL
* 1.0.
* @todo Make it more flexible (usable with * @todo Make it more flexible (usable with
* @extension{ARB,buffer_storage}, avoiding relocations...) * @extension{ARB,buffer_storage}, avoiding relocations...)
*/ */
@ -403,7 +422,7 @@ class MAGNUM_EXPORT AbstractFramebuffer {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL blitImplementationDSA(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); static void MAGNUM_LOCAL blitImplementationDSA(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter);
#endif #endif
#else #elif !defined(MAGNUM_TARGET_WEBGL)
static void MAGNUM_LOCAL blitImplementationANGLE(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); static void MAGNUM_LOCAL blitImplementationANGLE(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter);
static void MAGNUM_LOCAL blitImplementationNV(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter); static void MAGNUM_LOCAL blitImplementationNV(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter);
#endif #endif
@ -432,8 +451,10 @@ class MAGNUM_EXPORT AbstractFramebuffer {
#endif #endif
#else #else
void MAGNUM_LOCAL drawBuffersImplementationEXT(GLsizei count, const GLenum* buffers); void MAGNUM_LOCAL drawBuffersImplementationEXT(GLsizei count, const GLenum* buffers);
#ifndef MAGNUM_TARGET_WEBGL
void MAGNUM_LOCAL drawBuffersImplementationNV(GLsizei count, const GLenum* buffers); void MAGNUM_LOCAL drawBuffersImplementationNV(GLsizei count, const GLenum* buffers);
#endif #endif
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL drawBufferImplementationDefault(GLenum buffer); void MAGNUM_LOCAL drawBufferImplementationDefault(GLenum buffer);
@ -441,14 +462,18 @@ class MAGNUM_EXPORT AbstractFramebuffer {
void MAGNUM_LOCAL drawBufferImplementationDSAEXT(GLenum buffer); void MAGNUM_LOCAL drawBufferImplementationDSAEXT(GLenum buffer);
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void MAGNUM_LOCAL readBufferImplementationDefault(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDefault(GLenum buffer);
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDSA(GLenum buffer);
void MAGNUM_LOCAL readBufferImplementationDSAEXT(GLenum buffer); void MAGNUM_LOCAL readBufferImplementationDSAEXT(GLenum buffer);
#endif #endif
static void MAGNUM_LOCAL readImplementationDefault(const Range2Di& rectangle, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); static void MAGNUM_LOCAL readImplementationDefault(const Range2Di& rectangle, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
#ifndef MAGNUM_TARGET_WEBGL
static void MAGNUM_LOCAL readImplementationRobustness(const Range2Di& rectangle, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); static void MAGNUM_LOCAL readImplementationRobustness(const Range2Di& rectangle, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
#endif
void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*); void MAGNUM_LOCAL invalidateImplementationNoOp(GLsizei, const GLenum*);
void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments); void MAGNUM_LOCAL invalidateImplementationDefault(GLsizei count, const GLenum* attachments);
@ -466,7 +491,9 @@ class MAGNUM_EXPORT AbstractFramebuffer {
}; };
CORRADE_ENUMSET_OPERATORS(FramebufferClearMask) CORRADE_ENUMSET_OPERATORS(FramebufferClearMask)
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
CORRADE_ENUMSET_OPERATORS(FramebufferBlitMask) CORRADE_ENUMSET_OPERATORS(FramebufferBlitMask)
#endif
} }

4
src/Magnum/DefaultFramebuffer.cpp

@ -71,6 +71,7 @@ DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachme
return *this; return *this;
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) { DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) {
(this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment)); (this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment));
return *this; return *this;
@ -84,6 +85,7 @@ void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment
(this->*Context::current()->state().framebuffer->invalidateImplementation)(attachments.size(), _attachments); (this->*Context::current()->state().framebuffer->invalidateImplementation)(attachments.size(), _attachments);
} }
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle) { void DefaultFramebuffer::invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle) {
@ -117,7 +119,9 @@ Debug operator<<(Debug debug, const DefaultFramebuffer::Status value) {
switch(value) { switch(value) {
#define _c(value) case DefaultFramebuffer::Status::value: return debug << "DefaultFramebuffer::Status::" #value; #define _c(value) case DefaultFramebuffer::Status::value: return debug << "DefaultFramebuffer::Status::" #value;
_c(Complete) _c(Complete)
#ifndef MAGNUM_TARGET_WEBGL
_c(Undefined) _c(Undefined)
#endif
#undef _c #undef _c
} }

122
src/Magnum/DefaultFramebuffer.h

@ -73,8 +73,8 @@ more involved usage, usage of non-default or multiple framebuffers.
See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer". See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer".
If on desktop GL and either @extension{ARB,direct_state_access} (part of OpenGL If either @extension{ARB,direct_state_access} (part of OpenGL 4.5) or
4.5) or @extension{EXT,direct_state_access} is available, functions @extension{EXT,direct_state_access} desktop extension is available, functions
@ref checkStatus(), @ref mapForDraw(), @ref mapForRead() and @ref invalidate() @ref checkStatus(), @ref mapForDraw(), @ref mapForRead() and @ref invalidate()
use DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}. See their use DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}. See their
respective documentation for more information. respective documentation for more information.
@ -93,16 +93,19 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** The framebuffer is complete */ /** The framebuffer is complete */
Complete = GL_FRAMEBUFFER_COMPLETE, Complete = GL_FRAMEBUFFER_COMPLETE,
#ifndef MAGNUM_TARGET_WEBGL
/** /**
* The default framebuffer does not exist. * The default framebuffer does not exist.
* @requires_gles30 Extension @es_extension{OES,surfaceless_context} * @requires_gles30 Extension @es_extension{OES,surfaceless_context}
* in OpenGL ES 2.0 * in OpenGL ES 2.0.
* @requires_gles Surfaceless context is not available in WebGL.
*/ */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Undefined = GL_FRAMEBUFFER_UNDEFINED Undefined = GL_FRAMEBUFFER_UNDEFINED
#else #else
Undefined = GL_FRAMEBUFFER_UNDEFINED_OES Undefined = GL_FRAMEBUFFER_UNDEFINED_OES
#endif #endif
#endif
}; };
/** /**
@ -111,6 +114,8 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @see @ref mapForDraw() * @see @ref mapForDraw()
* @requires_gles30 Extension @es_extension{EXT,draw_buffers} in OpenGL * @requires_gles30 Extension @es_extension{EXT,draw_buffers} in OpenGL
* ES 2.0. * ES 2.0.
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0.
*/ */
enum class DrawAttachment: GLenum { enum class DrawAttachment: GLenum {
/** Don't use the output. */ /** Don't use the output. */
@ -119,25 +124,29 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Write output to front left buffer. * Write output to front left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES
* or WebGL.
*/ */
FrontLeft = GL_FRONT_LEFT, FrontLeft = GL_FRONT_LEFT,
/** /**
* Write output to front right buffer. * Write output to front right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES
* or WebGL.
*/ */
FrontRight = GL_FRONT_RIGHT, FrontRight = GL_FRONT_RIGHT,
/** /**
* Write output to back left buffer. * Write output to back left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES
* or WebGL.
*/ */
BackLeft = GL_BACK_LEFT, BackLeft = GL_BACK_LEFT,
/** /**
* Write output to back right buffer. * Write output to back right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES
* or WebGL.
*/ */
BackRight = GL_BACK_RIGHT, BackRight = GL_BACK_RIGHT,
#endif #endif
@ -145,8 +154,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** /**
* Write output to back buffer. * Write output to back buffer.
* *
* On desktop OpenGL, this is equal to * On desktop OpenGL this is equal to @ref DrawAttachment::BackLeft.
* @ref DrawAttachment::BackLeft.
*/ */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
Back = GL_BACK Back = GL_BACK
@ -155,12 +163,15 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
#endif #endif
}; };
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @brief Read attachment * @brief Read attachment
* *
* @see @ref mapForRead() * @see @ref mapForRead()
* @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
* in OpenGL ES 2.0 * in OpenGL ES 2.0.
* @requires_webgl20 Framebuffer read mapping is not available in WebGL
* 1.0.
*/ */
enum class ReadAttachment: GLenum { enum class ReadAttachment: GLenum {
/** Don't read from any buffer */ /** Don't read from any buffer */
@ -169,37 +180,43 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Read from front left buffer. * Read from front left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES or
* WebGL.
*/ */
FrontLeft = GL_FRONT_LEFT, FrontLeft = GL_FRONT_LEFT,
/** /**
* Read from front right buffer. * Read from front right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES or
* WebGL.
*/ */
FrontRight = GL_FRONT_RIGHT, FrontRight = GL_FRONT_RIGHT,
/** /**
* Read from back left buffer. * Read from back left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES or
* WebGL.
*/ */
BackLeft = GL_BACK_LEFT, BackLeft = GL_BACK_LEFT,
/** /**
* Read from back right buffer. * Read from back right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES or
* WebGL.
*/ */
BackRight = GL_BACK_RIGHT, BackRight = GL_BACK_RIGHT,
/** /**
* Read from left buffer. * Read from left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES or
* WebGL.
*/ */
Left = GL_LEFT, Left = GL_LEFT,
/** /**
* Read from right buffer. * Read from right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES or
* WebGL.
*/ */
Right = GL_RIGHT, Right = GL_RIGHT,
#endif #endif
@ -210,6 +227,8 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** /**
* Read from front buffer. * Read from front buffer.
* @requires_es_extension Extension @es_extension2{NV,read_buffer_front,GL_NV_read_buffer} * @requires_es_extension Extension @es_extension2{NV,read_buffer_front,GL_NV_read_buffer}
* @requires_gles Reading from front buffer is not available in
* WebGL.
*/ */
Front = GL_FRONT Front = GL_FRONT
@ -219,7 +238,8 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** /**
* Read from front and back buffer. * Read from front and back buffer.
* @requires_gl In OpenGL ES you must specify either * @requires_gl In OpenGL ES you must specify either
* @ref ReadAttachment::Front or @ref ReadAttachment::Back. * @ref ReadAttachment::Front or @ref ReadAttachment::Back. In
* WebGL there is only @ref ReadAttachment::Back.
*/ */
FrontAndBack = GL_FRONT_AND_BACK FrontAndBack = GL_FRONT_AND_BACK
#endif #endif
@ -230,32 +250,38 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* *
* @see @ref invalidate() * @see @ref invalidate()
* @requires_gl43 Extension @extension{ARB,invalidate_subdata} * @requires_gl43 Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 Extension @es_extension{EXT,discard_framebuffer} * @requires_gles30 Extension @es_extension{EXT,discard_framebuffer} in
* in OpenGL ES 2.0 * OpenGL ES 2.0.
* @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0.
*/ */
enum class InvalidationAttachment: GLenum { enum class InvalidationAttachment: GLenum {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Invalidate front left buffer. * Invalidate front left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES
* or WebGL.
*/ */
FrontLeft = GL_FRONT_LEFT, FrontLeft = GL_FRONT_LEFT,
/** /**
* Invalidate front right buffer. * Invalidate front right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES
* or WebGL.
*/ */
FrontRight = GL_FRONT_RIGHT, FrontRight = GL_FRONT_RIGHT,
/** /**
* Invalidate back left buffer. * Invalidate back left buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES
* or WebGL.
*/ */
BackLeft = GL_BACK_LEFT, BackLeft = GL_BACK_LEFT,
/** /**
* Invalidate back right buffer. * Invalidate back right buffer.
* @requires_gl Stereo rendering is not available in OpenGL ES. * @requires_gl Stereo rendering is not available in OpenGL ES
* or WebGL.
*/ */
BackRight = GL_BACK_RIGHT, BackRight = GL_BACK_RIGHT,
#endif #endif
@ -281,6 +307,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
Stencil = GL_STENCIL_EXT Stencil = GL_STENCIL_EXT
#endif #endif
}; };
#endif
explicit MAGNUM_LOCAL DefaultFramebuffer(); explicit MAGNUM_LOCAL DefaultFramebuffer();
@ -300,13 +327,15 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @brief Check framebuffer status * @brief Check framebuffer status
* @param target Target for which to check the status * @param target Target for which to check the status
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* *
* On OpenGL ES 2.0, if none of @es_extension{APPLE,framebuffer_multisample}, * The @p target parameter is ignored on OpenGL ES 2.0 if none of
* @es_extension{ANGLE,framebuffer_blit} or @es_extension{NV,framebuffer_blit} * @es_extension{APPLE,framebuffer_multisample}, @es_extension{ANGLE,framebuffer_blit}
* is available, the @p target parameter is ignored. * or @es_extension{NV,framebuffer_blit} is available and also on WebGL
* 1.0.
* @see @fn_gl2{CheckNamedFramebufferStatus,CheckFramebufferStatus}, * @see @fn_gl2{CheckNamedFramebufferStatus,CheckFramebufferStatus},
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}, * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{CheckFramebufferStatus} * eventually @fn_gl{BindFramebuffer} and @fn_gl{CheckFramebufferStatus}
@ -327,15 +356,18 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}}); * {MyShader::NormalOutput, DefaultFramebuffer::DrawAttachment::None}});
* @endcode * @endcode
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(), * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @ref mapForRead(), @fn_gl2{NamedFramebufferDrawBuffers,DrawBuffers}, * @ref mapForRead(), @fn_gl2{NamedFramebufferDrawBuffers,DrawBuffers},
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}, * @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffers} * eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffers}
* @requires_gles30 Extension @es_extension{EXT,draw_buffers} in OpenGL * @requires_gles30 Extension @es_extension{EXT,draw_buffers} in OpenGL
* ES 2.0. * ES 2.0.
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0.
*/ */
DefaultFramebuffer& mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments); DefaultFramebuffer& mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments);
@ -347,31 +379,38 @@ 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.
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref mapForRead(), @fn_gl2{NamedFramebufferDrawBuffer,DrawBuffer}, * @see @ref mapForRead(), @fn_gl2{NamedFramebufferDrawBuffer,DrawBuffer},
* @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, * @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffer} or * eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffer} or
* @fn_gl{DrawBuffers} in OpenGL ES 3.0 * @fn_gl{DrawBuffers} in OpenGL ES 3.0
* @requires_gles30 Extension @es_extension{EXT,draw_buffers} in OpenGL * @requires_gles30 Extension @es_extension{EXT,draw_buffers} in OpenGL
* ES 2.0. * ES 2.0.
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0.
*/ */
DefaultFramebuffer& mapForDraw(DrawAttachment attachment); DefaultFramebuffer& mapForDraw(DrawAttachment attachment);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @brief Map given attachment for reading * @brief Map given attachment for reading
* @param attachment Buffer attachment * @param attachment Buffer attachment
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref mapForDraw(), @fn_gl2{NamedFramebufferReadBuffer,ReadBuffer}, * @see @ref mapForDraw(), @fn_gl2{NamedFramebufferReadBuffer,ReadBuffer},
* @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}, * @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{ReadBuffer} * eventually @fn_gl{BindFramebuffer} and @fn_gl{ReadBuffer}
* @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
* in OpenGL ES 2.0 * in OpenGL ES 2.0.
* @requires_webgl20 Framebuffer read mapping is not available in WebGL
* 1.0.
*/ */
DefaultFramebuffer& mapForRead(ReadAttachment attachment); DefaultFramebuffer& mapForRead(ReadAttachment attachment);
@ -389,8 +428,11 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* eventually @fn_gl{InvalidateFramebuffer} or * eventually @fn_gl{InvalidateFramebuffer} or
* @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} * @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer}
* on OpenGL ES 2.0 * on OpenGL ES 2.0
* @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0.
*/ */
void invalidate(std::initializer_list<InvalidationAttachment> attachments); void invalidate(std::initializer_list<InvalidationAttachment> attachments);
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** /**
@ -408,6 +450,8 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* eventually @fn_gl{InvalidateSubFramebuffer} * eventually @fn_gl{InvalidateSubFramebuffer}
* @requires_gles30 Use @ref invalidate(std::initializer_list<InvalidationAttachment>) * @requires_gles30 Use @ref invalidate(std::initializer_list<InvalidationAttachment>)
* in OpenGL ES 2.0 instead. * in OpenGL ES 2.0 instead.
* @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0.
*/ */
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle); void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle);
#endif #endif

24
src/Magnum/Framebuffer.cpp

@ -36,7 +36,9 @@
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#include "Magnum/BufferImage.h" #include "Magnum/BufferImage.h"
#ifndef MAGNUM_TARGET_WEBGL
#include "Magnum/MultisampleTexture.h" #include "Magnum/MultisampleTexture.h"
#endif
#include "Magnum/TextureArray.h" #include "Magnum/TextureArray.h"
#endif #endif
@ -56,17 +58,27 @@ namespace Magnum {
const Framebuffer::DrawAttachment Framebuffer::DrawAttachment::None = Framebuffer::DrawAttachment(GL_NONE); 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::Depth = Framebuffer::BufferAttachment(GL_DEPTH_ATTACHMENT);
const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Stencil = Framebuffer::BufferAttachment(GL_STENCIL_ATTACHMENT); const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::Stencil = Framebuffer::BufferAttachment(GL_STENCIL_ATTACHMENT);
/** @todo where to get GL_DEPTH_STENCIL_ATTACHMENT for WebGL? */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::DepthStencil = Framebuffer::BufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT); const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::DepthStencil = Framebuffer::BufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT);
#elif defined(MAGNUM_TARGET_WEBGL)
const Framebuffer::BufferAttachment Framebuffer::BufferAttachment::DepthStencil = Framebuffer::BufferAttachment(0x821A);
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Depth = Framebuffer::InvalidationAttachment(GL_DEPTH_ATTACHMENT); const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Depth = Framebuffer::InvalidationAttachment(GL_DEPTH_ATTACHMENT);
const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Stencil = Framebuffer::InvalidationAttachment(GL_STENCIL_ATTACHMENT); const Framebuffer::InvalidationAttachment Framebuffer::InvalidationAttachment::Stencil = Framebuffer::InvalidationAttachment(GL_STENCIL_ATTACHMENT);
#endif
Int Framebuffer::maxColorAttachments() { Int Framebuffer::maxColorAttachments() {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_WEBGL
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::draw_buffers>() && if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::draw_buffers>() &&
!Context::current()->isExtensionSupported<Extensions::GL::NV::fbo_color_attachments>()) !Context::current()->isExtensionSupported<Extensions::GL::NV::fbo_color_attachments>())
return 0; return 0;
#else
if(!Context::current()->isExtensionSupported<Extensions::GL::WEBGL::draw_buffers>())
return 0;
#endif
#endif #endif
GLint& value = Context::current()->state().framebuffer->maxColorAttachments; GLint& value = Context::current()->state().framebuffer->maxColorAttachments;
@ -166,6 +178,7 @@ Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) {
return *this; return *this;
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) { Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) {
(this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment)); (this->*Context::current()->state().framebuffer->readBufferImplementation)(GLenum(attachment));
return *this; return *this;
@ -190,6 +203,7 @@ void Framebuffer::invalidate(std::initializer_list<InvalidationAttachment> attac
(this->*Context::current()->state().framebuffer->invalidateSubImplementation)(attachments.size(), _attachments, rectangle); (this->*Context::current()->state().framebuffer->invalidateSubImplementation)(attachments.size(), _attachments, rectangle);
} }
#endif #endif
#endif
Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) { Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) {
(this->*Context::current()->state().framebuffer->renderbufferImplementation)(attachment, renderbuffer); (this->*Context::current()->state().framebuffer->renderbufferImplementation)(attachment, renderbuffer);
@ -215,7 +229,7 @@ Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Recta
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, MultisampleTexture2D& texture) { Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, MultisampleTexture2D& texture) {
(this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D_MULTISAMPLE, texture.id(), 0); (this->*Context::current()->state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D_MULTISAMPLE, texture.id(), 0);
return *this; return *this;
@ -227,10 +241,12 @@ Framebuffer& Framebuffer::attachCubeMapTexture(const BufferAttachment attachment
return *this; return *this;
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture3D& texture, Int level, Int layer) { Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture3D& texture, Int level, Int layer) {
(this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); (this->*Context::current()->state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer);
return *this; return *this;
} }
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer) { Framebuffer& Framebuffer::attachTextureLayer(Framebuffer::BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer) {
@ -322,10 +338,11 @@ void Framebuffer::texture2DImplementationDSAEXT(BufferAttachment attachment, GLe
} }
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) { void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint mipLevel, GLint layer) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glFramebufferTextureLayer(GLenum(bindInternal()), GLenum(attachment), textureId, mipLevel, layer); glFramebufferTextureLayer(GLenum(bindInternal()), GLenum(attachment), textureId, mipLevel, layer);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_NACL)
glFramebufferTexture3DOES(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_3D_OES, textureId, mipLevel, layer); glFramebufferTexture3DOES(GLenum(bindInternal()), GLenum(attachment), GL_TEXTURE_3D_OES, textureId, mipLevel, layer);
#else #else
static_cast<void>(attachment); static_cast<void>(attachment);
@ -335,6 +352,7 @@ void Framebuffer::textureLayerImplementationDefault(BufferAttachment attachment,
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
} }
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void Framebuffer::textureLayerImplementationDSA(const BufferAttachment attachment, const GLuint textureId, const GLint mipLevel, const GLint layer) { void Framebuffer::textureLayerImplementationDSA(const BufferAttachment attachment, const GLuint textureId, const GLint mipLevel, const GLint layer) {
@ -359,7 +377,9 @@ Debug operator<<(Debug debug, const Framebuffer::Status value) {
_c(IncompleteReadBuffer) _c(IncompleteReadBuffer)
#endif #endif
_c(Unsupported) _c(Unsupported)
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
_c(IncompleteMultisample) _c(IncompleteMultisample)
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_c(IncompleteLayerTargets) _c(IncompleteLayerTargets)
#endif #endif

156
src/Magnum/Framebuffer.h

@ -93,8 +93,8 @@ void drawEvent() {
See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer". See also @ref AbstractFramebuffer-performance-optimization "relevant section in AbstractFramebuffer".
If on desktop GL and either @extension{ARB,direct_state_access} (part of OpenGL If either @extension{ARB,direct_state_access} (part of OpenGL 4.5) or
4.5) or @extension{EXT,direct_state_access} is available, functions @extension{EXT,direct_state_access} desktop extension is available, functions
@ref checkStatus(), @ref mapForDraw(), @ref mapForRead(), @ref invalidate(), @ref checkStatus(), @ref mapForDraw(), @ref mapForRead(), @ref invalidate(),
@ref attachRenderbuffer(), @ref attachTexture(), @ref attachCubeMapTexture() @ref attachRenderbuffer(), @ref attachTexture(), @ref attachCubeMapTexture()
and @ref attachTextureLayer() use DSA to avoid unnecessary calls to and @ref attachTextureLayer() use DSA to avoid unnecessary calls to
@ -117,6 +117,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @es_extension{NV,draw_buffers} for @ref mapForDraw() and * @es_extension{NV,draw_buffers} for @ref mapForDraw() and
* extension @es_extension{NV,fbo_color_attachments} for `attach*()` * extension @es_extension{NV,fbo_color_attachments} for `attach*()`
* in OpenGL ES 2.0. * in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0.
*/ */
class ColorAttachment { class ColorAttachment {
friend Framebuffer; friend Framebuffer;
@ -142,6 +144,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @see @ref mapForDraw() * @see @ref mapForDraw()
* @requires_gles30 Extension @es_extension{EXT,draw_buffers} or * @requires_gles30 Extension @es_extension{EXT,draw_buffers} or
* @es_extension{NV,draw_buffers} in OpenGL ES 2.0. * @es_extension{NV,draw_buffers} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0.
*/ */
class DrawAttachment { class DrawAttachment {
public: public:
@ -168,6 +172,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @ref attachCubeMapTexture(), @ref attachTextureLayer() * @ref attachCubeMapTexture(), @ref attachTextureLayer()
* @requires_gles30 Extension @es_extension{EXT,draw_buffers} or * @requires_gles30 Extension @es_extension{EXT,draw_buffers} or
* @es_extension{NV,fbo_color_attachments} in OpenGL ES 2.0. * @es_extension{NV,fbo_color_attachments} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0.
*/ */
class MAGNUM_EXPORT BufferAttachment { class MAGNUM_EXPORT BufferAttachment {
public: public:
@ -177,7 +183,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
/** @brief Stencil buffer */ /** @brief Stencil buffer */
static const BufferAttachment Stencil; static const BufferAttachment Stencil;
#ifndef MAGNUM_TARGET_GLES2 #if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_TARGET_WEBGL)
/** /**
* @brief Both depth and stencil buffer * @brief Both depth and stencil buffer
* *
@ -203,13 +209,16 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
GLenum attachment; GLenum attachment;
}; };
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @brief Invalidation attachment * @brief Invalidation attachment
* *
* @see @ref invalidate() * @see @ref invalidate()
* @requires_gl43 Extension @extension{ARB,invalidate_subdata} * @requires_gl43 Extension @extension{ARB,invalidate_subdata}
* @requires_gles30 Extension @es_extension{EXT,discard_framebuffer} * @requires_gles30 Extension @es_extension{EXT,discard_framebuffer} in
* in OpenGL ES 2.0 * OpenGL ES 2.0.
* @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0.
*/ */
class InvalidationAttachment { class InvalidationAttachment {
public: public:
@ -231,6 +240,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
GLenum attachment; GLenum attachment;
}; };
#endif
/** /**
* @brief Status * @brief Status
@ -251,13 +261,13 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
/** @todo Why exactly this is not needed? */ /** @todo Why exactly this is not needed? */
/** /**
* No object attached to any draw color attachment points * No object attached to any draw color attachment points
* @requires_gl Not available in OpenGL ES. * @requires_gl Not available in OpenGL ES or WebGL.
*/ */
IncompleteDrawBuffer = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER, IncompleteDrawBuffer = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER,
/** /**
* No object attached to read color attachment point * No object attached to read color attachment point
* @requires_gl Not available in OpenGL ES. * @requires_gl Not available in OpenGL ES or WebGL.
*/ */
IncompleteReadBuffer = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER, IncompleteReadBuffer = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER,
#endif #endif
@ -274,18 +284,21 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @requires_gles30 Extension @es_extension{ANGLE,framebuffer_multisample}, * @requires_gles30 Extension @es_extension{ANGLE,framebuffer_multisample},
* @es_extension{APPLE,framebuffer_multisample}, * @es_extension{APPLE,framebuffer_multisample},
* @es_extension{EXT,multisampled_render_to_texture} or * @es_extension{EXT,multisampled_render_to_texture} or
* @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0 * @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0.
* @requires_webgl20 Multisample framebuffers are not available in
* WebGL 1.0.
*/ */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
#else #elif !defined(MAGNUM_TARGET_WEBGL)
IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE, IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE,
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Mismatched layered color attachments * Mismatched layered color attachments
* @requires_gl Geometry shaders are not available in OpenGL ES. * @requires_gl Geometry shaders are not available in OpenGL ES or
* WebGL.
*/ */
IncompleteLayerTargets = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS IncompleteLayerTargets = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
#endif #endif
@ -297,9 +310,10 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @brief Max supported color attachment count * @brief Max supported color attachment count
* *
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. In OpenGL ES 2.0, if neither @es_extension{EXT,draw_buffers} * OpenGL calls. If neither @es_extension{EXT,draw_buffers} nor
* nor @es_extension{NV,fbo_color_attachments} extension is available, * @es_extension{NV,fbo_color_attachments} extension is available in
* returns `0`. * OpenGL ES 2.0 and @webgl_extension{WEBGL,draw_buffers} is not
* available in WebGL 1.0, returns `0`.
* @see @ref mapForDraw(), @fn_gl{Get} with @def_gl{MAX_COLOR_ATTACHMENTS} * @see @ref mapForDraw(), @fn_gl{Get} with @def_gl{MAX_COLOR_ATTACHMENTS}
*/ */
static Int maxColorAttachments(); static Int maxColorAttachments();
@ -308,7 +322,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @brief Constructor * @brief Constructor
* *
* Generates new OpenGL framebuffer object. If @extension{ARB,direct_state_access} * Generates new OpenGL framebuffer object. If @extension{ARB,direct_state_access}
* (part of OpenGL 4.5) is not supported, the framebuffer is created on * (part of OpenGL 4.5) is not available, the framebuffer is created on
* first use. * first use.
* @see @ref setViewport(), @fn_gl{CreateFramebuffers}, eventually * @see @ref setViewport(), @fn_gl{CreateFramebuffers}, eventually
* @fn_gl{GenFramebuffers} * @fn_gl{GenFramebuffers}
@ -379,13 +393,15 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @brief Check framebuffer status * @brief Check framebuffer status
* @param target Target for which check the status * @param target Target for which check the status
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* *
* On OpenGL ES 2.0, if none of @es_extension{APPLE,framebuffer_multisample}, * The @p target parameter is ignored on OpenGL ES 2.0 if none of
* @es_extension{ANGLE,framebuffer_blit} or @es_extension{NV,framebuffer_blit} * @es_extension{APPLE,framebuffer_multisample}, @es_extension{ANGLE,framebuffer_blit}
* is available, the @p target parameter is ignored. * or @es_extension{NV,framebuffer_blit} is available and also on WebGL
* 1.0.
* @see @fn_gl2{CheckNamedFramebufferStatus,CheckFramebufferStatus}, * @see @fn_gl2{CheckNamedFramebufferStatus,CheckFramebufferStatus},
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}, * @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{CheckFramebufferStatus} * eventually @fn_gl{BindFramebuffer} and @fn_gl{CheckFramebufferStatus}
@ -405,9 +421,10 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* {MyShader::NormalOutput, Framebuffer::DrawAttachment::None}}); * {MyShader::NormalOutput, Framebuffer::DrawAttachment::None}});
* @endcode * @endcode
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(), * @see @ref maxDrawBuffers(), @ref maxDualSourceDrawBuffers(),
* @ref maxColorAttachments(), @ref mapForRead(), * @ref maxColorAttachments(), @ref mapForRead(),
* @fn_gl2{NamedFramebufferDrawBuffers,DrawBuffers}, * @fn_gl2{NamedFramebufferDrawBuffers,DrawBuffers},
@ -415,6 +432,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffers} * eventually @fn_gl{BindFramebuffer} and @fn_gl{DrawBuffers}
* @requires_gles30 Extension @es_extension{EXT,draw_buffers} or * @requires_gles30 Extension @es_extension{EXT,draw_buffers} or
* @es_extension{NV,draw_buffers} in OpenGL ES 2.0. * @es_extension{NV,draw_buffers} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0.
*/ */
Framebuffer& mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments); Framebuffer& mapForDraw(std::initializer_list<std::pair<UnsignedInt, DrawAttachment>> attachments);
@ -426,9 +445,10 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* 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.
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref maxColorAttachments(), @ref mapForRead(), * @see @ref maxColorAttachments(), @ref mapForRead(),
* @fn_gl2{NamedFramebufferDrawBuffer,DrawBuffer}, * @fn_gl2{NamedFramebufferDrawBuffer,DrawBuffer},
* @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access}, * @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access},
@ -436,22 +456,28 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @fn_gl{DrawBuffers} in OpenGL ES) * @fn_gl{DrawBuffers} in OpenGL ES)
* @requires_gles30 Extension @es_extension{EXT,draw_buffers} or * @requires_gles30 Extension @es_extension{EXT,draw_buffers} or
* @es_extension{NV,draw_buffers} in OpenGL ES 2.0. * @es_extension{NV,draw_buffers} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{WEBGL,draw_buffers} in
* WebGL 1.0.
*/ */
Framebuffer& mapForDraw(DrawAttachment attachment); Framebuffer& mapForDraw(DrawAttachment attachment);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @brief Map given color attachment for reading * @brief Map given color attachment for reading
* @param attachment Color attachment * @param attachment Color attachment
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref mapForDraw(), @fn_gl2{NamedFramebufferReadBuffer,ReadBuffer}, * @see @ref mapForDraw(), @fn_gl2{NamedFramebufferReadBuffer,ReadBuffer},
* @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}, * @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{ReadBuffer} * eventually @fn_gl{BindFramebuffer} and @fn_gl{ReadBuffer}
* @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer} * @requires_gles30 Extension @es_extension2{NV,read_buffer,GL_NV_read_buffer}
* in OpenGL ES 2.0 * in OpenGL ES 2.0.
* @requires_webgl20 Framebuffer read mapping is not available in WebGL
* 1.0.
*/ */
Framebuffer& mapForRead(ColorAttachment attachment); Framebuffer& mapForRead(ColorAttachment attachment);
@ -469,8 +495,11 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* eventually @fn_gl{InvalidateFramebuffer} or * eventually @fn_gl{InvalidateFramebuffer} or
* @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} * @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer}
* on OpenGL ES 2.0 * on OpenGL ES 2.0
* @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0.
*/ */
void invalidate(std::initializer_list<InvalidationAttachment> attachments); void invalidate(std::initializer_list<InvalidationAttachment> attachments);
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** /**
@ -488,6 +517,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* eventually @fn_gl{InvalidateSubFramebuffer} * eventually @fn_gl{InvalidateSubFramebuffer}
* @requires_gles30 Use @ref invalidate(std::initializer_list<InvalidationAttachment>) * @requires_gles30 Use @ref invalidate(std::initializer_list<InvalidationAttachment>)
* in OpenGL ES 2.0 instead. * in OpenGL ES 2.0 instead.
* @requires_webgl20 Framebuffer invalidation is not available in WebGL
* 1.0.
*/ */
void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle); void invalidate(std::initializer_list<InvalidationAttachment> attachments, const Range2Di& rectangle);
#endif #endif
@ -498,9 +529,10 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param renderbuffer Renderbuffer * @param renderbuffer Renderbuffer
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @fn_gl2{NamedFramebufferRenderbuffer,FramebufferRenderbuffer}, * @see @fn_gl2{NamedFramebufferRenderbuffer,FramebufferRenderbuffer},
* @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access}, * @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl{FramebufferRenderbuffer} * eventually @fn_gl{BindFramebuffer} and @fn_gl{FramebufferRenderbuffer}
@ -515,14 +547,16 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref attachCubeMapTexture(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture}, * @see @ref attachCubeMapTexture(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture},
* @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}, * @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and * eventually @fn_gl{BindFramebuffer} and
* @fn_gl2{FramebufferTexture1D,FramebufferTexture} * @fn_gl2{FramebufferTexture1D,FramebufferTexture}
* @requires_gl Only 2D and 3D textures are available in OpenGL ES. * @requires_gl Only 2D and 3D textures are available in OpenGL ES and
* WebGL.
*/ */
Framebuffer& attachTexture(BufferAttachment attachment, Texture1D& texture, Int level); Framebuffer& attachTexture(BufferAttachment attachment, Texture1D& texture, Int level);
#endif #endif
@ -534,9 +568,10 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref attachCubeMapTexture(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture}, * @see @ref attachCubeMapTexture(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture},
* @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}, * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and * eventually @fn_gl{BindFramebuffer} and
@ -547,16 +582,18 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** @overload /** @overload
* @requires_gl31 Extension @extension{ARB,texture_rectangle} * @requires_gl31 Extension @extension{ARB,texture_rectangle}
* @requires_gl Rectangle textures are not available in OpenGL ES. * @requires_gl Rectangle textures are not available in OpenGL ES and
* WebGL.
*/ */
Framebuffer& attachTexture(BufferAttachment attachment, RectangleTexture& texture); Framebuffer& attachTexture(BufferAttachment attachment, RectangleTexture& texture);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/** @overload /** @overload
* @requires_gl32 Extension @extension{ARB,texture_multisample} * @requires_gl32 Extension @extension{ARB,texture_multisample}
* @requires_gles31 Multisample textures are not available in OpenGL ES * @requires_gles31 Multisample textures are not available in OpenGL ES
* 3.0 and older. * 3.0 and older.
* @requires_gles Multisample textures are not available in WebGL.
*/ */
Framebuffer& attachTexture(BufferAttachment attachment, MultisampleTexture2D& texture); Framebuffer& attachTexture(BufferAttachment attachment, MultisampleTexture2D& texture);
#endif #endif
@ -569,15 +606,17 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @ref attachTexture2D(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture}, * @see @ref attachTexture2D(), @fn_gl2{NamedFramebufferTexture,FramebufferTexture},
* @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access}, * @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl2{FramebufferTexture2D,FramebufferTexture} * eventually @fn_gl{BindFramebuffer} and @fn_gl2{FramebufferTexture2D,FramebufferTexture}
*/ */
Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level); Framebuffer& attachCubeMapTexture(BufferAttachment attachment, CubeMapTexture& texture, CubeMapTexture::Coordinate coordinate, Int level);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @brief Attach texture layer to given buffer * @brief Attach texture layer to given buffer
* @param attachment Buffer attachment * @param attachment Buffer attachment
@ -586,23 +625,27 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
* @param layer Layer * @param layer Layer
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the framebuffer is bound before the operation (if not already). * available, the framebuffer is bound before the operation (if not
* already).
* @see @fn_gl2{NamedFramebufferTextureLayer,FramebufferTextureLayer}, * @see @fn_gl2{NamedFramebufferTextureLayer,FramebufferTextureLayer},
* @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access}, * @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access},
* eventually @fn_gl{BindFramebuffer} and @fn_gl2{FramebufferTextureLayer,FramebufferTexture} * eventually @fn_gl{BindFramebuffer} and @fn_gl2{FramebufferTextureLayer,FramebufferTexture}
* or @fn_gles_extension{FramebufferTexture3D,OES,texture_3D} in * or @fn_gles_extension{FramebufferTexture3D,OES,texture_3D} in
* OpenGL ES 2.0 * OpenGL ES 2.0
* @requires_gles30 Extension @es_extension{OES,texture_3D} in OpenGL * @requires_gles30 Extension @es_extension{OES,texture_3D} in OpenGL
* ES 2.0 * ES 2.0.
* @requires_webgl20 Only 2D textures are available in WebGL 1.0.
*/ */
Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture3D& texture, Int level, Int layer); Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture3D& texture, Int level, Int layer);
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** @overload /** @overload
* @requires_gl30 Extension @extension{EXT,texture_array} * @requires_gl30 Extension @extension{EXT,texture_array}
* @requires_gl Only 2D array textures are available in OpenGL ES. * @requires_gl Only 2D array textures are available in OpenGL ES and
* WebGL.
*/ */
Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer); Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer);
#endif #endif
@ -610,7 +653,8 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** @overload /** @overload
* @requires_gl30 Extension @extension{EXT,texture_array} * @requires_gl30 Extension @extension{EXT,texture_array}
* @requires_gles30 Array textures are not available in OpenGL ES 2.0 * @requires_gles30 Array textures are not available in OpenGL ES 2.0.
* @requires_webgl20 Array textures are not available in WebGL 1.0.
*/ */
Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer); Framebuffer& attachTextureLayer(BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer);
#endif #endif
@ -618,13 +662,15 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** @overload /** @overload
* @requires_gl40 Extension @extension{ARB,texture_cube_map_array} * @requires_gl40 Extension @extension{ARB,texture_cube_map_array}
* @requires_gl Cube map texture arrays are not available in OpenGL ES. * @requires_gl Cube map texture arrays are not available in OpenGL ES
* or WebGL.
*/ */
Framebuffer& attachTextureLayer(BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer); Framebuffer& attachTextureLayer(BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer);
/** @overload /** @overload
* @requires_gl32 Extension @extension{ARB,texture_multisample} * @requires_gl32 Extension @extension{ARB,texture_multisample}
* @requires_gl Multisample array textures are not available in OpenGL ES. * @requires_gl Multisample array textures are not available in OpenGL
* ES or WebGL.
*/ */
Framebuffer& attachTextureLayer(BufferAttachment attachment, MultisampleTexture2DArray& texture, Int layer); Framebuffer& attachTextureLayer(BufferAttachment attachment, MultisampleTexture2DArray& texture, Int layer);
#endif #endif
@ -646,6 +692,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
*/ */
CORRADE_DEPRECATED("use one of attachTexture() overloads instead") Framebuffer& attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int level); CORRADE_DEPRECATED("use one of attachTexture() overloads instead") Framebuffer& attachTexture2D(BufferAttachment attachment, Texture2D& texture, Int level);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @copybrief attachTextureLayer() * @copybrief attachTextureLayer()
* @deprecated Use one of @ref attachTextureLayer() overloads instead. * @deprecated Use one of @ref attachTextureLayer() overloads instead.
@ -654,6 +701,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
return attachTextureLayer(attachment, texture, level, layer); return attachTextureLayer(attachment, texture, level, layer);
} }
#endif #endif
#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
@ -695,7 +743,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
void MAGNUM_LOCAL texture2DImplementationDSAEXT(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level); void MAGNUM_LOCAL texture2DImplementationDSAEXT(BufferAttachment attachment, GLenum textureTarget, GLuint textureId, GLint level);
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); void MAGNUM_LOCAL textureLayerImplementationDefault(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); void MAGNUM_LOCAL textureLayerImplementationDSA(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);
void MAGNUM_LOCAL textureLayerImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer); void MAGNUM_LOCAL textureLayerImplementationDSAEXT(BufferAttachment attachment, GLuint textureId, GLint level, GLint layer);

46
src/Magnum/Implementation/FramebufferState.cpp

@ -35,7 +35,10 @@ namespace Magnum { namespace Implementation {
constexpr const Range2Di FramebufferState::DisengagedViewport; constexpr const Range2Di FramebufferState::DisengagedViewport;
FramebufferState::FramebufferState(Context& context, std::vector<std::string>& extensions): readBinding{0}, drawBinding{0}, renderbufferBinding{0}, maxDrawBuffers{0}, maxColorAttachments{0}, maxRenderbufferSize{0}, maxSamples{0}, FramebufferState::FramebufferState(Context& context, std::vector<std::string>& extensions): readBinding{0}, drawBinding{0}, renderbufferBinding{0}, maxDrawBuffers{0}, maxColorAttachments{0}, maxRenderbufferSize{0},
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
maxSamples{0},
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
maxDualSourceDrawBuffers{0}, maxDualSourceDrawBuffers{0},
#endif #endif
@ -96,14 +99,18 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault; drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault; readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;
#endif
renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault; renderbufferImplementation = &Framebuffer::renderbufferImplementationDefault;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
texture1DImplementation = &Framebuffer::texture1DImplementationDefault; texture1DImplementation = &Framebuffer::texture1DImplementationDefault;
#endif #endif
texture2DImplementation = &Framebuffer::texture2DImplementationDefault; texture2DImplementation = &Framebuffer::texture2DImplementationDefault;
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
textureLayerImplementation = &Framebuffer::textureLayerImplementationDefault; textureLayerImplementation = &Framebuffer::textureLayerImplementationDefault;
#endif
renderbufferStorageImplementation = &Renderbuffer::storageImplementationDefault; renderbufferStorageImplementation = &Renderbuffer::storageImplementationDefault;
} }
@ -112,10 +119,13 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
/* Framebuffer binding and checking on ES2 */ /* Framebuffer binding and checking on ES2 */
/* Optimistically set separate binding targets and check if one of the /* Optimistically set separate binding targets and check if one of the
extensions providing them is available */ extensions providing them is available */
#ifndef MAGNUM_TARGET_WEBGL
bindImplementation = &Framebuffer::bindImplementationDefault; bindImplementation = &Framebuffer::bindImplementationDefault;
bindInternalImplementation = &Framebuffer::bindImplementationDefault; bindInternalImplementation = &Framebuffer::bindImplementationDefault;
#endif
checkStatusImplementation = &Framebuffer::checkStatusImplementationDefault; checkStatusImplementation = &Framebuffer::checkStatusImplementationDefault;
#ifndef MAGNUM_TARGET_WEBGL
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>()) { if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>()) {
extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string()); extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string());
@ -138,7 +148,9 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
bindInternalImplementation = &Framebuffer::bindImplementationSingle; bindInternalImplementation = &Framebuffer::bindImplementationSingle;
checkStatusImplementation = &Framebuffer::checkStatusImplementationSingle; checkStatusImplementation = &Framebuffer::checkStatusImplementationSingle;
} }
#endif
#ifndef MAGNUM_TARGET_WEBGL
/* Framebuffer draw mapping on ES2 */ /* Framebuffer draw mapping on ES2 */
if(context.isExtensionSupported<Extensions::GL::EXT::draw_buffers>()) { if(context.isExtensionSupported<Extensions::GL::EXT::draw_buffers>()) {
extensions.push_back(Extensions::GL::EXT::draw_buffers::string()); extensions.push_back(Extensions::GL::EXT::draw_buffers::string());
@ -149,9 +161,17 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationNV; drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationNV;
} else drawBuffersImplementation = nullptr; } else drawBuffersImplementation = nullptr;
#else
if(context.isExtensionSupported<Extensions::GL::WEBGL::draw_buffers>()) {
extensions.push_back(Extensions::GL::WEBGL::draw_buffers::string());
/* The EXT implementation is exposed in Emscripten */
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationEXT;
} else drawBuffersImplementation = nullptr;
#endif
#endif #endif
/* Framebuffer reading implementation */ /* Framebuffer reading implementation in desktop/ES */
#ifndef MAGNUM_TARGET_WEBGL
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::robustness>()) if(context.isExtensionSupported<Extensions::GL::ARB::robustness>())
#else #else
@ -167,6 +187,11 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
readImplementation = &AbstractFramebuffer::readImplementationRobustness; readImplementation = &AbstractFramebuffer::readImplementationRobustness;
} else readImplementation = &AbstractFramebuffer::readImplementationDefault; } else readImplementation = &AbstractFramebuffer::readImplementationDefault;
/* Framebuffer reading in WebGL */
#else
readImplementation = &AbstractFramebuffer::readImplementationDefault;
#endif
/* Multisample renderbuffer storage implementation */ /* Multisample renderbuffer storage implementation */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::ARB::direct_state_access>()) {
@ -181,7 +206,7 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
} else } else
#endif #endif
{ {
#ifdef MAGNUM_TARGET_GLES2 #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>()) { if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>()) {
extensions.push_back(Extensions::GL::ANGLE::framebuffer_multisample::string()); extensions.push_back(Extensions::GL::ANGLE::framebuffer_multisample::string());
@ -191,7 +216,7 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationNV; renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationNV;
} else renderbufferStorageMultisampleImplementation = nullptr; } else renderbufferStorageMultisampleImplementation = nullptr;
#else #elif !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDefault; renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDefault;
#endif #endif
} }
@ -216,7 +241,7 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
} }
/* Framebuffer invalidation implementation on ES2 */ /* Framebuffer invalidation implementation on ES2 */
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(context.isExtensionSupported<Extensions::GL::EXT::discard_framebuffer>()) { if(context.isExtensionSupported<Extensions::GL::EXT::discard_framebuffer>()) {
extensions.push_back(Extensions::GL::EXT::discard_framebuffer::string()); extensions.push_back(Extensions::GL::EXT::discard_framebuffer::string());
@ -226,7 +251,7 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
} }
/* Always available on ES3 */ /* Always available on ES3 */
#else #elif !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault; invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault;
invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault; invalidateSubImplementation = &AbstractFramebuffer::invalidateImplementationDefault;
#endif #endif
@ -240,7 +265,7 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
} else blitImplementation = &AbstractFramebuffer::blitImplementationDefault; } else blitImplementation = &AbstractFramebuffer::blitImplementationDefault;
/* Blit implementation on ES2 */ /* Blit implementation on ES2 */
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>()) { if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>()) {
extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string()); extensions.push_back(Extensions::GL::ANGLE::framebuffer_blit::string());
blitImplementation = &AbstractFramebuffer::blitImplementationANGLE; blitImplementation = &AbstractFramebuffer::blitImplementationANGLE;
@ -252,9 +277,14 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
} else blitImplementation = nullptr; } else blitImplementation = nullptr;
/* Always available on ES3 */ /* Always available on ES3 */
#else #elif !defined(MAGNUM_TARGET_WEBGL)
blitImplementation = &AbstractFramebuffer::blitImplementationDefault; blitImplementation = &AbstractFramebuffer::blitImplementationDefault;
#endif #endif
#if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
static_cast<void>(context);
static_cast<void>(extensions);
#endif
} }
void FramebufferState::reset() { void FramebufferState::reset() {

13
src/Magnum/Implementation/FramebufferState.h

@ -39,14 +39,18 @@ struct FramebufferState {
void reset(); void reset();
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void(*blitImplementation)(AbstractFramebuffer&, AbstractFramebuffer&, const Range2Di&, const Range2Di&, FramebufferBlitMask, FramebufferBlitFilter); void(*blitImplementation)(AbstractFramebuffer&, AbstractFramebuffer&, const Range2Di&, const Range2Di&, FramebufferBlitMask, FramebufferBlitFilter);
#endif
GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget); GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget);
void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*); void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void(AbstractFramebuffer::*drawBufferImplementation)(GLenum); void(AbstractFramebuffer::*drawBufferImplementation)(GLenum);
#endif #endif
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void(AbstractFramebuffer::*readBufferImplementation)(GLenum); void(AbstractFramebuffer::*readBufferImplementation)(GLenum);
void(AbstractFramebuffer::*invalidateImplementation)(GLsizei, const GLenum*); void(AbstractFramebuffer::*invalidateImplementation)(GLsizei, const GLenum*);
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void(AbstractFramebuffer::*invalidateSubImplementation)(GLsizei, const GLenum*, const Range2Di&); void(AbstractFramebuffer::*invalidateSubImplementation)(GLsizei, const GLenum*, const Range2Di&);
#endif #endif
@ -61,16 +65,23 @@ struct FramebufferState {
void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, GLuint, GLint); void(Framebuffer::*texture1DImplementation)(Framebuffer::BufferAttachment, GLuint, GLint);
#endif #endif
void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint); void(Framebuffer::*texture2DImplementation)(Framebuffer::BufferAttachment, GLenum, GLuint, GLint);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void(Framebuffer::*textureLayerImplementation)(Framebuffer::BufferAttachment, GLuint, GLint, GLint); void(Framebuffer::*textureLayerImplementation)(Framebuffer::BufferAttachment, GLuint, GLint, GLint);
#endif
void(Renderbuffer::*createRenderbufferImplementation)(); void(Renderbuffer::*createRenderbufferImplementation)();
void(Renderbuffer::*renderbufferStorageImplementation)(RenderbufferFormat, const Vector2i&); void(Renderbuffer::*renderbufferStorageImplementation)(RenderbufferFormat, const Vector2i&);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void(Renderbuffer::*renderbufferStorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&); void(Renderbuffer::*renderbufferStorageMultisampleImplementation)(GLsizei, RenderbufferFormat, const Vector2i&);
#endif
void(*readImplementation)(const Range2Di&, ColorFormat, ColorType, std::size_t, GLvoid*); void(*readImplementation)(const Range2Di&, ColorFormat, ColorType, std::size_t, GLvoid*);
GLuint readBinding, drawBinding, renderbufferBinding; GLuint readBinding, drawBinding, renderbufferBinding;
GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize, maxSamples; GLint maxDrawBuffers, maxColorAttachments, maxRenderbufferSize;
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
GLint maxSamples;
#endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GLint maxDualSourceDrawBuffers; GLint maxDualSourceDrawBuffers;
#endif #endif

10
src/Magnum/Renderbuffer.cpp

@ -46,6 +46,7 @@ Int Renderbuffer::maxSize() {
return value; return value;
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
Int Renderbuffer::maxSamples() { Int Renderbuffer::maxSamples() {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::framebuffer_multisample>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>())
@ -65,6 +66,7 @@ Int Renderbuffer::maxSamples() {
return value; return value;
} }
#endif
Renderbuffer::Renderbuffer() { Renderbuffer::Renderbuffer() {
(this->*Context::current()->state().framebuffer->createRenderbufferImplementation)(); (this->*Context::current()->state().framebuffer->createRenderbufferImplementation)();
@ -121,9 +123,11 @@ void Renderbuffer::setStorage(const RenderbufferFormat internalFormat, const Vec
(this->*Context::current()->state().framebuffer->renderbufferStorageImplementation)(internalFormat, size); (this->*Context::current()->state().framebuffer->renderbufferStorageImplementation)(internalFormat, size);
} }
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void Renderbuffer::setStorageMultisample(const Int samples, const RenderbufferFormat internalFormat, const Vector2i& size) { void Renderbuffer::setStorageMultisample(const Int samples, const RenderbufferFormat internalFormat, const Vector2i& size) {
(this->*Context::current()->state().framebuffer->renderbufferStorageMultisampleImplementation)(samples, internalFormat, size); (this->*Context::current()->state().framebuffer->renderbufferStorageMultisampleImplementation)(samples, internalFormat, size);
} }
#endif
void Renderbuffer::bind() { void Renderbuffer::bind() {
GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding; GLuint& binding = Context::current()->state().framebuffer->renderbufferBinding;
@ -157,9 +161,9 @@ void Renderbuffer::storageMultisampleImplementationDefault(const GLsizei samples
bind(); bind();
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GLenum(internalFormat), size.x(), size.y()); glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GLenum(internalFormat), size.x(), size.y());
} }
#else #elif !defined(MAGNUM_TARGET_WEBGL)
void Renderbuffer::storageMultisampleImplementationANGLE(const GLsizei samples, const RenderbufferFormat internalFormat, const Vector2i& size) { void Renderbuffer::storageMultisampleImplementationANGLE(const GLsizei samples, const RenderbufferFormat internalFormat, const Vector2i& size) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
bind(); bind();
glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, samples, GLenum(internalFormat), size.x(), size.y()); glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, samples, GLenum(internalFormat), size.x(), size.y());
#else #else
@ -171,7 +175,7 @@ void Renderbuffer::storageMultisampleImplementationANGLE(const GLsizei samples,
} }
void Renderbuffer::storageMultisampleImplementationNV(const GLsizei samples, const RenderbufferFormat internalFormat, const Vector2i& size) { void Renderbuffer::storageMultisampleImplementationNV(const GLsizei samples, const RenderbufferFormat internalFormat, const Vector2i& size) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
bind(); bind();
glRenderbufferStorageMultisampleNV(GL_RENDERBUFFER, samples, GLenum(internalFormat), size.x(), size.y()); glRenderbufferStorageMultisampleNV(GL_RENDERBUFFER, samples, GLenum(internalFormat), size.x(), size.y());
#else #else

32
src/Magnum/Renderbuffer.h

@ -51,8 +51,8 @@ The engine tracks currently bound renderbuffer to avoid unnecessary calls to
implementation-defined values (such as @ref maxSize()) are cached, so repeated implementation-defined values (such as @ref maxSize()) are cached, so repeated
queries don't result in repeated @fn_gl{Get} calls. queries don't result in repeated @fn_gl{Get} calls.
If not on OpenGL ES and either @extension{ARB,direct_state_access} (part of If either @extension{ARB,direct_state_access} (part of OpenGL 4.5) or
OpenGL 4.5) or @extension{EXT,direct_state_access} is available, functions @extension{EXT,direct_state_access} desktop extension is available, functions
@ref setStorage() and @ref setStorageMultisample() use DSA to avoid unnecessary @ref setStorage() and @ref setStorageMultisample() use DSA to avoid unnecessary
calls to @fn_gl{BindRenderbuffer}. See their respective documentation for more calls to @fn_gl{BindRenderbuffer}. See their respective documentation for more
information. information.
@ -73,6 +73,7 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
*/ */
static Int maxSize(); static Int maxSize();
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @brief Max supported sample count * @brief Max supported sample count
* *
@ -81,14 +82,17 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
* @es_extension{ANGLE,framebuffer_multisample} / * @es_extension{ANGLE,framebuffer_multisample} /
* @es_extension{NV,framebuffer_multisample} is available, returns `0`. * @es_extension{NV,framebuffer_multisample} is available, returns `0`.
* @see @ref setStorageMultisample(), @fn_gl{Get} with @def_gl{MAX_SAMPLES} * @see @ref setStorageMultisample(), @fn_gl{Get} with @def_gl{MAX_SAMPLES}
* @requires_webgl20 Multisample framebuffers are not available in
* WebGL 1.0.
*/ */
static Int maxSamples(); static Int maxSamples();
#endif
/** /**
* @brief Constructor * @brief Constructor
* *
* Generates new OpenGL renderbuffer object. If @extension{ARB,direct_state_access} * Generates new OpenGL renderbuffer object. If @extension{ARB,direct_state_access}
* (part of OpenGL 4.5) is not supported, the renderbuffer is created * (part of OpenGL 4.5) is not available, the renderbuffer is created
* on first use. * on first use.
* @see @fn_gl{CreateRenderbuffers}, eventually @fn_gl{GenRenderbuffers} * @see @fn_gl{CreateRenderbuffers}, eventually @fn_gl{GenRenderbuffers}
*/ */
@ -159,34 +163,40 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
* @param internalFormat Internal format * @param internalFormat Internal format
* @param size Renderbuffer size * @param size Renderbuffer size
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the renderbuffer is bound before the operation (if not already). * available, the renderbuffer is bound before the operation (if not
* already).
* @see @ref maxSize(), @fn_gl2{NamedRenderbufferStorage,RenderbufferStorage}, * @see @ref maxSize(), @fn_gl2{NamedRenderbufferStorage,RenderbufferStorage},
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}, * @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access},
* eventually @fn_gl{BindRenderbuffer} and @fn_gl{RenderbufferStorage} * eventually @fn_gl{BindRenderbuffer} and @fn_gl{RenderbufferStorage}
*/ */
void setStorage(RenderbufferFormat internalFormat, const Vector2i& size); void setStorage(RenderbufferFormat internalFormat, const Vector2i& size);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** /**
* @brief Set multisample renderbuffer storage * @brief Set multisample renderbuffer storage
* @param samples Sample count * @param samples Sample count
* @param internalFormat Internal format * @param internalFormat Internal format
* @param size Renderbuffer size * @param size Renderbuffer size
* *
* If on OpenGL ES or neither @extension{ARB,direct_state_access} (part * If neither @extension{ARB,direct_state_access} (part of OpenGL 4.5)
* of OpenGL 4.5) nor @extension{EXT,direct_state_access} is available, * nor @extension{EXT,direct_state_access} desktop extension is
* the renderbuffer is bound before the operation (if not already). * available, the renderbuffer is bound before the operation (if not
* already).
* @see @ref maxSize(), @ref maxSamples(), * @see @ref maxSize(), @ref maxSamples(),
* @fn_gl2{NamedRenderbufferStorageMultisample,RenderbufferStorageMultisample}, * @fn_gl2{NamedRenderbufferStorageMultisample,RenderbufferStorageMultisample},
* @fn_gl_extension{NamedRenderbufferStorageMultisample,EXT,direct_state_access}, * @fn_gl_extension{NamedRenderbufferStorageMultisample,EXT,direct_state_access},
* eventually @fn_gl{BindRenderbuffer} and @fn_gl{RenderbufferStorageMultisample} * eventually @fn_gl{BindRenderbuffer} and @fn_gl{RenderbufferStorageMultisample}
* @requires_gles30 Extension @es_extension{ANGLE,framebuffer_multisample} * @requires_gles30 Extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0 * or @es_extension{NV,framebuffer_multisample} in OpenGL ES 2.0.
* @requires_webgl20 Multisample framebuffers are not available in
* WebGL 1.0.
* @todo How about @es_extension{APPLE,framebuffer_multisample}? * @todo How about @es_extension{APPLE,framebuffer_multisample}?
* @todo NaCl has @fn_gl_extension{RenderbufferStorageMultisample,EXT,multisampled_render_to_texture} * @todo NaCl has @fn_gl_extension{RenderbufferStorageMultisample,EXT,multisampled_render_to_texture}
*/ */
void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size); void setStorageMultisample(Int samples, RenderbufferFormat internalFormat, const Vector2i& size);
#endif
private: private:
void MAGNUM_LOCAL createImplementationDefault(); void MAGNUM_LOCAL createImplementationDefault();
@ -212,7 +222,7 @@ class MAGNUM_EXPORT Renderbuffer: public AbstractObject {
void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
void MAGNUM_LOCAL storageMultisampleImplementationDSAEXT(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationDSAEXT(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#endif #endif
#else #elif !defined(MAGNUM_TARGET_WEBGL)
void MAGNUM_LOCAL storageMultisampleImplementationANGLE(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationANGLE(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
void MAGNUM_LOCAL storageMultisampleImplementationNV(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size); void MAGNUM_LOCAL storageMultisampleImplementationNV(GLsizei samples, RenderbufferFormat internalFormat, const Vector2i& size);
#endif #endif

Loading…
Cancel
Save