Browse Source

Merge branch 'master' into compatibility

Conflicts:
	src/Magnum/AbstractTexture.cpp
	src/Magnum/Context.cpp
	src/Magnum/CubeMapTexture.h
	src/Magnum/CubeMapTextureArray.h
	src/Magnum/Magnum.h
	src/Magnum/MeshTools/Duplicate.h
	src/Magnum/Platform/Sdl2Application.h
	src/Magnum/SceneGraph/Object.hpp
	src/Magnum/Shader.cpp
	src/Magnum/Shapes/Test/ShapeTest.cpp
	src/Magnum/Test/AbstractShaderProgramTest.cpp
	src/Magnum/Test/ColorTest.cpp
Vladimír Vondruš 12 years ago
parent
commit
f923a36d3a
  1. 58
      CMakeLists.txt
  2. 14
      Doxyfile
  3. 1
      README.md
  4. 23
      doc/best-practices.dox
  5. 136
      doc/building.dox
  6. 35
      doc/cmake.dox
  7. 1
      doc/mainpage.dox
  8. 120
      doc/matrix-vector.dox
  9. 3
      doc/opengl-mapping.dox
  10. 13
      doc/opengl-support.dox
  11. 14
      doc/platform.dox
  12. 17
      doc/portability.dox
  13. 58
      doc/shapes.dox
  14. 71
      doc/types.dox
  15. 76
      modules/FindCorrade.cmake
  16. 227
      modules/FindMagnum.cmake
  17. 6
      modules/FindOpenGLES3.cmake
  18. 5
      package/archlinux/PKGBUILD
  19. 42
      package/archlinux/PKGBUILD-android-arm
  20. 42
      package/archlinux/PKGBUILD-android-x86
  21. 3
      package/archlinux/PKGBUILD-clang
  22. 3
      package/archlinux/PKGBUILD-clang-libc++
  23. 3
      package/archlinux/PKGBUILD-emscripten
  24. 3
      package/archlinux/PKGBUILD-es2
  25. 3
      package/archlinux/PKGBUILD-es2desktop
  26. 3
      package/archlinux/PKGBUILD-es3
  27. 3
      package/archlinux/PKGBUILD-es3desktop
  28. 3
      package/archlinux/PKGBUILD-gcc46
  29. 3
      package/archlinux/PKGBUILD-gcc47
  30. 3
      package/archlinux/PKGBUILD-gcc49
  31. 4
      package/archlinux/PKGBUILD-mingw32
  32. 2
      package/archlinux/PKGBUILD-nacl-glibc
  33. 4
      package/archlinux/PKGBUILD-nacl-newlib
  34. 40
      package/archlinux/PKGBUILD-release
  35. 1
      package/archlinux/magnum-git/PKGBUILD
  36. 1
      package/ci/jenkins-emscripten.xml
  37. 2
      package/ci/jenkins-gltests.xml
  38. 3
      package/ci/jenkins-mingw32.xml
  39. 3
      package/ci/jenkins-nacl.xml
  40. 11
      package/ci/jenkins.xml
  41. 1
      package/debian/rules
  42. 77
      src/Magnum/AbstractShaderProgram.cpp
  43. 156
      src/Magnum/AbstractShaderProgram.h
  44. 211
      src/Magnum/AbstractTexture.cpp
  45. 145
      src/Magnum/AbstractTexture.h
  46. 1
      src/Magnum/Audio/CMakeLists.txt
  47. 39
      src/Magnum/Buffer.h
  48. 9
      src/Magnum/CMakeLists.txt
  49. 110
      src/Magnum/Context.cpp
  50. 28
      src/Magnum/Context.h
  51. 30
      src/Magnum/CubeMapTexture.h
  52. 28
      src/Magnum/CubeMapTextureArray.h
  53. 1
      src/Magnum/DebugTools/CMakeLists.txt
  54. 7
      src/Magnum/Extensions.h
  55. 4
      src/Magnum/Image.h
  56. 59
      src/Magnum/Implementation/TextureState.cpp
  57. 12
      src/Magnum/Implementation/TextureState.h
  58. 5
      src/Magnum/Implementation/setupDriverWorkarounds.cpp
  59. 54
      src/Magnum/Magnum.h
  60. 14
      src/Magnum/Math/Angle.h
  61. 4
      src/Magnum/Math/Complex.h
  62. 9
      src/Magnum/Math/Functions.h
  63. 2
      src/Magnum/Math/TypeTraits.h
  64. 3
      src/Magnum/Math/Vector.h
  65. 6
      src/Magnum/Mesh.cpp
  66. 32
      src/Magnum/Mesh.h
  67. 7
      src/Magnum/MeshTools/CMakeLists.txt
  68. 17
      src/Magnum/MeshTools/CombineIndexedArrays.cpp
  69. 22
      src/Magnum/MeshTools/CombineIndexedArrays.h
  70. 157
      src/Magnum/MeshTools/Compile.cpp
  71. 81
      src/Magnum/MeshTools/Compile.h
  72. 2
      src/Magnum/MeshTools/CompressIndices.h
  73. 5
      src/Magnum/MeshTools/Duplicate.h
  74. 206
      src/Magnum/MeshTools/Interleave.h
  75. 57
      src/Magnum/MeshTools/Test/InterleaveTest.cpp
  76. 3
      src/Magnum/MeshView.h
  77. 78
      src/Magnum/MultisampleTexture.h
  78. 32
      src/Magnum/Platform/AbstractXApplication.h
  79. 266
      src/Magnum/Platform/AndroidApplication.cpp
  80. 594
      src/Magnum/Platform/AndroidApplication.h
  81. 34
      src/Magnum/Platform/CMakeLists.txt
  82. 25
      src/Magnum/Platform/GlutApplication.cpp
  83. 195
      src/Magnum/Platform/GlutApplication.h
  84. 27
      src/Magnum/Platform/GlxApplication.h
  85. 54
      src/Magnum/Platform/Implementation/Egl.cpp
  86. 33
      src/Magnum/Platform/Implementation/Egl.h
  87. 42
      src/Magnum/Platform/Implementation/EglContextHandler.cpp
  88. 3
      src/Magnum/Platform/Implementation/EglContextHandler.h
  89. 117
      src/Magnum/Platform/NaClApplication.h
  90. 5
      src/Magnum/Platform/Sdl2Application.cpp
  91. 198
      src/Magnum/Platform/Sdl2Application.h
  92. 41
      src/Magnum/Platform/WindowlessGlxApplication.h
  93. 41
      src/Magnum/Platform/WindowlessNaClApplication.h
  94. 36
      src/Magnum/Platform/XEglApplication.h
  95. 26
      src/Magnum/Platform/magnum-info.cpp
  96. 1
      src/Magnum/Primitives/CMakeLists.txt
  97. 2
      src/Magnum/Query.cpp
  98. 8
      src/Magnum/Query.h
  99. 53
      src/Magnum/RectangleTexture.h
  100. 9
      src/Magnum/Renderer.h
  101. Some files were not shown because too many files have changed in this diff Show More

58
CMakeLists.txt

@ -41,7 +41,7 @@ option(WITH_FIND_MODULE "Install FindMagnum.cmake module into CMake's module dir
# Parts of the library # Parts of the library
option(WITH_AUDIO "Build Audio library" OFF) option(WITH_AUDIO "Build Audio library" OFF)
option(WITH_DEBUGTOOLS "Build DebugTools library" ON) 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_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_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) cmake_dependent_option(WITH_SHADERS "Build Shaders library" ON "NOT WITH_DEBUGTOOLS" ON)
@ -49,23 +49,35 @@ cmake_dependent_option(WITH_SHAPES "Build Shapes library" ON "NOT WITH_DEBUGTOOL
option(WITH_TEXT "Build Text library" ON) option(WITH_TEXT "Build Text library" ON)
cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT WITH_TEXT;NOT WITH_DISTANCEFIELDCONVERTER" 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) if(CORRADE_TARGET_NACL)
option(WITH_NACLAPPLICATION "Build NaClApplication library" OFF) option(WITH_NACLAPPLICATION "Build NaClApplication library" OFF)
cmake_dependent_option(WITH_WINDOWLESSNACLAPPLICATION "Build WindowlessNaClApplication library" OFF "NOT WITH_MAGNUMINFO" ON) cmake_dependent_option(WITH_WINDOWLESSNACLAPPLICATION "Build WindowlessNaClApplication library" OFF "NOT WITH_MAGNUMINFO" ON)
else()
# 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) 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_WINDOWLESSGLXAPPLICATION "Build WindowlessGlxApplication library" OFF "NOT WITH_MAGNUMINFO;NOT WITH_DISTANCEFIELDCONVERTER" ON)
cmake_dependent_option(WITH_XEGLAPPLICATION "Build XEglApplication library" OFF "TARGET_GLES" OFF) cmake_dependent_option(WITH_XEGLAPPLICATION "Build XEglApplication library" OFF "TARGET_GLES" OFF)
endif()
# 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) cmake_dependent_option(WITH_GLUTAPPLICATION "Build GlutApplication library" OFF "NOT TARGET_GLES" OFF)
option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF) option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF)
endif() endif()
# Utilities (currently depending on WindowlessGlxApplication) # Magnum Info (currently only using GLX or NaCl)
if(UNIX OR CORRADE_TARGET_NACL) if((CORRADE_TARGET_UNIX AND NOT APPLE) OR CORRADE_TARGET_NACL)
option(WITH_MAGNUMINFO "Build magnum-info utility" OFF) option(WITH_MAGNUMINFO "Build magnum-info utility" OFF)
endif() 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_FONTCONVERTER "Build magnum-fontconverter utility" OFF "NOT TARGET_GLES" OFF)
cmake_dependent_option(WITH_DISTANCEFIELDCONVERTER "Build magnum-distancefieldconverter utility" OFF "NOT TARGET_GLES" OFF) cmake_dependent_option(WITH_DISTANCEFIELDCONVERTER "Build magnum-distancefieldconverter utility" OFF "NOT TARGET_GLES" OFF)
endif() endif()
@ -73,6 +85,7 @@ endif()
# Plugins # Plugins
cmake_dependent_option(WITH_MAGNUMFONT "Build MagnumFont plugin" OFF "WITH_TEXT" OFF) 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) 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_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_TGAIMPORTER "Build TgaImporter plugin" OFF "NOT WITH_MAGNUMFONT" ON)
cmake_dependent_option(WITH_WAVAUDIOIMPORTER "Build WavAudioImporter plugin" OFF "WITH_AUDIO" OFF) cmake_dependent_option(WITH_WAVAUDIOIMPORTER "Build WavAudioImporter plugin" OFF "WITH_AUDIO" OFF)
@ -104,9 +117,15 @@ if(CORRADE_TARGET_NACL OR CORRADE_TARGET_EMSCRIPTEN)
set(TARGET_GLES2 1) set(TARGET_GLES2 1)
endif() 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 # NaCl newlib toolchain supports only static linking, dynamic linking is
# meaningless on Emscripten # meaningless on Emscripten and too inconvenient on Android
if(CORRADE_TARGET_NACL_NEWLIB OR CORRADE_TARGET_EMSCRIPTEN) if(CORRADE_TARGET_NACL_NEWLIB OR CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID)
set(BUILD_STATIC ON) set(BUILD_STATIC ON)
endif() endif()
@ -123,7 +142,7 @@ else()
find_package(OpenGLES3 REQUIRED) find_package(OpenGLES3 REQUIRED)
endif() endif()
# Configuration variables (saved later to corradeConfigure.h) # Configuration variables (saved later to configure.h)
if(TARGET_GLES) if(TARGET_GLES)
set(MAGNUM_TARGET_GLES 1) set(MAGNUM_TARGET_GLES 1)
if(TARGET_GLES2) if(TARGET_GLES2)
@ -132,6 +151,9 @@ if(TARGET_GLES)
set(MAGNUM_TARGET_GLES3 1) set(MAGNUM_TARGET_GLES3 1)
endif() endif()
endif() endif()
if(CORRADE_TARGET_EMSCRIPTEN)
set(MAGNUM_TARGET_WEBGL 1)
endif()
if(TARGET_DESKTOP_GLES) if(TARGET_DESKTOP_GLES)
set(MAGNUM_TARGET_DESKTOP_GLES 1) set(MAGNUM_TARGET_DESKTOP_GLES 1)
endif() endif()
@ -156,12 +178,18 @@ endif()
include(CorradeLibSuffix) include(CorradeLibSuffix)
set(MAGNUM_BINARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/bin) set(MAGNUM_BINARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/bin)
set(MAGNUM_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) set(MAGNUM_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
set(MAGNUM_PLUGINS_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) set(MAGNUM_PLUGINS_DEBUG_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d)
set(MAGNUM_PLUGINS_FONT_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fonts) set(MAGNUM_PLUGINS_RELEASE_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum)
set(MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fontconverters) set(MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fonts)
set(MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/imageconverters) set(MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fonts)
set(MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/importers) set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fontconverters)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/audioimporters) 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_DATA_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/magnum)
set(MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR ${CMAKE_ROOT}/Modules) set(MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR ${CMAKE_ROOT}/Modules)
set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum) set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum)

14
Doxyfile

@ -1653,7 +1653,19 @@ INCLUDE_FILE_PATTERNS =
# instead of the = operator. # instead of the = operator.
PREDEFINED = DOXYGEN_GENERATING_OUTPUT \ 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 # 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. # this tag can be used to specify a list of macro names that should be expanded.

1
README.md

@ -52,6 +52,7 @@ Platforms:
GLUT or SDL2 toolkit) GLUT or SDL2 toolkit)
* **Windows** (through GLUT or SDL2 toolkit) * **Windows** (through GLUT or SDL2 toolkit)
* **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) * **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt))
* **Android** 2.3 (API Level 9) and higher
* **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), * **Google Chrome** (through [Native Client](https://developers.google.com/native-client/),
both `newlib` and `glibc` toolchains are supported) both `newlib` and `glibc` toolchains are supported)
* **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki)) * **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki))

23
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 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) - [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 - [Best practices for 3D graphics](https://developers.google.com/native-client/beta/devguide/coding/3D-graphics#best-practices)
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().
To ease up the development, @ref Mesh checks proper target hint when adding Similarly to WebGL, buffers in NaCl implementation need to be bound only to one
vertex and index buffers in both Native Client and Emscripten. unique target. See @ref Buffer class documentation for more information.
@section best-practices-hw Hardware-specific @section best-practices-hw Hardware-specific

136
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) On Unix-based OSs, the library (for example with support for GLUT applications)
can be built and installed using these four commands: can be built and installed using these four commands:
mkdir -p build && cd build mkdir build && cd build
cmake .. \ cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_INSTALL_PREFIX=/usr \
-DWITH_GLUTAPPLICATION=ON -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 command-line. The bonus point is that you don't even need to wait for Visual
Studio to load: Studio to load:
mkdir build mkdir build && cd build
cd build
cmake -DCMAKE_INSTALL_PREFIX="C:/Sys" .. cmake -DCMAKE_INSTALL_PREFIX="C:/Sys" ..
cmake --build . cmake --build .
cmake --build . --target install cmake --build . --target install
@ -135,6 +134,14 @@ 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. code with `BUILD_STATIC_PIC`. If you want to build with another compiler (e.g.
Clang), pass `-DCMAKE_CXX_COMPILER=clang++` to CMake. Clang), pass `-DCMAKE_CXX_COMPILER=clang++` to CMake.
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 %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. the module with your code instead of depending on it being in system location.
You can install it by enabling `WITH_FIND_MODULE`. You can install it by enabling `WITH_FIND_MODULE`.
@ -186,6 +193,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 need at least one). Choose the one which suits your requirements and your
platform best: platform best:
- `WITH_ANDROIDAPPLICATION` - @ref Platform::AndroidApplication "AndroidApplication"
- `WITH_GLUTAPPLICATION` - @ref Platform::GlutApplication "GlutApplication" - `WITH_GLUTAPPLICATION` - @ref Platform::GlutApplication "GlutApplication"
- `WITH_GLXAPPLICATION` - @ref Platform::GlxApplication "GlxApplication" - `WITH_GLXAPPLICATION` - @ref Platform::GlxApplication "GlxApplication"
- `WITH_NACLAPPLICATION` - @ref Platform::NaClApplication "NaClApplication" - `WITH_NACLAPPLICATION` - @ref Platform::NaClApplication "NaClApplication"
@ -216,6 +224,7 @@ default.
- `WITH_MAGNUMFONTCONVERTER` -- @ref Text::MagnumFontConverter "MagnumFontConverter" - `WITH_MAGNUMFONTCONVERTER` -- @ref Text::MagnumFontConverter "MagnumFontConverter"
plugin. Available only if `WITH_TEXT` is enabled. Enables also building of plugin. Available only if `WITH_TEXT` is enabled. Enables also building of
@ref Trade::TgaImageConverter "TgaImageConverter" plugin. @ref Trade::TgaImageConverter "TgaImageConverter" plugin.
- `WITH_OBJIMPORTER` -- @ref Trade::ObjImporter "ObjImporter" plugin.
- `WITH_TGAIMPORTER` -- @ref Trade::TgaImporter "TgaImporter" plugin. - `WITH_TGAIMPORTER` -- @ref Trade::TgaImporter "TgaImporter" plugin.
- `WITH_TGAIMAGECONVERTER` -- @ref Trade::TgaImageConverter "TgaImageConverter" - `WITH_TGAIMAGECONVERTER` -- @ref Trade::TgaImageConverter "TgaImageConverter"
plugin. plugin.
@ -317,8 +326,9 @@ contents in `toolchains/` subdirectory.
@subsection building-cross-win Crosscompiling for Windows using MinGW @subsection building-cross-win Crosscompiling for Windows using MinGW
@note This guide is tailored mainly for crosscompiling from ArchLinux. For @note This guide is tailored mainly for crosscompiling from ArchLinux. For
this system there is also prepared `mingw32-magnum` development package in this system there is also prepared `mingw32-magnum` development package in
root, named `PKGBUILD-mingw32`. `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 You will need MinGW32 versions of the compiler and all dependent libraries
(Corrade), i.e. these ArchLinux packages: (Corrade), i.e. these ArchLinux packages:
@ -327,19 +337,18 @@ You will need MinGW32 versions of the compiler and all dependent libraries
- `mingw32-runtime` - `mingw32-runtime`
- `mingw32-corrade` - `mingw32-corrade`
Then create build directory and run cmake and make. You may need to modify the Then create build directory and run cmake and build command in it. You may need
`basic-mingw32.cmake` file and `CMAKE_INSTALL_PREFIX` to suit your distribution to modify the `basic-mingw32.cmake` file and `CMAKE_INSTALL_PREFIX` to suit
filesystem hierarchy. your distribution filesystem hierarchy.
mkdir build-win mkdir build-win && cd build-win
cd build-win
cmake .. \ cmake .. \
-DCMAKE_TOOLCHAIN_FILE=../toolchains/archlinux/basic-mingw32.cmake \ -DCMAKE_TOOLCHAIN_FILE=../toolchains/archlinux/basic-mingw32.cmake \
-DCMAKE_INSTALL_PREFIX=/usr/i486-mingw32 -DCMAKE_INSTALL_PREFIX=/usr/i486-mingw32
make cmake --build .
Then you can install the package using `make install` to make it available for Then you can install the package using `cmake --build . --target install` to
depending projects. make it available for depending projects.
@subsection building-cross-nacl Crosscompiling for Google Chrome Native Client @subsection building-cross-nacl Crosscompiling for Google Chrome Native Client
@ -354,14 +363,13 @@ adapt `NACL_PREFIX` variable in `generic/NaCl-*-x86-32.cmake` and
to find the compiler. NaCl currently supports only OpenGL ES 2, thus to find the compiler. NaCl currently supports only OpenGL ES 2, thus
`TARGET_GLES` and `TARGET_GLES2` is always enabled. `TARGET_GLES` and `TARGET_GLES2` is always enabled.
Then create build directories for x86-32 and x86-64 and run cmake and make in Then create build directories for x86-32 and x86-64 and run cmake and build
them. The toolchains need access to the platform file, so be sure to properly command in them. The toolchains need access to the platform file, so be sure to
set **absolute** path to `modules/` directory containing `Platform/NaCl.cmake`. properly set **absolute** path to `modules/` directory containing
Also adapt `CMAKE_INSTALL_PREFIX` to the same value as in `NACL_PREFIX` in `Platform/NaCl.cmake`. Also adapt `CMAKE_INSTALL_PREFIX` to the same value as
toolchain file. in `NACL_PREFIX` in toolchain file.
mkdir -p build-nacl-x86-32 mkdir build-nacl-x86-32 && cd build-nacl-x86-32
cd build-nacl-x86-32
cmake .. \ cmake .. \
-DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \
-DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/NaCl-newlib-x86-32.cmake" \ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/NaCl-newlib-x86-32.cmake" \
@ -369,23 +377,24 @@ toolchain file.
-DCMAKE_INSTALL_PREFIX=/usr/nacl \ -DCMAKE_INSTALL_PREFIX=/usr/nacl \
-DWITH_NACLAPPLICATION=ON \ -DWITH_NACLAPPLICATION=ON \
-DLIB_SUFFIX=/32 -DLIB_SUFFIX=/32
make cmake --build .
mkdir -p build-nacl-x86-64 mkdir build-nacl-x86-64 && cd build-nacl-x86-64
cd build-nacl-x86-64
cmake .. \ cmake .. \
-DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \
-DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/NaCl-newlib-x86-64.cmake" \ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/NaCl-newlib-x86-64.cmake" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/nacl \ -DCMAKE_INSTALL_PREFIX=/usr/nacl \
-DWITH_NACLAPPLICATION=ON -DWITH_NACLAPPLICATION=ON
make cmake --build .
Then you can install both versions using `make install` to make them available Then you can install both versions using `cmake --build . --target install` to
for depending projects. The headers are shared by both versions. make them available for depending projects. The headers are shared by both
versions.
For ArchLinux there are also prepared package files in root, named For ArchLinux there are also prepared package files in `package/archlinux`,
`PKGBUILD-nacl-glibc` and `PKGBUILD-nacl-newlib`. named `PKGBUILD-nacl-glibc` and `PKGBUILD-nacl-newlib`, see
@ref building-packages-arch "above" for more information.
@subsection building-cross-emscripten Crosscompiling for Emscripten @subsection building-cross-emscripten Crosscompiling for Emscripten
@ -397,34 +406,81 @@ to path where Emscripten is installed. Default is `/usr/emscripten`. Emscripten
supports dynamic libraries only to simplify porting and they are generally supports dynamic libraries only to simplify porting and they are generally
slower, thus `BUILD_STATIC` is implicitly enabled. slower, thus `BUILD_STATIC` is implicitly enabled.
Then create build directory and run cmake and make in it. The toolchain needs Then create build directory and run cmake and build command in it. The
access to its platform file, so be sure to properly set **absolute** path to toolchain needs access to its platform file, so be sure to properly set
`modules/` directory containing `Platform/Emscripten.cmake`. Also set **absolute** path to `modules/` directory containing `Platform/Emscripten.cmake`.
`CMAKE_INSTALL_PREFIX` to value which is contained in `CMAKE_FIND_ROOT_PATH` in Also set `CMAKE_INSTALL_PREFIX` to path contained in `EMSCRIPTEN_TOOLCHAIN_PATH`.
toolchain file.
mkdir -p build-emscripten mkdir build-emscripten && cd build-emscripten
cd build-emscripten
cmake .. \ cmake .. \
-DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \ -DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \
-DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Emscripten.cmake" \ -DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Emscripten.cmake" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \ -DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \
-DWITH_SDL2APPLICATION=ON -DWITH_SDL2APPLICATION=ON
make cmake --build .
Then you can install the library using `make install` to make it available for Then you can install the library using `cmake --build . --target install` to
depending projects. make it available for depending projects.
If you have Node.js installed, you can also build and run unit tests using If you have Node.js installed, you can also build and run unit tests using
`ctest`. See `BUILD_TESTS` above. `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)
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 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
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 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
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" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-19/arch-x86/usr \
-DTARGET_GLES=ON -DTARGET_GLES2=ON
cmake --build .
Then you can install the library using `cmake --build . --target 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 @section building-ci-jenkins Jenkins Continuous Integration
In `package/ci/` there are `jenkins.xml` and `jenkins-gltests.xml` files 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 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 GL tests only. Setup your Jenkins server, enable the **Git** and **Text-finder**
**Text-finder** plugin and download the CLI application from here: plugin and download the CLI application from here:
http://your-jenkins-server/cli http://your-jenkins-server/cli

35
doc/cmake.dox

@ -51,17 +51,19 @@ variables:
- `MAGNUM_FOUND` -- Whether the library was found - `MAGNUM_FOUND` -- Whether the library was found
- `MAGNUM_LIBRARIES` -- %Magnum library and dependent libraries - `MAGNUM_LIBRARIES` -- %Magnum library and dependent libraries
- `MAGNUM_INCLUDE_DIRS` -- Root include dir and include dirs of dependencies - `MAGNUM_INCLUDE_DIRS` -- Root include dir and include dirs of dependencies
- `MAGNUM_PLUGINS_DIR` -- Base directory with plugins, defaults to `magnum/` - `MAGNUM_PLUGINS_DIR` -- Base directory with dynamic plugins, defaults to
subdirectory of dir where Magnum library was found. You can modify it (e.g. `magnum/` subdirectory of dir where Magnum library was found (or
set it to `.` when deploying on Windows with plugins stored relatively to `magnum-d/` in debug build). . You can modify it (e.g. set it to `.` when
the executable), the following `MAGNUM_PLUGINS_*_DIR` variables depend on deploying on Windows with plugins stored relatively to the executable),
it. the following `MAGNUM_PLUGINS_*_DIR` variables depend on it.
- `MAGNUM_PLUGINS_FONT_DIR` -- Directory with font plugins - `MAGNUM_PLUGINS_FONT_DIR` -- Directory with dynamic font plugins
- `MAGNUM_PLUGINS_FONTCONVERTER_DIR` -- Directory with font converter plugins - `MAGNUM_PLUGINS_FONTCONVERTER_DIR` -- Directory with dynamic font converter
- `MAGNUM_PLUGINS_IMAGECONVERTER_DIR` -- Directory with image 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 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 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 components. The base library depends on %Corrade and OpenGL libraries (or
@ -103,6 +105,8 @@ dependencies, you need to find the dependency and then link to it.
`%Text` component and `TgaImporter` plugin) `%Text` component and `TgaImporter` plugin)
- `MagnumFontConverter` -- @ref Text::MagnumFontConverter "MagnumFontConverter" - `MagnumFontConverter` -- @ref Text::MagnumFontConverter "MagnumFontConverter"
plugin (depends on `%Text` component and `%TgaImageConverter` plugin) plugin (depends on `%Text` component and `%TgaImageConverter` plugin)
- `ObjImporter` -- @ref Trade::ObjImporter "ObjImporter" plugin (depends on
`%MeshTools` component)
- `TgaImageConverter` -- @ref Trade::TgaImageConverter "TgaImageConverter" - `TgaImageConverter` -- @ref Trade::TgaImageConverter "TgaImageConverter"
plugin plugin
- `TgaImporter` -- @ref Trade::TgaImporter "TgaImporter" plugin - `TgaImporter` -- @ref Trade::TgaImporter "TgaImporter" plugin
@ -130,6 +134,17 @@ convenience aliases `MAGNUM_APPLICATION_LIBRARIES` /
`MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES` and `MAGNUM_APPLICATION_INCLUDE_DIRS` `MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES` and `MAGNUM_APPLICATION_INCLUDE_DIRS`
/ `MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS` to simplify porting. / `MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS` to simplify porting.
The package is found if either debug or release version of each requested
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 Features of found %Magnum library are exposed in these CMake variables, they
are also available as preprocessor variables if including Magnum.h: are also available as preprocessor variables if including Magnum.h:

1
doc/mainpage.dox

@ -78,6 +78,7 @@ Platforms:
GLUT or SDL2 toolkit) GLUT or SDL2 toolkit)
- **Windows** (through GLUT or SDL2 toolkit) - **Windows** (through GLUT or SDL2 toolkit)
- **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) - **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt))
- **Android** 2.3 (API Level 9) and higher
- **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), - **Google Chrome** (through [Native Client](https://developers.google.com/native-client/),
both `newlib` and `glibc` toolchains are supported) both `newlib` and `glibc` toolchains are supported)
- **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki)) - **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki))

120
doc/matrix-vector.dox

@ -77,13 +77,14 @@ Vector3i b; // zero-filled
Matrix3 identity; // diagonal set to 1 Matrix3 identity; // diagonal set to 1
Matrix3 zero(Matrix::Zero); // zero-filled Matrix3 zero(Matrix::Zero); // zero-filled
Color4 black1; // {0.0f, 0.0f, 0.0f, 1.0f} Color4 black1; // {0.0f, 0.0f, 0.0f, 1.0f}
BasicColor4<UnsignedByte> black2; // {0, 0, 0, 255} Color4ub black2; // {0, 0, 0, 255}
@endcode @endcode
Most common and most efficient way to create vector is to pass all values to 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, 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 @code
Vector3i vec(0, 1, 2); Vector3i vec(0, 1, 2);
@ -91,11 +92,9 @@ Matrix3 mat({0.0f, 1.9f, 2.2f},
{3.5f, 4.0f, 5.1f}, {3.5f, 4.0f, 5.1f},
{6.0f, 7.3f, 8.0f}); {6.0f, 7.3f, 8.0f});
@endcode @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 You can specify all components of vector or whole diagonal of square matrix
once or you can create diagonal matrix from vector: with single value or create diagonal matrix from vector:
@code @code
Matrix3 diag(Matrix3::Identity, 2.0f); // diagonal set to 2.0f, zeros elsewhere Matrix3 diag(Matrix3::Identity, 2.0f); // diagonal set to 2.0f, zeros elsewhere
Vector3i fill(10); // {10, 10, 10} Vector3i fill(10); // {10, 10, 10}
@ -121,20 +120,14 @@ Int[] mat = { 2, 4, 6,
1, 3, 5 }; 1, 3, 5 };
Math::Matrix2x3<Int>::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 } Math::Matrix2x3<Int>::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 }
@endcode @endcode
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: Note that, unlike constructors, this function has no way to check whether the
@code array is long enough to contain all elements, so use with caution.
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 @section matrix-vector-component-access Accessing matrix and vector components
Column vectors of matrices and vector components can be accessed using square Column vectors of matrices and vector components can be accessed using square
brackets, there is also round bracket operator for accessing matrix components brackets:
directly:
@code @code
Matrix3x2 a; Matrix3x2 a;
a[2] /= 2.0f; // third column (column major indexing, see explanation below) a[2] /= 2.0f; // third column (column major indexing, see explanation below)
@ -145,7 +138,7 @@ b[1] = 1; // second element
@endcode @endcode
Row vectors can be accessed too, but only for reading, and the access is slower 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 @code
Vector2i c = a.row(2); // third row Vector2i c = a.row(2); // third row
@endcode @endcode
@ -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 } Math::Vector<6, Int> w10xyz = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original); // { 4, 1, 0, -1, 2, 3 }
@endcode @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<Color3ub>(a); // {204, 255, 76}
Color3ub c{64, 127, 89};
auto d = Math::normalize<Color3>(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 @section matrix-vector-operations Operations with matrices and vectors
Vectors can be added, subtracted, negated and multiplied or divided with Vectors can be added, subtracted, negated and multiplied or divided with
@ -193,8 +218,8 @@ In %Magnum all mulitplication/division operations involving integral vectors
will have integral result, you need to convert both arguments to the same will have integral result, you need to convert both arguments to the same
floating-point type to have floating-point result. floating-point type to have floating-point result.
@code @code
BasicColor3<UnsignedByte> color(80, 116, 34); Color3ub color(80, 116, 34);
BasicColor3<UnsignedByte> lighter = color*1.5f; // lighter = {120, 174, 51} Color3ub lighter = color*1.5f; // lighter = {120, 174, 51}
Vector3i a(4, 18, -90); Vector3i a(4, 18, -90);
Vector3 multiplier(2.2f, 0.25f, 0.1f); Vector3 multiplier(2.2f, 0.25f, 0.1f);
@ -230,6 +255,63 @@ Math::RectangularMatrix<4, 1, Float> d;
Matrix4x3 e = b*d; Matrix4x3 e = b*d;
@endcode @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 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
@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<Int, Int> minmax = Math::minmax(24, -5); // -5, 24
Int a = Math::lerp(0, 360, 0.75f); // 270
auto b = Math::denormalize<UnsignedByte>(0.89f); // 226
@endcode
@section matrix-vector-column-major Matrices are column-major and vectors are columns @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 OpenGL matrices are column-major, thus it is reasonable to have matrices in

3
doc/opengl-mapping.dox

@ -62,8 +62,7 @@ OpenGL function | Matching API
@fn_gl{BindRenderbuffer} | not needed, handhled internally in @ref Renderbuffer @fn_gl{BindRenderbuffer} | not needed, handhled internally in @ref Renderbuffer
@fn_gl{BindSampler} | | @fn_gl{BindSampler} | |
@fn_gl{BindSamplers} | | @fn_gl{BindSamplers} | |
@fn_gl{BindTexture}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind() @fn_gl{BindTexture}, \n @fn_gl{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind()
@fn_gl{BindTextures} | |
@fn_gl{BindTransformFeedback} | | @fn_gl{BindTransformFeedback} | |
@fn_gl{BindVertexArray} | not needed, handhled internally in @ref Mesh @fn_gl{BindVertexArray} | not needed, handhled internally in @ref Mesh
@fn_gl{BindVertexBuffer} | | @fn_gl{BindVertexBuffer} | |

13
doc/opengl-support.dox

@ -71,7 +71,7 @@ following:
@extension{EXT,texture_shared_exponent} | done @extension{EXT,texture_shared_exponent} | done
@extension{EXT,framebuffer_sRGB} | | @extension{EXT,framebuffer_sRGB} | |
@extension{EXT,draw_buffers2} | | @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{EXT,transform_feedback} | |
@extension{NV,half_float} | done (GL 3.0 subset) @extension{NV,half_float} | done (GL 3.0 subset)
@extension{NV,depth_buffer_float} | | @extension{NV,depth_buffer_float} | |
@ -100,7 +100,7 @@ following:
@extension{ARB,provoking_vertex} | done @extension{ARB,provoking_vertex} | done
@extension{ARB,seamless_cube_map} | done @extension{ARB,seamless_cube_map} | done
@extension{ARB,sync} | | @extension{ARB,sync} | |
@extension{ARB,texture_multisample} | | @extension{ARB,texture_multisample} | missing sample location queries and sample mask
@extension{ARB,vertex_array_bgra} | done @extension{ARB,vertex_array_bgra} | done
@subsection opengl-support-33 OpenGL 3.3 @subsection opengl-support-33 OpenGL 3.3
@ -187,7 +187,7 @@ following:
@extension{ARB,stencil_texturing} | | @extension{ARB,stencil_texturing} | |
@extension{ARB,texture_buffer_range} | done @extension{ARB,texture_buffer_range} | done
@extension{ARB,texture_query_levels} | done (shading language only) @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,texture_view} | |
@extension{ARB,vertex_attrib_binding} | | @extension{ARB,vertex_attrib_binding} | |
@ -201,7 +201,7 @@ following:
@extension{ARB,buffer_storage} | | @extension{ARB,buffer_storage} | |
@extension{ARB,clear_texture} | | @extension{ARB,clear_texture} | |
@extension{ARB,enhanced_layouts} | done (shading language only) @extension{ARB,enhanced_layouts} | done (shading language only)
@extension{ARB,multi_bind} | | @extension{ARB,multi_bind} | only texture binding
@extension{ARB,query_buffer_object} | | @extension{ARB,query_buffer_object} | |
@extension{ARB,texture_mirror_clamp_to_edge} | done @extension{ARB,texture_mirror_clamp_to_edge} | done
@extension{ARB,texture_stencil8} | done @extension{ARB,texture_stencil8} | done
@ -222,6 +222,7 @@ following:
@extension{EXT,texture_filter_anisotropic} (also in ES) | done @extension{EXT,texture_filter_anisotropic} (also in ES) | done
@extension{EXT,texture_mirror_clamp} | only GL 4.4 subset @extension{EXT,texture_mirror_clamp} | only GL 4.4 subset
@extension{EXT,direct_state_access} | done for implemented functionality @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_label} (also in ES) | missing pipeline, transform feedback and sampler label
@extension2{EXT,debug_marker} (also in ES) | missing marker groups @extension2{EXT,debug_marker} (also in ES) | missing marker groups
@extension{GREMEDY,string_marker} | done @extension{GREMEDY,string_marker} | done
@ -244,6 +245,7 @@ supported.
@es_extension{ANGLE,framebuffer_multisample} | done @es_extension{ANGLE,framebuffer_multisample} | done
@es_extension{ANGLE,depth_texture} | done @es_extension{ANGLE,depth_texture} | done
@es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset) @es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset)
@es_extension{APPLE,texture_max_level} | done
@es_extension{ARM,rgba8} | done @es_extension{ARM,rgba8} | done
@es_extension{EXT,texture_type_2_10_10_10_REV} | done @es_extension{EXT,texture_type_2_10_10_10_REV} | done
@es_extension{EXT,discard_framebuffer} | done @es_extension{EXT,discard_framebuffer} | done
@ -324,7 +326,8 @@ add any performance gains, is not supported in %Magnum. See also
with serious performance drops. Multisampling is far superior solution. with serious performance drops. Multisampling is far superior solution.
- Fixed precision data types (`GL_FIXED` in OpenGL ES) are not supported, as - 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 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 - Shader compiler is assumed to be present (`GL_SHADER_COMPILER` returning
true), as all desktop GL implementations and also ES3 are required to true), as all desktop GL implementations and also ES3 are required to
support it. support it.

14
doc/platform.dox

@ -66,10 +66,10 @@ blue color is shown in the following code listing.
repository. repository.
@code @code
#include <Color.h> #include <Magnum/Color.h>
#include <DefaultFramebuffer.h> #include <Magnum/DefaultFramebuffer.h>
#include <Renderer.h> #include <Magnum/Renderer.h>
#include <Platform/GlutApplication.h> #include <Magnum/Platform/GlutApplication.h>
using namespace Magnum; using namespace Magnum;
@ -88,7 +88,7 @@ MyApplication::MyApplication(const Arguments& arguments): Platform::Application(
void MyApplication::drawEvent() { void MyApplication::drawEvent() {
// Clear the window // Clear the window
defaultFramebuffer.clear(DefaultFramebuffer::Clear::Color); defaultFramebuffer.clear(FramebufferClear::Color);
// The context is double-buffered, swap buffers // The context is double-buffered, swap buffers
swapBuffers(); swapBuffers();
@ -148,8 +148,8 @@ renderer string and exits is in the following code listing.
repository. repository.
@code @code
#include <Context.h> #include <Magnum/Context.h>
#include <Platform/WindowlessGlxApplication.h> #include <Magnum/Platform/WindowlessGlxApplication.h>
using namespace Magnum; using namespace Magnum;

17
doc/portability.dox

@ -40,9 +40,10 @@ format is not supported.
If you include @ref Magnum.h, you get these predefined macros: If you include @ref Magnum.h, you get these predefined macros:
- @ref MAGNUM_TARGET_GLES if targeting OpenGL ES - @ref MAGNUM_TARGET_GLES if targeting OpenGL ES
- @ref MAGNUM_TARGET_GLES2 if targeting OpenGL ES 2.0 - @ref MAGNUM_TARGET_GLES2 if targeting OpenGL ES 2.0
- @ref MAGNUM_TARGET_GLES3 if targeting OpenGL ES 3.0 - @ref MAGNUM_TARGET_GLES3 if targeting OpenGL ES 3.0
- @ref MAGNUM_TARGET_WEBGL if targeting WebGL
Example usage: Example usage:
@code @code
@ -57,7 +58,7 @@ Renderer::setPolygonMode(Renderer::PolygonMode::Lines);
Each feature is marked accordingly if it is not available in some targets. See 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. 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 %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 possible. Many features from C++11 are used to simplify things and make them
@ -73,6 +74,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 will work also on Magnum compiled with support for newer compilers, although
newer compilers may catch errors that weren't spotted by earlier versions. 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 @section portability-extensions Extension-aware code
Some functionality is depending on support of particular extension and thus Some functionality is depending on support of particular extension and thus
@ -156,8 +161,8 @@ if(!Context::instance()->isExtensionSupported<Extensions::GL::ARB::explicit_attr
@endcode @endcode
See also @ref AbstractShaderProgram class documentation for information about See also @ref AbstractShaderProgram class documentation for information about
specifying attribute location, uniform location and texture layer in various specifying attribute location, uniform location and texture binding unit in
OpenGL versions. various OpenGL versions.
All shaders in @ref Shaders namespace support desktop OpenGL starting from All shaders in @ref Shaders namespace support desktop OpenGL starting from
version 2.1 and also OpenGL ES 2.0 and 3.0. Feel free to look into their version 2.1 and also OpenGL ES 2.0 and 3.0. Feel free to look into their

58
doc/shapes.dox

@ -77,9 +77,9 @@ is least efficient.
@section shapes-composition Creating shape compositions @section shapes-composition Creating shape compositions
%Shapes can be composed together using one of three available logical %Shapes can be composed together using one of three available logical
operations: AND, OR and NOT. These operations are mapped to operator&&(), operations: AND, OR and NOT. These operations are mapped to `&&`, `||` and `!`
operator||() and operator!(), so for example creating negation of logical OR operators, so for example creating negation of logical OR of line segment and
of line segment and point is simple as this: point is simple as this:
@code @code
Shapes::LineSegment3D segment; Shapes::LineSegment3D segment;
Shapes::Point3D point; 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 collision detection, because it might be testing collision with more shapes
than necessary. It's then good to specify simplified version of such shape, 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 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 was detected with the simplified shape. It is in fact logical AND using the
operator&&() - the collision is initially detected on first (simplified) shape `&&` operator -- the collision is initially detected on first (simplified)
and then on the other: shape and then on the other:
@code @code
Shapes::Sphere3D sphere; Shapes::Sphere3D sphere;
Shapes::Box3D box; Shapes::Box3D box;
@ -111,7 +111,7 @@ Shapes::Composition3D composition = simplified && (sphere || box);
@section shapes-collisions Detecting shape collisions @section shapes-collisions Detecting shape collisions
%Shape pairs which have collision occurence detection implemented can be tested %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: whether the collision happened or not. Example:
@code @code
Shapes::Point3D point; 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 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 serious physics you often need more information like contact point, separation
normal and penetration depth. For shape pairs which have implemented this normal and penetration depth. For shape pairs which have implemented this
detailed collision detection you can use `operator/()`, which returns @ref Collision detailed collision detection you can use the `/` operator, which returns
object. Note that unlike with `operator%()` mentioned above, this operation is @ref Collision object. Note that unlike with the `%` operator mentioned above,
not commutative. See @ref Collision class documentation for more information this operation is not commutative. See @ref Collision class documentation for
about the returned data. Example: more information about the returned data. Example:
@code @code
Shapes::Collision3D c = point/sphere; const Shapes::Collision3D c = point/sphere;
if(c) { if(c) {
Vector3 translation = c.separationNormal()*c.separationDistance(); Vector3 translation = c.separationNormal()*c.separationDistance();
// translate point by translation... // translate point by translation...
@ -137,15 +137,37 @@ if(c) {
@section shapes-scenegraph Integration with scene graph @section shapes-scenegraph Integration with scene graph
%Shape can be attached to object in the scene using Shapes::Shape feature and %Shape can be attached to object in the scene using @ref Shapes::Shape feature.
then used for collision detection. You can also use DebugTools::ShapeRenderer In conjunction with @ref Shapes::ShapeGroup you can use
to visualize the shape for debugging purposes. @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 @code
Object3D object; Shapes::ShapeGroup3D shapes;
auto shape = Shapes::Shape<Shapes::Sphere3D>(object, {{}, 23.0f}); Object3D& a;
auto aShape = new Shapes::Shape<Shapes::Sphere3D>(a, {{}, 23.0f}, &shapes);
Object3D& b;
auto bShape = new Shapes::Shape<Shapes::Point3D>(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 @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 - Previous page: @ref scenegraph
- Next page: @ref debug-tools - Next page: @ref debug-tools

71
doc/types.dox

@ -87,21 +87,82 @@ underlying type.
Any super- or sub-class of the same size and underlying type can be used 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). 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 @section types-other Other types
Other types, which don't have their GLSL equivalent, are: Other types, which don't have their GLSL equivalent, are:
- @ref Complex or @ref Complexd, @ref DualComplex or @ref DualComplexd - @ref Complex or @ref Complexd, @ref DualComplex or @ref DualComplexd
- @ref Quaternion or @ref Quaterniond, @ref DualQuaternion or @ref DualQuaterniond - @ref Quaternion or @ref Quaterniond, @ref DualQuaternion or
- @ref Range1D / @ref Range2D / @ref Range3D, @ref Range1Di / @ref Range2Di / @ref Range3Di or @ref DualQuaterniond
@ref Range1Dd / @ref Range2Dd / @ref Range3Dd - @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 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. underlying structure or converting them to types supported by GLSL (e.g.
quaternion to matrix). quaternion to matrix).
For your convenience, there is also alias for class with often used constants -- For your convenience, there is also alias for class with often used constants
@ref Constants or @ref Constantsd. -- @ref Constants or @ref Constantsd.
- Previous page: @ref platform - Previous page: @ref platform
- Next page: @ref matrix-vector - Next page: @ref matrix-vector

76
modules/FindCorrade.cmake

@ -3,7 +3,7 @@
# Basic usage: # Basic usage:
# find_package(Corrade [REQUIRED]) # find_package(Corrade [REQUIRED])
# This module tries to find Corrade library and then defines: # 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_INCLUDE_DIR - Root include dir
# CORRADE_INTERCONNECT_LIBRARIES - Interconnect library and dependent # CORRADE_INTERCONNECT_LIBRARIES - Interconnect library and dependent
# libraries # libraries
@ -14,9 +14,14 @@
# CORRADE_TESTSUITE_LIBRARIES - TestSuite library and dependent # CORRADE_TESTSUITE_LIBRARIES - TestSuite library and dependent
# libraries # libraries
# CORRADE_RC_EXECUTABLE - Resource compiler executable # 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 # 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 # use CORRADE_CXX_FLAGS to enable additional pedantic set of warnings and
# hidden visibility by default. # enable hidden visibility by default.
# #
# Features of found Corrade library are exposed in these variables: # Features of found Corrade library are exposed in these variables:
# CORRADE_GCC47_COMPATIBILITY - Defined if compiled with compatibility # CORRADE_GCC47_COMPATIBILITY - Defined if compiled with compatibility
@ -42,6 +47,7 @@
# CORRADE_TARGET_NACL_GLIBC - Defined if compiled for Google Chrome # CORRADE_TARGET_NACL_GLIBC - Defined if compiled for Google Chrome
# Native Client with `glibc` toolchain # Native Client with `glibc` toolchain
# CORRADE_TARGET_EMSCRIPTEN - Defined if compiled for Emscripten # 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 # If CORRADE_BUILD_DEPRECATED is defined, the CORRADE_INCLUDE_DIR variable also
# contains path directly to Corrade directory (i.e. for includes without # contains path directly to Corrade directory (i.e. for includes without
@ -71,15 +77,15 @@
# add_executable(app source1 source2 ... ${app_resources}) # add_executable(app source1 source2 ... ${app_resources})
# #
# Add dynamic plugin. # Add dynamic plugin.
# corrade_add_plugin(plugin_name install_dir metadata_file # corrade_add_plugin(plugin_name debug_install_dir release_install_dir
# sources...) # metadata_file sources...)
# The macro adds preprocessor directive CORRADE_DYNAMIC_PLUGIN. Additional # The macro adds preprocessor directive CORRADE_DYNAMIC_PLUGIN. Additional
# libraries can be linked in via target_link_libraries(plugin_name ...). If # 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), # debug_install_dir is set to CMAKE_CURRENT_BINARY_DIR (e.g. for testing
# the files are copied directly, without the need to run `make install`. Note # purposes), the files are copied directly, without the need to perform install
# that the files are actually put into configuration-based subdirectory, i.e. # step. Note that the files are actually put into configuration-based
# ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}. See documentation of # subdirectory, i.e. ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}. See
# CMAKE_CFG_INTDIR variable for more information. # documentation of CMAKE_CFG_INTDIR variable for more information.
# #
# #
# Add static plugin. # Add static plugin.
@ -88,7 +94,11 @@
# The macro adds preprocessor directive CORRADE_STATIC_PLUGIN. Additional # The macro adds preprocessor directive CORRADE_STATIC_PLUGIN. Additional
# libraries can be linked in via target_link_libraries(plugin_name ...). If # 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), # install_dir is set to CMAKE_CURRENT_BINARY_DIR (e.g. for testing purposes),
# no installation is performed. # 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: # Additionally these variables are defined for internal usage:
@ -98,6 +108,9 @@
# CORRADE_PLUGINMANAGER_LIBRARY - Plugin manager library (w/o # CORRADE_PLUGINMANAGER_LIBRARY - Plugin manager library (w/o
# dependencies) # dependencies)
# CORRADE_TESTSUITE_LIBRARY - TestSuite 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
# #
# #
@ -126,10 +139,28 @@
# #
# Libraries # Libraries
find_library(CORRADE_INTERCONNECT_LIBRARY CorradeInterconnect) foreach(_component Interconnect Utility PluginManager TestSuite)
find_library(CORRADE_UTILITY_LIBRARY CorradeUtility) string(TOUPPER ${_component} _COMPONENT)
find_library(CORRADE_PLUGINMANAGER_LIBRARY CorradePluginManager)
find_library(CORRADE_TESTSUITE_LIBRARY CorradeTestSuite) # 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 # RC executable
find_program(CORRADE_RC_EXECUTABLE corrade-rc) find_program(CORRADE_RC_EXECUTABLE corrade-rc)
@ -219,6 +250,10 @@ string(FIND "${_corradeConfigure}" "#define CORRADE_TARGET_EMSCRIPTEN" _TARGET_E
if(NOT _TARGET_EMSCRIPTEN EQUAL -1) if(NOT _TARGET_EMSCRIPTEN EQUAL -1)
set(CORRADE_TARGET_EMSCRIPTEN 1) set(CORRADE_TARGET_EMSCRIPTEN 1)
endif() 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_UTILITY_LIBRARIES ${CORRADE_UTILITY_LIBRARY})
set(CORRADE_INTERCONNECT_LIBRARIES ${CORRADE_INTERCONNECT_LIBRARY} ${CORRADE_UTILITY_LIBRARIES}) set(CORRADE_INTERCONNECT_LIBRARIES ${CORRADE_INTERCONNECT_LIBRARY} ${CORRADE_UTILITY_LIBRARIES})
@ -230,11 +265,12 @@ if(CORRADE_TARGET_UNIX OR CORRADE_TARGET_NACL_GLIBC)
set(CORRADE_PLUGINMANAGER_LIBRARIES ${CORRADE_PLUGINMANAGER_LIBRARIES} ${CMAKE_DL_LIBS}) set(CORRADE_PLUGINMANAGER_LIBRARIES ${CORRADE_PLUGINMANAGER_LIBRARIES} ${CMAKE_DL_LIBS})
endif() endif()
mark_as_advanced(CORRADE_UTILITY_LIBRARY # AndroidLogStreamBuffer class needs to be linked to log library
CORRADE_INTERCONNECT_LIBRARY if(CORRADE_TARGET_ANDROID)
CORRADE_PLUGINMANAGER_LIBRARY set(CORRADE_UTILITY_LIBRARIES ${CORRADE_UTILITY_LIBRARIES} log)
CORRADE_TESTSUITE_LIBRARY endif()
_CORRADE_INCLUDE_DIR
mark_as_advanced(_CORRADE_INCLUDE_DIR
_CORRADE_MODULE_DIR) _CORRADE_MODULE_DIR)
# Add Corrade dir to include path if this is deprecated build # Add Corrade dir to include path if this is deprecated build

227
modules/FindMagnum.cmake

@ -7,16 +7,19 @@
# MAGNUM_LIBRARIES - Magnum library and dependent libraries # MAGNUM_LIBRARIES - Magnum library and dependent libraries
# MAGNUM_INCLUDE_DIRS - Root include dir and include dirs of # MAGNUM_INCLUDE_DIRS - Root include dir and include dirs of
# dependencies # dependencies
# MAGNUM_PLUGINS_DIR - Base directory with plugins, defaults to # MAGNUM_PLUGINS_DIR - Base directory with dynamic plugins, defaults
# `magnum/` subdirectory of dir where Magnum library was found. You can # to magnum/ subdirectory of dir where Magnum library was found (or magnum-d/
# modify it (e.g. set it to `.` when deploying on Windows with plugins # in debug build). You can modify it (e.g. set it to `.` when deploying on
# stored relatively to the executable), the following MAGNUM_PLUGINS_*_DIR # Windows with plugins stored relatively to the executable), the following
# variables depend on it. # MAGNUM_PLUGINS_*_DIR variables depend on it.
# MAGNUM_PLUGINS_FONT_DIR - Directory with font plugins # MAGNUM_PLUGINS_FONT_DIR - Directory with dynamic font plugins
# MAGNUM_PLUGINS_FONTCONVERTER_DIR - Directory with font converter plugins # MAGNUM_PLUGINS_FONTCONVERTER_DIR - Directory with dynamic font converter
# MAGNUM_PLUGINS_IMAGECONVERTER_DIR - Directory with image converter plugins # plugins
# MAGNUM_PLUGINS_IMPORTER_DIR - Directory with importer plugins # MAGNUM_PLUGINS_IMAGECONVERTER_DIR - Directory with dynamic image converter
# MAGNUM_PLUGINS_AUDIOIMPORTER_DIR - Directory with audio importer plugins # 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 # This command will try to find only the base library, not the optional
# components. The base library depends on Corrade and OpenGL libraries (or # components. The base library depends on Corrade and OpenGL libraries (or
# OpenGL ES libraries). Additional dependencies are specified by the # OpenGL ES libraries). Additional dependencies are specified by the
@ -35,6 +38,7 @@
# and TgaImporter plugin) # and TgaImporter plugin)
# MagnumFontConverter - Magnum bitmap font converter plugin (depends on Text # MagnumFontConverter - Magnum bitmap font converter plugin (depends on Text
# component and TgaImageConverter plugin) # component and TgaImageConverter plugin)
# ObjImporter - OBJ importer plugin
# TgaImageConverter - TGA image converter plugin # TgaImageConverter - TGA image converter plugin
# TgaImporter - TGA importer plugin # TgaImporter - TGA importer plugin
# WavAudioImporter - WAV audio importer plugin (depends on Audio component) # WavAudioImporter - WAV audio importer plugin (depends on Audio component)
@ -58,6 +62,17 @@
# MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES and MAGNUM_APPLICATION_INCLUDE_DIRS # MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES and MAGNUM_APPLICATION_INCLUDE_DIRS
# / MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS to simplify porting. # / MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS to simplify porting.
# #
# The package is found if either debug or release version of each requested
# 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: # Features of found Magnum library are exposed in these variables:
# MAGNUM_BUILD_DEPRECATED - Defined if compiled with deprecated APIs # MAGNUM_BUILD_DEPRECATED - Defined if compiled with deprecated APIs
# included # included
@ -74,29 +89,29 @@
# plugins (i.e. instead of `MagnumPlugins/` prefix). # plugins (i.e. instead of `MagnumPlugins/` prefix).
# #
# Additionally these variables are defined for internal usage: # Additionally these variables are defined for internal usage:
# MAGNUM_INCLUDE_DIR - Root include dir (w/o # MAGNUM_INCLUDE_DIR - Root include dir (w/o dependencies)
# dependencies) # MAGNUM_LIBRARY - Magnum library (w/o dependencies)
# MAGNUM_LIBRARY - Magnum library (w/o # MAGNUM_LIBRARY_DEBUG - Debug version of Magnum library, if found
# dependencies) # MAGNUM_LIBRARY_RELEASE - Release version of Magnum library, if found
# MAGNUM_*_LIBRARY - Component libraries (w/o # MAGNUM_*_LIBRARY - Component libraries (w/o dependencies)
# dependencies) # MAGNUM_*_LIBRARY_DEBUG - Debug version of given library, if found
# MAGNUM_LIBRARY_INSTALL_DIR - Library installation directory # MAGNUM_*_LIBRARY_RELEASE - Release version of given library, if found
# MAGNUM_PLUGINS_INSTALL_DIR - Plugin installation directory # MAGNUM_LIBRARY_INSTALL_DIR - Library installation directory
# MAGNUM_PLUGINS_FONT_INSTALL_DIR - Font plugin installation # MAGNUM_PLUGINS_[DEBUG|RELEASE]_INSTALL_DIR - Plugin installation directory
# directory # MAGNUM_PLUGINS_FONT_[DEBUG|RELEASE]_INSTALL_DIR - Font plugin installation
# 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 # 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 # installation directory
# MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR - Installation dir for CMake # MAGNUM_PLUGINS_AUDIOIMPORTER_[DEBUG|RELEASE]_INSTALL_DIR - Audio importer
# Find* modules # plugin installation directory
# MAGNUM_INCLUDE_INSTALL_DIR - Header installation directory # MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR - Installation dir for CMake Find*
# MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR - Plugin header installation # modules
# directory # MAGNUM_INCLUDE_INSTALL_DIR - Header installation directory
# MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR - Plugin header installation directory
# #
# #
@ -127,8 +142,29 @@
# Dependencies # Dependencies
find_package(Corrade REQUIRED) find_package(Corrade REQUIRED)
# Magnum library # Base Magnum library
find_library(MAGNUM_LIBRARY Magnum) find_library(MAGNUM_LIBRARY_DEBUG Magnum-d)
find_library(MAGNUM_LIBRARY_RELEASE Magnum)
# 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)
endif()
# Root include dir # Root include dir
find_path(MAGNUM_INCLUDE_DIR find_path(MAGNUM_INCLUDE_DIR
@ -162,10 +198,22 @@ if(NOT _TARGET_DESKTOP_GLES EQUAL -1)
set(MAGNUM_TARGET_DESKTOP_GLES 1) set(MAGNUM_TARGET_DESKTOP_GLES 1)
endif() 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) if(NOT MAGNUM_TARGET_GLES OR MAGNUM_TARGET_DESKTOP_GLES)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
else() set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGL_gl_LIBRARY})
elseif(MAGNUM_TARGET_GLES2)
find_package(OpenGLES2 REQUIRED) 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() endif()
# On Windows and in static builds, *Application libraries need to have # On Windows and in static builds, *Application libraries need to have
@ -225,8 +273,30 @@ foreach(component ${Magnum_FIND_COMPONENTS})
# break something else # break something else
set(_tmp_prefixes ${CMAKE_FIND_LIBRARY_PREFIXES}) set(_tmp_prefixes ${CMAKE_FIND_LIBRARY_PREFIXES})
set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} "") set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES} "")
find_library(MAGNUM_${_COMPONENT}_LIBRARY ${component} find_library(MAGNUM_${_COMPONENT}_LIBRARY ${component}
PATH_SUFFIXES magnum/${_MAGNUM_${_COMPONENT}_PATH_SUFFIX}) 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(CMAKE_FIND_LIBRARY_PREFIXES ${_tmp_prefixes})
# Set library defaults, find the library # Set library defaults, find the library
@ -234,13 +304,37 @@ foreach(component ${Magnum_FIND_COMPONENTS})
set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_SUFFIX Magnum/${component}) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_SUFFIX Magnum/${component})
set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES ${component}.h) 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() endif()
# Applications # Applications
if(${component} MATCHES .+Application) if(${component} MATCHES .+Application)
set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_SUFFIX Magnum/Platform) 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 # GLUT application dependencies
if(${component} STREQUAL GlutApplication) if(${component} STREQUAL GlutApplication)
find_package(GLUT) find_package(GLUT)
@ -311,6 +405,9 @@ foreach(component ${Magnum_FIND_COMPONENTS})
set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES Atlas.h) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES Atlas.h)
endif() endif()
# The plugins don't have any dependencies, nothing additional to do for
# them
# Try to find the includes # Try to find the includes
if(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES) if(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES)
find_path(_MAGNUM_${_COMPONENT}_INCLUDE_DIR find_path(_MAGNUM_${_COMPONENT}_INCLUDE_DIR
@ -326,7 +423,11 @@ foreach(component ${Magnum_FIND_COMPONENTS})
set(Magnum_${component}_FOUND TRUE) set(Magnum_${component}_FOUND TRUE)
# Don't expose variables w/o dependencies to end users # 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. # Global aliases for Windowless*Application and *Application components.
# If already set, unset them to avoid ambiguity. # If already set, unset them to avoid ambiguity.
@ -357,41 +458,42 @@ find_package_handle_standard_args(Magnum
REQUIRED_VARS MAGNUM_LIBRARY MAGNUM_INCLUDE_DIR REQUIRED_VARS MAGNUM_LIBRARY MAGNUM_INCLUDE_DIR
HANDLE_COMPONENTS) 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})
else()
set(MAGNUM_LIBRARIES ${MAGNUM_LIBRARIES} ${OPENGLES2_LIBRARY})
endif()
# Installation dirs # Installation dirs
include(CorradeLibSuffix) include(CorradeLibSuffix)
set(MAGNUM_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) set(MAGNUM_LIBRARY_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
set(MAGNUM_PLUGINS_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum) set(MAGNUM_PLUGINS_DEBUG_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d)
set(MAGNUM_PLUGINS_FONT_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fonts) set(MAGNUM_PLUGINS_RELEASE_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum)
set(MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/fontconverters) set(MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fonts)
set(MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/imageconverters) set(MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_INSTALL_DIR}/fonts)
set(MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/importers) set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_INSTALL_DIR}/fontconverters)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR ${MAGNUM_PLUGINS_INSTALL_DIR}/audioimporters) 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_CMAKE_FIND_MODULE_INSTALL_DIR ${CMAKE_ROOT}/Modules)
set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum) set(MAGNUM_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/Magnum)
set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/MagnumPlugins) set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/MagnumPlugins)
mark_as_advanced(FORCE mark_as_advanced(FORCE
MAGNUM_LIBRARY_DEBUG
MAGNUM_LIBRARY_RELEASE
MAGNUM_LIBRARY MAGNUM_LIBRARY
MAGNUM_INCLUDE_DIR MAGNUM_INCLUDE_DIR
MAGNUM_LIBRARY_INSTALL_DIR MAGNUM_LIBRARY_INSTALL_DIR
MAGNUM_PLUGINS_INSTALL_DIR MAGNUM_PLUGINS_DEBUG_INSTALL_DIR
MAGNUM_PLUGINS_FONT_INSTALL_DIR MAGNUM_PLUGINS_RELEASE_INSTALL_DIR
MAGNUM_PLUGINS_FONTCONVERTER_INSTALL_DIR MAGNUM_PLUGINS_FONT_DEBUG_INSTALL_DIR
MAGNUM_PLUGINS_IMAGECONVERTER_INSTALL_DIR MAGNUM_PLUGINS_FONT_RELEASE_INSTALL_DIR
MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_INSTALL_DIR
MAGNUM_PLUGINS_AUDIOIMPORTER_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_CMAKE_MODULE_INSTALL_DIR
MAGNUM_INCLUDE_INSTALL_DIR MAGNUM_INCLUDE_INSTALL_DIR
MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR) MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR)
@ -406,8 +508,7 @@ if(MAGNUM_BUILD_DEPRECATED)
endif() endif()
# Get base plugin directory from main library location # 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${_MAGNUM_PLUGINS_DIR_SUFFIX}
set(MAGNUM_PLUGINS_DIR ${_MAGNUM_LIBRARY_PATH}/magnum
CACHE PATH "Base directory where to look for Magnum plugins") CACHE PATH "Base directory where to look for Magnum plugins")
# Plugin directories # Plugin directories

6
modules/FindOpenGLES3.cmake

@ -34,7 +34,11 @@
# Library # Library
find_library(OPENGLES3_LIBRARY NAMES 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 # Include dir
find_path(OPENGLES3_INCLUDE_DIR find_path(OPENGLES3_INCLUDE_DIR

5
package/archlinux/PKGBUILD

@ -13,7 +13,7 @@ provides=('magnum-git')
build() { build() {
mkdir -p "$startdir/build" mkdir -p "$startdir/build"
cd "$startdir/build/" cd "$startdir/build"
# Disable optimization (saves A LOT of compilation time) # Disable optimization (saves A LOT of compilation time)
newcxxflags=$(echo $CXXFLAGS | sed s/-O.//g | sed s/-D_FORTIFY_SOURCE=.//g) newcxxflags=$(echo $CXXFLAGS | sed s/-O.//g | sed s/-D_FORTIFY_SOURCE=.//g)
@ -29,6 +29,7 @@ build() {
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -43,7 +44,7 @@ build() {
check() { check() {
cd "$startdir/build" cd "$startdir/build"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

42
package/archlinux/PKGBUILD-android-arm

@ -0,0 +1,42 @@
# Author: mosra <mosra@centrum.cz>
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_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \
-DWITH_ANDROIDAPPLICATION=ON
ninja
}
package() {
cd "$startdir/build-android-arm"
DESTDIR="$pkgdir/" ninja install
}

42
package/archlinux/PKGBUILD-android-x86

@ -0,0 +1,42 @@
# Author: mosra <mosra@centrum.cz>
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_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \
-DWITH_ANDROIDAPPLICATION=ON
ninja
}
package() {
cd "$startdir/build-android-x86"
DESTDIR="$pkgdir/" ninja install
}

3
package/archlinux/PKGBUILD-clang

@ -33,6 +33,7 @@ build() {
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -46,7 +47,7 @@ build() {
check() { check() {
cd "$startdir/build-clang" cd "$startdir/build-clang"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

3
package/archlinux/PKGBUILD-clang-libc++

@ -35,6 +35,7 @@ build() {
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -48,7 +49,7 @@ build() {
check() { check() {
cd "$startdir/build-clang-libc++" cd "$startdir/build-clang-libc++"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

3
package/archlinux/PKGBUILD-emscripten

@ -18,7 +18,6 @@ build() {
cmake .. \ cmake .. \
-DCMAKE_MODULE_PATH="$startdir/toolchains/modules" \ -DCMAKE_MODULE_PATH="$startdir/toolchains/modules" \
-DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Emscripten.cmake" \ -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Emscripten.cmake" \
-DWITH_AUDIO=OFF \
-G Ninja -G Ninja
fi fi
@ -27,9 +26,9 @@ build() {
cmake .. \ cmake .. \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \ -DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \
-DWITH_AUDIO=OFF \
-DWITH_SDL2APPLICATION=ON \ -DWITH_SDL2APPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON -DWITH_WAVAUDIOIMPORTER=ON

3
package/archlinux/PKGBUILD-es2

@ -23,6 +23,7 @@ build() {
-DWITH_AUDIO=ON \ -DWITH_AUDIO=ON \
-DWITH_XEGLAPPLICATION=ON \ -DWITH_XEGLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -33,7 +34,7 @@ build() {
check() { check() {
cd "$startdir/build-es2" cd "$startdir/build-es2"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

3
package/archlinux/PKGBUILD-es2desktop

@ -26,6 +26,7 @@ build() {
-DWITH_GLXAPPLICATION=ON \ -DWITH_GLXAPPLICATION=ON \
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -38,7 +39,7 @@ build() {
check() { check() {
cd "$startdir/build-es2desktop" cd "$startdir/build-es2desktop"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

3
package/archlinux/PKGBUILD-es3

@ -23,6 +23,7 @@ build() {
-DWITH_AUDIO=ON \ -DWITH_AUDIO=ON \
-DWITH_XEGLAPPLICATION=ON \ -DWITH_XEGLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -33,7 +34,7 @@ build() {
check() { check() {
cd "$startdir/build-es3" cd "$startdir/build-es3"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

3
package/archlinux/PKGBUILD-es3desktop

@ -26,6 +26,7 @@ build() {
-DWITH_GLXAPPLICATION=ON \ -DWITH_GLXAPPLICATION=ON \
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -38,7 +39,7 @@ build() {
check() { check() {
cd "$startdir/build-es3desktop" cd "$startdir/build-es3desktop"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

3
package/archlinux/PKGBUILD-gcc46

@ -33,6 +33,7 @@ build() {
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -46,7 +47,7 @@ build() {
check() { check() {
cd "$startdir/build-gcc46" cd "$startdir/build-gcc46"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

3
package/archlinux/PKGBUILD-gcc47

@ -33,6 +33,7 @@ build() {
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -46,7 +47,7 @@ build() {
check() { check() {
cd "$startdir/build-gcc47" cd "$startdir/build-gcc47"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

3
package/archlinux/PKGBUILD-gcc49

@ -33,6 +33,7 @@ build() {
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -46,7 +47,7 @@ build() {
check() { check() {
cd "$startdir/build-gcc49" cd "$startdir/build-gcc49"
ctest --output-on-failure ctest --output-on-failure -j5
} }
package() { package() {

4
package/archlinux/PKGBUILD-mingw32

@ -12,7 +12,7 @@ options=('!buildflags' '!strip' 'staticlibs')
build() { build() {
mkdir -p "$startdir/build-win" mkdir -p "$startdir/build-win"
cd "$startdir/build-win/" cd "$startdir/build-win"
unset LDFLAGS unset LDFLAGS
@ -20,9 +20,11 @@ build() {
-DCMAKE_TOOLCHAIN_FILE=../toolchains/archlinux/basic-mingw32.cmake \ -DCMAKE_TOOLCHAIN_FILE=../toolchains/archlinux/basic-mingw32.cmake \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/i486-mingw32 \ -DCMAKE_INSTALL_PREFIX=/usr/i486-mingw32 \
-DWITH_AUDIO=ON \
-DWITH_GLUTAPPLICATION=ON \ -DWITH_GLUTAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \

2
package/archlinux/PKGBUILD-nacl-glibc

@ -24,6 +24,7 @@ build() {
-DWITH_NACLAPPLICATION=ON \ -DWITH_NACLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -44,6 +45,7 @@ build() {
-DWITH_NACLAPPLICATION=ON \ -DWITH_NACLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \

4
package/archlinux/PKGBUILD-nacl-newlib

@ -20,12 +20,12 @@ build() {
-DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/NaCl-newlib-x86-32.cmake" \ -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/NaCl-newlib-x86-32.cmake" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/nacl \ -DCMAKE_INSTALL_PREFIX=/usr/nacl \
-DWITH_AUDIO=OFF \
-DWITH_MAGNUMINFO=ON \ -DWITH_MAGNUMINFO=ON \
-DWITH_NACLAPPLICATION=ON \ -DWITH_NACLAPPLICATION=ON \
-DWITH_WINDOWLESSNACLAPPLICATION=ON \ -DWITH_WINDOWLESSNACLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -42,12 +42,12 @@ build() {
-DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/NaCl-newlib-x86-64.cmake" \ -DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/NaCl-newlib-x86-64.cmake" \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/nacl \ -DCMAKE_INSTALL_PREFIX=/usr/nacl \
-DWITH_AUDIO=OFF \
-DWITH_MAGNUMINFO=ON \ -DWITH_MAGNUMINFO=ON \
-DWITH_NACLAPPLICATION=ON \ -DWITH_NACLAPPLICATION=ON \
-DWITH_WINDOWLESSNACLAPPLICATION=ON \ -DWITH_WINDOWLESSNACLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \

40
package/archlinux/PKGBUILD-release

@ -2,18 +2,43 @@
pkgname=magnum pkgname=magnum
pkgver=dev.release pkgver=dev.release
pkgrel=1 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') arch=('i686' 'x86_64')
url="http://mosra.cz/blog/magnum.php" url="http://mosra.cz/blog/magnum.php"
license=('MIT') license=('MIT')
depends=('corrade' 'openal' 'sdl2' 'freeglut') depends=('corrade' 'openal' 'sdl2' 'freeglut')
makedepends=('cmake' 'ninja') makedepends=('cmake' 'ninja')
options=('!strip' 'staticlibs')
provides=('magnum-git') provides=('magnum-git')
options=('staticlibs')
build() { build() {
mkdir -p "$startdir/build" mkdir -p "$startdir/build"
cd "$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 .. \ cmake .. \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
@ -25,6 +50,7 @@ build() {
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -39,10 +65,16 @@ build() {
check() { check() {
cd "$startdir/build" cd "$startdir/build"
ctest --output-on-failure ctest --output-on-failure -j5
cd "$startdir/build-release"
ctest --output-on-failure -j5
} }
package() { package() {
cd "$startdir/build" cd "$startdir/build"
DESTDIR="$pkgdir/" ninja install DESTDIR="$pkgdir/" ninja install
cd "$startdir/build-release"
DESTDIR="$pkgdir/" ninja install/strip
} }

1
package/archlinux/magnum-git/PKGBUILD

@ -45,6 +45,7 @@ build() {
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \

1
package/ci/jenkins-emscripten.xml

@ -73,6 +73,7 @@ cmake .. \
`#-DWITH_AUDIO=ON` \ `#-DWITH_AUDIO=ON` \
-DWITH_SDL2APPLICATION=ON \ -DWITH_SDL2APPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
`#-DWITH_WAVAUDIOIMPORTER=ON` \ `#-DWITH_WAVAUDIOIMPORTER=ON` \

2
package/ci/jenkins-gltests.xml

@ -82,7 +82,7 @@ cd build-${compiler}-${libraries}-${compatibility}-${gl}
ninja ninja
ctest --output-on-failure -R GLTest || true ctest --output-on-failure -R GLTest -j5 || true
]]> ]]>
</command> </command>
</hudson.tasks.Shell> </hudson.tasks.Shell>

3
package/ci/jenkins-mingw32.xml

@ -87,6 +87,7 @@ cmake .. \
`#-DWITH_SDL2APPLICATION=ON` \ `#-DWITH_SDL2APPLICATION=ON` \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -96,7 +97,7 @@ cmake .. \
-G Ninja -G Ninja
ninja ninja
ninja install ninja install/strip
]]> ]]>
</command> </command>
</hudson.tasks.Shell> </hudson.tasks.Shell>

3
package/ci/jenkins-nacl.xml

@ -81,6 +81,7 @@ cmake .. \
-DWITH_NACLAPPLICATION=ON \ -DWITH_NACLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
`#-DWITH_WAVAUDIOIMPORTER=ON` \ `#-DWITH_WAVAUDIOIMPORTER=ON` \
@ -88,7 +89,7 @@ cmake .. \
-G Ninja -G Ninja
ninja ninja
ninja install ninja install/strip
]]> ]]>
</command> </command>
</hudson.tasks.Shell> </hudson.tasks.Shell>

11
package/ci/jenkins.xml

@ -99,22 +99,27 @@ fi
if [ ${gl} = "desktop" ] ; then if [ ${gl} = "desktop" ] ; then
desktop_flag=ON desktop_flag=ON
es_flag=OFF
windowless_flag=ON windowless_flag=ON
elif [ ${gl} = "es2" ] ; then elif [ ${gl} = "es2" ] ; then
gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=ON" gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=ON"
desktop_flag=OFF desktop_flag=OFF
es_flag=ON
windowless_flag=OFF windowless_flag=OFF
elif [ ${gl} = "es2desktop" ] ; then elif [ ${gl} = "es2desktop" ] ; then
gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=ON -DTARGET_DESKTOP_GLES=ON" gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=ON -DTARGET_DESKTOP_GLES=ON"
desktop_flag=OFF desktop_flag=OFF
es_flag=OFF
windowless_flag=ON windowless_flag=ON
elif [ ${gl} = "es3" ] ; then elif [ ${gl} = "es3" ] ; then
gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=OFF" gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=OFF"
desktop_flag=OFF desktop_flag=OFF
es_flag=ON
windowless_flag=OFF windowless_flag=OFF
elif [ ${gl} = "es3desktop" ] ; then elif [ ${gl} = "es3desktop" ] ; then
gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=OFF -DTARGET_DESKTOP_GLES=ON" gl_flags="-DTARGET_GLES=ON -DTARGET_GLES2=OFF -DTARGET_DESKTOP_GLES=ON"
desktop_flag=OFF desktop_flag=OFF
es_flag=OFF
windowless_flag=ON windowless_flag=ON
fi fi
@ -137,8 +142,10 @@ cmake .. \
-DWITH_GLUTAPPLICATION=ON \ -DWITH_GLUTAPPLICATION=ON \
-DWITH_GLXAPPLICATION=ON \ -DWITH_GLXAPPLICATION=ON \
-DWITH_SDL2APPLICATION=ON \ -DWITH_SDL2APPLICATION=ON \
-DWITH_XEGLAPPLICATION=${es_flag} \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=${desktop_flag} \ -DWITH_MAGNUMFONTCONVERTER=${desktop_flag} \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
@ -148,8 +155,8 @@ cmake .. \
-G Ninja -G Ninja
ninja ninja
ctest --output-on-failure -E GLTest || true ctest --output-on-failure -E GLTest -j5 || true
ninja install ninja install/strip
]]> ]]>
</command> </command>
</hudson.tasks.Shell> </hudson.tasks.Shell>

1
package/debian/rules vendored

@ -11,6 +11,7 @@ override_dh_auto_configure:
-DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \

77
src/Magnum/AbstractShaderProgram.cpp

@ -271,40 +271,53 @@ void AbstractShaderProgram::bindFragmentDataLocationIndexed(UnsignedInt location
} }
#endif #endif
bool AbstractShaderProgram::link() { bool AbstractShaderProgram::link(std::initializer_list<std::reference_wrapper<AbstractShaderProgram>> shaders) {
/* Link shader program */ bool allSuccess = true;
glLinkProgram(_id);
/* Invoke (possibly parallel) linking on all shaders */
/* Check link status */ for(AbstractShaderProgram& shader: shaders) glLinkProgram(shader._id);
GLint success, logLength;
glGetProgramiv(_id, GL_LINK_STATUS, &success); /* After linking phase, check status of all shaders */
glGetProgramiv(_id, GL_INFO_LOG_LENGTH, &logLength); Int i = 1;
for(AbstractShaderProgram& shader: shaders) {
/* Error or warning message. The string is returned null-terminated, scrap GLint success, logLength;
the \0 at the end afterwards */ glGetProgramiv(shader._id, GL_LINK_STATUS, &success);
std::string message(logLength, '\n'); glGetProgramiv(shader._id, GL_INFO_LOG_LENGTH, &logLength);
if(message.size() > 1)
glGetProgramInfoLog(_id, message.size(), nullptr, &message[0]); /* Error or warning message. The string is returned null-terminated,
message.resize(std::max(logLength, 1)-1); scrap the \0 at the end afterwards */
std::string message(logLength, '\n');
/* Show error log and delete shader */ if(message.size() > 1)
if(!success) { glGetProgramInfoLog(shader._id, message.size(), nullptr, &message[0]);
Error out; message.resize(std::max(logLength, 1)-1);
out.setFlag(Debug::NewLineAtTheEnd, false);
out.setFlag(Debug::SpaceAfterEachValue, false); /* Show error log */
out << "AbstractShaderProgram: linking failed with the following message:\n" if(!success) {
<< message; Error out;
out.setFlag(Debug::NewLineAtTheEnd, false);
/* Or just warnings, if there are any */ out.setFlag(Debug::SpaceAfterEachValue, false);
} else if(!message.empty()) { out << "AbstractShaderProgram::link(): linking";
Debug out; if(shaders.size() != 1) out << " of shader " << std::to_string(i);
out.setFlag(Debug::NewLineAtTheEnd, false); out << " failed with the following message:\n"
out.setFlag(Debug::SpaceAfterEachValue, false); << message;
out << "AbstractShaderProgram: linking succeeded with the following message:\n"
<< message; /* Or just warnings, if any */
} else if(!message.empty()) {
Warning 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) { Int AbstractShaderProgram::uniformLocation(const std::string& name) {

156
src/Magnum/AbstractShaderProgram.h

@ -29,6 +29,7 @@
* @brief Class @ref Magnum::AbstractShaderProgram * @brief Class @ref Magnum::AbstractShaderProgram
*/ */
#include <functional>
#include <string> #include <string>
#include <Corrade/Containers/EnumSet.h> #include <Corrade/Containers/EnumSet.h>
@ -63,27 +64,21 @@ enum: UnsignedInt {
NormalOutput = 1 NormalOutput = 1
}; };
@endcode @endcode
- **Uniform locations** for setting uniform data (see below) (private - **Constructor**, which loads, compiles and attaches particular shaders and
variables), for example: links the program together, 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:
@code @code
MyShader() { MyShader() {
// Load shaders, compile them and attach them to the program // Load shader sources
Shader vert(Version::GL430, Shader::Type::Vertex); 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); Shader frag(Version::GL430, Shader::Type::Fragment);
frag.attachFile("PhongShader.vert"); vert.addFile("PhongShader.vert");
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); 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); attachShader(frag);
// Link the program together // Link the program together
@ -94,24 +89,29 @@ MyShader() {
protected @ref setUniform() functions. For usability purposes you can protected @ref setUniform() functions. For usability purposes you can
implement also method chaining. Example: implement also method chaining. Example:
@code @code
MyShader& setTransformation(const Matrix4& matrix) { MyShader& setProjectionMatrix(const Matrix4& matrix) {
setUniform(TransformationUniform, matrix); setUniform(0, matrix);
return *this;
}
MyShader& setTransformationMatrix(const Matrix4& matrix) {
setUniform(1, matrix);
return *this; return *this;
} }
MyShader& setProjection(const Matrix4& matrix) { MyShader& setNormalMatrix(const Matrix3x3& matrix) {
setUniform(ProjectionUniform, matrix); setUniform(2, matrix);
return *this; return *this;
} }
@endcode @endcode
- **Texture setting functions** in which you bind the textures to particular - <strong>%Texture setting functions</strong> in which you bind the textures
layers using @ref AbstractTexture::bind() and equivalent, for example: to particular texture units using @ref Texture::bind() "*Texture::bind()"
and equivalents, for example:
@code @code
MyShader& setDiffuseTexture(Texture2D& texture) { MyShader& setDiffuseTexture(Texture2D& texture) {
texture->bind(0); texture.bind(0);
return *this; return *this;
} }
MyShader& setSpecularTexture(Texture2D& texture) { MyShader& setSpecularTexture(Texture2D& texture) {
texture->bind(1); texture.bind(1);
return *this; return *this;
} }
@endcode @endcode
@ -141,7 +141,7 @@ If you don't have the required extension, declare the attributes without
`layout()` qualifier and use functions @ref bindAttributeLocation() and `layout()` qualifier and use functions @ref bindAttributeLocation() and
@ref bindFragmentDataLocation() / @ref bindFragmentDataLocationIndexed() between @ref bindFragmentDataLocation() / @ref bindFragmentDataLocationIndexed() between
attaching the shaders and linking the program. Note that additional syntax 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 @code
in vec4 position; in vec4 position;
in vec3 normal; in vec3 normal;
@ -191,21 +191,24 @@ code, e.g.:
@code @code
// GLSL 4.30, or // GLSL 4.30, or
#extension GL_ARB_explicit_uniform_location: enable #extension GL_ARB_explicit_uniform_location: enable
layout(location = 0) uniform mat4 transformation; layout(location = 0) uniform mat4 projectionMatrix;
layout(location = 1) uniform mat4 projection; layout(location = 1) uniform mat4 transformationMatrix;
layout(location = 2) uniform mat3 normalMatrix;
@endcode @endcode
If you don't have the required extension, declare the uniforms without the If you don't have the required extension, declare the uniforms without the
`layout()` qualifier and get uniform location using @ref uniformLocation() `layout()` qualifier, get uniform location using @ref uniformLocation() *after*
*after* linking stage. Note that additional syntax changes may be needed for linking stage and then use the queried location in uniform setting functions.
GLSL 1.20 and GLSL ES 1.0. Note that additional syntax changes may be needed for GLSL 1.20 and GLSL ES.
@code @code
uniform mat4 transformation; uniform mat4 projectionMatrix;
uniform mat4 projection; uniform mat4 transformationMatrix;
uniform mat3 normalMatrix;
@endcode @endcode
@code @code
Int transformationUniform = uniformLocation("transformation"); Int projectionMatrixUniform = uniformLocation("projectionMatrix");
Int projectionUniform = uniformLocation("projection"); Int transformationMatrixUniform = uniformLocation("transformationMatrix");
Int normalMatrixUniform = uniformLocation("normalMatrix");
@endcode @endcode
@see @ref maxUniformLocations() @see @ref maxUniformLocations()
@ -216,10 +219,10 @@ Int projectionUniform = uniformLocation("projection");
@ref Magnum::AbstractShaderProgram::uniformLocation() "uniformLocation()" @ref Magnum::AbstractShaderProgram::uniformLocation() "uniformLocation()"
instead. 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 The preferred workflow is to specify texture binding unit directly in the
code, e.g.: shader code, e.g.:
@code @code
// GLSL 4.20, or // GLSL 4.20, or
#extension GL_ARB_shading_language_420pack: enable #extension GL_ARB_shading_language_420pack: enable
@ -227,25 +230,24 @@ layout(binding = 0) uniform sampler2D diffuseTexture;
layout(binding = 1) uniform sampler2D specularTexture; layout(binding = 1) uniform sampler2D specularTexture;
@endcode @endcode
If you don't have the required extension (or if you want to change the layer If you don't have the required extension, declare the uniforms without the
later), declare the uniforms without the `layout()` qualifier and set the `layout()` qualifier and set the texture binding unit using
texture layer uniform using @ref setUniform(Int, const T&) "setUniform(Int, Int)". @ref setUniform(Int, const T&) "setUniform(Int, Int)". Note that additional
Note that additional syntax changes may be needed for GLSL 1.20 and GLSL ES syntax changes may be needed for GLSL 1.20 and GLSL ES 1.0.
1.0.
@code @code
uniform sampler2D diffuseTexture; uniform sampler2D diffuseTexture;
uniform sampler2D specularTexture; uniform sampler2D specularTexture;
@endcode @endcode
@code @code
setUniform(DiffuseTextureUniform, 0); setUniform(uniformLocation("diffuseTexture"), 0);
setUniform(SpecularTextureUniform, 1); setUniform(uniformLocation("specularTexture"), 1);
@endcode @endcode
@see @ref Shader::maxTextureImageUnits() @see @ref Shader::maxTextureImageUnits()
@requires_gl42 %Extension @extension{ARB,shading_language_420pack} for explicit @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)". @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)" @ref Magnum::AbstractShaderProgram::setUniform(Int, const T&) "setUniform(Int, Int)"
instead. instead.
@ -320,8 +322,6 @@ comes in handy.
@see @ref portability-shaders @see @ref portability-shaders
@todo Use Containers::ArrayReference for setting uniform arrays? @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}) @todo `GL_NUM_{PROGRAM,SHADER}_BINARY_FORMATS` + `GL_{PROGRAM,SHADER}_BINARY_FORMATS` (vector), (@extension{ARB,ES2_compatibility})
*/ */
class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject { class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
@ -343,15 +343,6 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
*/ */
static Int maxVertexAttributes(); 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 #ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Max supported atomic counter buffer size * @brief Max supported atomic counter buffer size
@ -562,6 +553,21 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
#endif #endif
protected: 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<std::reference_wrapper<AbstractShaderProgram>> shaders);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Allow retrieving program binary * @brief Allow retrieving program binary
@ -655,14 +661,12 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
/** /**
* @brief Link the shader * @brief Link the shader
* *
* Returns `false` if linking failed, `true` otherwise. Compiler * Links single shader. If possible, prefer to link multiple shaders
* message (if any) is printed to error output. All attached shaders * at once using @ref link(std::initializer_list<std::reference_wrapper<AbstractShaderProgram>>)
* must be compiled with @ref Shader::compile() before linking. * for improved performance, see its documentation for more
* @see @fn_gl{LinkProgram}, @fn_gl{GetProgram} with * information.
* @def_gl{LINK_STATUS} and @def_gl{INFO_LOG_LENGTH},
* @fn_gl{GetProgramInfoLog}
*/ */
bool link(); bool link() { return link({*this}); }
/** /**
* @brief Get uniform location * @brief Get uniform location
@ -963,9 +967,17 @@ template<UnsignedInt location, class T> class AbstractShaderProgram::Attribute {
* @brief Type * @brief Type
* *
* Type used in shader code. * Type used in shader code.
* @see @ref DataType * @see @ref ScalarType, @ref DataType
*/
typedef T Type;
/**
* @brief Scalar type
*
* The underlying scalar type of the attribute.
* @see @ref Type, @ref DataType
*/ */
typedef typename Implementation::Attribute<T>::Type Type; typedef typename Implementation::Attribute<T>::ScalarType ScalarType;
/** /**
* @brief Component count * @brief Component count
@ -1257,7 +1269,7 @@ template<class> struct Attribute;
/* Base for float attributes */ /* Base for float attributes */
struct FloatAttribute { struct FloatAttribute {
typedef Float Type; typedef Float ScalarType;
enum class DataType: GLenum { enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE, UnsignedByte = GL_UNSIGNED_BYTE,
@ -1300,7 +1312,7 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, FloatAttribute::DataType value);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/* Base for int attributes */ /* Base for int attributes */
struct IntAttribute { struct IntAttribute {
typedef Int Type; typedef Int ScalarType;
enum class DataType: GLenum { enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE, UnsignedByte = GL_UNSIGNED_BYTE,
@ -1327,7 +1339,7 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value);
/* Base for unsigned int attributes */ /* Base for unsigned int attributes */
struct UnsignedIntAttribute { struct UnsignedIntAttribute {
typedef UnsignedInt Type; typedef UnsignedInt ScalarType;
typedef IntAttribute::DataType DataType; typedef IntAttribute::DataType DataType;
#if !defined(CORRADE_GCC45_COMPATIBILITY) && !defined(CORRADE_MSVC2013_COMPATIBILITY) #if !defined(CORRADE_GCC45_COMPATIBILITY) && !defined(CORRADE_MSVC2013_COMPATIBILITY)
@ -1349,7 +1361,7 @@ struct UnsignedIntAttribute {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/* Base for double attributes */ /* Base for double attributes */
struct DoubleAttribute { struct DoubleAttribute {
typedef Double Type; typedef Double ScalarType;
enum class DataType: GLenum { enum class DataType: GLenum {
Double = GL_DOUBLE Double = GL_DOUBLE
@ -1372,7 +1384,7 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value);
/* Floating-point four-component vector is absolutely special case */ /* Floating-point four-component vector is absolutely special case */
template<> struct Attribute<Math::Vector<4, Float>> { template<> struct Attribute<Math::Vector<4, Float>> {
typedef Float Type; typedef Float ScalarType;
enum class Components: GLint { enum class Components: GLint {
One = 1, One = 1,

211
src/Magnum/AbstractTexture.cpp

@ -48,7 +48,6 @@ namespace Magnum {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); } Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); }
Int AbstractTexture::maxSupportedLayerCount() { return Shader::maxCombinedTextureImageUnits(); }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -92,6 +91,72 @@ Int AbstractTexture::maxIntegerSamples() {
} }
#endif #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 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
void AbstractTexture::bind(const Int firstTextureUnit, std::initializer_list<AbstractTexture*> textures) {
/* State tracker is updated in the implementations */
Context::current()->state().texture->bindMultiImplementation(firstTextureUnit, textures);
}
void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, std::initializer_list<AbstractTexture*> 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<AbstractTexture*> textures) {
Implementation::TextureState* const textureState = Context::current()->state().texture;
/* Create array of IDs and also update bindings in state tracker */
Containers::Array<GLuint> 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) { AbstractTexture::AbstractTexture(GLenum target): _target(target) {
glGenTextures(1, &_id); glGenTextures(1, &_id);
} }
@ -101,9 +166,9 @@ AbstractTexture::~AbstractTexture() {
if(!_id) return; if(!_id) return;
/* Remove all bindings */ /* Remove all bindings */
std::vector<GLuint>& bindings = Context::current()->state().texture->bindings; std::vector<std::pair<GLenum, GLuint>>& bindings = Context::current()->state().texture->bindings;
for(auto it = bindings.begin(); it != bindings.end(); ++it) for(auto it = bindings.begin(); it != bindings.end(); ++it)
if(*it == _id) *it = 0; if(it->second == _id) *it = {};
glDeleteTextures(1, &_id); glDeleteTextures(1, &_id);
} }
@ -117,32 +182,53 @@ AbstractTexture& AbstractTexture::setLabel(const std::string& label) {
return *this; return *this;
} }
void AbstractTexture::bind(Int layer) { void AbstractTexture::bind(Int textureUnit) {
Implementation::TextureState* const textureState = Context::current()->state().texture; Implementation::TextureState* const textureState = Context::current()->state().texture;
/* If already bound in given layer, nothing to do */ /* If already bound in given texture unit, nothing to do */
if(textureState->bindings[layer] == _id) return; if(textureState->bindings[textureUnit].second == _id) return;
(this->*Context::current()->state().texture->bindImplementation)(layer); /* 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 layer) { void AbstractTexture::bindImplementationDefault(GLint textureUnit) {
Implementation::TextureState* const textureState = Context::current()->state().texture; Implementation::TextureState* const textureState = Context::current()->state().texture;
/* Change to given layer, if not already there */ /* Activate given texture unit if not already active, update state tracker */
if(textureState->currentLayer != layer) if(textureState->currentTextureUnit != textureUnit)
glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = layer)); glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = textureUnit));
/* Bind the texture to the layer */ glBindTexture(_target, _id);
glBindTexture(_target, (textureState->bindings[layer] = _id));
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::bindImplementationDSA(GLint layer) { void AbstractTexture::bindImplementationMulti(GLint textureUnit) {
glBindMultiTextureEXT(GL_TEXTURE0 + layer, _target, (Context::current()->state().texture->bindings[layer] = _id)); glBindTextures(textureUnit, 1, &_id);
}
void AbstractTexture::bindImplementationDSA(GLint textureUnit) {
glBindMultiTextureEXT(GL_TEXTURE0 + textureUnit, _target, _id);
}
#endif
#ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::setBaseLevel(Int level) {
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_BASE_LEVEL, level);
} }
#endif #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) { void AbstractTexture::setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap) {
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap)); (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap));
} }
@ -159,6 +245,16 @@ void AbstractTexture::setBorderColor(const Color4& color) {
#endif #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) { void AbstractTexture::setMaxAnisotropy(const Float anisotropy) {
(this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy); (this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy);
} }
@ -183,21 +279,26 @@ void AbstractTexture::mipmapImplementationDSA() {
#endif #endif
void AbstractTexture::bindInternal() { void AbstractTexture::bindInternal() {
/* Using glBindTextures() here is meaningless, because the non-DSA
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; Implementation::TextureState* const textureState = Context::current()->state().texture;
/* If the texture is already bound in current layer, nothing to do */ /* If the texture is already bound in current unit, nothing to do */
if(textureState->bindings[textureState->currentLayer] == _id) if(textureState->bindings[textureState->currentTextureUnit].second == _id)
return; return;
/* Set internal layer as active if not already */ /* Set internal unit as active if not already, update state tracker */
CORRADE_INTERNAL_ASSERT(textureState->maxLayers > 1); CORRADE_INTERNAL_ASSERT(textureState->maxTextureUnits > 1);
const GLint internalLayer = textureState->maxLayers-1; const GLint internalTextureUnit = textureState->maxTextureUnits-1;
if(textureState->currentLayer != internalLayer) if(textureState->currentTextureUnit != internalTextureUnit)
glActiveTexture(GL_TEXTURE0 + (textureState->currentLayer = internalLayer)); glActiveTexture(GL_TEXTURE0 + (textureState->currentTextureUnit = internalTextureUnit));
/* Bind the texture to internal layer, if not already */ /* Bind the texture to internal unit if not already, update state tracker */
if(textureState->bindings[internalLayer] != _id) if(textureState->bindings[internalTextureUnit].second == _id) return;
glBindTexture(_target, (textureState->bindings[internalLayer] = _id)); textureState->bindings[internalTextureUnit] = {_target, _id};
glBindTexture(_target, _id);
} }
ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) { ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat internalFormat) {
@ -602,6 +703,26 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat
} }
#endif #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::setMaxAnisotropyImplementationNoOp(GLfloat) {}
void AbstractTexture::setMaxAnisotropyImplementationExt(GLfloat anisotropy) { void AbstractTexture::setMaxAnisotropyImplementationExt(GLfloat anisotropy) {
@ -768,6 +889,36 @@ void AbstractTexture::storageImplementationDSA(GLenum target, GLsizei levels, Te
} }
#endif #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 #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) { void AbstractTexture::getImageImplementationDefault(const GLenum target, const GLint level, const ColorFormat format, const ColorType type, const std::size_t, GLvoid* const data) {
bindInternal(); bindInternal();
@ -975,6 +1126,16 @@ void AbstractTexture::DataHelper<3>::setStorage(AbstractTexture& texture, const
(texture.*Context::current()->state().texture->storage3DImplementation)(target, levels, internalFormat, size); (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 #ifndef MAGNUM_TARGET_GLES
void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) { void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, const ImageReference1D& image) {
Buffer::unbind(Buffer::Target::PixelUnpack); Buffer::unbind(Buffer::Target::PixelUnpack);

145
src/Magnum/AbstractTexture.h

@ -49,20 +49,31 @@ Encapsulates one OpenGL texture object. See @ref Texture, @ref CubeMapTexture
and @ref CubeMapTextureArray documentation for more information and usage and @ref CubeMapTextureArray documentation for more information and usage
examples. 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 @section AbstractTexture-performance-optimization Performance optimizations and security
The engine tracks currently bound textures in all available layers to avoid The engine tracks currently bound textures in all available texture units to
unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. %Texture avoid unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}.
configuration functions use dedicated highest available texture layer to not %Texture configuration functions use dedicated highest available texture unit
affect active bindings in user layers. %Texture limits and to not affect active bindings in user units. %Texture limits and
implementation-defined values (such as @ref maxColorSamples()) are cached, so implementation-defined values (such as @ref maxColorSamples()) are cached, so
repeated queries don't result in repeated @fn_gl{Get} calls. repeated queries don't result in repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, @ref bind() uses If extension @extension{ARB,multi_bind} is available, @ref bind() uses
DSA function to avoid unnecessary calls to @fn_gl{ActiveTexture}. Also all @fn_gl{BindTextures} to avoid unnecessary calls to @fn_gl{ActiveTexture}.
texture configuration and data updating functions use DSA functions to avoid Otherwise, if extension @extension{EXT,direct_state_access} is available,
unnecessary calls to @fn_gl{ActiveTexture} and @fn_gl{BindTexture}. See @ref bind() uses @fn_gl_extension{BindMultiTexture,EXT,direct_state_access}
respective function documentation for more information. 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 If extension @extension{ARB,robustness} is available, image reading operations
(such as @ref Texture::image()) are protected from buffer overflow. However, if (such as @ref Texture::image()) are protected from buffer overflow. However, if
@ -72,7 +83,7 @@ there isn't any function combining both features.
To achieve least state changes, fully configure each texture in one run -- 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 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 and *then* set the data, so OpenGL can optimize them to match the settings. To
avoid redundant consistency checks and memory reallocations when updating avoid redundant consistency checks and memory reallocations when updating
texture data, set texture storage at once using @ref Texture::setStorage() "setStorage()" texture data, set texture storage at once using @ref Texture::setStorage() "setStorage()"
@ -85,7 +96,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()" available, the feature is emulated with sequence of @ref Texture::setImage() "setImage()"
calls. 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 @ref Texture::invalidateSubImage() "invalidateSubImage()" if you don't need
texture data anymore to avoid unnecessary memory operations performed by OpenGL texture data anymore to avoid unnecessary memory operations performed by OpenGL
in order to preserve the data. If running on OpenGL ES or extension in order to preserve the data. If running on OpenGL ES or extension
@ -103,6 +114,10 @@ functions do nothing.
@todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented @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 `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done
@todo Query for immutable levels (@extension{ARB,ES3_compatibility}) @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 { class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
friend struct Implementation::TextureState; friend struct Implementation::TextureState;
@ -117,15 +132,6 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxLayers(); static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxLayers();
#endif #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 #ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Max supported color sample count * @brief Max supported color sample count
@ -162,12 +168,32 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
#endif #endif
/** /**
* @brief Destructor * @brief Unbind any texture from given texture unit
* *
* Deletes associated OpenGL texture. * If @extension{ARB,multi_bind} (part of OpenGL 4.4) or
* @see @fn_gl{DeleteTextures} * @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}
*/ */
~AbstractTexture(); 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<AbstractTexture*> textures);
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
AbstractTexture(const AbstractTexture&) = delete; AbstractTexture(const AbstractTexture&) = delete;
@ -175,6 +201,14 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
/** @brief Move constructor */ /** @brief Move constructor */
AbstractTexture(AbstractTexture&& other) noexcept; AbstractTexture(AbstractTexture&& other) noexcept;
/**
* @brief Destructor
*
* Deletes associated OpenGL texture.
* @see @fn_gl{DeleteTextures}
*/
~AbstractTexture();
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
AbstractTexture& operator=(const AbstractTexture&) = delete; AbstractTexture& operator=(const AbstractTexture&) = delete;
@ -211,19 +245,20 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
GLuint id() const { return _id; } 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 * If @extension{ARB,multi_bind} (part of OpenGL 4.4) or
* texture can be bound to given layer. If @extension{EXT,direct_state_access} * @extension{EXT,direct_state_access} is not available, the texture
* is not available, the layer is made active before binding the * unit is made active before binding the texture.
* texture.
* @note This function is meant to be used only internally from * @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation * @ref AbstractShaderProgram subclasses. See its documentation
* for more information. * for more information.
* @see @ref maxLayers(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} or * @see @ref bind(Int, std::initializer_list<AbstractTexture*>),
* @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} * @ref unbind(), @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 #ifdef DOXYGEN_GENERATING_OUTPUT
private: private:
@ -234,12 +269,18 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
explicit AbstractTexture(GLenum target); 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 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 setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap);
void setMagnificationFilter(Sampler::Filter filter); void setMagnificationFilter(Sampler::Filter filter);
void setBorderColor(const Color4& color); void setBorderColor(const Color4& color);
void setBorderColor(const Vector4i& color);
void setBorderColor(const Vector4ui& color);
void setMaxAnisotropy(Float anisotropy); void setMaxAnisotropy(Float anisotropy);
void invalidateImage(Int level); void invalidateImage(Int level);
void generateMipmap(); void generateMipmap();
@ -252,24 +293,36 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
GLenum _target; GLenum _target;
private: private:
void MAGNUM_LOCAL bindImplementationDefault(GLint layer); static void MAGNUM_LOCAL unbindImplementationDefault(GLint textureUnit);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL bindImplementationDSA(GLint layer); static void MAGNUM_LOCAL unbindImplementationMulti(GLint textureUnit);
static void MAGNUM_LOCAL unbindImplementationDSA(GLint textureUnit);
#endif #endif
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value); static void MAGNUM_LOCAL bindImplementationFallback(GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value); static void MAGNUM_LOCAL bindImplementationMulti(GLint firstTextureUnit, std::initializer_list<AbstractTexture*> textures);
#endif #endif
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value); void MAGNUM_LOCAL bindImplementationDefault(GLint textureUnit);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value); void MAGNUM_LOCAL bindImplementationMulti(GLint textureUnit);
void MAGNUM_LOCAL bindImplementationDSA(GLint textureUnit);
#endif #endif
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLint* values);
#endif
#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 GLfloat* values);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLuint* values);
void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLint* values);
#endif #endif
void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat); void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat);
@ -303,6 +356,16 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); void MAGNUM_LOCAL storageImplementationDSA(GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size);
#endif #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 #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 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); void MAGNUM_LOCAL getImageImplementationDSA(GLenum target, GLint level, ColorFormat format, ColorType type, std::size_t dataSize, GLvoid* data);
@ -399,6 +462,8 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<2> {
static void setStorage(AbstractTexture& texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); 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); static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference2D& image);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image); static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage2D& image);
@ -434,6 +499,8 @@ template<> struct MAGNUM_EXPORT AbstractTexture::DataHelper<3> {
static void setStorage(AbstractTexture& texture, GLenum target, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); 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); static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, const ImageReference3D& image);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage3D& image); static void setImage(AbstractTexture& texture, GLenum target, GLint level, TextureFormat internalFormat, BufferImage3D& image);

1
src/Magnum/Audio/CMakeLists.txt

@ -46,6 +46,7 @@ set(MagnumAudio_HEADERS
visibility.h) visibility.h)
add_library(MagnumAudio ${SHARED_OR_STATIC} ${MagnumAudio_SOURCES}) 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}) target_link_libraries(MagnumAudio ${CORRADE_PLUGINMANAGER_LIBRARIES} ${OPENAL_LIBRARY})
install(TARGETS MagnumAudio install(TARGETS MagnumAudio

39
src/Magnum/Buffer.h

@ -166,6 +166,23 @@ for(std::size_t i: {7, 27, 56, 128}) {
CORRADE_INTERNAL_ASSERT_OUTPUT(buffer.unmap()); CORRADE_INTERNAL_ASSERT_OUTPUT(buffer.unmap());
@endcode @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 @section Buffer-performance-optimization Performance optimizations
The engine tracks currently bound buffers to avoid unnecessary calls to The engine tracks currently bound buffers to avoid unnecessary calls to
@ -661,17 +678,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
*/ */
Buffer& setData(Containers::ArrayReference<const void> data, BufferUsage usage); Buffer& setData(Containers::ArrayReference<const void> data, BufferUsage usage);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief setData(Containers::ArrayReference<const void>, BufferUsage)
* @deprecated Use @ref Magnum::Buffer::setData(Containers::ArrayReference<const void>, BufferUsage) "setData(Containers::ArrayReference<const void>, 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 */ /** @overload */
template<class T> Buffer& setData(const std::vector<T>& data, BufferUsage usage) { template<class T> Buffer& setData(const std::vector<T>& data, BufferUsage usage) {
setData({data.data(), data.size()}, usage); setData({data.data(), data.size()}, usage);
@ -698,17 +704,6 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
*/ */
Buffer& setSubData(GLintptr offset, Containers::ArrayReference<const void> data); Buffer& setSubData(GLintptr offset, Containers::ArrayReference<const void> data);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief setSubData(GLintptr, Containers::ArrayReference<const void>)
* @deprecated Use @ref Magnum::Buffer::setSubData(GLintptr, Containers::ArrayReference<const void>) "setSubData(GLintptr, Containers::ArrayReference<const void>)"
* 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 */ /** @overload */
template<class T> Buffer& setSubData(GLintptr offset, const std::vector<T>& data) { template<class T> Buffer& setSubData(GLintptr offset, const std::vector<T>& data) {
setSubData(offset, {data.data(), data.size()}); setSubData(offset, {data.data(), data.size()});

9
src/Magnum/CMakeLists.txt

@ -130,9 +130,7 @@ set(Magnum_HEADERS
# Deprecated headers # Deprecated headers
if(BUILD_DEPRECATED) if(BUILD_DEPRECATED)
set(Magnum_HEADERS ${Magnum_HEADERS} set(Magnum_HEADERS ${Magnum_HEADERS}
DebugMarker.h DebugMarker.h)
ImageFormat.h
Swizzle.h)
endif() endif()
# Desktop-only headers and libraries # Desktop-only headers and libraries
@ -162,6 +160,7 @@ add_library(MagnumMathObjects OBJECT ${MagnumMath_SRCS})
add_library(Magnum ${SHARED_OR_STATIC} add_library(Magnum ${SHARED_OR_STATIC}
${Magnum_SRCS} ${Magnum_SRCS}
$<TARGET_OBJECTS:MagnumMathObjects>) $<TARGET_OBJECTS:MagnumMathObjects>)
set_target_properties(Magnum PROPERTIES DEBUG_POSTFIX "-d")
# TODO: fix when CMake sets target_EXPORTS for OBJECT targets as well # TODO: fix when CMake sets target_EXPORTS for OBJECT targets as well
if(NOT BUILD_STATIC OR BUILD_STATIC_PIC) if(NOT BUILD_STATIC OR BUILD_STATIC_PIC)
@ -237,7 +236,9 @@ if(BUILD_TESTS)
# Libraries with graceful assert for testing # Libraries with graceful assert for testing
add_library(MagnumMathTestLib ${SHARED_OR_STATIC} add_library(MagnumMathTestLib ${SHARED_OR_STATIC}
$<TARGET_OBJECTS:MagnumMathObjects>) $<TARGET_OBJECTS:MagnumMathObjects>)
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}) target_link_libraries(MagnumMathTestLib ${CORRADE_UTILITY_LIBRARY})
# On Windows we need to install first and then run the tests to avoid "DLL # On Windows we need to install first and then run the tests to avoid "DLL

110
src/Magnum/Context.cpp

@ -61,6 +61,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,texture_filter_anisotropic), _extension(GL,EXT,texture_filter_anisotropic),
_extension(GL,EXT,texture_mirror_clamp), _extension(GL,EXT,texture_mirror_clamp),
_extension(GL,EXT,direct_state_access), _extension(GL,EXT,direct_state_access),
_extension(GL,EXT,shader_integer_mix),
_extension(GL,EXT,debug_label), _extension(GL,EXT,debug_label),
_extension(GL,EXT,debug_marker), _extension(GL,EXT,debug_marker),
_extension(GL,GREMEDY,string_marker)}; _extension(GL,GREMEDY,string_marker)};
@ -213,6 +214,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,ANGLE,framebuffer_multisample), _extension(GL,ANGLE,framebuffer_multisample),
_extension(GL,ANGLE,depth_texture), _extension(GL,ANGLE,depth_texture),
_extension(GL,APPLE,framebuffer_multisample), _extension(GL,APPLE,framebuffer_multisample),
_extension(GL,APPLE,texture_max_level),
_extension(GL,ARM,rgba8), _extension(GL,ARM,rgba8),
_extension(GL,EXT,texture_type_2_10_10_10_REV), _extension(GL,EXT,texture_type_2_10_10_10_REV),
_extension(GL,EXT,discard_framebuffer), _extension(GL,EXT,discard_framebuffer),
@ -283,7 +285,7 @@ Context::Context() {
everything possible. */ everything possible. */
if(ogl_LoadFunctions() == ogl_LOAD_FAILED) { if(ogl_LoadFunctions() == ogl_LOAD_FAILED) {
Error() << "ExtensionWrangler: cannot initialize glLoadGen"; Error() << "ExtensionWrangler: cannot initialize glLoadGen";
std::exit(1); std::exit(64);
} }
#endif #endif
@ -313,7 +315,7 @@ Context::Context() {
const std::string version = versionString(); const std::string version = versionString();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(version.compare(0, 4, "2.1 ") == 0) 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) if(version.find("WebGL 1") != std::string::npos)
#else #else
if(version.find("OpenGL ES 2.0") != std::string::npos) if(version.find("OpenGL ES 2.0") != std::string::npos)
@ -327,7 +329,7 @@ Context::Context() {
#endif #endif
} else { } else {
Error() << "Context: unsupported version string:" << version; Error() << "Context: unsupported version string:" << version;
std::exit(1); std::exit(65);
} }
} }
#endif #endif
@ -346,17 +348,17 @@ Context::Context() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!isVersionSupported(Version::GL210)) if(!isVersionSupported(Version::GL210))
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(!isVersionSupported(Version::GLES200)) if(_version != Version::GLES200)
#else #else
if(!isVersionSupported(Version::GLES300)) if(_version != Version::GLES300)
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
Error() << "Context: unsupported OpenGL version" << Int(_version); Error() << "Context: unsupported OpenGL version" << Magnum::version(_version);
#else #else
Error() << "Context: unsupported OpenGL ES version" << Int(_version); Error() << "Context: unsupported OpenGL ES version" << Magnum::version(_version);
#endif #endif
std::exit(1); std::exit(66);
} }
/* Context flags are supported since GL 3.0 */ /* Context flags are supported since GL 3.0 */
@ -411,46 +413,15 @@ Context::Context() {
#endif #endif
} }
/* Check for presence of extensions in future versions */ /* Check for presence of future and vendor extensions */
#ifndef MAGNUM_TARGET_GLES2 const std::vector<std::string> extensions = extensionStrings();
GLint extensionCount = 0; for(const std::string& extension: extensions) {
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); const auto found = futureExtensions.find(extension);
#ifndef MAGNUM_TARGET_GLES3 if(found != futureExtensions.end()) {
if(extensionCount || isVersionSupported(Version::GL300)) _supportedExtensions.push_back(found->second);
#endif extensionStatus.set(found->second._index);
{
_supportedExtensions.reserve(extensionCount);
for(GLint i = 0; i != extensionCount; ++i) {
const std::string extension(reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)));
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<const char*>(glGetString(GL_EXTENSIONS));
if(e) {
std::vector<std::string> extensions = Utility::String::split(e, ' ');
for(auto it = extensions.begin(); it != extensions.end(); ++it) {
auto found = futureExtensions.find(*it);
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 */ /* Reset minimal required version to Version::None for whole array */
for(auto it = _extensionRequiredVersion.begin(); it != _extensionRequiredVersion.end(); ++it) for(auto it = _extensionRequiredVersion.begin(); it != _extensionRequiredVersion.end(); ++it)
@ -504,6 +475,38 @@ std::vector<std::string> Context::shadingLanguageVersionStrings() const {
#endif #endif
} }
std::vector<std::string> Context::extensionStrings() const {
std::vector<std::string> 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<const char*>(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<const char*>(glGetString(GL_EXTENSIONS));
if(e) extensions = Utility::String::splitWithoutEmptyParts(e, ' ');
}
#endif
return extensions;
}
Version Context::supportedVersion(std::initializer_list<Version> versions) const { Version Context::supportedVersion(std::initializer_list<Version> versions) const {
for(auto it = versions.begin(); it != versions.end(); ++it) for(auto it = versions.begin(); it != versions.end(); ++it)
if(isVersionSupported(*it)) return *it; if(isVersionSupported(*it)) return *it;
@ -515,4 +518,19 @@ Version Context::supportedVersion(std::initializer_list<Version> versions) const
#endif #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;
_c(Debug)
#ifndef MAGNUM_TARGET_GLES
_c(RobustAccess)
#endif
#undef _c
}
return debug << "Context::Flag::(invalid)";
}
#endif
} }

28
src/Magnum/Context.h

@ -107,7 +107,7 @@ class MAGNUM_EXPORT Context {
/** /**
* @brief Context flag * @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 { enum class Flag: GLint {
/** /**
@ -123,14 +123,22 @@ class MAGNUM_EXPORT Context {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* Context with robust buffer access * Context with robust access
* @requires_extension %Extension @extension{ARB,robustness} * @requires_extension %Extension @extension{ARB,robustness}
* @requires_es_extension %Extension @es_extension{EXT,robustness} * @requires_es_extension %Extension @es_extension{EXT,robustness}
* @todo In ES available under glGetIntegerv(CONTEXT_ROBUST_ACCESS_EXT), * @todo In ES available under glGetIntegerv(CONTEXT_ROBUST_ACCESS_EXT),
* how to make it compatible? * 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 Robustness = GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB
#endif #endif
#endif
}; };
/** /**
@ -237,6 +245,19 @@ class MAGNUM_EXPORT Context {
*/ */
std::vector<std::string> shadingLanguageVersionStrings() const; std::vector<std::string> 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<std::string> extensionStrings() const;
/** @brief Context flags */ /** @brief Context flags */
Flags flags() const { return _flags; } Flags flags() const { return _flags; }
@ -386,6 +407,9 @@ class MAGNUM_EXPORT Context {
Implementation::State* _state; Implementation::State* _state;
}; };
/** @debugoperator{Magnum::Context} */
MAGNUM_EXPORT Debug operator<<(Debug debug, Context::Flag value);
/** @hideinitializer /** @hideinitializer
@brief Assert that given OpenGL version is supported @brief Assert that given OpenGL version is supported
@param version Version @param version Version

30
src/Magnum/CubeMapTexture.h

@ -108,6 +108,20 @@ class CubeMapTexture: public AbstractTexture {
} }
#endif #endif
#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() */ /** @copydoc Texture::setMinificationFilter() */
CubeMapTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { CubeMapTexture& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) {
AbstractTexture::setMinificationFilter(filter, mipmap); AbstractTexture::setMinificationFilter(filter, mipmap);
@ -126,12 +140,26 @@ class CubeMapTexture: public AbstractTexture {
return *this; return *this;
} }
/** @copydoc Texture::setBorderColor() */ /** @copydoc Texture::setBorderColor(const Color4&) */
CubeMapTexture& setBorderColor(const Color4& color) { CubeMapTexture& setBorderColor(const Color4& color) {
AbstractTexture::setBorderColor(color); AbstractTexture::setBorderColor(color);
return *this; 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() */ /** @copydoc Texture::setMaxAnisotropy() */
CubeMapTexture& setMaxAnisotropy(Float anisotropy) { CubeMapTexture& setMaxAnisotropy(Float anisotropy) {
AbstractTexture::setMaxAnisotropy(anisotropy); AbstractTexture::setMaxAnisotropy(anisotropy);

28
src/Magnum/CubeMapTextureArray.h

@ -99,6 +99,18 @@ class CubeMapTextureArray: public AbstractTexture {
} }
#endif #endif
/** @copydoc Texture::setBaseLevel() */
CubeMapTextureArray& setBaseLevel(Int level) {
AbstractTexture::setBaseLevel(level);
return *this;
}
/** @copydoc Texture::setMaxLevel() */
CubeMapTextureArray& setMaxLevel(Int level) {
AbstractTexture::setMaxLevel(level);
return *this;
}
/** @copydoc Texture::setMinificationFilter() */ /** @copydoc Texture::setMinificationFilter() */
CubeMapTextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) { CubeMapTextureArray& setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap = Sampler::Mipmap::Base) {
AbstractTexture::setMinificationFilter(filter, mipmap); AbstractTexture::setMinificationFilter(filter, mipmap);
@ -123,6 +135,18 @@ class CubeMapTextureArray: public AbstractTexture {
return *this; return *this;
} }
/** @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;
}
/** @copydoc Texture::setMaxAnisotropy() */ /** @copydoc Texture::setMaxAnisotropy() */
CubeMapTextureArray& setMaxAnisotropy(Float anisotropy) { CubeMapTextureArray& setMaxAnisotropy(Float anisotropy) {
AbstractTexture::setMaxAnisotropy(anisotropy); AbstractTexture::setMaxAnisotropy(anisotropy);
@ -150,14 +174,12 @@ class CubeMapTextureArray: public AbstractTexture {
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief Read given mip level of texture to image * @brief Read given mip level of texture to image
* @param level Mip level * @param level Mip level
* @param image %Image where to put the data * @param image %Image where to put the data
* *
* See @ref Texture::image(Int, Image&) for more information. * 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) { void image(Int level, Image3D& image) {
AbstractTexture::image<3>(GL_TEXTURE_CUBE_MAP_ARRAY, level, image); AbstractTexture::image<3>(GL_TEXTURE_CUBE_MAP_ARRAY, level, image);
@ -171,12 +193,10 @@ class CubeMapTextureArray: public AbstractTexture {
* *
* See @ref Texture::image(Int, BufferImage&, BufferUsage) for more * See @ref Texture::image(Int, BufferImage&, BufferUsage) for more
* information. * information.
* @requires_gl %Texture image queries are not available in OpenGL ES.
*/ */
void image(Int level, BufferImage3D& image, BufferUsage usage) { void image(Int level, BufferImage3D& image, BufferUsage usage) {
AbstractTexture::image<3>(GL_TEXTURE_CUBE_MAP_ARRAY, level, image, usage); AbstractTexture::image<3>(GL_TEXTURE_CUBE_MAP_ARRAY, level, image, usage);
} }
#endif
/** /**
* @brief Set image data * @brief Set image data

1
src/Magnum/DebugTools/CMakeLists.txt

@ -51,6 +51,7 @@ set(MagnumDebugTools_HEADERS
visibility.h) visibility.h)
add_library(MagnumDebugTools ${SHARED_OR_STATIC} ${MagnumDebugTools_SRCS}) add_library(MagnumDebugTools ${SHARED_OR_STATIC} ${MagnumDebugTools_SRCS})
set_target_properties(MagnumDebugTools PROPERTIES DEBUG_POSTFIX "-d")
if(BUILD_STATIC_PIC) if(BUILD_STATIC_PIC)
# TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property
set_target_properties(MagnumDebugTools PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") set_target_properties(MagnumDebugTools PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}")

7
src/Magnum/Extensions.h

@ -182,6 +182,7 @@ namespace GL {
_extension(GL,EXT,transform_feedback, GL210, GL300) // #352 _extension(GL,EXT,transform_feedback, GL210, GL300) // #352
_extension(GL,EXT,direct_state_access, GL210, None) // #353 _extension(GL,EXT,direct_state_access, GL210, None) // #353
_extension(GL,EXT,texture_snorm, GL300, GL310) // #365 _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_label, GL210, None) // #439
_extension(GL,EXT,debug_marker, GL210, None) // #440 _extension(GL,EXT,debug_marker, GL210, None) // #440
} namespace GREMEDY { } namespace GREMEDY {
@ -211,6 +212,9 @@ namespace GL {
_extension(GL,APPLE,framebuffer_multisample, GLES200, GLES300) // #78 _extension(GL,APPLE,framebuffer_multisample, GLES200, GLES300) // #78
#endif #endif
_extension(GL,APPLE,texture_format_BGRA8888, GLES200, None) // #79 _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 { } namespace ARM {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(GL,ARM,rgba8, GLES200, GLES300) // #82 _extension(GL,ARM,rgba8, GLES200, GLES300) // #82
@ -245,6 +249,9 @@ namespace GL {
_extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121 _extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121
#endif #endif
_extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150 _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 { } namespace KHR {
_extension(GL,KHR,debug, GLES200, None) // #118 _extension(GL,KHR,debug, GLES200, None) // #118
} namespace NV { } namespace NV {

4
src/Magnum/Image.h

@ -138,8 +138,8 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
/** /**
* @brief Release data storage * @brief Release data storage
* *
* Returns the data pointer and resets internal state to default. * Releases the ownership of the data pointer and resets internal state
* Deleting the returned array is user responsibility. * to default. Deleting the returned array is then user responsibility.
* @see @ref setData() * @see @ref setData()
*/ */
unsigned char* release(); unsigned char* release();

59
src/Magnum/Implementation/TextureState.cpp

@ -36,20 +36,45 @@
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
TextureState::TextureState(Context& context, std::vector<std::string>& extensions): maxLayers(0), maxMaxAnisotropy(0.0f), currentLayer(0) TextureState::TextureState(Context& context, std::vector<std::string>& extensions): maxTextureUnits(0), maxMaxAnisotropy(0.0f), currentTextureUnit(0)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
, maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0)
#endif #endif
{ {
/* Bind implementation */
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::ARB::multi_bind>()) {
extensions.push_back(Extensions::GL::ARB::multi_bind::string());
unbindImplementation = &AbstractTexture::unbindImplementationMulti;
bindMultiImplementation = &AbstractTexture::bindImplementationMulti;
bindImplementation = &AbstractTexture::bindImplementationMulti;
} else if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
/* Extension name added below */
unbindImplementation = &AbstractTexture::unbindImplementationDSA;
bindMultiImplementation = &AbstractTexture::bindImplementationFallback;
bindImplementation = &AbstractTexture::bindImplementationDSA;
} else
#endif
{
unbindImplementation = &AbstractTexture::unbindImplementationDefault;
bindMultiImplementation = &AbstractTexture::bindImplementationFallback;
bindImplementation = &AbstractTexture::bindImplementationDefault;
}
/* DSA/non-DSA implementation */ /* DSA/non-DSA implementation */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) { if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
extensions.push_back(Extensions::GL::EXT::direct_state_access::string()); extensions.push_back(Extensions::GL::EXT::direct_state_access::string());
bindImplementation = &AbstractTexture::bindImplementationDSA;
parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameteriImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSA;
parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; parameterfvImplementation = &AbstractTexture::parameterImplementationDSA;
parameterIuivImplementation = &AbstractTexture::parameterImplementationDSA;
parameterIivImplementation = &AbstractTexture::parameterImplementationDSA;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA;
mipmapImplementation = &AbstractTexture::mipmapImplementationDSA; mipmapImplementation = &AbstractTexture::mipmapImplementationDSA;
getImageImplementation = &AbstractTexture::getImageImplementationDSA; getImageImplementation = &AbstractTexture::getImageImplementationDSA;
@ -65,11 +90,12 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
} else } else
#endif #endif
{ {
bindImplementation = &AbstractTexture::bindImplementationDefault;
parameteriImplementation = &AbstractTexture::parameterImplementationDefault; parameteriImplementation = &AbstractTexture::parameterImplementationDefault;
parameterfImplementation = &AbstractTexture::parameterImplementationDefault; parameterfImplementation = &AbstractTexture::parameterImplementationDefault;
parameterfvImplementation = &AbstractTexture::parameterImplementationDefault; parameterfvImplementation = &AbstractTexture::parameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
parameterIuivImplementation = &AbstractTexture::parameterImplementationDefault;
parameterIivImplementation = &AbstractTexture::parameterImplementationDefault;
getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault;
#endif #endif
mipmapImplementation = &AbstractTexture::mipmapImplementationDefault; mipmapImplementation = &AbstractTexture::mipmapImplementationDefault;
@ -153,6 +179,25 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
} }
#endif #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::GL::ARB::texture_storage_multisample>()) {
extensions.push_back(Extensions::GL::ARB::texture_storage_multisample::string());
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSA;
storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSA;
} else {
storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault;
storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault;
}
} else {
storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationFallback;
storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationFallback;
}
#endif
/* Anisotropic filter implementation */ /* Anisotropic filter implementation */
if(context.isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>()) { if(context.isExtensionSupported<Extensions::GL::EXT::texture_filter_anisotropic>()) {
extensions.push_back(Extensions::GL::EXT::texture_filter_anisotropic::string()); extensions.push_back(Extensions::GL::EXT::texture_filter_anisotropic::string());
@ -160,10 +205,10 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt; setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt;
} else setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationNoOp; } else setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationNoOp;
/* Resize bindings array to hold all possible layers */ /* Resize bindings array to hold all possible texture units */
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxLayers); glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
CORRADE_INTERNAL_ASSERT(maxLayers > 0); CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0);
bindings.resize(maxLayers); bindings.resize(maxTextureUnits);
} }
TextureState::~TextureState() = default; TextureState::~TextureState() = default;

12
src/Magnum/Implementation/TextureState.h

@ -55,10 +55,14 @@ struct TextureState {
explicit TextureState(Context& context, std::vector<std::string>& extensions); explicit TextureState(Context& context, std::vector<std::string>& extensions);
~TextureState(); ~TextureState();
void(*unbindImplementation)(GLint);
void(*bindMultiImplementation)(GLint, std::initializer_list<AbstractTexture*>);
void(AbstractTexture::*bindImplementation)(GLint); void(AbstractTexture::*bindImplementation)(GLint);
void(AbstractTexture::*parameteriImplementation)(GLenum, GLint); void(AbstractTexture::*parameteriImplementation)(GLenum, GLint);
void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat); void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat);
void(AbstractTexture::*parameterfvImplementation)(GLenum, const 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::*setMaxAnisotropyImplementation)(GLfloat);
void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*); void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*);
void(AbstractTexture::*mipmapImplementation)(); void(AbstractTexture::*mipmapImplementation)();
@ -68,6 +72,8 @@ struct TextureState {
void(AbstractTexture::*storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&); void(AbstractTexture::*storage2DImplementation)(GLenum, GLsizei, TextureFormat, const Vector2i&);
void(AbstractTexture::*storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&); void(AbstractTexture::*storage3DImplementation)(GLenum, GLsizei, TextureFormat, const Vector3i&);
#ifndef MAGNUM_TARGET_GLES #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::*getImageImplementation)(GLenum, GLint, ColorFormat, ColorType, std::size_t, GLvoid*);
void(AbstractTexture::*image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*); void(AbstractTexture::*image1DImplementation)(GLenum, GLint, TextureFormat, const Math::Vector<1, GLsizei>&, ColorFormat, ColorType, const GLvoid*);
#endif #endif
@ -86,9 +92,9 @@ struct TextureState {
void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr); void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr);
#endif #endif
GLint maxLayers; GLint maxTextureUnits;
GLfloat maxMaxAnisotropy; GLfloat maxMaxAnisotropy;
GLint currentLayer; GLint currentTextureUnit;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
GLint maxColorSamples, GLint maxColorSamples,
maxDepthSamples, maxDepthSamples,
@ -96,7 +102,7 @@ struct TextureState {
bufferOffsetAlignment; bufferOffsetAlignment;
#endif #endif
std::vector<GLuint> bindings; std::vector<std::pair<GLenum, GLuint>> bindings;
}; };
}} }}

5
src/Magnum/Implementation/setupDriverWorkarounds.cpp

@ -35,8 +35,8 @@ void Context::setupDriverWorkarounds() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/* This extension causes crash in GLSL compiler on AMD linux drivers 13.251 */ /* This extension causes crash in GLSL compiler on AMD linux drivers 13.251 */
const std::string renderer = rendererString(); const std::string vendor = vendorString();
if(renderer.find("Advanced Micro Devices") != std::string::npos) if(vendor.find("ATI Technologies Inc.") != std::string::npos)
_setRequiredVersion(GL::ARB::explicit_uniform_location, None); _setRequiredVersion(GL::ARB::explicit_uniform_location, None);
#endif #endif
@ -79,6 +79,7 @@ void Context::setupDriverWorkarounds() {
_setRequiredVersion(GL::NV::draw_buffers, None); _setRequiredVersion(GL::NV::draw_buffers, None);
_setRequiredVersion(GL::NV::fbo_color_attachments, None); // ?? _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ??
_setRequiredVersion(GL::NV::read_buffer, None); _setRequiredVersion(GL::NV::read_buffer, None);
_setRequiredVersion(GL::NV::framebuffer_blit, None);
_setRequiredVersion(GL::NV::framebuffer_multisample, None); _setRequiredVersion(GL::NV::framebuffer_multisample, None);
_setRequiredVersion(GL::OES::texture_3D, None); _setRequiredVersion(GL::OES::texture_3D, None);
_setRequiredVersion(GL::OES::vertex_array_object, None); _setRequiredVersion(GL::OES::vertex_array_object, None);

54
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 #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 Defined if the engine is built for OpenGL ES 2.0. Implies also
@ref MAGNUM_TARGET_GLES. @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 #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 Defined if the engine is built for OpenGL ES 3.0. Implies also
@ref MAGNUM_TARGET_GLES. @ref MAGNUM_TARGET_GLES.
@ -124,10 +124,24 @@ 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 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. 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 #define MAGNUM_TARGET_DESKTOP_GLES
#undef 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 #endif
/** @{ @name Basic type definitions /** @{ @name Basic type definitions
@ -153,11 +167,21 @@ typedef std::uint32_t UnsignedInt;
/** @brief Signed int (32bit) */ /** @brief Signed int (32bit) */
typedef std::int32_t Int; 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; 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; typedef std::int64_t Long;
#endif
/** @brief Float (32bit) */ /** @brief Float (32bit) */
typedef float Float; typedef float Float;
@ -210,14 +234,6 @@ typedef Math::Matrix2x2<Float> Matrix2x2;
typedef Math::Matrix<2, Float> Matrix2x2; typedef Math::Matrix<2, Float> Matrix2x2;
#endif #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 @brief 3x3 float matrix
@ -387,14 +403,6 @@ typedef Math::Matrix2x2<Double> Matrix2x2d;
typedef Math::Matrix<2, Double> Matrix2x2d; typedef Math::Matrix<2, Double> Matrix2x2d;
#endif #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 @brief 3x3 double matrix
@ -560,9 +568,6 @@ typedef BasicColor4<UnsignedByte> Color4ub;
#ifndef CORRADE_GCC45_COMPATIBILITY #ifndef CORRADE_GCC45_COMPATIBILITY
enum class ColorFormat: GLenum; enum class ColorFormat: GLenum;
enum class ColorType: GLenum; enum class ColorType: GLenum;
/** @todo Remove this when dropping backward compatibility */
typedef ColorFormat ImageFormat;
typedef ColorType ColorType;
#endif #endif
class Context; class Context;
@ -596,6 +601,7 @@ class Mesh;
class MeshView; class MeshView;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/* MultisampleTextureSampleLocations enum used only in the function */
template<UnsignedInt> class MultisampleTexture; template<UnsignedInt> class MultisampleTexture;
typedef MultisampleTexture<2> MultisampleTexture2D; typedef MultisampleTexture<2> MultisampleTexture2D;
typedef MultisampleTexture<3> MultisampleTexture2DArray; typedef MultisampleTexture<3> MultisampleTexture2DArray;

14
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 reduce unit-based errors. Consider following example with implicit conversions
allowed: allowed:
@code @code
Float std::sin(Float angle); namespace std { float sin(float angle); }
Float sine(Rad<Float> angle); Float sine(Rad<Float> angle);
Float a = 60.0f; // degrees 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: These silent errors are easily avoided by requiring explicit conversions:
@code @code
//sine(angleInDegrees); // compilation error //sine(a); // compilation error
sine(Deg<Float>(angleInDegrees)); // explicitly specifying unit sine(Deg<Float>{a}); // explicitly specifying unit
//std::sin(angleInDegrees); // compilation error //std::sin(b); // compilation error
std::sin(Float(Rad<Float>(angleInDegrees)); // required explicit conversion hints std::sin(Float(Rad<Float>(b)); // required explicit conversion hints to user
// to user that this case needs special // that this case needs special attention
// attention (i.e., conversion to radians) // (i.e., conversion to radians)
@endcode @endcode
@see Magnum::Deg, Magnum::Degd @see Magnum::Deg, Magnum::Degd

4
src/Magnum/Math/Complex.h

@ -343,8 +343,8 @@ template<class T> class Complex {
* @see isNormalized() * @see isNormalized()
*/ */
T length() const { T length() const {
/** @todo Remove when NaCl's newlib has this fixed */ /** @todo Remove when newlib has this fixed */
#ifndef CORRADE_TARGET_NACL_NEWLIB #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID)
return std::hypot(_real, _imaginary); return std::hypot(_real, _imaginary);
#else #else
return std::sqrt(dot()); return std::sqrt(dot());

9
src/Magnum/Math/Functions.h

@ -252,7 +252,8 @@ template<std::size_t size, class T> Vector<size, T> floor(const Vector<size, T>&
template<class T> inline T round(const T& a); template<class T> inline T round(const T& a);
#else #else
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type round(T a) { template<class T> inline typename std::enable_if<std::is_arithmetic<T>::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); return std::round(a);
#else #else
return (a > T(0)) ? std::floor(a + T(0.5)) : std::ceil(a - T(0.5)); return (a > T(0)) ? std::floor(a + T(0.5)) : std::ceil(a - T(0.5));
@ -261,7 +262,7 @@ template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T
template<std::size_t size, class T> Vector<size, T> round(const Vector<size, T>& a) { template<std::size_t size, class T> Vector<size, T> round(const Vector<size, T>& a) {
Vector<size, T> out; Vector<size, T> out;
for(std::size_t i = 0; i != size; ++i) { 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]); out[i] = std::round(a[i]);
#else #else
out[i] = round(a[i]); out[i] = round(a[i]);
@ -397,8 +398,8 @@ Computes and returns @f$ ab + c @f$.
template<class T> inline T fma(const T& a, const T& b, const T& c); template<class T> inline T fma(const T& a, const T& b, const T& c);
#else #else
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type fma(T a, T b, T c) { template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type fma(T a, T b, T c) {
/** @todo Remove when NaCl's newlib has this fixed */ /** @todo Remove when newlib has this fixed */
#ifndef CORRADE_TARGET_NACL_NEWLIB #if !defined(CORRADE_TARGET_NACL_NEWLIB) && !defined(CORRADE_TARGET_ANDROID)
return std::fma(a, b, c); return std::fma(a, b, c);
#else #else
return a*b + c; return a*b + c;

2
src/Magnum/Math/TypeTraits.h

@ -145,6 +145,7 @@ template<> struct TypeTraits<Int>: Implementation::TypeTraitsIntegral<Int> {
typedef Double FloatingPointType; typedef Double FloatingPointType;
#endif #endif
}; };
#ifndef MAGNUM_TARGET_WEBGL
template<> struct TypeTraits<UnsignedLong>: Implementation::TypeTraitsIntegral<UnsignedLong> { template<> struct TypeTraits<UnsignedLong>: Implementation::TypeTraitsIntegral<UnsignedLong> {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
typedef long double FloatingPointType; typedef long double FloatingPointType;
@ -155,6 +156,7 @@ template<> struct TypeTraits<Long>: Implementation::TypeTraitsIntegral<Long> {
typedef long double FloatingPointType; typedef long double FloatingPointType;
#endif #endif
}; };
#endif
/* Floating-point scalar types */ /* Floating-point scalar types */
namespace Implementation { namespace Implementation {

3
src/Magnum/Math/Vector.h

@ -408,7 +408,8 @@ template<std::size_t size, class T> class Vector {
* @brief Multiply vector component-wise * @brief Multiply vector component-wise
* *
* @see operator*(T) const, operator*=(const Vector<size, T>&), * @see operator*(T) const, operator*=(const Vector<size, T>&),
* operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&) * operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&),
* @ref product()
*/ */
Vector<size, T> operator*(const Vector<size, T>& other) const { Vector<size, T> operator*(const Vector<size, T>& other) const {
return Vector<size, T>(*this) *= other; return Vector<size, T>(*this) *= other;

6
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) { 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, CORRADE_ASSERT(buffer.targetHint() == Buffer::Target::ElementArray,
"Mesh::setIndexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::ElementArray << "but got" << buffer.targetHint(), *this); "Mesh::setIndexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::ElementArray << "but got" << buffer.targetHint(), *this);
#endif #endif
@ -270,7 +270,7 @@ void Mesh::destroyImplementationVAO() {
} }
void Mesh::attributePointerImplementationDefault(const Attribute& attribute) { 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, 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(), ); "Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::Array << "but got" << attribute.buffer->targetHint(), );
#endif #endif
@ -279,7 +279,7 @@ void Mesh::attributePointerImplementationDefault(const Attribute& attribute) {
} }
void Mesh::attributePointerImplementationVAO(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, 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(), ); "Mesh::addVertexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::Array << "but got" << attribute.buffer->targetHint(), );
#endif #endif

32
src/Magnum/Mesh.h

@ -291,6 +291,11 @@ respective shader, bind required textures (see
@ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation"
for more infromation) and call @ref Mesh::draw(). 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 @section Mesh-performance-optimization Performance optimizations
If @extension{APPLE,vertex_array_object} (part of OpenGL 3.0), OpenGL ES 3.0 or 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, you must ensure it will exist for whole lifetime of the
* mesh and delete it afterwards. * 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(), * @see @ref maxVertexAttributes(), @ref setPrimitive(),
* @ref setVertexCount(), @fn_gl{BindVertexArray}, * @ref setVertexCount(), @fn_gl{BindVertexArray},
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
@ -635,7 +646,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @copybrief draw(AbstractShaderProgram&) * @copybrief draw(AbstractShaderProgram&)
* @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) instead. * @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) "draw(AbstractShaderProgram&)"
* instead.
*/ */
void draw() { void draw() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -682,28 +694,28 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif #endif
/* Computing stride of interleaved vertex attributes */ /* Computing stride of interleaved vertex attributes */
template<UnsignedInt location, class T, class ...U> inline static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) { template<UnsignedInt location, class T, class ...U> static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) {
return attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount + strideOfInterleaved(attributes...); return attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount + strideOfInterleaved(attributes...);
} }
template<class ...T> inline static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) { template<class ...T> static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) {
return gap + strideOfInterleaved(attributes...); return gap + strideOfInterleaved(attributes...);
} }
inline static GLsizei strideOfInterleaved() { return 0; } static GLsizei strideOfInterleaved() { return 0; }
/* Adding interleaved vertex attributes */ /* Adding interleaved vertex attributes */
template<UnsignedInt location, class T, class ...U> inline void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) { template<UnsignedInt location, class T, class ...U> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) {
addVertexAttribute(buffer, attribute, offset, stride); addVertexAttribute(buffer, attribute, offset, stride);
/* Add size of this attribute to offset for next attribute */ /* Add size of this attribute to offset for next attribute */
addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount, stride, attributes...); addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount, stride, attributes...);
} }
template<class ...T> inline void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) { template<class ...T> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) {
/* Add the gap to offset for next attribute */ /* Add the gap to offset for next attribute */
addVertexBufferInternal(buffer, offset+gap, stride, attributes...); addVertexBufferInternal(buffer, offset+gap, stride, attributes...);
} }
inline void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {} void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {}
template<UnsignedInt location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::Type, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i) for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i)
attributePointerInternal(Attribute{ attributePointerInternal(Attribute{
&buffer, &buffer,
@ -717,7 +729,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::Type>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
attributePointerInternal(IntegerAttribute{ attributePointerInternal(IntegerAttribute{
&buffer, &buffer,
location, location,
@ -729,7 +741,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
template<UnsignedInt location, class T> inline void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::Type, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) { template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i) for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i)
attributePointerInternal(LongAttribute{ attributePointerInternal(LongAttribute{
&buffer, &buffer,

7
src/Magnum/MeshTools/CMakeLists.txt

@ -25,6 +25,7 @@
# Files shared between main library and unit test library # Files shared between main library and unit test library
set(MagnumMeshTools_SRCS set(MagnumMeshTools_SRCS
Compile.cpp
CompressIndices.cpp CompressIndices.cpp
FullScreenTriangle.cpp FullScreenTriangle.cpp
Tipsify.cpp) Tipsify.cpp)
@ -37,6 +38,7 @@ set(MagnumMeshTools_GracefulAssert_SRCS
set(MagnumMeshTools_HEADERS set(MagnumMeshTools_HEADERS
CombineIndexedArrays.h CombineIndexedArrays.h
Compile.h
CompressIndices.h CompressIndices.h
Duplicate.h Duplicate.h
FlipNormals.h FlipNormals.h
@ -64,6 +66,7 @@ endif()
add_library(MagnumMeshTools ${SHARED_OR_STATIC} add_library(MagnumMeshTools ${SHARED_OR_STATIC}
$<TARGET_OBJECTS:MagnumMeshToolsObjects> $<TARGET_OBJECTS:MagnumMeshToolsObjects>
${MagnumMeshTools_GracefulAssert_SRCS}) ${MagnumMeshTools_GracefulAssert_SRCS})
set_target_properties(MagnumMeshTools PROPERTIES DEBUG_POSTFIX "-d")
if(BUILD_STATIC_PIC) if(BUILD_STATIC_PIC)
# TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property
set_target_properties(MagnumMeshTools PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") set_target_properties(MagnumMeshTools PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}")
@ -81,7 +84,9 @@ if(BUILD_TESTS)
add_library(MagnumMeshToolsTestLib ${SHARED_OR_STATIC} add_library(MagnumMeshToolsTestLib ${SHARED_OR_STATIC}
$<TARGET_OBJECTS:MagnumMeshToolsObjects> $<TARGET_OBJECTS:MagnumMeshToolsObjects>
${MagnumMeshTools_GracefulAssert_SRCS}) ${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) target_link_libraries(MagnumMeshToolsTestLib Magnum)
# On Windows we need to install first and then run the tests to avoid "DLL # On Windows we need to install first and then run the tests to avoid "DLL

17
src/Magnum/MeshTools/CombineIndexedArrays.cpp

@ -56,26 +56,24 @@ std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> interleaveAndCombi
/* Combine them */ /* Combine them */
std::vector<UnsignedInt> combinedIndices; std::vector<UnsignedInt> combinedIndices;
std::tie(combinedIndices, interleavedArrays) = combineIndexArrays(interleavedArrays, stride); std::tie(combinedIndices, interleavedArrays) = MeshTools::combineIndexArrays(interleavedArrays, stride);
return {combinedIndices, interleavedArrays}; return {combinedIndices, interleavedArrays};
} }
} std::vector<UnsignedInt> combineIndexArrays(const std::reference_wrapper<std::vector<UnsignedInt>>* const begin, const std::reference_wrapper<std::vector<UnsignedInt>>* const end) {
std::vector<UnsignedInt> combineIndexArrays(const std::initializer_list<std::reference_wrapper<std::vector<UnsignedInt>>> arrays) {
/* Interleave and combine the arrays */ /* Interleave and combine the arrays */
std::vector<UnsignedInt> combinedIndices; std::vector<UnsignedInt> combinedIndices;
std::vector<UnsignedInt> interleavedCombinedArrays; std::vector<UnsignedInt> interleavedCombinedArrays;
std::tie(combinedIndices, interleavedCombinedArrays) = Implementation::interleaveAndCombineIndexArrays( std::tie(combinedIndices, interleavedCombinedArrays) = Implementation::interleaveAndCombineIndexArrays(
/* This will bite me hard once. */ /* This will bite me hard once. */
reinterpret_cast<const std::reference_wrapper<const std::vector<UnsignedInt>>*>(arrays.begin()), reinterpret_cast<const std::reference_wrapper<const std::vector<UnsignedInt>>*>(begin),
reinterpret_cast<const std::reference_wrapper<const std::vector<UnsignedInt>>*>(arrays.end())); reinterpret_cast<const std::reference_wrapper<const std::vector<UnsignedInt>>*>(end));
/* Update the original indices */ /* Update the original indices */
const UnsignedInt stride = arrays.size(); const UnsignedInt stride = end - begin;
const UnsignedInt outputSize = interleavedCombinedArrays.size()/stride; const UnsignedInt outputSize = interleavedCombinedArrays.size()/stride;
for(UnsignedInt offset = 0; offset != stride; ++offset) { for(UnsignedInt offset = 0; offset != stride; ++offset) {
auto& array = (arrays.begin()+offset)->get(); auto& array = (begin+offset)->get();
CORRADE_INTERNAL_ASSERT(array.size() >= outputSize); CORRADE_INTERNAL_ASSERT(array.size() >= outputSize);
array.resize(outputSize); array.resize(outputSize);
for(UnsignedInt i = 0; i != outputSize; ++i) for(UnsignedInt i = 0; i != outputSize; ++i)
@ -85,6 +83,8 @@ std::vector<UnsignedInt> combineIndexArrays(const std::initializer_list<std::ref
return combinedIndices; return combinedIndices;
} }
}
namespace { namespace {
class IndexHash { class IndexHash {
@ -116,6 +116,7 @@ class IndexEqual {
} }
std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> combineIndexArrays(const std::vector<UnsignedInt>& interleavedArrays, const UnsignedInt stride) { std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> combineIndexArrays(const std::vector<UnsignedInt>& 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", {}); CORRADE_ASSERT(interleavedArrays.size() % stride == 0, "MeshTools::combineIndexArrays(): array size is not divisible by stride", {});
/* Hash map with index combinations, containing just indices into /* Hash map with index combinations, containing just indices into

22
src/Magnum/MeshTools/CombineIndexedArrays.h

@ -32,6 +32,7 @@
#include <functional> #include <functional>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#include <Corrade/Utility/Assert.h>
#include "Magnum/Types.h" #include "Magnum/Types.h"
#include "Magnum/MeshTools/visibility.h" #include "Magnum/MeshTools/visibility.h"
@ -42,6 +43,10 @@
namespace Magnum { namespace MeshTools { namespace Magnum { namespace MeshTools {
namespace Implementation {
MAGNUM_MESHTOOLS_EXPORT std::vector<UnsignedInt> combineIndexArrays(const std::reference_wrapper<std::vector<UnsignedInt>>* begin, const std::reference_wrapper<std::vector<UnsignedInt>>* end);
}
/** /**
@brief Combine index arrays @brief Combine index arrays
@ -81,7 +86,14 @@ This function calls @ref combineIndexArrays(const std::vector<UnsignedInt>&, Uns
internally. See also @ref combineIndexedArrays() which does the vertex data internally. See also @ref combineIndexedArrays() which does the vertex data
reordering automatically. reordering automatically.
*/ */
MAGNUM_MESHTOOLS_EXPORT std::vector<UnsignedInt> combineIndexArrays(std::initializer_list<std::reference_wrapper<std::vector<UnsignedInt>>> arrays); inline std::vector<UnsignedInt> combineIndexArrays(const std::vector<std::reference_wrapper<std::vector<UnsignedInt>>>& arrays) {
return Implementation::combineIndexArrays(&arrays[0], &arrays[0] + arrays.size());
}
/** @overload */
inline std::vector<UnsignedInt> combineIndexArrays(std::initializer_list<std::reference_wrapper<std::vector<UnsignedInt>>> arrays) {
return Implementation::combineIndexArrays(arrays.begin(), arrays.end());
}
/** /**
@brief Combine index arrays @brief Combine index arrays
@ -111,10 +123,14 @@ namespace Implementation {
MAGNUM_MESHTOOLS_EXPORT std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> interleaveAndCombineIndexArrays(const std::reference_wrapper<const std::vector<UnsignedInt>>* begin, const std::reference_wrapper<const std::vector<UnsignedInt>>* end); MAGNUM_MESHTOOLS_EXPORT std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> interleaveAndCombineIndexArrays(const std::reference_wrapper<const std::vector<UnsignedInt>>* begin, const std::reference_wrapper<const std::vector<UnsignedInt>>* end);
template<class T> void writeCombinedArray(const UnsignedInt stride, const UnsignedInt offset, const std::vector<UnsignedInt>& interleavedCombinedIndexArrays, std::vector<T>& array) { template<class T> void writeCombinedArray(const UnsignedInt stride, const UnsignedInt offset, const std::vector<UnsignedInt>& interleavedCombinedIndexArrays, std::vector<T>& array) {
/* Can't use duplicate() here because we aren't accessing the index data sequentially */
std::vector<T> output; std::vector<T> output;
output.reserve(interleavedCombinedIndexArrays.size()/stride); output.reserve(interleavedCombinedIndexArrays.size()/stride);
for(std::size_t i = 0, max = interleavedCombinedIndexArrays.size()/stride; i != max; ++i) for(std::size_t i = 0, max = interleavedCombinedIndexArrays.size()/stride; i != max; ++i) {
output.push_back(array[interleavedCombinedIndexArrays[offset + i*stride]]); 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); std::swap(output, array);
} }

157
src/Magnum/MeshTools/Compile.cpp

@ -0,0 +1,157 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
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<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> 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<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}};
/* Interleave positions */
std::size_t vertexCount;
Containers::Array<char> 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<Buffer> 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<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> 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<Buffer> vertexBuffer{new Buffer{Buffer::Target::Array}};
/* Interleave positions */
std::size_t vertexCount;
Containers::Array<char> 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));
/* 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<Buffer> 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));
}
}}

81
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š <mosra@centrum.cz>
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 <tuple>
#include <memory>
#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<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> 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<Mesh, std::unique_ptr<Buffer>, std::unique_ptr<Buffer>> compile(const Trade::MeshData3D& meshData, BufferUsage usage);
}}
#endif

2
src/Magnum/MeshTools/CompressIndices.h

@ -73,7 +73,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 and @ref Mesh::setIndexBuffer(), thus you don't need to do anything else for
mesh index configuration. 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<UnsignedInt>& indices); void MAGNUM_MESHTOOLS_EXPORT compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector<UnsignedInt>& indices);

5
src/Magnum/MeshTools/Duplicate.h

@ -30,6 +30,7 @@
*/ */
#include <vector> #include <vector>
#include <Corrade/Utility/Assert.h>
#include "Magnum/Types.h" #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<class T> std::vector<T> duplicate(const std::vector<UnsignedInt>& indices, const std::vector<T>& data) { template<class T> std::vector<T> duplicate(const std::vector<UnsignedInt>& indices, const std::vector<T>& data) {
std::vector<T> out; std::vector<T> out;
out.reserve(indices.size()); out.reserve(indices.size());
for(auto it = indices.begin(); it != indices.end(); ++it) for(auto it = indices.begin(); it != indices.end(); ++it) {
CORRADE_ASSERT(*it < data.size(), "MeshTools::duplicate(): index out of range", out);
out.push_back(data[*it]); out.push_back(data[*it]);
}
return out; return out;
} }

206
src/Magnum/MeshTools/Interleave.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function @ref Magnum::MeshTools::interleave() * @brief Function @ref Magnum::MeshTools::interleave(), @ref Magnum::MeshTools::interleaveInto()
*/ */
#include <cstring> #include <cstring>
@ -41,93 +41,52 @@ namespace Magnum { namespace MeshTools {
namespace Implementation { namespace Implementation {
class Interleave { /* Attribute count, skipping gaps. If the attributes are just gaps, returns
public: ~std::size_t{0}. It must be in the structure to have proper overload
Interleave(): _attributeCount(0), _stride(0) {} resolution (the functions would otherwise need to be de-inlined to break
cyclic dependencies) */
template<class ...T> std::tuple<std::size_t, std::size_t, Containers::Array<char>> operator()(const T&... attributes) { struct AttributeCount {
/* Compute buffer size and stride */ template<class T, class ...U> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, std::size_t>::type operator()(const T& first, const U&... next) const {
_attributeCount = attributeCount(attributes...); 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);
Containers::Array<char> data;
if(_attributeCount && _attributeCount != ~std::size_t(0)) { return first.size();
_stride = stride(attributes...); }
template<class T, class... U> std::size_t operator()(std::size_t, const T& first, const U&... next) const {
/* Create output buffer */ return AttributeCount{}(first, next...);
data = Containers::Array<char>(_attributeCount*_stride); }
constexpr std::size_t operator()(std::size_t) const { return ~std::size_t(0); }
/* Save the data */ constexpr std::size_t operator()() const { return 0; }
write(data.begin(), attributes...); };
}
return std::make_tuple(_attributeCount, _stride, std::move(data));
}
template<class ...T> void operator()(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) {
Containers::Array<char> data;
std::tie(std::ignore, std::ignore, data) = operator()(attributes...);
mesh.setVertexCount(_attributeCount);
buffer.setData(data, usage);
}
/* Specialization for only one attribute array */
template<class T> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, void>::type operator()(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) {
mesh.setVertexCount(attribute.size());
buffer.setData(attribute, usage);
}
template<class T, class ...U> static typename std::enable_if<!std::is_convertible<T, std::size_t>::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<class... T> static std::size_t attributeCount(std::size_t, const T&... next) {
return attributeCount(next...);
}
template<class ...T> static std::size_t attributeCount(std::size_t) {
return ~std::size_t(0);
}
template<class T, class ...U> static typename std::enable_if<!std::is_convertible<T, std::size_t>::value, std::size_t>::type stride(const T&, const U&... next) {
return sizeof(typename T::value_type) + stride(next...);
}
template<class... T> static std::size_t stride(std::size_t gap, const T&... next) {
return gap + stride(next...);
}
private:
template<class T, class ...U> void write(char* startingOffset, const T& first, const U&... next) {
write(startingOffset+writeOne(startingOffset, first), next...);
}
/* Copy data to the buffer */
template<class T> typename std::enable_if<!std::is_convertible<T, std::size_t>::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<const char*>(&*it), sizeof(typename T::value_type));
return sizeof(typename T::value_type); /* Stride, taking gaps into account. It must be in the structure, same reason
} as above */
struct Stride {
template<class T, class ...U> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, std::size_t>::type operator()(const T&, const U&... next) const {
return sizeof(typename T::value_type) + Stride{}(next...);
}
template<class... T> std::size_t operator()(std::size_t gap, const T&... next) const {
return gap + Stride{}(next...);
}
constexpr std::size_t operator()() const { return 0; }
};
/* Fill gap with zeros */ /* Copy data to the buffer */
std::size_t writeOne(char* startingOffset, std::size_t gap) { template<class T> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, std::size_t>::type writeOneInterleaved(std::size_t stride, char* startingOffset, const T& attributeList) {
for(std::size_t i = 0; i != _attributeCount; ++i) auto it = attributeList.begin();
std::memset(startingOffset+i*_stride, 0, gap); for(std::size_t i = 0; i != attributeList.size(); ++i, ++it)
std::memcpy(startingOffset + i*stride, reinterpret_cast<const char*>(&*it), sizeof(typename T::value_type));
return gap; return sizeof(typename T::value_type);
} }
/* Terminator functions for recursive calls */ /* Skip gap */
static std::size_t attributeCount() { return 0; } inline constexpr std::size_t writeOneInterleaved(std::size_t, char*, std::size_t gap) { return gap; }
static std::size_t stride() { return 0; }
void write(char*) {}
std::size_t _attributeCount; /* Write interleaved data */
std::size_t _stride; inline void writeInterleaved(std::size_t, char*) {}
}; template<class T, class ...U> void writeInterleaved(std::size_t stride, char* startingOffset, const T& first, const U&... next) {
writeInterleaved(stride, startingOffset + writeOneInterleaved(stride, startingOffset, first), next...);
}
} }
@ -155,15 +114,15 @@ It's often desirable to align data for one vertex on 32bit boundaries. To
achieve that, you can specify gaps between the attributes: achieve that, you can specify gaps between the attributes:
@code @code
std::vector<Vector4> positions; std::vector<Vector4> positions;
std::vector<GLushort> weights; std::vector<UnsignedShort> weights;
std::vector<BasicColor3<GLubyte>> vertexColors; std::vector<Color3ub> vertexColors;
std::size_t attributeCount; std::size_t attributeCount;
std::size_t stride; std::size_t stride;
Containers::Array<char> data; Containers::Array<char> data;
std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1); std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1);
@endcode @endcode
This way vertex stride is 24 bytes, without gaps it would be 21 bytes, causing All gap bytes are set zero. This way vertex stride is 24 bytes, without gaps it
possible performance loss. would be 21 bytes, causing possible performance loss.
@attention The function expects that all arrays have the same size. @attention The function expects that all arrays have the same size.
@ -173,15 +132,53 @@ possible performance loss.
will be `std::vector` or `std::array`. will be `std::vector` or `std::array`.
See also @ref interleave(Mesh&, Buffer&, BufferUsage, const T&...), 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 */ /* enable_if to avoid clash with overloaded function below */
template<class T, class ...U> inline typename std::enable_if<!std::is_same<T, Mesh>::value, std::tuple<std::size_t, std::size_t, Containers::Array<char>>>::type interleave(const T& first, const U&... next) { template<class T, class ...U> typename std::enable_if<!std::is_same<T, Mesh>::value, std::tuple<std::size_t, std::size_t, Containers::Array<char>>>::type interleave(const T& first, const U&... next) {
return Implementation::Interleave()(first, next...); /* Compute buffer size and stride */
const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...);
const std::size_t stride = Implementation::Stride{}(first, next...);
/* Create output buffer only if we have some attributes */
if(attributeCount && attributeCount != ~std::size_t(0)) {
Containers::Array<char> data = Containers::Array<char>::zeroInitialized(attributeCount*stride);
Implementation::writeInterleaved(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);
}
/**
@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<class T, class ...U> std::tuple<std::size_t, std::size_t> interleaveInto(Containers::ArrayReference<char> 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 and write them to array buffer @brief %Interleave vertex attributes, write them to array buffer and configure the mesh
@param mesh Output mesh @param mesh Output mesh
@param buffer Output vertex buffer @param buffer Output vertex buffer
@param usage Vertex buffer usage @param usage Vertex buffer usage
@ -194,18 +191,31 @@ so you don't have to call @ref Mesh::setVertexCount() on your own.
@attention You still must call @ref Mesh::setPrimitive() and @attention You still must call @ref Mesh::setPrimitive() and
@ref Mesh::addVertexBuffer() on the mesh afterwards. @ref Mesh::addVertexBuffer() on the mesh afterwards.
For only one attribute array this function is convenient equivalent to the @see @ref compressIndices(), @ref compile()
following, without any performance loss: @todo rework so Mesh & Buffer doesn't need to be included in header
*/
template<class ...T> void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) {
Containers::Array<char> 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 @code
buffer.setData(attribute, usage); buffer.setData(attribute, usage);
mesh.setVertexCount(attribute.size()); mesh.setVertexCount(attribute.size());
@endcode @endcode
@see @ref MeshTools::compressIndices()
@todo rework so Mesh & Buffer doesn't need to be included in header
*/ */
template<class ...T> inline void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) { template<class T> typename std::enable_if<!std::is_convertible<T, std::size_t>::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) {
return Implementation::Interleave()(mesh, buffer, usage, attributes...); mesh.setVertexCount(attribute.size());
buffer.setData(attribute, usage);
} }
}} }}

57
src/Magnum/MeshTools/Test/InterleaveTest.cpp

@ -42,6 +42,8 @@ class InterleaveTest: public Corrade::TestSuite::Tester {
void strideGaps(); void strideGaps();
void write(); void write();
void writeGaps(); void writeGaps();
void interleaveInto();
}; };
InterleaveTest::InterleaveTest() { InterleaveTest::InterleaveTest() {
@ -50,36 +52,38 @@ InterleaveTest::InterleaveTest() {
&InterleaveTest::stride, &InterleaveTest::stride,
&InterleaveTest::strideGaps, &InterleaveTest::strideGaps,
&InterleaveTest::write, &InterleaveTest::write,
&InterleaveTest::writeGaps}); &InterleaveTest::writeGaps,
&InterleaveTest::interleaveInto});
} }
void InterleaveTest::attributeCount() { void InterleaveTest::attributeCount() {
std::stringstream ss; std::stringstream ss;
Error::setOutput(&ss); Error::setOutput(&ss);
CORRADE_COMPARE((Implementation::Interleave::attributeCount(std::vector<Byte>{0, 1, 2}, CORRADE_COMPARE((Implementation::AttributeCount{}(std::vector<Byte>{0, 1, 2},
std::vector<Byte>{0, 1, 2, 3, 4, 5})), std::size_t(0)); std::vector<Byte>{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(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<Byte>{0, 1, 2}, CORRADE_COMPARE((Implementation::AttributeCount{}(std::vector<Byte>{0, 1, 2},
std::vector<Byte>{3, 4, 5})), std::size_t(3)); std::vector<Byte>{3, 4, 5})), std::size_t(3));
} }
void InterleaveTest::attributeCountGaps() { void InterleaveTest::attributeCountGaps() {
CORRADE_COMPARE((Implementation::Interleave::attributeCount(std::vector<Byte>{0, 1, 2}, 3, CORRADE_COMPARE((Implementation::AttributeCount{}(std::vector<Byte>{0, 1, 2}, 3,
std::vector<Byte>{3, 4, 5}, 5)), std::size_t(3)); std::vector<Byte>{3, 4, 5}, 5)), std::size_t(3));
/* No arrays from which to get size */ /* 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() { void InterleaveTest::stride() {
CORRADE_COMPARE(Implementation::Interleave::stride(std::vector<Byte>()), std::size_t(1)); CORRADE_COMPARE(Implementation::Stride{}(std::vector<Byte>()), std::size_t(1));
CORRADE_COMPARE(Implementation::Interleave::stride(std::vector<Int>()), std::size_t(4)); CORRADE_COMPARE(Implementation::Stride{}(std::vector<Int>()), std::size_t(4));
CORRADE_COMPARE((Implementation::Interleave::stride(std::vector<Byte>(), std::vector<Int>())), std::size_t(5)); CORRADE_COMPARE((Implementation::Stride{}(std::vector<Byte>(), std::vector<Int>())), std::size_t(5));
} }
void InterleaveTest::strideGaps() { void InterleaveTest::strideGaps() {
CORRADE_COMPARE((Implementation::Interleave::stride(2, std::vector<Byte>(), 1, std::vector<Int>(), 12)), std::size_t(20)); CORRADE_COMPARE((Implementation::Stride{}(2, std::vector<Byte>(), 1, std::vector<Int>(), 12)), std::size_t(20));
} }
void InterleaveTest::write() { void InterleaveTest::write() {
@ -137,6 +141,41 @@ void InterleaveTest::writeGaps() {
} }
} }
void InterleaveTest::interleaveInto() {
std::size_t attributeCount;
std::size_t stride;
auto data = Containers::Array<char>::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<Int>{4, 5, 6, 7}, 1, std::vector<Short>{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<char>(data.begin(), data.end()), (std::vector<char>{
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<char>(data.begin(), data.end()), (std::vector<char>{
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) CORRADE_TEST_MAIN(Magnum::MeshTools::Test::InterleaveTest)

3
src/Magnum/MeshView.h

@ -126,7 +126,8 @@ class MAGNUM_EXPORT MeshView {
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @copybrief draw(AbstractShaderProgram&) * @copybrief draw(AbstractShaderProgram&)
* @deprecated Use * @deprecated Use @ref Magnum::MeshView::draw(AbstractShaderProgram&) "draw(AbstractShaderProgram&)"
* instead.
*/ */
CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw(); CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw();
#endif #endif

78
src/Magnum/MultisampleTexture.h

@ -44,6 +44,16 @@ namespace Implementation {
template<> inline constexpr GLenum multisampleTextureTarget<3>() { return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; } 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 @brief Mulitsample texture
@ -77,19 +87,67 @@ template<UnsignedInt dimensions> class MultisampleTexture: public AbstractTextur
*/ */
explicit MultisampleTexture(): AbstractTexture(Implementation::multisampleTextureTarget<dimensions>()) {} explicit MultisampleTexture(): AbstractTexture(Implementation::multisampleTextureTarget<dimensions>()) {}
#ifndef MAGNUM_TARGET_GLES /**
/** @copydoc Texture::imageSize() */ * @brief %Image size
typename DimensionTraits<dimensions, Int>::VectorType imageSize(Int level) { *
return DataHelper<dimensions>::imageSize(*this, _target, level); * 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<dimensions, Int>::VectorType imageSize() {
return DataHelper<dimensions>::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<dimensions>& setStorage(Int samples, TextureFormat internalFormat, const typename DimensionTraits<dimensions, Int>::VectorType& size, MultisampleTextureSampleLocations sampleLocations =
#ifndef DOXYGEN_GENERATING_OUTPUT
MultisampleTextureSampleLocations::NotFixed
#else
NotFixed
#endif
) {
DataHelper<dimensions>::setStorageMultisample(*this, _target, samples, internalFormat, size, GLboolean(sampleLocations));
return *this;
} }
#endif
/** @copydoc Texture::invalidateImage() */ /** @copydoc RectangleTexture::invalidateImage() */
void invalidateImage(Int level) { AbstractTexture::invalidateImage(level); } void invalidateImage() { AbstractTexture::invalidateImage(0); }
/** @copydoc Texture::invalidateSubImage() */ /** @copydoc RectangleTexture::invalidateSubImage() */
void invalidateSubImage(Int level, const typename DimensionTraits<dimensions, Int>::VectorType& offset, const typename DimensionTraits<dimensions, Int>::VectorType& size) { void invalidateSubImage(const typename DimensionTraits<dimensions, Int>::VectorType& offset, const typename DimensionTraits<dimensions, Int>::VectorType& size) {
DataHelper<dimensions>::invalidateSubImage(*this, level, offset, size); DataHelper<dimensions>::invalidateSubImage(*this, 0, offset, size);
} }
/* Overloads to remove WTF-factor from method chaining order */ /* Overloads to remove WTF-factor from method chaining order */

32
src/Magnum/Platform/AbstractXApplication.h

@ -92,7 +92,10 @@ class AbstractXApplication {
/** /**
* @brief Execute main loop * @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(); int exec();
@ -268,33 +271,6 @@ class AbstractXApplication::InputEvent {
Ctrl = ControlMask, /**< Ctrl */ Ctrl = ControlMask, /**< Ctrl */
Alt = Mod1Mask, /**< Alt */ Alt = Mod1Mask, /**< Alt */
AltGr = Mod5Mask, /**< AltGr */ 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 */ CapsLock = LockMask, /**< Caps lock */
NumLock = Mod2Mask /**< Num lock */ NumLock = Mod2Mask /**< Num lock */
}; };

266
src/Magnum/Platform/AndroidApplication.cpp

@ -0,0 +1,266 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
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 <Corrade/Utility/AndroidStreamBuffer.h>
#include <Corrade/Utility/Debug.h>
#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&) {}
void AndroidApplication::mousePressEvent(MouseEvent&) {}
void AndroidApplication::mouseReleaseEvent(MouseEvent&) {}
void AndroidApplication::mouseMoveEvent(MouseMoveEvent&) {}
namespace {
struct Data {
Data(std::unique_ptr<AndroidApplication>(*instancer)(const AndroidApplication::Arguments&)): instancer(instancer) {}
std::unique_ptr<AndroidApplication>(*instancer)(const AndroidApplication::Arguments&);
std::unique_ptr<AndroidApplication> instance;
};
}
void AndroidApplication::commandEvent(android_app* state, int32_t cmd) {
Data& data = *static_cast<Data*>(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* state, AInputEvent* event) {
CORRADE_INTERNAL_ASSERT(static_cast<Data*>(state->userData)->instance);
AndroidApplication& app = *static_cast<Data*>(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;
}
void AndroidApplication::exec(android_app* state, std::unique_ptr<AndroidApplication>(*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<void**>(&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;
}
}}

594
src/Magnum/Platform/AndroidApplication.h

@ -0,0 +1,594 @@
#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š <mosra@centrum.cz>
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 <memory>
#include <EGL/egl.h>
#include <android_native_app_glue.h>
#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
/* Undef Xlib nonsense which might get pulled in by EGL */
#undef None
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:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cz.mosra.magnum.application" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="9" />
<uses-feature android:glEsVersion="0x00020000" />
<application android:label="Magnum Android Application" android:hasCode="false">
<activity android:name="android.app.NativeActivity" android:label="Magnum Android Application">
<meta-data android:name="android.app.lib_name" android:value="{{application}}" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
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 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
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;
class InputEvent;
class MouseEvent;
class MouseMoveEvent;
/**
* @brief Execute the application
*
* See @ref MAGNUM_ANDROIDAPPLICATION_MAIN() for usage information.
*/
static void exec(android_app* state, std::unique_ptr<AndroidApplication>(*instancer)(const Arguments&));
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class T> static std::unique_ptr<AndroidApplication> instancer(const Arguments& arguments) {
return std::unique_ptr<AndroidApplication>{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;
/*@}*/
/** @{ @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;
enum class Flag: UnsignedByte {
Redraw = 1 << 0
};
typedef Containers::EnumSet<Flag, UnsignedByte> Flags;
static void commandEvent(android_app* state, std::int32_t cmd);
static std::int32_t inputEvent(android_app* state, AInputEvent* event);
void initialize();
android_app* const _state;
Flags _flags;
EGLDisplay _display;
EGLSurface _surface;
EGLContext _context;
std::unique_ptr<Context> _c;
std::unique_ptr<LogOutput> _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 `AndroidManifest.xml` file.
*/
template<class T> 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;
};
/**
@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.
* @attention Available since Android 4.0 (API level 14), not
* detectable in earlier versions.
*/
#if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14
Left = AMOTION_EVENT_BUTTON_PRIMARY,
#else
Left = 1 << 0,
#endif
/**
* Middle mouse button or second stylus button
* @attention Available since Android 4.0 (API level 14), not
* detectable in earlier versions.
*/
#if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14
Middle = AMOTION_EVENT_BUTTON_TERTIARY,
#else
Middle = 1 << 1,
#endif
/**
* Right mouse button or first stylus button
* @attention Available since Android 4.0 (API level 14), not
* detectable in earlier versions.
*/
#if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14
Right = AMOTION_EVENT_BUTTON_SECONDARY
#else
Right = 1 << 2
#endif
};
/** @brief Button */
Button button() {
#if __ANDROID_API__ >= 14
return Button(AMotionEvent_getButtonState(_event));
#else
return Button::None;
#endif
}
/** @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 buttons()
*/
enum class Button: std::int32_t {
/**
* 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 defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14
Left = AMOTION_EVENT_BUTTON_PRIMARY,
#else
Left = 1 << 0,
#endif
/**
* Middle mouse button or second stylus button
* @attention Available since Android 4.0 (API level 14), not
* detectable in earlier versions.
*/
#if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14
Middle = AMOTION_EVENT_BUTTON_TERTIARY,
#else
Middle = 1 << 1,
#endif
/**
* Right mouse button or first stylus button
* @attention Available since Android 4.0 (API level 14), not
* detectable in earlier versions.
*/
#if defined(DOXYGEN_GENERATING_OUTPUT) || __ANDROID_API__ >= 14
Right = AMOTION_EVENT_BUTTON_SECONDARY
#else
Right = 1 << 2
#endif
};
/**
* @brief Set of mouse buttons
*
* @see @ref buttons()
*/
typedef Containers::EnumSet<Button, std::int32_t> Buttons;
/** @brief Position */
Vector2i position() const {
return {Int(AMotionEvent_getX(_event, 0)),
Int(AMotionEvent_getY(_event, 0))};
}
/** @brief Mouse buttons */
Buttons buttons() const {
#if __ANDROID_API__ >= 14
return Button(AMotionEvent_getButtonState(_event));
#else
return {};
#endif
}
private:
MouseMoveEvent(AInputEvent* event): InputEvent(event) {}
};
CORRADE_ENUMSET_OPERATORS(AndroidApplication::MouseMoveEvent::Buttons)
/** @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<className>); \
}
#ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_APPLICATION_MAIN
typedef AndroidApplication Application;
typedef BasicScreen<AndroidApplication> Screen;
typedef BasicScreenedApplication<AndroidApplication> ScreenedApplication;
#define MAGNUM_APPLICATION_MAIN(className) MAGNUM_ANDROIDAPPLICATION_MAIN(className)
#else
#undef MAGNUM_APPLICATION_MAIN
#endif
#endif
}}
#endif

34
src/Magnum/Platform/CMakeLists.txt

@ -32,11 +32,32 @@ set(Platform_HEADERS
install(FILES ${Platform_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) 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})
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}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
# GLUT application # GLUT application
if(WITH_GLUTAPPLICATION) if(WITH_GLUTAPPLICATION)
find_package(GLUT) find_package(GLUT)
if(GLUT_FOUND) if(GLUT_FOUND)
add_library(MagnumGlutApplication STATIC GlutApplication.cpp) 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(FILES GlutApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumGlutApplication install(TARGETS MagnumGlutApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
@ -53,6 +74,7 @@ if(WITH_SDL2APPLICATION)
if(SDL2_FOUND) if(SDL2_FOUND)
include_directories(${SDL2_INCLUDE_DIR}) include_directories(${SDL2_INCLUDE_DIR})
add_library(MagnumSdl2Application STATIC Sdl2Application.cpp) 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(FILES Sdl2Application.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumSdl2Application install(TARGETS MagnumSdl2Application
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
@ -70,6 +92,7 @@ if(WITH_NACLAPPLICATION)
endif() endif()
add_library(MagnumNaClApplication STATIC NaClApplication.cpp) 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(FILES NaClApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumNaClApplication install(TARGETS MagnumNaClApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
@ -84,6 +107,7 @@ if(WITH_WINDOWLESSNACLAPPLICATION)
endif() endif()
add_library(MagnumWindowlessNaClApplication STATIC WindowlessNaClApplication.cpp) 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(FILES WindowlessNaClApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumWindowlessNaClApplication install(TARGETS MagnumWindowlessNaClApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
@ -109,6 +133,7 @@ if(WITH_GLXAPPLICATION)
$<TARGET_OBJECTS:MagnumAbstractXApplication> $<TARGET_OBJECTS:MagnumAbstractXApplication>
$<TARGET_OBJECTS:MagnumGlxContextHandler> $<TARGET_OBJECTS:MagnumGlxContextHandler>
GlxApplication.cpp) GlxApplication.cpp)
set_target_properties(MagnumGlxApplication PROPERTIES DEBUG_POSTFIX "-d")
install(FILES GlxApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(FILES GlxApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumGlxApplication install(TARGETS MagnumGlxApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
@ -124,6 +149,7 @@ if(WITH_XEGLAPPLICATION)
$<TARGET_OBJECTS:MagnumAbstractXApplication> $<TARGET_OBJECTS:MagnumAbstractXApplication>
$<TARGET_OBJECTS:MagnumEglContextHandler> $<TARGET_OBJECTS:MagnumEglContextHandler>
XEglApplication.cpp) XEglApplication.cpp)
set_target_properties(MagnumXEglApplication PROPERTIES DEBUG_POSTFIX "-d")
install(FILES XEglApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform) install(FILES XEglApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumXEglApplication install(TARGETS MagnumXEglApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
@ -142,7 +168,9 @@ endif()
if(WITH_WINDOWLESSGLXAPPLICATION) if(WITH_WINDOWLESSGLXAPPLICATION)
add_library(MagnumWindowlessGlxApplication STATIC WindowlessGlxApplication.cpp) add_library(MagnumWindowlessGlxApplication STATIC WindowlessGlxApplication.cpp)
# X11 macros are a mess, disable warnings for C-style casts # 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(FILES WindowlessGlxApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumWindowlessGlxApplication install(TARGETS MagnumWindowlessGlxApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
@ -171,7 +199,9 @@ if(NEED_EGLCONTEXT)
if(NOT EGL_FOUND) 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.") message(FATAL_ERROR "EGL library, required by some window contexts, was not found. Set WITH_*EGL*APPLICATION to OFF to skip building them.")
endif() 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 # X11 macros are a mess, disable warnings for C-style casts
set_target_properties(MagnumEglContextHandler PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") set_target_properties(MagnumEglContextHandler PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast")
endif() endif()

25
src/Magnum/Platform/GlutApplication.cpp

@ -96,12 +96,18 @@ bool GlutApplication::tryCreateContext(const Configuration& configuration) {
#endif #endif
} }
/* Set context flags */
glutInitContextFlags(int(configuration.flags()));
if(!glutCreateWindow(configuration.title().data())) { if(!glutCreateWindow(configuration.title().data())) {
Error() << "Platform::GlutApplication::tryCreateContext(): cannot create context"; Error() << "Platform::GlutApplication::tryCreateContext(): cannot create context";
return false; return false;
} }
glutReshapeFunc(staticViewportEvent); glutReshapeFunc(staticViewportEvent);
glutSpecialFunc(staticKeyEvent); glutKeyboardFunc(staticKeyPressEvent);
glutKeyboardUpFunc(staticKeyReleaseEvent);
glutSpecialFunc(staticSpecialKeyPressEvent);
glutSpecialUpFunc(staticSpecialKeyReleaseEvent);
glutMouseFunc(staticMouseEvent); glutMouseFunc(staticMouseEvent);
glutMotionFunc(staticMouseMoveEvent); glutMotionFunc(staticMouseMoveEvent);
glutDisplayFunc(staticDrawEvent); glutDisplayFunc(staticDrawEvent);
@ -114,11 +120,26 @@ GlutApplication::~GlutApplication() {
delete c; 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<KeyEvent::Key>(key), {x, y}); KeyEvent e(static_cast<KeyEvent::Key>(key), {x, y});
instance->keyPressEvent(e); instance->keyPressEvent(e);
} }
void GlutApplication::staticKeyReleaseEvent(unsigned char key, int x, int y) {
KeyEvent e(static_cast<KeyEvent::Key>(key), {x, y});
instance->keyReleaseEvent(e);
}
void GlutApplication::staticSpecialKeyPressEvent(int key, int x, int y){
KeyEvent e(static_cast<KeyEvent::Key>(key << 16), {x, y});
instance->keyPressEvent(e);
}
void GlutApplication::staticSpecialKeyReleaseEvent(int key, int x, int y){
KeyEvent e(static_cast<KeyEvent::Key>(key << 16), {x, y});
instance->keyReleaseEvent(e);
}
void GlutApplication::staticMouseEvent(int button, int state, int x, int y) { void GlutApplication::staticMouseEvent(int button, int state, int x, int y) {
MouseEvent e(static_cast<MouseEvent::Button>(button), {x, y}); MouseEvent e(static_cast<MouseEvent::Button>(button), {x, y});
if(state == GLUT_DOWN) if(state == GLUT_DOWN)

195
src/Magnum/Platform/GlutApplication.h

@ -52,25 +52,41 @@ namespace Platform {
/** @nosubgrouping /** @nosubgrouping
@brief GLUT application @brief GLUT application
Application using GLUT toolkit. Supports keyboard handling for limited subset Application using GLUT toolkit. Supports keyboard and mouse handling with
of keys, mouse handling with support for changing cursor and mouse tracking and support for changing cursor and mouse tracking and warping.
warping.
This application library is available only on desktop OpenGL (Linux, Windows, 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 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 enabled in CMake.
in CMake, add `${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path and link
to `${MAGNUM_GLUTAPPLICATION_LIBRARIES}`. If no other application is requested, ## 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 you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building and @ref cmake for more information. @ref building and @ref cmake for more information.
@section GlutApplication-usage Usage 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
You need to implement at least @ref drawEvent() to be able to draw on the convenience macro @ref MAGNUM_GLUTAPPLICATION_MAIN(). See @ref platform for
screen. The subclass can be then used directly in `main()` -- see convenience more information.
macro @ref MAGNUM_GLUTAPPLICATION_MAIN(). See @ref platform for more
information.
@code @code
class MyApplication: public Platform::GlutApplication { class MyApplication: public Platform::GlutApplication {
// implement required methods... // implement required methods...
@ -124,7 +140,12 @@ class GlutApplication {
/** @brief Moving is not allowed */ /** @brief Moving is not allowed */
GlutApplication& operator=(GlutApplication&&) = delete; 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() { int exec() {
glutMainLoop(); glutMainLoop();
return 0; return 0;
@ -173,12 +194,7 @@ class GlutApplication {
/** @copydoc Sdl2Application::keyPressEvent() */ /** @copydoc Sdl2Application::keyPressEvent() */
virtual void keyPressEvent(KeyEvent& event); virtual void keyPressEvent(KeyEvent& event);
/** /** @copydoc Sdl2Application::keyReleaseEvent() */
* @brief Key release event
*
* Included only for compatibility with other toolkits, doesn't get
* called at all.
*/
virtual void keyReleaseEvent(KeyEvent& event); virtual void keyReleaseEvent(KeyEvent& event);
/*@}*/ /*@}*/
@ -245,7 +261,11 @@ class GlutApplication {
instance->viewportEvent({x, y}); 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); static void staticMouseEvent(int button, int state, int x, int y);
@ -268,6 +288,26 @@ Double-buffered RGBA window with depth and stencil buffers.
*/ */
class GlutApplication::Configuration { class GlutApplication::Configuration {
public: 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<Flag, int, GLUT_DEBUG> Flags;
#else
typedef Containers::EnumSet<Flag, int> Flags;
#endif
/*implicit*/ Configuration(); /*implicit*/ Configuration();
~Configuration(); ~Configuration();
@ -299,6 +339,20 @@ class GlutApplication::Configuration {
return *this; 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 */ /** @brief Context version */
Version version() const { return _version; } Version version() const { return _version; }
@ -336,8 +390,11 @@ class GlutApplication::Configuration {
Vector2i _size; Vector2i _size;
Int _sampleCount; Int _sampleCount;
Version _version; Version _version;
Flags _flags;
}; };
CORRADE_ENUMSET_OPERATORS(GlutApplication::Configuration::Flags)
/** /**
@brief Base for input events @brief Base for input events
@ -395,27 +452,76 @@ class GlutApplication::KeyEvent: public GlutApplication::InputEvent {
* *
* @see @ref key() * @see @ref key()
*/ */
enum class Key: int { enum class Key: UnsignedInt {
Up = GLUT_KEY_UP, /**< Up arrow */ Esc = '\x1b', /**< Escape */
Down = GLUT_KEY_DOWN, /**< Down arrow */
Left = GLUT_KEY_LEFT, /**< Left arrow */ Up = GLUT_KEY_UP << 16, /**< Up arrow */
Right = GLUT_KEY_RIGHT, /**< Right arrow */ Down = GLUT_KEY_DOWN << 16, /**< Down arrow */
F1 = GLUT_KEY_F1, /**< F1 */ Left = GLUT_KEY_LEFT << 16, /**< Left arrow */
F2 = GLUT_KEY_F2, /**< F2 */ Right = GLUT_KEY_RIGHT << 16, /**< Right arrow */
F3 = GLUT_KEY_F3, /**< F3 */ F1 = GLUT_KEY_F1 << 16, /**< F1 */
F4 = GLUT_KEY_F4, /**< F4 */ F2 = GLUT_KEY_F2 << 16, /**< F2 */
F5 = GLUT_KEY_F5, /**< F5 */ F3 = GLUT_KEY_F3 << 16, /**< F3 */
F6 = GLUT_KEY_F6, /**< F6 */ F4 = GLUT_KEY_F4 << 16, /**< F4 */
F7 = GLUT_KEY_F7, /**< F7 */ F5 = GLUT_KEY_F5 << 16, /**< F5 */
F8 = GLUT_KEY_F8, /**< F8 */ F6 = GLUT_KEY_F6 << 16, /**< F6 */
F9 = GLUT_KEY_F9, /**< F9 */ F7 = GLUT_KEY_F7 << 16, /**< F7 */
F10 = GLUT_KEY_F10, /**< F10 */ F8 = GLUT_KEY_F8 << 16, /**< F8 */
F11 = GLUT_KEY_F11, /**< F11 */ F9 = GLUT_KEY_F9 << 16, /**< F9 */
F12 = GLUT_KEY_F12, /**< F12 */ F10 = GLUT_KEY_F10 << 16, /**< F10 */
Home = GLUT_KEY_HOME, /**< Home */ F11 = GLUT_KEY_F11 << 16, /**< F11 */
End = GLUT_KEY_END, /**< End */ F12 = GLUT_KEY_F12 << 16, /**< F12 */
PageUp = GLUT_KEY_PAGE_UP, /**< Page up */ Home = GLUT_KEY_HOME << 16, /**< Home */
PageDown = GLUT_KEY_PAGE_DOWN /**< Page down */ 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 */ /** @brief Key */
@ -512,9 +618,10 @@ class GlutApplication::MouseMoveEvent: public GlutApplication::InputEvent {
@brief Entry point for GLUT-based applications @brief Entry point for GLUT-based applications
@param className Class name @param className Class name
Can be with @ref Magnum::Platform::GlutApplication "Platform::GlutApplication" See @ref Magnum::Platform::GlutApplication "Platform::GlutApplication" for
subclasses used as equivalent to the following code to achieve better usage information. This macro abstracts out platform-specific entry point code
portability, see @ref portability-applications for more information. and is equivalent to the following, see @ref portability-applications for more
information.
@code @code
int main(int argc, char** argv) { int main(int argc, char** argv) {
className app({argc, argv}); className app({argc, argv});

27
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 This application library is available on desktop OpenGL and
@ref MAGNUM_TARGET_DESKTOP_GLES "OpenGL ES emulation on desktop" on Linux. It @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 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_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_GLXAPPLICATION_LIBRARIES}`. If no other application is requested, you `${MAGNUM_GLXAPPLICATION_LIBRARIES}`. If no other application is requested, you
can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building and @ref cmake for more information. @ref building and @ref cmake for more information.
@section GlxApplication-usage Usage 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
You need to implement at least @ref drawEvent() to be able to draw on the convenience macro @ref MAGNUM_GLXAPPLICATION_MAIN(). See @ref platform for more
screen. The subclass can be then used directly in `main()` -- see convenience
macro @ref MAGNUM_GLXAPPLICATION_MAIN(). See @ref platform for more
information. information.
@code @code
class MyApplication: public Platform::GlxApplication { class MyApplication: public Platform::GlxApplication {
@ -88,9 +96,10 @@ class GlxApplication: public AbstractXApplication {
@brief Entry point for GLX-based applications @brief Entry point for GLX-based applications
@param className Class name @param className Class name
Can be used with @ref Magnum::Platform::GlxApplication "Platform::GlxApplication" See @ref Magnum::Platform::GlxApplication "Platform::GlxApplication" for usage
subclasses as equivalent to the following code to achieve better portability, information. This macro abstracts out platform-specific entry point code and is
see @ref portability-applications for more information. equivalent to the following, see @ref portability-applications for more
information.
@code @code
int main(int argc, char** argv) { int main(int argc, char** argv) {
className app({argc, argv}); className app({argc, argv});

54
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š <mosra@centrum.cz>
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)";
}
}}}

33
src/Magnum/ImageFormat.h → src/Magnum/Platform/Implementation/Egl.h

@ -1,5 +1,5 @@
#ifndef Magnum_ImageFormat_h #ifndef Magnum_Platform_Implementation_Egl_h
#define Magnum_ImageFormat_h #define Magnum_Platform_Implementation_Egl_h
/* /*
This file is part of Magnum. This file is part of Magnum.
@ -25,33 +25,12 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
#ifdef MAGNUM_BUILD_DEPRECATED #include <EGL/egl.h>
/** @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 {
/** namespace Magnum { namespace Platform { namespace Implementation {
@copybrief ColorFormat
@deprecated Use @ref Magnum::ColorFormat "ColorFormat" instead.
*/
typedef CORRADE_DEPRECATED("use ColorFormat instead") ColorFormat ImageFormat;
/** const char* eglErrorString(EGLint error);
@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 #endif

42
src/Magnum/Platform/Implementation/EglContextHandler.cpp

@ -32,6 +32,8 @@
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Version.h" #include "Magnum/Version.h"
#include "Egl.h"
namespace Magnum { namespace Platform { namespace Implementation { namespace Magnum { namespace Platform { namespace Implementation {
EglContextHandler::~EglContextHandler() { EglContextHandler::~EglContextHandler() {
@ -44,7 +46,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) {
/* Initialize */ /* Initialize */
display = eglGetDisplay(nativeDisplay); display = eglGetDisplay(nativeDisplay);
if(!eglInitialize(display, nullptr, nullptr)) { if(!eglInitialize(display, nullptr, nullptr)) {
Error() << "Cannot initialize EGL:" << errorString(eglGetError()); Error() << "Cannot initialize EGL:" << Implementation::eglErrorString(eglGetError());
std::exit(1); std::exit(1);
} }
@ -54,7 +56,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) {
EGLenum api = EGL_OPENGL_ES_API; EGLenum api = EGL_OPENGL_ES_API;
#endif #endif
if(!eglBindAPI(api)) { if(!eglBindAPI(api)) {
Error() << "Cannot bind EGL API:" << errorString(eglGetError()); Error() << "Cannot bind EGL API:" << Implementation::eglErrorString(eglGetError());
std::exit(1); std::exit(1);
} }
@ -67,7 +69,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
#elif defined(MAGNUM_TARGET_GLES3) #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) #elif defined(MAGNUM_TARGET_GLES2)
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#else #else
@ -77,7 +79,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) {
}; };
EGLint configCount; EGLint configCount;
if(!eglChooseConfig(display, attribs, &config, 1, &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); std::exit(1);
} }
@ -89,7 +91,7 @@ VisualId EglContextHandler::getVisualId(EGLNativeDisplayType nativeDisplay) {
/* Get visual ID */ /* Get visual ID */
EGLint visualId; EGLint visualId;
if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &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); std::exit(1);
} }
@ -140,40 +142,16 @@ void EglContextHandler::createContext(const AbstractXApplication::Configuration&
} }
#endif #endif
if(!eglCreateContext(display, config, EGL_NO_CONTEXT, attributes)) { if(!(context = eglCreateContext(display, config, EGL_NO_CONTEXT, attributes))) {
Error() << "Cannot create EGL context:" << errorString(eglGetError()); Error() << "Cannot create EGL context:" << Implementation::eglErrorString(eglGetError());
std::exit(1); std::exit(1);
} }
if(!(surface = eglCreateWindowSurface(display, config, window, nullptr))) { 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); std::exit(1);
} }
/** @bug Fixme: On desktop OpenGL and Mesa EGL implementation OpenGL version is 1.0, which is wrong */ /** @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 {};
}
}}} }}}

3
src/Magnum/Platform/Implementation/EglContextHandler.h

@ -31,6 +31,7 @@
#include <EGL/egl.h> #include <EGL/egl.h>
/* undef Xlib nonsense to avoid conflicts */ /* undef Xlib nonsense to avoid conflicts */
#undef None #undef None
#undef Complex
#include <Corrade/compatibility.h> #include <Corrade/compatibility.h>
@ -71,8 +72,6 @@ class EglContextHandler: public AbstractContextHandler<AbstractXApplication::Con
} }
private: private:
const char* errorString(EGLint error);
EGLDisplay display; EGLDisplay display;
EGLConfig config; EGLConfig config;
EGLSurface surface; EGLSurface surface;

117
src/Magnum/Platform/NaClApplication.h

@ -52,6 +52,10 @@ namespace pp {
class Fullscreen; class Fullscreen;
} }
#ifndef CORRADE_TARGET_NACL
#error This header is available only on Google Chrome Native Client
#endif
namespace Magnum { namespace Platform { namespace Magnum { namespace Platform {
/** @nosubgrouping /** @nosubgrouping
@ -60,19 +64,68 @@ namespace Magnum { namespace Platform {
Application running in [Google Chrome Native Client](https://developers.google.com/native-client/). Application running in [Google Chrome Native Client](https://developers.google.com/native-client/).
Supports keyboard and mouse handling. Supports keyboard and mouse handling.
This application library is available only in @ref CORRADE_TARGET_NACL "Native Client". This application library is available only in
It is built if `WITH_NACLAPPLICATION` is enabled in CMake. To use it, you need @ref CORRADE_TARGET_NACL "Google Chrome Native Client", see respective sections
to request `%NaClApplication` component in CMake, add 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
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_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_NACLAPPLICATION_LIBRARIES}`. If no other application is requested, `${MAGNUM_NACLAPPLICATION_LIBRARIES}`. If no other application is requested,
you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building and @ref cmake for more information. @ref building and @ref cmake for more information.
@section NaClApplication-usage Usage 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
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 @ref MAGNUM_NACLAPPLICATION_MAIN() macro. See @ref platform for more
information. information.
@code @code
@ -86,13 +139,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()` `Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()`
to simplify porting. 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 need to provide HTML markup for your application. Template one is below or
you can modify it to your liking. The markup references two files, in the bootstrap application, you can modify it to your liking. The markup
`NaClApplication.js` and `WebApplication.css`, both are in `Platform/` references two files, `NaClApplication.js` and `WebApplication.css`, both are
directory in the source tree and are also installed into `share/magnum/` inside in `Platform/` directory in the source tree and are also installed into
your NaCl toolchain. Change `&lt;application&gt;` to name of your executable. `share/magnum/` inside your NaCl toolchain. Change `&lt;application&gt;` to
name of your executable.
@code @code
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
@ -135,9 +189,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/) all additional dependencies. See [Native Client](https://developers.google.com/native-client/)
documentation for more information. 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" @ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error"
output to JavaScript console. See also @ref Corrade::Utility::NaClConsoleStreamBuffer output to JavaScript console. See also @ref Corrade::Utility::NaClConsoleStreamBuffer
for more information. for more information.
@ -347,7 +401,7 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
@brief %Configuration @brief %Configuration
Double-buffered RGBA canvas with depth and stencil buffers. Double-buffered RGBA canvas with depth and stencil buffers.
@see @ref NaClApplication(), @ref createContext() @see @ref NaClApplication(), @ref createContext(), @ref tryCreateContext()
*/ */
class NaClApplication::Configuration { class NaClApplication::Configuration {
public: public:
@ -428,33 +482,6 @@ class NaClApplication::InputEvent {
Ctrl = PP_INPUTEVENT_MODIFIER_CONTROLKEY, /**< Ctrl */ Ctrl = PP_INPUTEVENT_MODIFIER_CONTROLKEY, /**< Ctrl */
Alt = PP_INPUTEVENT_MODIFIER_ALTKEY, /**< Alt */ Alt = PP_INPUTEVENT_MODIFIER_ALTKEY, /**< Alt */
Meta = PP_INPUTEVENT_MODIFIER_METAKEY, /**< Meta */ 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 */ CapsLock = PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY, /**< Caps lock */
NumLock = PP_INPUTEVENT_MODIFIER_NUMLOCKKEY /**< Num lock */ NumLock = PP_INPUTEVENT_MODIFIER_NUMLOCKKEY /**< Num lock */
}; };
@ -718,7 +745,9 @@ namespace Implementation {
@brief Entry point for NaCl application @brief Entry point for NaCl application
@param application Application class name @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 @ref portability-applications for more information. When no other application
header is included this macro is also aliased to `MAGNUM_APPLICATION_MAIN()`. header is included this macro is also aliased to `MAGNUM_APPLICATION_MAIN()`.
*/ */

5
src/Magnum/Platform/Sdl2Application.cpp

@ -115,6 +115,11 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, configuration.sampleCount() > 1 ? 1 : 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, configuration.sampleCount() > 1 ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration.sampleCount()); 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 */ /* Flags: if not hidden, set as shown */
Uint32 windowFlags(configuration.windowFlags()); Uint32 windowFlags(configuration.windowFlags());
if(!(configuration.windowFlags() & Configuration::WindowFlag::Hidden)) windowFlags |= SDL_WINDOW_SHOWN; if(!(configuration.windowFlags() & Configuration::WindowFlag::Hidden)) windowFlags |= SDL_WINDOW_SHOWN;

198
src/Magnum/Platform/Sdl2Application.h

@ -46,10 +46,6 @@
#include "Magnum/Version.h" #include "Magnum/Version.h"
#endif #endif
#ifdef MAGNUM_BUILD_DEPRECATED
#include <Corrade/Utility/Macros.h>
#endif
namespace Magnum { namespace Magnum {
class Context; class Context;
@ -63,21 +59,70 @@ Application using [Simple DirectMedia Layer](http://www.libsdl.org/) toolkit.
Supports keyboard and mouse handling. Supports keyboard and mouse handling.
This application library is in theory available for all platforms for which This application library is in theory available for all platforms for which
SDL2 is ported (thus also @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", but not SDL2 is ported (thus also @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", see
@ref CORRADE_TARGET_NACL "NaCl"). It depends on **SDL2** library (Emscripten respective sections in @ref building-corrade-cross-emscripten "Corrade's" and
has it built in) and is built if `WITH_SDL2APPLICATION` is enabled in CMake. To @ref building-cross-emscripten "Magnum's" building documentation). It depends
use it, you need to copy `FindSDL2.cmake` from `modules/` directory in %Magnum on **SDL2** library (Emscripten has it built in) and is built if
source to `modules/` dir in your project (so CMake is able to find SDL2), `WITH_SDL2APPLICATION` is enabled in CMake.
request `%Sdl2Application` component in CMake, add
`${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` to include path and link to ## Bootstrap application
`${MAGNUM_SDL2APPLICATION_LIBRARIES}`. If no other application is requested,
you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and Fully contained base application using @ref Sdl2Application along with
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See 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).
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
@ref building and @ref cmake for more information. @ref building and @ref cmake for more information.
@section Sdl2Application-usage Usage In C++ code you need to implement at least @ref drawEvent() to be able to draw on the
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 screen. The subclass can be then used directly in `main()` -- see convenience
macro @ref MAGNUM_SDL2APPLICATION_MAIN(). See @ref platform for more macro @ref MAGNUM_SDL2APPLICATION_MAIN(). See @ref platform for more
information. information.
@ -92,14 +137,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()` `Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()`
to simplify porting. to simplify porting.
@section Sdl2Application-html Usage with Emscripten ### Usage with Emscripten
If you are targetting @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", you need to If you are targetting Emscripten, you need to provide HTML markup for your
provide HTML markup for your application. Template one is below, you can modify application. Template one is below or in the bootstrap application, you can
it to your liking. The markup references two files, `EmscriptenApplication.js` modify it to your liking. The markup references two files,
and `WebApplication.css`, both are in `Platform/` directory in the source tree `EmscriptenApplication.js` and `WebApplication.css`, both are in `Platform/`
and are also installed into `share/magnum/` inside your Emscripten toolchain. directory in the source tree and are also installed into `share/magnum/` inside
Change `&lt;application&gt;` to name of your executable. your Emscripten toolchain. Change `&lt;application&gt;` to name of your
executable.
@code @code
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
@ -127,9 +173,11 @@ file contains event listeners which print loading status on the page. The
status displayed in the remaining two `&lt;div&gt;`s, if they are available. status displayed in the remaining two `&lt;div&gt;`s, if they are available.
The CSS file contains rudimentary style to avoid eye bleeding. The CSS file contains rudimentary style to avoid eye bleeding.
The application redirects @ref Corrade::Utility::Debug "Debug", ## Redirecting output to JavaScript console
@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error"
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 { class Sdl2Application {
public: public:
@ -189,7 +237,9 @@ class Sdl2Application {
/** /**
* @brief Execute main loop * @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(); int exec();
@ -237,7 +287,8 @@ class Sdl2Application {
* @brief Redraw immediately * @brief Redraw immediately
* *
* Marks the window for redrawing, resulting in call to @ref drawEvent() * 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; } void redraw() { flags |= Flag::Redraw; }
@ -380,6 +431,35 @@ depth buffer.
*/ */
class Sdl2Application::Configuration { class Sdl2Application::Configuration {
public: 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 */
/** Create context with robust access */
RobustAccess = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG
};
/**
* @brief Context flags
*
* @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten".
* @see @ref setFlags()
*/
#ifndef DOXYGEN_GENERATING_OUTPUT
typedef Containers::EnumSet<Flag, int, SDL_GL_CONTEXT_DEBUG_FLAG|
SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG> Flags;
#else
typedef Containers::EnumSet<Flag, int> Flags;
#endif
#endif
/** /**
* @brief Window flag * @brief Window flag
* *
@ -394,14 +474,6 @@ class Sdl2Application::Configuration {
MouseLocked = SDL_WINDOW_INPUT_GRABBED /**< Window with mouse locked */ 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 * @brief Window flags
* *
@ -415,14 +487,6 @@ class Sdl2Application::Configuration {
typedef Containers::EnumSet<WindowFlag, Uint32> WindowFlags; typedef Containers::EnumSet<WindowFlag, Uint32> WindowFlags;
#endif #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(); /*implicit*/ Configuration();
~Configuration(); ~Configuration();
@ -470,16 +534,6 @@ class Sdl2Application::Configuration {
/** @brief Window flags */ /** @brief Window flags */
WindowFlags windowFlags() const { return _windowFlags; } 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 * @brief Set window flags
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
@ -491,17 +545,26 @@ class Sdl2Application::Configuration {
return *this; return *this;
} }
#ifdef MAGNUM_BUILD_DEPRECATED #ifndef CORRADE_TARGET_EMSCRIPTEN
/**
* @brief Context flags
*
* @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten".
*/
Flags flags() const { return _flags; }
/** /**
* @copybrief setWindowFlags() * @brief Set context flags
* @deprecated Use @ref Magnum::Platform::Sdl2Application::Configuration::setWindowFlags "setWindowFlags()" instead. * @return Reference to self (for method chaining)
*
* Default is no flag.
* @note Not available in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten".
*/ */
CORRADE_DEPRECATED("use setWindowFlags() instead") Configuration& setFlags(WindowFlags flags) { Configuration& setFlags(Flags flags) {
return setWindowFlags(flags); _flags = flags;
return *this;
} }
#endif
#ifndef CORRADE_TARGET_EMSCRIPTEN
/** /**
* @brief Context version * @brief Context version
* *
@ -553,9 +616,13 @@ class Sdl2Application::Configuration {
Int _sampleCount; Int _sampleCount;
#ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef CORRADE_TARGET_EMSCRIPTEN
Version _version; Version _version;
Flags _flags;
#endif #endif
}; };
#ifndef CORRADE_TARGET_EMSCRIPTEN
CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::Flags)
#endif
CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::WindowFlags) CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::WindowFlags)
/** /**
@ -841,9 +908,10 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent {
@brief Entry point for SDL2-based applications @brief Entry point for SDL2-based applications
@param className Class name @param className Class name
Can be used with @ref Magnum::Platform::Sdl2Application "Platform::Sdl2Application" See @ref Magnum::Platform::Sdl2Application "Platform::Sdl2Application" for
subclasses as equivalent to the following code to achieve better portability, usage information. This macro abstracts out platform-specific entry point code
see @ref portability-applications for more information. and is equivalent to the following, see @ref portability-applications for more
information.
@code @code
int main(int argc, char** argv) { int main(int argc, char** argv) {
className app({argc, argv}); className app({argc, argv});

41
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 This application library is available on desktop OpenGL and
@ref MAGNUM_TARGET_DESKTOP_GLES "OpenGL ES emulation on desktop" on Linux. It @ref MAGNUM_TARGET_DESKTOP_GLES "OpenGL ES emulation on desktop" on Linux. It
depends on **X11** library and is built if `WITH_WINDOWLESSGLXAPPLICATION` is depends on **X11** library and is built if `WITH_WINDOWLESSGLXAPPLICATION` is
enabled in CMake. To use it, you need to request `%WindowlessGlxApplication` enabled in CMake.
component in CMake, add `${MAGNUM_WINDOWLESSGLXAPPLICATION_INCLUDE_DIRS}` to
include path and link to `${MAGNUM_WINDOWLESSGLXAPPLICATION_LIBRARIES}`. If no ## Bootstrap application
other windowless application is requested, you can also use generic
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_INCLUDE_DIRS}` and
`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building and @ref cmake for more information. @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 Place your code into @ref exec(). The subclass can be then used directly in
`main()` -- see convenience macro @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(). `main()` -- see convenience macro @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN().
See @ref platform for more information. See @ref platform for more information.
@ -117,7 +134,10 @@ class WindowlessGlxApplication {
/** /**
* @brief Execute application * @brief Execute application
* @return Value for returning from `main()`. * @return Value for returning from `main()`
*
* See @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN() for usage
* information.
*/ */
virtual int exec() = 0; virtual int exec() = 0;
@ -161,9 +181,10 @@ class WindowlessGlxApplication::Configuration {
@brief Entry point for windowless GLX application @brief Entry point for windowless GLX application
@param className Class name @param className Class name
Can be used with @ref Magnum::Platform::WindowlessGlxApplication "Platform::WindowlessGlxApplication" See @ref Magnum::Platform::WindowlessGlxApplication "Platform::WindowlessGlxApplication"
subclasses as equivalent to the following code to achieve better portability, for usage information. This macro abstracts out platform-specific entry point
see @ref portability-applications for more information. code and is equivalent to the following, see @ref portability-applications for
more information.
@code @code
int main(int argc, char** argv) { int main(int argc, char** argv) {
className app({argc, argv}); className app({argc, argv});

41
src/Magnum/Platform/WindowlessNaClApplication.h

@ -52,9 +52,20 @@ namespace Magnum { namespace Platform {
Application for offscreen rendering running in Application for offscreen rendering running in
[Google Chrome Native Client](https://developers.google.com/native-client/). [Google Chrome Native Client](https://developers.google.com/native-client/).
This application library is available only in @ref CORRADE_TARGET_NACL "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, see respective sections in @ref building-corrade-cross-nacl "Corrade's" and
you need to request `%WindowlessNaClApplication` component in CMake, add @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_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_WINDOWLESSNACLAPPLICATION_LIBRARIES}`. If no other windowless `${MAGNUM_WINDOWLESSNACLAPPLICATION_LIBRARIES}`. If no other windowless
application is requested, you can also use generic 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 `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building and @ref cmake for more information. @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 Place your code into @ref exec(). The subclass must be then registered to NaCl
API using @ref MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() macro. See @ref platform API using @ref MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() macro. See @ref platform
for more information. 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 `Platform::WindowlessApplication` and the macro is aliased to
`MAGNUM_WINDOWLESSAPPLICATION_MAIN()` to simplify porting. `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 `&lt;embed&gt;` pointing to `*.nmf` You need to provide HTML markup containing `&lt;embed&gt;` pointing to `*.nmf`
file describing the application. See @ref NaClApplication for more information. file describing the application. See @ref NaClApplication for more information.
@ -86,9 +95,9 @@ You may want to hide the `&lt;embed&gt;` (for example using CSS
`visibility: hidden;`), as it probably won't display anything to default `visibility: hidden;`), as it probably won't display anything to default
framebuffer. 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" @ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error"
output to JavaScript console. See also @ref Corrade::Utility::NaClConsoleStreamBuffer output to JavaScript console. See also @ref Corrade::Utility::NaClConsoleStreamBuffer
for more information. for more information.
@ -128,9 +137,17 @@ class WindowlessNaClApplication: public pp::Instance, public pp::Graphics3DClien
/** @brief Moving is not allowed */ /** @brief Moving is not allowed */
WindowlessNaClApplication& operator=(WindowlessNaClApplication&&) = delete; WindowlessNaClApplication& operator=(WindowlessNaClApplication&&) = delete;
#ifdef DOXYGEN_GENERATING_OUTPUT
protected:
#else
private:
#endif
/** /**
* @brief Execute application * @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; virtual int exec() = 0;
@ -194,8 +211,10 @@ namespace Implementation {
@param application Application class name @param application Application class name
See @ref Magnum::Platform::WindowlessNaClApplication "Platform::WindowlessNaClApplication" See @ref Magnum::Platform::WindowlessNaClApplication "Platform::WindowlessNaClApplication"
and @ref portability-applications for more information. When no other for usage information. This macro abstracts out platform-specific entry point
windowless application header is included this macro is also aliased to 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()`. `MAGNUM_WINDOWLESSAPPLICATION_MAIN()`.
*/ */
/* look at that insane placement of __attribute__. WTF. */ /* look at that insane placement of __attribute__. WTF. */

36
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 This application library is available on both desktop OpenGL and
@ref MAGNUM_TARGET_GLES "OpenGL ES" on Linux. It depends on **X11** and **EGL** @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 libraries and is built if `WITH_XEGLAPPLICATION` is enabled in CMake.
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), ## Bootstrap application
request `%XEglApplication` component in CMake, add `${MAGNUM_XEGLAPPLICATION_INCLUDE_DIRS}`
to include path and link to `${MAGNUM_XEGLAPPLICATION_LIBRARIES}`. If no other 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}` application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}`
and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building and @ref cmake for more information. @ref building and @ref cmake for more information.
@section XEglApplication-usage Usage 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
You need to implement at least @ref drawEvent() to be able to draw on the convenience macro @ref MAGNUM_XEGLAPPLICATION_MAIN(). See @ref platform for
screen. The subclass can be then used directly in `main()` -- see convenience more information.
macro @ref MAGNUM_XEGLAPPLICATION_MAIN(). See @ref platform for more
information.
@code @code
class MyApplication: public Platform::XEglApplication { class MyApplication: public Platform::XEglApplication {
// implement required methods... // implement required methods...
@ -89,9 +96,10 @@ class XEglApplication: public AbstractXApplication {
@brief Entry point for X/EGL-based applications @brief Entry point for X/EGL-based applications
@param className Class name @param className Class name
Can be used with @ref Magnum::Platform::XEglApplication "Platform::XEglApplication" See @ref Magnum::Platform::XEglApplication "Platform::XEglApplication" for
subclasses as equivalent to the following code to achieve better portability, usage information. This macro abstracts out platform-specific entry point code
see @ref portability-applications for more information. and is equivalent to the following, see @ref portability-applications for more
information.
@code @code
int main(int argc, char** argv) { int main(int argc, char** argv) {
className app({argc, argv}); className app({argc, argv});

26
src/Magnum/Platform/magnum-info.cpp

@ -61,8 +61,8 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
Utility::Arguments args; Utility::Arguments args;
args.addBooleanOption("all-extensions") args.addBooleanOption("all-extensions")
.setHelp("all-extensions", "show extensions also for fully supported versions") .setHelp("all-extensions", "show extensions also for fully supported versions")
.addBooleanOption("no-limits") .addBooleanOption("limits")
.setHelp("no-limits", "don't display limits and implementation-defined values") .setHelp("limits", "display also limits and implementation-defined values")
.setHelp("Displays information about Magnum engine and OpenGL capabilities."); .setHelp("Displays information about Magnum engine and OpenGL capabilities.");
/** /**
@ -73,11 +73,6 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
args.parse(arguments.argc, arguments.argv); args.parse(arguments.argc, arguments.argv);
#endif #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 */ /* Pass debug output as messages to JavaScript */
#ifdef CORRADE_TARGET_NACL #ifdef CORRADE_TARGET_NACL
Utility::NaClMessageStreamBuffer buffer(this); Utility::NaClMessageStreamBuffer buffer(this);
@ -142,12 +137,27 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
#ifdef MAGNUM_TARGET_DESKTOP_GLES #ifdef MAGNUM_TARGET_DESKTOP_GLES
Debug() << " MAGNUM_TARGET_DESKTOP_GLES"; Debug() << " MAGNUM_TARGET_DESKTOP_GLES";
#endif #endif
#ifdef MAGNUM_TARGET_WEBGL
Debug() << " MAGNUM_TARGET_WEBGL";
#endif
Debug() << ""; Debug() << "";
/* Create context here, so the context creation info is displayed at proper
place */
createContext();
Context* c = Context::current();
Debug() << "Vendor:" << c->vendorString(); Debug() << "Vendor:" << c->vendorString();
Debug() << "Renderer:" << c->rendererString(); Debug() << "Renderer:" << c->rendererString();
Debug() << "OpenGL version:" << c->version() << '(' + c->versionString() + ')'; 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:"; Debug() << "Supported GLSL versions:";
const std::vector<std::string> shadingLanguageVersions = c->shadingLanguageVersionStrings(); const std::vector<std::string> shadingLanguageVersions = c->shadingLanguageVersionStrings();
for(auto it = shadingLanguageVersions.begin(); it != shadingLanguageVersions.end(); ++it) for(auto it = shadingLanguageVersions.begin(); it != shadingLanguageVersions.end(); ++it)
@ -204,7 +214,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
Debug() << ""; Debug() << "";
} }
if(args.isSet("no-limits")) return; if(!args.isSet("limits")) return;
/* Limits and implementation-defined values */ /* Limits and implementation-defined values */
#define _h(val) Debug() << "\n " << Extensions::GL::val::string() + std::string(":"); #define _h(val) Debug() << "\n " << Extensions::GL::val::string() + std::string(":");

1
src/Magnum/Primitives/CMakeLists.txt

@ -53,6 +53,7 @@ set(MagnumPrimitives_HEADERS
visibility.h) visibility.h)
add_library(MagnumPrimitives ${SHARED_OR_STATIC} ${MagnumPrimitives_SRCS}) add_library(MagnumPrimitives ${SHARED_OR_STATIC} ${MagnumPrimitives_SRCS})
set_target_properties(MagnumPrimitives PROPERTIES DEBUG_POSTFIX "-d")
if(BUILD_STATIC_PIC) if(BUILD_STATIC_PIC)
# TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property # TODO: CMake 2.8.9 has this as POSITION_INDEPENDENT_CODE property
set_target_properties(MagnumPrimitives PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") set_target_properties(MagnumPrimitives PROPERTIES COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}")

2
src/Magnum/Query.cpp

@ -123,6 +123,7 @@ template<> Int AbstractQuery::result<Int>() {
return result; return result;
} }
#ifndef MAGNUM_TARGET_WEBGL
template<> UnsignedLong AbstractQuery::result<UnsignedLong>() { template<> UnsignedLong AbstractQuery::result<UnsignedLong>() {
CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {}); CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {});
@ -151,6 +152,7 @@ template<> Long AbstractQuery::result<Long>() {
return result; return result;
} }
#endif #endif
#endif
void AbstractQuery::begin(GLenum target) { void AbstractQuery::begin(GLenum target) {
CORRADE_ASSERT(!this->target, "AbstractQuery::begin(): the query is already running", ); CORRADE_ASSERT(!this->target, "AbstractQuery::begin(): the query is already running", );

8
src/Magnum/Query.h

@ -107,6 +107,8 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject {
* @requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query} * @requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query}
* for result types @ref Magnum::Int "Int", @ref Magnum::UnsignedLong "UnsignedLong" * for result types @ref Magnum::Int "Int", @ref Magnum::UnsignedLong "UnsignedLong"
* @ref Magnum::Long "Long". * @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<class T> T result(); template<class T> T result();
@ -147,16 +149,18 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject {
template<> bool MAGNUM_EXPORT AbstractQuery::result<bool>(); template<> bool MAGNUM_EXPORT AbstractQuery::result<bool>();
template<> UnsignedInt MAGNUM_EXPORT AbstractQuery::result<UnsignedInt>(); template<> UnsignedInt MAGNUM_EXPORT AbstractQuery::result<UnsignedInt>();
template<> Int MAGNUM_EXPORT AbstractQuery::result<Int>(); template<> Int MAGNUM_EXPORT AbstractQuery::result<Int>();
#ifndef MAGNUM_TARGET_WEBGL
template<> UnsignedLong MAGNUM_EXPORT AbstractQuery::result<UnsignedLong>(); template<> UnsignedLong MAGNUM_EXPORT AbstractQuery::result<UnsignedLong>();
template<> Long MAGNUM_EXPORT AbstractQuery::result<Long>(); template<> Long MAGNUM_EXPORT AbstractQuery::result<Long>();
#endif #endif
#endif
#ifndef MAGNUM_TARGET_GLES2 #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 Queries count of generated primitives from vertex shader, geometry shader or
transform feedback and elapsed time. Example usage: transform feedback. Example usage:
@code @code
PrimitiveQuery q; PrimitiveQuery q;

53
src/Magnum/RectangleTexture.h

@ -86,8 +86,8 @@ class RectangleTexture: public AbstractTexture {
* *
* Sets filter used when the object pixel size is smaller than the * Sets filter used when the object pixel size is smaller than the
* texture size. If @extension{EXT,direct_state_access} is not * texture size. If @extension{EXT,direct_state_access} is not
* available, the texture is bound to some layer before the operation. * available, the texture is bound to some texture unit before the
* Initial value is @ref Sampler::Filter::Linear. * operation. Initial value is @ref Sampler::Filter::Linear.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter}
* or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_MIN_FILTER} * with @def_gl{TEXTURE_MIN_FILTER}
@ -103,20 +103,17 @@ class RectangleTexture: public AbstractTexture {
return *this; return *this;
} }
#ifndef MAGNUM_TARGET_GLES
/** /**
* @brief %Image size * @brief %Image size
* *
* The result is not cached in any way. If * The result is not cached in any way. If
* @extension{EXT,direct_state_access} is not available, the texture * @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 * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and
* @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access}
* with @def_gl{TEXTURE_WIDTH} and @def_gl{TEXTURE_HEIGHT} * 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); } Vector2i imageSize() { return DataHelper<2>::imageSize(*this, _target, 0); }
#endif
/** /**
* @brief Set wrapping * @brief Set wrapping
@ -124,9 +121,9 @@ class RectangleTexture: public AbstractTexture {
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Sets wrapping type for coordinates out of (0, textureSizeInGivenDirection-1) * Sets wrapping type for coordinates out of (0, textureSizeInGivenDirection-1)
* range for rectangle textures. If @extension{EXT,direct_state_access} * range. If @extension{EXT,direct_state_access} is not available, the
* is not available, the texture is bound to some layer before the * texture is bound to some texture unit before the operation. Initial
* operation. Initial value is @ref Sampler::Wrapping::ClampToEdge. * value is @ref Sampler::Wrapping::ClampToEdge.
* @attention Only @ref Sampler::Wrapping::ClampToEdge and * @attention Only @ref Sampler::Wrapping::ClampToEdge and
* @ref Sampler::Wrapping::ClampToBorder is supported on this * @ref Sampler::Wrapping::ClampToBorder is supported on this
* texture type. * texture type.
@ -146,6 +143,20 @@ class RectangleTexture: public AbstractTexture {
return *this; 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() */ /** @copydoc Texture::setMaxAnisotropy() */
RectangleTexture& setMaxAnisotropy(Float anisotropy) { RectangleTexture& setMaxAnisotropy(Float anisotropy) {
AbstractTexture::setMaxAnisotropy(anisotropy); AbstractTexture::setMaxAnisotropy(anisotropy);
@ -155,7 +166,7 @@ class RectangleTexture: public AbstractTexture {
/** /**
* @brief Set storage * @brief Set storage
* @param internalFormat Internal format * @param internalFormat Internal format
* @param size Size * @param size %Texture size
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Specifies entire structure of a texture at once, removing the need * Specifies entire structure of a texture at once, removing the need
@ -165,10 +176,10 @@ class RectangleTexture: public AbstractTexture {
* allowed. * allowed.
* *
* If @extension{EXT,direct_state_access} is not available, the texture * If @extension{EXT,direct_state_access} is not available, the texture
* is bound to some layer before the operation. If @extension{ARB,texture_storage} * is bound to some texture unit before the operation. If
* (part of OpenGL 4.2), OpenGL ES 3.0 or @es_extension{EXT,texture_storage} * @extension{ARB,texture_storage} (part of OpenGL 4.2), OpenGL ES 3.0
* in OpenGL ES 2.0 is not available, the feature is emulated with * or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not
* @ref setImage() call. * available, the feature is emulated with @ref setImage() call.
* @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexStorage2D} * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexStorage2D}
* or @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, * or @fn_gl_extension{TextureStorage2D,EXT,direct_state_access},
* eventually @fn_gl{TexImage2D} or * eventually @fn_gl{TexImage2D} or
@ -189,7 +200,7 @@ class RectangleTexture: public AbstractTexture {
* @ref imageSize(). * @ref imageSize().
* *
* If @extension{EXT,direct_state_access} is not available, the * 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 * @extension{ARB,robustness} is available, the operation is protected
* from buffer overflow. However, if both @extension{EXT,direct_state_access} * from buffer overflow. However, if both @extension{EXT,direct_state_access}
* and @extension{ARB,robustness} are available, the DSA version is * and @extension{ARB,robustness} are available, the DSA version is
@ -230,7 +241,7 @@ class RectangleTexture: public AbstractTexture {
* use @ref setStorage() and @ref setSubImage() instead. * use @ref setStorage() and @ref setSubImage() instead.
* *
* If @extension{EXT,direct_state_access} is not available, the * 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} * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexImage2D}
* or @fn_gl_extension{TextureImage2D,EXT,direct_state_access} * or @fn_gl_extension{TextureImage2D,EXT,direct_state_access}
*/ */
@ -260,7 +271,7 @@ class RectangleTexture: public AbstractTexture {
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If @extension{EXT,direct_state_access} is not available, the * 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}, * @see @ref setStorage(), @ref setImage(), @fn_gl{ActiveTexture},
* @fn_gl{BindTexture} and @fn_gl{TexSubImage2D} or * @fn_gl{BindTexture} and @fn_gl{TexSubImage2D} or
* @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access} * @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}
@ -286,8 +297,8 @@ class RectangleTexture: public AbstractTexture {
/** /**
* @brief Invalidate texture image * @brief Invalidate texture image
* *
* If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} * If extension @extension{ARB,invalidate_subdata} (part of OpenGL 4.3)
* (part of OpenGL 4.3) is not available, this function does nothing. * is not available, this function does nothing.
* @see @ref invalidateSubImage(), @fn_gl{InvalidateTexImage} * @see @ref invalidateSubImage(), @fn_gl{InvalidateTexImage}
*/ */
void invalidateImage() { AbstractTexture::invalidateImage(0); } void invalidateImage() { AbstractTexture::invalidateImage(0); }
@ -297,8 +308,8 @@ class RectangleTexture: public AbstractTexture {
* @param offset Offset into the texture * @param offset Offset into the texture
* @param size Size of invalidated data * @param size Size of invalidated data
* *
* If running on OpenGL ES or extension @extension{ARB,invalidate_subdata} * If extension @extension{ARB,invalidate_subdata} (part of OpenGL 4.3)
* (part of OpenGL 4.3) is not available, this function does nothing. * is not available, this function does nothing.
* @see @ref invalidateImage(), @fn_gl{InvalidateTexSubImage} * @see @ref invalidateImage(), @fn_gl{InvalidateTexSubImage}
*/ */
void invalidateSubImage(const Vector2i& offset, const Vector2i& size) { void invalidateSubImage(const Vector2i& offset, const Vector2i& size) {

9
src/Magnum/Renderer.h

@ -519,6 +519,9 @@ class MAGNUM_EXPORT Renderer {
* @param mask Mask for both reference and buffer value. * @param mask Mask for both reference and buffer value.
* Initial value is all `1`s. * 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), * @see @ref Feature::StencilTest, @ref setStencilFunction(StencilFunction, Int, UnsignedInt),
* @ref setStencilOperation(), @fn_gl{StencilFuncSeparate} * @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 * Set given bit to `0` to disallow writing stencil value for given
* faces to it. Initial value is all `1`s. * 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(), * @see setStencilMask(UnsignedInt), setColorMask(), setDepthMask(),
* @fn_gl{StencilMaskSeparate} * @fn_gl{StencilMaskSeparate}
*/ */
@ -812,6 +818,9 @@ class MAGNUM_EXPORT Renderer {
* @param destination How the destination blending factor is * @param destination How the destination blending factor is
* computed from framebuffer. Initial value is @ref BlendFunction::Zero. * 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), * @see @ref Feature::Blending, @ref setBlendFunction(BlendFunction, BlendFunction, BlendFunction, BlendFunction),
* @ref setBlendEquation(), @ref setBlendColor(), * @ref setBlendEquation(), @ref setBlendColor(),
* @fn_gl{BlendFunc} * @fn_gl{BlendFunc}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save