From 31f24474b6cd76271f68e05d26214ecbeafe415b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 6 Apr 2016 16:18:09 +0200 Subject: [PATCH] DebugTools: utility to get buffer data on OpenGL ES. --- src/Magnum/Buffer.h | 6 +- src/Magnum/DebugTools/BufferData.cpp | 38 +++++++++ src/Magnum/DebugTools/BufferData.h | 81 +++++++++++++++++++ src/Magnum/DebugTools/CMakeLists.txt | 8 ++ .../DebugTools/Test/BufferDataGLTest.cpp | 71 ++++++++++++++++ src/Magnum/DebugTools/Test/CMakeLists.txt | 4 + 6 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 src/Magnum/DebugTools/BufferData.cpp create mode 100644 src/Magnum/DebugTools/BufferData.h create mode 100644 src/Magnum/DebugTools/Test/BufferDataGLTest.cpp diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index 3d070148b..a288276f9 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -1066,7 +1066,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @fn_gl_extension{GetNamedBufferSubData,EXT,direct_state_access}, * eventually @fn_gl{GetBufferSubData} * @requires_gl Buffer data queries are not available in OpenGL ES and - * WebGL. Use @ref map() in OpenGL ES instead. + * WebGL. Use @ref map() or @ref DebugTools::bufferData() in + * OpenGL ES instead. */ /* MinGW complains loudly if the declaration doesn't also have inline */ template inline Containers::Array data(); @@ -1085,7 +1086,8 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { * @fn_gl_extension{GetNamedBufferSubData,EXT,direct_state_access}, * eventually @fn_gl{BindBuffer} and @fn_gl{GetBufferSubData} * @requires_gl Buffer data queries are not available in OpenGL ES and - * WebGL. Use @ref map() in OpenGL ES instead. + * WebGL. Use @ref map() or @ref DebugTools::bufferData() in + * OpenGL ES instead. */ /* MinGW complains loudly if the declaration doesn't also have inline */ template inline Containers::Array subData(GLintptr offset, GLsizeiptr size); diff --git a/src/Magnum/DebugTools/BufferData.cpp b/src/Magnum/DebugTools/BufferData.cpp new file mode 100644 index 000000000..aff18c731 --- /dev/null +++ b/src/Magnum/DebugTools/BufferData.cpp @@ -0,0 +1,38 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + 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 "BufferData.h" + +#ifndef MAGNUM_TARGET_WEBGL +namespace Magnum { namespace DebugTools { namespace Implementation { + +void bufferSubData(Buffer& buffer, GLintptr offset, GLsizeiptr size, void* output) { + const char* data = buffer.map(offset, size, Buffer::MapFlag::Read); + std::copy(data, data + size, reinterpret_cast(output)); + buffer.unmap(); +} + +}}} +#endif diff --git a/src/Magnum/DebugTools/BufferData.h b/src/Magnum/DebugTools/BufferData.h new file mode 100644 index 000000000..4cf6a55b2 --- /dev/null +++ b/src/Magnum/DebugTools/BufferData.h @@ -0,0 +1,81 @@ +#ifndef Magnum_DebugTools_BufferData_h +#define Magnum_DebugTools_BufferData_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + 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. +*/ + +#ifndef MAGNUM_TARGET_WEBGL +/** @file + * @brief Function @ref Magnum::DebugTools::bufferData(), @ref Magnum::DebugTools::bufferSubData() + */ +#endif + +#include + +#include "Magnum/Buffer.h" +#include "Magnum/DebugTools/visibility.h" + +#ifndef MAGNUM_TARGET_WEBGL +namespace Magnum { namespace DebugTools { + +namespace Implementation { + MAGNUM_DEBUGTOOLS_EXPORT void bufferSubData(Buffer& buffer, GLintptr offset, GLsizeiptr size, void* output); +} + +/** +@brief Buffer subdata + +Emulates @ref Buffer::subData() call on platforms that don't support it (such +as OpenGL ES) by using @ref Buffer::map(). +@requires_gles30 Extension @es_extension{EXT,map_buffer_range} in OpenGL ES + 2.0. +@requires_gles Buffer mapping is not available in WebGL. +*/ +template Containers::Array inline bufferSubData(Buffer& buffer, GLintptr offset, GLsizeiptr size) { + Containers::Array data{std::size_t(size)}; + if(size) Implementation::bufferSubData(buffer, offset, size*sizeof(T), data); + return data; +} + +/** +@brief Buffer data + +Emulates @ref Buffer::data() call on platforms that don't support it (such as +OpenGL ES) by using @ref Buffer::map(). +@requires_gles30 Extension @es_extension{EXT,map_buffer_range} in OpenGL ES + 2.0. +@requires_gles Buffer mapping is not available in WebGL. +*/ +template Containers::Array inline bufferData(Buffer& buffer) { + const Int bufferSize = buffer.size(); + CORRADE_ASSERT(bufferSize%sizeof(T) == 0, "Buffer::data(): the buffer size is" << bufferSize << "bytes, which can't be expressed as array of types with size" << sizeof(T), nullptr); + return bufferSubData(buffer, 0, bufferSize/sizeof(T)); +} + +}} +#else +#error this header is not available in WebGL build +#endif + +#endif diff --git a/src/Magnum/DebugTools/CMakeLists.txt b/src/Magnum/DebugTools/CMakeLists.txt index f7caa6ae4..978e68a26 100644 --- a/src/Magnum/DebugTools/CMakeLists.txt +++ b/src/Magnum/DebugTools/CMakeLists.txt @@ -36,6 +36,14 @@ set(MagnumDebugTools_HEADERS # Header files to display in project view of IDEs only set(MagnumDebugTools_PRIVATE_HEADERS ) +if(NOT MAGNUM_TARGET_WEBGL) + list(APPEND MagnumDebugTools_SRCS + BufferData.cpp) + + list(APPEND MagnumDebugTools_HEADERS + BufferData.h) +endif() + if(WITH_SCENEGRAPH) list(APPEND MagnumDebugTools_SRCS ForceRenderer.cpp diff --git a/src/Magnum/DebugTools/Test/BufferDataGLTest.cpp b/src/Magnum/DebugTools/Test/BufferDataGLTest.cpp new file mode 100644 index 000000000..c9985ae26 --- /dev/null +++ b/src/Magnum/DebugTools/Test/BufferDataGLTest.cpp @@ -0,0 +1,71 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 + 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 + +#include "Magnum/DebugTools/BufferData.h" +#include "Magnum/Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace DebugTools { namespace Test { + +struct BufferDataGLTest: Magnum::Test::AbstractOpenGLTester { + explicit BufferDataGLTest(); + + void data(); + void subData(); +}; + +BufferDataGLTest::BufferDataGLTest() { + addTests({&BufferDataGLTest::data, + &BufferDataGLTest::subData}); +} + +namespace { + constexpr Int Data[] = {2, 7, 5, 13, 25}; +} + +void BufferDataGLTest::data() { + Buffer buffer; + buffer.setData(Data, BufferUsage::StaticDraw); + const Containers::Array contents = bufferData(buffer); + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE_AS(contents, + Containers::ArrayView{Data}, + TestSuite::Compare::Container); +} + +void BufferDataGLTest::subData() { + Buffer buffer; + buffer.setData(Data, BufferUsage::StaticDraw); + const Containers::Array contents = bufferSubData(buffer, 4, 3); + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE_AS(contents, + Containers::ArrayView{Data}.slice(1, 4), + TestSuite::Compare::Container); +} + +}}} + +MAGNUM_GL_TEST_MAIN(Magnum::DebugTools::Test::BufferDataGLTest) diff --git a/src/Magnum/DebugTools/Test/CMakeLists.txt b/src/Magnum/DebugTools/Test/CMakeLists.txt index 824ab777d..d1b2654a2 100644 --- a/src/Magnum/DebugTools/Test/CMakeLists.txt +++ b/src/Magnum/DebugTools/Test/CMakeLists.txt @@ -27,3 +27,7 @@ corrade_add_test(DebugToolsCapsuleRendererTest CapsuleRendererTest.cpp LIBRARIES corrade_add_test(DebugToolsCylinderRendererTest CylinderRendererTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(DebugToolsForceRendererTest ForceRendererTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(DebugToolsLineSegmentRendererTest LineSegmentRendererTest.cpp LIBRARIES MagnumMathTestLib) + +if(BUILD_GL_TESTS) + corrade_add_test(DebugToolsBufferDataGLTest BufferDataGLTest.cpp LIBRARIES MagnumDebugTools ${GL_TEST_LIBRARIES}) +endif()