From 5ddd9d16f8d66308281806dee98be921d83933a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 20 Feb 2014 13:15:55 +0100 Subject: [PATCH 001/141] GCC 4.7 compatibility: hide deprecated warnings in internal code. --- src/Magnum/SceneGraph/Object.hpp | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/Magnum/SceneGraph/Object.hpp b/src/Magnum/SceneGraph/Object.hpp index 6716902e2..876d3653e 100644 --- a/src/Magnum/SceneGraph/Object.hpp +++ b/src/Magnum/SceneGraph/Object.hpp @@ -52,7 +52,14 @@ template void AbstractObject::se #ifdef CORRADE_GCC47_COMPATIBILITY template void AbstractObject::setClean(std::initializer_list*> objects) { + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif return setClean(std::vector*>{objects}); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif } #endif #endif @@ -74,7 +81,14 @@ template auto AbstractObject::tr #ifdef CORRADE_GCC47_COMPATIBILITY template auto AbstractObject::transformationMatrices(std::initializer_list*> objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif return transformationMatrices(std::vector*>{objects}, initialTransformationMatrix); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif } #endif #endif @@ -234,7 +248,14 @@ template auto Object::transformationMatric #ifdef CORRADE_GCC47_COMPATIBILITY template auto Object::transformationMatrices(std::initializer_list*> objects, const MatrixType& initialTransformationMatrix) const -> std::vector { + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif return transformationMatrices(std::vector*>{objects}, initialTransformationMatrix); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif } #endif #endif @@ -360,7 +381,14 @@ template std::vector Ob #ifdef CORRADE_GCC47_COMPATIBILITY template std::vector Object::transformations(std::initializer_list*> objects, const typename Transformation::DataType& initialTransformation) const { + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif return transformations(std::vector*>{objects}, initialTransformation); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif } #endif #endif @@ -464,7 +492,14 @@ template void Object::setClean(const std:: #ifdef CORRADE_GCC47_COMPATIBILITY template void Object::setClean(std::initializer_list*> objects) { + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif setClean(std::vector*>{objects}); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif } #endif #endif From cb987f25d3568c30b4f01d2cc77921d705278e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:32:20 +0100 Subject: [PATCH 002/141] package: Audio library is disabled by default. --- package/archlinux/PKGBUILD-emscripten | 4 +--- package/archlinux/PKGBUILD-mingw32 | 1 + package/archlinux/PKGBUILD-nacl-newlib | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/package/archlinux/PKGBUILD-emscripten b/package/archlinux/PKGBUILD-emscripten index 7de134779..785f84ab7 100644 --- a/package/archlinux/PKGBUILD-emscripten +++ b/package/archlinux/PKGBUILD-emscripten @@ -17,8 +17,7 @@ build() { cmake .. \ -DCMAKE_MODULE_PATH="$startdir/toolchains/modules" \ - -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Emscripten.cmake" \ - -DWITH_AUDIO=OFF \ + -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Emscripten.cmake \ -G Ninja fi @@ -27,7 +26,6 @@ build() { cmake .. \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \ - -DWITH_AUDIO=OFF \ -DWITH_SDL2APPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_TGAIMAGECONVERTER=ON \ diff --git a/package/archlinux/PKGBUILD-mingw32 b/package/archlinux/PKGBUILD-mingw32 index 594932067..2f200f94f 100644 --- a/package/archlinux/PKGBUILD-mingw32 +++ b/package/archlinux/PKGBUILD-mingw32 @@ -20,6 +20,7 @@ build() { -DCMAKE_TOOLCHAIN_FILE=../toolchains/archlinux/basic-mingw32.cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/i486-mingw32 \ + -DWITH_AUDIO=ON \ -DWITH_GLUTAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ diff --git a/package/archlinux/PKGBUILD-nacl-newlib b/package/archlinux/PKGBUILD-nacl-newlib index d2a23fb6f..4cfe9fda9 100644 --- a/package/archlinux/PKGBUILD-nacl-newlib +++ b/package/archlinux/PKGBUILD-nacl-newlib @@ -20,7 +20,6 @@ build() { -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/NaCl-newlib-x86-32.cmake" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/nacl \ - -DWITH_AUDIO=OFF \ -DWITH_MAGNUMINFO=ON \ -DWITH_NACLAPPLICATION=ON \ -DWITH_WINDOWLESSNACLAPPLICATION=ON \ @@ -42,7 +41,6 @@ build() { -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/NaCl-newlib-x86-64.cmake" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/nacl \ - -DWITH_AUDIO=OFF \ -DWITH_MAGNUMINFO=ON \ -DWITH_NACLAPPLICATION=ON \ -DWITH_WINDOWLESSNACLAPPLICATION=ON \ From ed0cba85de82e47abc2f857a5037b66a96da466c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:32:48 +0100 Subject: [PATCH 003/141] Platform: proper suffix for EGL_OPENGL_ES3_BIT constant. Apparently not tested once. --- src/Magnum/Platform/Implementation/EglContextHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Platform/Implementation/EglContextHandler.cpp b/src/Magnum/Platform/Implementation/EglContextHandler.cpp index 7b3419a74..9661d1960 100644 --- a/src/Magnum/Platform/Implementation/EglContextHandler.cpp +++ b/src/Magnum/Platform/Implementation/EglContextHandler.cpp @@ -67,7 +67,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) { #ifndef MAGNUM_TARGET_GLES EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, #elif defined(MAGNUM_TARGET_GLES3) - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, #elif defined(MAGNUM_TARGET_GLES2) EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, #else From 722c98d2694ce4283313fd5f7614b94dc5a2fe39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:34:07 +0100 Subject: [PATCH 004/141] modules: different libraries for OpenGL ES 2.0/3.0 in FindMagnum.cmake. Also apparently not tested at all. --- modules/FindMagnum.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 998911a3a..e98f5ba44 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -164,8 +164,10 @@ endif() if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES) find_package(OpenGL REQUIRED) -else() +elseif(MAGNUM_TARGET_GLES2) find_package(OpenGLES2 REQUIRED) +elseif(MAGNUM_TARGET_GLES3) + find_package(OpenGLES3 REQUIRED) endif() # On Windows and in static builds, *Application libraries need to have @@ -366,8 +368,10 @@ set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARY} ${CORRADE_PLUGINMANAGER_LIBRARIES}) if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES) set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGL_gl_LIBRARY}) -else() +elseif(MAGNUM_TARGET_GLES2) set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGLES2_LIBRARY}) +else() + set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGLES3_LIBRARY}) endif() # Installation dirs From 5a94a3657058d88f8f7b8647419fda98fa77aef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:35:32 +0100 Subject: [PATCH 005/141] modules: libGLESv3 actually really exists. The world is actually sane. --- modules/FindOpenGLES3.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/FindOpenGLES3.cmake b/modules/FindOpenGLES3.cmake index 4fc74ecb2..fc9c9e573 100644 --- a/modules/FindOpenGLES3.cmake +++ b/modules/FindOpenGLES3.cmake @@ -34,7 +34,11 @@ # Library find_library(OPENGLES3_LIBRARY NAMES - GLESv2) # wtf? + GLESv3 + + # On some platforms (e.g. desktop emulation with Mesa or NVidia) ES3 + # support is provided in ES2 lib + GLESv2) # Include dir find_path(OPENGLES3_INCLUDE_DIR From 8f6f340e8c090c14c55f338c9d32aa7f0d95fcbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:39:59 +0100 Subject: [PATCH 006/141] Hardened checks for OpenGL ES version. There is no ES 2.5 or 3.01 and this way we can properly check for garbage returned by `glGet(GL_VERSION_M*OR)` (e.g. version 2674.-2O8539 would pass here). --- src/Magnum/Context.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 5bd900695..d3aa25122 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -346,9 +346,9 @@ Context::Context() { #ifndef MAGNUM_TARGET_GLES if(!isVersionSupported(Version::GL210)) #elif defined(MAGNUM_TARGET_GLES2) - if(!isVersionSupported(Version::GLES200)) + if(_version != Version::GLES200) #else - if(!isVersionSupported(Version::GLES300)) + if(_version != Version::GLES300) #endif { #ifndef MAGNUM_TARGET_GLES From c7607af0adfc6a34f2800ef1fae1bb3f6c2bac5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:42:02 +0100 Subject: [PATCH 007/141] Print separate major/minor integers for unsupported version. This message: Context: unsupported OpenGL version (1, 3). Is better than this: Context: unuspported OpenGL version 130. --- src/Magnum/Context.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index d3aa25122..ba41a0946 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -352,9 +352,9 @@ Context::Context() { #endif { #ifndef MAGNUM_TARGET_GLES - Error() << "Context: unsupported OpenGL version" << Int(_version); + Error() << "Context: unsupported OpenGL version" << Magnum::version(_version); #else - Error() << "Context: unsupported OpenGL ES version" << Int(_version); + Error() << "Context: unsupported OpenGL ES version" << Magnum::version(_version); #endif std::exit(1); } From 616bd5e517726daba9b20b83726adf73103dcfa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:53:20 +0100 Subject: [PATCH 008/141] Updated toolchains submodule with Android support. --- toolchains | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolchains b/toolchains index 749095394..ac87e416a 160000 --- a/toolchains +++ b/toolchains @@ -1 +1 @@ -Subproject commit 7490953943d6f23e7971b1b5076426dceb3c62eb +Subproject commit ac87e416a0e8052cde520426aa83e007d1e0e391 From 5790b96e6deca55c17463d407d09f5784c6bb3d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:36:04 +0100 Subject: [PATCH 009/141] modules: updated FindCorrade.cmake from Corrade repository. --- modules/FindCorrade.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake index 87af04d2a..5e20c71b5 100644 --- a/modules/FindCorrade.cmake +++ b/modules/FindCorrade.cmake @@ -36,6 +36,7 @@ # CORRADE_TARGET_NACL_GLIBC - Defined if compiled for Google Chrome # Native Client with `glibc` toolchain # CORRADE_TARGET_EMSCRIPTEN - Defined if compiled for Emscripten +# CORRADE_TARGET_ANDROID - Defined if compiled for Android # # If CORRADE_BUILD_DEPRECATED is defined, the CORRADE_INCLUDE_DIR variable also # contains path directly to Corrade directory (i.e. for includes without @@ -201,6 +202,10 @@ string(FIND "${_corradeConfigure}" "#define CORRADE_TARGET_EMSCRIPTEN" _TARGET_E if(NOT _TARGET_EMSCRIPTEN EQUAL -1) set(CORRADE_TARGET_EMSCRIPTEN 1) endif() +string(FIND "${_corradeConfigure}" "#define CORRADE_TARGET_ANDROID" _TARGET_ANDROID) +if(NOT _TARGET_ANDROID EQUAL -1) + set(CORRADE_TARGET_ANDROID 1) +endif() set(CORRADE_UTILITY_LIBRARIES ${CORRADE_UTILITY_LIBRARY}) set(CORRADE_INTERCONNECT_LIBRARIES ${CORRADE_INTERCONNECT_LIBRARY} ${CORRADE_UTILITY_LIBRARIES}) From 1b23406d7525768666872c8958839510d18ddaad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:52:26 +0100 Subject: [PATCH 010/141] external: updated Optional with Android support. --- src/MagnumExternal/Optional/optional.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MagnumExternal/Optional/optional.hpp b/src/MagnumExternal/Optional/optional.hpp index 6656bee81..07db190f5 100644 --- a/src/MagnumExternal/Optional/optional.hpp +++ b/src/MagnumExternal/Optional/optional.hpp @@ -149,6 +149,8 @@ template inline constexpr typename std::remove_reference::type&& co __assert_fail(expr, file, line, ""); # elif defined __native_client__ __assert(expr, line, file); // WHY. + # elif defined __ANDROID__ + __assert(file, line, expr); # elif defined __clang__ || defined __GNU_LIBRARY__ __assert(expr, file, line); # elif defined __GNUC__ From 7702399222917ee0146200405a37a38942e8975e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:46:49 +0100 Subject: [PATCH 011/141] Explicitly enable OpenGL ES when targeting Android. --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b669eb74..870cd785b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,6 +103,12 @@ if(CORRADE_TARGET_NACL OR CORRADE_TARGET_EMSCRIPTEN) set(TARGET_GLES2 1) endif() +# If targeting Android, set explicit OpenGL ES support. Decision between 2.0 +# and 3.0 is up to the user +if(CORRADE_TARGET_ANDROID) + set(TARGET_GLES 1) +endif() + # NaCl newlib toolchain supports only static linking, dynamic linking is # meaningless on Emscripten if(CORRADE_TARGET_NACL_NEWLIB OR CORRADE_TARGET_EMSCRIPTEN) From 30d156b3c860e05dca1b0a1c8baca9b3b89290a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:47:08 +0100 Subject: [PATCH 012/141] Build static libraries for Android. Same reasoning as in Corrade. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 870cd785b..bbd2160e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,8 +110,8 @@ if(CORRADE_TARGET_ANDROID) endif() # NaCl newlib toolchain supports only static linking, dynamic linking is -# meaningless on Emscripten -if(CORRADE_TARGET_NACL_NEWLIB OR CORRADE_TARGET_EMSCRIPTEN) +# meaningless on Emscripten and too inconvenient on Android +if(CORRADE_TARGET_NACL_NEWLIB OR CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID) set(BUILD_STATIC ON) endif() From 2235cb76b139279bb171e9eb3eac22f3b7e8e8a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:47:58 +0100 Subject: [PATCH 013/141] Apparently Android is something like newlib. --- src/Magnum/Math/Complex.h | 4 ++-- src/Magnum/Math/Functions.h | 9 +++++---- src/Magnum/Shader.cpp | 7 ++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Magnum/Math/Complex.h b/src/Magnum/Math/Complex.h index 6f7ba3371..84c97fd31 100644 --- a/src/Magnum/Math/Complex.h +++ b/src/Magnum/Math/Complex.h @@ -339,8 +339,8 @@ template class Complex { * @see isNormalized() */ T length() const { - /** @todo Remove when NaCl's newlib has this fixed */ - #ifndef CORRADE_TARGET_NACL_NEWLIB + /** @todo Remove when newlib has this fixed */ + #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) return std::hypot(_real, _imaginary); #else return std::sqrt(dot()); diff --git a/src/Magnum/Math/Functions.h b/src/Magnum/Math/Functions.h index 0f16e6e79..a1a42d060 100644 --- a/src/Magnum/Math/Functions.h +++ b/src/Magnum/Math/Functions.h @@ -251,7 +251,8 @@ template Vector floor(const Vector& template inline T round(const T& a); #else template inline typename std::enable_if::value, T>::type round(T a) { - #ifndef CORRADE_TARGET_NACL_NEWLIB + /** @todo Remove when newlib has this fixed */ + #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) return std::round(a); #else return (a > T(0)) ? std::floor(a + T(0.5)) : std::ceil(a - T(0.5)); @@ -260,7 +261,7 @@ template inline typename std::enable_if::value, T template Vector round(const Vector& a) { Vector out; for(std::size_t i = 0; i != size; ++i) { - #ifndef CORRADE_TARGET_NACL_NEWLIB + #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) out[i] = std::round(a[i]); #else out[i] = round(a[i]); @@ -396,8 +397,8 @@ Computes and returns @f$ ab + c @f$. template inline T fma(const T& a, const T& b, const T& c); #else template inline typename std::enable_if::value, T>::type fma(T a, T b, T c) { - /** @todo Remove when NaCl's newlib has this fixed */ - #ifndef CORRADE_TARGET_NACL_NEWLIB + /** @todo Remove when newlib has this fixed */ + #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) return std::fma(a, b, c); #else return a*b + c; diff --git a/src/Magnum/Shader.cpp b/src/Magnum/Shader.cpp index 23a00651f..fa93c2958 100644 --- a/src/Magnum/Shader.cpp +++ b/src/Magnum/Shader.cpp @@ -36,7 +36,7 @@ #include "Implementation/State.h" #include "Implementation/ShaderState.h" -#if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(__MINGW32__) +#if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(CORRADE_TARGET_ANDROID) || defined(__MINGW32__) #include #endif @@ -593,7 +593,8 @@ std::vector Shader::sources() const { return _sources; } Shader& Shader::addSource(std::string source) { if(!source.empty()) { - #if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(__MINGW32__) + /** @todo Remove when newlib has this fixed (also the include above) */ + #if defined(CORRADE_TARGET_NACL_NEWLIB) || defined(CORRADE_TARGET_ANDROID) || defined(__MINGW32__) std::ostringstream converter; converter << (_sources.size()+1)/2; #endif @@ -601,7 +602,7 @@ Shader& Shader::addSource(std::string source) { /* Fix line numbers, so line 41 of third added file is marked as 3(41). Source 0 is the #version string added in constructor. */ _sources.push_back("#line 1 " + - #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(__MINGW32__) + #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID) && !defined(__MINGW32__) std::to_string((_sources.size()+1)/2) + #else converter.str() + From facebfee6c63e00e5339328dfb5e6d48a4a9a10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 01:59:56 +0100 Subject: [PATCH 014/141] package: Android ARM and x86 development ArchLinux PKGBUILDs. --- package/archlinux/PKGBUILD-android-arm | 40 ++++++++++++++++++++++++++ package/archlinux/PKGBUILD-android-x86 | 40 ++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 package/archlinux/PKGBUILD-android-arm create mode 100644 package/archlinux/PKGBUILD-android-x86 diff --git a/package/archlinux/PKGBUILD-android-arm b/package/archlinux/PKGBUILD-android-arm new file mode 100644 index 000000000..ddbacac71 --- /dev/null +++ b/package/archlinux/PKGBUILD-android-arm @@ -0,0 +1,40 @@ +# Author: mosra +pkgname=android-arm-magnum +pkgver=dev +pkgrel=1 +pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Android ARM)" +arch=('any') +url="http://mosra.cz/blog/magnum.php" +license=('MIT') +depends=('android-arm-corrade') +makedepends=('cmake' 'ninja' 'android-ndk') +options=('!strip' '!buildflags' 'staticlibs') + +build() { + if [ ! -d "$startdir/build-android-arm" ] ; then + mkdir "$startdir/build-android-arm" + cd "$startdir/build-android-arm" + + cmake .. \ + -DCMAKE_MODULE_PATH="$startdir/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Android-ARM.cmake" \ + -DTARGET_GLES=ON \ + -DTARGET_GLES2=ON \ + -G Ninja + fi + + cd "$startdir/build-android-arm" + + cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-arm/usr \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON + ninja +} + +package() { + cd "$startdir/build-android-arm" + DESTDIR="$pkgdir/" ninja install +} diff --git a/package/archlinux/PKGBUILD-android-x86 b/package/archlinux/PKGBUILD-android-x86 new file mode 100644 index 000000000..39f31b54f --- /dev/null +++ b/package/archlinux/PKGBUILD-android-x86 @@ -0,0 +1,40 @@ +# Author: mosra +pkgname=android-x86-magnum +pkgver=dev +pkgrel=1 +pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Android x86)" +arch=('any') +url="http://mosra.cz/blog/magnum.php" +license=('MIT') +depends=('android-x86-corrade') +makedepends=('cmake' 'ninja' 'android-ndk') +options=('!strip' '!buildflags' 'staticlibs') + +build() { + if [ ! -d "$startdir/build-android-x86" ] ; then + mkdir "$startdir/build-android-x86" + cd "$startdir/build-android-x86" + + cmake .. \ + -DCMAKE_MODULE_PATH="$startdir/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Android-x86.cmake" \ + -DTARGET_GLES=ON \ + -DTARGET_GLES2=ON \ + -G Ninja + fi + + cd "$startdir/build-android-x86" + + cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-x86/usr \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON + ninja +} + +package() { + cd "$startdir/build-android-x86" + DESTDIR="$pkgdir/" ninja install +} From 6f5d556c02f9a30f5bff3a6a2bb5cfe7cc98a82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 18:28:38 +0100 Subject: [PATCH 015/141] Unique exit code for each failure in Context::Context(). Make it less annoying to debug things on platforms which send all standard output to /dev/hell without any easy way to override that. Yes, I'm looking at you, Android. --- src/Magnum/Context.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index ba41a0946..ca70e810a 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -283,7 +283,7 @@ Context::Context() { everything possible. */ if(ogl_LoadFunctions() == ogl_LOAD_FAILED) { Error() << "ExtensionWrangler: cannot initialize glLoadGen"; - std::exit(1); + std::exit(64); } #endif @@ -327,7 +327,7 @@ Context::Context() { #endif } else { Error() << "Context: unsupported version string:" << version; - std::exit(1); + std::exit(65); } } #endif @@ -356,7 +356,7 @@ Context::Context() { #else Error() << "Context: unsupported OpenGL ES version" << Magnum::version(_version); #endif - std::exit(1); + std::exit(66); } /* Context flags are supported since GL 3.0 */ From d2081e91ac91a0046f46caabeda4a87f1349c6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 18:50:31 +0100 Subject: [PATCH 016/141] Advertise particular application libraries only on supported platforms. --- CMakeLists.txt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bbd2160e5..ab57a329a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,23 +49,31 @@ cmake_dependent_option(WITH_SHAPES "Build Shapes library" ON "NOT WITH_DEBUGTOOL option(WITH_TEXT "Build Text library" ON) cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT WITH_TEXT;NOT WITH_DISTANCEFIELDCONVERTER" ON) -# Application libraries +# NaCl-specific application libraries if(CORRADE_TARGET_NACL) option(WITH_NACLAPPLICATION "Build NaClApplication library" OFF) cmake_dependent_option(WITH_WINDOWLESSNACLAPPLICATION "Build WindowlessNaClApplication library" OFF "NOT WITH_MAGNUMINFO" ON) -else() + +# X11, GLX and EGL-specific application libraries +elseif(CORRADE_TARGET_UNIX AND NOT APPLE) option(WITH_GLXAPPLICATION "Build GlxApplication library" OFF) cmake_dependent_option(WITH_WINDOWLESSGLXAPPLICATION "Build WindowlessGlxApplication library" OFF "NOT WITH_MAGNUMINFO;NOT WITH_DISTANCEFIELDCONVERTER" ON) cmake_dependent_option(WITH_XEGLAPPLICATION "Build XEglApplication library" OFF "TARGET_GLES" OFF) +endif() + +# Platform-independent application libraries +if(NOT CORRADE_TARGET_NACL) cmake_dependent_option(WITH_GLUTAPPLICATION "Build GlutApplication library" OFF "NOT TARGET_GLES" OFF) option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF) endif() -# Utilities (currently depending on WindowlessGlxApplication) -if(UNIX OR CORRADE_TARGET_NACL) +# Magnum Info (currently only using GLX or NaCl) +if((CORRADE_TARGET_UNIX AND NOT APPLE) OR CORRADE_TARGET_NACL) option(WITH_MAGNUMINFO "Build magnum-info utility" OFF) endif() -if(UNIX) + +# Utilities (currently depending on WindowlessGlxApplication) +if(CORRADE_TARGET_UNIX AND NOT APPLE) cmake_dependent_option(WITH_FONTCONVERTER "Build magnum-fontconverter utility" OFF "NOT TARGET_GLES" OFF) cmake_dependent_option(WITH_DISTANCEFIELDCONVERTER "Build magnum-distancefieldconverter utility" OFF "NOT TARGET_GLES" OFF) endif() From 15e1555bcaf546e14b2204d7a28a9c8d416aa8cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 20:11:14 +0100 Subject: [PATCH 017/141] doc: Android building documentation. --- doc/building.dox | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/doc/building.dox b/doc/building.dox index 3a9dbe0aa..6838a528e 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -419,6 +419,49 @@ depending projects. If you have Node.js installed, you can also build and run unit tests using `ctest`. See `BUILD_TESTS` above. +@subsection building-cross-android Crosscompiling for Android ARM and x86 + +You will need [Android NDK](https://developer.android.com/tools/sdk/ndk/index.html) +installed and configured. + +Don't forget to adapt `ANDROID_NDK_ROOT` in `generic/Android-*.cmake` to path +where NDK is installed. Default is `/opt/android-ndk`. Adapt also +`ANDROID_SYSROOT` to your preferred API level. You might also need to update +`ANDROID_TOOLCHAIN_PREFIX` and `ANDROID_TOOLCHAIN_ROOT` to fit your system. + +Then create build directory and run cmake and make in it. The toolchain needs +access to its platform file, so be sure to properly set **absolute** path to +`modules/` directory containing `Platform/Android.cmake`. Also set +`CMAKE_INSTALL_PREFIX` to `/usr` subdirectory of `ANDROID_SYSROOT`. + +Note that `BUILD_STATIC` is implicitly enabled, because manually loading all +depending shared libraries using JNI would be too inconvenient. Decision +between OpenGL ES 2.0 and ES 3.0 is left up to the user (i.e. you need to set +`TARGET_GLES2` to `ON` or `OFF`). + + mkdir -p build-android-arm + cd build-android-arm + cmake .. \ + -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Android-ARM.cmake" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-arm/usr \ + -DTARGET_GLES=ON -DTARGET_GLES2=ON + make + + mkdir -p build-android-x86 + cd build-android-x86 + cmake .. \ + -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Android-x86.cmake" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-x86/usr \ + -DTARGET_GLES=ON -DTARGET_GLES2=ON + make + +Then you can install the library using `make install` to make it available for +depending projects. + @section building-ci-jenkins Jenkins Continuous Integration In `package/ci/` there are `jenkins.xml` and `jenkins-gltests.xml` files From dbf6fc233ea95fe7c3044c4d28bf6204b3054c1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 20:14:50 +0100 Subject: [PATCH 018/141] Advertise Android support. --- README.md | 1 + doc/mainpage.dox | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 8b17a853b..29b7b2af9 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ Platforms: GLUT or SDL2 toolkit) * **Windows** (through GLUT or SDL2 toolkit) * **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) +* **Android** * **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), both `newlib` and `glibc` toolchains are supported) * **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki)) diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 7e83a9135..2cbe5a96e 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -78,6 +78,7 @@ Platforms: GLUT or SDL2 toolkit) - **Windows** (through GLUT or SDL2 toolkit) - **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) +- **Android** - **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), both `newlib` and `glibc` toolchains are supported) - **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki)) From e715b7dfd2c5245c6467d72937f19691fa7c119d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 21 Feb 2014 20:15:16 +0100 Subject: [PATCH 019/141] We don't have any platform support for Android yet. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ab57a329a..df893bbf9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,8 @@ elseif(CORRADE_TARGET_UNIX AND NOT APPLE) cmake_dependent_option(WITH_XEGLAPPLICATION "Build XEglApplication library" OFF "TARGET_GLES" OFF) endif() -# Platform-independent application libraries -if(NOT CORRADE_TARGET_NACL) +# Platform-independent (almost) application libraries +if(NOT CORRADE_TARGET_NACL AND NOT CORRADE_TARGET_ANDROID) cmake_dependent_option(WITH_GLUTAPPLICATION "Build GlutApplication library" OFF "NOT TARGET_GLES" OFF) option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF) endif() From c084c4ebc436024cb174b84a533e16704db12e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 22 Feb 2014 19:52:50 +0100 Subject: [PATCH 020/141] Platform: another round of insane documentation updates. Each class should now have *everything* needed in its documentation, nothing is left out. Most of the text was taken from README in magnum-bootstrap repository. --- src/Magnum/Platform/GlutApplication.h | 35 +++++-- src/Magnum/Platform/GlxApplication.h | 20 ++-- src/Magnum/Platform/NaClApplication.h | 80 ++++++++++++--- src/Magnum/Platform/Sdl2Application.h | 97 ++++++++++++++----- .../Platform/WindowlessGlxApplication.h | 29 ++++-- .../Platform/WindowlessNaClApplication.h | 25 +++-- src/Magnum/Platform/XEglApplication.h | 29 +++--- 7 files changed, 236 insertions(+), 79 deletions(-) diff --git a/src/Magnum/Platform/GlutApplication.h b/src/Magnum/Platform/GlutApplication.h index e2ae1bbe2..43198593d 100644 --- a/src/Magnum/Platform/GlutApplication.h +++ b/src/Magnum/Platform/GlutApplication.h @@ -54,19 +54,36 @@ warping. This application library is available only on desktop OpenGL (Linux, Windows, OS X). It depends on **GLUT** library and is built if `WITH_GLUTAPPLICATION` is -enabled in CMake. To use it, you need to request `%GlutApplication` component -in CMake, add `${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path and link -to `${MAGNUM_GLUTAPPLICATION_LIBRARIES}`. If no other application is requested, +enabled in CMake. + +## Bootstrap application + +Fully contained base application using @ref GlutApplication along with +CMake setup is available in `base` branch of +[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository, +download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base.tar.gz) +or [zip](https://github.com/mosra/magnum-bootstrap/archive/base.zip) file. +After extracting the downloaded archive you can build and run the application +with these four commands: + + mkdir build && cd build + cmake .. + cmake --build . + ./src/MyApplication # or ./src/Debug/MyApplication + +## General usage + +In CMake you need to request `%GlutApplication` component, add +`${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path and link to +`${MAGNUM_GLUTAPPLICATION_LIBRARIES}`. If no other application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See @ref building and @ref cmake for more information. -@section GlutApplication-usage Usage - -You need to implement at least @ref drawEvent() to be able to draw on the -screen. The subclass can be then used directly in `main()` -- see convenience -macro @ref MAGNUM_GLUTAPPLICATION_MAIN(). See @ref platform for more -information. +In C++ code you need to implement at least @ref drawEvent() to be able to draw +on the screen. The subclass can be then used directly in `main()` -- see +convenience macro @ref MAGNUM_GLUTAPPLICATION_MAIN(). See @ref platform for +more information. @code class MyApplication: public Platform::GlutApplication { // implement required methods... diff --git a/src/Magnum/Platform/GlxApplication.h b/src/Magnum/Platform/GlxApplication.h index 696ed5963..b406817bc 100644 --- a/src/Magnum/Platform/GlxApplication.h +++ b/src/Magnum/Platform/GlxApplication.h @@ -42,18 +42,26 @@ Application using pure X11 and GLX. Supports keyboard and mouse handling. This application library is available on desktop OpenGL and @ref MAGNUM_TARGET_DESKTOP_GLES "OpenGL ES emulation on desktop" on Linux. It depends on **X11** library and is built if `WITH_GLXAPPLICATION` is enabled in -CMake. To use it, you need to request `%GlxApplication` component in CMake, add +CMake. + +## Bootstrap application + +The usage is very similar to @ref Sdl2Application, for which fully contained +base application along with CMake setup is available, see its documentation for +more information. + +## General usage + +In CMake you need to request `%GlxApplication` component, add `${MAGNUM_GLXAPPLICATION_INCLUDE_DIRS}` to include path and link to `${MAGNUM_GLXAPPLICATION_LIBRARIES}`. If no other application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See @ref building and @ref cmake for more information. -@section GlxApplication-usage Usage - -You need to implement at least @ref drawEvent() to be able to draw on the -screen. The subclass can be then used directly in `main()` -- see convenience -macro @ref MAGNUM_GLXAPPLICATION_MAIN(). See @ref platform for more +In C++ code you need to implement at least @ref drawEvent() to be able to draw +on the screen. The subclass can be then used directly in `main()` -- see +convenience macro @ref MAGNUM_GLXAPPLICATION_MAIN(). See @ref platform for more information. @code class MyApplication: public Platform::GlxApplication { diff --git a/src/Magnum/Platform/NaClApplication.h b/src/Magnum/Platform/NaClApplication.h index 426187485..fb3552d69 100644 --- a/src/Magnum/Platform/NaClApplication.h +++ b/src/Magnum/Platform/NaClApplication.h @@ -56,19 +56,66 @@ namespace Magnum { namespace Platform { Application running in [Google Chrome Native Client](https://developers.google.com/native-client/). Supports keyboard and mouse handling. -This application library is available only in @ref CORRADE_TARGET_NACL "Native Client". -It is built if `WITH_NACLAPPLICATION` is enabled in CMake. To use it, you need -to request `%NaClApplication` component in CMake, add +This application library is available only in +@ref CORRADE_TARGET_NACL "Google Chrome Native Client", see respective sections +in @ref building-corrade-cross-nacl "Corrade's" and @ref building-cross-nacl "Magnum's" +building documentation. It is built if `WITH_NACLAPPLICATION` is enabled in +CMake. + +## Bootstrap application + +Fully contained base application using @ref GlutApplication for desktop build +and @ref NaClApplication for Native Client build along with full HTML markup +and CMake setup is available in `base-nacl` branch of +[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository, +download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-nacl.tar.gz) +or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-nacl.zip) file. +After extracting the downloaded archive, you can do the desktop build in the +same way as with @ref GlutApplication. For the Native Client build you also +need to put the contents of toolchains repository from https://github.com/mosra/toolchains +in `toolchains/` subdirectory. Don't forget to adapt `NACL_PREFIX` variable in +`toolchains/generic/NaCl-newlib-x86-32.cmake` and +`toolchains/generic/NaCl-newlib-x86-64.cmake` to path where your SDK is +installed. Default is `/usr/nacl`. You may need to adapt also +`NACL_TOOLCHAIN_PATH` so CMake is able to find the compiler. + +Then create build directories for x86-32 and x86-64 and run `cmake` and +build/install commands in them. The toolchains need access to the platform +file, so be sure to properly set **absolute** path to `toolchains/modules/` +directory containing `Platform/NaCl.cmake`. Set `CMAKE_INSTALL_PREFIX` to +location of your webserver to have the files installed in proper location (e.g. +`/srv/http/nacl`). + + mkdir build-nacl-x86-32 && cd build-nacl-x86-32 + cmake .. \ + -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/NaCl-newlib-x86-32.cmake" \ + -DCMAKE_INSTALL_PREFIX=/srv/http/nacl + cmake --build . + cmake --build . --target install + + mkdir build-nacl-x86-64 && cd build-nacl-x86-64 + cmake .. \ + -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/NaCl-newlib-x86-64.cmake" \ + -DCMAKE_INSTALL_PREFIX=/srv/http/nacl + cmake --build . + cmake --build . --target install + +You can then open `MyApplication` through your webserver in Chrome (e.g. +`http://localhost/nacl/MyApplication.html`). + +## General usage + +In CMake you need to request `%NaClApplication` component, add `${MAGNUM_NACLAPPLICATION_INCLUDE_DIRS}` to include path and link to `${MAGNUM_NACLAPPLICATION_LIBRARIES}`. If no other application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See @ref building and @ref cmake for more information. -@section NaClApplication-usage Usage - -You need to implement at least @ref drawEvent() to be able to draw on the -screen. The subclass must be then registered to NaCl API using +In C++ code you need to implement at least @ref drawEvent() to be able to draw +on the screen. The subclass must be then registered to NaCl API using @ref MAGNUM_NACLAPPLICATION_MAIN() macro. See @ref platform for more information. @code @@ -82,13 +129,14 @@ If no other application header is included, this class is also aliased to `Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()` to simplify porting. -@section NaClApplication-html HTML markup and NMF file +### HTML markup and NMF file -You need to provide HTML markup for your application. Template one is below, -you can modify it to your liking. The markup references two files, -`NaClApplication.js` and `WebApplication.css`, both are in `Platform/` -directory in the source tree and are also installed into `share/magnum/` inside -your NaCl toolchain. Change `<application>` to name of your executable. +You need to provide HTML markup for your application. Template one is below or +in the bootstrap application, you can modify it to your liking. The markup +references two files, `NaClApplication.js` and `WebApplication.css`, both are +in `Platform/` directory in the source tree and are also installed into +`share/magnum/` inside your NaCl toolchain. Change `<application>` to +name of your executable. @code @@ -131,9 +179,9 @@ If you target @ref CORRADE_TARGET_NACL_GLIBC "glibc", you need to specify also all additional dependencies. See [Native Client](https://developers.google.com/native-client/) documentation for more information. -@section NaClApplication-console Redirecting output to Chrome's JavaScript console +## Redirecting output to Chrome's JavaScript console -The application redirects @ref Corrade::Utility::Debug "Debug", +The application by default redirects @ref Corrade::Utility::Debug "Debug", @ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error" output to JavaScript console. See also @ref Corrade::Utility::NaClConsoleStreamBuffer for more information. @@ -339,7 +387,7 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public @brief %Configuration Double-buffered RGBA canvas with depth and stencil buffers. -@see @ref NaClApplication(), @ref createContext() +@see @ref NaClApplication(), @ref createContext(), @ref tryCreateContext() */ class NaClApplication::Configuration { public: diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 66f2aec62..b2c712343 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -59,21 +59,69 @@ Application using [Simple DirectMedia Layer](http://www.libsdl.org/) toolkit. Supports keyboard and mouse handling. This application library is in theory available for all platforms for which -SDL2 is ported (thus also @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", but not -@ref CORRADE_TARGET_NACL "NaCl"). It depends on **SDL2** library (Emscripten -has it built in) and is built if `WITH_SDL2APPLICATION` is enabled in CMake. To -use it, you need to copy `FindSDL2.cmake` from `modules/` directory in %Magnum -source to `modules/` dir in your project (so CMake is able to find SDL2), -request `%Sdl2Application` component in CMake, add -`${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` to include path and link to -`${MAGNUM_SDL2APPLICATION_LIBRARIES}`. If no other application is requested, -you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and -`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See +SDL2 is ported (thus also @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", see +respective sections in @ref building-corrade-cross-emscripten "Corrade's" and +@ref building-cross-emscripten "Magnum's" building documentation). It depends +on **SDL2** library (Emscripten has it built in) and is built if +`WITH_SDL2APPLICATION` is enabled in CMake. + +## Bootstrap application + +Fully contained base application using @ref Sdl2Application along with +CMake setup is available in `base-sdl2` branch of +[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository, +download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-sdl2.tar.gz) +or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-sdl2.zip) file. +After extracting the downloaded archive you can build and run the application +with these four commands: + + mkdir build && cd build + cmake .. + cmake --build . + ./src/MyApplication # or ./src/Debug/MyApplication + +## Bootstrap application for Emscripten + +Fully contained base application using @ref Sdl2Application for both desktop +and Emscripten build along with full HTML markup and CMake setup is available +in `base-emscripten` branch of [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) +repository, download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-emscripten.tar.gz) +or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-emscripten.zip) +file. After extracting the downloaded archive, you can do the desktop build in +the same way as above. For the Emscripten build you also need to put the +contents of toolchains repository from https://github.com/mosra/toolchains +in `toolchains/` subdirectory. Don't forget to adapt `EMSCRIPTEN_PREFIX` +variable in `toolchains/generic/Emscripten.cmake` to path where Emscripten is +installed. Default is `/usr/emscripten`. + +Then create build directory and run `cmake` and build/install commands in it. +The toolchain needs access to its platform file, so be sure to properly set +**absolute** path to `toolchains/modules/` directory containing `Platform/Emscripten.cmake`. +Set `CMAKE_INSTALL_PREFIX` to have the files installed in proper location (a +webserver, e.g. `/srv/http/emscripten`). + + mkdir build-emscripten && cd build-emscripten + cmake .. \ + -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Emscripten.cmake" + -DCMAKE_INSTALL_PREFIX=/srv/http/emscripten + cmake --build . + cmake --build . --target install + +You can then open `MyApplication.html` in Chrome or Firefox (through webserver, +e.g. `http://localhost/emscripten/MyApplication.html`). + +## General usage + +For CMake you need to copy `FindSDL2.cmake` from `modules/` directory in +%Magnum source to `modules/` dir in your project (so it is able to find SDL2), +request `%Sdl2Application` component, add `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` +to include path and link to `${MAGNUM_SDL2APPLICATION_LIBRARIES}`. If no other +application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` +and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See @ref building and @ref cmake for more information. -@section Sdl2Application-usage Usage - -You need to implement at least @ref drawEvent() to be able to draw on the +In C++ code you need to implement at least @ref drawEvent() to be able to draw on the screen. The subclass can be then used directly in `main()` -- see convenience macro @ref MAGNUM_SDL2APPLICATION_MAIN(). See @ref platform for more information. @@ -88,14 +136,15 @@ If no other application header is included, this class is also aliased to `Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()` to simplify porting. -@section Sdl2Application-html Usage with Emscripten +### Usage with Emscripten -If you are targetting @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", you need to -provide HTML markup for your application. Template one is below, you can modify -it to your liking. The markup references two files, `EmscriptenApplication.js` -and `WebApplication.css`, both are in `Platform/` directory in the source tree -and are also installed into `share/magnum/` inside your Emscripten toolchain. -Change `<application>` to name of your executable. +If you are targetting Emscripten, you need to provide HTML markup for your +application. Template one is below or in the bootstrap application, you can +modify it to your liking. The markup references two files, +`EmscriptenApplication.js` and `WebApplication.css`, both are in `Platform/` +directory in the source tree and are also installed into `share/magnum/` inside +your Emscripten toolchain. Change `<application>` to name of your +executable. @code @@ -123,9 +172,11 @@ file contains event listeners which print loading status on the page. The status displayed in the remaining two `<div>`s, if they are available. The CSS file contains rudimentary style to avoid eye bleeding. -The application redirects @ref Corrade::Utility::Debug "Debug", -@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error" -output to JavaScript console. +## Redirecting output to JavaScript console + +The application redirects all output (thus also @ref Corrade::Utility::Debug "Debug", +@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error") +to JavaScript console. */ class Sdl2Application { public: diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 9cb56707f..11d90b556 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -53,16 +53,33 @@ Application for offscreen rendering using pure X11 and GLX. This application library is available on desktop OpenGL and @ref MAGNUM_TARGET_DESKTOP_GLES "OpenGL ES emulation on desktop" on Linux. It depends on **X11** library and is built if `WITH_WINDOWLESSGLXAPPLICATION` is -enabled in CMake. To use it, you need to request `%WindowlessGlxApplication` -component in CMake, add `${MAGNUM_WINDOWLESSGLXAPPLICATION_INCLUDE_DIRS}` to -include path and link to `${MAGNUM_WINDOWLESSGLXAPPLICATION_LIBRARIES}`. If no -other windowless application is requested, you can also use generic +enabled in CMake. + +## Bootstrap application + +Fully contained windowless application using @ref WindowlessGlxApplication +along with CMake setup is available in `base-windowless` branch of +[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) +repository, download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-windowless.tar.gz) +or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-windowless.zip) +file. After extracting the downloaded archive you can build and run the +application with these four commands: + + mkdir build && cd build + cmake .. + cmake --build . + ./src/MyApplication # or ./src/Debug/MyApplication + +## General usage + +In CMake you need to request `%WindowlessGlxApplication` component, add +`${MAGNUM_WINDOWLESSGLXAPPLICATION_INCLUDE_DIRS}` to include path and link to +`${MAGNUM_WINDOWLESSGLXAPPLICATION_LIBRARIES}`. If no other windowless +application is requested, you can also use generic `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See @ref building and @ref cmake for more information. -@section WindowlessGlxApplication-usage Usage - Place your code into @ref exec(). The subclass can be then used directly in `main()` -- see convenience macro @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(). See @ref platform for more information. diff --git a/src/Magnum/Platform/WindowlessNaClApplication.h b/src/Magnum/Platform/WindowlessNaClApplication.h index a214a1fe1..c9f181d4b 100644 --- a/src/Magnum/Platform/WindowlessNaClApplication.h +++ b/src/Magnum/Platform/WindowlessNaClApplication.h @@ -52,9 +52,20 @@ namespace Magnum { namespace Platform { Application for offscreen rendering running in [Google Chrome Native Client](https://developers.google.com/native-client/). -This application library is available only in @ref CORRADE_TARGET_NACL "Native Client". -It is built if `WITH_WINDOWLESSNACLAPPLICATION` is enabled in CMake. To use it, -you need to request `%WindowlessNaClApplication` component in CMake, add +This application library is available only in @ref CORRADE_TARGET_NACL "Native Client", +see respective sections in @ref building-corrade-cross-nacl "Corrade's" and +@ref building-cross-nacl "Magnum's" building documentation. It is built if +`WITH_WINDOWLESSNACLAPPLICATION` is enabled in CMake. + +## Bootstrap application + +The usage is very similar to @ref NaClApplication, for which fully contained +base application along with CMake setup is available, see its documentation for +more information. + +## General Usage + +In CMake you need to request `%WindowlessNaClApplication` component, add `${MAGNUM_WINDOWLESSNACLAPPLICATION_INCLUDE_DIRS}` to include path and link to `${MAGNUM_WINDOWLESSNACLAPPLICATION_LIBRARIES}`. If no other windowless application is requested, you can also use generic @@ -62,8 +73,6 @@ application is requested, you can also use generic `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See @ref building and @ref cmake for more information. -@section WindowlessNaClApplication-usage Usage - Place your code into @ref exec(). The subclass must be then registered to NaCl API using @ref MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() macro. See @ref platform for more information. @@ -78,7 +87,7 @@ If no other application header is included, this class is also aliased to `Platform::WindowlessApplication` and the macro is aliased to `MAGNUM_WINDOWLESSAPPLICATION_MAIN()` to simplify porting. -@section WindowlessNaClApplication-html HTML markup and NMF file +### HTML markup and NMF file You need to provide HTML markup containing `<embed>` pointing to `*.nmf` file describing the application. See @ref NaClApplication for more information. @@ -86,9 +95,9 @@ You may want to hide the `<embed>` (for example using CSS `visibility: hidden;`), as it probably won't display anything to default framebuffer. -@section WindowlessNaClApplication-console Redirecting output to Chrome's JavaScript console +## Redirecting output to Chrome's JavaScript console -The application redirects @ref Corrade::Utility::Debug "Debug", +The application by default redirects @ref Corrade::Utility::Debug "Debug", @ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error" output to JavaScript console. See also @ref Corrade::Utility::NaClConsoleStreamBuffer for more information. diff --git a/src/Magnum/Platform/XEglApplication.h b/src/Magnum/Platform/XEglApplication.h index ff96cfd65..759487d49 100644 --- a/src/Magnum/Platform/XEglApplication.h +++ b/src/Magnum/Platform/XEglApplication.h @@ -41,21 +41,28 @@ Application using pure X11 and EGL. Supports keyboard and mouse handling. This application library is available on both desktop OpenGL and @ref MAGNUM_TARGET_GLES "OpenGL ES" on Linux. It depends on **X11** and **EGL** -libraries and is built if `WITH_XEGLAPPLICATION` is enabled in CMake. To use -it, you need to copy `FindEGL.cmake` from `modules/` directory in %Magnum -source to `modules/` dir in your project (so CMake is able to find EGL), -request `%XEglApplication` component in CMake, add `${MAGNUM_XEGLAPPLICATION_INCLUDE_DIRS}` -to include path and link to `${MAGNUM_XEGLAPPLICATION_LIBRARIES}`. If no other +libraries and is built if `WITH_XEGLAPPLICATION` is enabled in CMake. + +## Bootstrap application + +The usage is very similar to @ref Sdl2Application, for which fully contained +base application along with CMake setup is available, see its documentation for +more information. + +## General usage + +For CMake you need to copy `FindEGL.cmake` from `modules/` directory in %Magnum +source to `modules/` dir in your project (so it is able to find EGL), request +`%XEglApplication` component, add `${MAGNUM_XEGLAPPLICATION_INCLUDE_DIRS}` to +include path and link to `${MAGNUM_XEGLAPPLICATION_LIBRARIES}`. If no other application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See @ref building and @ref cmake for more information. -@section XEglApplication-usage Usage - -You need to implement at least @ref drawEvent() to be able to draw on the -screen. The subclass can be then used directly in `main()` -- see convenience -macro @ref MAGNUM_XEGLAPPLICATION_MAIN(). See @ref platform for more -information. +In C++ code you need to implement at least @ref drawEvent() to be able to draw +on the screen. The subclass can be then used directly in `main()` -- see +convenience macro @ref MAGNUM_XEGLAPPLICATION_MAIN(). See @ref platform for +more information. @code class MyApplication: public Platform::XEglApplication { // implement required methods... From 1aaa350e901799105d514394a371aa07114a6005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 22 Feb 2014 19:58:10 +0100 Subject: [PATCH 021/141] doc: use absolute includes. This somehow slipped through. --- doc/platform.dox | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/platform.dox b/doc/platform.dox index 607ffc2d0..d85bb5091 100644 --- a/doc/platform.dox +++ b/doc/platform.dox @@ -66,10 +66,10 @@ blue color is shown in the following code listing. repository. @code -#include -#include -#include -#include +#include +#include +#include +#include using namespace Magnum; @@ -148,8 +148,8 @@ renderer string and exits is in the following code listing. repository. @code -#include -#include +#include +#include using namespace Magnum; From 3cd1093a49f3afeede8372d4e1a738bcf22c3e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 22 Feb 2014 20:01:49 +0100 Subject: [PATCH 022/141] doc: fix more obsolete stuff in Platform docs. --- doc/platform.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/platform.dox b/doc/platform.dox index d85bb5091..44c6700a5 100644 --- a/doc/platform.dox +++ b/doc/platform.dox @@ -88,7 +88,7 @@ MyApplication::MyApplication(const Arguments& arguments): Platform::Application( void MyApplication::drawEvent() { // Clear the window - defaultFramebuffer.clear(DefaultFramebuffer::Clear::Color); + defaultFramebuffer.clear(FramebufferClear::Color); // The context is double-buffered, swap buffers swapBuffers(); From 20ee86be86677e975e5172e6cfaba26e8f96f15c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 22 Feb 2014 20:36:22 +0100 Subject: [PATCH 023/141] doc: building documentation updates. * Using portable `cmake --build` instead of `make`. * Mentioning all crosscompiling Arch PKGBUILDs. --- doc/building.dox | 105 ++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/doc/building.dox b/doc/building.dox index 6838a528e..20aabcd21 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -69,7 +69,7 @@ assuming you have at least basic knowledge of CMake. On Unix-based OSs, the library (for example with support for GLUT applications) can be built and installed using these four commands: - mkdir -p build && cd build + mkdir build && cd build cmake .. \ -DCMAKE_INSTALL_PREFIX=/usr \ -DWITH_GLUTAPPLICATION=ON @@ -102,8 +102,7 @@ The most straightforward way to build and install the library is again via the command-line. The bonus point is that you don't even need to wait for Visual Studio to load: - mkdir build - cd build + mkdir build && cd build cmake -DCMAKE_INSTALL_PREFIX="C:/Sys" .. cmake --build . cmake --build . --target install @@ -317,8 +316,9 @@ contents in `toolchains/` subdirectory. @subsection building-cross-win Crosscompiling for Windows using MinGW @note This guide is tailored mainly for crosscompiling from ArchLinux. For -this system there is also prepared `mingw32-magnum` development package in -root, named `PKGBUILD-mingw32`. + this system there is also prepared `mingw32-magnum` development package in + `package/archlinux`, named `PKGBUILD-mingw32`. See + @ref building-packages-arch "above" for more information. You will need MinGW32 versions of the compiler and all dependent libraries (Corrade), i.e. these ArchLinux packages: @@ -327,19 +327,18 @@ You will need MinGW32 versions of the compiler and all dependent libraries - `mingw32-runtime` - `mingw32-corrade` -Then create build directory and run cmake and make. You may need to modify the -`basic-mingw32.cmake` file and `CMAKE_INSTALL_PREFIX` to suit your distribution -filesystem hierarchy. +Then create build directory and run cmake and build command in it. You may need +to modify the `basic-mingw32.cmake` file and `CMAKE_INSTALL_PREFIX` to suit +your distribution filesystem hierarchy. - mkdir build-win - cd build-win + mkdir build-win && cd build-win cmake .. \ -DCMAKE_TOOLCHAIN_FILE=../toolchains/archlinux/basic-mingw32.cmake \ -DCMAKE_INSTALL_PREFIX=/usr/i486-mingw32 - make + cmake --build . -Then you can install the package using `make install` to make it available for -depending projects. +Then you can install the package using `cmake --build . --target install` to +make it available for depending projects. @subsection building-cross-nacl Crosscompiling for Google Chrome Native Client @@ -354,14 +353,13 @@ adapt `NACL_PREFIX` variable in `generic/NaCl-*-x86-32.cmake` and to find the compiler. NaCl currently supports only OpenGL ES 2, thus `TARGET_GLES` and `TARGET_GLES2` is always enabled. -Then create build directories for x86-32 and x86-64 and run cmake and make in -them. The toolchains need access to the platform file, so be sure to properly -set **absolute** path to `modules/` directory containing `Platform/NaCl.cmake`. -Also adapt `CMAKE_INSTALL_PREFIX` to the same value as in `NACL_PREFIX` in -toolchain file. +Then create build directories for x86-32 and x86-64 and run cmake and build +command in them. The toolchains need access to the platform file, so be sure to +properly set **absolute** path to `modules/` directory containing +`Platform/NaCl.cmake`. Also adapt `CMAKE_INSTALL_PREFIX` to the same value as +in `NACL_PREFIX` in toolchain file. - mkdir -p build-nacl-x86-32 - cd build-nacl-x86-32 + mkdir build-nacl-x86-32 && cd build-nacl-x86-32 cmake .. \ -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/NaCl-newlib-x86-32.cmake" \ @@ -369,23 +367,24 @@ toolchain file. -DCMAKE_INSTALL_PREFIX=/usr/nacl \ -DWITH_NACLAPPLICATION=ON \ -DLIB_SUFFIX=/32 - make + cmake --build . - mkdir -p build-nacl-x86-64 - cd build-nacl-x86-64 + mkdir build-nacl-x86-64 && cd build-nacl-x86-64 cmake .. \ -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/NaCl-newlib-x86-64.cmake" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/nacl \ -DWITH_NACLAPPLICATION=ON - make + cmake --build . -Then you can install both versions using `make install` to make them available -for depending projects. The headers are shared by both versions. +Then you can install both versions using `cmake --build . --target install` to +make them available for depending projects. The headers are shared by both +versions. -For ArchLinux there are also prepared package files in root, named -`PKGBUILD-nacl-glibc` and `PKGBUILD-nacl-newlib`. +For ArchLinux there are also prepared package files in `package/archlinux`, +named `PKGBUILD-nacl-glibc` and `PKGBUILD-nacl-newlib`, see +@ref building-packages-arch "above" for more information. @subsection building-cross-emscripten Crosscompiling for Emscripten @@ -397,28 +396,30 @@ to path where Emscripten is installed. Default is `/usr/emscripten`. Emscripten supports dynamic libraries only to simplify porting and they are generally slower, thus `BUILD_STATIC` is implicitly enabled. -Then create build directory and run cmake and make in it. The toolchain needs -access to its platform file, so be sure to properly set **absolute** path to -`modules/` directory containing `Platform/Emscripten.cmake`. Also set -`CMAKE_INSTALL_PREFIX` to value which is contained in `CMAKE_FIND_ROOT_PATH` in -toolchain file. +Then create build directory and run cmake and build command in it. The +toolchain needs access to its platform file, so be sure to properly set +**absolute** path to `modules/` directory containing `Platform/Emscripten.cmake`. +Also set `CMAKE_INSTALL_PREFIX` to path contained in `EMSCRIPTEN_TOOLCHAIN_PATH`. - mkdir -p build-emscripten - cd build-emscripten + mkdir build-emscripten && cd build-emscripten cmake .. \ -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Emscripten.cmake" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \ -DWITH_SDL2APPLICATION=ON - make + cmake --build . -Then you can install the library using `make install` to make it available for -depending projects. +Then you can install the library using `cmake --build . --target install` to +make it available for depending projects. If you have Node.js installed, you can also build and run unit tests using `ctest`. See `BUILD_TESTS` above. +For ArchLinux there is also prepared package file in `package/archlinux`, +named `PKGBUILD-emscripten`, see @ref building-packages-arch "above" for more +information. + @subsection building-cross-android Crosscompiling for Android ARM and x86 You will need [Android NDK](https://developer.android.com/tools/sdk/ndk/index.html) @@ -429,9 +430,9 @@ where NDK is installed. Default is `/opt/android-ndk`. Adapt also `ANDROID_SYSROOT` to your preferred API level. You might also need to update `ANDROID_TOOLCHAIN_PREFIX` and `ANDROID_TOOLCHAIN_ROOT` to fit your system. -Then create build directory and run cmake and make in it. The toolchain needs -access to its platform file, so be sure to properly set **absolute** path to -`modules/` directory containing `Platform/Android.cmake`. Also set +Then create build directory and run cmake and build command in it. The +toolchain needs access to its platform file, so be sure to properly set **absolute** +path to `modules/` directory containing `Platform/Android.cmake`. Also set `CMAKE_INSTALL_PREFIX` to `/usr` subdirectory of `ANDROID_SYSROOT`. Note that `BUILD_STATIC` is implicitly enabled, because manually loading all @@ -439,35 +440,37 @@ depending shared libraries using JNI would be too inconvenient. Decision between OpenGL ES 2.0 and ES 3.0 is left up to the user (i.e. you need to set `TARGET_GLES2` to `ON` or `OFF`). - mkdir -p build-android-arm - cd build-android-arm + mkdir build-android-arm && cd build-android-arm cmake .. \ -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Android-ARM.cmake" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-arm/usr \ -DTARGET_GLES=ON -DTARGET_GLES2=ON - make + cmake --build . - mkdir -p build-android-x86 - cd build-android-x86 + mkdir build-android-x86 && cd build-android-x86 cmake .. \ -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Android-x86.cmake" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-x86/usr \ -DTARGET_GLES=ON -DTARGET_GLES2=ON - make + cmake --build . + +Then you can install the library using `cmake --build . --target install` to +make it available for depending projects. -Then you can install the library using `make install` to make it available for -depending projects. +For ArchLinux there are also prepared package files in `package/archlinux`, +named `PKGBUILD-android-arm` and `PKGBUILD-android-x86`, see +@ref building-packages-arch "above" for more information. @section building-ci-jenkins Jenkins Continuous Integration In `package/ci/` there are `jenkins.xml` and `jenkins-gltests.xml` files containing job configuration, one for build and non-GL tests and the other for -GL tests only. Setup your Jenkins server, enable the **Git** and -**Text-finder** plugin and download the CLI application from here: +GL tests only. Setup your Jenkins server, enable the **Git** and **Text-finder** +plugin and download the CLI application from here: http://your-jenkins-server/cli From f021f09df832abde78afc4ba67b596928344d827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 23 Feb 2014 12:35:58 +0100 Subject: [PATCH 024/141] Platform: finally added proper key events to GlutApplication. The functions were there all the time, I just didn't try hard enough to find them. The special keys now have different values (the lower 16 bits are reserved for ASCII), but it is a source-compatible change. --- src/Magnum/Platform/GlutApplication.cpp | 22 ++++- src/Magnum/Platform/GlutApplication.h | 109 +++++++++++++++++------- 2 files changed, 98 insertions(+), 33 deletions(-) diff --git a/src/Magnum/Platform/GlutApplication.cpp b/src/Magnum/Platform/GlutApplication.cpp index d11123d65..58f8bc1ec 100644 --- a/src/Magnum/Platform/GlutApplication.cpp +++ b/src/Magnum/Platform/GlutApplication.cpp @@ -95,7 +95,10 @@ bool GlutApplication::tryCreateContext(const Configuration& configuration) { return false; } glutReshapeFunc(staticViewportEvent); - glutSpecialFunc(staticKeyEvent); + glutKeyboardFunc(staticKeyPressEvent); + glutKeyboardUpFunc(staticKeyReleaseEvent); + glutSpecialFunc(staticSpecialKeyPressEvent); + glutSpecialUpFunc(staticSpecialKeyReleaseEvent); glutMouseFunc(staticMouseEvent); glutMotionFunc(staticMouseMoveEvent); glutDisplayFunc(staticDrawEvent); @@ -108,11 +111,26 @@ GlutApplication::~GlutApplication() { delete c; } -void GlutApplication::staticKeyEvent(int key, int x, int y){ +void GlutApplication::staticKeyPressEvent(unsigned char key, int x, int y) { KeyEvent e(static_cast(key), {x, y}); instance->keyPressEvent(e); } +void GlutApplication::staticKeyReleaseEvent(unsigned char key, int x, int y) { + KeyEvent e(static_cast(key), {x, y}); + instance->keyReleaseEvent(e); +} + +void GlutApplication::staticSpecialKeyPressEvent(int key, int x, int y){ + KeyEvent e(static_cast(key << 16), {x, y}); + instance->keyPressEvent(e); +} + +void GlutApplication::staticSpecialKeyReleaseEvent(int key, int x, int y){ + KeyEvent e(static_cast(key << 16), {x, y}); + instance->keyReleaseEvent(e); +} + void GlutApplication::staticMouseEvent(int button, int state, int x, int y) { MouseEvent e(static_cast(button), {x, y}); if(state == GLUT_DOWN) diff --git a/src/Magnum/Platform/GlutApplication.h b/src/Magnum/Platform/GlutApplication.h index 43198593d..3721ef1fa 100644 --- a/src/Magnum/Platform/GlutApplication.h +++ b/src/Magnum/Platform/GlutApplication.h @@ -48,9 +48,8 @@ namespace Platform { /** @nosubgrouping @brief GLUT application -Application using GLUT toolkit. Supports keyboard handling for limited subset -of keys, mouse handling with support for changing cursor and mouse tracking and -warping. +Application using GLUT toolkit. Supports keyboard and mouse handling with +support for changing cursor and mouse tracking and warping. This application library is available only on desktop OpenGL (Linux, Windows, OS X). It depends on **GLUT** library and is built if `WITH_GLUTAPPLICATION` is @@ -182,12 +181,7 @@ class GlutApplication { /** @copydoc Sdl2Application::keyPressEvent() */ virtual void keyPressEvent(KeyEvent& event); - /** - * @brief Key release event - * - * Included only for compatibility with other toolkits, doesn't get - * called at all. - */ + /** @copydoc Sdl2Application::keyReleaseEvent() */ virtual void keyReleaseEvent(KeyEvent& event); /*@}*/ @@ -254,7 +248,11 @@ class GlutApplication { instance->viewportEvent({x, y}); } - static void staticKeyEvent(int key, int x, int y); + static void staticKeyPressEvent(unsigned char key, int x, int y); + static void staticKeyReleaseEvent(unsigned char key, int x, int y); + + static void staticSpecialKeyPressEvent(int key, int x, int y); + static void staticSpecialKeyReleaseEvent(int key, int x, int y); static void staticMouseEvent(int button, int state, int x, int y); @@ -396,27 +394,76 @@ class GlutApplication::KeyEvent: public GlutApplication::InputEvent { * * @see @ref key() */ - enum class Key: int { - Up = GLUT_KEY_UP, /**< Up arrow */ - Down = GLUT_KEY_DOWN, /**< Down arrow */ - Left = GLUT_KEY_LEFT, /**< Left arrow */ - Right = GLUT_KEY_RIGHT, /**< Right arrow */ - F1 = GLUT_KEY_F1, /**< F1 */ - F2 = GLUT_KEY_F2, /**< F2 */ - F3 = GLUT_KEY_F3, /**< F3 */ - F4 = GLUT_KEY_F4, /**< F4 */ - F5 = GLUT_KEY_F5, /**< F5 */ - F6 = GLUT_KEY_F6, /**< F6 */ - F7 = GLUT_KEY_F7, /**< F7 */ - F8 = GLUT_KEY_F8, /**< F8 */ - F9 = GLUT_KEY_F9, /**< F9 */ - F10 = GLUT_KEY_F10, /**< F10 */ - F11 = GLUT_KEY_F11, /**< F11 */ - F12 = GLUT_KEY_F12, /**< F12 */ - Home = GLUT_KEY_HOME, /**< Home */ - End = GLUT_KEY_END, /**< End */ - PageUp = GLUT_KEY_PAGE_UP, /**< Page up */ - PageDown = GLUT_KEY_PAGE_DOWN /**< Page down */ + enum class Key: UnsignedInt { + Esc = '\x1b', /**< Escape */ + + Up = GLUT_KEY_UP << 16, /**< Up arrow */ + Down = GLUT_KEY_DOWN << 16, /**< Down arrow */ + Left = GLUT_KEY_LEFT << 16, /**< Left arrow */ + Right = GLUT_KEY_RIGHT << 16, /**< Right arrow */ + F1 = GLUT_KEY_F1 << 16, /**< F1 */ + F2 = GLUT_KEY_F2 << 16, /**< F2 */ + F3 = GLUT_KEY_F3 << 16, /**< F3 */ + F4 = GLUT_KEY_F4 << 16, /**< F4 */ + F5 = GLUT_KEY_F5 << 16, /**< F5 */ + F6 = GLUT_KEY_F6 << 16, /**< F6 */ + F7 = GLUT_KEY_F7 << 16, /**< F7 */ + F8 = GLUT_KEY_F8 << 16, /**< F8 */ + F9 = GLUT_KEY_F9 << 16, /**< F9 */ + F10 = GLUT_KEY_F10 << 16, /**< F10 */ + F11 = GLUT_KEY_F11 << 16, /**< F11 */ + F12 = GLUT_KEY_F12 << 16, /**< F12 */ + Home = GLUT_KEY_HOME << 16, /**< Home */ + End = GLUT_KEY_END << 16, /**< End */ + PageUp = GLUT_KEY_PAGE_UP << 16, /**< Page up */ + PageDown = GLUT_KEY_PAGE_DOWN << 16, /**< Page down */ + + Space = ' ', /**< Space */ + Comma = ',', /**< Comma */ + Period = '.', /**< Period */ + Minus = '-', /**< Minus */ + Plus = '+', /**< Plus */ + Slash = '/', /**< Slash */ + Percent = '%', /**< Percent */ + Equal = '=', /**< Equal */ + + Zero = '0', /**< Zero */ + One = '1', /**< One */ + Two = '2', /**< Two */ + Three = '3', /**< Three */ + Four = '4', /**< Four */ + Five = '5', /**< Five */ + Six = '6', /**< Six */ + Seven = '7', /**< Seven */ + Eight = '8', /**< Eight */ + Nine = '9', /**< Nine */ + + A = 'a', /**< Letter A */ + B = 'b', /**< Letter B */ + C = 'c', /**< Letter C */ + D = 'd', /**< Letter D */ + E = 'e', /**< Letter E */ + F = 'f', /**< Letter F */ + G = 'g', /**< Letter G */ + H = 'h', /**< Letter H */ + I = 'i', /**< Letter I */ + J = 'j', /**< Letter J */ + K = 'k', /**< Letter K */ + L = 'l', /**< Letter L */ + M = 'm', /**< Letter M */ + N = 'n', /**< Letter N */ + O = 'o', /**< Letter O */ + P = 'p', /**< Letter P */ + Q = 'q', /**< Letter Q */ + R = 'r', /**< Letter R */ + S = 's', /**< Letter S */ + T = 't', /**< Letter T */ + U = 'u', /**< Letter U */ + V = 'v', /**< Letter V */ + W = 'w', /**< Letter W */ + X = 'x', /**< Letter X */ + Y = 'y', /**< Letter Y */ + Z = 'z' /**< Letter Z */ }; /** @brief Key */ From 68a672917340b0479a7313196ec77cb1231f024e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 17:46:13 +0100 Subject: [PATCH 025/141] Platform: more documentation updates. --- src/Magnum/Platform/AbstractXApplication.h | 5 ++++- src/Magnum/Platform/GlutApplication.h | 14 ++++++++++---- src/Magnum/Platform/GlxApplication.h | 7 ++++--- src/Magnum/Platform/NaClApplication.h | 4 +++- src/Magnum/Platform/Sdl2Application.h | 11 +++++++---- src/Magnum/Platform/WindowlessGlxApplication.h | 11 +++++++---- src/Magnum/Platform/WindowlessNaClApplication.h | 16 +++++++++++++--- src/Magnum/Platform/XEglApplication.h | 7 ++++--- 8 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index 41c265034..73f7c6faf 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -88,7 +88,10 @@ class AbstractXApplication { /** * @brief Execute main loop - * @return Value for returning from `main()`. + * @return Value for returning from `main()` + * + * See @ref MAGNUM_GLXAPPLICATION_MAIN() or + * @ref MAGNUM_XEGLAPPLICATION_MAIN() for usage information. */ int exec(); diff --git a/src/Magnum/Platform/GlutApplication.h b/src/Magnum/Platform/GlutApplication.h index 3721ef1fa..4947351da 100644 --- a/src/Magnum/Platform/GlutApplication.h +++ b/src/Magnum/Platform/GlutApplication.h @@ -132,7 +132,12 @@ class GlutApplication { /** @brief Moving is not allowed */ GlutApplication& operator=(GlutApplication&&) = delete; - /** @copydoc Sdl2Application::exec() */ + /** + * @brief Execute main loop + * @return Value for returning from `main()` + * + * See @ref MAGNUM_GLUTAPPLICATION_MAIN() for usage information. + */ int exec() { glutMainLoop(); return 0; @@ -560,9 +565,10 @@ class GlutApplication::MouseMoveEvent: public GlutApplication::InputEvent { @brief Entry point for GLUT-based applications @param className Class name -Can be with @ref Magnum::Platform::GlutApplication "Platform::GlutApplication" -subclasses used as equivalent to the following code to achieve better -portability, see @ref portability-applications for more information. +See @ref Magnum::Platform::GlutApplication "Platform::GlutApplication" for +usage information. This macro abstracts out platform-specific entry point code +and is equivalent to the following, see @ref portability-applications for more +information. @code int main(int argc, char** argv) { className app({argc, argv}); diff --git a/src/Magnum/Platform/GlxApplication.h b/src/Magnum/Platform/GlxApplication.h index b406817bc..8aead290a 100644 --- a/src/Magnum/Platform/GlxApplication.h +++ b/src/Magnum/Platform/GlxApplication.h @@ -92,9 +92,10 @@ class GlxApplication: public AbstractXApplication { @brief Entry point for GLX-based applications @param className Class name -Can be used with @ref Magnum::Platform::GlxApplication "Platform::GlxApplication" -subclasses as equivalent to the following code to achieve better portability, -see @ref portability-applications for more information. +See @ref Magnum::Platform::GlxApplication "Platform::GlxApplication" for usage +information. This macro abstracts out platform-specific entry point code and is +equivalent to the following, see @ref portability-applications for more +information. @code int main(int argc, char** argv) { className app({argc, argv}); diff --git a/src/Magnum/Platform/NaClApplication.h b/src/Magnum/Platform/NaClApplication.h index fb3552d69..d134c5560 100644 --- a/src/Magnum/Platform/NaClApplication.h +++ b/src/Magnum/Platform/NaClApplication.h @@ -750,7 +750,9 @@ namespace Implementation { @brief Entry point for NaCl application @param application Application class name -See @ref Magnum::Platform::NaClApplication "Platform::NaClApplication" and +See @ref Magnum::Platform::NaClApplication "Platform::NaClApplication" for +usage information. This macro abstracts out platform-specific entry point code +(the classic `main()` function cannot be used in NaCl). See @ref portability-applications for more information. When no other application header is included this macro is also aliased to `MAGNUM_APPLICATION_MAIN()`. */ diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index b2c712343..60009586b 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -232,7 +232,9 @@ class Sdl2Application { /** * @brief Execute main loop - * @return Value for returning from `main()`. + * @return Value for returning from `main()` + * + * See @ref MAGNUM_SDL2APPLICATION_MAIN() for usage information. */ int exec(); @@ -876,9 +878,10 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent { @brief Entry point for SDL2-based applications @param className Class name -Can be used with @ref Magnum::Platform::Sdl2Application "Platform::Sdl2Application" -subclasses as equivalent to the following code to achieve better portability, -see @ref portability-applications for more information. +See @ref Magnum::Platform::Sdl2Application "Platform::Sdl2Application" for +usage information. This macro abstracts out platform-specific entry point code +and is equivalent to the following, see @ref portability-applications for more +information. @code int main(int argc, char** argv) { className app({argc, argv}); diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 11d90b556..024ce2fa7 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -130,7 +130,9 @@ class WindowlessGlxApplication { /** * @brief Execute application - * @return Value for returning from `main()`. + * @return Value for returning from `main()` + * + * See @ref MAGNUM_WINDOWLESSAPPLICATION_MAIN() for usage information. */ virtual int exec() = 0; @@ -174,9 +176,10 @@ class WindowlessGlxApplication::Configuration { @brief Entry point for windowless GLX application @param className Class name -Can be used with @ref Magnum::Platform::WindowlessGlxApplication "Platform::WindowlessGlxApplication" -subclasses as equivalent to the following code to achieve better portability, -see @ref portability-applications for more information. +See @ref Magnum::Platform::WindowlessGlxApplication "Platform::WindowlessGlxApplication" +for usage information. This macro abstracts out platform-specific entry point +code and is equivalent to the following, see @ref portability-applications for +more information. @code int main(int argc, char** argv) { className app({argc, argv}); diff --git a/src/Magnum/Platform/WindowlessNaClApplication.h b/src/Magnum/Platform/WindowlessNaClApplication.h index c9f181d4b..8b2320850 100644 --- a/src/Magnum/Platform/WindowlessNaClApplication.h +++ b/src/Magnum/Platform/WindowlessNaClApplication.h @@ -133,9 +133,17 @@ class WindowlessNaClApplication: public pp::Instance, public pp::Graphics3DClien /** @brief Moving is not allowed */ WindowlessNaClApplication& operator=(WindowlessNaClApplication&&) = delete; + #ifdef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif /** * @brief Execute application - * @return Value for returning from `main()`. + * @return Value for returning from `main()` + * + * This function is not meant to be called from user code, see + * @ref MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() for usage information. */ virtual int exec() = 0; @@ -199,8 +207,10 @@ namespace Implementation { @param application Application class name See @ref Magnum::Platform::WindowlessNaClApplication "Platform::WindowlessNaClApplication" -and @ref portability-applications for more information. When no other -windowless application header is included this macro is also aliased to +for usage information. This macro abstracts out platform-specific entry point +code (the classic `main()` function cannot be used in NaCl). See +@ref portability-applications for more information. When no other windowless +application header is included this macro is also aliased to `MAGNUM_WINDOWLESSAPPLICATION_MAIN()`. */ /* look at that insane placement of __attribute__. WTF. */ diff --git a/src/Magnum/Platform/XEglApplication.h b/src/Magnum/Platform/XEglApplication.h index 759487d49..067cd8476 100644 --- a/src/Magnum/Platform/XEglApplication.h +++ b/src/Magnum/Platform/XEglApplication.h @@ -92,9 +92,10 @@ class XEglApplication: public AbstractXApplication { @brief Entry point for X/EGL-based applications @param className Class name -Can be used with @ref Magnum::Platform::XEglApplication "Platform::XEglApplication" -subclasses as equivalent to the following code to achieve better portability, -see @ref portability-applications for more information. +See @ref Magnum::Platform::XEglApplication "Platform::XEglApplication" for +usage information. This macro abstracts out platform-specific entry point code +and is equivalent to the following, see @ref portability-applications for more +information. @code int main(int argc, char** argv) { className app({argc, argv}); From 2a53a7094346fd0937a49260556bb91d9a72159f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 17:46:52 +0100 Subject: [PATCH 026/141] package: build XEglApplication on non-desktop ES. --- package/ci/jenkins.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package/ci/jenkins.xml b/package/ci/jenkins.xml index d3f3307a7..963afad27 100644 --- a/package/ci/jenkins.xml +++ b/package/ci/jenkins.xml @@ -97,22 +97,27 @@ fi if [ ${gl} = "desktop" ] ; then desktop_flag=ON + es_flag=OFF windowless_flag=ON elif [ ${gl} = "es2" ] ; then gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=ON" desktop_flag=OFF + es_flag=ON windowless_flag=OFF elif [ ${gl} = "es2desktop" ] ; then gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=ON -DTARGET_DESKTOP_GLES=ON" desktop_flag=OFF + es_flag=OFF windowless_flag=ON elif [ ${gl} = "es3" ] ; then gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=OFF" desktop_flag=OFF + es_flag=ON windowless_flag=OFF elif [ ${gl} = "es3desktop" ] ; then gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=OFF -DTARGET_DESKTOP_GLES=ON" desktop_flag=OFF + es_flag=OFF windowless_flag=ON fi @@ -135,6 +140,7 @@ cmake .. \ -DWITH_GLUTAPPLICATION=ON \ -DWITH_GLXAPPLICATION=ON \ -DWITH_SDL2APPLICATION=ON \ + -DWITH_XEGLAPPLICATION=${es_flag} \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=${desktop_flag} \ -DWITH_TGAIMAGECONVERTER=ON \ From a9bcaf4b89ff2c0b1b0f5be1dfdaca373b6f179e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 17:54:59 +0100 Subject: [PATCH 027/141] Platform: error out when trying to use NaClApplication outside of NaCl. --- src/Magnum/Platform/NaClApplication.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Magnum/Platform/NaClApplication.h b/src/Magnum/Platform/NaClApplication.h index d134c5560..efcb7d80f 100644 --- a/src/Magnum/Platform/NaClApplication.h +++ b/src/Magnum/Platform/NaClApplication.h @@ -48,6 +48,10 @@ namespace pp { class Fullscreen; } +#ifndef CORRADE_TARGET_NACL +#error This header is available only on Google Chrome Native Client +#endif + namespace Magnum { namespace Platform { /** @nosubgrouping From 5cd544b06d9891bb9076d0aee0372be25ec6502f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 17:58:23 +0100 Subject: [PATCH 028/141] Platform: move eglErrorString() helper to separate header. It will be useful also elsewhere. --- src/Magnum/Platform/CMakeLists.txt | 4 +- src/Magnum/Platform/Implementation/Egl.cpp | 54 +++++++++++++++++++ src/Magnum/Platform/Implementation/Egl.h | 36 +++++++++++++ .../Implementation/EglContextHandler.cpp | 40 ++++---------- .../Implementation/EglContextHandler.h | 2 - 5 files changed, 102 insertions(+), 34 deletions(-) create mode 100644 src/Magnum/Platform/Implementation/Egl.cpp create mode 100644 src/Magnum/Platform/Implementation/Egl.h diff --git a/src/Magnum/Platform/CMakeLists.txt b/src/Magnum/Platform/CMakeLists.txt index 1afd6dc0e..a3686d64d 100644 --- a/src/Magnum/Platform/CMakeLists.txt +++ b/src/Magnum/Platform/CMakeLists.txt @@ -171,7 +171,9 @@ if(NEED_EGLCONTEXT) if(NOT EGL_FOUND) message(FATAL_ERROR "EGL library, required by some window contexts, was not found. Set WITH_*EGL*APPLICATION to OFF to skip building them.") endif() - add_library(MagnumEglContextHandler OBJECT Implementation/EglContextHandler.cpp) + add_library(MagnumEglContextHandler OBJECT + Implementation/EglContextHandler.cpp + Implementation/Egl.cpp) # X11 macros are a mess, disable warnings for C-style casts set_target_properties(MagnumEglContextHandler PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") endif() diff --git a/src/Magnum/Platform/Implementation/Egl.cpp b/src/Magnum/Platform/Implementation/Egl.cpp new file mode 100644 index 000000000..35c5fdda1 --- /dev/null +++ b/src/Magnum/Platform/Implementation/Egl.cpp @@ -0,0 +1,54 @@ +/* + 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 "Egl.h" + +namespace Magnum { namespace Platform { namespace Implementation { + +const char* eglErrorString(const EGLint error) { + switch(error) { + #define _error(name) case name: return #name; + _error(EGL_SUCCESS) + _error(EGL_NOT_INITIALIZED) + _error(EGL_BAD_ACCESS) + _error(EGL_BAD_ALLOC) + _error(EGL_BAD_ATTRIBUTE) + _error(EGL_BAD_CONTEXT) + _error(EGL_BAD_CONFIG) + _error(EGL_BAD_CURRENT_SURFACE) + _error(EGL_BAD_DISPLAY) + _error(EGL_BAD_SURFACE) + _error(EGL_BAD_MATCH) + _error(EGL_BAD_PARAMETER) + _error(EGL_BAD_NATIVE_PIXMAP) + _error(EGL_BAD_NATIVE_WINDOW) + _error(EGL_CONTEXT_LOST) + #undef _error + } + + return "EGL_(invalid)"; +} + +}}} diff --git a/src/Magnum/Platform/Implementation/Egl.h b/src/Magnum/Platform/Implementation/Egl.h new file mode 100644 index 000000000..a84e4fe4c --- /dev/null +++ b/src/Magnum/Platform/Implementation/Egl.h @@ -0,0 +1,36 @@ +#ifndef Magnum_Platform_Implementation_Egl_h +#define Magnum_Platform_Implementation_Egl_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 + +namespace Magnum { namespace Platform { namespace Implementation { + +const char* eglErrorString(EGLint error); + +}}} + +#endif diff --git a/src/Magnum/Platform/Implementation/EglContextHandler.cpp b/src/Magnum/Platform/Implementation/EglContextHandler.cpp index 9661d1960..153dd7bad 100644 --- a/src/Magnum/Platform/Implementation/EglContextHandler.cpp +++ b/src/Magnum/Platform/Implementation/EglContextHandler.cpp @@ -32,6 +32,8 @@ #include "Magnum/Context.h" #include "Magnum/Version.h" +#include "Egl.h" + namespace Magnum { namespace Platform { namespace Implementation { EglContextHandler::~EglContextHandler() { @@ -44,7 +46,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) { /* Initialize */ display = eglGetDisplay(nativeDisplay); if(!eglInitialize(display, nullptr, nullptr)) { - Error() << "Cannot initialize EGL:" << errorString(eglGetError()); + Error() << "Cannot initialize EGL:" << Implementation::eglErrorString(eglGetError()); std::exit(1); } @@ -54,7 +56,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) { EGLenum api = EGL_OPENGL_ES_API; #endif if(!eglBindAPI(api)) { - Error() << "Cannot bind EGL API:" << errorString(eglGetError()); + Error() << "Cannot bind EGL API:" << Implementation::eglErrorString(eglGetError()); std::exit(1); } @@ -77,7 +79,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) { }; EGLint configCount; if(!eglChooseConfig(display, attribs, &config, 1, &configCount)) { - Error() << "Cannot get EGL visual config:" << errorString(eglGetError()); + Error() << "Cannot get EGL visual config:" << Implementation::eglErrorString(eglGetError()); std::exit(1); } @@ -89,7 +91,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) { /* Get visual ID */ EGLint visualId; if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) { - Error() << "Cannot get native visual ID:" << errorString(eglGetError()); + Error() << "Cannot get native visual ID:" << Implementation::eglErrorString(eglGetError()); std::exit(1); } @@ -140,40 +142,16 @@ void EglContextHandler::createContext(const AbstractXApplication::Configuration& } #endif - if(!eglCreateContext(display, config, EGL_NO_CONTEXT, attributes)) { - Error() << "Cannot create EGL context:" << errorString(eglGetError()); + if(!(context = eglCreateContext(display, config, EGL_NO_CONTEXT, attributes))) { + Error() << "Cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); std::exit(1); } if(!(surface = eglCreateWindowSurface(display, config, window, nullptr))) { - Error() << "Cannot create window surface:" << errorString(eglGetError()); + Error() << "Cannot create window surface:" << Implementation::eglErrorString(eglGetError()); std::exit(1); } /** @bug Fixme: On desktop OpenGL and Mesa EGL implementation OpenGL version is 1.0, which is wrong */ } -const char* EglContextHandler::errorString(EGLint error) { - switch(error) { - #define _error(name) case name: return #name; - _error(EGL_SUCCESS) - _error(EGL_NOT_INITIALIZED) - _error(EGL_BAD_ACCESS) - _error(EGL_BAD_ALLOC) - _error(EGL_BAD_ATTRIBUTE) - _error(EGL_BAD_CONTEXT) - _error(EGL_BAD_CONFIG) - _error(EGL_BAD_CURRENT_SURFACE) - _error(EGL_BAD_DISPLAY) - _error(EGL_BAD_SURFACE) - _error(EGL_BAD_MATCH) - _error(EGL_BAD_PARAMETER) - _error(EGL_BAD_NATIVE_PIXMAP) - _error(EGL_BAD_NATIVE_WINDOW) - _error(EGL_CONTEXT_LOST) - #undef _error - } - - return {}; -} - }}} diff --git a/src/Magnum/Platform/Implementation/EglContextHandler.h b/src/Magnum/Platform/Implementation/EglContextHandler.h index 2a4ff5ae5..9fba78fd9 100644 --- a/src/Magnum/Platform/Implementation/EglContextHandler.h +++ b/src/Magnum/Platform/Implementation/EglContextHandler.h @@ -71,8 +71,6 @@ class EglContextHandler: public AbstractContextHandler Date: Thu, 27 Feb 2014 18:03:00 +0100 Subject: [PATCH 029/141] Platform: undef even more Xlib nonsense. Do I really need to have everything uniquely prefixed with uncomprehensible names to defend myself from headers that were made by careless people two centuries ago?! Rage level +37. --- src/Magnum/Platform/Implementation/EglContextHandler.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magnum/Platform/Implementation/EglContextHandler.h b/src/Magnum/Platform/Implementation/EglContextHandler.h index 9fba78fd9..3f1dc51d3 100644 --- a/src/Magnum/Platform/Implementation/EglContextHandler.h +++ b/src/Magnum/Platform/Implementation/EglContextHandler.h @@ -31,6 +31,7 @@ #include /* undef Xlib nonsense to avoid conflicts */ #undef None +#undef Complex #include From e3013603f30b904f0726bb5b15a92eb9f01a3a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 20:13:29 +0100 Subject: [PATCH 030/141] modules: updated FindCorrade.cmake from Corrade repository. --- modules/FindCorrade.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake index 5e20c71b5..18ce88964 100644 --- a/modules/FindCorrade.cmake +++ b/modules/FindCorrade.cmake @@ -217,6 +217,11 @@ if(CORRADE_TARGET_UNIX OR CORRADE_TARGET_NACL_GLIBC) set(CORRADE_PLUGINMANAGER_LIBRARIES ${CORRADE_PLUGINMANAGER_LIBRARIES} ${CMAKE_DL_LIBS}) endif() +# AndroidLogStreamBuffer class needs to be linked to log library +if(CORRADE_TARGET_ANDROID) + set(CORRADE_UTILITY_LIBRARIES ${CORRADE_UTILITY_LIBRARIES} log) +endif() + mark_as_advanced(CORRADE_UTILITY_LIBRARY CORRADE_INTERCONNECT_LIBRARY CORRADE_PLUGINMANAGER_LIBRARY From c2dc386dee3949407f70da819c0d9e444d9715db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 20:14:16 +0100 Subject: [PATCH 031/141] modules: populate ${MAGNUM_LIBRARIES} before they are used. MAGNUM_LIBRARIES are used in all Application classes. I don't know when this got broken, but now it is fixed again. --- modules/FindMagnum.cmake | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index e98f5ba44..ec78ddd8b 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -162,12 +162,22 @@ if(NOT _TARGET_DESKTOP_GLES EQUAL -1) set(MAGNUM_TARGET_DESKTOP_GLES 1) endif() +# Dependent libraries and includes +set(MAGNUM_INCLUDE_DIRS ${MAGNUM_INCLUDE_DIR} + ${MAGNUM_INCLUDE_DIR}/MagnumExternal/OpenGL + ${CORRADE_INCLUDE_DIR}) +set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARY} + ${CORRADE_UTILITY_LIBRARIES} + ${CORRADE_PLUGINMANAGER_LIBRARIES}) if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES) find_package(OpenGL REQUIRED) + set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGL_gl_LIBRARY}) elseif(MAGNUM_TARGET_GLES2) find_package(OpenGLES2 REQUIRED) + set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGLES2_LIBRARY}) elseif(MAGNUM_TARGET_GLES3) find_package(OpenGLES3 REQUIRED) + set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGLES3_LIBRARY}) endif() # On Windows and in static builds, *Application libraries need to have @@ -359,21 +369,6 @@ find_package_handle_standard_args(Magnum REQUIRED_VARS MAGNUM_LIBRARY MAGNUM_INCLUDE_DIR HANDLE_COMPONENTS) -# Dependent libraries and includes -set(MAGNUM_INCLUDE_DIRS ${MAGNUM_INCLUDE_DIR} - ${MAGNUM_INCLUDE_DIR}/MagnumExternal/OpenGL - ${CORRADE_INCLUDE_DIR}) -set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARY} - ${CORRADE_UTILITY_LIBRARIES} - ${CORRADE_PLUGINMANAGER_LIBRARIES}) -if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES) - set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGL_gl_LIBRARY}) -elseif(MAGNUM_TARGET_GLES2) - set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGLES2_LIBRARY}) -else() - set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGLES3_LIBRARY}) -endif() - # Installation dirs include(CorradeLibSuffix) set(MAGNUM_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) From c34260d603cc5b9a281aa5e3a6ccbc2ddfe39372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 21:20:03 +0100 Subject: [PATCH 032/141] Platform: even more doc++. --- src/Magnum/Platform/NaClApplication.h | 4 +++- src/Magnum/Platform/Sdl2Application.h | 5 +++-- src/Magnum/Platform/WindowlessGlxApplication.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Magnum/Platform/NaClApplication.h b/src/Magnum/Platform/NaClApplication.h index efcb7d80f..d04899d54 100644 --- a/src/Magnum/Platform/NaClApplication.h +++ b/src/Magnum/Platform/NaClApplication.h @@ -111,7 +111,9 @@ You can then open `MyApplication` through your webserver in Chrome (e.g. ## General usage -In CMake you need to request `%NaClApplication` component, add +For CMake you need to copy `FindOpenGLES2.cmake` from `modules/` directory in +%Magnum source to `modules/` dir in your project (so it is able to find OpenGL +ES). Request `%NaClApplication` component, add `${MAGNUM_NACLAPPLICATION_INCLUDE_DIRS}` to include path and link to `${MAGNUM_NACLAPPLICATION_LIBRARIES}`. If no other application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 60009586b..eb5289388 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -114,8 +114,9 @@ e.g. `http://localhost/emscripten/MyApplication.html`). ## General usage For CMake you need to copy `FindSDL2.cmake` from `modules/` directory in -%Magnum source to `modules/` dir in your project (so it is able to find SDL2), -request `%Sdl2Application` component, add `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` +%Magnum source to `modules/` dir in your project (so it is able to find SDL2). +In case of Emscripten you need also `FindOpenGLES2.cmake`. Request +`%Sdl2Application` component, add `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` to include path and link to `${MAGNUM_SDL2APPLICATION_LIBRARIES}`. If no other application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 024ce2fa7..1269a5914 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -132,7 +132,8 @@ class WindowlessGlxApplication { * @brief Execute application * @return Value for returning from `main()` * - * See @ref MAGNUM_WINDOWLESSAPPLICATION_MAIN() for usage information. + * See @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN() for usage + * information. */ virtual int exec() = 0; From cb8eecce51945d817088966b45fb37f366396d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 21:26:29 +0100 Subject: [PATCH 033/141] Platform: initial version of AndroidApplication. No input events yet. --- CMakeLists.txt | 4 + doc/building.dox | 1 + modules/FindMagnum.cmake | 11 + src/Magnum/Platform/AndroidApplication.cpp | 242 ++++++++++++++ src/Magnum/Platform/AndroidApplication.h | 357 +++++++++++++++++++++ src/Magnum/Platform/CMakeLists.txt | 19 ++ 6 files changed, 634 insertions(+) create mode 100644 src/Magnum/Platform/AndroidApplication.cpp create mode 100644 src/Magnum/Platform/AndroidApplication.h diff --git a/CMakeLists.txt b/CMakeLists.txt index df893bbf9..ee3a229dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,10 @@ if(CORRADE_TARGET_NACL) option(WITH_NACLAPPLICATION "Build NaClApplication library" OFF) cmake_dependent_option(WITH_WINDOWLESSNACLAPPLICATION "Build WindowlessNaClApplication library" OFF "NOT WITH_MAGNUMINFO" ON) +# Android-specific application libraries +elseif(CORRADE_TARGET_ANDROID) + option(WITH_ANDROIDAPPLICATION "Build AndroidApplication library" OFF) + # X11, GLX and EGL-specific application libraries elseif(CORRADE_TARGET_UNIX AND NOT APPLE) option(WITH_GLXAPPLICATION "Build GlxApplication library" OFF) diff --git a/doc/building.dox b/doc/building.dox index 20aabcd21..15516371b 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -185,6 +185,7 @@ None of the @ref Platform "application libraries" is built by default (and you need at least one). Choose the one which suits your requirements and your platform best: +- `WITH_ANDROIDAPPLICATION` - @ref Platform::AndroidApplication "AndroidApplication" - `WITH_GLUTAPPLICATION` - @ref Platform::GlutApplication "GlutApplication" - `WITH_GLXAPPLICATION` - @ref Platform::GlxApplication "GlxApplication" - `WITH_NACLAPPLICATION` - @ref Platform::NaClApplication "NaClApplication" diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index ec78ddd8b..3257507ee 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -253,6 +253,17 @@ foreach(component ${Magnum_FIND_COMPONENTS}) if(${component} MATCHES .+Application) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_SUFFIX Magnum/Platform) + # Android application dependencies + if(${component} STREQUAL AndroidApplication) + find_package(EGL) + if(EGL_FOUND) + set(_MAGNUM_${_COMPONENT}_LIBRARIES android ${EGL_LIBRARY} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) + set(_MAGNUM_${_COMPONENT}_INCLUDE_DIRS ${ANDROID_NATIVE_APP_GLUE_INCLUDE_DIR}) + else() + unset(MAGNUM_${_COMPONENT}_LIBRARY) + endif() + endif() + # GLUT application dependencies if(${component} STREQUAL GlutApplication) find_package(GLUT) diff --git a/src/Magnum/Platform/AndroidApplication.cpp b/src/Magnum/Platform/AndroidApplication.cpp new file mode 100644 index 000000000..33eeecea1 --- /dev/null +++ b/src/Magnum/Platform/AndroidApplication.cpp @@ -0,0 +1,242 @@ +/* + 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 "AndroidApplication.h" + +#include +#include + +#include "Magnum/Context.h" + +#include "Implementation/Egl.h" + +namespace Magnum { namespace Platform { + +/** @todo Delegating constructors when support for GCC 4.6 can be dropped */ + +AndroidApplication::AndroidApplication(const Arguments& arguments, const Configuration& configuration): _state(arguments) { + initialize(); + createContext(configuration); +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +AndroidApplication::AndroidApplication(const Arguments& arguments): _state(arguments) { + initialize(); + createContext(); +} +#endif + +AndroidApplication::AndroidApplication(const Arguments& arguments, std::nullptr_t): _state(arguments) { + initialize(); +} + +AndroidApplication::~AndroidApplication() { + eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(_display, _context); + eglDestroySurface(_display, _surface); + eglTerminate(_display); +} + +struct AndroidApplication::LogOutput { + LogOutput(); + + Utility::AndroidLogStreamBuffer debugBuffer, warningBuffer, errorBuffer; + std::ostream debugStream, warningStream, errorStream; +}; + +AndroidApplication::LogOutput::LogOutput(): + debugBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Info, "magnum"), + warningBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Warning, "magnum"), + errorBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Error, "magnum"), + debugStream(&debugBuffer), warningStream(&warningBuffer), errorStream(&errorBuffer) +{ + Debug::setOutput(&debugStream); + Warning::setOutput(&warningStream); + Error::setOutput(&errorStream); +} + +void AndroidApplication::initialize() { + /* Redirect debug output to Android log */ + _logOutput.reset(new LogOutput); +} + +void AndroidApplication::createContext() { createContext({}); } + +void AndroidApplication::createContext(const Configuration& configuration) { + if(!tryCreateContext(configuration)) std::exit(32); +} + +bool AndroidApplication::tryCreateContext(const Configuration& configuration) { + /* Initialize EGL */ + _display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if(!eglInitialize(_display, nullptr, nullptr)) { + Error() << "Platform::AndroidApplication::tryCreateContext(): cannot initialize EGL:" + << Implementation::eglErrorString(eglGetError()); + return false; + } + + /* Choose config */ + const EGLint configAttributes[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + EGLint configCount; + EGLConfig config; + if(!eglChooseConfig(_display, configAttributes, &config, 1, &configCount)) { + Error() << "Platform::AndroidApplication::tryCreateContext(): cannot choose EGL config:" + << Implementation::eglErrorString(eglGetError()); + return false; + } + + /* Resize native window and match it to the selected format */ + EGLint format; + CORRADE_INTERNAL_ASSERT_OUTPUT(eglGetConfigAttrib(_display, config, EGL_NATIVE_VISUAL_ID, &format)); + ANativeWindow_setBuffersGeometry(_state->window, + configuration.size().isZero() ? 0 : configuration.size().x(), + configuration.size().isZero() ? 0 : configuration.size().y(), format); + + /* Create surface and context */ + if(!(_surface = eglCreateWindowSurface(_display, config, _state->window, nullptr))) { + Error() << "Platform::AndroidApplication::tryCreateContext(): cannot create EGL window surface:" + << Implementation::eglErrorString(eglGetError()); + return false; + } + const EGLint contextAttributes[] = { + #ifdef MAGNUM_TARGET_GLES2 + EGL_CONTEXT_CLIENT_VERSION, 2, + #elif defined(MAGNUM_TARGET_GLES3) + EGL_CONTEXT_CLIENT_VERSION, 3, + #else + #error Android with desktop OpenGL? Wow, that is a new thing. + #endif + EGL_NONE + }; + if(!(_context = eglCreateContext(_display, config, EGL_NO_CONTEXT, contextAttributes))) { + Error() << "Platform::AndroidApplication::tryCreateContext(): cannot create EGL context:" + << Implementation::eglErrorString(eglGetError()); + return false; + } + + /* Make the context current */ + CORRADE_INTERNAL_ASSERT_OUTPUT(eglMakeCurrent(_display, _surface, _surface, _context)); + + _c.reset(new Context); + return true; +} + +void AndroidApplication::swapBuffers() { + eglSwapBuffers(_display, _surface); +} + +void AndroidApplication::viewportEvent(const Vector2i&) {} + +namespace { + struct Data { + Data(std::unique_ptr(*instancer)(const AndroidApplication::Arguments&)): instancer(instancer) {} + + std::unique_ptr(*instancer)(const AndroidApplication::Arguments&); + std::unique_ptr instance; + }; +} + +void AndroidApplication::commandEvent(android_app* state, int32_t cmd) { + Data& data = *static_cast(state->userData); + + switch (cmd) { + case APP_CMD_SAVE_STATE: + /** @todo Make use of this */ + break; + + case APP_CMD_INIT_WINDOW: + /* Create the application */ + if(!data.instance) { + data.instance = data.instancer(state); + data.instance->drawEvent(); + } + break; + + case APP_CMD_TERM_WINDOW: + /* Destroy the application */ + data.instance.reset(); + break; + + case APP_CMD_GAINED_FOCUS: + case APP_CMD_LOST_FOCUS: + /** @todo Make use of these */ + break; + } +} + +std::int32_t AndroidApplication::inputEvent(android_app*, AInputEvent*) { + /** @todo Implement input events */ + return 0; +} + +void AndroidApplication::exec(android_app* state, std::unique_ptr(*instancer)(const Arguments&)) { + state->onAppCmd = commandEvent; + state->onInputEvent = inputEvent; + + /* Make sure the glue isn't stripped. WHY WHYYY CAN'T THIS BE DONE SOME + SANE WAY WHYY */ + app_dummy(); + + /** @todo Make use of saved state */ + Data data{instancer}; + state->userData = &data; + + for(;;) { + /* Read all pending events. Block and wait for them only if the app + doesn't want to redraw immediately WHY THIS GODDAMN THING DOESNT + HAVE SOMETHING LIKE WAIT FOR EVENT SO I NEED TO TANGLE THIS TANGLED + MESS OF HELL */ + int ident, events; + android_poll_source* source; + while((ident = ALooper_pollAll( + data.instance && (data.instance->_flags & Flag::Redraw) ? 0 : -1, + nullptr, &events, reinterpret_cast(&source))) >= 0) + { + /* Process this event OH SIR MAY MY POOR EXISTENCE CALL THIS + FUNCTION FOR YOU IF YOU DON'T MIND? */ + if(source) source->process(state, source); + + /* Exit WHY THIS HAS TO BE HANDLED HERE WHILE EVERY OTHER THING + IS HANDLED THROUGH CALLBACK GODDAMMIT */ + if(state->destroyRequested != 0) return; + } + + /* Redraw the app if it wants to be redrawn. Frame limiting is done by + Android itself */ + if(data.instance && (data.instance->_flags & Flag::Redraw)) + data.instance->drawEvent(); + } + + state->userData = nullptr; +} + +}} diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h new file mode 100644 index 000000000..305f09481 --- /dev/null +++ b/src/Magnum/Platform/AndroidApplication.h @@ -0,0 +1,357 @@ +#ifndef Magnum_Platform_AndroidApplication_h +#define Magnum_Platform_AndroidApplication_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. +*/ + +/** @file + * @brief Class @ref Magnum::Platform::AndroidApplication + */ + +#include +#include +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Math/Vector2.h" +#include "Magnum/Platform/Platform.h" + +#ifndef CORRADE_TARGET_ANDROID +#error This file is available only on Android +#endif + +namespace Magnum { namespace Platform { + +/** @nosubgrouping +@brief Android application + +Application running in Android. + +This application library is available only in +@ref CORRADE_TARGET_ANDROID "Android", see respective sections +in @ref building-corrade-cross-android "Corrade's" and @ref building-cross-android "Magnum's" +building documentation. It is built if `WITH_ANDROIDAPPLICATION` is enabled in +CMake. + +## Bootstrap application + +Fully contained base application using @ref GlutApplication for desktop build +and @ref AndroidApplication for Android build along with full Android packaging +stuff and CMake setup is available in `base-android` branch of +[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository, +download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-android.tar.gz) +or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-android.zip) file. +After extracting the downloaded archive, you can do the desktop build in the +same way as with @ref GlutApplication. For the Android build you also +need to put the contents of toolchains repository from https://github.com/mosra/toolchains +in `toolchains/` subdirectory. Don't forget to adapt `ANDROID_NDK_ROOT` in +`toolchains/generic/Android-*.cmake` to path where NDK is installed. Default is +`/opt/android-ndk`. Adapt also `ANDROID_SYSROOT` to your preferred API level. +You might also need to update `ANDROID_TOOLCHAIN_PREFIX` and +`ANDROID_TOOLCHAIN_ROOT` to fit your system. + +First you need to update Android project files with the following command. It +will create `build.xml` file for Ant and a bunch of other files. You need to +specify the target for which you will build in the `-t` parameter. List of all +targets can be obtained by calling `android list target`. + + android update project -p . -t "android-19" + +Then create build directories for ARM and x86 and run `cmake` and build command +in them. The toolchains need access to the platform file, so be sure to +properly set **absolute** path to `toolchains/modules/` directory containing +`Platform/Android.cmake`. + + mkdir build-android-arm && cd build-android-arm + cmake .. \ + -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Android-ARM.cmake" + cmake --build . + + mkdir build-android-x86 && cd build-android-x86 + cmake .. \ + -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ + -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Android-x86.cmake" + cmake --build . + +The compiled binaries will be put into `lib/armeabi-v7a` and `lib/x86`. You can +then build the APK package simply by running `ant`. The resulting APK package +can be then installed directly on the device or emulator using `adb install`. + + ant debug + adb install bin/NativeActivity-debug.apk + +## General usage + +For CMake you need to copy `FindEGL.cmake` and `FindOpenGLES2.cmake` (or +`FindOpenGLES3.cmake`) from `modules/` directory in %Magnum source to `modules/` +dir in your project (so it is able to find EGL and OpenGL ES libraries). +Request `%AndroidApplication` component, add +`${MAGNUM_ANDROIDAPPLICATION_INCLUDE_DIRS}` to include path and link to +`${MAGNUM_ANDROIDAPPLICATION_LIBRARIES}`. If no other application is requested, +you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and +`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See +@ref building and @ref cmake for more information. Note that unlike on other +platforms you need to create *shared library* instead of executable. The +resulting binary then needs to be copied to `lib/armeabi-v7a` and `lib/x86`, +you can do that automatically in CMake using the following commands: + + file(MAKE_DIRECTORY "${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}") + +In C++ code you need to implement at least @ref drawEvent() to be able to draw +on the screen. The subclass must be then made accessible from JNI using +@ref MAGNUM_ANDROIDAPPLICATION_MAIN() macro. See @ref platform for more +information. +@code +class MyApplication: public Platform::AndroidApplication { + // implement required methods... +}; +MAGNUM_ANDROIDAPPLICATION_MAIN(MyApplication) +@endcode + +If no other application header is included, this class is also aliased to +`Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()` +to simplify porting. + +### Android packaging stuff + +The application needs at least the `AndroidManifest.xml` with the following +contents: + + + + + + + + + + + + + + + + +Replace `{{name}}` with the actual application name and `{{application}}` with +name of the binary file (without extension). If you plan to use OpenGL ES, set +`android:glEsVersion` to `0x00030000`. + +## Redirecting output to Android log buffer + +The application by default redirects @ref Corrade::Utility::Debug "Debug", +@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error" +output to Android log buffer with tag `"magnum"`, which can be then accessed +through `logcat` utility. See also @ref Corrade::Utility::AndroidLogStreamBuffer +for more information. +*/ +class AndroidApplication { + public: + /** @brief Application arguments */ + typedef android_app* Arguments; + + class Configuration; + + /** + * @brief Execute the application + * + * See @ref MAGNUM_ANDROIDAPPLICATION_MAIN() for usage information. + */ + static void exec(android_app* state, std::unique_ptr(*instancer)(const Arguments&)); + + #ifndef DOXYGEN_GENERATING_OUTPUT + template static std::unique_ptr instancer(const Arguments& arguments) { + return std::unique_ptr{new T{arguments}}; + } + #endif + + /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ + #ifdef DOXYGEN_GENERATING_OUTPUT + explicit AndroidApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); + #else + /* To avoid "invalid use of incomplete type" */ + explicit AndroidApplication(const Arguments& arguments, const Configuration& configuration); + explicit AndroidApplication(const Arguments& arguments); + #endif + + /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ + explicit AndroidApplication(const Arguments& arguments, std::nullptr_t); + + /** @brief Copying is not allowed */ + AndroidApplication(const AndroidApplication&) = delete; + + /** @brief Moving is not allowed */ + AndroidApplication(AndroidApplication&&) = delete; + + virtual ~AndroidApplication(); + + /** @brief Copying is not allowed */ + AndroidApplication& operator=(const AndroidApplication&) = delete; + + /** @brief Moving is not allowed */ + AndroidApplication& operator=(AndroidApplication&&) = delete; + + protected: + /** @copydoc Sdl2Application::createContext() */ + #ifdef DOXYGEN_GENERATING_OUTPUT + void createContext(const Configuration& configuration = Configuration()); + #else + /* To avoid "invalid use of incomplete type" */ + void createContext(const Configuration& configuration); + void createContext(); + #endif + + /** @copydoc Sdl2Application::tryCreateContext() */ + bool tryCreateContext(const Configuration& configuration); + + /** @{ @name Screen handling */ + + /** @copydoc Sdl2Application::swapBuffers() */ + void swapBuffers(); + + /** @copydoc Sdl2Application::redraw() */ + void redraw() { _flags |= Flag::Redraw; } + + #ifdef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + /** @copydoc Sdl2Application::viewportEvent() */ + virtual void viewportEvent(const Vector2i& size); + + /** @copydoc Sdl2Application::drawEvent() */ + virtual void drawEvent() = 0; + + /*@}*/ + + private: + struct LogOutput; + + enum class Flag: UnsignedByte { + Redraw = 1 << 1 + }; + typedef Containers::EnumSet Flags; + + static void commandEvent(android_app* app, std::int32_t cmd); + static std::int32_t inputEvent(android_app* app, AInputEvent* event); + + void initialize(); + + android_app* const _state; + Flags _flags; + + EGLDisplay _display; + EGLSurface _surface; + EGLContext _context; + + std::unique_ptr _c; + std::unique_ptr _logOutput; + + CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) +}; + +CORRADE_ENUMSET_OPERATORS(AndroidApplication::Flags) + +/** +@brief %Configuration + +Double-buffered RGBA canvas with depth and stencil buffers. +@see @ref AndroidApplication(), @ref createContext(), @ref tryCreateContext() +*/ +class AndroidApplication::Configuration { + public: + constexpr /*implicit*/ Configuration() {} + + /** + * @brief Set window title + * @return Reference to self (for method chaining) + * + * @note This function does nothing and is included only for + * compatibility with other toolkits. You need to set the title + * separately in the XML file. + */ + template Configuration& setTitle(const T&) { return *this; } + + /** @brief Window size */ + Vector2i size() const { return _size; } + + /** + * @brief Set window size + * @return Reference to self (for method chaining) + * + * Default is `{0, 0}`, which means that the size of the physical + * window will be used. If set to different value than the physical + * size, the surface will be scaled. + */ + Configuration& setSize(const Vector2i& size) { + _size = size; + return *this; + } + + /** + * @brief Set context version + * + * @note This function does nothing and is included only for + * compatibility with other toolkits. @ref Version::GLES200 or + * @ref Version::GLES300 is used based on engine compile-time + * settings. + */ + Configuration& setVersion(Version) { return *this; } + + private: + Vector2i _size; +}; + +/** @hideinitializer +@brief Entry point for Android applications +@param className Class name + +See @ref Magnum::Platform::AndroidApplication "Platform::AndroidApplication" +for usage information. This macro abstracts out platform-specific entry point +code (the classic `main()` function cannot be used in Android). See +@ref portability-applications for more information. When no other application +header is included this macro is also aliased to `MAGNUM_APPLICATION_MAIN()`. +*/ +#define MAGNUM_ANDROIDAPPLICATION_MAIN(className) \ + void android_main(android_app* state) { \ + Magnum::Platform::AndroidApplication::exec(state, \ + Magnum::Platform::AndroidApplication::instancer); \ + } + +#ifndef DOXYGEN_GENERATING_OUTPUT +#ifndef MAGNUM_APPLICATION_MAIN +typedef AndroidApplication Application; +typedef BasicScreen Screen; +typedef BasicScreenedApplication ScreenedApplication; +#define MAGNUM_APPLICATION_MAIN(className) MAGNUM_ANDROIDAPPLICATION_MAIN(className) +#else +#undef MAGNUM_APPLICATION_MAIN +#endif +#endif + +}} + +#endif diff --git a/src/Magnum/Platform/CMakeLists.txt b/src/Magnum/Platform/CMakeLists.txt index a3686d64d..320cafdc1 100644 --- a/src/Magnum/Platform/CMakeLists.txt +++ b/src/Magnum/Platform/CMakeLists.txt @@ -32,6 +32,25 @@ set(Platform_HEADERS install(FILES ${Platform_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) +# Android application +if(WITH_ANDROIDAPPLICATION) + if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL Android) + message(FATAL_ERROR "AndroidApplication is available only when targeting Android. Set WITH_ANDROIDAPPLICATION to OFF to skip building it.") + endif() + + include_directories(${ANDROID_NATIVE_APP_GLUE_INCLUDE_DIR}) + + add_library(MagnumAndroidApplication STATIC + AndroidApplication.cpp + Implementation/Egl.cpp + ${ANDROID_NATIVE_APP_GLUE_SRC}) + install(FILES AndroidApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) + install(TARGETS MagnumAndroidApplication + RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} + LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} + ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +endif() + # GLUT application if(WITH_GLUTAPPLICATION) find_package(GLUT) From fe34fe84a3b89017ff16e1884b08675a3d4e77e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 21:27:52 +0100 Subject: [PATCH 034/141] package: build AndroidApplication in development PKGBUILDs. --- package/archlinux/PKGBUILD-android-arm | 3 ++- package/archlinux/PKGBUILD-android-x86 | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package/archlinux/PKGBUILD-android-arm b/package/archlinux/PKGBUILD-android-arm index ddbacac71..7ed7104e8 100644 --- a/package/archlinux/PKGBUILD-android-arm +++ b/package/archlinux/PKGBUILD-android-arm @@ -30,7 +30,8 @@ build() { -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-arm/usr \ -DWITH_MAGNUMFONT=ON \ -DWITH_TGAIMAGECONVERTER=ON \ - -DWITH_TGAIMPORTER=ON + -DWITH_TGAIMPORTER=ON \ + -DWITH_ANDROIDAPPLICATION=ON ninja } diff --git a/package/archlinux/PKGBUILD-android-x86 b/package/archlinux/PKGBUILD-android-x86 index 39f31b54f..4be7a2558 100644 --- a/package/archlinux/PKGBUILD-android-x86 +++ b/package/archlinux/PKGBUILD-android-x86 @@ -30,7 +30,8 @@ build() { -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-x86/usr \ -DWITH_MAGNUMFONT=ON \ -DWITH_TGAIMAGECONVERTER=ON \ - -DWITH_TGAIMPORTER=ON + -DWITH_TGAIMPORTER=ON \ + -DWITH_ANDROIDAPPLICATION=ON ninja } From 3be68f8f73a3113bf71376c4bb97a2e59c556886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 21:27:27 +0100 Subject: [PATCH 035/141] Mention minimal required Android version. We need 2.3 for native_app_glue. --- README.md | 2 +- doc/mainpage.dox | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 29b7b2af9..68cfeae81 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Platforms: GLUT or SDL2 toolkit) * **Windows** (through GLUT or SDL2 toolkit) * **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) -* **Android** +* **Android** 2.3 (API Level 9) and higher * **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), both `newlib` and `glibc` toolchains are supported) * **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki)) diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 2cbe5a96e..920ad37cb 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -78,7 +78,7 @@ Platforms: GLUT or SDL2 toolkit) - **Windows** (through GLUT or SDL2 toolkit) - **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) -- **Android** +- **Android** 2.3 (API Level 9) and higher - **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), both `newlib` and `glibc` toolchains are supported) - **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki)) From 26a2d7e1ab715956e8f5bd3a3925d005e86f1a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 27 Feb 2014 21:35:04 +0100 Subject: [PATCH 036/141] Platform: be consistent with default application names. --- src/Magnum/Platform/AndroidApplication.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 305f09481..31ded2747 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -144,8 +144,8 @@ contents: - - + + @@ -155,8 +155,8 @@ contents: -Replace `{{name}}` with the actual application name and `{{application}}` with -name of the binary file (without extension). If you plan to use OpenGL ES, set +Modify `android:label` to your liking and replace `{{application}}` with name +of the binary file (without extension). If you plan to use OpenGL ES, set `android:glEsVersion` to `0x00030000`. ## Redirecting output to Android log buffer From 822acd3b18630d733bd34a1535d5fa1dbd8318be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Feb 2014 14:21:37 +0100 Subject: [PATCH 037/141] Platform: minor documentation updates for AndroidApplication. I'm still learning the way around this. --- src/Magnum/Platform/AndroidApplication.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 31ded2747..e012630f1 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -141,7 +141,7 @@ The application needs at least the `AndroidManifest.xml` with the following contents: - + @@ -155,9 +155,11 @@ contents: -Modify `android:label` to your liking and replace `{{application}}` with name -of the binary file (without extension). If you plan to use OpenGL ES, set -`android:glEsVersion` to `0x00030000`. +Modify `android:label` to your liking, set unique `package` name and replace +`{{application}}` with name of the binary file (without extension). If you plan +to use OpenGL ES, set `android:glEsVersion` to `0x00030000`. The resulting APK +file will be named `NativeActivity.apk` by default, you can change that by +editing first line of the generated `build.xml` file. ## Redirecting output to Android log buffer @@ -291,7 +293,7 @@ class AndroidApplication::Configuration { * * @note This function does nothing and is included only for * compatibility with other toolkits. You need to set the title - * separately in the XML file. + * separately in the `AndroidManifest.xml` file. */ template Configuration& setTitle(const T&) { return *this; } From df06a8243004423925a60c09ea015116fff45fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Feb 2014 14:59:49 +0100 Subject: [PATCH 038/141] Android: define GL_ES in GLSL if not defined. My emulator doesn't define that, causing all stock shaders to fail on compilation. --- .../Shaders/Implementation/CreateCompatibilityShader.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.cpp b/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.cpp index 1377e6976..04accbfa1 100644 --- a/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.cpp +++ b/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.cpp @@ -44,6 +44,13 @@ Shader createCompatibilityShader(const Version version, const Shader::Type type) shader.addSource("#define DISABLE_GL_ARB_explicit_uniform_location\n"); #endif + /* My Android emulator (running on NVidia) doesn't define GL_ES + preprocessor macro, thus *all* the stock shaders fail to compile */ + /** @todo remove this when Android emulator is sane */ + #ifdef CORRADE_TARGET_ANDROID + shader.addSource("#ifndef GL_ES\n#define GL_ES 1\n#endif\n"); + #endif + shader.addSource(Utility::Resource("MagnumShaders").get("compatibility.glsl")); return shader; } From 9527d39ad3afd662f14d7f1febf8dab791992db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Mar 2014 00:32:30 +0100 Subject: [PATCH 039/141] Added Context::extensionStrings(). Returns list of _all_ extensions reported by the driver, even those that are not supported in Magnum and also those that are marked as disabled due to driver bugs. Usable mostly when doing fresh port to new platform to discover possible new features. The actual implementation was part of Context constructor (and now this function is called instead). It is rather ugly because we need to take care of both GL 2.1 and GL 3.0 (and also ES2 and ES3). --- src/Magnum/Context.cpp | 77 +++++++++++++++++++++--------------------- src/Magnum/Context.h | 13 +++++++ 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index ca70e810a..7055aa9c3 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -409,46 +409,15 @@ Context::Context() { futureExtensions.insert({extension._string, extension}); #endif - /* Check for presence of extensions in future versions */ - #ifndef MAGNUM_TARGET_GLES2 - GLint extensionCount = 0; - glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); - #ifndef MAGNUM_TARGET_GLES3 - if(extensionCount || isVersionSupported(Version::GL300)) - #endif - { - _supportedExtensions.reserve(extensionCount); - for(GLint i = 0; i != extensionCount; ++i) { - const std::string extension(reinterpret_cast(glGetStringi(GL_EXTENSIONS, i))); - auto found = futureExtensions.find(extension); - if(found != futureExtensions.end()) { - _supportedExtensions.push_back(found->second); - extensionStatus.set(found->second._index); - } + /* Check for presence of future and vendor extensions */ + const std::vector extensions = extensionStrings(); + for(const std::string& extension: extensions) { + const auto found = futureExtensions.find(extension); + if(found != futureExtensions.end()) { + _supportedExtensions.push_back(found->second); + extensionStatus.set(found->second._index); } } - #ifndef MAGNUM_TARGET_GLES3 - else - #endif - #endif - - #ifndef MAGNUM_TARGET_GLES3 - /* OpenGL 2.1 / OpenGL ES 2.0 doesn't have glGetStringi() */ - { - /* Don't crash when glGetString() returns nullptr */ - const char* e = reinterpret_cast(glGetString(GL_EXTENSIONS)); - if(e) { - std::vector extensions = Utility::String::split(e, ' '); - for(const std::string& extension: extensions) { - auto found = futureExtensions.find(extension); - if(found != futureExtensions.end()) { - _supportedExtensions.push_back(found->second); - extensionStatus.set(found->second._index); - } - } - } - } - #endif /* Reset minimal required version to Version::None for whole array */ for(auto& i: _extensionRequiredVersion) i = Version::None; @@ -501,6 +470,38 @@ std::vector Context::shadingLanguageVersionStrings() const { #endif } +std::vector Context::extensionStrings() const { + std::vector extensions; + + #ifndef MAGNUM_TARGET_GLES2 + GLint extensionCount = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); + #ifndef MAGNUM_TARGET_GLES3 + if(extensionCount || isVersionSupported(Version::GL300)) + #endif + { + extensions.reserve(extensionCount); + for(GLint i = 0; i != extensionCount; ++i) + extensions.push_back(reinterpret_cast(glGetStringi(GL_EXTENSIONS, i))); + } + #ifndef MAGNUM_TARGET_GLES3 + else + #endif + #endif + + #ifndef MAGNUM_TARGET_GLES3 + /* OpenGL 2.1 / OpenGL ES 2.0 doesn't have glGetStringi() */ + { + /* Don't crash when glGetString() returns nullptr (i.e. don't trust the + old implementations) */ + const char* e = reinterpret_cast(glGetString(GL_EXTENSIONS)); + if(e) extensions = Utility::String::splitWithoutEmptyParts(e, ' '); + } + #endif + + return extensions; +} + Version Context::supportedVersion(std::initializer_list versions) const { for(auto version: versions) if(isVersionSupported(version)) return version; diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index dab32ace8..7ddcc5291 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -233,6 +233,19 @@ class MAGNUM_EXPORT Context { */ std::vector shadingLanguageVersionStrings() const; + /** + * @brief Extension strings + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. Note that this function returns list of all extensions + * reported by the driver (even those not supported by %Magnum), see + * @ref supportedExtensions(), @ref Extension::extensions() or + * @ref isExtensionSupported() for alternatives. + * @see @fn_gl{Get} with @def_gl{NUM_EXTENSIONS}, @fn_gl{GetString} + * with @def_gl{EXTENSIONS} + */ + std::vector extensionStrings() const; + /** @brief Context flags */ Flags flags() const { return _flags; } From 3e7469c62fa926bc1d467e15df1f868266a3a78d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Mar 2014 00:36:40 +0100 Subject: [PATCH 040/141] Platform: doc++. --- src/Magnum/Platform/AndroidApplication.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index e012630f1..b887dbae3 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -158,8 +158,9 @@ contents: Modify `android:label` to your liking, set unique `package` name and replace `{{application}}` with name of the binary file (without extension). If you plan to use OpenGL ES, set `android:glEsVersion` to `0x00030000`. The resulting APK -file will be named `NativeActivity.apk` by default, you can change that by -editing first line of the generated `build.xml` file. +file will be named `NativeActivity.apk` by default, you can change that either +by passing `-n` parameter to `android update project` or later by editing first +line of the generated `build.xml` file. ## Redirecting output to Android log buffer From c5f99aade05ee192eed43b58d539f15c5b4ed852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Mar 2014 00:38:31 +0100 Subject: [PATCH 041/141] Platform: be less greedy in bit flags. --- src/Magnum/Platform/AndroidApplication.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index b887dbae3..5ba847a3d 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -254,7 +254,7 @@ class AndroidApplication { struct LogOutput; enum class Flag: UnsignedByte { - Redraw = 1 << 1 + Redraw = 1 << 0 }; typedef Containers::EnumSet Flags; From d70b7048832920e77ff47e8788fcad2e04e913fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Mar 2014 00:39:20 +0100 Subject: [PATCH 042/141] Platform: consistent naming. --- src/Magnum/Platform/AndroidApplication.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 5ba847a3d..192925ca5 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -258,8 +258,8 @@ class AndroidApplication { }; typedef Containers::EnumSet Flags; - static void commandEvent(android_app* app, std::int32_t cmd); - static std::int32_t inputEvent(android_app* app, AInputEvent* event); + static void commandEvent(android_app* state, std::int32_t cmd); + static std::int32_t inputEvent(android_app* state, AInputEvent* event); void initialize(); From 7b065d5aa6448e91d79161cd0a44289bfd1f6e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Mar 2014 00:40:50 +0100 Subject: [PATCH 043/141] Platform: initial support for touch/mouse events in AndroidApplication. The API now mimics desktop (mouse), might be changed in the future to properly support multitouch etc. features. --- src/Magnum/Platform/AndroidApplication.cpp | 28 +++- src/Magnum/Platform/AndroidApplication.h | 180 +++++++++++++++++++++ 2 files changed, 206 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Platform/AndroidApplication.cpp b/src/Magnum/Platform/AndroidApplication.cpp index 33eeecea1..436b02da1 100644 --- a/src/Magnum/Platform/AndroidApplication.cpp +++ b/src/Magnum/Platform/AndroidApplication.cpp @@ -155,6 +155,9 @@ void AndroidApplication::swapBuffers() { } void AndroidApplication::viewportEvent(const Vector2i&) {} +void AndroidApplication::mousePressEvent(MouseEvent&) {} +void AndroidApplication::mouseReleaseEvent(MouseEvent&) {} +void AndroidApplication::mouseMoveEvent(MouseMoveEvent&) {} namespace { struct Data { @@ -193,8 +196,29 @@ void AndroidApplication::commandEvent(android_app* state, int32_t cmd) { } } -std::int32_t AndroidApplication::inputEvent(android_app*, AInputEvent*) { - /** @todo Implement input events */ +std::int32_t AndroidApplication::inputEvent(android_app* state, AInputEvent* event) { + CORRADE_INTERNAL_ASSERT(static_cast(state->userData)->instance); + AndroidApplication& app = *static_cast(state->userData)->instance; + if(AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { + const std::int32_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; + switch(action) { + case AMOTION_EVENT_ACTION_DOWN: + case AMOTION_EVENT_ACTION_UP: { + MouseEvent e(event); + action == AMOTION_EVENT_ACTION_DOWN ? app.mousePressEvent(e) : app.mouseReleaseEvent(e); + return e.isAccepted() ? 1 : 0; + } + + case AMOTION_EVENT_ACTION_MOVE: { + MouseMoveEvent e(event); + app.mouseMoveEvent(e); + return e.isAccepted() ? 1 : 0; + } + } + + /** @todo Implement also other input events */ + } + return 0; } diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 192925ca5..c4b7975e6 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -41,6 +41,9 @@ #error This file is available only on Android #endif +/* Undef Xlib nonsense which might get pulled in by EGL */ +#undef None + namespace Magnum { namespace Platform { /** @nosubgrouping @@ -176,6 +179,9 @@ class AndroidApplication { typedef android_app* Arguments; class Configuration; + class InputEvent; + class MouseEvent; + class MouseMoveEvent; /** * @brief Execute the application @@ -250,6 +256,38 @@ class AndroidApplication { /*@}*/ + /** @{ @name Mouse handling */ + + #ifdef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + /** + * @brief Mouse press event + * + * Called when mouse button is pressed. Default implementation does + * nothing. + */ + virtual void mousePressEvent(MouseEvent& event); + + /** + * @brief Mouse release event + * + * Called when mouse button is released. Default implementation does + * nothing. + */ + virtual void mouseReleaseEvent(MouseEvent& event); + + /** + * @brief Mouse move event + * + * Called when mouse is moved. Default implementation does nothing. + */ + virtual void mouseMoveEvent(MouseMoveEvent& event); + + /*@}*/ + private: struct LogOutput; @@ -328,6 +366,148 @@ class AndroidApplication::Configuration { Vector2i _size; }; +/** +@brief Base for input events + +@see @ref MouseEvent, @ref MouseMoveEvent, @ref mousePressEvent(), + @ref mouseReleaseEvent(), @ref mouseMoveEvent() +*/ +class AndroidApplication::InputEvent { + public: + /** @brief Copying is not allowed */ + InputEvent(const InputEvent&) = delete; + + /** @brief Moving is not allowed */ + InputEvent(InputEvent&&) = delete; + + /** @brief Copying is not allowed */ + InputEvent& operator=(const InputEvent&) = delete; + + /** @brief Moving is not allowed */ + InputEvent& operator=(InputEvent&&) = delete; + + /** + * @brief Set event as accepted + * + * If the event is ignored (i.e., not set as accepted), it will be + * propagated elsewhere, for example to the Android system or to + * another screen when using @ref BasicScreenedApplication "ScreenedApplication". + * By default is each event ignored and thus propagated. + */ + void setAccepted(bool accepted = true) { _accepted = accepted; } + + /** @brief Whether the event is accepted */ + bool isAccepted() const { return _accepted; } + + #ifndef DOXYGEN_GENERATING_OUTPUT + protected: + explicit InputEvent(AInputEvent* event): _event(event), _accepted(false) {} + + ~InputEvent() = default; + + AInputEvent* _event; + #endif + + private: + bool _accepted; +}; + +/** +@brief Mouse event + +@see @ref MouseMoveEvent, @ref mousePressEvent(), @ref mouseReleaseEvent() +*/ +class AndroidApplication::MouseEvent: public InputEvent { + friend class AndroidApplication; + + public: + /** + * @brief Mouse button + * + * @see @ref button() + */ + enum class Button: std::int32_t { + /** No button was pressed (touch or stylus event) */ + None = 0, + + /** + * Left mouse button. Note that this button is not set if only + * touch or stylus event occured. + */ + Left = AMOTION_EVENT_BUTTON_PRIMARY, + + /** Middle mouse button or second stylus button */ + Middle = AMOTION_EVENT_BUTTON_TERTIARY, + + /** Right mouse button or first stylus button */ + Right = AMOTION_EVENT_BUTTON_SECONDARY + }; + + /** @brief Button */ + Button button() { return Button(AMotionEvent_getButtonState(_event)); } + + /** @brief Position */ + Vector2i position() { + return {Int(AMotionEvent_getX(_event, 0)), + Int(AMotionEvent_getY(_event, 0))}; + } + + private: + MouseEvent(AInputEvent* event): InputEvent(event) {} +}; + +/** +@brief Mouse move event + +@see @ref MouseEvent, @ref mouseMoveEvent() +*/ +class AndroidApplication::MouseMoveEvent: public InputEvent { + friend class AndroidApplication; + + public: + /** + * @brief Mouse button + * + * @see @ref button() + */ + enum class Button: std::int32_t { + /** + * Left mouse button. Note that this button is not set if only + * touch or stylus event occured. + */ + Left = AMOTION_EVENT_BUTTON_PRIMARY, + + /** Middle mouse button or second stylus button */ + Middle = AMOTION_EVENT_BUTTON_TERTIARY, + + /** Right mouse button or first stylus button */ + Right = AMOTION_EVENT_BUTTON_SECONDARY + }; + + /** + * @brief Set of mouse buttons + * + * @see @ref buttons() + */ + typedef Containers::EnumSet Buttons; + + /** @brief Position */ + Vector2i position() const { + return {Int(AMotionEvent_getX(_event, 0)), + Int(AMotionEvent_getY(_event, 0))}; + } + + /** @brief Mouse buttons */ + Buttons buttons() const { + return Button(AMotionEvent_getButtonState(_event)); + } + + private: + MouseMoveEvent(AInputEvent* event): InputEvent(event) {} +}; + +CORRADE_ENUMSET_OPERATORS(AndroidApplication::MouseMoveEvent::Buttons) + /** @hideinitializer @brief Entry point for Android applications @param className Class name From b9b7262ebabc32087c9ae00428552dde27ef8692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Mar 2014 00:42:28 +0100 Subject: [PATCH 044/141] GLSL ES 3.0 requires `es` in version directive. --- src/Magnum/Shader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Shader.cpp b/src/Magnum/Shader.cpp index fa93c2958..73ad186e4 100644 --- a/src/Magnum/Shader.cpp +++ b/src/Magnum/Shader.cpp @@ -555,7 +555,7 @@ Shader::Shader(const Version version, const Type type): _type(type), _id(0) { case Version::GL440: _sources.push_back("#version 440\n"); return; #else case Version::GLES200: _sources.push_back("#version 100\n"); return; - case Version::GLES300: _sources.push_back("#version 300\n"); return; + case Version::GLES300: _sources.push_back("#version 300 es\n"); return; #endif /* The user is responsible for (not) adding #version directive */ From 733de78b3437058ddd5ae2f2859ea7fa9dfd55bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 1 Mar 2014 02:16:02 +0100 Subject: [PATCH 045/141] Platform: fix AndroidApplication for Android < 4.0. --- src/Magnum/Platform/AndroidApplication.h | 64 ++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index c4b7975e6..c650f517c 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -433,18 +433,46 @@ class AndroidApplication::MouseEvent: public InputEvent { /** * Left mouse button. Note that this button is not set if only * touch or stylus event occured. + * @attention Available since Android 4.0 (API level 14), not + * detectable in earlier versions. */ + #if __ANDROID_API__ >= 14 Left = AMOTION_EVENT_BUTTON_PRIMARY, + #else + Left = 1 << 0, + #endif - /** Middle mouse button or second stylus button */ + /** + * Middle mouse button or second stylus button + * @attention Available since Android 4.0 (API level 14), not + * detectable in earlier versions. + */ + #if __ANDROID_API__ >= 14 Middle = AMOTION_EVENT_BUTTON_TERTIARY, + #else + Middle = 1 << 1, + #endif - /** Right mouse button or first stylus button */ + /** + * Right mouse button or first stylus button + * @attention Available since Android 4.0 (API level 14), not + * detectable in earlier versions. + */ + #if __ANDROID_API__ >= 14 Right = AMOTION_EVENT_BUTTON_SECONDARY + #else + Right = 1 << 2 + #endif }; /** @brief Button */ - Button button() { return Button(AMotionEvent_getButtonState(_event)); } + Button button() { + #if __ANDROID_API__ >= 14 + return Button(AMotionEvent_getButtonState(_event)); + #else + return Button::None; + #endif + } /** @brief Position */ Vector2i position() { @@ -474,14 +502,36 @@ class AndroidApplication::MouseMoveEvent: public InputEvent { /** * Left mouse button. Note that this button is not set if only * touch or stylus event occured. + * @attention Available since Android 4.0 (API level 14), not + * detectable in earlier versions. */ + #if __ANDROID_API__ >= 14 Left = AMOTION_EVENT_BUTTON_PRIMARY, + #else + Left = 1 << 0, + #endif - /** Middle mouse button or second stylus button */ + /** + * Middle mouse button or second stylus button + * @attention Available since Android 4.0 (API level 14), not + * detectable in earlier versions. + */ + #if __ANDROID_API__ >= 14 Middle = AMOTION_EVENT_BUTTON_TERTIARY, + #else + Middle = 1 << 1, + #endif - /** Right mouse button or first stylus button */ + /** + * Right mouse button or first stylus button + * @attention Available since Android 4.0 (API level 14), not + * detectable in earlier versions. + */ + #if __ANDROID_API__ >= 14 Right = AMOTION_EVENT_BUTTON_SECONDARY + #else + Right = 1 << 2 + #endif }; /** @@ -499,7 +549,11 @@ class AndroidApplication::MouseMoveEvent: public InputEvent { /** @brief Mouse buttons */ Buttons buttons() const { + #if __ANDROID_API__ >= 14 return Button(AMotionEvent_getButtonState(_event)); + #else + return {}; + #endif } private: From dee57c44796ce04d1ea11fcee9f24afe8ff924a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Mar 2014 12:58:58 +0100 Subject: [PATCH 046/141] MeshTools: add std::vector overload to combineIndexArrays(). So the functions can *really* be used at runtime. --- src/Magnum/MeshTools/CombineIndexedArrays.cpp | 16 ++++++++-------- src/Magnum/MeshTools/CombineIndexedArrays.h | 13 ++++++++++++- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Magnum/MeshTools/CombineIndexedArrays.cpp b/src/Magnum/MeshTools/CombineIndexedArrays.cpp index 57e918e8b..693c86896 100644 --- a/src/Magnum/MeshTools/CombineIndexedArrays.cpp +++ b/src/Magnum/MeshTools/CombineIndexedArrays.cpp @@ -56,26 +56,24 @@ std::pair, std::vector> interleaveAndCombi /* Combine them */ std::vector combinedIndices; - std::tie(combinedIndices, interleavedArrays) = combineIndexArrays(interleavedArrays, stride); + std::tie(combinedIndices, interleavedArrays) = MeshTools::combineIndexArrays(interleavedArrays, stride); return {combinedIndices, interleavedArrays}; } -} - -std::vector combineIndexArrays(const std::initializer_list>> arrays) { +std::vector combineIndexArrays(const std::reference_wrapper>* const begin, const std::reference_wrapper>* const end) { /* Interleave and combine the arrays */ std::vector combinedIndices; std::vector interleavedCombinedArrays; std::tie(combinedIndices, interleavedCombinedArrays) = Implementation::interleaveAndCombineIndexArrays( /* This will bite me hard once. */ - reinterpret_cast>*>(arrays.begin()), - reinterpret_cast>*>(arrays.end())); + reinterpret_cast>*>(begin), + reinterpret_cast>*>(end)); /* Update the original indices */ - const UnsignedInt stride = arrays.size(); + const UnsignedInt stride = end - begin; const UnsignedInt outputSize = interleavedCombinedArrays.size()/stride; for(UnsignedInt offset = 0; offset != stride; ++offset) { - auto& array = (arrays.begin()+offset)->get(); + auto& array = (begin+offset)->get(); CORRADE_INTERNAL_ASSERT(array.size() >= outputSize); array.resize(outputSize); for(UnsignedInt i = 0; i != outputSize; ++i) @@ -85,6 +83,8 @@ std::vector combineIndexArrays(const std::initializer_list combineIndexArrays(const std::reference_wrapper>* begin, const std::reference_wrapper>* end); +} + /** @brief Combine index arrays @@ -81,7 +85,14 @@ This function calls @ref combineIndexArrays(const std::vector&, Uns internally. See also @ref combineIndexedArrays() which does the vertex data reordering automatically. */ -MAGNUM_MESHTOOLS_EXPORT std::vector combineIndexArrays(std::initializer_list>> arrays); +inline std::vector combineIndexArrays(const std::vector>>& arrays) { + return Implementation::combineIndexArrays(&arrays[0], &arrays[0] + arrays.size()); +} + +/** @overload */ +inline std::vector combineIndexArrays(std::initializer_list>> arrays) { + return Implementation::combineIndexArrays(arrays.begin(), arrays.end()); +} /** @brief Combine index arrays From 14e4e78b6b255ff50d74197e77136228c2f9c371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Mar 2014 13:01:22 +0100 Subject: [PATCH 047/141] MeshTools: check out-of-range access in MeshTools::duplicate(). --- src/Magnum/MeshTools/Duplicate.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Magnum/MeshTools/Duplicate.h b/src/Magnum/MeshTools/Duplicate.h index 4d67ab583..7ba7772c2 100644 --- a/src/Magnum/MeshTools/Duplicate.h +++ b/src/Magnum/MeshTools/Duplicate.h @@ -30,6 +30,7 @@ */ #include +#include #include "Magnum/Types.h" @@ -45,8 +46,10 @@ index array `{1, 1, 0, 3, 2, 2}` will be converted to `{b, b, a, d, c, c}`. template std::vector duplicate(const std::vector& indices, const std::vector& data) { std::vector out; out.reserve(indices.size()); - for(const UnsignedInt index: indices) + for(const UnsignedInt index: indices) { + CORRADE_ASSERT(index < data.size(), "MeshTools::duplicate(): index out of range", out); out.push_back(data[index]); + } return out; } From 6bd5db4c2b815f7267fbd6bb4122ed89b3be5b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Mar 2014 13:04:47 +0100 Subject: [PATCH 048/141] MeshTools: check for out-of-range access also in combineIndexedArrays(). --- src/Magnum/MeshTools/CombineIndexedArrays.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Magnum/MeshTools/CombineIndexedArrays.h b/src/Magnum/MeshTools/CombineIndexedArrays.h index 7bb3fe65b..4feb71e9a 100644 --- a/src/Magnum/MeshTools/CombineIndexedArrays.h +++ b/src/Magnum/MeshTools/CombineIndexedArrays.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "Magnum/Types.h" #include "Magnum/MeshTools/visibility.h" @@ -122,10 +123,14 @@ namespace Implementation { MAGNUM_MESHTOOLS_EXPORT std::pair, std::vector> interleaveAndCombineIndexArrays(const std::reference_wrapper>* begin, const std::reference_wrapper>* end); template void writeCombinedArray(const UnsignedInt stride, const UnsignedInt offset, const std::vector& interleavedCombinedIndexArrays, std::vector& array) { + /* Can't use duplicate() here because we aren't accessing the index data sequentially */ std::vector output; output.reserve(interleavedCombinedIndexArrays.size()/stride); - for(std::size_t i = 0, max = interleavedCombinedIndexArrays.size()/stride; i != max; ++i) - output.push_back(array[interleavedCombinedIndexArrays[offset + i*stride]]); + for(std::size_t i = 0, max = interleavedCombinedIndexArrays.size()/stride; i != max; ++i) { + const UnsignedInt index = interleavedCombinedIndexArrays[offset + i*stride]; + CORRADE_ASSERT(index < array.size(), "MeshTools::combineIndexedArrays(): index out of range", ); + output.push_back(array[index]); + } std::swap(output, array); } From 598f31b9e36e744df1b12844468502967706950e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Mar 2014 13:05:08 +0100 Subject: [PATCH 049/141] MeshTools: check for proper stride value in combineIndexArrays(). --- src/Magnum/MeshTools/CombineIndexedArrays.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magnum/MeshTools/CombineIndexedArrays.cpp b/src/Magnum/MeshTools/CombineIndexedArrays.cpp index 693c86896..0de3b868a 100644 --- a/src/Magnum/MeshTools/CombineIndexedArrays.cpp +++ b/src/Magnum/MeshTools/CombineIndexedArrays.cpp @@ -116,6 +116,7 @@ class IndexEqual { } std::pair, std::vector> combineIndexArrays(const std::vector& interleavedArrays, const UnsignedInt stride) { + CORRADE_ASSERT(stride != 0, "MeshTools::combineIndexArrays(): stride can't be zero", {}); CORRADE_ASSERT(interleavedArrays.size() % stride == 0, "MeshTools::combineIndexArrays(): array size is not divisible by stride", {}); /* Hash map with index combinations, containing just indices into From 77e38fcce3a162863bed42190be4b51ecafa575d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Mar 2014 13:10:27 +0100 Subject: [PATCH 050/141] New ObjImporter plugin. --- CMakeLists.txt | 3 +- doc/building.dox | 1 + doc/cmake.dox | 2 + modules/FindMagnum.cmake | 4 + src/MagnumPlugins/CMakeLists.txt | 4 + src/MagnumPlugins/ObjImporter/CMakeLists.txt | 53 ++ .../ObjImporter/ObjImporter.conf | 0 src/MagnumPlugins/ObjImporter/ObjImporter.cpp | 408 ++++++++++ src/MagnumPlugins/ObjImporter/ObjImporter.h | 86 ++ .../ObjImporter/Test/CMakeLists.txt | 31 + src/MagnumPlugins/ObjImporter/Test/Test.cpp | 737 ++++++++++++++++++ .../ObjImporter/Test/configure.h.cmake | 26 + .../ObjImporter/Test/emptyFile.obj | 1 + .../ObjImporter/Test/keywords.obj | 7 + .../ObjImporter/Test/lineMesh.obj | 8 + .../ObjImporter/Test/missingData.obj | 23 + .../ObjImporter/Test/mixedPrimitives.obj | 13 + .../ObjImporter/Test/moreMeshes.obj | 21 + .../ObjImporter/Test/namedMesh.obj | 2 + .../ObjImporter/Test/normals.obj | 12 + .../ObjImporter/Test/optionalCoordinates.obj | 17 + .../ObjImporter/Test/pointMesh.obj | 10 + .../ObjImporter/Test/textureCoordinates.obj | 12 + .../Test/textureCoordinatesNormals.obj | 17 + .../ObjImporter/Test/triangleMesh.obj | 9 + .../ObjImporter/Test/unnamedFirstMesh.obj | 2 + .../ObjImporter/Test/wrongIndexCount.obj | 13 + .../ObjImporter/Test/wrongNumberCount.obj | 29 + .../ObjImporter/Test/wrongNumbers.obj | 20 + .../ObjImporter/pluginRegistration.cpp | 29 + 30 files changed, 1599 insertions(+), 1 deletion(-) create mode 100644 src/MagnumPlugins/ObjImporter/CMakeLists.txt create mode 100644 src/MagnumPlugins/ObjImporter/ObjImporter.conf create mode 100644 src/MagnumPlugins/ObjImporter/ObjImporter.cpp create mode 100644 src/MagnumPlugins/ObjImporter/ObjImporter.h create mode 100644 src/MagnumPlugins/ObjImporter/Test/CMakeLists.txt create mode 100644 src/MagnumPlugins/ObjImporter/Test/Test.cpp create mode 100644 src/MagnumPlugins/ObjImporter/Test/configure.h.cmake create mode 100644 src/MagnumPlugins/ObjImporter/Test/emptyFile.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/keywords.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/lineMesh.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/missingData.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/mixedPrimitives.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/moreMeshes.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/namedMesh.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/normals.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/optionalCoordinates.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/pointMesh.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/textureCoordinates.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/textureCoordinatesNormals.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/triangleMesh.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/unnamedFirstMesh.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/wrongIndexCount.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/wrongNumberCount.obj create mode 100644 src/MagnumPlugins/ObjImporter/Test/wrongNumbers.obj create mode 100644 src/MagnumPlugins/ObjImporter/pluginRegistration.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ee3a229dc..b3ff23af4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ option(WITH_FIND_MODULE "Install FindMagnum.cmake module into CMake's module dir # Parts of the library option(WITH_AUDIO "Build Audio library" OFF) option(WITH_DEBUGTOOLS "Build DebugTools library" ON) -cmake_dependent_option(WITH_MESHTOOLS "Build MeshTools library" ON "NOT WITH_DEBUGTOOLS" ON) +cmake_dependent_option(WITH_MESHTOOLS "Build MeshTools library" ON "NOT WITH_DEBUGTOOLS;NOT WITH_OBJIMPORTER" ON) cmake_dependent_option(WITH_PRIMITIVES "Builf Primitives library" ON "NOT WITH_DEBUGTOOLS" ON) cmake_dependent_option(WITH_SCENEGRAPH "Build SceneGraph library" ON "NOT WITH_DEBUGTOOLS;NOT WITH_SHAPES" ON) cmake_dependent_option(WITH_SHADERS "Build Shaders library" ON "NOT WITH_DEBUGTOOLS" ON) @@ -85,6 +85,7 @@ endif() # Plugins cmake_dependent_option(WITH_MAGNUMFONT "Build MagnumFont plugin" OFF "WITH_TEXT" OFF) cmake_dependent_option(WITH_MAGNUMFONTCONVERTER "Build MagnumFontConverter plugin" OFF "NOT MAGNUM_TARGET_GLES;WITH_TEXT" OFF) +option(WITH_OBJIMPORTER "Build ObjImporter plugin" OFF) cmake_dependent_option(WITH_TGAIMAGECONVERTER "Build TgaImageConverter plugin" OFF "NOT WITH_MAGNUMFONTCONVERTER" ON) cmake_dependent_option(WITH_TGAIMPORTER "Build TgaImporter plugin" OFF "NOT WITH_MAGNUMFONT" ON) cmake_dependent_option(WITH_WAVAUDIOIMPORTER "Build WavAudioImporter plugin" OFF "WITH_AUDIO" OFF) diff --git a/doc/building.dox b/doc/building.dox index 15516371b..2173ab1de 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -216,6 +216,7 @@ default. - `WITH_MAGNUMFONTCONVERTER` -- @ref Text::MagnumFontConverter "MagnumFontConverter" plugin. Available only if `WITH_TEXT` is enabled. Enables also building of @ref Trade::TgaImageConverter "TgaImageConverter" plugin. +- `WITH_OBJIMPORTER` -- @ref Trade::ObjImporter "ObjImporter" plugin. - `WITH_TGAIMPORTER` -- @ref Trade::TgaImporter "TgaImporter" plugin. - `WITH_TGAIMAGECONVERTER` -- @ref Trade::TgaImageConverter "TgaImageConverter" plugin. diff --git a/doc/cmake.dox b/doc/cmake.dox index c1b60c6e9..d106817c5 100644 --- a/doc/cmake.dox +++ b/doc/cmake.dox @@ -103,6 +103,8 @@ dependencies, you need to find the dependency and then link to it. `%Text` component and `TgaImporter` plugin) - `MagnumFontConverter` -- @ref Text::MagnumFontConverter "MagnumFontConverter" plugin (depends on `%Text` component and `%TgaImageConverter` plugin) +- `ObjImporter` -- @ref Trade::ObjImporter "ObjImporter" plugin (depends on + `%MeshTools` component) - `TgaImageConverter` -- @ref Trade::TgaImageConverter "TgaImageConverter" plugin - `TgaImporter` -- @ref Trade::TgaImporter "TgaImporter" plugin diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 3257507ee..f4c822644 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -35,6 +35,7 @@ # and TgaImporter plugin) # MagnumFontConverter - Magnum bitmap font converter plugin (depends on Text # component and TgaImageConverter plugin) +# ObjImporter - OBJ importer plugin # TgaImageConverter - TGA image converter plugin # TgaImporter - TGA importer plugin # WavAudioImporter - WAV audio importer plugin (depends on Audio component) @@ -334,6 +335,9 @@ foreach(component ${Magnum_FIND_COMPONENTS}) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES Atlas.h) endif() + # The plugins don't have any dependencies, nothing additional to do for + # them + # Try to find the includes if(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES) find_path(_MAGNUM_${_COMPONENT}_INCLUDE_DIR diff --git a/src/MagnumPlugins/CMakeLists.txt b/src/MagnumPlugins/CMakeLists.txt index 188c83af9..549a69ba0 100644 --- a/src/MagnumPlugins/CMakeLists.txt +++ b/src/MagnumPlugins/CMakeLists.txt @@ -40,6 +40,10 @@ if(WITH_TEXT AND WITH_MAGNUMFONTCONVERTER AND NOT MAGNUM_TARGET_GLES) add_subdirectory(MagnumFontConverter) endif() +if(WITH_OBJIMPORTER) + add_subdirectory(ObjImporter) +endif() + if(WITH_TGAIMAGECONVERTER) add_subdirectory(TgaImageConverter) endif() diff --git a/src/MagnumPlugins/ObjImporter/CMakeLists.txt b/src/MagnumPlugins/ObjImporter/CMakeLists.txt new file mode 100644 index 000000000..5ab131c03 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/CMakeLists.txt @@ -0,0 +1,53 @@ +# +# 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. +# + +add_library(ObjImporterObjects OBJECT ObjImporter.cpp) +if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) + set_target_properties(ObjImporterObjects PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") +endif() + +add_plugin(ObjImporter ${MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR} + ObjImporter.conf + $ + pluginRegistration.cpp) +target_link_libraries(ObjImporter Magnum MagnumMeshTools) + +install(FILES ObjImporter.h DESTINATION ${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}/ObjImporter) + +if(BUILD_TESTS) + add_library(ObjImporterTestLib STATIC $) + target_link_libraries(ObjImporterTestLib Magnum MagnumMeshTools) + + # On Windows we need to install first and then run the tests to avoid "DLL + # not found" hell, thus we need to install this too + if(WIN32 AND NOT CMAKE_CROSSCOMPILING) + install(TARGETS ObjImporterTestLib + RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} + LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} + ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) + endif() + + add_subdirectory(Test) +endif() diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.conf b/src/MagnumPlugins/ObjImporter/ObjImporter.conf new file mode 100644 index 000000000..e69de29bb diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp new file mode 100644 index 000000000..1d223fcae --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp @@ -0,0 +1,408 @@ +/* + 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 "ObjImporter.h" + +#include +#include +#include +#include +#include +#include + +#include "Magnum/Math/Vector3.h" +#include "Magnum/Trade/MeshData3D.h" +#include +#include +#include + +namespace Magnum { namespace Trade { + +struct ObjImporter::File { + std::unordered_map meshesForName; + std::vector meshNames; + std::vector> meshes; + std::unique_ptr in; +}; + +namespace { + +void ignoreLine(std::istream& in) { + in.ignore(std::numeric_limits::max(), '\n'); +} + +template Math::Vector extractFloatData(std::string str, Float* extra = nullptr) { + std::vector data = Utility::String::splitWithoutEmptyParts(str, ' '); + if(data.size() < size || data.size() > size + (extra ? 1 : 0)) { + Error() << "Trade::ObjImporter::mesh3D(): invalid float array size"; + throw 0; + } + + Math::Vector output; + for(std::size_t i = 0; i != size; ++i) + output[i] = std::stof(data[i]); + + if(data.size() == size+1) *extra = std::stof(data.back()); + + return output; +} + +template void reindex(const std::vector& indices, std::vector& data) { + /* Check that indices are in range */ + for(UnsignedInt i: indices) if(i >= data.size()) { + Error() << "Trade::ObjImporter::mesh3D(): index out of range"; + throw 0; + } + + data = MeshTools::duplicate(indices, data); +} + +} + +ObjImporter::ObjImporter() = default; + +ObjImporter::ObjImporter(PluginManager::AbstractManager& manager, std::string plugin): AbstractImporter(manager, std::move(plugin)) {} + +ObjImporter::~ObjImporter() = default; + +auto ObjImporter::doFeatures() const -> Features { return Feature::OpenData; } + +void ObjImporter::doClose() { _file.reset(); } + +bool ObjImporter::doIsOpened() const { return !!_file; } + +void ObjImporter::doOpenFile(const std::string& filename) { + /* Open file in *text* mode (to avoid \r handling) */ + std::unique_ptr in{new std::ifstream{filename}}; + if(!in->good()) { + Error() << "Trade::ObjImporter::openFile(): cannot open file" << filename; + return; + } + + _file.reset(new File); + _file->in = std::move(in); + parseMeshNames(); +} + +void ObjImporter::doOpenData(Containers::ArrayReference data) { + /* Open file in *text* mode (to avoid \r handling) */ + _file.reset(new File); + _file->in.reset(new std::istringstream{{reinterpret_cast(data.begin()), data.size()}}); + + parseMeshNames(); +} + +void ObjImporter::parseMeshNames() { + bool hasData = false; + std::string name; + std::streampos begin = 0; + while(_file->in->good()) { + /* The previous object ends at the beginning of this line */ + const std::streampos end = _file->in->tellg(); + + /* Comment line */ + if(_file->in->peek() == '#') { + ignoreLine(*_file->in); + continue; + } + + /* Parse the keyword */ + std::string keyword; + *_file->in >> keyword; + + /* Object name */ + if(keyword == "o") { + /* If there was any previous object, this is name of new object, + save the previous one */ + if(hasData) { + if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size()); + _file->meshNames.emplace_back(std::move(name)); + _file->meshes.emplace_back(begin, end); + + /* Otherwise it's the name of first object (there weren't any data + before) */ + } else hasData = true; + + /* Get name of new object, the object then starts at the next line */ + std::getline(*_file->in, name); + name = Utility::String::trim(name); + begin = _file->in->tellg(); + continue; + } + + /* If there are any data before the first name, it means that the first + object can be unnamed */ + if(!hasData) for(const std::string& data: {"v", "vt", "vn", "p", "l", "f"}) { + if(keyword == data) { + hasData = true; + break; + } + } + + /* Ignore the rest of the line */ + ignoreLine(*_file->in); + } + + /* Add also the last object */ + _file->in->clear(); + _file->in->seekg(0, std::ios::end); + if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size()); + _file->meshNames.emplace_back(std::move(name)); + _file->meshes.emplace_back(begin, _file->in->tellg()); +} + +UnsignedInt ObjImporter::doMesh3DCount() const { return _file->meshes.size(); } + +Int ObjImporter::doMesh3DForName(const std::string& name) { + const auto it = _file->meshesForName.find(name); + return it == _file->meshesForName.end() ? -1 : it->second; +} + +std::string ObjImporter::doMesh3DName(UnsignedInt id) { + return _file->meshNames[id]; +} + +std::optional ObjImporter::doMesh3D(UnsignedInt id) { + /* Seek the file */ + std::streampos begin, end; + std::tie(begin, end) = _file->meshes[id]; + _file->in->seekg(begin); + + std::optional primitive; + std::vector positions; + std::vector> textureCoordinates; + std::vector> normals; + std::vector positionIndices; + std::vector textureCoordinateIndices; + std::vector normalIndices; + + try { while(_file->in->good() && _file->in->tellg() < end) { + /* Ignore comments */ + if(_file->in->peek() == '#') { + ignoreLine(*_file->in); + continue; + } + + /* Get the line */ + std::string line; + std::getline(*_file->in, line); + line = Utility::String::trim(line); + + /* Ignore empty lines */ + if(line.empty()) continue; + + /* Split the line into keyword and contents */ + const std::size_t keywordEnd = line.find(' '); + const std::string keyword = line.substr(0, keywordEnd); + const std::string contents = keywordEnd != std::string::npos ? + Utility::String::ltrim(line.substr(keywordEnd+1)) : ""; + + /* Vertex position */ + if(keyword == "v") { + Float extra{1.0f}; + const Vector3 data = extractFloatData<3>(contents, &extra); + if(!Math::TypeTraits::equals(extra, 1.0f)) { + Error() << "Trade::ObjImporter::mesh3D(): homogeneous coordinates are not supported"; + return std::nullopt; + } + + positions.push_back(data); + + /* Texture coordinate */ + } else if(keyword == "vt") { + Float extra{0.0f}; + const auto data = extractFloatData<2>(contents, &extra); + if(!Math::TypeTraits::equals(extra, 0.0f)) { + Error() << "Trade::ObjImporter::mesh3D(): 3D texture coordinates are not supported"; + return std::nullopt; + } + + if(textureCoordinates.empty()) textureCoordinates.push_back({}); + textureCoordinates.front().push_back(data); + + /* Normal */ + } else if(keyword == "vn") { + if(normals.empty()) normals.push_back({}); + normals.front().push_back(extractFloatData<3>(contents)); + + /* Indices */ + } else if(keyword == "p" || keyword == "l" || keyword == "f") { + const std::vector indexTuples = Utility::String::splitWithoutEmptyParts(contents, ' '); + + /* Points */ + if(keyword == "p") { + /* Check that we don't mix the primitives in one mesh */ + if(primitive && primitive != MeshPrimitive::Points) { + Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Points; + return std::nullopt; + } + + /* Check vertex count per primitive */ + if(indexTuples.size() != 1) { + Error() << "Trade::ObjImporter::mesh3D(): wrong index count for point"; + return std::nullopt; + } + + primitive = MeshPrimitive::Points; + + /* Lines */ + } else if(keyword == "l") { + /* Check that we don't mix the primitives in one mesh */ + if(primitive && primitive != MeshPrimitive::Lines) { + Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Lines; + return std::nullopt; + } + + /* Check vertex count per primitive */ + if(indexTuples.size() != 2) { + Error() << "Trade::ObjImporter::mesh3D(): wrong index count for line"; + return std::nullopt; + } + + primitive = MeshPrimitive::Lines; + + /* Faces */ + } else if(keyword == "f") { + /* Check that we don't mix the primitives in one mesh */ + if(primitive && primitive != MeshPrimitive::Triangles) { + Error() << "Trade::ObjImporter::mesh3D(): mixed primitive" << *primitive << "and" << MeshPrimitive::Triangles; + return std::nullopt; + } + + /* Check vertex count per primitive */ + if(indexTuples.size() < 3) { + Error() << "Trade::ObjImporter::mesh3D(): wrong index count for triangle"; + return std::nullopt; + } else if(indexTuples.size() != 3) { + Error() << "Trade::ObjImporter::mesh3D(): polygons are not supported"; + return std::nullopt; + } + + primitive = MeshPrimitive::Triangles; + + } else CORRADE_ASSERT_UNREACHABLE(); + + for(const std::string& indexTuple: indexTuples) { + std::vector indices = Utility::String::split(indexTuple, '/'); + if(indices.size() > 3) { + Error() << "Trade::ObjImporter::mesh3D(): invalid index data"; + return std::nullopt; + } + + /* Indices in OBJ file start from 1 */ + + /* Position indices */ + positionIndices.push_back(std::stoul(indices[0])-1); + + /* Texture coordinates */ + if(indices.size() == 2 || (indices.size() == 3 && !indices[1].empty())) + textureCoordinateIndices.push_back(std::stoul(indices[1])-1); + + /* Normal indices */ + if(indices.size() == 3) + normalIndices.push_back(std::stoul(indices[2])-1); + } + + /* Ignore unsupported keywords, error out on unknown keywords */ + } else if(![&keyword](){ + /* Using lambda to emulate for-else construct like in Python */ + for(const std::string expected: {"mtllib", "usemtl", "g", "s"}) + if(keyword == expected) return true; + return false; + }()) { + Error() << "Trade::ObjImporter::mesh3D(): unknown keyword" << keyword; + return std::nullopt; + } + + }} catch(std::exception) { + Error() << "Trade::ObjImporter::mesh3D(): error while converting numeric data"; + return std::nullopt; + } catch(...) { + /* Error message already printed */ + return std::nullopt; + } + + /* There should be at least indexed position data */ + if(positions.empty() || positionIndices.empty()) { + Error() << "Trade::ObjImporter::mesh3D(): incomplete position data"; + return std::nullopt; + } + + /* If there are index data, there should be also vertex data (and also the other way) */ + if(normals.empty() != normalIndices.empty()) { + Error() << "Trade::ObjImporter::mesh3D(): incomplete normal data"; + return std::nullopt; + } + if(textureCoordinates.empty() != textureCoordinateIndices.empty()) { + Error() << "Trade::ObjImporter::mesh3D(): incomplete texture coordinate data"; + return std::nullopt; + } + + /* All index arrays should have the same length */ + if(!normalIndices.empty() && normalIndices.size() != positionIndices.size()) { + CORRADE_INTERNAL_ASSERT(normalIndices.size() < positionIndices.size()); + Error() << "Trade::ObjImporter::mesh3D(): some normal indices are missing"; + return std::nullopt; + } + if(!textureCoordinates.empty() && textureCoordinateIndices.size() != positionIndices.size()) { + CORRADE_INTERNAL_ASSERT(textureCoordinateIndices.size() < positionIndices.size()); + Error() << "Trade::ObjImporter::mesh3D(): some texture coordinate indices are missing"; + return std::nullopt; + } + + /* Merge index arrays, if there aren't just the positions */ + std::vector indices; + if(!normalIndices.empty() || !textureCoordinateIndices.empty()) { + std::vector>> arrays; + arrays.reserve(3); + arrays.push_back(positionIndices); + if(!normalIndices.empty()) arrays.push_back(normalIndices); + if(!textureCoordinateIndices.empty()) arrays.push_back(textureCoordinateIndices); + indices = MeshTools::combineIndexArrays(arrays); + + /* Reindex data arrays */ + try { + reindex(positionIndices, positions); + if(!normalIndices.empty()) reindex(normalIndices, normals.front()); + if(!textureCoordinateIndices.empty()) reindex(textureCoordinateIndices, textureCoordinates.front()); + } catch(...) { + /* Error message already printed */ + return std::nullopt; + } + + /* Otherwise just use the original position index array. Don't forget to + check range */ + } else { + indices = std::move(positionIndices); + for(UnsignedInt i: indices) if(i >= positions.size()) { + Error() << "Trade::ObjImporter::mesh3D(): index out of range"; + return std::nullopt; + } + } + + return MeshData3D(*primitive, std::move(indices), {std::move(positions)}, std::move(normals), std::move(textureCoordinates)); +} + +}} diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.h b/src/MagnumPlugins/ObjImporter/ObjImporter.h new file mode 100644 index 000000000..cf6931667 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/ObjImporter.h @@ -0,0 +1,86 @@ +#ifndef Magnum_Trade_ObjImporter_h +#define Magnum_Trade_ObjImporter_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. +*/ + +/** @file + * @brief Class @ref Magnum::Trade::ObjImporter + */ + +#include "Magnum/Trade/AbstractImporter.h" + +namespace Magnum { namespace Trade { + +/** +@brief OBJ importer plugin + +Supported features: +- multiple objects +- vertex positions, normals and 2D texture coordinates +- triangles, lines and points + +Polygons (quads etc.), automatic normal generation and material properties are +currently not supported. + +This plugin is built if `WITH_OBJIMPORTER` is enabled when building %Magnum. To +use dynamic plugin, you need to load `%ObjImporter` plugin from +`MAGNUM_PLUGINS_IMPORTER_DIR`. To use static plugin or use this as a dependency +of another plugin, you need to request `%ObjImporter` component of `%Magnum` +package in CMake and link to `${MAGNUM_OBJIMPORTER_LIBRARIES}`. See +@ref building, @ref cmake and @ref plugins for more information. +*/ +class ObjImporter: public AbstractImporter { + public: + /** @brief Default constructor */ + explicit ObjImporter(); + + /** @brief Plugin manager constructor */ + explicit ObjImporter(PluginManager::AbstractManager& manager, std::string plugin); + + ~ObjImporter(); + + private: + struct File; + + Features doFeatures() const override; + + bool doIsOpened() const override; + void doOpenData(Containers::ArrayReference data) override; + void doOpenFile(const std::string& filename) override; + void doClose() override; + + UnsignedInt doMesh3DCount() const override; + Int doMesh3DForName(const std::string& name) override; + std::string doMesh3DName(UnsignedInt id) override; + std::optional doMesh3D(UnsignedInt id) override; + + void parseMeshNames(); + + std::unique_ptr _file; +}; + +}} + +#endif diff --git a/src/MagnumPlugins/ObjImporter/Test/CMakeLists.txt b/src/MagnumPlugins/ObjImporter/Test/CMakeLists.txt new file mode 100644 index 000000000..c5dec7146 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# 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. +# + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h) + +include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) + +corrade_add_test(ObjImporterTest Test.cpp LIBRARIES ObjImporterTestLib) diff --git a/src/MagnumPlugins/ObjImporter/Test/Test.cpp b/src/MagnumPlugins/ObjImporter/Test/Test.cpp new file mode 100644 index 000000000..9b4d858e9 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/Test.cpp @@ -0,0 +1,737 @@ +/* + 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 +#include +#include + +#include "Magnum/Mesh.h" +#include "Magnum/Math/Vector3.h" +#include "Magnum/Trade/MeshData3D.h" +#include "MagnumPlugins/ObjImporter/ObjImporter.h" + +#include "configure.h" + +namespace Magnum { namespace Trade { namespace Test { + +class ObjImporterTest: public TestSuite::Tester { + public: + explicit ObjImporterTest(); + + void pointMesh(); + void lineMesh(); + void triangleMesh(); + void mixedPrimitives(); + + void positionsOnly(); + void textureCoordinates(); + void normals(); + void textureCoordinatesNormals(); + + void emptyFile(); + void unnamedMesh(); + void namedMesh(); + void moreMeshes(); + void unnamedFirstMesh(); + + void wrongFloat(); + void wrongInteger(); + void unmergedIndexOutOfRange(); + void mergedIndexOutOfRange(); + void zeroIndex(); + + void explicitOptionalPositionCoordinate(); + void explicitOptionalTextureCoordinate(); + void unsupportedOptionalPositionCoordinate(); + void unsupportedOptionalTextureCoordinate(); + + void shortFloatData(); + void longFloatData(); + void longOptionalFloatData(); + + void longIndexData(); + void wrongPointIndexData(); + void wrongLineIndexData(); + void wrongTriangleIndexData(); + void polygonIndexData(); + + void missingPositionData(); + void missingNormalData(); + void missingTextureCoordinateData(); + void missingPositionIndices(); + void missingNormalIndices(); + void missingTextureCoordinateIndices(); + + void wrongTextureCoordinateIndexCount(); + void wrongNormalIndexCount(); + + void unsupportedKeyword(); + void unknownKeyword(); +}; + +ObjImporterTest::ObjImporterTest() { + addTests({&ObjImporterTest::pointMesh, + &ObjImporterTest::lineMesh, + &ObjImporterTest::triangleMesh, + &ObjImporterTest::mixedPrimitives, + + &ObjImporterTest::positionsOnly, + &ObjImporterTest::textureCoordinates, + &ObjImporterTest::normals, + &ObjImporterTest::textureCoordinatesNormals, + + &ObjImporterTest::emptyFile, + &ObjImporterTest::unnamedMesh, + &ObjImporterTest::namedMesh, + &ObjImporterTest::moreMeshes, + &ObjImporterTest::unnamedFirstMesh, + + &ObjImporterTest::wrongFloat, + &ObjImporterTest::wrongInteger, + &ObjImporterTest::unmergedIndexOutOfRange, + &ObjImporterTest::mergedIndexOutOfRange, + &ObjImporterTest::zeroIndex, + + &ObjImporterTest::explicitOptionalPositionCoordinate, + &ObjImporterTest::explicitOptionalTextureCoordinate, + &ObjImporterTest::unsupportedOptionalPositionCoordinate, + &ObjImporterTest::unsupportedOptionalTextureCoordinate, + + &ObjImporterTest::shortFloatData, + &ObjImporterTest::longFloatData, + &ObjImporterTest::longOptionalFloatData, + + &ObjImporterTest::longIndexData, + &ObjImporterTest::wrongPointIndexData, + &ObjImporterTest::wrongLineIndexData, + &ObjImporterTest::wrongTriangleIndexData, + + &ObjImporterTest::missingPositionData, + &ObjImporterTest::missingNormalData, + &ObjImporterTest::missingTextureCoordinateData, + &ObjImporterTest::missingPositionIndices, + &ObjImporterTest::missingNormalIndices, + &ObjImporterTest::missingTextureCoordinateIndices, + + &ObjImporterTest::wrongTextureCoordinateIndexCount, + &ObjImporterTest::wrongNormalIndexCount, + + &ObjImporterTest::unsupportedKeyword, + &ObjImporterTest::unknownKeyword}); +} + +void ObjImporterTest::pointMesh() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "pointMesh.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + + const std::optional data = importer.mesh3D(0); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f}, + {2.0f, 3.0f, 5.0f} + })); + CORRADE_COMPARE(data->indices(), (std::vector{ + 0, 2, 1, 0 + })); +} + +void ObjImporterTest::lineMesh() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "lineMesh.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + + const std::optional data = importer.mesh3D(0); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f}, + {2.0f, 3.0f, 5.0f} + })); + CORRADE_COMPARE(data->indices(), (std::vector{ + 0, 1, 1, 2 + })); +} + +void ObjImporterTest::triangleMesh() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "triangleMesh.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + + const std::optional data = importer.mesh3D(0); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->primitive(), MeshPrimitive::Triangles); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f}, + {2.0f, 3.0f, 5.0f}, + {2.5f, 0.0f, 1.0f} + })); + CORRADE_COMPARE(data->indices(), (std::vector{ + 0, 1, 2, 3, 1, 0 + })); +} + +void ObjImporterTest::mixedPrimitives() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "mixedPrimitives.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(0)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): mixed primitive MeshPrimitive::Points and MeshPrimitive::Lines\n"); +} + +void ObjImporterTest::positionsOnly() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "triangleMesh.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + + const std::optional data = importer.mesh3D(0); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_VERIFY(!data->hasNormals()); + CORRADE_VERIFY(!data->hasTextureCoords2D()); +} + +void ObjImporterTest::textureCoordinates() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "textureCoordinates.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + + const std::optional data = importer.mesh3D(0); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_VERIFY(!data->hasNormals()); + CORRADE_COMPARE(data->textureCoords2DArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f}, + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f} + })); + CORRADE_COMPARE(data->textureCoords2D(0), (std::vector{ + {1.0f, 0.5f}, + {1.0f, 0.5f}, + {0.5f, 1.0f}, + {0.5f, 1.0f} + })); + CORRADE_COMPARE(data->indices(), (std::vector{ + 0, 1, 2, 3, 1, 0 + })); +} + +void ObjImporterTest::normals() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "normals.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + + const std::optional data = importer.mesh3D(0); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_VERIFY(!data->hasTextureCoords2D()); + CORRADE_COMPARE(data->normalArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f}, + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f} + })); + CORRADE_COMPARE(data->normals(0), (std::vector{ + {1.0f, 0.5f, 3.5f}, + {1.0f, 0.5f, 3.5f}, + {0.5f, 1.0f, 0.5f}, + {0.5f, 1.0f, 0.5f} + })); + CORRADE_COMPARE(data->indices(), (std::vector{ + 0, 1, 2, 3, 1, 0 + })); +} + +void ObjImporterTest::textureCoordinatesNormals() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "textureCoordinatesNormals.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + + const std::optional data = importer.mesh3D(0); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->primitive(), MeshPrimitive::Lines); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_COMPARE(data->textureCoords2DArrayCount(), 1); + CORRADE_COMPARE(data->normalArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f}, + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f}, + {0.0f, 1.5f, 1.0f} + })); + CORRADE_COMPARE(data->textureCoords2D(0), (std::vector{ + {1.0f, 0.5f}, + {1.0f, 0.5f}, + {0.5f, 1.0f}, + {0.5f, 1.0f}, + {0.5f, 1.0f} + })); + CORRADE_COMPARE(data->normals(0), (std::vector{ + {1.0f, 0.5f, 3.5f}, + {0.5f, 1.0f, 0.5f}, + {0.5f, 1.0f, 0.5f}, + {1.0f, 0.5f, 3.5f}, + {0.5f, 1.0f, 0.5f} + })); + CORRADE_COMPARE(data->indices(), (std::vector{ + 0, 1, 2, 3, 1, 0, 4, 2 + })); +} + +void ObjImporterTest::emptyFile() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "emptyFile.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); +} + +void ObjImporterTest::unnamedMesh() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "emptyFile.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + CORRADE_COMPARE(importer.mesh3DName(0), ""); + CORRADE_COMPARE(importer.mesh3DForName(""), -1); +} + +void ObjImporterTest::namedMesh() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "namedMesh.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 1); + CORRADE_COMPARE(importer.mesh3DName(0), "MyMesh"); + CORRADE_COMPARE(importer.mesh3DForName("MyMesh"), 0); +} + +void ObjImporterTest::moreMeshes() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "moreMeshes.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 3); + + CORRADE_COMPARE(importer.mesh3DName(0), "PointMesh"); + CORRADE_COMPARE(importer.mesh3DForName("PointMesh"), 0); + const std::optional data = importer.mesh3D(0); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f} + })); + CORRADE_COMPARE(data->indices(), (std::vector{ + 0, 1 + })); + + CORRADE_COMPARE(importer.mesh3DName(1), "LineMesh"); + CORRADE_COMPARE(importer.mesh3DForName("LineMesh"), 1); + const std::optional data1 = importer.mesh3D(1); + CORRADE_VERIFY(data1); + CORRADE_COMPARE(data1->primitive(), MeshPrimitive::Lines); + CORRADE_COMPARE(data1->positionArrayCount(), 1); + CORRADE_COMPARE(data1->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f} + })); + CORRADE_COMPARE(data1->indices(), (std::vector{ + 0, 1, 1, 0 + })); + + CORRADE_COMPARE(importer.mesh3DName(2), "TriangleMesh"); + CORRADE_COMPARE(importer.mesh3DForName("TriangleMesh"), 2); + const std::optional data2 = importer.mesh3D(2); + CORRADE_VERIFY(data2); + CORRADE_COMPARE(data2->primitive(), MeshPrimitive::Triangles); + CORRADE_COMPARE(data2->positionArrayCount(), 1); + CORRADE_COMPARE(data2->positions(0), (std::vector{ + {0.5f, 2.0f, 3.0f}, + {0.0f, 1.5f, 1.0f}, + {2.0f, 3.0f, 5.5f} + })); + CORRADE_COMPARE(data2->indices(), (std::vector{ + 0, 1, 2, 2, 1, 0 + })); +} + +void ObjImporterTest::unnamedFirstMesh() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "unnamedFirstMesh.obj"))); + CORRADE_COMPARE(importer.mesh3DCount(), 2); + + CORRADE_COMPARE(importer.mesh3DName(0), ""); + CORRADE_COMPARE(importer.mesh3DForName(""), -1); + + CORRADE_COMPARE(importer.mesh3DName(1), "SecondMesh"); + CORRADE_COMPARE(importer.mesh3DForName("SecondMesh"), 1); +} + +void ObjImporterTest::wrongFloat() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); + const Int id = importer.mesh3DForName("WrongFloat"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): error while converting numeric data\n"); +} + +void ObjImporterTest::wrongInteger() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); + const Int id = importer.mesh3DForName("WrongInteger"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): error while converting numeric data\n"); +} + +void ObjImporterTest::unmergedIndexOutOfRange() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); + const Int id = importer.mesh3DForName("PositionIndexOutOfRange"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): index out of range\n"); +} + +void ObjImporterTest::mergedIndexOutOfRange() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); + const Int id = importer.mesh3DForName("TextureIndexOutOfRange"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): index out of range\n"); +} + +void ObjImporterTest::zeroIndex() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumbers.obj"))); + const Int id = importer.mesh3DForName("ZeroIndex"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): index out of range\n"); +} + +void ObjImporterTest::explicitOptionalPositionCoordinate() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "optionalCoordinates.obj"))); + const Int id = importer.mesh3DForName("SupportedPositionW"); + CORRADE_VERIFY(id > -1); + + const std::optional data = importer.mesh3D(id); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {1.5f, 2.0f, 3.0f} + })); +} + +void ObjImporterTest::explicitOptionalTextureCoordinate() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "optionalCoordinates.obj"))); + const Int id = importer.mesh3DForName("SupportedTextureW"); + CORRADE_VERIFY(id > -1); + + const std::optional data = importer.mesh3D(id); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->textureCoords2DArrayCount(), 1); + CORRADE_COMPARE(data->textureCoords2D(0), (std::vector{ + {0.5f, 0.7f} + })); +} + +void ObjImporterTest::unsupportedOptionalPositionCoordinate() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "optionalCoordinates.obj"))); + const Int id = importer.mesh3DForName("UnsupportedPositionW"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): homogeneous coordinates are not supported\n"); +} + +void ObjImporterTest::unsupportedOptionalTextureCoordinate() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "optionalCoordinates.obj"))); + const Int id = importer.mesh3DForName("UnsupportedTextureW"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): 3D texture coordinates are not supported\n"); +} + +void ObjImporterTest::shortFloatData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); + const Int id = importer.mesh3DForName("ShortFloat"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): invalid float array size\n"); +} + +void ObjImporterTest::longFloatData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); + const Int id = importer.mesh3DForName("LongFloat"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): invalid float array size\n"); +} + +void ObjImporterTest::longOptionalFloatData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); + const Int id = importer.mesh3DForName("LongOptionalFloat"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): invalid float array size\n"); +} + +void ObjImporterTest::longIndexData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); + const Int id = importer.mesh3DForName("InvalidIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): invalid index data\n"); +} + +void ObjImporterTest::wrongPointIndexData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); + const Int id = importer.mesh3DForName("WrongPointIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): wrong index count for point\n"); +} + +void ObjImporterTest::wrongLineIndexData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); + const Int id = importer.mesh3DForName("WrongLineIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): wrong index count for line\n"); +} + +void ObjImporterTest::wrongTriangleIndexData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); + const Int id = importer.mesh3DForName("WrongTriangleIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): wrong index count for triangle\n"); +} + +void ObjImporterTest::polygonIndexData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongNumberCount.obj"))); + const Int id = importer.mesh3DForName("PolygonIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): polygons are not supported\n"); +} + +void ObjImporterTest::missingPositionData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); + const Int id = importer.mesh3DForName("MissingPositionData"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete position data\n"); +} + +void ObjImporterTest::missingPositionIndices() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); + const Int id = importer.mesh3DForName("MissingPositionIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete position data\n"); +} + +void ObjImporterTest::missingNormalData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); + const Int id = importer.mesh3DForName("MissingNormalData"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete normal data\n"); +} + +void ObjImporterTest::missingNormalIndices() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); + const Int id = importer.mesh3DForName("MissingNormalIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete normal data\n"); +} + +void ObjImporterTest::missingTextureCoordinateData() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); + const Int id = importer.mesh3DForName("MissingTextureData"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete texture coordinate data\n"); +} + +void ObjImporterTest::missingTextureCoordinateIndices() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "missingData.obj"))); + const Int id = importer.mesh3DForName("MissingTextureIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): incomplete texture coordinate data\n"); +} + +void ObjImporterTest::wrongNormalIndexCount() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongIndexCount.obj"))); + const Int id = importer.mesh3DForName("ShortNormalIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): some normal indices are missing\n"); +} + +void ObjImporterTest::wrongTextureCoordinateIndexCount() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "wrongIndexCount.obj"))); + const Int id = importer.mesh3DForName("ShortTextureIndices"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): some texture coordinate indices are missing\n"); +} + +void ObjImporterTest::unsupportedKeyword() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "keywords.obj"))); + const Int id = importer.mesh3DForName("UnsupportedKeyword"); + CORRADE_VERIFY(id > -1); + + /* Everything should be parsed properly */ + const std::optional data = importer.mesh3D(id); + CORRADE_VERIFY(data); + CORRADE_COMPARE(data->primitive(), MeshPrimitive::Points); + CORRADE_COMPARE(data->positionArrayCount(), 1); + CORRADE_COMPARE(data->positions(0), (std::vector{ + {0.0f, 1.0f, 2.0f} + })); + CORRADE_COMPARE(data->indices(), std::vector{0}); +} + +void ObjImporterTest::unknownKeyword() { + ObjImporter importer; + CORRADE_VERIFY(importer.openFile(Utility::Directory::join(OBJIMPORTER_TEST_DIR, "keywords.obj"))); + const Int id = importer.mesh3DForName("UnknownKeyword"); + CORRADE_VERIFY(id > -1); + + std::ostringstream out; + Error::setOutput(&out); + CORRADE_VERIFY(!importer.mesh3D(id)); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): unknown keyword bleh\n"); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Trade::Test::ObjImporterTest) diff --git a/src/MagnumPlugins/ObjImporter/Test/configure.h.cmake b/src/MagnumPlugins/ObjImporter/Test/configure.h.cmake new file mode 100644 index 000000000..484448999 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/configure.h.cmake @@ -0,0 +1,26 @@ +/* + 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. +*/ + +#define OBJIMPORTER_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}" diff --git a/src/MagnumPlugins/ObjImporter/Test/emptyFile.obj b/src/MagnumPlugins/ObjImporter/Test/emptyFile.obj new file mode 100644 index 000000000..2abea3a74 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/emptyFile.obj @@ -0,0 +1 @@ +# Nothinng to see here diff --git a/src/MagnumPlugins/ObjImporter/Test/keywords.obj b/src/MagnumPlugins/ObjImporter/Test/keywords.obj new file mode 100644 index 000000000..c93dce27f --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/keywords.obj @@ -0,0 +1,7 @@ +o UnsupportedKeyword +g VertexGroup +v 0 1 2 +p 1 + +o UnknownKeyword +bleh diff --git a/src/MagnumPlugins/ObjImporter/Test/lineMesh.obj b/src/MagnumPlugins/ObjImporter/Test/lineMesh.obj new file mode 100644 index 000000000..d6eae8940 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/lineMesh.obj @@ -0,0 +1,8 @@ +# Positions +v 0.5 2 3 +v 0 1.5 1 +v 2 3 5.0 + +# Lines +l 1 2 +l 2 3 diff --git a/src/MagnumPlugins/ObjImporter/Test/missingData.obj b/src/MagnumPlugins/ObjImporter/Test/missingData.obj new file mode 100644 index 000000000..e86b403bc --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/missingData.obj @@ -0,0 +1,23 @@ +o MissingPositionData +p 1 + +o MissingPositionIndices +v 1 2 3 + +o MissingNormalData +v 1 2 3 +p 1//1 + +o MissingNormalIndices +v 1 2 3 +vn 1 2 3 +p 1 + +o MissingTextureData +v 1 2 3 +p 1/1 + +o MissingTextureIndices +v 1 2 3 +vt 1 2 +p 1 diff --git a/src/MagnumPlugins/ObjImporter/Test/mixedPrimitives.obj b/src/MagnumPlugins/ObjImporter/Test/mixedPrimitives.obj new file mode 100644 index 000000000..e4ab55130 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/mixedPrimitives.obj @@ -0,0 +1,13 @@ +# Positions +v 0.5 2 3 +v 0 1.5 1 +v 2 3 5.0 + +# Points +p 1 +p 3 +p 2 + +# Lines +l 1 2 +l 2 3 diff --git a/src/MagnumPlugins/ObjImporter/Test/moreMeshes.obj b/src/MagnumPlugins/ObjImporter/Test/moreMeshes.obj new file mode 100644 index 000000000..256cc06d8 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/moreMeshes.obj @@ -0,0 +1,21 @@ +# Points +o PointMesh +v 0.5 2 3 +v 0 1.5 1 +p 1 +p 2 + +# Lines +o LineMesh +v 0.5 2 3 +v 0 1.5 1 +l 1 2 +l 2 1 + +# Triangles +o TriangleMesh +v 0.5 2 3 +v 0 1.5 1 +v 2 3 5.5 +f 1 2 3 +f 3 2 1 diff --git a/src/MagnumPlugins/ObjImporter/Test/namedMesh.obj b/src/MagnumPlugins/ObjImporter/Test/namedMesh.obj new file mode 100644 index 000000000..16802830f --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/namedMesh.obj @@ -0,0 +1,2 @@ +# Named mesh +o MyMesh diff --git a/src/MagnumPlugins/ObjImporter/Test/normals.obj b/src/MagnumPlugins/ObjImporter/Test/normals.obj new file mode 100644 index 000000000..15711d5ca --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/normals.obj @@ -0,0 +1,12 @@ +# Positions +v 0.5 2 3 +v 0 1.5 1 + +# Normals (don't have to be normalized) +vn 1 0.5 3.5 +vn 0.5 1 0.5 + +# Lines +l 1//1 2//1 +l 1//2 2//2 +l 2//1 1//1 diff --git a/src/MagnumPlugins/ObjImporter/Test/optionalCoordinates.obj b/src/MagnumPlugins/ObjImporter/Test/optionalCoordinates.obj new file mode 100644 index 000000000..6fe88d715 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/optionalCoordinates.obj @@ -0,0 +1,17 @@ +o SupportedPositionW +v 1.5 2 3 1.0 +p 1 + +o SupportedTextureW +v 1.5 2 3 +vt 0.5 0.7 0.0 +p 1/1 + +o UnsupportedPositionW +v 1.5 2 3 0.8 +p 1 + +o UnsupportedTextureW +v 1.5 2 3 +vt 0.5 0.7 0.5 +p 1/1 diff --git a/src/MagnumPlugins/ObjImporter/Test/pointMesh.obj b/src/MagnumPlugins/ObjImporter/Test/pointMesh.obj new file mode 100644 index 000000000..c5991619c --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/pointMesh.obj @@ -0,0 +1,10 @@ +# Positions +v 0.5 2 3 +v 0 1.5 1 +v 2 3 5.0 + +# Points +p 1 +p 3 +p 2 +p 1 diff --git a/src/MagnumPlugins/ObjImporter/Test/textureCoordinates.obj b/src/MagnumPlugins/ObjImporter/Test/textureCoordinates.obj new file mode 100644 index 000000000..ae72e239c --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/textureCoordinates.obj @@ -0,0 +1,12 @@ +# Positions +v 0.5 2 3 +v 0 1.5 1 + +# Texture coordinates +vt 1 0.5 +vt 0.5 1 + +# Lines +l 1/1 2/1 +l 1/2 2/2 +l 2/1 1/1 diff --git a/src/MagnumPlugins/ObjImporter/Test/textureCoordinatesNormals.obj b/src/MagnumPlugins/ObjImporter/Test/textureCoordinatesNormals.obj new file mode 100644 index 000000000..c1750ecb2 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/textureCoordinatesNormals.obj @@ -0,0 +1,17 @@ +# Positions +v 0.5 2 3 +v 0 1.5 1 + +# Texture coordinates +vt 1 0.5 +vt 0.5 1 + +# Normals +vn 1 0.5 3.5 +vn 0.5 1 0.5 + +# Lines +l 1/1/1 2/1/2 +l 1/2/2 2/2/1 +l 2/1/2 1/1/1 +l 2/2/2 1/2/2 diff --git a/src/MagnumPlugins/ObjImporter/Test/triangleMesh.obj b/src/MagnumPlugins/ObjImporter/Test/triangleMesh.obj new file mode 100644 index 000000000..32fb5196b --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/triangleMesh.obj @@ -0,0 +1,9 @@ +# Positions +v 0.5 2 3 +v 0 1.5 1 +v 2 3 5.0 +v 2.5 0 1 + +# Triangles +f 1 2 3 +f 4 2 1 diff --git a/src/MagnumPlugins/ObjImporter/Test/unnamedFirstMesh.obj b/src/MagnumPlugins/ObjImporter/Test/unnamedFirstMesh.obj new file mode 100644 index 000000000..71752c6d9 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/unnamedFirstMesh.obj @@ -0,0 +1,2 @@ +v 1 2 3 +o SecondMesh diff --git a/src/MagnumPlugins/ObjImporter/Test/wrongIndexCount.obj b/src/MagnumPlugins/ObjImporter/Test/wrongIndexCount.obj new file mode 100644 index 000000000..960ef3c10 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/wrongIndexCount.obj @@ -0,0 +1,13 @@ +o ShortNormalIndices +v 1 2 3 +vn 1 2 3 +p 1//1 +p 1 +p 1//1 + +o ShortTextureIndices +v 1 2 3 +vt 1 2 +p 1/1 +p 1 +p 1/1 diff --git a/src/MagnumPlugins/ObjImporter/Test/wrongNumberCount.obj b/src/MagnumPlugins/ObjImporter/Test/wrongNumberCount.obj new file mode 100644 index 000000000..c0797fb47 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/wrongNumberCount.obj @@ -0,0 +1,29 @@ +o ShortFloat +v 0.5 1.0 + +o LongFloat +v 0.5 1 2 +vn 0.5 1.0 2.3 7.4 + +o LongOptionalFloat +v 0.5 1 2 0.0 3.5 + +o InvalidIndices +v 1 2 3 +p 1/1/1/1 + +o WrongPointIndices +v 1 2 3 +p 1 1 + +o WrongLineIndices +v 1 2 3 +l 1 + +o WrongTriangleIndices +v 1 2 3 +f 1 1 + +o PolygonIndices +v 1 2 3 +f 1 1 1 1 diff --git a/src/MagnumPlugins/ObjImporter/Test/wrongNumbers.obj b/src/MagnumPlugins/ObjImporter/Test/wrongNumbers.obj new file mode 100644 index 000000000..c795997c2 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/Test/wrongNumbers.obj @@ -0,0 +1,20 @@ +o WrongFloat +v 1 bleh 2 +p 1 + +o WrongInteger +v 1 0 2 +p bleh + +o PositionIndexOutOfRange +v 1 0 2 +p 2 + +o TextureIndexOutOfRange +v 1 0 2 +vt 0 1 +p 1/2 + +o ZeroIndex +v 1 0 2 +p 0 diff --git a/src/MagnumPlugins/ObjImporter/pluginRegistration.cpp b/src/MagnumPlugins/ObjImporter/pluginRegistration.cpp new file mode 100644 index 000000000..4ded696b1 --- /dev/null +++ b/src/MagnumPlugins/ObjImporter/pluginRegistration.cpp @@ -0,0 +1,29 @@ +/* + 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 "MagnumPlugins/ObjImporter/ObjImporter.h" + +CORRADE_PLUGIN_REGISTER(ObjImporter, Magnum::Trade::ObjImporter, + "cz.mosra.magnum.Trade.AbstractImporter/0.3") From 8ee4d08d8711fc09a1edbe14ad8243c4657defc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Mar 2014 21:24:45 +0100 Subject: [PATCH 051/141] ObjImporter: the indices are actually global to whole file. There just isn't any sane and easily parsable format. --- src/MagnumPlugins/ObjImporter/ObjImporter.cpp | 99 ++++++++++++------- .../ObjImporter/Test/missingData.obj | 8 +- .../ObjImporter/Test/moreMeshes.obj | 18 ++-- .../ObjImporter/Test/optionalCoordinates.obj | 6 +- .../ObjImporter/Test/wrongIndexCount.obj | 6 +- .../ObjImporter/Test/wrongNumberCount.obj | 10 +- .../ObjImporter/Test/wrongNumbers.obj | 6 +- 7 files changed, 96 insertions(+), 57 deletions(-) diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp index 1d223fcae..dbcb66361 100644 --- a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp +++ b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp @@ -43,7 +43,7 @@ namespace Magnum { namespace Trade { struct ObjImporter::File { std::unordered_map meshesForName; std::vector meshNames; - std::vector> meshes; + std::vector> meshes; std::unique_ptr in; }; @@ -115,11 +115,20 @@ void ObjImporter::doOpenData(Containers::ArrayReference dat } void ObjImporter::parseMeshNames() { - bool hasData = false; - std::string name; - std::streampos begin = 0; + /* First mesh starts at the beginning, its indices start from 1. The end + offset will be updated to proper value later. */ + UnsignedInt positionIndexOffset = 1; + UnsignedInt normalIndexOffset = 1; + UnsignedInt textureCoordinateIndexOffset = 1; + _file->meshes.emplace_back(0, 0, positionIndexOffset, normalIndexOffset, textureCoordinateIndexOffset); + + /* The first mesh doesn't have name by default but we might find it later, + so we need to track whether there are any data before first name */ + bool thisIsFirstMeshAndItHasNoData = true; + _file->meshNames.emplace_back(); + while(_file->in->good()) { - /* The previous object ends at the beginning of this line */ + /* The previous object might end at the beginning of this line */ const std::streampos end = _file->in->tellg(); /* Comment line */ @@ -132,31 +141,56 @@ void ObjImporter::parseMeshNames() { std::string keyword; *_file->in >> keyword; - /* Object name */ + /* Mesh name */ if(keyword == "o") { - /* If there was any previous object, this is name of new object, - save the previous one */ - if(hasData) { + std::string name; + std::getline(*_file->in, name); + name = Utility::String::trim(name); + + /* This is the name of first mesh */ + if(thisIsFirstMeshAndItHasNoData) { + thisIsFirstMeshAndItHasNoData = false; + + /* Update its name and add it to name map */ + if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size() - 1); + _file->meshNames.back() = std::move(name); + + /* Update its begin offset to be more precise */ + std::get<0>(_file->meshes.back()) = _file->in->tellg(); + + /* Otherwise this is a name of new mesh */ + } else { + /* Set end of the previous one */ + std::get<1>(_file->meshes.back()) = end; + + /* Save name and offset of the new one. The end offset will be + updated later. */ if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size()); _file->meshNames.emplace_back(std::move(name)); - _file->meshes.emplace_back(begin, end); - - /* Otherwise it's the name of first object (there weren't any data - before) */ - } else hasData = true; + _file->meshes.emplace_back(_file->in->tellg(), 0, positionIndexOffset, textureCoordinateIndexOffset, normalIndexOffset); + } - /* Get name of new object, the object then starts at the next line */ - std::getline(*_file->in, name); - name = Utility::String::trim(name); - begin = _file->in->tellg(); continue; - } - /* If there are any data before the first name, it means that the first - object can be unnamed */ - if(!hasData) for(const std::string& data: {"v", "vt", "vn", "p", "l", "f"}) { + /* If there are any data/indices before the first name, it means that + the first object is unnamed. We need to check for them. */ + + /* Vertex data, update index offset for the following meshes */ + } else if(keyword == "v") { + ++positionIndexOffset; + thisIsFirstMeshAndItHasNoData = false; + } else if(keyword == "vt") { + ++textureCoordinateIndexOffset; + thisIsFirstMeshAndItHasNoData = false; + } else if(keyword == "vn") { + ++normalIndexOffset; + thisIsFirstMeshAndItHasNoData = false; + + /* Index data, just mark that we found something for first unnamed + object */ + } else if(thisIsFirstMeshAndItHasNoData) for(const std::string& data: {"p", "l", "f"}) { if(keyword == data) { - hasData = true; + thisIsFirstMeshAndItHasNoData = false; break; } } @@ -165,12 +199,10 @@ void ObjImporter::parseMeshNames() { ignoreLine(*_file->in); } - /* Add also the last object */ + /* Set end of the last object */ _file->in->clear(); _file->in->seekg(0, std::ios::end); - if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size()); - _file->meshNames.emplace_back(std::move(name)); - _file->meshes.emplace_back(begin, _file->in->tellg()); + std::get<1>(_file->meshes.back()) = _file->in->tellg(); } UnsignedInt ObjImporter::doMesh3DCount() const { return _file->meshes.size(); } @@ -185,9 +217,10 @@ std::string ObjImporter::doMesh3DName(UnsignedInt id) { } std::optional ObjImporter::doMesh3D(UnsignedInt id) { - /* Seek the file */ + /* Seek the file, set mesh parsing parameters */ std::streampos begin, end; - std::tie(begin, end) = _file->meshes[id]; + UnsignedInt positionIndexOffset, textureCoordinateIndexOffset, normalIndexOffset; + std::tie(begin, end, positionIndexOffset, textureCoordinateIndexOffset, normalIndexOffset) = _file->meshes[id]; _file->in->seekg(begin); std::optional primitive; @@ -311,18 +344,16 @@ std::optional ObjImporter::doMesh3D(UnsignedInt id) { return std::nullopt; } - /* Indices in OBJ file start from 1 */ - /* Position indices */ - positionIndices.push_back(std::stoul(indices[0])-1); + positionIndices.push_back(std::stoul(indices[0]) - positionIndexOffset); /* Texture coordinates */ if(indices.size() == 2 || (indices.size() == 3 && !indices[1].empty())) - textureCoordinateIndices.push_back(std::stoul(indices[1])-1); + textureCoordinateIndices.push_back(std::stoul(indices[1]) - textureCoordinateIndexOffset); /* Normal indices */ if(indices.size() == 3) - normalIndices.push_back(std::stoul(indices[2])-1); + normalIndices.push_back(std::stoul(indices[2]) - normalIndexOffset); } /* Ignore unsupported keywords, error out on unknown keywords */ diff --git a/src/MagnumPlugins/ObjImporter/Test/missingData.obj b/src/MagnumPlugins/ObjImporter/Test/missingData.obj index e86b403bc..554d520b9 100644 --- a/src/MagnumPlugins/ObjImporter/Test/missingData.obj +++ b/src/MagnumPlugins/ObjImporter/Test/missingData.obj @@ -6,18 +6,18 @@ v 1 2 3 o MissingNormalData v 1 2 3 -p 1//1 +p 3//3 o MissingNormalIndices v 1 2 3 vn 1 2 3 -p 1 +p 4 o MissingTextureData v 1 2 3 -p 1/1 +p 5/1 o MissingTextureIndices v 1 2 3 vt 1 2 -p 1 +p 6 diff --git a/src/MagnumPlugins/ObjImporter/Test/moreMeshes.obj b/src/MagnumPlugins/ObjImporter/Test/moreMeshes.obj index 256cc06d8..e4820d5b9 100644 --- a/src/MagnumPlugins/ObjImporter/Test/moreMeshes.obj +++ b/src/MagnumPlugins/ObjImporter/Test/moreMeshes.obj @@ -2,20 +2,26 @@ o PointMesh v 0.5 2 3 v 0 1.5 1 -p 1 -p 2 +vn 0.5 2 3 +vn 0 1.5 1 +p 1//1 +p 2//2 # Lines o LineMesh v 0.5 2 3 v 0 1.5 1 -l 1 2 -l 2 1 +vt 0.5 2 +vt 0 1.5 +l 3/1 4/2 +l 4/2 3/1 # Triangles o TriangleMesh v 0.5 2 3 v 0 1.5 1 v 2 3 5.5 -f 1 2 3 -f 3 2 1 +vt 0.5 2 +vn 0.5 2 3 +f 5/3/3 6/3/3 7/3/3 +f 7/3/3 6/3/3 5/3/3 diff --git a/src/MagnumPlugins/ObjImporter/Test/optionalCoordinates.obj b/src/MagnumPlugins/ObjImporter/Test/optionalCoordinates.obj index 6fe88d715..7e9132465 100644 --- a/src/MagnumPlugins/ObjImporter/Test/optionalCoordinates.obj +++ b/src/MagnumPlugins/ObjImporter/Test/optionalCoordinates.obj @@ -5,13 +5,13 @@ p 1 o SupportedTextureW v 1.5 2 3 vt 0.5 0.7 0.0 -p 1/1 +p 2/1 o UnsupportedPositionW v 1.5 2 3 0.8 -p 1 +p 3 o UnsupportedTextureW v 1.5 2 3 vt 0.5 0.7 0.5 -p 1/1 +p 4/2 diff --git a/src/MagnumPlugins/ObjImporter/Test/wrongIndexCount.obj b/src/MagnumPlugins/ObjImporter/Test/wrongIndexCount.obj index 960ef3c10..0a98d1573 100644 --- a/src/MagnumPlugins/ObjImporter/Test/wrongIndexCount.obj +++ b/src/MagnumPlugins/ObjImporter/Test/wrongIndexCount.obj @@ -8,6 +8,6 @@ p 1//1 o ShortTextureIndices v 1 2 3 vt 1 2 -p 1/1 -p 1 -p 1/1 +p 2/2 +p 2 +p 2/2 diff --git a/src/MagnumPlugins/ObjImporter/Test/wrongNumberCount.obj b/src/MagnumPlugins/ObjImporter/Test/wrongNumberCount.obj index c0797fb47..4bfab647f 100644 --- a/src/MagnumPlugins/ObjImporter/Test/wrongNumberCount.obj +++ b/src/MagnumPlugins/ObjImporter/Test/wrongNumberCount.obj @@ -10,20 +10,20 @@ v 0.5 1 2 0.0 3.5 o InvalidIndices v 1 2 3 -p 1/1/1/1 +p 4/1/1/1 o WrongPointIndices v 1 2 3 -p 1 1 +p 5 5 o WrongLineIndices v 1 2 3 -l 1 +l 6 o WrongTriangleIndices v 1 2 3 -f 1 1 +f 7 7 o PolygonIndices v 1 2 3 -f 1 1 1 1 +f 8 8 8 8 diff --git a/src/MagnumPlugins/ObjImporter/Test/wrongNumbers.obj b/src/MagnumPlugins/ObjImporter/Test/wrongNumbers.obj index c795997c2..ce6589a05 100644 --- a/src/MagnumPlugins/ObjImporter/Test/wrongNumbers.obj +++ b/src/MagnumPlugins/ObjImporter/Test/wrongNumbers.obj @@ -8,12 +8,14 @@ p bleh o PositionIndexOutOfRange v 1 0 2 -p 2 +# Should be 3 +p 1 o TextureIndexOutOfRange v 1 0 2 vt 0 1 -p 1/2 +# Should be 4/1 +p 4/2 o ZeroIndex v 1 0 2 From 1b2edafcecdf59450c6c3df834aeaa9ceaedb203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 4 Mar 2014 21:25:58 +0100 Subject: [PATCH 052/141] WavAudioImporter: use PIC only when needed. Also we don't export anything, so no need for -D*_EXPORTS definition. --- src/MagnumPlugins/WavAudioImporter/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt b/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt index cf984a9f9..7f04461cc 100644 --- a/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt +++ b/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt @@ -35,7 +35,9 @@ set(WavAudioImporter_HEADERS WavImporter.h) add_library(WavAudioImporterObjects OBJECT ${WavAudioImporter_SRCS}) -set_target_properties(WavAudioImporterObjects PROPERTIES COMPILE_FLAGS "-DWavAudioImporterObjects_EXPORTS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") +if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) + set_target_properties(WavAudioImporterObjects PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") +endif() add_plugin(WavAudioImporter ${MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR} WavAudioImporter.conf From aaa6d2e2b16fb42fdb40c5ff146c7f672e37fd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 5 Mar 2014 15:30:50 +0100 Subject: [PATCH 053/141] Fixed PrimitiveQuery documentation. Somehow this slipped through when splitting out the timer functions into TimeQuery in 5f00a1926daa0092b11e36f7496414bc8b3665ae (a year ago!). --- src/Magnum/Query.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Query.h b/src/Magnum/Query.h index 3a55772f3..db978053f 100644 --- a/src/Magnum/Query.h +++ b/src/Magnum/Query.h @@ -153,10 +153,10 @@ template<> Long MAGNUM_EXPORT AbstractQuery::result(); #ifndef MAGNUM_TARGET_GLES2 /** -@brief Query for primitives and elapsed time +@brief Query for primitives Queries count of generated primitives from vertex shader, geometry shader or -transform feedback and elapsed time. Example usage: +transform feedback. Example usage: @code PrimitiveQuery q; From b666044a47e366133919bab8fc956eacfa59c3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 11:31:40 +0100 Subject: [PATCH 054/141] Actually make use of Color[34]ub typedefs. --- doc/matrix-vector.dox | 8 ++++---- src/Magnum/MeshTools/Interleave.h | 4 ++-- src/Magnum/Test/ColorTest.cpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/matrix-vector.dox b/doc/matrix-vector.dox index 595cc43bc..3b2739cb7 100644 --- a/doc/matrix-vector.dox +++ b/doc/matrix-vector.dox @@ -77,8 +77,8 @@ Vector3i b; // zero-filled Matrix3 identity; // diagonal set to 1 Matrix3 zero(Matrix::Zero); // zero-filled -Color4 black1; // {0.0f, 0.0f, 0.0f, 1.0f} -BasicColor4 black2; // {0, 0, 0, 255} +Color4 black1; // {0.0f, 0.0f, 0.0f, 1.0f} +Color4ub black2; // {0, 0, 0, 255} @endcode Most common and most efficient way to create vector is to pass all values to @@ -193,8 +193,8 @@ In %Magnum all mulitplication/division operations involving integral vectors will have integral result, you need to convert both arguments to the same floating-point type to have floating-point result. @code -BasicColor3 color(80, 116, 34); -BasicColor3 lighter = color*1.5f; // lighter = {120, 174, 51} +Color3ub color(80, 116, 34); +Color3ub lighter = color*1.5f; // lighter = {120, 174, 51} Vector3i a(4, 18, -90); Vector3 multiplier(2.2f, 0.25f, 0.1f); diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 69879f1f6..8b572c7eb 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -155,8 +155,8 @@ It's often desirable to align data for one vertex on 32bit boundaries. To achieve that, you can specify gaps between the attributes: @code std::vector positions; -std::vector weights; -std::vector> vertexColors; +std::vector weights; +std::vector vertexColors; std::size_t attributeCount; std::size_t stride; Containers::Array data; diff --git a/src/Magnum/Test/ColorTest.cpp b/src/Magnum/Test/ColorTest.cpp index fdf75ea8e..933602990 100644 --- a/src/Magnum/Test/ColorTest.cpp +++ b/src/Magnum/Test/ColorTest.cpp @@ -289,19 +289,19 @@ void ColorTest::hsvAlpha() { void ColorTest::swizzleType() { constexpr Color3 origColor3; - constexpr BasicColor4 origColor4; + constexpr Color4ub origColor4; constexpr auto a = Math::swizzle<'y', 'z', 'r'>(origColor3); CORRADE_VERIFY((std::is_same::value)); constexpr auto b = Math::swizzle<'y', 'z', 'a'>(origColor4); - CORRADE_VERIFY((std::is_same>::value)); + CORRADE_VERIFY((std::is_same::value)); constexpr auto c = Math::swizzle<'y', 'z', 'y', 'x'>(origColor3); CORRADE_VERIFY((std::is_same::value)); constexpr auto d = Math::swizzle<'y', 'a', 'y', 'x'>(origColor4); - CORRADE_VERIFY((std::is_same>::value)); + CORRADE_VERIFY((std::is_same::value)); } void ColorTest::debug() { From 06b350871993e08cc31124faca76baaf86e158bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 12:44:17 +0100 Subject: [PATCH 055/141] MeshTools: refactored implementation of interleave(). Everything are now pure functions, no shared state, no useless functor class wrapping. Still needed to wrap attribute count and stride computation functions in struct to make proper overload resolution working without the need to deinline the functions (they have cyclic dependencies). --- src/Magnum/MeshTools/Interleave.h | 181 +++++++++---------- src/Magnum/MeshTools/Test/InterleaveTest.cpp | 16 +- 2 files changed, 93 insertions(+), 104 deletions(-) diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 8b572c7eb..43fccbb4b 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -41,94 +41,58 @@ namespace Magnum { namespace MeshTools { namespace Implementation { -class Interleave { - public: - Interleave(): _attributeCount(0), _stride(0) {} - - template std::tuple> operator()(const T&... attributes) { - /* Compute buffer size and stride */ - _attributeCount = attributeCount(attributes...); - Containers::Array data; - if(_attributeCount && _attributeCount != ~std::size_t(0)) { - _stride = stride(attributes...); - - /* Create output buffer */ - data = Containers::Array(_attributeCount*_stride); - - /* Save the data */ - write(data.begin(), attributes...); - } - - return std::make_tuple(_attributeCount, _stride, std::move(data)); - } - - template void operator()(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) { - Containers::Array data; - std::tie(std::ignore, std::ignore, data) = operator()(attributes...); - - mesh.setVertexCount(_attributeCount); - buffer.setData(data, usage); - } - - /* Specialization for only one attribute array */ - template typename std::enable_if::value, void>::type operator()(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) { - mesh.setVertexCount(attribute.size()); - buffer.setData(attribute, usage); - } - - template static typename std::enable_if::value, std::size_t>::type attributeCount(const T& first, const U&... next) { - CORRADE_ASSERT(sizeof...(next) == 0 || attributeCount(next...) == first.size() || attributeCount(next...) == ~std::size_t(0), "MeshTools::interleave(): attribute arrays don't have the same length, expected" << first.size() << "but got" << attributeCount(next...), 0); - - return first.size(); - } - - template static std::size_t attributeCount(std::size_t, const T&... next) { - return attributeCount(next...); - } - - template static std::size_t attributeCount(std::size_t) { - return ~std::size_t(0); - } - - template static typename std::enable_if::value, std::size_t>::type stride(const T&, const U&... next) { - return sizeof(typename T::value_type) + stride(next...); - } - - template static std::size_t stride(std::size_t gap, const T&... next) { - return gap + stride(next...); - } - - private: - template void write(char* startingOffset, const T& first, const U&... next) { - write(startingOffset+writeOne(startingOffset, first), next...); - } - - /* Copy data to the buffer */ - template typename std::enable_if::value, std::size_t>::type writeOne(char* startingOffset, const T& attributeList) { - auto it = attributeList.begin(); - for(std::size_t i = 0; i != _attributeCount; ++i, ++it) - std::memcpy(startingOffset+i*_stride, reinterpret_cast(&*it), sizeof(typename T::value_type)); - - return sizeof(typename T::value_type); - } - - /* Fill gap with zeros */ - std::size_t writeOne(char* startingOffset, std::size_t gap) { - for(std::size_t i = 0; i != _attributeCount; ++i) - std::memset(startingOffset+i*_stride, 0, gap); - - return gap; - } - - /* Terminator functions for recursive calls */ - static std::size_t attributeCount() { return 0; } - static std::size_t stride() { return 0; } - void write(char*) {} - - std::size_t _attributeCount; - std::size_t _stride; +/* Attribute count, skipping gaps. If the attributes are just gaps, returns + ~std::size_t{0}. It must be in the structure to have proper overload + resolution (the functions would otherwise need to be de-inlined to break + cyclic dependencies) */ +struct AttributeCount { + template typename std::enable_if::value, std::size_t>::type operator()(const T& first, const U&... next) { + CORRADE_ASSERT(sizeof...(next) == 0 || AttributeCount{}(next...) == first.size() || AttributeCount{}(next...) == ~std::size_t(0), "MeshTools::interleave(): attribute arrays don't have the same length, expected" << first.size() << "but got" << AttributeCount{}(next...), 0); + + return first.size(); + } + template std::size_t operator()(std::size_t, const T& first, const U&... next) { + return AttributeCount{}(first, next...); + } + constexpr std::size_t operator()(std::size_t) { return ~std::size_t(0); } + constexpr std::size_t operator()() { return 0; } }; +/* Stride, taking gaps into account. It must be in the structure, same reason + as above */ +struct Stride { + template typename std::enable_if::value, std::size_t>::type operator()(const T&, const U&... next) { + return sizeof(typename T::value_type) + Stride{}(next...); + } + template std::size_t operator()(std::size_t gap, const T&... next) { + return gap + Stride{}(next...); + } + constexpr std::size_t operator()() { return 0; } +}; + +/* Copy data to the buffer */ +template typename std::enable_if::value, std::size_t>::type writeOneInterleaved(std::size_t attributeCount, std::size_t stride, char* startingOffset, const T& attributeList) { + auto it = attributeList.begin(); + for(std::size_t i = 0; i != attributeCount; ++i, ++it) + std::memcpy(startingOffset + i*stride, reinterpret_cast(&*it), sizeof(typename T::value_type)); + + return sizeof(typename T::value_type); +} + +/* Fill gap with zeros */ +inline std::size_t writeOneInterleaved(std::size_t attributeCount, std::size_t stride, char* startingOffset, std::size_t gap) { + for(std::size_t i = 0; i != attributeCount; ++i) + std::memset(startingOffset + i*stride, 0, gap); + + return gap; +} + +/* Write interleaved data */ +inline void writeInterleaved(std::size_t, std::size_t, char*) {} +template void writeInterleaved(std::size_t attributeCount, std::size_t stride, char* startingOffset, const T& first, const U&... next) { + writeInterleaved(attributeCount, stride, startingOffset + writeOneInterleaved(attributeCount, stride, startingOffset, first), next...); +} + } /** @@ -176,12 +140,24 @@ See also @ref interleave(Mesh&, Buffer&, BufferUsage, const T&...), which writes the interleaved array directly into buffer of given mesh. */ /* enable_if to avoid clash with overloaded function below */ -template inline typename std::enable_if::value, std::tuple>>::type interleave(const T& first, const U&... next) { - return Implementation::Interleave()(first, next...); +template typename std::enable_if::value, std::tuple>>::type interleave(const T& first, const U&... next) { + /* Compute buffer size and stride */ + const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); + const std::size_t stride = Implementation::Stride{}(first, next...); + if(attributeCount && attributeCount != ~std::size_t(0)) { + + /* Create output buffer */ + Containers::Array data = Containers::Array(attributeCount*stride); + + /* Save the data */ + Implementation::writeInterleaved(attributeCount, stride, data.begin(), first, next...); + return std::make_tuple(attributeCount, stride, std::move(data)); + + } else return std::make_tuple(0, stride, nullptr); } /** -@brief %Interleave vertex attributes and write them to array buffer +@brief %Interleave vertex attributes, write them to array buffer and configure the mesh @param mesh Output mesh @param buffer Output vertex buffer @param usage Vertex buffer usage @@ -194,18 +170,31 @@ so you don't have to call @ref Mesh::setVertexCount() on your own. @attention You still must call @ref Mesh::setPrimitive() and @ref Mesh::addVertexBuffer() on the mesh afterwards. -For only one attribute array this function is convenient equivalent to the -following, without any performance loss: +@see @ref compressIndices(), @ref compile() +@todo rework so Mesh & Buffer doesn't need to be included in header +*/ +template void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) { + Containers::Array data; + std::size_t attributeCount; + std::tie(attributeCount, std::ignore, data) = interleave(attributes...); + + mesh.setVertexCount(attributeCount); + buffer.setData(data, usage); +} + +/** +@brief Write vertex attribute to array buffer and configure the mesh + +Simplified specialization of the above function for only one attribute array, +equivalent to the following: @code buffer.setData(attribute, usage); mesh.setVertexCount(attribute.size()); @endcode - -@see @ref MeshTools::compressIndices() -@todo rework so Mesh & Buffer doesn't need to be included in header */ -template inline void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) { - return Implementation::Interleave()(mesh, buffer, usage, attributes...); +template typename std::enable_if::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) { + mesh.setVertexCount(attribute.size()); + buffer.setData(attribute, usage); } }} diff --git a/src/Magnum/MeshTools/Test/InterleaveTest.cpp b/src/Magnum/MeshTools/Test/InterleaveTest.cpp index 00ec10389..55ad00b4b 100644 --- a/src/Magnum/MeshTools/Test/InterleaveTest.cpp +++ b/src/Magnum/MeshTools/Test/InterleaveTest.cpp @@ -56,30 +56,30 @@ InterleaveTest::InterleaveTest() { void InterleaveTest::attributeCount() { std::stringstream ss; Error::setOutput(&ss); - CORRADE_COMPARE((Implementation::Interleave::attributeCount(std::vector{0, 1, 2}, + CORRADE_COMPARE((Implementation::AttributeCount{}(std::vector{0, 1, 2}, std::vector{0, 1, 2, 3, 4, 5})), std::size_t(0)); CORRADE_COMPARE(ss.str(), "MeshTools::interleave(): attribute arrays don't have the same length, expected 3 but got 6\n"); - CORRADE_COMPARE((Implementation::Interleave::attributeCount(std::vector{0, 1, 2}, + CORRADE_COMPARE((Implementation::AttributeCount{}(std::vector{0, 1, 2}, std::vector{3, 4, 5})), std::size_t(3)); } void InterleaveTest::attributeCountGaps() { - CORRADE_COMPARE((Implementation::Interleave::attributeCount(std::vector{0, 1, 2}, 3, + CORRADE_COMPARE((Implementation::AttributeCount{}(std::vector{0, 1, 2}, 3, std::vector{3, 4, 5}, 5)), std::size_t(3)); /* No arrays from which to get size */ - CORRADE_COMPARE(Implementation::Interleave::attributeCount(3, 5), ~std::size_t(0)); + CORRADE_COMPARE(Implementation::AttributeCount{}(3, 5), ~std::size_t(0)); } void InterleaveTest::stride() { - CORRADE_COMPARE(Implementation::Interleave::stride(std::vector()), std::size_t(1)); - CORRADE_COMPARE(Implementation::Interleave::stride(std::vector()), std::size_t(4)); - CORRADE_COMPARE((Implementation::Interleave::stride(std::vector(), std::vector())), std::size_t(5)); + CORRADE_COMPARE(Implementation::Stride{}(std::vector()), std::size_t(1)); + CORRADE_COMPARE(Implementation::Stride{}(std::vector()), std::size_t(4)); + CORRADE_COMPARE((Implementation::Stride{}(std::vector(), std::vector())), std::size_t(5)); } void InterleaveTest::strideGaps() { - CORRADE_COMPARE((Implementation::Interleave::stride(2, std::vector(), 1, std::vector(), 12)), std::size_t(20)); + CORRADE_COMPARE((Implementation::Stride{}(2, std::vector(), 1, std::vector(), 12)), std::size_t(20)); } void InterleaveTest::write() { From 4fe1ecd4478bd5223bd218bbbff5fd874926ec97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 13:11:05 +0100 Subject: [PATCH 056/141] MeshTools: use zero-initialized array in interleave(). Surely is faster than calling std::memset for every zero byte. --- src/Magnum/MeshTools/Interleave.h | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 43fccbb4b..0c7412dd1 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -71,26 +71,21 @@ struct Stride { }; /* Copy data to the buffer */ -template typename std::enable_if::value, std::size_t>::type writeOneInterleaved(std::size_t attributeCount, std::size_t stride, char* startingOffset, const T& attributeList) { +template typename std::enable_if::value, std::size_t>::type writeOneInterleaved(std::size_t stride, char* startingOffset, const T& attributeList) { auto it = attributeList.begin(); - for(std::size_t i = 0; i != attributeCount; ++i, ++it) + for(std::size_t i = 0; i != attributeList.size(); ++i, ++it) std::memcpy(startingOffset + i*stride, reinterpret_cast(&*it), sizeof(typename T::value_type)); return sizeof(typename T::value_type); } -/* Fill gap with zeros */ -inline std::size_t writeOneInterleaved(std::size_t attributeCount, std::size_t stride, char* startingOffset, std::size_t gap) { - for(std::size_t i = 0; i != attributeCount; ++i) - std::memset(startingOffset + i*stride, 0, gap); - - return gap; -} +/* Skip gap */ +inline constexpr std::size_t writeOneInterleaved(std::size_t, char*, std::size_t gap) { return gap; } /* Write interleaved data */ -inline void writeInterleaved(std::size_t, std::size_t, char*) {} -template void writeInterleaved(std::size_t attributeCount, std::size_t stride, char* startingOffset, const T& first, const U&... next) { - writeInterleaved(attributeCount, stride, startingOffset + writeOneInterleaved(attributeCount, stride, startingOffset, first), next...); +inline void writeInterleaved(std::size_t, char*) {} +template void writeInterleaved(std::size_t stride, char* startingOffset, const T& first, const U&... next) { + writeInterleaved(stride, startingOffset + writeOneInterleaved(stride, startingOffset, first), next...); } } @@ -144,15 +139,15 @@ template typename std::enable_if::va /* Compute buffer size and stride */ const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); const std::size_t stride = Implementation::Stride{}(first, next...); - if(attributeCount && attributeCount != ~std::size_t(0)) { - /* Create output buffer */ - Containers::Array data = Containers::Array(attributeCount*stride); + /* Create output buffer only if we have some attributes */ + if(attributeCount && attributeCount != ~std::size_t(0)) { + Containers::Array data = Containers::Array::zeroInitialized(attributeCount*stride); + Implementation::writeInterleaved(stride, data.begin(), first, next...); - /* Save the data */ - Implementation::writeInterleaved(attributeCount, stride, data.begin(), first, next...); return std::make_tuple(attributeCount, stride, std::move(data)); + /* Otherwise return nullptr */ } else return std::make_tuple(0, stride, nullptr); } From dc4f667f7b1af7e936ef9911863a90b70d917cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:37:32 +0100 Subject: [PATCH 057/141] MeshTools: added interleaveInto(). Basically a version of interleave() which takes existing buffer instead of creating new zero-initialized one. The last bit needed for real runtime usage. --- src/Magnum/MeshTools/Interleave.h | 34 ++++++++++++++-- src/Magnum/MeshTools/Test/InterleaveTest.cpp | 41 +++++++++++++++++++- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 0c7412dd1..0c7d10b3f 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Function @ref Magnum::MeshTools::interleave() + * @brief Function @ref Magnum::MeshTools::interleave(), @ref Magnum::MeshTools::interleaveInto() */ #include @@ -121,8 +121,8 @@ std::size_t stride; Containers::Array data; std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1); @endcode -This way vertex stride is 24 bytes, without gaps it would be 21 bytes, causing -possible performance loss. +All gap bytes are set zero. This way vertex stride is 24 bytes, without gaps it +would be 21 bytes, causing possible performance loss. @attention The function expects that all arrays have the same size. @@ -132,7 +132,9 @@ possible performance loss. will be `std::vector` or `std::array`. See also @ref interleave(Mesh&, Buffer&, BufferUsage, const T&...), -which writes the interleaved array directly into buffer of given mesh. +which writes the interleaved array directly into buffer of given mesh or +@ref interleaveInto() which writes the data into existing buffer instead of +creating new one. */ /* enable_if to avoid clash with overloaded function below */ template typename std::enable_if::value, std::tuple>>::type interleave(const T& first, const U&... next) { @@ -151,6 +153,30 @@ template typename std::enable_if::va } else return std::make_tuple(0, stride, nullptr); } +/** +@brief %Interleave vertex attributes into existing buffer + +Unlike @ref interleave() this function interleaves the data into existing +buffer and leaves gaps untouched instead of zero-initializing them. This +function can thus be used for interleaving data depending on runtime +parameters. + +@attention Similarly to @ref interleave(), this function expects that all + arrays have the same size. The passed buffer must also be large enough to + contain the interleaved data. +*/ +template std::tuple interleaveInto(Containers::ArrayReference buffer, const T& first, const U&... next) { + /* Verify expected buffer size */ + const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); + const std::size_t stride = Implementation::Stride{}(first, next...); + CORRADE_ASSERT(attributeCount*stride <= buffer.size(), "MeshTools::interleaveInto(): the data buffer is too small, expected" << attributeCount*stride << "but got" << buffer.size(), {}); + + /* Write data */ + Implementation::writeInterleaved(stride, buffer.begin(), first, next...); + + return std::make_tuple(attributeCount, stride); +} + /** @brief %Interleave vertex attributes, write them to array buffer and configure the mesh @param mesh Output mesh diff --git a/src/Magnum/MeshTools/Test/InterleaveTest.cpp b/src/Magnum/MeshTools/Test/InterleaveTest.cpp index 55ad00b4b..a4f43878e 100644 --- a/src/Magnum/MeshTools/Test/InterleaveTest.cpp +++ b/src/Magnum/MeshTools/Test/InterleaveTest.cpp @@ -42,6 +42,8 @@ class InterleaveTest: public Corrade::TestSuite::Tester { void strideGaps(); void write(); void writeGaps(); + + void interleaveInto(); }; InterleaveTest::InterleaveTest() { @@ -50,7 +52,9 @@ InterleaveTest::InterleaveTest() { &InterleaveTest::stride, &InterleaveTest::strideGaps, &InterleaveTest::write, - &InterleaveTest::writeGaps}); + &InterleaveTest::writeGaps, + + &InterleaveTest::interleaveInto}); } void InterleaveTest::attributeCount() { @@ -137,6 +141,41 @@ void InterleaveTest::writeGaps() { } } +void InterleaveTest::interleaveInto() { + std::size_t attributeCount; + std::size_t stride; + auto data = Containers::Array::from( + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77 + ); + + std::tie(attributeCount, stride) = MeshTools::interleaveInto(data, + 2, std::vector{4, 5, 6, 7}, 1, std::vector{0, 1, 2, 3}, 3); + + CORRADE_COMPARE(attributeCount, std::size_t{4}); + CORRADE_COMPARE(stride, std::size_t{12}); + + if(!Utility::Endianness::isBigEndian()) { + /* _______gap, int___________________, _gap, short_____, _____________gap */ + CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ + 0x11, 0x33, 0x04, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x05, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x06, 0x00, 0x00, 0x00, 0x55, 0x02, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x07, 0x00, 0x00, 0x00, 0x55, 0x03, 0x00, 0x33, 0x55, 0x77 + })); + } else { + /* _______gap, ___________________int, _gap, _____short, _____________gap */ + CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ + 0x11, 0x33, 0x00, 0x00, 0x00, 0x04, 0x55, 0x00, 0x00, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x05, 0x55, 0x00, 0x01, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x06, 0x55, 0x00, 0x02, 0x33, 0x55, 0x77, + 0x11, 0x33, 0x00, 0x00, 0x00, 0x07, 0x55, 0x00, 0x03, 0x33, 0x55, 0x77 + })); + } +} + }}} CORRADE_TEST_MAIN(Magnum::MeshTools::Test::InterleaveTest) From 6dfd6d4ddbcc60ef99fdbdcb968c0f2a8c927128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:10:33 +0100 Subject: [PATCH 058/141] Why the heck did I leave inline here? --- src/Magnum/Mesh.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 87b6e25c6..6afd3441d 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -682,28 +682,28 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #endif /* Computing stride of interleaved vertex attributes */ - template inline static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute& attribute, const U&... attributes) { + template static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute& attribute, const U&... attributes) { return attribute.vectorSize()*AbstractShaderProgram::Attribute::VectorCount + strideOfInterleaved(attributes...); } - template inline static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) { + template static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) { return gap + strideOfInterleaved(attributes...); } - inline static GLsizei strideOfInterleaved() { return 0; } + static GLsizei strideOfInterleaved() { return 0; } /* Adding interleaved vertex attributes */ - template inline void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute& attribute, const U&... attributes) { + template void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute& attribute, const U&... attributes) { addVertexAttribute(buffer, attribute, offset, stride); /* Add size of this attribute to offset for next attribute */ addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute::VectorCount, stride, attributes...); } - template inline void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) { + template void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) { /* Add the gap to offset for next attribute */ addVertexBufferInternal(buffer, offset+gap, stride, attributes...); } - inline void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {} + void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {} - template inline void addVertexAttribute(typename std::enable_if::Type, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::Type, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) attributePointerInternal(Attribute{ &buffer, @@ -717,7 +717,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { } #ifndef MAGNUM_TARGET_GLES2 - template inline void addVertexAttribute(typename std::enable_if::Type>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::Type>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { attributePointerInternal(IntegerAttribute{ &buffer, location, @@ -729,7 +729,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { } #ifndef MAGNUM_TARGET_GLES - template inline void addVertexAttribute(typename std::enable_if::Type, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::Type, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) attributePointerInternal(LongAttribute{ &buffer, From 980503a5092ae465cc44566aaa2bf537cbdd5a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:20:00 +0100 Subject: [PATCH 059/141] Renamed AbstractShaderProgram::Attribute::Type to ScalarType. In all other places (e.g. Math, SceneGraph), SomeClass::Type is always T. I spent twenty minutes figuring out what went wrong, so better have this consistent. Also update the test to check for these, as they apparently were tested only indirectly through the MeshGLTest. --- src/Magnum/AbstractShaderProgram.h | 18 +++++++++--------- src/Magnum/Mesh.h | 6 +++--- src/Magnum/Test/AbstractShaderProgramTest.cpp | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 4dc6409a8..a4e9d9276 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -960,12 +960,12 @@ template class AbstractShaderProgram::Attribute { }; /** - * @brief Type + * @brief Scalar type * - * Type used in shader code. - * @see @ref DataType + * The underlying scalar type of the attribute. + * @see @ref Type, @ref DataType */ - typedef typename Implementation::Attribute::Type Type; + typedef typename Implementation::Attribute::ScalarType ScalarType; /** * @brief Component count @@ -1222,7 +1222,7 @@ template struct Attribute; /* Base for float attributes */ struct FloatAttribute { - typedef Float Type; + typedef Float ScalarType; enum class DataType: GLenum { UnsignedByte = GL_UNSIGNED_BYTE, @@ -1260,7 +1260,7 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, FloatAttribute::DataType value); #ifndef MAGNUM_TARGET_GLES2 /* Base for int attributes */ struct IntAttribute { - typedef Int Type; + typedef Int ScalarType; enum class DataType: GLenum { UnsignedByte = GL_UNSIGNED_BYTE, @@ -1282,7 +1282,7 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value); /* Base for unsigned int attributes */ struct UnsignedIntAttribute { - typedef UnsignedInt Type; + typedef UnsignedInt ScalarType; typedef IntAttribute::DataType DataType; constexpr static DataType DefaultDataType = DataType::UnsignedInt; @@ -1299,7 +1299,7 @@ struct UnsignedIntAttribute { #ifndef MAGNUM_TARGET_GLES /* Base for double attributes */ struct DoubleAttribute { - typedef Double Type; + typedef Double ScalarType; enum class DataType: GLenum { Double = GL_DOUBLE @@ -1317,7 +1317,7 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value); /* Floating-point four-component vector is absolutely special case */ template<> struct Attribute> { - typedef Float Type; + typedef Float ScalarType; enum class Components: GLint { One = 1, diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 6afd3441d..692b1940b 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -703,7 +703,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { } void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {} - template void addVertexAttribute(typename std::enable_if::Type, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) attributePointerInternal(Attribute{ &buffer, @@ -717,7 +717,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { } #ifndef MAGNUM_TARGET_GLES2 - template void addVertexAttribute(typename std::enable_if::Type>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { attributePointerInternal(IntegerAttribute{ &buffer, location, @@ -729,7 +729,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { } #ifndef MAGNUM_TARGET_GLES - template void addVertexAttribute(typename std::enable_if::Type, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) attributePointerInternal(LongAttribute{ &buffer, diff --git a/src/Magnum/Test/AbstractShaderProgramTest.cpp b/src/Magnum/Test/AbstractShaderProgramTest.cpp index 325e7d561..77317bf1c 100644 --- a/src/Magnum/Test/AbstractShaderProgramTest.cpp +++ b/src/Magnum/Test/AbstractShaderProgramTest.cpp @@ -76,6 +76,7 @@ AbstractShaderProgramTest::AbstractShaderProgramTest() { void AbstractShaderProgramTest::attributeScalar() { typedef AbstractShaderProgram::Attribute<3, Float> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::Location, 3); CORRADE_COMPARE(Attribute::VectorCount, 1); @@ -95,6 +96,7 @@ void AbstractShaderProgramTest::attributeScalar() { void AbstractShaderProgramTest::attributeScalarInt() { #ifndef MAGNUM_TARGET_GLES2 typedef AbstractShaderProgram::Attribute<3, Int> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ @@ -112,6 +114,7 @@ void AbstractShaderProgramTest::attributeScalarInt() { void AbstractShaderProgramTest::attributeScalarUnsignedInt() { #ifndef MAGNUM_TARGET_GLES2 typedef AbstractShaderProgram::Attribute<3, UnsignedInt> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ @@ -129,6 +132,7 @@ void AbstractShaderProgramTest::attributeScalarUnsignedInt() { void AbstractShaderProgramTest::attributeScalarDouble() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Double> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ @@ -141,6 +145,7 @@ void AbstractShaderProgramTest::attributeScalarDouble() { void AbstractShaderProgramTest::attributeVector() { typedef AbstractShaderProgram::Attribute<3, Vector3> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ @@ -164,6 +169,7 @@ void AbstractShaderProgramTest::attributeVector() { void AbstractShaderProgramTest::attributeVectorInt() { #ifndef MAGNUM_TARGET_GLES2 typedef AbstractShaderProgram::Attribute<3, Vector2i> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ @@ -183,6 +189,7 @@ void AbstractShaderProgramTest::attributeVectorInt() { void AbstractShaderProgramTest::attributeVectorUnsignedInt() { #ifndef MAGNUM_TARGET_GLES2 typedef AbstractShaderProgram::Attribute<3, Vector4ui> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ @@ -202,6 +209,7 @@ void AbstractShaderProgramTest::attributeVectorUnsignedInt() { void AbstractShaderProgramTest::attributeVectorDouble() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Vector2d> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ @@ -220,6 +228,7 @@ void AbstractShaderProgramTest::attributeVectorDouble() { void AbstractShaderProgramTest::attributeVector4() { typedef AbstractShaderProgram::Attribute<3, Vector4> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* Custom type */ @@ -235,6 +244,7 @@ void AbstractShaderProgramTest::attributeVector4() { void AbstractShaderProgramTest::attributeVectorBGRA() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Vector4> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 1); /* BGRA */ @@ -247,6 +257,7 @@ void AbstractShaderProgramTest::attributeVectorBGRA() { void AbstractShaderProgramTest::attributeMatrixNxN() { typedef AbstractShaderProgram::Attribute<3, Matrix3> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 3); /* Default constructor */ @@ -259,6 +270,7 @@ void AbstractShaderProgramTest::attributeMatrixNxN() { #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgramTest::attributeMatrixMxN() { typedef AbstractShaderProgram::Attribute<3, Matrix3x4> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 3); /* Default constructor */ @@ -272,6 +284,7 @@ void AbstractShaderProgramTest::attributeMatrixMxN() { void AbstractShaderProgramTest::attributeMatrixNxNd() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Matrix4d> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 4); /* Default constructor */ @@ -287,6 +300,7 @@ void AbstractShaderProgramTest::attributeMatrixNxNd() { void AbstractShaderProgramTest::attributeMatrixMxNd() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Matrix4x2d> Attribute; + CORRADE_VERIFY((std::is_same{})); CORRADE_COMPARE(Attribute::VectorCount, 4); /* Default constructor */ From a7db8052eacf327b746da211f4da19bc544a0ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:24:26 +0100 Subject: [PATCH 060/141] Define AbstractShaderProgram::Attribute::Type as T. The original comment is now saying the truth. --- src/Magnum/AbstractShaderProgram.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index a4e9d9276..138ce598a 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -959,6 +959,14 @@ template class AbstractShaderProgram::Attribute { VectorCount = Implementation::Attribute::VectorCount }; + /** + * @brief Type + * + * Type used in shader code. + * @see @ref ScalarType, @ref DataType + */ + typedef T Type; + /** * @brief Scalar type * From 26e7c9ce340455335fdf1f7af74bf9d21ba8617b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:38:46 +0100 Subject: [PATCH 061/141] MeshTools: added compile() function. All-in-one solution for preparing generic meshes with optional normals and texture coordinates, configured for use with Shaders::Generic. --- src/Magnum/MeshTools/CMakeLists.txt | 2 + src/Magnum/MeshTools/Compile.cpp | 160 +++++++++++++++++++++++++ src/Magnum/MeshTools/Compile.h | 81 +++++++++++++ src/Magnum/MeshTools/CompressIndices.h | 2 +- 4 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 src/Magnum/MeshTools/Compile.cpp create mode 100644 src/Magnum/MeshTools/Compile.h diff --git a/src/Magnum/MeshTools/CMakeLists.txt b/src/Magnum/MeshTools/CMakeLists.txt index f4e9587e2..fb2b324ca 100644 --- a/src/Magnum/MeshTools/CMakeLists.txt +++ b/src/Magnum/MeshTools/CMakeLists.txt @@ -25,6 +25,7 @@ # Files shared between main library and unit test library set(MagnumMeshTools_SRCS + Compile.cpp CompressIndices.cpp FullScreenTriangle.cpp Tipsify.cpp) @@ -37,6 +38,7 @@ set(MagnumMeshTools_GracefulAssert_SRCS set(MagnumMeshTools_HEADERS CombineIndexedArrays.h + Compile.h CompressIndices.h Duplicate.h FlipNormals.h diff --git a/src/Magnum/MeshTools/Compile.cpp b/src/Magnum/MeshTools/Compile.cpp new file mode 100644 index 000000000..b1372acfd --- /dev/null +++ b/src/Magnum/MeshTools/Compile.cpp @@ -0,0 +1,160 @@ +/* + 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 "Compile.h" + +#include "Magnum/Math/Vector3.h" +#include "Magnum/MeshTools/CompressIndices.h" +#include "Magnum/MeshTools/Interleave.h" +#include "Magnum/Trade/MeshData2D.h" +#include "Magnum/Trade/MeshData3D.h" + +/* This header is included only privately and doesn't introduce any linker + dependency, thus it's completely safe */ +#include "Magnum/Shaders/Generic.h" + +namespace Magnum { namespace MeshTools { + +std::tuple, std::unique_ptr> compile(const Trade::MeshData2D& meshData, const BufferUsage usage) { + Mesh mesh; + mesh.setPrimitive(meshData.primitive()); + + /* Decide about stride and offsets */ + UnsignedInt stride = sizeof(Shaders::Generic2D::Position::Type); + const UnsignedInt normalOffset = sizeof(Shaders::Generic2D::Position::Type); + if(meshData.hasTextureCoords2D()) + stride += sizeof(Shaders::Generic2D::TextureCoordinates::Type); + + /* Create vertex buffer */ + std::unique_ptr vertexBuffer{new Buffer{Buffer::Target::Array}}; + + /* Interleave positions */ + std::size_t vertexCount; + Containers::Array data; + std::tie(vertexCount, std::ignore, data) = MeshTools::interleave( + meshData.positions(0), + stride - sizeof(Shaders::Generic2D::Position::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + Shaders::Generic2D::Position(), + stride - sizeof(Shaders::Generic2D::Position::Type)); + + /* Add also texture coordinates, if present */ + if(meshData.hasTextureCoords2D()) { + MeshTools::interleaveInto(data, + normalOffset, + meshData.textureCoords2D(0), + stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + normalOffset, + Shaders::Generic2D::TextureCoordinates(), + stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type)); + } + + /* Fill vertex buffer with interleaved data and finalize mesh + configuration */ + vertexBuffer->setData(data, BufferUsage::StaticDraw); + mesh.setVertexCount(vertexCount); + + /* Fill index buffer */ + std::unique_ptr indexBuffer; + if(meshData.isIndexed()) { + indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); + MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); + } + + return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); +} + +std::tuple, std::unique_ptr> compile(const Trade::MeshData3D& meshData, const BufferUsage usage) { + Mesh mesh; + mesh.setPrimitive(meshData.primitive()); + + /* Decide about stride and offsets */ + UnsignedInt stride = sizeof(Shaders::Generic3D::Position::Type); + const UnsignedInt normalOffset = sizeof(Shaders::Generic3D::Position::Type); + UnsignedInt textureCoordsOffset = sizeof(Shaders::Generic3D::Position::Type); + if(meshData.hasNormals()) { + stride += sizeof(Shaders::Generic3D::Normal::Type); + textureCoordsOffset += sizeof(Shaders::Generic3D::Normal::Type); + } + if(meshData.hasTextureCoords2D()) + stride += sizeof(Shaders::Generic3D::TextureCoordinates::Type); + + /* Create vertex buffer */ + std::unique_ptr vertexBuffer{new Buffer{Buffer::Target::Array}}; + + /* Interleave positions */ + std::size_t vertexCount; + Containers::Array data; + std::tie(vertexCount, std::ignore, data) = MeshTools::interleave( + meshData.positions(0), + stride - sizeof(Shaders::Generic3D::Position::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + Shaders::Generic3D::Position(), + stride - sizeof(Shaders::Generic3D::Position::Type)); + + Debug() << stride << sizeof(Shaders::Generic3D::Position::Type) << vertexCount << normalOffset << textureCoordsOffset; + Debug() << data; + + /* Add also normals, if present */ + if(meshData.hasNormals()) { + MeshTools::interleaveInto(data, + normalOffset, + meshData.normals(0), + stride - normalOffset - sizeof(Shaders::Generic3D::Normal::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + normalOffset, + Shaders::Generic3D::Normal(), + stride - normalOffset - sizeof(Shaders::Generic3D::Normal::Type)); + } + + /* Add also texture coordinates, if present */ + if(meshData.hasTextureCoords2D()) { + MeshTools::interleaveInto(data, + textureCoordsOffset, + meshData.textureCoords2D(0), + stride - textureCoordsOffset - sizeof(Shaders::Generic3D::TextureCoordinates::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + textureCoordsOffset, + Shaders::Generic3D::TextureCoordinates(), + stride - textureCoordsOffset - sizeof(Shaders::Generic3D::TextureCoordinates::Type)); + } + + /* Fill vertex buffer with interleaved data and finalize mesh + configuration */ + vertexBuffer->setData(data, BufferUsage::StaticDraw); + mesh.setVertexCount(vertexCount); + + /* Fill index buffer */ + std::unique_ptr indexBuffer; + if(meshData.isIndexed()) { + indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); + MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); + } + + return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); +} + +}} diff --git a/src/Magnum/MeshTools/Compile.h b/src/Magnum/MeshTools/Compile.h new file mode 100644 index 000000000..3cb41c795 --- /dev/null +++ b/src/Magnum/MeshTools/Compile.h @@ -0,0 +1,81 @@ +#ifndef Magnum_MeshTools_Compile_h +#define Magnum_MeshTools_Compile_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. +*/ + +/** @file + * @brief Function @ref Magnum::MeshTools::compile() + */ + +#include +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Trade/Trade.h" +#include "Magnum/MeshTools/visibility.h" + +namespace Magnum { namespace MeshTools { + +/** +@brief Compile 2D mesh data + +Configures mesh for @ref Shaders::Generic2D shader with vertex buffer and +possibly also index buffer, if the mesh is indexed. Positions are bound to +@ref Shaders::Generic2D::Position attribute. If the mesh contains texture +coordinates, they are bound to @ref Shaders::Generic2D::TextureCoordinates +attribute. No data compression or index optimization (except for index buffer +packing) is done. The @p usage parameter is used for both vertex and index +buffer. + +The second returned buffer may be `nullptr` if the mesh is not indexed. + +This is just a convenience function for creating generic meshes, you might want +to use @ref interleave() and @ref compressIndices() functions instead for +greater flexibility. +*/ +MAGNUM_MESHTOOLS_EXPORT std::tuple, std::unique_ptr> compile(const Trade::MeshData2D& meshData, BufferUsage usage); + +/** +@brief Compile 3D mesh data + +Configures mesh for @ref Shaders::Generic3D shader with vertex buffer and +possibly also index buffer, if the mesh is indexed. Positions are bound to +@ref Shaders::Generic3D::Position attribute. If the mesh contains normals, they +are bound to @ref Shaders::Generic3D::Normal attribute, texture coordinates are +bound to @ref Shaders::Generic2D::TextureCoordinates attribute. No data +compression or index optimization (except for index buffer packing) is done. +The @p usage parameter is used for both vertex and index buffer. + +The second returned buffer may be `nullptr` if the mesh is not indexed. + +This is just a convenience function for creating generic meshes, you might want +to use @ref interleave() and @ref compressIndices() functions instead for +greater flexibility. +*/ +MAGNUM_MESHTOOLS_EXPORT std::tuple, std::unique_ptr> compile(const Trade::MeshData3D& meshData, BufferUsage usage); + +}} + +#endif diff --git a/src/Magnum/MeshTools/CompressIndices.h b/src/Magnum/MeshTools/CompressIndices.h index 844962dda..e1e847910 100644 --- a/src/Magnum/MeshTools/CompressIndices.h +++ b/src/Magnum/MeshTools/CompressIndices.h @@ -69,7 +69,7 @@ function writes the output to given buffer and calls @ref Mesh::setIndexCount() and @ref Mesh::setIndexBuffer(), thus you don't need to do anything else for mesh index configuration. -@see @ref MeshTools::interleave() +@see @ref MeshTools::interleave(), @ref MeshTools::compile() */ void MAGNUM_MESHTOOLS_EXPORT compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector& indices); From 5ffe761bade6412f0e15d364c762d264f879b00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:45:27 +0100 Subject: [PATCH 062/141] Shaders: doc++ --- src/Magnum/Shaders/Generic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Shaders/Generic.h b/src/Magnum/Shaders/Generic.h index 315a0e851..567fa6ab1 100644 --- a/src/Magnum/Shaders/Generic.h +++ b/src/Magnum/Shaders/Generic.h @@ -82,10 +82,10 @@ template struct Generic { }; #endif -/** @brief Generic 2D shader definition */ +/** @brief %Generic 2D shader definition */ typedef Generic<2> Generic2D; -/** @brief Generic 3D shader definition */ +/** @brief %Generic 3D shader definition */ typedef Generic<3> Generic3D; #ifndef DOXYGEN_GENERATING_OUTPUT From 0311ff01c343a9eea975ffe0e0aee66efa67ad18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:55:48 +0100 Subject: [PATCH 063/141] MeshTools: sorry about this mess. --- src/Magnum/MeshTools/Compile.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Magnum/MeshTools/Compile.cpp b/src/Magnum/MeshTools/Compile.cpp index b1372acfd..bc586f77a 100644 --- a/src/Magnum/MeshTools/Compile.cpp +++ b/src/Magnum/MeshTools/Compile.cpp @@ -115,9 +115,6 @@ std::tuple, std::unique_ptr> compile(const Shaders::Generic3D::Position(), stride - sizeof(Shaders::Generic3D::Position::Type)); - Debug() << stride << sizeof(Shaders::Generic3D::Position::Type) << vertexCount << normalOffset << textureCoordsOffset; - Debug() << data; - /* Add also normals, if present */ if(meshData.hasNormals()) { MeshTools::interleaveInto(data, From cdf24cb58cbb050f349f27be81b9538c5319982d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:57:23 +0100 Subject: [PATCH 064/141] Proper detection for AMD driver bug workaround. Not sure where I got that. --- src/Magnum/Implementation/setupDriverWorkarounds.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Implementation/setupDriverWorkarounds.cpp b/src/Magnum/Implementation/setupDriverWorkarounds.cpp index 5c0799c9a..d575ce324 100644 --- a/src/Magnum/Implementation/setupDriverWorkarounds.cpp +++ b/src/Magnum/Implementation/setupDriverWorkarounds.cpp @@ -35,8 +35,8 @@ void Context::setupDriverWorkarounds() { #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) + const std::string vendor = vendorString(); + if(vendor.find("ATI Technologies Inc.") != std::string::npos) _setRequiredVersion(GL::ARB::explicit_uniform_location, None); #endif From 69102817317e81665e655e68857537bae8311ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 7 Mar 2014 01:28:04 +0100 Subject: [PATCH 065/141] MeshTools: be const-correct. --- src/Magnum/MeshTools/Interleave.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 0c7d10b3f..d14913d5d 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -46,28 +46,28 @@ namespace Implementation { resolution (the functions would otherwise need to be de-inlined to break cyclic dependencies) */ struct AttributeCount { - template typename std::enable_if::value, std::size_t>::type operator()(const T& first, const U&... next) { + template typename std::enable_if::value, std::size_t>::type operator()(const T& first, const U&... next) const { CORRADE_ASSERT(sizeof...(next) == 0 || AttributeCount{}(next...) == first.size() || AttributeCount{}(next...) == ~std::size_t(0), "MeshTools::interleave(): attribute arrays don't have the same length, expected" << first.size() << "but got" << AttributeCount{}(next...), 0); return first.size(); } - template std::size_t operator()(std::size_t, const T& first, const U&... next) { + template std::size_t operator()(std::size_t, const T& first, const U&... next) const { return AttributeCount{}(first, next...); } - constexpr std::size_t operator()(std::size_t) { return ~std::size_t(0); } - constexpr std::size_t operator()() { return 0; } + constexpr std::size_t operator()(std::size_t) const { return ~std::size_t(0); } + constexpr std::size_t operator()() const { return 0; } }; /* Stride, taking gaps into account. It must be in the structure, same reason as above */ struct Stride { - template typename std::enable_if::value, std::size_t>::type operator()(const T&, const U&... next) { + template typename std::enable_if::value, std::size_t>::type operator()(const T&, const U&... next) const { return sizeof(typename T::value_type) + Stride{}(next...); } - template std::size_t operator()(std::size_t gap, const T&... next) { + template std::size_t operator()(std::size_t gap, const T&... next) const { return gap + Stride{}(next...); } - constexpr std::size_t operator()() { return 0; } + constexpr std::size_t operator()() const { return 0; } }; /* Copy data to the buffer */ From 4027a097e49d23fe3a936a667619ee4ed9c08a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 7 Mar 2014 01:45:39 +0100 Subject: [PATCH 066/141] package: build ObjImporter in all packages by default. --- package/archlinux/PKGBUILD | 1 + package/archlinux/PKGBUILD-android-arm | 1 + package/archlinux/PKGBUILD-android-x86 | 1 + package/archlinux/PKGBUILD-clang | 1 + package/archlinux/PKGBUILD-clang-libc++ | 1 + package/archlinux/PKGBUILD-emscripten | 1 + package/archlinux/PKGBUILD-es2 | 1 + package/archlinux/PKGBUILD-es2desktop | 1 + package/archlinux/PKGBUILD-es3 | 1 + package/archlinux/PKGBUILD-es3desktop | 1 + package/archlinux/PKGBUILD-gcc46 | 1 + package/archlinux/PKGBUILD-gcc47 | 1 + package/archlinux/PKGBUILD-gcc49 | 1 + package/archlinux/PKGBUILD-mingw32 | 1 + package/archlinux/PKGBUILD-nacl-glibc | 2 ++ package/archlinux/PKGBUILD-nacl-newlib | 2 ++ package/archlinux/PKGBUILD-release | 1 + package/archlinux/magnum-git/PKGBUILD | 1 + package/ci/jenkins-emscripten.xml | 1 + package/ci/jenkins-mingw32.xml | 1 + package/ci/jenkins-nacl.xml | 1 + package/ci/jenkins.xml | 1 + package/debian/rules | 1 + 23 files changed, 25 insertions(+) diff --git a/package/archlinux/PKGBUILD b/package/archlinux/PKGBUILD index c21cc7040..16162524e 100644 --- a/package/archlinux/PKGBUILD +++ b/package/archlinux/PKGBUILD @@ -29,6 +29,7 @@ build() { -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-android-arm b/package/archlinux/PKGBUILD-android-arm index 7ed7104e8..10e78f3a3 100644 --- a/package/archlinux/PKGBUILD-android-arm +++ b/package/archlinux/PKGBUILD-android-arm @@ -29,6 +29,7 @@ build() { -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-arm/usr \ -DWITH_MAGNUMFONT=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_ANDROIDAPPLICATION=ON diff --git a/package/archlinux/PKGBUILD-android-x86 b/package/archlinux/PKGBUILD-android-x86 index 4be7a2558..315471634 100644 --- a/package/archlinux/PKGBUILD-android-x86 +++ b/package/archlinux/PKGBUILD-android-x86 @@ -29,6 +29,7 @@ build() { -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-x86/usr \ -DWITH_MAGNUMFONT=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_ANDROIDAPPLICATION=ON diff --git a/package/archlinux/PKGBUILD-clang b/package/archlinux/PKGBUILD-clang index 45f89c36a..16ca20095 100644 --- a/package/archlinux/PKGBUILD-clang +++ b/package/archlinux/PKGBUILD-clang @@ -33,6 +33,7 @@ build() { -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-clang-libc++ b/package/archlinux/PKGBUILD-clang-libc++ index 88bc44219..6cd676c9c 100644 --- a/package/archlinux/PKGBUILD-clang-libc++ +++ b/package/archlinux/PKGBUILD-clang-libc++ @@ -35,6 +35,7 @@ build() { -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-emscripten b/package/archlinux/PKGBUILD-emscripten index 785f84ab7..91d29d943 100644 --- a/package/archlinux/PKGBUILD-emscripten +++ b/package/archlinux/PKGBUILD-emscripten @@ -28,6 +28,7 @@ build() { -DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \ -DWITH_SDL2APPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON diff --git a/package/archlinux/PKGBUILD-es2 b/package/archlinux/PKGBUILD-es2 index c1c9e82d3..7e9265775 100644 --- a/package/archlinux/PKGBUILD-es2 +++ b/package/archlinux/PKGBUILD-es2 @@ -23,6 +23,7 @@ build() { -DWITH_AUDIO=ON \ -DWITH_XEGLAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-es2desktop b/package/archlinux/PKGBUILD-es2desktop index 97e88d78f..2d9847e2c 100644 --- a/package/archlinux/PKGBUILD-es2desktop +++ b/package/archlinux/PKGBUILD-es2desktop @@ -26,6 +26,7 @@ build() { -DWITH_GLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-es3 b/package/archlinux/PKGBUILD-es3 index dbecf3486..d88141992 100644 --- a/package/archlinux/PKGBUILD-es3 +++ b/package/archlinux/PKGBUILD-es3 @@ -23,6 +23,7 @@ build() { -DWITH_AUDIO=ON \ -DWITH_XEGLAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-es3desktop b/package/archlinux/PKGBUILD-es3desktop index a84fa45ea..2ca7c0c15 100644 --- a/package/archlinux/PKGBUILD-es3desktop +++ b/package/archlinux/PKGBUILD-es3desktop @@ -26,6 +26,7 @@ build() { -DWITH_GLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-gcc46 b/package/archlinux/PKGBUILD-gcc46 index 15a1c6100..eb72eb27c 100644 --- a/package/archlinux/PKGBUILD-gcc46 +++ b/package/archlinux/PKGBUILD-gcc46 @@ -33,6 +33,7 @@ build() { -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-gcc47 b/package/archlinux/PKGBUILD-gcc47 index 600cc598f..a9c4abd8f 100644 --- a/package/archlinux/PKGBUILD-gcc47 +++ b/package/archlinux/PKGBUILD-gcc47 @@ -33,6 +33,7 @@ build() { -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-gcc49 b/package/archlinux/PKGBUILD-gcc49 index 02d6db4da..8d524a66b 100644 --- a/package/archlinux/PKGBUILD-gcc49 +++ b/package/archlinux/PKGBUILD-gcc49 @@ -33,6 +33,7 @@ build() { -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-mingw32 b/package/archlinux/PKGBUILD-mingw32 index 2f200f94f..276af9c95 100644 --- a/package/archlinux/PKGBUILD-mingw32 +++ b/package/archlinux/PKGBUILD-mingw32 @@ -24,6 +24,7 @@ build() { -DWITH_GLUTAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-nacl-glibc b/package/archlinux/PKGBUILD-nacl-glibc index 3a3477d09..3798cde72 100644 --- a/package/archlinux/PKGBUILD-nacl-glibc +++ b/package/archlinux/PKGBUILD-nacl-glibc @@ -24,6 +24,7 @@ build() { -DWITH_NACLAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ @@ -44,6 +45,7 @@ build() { -DWITH_NACLAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-nacl-newlib b/package/archlinux/PKGBUILD-nacl-newlib index 4cfe9fda9..77e0fd084 100644 --- a/package/archlinux/PKGBUILD-nacl-newlib +++ b/package/archlinux/PKGBUILD-nacl-newlib @@ -25,6 +25,7 @@ build() { -DWITH_WINDOWLESSNACLAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ @@ -46,6 +47,7 @@ build() { -DWITH_WINDOWLESSNACLAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/PKGBUILD-release b/package/archlinux/PKGBUILD-release index 61ff12d04..9d1266bd8 100644 --- a/package/archlinux/PKGBUILD-release +++ b/package/archlinux/PKGBUILD-release @@ -25,6 +25,7 @@ build() { -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/archlinux/magnum-git/PKGBUILD b/package/archlinux/magnum-git/PKGBUILD index e3ca44e5f..660b77f98 100644 --- a/package/archlinux/magnum-git/PKGBUILD +++ b/package/archlinux/magnum-git/PKGBUILD @@ -45,6 +45,7 @@ build() { -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/ci/jenkins-emscripten.xml b/package/ci/jenkins-emscripten.xml index bea34b38b..f0615f06f 100644 --- a/package/ci/jenkins-emscripten.xml +++ b/package/ci/jenkins-emscripten.xml @@ -73,6 +73,7 @@ cmake .. \ `#-DWITH_AUDIO=ON` \ -DWITH_SDL2APPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ `#-DWITH_WAVAUDIOIMPORTER=ON` \ diff --git a/package/ci/jenkins-mingw32.xml b/package/ci/jenkins-mingw32.xml index 343df8bf8..7f4a1f52e 100644 --- a/package/ci/jenkins-mingw32.xml +++ b/package/ci/jenkins-mingw32.xml @@ -87,6 +87,7 @@ cmake .. \ `#-DWITH_SDL2APPLICATION=ON` \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/ci/jenkins-nacl.xml b/package/ci/jenkins-nacl.xml index 7f3dc0453..5d19c1e07 100644 --- a/package/ci/jenkins-nacl.xml +++ b/package/ci/jenkins-nacl.xml @@ -81,6 +81,7 @@ cmake .. \ -DWITH_NACLAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ `#-DWITH_WAVAUDIOIMPORTER=ON` \ diff --git a/package/ci/jenkins.xml b/package/ci/jenkins.xml index 963afad27..beeaf2498 100644 --- a/package/ci/jenkins.xml +++ b/package/ci/jenkins.xml @@ -143,6 +143,7 @@ cmake .. \ -DWITH_XEGLAPPLICATION=${es_flag} \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=${desktop_flag} \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ diff --git a/package/debian/rules b/package/debian/rules index 3723072df..16cda466a 100755 --- a/package/debian/rules +++ b/package/debian/rules @@ -11,6 +11,7 @@ override_dh_auto_configure: -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \ From e76178691d050ea63793cdcb63720eb61eae228c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 12 Mar 2014 16:39:09 +0100 Subject: [PATCH 067/141] Shapes: added missing test for Shape::collides(). There is one not-yet-sure-about behavior, expecting the failure. --- src/Magnum/Shapes/Test/ShapeTest.cpp | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/Magnum/Shapes/Test/ShapeTest.cpp b/src/Magnum/Shapes/Test/ShapeTest.cpp index 5ad60e6a3..9f88909c4 100644 --- a/src/Magnum/Shapes/Test/ShapeTest.cpp +++ b/src/Magnum/Shapes/Test/ShapeTest.cpp @@ -41,6 +41,7 @@ class ShapeTest: public TestSuite::Tester { ShapeTest(); void clean(); + void collides(); void firstCollision(); void shapeGroup(); }; @@ -52,6 +53,7 @@ typedef SceneGraph::Object Object3D; ShapeTest::ShapeTest() { addTests({&ShapeTest::clean, + &ShapeTest::collides, &ShapeTest::firstCollision, &ShapeTest::shapeGroup}); } @@ -96,6 +98,45 @@ void ShapeTest::clean() { CORRADE_VERIFY(b.isDirty()); } +void ShapeTest::collides() { + Scene3D scene; + ShapeGroup3D shapes; + Object3D a(&scene); + Shape aShape(a, {{1.0f, -2.0f, 3.0f}, 1.5f}, &shapes); + + { + /* Collision with point inside the sphere */ + Shape aShape2(a, {{1.0f, -2.0f, 3.0f}}, &shapes); + shapes.setClean(); + CORRADE_VERIFY(aShape.collides(aShape2)); + } { + /* No collision with point inside the sphere, but not in the same group */ + ShapeGroup3D shapes2; + Shape aShape3(a, {{1.0f, -2.0f, 3.0f}}, &shapes2); + shapes2.setClean(); + CORRADE_VERIFY(!aShape.collides(aShape3)); + } { + CORRADE_EXPECT_FAIL("Should cross-scene collision work or not?"); + /* No collision with point inside the sphere, but not in the same scene */ + Scene3D scene2; + Object3D c(&scene2); + Shape cShape(c, {{1.0f, -2.0f, 3.0f}}, &shapes); + shapes.setClean(); + CORRADE_VERIFY(!aShape.collides(cShape)); + } { + /* No collision with point outside of the sphere */ + Object3D b(&scene); + Shape bShape(b, {{3.0f, -2.0f, 3.0f}}, &shapes); + shapes.setClean(); + CORRADE_VERIFY(!aShape.collides(bShape)); + + /* Move point inside the sphere -- collision */ + b.translate(Vector3::xAxis(-1.0f)); + shapes.setClean(); + CORRADE_VERIFY(aShape.collides(bShape)); + } +} + void ShapeTest::firstCollision() { Scene3D scene; ShapeGroup3D shapes; From 218b950aed261afd5a27173dc8a977a2f8f1d0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 12 Mar 2014 16:40:07 +0100 Subject: [PATCH 068/141] Shapes: added Shape::collision(). Much like Shape::collides() is equivalent to the more low-level collision detection using operator%, the Shape::collision() returns collision details similarly to operator/. Currently only Sphere/Sphere and Sphere/Point collision is done, thus the dispatch is nearly empty. --- src/Magnum/Shapes/AbstractShape.cpp | 5 +++ src/Magnum/Shapes/AbstractShape.h | 7 +++ .../Implementation/CollisionDispatch.cpp | 30 +++++++++++++ .../Shapes/Implementation/CollisionDispatch.h | 4 ++ src/Magnum/Shapes/Test/ShapeTest.cpp | 45 +++++++++++++++++++ 5 files changed, 91 insertions(+) diff --git a/src/Magnum/Shapes/AbstractShape.cpp b/src/Magnum/Shapes/AbstractShape.cpp index 913ed01e9..8bb10797a 100644 --- a/src/Magnum/Shapes/AbstractShape.cpp +++ b/src/Magnum/Shapes/AbstractShape.cpp @@ -27,6 +27,7 @@ #include +#include "Magnum/Shapes/Collision.h" #include "Magnum/Shapes/ShapeGroup.h" #include "Magnum/Shapes/Implementation/CollisionDispatch.h" @@ -52,6 +53,10 @@ template bool AbstractShape::collides(const return Implementation::collides(abstractTransformedShape(), other.abstractTransformedShape()); } +template Collision AbstractShape::collision(const AbstractShape& other) const { + return Implementation::collision(abstractTransformedShape(), other.abstractTransformedShape()); +} + template void AbstractShape::markDirty() { if(group()) group()->setDirty(); } diff --git a/src/Magnum/Shapes/AbstractShape.h b/src/Magnum/Shapes/AbstractShape.h index 2273944de..fdcb3a75c 100644 --- a/src/Magnum/Shapes/AbstractShape.h +++ b/src/Magnum/Shapes/AbstractShape.h @@ -102,6 +102,13 @@ template class MAGNUM_SHAPES_EXPORT AbstractShape: publi */ bool collides(const AbstractShape& other) const; + /** + * @brief Collision with other shape + * + * Default implementation returns empty collision. + */ + Collision collision(const AbstractShape& other) const; + protected: /** Marks also the group as dirty */ void markDirty() override; diff --git a/src/Magnum/Shapes/Implementation/CollisionDispatch.cpp b/src/Magnum/Shapes/Implementation/CollisionDispatch.cpp index 621396a1b..11a76adcd 100644 --- a/src/Magnum/Shapes/Implementation/CollisionDispatch.cpp +++ b/src/Magnum/Shapes/Implementation/CollisionDispatch.cpp @@ -65,6 +65,21 @@ template<> bool collides(const AbstractShape<2>& a, const AbstractShape<2>& b) { return false; } +template<> Collision<2> collision(const AbstractShape<2>& a, const AbstractShape<2>& b) { + if(a.type() < b.type()) return collision(b, a); + + switch(UnsignedInt(a.type())*UnsignedInt(b.type())) { + #define _c(aType, aClass, bType, bClass) \ + case UnsignedInt(ShapeDimensionTraits<2>::Type::aType)*UnsignedInt(ShapeDimensionTraits<2>::Type::bType): \ + return static_cast&>(a).shape / static_cast&>(b).shape; + _c(Sphere, Sphere2D, Point, Point2D) + _c(Sphere, Sphere2D, Sphere, Sphere2D) + #undef _c + } + + return {}; +} + template<> bool collides(const AbstractShape<3>& a, const AbstractShape<3>& b) { if(a.type() < b.type()) return collides(b, a); @@ -96,4 +111,19 @@ template<> bool collides(const AbstractShape<3>& a, const AbstractShape<3>& b) { return false; } +template<> Collision<3> collision(const AbstractShape<3>& a, const AbstractShape<3>& b) { + if(a.type() < b.type()) return collision(b, a); + + switch(UnsignedInt(a.type())*UnsignedInt(b.type())) { + #define _c(aType, aClass, bType, bClass) \ + case UnsignedInt(ShapeDimensionTraits<3>::Type::aType)*UnsignedInt(ShapeDimensionTraits<3>::Type::bType): \ + return static_cast&>(a).shape / static_cast&>(b).shape; + _c(Sphere, Sphere3D, Point, Point3D) + _c(Sphere, Sphere3D, Sphere, Sphere3D) + #undef _c + } + + return {}; +} + }}} diff --git a/src/Magnum/Shapes/Implementation/CollisionDispatch.h b/src/Magnum/Shapes/Implementation/CollisionDispatch.h index cd1dd564b..84d79aa2f 100644 --- a/src/Magnum/Shapes/Implementation/CollisionDispatch.h +++ b/src/Magnum/Shapes/Implementation/CollisionDispatch.h @@ -26,6 +26,7 @@ */ #include "Magnum/Types.h" +#include "Magnum/Shapes/Shapes.h" namespace Magnum { namespace Shapes { namespace Implementation { @@ -40,8 +41,11 @@ multiply the two numbers together and switch() on the result. Because of multiplying two prime numbers, there is no ambiguity (the result is unique for each combination). */ + template bool collides(const AbstractShape& a, const AbstractShape& b); +template Collision collision(const AbstractShape& a, const AbstractShape& b); + }}} #endif diff --git a/src/Magnum/Shapes/Test/ShapeTest.cpp b/src/Magnum/Shapes/Test/ShapeTest.cpp index 9f88909c4..e9a74d915 100644 --- a/src/Magnum/Shapes/Test/ShapeTest.cpp +++ b/src/Magnum/Shapes/Test/ShapeTest.cpp @@ -42,6 +42,7 @@ class ShapeTest: public TestSuite::Tester { void clean(); void collides(); + void collision(); void firstCollision(); void shapeGroup(); }; @@ -54,6 +55,7 @@ typedef SceneGraph::Object Object3D; ShapeTest::ShapeTest() { addTests({&ShapeTest::clean, &ShapeTest::collides, + &ShapeTest::collision, &ShapeTest::firstCollision, &ShapeTest::shapeGroup}); } @@ -137,6 +139,49 @@ void ShapeTest::collides() { } } +void ShapeTest::collision() { + Scene3D scene; + ShapeGroup3D shapes; + Object3D a(&scene); + Shape aShape(a, {{1.0f, -2.0f, 3.0f}, 1.5f}, &shapes); + + { + /* Collision with point inside the sphere */ + Shape aShape2(a, {{1.0f, -2.0f, 3.0f}}, &shapes); + shapes.setClean(); + const Collision3D collision = aShape.collision(aShape2); + CORRADE_VERIFY(collision); + CORRADE_COMPARE(collision.position(), Vector3(1.0f, -2.0f, 3.0f)); + } { + /* No collision with point inside the sphere, but not in the same group */ + ShapeGroup3D shapes2; + Shape aShape3(a, {{1.0f, -2.0f, 3.0f}}, &shapes2); + shapes2.setClean(); + CORRADE_VERIFY(!aShape.collision(aShape3)); + } { + CORRADE_EXPECT_FAIL("Should cross-scene collision work or not?"); + /* No collision with point inside the sphere, but not in the same scene */ + Scene3D scene2; + Object3D c(&scene2); + Shape cShape(c, {{1.0f, -2.0f, 3.0f}}, &shapes); + shapes.setClean(); + CORRADE_VERIFY(!aShape.collision(cShape)); + } { + /* No collision with point outside of the sphere */ + Object3D b(&scene); + Shape bShape(b, {{3.0f, -2.0f, 3.0f}}, &shapes); + shapes.setClean(); + CORRADE_VERIFY(!aShape.collision(bShape)); + + /* Move point inside the sphere -- collision */ + b.translate(Vector3::xAxis(-1.0f)); + shapes.setClean(); + const Collision3D collision = aShape.collision(bShape); + CORRADE_VERIFY(collision); + CORRADE_COMPARE(collision.position(), Vector3(2.0f, -2.0f, 3.0f)); + } +} + void ShapeTest::firstCollision() { Scene3D scene; ShapeGroup3D shapes; From 9d2ea4ba156bdd8f04c1bd0f2a614c87ab88ee61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 12 Mar 2014 16:41:46 +0100 Subject: [PATCH 069/141] Shapes: removed unused variable from the test. The purpose wasn't commented at all, so I may just assume that it got lost after some refactoring. --- src/Magnum/Shapes/Test/ShapeTest.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Magnum/Shapes/Test/ShapeTest.cpp b/src/Magnum/Shapes/Test/ShapeTest.cpp index e9a74d915..e75d5213a 100644 --- a/src/Magnum/Shapes/Test/ShapeTest.cpp +++ b/src/Magnum/Shapes/Test/ShapeTest.cpp @@ -192,9 +192,6 @@ void ShapeTest::firstCollision() { Object3D b(&scene); Shape bShape(b, {{3.0f, -2.0f, 3.0f}}, &shapes); - Object3D c(&scene); - Shape cShape(c, &shapes); - /* No collisions initially */ CORRADE_VERIFY(!shapes.firstCollision(aShape)); CORRADE_VERIFY(!shapes.firstCollision(bShape)); From 30809a86f3b920d2504c2da1d3e12e5f52a58b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 12 Mar 2014 17:36:42 +0100 Subject: [PATCH 070/141] Shapes: updated and cleaned up the documentation. --- doc/shapes.dox | 58 ++++++++++++++++++++---------- src/Magnum/Shapes/AbstractShape.h | 12 +++---- src/Magnum/Shapes/AxisAlignedBox.h | 4 +-- src/Magnum/Shapes/Box.h | 4 +-- src/Magnum/Shapes/Capsule.h | 4 +-- src/Magnum/Shapes/Collision.h | 2 +- src/Magnum/Shapes/Composition.h | 10 +++--- src/Magnum/Shapes/Cylinder.h | 2 +- src/Magnum/Shapes/Line.h | 6 ++-- src/Magnum/Shapes/LineSegment.h | 4 +-- src/Magnum/Shapes/Plane.h | 2 +- src/Magnum/Shapes/Point.h | 4 +-- src/Magnum/Shapes/Shape.h | 23 ++++++------ src/Magnum/Shapes/ShapeGroup.h | 23 ++++++------ src/Magnum/Shapes/Shapes.h | 2 +- src/Magnum/Shapes/Sphere.h | 4 +-- 16 files changed, 92 insertions(+), 72 deletions(-) diff --git a/doc/shapes.dox b/doc/shapes.dox index 2da04df93..b52c0ed0b 100644 --- a/doc/shapes.dox +++ b/doc/shapes.dox @@ -77,9 +77,9 @@ is least efficient. @section shapes-composition Creating shape compositions %Shapes can be composed together using one of three available logical -operations: AND, OR and NOT. These operations are mapped to operator&&(), -operator||() and operator!(), so for example creating negation of logical OR -of line segment and point is simple as this: +operations: AND, OR and NOT. These operations are mapped to `&&`, `||` and `!` +operators, so for example creating negation of logical OR of line segment and +point is simple as this: @code Shapes::LineSegment3D segment; Shapes::Point3D point; @@ -97,9 +97,9 @@ If there are many shapes composed together, it might hurt performance of collision detection, because it might be testing collision with more shapes than necessary. It's then good to specify simplified version of such shape, so the collision detection is done on the complex one if and only if collision -was detected with the simplified shape. It is in fact logical AND using -operator&&() - the collision is initially detected on first (simplified) shape -and then on the other: +was detected with the simplified shape. It is in fact logical AND using the +`&&` operator -- the collision is initially detected on first (simplified) +shape and then on the other: @code Shapes::Sphere3D sphere; Shapes::Box3D box; @@ -111,7 +111,7 @@ Shapes::Composition3D composition = simplified && (sphere || box); @section shapes-collisions Detecting shape collisions %Shape pairs which have collision occurence detection implemented can be tested -for collision using operator%(). The operator returns boolean describing +for collision using the `%` operator. The operator returns boolean describing whether the collision happened or not. Example: @code Shapes::Point3D point; @@ -123,12 +123,12 @@ bool collide = point % sphere; As this is useful for e.g. menu handling and simple particle systems, for serious physics you often need more information like contact point, separation normal and penetration depth. For shape pairs which have implemented this -detailed collision detection you can use `operator/()`, which returns @ref Collision -object. Note that unlike with `operator%()` mentioned above, this operation is -not commutative. See @ref Collision class documentation for more information -about the returned data. Example: +detailed collision detection you can use the `/` operator, which returns +@ref Collision object. Note that unlike with the `%` operator mentioned above, +this operation is not commutative. See @ref Collision class documentation for +more information about the returned data. Example: @code -Shapes::Collision3D c = point/sphere; +const Shapes::Collision3D c = point/sphere; if(c) { Vector3 translation = c.separationNormal()*c.separationDistance(); // translate point by translation... @@ -137,15 +137,37 @@ if(c) { @section shapes-scenegraph Integration with scene graph -%Shape can be attached to object in the scene using Shapes::Shape feature and -then used for collision detection. You can also use DebugTools::ShapeRenderer -to visualize the shape for debugging purposes. +%Shape can be attached to object in the scene using @ref Shapes::Shape feature. +In conjunction with @ref Shapes::ShapeGroup you can use +@ref Shapes::Shape::collides() and @ref Shapes::Shape::collision() similarly to +the `%` and `/` operators above. Please note that the shape group caches the +absolute transformations of all shapes and thus you need to explicitly call +@ref Shapes::ShapeGroup::setClean() before computing the collisions if you did +any modifications to the objects in the scene. + +Scenegraph-flavored equivalent to the above code: @code -Object3D object; -auto shape = Shapes::Shape(object, {{}, 23.0f}); +Shapes::ShapeGroup3D shapes; +Object3D& a; +auto aShape = new Shapes::Shape(a, {{}, 23.0f}, &shapes); + +Object3D& b; +auto bShape = new Shapes::Shape(b, {{1.0f, 0.2f, 3.0f}}, &shapes); + +// Translate point so the objects no longer collide +shapes.setClean(); +if(aShape->collides(*bShape)) { + const Shapes::Collision3D c = aShape->collision(*bShape); + b.translate(c.separationNormal()*c.separationDistance()); +} @endcode -See also @ref scenegraph for introduction. +There is also @ref Shapes::ShapeGroup::firstCollision() function which returns +arbitrary first collision for given shape in whole group (or `nullptr`, if +there isn't any collision). + +You can also use @ref DebugTools::ShapeRenderer to visualize the shapes for +debugging purposes. See also @ref scenegraph for introduction. - Previous page: @ref scenegraph - Next page: @ref debug-tools diff --git a/src/Magnum/Shapes/AbstractShape.h b/src/Magnum/Shapes/AbstractShape.h index fdcb3a75c..50c1c5303 100644 --- a/src/Magnum/Shapes/AbstractShape.h +++ b/src/Magnum/Shapes/AbstractShape.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::AbstractShape, typedef Magnum::Shapes::AbstractShape2D, Magnum::Shapes::AbstractShape3D + * @brief Class @ref Magnum::Shapes::AbstractShape, typedef @ref Magnum::Shapes::AbstractShape2D, @ref Magnum::Shapes::AbstractShape3D */ #include "Magnum/Magnum.h" @@ -46,9 +46,9 @@ namespace Implementation { /** @brief Base class for object shapes -This class is not directly instantiable, see Shape instead. See @ref shapes for -brief introduction. -@see AbstractShape2D, AbstractShape3D +This class is not directly instantiable, use @ref Shape instead. See +@ref shapes for brief introduction. +@see @ref AbstractShape2D, @ref AbstractShape3D */ template class MAGNUM_SHAPES_EXPORT AbstractShape: public SceneGraph::AbstractGroupedFeature, Float> { friend const Implementation::AbstractShape& Implementation::getAbstractShape<>(const AbstractShape&); @@ -90,9 +90,7 @@ template class MAGNUM_SHAPES_EXPORT AbstractShape: publi ShapeGroup* group(); const ShapeGroup* group() const; /**< @overload */ - /** - * @brief Shape type - */ + /** @brief Shape type */ Type type() const; /** diff --git a/src/Magnum/Shapes/AxisAlignedBox.h b/src/Magnum/Shapes/AxisAlignedBox.h index 900af0669..bb2d1076e 100644 --- a/src/Magnum/Shapes/AxisAlignedBox.h +++ b/src/Magnum/Shapes/AxisAlignedBox.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::AxisAlignedBox, typedef Magnum::Shapes::AxisAlignedBox2D, Magnum::Shapes.:AxisAlignedBox3D + * @brief Class @ref Magnum::Shapes::AxisAlignedBox, typedef @ref Magnum::Shapes::AxisAlignedBox2D, @ref Magnum::Shapes.:AxisAlignedBox3D */ #include "Magnum/DimensionTraits.h" @@ -40,7 +40,7 @@ namespace Magnum { namespace Shapes { @brief Axis-aligned box See @ref shapes for brief introduction. -@see AxisAlignedBox2D, AxisAlignedBox3D +@see @ref AxisAlignedBox2D, @ref AxisAlignedBox3D @todo Assert for rotation */ template class MAGNUM_SHAPES_EXPORT AxisAlignedBox { diff --git a/src/Magnum/Shapes/Box.h b/src/Magnum/Shapes/Box.h index c83822700..e6b785cd6 100644 --- a/src/Magnum/Shapes/Box.h +++ b/src/Magnum/Shapes/Box.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Box, typedef Magnum::Shapes::Box2D, Magnum::Shapes::Box3D + * @brief Class @ref Magnum::Shapes::Box, typedef @ref Magnum::Shapes::Box2D, @ref Magnum::Shapes::Box3D */ #include "Magnum/DimensionTraits.h" @@ -41,8 +41,8 @@ namespace Magnum { namespace Shapes { Unit-size means that half extents are equal to 1, equivalent to e.g. sphere radius. See @ref shapes for brief introduction. +@see @ref Box2D, @ref Box3D @todo Use quat + position + size instead? -@see Box2D, Box3D @todo Assert for skew */ template class MAGNUM_SHAPES_EXPORT Box { diff --git a/src/Magnum/Shapes/Capsule.h b/src/Magnum/Shapes/Capsule.h index 42556e019..e760327fc 100644 --- a/src/Magnum/Shapes/Capsule.h +++ b/src/Magnum/Shapes/Capsule.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Capsule, typedef Magnum::Shapes::Capsule2D, Magnum::Shapes::Capsule3D + * @brief Class @ref Magnum::Shapes::Capsule, typedef @ref Magnum::Shapes::Capsule2D, @ref Magnum::Shapes::Capsule3D */ #include "Magnum/DimensionTraits.h" @@ -41,7 +41,7 @@ namespace Magnum { namespace Shapes { Unlike other elements the capsule expects uniform scaling. See @ref shapes for brief introduction. -@see Capsule2D, Capsule3D, Cylinder +@see @ref Capsule2D, @ref Capsule3D, @ref Cylinder @todo Store the radius as squared value to avoid sqrt/pow? Will complicate collision detection with sphere. */ diff --git a/src/Magnum/Shapes/Collision.h b/src/Magnum/Shapes/Collision.h index 0ee1528ff..74f2f9d88 100644 --- a/src/Magnum/Shapes/Collision.h +++ b/src/Magnum/Shapes/Collision.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Shapes::Collision + * @brief Class @ref Magnum::Shapes::Collision, typedef @ref Magnum::Shapes::Collision2D, @ref Magnum::Shapes::Collision3D */ #include "Magnum/DimensionTraits.h" diff --git a/src/Magnum/Shapes/Composition.h b/src/Magnum/Shapes/Composition.h index 1583971e1..a81fa02ad 100644 --- a/src/Magnum/Shapes/Composition.h +++ b/src/Magnum/Shapes/Composition.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Composition, enum Magnum::Shapes::CompositionOperation + * @brief Class @ref Magnum::Shapes::Composition, typedef @ref Magnum::Shapes::Composition2D, @ref Magnum::Shapes::Composition3D, enum @ref Magnum::Shapes::CompositionOperation */ #include @@ -95,7 +95,7 @@ template class MAGNUM_SHAPES_EXPORT Composition { /** * @brief Default constructor * - * Creates empty hierarchy. + * Creates empty composition. */ explicit Composition() {} @@ -187,10 +187,10 @@ template class MAGNUM_SHAPES_EXPORT Composition { Containers::Array _nodes; }; -/** @brief Two-dimensional shape hierarchy */ +/** @brief Two-dimensional shape composition */ typedef Composition<2> Composition2D; -/** @brief Three-dimensional shape hierarchy */ +/** @brief Three-dimensional shape composition */ typedef Composition<3> Composition3D; #ifdef DOXYGEN_GENERATING_OUTPUT @@ -199,7 +199,7 @@ template Debug operator<<(Debug debug, typename Composit #endif /** @relates Composition -@brief Collision of shape with Composition +@brief Collision of shape with @ref Composition */ #ifdef DOXYGEN_GENERATING_OUTPUT template inline bool operator%(const T& a, const Composition& b) { diff --git a/src/Magnum/Shapes/Cylinder.h b/src/Magnum/Shapes/Cylinder.h index 6730c8e0b..04a311a71 100644 --- a/src/Magnum/Shapes/Cylinder.h +++ b/src/Magnum/Shapes/Cylinder.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Cylinder, typedef Magnum::Shapes::Cylinder2D, Magnum::Shapes::Cylinder3D + * @brief Class @ref Magnum::Shapes::Cylinder, typedef @ref Magnum::Shapes::Cylinder2D, @ref Magnum::Shapes::Cylinder3D */ #include "Magnum/DimensionTraits.h" diff --git a/src/Magnum/Shapes/Line.h b/src/Magnum/Shapes/Line.h index da4d98bf8..553beec0c 100644 --- a/src/Magnum/Shapes/Line.h +++ b/src/Magnum/Shapes/Line.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Line, typedef Magnum::Shapes::Line2D, Magnum::Shapes::Line3D + * @brief Class @ref Magnum::Shapes::Line, typedef @ref Magnum::Shapes::Line2D, @ref Magnum::Shapes::Line3D */ #include "Magnum/DimensionTraits.h" @@ -39,8 +39,8 @@ namespace Magnum { namespace Shapes { @brief Infinite line, defined by two points See @ref shapes for brief introduction. -@see Line2D, Line3D -@todo collision detection of two Line2D +@see @ref Line2D, @ref Line3D +@todo collision detection of two @ref Line2D */ template class MAGNUM_SHAPES_EXPORT Line { public: diff --git a/src/Magnum/Shapes/LineSegment.h b/src/Magnum/Shapes/LineSegment.h index 6a27e6712..da20b31b5 100644 --- a/src/Magnum/Shapes/LineSegment.h +++ b/src/Magnum/Shapes/LineSegment.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::LineSegment, typedef Magnum::Shapes::LineSegment2D, Magnum::Shapes::LineSegment3D + * @brief Class @ref Magnum::Shapes::LineSegment, typedef @ref Magnum::Shapes::LineSegment2D, @ref Magnum::Shapes::LineSegment3D */ #include "Magnum/Shapes/Line.h" @@ -37,7 +37,7 @@ namespace Magnum { namespace Shapes { @brief %Line segment, defined by starting and ending point See @ref shapes for brief introduction. -@see LineSegment2D, LineSegment3D +@see @ref LineSegment2D, @ref LineSegment3D */ template class LineSegment: public Line { public: diff --git a/src/Magnum/Shapes/Plane.h b/src/Magnum/Shapes/Plane.h index 8cac28180..70d6ec18c 100644 --- a/src/Magnum/Shapes/Plane.h +++ b/src/Magnum/Shapes/Plane.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Plane + * @brief Class @ref Magnum::Shapes::Plane */ #include "Magnum/Magnum.h" diff --git a/src/Magnum/Shapes/Point.h b/src/Magnum/Shapes/Point.h index b0c6790f6..b2358ade3 100644 --- a/src/Magnum/Shapes/Point.h +++ b/src/Magnum/Shapes/Point.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Point, typedef Magnum::Shapes::Point2D, Magnum::Shapes::Point3D + * @brief Class @ref Magnum::Shapes::Point, typedef @ref Magnum::Shapes::Point2D, @ref Magnum::Shapes::Point3D */ #include "Magnum/DimensionTraits.h" @@ -39,7 +39,7 @@ namespace Magnum { namespace Shapes { @brief %Point See @ref shapes for brief introduction. -@see Point2D, Point3D +@see @ref Point2D, @ref Point3D */ template class MAGNUM_SHAPES_EXPORT Point { public: diff --git a/src/Magnum/Shapes/Shape.h b/src/Magnum/Shapes/Shape.h index e1c70e8ed..dafa95226 100644 --- a/src/Magnum/Shapes/Shape.h +++ b/src/Magnum/Shapes/Shape.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Shape + * @brief Class @ref Magnum::Shapes::Shape */ #include "Magnum/Shapes/AbstractShape.h" @@ -43,16 +43,17 @@ namespace Implementation { @brief Object shape Adds shape for collision detection to object. Each %Shape is part of -some ShapeGroup, which essentially maintains a set of objects which can +some @ref ShapeGroup, which essentially maintains a set of objects which can collide with each other. See @ref shapes for brief introduction. -The shape contains original shape with relative transformation under shape() -and also caches a shape with absolute transformation under transformedShape(), -which can be used for collision detection. To conveniently use collision -detection among many object, you need to add the shape to ShapeGroup, which -then provides collision detection for given group of shapes. You can also use -ShapeGroup::add() and ShapeGroup::remove() later to manage e.g. collision -islands. +The shape contains original shape with relative transformation under +@ref shape() and also caches a shape with absolute transformation under +@ref transformedShape(), which can be used for collision detection. To +conveniently use collision detection among many objects, you need to add the +shape to @ref ShapeGroup, which then provides collision detection for given +group of shapes using either @ref collides(), @ref collision() or +@ref ShapeGroup::firstCollision(). You can also use @ref ShapeGroup::add() and +@ref ShapeGroup::remove() later to manage e.g. collision islands. @code Shapes::ShapeGroup3D shapes; @@ -62,8 +63,8 @@ auto shape = new Shapes::Shape(object, {{}, 0.75f}, &shapes); Shapes::AbstractShape3D* firstCollision = shapes.firstCollision(shape); @endcode -@see @ref scenegraph, ShapeGroup2D, ShapeGroup3D, - DebugTools::ShapeRenderer +@see @ref scenegraph, @ref ShapeGroup2D, @ref ShapeGroup3D, + @ref DebugTools::ShapeRenderer */ template class Shape: public AbstractShape { friend struct Implementation::ShapeHelper; diff --git a/src/Magnum/Shapes/ShapeGroup.h b/src/Magnum/Shapes/ShapeGroup.h index 0b8295a4d..83ca485d9 100644 --- a/src/Magnum/Shapes/ShapeGroup.h +++ b/src/Magnum/Shapes/ShapeGroup.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::ShapeGroup, typedef Magnum::Shapes::ShapeGroup2D, Magnum::Shapes::ShapeGroup3D + * @brief Class @ref Magnum::Shapes::ShapeGroup, typedef @ref Magnum::Shapes::ShapeGroup2D, @ref Magnum::Shapes::ShapeGroup3D */ #include @@ -40,8 +40,8 @@ namespace Magnum { namespace Shapes { /** @brief Group of shapes -See Shape for more information. See @ref shapes for brief introduction. -@see @ref scenegraph, ShapeGroup2D, ShapeGroup3D +See @ref Shape for more information. See @ref shapes for brief introduction. +@see @ref scenegraph, @ref ShapeGroup2D, @ref ShapeGroup3D */ template class MAGNUM_SHAPES_EXPORT ShapeGroup: public SceneGraph::FeatureGroup, Float> { friend class AbstractShape; @@ -66,8 +66,7 @@ template class MAGNUM_SHAPES_EXPORT ShapeGroup: public S * If some body in the group changes its transformation, it sets dirty * status also on the group to indicate that the body and maybe also * group state needs to be cleaned before computing collisions. - * - * @see setClean() + * @see @ref setClean() */ void setDirty() { dirty = true; } @@ -83,7 +82,7 @@ template class MAGNUM_SHAPES_EXPORT ShapeGroup: public S * @brief First collision of given shape with other shapes in the group * * Returns first shape colliding with given one. If there aren't any - * collisions, returns `nullptr`. Calls setClean() before the + * collisions, returns `nullptr`. Calls @ref setClean() before the * operation. */ AbstractShape* firstCollision(const AbstractShape& shape); @@ -93,18 +92,18 @@ template class MAGNUM_SHAPES_EXPORT ShapeGroup: public S }; /** -@brief Group of two-dimensional shaped objects +@brief Group of two-dimensional shapes -See Shape for more information. -@see ShapeGroup3D +See @ref Shape for more information. +@see @ref ShapeGroup3D */ typedef ShapeGroup<2> ShapeGroup2D; /** -@brief Group of three-dimensional shaped objects +@brief Group of three-dimensional shapes -See Shape for more information. -@see ShapeGroup2D +See @ref Shape for more information. +@see @ref ShapeGroup2D */ typedef ShapeGroup<3> ShapeGroup3D; diff --git a/src/Magnum/Shapes/Shapes.h b/src/Magnum/Shapes/Shapes.h index 5773f0aac..0c5382b09 100644 --- a/src/Magnum/Shapes/Shapes.h +++ b/src/Magnum/Shapes/Shapes.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Forward declarations for Magnum::Shapes namespace + * @brief Forward declarations for @ref Magnum::Shapes namespace */ #include "Magnum/Types.h" diff --git a/src/Magnum/Shapes/Sphere.h b/src/Magnum/Shapes/Sphere.h index 42960ca66..0b02115d8 100644 --- a/src/Magnum/Shapes/Sphere.h +++ b/src/Magnum/Shapes/Sphere.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Shapes::Sphere, typedef Magnum::Shapes::Sphere2D, Magnum::Shapes::Sphere3D + * @brief Class @ref Magnum::Shapes::Sphere, typedef @ref Magnum::Shapes::Sphere2D, @ref Magnum::Shapes::Sphere3D */ #include "Magnum/DimensionTraits.h" @@ -42,7 +42,7 @@ namespace Magnum { namespace Shapes { Unlike other elements the sphere expects uniform scaling. See @ref shapes for brief introduction. -@see Sphere2D, Sphere3D +@see @ref Sphere2D, @ref Sphere3D @todo Store the radius as squared value to avoid sqrt/pow? Will complicate collision detection with another sphere. */ From 93de51c32f4d5c4b5dd8e3caa48cfb97183e19fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 13 Mar 2014 19:28:37 +0100 Subject: [PATCH 071/141] Added EXT_shader_integer_mix to extension list. --- doc/opengl-support.dox | 1 + src/Magnum/Context.cpp | 1 + src/Magnum/Extensions.h | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index f103f292b..7780c5b66 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -222,6 +222,7 @@ following: @extension{EXT,texture_filter_anisotropic} (also in ES) | done @extension{EXT,texture_mirror_clamp} | only GL 4.4 subset @extension{EXT,direct_state_access} | done for implemented functionality +@extension{EXT,shader_integer_mix} (also in ES) | done (shading language only) @extension2{EXT,debug_label} (also in ES) | missing pipeline, transform feedback and sampler label @extension2{EXT,debug_marker} (also in ES) | missing marker groups @extension{GREMEDY,string_marker} | done diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 7055aa9c3..66b4d90fe 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -61,6 +61,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,EXT,texture_filter_anisotropic), _extension(GL,EXT,texture_mirror_clamp), _extension(GL,EXT,direct_state_access), + _extension(GL,EXT,shader_integer_mix), _extension(GL,EXT,debug_label), _extension(GL,EXT,debug_marker), _extension(GL,GREMEDY,string_marker)}; diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index d9271cffc..841d5710c 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -182,6 +182,7 @@ namespace GL { _extension(GL,EXT,transform_feedback, GL210, GL300) // #352 _extension(GL,EXT,direct_state_access, GL210, None) // #353 _extension(GL,EXT,texture_snorm, GL300, GL310) // #365 + _extension(GL,EXT,shader_integer_mix, GL300, None) // #437 _extension(GL,EXT,debug_label, GL210, None) // #439 _extension(GL,EXT,debug_marker, GL210, None) // #440 } namespace GREMEDY { @@ -245,6 +246,9 @@ namespace GL { _extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121 #endif _extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150 + #ifndef MAGNUM_TARGET_GLES2 + _extension(GL,EXT,shader_integer_mix, GLES300, None) // #161 + #endif } namespace KHR { _extension(GL,KHR,debug, GLES200, None) // #118 } namespace NV { From cfca2b50df06d35fb263f7a029e75c82bc2d6756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 13 Mar 2014 19:28:57 +0100 Subject: [PATCH 072/141] Platform: doc++ Display actual named constants in Doxygen. --- src/Magnum/Platform/AndroidApplication.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index c650f517c..38d482c4b 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -436,7 +436,7 @@ class AndroidApplication::MouseEvent: public InputEvent { * @attention Available since Android 4.0 (API level 14), not * detectable in earlier versions. */ - #if __ANDROID_API__ >= 14 + #if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14 Left = AMOTION_EVENT_BUTTON_PRIMARY, #else Left = 1 << 0, @@ -447,7 +447,7 @@ class AndroidApplication::MouseEvent: public InputEvent { * @attention Available since Android 4.0 (API level 14), not * detectable in earlier versions. */ - #if __ANDROID_API__ >= 14 + #if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14 Middle = AMOTION_EVENT_BUTTON_TERTIARY, #else Middle = 1 << 1, @@ -458,7 +458,7 @@ class AndroidApplication::MouseEvent: public InputEvent { * @attention Available since Android 4.0 (API level 14), not * detectable in earlier versions. */ - #if __ANDROID_API__ >= 14 + #if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14 Right = AMOTION_EVENT_BUTTON_SECONDARY #else Right = 1 << 2 @@ -496,7 +496,7 @@ class AndroidApplication::MouseMoveEvent: public InputEvent { /** * @brief Mouse button * - * @see @ref button() + * @see @ref buttons() */ enum class Button: std::int32_t { /** @@ -505,7 +505,7 @@ class AndroidApplication::MouseMoveEvent: public InputEvent { * @attention Available since Android 4.0 (API level 14), not * detectable in earlier versions. */ - #if __ANDROID_API__ >= 14 + #if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14 Left = AMOTION_EVENT_BUTTON_PRIMARY, #else Left = 1 << 0, @@ -516,7 +516,7 @@ class AndroidApplication::MouseMoveEvent: public InputEvent { * @attention Available since Android 4.0 (API level 14), not * detectable in earlier versions. */ - #if __ANDROID_API__ >= 14 + #if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14 Middle = AMOTION_EVENT_BUTTON_TERTIARY, #else Middle = 1 << 1, @@ -527,7 +527,7 @@ class AndroidApplication::MouseMoveEvent: public InputEvent { * @attention Available since Android 4.0 (API level 14), not * detectable in earlier versions. */ - #if __ANDROID_API__ >= 14 + #if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14 Right = AMOTION_EVENT_BUTTON_SECONDARY #else Right = 1 << 2 From 8adde5537719aa7981d8ca8b5218cbbf95f107df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 13 Mar 2014 23:19:14 +0100 Subject: [PATCH 073/141] Platform: improve documentation of redraw() function. Make it clear that it's possible and non-harmful to call it from drawEvent() itself. --- src/Magnum/Platform/Sdl2Application.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index eb5289388..30cb1643e 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -283,7 +283,8 @@ class Sdl2Application { * @brief Redraw immediately * * Marks the window for redrawing, resulting in call to @ref drawEvent() - * in the next iteration. + * in the next iteration. You can call it from @ref drawEvent() itself + * to redraw immediately without waiting for user input. */ void redraw() { flags |= Flag::Redraw; } From 2f8e5f31a1570e629b1b1ccf5a85cd78fef2fbf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 13 Mar 2014 23:20:03 +0100 Subject: [PATCH 074/141] Make Image*::release() documentation clearer. --- src/Magnum/Image.h | 4 ++-- src/Magnum/Trade/ImageData.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Magnum/Image.h b/src/Magnum/Image.h index e8d1c3866..7a7d0d4d5 100644 --- a/src/Magnum/Image.h +++ b/src/Magnum/Image.h @@ -138,8 +138,8 @@ template class Image: public AbstractImage { /** * @brief Release data storage * - * Returns the data pointer and resets internal state to default. - * Deleting the returned array is user responsibility. + * Releases the ownership of the data pointer and resets internal state + * to default. Deleting the returned array is then user responsibility. * @see @ref setData() */ unsigned char* release(); diff --git a/src/Magnum/Trade/ImageData.h b/src/Magnum/Trade/ImageData.h index c50ac610b..7ce0c1753 100644 --- a/src/Magnum/Trade/ImageData.h +++ b/src/Magnum/Trade/ImageData.h @@ -109,8 +109,8 @@ template class ImageData: public AbstractImage { /** * @brief Release data storage * - * Returns the data pointer and resets internal state to default. - * Deleting the returned array is user responsibility. + * Releases the ownership of the data pointer and resets internal state + * to default. Deleting the returned array is then user responsibility. * @see @ref data() */ unsigned char* release(); From 05f677cc302ac8c0d6250a338d70062f9094dddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 11:36:43 +0100 Subject: [PATCH 075/141] Platform: removed deprecated Flags from Sdl2Application::Configuration. WindowFlags should be used instead, these would now conflict with context flags. --- src/Magnum/Platform/Sdl2Application.h | 40 --------------------------- 1 file changed, 40 deletions(-) diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 30cb1643e..e4dd18f64 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -42,10 +42,6 @@ #include #include -#ifdef MAGNUM_BUILD_DEPRECATED -#include -#endif - namespace Magnum { class Context; @@ -441,14 +437,6 @@ class Sdl2Application::Configuration { MouseLocked = SDL_WINDOW_INPUT_GRABBED /**< Window with mouse locked */ }; - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief WindowFlag - * @deprecated Use @ref Magnum::Platform::Sdl2Application::Configuration::WindowFlag "WindowFlag" instead. - */ - typedef CORRADE_DEPRECATED("use WindowFlag instead") WindowFlag Flag; - #endif - /** * @brief Window flags * @@ -462,14 +450,6 @@ class Sdl2Application::Configuration { typedef Containers::EnumSet WindowFlags; #endif - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief WindowFlags - * @deprecated Use @ref Magnum::Platform::Sdl2Application::Configuration::WindowFlags "WindowFlags" instead. - */ - typedef CORRADE_DEPRECATED("use WindowFlags instead") WindowFlags Flags; - #endif - /*implicit*/ Configuration(); ~Configuration(); @@ -517,16 +497,6 @@ class Sdl2Application::Configuration { /** @brief Window flags */ WindowFlags windowFlags() const { return _windowFlags; } - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief windowFlags() - * @deprecated Use @ref Magnum::Platform::Sdl2Application::Configuration::windowFlags() "windowFlags()" instead. - */ - CORRADE_DEPRECATED("use windowFlags() instead") WindowFlags flags() const { - return windowFlags(); - } - #endif - /** * @brief Set window flags * @return Reference to self (for method chaining) @@ -538,16 +508,6 @@ class Sdl2Application::Configuration { return *this; } - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief setWindowFlags() - * @deprecated Use @ref Magnum::Platform::Sdl2Application::Configuration::setWindowFlags "setWindowFlags()" instead. - */ - CORRADE_DEPRECATED("use setWindowFlags() instead") Configuration& setFlags(WindowFlags flags) { - return setWindowFlags(flags); - } - #endif - #ifndef CORRADE_TARGET_EMSCRIPTEN /** * @brief Context version From 25994f28ab1d19eed6bbc1740c7c4ba58cd63a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 12:24:51 +0100 Subject: [PATCH 076/141] Follow OpenGL naming in Context::Flag enum. As usual, the old Context::Flag::Robustness is marked deprecated and will be removed in future release. --- src/Magnum/Context.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index 7ddcc5291..b471ec9b9 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -119,14 +119,22 @@ class MAGNUM_EXPORT Context { #ifndef MAGNUM_TARGET_GLES /** - * Context with robust buffer access + * Context with robust access * @requires_extension %Extension @extension{ARB,robustness} * @requires_es_extension %Extension @es_extension{EXT,robustness} * @todo In ES available under glGetIntegerv(CONTEXT_ROBUST_ACCESS_EXT), * how to make it compatible? */ + RobustAccess = GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB, + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief Context::Flag::RobustAccess + * @deprecated Use @ref Magnum::Context::Flag::RobustAccess "Context::Flag::RobustAccess" instead. + */ Robustness = GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB #endif + #endif }; /** From ca320d9e37ad7433a632671bfbc4560efcf11281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 12:26:58 +0100 Subject: [PATCH 077/141] Debug output operator for Context::Flag enum. --- src/Magnum/Context.cpp | 10 +++++++ src/Magnum/Context.h | 3 ++ src/Magnum/Test/CMakeLists.txt | 1 + src/Magnum/Test/ContextTest.cpp | 52 +++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+) create mode 100644 src/Magnum/Test/ContextTest.cpp diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 66b4d90fe..9eaa7c40a 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -514,4 +514,14 @@ Version Context::supportedVersion(std::initializer_list versions) const #endif } +Debug operator<<(Debug debug, const Context::Flag value) { + switch(value) { + #define _c(value) case Context::Flag::value: return debug << "Context::Flag::" #value; + _c(Debug) + _c(RobustAccess) + } + + return debug << "Context::Flag::(invalid)"; +} + } diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index b471ec9b9..cf44a5e6a 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -403,6 +403,9 @@ class MAGNUM_EXPORT Context { Implementation::State* _state; }; +/** @debugoperator{Magnum::Context} */ +MAGNUM_EXPORT Debug operator<<(Debug debug, Context::Flag value); + /** @hideinitializer @brief Assert that given OpenGL version is supported @param version Version diff --git a/src/Magnum/Test/CMakeLists.txt b/src/Magnum/Test/CMakeLists.txt index 76f3eafa3..eb8f51ff1 100644 --- a/src/Magnum/Test/CMakeLists.txt +++ b/src/Magnum/Test/CMakeLists.txt @@ -27,6 +27,7 @@ corrade_add_test(AbstractImageTest AbstractImageTest.cpp LIBRARIES Magnum) corrade_add_test(AbstractShaderProgramTest AbstractShaderProgramTest.cpp LIBRARIES Magnum) corrade_add_test(ArrayTest ArrayTest.cpp) corrade_add_test(ColorTest ColorTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(ContextTest ContextTest.cpp LIBRARIES Magnum) corrade_add_test(DebugMessageTest DebugMessageTest.cpp LIBRARIES Magnum) corrade_add_test(DefaultFramebufferTest DefaultFramebufferTest.cpp LIBRARIES Magnum) corrade_add_test(FramebufferTest FramebufferTest.cpp LIBRARIES Magnum) diff --git a/src/Magnum/Test/ContextTest.cpp b/src/Magnum/Test/ContextTest.cpp new file mode 100644 index 000000000..cb1b76327 --- /dev/null +++ b/src/Magnum/Test/ContextTest.cpp @@ -0,0 +1,52 @@ +/* + 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 +#include + +#include "Magnum/Context.h" + +namespace Magnum { namespace Test { + +class ContextTest: public TestSuite::Tester { + public: + explicit ContextTest(); + + void debugFlag(); +}; + +ContextTest::ContextTest() { + addTests({&ContextTest::debugFlag}); +} + +void ContextTest::debugFlag() { + std::ostringstream out; + Debug(&out) << Context::Flag::Debug; + CORRADE_COMPARE(out.str(), "Context::Flag::Debug\n"); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::ContextTest) From 6c2740b7d98447addd6e552a6164745c7652f68c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 12:27:24 +0100 Subject: [PATCH 078/141] Platform: print context flags in magnum-info. --- src/Magnum/Platform/magnum-info.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index 545d491b5..f381da939 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -142,6 +142,10 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat Debug() << "Renderer:" << c->rendererString(); Debug() << "OpenGL version:" << c->version() << '(' + c->versionString() + ')'; + Debug() << "Context flags:"; + for(const auto flag: {Context::Flag::Debug, Context::Flag::RobustAccess}) + if(c->flags() & flag) Debug() << " " << flag; + Debug() << "Supported GLSL versions:"; const std::vector shadingLanguageVersions = c->shadingLanguageVersionStrings(); for(const auto& version: shadingLanguageVersions) From 2e700ee3841e8e631acfdbde19a7e1df916fb10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 12:27:46 +0100 Subject: [PATCH 079/141] Platform: create context later so its output is at better place. --- src/Magnum/Platform/magnum-info.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index f381da939..faaee7d3b 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -73,11 +73,6 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat args.parse(arguments.argc, arguments.argv); #endif - /* Create context after parsing arguments, so the help can be displayed - without creating context */ - createContext(); - Context* c = Context::current(); - /* Pass debug output as messages to JavaScript */ #ifdef CORRADE_TARGET_NACL Utility::NaClMessageStreamBuffer buffer(this); @@ -138,6 +133,10 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat #endif Debug() << ""; + /* Create context here, so the context creation info is displayed at proper + place */ + createContext(); + Context* c = Context::current(); Debug() << "Vendor:" << c->vendorString(); Debug() << "Renderer:" << c->rendererString(); Debug() << "OpenGL version:" << c->version() << '(' + c->versionString() + ')'; From 0d7f7791250ddae3de63d7ebe6b1281991dbdf74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 12:30:07 +0100 Subject: [PATCH 080/141] Platform: don't display limits by default. The output with limits is overly verbose and I caught myself typing `magnum-info --no-limits` all the time, so let's reverse the default. --- src/Magnum/Platform/magnum-info.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index faaee7d3b..2f7ab955c 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -61,8 +61,8 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat Utility::Arguments args; args.addBooleanOption("all-extensions") .setHelp("all-extensions", "show extensions also for fully supported versions") - .addBooleanOption("no-limits") - .setHelp("no-limits", "don't display limits and implementation-defined values") + .addBooleanOption("limits") + .setHelp("limits", "display also limits and implementation-defined values") .setHelp("Displays information about Magnum engine and OpenGL capabilities."); /** @@ -198,7 +198,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat Debug() << ""; } - if(args.isSet("no-limits")) return; + if(!args.isSet("limits")) return; /* Limits and implementation-defined values */ #define _h(val) Debug() << "\n " << Extensions::GL::val::string() + std::string(":"); From c275640ee0169db95b3f423915e915a196e5ec7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 12:43:06 +0100 Subject: [PATCH 081/141] Platform: ability to specify context flags in Sdl2Application. Finally proper support for debug contexts :-) --- src/Magnum/Context.h | 2 +- src/Magnum/Platform/Sdl2Application.cpp | 3 ++ src/Magnum/Platform/Sdl2Application.h | 40 +++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Context.h b/src/Magnum/Context.h index cf44a5e6a..f74fd887e 100644 --- a/src/Magnum/Context.h +++ b/src/Magnum/Context.h @@ -103,7 +103,7 @@ class MAGNUM_EXPORT Context { /** * @brief Context flag * - * @see @ref Flags, @ref flags() + * @see @ref Flags, @ref flags(), @ref Platform::Sdl2Application::Configuration::setFlags() "Platform::*Application::Configuration::setFlags()" */ enum class Flag: GLint { /** diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 2735cfcbf..0a2c86728 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -109,6 +109,9 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, configuration.sampleCount() > 1 ? 1 : 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration.sampleCount()); + /* Context flags */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(configuration.flags())); + /* Flags: if not hidden, set as shown */ Uint32 windowFlags(configuration.windowFlags()); if(!(configuration.windowFlags() & Configuration::WindowFlag::Hidden)) windowFlags |= SDL_WINDOW_SHOWN; diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index e4dd18f64..222e0e1f0 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -423,6 +423,30 @@ depth buffer. */ class Sdl2Application::Configuration { public: + /** + * @brief Context flag + * + * @see @ref Flags @ref setFlags() + */ + enum class Flag: int { + Debug = SDL_GL_CONTEXT_DEBUG_FLAG, /**< Create debug context */ + + /** Create context with robust access */ + RobustAccess = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG + }; + + /** + * @brief Context flags + * + * @see @ref setFlags() + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + typedef Containers::EnumSet Flags; + #else + typedef Containers::EnumSet Flags; + #endif + /** * @brief Window flag * @@ -508,6 +532,20 @@ class Sdl2Application::Configuration { return *this; } + /** @brief Context flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + #ifndef CORRADE_TARGET_EMSCRIPTEN /** * @brief Context version @@ -561,8 +599,10 @@ class Sdl2Application::Configuration { #ifndef CORRADE_TARGET_EMSCRIPTEN Version _version; #endif + Flags _flags; }; +CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::Flags) CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::WindowFlags) /** From 085d96ce2584c70322deff04633bc8bdddb086cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 12:43:42 +0100 Subject: [PATCH 082/141] Platform: support for debug context flag in GlutApplication. For some weird reason this doesn't work for me. --- src/Magnum/Platform/GlutApplication.cpp | 3 ++ src/Magnum/Platform/GlutApplication.h | 37 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/Magnum/Platform/GlutApplication.cpp b/src/Magnum/Platform/GlutApplication.cpp index 58f8bc1ec..8009451b4 100644 --- a/src/Magnum/Platform/GlutApplication.cpp +++ b/src/Magnum/Platform/GlutApplication.cpp @@ -90,6 +90,9 @@ bool GlutApplication::tryCreateContext(const Configuration& configuration) { #endif } + /* Set context flags */ + glutInitContextFlags(int(configuration.flags())); + if(!glutCreateWindow(configuration.title().data())) { Error() << "Platform::GlutApplication::tryCreateContext(): cannot create context"; return false; diff --git a/src/Magnum/Platform/GlutApplication.h b/src/Magnum/Platform/GlutApplication.h index 4947351da..6ab203118 100644 --- a/src/Magnum/Platform/GlutApplication.h +++ b/src/Magnum/Platform/GlutApplication.h @@ -280,6 +280,26 @@ Double-buffered RGBA window with depth and stencil buffers. */ class GlutApplication::Configuration { public: + /** + * @brief Context flag + * + * @see @ref Flags @ref setFlags() + */ + enum class Flag: int { + Debug = GLUT_DEBUG /**< Create debug context */ + }; + + /** + * @brief Context flags + * + * @see @ref setFlags() + */ + #ifndef DOXYGEN_GENERATING_OUTPUT + typedef Containers::EnumSet Flags; + #else + typedef Containers::EnumSet Flags; + #endif + /*implicit*/ Configuration(); ~Configuration(); @@ -311,6 +331,20 @@ class GlutApplication::Configuration { return *this; } + /** @brief Context flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + /** @brief Context version */ Version version() const { return _version; } @@ -348,8 +382,11 @@ class GlutApplication::Configuration { Vector2i _size; Int _sampleCount; Version _version; + Flags _flags; }; +CORRADE_ENUMSET_OPERATORS(GlutApplication::Configuration::Flags) + /** @brief Base for input events From d4ec4ed3392bbf0b2b53e2da212bc05e0ba15bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 12:46:36 +0100 Subject: [PATCH 083/141] package: run the tests multiprocess. They are now taking too long (9 secs), with -j5 just 3 secs. --- package/archlinux/PKGBUILD | 2 +- package/archlinux/PKGBUILD-clang | 2 +- package/archlinux/PKGBUILD-clang-libc++ | 2 +- package/archlinux/PKGBUILD-es2 | 2 +- package/archlinux/PKGBUILD-es2desktop | 2 +- package/archlinux/PKGBUILD-es3 | 2 +- package/archlinux/PKGBUILD-es3desktop | 2 +- package/archlinux/PKGBUILD-gcc46 | 2 +- package/archlinux/PKGBUILD-gcc47 | 2 +- package/archlinux/PKGBUILD-gcc49 | 2 +- package/archlinux/PKGBUILD-release | 2 +- package/ci/jenkins-gltests.xml | 2 +- package/ci/jenkins.xml | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package/archlinux/PKGBUILD b/package/archlinux/PKGBUILD index 16162524e..23bd12817 100644 --- a/package/archlinux/PKGBUILD +++ b/package/archlinux/PKGBUILD @@ -44,7 +44,7 @@ build() { check() { cd "$startdir/build" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-clang b/package/archlinux/PKGBUILD-clang index 16ca20095..5e213067b 100644 --- a/package/archlinux/PKGBUILD-clang +++ b/package/archlinux/PKGBUILD-clang @@ -47,7 +47,7 @@ build() { check() { cd "$startdir/build-clang" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-clang-libc++ b/package/archlinux/PKGBUILD-clang-libc++ index 6cd676c9c..4ef88c32a 100644 --- a/package/archlinux/PKGBUILD-clang-libc++ +++ b/package/archlinux/PKGBUILD-clang-libc++ @@ -49,7 +49,7 @@ build() { check() { cd "$startdir/build-clang-libc++" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-es2 b/package/archlinux/PKGBUILD-es2 index 7e9265775..3cbd211ff 100644 --- a/package/archlinux/PKGBUILD-es2 +++ b/package/archlinux/PKGBUILD-es2 @@ -34,7 +34,7 @@ build() { check() { cd "$startdir/build-es2" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-es2desktop b/package/archlinux/PKGBUILD-es2desktop index 2d9847e2c..dee3cf815 100644 --- a/package/archlinux/PKGBUILD-es2desktop +++ b/package/archlinux/PKGBUILD-es2desktop @@ -39,7 +39,7 @@ build() { check() { cd "$startdir/build-es2desktop" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-es3 b/package/archlinux/PKGBUILD-es3 index d88141992..c13f5029f 100644 --- a/package/archlinux/PKGBUILD-es3 +++ b/package/archlinux/PKGBUILD-es3 @@ -34,7 +34,7 @@ build() { check() { cd "$startdir/build-es3" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-es3desktop b/package/archlinux/PKGBUILD-es3desktop index 2ca7c0c15..2b7a1a517 100644 --- a/package/archlinux/PKGBUILD-es3desktop +++ b/package/archlinux/PKGBUILD-es3desktop @@ -39,7 +39,7 @@ build() { check() { cd "$startdir/build-es3desktop" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-gcc46 b/package/archlinux/PKGBUILD-gcc46 index eb72eb27c..a3a545de7 100644 --- a/package/archlinux/PKGBUILD-gcc46 +++ b/package/archlinux/PKGBUILD-gcc46 @@ -47,7 +47,7 @@ build() { check() { cd "$startdir/build-gcc46" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-gcc47 b/package/archlinux/PKGBUILD-gcc47 index a9c4abd8f..eabf2142c 100644 --- a/package/archlinux/PKGBUILD-gcc47 +++ b/package/archlinux/PKGBUILD-gcc47 @@ -47,7 +47,7 @@ build() { check() { cd "$startdir/build-gcc47" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-gcc49 b/package/archlinux/PKGBUILD-gcc49 index 8d524a66b..1421f402c 100644 --- a/package/archlinux/PKGBUILD-gcc49 +++ b/package/archlinux/PKGBUILD-gcc49 @@ -47,7 +47,7 @@ build() { check() { cd "$startdir/build-gcc49" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/archlinux/PKGBUILD-release b/package/archlinux/PKGBUILD-release index 9d1266bd8..fd9c48abd 100644 --- a/package/archlinux/PKGBUILD-release +++ b/package/archlinux/PKGBUILD-release @@ -40,7 +40,7 @@ build() { check() { cd "$startdir/build" - ctest --output-on-failure + ctest --output-on-failure -j5 } package() { diff --git a/package/ci/jenkins-gltests.xml b/package/ci/jenkins-gltests.xml index e99fc6197..df9c6b0f9 100644 --- a/package/ci/jenkins-gltests.xml +++ b/package/ci/jenkins-gltests.xml @@ -80,7 +80,7 @@ cd build-${compiler}-${libraries}-${compatibility}-${gl} ninja -ctest --output-on-failure -R GLTest || true +ctest --output-on-failure -R GLTest -j5 || true ]]> diff --git a/package/ci/jenkins.xml b/package/ci/jenkins.xml index beeaf2498..b6cbc71f5 100644 --- a/package/ci/jenkins.xml +++ b/package/ci/jenkins.xml @@ -153,7 +153,7 @@ cmake .. \ -G Ninja ninja -ctest --output-on-failure -E GLTest || true +ctest --output-on-failure -E GLTest -j5 || true ninja install ]]> From b5814305bd795e99e995d62cbc892ecc14a681dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 13:05:08 +0100 Subject: [PATCH 084/141] Missing undef. --- src/Magnum/Context.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 9eaa7c40a..4142ee6b6 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -519,6 +519,7 @@ Debug operator<<(Debug debug, const Context::Flag value) { #define _c(value) case Context::Flag::value: return debug << "Context::Flag::" #value; _c(Debug) _c(RobustAccess) + #undef _c } return debug << "Context::Flag::(invalid)"; From 617e52436ac52dfbdacd8d6f7d9f43d51b85af3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 13:07:17 +0100 Subject: [PATCH 085/141] Fix ES build. --- src/Magnum/Context.cpp | 2 ++ src/Magnum/Platform/magnum-info.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 4142ee6b6..2e6be867a 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -518,7 +518,9 @@ Debug operator<<(Debug debug, const Context::Flag value) { switch(value) { #define _c(value) case Context::Flag::value: return debug << "Context::Flag::" #value; _c(Debug) + #ifndef MAGNUM_TARGET_GLES _c(RobustAccess) + #endif #undef _c } diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index 2f7ab955c..999de991a 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -142,7 +142,11 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat Debug() << "OpenGL version:" << c->version() << '(' + c->versionString() + ')'; Debug() << "Context flags:"; + #ifndef MAGNUM_TARGET_GLES for(const auto flag: {Context::Flag::Debug, Context::Flag::RobustAccess}) + #else + for(const auto flag: {Context::Flag::Debug}) + #endif if(c->flags() & flag) Debug() << " " << flag; Debug() << "Supported GLSL versions:"; From fde41147be8342a45130e5130b326e8dfcabecff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 14 Mar 2014 14:03:54 +0100 Subject: [PATCH 086/141] ObjImporter: fix compilation on GCC 4.6. --- src/MagnumPlugins/ObjImporter/ObjImporter.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp index dbcb66361..932e509c1 100644 --- a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp +++ b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp @@ -152,7 +152,12 @@ void ObjImporter::parseMeshNames() { thisIsFirstMeshAndItHasNoData = false; /* Update its name and add it to name map */ - if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size() - 1); + if(!name.empty()) + #ifndef CORRADE_GCC46_COMPATIBILITY + _file->meshesForName.emplace(name, _file->meshes.size() - 1); + #else + _file->meshesForName.insert({name, _file->meshes.size() - 1}); + #endif _file->meshNames.back() = std::move(name); /* Update its begin offset to be more precise */ @@ -165,7 +170,12 @@ void ObjImporter::parseMeshNames() { /* Save name and offset of the new one. The end offset will be updated later. */ - if(!name.empty()) _file->meshesForName.emplace(name, _file->meshes.size()); + if(!name.empty()) + #ifndef CORRADE_GCC46_COMPATIBILITY + _file->meshesForName.emplace(name, _file->meshes.size()); + #else + _file->meshesForName.insert({name, _file->meshes.size()}); + #endif _file->meshNames.emplace_back(std::move(name)); _file->meshes.emplace_back(_file->in->tellg(), 0, positionIndexOffset, textureCoordinateIndexOffset, normalIndexOffset); } From 4ce013515455a4e472abb8f19fdfcd21b52140d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 15 Mar 2014 14:54:43 +0100 Subject: [PATCH 087/141] package: fix Emscripten PKGBUILD. Caused by cb987f25d3568c30b4f01d2cc77921d705278e3a, unnoticed since. --- package/archlinux/PKGBUILD-emscripten | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/archlinux/PKGBUILD-emscripten b/package/archlinux/PKGBUILD-emscripten index 91d29d943..e25fa841f 100644 --- a/package/archlinux/PKGBUILD-emscripten +++ b/package/archlinux/PKGBUILD-emscripten @@ -17,7 +17,7 @@ build() { cmake .. \ -DCMAKE_MODULE_PATH="$startdir/toolchains/modules" \ - -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Emscripten.cmake \ + -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Emscripten.cmake" \ -G Ninja fi From b5017752a3646bb0baac9e8ef0d8fe4ffd8e4e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 15 Mar 2014 15:06:18 +0100 Subject: [PATCH 088/141] Platform: fix Emscripten build. --- src/Magnum/Platform/Sdl2Application.cpp | 2 ++ src/Magnum/Platform/Sdl2Application.h | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 0a2c86728..14cd04f21 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -109,8 +109,10 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, configuration.sampleCount() > 1 ? 1 : 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration.sampleCount()); + #ifndef CORRADE_TARGET_EMSCRIPTEN /* Context flags */ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(configuration.flags())); + #endif /* Flags: if not hidden, set as shown */ Uint32 windowFlags(configuration.windowFlags()); diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 222e0e1f0..caab3163a 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -423,10 +423,13 @@ depth buffer. */ class Sdl2Application::Configuration { public: + #ifndef CORRADE_TARGET_EMSCRIPTEN /** * @brief Context flag * + * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". * @see @ref Flags @ref setFlags() + * @todo re-enable when Emscripten has proper SDL2 support */ enum class Flag: int { Debug = SDL_GL_CONTEXT_DEBUG_FLAG, /**< Create debug context */ @@ -438,6 +441,7 @@ class Sdl2Application::Configuration { /** * @brief Context flags * + * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". * @see @ref setFlags() */ #ifndef DOXYGEN_GENERATING_OUTPUT @@ -446,6 +450,7 @@ class Sdl2Application::Configuration { #else typedef Containers::EnumSet Flags; #endif + #endif /** * @brief Window flag @@ -532,7 +537,12 @@ class Sdl2Application::Configuration { return *this; } - /** @brief Context flags */ + #ifndef CORRADE_TARGET_EMSCRIPTEN + /** + * @brief Context flags + * + * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". + */ Flags flags() const { return _flags; } /** @@ -540,13 +550,13 @@ class Sdl2Application::Configuration { * @return Reference to self (for method chaining) * * Default is no flag. + * @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". */ Configuration& setFlags(Flags flags) { _flags = flags; return *this; } - #ifndef CORRADE_TARGET_EMSCRIPTEN /** * @brief Context version * @@ -598,11 +608,13 @@ class Sdl2Application::Configuration { Int _sampleCount; #ifndef CORRADE_TARGET_EMSCRIPTEN Version _version; - #endif Flags _flags; + #endif }; +#ifndef CORRADE_TARGET_EMSCRIPTEN CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::Flags) +#endif CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::WindowFlags) /** From 7a1789470af135e0dd0f73d739633a7d0d213547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 18 Mar 2014 21:51:15 +0100 Subject: [PATCH 089/141] Initial ARB_multi_bind usage in *Texture::bind(). --- doc/opengl-mapping.dox | 3 +-- doc/opengl-support.dox | 2 +- src/Magnum/AbstractTexture.cpp | 8 ++++++++ src/Magnum/AbstractTexture.h | 24 ++++++++++++++-------- src/Magnum/Implementation/TextureState.cpp | 16 +++++++++++++-- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index c855e4bb8..7d77dc62f 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -62,8 +62,7 @@ OpenGL function | Matching API @fn_gl{BindRenderbuffer} | not needed, handhled internally in @ref Renderbuffer @fn_gl{BindSampler} | | @fn_gl{BindSamplers} | | -@fn_gl{BindTexture}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind() -@fn_gl{BindTextures} | | +@fn_gl{BindTexture}, \n @fn_gl{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind() @fn_gl{BindTransformFeedback} | | @fn_gl{BindVertexArray} | not needed, handhled internally in @ref Mesh @fn_gl{BindVertexBuffer} | | diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 7780c5b66..7a6a4e8bd 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -201,7 +201,7 @@ following: @extension{ARB,buffer_storage} | | @extension{ARB,clear_texture} | | @extension{ARB,enhanced_layouts} | done (shading language only) -@extension{ARB,multi_bind} | | +@extension{ARB,multi_bind} | only single texture binding @extension{ARB,query_buffer_object} | | @extension{ARB,texture_mirror_clamp_to_edge} | done @extension{ARB,texture_stencil8} | done diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 5594093c5..83eee7b62 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -137,6 +137,10 @@ void AbstractTexture::bindImplementationDefault(GLint layer) { } #ifndef MAGNUM_TARGET_GLES +void AbstractTexture::bindImplementationMulti(GLint layer) { + glBindTextures(layer, 1, &_id); +} + void AbstractTexture::bindImplementationDSA(GLint layer) { glBindMultiTextureEXT(GL_TEXTURE0 + layer, _target, (Context::current()->state().texture->bindings[layer] = _id)); } @@ -182,6 +186,10 @@ void AbstractTexture::mipmapImplementationDSA() { #endif void AbstractTexture::bindInternal() { + /* Using glBindTextures() here is meaningless, because the non-DSA + functions need to have the texture bound in *currently active* layer, + so we would need to call glActiveTexture() afterwards anyway. */ + Implementation::TextureState* const textureState = Context::current()->state().texture; /* If the texture is already bound in current layer, nothing to do */ diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 7062fbd64..136b46b4d 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -52,11 +52,15 @@ affect active bindings in user layers. %Texture limits and implementation-defined values (such as @ref maxColorSamples()) are cached, so repeated queries don't result in repeated @fn_gl{Get} calls. -If extension @extension{EXT,direct_state_access} is available, @ref bind() uses -DSA function to avoid unnecessary calls to @fn_gl{ActiveTexture}. Also all -texture configuration and data updating functions use DSA functions to avoid -unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. See -respective function documentation for more information. +If extension @extension{ARB,multi_bind} is available, @ref bind() uses +@fn_gl{BindTextures} to avoid unnecessary calls to @fn_gl{ActiveTexture}. +Otherwise, if extension @extension{EXT,direct_state_access} is available, +@ref bind() uses the DSA function. + +In addition, if extension @extension{EXT,direct_state_access} is available, +also all texture configuration and data updating functions use DSA functions +to avoid unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. +See respective function documentation for more information. If extension @extension{ARB,robustness} is available, image reading operations (such as @ref Texture::image()) are protected from buffer overflow. However, if @@ -208,13 +212,14 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * @brief Bind texture for rendering * * Sets current texture as active in given layer. Note that only one - * texture can be bound to given layer. If @extension{EXT,direct_state_access} - * is not available, the layer is made active before binding the - * texture. + * texture can be bound to given layer. If @extension{ARB,multi_bind} + * (part of OpenGL 4.4) or @extension{EXT,direct_state_access} is not + * available, the layer is made active before binding the texture. * @note This function is meant to be used only internally from * @ref AbstractShaderProgram subclasses. See its documentation * for more information. - * @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or + * @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}, + * @fn_gl{BindTextures} or * @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} */ void bind(Int layer); @@ -248,6 +253,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { private: void MAGNUM_LOCAL bindImplementationDefault(GLint layer); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL bindImplementationMulti(GLint layer); void MAGNUM_LOCAL bindImplementationDSA(GLint layer); #endif diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index dc1eab00b..845ade148 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -41,12 +41,25 @@ TextureState::TextureState(Context& context, std::vector& extension , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) #endif { + /* Bind implementation */ + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ARB::multi_bind::string()); + bindImplementation = &AbstractTexture::bindImplementationMulti; + } else if(context.isExtensionSupported()) { + /* Extension name added below */ + bindImplementation = &AbstractTexture::bindImplementationDSA; + } else + #endif + { + bindImplementation = &AbstractTexture::bindImplementationDefault; + } + /* DSA/non-DSA implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); - bindImplementation = &AbstractTexture::bindImplementationDSA; parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSA; parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; @@ -65,7 +78,6 @@ TextureState::TextureState(Context& context, std::vector& extension } else #endif { - bindImplementation = &AbstractTexture::bindImplementationDefault; parameteriImplementation = &AbstractTexture::parameterImplementationDefault; parameterfImplementation = &AbstractTexture::parameterImplementationDefault; parameterfvImplementation = &AbstractTexture::parameterImplementationDefault; From 22155e575a7f137fce66a82678535dbafce30806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 18 Mar 2014 22:02:51 +0100 Subject: [PATCH 090/141] Don't show *_EXPORT macros in the documentation. Got broken probably when trying to work around the issues with CORRADE_DEPRECATED() macro. --- Doxyfile | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Doxyfile b/Doxyfile index 542a114ab..ec1dd4e2d 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1653,7 +1653,19 @@ INCLUDE_FILE_PATTERNS = # instead of the = operator. PREDEFINED = DOXYGEN_GENERATING_OUTPUT \ - MAGNUM_BUILD_DEPRECATED CORRADE_DEPRECATED(message)= + MAGNUM_BUILD_DEPRECATED CORRADE_DEPRECATED(message)= \ + MAGNUM_EXPORT= \ + MAGNUM_AUDIO_EXPORT= \ + MAGNUM_DEBUGTOOLS_EXPORT= \ + MAGNUM_MATH_EXPORT= \ + MAGNUM_MESHTOOLS_EXPORT= \ + MAGNUM_PLATFORM_EXPORT= \ + MAGNUM_PRIMITIVES_EXPORT= \ + MAGNUM_SCENEGRAPH_EXPORT= \ + MAGNUM_SHADERS_EXPORT= \ + MAGNUM_SHAPES_EXPORT= \ + MAGNUM_TEXT_EXPORT= \ + MAGNUM_TEXTURETOOLS_EXPORT= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. From 8e9aa554f7b7ec517768cf2e6e64ca4593bb99b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 18 Mar 2014 22:05:10 +0100 Subject: [PATCH 091/141] Doc++ --- src/Magnum/AbstractTexture.h | 2 +- src/Magnum/Context.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 136b46b4d..ace81fc3a 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -83,7 +83,7 @@ OpenGL ES 3.0 or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not available, the feature is emulated with sequence of @ref Texture::setImage() "setImage()" calls. -You can use functions @ref Texture::invalidateImage() and +You can use functions @ref Texture::invalidateImage() "invalidateImage()" and @ref Texture::invalidateSubImage() "invalidateSubImage()" if you don't need texture data anymore to avoid unnecessary memory operations performed by OpenGL in order to preserve the data. If running on OpenGL ES or extension diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 2e6be867a..931daa7d2 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -514,6 +514,7 @@ Version Context::supportedVersion(std::initializer_list versions) const #endif } +#ifndef DOXYGEN_GENERATING_OUTPUT Debug operator<<(Debug debug, const Context::Flag value) { switch(value) { #define _c(value) case Context::Flag::value: return debug << "Context::Flag::" #value; @@ -526,5 +527,6 @@ Debug operator<<(Debug debug, const Context::Flag value) { return debug << "Context::Flag::(invalid)"; } +#endif } From a72ca4b2b67a63c2c4a02deeeac7ba9b9bf846c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 23 Mar 2014 19:26:23 +0100 Subject: [PATCH 092/141] Math: doc++ --- doc/matrix-vector.dox | 8 ++++---- doc/types.dox | 11 ++++++----- src/Magnum/Math/Angle.h | 14 +++++++------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/doc/matrix-vector.dox b/doc/matrix-vector.dox index 3b2739cb7..a7a3da78c 100644 --- a/doc/matrix-vector.dox +++ b/doc/matrix-vector.dox @@ -121,7 +121,8 @@ Int[] mat = { 2, 4, 6, 1, 3, 5 }; Math::Matrix2x3::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 } @endcode -Note that unlike constructors, this function has no way to check whether the + +Note that, unlike constructors, this function has no way to check whether the array is long enough to contain all elements, so use with caution. You can also *explicitly* convert between data types: @@ -133,8 +134,7 @@ auto integral = Vector4i(floating); // {1, 2, -15, 7} @section matrix-vector-component-access Accessing matrix and vector components Column vectors of matrices and vector components can be accessed using square -brackets, there is also round bracket operator for accessing matrix components -directly: +brackets: @code Matrix3x2 a; a[2] /= 2.0f; // third column (column major indexing, see explanation below) @@ -145,7 +145,7 @@ b[1] = 1; // second element @endcode Row vectors can be accessed too, but only for reading, and the access is slower -due to the way the matrix is stored (see explanation below): +due to the way the matrix is stored (see @ref matrix-vector-column-major "explanation below"): @code Vector2i c = a.row(2); // third row @endcode diff --git a/doc/types.dox b/doc/types.dox index ba8ff3af0..fb3a8a0c5 100644 --- a/doc/types.dox +++ b/doc/types.dox @@ -92,16 +92,17 @@ equivalently (e.g. @ref Math::Vector or @ref Color3 instead of @ref Vector3). Other types, which don't have their GLSL equivalent, are: - @ref Complex or @ref Complexd, @ref DualComplex or @ref DualComplexd -- @ref Quaternion or @ref Quaterniond, @ref DualQuaternion or @ref DualQuaterniond -- @ref Range1D / @ref Range2D / @ref Range3D, @ref Range1Di / @ref Range2Di / @ref Range3Di or - @ref Range1Dd / @ref Range2Dd / @ref Range3Dd +- @ref Quaternion or @ref Quaterniond, @ref DualQuaternion or + @ref DualQuaterniond +- @ref Range1D / @ref Range2D / @ref Range3D, @ref Range1Di / @ref Range2Di / + @ref Range3Di or @ref Range1Dd / @ref Range2Dd / @ref Range3Dd These types can be used in GLSL either by extracting values from their underlying structure or converting them to types supported by GLSL (e.g. quaternion to matrix). -For your convenience, there is also alias for class with often used constants -- -@ref Constants or @ref Constantsd. +For your convenience, there is also alias for class with often used constants +-- @ref Constants or @ref Constantsd. - Previous page: @ref platform - Next page: @ref matrix-vector diff --git a/src/Magnum/Math/Angle.h b/src/Magnum/Math/Angle.h index 443fbbe3a..f67811fb3 100644 --- a/src/Magnum/Math/Angle.h +++ b/src/Magnum/Math/Angle.h @@ -98,7 +98,7 @@ The requirement of explicit conversions from and to unitless types helps to reduce unit-based errors. Consider following example with implicit conversions allowed: @code -Float std::sin(Float angle); +namespace std { float sin(float angle); } Float sine(Rad angle); Float a = 60.0f; // degrees @@ -110,13 +110,13 @@ std::sin(b); // silent error, std::sin() expected radians These silent errors are easily avoided by requiring explicit conversions: @code -//sine(angleInDegrees); // compilation error -sine(Deg(angleInDegrees)); // explicitly specifying unit +//sine(a); // compilation error +sine(Deg{a}); // explicitly specifying unit -//std::sin(angleInDegrees); // compilation error -std::sin(Float(Rad(angleInDegrees)); // required explicit conversion hints - // to user that this case needs special - // attention (i.e., conversion to radians) +//std::sin(b); // compilation error +std::sin(Float(Rad(b)); // required explicit conversion hints to user + // that this case needs special attention + // (i.e., conversion to radians) @endcode @see Magnum::Deg, Magnum::Degd From 35e49c47e28c7d3e70bf0e7fd597d77d9a01d3d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 23 Mar 2014 19:37:31 +0100 Subject: [PATCH 093/141] doc: mention more features in math documentation. Introduce angle classes, more thoroughly explain the type conversion and do overview of component-wise functions. --- doc/matrix-vector.dox | 104 +++++++++++++++++++++++++++++++++++++----- doc/types.dox | 60 ++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 11 deletions(-) diff --git a/doc/matrix-vector.dox b/doc/matrix-vector.dox index a7a3da78c..45e20bb40 100644 --- a/doc/matrix-vector.dox +++ b/doc/matrix-vector.dox @@ -83,7 +83,8 @@ Color4ub black2; // {0, 0, 0, 255} Most common and most efficient way to create vector is to pass all values to constructor, matrix is created by passing all column vectors to the -constructor. +constructor. All constructors check number of passed arguments and the errors +are catched at compile time. @code Vector3i vec(0, 1, 2); @@ -91,11 +92,9 @@ Matrix3 mat({0.0f, 1.9f, 2.2f}, {3.5f, 4.0f, 5.1f}, {6.0f, 7.3f, 8.0f}); @endcode -All constructors check number of passed arguments and the errors are catched -at compile time. -You can specify all components of vector or whole diagonal of square matrix at -once or you can create diagonal matrix from vector: +You can specify all components of vector or whole diagonal of square matrix +with single value or create diagonal matrix from vector: @code Matrix3 diag(Matrix3::Identity, 2.0f); // diagonal set to 2.0f, zeros elsewhere Vector3i fill(10); // {10, 10, 10} @@ -125,12 +124,6 @@ Math::Matrix2x3::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 } Note that, unlike constructors, this function has no way to check whether the array is long enough to contain all elements, so use with caution. -You can also *explicitly* convert between data types: -@code -Vector4 floating(1.3f, 2.7f, -15.0f, 7.0f); -auto integral = Vector4i(floating); // {1, 2, -15, 7} -@endcode - @section matrix-vector-component-access Accessing matrix and vector components Column vectors of matrices and vector components can be accessed using square @@ -170,6 +163,38 @@ Vector4i bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, -1, 4 } Math::Vector<6, Int> w10xyz = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original); // { 4, 1, 0, -1, 2, 3 } @endcode +@section matrix-vector-conversion Converting between different underlying types + +All vector, matrix and other classes in @ref Math namespace and also +@ref Color3 and @ref Color4 classes are able to be constructed from type with +different underlying type (e.g. convert between integer and floating-point or +betweeen @ref Float and @ref Double). Unlike with plain C++ data types, the +conversion is done via *explicit* constructor. That might sound inconvenient, +but doing the conversion explicitly avoids common issues like precision loss +(or, on the other hand, doing computations in unnecessarily high precision). + +To further emphasise the intent of conversion (so it doesn't look like accident +or typo), you are encouraged to use `auto b = Type{a}` instead of `Type b{a}`. +@code +Vector3 a{2.2f, 0.25f, -5.1f}; +//Vector3i b = a; // error, implicit conversion not allowed +auto c = Vector3i{a}; // {2, 0, -5} +auto d = Vector3d{a}; // {2.2, 0.25, -5.1} +@endcode + +For normalizing and denormalizing there are @ref Math::normalize() and +@ref Math::denormalize() functions: +@code +Color3 a{0.8f, 1.0f, 0.3f}; +auto b = Math::denormalize(a); // {204, 255, 76} + +Color3ub c{64, 127, 89}; +auto d = Math::normalize(c); // {0.251, 0.498, 0.349} +@endcode + +See @ref matrix-vector-componentwise "below" for more information about other +available component-wise operations. + @section matrix-vector-operations Operations with matrices and vectors Vectors can be added, subtracted, negated and multiplied or divided with @@ -230,6 +255,63 @@ Math::RectangularMatrix<4, 1, Float> d; Matrix4x3 e = b*d; @endcode +@section matrix-vector-componentwise Component-wise and inter-vector operations + +As shown above, vectors can be added and multiplied component-wise using the +`+` or `*` operator. You can use @ref Vector::sum() "sum()" and +@ref Vector::product() "product()" for sum or product of components in one +vector: +@code +Float a = Vector3{1.5f, 0.3f, 8.0f}.sum(); // 8.8f +Int b = Vector3i{32, -5, 7}.product() // 1120 +@endcode + +Component-wise minimum and maximum of two vectors can be done using +@ref Math::min(), @ref Math::max() or @ref Math::minmax(), similarly with +@ref Vector::min() "min()", @ref Vector::max() "max()" and +@ref Vector2::minmax() "minmax()" for components in one vector. +@code +Vector3i a{-5, 7, 24}; +Vector3i b{8, -2, 12}; + +Vector3i min = Math::min(a, b); // {-5, -2, 12} +Int max = a.max(); // 24 +@endcode + +The vectors can be also compared component-wise, the result is returned in +@ref Math::BoolVector class: +@code +BoolVector<3> largerOrEqual = a >= b; // {false, true, true} +bool anySmaller = (a < b).any(); // true +bool allLarger = (a > b).all(); // false +@endcode + +There are also function for component-wise rounding, sign operations, square +root, various interpolation and (de)normalization functionality: +@code +Vector3 a{5.5f, -0.3f, 75.0f}; +Vector3 b = Math::round(a); // {5.0f, 0.0f, 75.0f} +Vector3 c = Math::abs(a); // {5.5f, -0.3f, 75.0f} +Vector3 d = Math::clamp(a, -0.2f, 55.0f); // {5.5f, -0.2f, 55.0f} +@endcode + +Component-wise functions are implemented only for vectors and not for matrices +to keep the math library in sane and maintainable size. Instead, you can +reinterpret the matrix as vector and do the operation on it (and vice versa): +@code +Matrix3x2 mat; +Math::Vector<6, Float> vec = mat.toVector(); +// ... +mat = Matrix3x2::fromVector(vec); +@endcode + +Note that all component-wise functions in Math namespace work also for scalars: +@code +std::pair minmax = Math::minmax(24, -5); // -5, 24 +Int a = Math::lerp(0, 360, 0.75f); // 270 +auto b = Math::denormalize(0.89f); // 226 +@endcode + @section matrix-vector-column-major Matrices are column-major and vectors are columns OpenGL matrices are column-major, thus it is reasonable to have matrices in diff --git a/doc/types.dox b/doc/types.dox index fb3a8a0c5..027c89e66 100644 --- a/doc/types.dox +++ b/doc/types.dox @@ -87,6 +87,66 @@ underlying type. Any super- or sub-class of the same size and underlying type can be used equivalently (e.g. @ref Math::Vector or @ref Color3 instead of @ref Vector3). +@section types-binary Binary representation + +Scalar types with GLSL equivalent are verified to be exactly the same as +corresponding `GL*` types. Matrix and vector classes have the same binary +representation as corresponding array of numeric values without any additional +data or padding (e.g. `sizeof(Vector3i) == sizeof(Int[3])`), all matrices are +stored in column-major order. + +This means that all scalar, matrix and vector types can be used directly for +filling GPU buffers and textures without any need for data extraction or +conversion. For convenience all vector and matrix classes provide +@ref Math::RectangularMatrix::data() "data()" function, which returns pointer +to the internal data array. + +@section types-special Special types + +%Magnum has special type for strongly-typed representation of angles, namely +the @ref Deg and @ref Rad classes (or @ref Degd and @ref Radd with @ref Double +as underlying type). Their only purpose is to avoid common degree-vs-radian +bugs (i.e. entering degree value where radians should be) and make the +conversion between these two representations easier. They are just a tiny +`inline` `constexpr` wrapper around the native type and they support all +meaningful numeric operations, so using them won't have any performance or +usability impact in practice. + +These classes are *not* implicitly constructible or convertible from/to +@ref Float or @ref Double, you have to either construct/convert them explicitly +or use custom `_degf`/`_deg` and `_radf`/`_rad` literals: +@code +//Deg a = 60.0f // error, no implicit conversion from Float +Deg a = 60.0_degf; // okay + +Float b = 3.2831853f; +auto tau = Rad{b} + 3.0_radf; +Radd pi = 3.141592653589793_rad; + +//Double c = pi; // error, no implicit conversion to Double +auto c = Double{pi}; // okay +@endcode + +They can be implicitly converted to each other, but conversion to different +underlying type is *explicit* to avoid precision loss (or, on the other hand, +unnecessarily high precision) during computations: +@code +Rad d = 60.0_degf; // 1.0471976f +auto e = Degd{pi}; // 180.0 + +//Rad f = pi; // error, no implicit conversion of underlying types +auto f = Rad{pi}; // 3.141592654f +@endcode + +These classes are used exclusively in all functions taking and returning angles +-- trigonometry, angle computation, rotating transformation etc. Thanks to +implicit conversion you can seamlessly use either radians or degrees without +any need to care about what input the function expects: +@code +Float a = Math::sin(1.32457_radf); +Complex b = Complex::rotation(60.0_degf); +@endcode + @section types-other Other types Other types, which don't have their GLSL equivalent, are: From 1b85fba608b9ec4de1548f26cefb043b21cf24ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 12:20:34 +0100 Subject: [PATCH 094/141] Minor cleanup. --- CMakeLists.txt | 2 +- doc/portability.dox | 6 +++--- src/Magnum/Magnum.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3ff23af4..fb405f9a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,7 +141,7 @@ else() find_package(OpenGLES3 REQUIRED) endif() -# Configuration variables (saved later to corradeConfigure.h) +# Configuration variables (saved later to configure.h) if(TARGET_GLES) set(MAGNUM_TARGET_GLES 1) if(TARGET_GLES2) diff --git a/doc/portability.dox b/doc/portability.dox index 1f7cd2644..5ecd1033b 100644 --- a/doc/portability.dox +++ b/doc/portability.dox @@ -40,9 +40,9 @@ format is not supported. If you include @ref Magnum.h, you get these predefined macros: -- @ref MAGNUM_TARGET_GLES if targeting OpenGL ES -- @ref MAGNUM_TARGET_GLES2 if targeting OpenGL ES 2.0 -- @ref MAGNUM_TARGET_GLES3 if targeting OpenGL ES 3.0 +- @ref MAGNUM_TARGET_GLES if targeting OpenGL ES +- @ref MAGNUM_TARGET_GLES2 if targeting OpenGL ES 2.0 +- @ref MAGNUM_TARGET_GLES3 if targeting OpenGL ES 3.0 Example usage: @code diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 969b9b4f4..48b6df03f 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -100,7 +100,7 @@ Defined if the engine is built for OpenGL ES 3.0 or OpenGL ES 2.0. #undef MAGNUM_TARGET_GLES /** -@brief OpenGL ES 2.0 target. +@brief OpenGL ES 2.0 target Defined if the engine is built for OpenGL ES 2.0. Implies also @ref MAGNUM_TARGET_GLES. @@ -110,7 +110,7 @@ Defined if the engine is built for OpenGL ES 2.0. Implies also #undef MAGNUM_TARGET_GLES2 /** -@brief OpenGL ES 3.0 target. +@brief OpenGL ES 3.0 target Defined if the engine is built for OpenGL ES 3.0. Implies also @ref MAGNUM_TARGET_GLES. From e5c366c6af42d404ce93c1d4179137fa7e8ad402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 12:28:07 +0100 Subject: [PATCH 095/141] Doc++ --- doc/matrix-vector.dox | 6 +++--- doc/portability.dox | 6 +++++- src/Magnum/Magnum.h | 2 +- src/Magnum/Math/Vector.h | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/matrix-vector.dox b/doc/matrix-vector.dox index 45e20bb40..d57326320 100644 --- a/doc/matrix-vector.dox +++ b/doc/matrix-vector.dox @@ -258,9 +258,9 @@ Matrix4x3 e = b*d; @section matrix-vector-componentwise Component-wise and inter-vector operations As shown above, vectors can be added and multiplied component-wise using the -`+` or `*` operator. You can use @ref Vector::sum() "sum()" and -@ref Vector::product() "product()" for sum or product of components in one -vector: +`+` or `*` operator. You can use @ref Math::Vector::sum() "sum()" and +@ref Math::Vector::product() "product()" for sum or product of components in +one vector: @code Float a = Vector3{1.5f, 0.3f, 8.0f}.sum(); // 8.8f Int b = Vector3i{32, -5, 7}.product() // 1120 diff --git a/doc/portability.dox b/doc/portability.dox index 5ecd1033b..0bf5a3b85 100644 --- a/doc/portability.dox +++ b/doc/portability.dox @@ -57,7 +57,7 @@ Renderer::setPolygonMode(Renderer::PolygonMode::Lines); Each feature is marked accordingly if it is not available in some targets. See also @ref requires-gl, @ref requires-gles20 and @ref requires-gles30. -@section portability-compiler Compiler-specific code +@section portability-compiler Compiler- and platform-specific code %Magnum is attempting to be future-proof and as intuitive for users as possible. Many features from C++11 are used to simplify things and make them @@ -73,6 +73,10 @@ platform) which compiler your code will support, code written for e.g. GCC 4.6 will work also on Magnum compiled with support for newer compilers, although newer compilers may catch errors that weren't spotted by earlier versions. +Some functionality (such as dynamic plugin loading or filesystem access) might +not be available on particular platforms. @ref Corrade.h contains defintions +which you can use for platform-aware code. + @section portability-extensions Extension-aware code Some functionality is depending on support of particular extension and thus diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 48b6df03f..a731466c7 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -124,7 +124,7 @@ Defined if the engine is built for OpenGL ES 3.0. Implies also Defined if the engine is built for OpenGL ES 3.0 or OpenGL ES 2.0 emulated within standard desktop OpenGL. Implies also @ref MAGNUM_TARGET_GLES. -@see @ref MAGNUM_TARGET_GLES2, @ref building +@see @ref MAGNUM_TARGET_GLES2, @ref MAGNUM_TARGET_GLES3, @ref building */ #define MAGNUM_TARGET_DESKTOP_GLES #undef MAGNUM_TARGET_DESKTOP_GLES diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index 3f6371fc5..f8becd762 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -379,7 +379,8 @@ template class Vector { * @brief Multiply vector component-wise * * @see operator*(T) const, operator*=(const Vector&), - * operator*(const Vector&, const Vector&) + * operator*(const Vector&, const Vector&), + * @ref product() */ Vector operator*(const Vector& other) const { return Vector(*this) *= other; From 6dee292654421e0c8e0467d16e462a96661e0b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 12:34:42 +0100 Subject: [PATCH 096/141] Added MAGNUM_TARGET_WEBGL definition. Treating JavaScript and WebGL as first-class compile target. What the world had come to :-) --- CMakeLists.txt | 3 +++ doc/portability.dox | 1 + src/Magnum/Magnum.h | 14 ++++++++++++++ src/Magnum/configure.h.cmake | 1 + 4 files changed, 19 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb405f9a3..3416841d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,9 @@ if(TARGET_GLES) set(MAGNUM_TARGET_GLES3 1) endif() endif() +if(CORRADE_TARGET_EMSCRIPTEN) + set(MAGNUM_TARGET_WEBGL 1) +endif() if(TARGET_DESKTOP_GLES) set(MAGNUM_TARGET_DESKTOP_GLES 1) endif() diff --git a/doc/portability.dox b/doc/portability.dox index 0bf5a3b85..880775cda 100644 --- a/doc/portability.dox +++ b/doc/portability.dox @@ -43,6 +43,7 @@ If you include @ref Magnum.h, you get these predefined macros: - @ref MAGNUM_TARGET_GLES if targeting OpenGL ES - @ref MAGNUM_TARGET_GLES2 if targeting OpenGL ES 2.0 - @ref MAGNUM_TARGET_GLES3 if targeting OpenGL ES 3.0 +- @ref MAGNUM_TARGET_WEBGL if targeting WebGL Example usage: @code diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index a731466c7..4e1dde2b7 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -128,6 +128,20 @@ within standard desktop OpenGL. Implies also @ref MAGNUM_TARGET_GLES. */ #define MAGNUM_TARGET_DESKTOP_GLES #undef MAGNUM_TARGET_DESKTOP_GLES + +/** +@brief WebGL target + +Defined if the engine is built for WebGL (using Emscripten). WebGL is nearly +equivalent to OpenGL ES 2.0, thus in most cases you don't need to treat it +differently, but there are some +[specific restrictions and features](http://www.khronos.org/registry/webgl/specs/latest/1.0/#6) +which you might want to be aware of. Implies also @ref MAGNUM_TARGET_GLES and +@ref MAGNUM_TARGET_GLES2. +@see @ref CORRADE_TARGET_EMSCRIPTEN, @ref building +*/ +#define MAGNUM_TARGET_WEBGL +#undef MAGNUM_TARGET_WEBGL #endif /** @{ @name Basic type definitions diff --git a/src/Magnum/configure.h.cmake b/src/Magnum/configure.h.cmake index ea20a8f7b..75a46c114 100644 --- a/src/Magnum/configure.h.cmake +++ b/src/Magnum/configure.h.cmake @@ -29,3 +29,4 @@ #cmakedefine MAGNUM_TARGET_GLES2 #cmakedefine MAGNUM_TARGET_GLES3 #cmakedefine MAGNUM_TARGET_DESKTOP_GLES +#cmakedefine MAGNUM_TARGET_WEBGL From 6ea243d2462c65fc7fb33b7a66a6c0480006f01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 12:39:35 +0100 Subject: [PATCH 097/141] doc: document all WebGL restrictions. --- doc/best-practices.dox | 23 ++++++++++++----------- doc/opengl-support.dox | 3 ++- src/Magnum/AbstractTexture.h | 6 ++++++ src/Magnum/Buffer.h | 17 +++++++++++++++++ src/Magnum/Mesh.h | 11 +++++++++++ src/Magnum/Renderer.h | 9 +++++++++ src/Magnum/Texture.h | 8 ++++++++ 7 files changed, 65 insertions(+), 12 deletions(-) diff --git a/doc/best-practices.dox b/doc/best-practices.dox index b1f17c9a0..3079ebf12 100644 --- a/doc/best-practices.dox +++ b/doc/best-practices.dox @@ -54,21 +54,22 @@ information. - [Best Practices for Working with Texture Data](http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesForWorkingWithTextureData/TechniquesForWorkingWithTextureData.html) - [Best Practices for Shaders](http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html#//apple_ref/doc/uid/TP40008793-CH7-SW3) -@subsection best-practices-nacl Google Chrome Native Client +@subsection best-practices-webgl WebGL (Emscripten) -- [Best practices for 3D graphics](https://developers.google.com/native-client/beta/devguide/coding/3D-graphics#best-practices) +WebGL is subset of OpenGL ES 2.0 with some [specific restrictions and features](http://www.khronos.org/registry/webgl/specs/latest/1.0/#6), namely requirement +for unique buffer target binding, aligned buffer offset and stride and some +other restrictions and also support for combined depth/stencil buffer +attachments. See @ref Buffer, @ref Framebuffer, @ref Texture::setSubImage() "*Texture::setSubImage()", +@ref Mesh::addVertexBuffer(), @ref Renderer::setStencilFunction(), +@ref Renderer::setStencilMask() and @ref Renderer::setBlendFunction() +documentation for more information. -@subsection best-practices-web-buffer-types Native Client and Emscripten require unique buffer binding +@subsection best-practices-nacl Google Chrome Native Client -As noted in the above link, buffers in NaCl implementation and and also in -WebGL need to be bound only to one unique target, i.e., @ref Buffer bound to -@ref Buffer::Target::Array cannot be later rebound to @ref Buffer::Target::ElementArray. -However, %Magnum by default uses any sufficient target when binding the buffer -internally (e.g. for setting data or copying). To avoid this, set target hint -to desired target, either in constructor or using @ref Buffer::setTargetHint(). +- [Best practices for 3D graphics](https://developers.google.com/native-client/beta/devguide/coding/3D-graphics#best-practices) -To ease up the development, @ref Mesh checks proper target hint when adding -vertex and index buffers in both Native Client and Emscripten. +Similarly to WebGL, buffers in NaCl implementation need to be bound only to one +unique target. See @ref Buffer class documentation for more information. @section best-practices-hw Hardware-specific diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 7a6a4e8bd..9da8957c3 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -325,7 +325,8 @@ add any performance gains, is not supported in %Magnum. See also with serious performance drops. Multisampling is far superior solution. - Fixed precision data types (`GL_FIXED` in OpenGL ES) are not supported, as they occupy the same memory as floats and they aren't faster than floats on - current hardware anymore. + current hardware anymore. They are also not available in WebGL or desktop + GL. - Shader compiler is assumed to be present (`GL_SHADER_COMPILER` returning true), as all desktop GL implementations and also ES3 are required to support it. diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index ace81fc3a..670edbed8 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -43,6 +43,12 @@ Encapsulates one OpenGL texture object. See @ref Texture, @ref CubeMapTexture and @ref CubeMapTextureArray documentation for more information and usage examples. +@section AbstractTexture-webgl-restrictions WebGL restrictions + +@ref MAGNUM_TARGET_WEBGL "WebGL" puts some restrictions on type of data +submitted to @ref Texture::setSubImage() "*Texture::setSubImage()", see its +documentation for details. + @section AbstractTexture-performance-optimization Performance optimizations and security The engine tracks currently bound textures in all available layers to avoid diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index 35d5d1e5d..bbd3d01a6 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -166,6 +166,23 @@ for(std::size_t i: {7, 27, 56, 128}) { CORRADE_INTERNAL_ASSERT_OUTPUT(buffer.unmap()); @endcode +@section Buffer-webgl-restrictions WebGL and NaCl restrictions + +Buffers in @ref MAGNUM_TARGET_WEBGL "WebGL" and @ref CORRADE_TARGET_NACL "NaCl" +need to be bound only to one unique target, i.e., @ref Buffer bound to +@ref Buffer::Target::Array cannot be later rebound to +@ref Buffer::Target::ElementArray. However, %Magnum by default uses any +sufficient target when binding the buffer internally (e.g. for setting data). +To avoid GL errors, set target hint to desired target, either in constructor or +using @ref Buffer::setTargetHint(): +@code +Buffer vertices{Buffer::Target::Array}; +Buffer indices{Buffer::Target::ElementArray}; +@endcode + +To ease up the development, @ref Mesh checks proper target hint when adding +vertex and index buffers in both WebGL and NaCl. + @section Buffer-performance-optimization Performance optimizations The engine tracks currently bound buffers to avoid unnecessary calls to diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 692b1940b..223de085d 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -291,6 +291,11 @@ respective shader, bind required textures (see @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" for more infromation) and call @ref Mesh::draw(). +@section Mesh-webgl-restrictions WebGL restrictions + +@ref MAGNUM_TARGET_WEBGL "WebGL" puts some restrictions on vertex buffer +layout, see @ref addVertexBuffer() for details. + @section Mesh-performance-optimization Performance optimizations If @extension{APPLE,vertex_array_object} (part of OpenGL 3.0), OpenGL ES 3.0 or @@ -553,6 +558,12 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * mesh, you must ensure it will exist for whole lifetime of the * mesh and delete it afterwards. * + * @attention In @ref MAGNUM_TARGET_WEBGL "WebGL" the data must be + * properly aligned (e.g. all float data must start at addresses + * divisible by four). Also the maximum stride of attribute data + * must be at most 255 bytes. This is not required anywhere else, + * but doing so may have performance benefits. + * * @see @ref maxVertexAttributes(), @ref setPrimitive(), * @ref setVertexCount(), @fn_gl{BindVertexArray}, * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, diff --git a/src/Magnum/Renderer.h b/src/Magnum/Renderer.h index d36e956b5..ff2226294 100644 --- a/src/Magnum/Renderer.h +++ b/src/Magnum/Renderer.h @@ -519,6 +519,9 @@ class MAGNUM_EXPORT Renderer { * @param mask Mask for both reference and buffer value. * Initial value is all `1`s. * + * @attention In @ref MAGNUM_TARGET_WEBGL "WebGL" the reference value + * and mask must be the same for both front and back polygon + * facing. * @see @ref Feature::StencilTest, @ref setStencilFunction(StencilFunction, Int, UnsignedInt), * @ref setStencilOperation(), @fn_gl{StencilFuncSeparate} */ @@ -606,6 +609,9 @@ class MAGNUM_EXPORT Renderer { * * Set given bit to `0` to disallow writing stencil value for given * faces to it. Initial value is all `1`s. + * + * @attention In @ref MAGNUM_TARGET_WEBGL "WebGL" the mask must be the + * same for both front and back polygon facing. * @see setStencilMask(UnsignedInt), setColorMask(), setDepthMask(), * @fn_gl{StencilMaskSeparate} */ @@ -812,6 +818,9 @@ class MAGNUM_EXPORT Renderer { * @param destination How the destination blending factor is * computed from framebuffer. Initial value is @ref BlendFunction::Zero. * + * @attention In @ref MAGNUM_TARGET_WEBGL "WebGL", constant color and + * constant alpha cannot be used together as source and + * destination factors. * @see @ref Feature::Blending, @ref setBlendFunction(BlendFunction, BlendFunction, BlendFunction, BlendFunction), * @ref setBlendEquation(), @ref setBlendColor(), * @fn_gl{BlendFunc} diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 5551e8f88..00e726294 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -299,6 +299,8 @@ template class Texture: public AbstractTexture { * (part of OpenGL 4.2), OpenGL ES 3.0 or @es_extension{EXT,texture_storage} * in OpenGL ES 2.0 is not available, the feature is emulated with * sequence of @ref setImage() calls. + * @todo allow the user to specify ColorType explicitly to avoid + * issues in WebGL (see setSubImage()) * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} * or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/ @@ -404,6 +406,12 @@ template class Texture: public AbstractTexture { * * If @extension{EXT,direct_state_access} is not available, the * texture is bound to some layer before the operation. + * + * @attention In @ref MAGNUM_TARGET_WEBGL "WebGL" the @ref ColorType of + * data passed in @p image must match the original one specified + * in @ref setImage(). It means that you might not be able to use + * @ref setStorage() as it uses implicit @ref ColorType value. + * * @see @ref setStorage(), @ref setImage(), @fn_gl{ActiveTexture}, * @fn_gl{BindTexture} and @fn_gl{TexSubImage1D}/ * @fn_gl{TexSubImage2D}/@fn_gl{TexSubImage3D} or From 8a011b7c4eef8dffd0a9c7c40e0cfe6a153522b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 12:40:23 +0100 Subject: [PATCH 098/141] Use more general MAGNUM_TARGET_WEBGL instead of CORRADE_TARGET_EMSCRIPTEN. Only where it matters, though. --- src/Magnum/Context.cpp | 2 +- src/Magnum/Mesh.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 931daa7d2..5f28b479f 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -314,7 +314,7 @@ Context::Context() { const std::string version = versionString(); #ifndef MAGNUM_TARGET_GLES if(version.compare(0, 4, "2.1 ") == 0) - #elif defined(CORRADE_TARGET_EMSCRIPTEN) + #elif defined(MAGNUM_TARGET_WEBGL) if(version.find("WebGL 1") != std::string::npos) #else if(version.find("OpenGL ES 2.0") != std::string::npos) diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index 250a7f0bd..0ed703735 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -148,7 +148,7 @@ Mesh& Mesh::setLabel(const std::string& label) { } Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end) { - #if defined(CORRADE_TARGET_NACL) || defined(CORRADE_TARGET_EMSCRIPTEN) + #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) CORRADE_ASSERT(buffer.targetHint() == Buffer::Target::ElementArray, "Mesh::setIndexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::ElementArray << "but got" << buffer.targetHint(), *this); #endif @@ -270,7 +270,7 @@ void Mesh::destroyImplementationVAO() { } void Mesh::attributePointerImplementationDefault(const Attribute& attribute) { - #if defined(CORRADE_TARGET_NACL) || defined(CORRADE_TARGET_EMSCRIPTEN) + #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::Target::Array, "Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::Array << "but got" << attribute.buffer->targetHint(), ); #endif @@ -279,7 +279,7 @@ void Mesh::attributePointerImplementationDefault(const Attribute& attribute) { } void Mesh::attributePointerImplementationVAO(const Attribute& attribute) { - #if defined(CORRADE_TARGET_NACL) || defined(CORRADE_TARGET_EMSCRIPTEN) + #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::Target::Array, "Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::Array << "but got" << attribute.buffer->targetHint(), ); #endif From 2cb165d63a80f851a922cefa1f62b0e1d7ac9599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 12:41:12 +0100 Subject: [PATCH 099/141] Platform: show MAGNUM_TARGET_WEBGL in magnum-info. --- src/Magnum/Platform/magnum-info.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index 999de991a..0728e5ab5 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -131,6 +131,9 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat #ifdef MAGNUM_TARGET_DESKTOP_GLES Debug() << " MAGNUM_TARGET_DESKTOP_GLES"; #endif + #ifdef MAGNUM_TARGET_WEBGL + Debug() << " MAGNUM_TARGET_WEBGL"; + #endif Debug() << ""; /* Create context here, so the context creation info is displayed at proper From 87d8b6a2298ae65e8de990b4bcb3d677691fb091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 12:53:56 +0100 Subject: [PATCH 100/141] Disable 64bit integers for WebGL. Due to crappy JavaScript design which doesn't count with any integers at all, the integers needs to be "emulated" inside the 52-bit exponent of doubles, which means that only 32bit integers can fit there (not to mention various issues with 32b overflow, which needs to be emulated somehow to work properly). --- src/Magnum/Magnum.h | 14 ++++++++++++-- src/Magnum/Math/TypeTraits.h | 2 ++ src/Magnum/Query.cpp | 2 ++ src/Magnum/Query.h | 4 ++++ src/Magnum/Types.h | 2 ++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 4e1dde2b7..3da95c146 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -167,11 +167,21 @@ typedef std::uint32_t UnsignedInt; /** @brief Signed int (32bit) */ typedef std::int32_t Int; -/** @brief Unsigned long (64bit) */ +#ifndef MAGNUM_TARGET_WEBGL +/** +@brief Unsigned long (64bit) + +@attention 64-bit integers are not available in @ref MAGNUM_TARGET_WEBGL "WebGL". +*/ typedef std::uint64_t UnsignedLong; -/** @brief Signed long (64bit) */ +/** +@brief Signed long (64bit) + +@attention 64-bit integers are not available in @ref MAGNUM_TARGET_WEBGL "WebGL". +*/ typedef std::int64_t Long; +#endif /** @brief Float (32bit) */ typedef float Float; diff --git a/src/Magnum/Math/TypeTraits.h b/src/Magnum/Math/TypeTraits.h index e8f515b88..6d2a4c0c0 100644 --- a/src/Magnum/Math/TypeTraits.h +++ b/src/Magnum/Math/TypeTraits.h @@ -144,6 +144,7 @@ template<> struct TypeTraits: Implementation::TypeTraitsIntegral { typedef Double FloatingPointType; #endif }; +#ifndef MAGNUM_TARGET_WEBGL template<> struct TypeTraits: Implementation::TypeTraitsIntegral { #ifndef MAGNUM_TARGET_GLES typedef long double FloatingPointType; @@ -154,6 +155,7 @@ template<> struct TypeTraits: Implementation::TypeTraitsIntegral { typedef long double FloatingPointType; #endif }; +#endif /* Floating-point scalar types */ namespace Implementation { diff --git a/src/Magnum/Query.cpp b/src/Magnum/Query.cpp index 649994cf8..d6bee60f2 100644 --- a/src/Magnum/Query.cpp +++ b/src/Magnum/Query.cpp @@ -123,6 +123,7 @@ template<> Int AbstractQuery::result() { return result; } +#ifndef MAGNUM_TARGET_WEBGL template<> UnsignedLong AbstractQuery::result() { CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {}); @@ -151,6 +152,7 @@ template<> Long AbstractQuery::result() { return result; } #endif +#endif void AbstractQuery::begin(GLenum target) { CORRADE_ASSERT(!this->target, "AbstractQuery::begin(): the query is already running", ); diff --git a/src/Magnum/Query.h b/src/Magnum/Query.h index db978053f..726d508ea 100644 --- a/src/Magnum/Query.h +++ b/src/Magnum/Query.h @@ -107,6 +107,8 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { * @requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query} * for result types @ref Magnum::Int "Int", @ref Magnum::UnsignedLong "UnsignedLong" * @ref Magnum::Long "Long". + * @attention @ref Magnum::UnsignedLong "UnsignedLong" and @ref Magnum::Long "Long" + * result type is not available in @ref MAGNUM_TARGET_WEBGL "WebGL". */ template T result(); @@ -147,9 +149,11 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject { template<> bool MAGNUM_EXPORT AbstractQuery::result(); template<> UnsignedInt MAGNUM_EXPORT AbstractQuery::result(); template<> Int MAGNUM_EXPORT AbstractQuery::result(); +#ifndef MAGNUM_TARGET_WEBGL template<> UnsignedLong MAGNUM_EXPORT AbstractQuery::result(); template<> Long MAGNUM_EXPORT AbstractQuery::result(); #endif +#endif #ifndef MAGNUM_TARGET_GLES2 /** diff --git a/src/Magnum/Types.h b/src/Magnum/Types.h index 8a2be413e..ef3de0a72 100644 --- a/src/Magnum/Types.h +++ b/src/Magnum/Types.h @@ -42,8 +42,10 @@ typedef std::uint16_t UnsignedShort; typedef std::int16_t Short; typedef std::uint32_t UnsignedInt; typedef std::int32_t Int; +#ifndef MAGNUM_TARGET_WEBGL typedef std::uint64_t UnsignedLong; typedef std::int64_t Long; +#endif /** @todo C++14: use std::float32_t and std::float_64t [N3626](http://open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3626.pdf) */ typedef float Float; From 346f723f570ccaac998210ef2ec57b9df72fed1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 18:54:09 +0100 Subject: [PATCH 101/141] Doc++ --- src/Magnum/Mesh.h | 3 ++- src/Magnum/MeshView.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 223de085d..bf7f899f1 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -646,7 +646,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #ifdef MAGNUM_BUILD_DEPRECATED /** * @copybrief draw(AbstractShaderProgram&) - * @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) instead. + * @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) "draw(AbstractShaderProgram&)" + * instead. */ void draw() { #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/MeshView.h b/src/Magnum/MeshView.h index 4b137ea17..d283d6410 100644 --- a/src/Magnum/MeshView.h +++ b/src/Magnum/MeshView.h @@ -126,7 +126,8 @@ class MAGNUM_EXPORT MeshView { #ifdef MAGNUM_BUILD_DEPRECATED /** * @copybrief draw(AbstractShaderProgram&) - * @deprecated Use + * @deprecated Use @ref Magnum::MeshView::draw(AbstractShaderProgram&) "draw(AbstractShaderProgram&)" + * instead. */ CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw(); #endif From 7b504a9bb1165393d192d096000c580035adc8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 24 Mar 2014 23:44:07 +0100 Subject: [PATCH 102/141] Finally implemented parallelizable shader compilation and linking. As g_truc said long ago: https://twitter.com/g_truc/status/352778836657700866 Currently there is not much use of this as the stock shaders are compiled one by one (and doing it differently would make things needlessly overcomplicated), but the users can do parallel compilation of their own shaders. Also removed a bunch of now-unneeded TODOs and made the linker/compiler code nearly similar. Also the whole Shader::compile() call now does two allocations in total instead of two allocations for each shader. --- src/Magnum/AbstractShaderProgram.cpp | 77 ++++++++++-------- src/Magnum/AbstractShaderProgram.h | 30 ++++--- src/Magnum/Shader.cpp | 112 ++++++++++++++++----------- src/Magnum/Shader.h | 28 +++++-- 4 files changed, 152 insertions(+), 95 deletions(-) diff --git a/src/Magnum/AbstractShaderProgram.cpp b/src/Magnum/AbstractShaderProgram.cpp index 4d1e966cf..1709edfb7 100644 --- a/src/Magnum/AbstractShaderProgram.cpp +++ b/src/Magnum/AbstractShaderProgram.cpp @@ -269,40 +269,53 @@ void AbstractShaderProgram::bindFragmentDataLocationIndexed(UnsignedInt location } #endif -bool AbstractShaderProgram::link() { - /* Link shader program */ - glLinkProgram(_id); - - /* Check link status */ - GLint success, logLength; - glGetProgramiv(_id, GL_LINK_STATUS, &success); - glGetProgramiv(_id, GL_INFO_LOG_LENGTH, &logLength); - - /* Error or warning message. The string is returned null-terminated, scrap - the \0 at the end afterwards */ - std::string message(logLength, '\n'); - if(message.size() > 1) - glGetProgramInfoLog(_id, message.size(), nullptr, &message[0]); - message.resize(std::max(logLength, 1)-1); - - /* Show error log and delete shader */ - if(!success) { - Error out; - out.setFlag(Debug::NewLineAtTheEnd, false); - out.setFlag(Debug::SpaceAfterEachValue, false); - out << "AbstractShaderProgram: linking failed with the following message:\n" - << message; - - /* Or just warnings, if there are any */ - } else if(!message.empty()) { - Debug out; - out.setFlag(Debug::NewLineAtTheEnd, false); - out.setFlag(Debug::SpaceAfterEachValue, false); - out << "AbstractShaderProgram: linking succeeded with the following message:\n" - << message; +bool AbstractShaderProgram::link(std::initializer_list> shaders) { + bool allSuccess = true; + + /* Invoke (possibly parallel) linking on all shaders */ + for(AbstractShaderProgram& shader: shaders) glLinkProgram(shader._id); + + /* After linking phase, check status of all shaders */ + Int i = 1; + for(AbstractShaderProgram& shader: shaders) { + GLint success, logLength; + glGetProgramiv(shader._id, GL_LINK_STATUS, &success); + glGetProgramiv(shader._id, GL_INFO_LOG_LENGTH, &logLength); + + /* Error or warning message. The string is returned null-terminated, + scrap the \0 at the end afterwards */ + std::string message(logLength, '\n'); + if(message.size() > 1) + glGetProgramInfoLog(shader._id, message.size(), nullptr, &message[0]); + message.resize(std::max(logLength, 1)-1); + + /* Show error log */ + if(!success) { + Error out; + out.setFlag(Debug::NewLineAtTheEnd, false); + out.setFlag(Debug::SpaceAfterEachValue, false); + out << "AbstractShaderProgram::link(): linking"; + if(shaders.size() != 1) out << " of shader " << std::to_string(i); + out << " failed with the following message:\n" + << message; + + /* Or just warnings, if any */ + } else if(!message.empty()) { + Debug out; + out.setFlag(Debug::NewLineAtTheEnd, false); + out.setFlag(Debug::SpaceAfterEachValue, false); + out << "AbstractShaderProgram::link(): linking"; + if(shaders.size() != 1) out << " of shader " << std::to_string(i); + out << " succeeded with the following message:\n" + << message; + } + + /* Success of all depends on each of them */ + allSuccess = allSuccess && success; + ++i; } - return success; + return allSuccess; } Int AbstractShaderProgram::uniformLocation(const std::string& name) { diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 138ce598a..124625d4c 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -29,6 +29,7 @@ * @brief Class @ref Magnum::AbstractShaderProgram */ +#include #include #include @@ -320,8 +321,6 @@ comes in handy. @see @ref portability-shaders @todo Use Containers::ArrayReference for setting uniform arrays? -@todo Compiling and linking more than one shader in parallel, then checking - status, should be faster -- https://twitter.com/g_truc/status/352778836657700866 @todo `GL_NUM_{PROGRAM,SHADER}_BINARY_FORMATS` + `GL_{PROGRAM,SHADER}_BINARY_FORMATS` (vector), (@extension{ARB,ES2_compatibility}) */ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { @@ -562,6 +561,21 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { #endif protected: + /** + * @brief Link the shader + * + * Returns `false` if linking of any shader failed, `true` if + * everything succeeded. Linker message (if any) is printed to error + * output. All attached shaders must be compiled with + * @ref Shader::compile() before linking. The operation is batched in a + * way that allows the driver to link multiple shaders simultaenously + * (i.e. in multiple threads). + * @see @fn_gl{LinkProgram}, @fn_gl{GetProgram} with + * @def_gl{LINK_STATUS} and @def_gl{INFO_LOG_LENGTH}, + * @fn_gl{GetProgramInfoLog} + */ + static bool link(std::initializer_list> shaders); + #ifndef MAGNUM_TARGET_GLES2 /** * @brief Allow retrieving program binary @@ -655,14 +669,12 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { /** * @brief Link the shader * - * Returns `false` if linking failed, `true` otherwise. Compiler - * message (if any) is printed to error output. All attached shaders - * must be compiled with @ref Shader::compile() before linking. - * @see @fn_gl{LinkProgram}, @fn_gl{GetProgram} with - * @def_gl{LINK_STATUS} and @def_gl{INFO_LOG_LENGTH}, - * @fn_gl{GetProgramInfoLog} + * Links single shader. If possible, prefer to link multiple shaders + * at once using @ref link(std::initializer_list>) + * for improved performance, see its documentation for more + * information. */ - bool link(); + bool link() { return link({*this}); } /** * @brief Get uniform location diff --git a/src/Magnum/Shader.cpp b/src/Magnum/Shader.cpp index 73ad186e4..64f684379 100644 --- a/src/Magnum/Shader.cpp +++ b/src/Magnum/Shader.cpp @@ -622,57 +622,75 @@ Shader& Shader::addFile(const std::string& filename) { return *this; } -bool Shader::compile() { - CORRADE_ASSERT(_sources.size() > 1, "Shader::compile(): no files added", false); - - /* Array of source string pointers and their lengths */ - /** @todo Use `Containers::ArrayTuple` to avoid one allocation if it ever - gets to be implemented (we need properly aligned memory too) */ - Containers::Array pointers(_sources.size()); - Containers::Array sizes(_sources.size()); - for(std::size_t i = 0; i != _sources.size(); ++i) { - pointers[i] = static_cast(_sources[i].data()); - sizes[i] = _sources[i].size(); +bool Shader::compile(std::initializer_list> shaders) { + bool allSuccess = true; + + /* Allocate large enough array for source pointers and sizes (to avoid + reallocating it for each of them) */ + std::size_t maxSourceCount = 0; + for(Shader& shader: shaders) { + CORRADE_ASSERT(shader._sources.size() > 1, "Shader::compile(): no files added", false); + maxSourceCount = std::max(shader._sources.size(), maxSourceCount); } + Containers::Array pointers(maxSourceCount); + Containers::Array sizes(maxSourceCount); - /* Create shader and set its source */ - glShaderSource(_id, _sources.size(), pointers, sizes); - - /* Compile shader */ - glCompileShader(_id); - - /* Check compilation status */ - GLint success, logLength; - glGetShaderiv(_id, GL_COMPILE_STATUS, &success); - glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logLength); - - /* Error or warning message. The string is returned null-terminated, scrap - the \0 at the end afterwards */ - std::string message(logLength, '\0'); - if(message.size() > 1) - glGetShaderInfoLog(_id, message.size(), nullptr, &message[0]); - message.resize(std::max(logLength, 1)-1); - - /* Show error log */ - if(!success) { - Error out; - out.setFlag(Debug::NewLineAtTheEnd, false); - out.setFlag(Debug::SpaceAfterEachValue, false); - out << "Shader: " << shaderName(_type) - << " shader failed to compile with the following message:\n" - << message; - - /* Or just message, if any */ - } else if(!message.empty()) { - Error out; - out.setFlag(Debug::NewLineAtTheEnd, false); - out.setFlag(Debug::SpaceAfterEachValue, false); - out << "Shader: " << shaderName(_type) - << " shader was successfully compiled with the following message:\n" - << message; + /* Upload sources of all shaders */ + for(Shader& shader: shaders) { + for(std::size_t i = 0; i != shader._sources.size(); ++i) { + pointers[i] = static_cast(shader._sources[i].data()); + sizes[i] = shader._sources[i].size(); + } + + glShaderSource(shader._id, shader._sources.size(), pointers, sizes); + } + + /* Invoke (possibly parallel) compilation on all shaders */ + for(Shader& shader: shaders) glCompileShader(shader._id); + + /* After compilation phase, check status of all shaders */ + Int i = 1; + for(Shader& shader: shaders) { + GLint success, logLength; + glGetShaderiv(shader._id, GL_COMPILE_STATUS, &success); + glGetShaderiv(shader._id, GL_INFO_LOG_LENGTH, &logLength); + + /* Error or warning message. The string is returned null-terminated, + scrap the \0 at the end afterwards */ + std::string message(logLength, '\0'); + if(message.size() > 1) + glGetShaderInfoLog(shader._id, message.size(), nullptr, &message[0]); + message.resize(std::max(logLength, 1)-1); + + /* Show error log */ + if(!success) { + Error out; + out.setFlag(Debug::NewLineAtTheEnd, false); + out.setFlag(Debug::SpaceAfterEachValue, false); + out << "Shader::compile(): compilation of " << shaderName(shader._type) + << " shader"; + if(shaders.size() != 1) out << ' ' << std::to_string(i); + out << " failed with the following message:\n" + << message; + + /* Or just warnings, if any */ + } else if(!message.empty()) { + Error out; + out.setFlag(Debug::NewLineAtTheEnd, false); + out.setFlag(Debug::SpaceAfterEachValue, false); + out << "Shader::compile(): compilation of " << shaderName(shader._type) + << " shader"; + if(shaders.size() != 1) out << ' ' << std::to_string(i); + out << " succeeded with the following message:\n" + << message; + } + + /* Success of all depends on each of them */ + allSuccess = allSuccess && success; + ++i; } - return success; + return allSuccess; } #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/Shader.h b/src/Magnum/Shader.h index e7768948a..d3a077f86 100644 --- a/src/Magnum/Shader.h +++ b/src/Magnum/Shader.h @@ -29,8 +29,9 @@ * @brief Class @ref Magnum::Shader */ -#include +#include #include +#include #include "Magnum/AbstractObject.h" #include "Magnum/Magnum.h" @@ -431,6 +432,20 @@ class MAGNUM_EXPORT Shader: public AbstractObject { static Int maxCombinedUniformComponents(Type type); #endif + /** + * @brief Compile multiple shaders simultaenously + * + * Returns `false` if compilation of any shader failed, `true` if + * everything succeeded. Compiler messages (if any) are printed to + * error output. The operation is batched in a way that allows the + * driver to perform multiple compilations simultaenously (i.e. in + * multiple threads). + * @see @fn_gl{ShaderSource}, @fn_gl{CompileShader}, @fn_gl{GetShader} + * with @def_gl{COMPILE_STATUS} and @def_gl{INFO_LOG_LENGTH}, + * @fn_gl{GetShaderInfoLog} + */ + static bool compile(std::initializer_list> shaders); + /** * @brief Constructor * @param version Target version @@ -524,13 +539,12 @@ class MAGNUM_EXPORT Shader: public AbstractObject { /** * @brief Compile shader * - * Returns `false` if compilation failed, `true` otherwise. Compiler - * message (if any) is printed to error output. - * @see @fn_gl{ShaderSource}, @fn_gl{CompileShader}, @fn_gl{GetShader} - * with @def_gl{COMPILE_STATUS} and @def_gl{INFO_LOG_LENGTH}, - * @fn_gl{GetShaderInfoLog} + * Compiles single shader. Prefer to compile multiple shaders at once + * using @ref compile(std::initializer_list>) + * for improved performance, see its documentation for more + * information. */ - bool compile(); + bool compile() { return compile({*this}); } private: Type _type; From 4be1c5e15c4376b26ba24273b621edaa9343da70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 25 Mar 2014 00:08:39 +0100 Subject: [PATCH 103/141] Print non-error shader compilation/linking messages to Warning output. Instead of schizophrenic Debug/Error. --- src/Magnum/AbstractShaderProgram.cpp | 2 +- src/Magnum/Shader.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/AbstractShaderProgram.cpp b/src/Magnum/AbstractShaderProgram.cpp index 1709edfb7..43ebf0ce2 100644 --- a/src/Magnum/AbstractShaderProgram.cpp +++ b/src/Magnum/AbstractShaderProgram.cpp @@ -301,7 +301,7 @@ bool AbstractShaderProgram::link(std::initializer_list> shade /* Or just warnings, if any */ } else if(!message.empty()) { - Error out; + Warning out; out.setFlag(Debug::NewLineAtTheEnd, false); out.setFlag(Debug::SpaceAfterEachValue, false); out << "Shader::compile(): compilation of " << shaderName(shader._type) From e9af8c8825aa98375cd25d4819440866f516db4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 25 Mar 2014 00:09:40 +0100 Subject: [PATCH 104/141] Fixed, cleaned up and updated AbstractShaderProgram documentation. --- src/Magnum/AbstractShaderProgram.h | 76 +++++++++++++++--------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 124625d4c..4f56fedf5 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -64,27 +64,21 @@ enum: UnsignedInt { NormalOutput = 1 }; @endcode -- **Uniform locations** for setting uniform data (see below) (private - variables), for example: -@code -Int TransformationUniform = 0, - ProjectionUniform = 1, - DiffuseTextureUniform = 2, - SpecularTextureUniform = 3; -@endcode -- **Constructor**, which attaches particular shaders, links the program and - gets uniform locations, for example: +- **Constructor**, which loads, compiles and attaches particular shaders and + links the program together, for example: @code MyShader() { - // Load shaders, compile them and attach them to the program + // Load shader sources Shader vert(Version::GL430, Shader::Type::Vertex); - vert.attachFile("PhongShader.vert"); - CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); - attachShader(vert); - Shader frag(Version::GL430, Shader::Type::Fragment); - frag.attachFile("PhongShader.vert"); - CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); + vert.addFile("PhongShader.vert"); + frag.addFile("PhongShader.vert"); + + // Invoke parallel compilation for best performance + CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); + + // Attach the shaders + attachShader(vert); attachShader(frag); // Link the program together @@ -95,24 +89,29 @@ MyShader() { protected @ref setUniform() functions. For usability purposes you can implement also method chaining. Example: @code -MyShader& setTransformation(const Matrix4& matrix) { - setUniform(TransformationUniform, matrix); +MyShader& setProjectionMatrix(const Matrix4& matrix) { + setUniform(0, matrix); + return *this; +} +MyShader& setTransformationMatrix(const Matrix4& matrix) { + setUniform(1, matrix); return *this; } -MyShader& setProjection(const Matrix4& matrix) { - setUniform(ProjectionUniform, matrix); +MyShader& setNormalMatrix(const Matrix3x3& matrix) { + setUniform(2, matrix); return *this; } @endcode -- **Texture setting functions** in which you bind the textures to particular - layers using @ref AbstractTexture::bind() and equivalent, for example: +- %Texture setting functions in which you bind the textures + to particular layers using @ref *Texture::bind() and equivalents, for + example: @code MyShader& setDiffuseTexture(Texture2D& texture) { - texture->bind(0); + texture.bind(0); return *this; } MyShader& setSpecularTexture(Texture2D& texture) { - texture->bind(1); + texture.bind(1); return *this; } @endcode @@ -142,7 +141,7 @@ If you don't have the required extension, declare the attributes without `layout()` qualifier and use functions @ref bindAttributeLocation() and @ref bindFragmentDataLocation() / @ref bindFragmentDataLocationIndexed() between attaching the shaders and linking the program. Note that additional syntax -changes may be needed for GLSL 1.20 and GLSL ES 1.0. +changes may be needed for GLSL 1.20 and GLSL ES. @code in vec4 position; in vec3 normal; @@ -192,21 +191,24 @@ code, e.g.: @code // GLSL 4.30, or #extension GL_ARB_explicit_uniform_location: enable -layout(location = 0) uniform mat4 transformation; -layout(location = 1) uniform mat4 projection; +layout(location = 0) uniform mat4 projectionMatrix; +layout(location = 1) uniform mat4 transformationMatrix; +layout(location = 2) uniform mat3 normalMatrix; @endcode If you don't have the required extension, declare the uniforms without the -`layout()` qualifier and get uniform location using @ref uniformLocation() -*after* linking stage. Note that additional syntax changes may be needed for -GLSL 1.20 and GLSL ES 1.0. +`layout()` qualifier, get uniform location using @ref uniformLocation() *after* +linking stage and then use the queried location in uniform setting functions. +Note that additional syntax changes may be needed for GLSL 1.20 and GLSL ES. @code -uniform mat4 transformation; -uniform mat4 projection; +uniform mat4 projectionMatrix; +uniform mat4 transformationMatrix; +uniform mat3 normalMatrix; @endcode @code -Int transformationUniform = uniformLocation("transformation"); -Int projectionUniform = uniformLocation("projection"); +Int projectionMatrixUniform = uniformLocation("projectionMatrix"); +Int transformationMatrixUniform = uniformLocation("transformationMatrix"); +Int normalMatrixUniform = uniformLocation("normalMatrix"); @endcode @see @ref maxUniformLocations() @@ -238,8 +240,8 @@ uniform sampler2D diffuseTexture; uniform sampler2D specularTexture; @endcode @code -setUniform(DiffuseTextureUniform, 0); -setUniform(SpecularTextureUniform, 1); +setUniform(uniformLocation("diffuseTexture"), 0); +setUniform(uniformLocation("specularTexture"), 1); @endcode @see @ref Shader::maxTextureImageUnits() From d7a13940b13dad6acde6edf7e5a0bd2337f8b866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 25 Mar 2014 01:10:40 +0100 Subject: [PATCH 105/141] Shaders: making use of parallel compilation. Compiling fragment and vertex shader simultaenously, at least. Nothing more can be done for now. Also removed weird duplicate compile/link calls from MeshVisualizer, went unnoticed since b9a72bd3d1fd2bf763ca43a8cde7726583b671c2. Why did I do that?! --- src/Magnum/Shaders/DistanceFieldVector.cpp | 11 +++---- src/Magnum/Shaders/Flat.cpp | 11 +++---- src/Magnum/Shaders/MeshVisualizer.cpp | 34 ++++++++++++---------- src/Magnum/Shaders/Phong.cpp | 11 +++---- src/Magnum/Shaders/Vector.cpp | 11 +++---- src/Magnum/Shaders/VertexColor.cpp | 11 +++---- 6 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/Magnum/Shaders/DistanceFieldVector.cpp b/src/Magnum/Shaders/DistanceFieldVector.cpp index 2b81b9d03..6479807ae 100644 --- a/src/Magnum/Shaders/DistanceFieldVector.cpp +++ b/src/Magnum/Shaders/DistanceFieldVector.cpp @@ -51,14 +51,15 @@ template DistanceFieldVector::DistanceFieldV #endif Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + frag.addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); - CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); - AbstractShaderProgram::attachShader(frag); - - Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); vert.addSource(rs.get("DistanceFieldVector.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); + + CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({frag, vert})); + + AbstractShaderProgram::attachShader(frag); AbstractShaderProgram::attachShader(vert); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Shaders/Flat.cpp b/src/Magnum/Shaders/Flat.cpp index 49f5cd830..387e2c1f6 100644 --- a/src/Magnum/Shaders/Flat.cpp +++ b/src/Magnum/Shaders/Flat.cpp @@ -54,16 +54,17 @@ template Flat::Flat(const Flags flags): tran #endif Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + vert.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") .addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); - CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); - attachShader(vert); - - Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") .addSource(rs.get("Flat.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); + + CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); + + attachShader(vert); attachShader(frag); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Shaders/MeshVisualizer.cpp b/src/Magnum/Shaders/MeshVisualizer.cpp index 660929260..c0d50e681 100644 --- a/src/Magnum/Shaders/MeshVisualizer.cpp +++ b/src/Magnum/Shaders/MeshVisualizer.cpp @@ -30,6 +30,7 @@ #include "Magnum/Context.h" #include "Magnum/Extensions.h" #include "Magnum/Shader.h" +#include "MagnumExternal/Optional/optional.hpp" #include "Implementation/CreateCompatibilityShader.h" @@ -56,31 +57,35 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP #endif Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(rs.get("generic.glsl")) .addSource(rs.get("MeshVisualizer.vert")); - CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); - vert.compile(); - attachShader(vert); + frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") + .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") + .addSource(rs.get("MeshVisualizer.frag")); #ifndef MAGNUM_TARGET_GLES + std::optional geom; if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { - Shader geom = Implementation::createCompatibilityShader(version, Shader::Type::Geometry); - geom.addSource(rs.get("MeshVisualizer.geom")); - CORRADE_INTERNAL_ASSERT_OUTPUT(geom.compile()); - geom.compile(); - attachShader(geom); + geom = Implementation::createCompatibilityShader(version, Shader::Type::Geometry); + geom->addSource(rs.get("MeshVisualizer.geom")); } #endif - 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("MeshVisualizer.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); - frag.compile(); + #ifndef MAGNUM_TARGET_GLES + if(geom) Shader::compile({vert, *geom, frag}); + else + #endif + Shader::compile({vert, frag}); + + attachShader(vert); attachShader(frag); + #ifndef MAGNUM_TARGET_GLES + if(geom) attachShader(*geom); + #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported(version)) @@ -99,7 +104,6 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP } CORRADE_INTERNAL_ASSERT_OUTPUT(link()); - link(); #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported(version)) diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/Phong.cpp index 48f34597c..e7bf2594e 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/Phong.cpp @@ -54,18 +54,19 @@ Phong::Phong(const Flags flags): transformationMatrixUniform(0), projectionMatri #endif Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + vert.addSource(flags ? "#define TEXTURED\n" : "") .addSource(rs.get("generic.glsl")) .addSource(rs.get("Phong.vert")); - CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); - attachShader(vert); - - 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("Phong.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); + + CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); + + attachShader(vert); attachShader(frag); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Shaders/Vector.cpp b/src/Magnum/Shaders/Vector.cpp index a4337f26f..c02411e5e 100644 --- a/src/Magnum/Shaders/Vector.cpp +++ b/src/Magnum/Shaders/Vector.cpp @@ -51,14 +51,15 @@ template Vector::Vector(): transformationPro #endif Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + vert.addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); - CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); - AbstractShaderProgram::attachShader(vert); - - Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); frag.addSource(rs.get("Vector.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); + + CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); + + AbstractShaderProgram::attachShader(vert); AbstractShaderProgram::attachShader(frag); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Shaders/VertexColor.cpp b/src/Magnum/Shaders/VertexColor.cpp index ca08de6ce..178d3bf6f 100644 --- a/src/Magnum/Shaders/VertexColor.cpp +++ b/src/Magnum/Shaders/VertexColor.cpp @@ -51,14 +51,15 @@ template VertexColor::VertexColor(): transfo #endif Shader vert = Implementation::createCompatibilityShader(version, Shader::Type::Vertex); + Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); + vert.addSource(rs.get("generic.glsl")) .addSource(rs.get(vertexShaderName())); - CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); - attachShader(vert); - - Shader frag = Implementation::createCompatibilityShader(version, Shader::Type::Fragment); frag.addSource(rs.get("VertexColor.frag")); - CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); + + CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); + + attachShader(vert); attachShader(frag); #ifndef MAGNUM_TARGET_GLES From 98f7dbb61bb38f3e9a880ca6e250daff606b72f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 25 Mar 2014 01:34:42 +0100 Subject: [PATCH 106/141] Fix ShaderGLTest on ES3. --- src/Magnum/Test/ShaderGLTest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Test/ShaderGLTest.cpp b/src/Magnum/Test/ShaderGLTest.cpp index dc33d3fc8..654b68251 100644 --- a/src/Magnum/Test/ShaderGLTest.cpp +++ b/src/Magnum/Test/ShaderGLTest.cpp @@ -77,7 +77,7 @@ void ShaderGLTest::construct() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(shader.sources(), std::vector{"#version 130\n"}); #else - CORRADE_COMPARE(shader.sources(), std::vector{"#version 300\n"}); + CORRADE_COMPARE(shader.sources(), std::vector{"#version 300 es\n"}); #endif } @@ -116,7 +116,7 @@ void ShaderGLTest::constructMove() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(b.sources(), std::vector{"#version 130\n"}); #else - CORRADE_COMPARE(b.sources(), std::vector{"#version 300\n"}); + CORRADE_COMPARE(b.sources(), std::vector{"#version 300 es\n"}); #endif #ifndef MAGNUM_TARGET_GLES @@ -135,7 +135,7 @@ void ShaderGLTest::constructMove() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(c.sources(), std::vector{"#version 130\n"}); #else - CORRADE_COMPARE(c.sources(), std::vector{"#version 300\n"}); + CORRADE_COMPARE(c.sources(), std::vector{"#version 300 es\n"}); #endif } From 0955390ca84a2ed9b9adcd274e3ff16f5ab654e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 25 Mar 2014 17:46:21 +0100 Subject: [PATCH 107/141] Follow OpenGL terminology for texture binding units. Until now the textures were bound to layers, which was rather confusing, especially when binding layered textures to layers (gaah). Also the wording might have implied that each texture must be in some layer in order to make it usable in shader. This is no longer the case with (yet unimplemented) bindless texture, so another reason to remove the confusion. All occurences of texture layers were replaced texture binding units to follow OpenGL naming. It was mostly in the docs, except for already-deprecated *Layer enums in shaders, but they will be removed soon anyway. --- doc/portability.dox | 4 +- src/Magnum/AbstractShaderProgram.h | 23 +++++----- src/Magnum/AbstractTexture.cpp | 50 +++++++++++----------- src/Magnum/AbstractTexture.h | 38 ++++++++-------- src/Magnum/Implementation/TextureState.cpp | 10 ++--- src/Magnum/Implementation/TextureState.h | 4 +- src/Magnum/RectangleTexture.h | 26 +++++------ src/Magnum/Shaders/AbstractVector.h | 2 +- src/Magnum/Shaders/Flat.h | 3 +- src/Magnum/Shaders/Phong.h | 12 +++--- src/Magnum/Texture.h | 41 +++++++++--------- src/Magnum/TextureArray.h | 6 +-- src/Magnum/TextureTools/DistanceField.cpp | 6 +-- 13 files changed, 113 insertions(+), 112 deletions(-) diff --git a/doc/portability.dox b/doc/portability.dox index 880775cda..578d0fa46 100644 --- a/doc/portability.dox +++ b/doc/portability.dox @@ -161,8 +161,8 @@ if(!Context::instance()->isExtensionSupported%Texture setting functions in which you bind the textures - to particular layers using @ref *Texture::bind() and equivalents, for - example: + to particular texture units using @ref *Texture::bind() and equivalents, + for example: @code MyShader& setDiffuseTexture(Texture2D& texture) { texture.bind(0); @@ -219,10 +219,10 @@ Int normalMatrixUniform = uniformLocation("normalMatrix"); @ref Magnum::AbstractShaderProgram::uniformLocation() "uniformLocation()" instead. -@subsection AbstractShaderProgram-texture-layer Binding texture layer uniforms +@subsection AbstractShaderProgram-texture-units Specifying texture binding units -The preferred workflow is to specify texture layers directly in the shader -code, e.g.: +The preferred workflow is to specify texture binding unit directly in the +shader code, e.g.: @code // GLSL 4.20, or #extension GL_ARB_shading_language_420pack: enable @@ -230,11 +230,10 @@ layout(binding = 0) uniform sampler2D diffuseTexture; layout(binding = 1) uniform sampler2D specularTexture; @endcode -If you don't have the required extension (or if you want to change the layer -later), declare the uniforms without the `layout()` qualifier and set the -texture layer uniform using @ref setUniform(Int, const T&) "setUniform(Int, Int)". -Note that additional syntax changes may be needed for GLSL 1.20 and GLSL ES -1.0. +If you don't have the required extension, declare the uniforms without the +`layout()` qualifier and set the texture binding unit using +@ref setUniform(Int, const T&) "setUniform(Int, Int)". Note that additional +syntax changes may be needed for GLSL 1.20 and GLSL ES 1.0. @code uniform sampler2D diffuseTexture; uniform sampler2D specularTexture; @@ -246,9 +245,9 @@ setUniform(uniformLocation("specularTexture"), 1); @see @ref Shader::maxTextureImageUnits() @requires_gl42 %Extension @extension{ARB,shading_language_420pack} for explicit - texture layer binding instead of using + texture binding unit instead of using @ref Magnum::AbstractShaderProgram::setUniform(Int, const T&) "setUniform(Int, Int)". -@requires_gl Explicit texture layer binding is not supported in OpenGL ES. Use +@requires_gl Explicit texture binding unit is not supported in OpenGL ES. Use @ref Magnum::AbstractShaderProgram::setUniform(Int, const T&) "setUniform(Int, Int)" instead. diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 83eee7b62..26d668a75 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -116,33 +116,33 @@ AbstractTexture& AbstractTexture::setLabel(const std::string& label) { return *this; } -void AbstractTexture::bind(Int layer) { +void AbstractTexture::bind(Int textureUnit) { Implementation::TextureState* const textureState = Context::current()->state().texture; - /* If already bound in given layer, nothing to do */ - if(textureState->bindings[layer] == _id) return; + /* If already bound in given texture unit, nothing to do */ + if(textureState->bindings[textureUnit] == _id) return; - (this->*Context::current()->state().texture->bindImplementation)(layer); + (this->*Context::current()->state().texture->bindImplementation)(textureUnit); } -void AbstractTexture::bindImplementationDefault(GLint layer) { +void AbstractTexture::bindImplementationDefault(GLint textureUnit) { Implementation::TextureState* const textureState = Context::current()->state().texture; - /* Change to given layer, if not already there */ - if(textureState->currentLayer != layer) - glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = layer)); + /* Activate given texture unit, if not already active */ + if(textureState->currentTextureUnit != textureUnit) + glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = textureUnit)); - /* Bind the texture to the layer */ - glBindTexture(_target, (textureState->bindings[layer] = _id)); + /* Bind the texture to the unit */ + glBindTexture(_target, (textureState->bindings[textureUnit] = _id)); } #ifndef MAGNUM_TARGET_GLES -void AbstractTexture::bindImplementationMulti(GLint layer) { - glBindTextures(layer, 1, &_id); +void AbstractTexture::bindImplementationMulti(GLint textureUnit) { + glBindTextures(textureUnit, 1, &_id); } -void AbstractTexture::bindImplementationDSA(GLint layer) { - glBindMultiTextureEXT(GL_TEXTURE0 + layer, _target, (Context::current()->state().texture->bindings[layer] = _id)); +void AbstractTexture::bindImplementationDSA(GLint textureUnit) { + glBindMultiTextureEXT(GL_TEXTURE0 + textureUnit, _target, (Context::current()->state().texture->bindings[textureUnit] = _id)); } #endif @@ -187,24 +187,24 @@ void AbstractTexture::mipmapImplementationDSA() { void AbstractTexture::bindInternal() { /* Using glBindTextures() here is meaningless, because the non-DSA - functions need to have the texture bound in *currently active* layer, + functions need to have the texture bound in *currently active* unit, so we would need to call glActiveTexture() afterwards anyway. */ Implementation::TextureState* const textureState = Context::current()->state().texture; - /* If the texture is already bound in current layer, nothing to do */ - if(textureState->bindings[textureState->currentLayer] == _id) + /* If the texture is already bound in current unit, nothing to do */ + if(textureState->bindings[textureState->currentTextureUnit] == _id) return; - /* Set internal layer as active if not already */ - CORRADE_INTERNAL_ASSERT(textureState->maxLayers > 1); - const GLint internalLayer = textureState->maxLayers-1; - if(textureState->currentLayer != internalLayer) - glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = internalLayer)); + /* Set internal unit as active if not already */ + CORRADE_INTERNAL_ASSERT(textureState->maxTextureUnits > 1); + const GLint internalTextureUnit = textureState->maxTextureUnits-1; + if(textureState->currentTextureUnit != internalTextureUnit) + glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = internalTextureUnit)); - /* Bind the texture to internal layer, if not already */ - if(textureState->bindings[internalLayer] != _id) - glBindTexture(_target, (textureState->bindings[internalLayer] = _id)); + /* Bind the texture to internal unit, if not already */ + if(textureState->bindings[internalTextureUnit] != _id) + glBindTexture(_target, (textureState->bindings[internalTextureUnit] = _id)); } ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) { diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 670edbed8..263094e53 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -51,17 +51,18 @@ documentation for details. @section AbstractTexture-performance-optimization Performance optimizations and security -The engine tracks currently bound textures in all available layers to avoid -unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. %Texture -configuration functions use dedicated highest available texture layer to not -affect active bindings in user layers. %Texture limits and +The engine tracks currently bound textures in all available texture units to +avoid unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. +%Texture configuration functions use dedicated highest available texture unit +to not affect active bindings in user units. %Texture limits and implementation-defined values (such as @ref maxColorSamples()) are cached, so repeated queries don't result in repeated @fn_gl{Get} calls. If extension @extension{ARB,multi_bind} is available, @ref bind() uses @fn_gl{BindTextures} to avoid unnecessary calls to @fn_gl{ActiveTexture}. Otherwise, if extension @extension{EXT,direct_state_access} is available, -@ref bind() uses the DSA function. +@ref bind() uses @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} +function. In addition, if extension @extension{EXT,direct_state_access} is available, also all texture configuration and data updating functions use DSA functions @@ -76,7 +77,7 @@ there isn't any function combining both features. To achieve least state changes, fully configure each texture in one run -- method chaining comes in handy -- and try to have often used textures in -dedicated layers, not occupied by other textures. First configure the texture +dedicated units, not occupied by other textures. First configure the texture and *then* set the data, so OpenGL can optimize them to match the settings. To avoid redundant consistency checks and memory reallocations when updating texture data, set texture storage at once using @ref Texture::setStorage() "setStorage()" @@ -215,20 +216,19 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { GLuint id() const { return _id; } /** - * @brief Bind texture for rendering + * @brief Bind texture to given texture unit * - * Sets current texture as active in given layer. Note that only one - * texture can be bound to given layer. If @extension{ARB,multi_bind} - * (part of OpenGL 4.4) or @extension{EXT,direct_state_access} is not - * available, the layer is made active before binding the texture. + * If @extension{ARB,multi_bind} (part of OpenGL 4.4) or + * @extension{EXT,direct_state_access} is not available, the texture + * unit is made active before binding the texture. * @note This function is meant to be used only internally from * @ref AbstractShaderProgram subclasses. See its documentation * for more information. - * @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture}, - * @fn_gl{BindTextures} or - * @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} + * @see @ref Shader::maxCombinedTextureImageUnits(), + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture}, @fn_gl{BindTextures} + * or @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} */ - void bind(Int layer); + void bind(Int textureUnit); #ifdef DOXYGEN_GENERATING_OUTPUT private: @@ -239,7 +239,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { explicit AbstractTexture(GLenum target); - /* Unlike bind() this also sets the binding layer as active */ + /* Unlike bind() this also sets the texture binding unit as active */ void MAGNUM_LOCAL bindInternal(); void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap); @@ -257,10 +257,10 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { GLenum _target; private: - void MAGNUM_LOCAL bindImplementationDefault(GLint layer); + void MAGNUM_LOCAL bindImplementationDefault(GLint textureUnit); #ifndef MAGNUM_TARGET_GLES - void MAGNUM_LOCAL bindImplementationMulti(GLint layer); - void MAGNUM_LOCAL bindImplementationDSA(GLint layer); + void MAGNUM_LOCAL bindImplementationMulti(GLint textureUnit); + void MAGNUM_LOCAL bindImplementationDSA(GLint textureUnit); #endif void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 845ade148..536f6a7b9 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -36,7 +36,7 @@ namespace Magnum { namespace Implementation { -TextureState::TextureState(Context& context, std::vector& extensions): maxLayers(0), maxMaxAnisotropy(0.0f), currentLayer(0) +TextureState::TextureState(Context& context, std::vector& extensions): maxTextureUnits(0), maxMaxAnisotropy(0.0f), currentTextureUnit(0) #ifndef MAGNUM_TARGET_GLES , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) #endif @@ -172,10 +172,10 @@ TextureState::TextureState(Context& context, std::vector& extension setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt; } else setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationNoOp; - /* Resize bindings array to hold all possible layers */ - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxLayers); - CORRADE_INTERNAL_ASSERT(maxLayers > 0); - bindings.resize(maxLayers); + /* Resize bindings array to hold all possible texture units */ + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); + CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0); + bindings.resize(maxTextureUnits); } TextureState::~TextureState() = default; diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 3b766becb..f6dec2d7c 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -68,9 +68,9 @@ struct TextureState { void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr); #endif - GLint maxLayers; + GLint maxTextureUnits; GLfloat maxMaxAnisotropy; - GLint currentLayer; + GLint currentTextureUnit; #ifndef MAGNUM_TARGET_GLES GLint maxColorSamples, maxDepthSamples, diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 2d8c76c6c..034e44dd9 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -86,8 +86,8 @@ class RectangleTexture: public AbstractTexture { * * Sets filter used when the object pixel size is smaller than the * texture size. If @extension{EXT,direct_state_access} is not - * available, the texture is bound to some layer before the operation. - * Initial value is @ref Sampler::Filter::Linear. + * available, the texture is bound to some texture unit before the + * operation. Initial value is @ref Sampler::Filter::Linear. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_MIN_FILTER} @@ -109,7 +109,7 @@ class RectangleTexture: public AbstractTexture { * * The result is not cached in any way. If * @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. + * is bound to some texture unit before the operation. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_WIDTH} and @def_gl{TEXTURE_HEIGHT} @@ -124,9 +124,9 @@ class RectangleTexture: public AbstractTexture { * @return Reference to self (for method chaining) * * Sets wrapping type for coordinates out of (0, textureSizeInGivenDirection-1) - * range for rectangle textures. If @extension{EXT,direct_state_access} - * is not available, the texture is bound to some layer before the - * operation. Initial value is @ref Sampler::Wrapping::ClampToEdge. + * range. If @extension{EXT,direct_state_access} is not available, the + * texture is bound to some texture unit before the operation. Initial + * value is @ref Sampler::Wrapping::ClampToEdge. * @attention Only @ref Sampler::Wrapping::ClampToEdge and * @ref Sampler::Wrapping::ClampToBorder is supported on this * texture type. @@ -165,10 +165,10 @@ class RectangleTexture: public AbstractTexture { * allowed. * * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. If @extension{ARB,texture_storage} - * (part of OpenGL 4.2), OpenGL ES 3.0 or @es_extension{EXT,texture_storage} - * in OpenGL ES 2.0 is not available, the feature is emulated with - * @ref setImage() call. + * is bound to some texture unit before the operation. If + * @extension{ARB,texture_storage} (part of OpenGL 4.2), OpenGL ES 3.0 + * or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not + * available, the feature is emulated with @ref setImage() call. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexStorage2D} * or @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, * eventually @fn_gl{TexImage2D} or @@ -189,7 +189,7 @@ class RectangleTexture: public AbstractTexture { * @ref imageSize(). * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. If + * texture is bound to some texture unit before the operation. If * @extension{ARB,robustness} is available, the operation is protected * from buffer overflow. However, if both @extension{EXT,direct_state_access} * and @extension{ARB,robustness} are available, the DSA version is @@ -230,7 +230,7 @@ class RectangleTexture: public AbstractTexture { * use @ref setStorage() and @ref setSubImage() instead. * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. + * texture is bound to some texture unit before the operation. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexImage2D} * or @fn_gl_extension{TextureImage2D,EXT,direct_state_access} */ @@ -260,7 +260,7 @@ class RectangleTexture: public AbstractTexture { * @return Reference to self (for method chaining) * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. + * texture is bound to some texture unit before the operation. * @see @ref setStorage(), @ref setImage(), @fn_gl{ActiveTexture}, * @fn_gl{BindTexture} and @fn_gl{TexSubImage2D} or * @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access} diff --git a/src/Magnum/Shaders/AbstractVector.h b/src/Magnum/Shaders/AbstractVector.h index 720de0714..4c1fc5399 100644 --- a/src/Magnum/Shaders/AbstractVector.h +++ b/src/Magnum/Shaders/AbstractVector.h @@ -49,7 +49,7 @@ template class AbstractVector: public AbstractShaderProg #ifdef MAGNUM_BUILD_DEPRECATED enum: Int { /** - * Layer for vector texture + * Vector texture binding unit * @deprecated Use @ref Magnum::Shaders::AbstractVector::setVectorTexture() "setVectorTexture()" instead. */ VectorTextureLayer = 16 diff --git a/src/Magnum/Shaders/Flat.h b/src/Magnum/Shaders/Flat.h index e64afdd2a..f4cdde677 100644 --- a/src/Magnum/Shaders/Flat.h +++ b/src/Magnum/Shaders/Flat.h @@ -74,7 +74,8 @@ template class MAGNUM_SHADERS_EXPORT Flat: public Abstra #ifdef MAGNUM_BUILD_DEPRECATED enum: Int { /** - * Layer for color texture. Used only if @ref Flag::Textured is set. + * Color texture binding unit. Used only if @ref Flag::Textured is + * set. * @deprecated use @ref Magnum::Shaders::Flat::setTexture() "setTexture()" instead. */ TextureLayer = 0 diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index f07967cfc..e203f98cc 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -65,24 +65,24 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { #ifdef MAGNUM_BUILD_DEPRECATED enum: Int { /** - * Layer for ambient texture. Used only if @ref Flag::AmbientTexture - * is set. + * Ambient texture binding unit. Used only if + * @ref Flag::AmbientTexture is set. * @deprecated Use @ref Magnum::Shaders::Phong::setAmbientTexture() "setAmbientTexture()" * instead. */ AmbientTextureLayer = 0, /** - * Layer for diffuse texture. Used only if @ref Flag::DiffuseTexture - * is set. + * Diffuse texture binding unit. Used only if + * @ref Flag::DiffuseTexture is set. * @deprecated Use @ref Magnum::Shaders::Phong::setDiffuseTexture() "setDiffuseTexture()" * instead. */ DiffuseTextureLayer = 1, /** - * Layer for specular texture. Used only if @ref Flag::SpecularTexture - * is set. + * Specular texture binding unit. Used only if + * @ref Flag::SpecularTexture is set. * @deprecated Use @ref Magnum::Shaders::Phong::setSpecularTexture() "setSpecularTexture()" * instead. */ diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 00e726294..6edcefa75 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -173,7 +173,7 @@ template class Texture: public AbstractTexture { * * The result is not cached in any way. If * @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. + * is bound to some texture unit before the operation. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or @def_gl{TEXTURE_DEPTH}. @@ -194,8 +194,9 @@ template class Texture: public AbstractTexture { * * Sets filter used when the object pixel size is smaller than the * texture size. If @extension{EXT,direct_state_access} is not - * available, the texture is bound to some layer before the operation. - * Initial value is (@ref Sampler::Filter::Nearest, @ref Sampler::Mipmap::Linear). + * available, the texture is bound to some texture unit before the + * operation. Initial value is {@ref Sampler::Filter::Nearest, + * @ref Sampler::Mipmap::Linear}. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_MIN_FILTER} @@ -212,8 +213,8 @@ template class Texture: public AbstractTexture { * * Sets filter used when the object pixel size is larger than largest * texture size. If @extension{EXT,direct_state_access} is not - * available, the texture is bound to some layer before the operation. - * Initial value is @ref Sampler::Filter::Linear. + * available, the texture is bound to some texture unit before the + * operation. Initial value is @ref Sampler::Filter::Linear. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_MAG_FILTER} @@ -228,11 +229,10 @@ template class Texture: public AbstractTexture { * @param wrapping Wrapping type for all texture dimensions * @return Reference to self (for method chaining) * - * Sets wrapping type for coordinates out of range (0, 1) for normal - * textures and (0, textureSizeInGivenDirection-1) for rectangle - * textures. If @extension{EXT,direct_state_access} is not available, - * the texture is bound to some layer before the operation. Initial - * value is @ref Sampler::Wrapping::Repeat. + * Sets wrapping type for coordinates out of range (0.0f, 1.0f). If + * @extension{EXT,direct_state_access} is not available, the texture is + * bound to some texture unit before the operation. Initial value is + * @ref Sampler::Wrapping::Repeat. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T}, @@ -249,7 +249,7 @@ template class Texture: public AbstractTexture { * * Border color when wrapping is set to @ref Sampler::Wrapping::ClampToBorder. * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. Initial value is + * is bound to some texture unit before the operation. Initial value is * `{0.0f, 0.0f, 0.0f, 0.0f}`. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} @@ -270,7 +270,7 @@ template class Texture: public AbstractTexture { * @extension{EXT,texture_filter_anisotropic} (desktop or ES) is not * available, this function does nothing. If * @extension{EXT,direct_state_access} is not available, the texture is - * bound to some layer before the operation. + * bound to some texture unit before the operation. * @see @ref Sampler::maxMaxAnisotropy(), @fn_gl{ActiveTexture}, * @fn_gl{BindTexture} and @fn_gl{TexParameter} or * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with @@ -295,10 +295,11 @@ template class Texture: public AbstractTexture { * allowed. * * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. If @extension{ARB,texture_storage} - * (part of OpenGL 4.2), OpenGL ES 3.0 or @es_extension{EXT,texture_storage} - * in OpenGL ES 2.0 is not available, the feature is emulated with - * sequence of @ref setImage() calls. + * is bound to some texture unit before the operation. If + * @extension{ARB,texture_storage} (part of OpenGL 4.2), OpenGL ES 3.0 + * or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not + * available, the feature is emulated with sequence of @ref setImage() + * calls. * @todo allow the user to specify ColorType explicitly to avoid * issues in WebGL (see setSubImage()) * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @@ -327,7 +328,7 @@ template class Texture: public AbstractTexture { * @ref imageSize(). * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. If + * texture is bound to some texture unit before the operation. If * @extension{ARB,robustness} is available, the operation is protected * from buffer overflow. However, if both @extension{EXT,direct_state_access} * and @extension{ARB,robustness} are available, the DSA version is @@ -371,7 +372,7 @@ template class Texture: public AbstractTexture { * @ref setStorage() and @ref setSubImage() instead. * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. + * texture is bound to some texture unit before the operation. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or * @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/ @@ -405,7 +406,7 @@ template class Texture: public AbstractTexture { * @return Reference to self (for method chaining) * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. + * texture is bound to some texture unit before the operation. * * @attention In @ref MAGNUM_TARGET_WEBGL "WebGL" the @ref ColorType of * data passed in @p image must match the original one specified @@ -442,7 +443,7 @@ template class Texture: public AbstractTexture { * @return Reference to self (for method chaining) * * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. + * is bound to some texture unit before the operation. * @see setMinificationFilter(), @fn_gl{ActiveTexture}, * @fn_gl{BindTexture} and @fn_gl{GenerateMipmap} or * @fn_gl_extension{GenerateTextureMipmap,EXT,direct_state_access} diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 412bf6503..578fcb6a2 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -158,7 +158,7 @@ template class TextureArray: public AbstractTexture { * allowed. * * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some layer before the operation. If + * is bound to some texture unit before the operation. If * @extension{ARB,texture_storage} (part of OpenGL 4.2) or OpenGL ES * 3.0 is not available, the feature is emulated with sequence of * @ref setImage() calls. @@ -200,7 +200,7 @@ template class TextureArray: public AbstractTexture { * @ref setStorage() and @ref setSubImage() instead. * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. + * texture is bound to some texture unit before the operation. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexImage2D}/@fn_gl{TexImage3D} or * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ @@ -233,7 +233,7 @@ template class TextureArray: public AbstractTexture { * @return Reference to self (for method chaining) * * If @extension{EXT,direct_state_access} is not available, the - * texture is bound to some layer before the operation. + * texture is bound to some texture unit before the operation. * @see @ref setStorage(), @ref setImage(), @fn_gl{ActiveTexture}, * @fn_gl{BindTexture} and @fn_gl{TexSubImage2D}/@fn_gl{TexSubImage3D} * or @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}/ diff --git a/src/Magnum/TextureTools/DistanceField.cpp b/src/Magnum/TextureTools/DistanceField.cpp index a68959db2..ccb2aefd6 100644 --- a/src/Magnum/TextureTools/DistanceField.cpp +++ b/src/Magnum/TextureTools/DistanceField.cpp @@ -63,12 +63,12 @@ class DistanceFieldShader: public AbstractShaderProgram { } DistanceFieldShader& setTexture(Texture2D& texture) { - texture.bind(TextureLayer); + texture.bind(TextureUnit); return *this; } private: - enum: Int { TextureLayer = 8 }; + enum: Int { TextureUnit = 8 }; Int radiusUniform, scalingUniform, @@ -130,7 +130,7 @@ DistanceFieldShader::DistanceFieldShader(): radiusUniform(0), scalingUniform(1) if(!Context::current()->isExtensionSupported()) #endif { - setUniform(uniformLocation("textureData"), TextureLayer); + setUniform(uniformLocation("textureData"), TextureUnit); } } From 67f4a2ff65b91da7cf6b308ab402aa913fbf09b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 25 Mar 2014 18:02:09 +0100 Subject: [PATCH 108/141] Doc++ --- src/Magnum/ResourceManager.h | 2 +- src/Magnum/Shader.h | 4 ++-- src/Magnum/Shaders/Phong.h | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Magnum/ResourceManager.h b/src/Magnum/ResourceManager.h index 67d6dfcc8..265a875f1 100644 --- a/src/Magnum/ResourceManager.h +++ b/src/Magnum/ResourceManager.h @@ -212,7 +212,7 @@ if(!cube) { @endcode - Using the resource data. @code -shader->setTexture(layer); +shader->setTexture(*texture); cube->draw(*shader); @endcode - Destroying resource references and deleting manager instance when nothing diff --git a/src/Magnum/Shader.h b/src/Magnum/Shader.h index d3a077f86..6d2b5ba1b 100644 --- a/src/Magnum/Shader.h +++ b/src/Magnum/Shader.h @@ -375,8 +375,8 @@ class MAGNUM_EXPORT Shader: public AbstractObject { * * The result is cached, repeated queries don't result in repeated * OpenGL calls. - * @see @ref AbstractTexture::maxLayers(), @ref maxTextureImageUnits(), - * @fn_gl{Get} with @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS} + * @see @ref maxTextureImageUnits(), @fn_gl{Get} with + * @def_gl{MAX_COMBINED_TEXTURE_IMAGE_UNITS} */ static Int maxCombinedTextureImageUnits(); diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index e203f98cc..c2cd09356 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -197,6 +197,9 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { /** * @brief Set normal matrix * @return Reference to self (for method chaining) + * + * The matrix doesn't need to be normalized, as the renormalization + * must be done in the shader anyway. */ Phong& setNormalMatrix(const Matrix3x3& matrix) { setUniform(normalMatrixUniform, matrix); From bf1d2e26fa19f898cde76de4347618de35162763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 12:15:38 +0100 Subject: [PATCH 109/141] Support for setting border color on integer textures. EXT_texture_integer implementation is now complete. Just GL 3.0 subset, though, as apparently glClearColorI*() is not part of it. --- doc/opengl-support.dox | 2 +- src/Magnum/AbstractTexture.cpp | 30 +++++++++++++ src/Magnum/AbstractTexture.h | 16 +++---- src/Magnum/CubeMapTexture.h | 16 ++++++- src/Magnum/CubeMapTextureArray.h | 14 +++++++ src/Magnum/Implementation/TextureState.cpp | 4 ++ src/Magnum/Implementation/TextureState.h | 2 + src/Magnum/RectangleTexture.h | 14 +++++++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 26 ++++++++++++ src/Magnum/Test/CubeMapTextureGLTest.cpp | 34 +++++++++++++++ src/Magnum/Test/RectangleTextureGLTest.cpp | 21 +++++++++- src/Magnum/Test/TextureArrayGLTest.cpp | 40 ++++++++++++++++-- src/Magnum/Test/TextureGLTest.cpp | 42 +++++++++++++++++-- src/Magnum/Texture.h | 28 +++++++++++++ src/Magnum/TextureArray.h | 14 +++++++ 15 files changed, 286 insertions(+), 17 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 9da8957c3..ed585c8ab 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -71,7 +71,7 @@ following: @extension{EXT,texture_shared_exponent} | done @extension{EXT,framebuffer_sRGB} | | @extension{EXT,draw_buffers2} | | -@extension{EXT,texture_integer} | missing integer color specification functions +@extension{EXT,texture_integer} | done (GL 3.0 subset) @extension{EXT,transform_feedback} | | @extension{NV,half_float} | done (GL 3.0 subset) @extension{NV,depth_buffer_float} | | diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 26d668a75..427f90140 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -162,6 +162,16 @@ void AbstractTexture::setBorderColor(const Color4& color) { #endif } +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::setBorderColor(const Vector4ui& color) { + (this->*Context::current()->state().texture->parameterIuivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); +} + +void AbstractTexture::setBorderColor(const Vector4i& color) { + (this->*Context::current()->state().texture->parameterIivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); +} +#endif + void AbstractTexture::setMaxAnisotropy(const Float anisotropy) { (this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy); } @@ -609,6 +619,26 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat } #endif +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLuint* values) { + bindInternal(); + glTexParameterIuiv(_target, parameter, values); +} + +void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLuint* values) { + glTextureParameterIuivEXT(_id, _target, parameter, values); +} + +void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLint* values) { + bindInternal(); + glTexParameterIiv(_target, parameter, values); +} + +void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLint* values) { + glTextureParameterIivEXT(_id, _target, parameter, values); +} +#endif + void AbstractTexture::setMaxAnisotropyImplementationNoOp(GLfloat) {} void AbstractTexture::setMaxAnisotropyImplementationExt(GLfloat anisotropy) { diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 263094e53..d0ab656f1 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -245,6 +245,8 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap); void setMagnificationFilter(Sampler::Filter filter); void setBorderColor(const Color4& color); + void setBorderColor(const Vector4i& color); + void setBorderColor(const Vector4ui& color); void setMaxAnisotropy(Float anisotropy); void invalidateImage(Int level); void generateMipmap(); @@ -264,18 +266,18 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { #endif void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value); - #ifndef MAGNUM_TARGET_GLES - void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value); - #endif - void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value); + void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values); #ifndef MAGNUM_TARGET_GLES - void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value); + void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLuint* values); + void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLint* values); #endif - - void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values); #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value); + void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value); void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values); + void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLuint* values); + void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLint* values); #endif void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat); diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 7b2ce1363..d750fd99d 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -116,12 +116,26 @@ class CubeMapTexture: public AbstractTexture { return *this; } - /** @copydoc Texture::setBorderColor() */ + /** @copydoc Texture::setBorderColor(const Color4&) */ CubeMapTexture& setBorderColor(const Color4& color) { AbstractTexture::setBorderColor(color); return *this; } + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setBorderColor(const Vector4ui&) */ + CubeMapTexture& setBorderColor(const Vector4ui& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @copydoc Texture::setBorderColor(const Vector4i&) */ + CubeMapTexture& setBorderColor(const Vector4i& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + #endif + /** @copydoc Texture::setMaxAnisotropy() */ CubeMapTexture& setMaxAnisotropy(Float anisotropy) { AbstractTexture::setMaxAnisotropy(anisotropy); diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 22cc837cc..5ec43b656 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -113,6 +113,20 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setBorderColor(const Vector4ui&) */ + CubeMapTextureArray& setBorderColor(const Vector4ui& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @copydoc Texture::setBorderColor(const Vector4i&) */ + CubeMapTextureArray& setBorderColor(const Vector4i& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + #endif + /** @copydoc Texture::setMaxAnisotropy() */ CubeMapTextureArray& setMaxAnisotropy(Float anisotropy) { AbstractTexture::setMaxAnisotropy(anisotropy); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 536f6a7b9..beae61381 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -63,6 +63,8 @@ TextureState::TextureState(Context& context, std::vector& extension parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSA; parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; + parameterIuivImplementation = &AbstractTexture::parameterImplementationDSA; + parameterIivImplementation = &AbstractTexture::parameterImplementationDSA; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA; mipmapImplementation = &AbstractTexture::mipmapImplementationDSA; getImageImplementation = &AbstractTexture::getImageImplementationDSA; @@ -82,6 +84,8 @@ TextureState::TextureState(Context& context, std::vector& extension parameterfImplementation = &AbstractTexture::parameterImplementationDefault; parameterfvImplementation = &AbstractTexture::parameterImplementationDefault; #ifndef MAGNUM_TARGET_GLES + parameterIuivImplementation = &AbstractTexture::parameterImplementationDefault; + parameterIivImplementation = &AbstractTexture::parameterImplementationDefault; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault; #endif mipmapImplementation = &AbstractTexture::mipmapImplementationDefault; diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index f6dec2d7c..f4ef89d69 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -41,6 +41,8 @@ struct TextureState { void(AbstractTexture::*parameteriImplementation)(GLenum, GLint); void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat); void(AbstractTexture::*parameterfvImplementation)(GLenum, const GLfloat*); + void(AbstractTexture::*parameterIuivImplementation)(GLenum, const GLuint*); + void(AbstractTexture::*parameterIivImplementation)(GLenum, const GLint*); void(AbstractTexture::*setMaxAnisotropyImplementation)(GLfloat); void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*); void(AbstractTexture::*mipmapImplementation)(); diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 034e44dd9..17a49372c 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -146,6 +146,20 @@ class RectangleTexture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setBorderColor(const Vector4ui&) */ + RectangleTexture& setBorderColor(const Vector4ui& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @copydoc Texture::setBorderColor(const Vector4i&) */ + RectangleTexture& setBorderColor(const Vector4i& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + #endif + /** @copydoc Texture::setMaxAnisotropy() */ RectangleTexture& setMaxAnisotropy(Float anisotropy) { AbstractTexture::setMaxAnisotropy(anisotropy); diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index e3da6a916..94e187714 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -40,26 +40,38 @@ class CubeMapTextureArrayGLTest: public AbstractOpenGLTester { explicit CubeMapTextureArrayGLTest(); void construct(); + void sampling(); + void samplingBorderInteger(); + void storage(); + void image(); void imageBuffer(); void subImage(); void subImageBuffer(); + void generateMipmap(); + void invalidateImage(); void invalidateSubImage(); }; CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() { addTests({&CubeMapTextureArrayGLTest::construct, + &CubeMapTextureArrayGLTest::sampling, + &CubeMapTextureArrayGLTest::samplingBorderInteger, + &CubeMapTextureArrayGLTest::storage, + &CubeMapTextureArrayGLTest::image, &CubeMapTextureArrayGLTest::imageBuffer, &CubeMapTextureArrayGLTest::subImage, &CubeMapTextureArrayGLTest::subImageBuffer, + &CubeMapTextureArrayGLTest::generateMipmap, + &CubeMapTextureArrayGLTest::invalidateImage, &CubeMapTextureArrayGLTest::invalidateSubImage}); } @@ -92,6 +104,20 @@ void CubeMapTextureArrayGLTest::sampling() { MAGNUM_VERIFY_NO_ERROR(); } +void CubeMapTextureArrayGLTest::samplingBorderInteger() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); + + CubeMapTextureArray a; + a.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4i(1, 56, 78, -2)); + CubeMapTextureArray b; + b.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4ui(35, 56, 78, 15)); + + MAGNUM_VERIFY_NO_ERROR(); +} + void CubeMapTextureArrayGLTest::storage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index 6e4d75a77..a66ca896e 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -43,34 +43,52 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester { explicit CubeMapTextureGLTest(); void construct(); + void sampling(); + #ifndef MAGNUM_TARGET_GLES + void samplingBorderInteger(); + #endif + void storage(); + void image(); #ifndef MAGNUM_TARGET_GLES2 void imageBuffer(); #endif + void subImage(); #ifndef MAGNUM_TARGET_GLES2 void subImageBuffer(); #endif + void generateMipmap(); + void invalidateImage(); void invalidateSubImage(); }; CubeMapTextureGLTest::CubeMapTextureGLTest() { addTests({&CubeMapTextureGLTest::construct, + &CubeMapTextureGLTest::sampling, + #ifndef MAGNUM_TARGET_GLES + &CubeMapTextureGLTest::samplingBorderInteger, + #endif + &CubeMapTextureGLTest::storage, + &CubeMapTextureGLTest::image, #ifndef MAGNUM_TARGET_GLES2 &CubeMapTextureGLTest::imageBuffer, #endif + &CubeMapTextureGLTest::subImage, #ifndef MAGNUM_TARGET_GLES2 &CubeMapTextureGLTest::subImageBuffer, #endif + &CubeMapTextureGLTest::generateMipmap, + &CubeMapTextureGLTest::invalidateImage, &CubeMapTextureGLTest::invalidateSubImage}); } @@ -97,6 +115,22 @@ void CubeMapTextureGLTest::sampling() { MAGNUM_VERIFY_NO_ERROR(); } +#ifndef MAGNUM_TARGET_GLES +void CubeMapTextureGLTest::samplingBorderInteger() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); + + CubeMapTexture a; + a.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4i(1, 56, 78, -2)); + CubeMapTexture b; + b.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4ui(35, 56, 78, 15)); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + void CubeMapTextureGLTest::storage() { CubeMapTexture texture; texture.setStorage(5, TextureFormat::RGBA8, Vector2i(32)); diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index e4ff02c4e..eedb2cdea 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -41,12 +41,14 @@ class TextureGLTest: public AbstractOpenGLTester { explicit TextureGLTest(); void construct(); + void sampling(); + void samplingBorderInteger(); + void storage(); void image(); void imageBuffer(); - void subImage(); void subImageBuffer(); @@ -56,7 +58,10 @@ class TextureGLTest: public AbstractOpenGLTester { TextureGLTest::TextureGLTest() { addTests({&TextureGLTest::construct, + &TextureGLTest::sampling, + &TextureGLTest::samplingBorderInteger, + &TextureGLTest::storage, &TextureGLTest::image, @@ -97,6 +102,20 @@ void TextureGLTest::sampling() { MAGNUM_VERIFY_NO_ERROR(); } +void TextureGLTest::samplingBorderInteger() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); + + RectangleTexture a; + a.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4i(1, 56, 78, -2)); + RectangleTexture b; + b.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4ui(35, 56, 78, 15)); + + MAGNUM_VERIFY_NO_ERROR(); +} + void TextureGLTest::storage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index 2c2eccfde..0a35c44c2 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -50,7 +50,10 @@ class TextureGLTest: public AbstractOpenGLTester { #endif void sampling2DArray(); - #ifdef MAGNUM_TARGET_GLES + #ifndef MAGNUM_TARGET_GLES + void samplingBorderInteger1DArray(); + void samplingBorderInteger2DArray(); + #else void samplingBorder2DArray(); #endif @@ -103,7 +106,10 @@ TextureGLTest::TextureGLTest() { #endif &TextureGLTest::sampling2DArray, - #ifdef MAGNUM_TARGET_GLES + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::samplingBorderInteger1DArray, + &TextureGLTest::samplingBorderInteger2DArray, + #else &TextureGLTest::samplingBorder2DArray, #endif @@ -189,6 +195,20 @@ void TextureGLTest::sampling1DArray() { MAGNUM_VERIFY_NO_ERROR(); } + +void TextureGLTest::samplingBorderInteger1DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); + + Texture1DArray a; + a.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4i(1, 56, 78, -2)); + Texture1DArray b; + b.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4ui(35, 56, 78, 15)); + + MAGNUM_VERIFY_NO_ERROR(); +} #endif void TextureGLTest::sampling2DArray() { @@ -211,7 +231,21 @@ void TextureGLTest::sampling2DArray() { MAGNUM_VERIFY_NO_ERROR(); } -#ifdef MAGNUM_TARGET_GLES +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::samplingBorderInteger2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); + + Texture2DArray a; + a.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4i(1, 56, 78, -2)); + Texture2DArray b; + b.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4ui(35, 56, 78, 15)); + + MAGNUM_VERIFY_NO_ERROR(); +} +#else void TextureGLTest::samplingBorder2DArray() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::NV::texture_border_clamp::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index 79a9368ae..e208c4f8d 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -54,7 +54,10 @@ class TextureGLTest: public AbstractOpenGLTester { void sampling2D(); void sampling3D(); - #ifdef MAGNUM_TARGET_GLES + #ifndef MAGNUM_TARGET_GLES + void samplingBorderInteger2D(); + void samplingBorderInteger3D(); + #else void samplingBorder2D(); void samplingBorder3D(); #endif @@ -126,7 +129,10 @@ TextureGLTest::TextureGLTest() { &TextureGLTest::sampling2D, &TextureGLTest::sampling3D, - #ifdef MAGNUM_TARGET_GLES + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::samplingBorderInteger2D, + &TextureGLTest::samplingBorderInteger3D, + #else &TextureGLTest::samplingBorder2D, &TextureGLTest::samplingBorder3D, #endif @@ -251,7 +257,21 @@ void TextureGLTest::sampling2D() { MAGNUM_VERIFY_NO_ERROR(); } -#ifdef MAGNUM_TARGET_GLES +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::samplingBorderInteger2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); + + Texture2D a; + a.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4i(1, 56, 78, -2)); + Texture2D b; + b.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4ui(35, 56, 78, 15)); + + MAGNUM_VERIFY_NO_ERROR(); +} +#else void TextureGLTest::samplingBorder2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::NV::texture_border_clamp::string() + std::string(" is not supported.")); @@ -284,7 +304,21 @@ void TextureGLTest::sampling3D() { MAGNUM_VERIFY_NO_ERROR(); } -#ifdef MAGNUM_TARGET_GLES +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::samplingBorderInteger3D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); + + Texture3D a; + a.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4i(1, 56, 78, -2)); + Texture3D b; + b.setWrapping(Sampler::Wrapping::ClampToBorder) + .setBorderColor(Vector4ui(35, 56, 78, 15)); + + MAGNUM_VERIFY_NO_ERROR(); +} +#else void TextureGLTest::samplingBorder3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current()->isExtensionSupported()) diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 6edcefa75..0f1ecf236 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -261,6 +261,34 @@ template class Texture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Set border color for integer texture + * @return Reference to self (for method chaining) + * + * Border color for integer textures when wrapping is set to + * @ref Sampler::Wrapping::ClampToBorder. If @extension{EXT,direct_state_access} + * is not available, the texture is bound to some texture unit before + * the operation. Initial value is `{0, 0, 0, 0}`. + * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} + * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} + * with @def_gl{TEXTURE_BORDER_COLOR} + * @requires_gl30 %Extension @extension{EXT,texture_integer} + * @requires_gl Border is available only for float textures in OpenGL + * ES. + */ + Texture& setBorderColor(const Vector4ui& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @overload */ + Texture& setBorderColor(const Vector4i& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + #endif + /** * @brief Set max anisotropy * @return Reference to self (for method chaining) diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 578fcb6a2..dcf983c14 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -131,6 +131,20 @@ template class TextureArray: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setBorderColor(const Vector4ui&) */ + TextureArray& setBorderColor(const Vector4ui& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + + /** @copydoc Texture::setBorderColor(const Vector4i&) */ + TextureArray& setBorderColor(const Vector4i& color) { + AbstractTexture::setBorderColor(color); + return *this; + } + #endif + /** @copydoc Texture::setMaxAnisotropy() */ TextureArray& setMaxAnisotropy(Float anisotropy) { AbstractTexture::setMaxAnisotropy(anisotropy); From de64c2e3e4f55b53c018690d71b7c1baeff982ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 12:29:17 +0100 Subject: [PATCH 110/141] Proper class/function names for *Texture GL tests. Another copypase bug. --- src/Magnum/Test/RectangleTextureGLTest.cpp | 48 +++---- src/Magnum/Test/TextureArrayGLTest.cpp | 146 ++++++++++----------- 2 files changed, 97 insertions(+), 97 deletions(-) diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index eedb2cdea..a4121ce06 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -36,9 +36,9 @@ namespace Magnum { namespace Test { -class TextureGLTest: public AbstractOpenGLTester { +class RectangleTextureGLTest: public AbstractOpenGLTester { public: - explicit TextureGLTest(); + explicit RectangleTextureGLTest(); void construct(); @@ -56,25 +56,25 @@ class TextureGLTest: public AbstractOpenGLTester { void invalidateSubImage(); }; -TextureGLTest::TextureGLTest() { - addTests({&TextureGLTest::construct, +RectangleTextureGLTest::RectangleTextureGLTest() { + addTests({&RectangleTextureGLTest::construct, - &TextureGLTest::sampling, - &TextureGLTest::samplingBorderInteger, + &RectangleTextureGLTest::sampling, + &RectangleTextureGLTest::samplingBorderInteger, - &TextureGLTest::storage, + &RectangleTextureGLTest::storage, - &TextureGLTest::image, - &TextureGLTest::imageBuffer, + &RectangleTextureGLTest::image, + &RectangleTextureGLTest::imageBuffer, - &TextureGLTest::subImage, - &TextureGLTest::subImageBuffer, + &RectangleTextureGLTest::subImage, + &RectangleTextureGLTest::subImageBuffer, - &TextureGLTest::invalidateImage, - &TextureGLTest::invalidateSubImage}); + &RectangleTextureGLTest::invalidateImage, + &RectangleTextureGLTest::invalidateSubImage}); } -void TextureGLTest::construct() { +void RectangleTextureGLTest::construct() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -88,7 +88,7 @@ void TextureGLTest::construct() { MAGNUM_VERIFY_NO_ERROR(); } -void TextureGLTest::sampling() { +void RectangleTextureGLTest::sampling() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -102,7 +102,7 @@ void TextureGLTest::sampling() { MAGNUM_VERIFY_NO_ERROR(); } -void TextureGLTest::samplingBorderInteger() { +void RectangleTextureGLTest::samplingBorderInteger() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); @@ -116,7 +116,7 @@ void TextureGLTest::samplingBorderInteger() { MAGNUM_VERIFY_NO_ERROR(); } -void TextureGLTest::storage() { +void RectangleTextureGLTest::storage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -130,7 +130,7 @@ void TextureGLTest::storage() { MAGNUM_VERIFY_NO_ERROR(); } -void TextureGLTest::image() { +void RectangleTextureGLTest::image() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -154,7 +154,7 @@ void TextureGLTest::image() { std::vector(data, data + 16), TestSuite::Compare::Container); } -void TextureGLTest::imageBuffer() { +void RectangleTextureGLTest::imageBuffer() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -179,7 +179,7 @@ void TextureGLTest::imageBuffer() { std::vector(data, data+16), TestSuite::Compare::Container); } -void TextureGLTest::subImage() { +void RectangleTextureGLTest::subImage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -210,7 +210,7 @@ void TextureGLTest::subImage() { }), TestSuite::Compare::Container); } -void TextureGLTest::subImageBuffer() { +void RectangleTextureGLTest::subImageBuffer() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -242,7 +242,7 @@ void TextureGLTest::subImageBuffer() { }), TestSuite::Compare::Container); } -void TextureGLTest::invalidateImage() { +void RectangleTextureGLTest::invalidateImage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -253,7 +253,7 @@ void TextureGLTest::invalidateImage() { MAGNUM_VERIFY_NO_ERROR(); } -void TextureGLTest::invalidateSubImage() { +void RectangleTextureGLTest::invalidateSubImage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); @@ -266,4 +266,4 @@ void TextureGLTest::invalidateSubImage() { }} -CORRADE_TEST_MAIN(Magnum::Test::TextureGLTest) +CORRADE_TEST_MAIN(Magnum::Test::RectangleTextureGLTest) diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index 0a35c44c2..f0a81fbd3 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -36,121 +36,121 @@ namespace Magnum { namespace Test { -class TextureGLTest: public AbstractOpenGLTester { +class TextureArrayGLTest: public AbstractOpenGLTester { public: - explicit TextureGLTest(); + explicit TextureArrayGLTest(); #ifndef MAGNUM_TARGET_GLES - void construct1DArray(); + void construct1D(); #endif - void construct2DArray(); + void construct2D(); #ifndef MAGNUM_TARGET_GLES - void sampling1DArray(); + void sampling1D(); #endif - void sampling2DArray(); + void sampling2D(); #ifndef MAGNUM_TARGET_GLES - void samplingBorderInteger1DArray(); - void samplingBorderInteger2DArray(); + void samplingBorderInteger1D(); + void samplingBorderInteger2D(); #else - void samplingBorder2DArray(); + void samplingBorder2D(); #endif #ifndef MAGNUM_TARGET_GLES - void storage1DArray(); + void storage1D(); #endif - void storage2DArray(); + void storage2D(); #ifndef MAGNUM_TARGET_GLES - void image1DArray(); - void image1DArrayBuffer(); + void image1D(); + void image1DBuffer(); #endif #ifndef MAGNUM_TARGET_GLES2 - void image2DArray(); - void image2DArrayBuffer(); + void image2D(); + void image2DBuffer(); #endif #ifndef MAGNUM_TARGET_GLES - void subImage1DArray(); - void subImage1DArrayBuffer(); + void subImage1D(); + void subImage1DBuffer(); #endif - void subImage2DArray(); - void subImage2DArrayBuffer(); + void subImage2D(); + void subImage2DBuffer(); #ifndef MAGNUM_TARGET_GLES - void generateMipmap1DArray(); + void generateMipmap1D(); #endif - void generateMipmap2DArray(); + void generateMipmap2D(); #ifndef MAGNUM_TARGET_GLES - void invalidateImage1DArray(); + void invalidateImage1D(); #endif - void invalidateImage2DArray(); + void invalidateImage2D(); #ifndef MAGNUM_TARGET_GLES - void invalidateSubImage1DArray(); + void invalidateSubImage1D(); #endif - void invalidateSubImage2DArray(); + void invalidateSubImage2D(); }; -TextureGLTest::TextureGLTest() { +TextureArrayGLTest::TextureArrayGLTest() { addTests({ #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::construct1DArray, + &TextureArrayGLTest::construct1D, #endif - &TextureGLTest::construct2DArray, + &TextureArrayGLTest::construct2D, #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::sampling1DArray, + &TextureArrayGLTest::sampling1D, #endif - &TextureGLTest::sampling2DArray, + &TextureArrayGLTest::sampling2D, #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::samplingBorderInteger1DArray, - &TextureGLTest::samplingBorderInteger2DArray, + &TextureArrayGLTest::samplingBorderInteger1D, + &TextureArrayGLTest::samplingBorderInteger2D, #else - &TextureGLTest::samplingBorder2DArray, + &TextureArrayGLTest::samplingBorder2D, #endif #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::storage1DArray, + &TextureArrayGLTest::storage1D, #endif - &TextureGLTest::storage2DArray, + &TextureArrayGLTest::storage2D, #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::image1DArray, - &TextureGLTest::image1DArrayBuffer, + &TextureArrayGLTest::image1D, + &TextureArrayGLTest::image1DBuffer, #endif - &TextureGLTest::image2DArray, - &TextureGLTest::image2DArrayBuffer, + &TextureArrayGLTest::image2D, + &TextureArrayGLTest::image2DBuffer, #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::subImage1DArray, - &TextureGLTest::subImage1DArrayBuffer, + &TextureArrayGLTest::subImage1D, + &TextureArrayGLTest::subImage1DBuffer, #endif - &TextureGLTest::subImage2DArray, - &TextureGLTest::subImage2DArrayBuffer, + &TextureArrayGLTest::subImage2D, + &TextureArrayGLTest::subImage2DBuffer, #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::generateMipmap1DArray, + &TextureArrayGLTest::generateMipmap1D, #endif - &TextureGLTest::generateMipmap2DArray, + &TextureArrayGLTest::generateMipmap2D, #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::invalidateImage1DArray, + &TextureArrayGLTest::invalidateImage1D, #endif - &TextureGLTest::invalidateImage2DArray, + &TextureArrayGLTest::invalidateImage2D, #ifndef MAGNUM_TARGET_GLES - &TextureGLTest::invalidateSubImage1DArray, + &TextureArrayGLTest::invalidateSubImage1D, #endif - &TextureGLTest::invalidateSubImage2DArray + &TextureArrayGLTest::invalidateSubImage2D }); } #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::construct1DArray() { +void TextureArrayGLTest::construct1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -165,7 +165,7 @@ void TextureGLTest::construct1DArray() { } #endif -void TextureGLTest::construct2DArray() { +void TextureArrayGLTest::construct2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -182,7 +182,7 @@ void TextureGLTest::construct2DArray() { } #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::sampling1DArray() { +void TextureArrayGLTest::sampling1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -196,7 +196,7 @@ void TextureGLTest::sampling1DArray() { MAGNUM_VERIFY_NO_ERROR(); } -void TextureGLTest::samplingBorderInteger1DArray() { +void TextureArrayGLTest::samplingBorderInteger1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); @@ -211,7 +211,7 @@ void TextureGLTest::samplingBorderInteger1DArray() { } #endif -void TextureGLTest::sampling2DArray() { +void TextureArrayGLTest::sampling2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -232,7 +232,7 @@ void TextureGLTest::sampling2DArray() { } #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::samplingBorderInteger2DArray() { +void TextureArrayGLTest::samplingBorderInteger2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); @@ -246,7 +246,7 @@ void TextureGLTest::samplingBorderInteger2DArray() { MAGNUM_VERIFY_NO_ERROR(); } #else -void TextureGLTest::samplingBorder2DArray() { +void TextureArrayGLTest::samplingBorder2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::NV::texture_border_clamp::string() + std::string(" is not supported.")); @@ -259,7 +259,7 @@ void TextureGLTest::samplingBorder2DArray() { #endif #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::storage1DArray() { +void TextureArrayGLTest::storage1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -279,7 +279,7 @@ void TextureGLTest::storage1DArray() { } #endif -void TextureGLTest::storage2DArray() { +void TextureArrayGLTest::storage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -304,7 +304,7 @@ void TextureGLTest::storage2DArray() { } #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::image1DArray() { +void TextureArrayGLTest::image1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -328,7 +328,7 @@ void TextureGLTest::image1DArray() { std::vector(data, data + 16), TestSuite::Compare::Container); } -void TextureGLTest::image1DArrayBuffer() { +void TextureArrayGLTest::image1DBuffer() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -354,7 +354,7 @@ void TextureGLTest::image1DArrayBuffer() { } #endif -void TextureGLTest::image2DArray() { +void TextureArrayGLTest::image2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -387,7 +387,7 @@ void TextureGLTest::image2DArray() { #endif } -void TextureGLTest::image2DArrayBuffer() { +void TextureArrayGLTest::image2DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -422,7 +422,7 @@ void TextureGLTest::image2DArrayBuffer() { } #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::subImage1DArray() { +void TextureArrayGLTest::subImage1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -453,7 +453,7 @@ void TextureGLTest::subImage1DArray() { }), TestSuite::Compare::Container); } -void TextureGLTest::subImage1DArrayBuffer() { +void TextureArrayGLTest::subImage1DBuffer() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -486,7 +486,7 @@ void TextureGLTest::subImage1DArrayBuffer() { } #endif -void TextureGLTest::subImage2DArray() { +void TextureArrayGLTest::subImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -541,7 +541,7 @@ void TextureGLTest::subImage2DArray() { #endif } -void TextureGLTest::subImage2DArrayBuffer() { +void TextureArrayGLTest::subImage2DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -598,7 +598,7 @@ void TextureGLTest::subImage2DArrayBuffer() { } #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::generateMipmap1DArray() { +void TextureArrayGLTest::generateMipmap1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not supported.")); if(!Context::current()->isExtensionSupported()) @@ -626,7 +626,7 @@ void TextureGLTest::generateMipmap1DArray() { } #endif -void TextureGLTest::generateMipmap2DArray() { +void TextureArrayGLTest::generateMipmap2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::framebuffer_object::string() + std::string(" is not supported.")); @@ -661,7 +661,7 @@ void TextureGLTest::generateMipmap2DArray() { } #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::invalidateImage1DArray() { +void TextureArrayGLTest::invalidateImage1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -673,7 +673,7 @@ void TextureGLTest::invalidateImage1DArray() { } #endif -void TextureGLTest::invalidateImage2DArray() { +void TextureArrayGLTest::invalidateImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -687,7 +687,7 @@ void TextureGLTest::invalidateImage2DArray() { } #ifndef MAGNUM_TARGET_GLES -void TextureGLTest::invalidateSubImage1DArray() { +void TextureArrayGLTest::invalidateSubImage1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -699,7 +699,7 @@ void TextureGLTest::invalidateSubImage1DArray() { } #endif -void TextureGLTest::invalidateSubImage2DArray() { +void TextureArrayGLTest::invalidateSubImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); @@ -714,4 +714,4 @@ void TextureGLTest::invalidateSubImage2DArray() { }} -CORRADE_TEST_MAIN(Magnum::Test::TextureGLTest) +CORRADE_TEST_MAIN(Magnum::Test::TextureArrayGLTest) From 8590d351b1e146e6f60d2e3140cf8f3b8841e9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 12:30:01 +0100 Subject: [PATCH 111/141] Doc++ --- src/Magnum/AbstractShaderProgram.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 27dd44cc4..40dbe55fe 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -103,8 +103,8 @@ MyShader& setNormalMatrix(const Matrix3x3& matrix) { } @endcode - %Texture setting functions in which you bind the textures - to particular texture units using @ref *Texture::bind() and equivalents, - for example: + to particular texture units using @ref Texture::bind() "*Texture::bind()" + and equivalents, for example: @code MyShader& setDiffuseTexture(Texture2D& texture) { texture.bind(0); From a24ea3ce25e108ef6d2c42771d08af10652bb66f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 15:49:28 +0100 Subject: [PATCH 112/141] Ability to set base and max mip level on textures. Curiously this functionality is not available on ES2, just the max limit is supported by APPLE_texture_max_level extension. --- doc/opengl-support.dox | 1 + src/Magnum/AbstractTexture.cpp | 16 +++++ src/Magnum/AbstractTexture.h | 4 ++ src/Magnum/Context.cpp | 1 + src/Magnum/CubeMapTexture.h | 14 +++++ src/Magnum/CubeMapTextureArray.h | 14 +++++ src/Magnum/Extensions.h | 3 + src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 2 + src/Magnum/Test/CubeMapTextureGLTest.cpp | 22 +++++++ src/Magnum/Test/TextureArrayGLTest.cpp | 26 ++++++++ src/Magnum/Test/TextureGLTest.cpp | 46 ++++++++++++++ src/Magnum/Texture.h | 62 ++++++++++++++++--- src/Magnum/TextureArray.h | 21 +++++-- 13 files changed, 218 insertions(+), 14 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index ed585c8ab..96444d692 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -245,6 +245,7 @@ supported. @es_extension{ANGLE,framebuffer_multisample} | done @es_extension{ANGLE,depth_texture} | done @es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset) +@es_extension{APPLE,texture_max_level} | done @es_extension{ARM,rgba8} | done @es_extension{EXT,texture_type_2_10_10_10_REV} | done @es_extension{EXT,discard_framebuffer} | done diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 427f90140..5766ae09f 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -146,6 +146,22 @@ void AbstractTexture::bindImplementationDSA(GLint textureUnit) { } #endif +#ifndef MAGNUM_TARGET_GLES2 +void AbstractTexture::setBaseLevel(Int level) { + (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_BASE_LEVEL, level); +} +#endif + +void AbstractTexture::setMaxLevel(Int level) { + (this->*Context::current()->state().texture->parameteriImplementation)( + #ifndef MAGNUM_TARGET_GLES2 + GL_TEXTURE_MAX_LEVEL + #else + GL_TEXTURE_MAX_LEVEL_APPLE + #endif + , level); +} + void AbstractTexture::setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap) { (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap)); } diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index d0ab656f1..6b57cace1 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -242,6 +242,10 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { /* Unlike bind() this also sets the texture binding unit as active */ void MAGNUM_LOCAL bindInternal(); + #ifndef MAGNUM_TARGET_GLES2 + void setBaseLevel(Int level); + #endif + void setMaxLevel(Int level); void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap); void setMagnificationFilter(Sampler::Filter filter); void setBorderColor(const Color4& color); diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 5f28b479f..2c5e16127 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -214,6 +214,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,ANGLE,framebuffer_multisample), _extension(GL,ANGLE,depth_texture), _extension(GL,APPLE,framebuffer_multisample), + _extension(GL,APPLE,texture_max_level), _extension(GL,ARM,rgba8), _extension(GL,EXT,texture_type_2_10_10_10_REV), _extension(GL,EXT,discard_framebuffer), diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index d750fd99d..53948a598 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -98,6 +98,20 @@ class CubeMapTexture: public AbstractTexture { */ explicit CubeMapTexture(): AbstractTexture(GL_TEXTURE_CUBE_MAP) {} + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc Texture::setBaseLevel() */ + CubeMapTexture& setBaseLevel(Int level) { + AbstractTexture::setBaseLevel(level); + return *this; + } + #endif + + /** @copydoc Texture::setMaxLevel() */ + CubeMapTexture& setMaxLevel(Int level) { + AbstractTexture::setMaxLevel(level); + return *this; + } + /** @copydoc Texture::setMinificationFilter() */ CubeMapTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { AbstractTexture::setMinificationFilter(filter, mipmap); diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 5ec43b656..a6c09f16a 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -89,6 +89,20 @@ class CubeMapTextureArray: public AbstractTexture { */ explicit CubeMapTextureArray(): AbstractTexture(GL_TEXTURE_CUBE_MAP_ARRAY) {} + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc Texture::setBaseLevel() */ + CubeMapTextureArray& setBaseLevel(Int level) { + AbstractTexture::setBaseLevel(level); + return *this; + } + #endif + + /** @copydoc Texture::setMaxLevel() */ + CubeMapTextureArray& setMaxLevel(Int level) { + AbstractTexture::setMaxLevel(level); + return *this; + } + /** @copydoc Texture::setMinificationFilter() */ CubeMapTextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { AbstractTexture::setMinificationFilter(filter, mipmap); diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index 841d5710c..e2f07f16d 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -212,6 +212,9 @@ namespace GL { _extension(GL,APPLE,framebuffer_multisample, GLES200, GLES300) // #78 #endif _extension(GL,APPLE,texture_format_BGRA8888, GLES200, None) // #79 + #ifdef MAGNUM_TARGET_GLES2 + _extension(GL,APPLE,texture_max_level, GLES200, None) // #80 + #endif } namespace ARM { #ifdef MAGNUM_TARGET_GLES2 _extension(GL,ARM,rgba8, GLES200, GLES300) // #82 diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 94e187714..1d7e69a43 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -97,6 +97,8 @@ void CubeMapTextureArrayGLTest::sampling() { CubeMapTextureArray texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + .setBaseLevel(1) + .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index a66ca896e..ede16a7f2 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -45,6 +45,9 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester { void construct(); void sampling(); + #ifdef MAGNUM_TARGET_GLES2 + void samplingMaxLevel(); + #endif #ifndef MAGNUM_TARGET_GLES void samplingBorderInteger(); #endif @@ -71,6 +74,9 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { addTests({&CubeMapTextureGLTest::construct, &CubeMapTextureGLTest::sampling, + #ifdef MAGNUM_TARGET_GLES2 + &CubeMapTextureGLTest::samplingMaxLevel, + #endif #ifndef MAGNUM_TARGET_GLES &CubeMapTextureGLTest::samplingBorderInteger, #endif @@ -108,6 +114,10 @@ void CubeMapTextureGLTest::sampling() { CubeMapTexture texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + #ifndef MAGNUM_TARGET_GLES2 + .setBaseLevel(1) + .setMaxLevel(750) + #endif .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); @@ -115,6 +125,18 @@ void CubeMapTextureGLTest::sampling() { MAGNUM_VERIFY_NO_ERROR(); } +#ifdef MAGNUM_TARGET_GLES2 +void CubeMapTextureGLTest::samplingMaxLevel() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); + + CubeMapTexture texture; + texture.setMaxLevel(750); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + #ifndef MAGNUM_TARGET_GLES void CubeMapTextureGLTest::samplingBorderInteger() { if(!Context::current()->isExtensionSupported()) diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index f0a81fbd3..2817bde22 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -50,6 +50,10 @@ class TextureArrayGLTest: public AbstractOpenGLTester { #endif void sampling2D(); + #ifdef MAGNUM_TARGET_GLES2 + void samplingMaxLevel2D(); + #endif + #ifndef MAGNUM_TARGET_GLES void samplingBorderInteger1D(); void samplingBorderInteger2D(); @@ -106,6 +110,10 @@ TextureArrayGLTest::TextureArrayGLTest() { #endif &TextureArrayGLTest::sampling2D, + #ifdef MAGNUM_TARGET_GLES2 + &TextureArrayGLTest::samplingMaxLevel2D, + #endif + #ifndef MAGNUM_TARGET_GLES &TextureArrayGLTest::samplingBorderInteger1D, &TextureArrayGLTest::samplingBorderInteger2D, @@ -189,6 +197,8 @@ void TextureArrayGLTest::sampling1D() { Texture1DArray texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + .setBaseLevel(1) + .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); @@ -220,6 +230,10 @@ void TextureArrayGLTest::sampling2D() { Texture2DArray texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + #ifndef MAGNUM_TARGET_GLES2 + .setBaseLevel(1) + .setMaxLevel(750) + #endif #ifndef MAGNUM_TARGET_GLES .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) @@ -231,6 +245,18 @@ void TextureArrayGLTest::sampling2D() { MAGNUM_VERIFY_NO_ERROR(); } +#ifdef MAGNUM_TARGET_GLES2 +void TextureArrayGLTest::samplingMaxLevel2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); + + Texture2DArray texture; + texture.setMaxLevel(750); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::samplingBorderInteger2D() { if(!Context::current()->isExtensionSupported()) diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index e208c4f8d..2f5a0f2ce 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -54,6 +54,11 @@ class TextureGLTest: public AbstractOpenGLTester { void sampling2D(); void sampling3D(); + #ifdef MAGNUM_TARGET_GLES2 + void samplingMaxLevel2D(); + void samplingMaxLevel3D(); + #endif + #ifndef MAGNUM_TARGET_GLES void samplingBorderInteger2D(); void samplingBorderInteger3D(); @@ -129,6 +134,11 @@ TextureGLTest::TextureGLTest() { &TextureGLTest::sampling2D, &TextureGLTest::sampling3D, + #ifdef MAGNUM_TARGET_GLES2 + &TextureGLTest::samplingMaxLevel2D, + &TextureGLTest::samplingMaxLevel3D, + #endif + #ifndef MAGNUM_TARGET_GLES &TextureGLTest::samplingBorderInteger2D, &TextureGLTest::samplingBorderInteger3D, @@ -234,6 +244,8 @@ void TextureGLTest::sampling1D() { Texture1D texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + .setBaseLevel(1) + .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); @@ -246,6 +258,10 @@ void TextureGLTest::sampling2D() { Texture2D texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + #ifndef MAGNUM_TARGET_GLES2 + .setBaseLevel(1) + .setMaxLevel(750) + #endif #ifndef MAGNUM_TARGET_GLES .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) @@ -257,6 +273,18 @@ void TextureGLTest::sampling2D() { MAGNUM_VERIFY_NO_ERROR(); } +#ifdef MAGNUM_TARGET_GLES2 +void TextureGLTest::samplingMaxLevel2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); + + Texture2D texture; + texture.setMaxLevel(750); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + #ifndef MAGNUM_TARGET_GLES void TextureGLTest::samplingBorderInteger2D() { if(!Context::current()->isExtensionSupported()) @@ -293,6 +321,10 @@ void TextureGLTest::sampling3D() { Texture3D texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + #ifndef MAGNUM_TARGET_GLES2 + .setBaseLevel(1) + .setMaxLevel(750) + #endif #ifndef MAGNUM_TARGET_GLES .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) @@ -304,6 +336,20 @@ void TextureGLTest::sampling3D() { MAGNUM_VERIFY_NO_ERROR(); } +#ifdef MAGNUM_TARGET_GLES2 +void TextureGLTest::samplingMaxLevel3D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::OES::texture_3D::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); + + Texture3D texture; + texture.setMaxLevel(750); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + #ifndef MAGNUM_TARGET_GLES void TextureGLTest::samplingBorderInteger3D() { if(!Context::current()->isExtensionSupported()) diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 0f1ecf236..2295f480e 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -77,10 +77,12 @@ texture.setMagnificationFilter(Sampler::Filter::Linear) .generateMipmap(); @endcode -@attention Note that default configuration (if @ref setMinificationFilter() is - not called with another value) is to use mipmaps, so be sure to either call - @ref setMinificationFilter(), explicitly specify all mip levels with - @ref setStorage() and @ref setImage() or call @ref generateMipmap(). +@attention Note that default configuration is to use mipmaps. Be sure to either + reduce mip level count using @ref setBaseLevel() and @ref setMaxLevel(), + explicitly allocate all mip levels using @ref setStorage(), call + @ref generateMipmap() after uploading the base level to generate the rest + of the mip chain or call @ref setMinificationFilter() with another value to + disable mipmapping. In shader, the texture is used via `sampler1D`/`sampler2D`/`sampler3D`, `sampler1DShadow`/`sampler2DShadow`/`sampler3DShadow`, @@ -184,6 +186,47 @@ template class Texture: public AbstractTexture { } #endif + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Set base mip level + * @return Reference to self (for method chaining) + * + * Taken into account when generating mipmap using @ref generateMipmap() + * and when considering texture completeness when using mipmap + * filtering. Initial value is `0`. + * @see @ref setMaxLevel(), @ref setMinificationFilter(), + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} + * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} + * with @def_gl{TEXTURE_BASE_LEVEL} + * @requires_gles30 Base level is always `0` in OpenGL ES 2.0. + */ + Texture& setBaseLevel(Int level) { + AbstractTexture::setBaseLevel(level); + return *this; + } + #endif + + /** + * @brief Set max mip level + * @return Reference to self (for method chaining) + * + * Taken into account when generating mipmap using @ref generateMipmap() + * and when considering texture completeness when using mipmap + * filtering. Initial value is `1000`, which is clamped to count of + * levels specified when using @ref setStorage(). + * @see @ref setBaseLevel(), @ref setMinificationFilter(), + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} + * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} + * with @def_gl{TEXTURE_MAX_LEVEL} + * @requires_gles30 %Extension @es_extension{APPLE,texture_max_level}, + * otherwise the max level is always set to largest possible value + * in OpenGL ES 2.0. + */ + Texture& setMaxLevel(Int level) { + AbstractTexture::setMaxLevel(level); + return *this; + } + /** * @brief Set minification filter * @param filter Filter @@ -197,9 +240,10 @@ template class Texture: public AbstractTexture { * available, the texture is bound to some texture unit before the * operation. Initial value is {@ref Sampler::Filter::Nearest, * @ref Sampler::Mipmap::Linear}. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_MIN_FILTER} + * @see @ref setBaseLevel(), @ref setMaxLevel(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_MIN_FILTER} */ Texture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { AbstractTexture::setMinificationFilter(filter, mipmap); @@ -330,8 +374,8 @@ template class Texture: public AbstractTexture { * calls. * @todo allow the user to specify ColorType explicitly to avoid * issues in WebGL (see setSubImage()) - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and - * @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} + * @see @ref setMaxLevel(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} + * and @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} * or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/ * @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureStorage3D,EXT,direct_state_access}, diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index dcf983c14..064c08cf8 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -55,6 +55,8 @@ Template class for one- and two-dimensional texture arrays. See also @section Texture-usage Usage +See @ref Texture documentation for introduction. + Common usage is to fully configure all texture parameters and then set the data. Example configuration: @code @@ -77,11 +79,6 @@ for(std::size_t i = 0; i != 16; ++i) { } @endcode -@attention Note that default configuration (if @ref setMinificationFilter() is - not called with another value) is to use mipmaps, so be sure to either call - @ref setMinificationFilter(), explicitly specify all mip levels with - @ref setStorage() and @ref setImage() or call @ref generateMipmap(). - In shader, the texture is used via `sampler1DArray`/`sampler2DArray`, `sampler1DArrayShadow`/`sampler1DArrayShadow`, `isampler1DArray`/`isampler2DArray` or `usampler1DArray`/`usampler2DArray`. See @ref AbstractShaderProgram @@ -107,6 +104,20 @@ template class TextureArray: public AbstractTexture { */ explicit TextureArray(): AbstractTexture(Implementation::textureArrayTarget()) {} + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc Texture::setBaseLevel() */ + TextureArray& setBaseLevel(Int level) { + AbstractTexture::setBaseLevel(level); + return *this; + } + #endif + + /** @copydoc Texture::setMaxLevel() */ + TextureArray& setMaxLevel(Int level) { + AbstractTexture::setMaxLevel(level); + return *this; + } + /** @copydoc Texture::setMinificationFilter() */ TextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { AbstractTexture::setMinificationFilter(filter, mipmap); From dfb051b74aa5b0c2ee249e4eb12bd92950f4ffdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 16:31:03 +0100 Subject: [PATCH 113/141] Removed long-deprecated Magnum/Swizzle.h header and Magnum::swizzle(). Use Math/Swizzle.h and Math::swizzle() instead. --- src/Magnum/CMakeLists.txt | 3 +-- src/Magnum/Swizzle.h | 56 --------------------------------------- 2 files changed, 1 insertion(+), 58 deletions(-) delete mode 100644 src/Magnum/Swizzle.h diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 304705c65..43be45b68 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -131,8 +131,7 @@ set(Magnum_HEADERS if(BUILD_DEPRECATED) set(Magnum_HEADERS ${Magnum_HEADERS} DebugMarker.h - ImageFormat.h - Swizzle.h) + ImageFormat.h) endif() # Desktop-only headers and libraries diff --git a/src/Magnum/Swizzle.h b/src/Magnum/Swizzle.h deleted file mode 100644 index 74ba3ab3a..000000000 --- a/src/Magnum/Swizzle.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef Magnum_Swizzle_h -#define Magnum_Swizzle_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. -*/ - -#ifdef MAGNUM_BUILD_DEPRECATED -/** @file - * @brief Function @ref Magnum::swizzle() - * @deprecated Use @ref Math/Swizzle.h instead. - */ -#endif - -#include "Magnum/Math/Swizzle.h" -#include "Magnum/Color.h" - -#ifdef MAGNUM_BUILD_DEPRECATED -namespace Magnum { - -/** -@copybrief Math::swizzle() -@deprecated Use @ref Magnum::Math::swizzle() "Math::swizzle()" instead. -*/ -#ifdef DOXYGEN_GENERATING_OUTPUT -template constexpr CORRADE_DEPRECATED("use Math::swizzle() instead") typename Math::Implementation::TypeForSize::Type swizzle(const T& vector); -#else -using Math::swizzle; -#endif - -} -#else -#error this header is available only on deprecated build -#endif - -#endif From 99086a367520b6c14b0c43f4959c24b7c8daa9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 16:33:02 +0100 Subject: [PATCH 114/141] Removed long-deprecated ImageFormat.h header, ImageFormat/ImageType enums. Use ColorFormat.h header, ColorFormat and ColorType enums instead. Amazingly enough there was a bug in Magnum.h (ColorType was typedef'd to itself instead of ImageType). --- src/Magnum/CMakeLists.txt | 3 +-- src/Magnum/ImageFormat.h | 57 --------------------------------------- src/Magnum/Magnum.h | 3 --- 3 files changed, 1 insertion(+), 62 deletions(-) delete mode 100644 src/Magnum/ImageFormat.h diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 43be45b68..72503b047 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -130,8 +130,7 @@ set(Magnum_HEADERS # Deprecated headers if(BUILD_DEPRECATED) set(Magnum_HEADERS ${Magnum_HEADERS} - DebugMarker.h - ImageFormat.h) + DebugMarker.h) endif() # Desktop-only headers and libraries diff --git a/src/Magnum/ImageFormat.h b/src/Magnum/ImageFormat.h deleted file mode 100644 index d91f9280c..000000000 --- a/src/Magnum/ImageFormat.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef Magnum_ImageFormat_h -#define Magnum_ImageFormat_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. -*/ - -#ifdef MAGNUM_BUILD_DEPRECATED -/** @file - * @brief Enum @ref Magnum::ImageFormat, @ref Magnum::ImageType - * @deprecated Use @ref ColorFormat.h instead. - */ -#endif - -#include "Magnum/ColorFormat.h" - -#ifdef MAGNUM_BUILD_DEPRECATED -namespace Magnum { - -/** -@copybrief ColorFormat -@deprecated Use @ref Magnum::ColorFormat "ColorFormat" instead. -*/ -typedef CORRADE_DEPRECATED("use ColorFormat instead") ColorFormat ImageFormat; - -/** -@copybrief ColorType -@deprecated Use @ref Magnum::ColorType "ColorType" instead. -*/ -typedef CORRADE_DEPRECATED("use ColorType instead") ColorType ImageType; - -} -#else -#error this header is available only on deprecated build -#endif - -#endif diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 3da95c146..f26c9ec39 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -579,9 +579,6 @@ typedef BasicColor4 Color4ub; enum class ColorFormat: GLenum; enum class ColorType: GLenum; -/** @todo Remove this when dropping backward compatibility */ -typedef ColorFormat ImageFormat; -typedef ColorType ColorType; class Context; From dc2c13c9d230bf9e118331cc1d362526d48294c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 16:34:45 +0100 Subject: [PATCH 115/141] Removed long-deprecated Matrix2 and Matrix2d typedefs. Use Matrix2x2 and Matrix2x2d instead. --- src/Magnum/Magnum.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index f26c9ec39..9c676f40e 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -234,14 +234,6 @@ typedef Math::Matrix2x2 Matrix2x2; typedef Math::Matrix<2, Float> Matrix2x2; #endif -#ifdef MAGNUM_BUILD_DEPRECATED -/** -@copybrief Matrix2x2 -@deprecated Use @ref Magnum::Matrix2x2 "Matrix2x2" instead. -*/ -typedef Math::Matrix<2, Float> Matrix2; -#endif - /** @brief 3x3 float matrix @@ -411,14 +403,6 @@ typedef Math::Matrix2x2 Matrix2x2d; typedef Math::Matrix<2, Double> Matrix2x2d; #endif -#ifdef MAGNUM_BUILD_DEPRECATED -/** -@copybrief Matrix2x2d -@deprecated Use @ref Magnum::Matrix2x2d "Matrix2x2d" instead. -*/ -typedef CORRADE_DEPRECATED("use Matrix2x2d instead") Math::Matrix<2, Double> Matrix2d; -#endif - /** @brief 3x3 double matrix From 49e0aa3dc48f2588bf9bf07b7af47433fb252404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 16:39:09 +0100 Subject: [PATCH 116/141] Removed long-deprecated Buffer::set*Data() raw pointer overloads. Use overloads taking Containers::ArrayReference instead. --- src/Magnum/Buffer.h | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/Magnum/Buffer.h b/src/Magnum/Buffer.h index bbd3d01a6..5d009b0ef 100644 --- a/src/Magnum/Buffer.h +++ b/src/Magnum/Buffer.h @@ -678,17 +678,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { */ Buffer& setData(Containers::ArrayReference data, BufferUsage usage); - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief setData(Containers::ArrayReference, BufferUsage) - * @deprecated Use @ref Magnum::Buffer::setData(Containers::ArrayReference, BufferUsage) "setData(Containers::ArrayReference, BufferUsage)" - * instead. - */ - CORRADE_DEPRECATED("use setData(Containers::ArrayReference, BufferUsage) instead") Buffer& setData(GLsizeiptr size, const GLvoid* data, BufferUsage usage) { - return setData({data, std::size_t(size)}, usage); - } - #endif - /** @overload */ template Buffer& setData(const std::vector& data, BufferUsage usage) { setData({data.data(), data.size()}, usage); @@ -715,17 +704,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject { */ Buffer& setSubData(GLintptr offset, Containers::ArrayReference data); - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief setSubData(GLintptr, Containers::ArrayReference) - * @deprecated Use @ref Magnum::Buffer::setSubData(GLintptr, Containers::ArrayReference) "setSubData(GLintptr, Containers::ArrayReference)" - * instead. - */ - CORRADE_DEPRECATED("use setSubData(GLintptr, Containers::ArrayReference) instead") Buffer& setSubData(GLintptr offset, GLsizeiptr size, const GLvoid* data) { - return setSubData(offset, {data, std::size_t(size)}); - } - #endif - /** @overload */ template Buffer& setSubData(GLintptr offset, const std::vector& data) { setSubData(offset, {data.data(), data.size()}); From 14a6b85612dacb15954c74e0ce8755d09aeaf3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 16:40:00 +0100 Subject: [PATCH 117/141] Platform: removed long-deprecated InputEvent::Modifier::*Button values. Use *Event::buttons() and *Event::Button enum instead. --- src/Magnum/Platform/AbstractXApplication.h | 27 ---------------------- src/Magnum/Platform/NaClApplication.h | 27 ---------------------- 2 files changed, 54 deletions(-) diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index 73f7c6faf..00eee6066 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -263,33 +263,6 @@ class AbstractXApplication::InputEvent { Ctrl = ControlMask, /**< Ctrl */ Alt = Mod1Mask, /**< Alt */ AltGr = Mod5Mask, /**< AltGr */ - - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief Button::Left - * @deprecated Use @ref Magnum::Platform::AbstractXApplication::InputEvent::buttons() "buttons()" - * and @ref Magnum::Platform::AbstractXApplication::InputEvent::Button::Left "Button::Left" - * instead. - */ - LeftButton = Button1Mask, - - /** - * @copybrief Button::Middle - * @deprecated Use @ref Magnum::Platform::AbstractXApplication::InputEvent::buttons() "buttons()" - * and @ref Magnum::Platform::AbstractXApplication::InputEvent::Button::Middle "Button::Middle" - * instead. - */ - MiddleButton = Button2Mask, - - /** - * @copybrief Button::Right - * @deprecated Use @ref Magnum::Platform::AbstractXApplication::InputEvent::buttons() "buttons()" - * and @ref Magnum::Platform::AbstractXApplication::InputEvent::Button::Right "Button::Right" - * instead. - */ - RightButton = Button3Mask, - #endif - CapsLock = LockMask, /**< Caps lock */ NumLock = Mod2Mask /**< Num lock */ }; diff --git a/src/Magnum/Platform/NaClApplication.h b/src/Magnum/Platform/NaClApplication.h index d04899d54..63fe8c491 100644 --- a/src/Magnum/Platform/NaClApplication.h +++ b/src/Magnum/Platform/NaClApplication.h @@ -474,33 +474,6 @@ class NaClApplication::InputEvent { Ctrl = PP_INPUTEVENT_MODIFIER_CONTROLKEY, /**< Ctrl */ Alt = PP_INPUTEVENT_MODIFIER_ALTKEY, /**< Alt */ Meta = PP_INPUTEVENT_MODIFIER_METAKEY, /**< Meta */ - - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief Button::Left - * @deprecated Use @ref Magnum::Platform::NaClApplication::InputEvent::buttons() "buttons()" - * and @ref Magnum::Platform::NaClApplication::InputEvent::Button::Left "Button::Left" - * instead. - */ - LeftButton = PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN, - - /** - * @copybrief Button::Middle - * @deprecated Use @ref Magnum::Platform::NaClApplication::InputEvent::buttons() "buttons()" - * and @ref Magnum::Platform::NaClApplication::InputEvent::Button::Middle "Button::Middle" - * instead. - */ - MiddleButton = PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN, - - /** - * @copybrief Button::Right - * @deprecated Use @ref Magnum::Platform::NaClApplication::InputEvent::buttons() "buttons()" - * and @ref Magnum::Platform::NaClApplication::InputEvent::Button::Right "Button::Right" - * instead. - */ - RightButton = PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN, - #endif - CapsLock = PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY, /**< Caps lock */ NumLock = PP_INPUTEVENT_MODIFIER_NUMLOCKKEY /**< Num lock */ }; From 116f474fabd16f0994f5c5d413c6981bf64f3086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 28 Mar 2014 16:43:06 +0100 Subject: [PATCH 118/141] Removed long-deprecated *::maxSupported*() limit queries. Use alternatives without the "Supported" substring instead. --- src/Magnum/AbstractShaderProgram.h | 9 --------- src/Magnum/AbstractTexture.cpp | 1 - src/Magnum/AbstractTexture.h | 9 --------- src/Magnum/Sampler.h | 7 ------- 4 files changed, 26 deletions(-) diff --git a/src/Magnum/AbstractShaderProgram.h b/src/Magnum/AbstractShaderProgram.h index 40dbe55fe..c5eb12559 100644 --- a/src/Magnum/AbstractShaderProgram.h +++ b/src/Magnum/AbstractShaderProgram.h @@ -343,15 +343,6 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { */ static Int maxVertexAttributes(); - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copydoc maxVertexAttributes() - * @deprecated Use @ref Magnum::AbstractShaderProgram::maxVertexAttributes() "maxVertexAttributes()" - * instead. - */ - static CORRADE_DEPRECATED("use maxVertexAttributes() instead") Int maxSupportedVertexAttributeCount() { return maxVertexAttributes(); } - #endif - #ifndef MAGNUM_TARGET_GLES /** * @brief Max supported atomic counter buffer size diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 5766ae09f..31bf05f99 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -48,7 +48,6 @@ namespace Magnum { #ifdef MAGNUM_BUILD_DEPRECATED Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); } -Int AbstractTexture::maxSupportedLayerCount() { return Shader::maxCombinedTextureImageUnits(); } #endif #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 6b57cace1..c8e7cba18 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -122,15 +122,6 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxLayers(); #endif - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @copybrief Shader::maxCombinedTextureImageUnits() - * @deprecated Use @ref Magnum::Shader::maxCombinedTextureImageUnits() "Shader::maxCombinedTextureImageUnits()" - * instead. - */ - static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxSupportedLayerCount(); - #endif - #ifndef MAGNUM_TARGET_GLES /** * @brief Max supported color sample count diff --git a/src/Magnum/Sampler.h b/src/Magnum/Sampler.h index b2c6e995a..51a6ba890 100644 --- a/src/Magnum/Sampler.h +++ b/src/Magnum/Sampler.h @@ -150,13 +150,6 @@ class MAGNUM_EXPORT Sampler { * instead. */ static CORRADE_DEPRECATED("use maxMaxAnisotropy() instead") Float maxAnisotropy() { return maxMaxAnisotropy(); } - - /** - * @copybrief maxMaxAnisotropy() - * @deprecated Use @ref Magnum::Sampler::maxMaxAnisotropy() "maxMaxAnisotropy()" - * instead. - */ - static CORRADE_DEPRECATED("use maxMaxAnisotropy() instead") Float maxSupportedAnisotropy() { return maxMaxAnisotropy(); } #endif }; From ecf7bfa2c148a93f354e38348fa8bc1cb6cc5d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 4 Apr 2014 10:45:17 +0200 Subject: [PATCH 119/141] Minor cleanup. --- src/Magnum/AbstractTexture.h | 12 ++++++------ src/Magnum/TextureArray.h | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index c8e7cba18..ea95a9706 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -157,6 +157,12 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { static Int maxIntegerSamples(); #endif + /** @brief Copying is not allowed */ + AbstractTexture(const AbstractTexture&) = delete; + + /** @brief Move constructor */ + AbstractTexture(AbstractTexture&& other) noexcept; + /** * @brief Destructor * @@ -165,12 +171,6 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { */ ~AbstractTexture(); - /** @brief Copying is not allowed */ - AbstractTexture(const AbstractTexture&) = delete; - - /** @brief Move constructor */ - AbstractTexture(AbstractTexture&& other) noexcept; - /** @brief Copying is not allowed */ AbstractTexture& operator=(const AbstractTexture&) = delete; diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 064c08cf8..bdf197a88 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -100,7 +100,8 @@ template class TextureArray: public AbstractTexture { * @brief Constructor * * Creates new OpenGL texture object. - * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_1D_ARRAY} or @def_gl{TEXTURE_2D_ARRAY} + * @see @fn_gl{GenTextures} with @def_gl{TEXTURE_1D_ARRAY} or + * @def_gl{TEXTURE_2D_ARRAY} */ explicit TextureArray(): AbstractTexture(Implementation::textureArrayTarget()) {} From f0df35aa654a5117a2795a2707ac8107f34eea89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 4 Apr 2014 10:58:21 +0200 Subject: [PATCH 120/141] Forgot to update state tracker in ARB_multi_bind texture binding impl. Would cause random weird issues with texture configuration/upload if ARB_multi_bind is available and EXT_direct_state_access is not. Probably not an issue, since EXT_direct_state_access is probably available on all drivers which support also ARB_multi_bind. --- src/Magnum/AbstractTexture.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 31bf05f99..6b9cdeeaa 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -137,6 +137,8 @@ void AbstractTexture::bindImplementationDefault(GLint textureUnit) { #ifndef MAGNUM_TARGET_GLES void AbstractTexture::bindImplementationMulti(GLint textureUnit) { + /* Bind the texture to the unit, update state tracker */ + Context::current()->state().texture->bindings[textureUnit] = _id; glBindTextures(textureUnit, 1, &_id); } From 26963970215f03018aca29b8638e702043c633f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Apr 2014 20:56:37 +0200 Subject: [PATCH 121/141] Verify that *Texture::bind() doesn't emit any GL errors. Can't verify much more at this time. --- src/Magnum/Test/BufferTextureGLTest.cpp | 12 ++++++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 9 +++++ src/Magnum/Test/CubeMapTextureGLTest.cpp | 9 +++++ src/Magnum/Test/MultisampleTextureGLTest.cpp | 26 ++++++++++++ src/Magnum/Test/RectangleTextureGLTest.cpp | 12 ++++++ src/Magnum/Test/TextureArrayGLTest.cpp | 34 ++++++++++++++++ src/Magnum/Test/TextureGLTest.cpp | 40 +++++++++++++++++++ 7 files changed, 142 insertions(+) diff --git a/src/Magnum/Test/BufferTextureGLTest.cpp b/src/Magnum/Test/BufferTextureGLTest.cpp index d0cbd7a4e..e61f38e62 100644 --- a/src/Magnum/Test/BufferTextureGLTest.cpp +++ b/src/Magnum/Test/BufferTextureGLTest.cpp @@ -36,12 +36,14 @@ class BufferTextureGLTest: public AbstractOpenGLTester { explicit BufferTextureGLTest(); void construct(); + void bind(); void setBuffer(); void setBufferOffset(); }; BufferTextureGLTest::BufferTextureGLTest() { addTests({&BufferTextureGLTest::construct, + &BufferTextureGLTest::bind, &BufferTextureGLTest::setBuffer, &BufferTextureGLTest::setBufferOffset}); } @@ -60,6 +62,16 @@ void BufferTextureGLTest::construct() { MAGNUM_VERIFY_NO_ERROR(); } +void BufferTextureGLTest::bind() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + + BufferTexture texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + void BufferTextureGLTest::setBuffer() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 1d7e69a43..9e353ca7d 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -40,6 +40,7 @@ class CubeMapTextureArrayGLTest: public AbstractOpenGLTester { explicit CubeMapTextureArrayGLTest(); void construct(); + void bind(); void sampling(); void samplingBorderInteger(); @@ -59,6 +60,7 @@ class CubeMapTextureArrayGLTest: public AbstractOpenGLTester { CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() { addTests({&CubeMapTextureArrayGLTest::construct, + &CubeMapTextureArrayGLTest::bind, &CubeMapTextureArrayGLTest::sampling, &CubeMapTextureArrayGLTest::samplingBorderInteger, @@ -90,6 +92,13 @@ void CubeMapTextureArrayGLTest::construct() { MAGNUM_VERIFY_NO_ERROR(); } +void CubeMapTextureArrayGLTest::bind() { + CubeMapTextureArray texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + void CubeMapTextureArrayGLTest::sampling() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index ede16a7f2..ac99f0cee 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -43,6 +43,7 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester { explicit CubeMapTextureGLTest(); void construct(); + void bind(); void sampling(); #ifdef MAGNUM_TARGET_GLES2 @@ -72,6 +73,7 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester { CubeMapTextureGLTest::CubeMapTextureGLTest() { addTests({&CubeMapTextureGLTest::construct, + &CubeMapTextureGLTest::bind, &CubeMapTextureGLTest::sampling, #ifdef MAGNUM_TARGET_GLES2 @@ -110,6 +112,13 @@ void CubeMapTextureGLTest::construct() { MAGNUM_VERIFY_NO_ERROR(); } +void CubeMapTextureGLTest::bind() { + CubeMapTexture texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + void CubeMapTextureGLTest::sampling() { CubeMapTexture texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) diff --git a/src/Magnum/Test/MultisampleTextureGLTest.cpp b/src/Magnum/Test/MultisampleTextureGLTest.cpp index 6c5e959cc..fbfd5d759 100644 --- a/src/Magnum/Test/MultisampleTextureGLTest.cpp +++ b/src/Magnum/Test/MultisampleTextureGLTest.cpp @@ -37,6 +37,9 @@ class MultisampleTextureGLTest: public AbstractOpenGLTester { void construct2D(); void construct2DArray(); + void bind2D(); + void bind2DArray(); + void storage2D(); void storage2DArray(); @@ -61,6 +64,9 @@ MultisampleTextureGLTest::MultisampleTextureGLTest() { addTests({&MultisampleTextureGLTest::construct2D, &MultisampleTextureGLTest::construct2DArray, + &MultisampleTextureGLTest::bind2D, + &MultisampleTextureGLTest::bind2DArray, + &MultisampleTextureGLTest::storage2D, &MultisampleTextureGLTest::storage2DArray, @@ -109,6 +115,26 @@ void MultisampleTextureGLTest::construct2DArray() { MAGNUM_VERIFY_NO_ERROR(); } +void MultisampleTextureGLTest::bind2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + MultisampleTexture2D texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + +void MultisampleTextureGLTest::bind2DArray() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); + + MultisampleTexture2DArray texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + void MultisampleTextureGLTest::storage2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index a4121ce06..7068671c5 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -41,6 +41,7 @@ class RectangleTextureGLTest: public AbstractOpenGLTester { explicit RectangleTextureGLTest(); void construct(); + void bind(); void sampling(); void samplingBorderInteger(); @@ -58,6 +59,7 @@ class RectangleTextureGLTest: public AbstractOpenGLTester { RectangleTextureGLTest::RectangleTextureGLTest() { addTests({&RectangleTextureGLTest::construct, + &RectangleTextureGLTest::bind, &RectangleTextureGLTest::sampling, &RectangleTextureGLTest::samplingBorderInteger, @@ -88,6 +90,16 @@ void RectangleTextureGLTest::construct() { MAGNUM_VERIFY_NO_ERROR(); } +void RectangleTextureGLTest::bind() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + void RectangleTextureGLTest::sampling() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index 2817bde22..33ff280db 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -45,6 +45,11 @@ class TextureArrayGLTest: public AbstractOpenGLTester { #endif void construct2D(); + #ifndef MAGNUM_TARGET_GLES + void bind1D(); + #endif + void bind2D(); + #ifndef MAGNUM_TARGET_GLES void sampling1D(); #endif @@ -105,6 +110,11 @@ TextureArrayGLTest::TextureArrayGLTest() { #endif &TextureArrayGLTest::construct2D, + #ifndef MAGNUM_TARGET_GLES + &TextureArrayGLTest::bind1D, + #endif + &TextureArrayGLTest::bind2D, + #ifndef MAGNUM_TARGET_GLES &TextureArrayGLTest::sampling1D, #endif @@ -189,6 +199,30 @@ void TextureArrayGLTest::construct2D() { MAGNUM_VERIFY_NO_ERROR(); } +#ifndef MAGNUM_TARGET_GLES +void TextureArrayGLTest::bind1D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +void TextureArrayGLTest::bind2D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); + #endif + + Texture2DArray texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::sampling1D() { if(!Context::current()->isExtensionSupported()) diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index 2f5a0f2ce..2cfa992a3 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -48,6 +48,12 @@ class TextureGLTest: public AbstractOpenGLTester { void construct2D(); void construct3D(); + #ifndef MAGNUM_TARGET_GLES + void bind1D(); + #endif + void bind2D(); + void bind3D(); + #ifndef MAGNUM_TARGET_GLES void sampling1D(); #endif @@ -128,6 +134,12 @@ TextureGLTest::TextureGLTest() { &TextureGLTest::construct2D, &TextureGLTest::construct3D, + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::bind1D, + #endif + &TextureGLTest::bind2D, + &TextureGLTest::bind3D, + #ifndef MAGNUM_TARGET_GLES &TextureGLTest::sampling1D, #endif @@ -239,6 +251,34 @@ void TextureGLTest::construct3D() { MAGNUM_VERIFY_NO_ERROR(); } +#ifndef MAGNUM_TARGET_GLES +void TextureGLTest::bind1D() { + Texture1D texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} +#endif + +void TextureGLTest::bind2D() { + Texture2D texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + +void TextureGLTest::bind3D() { + #ifdef MAGNUM_TARGET_GLES2 + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::OES::texture_3D::string() + std::string(" is not supported.")); + #endif + + Texture3D texture; + texture.bind(15); + + MAGNUM_VERIFY_NO_ERROR(); +} + #ifndef MAGNUM_TARGET_GLES void TextureGLTest::sampling1D() { Texture1D texture; From e2abc3976682936a5f88d46aa807b80126fff16e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Apr 2014 20:59:52 +0200 Subject: [PATCH 122/141] Save texture target along with ID in state tracker. Makes later unbinding easier (i.e. we don't need to cycle through all possible/supported targets and call glBindTexture(target, 0) with each. --- src/Magnum/AbstractTexture.cpp | 28 ++++++++++++------------ src/Magnum/Implementation/TextureState.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 6b9cdeeaa..7ce9d4e98 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -100,8 +100,8 @@ AbstractTexture::~AbstractTexture() { if(!_id) return; /* Remove all bindings */ - for(GLuint& binding: Context::current()->state().texture->bindings) - if(binding == _id) binding = 0; + for(auto& binding: Context::current()->state().texture->bindings) + if(binding.second == _id) binding = {}; glDeleteTextures(1, &_id); } @@ -119,31 +119,30 @@ void AbstractTexture::bind(Int textureUnit) { Implementation::TextureState* const textureState = Context::current()->state().texture; /* If already bound in given texture unit, nothing to do */ - if(textureState->bindings[textureUnit] == _id) return; + if(textureState->bindings[textureUnit].second == _id) return; + /* Update state tracker, bind the texture to the unit */ + textureState->bindings[textureUnit] = {_target, _id}; (this->*Context::current()->state().texture->bindImplementation)(textureUnit); } void AbstractTexture::bindImplementationDefault(GLint textureUnit) { Implementation::TextureState* const textureState = Context::current()->state().texture; - /* Activate given texture unit, if not already active */ + /* Activate given texture unit if not already active, update state tracker */ if(textureState->currentTextureUnit != textureUnit) glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = textureUnit)); - /* Bind the texture to the unit */ - glBindTexture(_target, (textureState->bindings[textureUnit] = _id)); + glBindTexture(_target, _id); } #ifndef MAGNUM_TARGET_GLES void AbstractTexture::bindImplementationMulti(GLint textureUnit) { - /* Bind the texture to the unit, update state tracker */ - Context::current()->state().texture->bindings[textureUnit] = _id; glBindTextures(textureUnit, 1, &_id); } void AbstractTexture::bindImplementationDSA(GLint textureUnit) { - glBindMultiTextureEXT(GL_TEXTURE0 + textureUnit, _target, (Context::current()->state().texture->bindings[textureUnit] = _id)); + glBindMultiTextureEXT(GL_TEXTURE0 + textureUnit, _target, _id); } #endif @@ -220,18 +219,19 @@ void AbstractTexture::bindInternal() { Implementation::TextureState* const textureState = Context::current()->state().texture; /* If the texture is already bound in current unit, nothing to do */ - if(textureState->bindings[textureState->currentTextureUnit] == _id) + if(textureState->bindings[textureState->currentTextureUnit].second == _id) return; - /* Set internal unit as active if not already */ + /* Set internal unit as active if not already, update state tracker */ CORRADE_INTERNAL_ASSERT(textureState->maxTextureUnits > 1); const GLint internalTextureUnit = textureState->maxTextureUnits-1; if(textureState->currentTextureUnit != internalTextureUnit) glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = internalTextureUnit)); - /* Bind the texture to internal unit, if not already */ - if(textureState->bindings[internalTextureUnit] != _id) - glBindTexture(_target, (textureState->bindings[internalTextureUnit] = _id)); + /* Bind the texture to internal unit if not already, update state tracker */ + if(textureState->bindings[internalTextureUnit].second == _id) return; + textureState->bindings[internalTextureUnit] = {_target, _id}; + glBindTexture(_target, _id); } ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) { diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index f4ef89d69..9cb56fa46 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -80,7 +80,7 @@ struct TextureState { bufferOffsetAlignment; #endif - std::vector bindings; + std::vector> bindings; }; }} From 580a723d6179e5ac5c4e61b762662f74d31c71cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Apr 2014 21:07:44 +0200 Subject: [PATCH 123/141] Added *Texture::unbind(). Will be used in fallback implementation of multi-bind. --- src/Magnum/AbstractTexture.cpp | 36 +++++++++++++++++++ src/Magnum/AbstractTexture.h | 23 +++++++++++- src/Magnum/Implementation/TextureState.cpp | 7 ++++ src/Magnum/Implementation/TextureState.h | 1 + src/Magnum/Test/BufferTextureGLTest.cpp | 4 +++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 4 +++ src/Magnum/Test/CubeMapTextureGLTest.cpp | 4 +++ src/Magnum/Test/MultisampleTextureGLTest.cpp | 8 +++++ src/Magnum/Test/RectangleTextureGLTest.cpp | 4 +++ src/Magnum/Test/TextureArrayGLTest.cpp | 8 +++++ src/Magnum/Test/TextureGLTest.cpp | 12 +++++++ 11 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 7ce9d4e98..93d74dacc 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -91,6 +91,42 @@ Int AbstractTexture::maxIntegerSamples() { } #endif +void AbstractTexture::unbind(const Int textureUnit) { + Implementation::TextureState* const textureState = Context::current()->state().texture; + + /* If given texture unit is already unbound, nothing to do */ + if(textureState->bindings[textureUnit].second == 0) return; + + /* Unbind the texture, reset state tracker */ + Context::current()->state().texture->unbindImplementation(textureUnit); + textureState->bindings[textureUnit] = {}; +} + +void AbstractTexture::unbindImplementationDefault(const GLint textureUnit) { + Implementation::TextureState* const textureState = Context::current()->state().texture; + + /* Activate given texture unit if not already active, update state tracker */ + if(textureState->currentTextureUnit != textureUnit) + glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = textureUnit)); + + CORRADE_INTERNAL_ASSERT(textureState->bindings[textureUnit].first != 0); + glBindTexture(textureState->bindings[textureUnit].first, 0); +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::unbindImplementationMulti(const GLint textureUnit) { + constexpr static const GLuint zero = 0; + glBindTextures(textureUnit, 1, &zero); +} + +void AbstractTexture::unbindImplementationDSA(const GLint textureUnit) { + Implementation::TextureState* const textureState = Context::current()->state().texture; + + CORRADE_INTERNAL_ASSERT(textureState->bindings[textureUnit].first != 0); + glBindMultiTextureEXT(GL_TEXTURE0 + textureUnit, textureState->bindings[textureUnit].first, 0); +} +#endif + AbstractTexture::AbstractTexture(GLenum target): _target(target) { glGenTextures(1, &_id); } diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index ea95a9706..099a74d35 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -157,6 +157,21 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { static Int maxIntegerSamples(); #endif + /** + * @brief Unbind any texture from given texture unit + * + * If @extension{ARB,multi_bind} (part of OpenGL 4.4) or + * @extension{EXT,direct_state_access} is not available, the texture + * unit is made active before binding the texture. + * @note This function is meant to be used only internally from + * @ref AbstractShaderProgram subclasses. See its documentation + * for more information. + * @see @ref bind(), @ref Shader::maxCombinedTextureImageUnits(), + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture}, @fn_gl{BindTextures} + * or @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} + */ + static void unbind(Int textureUnit); + /** @brief Copying is not allowed */ AbstractTexture(const AbstractTexture&) = delete; @@ -215,7 +230,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * @note This function is meant to be used only internally from * @ref AbstractShaderProgram subclasses. See its documentation * for more information. - * @see @ref Shader::maxCombinedTextureImageUnits(), + * @see @ref unbind(), @ref Shader::maxCombinedTextureImageUnits(), * @fn_gl{ActiveTexture}, @fn_gl{BindTexture}, @fn_gl{BindTextures} * or @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} */ @@ -254,6 +269,12 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { GLenum _target; private: + static void MAGNUM_LOCAL unbindImplementationDefault(GLint textureUnit); + #ifndef MAGNUM_TARGET_GLES + static void MAGNUM_LOCAL unbindImplementationMulti(GLint textureUnit); + static void MAGNUM_LOCAL unbindImplementationDSA(GLint textureUnit); + #endif + void MAGNUM_LOCAL bindImplementationDefault(GLint textureUnit); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL bindImplementationMulti(GLint textureUnit); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index beae61381..23aafcfe1 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -45,13 +45,20 @@ TextureState::TextureState(Context& context, std::vector& extension #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::ARB::multi_bind::string()); + + unbindImplementation = &AbstractTexture::unbindImplementationMulti; bindImplementation = &AbstractTexture::bindImplementationMulti; + } else if(context.isExtensionSupported()) { /* Extension name added below */ + + unbindImplementation = &AbstractTexture::unbindImplementationDSA; bindImplementation = &AbstractTexture::bindImplementationDSA; + } else #endif { + unbindImplementation = &AbstractTexture::unbindImplementationDefault; bindImplementation = &AbstractTexture::bindImplementationDefault; } diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 9cb56fa46..3fb4af551 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -37,6 +37,7 @@ struct TextureState { explicit TextureState(Context& context, std::vector& extensions); ~TextureState(); + void(*unbindImplementation)(GLint); void(AbstractTexture::*bindImplementation)(GLint); void(AbstractTexture::*parameteriImplementation)(GLenum, GLint); void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat); diff --git a/src/Magnum/Test/BufferTextureGLTest.cpp b/src/Magnum/Test/BufferTextureGLTest.cpp index e61f38e62..1eb02c535 100644 --- a/src/Magnum/Test/BufferTextureGLTest.cpp +++ b/src/Magnum/Test/BufferTextureGLTest.cpp @@ -70,6 +70,10 @@ void BufferTextureGLTest::bind() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } void BufferTextureGLTest::setBuffer() { diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 9e353ca7d..5ee8b18d2 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -97,6 +97,10 @@ void CubeMapTextureArrayGLTest::bind() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } void CubeMapTextureArrayGLTest::sampling() { diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index ac99f0cee..a8631da68 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -117,6 +117,10 @@ void CubeMapTextureGLTest::bind() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } void CubeMapTextureGLTest::sampling() { diff --git a/src/Magnum/Test/MultisampleTextureGLTest.cpp b/src/Magnum/Test/MultisampleTextureGLTest.cpp index fbfd5d759..e2df0e503 100644 --- a/src/Magnum/Test/MultisampleTextureGLTest.cpp +++ b/src/Magnum/Test/MultisampleTextureGLTest.cpp @@ -123,6 +123,10 @@ void MultisampleTextureGLTest::bind2D() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::bind2DArray() { @@ -133,6 +137,10 @@ void MultisampleTextureGLTest::bind2DArray() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::storage2D() { diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index 7068671c5..b7a54c2e3 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -98,6 +98,10 @@ void RectangleTextureGLTest::bind() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } void RectangleTextureGLTest::sampling() { diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index 33ff280db..38e286dba 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -208,6 +208,10 @@ void TextureArrayGLTest::bind1D() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } #endif @@ -221,6 +225,10 @@ void TextureArrayGLTest::bind2D() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index 2cfa992a3..cabcf2de4 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -257,6 +257,10 @@ void TextureGLTest::bind1D() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } #endif @@ -265,6 +269,10 @@ void TextureGLTest::bind2D() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } void TextureGLTest::bind3D() { @@ -277,6 +285,10 @@ void TextureGLTest::bind3D() { texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::unbind(15); + + MAGNUM_VERIFY_NO_ERROR(); } #ifndef MAGNUM_TARGET_GLES From cc66fa76ba61b17f0d8d93f7d263836606f650ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Apr 2014 22:25:06 +0200 Subject: [PATCH 124/141] Support ARB_multi_bind for textures. --- doc/opengl-support.dox | 2 +- src/Magnum/AbstractTexture.cpp | 30 +++++++++++++++++++ src/Magnum/AbstractTexture.h | 21 ++++++++++++- src/Magnum/Implementation/TextureState.cpp | 3 ++ src/Magnum/Implementation/TextureState.h | 1 + src/Magnum/Test/BufferTextureGLTest.cpp | 4 +++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 4 +++ src/Magnum/Test/CubeMapTextureGLTest.cpp | 4 +++ src/Magnum/Test/MultisampleTextureGLTest.cpp | 8 +++++ src/Magnum/Test/RectangleTextureGLTest.cpp | 4 +++ src/Magnum/Test/TextureArrayGLTest.cpp | 8 +++++ src/Magnum/Test/TextureGLTest.cpp | 12 ++++++++ 12 files changed, 99 insertions(+), 2 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 96444d692..6ec01fbe5 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -201,7 +201,7 @@ following: @extension{ARB,buffer_storage} | | @extension{ARB,clear_texture} | | @extension{ARB,enhanced_layouts} | done (shading language only) -@extension{ARB,multi_bind} | only single texture binding +@extension{ARB,multi_bind} | only texture binding @extension{ARB,query_buffer_object} | | @extension{ARB,texture_mirror_clamp_to_edge} | done @extension{ARB,texture_stencil8} | done diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 93d74dacc..c940f0580 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -127,6 +127,36 @@ void AbstractTexture::unbindImplementationDSA(const GLint textureUnit) { } #endif +void AbstractTexture::bind(const Int firstTextureUnit, std::initializer_list textures) { + /* State tracker is updated in the implementations */ + Context::current()->state().texture->bindMultiImplementation(firstTextureUnit, textures); +} + +void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, std::initializer_list textures) { + Int unit = firstTextureUnit; + for(AbstractTexture* const texture: textures) { + if(texture) texture->bind(unit); + else unbind(unit); + ++unit; + } +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, std::initializer_list textures) { + Implementation::TextureState* const textureState = Context::current()->state().texture; + + /* Create array of IDs and also update bindings in state tracker */ + Containers::Array ids{textures.size()}; + Int i{}; + for(const AbstractTexture* const texture: textures) { + textureState->bindings[firstTextureUnit + i].second = ids[i] = texture ? texture->id() : 0; + ++i; + } + + glBindTextures(firstTextureUnit, ids.size(), ids); +} +#endif + AbstractTexture::AbstractTexture(GLenum target): _target(target) { glGenTextures(1, &_id); } diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 099a74d35..b708473be 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -172,6 +172,19 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { */ static void unbind(Int textureUnit); + /** + * @brief Bind textures to given range of texture units + * + * Binds first texture in the list to @p firstTextureUnit, second to + * `firstTextureUnit + 1` etc. If any texture is `nullptr`, given + * texture unit is unbound. If @extension{ARB,multi_bind} (part of + * OpenGL 4.4) is not available, the feature is emulated with sequence + * of @ref bind(Int) / @ref unbind() calls. + * @see @fn_gl{BindTextures}, eventually @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} or @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} + */ + static void bind(Int firstTextureUnit, std::initializer_list textures); + /** @brief Copying is not allowed */ AbstractTexture(const AbstractTexture&) = delete; @@ -230,7 +243,8 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { * @note This function is meant to be used only internally from * @ref AbstractShaderProgram subclasses. See its documentation * for more information. - * @see @ref unbind(), @ref Shader::maxCombinedTextureImageUnits(), + * @see @ref bind(Int, std::initializer_list), + * @ref unbind(), @ref Shader::maxCombinedTextureImageUnits(), * @fn_gl{ActiveTexture}, @fn_gl{BindTexture}, @fn_gl{BindTextures} * or @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} */ @@ -275,6 +289,11 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { static void MAGNUM_LOCAL unbindImplementationDSA(GLint textureUnit); #endif + static void MAGNUM_LOCAL bindImplementationFallback(GLint firstTextureUnit, std::initializer_list textures); + #ifndef MAGNUM_TARGET_GLES + static void MAGNUM_LOCAL bindImplementationMulti(GLint firstTextureUnit, std::initializer_list textures); + #endif + void MAGNUM_LOCAL bindImplementationDefault(GLint textureUnit); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL bindImplementationMulti(GLint textureUnit); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 23aafcfe1..e83e195e5 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -47,18 +47,21 @@ TextureState::TextureState(Context& context, std::vector& extension extensions.push_back(Extensions::GL::ARB::multi_bind::string()); unbindImplementation = &AbstractTexture::unbindImplementationMulti; + bindMultiImplementation = &AbstractTexture::bindImplementationMulti; bindImplementation = &AbstractTexture::bindImplementationMulti; } else if(context.isExtensionSupported()) { /* Extension name added below */ unbindImplementation = &AbstractTexture::unbindImplementationDSA; + bindMultiImplementation = &AbstractTexture::bindImplementationFallback; bindImplementation = &AbstractTexture::bindImplementationDSA; } else #endif { unbindImplementation = &AbstractTexture::unbindImplementationDefault; + bindMultiImplementation = &AbstractTexture::bindImplementationFallback; bindImplementation = &AbstractTexture::bindImplementationDefault; } diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 3fb4af551..098080fb0 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -38,6 +38,7 @@ struct TextureState { ~TextureState(); void(*unbindImplementation)(GLint); + void(*bindMultiImplementation)(GLint, std::initializer_list); void(AbstractTexture::*bindImplementation)(GLint); void(AbstractTexture::*parameteriImplementation)(GLenum, GLint); void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat); diff --git a/src/Magnum/Test/BufferTextureGLTest.cpp b/src/Magnum/Test/BufferTextureGLTest.cpp index 1eb02c535..b67180ea9 100644 --- a/src/Magnum/Test/BufferTextureGLTest.cpp +++ b/src/Magnum/Test/BufferTextureGLTest.cpp @@ -74,6 +74,10 @@ void BufferTextureGLTest::bind() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } void BufferTextureGLTest::setBuffer() { diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 5ee8b18d2..fbe7e7f5c 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -101,6 +101,10 @@ void CubeMapTextureArrayGLTest::bind() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } void CubeMapTextureArrayGLTest::sampling() { diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index a8631da68..092d6b5e4 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -121,6 +121,10 @@ void CubeMapTextureGLTest::bind() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } void CubeMapTextureGLTest::sampling() { diff --git a/src/Magnum/Test/MultisampleTextureGLTest.cpp b/src/Magnum/Test/MultisampleTextureGLTest.cpp index e2df0e503..0de1a3d44 100644 --- a/src/Magnum/Test/MultisampleTextureGLTest.cpp +++ b/src/Magnum/Test/MultisampleTextureGLTest.cpp @@ -127,6 +127,10 @@ void MultisampleTextureGLTest::bind2D() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::bind2DArray() { @@ -141,6 +145,10 @@ void MultisampleTextureGLTest::bind2DArray() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::storage2D() { diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index b7a54c2e3..a0a9827c3 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -102,6 +102,10 @@ void RectangleTextureGLTest::bind() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } void RectangleTextureGLTest::sampling() { diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index 38e286dba..0a7f7676b 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -212,6 +212,10 @@ void TextureArrayGLTest::bind1D() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } #endif @@ -229,6 +233,10 @@ void TextureArrayGLTest::bind2D() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index cabcf2de4..fb5a90b5b 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -261,6 +261,10 @@ void TextureGLTest::bind1D() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } #endif @@ -273,6 +277,10 @@ void TextureGLTest::bind2D() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } void TextureGLTest::bind3D() { @@ -289,6 +297,10 @@ void TextureGLTest::bind3D() { AbstractTexture::unbind(15); MAGNUM_VERIFY_NO_ERROR(); + + AbstractTexture::bind(7, {&texture, nullptr, &texture}); + + MAGNUM_VERIFY_NO_ERROR(); } #ifndef MAGNUM_TARGET_GLES From 2e3a00ab8b2aa534b694fc39e25b538cc917903c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Apr 2014 22:25:46 +0200 Subject: [PATCH 125/141] Fix (workaround) failing texture tests. With ARB_multi_bind it is needed to associate the texture with some target before calling glBindTextures(), otherwise the texture is treated as invalid. --- src/Magnum/AbstractTexture.h | 4 +++ src/Magnum/Test/BufferTextureGLTest.cpp | 13 ++++++++++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 9 +++++++ src/Magnum/Test/CubeMapTextureGLTest.cpp | 9 +++++++ src/Magnum/Test/MultisampleTextureGLTest.cpp | 14 +++++++++++ src/Magnum/Test/RectangleTextureGLTest.cpp | 9 +++++++ src/Magnum/Test/TextureArrayGLTest.cpp | 16 ++++++++++++ src/Magnum/Test/TextureGLTest.cpp | 25 +++++++++++++++++++ 8 files changed, 99 insertions(+) diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index b708473be..e6c62decf 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -108,6 +108,10 @@ functions do nothing. @todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented @todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done @todo Query for immutable levels (@extension{ARB,ES3_compatibility}) +@bug If using @extension{ARB,multi_bind} and the texture is bound right after + construction, the @fn_gl{BindTextures} call will fail with + Renderer::Error::InvalidOperation, because the texture doesn't yet have + associated target */ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { friend struct Implementation::TextureState; diff --git a/src/Magnum/Test/BufferTextureGLTest.cpp b/src/Magnum/Test/BufferTextureGLTest.cpp index b67180ea9..0789b2aaa 100644 --- a/src/Magnum/Test/BufferTextureGLTest.cpp +++ b/src/Magnum/Test/BufferTextureGLTest.cpp @@ -67,6 +67,19 @@ void BufferTextureGLTest::bind() { CORRADE_SKIP(Extensions::GL::ARB::texture_buffer_object::string() + std::string(" is not supported.")); BufferTexture texture; + + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it"); + Buffer buffer; + constexpr UnsignedByte data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + buffer.setData(data, BufferUsage::StaticDraw); + texture.setBuffer(BufferTextureFormat::R8UI, buffer); + CORRADE_VERIFY(false); + } + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index fbe7e7f5c..e6f9fdf63 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -94,6 +94,15 @@ void CubeMapTextureArrayGLTest::construct() { void CubeMapTextureArrayGLTest::bind() { CubeMapTextureArray texture; + + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setBaseLevel(0); + CORRADE_VERIFY(false); + } + #endif + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index 092d6b5e4..c820d365c 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -114,6 +114,15 @@ void CubeMapTextureGLTest::construct() { void CubeMapTextureGLTest::bind() { CubeMapTexture texture; + + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setBaseLevel(0); + CORRADE_VERIFY(false); + } + #endif + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Magnum/Test/MultisampleTextureGLTest.cpp b/src/Magnum/Test/MultisampleTextureGLTest.cpp index 0de1a3d44..afeaec3b0 100644 --- a/src/Magnum/Test/MultisampleTextureGLTest.cpp +++ b/src/Magnum/Test/MultisampleTextureGLTest.cpp @@ -120,6 +120,13 @@ void MultisampleTextureGLTest::bind2D() { CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); MultisampleTexture2D texture; + + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + CORRADE_VERIFY(false); + CORRADE_SKIP("...but we don't have any function to do that yet."); + } + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); @@ -138,6 +145,13 @@ void MultisampleTextureGLTest::bind2DArray() { CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); MultisampleTexture2DArray texture; + + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + CORRADE_VERIFY(false); + CORRADE_SKIP("...but we don't have any function to do that yet."); + } + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index a0a9827c3..91404f694 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -95,6 +95,15 @@ void RectangleTextureGLTest::bind() { CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); RectangleTexture texture; + + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setWrapping(Sampler::Wrapping::ClampToEdge); + CORRADE_VERIFY(false); + } + #endif + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index 0a7f7676b..d7c2d2f68 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -205,6 +205,13 @@ void TextureArrayGLTest::bind1D() { CORRADE_SKIP(Extensions::GL::EXT::texture_array::string() + std::string(" is not supported.")); Texture1DArray texture; + + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setBaseLevel(0); + CORRADE_VERIFY(false); + } + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); @@ -226,6 +233,15 @@ void TextureArrayGLTest::bind2D() { #endif Texture2DArray texture; + + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setBaseLevel(0); + CORRADE_VERIFY(false); + } + #endif + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index fb5a90b5b..ee23b0316 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -254,6 +254,13 @@ void TextureGLTest::construct3D() { #ifndef MAGNUM_TARGET_GLES void TextureGLTest::bind1D() { Texture1D texture; + + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setBaseLevel(0); + CORRADE_VERIFY(false); + } + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); @@ -270,6 +277,15 @@ void TextureGLTest::bind1D() { void TextureGLTest::bind2D() { Texture2D texture; + + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setBaseLevel(0); + CORRADE_VERIFY(false); + } + #endif + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); @@ -290,6 +306,15 @@ void TextureGLTest::bind3D() { #endif Texture3D texture; + + #ifndef MAGNUM_TARGET_GLES + if(Context::current()->isExtensionSupported()) { + CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setBaseLevel(0); + CORRADE_VERIFY(false); + } + #endif + texture.bind(15); MAGNUM_VERIFY_NO_ERROR(); From e3b0d1d4ceb2bfe6ca01db71fe596a4e98cdc345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 6 Apr 2014 22:42:54 +0200 Subject: [PATCH 126/141] Shaders: use texture multi-bind functionality in Phong shader. --- src/Magnum/Shaders/Phong.cpp | 5 +++++ src/Magnum/Shaders/Phong.h | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/Phong.cpp index e7bf2594e..21f346d16 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/Phong.cpp @@ -130,4 +130,9 @@ Phong& Phong::setSpecularTexture(Texture2D& texture) { return *this; } +Phong& Phong::setTextures(Texture2D* ambient, Texture2D* diffuse, Texture2D* specular) { + AbstractTexture::bind(AmbientTextureLayer, {ambient, diffuse, specular}); + return *this; +} + }} diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index c2cd09356..902496ca7 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -132,7 +132,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { * @return Reference to self (for method chaining) * * Has effect only if @ref Flag::AmbientTexture is set. - * @see @ref setAmbientColor() + * @see @ref setTextures(), @ref setAmbientColor() */ Phong& setAmbientTexture(Texture2D& texture); @@ -150,7 +150,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { * @return Reference to self (for method chaining) * * Has effect only if @ref Flag::DiffuseTexture is set. - * @see @ref setDiffuseColor() + * @see @ref setTextures(), @ref setDiffuseColor() */ Phong& setDiffuseTexture(Texture2D& texture); @@ -169,10 +169,22 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { * @return Reference to self (for method chaining) * * Has effect only if @ref Flag::SpecularTexture is set. - * @see @ref setSpecularColor() + * @see @ref setTextures(), @ref setSpecularColor() */ Phong& setSpecularTexture(Texture2D& texture); + /** + * @brief Set textures + * @return Reference to self (for method chaining) + * + * A particular texture has effect only if particular texture flag from + * @ref Phong::Flag "Flag" is set, you can use `nullptr` for the rest. + * More efficient than setting each texture separately. + * @see @ref setAmbientTexture(), @ref setDiffuseTexture(), + * @ref setSpecularTexture() + */ + Phong& setTextures(Texture2D* ambient, Texture2D* diffuse, Texture2D* specular); + /** * @brief Set shininess * @return Reference to self (for method chaining) From 6f0a238376e1c174216046a1e3a62928252bfe02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 7 Apr 2014 22:29:46 +0200 Subject: [PATCH 127/141] Disable also NV_framebuffer_blit on ES2. Until we have proper extension loader implemented (caused FramebufferGLTest to assert). On a related note, NVidia drivers 334.21 support *a lot* of ES2 extensions. Wow. --- src/Magnum/Implementation/setupDriverWorkarounds.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magnum/Implementation/setupDriverWorkarounds.cpp b/src/Magnum/Implementation/setupDriverWorkarounds.cpp index d575ce324..7d5d7f8be 100644 --- a/src/Magnum/Implementation/setupDriverWorkarounds.cpp +++ b/src/Magnum/Implementation/setupDriverWorkarounds.cpp @@ -79,6 +79,7 @@ void Context::setupDriverWorkarounds() { _setRequiredVersion(GL::NV::draw_buffers, None); _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ?? _setRequiredVersion(GL::NV::read_buffer, None); + _setRequiredVersion(GL::NV::framebuffer_blit, None); _setRequiredVersion(GL::NV::framebuffer_multisample, None); _setRequiredVersion(GL::OES::texture_3D, None); _setRequiredVersion(GL::OES::vertex_array_object, None); From f46cda1900d14bb8760dcac4d3d3d38c0b10202d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 7 Apr 2014 20:02:32 +0200 Subject: [PATCH 128/141] Remove redundant ifdefs and docs from desktop-GL-only code. --- src/Magnum/CubeMapTextureArray.h | 8 -------- src/Magnum/MultisampleTexture.h | 2 -- src/Magnum/RectangleTexture.h | 11 ++++------- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index a6c09f16a..4cc079709 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -89,13 +89,11 @@ class CubeMapTextureArray: public AbstractTexture { */ explicit CubeMapTextureArray(): AbstractTexture(GL_TEXTURE_CUBE_MAP_ARRAY) {} - #ifndef MAGNUM_TARGET_GLES2 /** @copydoc Texture::setBaseLevel() */ CubeMapTextureArray& setBaseLevel(Int level) { AbstractTexture::setBaseLevel(level); return *this; } - #endif /** @copydoc Texture::setMaxLevel() */ CubeMapTextureArray& setMaxLevel(Int level) { @@ -127,7 +125,6 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } - #ifndef MAGNUM_TARGET_GLES /** @copydoc Texture::setBorderColor(const Vector4ui&) */ CubeMapTextureArray& setBorderColor(const Vector4ui& color) { AbstractTexture::setBorderColor(color); @@ -139,7 +136,6 @@ class CubeMapTextureArray: public AbstractTexture { AbstractTexture::setBorderColor(color); return *this; } - #endif /** @copydoc Texture::setMaxAnisotropy() */ CubeMapTextureArray& setMaxAnisotropy(Float anisotropy) { @@ -168,14 +164,12 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } - #ifndef MAGNUM_TARGET_GLES /** * @brief Read given mip level of texture to image * @param level Mip level * @param image %Image where to put the data * * See @ref Texture::image(Int, Image&) for more information. - * @requires_gl %Texture image queries are not available in OpenGL ES. */ void image(Int level, Image3D& image) { AbstractTexture::image<3>(GL_TEXTURE_CUBE_MAP_ARRAY, level, image); @@ -189,12 +183,10 @@ class CubeMapTextureArray: public AbstractTexture { * * See @ref Texture::image(Int, BufferImage&, BufferUsage) for more * information. - * @requires_gl %Texture image queries are not available in OpenGL ES. */ void image(Int level, BufferImage3D& image, BufferUsage usage) { AbstractTexture::image<3>(GL_TEXTURE_CUBE_MAP_ARRAY, level, image, usage); } - #endif /** * @brief Set image data diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h index 97c986b6d..3b6f55264 100644 --- a/src/Magnum/MultisampleTexture.h +++ b/src/Magnum/MultisampleTexture.h @@ -77,12 +77,10 @@ template class MultisampleTexture: public AbstractTextur */ explicit MultisampleTexture(): AbstractTexture(Implementation::multisampleTextureTarget()) {} - #ifndef MAGNUM_TARGET_GLES /** @copydoc Texture::imageSize() */ typename DimensionTraits::VectorType imageSize(Int level) { return DataHelper::imageSize(*this, _target, level); } - #endif /** @copydoc Texture::invalidateImage() */ void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); } diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 17a49372c..50673e8e5 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -103,7 +103,6 @@ class RectangleTexture: public AbstractTexture { return *this; } - #ifndef MAGNUM_TARGET_GLES /** * @brief %Image size * @@ -113,10 +112,8 @@ class RectangleTexture: public AbstractTexture { * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_WIDTH} and @def_gl{TEXTURE_HEIGHT} - * @requires_gl %Texture image queries are not available in OpenGL ES. */ Vector2i imageSize() { return DataHelper<2>::imageSize(*this, _target, 0); } - #endif /** * @brief Set wrapping @@ -300,8 +297,8 @@ class RectangleTexture: public AbstractTexture { /** * @brief Invalidate texture image * - * If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} - * (part of OpenGL 4.3) is not available, this function does nothing. + * If extension @extension{ARB,invalidate_subdata} (part of OpenGL 4.3) + * is not available, this function does nothing. * @see @ref invalidateSubImage(), @fn_gl{InvalidateTexImage} */ void invalidateImage() { AbstractTexture::invalidateImage(0); } @@ -311,8 +308,8 @@ class RectangleTexture: public AbstractTexture { * @param offset Offset into the texture * @param size Size of invalidated data * - * If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} - * (part of OpenGL 4.3) is not available, this function does nothing. + * If extension @extension{ARB,invalidate_subdata} (part of OpenGL 4.3) + * is not available, this function does nothing. * @see @ref invalidateImage(), @fn_gl{InvalidateTexSubImage} */ void invalidateSubImage(const Vector2i& offset, const Vector2i& size) { From b28876ec7067a0b9c3621725afb19bd70bb2caba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 7 Apr 2014 22:58:57 +0200 Subject: [PATCH 129/141] Doc++ --- src/Magnum/RectangleTexture.h | 2 +- src/Magnum/Texture.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 50673e8e5..91a3fca21 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -166,7 +166,7 @@ class RectangleTexture: public AbstractTexture { /** * @brief Set storage * @param internalFormat Internal format - * @param size Size + * @param size %Texture size * @return Reference to self (for method chaining) * * Specifies entire structure of a texture at once, removing the need diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 2295f480e..4b6694fdf 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -178,7 +178,8 @@ template class Texture: public AbstractTexture { * is bound to some texture unit before the operation. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or @def_gl{TEXTURE_DEPTH}. + * with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or + * @def_gl{TEXTURE_DEPTH} * @requires_gl %Texture image queries are not available in OpenGL ES. */ typename DimensionTraits::VectorType imageSize(Int level) { @@ -382,7 +383,7 @@ template class Texture: public AbstractTexture { * eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or * @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ - * @fn_gl_extension{TextureImage3D,EXT,direct_state_access}. + * @fn_gl_extension{TextureImage3D,EXT,direct_state_access} */ Texture& setStorage(Int levels, TextureFormat internalFormat, const typename DimensionTraits::VectorType& size) { DataHelper::setStorage(*this, _target, levels, internalFormat, size); From 55d9a2f5c6fe525f0fc6e08011a9563853d7e88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 7 Apr 2014 22:47:34 +0200 Subject: [PATCH 130/141] Multisample textures don't have mip levels. Another victim of copy-paste, which was never tested in practice because of incomplete implementation. --- src/Magnum/MultisampleTexture.h | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h index 3b6f55264..2ad0abc34 100644 --- a/src/Magnum/MultisampleTexture.h +++ b/src/Magnum/MultisampleTexture.h @@ -77,17 +77,27 @@ template class MultisampleTexture: public AbstractTextur */ explicit MultisampleTexture(): AbstractTexture(Implementation::multisampleTextureTarget()) {} - /** @copydoc Texture::imageSize() */ - typename DimensionTraits::VectorType imageSize(Int level) { - return DataHelper::imageSize(*this, _target, level); + /** + * @brief %Image size + * + * The result is not cached in any way. If + * @extension{EXT,direct_state_access} is not available, the texture + * is bound to some texture unit before the operation. + * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} + * with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or + * @def_gl{TEXTURE_DEPTH} + */ + typename DimensionTraits::VectorType imageSize() { + return DataHelper::imageSize(*this, _target, 0); } - /** @copydoc Texture::invalidateImage() */ - void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); } + /** @copydoc RectangleTexture::invalidateImage() */ + void invalidateImage() { AbstractTexture::invalidateImage(0); } - /** @copydoc Texture::invalidateSubImage() */ - void invalidateSubImage(Int level, const typename DimensionTraits::VectorType& offset, const typename DimensionTraits::VectorType& size) { - DataHelper::invalidateSubImage(*this, level, offset, size); + /** @copydoc RectangleTexture::invalidateSubImage() */ + void invalidateSubImage(const typename DimensionTraits::VectorType& offset, const typename DimensionTraits::VectorType& size) { + DataHelper::invalidateSubImage(*this, 0, offset, size); } /* Overloads to remove WTF-factor from method chaining order */ From 32fee76081f0524d859d89030c31a027cd86aab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 7 Apr 2014 22:53:53 +0200 Subject: [PATCH 131/141] Multisample textures also won't have any image setting functions. --- src/Magnum/Test/MultisampleTextureGLTest.cpp | 76 -------------------- 1 file changed, 76 deletions(-) diff --git a/src/Magnum/Test/MultisampleTextureGLTest.cpp b/src/Magnum/Test/MultisampleTextureGLTest.cpp index afeaec3b0..dfbd2de98 100644 --- a/src/Magnum/Test/MultisampleTextureGLTest.cpp +++ b/src/Magnum/Test/MultisampleTextureGLTest.cpp @@ -43,16 +43,6 @@ class MultisampleTextureGLTest: public AbstractOpenGLTester { void storage2D(); void storage2DArray(); - void image2D(); - void image2DBuffer(); - void image2DArray(); - void image2DArrayBuffer(); - - void subImage2D(); - void subImage2DBuffer(); - void subImage2DArray(); - void subImage2DArrayBuffer(); - void invalidateImage2D(); void invalidateImage2DArray(); @@ -70,16 +60,6 @@ MultisampleTextureGLTest::MultisampleTextureGLTest() { &MultisampleTextureGLTest::storage2D, &MultisampleTextureGLTest::storage2DArray, - &MultisampleTextureGLTest::image2D, - &MultisampleTextureGLTest::image2DBuffer, - &MultisampleTextureGLTest::image2DArray, - &MultisampleTextureGLTest::image2DArrayBuffer, - - &MultisampleTextureGLTest::subImage2D, - &MultisampleTextureGLTest::subImage2DBuffer, - &MultisampleTextureGLTest::subImage2DArray, - &MultisampleTextureGLTest::subImage2DArrayBuffer, - &MultisampleTextureGLTest::invalidateImage2D, &MultisampleTextureGLTest::invalidateImage2DArray, @@ -179,62 +159,6 @@ void MultisampleTextureGLTest::storage2DArray() { CORRADE_SKIP("Not implemented yet."); } -void MultisampleTextureGLTest::image2D() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void MultisampleTextureGLTest::image2DBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void MultisampleTextureGLTest::image2DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void MultisampleTextureGLTest::image2DArrayBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void MultisampleTextureGLTest::subImage2D() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void MultisampleTextureGLTest::subImage2DBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void MultisampleTextureGLTest::subImage2DArray() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - -void MultisampleTextureGLTest::subImage2DArrayBuffer() { - if(!Context::current()->isExtensionSupported()) - CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - - CORRADE_SKIP("Not implemented yet."); -} - void MultisampleTextureGLTest::invalidateImage2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); From 0a2b8088a6427db6e7d5a2dcf4a4f1a65aad6826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 7 Apr 2014 22:57:48 +0200 Subject: [PATCH 132/141] Added MultisampleTexture::setStorage(). With this function multisample texture implementation is pretty much done. Also implemented all the tests. --- doc/opengl-support.dox | 4 +- src/Magnum/AbstractTexture.cpp | 40 ++++++++++++++++ src/Magnum/AbstractTexture.h | 14 ++++++ src/Magnum/Implementation/TextureState.cpp | 19 ++++++++ src/Magnum/Implementation/TextureState.h | 2 + src/Magnum/Magnum.h | 1 + src/Magnum/MultisampleTexture.h | 50 ++++++++++++++++++++ src/Magnum/Test/MultisampleTextureGLTest.cpp | 48 +++++++++++++++---- 8 files changed, 168 insertions(+), 10 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 6ec01fbe5..409d5e9d3 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -100,7 +100,7 @@ following: @extension{ARB,provoking_vertex} | done @extension{ARB,seamless_cube_map} | done @extension{ARB,sync} | | -@extension{ARB,texture_multisample} | | +@extension{ARB,texture_multisample} | missing sample location queries and sample mask @extension{ARB,vertex_array_bgra} | done @subsection opengl-support-33 OpenGL 3.3 @@ -187,7 +187,7 @@ following: @extension{ARB,stencil_texturing} | | @extension{ARB,texture_buffer_range} | done @extension{ARB,texture_query_levels} | done (shading language only) -@extension{ARB,texture_storage_multisample} | | +@extension{ARB,texture_storage_multisample} | done @extension{ARB,texture_view} | | @extension{ARB,vertex_attrib_binding} | | diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index c940f0580..70f053657 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -885,6 +885,36 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te } #endif +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::storageMultisampleImplementationFallback(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) { + bindInternal(); + glTexImage2DMultisample(target, samples, GLenum(internalFormat), size.x(), size.y(), fixedSampleLocations); +} + +void AbstractTexture::storageMultisampleImplementationDefault(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) { + bindInternal(); + glTexStorage2DMultisample(target, samples, GLenum(internalFormat), size.x(), size.y(), fixedSampleLocations); +} + +void AbstractTexture::storageMultisampleImplementationDSA(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) { + glTextureStorage2DMultisampleEXT(_id, target, samples, GLenum(internalFormat), size.x(), size.y(), fixedSampleLocations); +} + +void AbstractTexture::storageMultisampleImplementationFallback(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) { + bindInternal(); + glTexImage3DMultisample(target, samples, GLenum(internalFormat), size.x(), size.y(), size.z(), fixedSampleLocations); +} + +void AbstractTexture::storageMultisampleImplementationDefault(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) { + bindInternal(); + glTexStorage3DMultisample(target, samples, GLenum(internalFormat), size.x(), size.y(), size.z(), fixedSampleLocations); +} + +void AbstractTexture::storageMultisampleImplementationDSA(const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) { + glTextureStorage3DMultisampleEXT(_id, target, samples, GLenum(internalFormat), size.x(), size.y(), size.z(), fixedSampleLocations); +} +#endif + #ifndef MAGNUM_TARGET_GLES void AbstractTexture::getImageImplementationDefault(const GLenum target, const GLint level, const ColorFormat format, const ColorType type, const std::size_t, GLvoid* const data) { bindInternal(); @@ -1092,6 +1122,16 @@ void AbstractTexture::DataHelper<3>::setStorage(AbstractTexture& texture, const (texture.*Context::current()->state().texture->storage3DImplementation)(target, levels, internalFormat, size); } +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::DataHelper<2>::setStorageMultisample(AbstractTexture& texture, const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) { + (texture.*Context::current()->state().texture->storage2DMultisampleImplementation)(target, samples, internalFormat, size, fixedSampleLocations); +} + +void AbstractTexture::DataHelper<3>::setStorageMultisample(AbstractTexture& texture, const GLenum target, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) { + (texture.*Context::current()->state().texture->storage3DMultisampleImplementation)(target, samples, internalFormat, size, fixedSampleLocations); +} +#endif + #ifndef MAGNUM_TARGET_GLES void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) { Buffer::unbind(Buffer::Target::PixelUnpack); diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index e6c62decf..c53b07b91 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -350,6 +350,16 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); #endif + #ifndef MAGNUM_TARGET_GLES + void MAGNUM_LOCAL storageMultisampleImplementationFallback(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector2i& size, GLboolean fixedsamplelocations); + void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector2i& size, GLboolean fixedsamplelocations); + void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector2i& size, GLboolean fixedsamplelocations); + + void MAGNUM_LOCAL storageMultisampleImplementationFallback(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations); + void MAGNUM_LOCAL storageMultisampleImplementationDefault(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations); + void MAGNUM_LOCAL storageMultisampleImplementationDSA(GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedsamplelocations); + #endif + #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL getImageImplementationDefault(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); void MAGNUM_LOCAL getImageImplementationDSA(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data); @@ -446,6 +456,8 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> { static void setStorage(AbstractTexture& texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); + static void setStorageMultisample(AbstractTexture& texture, GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector2i& size, GLboolean fixedSampleLocations); + static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference2D& image); #ifndef MAGNUM_TARGET_GLES2 static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image); @@ -481,6 +493,8 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> { static void setStorage(AbstractTexture& texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); + static void setStorageMultisample(AbstractTexture& texture, GLenum target, GLsizei samples, TextureFormat internalFormat, const Vector3i& size, GLboolean fixedSampleLocations); + static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference3D& image); #ifndef MAGNUM_TARGET_GLES2 static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage3D& image); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index e83e195e5..60d362f43 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -179,6 +179,25 @@ TextureState::TextureState(Context& context, std::vector& extension } #endif + #ifndef MAGNUM_TARGET_GLES + /* Storage implementation for multisample textures. The fallback doesn't + have DSA alternative, so it must be handled specially. */ + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ARB::texture_storage_multisample::string()); + + if(context.isExtensionSupported()) { + storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSA; + storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSA; + } else { + storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault; + storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault; + } + } else { + storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationFallback; + storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationFallback; + } + #endif + /* Anisotropic filter implementation */ if(context.isExtensionSupported()) { extensions.push_back(Extensions::GL::EXT::texture_filter_anisotropic::string()); diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 098080fb0..a3057eca4 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -54,6 +54,8 @@ struct TextureState { void(AbstractTexture::*storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&); void(AbstractTexture::*storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&); #ifndef MAGNUM_TARGET_GLES + void(AbstractTexture::*storage2DMultisampleImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&, GLboolean); + void(AbstractTexture::*storage3DMultisampleImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&, GLboolean); void(AbstractTexture::*getImageImplementation)(GLenum, GLint, ColorFormat, ColorType, std::size_t, GLvoid*); void(AbstractTexture::*image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*); #endif diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 9c676f40e..b48e0b054 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -594,6 +594,7 @@ class Mesh; class MeshView; #ifndef MAGNUM_TARGET_GLES +/* MultisampleTextureSampleLocations enum used only in the function */ template class MultisampleTexture; typedef MultisampleTexture<2> MultisampleTexture2D; typedef MultisampleTexture<3> MultisampleTexture2DArray; diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h index 2ad0abc34..05d54a2c3 100644 --- a/src/Magnum/MultisampleTexture.h +++ b/src/Magnum/MultisampleTexture.h @@ -44,6 +44,16 @@ namespace Implementation { template<> inline constexpr GLenum multisampleTextureTarget<3>() { return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; } } +/** +@brief Multisample texture sample locations + +@see @ref MultisampleTexture::setStorage() +*/ +enum class MultisampleTextureSampleLocations: GLboolean { + NotFixed = GL_FALSE, + Fixed = GL_TRUE +}; + /** @brief Mulitsample texture @@ -92,6 +102,46 @@ template class MultisampleTexture: public AbstractTextur return DataHelper::imageSize(*this, _target, 0); } + /** + * @brief Set storage + * @param samples Sample count + * @param internalFormat Internal format + * @param size %Texture size + * @param sampleLocations Whether to use fixed sample locations + * @return Reference to self (for method chaining) + * + * After calling this function the texture is immutable and calling + * @ref setStorage() again is not allowed. + * + * If @extension{EXT,direct_state_access} is not available, the texture + * is bound to some texture unit before the operation. If + * @extension{ARB,texture_storage_multisample} (part of OpenGL 4.3) is + * not available, the feature is emulated using plain + * @extension{ARB,texture_storage} functionality (which unfortunately + * doesn't have any DSA alternative, so the texture must be bound + * to some texture unit before). + * @see @ref maxColorSamples(), @ref maxDepthSamples(), + * @ref maxIntegerSamples(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} + * and @fn_gl{TexStorage2DMultisample}/@fn_gl{TexStorage3DMultisample} + * or @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}/ + * @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} + * eventually @fn_gl{TexImage2DMultisample}/@fn_gl{TexImage3DMultisample} + * @todoc Remove the workaround when it stops breaking Doxygen layout so badly + */ + /* The default parameter value was chosen based on discussion in + ARB_texture_multisample specs (fixed locations is treated as the + special case) */ + MultisampleTexture& setStorage(Int samples, TextureFormat internalFormat, const typename DimensionTraits::VectorType& size, MultisampleTextureSampleLocations sampleLocations = + #ifndef DOXYGEN_GENERATING_OUTPUT + MultisampleTextureSampleLocations::NotFixed + #else + NotFixed + #endif + ) { + DataHelper::setStorageMultisample(*this, _target, samples, internalFormat, size, GLboolean(sampleLocations)); + return *this; + } + /** @copydoc RectangleTexture::invalidateImage() */ void invalidateImage() { AbstractTexture::invalidateImage(0); } diff --git a/src/Magnum/Test/MultisampleTextureGLTest.cpp b/src/Magnum/Test/MultisampleTextureGLTest.cpp index dfbd2de98..e5b8115b4 100644 --- a/src/Magnum/Test/MultisampleTextureGLTest.cpp +++ b/src/Magnum/Test/MultisampleTextureGLTest.cpp @@ -26,6 +26,8 @@ #include #include "Magnum/MultisampleTexture.h" +#include "Magnum/TextureFormat.h" +#include "Magnum/Math/Vector3.h" #include "Magnum/Test/AbstractOpenGLTester.h" namespace Magnum { namespace Test { @@ -103,8 +105,8 @@ void MultisampleTextureGLTest::bind2D() { if(Context::current()->isExtensionSupported()) { CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setStorage(4, TextureFormat::RGBA8, {16, 16}); CORRADE_VERIFY(false); - CORRADE_SKIP("...but we don't have any function to do that yet."); } texture.bind(15); @@ -128,8 +130,8 @@ void MultisampleTextureGLTest::bind2DArray() { if(Context::current()->isExtensionSupported()) { CORRADE_EXPECT_FAIL("With ARB_multi_bind the texture must be associated with given target at least once before binding it."); + texture.setStorage(4, TextureFormat::RGBA8, {16, 16, 5}); CORRADE_VERIFY(false); - CORRADE_SKIP("...but we don't have any function to do that yet."); } texture.bind(15); @@ -149,42 +151,72 @@ void MultisampleTextureGLTest::storage2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - CORRADE_SKIP("Not implemented yet."); + MultisampleTexture2D texture; + texture.setStorage(4, TextureFormat::RGBA8, {16, 16}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(texture.imageSize(), Vector2i(16, 16)); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::storage2DArray() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - CORRADE_SKIP("Not implemented yet."); + MultisampleTexture2DArray texture; + texture.setStorage(4, TextureFormat::RGBA8, {16, 16, 5}); + + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_COMPARE(texture.imageSize(), Vector3i(16, 16, 5)); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::invalidateImage2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - CORRADE_SKIP("Multisample storage is not implemented yet."); + MultisampleTexture2D texture; + texture.setStorage(4, TextureFormat::RGBA8, {16, 16}); + texture.invalidateImage(); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::invalidateImage2DArray() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - CORRADE_SKIP("Multisample storage is not implemented yet."); + MultisampleTexture2DArray texture; + texture.setStorage(4, TextureFormat::RGBA8, {16, 16, 5}); + texture.invalidateImage(); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::invalidateSubImage2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - CORRADE_SKIP("Multisample storage is not implemented yet."); + MultisampleTexture2D texture; + texture.setStorage(4, TextureFormat::RGBA8, {16, 16}); + texture.invalidateSubImage({3, 4}, {5, 6}); + + MAGNUM_VERIFY_NO_ERROR(); } void MultisampleTextureGLTest::invalidateSubImage2DArray() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_multisample::string() + std::string(" is not supported.")); - CORRADE_SKIP("Multisample storage is not implemented yet."); + MultisampleTexture2DArray texture; + texture.setStorage(4, TextureFormat::RGBA8, {16, 16, 5}); + texture.invalidateSubImage({3, 4, 1}, {5, 6, 3}); + + MAGNUM_VERIFY_NO_ERROR(); } }} From ab6e645b0e13218ff69d75979a108e0fe1b1741f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 7 Apr 2014 22:59:13 +0200 Subject: [PATCH 133/141] Compressed formats are not available for multisample textures. --- src/Magnum/TextureFormat.h | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/Magnum/TextureFormat.h b/src/Magnum/TextureFormat.h index a1387b240..b173c7960 100644 --- a/src/Magnum/TextureFormat.h +++ b/src/Magnum/TextureFormat.h @@ -674,82 +674,94 @@ enum class TextureFormat: GLenum { #ifndef MAGNUM_TARGET_GLES /** - * Compressed red channel, normalized unsigned. + * Compressed red channel, normalized unsigned. **Not available on + * multisample textures.** * @requires_gl30 %Extension @extension{ARB,texture_rg} * @requires_gl Generic texture compression is not available in OpenGL ES. */ CompressedRed = GL_COMPRESSED_RED, /** - * Compressed red and green channel, normalized unsigned. + * Compressed red and green channel, normalized unsigned. **Not available + * on multisample textures.** * @requires_gl30 %Extension @extension{ARB,texture_rg} * @requires_gl Generic texture compression is not available in OpenGL ES. */ CompressedRG = GL_COMPRESSED_RG, /** - * Compressed RGB, normalized unsigned. + * Compressed RGB, normalized unsigned. **Not available on multisample + * textures.** * @requires_gl Generic texture compression is not available in OpenGL ES. */ CompressedRGB = GL_COMPRESSED_RGB, /** - * Compressed RGBA, normalized unsigned. + * Compressed RGBA, normalized unsigned. **Not available on multisample + * textures.** * @requires_gl Generic texture compression is not available in OpenGL ES. */ CompressedRGBA = GL_COMPRESSED_RGBA, /** - * RTGC compressed red channel, normalized unsigned. + * RTGC compressed red channel, normalized unsigned. **Not available on + * multisample textures.** * @requires_gl30 %Extension @extension{EXT,texture_compression_rgtc} * @requires_gl RGTC texture compression is not available in OpenGL ES. */ CompressedRedRtgc1 = GL_COMPRESSED_RED_RGTC1, /** - * RTGC compressed red and green channel, normalized unsigned. + * RTGC compressed red and green channel, normalized unsigned. **Not + * available on multisample textures.** * @requires_gl30 %Extension @extension{EXT,texture_compression_rgtc} * @requires_gl RGTC texture compression is not available in OpenGL ES. */ CompressedRGRgtc2 = GL_COMPRESSED_RG_RGTC2, /** - * RTGC compressed red channel, normalized signed. + * RTGC compressed red channel, normalized signed. **Not available on + * multisample textures.** * @requires_gl30 %Extension @extension{EXT,texture_compression_rgtc} * @requires_gl RGTC texture compression is not available in OpenGL ES. */ CompressedSignedRedRgtc1 = GL_COMPRESSED_SIGNED_RED_RGTC1, /** - * RTGC compressed red and green channel, normalized signed. + * RTGC compressed red and green channel, normalized signed. **Not + * available on multisample textures.** * @requires_gl30 %Extension @extension{EXT,texture_compression_rgtc} * @requires_gl RGTC texture compression is not available in OpenGL ES. */ CompressedSignedRGRgtc2 = GL_COMPRESSED_SIGNED_RG_RGTC2, /** - * BPTC compressed RGB, unsigned float. + * BPTC compressed RGB, unsigned float. **Not available on multisample + * textures.** * @requires_gl42 %Extension @extension{ARB,texture_compression_bptc} * @requires_gl BPTC texture compression is not available in OpenGL ES. */ CompressedRGBBptcUnsignedFloat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, /** - * BPTC compressed RGB, signed float. + * BPTC compressed RGB, signed float. **Not available on multisample + * textures.** * @requires_gl42 %Extension @extension{ARB,texture_compression_bptc} * @requires_gl BPTC texture compression is not available in OpenGL ES. */ CompressedRGBBptcSignedFloat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, /** - * BPTC compressed RGBA, normalized unsigned. + * BPTC compressed RGBA, normalized unsigned. **Not available on + * multisample textures.** * @requires_gl42 %Extension @extension{ARB,texture_compression_bptc} * @requires_gl BPTC texture compression is not available in OpenGL ES. */ CompressedRGBABptcUnorm = GL_COMPRESSED_RGBA_BPTC_UNORM, /** - * BPTC compressed sRGBA, normalized unsigned. + * BPTC compressed sRGBA, normalized unsigned. **Not available on + * multisample textures.** * @requires_gl42 %Extension @extension{ARB,texture_compression_bptc} * @requires_gl BPTC texture compression is not available in OpenGL ES. */ From b921d0c95c1840bdd1494c93f4052ef80732dfd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Apr 2014 00:53:18 +0200 Subject: [PATCH 134/141] Fix compilation on GCC 4.6. Can't have both constexpr and const. --- src/Magnum/AbstractTexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 70f053657..81c71fe9c 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -115,7 +115,7 @@ void AbstractTexture::unbindImplementationDefault(const GLint textureUnit) { #ifndef MAGNUM_TARGET_GLES void AbstractTexture::unbindImplementationMulti(const GLint textureUnit) { - constexpr static const GLuint zero = 0; + constexpr static GLuint zero = 0; glBindTextures(textureUnit, 1, &zero); } From 8533971931ffd24e9c17800f55f206aadba89bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Apr 2014 02:16:35 +0200 Subject: [PATCH 135/141] package: remove superfluous character. --- package/archlinux/PKGBUILD | 2 +- package/archlinux/PKGBUILD-mingw32 | 2 +- package/archlinux/PKGBUILD-release | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package/archlinux/PKGBUILD b/package/archlinux/PKGBUILD index 23bd12817..dc4913ad7 100644 --- a/package/archlinux/PKGBUILD +++ b/package/archlinux/PKGBUILD @@ -13,7 +13,7 @@ provides=('magnum-git') build() { mkdir -p "$startdir/build" - cd "$startdir/build/" + cd "$startdir/build" # Disable optimization (saves A LOT of compilation time) newcxxflags=$(echo $CXXFLAGS | sed s/-O.//g | sed s/-D_FORTIFY_SOURCE=.//g) diff --git a/package/archlinux/PKGBUILD-mingw32 b/package/archlinux/PKGBUILD-mingw32 index 276af9c95..a4b406ac8 100644 --- a/package/archlinux/PKGBUILD-mingw32 +++ b/package/archlinux/PKGBUILD-mingw32 @@ -12,7 +12,7 @@ options=('!buildflags' '!strip' 'staticlibs') build() { mkdir -p "$startdir/build-win" - cd "$startdir/build-win/" + cd "$startdir/build-win" unset LDFLAGS diff --git a/package/archlinux/PKGBUILD-release b/package/archlinux/PKGBUILD-release index fd9c48abd..74fc36444 100644 --- a/package/archlinux/PKGBUILD-release +++ b/package/archlinux/PKGBUILD-release @@ -13,7 +13,7 @@ options=('staticlibs') build() { mkdir -p "$startdir/build" - cd "$startdir/build/" + cd "$startdir/build" cmake .. \ -DCMAKE_BUILD_TYPE=Release \ From a08fa16d4ec7b594df1d10cd9b47380797bc2428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Apr 2014 02:14:57 +0200 Subject: [PATCH 136/141] modules: updated FindCorrade.cmake from Corrade repository. --- modules/FindCorrade.cmake | 48 ++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake index 18ce88964..90e038f31 100644 --- a/modules/FindCorrade.cmake +++ b/modules/FindCorrade.cmake @@ -3,7 +3,7 @@ # Basic usage: # find_package(Corrade [REQUIRED]) # This module tries to find Corrade library and then defines: -# CORRADE_FOUND - True if Corrade library is found +# CORRADE_FOUND - True if Corrade is found # CORRADE_INCLUDE_DIR - Root include dir # CORRADE_INTERCONNECT_LIBRARIES - Interconnect library and dependent # libraries @@ -14,9 +14,14 @@ # CORRADE_TESTSUITE_LIBRARIES - TestSuite library and dependent # libraries # CORRADE_RC_EXECUTABLE - Resource compiler executable +# The package is found if either debug or release version of each library is +# found. If both debug and release libraries are found, proper version is +# chosen based on actual build configuration of the project (i.e. Debug build +# is linked to debug libraries, Release build to release libraries). +# # Corrade configures the compiler to use C++11 standard. Additionally you can -# use CORRADE_CXX_FLAGS to enable additional pedantic set of warnings and enable -# hidden visibility by default. +# use CORRADE_CXX_FLAGS to enable additional pedantic set of warnings and +# enable hidden visibility by default. # # Features of found Corrade library are exposed in these variables: # CORRADE_GCC47_COMPATIBILITY - Defined if compiled with compatibility @@ -83,7 +88,7 @@ # The macro adds preprocessor directive CORRADE_STATIC_PLUGIN. Additional # libraries can be linked in via target_link_libraries(plugin_name ...). If # install_dir is set to CMAKE_CURRENT_BINARY_DIR (e.g. for testing purposes), -# no installation is performed. +# no installation rules are added. # # # Additionally these variables are defined for internal usage: @@ -93,6 +98,9 @@ # CORRADE_PLUGINMANAGER_LIBRARY - Plugin manager library (w/o # dependencies) # CORRADE_TESTSUITE_LIBRARY - TestSuite library (w/o dependencies) +# CORRADE_*_LIBRARY_DEBUG - Debug version of given library, if found +# CORRADE_*_LIBRARY_RELEASE - Release version of given library, if +# found # # @@ -121,10 +129,28 @@ # # Libraries -find_library(CORRADE_INTERCONNECT_LIBRARY CorradeInterconnect) -find_library(CORRADE_UTILITY_LIBRARY CorradeUtility) -find_library(CORRADE_PLUGINMANAGER_LIBRARY CorradePluginManager) -find_library(CORRADE_TESTSUITE_LIBRARY CorradeTestSuite) +foreach(_component Interconnect Utility PluginManager TestSuite) + string(TOUPPER ${_component} _COMPONENT) + + # Try to find both debug and release version + find_library(CORRADE_${_COMPONENT}_LIBRARY_DEBUG Corrade${_component}-d) + find_library(CORRADE_${_COMPONENT}_LIBRARY_RELEASE Corrade${_component}) + + # Set the _LIBRARY variable based on what was found + if(CORRADE_${_COMPONENT}_LIBRARY_DEBUG AND CORRADE_${_COMPONENT}_LIBRARY_RELEASE) + set(CORRADE_${_COMPONENT}_LIBRARY + debug ${CORRADE_${_COMPONENT}_LIBRARY_DEBUG} + optimized ${CORRADE_${_COMPONENT}_LIBRARY_RELEASE}) + elseif(CORRADE_${_COMPONENT}_LIBRARY_DEBUG) + set(CORRADE_${_COMPONENT}_LIBRARY ${CORRADE_${_COMPONENT}_LIBRARY_DEBUG}) + elseif(CORRADE_${_COMPONENT}_LIBRARY_RELEASE) + set(CORRADE_${_COMPONENT}_LIBRARY ${CORRADE_${_COMPONENT}_LIBRARY_RELEASE}) + endif() + + mark_as_advanced(CORRADE_${_COMPONENT}_LIBRARY_DEBUG + CORRADE_${_COMPONENT}_LIBRARY_RELEASE + CORRADE_${_COMPONENT}_LIBRARY) +endforeach() # RC executable find_program(CORRADE_RC_EXECUTABLE corrade-rc) @@ -222,11 +248,7 @@ if(CORRADE_TARGET_ANDROID) set(CORRADE_UTILITY_LIBRARIES ${CORRADE_UTILITY_LIBRARIES} log) endif() -mark_as_advanced(CORRADE_UTILITY_LIBRARY - CORRADE_INTERCONNECT_LIBRARY - CORRADE_PLUGINMANAGER_LIBRARY - CORRADE_TESTSUITE_LIBRARY - _CORRADE_INCLUDE_DIR +mark_as_advanced(_CORRADE_INCLUDE_DIR _CORRADE_MODULE_DIR) # Add Corrade dir to include path if this is deprecated build From 1e6e4c3f73c8595d5988650fd3ccded5c987ddd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Apr 2014 13:35:13 +0200 Subject: [PATCH 137/141] Install and find debug libraries with "-d" suffix. Makes it possible to have both debug and release libraries installed. If both libraries are present when finding the package, proper version is used based on what configuration is used in depending project. --- doc/building.dox | 6 +++ doc/cmake.dox | 5 ++ modules/FindMagnum.cmake | 73 ++++++++++++++++++++------ src/Magnum/Audio/CMakeLists.txt | 1 + src/Magnum/CMakeLists.txt | 5 +- src/Magnum/DebugTools/CMakeLists.txt | 1 + src/Magnum/MeshTools/CMakeLists.txt | 5 +- src/Magnum/Platform/CMakeLists.txt | 11 +++- src/Magnum/Primitives/CMakeLists.txt | 1 + src/Magnum/SceneGraph/CMakeLists.txt | 5 +- src/Magnum/Shaders/CMakeLists.txt | 1 + src/Magnum/Shapes/CMakeLists.txt | 1 + src/Magnum/Text/CMakeLists.txt | 1 + src/Magnum/TextureTools/CMakeLists.txt | 1 + 14 files changed, 96 insertions(+), 21 deletions(-) diff --git a/doc/building.dox b/doc/building.dox index 2173ab1de..56c24d996 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -134,6 +134,12 @@ plan to use them with shared libraries later, enable also position-independent code with `BUILD_STATIC_PIC`. If you want to build with another compiler (e.g. Clang), pass `-DCMAKE_CXX_COMPILER=clang++` to CMake. +Libraries built in `Debug` configuration (e.g. with `CMAKE_BUILD_TYPE` set to +`Debug`) have `-d` suffix to make it possible to have both debug and release +libraries installed alongside each other. Headers and other files are the same +for both. The library distinction is handled automatically when using %Magnum +in depending projects, see @ref cmake for more information. + %Magnum by default does not install `FindMagnum.cmake`, as you should bundle the module with your code instead of depending on it being in system location. You can install it by enabling `WITH_FIND_MODULE`. diff --git a/doc/cmake.dox b/doc/cmake.dox index d106817c5..81ea3723d 100644 --- a/doc/cmake.dox +++ b/doc/cmake.dox @@ -132,6 +132,11 @@ convenience aliases `MAGNUM_APPLICATION_LIBRARIES` / `MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES` and `MAGNUM_APPLICATION_INCLUDE_DIRS` / `MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS` to simplify porting. +The package is found if either debug or release version of each requested +library is found. If both debug and release libraries are found, proper version +is chosen based on actual build configuration of the project (i.e. `Debug` +build is linked to debug libraries, `Release` build to release libraries). + Features of found %Magnum library are exposed in these CMake variables, they are also available as preprocessor variables if including Magnum.h: diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index f4c822644..89bb4ed94 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -59,6 +59,12 @@ # MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES and MAGNUM_APPLICATION_INCLUDE_DIRS # / MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS to simplify porting. # +# The package is found if either debug or release version of each requested +# library is found. If both debug and release libraries are found, proper +# version is chosen based on actual build configuration of the project (i.e. +# Debug build is linked to debug libraries, Release build to release +# libraries). +# # Features of found Magnum library are exposed in these variables: # MAGNUM_BUILD_DEPRECATED - Defined if compiled with deprecated APIs # included @@ -75,13 +81,14 @@ # plugins (i.e. instead of `MagnumPlugins/` prefix). # # Additionally these variables are defined for internal usage: -# MAGNUM_INCLUDE_DIR - Root include dir (w/o -# dependencies) -# MAGNUM_LIBRARY - Magnum library (w/o -# dependencies) -# MAGNUM_*_LIBRARY - Component libraries (w/o -# dependencies) -# MAGNUM_LIBRARY_INSTALL_DIR - Library installation directory +# MAGNUM_INCLUDE_DIR - Root include dir (w/o dependencies) +# MAGNUM_LIBRARY - Magnum library (w/o dependencies) +# MAGNUM_LIBRARY_DEBUG - Debug version of Magnum library, if found +# MAGNUM_LIBRARY_RELEASE - Release version of Magnum library, if found +# MAGNUM_*_LIBRARY - Component libraries (w/o dependencies) +# MAGNUM_*_LIBRARY_DEBUG - Debug version of given library, if found +# MAGNUM_*_LIBRARY_RELEASE - Release version of given library, if found +# MAGNUM_LIBRARY_INSTALL_DIR - Library installation directory # MAGNUM_PLUGINS_INSTALL_DIR - Plugin installation directory # MAGNUM_PLUGINS_FONT_INSTALL_DIR - Font plugin installation # directory @@ -93,11 +100,10 @@ # directory # MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR - Audio omporter plugin # installation directory -# MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR - Installation dir for CMake -# Find* modules -# MAGNUM_INCLUDE_INSTALL_DIR - Header installation directory -# MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR - Plugin header installation -# directory +# MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR - Installation dir for CMake Find* +# modules +# MAGNUM_INCLUDE_INSTALL_DIR - Header installation directory +# MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR - Plugin header installation directory # # @@ -128,8 +134,23 @@ # Dependencies find_package(Corrade REQUIRED) -# Magnum library -find_library(MAGNUM_LIBRARY Magnum) +# Base Magnum library +find_library(MAGNUM_LIBRARY_DEBUG Magnum-d) +find_library(MAGNUM_LIBRARY_RELEASE Magnum) + +# Set the MAGNUM_LIBRARY variable based on what was found +if(MAGNUM_LIBRARY_DEBUG AND MAGNUM_LIBRARY_RELEASE) + set(MAGNUM_LIBRARY + debug ${MAGNUM_LIBRARY_DEBUG} + optimized ${MAGNUM_LIBRARY_RELEASE}) + get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY_DEBUG} PATH) +elseif(MAGNUM_LIBRARY_DEBUG) + set(MAGNUM_LIBRARY ${MAGNUM_LIBRARY_DEBUG}) + get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY_DEBUG} PATH) +elseif(MAGNUM_LIBRARY_RELEASE) + set(MAGNUM_LIBRARY ${MAGNUM_LIBRARY_RELEASE}) + get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY_RELEASE} PATH) +endif() # Root include dir find_path(MAGNUM_INCLUDE_DIR @@ -247,7 +268,20 @@ foreach(component ${Magnum_FIND_COMPONENTS}) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_SUFFIX Magnum/${component}) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES ${component}.h) - find_library(MAGNUM_${_COMPONENT}_LIBRARY Magnum${component}) + # Try to find both debug and release version + find_library(MAGNUM_${_COMPONENT}_LIBRARY_DEBUG Magnum${component}-d) + find_library(MAGNUM_${_COMPONENT}_LIBRARY_RELEASE Magnum${component}) + + # Set the _LIBRARY variable based on what was found + if(MAGNUM_${_COMPONENT}_LIBRARY_DEBUG AND MAGNUM_${_COMPONENT}_LIBRARY_RELEASE) + set(MAGNUM_${_COMPONENT}_LIBRARY + debug ${MAGNUM_${_COMPONENT}_LIBRARY_DEBUG} + optimized ${MAGNUM_${_COMPONENT}_LIBRARY_RELEASE}) + elseif(MAGNUM_${_COMPONENT}_LIBRARY_DEBUG) + set(MAGNUM_${_COMPONENT}_LIBRARY ${MAGNUM_${_COMPONENT}_LIBRARY_DEBUG}) + elseif(MAGNUM_${_COMPONENT}_LIBRARY_RELEASE) + set(MAGNUM_${_COMPONENT}_LIBRARY ${MAGNUM_${_COMPONENT}_LIBRARY_RELEASE}) + endif() endif() # Applications @@ -353,7 +387,11 @@ foreach(component ${Magnum_FIND_COMPONENTS}) set(Magnum_${component}_FOUND TRUE) # Don't expose variables w/o dependencies to end users - mark_as_advanced(FORCE MAGNUM_${_COMPONENT}_LIBRARY _MAGNUM_${_COMPONENT}_INCLUDE_DIR) + mark_as_advanced(FORCE + MAGNUM_${_COMPONENT}_LIBRARY_DEBUG + MAGNUM_${_COMPONENT}_LIBRARY_RELEASE + MAGNUM_${_COMPONENT}_LIBRARY + _MAGNUM_${_COMPONENT}_INCLUDE_DIR) # Global aliases for Windowless*Application and *Application components. # If already set, unset them to avoid ambiguity. @@ -397,6 +435,8 @@ set(MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR ${CMAKE_ROOT}/Modules) set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum) set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/MagnumPlugins) mark_as_advanced(FORCE + MAGNUM_LIBRARY_DEBUG + MAGNUM_LIBRARY_RELEASE MAGNUM_LIBRARY MAGNUM_INCLUDE_DIR MAGNUM_LIBRARY_INSTALL_DIR @@ -420,7 +460,6 @@ if(MAGNUM_BUILD_DEPRECATED) endif() # Get base plugin directory from main library location -get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY} PATH) set(MAGNUM_PLUGINS_DIR ${_MAGNUM_LIBRARY_PATH}/magnum CACHE PATH "Base directory where to look for Magnum plugins") diff --git a/src/Magnum/Audio/CMakeLists.txt b/src/Magnum/Audio/CMakeLists.txt index f4f13603e..f5b35054d 100644 --- a/src/Magnum/Audio/CMakeLists.txt +++ b/src/Magnum/Audio/CMakeLists.txt @@ -46,6 +46,7 @@ set(MagnumAudio_HEADERS visibility.h) add_library(MagnumAudio ${SHARED_OR_STATIC} ${MagnumAudio_SOURCES}) +set_target_properties(MagnumAudio PROPERTIES DEBUG_POSTFIX "-d") target_link_libraries(MagnumAudio ${CORRADE_PLUGINMANAGER_LIBRARIES} ${OPENAL_LIBRARY}) install(TARGETS MagnumAudio diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 72503b047..5ff0d2030 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -160,6 +160,7 @@ add_library(MagnumMathObjects OBJECT ${MagnumMath_SRCS}) add_library(Magnum ${SHARED_OR_STATIC} ${Magnum_SRCS} $) +set_target_properties(Magnum PROPERTIES DEBUG_POSTFIX "-d") # TODO: fix when CMake sets target_EXPORTS for OBJECT targets as well if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) @@ -235,7 +236,9 @@ if(BUILD_TESTS) # Libraries with graceful assert for testing add_library(MagnumMathTestLib ${SHARED_OR_STATIC} $) - set_target_properties(MagnumMathTestLib PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) + set_target_properties(MagnumMathTestLib PROPERTIES + COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT" + DEBUG_POSTFIX "-d") target_link_libraries(MagnumMathTestLib ${CORRADE_UTILITY_LIBRARY}) # On Windows we need to install first and then run the tests to avoid "DLL diff --git a/src/Magnum/DebugTools/CMakeLists.txt b/src/Magnum/DebugTools/CMakeLists.txt index 619c34fb1..4455b248e 100644 --- a/src/Magnum/DebugTools/CMakeLists.txt +++ b/src/Magnum/DebugTools/CMakeLists.txt @@ -51,6 +51,7 @@ set(MagnumDebugTools_HEADERS visibility.h) add_library(MagnumDebugTools ${SHARED_OR_STATIC} ${MagnumDebugTools_SRCS}) +set_target_properties(MagnumDebugTools PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property set_target_properties(MagnumDebugTools PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") diff --git a/src/Magnum/MeshTools/CMakeLists.txt b/src/Magnum/MeshTools/CMakeLists.txt index fb2b324ca..67f9a9a82 100644 --- a/src/Magnum/MeshTools/CMakeLists.txt +++ b/src/Magnum/MeshTools/CMakeLists.txt @@ -66,6 +66,7 @@ endif() add_library(MagnumMeshTools ${SHARED_OR_STATIC} $ ${MagnumMeshTools_GracefulAssert_SRCS}) +set_target_properties(MagnumMeshTools PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property set_target_properties(MagnumMeshTools PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") @@ -83,7 +84,9 @@ if(BUILD_TESTS) add_library(MagnumMeshToolsTestLib ${SHARED_OR_STATIC} $ ${MagnumMeshTools_GracefulAssert_SRCS}) - set_target_properties(MagnumMeshToolsTestLib PROPERTIES COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT -DMagnumMeshTools_EXPORTS") + set_target_properties(MagnumMeshToolsTestLib PROPERTIES + COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT -DMagnumMeshTools_EXPORTS" + DEBUG_POSTFIX "-d") target_link_libraries(MagnumMeshToolsTestLib Magnum) # On Windows we need to install first and then run the tests to avoid "DLL diff --git a/src/Magnum/Platform/CMakeLists.txt b/src/Magnum/Platform/CMakeLists.txt index 320cafdc1..e3a70508e 100644 --- a/src/Magnum/Platform/CMakeLists.txt +++ b/src/Magnum/Platform/CMakeLists.txt @@ -44,6 +44,7 @@ if(WITH_ANDROIDAPPLICATION) AndroidApplication.cpp Implementation/Egl.cpp ${ANDROID_NATIVE_APP_GLUE_SRC}) + set_target_properties(MagnumAndroidApplication PROPERTIES DEBUG_POSTFIX "-d") install(FILES AndroidApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumAndroidApplication RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} @@ -56,6 +57,7 @@ if(WITH_GLUTAPPLICATION) find_package(GLUT) if(GLUT_FOUND) add_library(MagnumGlutApplication STATIC GlutApplication.cpp) + set_target_properties(MagnumGlutApplication PROPERTIES DEBUG_POSTFIX "-d") install(FILES GlutApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumGlutApplication RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} @@ -72,6 +74,7 @@ if(WITH_SDL2APPLICATION) if(SDL2_FOUND) include_directories(${SDL2_INCLUDE_DIR}) add_library(MagnumSdl2Application STATIC Sdl2Application.cpp) + set_target_properties(MagnumSdl2Application PROPERTIES DEBUG_POSTFIX "-d") install(FILES Sdl2Application.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumSdl2Application RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} @@ -89,6 +92,7 @@ if(WITH_NACLAPPLICATION) endif() add_library(MagnumNaClApplication STATIC NaClApplication.cpp) + set_target_properties(MagnumNaClApplication PROPERTIES DEBUG_POSTFIX "-d") install(FILES NaClApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumNaClApplication RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} @@ -103,6 +107,7 @@ if(WITH_WINDOWLESSNACLAPPLICATION) endif() add_library(MagnumWindowlessNaClApplication STATIC WindowlessNaClApplication.cpp) + set_target_properties(MagnumWindowlessNaClApplication PROPERTIES DEBUG_POSTFIX "-d") install(FILES WindowlessNaClApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumWindowlessNaClApplication RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} @@ -128,6 +133,7 @@ if(WITH_GLXAPPLICATION) $ $ GlxApplication.cpp) + set_target_properties(MagnumGlxApplication PROPERTIES DEBUG_POSTFIX "-d") install(FILES GlxApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumGlxApplication RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} @@ -143,6 +149,7 @@ if(WITH_XEGLAPPLICATION) $ $ XEglApplication.cpp) + set_target_properties(MagnumXEglApplication PROPERTIES DEBUG_POSTFIX "-d") install(FILES XEglApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumXEglApplication RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} @@ -161,7 +168,9 @@ endif() if(WITH_WINDOWLESSGLXAPPLICATION) add_library(MagnumWindowlessGlxApplication STATIC WindowlessGlxApplication.cpp) # X11 macros are a mess, disable warnings for C-style casts - set_target_properties(MagnumWindowlessGlxApplication PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") + set_target_properties(MagnumWindowlessGlxApplication PROPERTIES + COMPILE_FLAGS "-Wno-old-style-cast" + DEBUG_POSTFIX "-d") install(FILES WindowlessGlxApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(TARGETS MagnumWindowlessGlxApplication RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} diff --git a/src/Magnum/Primitives/CMakeLists.txt b/src/Magnum/Primitives/CMakeLists.txt index b791282eb..6f2119939 100644 --- a/src/Magnum/Primitives/CMakeLists.txt +++ b/src/Magnum/Primitives/CMakeLists.txt @@ -53,6 +53,7 @@ set(MagnumPrimitives_HEADERS visibility.h) add_library(MagnumPrimitives ${SHARED_OR_STATIC} ${MagnumPrimitives_SRCS}) +set_target_properties(MagnumPrimitives PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property set_target_properties(MagnumPrimitives PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") diff --git a/src/Magnum/SceneGraph/CMakeLists.txt b/src/Magnum/SceneGraph/CMakeLists.txt index 4eaf4e304..4b4c42b4b 100644 --- a/src/Magnum/SceneGraph/CMakeLists.txt +++ b/src/Magnum/SceneGraph/CMakeLists.txt @@ -83,6 +83,7 @@ endif() add_library(MagnumSceneGraph ${SHARED_OR_STATIC} $ ${MagnumSceneGraph_GracefulAssert_SRCS}) +set_target_properties(MagnumSceneGraph PROPERTIES DEBUG_POSTFIX "-d") target_link_libraries(MagnumSceneGraph Magnum) install(TARGETS MagnumSceneGraph @@ -96,7 +97,9 @@ if(BUILD_TESTS) add_library(MagnumSceneGraphTestLib ${SHARED_OR_STATIC} $ ${MagnumSceneGraph_GracefulAssert_SRCS}) - set_target_properties(MagnumSceneGraphTestLib PROPERTIES COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT -DMagnumSceneGraph_EXPORTS") + set_target_properties(MagnumSceneGraphTestLib PROPERTIES + COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT -DMagnumSceneGraph_EXPORTS" + DEBUG_POSTFIX "-d") target_link_libraries(MagnumSceneGraphTestLib MagnumMathTestLib) # On Windows we need to install first and then run the tests to avoid "DLL diff --git a/src/Magnum/Shaders/CMakeLists.txt b/src/Magnum/Shaders/CMakeLists.txt index 8b2e16a16..6ffa51558 100644 --- a/src/Magnum/Shaders/CMakeLists.txt +++ b/src/Magnum/Shaders/CMakeLists.txt @@ -60,6 +60,7 @@ if(BUILD_STATIC) endif() add_library(MagnumShaders ${SHARED_OR_STATIC} ${MagnumShaders_SRCS}) +set_target_properties(MagnumShaders PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property set_target_properties(MagnumShaders PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") diff --git a/src/Magnum/Shapes/CMakeLists.txt b/src/Magnum/Shapes/CMakeLists.txt index 812b209f8..4c8669773 100644 --- a/src/Magnum/Shapes/CMakeLists.txt +++ b/src/Magnum/Shapes/CMakeLists.txt @@ -62,6 +62,7 @@ set(MagnumShapes_HEADERS visibility.h) add_library(MagnumShapes ${SHARED_OR_STATIC} ${MagnumShapes_SRCS}) +set_target_properties(MagnumShapes PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property set_target_properties(MagnumShapes PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") diff --git a/src/Magnum/Text/CMakeLists.txt b/src/Magnum/Text/CMakeLists.txt index 7206c9002..c742bd3f8 100644 --- a/src/Magnum/Text/CMakeLists.txt +++ b/src/Magnum/Text/CMakeLists.txt @@ -46,6 +46,7 @@ if(MAGNUM_BUILD_DEPRECATED) endif() add_library(MagnumText ${SHARED_OR_STATIC} ${MagnumText_SRCS}) +set_target_properties(MagnumText PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property set_target_properties(MagnumText PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") diff --git a/src/Magnum/TextureTools/CMakeLists.txt b/src/Magnum/TextureTools/CMakeLists.txt index aa8f6b4e5..19e06bb5c 100644 --- a/src/Magnum/TextureTools/CMakeLists.txt +++ b/src/Magnum/TextureTools/CMakeLists.txt @@ -41,6 +41,7 @@ if(BUILD_STATIC) endif() add_library(MagnumTextureTools ${SHARED_OR_STATIC} ${MagnumTextureTools_SRCS}) +set_target_properties(MagnumTextureTools PROPERTIES DEBUG_POSTFIX "-d") if(BUILD_STATIC_PIC) # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property set_target_properties(MagnumTextureTools PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") From bfe6c6fbb681a89bd53e6ad510c7bb0b88c7b1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Apr 2014 16:11:42 +0200 Subject: [PATCH 138/141] package: updated FindCorrade.cmake from Corrade repository. --- modules/FindCorrade.cmake | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake index 90e038f31..55077a0aa 100644 --- a/modules/FindCorrade.cmake +++ b/modules/FindCorrade.cmake @@ -71,15 +71,15 @@ # add_executable(app source1 source2 ... ${app_resources}) # # Add dynamic plugin. -# corrade_add_plugin(plugin_name install_dir metadata_file -# sources...) +# corrade_add_plugin(plugin_name debug_install_dir release_install_dir +# metadata_file sources...) # The macro adds preprocessor directive CORRADE_DYNAMIC_PLUGIN. Additional # libraries can be linked in via target_link_libraries(plugin_name ...). If -# install_dir is set to CMAKE_CURRENT_BINARY_DIR (e.g. for testing purposes), -# the files are copied directly, without the need to run `make install`. Note -# that the files are actually put into configuration-based subdirectory, i.e. -# ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}. See documentation of -# CMAKE_CFG_INTDIR variable for more information. +# debug_install_dir is set to CMAKE_CURRENT_BINARY_DIR (e.g. for testing +# purposes), the files are copied directly, without the need to perform install +# step. Note that the files are actually put into configuration-based +# subdirectory, i.e. ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}. See +# documentation of CMAKE_CFG_INTDIR variable for more information. # # # Add static plugin. @@ -90,6 +90,10 @@ # install_dir is set to CMAKE_CURRENT_BINARY_DIR (e.g. for testing purposes), # no installation rules are added. # +# Note that plugins built in debug configuration (e.g. with CMAKE_BUILD_TYPE +# set to Debug) have "-d" suffix to make it possible to have both debug and +# release plugins installed alongside each other. +# # # Additionally these variables are defined for internal usage: # CORRADE_INTERCONNECT_LIBRARY - Interconnect library (w/o From 5101e3a60c1d9b4c8c584136a340fc97d7d8e69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Apr 2014 16:10:23 +0200 Subject: [PATCH 139/141] Install also debug plugins to different location. Following changes done in Corrade. --- CMakeLists.txt | 18 ++- doc/building.dox | 12 +- doc/cmake.dox | 34 +++-- modules/FindMagnum.cmake | 122 ++++++++++++------ src/MagnumPlugins/CMakeLists.txt | 6 +- src/MagnumPlugins/MagnumFont/CMakeLists.txt | 2 +- .../MagnumFontConverter/CMakeLists.txt | 2 +- src/MagnumPlugins/ObjImporter/CMakeLists.txt | 2 +- .../TgaImageConverter/CMakeLists.txt | 2 +- src/MagnumPlugins/TgaImporter/CMakeLists.txt | 2 +- .../WavAudioImporter/CMakeLists.txt | 2 +- 11 files changed, 134 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3416841d9..e73164561 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -177,12 +177,18 @@ endif() include(CorradeLibSuffix) set(MAGNUM_BINARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/bin) set(MAGNUM_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) -set(MAGNUM_PLUGINS_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) -set(MAGNUM_PLUGINS_FONT_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fonts) -set(MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fontconverters) -set(MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/imageconverters) -set(MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/importers) -set(MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_DEBUG_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d) +set(MAGNUM_PLUGINS_RELEASE_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) +set(MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/audioimporters) set(MAGNUM_DATA_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/magnum) set(MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR ${CMAKE_ROOT}/Modules) set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum) diff --git a/doc/building.dox b/doc/building.dox index 56c24d996..c513a58da 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -134,11 +134,13 @@ plan to use them with shared libraries later, enable also position-independent code with `BUILD_STATIC_PIC`. If you want to build with another compiler (e.g. Clang), pass `-DCMAKE_CXX_COMPILER=clang++` to CMake. -Libraries built in `Debug` configuration (e.g. with `CMAKE_BUILD_TYPE` set to -`Debug`) have `-d` suffix to make it possible to have both debug and release -libraries installed alongside each other. Headers and other files are the same -for both. The library distinction is handled automatically when using %Magnum -in depending projects, see @ref cmake for more information. +Libraries and static plugins built in `Debug` configuration (e.g. with +`CMAKE_BUILD_TYPE` set to `Debug`) have `-d` suffix to make it possible to have +both debug and release libraries installed alongside each other. *Dynamic* +plugins in `Debug` configuration are installed to `magnum-d` subdirectory +instead of `magnum`. Headers and other files are the same for both. The library +and plugin distinction is handled semi-automatically when using %Magnum in +depending projects, see @ref cmake for more information. %Magnum by default does not install `FindMagnum.cmake`, as you should bundle the module with your code instead of depending on it being in system location. diff --git a/doc/cmake.dox b/doc/cmake.dox index 81ea3723d..d5b7aa086 100644 --- a/doc/cmake.dox +++ b/doc/cmake.dox @@ -51,17 +51,19 @@ variables: - `MAGNUM_FOUND` -- Whether the library was found - `MAGNUM_LIBRARIES` -- %Magnum library and dependent libraries - `MAGNUM_INCLUDE_DIRS` -- Root include dir and include dirs of dependencies -- `MAGNUM_PLUGINS_DIR` -- Base directory with plugins, defaults to `magnum/` - subdirectory of dir where Magnum library was found. You can modify it (e.g. - set it to `.` when deploying on Windows with plugins stored relatively to - the executable), the following `MAGNUM_PLUGINS_*_DIR` variables depend on - it. -- `MAGNUM_PLUGINS_FONT_DIR` -- Directory with font plugins -- `MAGNUM_PLUGINS_FONTCONVERTER_DIR` -- Directory with font converter plugins -- `MAGNUM_PLUGINS_IMAGECONVERTER_DIR` -- Directory with image converter +- `MAGNUM_PLUGINS_DIR` -- Base directory with dynamic plugins, defaults to + `magnum/` subdirectory of dir where Magnum library was found (or + `magnum-d/` in debug build). . You can modify it (e.g. set it to `.` when + deploying on Windows with plugins stored relatively to the executable), + the following `MAGNUM_PLUGINS_*_DIR` variables depend on it. +- `MAGNUM_PLUGINS_FONT_DIR` -- Directory with dynamic font plugins +- `MAGNUM_PLUGINS_FONTCONVERTER_DIR` -- Directory with dynamic font converter + plugins +- `MAGNUM_PLUGINS_IMAGECONVERTER_DIR` -- Directory with dynamic image + converter plugins +- `MAGNUM_PLUGINS_IMPORTER_DIR` -- Directory with dynamic importer plugins +- `MAGNUM_PLUGINS_AUDIOIMPORTER_DIR` -- Directory with dynamic audio importer plugins -- `MAGNUM_PLUGINS_IMPORTER_DIR` -- Directory with importer plugins -- `MAGNUM_PLUGINS_AUDIOIMPORTER_DIR` -- Directory with audio importer plugins However, this command will try to find only the base library, not the optional components. The base library depends on %Corrade and OpenGL libraries (or @@ -133,9 +135,15 @@ convenience aliases `MAGNUM_APPLICATION_LIBRARIES` / / `MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS` to simplify porting. The package is found if either debug or release version of each requested -library is found. If both debug and release libraries are found, proper version -is chosen based on actual build configuration of the project (i.e. `Debug` -build is linked to debug libraries, `Release` build to release libraries). +library (or plugin) is found. If both debug and release libraries (or plugins) +are found, proper version is chosen based on actual build configuration of the +project (i.e. `Debug` build is linked to debug libraries, `Release` build to +release libraries). Note that this autodetection might fail for the +`MAGNUM_PLUGINS_DIR` variable, i.e. you might need to switch it manually to +`magnum-d/` or `magnum/` subdirectory based on whether you want to dynamically +load plugins with or without debug information. You can also make use of +`CMAKE_BUILD_TYPE` or `CMAKE_CFG_INTDIR` CMake variables for compile-time +decision. Features of found %Magnum library are exposed in these CMake variables, they are also available as preprocessor variables if including Magnum.h: diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 89bb4ed94..68462478b 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -7,16 +7,19 @@ # MAGNUM_LIBRARIES - Magnum library and dependent libraries # MAGNUM_INCLUDE_DIRS - Root include dir and include dirs of # dependencies -# MAGNUM_PLUGINS_DIR - Base directory with plugins, defaults to -# `magnum/` subdirectory of dir where Magnum library was found. You can -# modify it (e.g. set it to `.` when deploying on Windows with plugins -# stored relatively to the executable), the following MAGNUM_PLUGINS_*_DIR -# variables depend on it. -# MAGNUM_PLUGINS_FONT_DIR - Directory with font plugins -# MAGNUM_PLUGINS_FONTCONVERTER_DIR - Directory with font converter plugins -# MAGNUM_PLUGINS_IMAGECONVERTER_DIR - Directory with image converter plugins -# MAGNUM_PLUGINS_IMPORTER_DIR - Directory with importer plugins -# MAGNUM_PLUGINS_AUDIOIMPORTER_DIR - Directory with audio importer plugins +# MAGNUM_PLUGINS_DIR - Base directory with dynamic plugins, defaults +# to magnum/ subdirectory of dir where Magnum library was found (or magnum-d/ +# in debug build). You can modify it (e.g. set it to `.` when deploying on +# Windows with plugins stored relatively to the executable), the following +# MAGNUM_PLUGINS_*_DIR variables depend on it. +# MAGNUM_PLUGINS_FONT_DIR - Directory with dynamic font plugins +# MAGNUM_PLUGINS_FONTCONVERTER_DIR - Directory with dynamic font converter +# plugins +# MAGNUM_PLUGINS_IMAGECONVERTER_DIR - Directory with dynamic image converter +# plugins +# MAGNUM_PLUGINS_IMPORTER_DIR - Directory with dynamic importer plugins +# MAGNUM_PLUGINS_AUDIOIMPORTER_DIR - Directory with dynamic audio importer +# plugins # This command will try to find only the base library, not the optional # components. The base library depends on Corrade and OpenGL libraries (or # OpenGL ES libraries). Additional dependencies are specified by the @@ -60,10 +63,15 @@ # / MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS to simplify porting. # # The package is found if either debug or release version of each requested -# library is found. If both debug and release libraries are found, proper -# version is chosen based on actual build configuration of the project (i.e. -# Debug build is linked to debug libraries, Release build to release -# libraries). +# library (or plugin) is found. If both debug and release libraries (or +# plugins) are found, proper version is chosen based on actual build +# configuration of the project (i.e. Debug build is linked to debug libraries, +# Release build to release libraries). Note that this autodetection might fail +# for the MAGNUM_PLUGINS_DIR variable, i.e. you might need to switch it +# manually to magnum-d/ or magnum/ subdirectory based on whether you want +# to dynamically load plugins with or without debug information. You can also +# make use of CMAKE_BUILD_TYPE or CMAKE_CFG_INTDIR CMake variables for +# compile-time decision. # # Features of found Magnum library are exposed in these variables: # MAGNUM_BUILD_DEPRECATED - Defined if compiled with deprecated APIs @@ -89,17 +97,17 @@ # MAGNUM_*_LIBRARY_DEBUG - Debug version of given library, if found # MAGNUM_*_LIBRARY_RELEASE - Release version of given library, if found # MAGNUM_LIBRARY_INSTALL_DIR - Library installation directory -# MAGNUM_PLUGINS_INSTALL_DIR - Plugin installation directory -# MAGNUM_PLUGINS_FONT_INSTALL_DIR - Font plugin installation +# MAGNUM_PLUGINS_[DEBUG|RELEASE]_INSTALL_DIR - Plugin installation directory +# MAGNUM_PLUGINS_FONT_[DEBUG|RELEASE]_INSTALL_DIR - Font plugin installation # directory -# MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR - Font converter plugin -# installation directory -# MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR - Image converter plugin -# installation directory -# MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR - Importer plugin installation -# directory -# MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR - Audio omporter plugin +# MAGNUM_PLUGINS_FONTCONVERTER_[DEBUG|RELEASE]_INSTALL_DIR - Font converter +# plugin installation directory +# MAGNUM_PLUGINS_IMAGECONVERTER_[DEBUG|RELEASE]_INSTALL_DIR - Image converter +# plugin installation directory +# MAGNUM_PLUGINS_IMPORTER_[DEBUG|RELEASE]_INSTALL_DIR - Importer plugin # installation directory +# MAGNUM_PLUGINS_AUDIOIMPORTER_[DEBUG|RELEASE]_INSTALL_DIR - Audio importer +# plugin installation directory # MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR - Installation dir for CMake Find* # modules # MAGNUM_INCLUDE_INSTALL_DIR - Header installation directory @@ -138,15 +146,21 @@ find_package(Corrade REQUIRED) find_library(MAGNUM_LIBRARY_DEBUG Magnum-d) find_library(MAGNUM_LIBRARY_RELEASE Magnum) -# Set the MAGNUM_LIBRARY variable based on what was found +# Set the MAGNUM_LIBRARY variable based on what was found, use that information +# to guess also build type of dynamic plugins if(MAGNUM_LIBRARY_DEBUG AND MAGNUM_LIBRARY_RELEASE) set(MAGNUM_LIBRARY debug ${MAGNUM_LIBRARY_DEBUG} optimized ${MAGNUM_LIBRARY_RELEASE}) get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY_DEBUG} PATH) + # TODO: how to handle this with MSVC and other multi-configuration tools? + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(_MAGNUM_PLUGINS_DIR_SUFFIX "-d") + endif() elseif(MAGNUM_LIBRARY_DEBUG) set(MAGNUM_LIBRARY ${MAGNUM_LIBRARY_DEBUG}) get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY_DEBUG} PATH) + set(_MAGNUM_PLUGINS_DIR_SUFFIX "-d") elseif(MAGNUM_LIBRARY_RELEASE) set(MAGNUM_LIBRARY ${MAGNUM_LIBRARY_RELEASE}) get_filename_component(_MAGNUM_LIBRARY_PATH ${MAGNUM_LIBRARY_RELEASE} PATH) @@ -259,8 +273,30 @@ foreach(component ${Magnum_FIND_COMPONENTS}) # break something else set(_tmp_prefixes ${CMAKE_FIND_LIBRARY_PREFIXES}) set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} "") + find_library(MAGNUM_${_COMPONENT}_LIBRARY ${component} PATH_SUFFIXES magnum/${_MAGNUM_${_COMPONENT}_PATH_SUFFIX}) + + # Try to find both debug and release version. Dynamic and static debug + # libraries are on different places. + find_library(MAGNUM_${_COMPONENT}_LIBRARY_DEBUG ${component} + PATH_SUFFIXES magnum-d/${_MAGNUM_${_COMPONENT}_PATH_SUFFIX}) + find_library(MAGNUM_${_COMPONENT}_LIBRARY_DEBUG ${component}-d + PATH_SUFFIXES magnum/${_MAGNUM_${_COMPONENT}_PATH_SUFFIX}) + find_library(MAGNUM_${_COMPONENT}_LIBRARY_RELEASE ${component} + PATH_SUFFIXES magnum/${_MAGNUM_${_COMPONENT}_PATH_SUFFIX}) + + # Set the _LIBRARY variable based on what was found + if(MAGNUM_${_COMPONENT}_LIBRARY_DEBUG AND MAGNUM_${_COMPONENT}_LIBRARY_RELEASE) + set(MAGNUM_${_COMPONENT}_LIBRARY + debug ${MAGNUM_${_COMPONENT}_LIBRARY_DEBUG} + optimized ${MAGNUM_${_COMPONENT}_LIBRARY_RELEASE}) + elseif(MAGNUM_${_COMPONENT}_LIBRARY_DEBUG) + set(MAGNUM_${_COMPONENT}_LIBRARY ${MAGNUM_${_COMPONENT}_LIBRARY_DEBUG}) + elseif(MAGNUM_${_COMPONENT}_LIBRARY_RELEASE) + set(MAGNUM_${_COMPONENT}_LIBRARY ${MAGNUM_${_COMPONENT}_LIBRARY_RELEASE}) + endif() + set(CMAKE_FIND_LIBRARY_PREFIXES ${_tmp_prefixes}) # Set library defaults, find the library @@ -425,12 +461,18 @@ find_package_handle_standard_args(Magnum # Installation dirs include(CorradeLibSuffix) set(MAGNUM_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) -set(MAGNUM_PLUGINS_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) -set(MAGNUM_PLUGINS_FONT_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fonts) -set(MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fontconverters) -set(MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/imageconverters) -set(MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/importers) -set(MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_DEBUG_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d) +set(MAGNUM_PLUGINS_RELEASE_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) +set(MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fonts) +set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fontconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/imageconverters) +set(MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/importers) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/audioimporters) +set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/audioimporters) set(MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR ${CMAKE_ROOT}/Modules) set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum) set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/MagnumPlugins) @@ -440,12 +482,18 @@ mark_as_advanced(FORCE MAGNUM_LIBRARY MAGNUM_INCLUDE_DIR MAGNUM_LIBRARY_INSTALL_DIR - MAGNUM_PLUGINS_INSTALL_DIR - MAGNUM_PLUGINS_FONT_INSTALL_DIR - MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR - MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR - MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR - MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR + MAGNUM_PLUGINS_DEBUG_INSTALL_DIR + MAGNUM_PLUGINS_RELEASE_INSTALL_DIR + MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR + MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR + MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR + MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_INSTALL_DIR + MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_INSTALL_DIR + MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_INSTALL_DIR + MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR + MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR + MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_INSTALL_DIR + MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_INSTALL_DIR MAGNUM_CMAKE_MODULE_INSTALL_DIR MAGNUM_INCLUDE_INSTALL_DIR MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR) @@ -460,7 +508,7 @@ if(MAGNUM_BUILD_DEPRECATED) endif() # Get base plugin directory from main library location -set(MAGNUM_PLUGINS_DIR ${_MAGNUM_LIBRARY_PATH}/magnum +set(MAGNUM_PLUGINS_DIR ${_MAGNUM_LIBRARY_PATH}/magnum${_MAGNUM_PLUGINS_DIR_SUFFIX} CACHE PATH "Base directory where to look for Magnum plugins") # Plugin directories diff --git a/src/MagnumPlugins/CMakeLists.txt b/src/MagnumPlugins/CMakeLists.txt index 549a69ba0..59dab5adb 100644 --- a/src/MagnumPlugins/CMakeLists.txt +++ b/src/MagnumPlugins/CMakeLists.txt @@ -24,11 +24,11 @@ # # Wrapper for creating given plugin type -macro(add_plugin) +macro(add_plugin plugin_name debug_install_dir release_install_dir metadata_file) if(NOT BUILD_STATIC) - corrade_add_plugin(${ARGN}) + corrade_add_plugin(${plugin_name} ${debug_install_dir} ${release_install_dir} ${metadata_file} ${ARGN}) else() - corrade_add_static_plugin(${ARGN}) + corrade_add_static_plugin(${plugin_name} ${release_install_dir} ${metadata_file} ${ARGN}) endif() endmacro() diff --git a/src/MagnumPlugins/MagnumFont/CMakeLists.txt b/src/MagnumPlugins/MagnumFont/CMakeLists.txt index bc68bb215..54026939f 100644 --- a/src/MagnumPlugins/MagnumFont/CMakeLists.txt +++ b/src/MagnumPlugins/MagnumFont/CMakeLists.txt @@ -32,7 +32,7 @@ set(MagnumFont_HEADERS add_library(MagnumFontObjects OBJECT ${MagnumFont_SOURCES}) set_target_properties(MagnumFontObjects PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") -add_plugin(MagnumFont ${MAGNUM_PLUGINS_FONT_INSTALL_DIR} +add_plugin(MagnumFont ${MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR} MagnumFont.conf $ pluginRegistration.cpp) diff --git a/src/MagnumPlugins/MagnumFontConverter/CMakeLists.txt b/src/MagnumPlugins/MagnumFontConverter/CMakeLists.txt index d50d535a1..e171f6c81 100644 --- a/src/MagnumPlugins/MagnumFontConverter/CMakeLists.txt +++ b/src/MagnumPlugins/MagnumFontConverter/CMakeLists.txt @@ -32,7 +32,7 @@ set(MagnumFontConverter_HEADERS add_library(MagnumFontConverterObjects OBJECT ${MagnumFontConverter_SOURCES}) set_target_properties(MagnumFontConverterObjects PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") -add_plugin(MagnumFontConverter ${MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR} +add_plugin(MagnumFontConverter ${MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_INSTALL_DIR} MagnumFontConverter.conf $ pluginRegistration.cpp) diff --git a/src/MagnumPlugins/ObjImporter/CMakeLists.txt b/src/MagnumPlugins/ObjImporter/CMakeLists.txt index 5ab131c03..63a09e70b 100644 --- a/src/MagnumPlugins/ObjImporter/CMakeLists.txt +++ b/src/MagnumPlugins/ObjImporter/CMakeLists.txt @@ -28,7 +28,7 @@ if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) set_target_properties(ObjImporterObjects PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") endif() -add_plugin(ObjImporter ${MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR} +add_plugin(ObjImporter ${MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR} ObjImporter.conf $ pluginRegistration.cpp) diff --git a/src/MagnumPlugins/TgaImageConverter/CMakeLists.txt b/src/MagnumPlugins/TgaImageConverter/CMakeLists.txt index 5d0f72443..d0f03e2b8 100644 --- a/src/MagnumPlugins/TgaImageConverter/CMakeLists.txt +++ b/src/MagnumPlugins/TgaImageConverter/CMakeLists.txt @@ -32,7 +32,7 @@ set(TgaImageConverter_HEADERS add_library(TgaImageConverterObjects OBJECT ${TgaImageConverter_SRCS}) set_target_properties(TgaImageConverterObjects PROPERTIES COMPILE_FLAGS "-DTgaImageConverterObjects_EXPORTS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") -add_plugin(TgaImageConverter ${MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR} +add_plugin(TgaImageConverter ${MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_INSTALL_DIR} TgaImageConverter.conf $ pluginRegistration.cpp) diff --git a/src/MagnumPlugins/TgaImporter/CMakeLists.txt b/src/MagnumPlugins/TgaImporter/CMakeLists.txt index 6d214d263..05633463d 100644 --- a/src/MagnumPlugins/TgaImporter/CMakeLists.txt +++ b/src/MagnumPlugins/TgaImporter/CMakeLists.txt @@ -33,7 +33,7 @@ set(TgaImporter_HEADERS add_library(TgaImporterObjects OBJECT ${TgaImporter_SRCS}) set_target_properties(TgaImporterObjects PROPERTIES COMPILE_FLAGS "-DTgaImporterObjects_EXPORTS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") -add_plugin(TgaImporter ${MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR} +add_plugin(TgaImporter ${MAGNUM_PLUGINS_IMPORTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_IMPORTER_RELEASE_INSTALL_DIR} TgaImporter.conf $ pluginRegistration.cpp) diff --git a/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt b/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt index 7f04461cc..1ba650e7a 100644 --- a/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt +++ b/src/MagnumPlugins/WavAudioImporter/CMakeLists.txt @@ -39,7 +39,7 @@ if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) set_target_properties(WavAudioImporterObjects PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") endif() -add_plugin(WavAudioImporter ${MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR} +add_plugin(WavAudioImporter ${MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_INSTALL_DIR} ${MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_INSTALL_DIR} WavAudioImporter.conf $ pluginRegistration.cpp) From 4808b516ccabba35cedcd7fcfb3134b168196252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Apr 2014 16:27:52 +0200 Subject: [PATCH 140/141] package: build both debug and release libs in PKGBUILD-release. --- package/archlinux/PKGBUILD-release | 35 ++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/package/archlinux/PKGBUILD-release b/package/archlinux/PKGBUILD-release index 74fc36444..547900941 100644 --- a/package/archlinux/PKGBUILD-release +++ b/package/archlinux/PKGBUILD-release @@ -2,19 +2,44 @@ pkgname=magnum pkgver=dev.release pkgrel=1 -pkgdesc="C++11 and OpenGL 2D/3D graphics engine" +pkgdesc="C++11 and OpenGL 2D/3D graphics engine (debug+release libs)" arch=('i686' 'x86_64') url="http://mosra.cz/blog/magnum.php" license=('MIT') depends=('corrade' 'openal' 'sdl2' 'freeglut') makedepends=('cmake' 'ninja') +options=('!strip' 'staticlibs') provides=('magnum-git') -options=('staticlibs') build() { mkdir -p "$startdir/build" cd "$startdir/build" + cmake .. \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DWITH_AUDIO=ON \ + -DWITH_GLUTAPPLICATION=ON \ + -DWITH_GLXAPPLICATION=ON \ + -DWITH_SDL2APPLICATION=ON \ + -DWITH_WINDOWLESSGLXAPPLICATION=ON \ + -DWITH_MAGNUMFONT=ON \ + -DWITH_MAGNUMFONTCONVERTER=ON \ + -DWITH_OBJIMPORTER=ON \ + -DWITH_TGAIMAGECONVERTER=ON \ + -DWITH_TGAIMPORTER=ON \ + -DWITH_WAVAUDIOIMPORTER=ON \ + -DWITH_DISTANCEFIELDCONVERTER=ON \ + -DWITH_FONTCONVERTER=ON \ + -DWITH_MAGNUMINFO=ON \ + -DBUILD_TESTS=ON \ + -DBUILD_GL_TESTS=ON \ + -G Ninja + ninja + + mkdir -p "$startdir/build-release" + cd "$startdir/build-release" + cmake .. \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ @@ -41,9 +66,15 @@ build() { check() { cd "$startdir/build" ctest --output-on-failure -j5 + + cd "$startdir/build-release" + ctest --output-on-failure -j5 } package() { cd "$startdir/build" DESTDIR="$pkgdir/" ninja install + + cd "$startdir/build-release" + DESTDIR="$pkgdir/" ninja install/strip } From 6c56012431104c35b2c5268490331ddb48547091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 8 Apr 2014 20:31:45 +0200 Subject: [PATCH 141/141] package: strip CI build. --- package/ci/jenkins-mingw32.xml | 2 +- package/ci/jenkins-nacl.xml | 2 +- package/ci/jenkins.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package/ci/jenkins-mingw32.xml b/package/ci/jenkins-mingw32.xml index 7f4a1f52e..9cf01d7de 100644 --- a/package/ci/jenkins-mingw32.xml +++ b/package/ci/jenkins-mingw32.xml @@ -97,7 +97,7 @@ cmake .. \ -G Ninja ninja -ninja install +ninja install/strip ]]> diff --git a/package/ci/jenkins-nacl.xml b/package/ci/jenkins-nacl.xml index 5d19c1e07..2cccbe67b 100644 --- a/package/ci/jenkins-nacl.xml +++ b/package/ci/jenkins-nacl.xml @@ -89,7 +89,7 @@ cmake .. \ -G Ninja ninja -ninja install +ninja install/strip ]]> diff --git a/package/ci/jenkins.xml b/package/ci/jenkins.xml index b6cbc71f5..b8038faaf 100644 --- a/package/ci/jenkins.xml +++ b/package/ci/jenkins.xml @@ -154,7 +154,7 @@ cmake .. \ ninja ctest --output-on-failure -E GLTest -j5 || true -ninja install +ninja install/strip ]]>