Browse Source

GL: implement {EXT,WEBGL}_blend_func_extended.

Fortunately WebGL doesn't have the EXT entrypoints in this case, so I
don't need to wait for Emscripten support.
pull/638/head
Vladimír Vondruš 2 years ago
parent
commit
04a2d9281c
  1. 4
      doc/opengl-support.dox
  2. 17
      src/Magnum/GL/AbstractShaderProgram.cpp
  3. 38
      src/Magnum/GL/AbstractShaderProgram.h
  4. 40
      src/Magnum/GL/Renderer.h
  5. 42
      src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp
  6. 2
      src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShader.vert
  7. 4
      src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShaderFragmentOutputs.frag

4
doc/opengl-support.dox

@ -481,7 +481,7 @@ Extension | Status
@gl_extension{EXT,texture_norm16} | done @gl_extension{EXT,texture_norm16} | done
@gl_extension{EXT,texture_sRGB_R8} | done @gl_extension{EXT,texture_sRGB_R8} | done
@gl_extension{EXT,texture_sRGB_RG8} | done @gl_extension{EXT,texture_sRGB_RG8} | done
@gl_extension{EXT,blend_func_extended} | | @gl_extension{EXT,blend_func_extended} | done
@gl_extension{EXT,polygon_offset_clamp} | | @gl_extension{EXT,polygon_offset_clamp} | |
@gl_extension{EXT,clip_cull_distance} | done @gl_extension{EXT,clip_cull_distance} | done
@gl_extension{EXT,texture_compression_rgtc} | done @gl_extension{EXT,texture_compression_rgtc} | done
@ -596,7 +596,7 @@ Extension | Status
@webgl_extension{WEBGL,multi_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,provoking_vertex} | missing support in Emscripten
@webgl_extension{WEBGL,polygon_mode} | missing support in Emscripten @webgl_extension{WEBGL,polygon_mode} | missing support in Emscripten
@webgl_extension{WEBGL,blend_func_extended} | | @webgl_extension{WEBGL,blend_func_extended} | done
@webgl_extension{WEBGL,stencil_texturing} | done @webgl_extension{WEBGL,stencil_texturing} | done
@section opengl-unsupported Unsupported OpenGL features @section opengl-unsupported Unsupported OpenGL features

17
src/Magnum/GL/AbstractShaderProgram.cpp

@ -551,12 +551,23 @@ void AbstractShaderProgram::bindAttributeLocation(const UnsignedInt location, co
glBindAttribLocation(_id, location, Containers::String::nullTerminatedView(name).data()); glBindAttribLocation(_id, location, Containers::String::nullTerminatedView(name).data());
} }
#ifndef MAGNUM_TARGET_GLES #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractShaderProgram::bindFragmentDataLocation(const UnsignedInt location, const Containers::StringView name) { void AbstractShaderProgram::bindFragmentDataLocation(const UnsignedInt location, const Containers::StringView name) {
glBindFragDataLocation(_id, location, Containers::String::nullTerminatedView(name).data()); #ifndef MAGNUM_TARGET_GLES
glBindFragDataLocation
#else
glBindFragDataLocationEXT
#endif
(_id, location, Containers::String::nullTerminatedView(name).data());
} }
void AbstractShaderProgram::bindFragmentDataLocationIndexed(const UnsignedInt location, UnsignedInt index, const Containers::StringView name) { void AbstractShaderProgram::bindFragmentDataLocationIndexed(const UnsignedInt location, UnsignedInt index, const Containers::StringView name) {
glBindFragDataLocationIndexed(_id, location, index, Containers::String::nullTerminatedView(name).data()); #ifndef MAGNUM_TARGET_GLES
glBindFragDataLocationIndexed
#else
glBindFragDataLocationIndexedEXT
#endif
(_id, location, index, Containers::String::nullTerminatedView(name).data());
} }
#endif #endif

38
src/Magnum/GL/AbstractShaderProgram.h

@ -178,13 +178,20 @@ out vec3 normal;
supported in OpenGL ES 2.0, use @ref bindAttributeLocation() supported in OpenGL ES 2.0, use @ref bindAttributeLocation()
instead. instead.
@requires_gles30 Multiple fragment shader outputs are not available in OpenGL @requires_gles30 Multiple fragment shader outputs are not available in OpenGL
ES 2.0, similar functionality is available in extension ES 2.0, similar functionality is available in the
@gl_extension{EXT,draw_buffers} or @gl_extension{NV,draw_buffers}. @gl_extension{EXT,draw_buffers} or @gl_extension{NV,draw_buffers}
extensions
@requires_es_extension OpenGL ES 3.0 and extension
@gl_extension{EXT,blend_func_extended} for using
@ref bindFragmentDataLocation() or @ref bindFragmentDataLocationIndexed()
@requires_webgl20 Explicit location specification of input attributes is not @requires_webgl20 Explicit location specification of input attributes is not
supported in WebGL 1.0, use @ref bindAttributeLocation() instead. supported in WebGL 1.0, use @ref bindAttributeLocation() instead.
@requires_webgl20 Multiple fragment shader outputs are not available in WebGL @requires_webgl20 Multiple fragment shader outputs are not available in WebGL
1.0, similar functionality is available in extension 1.0, similar functionality is available in the
@webgl_extension{WEBGL,draw_buffers}. @webgl_extension{WEBGL,draw_buffers} or
@webgl_extension{WEBGL,blend_func_extended} extensions. Additionally, the
@webgl_extension{WEBGL,blend_func_extended} extension doesn't support
application-side binding of fragment data locations.
@todo @gl_extension2{EXT,separate_shader_objects,EXT_separate_shader_objects.gles} @todo @gl_extension2{EXT,separate_shader_objects,EXT_separate_shader_objects.gles}
supports explicit attrib location supports explicit attrib location
@ -1437,7 +1444,7 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
*/ */
void bindAttributeLocation(UnsignedInt location, Containers::StringView name); void bindAttributeLocation(UnsignedInt location, Containers::StringView name);
#ifndef MAGNUM_TARGET_GLES #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/** /**
* @brief Bind fragment data to given location and color input index * @brief Bind fragment data to given location and color input index
* @param location Location * @param location Location
@ -1454,8 +1461,11 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
* @ref GL-AbstractShaderProgram-attribute-location "class documentation" * @ref GL-AbstractShaderProgram-attribute-location "class documentation"
* for more information. * for more information.
* @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended}
* @requires_gl Multiple blend function inputs are not available in * @requires_es_extension OpenGL ES 3.0 and extension
* OpenGL ES or WebGL. * @gl_extension{EXT,blend_func_extended}
* @requires_gles The @webgl_extension{WEBGL,blend_func_extended}
* extension doesn't support application-side binding of fragment
* data locations
*/ */
void bindFragmentDataLocationIndexed(UnsignedInt location, UnsignedInt index, Containers::StringView name); void bindFragmentDataLocationIndexed(UnsignedInt location, UnsignedInt index, Containers::StringView name);
@ -1472,10 +1482,16 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
* @ref GL-AbstractShaderProgram-attribute-location "class documentation" * @ref GL-AbstractShaderProgram-attribute-location "class documentation"
* for more information. * for more information.
* @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4}
* @requires_gl Use explicit location specification in OpenGL ES 3.0 or * @requires_es_extension OpenGL ES 3.0 and extension
* WebGL 2.0 and `gl_FragData[n]` provided by @gl_extension{NV,draw_buffers} * @gl_extension{EXT,blend_func_extended}. Alternatively use
* in OpenGL ES 2.0 and @webgl_extension{WEBGL,draw_buffers} in * explicit location specification in OpenGL ES 3.0 and
* WebGL 1.0. * `gl_FragData[n]` provided by @gl_extension{NV,draw_buffers} in
* OpenGL ES 2.0
* @requires_gles The @webgl_extension{WEBGL,blend_func_extended}
* extension doesn't support application-side binding of fragment
* data locations. Alternatively use explicit location
* specification in WebGL 2.0 and `gl_FragData[n]` provided by
* @webgl_extension{WEBGL,draw_buffers} in WebGL 1.0.
*/ */
void bindFragmentDataLocation(UnsignedInt location, Containers::StringView name); void bindFragmentDataLocation(UnsignedInt location, Containers::StringView name);
#endif #endif

40
src/Magnum/GL/Renderer.h

@ -1700,16 +1700,20 @@ class MAGNUM_GL_EXPORT Renderer {
/** Source color (@f$ RGB = (R_{s0}, G_{s0}, B_{s0}); A = A_{s0} @f$) */ /** Source color (@f$ RGB = (R_{s0}, G_{s0}, B_{s0}); A = A_{s0} @f$) */
SourceColor = GL_SRC_COLOR, SourceColor = GL_SRC_COLOR,
#ifndef MAGNUM_TARGET_GLES
/** /**
* Second source color (@f$ RGB = (R_{s1}, G_{s1}, B_{s1}); A = A_{s1} @f$) * Second source color (@f$ RGB = (R_{s1}, G_{s1}, B_{s1}); A = A_{s1} @f$)
* *
* @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() * @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed()
* @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended}
* @requires_gl Multiple blending inputs are not available in * @requires_es_extension Extension
* OpenGL ES and WebGL. * @gl_extension{EXT,blend_func_extended}
* @requires_webgl_extension Extension
* @webgl_extension{WEBGL,blend_func_extended}
*/ */
#ifndef MAGNUM_TARGET_GLES
SecondSourceColor = GL_SRC1_COLOR, SecondSourceColor = GL_SRC1_COLOR,
#else
SecondSourceColor = GL_SRC1_COLOR_EXT,
#endif #endif
/** /**
@ -1717,16 +1721,20 @@ class MAGNUM_GL_EXPORT Renderer {
*/ */
OneMinusSourceColor = GL_ONE_MINUS_SRC_COLOR, OneMinusSourceColor = GL_ONE_MINUS_SRC_COLOR,
#ifndef MAGNUM_TARGET_GLES
/** /**
* One minus second source color (@f$ RGB = (1.0 - R_{s1}, 1.0 - G_{s1}, 1.0 - B_{s1}); A = 1.0 - A_{s1} @f$) * One minus second source color (@f$ RGB = (1.0 - R_{s1}, 1.0 - G_{s1}, 1.0 - B_{s1}); A = 1.0 - A_{s1} @f$)
* *
* @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() * @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed()
* @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended}
* @requires_gl Multiple blending inputs are not available in * @requires_es_extension Extension
* OpenGL ES and WebGL. * @gl_extension{EXT,blend_func_extended}
* @requires_webgl_extension Extension
* @webgl_extension{WEBGL,blend_func_extended}
*/ */
#ifndef MAGNUM_TARGET_GLES
OneMinusSecondSourceColor = GL_ONE_MINUS_SRC1_COLOR, OneMinusSecondSourceColor = GL_ONE_MINUS_SRC1_COLOR,
#else
OneMinusSecondSourceColor = GL_ONE_MINUS_SRC1_COLOR_EXT,
#endif #endif
/** Source alpha (@f$ RGB = (A_{s0}, A_{s0}, A_{s0}); A = A_{s0} @f$) */ /** Source alpha (@f$ RGB = (A_{s0}, A_{s0}, A_{s0}); A = A_{s0} @f$) */
@ -1739,16 +1747,20 @@ class MAGNUM_GL_EXPORT Renderer {
*/ */
SourceAlphaSaturate = GL_SRC_ALPHA_SATURATE, SourceAlphaSaturate = GL_SRC_ALPHA_SATURATE,
#ifndef MAGNUM_TARGET_GLES
/** /**
* Second source alpha (@f$ RGB = (A_{s1}, A_{s1}, A_{s1}); A = A_{s1} @f$) * Second source alpha (@f$ RGB = (A_{s1}, A_{s1}, A_{s1}); A = A_{s1} @f$)
* *
* @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() * @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed()
* @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended}
* @requires_gl Multiple blending inputs are not available in * @requires_es_extension Extension
* OpenGL ES and WebGL. * @gl_extension{EXT,blend_func_extended}
* @requires_webgl_extension Extension
* @webgl_extension{WEBGL,blend_func_extended}
*/ */
#ifndef MAGNUM_TARGET_GLES
SecondSourceAlpha = GL_SRC1_ALPHA, SecondSourceAlpha = GL_SRC1_ALPHA,
#else
SecondSourceAlpha = GL_SRC1_ALPHA_EXT,
#endif #endif
/** /**
@ -1756,16 +1768,20 @@ class MAGNUM_GL_EXPORT Renderer {
*/ */
OneMinusSourceAlpha = GL_ONE_MINUS_SRC_ALPHA, OneMinusSourceAlpha = GL_ONE_MINUS_SRC_ALPHA,
#ifndef MAGNUM_TARGET_GLES
/** /**
* One minus second source alpha (@f$ RGB = (1.0 - A_{s1}, 1.0 - A_{s1}, 1.0 - A_{s1}); A = 1.0 - A_{s1} @f$) * One minus second source alpha (@f$ RGB = (1.0 - A_{s1}, 1.0 - A_{s1}, 1.0 - A_{s1}); A = 1.0 - A_{s1} @f$)
* *
* @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() * @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed()
* @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended}
* @requires_gl Multiple blending inputs are not available in * @requires_es_extension Extension
* OpenGL ES and WebGL. * @gl_extension{EXT,blend_func_extended}
* @requires_webgl_extension Extension
* @webgl_extension{WEBGL,blend_func_extended}
*/ */
#ifndef MAGNUM_TARGET_GLES
OneMinusSecondSourceAlpha = GL_ONE_MINUS_SRC1_ALPHA, OneMinusSecondSourceAlpha = GL_ONE_MINUS_SRC1_ALPHA,
#else
OneMinusSecondSourceAlpha = GL_ONE_MINUS_SRC1_ALPHA_EXT,
#endif #endif
/** Destination color (@f$ RGB = (R_d, G_d, B_d); A = A_d @f$) */ /** Destination color (@f$ RGB = (R_d, G_d, B_d); A = A_d @f$) */

42
src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp

@ -77,7 +77,7 @@ struct AbstractShaderProgramGLTest: OpenGLTester {
void create(); void create();
void createMultipleOutputs(); void createMultipleOutputs();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2
void createMultipleOutputsIndexed(); void createMultipleOutputsIndexed();
#endif #endif
void createAsync(); void createAsync();
@ -179,7 +179,7 @@ AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() {
addInstancedTests({ addInstancedTests({
&AbstractShaderProgramGLTest::createMultipleOutputs, &AbstractShaderProgramGLTest::createMultipleOutputs,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2
&AbstractShaderProgramGLTest::createMultipleOutputsIndexed, &AbstractShaderProgramGLTest::createMultipleOutputsIndexed,
#endif #endif
}, Containers::arraySize(CreateMultipleOutputsData)); }, Containers::arraySize(CreateMultipleOutputsData));
@ -292,7 +292,7 @@ void AbstractShaderProgramGLTest::label() {
struct MyPublicShader: AbstractShaderProgram { struct MyPublicShader: AbstractShaderProgram {
using AbstractShaderProgram::attachShaders; using AbstractShaderProgram::attachShaders;
using AbstractShaderProgram::bindAttributeLocation; using AbstractShaderProgram::bindAttributeLocation;
#ifndef MAGNUM_TARGET_GLES #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
using AbstractShaderProgram::bindFragmentDataLocationIndexed; using AbstractShaderProgram::bindFragmentDataLocationIndexed;
using AbstractShaderProgram::bindFragmentDataLocation; using AbstractShaderProgram::bindFragmentDataLocation;
#endif #endif
@ -452,14 +452,21 @@ void AbstractShaderProgramGLTest::createMultipleOutputs() {
auto&& data = CreateMultipleOutputsData[testCaseInstanceId()]; auto&& data = CreateMultipleOutputsData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
#else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::blend_func_extended>())
CORRADE_SKIP(GL::Extensions::EXT::blend_func_extended::string() << "is not supported.");
#endif
Utility::Resource rs("AbstractShaderProgramGLTest"); Utility::Resource rs("AbstractShaderProgramGLTest");
Shader vert( Shader vert(
#ifndef CORRADE_TARGET_APPLE #ifdef MAGNUM_TARGET_GLES
Version::GLES300
#elif !defined(CORRADE_TARGET_APPLE)
Version::GL210 Version::GL210
#else #else
Version::GL310 Version::GL310
@ -469,7 +476,9 @@ void AbstractShaderProgramGLTest::createMultipleOutputs() {
const bool vertCompiled = vert.compile(); const bool vertCompiled = vert.compile();
Shader frag( Shader frag(
#ifndef CORRADE_TARGET_APPLE #ifdef MAGNUM_TARGET_GLES
Version::GLES300
#elif !defined(CORRADE_TARGET_APPLE)
Version::GL300 Version::GL300
#else #else
Version::GL310 Version::GL310
@ -503,27 +512,35 @@ void AbstractShaderProgramGLTest::createMultipleOutputs() {
#endif #endif
CORRADE_VERIFY(valid); CORRADE_VERIFY(valid);
} }
#elif !defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_WEBGL)
CORRADE_SKIP("Only explicit location specification supported in ES 3.0."); CORRADE_SKIP("Only explicit location specification supported in WebGL 2.0.");
#else #else
CORRADE_SKIP("Only gl_FragData[n] supported in ES 2.0."); CORRADE_SKIP("Only gl_FragData[n] supported in ES 2.0.");
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2
void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() { void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() {
auto&& data = CreateMultipleOutputsData[testCaseInstanceId()]; auto&& data = CreateMultipleOutputsData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
#ifndef MAGNUM_TARGET_WEBGL
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::blend_func_extended>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::blend_func_extended>())
CORRADE_SKIP(GL::Extensions::ARB::blend_func_extended::string() << "is not supported."); CORRADE_SKIP(GL::Extensions::ARB::blend_func_extended::string() << "is not supported.");
#else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::blend_func_extended>())
CORRADE_SKIP(GL::Extensions::EXT::blend_func_extended::string() << "is not supported.");
#endif
Utility::Resource rs("AbstractShaderProgramGLTest"); Utility::Resource rs("AbstractShaderProgramGLTest");
Shader vert( Shader vert(
#ifndef CORRADE_TARGET_APPLE #ifdef MAGNUM_TARGET_GLES
Version::GLES300
#elif !defined(CORRADE_TARGET_APPLE)
Version::GL210 Version::GL210
#else #else
Version::GL310 Version::GL310
@ -533,7 +550,9 @@ void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() {
const bool vertCompiled = vert.compile(); const bool vertCompiled = vert.compile();
Shader frag( Shader frag(
#ifndef CORRADE_TARGET_APPLE #ifdef MAGNUM_TARGET_GLES
Version::GLES300
#elif !defined(CORRADE_TARGET_APPLE)
Version::GL300 Version::GL300
#else #else
Version::GL310 Version::GL310
@ -565,6 +584,9 @@ void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() {
#endif #endif
CORRADE_VERIFY(valid); CORRADE_VERIFY(valid);
} }
#else
CORRADE_SKIP("Only explicit location specification supported in WebGL 2.0.");
#endif
} }
#endif #endif

2
src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShader.vert

@ -2,7 +2,7 @@
#define mediump #define mediump
#endif #endif
#if defined(GL_ES) || __VERSION__ == 120 #if (defined(GL_ES) && __VERSION__ == 100) || __VERSION__ == 120
#define in attribute #define in attribute
#endif #endif

4
src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShaderFragmentOutputs.frag

@ -1,5 +1,5 @@
out vec4 first; out lowp vec4 first;
out vec3 second; out lowp vec3 second;
void main() { void main() {
first = vec4(1.0, 0.3, 0.5, 0.1); first = vec4(1.0, 0.3, 0.5, 0.1);

Loading…
Cancel
Save