From 04a2d9281cefd2af2273e109d686a23f56bdaba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 14 Feb 2024 20:42:48 +0100 Subject: [PATCH] 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. --- doc/opengl-support.dox | 4 +- src/Magnum/GL/AbstractShaderProgram.cpp | 17 ++++++-- src/Magnum/GL/AbstractShaderProgram.h | 38 ++++++++++++----- src/Magnum/GL/Renderer.h | 40 ++++++++++++------ .../GL/Test/AbstractShaderProgramGLTest.cpp | 42 ++++++++++++++----- .../MyShader.vert | 2 +- .../MyShaderFragmentOutputs.frag | 4 +- 7 files changed, 106 insertions(+), 41 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index cad12726b..98ca66377 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -481,7 +481,7 @@ Extension | Status @gl_extension{EXT,texture_norm16} | done @gl_extension{EXT,texture_sRGB_R8} | 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,clip_cull_distance} | 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,provoking_vertex} | 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 @section opengl-unsupported Unsupported OpenGL features diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index c669c4366..ab8428f96 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -551,12 +551,23 @@ void AbstractShaderProgram::bindAttributeLocation(const UnsignedInt location, co 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) { - 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) { - 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 diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index fc254915d..2f6ce457e 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -178,13 +178,20 @@ out vec3 normal; supported in OpenGL ES 2.0, use @ref bindAttributeLocation() instead. @requires_gles30 Multiple fragment shader outputs are not available in OpenGL - ES 2.0, similar functionality is available in extension - @gl_extension{EXT,draw_buffers} or @gl_extension{NV,draw_buffers}. + ES 2.0, similar functionality is available in the + @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 supported in WebGL 1.0, use @ref bindAttributeLocation() instead. @requires_webgl20 Multiple fragment shader outputs are not available in WebGL - 1.0, similar functionality is available in extension - @webgl_extension{WEBGL,draw_buffers}. + 1.0, similar functionality is available in the + @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} supports explicit attrib location @@ -1437,7 +1444,7 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { */ 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 * @param location Location @@ -1454,8 +1461,11 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { * @ref GL-AbstractShaderProgram-attribute-location "class documentation" * for more information. * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} - * @requires_gl Multiple blend function inputs are not available in - * OpenGL ES or WebGL. + * @requires_es_extension OpenGL ES 3.0 and extension + * @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); @@ -1472,10 +1482,16 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { * @ref GL-AbstractShaderProgram-attribute-location "class documentation" * for more information. * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gl Use explicit location specification in OpenGL ES 3.0 or - * WebGL 2.0 and `gl_FragData[n]` provided by @gl_extension{NV,draw_buffers} - * in OpenGL ES 2.0 and @webgl_extension{WEBGL,draw_buffers} in - * WebGL 1.0. + * @requires_es_extension OpenGL ES 3.0 and extension + * @gl_extension{EXT,blend_func_extended}. Alternatively use + * explicit location specification in OpenGL ES 3.0 and + * `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); #endif diff --git a/src/Magnum/GL/Renderer.h b/src/Magnum/GL/Renderer.h index ee88e6674..9cc4ae81e 100644 --- a/src/Magnum/GL/Renderer.h +++ b/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$) */ SourceColor = GL_SRC_COLOR, - #ifndef MAGNUM_TARGET_GLES /** * Second source color (@f$ RGB = (R_{s1}, G_{s1}, B_{s1}); A = A_{s1} @f$) * * @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} - * @requires_gl Multiple blending inputs are not available in - * OpenGL ES and WebGL. + * @requires_es_extension Extension + * @gl_extension{EXT,blend_func_extended} + * @requires_webgl_extension Extension + * @webgl_extension{WEBGL,blend_func_extended} */ + #ifndef MAGNUM_TARGET_GLES SecondSourceColor = GL_SRC1_COLOR, + #else + SecondSourceColor = GL_SRC1_COLOR_EXT, #endif /** @@ -1717,16 +1721,20 @@ class MAGNUM_GL_EXPORT Renderer { */ 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$) * * @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} - * @requires_gl Multiple blending inputs are not available in - * OpenGL ES and WebGL. + * @requires_es_extension Extension + * @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, + #else + OneMinusSecondSourceColor = GL_ONE_MINUS_SRC1_COLOR_EXT, #endif /** 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, - #ifndef MAGNUM_TARGET_GLES /** * Second source alpha (@f$ RGB = (A_{s1}, A_{s1}, A_{s1}); A = A_{s1} @f$) * * @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} - * @requires_gl Multiple blending inputs are not available in - * OpenGL ES and WebGL. + * @requires_es_extension Extension + * @gl_extension{EXT,blend_func_extended} + * @requires_webgl_extension Extension + * @webgl_extension{WEBGL,blend_func_extended} */ + #ifndef MAGNUM_TARGET_GLES SecondSourceAlpha = GL_SRC1_ALPHA, + #else + SecondSourceAlpha = GL_SRC1_ALPHA_EXT, #endif /** @@ -1756,16 +1768,20 @@ class MAGNUM_GL_EXPORT Renderer { */ 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$) * * @see @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() * @requires_gl33 Extension @gl_extension{ARB,blend_func_extended} - * @requires_gl Multiple blending inputs are not available in - * OpenGL ES and WebGL. + * @requires_es_extension Extension + * @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, + #else + OneMinusSecondSourceAlpha = GL_ONE_MINUS_SRC1_ALPHA_EXT, #endif /** Destination color (@f$ RGB = (R_d, G_d, B_d); A = A_d @f$) */ diff --git a/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp b/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp index a2d6c70b4..b63130e2b 100644 --- a/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp +++ b/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp @@ -77,7 +77,7 @@ struct AbstractShaderProgramGLTest: OpenGLTester { void create(); void createMultipleOutputs(); - #ifndef MAGNUM_TARGET_GLES + #ifndef MAGNUM_TARGET_GLES2 void createMultipleOutputsIndexed(); #endif void createAsync(); @@ -179,7 +179,7 @@ AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() { addInstancedTests({ &AbstractShaderProgramGLTest::createMultipleOutputs, - #ifndef MAGNUM_TARGET_GLES + #ifndef MAGNUM_TARGET_GLES2 &AbstractShaderProgramGLTest::createMultipleOutputsIndexed, #endif }, Containers::arraySize(CreateMultipleOutputsData)); @@ -292,7 +292,7 @@ void AbstractShaderProgramGLTest::label() { struct MyPublicShader: AbstractShaderProgram { using AbstractShaderProgram::attachShaders; using AbstractShaderProgram::bindAttributeLocation; - #ifndef MAGNUM_TARGET_GLES + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) using AbstractShaderProgram::bindFragmentDataLocationIndexed; using AbstractShaderProgram::bindFragmentDataLocation; #endif @@ -452,14 +452,21 @@ void AbstractShaderProgramGLTest::createMultipleOutputs() { auto&& data = CreateMultipleOutputsData[testCaseInstanceId()]; setTestCaseDescription(data.name); + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::blend_func_extended::string() << "is not supported."); + #endif Utility::Resource rs("AbstractShaderProgramGLTest"); Shader vert( - #ifndef CORRADE_TARGET_APPLE + #ifdef MAGNUM_TARGET_GLES + Version::GLES300 + #elif !defined(CORRADE_TARGET_APPLE) Version::GL210 #else Version::GL310 @@ -469,7 +476,9 @@ void AbstractShaderProgramGLTest::createMultipleOutputs() { const bool vertCompiled = vert.compile(); Shader frag( - #ifndef CORRADE_TARGET_APPLE + #ifdef MAGNUM_TARGET_GLES + Version::GLES300 + #elif !defined(CORRADE_TARGET_APPLE) Version::GL300 #else Version::GL310 @@ -503,27 +512,35 @@ void AbstractShaderProgramGLTest::createMultipleOutputs() { #endif CORRADE_VERIFY(valid); } - #elif !defined(MAGNUM_TARGET_GLES2) - CORRADE_SKIP("Only explicit location specification supported in ES 3.0."); + #elif defined(MAGNUM_TARGET_WEBGL) + CORRADE_SKIP("Only explicit location specification supported in WebGL 2.0."); #else CORRADE_SKIP("Only gl_FragData[n] supported in ES 2.0."); #endif } -#ifndef MAGNUM_TARGET_GLES +#ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() { auto&& data = CreateMultipleOutputsData[testCaseInstanceId()]; setTestCaseDescription(data.name); + #ifndef MAGNUM_TARGET_WEBGL + #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::blend_func_extended::string() << "is not supported."); + #else + if(!GL::Context::current().isExtensionSupported()) + CORRADE_SKIP(GL::Extensions::EXT::blend_func_extended::string() << "is not supported."); + #endif Utility::Resource rs("AbstractShaderProgramGLTest"); Shader vert( - #ifndef CORRADE_TARGET_APPLE + #ifdef MAGNUM_TARGET_GLES + Version::GLES300 + #elif !defined(CORRADE_TARGET_APPLE) Version::GL210 #else Version::GL310 @@ -533,7 +550,9 @@ void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() { const bool vertCompiled = vert.compile(); Shader frag( - #ifndef CORRADE_TARGET_APPLE + #ifdef MAGNUM_TARGET_GLES + Version::GLES300 + #elif !defined(CORRADE_TARGET_APPLE) Version::GL300 #else Version::GL310 @@ -565,6 +584,9 @@ void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() { #endif CORRADE_VERIFY(valid); } + #else + CORRADE_SKIP("Only explicit location specification supported in WebGL 2.0."); + #endif } #endif diff --git a/src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShader.vert b/src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShader.vert index d839d0f7e..0c2e5541c 100644 --- a/src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShader.vert +++ b/src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShader.vert @@ -2,7 +2,7 @@ #define mediump #endif -#if defined(GL_ES) || __VERSION__ == 120 +#if (defined(GL_ES) && __VERSION__ == 100) || __VERSION__ == 120 #define in attribute #endif diff --git a/src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShaderFragmentOutputs.frag b/src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShaderFragmentOutputs.frag index ae85b17ba..457c1b539 100644 --- a/src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShaderFragmentOutputs.frag +++ b/src/Magnum/GL/Test/AbstractShaderProgramGLTestFiles/MyShaderFragmentOutputs.frag @@ -1,5 +1,5 @@ -out vec4 first; -out vec3 second; +out lowp vec4 first; +out lowp vec3 second; void main() { first = vec4(1.0, 0.3, 0.5, 0.1);