Browse Source

Merge branch 'master' into compatibility

Conflicts:
	src/AbstractFramebuffer.h
Vladimír Vondruš 13 years ago
parent
commit
bf8fb1adb7
  1. 1
      Doxyfile
  2. 2
      PKGBUILD-es2
  3. 7
      PKGBUILD-es2desktop
  4. 2
      PKGBUILD-es3
  5. 12
      doc/required-extensions.dox
  6. 2
      doc/unsupported.dox
  7. 82
      src/AbstractFramebuffer.cpp
  8. 84
      src/AbstractFramebuffer.h
  9. 6
      src/AbstractImage.cpp
  10. 10
      src/AbstractShaderProgram.cpp
  11. 497
      src/AbstractTexture.cpp
  12. 14
      src/AbstractTexture.h
  13. 26
      src/Context.cpp
  14. 12
      src/Context.h
  15. 13
      src/DefaultFramebuffer.cpp
  16. 45
      src/DefaultFramebuffer.h
  17. 15
      src/Extensions.h
  18. 23
      src/Framebuffer.cpp
  19. 79
      src/Framebuffer.h
  20. 6
      src/ImageFormat.cpp
  21. 36
      src/ImageFormat.h
  22. 1
      src/Platform/AbstractXApplication.h
  23. 3
      src/Renderbuffer.h
  24. 2
      src/RenderbufferFormat.h
  25. 47
      src/Renderer.cpp
  26. 74
      src/Renderer.h
  27. 5
      src/Shader.cpp
  28. 8
      src/Shaders/DistanceFieldVector.cpp
  29. 13
      src/Shaders/DistanceFieldVector.frag
  30. 11
      src/Shaders/DistanceFieldVector.h
  31. 4
      src/Shaders/Vector.cpp
  32. 5
      src/Shaders/Vector.frag
  33. 3
      src/Test/CMakeLists.txt
  34. 52
      src/Test/DefaultFramebufferTest.cpp
  35. 52
      src/Test/FramebufferTest.cpp
  36. 72
      src/Test/RendererTest.cpp
  37. 42
      src/Text/DistanceFieldGlyphCache.cpp
  38. 8
      src/Text/DistanceFieldGlyphCache.h
  39. 22
      src/Text/GlyphCache.cpp
  40. 9
      src/Text/GlyphCache.h
  41. 13
      src/Texture.h
  42. 167
      src/TextureFormat.h
  43. 128
      src/TextureTools/DistanceField.cpp
  44. 29
      src/TextureTools/DistanceField.h
  45. 86
      src/TextureTools/DistanceFieldShader.frag
  46. 8
      src/TextureTools/DistanceFieldShader.vert

1
Doxyfile

@ -220,6 +220,7 @@ ALIASES = \
"extension{2}=<a href=\"http://www.opengl.org/registry/specs/\1/\2.txt\"><tt>\1_\2</tt></a>" \
"requires_gles30=@xrefitem requires-gles30 \"Requires OpenGL ES 3.0\" \"Functionality requiring OpenGL ES 3.0\"" \
"requires_gl=@xrefitem requires-gl \"Requires desktop OpenGL\" \"Functionality requiring desktop OpenGL (not available in OpenGL ES)\"" \
"requires_gles20=@xrefitem requires-gles20 \"Requires OpenGL ES 2.0\" \"Functionality requiring OpenGL ES 2.0 (not available in ES 3.0 and desktop OpenGL)\"" \
"requires_es_extension=@xrefitem requires-es-extension \"Requires OpenGL ES extension\" \"Functionality requiring specific OpenGL ES extension\"" \
"es_extension{2}=<a href=\"http://www.khronos.org/registry/gles/extensions/\1/\1_\2.txt\"><tt>\1_\2</tt></a>" \
"es_extension2{3}=<a href=\"http://www.khronos.org/registry/gles/extensions/\1/\3.txt\"><tt>\1_\2</tt></a>"

2
PKGBUILD-es2

@ -26,8 +26,6 @@ build() {
-DBUILD_TESTS=ON \
-DTARGET_GLES=ON \
-DTARGET_GLES2=ON \
-DWITH_TEXT=OFF \
-DWITH_TEXTURETOOLS=OFF \
-DWITH_MAGNUMINFO=OFF \
-DWITH_XEGLAPPLICATION=ON
make

7
PKGBUILD-es2desktop

@ -27,10 +27,9 @@ build() {
-DTARGET_GLES=ON \
-DTARGET_GLES2=ON \
-DTARGET_DESKTOP_GLES=ON \
-DWITH_TEXT=OFF \
-DWITH_TEXTURETOOLS=OFF \
-DWITH_MAGNUMINFO=OFF \
-DWITH_XEGLAPPLICATION=ON
-DWITH_MAGNUMINFO=ON \
-DWITH_GLXAPPLICATION=ON \
-DWITH_WINDOWLESSGLXAPPLICATION=ON
make
}

2
PKGBUILD-es3

@ -26,8 +26,6 @@ build() {
-DBUILD_TESTS=ON \
-DTARGET_GLES=ON \
-DTARGET_GLES2=OFF \
-DWITH_TEXT=OFF \
-DWITH_TEXTURETOOLS=OFF \
-DWITH_MAGNUMINFO=OFF \
-DWITH_XEGLAPPLICATION=ON
make

12
doc/required-extensions.dox

@ -48,13 +48,11 @@ supported on Intel GPUs even if they are capable of OpenGL 2.1 only).
- @subpage requires-gl43
- @subpage requires-extension
- @subpage requires-gl
- @subpage requires-gles20
- @subpage requires-gles30
- @subpage requires-es-extension
- @subpage unsupported
@page requires-gl Functionality requiring desktop OpenGL (not available on OpenGL ES)
@see @ref MAGNUM_TARGET_GLES_ "MAGNUM_TARGET_GLES"
@page requires-gl30 Functionality requiring OpenGL 3.0
@page requires-gl31 Functionality requiring OpenGL 3.1
@page requires-gl32 Functionality requiring OpenGL 3.2
@ -66,9 +64,15 @@ supported on Intel GPUs even if they are capable of OpenGL 2.1 only).
@page requires-extension Functionality requiring specific OpenGL extension
@page requires-gles30 Functionality requiring OpenGL ES 3.0
@page requires-gl Functionality requiring desktop OpenGL (not available on OpenGL ES)
@see @ref MAGNUM_TARGET_GLES_ "MAGNUM_TARGET_GLES"
@page requires-gles20 Functionality requiring OpenGL ES 2.0 (not available in ES 3.0 and desktop OpenGL)
@see @ref MAGNUM_TARGET_GLES2_ "MAGNUM_TARGET_GLES2"
@page requires-gles30 Functionality requiring OpenGL ES 3.0
@see @ref MAGNUM_TARGET_GLES3_ "MAGNUM_TARGET_GLES3"
@page requires-es-extension Functionality requiring specific OpenGL ES extension
@see @ref MAGNUM_TARGET_GLES2_ "MAGNUM_TARGET_GLES2"

2
doc/unsupported.dox

@ -29,8 +29,6 @@ add any performance gains, is not supported in %Magnum.
@section unsupported-features Unsupported features
- Luminance texture formats (OpenGL ES) are not supported, as they are
deprecated in OpenGL ES 3.0 and not present in core desktop OpenGL.
- Fixed precision data types (OpenGL ES) are not supported, as they occupy the
same memory as floats and they aren't faster than floats on current hardware
anymore.

82
src/AbstractFramebuffer.cpp

@ -34,16 +34,18 @@
namespace Magnum {
AbstractFramebuffer::CheckStatusImplementation AbstractFramebuffer::checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault;
AbstractFramebuffer::ReadImplementation AbstractFramebuffer::readImplementation = &AbstractFramebuffer::readImplementationDefault;
AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault;
AbstractFramebuffer::DrawBufferImplementation AbstractFramebuffer::drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
AbstractFramebuffer::ReadBufferImplementation AbstractFramebuffer::readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;
#ifdef MAGNUM_TARGET_GLES2
FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw;
FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw;
AbstractFramebuffer::~AbstractFramebuffer() {}
#endif
void AbstractFramebuffer::bind(FramebufferTarget target) {
bindInternal(target);
@ -81,10 +83,15 @@ FramebufferTarget AbstractFramebuffer::bindInternal() {
/* Or bind it, if not already */
state->readBinding = _id;
if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
#ifndef MAGNUM_TARGET_GLES2
glBindFramebuffer(GLenum(FramebufferTarget::Read), _id);
return FramebufferTarget::Read;
#else
if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
glBindFramebuffer(GLenum(readTarget), _id);
return readTarget;
#endif
}
void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Rectanglei& sourceRectangle, const Rectanglei& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter) {
@ -126,12 +133,20 @@ void AbstractFramebuffer::setViewportInternal() {
}
void AbstractFramebuffer::clear(FramebufferClearMask mask) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else
bindInternal(drawTarget);
#endif
glClear(static_cast<GLbitfield>(mask));
}
void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Image2D* image) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Read);
#else
bindInternal(readTarget);
#endif
const std::size_t dataSize = image->pixelSize()*size.product();
char* const data = new char[dataSize];
readImplementation(offset, size, image->format(), image->type(), dataSize, data);
@ -140,7 +155,11 @@ void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Ima
#ifndef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, BufferImage2D* image, Buffer::Usage usage) {
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Read);
#else
bindInternal(readTarget);
#endif
/* If the buffer doesn't have sufficient size, resize it */
/** @todo Explicitly reset also when buffer usage changes */
if(image->size() != size)
@ -177,22 +196,42 @@ void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attach
void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context) {
#ifndef MAGNUM_TARGET_GLES
if(context->isExtensionSupported<Extensions::GL::EXT::framebuffer_blit>()) {
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::framebuffer_blit::string() << "features";
readTarget = FramebufferTarget::Read;
drawTarget = FramebufferTarget::Draw;
}
if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";
checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA;
drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA;
drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA;
readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA;
}
#endif
#ifdef MAGNUM_TARGET_GLES2
/* Optimistically set separate binding targets and check if one of the
extensions providing them is available */
readTarget = FramebufferTarget::Read;
drawTarget = FramebufferTarget::Draw;
if(context->isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::ANGLE::framebuffer_blit::string() << "features";
else if(context->isExtensionSupported<Extensions::GL::APPLE::framebuffer_multisample>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::APPLE::framebuffer_multisample::string() << "features";
else if(context->isExtensionSupported<Extensions::GL::NV::framebuffer_blit>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_blit::string() << "features";
/* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these
enums. However, on my system only NV_framebuffer_multisample is
supported, but NV_framebuffer_blit isn't. I will hold my breath and
assume these enums are available. */
else if(context->isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>())
Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_multisample::string() << "features";
/* If no such extension is available, reset back to unified target */
else readTarget = drawTarget = FramebufferTarget::ReadDraw;
#endif
#ifndef MAGNUM_TARGET_GLES3
#ifndef MAGNUM_TARGET_GLES
if(context->isExtensionSupported<Extensions::GL::ARB::robustness>())
@ -216,10 +255,25 @@ void AbstractFramebuffer::initializeContextBasedFunctionality(Context* context)
#endif
}
GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) {
bindInternal(target);
return glCheckFramebufferStatus(GLenum(target));
}
#ifndef MAGNUM_TARGET_GLES
GLenum AbstractFramebuffer::checkStatusImplementationDSA(const FramebufferTarget target) {
return glCheckNamedFramebufferStatusEXT(_id, GLenum(target));
}
#endif
void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers) {
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else
bindInternal(drawTarget);
#endif
glDrawBuffers(count, buffers);
#else
static_cast<void>(count);
@ -236,7 +290,11 @@ void AbstractFramebuffer::drawBuffersImplementationDSA(GLsizei count, const GLen
void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) {
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Draw);
#else
bindInternal(drawTarget);
#endif
#ifndef MAGNUM_TARGET_GLES3
glDrawBuffer(buffer);
#else
@ -256,7 +314,11 @@ void AbstractFramebuffer::drawBufferImplementationDSA(GLenum buffer) {
void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
/** @todo Get some extension wrangler instead to avoid undeclared glReadBuffer() on ES2 */
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES2
bindInternal(FramebufferTarget::Read);
#else
bindInternal(readTarget);
#endif
glReadBuffer(buffer);
#else
static_cast<void>(buffer);

84
src/AbstractFramebuffer.h

@ -40,10 +40,10 @@
namespace Magnum {
/**
* @brief Mask for framebuffer clearing
*
* @see AbstractFramebuffer, FramebufferClearMask
*/
@brief Mask for framebuffer clearing
@see AbstractFramebuffer, FramebufferClearMask
*/
enum class FramebufferClear: GLbitfield {
Color = GL_COLOR_BUFFER_BIT, /**< Color */
Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value */
@ -51,21 +51,21 @@ enum class FramebufferClear: GLbitfield {
};
/**
* @brief Mask for clearing
*
* @see AbstractFramebuffer::clear()
*/
@brief Mask for clearing
@see AbstractFramebuffer::clear()
*/
typedef Containers::EnumSet<FramebufferClear, GLbitfield,
GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT> FramebufferClearMask;
/**
* @brief Mask for framebuffer blitting
*
* @see AbstractFramebuffer, FramebufferBlitMask
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
*/
@brief Mask for framebuffer blitting
@see AbstractFramebuffer, FramebufferBlitMask
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
*/
enum class FramebufferBlit: GLbitfield {
ColorBuffer = GL_COLOR_BUFFER_BIT, /**< Color buffer */
DepthBuffer = GL_DEPTH_BUFFER_BIT, /**< Depth buffer */
@ -73,36 +73,38 @@ enum class FramebufferBlit: GLbitfield {
};
/**
* @brief Mask for framebuffer blitting
*
* @see AbstractFramebuffer::blit()
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
*/
@brief Mask for framebuffer blitting
@see AbstractFramebuffer::blit()
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
*/
typedef Containers::EnumSet<FramebufferBlit, GLbitfield,
GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT> FramebufferBlitMask;
/**
* @brief %Framebuffer blit filtering
*
* @see AbstractFramebuffer::blit()
*/
@brief %Framebuffer blit filtering
@see AbstractFramebuffer::blit()
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
@requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
@es_extension{NV,framebuffer_blit}
*/
enum class FramebufferBlitFilter: GLenum {
Nearest = GL_NEAREST, /**< Nearest neighbor filtering */
Linear = GL_LINEAR /**< Linear interpolation filtering */
};
/**
* @brief Target for binding framebuffer
*
* @see DefaultFramebuffer::bind(), Framebuffer::bind()
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
*/
@brief Target for binding framebuffer
@see DefaultFramebuffer::bind(), Framebuffer::bind()
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
enum class FramebufferTarget: GLenum {
/**
* For reading only.
* @requires_gl30 %Extension @extension{EXT,framebuffer_blit}
* @requires_gles30 %Extension @es_extension{APPLE,framebuffer_multisample},
* @es_extension{ANGLE,framebuffer_blit} or @es_extension{NV,framebuffer_blit}
*/
@ -114,7 +116,6 @@ enum class FramebufferTarget: GLenum {
/**
* For drawing only.
* @requires_gl30 %Extension @extension{EXT,framebuffer_blit}
* @requires_gles30 %Extension @es_extension{APPLE,framebuffer_multisample},
* @es_extension{ANGLE,framebuffer_blit} or @es_extension{NV,framebuffer_blit}
*/
@ -167,7 +168,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* Framebuffer::mapForDraw() for specifying particular buffers for
* blitting operation.
* @see @fn_gl{BlitFramebuffer}
* @requires_gl30 %Extension @extension{EXT,framebuffer_blit}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
*/
@ -186,7 +186,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* @ref FramebufferBlitFilter "FramebufferBlitFilter::Nearest"
* filtering is used by default.
* @see @fn_gl{BlitFramebuffer}
* @requires_gl30 %Extension @extension{EXT,framebuffer_blit}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_blit} or
* @es_extension{NV,framebuffer_blit}
*/
@ -195,7 +194,6 @@ class MAGNUM_EXPORT AbstractFramebuffer {
}
explicit AbstractFramebuffer();
virtual ~AbstractFramebuffer() = 0;
/**
* @brief Bind framebuffer for rendering
@ -205,6 +203,8 @@ class MAGNUM_EXPORT AbstractFramebuffer {
* Framebuffer::mapForRead(), DefaultFramebuffer::mapForDraw(),
* Framebuffer::mapForDraw(), @fn_gl{BindFramebuffer},
* @fn_gl{Viewport}
* @todo Bind internally to ReadDraw if separate binding points are not
* supported
*/
void bind(FramebufferTarget target);
@ -272,12 +272,19 @@ class MAGNUM_EXPORT AbstractFramebuffer {
#else
protected:
#endif
~AbstractFramebuffer() = default;
void MAGNUM_LOCAL bindInternal(FramebufferTarget target);
FramebufferTarget MAGNUM_LOCAL bindInternal();
void MAGNUM_LOCAL setViewportInternal();
#ifdef MAGNUM_TARGET_GLES2
static MAGNUM_LOCAL FramebufferTarget readTarget;
static MAGNUM_LOCAL FramebufferTarget drawTarget;
#endif
typedef GLenum(AbstractFramebuffer::*CheckStatusImplementation)(FramebufferTarget);
static CheckStatusImplementation checkStatusImplementation;
typedef void(AbstractFramebuffer::*DrawBuffersImplementation)(GLsizei, const GLenum*);
static MAGNUM_LOCAL DrawBuffersImplementation drawBuffersImplementation;
@ -297,6 +304,11 @@ class MAGNUM_EXPORT AbstractFramebuffer {
private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
GLenum MAGNUM_LOCAL checkStatusImplementationDefault(FramebufferTarget target);
#ifndef MAGNUM_TARGET_GLES
GLenum MAGNUM_LOCAL checkStatusImplementationDSA(FramebufferTarget target);
#endif
void MAGNUM_LOCAL drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers);

6
src/AbstractImage.cpp

@ -99,11 +99,17 @@ std::size_t AbstractImage::pixelSize(ImageFormat format, ImageType type) {
case ImageFormat::Blue:
case ImageFormat::GreenInteger:
case ImageFormat::BlueInteger:
#endif
#ifdef MAGNUM_TARGET_GLES2
case ImageFormat::Luminance:
#endif
return 1*size;
case ImageFormat::RG:
#ifndef MAGNUM_TARGET_GLES2
case ImageFormat::RGInteger:
#endif
#ifdef MAGNUM_TARGET_GLES2
case ImageFormat::LuminanceAlpha:
#endif
return 2*size;
case ImageFormat::RGB:

10
src/AbstractShaderProgram.cpp

@ -116,10 +116,9 @@ std::pair<bool, std::string> AbstractShaderProgram::validate() {
/* Error or warning message. The string is returned null-terminated, scrap
the \0 at the end afterwards */
std::string message(logLength, '\n');
if(!message.empty()) {
if(message.size() > 1)
glGetProgramInfoLog(_id, message.size(), nullptr, &message[0]);
message.resize(logLength-1);
}
message.resize(std::max(logLength, 1)-1);
return {success, std::move(message)};
}
@ -159,10 +158,9 @@ bool AbstractShaderProgram::link() {
/* Error or warning message. The string is returned null-terminated, scrap
the \0 at the end afterwards */
std::string message(logLength, '\n');
if(!message.empty()) {
if(message.size() > 1)
glGetProgramInfoLog(_id, message.size(), nullptr, &message[0]);
message.resize(logLength-1);
}
message.resize(std::max(logLength, 1)-1);
/* Show error log and delete shader */
if(!success) {

497
src/AbstractTexture.cpp

@ -29,6 +29,8 @@
#include "Context.h"
#include "Extensions.h"
#include "Image.h"
#include "ImageFormat.h"
#include "TextureFormat.h"
#include "Implementation/State.h"
#include "Implementation/TextureState.h"
@ -50,12 +52,12 @@ AbstractTexture::MipmapImplementation AbstractTexture::mipmapImplementation =
&AbstractTexture::mipmapImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::Storage1DImplementation AbstractTexture::storage1DImplementation =
&AbstractTexture::storageImplementationDefault;
&AbstractTexture::storageImplementationFallback;
#endif
AbstractTexture::Storage2DImplementation AbstractTexture::storage2DImplementation =
&AbstractTexture::storageImplementationDefault;
&AbstractTexture::storageImplementationFallback;
AbstractTexture::Storage3DImplementation AbstractTexture::storage3DImplementation =
&AbstractTexture::storageImplementationDefault;
&AbstractTexture::storageImplementationFallback;
#ifndef MAGNUM_TARGET_GLES
AbstractTexture::GetImageImplementation AbstractTexture::getImageImplementation =
&AbstractTexture::getImageImplementationDefault;
@ -205,9 +207,6 @@ void AbstractTexture::initializeContextBasedFunctionality(Context* context) {
parameterfvImplementation = &AbstractTexture::parameterImplementationDSA;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA;
storage1DImplementation = &AbstractTexture::storageImplementationDSA;
storage2DImplementation = &AbstractTexture::storageImplementationDSA;
storage3DImplementation = &AbstractTexture::storageImplementationDSA;
getImageImplementation = &AbstractTexture::getImageImplementationDSA;
image1DImplementation = &AbstractTexture::imageImplementationDSA;
image2DImplementation = &AbstractTexture::imageImplementationDSA;
@ -230,9 +229,396 @@ void AbstractTexture::initializeContextBasedFunctionality(Context* context) {
getImageImplementation = &AbstractTexture::getImageImplementationRobustness;
}
if(context->isExtensionSupported<Extensions::GL::ARB::texture_storage>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::ARB::texture_storage::string() << "features";
if(context->isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
storage1DImplementation = &AbstractTexture::storageImplementationDSA;
storage2DImplementation = &AbstractTexture::storageImplementationDSA;
storage3DImplementation = &AbstractTexture::storageImplementationDSA;
} else {
storage1DImplementation = &AbstractTexture::storageImplementationDefault;
storage2DImplementation = &AbstractTexture::storageImplementationDefault;
storage3DImplementation = &AbstractTexture::storageImplementationDefault;
}
}
#endif
}
ImageFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) {
switch(internalFormat) {
case TextureFormat::Red:
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8:
case TextureFormat::R8Snorm:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::R16:
case TextureFormat::R16Snorm:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R16F:
case TextureFormat::R32F:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::CompressedRed:
case TextureFormat::CompressedRedRtgc1:
case TextureFormat::CompressedSignedRedRgtc1:
#endif
return ImageFormat::Red;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8UI:
case TextureFormat::R8I:
case TextureFormat::R16UI:
case TextureFormat::R16I:
case TextureFormat::R32UI:
case TextureFormat::R32I:
return ImageFormat::RedInteger;
#endif
case TextureFormat::RG:
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RG8:
case TextureFormat::RG8Snorm:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RG16:
case TextureFormat::RG16Snorm:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RG16F:
case TextureFormat::RG32F:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::CompressedRG:
case TextureFormat::CompressedRGRgtc2:
case TextureFormat::CompressedSignedRGRgtc2:
#endif
return ImageFormat::RG;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RG8UI:
case TextureFormat::RG8I:
case TextureFormat::RG16UI:
case TextureFormat::RG16I:
case TextureFormat::RG32UI:
case TextureFormat::RG32I:
return ImageFormat::RGInteger;
#endif
case TextureFormat::RGB:
case TextureFormat::RGB8:
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB8Snorm:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGB16:
case TextureFormat::RGB16Snorm:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB16F:
case TextureFormat::RGB32F:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::R3B3G2:
case TextureFormat::RGB4:
case TextureFormat::RGB5:
#endif
case TextureFormat::RGB565:
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::RGB10:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGB12:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R11FG11FB10F:
case TextureFormat::RGB9E5:
#endif
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::SRGB:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::SRGB8:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::CompressedRGB:
case TextureFormat::CompressedRGBBptcUnsignedFloat:
case TextureFormat::CompressedRGBBptcSignedFloat:
#endif
return ImageFormat::RGB;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB8UI:
case TextureFormat::RGB8I:
case TextureFormat::RGB16UI:
case TextureFormat::RGB16I:
case TextureFormat::RGB32UI:
case TextureFormat::RGB32I:
return ImageFormat::RGBInteger;
#endif
case TextureFormat::RGBA:
case TextureFormat::RGBA8:
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGBA8Snorm:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGBA16:
case TextureFormat::RGBA16Snorm:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGBA16F:
case TextureFormat::RGBA32F:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGBA2:
#endif
case TextureFormat::RGBA4:
case TextureFormat::RGB5A1:
case TextureFormat::RGB10A2:
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGBA12:
#endif
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::SRGBAlpha:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::SRGB8Alpha8:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::CompressedRGBA:
case TextureFormat::CompressedRGBABptcUnorm:
case TextureFormat::CompressedSRGBAlphaBptcUnorm:
#endif
return ImageFormat::RGBA;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGBA8UI:
case TextureFormat::RGBA8I:
case TextureFormat::RGBA16UI:
case TextureFormat::RGBA16I:
case TextureFormat::RGBA32UI:
case TextureFormat::RGBA32I:
case TextureFormat::RGB10A2UI:
return ImageFormat::RGBAInteger;
#endif
#ifdef MAGNUM_TARGET_GLES2
case TextureFormat::Luminance:
return ImageFormat::Luminance;
case TextureFormat::LuminanceAlpha:
return ImageFormat::LuminanceAlpha;
#endif
case TextureFormat::DepthComponent:
case TextureFormat::DepthComponent16:
case TextureFormat::DepthComponent24:
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::DepthComponent32:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::DepthComponent32F:
#endif
return ImageFormat::DepthComponent;
case TextureFormat::DepthStencil:
case TextureFormat::Depth24Stencil8:
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::Depth32FStencil8:
#endif
return ImageFormat::DepthStencil;
}
CORRADE_ASSERT_UNREACHABLE();
}
ImageType AbstractTexture::imageTypeForInternalFormat(const TextureFormat internalFormat) {
switch(internalFormat) {
case TextureFormat::Red:
case TextureFormat::RG:
case TextureFormat::RGB:
case TextureFormat::RGBA:
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8:
case TextureFormat::RG8:
#endif
case TextureFormat::RGB8:
case TextureFormat::RGBA8:
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8UI:
case TextureFormat::RG8UI:
case TextureFormat::RGB8UI:
case TextureFormat::RGBA8UI:
#endif
#ifdef MAGNUM_TARGET_GLES2
case TextureFormat::Luminance:
case TextureFormat::LuminanceAlpha:
#endif
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::SRGB:
case TextureFormat::SRGBAlpha:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::SRGB8:
case TextureFormat::SRGB8Alpha8:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGBA2: /**< @todo really? */
case TextureFormat::CompressedRed:
case TextureFormat::CompressedRG:
case TextureFormat::CompressedRGB:
case TextureFormat::CompressedRGBA:
case TextureFormat::CompressedRedRtgc1:
case TextureFormat::CompressedRGRgtc2:
case TextureFormat::CompressedRGBABptcUnorm:
case TextureFormat::CompressedSRGBAlphaBptcUnorm:
#endif
return ImageType::UnsignedByte;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R8Snorm:
case TextureFormat::RG8Snorm:
case TextureFormat::RGB8Snorm:
case TextureFormat::RGBA8Snorm:
case TextureFormat::R8I:
case TextureFormat::RG8I:
case TextureFormat::RGB8I:
case TextureFormat::RGBA8I:
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::CompressedSignedRedRgtc1:
case TextureFormat::CompressedSignedRGRgtc2:
#endif
return ImageType::Byte;
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::R16:
case TextureFormat::RG16:
case TextureFormat::RGB16:
case TextureFormat::RGBA16:
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R16UI:
case TextureFormat::RG16UI:
case TextureFormat::RGB16UI:
case TextureFormat::RGBA16UI:
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGB12: /**< @todo really? */
#endif
case TextureFormat::RGBA4: /**< @todo really? */
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGBA12: /**< @todo really? */
#endif
return ImageType::UnsignedShort;
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::R16Snorm:
case TextureFormat::RG16Snorm:
case TextureFormat::RGB16Snorm:
case TextureFormat::RGBA16Snorm:
#endif
case TextureFormat::R16I:
case TextureFormat::RG16I:
case TextureFormat::RGB16I:
case TextureFormat::RGBA16I:
return ImageType::Short;
#endif
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R16F:
case TextureFormat::RG16F:
case TextureFormat::RGB16F:
case TextureFormat::RGBA16F:
return ImageType::HalfFloat;
case TextureFormat::R32UI:
case TextureFormat::RG32UI:
case TextureFormat::RGB32UI:
case TextureFormat::RGBA32UI:
return ImageType::UnsignedInt;
case TextureFormat::R32I:
case TextureFormat::RG32I:
case TextureFormat::RGB32I:
case TextureFormat::RGBA32I:
return ImageType::Int;
case TextureFormat::R32F:
case TextureFormat::RG32F:
case TextureFormat::RGB32F:
case TextureFormat::RGBA32F:
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::CompressedRGBBptcUnsignedFloat:
case TextureFormat::CompressedRGBBptcSignedFloat:
#endif
return ImageType::Float;
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::R3B3G2:
return ImageType::UnsignedByte332;
case TextureFormat::RGB4:
return ImageType::UnsignedShort4444;
#endif
#ifndef MAGNUM_TARGET_GLES
case TextureFormat::RGB5:
#endif
case TextureFormat::RGB5A1:
return ImageType::UnsignedShort5551;
case TextureFormat::RGB565:
return ImageType::UnsignedShort565;
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::RGB10:
#endif
case TextureFormat::RGB10A2:
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::RGB10A2UI:
#endif
return ImageType::UnsignedInt2101010Rev; /**< @todo Rev for all? */
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::R11FG11FB10F:
return ImageType::UnsignedInt10F11F11FRev;
case TextureFormat::RGB9E5:
return ImageType::UnsignedInt5999Rev;
#endif
case TextureFormat::DepthComponent16:
return ImageType::UnsignedShort;
case TextureFormat::DepthComponent:
case TextureFormat::DepthComponent24:
#ifndef MAGNUM_TARGET_GLES3
case TextureFormat::DepthComponent32:
#endif
return ImageType::UnsignedInt;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::DepthComponent32F:
return ImageType::Float;
#endif
case TextureFormat::DepthStencil:
case TextureFormat::Depth24Stencil8:
return ImageType::UnsignedInt248;
#ifndef MAGNUM_TARGET_GLES2
case TextureFormat::Depth32FStencil8:
return ImageType::Float32UnsignedInt248Rev;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
void AbstractTexture::parameterImplementationDefault(GLenum parameter, GLint value) {
bindInternal();
glTexParameteri(_target, parameter, value);
@ -278,7 +664,20 @@ void AbstractTexture::getLevelParameterImplementationDSA(GLenum target, GLint le
#endif
#ifndef MAGNUM_TARGET_GLES
void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) {
void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) {
CORRADE_INTERNAL_ASSERT(target == GL_TEXTURE_1D);
const ImageFormat format = imageFormatForInternalFormat(internalFormat);
const ImageType type = imageTypeForInternalFormat(internalFormat);
auto levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
(this->*image1DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
levelSize = Math::max(Math::Vector<1, GLsizei>(1), levelSize/2);
}
}
void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) {
bindInternal();
/** @todo Re-enable when extension wrangler is available for ES2 */
#ifndef MAGNUM_TARGET_GLES2
@ -292,11 +691,56 @@ void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels
#endif
}
void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) {
void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size) {
glTextureStorage1DEXT(_id, target, levels, GLenum(internalFormat), size[0]);
}
#endif
void AbstractTexture::storageImplementationFallback(const GLenum target, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) {
const ImageFormat format = imageFormatForInternalFormat(internalFormat);
const ImageType type = imageTypeForInternalFormat(internalFormat);
/* Common code for classic types */
#ifndef MAGNUM_TARGET_GLES
if(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE)
#else
if(target == GL_TEXTURE_2D)
#endif
{
Vector2i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
(this->*image2DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
levelSize = Math::max(Vector2i(1), levelSize/2);
}
/* Cube map additionaly needs to specify all faces */
} else if(target == GL_TEXTURE_CUBE_MAP) {
Vector2i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
for(GLenum face: {GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z})
(this->*image2DImplementation)(face, level, internalFormat, levelSize, format, type, nullptr);
levelSize = Math::max(Vector2i(1), levelSize/2);
}
#ifndef MAGNUM_TARGET_GLES
/* Array texture is not scaled in "layer" dimension */
} else if(target == GL_TEXTURE_1D_ARRAY) {
Vector2i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
(this->*image2DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
levelSize.x() = Math::max(1, levelSize.x()/2);
}
#endif
/* No other targets are available */
} else CORRADE_ASSERT_UNREACHABLE();
}
void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size) {
bindInternal();
/** @todo Re-enable when extension wrangler is available for ES2 */
@ -317,6 +761,43 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te
}
#endif
void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) {
const ImageFormat format = imageFormatForInternalFormat(internalFormat);
const ImageType type = imageTypeForInternalFormat(internalFormat);
/* Common code for classic type */
#ifndef MAGNUM_TARGET_GLES2
if(target == GL_TEXTURE_3D)
#else
if(target == GL_TEXTURE_3D_OES)
#endif
{
Vector3i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
(this->*image3DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
levelSize = Math::max(Vector3i(1), levelSize/2);
}
#ifndef MAGNUM_TARGET_GLES2
/* Array texture is not scaled in "layer" dimension */
}
#ifndef MAGNUM_TARGET_GLES
else if(target == GL_TEXTURE_2D_ARRAY || target == GL_TEXTURE_CUBE_MAP_ARRAY)
#else
else if(target == GL_TEXTURE_2D_ARRAY)
#endif
{
Vector3i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
(this->*image3DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
levelSize.xy() = Math::max(Vector2i(1), levelSize.xy()/2);
}
#endif
/* No other targets are available */
} else CORRADE_ASSERT_UNREACHABLE();
}
void AbstractTexture::storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size) {
bindInternal();
/** @todo Re-enable when extension wrangler is available for ES2 */

14
src/AbstractTexture.h

@ -77,6 +77,13 @@ avoid redundant consistency checks and memory reallocations when updating
texture data, set texture storage at once using @ref Texture::setStorage() "setStorage()"
and then set data using @ref Texture::setSubImage() "setSubImage()".
Function @ref Texture::setStorage() "setStorage()" creates immutable texture
storage, removing the need for additional consistency checks and memory
reallocations when updating the data later. If OpenGL 4.2, @extension{ARB,texture_storage},
OpenGL ES 3.0 or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not
available, the feature is emulated with sequence of @ref Texture::setImage() "setImage()"
calls.
You can use functions invalidateImage() and @ref Texture::invalidateSubImage() "invalidateSubImage()"
if you don't need texture data anymore to avoid unnecessary memory operations
performed by OpenGL in order to preserve the data. If running on OpenGL ES or
@ -251,7 +258,7 @@ class MAGNUM_EXPORT AbstractTexture {
* @see setMinificationFilter(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{GenerateMipmap} or
* @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{EXT,framebuffer_object}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
AbstractTexture* generateMipmap();
@ -319,12 +326,14 @@ class MAGNUM_EXPORT AbstractTexture {
#ifndef MAGNUM_TARGET_GLES
typedef void(AbstractTexture::*Storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&);
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size);
static Storage1DImplementation storage1DImplementation;
#endif
typedef void(AbstractTexture::*Storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&);
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size);
@ -332,6 +341,7 @@ class MAGNUM_EXPORT AbstractTexture {
static Storage2DImplementation storage2DImplementation;
typedef void(AbstractTexture::*Storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&);
void MAGNUM_LOCAL storageImplementationFallback(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
void MAGNUM_LOCAL storageImplementationDefault(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
@ -404,6 +414,8 @@ class MAGNUM_EXPORT AbstractTexture {
void MAGNUM_LOCAL destroy();
void MAGNUM_LOCAL move();
ImageFormat MAGNUM_LOCAL imageFormatForInternalFormat(TextureFormat internalFormat);
ImageType MAGNUM_LOCAL imageTypeForInternalFormat(TextureFormat internalFormat);
GLuint _id;
};

26
src/Context.cpp

@ -97,14 +97,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,ARB,texture_float), // done
_extension(GL,ARB,depth_buffer_float), // done
_extension(GL,ARB,texture_rg), // done
/**
* @todo Remove as it doesn't have the same functionality present in
* GL 3.0 and replace with ARB_framebuffer_object?
*/
_extension(GL,EXT,framebuffer_object),
_extension(GL,EXT,packed_depth_stencil), // done
_extension(GL,EXT,framebuffer_blit), // done
_extension(GL,EXT,framebuffer_multisample),
_extension(GL,ARB,framebuffer_object),
_extension(GL,EXT,gpu_shader4),
_extension(GL,EXT,packed_float), // done
_extension(GL,EXT,texture_array),
@ -213,7 +206,13 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,disjoint_timer_query),
_extension(GL,EXT,separate_shader_objects),
_extension(GL,EXT,sRGB),
/**
* @todo Support also IMG_multisampled_render_to_texture? It has
* different enum values (!)
*/
_extension(GL,EXT,multisampled_render_to_texture),
_extension(GL,EXT,robustness),
_extension(GL,KHR,debug),
_extension(GL,NV,read_buffer_front),
_extension(GL,NV,read_stencil),
_extension(GL,NV,texture_border_clamp), // done
@ -253,7 +252,8 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,OES,depth_texture),
_extension(GL,OES,standard_derivatives), // done
_extension(GL,OES,vertex_array_object),
_extension(GL,OES,required_internalformat)};
_extension(GL,OES,required_internalformat),
_extension(GL,OES,surfaceless_context)}; // done
#endif
switch(version) {
@ -292,6 +292,14 @@ Context::Context() {
#endif
_version = static_cast<Version>(_majorVersion*100+_minorVersion*10);
#ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(isVersionSupported(Version::GL210), "Context: unsupported OpenGL version" << Int(_version), );
#elif defined(MAGNUM_TARGET_GLES2)
CORRADE_ASSERT(isVersionSupported(Version::GLES200), "Context: unsupported OpenGL ES version" << Int(_version), );
#else
CORRADE_ASSERT(isVersionSupported(Version::GLES300), "Context: unsupported OpenGL ES version" << Int(_version), );
#endif
/* Context flags are supported since GL 3.0 */
#ifndef MAGNUM_TARGET_GLES
/**

12
src/Context.h

@ -382,8 +382,8 @@ class MAGNUM_EXPORT Context {
Useful for initial checks on availability of required features.
By default, if assertion fails, an message is printed to error output and the
application exits with value `-3`. If `CORRADE_NO_ASSERT` is defined, this
macro does nothing. Example usage:
application aborts. If `CORRADE_NO_ASSERT` is defined, this macro does nothing.
Example usage:
@code
MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL330);
@endcode
@ -399,7 +399,7 @@ MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL330);
do { \
if(!Magnum::Context::current()->isVersionSupported(version)) { \
Corrade::Utility::Error() << "Magnum: required version" << version << "is not supported"; \
std::exit(-3); \
std::abort(); \
} \
} while(0)
#endif
@ -412,8 +412,8 @@ MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL330);
Useful for initial checks on availability of required features.
By default, if assertion fails, an message is printed to error output and the
application exits with value `-3`. If `CORRADE_NO_ASSERT` is defined, this
macro does nothing. Example usage:
application aborts. If `CORRADE_NO_ASSERT` is defined, this macro does nothing.
Example usage:
@code
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4);
@endcode
@ -429,7 +429,7 @@ MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4);
do { \
if(!Magnum::Context::current()->isExtensionSupported<extension>()) { \
Corrade::Utility::Error() << "Magnum: required extension" << extension::string() << "is not supported"; \
std::exit(-3); \
std::abort(); \
} \
} while(0)
#endif

13
src/DefaultFramebuffer.cpp

@ -90,4 +90,17 @@ void DefaultFramebuffer::initializeContextBasedFunctionality(Context* context) {
#endif
}
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, const DefaultFramebuffer::Status value) {
switch(value) {
#define _c(value) case DefaultFramebuffer::Status::value: return debug << "DefaultFramebuffer::Status::" #value;
_c(Complete)
_c(Undefined)
#undef _c
}
return debug << "DefaultFramebuffer::Status::(invalid)";
}
#endif
}

45
src/DefaultFramebuffer.h

@ -80,6 +80,27 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
friend class Context;
public:
/**
* @brief Status
*
* @see checkStatus()
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
enum class Status: GLenum {
/** The framebuffer is complete */
Complete = GL_FRAMEBUFFER_COMPLETE,
/**
* The default framebuffer does not exist.
* @requires_es_extension %Extension @es_extension{OES,surfaceless_context}
*/
#ifndef MAGNUM_TARGET_GLES2
Undefined = GL_FRAMEBUFFER_UNDEFINED
#else
Undefined = GL_FRAMEBUFFER_UNDEFINED_OES
#endif
};
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Draw attachment
@ -270,6 +291,21 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
explicit MAGNUM_LOCAL DefaultFramebuffer();
/**
* @brief Check framebuffer status
* @param target Target for which to check the status
*
* If @extension{EXT,direct_state_access} is not available and the
* framebuffer is not currently bound, it is bound before the
* operation.
* @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
Status checkStatus(FramebufferTarget target) {
return Status((this->*checkStatusImplementation)(target));
}
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Map shader outputs to buffer attachment
@ -285,7 +321,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @endcode
*
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* framebuffer is not currently bound, it is bound before the
* operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffers} or
* @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}
@ -303,7 +339,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* only one (unnamed) output.
*
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* framebuffer is not currently bound, it is bound before the
* operation.
* @see mapForRead(), @fn_gl{BindFramebuffer}, @fn_gl{DrawBuffer} or
* @fn_gl_extension{FramebufferDrawBuffer,EXT,direct_state_access},
@ -323,7 +359,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
* @return Pointer to self (for method chaining)
*
* If @extension{EXT,direct_state_access} is not available and the
* framebufferbuffer is not currently bound, it is bound before the
* framebuffer is not currently bound, it is bound before the
* operation.
* @see mapForDraw(), @fn_gl{BindFramebuffer}, @fn_gl{ReadBuffer} or
* @fn_gl_extension{FramebufferReadBuffer,EXT,direct_state_access}
@ -380,6 +416,9 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** @brief Default framebuffer instance */
extern DefaultFramebuffer MAGNUM_EXPORT defaultFramebuffer;
/** @debugoperator{DefaultFramebuffer} */
Debug MAGNUM_EXPORT operator<<(Debug debug, DefaultFramebuffer::Status value);
}
#endif

15
src/Extensions.h

@ -76,6 +76,7 @@ namespace GL {
_extension(GL,ARB,texture_float, GL210, GL300) // #41
_extension(GL,ARB,depth_buffer_float, GL210, GL300) // #43
_extension(GL,ARB,draw_instanced, GL210, GL310) // #44
_extension(GL,ARB,framebuffer_object, GL210, GL300) // #45
_extension(GL,ARB,geometry_shader4, GL210, GL320) // #47
_extension(GL,ARB,instanced_arrays, GL210, GL330) // #49
_extension(GL,ARB,map_buffer_range, GL210, GL300) // #50
@ -154,10 +155,8 @@ namespace GL {
_extension(GL,ARB,texture_storage_multisample, GL210, GL430) // #141
} namespace EXT {
_extension(GL,EXT,texture_filter_anisotropic, GL210, None) // #187
_extension(GL,EXT,framebuffer_object, GL210, GL300) // #310
_extension(GL,EXT,packed_depth_stencil, GL210, GL300) // #312
_extension(GL,EXT,framebuffer_blit, GL210, GL300) // #316
_extension(GL,EXT,framebuffer_multisample, GL210, GL300) // #317
/* EXT_framebuffer_object, EXT_packed_depth_stencil, EXT_framebuffer_blit,
EXT_framebuffer_multisample replaced with ARB_framebuffer_object */
_extension(GL,EXT,gpu_shader4, GL210, GL300) // #326
_extension(GL,EXT,packed_float, GL210, GL300) // #328
_extension(GL,EXT,texture_array, GL210, GL300) // #329
@ -206,10 +205,13 @@ namespace GL {
_extension(GL,EXT,separate_shader_objects, GLES200, None) // #101
_extension(GL,EXT,texture_rg, GLES200, GLES300) // #103
_extension(GL,EXT,sRGB, GLES200, None) // #105
_extension(GL,EXT,robustness, GLES200, None) // #105
_extension(GL,EXT,multisampled_render_to_texture, GLES200, None) // #106
_extension(GL,EXT,robustness, GLES200, None) // #107
_extension(GL,EXT,texture_storage, GLES200, GLES300) // #108
_extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121
_extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150
} namespace KHR {
_extension(GL,KHR,debug, GLES200, None) // #118
} namespace NV {
_extension(GL,NV,draw_buffers, GLES200, GLES300) // #91
_extension(GL,NV,read_buffer, GLES200, GLES300) // #93
@ -238,7 +240,8 @@ namespace GL {
_extension(GL,OES,depth_texture, GLES200, GLES300) // #44
_extension(GL,OES,standard_derivatives, GLES200, GLES300) // #45
_extension(GL,OES,vertex_array_object, GLES200, GLES300) // #71
_extension(GL,OES,required_internalformat, GLES200, GLES300) // #?
_extension(GL,OES,required_internalformat, GLES200, GLES300) // #115
_extension(GL,OES,surfaceless_context, GLES200, GLES300) // #116
}
#endif
}

23
src/Framebuffer.cpp

@ -172,4 +172,27 @@ void Framebuffer::texture3DImplementationDSA(BufferAttachment attachment, Textur
}
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, const Framebuffer::Status value) {
switch(value) {
#define _c(value) case Framebuffer::Status::value: return debug << "Framebuffer::Status::" #value;
_c(Complete)
_c(IncompleteAttachment)
_c(IncompleteMissingAttachment)
#ifndef MAGNUM_TARGET_GLES
_c(IncompleteDrawBuffer)
_c(IncompleteReadBuffer)
#endif
_c(Unsupported)
_c(IncompleteMultisample)
#ifndef MAGNUM_TARGET_GLES
_c(IncompleteLayerTargets)
#endif
#undef _c
}
return debug << "Framebuffer::Status::(invalid)";
}
#endif
}

79
src/Framebuffer.h

@ -94,7 +94,7 @@ attachTexture2D(), attachCubeMapTexture() and attachTexture3D() use DSA
to avoid unnecessary calls to @fn_gl{BindFramebuffer}. See their respective
documentation for more information.
@requires_gl30 %Extension @extension{EXT,framebuffer_object}
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
friend class Context;
@ -228,6 +228,66 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
GLenum attachment;
};
/**
* @brief Status
*
* @see checkStatus()
*/
enum class Status: GLenum {
/** The framebuffer is complete */
Complete = GL_FRAMEBUFFER_COMPLETE,
/** Any of the attachment points are incomplete */
IncompleteAttachment = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
/** The framebuffer does not have at least one image attached to it */
IncompleteMissingAttachment = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
#ifndef MAGNUM_TARGET_GLES
/** @todo Why exactly this is not needed? */
/**
* No object attached to any draw color attachment points
* @requires_gl Not available in OpenGL ES.
*/
IncompleteDrawBuffer = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER,
/**
* No object attached to read color attachment point
* @requires_gl Not available in OpenGL ES.
*/
IncompleteReadBuffer = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER,
#endif
/**
* Combination of internal formats of the attached images violates
* an implementation-dependent set of restrictions.
*/
Unsupported = GL_FRAMEBUFFER_UNSUPPORTED,
/**
* Sample count or locations are not the same for all attached
* images.
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample},
* @es_extension{APPLE,framebuffer_multisample},
* @es_extension{EXT,multisampled_render_to_texture} or
* @es_extension{NV,framebuffer_multisample}
*/
#ifndef MAGNUM_TARGET_GLES2
IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
#else
IncompleteMultisample = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE,
#endif
#ifndef MAGNUM_TARGET_GLES
/** @todo Why exactly this is not needed? */
/**
* Mismatched layered color attachments
* @requires_gl Not available in OpenGL ES.
*/
IncompleteLayerTargets = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
#endif
};
/**
* @brief Constructor
*
@ -244,6 +304,20 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
*/
~Framebuffer();
/**
* @brief Check framebuffer status
* @param target Target for which check the status
*
* If @extension{EXT,direct_state_access} is not available and the
* framebuffer is not currently bound, it is bound before the
* operation.
* @see @fn_gl{BindFramebuffer}, @fn_gl{CheckFramebufferStatus} or
* @fn_gl_extension{CheckNamedFramebufferStatus,EXT,direct_state_access}
*/
Status checkStatus(FramebufferTarget target) {
return Status((this->*checkStatusImplementation)(target));
}
/**
* @brief Map shader output to attachments
* @return Pointer to self (for method chaining)
@ -468,6 +542,9 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer {
static Texture3DImplementation texture3DImplementation;
};
/** @debugoperator{DefaultFramebuffer} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Framebuffer::Status value);
}
#endif

6
src/ImageFormat.cpp

@ -37,7 +37,13 @@ Debug operator<<(Debug debug, ImageFormat value) {
_c(Green)
_c(Blue)
#endif
#ifdef MAGNUM_TARGET_GLES2
_c(Luminance)
#endif
_c(RG)
#ifdef MAGNUM_TARGET_GLES2
_c(LuminanceAlpha)
#endif
_c(RGB)
_c(RGBA)
#ifndef MAGNUM_TARGET_GLES

36
src/ImageFormat.h

@ -68,8 +68,18 @@ enum class ImageFormat: GLenum {
* available in OpenGL ES.
*/
Blue = GL_BLUE,
#endif
/** @todo GL_ALPHA? */
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* Floating-point luminance channel. The value is used for all RGB
* channels.
* @deprecated Included for compatibility reasons only, use
* @ref Magnum::ImageFormat "ImageFormat::Red" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ImageFormat "ImageFormat::Red" instead.
*/
Luminance = GL_LUMINANCE,
#endif
/**
@ -84,6 +94,18 @@ enum class ImageFormat: GLenum {
RG = GL_RG_EXT,
#endif
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* Floating-point luminance and alpha channel. First value is used for all
* RGB channels, second value is used for alpha channel.
* @deprecated Included for compatibility reasons only, use
* @ref Magnum::ImageFormat "ImageFormat::RG" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ImageFormat "ImageFormat::RG" instead.
*/
LuminanceAlpha = GL_LUMINANCE_ALPHA,
#endif
/**
* Floating-point RGB.
* @requires_gl Can't be used for framebuffer reading in OpenGL ES.
@ -214,7 +236,7 @@ enum class ImageFormat: GLenum {
/**
* Depth and stencil.
* @requires_gl30 %Extension @extension{EXT,packed_depth_stencil}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
* @requires_es_extension For framebuffer reading only, extension
* @es_extension2{NV,read_depth_stencil,GL_NV_read_depth_stencil}.
@ -424,14 +446,16 @@ enum class ImageType: GLenum {
/**
* Unsigned int, depth component 24bit, stencil index 8bit.
* @requires_gl30 %Extension @extension{EXT,packed_depth_stencil}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 For texture data only, extension @es_extension{OES,packed_depth_stencil}.
*/
#ifdef MAGNUM_TARGET_GLES2
UnsignedInt248 = GL_UNSIGNED_INT_24_8_OES
#else
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt248 = GL_UNSIGNED_INT_24_8,
#else
UnsignedInt248 = GL_UNSIGNED_INT_24_8_OES,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Float + unsigned int, depth component 32bit float, 24bit gap, stencil
* index 8bit.

1
src/Platform/AbstractXApplication.h

@ -35,6 +35,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
/* undef Xlib nonsense to avoid conflicts */
#undef Complex
#undef None
#undef Always

3
src/Renderbuffer.h

@ -53,7 +53,7 @@ If extension @extension{EXT,direct_state_access} is available, function
setStorage() uses DSA to avoid unnecessary calls to @fn_gl{BindFramebuffer}.
See its documentation for more information.
@requires_gl30 %Extension @extension{EXT,framebuffer_object}
@requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
class MAGNUM_EXPORT Renderbuffer {
friend class Context;
@ -109,7 +109,6 @@ class MAGNUM_EXPORT Renderbuffer {
* operation.
* @see @fn_gl{BindRenderbuffer}, @fn_gl{RenderbufferStorage} or
* @fn_gl_extension{NamedRenderbufferStorage,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{EXT,framebuffer_multisample}
* @requires_gles30 %Extension @es_extension{ANGLE,framebuffer_multisample}
* or @es_extension{NV,framebuffer_multisample}
* @todo How about @es_extension{APPLE,framebuffer_multisample}?

2
src/RenderbufferFormat.h

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

47
src/Renderer.cpp

@ -233,4 +233,51 @@ Renderer::GraphicsResetStatus Renderer::graphicsResetStatusImplementationRobustn
}
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, const Renderer::Error value) {
switch(value) {
#define _c(value) case Renderer::Error::value: return debug << "Renderer::Error::" #value;
_c(NoError)
_c(InvalidEnum)
_c(InvalidValue)
_c(InvalidOperation)
_c(InvalidFramebufferOperation)
_c(OutOfMemory)
#ifndef MAGNUM_TARGET_GLES3
_c(StackUnderflow)
_c(StackOverflow)
#endif
#undef _c
}
return debug << "Renderer::Error::(invalid)";
}
#ifndef MAGNUM_TARGET_GLES3
Debug operator<<(Debug debug, const Renderer::ResetNotificationStrategy value) {
switch(value) {
#define _c(value) case Renderer::ResetNotificationStrategy::value: return debug << "Renderer::ResetNotificationStrategy::" #value;
_c(NoResetNotification)
_c(LoseContextOnReset)
#undef _c
}
return debug << "Renderer::ResetNotificationStrategy::(invalid)";
}
Debug operator<<(Debug debug, const Renderer::GraphicsResetStatus value) {
switch(value) {
#define _c(value) case Renderer::GraphicsResetStatus::value: return debug << "Renderer::GraphicsResetStatus::" #value;
_c(NoError)
_c(GuiltyContextReset)
_c(InnocentContextReset)
_c(UnknownContextReset)
#undef _c
}
return debug << "Renderer::ResetNotificationStrategy::(invalid)";
}
#endif
#endif
}

74
src/Renderer.h

@ -871,6 +871,69 @@ class MAGNUM_EXPORT Renderer {
*/
static void finish() { glFinish(); }
/**
* @brief Error status
*
* @see error()
*/
enum class Error: GLenum {
/** No error has been recorded */
NoError = GL_NO_ERROR,
/** An unacceptable value specified for enumerated argument */
InvalidEnum = GL_INVALID_ENUM,
/** A numeric argument is out of range */
InvalidValue = GL_INVALID_VALUE,
/** The specified operation is not allowed in the current state */
InvalidOperation = GL_INVALID_OPERATION,
/**
* The framebuffer object is not complete.
* @see AbstractFramebuffer::checkStatus()
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
*/
InvalidFramebufferOperation = GL_INVALID_FRAMEBUFFER_OPERATION,
/** There is not enough memory left to execute the command. */
OutOfMemory = GL_OUT_OF_MEMORY,
#ifndef MAGNUM_TARGET_GLES3
/**
* Given operation would cause an internal stack to underflow.
* @requires_gl43 %Extension @extension{KHR,debug}
* @requires_es_extension %Extension @es_extension2{KHR,debug,debug}
*/
#ifndef MAGNUM_TARGET_GLES2
StackUnderflow = GL_STACK_UNDERFLOW,
#else
StackUnderflow = GL_STACK_UNDERFLOW_KHR,
#endif
/**
* Given operation would cause an internal stack to overflow.
* @requires_gl43 %Extension @extension{KHR,debug}
* @requires_es_extension %Extension @es_extension2{KHR,debug,debug}
*/
#ifndef MAGNUM_TARGET_GLES2
StackOverflow = GL_STACK_OVERFLOW
#else
StackOverflow = GL_STACK_OVERFLOW_KHR
#endif
#endif
};
/**
* @brief Error status
*
* Returns error flag, if any set. If there aren't any more error
* flags, returns @ref Error "Error::NoError". Thus this function
* should be always called in a loop until it returns @ref Error "Error::NoError".
* @see @fn_gl{GetError}
*/
static Error error() { return static_cast<Error>(glGetError()); }
#ifndef MAGNUM_TARGET_GLES3
/**
* @brief Graphics reset notification strategy
@ -980,6 +1043,17 @@ class MAGNUM_EXPORT Renderer {
#endif
};
/** @debugoperator{Renderer} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Renderer::Error value);
#ifndef MAGNUM_TARGET_GLES3
/** @debugoperator{Renderer} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Renderer::ResetNotificationStrategy value);
/** @debugoperator{Renderer} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Renderer::GraphicsResetStatus value);
#endif
}
#endif

5
src/Shader.cpp

@ -171,10 +171,9 @@ bool Shader::compile() {
/* Error or warning message. The string is returned null-terminated, scrap
the \0 at the end afterwards */
std::string message(logLength, '\0');
if(!message.empty()) {
if(message.size() > 1)
glGetShaderInfoLog(_id, message.size(), nullptr, &message[0]);
message.resize(logLength-1);
}
message.resize(std::max(logLength, 1)-1);
/* Show error log */
if(!success) {

8
src/Shaders/DistanceFieldVector.cpp

@ -88,8 +88,16 @@ template<UnsignedInt dimensions> DistanceFieldVector<dimensions>::DistanceFieldV
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>())
#endif
{
AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"),
AbstractVector<dimensions>::VectorTextureLayer);
}
/* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
#ifdef MAGNUM_TARGET_GLES
setOutlineRange(0.5f, 1.0f);
setSmoothness(0.04f);
#endif
}

13
src/Shaders/DistanceFieldVector.frag

@ -25,18 +25,19 @@
#ifndef NEW_GLSL
#define in varying
#define fragmentColor gl_FragColor
#define texture texture2D
#endif
#ifndef GL_ES
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 1) uniform lowp vec4 color;
layout(location = 2) uniform lowp vec4 outlineColor;
layout(location = 3) uniform lowp vec2 outlineRange = vec2(0.5, 0.0);
layout(location = 3) uniform lowp vec2 outlineRange = vec2(0.5, 1.0);
layout(location = 4) uniform lowp float smoothness = 0.04;
#else
uniform lowp vec4 color;
uniform lowp vec4 outlineColor;
uniform lowp vec2 outlineRange = vec2(0.5, 0.0);
uniform lowp vec2 outlineRange = vec2(0.5, 1.0);
uniform lowp float smoothness = 0.04;
#endif
#else
@ -52,10 +53,10 @@ layout(binding = 16) uniform sampler2D vectorTexture;
uniform lowp sampler2D vectorTexture;
#endif
in vec2 fragmentTextureCoordinates;
in mediump vec2 fragmentTextureCoordinates;
#ifdef NEW_GLSL
out vec4 fragmentColor;
out lowp vec4 fragmentColor;
#endif
void main() {
@ -65,9 +66,9 @@ void main() {
fragmentColor = smoothstep(outlineRange.x-smoothness, outlineRange.x+smoothness, intensity)*color;
/* Outline */
if(outlineRange.x < outlineRange.y) {
if(outlineRange.x > outlineRange.y) {
lowp float mid = (outlineRange.x + outlineRange.y)/2.0;
lowp float half = (outlineRange.y - outlineRange.x)/2.0;
lowp float half = (outlineRange.x - outlineRange.y)/2.0;
fragmentColor += smoothstep(half+smoothness, half-smoothness, distance(mid, intensity))*outlineColor;
}
}

11
src/Shaders/DistanceFieldVector.h

@ -43,6 +43,9 @@ Renders vector art in form of signed distance field. See TextureTools::distanceF
for more information. Note that the final rendered outlook will greatly depend
on radius of input distance field and value passed to setSmoothness().
@see DistanceFieldVector2D, DistanceFieldVector3D
@todo Use fragment shader derivations to have proper smoothness in perspective/
large zoom levels, make it optional as it might have negative performance
impact
*/
template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector: public AbstractVector<dimensions> {
public:
@ -81,12 +84,12 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
* @return Pointer to self (for method chaining)
*
* Parameter @p start describes where fill ends and possible outline
* starts. Initial value is `0.5f`, smaller values will make the vector
* art look thinner, larger will make it look thicker.
* starts. Initial value is `0.5f`, larger values will make the vector
* art look thinner, smaller will make it look thicker.
*
* Parameter @p end describes where outline ends. If set to value
* smaller than @p start the outline is not drawn. Initial value is
* `0.0f`.
* larger than @p start the outline is not drawn. Initial value is
* `1.0f`.
*
* @see setOutlineColor()
*/

4
src/Shaders/Vector.cpp

@ -85,8 +85,10 @@ template<UnsignedInt dimensions> Vector<dimensions>::Vector(): transformationPro
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>())
AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractVector<dimensions>::VectorTextureLayer);
#endif
{
AbstractShaderProgram::setUniform(AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractVector<dimensions>::VectorTextureLayer);
}
}
template class Vector<2>;

5
src/Shaders/Vector.frag

@ -25,6 +25,7 @@
#ifndef NEW_GLSL
#define in varying
#define fragmentColor gl_FragColor
#define texture texture2D
#endif
#ifdef EXPLICIT_UNIFORM_LOCATION
@ -39,10 +40,10 @@ layout(binding = 16) uniform sampler2D vectorTexture;
uniform lowp sampler2D vectorTexture;
#endif
in vec2 fragmentTextureCoordinates;
in mediump vec2 fragmentTextureCoordinates;
#ifdef NEW_GLSL
out vec4 fragmentColor;
out lowp vec4 fragmentColor;
#endif
void main() {

3
src/Test/CMakeLists.txt

@ -26,7 +26,10 @@ corrade_add_test(AbstractImageTest AbstractImageTest.cpp LIBRARIES Magnum)
corrade_add_test(AbstractShaderProgramTest AbstractShaderProgramTest.cpp LIBRARIES Magnum)
corrade_add_test(ArrayTest ArrayTest.cpp)
corrade_add_test(ColorTest ColorTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(DefaultFramebufferTest DefaultFramebufferTest.cpp LIBRARIES Magnum)
corrade_add_test(FramebufferTest FramebufferTest.cpp LIBRARIES Magnum)
corrade_add_test(MeshTest MeshTest.cpp LIBRARIES Magnum)
corrade_add_test(RendererTest RendererTest.cpp LIBRARIES Magnum)
corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(SwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib)

52
src/Test/DefaultFramebufferTest.cpp

@ -0,0 +1,52 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <TestSuite/Tester.h>
#include "DefaultFramebuffer.h"
namespace Magnum { namespace Test {
class DefaultFramebufferTest: public TestSuite::Tester {
public:
explicit DefaultFramebufferTest();
void debugStatus();
};
DefaultFramebufferTest::DefaultFramebufferTest() {
addTests({&DefaultFramebufferTest::debugStatus});
}
void DefaultFramebufferTest::debugStatus() {
std::ostringstream out;
Debug(&out) << DefaultFramebuffer::Status::Undefined;
CORRADE_COMPARE(out.str(), "DefaultFramebuffer::Status::Undefined\n");
}
}}
CORRADE_TEST_MAIN(Magnum::Test::DefaultFramebufferTest)

52
src/Test/FramebufferTest.cpp

@ -0,0 +1,52 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <TestSuite/Tester.h>
#include "Framebuffer.h"
namespace Magnum { namespace Test {
class FramebufferTest: public TestSuite::Tester {
public:
explicit FramebufferTest();
void debugStatus();
};
FramebufferTest::FramebufferTest() {
addTests({&FramebufferTest::debugStatus});
}
void FramebufferTest::debugStatus() {
std::ostringstream out;
Debug(&out) << Framebuffer::Status::IncompleteMissingAttachment;
CORRADE_COMPARE(out.str(), "Framebuffer::Status::IncompleteMissingAttachment\n");
}
}}
CORRADE_TEST_MAIN(Magnum::Test::FramebufferTest)

72
src/Test/RendererTest.cpp

@ -0,0 +1,72 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <sstream>
#include <TestSuite/Tester.h>
#include "Renderer.h"
namespace Magnum { namespace Test {
class RendererTest: public TestSuite::Tester {
public:
explicit RendererTest();
void debugError();
#ifndef MAGNUM_TARGET_GLES3
void debugResetNotificationStrategy();
void debugGraphicsResetStatus();
#endif
};
RendererTest::RendererTest() {
addTests({&RendererTest::debugError});
}
void RendererTest::debugError() {
std::ostringstream out;
Debug(&out) << Renderer::Error::InvalidOperation;
CORRADE_COMPARE(out.str(), "Renderer::Error::InvalidOperation\n");
}
#ifndef MAGNUM_TARGET_GLES3
void RendererTest::debugResetNotificationStrategy() {
std::ostringstream out;
Debug(&out) << Renderer::ResetNotificationStrategy::LoseContextOnReset;
CORRADE_COMPARE(out.str(), "Renderer::ResetNotificationStrategy::LoseContextOnReset\n");
}
void RendererTest::debugGraphicsResetStatus() {
std::ostringstream out;
Debug(&out) << Renderer::GraphicsResetStatus::GuiltyContextReset;
CORRADE_COMPARE(out.str(), "Renderer::GraphicsResetStatus::GuiltyContextReset\n");
}
#endif
}}
CORRADE_TEST_MAIN(Magnum::Test::RendererTest)

42
src/Text/DistanceFieldGlyphCache.cpp

@ -26,30 +26,54 @@
#include "Extensions.h"
#include "Image.h"
#ifndef CORRADE_NO_ASSERT
#include "ImageFormat.h"
#endif
#include "TextureFormat.h"
#include "TextureTools/DistanceField.h"
namespace Magnum { namespace Text {
namespace {
DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, const Vector2i& distanceFieldSize, UnsignedInt radius): GlyphCache(originalSize, Vector2i(radius)), scale(Vector2(distanceFieldSize)/originalSize), radius(radius) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg);
#endif
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3)
const TextureFormat internalFormat = TextureFormat::R8;
#else
const TextureFormat internalFormat = TextureFormat::Red;
const TextureFormat internalFormat =
Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>() ?
TextureFormat::Red : TextureFormat::RGB;
if(internalFormat == TextureFormat::RGB)
Warning() << "Text::DistanceFieldGlyphCache:" << Extensions::GL::EXT::texture_rg::string() << "not supported, using inefficient RGB format for glyph cache texture";
#endif
initialize(internalFormat, distanceFieldSize);
}
DistanceFieldGlyphCache::DistanceFieldGlyphCache(const Vector2i& originalSize, const Vector2i& distanceFieldSize, UnsignedInt radius): GlyphCache(originalSize, Vector2i(radius)), scale(Vector2(distanceFieldSize)/originalSize), radius(radius) {
void DistanceFieldGlyphCache::setImage(const Vector2i& offset, Image2D* const image) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg);
#else
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::texture_rg);
#endif
initialize(internalFormat, distanceFieldSize);
}
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3)
const TextureFormat internalFormat = TextureFormat::R8;
CORRADE_ASSERT(image->format() == ImageFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image->format(), );
#else
TextureFormat internalFormat;
if(Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>()) {
internalFormat = TextureFormat::Red;
CORRADE_ASSERT(image->format() == ImageFormat::Red,
"Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Red << "but got" << image->format(), );
} else {
internalFormat = TextureFormat::Luminance;
CORRADE_ASSERT(image->format() == ImageFormat::Luminance,
"Text::DistanceFieldGlyphCache::setImage(): expected" << ImageFormat::Luminance << "but got" << image->format(), );
}
#endif
void DistanceFieldGlyphCache::setImage(const Vector2i& offset, Image2D* const image) {
Texture2D input;
input.setWrapping(Sampler::Wrapping::ClampToEdge)
->setMinificationFilter(Sampler::Filter::Linear)
@ -57,7 +81,7 @@ void DistanceFieldGlyphCache::setImage(const Vector2i& offset, Image2D* const im
->setImage(0, internalFormat, image);
/* Create distance field from input texture */
TextureTools::distanceField(&input, &_texture, Rectanglei::fromSize(offset*scale, image->size()*scale), radius);
TextureTools::distanceField(&input, &_texture, Rectanglei::fromSize(offset*scale, image->size()*scale), radius, image->size());
}
void DistanceFieldGlyphCache::setDistanceFieldImage(const Vector2i& offset, Image2D* const image) {

8
src/Text/DistanceFieldGlyphCache.h

@ -62,7 +62,13 @@ class MAGNUM_TEXT_EXPORT DistanceFieldGlyphCache: public GlyphCache {
* @param radius Distance field computation radius
*
* See TextureTools::distanceField() for more information about the
* parameters.
* parameters. Sets internal texture format to red channel only. On
* desktop OpenGL requires @extension{ARB,texture_rg} (also part of
* OpenGL ES 3.0), in ES2 uses @es_extension{EXT,texture_rg} if
* available or @ref TextureFormat "TextureFormat::RGB" as fallback.
* @todo Is Luminance format renderable anywhere? Also would it be
* possible to convert the RGB texture to Luminance after it has
* been rendered when blitting is not supported to save memory?
*/
explicit DistanceFieldGlyphCache(const Vector2i& originalSize, const Vector2i& distanceFieldSize, UnsignedInt radius);

22
src/Text/GlyphCache.cpp

@ -31,19 +31,17 @@
namespace Magnum { namespace Text {
namespace {
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3)
const TextureFormat internalFormat = TextureFormat::R8;
#else
const TextureFormat internalFormat = TextureFormat::Red;
#endif
}
GlyphCache::GlyphCache(const Vector2i& size): _size(size) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg);
#endif
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES3)
const TextureFormat internalFormat = TextureFormat::R8;
#else
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::texture_rg);
const TextureFormat internalFormat =
Context::current()->isExtensionSupported<Extensions::GL::EXT::texture_rg>() ?
TextureFormat::Red : TextureFormat::Luminance;
#endif
initialize(internalFormat, size);
@ -59,12 +57,6 @@ GlyphCache::~GlyphCache() = default;
/** @todo Delegating constructor when support for GCC 4.6 is dropped */
void GlyphCache::initialize(const TextureFormat internalFormat, const Vector2i& size) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_storage);
#else
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::texture_storage);
#endif
_texture.setWrapping(Sampler::Wrapping::ClampToEdge)
->setMinificationFilter(Sampler::Filter::Linear)
->setMagnificationFilter(Sampler::Filter::Linear)

9
src/Text/GlyphCache.h

@ -28,6 +28,7 @@
* @brief Class Magnum::Text::GlyphCache
*/
#include <vector>
#include <unordered_map>
#include "Math/Geometry/Rectangle.h"
@ -54,6 +55,7 @@ font->createGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz"
@endcode
See TextRenderer for information about text rendering.
@todo Some way for Font to negotiate or check internal texture format
*/
class MAGNUM_TEXT_EXPORT GlyphCache {
public:
@ -68,9 +70,10 @@ class MAGNUM_TEXT_EXPORT GlyphCache {
* @brief Constructor
* @param size Glyph cache texture size
*
* Sets internal texture format to red channel only. Requires
* @extension{ARB,texture_rg} (also part of OpenGL ES 3.0 or available
* as @es_extension{EXT,texture_rg} in ES 2.0).
* Sets internal texture format to red channel only. On desktop OpenGL
* requires @extension{ARB,texture_rg} (also part of OpenGL ES 3.0), in
* ES2 uses @es_extension{EXT,texture_rg}, if available, or
* @ref TextureFormat "TextureFormat::Luminance" as fallback.
*/
explicit GlyphCache(const Vector2i& size);

13
src/Texture.h

@ -282,14 +282,19 @@ template<UnsignedInt dimensions> class Texture: public AbstractTexture {
* is immutable and calling setStorage() or setImage() is not allowed.
*
* If @extension{EXT,direct_state_access} is not available, the
* texture is bound to some layer before the operation.
* texture is bound to some layer before the operation. If
* OpenGL 4.2, @extension{ARB,texture_storage}, OpenGL ES 3.0 or @es_extension{EXT,texture_storage}
* in OpenGL ES 2.0 is not available, the feature is emulated with
* sequence of setImage() calls.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D}
* or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureStorage3D,EXT,direct_state_access}
* @requires_gl42 %Extension @extension{ARB,texture_storage}
* @requires_gles30 %Extension @es_extension{EXT,texture_storage}
* @fn_gl_extension{TextureStorage3D,EXT,direct_state_access},
* eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or
* @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/
* @fn_gl_extension{TextureImage3D,EXT,direct_state_access}.
*/
Texture<Dimensions>* setStorage(Int levels, TextureFormat internalFormat, const typename DimensionTraits<Dimensions, Int>::VectorType& size) {
DataHelper<Dimensions>::setStorage(this, _target, levels, internalFormat, size);

167
src/TextureFormat.h

@ -147,6 +147,7 @@ enum class TextureFormat: GLenum {
* @requires_gles30 Only unsigned formats are available in OpenGL ES 2.0.
*/
RGBA8Snorm = GL_RGBA8_SNORM,
#endif
#ifndef MAGNUM_TARGET_GLES
/**
@ -212,6 +213,7 @@ enum class TextureFormat: GLenum {
RGBA16Snorm = GL_RGBA16_SNORM,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Red component, non-normalized unsigned byte.
* @requires_gl30 %Extension @extension{ARB,texture_rg} and @extension{EXT,texture_integer}
@ -469,6 +471,29 @@ enum class TextureFormat: GLenum {
RGBA32F = GL_RGBA32F,
#endif
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* Luminance, normalized unsigned, single value used for all RGB channels.
* Size implementation-dependent.
* @deprecated Included for compatibility reasons only, use
* @ref Magnum::TextureFormat "TextureFormat::R8" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::TextureFormat "TextureFormat::R8" instead.
*/
Luminance = GL_LUMINANCE,
/**
* Floating-point luminance and alpha channel. First value is used for all
* RGB channels, second value is used for alpha channel. Size
* implementation-dependent.
* @deprecated Included for compatibility reasons only, use
* @ref Magnum::TextureFormat "TextureFormat::RG8" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::TextureFormat "TextureFormat::RG8" instead.
*/
LuminanceAlpha = GL_LUMINANCE_ALPHA,
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* RGB, normalized unsigned, red and green component 3bit, blue 2bit.
@ -490,14 +515,16 @@ enum class TextureFormat: GLenum {
RGB5 = GL_RGB5,
#endif
/* 1.5.6 <= GLEW < 1.8.0 doesn't have this, even if there is
GL_ARB_ES2_compatibility */
#if defined(GL_RGB565) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* RGB, normalized unsigned, red and blue component 5bit, green 6bit.
* @requires_gles30 %Extension @es_extension{OES,required_internalformat}
*/
/* 1.5.6 <= GLEW < 1.8.0 doesn't have this, even if there is
GL_ARB_ES2_compatibility */
#ifdef GL_RGB565
RGB565 = GL_RGB565,
#else
RGB565 = 0x8D62,
#endif
#ifndef MAGNUM_TARGET_GLES3
@ -519,7 +546,53 @@ enum class TextureFormat: GLenum {
* @requires_gl Packed 36bit types are not available in OpenGL ES.
*/
RGB12 = GL_RGB12,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* RGB, float, red and green component 11bit, blue 10bit.
* @requires_gl30 %Extension @extension{EXT,packed_float}
* @requires_gles30 Only normalized integral formats are available in
* OpenGL ES 2.0.
*/
R11FG11FB10F = GL_R11F_G11F_B10F,
/**
* RGB, unsigned with exponent, each RGB component 9bit, exponent 5bit.
* @requires_gl30 %Extension @extension{EXT,texture_shared_exponent}
* @requires_gles30 Use @ref Magnum::TextureFormat "TextureFormat::RGB" in
* OpenGL ES 2.0 instead.
*/
RGB9E5 = GL_RGB9_E5,
#endif
#ifndef MAGNUM_TARGET_GLES3
/**
* sRGB, normalized unsigned, size implementation-dependent.
* @todo is this allowed in core?
* @deprecated Prefer to use the exactly specified version of this format,
* i.e. @ref Magnum::TextureFormat "TextureFormat::SRGB8".
* @requires_es_extension %Extension @es_extension{EXT,sRGB} in OpenGL ES
* 2.0, use @ref Magnum::TextureFormat "TextureFormat::SRGB8" in
* OpenGL ES 3.0 instead.
*/
#ifndef MAGNUM_TARGET_GLES
SRGB = GL_SRGB,
#else
SRGB = GL_SRGB_EXT,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* sRGB, each component normalized unsigned byte.
* @requires_gles30 Use @ref Magnum::TextureFormat "TextureFormat::SRGB" in
* OpenGL ES 2.0 instead.
*/
SRGB8 = GL_SRGB8,
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* RGBA, normalized unsigned, each component 2bit.
* @requires_gl Packed 8bit types are not available in OpenGL ES.
@ -568,52 +641,6 @@ enum class TextureFormat: GLenum {
RGBA12 = GL_RGBA12,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* RGB, float, red and green component 11bit, blue 10bit.
* @requires_gl30 %Extension @extension{EXT,packed_float}
* @requires_gles30 Only normalized integral formats are available in
* OpenGL ES 2.0.
*/
R11FG11FB10F = GL_R11F_G11F_B10F,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* RGB, unsigned with exponent, each RGB component 9bit, exponent 5bit.
* @requires_gl30 %Extension @extension{EXT,texture_shared_exponent}
* @requires_gles30 Use @ref Magnum::TextureFormat "TextureFormat::RGB" in
* OpenGL ES 2.0 instead.
*/
RGB9E5 = GL_RGB9_E5,
#endif
#ifndef MAGNUM_TARGET_GLES3
/**
* sRGB, normalized unsigned, size implementation-dependent.
* @todo is this allowed in core?
* @deprecated Prefer to use the exactly specified version of this format,
* i.e. @ref Magnum::TextureFormat "TextureFormat::SRGB8".
* @requires_es_extension %Extension @es_extension{EXT,sRGB} in OpenGL ES
* 2.0, use @ref Magnum::TextureFormat "TextureFormat::SRGB8" in
* OpenGL ES 3.0 instead.
*/
#ifndef MAGNUM_TARGET_GLES
SRGB = GL_SRGB,
#else
SRGB = GL_SRGB_EXT,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* sRGB, each component normalized unsigned byte.
* @requires_gles30 Use @ref Magnum::TextureFormat "TextureFormat::SRGB" in
* OpenGL ES 2.0 instead.
*/
SRGB8 = GL_SRGB8,
#endif
#ifndef MAGNUM_TARGET_GLES3
/**
* sRGBA, normalized unsigned, size implementation-dependent.
@ -700,32 +727,32 @@ enum class TextureFormat: GLenum {
late as of 1.8.0 { */
/**
* BPTC compressed RGBA, normalized unsigned.
* BPTC compressed RGB, unsigned float.
* @requires_gl42 %Extension @extension{ARB,texture_compression_bptc}
* @requires_gl BPTC texture compression is not available in OpenGL ES.
*/
CompressedRGBABtpcUnorm = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB,
CompressedRGBBptcUnsignedFloat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB,
/**
* BPTC compressed sRGBA, normalized unsigned.
* BPTC compressed RGB, signed float.
* @requires_gl42 %Extension @extension{ARB,texture_compression_bptc}
* @requires_gl BPTC texture compression is not available in OpenGL ES.
*/
CompressedSRGBAlphaBtpcUnorm = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB,
CompressedRGBBptcSignedFloat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB,
/**
* BPTC compressed RGB, unsigned float.
* BPTC compressed RGBA, normalized unsigned.
* @requires_gl42 %Extension @extension{ARB,texture_compression_bptc}
* @requires_gl BPTC texture compression is not available in OpenGL ES.
*/
CompressedRGBBptcUnsignedFloat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB,
CompressedRGBABptcUnorm = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB,
/**
* BPTC compressed RGB, signed float.
* BPTC compressed sRGBA, normalized unsigned.
* @requires_gl42 %Extension @extension{ARB,texture_compression_bptc}
* @requires_gl BPTC texture compression is not available in OpenGL ES.
*/
CompressedRGBBptcSignedFloat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB,
CompressedSRGBAlphaBptcUnorm = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB,
/*}*/
#endif
@ -739,18 +766,6 @@ enum class TextureFormat: GLenum {
*/
DepthComponent = GL_DEPTH_COMPONENT,
/**
* Depth and stencil component, size implementation-dependent.
* @deprecated Prefer to use exactly specified version of this format, e.g.
* @ref Magnum::TextureFormat "TextureFormat::Depth24Stencil8".
* @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil}
*/
#ifndef MAGNUM_TARGET_GLES2
DepthStencil = GL_DEPTH_STENCIL,
#else
DepthStencil = GL_DEPTH_STENCIL_OES,
#endif
/**
* Depth component, 16bit.
* @requires_gles30 %Extension (@es_extension{OES,required_internalformat}
@ -794,9 +809,21 @@ enum class TextureFormat: GLenum {
DepthComponent32F = GL_DEPTH_COMPONENT32F,
#endif
/**
* Depth and stencil component, size implementation-dependent.
* @deprecated Prefer to use exactly specified version of this format, e.g.
* @ref Magnum::TextureFormat "TextureFormat::Depth24Stencil8".
* @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil}
*/
#ifndef MAGNUM_TARGET_GLES2
DepthStencil = GL_DEPTH_STENCIL,
#else
DepthStencil = GL_DEPTH_STENCIL_OES,
#endif
/**
* 24bit depth and 8bit stencil component.
* @requires_gl30 %Extension @extension{EXT,packed_depth_stencil}
* @requires_gl30 %Extension @extension{ARB,framebuffer_object}
* @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} and
* (@es_extension{OES,required_internalformat} or
* (@es_extension{EXT,texture_storage} and @es_extension{ANGLE,depth_texture}))

128
src/TextureTools/DistanceField.cpp

@ -39,6 +39,8 @@ namespace {
class DistanceFieldShader: public AbstractShaderProgram {
public:
typedef Attribute<0, Vector2> Position;
enum: Int {
TextureLayer = 8
};
@ -50,62 +52,148 @@ class DistanceFieldShader: public AbstractShaderProgram {
return this;
}
DistanceFieldShader* setScaling(Vector2 scaling) {
DistanceFieldShader* setScaling(const Vector2& scaling) {
setUniform(scalingUniform, scaling);
return this;
}
DistanceFieldShader* setImageSizeInverted(const Vector2& size) {
setUniform(imageSizeInvertedUniform, size);
return this;
}
private:
static const Int radiusUniform = 0,
scalingUniform = 1;
Int radiusUniform,
scalingUniform,
imageSizeInvertedUniform;
};
DistanceFieldShader::DistanceFieldShader() {
MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL330);
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::explicit_attrib_location);
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::explicit_uniform_location);
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::shading_language_420pack);
/** @todo compatibility! */
DistanceFieldShader::DistanceFieldShader(): radiusUniform(0), scalingUniform(1) {
Utility::Resource rs("MagnumTextureTools");
Shader vert(Version::GL330, Shader::Type::Vertex);
vert.addSource(rs.get("DistanceFieldShader.vert"));
#ifndef MAGNUM_TARGET_GLES
const Version v = Context::current()->supportedVersion({Version::GL320, Version::GL300, Version::GL210});
#else
const Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
Shader vert(v, Shader::Type::Vertex);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("DistanceFieldShader.vert"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
Shader frag(Version::GL330, Shader::Type::Fragment);
Shader frag(v, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("DistanceFieldShader.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
/* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isVersionSupported(Version::GL300))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
{
bindAttributeLocation(Position::Location, "position");
}
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
}
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>())
#endif
{
radiusUniform = uniformLocation("radius");
scalingUniform = uniformLocation("scaling");
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isVersionSupported(Version::GL300))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
{
imageSizeInvertedUniform = uniformLocation("imageSizeInverted");
}
}
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::shading_language_420pack>())
#endif
{
setUniform(uniformLocation("textureData"), TextureLayer);
}
}
void distanceField(Texture2D* input, Texture2D* output, const Rectanglei& rectangle, const Int radius) {
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::framebuffer_object);
}
#ifndef MAGNUM_TARGET_GLES
void distanceField(Texture2D* input, Texture2D* output, const Rectanglei& rectangle, const Int radius, const Vector2i&)
#else
void distanceField(Texture2D* input, Texture2D* output, const Rectanglei& rectangle, const Int radius, const Vector2i& imageSize)
#endif
{
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::framebuffer_object);
#endif
/** @todo Disable depth test, blending and then enable it back (if was previously) */
#ifndef MAGNUM_TARGET_GLES
Vector2i imageSize = input->imageSize(0);
#endif
Framebuffer framebuffer(rectangle);
framebuffer.attachTexture2D(Framebuffer::ColorAttachment(0), output, 0);
framebuffer.bind(FramebufferTarget::Draw);
framebuffer.clear(FramebufferClear::Color);
const Framebuffer::Status status = framebuffer.checkStatus(FramebufferTarget::Draw);
if(status != Framebuffer::Status::Complete) {
Error() << "TextureTools::distanceField(): cannot render to given output texture, unexpected framebuffer status"
<< status;
return;
}
DistanceFieldShader shader;
shader.setRadius(radius)
->setScaling(Vector2(input->imageSize(0))/rectangle.size())
->setScaling(Vector2(imageSize)/rectangle.size())
->use();
input->bind(DistanceFieldShader::TextureLayer);
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isVersionSupported(Version::GL300))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
{
shader.setImageSizeInverted(Vector2(1)/imageSize);
}
Mesh mesh;
mesh.setPrimitive(Mesh::Primitive::Triangles)
->setVertexCount(3)
->draw();
->setVertexCount(3);
/* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */
Buffer buffer;
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isVersionSupported(Version::GL300))
#else
if(!Context::current()->isVersionSupported(Version::GLES300))
#endif
{
constexpr Vector2 triangle[] = {
Vector2(-1.0, 1.0),
Vector2(-1.0, -3.0),
Vector2( 3.0, 1.0)
};
buffer.setData(triangle, Buffer::Usage::StaticDraw);
mesh.addVertexBuffer(&buffer, 0, DistanceFieldShader::Position());
}
/* Draw the mesh */
mesh.draw();
}
}}

29
src/TextureTools/DistanceField.h

@ -28,6 +28,9 @@
* @brief Function Magnum::TextureTools::distanceField()
*/
#ifndef MAGNUM_TARGET_GLES
#include "Math/Vector2.h"
#endif
#include "Magnum.h"
#include "TextureTools/magnumTextureToolsVisibility.h"
@ -40,6 +43,8 @@ namespace Magnum { namespace TextureTools {
@param output Output texture
@param rectangle Rectangle in output texture where to render
@param radius Max lookup radius in input texture
@param imageSize Input texture size. Needed only in OpenGL ES, in desktop
OpenGL the information is gathered automatically using Texture::imageSize().
Converts binary image (stored in red channel of @p input) to signed distance
field (stored in red channel in @p rectangle of @p output). The purpose of this
@ -51,9 +56,9 @@ foundation for features like outlining, glow or drop shadow essentialy for free.
For each pixel inside @p rectangle the algorithm looks at corresponding pixel in
@p input and tries to find nearest pixel of opposite color in area given by
@p radius. Signed distance between the points is then saved as value of given
pixel in @p output. Value of `0` means that the pixel was originally colored
white and nearest black pixel is farther than @p radius, value of `1` means that
the pixel was originally black and nearest white pixel is farther than
pixel in @p output. Value of `1.0` means that the pixel was originally colored
white and nearest black pixel is farther than @p radius, value of `0.0` means
that the pixel was originally black and nearest white pixel is farther than
@p radius. Values around `0.5` are around edges.
The resulting texture can be used with bilinear filtering. It can be converted
@ -66,8 +71,24 @@ and Special Effects, SIGGRAPH 2007,
http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf*
@attention This is GPU-only implementation, so it expects active context.
@note If internal format of @p output texture is not renderable, this function
prints message to error output and does nothing. In desktop OpenGL and
OpenGL ES 3.0 it's common to render to @ref TextureFormat "TextureFormat::R8".
In OpenGL ES 2.0 you can use @ref TextureFormat "TextureFormat::Red" if
@es_extension{EXT,texture_rg} is available, if not, the smallest but still
inefficient supported format is in most cases @ref TextureFormat "TextureFormat::RGB",
rendering to @ref TextureFormat "TextureFormat::Luminance" is not supported
in most cases.
@bug ES (and maybe GL < 3.20) implementation behaves slightly different
(jaggies, visible e.g. when rendering outlined fonts)
*/
void MAGNUM_TEXTURETOOLS_EXPORT distanceField(Texture2D* input, Texture2D* output, const Rectanglei& rectangle, Int radius);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_TEXTURETOOLS_EXPORT distanceField(Texture2D* input, Texture2D* output, const Rectanglei& rectangle, Int radius, const Vector2i& imageSize = Vector2i());
#else
void MAGNUM_TEXTURETOOLS_EXPORT distanceField(Texture2D* input, Texture2D* output, const Rectanglei& rectangle, Int radius, const Vector2i& imageSize);
#endif
}}

86
src/TextureTools/DistanceFieldShader.frag

@ -22,40 +22,90 @@
DEALINGS IN THE SOFTWARE.
*/
#ifndef NEW_GLSL
#define in varying
#define value gl_FragColor.x
#define const
#define texture texture2D
#endif
#if (defined(GL_ES) && __VERSION__ >= 300) || (!defined(GL_ES) && __VERSION__ >= 150)
#define TEXELFETCH_USABLE
#endif
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 0) uniform int radius;
layout(location = 1) uniform vec2 scaling;
layout(binding = 8) uniform sampler2D texture;
layout(pixel_center_integer) in vec4 gl_FragCoord;
out float value;
layout(binding = 8) uniform sampler2D textureData;
#else
uniform lowp int radius;
uniform mediump vec2 scaling;
uniform lowp sampler2D textureData;
#endif
#ifdef TEXELFETCH_USABLE
layout(pixel_center_integer) in mediump vec4 gl_FragCoord;
#else
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 2) uniform vec2 imageSizeInverted;
#else
uniform mediump vec2 imageSizeInverted;
#endif
#endif
#ifdef NEW_GLSL
out lowp float value;
#endif
#ifdef TEXELFETCH_USABLE
mediump ivec2 rotate(const mediump ivec2 vec) {
return mediump ivec2(-vec.y, vec.x);
}
ivec2 rotate(const ivec2 vec) {
return ivec2(-vec.y, vec.x);
bool hasValue(const mediump ivec2 position, const mediump ivec2 offset) {
return texelFetch(textureData, position+offset, 0).r > 0.5;
}
#else
mediump vec2 rotate(const mediump vec2 vec) {
return mediump vec2(-vec.y, vec.x);
}
bool hasValue(const ivec2 position, const ivec2 offset) {
return texelFetch(texture, position+offset, 0).r > 0.5;
bool hasValue(const mediump vec2 position, const mediump vec2 offset) {
return texture(textureData, position+offset).r > 0.5;
}
#endif
void main() {
const ivec2 position = ivec2(gl_FragCoord.xy*scaling);
#ifdef TEXELFETCH_USABLE
const mediump ivec2 position = ivec2(gl_FragCoord.xy*scaling);
#else
const mediump vec2 position = gl_FragCoord.xy*scaling*imageSizeInverted;
#endif
/* If pixel at the position is inside (1), we are looking for nearest pixel
outside and the value will be positive (> 0.5). If it is outside (0), we
are looking for nearest pixel inside and the value will be negative
(< 0.5). */
#ifdef TEXELFETCH_USABLE
const bool isInside = hasValue(position, ivec2(0, 0));
const float sign = isInside ? 1.0 : -1.0;
#else
const bool isInside = hasValue(position, vec2(0.0, 0.0));
#endif
const highp float sign = isInside ? 1.0 : -1.0;
/* Minimal found distance is just out of the radius (i.e. infinity) */
float minDistanceSquared = float((radius+1)*(radius+1));
highp float minDistanceSquared = float((radius+1)*(radius+1));
/* Go in circles around the point and find nearest value */
int radiusLimit = radius;
for(int i = 1; i <= radiusLimit; ++i) {
for(int j = 0, jmax = i*2; j != jmax; ++j) {
const ivec2 offset = {-i+j, i};
#ifdef TEXELFETCH_USABLE
const lowp ivec2 offset = ivec2(-i+j, i);
#else
const lowp vec2 pixelOffset = vec2(float(-i+j), float(i));
const lowp vec2 offset = pixelOffset*imageSizeInverted;
#endif
/* If any of the four values is opposite of what is on the pixel,
we found nearest value */
@ -63,7 +113,11 @@ void main() {
hasValue(position, rotate(offset)) == !isInside ||
hasValue(position, rotate(rotate(offset))) == !isInside ||
hasValue(position, rotate(rotate(rotate(offset)))) == !isInside) {
const float distanceSquared = dot(vec2(offset), vec2(offset));
#ifdef TEXELFETCH_USABLE
const mediump float distanceSquared = dot(vec2(offset), vec2(offset));
#else
const mediump float distanceSquared = dot(pixelOffset, pixelOffset);
#endif
/* Set smaller distance, if found, or continue with lookup for
smaller */
@ -73,7 +127,11 @@ void main() {
/* Set radius limit to max radius which can contain smaller
value, e.g. for distance 3.5 we can find smaller value even
in radius 3 */
#ifdef NEW_GLSL
radiusLimit = min(radius, int(floor(length(vec2(offset)))));
#else
radiusLimit = int(min(float(radius), floor(length(vec2(offset)))));
#endif
}
}
}

8
src/TextureTools/DistanceFieldShader.vert

@ -22,7 +22,15 @@
DEALINGS IN THE SOFTWARE.
*/
#ifndef NEW_GLSL
attribute lowp vec4 position;
#endif
void main() {
#ifdef NEW_GLSL
gl_Position = vec4((gl_VertexID == 2) ? 3.0 : -1.0,
(gl_VertexID == 1) ? -3.0 : 1.0, 0.0, 1.0);
#else
gl_Position = position;
#endif
}

Loading…
Cancel
Save