Browse Source

GL: implement EXT_clip_control and WEBGL_polygon_mode on Emscripten.

Following the spirit of extension-based functionality, the entrypoints
are available always but do something (i.e., call the actual WebGL API)
only if the extension is advertised. Which it is only on Emscripten
3.1.66+ because older versions don't have the corresponding entrypoints,
so there it's marked as disabled.

Additionally, EXT_polygon_offset_clamp is now also working on 3.1.66+,
but there's no wrapper for it yet.
pull/650/head
Vladimír Vondruš 2 years ago
parent
commit
a95fdb5598
  1. 16
      doc/changelog.dox
  2. 4
      doc/opengl-support.dox
  3. 23
      src/Magnum/GL/Implementation/RendererState.cpp
  4. 2
      src/Magnum/GL/Implementation/RendererState.h
  5. 10
      src/Magnum/GL/Implementation/driverSpecific.cpp
  6. 20
      src/Magnum/GL/Renderer.cpp
  7. 55
      src/Magnum/GL/Renderer.h
  8. 20
      src/Magnum/GL/Test/RendererGLTest.cpp

16
doc/changelog.dox

@ -129,8 +129,9 @@ See also:
extensions on GLES 3.1+, exposed as @ref GL::Texture::view() and similar
APIs on other texture types
- Implemented the GL 4.5 @gl_extension{ARB,clip_control} extension and
matching @gl_extension{EXT,clip_control} extension on GLES, exposed as
@ref GL::Renderer::setClipControl(). See also [mosra/magnum#543](https://github.com/mosra/magnum/issues/543).
matching @gl_extension{EXT,clip_control} and
@webgl_extension{WEBGL,clip_control} extension on GLES and WebGL, exposed
as @ref GL::Renderer::setClipControl(). See also [mosra/magnum#543](https://github.com/mosra/magnum/issues/543).
- Implemented @gl_extension{EXT,texture_norm16} and
@webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making
normalized 16-bit texture and renderbuffer formats available on all
@ -156,18 +157,19 @@ See also:
WebGL extensions, making @ref GL::SamplerWrapping::MirrorClampToEdge
available on all platforms
- Implemented the @m_class{m-doc-external} [ANGLE_provoking_vertex](https://chromium.googlesource.com/angle/angle/+/main/extensions/ANGLE_provoking_vertex.txt)
and @m_class{m-doc-external} [ANGLE_polygon_mode](https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/ANGLE_polygon_mode.txt)
ES extensions. Recognized also on WebGL as
@webgl_extension{WEBGL,provoking_vertex} and
@webgl_extension{WEBGL,polygon_mode} but with no implementation as
ES extension. Recognized also on WebGL as
@webgl_extension{WEBGL,provoking_vertex} but with no implementation as
Emscripten doesn't have the required entrypoints yet.
- Implemented the @m_class{m-doc-external} [ANGLE_polygon_mode](https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/ANGLE_polygon_mode.txt)
and @webgl_extension{WEBGL,polygon_mode} ES and WebGL extension.
- Implemented the @m_class{m-doc-external} [ANGLE_stencil_texturing](https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/ANGLE_stencil_texturing.txt)
ES and @webgl_extension{WEBGL,stencil_texturing} WebGL extensions
- Implemented the @gl_extension{EXT,blend_func_extended} ES and
@webgl_extension{WEBGL,blend_func_extended} WebGL extensions
- Implemented the @gl_extension{INTEL,blackhole_render} desktop and ES
extension
- Recognizing @webgl_extension{EXT,float_blend} and
- Recognizing @webgl_extension{EXT,float_blend},
@webgl_extension{EXT,polygon_offset_clamp} and
@webgl_extension{WEBGL,debug_shaders} WebGL extensions, no implementation
done yet
- Implemented @ref GL-AbstractShaderProgram-async "Async shader compilation and linking"

4
doc/opengl-support.dox

@ -576,7 +576,7 @@ Extension | Status
@webgl_extension{EXT,texture_compression_bptc} | done
@webgl_extension{EXT,texture_norm16} | done
@webgl_extension{EXT,polygon_offset_clamp} | |
@webgl_extension{EXT,clip_control} | |
@webgl_extension{EXT,clip_control} | done
@webgl_extension{EXT,depth_clamp} | done
@webgl_extension{EXT,texture_mirror_clamp_to_edge} | done
@webgl_extension{KHR,parallel_shader_compile} | done
@ -598,7 +598,7 @@ Extension | Status
@webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance} | done
@webgl_extension{WEBGL,multi_draw_instanced_base_vertex_base_instance} | done
@webgl_extension{WEBGL,provoking_vertex} | missing support in Emscripten
@webgl_extension{WEBGL,polygon_mode} | |
@webgl_extension{WEBGL,polygon_mode} | done
@webgl_extension{WEBGL,blend_func_extended} | done
@webgl_extension{WEBGL,stencil_texturing} | done

23
src/Magnum/GL/Implementation/RendererState.cpp

@ -31,6 +31,16 @@
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
/* The __EMSCRIPTEN_major__ etc macros used to be passed implicitly, version
3.1.4 moved them to a version header and version 3.1.23 dropped the
backwards compatibility. To work consistently on all versions, including the
header only if the version macros aren't present.
https://github.com/emscripten-core/emscripten/commit/f99af02045357d3d8b12e63793cef36dfde4530a
https://github.com/emscripten-core/emscripten/commit/f76ddc702e4956aeedb658c49790cc352f892e4c */
#if defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(__EMSCRIPTEN_major__)
#include <emscripten/version.h>
#endif
namespace Magnum { namespace GL { namespace Implementation {
using namespace Containers::Literals;
@ -206,7 +216,8 @@ RendererState::RendererState(Context& context, ContextState& contextState, Conta
#endif
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_WEBGL
if(context.isExtensionSupported<Extensions::NV::polygon_mode>()) {
extensions[Extensions::NV::polygon_mode::Index] =
Extensions::NV::polygon_mode::string();
@ -215,7 +226,15 @@ RendererState::RendererState(Context& context, ContextState& contextState, Conta
extensions[Extensions::ANGLE::polygon_mode::Index] =
Extensions::ANGLE::polygon_mode::string();
polygonModeImplementation = glPolygonModeANGLE;
} else {
} else
#elif __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 30166
if(context.isExtensionSupported<Extensions::WEBGL::polygon_mode>()) {
extensions[Extensions::WEBGL::polygon_mode::Index] =
Extensions::WEBGL::polygon_mode::string();
polygonModeImplementation = glPolygonModeWEBGL;
} else
#endif
{
polygonModeImplementation = nullptr;
}
#endif

2
src/Magnum/GL/Implementation/RendererState.h

@ -59,7 +59,7 @@ struct RendererState {
void(APIENTRY *blendFuncSeparateiImplementation)(GLuint, GLenum, GLenum, GLenum, GLenum);
void(APIENTRY *colorMaskiImplementation)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean);
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
#ifdef MAGNUM_TARGET_GLES
void(APIENTRY *polygonModeImplementation)(GLenum, GLenum);
#endif
#ifndef MAGNUM_TARGET_WEBGL

10
src/Magnum/GL/Implementation/driverSpecific.cpp

@ -732,6 +732,16 @@ void Context::setupDriverWorkarounds() {
#if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ < 20000
_setRequiredVersion(WEBGL::multi_draw, None);
#endif
/* EXT_clip_control, EXT_polygon_offset_clamp and WEBGL_polygon_mode
entrypoints are only available since Emscripten 3.1.66:
https://github.com/emscripten-core/emscripten/pull/20841
However, the extension is advertised even on older versions and we have
no way to link to those entrypoints there. */
#if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ < 30166
_setRequiredVersion(EXT::clip_control, None);
_setRequiredVersion(EXT::polygon_offset_clamp, None);
_setRequiredVersion(WEBGL::polygon_mode, None);
#endif
#ifndef MAGNUM_TARGET_GLES2
/* WEBGL_multi_draw_instanced_base_vertex_base_instance only since
Emscripten 2.0.5: https://github.com/emscripten-core/emscripten/pull/12282 */

20
src/Magnum/GL/Renderer.cpp

@ -33,6 +33,16 @@
#include "Magnum/GL/Implementation/State.h"
#include "Magnum/GL/Implementation/RendererState.h"
/* The __EMSCRIPTEN_major__ etc macros used to be passed implicitly, version
3.1.4 moved them to a version header and version 3.1.23 dropped the
backwards compatibility. To work consistently on all versions, including the
header only if the version macros aren't present.
https://github.com/emscripten-core/emscripten/commit/f99af02045357d3d8b12e63793cef36dfde4530a
https://github.com/emscripten-core/emscripten/commit/f76ddc702e4956aeedb658c49790cc352f892e4c */
#if defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(__EMSCRIPTEN_major__)
#include <emscripten/version.h>
#endif
namespace Magnum { namespace GL {
Range1D Renderer::lineWidthRange() {
@ -137,7 +147,6 @@ void Renderer::setProvokingVertex(const ProvokingVertex mode) {
}
#endif
#ifndef MAGNUM_TARGET_WEBGL
void Renderer::setPolygonMode(const PolygonMode mode) {
#ifndef MAGNUM_TARGET_GLES
glPolygonMode
@ -146,7 +155,6 @@ void Renderer::setPolygonMode(const PolygonMode mode) {
#endif
(GL_FRONT_AND_BACK, GLenum(mode));
}
#endif
void Renderer::setPolygonOffset(const Float factor, const Float units) {
glPolygonOffset(factor, units);
@ -331,15 +339,17 @@ void Renderer::depthRangefImplementationDefault(const Float near, const Float fa
}
#endif
#ifndef MAGNUM_TARGET_WEBGL
void Renderer::setClipControl(const ClipOrigin origin, const ClipDepth depth) {
#ifndef MAGNUM_TARGET_GLES
glClipControl(GLenum(origin), GLenum(depth));
#else
#elif !defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 30166
glClipControlEXT(GLenum(origin), GLenum(depth));
#else
static_cast<void>(origin);
static_cast<void>(depth);
CORRADE_INTERNAL_ASSERT_UNREACHABLE();
#endif
}
#endif
void Renderer::setColorMask(const GLboolean allowRed, const GLboolean allowGreen, const GLboolean allowBlue, const GLboolean allowAlpha) {
glColorMask(allowRed, allowGreen, allowBlue, allowAlpha);

55
src/Magnum/GL/Renderer.h

@ -417,7 +417,6 @@ class MAGNUM_GL_EXPORT Renderer {
*/
PolygonOffsetFill = GL_POLYGON_OFFSET_FILL,
#ifndef MAGNUM_TARGET_WEBGL
/**
* Offset lines. Note that this affects only filled polygons
* rendered with @ref setPolygonMode() set to
@ -426,15 +425,20 @@ class MAGNUM_GL_EXPORT Renderer {
* @ref setPolygonOffset()
* @requires_es_extension Extension @gl_extension{NV,polygon_offset}
* or @m_class{m-doc-external} [ANGLE_polygon_mode](https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/ANGLE_polygon_mode.txt)
* @requires_gles Only @ref Feature::PolygonOffsetFill is available
* in WebGL.
* @requires_webgl_extension Extension @webgl_extension{WEBGL,polygon_mode}.
* Note that this extension is only implemented since
* Emscripten 3.1.66 and thus it's not even advertised on
* older versions.
*/
#ifndef MAGNUM_TARGET_GLES
PolygonOffsetLine = GL_POLYGON_OFFSET_LINE,
#else
#elif !defined(MAGNUM_TARGET_WEBGL)
PolygonOffsetLine = GL_POLYGON_OFFSET_LINE_NV,
#else
PolygonOffsetLine = GL_POLYGON_OFFSET_LINE_WEBGL,
#endif
#ifndef MAGNUM_TARGET_WEBGL
/**
* Offset points. Note that this affects only filled polygons
* rendered with @ref setPolygonMode() set to
@ -442,8 +446,8 @@ class MAGNUM_GL_EXPORT Renderer {
* @see @ref Feature::PolygonOffsetFill, @ref Feature::PolygonOffsetLine,
* @ref setPolygonOffset()
* @requires_es_extension Extension @gl_extension{NV,polygon_offset}
* @requires_gles Only @ref Feature::PolygonOffsetFill is available
* in WebGL.
* @requires_gles Only @ref Feature::PolygonOffsetFill and
* @ref Feature::PolygonOffsetPoint is available in WebGL.
*/
#ifndef MAGNUM_TARGET_GLES
PolygonOffsetPoint = GL_POLYGON_OFFSET_POINT,
@ -856,7 +860,6 @@ class MAGNUM_GL_EXPORT Renderer {
static void setProvokingVertex(ProvokingVertex mode);
#endif
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Polygon mode
*
@ -866,7 +869,10 @@ class MAGNUM_GL_EXPORT Renderer {
* @m_class{m-doc-external} [ANGLE_polygon_mode](https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/ANGLE_polygon_mode.txt).
* Otherwise behaves always like @ref PolygonMode::Fill. See
* @ref Mesh::setPrimitive() for a possible workaround.
* @requires_gles WebGL behaves always like @ref PolygonMode::Fill. See
* @requires_webgl_extension Extension @webgl_extension{WEBGL,polygon_mode}.
* Note that this extension is only implemented since Emscripten
* 3.1.66 and thus it's not even advertised on older versions.
* Otherwise behaves always like @ref PolygonMode::Fill. See
* @ref Mesh::setPrimitive() for a possible workaround.
*/
enum class PolygonMode: GLenum {
@ -875,8 +881,10 @@ class MAGNUM_GL_EXPORT Renderer {
*/
#ifndef MAGNUM_TARGET_GLES
Fill = GL_FILL,
#else
#elif !defined(MAGNUM_TARGET_WEBGL)
Fill = GL_FILL_NV,
#else
Fill = GL_FILL_WEBGL,
#endif
/**
@ -884,21 +892,26 @@ class MAGNUM_GL_EXPORT Renderer {
*/
#ifndef MAGNUM_TARGET_GLES
Line = GL_LINE,
#else
#elif !defined(MAGNUM_TARGET_WEBGL)
Line = GL_LINE_NV,
#else
Line = GL_LINE_WEBGL,
#endif
#ifndef MAGNUM_TARGET_WEBGL
/**
* Starts of boundary edges are drawn as points. See also
* @ref setPointSize().
* @requires_es_extension Extension @gl_extension{NV,polygon_mode},
* not available with @m_class{m-doc-external} [ANGLE_polygon_mode](https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/ANGLE_polygon_mode.txt)
* @requires_gles Not available in @webgl_extension{WEBGL,polygon_mode}
*/
#ifndef MAGNUM_TARGET_GLES
Point = GL_POINT
#else
Point = GL_POINT_NV
#endif
#endif
};
/**
@ -910,11 +923,13 @@ class MAGNUM_GL_EXPORT Renderer {
* @m_class{m-doc-external} [ANGLE_polygon_mode](https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/ANGLE_polygon_mode.txt).
* Otherwise behaves always like the default. See
* @ref Mesh::setPrimitive() for possible workaround.
* @requires_gles WebGL behaves always like the default. See
* @requires_webgl_extension Extension @webgl_extension{WEBGL,polygon_mode}.
* Note that this extension is only implemented since Emscripten
* 3.1.66 and thus it's not even advertised on older versions.
* Otherwise behaves always like the default. See
* @ref Mesh::setPrimitive() for possible workaround.
*/
static void setPolygonMode(PolygonMode mode);
#endif
/**
* @brief Set polygon offset
@ -1234,7 +1249,6 @@ class MAGNUM_GL_EXPORT Renderer {
/** @{ @name Depth testing and clip control */
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Clip origin
* @m_since_latest
@ -1243,7 +1257,9 @@ class MAGNUM_GL_EXPORT Renderer {
* @m_enum_values_as_keywords
* @requires_gl45 Extension @gl_extension{ARB,clip_control}
* @requires_es_extension Extension @gl_extension{EXT,clip_control}
* @requires_gles Clip control is not available in WebGL.
* @requires_webgl_extension Extension @webgl_extension{EXT,clip_control}.
* Note that this extension is only implemented since Emscripten
* 3.1.66 and thus it's not even advertised on older versions.
*/
enum class ClipOrigin: GLenum {
/** Lower left */
@ -1269,7 +1285,9 @@ class MAGNUM_GL_EXPORT Renderer {
* @m_enum_values_as_keywords
* @requires_gl45 Extension @gl_extension{ARB,clip_control}
* @requires_es_extension Extension @gl_extension{EXT,clip_control}
* @requires_gles Clip control is not available in WebGL.
* @requires_webgl_extension Extension @webgl_extension{EXT,clip_control}.
* Note that this extension is only implemented since Emscripten
* 3.1.66 and thus it's not even advertised on older versions.
*/
enum class ClipDepth: GLenum {
/** -1 to 1 */
@ -1286,7 +1304,6 @@ class MAGNUM_GL_EXPORT Renderer {
ZeroToOne = GL_ZERO_TO_ONE_EXT,
#endif
};
#endif
/**
* @brief Depth function
@ -1335,7 +1352,6 @@ class MAGNUM_GL_EXPORT Renderer {
*/
static void setDepthRange(Float near, Float far);
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Set clipping behavior
* @m_since_latest
@ -1345,10 +1361,11 @@ class MAGNUM_GL_EXPORT Renderer {
* @see @fn_gl_keyword{ClipControl}
* @requires_gl45 Extension @gl_extension{ARB,clip_control}
* @requires_es_extension Extension @gl_extension{EXT,clip_control}
* @requires_gles Clip control is not available in WebGL.
* @requires_webgl_extension Extension @webgl_extension{EXT,clip_control}.
* Note that this extension is only implemented since Emscripten
* 3.1.66 and thus it's not even advertised on older versions.
*/
static void setClipControl(ClipOrigin origin, ClipDepth depth);
#endif
/* Since 1.8.17, the original short-hand group closing doesn't work
anymore. FFS. */

20
src/Magnum/GL/Test/RendererGLTest.cpp

@ -61,9 +61,7 @@ struct RendererGLTest: OpenGLTester {
void maxLineWidth();
void pointCoord();
#ifndef MAGNUM_TARGET_WEBGL
void polygonMode();
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void patchParameters();
#endif
@ -72,9 +70,7 @@ struct RendererGLTest: OpenGLTester {
void drawBuffersBlend();
#endif
template<class T> void clearDepthDepthRange();
#ifndef MAGNUM_TARGET_WEBGL
void clipControl();
#endif
private:
PluginManager::Manager<Trade::AbstractImporter> _manager{"nonexistent"};
@ -89,9 +85,7 @@ using namespace Math::Literals;
RendererGLTest::RendererGLTest() {
addTests({&RendererGLTest::maxLineWidth,
&RendererGLTest::pointCoord,
#ifndef MAGNUM_TARGET_WEBGL
&RendererGLTest::polygonMode,
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
&RendererGLTest::patchParameters,
#endif
@ -103,10 +97,7 @@ RendererGLTest::RendererGLTest() {
&RendererGLTest::clearDepthDepthRange<Double>,
#endif
&RendererGLTest::clearDepthDepthRange<Float>,
#ifndef MAGNUM_TARGET_WEBGL
&RendererGLTest::clipControl
#endif
});
&RendererGLTest::clipControl});
/* Load the plugins directly from the build tree. Otherwise they're either
static and already loaded or not present in the build tree */
@ -259,9 +250,11 @@ void RendererGLTest::pointCoord() {
(DebugTools::CompareImageToFile{_manager, maxThreshold, meanThreshold}));
}
#ifndef MAGNUM_TARGET_WEBGL
void RendererGLTest::polygonMode() {
#ifdef MAGNUM_TARGET_GLES
#ifdef MAGNUM_TARGET_WEBGL
if(!Context::current().isExtensionSupported<Extensions::WEBGL::polygon_mode>())
CORRADE_SKIP(Extensions::WEBGL::polygon_mode::string() << "is not supported.");
#elif defined(MAGNUM_TARGET_GLES)
if(!Context::current().isExtensionSupported<Extensions::NV::polygon_mode>() &&
!Context::current().isExtensionSupported<Extensions::ANGLE::polygon_mode>())
CORRADE_SKIP("Neither" << Extensions::NV::polygon_mode::string() << "nor" << Extensions::ANGLE::polygon_mode::string() << "is supported.");
@ -273,7 +266,6 @@ void RendererGLTest::polygonMode() {
Renderer::setPolygonMode(Renderer::PolygonMode::Fill);
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void RendererGLTest::patchParameters() {
@ -343,7 +335,6 @@ template<class T> void RendererGLTest::clearDepthDepthRange() {
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_WEBGL
void RendererGLTest::clipControl() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::clip_control>())
@ -359,7 +350,6 @@ void RendererGLTest::clipControl() {
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif
}}}}

Loading…
Cancel
Save