diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 359fa3301..304705c65 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -60,6 +60,7 @@ set(Magnum_SRCS Implementation/ShaderProgramState.cpp Implementation/State.cpp Implementation/TextureState.cpp + Implementation/setupDriverWorkarounds.cpp Trade/AbstractImageConverter.cpp Trade/AbstractImporter.cpp diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 470496409..d5ccbaa08 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -369,7 +369,6 @@ Context::Context() { glGetIntegerv(GL_CONTEXT_FLAGS, reinterpret_cast(&_flags)); #endif - /* Get first future (not supported) version */ std::vector versions{ #ifndef MAGNUM_TARGET_GLES Version::GL300, @@ -387,10 +386,17 @@ Context::Context() { #endif Version::None }; + + /* Get first future (not supported) version */ std::size_t future = 0; while(versions[future] != Version::None && isVersionSupported(versions[future])) ++future; + /* Mark all extensions from past versions as supported */ + for(std::size_t i = 0; i != future; ++i) + for(const Extension& extension: Extension::extensions(versions[i])) + extensionStatus.set(extension._index); + /* List of extensions from future versions (extensions from current and previous versions should be supported automatically, so we don't need to check for them) */ @@ -446,44 +452,17 @@ Context::Context() { } #endif - /* Disable extensions for which we need extension loader, as they would - crash otherwise. */ - /** @todo Remove this when extension loader for ES is available */ - #ifdef MAGNUM_TARGET_GLES - #define _disable(prefix, vendor, extension) \ - extensionStatus.reset(Extensions::prefix::vendor::extension::Index); - #ifndef CORRADE_TARGET_NACL - _disable(GL,CHROMIUM,map_sub) - #endif - _disable(GL,EXT,debug_label) - _disable(GL,EXT,debug_marker) - _disable(GL,EXT,disjoint_timer_query) - _disable(GL,EXT,separate_shader_objects) - _disable(GL,EXT,multisampled_render_to_texture) - _disable(GL,EXT,robustness) - _disable(GL,KHR,debug) - _disable(GL,NV,read_buffer_front) - _disable(GL,OES,mapbuffer) - #ifdef MAGNUM_TARGET_GLES2 - _disable(GL,ANGLE,framebuffer_blit) - _disable(GL,ANGLE,framebuffer_multisample) - _disable(GL,APPLE,framebuffer_multisample) - _disable(GL,EXT,discard_framebuffer) - _disable(GL,EXT,blend_minmax) - #ifndef CORRADE_TARGET_NACL - _disable(GL,EXT,occlusion_query_boolean) - #endif - _disable(GL,EXT,texture_storage) - _disable(GL,EXT,map_buffer_range) - _disable(GL,NV,draw_buffers) - _disable(GL,NV,fbo_color_attachments) // ?? - _disable(GL,NV,read_buffer) - _disable(GL,NV,framebuffer_multisample) - _disable(GL,OES,texture_3D) - _disable(GL,OES,vertex_array_object) - #endif - #undef _disable - #endif + /* Reset minimal required version to Version::None for whole array */ + for(auto& i: _extensionRequiredVersion) i = Version::None; + + /* Initialize required versions from extension info */ + for(const auto version: versions) + for(const Extension& extension: Extension::extensions(version)) + _extensionRequiredVersion[extension._index] = extension._requiredVersion; + + /* Setup driver workarounds (increase required version for particular + extensions), see Implementation/driverWorkarounds.cpp */ + setupDriverWorkarounds(); /* Set this context as current */ CORRADE_ASSERT(!_current, "Context: Another context currently active", ); diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index 89bb24747..088f585d0 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -30,6 +30,7 @@ */ #include +#include #include #include #include @@ -291,11 +292,12 @@ class MAGNUM_EXPORT Context { * @endcode * * @see isExtensionSupported(const Extension&) const, - * @ref MAGNUM_ASSERT_EXTENSION_SUPPORTED() + * @ref MAGNUM_ASSERT_EXTENSION_SUPPORTED(), + * @ref isExtensionDisabled() * @todoc Explicit reference when Doxygen is sane */ template bool isExtensionSupported() const { - return isVersionSupported(T::coreVersion()) || (isVersionSupported(T::requiredVersion()) && extensionStatus[T::Index]); + return isExtensionSupported(version()); } /** @@ -314,7 +316,7 @@ class MAGNUM_EXPORT Context { * @endcode */ template bool isExtensionSupported(Version version) const { - return T::coreVersion() <= version || (T::requiredVersion() <= version && extensionStatus[T::Index]); + return _extensionRequiredVersion[T::Index] <= version && extensionStatus[T::Index]; } /** @@ -323,12 +325,44 @@ class MAGNUM_EXPORT Context { * Can be used e.g. for listing extensions available on current * hardware, but for general usage prefer isExtensionSupported() const, * as it does most operations in compile time. - * * @see @ref supportedExtensions(), @ref Extension::extensions(), * @ref MAGNUM_ASSERT_EXTENSION_SUPPORTED() */ bool isExtensionSupported(const Extension& extension) const { - return isVersionSupported(extension._coreVersion) || (isVersionSupported(extension._requiredVersion) && extensionStatus[extension._index]); + return isVersionSupported(_extensionRequiredVersion[extension._index]) && extensionStatus[extension._index]; + } + + /** + * @brief Whether given extension is supported by the driver but disabled + * + * Can be used for detecting driver bug workarounds. Disabled + * extensions return `false` in @ref isExtensionSupported() even if + * they are advertised as being supported by the driver. + */ + template bool isExtensionDisabled() const { + return isExtensionDisabled(version()); + } + + /** + * @brief Whether given extension is supported by the driver but disabled for given version + * + * Similar to above, but can also check for extensions which are + * disabled only for particular versions. + */ + template bool isExtensionDisabled(Version version) const { + /* The extension is advertised, but the minimal version has been increased */ + return T::requiredVersion() <= version && extensionStatus[T::Index] && _extensionRequiredVersion[T::Index] > version; + } + + /** + * @brief Whether given extension is supported by the driver but disabled + * + * Can be used e.g. for listing extensions available on current + * hardware, but for general usage prefer isExtensionDisabled() const, + * as it does most operations in compile time. + */ + bool isExtensionDisabled(const Extension& extension) const { + return isVersionSupported(extension._requiredVersion) && extensionStatus[extension._index] && !isVersionSupported(_extensionRequiredVersion[extension._index]); } #ifndef DOXYGEN_GENERATING_OUTPUT @@ -338,11 +372,14 @@ class MAGNUM_EXPORT Context { private: static Context* _current; + MAGNUM_LOCAL void setupDriverWorkarounds(); + Version _version; Int _majorVersion; Int _minorVersion; Flags _flags; + std::array _extensionRequiredVersion; std::bitset<160> extensionStatus; std::vector _supportedExtensions; diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index 67ef86c65..d9271cffc 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -101,7 +101,7 @@ namespace GL { _extension(GL,ARB,texture_query_lod, GL210, GL400) // #73 _extension(GL,ARB,texture_compression_bptc, GL310, GL420) // #77 _extension(GL,ARB,blend_func_extended, GL210, GL330) // #78 - _extension(GL,ARB,explicit_attrib_location, /*!*/ GL320, GL330) // #79 + _extension(GL,ARB,explicit_attrib_location, GL210, GL330) // #79 _extension(GL,ARB,occlusion_query2, GL210, GL330) // #80 _extension(GL,ARB,sampler_objects, GL210, GL330) // #81 _extension(GL,ARB,shader_bit_encoding, /*?*/ GL210, GL330) // #82 @@ -125,7 +125,7 @@ namespace GL { _extension(GL,ARB,viewport_array, GL210, GL410) // #100 _extension(GL,ARB,robustness, GL210, None) // #105 _extension(GL,ARB,base_instance, GL210, GL420) // #107 - _extension(GL,ARB,shading_language_420pack, /*!*/ GL320, GL420) // #108 + _extension(GL,ARB,shading_language_420pack, GL300, GL420) // #108 _extension(GL,ARB,transform_feedback_instanced, GL210, GL420) // #109 _extension(GL,ARB,compressed_texture_pixel_storage, GL210, GL420) // #110 _extension(GL,ARB,conservative_depth, GL300, GL420) // #111 @@ -142,7 +142,7 @@ namespace GL { _extension(GL,ARB,texture_view, GL210, GL430) // #124 _extension(GL,ARB,vertex_attrib_binding, GL210, GL430) // #125 _extension(GL,ARB,ES3_compatibility, GL330, GL430) // #127 - _extension(GL,ARB,explicit_uniform_location, /*!*/ GL320, GL430) // #128 + _extension(GL,ARB,explicit_uniform_location, GL210, GL430) // #128 _extension(GL,ARB,fragment_layer_viewport, GL300, GL430) // #129 _extension(GL,ARB,framebuffer_no_attachments, GL210, GL430) // #130 _extension(GL,ARB,internalformat_query2, GL210, GL430) // #131 @@ -296,21 +296,6 @@ namespace GL { #undef _extension #endif -/* - Notes (marked with ! above) - - ARB_explicit_attrib_location, ARB_explicit_uniform_location don't work - with GLSL 1.20 (compiler error related to layout qualifier on Mesa), 1.30 - (compiler error related to layout qualifier on NVidia) or 1.40 (compiler - error on Mac OS X), bumping minimal required version to GL 3.2 even if both - have *2.1* as minimal. - - ARB_shading_language_420pack (particularly sampler bindings) doesn't work - with GLSL 1.40 (compiler error related to layout qualifier, similar to the - above), bumping minimal required version to GL 3.2 even that it has *3.0* - as minimal. -*/ - } } diff --git a/src/Magnum/Implementation/setupDriverWorkarounds.cpp b/src/Magnum/Implementation/setupDriverWorkarounds.cpp new file mode 100644 index 000000000..5c0799c9a --- /dev/null +++ b/src/Magnum/Implementation/setupDriverWorkarounds.cpp @@ -0,0 +1,91 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + 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 "Magnum/Context.h" +#include "Magnum/Extensions.h" + +namespace Magnum { + +void Context::setupDriverWorkarounds() { + #define _setRequiredVersion(extension, version) \ + if(_extensionRequiredVersion[Extensions::extension::Index] < Version::version) \ + _extensionRequiredVersion[Extensions::extension::Index] = Version::version + + #ifndef MAGNUM_TARGET_GLES + /* This extension causes crash in GLSL compiler on AMD linux drivers 13.251 */ + const std::string renderer = rendererString(); + if(renderer.find("Advanced Micro Devices") != std::string::npos) + _setRequiredVersion(GL::ARB::explicit_uniform_location, None); + #endif + + #ifndef MAGNUM_TARGET_GLES + /* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL 1.30 + on NVidia and 1.40 on Mac OS X */ + /** @todo Different version on different vendors? */ + _setRequiredVersion(GL::ARB::explicit_attrib_location, GL320); + _setRequiredVersion(GL::ARB::explicit_uniform_location, GL320); + _setRequiredVersion(GL::ARB::shading_language_420pack, GL320); + #endif + + #ifdef MAGNUM_TARGET_GLES + /* Disable extensions for which we need extension loader, as they would + crash otherwise. */ + /** @todo Remove this when extension loader for ES is available */ + #ifndef CORRADE_TARGET_NACL + _setRequiredVersion(GL::CHROMIUM::map_sub, None); + #endif + _setRequiredVersion(GL::EXT::debug_label, None); + _setRequiredVersion(GL::EXT::debug_marker, None); + _setRequiredVersion(GL::EXT::disjoint_timer_query, None); + _setRequiredVersion(GL::EXT::separate_shader_objects, None); + _setRequiredVersion(GL::EXT::multisampled_render_to_texture, None); + _setRequiredVersion(GL::EXT::robustness, None); + _setRequiredVersion(GL::KHR::debug, None); + _setRequiredVersion(GL::NV::read_buffer_front, None); + _setRequiredVersion(GL::OES::mapbuffer, None); + #ifdef MAGNUM_TARGET_GLES2 + _setRequiredVersion(GL::ANGLE::framebuffer_blit, None); + _setRequiredVersion(GL::ANGLE::framebuffer_multisample, None); + _setRequiredVersion(GL::APPLE::framebuffer_multisample, None); + _setRequiredVersion(GL::EXT::discard_framebuffer, None); + _setRequiredVersion(GL::EXT::blend_minmax, None); + #ifndef CORRADE_TARGET_NACL + _setRequiredVersion(GL::EXT::occlusion_query_boolean, None); + #endif + _setRequiredVersion(GL::EXT::texture_storage, None); + _setRequiredVersion(GL::EXT::map_buffer_range, None); + _setRequiredVersion(GL::NV::draw_buffers, None); + _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ?? + _setRequiredVersion(GL::NV::read_buffer, None); + _setRequiredVersion(GL::NV::framebuffer_multisample, None); + _setRequiredVersion(GL::OES::texture_3D, None); + _setRequiredVersion(GL::OES::vertex_array_object, None); + #endif + #endif + + #undef _setRequiredVersion +} + +} diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index 3cef8bebc..5e83b4762 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -168,7 +168,6 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat Version::GL430, Version::GL440, #else - Version::GLES200, Version::GLES300, #endif Version::None @@ -194,10 +193,12 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat d << " " << extensionName << std::string(60-extensionName.size(), ' '); if(c->isExtensionSupported(extension)) d << "SUPPORTED"; + else if(c->isExtensionDisabled(extension)) + d << " removed"; else if(c->isVersionSupported(extension.requiredVersion())) d << " -"; else - d << " ---"; + d << " n/a"; } Debug() << ""; diff --git a/src/Magnum/Shaders/CMakeLists.txt b/src/Magnum/Shaders/CMakeLists.txt index 0405f7529..8b2e16a16 100644 --- a/src/Magnum/Shaders/CMakeLists.txt +++ b/src/Magnum/Shaders/CMakeLists.txt @@ -33,6 +33,9 @@ set(MagnumShaders_SRCS Phong.cpp Vector.cpp VertexColor.cpp + + Implementation/CreateCompatibilityShader.cpp + ${MagnumShaders_RCS}) set(MagnumShaders_HEADERS diff --git a/src/Magnum/Shaders/DistanceFieldVector.cpp b/src/Magnum/Shaders/DistanceFieldVector.cpp index dba501371..88f2a1236 100644 --- a/src/Magnum/Shaders/DistanceFieldVector.cpp +++ b/src/Magnum/Shaders/DistanceFieldVector.cpp @@ -31,6 +31,8 @@ #include "Magnum/Extensions.h" #include "Magnum/Shader.h" +#include "Implementation/CreateCompatibilityShader.h" + namespace Magnum { namespace Shaders { namespace { @@ -51,16 +53,14 @@ template DistanceFieldVector::DistanceFieldV #endif Version version = Context::current()->supportedVersion(vs); - Shader frag(version, Shader::Type::Vertex); - frag.addSource(rs.get("compatibility.glsl")) - .addSource(rs.get("generic.glsl")) + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + frag.addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); AbstractShaderProgram::attachShader(frag); - Shader vert(version, Shader::Type::Fragment); - vert.addSource(rs.get("compatibility.glsl")) - .addSource(rs.get("DistanceFieldVector.frag")); + Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + vert.addSource(rs.get("DistanceFieldVector.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); AbstractShaderProgram::attachShader(vert); diff --git a/src/Magnum/Shaders/Flat.cpp b/src/Magnum/Shaders/Flat.cpp index 7e487927c..60c77ca6e 100644 --- a/src/Magnum/Shaders/Flat.cpp +++ b/src/Magnum/Shaders/Flat.cpp @@ -32,6 +32,8 @@ #include "Magnum/Shader.h" #include "Magnum/Texture.h" +#include "Implementation/CreateCompatibilityShader.h" + namespace Magnum { namespace Shaders { namespace { @@ -54,17 +56,15 @@ template Flat::Flat(const Flags flags): tran #endif Version version = Context::current()->supportedVersion(vs); - Shader vert(version, Shader::Type::Vertex); + Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); vert.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") - .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); attachShader(vert); - Shader frag(version, Shader::Type::Fragment); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") - .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("Flat.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); attachShader(frag); diff --git a/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.cpp b/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.cpp new file mode 100644 index 000000000..1377e6976 --- /dev/null +++ b/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.cpp @@ -0,0 +1,51 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + 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 "CreateCompatibilityShader.h" + +#include + +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +namespace Magnum { namespace Shaders { namespace Implementation { + +Shader createCompatibilityShader(const Version version, const Shader::Type type) { + Shader shader(version, type); + + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionDisabled(version)) + shader.addSource("#define DISABLE_GL_ARB_explicit_attrib_location\n"); + if(Context::current()->isExtensionDisabled(version)) + shader.addSource("#define DISABLE_GL_ARB_shading_language_420pack\n"); + if(Context::current()->isExtensionDisabled(version)) + shader.addSource("#define DISABLE_GL_ARB_explicit_uniform_location\n"); + #endif + + shader.addSource(Utility::Resource("MagnumShaders").get("compatibility.glsl")); + return shader; +} + +}}} diff --git a/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h b/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h new file mode 100644 index 000000000..bb8790629 --- /dev/null +++ b/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h @@ -0,0 +1,36 @@ +#ifndef Magnum_Shaders_Implementation_CreateCompatibilityShader_h +#define Magnum_Shaders_Implementation_CreateCompatibilityShader_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + 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 "Magnum/Shader.h" + +namespace Magnum { namespace Shaders { namespace Implementation { + +Shader createCompatibilityShader(Version version, Shader::Type type); + +}}} + +#endif diff --git a/src/Magnum/Shaders/MeshVisualizer.cpp b/src/Magnum/Shaders/MeshVisualizer.cpp index 2c2d6ab14..660929260 100644 --- a/src/Magnum/Shaders/MeshVisualizer.cpp +++ b/src/Magnum/Shaders/MeshVisualizer.cpp @@ -31,6 +31,8 @@ #include "Magnum/Extensions.h" #include "Magnum/Shader.h" +#include "Implementation/CreateCompatibilityShader.h" + namespace Magnum { namespace Shaders { MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) { @@ -53,10 +55,9 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); #endif - Shader vert(version, Shader::Type::Vertex); + Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") - .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("generic.glsl")) .addSource(rs.get("MeshVisualizer.vert")); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); @@ -65,19 +66,17 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP #ifndef MAGNUM_TARGET_GLES if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { - Shader geom(version, Shader::Type::Geometry); - geom.addSource(rs.get("compatibility.glsl")) - .addSource(rs.get("MeshVisualizer.geom")); + Shader geom = Implementation::createCompatibilityShader(version, Shader::Type::Geometry); + geom.addSource(rs.get("MeshVisualizer.geom")); CORRADE_INTERNAL_ASSERT_OUTPUT(geom.compile()); geom.compile(); attachShader(geom); } #endif - Shader frag(version, Shader::Type::Fragment); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") - .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("MeshVisualizer.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); frag.compile(); diff --git a/src/Magnum/Shaders/MeshVisualizer.geom b/src/Magnum/Shaders/MeshVisualizer.geom index 8ad06bb50..6e51b930e 100644 --- a/src/Magnum/Shaders/MeshVisualizer.geom +++ b/src/Magnum/Shaders/MeshVisualizer.geom @@ -27,7 +27,11 @@ #define const #endif +#ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 1) uniform vec2 viewportSize; +#else +uniform vec2 viewportSize; +#endif layout(triangles) in; diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/Phong.cpp index bb88002c3..48f34597c 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/Phong.cpp @@ -32,6 +32,8 @@ #include "Magnum/Shader.h" #include "Magnum/Texture.h" +#include "Implementation/CreateCompatibilityShader.h" + namespace Magnum { namespace Shaders { namespace { @@ -51,19 +53,17 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); #endif - Shader vert(version, Shader::Type::Vertex); + Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); vert.addSource(flags ? "#define TEXTURED\n" : "") - .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("generic.glsl")) .addSource(rs.get("Phong.vert")); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); attachShader(vert); - Shader frag(version, Shader::Type::Fragment); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "") .addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") .addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") - .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("Phong.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); attachShader(frag); diff --git a/src/Magnum/Shaders/Vector.cpp b/src/Magnum/Shaders/Vector.cpp index aee88f0ce..459a90595 100644 --- a/src/Magnum/Shaders/Vector.cpp +++ b/src/Magnum/Shaders/Vector.cpp @@ -31,6 +31,8 @@ #include "Magnum/Extensions.h" #include "Magnum/Shader.h" +#include "Implementation/CreateCompatibilityShader.h" + namespace Magnum { namespace Shaders { namespace { @@ -51,16 +53,14 @@ template Vector::Vector(): transformationPro #endif Version version = Context::current()->supportedVersion(vs); - Shader vert(version, Shader::Type::Vertex); - vert.addSource(rs.get("compatibility.glsl")) - .addSource(rs.get("generic.glsl")) + Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + vert.addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); AbstractShaderProgram::attachShader(vert); - Shader frag(version, Shader::Type::Fragment); - frag.addSource(rs.get("compatibility.glsl")) - .addSource(rs.get("Vector.frag")); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + frag.addSource(rs.get("Vector.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); AbstractShaderProgram::attachShader(frag); diff --git a/src/Magnum/Shaders/VertexColor.cpp b/src/Magnum/Shaders/VertexColor.cpp index de1453533..282f452f2 100644 --- a/src/Magnum/Shaders/VertexColor.cpp +++ b/src/Magnum/Shaders/VertexColor.cpp @@ -31,6 +31,8 @@ #include "Magnum/Extensions.h" #include "Magnum/Shader.h" +#include "Implementation/CreateCompatibilityShader.h" + namespace Magnum { namespace Shaders { namespace { @@ -59,16 +61,14 @@ template VertexColor::VertexColor(): transfo Version version = Context::current()->supportedVersion(vs); #endif - Shader vert(version, Shader::Type::Vertex); - vert.addSource(rs.get("compatibility.glsl")) - .addSource(rs.get("generic.glsl")) + Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + vert.addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); attachShader(vert); - Shader frag(version, Shader::Type::Fragment); - frag.addSource(rs.get("compatibility.glsl")) - .addSource(rs.get("VertexColor.frag")); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + frag.addSource(rs.get("VertexColor.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); attachShader(frag); diff --git a/src/Magnum/Shaders/compatibility.glsl b/src/Magnum/Shaders/compatibility.glsl index 94eaf9440..e041903d6 100644 --- a/src/Magnum/Shaders/compatibility.glsl +++ b/src/Magnum/Shaders/compatibility.glsl @@ -27,26 +27,20 @@ #define NEW_GLSL #endif -#ifdef GL_ARB_shading_language_420pack +#if !defined(GL_ES) && defined(GL_ARB_explicit_attrib_location) && !defined(DISABLE_GL_ARB_explicit_attrib_location) + #extension GL_ARB_explicit_attrib_location: enable + #define EXPLICIT_ATTRIB_LOCATION +#endif + +#if !defined(GL_ES) && defined(GL_ARB_shading_language_420pack) && !defined(DISABLE_GL_ARB_shading_language_420pack) #extension GL_ARB_shading_language_420pack: enable #define RUNTIME_CONST + #define EXPLICIT_TEXTURE_LAYER #endif -/* On NVidia and GLSL 1.20 layout qualifiers result in parsing error, even if - the extension is defined as supported */ -#if !defined(GL_ES) && __VERSION__ >= 140 - #ifdef GL_ARB_explicit_attrib_location - #extension GL_ARB_explicit_attrib_location: enable - #define EXPLICIT_ATTRIB_LOCATION - #endif - #ifdef GL_ARB_shading_language_420pack - /* Already enabled */ - #define EXPLICIT_TEXTURE_LAYER - #endif - #ifdef GL_ARB_explicit_uniform_location - #extension GL_ARB_explicit_uniform_location: enable - #define EXPLICIT_UNIFORM_LOCATION - #endif +#if !defined(GL_ES) && defined(GL_ARB_explicit_uniform_location) && !defined(DISABLE_GL_ARB_explicit_uniform_location) + #extension GL_ARB_explicit_uniform_location: enable + #define EXPLICIT_UNIFORM_LOCATION #endif #if defined(GL_ES) && __VERSION__ >= 300 diff --git a/src/Magnum/Test/ContextGLTest.cpp b/src/Magnum/Test/ContextGLTest.cpp index 9f72b9e69..e6de8bcfe 100644 --- a/src/Magnum/Test/ContextGLTest.cpp +++ b/src/Magnum/Test/ContextGLTest.cpp @@ -33,24 +33,20 @@ class ContextGLTest: public AbstractOpenGLTester { public: explicit ContextGLTest(); - void version(); - void versionList(); - void supportedExtension(); - void unsupportedExtension(); - void pastExtension(); - void versionDependentExtension(); + void isVersionSupported(); + void supportedVersion(); + void isExtensionSupported(); + void isExtensionDisabled(); }; ContextGLTest::ContextGLTest() { - addTests({&ContextGLTest::version, - &ContextGLTest::versionList, - &ContextGLTest::supportedExtension, - &ContextGLTest::unsupportedExtension, - &ContextGLTest::pastExtension, - &ContextGLTest::versionDependentExtension}); + addTests({&ContextGLTest::isVersionSupported, + &ContextGLTest::supportedVersion, + &ContextGLTest::isExtensionSupported, + &ContextGLTest::isExtensionDisabled}); } -void ContextGLTest::version() { +void ContextGLTest::isVersionSupported() { const Version v = Context::current()->version(); CORRADE_VERIFY(Context::current()->isVersionSupported(v)); CORRADE_VERIFY(Context::current()->isVersionSupported(Version(Int(v)-1))); @@ -61,7 +57,7 @@ void ContextGLTest::version() { MAGNUM_ASSERT_VERSION_SUPPORTED(Version(Int(v)-1)); } -void ContextGLTest::versionList() { +void ContextGLTest::supportedVersion() { const Version v = Context::current()->version(); /* Selects first supported version (thus not necessarily the highest) */ @@ -69,61 +65,46 @@ void ContextGLTest::versionList() { CORRADE_VERIFY(Context::current()->supportedVersion({Version(Int(v)+1), Version(Int(v)-1), v}) == Version(Int(v)-1)); } -void ContextGLTest::supportedExtension() { +void ContextGLTest::isExtensionSupported() { + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::GREMEDY::string_marker::string() + std::string(" extension should not be supported, can't test")); + if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_filter_anisotropic::string() + std::string(" extension should be supported, can't test")); - std::string extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); - CORRADE_VERIFY(extensions.find(Extensions::GL::EXT::texture_filter_anisotropic::string()) != std::string::npos); -} - -void ContextGLTest::unsupportedExtension() { - #ifndef MAGNUM_TARGET_GLES - if(Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::GREMEDY::string_marker::string() + std::string(" extension shouldn't be supported, can't test")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::explicit_attrib_location::string() + std::string(" extension should be supported, can't test")); + /* Test that we have proper extension list parser */ std::string extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); + CORRADE_VERIFY(extensions.find(Extensions::GL::EXT::texture_filter_anisotropic::string()) != std::string::npos); CORRADE_VERIFY(extensions.find(Extensions::GL::GREMEDY::string_marker::string()) == std::string::npos); - #elif !defined(CORRADE_TARGET_NACL) - if(Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::CHROMIUM::map_sub::string() + std::string(" extension shouldn't be supported, can't test")); - std::string extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); - CORRADE_VERIFY(extensions.find(Extensions::GL::CHROMIUM::map_sub::string()) == std::string::npos); + /* This is disabled in GL < 3.2 to work around GLSL compiler bugs */ + CORRADE_VERIFY(!Context::current()->isExtensionSupported(Version::GL310)); + CORRADE_VERIFY(Context::current()->isExtensionSupported(Version::GL320)); #else - if(Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::NV::read_buffer_front::string() + std::string(" extension shouldn't be supported, can't test")); - - std::string extensions(reinterpret_cast(glGetString(GL_EXTENSIONS))); - CORRADE_VERIFY(extensions.find(Extensions::GL::NV::read_buffer_front::string()) == std::string::npos); + CORRADE_SKIP("No useful extensions to test on OpenGL ES"); #endif } -void ContextGLTest::pastExtension() { +void ContextGLTest::isExtensionDisabled() { #ifndef MAGNUM_TARGET_GLES - if(!Context::current()->isVersionSupported(Version::GL300)) - CORRADE_SKIP("No already supported extensions are listed for OpenGL 2.1"); - - CORRADE_VERIFY(Context::current()->isExtensionSupported()); - /* No assertion should be fired */ - MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::APPLE::vertex_array_object); - #elif defined(MAGNUM_TARGET_GLES2) - CORRADE_SKIP("No already supported extensions are listed for OpenGL ES 2.0"); - #else - CORRADE_SKIP("No already supported extensions are listed for OpenGL ES 3.0"); - #endif -} + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::APPLE::vertex_array_object::string() + std::string(" extension should be supported, can't test")); -void ContextGLTest::versionDependentExtension() { - #ifndef MAGNUM_TARGET_GLES - CORRADE_COMPARE(Extensions::GL::ARB::get_program_binary::requiredVersion(), Version::GL300); - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::get_program_binary::string() + std::string("extension isn't supported, can't test")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::explicit_attrib_location::string() + std::string(" extension should be supported, can't test")); + + /* This is not disabled anywhere */ + CORRADE_VERIFY(!Context::current()->isExtensionDisabled()); - CORRADE_VERIFY(Context::current()->isExtensionSupported(Context::current()->version())); - CORRADE_VERIFY(!Context::current()->isExtensionSupported(Version::GL210)); + /* This is disabled in GL < 3.2 to work around GLSL compiler bugs */ + CORRADE_VERIFY(Context::current()->isExtensionDisabled(Version::GL310)); + CORRADE_VERIFY(!Context::current()->isExtensionDisabled(Version::GL320)); #else - CORRADE_SKIP("No OpenGL ES 3.0-only extensions exist yet"); + CORRADE_SKIP("No useful extensions to test on OpenGL ES"); #endif }