diff --git a/doc/changelog.dox b/doc/changelog.dox index c34112b69..5d26f8f6e 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -55,6 +55,10 @@ See also: - Exposing @ref GL::Context::Flag::ForwardCompatible through @ref GL::Context::flags(), which was deliberately ignored before. +- New @ref GL::Renderer::lineWidthRange() limit query. The reported maximum + can be over @cpp 1.0f @ce only in non-forward-compatible contexts, a new + @cpp "mesa-forward-compatible-line-width-range" @ce workaround fixes that + for Mesa. See @ref opengl-workarounds for more information. @subsubsection changelog-latest-new-math Math library diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 8a9369de4..708998e6e 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -436,7 +436,7 @@ OpenGL function | Matching API glGet() parameter | Matching API --------------------------------------- | ------------ @def_gl{ACTIVE_TEXTURE}, \n @def_gl{TEXTURE_BINDING_1D_ARRAY}, \n @def_gl{TEXTURE_BINDING_1D}, \n @def_gl{TEXTURE_BINDING_2D_ARRAY}, \n @def_gl{TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY}, \n @def_gl{TEXTURE_BINDING_2D_MULTISAMPLE}, \n @def_gl{TEXTURE_BINDING_2D} , \n @def_gl{TEXTURE_BINDING_3D}, \n @def_gl{TEXTURE_BINDING_BUFFER}, \n @def_gl{TEXTURE_BINDING_BUFFER}, \n @def_gl{TEXTURE_BINDING_CUBE_MAP}, \n @def_gl{TEXTURE_BINDING_RECTANGLE} | not queryable but tracked internally -@def_gl{ALIASED_LINE_WIDTH_RANGE} | | +@def_gl{ALIASED_LINE_WIDTH_RANGE} | @ref GL::Renderer::lineWidthRange() @def_gl{ARRAY_BUFFER_BINDING}, \n @def_gl{DISPATCH_INDIRECT_BUFFER_BINDING}, \n @def_gl{ELEMENT_ARRAY_BUFFER_BINDING}, \n @def_gl{PIXEL_PACK_BUFFER_BINDING}, \n @def_gl{PIXEL_UNPACK_BUFFER_BINDING} | not queryable but tracked internally @def_gl{BLEND_COLOR} | not queryable, @ref GL::Renderer::setBlendColor() setter only @def_gl{BLEND_DST_ALPHA}, \n @def_gl{BLEND_DST_RGB}, \n @def_gl{BLEND_SRC_ALPHA}, \n @def_gl{BLEND_SRC_RGB} | not queryable, @ref GL::Renderer::setBlendFunction() setter only @@ -458,7 +458,6 @@ glGet() parameter | Matching API @def_gl{IMPLEMENTATION_COLOR_READ_TYPE} | | @def_gl{LAYER_PROVOKING_VERTEX} | | @def_gl{LINE_SMOOTH}, \n @def_gl{POLYGON_SMOOTH} | not supported (@ref opengl-unsupported "details") -@def_gl{LINE_WIDTH_GRANULARITY}, \n @def_gl{LINE_WIDTH_RANGE} | | @def_gl{LINE_WIDTH} | not queryable, @ref GL::Renderer::setLineWidth() setter only @def_gl{LOGIC_OP_MODE} | not queryable, @ref GL::Renderer::setLogicOperation() setter only @def_gl{MAJOR_VERSION}, \n @def_gl{MINOR_VERSION} | @ref GL::Context::version() @@ -559,7 +558,8 @@ glGet() parameter | Matching API @def_gl{SHADER_COMPILER} | not supported (@ref opengl-unsupported "details") @def_gl{SHADER_STORAGE_BUFFER_BINDING}, \n @def_gl{SHADER_STORAGE_BUFFER_SIZE}, \n @def_gl{SHADER_STORAGE_BUFFER_START} | not queryable @def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT} | @ref GL::Buffer::shaderStorageOffsetAlignment() -@def_gl{SMOOTH_LINE_WIDTH_GRANULARITY}, \n @def_gl{SMOOTH_LINE_WIDTH_RANGE} | | +@def_gl{SMOOTH_LINE_WIDTH_GRANULARITY} / @def_gl{LINE_WIDTH_GRANULARITY}, \n +@def_gl{SMOOTH_LINE_WIDTH_RANGE} / @def_gl{LINE_WIDTH_RANGE} | not supported (@ref opengl-unsupported "details") @def_gl{STENCIL_BACK_FUNC}, \n @def_gl{STENCIL_BACK_REF}, \n @def_gl{STENCIL_BACK_VALUE_MASK}, \n @def_gl{STENCIL_FUNC}, \n @def_gl{STENCIL_REF}, \n @def_gl{STENCIL_VALUE_MASK} | not queryable, @ref GL::Renderer::setStencilFunction() setter only @def_gl{STENCIL_BACK_FAIL}, \n @def_gl{STENCIL_BACK_PASS_DEPTH_FAIL}, \n @def_gl{STENCIL_BACK_PASS_DEPTH_PASS}, \n @def_gl{STENCIL_FAIL}, \n @def_gl{STENCIL_PASS_DEPTH_FAIL}, \n @def_gl{STENCIL_PASS_DEPTH_PASS} | not queryable, @ref GL::Renderer::setStencilOperation() setter only @def_gl{SUBPIXEL_BITS} | | diff --git a/src/Magnum/GL/Implementation/RendererState.cpp b/src/Magnum/GL/Implementation/RendererState.cpp index 6b9288351..9c017c25f 100644 --- a/src/Magnum/GL/Implementation/RendererState.cpp +++ b/src/Magnum/GL/Implementation/RendererState.cpp @@ -84,6 +84,17 @@ RendererState::RendererState(Context& context, std::vector& extensi packPixelStorage.disengagedRowLength = 0; #endif #endif + + #ifndef MAGNUM_TARGET_GLES + if((context.detectedDriver() & Context::DetectedDriver::Mesa) && + (context.flags() & Context::Flag::ForwardCompatible) && + !context.isDriverWorkaroundDisabled("mesa-forward-compatible-line-width-range")) + lineWidthRangeImplementation = &Renderer::lineWidthRangeImplementationMesaForwardCompatible; + else + #endif + { + lineWidthRangeImplementation = &Renderer::lineWidthRangeImplementationDefault; + } } RendererState::PixelStorage::PixelStorage(): diff --git a/src/Magnum/GL/Implementation/RendererState.h b/src/Magnum/GL/Implementation/RendererState.h index 07ca2df1c..c45e58716 100644 --- a/src/Magnum/GL/Implementation/RendererState.h +++ b/src/Magnum/GL/Implementation/RendererState.h @@ -29,13 +29,14 @@ #include #include "Magnum/GL/Renderer.h" -#include "Magnum/Math/Vector3.h" +#include "Magnum/Math/Range.h" namespace Magnum { namespace GL { namespace Implementation { struct RendererState { explicit RendererState(Context& context, std::vector& extensions); + Range1D(*lineWidthRangeImplementation)(); void(*clearDepthfImplementation)(GLfloat); #ifndef MAGNUM_TARGET_WEBGL Renderer::GraphicsResetStatus(*graphicsResetStatusImplementation)(); @@ -69,6 +70,7 @@ struct RendererState { }; PixelStorage packPixelStorage, unpackPixelStorage; + Range1D lineWidthRange; /* Bool parameter is ugly, but this is implementation detail of internal API so who cares */ diff --git a/src/Magnum/GL/Implementation/driverSpecific.cpp b/src/Magnum/GL/Implementation/driverSpecific.cpp index f2e9fafd7..6070bb80f 100644 --- a/src/Magnum/GL/Implementation/driverSpecific.cpp +++ b/src/Magnum/GL/Implementation/driverSpecific.cpp @@ -50,6 +50,14 @@ namespace { "intel-windows-glsl-exposes-unsupported-shading-language-420pack", #endif + #ifndef MAGNUM_TARGET_GLES + /* Forward-compatible GL contexts on Mesa still report line width range + as [1, 7], but setting wide line width fails. According to the specs + the max value on forward compatible contexts should be 1.0, so + patching it. */ + "mesa-forward-compatible-line-width-range", + #endif + #if !defined(MAGNUM_TARGET_GLES2) && defined(CORRADE_TARGET_WINDOWS) /* On Windows NVidia drivers the glTransformFeedbackVaryings() does not make a copy of its char* arguments so it fails at link time when the diff --git a/src/Magnum/GL/Renderer.cpp b/src/Magnum/GL/Renderer.cpp index 63e96cd89..920bdfcda 100644 --- a/src/Magnum/GL/Renderer.cpp +++ b/src/Magnum/GL/Renderer.cpp @@ -35,6 +35,31 @@ namespace Magnum { namespace GL { +Range1D Renderer::lineWidthRange() { + auto& state = *Context::current().state().renderer; + Range1D& value = state.lineWidthRange; + + /* Get the value, if not already cached */ + if(value.max().isZero()) + value = state.lineWidthRangeImplementation(); + + return value; +} + +Range1D Renderer::lineWidthRangeImplementationDefault() { + Range1D value; + glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, value.data()); + return value; +} + +#ifndef MAGNUM_TARGET_GLES +Range1D Renderer::lineWidthRangeImplementationMesaForwardCompatible() { + Range1D value = lineWidthRangeImplementationDefault(); + value.max() = Math::min(1.0f, value.max()[0]); + return value; +} +#endif + void Renderer::enable(const Feature feature) { glEnable(GLenum(feature)); } diff --git a/src/Magnum/GL/Renderer.h b/src/Magnum/GL/Renderer.h index ec1cbedb8..c274a638b 100644 --- a/src/Magnum/GL/Renderer.h +++ b/src/Magnum/GL/Renderer.h @@ -287,6 +287,18 @@ class MAGNUM_GL_EXPORT Renderer { StencilTest = GL_STENCIL_TEST }; + /** + * @brief Line width range + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. Note that lines wider than @cpp 1.0f @ce are supported + * only when the context is not forward-compatible. Smooth lines are + * @ref opengl-unsupported "not supported by design". + * @see @ref setLineWidth(), @fn_gl{Get} with + * @def_gl_keyword{ALIASED_LINE_WIDTH_RANGE} + */ + static Range1D lineWidthRange(); + /** * @brief Enable feature * @@ -567,8 +579,11 @@ class MAGNUM_GL_EXPORT Renderer { /** * @brief Set line width * - * Initial value is @cpp 1.0f @ce. - * @see @fn_gl_keyword{LineWidth} + * Initial value is @cpp 1.0f @ce. Note that on contexts that are + * @ref Context::Flag::ForwardCompatible the max supported value is + * @cpp 1.0f @ce --- request a non-forward-compatible context to get + * wide lines on supported hardware. + * @see @ref lineWidthRange(), @fn_gl_keyword{LineWidth} */ static void setLineWidth(Float width); @@ -1628,6 +1643,11 @@ class MAGNUM_GL_EXPORT Renderer { private: static void MAGNUM_GL_LOCAL initializeContextBasedFunctionality(); + static MAGNUM_GL_LOCAL Range1D lineWidthRangeImplementationDefault(); + #ifndef MAGNUM_TARGET_GLES + static MAGNUM_GL_LOCAL Range1D lineWidthRangeImplementationMesaForwardCompatible(); + #endif + #ifndef MAGNUM_TARGET_GLES static void MAGNUM_GL_LOCAL clearDepthfImplementationDefault(GLfloat depth); #endif diff --git a/src/Magnum/GL/Test/CMakeLists.txt b/src/Magnum/GL/Test/CMakeLists.txt index 9052250a6..01129fb2e 100644 --- a/src/Magnum/GL/Test/CMakeLists.txt +++ b/src/Magnum/GL/Test/CMakeLists.txt @@ -110,6 +110,7 @@ if(BUILD_GL_TESTS) corrade_add_test(GLCubeMapTextureGLTest CubeMapTextureGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLFramebufferGLTest FramebufferGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLMeshGLTest MeshGLTest.cpp LIBRARIES MagnumGLTestLib MagnumOpenGLTester) + corrade_add_test(GLRendererGLTest RendererGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLRenderbufferGLTest RenderbufferGLTest.cpp LIBRARIES MagnumOpenGLTester) corrade_add_test(GLTextureGLTest TextureGLTest.cpp LIBRARIES MagnumOpenGLTester) diff --git a/src/Magnum/GL/Test/RendererGLTest.cpp b/src/Magnum/GL/Test/RendererGLTest.cpp new file mode 100644 index 000000000..3cb9586f7 --- /dev/null +++ b/src/Magnum/GL/Test/RendererGLTest.cpp @@ -0,0 +1,65 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + 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/GL/Context.h" +#include "Magnum/GL/Renderer.h" +#include "Magnum/GL/OpenGLTester.h" +#include "Magnum/Math/Range.h" + +namespace Magnum { namespace GL { namespace Test { + +struct RendererGLTest: OpenGLTester { + explicit RendererGLTest(); + + void maxLineWidth(); +}; + +RendererGLTest::RendererGLTest() { + addTests({&RendererGLTest::maxLineWidth}); +} + +void RendererGLTest::maxLineWidth() { + #ifndef MAGNUM_TARGET_GLES + Debug{} << "Core profile:" << Context::current().isCoreProfile(); + #endif + #ifndef MAGNUM_TARGET_WEBGL + Debug{} << "Context flags:" << Context::current().flags(); + #endif + + MAGNUM_VERIFY_NO_GL_ERROR(); + + Range1D lineWidthRange = Renderer::lineWidthRange(); + Debug{} << "Line width range:" << lineWidthRange; + + MAGNUM_VERIFY_NO_GL_ERROR(); + + Renderer::setLineWidth(lineWidthRange.max()[0]); + + MAGNUM_VERIFY_NO_GL_ERROR(); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::GL::Test::RendererGLTest)